mirror of
https://github.com/jkdansereau/goldeneye-pc-port.git
synced 2026-10-23 15:52:42 +02:00
- level_sweep.sh: frames rendered then frozen with process alive -> STALLED (froze at N/M frames) instead of a false PASS (the Silo -level_20 fly-down / D117-D134 load case). Retried once like NO-FRAMES. - input.c: Input.MouseRawInput=1 (default 0) sets SDL relative system-scale + warp hints off in inputInit -> no OS pointer accel on aim. - docs: M-26-QOL-REVIEW.md + HANDOFF section.
136 lines
5.0 KiB
Bash
136 lines
5.0 KiB
Bash
#!/bin/bash
|
|
# Level sweep: bare -level_XX boot for all 21 solo levels; PASS/NO-FRAMES/CRASH.
|
|
#
|
|
# Flakiness notes (M-13..M-21): the port is not frame-deterministic (D117) and
|
|
# a loaded machine (a concurrent ninja build, another sweep, a stray ge007)
|
|
# routinely turns a known-good level into a spurious NO-FRAMES. This runner is
|
|
# therefore SERIALIZED (a lockdir + a stray-process kill before each level) and
|
|
# uses a 45 s watchdog, and it RETRIES a NO-FRAMES row once before reporting it.
|
|
# Do not run it next to a build.
|
|
#
|
|
# Speed (M-22): the 45 s watchdog is a CEILING, not a fixed cost. A level that
|
|
# has produced its whole GE_PCDUMP frame set is killed immediately (PASS), and a
|
|
# level that renders a few frames then stops moving is cut after ~STALL_SECS. So
|
|
# a healthy 21-level sweep now finishes in a few minutes instead of ~16.
|
|
#
|
|
# Env overrides:
|
|
# SWEEP_SECS=45 per-level watchdog seconds
|
|
# SWEEP_DUMP=80-400:40 GE_PCDUMP window
|
|
# SWEEP_LEVELS="Dam:33" subset to run
|
|
cd "$(dirname "$0")/.."
|
|
|
|
SWEEP_SECS=${SWEEP_SECS:-45}
|
|
SWEEP_DUMP=${SWEEP_DUMP:-80-400:40}
|
|
STALL_SECS=${STALL_SECS:-18} # frames stopped growing this long -> stop early
|
|
|
|
# how many .ppm files a complete GE_PCDUMP window produces (start-end:stride)
|
|
_d=${SWEEP_DUMP%%:*}; _stride=${SWEEP_DUMP##*:}
|
|
_start=${_d%%-*}; _end=${_d##*-}
|
|
if [ "$_start" -ge 0 ] 2>/dev/null && [ "$_stride" -gt 0 ] 2>/dev/null; then
|
|
EXPECT_FRAMES=$(( (_end - _start) / _stride + 1 ))
|
|
else
|
|
EXPECT_FRAMES=4
|
|
fi
|
|
[ "$EXPECT_FRAMES" -lt 1 ] && EXPECT_FRAMES=1
|
|
LV=${SWEEP_LEVELS:-"Dam:33 Facility:34 Runway:35 Surface1:36 Bunker1:09 Silo:20 Frigate:26 Surface2:43 Bunker2:27 Statue:22 Archives:24 Streets:29 Depot:30 Train:25 Jungle:37 Control:23 Caverns:39 Cradle:41 Aztec:28 Egypt:32 Cuba:54"}
|
|
|
|
OUT=/tmp/sweep_results
|
|
LOGS=/tmp/sweeplogs
|
|
LOCK=/tmp/ge007_sweep.lock
|
|
|
|
# --- serialize: one sweep at a time -----------------------------------------
|
|
if ! mkdir "$LOCK" 2>/dev/null; then
|
|
echo "another sweep holds $LOCK (stale? rmdir it)" >&2
|
|
exit 1
|
|
fi
|
|
trap 'taskkill //F //IM ge007.x86_64.exe >/dev/null 2>&1; rmdir "$LOCK" 2>/dev/null' EXIT INT TERM
|
|
|
|
export PATH="/c/msys64/mingw64/bin:$PATH" # addr2line + runtime DLLs
|
|
|
|
mkdir -p $LOGS
|
|
: > $OUT
|
|
rm -f $LOGS/*.crash.log
|
|
|
|
# one run of one level -> echoes the status string
|
|
run_level() {
|
|
local name=$1 num=$2
|
|
rm -f ge007.crash.log; rm -rf ppm
|
|
# kill anything left over from a previous level / another session
|
|
taskkill //F //IM ge007.x86_64.exe > /dev/null 2>&1
|
|
sleep 1
|
|
|
|
GE_PCDUMP="$SWEEP_DUMP" ./build-pc/ge007.x86_64.exe -level_$num > $LOGS/$name.log 2>&1 &
|
|
local pid=$!
|
|
|
|
# watchdog: poll so we do not pay the full window when the outcome is already
|
|
# known -- exit as soon as the whole dump set is on disk (PASS), or the frame
|
|
# count has been frozen for STALL_SECS (level rendered a bit then wedged), or
|
|
# the process exits on its own (clean exit / crash).
|
|
local waited=0 fcnt=0 prev=0 stall=0 stalled=0
|
|
while [ $waited -lt $SWEEP_SECS ] && kill -0 $pid 2>/dev/null; do
|
|
sleep 1; waited=$((waited + 1))
|
|
fcnt=$(ls ppm/*.ppm 2>/dev/null | wc -l)
|
|
[ "$fcnt" -ge "$EXPECT_FRAMES" ] && break
|
|
if [ "$fcnt" -gt 0 ] && [ "$fcnt" -eq "$prev" ]; then
|
|
stall=$((stall + 1))
|
|
if [ $stall -ge $STALL_SECS ]; then stalled=1; break; fi
|
|
else
|
|
stall=0
|
|
fi
|
|
prev=$fcnt
|
|
done
|
|
# was the process still alive when we gave up (vs. a clean exit / crash)?
|
|
local alive=0
|
|
kill -0 $pid 2>/dev/null && alive=1
|
|
taskkill //F //IM ge007.x86_64.exe > /dev/null 2>&1
|
|
wait $pid 2>/dev/null
|
|
sleep 2
|
|
|
|
if [ -f ge007.crash.log ]; then
|
|
local pc sym
|
|
pc=$(grep -oE '0x[0-9a-fA-F]+' ge007.crash.log | head -1)
|
|
sym=$(addr2line -e build-pc/ge007.x86_64.exe -f -C "$pc" 2>/dev/null | head -1)
|
|
cp ge007.crash.log $LOGS/$name.crash.log
|
|
echo "CRASH @ $sym ($pc)"
|
|
return
|
|
fi
|
|
|
|
local last pcnt
|
|
last=$(ls ppm/*.ppm 2>/dev/null | tail -1)
|
|
if [ -n "$last" ]; then
|
|
pcnt=$(python tools_pc/pixcount.py "$last" 2>/dev/null | grep -oE 'non-clear [0-9]+ \([0-9.]+%\)')
|
|
# frames rendered then froze while the process stayed alive -> STALLED,
|
|
# not a real PASS (the Silo -level_20 fly-down case, D117/D134 load
|
|
# sensitivity). A complete dump set is still a genuine PASS.
|
|
if [ "$stalled" = 1 ] && [ "$alive" = 1 ] && [ "$fcnt" -lt "$EXPECT_FRAMES" ]; then
|
|
echo "STALLED (froze at $fcnt/$EXPECT_FRAMES frames) $pcnt"
|
|
else
|
|
echo "PASS $pcnt"
|
|
fi
|
|
else
|
|
echo "NO-FRAMES"
|
|
fi
|
|
}
|
|
|
|
for entry in $LV; do
|
|
name=${entry%%:*}; num=${entry##*:}
|
|
status=$(run_level "$name" "$num")
|
|
|
|
# NO-FRAMES and STALLED are the flaky outcomes (D117 + host load) -- retry
|
|
# once before believing them. A CRASH is deterministic enough to report as-is.
|
|
case "$status" in
|
|
NO-FRAMES|STALLED*)
|
|
sleep 3
|
|
retry=$(run_level "$name" "$num")
|
|
case "$retry" in
|
|
NO-FRAMES) status="NO-FRAMES (2 attempts)" ;;
|
|
STALLED*) status="$retry (2 attempts)" ;;
|
|
*) status="$retry [passed on retry]" ;;
|
|
esac
|
|
;;
|
|
esac
|
|
|
|
echo "$name ($num): $status" | tee -a $OUT
|
|
done
|
|
echo "SWEEP DONE"
|