diff --git a/docs/port/HANDOFF.md b/docs/port/HANDOFF.md index 30e44011..4366e0cc 100644 --- a/docs/port/HANDOFF.md +++ b/docs/port/HANDOFF.md @@ -193,7 +193,12 @@ authored version can be deleted. movie manifest carries assets not transitions, the requested GamePart id lives **only as a stack argument in flight** (no persistent field, no literal store), and the string `GP_ADVERTISE_DEMO` has **zero xrefs**. A transition is a call - with an id argument, chosen by code. The sequence itself is fully measured: + with an id argument, chosen by code. + 🟡 **The states do have names, though.** `sub_821C6458`, the title part's state + function, references `TITLE_SCREEN`, `TITLE_MENU` and `LOADING` — the three + states measured off the game, in the game's own words — and asks for screen + config under those keys. `config.ini` has no such sections, so the contents are + code defaults. The port can transcribe the **names**, not the values. The sequence itself is fully measured: splash → `ADV.wmv` → title + `PRESS Ⓐ` → (idle ~8–10 s → `ADV.wmv` in full → title) → Ⓐ → main menu, with Ⓑ from the main menu returning to the title. @@ -270,7 +275,7 @@ here until 2026-08-28 and is now settled.) | ❔ | **the other ~319 SE cues** (Q8) | located one at a time by triggering them; only the three the menu needs have been done | | 🟡 | **the paint-order tie-break** (Q3) | eight candidates refuted; costs one element's blend on one screen | | 🟡 | **GamePart ids behind the buttons** (Q4) | the *screens* are measured; the ids are a name match onto the executable's class names | -| ❔ | **the boot transitions in code** (Q6) | bounded as code-not-data, not proven. `sub_821C6458` — the substantial function in `GamePart_Title`'s neighbourhood — has **not been read** | +| 🟡 | **the boot transitions in code** (Q6) | `sub_821C6458` is the title's state function and **names its states** — `TITLE_SCREEN`, `TITLE_MENU`, `LOADING`. It asks for config under those keys and `config.ini` has no such sections, so the defaults are in code. Which state leads to which is still unread | | ❔ | **builds 0/1 and 10/11**, the `DELTASABER` plates (Q2) | never seen anywhere in the boot path, the title-side screens or the attract loop. A mission load is the remaining candidate and this container kills runs before one completes | (An earlier version of this table called the audio items blocked on "an emulator diff --git a/docs/re/REFUTED.md b/docs/re/REFUTED.md index 74e44db6..2c239bd1 100644 --- a/docs/re/REFUTED.md +++ b/docs/re/REFUTED.md @@ -35,6 +35,11 @@ neighbourhood, not just the line. ## Screens, classes and RTTI +* "the `{func, func, ptr}` triples at `0x820a3b48` are a GamePart state table" → + **static-initialiser records trailing the `RegisterToFactory` strings.** The + bytes before them are the tail of a diagnostic string and the data column is + zero-filled descriptors. + [`boot-config-and-gamepart-registry.md`](boot-config-and-gamepart-registry.md) * "the boot sequence is driven by a table the game reads" → it is **not data-driven**; four search spaces closed, transitions are calls with an id argument. [`boot-config-and-gamepart-registry.md`](boot-config-and-gamepart-registry.md) diff --git a/docs/re/boot-config-and-gamepart-registry.md b/docs/re/boot-config-and-gamepart-registry.md index 523e2425..050d87a2 100644 --- a/docs/re/boot-config-and-gamepart-registry.md +++ b/docs/re/boot-config-and-gamepart-registry.md @@ -132,3 +132,60 @@ developer splash (a RATC screen, not a video) with the fade-through-black timings in [`screen-transitions.md`](screen-transitions.md) and Ⓑ from the main menu returning to the title. + + +## 🟡 `sub_821C6458` read — the title's states are NAMED in the executable + +The page above left this function as the named next step: "the substantial +function in `GamePart_Title`'s neighbourhood, and **reading it has not been +attempted**". It has now been looked at — not disassembled line by line, but +characterised, which is enough to sharpen Q6. + +**It is the title part's screen-state function.** 4 460 bytes, has EH, and called +from **exactly one** place — `sub_821C7850`, which sits in the same neighbourhood +as the creator the registration site points at (`sub_821C7D98`). It makes 33 +distinct calls. + +**What it names.** Its `.rdata` string references are: + +| string | at | +|---|---| +| **`TITLE_SCREEN`** | `0x820a3d3c` | +| **`TITLE_MENU`** | `0x820a3d30` | +| **`LOADING`** | `0x820a214c` | +| `BASE_INFO` (×2) | `0x820a20ec` | + +Those are the states measured off the running game, in the game's own words: the +title carrying `PRESS Ⓐ BUTTON`, the five-button menu, and a loading state. And +`BASE_INFO` is this corpus's own marker for a **screen-config lookup** rather than +a table read ([`REFUTED.md`](REFUTED.md), "`BASE_INFO` discriminates +screen-config from table-read, 9/9 vs 10/10"). + +### The sharper negative + +So the title part **does ask for configuration keyed by `TITLE_SCREEN` and +`TITLE_MENU`** — and [`config.ini`](#-configini--the-discs-only-config-and-it-selects-the-language), +the disc's only config file, contains **no such sections**. Its only sections are +an empty `[SYSTEM]` and `[LANGUAGE]`. The lookups find nothing, and the values are +whatever the code defaults to. + +That is a better answer than "the order is not in config": the game *asks the +question*, the shipped disc *does not answer it*, and the defaults live in code. +For the port it means the state **names** are transcribable even though their +contents are not. + +🟡 **Not ✅.** This is a characterisation from string references and call counts, +not a read of the control flow. Two self-references (`0x821c6498`, `0x821c6b7c`) +inside the function look like jump tables — a switch, which is what a state +machine compiles to — but that was **not confirmed**, and nothing here shows which +state leads to which. + +### 🔴 Refuted on the way, because it looked like a find + +The words at `0x820a3b48`… resolve as neat `{func, func, ptr}` triples and read +convincingly as a state/handler table. **They are not.** The bytes immediately +before them are the tail of +`…SaveLoad>::RegisterToFactory is failed!`, and the `0x8210c1xx` targets are +zero-filled descriptors — static-initialiser records trailing the registration +strings, not a dispatch table. A plausible-looking array of function pointers next +to relevant strings is not evidence of anything until its neighbours are read.