diff --git a/snes-core/src/cpu/interface.rs b/snes-core/src/cpu/interface.rs index 18520c3..b560546 100644 --- a/snes-core/src/cpu/interface.rs +++ b/snes-core/src/cpu/interface.rs @@ -34,9 +34,9 @@ impl CPU { return false; } if self.registers.is_cpu_waiting_interrupt { - // TODO: check for interrupts here - let (bytes, cycles) = cycles::increment_cycles_while_stopped(); - self.registers.increment_pc(bytes); self.registers.cycles += cycles; + self.check_interrupts(bus); + let (_, cycles) = cycles::increment_cycles_while_stopped(); + self.registers.cycles += cycles; return false; } if self.registers.is_moving { diff --git a/snes-core/src/cpu/vectors.rs b/snes-core/src/cpu/vectors.rs index 3871550..418d69e 100644 --- a/snes-core/src/cpu/vectors.rs +++ b/snes-core/src/cpu/vectors.rs @@ -1,4 +1,4 @@ -use super::{interface::CPU, instructions::{phk::PHK, CPUInstruction, php::PHP, push_common}}; +use super::{instructions::{phk::PHK, php::PHP, push_common, CPUInstruction}, interface::CPU, internal_registers::RDNMI}; use crate::cpu::bus::Bus; @@ -38,13 +38,6 @@ impl CPU { self.registers.is_cpu_stopped = false; } - fn get_vector_from_interrupts(&self) -> Option { - if self.registers.get_irq_disable_flag() { - return None; - } - Some(Vector::Reset) - } - fn push_emulation_interrupt(&mut self, bus: &mut Bus) { if !self.registers.emulation_mode { PHK{}.execute(&mut self.registers, bus); @@ -57,14 +50,22 @@ impl CPU { PHP{}.execute(&mut self.registers, bus); } - pub fn handle_interrupts(&mut self, bus: &mut Bus) { + fn handle_interrupt(&mut self, bus: &mut Bus, vector: Vector) { self.push_emulation_interrupt(bus); - if let Some(vector) = self.get_vector_from_interrupts() { - let effective_vector = vector.get_base_address(); - self.registers.pc = effective_vector as u16; - self.registers.pbr = (effective_vector >> 16) as u8; + let effective_vector = vector.get_base_address(); + self.registers.pc = effective_vector as u16; + self.registers.pbr = (effective_vector >> 16) as u8; + } + + pub fn check_interrupts(&mut self, bus: &mut Bus) { + let rdnmi_byte = bus.read(RDNMI as u32); + if rdnmi_byte >> 7 != 0 { + self.registers.is_cpu_waiting_interrupt = false; + self.handle_interrupt(bus, Vector::NMI); + return; } } + } diff --git a/snes-core/src/ppu/interface.rs b/snes-core/src/ppu/interface.rs index a07117f..babdb88 100644 --- a/snes-core/src/ppu/interface.rs +++ b/snes-core/src/ppu/interface.rs @@ -3,6 +3,7 @@ use super::registers::PPURegisters; pub struct PPU { framebuffer: Vec, pub registers: PPURegisters, + was_vblank_nmi_set: bool, } impl PPU { @@ -10,6 +11,7 @@ impl PPU { Self { framebuffer: vec![], registers: PPURegisters::new(), + was_vblank_nmi_set: false, } } @@ -28,10 +30,12 @@ impl PPU { if self.registers.h_count > 339 { self.registers.h_count = 0; self.registers.v_count += 1; - if self.registers.v_count > 224 { + if self.registers.v_count > 224 && !self.was_vblank_nmi_set { self.registers.vblank_nmi = true; + self.was_vblank_nmi_set = true; } if self.registers.v_count > 261 { + self.was_vblank_nmi_set = false; self.registers.v_count = 0; } }