Updated 2019-04-10: Added mention of efforts to backport the open-sourced WINFILE.EXE code and a little more info on how to target Win32s with Free Pascal.

See Also: Resources for Reverse-Engineering 16-bit Applications for DOS and Win16 debuggers.

While I was poking around the web, looking for information on the most liberally licensed way to put together some utilities for the copies of MS-DOS 6.22 and Windows 3.11 for Workgroups on my retro-gaming PC, I ran across a thread on Computing.Net titled win3.x compatable compilers.

Now, given that it was opened in 2007 and the most recent post was as new as April of 2016, I though I might as well help to fill in the gaps in their knowledge but, much to my dismay, after creating a post (in Leafpad) and creating an account, it seems it’s been locked for being too old. (I can only assume the threshold is something more than 9 years and less than 10.)

…so I decided to post what I put together here instead, so it won’t go to waste.

Tip 1: Current versions of Open Watcom C/C++ can definitely be used to target Windows 3.x.

Not only have I successfully used it to cross-compile basic test binaries on Linux and then run them in Windows 3.11 for Workgroups under DOSBox, I found a Building Win16 GUI Applications in C tutorial which includes an OpenWatcom project file in its example code archive.

Beyond that, it also includes a “windows extender” called Win386, which is essentially a DPMI extender for Windows 3.x applications, providing both a 32-bit flat address space and API thunks to make it more comfortable to call the Win16 API from 32-bit code.

From a deployment standpoint, Win386 has the advantage that it gets bundled into your executable rather than being installed separately like Win32s, so users need never know it even exists. (In fact, for that exact reason, there’s not much information on the web about it today outside the Watcom documentation.)

Tip 1.5: A Single OpenWatcom Install Can Compile To All Targets

In the build.sh script I put together for generating test files in one of my projects, I generate .com , 16-bit DOS EXE, DOS/4GW EXE, OS/2 1.x, OS/2 2.x, Win16, Win386, Windows 95, and Windows NT binaries all from the same hello.c file using the same OpenWatcom install.

(Also note that the linked script cross-compiles using other compilers as well, such as DJGPP, and includes instruction on how to get prebuilt Linux cross-compile binaries for them.)

Tip 2: Open Watcom C/C++ is the same compiler used by many classic games.

Watcom C/C++ was used in quite a few applications back in the day, because they offered the best value for your money if you wanted to do 32-bit protected-mode development. (The compiler was competitively priced, it was known for producing the tightest code, and it came with royalty-free licenses for both a DPMI extender and a precursor to Win32s at no extra charge.)

I’ll go into more detail on all of that…

DOS/4GW

When DOS games like DOOM say “DOS/4GW Protected Mode Runtime” on startup (or don’t, but include a copy of DOS4GW.EXE ), that means they were compiled using Watcom C/C++ because DOS/4GW is the special Watcom bundle edition of DOS/4G.

(It’s even still included in OpenWatcom, though more advanced, less nostalgic extenders like PMODE/W, DOS/32A and Causeway are also now included. In fact, it’s creator was planning to dig out and provide the source for a more recent version for Open Watcom 2.0 but, sadly, he passed away in 2018.)

I forget which, but at least some of them can be merged into the binary to remove the need for a separate DPMI EXE file.

Win386

Win32s came out relatively late in Windows 3.1’s lifetime, so Watcom included a product called Win386 which did basically the same thing. (Providing a a 32-bit protected-mode environment with thunking wrappers to call back into Win16 code.)

Unlike with DOS/4GW, there’s no optional-but-on-by-default splash screen to tell you when Win386 is in use, but things like the Windows version of the Sierra SCI runtime use it.

(That’s actually why some Win16 programs crash on startup on modern CPUs. There’s a bug in older versions of Win386 that gets triggered on encountering CPUs faster than about 300MHz which can be fixed in any application by the “international” version of the KB240982 patch for Microsoft FoxPro 2.6.)

Information sourced from http://www.os2museum.com/wp/watcom-win386/

Performance of Resulting Binaries

According to Paul Hsieh’s WATCOM C/C++ Programmer’s FAQ, PC Magazine benchmarks indicated that “WATCOM C/C++ version 9.5 had the tightest and

fastest code among such compilers as Visual C++, Borland C/C++, Metaware Hi

C, Zortech and Symantec (by a wide margin)”.

According to that same FAQ, Borland’s strength was always their IDE and compile speed and, better code generators or not, Watcom’s approach to supporting embedding bits of assembly language is superior.

Tip 3: Older Versions of Free Pascal Can Produce Win32s-Compatible Applications and Win16 Support is Being Worked On

Release versions of Free Pascal are currently (v3.0.4) incapable of developing Win16 applications, but real-mode DOS support has been released and Win16 support is being developed in FPC trunk.

That said, the user “watler” on the aforementioned Computing.Net thread claims to have confirmed that Free Pascal 1.9.6 could produce Win32s binaries. However, aside from these pages saying to use -WR with Free Pascal 1.0.10 and avoid console functions in order to target Win32s, I haven’t yet found any further information on the DOs and DON’Ts.

According to this thread, Lazarus 1.6.x and Free Pascal 2.6.4 are the last versions to support Windows 9x with Free Pascal 2.4.x being the last to support it officially, so that’s where you’d want to start looking if you need to develop a Win32s application right now.

Tip 4: Open-Source Installer Creators for Old OSes

This section has been moved to its own post.

Tip 5: WINFILE.EXE is MIT-licensed

Remember how Microsoft included tools like Program Manager in 32-bit Windows up until Windows XP SP1 in order to allow companies to delay retraining?

Well, in early 2018, they MIT-licensed and GitHub’d the version of the Windows 3.1 File Manager that had been included in Windows NT 4 with the original_plus branch containing only minimal changes to allow it to build as a native 64-bit application using Visual Studio 2015 and 2017.

To quote the README…

The most significant changes are: converted to Visual Studio solution; works on VS 2015 and 2017 compiles and runs on 64-bit Windows (e.g., GetWindowLong -> GetWindowLongPtr, LONG -> LPARAM) added a few header files which were stored elsewhere in the NT source tree (e.g., wfext.h) deleted some unused files (e.g., winfile.def) converted 64-bit arithmetic from internal libraries to C converted internal shell APIs to public APIs (the primary reason the old version would not run)

That means it shouldn’t be too difficult to port things back if you want to borrow things now considered standard (like the Tree View widget) for your own projects or if you just want to read the code comments and examine the architectural decisions made by official Microsoft programmers.

UPDATE: In fact, efforts are being made to backport it at least far enough to get a Windows 3.11-compatible Win32s build.

As for those “internal shell APIs”, that’s why we have used/library copies of books like Undocumented Windows and Windows Internals by Schulman, Maxey, and Pietrek. (If you came here trying to figure out how to write a shell extension of the Windows Explorer variety, see this article.)

Other Tips

Since I’m doing this as a standalone blog post, I might as well throw in a few other related bits of knowledge I’ve had kicking around:

I also have a bunch of useful links for building things with Pascal and DOS batch files, but this is already getting really long, so I’ll leave that for another day.

Changelog

2017-12-29: Add a mention of the installer for Open Watcom C/C++, which is in the same source repository and can be built to run as a DOS or Win32 (possibly more) application using a single codebase and setup.inf .

Add a mention of the installer for Open Watcom C/C++, which is in the same source repository and can be built to run as a DOS or Win32 (possibly more) application using a single codebase and . 2017-12-27: Merry slightly overdue Christmas. I tracked down the installer builder from the Windows 3.1 SDK, discovered that it’s effectively freeware, and added it to the table. (see LEGAL.TXT inside the self-extracting archive.)

Merry slightly overdue Christmas. I tracked down the installer builder from the Windows 3.1 SDK, discovered that it’s effectively freeware, and added it to the table. (see inside the self-extracting archive.) 2017-12-19: Added mentions of x2ftp and sunsite mirrors as good places to look for old programming resources.

Added mentions of x2ftp and sunsite mirrors as good places to look for old programming resources. 2017-12-17: Added instructions for generating retro-styled Windows 9x installers using either an InnoSetup release or NSIS plugins. (And completed the table up to the present day for the heck of it. Speaking of which, for Linux, use Flatpak. It’s good enough for software pirates!)

Added instructions for generating retro-styled Windows 9x installers using either an InnoSetup release or NSIS plugins. (And completed the table up to the present day for the heck of it. Speaking of which, for Linux, use Flatpak. It’s good enough for software pirates!) 2017-12-10: Updated information on Free Pascal’s real-mode support and added instructions for embedding the DPMI stub used by DJGPP and Free Pascal.

Updated information on Free Pascal’s real-mode support and added instructions for embedding the DPMI stub used by DJGPP and Free Pascal. 2017-12-08: Added “Tip 4: Open-Source Installer Creators for Old OSes” and a link to microjson.

Added “Tip 4: Open-Source Installer Creators for Old OSes” and a link to microjson. 2018-02-16: Moved list of installer creators to its own post and moved changelog to the bottom of the post.

Moved list of installer creators to its own post and moved changelog to the bottom of the post. 2018-12-12: Added mention of WinFile being open-source.

Added mention of WinFile being open-source. 2019-01-11: Added link to tutorial and documentation for Watcom’s wmake makefile dialect.

Added link to tutorial and documentation for Watcom’s makefile dialect. 2019-04-10: Added mention of efforts to backport the open-sourced WINFILE.EXE code and a little more info on how to target Win32s with Free Pascal.

Added mention of efforts to backport the open-sourced code and a little more info on how to target Win32s with Free Pascal. 2020-05-21: Added mention of GW-BASIC being released under the MIT license and added a link to The Complete Idiot’s Guide To Writing Shell Extensions for lack of a better place.

Useful Info On Win16-Targeting Compilers… And a List of DOS/Win16 Resources by Stephan Sokolow is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License.