Antique Display Driving

Here’s a preview of something I’ve been slowly working on, bit by bit:

Windows 1.04 Reversi

That screenshot surely looks a little funny. That’s because it is Windows 1.04 running with a heavily modified 256-color Windows 3.x display driver, using resources from a Windows 2.0 VGA driver.

This is mostly the same driver, running real-mode Windows 3.0:

High-res Real Mode Windows 3.0

This is the same driver breaking Microsoft’s DDTest utility in Windows 3.1. DDTest is meant to assess performance of Windows 3.x display drivers, but it can’t handle the speed:

Too fast to be considered fast?

DDTest is a little bit buggy and if the display is too fast, it thinks the performance is “poor”.

For good measure, this is again mostly the same driver, running Windows 2.11 and using 8514/A style big fonts (and icons, bitmaps, and cursors).

Windows 2.11 fonts

How did I get there? I started with the 256-color Video 7 driver from the Windows 3.1 DDK. I threw out all the Video 7 specific hardware rendering code and replaced the mode setting logic with code that runs on VirtualBox. The driver is thus a sort of ancestor of the Windows 9x video minidriver.

I had to fix a couple of extremely nasty problems that probably didn’t show up with Video 7 hardware, or at least not usually, but popped up when the generic software rendering was used.

One of the bugs had to do with drawing patterned lines and manifested itself by leaving behind very visible trails when dragging window outlines around. That bug probably would have been seen with the original driver when rendering into memory bitmaps, but without the frequent XOR redraws it would have been extremely difficult to spot.

Another bug was related to software cursor drawing, and again was probably unlikely to trigger with Video 7 hardware because the hardware cursor would have been used more or less all the time.

I also extended the resolution support to go beyond 1024×768 (limit of the original Video 7 driver) up to somewhere around 2048×1536. Note that the driver supports strictly 8 bpp only. Different color depths would require different rendering code.

Once Windows 3.1 worked to my satisfaction, I made a few minor tweaks for the driver to run with Windows 3.0. The changes were very small and the biggest issue were the driver resources. For some reason I still don’t understand, Windows 3.0 failed to load the OEMBIN FONT resource, which caused very interesting failures with fonts.

I also switched around the bitmap, cursor, and icon resources so that Windows 3.0 would use the smaller “96 DPI” variants. Windows 3.1 supports multi-DPI drivers and the driver can tell Windows which resources to use through the GetDriverResourceID callback. The same binary can run on both Windows 3.0 and 3.1, but on Windows 3.0 the resources are fixed and can’t be adjusted at run-time.

Then I thought, hmm, what would it take to get the driver to run on Windows 2.x? That was a bit more work. It required dropping all APIs that were added in Windows 3.0 to support protected mode: AllocSelector and FreeSelector, AllocCSToDSAlias, PrestoChangeoSelector, and more.

However, the GDI rendering functionality remained more or less completely unchanged. That is, GDI in Windows 3.x is strictly a superset of Windows 2.x GDI, with more capabilities (such as palette manager support, transparent blits, etc.) but no changes to existing functionality.

There was again work needed on resources: Microsoft significantly changed the resource format between Windows 2.x and 3.0. Annoyingly, resource compilers and other tools designed for Windows 3.x can’t work with Windows 2.x resources at all. The resource compiler for Windows 2.x has to be used. But that is not an insurmountable problem, and the driver works with Windows 2.x reasonably well.

And then I thought, what the heck, can I make it work on Windows 1.x as well? The answer is yes, but… it was a lot of work. Windows 1.x GDI is again mostly a reduced subset of Windows 2.x GDI, with one big exception: Fonts.

As it turns out, Microsoft significantly reworked the font format between Windows 1.0 and 2.0. In Windows 1.0, all characters are effectively stored in a single wide bitmap, tightly packed together. In Windows 2.0, each character is stored separately, and in column-first (rather than row-first) order. To make matters more fun, the Windows 2.0 SDK documentation is completely wrong and describes the font format incorrectly; it notes that the font format was changed from Windows 1.0, but claims that character bitmaps are stored row by row, when in reality it’s column by column. The Windows 2.1 SDK documentation was corrected and no longer lies (or at least not as much).

The Windows 2.0 font format is easier for the driver to work with, although it is less memory efficient. As an aside, Windows 3.0 introduced yet another font format, though only in protected mode. The 3.0 font format is very similar to the 2.0 format but uses 32-bit pointers, and is thus not limited to 64KB. I assume that with the advent of ATM and later TrueType, combined with higher display resolutions, the 64KB font limitation became too much of a problem.

At any rate, reworking the driver to support Windows 1.0 fonts was quite difficult and is not fully finished yet. The font code in the driver is extremely complicated, with lots of special cases and many parts of code accessing the font data, sometimes in not very obvious ways.

Here’s a screenshot of Write, showing occasional clipping problems at the ends of lines:

Windows 1.04 Write, nearly working

It’s not perfect but it is mostly working. So far I made no attempt to use Windows 1.x style resources for the driver, which is why it looks a bit like Windows 2.0.

In the process, I learned to use WDEB386 and SYMDEB (they’re very similar but sometimes weirdly different), and I learned to both appreciate and dislike complex MASM macros that the driver uses a lot.

All in all, an interesting adventure in retro development.

Update: Below is more or less the same screenshot of Write in Windows 1.04 as above, but now using the aggressively cheerful Windows 1.0 colors and the default window decorations:

Write in default Windows 1.0 colors

Later Update: Below is the PALETTE.EXE demo running on Windows 1.04. It uses dithering to display most colors, but with the relatively high resolution it works okay. I believe the driver does not try very hard to use a large palette of physical colors, given that it’s meant to be used with Windows 3.1 which has the palette manager. That could probably be changed.

Palette demo on Windows 1.04
This entry was posted in Development, Microsoft, Windows. Bookmark the permalink.

14 Responses to Antique Display Driving

  1. Richard Wells says:

    Congratulations of getting Windows running at higher numbers of colors. How slow is the repainting of uncovered regions?

  2. Michal Necasek says:

    It’s not slow at all. Of course I’m running this on hardware that’s many orders of magnitude faster than what was available in Windows 1.x/2.x/3.x days. The bank switching slows things down but it’s not bad. A linear framebuffer would be faster but getting that working in real-mode Windows would have been far too ugly. Not impossible, just too nasty and complex for the expected payoff.

  3. JRD says:

    What, a 256-color driver, and no screenshots of PALETTE.EXE? 🙂

    More seriously, I’d be interested in the source when you’re finished, especially on the difference between 1.x and 2.x. Because I’ve been playing with the Tandy 2000 version of Windows 1 in MAME emulation, and I’ve been curious what Windows 2.x on the T2000 would have been like. Tandy only wrote T2000 drivers for 1.x. and 1.x drivers don’t work on Win 2.x. It would be a lot of work to convert because all of the drivers, not just Display, would have to be custom-converted from 1.x to 2.x (and assuming it would still run on the custom T2000 DOS 2.11 ), but it’s a neat goal to try for.

    The Tandy 2000 display introduced shared color-planes memory layout before the EGA did, plus the memory map is high up so you get more memory for Windows than a PC can give you.

  4. Spiral says:

    Thirty years ago my old man bought an IBM XT back from work – they were chucking them out and he liberated it from the skip. We upgraded it with an 8-bit VGA card (Paradise, I think it was), then after upping the RAM to the full 640K I managed to get a copy of Windows 3.0 from the small ads in the local newspaper (no eBay back then!)

    Much to my annoyance, it would only display in mono. I had been expecting the same 16 colours that we had on our RM Nimbus 186 PCs at school and it looked kind of crummy in just black and white – no 3D effects on the GUI buttons, for example. Attempting to switch to colour VGA just locked things up every time.

    It was only decades later that I read the reason was the colour VGA driver for Windows 3.0 used 186 opcodes, hence it would never have worked on an XT.

    If only I had this driver back then! Mind you, Windows 3.0 was s-l-o-w on that 4.77MHz 8088 chip – you could actually see the GUI elements pop up in sequence when a dialog box was being shown, for example.

  5. Michal Necasek says:

    I’ve never seen Windows 3.0 on an XT class machine but from people who have, I heard that it was not a pleasant experience. XTs were on the way out at the time, but quite a few were still in service.

  6. Yuhong Bao says:

    I wonder why Wes Cherry only got an XT for the work on Solitaire.

  7. Michal Necasek says:

    Because he was an intern. They probably said “hey, we want to make sure it still runs (crawls) on an XT”.

  8. Yuhong Bao says:

    Admittingly there was a DRAM shortage at the time, but protected mode Windows is very different from real mode.

  9. Peter Hoeg says:

    I’m absolutely going to add “aggressively cheerful” to my vocabulary.

  10. Michal Necasek says:

    I added a screenshot of PALETTE.EXE. It uses dithering, I didn’t investigate how the driver could use more solid colors (I am pretty sure it could).

  11. Darkhog says:

    I wonder how Win 1.x would look on an 1080p widescreen display resolution. Since it is in the range supported by that driver. Probably the UI would be absolutely tiny and stretched, but by how much?

  12. Richard Wells says:

    Win 1.x should have no problems with 1080p if the driver was correctly implemented. The Moniterm Viking I had a resolution of 2048 by 960 and people paid $2600 to use that with Windows Pagemaker. That is close enough to 1920 by 1080 for indicating expectations.

    The major problem with Windows applications came later with a lot of Win 3 and 95 programs having dialog boxes carefully crafted for 640×480. With higher resolutions and larger fonts, list boxes had very few lines available. Describe doesn’t handle 1080p or higher resolutions very well.

    Performance of Windows on an XT was fairly good. Excel came close to matching Lotus 1-2-3 2.x on the same hardware. Without EMS, the system was largely single tasking. The whole floppy only Windows was a massive waste of development time. The reason turbo XTs didn’t see Windows too often was the overall expense of the system. Plug in a good video system and respectable hard drive and a turbo AT offered twice the performance for a 10% increase in cost.

  13. John Elliott says:

    When I got the IM-1024 emulation in PCEM working enough to run the Windows 1 driver, I found that it used 8-bit truecolour (rrrgggbb) rather than dithering (example screenshot: Interesting to see another (and more widely applicable) take on Windows 1 in 256 colours.

  14. Michal Necasek says:

    Very interesting. What are those fonts? Something VMI shipped with their drivers? Just curious because Windows 1.x does not even come with any fonts designed for square pixels. I could borrow fonts from Windows 2.x though, with a bit of conversion work.

Leave a Reply

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.