re: sub_822737C8 is the coroutine spawner; the record's third word is the MAIN ENTRY

Asking who calls the function the timeline calls enumerates every way an ISL routine
can begin.  sub_822737C8(phase, base, offset) computes base + offset early on, and has
seven real call sites: the phase initialiser sub_82270DF8, the built-in stub region
(start_coroutine), the timeline walker sub_822748D0, TWICE inside sub_8226D740 -- the
per-frame engine->script drain -- and two unread, sub_82273910 and sub_82264058.

CORRECTION to my own write-up: the 0x1883 record's third word is the phase's MAIN
ENTRY, not a "size".  The initialiser hands it straight to the spawner:

    8227101C  or  r5, r22, r22     ; the record's third word
    82271020  or  r4, r26, r26     ; the code base
    82271030  bl  0x822737C8

44 of 44 records land on the instruction stream (100%) against a 25.0% control, and
all three Stage-02 targets open with the identical prologue
`special[0]=0 ; local[0]=0 ; call builtin116(0)` -- a routine entry, not a length.
So the record is 0x1883, base, MAIN_ENTRY, 0, code_end, force_end_handler.

Seeding the main entries moves no coverage number: every one was already among the
CFG's entry points by another route.  This corrects a field's meaning, not the graph.

Lead recorded rather than claimed: both of the drain's spawns take their offset from
[node+112], the first field of a drained node to be located, and the best remaining
angle on the ~15% of code nothing appears to start.  It is NOT shown that those nodes
come from the trigger queue at phase+272 -- that is precisely the over-reach
isl-builtins.md already made and withdrew, so it is not asserted here.

All artefacts regenerate byte-identical; this is documentation only.
This commit is contained in:
Sylpheed RE agent
2026-08-27 07:22:51 +00:00
parent f37df54ed2
commit 62f52a4543
3 changed files with 97 additions and 2 deletions

View File

@@ -80,6 +80,24 @@ unknown, what evidence exists, and what the first step would be. Move an item in
unread. 🟡 **Still NOT what starts the unreachable code** — 0 of the 675 targets
are unreached run-starts, so the ~15 % gap stands.
***(2026-08-27) `sub_822737C8` IS THE COROUTINE SPAWNER — [isl-coroutine-spawner](isl-coroutine-spawner.md).**
`spawn(phase, base, offset)`; **7 call sites** that between them name the whole
start-up path: the phase initialiser, `start_coroutine`'s stub, the timeline
walker, TWICE inside **`sub_8226D740`** (the per-frame engine→script drain), and
two unread (`sub_82273910`, `sub_82264058`).
🔴 **CORRECTION: the `0x1883` record's third word is the phase's MAIN ENTRY, not
a "size"** — my label was wrong. The initialiser passes it straight to the
spawner (`or r5,r22,r22; or r4,r26,r26; bl 0x822737C8`), **44/44 land on the
instruction stream vs a 25.0 % control**, and all three Stage-02 targets share the
prologue `special[0]=0; local[0]=0; call builtin116(0)`. Record =
`0x1883, base, MAIN_ENTRY, 0, code_end, force_end_handler`. 🟡 Seeding it moves
no coverage — every main entry was already an entry point by another route.
🔑 **LEAD:** the drain's two spawns take their offset from **`[node+112]`** —
the first field of a drained node located, and the best remaining angle on the
~15 % of code nothing appears to start. 🟡 NOT shown that those nodes come from
the trigger queue at `phase+272`; that is the exact over-reach the corpus already
withdrew once, so it is not asserted.
## ✅✅ SOLVED — the mission freeze was a modal sign-in dialog (2026-08-26)
`XamShowSigninUI` opens a modal dialog and `xeXamDispatchDialog` blocks the

View File

@@ -0,0 +1,60 @@
# ✅ `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.
## 🔑 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
```
`isl-builtins.md` describes `sub_8226D740` as the per-frame engine→script drain,
and here it is spawning routines from a **code offset carried in the drained
node at `+112`**. That is the first field of a trigger-style node to be located,
and it is the most promising remaining lead on the routines nothing else starts.
## 🟡 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.

View File

@@ -99,8 +99,25 @@ tag `0x19` = int, tag `0x1A` = IEEE float — and `entry_a` is where it starts.
exceeds 0x18 is exactly that phase's `entry_a`. Zero exceptions.** Only two tags
ever appear: 1 394 × `0x19` and 675 × `0x1A`.
So the record is `0x1883, base, size, 0, code_end, force_end_handler` — one
boundary and one entry.
So the record is
```
0x1883, base, MAIN_ENTRY, 0, code_end, force_end_handler
```
🔴 **The third word is NOT a size** — that was my label and it was wrong. The
phase initialiser `sub_82270DF8` passes it straight to the coroutine spawner:
```
8227101C or r5, r22, r22 ; r22 = the record's third word
82271020 or r4, r26, r26 ; r26 = the code base
82271030 bl 0x822737C8 ; spawn(phase, base, word3)
```
Measured: **44 of 44 records land on the instruction stream (100 %) against a
25.0 % control**, and all three of Stage 02's targets open with the identical
prologue `special[0]=0 ; local[0]=0 ; call builtin116(0)` — a routine entry, not
a length.
🟡 The table's contents are **not decoded**. Its int values do land on the
instruction stream more often than chance (46/51 vs 29.5 %), but **0 of them are