Controllers are surprisingly super easy to work with and a good gateway to some basic electronics hacking.
I've actually gone the opposite direction from this post. I have a Neo Geo arcade board (JAMMA) and it has plugs for Neo Geo controllers (as in the controllers for the console version of the Neo Geo). I wanted to use the Neo Geo without plugging it into an arcade cabinet, so I got a "Supergun" board to play it on an RGB monitor. However, I didn't have a controller for it.
I noticed that there was an emulator-based "Neo Geo X" system out in the wild and you could purchase a controller accessory on its own, so I got one, not realizing it was purely a USB controller in the shape of the original Neo Geo ones, but no problem. I bought a Neo Geo controller cable and just desoldered the button to USB connections inside the controller and connected them directly to the Neo Geo controller cable. Worked like a charm!
As a poor college student, I home-built a dance pad for Dance Dance Revolution, out of wood and foil and by soldering the connections into a controller. Worked perfectly!
Yes. I got my start, back in the day, following along a magazine article on modifying an Atari 2600 joystick for use with the Tandy Color computer. Worked fairly well too, though I ended up modifying my Galaxian arcade game clone to work with it.
Looking at the described protocol it seems the SNES controller uses a simple 16-bit parallel-in-serial-out shift register - and a quick Google confirmed that.
This means the timing is almost certainly quite loose, and there's a pretty decent chance you might even be able to poll it as the 1kHz "needed" for "serious" gaming. And it'd be pretty trivial to offload the readout to the MCU's SPI peripheral.
It's extremely loose! Using a custom PCB to connect the controller over RJ45 to a custom Pi hat I wrote some code to simply display the button presses on screen, to test the functionality of the controller (we are modifying hundreds). I had to play around a lot with the timings to match up the response of the program with the speed of my finger pushing a button, else the program would return "you pushed B" a dozen times on a single push.
I do wonder how much original SNES devs had to consider similar scenarios.
The physical switches may actually bounce, so you might need some debounce logic, if it wasn't the shift register glitching out. It's pretty common for buttons to need this, often seen in keyboard firmware as well for similar reasons, the physical mechanism actually will oscillate a bit between states.
The way the NES and SNES work is that once per frame you read from the memory address mapped to the shift register to get all the bits out, one at a time. For certain inputs you only care if it's pressed now. Others you compare to previous state to see if it changed.
Bounce could, theoretically, cause an input to be read as a non-input if it just bounced at exactly the wrong time, but it won't cause multiple inputs, as it's only polled every 1/60th of a second.
Yes, it sounds like SNES implements debounce by just scanning slowly, but if you want to feed USB reports at maximum (or above maximum) specification, you will want to check the state more frequently, and you'll need an alternate mitigation for switch bounce.
Were you checking to see if the button state changed between reads? Or were you reading a 1 as "down" regardless of whether the previous read was "up"?
I converted a DOS-era joystick like this, and the shift registers inside were stable at higher speeds, I don't remember needing to care about the timing much. I may have just run the clock in a for-loop during the polling loop.
The Daemonbite project (https://github.com/MickGyver/DaemonBite-Retro-Controllers-US...) does essentially the same thing, but works like a normal USB controller from the perspective of the host. I've used one with a MiSTer FPGA setup and it's almost indistinguishable from a native SNES controller in terms of response. For my build, I cut a cheap controller extension cord in half, avoiding the need to actually modify the controller itself.
One thing I'm wondering is how the SNES implemented its Multitap support[1] with such a simple "wire protocol". Could it be that the two missing wires and/or 4 unused slots in the polling cycle are used for some kind of adressing scheme when a multitap is plugged in?
RGMX has a video series on a lot of the low-level SNES functions. If you've ever wanted to know how Mode-7 works, it's great.
The video below goes over the controllers, Super Scope, mouse, etc. A brief discussion of the multi-tap starts around 16:00. You are correct that it leverages the spare pins.
The schematics for the multitap are out there in the SNES developer manual [1]. I actually made one on a breadboard for fun [2] and eventually turned it into a PCB. It's a pretty simple circuit with an analog mux and some tri-state buffers.
The NES also had “multitaps”. One model was wired (the “Four Score”), the other was wireless (battery powered; the “Satellite”) with an IR receiver unit that plugged into both controller ports.
The IR wireless one was, in my experience (it was the only one I had) far less janky and failure-prone than one might suppose. Actually worked quite well.
I think the project is cool, but since a usb snes controller is, what 5$ on ebay (or more to have quality one), I find it too bad that you damage a working, vintage real snes controller that there will be less and less of.
I've tried building an arcade stick in the past by having the Arduino emulate a keyboard and doing standard Arduino lib digitalRead of the buttons and sending keypresses (for MAME) over USB. It worked, but the lag was terrible. I wonder if this fares any better.
In any case, if you can handle the wait, you can get a knockoff SNES USB pad from China for a few bucks. The plastic will feel way off, but you can probably swap over the shell from your original pad with little effort. And you'll get fresh rubber button pads, rather than 30 year old spongy ones, as a bonus. :)
Before the existence of Blue Retro or any commerically available adapter, I wanted to use Playstation 4 Dual Shock wireless controllers with my Sega Saturn as an analog controller. I used the Arduino USB Shield Adapter since that supported wireless Dual Shock controller and all I needed to handle was the Saturn side of things with emulating a controller protocol so the Saturn things it had a 3D controller plugged into it.
This was my introduction to Arduino programming, bitmasks and direct port manipulation. I have changed the recently to not use direct port manipulation since it really isn't need for the Saturn and I wanted to make the code more portable.
I have since made a wireless for the official 3D controllers for the Saturn with no noticeable latency. Something it seems is still taking others a while to figure out it. I am not doing anything fancy so I don't know how they can't figure that out yet. They are using Blue Retro though where as I am just using an nRF24L01. So maybe the Blue Retro is adding some unnecessary over head. This i have not released the source for though.
my very first electronics projects were classic controller to USB conversions. I remember struggling with PIC after just wrapping my head around BASIC Stamps, and trying to follow raphnet tutorials https://www.raphnet.net/electronique/multiuse_tiny1/index_en...
going to show this article when people ask 'how do i get started with a fun electronics project' :)
This brings back memories. The first (and only) hardware project I've ever done is building a 4-controller multitap that connected via parallel port. It ended up working really well--lots of fun playing games on snes9x with friends.
This reminds me, years back I picked up an NTT Data Super Famicom Controller [0] with the idea of adapting it to USB. An off-the shelf USB converter only handled the standard SNES/SFC buttons and completely ignored the number pad. At the time few resources even mentioned the existence of this thing, so I put it on the shelf and promptly forgot about it for other projects.
I did something similar by cutting down the PCB of a standard Microsoft game controller and wiring it into an old Wico Command Control joystick (the only thing I kept when I gave away all my C64 stuff - before it became collectible).
Totally authentic for playing old C64 games in an emulator. But these days, I'd leave the joystick alone and just use an Arduino to do a DB9 to USB translator.
I'm fairly novice with Arduino and interfacing with buttons/pots but I thought delays / loop interrupts were discouraged versus a reset-able counter variable?
They are if you have anything else that needs to be done at the same time. I would say they're fine if you have nothing else to do while waiting, or you need microsecond delays to generate a signal like in this case.
I prefer a nondestructive approach. I set up an ATTINY85 clone to serve as a DIY USB adapter. Just solder a controller extension cable to the microcontroller to donate the right port, and you have everything you need. You have enough GPIO pins and the requisite 5v logic to make it a great fit. Mine was made for NES controllers, but it uses the same shift logic as the SNES controller, just with fewer buttons.
I recently made an xbox 360 chatpad work with windows using an esp32. It's kind of a grail moment when you search about it. A bit late to the party as the modern chatpad + controller do work, but 360 controllers and chatpads are very inexpensive. It's chatpad > esp32 > bluetooth > anything, stuck neatly on the back you hardly notice it's there.
Don't forget that these controllers operate at 5V logic and the ESP32 at 3.3V. Supposedly the ESP32 can tolerate 5V inputs [0], but it's probably best to put a level shifter between the two.
Yeah I too wondered why the author would target 60Hz at all. The fact that the SNES controller is polled at 60Hz is simply a consequence of the game reading the input at that rate. As mentioned in the other comment in this setup the polling of the controller is not in sync with the game reading the input at all. Thus even if you target a polling rate of 60Hz perfectly you'd actually have worse input latency than the original hardware.
It would be much better to target 120Hz or higher to reduce input latency and bring it as close to the original hardware as possible by ensuring there is always an up-to-date input state ready for the game to read.
I had a feeling the polling rate was probably to do with the frame rate of the SNES rather than some requirement of the controller. I'll try out a higher polling rate and see what happens.
Yeah I wouldn't be worried about the hardware at all. The only chips on there are two 8-bit shift registers and according to the datasheet at 5V they can run up to 3MHz. You're much more likely to run into the limits of the USB protocol than the SNES controller hardware.
If for the sake of argument we are plugging this into an SNES emulator running at 60Hz, then the stack between the USB gamepad and the emulator already has to handle that the gamepad is not rigidly synced to the emulated SNES and will presumably take every input from the gamepad and use it as the emulated input to the SNES next time it asks, unless a new one comes in first.
At slightly faster than 60Hz, the net effect will be that the delay between input and having an effect on the SNES will wander about 1/60th of a second over time, as the sync varies, and every once in a while a particular input will be overwritten before it makes it into the emulator. It may be very difficult to perceive this, though, due to other delays already built into such a set up. On a real SNES, it would be right on the edge of perception anyhow.
Being very close to the poll rate but not quite there is probably near the theoretically worst case. It would probably be much better to poll at 240+Hz, cutting the latency between input to a consistent 1/4ish of a frame. However, I doubt this improvement could be "felt" by very many people at all.
This is AWESOME. I set out to do exactly this like a decade ago and couldn't figure out how. I still have the two SNES controllers in my electronics box and dozens of Arduinos. Looks like I'll be making some USB SNES controllers this weekend.
These, as well as NES dittos, were all over eBay and AliExpress for $3 a piece some 10 years ago. Probably still are. I've got one of each, just to get the right feeling when playing Zelda 1 and Pocky & Rocky on emulators.
I bet you could build something like this with a Seeeduino Xiao (or Adafruit QTPY) to get a smaller footprint inside the case and not need to modify the plastic.
Of course completely awesome to make a modification like this.
However, if you yourself want a USB SNES controller, consider buying one instead. 8BitDo offers them with the SN 30 Pro - the quality is good, they work with the Nintendo Switch or PC (including Linux), they have the additional buttons needed for modern games, there is a wired and a wireless version and the newer variant has afaik a replaceable battery (unlike the first).
Edit: I was probably wrong about the replaceable battery, that was the 8BitDo Pro 2. Which might indeed be the better choice. Looks less like a SNES controller, but at least still has the correct button labels and core layout, see https://www.8bitdo.com/pro2/
I did try different 8BitDo controllers, and one issue with them is the "multi-mode": in order to make them work with Android/iOS/Windows/whatever, you need to press some key before connecting them, to change the way the OS recognizes the input. Which is a deal-breaker for small children, and prevents keeping things simple (e.g. "remember to disconnect and reconnect the USB before turning the power on", e.g. when using a Raspberry Pi-based console emulator). For wireless controllers, it's even worse (extra Bluetooth mode). If only they had mechanical switches to select this behavior... You may need to keep the instructions booklet with it, just to remember which keys must be pressed before turning it on, to see which mode will be activated. The controller in TFA is more useful in this scenario, since it will always behave in the same way.
The ones I have (SF30/SN30) remember which mode they're in so I just press the start button and it connects to my Switch. Then if I change it to bluetooth, it's the same for my Steam link until I switch it back. Plus there's a sticker on the back that gives the combos to change modes (Y+Start=Switch, X+Start=Bluetooth, etc). Some models, like the Lite 2, do have that physical mode switch.
I have four of the bluetooth SN30's for couch co-op games on my SteamDeck. I agree that if I switched between devices often (like my son's switch) I'd need a lookup table for the power-on chording. Mine have the key combinations printed onto the label on the back.
Fwiw, the ones I have remember their last pairing setup, so I only need to power them back on via the "Start" button.
Completely agree. I even had that situation myself - I misremembered how the mode switch/bluetooth pairing mode worked and was not able to connect my controller to a switch, thinking it was broken, until I realized what had happened. A small toggle switch really would be much easier.
Still think it's worth it, also to not destroy an original one. On the other hand, better to modify it like this than to throw it away of course...
The new version does actually use a switch instead of the magic button combination. Agreed on the previous version being annoying. Had many kid debugging sessions when they accidentally switched the mode and “broke” it.
I speed run Zelda 2, though using an SNES controller. My experience with 8BitDo controllers is that they're stiffer than OEM, especially with the d-pad arrow keys. If you can use the analog inputs, they're great -- I use a Pro 2 with my Switch all the time. The d-pad, though, is a deal-breaker for classic gaming. iBuffalo used to make a controller that really did feel like OEM, but they've been out of the business for a few years.
Can only recommend the iBuffalo SNES controller too, I have two of them and they are quite good. Didn't know the brand stopped making them, it's a pity.
Maybe if you want to play super mario, the 8bitdo sn30pro works.
But it has a huge problem of false diagonals, making is absolutely worthless to play tetris, or any fighting game that requires precise control. If you need precise controls, avoid this model.
I have the SF30 Pro since a few years now and there might have been different revisions, but I definitely did not observe that. And I played through Hollow Knight with it, so I doubt that the controls are imprecise - I would not have had succeeded. Granted though, neither tried Tetris nor a classical fighting game.
8BitDo makes great controllers. I have an SN30 Pro, a Zero 2 and a pair of Ultimate Cs. All of them have been used extensively and they are all excellent quality.
On the other hand I've had back luck with generic NES and SNES knockoff USB controllers. The quality is much worse than the originals especially in the D-Pad. It seems nobody but 8BitDo can get this right.
If you stick with 8BitDo you'll have great quality but they don't necessarily match the form factor of the originals. I can see why OP would want to convert a real one.
The form factor is really close though. Ignoring the added buttons, which is completely possible while gaming, it does not feel much different. https://www.onli-blogging.de/uploads/sf30pro.jpg for an example picture :)
I'm using the 8BitDo wireless pads on my Switch and am very happy with them— vastly more comfortable than joycons, but a fraction of the price of the official pro controller.
I once designed a custom PCB that fits inside the original NES four score case.
You can connect 4 NES controllers to it and the inputs were sent to a Raspberry Pi via UDP (so no wire between couch table and TV was needed).
I think my PCB had more parts for its simple power supply than all 4 NES controllers combined.
These things are an absolute masterpiece of simplicity!
My coworker has done a similar thing, designing a PCB that allows us to connect the SNES controller over RJ45 to a custom Pi hat. We have students writing bare metal code for it!
SNES can go up to a whopping 3.58Mhz (NTSC clock, not sure if exactly the same for PAL) but I believe due to some bus/architecture weirdness slows down to 1.79Mhz (which is what the NTSC NES runs at) when reading the controllers.
Now the SuperFX chip, in Star Fox, ran at 10Mhz. Later versions like the one in Doom on SNES went up to 21Mhz.
That 16MHz of processing power is doing a pretty magical thing, though. It's encapsulating what is basically a serial bus, into a universal serial bus — i.e. it's making it so that:
• you can plug this controller into any USB host, and the host can probe the device and discover that it's got a USB HID gamepad device
• the SNES buttons get mapped onto standard USB HID event codes (HID Usage IDs), such that you could have a SNES controller plugged into one USB port and a Sega Saturn controller plugged into another USB port on the same computer, and they'd both be using a common language for events like "D-Pad Up button pressed", such that a framework like DirectInput or SDL can understand that out of the box. The SNES just uses the same 16 bits of input register no matter what's plugged in (gamepad, mouse, super scope, etc) — with games either assuming a specific static input device type and thus parsing those 16 bits in terms of that; or telling you to have a gamepad on P1 and whatever on P2, and then asking you on startup what type of thing you've got plugged into P2.
• And — not so applicable to the SNES — but with USB, you can also have more than one of any given HID Usage ID reported by the same device. A gamepad with two analogue sticks can† just report analogue data for X/Y/Z-axis Usage IDs twice.
• You can also have as many USB HID gamepads plugged into the same host machine at the same time as you like†. Even USB 1.1 is a very fast bus compared to the SNES's input polling rate; tons of HID reports will "fit" down the pipe as packets. The SNES, meanwhile, fundamentally only supported four input devices at once, because the hardware had exactly 64 bits mapped starting at $4218, representing the 16-bit readouts from polling of up to four input devices. And even then, if you wanted all four inputs to be polled, then you'd only be getting input for devices 1+3 refreshed on even frames, and 2+4 polled on odd frames.
• You can have tons of other things — more data-intensive things! — plugged into the USB bus at the same time as the gamepad, and it'll still work just fine, because USB HID reports are given high QoS by USB host controllers and hubs. The SNES needs a separate bus for the cartridge, but on a PC the equivalent of a "cartridge" (an eGPU + eFPGA + NVMe, let's say?) could be connected to a USB4 dock, that your gamepad is also plugged into — and a single USB cable will take all that into your computer.
• You can hotplug USB devices, without confusing either the client input device or the running program on the host. Both sides of a USB link (well, assuming the client retains power when unplugged) have knowledge of the connection lifecycle state. "Device unplugged" or "device plugged in" or even "a new, second device plugged in" are just like any other gamepad events, that your game can have a handler for. Meanwhile on the SNES, both input ports are just assumed to be populated at all times — and are therefore electrically live‡ and receiving a polling clock at all times. The distinction between there being 1/2/3/4 input devices connected, has to be made manually, by the game asking. There's no way for the game to know that a device was plugged/unplugged.
---
† Consumer OSes mostly don't like this — but that's because consumer OSes are dumb, and have to this day never surfaced a high-level "gamepad API" that actually exposes the full extensibility of USB HID reporting.
A high-level API that was actually designed to reflect the HID spec, would have an input-event report be a dictionary where the keys are usage IDs and the values are arrays of sensor readouts. Or a stream of polymorphic Usage-ID-keyed sensor-readout records. And either way, each report would at the very least identify which USB device it's coming from, so that you can tell apart reports from two identical controllers.
But instead, what most gamedevs get from using industry "best practices" when writing an app-game using e.g. DirectInput or SDL for input, is an API that's even more naive than the SNES joypad input registers — it assumes that there's exactly one gamepad, and that it's reporting exactly one of each HID Usage ID. (And even worse with XInput, which assumes a fixed set of Usage IDs corresponding to "what an XBox controller has!")
As such, most USB HID gamepads sold to consumers for use with PCs, in practice, don't take real advantage of what USB HID gamepads can in theory report.
USB HID gamepads made to be used in proprietary ecosystems, on the other hand — think "the Nintendo Switch Pro controller" or "the input board on an arcade machine" — are free to be designed to actually use USB HID correctly. Which is why such devices usually need special drivers on PCs. They're not speaking a brain-damaged wire protocol; rather, they're living in the present and taking full advantage of USB HID features... while consumer OSes are still stuck in the past, unable to cope. :)
This is also why so many systems like emulators that support these proprietary input devices — or games complex enough, that they expect USB HID devices that are themselves complex enough to only be possible if using the spec the modern way (think, uh, this thing: https://www.amazon.ca/Logitech-Saitek-Vehicle-Panel-945-0000...) — just skip the high-level gamepad-input-handling frameworks, and just register to listen to USB HID events directly. Because that's the only level at which they'll receive the information they actually care about, without the OS first mangling it into incomprehensibility.
‡ I believe polling for the input ports get zeroes rather than garbage if the ports aren't connected — but this is likely more for hardware protection than anything else, with pulldown resistors on the read path to prevent you from shorting out the input pins by unplugging while the console is on. Nintendo at least learned the lesson of the PS/2 bus.)
Kind of amazing that you can get a whole controller (including buttons etc.) for a fraction of the cost of an adapter. Probably a less authentic experience though:
https://www.aliexpress.com/item/1005005998083106.html
People are always surprised that the controllers are the largest line item when building a retropie. You really want quality though, they make a big difference in that the dpads and the thumb sticks are both good.
I just got a RetroUSB Genesis adapter to use a 22-year-old Asciiware Power Clutch SG I had rotting in the basement for some JavaScript Gamepad API experiments. The adapter works great, feels good to breathe new life into an ancient peripheral!
I've actually gone the opposite direction from this post. I have a Neo Geo arcade board (JAMMA) and it has plugs for Neo Geo controllers (as in the controllers for the console version of the Neo Geo). I wanted to use the Neo Geo without plugging it into an arcade cabinet, so I got a "Supergun" board to play it on an RGB monitor. However, I didn't have a controller for it.
I noticed that there was an emulator-based "Neo Geo X" system out in the wild and you could purchase a controller accessory on its own, so I got one, not realizing it was purely a USB controller in the shape of the original Neo Geo ones, but no problem. I bought a Neo Geo controller cable and just desoldered the button to USB connections inside the controller and connected them directly to the Neo Geo controller cable. Worked like a charm!