This repository has been archived on 2026-09-16. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
Syplheed-Reborn/docs/re/structures/mission-script-manifest.md
Sylpheed RE agent 1132d95227 re: an embedded .prt part is a top-level RATC bundle, addressed by its element prefix
Read first: ui-rat-layout.md OWNS the RATC stack and already documents
the 60-byte element declaration table and 'one bundle = one
(context x language) build of that screen'.  What it does not say is how
a part is addressed when it is NOT a pak entry.

The elements of one bundle share a common name prefix, and that prefix
is the part name.  GP_MAIN_GAME_E2D.pak has 130 bundles with 114
distinct element prefixes -- pgmenu_btn00, pghud_wing, pgface,
pghud_range, pgmanuva_eff0 -- exactly the in-game part names.

The 100 in-game-only .prt names match a 2D bundle prefix 68 times; the
control, the 241 shipped parts, matches ZERO.  The two families are
disjoint on the test.  13 shipped parts match a bundle prefix in their
own screen pak, which is the expected shape.

Four of the five mission banners land here: pgmsg_start.prt is E2D
bundle 0x89fac252, a one-element bundle declaring pgmsg_start_sub.rat;
likewise _end_, _failed_, _restart_.  pgmsg_update has no bundle at all,
consistent with having no _sub.rat.

32 in-game names still have no 2D bundle.  They cluster into families
whose base name is a bundle, reading as a variant declared inside a
parent bundle -- a reading, not adopted.

Artefact +38 lines / 0 deletions; the other six regenerate
byte-identical.
2026-08-27 14:27:38 +00:00

10 KiB
Raw Blame History

✅ Stage\script.tbl — the 11 non-MISSION fields, and where they point

mission-script-ssb owns this manifest and names its 40 fields; it never read the 11 that are not MISSION<n> = StageNN.ssb. This does, and follows each value into the archives. Artefact ../data/script-manifest.txt, regenerator tools/re-capture/script_manifest.py.

DIALOG_MESSAGE        MissionDialogMessage.tbl
DIALOG_LOCAL_STRING   MissionDialog_local_string.tbl
FONT                  dat\fonts.pak+HGRGE00.TTF     FONT_SIZE 15
TEXT_POS              128,128,16                    TEXT_LINES 30
MISSION_START_PRT     pgmsg_start.prt      MISSION_END_PRT      pgmsg_end.prt
MISSION_UPDATE_PRT    pgmsg_update.prt     MISSION_FAILED_PRT   pgmsg_failed.prt
MISSION_RESTART_PRT   pgmsg_restart.prt

Two sibling records in the same file, also unread until now: GP_TEST (PATH = dat\GP_TEST\ — a debug archive that is not on the disc) and TEXTS (FONT_SIZE 33, TEXT_LINES 3, TEXT_POS 296,565,39 — a second, larger text style beside SCRIPTS's own 15/30/128,128,16).

❌ CORRECTION (2026-08-27, same day) — the dialogue table was ALREADY KNOWN,

and one "not found" was a FALSE NEGATIVE

This page announced message\MissionDialogMessage.tbl as a find. ixud-localised-text owns it and already states that S02_P1_OBJECTIVE and friends "are record names in an IDXD map, message\MissionDialogMessage.tbl, whose positional fields list the lowercase per-line IXUD names", and that "*_GRAPH is the odd one: a single named field holding a texture, pgmsg_stg02_1.t32". I grepped the manifest doc and not the text doc. Third overclaim in four days.

Worse, the sweep's headline negative was wrong. MissionDialog_local_string.tbl DOES resolve — as language\MissionDialog_local_string.tbl, IXUD, in all six GP_MAIN_GAME_* paks. My 33 prefixes omitted language\, which is exactly the convention ixud-localised-text.md records for language paks. A prefix sweep is only as good as its prefix list, and the list should have come from the corpus.

Also wrong here: "LOSE has exactly one entry". Per kind the shapes are HINT_PAUSE 4, HINT 3, LOSE 4, OBJECTIVE 4 positional fields, and GRAPH 1 NAMED field — the .t32 texture. The single-field bucket was GRAPH, not LOSE.

What survives as new: the 11 field VALUES read as a block, the GP_TEST and TEXTS sibling records, the per-stage phase census, and the five pgmsg_*.prt still resolving nowhere.

message\MissionDialogMessage.tbl — keyed by stage AND phase

Probed 7 values × 34 prefixes × 41 archives. Two resolve: message\MissionDialogMessage.tbl (IDXD) and language\MissionDialog_local_string.tbl (IXUD), each in all six GP_MAIN_GAME_* paks. 200 records, 25 280 bytes, every name of the form S<NN>_P<n>_<KIND> with five kinds, 40 each:

kind fields reading
HINT_PAUSE 4 the pause menu's hint lines
HINT 3 🟡 in-mission hint
OBJECTIVE 4 🟡 the objective text
LOSE 4 🟡 the failure lines
GRAPH 1 NAMED ✅ a .t32 texture — S10_P1_GRAPH → pgmsg_stg10_1.t32

The fields are positional, tagged 0…3, and each value is a message key: S10_P1_HINT_PAUSE → S10_P1_Hint_Pause_00 … _03. So this is an index from (stage, phase, kind) to the localised strings — the same S<NN>_P<n> keying the ISL corpus uses for mission phases.

🧪 Control — the 22 stages are exactly the STORY stages. The 40 stage-phases span stages 1–16 and 24–29; that is a subset of the 28 shipped, and the six with no hints at all are 18–23, the tutorials (stage-numbering-and-player-craft). A fifth independent route to the same story/tutorial split, and it also gives the phase count per stage — 1 to 3, e.g. S02 and S03 have 3, S10 and S13 have 1.

🟡 Five values still do not resolve — with two working controls

All five pgmsg_*.prt are not a pak entry under any of the 34 prefixes tried. Two controls sit in the same sweep and both resolve in 6 archives: message\MissionDialogMessage.tbl and language\MissionDialog_local_string.tbl — the second only after the correction above added language\.

This is the same wall mission-phase-advance hit for the manifest's KEYS — but that sweep probed MISSION1..33 and MISSION_*_PRT as names. This one probes the values, which had never been read, and closes them the same way.

⚠️ name_hash is CASE-INSENSITIVE

name_hash("message\\a.tbl") == name_hash("Message\\A.TBL"). tag_hash is not (tag_hash("Abc") != tag_hash("abc")). Already noted for archive lookup in sound-pak-contents; worth repeating because it doubles the apparent hit count of any prefix sweep.

🔎 Where .prt parts live — and why these five are the exception

Followed up the next iteration. Read first: ui-prm-primitives.md, ui-rat-layout.md, ui-screen-runtime.md — they own the .prt/RATC/T8aD UI stack and describe element names inside bundles, not where the parts live. Artefact ../data/prt-parts.txt, regenerator tools/re-capture/prt_parts.py.

A .prt IS a pak entry — under a LANGUAGE directory. Of the 376 distinct .prt names referenced anywhere on the disc, 241 resolve as an archive entry: 220 under eng\ and jpn\, 38 under each of the other four. My earlier sweep had eng\…esp\ in the list, so this is not the missing-prefix mistake again — the five simply are not there.

name resolves under
prbase.prt all six language dirs
palogo1.prt eng\, jpn\
all five pgmsg_*.prt nothing, under any of 15 prefixes

🟡 A partial lead, and its own refutation. Four of the five have a same-stem _sub.rat sub-bundle inside every per-language 2D pak (pgmsg_start_sub.rat, _end_, _failed_, _restart_ — 6 archives each); pgmsg_update has none. Tempting as "the parts live as RATC sub-bundles", but the control kills the generalisation: only 4 of 376 .prt stems have a _sub.rat at all (the other 7 belong to GP_BUNK, GP_SYSTEM, GP_MISSION_LOG), and prbase.prt — which does ship as an entry — has no _sub.rat. So _sub.rat is not the container convention; it is something these four happen to have.

✅ Who REFERENCES a part decides whether it ships as an entry

Censused the whole 135, not the five. The cross-tab over all 376 names:

referenced by tables.pak resolves as an entry count
yes yes 241
no no 100
yes no 35
no yes 0

Resolving implies being referenced by tables.pak — 0 counterexamples in 376. tables.pak holds the menu screen configs; every part it names ships as <lang3>\<name>.prt. The 100 names that appear only inside the GP_MAIN_GAME_*2D.pak bundles never ship as entries at all — they are the in-flight HUD, authored into the bundles rather than loaded by name.

🔑 So the five pgmsg_*.prt are not a special case of their own: they belong to the 135, and the real split is menu parts (named, shipped) vs in-game parts (embedded). It is not a prefix rule — 6 of the 135 pg* names do resolve (pgloading, pgloading2, pgmsg_scr, pgpause, pgpause_ttrl, pgpbase), because tables.pak names them.

🟡 The 35-name residual is one coherent family: referenced by tables.pak yet absent — pgmenu_btn* / pgmenu_item* / pgmenu_pad, pgfacewin*, pgtextwin, phinfo1-3, 02d, 02d_scr, psview_release. That is the in-game pause menu and squadron-order overlay: named by a menu config but drawn from the in-game bundles. Consistent with the split above; not separately proved.

✅ An embedded part IS a top-level RATC bundle, named by its element prefix

ui-rat-layout owns this stack and already says a top-level RATC bundle is "one (context × language) build of that screen" with a 60-byte element declaration table at 0x20. What it does not say is how a part is addressed when it is not a pak entry. It is addressed by the bundle itself: the elements of one bundle share a common name prefix, and that prefix is the part name.

GP_MAIN_GAME_E2D.pak holds 130 bundles with 114 distinct element prefixes — pgmenu_btn00, pghud_wing, pgface, pghud_range, pgmanuva_eff0, … i.e. exactly the in-game part names.

matches a 2D bundle prefix matches any bundle prefix
the 100 in-game-only .prt 68 68
CONTROL the 241 shipped .prt 0 13

0 of 241 is what makes this a result rather than a coincidence: the two families are disjoint on the test. (The 13 are shipped parts matching a bundle in their own screen pak, which is expected.)

Four of the five mission banners land here: pgmsg_start.prt is the E2D bundle 0x89fac252, a one-element bundle declaring pgmsg_start_sub.rat; likewise _end_ 0x92239624, _failed_ 0xc01017fc, _restart_ 0x606fef65. pgmsg_update has no bundle at all — consistent with it having no _sub.rat either.

🟡 32 in-game names still have no 2D bundle (listed in the artefact). They visibly cluster into families whose base name is a bundle — pghud_wing_act_* beside pghud_wing, pghud_range_* beside pghud_range, pgmanuva_eff1..3 beside pgmanuva_eff0, pgtarget_* — which reads as "a variant declared inside a parent bundle rather than a bundle of its own". A reading, not adopted; nothing here shows the variant mechanism.

Still not settled: those 32, and pgmsg_update, which is absent from every route tried. What is now settled is that they are not pak entries while 241 of their siblings are, and that pgmsg_update is the odd one out even among them.

🟡 Not settled

  • Where the five pgmsg_*.prt screen parts live — see the section above for how far that got.
  • dat\GP_TEST\ is named by the manifest and is not on the disc — a debug path left in, not a missing asset. Not chased.