Taking Hotline Miami 2 at face value; it can be perceived as a bigger and badder version of its 2012 predecessor with a few additional bells and whistles, a new story, a new battery of excellent soundtrack tunes and a lot more content. While the games may seem broadly similar, the underlying tech has undergone quite a lot of changes since the PlayStation release of the original Hotline Miami.

The Hotline Miami-port started out as a number of tools that converted all the assets from a GameMaker 7.0 binary project file into a friendlier format we could work with at runtime. Additionally the GameMaker Scripts were converted to C++ using Irony.NET. The runtime implementation was a cobbled together amalgamation of the generated C++ code and a whole lot of reverse engineered implementations of GameMaker’s core functionality. All of this was built on top of a messy integration with a hacked up version of Sony’s PhyreEngine.

The most prevalent problems we ran into with the original Hotline Miami were performance related. Since Hotline Miami 2 seemed to be a lot more demanding than its predecessor—to the point where GameMaker itself can’t even deal with it—something had to change. Prime candidates for optimization were rendering and the excessive amount of overhead that was present when executing the generated C++ code.

The first big overhaul we instigated was the incarnation of what is now GameBaker. We moved from a monolithic codebase towards having a shared, separate library for the generic simulation code and kept a per-project library for the generated C++ code.

Having the engine level tech separated made it a lot easier for us to start the next phase: migrating away from PhyreEngine and towards our own low level, cross-platform library SilverWare. This decision was made in large part because it would allow us to further improve our own reusable tech and accommodate future ports to Android devices. Ditching the messy PhyreEngine integration was the icing on the cake.

Once this was up and running on our target platforms, it became apparent that SilverWare wasn’t up to the task just yet—performance of the immature, single-threaded rendering pipeline being the largest problem. To resolve this we reworked that into an asynchronous model which got us reasonable performance across the board. Later, we ended up moving all the GameMaker draw command processing into a third thread to overcome the last performance hurdles we had on Vita.

The final overhaul we did was a complete rework of the way we handle GameMaker variables. We moved from the initial, strongly typed system toward something more closely resembling the way GameMaker actually works. While the old system was designed to catch bugs early, it proved to create more bugs than it solved and created quite a few performance issues. After this rework we rarely had to address issues at the code-simulation level, something that was an extremely common time-sink before.

It’s all too easy in this industry—perhaps particularly so in porting—to take the path of least resistance due to time and budget constraints. Risky technology reworks are often discouraged, especially so with proven tech that has shipped a game. For Hotline Miami 2 we were forced to roll the dice and battle the odds; we didn’t ship on-budget but would not have shipped on-time either if it wasn’t for these rigorous reworks.

  • Matthew Arnold

    This was a good read :)