use super::MBC; pub struct MBC3 { rom: Box<[u8]>, ram: Box<[u8]>, rom_bank_no: u8, ram_bank_no: u8, ram_rtc_enabled: bool, } impl MBC3 { pub fn new(rom: Box<[u8]>, ram: Box<[u8]>) -> MBC3 { MBC3 { rom, ram, rom_bank_no: 1, ram_bank_no: 0, ram_rtc_enabled: false, } } fn active_rom_bank(&self) -> u8 { self.rom_bank_no } fn active_ram_bank(&self) -> u8 { self.ram_bank_no } } impl MBC for MBC3 { fn dump_ram(&self, file: &str) { super::super::write_file(&file, &self.ram).expect("Saving failed"); } fn read_byte(&self, addr: u16) -> u8 { match addr { 0x0000..=0x3FFF => self.rom[addr as usize], 0x4000..=0x7FFF => { let addr = addr - 0x4000; let abs_addr: usize = addr as usize + self.active_rom_bank() as usize * 0x4000; let val: u8 = self.rom[abs_addr]; val } 0xA000..=0xBFFF => { let addr = addr - 0xA000; match self.active_ram_bank() { 0x00..=0x03 => { self.ram[self.active_ram_bank() as usize * 0x2000 + addr as usize] } 0x08..=0x0C => { // TODO println!("MBC3: Ignoring RTC read"); 0 } _ => panic!( "MBC3: Accessing unknown RAM bank {:02X}", self.active_ram_bank() ), } } _ => { panic!("MBC3: Unable to read from {:04X}", addr); } } } fn write_byte(&mut self, addr: u16, val: u8) { match addr { 0x0000..=0x1FFF => match val { 0x0A => self.ram_rtc_enabled = true, 0x00 => self.ram_rtc_enabled = false, _ => println!("MBC3: Unknown MBC value {:02X} for {:04X}", val, addr), }, 0x2000..=0x3FFF => self.rom_bank_no = val & 0x7F, 0x4000..=0x5FFF => { // RAM bank select match val { 0x00..=0x03 => self.ram_bank_no = val, 0x08..=0x0C => self.ram_bank_no = val, _ => panic!("MBC3: Unknown RAM bank {:02X}", val), } } 0x6000..=0x7FFF => { // Latch clock data match val { 0x00 => println!("latch = 0"), 0x01 => println!("latch = 1"), // TODO: This should copy the current clock to the register _ => panic!("MBC3: Unknown latch value {:02X}", val), } } 0xA000..=0xBFFF => { let addr = addr - 0xA000; match self.active_ram_bank() { 0x00..=0x03 => { let active_bank = self.active_ram_bank() as usize; self.ram[active_bank * 0x2000 + addr as usize] = val; } 0x08..=0x0C => { // TODO println!("MBC3: Ignoring RTC write ({:02X})", val); } _ => panic!( "MBC3: Writing unknown RAM bank {:02X}", self.active_ram_bank() ), } } _ => panic!("MBC3: Writing {:02X} to {:04X} not supported", val, addr), } } }