Hi All,
I'm trying to get the cpu_interrupts_v2/rom_singles/3-nmi_and_irq.nes and blargg_apu_2005.07.30/08.irq_timing.nes tests to pass in my emulator. The problem is that when the frame counter write ($4017) delay is 3 cycles rather than 4, the frame IRQ pending flag is set one CPU cycle too early. This results in off-by-one timing for every other APU frame IRQ in 3-nmi_and_irq When I remove the jitter by setting the write delay to always be 4 cycles, then these two tests pass, but then the APU jitter tests obviously fail (blargg_apu_2005.07.30/04-clock_jitter.nes and apu_test/rom_singles/4-jitter.nes).
Relevant tests that already pass (should be all the necessary prerequisites and more):
According to 3-nmi_and_irq, the proper test output is:When run against my emulator, I instead get the following oscillating failure:Consistent with the above, 08.irq_timing.nes fails with "2) Too soon".
What I've tried to fix this:
I'm trying to get the cpu_interrupts_v2/rom_singles/3-nmi_and_irq.nes and blargg_apu_2005.07.30/08.irq_timing.nes tests to pass in my emulator. The problem is that when the frame counter write ($4017) delay is 3 cycles rather than 4, the frame IRQ pending flag is set one CPU cycle too early. This results in off-by-one timing for every other APU frame IRQ in 3-nmi_and_irq When I remove the jitter by setting the write delay to always be 4 cycles, then these two tests pass, but then the APU jitter tests obviously fail (blargg_apu_2005.07.30/04-clock_jitter.nes and apu_test/rom_singles/4-jitter.nes).
Relevant tests that already pass (should be all the necessary prerequisites and more):
- Almost all CPU instruction tests (including cpu_timing_test.nes, dummy reads/writes)
- All NMI tests (except 3-nmi_and_irq.nes)
- All apu_test tests (including the IRQ related ones)
- All apu_test_2 tests
- cpu_interrupts_v2 ===== 1-cli_latency.nes 2-nmi_and_brk.nes
- blargg_apu_2005-07-30 ===== 01-len_ctr.nes 02-len_table.nes 03-irq_flag.nes 04-clock_jitter.nes 05-len_timing_mode0.nes 06-len_timing_mode1.nes 07-irq_flag_timing.nes
According to 3-nmi_and_irq, the proper test output is:
Code:
3-nmi_and_irq-------------NMI behavior when it interrupts IRQ vectoring.Result when run:NMI IRQ23 00 NMI occurs before LDA #121 00 NMI occurs after LDA #1 (Z flag clear)21 0020 00 NMI occurs after CLC, interrupting IRQ20 0020 0020 0020 0020 0020 00 Same result for 7 clocks before IRQ is vectored25 20 IRQ occurs, then NMI occurs after SEC in IRQ handler25 20
Code:
NMI IRQ23 0021 0021 0020 0020 0021 00 WRONG: IRQ went pending a cycle too early such that CLC didn't run before it started. NMI hijacked IRQ (expected).20 0021 00 WRONG: IRQ went pending a cycle too early such that CLC didn't run before it started. NMI hijacked IRQ (expected).20 0025 21 WRONG: IRQ should have been hijacked by NMI, but the IRQ went pending a cycle too early so both an IRQ and NMI fired in succession.25 2025 21 WRONG: IRQ should have fired a cycle later. NMI ran afterwards as expected.
What I've tried to fix this:
- Get rid of the jitter, always have a frame counter write delay of 4 cycles. Result: The tests in question pass, but APU jitter tests (obviously) fail.
- Instead of polling the interrupt handlers on the second-to-last instruction cycle, poll them on the last instruction cycle (both first half and second half). Result: even worse timings.
- Poll the interrupt handlers on every non-interrupt cycle. Result: nearly the same as no modification at all.
- How do I get my emulator to pass 3-nmi_and_irq and 08.irq_timing.nes without breaking the APU jitter tests?
- Is there another test or resource that will better explain what is wrong? Currently my emulator seems to be running exactly how I intend it to, which makes debugging this much more difficult.
- Is interrupt polling always on the second to last cycle of an instruction (other than for branches taken)? Or are some instructions different?
- ****My emulator fails scanline/scanline.nes if I don't move the JMP Absolute interrupt polling to the last cycle, which seems suspicious.
- Is there an emulator that has useful APU frame counter write and IRQ timing output so I can determine where my emulator diverges? FCEUX doesn't pass the tests in question.
- How are these back-to-back statements on the wiki not contradictions? "The output from the edge detector and level detector are polled at certain points to detect pending interrupts. For most instructions, this polling happens during the final cycle of the instruction, before the opcode fetch for the next instruction." and " Many references will claim that interrupts are polled during the last cycle of an instruction, but this is true only when talking about the output from the edge and level detectors. As can be deduced from above, it's really the status of the interrupt lines at the end of the second-to-last cycle that matters.".
Statistics: Posted by merehap — Sat Apr 20, 2024 9:47 pm — Replies 0 — Views 67