nmi_suppression problem

This is an archive of a topic from NESdev BBS, taken in mid-October 2019 before a server upgrade.
View original topic
nmi_suppression problem
by on (#19461)
Ive problems with the nmi_suppression test.
my questions goes like this:

1. after how many PPU cycles is the actual read made in an opcode (is it same for all read opcodes)

2. My solution for test 8 in the vbl_timing was to in my "Read PPU Status" I check if ppu-clock equals to 89341 then suppress the flag!
is this a hack?

3. when is vblank-flag actually set? isnt that exactly at the time as NMI is called (if enabled)

thanks
Re: nmi_suppression problem
by on (#19642)
Since nobody else has replied...

n6 wrote:
1. after how many PPU cycles is the actual read made in an opcode (is it same for all read opcodes)


Each CPU cycle performs either 1 read or 1 write. LDA $2002 is 4 cycles, and therefore performs 4 reads (1 to read the opcode, 1 for the low byte of address, 1 for high byte of address, and one read from the assembled address ($2002)). So in the case of LDA absolute -- the actual $2002 read is the very last read performed (on the 4th cycle of the instruction).

This doc: http://nesdev.com/6502_cpu.txt lays out which reads/writes are performed and when for every instruction (even "illegal" ones). As well as other things the CPU is doing during that time. (Scroll down 75% of the way through the doc)

Quote:
2. My solution for test 8 in the vbl_timing was to in my "Read PPU Status" I check if ppu-clock equals to 89341 then suppress the flag!
is this a hack?


I wouldn't call it a hack. It's a special case scenario. There's really no other way to emulate it other than to check for a reads on a specific cycle and change the behavior accordingly.

Quote:
3. when is vblank-flag actually set?


Immediately at the start of VBlank.

Code:
|--idle scanline--| |--    VBlank   --|
336-337-338-339-340-000-001-002-003-004
                   ^
                   |
                   $2002.7 goes high


I.E., on cycle 340 it would be clear, and on 0 it would be set

Quote:
isnt that exactly at the time as NMI is called (if enabled)


NMI is triggered by $2002.7 going high when $2000.7 is high (and vice versa) -- so yes. Although there is a slight (~2 CPU cycle) delay between when the NMI is triggered and when the NMI handler is invoked. I'm still a little fuzzy on the details of why. Byuu explained it all in this thread:

http://nesdev.com/bbs/viewtopic.php?t=1695

In that thread we were speaking about IRQs, but the same thing seems to happen for NMIs as well.

by on (#19651)
Thanks for your answer, one ? though...
Ive changed and are now updating cycles through the opcode (instead of in the end). Now #8 of vbl-timing failes! why did it work when I updated the cycles in the end (this must have been incorrect right, since the opcode didnt do the status read at that time!)

by on (#19653)
It's hard to say -- this is the kind of problem which can only be resolved by fine tuning your emulator's timing.

If you were doing it at the end of the instruction before, but are now doing it on the last cycle of the instruction -- your read might be coming 1 cycle earlier than it was before which would be throwing off your timing.

by on (#19657)
actually I incremented clock after the read, so its 3 CPU cycles off. blarggs cpu timing test passes, and my NMI takes 7 cycles, and I take care of the extra PPU cycle that may occur if bg enabled and it is an odd frame.

Do any read/writes to the PPU take extra cycles?
Is my problem probably cpu opcodes that are to short/long anyway?

by on (#19660)
I had this issue too, exactly the same. My fix was to assert the NMI flag before the PPU clock on argument fetching. In other words, to clock the PPU after fetching the instruction byte. When fetching the instruction byte, so the NMI flag is asseted after the PPU clock. Notice this might be an hack, plus NOT the main point to fix your problem though...

by on (#19677)
Quote:
I take care of the extra PPU cycle that may occur if bg enabled and it is an odd frame


Missing cycle you mean.

Quote:
In other words, to clock the PPU after fetching the instruction byte. When fetching the instruction byte, so the NMI flag is asserted after the PPU clock.


Right, an emulator must handle PPU events that occur in the middle of a CPU instruction.