diff --git a/tools/re-capture/menu_blend_capture.sh b/tools/re-capture/menu_blend_capture.sh new file mode 100755 index 00000000..e950b5b9 --- /dev/null +++ b/tools/re-capture/menu_blend_capture.sh @@ -0,0 +1,88 @@ +#!/usr/bin/env bash +# Boot -> title -> MAIN MENU (or EXTRAS) -> arm the UI draw capture and read the +# BLEND STATE the guest set for each draw. +# +# Why this exists rather than `menu_draw_capture.sh`: that script launches with +# `--log_ui_draws=true`, and Canary's own source records why that is now a bad +# idea — `RequestUiDrawCapture()` in command_processor.cc says arming is +# unconditional since the flag "correlates, across 12 runs, with the title screen +# refusing (A) (0 of 7 with the flag, 4 of 5 without)". The flag is OBSOLETE and +# only kept so old command lines parse. So this one does not pass it. +# +# The measurement: `CaptureUiDrawForRE` now also logs RB_BLENDCONTROL0, +# RB_COLORCONTROL and RB_COLOR_MASK per draw, raw and decoded. That is what the +# GPU was actually told, which is the only thing that can settle whether the +# menu's `ptframe1`/`ptframe2` are composited with something other than +# alpha-over — nothing on the disc selects a per-element mode +# (docs/re/structures/t32-blend-mode-not-on-disc.md). +# +# Two traps this inherits from menu_draw_capture.sh, both measured: +# * (A) at the title is accepted only intermittently, but the title that ENDS +# the boot accepts a single tap; repeating is pointless. +# * F10 arms the capture AND opens the emulator's menu bar. Any Xenia UI makes +# IsUIActive() true, and then XamInputGetKeystrokeEx returns SUCCESS with a +# zeroed keystroke forever, which is the guest-side crash in +# docs/re/structures/title-a-press-fault.md. So click the game surface +# immediately after F10 to dismiss it. +# +# Usage: menu_blend_capture.sh [out_dir] +# SCREEN=extras walk one step right and (A) into EXTRAS before arming +set -u +export HOME=/sylph-home/re SDL_AUDIODRIVER=dummy DISPLAY=:98 +SD="$(cd "$(dirname "$0")" && pwd)" +OUT="${1:-/sylph-home/re/blendcap}" +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; } +screen(){ shot /tmp/mbc.png; python3 "$SD/screen_id.py" /tmp/mbc.png | awk '{print $1}'; } + +( cd "$OUT" && nohup run-canary --mem_watch=false \ + --ui_draw_capture_frames="${FRAMES:-4}" --ui_draw_capture_max="${MAXDRAWS:-4000}" \ + --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)" +echo "WINDOW=$win" + +# 1. WAIT for the title. Do not tap through the intro: it is ~3.5 minutes and it +# gets there on its own; a run that tapped every 4 s delivered 88 presses and +# ended on a black screen. +s="" +deadline=$(( SECONDS + 420 )) +while [ $SECONDS -lt $deadline ]; do + s="$(screen)"; echo "t=${SECONDS}s $s" + [ "$s" = "title" ] && break + sleep 4 +done +[ "$s" = "title" ] || { echo "NEVER REACHED THE TITLE"; exit 1; } + +# 2. ONE tap. +python3 "$SD/pad.py" tap A 0.3 +for _ in 1 2 3 4 5 6; do + sleep 4; s="$(screen)"; echo " after A: $s" + [ "$s" = "menu" ] && break +done +shot "$OUT/menu.png" +[ "$s" = "menu" ] || { echo "NO MENU (screen=$s)"; exit 2; } +echo "MENU at ${SECONDS}s" + +if [ "${SCREEN:-menu}" = "extras" ]; then + # EXTRAS is the second item; the menu opens on NEW GAME. + python3 "$SD/pad.py" tap DOWN 0.2; sleep 1 + python3 "$SD/pad.py" tap DOWN 0.2; sleep 1 + python3 "$SD/pad.py" tap A 0.3; sleep 4 + s="$(screen)"; echo " after EXTRAS attempt: $s"; shot "$OUT/extras.png" +fi + +# 3. arm, then dismiss the menu bar F10 opened +xdotool windowactivate --sync "$win"; sleep 1 +xdotool key F10; sleep 3 +xdotool mousemove 900 400 click 1; sleep 2 +shot "$OUT/after-f10.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 +pkill -x xenia_canary 2>/dev/null; sleep 2 +echo "DONE at ${SECONDS}s (emulator killed)"