#!/usr/bin/env bash
# snapDemo.sh - boot a demo OMF in MAME and capture multiple SHR
# snapshots while it runs.  Useful for verifying that a demo's window
# is actually drawn (vs the headless test which only checks the $99
# end-marker at $00:0070).
#
# Usage: bash scripts/snapDemo.sh <demo-name> [snap-frame-list]
# Default snap frames: 4800,5000,5200,5500,6000,6500.
# Optional env: SYSDISK=path/to/sys602.po (or other ProDOS .po).
#
# Snapshots land in a TMPDIR-rooted snapdir; the path is echoed at
# the end.  The work disk image and Finder navigation script are
# cleaned up via trap.

set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"

[ $# -ge 1 ] || { echo "usage: $0 <demo-name> [frames]" >&2; exit 2; }
BASE="$1"
FRAMES="${2:-4800,5000,5200,5500,6000,6500}"

CADIUS="${CADIUS:-$PROJECT_ROOT/tools/cadius/cadius}"
SYSDISK="${SYSDISK:-$PROJECT_ROOT/tools/gsos/sys602.po}"
OMF="$PROJECT_ROOT/demos/${BASE}.omf"

[ -x "$CADIUS" ]  || { echo "cadius not found: $CADIUS" >&2; exit 2; }
[ -f "$SYSDISK" ] || { echo "sysdisk not found: $SYSDISK" >&2; exit 2; }
[ -f "$OMF" ]     || { echo "OMF not found: $OMF (run demos/build.sh $BASE first)" >&2; exit 2; }
command -v mame >/dev/null || { echo "mame not in PATH" >&2; exit 2; }

WORK=$(mktemp -d -t snapDemo.XXXXXX)
SNAPDIR=$(mktemp -d -t snapDemoOut.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

# Build lua steps[] entries for each requested snap frame.
SNAP_STEPS=""
for f in ${FRAMES//,/ }; do
    SNAP_STEPS="${SNAP_STEPS}    {${f}, function() manager.machine.video:snapshot(); print(string.format(\"SNAP-FRAME=${f}\")) end},
"
done

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 gf(p,n) local pp = manager.machine.ioport.ports[p]; return pp and pp.fields[n] end
local kcmd = gf(":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
-- ADB mouse input ports (set when PARK_MOUSE is enabled to scroll the
-- IIgs cursor out of the snapshot region — otherwise the Finder-left
-- cursor sits on the menu bar and the inverted-XOR cursor shape leaves
-- a visible dark square in the captured screen).
local mx = gf(":macadb:MOUSE1", "Mouse X")
local my = gf(":macadb:MOUSE2", "Mouse Y")
local park_active = ${PARK_MOUSE:-0}
local park_frame_start = 5500   -- after the Cmd-O that launches the demo
local park_frame_end   = 5900   -- stop nudging once well off screen
local steps = {
    {3300, function() nat:post("D") end},
    {3540, function() press(kcmd) end},
    {3546, function() nat:post("o") end},
    {3600, function() release(kcmd) end},
    {4200, function() nat:post("H") end},
    {4500, function() press(kcmd) end},
    {4506, function() nat:post("o") end},
    {4560, function() release(kcmd) end},
${SNAP_STEPS}
    {8500, function()
        local count = 0
        for o = 0, 31999 do
            if mem:read_u8(0xE12000 + o) ~= 0 then count = count + 1 end
        end
        print(string.format("SHR-NONZERO=%d", count))
        print(string.format("MAME-READ 0x70=%02x", mem:read_u8(0x70)))
        print(string.format("MAME-READ 0x71=%02x", mem:read_u8(0x71)))
        print(string.format("MAME-READ 0x72=%02x", mem:read_u8(0x72)))
        print(string.format("MAME-READ 0x73=%02x", mem:read_u8(0x73)))
        manager.machine:exit()
    end},
}
emu.register_frame_done(function()
    frame = frame + 1
    -- Park the cursor at the right edge of the screen when PARK_MOUSE=1.
    -- ADB mouse takes deltas, so push X for a window of frames and the
    -- cursor scrolls right until the IIgs cursor manager clamps it at
    -- the screen edge.  Don't push Y — that moves the cursor INTO the
    -- demo's content area (most demos sit in the upper screen, so a
    -- downward-parked cursor lands ON visible content).
    if park_active == 1 and mx and my and
       frame >= park_frame_start and frame <= park_frame_end then
        mx:set_value(100); my:set_value(0)
    end
    while idx <= #steps and frame >= steps[idx][1] do
        steps[idx][2](); idx = idx + 1
    end
end)
LUA

timeout 200 mame apple2gs -rompath "$PROJECT_ROOT/tools/mame/roms" \
    -window -nothrottle -sound none \
    -snapshot_directory "$SNAPDIR" \
    -seconds_to_run 180 -flop3 "$WORK/disk.po" -flop4 "$WORK/data.po" \
    -autoboot_script "$WORK/launch.lua" </dev/null 2>&1 | \
    grep -E "MAME-READ|SHR-|SNAP-" || true
echo "snaps in: $SNAPDIR"
find "$SNAPDIR" -name '*.png' | sort
