Measured the <id>_<page>_<line> key structure: a page is one subtitle box of 3 or 4 wrapped lines, and successive pages are successive utterances by possibly different speakers. 452 of 4091 ids span more than one page, up to 8. That refutes the isl_dialogue.py committed two commits ago, which read only page 000 -- 356 of the 1338 script message names are multi-page, so a quarter of its output was truncated to the opening utterance. Tool now walks pages until one is empty; Stage 02 sample regenerated (43 of 213 calls multi-page). The 2683/2683 resolution figure is unaffected: it counted ids that have text, and every id does have a page 000. What was wrong was the rendered text.
99 lines
4.4 KiB
Markdown
99 lines
4.4 KiB
Markdown
# ISL `request_script_message` → caption text
|
|
|
|
**✅ Settled 2026-08-26.** Every mission-script message call resolves to the
|
|
dialogue line it plays. The 28 stage scripts are readable as dialogue.
|
|
|
|
## The link
|
|
|
|
Built-in **64** (`request_script_message`) takes one operand in slot 0: a
|
|
two-word symbol reference into **symbol table 1**. The symbol's name is a
|
|
message id such as `MSG_VOICE_D_257`. The text lives in the language pack's
|
|
IXUD blocks (`dat/GP_MAIN_GAME_<lang>.pak`) as a **named field** whose key is
|
|
`<id>_<page>_<line>`, read via the record/field table documented in
|
|
[idxd-container.md](idxd-container.md).
|
|
|
|
MSG_VOICE_D_257 → field key `MSG_VOICE_D_257_000_00` → "Katana! Damn it!"
|
|
|
|
## Evidence
|
|
|
|
Measured over all 28 `StageNN.ssb`:
|
|
|
|
| | |
|
|
|---|---|
|
|
| built-in 64 call sites | **2683** |
|
|
| slot 0 not staged | 0 |
|
|
| operand not in symbol table 1 | 0 |
|
|
| operand symbol type | **6** at all 2683 sites |
|
|
| distinct message names | 1338 |
|
|
| names with caption text at `_000_00` | **2683 / 2683 (100 %)** |
|
|
|
|
There is no residue: no call site takes a different operand shape, no name is
|
|
of a type other than 6, and no name is missing from the caption table. That
|
|
totality is the result — a partial rate would have meant the operand encoding
|
|
was only sometimes what I thought it was.
|
|
|
|
Name families and their share of call sites:
|
|
|
|
MSG_VOICE 2407 MSG_ADAN 118 MSG_ACRO 82
|
|
MSG_ADPL 38 MSG_TCAF 35 MSG_RHIN 3
|
|
|
|
`MSG_VOICE_*` is crew/wingman dialogue; the four-letter families are
|
|
ship-side announcements (`ACRO` = ACROPOLIS, `ADAN`/`ADPL` = ADAN,
|
|
`TCAF`, `RHIN` = Rhino flight).
|
|
|
|
## Page and line structure — and a correction to this page's first tool
|
|
|
|
**✅ Measured 2026-08-26**, on the English pack. A caption id is keyed
|
|
`<id>_<page>_<line>`:
|
|
|
|
* a **page** is one subtitle box, holding **3 or 4 wrapped lines** (4 506 pages
|
|
of 4, 263 of 3 — no other width occurs);
|
|
* successive **pages are successive utterances**, and may be different
|
|
speakers. A multi-page id is therefore a whole exchange, not one long line:
|
|
|
|
MSG_DEMO_009 page 0 No way! There's more of them?
|
|
page 1 Rhino Leader to ACROPOLIS! There's a whole fleet of them now!
|
|
page 2 What? Is there any way you can get out of there?
|
|
page 3 If we get rid of those fighters, we can cut our way out of here.
|
|
|
|
Of 4 091 distinct ids, **452 span more than one page** (374 `MSG_VOICE`,
|
|
78 `MSG_DEMO`), up to 8 pages.
|
|
|
|
**This refuted the first version of `isl_dialogue.py`**, committed earlier the
|
|
same day, which read only page `000`. **356 of the 1338 script message names
|
|
are multi-page**, so a quarter of the dialogue it printed was silently
|
|
truncated to its opening utterance. The tool now walks pages until one is
|
|
empty. The 2683/2683 resolution figure above is unaffected — it counted ids
|
|
that *have* text, and every id does have a page `000` — but the *rendered*
|
|
text was incomplete, and the caveat this page originally carried ("whether any
|
|
id uses a page other than `000` is unmeasured") understated it as a question
|
|
when it was already a defect.
|
|
|
|
## Why this was not obvious earlier
|
|
|
|
The caption table only became readable on 2026-08-25, when `build_caption_text`
|
|
was switched from scraping adjacent string-pool tokens to reading the IXUD
|
|
**field** table — which took the extractable line count from 537 to 8800
|
|
(8800 of 8800 distinct keys). Before that the great majority of these 1338
|
|
names had no text to resolve *to*, and the 100 % figure was unreachable.
|
|
|
|
## What this does not settle
|
|
|
|
* **Which recording plays.** The caption is the *text*; the voice bank binding
|
|
is a separate and still-unresolved question — see
|
|
[voice-bank-leading-region.md](voice-bank-leading-region.md) and the
|
|
known case of a generic line playing against a specific subtitle.
|
|
* **Which page a `MSG_DEMO_*` id belongs to.** The `DEMO` family is not called
|
|
from the stage scripts at all — 78 of its ids are multi-page, so something
|
|
else drives cutscene dialogue. That driver is unidentified.
|
|
* **The other five languages.** Only the English pack was swept.
|
|
* **Ordering.** The tool prints call sites in file order, which is *script*
|
|
order, not necessarily *play* order — phases and branches are not resolved.
|
|
|
|
## Tool
|
|
|
|
tools/re-capture/isl_dialogue.py <StageNN.ssb> [GP_MAIN_GAME_E.pak]
|
|
|
|
Sample output committed at [../data/isl-stage02-dialogue.txt](../data/isl-stage02-dialogue.txt)
|
|
(Stage 02, 213 message calls, 213 with text).
|