joeylib2/scripts/bench-staxi-title.sh

160 lines
5.9 KiB
Bash
Executable file

#!/usr/bin/env bash
# bench-staxi-title.sh - Space Taxi title-screen logo cadence measurement
# (the PERF-AUDIT #3 acceptance test: the logo repaints via 103
# jlTilePasteMono calls, intended every 4th frame -- stRender.c
# titleAnimateLogo's `& 3u` divider mirroring the C64 original).
#
# Boots GS/OS under headless MAME with a WORK COPY of joey.2mg (must
# contain STAXI + its DATA tree; build with
# JOEY_DISK_EXAMPLES="STAXI" scripts/make-iigs-disk.sh),
# launches STAXI via the standard Finder keystroke timeline, then
# samples 8 known logo tile cells from the SHR framebuffer EVERY frame.
# Each frame the sampled 256 bytes fold into a rolling hash; a hash
# change means the logo visibly changed on screen (the flip-book tile
# differs on every 4-frame step, so a healthy title changes every 4
# frames; a slow repaint stretches the observed period).
#
# Emits "STAXI-CHG frame=N sum=XXXXXX" per change, heartbeats, and a
# final verify-style summary. Post-process the change frames into
# periods with the analysis snippet in the acceptance report.
#
# Usage: scripts/bench-staxi-title.sh [label]
# MAME_ROMPATH override ROM dir (default ~/.mame/roms)
# STAXI_MAX_FRAMES frame cap (default 15000)
# STAXI_MAX_CHANGES stop after this many logo changes (default 80)
set -euo pipefail
repo=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)
: "${LLVM816_ROOT:?bench-staxi-title.sh: source toolchains/env.sh first}"
CADIUS="${CADIUS:-$LLVM816_ROOT/tools/cadius/cadius}"
sys_disk=$repo/toolchains/emulators/support/gsos-system.po
data_disk=$repo/build/iigs/bin/joey.2mg
rompath="${MAME_ROMPATH:-$HOME/.mame/roms}"
maxFrames="${STAXI_MAX_FRAMES:-15000}"
maxChanges="${STAXI_MAX_CHANGES:-80}"
label="${1:-run}"
for f in "$sys_disk" "$data_disk"; do
[ -f "$f" ] || { echo "bench-staxi-title: missing $f" >&2; exit 2; }
done
if ! "$CADIUS" CATALOG "$data_disk" 2>/dev/null | grep -qE '^ STAXI +S16'; then
echo "bench-staxi-title: STAXI not on joey.2mg (JOEY_DISK_EXAMPLES=\"STAXI\" scripts/make-iigs-disk.sh)" >&2
exit 2
fi
work=$(mktemp -d -t joeylib-staxi.XXXXXX)
trap 'rm -rf "$work"' EXIT
cp "$sys_disk" "$work/boot.po"
cp "$data_disk" "$work/joey.2mg"
cat > "$work/staxi.lua" <<LUA
local cpu = manager.machine.devices[":maincpu"]
local mem = cpu.spaces["program"]
local nat = manager.machine.natkeyboard
local frame = 0
local idx = 1
local function field(port, name)
local p = manager.machine.ioport.ports[port]
if p == nil then return nil end
return p.fields[name]
end
local key_cmd = field(":macadb:KEY3", "Command / Open Apple")
local function press(f) if f then f:set_value(1) end end
local function release(f) if f then f:set_value(0) end end
-- 8 logo tile cells (bx,by) chosen from title.dat's 0x84 map: byte
-- offset in SHR = 0xE12000 + (by*8 + r)*160 + bx*4, 4 bytes per row.
-- Every repaint pastes a different flip tile into these cells, so
-- their content changes on every animation step.
local cells = { {6,1},{11,1},{24,1},{29,1},{12,7},{16,8},{12,9},{15,10} }
local function logoSum()
local sum = 0
for _, c in ipairs(cells) do
local base = 0xE12000 + (c[2] * 8) * 160 + c[1] * 4
for r = 0, 7 do
local off = base + r * 160
for b = 0, 3 do
sum = (sum * 33 + mem:read_u8(off + b)) % 16777213
end
end
end
return sum
end
local steps = {
{3000, function() nat:post("J") end},
{3120, function() press(key_cmd) end},
{3126, function() nat:post("o") end},
{3180, function() release(key_cmd) end},
{3540, function() nat:post("STAXI") end},
{3660, function() press(key_cmd) end},
{3666, function() nat:post("o") end},
{3720, function() release(key_cmd) end},
}
local prevSum = -1
local nChanges = 0
local function summary(tag)
local distinct = {}
local nonzero = 0
local checksum = 0
for i = 0, 31999 do
local b = mem:read_u8(0xE12000 + i)
if b ~= 0 then nonzero = nonzero + 1 end
distinct[b & 0x0F] = true
distinct[(b >> 4) & 0x0F] = true
checksum = (checksum + b) & 0xFFFFFF
end
local n = 0
for _ in pairs(distinct) do n = n + 1 end
io.write(string.format("STAXI-%s label=$label frame=%d changes=%d distinctNibbles=%d nonZeroBytes=%d checksum=%06X\n",
tag, frame, nChanges, n, nonzero, checksum))
io.flush()
end
emu.register_frame_done(function()
frame = frame + 1
while idx <= #steps and frame >= steps[idx][1] do
steps[idx][2]()
idx = idx + 1
end
if frame >= 3800 then
local s = logoSum()
if s ~= prevSum then
io.write(string.format("STAXI-CHG frame=%d sum=%06X\n", frame, s))
io.flush()
prevSum = s
nChanges = nChanges + 1
if nChanges >= $maxChanges then
summary("DONE")
manager.machine:exit()
end
end
end
if frame % 1500 == 0 then
io.write(string.format("STAXI-HEART frame=%d changes=%d\n", frame, nChanges))
io.flush()
end
if frame >= $maxFrames then
summary("TIMEOUT")
manager.machine:exit()
end
end)
LUA
echo "bench-staxi-title[$label]: running STAXI headless under MAME (cap $maxFrames frames, $maxChanges changes)..." >&2
cd "$work"
out=$(QT_QPA_PLATFORM=offscreen SDL_VIDEODRIVER=dummy SDL_AUDIODRIVER=dummy \
timeout "${STAXI_WALL_TIMEOUT:-900}" mame apple2gs \
-rompath "$rompath" \
-flop3 "$work/boot.po" -flop4 "$work/joey.2mg" \
-video none -sound none -nothrottle \
-autoboot_script "$work/staxi.lua" </dev/null 2>&1) || true
echo "$out" | grep -E '^STAXI-(CHG|HEART|DONE|TIMEOUT)' > "$repo/build/iigs/bin/staxi-title-$label.log" || true
tail -3 "$repo/build/iigs/bin/staxi-title-$label.log" >&2
lines=$(grep -c '^STAXI-CHG' "$repo/build/iigs/bin/staxi-title-$label.log" || true)
echo "bench-staxi-title[$label]: $lines change events -> build/iigs/bin/staxi-title-$label.log" >&2