Story: E01-S02
Status: observed in VICE x128 3.10; not a final compiler memory map
| 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.
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 |
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:
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.
These facts are VICE x128 3.10 observations. Physical-hardware confirmation belongs to E08-S06.
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.
Powered by TurnKey Linux.