re: read_freg counts SECONDS -- the 32 "flags" are a stopwatch bank

The open question was the unit, not the array.  Following the writers of
[phase+88] settles it:

  * sub_822710D0(phase, dt), called from ScriptPhase::Update, does
    prev[i] = cur[i] then, only while [phase+120][i] == 1, cur[i] += dt --
    so +88/+104/+120 are current / previous / running, 32 entries each.
  * dt is seconds by a non-circular round trip: frames * (1/60) * 10000
    -> clamp 3200 -> * 1e-4, in the timing singleton at [0x828F35B4].
    The clamp is 0.32 s, a frame ceiling.
  * 675/675 timeline kinds are indices their own phase starts (control
    11.2 %), which is why kind is only ever 0 or 5.

Corrects isl-builtins.md twice: set_flag writes 0.0 not 1.0, and
clear_flag clears the running flag rather than the value.  Confirms its
grouping of 8/9/93 as one family.  Docs only -- all seven ISL artefacts
regenerate byte-identical.
This commit is contained in:
Sylpheed RE agent
2026-08-27 08:48:49 +00:00
parent 20b8412a38
commit 3cad5d063f
6 changed files with 268 additions and 4 deletions

View File

@@ -143,8 +143,17 @@ inference from the layout; it is now a read.
## 🟡 Not settled
* **This is not what starts the unreachable code.** All 675 targets are already
reachable — **0 are unreached run-starts** — so the ~15 % gap stands.
* **What the six clocks are.** `kind` indexes arrays at `[phase+88]` and
`[phase+104]`; only indices 0 and 5 are ever used by the data, and neither
array's contents were traced to a source.
* ~~**What the six clocks are.**~~ ✅ **SETTLED — [isl-timers](isl-timers.md).**
The two arrays are a bank of **32 stopwatches**: `[phase+88]` is the current
value, `[phase+104]` last frame's, `[phase+120]` a *running* flag, and
`sub_822710D0` — called from `ScriptPhase::Update` — does
`prev[i] = cur[i]; if running[i] then cur[i] += dt` every frame. Built-in 8
starts a timer, 9 reads it, 93 stops it. So the walker's `prev <= t < cur`
test is "did timer `kind` cross `t` this frame", and **`t` is in SECONDS** —
`dt` is `frames * (1/60) * 10000` ticks scaled back by `1e-4`, clamped at
3200 ticks = 0.32 s. That the numbers in the table *looked* like mission times
is no longer the evidence. **675 / 675 timeline entries name a timer their own
phase starts** (control 11.2 %), which is why `kind` is only ever 0 or 5:
every phase opens `set_flag(5); set_flag(0)`.
* **`sub_822737C8`**, which actually starts the routine, is not read — it is
presumably the same spawner `start_coroutine` uses, but that is unchecked.