The OS/2 Museum has made available the first version of a display driver disk for Windows 9x running on VirtualBox. The driver uses a linear framebuffer and supports 8/16/24/32bpp modes with resolutions up to 1920×1200 pixels (see more below). The driver is not accelerated but tends to be very speedy on modern hardware.
I’d like to say that it was easy to adapt the existing Windows NT video miniport driver for Windows 9x… but of course it wasn’t. The Windows 9x display driver model is completely different and has nothing in common with NT. The Windows 9x display driver has much more in common with Windows 3.1 (and 3.0 and 2.x) drivers, and it has clearly directly evolved from those older drivers.
So what makes it a “minidriver”? A Windows 2.x/3.x display driver has to implement a very significant chunk of GDI. Bit blits, lines, text output. There is a lot of cases to handle and a great deal of complexity. To give some sense of the complexity, the Windows 3.1 DDK sample driver for Video 7 cards is about 1.6 MB (circa 60,000 lines) of assembler source code. And that’s just for 8bpp displays.
Windows 9x drivers still have to do all that. The difference is that Windows 95 introduced the “DIB Engine”, a large library that implements more or less all of GDI and that the display driver can “punt” to. The minidriver has to set modes and implement various housekeeping tasks, but all drawing can be handled by the DIB Engine. The minidriver can implement what it can do better than the DIB Engine, but doesn’t have to.
The DIB Engine in Windows 95 (DIBENG.DLL) is very similar to the DIB Engine that Microsoft released in September 1994 as part of WinG (WINGDE.DLL). I do not know the exact timeline and history. The WinG DIB Engine was designed to draw to memory bitmaps using GDI. DIBENG.DLL does exactly the same thing, but takes the idea one step further by making the video framebuffer itself a memory bitmap, optionally using the VFlatD VxD to present a bank-switched graphics card as a linear framebuffer.
The exact history of the WinG and Windows 95 DIB Engine is unclear. WinG was released in September 1994, when Windows 95 was already well underway. It is possible that the DIB Engine was planned for Windows 95 and repurposed for WinG—which also ran on Windows 3.1 and NT 3.5. Or perhaps the DIB Engine was first written for WinG and then adopted for Windows 95.
Minidriver in C
The OS/2 Museum Win9x minidriver is written almost completely in C (using Open Watcom C/C++), in part to show that not only it can be done, but it isn’t even too difficult, and the code is significantly easier to understand than the all-assembly DDK sample code.
Writing the driver in C was mildly challenging. The biggest challenge was the fact that the Windows 9x display driver is a 16-bit driver, which means it has to deal with segmentation. That’s actually something which is easier to deal with in C, because the C compiler provides a lot more sanity checks than assembler can.
A somewhat nastier problem was that although the Windows DDK documents all the functions which the driver needs to implement and the DIB Engine functions it can call, the DDK does not provide prototypes for those functions. Although the documentation does pretend to list the prototypes, it often omits return types, more or less always omits the calling convention, and sometimes is a bit sloppy with argument types.
I spent a good deal of time trying to figure out why the
CreateDIBPDevice function was failing. I kept looking for bugs in my initialization code, but in the end I discovered that even though
CreateDIBPDevice is a 16-bit function, it returns a 32-bit value not in the DX:AX register pair but rather in the EAX register. The Windows 95 DDK completely fails to mention this non-obvious yet crucial detail; I found it “documented” in U.S. Patent 6,525,743.
The driver also implements and calls a couple of undocumented functions. One of the functions it calls is
AllocCStoDSAlias, which Microsoft’s KB Article Q67165 admits is used in the Windows 3.0 DDK but says it “will not be supported in future versions of Windows”. In reality it was of course supported all the way to Windows Me…
While the Windows DDK sample drivers are all hardcoded to support a small set of resolutions, the OS/2 Museum minidriver is not. It restricts the smallest resolution to 640×480 but not much beyond that. The maximum allowed is 5,120×3,840 pixels, but that is entirely untested.
The supplied .INF files sets up common resolutions up to 1,920×1,200 pixels, but users can edit the .INF file (or Registry) and add their own resolutions. Note that Windows 9x likely will have trouble if there are “too many” modes listed, and it is unknown what the highest resolution might be before funny things start happening.
The driver can be installed through the Display Properties dialog or through the Device Manager; the method used should not matter.
The driver works on Windows 95, Windows 98, and Windows Me. No attempt has been made to discover how far back it might work with Windows 95 betas.