108 lines
3.7 KiB
Bash
Executable file
108 lines
3.7 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
# test.sh - headless test of a demo OMF. Boots MAME, drives the
|
|
# Finder to launch the demo, waits for the demo to reach its event
|
|
# loop, injects a keystroke to wake it, then reads back the
|
|
# trailing marker at $00:0070 to confirm the demo ran to completion.
|
|
#
|
|
# Usage: bash demos/test.sh <demo-name>
|
|
#
|
|
# Expected outcome: $0070 reads back as $99.
|
|
|
|
set -euo pipefail
|
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
|
|
[ $# -ge 1 ] || { echo "usage: $0 <demo-name>" >&2; exit 2; }
|
|
BASE="$1"
|
|
SRC="$SCRIPT_DIR/$BASE.c"
|
|
OMF="$SCRIPT_DIR/$BASE.omf"
|
|
|
|
if [ ! -f "$OMF" ] || [ "$SRC" -nt "$OMF" ]; then
|
|
bash "$SCRIPT_DIR/build.sh" "$BASE" >/dev/null
|
|
fi
|
|
|
|
CADIUS=${CADIUS:-$PROJECT_ROOT/tools/cadius/cadius}
|
|
SYSDISK=${SYSDISK:-$PROJECT_ROOT/tools/gsos/sys602.po}
|
|
|
|
[ -x "$CADIUS" ] || { echo "cadius not found: $CADIUS" >&2; exit 2; }
|
|
[ -f "$SYSDISK" ] || { echo "sysdisk not found: $SYSDISK" >&2; exit 2; }
|
|
command -v mame >/dev/null || { echo "mame not in PATH" >&2; exit 2; }
|
|
|
|
WORK=$(mktemp -d -t demotest.XXXXXX)
|
|
trap 'rm -rf "$WORK"' EXIT
|
|
|
|
cp "$SYSDISK" "$WORK/disk.po"
|
|
"$CADIUS" CREATEVOLUME "$WORK/data.po" DATA 800KB >/dev/null
|
|
cp "$OMF" "$WORK/HELLO#B30000"
|
|
"$CADIUS" ADDFILE "$WORK/data.po" /DATA "$WORK/HELLO#B30000" >/dev/null
|
|
|
|
# Same Finder-navigation timeline as runViaFinder.sh, plus a key
|
|
# injection at frame 6000 (well after the demo has launched and is
|
|
# waiting in its event loop), and a memory check at frame 8000.
|
|
cat > "$WORK/launch.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 get_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 = get_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
|
|
|
|
local steps = {
|
|
{3300, function() nat:post("D") end},
|
|
{3540, function() press(key_cmd) end},
|
|
{3546, function() nat:post("o") end},
|
|
{3600, function() release(key_cmd) end},
|
|
{4200, function() nat:post("H") end},
|
|
{4500, function() press(key_cmd) end},
|
|
{4506, function() nat:post("o") end},
|
|
{4560, function() release(key_cmd) end},
|
|
{7000, function() nat:post(" ") end}, -- wake the demo's event loop
|
|
{7500, function() nat:post(" ") end}, -- send a few in case GetNextEvent runs in between
|
|
{8000, function() nat:post(" ") end},
|
|
{9000, function()
|
|
print(string.format("MAME-READ 0x70=%02x", mem:read_u8(0x70)))
|
|
for a = 0x60, 0x7F do
|
|
local v = mem:read_u8(a)
|
|
if v ~= 0 and a ~= 0x70 then
|
|
print(string.format("MAME-READ 0x%02x=%02x", a, v))
|
|
end
|
|
end
|
|
for a = 0x0F80, 0x0F9F do
|
|
local v = mem:read_u8(a)
|
|
if v ~= 0 then
|
|
print(string.format("MAME-READ 0x%04x=%02x", a, v))
|
|
end
|
|
end
|
|
manager.machine:exit()
|
|
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
|
|
end)
|
|
LUA
|
|
|
|
OUT=$(timeout 200 mame apple2gs -rompath "$PROJECT_ROOT/tools/mame/roms" \
|
|
-window -nothrottle -sound none \
|
|
-seconds_to_run 180 -flop3 "$WORK/disk.po" -flop4 "$WORK/data.po" \
|
|
-autoboot_script "$WORK/launch.lua" </dev/null 2>&1)
|
|
|
|
echo "$OUT" | grep "MAME-READ" || true
|
|
VAL=$(echo "$OUT" | grep "MAME-READ 0x70=" | tail -1 | sed 's/.*=//')
|
|
if [ "$VAL" = "99" ]; then
|
|
echo "PASS: $BASE reached end (\$70 = 0x99)"
|
|
exit 0
|
|
fi
|
|
echo "FAIL: $BASE marker at \$70 = 0x$VAL (want 0x99)"
|
|
exit 1
|