#!/usr/bin/env bash # Drive the boot sequence to the main menu without a human in the loop. # - movie playing (two grabs 0.6s apart differ a lot) -> tap A to skip # - static screen -> if the green "PRESS (A) BUTTON" glyph is there, tap A and stop # Static logo screens are left alone, so a stray tap can never land on NEW GAME. # # LIVENESS IS CHECKED EVERY ITERATION, and that is not a nicety. When the # display died 3 minutes into a run, `screenshot` started failing silently and # left /tmp/f1.png and /tmp/f2.png at their last contents — two *stale* files, # which compare to a constant non-zero RMSE, which reads exactly like "the # screen is changing a lot". So the loop reported "movie -> skip A" every 5 s # for the full 600 s timeout with no emulator and no X server running. A dead # display and a playing movie must never be able to look the same. set -u export HOME=/sylph-home/re DISP="${DISPLAY:-:98}" alive(){ ps -o pid=,stat= -C xenia_canary 2>/dev/null | awk '$2 !~ /^Z/ {print $1}'; } # The X root keeps the DEAD session's last frame, so a fresh launch would be # detected as "already at the title". Blank it, and wait for the new window. xsetroot -solid black 2>/dev/null || true until xdotool search --name "Xenia-canary" >/dev/null 2>&1; do xdpyinfo -display "$DISP" >/dev/null 2>&1 || { echo "DISPLAY LOST at ${SECONDS}s (before the window appeared)"; exit 3; } [ -n "$(alive)" ] || { echo "EMULATOR GONE at ${SECONDS}s (before the window appeared)"; exit 4; } sleep 1 done deadline=$(( SECONDS + ${1:-900} )) while [ $SECONDS -lt $deadline ]; do rm -f /tmp/f1.png /tmp/f2.png screenshot /tmp/f1.png >/dev/null 2>&1; sleep 0.6 screenshot /tmp/f2.png >/dev/null 2>&1 if [ ! -s /tmp/f1.png ] || [ ! -s /tmp/f2.png ]; then xdpyinfo -display "$DISP" >/dev/null 2>&1 \ || { echo "DISPLAY LOST at ${SECONDS}s"; exit 3; } echo "SCREENSHOT FAILED at ${SECONDS}s with the display up"; exit 5 fi [ -n "$(alive)" ] || { echo "EMULATOR GONE at ${SECONDS}s"; exit 4; } d=$(compare -metric RMSE /tmp/f1.png /tmp/f2.png null: 2>&1 | sed 's/ .*//' | cut -d. -f1) d=${d:-0} read -r r g b < <(convert /tmp/f2.png -format "%[fx:int(255*p{625,618}.r)] %[fx:int(255*p{625,618}.g)] %[fx:int(255*p{625,618}.b)]" info:) if [ "$g" -gt 130 ] && [ $((g - r)) -gt 45 ] && [ $((g - b)) -gt 45 ]; then echo "TITLE at ${SECONDS}s -> A"; vgamepad tap A 250; exit 0 fi if [ "$d" -gt 1500 ]; then echo "movie (rmse $d) at ${SECONDS}s -> skip A"; vgamepad tap A 250; sleep 3 fi sleep 1 done echo "TIMEOUT"; exit 1