blargg's vbl_nmi_timing and special-case behavior confusion

This is an archive of a topic from NESdev BBS, taken in mid-October 2019 before a server upgrade.
View original topic
blargg's vbl_nmi_timing and special-case behavior confusion
by on (#110683)
I'm trying to understand how the special behavior related to reading $2002 around the point where the vbl flag is set works. Here are two (semi-)related questions:

1. What's the ideal PPU/CPU alignment to assume in an emulator? One where the the CPU and PPU ticks line up like below? (Alignments where they don't line up nicely are possible since the PPU divides the master clock by 4.)

Code:
[          CPU  tick         ][          CPU  tick         ]
[PPU tick][PPU tick][PPU tick][PPU tick][PPU tick][PPU tick]


2. When the wiki says e.g. "reading one PPU clock before reads it as clear and never sets the flag or generates NMI for that frame" (on http://wiki.nesdev.com/w/index.php/PPU_frame_timing), is that referring to a situation like below?

Code:
CPU: [              Read $2002                ]
PPU: [............][Set VBL flag][............]


If so, does that mean that there's no special-case behavior for e.g.

Code:
CPU: [              Read $2002                ]
PPU: [............][............][Set VBL flag]


? (I.e., will that read the flag as false and later set it and generate an NMI?)
Re: blargg's vbl_nmi_timing and special-case behavior confus
by on (#110689)
ulfalizer wrote:
1. What's the ideal PPU/CPU alignment to assume in an emulator? One where the the CPU and PPU ticks line up like below?

Ideal in what sense? I'd love to see an emulator that actually emulates all of the different PPU/CPU alignments, because that would be something new, something unique, something that nobody else has done yet.
Re: blargg's vbl_nmi_timing and special-case behavior confus
by on (#110705)
Seconded. The snag is that this basically requires testing all CPU-PPU timings thoroughly for the other three alignments, or else the emulator will be less accurate than using the preferred one.

I tested the four alignments and mapped them to the previous findings. The top trace is the PPU's ALE, the bottom M2 out of the 2A03. Note that the ALE is effectively overlaid on itself offset by one PPU clock, such that it shows every PPU clock rather than every other one (normally ALE occurs every two PPU clocks). This is because the scope is triggering on the CPU's M2, and you get 1.5 ALE pulses for every M2. This is exactly what we want since it shows every PPU clock. So it's all good. And yeah, there's not the best connection to the CPU's M2, as shown by the ripple when it's low.

Code:
After power/reset, PPU is randomly in one of four synchronizations with CPU. This synchronization cannot be changed without resetting/powering down. Trials of 50-60 power/resets were done to determine likelihoods. The third synchronization is the preferred one for emulators and test ROMs, due to the least special cases. Also, the three-digit codes are just something specific to my tests that help identify each alignment; the numbrs of no significance worth explaining.

[code]        NMI     VBL         Hit             Overflow    Likelihood
                Reset   Reset   Set     Reset   Set
                        6819+   7502+   6819+   7290+   Power   Reset
----------------------------------------------------------------------
632     -1      -1      -1      0       -1      -1      27%     26%
732     0       -1      0       0       0       0       15%     22%
742     0       0       0       0       0       0       31%     30%
743     0       0       0       +1      0       0       27%     22%


Image
Re: blargg's vbl_nmi_timing and special-case behavior confus
by on (#110712)
OK - just to see that I'm reading this right: Do the above configurations correspond to the following alignments (where X is the relevant flag setting/clearing point)?

Code:
Master:  ***********************
PPU:     *   X   *   *   *   *
CPU@632:     ----read----
CPU@732:    ----read----
CPU@742:   ----read----
CPU@743:  ----read----


If so, does a -1 mean that the read can start one tick before the flag is set/cleared and be seen, and a +1 that it needs to start one tick after?

By the way, the image starts at h=2 and not at h=0 as far as sprite zero hits are concerned, if that could be relevant. (See the second note in http://wiki.nesdev.com/w/images/d/d1/Ntsc_timing.png)

Here's an easier-to-read version of the +- table since it got a bit mangled btw:

Code:
     |  NMI  |  VBL   |     Hit       |    Overflow   | Likelihood
     |       |  Reset | Reset | Set   | Reset | Set   |       |
     |       |        | 6819+ | 7502+ | 6819+ | 7290+ | Power | Reset
-----+-------+--------+-------+-------+-------+-------+-------+-------
632  |  -1   |  -1    | -1    | 0     | -1    | -1    | 27%   | 26%
732  |  0    |  -1    | 0     | 0     | 0     | 0     | 15%   | 22%
742  |  0    |  0     | 0     | 0     | 0     | 0     | 31%   | 30%
743  |  0    |  0     | 0     | +1    | 0     | 0     | 27%   | 22%
Re: blargg's vbl_nmi_timing and special-case behavior confus
by on (#110717)
Sorry, I'm only now noticing your specific questions.

1. We don't know yet what the signal level looks like for each alignment. The tests I've done are for the "742" one, which has the most common timing to all four. I don't know what this corresponds to physically. The order they're listed in the table earlier was confirmed by the scope check yesterday to be in the correct order, where each one is the next in the same "direction" of relative alignments.

Quote:
2. When the wiki says e.g. "reading one PPU clock before reads it as clear and never sets the flag or generates NMI for that frame", is that referring to a situation like below?

It means that if you keep reading it earlier and earlier in the frame, at some point you'll read it as set, and one PPU clock before that you'll read it as clear AND suppress the NMI for that frame. And again, this is for the "742" alignment. I'm not positive, but I believe that at least one other alignment has this suppression on reading one and two PPU clocks before this point. Possibly also one where you read it as clear and it keeps it from being set for the frame, but the NMI still occurs. See how much fun it is to try to cover all four alignments? four variants of each test ROM, perhaps using SRAM to be sure you've tested all four power-on/reset alignments (askng you to press reset until it gets to the next alignment it wants to test... hmmm, this would be a nice test that would eliminate all emulators from passing for now).
Re: blargg's vbl_nmi_timing and special-case behavior confus
by on (#110718)
Am I interpreting the -1's and +1's in the table correctly though? I.e., does a -1 mean that you see the change one PPU tick earlier in that alignment compared to an alignment that has 0? (Or equivalently, that you can start reading one PPU tick earlier and see it.)

And do the timings for sprite 0 account for the fact that sprite 0 hits treat the image as starting as h=2 (while other flags like vbl are set/cleared at h=1)?

(Not sure if you saw my other post above, but just in case :) )
Re: blargg's vbl_nmi_timing and special-case behavior confus
by on (#110719)
The times are I believe PPU clocks after the earliest you find VBL set. I did it mainly to keep track of the differences I found. I'd have to get back to those tests and make some test ROMs to give you anything concrete.
Re: blargg's vbl_nmi_timing and special-case behavior confus
by on (#110720)
It's not surprising that e.g. 632 might allow changes to be seen earlier at least, since you could get e.g.

Code:
Master:  ***********************
PPU:     *   *   S   *   *   *
CPU@632:     ----read----


With other alignments the setting would be further into the read cycle, and so might pass under the radar - e.g.

Code:
Master:  ***********************
PPU:     *   *   S   *   *   *
CPU@742:   ----read----


Depends on exactly how 6502 does reads I guess (and on what the signal level looks like from the PPU around where the read happens), which someone more savvy than me on the hw side of things might be able to shed some light on.
Re: blargg's vbl_nmi_timing and special-case behavior confus
by on (#110830)
What's the first entry on http://wiki.nesdev.com/w/index.php/Tric ... late_games (for Adventures of Lolo 2, etc.) talking about btw? It's not entirely clear to me.
Re: blargg's vbl_nmi_timing and special-case behavior confus
by on (#110854)
Not clear to me either. I think those games have an NMI handler and do a $2002 polling loop, such that the NMI suppression must be handled correctly. I remember the Ms. Pac Man one hanging with a black screen at power if you emulate it wrong.