PPU registers: Difference between revisions

From NESdev Wiki
Jump to navigationJump to search
mNo edit summary
Line 9: Line 9:
</noinclude>
</noinclude>


===Controller ($2000) [write]===  
===Controller ($2000) [write] {{Anchor|PPUCTRL}}===  


Is often referred as PPUCTRL.
Is often referred as PPUCTRL.
Line 28: Line 28:
           [[wikipedia:Vertical blanking interval|vertical blanking interval]] (0: off; 1: on)
           [[wikipedia:Vertical blanking interval|vertical blanking interval]] (0: off; 1: on)


Equivalently, bits 0 and 1 are the most significant bit of the scrolling coordinates (see [[PPU_nametables|Nametables]] and [[#Scroll ($2005)|PPU scroll]]):
Equivalently, bits 0 and 1 are the most significant bit of the scrolling coordinates (see [[PPU_nametables|Nametables]] and [[#PPUSCROLL|PPU scroll]]):
  76543210
  76543210
       ||
       ||
Line 37: Line 37:
Another way of seeing the explanation above is that when you reach the end of a nametable, you must switch to the next one, hence, changing the nametable address.
Another way of seeing the explanation above is that when you reach the end of a nametable, you must switch to the next one, hence, changing the nametable address.


=== Mask ($2001) [write] ===
=== Mask ($2001) [write] {{Anchor|PPUMASK}}===


is often referred as PPUMASK.
is often referred as PPUMASK.
Line 57: Line 57:




=== Status ($2002) [read] ===
=== Status ($2002) [read] {{Anchor|PPUSTATUS}}===


Is often referred as PPUSTATUS.
Is often referred as PPUSTATUS.
Line 75: Line 75:


==== Notes ====
==== Notes ====
* Reading the status register will clear D7 mentioned above and also the address latch used by [[PPU_REGISTER_SCROLL|PPUSCROLL]] and [[PPU_REGISTER_ADDRESS|PPUADDR]].
* Reading the status register will clear D7 mentioned above and also the address latch used by [[#PPUSCROLL|PPUSCROLL]] and [[#PPUADDR|PPUADDR]].


* '''Caution:''' Reading PPUSTATUS at the exact start of vertical blank will return a 0 in D7 but clear the latch anyway, causing the program to miss frames. See [[NMI]] for details.
* '''Caution:''' Reading PPUSTATUS at the exact start of vertical blank will return a 0 in D7 but clear the latch anyway, causing the program to miss frames. See [[NMI]] for details.




=== OAM address ($2003) [write] ===  
=== OAM address ($2003) [write] {{Anchor|OAMADDR}}===  


Is often referred as OAMADDR.
Is often referred as OAMADDR.
Line 90: Line 90:




=== OAM data ($2004) [read/write] ===
=== OAM data ($2004) [read/write] {{Anchor|OAMDATA}}===


Is often referred as OAMDATA.
Is often referred as OAMDATA.
Line 97: Line 97:
OAM data port.
OAM data port.


Write OAM data here. Writes will increment [[PPU_REGISTER_OAM_ADDRESS|OAMADDR]]; reads won't.  
Write OAM data here. Writes will increment [[#OAMADDR|OAMADDR]]; reads won't.  


Most games access this register through $4014 instead. Reading OAMDATA while the PPU is rendering will expose internal OAM accesses during sprite evaluation and loading; Micro Machines does this.
Most games access this register through $4014 instead. Reading OAMDATA while the PPU is rendering will expose internal OAM accesses during sprite evaluation and loading; Micro Machines does this.




=== Scroll ($2005) [write x2] ===
=== Scroll ($2005) [write x2] {{Anchor|PPUSCROLL}}===
Is often referred as PPUSCROLL.
Is often referred as PPUSCROLL.


Line 108: Line 108:
Scroll register (2x write)
Scroll register (2x write)


After reading [[PPU_REGISTER_STATUS|PPUSTATUS]] to reset the address latch, write the horizontal and vertical scroll offsets here just before turning on the screen:
After reading [[#PPUSTATUS|PPUSTATUS]] to reset the address latch, write the horizontal and vertical scroll offsets here just before turning on the screen:
   bit PPUSTATUS
   bit PPUSTATUS
   ; possibly other code goes here
   ; possibly other code goes here
Line 122: Line 122:




=== Address ($2006) [write x2] ===
=== Address ($2006) [write x2] {{Anchor|PPUADDR}}===


Is often referred as PPUADDR
Is often referred as PPUADDR
Line 129: Line 129:
VRAM address register (2x write)
VRAM address register (2x write)


After reading [[PPU_REGISTER_STATUS|PPUSTATUS]] to reset the address latch, write the 16-bit address of VRAM you want to access here, upper byte first. Valid addresses are $0000-$3FFF.
After reading [[#PPUSTATUS|PPUSTATUS]] to reset the address latch, write the 16-bit address of VRAM you want to access here, upper byte first. Valid addresses are $0000-$3FFF.


==== note ====
==== note ====
Access to [[PPU_REGISTER_SCROLL|PPUSCROLL]] and PPUADDR during screen refresh produces interesting raster effects; the starting position of each scanline can be set to any pixel position in nametable memory. For more information, see "The Skinny on NES Scrolling" by loopy, available from [http://nesdev.parodius.com/ the main site].
Access to [[$PPUSCROLL|PPUSCROLL]] and PPUADDR during screen refresh produces interesting raster effects; the starting position of each scanline can be set to any pixel position in nametable memory. For more information, see "The Skinny on NES Scrolling" by loopy, available from [http://nesdev.parodius.com/ the main site].


''' Editor's note:''' Last comment about external page should be re-directed to the getting started section instead.
''' Editor's note:''' Last comment about external page should be re-directed to the getting started section instead.




=== Data ($2007) [read/write] ===
=== Data ($2007) [read/write] {{Anchor|PPUDATA}}===


Is often referred as PPUDATA.
Is often referred as PPUDATA.
Line 144: Line 144:
VRAM data register.
VRAM data register.


When the screen is turned off by disabling the background/sprite rendering flag with the [[PPU_REGISTER_MASK|PPUMASK]] or during vertical blank, you can read or write data from VRAM through this port.
When the screen is turned off by disabling the background/sprite rendering flag with the [[$PPUMASK|PPUMASK]] or during vertical blank, you can read or write data from VRAM through this port.


==== Note ====
==== Note ====
Reads are delayed by one cycle; discard the first byte read. Do '''not''' attempt to access this register while the PPU is rendering; if you do, Bad Things&trade; will happen (i.e. graphical glitches and RAM corruption).
Reads are delayed by one cycle; discard the first byte read. Do '''not''' attempt to access this register while the PPU is rendering; if you do, Bad Things&trade; will happen (i.e. graphical glitches and RAM corruption).

Revision as of 13:27, 11 June 2009

The PPU exposes only eight memory-mapped registers to the CPU. These nominally sit at $2000 through $2007 in the CPU's address space, but because they're incompletely decoded, they're mirrored in every 8 bytes from $2008 through $3FFF, so a write to $3456 is the same as a write to $2006.

Note: The next paragraph explain details that should be more in the getting started reference?

Immediately after powerup, the PPU must wait at least one full frame before it is stable enough to operate normally. The first thing that should be done on startup is to write a zero byte to registers PPUCTRL and PPUMASK (to disable rendering and NMIs) and then wait for bit 7 of PPUSTATUS to be set twice. Some programs will wait for $2002 bit 7 to be set, initialize hardware other than the PPU (such as zeroing CPU RAM), and then wait for $2002 bit 7 to be set again.



Controller ($2000) [write]

Is often referred as PPUCTRL.


Various flags controlling PPU operation

76543210
||||||||
||||||++- Base nametable address
||||||    (0 = $2000; 1 = $2400; 2 = $2800; 3 = $2C00)
|||||+--- VRAM address increment per CPU read/write of PPUDATA
|||||     (0: increment by 1, going across; 1: increment by 32, going down)
||||+---- Sprite pattern table address for 8x8 sprites (0: $0000; 1: $1000)
|||+----- Background pattern table address (0: $0000; 1: $1000)
||+------ Sprite size (0: 8x8; 1: 8x16)
|+------- PPU master/slave select (has no effect on the NES)
+-------- Generate an NMI at the start of the
          vertical blanking interval (0: off; 1: on)

Equivalently, bits 0 and 1 are the most significant bit of the scrolling coordinates (see Nametables and PPU scroll):

76543210
      ||
      |+- 1: Add 256 to the X scroll position
      +-- 1: Add 240 to the Y scroll position

Note

Another way of seeing the explanation above is that when you reach the end of a nametable, you must switch to the next one, hence, changing the nametable address.

Mask ($2001) [write]

is often referred as PPUMASK.


Screen enable, masking, and intensity

76543210
||||||||
|||||||+- Grayscale (0: normal color; 1: AND all palette entries
|||||||   with 0x30, effectively producing a monochrome display;
|||||||   note that colour emphasis STILL works when this is on!)
||||||+-- Enable background in leftmost 8 pixels of screen (0: clip; 1: display)
|||||+--- Enable sprite in leftmost 8 pixels of screen (0: clip; 1: display)
||||+---- Enable background rendering
|||+----- Enable sprite rendering
||+------ Intensify reds (and darken other colors)
|+------- Intensify greens (and darken other colors)
+-------- Intensify blues (and darken other colors)


Status ($2002) [read]

Is often referred as PPUSTATUS.


PPU status

76543210
||||||||
|||+++++- Unimplemented
||+------ 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)

Notes

  • Reading the status register will clear D7 mentioned above and also the address latch used by PPUSCROLL and PPUADDR.
  • Caution: Reading PPUSTATUS at the exact start of vertical blank will return a 0 in D7 but clear the latch anyway, causing the program to miss frames. See NMI for details.


OAM address ($2003) [write]

Is often referred as OAMADDR.


Write the address of OAM you want to access here. Most games just write $00 here and then use OAM_DMA ($4014).

This register also seems to affect Sprite 0 Hit, though it is not yet understood exactly how it does. The upper 5 bits of this register seem to select which SPR-RAM data is used for sprites 0 and 1 (instead of the first 8 bytes of SPR-RAM), though actual behavior varies between resets.


OAM data ($2004) [read/write]

Is often referred as OAMDATA.


OAM data port.

Write OAM data here. Writes will increment OAMADDR; reads won't.

Most games access this register through $4014 instead. Reading OAMDATA while the PPU is rendering will expose internal OAM accesses during sprite evaluation and loading; Micro Machines does this.


Scroll ($2005) [write x2]

Is often referred as PPUSCROLL.


Scroll register (2x write)

After reading PPUSTATUS to reset the address latch, write the horizontal and vertical scroll offsets here just before turning on the screen:

 bit PPUSTATUS
 ; possibly other code goes here
 lda cam_position_x
 sta PPUSCROLL
 lda cam_position_y
 sta PPUSCROLL

Horizontal offsets range from 0 to 255. "Normal" vertical offsets range from 0 to 239. (Values of 240 to 255 are treated as -16 through -1 in a way, pulling tile data from the attribute table.)


Editing note: some information should be in the getting started section instead of here. It doesn't say explicitly you have to do 2 write: first X value then Y. Must change text.


Address ($2006) [write x2]

Is often referred as PPUADDR


VRAM address register (2x write)

After reading PPUSTATUS to reset the address latch, write the 16-bit address of VRAM you want to access here, upper byte first. Valid addresses are $0000-$3FFF.

note

Access to PPUSCROLL and PPUADDR during screen refresh produces interesting raster effects; the starting position of each scanline can be set to any pixel position in nametable memory. For more information, see "The Skinny on NES Scrolling" by loopy, available from the main site.

Editor's note: Last comment about external page should be re-directed to the getting started section instead.


Data ($2007) [read/write]

Is often referred as PPUDATA.


VRAM data register.

When the screen is turned off by disabling the background/sprite rendering flag with the PPUMASK or during vertical blank, you can read or write data from VRAM through this port.

Note

Reads are delayed by one cycle; discard the first byte read. Do not attempt to access this register while the PPU is rendering; if you do, Bad Things™ will happen (i.e. graphical glitches and RAM corruption).