re: a second save names Points, flight time and clear ratio — and shows the payload is pure state
Made a second save in-game (READY ROOM -> SYSTEM -> SAVE GAME -> empty slot) so the format had a differential to read against. nav_probe.sh drives it: boot to the READY ROOM, walk a scripted step list, screenshot after every step and stamp every save file's md5, so the trail says which keypress wrote a save. That stamp is what caught the first attempt failing -- the save confirm starts on YES, unlike the load confirm which starts on NO, so the load flow's extra up-press selected NO and wrote nothing. Result 1: saving the same loaded state into a new slot produces a BYTE-IDENTICAL 545-byte payload. Only the GDHA header moves, and every byte that moves is either the container FILETIME or one of the guest-pointer words -- which empirically confirms those words are uninitialised padding rather than data. So the payload holds no timestamp, no slot number and no name; a save's identity is entirely in its content header. Result 2: the LOAD/SAVE screen's Details panel prints Points 4101 P, Flight Time 000:05:24 and Clear Ratio 5 % for exactly this state, which names GHAD +24 (Points), +4 (flight time in ms -- 324773 ms = 5m24.773s) and +8 (clear ratio %). Difficulty EASY and STAGE 02 both being 2, and three fields holding 2, is left undecided on purpose: one save cannot separate them. Result 3: the 16 SHAB records are not the UI's save slots. The UI has 20, slots are separate gameNN files, and record 0's FILETIME stayed at 2026-07-23 in a save written on 2026-08-11 -- so the table is part of the game state, most likely a per-stage result record (one stage finished, one record filled), which the next cleared stage will falsify or confirm. The original save was backed up first and is untouched; the new save went to an empty slot.
This commit is contained in:
68
tools/re-capture/nav_probe.sh
Executable file
68
tools/re-capture/nav_probe.sh
Executable file
@@ -0,0 +1,68 @@
|
||||
#!/usr/bin/env bash
|
||||
# Boot to the READY ROOM and walk a scripted d-pad sequence, screenshotting after
|
||||
# every step and stamping the save file's md5+mtime alongside — so the trail says
|
||||
# not just what was on screen but exactly which keypress wrote a save.
|
||||
#
|
||||
# Boot half is launch_mission.sh's verified route, stopped at the READY ROOM.
|
||||
# Run as ONE BLOCKING FOREGROUND call (see docs/re/session-lifetime notes).
|
||||
#
|
||||
# Usage: nav_probe.sh <tag> <step> [<step>...]
|
||||
# step = "d"/"u"/"l"/"r" (d-pad), "A"/"B"/"X"/"Y" (button), "wN" (wait N s)
|
||||
set -u
|
||||
export HOME=/sylph-home/re SDL_AUDIODRIVER=dummy DISPLAY=:98
|
||||
SD="$(cd "$(dirname "$0")" && pwd)"
|
||||
SHOTS=/sylph-home/re/shots
|
||||
SAVE=/sylph-home/re/.local/share/Xenia/content/E0300000EFBEA3D4/535107D4/00000001/game01/savedata
|
||||
TAG="${1:?tag}"; shift
|
||||
OUT="/sylph-home/re/$TAG"; mkdir -p "$OUT" "$SHOTS"
|
||||
|
||||
alive(){ ps -o pid=,stat= -C xenia_canary 2>/dev/null | awk '$2 !~ /^Z/ {print $1}'; }
|
||||
ensure_display(){
|
||||
if ! xdpyinfo -display "$DISPLAY" >/dev/null 2>&1; then
|
||||
rm -f "/tmp/.X${DISPLAY#:}-lock" 2>/dev/null || true
|
||||
nohup bash -c 'Xvfb "$0" -screen 0 1280x720x24 -ac -nolisten tcp \
|
||||
+extension GLX +extension RANDR >/tmp/xvfb98.log 2>&1' "$DISPLAY" </dev/null >/dev/null 2>&1 &
|
||||
for _ in $(seq 1 50); do xdpyinfo -display "$DISPLAY" >/dev/null 2>&1 && break; sleep 0.2; done
|
||||
nohup env DISPLAY="$DISPLAY" HOME=/sylph-home openbox </dev/null >/tmp/openbox98.log 2>&1 &
|
||||
sleep 1
|
||||
fi
|
||||
xdpyinfo -display "$DISPLAY" >/dev/null 2>&1 || { echo "DISPLAY UNAVAILABLE"; exit 1; }
|
||||
}
|
||||
CDIR=/sylph-home/re/.local/share/Xenia/content/E0300000EFBEA3D4/535107D4/00000001
|
||||
stamp(){ printf '%-14s %s\n' "$1" \
|
||||
"$(find "$CDIR" -name savedata -printf '%f ' -exec md5sum {} \; 2>/dev/null \
|
||||
| awk '{printf "%s=%s ", $3, substr($2,1,8)}' | sed 's#.*/00000001/##g')"; }
|
||||
step(){ vgamepad dpad "$1"; sleep 0.25; vgamepad dpad center; sleep 0.7; }
|
||||
|
||||
pkill -x xenia_canary 2>/dev/null; sleep 2
|
||||
[ -n "$(alive)" ] && { kill -9 $(alive) 2>/dev/null; sleep 2; }
|
||||
rm -f /dev/shm/xenia_memory_* /dev/shm/xenia_code_cache_* 2>/dev/null
|
||||
ensure_display
|
||||
cd /sylph-home/re
|
||||
nohup run-canary --audio --apu=sdl --log_mask=13 \
|
||||
--logged_profile_slot_0_xuid=E0300000EFBEA3D4 </dev/null >/dev/null 2>&1 &
|
||||
sleep 5
|
||||
"$SD/skip_intro.sh" 600 || { echo "BOOT FAILED (skip_intro exit $?)"; exit 1; }
|
||||
sleep 14
|
||||
step down # NEW GAME -> LOAD GAME
|
||||
vgamepad tap A 250; sleep 8
|
||||
vgamepad tap A 250; sleep 4 # "Load game?" -- cursor starts on NO
|
||||
step up
|
||||
vgamepad tap A 250
|
||||
sleep 28
|
||||
screenshot "$SHOTS/$TAG-00-readyroom.png" >/dev/null 2>&1
|
||||
stamp "boot"
|
||||
|
||||
i=0
|
||||
for s in "$@"; do
|
||||
i=$((i+1))
|
||||
case "$s" in
|
||||
d) step down ;; u) step up ;; l) step left ;; r) step right ;;
|
||||
A|B|X|Y) vgamepad tap "$s" 250; sleep 2 ;;
|
||||
w*) sleep "${s#w}" ;;
|
||||
*) echo "unknown step $s"; continue ;;
|
||||
esac
|
||||
screenshot "$(printf '%s/%s-%02d-%s.png' "$SHOTS" "$TAG" "$i" "$s")" >/dev/null 2>&1
|
||||
stamp "$i:$s"
|
||||
done
|
||||
echo "NAV PROBE DONE ($TAG, $i steps)"
|
||||
Reference in New Issue
Block a user