#!/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 # # Headless UBER run for DVX (DOSBox Staging, DVX's own emulator setup). # # Stages a scratch DVX (scripts/lib/dvxGate.sh) whose desktop is UBER, boots # it in DOSBox Staging under Xvfb, and waits for UBER's "press any key to # exit" line in its joeylog.txt -- which a DVX program writes to its settings # folder, CONFIG\APPS\\UBER on the staged drive. The log is copied to # build/dvx/bin/joeylog.txt (tools/diff-uber-hashes and tools/uber-perf-table # read it from there) and DOSBox is stopped. # # The stage is the DOS stage, so the hashes must equal the DOS port's: # scripts/bench-dvx.sh && tools/diff-uber-hashes tests/goldens/uber/dos.txt build/dvx/bin/joeylog.txt # The ops/sec are the emulated machine's at DOSBox's full host speed, not a # reference machine's: compare them only run against run. # # --full-screen runs UBER on the whole screen (the port's full-screen # setting staged as Game > Full Screen leaves it, DVX's exclusive mode at # 320x200x8, VGA mode 13h here), and fails unless DVX.LOG says the mode was # set: the same hashes, the full-screen present's timings. # # --square opens the window with square pixels (Game > Square Pixels, staged # the same way) instead of 4:3. # # --probe runs UBER's probe build instead (make dvx builds it: its UBER_PROBE # rows, the display parity row among them, at one frame per timed op), its # log copied to build/dvx/probe/joeylog.txt; scripts/verify-dvx-display.sh # judges it. Either way DVX.LOG is copied beside the log, as dvx.log. The # desktop is dvxGate.sh's (DVX_VIDEO_W/H/BPP). # # scripts/bench-dvx.sh # default 600 s timeout # scripts/bench-dvx.sh --full-screen # on the whole screen # scripts/bench-dvx.sh --probe # the probe build (with --full-screen or --square too) # TIMEOUT=900 scripts/bench-dvx.sh # override set -euo pipefail repo=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd) source "$repo/scripts/lib/joeyEnv.sh" source "$repo/scripts/lib/dvxGate.sh" joeyNeed DOSBOX dosbox joeyNeed DVX_ROOT dvx fullScreen=0 square=0 program=uber appDir=$(dvxAppDir uber) out=$DVX_BIN/$DVX_LOG_NAME for arg in "$@"; do case "$arg" in --full-screen) fullScreen=1 ;; --square) square=1 ;; --probe) program=uberprob appDir=$DVX_PROBE_DIR/apps/$DVX_VENDOR/$program out=$DVX_PROBE_DIR/$DVX_LOG_NAME ;; *) echo "usage: scripts/bench-dvx.sh [--full-screen] [--square] [--probe]" >&2 exit 2 ;; esac done timeoutSeconds=${TIMEOUT:-600} # The emulator's hard cap, a little past the wait, whatever this script does. wallSeconds=$((timeoutSeconds + 30)) dvxLogOut=${out%/*}/dvx.log doneLine="press any key to exit" if [ ! -f "$appDir/$program.app" ]; then echo "bench-dvx: $appDir/$program.app is missing; run: make dvx" >&2 exit 2 fi work=$(mktemp -d -t joeylib-bench-dvx.XXXXXX) guard="" dosbox="" xvfb="" # 2>/dev/null: bash reports the SIGKILLed timeout wrapper as "Killed". cleanup() { joeyStop "$dosbox" "$guard" "$xvfb" 2> /dev/null rm -rf "$work" } trap cleanup EXIT dvxStage "$work/c" "$appDir" switches=() [ "$fullScreen" = 1 ] && switches+=("$DVX_SETTINGS_FULL_SCREEN") [ "$square" = 1 ] && switches+=("$DVX_SETTINGS_SQUARE") if [ ${#switches[@]} -gt 0 ]; then dvxSettings "$work/c" "$program" "${switches[@]}" fi dvxDosboxConf "$work/dosbox.conf" "$work/c" mkdir -p "$work/xdg" rm -f "$out" "$dvxLogOut" display=":$((RANDOM % 400 + 1700))" Xvfb "$display" -screen 0 1024x768x24 -nolisten tcp > /dev/null 2>&1 & xvfb=$! sleep 1 echo "bench-dvx: running $program in DVX headless on ${DVX_VIDEO_W}x${DVX_VIDEO_H}x${DVX_VIDEO_BPP} (timeout ${timeoutSeconds}s)..." >&2 XDG_CONFIG_HOME="$work/xdg" DISPLAY="$display" SDL_AUDIODRIVER=dummy \ timeout -s KILL "$wallSeconds" "$DOSBOX" "${JOEY_DOSBOX_ISOLATE[@]}" \ --conf "$work/dosbox.conf" > "$work/dosbox.log" 2>&1 & guard=$! dosbox=$(joeyChild "$guard" || true) start=$SECONDS log=$(dvxAwaitLog "$work/c" "$program" "$doneLine" "$timeoutSeconds" "$guard" || true) waited=$((SECONDS - start)) if [ -z "$log" ]; then log=$(dvxProgramLog "$work/c" "$program") fi if [ -z "$log" ]; then echo "bench-dvx: FAIL -- $program wrote no joeylog.txt (DVX.LOG follows)" >&2 dvxDvxLog "$work/c" >&2 exit 1 fi tr -d '\r' < "$log" > "$out" joeyStop "$dosbox" "$guard" 2> /dev/null dosbox="" guard="" dvxDvxLogCopy "$work/c" "$dvxLogOut" if [ "$fullScreen" = 1 ] && ! dvxDvxLog "$work/c" 200 | grep -q "$DVX_FULL_SCREEN_LOG"; then echo "bench-dvx: FAIL -- --full-screen, but DVX.LOG has no \"$DVX_FULL_SCREEN_LOG\" (DVX.LOG follows)" >&2 dvxDvxLog "$work/c" >&2 exit 1 fi ops=$(grep -c "ops/sec" "$out" || true) if ! grep -q "$doneLine" "$out"; then echo "bench-dvx: WARNING -- timed out before the completion line (partial capture)" >&2 fi echo "bench-dvx: captured $ops op lines in ${waited}s" >&2 echo " -> $out" >&2 grep "UBER:" "$out" | sed 's/ | hash=.*//' || true