#!/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" # Refuse to run two of these at once. Each iteration below kills the emulator by # name, which is outside run-canary's lockfile — so a second copy of this script # silently killed the first copy's boots mid-run and they were recorded as # failures ("title_at_s=none", the emulator log ending in "Killed"). One # emulator at a time has to mean one DRIVER at a time too. exec 8>/tmp/resume-reliability.lock if ! flock -n 8; then echo "resume_reliability.sh: another run is in progress (lock /tmp/resume-reliability.lock)" >&2 echo " kill it with: pkill -x resume_reliability.sh # -x, NOT -f: -f matches your own shell" >&2 exit 1 fi 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"