diff --git a/src/cpu.rs b/src/cpu.rs index 503bf3d..a5abd07 100644 --- a/src/cpu.rs +++ b/src/cpu.rs @@ -102,8 +102,24 @@ impl CPU { if self.debug { println!("RL {}", REG_NAMES[reg_id]); } - self.regs[REG_A].rotate_left(val as u32); - } + + let carry = self.flags & FLAG_C > 0; + if !carry { + // No carry before, now we got a carry => set it + if self.regs[REG_A] & 0x80 == 0x80 { + self.set_flag(FLAG_C); + } + self.regs[REG_A] = val << 1; + } else { + if self.regs[REG_A] & 0x80 == 0 { + self.clear_flag(FLAG_C); + } + self.regs[REG_A] = val << 1 | 1; + } + self.clear_flag(FLAG_Z); + self.clear_flag(FLAG_N); + self.clear_flag(FLAG_H); + }, 0x40 ... 0x47 => { // Test 0th bit let reg_id = (instruction - 0x40) as usize; @@ -393,19 +409,22 @@ impl CPU { if self.debug { println!("RLA"); } - let carry = self.flags & FLAG_C == FLAG_C; + let carry = self.flags & FLAG_C > 0; if !carry { // No carry before, now we got a carry => set it if self.regs[REG_A] & 0x80 == 0x80 { - self.flags |= FLAG_C + self.set_flag(FLAG_C); } self.regs[REG_A] = self.regs[REG_A] << 1; } else { if self.regs[REG_A] & 0x80 == 0 { - self.flags &= !FLAG_C; + self.clear_flag(FLAG_C); } self.regs[REG_A] = self.regs[REG_A] << 1 | 1; } + self.clear_flag(FLAG_Z); + self.clear_flag(FLAG_N); + self.clear_flag(FLAG_H); 4 }, 0x18 => { diff --git a/src/display.rs b/src/display.rs index e3cad99..7e3424c 100644 --- a/src/display.rs +++ b/src/display.rs @@ -93,7 +93,10 @@ impl Display { pub fn write_byte(&mut self, addr: u16, val: u8) { match addr { - 0x8000 ... 0x9FFF => self.vram[(addr - 0x8000) as usize] = val, + 0x8000 ... 0x9FFF => { + println!("VRAM: Write {:02X} to {:04X}", val, addr); + self.vram[(addr - 0x8000) as usize] = val; + } 0xFF40 => self.control = val, 0xFF41 => self.status = val, 0xFF42 => self.scrolly = val, diff --git a/src/interconnect.rs b/src/interconnect.rs index 50b9b9f..953f8aa 100644 --- a/src/interconnect.rs +++ b/src/interconnect.rs @@ -9,6 +9,15 @@ use super::sound; use super::timer; use super::serial; +#[derive(Debug)] +enum MemoryBankControllerType { + None, + MBC1, + MBC2, + MBC3, + HuC1, +} + pub struct Interconnect { bios: Box<[u8]>, rom: Box<[u8]>, @@ -22,10 +31,24 @@ pub struct Interconnect { infrared_com_port: u8, serial: serial::Serial, timer: timer::Timer, + + bank_no: u16, + mbc_type: MemoryBankControllerType, } impl Interconnect { pub fn new(bios: Box<[u8]>, rom: Box<[u8]>) -> Interconnect { + let mbc: MemoryBankControllerType = match rom[0x0147] { + 0x00 | 0x08 ... 0x09 => MemoryBankControllerType::None, +// 0x01 ... 0x03 => MemoryBankControllerType::MBC1, +// 0x05 ... 0x06 => MemoryBankControllerType::MBC2, +// 0x0F ... 0x13 => MemoryBankControllerType::MBC3, +// 0xFF => MemoryBankControllerType::HuC1, + _ => panic!("Unsupported MBC type"), + }; + + println!("MBC Type: {:?}", &mbc); + Interconnect { bios: bios, rom: rom, @@ -40,6 +63,9 @@ impl Interconnect { disable_bootrom: 0, timer: timer::Timer::new(), serial: serial::Serial::new(), + + bank_no: 0, + mbc_type: mbc, } } @@ -65,14 +91,22 @@ impl Interconnect { // TODO: if some flag set, use bios, otherwise only use rom // For now, just use bios match addr { - 0x0000 ... 0x7FFF => { + 0x0000 ... 0x3FFF => { // TODO: Check if bios or cartridge (additional condition: isEnabled) if addr < 0x100 && self.disable_bootrom == 0 { self.bios[addr as usize] } else { - self.rom[addr as usize] + let val: u8 = self.rom[addr as usize]; + println!("Access {:04X} = {:02X}", addr, val); + val } - } + }, + 0x4000 ... 0x7FFF => { + let abs_addr: usize = addr as usize + self.bank_no as usize * 0x4000; + let val: u8 = self.rom[abs_addr]; + println!("Access {:04X}{:04X} = {:02X}", self.bank_no, addr, val); + val + }, 0x8000 ... 0x9FFF => self.display.read_byte(addr), 0xC000 ... 0xDFFF => { self.ram[(addr - 0xC000) as usize]