From 8c6a6fa33c374de658a4574ed897c9e825df2902 Mon Sep 17 00:00:00 2001 From: Kevin Hamacher Date: Wed, 1 Jun 2016 15:28:20 +0200 Subject: [PATCH] Add MBC2 implementation --- src/cartridge.rs | 3 ++- src/mbc/mbc1.rs | 4 +-- src/mbc/mbc2.rs | 70 ++++++++++++++++++++++++++++++++++++++++++++++++ src/mbc/mod.rs | 1 + 4 files changed, 75 insertions(+), 3 deletions(-) create mode 100644 src/mbc/mbc2.rs diff --git a/src/cartridge.rs b/src/cartridge.rs index a181b3b..8984512 100644 --- a/src/cartridge.rs +++ b/src/cartridge.rs @@ -27,7 +27,7 @@ impl Cartridge { let mbc_type: MemoryBankControllerType = match rom[0x0147] { 0x00 | 0x08 ... 0x09 => MemoryBankControllerType::None, 0x01 ... 0x03 => MemoryBankControllerType::MBC1, - // 0x05 ... 0x06 => MemoryBankControllerType::MBC2, + 0x05 ... 0x06 => MemoryBankControllerType::MBC2, 0x0F ... 0x13 => MemoryBankControllerType::MBC3, // 0xFF => MemoryBankControllerType::HuC1, _ => panic!("Unsupported MBC type: {:02X}", rom[0x0147]), @@ -65,6 +65,7 @@ impl Cartridge { let mbc: Box = match mbc_type { MemoryBankControllerType::None => Box::new(super::mbc::mbc::NoMBC::new(rom, ram)), MemoryBankControllerType::MBC1 => Box::new(super::mbc::mbc1::MBC1::new(rom, ram)), + MemoryBankControllerType::MBC2 => Box::new(super::mbc::mbc2::MBC2::new(rom, ram)), MemoryBankControllerType::MBC3 => Box::new(super::mbc::mbc3::MBC3::new(rom, ram)), _ => panic!("{:?} not implemented", mbc_type), }; diff --git a/src/mbc/mbc1.rs b/src/mbc/mbc1.rs index 1ce277c..c49932c 100644 --- a/src/mbc/mbc1.rs +++ b/src/mbc/mbc1.rs @@ -58,7 +58,7 @@ impl MBC for MBC1 { self.ram[self.active_ram_bank() as usize * 0x2000 + addr as usize] } _ => { - panic!("Cartride: Unable to read from {:04X}", addr); + panic!("MBC1: Unable to read from {:04X}", addr); } } } @@ -73,12 +73,12 @@ impl MBC for MBC1 { } }, 0x2000 ... 0x3FFF => { - println!("Selecting bank {:02X}", self.rom_bank_no); if val != 0 { self.rom_bank_no = val & 0x1F; } else { self.rom_bank_no = 1; // 0x00 -> 0x01, 0x20 -> 0x21 etc } + println!("MBC1: Selecting bank {:02X}", self.rom_bank_no); } 0x4000 ... 0x5FFF => { // Upper ROM bank / RAM bank select diff --git a/src/mbc/mbc2.rs b/src/mbc/mbc2.rs new file mode 100644 index 0000000..22a9e62 --- /dev/null +++ b/src/mbc/mbc2.rs @@ -0,0 +1,70 @@ +use super::mbc::MBC; + +pub struct MBC2 { + rom: Box<[u8]>, + ram: Box<[u8]>, + rom_bank_no: u8, + ram_enable: bool, +} + +impl MBC2 { + pub fn new(rom: Box<[u8]>, ram: Box<[u8]>) -> MBC2 { + MBC2 { + rom: rom, + ram: ram, + rom_bank_no: 0, + ram_enable: false, + } + } + + fn active_rom_bank(&self) -> u8 { + self.rom_bank_no + } + } + +impl MBC for MBC2 { + 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 ... 0xA1FF => { + let addr = addr - 0xA000; + self.ram[addr as usize] & 0x0F + } + _ => { + panic!("MBC2: Unable to read from {:04X}", addr); + } + } + } + + fn write_byte(&mut self, addr: u16, val: u8) { + match addr { + 0x0000 ... 0x1FFF => { + // To enable the ram, the LSB of the higher byte must be 0 + if val & 0x0100 == 0 { + match val { + 0x0A => self.ram_enable = true, + 0x00 => self.ram_enable = false, + _ => println!("Unknown MBC2 value {:02X} for {:04X}", val, addr) + } + } else { + println!("MBC2: Write {:02X} to {:04X} has no effect", val, addr); + } + }, + 0x2000 ... 0x3FFF => { + if val & 0x0100 == 1 { + self.rom_bank_no = val & 0x0F; + println!("MBC2: Selecting bank {:02X}", self.rom_bank_no); + } else { + println!("MBC2: Write {:02X} to {:04X} has no effect", val, addr); + } + } + _ => panic!("MBC2: Writing {:02X} to {:04X} not supported", val, addr), + } + } +} diff --git a/src/mbc/mod.rs b/src/mbc/mod.rs index 127b37b..fdcb7ca 100644 --- a/src/mbc/mod.rs +++ b/src/mbc/mod.rs @@ -1,3 +1,4 @@ pub mod mbc; pub mod mbc1; +pub mod mbc2; pub mod mbc3;