#!/usr/bin/env bash # Part of JoeyLib, Copyright (c) 2026 Scott Duensing, under the MIT License. # See LICENSE.md for license information. # SPDX-License-Identifier: MIT # # verify-iigs-keys.sh - Headless gate for the IIgs's key predicates, the # asm jlKeyDown and jlKeyPressed (JL_HAS_INPUT_PREDICATES, joeyDraw.s). # Boots GS/OS under MAME and launches the KEYS example off joey.2mg, which # lights a key's cell while jlKeyDown says it is held and quits on # jlKeyPressed(JL_KEY_ESCAPE). Holds A on the emulated ADB keyboard and # reads the A cell straight out of SHR memory: unlit before, lit while # held, unlit after. Then presses Escape: KEYS must quit to the Finder, # whose 640-mode SCB replaces KEYS' 320-mode one. # # Usage: scripts/verify-iigs-keys.sh # Requires: ./install.sh install iigs; build/iigs/bin/joey.2mg built # with the current KEYS (make iigs-disk). set -euo pipefail repo=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd) source "$repo/scripts/lib/joeyEnv.sh" joeyNeed MAME mame joeyNeed IIGS_ROMPATH iigsFirmware joeyNeed GSOS_SYSTEM_DISK iigsFirmware sys_disk=$GSOS_SYSTEM_DISK data_disk=$repo/build/iigs/bin/joey.2mg for f in "$sys_disk" "$data_disk"; do [ -f "$f" ] || { echo "verify-iigs-keys: missing $f (run 'make iigs-disk')" >&2; exit 2; } done work=$(mktemp -d -t joeylib-keys-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-input.sh. The A cell is # KEYS' row 2, column 0 (examples/keys: MARGIN 2, CELL 28x26, GAP 4); its # middle, x 16 y 75, is the SHR byte $E1/2000 + 75*160 + 8 = $E1/4EE8: # $11 unlit (COLOR_UNLIT), $22 lit (COLOR_LIT). SCB 0 is $E1/9D00. 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 key_a = field(":macadb:KEY0", "a A") local key_esc = field(":macadb:KEY3", "Esc") 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(tag) io.write(string.format("VERIFY-IIGS-KEYS %s scb0=%02X cell=%02X\n", tag, mem:read_u8(0xE19D00), mem:read_u8(0xE14EE8))) 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}, {6600, function() report("before") end}, {6610, function() press(key_a) end}, {6700, function() report("held") end}, {6710, function() release(key_a) end}, {6800, function() report("released") end}, {6810, function() press(key_esc) end}, {6830, function() release(key_esc) end}, {9000, function() report("escape"); 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 "$IIGS_ROMPATH" \ -flop3 "$work/boot.po" -flop4 "$work/joey.2mg" \ -video none -sound none -nothrottle \ -autoboot_script "$work/verify.lua" &1) || true report=$(echo "$out" | grep -E '^VERIFY-IIGS-KEYS ' || true) echo "$report" value() { echo "$report" | grep " $1 " | sed -E "s/.*$2=([0-9A-Fa-f]+).*/\1/" } fails=() [ "$(value before scb0)" = "00" ] || fails+=("KEYS never launched (SCB 0 $(value before scb0))") [ "$(value before cell)" = "11" ] || fails+=("the A cell lit before A was held ($(value before cell))") [ "$(value held cell)" = "22" ] || fails+=("jlKeyDown: the A cell unlit while A was held ($(value held cell))") [ "$(value released cell)" = "11" ] || fails+=("jlKeyDown: the A cell still lit after A was let go ($(value released cell))") scb=$(value escape scb0) [ -n "$scb" ] && [ $((16#$scb)) -ge 128 ] || fails+=("jlKeyPressed: Escape did not quit KEYS (SCB 0 ${scb:-none})") if [ ${#fails[@]} -eq 0 ]; then echo "verify-iigs-keys: PASS (A lit only while held; Escape quit KEYS)" exit 0 fi for f in "${fails[@]}"; do echo "verify-iigs-keys: FAIL - $f" >&2 done exit 1