diff --git a/docs/port/HANDOFF.md b/docs/port/HANDOFF.md index 4ee9ff4f..062eafe6 100644 --- a/docs/port/HANDOFF.md +++ b/docs/port/HANDOFF.md @@ -212,6 +212,11 @@ authored version can be deleted. `LOADING`. `4 → 0` is the only edge back to the title, reached from `2 → 4` — which matches Ⓑ-returns-to-title as measured. Full graph in [`data/title-state-machine.txt`](../re/data/title-state-machine.txt). + ⚠️ **All of that is ONE PHASE.** `GamePart_Title` dispatches on an outer phase + field at `this+132` (five values) before reaching any of it: phase 0 is the + **developer splash** (`sub_821C5690`, the same function the corpus fingered + independently), phase 4 is the title/menu machine. The ten states and + eighteen edges above live inside phase 4 alone. ✅ **State 4's edge conditions are an event code** — `sub_821C6458`'s third argument. State 4 is the input-waiting state (reached straight after the menu is installed) and handles 6 of 26 events: **`0` → title**, **`3`, `5`, `8`, @@ -296,7 +301,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) | state machine **decoded** (10 states, 18 edges) and state 4's edges are selected by an **event code** — 6 of 26 handled: `0`→title, `3/5/8/25`→`LOADING`, `10`→state 5. Still unknown: what the event *numbers* mean | +| 🟡 | **the boot transitions in code** (Q6) | `GamePart_Title` has **two nested state fields** — a 5-way phase at `this+132` (phase 0 = the splash, phase 4 = title/menu) and a 10-way state at `this+136` inside phase 4, with 18 edges selected by an **event code**. Unknown: what the event *numbers* mean, and phases 1–3 | | ❔ | **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 10a145b6..a9ca0f06 100644 --- a/docs/re/REFUTED.md +++ b/docs/re/REFUTED.md @@ -35,6 +35,10 @@ neighbourhood, not just the line. ## Screens, classes and RTTI +* "`sub_821C6458` is `GamePart_Title`'s state machine" → **mine, imprecise.** It + is the machine for **phase 4** of a five-way outer dispatch at `this+132`; + phase 0 is the splash. The ten states and eighteen edges are phase 4 only. + [`boot-config-and-gamepart-registry.md`](boot-config-and-gamepart-registry.md) * "`sub_821CC860` is the game's by-name screen factory" → **mine, and wrong.** Its decoded arguments include `BG`, `BLACK`, `FADE`, `FILE`, `KEY`, `PAD`, `SOUND`, `GAMMA_RGB` — it is a **generic name-keyed lookup**, mostly config. diff --git a/docs/re/boot-config-and-gamepart-registry.md b/docs/re/boot-config-and-gamepart-registry.md index d7848165..7d127f96 100644 --- a/docs/re/boot-config-and-gamepart-registry.md +++ b/docs/re/boot-config-and-gamepart-registry.md @@ -399,3 +399,45 @@ observation so the next person sees the shape; it is **not** a button→event ma * **what the event numbers mean** — button id, menu-item index, or message id; * **conditions on edges out of the other states** (`0 → 1` vs `0 → 2`, `6 → 7/9/2`); * states 1, 3, 5, 6, 7, 9, which install no named screen. + + +## 🔴 Correcting my own framing: `sub_821C6458` is ONE PHASE, not the whole part + +Chasing where the event code comes from turned up the level above, and it revises +what the previous three sections called "the title part's state machine". + +`sub_821C6458` has exactly one caller, `sub_821C7850`, and that caller is itself a +dispatcher — on a **second, outer state field**: + +``` +821c786c lwz r11, 16(r30) ; only runs at all when this+16 == 3 +821c7874 bne cr6, +821c787c lwz r11, 132(r30) ; phase = this+0x84 +821c7880 cmplwi cr6, r11, 0x4 ; FIVE phases, 0..4 +821c789c bctr ; table at 0x821C78A0 +``` + +| phase | handler | | +|---|---|---| +| 0 | `sub_821C5690` | **the splash** — independently identified as the splash mechanics in the `iterate3E` notes, before any of this | +| 1 | inline at `0x821c790c` | | +| 2 | `sub_821C5818` | | +| 3 | `sub_821C5EC0` | | +| **4** | **`sub_821C6458`** | the title/menu machine — `TITLE_SCREEN` / `TITLE_MENU` / `LOADING` | + +So `GamePart_Title` has **two nested state fields**: a phase at `this+132` (five +values) selecting which sub-machine runs, and the state at `this+136` (ten values) +*inside phase 4*. Everything the previous sections decoded — the ten states, the +eighteen edges, the event dispatch — is **phase 4 only**. Phases 0–3 are +untouched, and one of them is the developer splash. + +That phase 0 lands on the function the corpus had already fingered as the splash, +from a completely different direction, is the useful check here. + +### And the event code is forwarded, not created + +All five phase handlers are called as `(this, r29, r28)` with the *same* +arguments, and `r28` is `sub_821C7850`'s own third argument, passed through +untouched. So the event vocabulary is defined **at least one level above** this +function. Finding what `3`, `5`, `8`, `10`, `25` mean means going up again, and +that was not done. diff --git a/docs/re/data/title-state-machine.txt b/docs/re/data/title-state-machine.txt index dc9311ae..31a8f085 100644 --- a/docs/re/data/title-state-machine.txt +++ b/docs/re/data/title-state-machine.txt @@ -1,4 +1,26 @@ -GamePart_Title's screen state machine -- sub_821C6458, decoded statically. +GamePart_Title has TWO nested state fields. + +OUTER -- sub_821C7850, the part's dispatcher + 821c786c lwz r11, 16(r30) ; only runs when this+16 == 3 + 821c7870 cmpwi cr6, r11, 3 + 821c7874 bne cr6, + 821c787c lwz r11, 132(r30) ; phase = this+0x84 + 821c7880 cmplwi cr6, r11, 0x4 ; five phases, 0..4 + 821c7888 lis/addi r12, 0x821C78A0 ; jump table + 821c789c bctr + + phase 0 -> sub_821C5690 (the splash -- independently identified as the + splash mechanics in the iterate3E notes) + phase 1 -> inline block at 0x821c790c + phase 2 -> sub_821C5818 + phase 3 -> sub_821C5EC0 + phase 4 -> sub_821C6458 (the title/menu machine, below) + + All four call sites forward the SAME three arguments: (this, r29, r28), + where r28 is this function's own third argument -- an EVENT CODE passed + through unchanged from ITS caller. + +INNER -- sub_821C6458, the title/menu machine (phase 4 only) DISPATCH 821c6474 lwz r11, 136(r30) ; state = this+0x88 @@ -67,7 +89,8 @@ THE CONDITION ON STATE 4's EDGES -- decoded event 25 -> block 0x821c6ed8 -> state 8 (LOADING) WHAT IS NOT DECODED - * what the event NUMBERS mean -- button id, menu-item id or message id; + * what the event NUMBERS mean -- they are forwarded unchanged from + sub_821C7850's caller, so the vocabulary is defined at least one level up -- button id, menu-item id or message id; * the conditions on edges out of states other than 4; * what states 1, 3, 5, 6, 7 and 9 do (they install no named screen); * state 3 is never a destination here, so something outside this function