#!/usr/bin/env bash # Play one TUTORIAL and photograph what it teaches. # # The OPTIONS key-config screen names the in-flight actions but not the buttons # they sit on, and probing the pad found the weapons only (an action that does # not fire a gun is invisible in the ammo counters). The tutorials state the # mapping outright — `ADVANCED CONTROLS` is index 5 and is where Change Target # and Padlock Mode live — so read it from the game instead of guessing. # # Boot + nav is launch_mission.sh's route as far as the main menu, then TUTORIAL # instead of LOAD GAME. Everything stays a CHILD of this script (no setsid): a # detached process is not a survivable one here, see the session-lifetime note. set -u N="${1:-5}" # 0 BASIC, 1 HUD, 2 RADAR, 3 SUPPLY, 4 RADIO, 5 ADVANCED SECS="${2:-150}" TAG="${3:-tut}" export HOME=/sylph-home/re SDL_AUDIODRIVER=dummy DISPLAY=:98 SD="$(cd "$(dirname "$0")" && pwd)" SHOTS=/sylph-home/re/shots alive(){ ps -o pid=,stat= -C xenia_canary 2>/dev/null | awk '$2 !~ /^Z/ {print $1}'; } step(){ vgamepad dpad "$1"; sleep 0.25; vgamepad dpad center; sleep 0.7; } shot(){ screenshot "$SHOTS/$TAG-$1.png" >/dev/null 2>&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 if ! xdpyinfo -display "$DISPLAY" >/dev/null 2>&1; then rm -f "/tmp/.X${DISPLAY#:}-lock" 2>/dev/null || true nohup Xvfb "$DISPLAY" -screen 0 1280x720x24 -ac -nolisten tcp \ +extension GLX +extension RANDR /tmp/xvfb98.log 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 /tmp/openbox98.log 2>&1 & sleep 1 fi cd /sylph-home/re nohup run-canary --audio --apu=sdl --log_mask=13 \ --logged_profile_slot_0_xuid=E0300000EFBEA3D4 /dev/null 2>&1 & sleep 5 "$SD/skip_intro.sh" 600 || { echo "BOOT FAILED (skip_intro exit $?)"; exit 1; } sleep 14 # main menu is not input-ready before this step down; step down # NEW GAME -> LOAD GAME -> TUTORIAL vgamepad tap A 250; sleep 8 shot "list" i=0; while [ "$i" -lt "$N" ]; do step down; i=$((i+1)); done shot "pick" vgamepad tap A 250; sleep 6 shot "sub" # some tutorials offer Level 1 / Level 2 vgamepad tap A 250 # Then just watch. The lesson drives itself and prints its instructions; tap A # periodically to advance any prompt, and photograph often enough to catch the # caption before it is replaced. end=$(( SECONDS + SECS )); n=0 while [ $SECONDS -lt $end ]; do n=$((n+1)); shot "$(printf '%02d' $n)" [ -n "$(alive)" ] || { echo "EMULATOR GONE at ${SECONDS}s"; exit 4; } sleep 5 [ $((n % 3)) -eq 0 ] && vgamepad tap A 250 done echo "TUTORIAL CAPTURE DONE ($n frames)"