Getting MS-DOS games to run on Windows 95: Virtual memory


A lot of games of the pre-Windows 95 era use so-called MS-DOS Extenders, which are libraries that provide a protected-mode environment to MS-DOS applications. The application is technically two programs glued together: The first program is the MS-DOS Extender itself, also known as the server, and the second program is the game that is a client of the MS-DOS Extender.

The interface that the client uses to talk to the extender takes a variety of forms. There were a handful of extenders that made up their own interface from scratch, but most extenders implement either the VCPI or DPMI interface. The main difference that mattered to me is that VCPI gives the application full control of the CPU at ring zero, which means that it cannot coexist with any other operating system. DPMI is a much friendlier interface to a host operating system, since it allows the host operating system to remain in control while still granting the client access to protected mode.

One nice feature of the DPMI extenders is that when they start up, they look to see if they are already running inside a DPMI extender. If so, then the extender shuts itself off and allows the client to talk directly to the existing DPMI extender. (In the case of a program running inside an MS-DOS virtual machine created by Windows, the existing DPMI extender is the Windows virtual machine manager.)

Now things get interesting: The client application was written with the assumption that it is using the MS-DOS extender that is included with the application, but in reality it is talking to the DPMI host that comes with Windows. The fact that programs seem to run mostly okay in spite of running under a foreign extender is either completely astonishing or totally obvious, depending on your point of view. It's completely astonishing because, well, you're taking a program written to be run in one environment, and running it in a different environment. Or it's totally obvious because they are using the same DPMI interface, and as long as the interface has the same behavior, then naturally the program will continue to work, because that's why we have interfaces!

In practice, the issues that arose with running under Windows DPMI instead of the built-in extender's DPMI fell into a few categories, all due to differences between the implementations, despite both adhering to the documented interface.¹

One is virtual memory.

The built-in extender didn't implement virtual memory, and client applications often use programming techniques that don't work well in a virtual memory environment.

Virtual memory introduced latency that applications hadn't been designed for. They would allocate memory and put an interrupt handler in it. This works fine if there is no virtual memory, but once you enable virtual memory, the memory for the interrupt handler might get paged out, and then bad things would happen, usually race conditions.

A more common programming pattern that falls down in the face of virtual memory is an application that simply allocates all the memory in the system and adds it to a memory pool. (As a bonus, the applications often initialize the memory as it was allocated.) If you have virtual memory, the client application can go a very long time before it runs out of memory because each "memory" allocation is really a disk allocation. This typically manifested itself by the application taking a long time to start up, accompanied by heavy disk activity as the operating system swapped out tons of pages until you ran out of disk space.

As I recall, we fixed this by setting a default policy for MS-DOS applications to limit EMS and XMS memory usage to the actual amount of physical RAM installed in the computer. (The DPMI memory quota defaulted to 8MB or a little bit less than physical memory, whichever is lower.) That way, these programs that try to allocate all the memory in the system would give up before the swap file spiraled out of control. This was the setting known as Auto in the memory properties page.

Bonus chatter: There was one program that not only allocated all the memory in the system and added it to a memory pool. Later during the execution of the program, it would ask for still more memory, and if the call succeeded, the program crashed!

¹These issues were called out in the DPMI documentation, but since the applications assumed that they were running under their built-in extender, they figured that the warnings in the DPMI documentation didn't apply to them. It never occurred to them that their preferred DPMI extender would not actually be the one in charge.

Comments (18)
  1. DWalker says:

    I remember EMS and XMS memory! Good times.

  2. DWalker says:

    I remember EMS and XMS memory! Good times.

    1. AK says:

      Oh yeah, separate versions of CONFIG.SYS for different combinations and parameters of HIMEM.SYS and EMM386.EXE. Good times…!

  3. Yukkuri says:

    > Later during the execution of the program, it would ask for still more memory, and if the call succeeded, the program crashed!

    I asked for the world, yes. But I didn’t expect you to actually give it to me!

  4. Yukkuri says:

    > Later during the execution of the program, it would ask for still more memory, and if the call succeeded, the program crashed!

    I asked for the world, yes. But I didn’t expect you to actually give it to me!

  5. Joshua says:

    Well sometimes you can do your job too good.

    There was this guy who tried to run our motor exercise management software on Windows 95 instead of DOS like he should have. Unfortunately, while the software does run, the hard-realtime hardware management loop is no longer realtime. That guy was seriously risking a broken arm. No version of Windows was authorized for a reason.

  6. Not strictly relevant to the Windows DPMI implementation, but in terms of DPMI implementation “issues”…

    Way back when, I was greatly enjoying the original Grand Theft Auto (which actually came in two versions, one for DOS, and one for Windows 95). The DOS version (which I preferred; it was slightly faster) shipped with the DOS/4GW extender.

    At one point, I upgraded the memory in my PC and suddenly GTA wouldn’t run any more. If I took half the memory out, it ran fine. I started digging into the release notes for DOS4GW to see if there was a recent patch that might fix my problem. One of the items was something along the lines of “increased maximum supported virtual memory to 64MB”.

    “Hmmm”, says I, and I drop them an email: “What if I’ve got 64MB of *physical* memory?”. A little while later, comes the sheepish reply: “Ah. We didn’t test that…”.

    Cue me feeling slightly smug that I had more memory than the people who wrote the DOS extenders for some of my favourite games…

  7. Not strictly relevant to the Windows DPMI implementation, but in terms of DPMI implementation “issues”… Way back when, I was greatly enjoying the original Grand Theft Auto (which actually came in two versions, one for DOS, and one for Windows 95). The DOS version (which I preferred; it was slightly faster) shipped with the DOS/4GW extender. At one point, I upgraded the memory in my PC and suddenly GTA wouldn’t run any more. If I took half the memory out, it ran fine. I started digging into the release notes for DOS4GW to see if there was a recent patch that might fix my problem. One of the items was something along the lines of “increased maximum supported virtual memory to 64MB”. “Hmmm”, says I, and I drop them an email: “What if I’ve got 64MB of *physical* memory?”. A little while later, comes the sheepish reply: “Ah. We didn’t test that…”. Cue me feeling slightly smug that I had more memory than the people who wrote the DOS extenders for some of my favourite games…

  8. Yuhong Bao says:

    I think most of the time for games it was a *deliberate decision* to only support running under pure DOS. Of course, if MS and IBM actually worked together and OS/2 2.x actually replaced DOS/Windows, it is unlikely that DOS gaming would last as long as it did.

    1. Scarlet Manuka says:

      You’re probably right; supporting running under Windows would have meant a lot of extra support work compared to just telling people how to make a DOS mode boot floppy which loaded minimal extra stuff, which was the option most games of the time took.

      I did prefer to boot to real DOS rather than using MS-DOS Mode from Windows for playing DOS games. Some games were fine in MS-DOS mode but many had subtle issues – I forget the details, though I suspect sound was involved in a lot of them. It was easier just to boot to DOS with an appropriate config. (I had five configs defined – four DOS ones depending on whether we wanted CD and/or EMS drivers loaded, and one for Windows which was similar to the no CD, no EMS one but ran Windows in the autoexec. The tricky part was that my soundcard needed EMS for one of its emulation modes, so if I was running without EMS and wanted to play a game that was set up for that mode, I’d have to reboot and change configs.)

      I kept doing that until I finally abandoned Win98 for XP and started using DOSBox. Of course by that time I also didn’t have the soundcard with the complicated behaviour.

      1. Yuhong Bao says:

        “MS-DOS mode” is real DOS, and Win9x did ship with EMM386.

        1. Scarlet Manuka says:

          Sorry, you’re right about MS-DOS Mode, I misspoke; I was thinking more of running DOS applications within Windows (though I did have the impression that there were still a few problems I encountered with MS-DOS Mode, but I could easily be mistaken there). I did avoid using MS-DOS Mode as well, but that was mainly for the convenience – easier to boot into plain DOS, rebooting as necessary to change configs, than to boot into Windows and then reboot into MS-DOS Mode.

          I’m not sure what your point is about Win9x and EMM386. I never claimed otherwise, it’s just that for some games you had to really squeeze out every bit of conventional memory possible. (Loading as much you could into the HMA helped a lot.) I think some of them also required EMS not to be running, but it’s been long enough ago that I don’t remember exactly.

    2. smf says:

      “Of course, if MS and IBM actually worked together and OS/2 2.x actually replaced DOS/Windows, it is unlikely that DOS gaming would last as long as it did.”

      Even XP had an improved DOS emulation to persuade people to switch from Windows 98. So I doubt it would have made much difference.

  9. Neil says:

    I remember one application that originally used a VCPI extender, so under Windows you had to run the 80286 version (which used EMS) instead. The application was later bought by Microsoft, and the next version used a DPMI extender. Sadly we didn’t discover the magic setting that limited the memory to the amount of physical RAM so we had to fake it by minimising the size of the page file.

  10. Darran Rowe says:

    Raymond: is your post running late today?

  11. Ivan K says:

    Growing older I think I missed the transition zone between using a boot disk vs. Dos from win95. DirectX (3, then 5) was the thing killed dos mode and made Win95 and beyond a gaming platform for me. The first pc I ever bought with my own money was a win95 machine, and seeing it run “the game” in DirextX vs Dos made my dos boot disks bitrot.

  12. Dave Oldcorn says:

    >These issues were called out in the DPMI documentation, but since the applications assumed that they were running under their built-in extender, they figured that the warnings in the DPMI documentation didn’t apply to them.
    If you had the DPMI documentation… most of us just had whatever documentation came with Watcom for DOS/4GW, which if I remember right wasn’t much, and this was in the very nascent days of the internet, when ‘standard’ specs were a bit harder to come by. And that’s if you even used DPMI memory management explicitly rather than relying on the compiler’s malloc. (I didn’t. I did use the interrupt management capabilities, for sound cards, but that was about it when it came to explicitly talking to DPMI).

    I was rather surprised when I dug later on and found a lot more DPMI existed than DOS/4GW supported. I’m not sure if the game had already shipped by that point…

  13. Yuhong Bao says:

    This also reminds me of real mode paging where hardware interrupt handlers has to be page locked.

Comments are closed.

Skip to main content