Updating Light Gun Commando to ESP-IDF 5.0 and simulating a Guncon 2

Sunday, 25th December 2022

I've continued working on the Light Gun Commando project that I hope to be able to use as a system for playing light gun games on old consoles with Wii remotes.

The Wii remotes are connected to an ESP32 microcontroller using Bluetooth, and I had a few small issues with this arrangement, most obviously with a cheap third-party Wii remote that refused to pair. I had also encountered a few other quirks and oddities along the way, such as the timer capture's interrupt (used to measure the horizontal scanline period for timing purposes) crashing the whole system if it received too many pulses in a short while (e.g. by inserting or removing the video sync cable producing lots of fast glitchy pulses). I'd found some clumsy workarounds, but when I saw that the ESP-IDF 5.0 development tools for the ESP32 had been released I thought it would be worth updating to that to see if it improved matters.

As well as a lot of improvements and bug fixes ESP-IDF 5.0 did introduce quite a few breaking changes and I couldn't get the project's existing Bluetooth code to compile at all under the new environment. Much of it was based on sample code and rather than try to get this old copied-and-pasted code that I didn't fully understand up to scratch I ended up writing my own code to handle searching and connecting to devices. Fortunately this is quite straightforward to do with the Bluetooth APIs provided, and I even got my cheap 3rd-party knockoff Wii remote to pair alongside my official Wii remotes.

I use the Motor Control Pulse Width Modulator (MCPWM) and Pulse Counter (PCNT) peripherals on the ESP32 to generate the waveforms that approximate what a light gun would see if it was pointed at a CRT based on where the Wii remote is aimed. The old drivers for these peripherals have been deprecated in ESP-IDF 5.0, and though my old code still worked it threw up some compiler warnings and as I'd experienced crashing issues I thought it best to update my code.

I've found the new drivers provide much better control over the peripherals, at least for my use case, and are quite a bit easier to use. I was able to remove some of my clumsy workarounds and improve overall performance, as well as properly handle the timing for a range of different video modes: 240p, 480i, 288p, 576i and 480p are now all supported. Separate sync is now also supported for Dreamcast VGA compatibility, as the following video demonstrates:

One light gun I hoped to support was the PlayStation 2's Guncon 2. This uses a USB connection and USB is not something I have very much experience with, though I have used V-USB in a few projects before to add USB support — I'd been using standard device classes (e.g. HID or MIDI) where it's a case of simple "fill in the blanks" coding to get a working USB device, rather than a vendor-specific class device like the Guncon 2.

Fortunately I do have a real Guncon 2 and by plugging it into my PC I was able to get a device descriptor from the Windows SDK's usbview. From this I could see the device IDs that I'd need to include as well as see that the Guncon 2 has an interrupt endpoint. Armed with this information I was able to set up a USB device descriptor that closely matched the Guncon 2 by editing V-USB's usbconfig.h.

Of course, having a matching device descriptor is not much use without sending the approprate data back to the console. I'd seen a few places mention that the gun's data is six bytes long: two bytes of button data, two bytes of 16-bit X coordinate data, two bytes of 16-bit Y coordinate data (least significant byte first). I was able to find a mapping of button names to bit indices in the button status data, but nothing clear about the coordinates. I started by just using the same coordinates as the original Guncon, which appears to work for Y but squished the X coordinates into the left half of the screen. I tried doubling the X coordinate range (from 384 units to 768 units) but this seemed a little too wide. I ended up settling on an X coordinate range of 640 units, which seems to provide good results:

The only USB-handling code I've got in there at the moment is a basic poll/check interrupt ready/write interrupt data loop, though, which is likely not enough to properly implement all of the Guncon 2's functionality. Time Crisis 3 and Virtua Cop: Elite Edition seem happy enough so far, but I'll need to do some further digging into the Guncon 2's USB protocol. I've also ordered an original Xbox controller extension cable to cut in half as I'd very much like to see if I can build an Xbox gun adaptor, and the Xbox uses USB like the Guncon 2.

FirstPreviousNextLast RSSSearchBrowse by dateIndexTags