#!/usr/bin/env bash # Catch a screen being BUILT, not sitting still. # # `log_ui_draws` armed at the title only ever sees the steady state, and the # steady state is the one thing an animation question cannot be asked of. The # build — the wordmarks zooming in, the effect sprites wiping across, the black # fade lifting — happens in the seconds BEFORE the screen classifier can call it # a title. # # So arm repeatedly and keep every log: each F10 opens a new numbered file and # CLOSES the previous one (which stays on disk, complete). Re-arming every few # seconds through the boot therefore tiles the whole approach to the title, and # whichever file happens to straddle the build contains it. Stop re-arming the # instant the title is classified, so a press cannot land mid-build and abandon # the one file that matters. # # NO pad input at all. Ⓐ during the boot has ended a run on a permanent black # screen (docs/re/canary-scripted-input-traps.md), and nothing here needs it. # # Usage: screen_build_capture.sh [out_dir] [timeout_s] # FRAMES= frames per capture window (default 1200 ~ 20 s at 60 Hz) # MAXDRAWS= hard stop per capture (default 80000) # REARM= seconds between F10 presses (default 10) set -u export HOME=/sylph-home/re SDL_AUDIODRIVER=dummy DISPLAY=:98 SD="$(cd "$(dirname "$0")" && pwd)" OUT="${1:-/sylph-home/re/buildcap}" TIMEOUT="${2:-600}" mkdir -p "$OUT"; rm -f "$OUT"/xenia_re_ui_draws_*.log alive(){ ps -o pid=,stat= -C xenia_canary 2>/dev/null | awk '$2 !~ /^Z/ {print $1}'; } shot(){ screenshot "$1" >/dev/null 2>&1; } wide(){ [ "$(identify -format '%w' "$1" 2>/dev/null || echo 0)" -gt 1000 ]; } ( cd "$OUT" && nohup run-canary \ --ui_draw_capture_frames="${FRAMES:-1200}" \ --ui_draw_capture_max="${MAXDRAWS:-80000}" \ --create_profile_if_none="${SYLPH_TAG:-SylphRE}" \ --logged_profile_slot_0_xuid="${SYLPH_XUID:-B13EBABEBABEBABE}" \ >"$OUT/canary.stdout" 2>"$OUT/canary.stderr" & ) sleep "${LAUNCH_WAIT:-8}" until xdotool search --name "Xenia-canary" >/dev/null 2>&1; do [ -n "$(alive)" ] || { echo "EMULATOR GONE before the window appeared"; exit 4; } sleep 1 done win="$(xdotool search --name "Xenia-canary" | tail -1)" echo "WINDOW=$win" arm(){ xdotool windowactivate "$win" 2>/dev/null xdotool key --window "$win" F10 2>/dev/null xdotool key F10 2>/dev/null } last_arm=-999 deadline=$(( SECONDS + TIMEOUT )) s=none while [ $SECONDS -lt $deadline ]; do [ -n "$(alive)" ] || { echo "EMULATOR GONE at ${SECONDS}s"; exit 4; } shot /tmp/sbc.png if [ -s /tmp/sbc.png ]; then wide /tmp/sbc.png || { echo "GRAB IS NOT THE GAME SURFACE at ${SECONDS}s"; exit 6; } s="$(python3 "$SD/screen_id.py" /tmp/sbc.png | awk '{print $1}')" fi if [ "$s" = "${WANT:-title}" ]; then echo "t=${SECONDS}s $s <- STOP re-arming" cp /tmp/sbc.png "$OUT/reached.png" break fi if [ $(( SECONDS - last_arm )) -ge "${REARM:-10}" ]; then arm; last_arm=$SECONDS echo "t=${SECONDS}s $s (armed)" else echo "t=${SECONDS}s $s" fi sleep 1 done # Let the straddling window run itself out rather than cutting it short. echo "waiting for the in-flight capture to close..." for _ in $(seq 1 40); do grep -q "UI-CAP. done" "$OUT/canary.stdout" 2>/dev/null && break sleep 1 done grep -i "UI-CAP" "$OUT/canary.stdout" | tail -6 ls -l "$OUT"/xenia_re_ui_draws_*.log 2>/dev/null || echo "NO CAPTURE LOG" echo "SCREEN BUILD CAPTURE DONE (screen=$s, emulator left running)"