10. Reference tables

Everything needed to reimplement the pipeline, plus an index into the decomp.

The character → voice code table

mMsg_sound_voice_get's full 256-byte array, indexed by the game character code (row × 16 + column). 0x7F and 0x80 hold 0xFF but the function returns −1 for them before the lookup.

      x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF
0x00  85 85 5D 5D 5D 5D 5D 5D 5F 61 61 61 61 65 65 65
0x10  65 60 6A 6B 6B 6B 6B 6B 85 71 71 71 71 5E 6C 5D
0x20  81 83 85 5D 5D 85 85 85 85 85 85 85 85 85 85 80
0x30  53 54 55 56 57 58 59 5A 5B 5C 85 85 85 85 85 82
0x40  85 5D 5E 5F 60 61 62 63 64 65 66 67 68 69 6A 6B
0x50  6C 6D 6E 6F 70 71 72 73 74 75 76 5D 85 5D 5D 85
0x60  5F 5D 5E 5F 60 61 62 63 64 65 66 67 68 69 6A 6B
0x70  6C 6D 6E 6F 70 71 72 73 74 75 76 61 61 61 61 FF
0x80  FF 65 65 65 65 86 60 6A 6B 6B 6B 6B 6B 85 71 71
0x90  85 71 71 75 75 6C 75 85 85 5D 6B 85 85 85 85 85
0xA0  85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85
0xB0  85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85
0xC0  85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85
0xD0  85 85 81 81 85 85 85 85 85 85 85 85 85 85 85 85
0xE0  85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85
0xF0  85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 81

Source: src/game/m_msg_sound.c_inc:2, verified verbatim.

Voice codes

CodeCharClass
0x53–0x5C0–92 (neither)
0x5D 0x61 0x65 0x6A 0x6B 0x71a e i n o u0 (vowel)
other of 0x5D–0x76b c d f g h j k l m p q r s t v w x y z1 (consonant)
0x80–0x86, 0xFF♪  ␣  ?  !  ⏎  mute  click  empty2 (neither)

Letter L ↔ code: 0x5D + (L − 'a'). Digit D ↔ code: 0x53 + D.

Phoneme codes

Phoneme code v plays soundfont instrument v − 1. Code 0 is silence. Codes marked † are produced by more than one rule and therefore share a sample.

Short vowels (Sou_TanboinHenkan)

aiueon
0x010x140x290x0A0x1D0x1B

Long vowels (Sou_ChouboinHenkan)

aiueon
0x02 †0x15 †0x2A †0x0E †0x1E0x1B

Used only when class(a) == vowel && class(b) == consonant && c == 'e'. The tables are otherwise byte-identical.

Consonants (both tables)

LetterCodeNotes
b0x07
c0x23 / 0x18soft (= s) if next letter is i or e, else hard (= k)
d0x09
f0x11
g0x12
h0x00silent — no instrument
j0x17shares ge
k q0x18
l0x19
m0x1A
p0x21
r0x22
s0x23
t0x26shares digit 2
v0x2D
w0x2E
x0x31shares ks
y0x15shares long i and ea
z0x30

Digits (both tables)

0123456789
0x320x330x260x270x340x350x360x370x100x38

Digraphs (Sou_ConnectCheck) — 53 entries

PairCodePairCodePairCodePairCode
ai0x0Fgo0x3Eno0x49si0x36
al0x02ha0x3Fof0x4Aso0x4F
an0x39he0x40oh0x4Bsu0x25
ar0x16hi0x41ok0x4Cth0x28
as0x3Aho0x42on0x4Dto0x50
be0x3Bi␣0x05oo0x2Aup0x51
by0x3Cif0x43or0x2Cwe0x52
ch0x08in0x44ou0x20wo0x33
do0x3Dir0x0Cow0x06you0x77
ea0x15is0x45oy0x1Fze0x32
er0x0Dit0x46re0x0E
fa0x35ks0x31se0x37
fo0x34me0x47sh0x24
ge0x17my0x48na0x38
ng0x1C

Of the 119 codes 0x01–0x77, the phonology engine produces 76. The 43 it never produces are seven isolated gaps — 0x03 0x04 0x0B 0x13 0x2B 0x2F 0x4E — plus the 36-code block 0x53–0x76. The anti-repetition substitution can reach the first six of the gaps (it only emits 0x00–0x3F); the block is reachable only via the editor path; 0x4E appears to be reachable by nothing at all.

Specs

SpecSeqBankVolPitchSpeaker
22431560.651.00lazy & jock villagers; most special NPCs (default)
32441570.651.00cranky villagers; Wendell, Pete, Booker, Jack
42451580.651.00normal, peppy, snooty villagers; Pelly, Phyllis, Mabel, Sable, Blanca; event narration
52431560.901.00player, male — text editor only
62451580.901.00player, female — text editor only
72431560.901.30Timmy & Tommy (via control code 93)
82451580.900.75Joan
92431560.700.65Farley

Per-code playback parameters

What each phoneme code actually plays — instrument, semitone, note delay, velocity, per sequence — is tabulated on the disc page, extracted from the shipped sequence data. The headline constants: dialogue phonemes play at semitone 44 (seq 243), 41/39 (seq 244) or 39 (seq 245) against unity-at-48 (PITCHTABLE[i] = 2^((i−48)/12)), velocity 110 (gain (110/127)² ≈ 0.75); editor letter names at semitone 44 with a rising sweep from 41, velocity 95; all samples tuned 0.689062 = 22050/32000.

Disc image quick reference (GAFE01 USA rev 0)

ThingWhere
main DOLdisc 0x1E000 (from header 0x420)
FSTdisc 0xFE500, size 0x102 (from header 0x424/0x428)
/audiorom.imgdisc 0x626D10, size 0x7EA760
the five audio tablesDOL .data5; VAs 0x800CCA40 (seq), 0x800CD9E0 (bank), 0x800CE3E0 (wave), 0x800CE450 (data), 0x800CE490 (map)
seq 243 / 244 / 245disc 0x6D2770 / 0x6D2DD0 / 0x6D3250, sizes 0x660 / 0x480 / 0x660
bank 156 / 157 / 158disc 0x752670 / 0x756B70 / 0x759B90
wave bank 5disc 0xA23E50, size 0x3ED620; smzwavetable.sample is relative to this

Full derivations, structure layouts and the VADPCM decoder are on the disc page.

Text control codes that affect voice

ValueNameEffect
3CURSOR_SET_TIMEpauses the cursor; lets a half-built window fire early
75–79, 97SET_MESSAGE_CONTENTS_*emotion state (normal / angry / sad / fun / sleepy / gloomy)
81SOUND_CUTplays system SE 0x54, sends the end code, suppresses voice
84SET_CHAR_SCALEchanges glyph scale → the volume step
90SET_LINE_SCALEsame, per line
92VOICE_TRUErestore spec (Timmy/Tommy only)
93VOICE_FALSEspec 7 (Timmy/Tommy only)

Source index

Paths relative to the ac-decomp root. Line numbers are for commit 09ca8e8b.

Message layer

src/game/m_msg_sound.c_inc:1mMsg_sound_voice_get — the 256-entry table
​:26mMsg_sound_voice_get_for_editor
​:44mMsg_sound_voice_get2 — newline injection
​:52mMsg_check_sound_special — forced-voice message ranges
​:66mMsg_check_sound_animal
​:85mMsg_sound_voice_entry — the (a, b, c) window
​:117mMsg_sound_voice_endcode_set
​:126mMsg_sound_CodeVoice
​:259mMsg_sound_voice_mode_get
​:288mMsg_sound_spec_change_voice_force
​:317mMsg_sound_spec_change_true/false — Timmy/Tommy
src/game/m_msg_cursol.c_inc:1100mMsg_Main_Cursol_ControlCursol — the cursor loop
​:1184the NOT_PAUSE_FRAME toggle
src/game/m_msg_draw_font.c_inc:35voice-fire decision
src/game/m_font_main.c_inc:951mFontSentence_animal_voice_se — scale, and the call
​:1078the draw-loop trigger
src/game/m_npc.c:32l_sp_actor_name — special-NPC spec table
​:4116mNpc_GetNpcSoundSpec
src/game/m_submenu.c:364player voice, specs 5 / 6
src/game/m_editor_ovl.c:712the mode-1 editor path

Bridge

src/audio.c:96sAdo_VoiceSe
​:152sAdo_SetVoiceMode
​:216sAdo_SpecChange
include/audio.h:45VOICE_STATUS_*
include/audio_defs.h:10VOICE_MODE_*

Audio engine — src/static/jaudio_NES/game/game64.c_inc

:22VOICE_GROUP = NA_GROUP4
:97SOU_VOICE_SE struct
:236SHIIN2BOIN (dead)
:311sou_voice_se_init — pan 0x3F, reverb 0
:820Sou_VoiceStart
:1174Sou_VoiceMake
:1708Sou_SpecialRoutine10 — deferred syllable
:1852Na_GameFrame
:2146Sou_TanboinHenkan
:2231Sou_ChouboinHenkan
:2316Sou_ConnectCheck
:2564Sou_BoinShiinCheck
:2598Na_VoiceSe
:3319Na_SetVoiceMode
:3459Na_SpecChange
melody.c:727Na_MelodyVoice — the ♪ handler
audioheaders.c:4073bank 156–158 entries
audioheaders.c:4176AudiodataHeaderStart — the three archives
audioheaders.c:4717seq 243–245 → bank 156–158

Soundfont / bank loading

include/jaudio_NES/audiostruct.h:74ArcEntry / ArcHeader
​:95adpcmloop, adpcmbook, smzwavetable, wtstr
​:348voicetable — the instrument
​:373voiceinfo — per-bank runtime info
src/static/jaudio_NES/internal/system.c:772__Link_BankNum — alias entries
​:813Nas_BankOfsToAddr_Inner — offset → pointer
​:1171__SetVlute — param0/1/2 decode
​:1692__WaveTouch — sample vs bank relocation
internal/channel.c:354NoteToVoice
​:368ProgToVp — instrument index → voicetable
internal/track.c:1159Nas_ProgramChanger
​:1399SUBTRACK_CMD_SET_INSTRUMENT_BANK — reverse bank-list index

Sequence playback internals

include/jaudio_NES/audiocommon.h:405common / group / subtrack / note command opcodes
internal/track.c:543Nas_NoteSeq — note layer interpreter
​:1028__SetNote — note byte → semitone/delay/velocity
​:780__SetVoice — frequency_scale = PITCHTABLE[semitone] × tuning, portamento
​:1746MACRO_READ_PORT0 — destructive port read (resets to −1)
​:1877GRP_CMD_SET_TEMPO — tempo = byte × 48 tatums
internal/audiotable.c:321PITCHTABLE — 2^((i−48)/12), unity at 48
internal/memory.c:998max_tempo derivation (tick rate)
internal/audioconst.c:32AGC — timeBase = 48
internal/dummyrom.c:68Jac_InitARAM — opens /audiorom.img
internal/neosthread.c:56DVDT_LoadtoARAM("/audiorom.img", …)
← 9. Quirks & corrections Index