made mapper module to support the various NES cartridge types in the furyte, MMC1 support added

This commit is contained in:
2026-08-09 14:03:08 -05:00
parent a54d3ccc09
commit b4504bf9ce
5 changed files with 180 additions and 23 deletions
+14 -4
View File
@@ -39,11 +39,19 @@
## Next
Official CPU milestone is COMPLETE (all 151 opcodes, nestest-verified through line 5003). The full 8991-line nestest log tests illegal opcodes too (225 distinct opcodes total; first illegal is 0x04 at line 5004). Official opcodes never seen in the log: BRK 0x00, CLI 0x58.
CURRENT TASK: add MMC1 (mapper 1) support so blargg official_only.nes / all_instrs.nes can run (authoritative opcode check). Then the illegal-opcode phase for the full 8991-line nestest pass.
Follow-up options, in any order:
- Illegal-opcode phase: implement the undocumented opcodes (0x04 and friends) for the full 8991-line nestest pass. ~76 illegal opcodes present in the log. Reference: nesdev wiki undocumented opcode table
- MMC1 (mapper 1) in the cartridge so blargg official_only.nes / all_instrs.nes can run (authoritative official check)
MMC1 plan (new mapper.rs module, trait-based for future-proofing):
- Phase 1 - DONE (src/mapper.rs written): Mirroring enum (5 variants incl. OneScreenLow/High), trait Mapper: Debug (read_prg/write_prg/read_chr/write_chr/mirroring, ROM passed in per call), Nrom impl (16KB-mirror/32KB-direct, write_prg no-op), Mmc1 impl (shift-register protocol: bit-7 reset, shift LSB, latch after 5 by addr range; PRG modes 0/1=32K at $8000 bank=prg_bank&0x0E, 2/3=16K with $8000 fixed bank0 $C000 switches; CHR mode 0=8K via chr0, 1=two 4K via chr0/chr1 modulo-safe; init control=0x0C). Code verified by review; crate intentionally not compiling yet until Phase 2 rewiring
- Phase 2 - DONE (src/cartridge.rs rewired): mapper is Box<dyn Mapper>, added 8KB prg_ram, derives now Debug only. from_file accepts mapper 0/1 and builds Nrom::new(mirroring) / Mmc1::new(). read/write_prg, read/write_chr delegate to mapper. Added mirroring() accessor + read/write_prg_ram (offset addr - 0x6000). mod mapper; added to main.rs
- Phase 3 - DONE (src/bus.rs): $6000-$7FFF reads route to cart.read_prg_ram, writes to cart.write_prg_ram (was stub 0 / dropped). $8000-$FFFF writes route to cart.write_prg (was dropped)
- Phase 4 - DONE (regression gate): nestest still matches 5004 lines / 0 mismatches. Crate builds and runs clean
- Phase 5 - NEXT: Blargg harness in main.rs: cargo run = nestest mode (unchanged); cargo run -- <rom> = blargg mode using cpu.reset() (boots from $FFFC-$FFFD vector), run cycle cap, report $6000-$6003. Verify with official_only.nes
- Phase 6 - Tests: flip rejects_mmc1 to positive loads_mmc1, update mirroring assertions to accessor, add shift-register latching / PRG banking math / PRG RAM roundtrip / Nrom unit tests
Then after MMC1:
- Illegal-opcode phase: implement the undocumented opcodes (0x04 and friends) for the full 8991-line nestest pass. ~76 illegal opcodes present in the log, grouped into batches (23 undocumented NOPs, SLO/RLA/SRE/RRA shift-logic hybrids, LAX/SAX load-store combos, DCP/ISC RMW compare-subtract hybrids, EB = SBC imm alias). Reference: nesdev wiki undocumented opcode table
- Run blargg mapper-0 suite (coredump, cpu_timing_test, ram_after_reset, registers)
- Then PPU/bus/timing, GUI (egui + winit) come after the CPU milestone
@@ -57,4 +65,6 @@ Follow-up options, in any order:
- opcode length is a growing match in opcode_len() (returns u8); migrate to a full 256-entry table when it gets big
- trace diff compares PC + A/X/Y/P/SP/CYC, ignoring disassembly/PPU columns
- Mapper 0 first, other mappers (MMC1, CNROM) implemented after CPU works
- Mappers use a trait-based design (Mapper trait + Box<dyn Mapper>) so new mappers are self-contained impl blocks; ROM data owned by Cartridge and passed in per call
- PRG RAM lives on the Cartridge (8KB), the bus interconnects it
- Test ROMs are homebrew/open, no ethics issue; game backups stay in gitignored roms/backup