PPU clarifications

This is an archive of a topic from NESdev BBS, taken in mid-October 2019 before a server upgrade.
View original topic
PPU clarifications
by on (#4856)
I've some trouble emulating the PPU in my
emulator and hope that I can get some help
and clarifications on some things from you guys here.

1)
How does bit 3-4 in PPU register $2001 work?
I understand that they control if background/sprites
should be rendered, but how do they effect the PPU?
They seem to effect PPU's memory reads and if the
address (Loopy_v) should be updated with the temp
address (Loopy_t).

What is done and what is not done by the PPU
depending on how these bits are set?


2)
When is the VBlank flag set (bit 7 in $2002)?
Is it on the last cycle in the scanline after
the 240 visible or on the first cycle in PPU's
VBlank period?

Is NMI generated at the same cycle the flag is set?


3)
At which cycle in the dummy scanline is the PPU address

(Loopy_v) loaded with the temp address (Loopy_t)?

Any help appreciated.
Re: PPU clarifications
by on (#4857)
1)

If either one of the bits is on... the PPU is active and rendering pixels normally throughout the frame. If D3 is off, every background pixel will be transparent (so the background will not be visible), and if D4 is off, every sprite pixel will be transparent (so sprites will not be visible).

If BOTH bits are off, the PPU is "turned off" and becomes inactive during frame rendering time. When the PPU is off, it will not change Loopy_V at all like it normally would if it was switched on. Games will switch off the PPU for large drawing routines... when all the drawing can't be done in VBlank. For frames which the PPU is switched off... you render pixels based on palette entry 0 (ppu$3F00).. UNLESS the PPU address (Loopy_V) is pointing to a place in palette mem ($3Fxx or any mirrored region) -- in which case you render the color the PPU address points to (many Camerica games rely on this to quickly change the background color -- most notably Micro Machines and Bee 52)


2)

VBlank flag is set at the very start of the first scanline of VBlank. For a visual example... one frame consists of the following:

Code:
-----------
20 scanlines of vblank

-----------
pre-render scanline
-----------


240 rendered scanlines



-----------
1 dummy scanline
-----------


The VBlank flag is raised, presumably on cycle 0 of the first scanline on that chart.

NMI is triggered AFTER VBlank is raised... there is some latency between the two. I don't know how much latency exactly, but running 1 CPU instruction between the time $2002.7 is raised and when NMI is triggered works nicely.


3)
Cycle 304. Note this reload only happens if the PPU is switched on (D3 or D4 of $2001 on). If the PPU is off, the address will not reload.

Reference:
http://nesdev.com/bbs/viewtopi ... t=304#3288
Re: PPU clarifications
by on (#4858)
Disch wrote:
NMI is triggered AFTER VBlank is raised... there is some latency between the two. I don't know how much latency exactly, but running 1 CPU instruction between the time $2002.7 is raised and when NMI is triggered works nicely.


Actually, there is no latency at all on the real hardware, but you will need SOME latency if you do not emulate the CPU and PPU completely synchronously with each other (cycle for cycle).
Re: PPU clarifications
by on (#4859)
I see... like the VBlank flag could be raised in the middle of an "LDA $2002" instruction ... but the NMI won't happen until after the instruction completes... right?

by on (#4860)
As Disch said. The thing I want to find out is when the NMI takes effect when asserted at various times in an instruction. I imagine that even if it was just asserted at the beginning of the first clock of an instruction, it still wouldn't take effect until after that instruction completed (hmmm, I guess first clock of an instruction is kind of vague on a pipelined processor).

Handling this in a PPU emulator is simple enough; in the $2002 read handler, set the VBL flag if the CPU time has gone over the current frame length. Oh, and of course skip setting the flag (but still generate the NMI?) if the CPU reads just as it's being set, whenever exactly that is. I need to devise a way to synchronize some code exactly with the VBL timing, then find out exact timing of this (along with a test ROM, since it's tricky to be sure it's emulated exactly).

by on (#4908)
Thanks for all the help guys.
That really made some things
clearer for me.