Blog

SwiftShader on Windows 98

28 October 2018

SwiftShader was a commercial product that emulated a 3D graphics accelerator. Programs that required one could now run entirely in software, as long as you had the CPU power to run both the program and SwiftShader. In practice, this worked better than it sounds. A single-threaded program could run on one CPU core, while SwiftShader could run on any other cores. It also used highly optimized code and SSE instructions to help make it faster.

The company was acquired by Google, and the source code to SwiftShader was made available under the Apache license. It is being actively developed to this day, although there is a lot more work towards OpenGL support than Direct3D.

So. What's my interest in this? I have a game that only works properly on Windows 9x. I wanted to see if there was a way to emulate a 3D graphics accelerator within a virtual machine, so that I could play the game as it was intended. The first versions of SwiftShader were Windows 98 compatible, and it was still listed as supported in the readme files.

The first port of call was to get my hands on the old 3.0.3383 demo (dated 2010-10-27). It still stated Windows 98SE compatibility, so I thought I'd try it out. It did not load. I am skeptical that 98SE support was tested because there are several missing dependencies and missing APIs. Looking at the DLL in dependency walker I can see that it was built using Visual Studio 2010, and that compiler targets Windows XP or later.

Screenshot of Dependency Walker on Windows 98.

Building It

Since the program is now open source, I wanted to see if it was possible to build myself a 9x compatible version. The earliest code available is for version 3.0.3689 (dated 2011-10-06). I also needed:

- Visual Studio 2005 compilers (last version that supports 9x as a target)

- Platform SDK February 2003 (last version for 95+ development)

- DirectX SDK December 2006 (last version that supports 98SE)

- Visual Studio 2010 (to open the solution file)

I set the toolset to 8.0 (VS2005) accordingly within the solution, and built the program. It compiled without errors. I managed to eliminate some dependencies: PSAPI was only used to check for one specific program. One extra line of code worked around the winsock issue. dbghelp.dll can be delay loaded. CreateThread needed a threadID variable for Windows 9x. Eventually, my build contained no unresolved dependencies on Windows 98SE, at least not according to dependency walker.

I tried my build on Windows 2000, and it worked fine. But on 98SE... the host program crashed. Argh.

Time To Cheat

I couldn't work out what was causing the crash, even though I had the exact location (somewhere within the statically linked CRT library, but not recognised by IDA). It's quite difficult to debug something that only crashes on 98 and not on NT-based systems, where the compiler and tools are. So I decided to give up on a completely native build, and install KernelEx.

KernelEx extends the Windows 98SE & Me kernel with some APIs that are normally found on NT. It also works around some compatibility issues. In this case, applying KernelEx to the SwiftShader DLL allowed it to run at last.

Screenshot of Text3D.

Text3D sample program from the DirectX SDK using SwiftShader.

How To Use SwiftShader

To make SwiftShader work with a given program, you simply place the DLL in the same directory as the program. When initializing Direct3D, Windows will normally load the necessary DLLs from the SYSTEM (9x) or SYSTEM32 folder. However, the SwiftShader DLL will be found first and insert itself between the real D3D and the program. This is the same method used by D3DSpy within the DirectX SDK tools.

Conclusions

Did it work with my game? No. Unfortunately it does not use DirectX 9 - it uses 6.1. Before this, I always thought the same library file was used and extended for each version of DirectX. This was effectively the case between the early versions up to 7.0, but 8 and 9 have their own.

The program might still come in handy, and I may come back to this in the future. Also, in the current sources of SwiftShader (4.1) there is also a library that works with Direct3D 8. It can be built for Windows XP through Visual Studio 2017 with the XP toolchain.

Return to Blog Index