#!/usr/bin/env bash # Launch the IIgs sprite demo (or other example) under MAME's apple2gs # driver instead of GSplus. We get: # - The MAME debugger window (always visible with -debug) # - debug.log file written to the working directory # - A Lua hook that, when the CPU halts (e.g., BRK), dumps registers # and the surrounding code bytes to /tmp/mame-iigs/crash.txt # # The boot path is the same as run-iigs.sh: gsos-system.po as flop3, our # joey.2mg as flop4. Once Finder is up, navigate to JOEYLIB and double- # click the example. # # Outputs of a run land in /tmp/mame-iigs/: # - debug.log MAME's debugger console output (-debuglog) # - crash.txt Lua-hook crash dump (if anything halts the CPU) # - joeylog.txt Extracted from the post-run disk image set -euo pipefail if [[ $# -gt 1 ]]; then echo "usage: $0 [example-name]" >&2 exit 2 fi prog=${1:-pattern} repo=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd) bin_dir=$repo/build/iigs/bin target=${prog^^} if [[ ! -f "$bin_dir/$target" ]]; then echo "$bin_dir/$target not built. Run 'make iigs' first." >&2 if compgen -G "$bin_dir/*" > /dev/null; then echo "available examples in $bin_dir:" >&2 find "$bin_dir" -maxdepth 1 -type f -printf '%f\n' \ | grep -vE '\.2mg$|\.txt$' >&2 || true fi exit 1 fi sys_disk=$repo/toolchains/emulators/support/gsos-system.po data_disk=$bin_dir/joey.2mg for f in "$sys_disk" "$data_disk"; do if [[ ! -f $f ]]; then echo "missing: $f" >&2 exit 1 fi done work=$(mktemp -d -t joeylib-mame.XXXXXX) out=/tmp/mame-iigs mkdir -p "$out" cp "$sys_disk" "$work/boot.po" cp "$data_disk" "$work/joey.2mg" # Lua script: drives Finder via natural keyboard + macadb key fields # to launch the requested example, dumps register state on any halt # (BRK, breakpoint, watchpoint, manual stop). Field names for keys # come from MAME's apple2gs macadb input definitions: # :macadb:KEY0 -> "d D" # :macadb:KEY1 -> "o O" # :macadb:KEY2 -> "j J", "p P" # :macadb:KEY3 -> "Command / Open Apple" # Letters not on KEY0..2 fall back to natkeyboard:post() (which # handles modifier-less character entry only). # Type the FULL program name to disambiguate (DRAW vs DATA which both # start with D and live in the same JOEYLIB volume). prog_select_str=${target} cat > "$work/crash-hook.lua" <= steps[step_idx][1] do steps[step_idx][2]() step_idx = step_idx + 1 end if boot_frames > 18000 and not crashed then crashed = true dump("watchdog") signal_done("watchdog") end end end) LUA # Wipe prior crash.txt so we don't confuse runs. : > "$out/crash.txt" cat </dev/null; then for name in JOEYLOG.TXT joeylog.txt; do if [[ -f $mnt/$name ]]; then cp "$mnt/$name" "$out/joeylog.txt" echo "extracted joeylog.txt -> $out/joeylog.txt" >&2 break fi done fusermount -u "$mnt" 2>/dev/null || true fi fi rm -rf "$work" } trap cleanup EXIT # Visible by default. Set MAME_HEADLESS=1 to suppress the video window # (CI / batch runs that only care about crash.txt). video_arg="-window" if [[ "${MAME_HEADLESS:-0}" = "1" ]]; then video_arg="-video none" fi # Clear the done-marker the Lua hook uses to signal shutdown. rm -f "$out/.done" cd "$work" mame apple2gs \ -flop3 "$work/boot.po" \ -flop4 "$work/joey.2mg" \ $video_arg -sound none \ -nothrottle \ -debug -debuglog \ -autoboot_script "$work/crash-hook.lua" & mame_pid=$! # Poll for the done-marker. Kill MAME once Lua signals it. Cap total # wall-clock at 6 min so we don't outlive the Lua-side watchdog (5 min). deadline=$((SECONDS + 360)) while kill -0 "$mame_pid" 2>/dev/null; do if [[ -f $out/.done ]]; then kill "$mame_pid" 2>/dev/null break fi if (( SECONDS > deadline )); then kill "$mame_pid" 2>/dev/null break fi sleep 0.5 done wait "$mame_pid" 2>/dev/null || true