tetanes_core/mapper/
m000_nrom.rs1use crate::{
6 cart::Cart,
7 common::{Clock, Regional, Reset, Sram},
8 mapper::{
9 self, MapRead, MapWrite, MappedRead, MappedWrite, Mapper, Mirrored, OnBusRead, OnBusWrite,
10 },
11 ppu::Mirroring,
12};
13use serde::{Deserialize, Serialize};
14
15#[derive(Debug, Copy, Clone, Serialize, Deserialize)]
17#[must_use]
18pub struct Nrom {
19 pub mirroring: Mirroring,
20 pub mirror_prg_rom: bool,
21}
22
23impl Nrom {
24 const PRG_RAM_SIZE: usize = 8 * 1024;
25 const CHR_RAM_SIZE: usize = 8 * 1024;
26
27 pub fn load(cart: &mut Cart) -> Result<Mapper, mapper::Error> {
28 cart.add_prg_ram(Self::PRG_RAM_SIZE);
30 if !cart.has_chr_rom() && cart.chr_ram.is_empty() {
33 cart.add_chr_ram(Self::CHR_RAM_SIZE);
34 };
35 let nrom = Self {
36 mirroring: cart.mirroring(),
37 mirror_prg_rom: cart.prg_rom.len() <= 0x4000,
38 };
39 Ok(nrom.into())
40 }
41}
42
43impl Mirrored for Nrom {
44 fn mirroring(&self) -> Mirroring {
45 self.mirroring
46 }
47
48 fn set_mirroring(&mut self, mirroring: Mirroring) {
49 self.mirroring = mirroring;
50 }
51}
52
53impl MapRead for Nrom {
54 fn map_peek(&self, addr: u16) -> MappedRead {
60 match addr {
61 0x0000..=0x1FFF => MappedRead::Chr(addr.into()),
62 0x6000..=0x7FFF => MappedRead::PrgRam((addr & 0x1FFF).into()),
63 0x8000..=0xBFFF => MappedRead::PrgRom((addr & 0x3FFF).into()),
64 0xC000..=0xFFFF => {
65 let mirror = if self.mirror_prg_rom { 0x3FFF } else { 0x7FFF };
66 MappedRead::PrgRom((addr & mirror).into())
67 }
68 _ => MappedRead::Bus,
69 }
70 }
71}
72
73impl MapWrite for Nrom {
74 fn map_write(&mut self, addr: u16, val: u8) -> MappedWrite {
75 match addr {
76 0x0000..=0x1FFF => MappedWrite::ChrRam(addr.into(), val),
77 0x6000..=0x7FFF => MappedWrite::PrgRam((addr & 0x1FFF).into(), val),
78 _ => MappedWrite::Bus,
79 }
80 }
81}
82
83impl OnBusRead for Nrom {}
84impl OnBusWrite for Nrom {}
85impl Reset for Nrom {}
86impl Clock for Nrom {}
87impl Regional for Nrom {}
88impl Sram for Nrom {}