Files
Sylpheed/docs/re/structures/cutscene-message-table.md
Sylpheed RE agent f58cee368f re: the cue-less cutscene pages ARE the resupply lines, and they cross-check the movie work
16 of the 17 pages with an empty slot 4 belong to MSG_DEMO_600..604, whose
caption text matches, word for word, the five resupply lines documented from the
movie side as VOICE_D_450..454. Slot 4 is empty on purpose: that audio binds
through the movie path, not through a DEMO_nnn cue.

That also disposes of the '5 ids with more than one record' item -- each appears
once per stage that uses it, and the repeat counts equal the movie-slot counts
recorded independently for the matching banks: 3/3/4/4/2 both ways, 5 of 5. The
11 extra records over 138 ids are these repeats.

Worth more than closing two items: the cutscene message table and the movie
subtitle chain were decoded from different containers by different routes and
agree on the same five lines with the same multiplicities.

MSG_DEMO_500 remains: one page, KATANA, 2s, no text and no cue.
2026-08-26 04:23:52 +00:00

122 lines
5.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# The cutscene message table — speaker, portrait, timing and audio cue
**✅ Settled 2026-08-26.** The `MSG_DEMO_*` family is not called from any stage
script; it is driven by its own IDXD tables in the language packs. Those tables
carry, per line of cutscene dialogue: **who says it, which portrait is shown,
how long it stays on screen, and which audio cue plays**.
This answers the question left open by
[isl-message-dialogue-link.md](isl-message-dialogue-link.md) — what drives
cutscene dialogue, given that built-in 64 never mentions it.
## Where it lives
32 IDXD objects per language pack (`dat/GP_MAIN_GAME_<lang>.pak`). Each holds a
`Generic` record with a `Count`, plus some number of `Message_NNN` records —
**149 in total** across the English pack, covering **138 distinct ids**.
## Record layout
A `Message_NNN` record has two named fields, `ID` and `PageCount`, and then
**9 positional fields per page**:
| slot | content | example |
|---|---|---|
| 0 | speaker | `CharacterNATALIE` |
| 1 | portrait | `FaceNATALIE_01` |
| 2 | constant `None` at all 149 records | `None` |
| 3 | on-screen seconds, 1.00 5.00 (mean 2.48) | `1.9` |
| 4 | audio cue, or empty | `DEMO_017` |
| 58 | the four caption keys of that page | `MSG_DEMO_600_000_00``_03` |
The field count is exactly **9 · PageCount + 2**, and that identity holds for
every one of the 7 distinct PageCount values present (1→11, 2→20, 3→29, 4→38,
5→47, 6→56, 8→74). That is what pins the per-page grouping.
## Evidence
* **1 252 of 1 252** caption-key slots equal `<ID>_<page>_<line>` exactly, with
**zero** mismatches. The grouping is not a guess about which slot is which.
* **78** records span more than one page — which independently equals the 78
multi-page `MSG_DEMO` ids counted from the *caption* side, by a different
method. Two measurements, same number.
* In **68 of those 78** the speaker changes between pages, confirming from the
data that successive pages are successive utterances rather than one long
speech.
* The id sets close exactly: **138 ids in the caption table, 138 in the message
table, none on either side without the other.**
* 28 distinct speakers, 98 distinct portraits.
## The audio cue (slot 4)
296 of 313 pages carry a cue, and there are **296 distinct values** — one per
page, never reused. It joins to the `SOUNDS` table described in
[sound-cue-table.md](sound-cue-table.md):
DEMO_017 -> sound id 8017
The numbering rule is `DEMO_nnn``8000 + nnn`, which holds for **286 of 286**
plain-numeric cues. The 9 remaining cues carry a letter suffix
(`DEMO_067A`, `DEMO_190A``C`, `DEMO_216A``C`, `DEMO_278A``B`) and are
assigned 84008408 in order. There is no unexplained residue.
Within a message, **77 of the 78** multi-page records number their cues
consecutively; one does not.
**A guess I had and dropped:** slot 4 looked at first like a movie reference,
since the values resemble the `DEMO_nnn` naming of a clip. It is not — there
are 97 `.wmv` files on the disc and their names look nothing like this
(`ADV.wmv`, `RT01A.wmv`), and the values are unique *per page*, which no movie
reference would be.
## What this does not settle
* **`MSG_DEMO_500`** — one page, KATANA, 2 s, **no text and no cue**. A
placeholder, apparently.
* **Slot 2 is `None` at all 149 records**, so what it would hold otherwise is
unknown — a constant with no observed variation carries no information.
* **Nothing here was run.** This is a static read of the tables; the playback
order, and whether slot 3 is really the on-screen duration rather than an
audio length or a delay, has not been checked against the running game.
## Artifact
[`../data/cutscene-message-table.txt`](../data/cutscene-message-table.txt) —
all 313 pages with speaker, portrait, seconds, cue and text.
Regenerate with `tools/re-capture/sound_cues.py demo`.
## ✅ The cue-less pages are the resupply lines — and they corroborate the movie work
**Settled 2026-08-26.** 16 of the 17 pages with an empty slot 4 belong to five
ids, and those five are exactly the resupply lines already documented from the
*movie* side in [voice-bank-leading-region.md](../voice-bank-leading-region.md).
The caption text matches word for word:
| id | speaker | line | bank |
|---|---|---|---|
| `MSG_DEMO_600` | NATALIE | "Rhino 3 has landed. Commencing resupply." | `VOICE_D_450` |
| `MSG_DEMO_601` | NATALIE | "Rhino Leader has landed. Commencing resupply." | `VOICE_D_451` |
| `MSG_DEMO_602` | NATALIE | "Resupply complete. You are cleared for take-off!" | `VOICE_D_452` |
| `MSG_DEMO_603` | TCAFSUPPLY | "All right, beginning resupply." | `VOICE_D_453` |
| `MSG_DEMO_604` | TCAFSUPPLY | "Resupply complete. Switching to take-off sequence." | `VOICE_D_454` |
This also explains the duplicate records. Each of these ids appears **once per
stage that uses it**, and the repeat counts equal the movie-slot counts recorded
independently for the corresponding banks — **5 of 5**:
DEMO_600 x3 DEMO_601 x3 DEMO_602 x4 DEMO_603 x4 DEMO_604 x2
D_450 x3 D_451 x3 D_452 x4 D_453 x4 D_454 x2
Two facts fall out:
* the **11 extra records over 138 ids** are these repeats, not an anomaly; and
* slot 4 is empty on purpose — a resupply line's audio is bound through the
**movie** path (`VOICE_D_45x`), not through the `DEMO_nnn` cue path, so there
is no cue to name.
The agreement is worth something beyond closing two items: the cutscene message
table and the movie subtitle chain were decoded separately, from different
containers, and they land on the same five lines with the same multiplicities.