re: +36/+52/+56 are neither stage nor difficulty -- refuted with eleven probe saves
Those three fields all hold 2, and "difficulty or stage, undecidable from one save" has been the reading since the format was parsed. Writing saves makes it decidable and the answer is neither. boot_menu.sh boots to the title menu WITHOUT loading anything, and LOAD GAME's slot list renders each slot's Details panel from that slot's payload. Extra slots can be fabricated (copy the directory plus a gameNN.header with its UTF-16BE display string and ASCII name patched), so four probes fit in one boot, read-only. Probed: +36 at 1/3/9, +52 and +56 at 1/9, and +0, +16, +32, +48, +28, SHAB[0].a. Every one left the panel at STAGE 02 / EASY / At Standby / Times Cleared 0. The negative is meaningful because the panel does read each payload -- slot 02 shows 5% clear ratio against the others' 6%, and Points tracked +24 exactly. Two controls: patching a slot header to "STAGE09 HARD" changed nothing (the display is payload-driven, not header text), and the row date follows the container FILETIME. Remaining candidates: +12, +20, +40 (u64), +60, +64, or the phase string. Also here: savegame_edit.py --slot for SHAB records, and boot_menu.sh itself -- nav_probe.sh's boot loads a save, which with probe slots on disc loads a probe, and a dropped d-pad step there put A on TAKE OFF and spent a boot loading a mission. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
46
tools/re-capture/boot_menu.sh
Executable file
46
tools/re-capture/boot_menu.sh
Executable file
@@ -0,0 +1,46 @@
|
||||
#!/usr/bin/env bash
|
||||
# Boot to the TITLE MENU and stop there — no save is loaded.
|
||||
#
|
||||
# nav_probe.sh's boot half deliberately loads a save, which is wrong for any
|
||||
# experiment that wants to *inspect* save slots rather than enter one: with
|
||||
# several probe saves on disc the load picks one of them, and a probe value the
|
||||
# game cannot make sense of turns into a long "NOW PROCESSING" (or a mission
|
||||
# load, if a d-pad step is dropped and A lands on TAKE OFF).
|
||||
#
|
||||
# From the main menu, LOAD GAME is one d-pad step away and its slot list renders
|
||||
# every slot's Details panel — STAGE, Game Status, Points, Times Cleared — which
|
||||
# is read straight out of each save's payload. That makes this the cheap harness
|
||||
# for save-field probes: write N slots, boot once, arrow through them.
|
||||
#
|
||||
# Run as ONE BLOCKING FOREGROUND call. Usage: boot_menu.sh [tag]
|
||||
set -u
|
||||
export HOME=/sylph-home/re SDL_AUDIODRIVER=dummy DISPLAY=:98
|
||||
SD="$(cd "$(dirname "$0")" && pwd)"
|
||||
SHOTS=/sylph-home/re/shots
|
||||
TAG="${1:-menu}"
|
||||
mkdir -p "$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; }
|
||||
}
|
||||
|
||||
[ -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
|
||||
screenshot "$SHOTS/$TAG-menu.png" >/dev/null 2>&1
|
||||
echo "AT MAIN MENU (cursor on NEW GAME); LOAD GAME is one d-pad step down"
|
||||
@@ -78,6 +78,13 @@ def main():
|
||||
elif a == "--set":
|
||||
k, v = args[i + 1].split("=")
|
||||
parsed["ghad"][k] = int(v, 0)
|
||||
elif a == "--slot":
|
||||
# --slot <record>,<field>=<value>, e.g. --slot 0,0=3
|
||||
where, v = args[i + 1].split("=")
|
||||
rec, fld = (int(x) for x in where.split(","))
|
||||
row = list(parsed["slots"][rec])
|
||||
row[fld] = int(v, 0)
|
||||
parsed["slots"][rec] = tuple(row)
|
||||
parsed["ghad"]["blob_68"] = bytes(blob)
|
||||
|
||||
out = wrap(header, sg.serialize(parsed))
|
||||
|
||||
Reference in New Issue
Block a user