161 lines
6.2 KiB
Bash
Executable file
161 lines
6.2 KiB
Bash
Executable file
#!/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-mouse.sh - Headless gate for the IIgs's mouse buttons. Every
|
|
# port has two, and the IIgs's ADB mouse has one: a left click made with
|
|
# Ctrl held is the right button (src/core/input.c, mouseCtrlClick), read
|
|
# through the asm snapshot and predicates (joeyDraw.s). Boots GS/OS under
|
|
# MAME and launches the KEYS example off joey.2mg, which stamps the mouse's
|
|
# state on its stage row 199: the sentinel 5A5A, then present, left,
|
|
# right, and a zero nibble. Presses the emulated mouse button and Ctrl in
|
|
# turn and reads the row straight out of SHR memory after each:
|
|
#
|
|
# start present, no button
|
|
# click left
|
|
# click let go none
|
|
# Ctrl-click right, not left
|
|
# Ctrl let go first still right (until the button is let go)
|
|
# Ctrl-click let go none
|
|
# click, then Ctrl left: Ctrl after the press changes nothing
|
|
# both let go none
|
|
#
|
|
# Then Escape: KEYS must quit to the Finder.
|
|
#
|
|
# Usage: scripts/verify-iigs-mouse.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
|
|
|
|
label=verify-iigs-mouse
|
|
sys_disk=$GSOS_SYSTEM_DISK
|
|
data_disk=$repo/build/iigs/bin/joey.2mg
|
|
|
|
for f in "$sys_disk" "$data_disk"; do
|
|
[ -f "$f" ] || { echo "$label: missing $f (run 'make iigs-disk')" >&2; exit 2; }
|
|
done
|
|
|
|
work=$(mktemp -d -t joeylib-mouse-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-keys.sh. KEYS' mouse row is
|
|
# stage row 199, the SHR bytes from $E1/2000 + 199*160 = $E1/9C60, two
|
|
# nibble pixels a byte: 5A 5A, then the flags word (present 1000, left
|
|
# 0100, right 0010). SCB 0 is $E1/9D00. Each step waits 90 frames (1.5 s)
|
|
# before the row is read: KEYS restamps it at its next frame.
|
|
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_ctrl = field(":macadb:KEY3", "Control")
|
|
local key_esc = field(":macadb:KEY3", "Esc")
|
|
local button = field(":macadb:MOUSE0", "Mouse Button")
|
|
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)
|
|
local row = ""
|
|
for i = 0, 3 do
|
|
row = row .. string.format("%02X", mem:read_u8(0xE19C60 + i))
|
|
end
|
|
io.write(string.format("VERIFY-IIGS-MOUSE %s scb0=%02X row=%s\n", tag, mem:read_u8(0xE19D00), row))
|
|
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("start") end},
|
|
{6610, function() press(button) end},
|
|
{6700, function() report("click") end},
|
|
{6710, function() release(button) end},
|
|
{6800, function() report("clickLetGo") end},
|
|
{6810, function() press(key_ctrl) end},
|
|
{6840, function() press(button) end},
|
|
{6930, function() report("ctrlClick") end},
|
|
{6940, function() release(key_ctrl) end},
|
|
{7030, function() report("ctrlLetGoFirst") end},
|
|
{7040, function() release(button) end},
|
|
{7130, function() report("ctrlClickLetGo") end},
|
|
{7140, function() press(button) end},
|
|
{7170, function() press(key_ctrl) end},
|
|
{7260, function() report("clickThenCtrl") end},
|
|
{7270, function() release(button) end},
|
|
{7280, function() release(key_ctrl) end},
|
|
{7370, function() report("bothLetGo") end},
|
|
{7380, function() press(key_esc) end},
|
|
{7400, function() release(key_esc) end},
|
|
{9600, 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" </dev/null 2>&1) || true
|
|
|
|
report=$(echo "$out" | grep -E '^VERIFY-IIGS-MOUSE ' || true)
|
|
echo "$report"
|
|
value() {
|
|
echo "$report" | grep " $1 " | sed -E "s/.*$2=([0-9A-Fa-f]+).*/\1/"
|
|
}
|
|
fails=()
|
|
[ "$(value start scb0)" = "00" ] || fails+=("KEYS never launched (SCB 0 $(value start scb0))")
|
|
# step, the row it must show, what that means
|
|
for check in "start 5A5A1000 present, no button" \
|
|
"click 5A5A1100 the left button" \
|
|
"clickLetGo 5A5A1000 no button" \
|
|
"ctrlClick 5A5A1010 the right button" \
|
|
"ctrlLetGoFirst 5A5A1010 the right button" \
|
|
"ctrlClickLetGo 5A5A1000 no button" \
|
|
"clickThenCtrl 5A5A1100 the left button" \
|
|
"bothLetGo 5A5A1000 no button"; do
|
|
read -r step want meaning <<< "$check"
|
|
got=$(value "$step" row)
|
|
[ "$got" = "$want" ] || fails+=("$step: row ${got:-none}, want $want ($meaning)")
|
|
done
|
|
scb=$(value escape scb0)
|
|
[ -n "$scb" ] && [ $((16#$scb)) -ge 128 ] || fails+=("Escape did not quit KEYS (SCB 0 ${scb:-none})")
|
|
if [ ${#fails[@]} -eq 0 ]; then
|
|
echo "$label: PASS (the mouse button is left, and right when Ctrl is held as it goes down, until it is let go; Escape quit KEYS)"
|
|
exit 0
|
|
fi
|
|
for f in "${fails[@]}"; do
|
|
echo "$label: FAIL - $f" >&2
|
|
done
|
|
exit 1
|