From af77f9298a527e4cd03ade14f6397dfd2011e7a4 Mon Sep 17 00:00:00 2001 From: Thomas Date: Sun, 19 Nov 2023 06:27:14 +0100 Subject: [PATCH] Increase interrupt/HDMA cycle accuracy --- src/snes/bus/mainbus.rs | 60 +++++++++++++++++++++-------------------- 1 file changed, 31 insertions(+), 29 deletions(-) diff --git a/src/snes/bus/mainbus.rs b/src/snes/bus/mainbus.rs index 00486a3..23c80b9 100644 --- a/src/snes/bus/mainbus.rs +++ b/src/snes/bus/mainbus.rs @@ -745,41 +745,43 @@ where { fn tick(&mut self, ticks: Ticks) -> Result<()> { // This ratio is not based on anything that makes sense yet - self.ppu.tick(ticks * 8)?; + for _ in 0..(ticks * 8) { + self.ppu.tick(1)?; - let entered_vblank = self.ppu.get_clr_intreq_vblank(); - let entered_hblank = self.ppu.get_clr_intreq_hblank(); + let entered_vblank = self.ppu.get_clr_intreq_vblank(); + let entered_hblank = self.ppu.get_clr_intreq_hblank(); - if entered_hblank && !self.ppu.in_vblank() { - if self.ppu.get_current_scanline() == 0 { - self.hdma_reset(); - } + if entered_hblank && !self.ppu.in_vblank() { + if self.ppu.get_current_scanline() == 0 { + self.hdma_reset(); + } - self.hdma_run(); - } + self.hdma_run(); + } - if entered_vblank && self.nmitimen & (1 << 7) != 0 { - self.intreq_nmi = true; - } + if entered_vblank && self.nmitimen & (1 << 7) != 0 { + self.intreq_nmi = true; + } - // H/V interrupt - // TODO stop at EXACT H rather than at 0 - let hvint = match (self.nmitimen >> 4) & 0x03 { - // Disabled - 0 => false, - // H=H + V=* - 1 => self.ppu.get_current_scanline() != self.last_scanline, - // H=0, V=V (2) + H=H, V=V (3) - 2 | 3 => { - self.ppu.get_current_scanline() != self.last_scanline - && self.ppu.get_current_scanline() == usize::from(self.vtime) + // H/V interrupt + // TODO stop at EXACT H rather than at 0 + let hvint = match (self.nmitimen >> 4) & 0x03 { + // Disabled + 0 => false, + // H=H + V=* + 1 => self.ppu.get_current_scanline() != self.last_scanline, + // H=0, V=V (2) + H=H, V=V (3) + 2 | 3 => { + self.ppu.get_current_scanline() != self.last_scanline + && self.ppu.get_current_scanline() == usize::from(self.vtime) + } + _ => unreachable!(), + }; + self.last_scanline = self.ppu.get_current_scanline(); + if hvint { + self.intreq_int = true; + self.timeup.set(true); } - _ => unreachable!(), - }; - self.last_scanline = self.ppu.get_current_scanline(); - if hvint { - self.intreq_int = true; - self.timeup.set(true); } Ok(())