Container PID 1 is `sleep infinity` and never reaps, so every emulator this script kills stays as a <defunct> entry that `pgrep -x` still matches -- after a few captures the script always believed one was running. Same trap as the Xvfb check. Ask ps for the process state and skip anything in Z.
71 lines
3.1 KiB
Bash
Executable File
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 --audio --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))"
|