#!/usr/bin/env bash
# verify-iigs-input.sh - Headless typed-character acceptance gate for the
# IIgs port. Boots GS/OS under MAME, launches the KEYS example off
# joey.2mg, types the RetroNet definition-of-done string on the emulated
# keyboard, and reads the example's verification scanline (row 198)
# straight out of SHR memory. KEYS encodes every character it received
# from jlInputGetChar as raw nibble pixel pairs behind an A5A5 sentinel,
# so the row bytes must equal the typed ASCII exactly -- proving digits,
# '.', and ':' all arrive through the typed-character queue.
#
# Usage:   scripts/verify-iigs-input.sh
# Requires: toolchains/env.sh sourced; build/iigs/bin/joey.2mg built
#           with the current KEYS (make iigs-disk).
set -euo pipefail

repo=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)

target="192.168.1.10:6510"

sys_disk=$repo/toolchains/emulators/support/gsos-system.po
data_disk=$repo/build/iigs/bin/joey.2mg
rompath="${MAME_ROMPATH:-$HOME/.mame/roms}"
typeFrame="${MAME_TYPE_FRAME:-6600}"
readFrame="${MAME_READ_FRAME:-12000}"

for f in "$sys_disk" "$data_disk"; do
    [ -f "$f" ] || { echo "verify-iigs-input: missing $f (run 'make iigs-disk')" >&2; exit 2; }
done

work=$(mktemp -d -t joeylib-input-verify.XXXXXX)
trap 'rm -rf "$work"' EXIT
cp "$sys_disk"  "$work/boot.po"
cp "$data_disk" "$work/joey.2mg"

# Finder keystroke timeline as in verify-iigs.sh, then the typed string
# once KEYS is running, then a dump of verification row 198:
#   base = $E1/2000 + 198*160 = $E1/9BC0
#   byte 0..1 = A5 A5 sentinel, byte 2 = received count, byte 3 = pad,
#   byte 4..  = one received character per byte.
cat > "$work/verify.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

local function report()
    local base = 0xE19BC0
    local scb0 = mem:read_u8(0xE19D00)
    local bytes = {}
    for i = 0, 39 do
        bytes[#bytes + 1] = string.format("%02X", mem:read_u8(base + i))
    end
    io.write(string.format("VERIFY-IIGS-INPUT frame=%d scb0=%02X row=%s\n",
                           frame, scb0, table.concat(bytes)))
    io.flush()
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("KEYS") end},
    {3660, function() press(key_cmd) end},
    {3666, function() nat:post("o") end},
    {3720, function() release(key_cmd) end},
    {$typeFrame, function() nat:post("$target") end},
    {$readFrame, function() report(); 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

cd "$work"
out=$(QT_QPA_PLATFORM=offscreen SDL_VIDEODRIVER=dummy SDL_AUDIODRIVER=dummy \
    timeout 300 mame apple2gs \
        -rompath "$rompath" \
        -flop3 "$work/boot.po" -flop4 "$work/joey.2mg" \
        -video none -sound none -nothrottle \
        -autoboot_script "$work/verify.lua" </dev/null 2>&1) || true

line=$(echo "$out" | grep -E '^VERIFY-IIGS-INPUT ' | tail -1)
echo "$line"
if [ -z "$line" ]; then
    echo "verify-iigs-input: FAIL - no report (boot/launch failed)" >&2
    echo "$out" | tail -15 >&2
    exit 1
fi

scb0=$(echo "$line" | sed -E 's/.*scb0=([0-9A-Fa-f]+).*/\1/')
if [ $((16#$scb0)) -ge 16 ]; then
    echo "verify-iigs-input: FAIL (KEYS never launched - SCB[0]=0x$scb0)" >&2
    exit 1
fi

row=$(echo "$line" | sed -E 's/.*row=([0-9A-Fa-f]+).*/\1/')
expect="A5A5"
count=$(printf '%02X' ${#target})
expect+="$count"
expect+="00"
expect+=$(printf '%s' "$target" | od -A n -t x1 | tr -d ' \n' | tr 'a-f' 'A-F')
got=${row:0:${#expect}}
if [ "$got" = "$expect" ]; then
    echo "verify-iigs-input: PASS (typed \"$target\", all ${#target} chars arrived via jlInputGetChar)"
else
    echo "verify-iigs-input: FAIL" >&2
    echo "  expected row prefix: $expect" >&2
    echo "  got:                 $got" >&2
    exit 1
fi
