PPU registers: Difference between revisions
From SNESdev Wiki
Jump to navigationJump to search
(Further information on counter_latch behavior.) |
(VRAM latching behavior.) |
||
Line 162: | Line 162: | ||
===VRAM address=== | ===VRAM address=== | ||
---- | ---- | ||
====VMADDL - VRAM address low ($2116 write)==== | ====VMADDL - VRAM word address low ($2116 write)==== | ||
7 bit 0 | 7 bit 0 | ||
---- ---- | ---- ---- | ||
LLLL LLLL | LLLL LLLL | ||
|||| |||| | |||| |||| | ||
++++-++++- VRAM address low byte | ++++-++++- VRAM word address low byte | ||
On write: VMADD.low = value | |||
vram_latch = [VMADD] | |||
====VMADDH - VRAM address high ($2117 write)==== | ====VMADDH - VRAM word address high ($2117 write)==== | ||
7 bit 0 | 7 bit 0 | ||
---- ---- | ---- ---- | ||
HHHH HHHH | HHHH HHHH | ||
|||| |||| | |||| |||| | ||
++++-++++- VRAM address high byte | ++++-++++- VRAM word address high byte | ||
On write: VMADD.high = value | |||
vram_latch = [VMADD] | |||
Because the SNES only has 64 KiB of VRAM, VRAM address bit 15 has no effect. | |||
===VRAM data=== | ===VRAM data=== | ||
Line 184: | Line 192: | ||
|||| |||| | |||| |||| | ||
++++-++++- VRAM data low byte | ++++-++++- VRAM data low byte | ||
On write: If address increment mode == 0, increments VMADD | |||
====VMDATAH - VRAM data write high ($2119 write)==== | ====VMDATAH - VRAM data write high ($2119 write)==== | ||
Line 191: | Line 201: | ||
|||| |||| | |||| |||| | ||
++++-++++- VRAM data high byte | ++++-++++- VRAM data high byte | ||
On write: If address increment mode == 1, increments VMADD | |||
====VMDATALREAD - VRAM data read low ($2139 read)==== | ====VMDATALREAD - VRAM data read low ($2139 read)==== | ||
Line 198: | Line 210: | ||
|||| |||| | |||| |||| | ||
++++-++++- VRAM data low byte | ++++-++++- VRAM data low byte | ||
On read: value = vram_latch.low | |||
vram_latch = [VMADD] | |||
If address increment mode == 0, increments VMADD | |||
====VMDATAHREAD - VRAM data read | ====VMDATAHREAD - VRAM data read high ($213A read)==== | ||
7 bit 0 | 7 bit 0 | ||
---- ---- | ---- ---- | ||
Line 205: | Line 221: | ||
|||| |||| | |||| |||| | ||
++++-++++- VRAM data high byte | ++++-++++- VRAM data high byte | ||
On read: value = vram_latch.high | |||
vram_latch = [VMADD] | |||
If address increment mode == 1, increments VMADD | |||
==CGRAM== | ==CGRAM== | ||
Line 215: | Line 235: | ||
++++-++++- CGRAM word address | ++++-++++- CGRAM word address | ||
On write: cgram_byte = 0 | |||
===CGRAM data=== | ===CGRAM data=== | ||
Line 243: | Line 263: | ||
+-------------------- PPU2 open bus | +-------------------- PPU2 open bus | ||
On read: If cgram_byte == 0, value = CGDATA low | On read: If cgram_byte == 0, value = CGDATA.low | ||
If cgram_byte == 1, value = CGDATA high | If cgram_byte == 1, value = CGDATA.high | ||
cgram_byte = ~cgram_byte | cgram_byte = ~cgram_byte | ||
Line 555: | Line 575: | ||
++++-+++------------- PPU2 open bus | ++++-+++------------- PPU2 open bus | ||
On read: If ophct_byte == 0, value = OPHCT low | On read: If ophct_byte == 0, value = OPHCT.low | ||
If ophct_byte == 1, value = OPHCT high | If ophct_byte == 1, value = OPHCT.high | ||
ophct_byte = ~ophct_byte | ophct_byte = ~ophct_byte | ||
Line 567: | Line 587: | ||
++++-+++------------- PPU2 open bus | ++++-+++------------- PPU2 open bus | ||
On read: If opvct_byte == 0, value = OPVCT low | On read: If opvct_byte == 0, value = OPVCT.low | ||
If opvct_byte == 1, value = OPVCT high | If opvct_byte == 1, value = OPVCT.high | ||
opvct_byte = ~opvct_byte | opvct_byte = ~opvct_byte | ||
Revision as of 05:21, 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 word address low ($2116 write)
7 bit 0 ---- ---- LLLL LLLL |||| |||| ++++-++++- VRAM word address low byte On write: VMADD.low = value vram_latch = [VMADD]
VMADDH - VRAM word address high ($2117 write)
7 bit 0 ---- ---- HHHH HHHH |||| |||| ++++-++++- VRAM word address high byte On write: VMADD.high = value vram_latch = [VMADD]
Because the SNES only has 64 KiB of VRAM, VRAM address bit 15 has no effect.
VRAM data
VMDATAL - VRAM data write low ($2118 write)
7 bit 0 ---- ---- LLLL LLLL |||| |||| ++++-++++- VRAM data low byte On write: If address increment mode == 0, increments VMADD
VMDATAH - VRAM data write high ($2119 write)
7 bit 0 ---- ---- HHHH HHHH |||| |||| ++++-++++- VRAM data high byte On write: If address increment mode == 1, increments VMADD
VMDATALREAD - VRAM data read low ($2139 read)
7 bit 0 ---- ---- LLLL LLLL |||| |||| ++++-++++- VRAM data low byte On read: value = vram_latch.low vram_latch = [VMADD] If address increment mode == 0, increments VMADD
VMDATAHREAD - VRAM data read high ($213A read)
7 bit 0 ---- ---- LLLL LLLL |||| |||| ++++-++++- VRAM data high byte On read: value = vram_latch.high vram_latch = [VMADD] If address increment mode == 1, increments VMADD
CGRAM
CGADD - CGRAM word address ($2121 write)
7 bit 0 ---- ---- AAAA AAAA |||| |||| ++++-++++- CGRAM word address On write: 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.