pico: implement ROM mirroring for small cartridges

Hardware-accurate ROM mirroring is now applied to all cartridges smaller
than 4MB. By rounding the ROM size up to the next power-of-two and
mapping it repeatedly across the 4MB window:
1. It matches real hardware mirroring behavior.
2. It prevents FAME/M68K Fetch table misses where Fetch[n] would be 0.
3. It fixes SIGSEGV crashes caused by the CPU jumping to unmapped
   memory regions within the cartridge space.
This commit is contained in:
ZengGengSen authored and irixxxx committed 2026-08-20 17:59:19 +02:00
1 parent e2540920a2
commit 733c711a47
1 file changed
+22 -2
+22 -2
View File
@@ -1180,8 +1180,28 @@ PICO_INTERNAL void PicoMemSetup(void)
rs = (Pico.romsize + mask) & ~mask;
if (rs > 0xa00000) rs = 0xa00000; // max cartridge area
if (rs) {
cpu68k_map_set(m68k_read8_map, 0x000000, rs - 1, Pico.rom, 0);
cpu68k_map_set(m68k_read16_map, 0x000000, rs - 1, Pico.rom, 0);
if (rs <= 0x400000) {
// For ROMs smaller than 4 MB, mirror them across the entire 4 MB
// cartridge space. This is required so that FAME's Fetch table has
// valid entries for every page the 68K might execute from; without
// mirroring, pages beyond the physical ROM end have Fetch[n] = 0,
// which causes BasePC = 0 and PC = raw-virtual-address -> SIGSEGV.
// Round up to the next power-of-two to match real hardware mirroring.
u32 mirror = 1;
while (mirror < rs) mirror <<= 1;
u32 off;
for (off = 0; off < 0x400000; off += mirror) {
u32 end = off + mirror - 1;
if (end >= 0x400000) end = 0x3fffff;
// Passing Pico.rom (not Pico.rom+off) lets xmap_set/cpu68k_map_set
// subtract start_addr internally, producing the correct mirrored base.
cpu68k_map_set(m68k_read8_map, off, end, Pico.rom, 0);
cpu68k_map_set(m68k_read16_map, off, end, Pico.rom, 0);
}
} else {
cpu68k_map_set(m68k_read8_map, 0x000000, rs - 1, Pico.rom, 0);
cpu68k_map_set(m68k_read16_map, 0x000000, rs - 1, Pico.rom, 0);
}
}
// Common case of on-cart (save) RAM, usually at 0x200000-...