Difference between revisions of "Internal Registers"
(→Register Explanations) |
m (Sour moved page Registers to Internal Registers) |
(No difference)
|
Revision as of 17:13, 17 February 2019
SOURCE: https://wiki.superfamicom.org/registers
Contents
- 1 Address Bus B Registers
- 2 Old Style Joypad Registers
- 3 Internal CPU Registers
- 4 HDMA Registers
- 5 Register Explanations
- 6 NMI/IRQ Registers
- 7 APU Registers
- 8 WRAM Registers
- 9 Joypad registers
- 9.1 JOYSER0 - NES-style Joypad Access Port 1
- 9.2 JOYSER1 - NES-style Joypad Access Port 2
- 9.3 JOY1L - Controller Port 1 Data1 Register low byte
- 9.4 JOY1H - Controller Port 1 Data1 Register high byte
- 9.5 JOY2L - Controller Port 2 Data1 Register low byte
- 9.6 JOY2H - Controller Port 2 Data1 Register high byte
- 9.7 JOY3L - Controller Port 1 Data2 Register low byte
- 9.8 JOY3H - Controller Port 1 Data2 Register high byte
- 9.9 JOY4L - Controller Port 2 Data2 Register low byte
- 9.10 JOY4H - Controller Port 2 Data2 Register high byte
- 10 Multiplication / Division registers
- 10.1 WRMPYA - Multiplicand A
- 10.2 WRMPYB - Multiplicand B
- 10.3 WRDIVL - Dividend C low byte
- 10.4 WRDIVH - Dividend C high byte
- 10.5 WRDIVB - Divisor B
- 10.6 RDDIVL - Quotient of Divide Result low byte
- 10.7 RDDIVH - Quotient of Divide Result high byte
- 10.8 RDMPYL - Multiplication Product or Divide Remainder low byte
- 10.9 RDMPYH - Multiplication Product or Divide Remainder high byte
- 11 Misc
Address Bus B Registers
TODO: note on fast access time
Register | Address | Name | Style | Access | Timing |
---|---|---|---|---|---|
Screen Display Register | $2100
|
INIDISP | single | write | any time |
Object Size and Character Size Register | $2101
|
OBSEL | single | write | f-blank, v-blank |
OAM Address Registers (Low) | $2102
|
OAMADDL | single | write | f-blank, v-blank |
OAM Address Registers (High) | $2103
|
OAMADDH | single | write | f-blank, v-blank |
OAM Data Write Register | $2104
|
OAMDATA | single | write | f-blank, v-blank |
BG Mode and Character Size Register | $2105
|
BGMODE | single | write | f-blank, v-blank, h-blank |
Mosaic Register | $2106
|
MOSAIC | single | write | f-blank, v-blank, h-blank |
BG Tilemap Address Registers (BG1) | $2107
|
BG1SC | single | write | f-blank, v-blank |
BG Tilemap Address Registers (BG2) | $2108
|
BG2SC | single | write | f-blank, v-blank |
BG Tilemap Address Registers (BG3) | $2109
|
BG3SC | single | write | f-blank, v-blank |
BG Tilemap Address Registers (BG4) | $210A
|
BG3SC | single | write | f-blank, v-blank |
BG Character Address Registers (BG1&2) | $210B
|
BG12NBA | single | write | f-blank, v-blank |
BG Character Address Registers (BG3&4) | $210C
|
BG34NBA | single | write | f-blank, v-blank |
BG Scroll Registers (BG1) | $210D
|
BG1HOFS | dual | write | f-blank, v-blank, h-blank |
BG Scroll Registers (BG1) | $210E
|
BG1VOFS | dual | write | f-blank, v-blank, h-blank |
BG Scroll Registers (BG2) | $210F
|
BG2HOFS | dual | write | f-blank, v-blank, h-blank |
BG Scroll Registers (BG2) | $2110
|
BG2VOFS | dual | write | f-blank, v-blank, h-blank |
BG Scroll Registers (BG3) | $2111
|
BG3HOFS | dual | write | f-blank, v-blank, h-blank |
BG Scroll Registers (BG3) | $2112
|
BG3VOFS | dual | write | f-blank, v-blank, h-blank |
BG Scroll Registers (BG4) | $2113
|
BG4HOFS | dual | write | f-blank, v-blank, h-blank |
BG Scroll Registers (BG4) | $2114
|
BG4VOFS | dual | write | f-blank, v-blank, h-blank |
Video Port Control Register | $2115
|
VMAIN | single | write | f-blank, v-blank |
VRAM Address Registers (Low) | $2116
|
VMADDL | single | write | f-blank, v-blank |
VRAM Address Registers (High) | $2117
|
VMADDH | single | write | f-blank, v-blank |
VRAM Data Write Registers (Low) | $2118
|
VMDATAL | single | write | f-blank, v-blank |
VRAM Data Write Registers (High) | $2119
|
VMDATAH | single | write | f-blank, v-blank |
Mode 7 Settings Register | $211A
|
M7SEL | single | write | f-blank, v-blank |
Mode 7 Matrix Registers | $211B
|
M7A | dual | write | f-blank, v-blank, h-blank |
Mode 7 Matrix Registers | $211C
|
M7B | dual | write | f-blank, v-blank, h-blank |
Mode 7 Matrix Registers | $211D
|
M7C | dual | write | f-blank, v-blank, h-blank |
Mode 7 Matrix Registers | $211E
|
M7D | dual | write | f-blank, v-blank, h-blank |
Mode 7 Matrix Registers | $211F
|
M7X | dual | write | f-blank, v-blank, h-blank |
Mode 7 Matrix Registers | $2120
|
M7Y | dual | write | f-blank, v-blank, h-blank |
CGRAM Address Register | $2121
|
CGADD | single | write | f-blank, v-blank, h-blank |
CGRAM Data Write Register | $2122
|
CGDATA | dual | write | f-blank, v-blank, h-blank |
Window Mask Settings Registers | $2123
|
W12SEL | single | write | f-blank, v-blank, h-blank |
Window Mask Settings Registers | $2124
|
W34SEL | single | write | f-blank, v-blank, h-blank |
Window Mask Settings Registers | $2125
|
WOBJSEL | single | write | f-blank, v-blank, h-blank |
Window Position Registers (WH0) | $2126
|
WH0 | single | write | f-blank, v-blank, h-blank |
Window Position Registers (WH1) | $2127
|
WH1 | single | write | f-blank, v-blank, h-blank |
Window Position Registers (WH2) | $2128
|
WH2 | single | write | f-blank, v-blank, h-blank |
Window Position Registers (WH3) | $2129
|
WH3 | single | write | f-blank, v-blank, h-blank |
Window Mask Logic registers (BG) | $212A
|
WBGLOG | single | write | f-blank, v-blank, h-blank |
Window Mask Logic registers (OBJ) | $212B
|
WOBJLOG | single | write | f-blank, v-blank, h-blank |
Screen Destination Registers | $212C
|
TM | single | write | f-blank, v-blank, h-blank |
Screen Destination Registers | $212D
|
TS | single | write | f-blank, v-blank, h-blank |
Window Mask Destination Registers | $212E
|
TMW | single | write | f-blank, v-blank, h-blank |
Window Mask Destination Registers | $212F
|
TSW | single | write | f-blank, v-blank, h-blank |
Color Math Registers | $2130
|
CGWSEL | single | write | f-blank, v-blank, h-blank |
Color Math Registers | $2131
|
CGADSUB | single | write | f-blank, v-blank, h-blank |
Color Math Registers | $2132
|
COLDATA | single | write | f-blank, v-blank, h-blank |
Screen Mode Select Register | $2133
|
SETINI | single | write | f-blank, v-blank, h-blank |
Multiplication Result Registers | $2134
|
MPYL | single | read | f-blank, v-blank, h-blank |
Multiplication Result Registers | $2135
|
MPYM | single | read | f-blank, v-blank, h-blank |
Multiplication Result Registers | $2136
|
MPYH | single | read | f-blank, v-blank, h-blank |
Software Latch Register | $2137
|
SLHV | single | any time | |
OAM Data Read Register | $2138
|
OAMDATAREAD | dual | read | f-blank, v-blank |
VRAM Data Read Register (Low) | $2139
|
VMDATALREAD | single | read | f-blank, v-blank |
VRAM Data Read Register (High) | $213A
|
VMDATAHREAD | single | read | f-blank, v-blank |
CGRAM Data Read Register | $213B
|
CGDATAREAD | dual | read | f-blank, v-blank |
Scanline Location Registers (Horizontal) | $213C
|
OPHCT | dual | read | any time |
Scanline Location Registers (Vertical) | $213D
|
OPVCT | dual | read | any time |
PPU Status Register | $213E
|
STAT77 | single | read | any time |
PPU Status Register | $213F
|
STAT78 | single | read | any time |
APU IO Registers | $2140
|
APUIO0 | single | both | any time |
APU IO Registers | $2141
|
APUIO1 | single | both | any time |
APU IO Registers | $2142
|
APUIO2 | single | both | any time |
APU IO Registers | $2143
|
APUIO3 | single | both | any time |
WRAM Data Register | $2180
|
WMDATA | single | both | any time |
WRAM Address Registers | $2181
|
WMADDL | single | write | any time |
WRAM Address Registers | $2182
|
WMADDM | single | write | any time |
WRAM Address Registers | $2183
|
WMADDH | single | write | any time |
Old Style Joypad Registers
TODO: note on extra slow access time
Register | Address | Name | Style | Access | Timing |
---|---|---|---|---|---|
Old Style Joypad Registers | $4016
|
JOYSER0 | single (write) | read/write | any time that is not auto-joypad |
Old Style Joypad Registers | $4017
|
JOYSER1 | many (read) | read | any time that is not auto-joypad |
Internal CPU Registers
TODO: note on fast access time
Register | Address | Name | Style | Access | Timing |
---|---|---|---|---|---|
Interrupt Enable Register | $4200
|
NMITIMEN | single | write | any time |
IO Port Write Register | $4201
|
WRIO | single | write | any time |
Multiplicand Registers | $4202
|
WRMPYA | single | write | any time |
Multiplicand Registers | $4203
|
WRMPYB | single | write | any time |
Divisor & Dividend Registers | $4204
|
WRDIVL | single | write | any time |
Divisor & Dividend Registers | $4205
|
WRDIVH | single | write | any time |
Divisor & Dividend Registers | $4206
|
WRDIVB | single | write | any time |
IRQ Timer Registers (Horizontal - Low) | $4207
|
HTIMEL | single | write | any time |
IRQ Timer Registers (Horizontal - High) | $4208
|
HTIMEH | single | write | any time |
IRQ Timer Registers (Vertical - Low) | $4209
|
VTIMEL | single | write | any time |
IRQ Timer Registers (Vertical - High) | $420A
|
VTIMEH | single | write | any time |
DMA Enable Register | $420B
|
MDMAEN | single | write | any time |
HDMA Enable Register | $420C
|
HDMAEN | single | write | any time |
ROM Speed Register | $420D
|
MEMSEL | single | write | any time |
Interrupt Flag Registers | $4210
|
RDNMI | single | read | any time |
Interrupt Flag Registers | $4211
|
TIMEUP | single | read | any time |
PPU Status Register | $4212
|
HVBJOY | single | read | any time |
IO Port Read Register | $4213
|
RDIO | single | read | any time |
Multiplication Or Divide Result Registers (Low) | $4214
|
RDDIVL | single | read | any time |
Multiplication Or Divide Result Registers (High) | $4215
|
RDDIVH | single | read | any time |
Multiplication Or Divide Result Registers (Low) | $4216
|
RDMPYL | single | read | any time |
Multiplication Or Divide Result Registers (High) | $4217
|
RDMPYH | single | read | any time |
Controller Port Data Registers (Pad 1 - Low) | $4218
|
JOY1L | single | read | any time that is not auto-joypad |
Controller Port Data Registers (Pad 1 - High) | $4219
|
JOY1H | single | read | any time that is not auto-joypad |
Controller Port Data Registers (Pad 2 - Low) | $421A
|
JOY2L | single | read | any time that is not auto-joypad |
Controller Port Data Registers (Pad 2 - High) | $421B
|
JOY2H | single | read | any time that is not auto-joypad |
Controller Port Data Registers (Pad 3 - Low) | $421C
|
JOY3L | single | read | any time that is not auto-joypad |
Controller Port Data Registers (Pad 3 - High) | $421D
|
JOY3H | single | read | any time that is not auto-joypad |
Controller Port Data Registers (Pad 4 - Low) | $421E
|
JOY4L | single | read | any time that is not auto-joypad |
Controller Port Data Registers (Pad 4 - High) | $421F
|
JOY4H | single | read | any time that is not auto-joypad |
DMA Registers
These registers can be read or written at any time. TODO: write something about fast access time. TODO: write something about x here.
Register | Address | Name |
---|---|---|
DMA Control Register | $43x0
|
DMAPx |
DMA Destination Register | $43x1
|
BBADx |
DMA Source Address Registers | $43x2
|
A1TxL |
DMA Source Address Registers | $43x3
|
A1TxH |
DMA Source Address Registers | $43x4
|
A1Bx |
DMA Size Registers (Low) | $43x5
|
DASxL |
DMA Size Registers (High) | $43x6
|
DASxH |
HDMA Registers
These registers can be read or written at any time. TODO: write something about fast access time. TODO: write something about x here.
Register | Address | Name |
---|---|---|
HDMA Control Register | $43x0
|
DMAPx |
HDMA Destination Register | $43x1
|
BBADx |
HDMA Table Address Registers | $43x2
|
A1TxL |
HDMA Table Address Registers | $43x3
|
A1TxH |
HDMA Table Address Registers | $43x4
|
A1Bx |
HDMA Indirect Address Registers | $43x5
|
DASxL |
HDMA Indirect Address Registers | $43x6
|
DASxH |
HDMA Indirect Address Registers | $43x7
|
DASBx |
HDMA Mid Frame Table Address Registers (Low) | $43x8
|
A2AxL |
HDMA Mid Frame Table Address Registers (High) | $43x9
|
A2AxH |
HDMA Line Counter Register | $43xA
|
NTLRX |
Register Explanations
The flags are:
rw?fvha ||||||+--> '+' if it can be read/written at any time, '-' otherwise |||||+---> '+' if it can be read/written during H-Blank ||||+----> '+' if it can be read/written during V-Blank |||+-----> '+' if it can be read/written during force-blank ||+------> Read/Write style: 'b' => byte || 'h'/'l' => read/write high/low byte of a word || 'w' => word read/write twice low then high |+-------> 'w' if the register is writable for an effect +--------> 'r' if the register is readable for a value or effect (i.e. not [open bus](/open-bus)).
To find the entry for a particular register, search for the register number (i.e. ‘2100’) at the very beginning of the line. Note that the DMA registers are combined, so e.g. to find $4300, $4310, $4320, $4330, $4340, $4350, $4360, or $4370 you’d search for ‘43x0’.
For most registers (and most undefined bits of readable registers), the returned value is Open Bus, that is the last value read over the main bus from the ROM (typically part of the opcode arguments or the indirect base address).
Registers matching $21x4-6 or $21x8-A (where x is 0-2) return the last value read from any of the PPU1 registers $2134-6, $2138-A, or $213E. This is known as PPU1 Open Bus. Similarly, PPU2 Open Bus involves reading registers $213B-D or $213F (NOT $21xB-D though).
Note that it may be possible to write registers anytime even if marked ‘-’, but until we have proof ‘-’ is a better guess.
NMI/IRQ Registers
HVBJOY - PPU Status
NMITIMEN - Interrupt Enable Flags ($4200)
$4200 | Byte
|
☐ Read | ☑ Write
|
Access during: |
☑ Forced blank |
☑ Vertical blank |
☑ Horizontal blank |
⍰ Rendering |
7 bit 0 ---- ---- n-yx ---a | || | | || +-- Auto-Joypad Read Enable. | || When set, the registers $4218-$421f will be updated at about V Counter = $E3 (or presumably $F2). | || | ++------- IRQ enable | 0/0 = No IRQ will occur | 0/1 = An IRQ will occur sometime just after the V Counter reaches the value set in $4209/$420A. | 1/0 = An IRQ will occur sometime just after the H Counter reaches the value set in $4207/$4208. | 1/1 = An IRQ will occur sometime just after the H Counter reaches the value set in $4207/$4208 | when V Counter equals the value set in $4209/$420A. | +---------- NMI Enable If clear, NMI will not occur. If set, NMI will fire just after the start of V-Blank. NMI fires shortly after the V Counter reaches $E1 (or presumably $F0 if overscan is enabled, see register $2133).
Some games try to read this register. However, they work only because open bus behavior gives them values they expect. This register is initialized to $00 on power on or reset.
HTIMEL/HTIMEH - H Timer low/high bytes ($4207/$4208)
$4207 | Low byte
|
☐ Read | ☑ Write
|
Access during: |
☑ Forced blank |
☑ Vertical blank |
☑ Horizontal blank |
☑ Rendering |
$4208 | High byte
|
☐ Read | ☑ Write
|
Access during: |
☑ Forced blank |
☑ Vertical blank |
☑ Horizontal blank |
☑ Rendering |
15 8 7 0 ======== ======== -------h hhhhhhhh
If bit 4 of $4200 is set and bit 5 is clear, an IRQ will fire every scanline when the H Counter reaches the value set here. If bits 4 and 5 are both set, the IRQ will fire only when the V Counter equals the value set in $4209/$420A. Note that the H Counter ranges from 0 to 339, thus greater values will result in no IRQ firing. HTIME is initialized to $1ff on power on, unchanged on reset.
VTIMEL/VTIMEL - V Timer low/high bytes ($4209/$420A)
$4209 | Low byte
|
☐ Read | ☑ Write
|
Access during: |
☑ Forced blank |
☑ Vertical blank |
☑ Horizontal blank |
☑ Rendering |
$420A | High byte
|
☐ Read | ☑ Write
|
Access during: |
☑ Forced blank |
☑ Vertical blank |
☑ Horizontal blank |
☑ Rendering |
15 8 7 0 ======== ======== -------v vvvvvvvv
If bit 5 of $4200 is set and bit 4 is clear, an IRQ will fire just after the V Counter reaches the value set here. If bits 4 and 5 are both set, the IRQ will fire instead when the V Counter equals the value set here and the H Counter reaches the value set in $4207/$4208. Note that the V Counter ranges from 0 to 261 in NTSC mode (262 is possible every other frame whan interlace is active) and 0 to 311 in PAL mode (312 in interlace?), thus greater values will result in no IRQ firing. VTIME is initialized to $1ff on power on, unchanged on reset.
NMI Flag and 5A22 Version ($4210)
$4210 | Byte
|
☑ Read | ☐ Write
|
Access during: |
☑ Forced blank |
☑ Vertical blank |
☑ Horizontal blank |
☑ Rendering |
7 bit 0 ---- ---- nooo vvvv |||| |||| |||| ++++-- 5A22 chip version number |+++------- Open bus +---------- NMI Flag.
The NMI flag is set at the start of V-Blank (at the moment, we suspect when H-Counter is somewhere between $28 and $4E), and cleared on read or at the end of V-Blank. Supposedly, it is required that this register be read during NMI. Note that this bit is not affected by bit 7 of $4200. NMI is cleared on power on or reset.
TIMEUP - IRQ Flag ($4211)
$4211 | Byte
|
☑ Read | ☐ Write
|
Access during: |
☑ Forced blank |
☑ Vertical blank |
☑ Horizontal blank |
☑ Rendering |
7 bit 0 ---- ---- iooo oooo |||| |||| |+++ ++++-- Open Bus +---------- IRQ Flag
This bit is set just after an IRQ fires (at the moment, it seems to have the same delay as the NMI Flag of $4210 has following NMI), and is cleared on read or write. Supposedly, it is required that this register be read during the IRQ handler. If this really is the case, then I suspect that that read is what actually clears the CPU’s IRQ line. This register is marked read/write in another doc, with no explanation. IRQ is cleared on power on or reset.
4212 r b++++ vh-----a v = V-Blank Flag.^ h = H-Blank Flag.^^ a = Auto-Joypad Status.^^^
^If we’re currently in V-Blank, this flag is set, otherwise it is clear. The setting seems to occur at H Counter about $16-$17 when V Counter is $E1, and the clearing at about $1E with V Counter 0.
^^If we’re currently in H-Blank, this flag is set, otherwise it is clear. The setting seems to occur at H Counter about $121-$122, and the clearing at about $12-$18.
^^^This is set while Auto-Joypad Read is in progress, and cleared when complete. It typically turns on at the start of V-Blank, and completes 3 scanlines later.
This register is marked read/write in another doc, with no explanation.
APU Registers
APUIO0 - APU I/O register 0
APUIO1 - APU I/O register 1
APUIO2 - APU I/O register 2
APUIO3 - APU I/O register 3
2140 rwb++++ 2141 rwb++++ 2142 rwb++++ 2143 rwb++++ xxxxxxxx
These registers are used in communication with the SPC700. Note that the value written here is not the value read back. Rather, the value written shows up in the SPC700’s registers $f4-7, and the values written to those registers by the SPC700 are what you read here. If the SPC700 writes the register during a read, the value read will be the logical OR of the old and new values. The exact cycles during which the ‘read’ actually occurs is not known, although a good guess would be some portion of the final 3 master cycles of the 6-cycle memory access. Note that these registers are mirrored throughout the range $2140-$217f.
WRAM Registers
WMDATA - WRAM Data read/write
2180 rwb++++ xxxxxxxx
This register reads to or writes from the WRAM address set in $2181-3. The address is then incremented. The effect of mixed reads and writes is unknown, but it is suspected that they are handled logically. Note that attempting a DMA from WRAM to this register will not work, WRAM will not be written. Attempting a DMA from this register to WRAM will similarly not work, the value written is (initially) the Open Bus value. In either case, the address in $2181-3 is not incremented.
WMADDL - WRAM Address low byte
WMADDM - WRAM Address middle byte
WMADDH - WRAM Address high bit
2181 wl++++ 2182 wm++++ 2183 wh++++ -------x xxxxxxxx xxxxxxxx
This is the address that will be read or written by accesses to $2180. Note that WRAM is also mapped in the SNES memory space from $7E:0000 to $7F:FFFF, and from $0000 to $1FFF in banks $00 through $3F and $80 through $BF. Verious docs indicate that these registers may be read as well as written. However, they are wrong. These registers are open bus. DMA from WRAM to these registers has no effect. Otherwise, however, DMA writes them as normal. This means you could use DMA mode 4 to $2180 and a table in ROM to write any sequence of RAM addresses. The value does not wrap at page boundaries on increment.
Joypad registers
JOYSER0 - NES-style Joypad Access Port 1
JOYSER1 - NES-style Joypad Access Port 2
4016 rwb++++ Rd: ------ca Wr: -------l 4017 r?b++++ ---111db l = Writing this bit controlls the Latch line of both controller ports. When 1 is set, the Latch goes high (or is it low? At any rate, whichever one makes the pads latch their state). When cleared, the Latch goes the other way. a/b = These bits return the state of the Data1 line. c/d = These bits return the state of the Data2 line. Reading $4016 drives the Clock line of Controller Port 1 low. The SNES then reads the Data1 and Data2 lines, and Clock is set back to high. $4017 does the same for Port 2.
These registers basically have a direct connection to the controller ports on the front of the SNES. Note the 1-bits in $4017: the CPU chip has pins for these bits, but these pins are tied to Gnd and thus always 1. Data for normal joypads is returned in the order: B, Y, Select, Start, Up, Down, Left, Right, A, X, L, R, 0, 0, 0, 0, then ones until latched again. Note that Auto-Joypad Read (see register $4200) will effectively write 1 then 0 to bit ‘l’, then read 16 times from both $4016 and $4017. The ‘a’ bits will end up in $4218/9, with the first bit read (e.g. the B button) in bit 15 of the word. Similarly, the ‘b’ bits end up in $421a/b, the ‘c’ bits in $42c/d, and the ‘d’ bits in $421e/f. Any further bits the device may return may be read from $4016/$4017 as normal. The effect of reading these during auto-joypad read is unknown. See the section “CONTROLLERS” below for details.
JOY1L - Controller Port 1 Data1 Register low byte
JOY1H - Controller Port 1 Data1 Register high byte
JOY2L - Controller Port 2 Data1 Register low byte
JOY2H - Controller Port 2 Data1 Register high byte
JOY3L - Controller Port 1 Data2 Register low byte
JOY3H - Controller Port 1 Data2 Register high byte
JOY4L - Controller Port 2 Data2 Register low byte
JOY4H - Controller Port 2 Data2 Register high byte
4218 r l++++ 4219 r h++++ 421a r l++++ 421b r h++++ 421c r l++++ 421d r h++++ 421e r l++++ 421f r h++++ byetUDLR axlr0000 a/b/x/y/l/r/e/t = A/B/X/Y/L/R/Select/Start button status. U/D/L/R = Up/Down/Left/Right control pad status. Note that only one of L/R and only one of U/D may be set, due to the pad hardware.
The bitmap above only applies for joypads, obviously. More generically, Auto Joypad Read effectively sets 1 then 0 to $4016, then reads $4016/7 16 times to get the bits for these registers. These registers are only updated when the Auto-Joypad Read bit (bit 0) of $4200 is set. They are being updated while the Auto-Joypad Status bit (bit 0) of $4212 is set. Reading during this time will return incorrect values. See the section “CONTROLLERS” below for details.
Multiplication / Division registers
WRMPYA - Multiplicand A
WRMPYB - Multiplicand B
4202 wb++++ 4203 wb++++ mmmmmmmm
Write $4202, then $4203. 8 “machine cycles” (probably 48 master cycles) after $4203 is set, the product may be read from $4216/7. $4202 will not be altered by this process, thus a new value may be written to $4203 to perform another multiplication without resetting $4202. The multiplication is unsigned. $4202 holds the value $ff on power on and is unchanged on reset.
WRDIVL - Dividend C low byte
WRDIVH - Dividend C high byte
WRDIVB - Divisor B
4204 wl++++ 4205 wh++++ dddddddd dddddddd 4206 wb++++ bbbbbbbb
Write $4204/5, then $4206. 16 “machine cycles” (probably 96 master cycles) after $4206 is set, the quotient may be read from $4214/5, and the remainder from $4216/7. Presumably, $4204/5 are not altered by this process, much like $4202. The division is unsigned. Division by 0 gives a quotient of $FFFF and a remainder of C. WRDIV holds the value $ffff on power on and is unchanged on reset.
RDDIVL - Quotient of Divide Result low byte
RDDIVH - Quotient of Divide Result high byte
4214 r l++++ 4215 r h++++ qqqqqqqq qqqqqqqq Write $4204/5, then $4206. 16 "machine cycles" (probably 96 master cycles) after $4206 is set, the quotient may be read from these registers, and the remainder from $4216/7. The division is unsigned.
RDMPYL - Multiplication Product or Divide Remainder low byte
RDMPYH - Multiplication Product or Divide Remainder high byte
4216 r l++++ 4217 r h++++ xxxxxxxx xxxxxxxx
Write $4202, then $4203. 8 “machine cycles” (probably 48 master cycles) after $4203 is set, the product may be read from these registers. Write $4204/5, then $4206. 16 “machine cycles” (probably 96 master cycles) after $4206 is set, the quotient may be read from $4214/5, and the remainder from these registers. The multiplication and division are both unsigned.
Misc
WRIO - Programmable I/O port (out-port)
4201 wb++++ abxxxxxx
This is basically just an 8-bit I/O Port. ‘b’ is connected to pin 6 of Controller Port 1. ‘a’ is connected to pin 6 of Controller Port 2, and to the PPU Latch line. Thus, writing a 0 then a 1 to bit ‘a’ will latch the H and V Counters much like reading $2137 (the latch happens on the transition to 0). When bit ‘a’ is 0, no latching can occur. Any other effects of this register are unknown. See $4213 for the I half of the I/O Port. Note that the IO Port is initialized as if this register were written with all 1-bits at power up, unchanged on reset(?).
RDIO - Programmable I/O port (in-port)
4213 r b++++ abxxxxxx
Reading this register reads data from the I/O Port. The way the I/O Port works, any bit set to 0 in $4201 will be 0 here. Any bit set to 1 in $4201 may be 1 or 0 here, depending on whether any other device connected to the I/O Port has set a 0 to that bit. Bit ‘b’ is connected to pin 6 of Controller Port 1. Bit ‘a’ is connected to pin 6 of Controller Port 2, and to the PPU Latch line. See register $4201 for the O side of the I/O Port.
MEMSEL - ROM Access Speed
420d wb++++ -------f f = FastROM select.
The SNES uses a master clock running at about 21.477 MHz (current theory is 1.89e9/88 Hz). By default, the SNES takes 8 master cycles for each ROM access. If this bit is set and ROM is accessed via banks $80-$FF, only 6 master cycles will be used. This register is initialized to $00 on power on (or reset?). See my memory map and timing doc (memmap.txt) for more details.
????x - Unknown (x=0-7)
????x - Unknown (x=0-7)
43xb rwb++++ 43xf rwb++++ ????????
The effects of these registers (if any) are unknown. $43xf and $43xb are really aliases for the same register. This register is set to $ff on power on, and is unchanged on reset.