jc-SpaceXp / cNES

NES emulator written in C and targeted for Linux.
zlib License
6 stars 4 forks source link

Correct when cpu (hardware) interrupts are polled #11

Open jc-SpaceXp opened 1 year ago

jc-SpaceXp commented 1 year ago

After looking into the cpu interrupts I noticed cNES isn't emulating interrupts correctly.

All interrupts are polled on phi2 (of every cpu clock, not just the last cycle). When an interrupt is detected the appropriate edge and/or level detector is set. NMI is edge sensitive (high-to-low transitions), IRQ is level sensitive active low, setting the edge and level detectors respectively.

Now, the cpu polls these detectors during the T2 state (for branch instructions) and the T0 state. It will then set the instruction register to BRKs opcode (0x00) on the next T2 state (when it usually updates the instruction register, marking the completion of an instruction being executed) and execute the NMI/IRQ. If the detectors are set after a T2 state then it must wait for that instruction to complete before handling an interrupt (what we see for a branch's that don't hit T0 and have an interrupt noticed on T2's phi2).

D1x1 signal in the visual6502 goes from high-to-low when the detector is active has been polled.

jc-SpaceXp commented 1 year ago

cNES has these signals, nmi_pending for a high-to-low transition for the NMI, it then gets incorrectly polled on the last cycle of the current instruction being executed (not sure if that matches the T0 state or not). When polled it sets the process_interrupt flag which will handle the interrupt before the next opcode is fetched (if not delayed).

jc-SpaceXp commented 1 year ago

Not attempting to fix this issue for now. I would like to unit test the current NMI polling and interrupt handling first.

jc-SpaceXp commented 7 months ago

New branch attempts to address this issue: https://github.com/jc-SpaceXp/cNES/tree/cpu_interrupts_rework