#!/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 perf capture for the Atari ST family (Hatari). # # Runs UBER.PRG under Hatari (fast-forward, no sound) on a private Xvfb # display, polling joeylog.txt until UBER prints its "press any key to # exit" completion marker (or a wall-clock timeout), then kills the # emulator. # # The machine picks the build: a plain ST or a Mega ST runs the ST build # (make atarist, build/atarist), an STe or Mega STe the STe build (make # ste, build/ste: BLiTTER, DMA sound, 4-bit palette, and the Mega STe's # 16 MHz). Both builds' hashes must match the ST's golden; the rates # differ. # # UBER writes "UBER: : N iters / M frames = K ops/sec" lines to # joeylog.txt in its CWD == the GEMDOS drive C: == the bin dir, so the # log lands directly in build//bin/joeylog.txt (for the ST build # where tools/uber-perf-table expects it). A copy is kept as # joeylog-MACHINE.txt beside it, so runs on several machines can be # compared afterwards. # # scripts/bench-atarist.sh # the ST build on a plain ST, default 90s timeout # scripts/bench-atarist.sh megast # the ST build on a Mega ST # scripts/bench-atarist.sh ste # the STe build on an STe # scripts/bench-atarist.sh megaste # the STe build on a Mega STe # TIMEOUT=120 scripts/bench-atarist.sh # override # BENCH_PRG / BENCH_BIN_DIR # another program and its folder # # (UBERPROB, verify-atarist-display.sh) # # NOTE: requires the ST supervisor-mode fix in src/atarist/hal.c # (jlpInit Super(0L)); without it UBER bus-errors on the first present. set -euo pipefail repo=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd) source "$repo/scripts/lib/joeyEnv.sh" joeyNeed HATARI hatari joeyNeed EMUTOS_IMG emutos machine=${1:-st} case $machine in st|megast) build=atarist ;; ste|megaste) build=ste ;; *) echo "usage: scripts/bench-atarist.sh [st|megast|ste|megaste]" >&2; exit 2 ;; esac bin_dir=${BENCH_BIN_DIR:-$repo/build/$build/bin} prg=${BENCH_PRG:-UBER.PRG} tos=$EMUTOS_IMG log=$bin_dir/joeylog.txt timeout_s=${TIMEOUT:-90} if [[ ! -f $bin_dir/$prg ]]; then echo "$prg not built. Run 'make $build' first." >&2 exit 1 fi if [[ ! -f $tos ]]; then echo "TOS ROM missing: $tos" >&2 exit 1 fi rm -f "$log" display=:$((90 + RANDOM % 9)) Xvfb "$display" -screen 0 800x600x24 -nolisten tcp >/dev/null 2>&1 & xvfb_pid=$! sleep 0.4 cleanup() { joeyStop "$hat_pid" kill "$xvfb_pid" 2>/dev/null || true wait 2>/dev/null || true } trap cleanup EXIT echo "bench-atarist: running the $build build's $prg headless on a $machine (timeout ${timeout_s}s)..." >&2 DISPLAY=$display "$HATARI" \ --machine "$machine" \ --tos "$tos" \ --harddrive "$bin_dir" \ --gemdos-drive C \ --drive-a off --drive-b off \ --sound off \ --fast-forward on \ --frameskips 4 \ --auto "C:\\$prg" >/tmp/bench-atarist-hatari.log 2>&1 & hat_pid=$! # Poll for the completion marker UBER flushes just before its key wait. waited=0 while (( waited < timeout_s )); do if [[ -f $log ]] && grep -q "press any key to exit" "$log"; then break fi sleep 1 (( waited++ )) || true done if [[ ! -f $log ]]; then echo "bench-atarist: FAIL -- no joeylog.txt produced" >&2 exit 1 fi ops=$(grep -c "ops/sec" "$log" || true) done_marker=$(grep -c "press any key to exit" "$log" || true) if (( done_marker == 0 )); then echo "bench-atarist: WARNING -- timed out before completion marker (partial capture)" >&2 fi cp "$log" "$bin_dir/joeylog-$machine.txt" echo "bench-atarist: captured $ops op lines (complete=$done_marker) on a $machine in ${waited}s" >&2 echo " -> $log (and joeylog-$machine.txt)" >&2 grep "UBER:" "$log" | sed 's/ | hash=.*//' || true