Reading Game Boy Carts With I2C

rasgame

After seeing a Game Boy emulator for the first time, [Thijs] was amazed. A small box with just a handful of electronics that turns a Game Boy cartridge into a file able to be run on an emulator is simply magical. [Thijs] has learned a lot about GB and GBC cartridges in the mean time, but still thinks the only way to really learn something is to roll up your sleeves and get your hands dirty. Thus was born [Thijs]’ Game Boy cartridge dumper, powered by a pair of I2C port expanders and a Raspberry Pi.

Inspired by a build to dump ROMs off Super Nintendo games with the help of a Raspberry Pi, [Thijs] grabbed all the hardware necessary to create his own GB cart dumper. A DS Lite cartridge adapter provided the physical connection and a pair of MCP23017 I/O expanders – one soldered to a Slice of PI/O board – provided the electrical connections.

In the end, [Thijs] managed to dump the ROMs off the Japanese editions of Pokemon Yellow and Gold in about 13 minutes. This is a much slower transfer rate of 26 minutes per SNES cart in the post that gave [Thijs] the inspiration for this build. Still, [Thijs] will probably be the first to say he’s learned a lot from this build, especially after some problems with dumping the right banks from the cartridge.

18 thoughts on “Reading Game Boy Carts With I2C

  1. I’d just use an AVR to interface with the card and then connect to the pi over high speed serial. All of the IO expanders on the I2C bus controlled by python scripts are making this so slow. Now he’s waiting for an eternal millisecond after each write :\

    1. Why bother connecting to the pi at all if you already have a microcontroller handling the interfacing? Make it appear as a USB flash drive with a lone *.bin file inside for you to copy straight off the cartridge, or possibly play directly in an emulator on pc if the speeds will allow (yes, even a pi if you must.)

      Of course this idea requires you to figure out the organization of the memory blocks etc with the uC, which shouldn’t be too hard.

      Also try ditching the expander entirely, just go with a chip with lots of ports for blazing parallel speeds.

    2. bty, if you are talking “high speed” UART, keep in mind that 115200 baud is only 14.4 kilobytes per second. Much faster than 13 minutes per MB, but depending on the size of the cart, nowhere near instantaneous. I’m sure you could get i2c, and especially SPI on the Pi to surpass that.

      Nova. There still would be utility in using a microcontroller between the cart and the pi, as you could transfer the adapter to a full PC, or choose to use it with a Pi, and have a compact, portable Game Boy Playing machine.

      As for having Game Boy games mount as USB Mass Storage devices, the Retrode already does this. As much as I am about reinventing the wheel, that is one wheel I’d just rather pay for, than re-invent. A very low cost Serial/i2c/SPI reader I find to be cool, though. Not trying to poo-poo your idea, it’s just not a trivial task! :D

      1. I might have phrased what I meant a bit odd, but yes that’s exactly what I was getting at. This sort of project is much better suited to be handled by a low-level uC than a full-blown RTOS with delays scattered all around the code.

        When you take I2C down to the hardware level it goes amazingly quick. I’ve taken to programming MSP430’s and recently found out that my I2C routine runs too fast for a v3 buspirate to properly buffer and examine. (It only catches about 1 of every 5 bytes) despite all the devices ‘ACK’ing the commands.

      2. I2C can not be made much faster.
        By spec, it is 400kHz top (3.4MHz on clock is used only for some devices, and there are restrictions). About 20 bits per transfer of 1 byte. About 20kTransfers/s on top speed. So 20kBytes is peak for I2C, even without factoring in the delays between transfers.

  2. Holy unfathomable coincidence, Batman! I am the maker of the SNES Raspberry Pi project mentioned here, and before checking HaD tonight, I had been watching hours of Game Boy clips. My friend bought a Gamecube for $5 earlier today, and I’ve been trying to hunt down a Game Boy Player for him. I had a touch of nostalgia, so have been looking up all things Game Boy. Seems it has come full circle. :D

    I had actually thought about reading a Game Boy cart with a Pi in the same fashion that I did with the SNES, but haven’t had the time. I’m honored I inspired Thijs to take over the reins. ^_^

    Thijs, if I could suggest something. The Pi could easily fit in a Game Boy case, and it could be powered by 4AA batteries. Portable linux powered Game Boy, maybe? I don’t have the time, but you could totally own this.

    As far as the memory read corruption issues, you’d be surprised how much cross-talk you may be introducing with the breadboard and loose wire. If all else fails, check that.

    As far as dumping a 4MB title in 34 minutes, I was able to get it down to less than 20 minutes by overclocking the core to 500MHz. My Pi seems to run stable with a 500MHz core, and a 1GHz clock, but I find stability issues when overclocking the RAM, so I manually keep it at 400MHz.

    Besides, it has been found that overclocking the core yields a much better performance gain than overclocking the memory. You do run the risk of corrupting your SD card by overclocking the core, as I go into in my blog, but I haven’t run into any problems with my Sandisk Class 10 card. It also helps that the core overclock ratio is a whole ratio to the original. In fact, I am guessing many of your issues will go away by by overclocking the core. The only time I ran into any SNES read corruption issues was when my code was going too fast for the i2c bus. The SNESMCP23017 communications never seemed to be the issue. (Don’t cry to me if you corrupt your SD card though :-) )

    Congrats on making HaD! Feel free to contact me back for help. I have a shit ton of those MCP23017 expanders left, and a few Game Boy Cartridge connectors lying around. It would be cool to pick up where you left off!

    1. Nice jobs on the cart dumpers. I didn’t look too far into these designs, but might I recommend tying maybe 4 of the lower cartridge address lines directly to mcu pins instead of the i/o expander. By the time you tell the i/o expander to change the read address several times in a row, direct pin access could read tons more without excess shifting. So read 16 bytes direct, increment the i/o expander counter, read 16 more, all into memory. Keep an eye on timings, snes carts run at like 60ns read times, the internet has plenty of docs. Ignore this if this is what you guys are doing, and keep up the good work!

  3. Pokemon Gold and Yellow together are 3MB. Dumping both in 13 minutes implies an aggregate transfer speed of 4KB/s… I guess that’s consistent with using 100kHz mode I²C and bus expanders …

    Each byte in a GB cart can be read (or written to) in at most 375ns, and probably faster. A good next step would be using a microcontroller; you should be able to maintain >90kB/s using a USB-serial bridge without trying to hard.

Leave a Reply

Please be kind and respectful to help make the comments section excellent. (Comment Policy)

This site uses Akismet to reduce spam. Learn how your comment data is processed.