diff --git a/docs/port/HANDOFF.md b/docs/port/HANDOFF.md index 4366e0c..58b6044 100644 --- a/docs/port/HANDOFF.md +++ b/docs/port/HANDOFF.md @@ -194,11 +194,19 @@ authored version can be deleted. **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 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: + 🟡 **But the states have names, and the transition uses them.** `sub_821C6458`, + the title part's state function, calls **`sub_821CC860(…, "", 0)`** with + `TITLE_SCREEN`, `TITLE_MENU` and `LOADING` — the three states measured off the + game, in the game's own words — and installs the result. So a transition is a + call with a **name** argument, which is also why `GP_ADVERTISE_DEMO` has no + xrefs: at this level the screen graph is name-keyed, not id-keyed. + That lookup has 28 callers, and the identifier strings around them include + `DIFFICULTY`, `EXTRA_MENU` and `TUTORIAL_MENU` — screens measured independently + before the function was read. 🟡 a **candidate** vocabulary: those strings are + referenced by the callers, not proven to be the argument, and the list mixes in + config keys (`TEXT_FONT`, `GAMMA_RGB`, …). + The port can transcribe the state **names**; the order still comes from + measurement. 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. @@ -275,7 +283,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) | `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 | +| 🟡 | **the boot transitions in code** (Q6) | a title-side transition is a **screen lookup by NAME** — `sub_821CC860(…, "TITLE_SCREEN"/"TITLE_MENU"/"LOADING", 0)` then install. A candidate name vocabulary of ~12 screens falls out, 3 of them corroborated by measurement. 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/boot-config-and-gamepart-registry.md b/docs/re/boot-config-and-gamepart-registry.md index 050d87a..3df79fd 100644 --- a/docs/re/boot-config-and-gamepart-registry.md +++ b/docs/re/boot-config-and-gamepart-registry.md @@ -189,3 +189,63 @@ before them are the tail of 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. + + +## 🟡 The title's transition is a screen lookup BY NAME — `sub_821CC860` + +Reading the code around each of the three state names shows the **same four +instructions** at all three sites: + +``` + lwz r29, 20(r30) ; an object off the part + lwz r3, 4(...) ; ... + bl 0x822F2328 + lis r11, 0x820A + li r6, 0 + lwz r4, 24(r30) + addi r5, r11, 15676 ; "TITLE_SCREEN" (15664 = "TITLE_MENU", + lwz r3, 88(r30) ; 8524 = "LOADING") + bl 0x821CC860 ; <- lookup(this+88, this+24, NAME, 0) + mr r4, r3 + bl 0x82187B78 ; <- install the result +``` + +So a title-side transition is **`sub_821CC860(…, "", 0)` followed by +`sub_82187B78(result)`** — a *string-keyed* screen lookup, then an install. Not a +numeric id, not a table index. That also fits `GP_ADVERTISE_DEMO` having zero +xrefs: at this level the screen graph is keyed by **name**, not by GamePart id. + +### The candidate name vocabulary + +`sub_821CC860` is called from **28 distinct functions**. Collecting the +upper-case identifier strings those callers reference gives 35 names, and they +split into two obvious families: + +* **screen/state names** — `TITLE_SCREEN`, `TITLE_MENU`, `LOADING`, + **`DIFFICULTY`**, `EXTRA_MENU`, `TUTORIAL_MENU`, `STANDARD_MENU`, `DEBRIEFING`, + `CHALLENGE`, `MISSIONS`, `LIVE_BOARD`, `LOCAL_BOARD`, `EXTRA_MENU`; +* **config keys** — `TEXT_FONT`, `TEXT_HEIGHT`, `LINE_SPACE`, `GAMMA_RGB`, + `GAMMA_WB`, `TEXT_SPEED_PER_LETTER`, `EXIT_VALUE`, `INPUT_DIR`, + `MENU_ENABLE_SKIP`/`_DISABLE_SKIP`, `PAUSE_SE`, `JINGLE`, … + +plus `BASE_INFO` in **19 of the 28** callers, which is this corpus's existing +marker for a screen-config function. + +**Three of the screen names are independently corroborated by measurement**: +`DIFFICULTY` is exactly the screen `NEW GAME` opens, `EXTRA_MENU` matches the +`EXTRAS` submenu and `TUTORIAL_MENU` the lesson list — all three measured off the +running game in [`menu-navigation-semantics.md`](menu-navigation-semantics.md) +before this function was ever looked at. + +⚠️ **Why this is 🟡 and not ✅.** The 35 strings are what those callers +*reference*, **not** proven arguments to `sub_821CC860` — the list plainly mixes +screen names with config keys, so it is a **candidate vocabulary**, not a decoded +one. Confirming it means checking, per call site, which string actually lands in +`r5`. That was not done. + +### What is still unread + +Which state leads to which. The three lookups sit in different branches of one +function and at least one (`TITLE_MENU`) is guarded by a `cmplwi`/`bne`, but the +branch structure was not traced, so the *order* still comes from measurement, not +from the code.