#!/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-dvx-icon.sh - a DVX program's icon as Program Manager shows it. # # make gives every DVX program its icon (make/dvx.mk: tools/iconBake bmp, # a 32x32 24-bit BMP on DVX's grey, appended by dvxres as the icon32 # resource). DVX is staged with DRAW (examples/draw) installed and Program # Manager, DVX's own, as the desktop (scripts/lib/dvxGate.sh), and boots in # DOSBox Staging; Program Manager draws each program by its icon32, so # DOSBox's own screenshot must hold the baked icon: every pixel of it that # is not the grey, in its colour (give or take TOLERANCE: the desktop is # 16-bit). # # Usage: scripts/verify-dvx-icon.sh # Env: DVX_ICON_KEEP keep the last screenshot as build/dvx/dvx-icon.png # Exit: 0 PASS, 1 FAIL, 2 SKIP (DOSBox or DVX not installed, or DRAW not # built) # Requires: DOSBox Staging, Xvfb, xdotool, the dvx # component; DRAW (make dvx). set -uo 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 label=verify-dvx-icon program=draw # DVX's own desktop program, from its DVX.INI. progman=apps/kpunch/progman/progman.app wall=180 # hard cap on DOSBox, whatever happens to this script readySeconds=60 # DVX boot until its shell reports ready lookSeconds=60 # then screenshots until the icon shows shotSeconds=3 dvxNeedBuild "$program" icon=$repo/build/dvx/apps/$program/icon32.bmp [ -f "$icon" ] || { echo "$label: build DRAW first (make dvx)" >&2; exit 2; } work=$(mktemp -d -t joeylib-dvx-icon.XXXXXX) guard="" dosbox="" xvfb="" cleanup() { joeyStop "$dosbox" "$guard" "$xvfb" 2> /dev/null rm -rf "$work" } trap cleanup EXIT # iconShown PNG -- true when PNG holds the icon; prints the verdict. iconShown() { "$(joeyTool iconFind)" dvx "$1" "$icon" "$label" } display=":$((RANDOM % 400 + 2500))" Xvfb "$display" -screen 0 1024x768x24 -nolisten tcp > /dev/null 2>&1 & xvfb=$! sleep 1 dvxStage "$work/c" "$(dvxAppDir "$program")" dvxIniSet "$work/c/DVX/config/DVX.INI" "$progman" dvxDosboxConf "$work/dosbox.conf" "$work/c" printf '\n[capture]\ncapture_dir = %s\ndefault_image_capture_formats = raw\n' "$work/shots" >> "$work/dosbox.conf" mkdir -p "$work/xdg" "$work/shots" XDG_CONFIG_HOME="$work/xdg" DISPLAY="$display" SDL_AUDIODRIVER=dummy \ timeout -s KILL "$wall" "$DOSBOX" "${JOEY_DOSBOX_ISOLATE[@]}" \ --conf "$work/dosbox.conf" > "$work/dosbox.log" 2>&1 & guard=$! dosbox=$(joeyChild "$guard") ready="" for ((waited = 0; waited < readySeconds; waited++)); do if dvxDvxLog "$work/c" 200 | grep -q "DVX Shell ready"; then ready=1 break fi joeyAlive "$guard" || break sleep 1 done if [ -z "$ready" ]; then echo "$label: FAIL - DVX did not come up within ${readySeconds}s (DVX.LOG follows)" >&2 dvxDvxLog "$work/c" >&2 exit 1 fi win=$(joeyFindWindow "$display" "$dosbox") [ -n "$win" ] || { echo "$label: FAIL - DOSBox window not found" >&2; exit 1; } lookEnd=$((SECONDS + lookSeconds)) while [ "$SECONDS" -lt "$lookEnd" ]; do sleep "$shotSeconds" rm -f "$work/shots/"*.png # Ctrl+F5: DOSBox's screenshot hotkey. DISPLAY="$display" xdotool key --window "$win" ctrl+F5 sleep 1 png=$(find "$work/shots" -name '*.png' -print -quit) [ -n "$png" ] || continue [ -n "${DVX_ICON_KEEP:-}" ] && cp "$png" "$repo/build/dvx/dvx-icon.png" if iconShown "$png" > "$work/verdict"; then cat "$work/verdict" exit 0 fi done cat "$work/verdict" 2> /dev/null || echo "$label: FAIL - DOSBox took no screenshot" exit 1