Files
Sylpheed/tools/re-capture/grab_tutorial.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

71 lines
3.1 KiB
Bash
Executable File

#!/usr/bin/env bash
# Capture one tutorial's unit definitions: cold-boot Canary, walk
# title -> TUTORIAL -> the Nth entry, wait for the stage to load, snapshot RAM.
#
# One emulator per tutorial on purpose: backing out of a loaded mission via
# PAUSE -> BACK TO MENU wedged the emulator (log stops, CPU spins), while a
# cold boot here is ~15 s. The unit definitions are all parsed at stage load,
# so a single snapshot right after the load is everything this needs.
set -u
N="${1:?usage: grab_tutorial.sh <index 0..5> <outfile>}"
OUT="${2:?}"
export HOME=/sylph-home/re SDL_AUDIODRIVER=dummy DISPLAY=:98
SD="$(cd "$(dirname "$0")" && pwd)"
RC="/home/fabi/RE - Project Sylpheed/sylpheed-reborn/tools/re-capture"
# The container entrypoint's Xvfb/openbox do NOT restart on their own, and a
# dead Xvfb leaves a <defunct> entry that still matches `pgrep` -- so test the
# display with xdpyinfo, never by process name.
ensure_display(){
if ! xdpyinfo -display "$DISPLAY" >/dev/null 2>&1; then
echo "[grab] $DISPLAY is down -> restarting Xvfb + openbox"
setsid nohup Xvfb "$DISPLAY" -screen 0 1280x720x24 -ac -nolisten tcp \
+extension GLX +extension RANDR </dev/null >/tmp/xvfb98.log 2>&1 &
for _ in $(seq 1 50); do xdpyinfo -display "$DISPLAY" >/dev/null 2>&1 && break; sleep 0.2; done
setsid 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; }
}
step(){ vgamepad dpad "$1"; sleep 0.2; vgamepad dpad center; sleep 0.6; }
shot(){ screenshot "$SD/$1" >/dev/null 2>&1; }
# Container PID 1 is `sleep infinity`, which never reaps, so every killed
# emulator stays as a <defunct> entry that `pgrep` still matches. Ask ps for the
# state and ignore anything zombie, or this always thinks one is running.
alive(){ ps -o pid=,stat= -C xenia_canary 2>/dev/null | awk '$2 !~ /^Z/ {print $1}'; }
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
setsid nohup run-canary --apu=sdl --log_mask=13 \
--logged_profile_slot_0_xuid=E0300000EFBEA3D4 </dev/null >/dev/null 2>&1 &
sleep 5
"$RC/skip_intro.sh" 600 || { echo "BOOT FAILED"; exit 1; }
# The main menu is not input-ready for ~10 s after the title tap under lavapipe;
# d-pad presses before that are silently dropped, and the A then lands on NEW
# GAME instead of TUTORIAL. This wait is the whole fix.
sleep 14
shot "nav-$N-menu.png"
step down; step down # NEW GAME -> TUTORIAL
vgamepad tap A 250; sleep 8
shot "nav-$N-list.png"
i=0; while [ "$i" -lt "$N" ]; do step down; i=$((i+1)); done
shot "nav-$N-pick.png"
vgamepad tap A 250
# the stage load takes ~25-45 s under lavapipe; wait for the screen to settle
sleep 50
shot "nav-$N-loaded.png"
MEM=$(ls /dev/shm/xenia_memory_* 2>/dev/null | head -1)
[ -n "$MEM" ] || { echo "NO SHM"; exit 1; }
cp --sparse=always "$MEM" "$SD/$OUT" || exit 1
echo "SNAPSHOT $OUT ($(du -h "$SD/$OUT" | cut -f1))"