re: the trigger-queue appender is built-in 25 -- the script appends, not the engine

isl-builtins.md carried the trigger queue at phase+272 a long way -- layout, live
count at +272+20, the generic appender sub_8226EAB8 -- and stopped at "what actually
appends a node is still unidentified", proposing a gdb watchpoint on a running
emulator.  It is a static question after all.

sub_8226EAB8 is a shared helper with 16 callers, so it cannot be identified by name.
But the corpus records that the trigger container EMBEDS its inner list at +12, so the
appender must hand it container+12.  Only two of the sixteen callers do, and one sets
its base 34 instructions earlier:

  8226A22C  addi r29, r24, 272     ; r24 = the ScriptPhase
  8226A2B4  addi r3,  r29, 12      ; -> phase + 272 + 12
            bl   0x8226EAB8

phase+272+12 is exactly the inner list whose count the corpus watched at +272+20.

sub_8226A0D8 is ScriptPhase vtable SLOT 28, which is what BUILT-IN 25's stub
tail-calls, and there are ZERO real `bl 0x8226A0D8` instructions in the image -- it is
reached only through the vtable.  So the queue is populated by the SCRIPT, retiring
the residual "the engine moves records into the phase's queue each frame" reading that
isl-builtins.md had already flagged as unsupported by its own call site.  Built-in 25's
arguments agree with two independently measured tables: UNIT_ARG (a unit at local[4])
and SYM1_SLOTS[12] (a symtab-1 name at local[12]).

REFUTED in the same pass, with a control: built-in 25 does NOT carry the coroutine
entry that a trigger fires, which would have seeded the 389 routines reachable from no
static entry.  Taking each staged operand as a code offset from the phase base, 0 of 8
land on an instruction boundary, against 38.7% for an arbitrary 4-aligned offset --
below chance, not above it.  And the scale is wrong regardless: built-in 25 has only
2 call sites in Stage 02.

So what starts the unreachable routines is still open, and it is not this.  A trigger
node's own layout and its consumer are unread, and built-in 25 stays unnamed.
This commit is contained in:
Sylpheed RE agent
2026-08-27 06:42:47 +00:00
parent 6cbfe0524f
commit 6c9e2ca44d
3 changed files with 99 additions and 1 deletions

View File

@@ -897,7 +897,10 @@ So built-in 100 *clears* the trigger queue and then rebuilds the thread list via
("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.
too. ~~What actually *appends* a node is still unidentified.~~
**(2026-08-27) IDENTIFIED — see [isl-trigger-queue](../isl-trigger-queue.md):
it is `sub_8226A0D8` = ScriptPhase vtable slot 28 = BUILT-IN 25.** The *script*
appends triggers; the engine does not.
## ✅ FOUND: the appender is `sub_8226EAB8`, and the count lives at `inner+8`