Announcing EmuWoW Beta 1 (AXP Preview1)

Freecell & Winver

This is a guest post by CaptainWillStarblazer

Hello, everyone. This is a continuation of my previous blogpost on EmuWoW (formerly win32emu) found here, but to summarize, I’m the 18-year-old developer behind a project that allows running applications compiled for the MIPS/Alpha version of Windows NT on standard x86 PCs through emulation, but without requiring a full system emulator. Since that last post, the project has made some substantial strides.

Since then, I’ve adapted the MIPS emulator from MAME, which is both more accurate and faster than my own (writing my own was a fun exercise but to the end of running applications, borrowing an emulator was a better decision). This alone enabled WinMine to function, which can be seen below.

Winmine for MIPS!

Around the same time, another VirtuallyFun member named x86matthew entered the scene. His prior credits include a similar project, for Win16. He was inspired by the initial win32emu blog post, created his own similar project called WoWMIPS, which quickly started running a few simple apps, such as WinMine, Solitaire, and Notepad. Be sure to check out WoWMIPS – MIPS Emulator for Windows, Part 1: Introduction, and parts 2,3,4,5,6!

This had actually been what I was hoping for from the beginning; I always saw win32emu as a proof of concept for a smarter person (either myself in the future or someone else altogether) to come back later and do it better, and this is a massive undertaking for a single individual. What makes x86matthew’s WoWMIPS so incredible is its clean design. For one, there’s no thunk DLLs required. When an application tries to import a DLL, the host x86 DLL is first loaded, and then any attempts to get the address of an exported procedure from it are then redirected to an auto-generated stub of MIPS code which invokes the emulator to call the function. In other words, the thunk DLLs are generated at load time. Additionally, there’s no window procedure thunks required either. Instead, MIPS code pages are marked as non-executable, causing an access violation when Windows attempts to call them. Using an exception handler implemented via Windows XP’s Vectored Exception Handling feature, one can detect this and then invoke the emulator to execute the callback. Storing the CPU state in thread-local-storage allowed proper support for multithreading. I duplicated these design choices into EmuWoW, and the results largely speak for themselves. Unlike WoWMIPS (at time of writing), EmuWoW is still capable of loading MIPS DLLs (and will prefer to do so if possible), however.

Various MIPS Windows NT applications running

To aid the process of fixing faults in the emulator, I hacked up a quick, minimal debugger into EmuWoW. First of all, there’s a “crash screen” which will indicate the type of error and dump registers and the current instruction if there’s a fault, and a running disassembly can be printed as you go, but most crucially, there’s a limited degree of interactive debugging functionality.

The built in debugger to EmuWow

The main capabilities contained herein are dumping registers and memory to the screen, disassembling regions of memory, listing loaded modules, getting import entry points, setting breakpoints, and single-stepping, along with printing functions. It’s no gdb (especially for the lack of PDB symbol support), but it’s something.

MIPS is all well and good, however, but we can already emulate Windows NT for MIPS. MIPS is a fairly clean, simple architecture, often used for teaching, and short of weirdness like delay slots, is dead simple to emulate. And it fits the bill for what I’m trying to do here – a RISC architecture Microsoft abandoned, fixed-length 32-bit instructions, the works. However, adding support for the DEC Alpha AXP will finally get this project to where it was intended to be from the beginning, and I hope for it to eventually be able to run the Visual C++ compiler toolchain under EmuWoW. Being able to compile (and even test!) Alpha apps on readily available modern PCs will be a game-changer, and I intentionally wrote EmuWoW to be CPU-agnostic, so adding rudimentary support for the Alpha wasn’t difficult. Like with MIPS, I lifted the emulator from MAME. This admittedly did pose some challenges, due to MAME’s use of C++ features such as

  • Classes (which I had to substitute for passing pointers to structs)
  • Templates (which I had to substitute for macros)
  • Function-style casts (which I had to change into C-style casts)

There was a lot of weirdness in how Alpha function calls, but it was my misunderstanding of the calling convention, and when to consider values to be 32-bit vs 64-bit posed a modest issue, but I got it to the point where some very simple DEC Alpha programs started to run, though many of them have various issues.

Various Dec Alpha Windows NT applications running

This is the first time this has ever been possible; emulation of AXP NT programs on standard PCs has just become possible now. I’m hoping to see EmuWoW continue to evolve, and I welcome contributions, whether that be improving support for the CPUs I already have, adding support for another (such as PowerPC) or anything else. To take a look at the code, go to github.com/bhty/emuwow and to download EmuWoW and try it out for yourself, click here.

So it turns out GCC could have been available on Windows NT the entire time!

This is going to be a bit convoluted but here goes.. GCC isn’t a monolithic compiler, instead it’s various parts are separate programs. This lets us tackle it one part at a time. And/Or bypass a lot of it until I want to tackle it.

Flow of GCC

I’m sure many people have explained this far better than I ever could but in C you write source files (obviously), the pre-processor reads those and ‘header’ files that describe interfaces to libraries, other objects, various macros and definitions (magical numbers) and the pre-processor will read those files, and do simple macro expansion and test insert/replacements to generate a single .i file at the end of it’s run.

The C compiler (cc1) now reads that single .i file and translates it into native assembly. This allows for ‘mid/high level’ aspects of C to be machine independent (portable) but now will be written into a very system dependant assembly file, the single .S file. One thing of note is that so far everything is text files. You can edit the assembly file as you would any document, or even further ‘process’ it if needed/wanted.

The assembler ax386 (GAS) will then read the single assembly file and write a a binary object file hi.OBJ. There typically isn’t all that much to be said about assemblers although fancier ones allow for really strong Macro capabilities like Microsoft MASM.

From here on, it’s all binary objects!

The linker then takes your object files, and links them together with other system objects and system libraries into an executable, in this case. Linkers can build all kinds of other things, but for now we’re just pretending its static C compilation like it’s the 1970’s.

At it’s heart GCC processes text files.

The first part in this insane experiment, is to build GCC 1.40 with Microsoft Visual C++ 1.0. Surprisingly it didn’t take an insane amount of messing with stuff, and I got an executable! But everything it compiled failed to assemble. Looking at this fragment, even if you don’t know i386 assembly you might spot the error:

main:
        pushl %ebp
        a b,c
        pushl %esi
        pushl %ebx

Yeah, it’s the “a b,c” part. Those are NOT valid i386 opcodes!

Just because it compiled didn’t mean it actually worked.

I used MinGW to build the same source, same Makefile, and I got a working executable. Annoyed I started compiling random files with Microsoft C, and finally found the file that broke it all, it turned out to be insn-output.c needing to be compiled with the “/D__STDC__” flags. A quick modification of the Makefile and now I have a working CC1!

Okay, great, it’s well known back in the early dangerous ages of the 1980’s/1990’s that everyone wasn’t running Linux, nor were binary distributions of GCC that far spread, rather I think to re-enforce the source was available it was expected that you’d use your system compiler. Systems like DJGPP/EMX take the path of binding a.out object files into something that MS-DOS can run via a dos extender, or the bind utility to allow you to run the a.out on OS/2. What I wan’t to do is verify that in fact Windows NT was a viable host for GCC back in the public pre-releases of 1991.

I’m sticking with the December build 239 version as it has working floating point. Something that GCC has intrinsic support of, and I don’t feel like trying to work out emulation.

The next step is to try to build it with the family mode-OS/2 version of the C compiler, which of course lead to the real issue of this 16bit hosted cross compiler:

        cl386 /u /Od /Ic:\MSVC32S\C386\INCLUDE /I. /Iconfig /c combine.c
Microsoft (R) Microsoft 386 C Compiler. Version 1.00.075
Copyright (c) Microsoft Corp 1984-1989. All rights reserved.

combine.c
combine.c(1734) : fatal error C1002: compiler is out of heap space in Pass 2
NMAKE : fatal error U1077: 'C:\WINDOWS\system32\cmd.exe' : return code '0x2'
Stop.

Very frustrating. I tried mixing and matching from Visual C++ 1.0 & this old compiler, and while it did compile, it doesn’t run. does it mean anything?!

GCC 1.40 compiled by Microsoft 386 C Compiler. Version 1.00.075

I should point out that this should be an expected working configuration as GCC does build on Xenix using the 32bit Microsoft C 5.1/386 compiler. Furthered again that Xenix and these 1991 versions of NT use the same 32bit OMF object format. And expanding on the Xenixnt experiment using the Xenix’ified GAS assembler with old Visual C++ includes & libraries to produce a possible retro-early port of GCC to NT, the next move is to bulid GAS on NT.

Xenix GAS 1.38 compiled by by Microsoft 386 C Compiler. Version 1.00.075

GAS gave me some weird issues with ctype.h where it runs fine with the one from Visual C++ 1.0 but the OS/2 & NT pre-release both fail. However the old Pre-release compiler cannot deal with the much newer ctype include file. So after much hammering I amputated whatever was bothering it, and it’s just enough to build & run. Great!

Going back to the phases, I used a simple hello world program:

void main() {
 printf("Hello World!\n");
}

While not being a good program, it doesn’t include stdio.h, nor does it return anything. It’s terrible. But in this case it allows me to be lazy and sidestep the pre-processor cpp.exe. This way I can just directly run it through cc1 and get my assembler file hi.S

Next I pass it to ax386 (GAS) and get the resulting object file hi.OBJ

And finally link it with link.exe in this case.

Hello World from GCC 1.40 on NT!

And with all the drama I’ve now compiled a simple hello world program on Windows NT.

If it were 1991, I would hollow out gcc.c so it doesn’t use signals or forks to invoke the needed phases, and of course build the pre-processor. In addition, libgcc needs to be compiled to allow for floating point operations to work correctly. None of which is impossible, although I’m not sure it’s all that needed as it isn’t 1991.

phoon

With a little bit more work, I got the floating point support to compile, which relies on both a working ‘native’ compiler, and a working GCC to compile the 2nd half. I usually use phoon, or Phases of the Moon, to test floating point, and as you can see, it’s working!

I’m not sure if there was a 32bit version of Microsoft C/386 available for Microsoft OS/2 2.00 betas. Also, I don’t know if the Microsoft link386 for OS/2 can also link Xenix 386 object files? Would it have been possible to bootstrap GCC/GAS on Microsoft OS/2 2.00? I really don’t know, and as of this writing no versions of the old Microsoft OS/2 2.00 betas have surfaced.

** update from the future, turns out that I found a way to convince the cl386 compilers from the NT Pre-Releases in 1991 to re-build an existing GCC that was built for NT. The catch is the linker, LINK386 of course, as the format was constantly changing. However the object files are fine, and I was able to just copy them over on diskette and re-link the compiler. It even ran. It’s not tested at all, so it turns out the 1989 compiler wasn’t good enough, but the 1991 was.

GCC 1.40 on OS/2 2.00 beta 6.123

It’s interesting to me to see that even before GCC 2.6, that vintage versions from 1991 would compile and run directly on Windows NT.

I uploaded the source on github, along with some binaries.

Windows NT 3.1 on DEC Alpha AXP

(this is a guest post by Antoni Sawicki aka Tenox)

As I was preparing the Windows NT RISC exhibit for VCF west, I realized that I’m missing a rather important piece of the history. While I will be showing the potentially last DEC Alpha Windows build ever – AXP64 2210, I don’t have anything earlier than NT 3.51. It would be nice to showcase the very first RTM version – NT 3.1. From time perspective, NT did not get popular until the version 3.5 and later. Windows NT 3.1 would be considered rare even on a 386, let alone on a RISC CPU! So what RISC hardware does Windows NT 3.1 run on?

NT 3.1 RISC HCL

Not many! The HCL published on gunkies has a few more systems, but nothing that I have. The early MIPS based systems are all but unobtanium as of today. This is probably a good time to mention a little known port of Windows NT 3.1 to the DECstation 5000. However these builds are not found even on earliest NT betas. Not to mention lack of ARC firmware for this machine.

The Alphas were looking a little more reachable. The DEC 2000 Model 300 and DECpc AXP 150 are one and the same machine, packaged in a server and workstation cases. Code-named Jensen, DEC designed and marketed these specifically around Windows NT. Unlike prior Alphas, this model used a lot of “PC” components for increased compatibility and lower cost. Eventually paved way for the more well known DEC Multia. The Jensen has been seen floating here and there and many people have these.

I was able to get a loaner from Chris Satterfield aka Compgeke for the VCF. Having a working specimen at hand, I started looking at part numbers of various components. In an amazing streak of luck, in practically zero time I was able to find, buy and assemble a complete DECpc AXP 150 from spare parts on eBay! Without a case, but nevertheless. Also big thanks to Christopher Rivett for help with some fine details!

Franken Jensen built from spare parts off eBay.
Jensen running at VCF West 2023, with fans installed

BOM

  • Motherboard + CPU – DEC 70-29685-01
  • GPU – DEC/Compaq Qvision 1024/E (1024×768) – 126654-001
  • GPU – (Optional) Number 9 High Res (1280×1024) – 30-41800-01
  • HBA – Adaptec AHA-1742A EISA – 467806-00
  • NIC – DEC DE422-S EISA – 5021102-01
  • RAM – 4x 16MB, FPM, 60ns, 72-Pin, 12-Chip, True Parity SIMM
  • PSU – DEC/HP 30-37197-02, however a standard AT PSU may be OK

If you going to build one yourself, beware of overheating. Jensen runs rather hot and needs good cooling. Not only for the CPU. There is a section of the motherboard just under the EISA cards that runs incredibly hot. See the picture, where I have installed a large Noctua fan.

OS Install

There are many Windows NT 3.1 CDROMs floating around. I purchased a DEC branded, shrink-wrapped CD on eBay to use as a prop along with the machine. You can download the iso image here.

Installation of Windows NT 3.1 on DECpc AXP 150 is pretty straightforward and not that much different from the later versions. However as a prerequisite you will need the ECU floppy disk to configure the EISA slot assignments, card and jumper settings. After that you will have to go through various setup screens in ARC BIOS to configure system settings. Then you run arcinst to create a system partition and setupldr to install the OS. The rest of it is pretty uneventful. This is somewhat expected, as this was pretty much the only one and supported hardware combination, so must have been well tested. The only curious part is that the NT OS Kernel does not display any text during normal boot. Later versions of NT will display the build number and MP or UP kernel variant and dots indicating subsystem load progress. This is rather odd because I expected more text mode stuff from older NT version, but who knows.

Jensen NT 3.1 Boot Menu
Windows NT 3.1 on DEC Alpha AXP, DECpc 150 aka Jensen

Service Pack Saga

If you are even vaguely familiar with installing Windows NT at all, you will know that the very first thing you have to perform after installation, is to apply a service pack. NT 3.1 did have service packs, up to SP3. The problem is that, as you may very well expect, non-x86 editions were nowhere to be found in 2023. The only thing I could come up with was http://www.win31.de/ent31.htm, which had a German AXP and MIPS SP3, but no English! [It since has been updated…]. I had to do some real detective work to track down an US-English AXP SP3 version. I spent a few days going through various random CDs and ftp site mirrors of that era, with little luck. Eventually I stumbled on this README file, stating:

Due to space constraints on the Windows NT Service Packs for
International Versions CD, the USA Service Pack version 3 is located on
the Additional Windows NT Service Packs, Windows 3.11 versions, SDKs,
and DDKs CD in the NTSRVPC3\USA directory.

Bingo! After a few hits and missed I spotted this particular CDROM here: https://archive.org/details/microsoft-developer-network-january-1995-disc-4-of-15 – Now the OS is finally “servicepacked” 🙂

Applications!

My general impression of NT 3.1 on DEC Alpha is pretty awesome. If you can overlook the age and some obvious shortcomings, the OS is pretty stable, solid and even snappy for such old hardware. An OS itself without apps is not much. While overall Alpha NT application outlook is pretty scanty I was able to find a several very interesting gems!

Most importantly, thanks to Chris, a DEC Windows NT Developers CD-ROM!

The disk has an incredible amount of demo, freeware, public domain and shareware applications as well as DEC marketing material.

Windows NT Developers CD for DEC Alpha NT 3.1

You can get a lot of DEC proprietary software like C++, Fortran, PATHWORKS, DECtalk, as well as X servers, etc.

However I was particularly interested in some 3rd party commercial apps.

For example there is an early version of DMC Calamus Desktop Publishing.

DMC Calamus desktop publishing on Windows NT 3.1 DEC Alpha AXP

Also a demo version of a vintage, text-mode SlickEdit, way before it was replaced by the Visual SlickEdit known today.

SlickEdit 2.3 on Windows NT 3.1 DEC Alpha AXP

There also is WinDev editior, which is quite superior to Notepad and has some code editing goodies and shortcuts to SDK tools, making it something of a simple IDE.

WinDev 1.56 on Windows NT 3.1 DEC Alpha AXP

Another big source is Windows NT Application Sampler CDROM, (also from Smithsonian).

One of the coolest thing found there is a graphical text editor called WinEdit. It has a ton of features and even syntax highlighting! It has since became my default to go editor / IDE on this system!

WinEdit 3.0E on Windows NT 3.1 DEC Alpha AXP

There of course is a Windows NT SDK with the M (MEP) editor.

Windows NT 3.1 SDK with M / MEP Editor on DEC Alpha AXP

There also are quite few public domain apps and games, ports of GNU software, Micro Emacs, Kermit, etc.

Update: CICA NT Shareware Collection has some interesting apps under the /alpha directory.

High Resolution GPU

One of things that was troubling me for some time was rather low resolution of the default QVision graphics card. The maximum being only 1024×768 is just not acceptable. Talking to several Jensen’s owners, no one even heard about anything better. However looking at the Windows setup options, I curiously noticed that the system does support one 1280×1024 video card – Number 9 GXE.

I simply assumed that such card would simply be unobtanium in 2023. However, digging through some old catalogs and spare part listings, I managed to find a DEC part number, which is 30-41800-01. Armed with this, I was able to find it via DEC spare part reseller that I often use. They had it in stock listed as “HIGH RES EISA 1280 x 1024 GRAPHICS”. The price wasn’t too bad either, at least compared to the whole endeavor. A few days later I received this:

After installation of the S3 driver (must be the Service Pack 3 version!) I was finally able to get 1280×1024 from the poor thing!

With this I should have a more cozy environment to compile and port even more apps 🙂

In future I want to try the Advanced Server edition as well as some early Betas with Alpha support.

Windows NT demo on the DECstation 5000

Well this was unexpected find! Thanks to hyenasky over on discord.

While the platform had a few mentions here and there but it’s great to have found a talk about the product with video of it running.

Interestingly enough Compaq was apparently in charge of the ARC specifications? Also kind of funny how the do touch on that maybe one day it could be available for the Dec Alpha, but as we know DEC pivoted away from the MIPS entirely to focus on the Alpha.

The other part being how the Pentium/Pentium Pro was entirely unexpected from the wider RISC market that thought they had the migration point out of 386/486 based machines.

Unfortunately, like the platform, Alexandre Bronstein exited DEC to go onto other ventures, oddly enough at Veritas being pulled back into dealing with Microsoft with the disk manager.

Fun with Windows ePDK NT 3.1 build 196 & Some Xenix fun!

I’m not sure if I covered the Windows NT 3.1 build 196 before. First the most obvious is that as of this moment it’s the earliest version of Windows NT available.

So let’s do some obligatory scratch of the surface. Like all the other 1991 pre-releases there really is just a text mode setup install script. Choosing the lesser amount of pain, I went with a MS-DOS hosted install. However, using MS-DOS 6.22 resulted in a broken dual boot system. But we live in the era of virtual machines, so it really doesn’t matter. I’m using Qemu 0.14-rc2, something that is ‘era correct’ for when the first avalanche broke on early Windows NT pre-releases. I’ve had issues with more modern versions of Qemu, and I felt that if we’re using vintage software may as well go in all the way.

The boot loader identifies itself as being 1990 vintage. Pretty sure it doesn’t mean anything, but we haven’t been blessed with the “blue screen” of ARC yet.

The login screen and desktop have a very strong Windows 3.1 beta feel to them. And that would land this where it was, Windows was such a big seller that Maritz had been trying to convince Gates & Balmer to ‘switch to the Windows horse’ in the spring/summer of 1990, culminating in Gate’s July decision to walk away from NT/OS2 and rebrand the new OS as Windows NT. Oddly enough it was Balmer who was in favour of OS/2 & IBM. (Showstopper 89-90)

At first glance the opening window isn’t all that interesting. It’s just very. Windows.

Rest assured Reversi, of course made the this Win32 cut. And it’s full of weird easter eggs, oddly enough in the OS/2 surviving bits.

type OS2LDR.DOS
OS2LDR 01.00.01
by KeithMo 01/08/91

On the Discord there had been a big discussion about early NT executable formats, and the whole COFF vs ECOFF vs PE/PEI. I had tried to hunt down the specific version of GCC I used ages to to build a so called Dec Alpha GCC cross compiler, but the short version is that it didn’t work as we don’t have any assembler/linker for anything GNU targets. There had been a cygwin port and an OpenNT on Alpha, but all that is lost to the winds, minus what few scraps I had saved. I did try building some cross tools to elf hoping to just objcopy out the data and get linkable objects, but that didn’t work either.

So I though this was a perfect opportunity to take a look at this early pre-release version of NT, and although I do know that you have to convert your objects into something the ‘COFF’ linker will accept:

And I never really paid that much attention to the object files. I do know that you can link them with Link386 for OS/2, but the NT object files themselves report:

wsl file SIMPLE.OBJ
SIMPLE.OBJ: Intel 80386 COFF object file, not stripped, 4 sections, symbol offset=0x102, 20 symbols, created Thu Jun  1 14:13:50 2023, 1st section name ".text"

Well, now that is interesting. And of course the COFF thing reminded me of Xenix! And sure enough ages ago I had found the source to a modified version of GNU GAS that outputs COFF. Once more again this is an indication that all 386 roads in Microsoft really did originate with Xenix. It’s too bad there never was a Windows/386 on Xenix/386. What an incredible OS that would have been! There must be some incredible stories from the tool teams that worked on Microsoft C/386 along with other projects. Oddly enough they never get anywhere near as much exposure as Office or OS.

Now this is fun, but nothing takes in these ancient COFF objects, do they? I tried to run LINK 1.0 from Win32s SDK and surprisingly it didn’t complain about the object, rather, it auto converted it in memory:

Microsoft (R) 32-Bit Executable Linker Version 1.00
Copyright (C) Microsoft Corp 1992-93. All rights reserved.

SIMPLE.OBJ : warning LNK4016: unresolved external symbol "__chkstk"
LINK : warning LNK4016: unresolved external symbol "_mainCRTStartup"
SIMPLE.OBJ : warning LNK4016: unresolved external symbol "_printf"
SIMPLE.exe : error LNK1120: 3 unresolved externals

Does this mean that if I give it some libraries it will actually link?

LINK.EXE SIMPLE.OBJ /SUBSYSTEM:CONSOLE /MACHINE:i386 -entry:mainCRTStartup -out:simple.exe libc.lib kernel32.lib
Microsoft (R) 32-Bit Executable Linker Version 1.00
Copyright (C) Microsoft Corp 1992-93. All rights reserved.


C:\temp\nt196\x\dec\x>simple
Win32, it's happenin'!

This was. VERY unexpected.

So I had this crazy idea, what if the Xenix assembler could in fact build objects that are also compaible in this manner? I used the a.out GCC / Linux porting tools I had built so I could compile Linux on Windows NT using the vintage tools as a starting point. I guess I should also add that when people always say ‘use newer version of THING’ this is how you miss out on old stuff like this. If I had been obsessed with using modern tools and modern operating systems, I’d have missed out on this Xenix filled window.

I took the gcc driver & the cc1 compiler from 1.40 and the c pre-processor from 2.5.8 as it can understand C++ comments. First I manually compiled the ‘simple’ example to assembly:

gcc -v -nostdinc -I/xenixnt/h -S SIMPLE.c -O simple.S
gcc version 1.40
 cpp -nostdinc -v -I/xenixnt/h -undef -D__GNUC__ -Dunix -Di386 -D__unix__ -D__i386__ -D__OPTIMIZE__ SIMPLE.c C:/Users/jsteve/AppData/Local/Temp/cca2_048.cpp
GNU CPP version 2.5.8 (80386, BSD syntax)
#include "..." search starts here:
#include <...> search starts here:
 /xenixnt/h
End of search list.
 cc1 C:/Users/jsteve/AppData/Local/Temp/cca2_048.cpp -quiet -dumpbase SIMPLE.c -O -version -o SIMPLE.s
GNU C version 1.40 (80386, BSD syntax) compiled by GNU C version 5.1.0.
default target switches: -m80387
 cpp -nostdinc -v -I/xenixnt/h -undef -D__GNUC__ -$ -Dunix -Di386 -D__unix__ -D__i386__ -D__OPTIMIZE__ simple.S C:/Users/jsteve/AppData/Local/Temp/cca2_048.s
GNU CPP version 2.5.8 (80386, BSD syntax)
#include "..." search starts here:
#include <...> search starts here:
 /xenixnt/h
End of search list.

Which gave me the following assembly:

        .file   "SIMPLE.c"
gcc_compiled.:
.text
LC0:
        .ascii "Win32, it's happenin'!\0"
        .align 2
.globl _main
_main:
        pushl %ebp
        movl %esp,%ebp
        pushl $LC0
        call _printf
        leave
        ret

Now to assemble with the GAS Xenix assembler

C:\temp\nt196\files\MSTOOLS\SAMPLES\SIMPLE>ax386 SIMPLE.s -o SIMPLE.obj

C:\temp\nt196\files\MSTOOLS\SAMPLES\SIMPLE>wsl file SIMPLE.obj
SIMPLE.obj: 8086 relocatable (Microsoft), "SIMPLE.c", 1st record data length 10, 2nd record type 0x88, 2nd record data length 11

Not quite the same. But it does closer resemble the output from the OS/2 bound versions of the Pre-Rease compilers:

file EMPTY.OBJ
EMPTY.OBJ: 8086 relocatable (Microsoft), "empty.c", 1st record data length 9, 2nd record type 0x88, 2nd record data length 7

So will it link?!

C:\temp\nt196\files\MSTOOLS\SAMPLES\SIMPLE>LINK.EXE SIMPLE.OBJ /SUBSYSTEM:CONSOLE /MACHINE:i386 -entry:mainCRTStartup -out:simple.exe libc.lib kernel32.lib
Microsoft (R) 32-Bit Incremental Linker Version 2.50
Copyright (C) Microsoft Corp 1992-94. All rights reserved.

SIMPLE.OBJ : warning LNK4033: converting object format from OMF to COFF

C:\temp\nt196\files\MSTOOLS\SAMPLES\SIMPLE>simple
Win32, it's happenin'!

Well now this is interesting! LONG before MinGW, or the GCC port to Windows NT, it turns out that in fact GCC could target Windows NT the entire time!

So the next thing to do is something not as trivial, like phoon.

I setup some quick script to pre-process, compile, assemble and then try to link, but as this one uses floating point, disaster struck:

phoon.obj : error LNK2001: unresolved external symbol "___fixdfsi"
astro.obj : error LNK2001: unresolved external symbol "___fixdfsi"
phoon.exe : error LNK1120: 1 unresolved externals

Now ages ago while messgin with old GCC & DooM I also had weird math calls not working. In the end I ended up extracting them from libgcc builds, so I thought I’d try the libgcc built during the GCC 2.6.3 on NT adventure.

link /NODEFAULTLIB:libc.lib /NODEFAULTLIB:OLDNAMES.LIB -out:phoon.exe astro.obj date_p.obj phoon.obj -entry:mainCRTStartup libgcc1.lib LIBC.LIB KERNEL32.LIB
Microsoft (R) 32-Bit Incremental Linker Version 2.50
Copyright (C) Microsoft Corp 1992-94. All rights reserved.

And of course:

To try to make the steps make a little more sense, and to allow for some higher level of automation I made a Makefile:

CC=gcc
CC1=cc1
AS=ax386
CPP=cpp


CFLAGS= -O
CPPFLAGS= -lang-c-c++-comments -nostdinc -I/xenixnt/h

OBJ =   astro.obj \
date_p.obj \
phoon.obj

LIBS = libgcc1.lib LIBC.LIB KERNEL32.LIB

phoon.exe: $(OBJ)
        link -out:phoon.exe $(OBJ) -entry:mainCRTStartup $(LIBS)

%.obj: %.c
        $(CPP) $(CPPFLAGS) $< $*.i
        $(CC1) $*.i -quiet $(CFLAGS) -version -o $*.S
        $(AS) $*.S -o $*.obj


clean:
        del $(OBJ) *.i *.S phoon.exe

I’m sure there is better ways to do this, but it breaks the compile up to it’s individual parts:

Run the pre-processor to allow // in the comments, C++ hadn’t been the default thing back when GCC 1.40 was a thing. Also path it to the headers, in this case I’m using the ones from NT 196. Trying to link with the 196 libraries gave me this:

C:\xenixnt\demos\phoon>link /NODEFAULTLIB:LIBC.LIB /NODEFAULTLIB:OLDNAMES.LIB -out:phoon.exe astro.obj date_p.obj phoon.obj -entry:mainCRTStartup base.lib wincrt.lib ntdll.lib \xenixnt\lib\libgcc1.lib
Microsoft (R) 32-Bit Incremental Linker Version 2.50
Copyright (C) Microsoft Corp 1992-94. All rights reserved.

wincrt.lib(maincrt0.obj) : warning LNK4078: multiple ".data" sections found with different attributes (40000040)
astro.obj : error LNK2001: unresolved external symbol "_asin"
astro.obj : error LNK2001: unresolved external symbol "_atan"
astro.obj : error LNK2001: unresolved external symbol "_atan2"
phoon.obj : error LNK2001: unresolved external symbol "_cos"
astro.obj : error LNK2001: unresolved external symbol "_cos"
astro.obj : error LNK2001: unresolved external symbol "_floor"
astro.obj : error LNK2001: unresolved external symbol "_sin"
phoon.obj : error LNK2001: unresolved external symbol "_sqrt"
astro.obj : error LNK2001: unresolved external symbol "_sqrt"
astro.obj : error LNK2001: unresolved external symbol "_tan"
phoon.exe : error LNK1120: 8 unresolved externals

Which is not surprising as there is no FPU/Floating point math support in 196. I tried the December 1991 Pre-Release, but it failed for other reasons:

I did copy over BASE.DLL BASERTL.DLL CSR.DLL DBGDLL.DLL as it wanted, but despite the symbol being in the DLL it didn’t load.

So that’s why I’m using the libraries from the Win32s SDK.

Okay, so far now we have GCC 1.40 compiling to an old Xenix GAS assembler, and linking with Microsoft link from Visual C++ 1.0/2.0 era. The next step is to see if we can just link the objects under 196, and get a running EXE!

I have this tiny fibonacci example program, so with it compiled & assembled by GCC & GAS, I did the final link under 196, and YES it runs!

I then built the ’87 InfoTaskForce, Infocom interpreter, and it was just a simple link, and it’s running!

Possible things to do? GCC should be able to build itself, so it should be possible to build GCC and link that on 196 or December 1991, and get a native version of GCC on NT. The other possibility is to get newer versions of GCC (cc1 drop in replacements) to build for Xenix and / or OS/2. Obviously this Xenix linker is the gateway to older 386 Microsoft based products!

For those interested in such things, I’ve uploaded all of this to archive.org here: windows-nt-196-linking-and-running-gcc

Interesting? Maybe. October 1991 NT SDK uses the OS/2 toolchain

The linker is from an older MS SDK, the compiler from October 1991 preview of NT

So back in the day I wrote something vague about the October 1991 preview version of Windows NT, and after messing with the tools and building f2c & dungeon (among some other stuff) one that that stuck out to me is that the object files had to be converted for NT.

cvtomf!

The interesting thing is of course that it doesn’t support the cl386 direct compile and link (hence CL). Instead you have to compile, convert and then link. A fun thing about the October 1991 version is that there is a cl386 cross compiler for OS/2. So while looking around for OMF linkers (and assemblers that either understand GAS but output OMF, or some translator) I ran across this, and well yeah, it turns out that the OS/2 tool chain is the toolchain. I guess it makes sense in that the NT team was using OS/2 to build NT, but objects and exe’s were not solidified.

I think 6.00.080 was the last version of Microsoft C 386 for OS/2. I need to start collecting more of the SDK/DDK’s of the mixed era, I think the LX/OMF stuff was a bit more widespread hiding in plain sight.

Anyways, interesting?! sure. useful? Maybe 30 years ago. Although I’d probably say just use Watcom C/C++ instead of Microsoft C 6.00

MSDN from October 1994

I picked this 20 disc set recently and ugh the cringe is just… insane.  And yes, that is Bill Nye

 

STUDS from Microsoft .
(Video in MPEG-1/Audio MPEG-2 care of JSMpeg).

I had this ages ago, although I couldn't remember if the NT 3.5 SDK/DDK had shown up at this point, but it's only the Japanese version in this set.  Since I'm having such a PITA in tracking down a 3.5 set, and I'm not sitting on this, I may as well archive it.

Yes, I had to rip 20 of these!

So you too can find the early Video for Windows, and all kinds of other things from the mid '90's on archive.org.

Or Wallpapers like this 'puppy' from the Japanese version of Windows 3.1

https://archive.org/details/MSDNOctober1994

Re-enabling WinHelp on Windows 10

There was a shift years ago from the old help system that has it’s roots going back to Windows 3.0, and was certainly one of the killer features of Windows 3.0, the hyperlinked and searchable help files.  They were a form of compiled RTF files, and could also embed image resources, and later audio & video with the evolution of Windows.  This allowed for a platform for early multimedia encylopedias and other refrence books of sorts.

Starting with Windows Vista, however the WinHelp engine was being retired out for a CHM or compiled HTML help engine.  And for a whlie there optional updates and later downloads to re-enable WinHelp.  However starting with Windows 10 the downloads no longer work.

All is not lost however, if you copy any of the 32bit WinHelp programs from NT 3.1 onward it will still function on Windows 10.  And thanks to this great post on TenForums, you can re-enable the hook so that Windows 10 will integrate again with WinHelp.

@echo off
set crtpth=%CD%
takeown /f "%windir%\winhlp32.exe" >nul
icacls "%windir%\winhlp32.exe" /grant *S-1-5-32-544:F >nul
copy /y "%crtpth%\winhlp32.exe" %windir%
icacls "%windir%\winhlp32.exe" /setowner "NT Service\TrustedInstaller" >nul
echo.
echo Done.
echo.
echo Press any key to Exit
pause >nul

WinHelp from Windows NT 3.1 refresh on Windows 10

And there we go, now I can load obsolete refrence docs from great old programs like Visual C++ 1.10 for Windows NT!

Naturally Microsoft removed all this stuff as it was a security risk, in that they apparently never revamped or updated it, so yeah it may be another infection vector.

Microsoft Fortran PowerStation for NT 1.00

So I came across this recently, and unlike the previous version I had for Windows 3.1, This version is for Windows NT.  And unlike the Windows 3.1 version this version does actually run on the shipping version of Windows NT 3.1, and thus will work all the though including Windows 10 on x64.  The setup program unfortunately doesn’t complete leaving it ‘unlicensed’ however it’ll still run.

The diskettes for the Windows 3.1 version I have are dated 11-23-93, but once installed the compiler is actually from February of 1993, with the Windows NT version being dated October of 1993.

So the nice thing with the Windows NT version is that you don’t have to mess with the compiler, and linker, it’ll just run.  And just like Visual C++ 1.0 / 1.10 for NT the linker doing a release build will always result in an exe being at least 2 megabytes in size.

I know that this is pretty much useless for 99.9999% of people.  Yes it’s ancient Fortran.  Yes Fortran PowerStation 4.0 is far more comprehensive.  Yes after it was sold to Compaq as part of some deal over the collapse of Dec & Windows NT, then sold out to Intel.  And GFortran is free.

But here we go.

32bit Fortran from 1993 in 2018!