re: a title-side transition is a screen lookup BY NAME, not by id
Continuing Q6's last residual -- the control flow I left unread. All three state-name sites in sub_821C6458 compile to the same shape: load the name, then bl 0x821CC860 with it in r5 and 0 in r6, then hand the result to sub_82187B78. So a transition is lookup-by-string then install: sub_821CC860(this+88, this+24, "TITLE_SCREEN", 0). Not a numeric id and not a table index. That also explains something that had been sitting unexplained -- GP_ADVERTISE_DEMO having zero xrefs -- because at this level the screen graph is keyed by name rather than by GamePart id. sub_821CC860 has 28 callers, and the upper-case identifiers in that neighbourhood split cleanly into screen names and config keys. Three of the screen names are corroborated by measurements I took before ever opening this function: DIFFICULTY is what NEW GAME opens, EXTRA_MENU is the EXTRAS submenu, TUTORIAL_MENU the lesson list. That is the static side agreeing with the dynamic side on names neither knew about the other. Held at amber deliberately. The 35 strings are what those callers REFERENCE, not proven arguments, and the list plainly mixes screen names with things like TEXT_FONT and GAMMA_RGB. Confirming it means checking per call site which string actually lands in r5, and I did not do that. Still unread: which state leads to which. The three lookups sit in different branches and TITLE_MENU's is guarded by a cmplwi/bne, but I did not trace the branch structure, so the ORDER still comes from measurement rather than from the code.
This commit is contained in:
@@ -194,11 +194,19 @@ authored version can be deleted.
|
|||||||
**only as a stack argument in flight** (no persistent field, no literal store),
|
**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
|
and the string `GP_ADVERTISE_DEMO` has **zero xrefs**. A transition is a call
|
||||||
with an id argument, chosen by code.
|
with an id argument, chosen by code.
|
||||||
🟡 **The states do have names, though.** `sub_821C6458`, the title part's state
|
🟡 **But the states have names, and the transition uses them.** `sub_821C6458`,
|
||||||
function, references `TITLE_SCREEN`, `TITLE_MENU` and `LOADING` — the three
|
the title part's state function, calls **`sub_821CC860(…, "<NAME>", 0)`** with
|
||||||
states measured off the game, in the game's own words — and asks for screen
|
`TITLE_SCREEN`, `TITLE_MENU` and `LOADING` — the three states measured off the
|
||||||
config under those keys. `config.ini` has no such sections, so the contents are
|
game, in the game's own words — and installs the result. So a transition is a
|
||||||
code defaults. The port can transcribe the **names**, not the values. The sequence itself is fully measured:
|
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 →
|
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.
|
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 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 |
|
| 🟡 | **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 |
|
| 🟡 | **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 |
|
| ❔ | **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
|
(An earlier version of this table called the audio items blocked on "an emulator
|
||||||
|
|||||||
@@ -189,3 +189,63 @@ before them are the tail of
|
|||||||
zero-filled descriptors — static-initialiser records trailing the registration
|
zero-filled descriptors — static-initialiser records trailing the registration
|
||||||
strings, not a dispatch table. A plausible-looking array of function pointers next
|
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.
|
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(…, "<NAME>", 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.
|
||||||
|
|||||||
Reference in New Issue
Block a user