#!/usr/bin/env bash # verify-all.sh - Run JoeyLib's gates, one kind or all of them, and summarise. # # Driven by `make verify` (all), `make verify-audio` and `make verify-serial`. # # Kinds, in the order `all` runs them: # host the shared layer on the host, no emulator: the new-port # template (blank), input, millis, save, serial, sfxmix, tilebank # golden UBER on each port, its 51 per-op surface hashes against # tests/goldens/uber (x68000 against the IIgs's, its own gate; # dvx against the DOS port's, whose stage it shows) # visual iigs: every launchable example on joey.2mg boots and draws # dvx: full screen -- UBER's hashes through a suspend and a # resume, and KEYS's row read off the 320x200 VGA screen, then # in its window, then on the whole screen again # tilebank each port: examples/tilebank loads the port's own .tbk bake # of the host fixture both ways, pixel-exact and with the host # gate's surface hash, and refuses every other target's bake (the # host half is check-tilebank.sh under `host`) # input each port: a typed string reaches jlInputGetChar byte-exact # (dvx: and the present shows it, decoded from the desktop) # audio six gates, two kinds: # iigs DOC wavetable + sound IRQ vector (register tap) # x68000 YM2151 noise + PPI port C + ADPCM rate (register tap) # atarist YM2149 write trace, with the pc (register tap) # amiga recorded sound, four loudness phases (Paula has no tap) # dos recorded sound, four loudness phases (SB has no tap) # dvx recorded sound, four loudness phases (DVX's mixer, SB) # serial the host check of the shared layer, then each port's loopback # (banner out, probe echoed back): # host scripts/check-serial.sh (no emulator) # iigs SCC modem port -> MAME null_modem # x68000 SCC channel A -> MAME null_modem # atarist Modem port -> Hatari pty # amiga serial.device -> FS-UAE TCP # dos COM1 -> DOSBox nullmodem # dvx COM1 through DVX's rs232 library -> DOSBox nullmodem # mouse x68000: deltas, clamps and buttons through the IOCS mouse # (and with serial streaming both ways on the same SCC) # save iigs: a SAVES/ blob written and read back through GS/OS # loss iigs: 4096 bytes through full-screen presents, lossless on the # modem port at 9600 and a Super Serial Card at 2400 # disk iigs: the one-disk STAXI (ROM 3 and ROM 01) and AGI images boot # and draw # # `all` first BUILDS every selected port (make , and iigs-disk plus the # loss probes and game disks for the IIgs), stopping on a build failure, then # runs every kind. A gate for a port that was not selected is left out. # # SEQUENTIAL, deliberately. The recording audio gates drive the emulator on # wall-clock sleeps and grade fixed time windows of the capture, so a # second emulator competing for CPU can slide a phase boundary and fail a # gate that is actually fine. Running several emulators at once also makes # the timing-sensitive register gates noisier. # # Exit codes, distinguishing "it works" from "it did not run": # 0 every selected gate PASSED # 1 at least one gate FAILED (a real defect), or an `all` build failed # 3 no failures, but at least one gate SKIPPED for a missing # prerequisite -- an unbuilt port or absent emulator. Non-zero on # purpose: a run that quietly tested nothing must not look green. # A gate reached through make cannot tell a skip from a failure (make # exits 2 for both), so those count as failures; `all` builds their # prerequisites first, so a missing one is a real problem anyway. # # Each gate already reports its own evidence line; this only adds the # roll-up. Gate stdout/stderr is echoed as it happens, so a failure shows # its diagnosis here and not just a verdict. # # Usage: scripts/verify-all.sh KIND|all [port ...] # with no ports, every port the kind has. Ports: host iigs # x68000 atarist amiga dos dvx # Env: VERIFY_ALL_LOG also append the full transcript to this file # Requires: whatever each selected gate requires; missing ones SKIP. set -uo pipefail repo=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd) kind=${1:-} shift || true label="verify-all $kind" KINDS="host golden visual tilebank input audio serial mouse save loss disk" ALL_PORTS="host iigs x68000 atarist amiga dos dvx" # UBER on the Amiga needs longer than bench-amiga.sh's interactive default. AMIGA_UBER_SECONDS=400 # kind port name command...: every gate, in run order within its kind. GATES=$(cat <&2; exit 2 ;; esac if [ "$kind" = all ]; then kinds=$KINDS kindPorts=$ALL_PORTS else kinds=$kind kindPorts=$(echo "$GATES" | awk -v k="$kind" '$1 == k { print $2 }' | awk '!seen[$0]++' | tr '\n' ' ') fi ports=${*:-$kindPorts} for p in $ports; do case " $kindPorts " in *" $p "*) ;; *) echo "$label: unknown port '$p' (choose from: $kindPorts)" >&2; exit 2 ;; esac done # Echo a command's output as it happens, and into VERIFY_ALL_LOG if set; # returns the command's exit code. stdin is /dev/null so no gate can read # the rest of the gate list. runLogged() { if [ -n "${VERIFY_ALL_LOG:-}" ]; then ( cd "$repo" && bash -c "$1" ) < /dev/null 2>&1 | tee -a "$VERIFY_ALL_LOG" return "${PIPESTATUS[0]}" fi ( cd "$repo" && bash -c "$1" ) < /dev/null } # The build step of `all`: each selected port, then the IIgs extras its # gates need (make iigs builds no examples; iigs-disk does). buildPorts() { local port local cmd for port in $ports; do case $port in host) continue ;; iigs) cmd="make -f make/iigs.mk iigs-disk $repo/build/iigs/bin/SCCPROBE $repo/build/iigs/bin/SERLOSS $repo/build/iigs/bin/SERLOSSS" ;; *) cmd="make $port" ;; esac echo echo "=== $label: build $port ($cmd) ===" if ! runLogged "$cmd"; then echo "$label: FAIL - building $port failed" >&2 exit 1 fi done } if [ "$kind" = all ]; then buildPorts fi gateNames=() gateVerdicts=() gateSeconds=() passed=0 failed=0 skipped=0 for k in $kinds; do while read -r gKind gPort gName gCmd; do [ "$gKind" = "$k" ] || continue case " $ports " in *" $gPort "*) ;; *) continue ;; esac echo echo "=== $label: $gKind $gPort $gName ($gCmd) ===" start=$SECONDS runLogged "$gCmd" rc=$? case $rc in 0) verdict=PASS; passed=$((passed + 1)) ;; 2) verdict="SKIP (prerequisite missing)"; skipped=$((skipped + 1)) ;; *) verdict=FAIL; failed=$((failed + 1)) ;; esac gateNames+=("$gKind $gPort $gName") gateVerdicts+=("$verdict") gateSeconds+=("$((SECONDS - start))") done <<< "$GATES" done echo echo "================ $label summary ================" for i in "${!gateNames[@]}"; do printf " %-26s %-28s %4ds\n" "${gateNames[$i]}" "${gateVerdicts[$i]}" "${gateSeconds[$i]}" done echo " ----" printf " %d passed, %d failed, %d skipped\n" "$passed" "$failed" "$skipped" if [ "$failed" -gt 0 ]; then echo "$label: FAIL" >&2 exit 1 fi if [ "$skipped" -gt 0 ]; then echo "$label: INCOMPLETE - some gates skipped (build those ports, then re-run)" >&2 exit 3 fi if [ "$passed" -eq 0 ]; then echo "$label: nothing selected" >&2 exit 2 fi echo "$label: PASS (all $passed gates)" exit 0