quickdev16/files/docs/snes/snestech.txt
2016-02-15 17:42:39 +01:00

851 lines
32 KiB
Plaintext

SNES hardware notes
by Charles MacDonald
WWW: http://cgfm2.emuviews.com
Unpublished work Copyright 2003 Charles MacDonald
This document is in a very preliminary state and is subject to change.
Most everything within has been tested and verified on a SNES but
please be aware that my testing methods or interpretations of results
could be flawed. I can't guarantee that everything is 100% accurate.
Last updated 09/17/03
[09/17/03]
- Added the cartridge information section.
- Added some details on the screen layout.
[08/27/03]
- Fixed some typos
- Added CGRAM information
- Added notes about valid times to access OAM
[08/25/03]
- Added some sprite information
[08/22/03]
- Added mouse information
- Added multitap information
- Changed joypad section
[08/20/03]
- Initial release
Table of contents
1. Various notes
2. CGRAM
3. Sprites
3. Hardware version registers
4. I/O hardware
5. Register reference
6. Cartridge information
7. Assistance needed
8. Credits and acknowledgements
9. Disclaimer
----------------------------------------------------------------------------
Various notes
----------------------------------------------------------------------------
V-Blank occurance flag
- Bit 7 of $4212 is set at line $00E1 and cleared at line $0000 in 224-line
mode.
- Bit 7 of $4212 is set at line $00F0 and cleared at line $0000 in 239-line
mode.
Joypad automatic scanning flag
- Bit 0 of $4212 is set at line $00E1 and cleared at line $00E4 in 224-line
mode.
- Bit 0 of $4212 is set at line $00F0 and cleared at line $00F3 in 239-line
mode.
Non-maskable interrupts
According to the 65816 manual, the NMI signal is an edge-sensitive input,
so that only a high to low transition on the NMI pin will cause an interrupt
to occur. Leaving it high, low, or having a low to high transition has no
effect. I'm going to assume the PPU normally holds NMI high and brings it
low to trigger an interrupt.
The PPU will pull NMI low at line $00E8 in 224-line mode or line $00F7 in
239-line mode. It will remain low until either $4210 is read, or a new
frame starts, at which point the PPU will bring NMI high again.
The inverted state of the NMI signal from the PPU can be read through bit 7
of $4210, where 0= no NMI has been requested, 1= an NMI is pending. After
reading this register, the PPU resets the NMI signal by pulling it high.
Bit 7 of $4200 doesn't affect how the PPU manages NMIs at all, it is just
a gate between the NMI output of the PPU and the NMI input of the CPU.
When set, NMIs can be generated. When cleared, the CPU ignores the state of
the NMI pin.
Here are some details of specific situations:
When there is a pending NMI, toggling bit 7 of $4200 does not create any
additional interrupts.
Bit 7 of $4210 will be set in the NMI routine when it executes.
After the NMI routine finishes, bit 7 will remain set (assuming $4210 wasn't
read) until the start of the next frame. This will not cause more NMIs to
occur as they are only triggered by high-to-low transitions, having the NMI
pin remain low does not do anything.
Bit 7 of $4210 reflects the NMI status independantly of bit 7 of $4200.
Interlaced display
When bit 0 of $2133 is set, the screen becomes interlaced regardless of
the BG mode setting. When the screen is interlaced, the following applies:
- For BG modes 0,1,2,3,4,7 each line of the background is repeated in the
even and odd frames for single-density interlace. (224 or 239 lines shown)
- For BG modes 5,6 each line of the background is unique for the even and
odd frames for double-density interlace. (448 or 478 lines shown)
Screen layout
For an NTSC non-interlaced display, each frame consists of 262 lines.
Depending on the screen height, these lines are divided into the following
groups:
Section 224-line mode 239-line mode
Active display 224 239
Bottom blanking 12 15
Vertical sync 3 3
Top blanking 23 5
Total 262 262
Active display is the portion of the screen where graphics are displayed.
Bottom blanking is the bottom border after the active display shown at the
very bottom of the display. Lines are filled with black.
Vertical sync is the period between the bottom and top borders which is
off-screen. Lines are filled with a darker black color than in the blanking
areas.
Top blanking is the border after the vertical sync period shown at the very
top of the display. Lines are filled with black.
----------------------------------------------------------------------------
CGRAM
----------------------------------------------------------------------------
Overview
The PPU has 512 bytes of on-chip RAM called CGRAM which holds palette data.
CGRAM is divided into 256 2-byte entries that define a single color.
Each entry has the following format:
MSB LSB
-bbbbbgggggrrrrr
b = Blue component (0=black, 31=bright)
g = Green component (0=black, 31=bright)
r = Red component (0=black, 31=bright)
- = Unused bit.
The background can use the first 128 colors in BG modes 0,1,2,5,6, and all
256 colors in BG modes 3,4,7 when not in direct color mode. Sprites always
use the latter 128 colors. Specific details about palette use and selection
for each mode will be described later.
The PPU provides several registers for using CGRAM:
$2121 - CGRAM address
$2122 - CGRAM data port (write)
$213B - CGRAM data port (read)
CGRAM access
The PPU has a 9-bit address register which gives a byte offset into CGRAM.
Writing to $2121 loads the CPU data into bits 8-1 of the address register
and clears bit 0, forcing an even address to be set.
Each time $213B is read, the byte at the current offset pointed to by the
address register is returned to the CPU, and the address register is
incremented by one.
Each time $2122 is written to the address register is incremented by one.
If the address register is even during a write, the CPU data is stored in
a latch. If the address register is odd, the latched data becomes the LSB
and the new data written becomes the MSB of a 16-bit word. This word is
written to the current address, with bit 0 of the address register ignored.
The address register will wrap from $01FF to $0000 due to reading $213B or
writing to $2122. You can mix reads and writes freely.
Valid access times
When the screen is forcibly blanked or in the V-Blank period, CGRAM can be
read and written. I haven't tested access during H-Blank yet.
Here are my observations about CGRAM access during the active display
period:
- Writing to CGRAM always results in the last word written to the data port
being written to address 0,1 regardless of the address register setting.
You could think of address bits 8-1 as always being fixed to zero during
this time.
- Reading from CGRAM returns a random mix of bytes from CGRAM and data that
wasn't stored in CGRAM. The address register has no effect on where the
data comes from.
- When the screen is turned on, the previously set value in the address
register not changed. Following reads or writes with the screen off
affect the address originally selected.
CGRAM access examples
Here are some examples of unexpected behavior. Assume CGRAM contains the
bytes $AA, $BB, $CC, $DD at address $0000 for each test:
- Set address to $0000
- Write $45
CGRAM is not updated, and the LSB latch contains $45
- Set address to $0000
- Read $2138
- Write #$45
The bytes $CC, $45 are written to address $0000. $CC was the last value
in the LSB latch, and a single byte write triggers a write to CGRAM as the
previous read made the address register odd.
----------------------------------------------------------------------------
Sprites
----------------------------------------------------------------------------
The PPU can manage up to 128 sprites. Sprites use 16-color 8x8 tiles, the
same as used by the backgrounds. The sprite size can range from 1x1 tiles
up to 8x8 tiles, with several variations in between.
The attributes for each sprite are stored in 544 bytes of on-chip RAM called
OAM or "Object Attribute Memory". The OAM can be thought of having two
sections, a 512-byte table that has 128 x 4-byte entries, and a 32-byte
table used as 128 x 2-bit entries.
The PPU provides several registers for sprite control:
$2101 - OAM control
$2102 - OAM address LSB
$2103 - OAM address MSB
$2104 - OAM data port (write)
$2138 - OAM data port (read)
The OAM control register defines various aspects about the sprites:
D7 : Sprite size, bit 2
D6 : Sprite size, bit 1
D5 : Sprite size, bit 0
D4 : Sprite name offset, bit 1
D3 : Sprite name offset, bit 0
D2 : Sprite pattern table base, bit 2
D1 : Sprite pattern table base, bit 1
D0 : Sprite pattern table base, bit 0
The sprite pattern table is where the tile data for sprites is fetched from.
The table is 16K in size and can be positioned on 16K boundaries. Bits 2-0
of this register correspond to bits 16-14 of the VRAM address.
As there is only 64K of VRAM, bit 2 has no effect. Pattern data read from
$10000-$1FFFF is instead read from $00000-$0FFFF due to mirroring.
When a sprite has bit 8 of it's name field set so that it reads patterns
out of the upper 8K of the 16K table (tiles 256-511), bits 4, 3 of this
register are added to bits 14 and 13 of the VRAM address.
If the resulting address is bigger than $10000 then data is read from
$00000 onwards due to mirroring. The same holds true if the address is
bigger than $20000, due to wrapping.
The sprite sizes are as follows:
D7 D6 D5 Small Large
0 0 0 8x8 16x16
0 0 1 8x8 32x32
0 1 0 8x8 64x64
0 1 1 16x16 32x32
1 0 0 16x16 64x64
1 0 1 32x32 64x64
1 1 0 16x32 32x64
1 1 1 16x32 32x32
The last two settings are undocumented but appear to function normally.
Overview
The CPU interface to the OAM appears as a 1024-byte array. Here's a memory
map:
$0000-$01FF : 512 bytes, used as 128 x 4-byte entries
$0200-$03FF : 32 bytes, mirrored every 32 bytes (so mirrored 16 times)
Reading and writing from the mirrored areas are valid.
OAM access
The PPU has a 10-bit address register which gives a byte offset into OAM.
Writing to $2102 will load the CPU data into bits 8-1 of the address
register. Writing to $2103 will load bit 0 of the CPU data into bit 9 of
the address register. Writing to $2102 or $2103 will clear bit 0 of the
address register so an even address is always selected. You can write to
$2102 and $2103 in any order, or write to just one or the other to update
part or all of the address.
Each time $2138 is read, the byte at the current offset pointed to by the
address register is returned to the CPU, and the address register is
incremented by one.
Each time $2104 is written to the address register is incremented by one.
If the address register is even during a write, the CPU data is stored in
a latch. If the address register is odd, the latched data becomes the LSB
and the new data written becomes the MSB of a 16-bit word. This word is
written to the current address, with bit 0 of the address register ignored.
This only affects writing to offsets $0000-$01FF. The 32 byte table at
$0200-$03FF will be updated for a write to even or odd addresses. Writes
to even addresses still update the LSB latch, however.
The address register will wrap from $03FF to $0000 due to reading $2138 or
writing to $2104. You can mix reads and writes freely.
Valid access times
When the screen is forcibly blanked or in the V-Blank period, OAM can be
read and written. I haven't tested access during H-Blank yet.
It would seem that the address register is used for some internal operation
during the active display period, which involves incrementing it. Here are
my observations:
- Writing to OAM during this time results in the data being written to
consecutively larger addresses, starting at a random offset and with
a random amount of skipped bytes between the data. The address register
has no effect on where the data goes.
- Reading from OAM returns data from consecutively larger addresses,
starting at a random offset and with a random amount of skipped bytes
between the data. The address register has no effect on where the data
goes.
- Setting the address register to a known value and waiting a few scanlines
with the screen turned on results in data being read or written to a
larger address than the one originally set.
- Writing to the address register on the same scanline where a sprite is
being displayed has no effect on the sprite. I would assume during the
active display period, the address register can't be updated by the CPU
as it is being used by the PPU exclusively.
OAM access examples
Here are some examples of unexpected behavior. Assume OAM contains the
bytes $AA, $BB, $CC, $DD at address $0000 for each test:
- Set address to $0000
- Write $45
OAM is not updated, and the LSB latch contains $45
- Set address to $0000
- Read $2138
- Write #$45
The bytes $CC, $45 are written to address $0000. $CC was the last value
in the LSB latch, and a single byte write triggers a write to OAM as the
previous read made the address register odd.
- Set address to $0000
- Write #$12
- Write #$00 to $2103
- Write #$34
OAM is not updated. The second write only loads the LSB latch as the
write to $2103 cleared bit 0 of the address register.
----------------------------------------------------------------------------
Hardware version registers
----------------------------------------------------------------------------
Here are the version register return values and chip markings for my
original model NTSC SNES:
Register Value Chip
$4210 $01 Nintendo S-CPU 5A22-01
$213E $01 Nintendo S-PPU1 5C77-01
$213F $01 Nintendo S-PPU2 5C78-01
----------------------------------------------------------------------------
I/O hardware
----------------------------------------------------------------------------
The SNES has two 7-pin joypad ports. Here's a diagram of the faceplate of
the SNES to show the pin configuration:
1P port 2P port
(Power light) ( o o o | o o o o ] [ o o o o | o o o )
7 6 5 4 3 2 1 1 2 3 4 5 6 7
Pin # Description S-CPU pin (1P) S-CPU pin (2P)
Pin 1 +5V n/a n/a
Pin 2 Output strobe 35 36
Pin 3 Output 37 37 (common between both ports)
Pin 4 Serial input 1 32 28
Pin 5 Serial input 2 33 27
Pin 6 Bidirectional 25 26
Pin 7 Ground n/a n/a
Each pin is accessible through the various hardware registers as follows:
1P port
- Read $4016 to pulse pin 2.
- Writing to bit 0 of $4016 controls pin 3.
- Reading bit 0 of $4016 returns data from pin 4.
- Reading bit 1 of $4016 returns data from pin 5.
- Pin 6 is connected to bit 6 of $4201 (WRIO) and $4213 (RDIO).
2P port
- Read $4017 to pulse pin 2.
- Writing to bit 0 of $4016 controls pin 3.
- Reading bit 0 of $4017 returns data from pin 4.
- Reading bit 1 of $4017 returns data from pin 5.
- Pin 6 is connected to bit 7 of $4201 (WRIO) and $4213 (RDIO).
2P pin 6 is also connected to S-PPU2 pin 29. This is most likely the
external input signal that can be used to latch the H/V counter. A lightgun
such as the Super Scope or Konami Justifier would use pulse pin 6 of the 2P
port to make the PPU2 latch the H/V counter when it detects the raster beam.
The second serial input from pin 5 and bidirectional pin 6 are unused by
the joypad and mouse. The Hudson Super Multitap may be the only peripheral
to use them, see the multitap section for more details.
The standard way most peripherals work is to write 1 then 0 to bit 0 of
$4016 to reset the devices in the 1P and 2P ports. You can then read bit 0
of $4016 and $4017 multiple times to return data serially, starting with
the MSB down to the LSB.
I/O port
The SNES is described as having an 8-bit bidirectional I/O port. I don't
know if this physically corresponds to the expansion port on the bottom of
the control deck, or if the CPU just has an I/O port built in and some or
all of the port pins are used.
Writing to $4201 (WRIO) sets the data to be output through the I/O port.
Any bit that is also set to 1 will allow the corresponding pin to act
as an input, and data from that pin can be read through $4213 (RDIO).
The only uses I know of for the I/O port are as follows:
- Any value written to $4201 can be read back through $4213.
- As bit 7 of $4201 controls pin 6 of the 2P port, which is also shared with
the external signal input of the PPU to latch the H/V counter, writing 1
then 0 to bit 7 of $4201 will latch the H/V counter.
While bit 7 is set to 0, the latch will always hold the same value and
reading $2137 will not change the latched value. If you want to poll
the H/V counter using $2137, set bit 7 back to 1 for it to work properly.
- Pin 6 of the 1P or 2P port is used as an output to control the Hudson
Super Multitap. See the multitap section for more details.
----------------------------------------------------------------------------
Automatic reading
----------------------------------------------------------------------------
The SNES has a feature to automatically read the four serial input pins
and store them into a set of registers during V-Blank. This can be done
without the CPU having to manually write and read $4016 / $4017, saving
time for other tasks.
When bit 0 of $4200 is set, at the start of V-Blank (depending on the screen
height) the SNES will automatically do the following steps:
- Write 1 then 0 to bit 0 of $4016.
- Read $4016 and $4017 sixteen times, storing the return values from bits
0 and 1 into eight registers like so:
- 16 bits from bit 0 of $4016 are stored in $4218 (LSB) and $4219 (MSB)
- 16 bits from bit 1 of $4016 are stored in $421C (LSB) and $421D (MSB)
- 16 bits from bit 0 of $4017 are stored in $421A (LSB) and $421B (MSB)
- 16 bits from bit 1 of $4017 are stored in $421E (LSB) and $421F (MSB)
This process takes three scanlines to complete. Bit 0 of $4212 shows the
scanning status, where 1= the SNES is still reading data, 0= the SNES has
finished or automatic scanning was not enabled.
The use I've seen in games and demos is to wait for this bit to be set, and
then cleared in the NMI handler.
----------------------------------------------------------------------------
Hudson Super Multitap
----------------------------------------------------------------------------
The multitap plugs into the 1P or 2P port. It has four connectors to plug
additional joypads into, and has a switch for selecting a multiplayer or
compatability mode.
In compatability mode (switch = 2P) the joypad plugged in to connector #1
works like a standard pad. All remaining connectors are ignored, pin 6
is ignored in terms of selecting which set of joypad data to return, and
no extra data is returned in the second serial input.
In multiplayer mode (switch = 3P-5P) the first serial input returns data
from the joypad in connector #1 or #3, and the second serial input returns
data from the joypad in connector #2 or #4. Pin 6 of the 1P or 2P port
is used to select connectors #1 and #3 when set to 1, or #2 and #4 when
set to 0.
----------------------------------------------------------------------------
SNES joypad
----------------------------------------------------------------------------
The SNES joypad uses two 4021 ICs, which are 8-stage static shift registers.
They are cascaded together to form a 16-bit shift register that stores the
state of the directional pad and buttons, allowing the SNES to read out
the state of the joypad serially.
The button states will be loaded into the shift register when bit 0 of
$4016 is set to 1 and then 0. This happens to both control pads as they
share a common pin. Each time $4016 or $4017 is read, the shift register
for the 1P or 2P pad advances by one, outputting a bit which can be read
in bit 0 of $4016 or $4017 respectively.
The tail end of the shift register is filled with a one on each shift. After
the sixteenth time $4016 or $4017 has been read, all consecutive reads will
return one due to the shift register being completely filled with ones.
This will go on forever until the shift register is loaded again by writing
1 then 0 to $4016.
If at any time $4016 is left at 1, reading either joypad will always return
the state of the first input, which is the 'B' button. This won't stop until
$4016 is set to zero again.
Here is the order of button states read out through $4016 or $4017:
Read 1 - Button B Read 9 - Button A
Read 2 - Button Y Read 10 - Button X
Read 3 - Button Select Read 11 - Button L
Read 4 - Button Start Read 12 - Button R
Read 5 - Up Read 13 - '0'
Read 6 - Down Read 14 - '0'
Read 7 - Left Read 15 - '0'
Read 8 - Right Read 16 - '0'
All reads after read 16 will return 1.
All buttons are 1= pressed, 0= released.
If no joypad is plugged in, then zero is always read from $4016 or $4017.
A game can check if a joypad is connected by seeing if any reads beyond
the 16th one return '1', otherwise there is no joypad.
As far as I can tell, the joypad does not return any data through pin 5
(which always returns zero) and any setting of pin 6 will not affect the
joypad operation.
----------------------------------------------------------------------------
SNES mouse
----------------------------------------------------------------------------
The SNES mouse works in a similar fashion to the joypad. It has a custom
18-pin chip called the "SFM1" which returns data about the mouse status
serially to the SNES.
Writing 1, then 0 to bit 0 of $4016 will reset the SFM1 and subsequent reads
from $4016 or $4017 (depending on which port the mouse is plugged into) will
return the mouse state data. Leaving bit 0 of $4016 set to 1 will result
in zero always being read back.
The mouse data is as follows:
Read 1 - '0' Read 17 - Y sign
Read 2 - '0' Read 18 - Y movement bit 6 (?)
Read 3 - '0' Read 19 - Y movement bit 5
Read 4 - '0' Read 20 - Y movement bit 4
Read 5 - '0' Read 21 - Y movement bit 3
Read 6 - '0' Read 22 - Y movement bit 2
Read 7 - '0' Read 23 - Y movement bit 1
Read 8 - '0' Read 24 - Y movement bit 0
Read 9 - Right button Read 25 - X sign
Read 10 - Left button Read 26 - X movement bit 6 (?)
Read 11 - '0' Read 27 - X movement bit 5
Read 12 - '0' Read 28 - X movement bit 4
Read 13 - '0' Read 29 - X movement bit 3
Read 14 - '0' Read 30 - X movement bit 2
Read 15 - '0' Read 31 - X movement bit 1
Read 16 - '1' Read 32 - X movement bit 0
All reads after read 32 will return 1.
The left/right buttons are 1= pressed, 0= released.
The Y and X sign are 1= up/left movement, 0= down/right movement. The sign
bits do not change until the mouse is moved in a opposite direction. So
moving the mouse up, and leaving it stationary would keep the Y sign bit
set to 1.
The Y and X movement fields indicate how rapidly the mouse was moved in a
particular direction. This is usually $00-$1F, but extremely rapid movements
can yield higher values. I haven't been able to get values large enough
to indicate there is a seventh movement bit, but there may likely be one.
Both fields are zero when there is no movement.
As far as I can tell, the mouse does not return any data through pin 5
(which always returns zero) and any setting of pin 6 will not affect the
mouse operation.
----------------------------------------------------------------------------
Register reference
----------------------------------------------------------------------------
$2180 - WRAM data port
$2181 - WRAM offset (bits 7-0 are offset bits 7-0)
$2182 - WRAM offset (bits 7-0 are bits 15-8)
$2183 - WRAM offset (bit 0 is offset bit 16, bits 7-1 are unused)
Registers $2181-$2183 define a 17-bit offset in WRAM. Reading or writing
$2180 will return a byte from or write a byte to WRAM, and automatically
increment the WRAM offset by one. The offset wraps from $01FFFF to $000000.
Reading $2180, $2181, or $2183 returns the last value on the data bus,
which is usually the last byte of the opcode fetched. For example, this
value would be $21 for 'lda $2181', or $00 for 'lda [$00]' when the pointer
at $00 is $2181.
----------------------------------------------------------------------------
Cartridge information
----------------------------------------------------------------------------
Cartridge pinout
Solder side Component side
MCK - 01 32 - /RAMSEL
EXPAND - 02 33 - REFRESH
PA6 - 03 34 - PA7
/PARD - 04 35 - /PAWR
<key>
GND - 05 36 - GND
A11 - 06 37 - A12
A10 - 07 38 - A13
A9 - 08 39 - A14
A8 - 09 40 - A15
A7 - 10 41 - A16
A6 - 11 42 - A17
A5 - 12 43 - A18
A4 - 13 44 - A19
A3 - 14 45 - A20
A2 - 15 46 - A21
A1 - 16 47 - A22
A0 - 17 48 - A23
/IRQ - 18 49 - /ROMSEL
D0 - 19 50 - D4
D1 - 20 51 - D5
D2 - 21 52 - D6
D3 - 22 53 - D7
/RD - 23 54 - /WR
CIC0 - 24 55 - CIC1
CIC2 - 25 56 - CIC3
/RESET - 26 57 - SYSCK
+5V - 27 58 - +5V
<key>
PA0 - 28 59 - PA1
PA2 - 29 60 - PA3
PA4 - 30 61 - PA5
SOUND-L - 31 62 - SOUND-R
Pin assignments
A23-0 - CPU address bus
D7-0 - CPU data bus
/WR - CPU write strobe
/RD - CPU read strobe
/IRQ - CPU IRQ input. Allows on-cart hardware to interrupt the CPU.
/RESET - When the system is reset (power-up or hard reset) this goes low.
Could be used to reset additional on-cart hardware.
/RAMSEL - Goes low on accesses to WRAM at the following addresses:
00-3F:0000-1FFF
80-BF:0000-1FFF
7E-7F:0000-FFFF
/ROMSEL - Goes low on access to cartridge ROM at the following addresses:
00-3F:8000-FFFF
40-7D:0000-FFFF
80-BF:8000-FFFF
C0-FF:0000-FFFF
PA7-0 - Address bus for $2100-$21FF range in banks $00-$3F/$80-$BF (B-Bus)
/PAWR - Write strobe for B-Bus
/PARD - Read strobe for B-Bus
MCK - 21.47727 MHz master clock
SYSCK - Unknown, is an output from the CPU.
SOUND-L - Audio input to be mixed with left channel output
SOUND-R - Audio input to be mixed with right channel output
THROUGH - Connected to pin 24 of the expansion port.
REFRESH - Unknown, is an output from the CPU also connected to WRAM.
This is most likely to manage DRAM refresh.
CIC3-0 - To CIC chip on cartridge
Details
For more information about the CIC chip, please see the following:
- U.S. Patent no. 4,799,635 (NES specific)
- http://home.freeuk.com/markk/Consoles/SNES_Lockout.txt
The only hardware I know of which uses the two sound input pins is the
Super Gameboy and Super Gameboy 2.
The SNES has two address busses, the A-Bus which is used by the CPU, ROM,
WRAM, etc. and the B-Bus which is used by the PPU1, PPU2, APU I/O ports,
and WRAM. When the SNES does DMA, it can transfer data from the A-Bus to
the B-Bus or vice-versa, but not to the same bus. This holds true even
for WRAM, which is connected to both the A-Bus and B-Bus.
I would guess the B-Bus signals are brought out to the cartridge connector
so any on-cart hardware could map it's own registers within that region,
allowing for DMA from the A-Bus to it. Exactly what range of B-Bus addresses
are open for expansion purposes is unknown.
Cartridge information
Here's some information about several cartridges I've examined:
Name: Lagoon
Board: SHVC-1A3B-12
Type: LoROM / 16 megabits / 8K SRAM
This cartridge has a 74LS139 for address decoding and a 8K SRAM chip.
00-1F:8000-FFFF : Program ROM
20-3F:8000-FFFF : Unmapped
40-6F:0000-FFFF : Unmapped
70-7D:0000-FFFF : SRAM
7E-7F:0000-FFFF : Work RAM
80-9F:8000-FFFF : Program ROM
A0-BF:8000-FFFF : Unmapped
C0-EF:0000-FFFF : Unmapped
F0-FF:0000-FFFF : SRAM
- A23 and A15 are ignored, so banks $80-FF are a mirror of $00-7F.
- SRAM is mirrored repeatedly in the areas it's assigned to.
- When accessing an unmapped region, neither the ROM or SRAM are enabled.
Name: Pilotwings
Board: SHVC-1BON-02
Type: LoROM / 8 megabits / DSP-1
This cartridge has a 74LS139 for address decoding and a NEC uPD77C25 DSP
which Nintendo labels as the "DSP-1" custom chip. It also has a oscillator
and 74HCU04 to provide a clock signal, but I don't know what speed the DSP
actually runs at.
00-1F:8000-FFFF : Program ROM
20-2F:8000-FFFF : Unmapped
30-3F:8000-BFFF : DSP data register (r/w)
30-3F:C000-FFFF : DSP status register (r/o)
40-7D:0000-FFFF : Unmapped
7E-7F:0000-FFFF : Work RAM
80-9F:8000-FFFF : Program ROM
A0-AF:8000-FFFF : Unmapped
80-BF:8000-BFFF : DSP data register (r/w)
80-BF:C000-FFFF : DSP status register (r/o)
C0-FF:0000-FFFF : Unmapped
- A23 and A15 are ignored, so banks $80-FF are a mirror of $00-7F.
- DSP pins INT, SCK, /SIEN, /SOEN are all tied to +5V and are unused.
- When accessing an unmapped region, neither the ROM or DSP are enabled.
Name: Killer Instinct
Board: SHVC-1JON-20
Type: HiROM / 32 megabits
The mask ROM socket on the PCB has the following pin assignments:
+---\/---+
A20 -|01 36|- +5V
A21 -|02 35|- A23
A17 -|03 34|- +5V
A18 -|04 33|- /ROMSEL (ROM /CS)
A15 -|05 32|- A19
A12 -|06 31|- A14
A7 -|07 30|- A13
A6 -|08 29|- A8
A5 -|09 28|- A9
A4 -|10 27|- A11
A3 -|11 26|- A16
A2 -|12 25|- A10
A1 -|13 24|- /RD (ROM /OE)
A0 -|14 23|- D7
D0 -|15 22|- D6
D1 -|16 21|- D5
D2 -|17 20|- D4
GND -|18 19|- D3
+--------+
- A22 is unconnected.
- This game uses a MX23C3201 4096Kx8 mask ROM. I can't find a datasheet for
this chip, so I'm not sure what pin 35 (A23) is used for. It could be
an inverted chip select so the ROM is only mapped to banks $40-$7E and
$C0-$FF, but that's just a guess.
----------------------------------------------------------------------------
Assistance needed
----------------------------------------------------------------------------
If any games have a legitimate use of writing to OAM or reading OAM or CGRAM
during the active display period, I'd like to hear about the details of how
the data is used. So far it's been confirmed that Uniracers writes to OAM
this way, maybe there are others.
----------------------------------------------------------------------------
Credits and acknowlegements
----------------------------------------------------------------------------
- ToToTek Multimedia for the Game Doctor SF7. (www.tototek.com)
- neviksti for the SNES starter kit. (available at nesdev.parodius.com)
- John Weidman, CaitSith2, neviksti, for the SNES schematic scans.
- Gilligan for the SNES documentation.
- Qwertie for the SNES documentation.
- anomie for the post about SNES peripherals at the SNES9X development forum,
pointing out errors, and suggesting tests.
- Overload for clarifying some details about the mouse.
- Chris MacDonald for testing and support.
----------------------------------------------------------------------------
Disclaimer
----------------------------------------------------------------------------
If you use any information from this document, please credit me
(Charles MacDonald) and optionally provide a link to my webpage
(http://cgfm2.emuviews.com/) so interested parties can access it.
The credit text should be present in the accompanying documentation of
whatever project which used the information, or even in the program
itself (e.g. an about box).
Regarding distribution, you cannot put this document on another
website, nor link directly to it.