From af9e8006b68ef8dede6db08ec36a9c6dd7f324c0 Mon Sep 17 00:00:00 2001 From: Sylpheed RE agent Date: Thu, 27 Aug 2026 07:53:26 +0000 Subject: [PATCH] re: +24 is the trigger kind tag -- built-in 19 registers a routine, built-in 25 a route Read straight off the drain, immediately after the pop: 8226D7AC lwz r11, 92(r31) ; payload+24 8226D7B8 cmpli cr6, 0, r11, 0x1 8226D7C4 bc 12, lt, 0x8226D89C ; +24 == 0 -> the SPAWN path 8226D7C8 bc 4, eq, 0x8226DA44 ; +24 > 1 -> bail ; +24 == 1 -> fall through, a NON-spawn path So the field I recorded last iteration as "kind-tag shaped, but the drain was not shown branching on it" does branch on it, three ways. +24 = 0, written by built-in 19: condition sub_8226DAF8, then bl 0x822737C8 -- +28 is a code offset, matching the 79/79-vs-27.8%-control measurement. +24 = 1, written by built-in 25: condition sub_8226DC80, no spawn, and the path resolves +28 through [phase+244] -- symbol table 1: 8226D834 lwz r10, 112(r31) ; payload+28 8226D838 lwz r11, 244(r29) ; symtab 1 8226D848 lwzx r10, r10, r11 And that resolution checks out: over all 25 call sites disc-wide, built-in 25's local[12] resolves to a symbol-table-1 entry 25 times out of 25, and every name is a route -- Route_ADS101_p1F, Route_ADT107_p1F, Route_TCN004_p1S, Route_ADT202A_p2S. The 1-12 values that looked like a puzzle two iterations ago are simply small symbol indices. This independently confirms isl.py's SYM1_SLOTS, which lists slot 12 for built-in 25 and was derived from operand ranges alone. So there are two kinds of trigger: built-in 19 registers one whose payload is a HANDLER ROUTINE, built-in 25 one whose payload is a ROUTE. All artefacts regenerate byte-identical; documentation only. Unread: both condition testers (sub_8226DAF8, sub_8226DC80), what the kind-1 path does with the route past sub_8217FA08 / sub_8218CC88 / sub_8225FEA0, and the drain's second spawn site at 0x8226DA10. --- docs/re/BACKLOG.md | 17 +++++++++ docs/re/structures/isl-trigger-node.md | 53 +++++++++++++++++++++++--- 2 files changed, 64 insertions(+), 6 deletions(-) diff --git a/docs/re/BACKLOG.md b/docs/re/BACKLOG.md index 8a2a6081..c9fef6d1 100644 --- a/docs/re/BACKLOG.md +++ b/docs/re/BACKLOG.md @@ -153,6 +153,23 @@ unknown, what evidence exists, and what the first step would be. Move an item in entered from outside it. ▶️ **No static test I have devised can choose**; a runtime probe on `sub_822737C8`'s third argument would. +* ✅ **(2026-08-27) `+24` IS the trigger kind tag, and built-in 25's payload is a + ROUTE. [structures/isl-trigger-node](structures/isl-trigger-node.md).** Read + straight off the drain after the pop: `lwz r11,92(r31)` (payload+24), + `cmpli 0x1`, `bc lt → 0x8226D89C` (**+24 == 0 → the SPAWN path**), `bc ne → exit` + (**+24 > 1 → bail**), else fall through (**+24 == 1 → a NON-spawn path**). + So **built-in 19 (writes 0) → spawn**, condition `sub_8226DAF8`, `+28` = a code + offset (79/79 vs 27.8 % control); **built-in 25 (writes 1) → no spawn**, condition + `sub_8226DC80`, and the path resolves `+28` through **`[phase+244]` = symbol + table 1** (`lwz r10,112(r31); lwz r11,244(r29); lwzx`). 🔑 **All 25 of built-in + 25's `local[12]` values resolve to symtab-1 entries, and every one is a + `Route_*`** (`Route_ADS101_p1F`, `Route_TCN004_p1S`, …) — so the puzzling 1–12 + values are small symbol indices, and this independently confirms `SYM1_SLOTS[12] ∋ + 25`, derived from operand ranges alone. **Two trigger kinds: built-in 19 registers + a HANDLER ROUTINE, built-in 25 registers a ROUTE.** 🟡 Unread: both condition + testers, what the kind-1 path does with the route, and the drain's second spawn + site `0x8226DA10`. + ## ✅✅ SOLVED — the mission freeze was a modal sign-in dialog (2026-08-26) `XamShowSigninUI` opens a modal dialog and `xeXamDispatchDialog` blocks the diff --git a/docs/re/structures/isl-trigger-node.md b/docs/re/structures/isl-trigger-node.md index bda4ffb1..332a01a8 100644 --- a/docs/re/structures/isl-trigger-node.md +++ b/docs/re/structures/isl-trigger-node.md @@ -127,16 +127,57 @@ different things in the same slot. Observed alongside it: built-in 25 writes tag — 🟡 but the drain was not shown branching on it, so that is an observation, not a reading. +## ✅ `+24` IS the kind tag — a three-way dispatch in the drain + +Read straight off the drain, immediately after the pop: + +``` +8226D7AC lwz r11, 92(r31) ; payload+24 +8226D7B8 cmpli cr6, 0, r11, 0x1 +8226D7C4 bc 12, lt, 0x8226D89C ; +24 == 0 -> the SPAWN path +8226D7C8 bc 4, eq, 0x8226DA44 ; +24 > 1 -> bail + ; +24 == 1 -> fall through, the OTHER path +``` + +| `+24` | written by | path | condition test | what `+28` is | +|---|---|---|---|---| +| **0** | **built-in 19** | `0x8226D89C` → `bl 0x822737C8` | `sub_8226DAF8` | a **code offset** (79/79 vs a 27.8 % control) | +| **1** | **built-in 25** | falls through at `0x8226D7CC` — **no spawn** | `sub_8226DC80` | an index into **`[phase+244]`** | + +The non-spawn path is explicit about it: + +``` +8226D834 lwz r10, 112(r31) ; payload+28 +8226D838 lwz r11, 244(r29) ; [phase+244] = SYMBOL TABLE 1 +8226D848 lwzx r10, r10, r11 ; resolve it as a symtab-1 index +``` + +### ✅ And built-in 25's `+28` resolves to a ROUTE + +Over all 25 call sites disc-wide, `local[12]` read through symbol table 1: + +**25 of 25 resolve**, and every name is a route — +`Route_ADS101_p1F`, `Route_ADT107_p1F`, `Route_TCN004_p1S`, `Route_ADT202A_p2S`, … + +So the 1–12 values that looked like a puzzle are simply small symbol indices. +This also confirms `isl.py`'s `SYM1_SLOTS`, which lists slot 12 for built-in 25 +and was derived from operand ranges alone — **two independent routes, same +conclusion**. + +**The two built-ins register two kinds of trigger:** built-in 19 a trigger whose +payload is a *handler routine*, built-in 25 one whose payload is a *route*. + ## 🟡 Not settled -* **What `local[12]` indexes.** Values 1–12, and `SYM1_SLOTS` lists slot 12 for - built-in 25 (symbol table 1 — routes, messages, objectives), which is - consistent with a small index but was not verified here. * ~~What the drain actually spawns.~~ ✅ Resolved above: built-in 19's nodes carry a real routine offset at `+28`. -* **Whether `+24` selects between the two node kinds** — 1 from built-in 25, 0 - from built-in 19 — is unshown; the drain reads it into a stack slot that the - spawn path does not visibly use. +* ~~Whether `+24` selects between the two node kinds~~ ✅ It does — see above. +* **The two condition testers are unread**: `sub_8226DAF8` (kind 0) and + `sub_8226DC80` (kind 1), each gating its path on a `== 1` result. +* **What the kind-1 path DOES with the route** past `sub_8217FA08` / + `sub_8218CC88` / `sub_8225FEA0` is unread. +* **The drain's second spawn site** (`0x8226DA10`) is in a later block and was + not traced. * **This still does not explain the unreached code.** All 79 of built-in 19's handler offsets are already reachable — **0 are unreached run-starts**. * **`sub_8226E458`'s effect** on the container.