So I bought the game Galactic Civilizations II a long time ago. I was able to play it on my wife’s laptop and I figured it had to be pretty easy to get at least the major parts of the game running in Wine since it doesn’t have the copy protection code which normally breaks games nowadays, and it didn’t look like it was using any fancy DirectX features.
Needless to say my first attempts to make it work in Wine didn’t go so well. I tried off and on over that month and eventually just gave up, playing it on the laptop when I had time. I basically never play it now, as moving over to the laptop is just too much of a hassle.
Last night I decided to try again. It took some 6 hours and probably the most debugging I’ve had to employ over this entire year on a problem, but Victory is Mine! :)
The first problem I had is that after patching the game to the latest version, 1.4x, it required activation (what Stardock uses for copy protection instead of CD copying controls) in order to start. This is normally pretty easy, and you can activate by email even if necessary. But the process always crashed. I first tried copying over the authentication certificate from the laptop but it’s tied to the machine you’re on.
So I then tried bringing down the network interface, running the activation again and trying to get the activation request so I could email it to Stardock. That didn’t work either, as it crashed just before I got to that part.
Getting fed up I decided to use one of the Wine debugging megaweapons, relay tracing. This option causes Wine to mark the entry and exit from practically every single procedure call in Wine, including function name, module, and parameters and return codes. You can filter this all down to just the module you need but I didn’t know where the problem was. 70 megabytes of a relay log later, I had something which I could look at.
It took a bit of deductiveness (i.e. searching for the last place where the serial number is used, which is probably close to the crash location) but it turned out the error was in advapi32, in the cryptographic code. Looking at the Wine source code, it looked like the code was trying and failing to read a required Registry key. But how did Wine install itself without setting up required Registry contents?
I tried running wineprefixcreate (which among other things, sets up default Registry contents) but that didn’t help. Eventually a bit of Google searching for the registry key name (Cryptography\Defaults or something like that) resulted in a hit on the rsaenh.dll in the Wine source, in the DllRegisterServer() function. That looked like it created the required keys. Hmm.
From my past life developing Win32 applications I knew that OLE registration for a DLL was typically handled by running rundll32
and passing the DLL name and entry point (DllRegisterServer in this case). wine has that tool as well so I tried running it and… success at last!
Now GalCiv2 wouldn’t run because it said I didn’t have DirectX 9.0c. I tried following some instructions I found to install DirectX 9.0c DLLs into Wine. It turned out I had to use the rundll32 program again on the wintrust DLL to get the installer to do anything. It would still error out though.
At this time I figured there were probably many DLLs that needed to be registered. So I took the rash action of going to my /usr/lib32/wine directory and registering every single DLL in there.
GalCiv2 still didn’t start up, but that’s because I forgot to undo some of the steps I took in the previously mentioned DirectX 9.0c install guide (namely, using native instead of builtin versions of some DLLs). Once I undid that GalCiv2 started up just fine. I haven’t actually played it yet. It was so late by that point that I immediately went to bed. Now I need to see if the game can actually be played in Wine.
I also wonder what part of Wine is supposed to register DLLs (i.e. installer, on first run, or what?) and figure out why it never happened here.