#!/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-win32-joy.sh - Joystick gate for the Win32 port: both sticks, every # direction, both buttons and every release, driven through two virtual # gamepads under Wine and read back from what examples/joy draws; then the # pads unplugged while JOY runs. # # The port (src/hosted/win32/win32Backend.c) reads JOYSTICKID1 and # JOYSTICKID2 through joyGetPosEx once a virtual frame, their X and Y scaled # from the driver's range and buttons 1 and 2. Under Wine those come from its # bus driver (winebus, through the host's SDL); the pads are Linux uinput # devices laid out as Xbox 360 pads (scripts/lib/padGate.sh), the only ones # SDL is let see. JOY runs headless under Wine (scripts/lib/wineGate.sh) at # one window pixel per stage pixel, and window grabs go through # tests/gate/joyScreen.c (scripts/lib/joyGate.sh). Removing the pads must # leave both sticks disconnected, and Escape must then end JOY. # # Usage: scripts/verify-win32-joy.sh # Env: JOY_SHOTS also keep the screenshots in this folder # Requires: Wine, write access to /dev/uinput, Xvfb, xdotool, ImageMagick; # build/win32/bin/JOY.EXE (make win32). 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" source "$repo/scripts/lib/wineGate.sh" wineNeed JOY_LABEL=verify-win32-joy JOY_SCALE=1 program=$(joeyExampleProgram joy win32) unplugSeconds=3 # the pads gone until Wine has dropped them exitSeconds=5 # Escape until JOY has gone [ -f "$program" ] || { echo "$JOY_LABEL: build JOY.EXE first (make win32)" >&2; exit 2; } JOY_WORK=$(mktemp -d -t joeylib-win32-joy.XXXXXX) win="" cleanup() { padStop wineStop rm -rf "$JOY_WORK" } trap cleanup EXIT joyShot() { import -window "$win" "$1" 2> /dev/null } wineStart "$JOY_WORK" padStart "$JOY_WORK" # Wine's services (its bus driver among them) start with the first program # and take its environment. for setting in "${PAD_ONLY_ENV[@]}"; do export "${setting?}" done JOEYLIB_SCALE=1 JOEYLIB_ASPECT=square wineRun "$program" win=$(wineWindow JOY) || { echo "$JOY_LABEL: FAIL - JOY's window did not come up" >&2; cat "$JOY_WORK/wine.log" >&2; exit 1; } xdotool windowfocus --sync "$win" 2> /dev/null || true sleep 2 padOrder joyCheck "rest" "A=$JOY_REST B=$JOY_REST" joyRunSteps "${JOY_STEPS_TWO_STICKS[@]}" padStop sleep "$unplugSeconds" joyCheck "pads unplugged" "A=$JOY_ABSENT B=$JOY_ABSENT" xdotool key Escape for ((waited = 0; waited < exitSeconds; waited++)); do joeyAlive "$WINE_PID" || break sleep 1 done joeyAlive "$WINE_PID" && joyFail "Escape did not end JOY" joyResult "$JOY_LABEL" "both pads, every direction, both buttons and every release; unplugged, both sticks gone; Escape ends JOY"