This repository has been archived on 2026-09-16. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
Syplheed-Reborn/tools/re-capture/ssb_watch.py
Sylpheed RE agent 121004ef3c re: the mission script is resident immediately -- two explanations refuted
ssb_watch.py polls the .ssb header, a symbol string and find_mission from the
moment flight is detected. On a normal run all three are present at the FIRST
sample (t=0.0, mission 0xBC79C960), so 'the script loads later than assumed' and
'the probe raced a load' are both out -- there is no window in which a healthy
mission flies without its script in memory.

A detail worth more than it looks: at that sample screen_id reported 'other',
not 'flight'. The script is loaded and the ScriptMission locatable BEFORE the
flight HUD appears, so residency is not gated on the HUD, and a run showing the
HUD without the script is in a state a healthy run never passes through.

That leaves the third candidate: the anomalous run's mission never loaded and
its IN FLIGHT was a misdetection -- consistent with it being frozen on a black
screen when checked afterwards. Not proven, but now the only surviving
explanation rather than one of three.
2026-08-25 19:16:13 +00:00

64 lines
2.2 KiB
Python

#!/usr/bin/env python3
"""When does the mission script become resident in guest memory?
One run reached `IN FLIGHT` with the `.ssb` header ABSENT from guest memory and
`find_mission` returning NOTFOUND, while the manifest string `Stage02.ssb` was
present (script-runtime-probe.md). Three explanations were possible: the script
loads later than assumed, the probe raced a load, or that run never really
entered the mission.
Sampling once cannot separate them. This polls from the moment flight is
detected and records WHEN each marker appears:
header the .ssb's 20-byte header -> the script image itself
ADN110 a symbol-table string -> its symbol table
mission find_mission() succeeding -> the live ScriptMission
Usage: ssb_watch.py [secs] [every_s]
"""
import os
import sys
import time
sys.path.insert(0, __file__.rsplit('/', 1)[0])
import gmem
import isl
import squadron_state as S
def main():
ssb = isl.load('/tmp/Stage02.ssb')
hdr = ssb[:20]
secs = float(sys.argv[1]) if len(sys.argv) > 1 else 300
every = float(sys.argv[2]) if len(sys.argv) > 2 else 10
path = gmem.mem_path()
size = os.path.getsize(path)
t0 = time.time()
seen = {}
with open(path, 'rb', buffering=0) as f:
while time.time() - t0 < secs:
t = time.time() - t0
marks = {}
marks['header'] = len(S._find(f, size, hdr))
marks['ADN110'] = len(S._find(f, size, b'ADN110'))
m, _fb = (None, None)
if marks['header']:
m, _fb = S.find_mission(f, size, ssb)
marks['mission'] = 1 if m else 0
for k, v in marks.items():
if v and k not in seen:
seen[k] = t
print(' [%6.1fs] %-8s FIRST SEEN (%s)' % (t, k, v), flush=True)
print(' [%6.1fs] header=%d ADN110=%d mission=%s' % (
t, marks['header'], marks['ADN110'],
('0x%08X' % m) if m else 'no'), flush=True)
if len(seen) == 3:
print('all three resident at %.1fs' % t, flush=True)
return 0
time.sleep(every)
print('timed out; seen=%s' % seen, flush=True)
return 1
if __name__ == '__main__':
sys.exit(main())