User:Ddribin/PPU Sandbox: Difference between revisions

From NESdev Wiki
Jump to navigationJump to search
No edit summary
(Rename registers)
 
(21 intermediate revisions by the same user not shown)
Line 1: Line 1:
== PPU Registers ==
== PPU Register Overview ==
 
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.
 
{| class="wikitable" border="1" cellspacing="0" cellpadding="3"
{| class="wikitable" border="1" cellspacing="0" cellpadding="3"
|+ PPU Registers
|-
! Address !! Name !! (Alt. Names?) !! Function
|-
| $2000 || [[#PPUCR1|PPUCR1]] || PPUCTRL PCR ||  PPU Control Register 1
|-
| $2001 || [[#PPUCR1|PPUCR2]] || PPUMASK PPUMR  PMR || PPU Control Register 2
|-
| $2002 || [[#PPUSR|PPUSR]] || PPUSTATUS PSR || PPU Status Register
|-
| $2003 || OAMAR || OAMADDR OAR || OAM Address Register
|-
|-
! Address !! Register !! Function
| $2004 || OAMDR || OAMDATA ODR || OAM Data Register
|-
|-
| $2000 || [[#PPUCTRL]] || PPU Control Register
| $2005 || PPUSCR || PPUSCROLL PSCR || PPU Scroll Register
|-
| $2006 || PPUAR || PPUADDR PAR || PPU Address Register
|-
|-
| $2001 || PPUMASK || PPU Mask Register
| $2007 || PPUDR || PPUDATA PDR || PPU Data Register
|-
|-
| $2002 || PPUSTATUS || PPU Status Register
| $4014 || OAMDMA || ODMA || OAM DMA
|}
|}


== PPUCTRL ==
== <span id="PPUCR1">PPUCR1</span>: PPU Control Register 1 ==


{| class="wikitable" style="text-align:center;" border="1" cellspacing="0" cellpadding="3"
{| class="wikitable" style="text-align:center;" border="1" cellspacing="0" cellpadding="3"
Line 18: Line 34:
|-
|-
! $2000
! $2000
| NMI || MSS || SSZ || BPT || SPT || VDN || NTA1 || NTA0
| NMIE || MSE || SSZ || BPT || SPT || VDN || NTA1 || NTA0
|-
|-
! Read/Write
! Read/Write
Line 24: Line 40:
|-
|-
! Initial Value
! Initial Value
| X || X || X || X || X || X || X || X
| 0 || X || 0 || 0 || 0 || 0 || 0 || 0
|}
|}


; Bit 7 - NMI<nowiki>:</nowiki> NMI Enable
=== Bit 7 - NMIE<nowiki>:</nowiki> NMI Enable ===
Setting NMI to one causes an NMI to be generated at the start of the  vertical blanking interval
Setting NMIE to one causes an NMI to be generated at the start of the  vertical blanking interval.


; Bit 6 - MSS<nowiki>:</nowiki> Master/Slave Enable
=== Bit 6 - MSE<nowiki>:</nowiki> Master/Slave Enable ===
Has no effect on the NES.
Has no effect on the NES.


; Bit 5 - SSZ<nowiki>:</nowiki> Sprite Size
=== Bit 5 - SSZ<nowiki>:</nowiki> Sprite Size ===
0: 8x8; 1: 8x16
0: 8x8; 1: 8x16


; Bit 4 - BPT<nowiki>:</nowiki> Background Pattern Table
=== Bit 4 - BPT<nowiki>:</nowiki> Background Pattern Table ===
Background pattern table address (0: $0000; 1: $1000)
Background pattern table address (0: $0000; 1: $1000)


; Bit 3 - SPT<nowiki>:</nowiki> Sprite Pattern Table
=== Bit 3 - SPT<nowiki>:</nowiki> Sprite Pattern Table ===
Sprite pattern table address for 8x8 sprites (0: $0000; 1: $1000)
Sprite pattern table address for 8x8 sprites (0: $0000; 1: $1000)


; Bit 2 - VDN<nowiki>:</nowiki> VRAM Increment Down
=== Bit 2 - VDN<nowiki>:</nowiki> VRAM Increment Down ===
VRAM address increment per CPU read/write of PPUDATA (0: increment by 1, going across; 1: increment by 32, going down)
VRAM address increment per CPU read/write of PPUDATA (0: increment by 1, going across; 1: increment by 32, going down)


; Bits 1, 0 - NTA1 and NTA0<nowiki>:</nowiki> Base Nametable Address
=== Bits 1, 0 - NTA1 and NTA0<nowiki>:</nowiki> Base Nametable Address 1 and 0 ===
{| class="wikitable" style="text-align:center;" border="1" cellspacing="0" cellpadding="3"
{| class="wikitable" style="text-align:center;" border="1" cellspacing="0" cellpadding="3"
|-
|-
Line 59: Line 75:
|}
|}


== PPUSTATUS - The PPU Status Register ==
== <span id="PPUCR2">PPUCR2</span>: PPU Control Register 2 ==


{| class="wikitable" style="text-align:center;" border="1" cellspacing="0" cellpadding="3"
{| class="wikitable" style="text-align:center;" border="1" cellspacing="0" cellpadding="3"
Line 66: Line 82:
|-
|-
! $2001
! $2001
| INB || ING || INR || SPR || BGR || SPC || BGC || GRY
| INB || ING || INR || SRE || BRE || SCD || BCD || GSE
|-
|-
! Read/Write
! Read/Write
Line 72: Line 88:
|-
|-
! Initial Value
! Initial Value
| X || X || X || || X || X || X || X
| 0 || 0 || 0|| 0 || 0 || X || X || 0
|}
|}


; Bit 7 - INB<nowiki>:</nowiki> Intensify Blues
=== Bit 7 - INB<nowiki>:</nowiki> Intensify Blues ===
 
Intensify blues and darken other colors.
 
=== Bit 6 - ING<nowiki>:</nowiki> Intensify Greens ===
 
Intensify greens and darken other colors.
 
=== Bit 5 - INR<nowiki>:</nowiki> Intensify Reds ===
 
Intensify reds and darken other colors.
 
=== Bit 4 - SRE<nowiki>:</nowiki> Sprite Render Enable ===
 
Enable sprite rendering.
 
=== Bit 3 - BRE<nowiki>:</nowiki> Background Render Enable ===
 
Enable background rendering.
 
=== Bit 2 - SCD<nowiki>:</nowiki> Sprite Clip Disable ===
 
Control sprite clipping in leftmost 8 pixels of screen (0: clip; 1: display).
 
=== Bit 1 - BCD<nowiki>:</nowiki> Background Clip Disable ===
 
Control background clipping in leftmost 8 pixels of screen (0: clip; 1: display).
 
=== Bit 0 - GSE<nowiki>:</nowiki> Grayscale Enable ===


; Bit 6 - ING<nowiki>:</nowiki> Intensify Greens
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!


; Bit 5 - INR<nowiki>:</nowiki> Intensify Reds
== <span id="PPUSR">PPUSR</span>: PPU Status Register ==


; Bit 4 - SPR<nowiki>:</nowiki> Sprite Render Enable
{| class="wikitable" style="text-align:center;" border="1" cellspacing="0" cellpadding="3"
|-
! Bit !! 7 !! 6 !! 5 !! 4 !! 3 !! 2 !! 1 !! 0
|-
! $2002
| VBL || S0H || SOV || --- || --- || --- || --- || ---
|-
! Read/Write
| R || R || R || R || R || R || R || R
|-
! Initial Value
| X || 0 || X || X  || X || X || X || X
|}


; Bit 3 - BGR<nowiki>:</nowiki> Background Render Enable
=== Bit 7 - VBL: Vertical Blank ===


; Bit 2 - SPC<nowiki>:</nowiki> Sprite Clip
=== Bit 6 - S0H: Sprite 0 Hit ===


; Bit 1 - BGC<nowiki>:</nowiki> Background Clip
=== Bit 5 - SOV: Sprite Overflow ===


; Bit 0 - GRY<nowiki>:</nowiki> Grayscale Enable
=== Bits 4..0 - Res: Reserved ===


== CA65 Definitions ==
== CA65 Definitions ==
Line 98: Line 154:


         ;; PPU Registers
         ;; PPU Registers
         ppuctrl        := $2000
         ppucr1 := $2000
         ppumask         := $2001
         nmie = bit2mask(7)
        mse  = bit2mask(6)
        ssz  = bit2mask(5)
        bpt  = bit2mask(4)
        spt  = bit2mask(3)
        vdn  = bit2mask(2)
        nta1 = bit2mask(1)
        nta0 = bit2mask(0)
 
        nta_2000 = bits2mask(%00, nta0)
        nta_2400 = bits2mask(%01, nta0)
        nta_2800 = bits2mask(%10, nta0)
        nta_2c00 = bits2mask(%11, nta0)
 
         ppucr2 := $2001
        inb = bit2mask(7)
        ing = bit2mask(6)
        inr = bit2mask(5)
        sre = bit2mask(4)
        bre = bit2mask(3)
        scd = bit2mask(2)
        bcd = bit2mask(1)
        gse= bit2mask(0)


         ppuctrl_nmi = bit2mask(7)
         ppusr := $2002
         ppuctrl_mss = bit2mask(6)
        vbl = bit2mask(7)
         ppuctrl_ssz = bit2mask(5)
         s0h = bit2mask(6)
        ppuctrl_bpt = bit2mask(4)
         sov = bit2mask(5)
        ppuctrl_spt = bit2mask(3)
        ppuctrl_vdn = bit2mask(2)
        ppuctrl_nta1 = bit2mask(1)
        ppuctrl_nta0 = bit2mask(0)


         ppuctrl_nta_2000 = bits2mask(%00, ppuctrl_nta0)
         oamaddr := $2003
         ppuctrl_nta_2400 = bits2mask(%01, ppuctrl_nta0)
         oamdata := $2004
         ppuctrl_nta_2800 = bits2mask(%10, ppuctrl_nta0)
         ppuscroll := $2005
         ppuctrl_nta_2c00 = bits2mask(%11, ppuctrl_nta0)
         ppuaddr := $2006
          
         ppuaddr := $2007
        ppumask_inb = bit2mask(7)
         oamdma := $4014
        ppumask_ing = bit2mask(6)
        ppumask_inr = bit2mask(5)
        ppumask_spr = bit2mask(4)
        ppumask_bgr = bit2mask(3)
        ppumask_spc = bit2mask(2)
        ppumask_bgc = bit2mask(1)
         ppumask_gry = bit2mask(0)
</pre>
</pre>

Latest revision as of 22:09, 5 December 2010

PPU Register Overview

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.

PPU Registers
Address Name (Alt. Names?) Function
$2000 PPUCR1 PPUCTRL PCR PPU Control Register 1
$2001 PPUCR2 PPUMASK PPUMR PMR PPU Control Register 2
$2002 PPUSR PPUSTATUS PSR PPU Status Register
$2003 OAMAR OAMADDR OAR OAM Address Register
$2004 OAMDR OAMDATA ODR OAM Data Register
$2005 PPUSCR PPUSCROLL PSCR PPU Scroll Register
$2006 PPUAR PPUADDR PAR PPU Address Register
$2007 PPUDR PPUDATA PDR PPU Data Register
$4014 OAMDMA ODMA OAM DMA

PPUCR1: PPU Control Register 1

Bit 7 6 5 4 3 2 1 0
$2000 NMIE MSE SSZ BPT SPT VDN NTA1 NTA0
Read/Write W W W W W W W W
Initial Value 0 X 0 0 0 0 0 0

Bit 7 - NMIE: NMI Enable

Setting NMIE to one causes an NMI to be generated at the start of the vertical blanking interval.

Bit 6 - MSE: Master/Slave Enable

Has no effect on the NES.

Bit 5 - SSZ: Sprite Size

0: 8x8; 1: 8x16

Bit 4 - BPT: Background Pattern Table

Background pattern table address (0: $0000; 1: $1000)

Bit 3 - SPT: Sprite Pattern Table

Sprite pattern table address for 8x8 sprites (0: $0000; 1: $1000)

Bit 2 - VDN: VRAM Increment Down

VRAM address increment per CPU read/write of PPUDATA (0: increment by 1, going across; 1: increment by 32, going down)

Bits 1, 0 - NTA1 and NTA0: Base Nametable Address 1 and 0

NTA1 NTA0 Base VRAM Address
0 0 $2000 (Nametable 0)
0 1 $2400 (Nametable 1)
1 0 $2800 (Nametable 2)
1 1 $2C00 (Nametable 3)

PPUCR2: PPU Control Register 2

Bit 7 6 5 4 3 2 1 0
$2001 INB ING INR SRE BRE SCD BCD GSE
Read/Write W W W W W W W W
Initial Value 0 0 0 0 0 X X 0

Bit 7 - INB: Intensify Blues

Intensify blues and darken other colors.

Bit 6 - ING: Intensify Greens

Intensify greens and darken other colors.

Bit 5 - INR: Intensify Reds

Intensify reds and darken other colors.

Bit 4 - SRE: Sprite Render Enable

Enable sprite rendering.

Bit 3 - BRE: Background Render Enable

Enable background rendering.

Bit 2 - SCD: Sprite Clip Disable

Control sprite clipping in leftmost 8 pixels of screen (0: clip; 1: display).

Bit 1 - BCD: Background Clip Disable

Control background clipping in leftmost 8 pixels of screen (0: clip; 1: display).

Bit 0 - GSE: Grayscale Enable

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!

PPUSR: PPU Status Register

Bit 7 6 5 4 3 2 1 0
$2002 VBL S0H SOV --- --- --- --- ---
Read/Write R R R R R R R R
Initial Value X 0 X X X X X X

Bit 7 - VBL: Vertical Blank

Bit 6 - S0H: Sprite 0 Hit

Bit 5 - SOV: Sprite Overflow

Bits 4..0 - Res: Reserved

CA65 Definitions

.define bit2mask(bitnum) (1 << bitnum)
.define bits2mask(bits, bitnum) (bits << bitnum)

        ;; PPU Registers
        ppucr1 := $2000
        nmie = bit2mask(7)
        mse  = bit2mask(6)
        ssz  = bit2mask(5)
        bpt  = bit2mask(4)
        spt  = bit2mask(3)
        vdn  = bit2mask(2)
        nta1 = bit2mask(1)
        nta0 = bit2mask(0)

        nta_2000 = bits2mask(%00, nta0)
        nta_2400 = bits2mask(%01, nta0)
        nta_2800 = bits2mask(%10, nta0)
        nta_2c00 = bits2mask(%11, nta0)

        ppucr2 := $2001
        inb = bit2mask(7)
        ing = bit2mask(6)
        inr = bit2mask(5)
        sre = bit2mask(4)
        bre = bit2mask(3)
        scd = bit2mask(2)
        bcd = bit2mask(1)
        gse= bit2mask(0)

        ppusr := $2002
        vbl = bit2mask(7)
        s0h = bit2mask(6)
        sov = bit2mask(5)

        oamaddr := $2003
        oamdata := $2004
        ppuscroll := $2005
        ppuaddr := $2006
        ppuaddr := $2007
        oamdma := $4014