mirror of
https://git.k-space.ee/arti/vt1200.git
synced 2026-10-31 12:05:05 +02:00
The skip gate reaches the root weave and stops: video RAM and the rendered
frame are byte-identical at frames 3000/10000/30000/45000/60000 (42 s -> 14
min), and all 4 MiB of main RAM is identical at every sample except one byte
that oscillates. The PC histogram is tight: entered at frame ~611, dominated
by 0x3FB30390/0x3FB30110.
Wall: DUART2 (0x0620000, keyboard/mouse) is unmodelled, so the read-only ISR
at 0x06200005 is served by the board write-back latch and returns the value
the OS wrote to the write-only IMR (0x0033). The OS's DUART dispatcher
(0x3FB43800) masks 0x66 -> 0x22, so it services a phantom interrupt that can
never clear, spinning in the channel handler 0x3FB42410 and queue routine
0x3FB300F0. Forcing only 0x06200005 to 0 reproduces the full DUART2-mapped
run byte-for-byte; with VT1200_DUART2=1 the Terminal Manager dialog box from
the reference video appears at frame 3000 and the machine runs on.
Defaults unchanged: no-env still reaches HOST PORT - 15, skip still reaches
the weave. New opt-in knobs VT1200_DUMP_{FRAME,RAM_FRAMES,VRAM_FRAMES} and
resolve_console.py; progress.lua untouched.
52 lines
1.6 KiB
Python
52 lines
1.6 KiB
Python
#!/usr/bin/env python3
|
|
"""Resolve the a9 message pointers from a cap.lua debug.log capture.
|
|
|
|
cap.lua breaks at the firmware's console-print entry (bit 0x3FDE00C0) and logs
|
|
`PRINT pc=.. a9=.. a11=.. a5=..` lines (they land in MAME's -debuglog file,
|
|
i.e. `debug.log` in the CWD). a9 is a BIT address; the ROM image is byte-based
|
|
at 0x07E40000, so the string bytes are at file offset (a9 >> 3) - 0x07E40000.
|
|
|
|
Usage: resolve_console.py <debug.log> [rom.bin]
|
|
"""
|
|
import sys
|
|
|
|
ROM_BASE_BYTE = 0x07E40000
|
|
|
|
|
|
def main() -> int:
|
|
log = sys.argv[1]
|
|
rompath = sys.argv[2] if len(sys.argv) > 2 else "vt1200_v22.bin"
|
|
with open(rompath, "rb") as f:
|
|
rom = f.read()
|
|
|
|
seen = set()
|
|
with open(log, "r", errors="replace") as f:
|
|
for line in f:
|
|
if "PRINT pc=" not in line:
|
|
continue
|
|
fields = dict(
|
|
kv.split("=", 1) for kv in line.split() if "=" in kv
|
|
)
|
|
a9 = fields.get("a9")
|
|
a11 = fields.get("a11")
|
|
if a9 is None:
|
|
continue
|
|
bit = int(a9, 16)
|
|
off = (bit >> 3) - ROM_BASE_BYTE
|
|
key = (a9, a11)
|
|
if key in seen:
|
|
continue
|
|
seen.add(key)
|
|
if 0 <= off < len(rom):
|
|
end = rom.find(b"\x00", off)
|
|
raw = rom[off:end if end != -1 else off + 80]
|
|
txt = raw.decode("latin-1").replace("\n", "\\n")
|
|
print(f"a9={a9} a11={a11} {txt!r}")
|
|
else:
|
|
print(f"a9={a9} a11={a11} <not a ROM pointer: off={off:#x}>")
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main())
|