I chose Python to read carts as I’ve used it a lot in the past, and felt it would be useful for quick rewrites. The trade-off is that it’s an interpreted language, and is not nearly as efficient or quick as C++.
When it came down to reading carts, I found that the ripping speed was not as fast as I’d hope due to the Pi’s configured I2C speed. The time needed was dependent on the size of the game, with most titles being between 4 to 16 Megabits. I was finding that an 8-Megabit title would take almost 18 minutes to rip. As you’d only need to rip a cartridge once, a long wait may be tolerable for a one time deal, but the waits became extreme for larger titles.
For example, ripping Donkey Kong Country, a full 32-Megabit title, took a little over 70 minutes. I set out to find a way to increase the speed of the Pi’s I2C bus, and finally found a solution on the official Raspberry Pi forums. Using Modprobe, I was able to force the I2C bus to operate at a faster rate, and well, the results were rather astounding. DKC now ripped in about 34 minutes. That is more than twice as fast!
To prevent re-ripping of already read carts, I check the Game Title which is in the header represented by 21-characters. When reading a cart, I have been using the full 21 characters as it is for the file name. This is less than ideal as many game titles have trailing spaces, and some will have a not so detailed Game Title. For instance, A Legend of Zelda: A Link to the Past has the header name of “THE LEGEND OF ZELDA “. This is not so bad considering there was only one Zelda title for the SNES, and the title is close to 21 characters, but for automating game ripping I may include a way to manually enter a Game Title in the future.
The python script I wrote, “cart_reader.py” sets up the SNES Cart reader by turning on a MOSFET I connected to the cartridge port for hot-swapping games. It then initializes the address, bank, and control lines by changing their states from input to output. I normally keep all the pins as inputs so they are in high impedance; this also helps the cartridge port go into isolation for hot-swapping.
The next step is to scan the checksums, and if valid pulls the game title. The game title text is then written to /tmp/insertedCart. If the game title matches an existing file name by the same Game Title, it quits, else it rips. If no valid game is found, the text “NULL” is written to insertedCart.
The BASH script “cartCheckAndEmulate.sh” runs cart_reader.py and when done uses the text of insertedCart to pass as an argument to the emulator to be called next. If no cartridge was detected, it launches EmulatioStation, a front end for Raspberry Pi Game ROMs, namely the ones previously ripped.
As previously mentioned, I modified SNESDev-RPi for my Reset Button. When the Reset is pressed, it sended the ESC key to the console, then the F4 key. ESC is to quit out of the emulator, if it is running, and to then quit out of EmulationStation, assuming that is running. It then launches cartCheckAndEmulate.sh. As all of this is being invoked by a daemon, I ran into issues.
Originally, I was using RetroArch with PocketSNES libs for SNES emulation, but found that the emulation speed was quite lacking with sound enabled. More importantly for use with the Reset Button, it uses raw keyboard drivers. When it is not launched from a console connected to the keyboard, it refuses to accept keyboard input. As both the controllers, and the Reset button sends virtual keyboard presses to the emulator, this became a serious problem.
For decent emulation speed with sound enabled, I went with an ancient build of SNES9X. It’s emulation accuracy is not nearly as accurate as recent emulators, but was deisgned for much older harder, and as such works for my purposes. More importantly, when evoked by a daemon, still allows key presses. I modified my cartCheckAndEmulate script, and when called without an argument, uses RetroArch. If called with any argument, uses SNES9x. With a quick re-code, the Reset Button now works as I intended.
My modified SNESDev-Rpi fork may be found here.
To further aid in emulation speed,recently I decided to finally mess with the Raspberry Pi’s “Core” overclock, …again. You see, back in September, 2012, the Raspberry Pi Foundation announced an officially sanctioned way to “safely” overclock the Pi using rasp-config. I utilized this overclock for when Eben and Liz Upton of the Raspberry Pi Foundation came to visit our hackerspace. I had a music controlled Raspberry Pi stop light display ready to go, and when the event was ready to start, my image corrupted. I found out later from Eben that Core overclocks have been known to corrupt SD cards.
The new official Core overclock doubles the Core speed from 250MHz to 500MHz. The thinking of the community is that maintaining the same ratio of the 250MHz clock, in this case twice the clock, helps.
It helped not only in emulation, but in cart ripping. Look at my Results with Donkey Kong Country below!
It took 4213.22911692seconds to read cart – Default Core & I2C speed
It took 2036.41756105seconds to read cart – Default Core; Increased I2C Baud
It took 1172.85034895seconds to read cart – 500MHz Core; Increased I2C Baud
Next up, some final thoughts..