Useful Info On Win16-Targeting Compilers… And a List of DOS/Win16 Resources

Updated 2018-02-16: Moved list of installer creators to its own post and moved changelog to the bottom of the post.

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/WDOS/32A and Causeway are also now included.)

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: Free Pascal Can Apparently Produce Win32s-Compatible Applications and Win16 support is pending

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, I haven’t yet found any further information on the DOs and DON’Ts of doing so.

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.

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:

      1. Custom DOS Stub: The Windows executable format must begin with a DOS executable. Normally, it just displays that message about it not being a DOS program, but both the Watcom and Microsoft linkers allow you to specify a STUB=filename.exe option to provide a custom DOS EXE file. QEMM 97 uses this facility to put its DOS and Windows installers inside the same .EXE file rather than having separate INSTALL.EXE (DOS) and SETUP.EXE (Windows) files.
      2. Other Libre DOS C Compilers: I’ve already written a StackOverflow answer listing all of the ones I know, but DJGPP is the only one I’d consider worthwhile. (While not as native/storied/historic as Watcom and only capable of protected-mode DOS output, this GCC port has a big ecosystem and, according to this comp.os.msdos.programmer post, produces DPMI executables which require no extender under NTVDM or dosemu, unlike OpenWatcom.)
      3. Bundling the DPMI stub: If you’re using DJGPP or Free Pascal, then it’s possible to bundle the GO32v2 DPMI stub to produce a standalone EXE file by stripping the default one off using exe2coff (also included with DJGPP cross-compiler builds.) and then prepending cwsdstub.exe (included with DOS versions of DJGPP and Free Pascal) using the same technique shown in my installer creator list for cross-building self-extracting Zip files. Some of the DPMI extenders included with OpenWatcom can also be bundled in a similar manner. This comp.os.msdos.programmer post provides a good overview of how it all fits together and this other post lists noteworthy alternative DPMI hosts such as DPMIONE.
      4. Supplemental Libraries: Here are some which look promising:
        1. Argument Parsing: Argtable 3.x seems to place a pretty big emphasis on portability and argtable 2.x explicitly lists DJGPP and Open Watcom as known to build it successfully.
        2. zlib/libzip: Archlinux’s AUR contains patches to build zlib and libzip for OpenWatcom’s DOS targets. (As well as one for zlib on win16, though I don’t see why there would be a difference unless it’s for static libraries vs. an LE-format DLL.)
        3. Extended standard library: iMatix’s legacy repositories on GitHub provide a Standard Function Library (online docs) which offers useful stuff for C such as various string- and filesystem-related functions now standard in modern languages and INI and XML reading/writing. The docs list Watcom and DJGPP among the supported compilers for targeting DOS.
        4. TUI (ie. text-mode GUI) Development: There are ports of Turbo Vision for DJGPP (instructions) and Free Pascal.
        5. DOS Game Development: Allegro provides API abstractions and a library of ready-made, optimized utility routines to allow easy writing of portable games. Version 4.2 is the last release which supports targeting DOS.
        6. Pattern Matching: Ozan Yigit’s website has single-file public domain implementations of a robust glob matcher and 4.3 BSD regex syntax.
        7. Executable Compression: UPX can pack pretty much any kind of executable you’re likely to want to pack except Win16 or .NET.
        8. JSON Parsing: While it doesn’t explicitly list compatibility with compilers like Open Watcom, microjson is a likely candidate, being a very compact, low-footprint, malloc-free parser for a subset of JSON intended for resource-constrained environments.
        9. Useful Misc.: You can find lots of useful bits in the Wayback Machine on Troels K. and Japheth‘s sites, such as Win16-compatible CEditView / CRichEditView implementations and the HX DOS extender (which provides limited support for Win32 applications in DOS), but be sure to double-check for license compatibility since I think at least one component on the list is an improvement on an EPL-licensed component and the EPL is GPL-incompatible.
        10. More Useful Misc.: Also, check out x2ftp and Sunsite mirrors for useful libraries and tutorials. (eg. the watcom folder on x2ftp)
      5. BASIC: If QBasic/QuickBASIC was more your thing, FreeBASIC supports targeting 32-bit protected-mode DOS and offers a qb dialect mode.
      6. Python: It’s ancient, protected-mode, and I’ve heard people use the phrase “buggy old …” to describe it, but a port of Python 2.4.2 for DOS does exist.
      7. Embedded Scripting: While I haven’t tested any of them yet, the most likely candidates for embedded scripting in a DOS/Win16 environment seem to be running either Lua or the V7 or tiny-js JavaScript runtimes under one of DPMI, Win386, or Win32s. (For more home-grown scripting handling, microjson may be useful as an example of how to write a resource-constrained parser.)

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.
  • 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.)
  • 2017-12-19: 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!)
  • 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.
  • 2017-12-08: 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.

CC BY-SA 4.0 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.

This entry was posted in Geek Stuff. Bookmark the permalink.

7 Responses to Useful Info On Win16-Targeting Compilers… And a List of DOS/Win16 Resources

  1. Nikolay Nikolov says:

    The Free Pascal wiki page for the i8086-msdos compiler was a little outdated, so I updated it:
    1) the latest stable release for i8086-msdos is 3.0.4, not 3.0.0
    2) the large memory model support has matured and win16 support has already been started in fpc trunk. I’ve created a new wiki page for it:
    http://wiki.freepascal.org/Win16
    It still doesn’t contain much information, but it will gradually be updated.

    • Thanks. I’ve updated the post accordingly.

      (Now all I need to do is get off my lazy butt and start making real-mode ports of RTL and FCL components I’d want to use in a real-mode application, like INI read/write, JSON parsing, and unzipping.)

      • Nikolay Nikolov says:

        Can’t wait to see it happen 😉

        Btw, I just added information on what units are currently available for win16 in the wiki page:

        http://wiki.freepascal.org/Win16#Status

        Later, I will probably also add a screenshot of fpctris working under Windows for Workgroups 3.11 🙂

        • Nice! I should really look into what it would take to automate the generation of that kind of information for display on the website.

          That said, whatever I decide to work on, It’ll be a while before I contribute anything.

          I spent so much of my life never bringing hobby projects to v1.0 (either due to perfectionist burn-out or because something new caught my attention) that my mantra these days is “make it work, then make it perfect”… and I can build v1.0 of my first Pascal project using the units available for GO32v2.

          Specifically, I want to write libre installer toolkits for DOS and Win16 (starting with DOS, since there isn’t even an InnoSetup 1.2.16 analogue for it) with selectable “themes” that allow hobbyist developers to easily replicate the look and feel of nostalgic installers from companies like iD Software, Microsoft, Sierra, Wise, etc.

          I just spent yesterday going through about a quarter of my collection of old CD-ROMs (so far), screenshotting the installers in DOSBox so I can have reference material to work from while I wait for the book I’ve ordered on Turbo Vision.

  2. Another tip which I don’t yet consider high-enough quality to include in the main post:

    In theory, it should be possible to use Duncan Murdoch’s freely-redistributable glue.exe tool (originally here) to replace the DOS stubs in NE-format (Windows 3.x) EXE files if the compiler is something like Free Pascal which doesn’t support a /STUB option in the linker.

    Unfortunately, it dies with “Runtime error 200” for me in both DOSBox and DOSEmu and none of the patchers I tried would fix it.

  3. Flag User says:

    Great stuff!

    Just want to add that Digital Mars C++ is another relatively new compiler that targets DOS/Win16. It is not free though. DJGPP also has been updated 2015, after being dormant for a while. wxWidgets also supported win16 upto a certain version.

    • Thanks.

      I hadn’t realized wxWidgets (or wxWindows, as it no doubt would still have been called at the time) supported Win16 but, looking at the date of its initial release, that makes perfect sense.

      I’ll have to look into what the last Win16-supporting version was that when I can find a moment.

      UPDATE: I couldn’t wait… and bah!

      According to this FAQ, while wxWindows 2.x does still support Windows 3.1 up to at least version 2.4.2 (the release associated with the FAQ), it only supports 16-bit compilation with Microsoft and Borland compilers.

Leave a Reply

Your email address will not be published. Required fields are marked *

By submitting a comment here you grant this site a perpetual license to reproduce your words and name/web site in attribution under the same terms as the associated post.       Also, please be aware that non-constructive comments will have their URL field erased before being approved in order to combat SEO spam.