From 6455732043f3cdcb95e87df65e6664a919c26cac Mon Sep 17 00:00:00 2001 From: Kevin Hamacher Date: Sun, 29 May 2016 18:36:40 +0200 Subject: [PATCH] Add support for MBC1. TODO: Refactor the cartridge code --- src/cartridge.rs | 69 ++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 67 insertions(+), 2 deletions(-) diff --git a/src/cartridge.rs b/src/cartridge.rs index b83b054..edfb9f8 100644 --- a/src/cartridge.rs +++ b/src/cartridge.rs @@ -25,6 +25,9 @@ pub struct Cartridge { ram_size: RamSize, rom_banks: u16, + + bank_mode: u8, + bank_no_high: u8, } impl Cartridge { @@ -77,15 +80,18 @@ impl Cartridge { ram_size: ram_size, rom_banks: rom_banks, - ram: ram + ram: ram, + bank_mode: 0, + bank_no_high: 0, } } - pub fn read_byte(&self, addr: u16) -> u8 { + pub fn read_byte_mbc3(&self, addr: u16) -> u8 { match addr { 0x0000 ... 0x3FFF => self.rom[addr as usize], 0x4000 ... 0x7FFF => { let addr = addr - 0x4000; + println!("BankNo: {:02X}", self.bank_no); let abs_addr: usize = addr as usize + self.bank_no as usize * 0x4000; let val: u8 = self.rom[abs_addr]; val @@ -106,6 +112,43 @@ impl Cartridge { } } + pub fn read_byte_mbc1(&self, addr: u16) -> u8 { + match addr { + 0x0000 ... 0x3FFF => self.rom[addr as usize], + 0x4000 ... 0x7FFF => { + let addr = addr - 0x4000; + let mut bank: u8 = self.bank_no; + if self.bank_mode == 0 { + bank |= self.bank_no_high << 5; + } + println!("BankNo: {:02X}", bank); + let abs_addr: usize = addr as usize + bank as usize * 0x4000; + let val: u8 = self.rom[abs_addr]; + val + }, + 0xA000 ... 0xBFFF => { + // TODO: Safty checks? Or let rust handle this? + let addr = addr - 0xA000; + let mut bank: u8 = 0; + if self.bank_mode == 1 { + bank = self.bank_no_high + } + + self.ram[bank as usize * 0x2000 + addr as usize] + } + _ => { + panic!("Cartride: Unable to read from {:04X}", addr); + } + } + } + pub fn read_byte(&self, addr: u16) -> u8{ + match self.mbc_type { + MemoryBankControllerType::MBC1 => self.read_byte_mbc1(addr), + MemoryBankControllerType::MBC3 | MemoryBankControllerType::None => self.read_byte_mbc3(addr), + _ => panic!("MBC not supported.") + } + } + fn write_byte_none(&mut self, addr: u16, val: u8) { match addr { 0xA000 ... 0xBFFF => { @@ -116,6 +159,27 @@ impl Cartridge { } } + fn write_byte_mbc1(&mut self, addr: u16, val: u8) { + match addr { + 0x2000 ... 0x3FFF => { + // Write low bits of addr. + self.bank_no &= 0xE0; + self.bank_no |= val & 0x1F; + + // Can't select 0x00, 0x20, 0x40, 0x60. Adapt it to 0x01, 0x21, 0x41, 0x61 + if self.bank_no & 0x1F == 0 { + self.bank_no |= 1; + } + } + 0x4000 ... 0x5FFF => { + self.bank_no_high = val & 3; + } + 0x6000 ... 0x7FFF => { + self.bank_mode = val & 1; + } + _ => panic!("MBC1 Write {:02X} to {:04X} unsupported", val, addr), + } + } fn write_byte_mbc3(&mut self, addr: u16, val: u8) { match addr { 0x0000 ... 0x1FFF => { @@ -154,6 +218,7 @@ impl Cartridge { pub fn write_byte(&mut self, addr: u16, val: u8) { match self.mbc_type { MemoryBankControllerType::None => self.write_byte_none(addr, val), + MemoryBankControllerType::MBC1 => self.write_byte_mbc1(addr, val), MemoryBankControllerType::MBC3 => self.write_byte_mbc3(addr, val), _ => panic!("MBC not supported.") }