161 lines
6.8 KiB
Bash
Executable file
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)"
|