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/find_partslot.sh
Sylpheed RE agent 01580d294e tools: two dead flags that made every emulator boot script fail silently
Trying to read a third paint order off the running game turned up two bugs in
the capture harness, both of which fail in ways that look like the game
misbehaving rather than the script being wrong.

1. `--audio` is not a cvar in this tree, and eight boot scripts passed it.
   Xenia calls ShowSimpleMessageBox from ParseLaunchArguments, BEFORE logging is
   initialised, so the symptom is a 10x10 window, no log, no guest memory and a
   dialog that blocks on XIfEvent forever - i.e. a hang deep in the emulator.
   run-canary`s own header documents this exact trap; the scripts predate it.
   Removed from all eight.

2. `vgamepad` no longer exists - the uinput pad was replaced by the --hid=file
   driver and pad.py - but skip_intro.sh still called it. The script runs
   without `set -e`, so the call failed silently and the title branch pressed
   nothing while still exiting 0. A caller was told "TITLE -> A" with the game
   sitting on the title screen. It now presses through pad.py and exits 6 if
   that fails.

The first bug is fixed and verified: the boot now reaches the title screen with
PRESS (A) BUTTON. The second is fixed but does NOT unblock the title - see the
next commit.
2026-08-19 07:48:16 +00:00

70 lines
2.9 KiB
Bash
Executable File

#!/usr/bin/env bash
# Locate the GamePart "slot" in guest memory by DIFFERENTIAL SEARCH.
#
# sub_821749C0 creates a part from slot+12 (the requested part id) and stores the
# result at *(slot+16). The id is computed from a menu selection -- no literal 26
# exists anywhere -- so it cannot be found statically. But the id is KNOWN at each
# screen from the GamePart table (docs/re/challenge-mission-gate.md section 3):
#
# GP_EXTRAS = 5 GP_MISSION_SELECT = 7
#
# so the slot is simply the word that reads 5 on the EXTRAS screen and 7 on the
# MISSION SELECT screen. Snapshot both, intersect, and the candidates are few.
#
# Usage: find_partslot.sh [boot_timeout_s]
set -u
export HOME=/sylph-home/re DISPLAY=:99 SDL_AUDIODRIVER=dummy
export XENIA_PAD_FILE=/tmp/xenia_pad.txt
HERE="$(cd "$(dirname "$0")" && pwd)"
pad() { python3 "$HERE/pad.py" "$@"; }
poke() { python3 "$HERE/gpoke.py" "$@"; }
BOOT_TIMEOUT="${1:-400}"
say() { echo "[$(date +%H:%M:%S)] $*"; }
px() { convert /tmp/nav-probe.png -format \
"%[fx:int(255*p{$1}.r)] %[fx:int(255*p{$1}.g)] %[fx:int(255*p{$1}.b)]" info: 2>/dev/null; }
at_menu() {
screenshot /tmp/nav-probe.png >/dev/null 2>&1 || return 1
read -r r g b < <(px "648,221"); [ -n "${r:-}" ] || return 1
[ "$r" -gt 230 ] && [ "$g" -gt 230 ] && [ "$b" -gt 230 ] || return 1
read -r r2 g2 b2 < <(px "560,300"); [ -n "${r2:-}" ] || return 1
[ "$r2" -lt 120 ] && [ "$b2" -gt "$r2" ]
}
at_title() {
screenshot /tmp/nav-probe.png >/dev/null 2>&1 || return 1
read -r r g b < <(px "625,618"); [ -n "${g:-}" ] || return 1
[ "$g" -gt 130 ] && [ $((g - r)) -gt 45 ] && [ $((g - b)) -gt 45 ]
}
snap() { SHM=$(ls /dev/shm/xenia_memory_* 2>/dev/null | head -1); cp --sparse=always "$SHM" "$1"; }
pkill -9 -x xenia_canary 2>/dev/null; sleep 1
rm -f /dev/shm/xenia_* 2>/dev/null; : > "$XENIA_PAD_FILE"
say "launching"
run-canary --apu=sdl --log_mask=13 \
--logged_profile_slot_0_xuid=E0300000EFBEA3D4 \
--hid=file --pad_file="$XENIA_PAD_FILE" &
xsetroot -solid black 2>/dev/null || true
MENU=0
for i in $(seq 1 "$BOOT_TIMEOUT"); do
[ "$i" -lt 40 ] && { sleep 1; continue; }
if at_menu && sleep 1 && at_menu; then say "MAIN MENU after ${i}s"; MENU=1; break; fi
at_title && { say " title — tapping A"; pad tap A 0.25; sleep 2; }
sleep 1
done
[ "$MENU" = 1 ] || { say "TIMEOUT"; exit 1; }
say "-> EXTRAS (GamePart 5)"
for _ in 1 2 3 4; do pad dpad down 0.06; sleep 0.35; done
sleep 0.5; pad tap A 0.15; sleep 4
screenshot "$HOME/shots/slot-01-extras.png" >/dev/null
snap /sylph-home/re/snap-extras.bin; say "snapshot A (EXTRAS) taken"
say "-> MISSION SELECT (GamePart 7)"
pad tap A 0.15; sleep 5
screenshot "$HOME/shots/slot-02-missionselect.png" >/dev/null
snap /sylph-home/re/snap-msel.bin; say "snapshot B (MISSION SELECT) taken"
say "intersecting: word == 5 in A and == 7 in B"
python3 "$HERE/diff_words.py" /sylph-home/re/snap-extras.bin 5 /sylph-home/re/snap-msel.bin 7
say "done — emulator left running"