SNES cartridges come in a few different variants, distinct in a few major ways. As noted in the main SNES reproduction guide, there are six major categories that set apart different boards – bank type, ROM size, SRAM size, extra chips, speed, and the video type or region. If you check out my big list of SNES games you’ll see the games sorted by these different categories. For the purpose of this post, since we don’t have an easy way of reproducing these chips (and I lack the knowledge to sufficiently explain their functions), we’re only going to focus on designs of cartridges that use “Normal” chips. The other types are “enhancement chips” – usually proprietary graphics-boosting chips. The popular example that you probably already know about is the Super FX chip, used in games like Star Fox to generate better 3D graphics. (Note that you can still make these games, you’ll just need to use a donor cartridge that already has one of these chips on it.) The “normal” chips include one or more ROM chips and a CIC region lockout chip. And if your game saves, then it’ll also have a mapper, battery, and SRAM. There are also various capacitors and possibly resistors and diodes for games that have a battery.
Table of Contents
- The Cartridge Connector
- Power Supplies
- CIC Region Lockout Chip
- ROM Connections
- SRAM Connections
- Battery Circuit
- SNES Memory Map
- Further Remarks
The Cartridge Connector
Let’s start out our analysis at the cartridge connector – the exposed teeth-looking pads at the bottom of the board that goes into your SNES. There are two major variations of the connector – one that has just a large 46-pin section, and another variation that additionally has two sections of 8 more pins on each side of the main 46-pin connector (for a total of 62 pins). We’ll be looking at only the 46-pin variation. Since we’re ignoring 8 pins on either side of the 46-pin part, the numbering is going to be offset by a bit. If you look closely, you’ll see some of the pins called out in green above the gold teeth. Thanks to neviksti for the convenient pinout.
VCC, GND: Power pins
A0-A15: Address pins (offset)
BA0-BA7: Address pins (bank)
D0-D7: Data pins
/RD: Read data
/WR: Write command
/CART: Low when accessing ROM data (only goes low during certain addresses, based on the memory map)
CIC pins: CIC interface with the SNES
/RESET: Reset signal
/IRQ: Interrupt request
As far as I have seen, the /IRQ pin isn’t really used for much on the cartridge. It might have some use in some niche areas, probably with some extra enhancement chips on the board, but for the purposes of this post we will be ignoring it. Let’s start the analysis with an overview of the components on the board and how power is applied.
On every SNES board you’ll notice a handful of capacitors. There’s one large bulk electrolytic capacitor (looks like a metal can) that’s used to keep the VCC rail powered on and steady, so that varying voltages supplied from the SNES don’t interrupt the operation of the game, and to help maintain power during any voltage dropouts or similar events. Similarly, there are usually multiple small ceramic capacitors scattered across the board. There should be at least one for each major chip on the board, like the ROM, RAM, and CIC. These are called decoupling capacitors, and are used to filter out any stray noisy signals that may be propagating through the VCC line that could disturb the chips and circuitry on the board. If you don’t have these capacitors, the board will still probably work ok, but it’s good electrical engineering practice to include them. For my custom boards, I use 22 uF electrolytic capacitors and 0.1 uF ceramic capacitors.
CIC Region Lockout Chip
Every SNES game comes with one of these region lockout chips. They were used by Nintendo to prevent you from using a game from one region in the hardware from a different region. They had their reasons for this… with only one of which that actually benefited the consumer. There are two main types of video encoding in the world – NTSC and PAL. There’s a huge history behind these standards, and it’s quite interesting if you’re a nerd like me and think video encoding standards are something worth learning about, but the only thing that really matters for our purposes is that some PAL games played on NTSC consoles (and vice versa) can get really weird. NTSC runs at 60 Hz, while PAL runs at 50 Hz, making the games run slower or faster depending on which you’re using, and a bunch of graphical glitches can occur too. That’s even if the game will start up.
Anyway… the CIC chip is a necessary evil. I’m not going to go into how it works, but I WILL tell you how to fake out the chip with your own. All you need is a PIC12F629, a tiny little 8-pin microcontroller, and some custom code from SD2SNES. Just extract the folder and find the file named “supercic-key.hex” and MAKE SURE it ends with -key, NOT -lock. You can load this file up into a cheap programmer, like the TL866, and load it into the PIC. Then, route the pins as shown below.
To start talking about how the ROM connects to the cartridge connector, let’s get the easiest ones out of the way first.
D0 through D7 are the data lines. Whenever an address is called from the SNES onto the ROM A (and BA) pins, an 8-bit word is placed on the data lines and read by the SNES. So, it makes sense that D0 on the ROM connects to D0 on the cartridge connector, and so on. The collection of data pins (normally listed as D or Q pins) creates what is known as the data bus. It is important that only one device outputs onto the data bus at one time – otherwise, you will get what is known as a “bus conflict”. This can happen if, say, the ROM and the RAM are both trying to output data at once. Or maybe you’re using a 27C322 with mutliplexers, and you don’t drive the multiplexers correctly. In order to prevent bus conflicts from happening, you can use the various enabling pins on devices to control the data output. We’ll go over the RAM connections later.
As it happens, ROM pins A0 through A14 are all connected to their respective address pins on the cartridge connector. On HiROM boards, this continues with A15, A16 (which connects to BA0), A17 (BA1), etc.
However, on LoROM boards, A15 is skipped. Instead of the ROM A15 connecting to the cartridge connector A15, it instead connects to cartridge connector BA0. Then, BA1 connects to A16. And so on, until BA7, which connects to ROM A22.
You might be asking, what’s A15 connected to then? Well, if you have a LoROM board with no SRAM, it’s connected to nothing! But if you have SRAM, it plays a bigger role. We’ll cover this in the memory map section later on.
There are two pins that control when the ROM outputs data onto the data bus – /CE (or /CS) and /OE. These stand for “Chip Select/Enable” and “Output Enable” respectively, and they both need to be active (driven to GND) for the ROM to operate. If one of these pins is disabled, then the D0 through D7 pins will be put into a high-impedance state, where no data is output onto the data bus, and thus cannot produce a bus conflict with another device.
There are multiple ways of connecting these enable pins to achieve the same results. The way Nintendo wired cartridges, as far as I have been able to find, is that the /OE pin is driven by the /CART signal, and the /CE pin is driven by the /RD signal. Remember, /CART and /RD come from the SNES, so these signals represent what the SNES wants from the cartridge. In general, the /RD signal is active whenever data is being read from the cartridge. The /CART signal will change based on specific address locations, which will be covered later with the memory map.
Note that /CART isn’t always directly connected to the /OE pin. In order to manage both ROM and RAM data, a decoder (like the MAD-1 or the ‘139) will be used to manage when to operate each device. But in general, the output of the decoder that controls /OE will be in part determined by the /CART signal.
Here’s an oscilloscope trace of what the /RD, /CART, and /WR lines look like on a SNES cartridge:
You can see that the /CART signal does not toggle. You can also see that the /WR and /RD lines toggle at a fixed frequency.
If you want optimal operation of a ROM in terms of timing and power consumption, the /CART signal should drive the /CE pin and the /RD signal should drive the /OE pin. This is because the /RD signal toggles continuously for each data cycle, while the /CART signal is driven either on or off for longer periods of time. When the /CE pin is activated on a ROM chip (and generally any other electronic device), that puts the device into a “ready” state, where processes internal to the device start up. A ROM chip will respond faster when its already active, and the /OE pin toggles data output, rather than the other way around where every toggle of the /CE pin will cause the chip to essentially start-up over and over again. You can find this out by reading datasheets – one of my favorite pastimes!
Now, obviously Nintendo did this backwards in at least a large handful of boards, so it isn’t absolutely necessary to get the optimal operation out of these devices if it makes things easier to manage, helps prevent bus conflicts, or gives other advantages. If a cartridge works without damaging anything or running into errors, then it just works!
Like the ROM, a lot of the SRAM pins are straightforward. Let’s start with a quick look at the power supply – since the SRAM keeps our save data, we need it to survive even when the console is off!
The VCC pin on the SRAM chip is powered by either the VCC from the SNES (5 V) or the voltage from the battery (VBAT, which is usually 3 V with a C2032 battery). This is done with two small diodes connected to each voltage source. This acts like an OR gate.
When VCC is on, the voltage on the SRAM supply is ~5 V, which causes the battery to not discharge any power through its diode. When VCC is off, the voltage on the SRAM supply is ~3 V, supplied by the battery. The resistor R2 is there as a current limiting resistor. This is to make sure the battery isn’t accidentally short circuited, or to stop it from discharging too quickly during a catastrophic event. You shouldn’t make this resistor too large, though, because you don’t want to limit the current coming out of the battery during normal operation!
Data Pins and Write/Output Enable
The digital pins D0 through D7 are all connected to the D0 through D7 pins on the cartridge connector (the data bus). /WE (write enable) is connected to /WR on the cartridge connector, which tells the cartridge when to write data onto the SRAM from the data bus, like when you’re saving your game. And /OE is connected to /RD on the cartridge connector so that it only outputs data onto the data bus when the SNES requests cartridge data, and when the chip enable pins are active.
The address pins on the SRAM are actually more straightforward than the ROM address lines. A0 through A12 all connect to their respective cartridge connector address lines. A13 and A14 on LoROM boards also connect to A13 and A14 on the cartridge connector. The only difference is on HiROM boards, A13 and A14 are connected to BA0 and BA1 on the connector, respectively. You’ll only ever see SRAM’s A13 and A14 used on a few games, that is, games with 256 Kbit (32 KB) of SRAM. Theoretically, for larger sizes of RAM, the addresses would continue sequentially for both bank types. It’s good to note that on games with 64Kb (8KB) of SRAM, A13 and A14 on the SRAM chip can just be tied to VCC or GND to simulate a smaller RAM size, and on games with 16 Kbit (2 KB) of SRAM, A11 and A12 can also be tied to VCC or GND.
Chip Enable Pins
This leaves us with the /CE pin (chip enable), and, in the case of smaller SRAM chips, CE2 pin (secondary chip enable). If the SRAM has both pins, the /CE pin and the CE2 pin both need to be at the correct voltage level in order to allow the SRAM to operate – if one is disabled, the entire chip will be disabled. No data can be written or output on the device while disabled. For /CE, it needs to be pulled to GND to activate. The CE2 pin is similar to the /CE pin, but inverse logic – it needs to be pulled to VCC to activate. If either of these pins are not at the correct voltage, the chip will remain disabled.
On my boards and on standard SNES boards (without the MAD-1 chip), the /CE pin is controlled by the SRAM decoder, and the CE2 pin is controlled by the NPN circuit. The SRAM decoder is commonly a 74HC139, or equivalent part (I’ll denote it as ‘139). A common decoder chip that Nintendo’s SNES boards use are the MAD-1, which stands for Memory Address Decoder. They’re also commonly used on multi-ROM chip boards to switch between which ROM should be active. We can replicate its functions with the ‘139 decoder and the battery transistor circuit, detailed below.
Most importantly, when a game is powered off or removed, the SRAM needs to exist in a low-power standby mode while the battery backup is supplying the SRAM as described earlier. The SRAM on SNES games is volatile. This means that whenever power is removed from the chip, all the memory is erased. That’s why you have the battery inside games that save, and why you need to go replace all of your old NES, SNES, Genesis, and Gameboy game batteries RIGHT NOW OR ELSE YOU’LL LOSE YOUR SAVE DATA GO DO IT NOW!! But be sure to keep your SRAM powered while you replace them!
Anyway… as I mentioned earlier, the /CE pin is connected to the SRAM decoder. Where on the decoder it’s connected and when it’s activated is determined by the resulting memory map the game follows based on the “bank type” of the game – LoROM or HiROM. Basically, whenever the SRAM needs to be activated for saving, the decoder pulls the /CE pin to GND, and whenever it isn’t being used, it keeps it at VCC. The memory mapping will be covered later, as it requires a lot of explanation – don’t worry, it’s coming. For now, let’s move on and look at the standby mode we need the SRAM to operate within and battery circuit and see what’s going on there.
The typical coin cell batteries (CR2032) are rated for 220 mAh, or milliamp-hours. This isn’t very high when talking about long-term saving under normal operation, if your board operates with just 1 mA when disconnected from the SNES, for example, your save game will last at most around 220 hours! So it’s crucial to get that current as low as possible to keep your save games going for a long time.
Using 64K SRAM
Let’s look at the circuit below as an example for saving with 64K of SRAM, and the two states it can be in.
The NPN transistor is activated by the /RESET signal coming from the cartridge connector. The /RESET pin is held at VCC during normal gameplay, but pulled to GND when the reset button is held down, or when the console is off.
Left: When /RESET is at VCC, current flows into the base of Q1. This allows current to conduct from collector to emitter (assuming the gain of the device is higher than RB/RE) and the CE2 pin is pulled to VCC. This allows the operation of the SRAM chip, depending on what /CE is doing.
Right: When /RESET is at GND or disconnected, the transistor base current goes to zero, and conduction from collector to emitter is cut off. The CE2 pin is pulled low through the lower resistor (called a pull-down resistor), which automatically disables the SRAM no matter what /CE is doing.
To better explain the point of this circuit, let’s look at an example of a simpler circuit one might want to use instead that includes no transistor. After all, why do we care what happens to CE2 when the game is off? Why not just tie CE2 to VCC permanently, control the SRAM activation with only /CE, and be done with it? That’s what I wondered too, originally – I had the ‘139 decoder take care of the /CE pin, and separately held CE2 to VCC. And when the cartridge wasn’t powered, I had a pull-up resistor from /CE to the SRAM’s VCC pin, which was powered by the battery, to keep the chip from operating while off (to make sure no random data got written to the SRAM from noise). This worked great – the game would save just fine. Except for one tiny detail… take a look at the schematic:
So as you can see, I had a pull-up resistor R3 from /CE to VCC to keep the SRAM off during normal operation of the game and when the decoder wasn’t pulling the pin down to activate the SRAM. But when the game turned off….
Left (what I thought would happen): The ‘139 decoder is off, so we remove the connection from it to /CE. The SRAM’s /CE pin is then pulled up to the voltage from the battery, minus a diode drop. The datasheet on the SRAM says it can retain data down to 2 volts, so we’re in the clear. Right…..?
Right (what ACTUALLY happened): The ‘139 decoder is powered off, but there is still a leakage current through the output pin to ground – because nothing is perfect! Unfortunately this leakage current isn’t detailed on the datasheet anywhere, but disconnecting the leg reduces the current draw, so we know it’s a problem. Based on measurements elsewhere in the circuit, I estimated this leakage (on this particular chip) to be approximately 500 uA (microamps). Also, the SRAM chip can draw up to 2 mA during normal operation while in standby – I estimated about 1 mA on my particular part. These two currents caused voltage drops across the resistor R3, and the battery current limiting resistor R2, and also increased the voltage drop across the diode D2 because of the current being conducted. So after all of this, the supply voltage on the SRAM was only 2.1 V, and the /CE pin was at a paltry 1.6 V.
Maybe you’re saying – ok, wait a minute, why is the SRAM pulling so much current when it’s off? Even if the voltage was at a full 3 volts, it would still be drawing too much current for the battery to last! How does any save game survive?
If you look at the datasheet of a standard 64K SRAM chip, and look at the standby current, you’ll see this:
The conditions in the middle column (Test Condition) say that CE2 needs to be held to GND, or /CE needs to be held to VCC (within 0.2 V) in order to get the low standby current in the microamps. That’s how the game holds a save for a long time – and exactly why the games weren’t holding a save for very long. The battery was draining! So, we need the decoder connected to the /CE pin. What if we ground CE2 when the game is off instead?
So, remember the NPN circuit I showed you before?
We can see that if the /RESET pin is at GND or floating, then the transistor won’t be conducting. Then, the resistor RE pulls down the CE2 pin all the way to GND – no voltage drop to worry about. This is what puts the SRAM in the low standby current mode. Depending on the chip you get, you could see as little as 1 microamp of power being pulled from the battery – this would theoretically allow your game to last for 220,000 hours, or about 25 years!
Using 256K SRAM
Now, 256 Kbit SRAM doesn’t have a CE2 pin. So in order to get to a low power state, our only option for long-term saves is to keep /CE within 0.2 V of the SRAM VCC. Nintendo’s answer to this was the custom-built MAD-1 decoder, as that chip controls the SRAM’s /CE pin and has connections to the battery and voltage supply pin of the SRAM. We can’t exactly replicate a MAD-1 chip, so our answer to this problem is gonna look a bit different!
The save circuit for using 256K SRAM chips is actually quite similar to the 64K SRAM circuit above. It’s another simple transistor circuit. Instead of attaching the emitter to GND through a resistor, we’ll instead connect that to the output of the ‘139 decoder that activates the /CE pin of the SRAM. And instead of connecting the collector to VCC, this will instead go to the /CE pin of the 256K SRAM. Finally, we add a pull-up resistor from the collector to the VCC of the SRAM (note that this VCC is the voltage bus after the two diodes combining the SNES power and battery power on the cartridge together). The transistor stays an NPN, and the base is still connected to the /RESET line through a resistor. See the circuit below.
Now, a bit of analysis. This NPN transistor basically combines two previously separated inputs – /RESET from the cart edge and /CE command from the decoder.
Left: When /RESET is VCC (normal operation) and the ‘139 output is GND (to activate the SRAM), current flows into the base of the transistor, causing the /CE pin to conduct down to GND as well.
Middle: During normal operation as with the left case, when the ‘139 output is at VCC, or when the SRAM is to be disabled, no current flows into the base of the transistor. The /CE pin is then pulled up to VCC through RC.
Right: When /RESET is GND, no current can flow into the base of the transistor, and thus like the middle case, the /CE pin is pulled to VCC. Because there is very little leakage through the NPN transistor, there will be little to no voltage drop seen across the pull-up resistor RC, ensuring the voltage is within the small voltage margin allowed for data retention. Note that this circuit can easily be applied to the 64K SRAM circuit as well, we just need to tie CE2 to VCC as well!
So now, I think it’s time we finally talk about the memory map of SNES games, what the true difference is between LoROM and HiROM, and how that affects our connections. This next section is going to get a bit confusing and wordy, so bear with me! This is the real meat and potatoes of this entry.
SNES Memory Map
The SNES organizes information into different areas of memory for different purposes. Based on development manuals we can figure out where different types of memory are stored. There’s some pretty technical stuff going on here, and I’ll do my best to explain it in as simple of terms as possible. And I’ll only go into what we care about as it relates to the mapper on the cartridge, rather than trying to explain all of it (because I’ll probably embarrass myself with misinformation if I try to anyway).
It’s important to remember that the memory maps detailed below are driven by the SNES, not by the cartridge. The SNES CPU generates the address lines, and what is activated and what is not is (mostly) determined by how the cartridge is wired. Traditionally, you usually see LoROM and HiROM types (or modes 20 and 21, respectively, as seen in the manual). The actual difference between these cartridges lies in how they are wired up. Let’s take a quick look at how the SNES CPU memory is divided up.
This is from the official manual and honestly it’s hard to look at. The only thing I really want to point out here is the cross-shaded part of the map. This represents when the SNES is expecting data from the ROM. Whenever the CPU address (on pins A0-A15 and BA0-BA7) is in these locations, the /CART pin on the cartridge connector is pulled LOW to activate the ROM’s memory. In all the other locations, the /CART pin will be pulled HIGH to deactivate the ROM output.
You’re about to get blasted with some more charts with a lot of hexadecimal numbers all over the place. Luckily, the next few charts you’ll be looking at are a lot easier to read than the first one up there. So I’m going to briefly explain what these hex numbers are referencing. Take a look at what the memory map becomes when a LoROM board is used (from page 95 of the manual) for an easier look:
If you ever took any kind of digital logic class in school, recall that one hexadecimal number is four binary numbers. So one hex digit represents four address pins. The standard notation to show a hex number instead of a decimal number has an 0x before the number. Similarly, binary numbers have 0b before the number (decimal numbers are just written out). So 0xC is 12 in decimal, 0b1100 in binary. 0xFF is 255 in decimal, 0b11111111 in binary.
Refer back to the cartridge connector – there are sixteen “A” address pins (offset, making a four digit hex number) and eight “BA” address pins (bank, making a two digit hex number). This chart shows why they’re known as “bank” and “offset” address pins. Essentially, the A pins determine where in the row the data is accessed, and the BA pins determine the column. For example, an offset of 0x0000 means that the bottom sixteen address pins (A0 to A15) are all 0. An offset of 0xFFFF means all the pins are 1. A bank of 0x00 means the top eight address pins (BA0 to BA7) are all 0, and 0xFF means they’re all 1. It’s a very common practice to organize data into different banks like this.
So, if the SNES CPU sends the address for bank 0x73, with an offset 0x6000, the data on the address pins of the cartridge connector would look like this:
Yeah, Windows’ built in programming calculator comes in handy here. You’ll see the binary number up there – each digit references a different address pin on the cartridge connector. So if BA6, BA5, BA4, BA1, BA0, A14, and A13 are all 1’s and the rest 0’s, the SNES will access the data at address 0x73:6000, wherever it may come from based on the memory map.
Before going any further, it’s time to briefly talk about the chip known as the “mapper”. On my boards, and most other unofficial reproduction boards, the mapper used is a dual ‘139 decoder. Official Nintendo boards sometimes use the ‘139, but also use a proprietary MAD-1 decoder. I’ll only be talking about the ‘139. Each of the two decoders on this dual chip have two inputs and four outputs, along with an enable pin. The truth table is below.
Remember that for the /OE or /CE pins on the various chips on the board, the logic level is pulled LOW to enable. So we use the decoder to tie these lines low. The way the inputs are wired will manipulate how the SNES memory map from before actually functions. We can then redraw the memory map for the two main different wirings for cartridges (LoROM and HiROM).
LoROM Memory Map (Mode 20)
Remember how I mentioned the CPU A15 address was skipped on LoROM boards? Well, it’s actually connected to both the A0 and A1 inputs on the decoder for games that save. This means that when CPU A15 is 0, output Y0 will be pulled LOW. When CPU A15 is 1, output Y3 is pulled LOW. The enable pin of this decoder is connected to the /CART pin on the cartridge connector, so only when the SNES requests ROM data will the decoder pull one of the outputs low.
The output of Y3 is directly connected to the /OE pin on the ROM. Therefore, the output of the ROM is only enabled when CPU A15 is 1, and when /CART is LOW. Take a look at the resulting memory map for LoROM boards again.
Because CPU A15 must be 1 to enable the ROM output, any offset below 0x8000 disables the ROM output (because 0x8000 means A15 is 1 and every address below that is 0). Any offset above 0x8000 means CPU A15 is set to 1, and therefore the ROM output is enabled (as long as the decoder is enabled with the /CART line). The only region of the memory where the ROM output would be enabled, but is pulled HIGH because the /CART pin will not be enabled, is between banks 0x7E to 0x7F (which is reserved for use by the SNES WRAM).
Ever wonder why we call LoROM and HiROM different “bank” types? It’s because of the memory map – LoROM uses only half of each bank for ROM information. HiROM uses the entire bank, but we’ll talk about that type later.
Another important thing to note is the symmetry of the map. Doesn’t it look like the memory is symmetrical across the line between banks 0x7F and 0x80? There’s a reason for this! Any bank above 0x80 (0b1000000) means the BA7 line is 1. But, if you didn’t notice already, BA7 isn’t actually connected anywhere on a LoROM board. Therefore, the cartridge outputs the same data when banks above 0x80 are called, treating it as if the address was actually in banks 0x00 and above. 0x80 corresponds to 0x00, 0x81 corresponds to 0x01, and so on. This effect is called “mirroring”. This will be important later.
Now, look at that LoROM memory map picture again and find that location 0x73:6000 we talked about earlier. Because the offset is below 0x8000, the ROM output is disabled from the decoder. You’ll see this address is in a lightly shaded box labelled “Static RAM Area”. As it happens, when this specific memory location is accessed, the Static RAM (or SRAM) on the cartridge is being used. In fact, if you look at the entire shaded box, you’ll see that on a cartridge wired in the LoROM PCB type, the SRAM is enabled anytime the SNES accesses banks 0x70 to 0x7D with an offset of 0x0000 to 0x8000. Essentially, the SRAM needs to be enabled whenever the memory in this region is being accessed, which is done by the second decoder in our dual ‘139 package.
Remember the Y0 output from the first decoder? It’s set to 0 whenever CPU A15 is also 0. If we put this Y0 pin on the enable line of the second decoder, we can make this second decoder only allow output whenever CPU A15 is 0. Since the SRAM region in the LoROM memory map is located in a region when CPU A15 is 0 (below offset 0x8000), we can achieve this very effect. So now with the offset taken care of, we have to take into account the bank region. This is where it gets a bit tricky.
First, remember that along with CPU A15, /CART is controlling the output of Y0 as well. Below offset 0x8000, /CART is only active in the banks 0x40 to 0x7D and 0xC0 to 0xFF. Because of the mirroring effect we discussed earlier, we will ignore 0xC0 to 0xFF and focus on 0x40 to 0x7D. Because /CART is disabled in banks above 0x7D, and the SRAM region also stops at 0x7D, we have one boundary already ready to go for enabling the SRAM. Now all we need is to check if the address is above 0x70.
0x70 corresponds to 0b01110000 in binary, or BA4, BA5, and BA6 set to 1 and the rest set to 0. Here, we run into a small issue. We have to check for 3 pins, but we only have 2 inputs available. Check out that memory map again, though. The area next to the SRAM between banks 0x60 and 0x6F is labelled “DSP Area”. Well, hot dog, we’re making simple reproductions that don’t have any extra chips on them! Essentially, because we won’t ever be using the DSP area on our boards, we can treat this memory region as unused. So we can actually ignore BA4, and extend our SRAM region from 0x60 (0b01100000 in binary) to 0x7D. To get our 0x60 boundary, looking at the number in binary, we see that all we need to do is to check if BA5 and BA6 are 1’s. If they are 0’s, the bank will be lower than 0x60. So the second decoder will have these two address lines as inputs, making the Y3 output go low when they are both 1’s. Tie this Y3 to the SRAM /CE line and we’ve got our SRAM memory region covered!
So that’s the LoROM memory map. A bit tricky to explain, but we got it! Onto the HiROM board type.
HiROM Memory Map (Mode 21)
Now that we’ve got a grasp on how this memory map works, let’s take a look at the HiROM memory map.
In my opinion, figuring out HiROM is easier than LoROM, at least in terms of setting up the decoder. For starters, look at the ROM area. It’s waaaay off to the left of the map. Why is that?
The ROM area is between banks 0xC0 to 0xFF. This corresponds to the values of BA6 and BA7 being 1. But….. those pins aren’t even connected on the ROM! How can you prove this to yourself without looking at a board? Well, if each SNES address pin was connected to its corresponding ROM address pin, BA5 connects to A21 on the ROM. And A21 is the 22nd address pin. Meaning, we have 2^22 bytes available to work with, or 4,194,304 bytes (4MB, or 32Mbit). That’s exactly the maximum size of (most) SNES games, and the maximum size of the 27C322. And it’s also the size of the area of the ROM area on the memory map!
Now, you might be asking yourself, what about that big ol’ empty space in the middle between banks 0x40 and 0x7D? Isn’t that data going to be accessed too if BA7 and BA6 are 0? Well, maybe. That area is part of the memory where /CART would enable the ROM, sure, but we’re missing another detail. You may have seen the terms “FastROM” and “SlowROM” thrown around. Generally, you don’t need to bother worrying about the differences between the two unless you’re looking at the actual operation of the board. FastROM is defined as a response time of 120 nanoseconds, and SlowROM is 200 nanoseconds. Apparently, at the start of the SNES life cycle, ROMs that responded at faster speeds were more expensive. So Nintendo made it so the SNES can operate only at slower speeds in banks below 0x80, restricting the game to operate in a “SlowROM” mode. However, in banks above 0x80, the clock speed of the SNES can be increased in the code to accommodate faster response times from ROMs, if they had the capability, in a “FastROM” mode.
Since the memory in the upper banks can operate at both fast AND slow speeds, and the memory that would be mirrored in the slower lower banks is also cut off at 0x7D by the WRAM of the SNES, it was probably easier to just define the working ROM area to be in banks above 0xC0.
So what does that mean for us? Well, if you recall the SNES CPU map way up above, remember that the /CART line is LOW in these upper banks. So we don’t have to worry at all about trying to figure out when to enable the ROM – we just tie the /CART line directly to the ROM’s /OE pin! Now all that’s left is to figure out how to enable the SRAM properly. The RAM in the HiROM memory map above is specified between offsets 0x6000 to 0x8000, in banks 0x30 to 0x3F.
Let’s start with the offset addresses. 0x8000 and lower requires our good ol’ friend A15 to be 0, since 0x8000 and above means A15 is 1. 0x6 is 0b0110 in binary, which in 0x6000 corresponds to A14 and A13 needing to be 1’s. So, so far, our requirements are that A13 and A14 are 1, and A15 is 0.
As for the banks, 0x40 is the upper bound. 0x40 in binary is 0b01000000, or BA6 as 1. So we need BA6 to stay 0 to keep it below 0x40. 0x30 in binary is 0b00110000, or BA5 and BA4 as 1. Our bank requirements are that BA4 and BA5 are 1, and BA6 is 0. Similar to the offset requirements!
However, this is where we hit a roadblock. We have two decoders to work with. How are we supposed to wire this up with 6 input conditions? I’ll save you the thought experiment – we can’t. Not without extra circuitry. But! Similar to the LoROM SRAM mapping, there’s a way around this problem. The area around the SRAM area in the memory map is blank, meaning it might be ok if we extend our SRAM area a bit. According to the SNES CPU memory map way up above, the area next to bank 0x30, all the way down to 0x00, is part of the “Expansion” region of the memory map. Let’s confine ourselves to this area, instead of extending downwards into the “CPU” and “DMA” region (sounds important!), and extend our SRAM region to some neighboring banks. What if we just ignored BA4? So our only bank requirement was that BA6 was 0, and BA5 was 1? This would extend our SRAM region down to bank 0x20 instead. Perfect!
Now, wiring up the two decoders. Remember, our requirements are A13, A14, and BA5 are 1, while A15 and BA6 are 0. We have six inputs to work with – four “selector” pins, and two enable pins. Enable pins on the decoder are active low, meaning they MUST be 0 in order for the decoder to make any kind of output. Ok, so prime candidate for A15, since we need A15 to be 0. Let’s put the other two A pins on the selectors of this first decoder. When A15 is 0, and A13 and A14 are 1, that makes Y3 on the decoder become 0. Let’s feed that into the second decoder to activate it. Then, we just need BA5 and BA6 on the second selector pins (BA5 on the first input, BA6 on the second input). When BA5 is 1, and BA6 is 0, that makes pin Y1 become 0. Great! Y1, which we can tie to the SRAM /CE pin, will become 0 and activate the SRAM when our criteria is met.
Now, we know how HiROM works. Let’s explore the last mode that’s an extension of HiROM – it’s not very common, but can be helpful, especially for ROM hacks.
ExHiROM Memory Map (Mode 25)
ExHiROM is basically the same as HiROM, except it’s… well, extended! Expanded? Extra? Whatever. The memory map looks much like how it does for HiROM.
Compare that to the HiROM memory map, and it looks nearly identical, except there are now two program ROM areas called out. One is in the banks 0xC0 to 0xFF, and the second is in banks 0x40 to 0x7D. We also have a tiny sliver between 0x30 and 0x3F, in the offset area above 0x8000. This gives us nearly twice as much space to play with, just shy a bit. This is due to the WRAM restricting the banks 0x7E to 0x7F, and the mirror image of the second ROM area being restricted to offsets above 0x8000. Since that adds a bit of complexity, and because I don’t know of any games that fill up the ENTIRE 63.5 Mbits of space, we’ll narrow our view to ignore the third ROM area called out and stick to 63 Mbits total. But theoretically, this small area can be used for game data.
Because the areas of memory between banks 0x80 and 0xBF (and 0x00 and 0x3F) are restricted to the top half of the offset range, Mode 25 treats these regions as mirror images. BA6 is the line responsible for creating the mirror region of the program ROM area – for example, bank 0xFF (or 0b11111111, where BA6 is a “1”) mirrors to bank 0xBF (0b10111111, where BA6 is “0”). So if we ignore the BA6 line, we don’t have to worry about interfering with the reserved areas below offsets 0x8000 in those lower banks. If you remember, BA6 was also ignored in the HiROM format. But, what about BA7? That’s the exact line we can use to switch between the two program ROM areas.
Since ROM chips typically top out at 32 Mbits (as the 27C322 does), we need to add another ROM. We can therefore use the BA7 line and a decoder to switch between two separate ROMs, which is exactly what the MAD-1 chip can do on multi-ROM boards (sometimes with different address lines depending on the board, for boards that have two 16 Mbit Mask ROMs or 8 Mbit Mask ROMs). Along with the existing decoder logic for HiROM creates the ExHiROM memory map – since the SRAM decoder logic doesn’t take into account BA7, we can use the decoder scheme from HiROM without modification.
We want to make sure when BA7 is high, that the first ROM is activated (since it’s the area in the upper banks, from 0xC0 to 0xFF) and when BA7 is low, the second ROM is activated (as it’s in the lower banks, from 0x40 to 0x7D, where the banks above 0x7D is cut off for the SNES WRAM).
This post was a compilation of all the information I gathered and surmised in order to create my own SNES PCBs. Like I said earlier, there are multiple ways to wire a SNES cartridge, all you have to do is make sure it works! That’s the hard part.
The biggest challenge I run into when trying out new designs is avoiding bus conflicts. If you’re going to use a 27C322, or any 16-bit data bus device, and use multiplexers to change that 16-bit data bus to an 8-bit data bus, you’ve got a new set of /OE pins to worry about. If you were to swap the /CART and /RD signals going to the ROM as detailed in the above tutorial, an 8-bit ROM isn’t going to care, because the /CE and /OE pins do the same thing from a high level. In fact, as I briefly mentioned, you’ll get a lower power draw! But a 16-bit ROM? Well, now you gotta figure out where to tie the /OE pins on the multiplexers. You can’t just tie them to GND to have the multiplexers outputting all the time – that’s gonna give you a bus conflict. And you can’t run them off of the /RD signal, because that can drive the output even when ROM data isn’t necessarily desired.
My solution has always been to use /CART to drive the ROM /OE signal, and then reroute the ROM’s /OE signal to the multiplexers, and ground the ROM’s /OE. That’s how my 27C322 adapter boards work. Since /CART is only driven when ROM data is requested, you won’t run into any bus conflicts this way.
This post represents all the work I’ve done over the years in reverse-engineering the SNES cartridge. This is the information I used to create my very own SNES cartridge boards, even including some of my failures and what I learned from them. I’m definitely not the first to make a custom board like this, but I do believe I’ve compiled a pretty robust and thorough explainer that should be able to help you either troubleshoot a problem you’re having, make a board for yourself, or just learn something new about retro electronics! Thank you so much for reading.
I found a bunch of information on the NesDev forums, and you may even run into some of my own questions and contributions on there. Everyone starts somewhere (I mean, come on, it took me over 2 years to get to this point!), so if you have some more in-depth questions or need better explanations, don’t hesitate to contact me or submit a forum post. And if you have any corrections, do not hesitate to let me know!
Thanks for sticking around til the end of the post, your time reading this means a lot to me! As a thank you, if you want to purchase something from my Etsy store and get 10% off, use the code BUCKETMOUSE.
Shh… it’s a secret to everybody…