modemwars/swiftlink/probeBankOut.py
2026-08-23 02:09:40 -05:00

57 lines
3 KiB
Python

#!/usr/bin/env python3
# probeBankOut.py - two facts about a $DF00-strapped cartridge that the rest of the strap testing
# rests on, asked of the emulator directly rather than argued from first principles.
#
# python3 probeBankOut.py
#
# 1. What VICE maps, and where. The monitor's "io" command lists the I/O devices and the address
# range each one claims, which is what says whether a stop on $DF04-$DFFF would be a register
# access in the emulator or just an address nobody answers.
# 2. Whether an access to $DFxx reaches the cartridge when the I/O area is banked out. The game's
# film buffer is the RAM under $D000-$DFFF; copyPageUnderIo $58B2 walks a page pointer up to
# $DF00 and readFilmByte / writeFilmByte dereference filmPtr anywhere in it, all with $01 = $34.
# If those reached the 6551 they would consume received characters and clear interrupt flags, so
# the whole film system would be a hazard on the $DF00 strap. The test writes through the I/O
# window, then writes a different value to the same address with the I/O area banked out, then
# banks I/O back in and reads the register again: if the register still holds the first value, the
# second write went to RAM and never reached the chip.
import os
import sys
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
from viceHarness import ViceSession, aciaArgs, readByte, SCRATCH
def main():
session = ViceSession("", f"{SCRATCH}/probeBankOut.log", aciaArgs(base="0xDF00"), label="bankout")
try:
session.connect()
session.enterMonitor()
print("--- what VICE has mapped in the I/O area ---", flush=True)
print(session.mon("io"), flush=True)
session.mon("bank cpu")
session.mon("sidefx on")
print("--- unmapped $DE00-$DE07 (nothing is strapped there in this run) ---", flush=True)
print(session.mon("m de00 de07"), flush=True)
print("--- the page above the four registers, $DF40-$DF47 and $DFFC-$DFFF ---", flush=True)
print(session.mon("m df40 df47"), flush=True)
print(session.mon("m dffc dfff"), flush=True)
session.mon("> df03 1e")
first = readByte(session, 0xDF03)
session.mon("> 0001 34") # bank the RAM under $D000-$DFFF into view
session.mon("> df03 55") # must land in RAM, not in the ACIA
underneath = readByte(session, 0xDF03)
session.mon("> 0001 37") # I/O back
after = readByte(session, 0xDF03)
print(f"control register written through the I/O window: ${first:02X}", flush=True)
print(f"same address written again with $01 = $34, read back banked out: "
f"${underneath:02X}", flush=True)
print(f"control register with the I/O area banked in again: ${after:02X}", flush=True)
print("the banked-out write reached the cartridge: "
f"{'YES - hazard' if after != first else 'no, it went to RAM'}", flush=True)
finally:
session.close()
main()