From 5a42d76f1ea57ccb993b8c7d5ce617947d19bf3e Mon Sep 17 00:00:00 2001 From: Rekai Musuka Date: Sun, 21 Mar 2021 00:01:21 -0500 Subject: [PATCH] feat: implement LCDSTAT interrupt --- src/bus.rs | 11 ++++++++++- src/cpu.rs | 16 ---------------- src/ppu.rs | 34 +++++++++++++++++++++++++++------- 3 files changed, 37 insertions(+), 24 deletions(-) diff --git a/src/bus.rs b/src/bus.rs index 4e692fe..74ab198 100644 --- a/src/bus.rs +++ b/src/bus.rs @@ -223,7 +223,16 @@ impl Bus { 0xFF42 => self.ppu.pos.scroll_y = byte, 0xFF43 => self.ppu.pos.scroll_x = byte, 0xFF44 => self.ppu.pos.line_y = byte, - 0xFF45 => self.ppu.pos.ly_compare = byte == 0x01, // FIXME: We don't consider the possibility of a byte being different form 0x00 or 0x01 + 0xFF45 => { + // Update LYC + self.ppu.pos.ly_compare = byte; + + // Update Coincidence Flag + if self.ppu.stat.coincidence_intr() { + let are_equal = self.ppu.pos.line_y == byte; + self.ppu.stat.set_coincidence(are_equal); + } + } 0xFF47 => self.ppu.monochrome.bg_palette = byte.into(), 0xFF48 => self.ppu.monochrome.obj_palette_0 = byte.into(), 0xFF49 => self.ppu.monochrome.obj_palette_1 = byte.into(), diff --git a/src/cpu.rs b/src/cpu.rs index 738bb48..ac20718 100644 --- a/src/cpu.rs +++ b/src/cpu.rs @@ -76,24 +76,9 @@ impl Cpu { pub fn step(&mut self) -> Cycles { let opcode = self.fetch(); let instr = self.decode(opcode); - - // println!( - // "Addr: {:#06X} | Opcode: {:#04X} | Instr: {:X?}", - // self.reg.pc, opcode, instr - // ); - let cycles = self.execute(instr); - // if self.bus.read_byte(0xFF02) == 0x81 { - // let c = self.bus.read_byte(0xFF01) as char; - // self.bus.write_byte(0xFF02, 0x00); - - // print!("{}", c); - // std::io::stdout().flush().unwrap(); - // } - self.bus.step(cycles); - self.handle_interrupts(); cycles @@ -188,7 +173,6 @@ impl Cpu { // Disable all future interrupts self.set_ime(false); - self.execute(Instruction::CALL(Always, register)) } None => Cycles::new(0), // NO Interrupts were enabled and / or requested diff --git a/src/ppu.rs b/src/ppu.rs index 1b2260c..73e78bd 100644 --- a/src/ppu.rs +++ b/src/ppu.rs @@ -39,9 +39,6 @@ impl Ppu { pub fn step(&mut self, cycles: Cycles) { self.cycles += cycles; - // let tmp: u32 = self.cycles.into(); - // println!("Mode: {:?} | Cycles: {}", self.mode, tmp); - match self.stat.mode() { Mode::OamScan => { if self.cycles >= 80.into() { @@ -59,6 +56,10 @@ impl Ppu { if self.cycles >= 172.into() { self.cycles %= 172; + if self.stat.hblank_intr() { + self.interrupt.set_lcd_stat(true); + } + self.stat.set_mode(Mode::HBlank); self.draw_scanline(); } @@ -71,12 +72,26 @@ impl Ppu { let next_mode = if self.pos.line_y >= 144 { self.interrupt.set_vblank(true); + + if self.stat.vblank_intr() { + self.interrupt.set_lcd_stat(true); + } + Mode::VBlank } else { + if self.stat.oam_intr() { + self.interrupt.set_lcd_stat(true); + } + Mode::OamScan }; self.stat.set_mode(next_mode); + + if self.stat.coincidence_intr() { + let are_equal = self.pos.line_y == self.pos.ly_compare; + self.stat.set_coincidence(are_equal); + } } } Mode::VBlank => { @@ -90,6 +105,11 @@ impl Ppu { self.stat.set_mode(Mode::OamScan); self.pos.line_y = 0; } + + if self.stat.coincidence_intr() { + let are_equal = self.pos.line_y == self.pos.ly_compare; + self.stat.set_coincidence(are_equal); + } } } } @@ -192,11 +212,11 @@ impl Interrupt { bitfield! { pub struct LCDStatus(u8); impl Debug; - pub lyc_ly_intr, set_lyc_ly_intr: 6; + pub coincidence_intr, set_coincidence_intr: 6; pub oam_intr, set_oam_intr: 5; pub vblank_intr, set_vblank_intr: 4; pub hblank_intr, set_hblank_intr: 3; - pub coincidence, _: 2; // LYC == LY Flag + pub coincidence, set_coincidence: 2; // LYC == LY Flag from into Mode, _mode, set_mode: 1, 0; } @@ -215,7 +235,7 @@ impl Clone for LCDStatus { impl Default for LCDStatus { fn default() -> Self { - Self(0) + Self(0x80) // bit 7 is always 1 } } @@ -268,7 +288,7 @@ pub struct ScreenPosition { pub scroll_y: u8, pub scroll_x: u8, pub line_y: u8, - pub ly_compare: bool, + pub ly_compare: u8, pub window_y: u8, pub window_x: u8, }