65816-llvm-mos/scripts/probeHelloWindow.sh
2026-05-18 14:43:35 -05:00

161 lines
6.8 KiB
Bash
Executable file

#!/usr/bin/env bash
# probeHelloWindow.sh - headless run of demos/helloWindow that dumps
# the step markers ($70..$72, written via MARK_AT = STA long, bank-0
# explicit) and the gDiag[] capture buffer (discovered from the .map)
# so we can see what NewWindow ($090E) actually returns at the
# toolbox-dispatcher level.
#
# Captures:
# $70 = end-of-main marker ($99 = ran to completion)
# $71 = step marker (last value reached: $10..$19)
# $72 = NewWindow C-level result ($01/$02 = success, $EE = NULL)
# gDiag[0/1] = paramLength readback ($4C if parm ptr is good)
# gDiag[2/3] = result-space LOW word (window-ptr lo)
# gDiag[4/5] = result-space HIGH word (window-ptr hi)
# gDiag[6] = P byte at JSL return (bit 0 = carry)
# gDiag[7] = $AA if probe ran to completion
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
OMF="$PROJECT_ROOT/demos/helloWindow.omf"
SRC="$PROJECT_ROOT/demos/helloWindow.c"
MAP="$PROJECT_ROOT/demos/helloWindow.map"
if [ ! -f "$OMF" ] || [ "$SRC" -nt "$OMF" ]; then
bash "$PROJECT_ROOT/demos/build.sh" helloWindow >/dev/null
fi
GDIAG_HEX=$(awk '$2 == "gDiag" {print $1; exit}' "$MAP")
[ -n "$GDIAG_HEX" ] || { echo "gDiag not found in $MAP" >&2; exit 2; }
GDIAG=$((GDIAG_HEX))
echo "gDiag at $(printf '0x%06x' $GDIAG)"
CADIUS=${CADIUS:-$PROJECT_ROOT/tools/cadius/cadius}
SYSDISK=${SYSDISK:-$PROJECT_ROOT/tools/gsos/sys602.po}
[ -x "$CADIUS" ] || { echo "cadius not found: $CADIUS" >&2; exit 2; }
[ -f "$SYSDISK" ] || { echo "sysdisk not found: $SYSDISK" >&2; exit 2; }
command -v mame >/dev/null || { echo "mame not in PATH" >&2; exit 2; }
WORK=$(mktemp -d -t probe.XXXXXX)
trap 'rm -rf "$WORK"' EXIT
cp "$SYSDISK" "$WORK/disk.po"
"$CADIUS" CREATEVOLUME "$WORK/data.po" DATA 800KB >/dev/null
cp "$OMF" "$WORK/HELLO#B30000"
"$CADIUS" ADDFILE "$WORK/data.po" /DATA "$WORK/HELLO#B30000" >/dev/null
cat > "$WORK/launch.lua" <<LUA
local GDIAG = $GDIAG
LUA
cat >> "$WORK/launch.lua" <<'LUA'
local cpu = manager.machine.devices[":maincpu"]
local mem = cpu.spaces["program"]
local nat = manager.machine.natkeyboard
local frame = 0
local idx = 1
local function get_field(port, name)
local p = manager.machine.ioport.ports[port]
if p == nil then return nil end
return p.fields[name]
end
local key_cmd = get_field(":macadb:KEY3", "Command / Open Apple")
local function press(f) if f then f:set_value(1) end end
local function release(f) if f then f:set_value(0) end end
local steps = {
{3300, function() nat:post("D") end},
{3540, function() press(key_cmd) end},
{3546, function() nat:post("o") end},
{3600, function() release(key_cmd) end},
{4200, function() nat:post("H") end},
{4500, function() press(key_cmd) end},
{4506, function() nat:post("o") end},
{4560, function() release(key_cmd) end},
{7000, function() nat:post(" ") end},
{7500, function() nat:post(" ") end},
{8000, function() nat:post(" ") end},
{9000, function()
for a = 0x70, 0x7f do
print(string.format("MARK $%02x = %02x", a, mem:read_u8(a)))
end
print(string.format("MARK $96 (event type) = %02x", mem:read_u8(0x96)))
print(string.format("MARK $97 (loop iters lo) = %02x", mem:read_u8(0x97)))
print(string.format("MARK $93 (sizeof gWp) = %02x = %d",
mem:read_u8(0x93), mem:read_u8(0x93)))
print(string.format("A post-JSL = $%04x (lo=%02x hi=%02x)",
mem:read_u8(0x90) | (mem:read_u8(0x91)*256),
mem:read_u8(0x90), mem:read_u8(0x91)))
local pbr = mem:read_u8(0x73)
-- The OMF Loader places our segment at offset $0000 within bank
-- $PBR (not at $1000 like our text-base). The cRELOC mechanism
-- patches all symbolic abs-16 stores to (segPlacedBase + offsetRef)
-- = ($0000 + symbol_offset_within_segment) = link_addr - text_base.
-- So runtime_address(sym) = pbr*0x10000 + (link_addr - text_base).
local TEXT_BASE = 0x1000
local base = pbr * 0x10000 + (GDIAG - TEXT_BASE)
print(string.format("PBR = $%02x; gDiag at $%06x", pbr, base))
for i = 0, 15 do
print(string.format("gDiag[%d] = %02x", i, mem:read_u8(base + i)))
end
-- Cross-check: read sanity bytes at the same offset in bank 0
-- and bank 8 to find where DBR-rel stores actually land.
-- Search every bank from $00..$FF for $5A at offset $6F5D.
for bank = 0, 0xff do
local v = mem:read_u8(bank*0x10000+0x6F5D)
if v == 0x5a then
print(string.format("*** bank %02x HAS $5A at $6F5D ***", bank))
end
end
for _, bank in ipairs({0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f}) do
print(string.format("bank %02x: $%06x = %02x (gDiag+e) $%06x = %02x (s2) $%06x = %02x (s1)",
bank,
bank*0x10000+0x6F5C, mem:read_u8(bank*0x10000+0x6F5C),
bank*0x10000+0x6F5D, mem:read_u8(bank*0x10000+0x6F5D),
bank*0x10000+0x6F4E, mem:read_u8(bank*0x10000+0x6F4E)))
end
-- Dump the runtime operand bytes of the symbolic `sta gDiag+0`
-- at .bin offset $387. With text-base=$1000, that's runtime
-- $08:$1387 (PBR + .bin offset + text-base). If the Loader
-- re-applied the cRELOC with a different segPlacedBase, the
-- operand bytes will differ from what the linker wrote.
local probeBase = 0x081000
for ofs = 0x380, 0x39f, 0x10 do
local row = string.format("$08:%04x:", ofs)
for j = 0, 15 do
row = row .. string.format(" %02x", mem:read_u8(probeBase + ofs - 0x1000 + j))
end
print(row)
end
print(string.format("test $704E: $08=%02x $00=%02x",
mem:read_u8(0x08704E), mem:read_u8(0x00704E)))
print(string.format("test $7060: $08=%02x $00=%02x",
mem:read_u8(0x087060), mem:read_u8(0x007060)))
print(string.format("test $70FF: $08=%02x $00=%02x",
mem:read_u8(0x0870FF), mem:read_u8(0x0070FF)))
for b = 0, 0xff do
if mem:read_u8(b*0x10000+0x704E) == 0xAB then
print(string.format("*** $AB at bank %02x:$704e ***", b))
end
end
manager.machine:exit()
end},
}
emu.register_frame_done(function()
frame = frame + 1
while idx <= #steps and frame >= steps[idx][1] do
steps[idx][2]()
idx = idx + 1
end
end)
LUA
OUT=$(timeout 220 mame apple2gs -rompath "$PROJECT_ROOT/tools/mame/roms" \
-window -nothrottle -sound none \
-seconds_to_run 180 -flop3 "$WORK/disk.po" -flop4 "$WORK/data.po" \
-autoboot_script "$WORK/launch.lua" </dev/null 2>&1)
echo "$OUT" | grep -E "^(MARK|gDiag|bank|PBR|\*\*\*|\\\$08|test|A post)"