re: the (16,32] gate is != 16 && <= 32, a validity check on a load parameter

Corrects this corpus's own notation: there is no lower bound, values
below 16 pass.

sub_8225EC78(X, kind, ...) -- the function carrying "script load
cancel" -- stores its second argument into X+12 and applies the same
two tests to it immediately, bailing out of the load.  So the gate is
the object's invariant, re-checked at every later touch, not a
selector.  42 sites image-wide have the shape, 34 of them in one code
region plus 3 in sub_8225EC78.

Object chain: X = [GamePart+104] is the current script instance
(installed at 0x821A78EC, previous one torn down via sub_8225EB60);
X+4 -> Y; Y+4 -> the ScriptPhase; Y+72 and [ScriptPhase+10152] get
the answer.

Refutes my own lead in the same pass: "X+12 is a GamePart id and 16 is
the unregistered one" fails its control -- 1, 2 and 18 are also absent
from the RegisterToFactory list, so 16 is one of four gaps.

Docs only; artefacts byte-identical.
This commit is contained in:
Sylpheed RE agent
2026-08-27 09:48:36 +00:00
parent 237dbce155
commit 2c5c8b11d9
2 changed files with 71 additions and 0 deletions

View File

@@ -450,6 +450,34 @@ unknown, what evidence exists, and what the first step would be. Move an item in
System 15, MainGame 17, PauseMenu 19, StageClear 20, MissionLog 21, GameOver 22,
Debriefing 23, Dialog 24, Tutorial 25, ChallengeMission 26, Leaderboard 27.
* ✅🔴 **(2026-08-27) THE `(16,32]` GATE IS READ — it is `!= 16 && <= 32`, a
VALIDITY CHECK on a load-time parameter, and my own GamePart-id lead is killed
by its control. [structures/isl-condition-builtins](structures/isl-condition-builtins.md).**
🔴 **The corpus's own notation was wrong.** `(16, 32]` implies a lower bound;
there is none — everything **below 16 passes**. The test is
`kind != 16 && kind <= 32`.
**`X+12` is a constructor argument, not engine state.** `sub_8225EC78(X,
kind, …)` — the function carrying `"script load cancel"` — does
`stw r4, 12(r30)` and then applies **those same two tests to `r4`**, bailing
out of the load. Every later site re-tests the field it just stored, so the
gate is the object's **invariant**, not a selector between behaviours. Control:
**42 sites image-wide** have this exact `cmpi 16``cmpi 32` shape, **34 in one
region** (`sub_821A9DC8`, `sub_821AA1B0`, `sub_821AB570`, `sub_821AB650`) plus 3
in `sub_8225EC78` — one object, guarded everywhere it is touched.
**The object chain is read.** `X` is installed at `0x821A78EC`
(`stw r25, 104(r30)`), the previous instance torn down first via
`sub_8225EB60` — so **`X = [GamePart+104]` is the game part's CURRENT SCRIPT
INSTANCE**. `X+4``Y`; `Y+4` → the **ScriptPhase**; `Y+72` = the answer, and
`[ScriptPhase+10152]` gets the same value. `X+12` arrives as `[r21+8]`, `r21`
being `sub_821A6CF0`'s second argument.
🔴 **REFUTED, my own lead, in the same pass.** GamePart ids run 0…27 and **16 is
not among them**, which made "`X+12` is a GamePart id, 16 being the unregistered
one" very inviting. Its control kills it: **1, 2 and 18 are also missing** from
the `RegisterToFactory` list, so 16 is one of *four* gaps, not a unique one.
Not adopted.
🟡 Not settled: what the kind **means**. The gate is read; the value's domain is
not, and chasing it needs another hop up (`sub_821A6CF0`'s caller).
## ✅✅ SOLVED — the mission freeze was a modal sign-in dialog (2026-08-26)
`XamShowSigninUI` opens a modal dialog and `xeXamDispatchDialog` blocks the