re: the trailing data table is a per-phase TIMELINE of scheduled routines

Decodes the table found at the end of every phase region.  Layout:

    int  N
    N x [ int offset ; float t ; int kind ]      -- 8-byte typed records,
                                                    tag 0x19 int, 0x1A float

1 + 3N matches the record count in every phase measured (Stage 02: 76/40/55
records for N = 25/13/18).

Checks, all independent of each other:
  schedule entries disc-wide                675
  0x1A float records disc-wide              675   (counted by a different route)
  offsets landing on the instruction stream 675/675 = 100.0%
  control, random 4-aligned offsets                  33.3%

The floats are seconds -- 0, 0.5, 1, 4, 5, 30, 50, 60, 90, 120, 150, 170, 180, 210,
240, 270, 300, 330, 360, 420, 570, 1020, 1080, 1140, 1170 -- and the targets are small
one-shot coroutines that set arguments, call one built-in and end_coroutine.  kind is
0 (556) or 5 (119) and is not identified.

Runtime cross-check, recorded as consistency rather than confirmation: the closed
REMAINING OB work measured Stage 02's squadron arrivals at t = 0, 120 and 210 s over
n=5 emulator runs, and all three appear in phase 1's static schedule, with 120 and 210
each appearing TWICE.  These are round numbers and phase 1 has ~22 distinct times over
0-1170, so presence alone is not unlikely; the doubling is the sharper detail and was
not predicted in advance.

New artefacts data/isl-stage02-schedule.txt and data/isl-schedule-all.txt with a
committed generator (isl_report.py schedule).  calls, phase-ends, conditions and
phase-guards all regenerate byte-identical.

Not settled and said so: kind is unread; the consumer is unread, so the decode rests
on the structural checks above; whether the clock is per-phase or per-mission is an
inference from the layout; and this is NOT what starts the unreachable code -- 0 of
the 675 targets are unreached run-starts, so that ~15% gap stands.
This commit is contained in:
Sylpheed RE agent
2026-08-27 07:07:35 +00:00
parent 02d3c9c82b
commit 2463748a71
6 changed files with 1236 additions and 2 deletions

View File

@@ -52,6 +52,23 @@ unknown, what evidence exists, and what the first step would be. Move an item in
int values hit the stream 46/51 vs 29.5 % chance but **0 are unreached
run-starts**), and what starts the other ~15 % of code is still unknown.
***(2026-08-27) THE TRAILING DATA TABLE IS A TIMELINE — [structures/isl-schedule](structures/isl-schedule.md).**
Layout `int N; N x [int offset; float t; int kind]`; `1 + 3N` matches the record
count in every phase. **675 entries disc-wide — exactly the independently counted
number of `0x1A` float records — and 675/675 offsets land on the instruction
stream vs a 33.3 % control.** The floats are SECONDS (0, 0.5, 1, 4, 30, 60, 90,
120, 150, 180, 210, 240, 300, 420, 1020 …) and the targets are small one-shot
coroutines (`set args; call builtinN; end_coroutine`). `kind` is 0 (556) or 5
(119) — unidentified. 🟡 **Runtime cross-check, consistent not conclusive:** the
closed `REMAINING OB` work measured Stage 02 arrivals at **t = 0, 120, 210 s**
(n=5 emulator runs); all three are in phase 1's static schedule and **120 and 210
each appear TWICE** — but the times are round numbers, so presence alone is weak;
the doubling is the sharper detail. Artefacts `data/isl-stage02-schedule.txt` and
`data/isl-schedule-all.txt`; the four earlier artefacts regenerate byte-identical.
🟡 **Still NOT what starts the unreachable code** — 0 of the 675 targets are
unreached run-starts, so the ~15 % gap stands. The consumer is unread, and whether
the clock is per-phase or per-mission is an inference from layout, not a read.
## ✅✅ SOLVED — the mission freeze was a modal sign-in dialog (2026-08-26)
`XamShowSigninUI` opens a modal dialog and `xeXamDispatchDialog` blocks the

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,68 @@
# Stage02.ssb — phase timelines
Generated by `tools/re-capture/isl_report.py schedule`.
Each phase ends with a table of `(routine offset, time in seconds, kind)`.
56 entries.
## phase 1 — 25 scheduled routines
t=0 kind=5 -> 0x002C04
t=0.5 kind=5 -> 0x002C6C
t=1 kind=5 -> 0x002CE0
t=1 kind=0 -> 0x00747C
t=4 kind=5 -> 0x002D30
t=30 kind=0 -> 0x00323C
t=30 kind=0 -> 0x007754
t=60 kind=0 -> 0x007804
t=90 kind=0 -> 0x003448
t=90 kind=0 -> 0x0078B4
t=120 kind=0 -> 0x003A2C
t=120 kind=0 -> 0x007964
t=170 kind=0 -> 0x003F84
t=170 kind=0 -> 0x007AB4
t=210 kind=0 -> 0x00461C
t=210 kind=0 -> 0x007C04
t=240 kind=0 -> 0x004AF8
t=240 kind=0 -> 0x007D54
t=270 kind=0 -> 0x007EA4
t=300 kind=0 -> 0x007F54
t=330 kind=0 -> 0x0080A4
t=1020 kind=0 -> 0x008154
t=1080 kind=0 -> 0x008204
t=1140 kind=0 -> 0x0082B4
t=1170 kind=0 -> 0x008364
## phase 2 — 13 scheduled routines
t=0 kind=5 -> 0x0183D4
t=0.5 kind=5 -> 0x01843C
t=1 kind=0 -> 0x01F230
t=4 kind=5 -> 0x0184B0
t=30 kind=0 -> 0x0186F8
t=60 kind=0 -> 0x01892C
t=180 kind=0 -> 0x018B78
t=240 kind=0 -> 0x018ED4
t=300 kind=0 -> 0x01F488
t=330 kind=0 -> 0x01F538
t=360 kind=0 -> 0x01F5E8
t=420 kind=0 -> 0x019118
t=570 kind=0 -> 0x01F698
## phase 3 — 18 scheduled routines
t=0 kind=5 -> 0x0289EC
t=0.5 kind=5 -> 0x028A54
t=1 kind=0 -> 0x028EC0
t=1 kind=0 -> 0x02E364
t=4 kind=5 -> 0x028AC8
t=5 kind=5 -> 0x028E30
t=50 kind=0 -> 0x029724
t=120 kind=0 -> 0x0299C8
t=120 kind=0 -> 0x02E63C
t=150 kind=0 -> 0x02A7BC
t=150 kind=0 -> 0x02E78C
t=180 kind=0 -> 0x029D14
t=240 kind=0 -> 0x02E8DC
t=270 kind=0 -> 0x02E98C
t=300 kind=0 -> 0x02A92C
t=300 kind=0 -> 0x02EA3C
t=330 kind=0 -> 0x02EAEC
t=360 kind=0 -> 0x02EB9C

View File

@@ -0,0 +1,76 @@
# ✅ Each phase carries a TIMELINE — 675 scheduled routines across the disc
The trailing data table found at the end of every phase region
([isl-stream-entry-points](../isl-stream-entry-points.md)) is decoded. It is the
mission's **scripted event schedule**.
## Layout
After the phase's code ends — at the first value of that phase's mission-level
`0x1883` record — comes a run of 8-byte typed records, tag `0x19` = int,
`0x1A` = IEEE float:
```
int N -- entry count
N x [ int offset ; float t ; int kind ]
```
`1 + 3N` matches the record count in **every** phase measured: Stage 02's three
phases hold 76, 40 and 55 records for N = 25, 13 and 18.
## ✅ The checks
| | |
|---|---|
| schedule entries disc-wide | **675** |
| `0x1A` float records disc-wide | **675** — the same number, independently counted |
| offsets landing on the instruction stream | **675 / 675 = 100.0 %** |
| control: random 4-aligned offsets | 33.3 % |
The float count and the entry count are derived by different routes and agree
exactly, and every single offset resolves. `kind` is **0** (556) or **5** (119).
## ✅ The floats are seconds
The distribution is unmistakable: 0, 0.5, 1, 4, 5, 30, 50, 60, 90, 120, 150,
170, 180, 210, 240, 270, 300, 330, 360, 420, 570, 1020, 1080, 1140, 1170 …
mission times, not fractions.
And the targets are what a schedule would point at — small one-shot coroutines:
```
002C04: set.i local[0] = 1
002C1C: set.i local[4] = 1
002C34: set.f local[8] = 0.4
002C50: call builtin106(0x1, 0x1, 0.4)
002C5C: call end_coroutine
```
## 🟡 A runtime cross-check — consistent, and not proof
The closed `REMAINING OB` work measured, on the emulator over n=5 runs, that
Stage 02's squadrons arrive at **t = 0, 120 and 210 s**. All three times are in
phase 1's static schedule, and **120 and 210 each appear twice**, which is what
two squadrons arriving together would look like.
⚠️ Stated as consistency rather than confirmation: these are round numbers, and
phase 1 has ~22 distinct times spread over 01170, so three specified round
values all being present is not by itself unlikely. The **doubling** is the
sharper detail, and it was not predicted in advance.
## Artefacts
`data/isl-stage02-schedule.txt` and `data/isl-schedule-all.txt` (all 28 stages,
675 entries), generator `isl_report.py schedule`. The four earlier artefacts
regenerate byte-identical.
## 🟡 Not settled
* **`kind` (0 or 5) is not identified.** Two behaviours, no reading.
* **This is not what starts the unreachable code.** All 675 targets are already
reachable — **0 are unreached run-starts** — so the ~15 % gap stands.
* **Whether the schedule is per-phase-clock or mission-clock** is not
established; each phase's table restarts at t=0, which suggests per-phase, but
that is an inference from the layout, not a read of the consumer.
* **The consumer is unread.** Nothing here shows the engine walking this table;
the decode rests on the structural checks above.

View File

@@ -495,6 +495,47 @@ def conditions(b, sym1=None, sym2=None):
return out
def schedule(b):
"""Each phase's trailing TIMELINE table: (phase, routine_offset, time_s, kind).
Layout, after the phase's code ends (the `0x1883` record's first value):
int N -- entry count
N x [ int offset ; float t ; int kind ] -- 8-byte typed records,
tag 0x19 int, 0x1A float
`1 + 3N` matches the record count in every phase measured. Disc-wide there
are 675 entries -- exactly the number of `0x1A` float records, which is the
consistency check -- and **675 of 675 offsets land on the instruction
stream** against a 33.3 % chance rate.
The floats are SECONDS: 0, 0.5, 1, 4, 30, 60, 90, 120, 150, 180, 240, 300,
420 ... The `kind` field is 0 (556) or 5 (119).
"""
end = struct.unpack_from('>I', b, 0x0C)[0]
bases = phase_bases(b)
limits = list(bases[1:]) + [end]
out = []
for ph, (base, hi) in enumerate(zip(bases, limits), 1):
o = base
while o + 4 <= hi and (struct.unpack_from('>I', b, o)[0] & 0xFF) <= 0x18:
ln = (struct.unpack_from('>I', b, o)[0] >> 8) & 0xFF
if ln == 0 or ln % 2: break
o += ln
if o + 8 > hi: continue
n = struct.unpack_from('>I', b, o + 4)[0]
o += 8
for _ in range(n):
if o + 24 > hi: break
a = struct.unpack_from('>I', b, o + 4)[0]
t = struct.unpack('>f', struct.pack(
'>I', struct.unpack_from('>I', b, o + 12)[0]))[0]
k = struct.unpack_from('>I', b, o + 20)[0]
out.append((ph, base + a, t, k))
o += 24
return out
def call_sites(b):
"""Every `call` in the code region. Scans on the encoding, not by decoding,
so a bad length somewhere cannot hide the rest of the file."""

View File

@@ -12,6 +12,7 @@ generator in the tree is the point of this file.
isl_report.py <StageNN.ssb> conditions -> every condition site, comparand resolved
isl_report.py <StageNN.ssb> phase-guards -> the NECESSARY conditions for each exit
isl_report.py <dir> phase-guards -> the same for every Stage*.ssb it holds
isl_report.py <StageNN.ssb> schedule -> the phase timeline tables
The "needs the coroutine entry points" blocker recorded here is REFUTED: the
instruction stream is FLAT and `isl.linear_offsets` reaches 25705/25705 call
@@ -169,6 +170,23 @@ def emit_phase_guards(b, path):
print(' %s0x%06X %s %s %s' % (tag, c['off'], lhs, c['rel'], rhs))
def emit_schedule(b, path):
"""The per-phase timeline: what the script launches, and when."""
sch = isl.schedule(b)
print('# %s — phase timelines' % path)
print()
print('Generated by `tools/re-capture/isl_report.py schedule`.')
print()
print('Each phase ends with a table of `(routine offset, time in seconds, kind)`.')
print('%d entries.' % len(sch))
for ph in sorted({p for p, _o, _t, _k in sch}):
rows = [r for r in sch if r[0] == ph]
print()
print('## phase %d%d scheduled routines' % (ph, len(rows)))
for _p, off, t, k in sorted(rows, key=lambda r: (r[2], r[1])):
print(' t=%-8g kind=%d -> 0x%06X' % (t, k, off))
def main():
# The dominator pass over a large stage is memory-hungry and once OOM-KILLED
# a run on this 15 GB box. Cap the address space so a bad input fails this
@@ -186,14 +204,16 @@ def main():
if i: print(); print('-' * 72); print()
{'calls': emit_calls, 'phase-ends': emit_phase_ends,
'conditions': emit_conditions,
'phase-guards': emit_phase_guards}[sys.argv[2]](
'phase-guards': emit_phase_guards,
'schedule': emit_schedule}[sys.argv[2]](
isl.load(f), os.path.basename(f))
return
b = isl.load(path)
name = path.replace('\\', '/').split('/')[-1]
{'calls': emit_calls, 'phase-ends': emit_phase_ends,
'conditions': emit_conditions,
'phase-guards': emit_phase_guards}[sys.argv[2]](b, name)
'phase-guards': emit_phase_guards,
'schedule': emit_schedule}[sys.argv[2]](b, name)
if __name__ == '__main__':