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:
@@ -249,6 +249,50 @@ unknown, what evidence exists, and what the first step would be. Move an item in
|
||||
INFERRED from the 210/300/600/1200 gate values, exactly as before. 🟡 Also open:
|
||||
what writes `[phase+88]` — 73 writers in the ISL region alone.
|
||||
|
||||
* ✅🔴 **(2026-08-27) THE UNIT IS SETTLED — `read_freg` RETURNS SECONDS, and the
|
||||
three "flag" built-ins are a STOPWATCH BANK. [structures/isl-timers](structures/isl-timers.md).**
|
||||
Last iteration found what `read_freg` reads and said plainly it had *not*
|
||||
answered the item, which was the unit. Following the writers does.
|
||||
**`[phase+88]`, `[phase+104]`, `[phase+120]` are three parallel 32-entry
|
||||
arrays**, cleared together by the phase initialiser in one unrolled loop
|
||||
(bases 12/44/76/108, offsets 0…127). **`sub_822710D0(phase, dt)` — called from
|
||||
`ScriptPhase::Update` at `0x82263480` with Update's own float passed straight
|
||||
through — does `prev[i] = cur[i]` then `if running[i] == 1: cur[i] += dt`.**
|
||||
So `[phase+104]` is last frame's value and `[phase+120]` the running flag, and
|
||||
the walker's `prev <= t < cur` is "did timer `kind` cross `t` this frame".
|
||||
🔑 **`dt` is SECONDS, by a round trip that is not circular**: the frame loop
|
||||
`sub_821AA1B0` computes `frames × (1/60)` (`0x8289A0F8` = 0.016666668), turns
|
||||
it into integer ticks with `× 10000.0` (`0x820A13B4`), **clamps at 3200**, and
|
||||
`sub_821A49A8` scales back by `1e-4` (`0x8289A0FC`) into the timing singleton
|
||||
at `[0x828F35B4]` — `+8` for the script VM, `+16` for the flight code. Produced
|
||||
as seconds × 10⁴, consumed as × 10⁻⁴; the clamp is **0.32 s**, a frame ceiling.
|
||||
✅ **Refutation test, 675 / 675 vs an 11.2 % control**: if a timer only runs
|
||||
once started, every timeline `kind` must be an index its own phase starts —
|
||||
and every one is. That is also why `kind` is only ever 0 or 5: **every phase
|
||||
opens `set_flag(5); set_flag(0)`.** Artefact `data/isl-timers.txt`; all seven
|
||||
existing artefacts regenerate **byte-identical**.
|
||||
🔴 **Two corrections to `isl-builtins.md`.** `set_flag(i)` writes **`0.0`**,
|
||||
not `1.0` — the constant at `0x8209FD28` is literally zero, the same one the
|
||||
initialiser clears with; and `clear_flag(i)` does **not** zero the value, it
|
||||
clears `[phase+120][i]` only (all 133 sites disc-wide pass **−1** = all 32, in
|
||||
the teardown `reset_phase_threads ; timer_stop ; clear_flag(-1)`). So the
|
||||
family is start / read / stop, and the earlier "latch" reading was a timeout
|
||||
all along. ✅ The corpus's grouping of 8/9/93 is **confirmed** — `[phase+120]`
|
||||
is this family's *running* column, not a different array as last iteration's
|
||||
note allowed.
|
||||
⚠️ **The first run of the test scored 433/675 and looked like a real
|
||||
refutation** (misses all `kind = 0`, in a coherent block of stages). Cause:
|
||||
`isl.dis` defaults to `stop_at_ret=True`, so a `set_flag` at the *start* of a
|
||||
coroutine lost its operand staging to the preceding `ret`. Checked before
|
||||
believing — the corpus's own trap, paid again.
|
||||
🟡 Not settled: the **names** (`set_flag`/`read_freg`/`clear_flag` describe
|
||||
none of this, but 127/123/124 already hold `timer_set`/`timer_resume`/
|
||||
`timer_stop` for a different timer, so renaming is its own change); one
|
||||
exception, `read_freg(15)` in Stage 06 phase 1 has no `set_flag(15)` in that
|
||||
phase; the three scale fields `s24`/`s40`/`s44` (all 1.0 at construction) have
|
||||
no writer searched for — a game-speed setter would be one; and 31 `read_freg`
|
||||
sites index by a computed value rather than an immediate.
|
||||
|
||||
## ✅✅ SOLVED — the mission freeze was a modal sign-in dialog (2026-08-26)
|
||||
|
||||
`XamShowSigninUI` opens a modal dialog and `xeXamDispatchDialog` blocks the
|
||||
|
||||
Reference in New Issue
Block a user