143 lines
5.7 KiB
Bash
Executable file
143 lines
5.7 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
# diag-staxi-screen.sh - one-off diagnostic for the STAXI title test:
|
|
# boot + launch STAXI, dump the full SHR framebuffer + palettes as hex
|
|
# at a target frame, then extract JOEYLOG.TXT from the work disk so the
|
|
# game's own init/asset-load log is visible. Outputs land in
|
|
# build/iigs/bin/ (staxi-shr.hex, staxi-joeylog.txt).
|
|
set -euo pipefail
|
|
|
|
repo=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)
|
|
: "${LLVM816_ROOT:?diag-staxi-screen.sh: source toolchains/env.sh first}"
|
|
CADIUS="${CADIUS:-$LLVM816_ROOT/tools/cadius/cadius}"
|
|
|
|
sys_disk=$repo/toolchains/emulators/support/gsos-system.po
|
|
data_disk=$repo/build/iigs/bin/joey.2mg
|
|
rompath="${MAME_ROMPATH:-$HOME/.mame/roms}"
|
|
dumpFrame="${STAXI_DUMP_FRAME:-9000}"
|
|
|
|
work=$(mktemp -d -t joeylib-staxidiag.XXXXXX)
|
|
trap 'rm -rf "$work"' EXIT
|
|
cp "$sys_disk" "$work/boot.po"
|
|
cp "$data_disk" "$work/joey.2mg"
|
|
|
|
cat > "$work/diag.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 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 = 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 = {
|
|
{3000, function() nat:post("J") end},
|
|
{3120, function() press(key_cmd) end},
|
|
{3126, function() nat:post("o") end},
|
|
{3180, function() release(key_cmd) end},
|
|
{3540, function() nat:post("STAXI") end},
|
|
{3660, function() press(key_cmd) end},
|
|
{3666, function() nat:post("o") end},
|
|
{3720, function() release(key_cmd) end},
|
|
}
|
|
local pcs = {}
|
|
|
|
emu.register_frame_done(function()
|
|
frame = frame + 1
|
|
while idx <= #steps and frame >= steps[idx][1] do
|
|
steps[idx][2]()
|
|
idx = idx + 1
|
|
end
|
|
-- Hang localization: sample the PC over 60 frames before the dump,
|
|
-- and probe NEWVIDEO (0xE0C029: bit7 = SHR on -> jlpInit ran).
|
|
if frame == $dumpFrame - 120 then
|
|
io.write(string.format("SHRPROBE newvideo=%02X shadow=%02X\n",
|
|
mem:read_u8(0xE0C029), mem:read_u8(0xE0C035)))
|
|
io.flush()
|
|
end
|
|
if frame >= $dumpFrame - 100 and frame < $dumpFrame - 40 then
|
|
local pc = cpu.state["PC"].value
|
|
local k = string.format("%06X", pc)
|
|
pcs[k] = (pcs[k] or 0) + 1
|
|
end
|
|
if frame == $dumpFrame - 40 then
|
|
for k, v in pairs(pcs) do
|
|
io.write(string.format("SHRPC %s count=%d\n", k, v))
|
|
end
|
|
io.flush()
|
|
end
|
|
if frame == $dumpFrame - 20 then
|
|
-- Locate the jlLog RAM ring without UBER's mailbox: bulk-read every
|
|
-- RAM bank and emit it as hex; the host greps for the build-stamp
|
|
-- text. read_range failures are reported, not swallowed.
|
|
local banks = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,0xE0,0xE1}
|
|
for _, bank in ipairs(banks) do
|
|
local base = bank * 65536
|
|
local ok, buf = pcall(function() return mem:read_range(base, base + 65535, 8) end)
|
|
if ok and buf ~= nil then
|
|
for off = 0, 65535, 256 do
|
|
local chunk = string.sub(buf, off + 1, off + 256)
|
|
local hex = {}
|
|
for i = 1, #chunk do
|
|
hex[#hex + 1] = string.format("%02X", string.byte(chunk, i))
|
|
end
|
|
io.write(string.format("SHRMEM %02X%04X %s\n", bank, off, table.concat(hex)))
|
|
end
|
|
else
|
|
io.write(string.format("SHRMEM-FAIL bank=%02X err=%s\n", bank, tostring(buf)))
|
|
end
|
|
end
|
|
io.flush()
|
|
end
|
|
if frame == $dumpFrame then
|
|
-- SHR pixel dump: 200 rows x 160 bytes as hex lines.
|
|
for row = 0, 199 do
|
|
local parts = {}
|
|
for b = 0, 159 do
|
|
parts[#parts + 1] = string.format("%02X", mem:read_u8(0xE12000 + row * 160 + b))
|
|
end
|
|
io.write("SHRROW " .. table.concat(parts) .. "\n")
|
|
end
|
|
-- SCBs + palettes.
|
|
local scb = {}
|
|
for i = 0, 15 do scb[#scb + 1] = string.format("%02X", mem:read_u8(0xE19D00 + i)) end
|
|
io.write("SHRSCB " .. table.concat(scb, " ") .. "\n")
|
|
local pal = {}
|
|
for i = 0, 31 do pal[#pal + 1] = string.format("%02X", mem:read_u8(0xE19E00 + i)) end
|
|
io.write("SHRPAL " .. table.concat(pal, " ") .. "\n")
|
|
io.flush()
|
|
manager.machine:exit()
|
|
end
|
|
end)
|
|
LUA
|
|
|
|
echo "diag-staxi: dumping SHR at frame $dumpFrame..." >&2
|
|
cd "$work"
|
|
out=$(QT_QPA_PLATFORM=offscreen SDL_VIDEODRIVER=dummy SDL_AUDIODRIVER=dummy \
|
|
timeout 900 mame apple2gs \
|
|
-rompath "$rompath" \
|
|
-flop3 "$work/boot.po" -flop4 "$work/joey.2mg" \
|
|
-video none -sound none -nothrottle \
|
|
-autoboot_script "$work/diag.lua" </dev/null 2>&1) || true
|
|
|
|
echo "$out" | grep -E '^SHR(PROBE|PC)|^SHRMEM-FAIL' | sed 's/^/diag-staxi: /' >&2
|
|
echo "$out" | grep -E '^SHRMEM ' > "$repo/build/iigs/bin/staxi-mem.hex" || true
|
|
echo "$out" | grep -E '^SHR(ROW|SCB|PAL)' > "$repo/build/iigs/bin/staxi-shr.hex"
|
|
wc -l "$repo/build/iigs/bin/staxi-shr.hex" >&2
|
|
|
|
# The game flushed its log to the volume root; pull it off the WORK copy.
|
|
rm -f "$repo/build/iigs/bin/staxi-joeylog.txt" "$work/JOEYLOG.TXT"* 2>/dev/null || true
|
|
"$CADIUS" EXTRACTFILE "$work/joey.2mg" "/JOEYLIB/JOEYLOG.TXT" "$work/" >/dev/null 2>&1 || true
|
|
found=$(ls "$work"/JOEYLOG.TXT* 2>/dev/null | head -1)
|
|
if [ -n "$found" ]; then
|
|
tr -d '\r' < "$found" > "$repo/build/iigs/bin/staxi-joeylog.txt"
|
|
echo "diag-staxi: extracted JOEYLOG.TXT:" >&2
|
|
else
|
|
echo "diag-staxi: no JOEYLOG.TXT on work disk (flush never ran?)" >&2
|
|
fi
|