A while ago, I got interested in making SNES repro boards. This was part due to the cost of genuine copies of some titles, and half in the interest of playing some of the the SMW hacks that have been released online (or maybe making my own!) I have never really built any hardware that interfaces with a CPU before, so there was a lot of learning to be done. This will be a multi-part post since there is so much material to cover.
A really fantastic resource for all of this has been SNEScentral. There are also plenty of other resources scattered around in no particular area. I found poorstudenthobbyist extremely helpful in getting into the idea of what fundamentals need to be in place for the game to run, and the forum over at NESdev (or for me, SNESdev) very useful in answering some more niche questions on how the SNES works. I would also like to thank Martin after I found his boards on Tindie and talked with him during the early phase of this project.
What’s in a game cart, anyway?
So, where do you start with a project like this? It’s probably a good idea to abstract out the required elements, and to use a reference. The goal is to run a program on the SNES that is hosted externally. This means that we will need to store the program externally. If it’s a game that saves, the saves are all stored externally as well, so we’ll need some sort of storage on the board.
If you open up a SNES game, you’ll find a PCB with a ton of different stuff mounted on it. However, it’s easiest to identify the ROM and the RAM, since those are (usually) the largest chips (we’ll get into games that use special chips later, since some later games have quite a bit of advanced circuitry). In the above picture is the PCB for Super Mario World. The ROM chip (Read Only Memory) is the large chip in the bottom right. This is a mask ROM, meaning that the contents are written during fabrication of the chip, and can’t be altered or programmed after. Since we want to be able to program whatever we want on the memory, we’ll have to find a type of memory that is programmable, at least once to put our game on it. Let’s mark that as a design point we need to meet.
Above the ROM chip is the RAM chip for the cart. This is where temporary or changing contents are stored, such as save states and other peripheral data. Note that these carts were all made before the advent of flash memory, so the contents are volatile. This means that if the chip is powered off, all the contents will be wiped- hence the need for a small battery to keep the RAM powered even while the cart is unplugged. Depending on the game, more RAM might be necessary- explaining the two rows of sockets here, you can see the second row of blank holes above the RAM chip- this is because each PCB wasn’t designed for each game, there are sort of templates that game designers could pick for their game based on their size, memory, and graphics needs. (As a side note, the development manual for the SNES can be easily found online. They have a LOT of pertinent information as well as mapping/other information for all the PCB types. )
So now that we know where the game reads and writes it’s data, what are the other chips on there? Those are ICs that help interface the ROM and RAM with the rest of the SNES. One of them is a region lock chip that acts as a verification for the hardware, and the other is a mapping chip that helps the cartridge decide whether the SNES CPU is looking for data that’s stored in the ROM or the RAM. The other miscellaneous components on there are mainly for power conditioning and maintaining the RAM during power-off. We have a pretty good idea of what’s necessary for the cartridge to work. Are we ready to start designing yet? First, we should further define the specifications that we need for the ROM and RAM so we can pick components for the board. And before that, we should figure out:
How does the SNES talk with the cart?
Let’s take a step back: how does a processor read information in from memory? If we have a program that’s stored externally, we need to have a way to reliably load it in and communicate it out. This is where the concept of address and data bus lines come in. For an 16 bit address bus, you would write out the address in memory you’re looking to read from on lines A0 through A15, with each line being a bit on the address. For example, if you were looking for 0x3F00 , with a 16 bit address bus, you (the CPU) would write out 0011 1110 0000 0000 onto the address bus, with each line from A0 to A15 taking either low (0) or high (1). Make sense? The important thing to note here is that the processor bus lines are working in parallel, not series. So, for each extra bit of resolution you want to add, you need another line on the bus. Suppose you wrote that address onto the bus- because you’re expecting to read the data that’s stored in that location on the memory. You would read the information stored in that location back across the data bus. If you have an 8 bit data bus, suppose you receive back some data like 0xFF (1111 1111). This seems pretty straightforward: each address has data stored in it, so if you point to a location using the address bus, you’ll get that data out on the data bus. Or, to write data, you can do the opposite: write the location you want to store something, and then output your information on the data bus. So, what does the SNES have to work with in terms of address and data buses?
If we look up a pinout for the SNES cartridge connector, we’ll find A0-A23 as the address bus (or potentially A0-A15 and BA0-BA7 depending on where you look) and D0-D7 on the data bus. So, we’ve got a 24-bit address bus, and an 8 bit data bus. The address bus might be a little confusing, until we reference the memory map used in the SNES. The 24 bit address bus is split into two sections, the first 16 bits (0x0000 to 0xFFFF) being used for addressing, and the upper 8 bits (0x00 to 0xFF) being used for bank selection. Splitting the banks like this gives us a two-dimensional map of where in the memory we’re looking, and the development manual has all of the mapping details we need for reverse-engineering the cart. Sometimes you will see the memory addressed like this: 0xFF:FFFFF or as one large word: just remember that the upper two hex bytes are for the bank, and the lower four are for the address. This is our golden guide to understanding where the CPU is expecting to find information.
A note on the ROM storing the game: while we can’t write to one of the mask ROMs used in commercial games, the R in ROM does stand for read- so we can just scroll through all of the addresses and dump out the data at each address, effectively getting a copy of the code that was written in during production. There are a number of tools you can use to do this, but the cheapest is one of these TL866 programmers from eBay. They can read and write memory to ROM chips, as well as microprocessors like for Arduino, and a bunch of other things. A ROM dump has been done for basically every game released, and it easily located online, or you can do it yourself. Without this ROM, we don’t have a game to run! The file we get from here is what we’ll write onto the ROM when it comes time to assemble the PCB and get it running.
What are the size limits of chips the SNES can talk to?
Depending on the game you’d like to make, there are a few different memory mapping schemes. There are a few different sites that you can find information about SNES games like the memory mapping type, ROM size, and any special hardware, like the SNES ROM Header Database. Where did this database get the information from? Well, it’s stored in the header! On this wiki we can find the location and type of information that is stored in the header. Note that the memory mapping mode type of the game is at location 0x15. There is a table that decodes the stored byte into the memory mapping configuration, telling the CPU what sort of mapping to expect from the ROM and RAM. This memory configuration is incredibly important, as it tells you where all the resources the CPU will need are located as well as the hard limits for the maximum memory that can be accessed with that mapping. Suppose we’re just interested in making a game that uses the Mode 21 memory mapping. From just that decision, we know the the maximum (usable) size of the ROM is 32Mbit and the maximum (usable) size of the RAM on the cart is 64Kbit. How do we know that? Besides the fact that it’s listed in the diagram, I’ll try and run you through it how I understand it. Once we derive it, it will be easier to understand how the SNES is talking with the game cart.
As a note: this is an area that held me up for a while. I don’t have any background in electronics, and, I also don’t have any background in computer science. So, I will try and walk you through this with the same reasoning that convinced me of the solution. We have 16 bits of resolution on the address bus (A0-A15, 2^16 values). This means that we can access up to 65535 (64K) locations in memory, and we’ll steer where we want to look using those addresses. However, that’s only one axis of the memory. Since we want to be able to steer around the map in two axes, we can use the 8 bit bank addresses (256) to also move around. So, in the map for mode 21, we can measure the size of the areas we’re interested in. Let’s start with the Program ROM on the left (the 1′ zones are where the ROM will get mirrored during operation, we only need to worry about the main ROM area for now). The ROM is from addresses 0x0000 to 0xFFFF, which is 64Kbits long. This region is also valid for banks 0xC0 to 0xFF, which is 64 bits wide. Since each address holds 8 bits (the resolution of our data bus), that gives us a total of 32Mbit ( 64K * 64 *8 ) worth of data in the space allocated. This aligns with the first footnote stating that the maximum size is 32Mbit.
For the RAM, we can do the same thing, but there is a trick we can use to minimize the size. For mode 21 mapping, the valid addresses are from 0x6000 to 0x8000, giving a length of 0x2000 (8Kbit). Each address is going to hold 8 bits, making our storage requirement at least 64Kbit. Like the ROM, we could then multiply again by the bank width to find the total maximum size, but let’s take a look at what sort of RAM chips have been used in actual SNES carts first.
Remember how earlier I mentioned that there is some bits of information stored in the header of the ROM that are useful, like the memory mapping mode type? Well, the RAM that the game uses on the cartridge is also stored in the header at location 0xFFD8 (for mode 21). Using the SNES ROM Header database, poorstudenthobbyist created a script that generated a table of games with their relevant ROM size, RAM size, game speed, and some other bits from the site. If you sort the PSH document by HiROM format games and look at the SRAM requirements, you’ll find that it never exceeds 64Kbit. If you take a look at the actual RAM chips used on the SNES PCBs, this makes more sense. If you look at the boards for games that use the HiROM, you’ll notice that on an 8K (64Kbit) SRAM chip, there are only 13 address lines. This makes sense because 2^13 is 8192bytes (since each address is 8 bits wide), which converted to bits gives us the 64Kbit. However, that means that we won’t be able to connect up the rest of the address lines to the RAM. What are we going to do with them?
This is where an understanding of the relationship between the memory map and the hardware helps a lot. The memory mapping tells us where the CPU will be looking for any particular information. The mapping helps the processor guide the address bus to the right location. However, it can’t know what hardware is linked outside of the CPU, since we’ll be plugging in different programs and games all the time. So, since the bank region for SRAM access is between 0x30 and 0x3F, we can use that information to enable the chip when we see that the CPU is looking in that location. The trick is, the data that the SNES gets back doesn’t need to be different whether it’s looking at the 0x30, 0x3D, or 0x3F banks, for example. It’s just expecting the SRAM data to be in that region. So, we will use the entire bank region to determine whether or not to enable the SRAM chip, but the CPU will receive the same data for the same address no matter where it is in the bank. This is why we don’t need to account for the bank width like we did with the ROM (which does have bank lines attached to the chip, and helps with searching for correct data). So, our final answer for the maximum memory that can be used by a HiROM game is 8Kbyte (64Kbit).
What hardware are we actually going to use?
So, we have our ROM size limit (32Mbit) and our RAM size limit (8Kbit) for making a mode 21 game. These are different if you’re using mode 20 (LoROM), or the extended mapping (ExHiROM and ExLoROM). I put the diagrams in here from the other memory mapping models, see if you can figure out the maximum size limitations for the other game types. An important note here is that the size of the SRAM actually does matter for some games, so it’s a good idea to match the memory with the game you’re making. This can be done easily by just getting the largest required size (8K for HiROM or 32K for LoROM) and disabling a few lines with jumpers, but we’ll cover that later when we’re doing the schematic and PCB layouts.
So, how are we going to store the program on the ROM? There are a few different options. We could do something like a USB, which is based on flash memory. However, recall that the address and data busses work on parallel protocols, so we’d need to find a parallel flash memory with 32Kbit memory. If you do a quick search, you find that these are generally pretty expensive, and are only available in TSOP packages, which are more difficult to solder than DIP, at least at first. There does appear to be one affordable repro community favorite, and that’s the 29F033, which can be had for about a dollar per piece. Not too bad! Another option is the memory standard that was around before flash memory, the EPROM and it’s successor, the EEPROM. EPROM memory is Erasable Programmable ROM, but the erasing method is pretty unique. It uses high energy light (UV) to reset the state of the memory cells in the chip. Because it uses light to clear the state, EPROMS have a clear epoxy or glass window on the top. After writing, you have to cover the window or else stray radiation from the sun, etc, can damage the data stored inside. These are fairly cheap since they are old and not really in commercial use anymore, but there are a lot floating around. A cheap (as low as 50c per chip!), popular one for use in repro carts is the 27C322, but there’s an issue with this one: it has a 16 bit data bus. We’ll figure out a way to get around this later. We could also use other chips from the same family that do have an 8 bit data bus, like the 27c801, but this chip is only 8Mbit, meaning we’d need 4 of them. The last type is the EEPROM, as in Electronically Erasable Programmable ROM. This is like the EPROM, but you can wipe it using a programmer instead of using a UV light. These are a little more uncommon and a lot more expensive than most EPROMs. I’m going to pick the 27C322 for my board, but feel free to choose whichever suits you best for your design needs.
Now that we’ve got the ROM figured out, let’s take a look at the RAM. We want to use something called Static RAM, or SRAM (I have already probably used this terminology without defining it, but now you know!). The counterpart to SRAM is Dynamic RAM. The Dynamic in DRAM means that you have to strobe the RAM buses when reading or writing using some sort of external timing circuit. Maybe you could use the clock signals provided by the SNES, but I don’t know a whole lot about how to interface the two. SRAM is much easier to interface with hobbyist projects since no timing is necessary- you can just hook up the data and address lines and then start using the memory. So, we’re interested in SRAM. Like the ROM, we could look at some more contemporary chips, but wow they are expensive. If you search for nonvolatile (meaning no battery-backup needed) SRAM chips with a storage capability of 64kbit with an 8 bit bus, you find some really pricy chips.
So, like the the ROM, let’s look to some older standards to find cheaper parts. Half of the fun with projects like these is working through the constraint of personal funding- how much do you really want to invest into something that’s just for personal use and doesn’t arguably have too much value? If we just search for 64kbit x 8 SRAM, an easy find is the 6264 chip. This is sort of an ubiquitous chip for cheap SRAM, about $2 a pop. Let’s use these in our design. However, do note that the fact that we’re now using volatile memory, meaning we’ll have to invent a way to keep the SRAM powered on even when the system is turned off and the cart is removed. Without this, there is no way to retain the contents between uses.
So, we’ve got our core SNES game hardware down. We know where we’re going to keep the memory, and we know where we’re going to put the save data and temp files from the game. Now, we’re just got to figure out how to interface it with the rest of the SNES so that it’s usable as a cartridge. I’ll cover that in my next blog post. As always, I hope you learned something, and thanks for reading. I know this was a lot of information, but I have had an incredible time learning about computer science, hardware, and how to make it all work together and I hope that’s conveyed in this post. If you have any questions about material in this post, please let me know. I’ll have another up soon about how we’re going to interface the two, create the schematic and PCB layout, and finally on how to program the boards so we can use them.