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

@@ -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."""