In 2012, Peter "Durante" Thoman wrote the popular mod DSfix for Dark Souls: Prepare to Die on PC, fixing its locked 1024x720 resolution and other issues. In 2013, he released a similar fix for Deadly Premonition . We asked Durante to analyze the PC port of Dark Souls 2 in a series of articles. He also modded the game. The image above is an in-game texture, not a Photoshop.
My first two articles about Dark Souls 2 investigated the PC port's features and how generic PC tweaking tools like SweetFX can be used to further improve its graphics . Now it's time to look at the full extent of what can be achieved by modifying Dark Souls 2 on a deeper level. First, I'll provide a short overview of the general avenues available for PC game modding and how each applies to Dark Souls 2. Then I'll detail the modifications I have implemented so far with a new tool I'm calling GeDoSaTo, which enables texture modding, arbitrary downsampling, and more. Consider it the successor to DSfix and DPfix—except its final goal is to work with any 3D game, not just Dark Souls 2.
The many paths of modding
While there are many ways to modify a game, they can generally be assigned to one of three categories based on their underlying approach:
- Data File Alteration
- Library Call Interception
- Direct Binary Modification
These are ordered by increasing “invasiveness” of the procedure. The more invasive the mod, the more difficult it is. We'll now look at each approach and how it can be applied to Dark Souls 2.
If you just want to get to GeDoSaTo and how it enables modding in Dark Souls 2, click here to jump to page two.
Data file alteration
This is a simple method in principle, and can be used with many games to alter their assets—textures, sound files, even models and levels. Imagine a basic game, which ships with a folder full of images used directly as textures. By changing one of these images, you perform modding via data file alteration. For example, the popular rhythm game Audiosurf has all of its files fully accessible in this way.
In most modern games—at least those not built for modding—the situation is not this convenient. Data files are often gathered in undocumented custom archive formats with unknown forms of compression. While this is of course an obstacle, resourceful modders may reverse-engineer such archives and provide tools to rebuild them with different data. Dark Souls 2, as discussed in the initial article , stores the vast majority of its data in “*.bdt” files, such as “GameDataEbl.bdt”.(opens in new tab)
Above, you see a tiny excerpt of the contents of Dark Souls 2's main game data file. As you can see on the right, this part appears to contain some names of a few individual files stored in this archive. Before this section, a set of numbers is stored which might well contain offsets into the archive which designate the location of each individual file. With enough time and effort, it should be feasible to fully understand this file format and write tools for handling it. That could take anywhere from weeks to years, and even such a heroic attempt might still not suffice to enable Data File Alteration in Dark Souls 2.(opens in new tab)
What you see above are the contents of the “GameDataKeyCode.pem” file shipped with Dark Souls. It is a RSA public key file , and there is one such file associated with each game data archive. The most obvious interpretation of this is that the game checks the signature of each data file upon load, in order to ascertain that no modifications have been made. Note that this is not a certainty—it's an educated guess. If I'm correct, then data file alteration for Dark Souls 2 will additionally require breaking its encryption and/or direct binary modification in order to disable it. Luckily, there are alternative approaches.
Library call interception
Library call interception works by replacing a library (a collection of program functions) that a given game depends on with a customized alternative. A very common tool based on this principle is SweetFX.(opens in new tab)
In the image above, you see a schematic illustration of the “normal” execution of a program. At various points in time, the game makes a call to a library function (for example in the Direct3D9 library d3d9.dll), which cause some procedure to be executed and a value reported back to the program. Library calls in the program are illustrated by blue arrows, and return values by green arrows.(opens in new tab)
An interceptor, as the name suggests, intercepts the program's library calls, altering them before they reach the library. It then reports its return values—or entirely different ones—to the program. As an example, think of Dark Souls 1 and DSFix. In simplified terms, DS1 asked Direct3D for a 1024x720 surface to render the game to. DSfix took this request, changed the resolution to whatever the user desired, and gave the subsequently generated surface back to Dark Souls. That alone would generally just break rendering—you also need to adjust rendering viewports, projection matrices, scissor rectangles and potentially shader parameters to make it work—but this is the basic idea.
The largest challenge when writing an interceptor (beyond the mechanics of interception) is understanding the original program's behavior and determining how to alter it in order to achieve the desired effect. Crucially, a library call or sequence of calls has to be determined which uniquely identifies what a program is doing at that given point in time. This difficulty is the reason why SweetFX works well with a great number of games: it simply changes the output image at the very end before it is presented on the monitor, and this point is easy to generically identify.
Direct binary modification
Modifying the code of a running program directly in memory is the most powerful, but also most complex, form of modification. In this process, some binary instructions in the original program are replaced with different ones, resulting in an altered behavior. It can—in theory—be used to accomplish anything, but in practice this is often not feasible for large modern games due to the reverse engineering effort necessary to understand their code base to the degree required for meaningful alterations. Nwks achieved the Dark Souls 1 frame rate unlocking using this process, and something similar might be possible for Dark Souls 2.
For now, we're going with the interception method. On page two, we mod Dark Souls 2.