#!/usr/bin/env bash # Boot -> first title -> main menu -> OPTIONS, and capture the UI draw order and # the BLEND STATE there. OPTIONS is the fourth menu item. # # 🔴 It used to say "so: three d-pad steps down, then (A)" and do exactly that. # Counting presses does not work here -- presses get dropped, and a dropped one # lands the cursor on TUTORIAL, whose (A) starts the tutorial. Two later attempts # to avoid counting were worse: "press until the cursor stops moving" is # unreachable on a menu that WRAPS, and an earlier version of it read the same # row twice because the first press was lost and pressed (A) on NEW GAME. # # What works is to use the wrap as the landmark. Press down until the row # DECREASES -- that is the wrap, and the cursor is now on item 1 whatever it # started on -- then take exactly three verified steps, retrying any press that # does not move the cursor. Geometry-free: it needs the row to be monotone in the # item, not calibrated, and ring_row.py's ROW0/SPACING are x11grab constants that # do not fit a `screenshot` grab (METHOD.md). # # The recipe for the first two hops is measured, not guessed (see # docs/re/canary-scripted-input-traps.md): the title that ENDS THE BOOT accepts a # single (A); the one the attract loop returns to accepts nothing. So never tap # during the boot, and take the first title. set -u export HOME=/sylph-home/re SDL_AUDIODRIVER=dummy DISPLAY=:98 SD="$(cd "$(dirname "$0")" && pwd)" OUT="${1:-/sylph-home/re/optcap}" mkdir -p "$OUT"; rm -f "$OUT"/xenia_re_ui_draws_*.log shot(){ screenshot "$1" >/dev/null 2>&1; } screen(){ shot /tmp/odc.png; python3 "$SD/screen_id.py" /tmp/odc.png | awk '{print $1}'; } alive(){ ps -o pid=,stat= -C xenia_canary 2>/dev/null | awk '$2 !~ /^Z/ {print $1}'; } # No capture flags at launch: F10 arms the capture unconditionally now, and # launching with --log_ui_draws correlated (0 of 7) with the title refusing (A). ( cd "$OUT" && nohup run-canary --mem_watch=false \ --logged_profile_slot_0_xuid=B13EBABEBABEBABE \ >"$OUT/canary.stdout" 2>"$OUT/canary.stderr" & ) sleep 8 until xdotool search --name "Xenia-canary" >/dev/null 2>&1; do [ -n "$(alive)" ] || { echo "EMULATOR GONE"; exit 4; }; sleep 1 done win="$(xdotool search --name "Xenia-canary" | tail -1)" deadline=$(( SECONDS + ${DEADLINE:-1200} )) while [ $SECONDS -lt $deadline ]; do s="$(screen)"; echo "t=${SECONDS}s $s" [ "$s" = "title" ] && break sleep 1 done [ "$s" = "title" ] || { echo "NO BOOT TITLE"; exit 1; } echo "-> A on the boot title" python3 "$SD/pad.py" tap A 0.3 for _ in 1 2 3 4 5 6 7 8; do sleep 3; s="$(screen)"; echo " $s"; [ "$s" = "menu" ] && break; done shot "$OUT/menu.png" [ "$s" = "menu" ] || { echo "NO MENU (screen=$s)"; exit 2; } row(){ shot /tmp/odc_row.png; python3 - <<'PY' from PIL import Image import sys; sys.path.insert(0,"/work/tools/re-capture") import ring_row try: print("%.1f" % ring_row.ring_row(Image.open("/tmp/odc_row.png"))) except Exception: print("nan") PY } down(){ python3 "$SD/pad.py" tap DOWN 0.2; sleep 3; } echo "-> find the wrap, then take three verified steps to OPTIONS" prev="$(row)"; echo " row $prev" wrapped=0 for _ in $(seq 1 12); do down; cur="$(row)"; echo " row $cur" if [ "$(python3 -c "print(1 if float('$cur') < float('$prev') - 5 else 0)")" = "1" ]; then wrapped=1; prev="$cur"; break fi prev="$cur" done [ "$wrapped" = 1 ] || { echo "NEVER SAW THE WRAP -- not pressing (A)"; exit 3; } echo " wrapped to item 1" for step in 1 2 3; do ok=0 for _ in 1 2 3; do down; cur="$(row)"; echo " step $step row $cur" if [ "$(python3 -c "print(1 if float('$cur') > float('$prev') + 5 else 0)")" = "1" ]; then ok=1; prev="$cur"; break fi echo " (press dropped, retrying)" done [ "$ok" = 1 ] || { echo "STEP $step NEVER LANDED -- not pressing (A)"; exit 3; } done shot "$OUT/menu-on-options.png" python3 "$SD/pad.py" tap A 0.3 sleep 8 shot "$OUT/options.png" echo "screen after A: $(screen)" xdotool windowactivate --sync "$win"; sleep 1 xdotool key F10; sleep 3 xdotool mousemove 900 400 click 1; sleep 2 shot "$OUT/options-armed.png" ls -l "$OUT"/xenia_re_ui_draws_*.log 2>/dev/null || echo "NO CAPTURE LOG" grep -i "UI-CAP" "$OUT/canary.stdout" | tail -3 echo "OPTIONS CAPTURE DONE" pkill -x xenia_canary 2>/dev/null; sleep 2; echo "emulator killed"