Having found that the cue-less cutscene pages bind their audio through the movie
path, I tested the same explanation on the twelve script lines with no cue and
no bank. It fails: matching their caption text against every line in the
cutscene message table gives 0 of 14 hits, so nothing carries their audio by
another route.
They are ordinary story dialogue ('Katana, wait for me in hell'), which makes a
deliberate subtitle-only design unlikely -- but that is a judgement, not a
measurement, and why they are unvoiced is still open. Also noted: D_609 and
D_610 are equally unvoiced and simply are not among the twelve, because the
twelve counts script-called names and nothing calls them.
117 lines
5.5 KiB
Markdown
117 lines
5.5 KiB
Markdown
# 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 <MSG_id> | demo | unbound
|