From 25a98fb2049b390ed63f71a6b7267243587f62cd Mon Sep 17 00:00:00 2001 From: Sylpheed RE agent Date: Tue, 25 Aug 2026 18:18:19 +0000 Subject: [PATCH] re: trigger queue walks live -- structure confirmed, record contents refuted Walked the container's list from +16 for 200s. The structure holds: +20 tracks the node count, nodes chain through their first word, and entries appear as the mission runs (0 -> 1 -> 2, then stable). The record layout does not. I expected node+8 to hold small symbol indices, which the pop's out-parameters made natural. Every field is a guest heap pointer (0xBC..), so trigger records reference objects rather than table indices, and those objects are unidentified. Also records a false resolution I introduced: a line printed 'f4=0(ADN101)' because the raw value is 0 and my formatter mapped index 0 to symbol-table-2's first entry. ADN101 is not in that record -- the pretty-printer invented a name for a null. A resolver must refuse values that were never indices. And corrects the previous section: sub_8226E3B8 is a CLEAR, not a push. Its tail decrements a counter, calls an erase helper, and loops while [+20] != 0. So built-in 100 clears the queue then rebuilds the thread list, matching the built-in table's own wording; 'push' was my label, not the disassembly's. Two callers: vt2 (script) and 0x8226D420 (an engine site). What appends a node is still unidentified. --- docs/re/structures/isl-builtins.md | 45 ++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/docs/re/structures/isl-builtins.md b/docs/re/structures/isl-builtins.md index b5fa077..19385bb 100644 --- a/docs/re/structures/isl-builtins.md +++ b/docs/re/structures/isl-builtins.md @@ -293,3 +293,48 @@ debugger. That is the first direct view of *what the script is waiting for*. `0x000A0009`, which is not a pointer. The `addi r31, r30, 12` in the push made "list head" the obvious reading and the value does not support it. Recorded as unresolved rather than quietly kept. + + +## 🟡 Walking the trigger queue live — structure confirmed, contents not + +Walked the container's linked list from `+16` for 200 s of a Stage 02 mission: + +``` +[ 0s] count=0 head=0xBC28E610 +[ 80s] count=1 head=0xBC28E610 + node 0 @0xBC28E610: f0=0xBC63.. f4=0xBC40.. f8=0xBC25.. dbl=-0.000 f24=0xBC25.. +[120s] count=2 head=0xBC28E610 + node 1 @0xBC28E630: f0=0xBC65.. f4=0 f8=0xBC25.. dbl=-0.000 f24=0xBC25.. +``` + +✅ **The structure holds**: the count at `+20` tracks the number of nodes, the +nodes chain through their first word, and new entries appear as the mission runs +(0 → 1 → 2, stable thereafter). + +🔴 **The record layout does not.** I expected `node+8` to hold small **symbol +indices** — the pop's out-parameters made that the natural reading. Every field +is a **guest heap pointer** (`0xBC…`). So the trigger record references objects, +not table indices, and what those objects are is unidentified. + +### ⚠️ A false resolution I introduced myself + +The `[120s]` line first printed `f4=0(ADN101)` — because the raw value is **0** +and my formatter mapped index 0 to symbol-table-2's first entry. `ADN101` is not +in that record; it is my own pretty-printer inventing a name for a null. A +resolver must refuse to resolve values that were never indices, and this one had +no such guard. Recorded because it is exactly the sort of plausible label that +would survive into a conclusion. + +## 🔴 Correction: `sub_8226E3B8` is a CLEAR, not a push + +The previous section called it the push, reached from built-in 100 via `vt2`. +Its tail refutes that: it decrements a counter, calls an erase helper +(`sub_8226EAB8`), and **loops while `[+20] != 0`** (`beq 0x8226E3E4`). That is a +**drain-the-whole-queue** routine. + +So built-in 100 *clears* the trigger queue and then rebuilds the thread list via +`sub_82273BE8` — consistent with the built-in table's own description +("push the argument record ... then drain/rebuild"), and the "push" label was +mine, not the disassembly's. `xrefs` gives it two callers: `0x82265DD4` (vt2, +the script side) and **`0x8226D420`, an engine site** — so the engine clears it +too. What actually *appends* a node is still unidentified.