This repository has been archived on 2026-09-16. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
Syplheed-Reborn/docs/re/isl-coroutine-spawner.md
Sylpheed RE agent 9ee32f7940 re: decode the trigger node -- and withdraw two of my own claims about it
The reader is sub_8226E220, called by the per-frame drain sub_8226D740 as
(phase+272, six out-params).  It pops one node and copies seven payload fields out.
Built-in 25, the appender, writes exactly those seven offsets:

    +0   local[4]  -- the unit          +24  the constant 1
    +4   local[12]                      +28  local[12] again
    +8   computed                       +32  --
    +16  a DOUBLE from local[16]

Neither side was derived from the other, so the agreement is the check.  Container:
+16 head, +20 pending count -- which matches the count isl-builtins.md watched live at
phase+272+20 from a completely different direction -- and +24 a cursor.

WITHDRAWN, from the previous commit: "the drain spawns from [node+112]".  r31 = r1 -
256, the stack frame, so +112 is an output slot and not a node field.

REFUTED, the follow-up hypothesis that the trigger carries the routine offset and so
names the code nothing else starts: payload+28 is local[12], and across all 25 call
sites disc-wide those values are the small integers 1 through 12 -- 1 of 25 (4.0%)
land on the instruction stream against a 16.0% control, and none are unreached
run-starts.  Below chance.  My first version of that test used n=2, Stage 02 only; it
happened to agree, but two samples could not have supported it either way.

One correction in the other direction, to the corpus: isl-builtins.md withdrew
sub_8226E458's link to the trigger queue on the grounds that "the argument is
lwz r4, 324(r29), the unit array, not the trigger container".  That is the SECOND
argument; the first is r26 = phase + 272, set twelve instructions earlier.  The drain
does operate on the container.  What sub_8226E458 does to it remains unread, so only
the argument is corrected, not the conclusion.

All artefacts regenerate byte-identical; documentation only.

Still open: what local[12] indexes; what the drain actually spawns, since [stack+112]
is filled from payload+28 yet the spawner wants a code offset, so some step in that
chain is not what I read; and what starts the ~15% of unreached code.
2026-08-27 07:30:41 +00:00

2.6 KiB

sub_822737C8 is the coroutine spawner — and its seven callers name the whole start-up path

Asking who calls the thing the timeline calls turns out to enumerate every way an ISL routine can begin.

sub_822737C8(phase, base, offset)add r9, r4, r28 computes base + offset early on, so the third argument is a phase-relative code offset.

The seven call sites

site in what it starts
0x82271030 sub_82270DF8 — the phase initialiser the phase's main entry (the 0x1883 record's third word)
0x822724D0 the built-in stub region start_coroutine's target
0x82274934 sub_822748D0 — the timeline walker a scheduled routine
0x8226D8D0 sub_8226D740 — the per-frame engine→script drain an offset from [node+112]
0x8226DA10 the same drain, second path the same [node+112]
0x82273938 sub_82273910 not read
0x82264080 sub_82264058 not read

The phase's main entry — a correction

isl-stream-entry-points.md called the record's third word a size. It is not: the initialiser hands it to the spawner as an offset.

  • 44 of 44 records land on the instruction stream — 100 %, against a 25.0 % control.
  • All three of Stage 02's targets begin with the same prologue, special[0] = 0 ; local[0] = 0 ; call builtin116(0), which is a routine entry and not a length.

So the record reads 0x1883, base, MAIN_ENTRY, 0, code_end, force_end_handler.

🟡 Seeding it changes nothing measurable — every main entry was already among the CFG's entry points by another route — so this corrects the meaning of a field without moving any coverage number.

🔴 WITHDRAWN: "the drain spawns from [node+112]"

The two calls inside sub_8226D740 both do

lwz  r5, 112(r31)      ; the routine offset, out of the node
lwz  r4, 232(r29)      ; the phase's code base
bl   0x822737C8

r31 = r1 - 256 — it is the stack frame, so +112 is an output slot, not a node field. See structures/isl-trigger-node, which reads the node properly and also refutes the follow-up hypothesis that the trigger carries a routine offset.

🟡 Not settled

  • +112 is a field of some node — this does not show the node comes from the trigger queue at phase+272. That link is exactly the over-reach isl-builtins.md already recorded and withdrew once; it is not asserted here.
  • Two callers unread: sub_82273910 and sub_82264058.
  • Whether the drain's nodes explain the unreached routines is untested. It is a lead, not a result.