Xbox 360 Gaming with a Wiimote
Xbox 360 Input Machine (XIM) enables any PC input device to be used on the Xbox 360.
I (like many others) am a proud owner of a Wii60. Us Wii60 owners feel that we've got gaming all covered. Our Xbox 360 gives us top-class hard core online gaming in high definition. Our Wii gives us really unique gaming experiences because the Wiimote is like nothing else. But, what if we could get the best of the Xbox 360 and the best of the Wii, together, in a single game? I was curious, and the end result is my creation that I call Xbox 360 Input Machine
(or, "XIM" for short).
(Even though I chose to adapt a Wiimote to my Xbox 360, this system will work with any input device that a PC can recognize. This, of course, includes any gaming mouse and keyboard (wired or wireless) available.)
Why a project like this?
XIM is, by far, the most ambitious side project I have ever worked on. It took most of my spare time over many months to complete and there were a lot of failures along the way. People may wonder why I'd spend so much time on a project like this. I have no agenda behind it. The answer is simple: I enjoy it. I like working on hardware, software, and firmware. Given that I also like gaming, I felt this sort of project was a natural fit with my interests.
No matter what, I wasn't interested in creating vaporware. The end result had to work. I wanted something that I could play on daily that performed well.
Where to start?
The initial hurdle was to figure out where to start. We've seen devices come and go that let you use alternate input devices on the Xbox. Of course, there was the SmartJoy FRAG (SJF) for the Xbox, and now the XFPS 360 for the Xbox 360. Both these devices enable gaming using a mouse and keyboard with various levels of success. I own both of these devices and I can tell you that the SJF worked well on the Xbox (all my time with the device was spent on Halo 2). It was far from perfect, but, it was workable. As for the XFPS, that's a different story. It's performance is horrific (not to mention its hefty price tag). A lot of "SJF people" like me bought this device only to be very disappointed.
One redeeming trait of the XFPS is that it can also accept Playstation 2 controllers. It turns out that it does the translation to Xbox 360 very well. The XFPS also has another important feature: it circumvents the Xbox 360s security which prohibits 3rd parties from creating alternate input devices. Because of this, I decided to take my XFPS (which, at this point was collecting dust) and use it in my project.
Generating the right signals
As I mentioned, the XFPS can convert PS2 controller input to Xbox 360 input. This meant that I needed to emulate a PS2 controller. Turns out that the protocol is fairly well documented. The best source of information I found is here
. The document describes the protocol in detail (using ASCII-art for the waveforms!). It turns out that the PS2 protocol is very similar to the standard Serial Peripheral Interface (SPI) (4-wire Master/Slave) that many microcontrollers support in hardware. It's not exact though. The PS2 protocol includes an controller-side acknowledgement (ACK) signal and it delivers bits in reverse relative to SPI. There was another issue too: the XFPS itself is emulating a PS2 console so, there may be slight differences in how it implements the protocol. Despite all these differences, I decided to go down the SPI route, and, I was glad it did.
The microcontroller and firmware
It's been many years since I used and wrote firmware for a microcontroller. Back then I was using a Motorola HC11 and the firmware was in assembly language. Compared to the types of desktop software development tools and debuggers we have today, it was a pretty primitive environment. As I was searching for a microcontroller platform to develop on, I was thinking (hoping) that times have changed. I'm happy to report they have.
It hasn't reached the level of sophistication of desktop software development environments, but, microcontroller development has come a long way. They now have integrated development environments (IDEs), in-circuit real-time debugging, and mature C-based compilers. There are quite a few offerings out there, but, the company that stood out amongst the rest is Silicon Labs
. They offer a great end-to-end solution that includes affordable (cheap) development kits called their ToolStick
line. For $25 I got a nice 8051-based kit that includes a prototyping area and also interfaces with the PC via USB. These processors are incredibly fast (25 MHz) and are only a couple of millimeters in size. And, most importantly, they include the SPI interface in hardware.
The "black box" in my design contains the development kit along with a PS2 controller extension cord cut and soldered on to the prototype area. The firmware I wrote configures the microcontroller to interface to the PS2 bus via the SPI interface. The ACK signal I mentioned before is also generated after an entire data transfer cycle is complete to inform the XFPS to start on the next cycle. The firmware also handles communication with PC via the onboard USB connection. The PC sends a PS2 controller state "packet" down to the microcontroller, then, in turn, the microcontroller places this data on the PS2 bus. Of course, timing is everything. Care was taken to ensure that the microcontroller is always responding to the XFPS quickly, otherwise, data would be corrupted or lost. At the same time, packets received from the PC must be buffered until the latest PS2 bus transfer is fully committed. As I was unfamiliar with development on this microcontroller, it took some time, trial and error to get this all working. The result turned out to be really solid and I'm happy with the overall design.
The PC connection
The requirement of a PC could be considered pretty "heavy-weight". Even though an underpowered PC is good enough, we are still talking about gaming on a console after all. But, the PC in the overall XIM-equation is a vital piece of the puzzle for a few reasons:
1) The ability to interface with just about any input device
As I mentioned before, the system can interface with any input device that the PC supports. Given that the Wiimote is a standard Bluetooth HID (Human Interface Device), existing OS interfaces could be used access the device.
2) The ability to model complex input translation "profiles"
Input translation is how input from the Wiimote is ultimately converted to input to the Xbox 360. The more I worked on this project, the more I realized that a "one-size-fits-all" solution just isn't enough.
Games for the Xbox 360 are simply not designed for anything other than a dual-analog game pad configuration and it differs per-game. First Person Shooter games are especially difficult due to extensive "aim assist" features (in the form of look acceleration and auto-aim) to make aiming with your thumb possible. These assist features make simplistic translations result in a mediocre play experience (i.e. "jumpy reticule") when using a Wiimote or mouse.
Every combination of game and input device truly requires a different (potentially complex) translation method (i.e. "profile") for best experience. My first profile is Halo 2 played with the Wiimote.
3) Shareable input translation profiles
It wasn't easy building a good translation profile between the Wiimote and Halo 2 on the Xbox 360. Since I'm using a PC, I could share the profile with someone else by publishing it online.
Talking to the Wiimote
The Wiimote and Nunchuk are great input devices. They are relatively straight forward to program against since they are standard HID devices. There is actually a decent sized community out there using the Wiimote in different ways. The main alternate use is gaming on the PC.
Accessing the Wiimote via HID APIs is one thing, but, knowing how to send commands to it and decipher data coming from it is another. I was happy to find that there is a decent amount of code available online that I could reference. The best I found is a .NET library
. This code base gave me the vital information I needed to communicate with the Wiimote using my unmanaged C++ code base.
The Wiimote Halo 2 input translation profile
I was set. The hardware interface and firmware was done. I could send single controller state (button presses and analog stick positions) commands from my PC to the Xbox 360. It worked really well. I could also read input commands from my Wiimote and Nunchuk. But, the next hurdle was to take this live data from the Wiimote and convert it to Xbox 360 controller input that actually felt right in-game. Button presses are easy to map. What was going to be most difficult is mapping look (reticule) movement in Halo 2. (Why Halo 2? Because I love Halo and Halo 3 is right around the corner!)
I had two problems left now:
1) How to use a Wiimote in a fixed-reticule game like Halo
2) How to compensate for the aim-assist that made for jumpy reticules with Xbox mouse and keyboard adapters
Wiimote and fixed reticules
Anyone that has played a FPS game on the Wii knows that they use a "bounding-box" technique for aiming. The reticule moves with the Wiimote and look movement occurs when the reticule goes beyond an imaginary box on the screen. Once you get used to it, it controls very well and makes for really fun game play. I had the problem now of figuring out how to make Halo's fixed-point reticule move with the Wiimote.
Various PC demos I've seen used the tilt of the Wiimote to cause reticule movement. This struck me as awkward as it seemed like it would be difficult to control (especially restoring the Wiimote back to the "zero" position to stop movement). I went ahead and tried this sort of look translation, and, I was right, although movement was smooth, it was uncontrollable.
I decided to take the same approach as a mouse in FPS gaming. Reticule movement on screen would correspond to where the Wiimote is pointing (via its IR sensors). When you run out of "mouse pad" the mouse is picked up and repositioned on the pad. Similarly for the Wiimote, when the Wiimote exceeds the IR field, you use the A button to disengage movement and reposition the Wiimote. This feels the most natural and responsive to play. The negative to this was that, since the Wiimote IR is so sensitive, every little movement (including your hand shaking slightly) would translate to movement on the screen. This problem along with the game's existing "auto-aim" needed to be addressed.
Smoothing out the reticule
Making look (reticule) movement feel smooth turned out to be a recurring process of trial and error. Wiimote IR movement deltas couldn't be translated directly (linearly) to Xbox look thumb stick deltas without a jumpy reticule. I settled on an exponential translation curve to best help counter the affects of in-game acceleration. I then added smoothing algorithms to help keep the reticule stable. I still had a problem between precise aiming and fast turning.
I felt like given the constraints of the look mechanics of the game, I couldn't make both precise aiming and fast turning work with the same translation curve. That's when I decided to program in two curves which are switched based on the state of the Nunchuk C button. By default, turning is fast. But, when you need to be more precise on aiming, pressing the C button drops the sensitivity.
All this combined with independent X-Y sensitively and, of course, dead zone compensation, made for a good experience. It's not perfect, but, I feel with more tweaking, it has the potential of being great.
Where we go from here
As far as hardware, where I think where it should go is beyond the free time I have to invest. I'd love to see something like this packaged (i.e. all the parts) into a single device. The device would have to be sophisticated enough to accept new, relatively complex input transformation profiles. This means it would need to be able to interface with a PC in some way (ideally wirelessly) and be programmable via the PC. Of course, accepting more than a mouse and keyboard is a must (such as a Wiimote or other bluetooth devices).
But, for now, I'm looking forward to spending quality time gaming with this new setup, applying incremental improvements to the software and firmware, and coming up with new profiles for different games.