Ever since ME2 was released, some people have been affected by a bug that causes the game to crash at the end of Kasumi's loyalty mission, after the shuttle scene, when pressing the Exit button to return to Normandy. This crash seems to affect modern PCs more than old ones so I decided to investigate.
In this article, I'll explain how I fixed the problem and made a mod that can be easily loaded into the game to fix the crash.
If you're just here for the fix, here's what you have to do:
At the end of the process, your Binaries and asi folders should look like this:
Now you can run the game.
Now that the good stuff is out of the way, let's get into how it works.
To investigate the crash, we can't use a regularly purchased version of the game because there's DRM on it and the exe file is encrypted, so I used a cracked exe, which is unencrypted, and triggered the crash.
In the Event Viewer, we can see some the details of the crash, collected by Windows:
Windows tells us that the game crashed due to a null pointer exception, at file offset 1ACBCF.
A quick look with IDA Pro shows us the incriminated code with the crash at .text:005ACBCF:
As C-style pseudocode, this is what's going on:
...
MyStruct *s=someFunction();
badFunction(s);
...
void badFunction(MyStruct *s){
...
if(s->attr1==NULL) return 0;
...
return 1;
}
...
The game calls a function with a pointer to a struct, then proceeds to check if some attributes of the struct are NULL without checking that the pointer to the struct itself isn't NULL, and that's where it crashes.
But what is this struct anyway? Honestly, I have no idea. Looking at the stack trace, it looks like we're inside the engine, possibly in the scripting engine.
Previous "fixes" for this issue suggest using the -nomoviesstartup command line argument to workaround this issue, and that disables Bink video playback so my guess is that it's something releated to video playback, maybe it tries to play a file that doesn't exist? I don't know.
The fix is quite simple: we need to modify the code so that badFunction will do this:
...
if(s==NULL) return 0;
if(s->attr1==NULL) return 0;
...
return 1;
Adding code to an existing binary is not always easy, but in this case we're lucky because there're an empty area in the exe nearby, presumably used for cache alignment.
We're going to overwrite the first part of the function with our new code, put the overwritten code in the previously empty area and use jumps to get the correct execution path.
This is the new code:
test eax, eax ;check s==NULL
jz short loc_5ACC40 ;if it's NULL, go to the code that returns 0
jmp short loc_5ACC44 ;jump to the overwritten code
loc_5ACBD5: ;rest of original code begins
...
loc_5ACC44:
cmp dword ptr [eax+54h], 0 ;check s->attr1==NULL
jz short loc_5ACC40 ;if it's NULL, go to the code that returns 0
jmp short loc_5ACBD5 ;continue with the original code
...
This is what the function looks like now:
Running the game we can see that it no longer crashes.
While the fix seems to work perfectly, there is the issue of distribution: I can't just distribute my modified exe because it's based on a cracked version and ME2 is not exactly abandonware, I'd run into copyright issues. This is where Erik-JS's binkw32 DLL comes to rescue, since it allows loading of ASI mods.
An ASI file is basically a DLL that is loaded into the game at run time and can provide various functionality, most interestingly, it can alter the program code, and this is exactly what my fix does:
Thanks to Erik-JS's excellent code, creating the ASI file was surprisingly easy, I simply reused one of his mods and adapted it to my needs. Visual Studio was the main source of wasted time, to be honest.
Getting the fix working on all versions of the game took some time: the cracked version is the best, as usual, but I had to add a couple of workarounds to get it working on the official DRM-infested releases:
This fix should work on all versions of Mass Effect 2: Steam, Origin, Disc or cracked, although I've only personally tested it on the cracked version, which is the one I usually play because I don't want DRM running on my system.
At the moment, I've only tested the fix on Windows 10, but it should work on Windows 7 as well. Erik-JS says that his loader is designed for Windows 7 and newer so it should not work on Windows XP.
You can download the ASI file from here
You can get the source code from here or from the Github repo. You'll need Visual Studio 2019 with MSVC v140 to build it.
The fix is distributed under the GNU GPL v3 license.
Needless to say, I am not affiliated to EA or Bioware in any way, and this is not an official fix.
If you're running into issues with this mod, open an issue on Github or send me an email at info@fdossena.com.