nes_core/mapper/
m066_gxrom.rs

1//! `GxROM` (Mapper 066)
2//!
3//! <https://wiki.nesdev.org/w/index.php?title=GxROM>
4
5use crate::{
6    cart::Cart,
7    common::{Clock, Regional, Reset},
8    mapper::{Mapped, MappedRead, MappedWrite, Mapper, MemMap},
9    mem::MemBanks,
10    ppu::Mirroring,
11};
12use serde::{Deserialize, Serialize};
13
14#[derive(Debug, Clone, Serialize, Deserialize)]
15#[must_use]
16pub struct Gxrom {
17    mirroring: Mirroring,
18    chr_banks: MemBanks,
19    prg_rom_banks: MemBanks,
20}
21
22impl Gxrom {
23    const PRG_ROM_WINDOW: usize = 32 * 1024;
24    const CHR_WINDOW: usize = 8 * 1024;
25
26    const CHR_BANK_MASK: u8 = 0x0F; // 0b1111
27    const PRG_BANK_MASK: u8 = 0x30; // 0b110000
28
29    pub fn load(cart: &mut Cart) -> Mapper {
30        let gxrom = Self {
31            mirroring: cart.mirroring(),
32            chr_banks: MemBanks::new(0x0000, 0x1FFF, cart.chr_rom.len(), Self::CHR_WINDOW),
33            prg_rom_banks: MemBanks::new(0x8000, 0xFFFF, cart.prg_rom.len(), Self::PRG_ROM_WINDOW),
34        };
35        gxrom.into()
36    }
37}
38
39impl MemMap for Gxrom {
40    // PPU $0000..=$1FFF 8K CHR-ROM Bank Switchable
41    // CPU $8000..=$FFFF 32K PRG-ROM Bank Switchable
42
43    fn map_peek(&self, addr: u16) -> MappedRead {
44        match addr {
45            0x0000..=0x1FFF => MappedRead::Chr(self.chr_banks.translate(addr)),
46            0x8000..=0xFFFF => MappedRead::PrgRom(self.prg_rom_banks.translate(addr)),
47            _ => MappedRead::None,
48        }
49    }
50
51    fn map_write(&mut self, addr: u16, val: u8) -> MappedWrite {
52        if matches!(addr, 0x8000..=0xFFFF) {
53            self.chr_banks.set(0, (val & Self::CHR_BANK_MASK).into());
54            self.prg_rom_banks
55                .set(0, ((val & Self::PRG_BANK_MASK) >> 4).into());
56        }
57        MappedWrite::None
58    }
59}
60
61impl Mapped for Gxrom {
62    #[inline]
63    fn mirroring(&self) -> Mirroring {
64        self.mirroring
65    }
66
67    #[inline]
68    fn set_mirroring(&mut self, mirroring: Mirroring) {
69        self.mirroring = mirroring;
70    }
71}
72
73impl Clock for Gxrom {}
74impl Regional for Gxrom {}
75impl Reset for Gxrom {}