From 7affd81f1d8a638ce4fc7d35c815a2759304eb58 Mon Sep 17 00:00:00 2001 From: ichirin2501 Date: Fri, 9 Feb 2024 21:19:11 +0900 Subject: [PATCH] prevent NMI from occurring multiple times at almost the same timing --- nes/cpu.go | 5 +++++ nes/instruction.go | 6 +++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/nes/cpu.go b/nes/cpu.go index a623754..13cdd71 100644 --- a/nes/cpu.go +++ b/nes/cpu.go @@ -381,6 +381,11 @@ func (cpu *CPU) pollInterrupts() { } } +func (cpu *CPU) clearNMIInterruptState() { + cpu.nmiSignal = false + cpu.nmiTriggered = false +} + func (cpu *CPU) Read(addr uint16) byte { cpu.bus.RunDMAIfOccurred(true) cpu.pollInterruptSignals() diff --git a/nes/instruction.go b/nes/instruction.go index 97c169b..d7bce1f 100644 --- a/nes/instruction.go +++ b/nes/instruction.go @@ -470,10 +470,10 @@ func (cpu *CPU) brk() { // As far as I checked with cpu_interrupts_v2/2-nmi_and_brk.nes, // it seems to be expecting the NMI edge detector timing. if cpu.nmiSignal || cpu.nmiTriggered { - cpu.nmiSignal = false cpu.push(cpu.P.Byte() | 0x30) cpu.P.SetInterruptDisable(true) cpu.PC = cpu.read16(0xFFFA) + cpu.clearNMIInterruptState() } else { cpu.push(cpu.P.Byte() | 0x30) cpu.P.SetInterruptDisable(true) @@ -504,7 +504,6 @@ ref: https://www.nesdev.org/wiki/CPU_interrupts#IRQ_and_NMI_tick-by-tick_executi */ func (cpu *CPU) nmi() { cpu.interrupting = true - cpu.nmiSignal = false cpu.Read(cpu.PC) // dummy read cpu.Read(cpu.PC) // dummy read @@ -513,6 +512,7 @@ func (cpu *CPU) nmi() { cpu.P.SetInterruptDisable(true) cpu.PC = cpu.read16(0xFFFA) + cpu.clearNMIInterruptState() cpu.interrupting = false } @@ -522,10 +522,10 @@ func (cpu *CPU) irq() { cpu.Read(cpu.PC) // dummy read cpu.push16(cpu.PC) if cpu.nmiSignal || cpu.nmiTriggered { - cpu.nmiSignal = false cpu.push(cpu.P.Byte() | 0x20) cpu.P.SetInterruptDisable(true) cpu.PC = cpu.read16(0xFFFA) + cpu.clearNMIInterruptState() } else { cpu.push(cpu.P.Byte() | 0x20) cpu.P.SetInterruptDisable(true)