Files
Syplheed-Reborn/tools/re-capture
Claude (auto-RE) 2da9b8a9b8 re: the whole GHAD block is neither stage nor difficulty -- sixteen probe saves
Extends the previous refutation to a sweep. Probed with no effect on STAGE 02 or
Difficulty EASY: every scalar in the GHAD block (+0, +12, +16, +20, +28, +32,
+36 at 1/3/9, +40 u64, +48, +52, +56, +60, +64 raw), SHAB[0].a, and the SHAB
FILL COUNT in both directions -- record 1 filled with a copy of record 0, and
record 0 cleared. The "stage = filled-record count + 1" idea dies with it, and
so does the reading that made SHAB a per-stage result table by that route.

The panel does re-read each slot: slot 02 holds Points 4101 / Clear Ratio 5 %
and displays exactly that while its neighbours show 101 / 6 %.

Left: the phase string, the trailer, or the blob. Recorded caveat -- every save
on disc is genuinely Stage 02 EASY, so "field not found" and "panel does not vary
those two labels per slot" are not yet separated, and another probe round cannot
separate them. The next move is static: find the code that formats STAGE %02d
and read which offset it loads.

savegame_edit.py --set now packs an int into raw_* byte fields.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-11 20:01:26 +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.