joeylib2/scripts/verify-sdl3-joy.sh

115 lines
4.1 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-sdl3-joy.sh - Joystick gate for the SDL3 port: both sticks, every
# direction, both buttons and every release, driven through two virtual
# gamepads and read back from what examples/joy draws; then the pads
# unplugged while JOY runs. Twice: once with gamepads SDL has a mapping for,
# once with plain joysticks it has none for.
#
# The port (src/hosted/sdl3/sdl3Backend.c) opens the first two gamepads or
# joysticks SDL offers as JL_JOYSTICK_0 and JL_JOYSTICK_1, plugged and
# unplugged as they come and go: a gamepad's left stick, its south button as
# button 0 and its east as button 1; a joystick SDL cannot map, its first
# two axes, its first hat, and its first two buttons. The pads are Linux
# uinput devices (scripts/lib/padGate.sh), laid out as Xbox 360 pads in the
# first pass and as two-button joysticks in the second, the only ones SDL is
# let see; JOY runs on a private Xvfb display through SDL's X11 driver at
# one window pixel per stage pixel, and window grabs go through
# scripts/lib/joyScreen.py (scripts/lib/joyGate.sh). Removing the pads must
# leave both sticks disconnected, and Escape must then end JOY.
#
# Usage: scripts/verify-sdl3-joy.sh
# Env: JOY_SHOTS also keep the screenshots in this folder
# Requires: write access to /dev/uinput, Xvfb, xdotool, ImageMagick,
# python3 + PIL; build/sdl3/bin/JOY (make sdl3).
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/padGate.sh"
JOY_LABEL=verify-sdl3-joy
JOY_SCALE=1
program=$(joeyExampleProgram joy sdl3)
wall=120 # hard cap on JOY, whatever happens to this script
readySeconds=10 # JOY's window up and drawn, with both pads open
exitSeconds=5 # Escape until JOY has gone
[ -f "$program" ] || { echo "$JOY_LABEL: build JOY first (make sdl3)" >&2; exit 2; }
JOY_WORK=$(mktemp -d -t joeylib-sdl3-joy.XXXXXX)
guard=""
xvfb=""
display=""
win=""
cleanup() {
padStop
joeyStop "$guard" "$xvfb" 2> /dev/null
rm -rf "$JOY_WORK"
}
trap cleanup EXIT
joyShot() {
DISPLAY="$display" import -window "$win" "$1" 2> /dev/null
}
# joyPass KIND -- the whole run with KIND's pads ("" for Xbox 360 pads,
# generic for plain joysticks): a fresh JOY, every step, the pads
# unplugged, and Escape.
joyPass() {
local waited
JOY_PASS="${1:-gamepad}"
win=""
mkdir -p "$JOY_WORK/$JOY_PASS"
padStart "$JOY_WORK/$JOY_PASS" "$1"
(cd "$(dirname "$program")" && exec env DISPLAY="$display" SDL_VIDEO_DRIVER=x11 SDL_AUDIO_DRIVER=dummy \
JOEYLIB_SCALE=1 JOEYLIB_ASPECT=square "${PAD_ONLY_ENV[@]}" timeout -s KILL "$wall" "$program") \
> "$JOY_WORK/$JOY_PASS/joy.log" 2>&1 &
guard=$!
for ((waited = 0; waited < readySeconds; waited++)); do
sleep 1
win=$(joeyFindWindow "$display" "$(joeyChild "$guard")") && break
done
if [ -z "$win" ]; then
echo "$JOY_LABEL: FAIL - $JOY_PASS: JOY's window did not come up" >&2
cat "$JOY_WORK/$JOY_PASS/joy.log" >&2
exit 1
fi
DISPLAY="$display" xdotool windowfocus --sync "$win" 2> /dev/null || true
sleep 1
echo "$JOY_LABEL: $JOY_PASS pass"
padOrder
joyCheck "rest" "A=$JOY_REST B=$JOY_REST"
joyRunSteps "${JOY_STEPS_TWO_STICKS[@]}"
padStop
sleep "$JOY_PRESS_SECONDS"
joyCheck "pads unplugged" "A=$JOY_ABSENT B=$JOY_ABSENT"
DISPLAY="$display" xdotool key Escape
for ((waited = 0; waited < exitSeconds; waited++)); do
joeyAlive "$guard" || break
sleep 1
done
joeyAlive "$guard" && joyFail "Escape did not end JOY"
joeyStop "$guard" 2> /dev/null
guard=""
}
display=":$((RANDOM % 400 + 5900))"
Xvfb "$display" -screen 0 1024x768x24 -nolisten tcp > /dev/null 2>&1 &
xvfb=$!
sleep 1
joyPass ""
joyPass generic
JOY_PASS=""
joyResult "$JOY_LABEL" "gamepads and unmapped joysticks: both sticks, every direction, both buttons and every release; unplugged, both sticks gone; Escape ends JOY"