#!/usr/bin/env bash # captureDos.sh -- run a built DOS example in headless DOSBox via Xvfb # and snap a PNG of the simulated screen. Lets us verify the runtime # output without an interactive emulator session. # # scripts/captureDos.sh staxi /tmp/staxi.png # default 5s wait # scripts/captureDos.sh staxi /tmp/staxi.png 12 # 12s wait # # The wait time gives the program enough cycles to boot, draw, and # settle on a steady frame. Increase for slow boots / cold caches. set -euo pipefail if [[ $# -lt 2 || $# -gt 3 ]]; then echo "usage: $0 [wait-seconds]" >&2 exit 2 fi prog=$1 out=$2 wait_s=${3:-5} repo=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd) bin_dir=$repo/build/dos/bin conf=$repo/scripts/dosbox-386sx16.conf file=${prog^^}.EXE appdir=${prog^^} if [[ -f "$bin_dir/$appdir/$file" ]]; then mount_dir="$bin_dir/$appdir" elif [[ -f "$bin_dir/$file" ]]; then mount_dir="$bin_dir" else echo "captureDos: $file not found in $bin_dir" >&2 exit 1 fi display=:$((90 + RANDOM % 9)) Xvfb "$display" -screen 0 800x600x24 -nolisten tcp & xvfb_pid=$! sleep 0.3 trap 'kill $xvfb_pid 2>/dev/null || true; kill $dosbox_pid 2>/dev/null || true' EXIT # Mount with an explicit -c, not by handing DOSBox the directory as a # positional argument: 0.74-3 ignored it here and dropped the program at # "Drive C does not exist", which looks exactly like a program that # failed to start. The cycles override has to be one argv entry too -- # unquoted it split into three words and ate the path. dosboxArgs=(-conf "$conf" -set "mouse_capture=seamless") if [[ -n ${CYCLES:-} ]]; then dosboxArgs+=(-set "cpu cycles=${CYCLES}") fi dosboxArgs+=(-c "mount c \"$mount_dir\"" -c "C:" -c "$file") DISPLAY=$display SDL_VIDEO_X11_VISUALID="" \ dosbox "${dosboxArgs[@]}" >/tmp/captureDos-dosbox.log 2>&1 & dosbox_pid=$! # Wait for DOSBox to boot the program and settle. sleep "$wait_s" DISPLAY=$display import -window root -screen "$out" 2>/dev/null echo "captureDos: wrote $out" # DOSBox is still running -- the trap will clean it up.