After I set up the hardware and the Linux environment, I was ready to read and rip cartridges! So where to start? I remember reading about a SNES cartridge reader that would later be known as the Retrode on Hack-a-Day. So I went to read one of the original blog posts to see what resources the original engineer used.
The only resource mentioned was an old blog, titled “SNES Kart.” It is hosted on emularonia.com and was written by DiskDude. While the resource helped tremendously, a lot of it is a collection of observations DiskDude made way back in 1996. Since then, let’s just say there are less uncertainties; a lot of time has passed, and the SNES hardware has been thoroughly reverse engineered by now. A break down of this information was a pain in the ass to find though.
Try Googling “Reading SNES Cartridges.” Most of the results link you to already available commercial solutions, or a forum post where the answer is using a commercial solution.The other 99% of the results are for reading ABOUT the SNES, and nothing technical. Searching for “Ripping” or “Dumping” largely links to ROM sites. The obvious issue is that every commercial SNES title has already been ripped, and not too many people are interested in re-ripping them. I wanted to though, damn it!
To spare time, I will break down my findings. Use the notes below as a supplement to other ROM reading documents on the internet. I’m going to document things I feel will save others time.
SNES Cartridges have:
- 4 Control Pins, and an IRQ Pin. To read a cart, hold the control pins RD, and CS low. WR Should be held high. Also, RESET should be held high, despite the “SNES Kart” document indicating the opposite. The IRQ pin can send a signal from the cart to the console when the CPU should be halted. I’m not sure if it will ever be necessary for cartridge reading, but I broke it out just in case.
- 4 CIC Security Check Pins. In SNES consoles there is a chip known as the “CIC” chip. This chip acts as an anti-counterfeiting “lock,” and will hold the console in reset until it is unlocked by the corresponding “key” in a legitimate cartridge. Cartridges typically don’t care if the CIC lock is missing from the device communicating to it, and some people would disable this chip to thwart the anti-piracy.
Nintendo got smart to this, and games with SA-1 chips actually won’t work if the CIC chip doesn’t communicate with it. The CIC chips have been reverse engineered, and the SuperCIC was designed to emulate the original chip, and will work as a drop-in replacement. I haven’t attempted to emulate the CIC yet, but expect to have to in order to read games such as Super Mario RPG.
- 16 OPTIONAL “Bus B” (Expansion Chip) Pins. If you’ve ever looked at the bottom of a Super FX game, or any other cartridge with an expansion chip, you’ll notice an additional 16 pins on both sides of the center PCB. As far as I can conclude, these are useful for speedy (CPU<>Expansion Chip) communications. While I wouldn’t be surprised if a handful of carts use these pins for transferring ROM data at faster rates, I don’t expect you’ll ever NEED them to dump a cart. Besides, every expansion chipped game I’ve visually inspected seem to only utilize the SNES clock pin. (Likely for sync)
- 16 Address pins, and an 8-pin Data Bus. When you move to an address, the 8-bit piece of data held at that address could be read from the data bus. If you understand bits, bytes, and binary, this shouldn’t be too hard to follow so far.
As 8 bits are in a byte, in actuality there is exactly 1 byte at every address read. Counting by the number of addresses (2^16), you’ll find that you could read up to 65536 bytes, which converts to 64 Kilobytes. SNES games often contain a lot more data, so how do you read more than 64Kilobytes? By switching banks!
- 8 Bank pins, giving a maximum of 256 banks that could be accessed. There are two ways of bank switching you must be aware of. One method for LoROM, and another for HiROM games. HiROM reading is simply the matter of incrementing the address for the full 16-bit length. Then you increment the bank, and read the next 64 Kilobytes. LoROM games only use half of each bank, leaving only 32 Kilobytes per bank.
The way I understood LoROM addressing was to read the first 32 Kilobytes, switch banks,and then read the next lower 32KB, starting again at address 0. Many different resources seemed to allude that having pin A15 high was optional, but this is not the case.
In actuality, you NEED to hold A15 high with LoROMs, so you are in essence reading the UPPER 32KB. Many docs say that the lower 32KB is mirrored with the top 32KB on LoROM games. NOPE. Super Mario World worked reading the lower half, Super Metroid did not, though.
All SNES games hold a standardized header at the same address. The SNES Kart document has this address at two separate offsets, depending on LoROM or HiROM. In practice, these two addresses are the same.
The header for LoROM games is said to be held at offset DEC: 32704. This is
- 0111111111000000 in binary.
The header for HiROM games is said to be held at offset DEC: 65472. This is
- 1111111111000000 in binary.
Notice the only difference is at bit 15.
My code ORs a ‘1’ to bit 15 regardless of the specified address in LoROM mode. So moving to address 32704 in LoROM is actually 65472 when accounting for that fact that A15 will be high.
ROM Type Detection, and Checksums:
So the question you may be asking is how would you know if a game is LoROM or HiROM? Good question! It’s in the header! As I mentioned, since the header is at the same location on both types of ROMs, the nibble containing the ROM type is, as well.
The ROM Type is at address DEC:65493, contained in the lower nibble.
- 0x0 is for LoROM, and
- 0x1 is for HiROM.
If the cartridge connector is dirty, the Data Pins will not be accurate, or in the case where these is no cart, will be held high by the MCP23017’s internal pull-up resistors.
A good way to test if a cartridge is connected, and is working properly is to check it’s checksum bytes.
In SNES carts, at addresses DEC:65500-65501 are two bytes that make up a 16-bit ROM Checksum. Lower byte at 65500, and upper byte at 65501.
There is also an 16-bit Inverse Checksum at addresses DEC:65002-65003, respectively.
XOR’ing the ROM Checksum to the Inverse Checksum should produce 0xffff. If it does not, I assume that the cartridge data is invalid. As this is stored in the header, I could check for this rather quickly.
As an example, Super Mario Kart has a ROM Checksum of 0xeb44, and the Inverse Checksum is 0x14bb. XOR-ing them together equals 0xfff.
The ROM checksum is also the last 16-bits of the calculated checksum from reading the contents of the cartridge. For example, Super Mario Kart is a 512 Kilobyte HiROM game. Since it’s HiROM, you read in 64-Kilobyte “pages.* (512/64 = 8 pages.) When reading a ROM, add each byte of 64-Kilobyte pages together, then add the results of each page together.
For Super Mario Kart, the calculated checksum is 0x286eb44.The 16-bit ROM Checksum in the header is 0xeb44. Notice the header checksum is indeed the last 16-bits of the fully calculated checksum..
To know how many pages will need to be read, in addition to the ROM type, you’d need to know the ROM size. This too is stored in the header, at offset DEC:65494. Unfortunately, it’s size is listed as exponents of 2. The size in Megabits can be 2, 4, 8, 16, or 32 Megabits, but games could be of different sizes.
Super Metroid is a 24 Megabit game, but going by the header, is listed as a 32 Megabit game. In this case I read the full 32-Megabits, and calculated the checksum. It matches the checksum in the header, but it’s possible the file size is 8 Megabits longer than it has to be. It works for now, though, and I doubt emulators will care there is data passed the declared ROM length.
What address to begin reading at:
For both HiROM, and LoROM games I used to start at offset 0. That is Address 0, and Bank 0. I started noticing checksum errors, so I attempted to clarify. It helps to actually have some very specific knowledge to Google search with! I used the search term for “SNES rom” with hexadecimal addresses I had been using and finally found comments in source code.
I found a SNES ROM reading driver for the M.E.S.S (Multi-Emulator Super System) Project, and used the memory maps it uses.
For LoRom Games:
- Read up to 96 possible pages starting at bank 0x00.
For HiROM Games:
- Read the first 64 pages beginning at bank 0xc0.
- IF the ROM is larger than 32-Megabits (VERY rare!,) read the final 32 pages starting at bank 0x40.
and that’s about it. I haven’t attempted to read or write save game data yet, but that too is just a matter of software.
For additional reading, use these resources:
Next, the Reset Switch, along with Bash and Python scripting..