From 9203b61533a9776dbe8396304516818e52bba9d9 Mon Sep 17 00:00:00 2001 From: Rekai Musuka Date: Mon, 18 Jan 2021 02:22:45 -0600 Subject: [PATCH] fix: implement 0xff41 and fix CALL instruciton --- src/bus.rs | 8 ++++++++ src/cpu.rs | 8 ++++---- src/instruction.rs | 40 ++++++++++++++++++++++++++-------------- src/main.rs | 2 +- src/ppu.rs | 45 +++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 84 insertions(+), 19 deletions(-) diff --git a/src/bus.rs b/src/bus.rs index 2f9f7c3..2868f8c 100644 --- a/src/bus.rs +++ b/src/bus.rs @@ -108,6 +108,10 @@ impl Bus { 0xFF25 => self.sound.control.select.into(), 0xFF26 => self.sound.control.status.into(), 0xFF40 => self.ppu.lcd_control.into(), + 0xFF41 => self.ppu.stat.into(), + 0xFF42 => self.ppu.pos.scroll_y, + 0xFF43 => self.ppu.pos.scroll_x, + 0xFF44 => self.ppu.pos.line_y, 0xFF47 => self.ppu.monochrome.bg_palette.into(), _ => unimplemented!("Unable to read {:#06X} in I/O Registers", addr), } @@ -172,6 +176,10 @@ impl Bus { 0xFF25 => self.sound.control.select = byte.into(), 0xFF26 => self.sound.control.status = byte.into(), // FIXME: Should we control which bytes are written to here? 0xFF40 => self.ppu.lcd_control = byte.into(), + 0xFF41 => self.ppu.stat = byte.into(), + 0xFF42 => self.ppu.pos.scroll_y = byte, + 0xFF43 => self.ppu.pos.scroll_x = byte, + 0xFF44 => self.ppu.pos.line_y = byte, 0xFF47 => self.ppu.monochrome.bg_palette = byte.into(), _ => unimplemented!("Unable to write to {:#06X} in I/O Registers", addr), }; diff --git a/src/cpu.rs b/src/cpu.rs index be542fc..ed9ee0a 100644 --- a/src/cpu.rs +++ b/src/cpu.rs @@ -70,10 +70,10 @@ impl Cpu { let hl = self.register_pair(RegisterPair::HL); let sp = self.register_pair(RegisterPair::SP); - println!( - "A: {:#04X} | BC: {:#06X} | DE: {:#06X} | HL: {:#06X} | SP: {:#06X} | {}", - a, bc, de, hl, sp, flag - ); + // println!( + // "A: {:#04X} | BC: {:#06X} | DE: {:#06X} | HL: {:#06X} | SP: {:#06X} | {}", + // a, bc, de, hl, sp, flag + // ); // Get info from serial port // if self.bus.read_byte(0xFF02) == 0x81 { diff --git a/src/instruction.rs b/src/instruction.rs index ddad572..c33a464 100644 --- a/src/instruction.rs +++ b/src/instruction.rs @@ -61,7 +61,7 @@ pub enum Registers { Word(RegisterPair), } -#[derive(Debug, Copy, Clone)] +#[derive(Copy, Clone)] pub enum MATHTarget { HL, SP, @@ -1026,39 +1026,39 @@ impl Instruction { match cond { JumpCondition::NotZero => { if !flags.z { - Self::push(cpu, nn); - cpu.set_register_pair(RegisterPair::PC, pc + 1); + Self::push(cpu, pc); + cpu.set_register_pair(RegisterPair::PC, nn); return Cycles(24); } Cycles(12) } JumpCondition::Zero => { if flags.z { - Self::push(cpu, nn); - cpu.set_register_pair(RegisterPair::PC, pc + 1); + Self::push(cpu, pc); + cpu.set_register_pair(RegisterPair::PC, nn); return Cycles(24); } Cycles(12) } JumpCondition::NotCarry => { if !flags.c { - Self::push(cpu, nn); - cpu.set_register_pair(RegisterPair::PC, pc + 1); + Self::push(cpu, pc); + cpu.set_register_pair(RegisterPair::PC, nn); return Cycles(24); } Cycles(12) } JumpCondition::Carry => { if flags.c { - Self::push(cpu, nn); - cpu.set_register_pair(RegisterPair::PC, pc + 1); + Self::push(cpu, pc); + cpu.set_register_pair(RegisterPair::PC, nn); return Cycles(24); } Cycles(12) } JumpCondition::Always => { - Self::push(cpu, nn); - cpu.set_register_pair(RegisterPair::PC, pc + 1); + Self::push(cpu, pc); + cpu.set_register_pair(RegisterPair::PC, nn); Cycles(24) } } @@ -2038,14 +2038,26 @@ impl std::fmt::Debug for LDTarget { match *self { LDTarget::IndirectC => f.write_str("IndirectC"), LDTarget::Register(reg) => write!(f, "{:?}", reg), - LDTarget::IndirectRegister(pair) => write!(f, "{:?}", pair), - LDTarget::ByteAtAddress(addr) => write!(f, "{:#06X}", addr), + LDTarget::IndirectRegister(pair) => write!(f, "[{:?}]", pair), + LDTarget::ByteAtAddress(addr) => write!(f, "[{:#06X}]", addr), LDTarget::ImmediateWord(word) => write!(f, "{:#06X}", word), LDTarget::ImmediateByte(byte) => write!(f, "{:#04X}", byte), LDTarget::RegisterPair(pair) => write!(f, "{:?}", pair), LDTarget::ByteAtAddressWithOffset(byte) => { - write!(f, "{:#04X}", 0xFF00 + byte as u16) + write!(f, "[0xFF00 + {:#04X}, {:#06X}]", byte, 0xFF00 + byte as u16) } } } } + +impl std::fmt::Debug for MATHTarget { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match *self { + MATHTarget::HL => f.write_str("HL"), + MATHTarget::SP => f.write_str("SP"), + MATHTarget::Register(reg) => write!(f, "{:?}", reg), + MATHTarget::RegisterPair(pair) => write!(f, "{:?}", pair), + MATHTarget::ImmediateByte(byte) => write!(f, "{:#04X}", byte), + } + } +} diff --git a/src/main.rs b/src/main.rs index 17daecd..56ac559 100644 --- a/src/main.rs +++ b/src/main.rs @@ -11,7 +11,7 @@ fn main() { let instruction = game_boy.decode(opcode); println!( - "\nAddr: {:#06X} | Opcode: {:#04X} | Instr: {:X?}", + "Addr: {:#06X} | Opcode: {:#04X} | Instr: {:X?}", pc, opcode, instruction ); diff --git a/src/ppu.rs b/src/ppu.rs index 87b7b15..4f73a00 100644 --- a/src/ppu.rs +++ b/src/ppu.rs @@ -2,7 +2,9 @@ pub struct PPU { pub lcd_control: LCDControl, pub monochrome: Monochrome, + pub pos: ScreenPosition, pub vram: Box<[u8]>, + pub stat: LCDStatus, } impl Default for PPU { @@ -10,11 +12,54 @@ impl Default for PPU { Self { lcd_control: Default::default(), monochrome: Default::default(), + pos: Default::default(), + stat: Default::default(), vram: vec![0; 8192].into_boxed_slice(), } } } +#[derive(Debug, Clone, Copy, Default)] +pub struct LCDStatus { + lyc_eq_ly: bool, + mode2_stat: bool, + mode1_stat: bool, + mode0_stat: bool, + coincidence: bool, + ppu_mode: u8, +} + +impl From for LCDStatus { + fn from(byte: u8) -> Self { + Self { + lyc_eq_ly: (byte >> 6) & 0x01 == 0x01, + mode2_stat: (byte >> 5) & 0x01 == 0x01, + mode1_stat: (byte >> 4) & 0x01 == 0x01, + mode0_stat: (byte >> 3) & 0x01 == 0x01, + coincidence: (byte >> 2) & 0x01 == 0x01, + ppu_mode: byte & 0x03, + } + } +} + +impl From for u8 { + fn from(status: LCDStatus) -> Self { + 0x80 | (status.lyc_eq_ly as u8) << 6 + | (status.mode2_stat as u8) << 5 + | (status.mode1_stat as u8) << 4 + | (status.mode0_stat as u8) << 3 + | (status.coincidence as u8) << 2 + | (status.ppu_mode & 0x03) + } +} + +#[derive(Debug, Clone, Copy, Default)] +pub struct ScreenPosition { + pub scroll_y: u8, + pub scroll_x: u8, + pub line_y: u8, +} + #[derive(Debug, Clone, Copy, Default)] pub struct Monochrome { pub bg_palette: BackgroundPalette,