Saturday, January 29, 2011

Old Game Shenanigans - Getting Silver to work


This time the topic will be a bit different from the other stuff I wrote about and a little bit unusual. It's about games. Old games. Good old games. No not Gog.com in particular (though some titles might have been picked up by them). I will talk about Silver today, though some ideas I'll present can work for other games as well.

What's so special about Silver, you may ask. Nothing particular really, it's just an old game I remember playing some 10 years back. Back then I wasn't able to finish it and generally I have good memories of it and wanted to play it again. That doesn't work in a lot of cases though. Silver was written for the DirectDraw API under Win9x, which was the status quo back when the game was under development. When looking at PC gaming I'd generally consider Windows platforms. That's where the mainstream goes and that’s usually the target platform of the developer.

On the Windows platform happened alot since then. Win9x went EOL a long time ago and anyone running these OSes nowadays for anything else than old application compatibility would be considered strange. Since games transitioned to 3D they mostly use Direct3D which is available since DirectX 2, however serious 3D only started to crop up circa DirectX 6/7 (where Microsoft expanded the feature set tremendously). There were some 3D games before that, which partly used other APIs (e.g. Glide), though thats not the topic of this blog. Since then Direct3D evolved, most notably by providing programmability starting with DirectX 8. The programmability features have since then evolved considerably. Currently DirectX 11 is state of the art which added support for general purpose programmability.

The reason I'm writing this is that I'd like to state that Silver uses an ancient graphics API that's been obsoleted a couple of times already. For backwards compatibility it still exist. However there is more to it. While Microsoft provides the APIs, the graphics driver has to implement the respective backends for the API calls. These backends obviously differ from manufacturer. This is exactly the reason, why some games work without problem on hardware from vendor A, but produce glitches on vendor B. Due to DirectDraw being an ancient API, it's still supported in current drivers, however not very well supported since basically no one cares anymore. That's the situation on WinXP. Since Microsoft changed the driver model in Windows Vista and subsequent versions the situation is quite different here. In WDDM there is no DirectDraw implementation in the graphics driver anymore. Microsoft solved the compatibility issue with a software DirectDraw implementation which probably uses Direct2D/3D calls, though that's an assumption on my part. I will explain later, in which way this will affect us.

So how to get it to work? Basically there can be a lot of problems, though I've found a way around most of them. First you should obviously install it. I wasn't able to set it up to run without CDs, although I copied over the contents of the 2nd CD to the harddisk. So I created ISO images which I can mount with Daemon Tools Lite. Note that even when the game requests a CD change this will work with Alt-tabbing out of the game, switching the image, then tabbing back. Sometimes it's required to hit ENTER and the game will continue. Rarely it will crash but often the crash won't happen a second time. After installing the most important thing would be to install the GeForce / Radeon patch. It's required to run it on anything considered a current video card. Since the support sites for Silver are not available anymore, I decided to upload the files to Dropbox and make them available for you. Just pick the correct version for your release:

In some cases Silver wouldn't start or would crash starting a game. In this case, it's most probably the fault of DEP, a security feature which prevents the execution of non-executable memory pages. Back when Silver was current, this feature wasn't present and it wasn't even possible to mark memory pages as executable until Windows 2000 as the VirtualProtect API documentation explains. For most people this won't actually be a problem, since the default setting for DEP is to be active for windows services and programs only (newer applications can set a bit in the PE header to explicitly request the activation of DEP). However, it's possible to enable DEP for all programs, which personally I'd recommend for security reasons. Whenever a program acts up because of this, it's required to define an exception though, which is rather easily done in the (extended) System properties.

Ok now without DEP standing in the way the game runs. Though there might be additional problems, like the sound stuttering like hell or various display glitches and some crashes at certain positions in the game. First up is sound, still it's a problem you will notice in the main menu already. I have encountered this problem on various computers, so it's not an isolated problem. So I tried to find the reason for it. You have to know that Silver uses the rather popular Miles Sound System API for anything sound-related. This can be confirmed by the presence of mss32.dll in the Silver directory. However the version shipped with Silver is really ancient (5.0e released on 01.01.1999). The nice thing about DLLs is, that unless the API is changed, in most cases you can replace it with a newer version and it will work nonetheless including bugfixes introduced by the newer version.

So I started playing around and replaced it by mss32.dll files from other, more recent games. Whenever I replaced it I tried to run Silver. If the DLL was too recent, meaning the API was changed, Silver would crash right at the start because it couldn't find some imports. Still I was able to upgrade it with a newer version, the most recent version that works is 6.1c from 15.10.2001. In version 6.5a they “Dropped Win32s support (Win32 on Win16).“ according to the version history, so that probably explains why newer versions won't work. Once running with a version from the 6.0 release, the sound stuttering will be gone. To make things easier for you, I uploaded the newest version I could find to Dropbox (shamelessly taken from Gothic II 1.30 by the way):

This should fix most problems. There are a few more glitches though. On Windows XP, whenever you open the inventory summary, the game crashes with an access violation exception, when running on NVIDIA or ATI hardware. This alone wouldn't stop anyone from playing Silver, since the overview is not really required and the map can be displayed by pressing the M key. However relatively at the beginning after the scene at the Oracle where you get the map for the first time, the inventory screen will be automatically opened. This is not cancel-able and will lead to the aforementioned crash – this bug got the fitting name „Oracle bug“. Most people circumvented it by downloaded a savegame from right after this situation. I found another way to circumvent it on Windows XP. If you happen to own a computer including integrated graphics by Intel, this is probably the first time you will be amazed by its capabilities. On Intel IGP graphics the inventory works just fine and will not crash. So Intel probably has the cleaner DirectDraw implementation in their driver. To cover all bases I also uploaded an Oracle savegame to Dropbox:

On ATI hardware there might be another problem called the „lines glitch“. Basically you will have weird display of graphics, which is due to how the game renders its scenes. This problem is rather old and luckily some programmer wrote a little hack to fix it. For this you need the Silver Patcher. With this little tool, it's possible to patch the silver.exe file to change the rendering of the lines. Most forum posts on the Internet suggest to change it from 640 (default) to 1. However I found that patching it to 768 is the better solution, it will make some other scenes in the game work better than with a setting of 1 (notably the room at the end where you confront Silver, with the blood flow animation displaying correctly with a setting of 768). This can also help fix some color issues under Windows Vista/7 in the main menu.Your mileage may vary, so make a backup beforehand. To your conveniance the Silver Patcher can be downloaded via Dropbox as well:

When writing the blog I realized it would be nice to dig into newer Windows versions as well, since they have seen broad adoption by customers. On Windows Vista/7 the colors of the game will be way off unless the DirectDraw compatibility mode is correctly set up. On the Internet you will find instructions to run the game, kill explorer.exe and then the colors should be right. There are also scripts which run Silver, kill explorer.exe, wait for Silver to quit and run Explorer again. While these solutions work, they have a major drawback. You will lose all open folders which can be quite annoying. This is where the DirectDraw compatibility mode comes in. In the registry on Windows there is a key where compatibility settings can be defined. There is no GUI for that (setting compatibility for older Windows versions doesn't enable this), it needs to be done manually or through importing a reg file. I provide reg files for Silver, which were tested with the UK version. I don't know if the US version has the same DirectDraw application ID, so depending on that it might work or not. Feedback on that is appreciated as well.

If you want to define custom compatibility settings for other applications, basically you need to create a key under one of the following keys:

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\DirectDraw\Compatibility //for 32-bit Windows
HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\DirectDraw\Compatibility //for 64-bit Windows

The name of the key is not that important, but I suggest to use something that relates to the application. Then you add a "Name" string value with the filename of the executable. The "Flags" hex value needs to be present as well. The actual meaning of the flags value is not known, it's probably safe to set it to the same value that is used for all these compatibility profiles, that would be hex:00,08,00,00. The "ID" hex value is the tricky part. The easiest way to find it is running the game/app once and then checking the contents of one of the following keys: 

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\DirectDraw\MostRecentApplication //for 32-bit Windows
HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\DirectDraw\MostRecentApplication //for 64-bit Windows

When taking the ID from there, note that it's a DWORD value, so if you want to set the hex value correctly you need to reverse it (e.g. dword:36dfe6f7 becomes hex:f7,e6,df,36 in the case of Silver). Reportedly it's also possible to set it to a DWORD value in the compatibility profile, though I didn't try that. Greg put up a nice write-up of that process.

I only tested this with Windows 7, so I don't know if it works on Vista as well. Feedback is appreciated. Notably the inventory will work properly on Windows 7 even on ATI / NVIDIA hardware. I assume this is due to a change in the driver model, where in XPDM the graphics driver was responsible of providing a DirectDraw implementation, while in WDDM this is done by a wrapper API of Microsoft. I hopy my comprehensive writeup helped you getting Silver to run. There are lots of hassles but in my opinion the game is totally worth it. Have fun playing Silver. If you could put any of the tricks here to use on another game, I'd be happy to hear about it in the comments.