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:
@@ -134,6 +134,49 @@ left unnamed rather than named off an unverified premise.
|
||||
and exactly one reference in the image — a tail `b` from `0x821AC064` — so the
|
||||
string recipe finds nothing there.
|
||||
|
||||
## 🔴✅ (2026-08-27) The gate is `!= 16 && <= 32` — and it is a VALIDITY CHECK, not a selector
|
||||
|
||||
🔴 **First, a correction to this page's own notation.** Written as `(16, 32]` it
|
||||
implies a lower bound. There is none:
|
||||
|
||||
```
|
||||
8225EC90 cmpi cr6, 0, r4, 16
|
||||
8225EC94 stw r4, 12(r30) ; <- the field IS the argument
|
||||
8225EC98 bc 12, eq, <bail> ; == 16 -> bail
|
||||
8225EC9C cmpi cr6, 0, r4, 32
|
||||
8225ECA0 bc 12, gt, <bail> ; > 32 -> bail
|
||||
```
|
||||
|
||||
Everything **below** 16 passes. The condition is `kind != 16 && kind <= 32`.
|
||||
|
||||
✅ **`X+12` is a constructor parameter, not engine state.** `sub_8225EC78(X,
|
||||
kind, …)` — the function carrying the string `"script load cancel\n"` — stores
|
||||
its second argument into `+12` and applies the identical pair of tests to it
|
||||
immediately, bailing out of the load. Every later occurrence re-tests the field
|
||||
it just stored. So the gate is that object's **invariant**, re-checked wherever
|
||||
it is touched, not a switch selecting between behaviours.
|
||||
|
||||
✅ **Where it is checked**: 42 sites image-wide with this exact `cmpi 16` →
|
||||
`cmpi 32` shape, **34 of them in one code region** — `sub_821A9DC8`,
|
||||
`sub_821AA1B0`, `sub_821AB570`, `sub_821AB650` — plus 3 in `sub_8225EC78`. One
|
||||
object, guarded everywhere.
|
||||
|
||||
✅ **And the object chain is now read.** `X` is installed at `0x821A78EC`
|
||||
(`stw r25, 104(r30)`), the previous one torn down first through `sub_8225EB60`;
|
||||
so `X = [GamePart+104]` is **the game part's current script instance**. From
|
||||
there `X+4` → `Y`, and `Y+4` → the **ScriptPhase**, `Y+72` = the answer, with
|
||||
`[ScriptPhase+10152]` receiving the same value. `X+12`'s value arrives as
|
||||
`[r21+8]`, `r21` being `sub_821A6CF0`'s own second argument.
|
||||
|
||||
🔴 **A tempting reading, killed by its control.** GamePart ids (from the
|
||||
`RegisterToFactory<N,…>` strings) run 0…27, and **16 is not among them** — which
|
||||
makes "`X+12` is a GamePart id and 16 is the unregistered one" very inviting.
|
||||
It fails: **1, 2 and 18 are also absent** from that list, so 16 is one of *four*
|
||||
gaps, not a unique one. Nothing distinguishes it. The reading is not adopted.
|
||||
|
||||
🟡 So what the kind **means** is still open — the gate is now read, but the
|
||||
value's domain is not.
|
||||
|
||||
🟡 Its neighbours belong to the same cluster: `builtin103` reads
|
||||
`[phase+10156]` and `[phase+10152]` (9 and 7 writers), and a sibling vtable stub
|
||||
clears `[phase+10152]`. The shape is an engine→script status trio, but that is a
|
||||
|
||||
Reference in New Issue
Block a user