re: what the game actually reads at boot -- config.ini, and which
GameParts exist at all Q6's second half, advanced but not closed, and the negative is the point. config.ini is the disc's ONLY config file -- one find over the whole extract -- and its own Shift-JIS header calls it the "Application / GamePart initial settings table". Its [SYSTEM] section, which that same comment says holds what the game and every game part share, is EMPTY. So the boot order is not in disc-side configuration at all, and that search space is now closed rather than merely unexplored. What the file DOES carry is the language: XC_LANGUAGE_* -> eng/jpn/deu/ fra/esp/ita, defaulting to eng. That is the mechanism behind the EN/JP build pairs in GP_TITLE and the <lang>.pak families -- a question the corpus had described but never traced to its input. Then the registry. Pulling every RegisterToFactory diagnostic string binds 24 of the 29 GamePart ids to a C++ class, and five ids have no registration site: 1, 2, 16, 18, 28. Id 1 is GP_ADVERTISE_DEMO, which agrees with what I measured two iterations ago -- the attract loop is the TITLE replaying ADV.wmv, not a transition into an advertise part. Marked amber, not green: it is an argument from an error message, not from code. Two things fall out for Q4: ids 3 and 4 are the same class (GamePart_SaveLoad, one part with two ids), and the menu buttons' ids now match the executable's own class names rather than a list of table names. Still a name match, one level closer to the code. What is still missing is the transitions themselves, and I say so: the manifest gives the boot-side assets, config.ini the language, the registry which parts exist. What decides to advance is in GamePart_Title's code and that dig has not been started.
This commit is contained in:
@@ -32,7 +32,7 @@ authored version can be deleted.
|
||||
| Q3 | paint order for the six screens | ✅ answered | **decoded**: a `u16` layer key at `+0x0A` of each `T8aD` sprite header, stable-sorted with declaration index; unkeyed elements get an implied key. Confirmed on 5 measured orders + `EXTRAS` vs a capture. One residual: the **tie-break** is unknown and bites on one element of the title — [`structures/ui-paint-order-key.md`](../re/structures/ui-paint-order-key.md) |
|
||||
| Q4 | button → GamePart | ✅ answered | **measured** which screen all **5** buttons open — `NEW GAME` → `DIFFICULTY` → `SELECT DATA`, not a hang. The **GamePart id is still a name match**, not a measurement — [`menu-navigation-semantics.md`](../re/menu-navigation-semantics.md) |
|
||||
| Q5 | navigation semantics | ✅ answered | **measured**: initial focus varies boot to boot (2× `TUTORIAL`, 1× `NEW GAME`); ⬆⬇ one step, **wraps both ends**; ⬅➡ do nothing; Ⓑ returns to the parent **with focus restored**; Ⓑ on the main menu → title; Ⓑ on the title → nothing — [`menu-navigation-semantics.md`](../re/menu-navigation-semantics.md) |
|
||||
| Q6 | boot sequence + what drives it | 🟡 partial | order observed and the attract cycle timed: ~8–10 s idle → fade to black → **`ADV.wmv` in full (137 s)** → title again. The **movie manifest** supplies the boot-side asset order (slot key = role); the code that decides to advance is still not decoded |
|
||||
| Q6 | boot sequence + what drives it | 🟡 partial | order observed and timed; the **manifest** gives the boot-side assets, **`config.ini`** the language, the **registration strings** which parts exist — but the *transitions* are in `GamePart_Title`'s code and are not decoded — [`boot-config-and-gamepart-registry.md`](../re/boot-config-and-gamepart-registry.md) |
|
||||
| Q7 | transitions | ✅ answered | a **fade through black**, drawn by the screen's own last-painting `.prm` quad. Fade-in ramp is **decoded** from its keyframes; the ~0.4 s fade-out is **measured** (not in the file) — [`screen-transitions.md`](../re/screen-transitions.md) |
|
||||
| Q8 | menu audio bindings | 🟡 mostly answered | the **UI cue vocabulary is decoded** (`SE_UI_CURSOR`/`DECIDE`/`CANSEL`/`IMPOSI`, all in `Static.slb` per `BANK_SE`); the event binding is a **name match**, and the SE audio is **not extractable yet** — [`menu-audio-cues.md`](../re/menu-audio-cues.md) |
|
||||
| Q9 | video binding + playback rules | ✅ answered | **decoded** from the movie manifest: `ADVERTISE_MOVIE`→`ADV.wmv` (boot intro *and* attract are one asset), `MS00A`→`S00A.wmv` is the new-game intro, `STAFF_ROLL`→the credits reel. ✅ **one Ⓐ skips a movie** (title at 57 s vs a 193 s baseline) — [`movie-binding.md`](../re/movie-binding.md) |
|
||||
@@ -161,6 +161,25 @@ authored version can be deleted.
|
||||
for all 7 620 other banks is simply absent, so an individual cue's wave is not
|
||||
locatable. Next step is `Pj_Silph.xgs` (in `sound.pak`, TOC 9454).
|
||||
|
||||
* **`config.ini` picks the language, and that is what picks the EN/JP build.**
|
||||
The disc's **only** config file (400 bytes, at the root; one `find` over the
|
||||
whole extract). Its `[LANGUAGE]` section maps the console's `XC_LANGUAGE_*`
|
||||
value to `eng`/`jpn`/`deu`/`fra`/`esp`/`ita`, defaulting to `eng` — that code
|
||||
selects `GP_TITLE`'s English or Japanese build and the `<lang>.pak` families.
|
||||
✅ decoded.
|
||||
❔ Its `[SYSTEM]` section — which the file's own comment says holds what the
|
||||
game and every game part share — is **empty**, so the boot *order* is not in
|
||||
disc-side configuration at all.
|
||||
* **Five GameParts are named but never registered.** Pulling every
|
||||
`RegisterToFactory<N, class silph::GamePart_X>` diagnostic string binds **24 of
|
||||
the 29 ids to a C++ class**
|
||||
([`data/gamepart-class-ids.txt`](../re/data/gamepart-class-ids.txt)). Ids `1`,
|
||||
`2`, `16`, `18`, `28` have no registration site — including
|
||||
**`GP_ADVERTISE_DEMO` (1)**, which agrees with the measurement that the attract
|
||||
loop is the *title* replaying `ADV.wmv` rather than a separate part. 🟡 an
|
||||
argument from a diagnostic string, not from the code.
|
||||
Also: **`3` and `4` are both `GamePart_SaveLoad`** — one part, two ids.
|
||||
|
||||
* **The GamePart id table** — 29 entries at `.rdata 0x820A1630`, confirmed by the
|
||||
executable's own registration strings. ✅ This is the screen vocabulary; which
|
||||
button reaches which entry is Q4 and is *not* part of it.
|
||||
|
||||
@@ -153,6 +153,7 @@ files, which is how the same ground got covered twice.
|
||||
| [`menu-navigation-semantics.md`](menu-navigation-semantics.md) | The title menu — how it moves, and where each button goes | ✅ measured: wraps both ends, Ⓑ restores focus, ⬅➡ inert; 4 of 5 destinations driven. 🟡 GamePart id is a name match, ❔ `NEW GAME` untested |
|
||||
| [`screen-transitions.md`](screen-transitions.md) | Between two screens — a fade through black, and where its timing lives | ✅ the fade quad's keyframe group is decoded (disc-wide: per-pak all-or-nothing; `GP_TITLE` = the 6 screens, not the 6 overlays); the ~0.4 s fade-OUT is measured, not on the disc |
|
||||
| [`menu-audio-cues.md`](menu-audio-cues.md) | Menu audio — the event vocabulary is on the disc, the binding is not | ✅ `SE_UI_*` cue names/ids decoded and `BANK_SE`→`Static.slb` (0/322 in FILES); 🟡 event binding is a name match; ❔ `Static.slb` has no wave boundaries, so SE audio is not extractable |
|
||||
| [`boot-config-and-gamepart-registry.md`](boot-config-and-gamepart-registry.md) | What the game reads at boot — `config.ini`, and which GameParts exist | ✅ `config.ini` selects the language (the disc's only config); ❔ its `[SYSTEM]` is empty so the boot order is not in config; 🟡 24/29 ids bind to a class, `GP_ADVERTISE_DEMO` is never registered |
|
||||
| [`movie-binding.md`](movie-binding.md) | Which movie plays where — boot intro, attract loop, new-game intro | ✅ decoded from the movie manifest (`ADVERTISE_MOVIE`→`ADV.wmv`, `MS00A`→`S00A.wmv`); attract identity confirmed independently by frame matching; 🟡 skippability unsettled |
|
||||
| [`ready-room-probe.md`](ready-room-probe.md) | S1 — the Ready Room probe: no-go, and not for the reason expected | ✅ it is 2D and enumerates (60 builds), but the pak is briefing/tactical-map content; and `kind == 0x3002` finds 0 buttons there |
|
||||
| [`ui-title-build-map.md`](ui-title-build-map.md) | Which `GP_TITLE` build is which screen state | ✅ CONFIRMED for title / `PRESS Ⓐ` / main menu / `EXTRAS` against live captures; the archive is 8 screens × EN/JP, and "6/8/9 are submenus" is withdrawn |
|
||||
|
||||
@@ -35,6 +35,14 @@ neighbourhood, not just the line.
|
||||
|
||||
## Screens, classes and RTTI
|
||||
|
||||
* "`config.ini` is a GamePart settings table, so the boot order is in it" → its
|
||||
`[SYSTEM]` section is **empty**; the only populated section is `[LANGUAGE]`.
|
||||
[`boot-config-and-gamepart-registry.md`](boot-config-and-gamepart-registry.md)
|
||||
* "the attract loop is `GP_ADVERTISE_DEMO` (GamePart 1)" → 🟡 id 1 has **no
|
||||
registration site** in the shipped build; the attract is the title replaying
|
||||
`ADV.wmv`.
|
||||
* "the 29 id-table names are 29 distinct GameParts" → 24 register, and `3`/`4`
|
||||
are the **same class** (`GamePart_SaveLoad`).
|
||||
* "Ⓐ on `NEW GAME` leads to a standing black-screen hang" → it opens
|
||||
**`DIFFICULTY`**, then **`SELECT DATA`**. What looked like a hang was a menu
|
||||
waiting for input that nobody pressed; the crash that follows is the already
|
||||
|
||||
93
docs/re/boot-config-and-gamepart-registry.md
Normal file
93
docs/re/boot-config-and-gamepart-registry.md
Normal file
@@ -0,0 +1,93 @@
|
||||
# What the game reads at boot — `config.ini`, and which GameParts actually exist
|
||||
|
||||
**Status:** ✅ `CONFIRMED` and **decoded** for the language selection. ❔ a bounded
|
||||
**negative** for the boot *order*. 🟡 for what the registration strings imply
|
||||
about the attract loop.
|
||||
|
||||
Contributes to [MISSION Q6](../port/MISSION.md), and firms up Q4's ids.
|
||||
|
||||
## ✅ `config.ini` — the disc's only config, and it selects the language
|
||||
|
||||
`config.ini` sits at the **disc root**, is 400 bytes, and is the **only** `.ini`,
|
||||
`.cfg` or `.txt` anywhere on the disc. Its own header comment (Shift-JIS) names
|
||||
it:
|
||||
|
||||
> `アプリケーション/ゲームパート初期設定テーブル`
|
||||
> — *"Application / GamePart initial settings table"*
|
||||
>
|
||||
> `SYSTEM セクションには、ゲーム及び各ゲームパートで共通にアクセスする情報を記述する`
|
||||
> — *"the SYSTEM section describes information accessed in common by the game and
|
||||
> each game part"*
|
||||
|
||||
```ini
|
||||
[SYSTEM]
|
||||
|
||||
[LANGUAGE]
|
||||
= eng ; default
|
||||
#0x01 = eng ; XC_LANGUAGE_ENGLISH
|
||||
#0x02 = jpn ; XC_LANGUAGE_JAPANESE
|
||||
#0x03 = deu ; XC_LANGUAGE_GERMAN
|
||||
#0x04 = fra ; XC_LANGUAGE_FRENCH
|
||||
#0x05 = esp ; XC_LANGUAGE_SPANISH
|
||||
#0x06 = ita ; XC_LANGUAGE_ITALIAN
|
||||
```
|
||||
|
||||
**This is the mechanism behind the EN/JP screen pairs.** The console's
|
||||
`XC_LANGUAGE_*` setting selects a three-letter code, and that code is what picks
|
||||
`GP_TITLE`'s English or Japanese build ([`ui-title-build-map.md`](ui-title-build-map.md))
|
||||
and the `<lang>.pak` families. Default is `eng`, keyed by the empty line — an
|
||||
unlisted language falls back to English. ✅ decoded. The executable does read the
|
||||
file: the string `config.ini` is at `.rdata 0x82062b44`.
|
||||
|
||||
## ❔ But the boot ORDER is not in it — and this is the whole search space
|
||||
|
||||
`[SYSTEM]` — the section the file's own comment says holds what the game and every
|
||||
game part share — is **empty**. So the file the game itself calls the *GamePart
|
||||
initial settings table* says nothing about which part runs first or what follows
|
||||
what.
|
||||
|
||||
**Reach of the negative:** this is the only config file on the disc (one `find`
|
||||
over the whole extract). The boot order is therefore not in disc-side
|
||||
configuration at all; it is in code, or in a table inside the executable that has
|
||||
not been located.
|
||||
|
||||
## 🟡 `GP_ADVERTISE_DEMO` is never registered — the attract loop is not its own part
|
||||
|
||||
The executable carries one diagnostic string per GamePart registration site
|
||||
(`silph::GamePartTask::RegisterToFactory<N, class silph::GamePart_X>::RegisterToFactory is failed!`)
|
||||
— the same evidence the corpus used to pin the id table
|
||||
([`challenge-mission-gate.md`](challenge-mission-gate.md) §3). Extracting all of
|
||||
them gives **24 of the 29 ids bound to a C++ class**; full list in
|
||||
[`data/gamepart-class-ids.txt`](data/gamepart-class-ids.txt).
|
||||
|
||||
**The five ids with no registration site are `1`, `2`, `16`, `18`, `28`** — in the
|
||||
id table's naming, `GP_ADVERTISE_DEMO`, `GP_SELECT_STORAGE`, `GP_DEMO`,
|
||||
`GP_SELECTOR`, `GP_TEST`.
|
||||
|
||||
That `GP_ADVERTISE_DEMO` (1) is among them matters for Q6, and it agrees with
|
||||
what was measured: the attract loop is **the title screen replaying `ADV.wmv`**
|
||||
([`movie-binding.md`](movie-binding.md)), not a transition into a separate
|
||||
advertise part. The id table names a part the shipped build never registers.
|
||||
|
||||
🟡 **not ✅**, because this is an argument from a *diagnostic string*: no error
|
||||
message for id 1 implies no registration site for id 1. That is how the corpus
|
||||
already reads these strings, and it is sound, but it is not the code.
|
||||
|
||||
### Two bonuses for Q4
|
||||
|
||||
* **`3` and `4` are the same class** — `GamePart_SaveLoad` is registered twice.
|
||||
The id table's separate `GP_LOAD` / `GP_SAVE` names are two ids on one part.
|
||||
* The ids behind the menu buttons now match the executable's own **class** names,
|
||||
not just a list of table names: `GamePart_Options` = 8, `GamePart_Tutorial` =
|
||||
25, `GamePart_Extras` = 5, `GamePart_MissionSelect` = 7,
|
||||
`GamePart_MovieTheater` = 6, `GamePart_Title` = 0. Still a **name match** —
|
||||
screen title ↔ class name — but anchored one level closer to the code.
|
||||
|
||||
## What is still missing for Q6
|
||||
|
||||
The *transitions*. Nothing found so far says "title, then movie, then title" — the
|
||||
manifest gives the boot-side **assets** in play order
|
||||
([`movie-binding.md`](movie-binding.md)), `config.ini` gives the **language**, and
|
||||
the registry gives **which parts exist**. What decides to advance is in
|
||||
`GamePart_Title`'s own code, and reading it is a static PPC job that has not been
|
||||
started.
|
||||
29
docs/re/data/gamepart-class-ids.txt
Normal file
29
docs/re/data/gamepart-class-ids.txt
Normal file
@@ -0,0 +1,29 @@
|
||||
GamePart ids bound to a C++ class by the executable's own registration strings
|
||||
(24 strings, 24 distinct ids)
|
||||
|
||||
0 GamePart_Title
|
||||
3 GamePart_SaveLoad
|
||||
4 GamePart_SaveLoad
|
||||
5 GamePart_Extras
|
||||
6 GamePart_MovieTheater
|
||||
7 GamePart_MissionSelect
|
||||
8 GamePart_Options
|
||||
9 GamePart_Movie
|
||||
10 GamePart_Bunk
|
||||
11 GamePart_ReadyRoom
|
||||
12 GamePart_Hangar
|
||||
13 GamePart_Arsenal
|
||||
14 GamePart_PilotLog
|
||||
15 GamePart_System
|
||||
17 GamePart_MainGame
|
||||
19 GamePart_PauseMenu
|
||||
20 GamePart_StageClear
|
||||
21 GamePart_MissionLog
|
||||
22 GamePart_GameOver
|
||||
23 GamePart_Debriefing
|
||||
24 GamePart_Dialog
|
||||
25 GamePart_Tutorial
|
||||
26 GamePart_ChallengeMission
|
||||
27 GamePart_Leaderboard
|
||||
|
||||
ids 0..28 with NO registration string: [1, 2, 16, 18, 28]
|
||||
Reference in New Issue
Block a user