Rev 2 cannot bus-master, so the hypervisor saves by shadowing and restores through the 6502
What I tried
The idea after the SDRAM monitor was a snapshot hypervisor: treat a whole booted machine, main 64K plus aux 64K plus registers and soft switches, as a guest that lives in one SDRAM context bank. Boot a disk, hit a hyperkey, the card traps the 6502 with NMI and INH, pages the guest out to SDRAM, pages the supervisor back in. The obvious fast path is DMA: pull the DMA line, halt the 6502, and let the card copy RAM to SDRAM itself.
On 2026-06-05 I went through the KiCad netlist to wire that up and found there is nothing to wire. The three address-bus level shifters, U8 for A0 to A6, U11 for A7 to A13 and U13 for A14 and A15, have DIR tied to +5 V and OE to ground. They pass slot to FPGA and nothing else. R/W is input-only at the FPGA on D10. The card can pull DMA low and stop the 6502, and after that no one can drive an address. The data bus through U12 is reversible and NMI, INH and RES are FPGA outputs, so the trap works, but nothing can drive an address.
So the mechanism changed. Save is continuous write-through shadowing: the card snoops every qualified CPU write, PHI0 falling with R/W low in a RAM region, and mirrors the byte into the active context’s SDRAM bank as it happens. The 6502 only drives the bus in phase 0, video and refresh are phase 1 reads, read-modify-write dummy writes self-correct because the last write wins, and the STA abs,X dummy cycle is a read, so that condition is enough. A soft-switch tracker supplies the main-or-aux bank bit per cycle, since RAMWRT and friends are not on the address bus. Restore is the 6502 pulling bytes out of the $C0Cx port with hardware auto-increment and storing them, with 256-byte dirty-page tracking so only clobbered pages get copied.
What I measured
- SDRAM at 100 MHz against a roughly 1 MHz write stream: about 100:1, so the shadow keeps up with no buffering.
- Estimated switch cost: 3.3 s for a naive full copy, 1.7 s with write-through save, 0.3 s target with dirty-page restore. A Rev 3 with DMA would be 50 ms to 100 ms.
- 06-06, restore on the bench: POKE 8192,17 into context 0, switch context, scribble 238 over the same RAM, BRUN SDMREST, PEEK(8192) reads 17. First 4 KB slice,
$2000to$2FFFmain, software only, no gateware change. - 06-07, trap unit 5c-2b: NMI vector hardwired to a handler in the
$C800ROM with INH forcing the fetch, captures a clean frame even with the vector page trashed and INTCXROM set.
What broke or surprised me
The SYNC line on B11 looked useful for the write snoop and is not. It marks opcode fetches, which never coincide with a write. It is parked as a future trace primitive.
BRUN needs ProDOS booted. Bare Applesoft gives ?SYNTAX ERROR because there is no DOS to hook the command.
Time-slicing the one host 6502 through this machinery costs seconds per switch, too slow to use it as a helper. A second CPU inside the FPGA gives real concurrency with no switch at all. That became the coprocessor, and the hypervisor stopped at 5c-2b on branch obscurus-sdram-monitor.
Next
Rev 3 needs DIR and OE on U8, U11 and U13 routed to the FPGA plus an R/W output. I am not going to bodge three transceivers on a Rev 2 board. When Rev 3 happens, DMA drops in behind the same trap and vault logic as a speedup.