diff --git a/src/cartridge.rs b/src/cartridge.rs index f1ad753..a181b3b 100644 --- a/src/cartridge.rs +++ b/src/cartridge.rs @@ -26,7 +26,7 @@ impl Cartridge { pub fn new(rom: Box<[u8]>) -> Cartridge { let mbc_type: MemoryBankControllerType = match rom[0x0147] { 0x00 | 0x08 ... 0x09 => MemoryBankControllerType::None, - // 0x01 ... 0x03 => MemoryBankControllerType::MBC1, + 0x01 ... 0x03 => MemoryBankControllerType::MBC1, // 0x05 ... 0x06 => MemoryBankControllerType::MBC2, 0x0F ... 0x13 => MemoryBankControllerType::MBC3, // 0xFF => MemoryBankControllerType::HuC1, @@ -64,6 +64,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::MBC3 => Box::new(super::mbc::mbc3::MBC3::new(rom, ram)), _ => panic!("{:?} not implemented", mbc_type), }; diff --git a/src/cpu.rs b/src/cpu.rs index d62cc92..3f72d10 100644 --- a/src/cpu.rs +++ b/src/cpu.rs @@ -874,7 +874,10 @@ impl CPU { } pub fn run_instruction(&mut self) { - // self.debug = !self.interconnect.is_boot_rom(); + //self.debug = !self.interconnect.is_boot_rom(); + if self.ip == 0x553 { + self.debug = true; + } // Check for interrupts. // TODO: Make this right if self.ime { @@ -902,7 +905,7 @@ impl CPU { // We need to double-check the flags let instruction = self.read_byte(self.ip); if self.debug { - print!("{:#04x}: [SP: {:#04X}] i={:02X}. ", &self.ip, &self.sp, &instruction); + print!("{:#06x}: [SP: {:#04X}] i={:02X}. ", &self.ip, &self.sp, &instruction); for i in 0 .. 6 { print!("{}: {:02X} ", REG_NAMES[i], self.get_8bit_reg(i)); } @@ -1356,6 +1359,9 @@ impl CPU { }, 0xC3 => { let dst = to_u16(self.load_args(2)); + if self.debug { + println!("JMP {:04X}", dst); + } self.jmp_p(dst); 16 }, @@ -1379,7 +1385,13 @@ impl CPU { let c = self.flags & FLAG_Z == FLAG_Z; self.ret_condition("Z".to_owned(), c) }, - 0xC9 => {self.ret(); 16}, + 0xC9 => { + if self.debug { + println!("RET"); + } + self.ret(); + 16 + }, 0xCA => { let c = self.flags & FLAG_Z == FLAG_Z; self.jmp_p_condition("Z".to_owned(), c) @@ -1433,7 +1445,12 @@ impl CPU { let c = self.flags & FLAG_C == FLAG_C; self.ret_condition("C".to_owned(), c) }, - 0xD9 => self.reti(), + 0xD9 => { + if self.debug { + println!("RETI"); + } + self.reti() + } 0xDA => { let c = self.flags & FLAG_C == FLAG_C; self.jmp_p_condition("C".to_owned(), c) diff --git a/src/mbc/mbc1.rs b/src/mbc/mbc1.rs new file mode 100644 index 0000000..65fb46f --- /dev/null +++ b/src/mbc/mbc1.rs @@ -0,0 +1,93 @@ +use super::mbc::MBC; + +pub struct MBC1 { + rom: Box<[u8]>, + ram: Box<[u8]>, + bank_no: u8, + ram_rtc_enabled: bool, + ram_bank_no: u8, + + rom_banks: u16, + + bank_mode: u8, + bank_no_high: u8, +} + +impl MBC1 { + pub fn new(rom: Box<[u8]>, ram: Box<[u8]>) -> MBC1 { + MBC1 { + rom: rom, + ram: ram, + bank_no: 0, + ram_rtc_enabled: false, + ram_bank_no: 0, + rom_banks: 0, + bank_mode: 0, + bank_no_high: 0, + } + } +} + +impl MBC for MBC1 { + fn read_byte(&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 + }, + 0xA000 ... 0xBFFF => { + // TODO: Safty checks? Or let rust handle this? + let addr = addr - 0xA000; + if self.ram_bank_no < 4 { + println!("Access [{:02X}] {:04X}", self.ram_bank_no, addr); + self.ram[self.ram_bank_no as usize * 0x2000 + addr as usize] + } else { + println!("Ignoring RTC read"); + 0 + } + } + _ => { + panic!("Cartride: 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!("Unknown MBC value {:02X} for {:04X}", val, addr) + } + }, + 0x2000 ... 0x3FFF => self.bank_no = val & 0x7F, + 0x4000 ... 0x5FFF => { + // RAM bank select + match val { + 0x00 ... 0x03 => self.ram_bank_no = 0, //val, + 0x08 ... 0x0C => self.ram_bank_no = val, // RTC clock values, TODO + _ => panic!("Unknown MBC1 RAM BANK NO: {:02X}", val) + } + + }, + 0x6000 ... 0x7FFF => { + // Latch clock data, ignore. + }, + 0xA000 ... 0xBFFF => { + // TODO: Safty checks? Or let rust handle this? + let addr = addr - 0xA000; + if self.ram_bank_no < 4 { + self.ram[self.ram_bank_no as usize * 0x2000 + addr as usize] = val; + } else { + println!("Ignoring RTC write"); + } + } + _ => panic!("MBC1: Writing {:02X} to {:04X} not supported", val, addr), + } + } +} diff --git a/src/mbc/mod.rs b/src/mbc/mod.rs index 14c0767..127b37b 100644 --- a/src/mbc/mod.rs +++ b/src/mbc/mod.rs @@ -1,2 +1,3 @@ pub mod mbc; +pub mod mbc1; pub mod mbc3;