PPUSTATUS lower bits

This is an archive of a topic from NESdev BBS, taken in mid-October 2019 before a server upgrade.
View original topic
PPUSTATUS lower bits
by on (#85115)
I'm in the middle of my PPU development, and I would like to clear up a few things about the PPUSTATUS register. Most of the sources of information that I have checked so far more or less agree with what is said in the wiki:

Code:
76543210
||||||||
|||+++++- Least significant bits previously written into a PPU register
|||       (due to register not being updated for this address)
||+------ Sprite overflow. The PPU can handle only eight sprites on one
||        scanline and sets this bit if it starts dropping sprites.
||        Normally, this triggers when there are 9 sprites on a scanline,
||        but the actual behavior is significantly more complicated.
|+------- Sprite 0 Hit.  Set when a nonzero pixel of sprite 0 'hits'
|         a nonzero background pixel.  Used for raster timing.
+-------- Vertical blank has started (0: not in VBLANK; 1: in VBLANK)


However, the Nestech document provides this information:

Code:
+---------+----------------------------------------------------------+
|  $2002  | PPU Status Register (R)                                  |
|         |                                                          |
|         |    D7: VBlank Occurance                                  |
|         |          0 = Not occuring                                |
|         |          1 = In VBlank                                   |
|         |    D6: Sprite #0 Occurance                               |
|         |          0 = Sprite #0 not found                         |
|         |          1 = PPU has hit Sprite #0                       |
|         |    D5: Scanline Sprite Count                             |
|         |          0 = Eight (8) sprites or less on current scan-  |
|         |              line                                        |
|         |          1 = More than 8 sprites on current scanline     |
|         |    D4: VRAM Write Flag                                   |
|         |          0 = Writes to VRAM are respected                |
|         |          1 = Writes to VRAM are ignored                  |
|         |                                                          |
|         | NOTE: D7 is set to 0 after read occurs.                  |
|         | NOTE: After a read occurs, $2005 is reset, hence the     |
|         |       next write to $2005 will be Horizontal.            |
|         | NOTE: After a read occurs, $2006 is reset, hence the     |
|         |       next write to $2006 will be the high byte portion. |
+---------+----------------------------------------------------------+


So here are the things I would like cleared up for me:

1. How many bits are written to PPUSTATUS as a result of data being written into a PPU register - 4 bits or 5 bits?
2. Is bit 4 actually a VRAM write flag?
3. Is bit 7 cleared after a read from PPUSTATUS, or a read from any PPU register?
4. Similarly, are PPUSCROLL and PPUADDR cleared after a read from PPUSTATUS, or a read from any PPU register?


Like I said, the Nestech document seems to have different information than most of my sources on this register, so I would like to know how accurate this information is. Any help would be appreciated!

by on (#85116)
Always trust the wiki info over any 3rd party stuff, I've never heard of that other document you were referencing. But anyway...

1. You don't write to the register. the "clearing" is of the way the $2006/$2005 registers work. You write multiple values. $2006 goes high byte of data and then low, and a read resets it to write the high byte being written so you KNOW the status of $2006 write is as it could be the low byte for some reason. Same with the $2005 latch, you write X then Y scroll. You read $2002 it to make sure you're writing the first byte of the latch first, not the another for any reason.

2. AFAIK, D4 does nothing. there's only those 3 flags. And I also hear that D5 is slightly more complicated, but I know no details about that, wait till others chime in.

3. D7 is cleared when read from $2002 and $2002 only. It also triggers the NMI too. If it's 1 and and NMI is disabled on the CPU side, nothing happens. But if it's 1 and you then enable NMI on the CPU side, the CPU will get interrupted at that very time nomatter if it's rendering or not IIRC.

4. See how the PPU $2006 works, same thing, making sure you're writing the value you want first pretty much.
Re: PPUSTATUS lower bits
by on (#85117)
Elessar wrote:
However, the Nestech document provides this information

NESTECH.txt is very old.

Quote:
1. How many bits are written to PPUSTATUS as a result of data being written into a PPU register - 4 bits or 5 bits?

I'm not aware of any test ROM for PPU open bus behavior, and I'm not aware of any game that depends on it. I think it has something to do with how the pin drivers are set up inside the PPU.

Quote:
2. Is bit 4 actually a VRAM write flag?

No.

Quote:
3. Is bit 7 cleared after a read from PPUSTATUS, or a read from any PPU register?

Bit 7 of PPUSTATUS is set to 0 after reading PPUSTATUS, not after reading any of the other seven ports. The behavior is described in the page on NMI.

Quote:
4. Similarly, are PPUSCROLL and PPUADDR cleared after a read from PPUSTATUS, or a read from any PPU register?

Nothing "clears" PPUSCROLL and PPUADDR, except that parts of t (loaded through PPUSCROLL) are copied to v (PPUADDR) at the start of a frame and at the end of each scanline if rendering is turned on in PPUMASK. What this refers to is an internal 1-bit address latch telling whether to write to the top half or the bottom half of a register.
Re: PPUSTATUS lower bits
by on (#85118)
tepples wrote:
Elessar wrote:
However, the Nestech document provides this information

NESTECH.txt is very old.

...

Quote:
2. Is bit 4 actually a VRAM write flag?

No.

I suspected that this might be the case, but I wanted to make sure.


tepples wrote:
Quote:
1. How many bits are written to PPUSTATUS as a result of data being written into a PPU register - 4 bits or 5 bits?

I'm not aware of any test ROM for PPU open bus behavior, and I'm not aware of any game that depends on it. I think it has something to do with how the pin drivers are set up inside the PPU.

Would I be able to safely ignore the lower bits of the PPUSTATUS register then?

by on (#85119)
Yes, you can ignore D4-D0 of PPUSTATUS because games typically use instructions that likewise ignore these bits. Typical program fragments:
Code:
; In init code, while waiting for the PPU to warm up

warmup1:
  bit PPUSTATUS
  bpl warmup1
  ; at this point we should be at the bottom of the first frame
warmup2:
  bit PPUSTATUS
  bpl warmup2
  ; after this point, the game will use only NMIs to wait for vblank

; 8< cut >8

; During game play, while waiting for sprite 0 to change the
; scroll position from the status bar to the playfield

  ; first wait for sprite 0 flag to be cleared at end of vblank
s0wait_0:
  bit PPUSTATUS
  bvs s0wait_0
  ; now wait for it to be set again
s0wait_1:
  bit PPUSTATUS
  bvs s0wait_1
  ; at this point, the game is likely to write to PPUCTRL,
  ; PPUSCROLL, and/or PPUADDR to change the scroll position

The BIT instruction is commonly used to load bits 7 and 6 of a value in into flags N and V.
Re: PPUSTATUS lower bits
by on (#85120)
tepples wrote:
Quote:
1. How many bits are written to PPUSTATUS as a result of data being written into a PPU register - 4 bits or 5 bits?

I'm not aware of any test ROM for PPU open bus behavior, and I'm not aware of any game that depends on it. I think it has something to do with how the pin drivers are set up inside the PPU.

No idea about games depending on stuff, but Blargg has an open bus test that can be downloaded at http://blargg.parodius.com/nes-tests/ .

by on (#85121)
tepples wrote:
Yes, you can ignore D4-D0 of PPUSTATUS because games typically use instructions that likewise ignore these bits.

Good to know.


Bisqwit wrote:
tepples wrote:
Quote:
1. How many bits are written to PPUSTATUS as a result of data being written into a PPU register - 4 bits or 5 bits?

I'm not aware of any test ROM for PPU open bus behavior, and I'm not aware of any game that depends on it. I think it has something to do with how the pin drivers are set up inside the PPU.

No idea about games depending on stuff, but Blargg has an open bus test that can be downloaded at http://blargg.parodius.com/nes-tests/ .

I'll check it out, thanks!

by on (#85125)
I still find that open bus test ROM a little vague in it's errors and descriptions of how PPU open bus works.

I can also state that not having it emulated causes exactly 0 games to malfunction. That being said PPU open bus should be low priority for any PPU emulator. It really doesn't matter.

by on (#85161)
Quote:
3. D7 is cleared when read from $2002 and $2002 only. It also triggers the NMI too. If it's 1 and and NMI is disabled on the CPU side, nothing happens. But if it's 1 and you then enable NMI on the CPU side, the CPU will get interrupted at that very time nomatter if it's rendering or not IIRC.

I just wanted to correct you, it's impossible to disable NMIs from CPU side, you can only disable IRQs by setting the I flag.
However, you can disable NMIs on the PPU side by setting $2000.7 to 0, then what you say happens.

$2002.7 was really meant to be a NMI acknownledge, reading it as a '1' means the PPU just triggered an NMI. Because of how the 2A03 is wired inside the NES, no other NMI sources are possible so a game can freely ignore the acknownledge part and exectue NMI without any acknownledge, but you can trigger multiple NMIs by toggling $2000.7 off and on again without reading $2002.