joeylib2/scripts/verify-dos-joy.sh

105 lines
4 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-joy.sh - Joystick gate for DOS: both sticks, every direction,
# both buttons and every release, driven through DOSBox Staging's emulated
# game port and read back from what examples/joy draws; and no joystick at
# all when the game port is empty.
#
# The port (src/dos/input.c) reads the game port through the BIOS, INT 15h
# function 84h: the switches, then the four positions, both sticks connected
# while the BIOS answers. DOSBox's joysticktype 4axis gives it two sticks on
# one port, moved by host keys through a mapper file
# (scripts/lib/dosboxJoy.sh); the raw screenshots go through
# scripts/lib/joyScreen.py (scripts/lib/joyGate.sh). With joysticktype none
# the BIOS says there is no game port and JOY must show both sticks
# disconnected. Each run ends with Escape, which must end JOY (DOSBox exits
# after it).
#
# Usage: scripts/verify-dos-joy.sh
# Env: JOY_SHOTS also keep the screenshots in this folder
# Requires: DOSBox Staging, Xvfb, xdotool, python3 + PIL;
# build/dos/bin/JOY.EXE (make dos).
set -uo pipefail
repo=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)
source "$repo/scripts/lib/joeyEnv.sh"
source "$repo/scripts/lib/joyGate.sh"
source "$repo/scripts/lib/dosboxJoy.sh"
joeyNeed DOSBOX dosbox
JOY_LABEL=verify-dos-joy
program="$repo/build/dos/bin/JOY.EXE"
wall=240 # hard cap on each DOSBox run, whatever happens to this script
bootSeconds=12 # DOS booting and JOY drawing on the emulated 386SX-16
exitSeconds=10 # Escape until DOSBox, which exits after JOY, has gone
[ -f "$program" ] || { echo "$JOY_LABEL: build JOY.EXE first (make dos)" >&2; exit 2; }
JOY_WORK=$(mktemp -d -t joeylib-dos-joy.XXXXXX)
guard=""
dosbox=""
xvfb=""
cleanup() {
joeyStop "$dosbox" "$guard" "$xvfb" 2> /dev/null
rm -rf "$JOY_WORK"
}
trap cleanup EXIT
# boot RUN JOYTYPE -- JOY in DOSBox with joysticktype JOYTYPE; sets guard,
# dosbox and DOSBOX_JOY_WINDOW.
boot() {
local dir="$JOY_WORK/$1"
mkdir -p "$dir/xdg" "$dir/shots"
dosboxJoyMapper "$dir/mapper.txt"
DOSBOX_JOY_SHOTS="$dir/shots"
XDG_CONFIG_HOME="$dir/xdg" DISPLAY="$DOSBOX_JOY_DISPLAY" SDL_AUDIODRIVER=dummy \
timeout -s KILL "$wall" "$DOSBOX" "${JOEY_DOSBOX_ISOLATE[@]}" \
--conf "$repo/scripts/dosbox-386sx16.conf" --set "joysticktype=$2" "${DOSBOX_JOY_SET_ARGS[@]}" \
--set "mapperfile=$dir/mapper.txt" --set "capture_dir=$dir/shots" \
-c "MOUNT C \"$(dirname "$program")\"" -c "C:" -c "$(basename "$program")" -c "EXIT" \
> "$dir/dosbox.log" 2>&1 &
guard=$!
dosbox=$(joeyChild "$guard")
sleep "$bootSeconds"
DOSBOX_JOY_WINDOW=$(joeyFindWindow "$DOSBOX_JOY_DISPLAY" "$dosbox")
[ -n "$DOSBOX_JOY_WINDOW" ] || return 1
DISPLAY="$DOSBOX_JOY_DISPLAY" xdotool windowactivate --sync "$DOSBOX_JOY_WINDOW" 2> /dev/null || true
}
# quit -- Escape, which must end JOY and with it DOSBox.
quit() {
local waited
dosboxJoyTap escape
for ((waited = 0; waited < exitSeconds; waited++)); do
joeyAlive "$guard" || break
sleep 1
done
joeyAlive "$guard" && joyFail "Escape did not end JOY"
joeyStop "$dosbox" "$guard" 2> /dev/null
dosbox=""
guard=""
}
DOSBOX_JOY_DISPLAY=":$((RANDOM % 400 + 4700))"
Xvfb "$DOSBOX_JOY_DISPLAY" -screen 0 1024x768x24 -nolisten tcp > /dev/null 2>&1 &
xvfb=$!
sleep 1
# 1. Both sticks on the game port.
boot sticks 4axis || { echo "$JOY_LABEL: FAIL - DOSBox with JOY did not come up" >&2; exit 1; }
joyCheck "rest" "A=$JOY_REST B=$JOY_REST"
joyRunSteps "${JOY_STEPS_TWO_STICKS[@]}"
quit
# 2. No game port.
boot none none || { echo "$JOY_LABEL: FAIL - DOSBox with JOY and no joystick did not come up" >&2; exit 1; }
joyCheck "no joystick" "A=$JOY_ABSENT B=$JOY_ABSENT"
quit
joyResult "$JOY_LABEL" "both sticks, every direction, both buttons and every release; no joystick without a game port; Escape ends JOY"