Files
Syplheed-Reborn/tools/re-capture
claude-re 402985adbf pilot: escort-weighted targeting (DEFEND), plus the capital-ship keep-out it needed
While the asset is losing hull, target what is pressing IT — ranked by distance
to the asset minus credit for closing on it — instead of what is nearest to us.
Trigger and ranking both read the live hull (pos+0x154), so nothing is inferred.
DEFEND engaged 1.9 s after the asset's first hit and held 54% of a 330 s run.

It did NOT measurably save the asset: over the window two runs share, the
policies are equal to within noise (t=239: 23218 vs 23038). Two reasons, both
recorded rather than papered over: the runs are not comparable past that window
(spawn timing differs and the hostile count GREW 134->166 in one, fell 147->118
in the other), and the real bottleneck is lethality — the guns are on for 12% of
combat frames because the target is outside the 9 deg cone the rest of the time.

Also corrects a single-run claim in the previous commit: the asset is NOT
reliably safe for the first ~170 s. A second run had first damage at t=70 s. The
stage does not replay identically; only 'the loss is slow' survives.

Fixes a fatal bug the new mode exposed: DEFEND flies at the asset, which sits
inside the friendly formation, and the first escort run went hull 1500 -> DEAD in
one tick at 2026 units/s, 0.6 s from a friendly destroyer that avoidance thought
it would clear by 365 units — the ship's radius is 2000. Keep-out applied only to
hostile turrets. Every entity above BIG_RADIUS now gets its own radius + 800 of
physical keep-out with braking inside it, whatever its faction.
2026-07-30 17:49:38 +00:00
..

Runtime-capture harness (sylph-re container)

Screenshot-driven scripts for reading the running retail game's menus under Xenia Canary + lavapipe, headless. They assume the container helpers screenshot, vgamepad, pad are on $PATH and HOME=/sylph-home/re.

Script What it does
skip_intro.sh Boot → main menu, unattended. Taps A only while the intro movie is actually playing (frame-to-frame RMSE), then once at the PRESS Ⓐ BUTTON title. Static logo screens are left alone, so a stray tap can never land on NEW GAME.
wait_title.sh Older variant: wait for the title (green Ⓐ glyph at px 625,618) and tap A. Superseded by skip_intro.sh.
step.sh One Arsenal navigation step (down/up/next/prev/none) + a compact capture: weapon list stacked over the DATA SHEET.
sweep.sh Walk a whole weapon-type list, capturing only rows that show a DATA SHEET — locked rows (a "Conditions to Develop" panel) are detected by the brightness of the Range Class label box and skipped.
type.sh Change weapon-type tab N times (RB) and report the header strip.
hp.sh / cyc.sh Hangar hard-point carousel: cyc.sh steps it (d-pad down, not left/right) and captures the Name + DATA SHEET.

Input timing under lavapipe: the game polls input at its own low frame rate, so a 60 ms d-pad tap is dropped roughly half the time. 200 ms is reliable; 300 ms starts to auto-repeat (two rows per press).

Findings produced with these: docs/re/weapon-datasheet-runtime.md.

Guest-memory tools (no screenshots)

Script What it does
gmem.py Read the live guest address space out of /dev/shm/xenia_memory_* (Xenia's backing file), addressed by guest VA. find / read / words.
weapon_runtime.py Solve the Weapon/Shell struct layouts against the disc records and read the fields the disc defaults.
unit_discover.py Find which runtime class carries a set of ID strings, assuming no vtable: tallies the word at pointer_site - k across distinct IDs.
unit_runtime.py Same solver for the unit\UN_*.tbl definition objects (vtable 0x820af844). Unions several snapshots — unit definitions are per-stage.
schema_order.py Merge a sub-record's field-declaration order across all tables (topological sort); the layout check that pins fields no table ever values.
order_check.py Test offset = base + 4*index for one table's sub-record against solver output.
grab_tutorial.sh Cold-boot Canary, walk to the Nth TUTORIAL entry, wait for the stage load, snapshot guest RAM. One emulator per capture — backing out of a loaded mission wedges it.

Snapshot first — cp --sparse=always /dev/shm/xenia_memory_* snap.bin (~2 s) — and point $GMEM_FILE at the copy; the running emulator pegs every core under lavapipe.