An inside look at how modding makes PC games better
Peter "Durante" Thoman is the creator of PC downsampling tool GeDoSaTo and the modder behind Dark Souls' DSfix. He has previously analyzed PC ports of Valkyria Chronicles, The Witcher 3, Tales of Zestiria and more.
The recent release of a modification for running Tales of Zestiria at 60 fps—rather than the default 30—has once again demonstrated that mods can significantly improve PC games after release. But what actually constitutes this type of “modding” is still a mystery to most gamers. How difficult is it? How complicated? If modders make it look easy, why can't game developers implement these features in the first place?
In this article, I'll go over the most common types of modding today, and then go into more detail concerning the ones relevant in cases like Zestiria and Dark Souls. I’ll also go back to the vexed question of why mods can often accomplish feats which are apparently out of reach of the original developers and publishers, and provide both my own and other modders’ perspectives.
This is my first time reporting primarily on other modders’ work, and it’s a great joy to see an excellent community form itself around the practice, even for games which don’t natively support any modifications. As such, before delving into the heart of the matter, I’d first like to extend my thanks to the two people primarily responsible for the improved state of Tales of Zestiria on PC today: Andon “Kaldaien” Coleman and Niklas “DrDaxxy” Kielblock. Both have been exceedingly helpful in providing their own perspective on the process of modding in general, and on modding Tales of Zestiria in particular.
A Short Taxonomy of Modding
When trying to classify types of modding, the first and most crucial distinction is between mods directly supported by the developers of a game, and ones which are not. The former is a staple in e.g. Bethesda’s games, and also somewhat common with releases from other developers with a PC background.
What is possible through this type of modding and how it is accomplished depends completely on the types of tools provided by the developers. In general, gameplay modifications and content additions are far easier to accomplish when official tools are provided, and a truly staggering amount of content can result. However, as it’s the most well-understood and easiest form of modding to get into, it's not our target in this article.
If modding is not officially supported, there are three common ways of modifying the behavior of a game despite that limitation: data file editing, API-level interception and direct binary code injection. Of these options, editing a game’s data files is the most straightforward, though it can vary from simply modifying .jpg images to adjust textures all the way to reverse-engineering the custom binary file format(s) of a game.
The biggest gaming news, reviews and hardware deals
Keep up to date with the most important stories and the best deals, as picked by the PC Gamer team.
This leaves us with API-level interception and binary code modifications, which are the methods applied to Tales of Zestiria. We’ll investigate these in more detail now.
API Call Interception
The TZFix project by Kaldaien—the primary mod for Tales of Zestiria—started out with the goal of solving an issue I missed in my initial port review, simply because I use an audio setup on which it does occur. While this bug was patched rather quickly, the game used to unceremoniously crash on startup on systems which use a 7.1 speaker setup.
TZF was soon extended to also improve the game’s frame pacing (poor consistency of frames can cause stuttering even with a high average fps), which was problematic on many systems, reducing apparent smoothness despite ample performance. By now, it features aspect ratio support for non-16:9 displays, a shimmering fix, and also integrated my character shadow resolution improvements.
As you might expect from the title of this section, all these improvements were achieved using API call interception. This means that calls to standard programming interfaces—such as DirectX or core Windows functions—are intercepted by the mod, examined, and potentially modified. A fundamental tool often used for this purpose is minHook, which provides functions for relatively conveniently replacing API calls in memory. The other part of the “fundamentals” equation is actually getting the mod code into the game process, which is generally accomplished either by replacing a library used by the game with a wrapper—as TZF does for d3d9.dll—or injecting it by other means.
In any case, applying these modifications, while requiring some mechanical effort and familiarity with low-level details of how library function calls work, is really the simpler part of the process. Figuring out where and what to modify when to achieve a desired effect, without introducing undesired consequences, is where the true challenge lies. This falls squarely in the area of reverse engineering, a topic whole books have been written about, but I’ll try to provide a quick overview based on a concrete example from Tales of Zestiria.
The first step is to figure out which API functions are actually invoked by a game. I mostly simply use Microsoft’s dumpbin utility for this, while Kaldaien prefers Dependency Walker and specialized debugging tools. Either way, as a modder you have to form a hypothesis on which APIs are probably involved, and then investigate its use more closely. For our discussion, I’ll go with the character shadow resolution mod I implemented.
Generally, with some basic knowledge of how 3D rendering works, you expect shadows to be rendered to some intermediate buffer first, and this buffer to be used again when the final scene is rendered later on. There are a lot of tools out there to investigate the rendering of a game, but few of them are geared for reverse engineering and modification of games with only access to a (potentially encrypted) binary. I was happy to hear that Kaldaien found the framedumping functionality built into GeDoSaTo useful for this purpose. By associating its visual image dumps and logging output, it’s possible to reconstruct which buffers are involved in shadow rendering.
However, simply changing their size did little to improve the visual output in Tales of Zestiria. It was also necessary to determine which GPU shaders are used in filtering, reconstruct the meaning of their parameters from their usage, and adjust those parameters to the new shadow dimensions. Note that this is a few hours of work summarized to one sentence.
That’s API call interception in a nutshell. It can be used to work around game bugs, as in the initial TZF or my recent short-term Mushihimesama fix, but it can also greatly improve aspects of a game or even add features to it. Examples of this include TZF, DSfix and even the generic functionality of GeDoSaTo.
Binary Code Modification
While API interception opens up a great many possibilities, it cannot by definition modify behavior which does not involve any external library calls. That’s why the 60 fps modification by DrDaxxy was missing from the list of features in the previous section, and why he had to resort to direct investigation and modification of the game code and variables to accomplish this feat.
While both API interception and binary modification boil down to reverse engineering, with the former a modder at least has the known semantics of the library functions to guide them. With binary code modification, one of the greatest challenges is finding some starting point. For DrDaxxy, who used CheatEngine for most of his work, that starting point was the idea that a game running at 30 fps should store some values representing “1/30” somewhere in memory.
Just changing those values already had some effect, but only achieved the desired effect in some scenarios. What followed was an investigation of the game code which uses these values, which finally turned up a multiplier used in several other instances. Adjusting this multiplier led to mostly-working 60 fps gameplay. Subsequently, these adjustments were refined further, implemented in C and included in TZF. If this description sounds like it is glossing over tons of important details and lots of intuitive leaps, that’s because it is. There is just no way to fully convey everything you need to know to get started on a binary mod project in a few short paragraphs.
The power afforded by binary modification comes with some drawbacks (other than its sheer difficulty). For example, official patches to a game should usually not change the behavior of API-level interception, but often completely break binary modifications hardcoded to specific addresses.
So why can’t [company X] do it?
This is a question that commonly, and understandably, gets asked a lot. The answer likely differs with each individual case, but it is important to gain some perspective on both sides of the equation.
Both Kaldaien, who got his start reverse engineering games 15 years ago on Everquest, and DrDaxxy, a 20-year-old student who first made headlines for his GTAV FoV mod earlier this year, told me that they invested about 10 hours each before the first public release of their mods. Now this is obviously based on existing infrastructure and knowledge, but nonetheless it is not a huge amount of time compared to what it takes to develop a game. Even more crucially, as the main part of the article should have made obvious, the majority of this time is spent reverse-engineering behavior which should be far more obvious in the original code base that the developers work on.
However, the expectations for mods and official releases are vastly different when it comes to stability and polish. The initial version of the 60 fps unlock suffered from a variety of glitches, many of which have been resolved by now. Still, some remain, including minor visual niggles to at least one currently known progress-stopping bug—which incidentally, according to DrDaxxy, might also be one of the hardest to fix. For an unofficial release, many gamers won’t mind disabling a mod manually for 1 minute in return for 50+ hours of a much smoother gaming experience. But for an official release, this would be unacceptable.
Taking into account these constraints, Kaldaien opined that Bandai Namco delivered a respectable port and made a significant effort to accomplish many of the things TZF is polishing off.
In my personal opinion, what should truly be taken away from this is a celebration of the nature of the PC platform, which allows people to tailor their experiences in the way they want. We get to decide for ourselves whether to put up with minor annoyances in return for a given feature or not.
You can download TZFix and the 60fps mod on the Steam page here.
Path of Exile 2's genius theorycrafters have already put together some wild builds, so we've plucked out a few of our favorites that you need to try
The voice of Shadowheart, Jennifer English, would love to return to the role after Baldur's Gate 3—as long as Hasbro doesn't mess it up and 'make her into a cartoon'