joeylib2/scripts/verify-dos-mouse.sh

126 lines
4.6 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-dos-mouse.sh - Headless mouse acceptance gate for the DOS port.
# The port has the mouse driver call it on every move and button change
# (INT 33h function 0Ch, a DPMI real-mode callback, src/dos/input.c); a
# callback that never runs leaves the pointer where it started. Runs
# KEYS.EXE in DOSBox Staging under Xvfb with the mouse captured from the
# start, moves it with xdotool (real X pointer motion), and decodes KEYS's
# mouse verification scanline (row 199: 5A5A, the button flags, X, Y as
# nibble pixels) from a raw screenshot after each step. Covered: the start
# at the stage's middle, a move each way on both axes, clamping at all
# four edges, an odd column, and press and release of the left and right
# buttons.
# DOSBox scales host motion into mickeys its own way, so a move is checked
# by its direction and only the clamps by position, and a one-pixel nudge
# by landing on an odd column: in mode 13h the driver steps X by 2 in a
# 640-wide virtual screen, which the port halves, so every column counts.
#
# Usage: scripts/verify-dos-mouse.sh
# Requires: DOSBox Staging (install.sh install emulator:dos), Xvfb, xdotool;
# build/dos/bin/KEYS.EXE (make dos).
set -uo pipefail
repo=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)
source "$repo/scripts/lib/joeyEnv.sh"
source "$repo/scripts/lib/dosboxKeys.sh"
joeyNeed DOSBOX dosbox
bin_dir=$repo/build/dos/bin
conf=$repo/scripts/dosbox-386sx16.conf
label=verify-dos-mouse
[ -f "$bin_dir/KEYS.EXE" ] || { echo "$label: build KEYS.EXE first (make dos)" >&2; exit 2; }
work=$(mktemp -d -t joeylib-dos-mouse.XXXXXX)
display_num=$((RANDOM % 500 + 300))
cleanup() {
joeyStop "${dosbox_pid:-}"
[ -n "${xvfb_pid:-}" ] && kill "$xvfb_pid" 2>/dev/null
rm -rf "$work"
}
trap cleanup EXIT
mkdir -p "$work/shots"
dosboxKeysMapper "$work/mapper.txt"
Xvfb ":$display_num" -screen 0 1024x768x24 >/dev/null 2>&1 &
xvfb_pid=$!
sleep 1
XDG_CONFIG_HOME="$work/xdg" DISPLAY=":$display_num" "$DOSBOX" "${JOEY_DOSBOX_ISOLATE[@]}" \
--conf "$conf" \
--set "capture_dir=$work/shots" \
--set "mapperfile=$work/mapper.txt" \
--set "mouse_capture=onstart" \
-c "MOUNT C $bin_dir" -c "C:" -c "KEYS.EXE" \
>"$work/dosbox.log" 2>&1 &
dosbox_pid=$!
# Let DOS boot and KEYS reach its poll loop on the simulated 386SX-16.
sleep 12
win=$(joeyFindWindow ":$display_num" "$dosbox_pid")
if [ -z "$win" ]; then
echo "$label: FAIL - DOSBox window not found" >&2
exit 1
fi
DISPLAY=":$display_num" xdotool windowactivate --sync "$win" 2>/dev/null || true
# The mouse row of a fresh screenshot as "flags x y" (hex flags).
readRow() {
local png="$work/$1.png"
dosboxShot ":$display_num" "$win" "$work/shots" "$png" || return 1
"$(joeyTool dosRow)" mouse "$png"
}
fails=()
step() {
local tag="$1"
local row
shift
if [ $# -gt 0 ]; then
DISPLAY=":$display_num" xdotool "$@"
sleep 1
fi
if ! row=$(readRow "$tag"); then
fails+=("$tag: no mouse row in the screenshot")
row="---- -1 -1"
fi
read -r flags mx my <<< "$row"
echo " $tag: flags=$flags x=$mx y=$my"
}
step start
[ "$flags $mx $my" = "1000 160 100" ] || fails+=("start: expected flags 1000 at 160,100")
step upLeft mousemove_relative -- -60 -40
[ "$flags" = "1000" ] && [ "$mx" -lt 160 ] && [ "$my" -lt 100 ] || fails+=("a move up and left did not arrive")
lastX=$mx
lastY=$my
step downRight mousemove_relative -- 120 80
[ "$flags" = "1000" ] && [ "$mx" -gt "$lastX" ] && [ "$my" -gt "$lastY" ] || fails+=("a move down and right did not arrive")
step topLeft mousemove_relative -- -2000 -2000
[ "$flags $mx $my" = "1000 0 0" ] || fails+=("not held at the top left (0,0)")
step nudge mousemove_relative -- 1 0
[ "$flags" = "1000" ] && [ $((mx % 2)) -eq 1 ] || fails+=("a one-pixel nudge did not reach an odd column")
step bottomRight mousemove_relative -- 2000 2000
[ "$flags $mx $my" = "1000 319 199" ] || fails+=("not held at the bottom right (319,199)")
step leftDown mousedown 1
[ "$flags" = "1100" ] || fails+=("the left button down not seen")
step leftUp mouseup 1
[ "$flags" = "1000" ] || fails+=("the left button up not seen")
step rightDown mousedown 3
[ "$flags" = "1010" ] || fails+=("the right button down not seen")
step rightUp mouseup 3
[ "$flags" = "1000" ] || fails+=("the right button up not seen")
if [ ${#fails[@]} -eq 0 ]; then
echo "$label: PASS (moves both ways, all four edges, every column, both buttons down and up)"
exit 0
fi
for f in "${fails[@]}"; do
echo "$label: FAIL - $f" >&2
done
exit 1