It’s been a while since I did this, but I got some people asking me lately about how exactly I did it and I thought it could be nice to write a post answering that question. Actually, it would be a nice thing for me to have anyway at least as “documentation”, so here it is.
But first of all, the idea: my personal and very particular goal was to have a proper SNES emulator plugged to my TV, based on the Raspberry Pi (simply because I had a spare one) that I could control entirely with a gamepad (no external keyboards, no ssh connection from a laptop, nothing).
Yes, I know there are other emulators I could aim for and even Raspberry specific distros designed for a similar purpose but, honestly, I don’t really care about MAME, NeoGeo, PSX emulators or the like. I simply wanted a SNES emulator, period. And on top of that I was quite keen on playing a bit with the Raspberry, so I took this route, for good or bad.
Anyway, after doing some investigation I realized all the main pieces were already out there for me to build such a thing, all that was needed was to put them all together, so I went ahead and did it. And these are the HW & SW ingredients involved in this recipe:
- A Raspberry Pi Model B (or better) with Raspbian installed
- A Bluetooth 2.0 dongle
- A PS3 DualShock 3 gamepad
- QtSixA: a joystick manager for PS3’s SixAxis gamepads
- PiSNES: A SNES emulator for the Raspberry Pi, based on SNES9X 1.39
Once I got all these things around, this is how I assembled the whole thing:
1. Got the gamepad paired and recognized as a joystick under /dev/input/js0 using the QtSixA project. I followed the instructions here, which explain fairly well how to use sixpair to pair the gamepad and how to get the sixad daemon running at boot time, which was an important requirement for this whole thing to work as I wanted it to.
2. I downloaded the source code of PiSNES, then patched it slightly so that it would recognize the PS3 DualShock gamepad, allow me define the four directions of the joystick through the configuration file, among other things.
3. I had no idea how to get the PS3 gamepad paired automatically when booting the Raspberry Pi, so I wrote a stupid small script that would basically wait for the gamepad to be detected under /dev/input/js0, and then launch the snes9x.gui GUI to choose a game from the list of ROMS available. I placed it under /usr/local/bin/snes-run-gui, and looks like this:
#!/bin/bash BASEDIR=/opt/pisnes # Wait for the PS3 Game pad to be available while [ ! -e /dev/input/js0 ]; do sleep 2; done # The DISPLAY=:0 bit is important for the GUI to work DISPLAY=:0 $BASEDIR/snes9x.gui
4. Because I wanted that script to be launched on boot, I simply added a line to /etc/xdg/lxsession/LXDE/autostart, so that it looked like this:
@lxpanel --profile LXDE @pcmanfm --desktop --profile LXDE @xscreensaver -no-splash @/etc/sudoers.d/vsrv.sh @/usr/local/bin/snes-run-gui
By doing the steps mentioned above, I got the following “User Experience”:
- Turn on the RPi by simply plugging it in
- Wait for Raspbian to boot and for the desktop to be visible
- At this point, both the sixad daemon and the snes-run-gui script should be running, so press the PS button in the gamepad to connect the gamepad
- After a few seconds, the lights in the gamepad should stop blinking and the /dev/input/js0 device file should be available, so snes9x.gui is launched
- Select the game you want to play and press with the ‘X’ button to run it
- While in the game, press the PS button to get back to the game selection UI
- From the game selection UI, press START+SELECT to shutdown the RPi
Unfortunately, those steps above were enough to get the gamepad paired and working with PiSNES, but my TV was a bit tricky and I needed to do a few adjustments more in the booting configuration of the Raspberry Pi, which took me a while to find out too.
So, here is the contents of my /boot/config.txt file in case it helps somebody else out there, or simply as reference (more info about the contents of this file in RPiConfig):
# NOOBS Auto-generated Settings: hdmi_force_hotplug=1 config_hdmi_boost=4 overscan_left=24 overscan_right=24 overscan_top=16 overscan_bottom=16 disable_overscan=0 core_freq=250 sdram_freq=500 over_voltage=2 # Set sdtv mode to PAL (as used in Europe) sdtv_mode=2 # Force sound to be sent over the HDMI cable hdmi_drive=2 # Set monitor mode to DMT hdmi_group=2 # Overclock the CPU a bit (700 MHz is the default) arm_freq=900 # Set monitor resolution to 1280x720p @ 60Hz XGA hdmi_mode=85
As you can imagine, some of those configuration options are specific to the TV I have it connected to (e.g. hdmi_mode), so YMMV. In my case I actually had to try different HDMI modes before settling on one that would simply work, so if you are ever in the same situation, you might want to apt-get install libraspberrypi-bin and use the following commands as well:
$ tvservice -m DMT # List all DMT supported modes $ tvservice -d edid.dat # Dump detailed info about your screen $ edidparser edid.dat | grep mode # List all possible modes
In my case, I settled on hdmi_mode=85 simply because that’s the one that work better for me, which stands for the 1280x720p@60Hz DMT mode, according to edidparser:
HDMI:EDID DMT mode (85) 1280x720p @ 60 Hz with pixel clock 74 MHz has a score of 80296
And that’s all I think. Of course there’s a chance I forgot to mention something because I did this in my random slots of spare time I had back in July, but that should be pretty much it.
Now, simply because this post has been too much text already, here you have a video showing off how this actually works (and let alone how good/bad I am playing!):
I have to say I had great fun doing this and, even if it’s a quite hackish solution, I’m pretty happy with it because it’s been so much fun to play those games again, and also because it’s been working like a charm ever since I set it up, more than half a year ago.
And even better… turns out I got it working just in time for “Father’s Day”, which made me win the “best dad in the world” award, unanimously granted by my two sons, who also enjoy playing those good old games with me now (and beating me on some of them!).
Actually, that has been certainly the most rewarding thing of all this, no doubt about it.