Input Control

SNES Input Viewer, Logging, and Playback

My first foray into working with controller monitoring and manipulation started with my desire to create a custom SNES input viewer. Input viewers are software displays that illustrate what buttons are being pressed on a controller, and can add some flair to a player’s stream while doing speedruns. I started with the instructions and code from jaburn’s NintendoSpy project, but I wasn’t quite satisfied with its performance or features. So I set out to make my own, using NintendoSpy as a template.

My first step was to design the visual side of the viewer. This would also serve as my first introduction to Windows Presentation Foundation, as I hadn’t worked with dynamic graphical elements in any of my preferred programming languages before. I had an idea for structuring a viewer similar to StepMania, where the inputs would cascade down over a fixed length of time. This would also serve to show discrepancies in inputs, letting viewers more easily identify the sequence and duration of presses.

My next challenge was to allow for a more responsive communications between the host and an Arduino that was monitoring the communications. NintendoSpy originally only checked for updates every 50 ms or so, which is fine for most scenarios, but I felt it made the input reading too inconsistent and jumpy. But it turns out that precise event timing in Windows is harder than it should be. I went through several different architectures for capturing inputs in a more precise manner, and eventually settled on a FIFO setup with modifications to the firmware for precision. Basically, I couldn’t guarantee that Windows would be able to receive the data in a timely fashion, but I could make sure that it definitely received the data at some point, and update the visuals accordingly.

Over the course of these tweaks, I realized that this more precise architecture could also potentially be used for something else entirely: accurate logging and playback of player inputs. The idea was that if I could accurately capture a player’s inputs from a fixed reference point, then those same inputs could be played back for an exact repeat of the performance, whether on console or through an emulator. This could have allowed for remote verification in speedrunning, which seemed really cool to me. Thus I began work on what would become Input Control.

Input Control took the modifications I made to NintendoSpy and further updated them with more context-aware control functionality. I then added in a playback mode, where instead of passively monitoring the control lines, the Arduino would actually drive the communications and pretend to be a controller. In addition, I added software functionality to package the resulting input log files in a format that could be played back on BizHawk. Finally, I integrated my input viewer, now called Input Mania, right into Input Control just because.

But did it work? Well, yes and no. It certainly was able to record and play back the inputs exactly. The issue is that even if the inputs are played back in precisely the same order, the console did not operate deterministically enough to respond the same way. Many of my test runs were able to stay in sync for several minutes, but there would inevitably be some point where the playback and the console would become desynced. Without controlling the operation of the console itself, I would not be able to guarantee that logs could play back perfectly. The same went for emulators; there was always a discrepancy somewhere that prevented them from working out.

This realization killed my motivation to work further on the project, but I still learned plenty from the experience. Even if the logging and playback couldn’t be perfect, it’s still a neat feature that could be used for review. And if nothing else, Input Mania is still a pretty nifty input viewer. You can find the source code for the software and firmware on SourceForge. I’ll probably get them on my GitHub eventually, too.