#!/usr/bin/env bash # Run a 65816 binary in MAME after pre-loading a stub GS/OS # dispatcher at $E100A8. This lets the smoke test exercise the # wrapper-to-dispatcher contract end-to-end without needing a # real GS/OS-bootable disk image. # # The stub is the assembled bytes of /tmp/gsosStub.s (rebuilt # from runtime/src/iigsGsosStub.s as part of this script — kept # in-tree so it's reproducible). It writes byte $42 to *parm # and returns A=0 (success) for any call number. That is enough # to verify the wrapper: # 1. pushes the parm-block low ptr (PHA), # 2. pushes a zero bank (PEA 0), # 3. JSLs $E100A8 with the right return convention, # 4. returns A correctly to the caller. # # Usage: runInMameWithGsosStub.sh # runInMameWithGsosStub.sh --check =... set -euo pipefail source "$(dirname "$0")/common.sh" BIN="$1" shift SECS=3 # 23-byte stub bytes (see runtime/src/iigsGsosStub.s for source). # Hand-assembled to avoid relying on llvm-mc tracking M-flag state. STUB_HEX="0848 a309 85e4 a000 00e2 20a9 4291 e4c2 2068 28a9 0000 6b" LUA_CHECKS="" EXPECT_LIST=() ADDR_LIST=() if [ "$1" = "--check" ]; then shift for pair in "$@"; do ADDR="${pair%=*}" EXP="${pair#*=}" ADDR_LIST+=("$ADDR") EXPECT_LIST+=("$EXP") LUA_CHECKS="$LUA_CHECKS print(string.format('MAME-READ addr=0x%06x val=0x%04x', $ADDR, mem:read_u16($ADDR)))"$'\n' done else ADDR="$1" EXP="$2" ADDR_LIST+=("$ADDR") EXPECT_LIST+=("$EXP") LUA_CHECKS="print(string.format('MAME-READ addr=0x%06x val=0x%04x', $ADDR, mem:read_u16($ADDR)))" fi [ -f "$BIN" ] || die "binary not found: $BIN" LUA_PATH=$(mktemp --suffix=.lua) trap 'rm -f "$LUA_PATH"' EXIT # Build the stub-write Lua statement (one mem:write_u8 per byte). STUB_BYTES=$(echo "$STUB_HEX" | tr -d ' ') STUB_LUA="" i=0 while [ $i -lt ${#STUB_BYTES} ]; do byte="${STUB_BYTES:$i:2}" addr=$(( 0xe100a8 + i / 2 )) STUB_LUA="${STUB_LUA} mem:write_u8(${addr}, 0x${byte})"$'\n' i=$(( i + 2 )) done cat > "$LUA_PATH" <= 0x00C000 and addr < 0x00D000) then mem:write_u8(addr, data:byte(i)) end end -- Install GS/OS dispatcher stub at \$E100A8 (bank E1 RAM). $STUB_LUA loaded = true cpu.state["PC"].value = 0x1000 cpu.state["PB"].value = 0x00 cpu.state["DB"].value = 0x00 cpu.state["D"].value = 0x00 cpu.state["P"].value = 0x34 cpu.state["E"].value = 0 cpu.state["S"].value = 0x01FF print("MAME-LOADED bytes=" .. #data .. " stub=$((${#STUB_BYTES}/2))") end if frame == 60 then local cpu = manager.machine.devices[":maincpu"] local mem = cpu.spaces["program"] $LUA_CHECKS manager.machine:exit() end end) EOF OUT=$(timeout 30 mame apple2gs \ -rompath "$PROJECT_ROOT/tools/mame/roms" \ -plugins -autoboot_script "$LUA_PATH" \ -window -sound none -nothrottle -seconds_to_run "$SECS" 2>&1 | grep "^MAME-") echo "$OUT" mapfile -t GOT_LIST < <(printf '%s\n' "$OUT" | grep -oE 'val=0x[0-9a-f]+' | sed 's/val=0x//') ok=1 for i in "${!EXPECT_LIST[@]}"; do if [ "${GOT_LIST[$i]:-}" != "${EXPECT_LIST[$i]}" ]; then warn "MAME mismatch at ${ADDR_LIST[$i]}: got 0x${GOT_LIST[$i]:-MISSING} expected 0x${EXPECT_LIST[$i]}" ok=0 fi done if [ $ok -eq 1 ]; then log "MAME (gsos-stub) OK: ${#EXPECT_LIST[@]} reads matched" exit 0 fi exit 1