Censused the 32 bundle-less in-game .prt names with the 68 as control: 4 of 32 appear as an element of some 2D bundle, against 58 of 68. Being an element is normal for a part that exists; these are not elements either. Last iteration's 'not adopted' reading is refuted. 28 names are neither a bundle nor an element. They are not unreferenced: a HudResource record inside the 2D paks' own IDXD entries names them -- the in-game screen config, parallel to tables.pak for menus. GP_MAIN_GAME_E2D.pak has 6 IDXD entries; two carry HudResource (24 named fields) beside ArmsStatus, Map, ArmsItem, RangeFinder, Marker, Manuva, Number; two more carry the ObjectiveMarker_*/TutorialMarker_* set. Its values carry subdirectory prefixes -- Hitmark\, Lockon\ -- which my hand-written prefix list never had. So I rebuilt the negative the right way round: harvested every IDXD field value containing a backslash, kept the 60 commonest directories, and re-swept. 241/376 with the hand list; 241 with hand + harvested -- zero new resolutions. After the language\ miss, this is the closure that counts: the prefix list came from the disc, not from me. Still open: whether the 28 are cut features or assembled at runtime from sprites. Nothing static separates those two. Artefact +45 lines / 0 deletions; the other six regenerate byte-identical.
252 lines
12 KiB
Markdown
252 lines
12 KiB
Markdown
# ✅ `Stage\script.tbl` — the 11 non-`MISSION` fields, and where they point
|
||
|
||
[mission-script-ssb](mission-script-ssb.md) 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](ixud-localised-text.md) 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](isl-phase-guards.md).
|
||
|
||
🧪 **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](stage-numbering-and-player-craft.md)). 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](../mission-phase-advance.md) 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](sound-pak-contents.md); 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](ui-rat-layout.md) 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.
|
||
|
||
### ❌ The "variant inside a parent bundle" reading is REFUTED
|
||
|
||
Censused the 32, with the 68 as the control:
|
||
|
||
| | appear as an ELEMENT of some 2D bundle |
|
||
|---|---:|
|
||
| the 32 **without** their own bundle | **4** |
|
||
| **control** — the 68 **with** one | **58** |
|
||
|
||
Being an element is normal for a part that exists (58/68); the bundle-less ones
|
||
are not elements either. **28 names are neither a bundle nor an element.**
|
||
|
||
### 🔑 `HudResource` — the in-game counterpart of `tables.pak`
|
||
|
||
The 28 are not unreferenced: they are named by a **`HudResource`** record inside
|
||
the 2D paks' *own* IDXD entries — the in-game screen config, exactly parallel to
|
||
`tables.pak` for menus. `GP_MAIN_GAME_E2D.pak` has 6 IDXD entries; two carry
|
||
`HudResource` (24 named fields) beside `ArmsStatus`, `Map`, `ArmsItem`,
|
||
`RangeFinder`, `Marker`, `Manuva`, `Number`, and two more carry the
|
||
`ObjectiveMarker_*` / `TutorialMarker_*` set.
|
||
|
||
```
|
||
HUD_RES_FONT DFSOGE5.TTC PGHUD_LOCATOR pghud_target_locator.prt
|
||
PGHUD_HITMARK Hitmark\pghud_hitmark.prt PGLOCKON Lockon\pglockon.t32
|
||
PGHUD_OBREMAINDER Hitmark\pghud_OBremainder.prt PGTIMER pgtimer.prt
|
||
PGHUD_SUBTARGET pghud_subtarget.prt PGREMAINING pgremaining.prt
|
||
… plus the pitch ladder / yaw / cockpit `.t32` sprites
|
||
```
|
||
|
||
🔑 Its values carry **subdirectory prefixes** — `Hitmark\`, `Lockon\` — which my
|
||
hand-written prefix list never had.
|
||
|
||
### 🧪 Control — a prefix list harvested from the data adds nothing
|
||
|
||
Took every `IDXD` field value containing a backslash, kept the 60 commonest
|
||
directories (`Sight\`, `Radar\`, `Marker\`, `Wing\`, `ArmsSt\`, `Manuva\`,
|
||
`Hitmark\`, `Lockon\`, the `<lang>\Voice\` and `<lang>\etc\` trees …) and
|
||
re-ran the sweep. **241 of 376 with the hand list; 241 with hand + harvested.**
|
||
Zero new resolutions. After the `language\` miss, this is the negative built the
|
||
right way round: the prefix list came from the disc, not from me.
|
||
|
||
**So 28 `.prt` names are referenced by the in-game configs and exist nowhere on
|
||
the disc** — not an entry, not a bundle, not an element, under any prefix the
|
||
data itself supplies. A coherent HUD family: `pghud_range_*`, `pghud_wing_*`,
|
||
`pghud_arms_active*`, `pgtarget_*`, `pgmanuva_eff2/3`, `pggauge_*_eff1`,
|
||
`pgtimer`, `pgremaining`, `pgmsg_update`.
|
||
|
||
**Still not settled**: whether the 28 are cut features or built at runtime from
|
||
sprites. Nothing static can separate those two. 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.
|