movie_manifest::parse now reads BASE_INFO's positional field keys (the game's own cutscene ids, stage*100 + slot) and follows each to its record, instead of scraping the string pool. The pool stores each distinct string once, so a REPEAT reference produced no token and read as "no binding". That single cause explains every wrong cell: 13 later references to VOICE_D_450..454, two to SUBTITLE_hokyu_LS_s11A.tbl, and MS01A's share of pwterop_s01a.prt. All 18 hokyu movies are bound, not five. Counts, verified independently by me against the disc before recording: 104 cutscene SLOTS binding 101 distinct MOVIES; 99 slots / 96 movies with a voice track, 99 / 96 with a subtitle, 22 / 22 with a telop. The docs' old 94 / 83 / 21 are exactly the counts of DISTINCT POOL STRINGS -- not wrong measurements, measurements of the wrong thing. Three denominators were being conflated; the new test pins all three. Two assertions in movie_manifest_disc.rs were false and are corrected: hokyu_DS_s13A binds VOICE_D_452 and resolves to eng\etc\VOICE_D_452.slb. The in-game verdict that rejected that value tested an INFERENCE from a shared demo id, on a decoder that discards 85-87% of banks in this class -- see voice-bank-leading-region.md, committed earlier today. The ~104 script ids are no longer open: they are literal positional keys, each naming its record, and all 104 resolve. The old "counts differ by three, positional pairing does not work" has a concrete cause -- three resupply movies are bound by TWO slots each. Also corrected: the naming convention has 3 subtitle exceptions (s24A/s27A borrow s11A's track) and 18 voice exceptions, not one and five. The legacy scraper is kept as a fallback for blobs with no record table, so the synthetic unit fixtures still exercise it. Artifacts: examples/movie_map_csv.rs regenerates the CSV, now slot-keyed (104 rows; the movie-keyed version silently dropped one slot of each duplicate). Disc tests green. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PMRJjbxLqZtsb5Vb7KunPE
4.6 KiB
The movie ↔ subtitle ↔ voice link ✅ (static)
INDEX carried the IXUD subtitle format as 🟡 with "movie↔track
link unknown (dynamic item)" — i.e. a question expected to need the running
game. It does not: the link is a config record on the disc, and it verifies
against the disc's own contents.
Where it is
dat/tables.pak, the IDXD record with schema 0x067025b9. Its keys come from
the movie game-part — the executable carries them next to the symbol
silph::GamePart_Movie::Impl::OnPrepare:
PATH = dat\movie\ SUBTITLE_FONT = fra.pak+GOTHICB.TTF
SUBTITLE_Y = 600 SUBTITLE_HEIGHT = 33
MOVIE TELOP SUBTITLE VOICETRACK
Each movie is one group of values:
S02A.wmv MOVIE
fra.pak+pwterop_s02a.prt TELOP (optional overlay)
fra.pak+SUBTITLE_S02A.tbl SUBTITLE
VOICE_S02A VOICETRACK
<lang>.pak+<member> resolves inside dat/movie/<lang>.pak, and the six
language paks (eng, fra, deu, esp, ita, jpn) each carry the same
member names — so the prefix in the table is just the build's language and the
member name is the portable part. The recovered map is
captures/movie-subtitle-voice-map.csv,
now regenerated from the record table (examples/movie_map_csv.rs) and keyed
by cutscene slot:
104 slots binding 101 distinct movies. 99 slots / 96 movies have a subtitle, 99 slots / 96 movies have a voice track, 22 slots / 22 movies have a telop — drawing on 94 distinct subtitle tables, 83 distinct voice banks and 21 distinct telop overlays.
❌ The old counts were measuring the wrong thing
This file used to say "101 movies, 94 with a subtitle, 83 with a voice track, 21
with a telop". Those three numbers are exactly the counts of distinct pool
strings — which is all a string-pool scraper can see. The pool stores each
value once, so a repeat reference contributes no token and read as "no
binding": 13 later references to VOICE_D_450..454, two to
SUBTITLE_hokyu_LS_s11A.tbl, and MS01A's share of pwterop_s01a.prt.
Slots, movies and distinct strings are three different denominators and this file
conflated them. Pinned by manifest_slot_and_movie_counts.
Verified, and one real defect
Every subtitle reference was looked up in the language paks. 93 of the 94
distinct members resolve. SUBTITLE_S12B.tbl resolves in none of the six
languages — a dangling reference on the retail disc, not a decode failure on
our side. Worth knowing before the reimplementation treats a missing subtitle
table as a bug of its own.
The naming is a convention, with more exceptions than were recorded:
- subtitles are
SUBTITLE_<movie base>.tbl, with 3 departures — the staff roll (SYLPH_HD720p_8M-CBR_2ch.wmv→SYLPH_HD720p_8M-CBR_2ch.tbl), andhokyu_LS_s24A/hokyu_LS_s27A, which borrowSUBTITLE_hokyu_LS_s11A.tbl; - voice tracks are
VOICE_<movie base>except all 18 hokyu movies (21 supply slots), which shareVOICE_D_450…454. The old text said five; the other 13 were invisible to the scraper for the dedup reason above.
So a reimplementation should read this table, not apply the convention with a short exception list.
✅ The script ids ARE recoverable — the old ❔ is closed
The record also lists 104 script ids — the names stage scripts use to trigger
a movie. This file used to say pairing them with the movie groups "does not
work: the counts differ by three". The counts differ by three for a concrete
reason: three resupply movies are bound by two slots each
(hokyu_LS_s02A by S02 and S05, hokyu_DS_s07A and hokyu_DS_s07H by S07 and
S12). Positional pairing was never the right model — the ids are stored as
literal positional field keys in BASE_INFO, each naming its record
directly, so every one of the 104 resolves with nothing to infer. The id is
stage*100 + slot, with 91/92 for _SUPPLY_ACROPOLIS/_SUPPLY_TANKER.
The cause is the same IDXD property that bit the Arsenal table: the string pool stores each distinct string once, so an id whose movie was already named earlier contributes no new value token and its group silently disappears. The id list is therefore ❔ until the binary node/index region is decoded — and the CSV is deliberately keyed by movie file, which is the part the data actually supports.
Note for the intro-movie investigation
ADV.wmv — the one the emulator work is about — has VOICETRACK = VOICE_ADV
and no subtitle and no telop. So a correct playback of it needs the video and
that one voice track, nothing else from this table.