PPU registers: Difference between revisions

From SNESdev Wiki
Jump to navigationJump to search
(Adds counter latching information (partly speculative). Existing documentation around this latching is incomplete and misleading. Also adds CGRAM latching information.)
(Further information on counter_latch behavior.)
Line 604: Line 604:
           opvct_byte = 0
           opvct_byte = 0


Because reading this clears counter_latch, the counters can become latched again immediately if a latch condition is true.
If a condition that sets counter_latch is active when STAT78 is read, it is not known if counter_latch is cleared. Existing documentation suggests it is not cleared and the counters are not relatched.

Revision as of 04:46, 6 May 2022

Display configuration

INIDISP - Screen display ($2100 write)


7  bit  0
---- ----
F... BBBB
|    ||||
|    ++++- Screen brightness (linear steps from 0 = none to $F = full)
+--------- Force blanking

BGMODE - BG mode and Character size ($2105 write)


7  bit  0
---- ----
4321 PMMM
|||| ||||
|||| |+++- BG mode
|||| +---- Mode 1 BG3 priority (0 = normal, 1 = high)
|||+------ BG1 character size (0 = 8x8, 1 = 16x16)
||+------- BG2 character size (0 = 8x8, 1 = 16x16)
|+-------- BG3 character size (0 = 8x8, 1 = 16x16)
+--------- BG4 character size (0 = 8x8, 1 = 16x16)
Mode| BG bit depth  |Offsets |     Priorities (front -> back)       |                     Notes                      
    |BG1 BG2 BG3 BG4|per tile|                                      |                                                
 0  | 2   2   2   2 |   No   |   S3 1H 2H S2 1L 2L S1 3H 4H S0 3L 4L|                                                
 1  | 4   4   2     |   No   |   S3 1H 2H S2 1L 2L S1 3H    S0 3L   |BG3 priority = 0                                
    |               |        |3H S3 1H 2H S2 1L 2L S1       S0 3L   |BG3 priority = 1                                
 2  | 4   4         |  Yes   |   S3 1H    S2 2H    S1 1L    S0 2L   |                                                
 3  | 8   4         |   No   |   S3 1H    S2 2H    S1 1L    S0 2L   |                                                
 4  | 8   2         |  Yes   |   S3 1H    S2 2H    S1 1L    S0 2L   |                                                
 5  | 4   2         |   No   |   S3 1H    S2 2H    S1 1L    S0 2L   |Fixed 16 pixel char width. Forced high-res mode.
 6  | 4             |  Yes   |   S3 1H    S2       S1 1L    S0      |Fixed 16 pixel char width. Forced high-res mode.
 7  | 8             |   No   |   S3       S2       S1 1L    S0      |Fixed 8x8 char size.                            
7EXT| 8   7         |   No   |   S3       S2 2H    S1 1L    S0 2L   |Fixed 8x8 char size. BG2 bit 7 acts as priority.

MOSAIC - Screen pixelation ($2106 write)


7  bit  0
---- ----
SSSS 4321
|||| ||||
|||| |||+- Enable BG1 mosaic
|||| ||+-- Enable BG2 mosaic
|||| |+--- Enable BG3 mosaic
|||| +---- Enable BG4 mosaic
++++------ Mosaic size in pixels (0 = 1x1, ..., 15 = 16x16)

BGnSC - BG1-4 tilemap address and size ($2107-$210A write)


7  bit  0
---- ----
AAAA AAYX
|||| ||||
|||| |||+- Horizontal tilemap count (0 = 1 tilemap, 1 = 2 tilemaps)
|||| ||+-- Vertical tilemap count (0 = 1 tilemap, 1 = 2 tilemaps)
++++-++--- Tilemap VRAM address (address = AAAAAA << 10)

CHR word base address


BG12NBA - BG1 and BG2 CHR word base address ($210B write)

7  bit  0
---- ----
BBBB AAAA
|||| ||||
|||| ++++- BG1 CHR word base address (address = AAAA << 12)
++++------ BG2 CHR word base address (address = BBBB << 12)

BG34NBA - BG3 and BG4 CHR word base address ($210C write)

7  bit  0
---- ----
DDDD CCCC
|||| ||||
|||| ++++- BG3 CHR word base address (address = CCCC << 12)
++++------ BG4 CHR word base address (address = DDDD << 12)

Scroll


BGnHOFS - BG1-4 horizontal scroll offset ($210D/$210F/$2111/$2113 write)

15  bit  8  7  bit  0
 ---- ----  ---- ----
 .... ..XX  XXXX XXXX
        ||  |||| ||||
        ++--++++-++++- BGn horizontal scroll

On write: BGnHOFS = (value << 8) | (bgofs_latch & ~7) | (bghofs_latch & 7)
          bgofs_latch = value
          bghofs_latch = value

Note: BG1HOFS uses the same address as M7HOFS

BGnVOFS - BG1-4 vertical scroll offset ($210E/$2110/$2112/$2114 write)

15  bit  8  7  bit  0
 ---- ----  ---- ----
 .... ..YY  YYYY YYYY
        ||  |||| ||||
        ++--++++-++++- BGn vertical scroll

On write: BGnVOFS = (value << 8) | bgofs_latch
          bgofs_latch = value

Note: BG1VOFS uses the same address as M7VOFS

Layer enable


TM - Main screen layer enable ($212C write)

7  bit  0
---- ----
...O 4321
   | ||||
   | |||+- Enable BG1 on main screen
   | ||+-- Enable BG2 on main screen
   | |+--- Enable BG3 on main screen
   | +---- Enable BG4 on main screen
   +------ Enable OBJ on main screen

TS - Subscreen layer enable ($212D write)

7  bit  0
---- ----
...O 4321
   | ||||
   | |||+- Enable BG1 on subscreen
   | ||+-- Enable BG2 on subscreen
   | |+--- Enable BG3 on subscreen
   | +---- Enable BG4 on subscreen
   +------ Enable OBJ on subscreen

SETINI - Screen Mode/Video Select ($2133 write)


7  bit  0
---- ----
EX.. HOiI
||   ||||
||   |||+- Screen interlacing
||   ||+-- OBJ interlacing
||   |+--- Overscan mode
||   +---- High-res mode
|+-------- EXTBG mode
+--------- External sync

VRAM

VMAIN - Video Port Control ($2115 write)


7  bit  0
---- ----
M... RRII
|    ||||
|    ||++- Address increment amount:
|    ||     00: Increment by 1
|    ||     01: Increment by 32
|    ||     10: Increment by 128
|    ||     11: Increment by 128
|    ++--- Address remapping:
|           00: None
|           01: Remap aaaaaaaa BBBccccc to aaaaaaaa cccccBBB
|           10: Remap aaaaaaaB BBcccccc to aaaaaaac cccccBBB
|           11: Remap aaaaaaBB Bccccccc to aaaaaacc cccccBBB
+--------- Address increment mode:
            0: Increment after writing $2118 or reading $2139
            1: Increment after writing $2119 or reading $213A

VRAM address


VMADDL - VRAM address low ($2116 write)

7  bit  0
---- ----
LLLL LLLL
|||| ||||
++++-++++- VRAM address low byte

VMADDH - VRAM address high ($2117 write)

7  bit  0
---- ----
HHHH HHHH
|||| ||||
++++-++++- VRAM address high byte

VRAM data


VMDATAL - VRAM data write low ($2118 write)

7  bit  0
---- ----
LLLL LLLL
|||| ||||
++++-++++- VRAM data low byte

VMDATAH - VRAM data write high ($2119 write)

7  bit  0
---- ----
HHHH HHHH
|||| ||||
++++-++++- VRAM data high byte

VMDATALREAD - VRAM data read low ($2139 read)

7  bit  0
---- ----
LLLL LLLL
|||| ||||
++++-++++- VRAM data low byte

VMDATAHREAD - VRAM data read low ($213A read)

7  bit  0
---- ----
LLLL LLLL
|||| ||||
++++-++++- VRAM data high byte

CGRAM

CGADD - CGRAM word address ($2121 write)


7  bit  0
---- ----
AAAA AAAA
|||| ||||
++++-++++- CGRAM word address

Side-effect: cgram_byte = 0

CGRAM data


CGDATA - CGRAM data write ($2122 write)

15  bit  8  7  bit  0
 ---- ----  ---- ----
 .BBB BBGG  GGGR RRRR
  ||| ||||  |||| ||||
  ||| ||||  |||+-++++- Red component 
  ||| ||++--+++------- Green component
  +++-++-------------- Blue component

On write: If cgram_byte == 0, cgram_latch = value
          If cgram_byte == 1, CGDATA = (value << 8) | cgram_latch
          cgram_byte = ~cgram_byte


CGDATA - CGRAM data read ($213B read)

15  bit  8  7  bit  0
 ---- ----  ---- ----
 xBBB BBGG  GGGR RRRR
 |||| ||||  |||| ||||
 |||| ||||  |||+-++++- Red component 
 |||| ||++--+++------- Green component
 |+++-++-------------- Blue component
 +-------------------- PPU2 open bus

On read: If cgram_byte == 0, value = CGDATA low
         If cgram_byte == 1, value = CGDATA high
         cgram_byte = ~cgram_byte

Mode 7

M7SEL - Mode 7 settings ($211A write)


7  bit  0
---- ----
EF.. ..YX
||     ||
||     |+- Mirror screen horizontally
||     +-- Mirror screen vertically
|+-------- Empty space fill (0 = transparent, 1 = character 0)
+--------- Empty space beyond tilemap (0 = tilemap repeats, 1 = empty space)

Scroll


M7HOFS - Mode 7 horizontal scroll offset ($210D write)

15  bit  8  7  bit  0
 ---- ----  ---- ----
 ...X XXXX  XXXX XXXX
    | ||||  |||| ||||
    +-++++--++++-++++- Mode 7 horizontal scroll (signed)

On write: M7HOFS = (value << 8) | mode7_latch
          mode7_latch = value

Note: This register uses the same address as BG1HOFS

M7VOFS - Mode 7 vertical scroll offset ($210E write)

15  bit  8  7  bit  0
 ---- ----  ---- ----
 ...Y YYYY  YYYY YYYY
    | ||||  |||| ||||
    +-++++--++++-++++- Mode 7 vertical scroll (signed)

On write: M7VOFS = (value << 8) | mode7_latch
          mode7_latch = value

Note: This register uses the same address as BG1VOFS

Matrices


M7A - Mode 7 matrix A and Multiplication factor 1 ($211B write)

15  bit  8  7  bit  0
 ---- ----  ---- ----
 DDDD DDDD  dddd dddd
 |||| ||||  |||| ||||
 ++++-++++--++++-++++- Mode 7 matrix A (8.8 fixed point)
 ++++-++++--++++-++++- 16-bit multiplication factor

On write: M7A = (value << 8) | mode7_latch
          mode7_latch = value

M7B - Mode 7 matrix B and Multiplication factor 2 ($211C write)

15  bit  8  7  bit  0
 ---- ----  ---- ----
 DDDD DDDD  dddd dddd
 |||| ||||  |||| ||||
 ++++-++++--++++-++++- Mode 7 matrix B (8.8 fixed point)
            ++++-++++- 8-bit multiplication factor

On write: M7B = (value << 8) | mode7_latch
          mode7_latch = value

M7n - Mode 7 matrix C-D ($211D-211E write)

15  bit  8  7  bit  0
 ---- ----  ---- ----
 DDDD DDDD  dddd dddd
 |||| ||||  |||| ||||
 ++++-++++--++++-++++- Mode 7 matrix n (8.8 fixed point)

On write: M7n = (value << 8) | mode7_latch
          mode7_latch = value

Center


M7X - Mode 7 center X ($211F write)

15  bit  8  7  bit  0
 ---- ----  ---- ----
 ...X XXXX  XXXX XXXX
    | ||||  |||| ||||
    +-++++--++++-++++- Mode 7 center X (signed)

On write: M7X = (value << 8) | mode7_latch
          mode7_latch = value

M7Y - Mode 7 center Y ($2120 write)

15  bit  8  7  bit  0
 ---- ----  ---- ----
 ...Y YYYY  YYYY YYYY
    | ||||  |||| ||||
    +-++++--++++-++++- Mode 7 center Y (signed)

On write: M7Y = (value << 8) | mode7_latch
          mode7_latch = value

Windows

Window mask settings


W12SEL - Window Mask Settings for BG1 and BG2 ($2123 write)

7  bit  0
---- ----
DdCc BbAa
|||| ||||
|||| |||+- Invert window 1 for BG1
|||| ||+-- Enable window 1 for BG1
|||| |+--- Invert window 2 for BG1
|||| +---- Enable window 2 for BG1
|||+------ Invert window 1 for BG2
||+------- Enable window 1 for BG2
|+-------- Invert window 2 for BG2
+--------- Enable window 2 for BG2

W34SEL - Window Mask Settings for BG3 and BG4 ($2124 write)

7  bit  0
---- ----
HhGg FfEe
|||| ||||
|||| |||+- Invert window 1 for BG3
|||| ||+-- Enable window 1 for BG3
|||| |+--- Invert window 2 for BG3
|||| +---- Enable window 2 for BG3
|||+------ Invert window 1 for BG4
||+------- Enable window 1 for BG4
|+-------- Invert window 2 for BG4
+--------- Enable window 2 for BG4

WOBJSEL - Window Mask Settings for OBJ and Color Window ($2125 write)

7  bit  0
---- ----
LlKk JjIi
|||| ||||
|||| |||+- Invert window 1 for OBJ
|||| ||+-- Enable window 1 for OBJ
|||| |+--- Invert window 2 for OBJ
|||| +---- Enable window 2 for OBJ
|||+------ Invert window 1 for color math
||+------- Enable window 1 for color math
|+-------- Invert window 2 for color math
+--------- Enable window 2 for color math

Window positions


WH0 - Window 1 left position ($2126 write)

7  bit  0
---- ----
LLLL LLLL
|||| ||||
++++-++++- Window 1 left edge position

WH1 - Window 1 right position ($2127 write)

7  bit  0
---- ----
RRRR RRRR
|||| ||||
++++-++++- Window 1 right edge position

WH2 - Window 2 left position ($2128 write)

7  bit  0
---- ----
LLLL LLLL
|||| ||||
++++-++++- Window 2 left edge position

WH3 - Window 2 right position ($2129 write)

7  bit  0
---- ----
RRRR RRRR
|||| ||||
++++-++++- Window 2 left edge position

Window mask logic


WBGLOG - Window BG mask logic ($212A write)

7  bit  0
---- ----
4433 2211
|||| ||||
|||| ||++- BG1 window mask logic
|||| ++--- BG2 window mask logic
||++------ BG3 window mask logic
++-------- BG4 window mask logic

WOBJLOG - Window OBJ and color math mask logic ($212B write)

7  bit  0
---- ----
.... CCOO
     ||||
     ||++- OBJ window mask logic
     ++--- Color window mask logic
Mask logic types
Value|Logic
  00 | OR
  01 | AND
  10 | XOR
  11 | XNOR

Window enable


TMW - Main screen layer window enable ($212E write)

7  bit  0
---- ----
...O 4321
   | ||||
   | |||+- Apply enabled windows to main screen BG1
   | ||+-- Apply enabled windows to main screen BG2
   | |+--- Apply enabled windows to main screen BG3
   | +---- Apply enabled windows to main screen BG4
   +------ Apply enabled windows to main screen OBJ

TSW - Subscreen layer window enable ($212F write)

7  bit  0
---- ----
...O 4321
   | ||||
   | |||+- Apply enabled windows to subscreen BG1
   | ||+-- Apply enabled windows to subscreen BG2
   | |+--- Apply enabled windows to subscreen BG3
   | +---- Apply enabled windows to subscreen BG4
   +------ Apply enabled windows to subscreen OBJ

Color math

CGWSEL - Color addition select ($2130 write)


7  bit  0
---- ----
BBMM ..AD
||||   ||
||||   |+- Direct color mode
||||   +-- Addend (0 = fixed color, 1 = subscreen)
||++------ Color math disable region
++-------- Clip colors to black before math region
Region types
Value|Region               
  00 |Nowhere
  01 |Outside color window
  10 |Inside color window
  11 |Everywhere

CGADSUB - Color math designation ($2131 write)


7  bit  0
---- ----
MHBO 4321
|||| ||||
|||| |||+- BG1 color math enable
|||| ||+-- BG2 color math enable
|||| |+--- BG3 color math enable
|||| +---- BG4 color math enable
|||+------ OBJ color math enable
||+------- Backdrop color math enable
|+-------- Half color math
+--------- Operator type (0 = add, 1 = subtract)

COLDATA - Fixed color data ($2131 write)


7  bit  0
---- ----
BGRC CCCC
|||| ||||
|||+-++++- Color value
||+------- Write color value to blue channel
|+-------- Write color value to green channel
+--------- Write color value to red channel

Multiplication result

MPYL - Multiplication result low byte ($2134 read)

7  bit  0
---- ----
LLLL LLLL
|||| ||||
++++-++++- Multiplication result low byte

MPYM - Multiplication result middle byte ($2135 read)

7  bit  0
---- ----
MMMM MMMM
|||| ||||
++++-++++- Multiplication result middle byte

MPYH - Multiplication result high byte ($2136 read)

7  bit  0
---- ----
HHHH HHHH
|||| ||||
++++-++++- Multiplication result high byte

H/V counters

SLHV - Software latch for H/V counters ($2137 read)


7  bit  0
---- ----
xxxx xxxx
|||| ||||
++++-++++- Open bus

On read: counter_latch = 1

Counters


OPHCT - Output horizontal counter ($213C read)

15  bit  8  7  bit  0
 ---- ----  ---- ----
 xxxx xxxX  XXXX XXXX
 |||| ||||  |||| ||||
 |||| |||+--++++-++++- Horizontal counter value
 ++++-+++------------- PPU2 open bus

On read: If ophct_byte == 0, value = OPHCT low
         If ophct_byte == 1, value = OPHCT high
         ophct_byte = ~ophct_byte

OPVCT - Output vertical counter ($213D read)

15  bit  8  7  bit  0
 ---- ----  ---- ----
 xxxx xxxY  YYYY YYYY
 |||| ||||  |||| ||||
 |||| |||+--++++-++++- Vertical counter value
 ++++-+++------------- PPU2 open bus

On read: If opvct_byte == 0, value = OPVCT low
         If opvct_byte == 1, value = OPVCT high
         opvct_byte = ~opvct_byte

When counter_latch transitions from 0 to 1, these registers are latched with the current counter values. counter_latch is set when SLHV is read or /EXTLATCH (PPU2 pin 29) is asserted, and is cleared when STAT78 is read. /EXTLATCH is connected to joypad IO D7 and can be controlled by the CPU via WRIO or by a joypad.

counter_latch behavior has not been fully confirmed.

Status

STAT77 - PPU1 status flags and version ($213E read)


7  bit  0
---- ----
TRMx VVVV
|||| ||||
|||| ++++- PPU1 version
|||+------ PPU1 open bus
||+------- Master/slave mode (PPU1 pin 25)
|+-------- Range over flag (sprite tile overflow)
+--------- Time over flag (sprite overflow)

STAT78 - PPU2 status flags and version ($213F read)


7  bit  0
---- ----
FLxM VVVV
|||| ||||
|||| ++++- PPU2 version
|||+------ NTSC/PAL mode (0 = NTSC, 1 = PAL) (PPU2 pin 30)
||+------- PPU2 open bus
|+-------- Counter latch value
+--------- Interlace field

On read: counter_latch = 0
         ophct_byte = 0
         opvct_byte = 0

If a condition that sets counter_latch is active when STAT78 is read, it is not known if counter_latch is cleared. Existing documentation suggests it is not cleared and the counters are not relatched.