reznez/memory/mappers/
mapper076.rs

1use crate::memory::mapper::*;
2
3const PRG_LAYOUT: PrgLayout = PrgLayout::new(&[
4    PrgWindow::new(0x6000, 0x7FFF, 8 * KIBIBYTE, Bank::EMPTY),
5    PrgWindow::new(0x8000, 0x9FFF, 8 * KIBIBYTE, Bank::switchable_rom(P0)),
6    PrgWindow::new(0xA000, 0xBFFF, 8 * KIBIBYTE, Bank::switchable_rom(P1)),
7    PrgWindow::new(0xC000, 0xDFFF, 8 * KIBIBYTE, Bank::fixed_rom(BankIndex::SECOND_LAST)),
8    PrgWindow::new(0xE000, 0xFFFF, 8 * KIBIBYTE, Bank::fixed_rom(BankIndex::LAST)),
9]);
10
11const CHR_LAYOUT: ChrLayout = ChrLayout::new(&[
12    ChrWindow::new(0x0000, 0x07FF, 2 * KIBIBYTE, Bank::switchable_rom(C0)),
13    ChrWindow::new(0x0800, 0x0FFF, 2 * KIBIBYTE, Bank::switchable_rom(C1)),
14    ChrWindow::new(0x1000, 0x17FF, 2 * KIBIBYTE, Bank::switchable_rom(C2)),
15    ChrWindow::new(0x1800, 0x1FFF, 2 * KIBIBYTE, Bank::switchable_rom(C3)),
16]);
17
18const BANK_INDEX_REGISTER_IDS: [Option<BankRegisterId>; 8] =
19    [None, None, Some(C0), Some(C1), Some(C2), Some(C3), Some(P0), Some(P1)];
20
21// NAMCOT-3446 
22// Similar to Namcot 108, but with only large CHR windows and more PRG and CHR.
23pub struct Mapper076 {
24    selected_register_id: BankRegisterId,
25}
26
27impl Mapper for Mapper076 {
28    fn initial_layout(&self) -> InitialLayout {
29        InitialLayout::builder()
30            .prg_max_bank_count(16)
31            .prg_bank_size(8 * KIBIBYTE)
32            .prg_windows(PRG_LAYOUT)
33            .chr_max_bank_count(64)
34            .chr_bank_size(2 * KIBIBYTE)
35            .chr_windows(CHR_LAYOUT)
36            .name_table_mirroring_source(NameTableMirroringSource::Cartridge)
37            .build()
38    }
39
40    fn write_to_cartridge_space(&mut self, params: &mut MapperParams, address: CpuAddress, value: u8) {
41        match address.to_raw() {
42            0x0000..=0x401F => unreachable!(),
43            0x4020..=0x5FFF => { /* Do nothing. */ }
44            0x6000..=0x7FFF => params.write_prg(address, value),
45            0x8000..=0x9FFF => {
46                if address.to_raw() % 2 == 0 {
47                    self.bank_select(params, value);
48                } else {
49                    self.set_bank_index(params, value);
50                }
51            }
52            0xA000..=0xFFFF => { /* Do nothing. */ }
53        }
54    }
55}
56
57impl Mapper076 {
58    pub fn new() -> Self {
59        Self {
60            selected_register_id: C0,
61        }
62    }
63
64    fn bank_select(&mut self, _params: &mut MapperParams, value: u8) {
65        if let Some(reg_id) = BANK_INDEX_REGISTER_IDS[(value & 0b0000_0111) as usize] {
66            self.selected_register_id = reg_id;
67        }
68    }
69
70    fn set_bank_index(&mut self, params: &mut MapperParams, value: u8) {
71        let bank_index = u16::from(value & 0b0011_1111);
72        params.set_bank_register(self.selected_register_id, bank_index);
73    }
74}