# The sound-cue table, and how dialogue binds to a recording **✅ Settled 2026-08-26.** `dat/tables.pak` carries the game's cue index. It closes the join from a message id to the `.slb` bank that voices it — the missing link between the script/caption side and the audio side. ## The table One IDXD object in `dat/tables.pak` (373 680 bytes, 5 records, 10 937 fields) holds: | record | shape | content | |---|---|---| | `SETTINGS` | 3 fields | `PATH` = `game:\dat\sound.pak+`, `PARAM` = `Pj_Silph.xgs`, and a positional `BANK_SE` | | `BANK_SE` | 1 positional | `Static.slb` | | `FILES` | 5 135 positional | bank paths — `jpn\Voice\VOICE_TCAF_592.slb`, `BGM_001.slb`, … | | `STAGES` | **0 fields** | present but empty | | `SOUNDS` | 5 798 **named** | cue name → numeric sound id | `SOUNDS` is the only record on the disc found so far that is entirely named fields, and the names are the join key. Cue families and their id ranges — the id space is partitioned by family, with no overlap: VOICE n=5044 1500 .. 7331 SE n= 322 1 .. 901 DEMO n= 295 8000 .. 8408 BR n= 101 8500 .. 8600 BGM n= 32 1001 .. 1109 JNGL n= 3 1201 .. 1203 5 797 of the 5 798 values are numeric and **all 5 797 are distinct** — the ids are unique, so the id is not how banks get shared. One cue's value is non-numeric. The id is **not** an index into `FILES`: ids run to 8 600 and `FILES` has only 5 135 entries. `FILES` is reached by *name*, not by id. ## The join: a message id to a recording MSG_VOICE_D_257 (built-in 64's operand, see isl-message-dialogue-link.md) -> cue VOICE_D_257 `MSG_` becomes `VOICE_` -> id 6945 SOUNDS -> bank jpn\etc\VOICE_D_257.slb FILES, matched on stem The prefix rule has one wrinkle, and getting it wrong is easy: * **`MSG_` is replaced by `VOICE_`** — it is not simply stripped. * A name that already carries `VOICE_` keeps the one it has rather than doubling it: `MSG_VOICE_D_257` → `VOICE_D_257`, but `MSG_TCAF_592` → `VOICE_TCAF_592` (not `TCAF_592`). **I got this wrong first.** Stripping `MSG_` resolved 1 250 of 1 338 script message names and left 88 unresolved, and the 88 were exactly the four-letter ship families (`ADAN` 32, `ADPL` 27, `TCAF` 12, `ACRO` 3, `RHIN` 2) — which I was ready to write up as "text-only announcements with no recording". Seeing `jpn\Voice\VOICE_TCAF_592.slb` in `FILES` refuted that: the recordings exist, my rule was wrong. Under the corrected rule the count is **1 326 of 1 338**. `SOUNDS` and `FILES` agree exactly — the same 12 names are absent from both, and **every one of the 5 135 bank files has a cue** (zero orphans). 663 cues have no bank file; those are `SE`/`BGM`-family cues living in other banks. ## The 12 script lines with no recording MSG_VOICE_A_273 MSG_VOICE_D_183 MSG_VOICE_D_600 … MSG_VOICE_D_608 MSG_VOICE_D_611 All twelve are in the `VOICE` family, have caption text, are called from the stage scripts, and have neither a cue nor a bank. Ten of them form the near contiguous block `D_600`–`D_611`. (`D_609` and `D_610` are equally unvoiced but are not among the twelve, because nothing in the stage scripts calls them — the twelve counts *script-called* names only.) **They are not the resupply case.** When the cue-less *cutscene* pages turned out to be lines whose audio binds through the movie path rather than a cue (see [cutscene-message-table.md](cutscene-message-table.md)), the obvious question was whether these twelve are the same thing. They are not: matching their caption text against every line in the cutscene message table gives **0 of 14** hits. There is no twin carrying the audio by another route. They are ordinary story dialogue, not stage furniture — D_602 "Katana, wait for me in hell. I won't be long." D_611 "Ahahahaha! Father, I've done it!" A_273 "Emergency! Emergency! We just received orders to evacuate…" — which makes a deliberate subtitle-only design unlikely, but *unlikely* is not *measured*. ❔ Whether these are a late cut, lines added after the recording sessions, or something else is **still not settled**. What is now settled is that the one available alternative explanation does not apply. ## What this does *not* settle * **The wrong-recording case was already explained, and I overstated it as open.** On first writing this page I said the cue table "does not explain" the `hokyu_DS_s13A → VOICE_D_452` rejection and that the sharing must therefore live deeper. That was careless: [voice-bank-leading-region.md](../voice-bank-leading-region.md) settled it earlier — the bank holds one **generic** line ("Resupply complete. You are cleared for take-off!") reused across four stages, so the binding is right and only the expectation was wrong. What this table adds is narrower and worth stating precisely: the reuse is a **movie-slot → bank** relation, not a cue-level one, because all 5 797 numeric cue ids are distinct and no two cues name the same bank file. * **`STAGES` is empty**, and what would have populated it is unknown. * **`SOUNDS`' one non-numeric value** was not chased down. * Only the English pack and the `jpn\` bank paths were examined. Every path in `FILES` begins with `jpn\`, which is consistent with the already-recorded finding that the voice set is Japanese, but the other language packs' tables were not diffed against this one. ## Tool tools/re-capture/sound_cues.py summary | resolve | demo | unbound