The popularity of DOS/4GW made Windows 95 game compatibility a little easier, but with higher stakes

Raymond Chen

By far, the most popular so-called DOS Extender in the early 1990’s was DOS/4GW. MS-DOS game compatibility occupied a very large portion of my time during Windows 95 development, so I saw a lot of DOS Extender banners, most frequently the DOS/4GW banner.

Now, you might wonder, “How did these games even run in Windows 95 if they came with a DOS Extender? Wouldn’t the extender try to enter protected mode and fail, because Windows was already managing protected mode?”

The trick is that these extenders were really two programs bundled together. One was a protected mode server, and the other was a protected mode client library.

In the beginning, there was the Virtual Control Program Interface (VCPI), which was supported by expanded memory managers like EMM386. These expanded memory managers barely used protected mode at all: The only thing they cared about was getting access to memory above the 1MB boundary, so they set up some page tables in order to map extended memory into the expanded memory page frame, but did no other virtualization. MS-DOS ran in a virtual machine that had full hardware access, and the VCPI interface let an MS-DOS application say, “Hey, I’d like to take over complete control of the system now,” and VCPI would say “Sure, no problem!”

The VCPI interface quickly faded in popularity because no protected mode operating system (like Windows 3.0 in enhanced mode) would let any program take over complete control of the system. You would basically be suspending the old operating system in order to let the MS-DOS program take over as its own new custom operating system. Windows 3.0 introduced a new interface called the DOS Protected Mode Interface (DPMI) which let MS-DOS programs request that their code execute in protected mode, but only in user mode. The DPMI provider remained in control of kernel mode.

Okay, so back to DOS/4GW. When it started up, the DOS/4GW extender looked around to see if a DPMI server was already running. If not, then it installed itself as the DPMI server. But if a DPMI server was already running, then it allowed that DPMI server to remain in charge.

The game communicated only with the DPMI client portion of the library, which it used to transition to 32-bit mode, allocate memory, and do all those 32-bit things that these 32-bit game wanted to 32-bit do.

In other words, we have the following block diagram:

  Inside Windows       Standalone
DPMI server
(ring 0)
Windows       DOS/4GW
DPMI Server
    ⤡   ⤢  
DPMI client
(ring 3)
    DOS/4GW
DPMI Client
   
      ⇅    
Game code
(ring 3)
    Game    

Both Windows and the DOS/4GW DPMI server implement the DPMI interface, so the DOS/4GW DPMI client used standard DPMI calls to communicate with both servers.

This was great for application compatibility, because if there was some issue with how the DOS/4GW client communicated with the DOS/4GW server, we just had to fix it once, and it fixed a lot of games. On the other hand, if the issue couldn’t be fixed, it broke a lot of games.

High risk, high reward.

Miraculously, most games just worked despite running under a different DPMI server from what they were originally developed with. There were occasional issues with specific games. Popular ones include games which assumed that all memory was physical and games which assumed the interrupt flag was unvirtualized, but for the most part, things worked well enough that the remaining issues could be treated as app-specific bugs.

10 comments

Discussion is closed. Login to edit/delete existing comments.

  • Stewart Shearer 0

    This has stirred an ancient memory for me: Around the time of the Windows 95 release, there was some sort of library / backport (?) that allowed some Windows 95 software to run on Windows 3.11. Does this ring any bells?

    • Marek Knápek 0

      That’s Win32s.

    • Sunil Joshi 0

      I think you’re speaking of Win32S. This was a product which allowed some Windows NT3.1 software to run on Windows 3.11. It supported a limited subset of the Win32 API.

    • Stewart Shearer 0

      Ah, thanks Marek & Sunil; you’re right!
      https://en.wikipedia.org/wiki/Win32s

      I remember Space Cadet being able to run, as well as Photoshop 4(?).

    • Georg Rottensteiner 0

      Win32s was a nifty library, together with WinG it was used for quite a bunch of early Windows games.

      And backwards compatibility with it rocks! Games I’ve written for Win 3.11 with Win32s still run flawlessly in Windows 11.

    • Almighty Toomre 0

      My own Win32 memory as a programmer: I was porting a large statistics program that had originally be written to run on computers like the PDP-11 and various Unix boxes over to the Windows 3.1 platform using Win32s as our 32-bit solution. The program had a clever scheme so that it could deal with very large data tables on very low memory machines: we would automatically move data between disk and memory buffers as needed. We also supported “temporary” tables that would try to stay in-memory if possible, but would be flushed to disk if needed. The temporary tables had a defined file name which might or might not get used.

      The problem was how we determined if a table had ever been written to disk: we would attempt to delete the table with an “unlink” (delete) and then we’d check the return code. The return code on unix is clearly defined: unlinking a non-existing file should return error (and set the error to ENOENT, IIRC). But on Win32s this would return success (on the grounds that the file is as deleted as it can be, maybe?)

      The result was a slow-motion catastrophe: the internals table-buffer management code would be all confused and start returning bad data. On every failure on Win 3.1, the result was a completely wedged machine; we had to reboot to get working again.

      Debugging took a week and was eventually solved only because we did a parallel debug: stepping through code on Windows 3.1 (which failed) and Windows NT (which worked) to see where the code paths diverged.

      The good news is that the problem was detected by our “systemtest()” function that did a complete analysis of the entire system.

  • Damon Chitsaz 0

    I remember being in my early teens, desperately looking for Whatcom compiler just to have that 4GW/DOS banner above my simple C programs. Thanks for shedding some light on this and bringing ol memories back!

  • Neil Rashbrook 0

    I remember an application that was changed from VCPI in its 2.0 edition to DPMI in its 2.5 DOS edition, and also had a 2.5 Windows edition. The VCPI version obviously wouldn’t run under Windows, so you had to use the EMS version instead, which was limited by the PIF to a reasonable amount of EMS memory. But the DPMI version completely ignored the PIF settings and allocated all the rest of your virtual memory. The only way to get it to run reasonably seemed to be to reduce the amount of virtual memory you had. Or preferably switch to the Windows edition, but that wasn’t always possible given the circumstances.

Feedback usabilla icon