# C128 MMU and Common-RAM Probe Story: E01-S02 Status: observed in VICE x128 3.10; not a final compiler memory map ## Registers Used | Address | Name | Use in the probe | |---|---|---| | `$FF00` | CR | Bank/ROM/I/O configuration; visible in every mapping | | `$D506` | RCR | Common-RAM size/placement; bits 6–7 (VIC bank) preserved | | `$D507/$D508` | P0L/P0H | Page-zero pointer; write H first, L commits | | `$D509/$D50A` | P1L/P1H | Page-one pointer; write H first, L commits | Configurations exercised: - `CR=$0E`: RAM bank 0, KERNAL ROM high, I/O at `$D000`. - `CR=$4E`: the same with RAM bank 1 selected (bit 6). - `RCR=$0E` (low bits): 8K common RAM at both bottom (`$0000–$1FFF`) and top (`$E000–$FFFF`), always backed by bank 0. The probe lives entirely in `$1C01–$1F46`, inside the bottom 8K common window, so its code, data, zero page, and hardware stack stay visible with bank 1 selected. ## Observed Results All checks pass (`mmu_probe_result = $FF`). The x128 screenshot shows `NOVA128 MMU PROBE OK` followed by `READY.`. | Check | Observation | |---|---| | Distinct banks | `$4000` holds `$11` in bank 0 and `$22` in bank 1 at the same time | | Common RAM | A marker written in bank 0 is read and rewritten while bank 1 is selected, and the rewrite is visible from bank 0 | | Bank-switched return | `JSR`/`RTS` with bank 1 selected returns with the same SP | | P0 relocation, common off | P0 → bank 1 page `$20`: a write to `$00F0` appears at bank1:`$20F0` (`$77`) | | P0 with common on | P0 → bank 1 page `$21`: a write to `$00F1` lands at **bank0**:`$21F1` (`$66`); logical `$00F1` and bank1:`$21F1` are unchanged | | P1 with common on | P1 → bank 1 page `$21`: `PHA` lands at **bank0**:`$2100+SP` (`$5A`); bank0 page 1 and the bank-1 sentinel (`$33`) are unchanged; `PLA` returns the pushed value | | Restoration | CR, RCR, P0L/H, P1L/H read back equal to their entry values before `PLP` | | MMU write audit | 42 stores to `$FF00`/`$D500–$D50B` between entry and done, all from probe code; only `$FF00` and `$D506–$D50A` are written | ### Common-RAM priority model The original probe assumed common RAM would *cancel* a page pointer aimed at bank 1. That was wrong. The observed rule is: > The page pointer's page translation always applies. When the logical page > (0 or 1) lies inside the active bottom common window, the pointer's bank > bit is ignored and the access goes to bank 0 at the translated page. Consequences for the compiler: 1. With bottom common enabled, P0/P1 can relocate zero page or the stack only within bank 0. Nova128 should keep both pointers in bank 0. 2. Relocating P0/P1 into bank 1 requires bottom common disabled, which also removes common visibility of the code doing the switch. Avoid it. 3. A relocated page swaps with physical page 0/1 at the target address, so a relocation target must not overlap live compiler data. ## Interrupt Policy The probe saves P with `PHP`, executes `SEI` before the first MMU write, and does not restore the caller's I flag (`PLP`) until every MMU register has been restored and checked. No KERNAL call occurs while a non-default mapping is active. Taking an IRQ with bank 1 selected was deliberately **not** tested; the `mmu.s` wrappers must either keep IRQs masked across non-default mappings or E01-S03/E01-S05 must prove a common-RAM IRQ path. ## Hardware Caveat These facts are VICE x128 3.10 observations. Physical-hardware confirmation belongs to E08-S06. ## Reproducing ```powershell scripts/build-mmu-probe.ps1 # assemble + link, checks it fits below $2000 scripts/run-mmu-probe.ps1 # visible run, writes build/mmu-probe-vicii.png scripts/verify-mmu-probe.ps1 # remote-monitor result block + MMU write audit ``` `verify-mmu-probe.ps1` builds `build/mmu-probe-trace.gen.txt` from `monitor/mmu-probe-trace.txt` plus the current `mmu_probe_done` address. The `$FF00` store trace is armed only between probe entry and done, because the KERNAL's common-RAM fetch helper at `$02A5/$02AB` writes `$FF00` hundreds of times during boot. The full trace is saved to `build/mmu-probe-trace-dump.txt`. For interactive debugging, use `monitor/mmu-probe-debug.txt`.