diff --git a/tools/re-capture/resume_reliability.sh b/tools/re-capture/resume_reliability.sh new file mode 100755 index 00000000..3707328b --- /dev/null +++ b/tools/re-capture/resume_reliability.sh @@ -0,0 +1,45 @@ +#!/usr/bin/env bash +# Count how often the title screen's loader thread actually RUNS. +# +# Pressing (A) at the title makes the game ExCreateThread(CREATE_SUSPENDED) + +# NtResumeThread. Before canary a60fe7d11 that resume could be lost, leaving a +# thread with zero kernel calls and zero CPU (docs/re/canary-scripted-input-traps.md). +# The menu appearing is a poor test — it needs the game to get further, and the +# attract loop confuses it — so this measures the thing the fix targets directly: +# does the slot-(1F) thread appear as the CALLER of any kernel call? +# +# Needs kernel logging, which is off by default: LOG_MASK=12 LOG_LEVEL=3. +# +# resume_reliability.sh [runs] [tag] +set -u +export HOME=/sylph-home/re SDL_AUDIODRIVER=dummy DISPLAY=:98 +SD="$(cd "$(dirname "$0")" && pwd)" +RUNS="${1:-4}" +TAG="${2:-rel}" +OUT=/sylph-home/re/resume-reliability +mkdir -p "$OUT" +CSV="$OUT/$TAG.csv" +echo "run,title_at_s,thread_created,thread_ran_calls,resolvepath_after,screen" > "$CSV" + +for i in $(seq 1 "$RUNS"); do + pkill -9 -x xenia_canary 2>/dev/null; sleep 3 + rm -f /tmp/xenia-canary.lock + LOG_MASK=12 LOG_LEVEL=3 BOOT_MENU_LOG="$OUT/$TAG-$i.stdout" \ + timeout 700 "$SD/boot_menu.sh" "$TAG-$i" > "$OUT/$TAG-$i.boot" 2>&1 + sleep 20 + L="$OUT/$TAG-$i.stdout" + t=$(grep -ao 'TITLE at [0-9]*s' "$OUT/$TAG-$i.boot" 2>/dev/null | head -1 | tr -dc '0-9') + created=$(grep -ac '(1F) Stack' "$L" 2>/dev/null); created=${created:-0} + h=$(grep -a '(1F) Stack' "$L" 2>/dev/null | tail -1 | grep -ao 'XThread[0-9A-F]*' | sed 's/XThread//') + calls=0; rp=0 + if [ -n "${h:-}" ]; then + calls=$(grep -ac "^[dik]> $h" "$L" 2>/dev/null); calls=${calls:-0} + n=$(grep -an "NtResumeThread($h" "$L" 2>/dev/null | tail -1 | cut -d: -f1) + if [ -n "${n:-}" ]; then rp=$(tail -n +"$n" "$L" | grep -ac 'ResolvePath'); rp=${rp:-0}; fi + fi + screenshot "$OUT/$TAG-$i.png" >/dev/null 2>&1 + s=$(python3 "$SD/screen_id.py" "$OUT/$TAG-$i.png" 2>/dev/null | awk '{print $1}') + echo "$i,${t:-none},$created,$calls,$rp,${s:-none}" | tee -a "$CSV" +done +pkill -9 -x xenia_canary 2>/dev/null +echo "--- $CSV ---"; cat "$CSV" diff --git a/tools/re-capture/skip_intro.sh b/tools/re-capture/skip_intro.sh index 6c7d43fe..b8f9a5d7 100755 --- a/tools/re-capture/skip_intro.sh +++ b/tools/re-capture/skip_intro.sh @@ -50,7 +50,12 @@ while [ $SECONDS -lt $deadline ]; do # then over-matched the other way: it called the SQUARE ENIX publisher logo # "title" 151s into a boot, and this script spent its one press there. # is_title.py counts glyph pixels, which only the interactive title has. - if python3 "$SD_SI/is_title.py" /tmp/f2.png >/dev/null 2>&1; then + # AND the frame must be STATIC. A glyph count alone still fired at 113-173s, + # during the intro movie, and the press was wasted — measured by the loader + # thread that the title handler ALWAYS creates being absent entirely on those + # runs. The resting title barely changes between two grabs 0.6s apart; a movie + # does, and `$d` is already computed above for exactly that distinction. + if [ "$d" -le 1500 ] && python3 "$SD_SI/is_title.py" /tmp/f2.png 800 >/dev/null 2>&1; then echo "TITLE at ${SECONDS}s -> A"; tapA; exit 0 fi # DO NOT tap through the movies. This branch used to, and for a long time it