After seeing the spotlight on twitter from WinWorld, on NetManage Chameleon, an old TCP/IP stack that supported Windows 3.0! With more details over on the forum. I was inspired to set it up myself.
I did go a bit overboard showing how to install MS-DOS & Windows 3.0 on Qemu. Maybe it’ll help someone who wants to try to use Qemu, but is too scared? Maybe I moved too quickly.
One thing I did do differently in this run, is launching the monitor and a serial port as tcp servers so I could telnet into the VM, effectively having a way to share text like a clipboard back and forth. I’m kind of surprised I hadn’t really started using Qemu in this manner much earlier.
It’s 1995 and I’ve been nearly two years in the professional workspace. OS/2 is the dominant workstation product, Netware servers rule the world, and the year of the Linux desktop is going to happen any moment now. If you weren’t running OS/2, you were probably running Windows 3.1, only very few people were using that Linux thing. What would have been the prefect OS at the time would have been NT with a competent POSIX subsystem, but since we were denied that, enter Hiroshi Oota with BSD on Windows.
It was a late night browsing yahoo auctions Japan as one does, laughing at the absurd Famicom/Super Famicom games, and I went ahead and looked for BSD CD-ROMS, where I first came across BSD on Windows. And then I’d forgotten about it and went to work on some Darwin projects.
Fast forward 3 weeks, and vic485 had bought it, had it shipped, and uploaded on archive.org. So a big super thanks to vic485 for making this all possible!
So what is it? It’s not quite BSD, its a bunch of 16bit DLL’s that broke the kernel down into subsystems, that each rely on winmem32.dll to give access to flat/32bit address space. BSD on Windows (BOW) being a hybrid 16/32bit app is originally for Windows 3.1, with the later 1.5 update for Windows 95, which includes support for long filenames. I’m not sure if it’ll run on Windows NT or OS/2, as I don’t think
So what do you get?
The key media contents are the install floppy and the CD-ROM. Yes the setup program IS only on the floppy. Hope you get that disk image. I’m unsure what the manual is like, other than of course it is in Japanese.
It’s very much a single user mode BSD like environment complete with vi/gcc/csh/perl just to name a few. I’ve been able to test job control, and building some simple programs like Hack 1.03. I found a few issues however.
I haven’t tested enough with FreeBSD 1/2 but I can verify that from my ‘Ancient Linux on Windows‘ packages, the object format is the same, which is that early era when everything was a.out, although all different the reliance on GNU GAS & LD did make the object format the same. And it was nice to compile a hello world from my Linux cross compiler, link it on BOW, and get a running executable.
The memory is weird, in that you can add hundreds of megabytes to Windows and BOW will always run exhausted. In the bow.ini file you can set the heap for each program, and I found out from some silly trial and error that the maximum heap you can effectively give is 13 megabytes. It seems that winmem32 has a single chunk of memory where all processes run out of, hence the sub 16mb ram zone. Maybe there is a way to allocate it, but I’m unsure, maybe it’s in the book. CC1 was frequently having issues, so setting it’s heap to 13M sure helped, the linker ‘ld’ of course was running out of memory as well so setting it to 8M got me linking.
Filenames, especially on Windows 3.1 are a huge problem. All the LFN TSR’s I tried to load just resulted in a full crash. I had to point the linker to the CD-ROM live filesystem, which maybe would be tedious on a real machine, but under emulation it’s fine.
BOW does NOT like Qemu. At all. It won’t under otvdm either. I suspect NT is a no go but I haven’t tried. Oddly enough it’s not a timing issue, as it does run under VMware. There is an advantage to running it under Windows 95, is that it supports long filenames. 86Box works as well, I even was using the Pentium II Xeon at 400Mhz and that ran fine.
Probably the most annoying and silly thing is that the GCC C compiler doesn’t have C++ style comments turned on. Not being able to use ‘//’ is quite annoying.
Hack ran fine on my 386, which was a pleasant surprise!. It was really cool to have Word+Excel and Hack running at the same time.
Had I known about this, it would have been an incredible bridge product. Not to mention cross compiling to even Win32, or Linux. Not to mention at the time being able to run BSD with no real pain, just install and go
There is generic TCP/IP Winsock support in BOW 1.5 as it simply calls winsock. This also includes the ability to run daemons, however limitations in BOW are quickly exposed, such as missing setuid/setgid sno there is no ability to impersonate lower privileged users. MMAP stuff also doesn’t seem to work, although I was able to build a super simple port of Apache 1.3.1 to BSD on Windows (BOW).
While BOW may appear to be very BSD like, there is a lack of a the mmap Apache needs, along with user mapping & impersonation. I ended up using the EMX – OS/2 system code, since it’s very POSIX like without relying on the Unix like OS actually working.
I’ve been able to serve pages to myself, however BOW crashing out many emulators and hypervisors kind of stops me from putting it on the internet. BOW enthusiasts can download it from archive.org
Today, there is really no point to BOW, it’s an interesting oddity, but back in the day, for a jr network administrator being able to run the Unix version of the snmp tools, even if it’s only client side would have been great. If tftpd could be built to run this would have been beyond amazing, as you not only get BSD, but full Windows apps at the same time, much like MachTen.
It’s a shame I never knew this was a thing, I certainly would have been evangelizing BOW! Who knows what other treasures are in the parallel societies of Japan/Asia/Europe?
Back in the olden days of when Microsoft had pivoted out of OS/2 in a hurry, I’ve always felt that the common ‘OMF’ objects ought to link for OS/2. But for some reason I never tried. But for some reason I thought I’d try it today.
I first installed Microsoft C 6.0, and set it up for a native OS/2 to OS/2 1.2 setup. This way I get a pure OS/2 include/library directory set. In retrospect, I don’t know why I didn’t just use 2 include / library directory sets to far easier target stuff, without dealing with changing the default names, and making linking an all around living hell.
So the first thing to do is to tell QuickC for Windows to default to the OS/2 include directory (turns out it wont link anyways). Compiling is nothing special. When setting up the project you’ll need a DEF file, I use this simple one:
NAME QCO2 WINDOWAPI
PROTMODE
CODE PRELOAD
Nothing to it!
I tried to fight the Windows linker, but it figures out what you are doing and won’t do it. But can you manually link? Well QuickC for Windows does include a DOS linker, and it’s oddly enough newer than the one for Microsoft C 6.0!
C:\proj\o2>msdos \WIN16APP\QCWIN\bin\link hi.obj
Microsoft (R) Segmented-Executable Linker Version 5.15
Copyright (C) Microsoft Corp 1984-1991. All rights reserved.
Run File [hi.exe]:
List File [NUL.MAP]:
Libraries [.LIB]: doscalls SLIBCE
Definitions File [NUL.DEF]: qco2.def
C:\proj\o2>msdos hi.exe
This program cannot be run in DOS mode.
Manually invoking the linker wasn’t all too hard, just answer the 30 questions. I did set the LIB environment variable so it picked up the libraries just fine. And yes, it created my OS/2 binary no problem!
And as you saw from above, yes it does run!
I do suppose the graphical editors would have been nice some 30 years ago, but in today’s era, sadly it doesn’t matter. QuickC for Windows won’t run under WLO, so this prevents it being a backdoor GUI/Protected mode compiler for OS/2. It’s a shame too as at least running under Windows 3.0, QuickC for Windows is WAY faster than using Microsoft C 6.00 in either read mode, protected mode with smartdrive.. I’m not sure what the deal is. Even with the advanced caching SCSI controller.
A talk from Dave Probert on the design of the NTOS kernel. Shame Microsoft didn’t put this anywhere people could have found this 20+ years ago, just as a shame they never opened up NTOS like they did that even tepid Windows Research Kernel. It goes without saying this is the ‘Linux is a cancer’ generation, with the crazed idea that looking at Linux would contaminate Windows.
So I had gotten this Boca Ram/2 card with 2MB of RAM, with space for an additional 6MB. Unfortunately trying to find matching memory has been a lost cause. Since the existing memory is 9 chip modules, I take that to mean it’s parity RAM, so I went shopping for much more available 3 chip modules.
I picked up 2x 1MB modules for £10.
Slotting them carefully into the ram card, taking great care as the clips are plastic!
Now from what I can remember being told is to never ever ever mix memory types like this. But logically I have to think that 9×1 = 4+4+1, right? RIGHT?!
I copied the @7A7A.ADF onto the reference disk image, slotted the card and booted up to the config, and toggled the card to 4M
I didn’t trust the auto-config, plus I just wanted to see what was there. Also I’ve always wondered if the PS/2 model 60 (or 30? 50z?) can slot higher density than the 256kb SIMM’s that IBM had used. I guess one day I’ll give it a shot.
Anyways thinking that this is about done, I save the config and reboot and now It’s Bocaram/2 issues.
Immediately, on reboot I get error 164.
164 POST detected a base memory or extended memory size mismatch error.
1. Run F1 Setup. Check System Summary menu for memory size change. 2. Run the Extended Memory Diagnostic tests.
Booting from the reference disk just crashes the PC.
Fantastic.
Pressing F1 however does let you boot, ignoring the issue.
After a bunch of digging I found this zip file with some utils. And just guessing br2pmems ‘fixes’ the CMOS settings allowing the machine to boot normally.
So now it’ll recognize the 5MB of RAM, and just boot normally. GREAT. But booting the reference disk still hangs the machine.
Which then brings me to the next upgrade:
The IBM SCSI with Cache aka the SPOCK. Since I ruined the one SCSI card, and ended up picking up a second card, but this time with the appropriate cable I’ve caused a massive market panic on Microchannel SCSI cards. Seriously check eBay, and you will see that the pricing has collapsed with many now selling in the £20-30 range. You’re welcome!
Not really wanting a 3rd SCSI card, but my eye saw this one with the cache RAM, and I figured if I wanted the ultimate PS/2 of course I’d want a caching controller. This looks to be the first rev of the PCB, but with the ‘hot fixes’ in place from the second rev. While the ROMs are stepping back to 1990, I don’t care much about the 1GB disk limit, as the BlueSCSI can emulate all the available devices in the chain, so I’m not losing anything in the way of capacity. This is a 286 after all.
Since the RAM card screws up the setup program, I have to remove it, and the old SCSI controller, re-configure the system with all the RAM and disks removed first. Then put in the new controller, and re-run setup.
I just accept the defaults, and reboot to check what happened. So far it looks good, slot 8 being near the middle of the PCB, and closer to the disk cage where the blue SCSI rests.
Remembering that the IBM controllers inventory the disks backwards, the 380MB disk image on SCSI ID 6, is the primary boot disk. I didn’t set it to the full 1GB as I want to later see how older versions of DOS/OS2 work with this, and I know they have issues with disks bigger than 512MB, but I figured matching a disk that did exist in 1988 would be more realistic.
With the SCSI setup, I could put the troublesome Boca board back with the RAM, and get my system booting up with the new “faster” SCSI controller, and all that new RAM.
Of course I did a few benchmarks on the old SCSI controller so I would know how much more awesome the new one is.
As you can see this is booted with my normal config.sys with a himem.sys and smartdrv from Windows 3.1 on a MS-DOS 5.1 install.
2,345.8 KB/sec With himem.sys & smartdrv
2,347.5 KB/sec with no himem.sys
2,316.6 KB/sec with runtime xmsmmgr & smartdrv
2,334.0 KB/sec with Windows 3.1 himem.sys no smartdrv
So, with these scores in hand, you can see that the penalty for various XMS memory access being turned on is there, but it’s nowhere near as massive as I’d have thought for performance. Even with it just being there, although again it’s so minimal.
Now for the real shocker:
That’s right, the advanced card is slower. A good 11% slower. Well, that was disappointing. I’m still keeping it in the machine, as having a hardware caching controller was all the rage, just like Mach microkernels. Maybe it’d make more of a difference in a 32bit system, but it’s performance is very underwhelming. For anyone wondering, the WDC AC2340, is an EIDE 340MB hard disk, with a 64kb cache. Im sure it was considered very fancy, and fast for the era, and it’s nice to know that no matter the SCSI controller, the BlueSCSI blows it out of the water. Also keeping in mind that MFM data transfers are usually sub 400KB/sec, so this is much more faster.
Okay you have all this XMS what are you going to do with it?
Well, after I did manage to get this original copy of Word for Windows 1.0, I thought that it would be a good test. One fun thing is that it includes the ‘runtime’ version of Windows 2.11, which can also upgrade an existing install of Windows 2 if detected. Running Windows 2 on MS-DOS 5, does involve loading the setver command in the config.sys, and rebooting. Windows 2 cannot use XMS (more on that) but instead uses the older LIM EMS standard that allows a 64kb page to be viewed from a far larger card. Since the 8086/80286 still use 64kb segments it’s not all that crazy to use.
And that brings me to this great program EMM286!
It allocates a 64kb page in low ROM, and backfills it from XMS. So I give it 3MB, and now I have 1.3MB of XMS left, and 3MB of LIM EMS ready for Windows!
So now I have EMS & XMS! And didn’t have to get some pesky EMS board either. I am pretty sure you need device drivers to use EMS, so how do you use LIM EMS under OS/2 1.x? I have no idea. Probably not I guess?
Anyways I run word, everything is great, it sees extra ram. I exit windows, and unload EMM286, and ..
3.4MB of XMS available? Somehow I lost a megabyte of RAM from Windows 2?! I’m not sure what is going on, or why or how Windows even touched it. Needless to say if you want it back, you need to reboot.
That’s right 494KB free! I thought MS-DOS under OS/2 just used some stubs in real mode, and called back to protected mode. No doubt this is totally wrong, there has to be some weird version of DOS+OS2 that actually runs in real mode going on here. I know that ‘bimodal drivers’ were a thing, but it sure seems like there really is a ‘real mode OS/2’ kernel with MS-DOS tacked onto the side.
It’s annoying OS/2 can’t tell you how much ram it sees and what is in use, but at least Windows 3.0 can. It’s more than enough to run Sim City, clearly making this one of the more expensive machines to run the game as intended. With the added RAM it doesn’t thrash as hard, but having emulated disks probably doesn’t matter as much as access time is always zero, and it’ll stream data as fast as it can. You can feel the difference moving between tasks, but things like the OS/2 file manager that loads a view into every directory is still incredibly slow. What were they thinking?!
Thouhts?
Back in the day this would have been an incredibly expensive upgrade. And is it worth it? The machine is still locked at 10Mhz. The FPU is also locked at 10Mhz, and you can feel it. The lightening fast disk access, despite it being some 11% slower is really hard to tell. Does the caching help at all? Applications don’t have to page in/out like crazy before as there is enough RAM to actually run them, but that is where the 10Mhz processor just isn’t there.
Just like the caching SCSI controller, I’m sure we’ve all heard how having that magical EMS memory would help out games like Wing Commander.
Well, I had to put them side by side, as I couldn’t believe it, but adding EMS made it noticeably slower. I was *NOT* expecting that. I should add that I used Vegas & this quick tutorial, on how to pan & resize one video to get them side by side. No doubt it’s not perfect but it’s enough to see that once the ship explodes, the performance on the EMS configuration is greatly throttled. It’s moments like this that makes me wonder is this something the caching SCSI card would do better implicitly? Or is it snake oil as well?
3MB is enough to load OS/2, and one application, just as Word v1 or Excel v2/v3 load just fine, but swapping between them is basically unloading one from memory, and loading the other back out to disk. It’s a shame RAM cost so much 1987-1992 as people really could have benefited from it. It’s just utterly bizarre that on such an outrageously expensive system that you even need RAM upgrade cards, it really should have been baked into the main logic board.
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 andanOpenNT 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.
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:
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:
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!
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!
With the pre-christmas release of the Microsoft OS/2 betas 1.00, 1.01, 1.02, 1.03 & 1.05 on archive.org, and helping Ncommander with an upcoming video, it seemed like a good place to start, not with OS/2 but rather with MS-DOS 4.0.
Microsoft started work on a multitasking version of MS-DOS in January 1983. At the time, it was internally called MS-DOS version 3.0. When a new version of the single-tasking MS-DOS was shipped under the name MS-DOS version 3.0, the multitasking version was renamed, internally, to MS-DOS version 4.0. A version of this product–a multitasking, real-mode only MS-DOS–was shipped as MS-DOS version 4.0. Because MS-DOS version 4.0 runs only in real mode, it can run on 8088 and 8086 machines as well as on 80286 machines. The limitations of the real mode environment make MS-DOS version 4.0 a specialized product. Although MS-DOS version 4.0 supports full preemptive multitasking, system memory is limited to the 640 KB available in real mode, with no swapping.2 This means that all processes have to fit into the single 640 KB memory area. Only one MS-DOS version 3.x compatible real mode application can be run; the other processes must be special MS-DOS version 4.0 processes that understand their environment and cooperate with the operating system to coexist peacefully with the single MS-DOS version 3.x real mode application.
Because of these restrictions, MS-DOS version 4.0 was not intended for general release, but as a platform for specific OEMs to support extended PC architectures. For example, a powerful telephone management system could be built into a PC by using special MS-DOS version 4.0 background processes to control the telephone equipment. The resulting machine could then be marketed as a “compatible MS-DOS 3 PC with a built-in superphone.” Although MS-DOS version 4.0 was released as a special OEM product, the project–now called MS-DOS version 5.0–continued. The goal was to take advantage of the protected mode of the 80286 to provide full general purpose multitasking without the limitations–as seen in MS-DOS version 4.0–of a real-mode only environment. Soon, Microsoft and IBM signed a Joint Development Agreement that provided for the design and development of MS-DOS version 5.0 (now called CP/DOS). The agreement is complex, but it basically provides for joint development and then subsequent joint ownership, with both companies holding full rights to the resulting product.
As the project neared completion, the marketing staffs looked at CP/DOS, nee DOS 5, nee DOS 4, nee DOS 3, and decided that it needed…you guessed it…a name change. As a result, the remainder of this book will discuss the design and function of an operating system called OS/2.
– Inside OS/2.
Although MS-DOS 4.00M disk images have been floating around for quite some time, either a 2 360k disk set, or a single 720k disk image, I don’t think anyone (including me) really tore into it that much. It does have the ability to freeze DOS 3 programs, giving the illusion of running more than one. The session manager is pretty sparse but hitting left alt twice will pop it up giving you the ability to toggle through programs with ease.
There is a FDISK, FORMAT & SYS command making it straight forward to setup a hard disk, and copy the files over, I didn’t see any installer.
there is a PS command to show running processes. Also there is a DOSSIZE to show the memory partitioning and how much is available. Although there is a SWAPPER program I’ve been unable to get it to actually fun.
Another interesting thing if you run the unix ‘strings’ command against all the EXE’s you’ll find the string:
C Library - (C)Copyright Microsoft Corp 1985
Implying that not only was DOS 4.00M a ‘new’ DOS, but it was also written in C. No doubt this contributed to a larger file size than DOS 3, however it would also give that holy grail of portability, at least to new CPU modes. Also many files have the name of the source files baked in such as:
Okay so far, so good. But we’ve all seen this before, and scratched this OS about this far, because what else can you do? It’s not like there is any dev tools to do anything fun!
Well the tool hidden in plain sight is LINK4, which in retrospect is specific for MS-DOS 4.00M.
Microsoft (R) 8086 Object Linker Version 4.01
Copyright (C) Microsoft Corp 1984, 1985. All rights reserved.
Object Modules [.OBJ]:
There is no SDK for MS-DOS 4.00M, but they were kind enough to leave the linker in place. A quick check of the Windows 1.01 SDK shows that it also includes LINK4:
Microsoft 8086 Object Linker
Version 4.00 (C) Copyright Microsoft Corp 1984, 1985
Object Modules [.OBJ]:
It appears that if the dates and versions are to be trusted they are of the same vintage, but the Windows linker is older, and that they both output to a NE or New Executable. So to start the experiment I created a simple hello world exe from a simple:
void main(){
printf("Hello from MSC 3\n");
}
To compile this I used Microsoft C 3.0 (more on why later), and used LINK4 to create an EXE:
C:\dos\msc3>cl /c hello.c
Microsoft C Compiler Version 3.00
(C)Copyright Microsoft Corp 1984 1985
hello.c
C:\dos\msc3>msdos dos4m\link4 hello.OBJ
Microsoft (R) 8086 Object Linker Version 4.01
Copyright (C) Microsoft Corp 1984, 1985. All rights reserved.
Run File [HELLO.EXE]:
List File [NUL.MAP]:
Libraries [.LIB]:
Definitions File [NUL.DEF]
Okay, everything looks fine so far. Attempting to run this under MS-DOS just results in the error:
Program too big to fit into memory
Well now that’s odd. Checking the EXE with the Linux ‘file’ command reveals:
file HELLO.EXE
HELLO.EXE: MS-DOS executable, NE (unknown OS 0) (EXE)
So obviously it’s a NE, but it is an older/unknown version to the file map database. There is no stub so I suppose that is why MS-DOS is getting confused.
Now let’s try MS-DOS 4.00M
Well now isn’t that interesting?!
Excited with the ability to create special MS-DOS 4.00M programs, I get my favorite vintage ’87 Infocom interpreter, InfoTaskForce 87, and get it building on MSC 3.0. However instead of using the MS-DOS 4.00M linker, I thought I should try to use the Windows 1.01 linker and libraries for the exe:
NAME Infocom
DESCRIPTION 'Infocom 87 interpreter for Planetfall(83)'
DATA MULTIPLE
HEAPSIZE 1024 ; Must be non-zero to use Local memory manager
STACKSIZE 4096 ; Must be non-zero for SS == DS
; suggest 4k as minimum stacksize
SEGMENTS
_INIT PRELOAD MOVEABLE DISCARDABLE
One thing to save you the horror is that between MS-DOS 2 & 3 the way command line arguments changed. I forget the details but no matter what I tried I was unable to parse the CLI or the environment in this setup. I suppose if I had documentation of the product there would be some hint as to what tools or setup to use. Instead, I took the easy way and hard coded to load Planetfall.
Unfortunately, this success would prove to be the exception to the rule. I took trek, converted it to K&R C, as Microsoft C 3.00 from 1985 is well. old, and sadly it just won’t run. Likewise, I took Hack 1.03 and although it runs on MS-DOS it will not run on MS-DOS 4.00M. I am sure there is some fundamental reason why it’s not working, and probably tied to creating a proper DEF file. I’m sure it was all written down somewhere but I don’t know. And yes I tried specifying either floating point emulation via library or inline, and it made no difference.
Looking at OS/2 1.00
Loading up the infamous $3,000 OS/2 1.00 beta, and hitting ctrl+escape you are greeted with session manager!
Notice the R for real-mode. With the obvious implication that everything else is protected mode. Going one step further on the excellent site pcjs.org there is OS/2 betas SIZZLE and although there is no OS/2 development bits on there, the directory DOS3TOOL reveals that the C compiler for this era for at least MS-DOS is MSC 3.0. Also included is our friend LINK4.
I create a simple def file that contains the single word ‘PROTMODE’ which should give me my OS/2 binary.
So let’s run that through hello world:
msdos sizzle\DOS3TOOL\link4 hello.OBJ,hello,,,hello.def;
Microsoft (R) Segmented-Executable Linker Version 5.00.21
Copyright (C) Microsoft Corp 1984, 1985, 1986. All rights reserved.
C:\dos\msc3>
However attempting to run this just crashes amazingly.
No doubt it’s because the real-mode libc is using interrupt 21 calls, which OS/2 sure wouldn’t like. I’m pretty sure it requires an OS/2 libc that uses DOSCALLS.DLL to function, which I just don’t have any pre-release versions, nor any libc source code to really make it possible. And attempting to port one to OS/2 pre-releases just doesn’t seem so worth the time.
So for the heck of it I point the LIB variable to the OS/2 1.00 SDK’s libs and re-run the link:
C:\dos\msc3>msdos sizzle\DOS3TOOL\link4 hello.OBJ,hello.exe,hello.map,C:box0\x\MSC\LIB\slibc5.lib box0\x\LIB\DOSCALLS.LIB,hello.def;
Microsoft (R) Segmented-Executable Linker Version 5.00.21
Copyright (C) Microsoft Corp 1984, 1985, 1986. All rights reserved.
By default it’s trying to link in EM.LIB, SLIBFP.LIB, SLIBC.LIB. Trying to add them all in the command line link just hangs LINK4 maybe a response file is better suited. Anyways:
It does run on OS/2 1.00, which I guess isn’t surprising as the LINK4 & libraries are from/for this version.
As an interesting note, OS/2 links against doscalls library/DLL to interface to the OS. While MS-DOS 4.00M doesn’t have a seperate DLL, rather it’s baked into IBMDOS.COM
Noticeably absent is file I/O, No doubt allowing programs to use the standard int21 interface to the kernel for file I/O. No doubt this is in its primordial state, as the OS was going to evolve a bit more until it became OS/2. Unfortunately I have no idea how to link or call into this. Without any SDK it’s impossible to say. And even then is developing for a real mode OS worth the effort?
So what have we learned? LINK4, aka the MS-DOS 4.00M Linker, probably should have been called LINKNE for the NE format. Also there is references to it having it’s own virtual memory paging system, and being able to link larger EXE’s than the traditional link command. Sadly I was unable to get any non trivial programs running. I don’t think it was a memory model thing, although the C compiler has issues with InfoTaskForce and the large memory model for some reason, but small & medium work fine. I’d like to think that DOS 4.00M could support massive EXE’s much like Windows 1.01, however despite being from the same company and using the same tools, the memory manager for DOS 4.00M & Windows is fundamentally different.
With all these exiting OS/2 betas now available I’ll have to take some more time to explore them in more detail.
But until then I thought this genesis of DOS 4.00M was worth the look.
I was so tired I ended up sleeping through the whole thing. Sometimes it’s hard being on the other side of the planet. But for anyone interested in Windows programming it’ll be super interesting in how much has changed, and yet how much things haven’t changed.
As an added bonus, 65scribe has also blessed us with not only another great retrospective on iMacs, but also our favorite museum in Ontario, but left us with a cliff hanger (minor spoiler!).
I never knew about the artic blue ice thing before. Maybe it’s a coincidence, but who knows?!
(This is a guest post by Antoni Sawicki aka Tenox)
While everybody is busy buzzing about Windows 11, I wanted to commemorate the finest operating system ever made by Microsoft – Nano Server.
For most of people Nano Server was esoteric, distant and unapproachable. It had a rather high entry barrier, requiring you to build it on a Windows Server 2016 host using PowerShell magic spells. You couldn’t just simply download and run it. Even if you managed to get it running, there wasn’t anything you could actually do with it for fun. People didn’t bother to even check it out. My goal is to demystify this a bit, lower the entry bar and made it easy for people to hack it.
Background info (you can skip it)
Nano Server was an interesting attempt at creating a datacenter grade OS that’s not managed via local GUI, keyboard and mouse, but rather full automation, remote tooling and code. It went one step further than Server Core or Windows PE by completely removing GUI components and local shell. Hence it’s not actually called “Windows” or “Windows Nano” but rather simply “Nano Server”. Rumor has it, it started as MinWin. The OS has a rudimentary text mode console with functionality similar of VMware ESXi console. However Nano was much more than a bare metal hypervisor. It was a fully fledged operating system. Unlike ESXi you can develop and install services/apps for it and hypervisor wasn’t even it’s default role.
Ever since I first saw a demo on Microsoft Ignite (previously known as TechEd) I wanted to run aclock on the text console. Much like the WinNT BSOD edition. This article started around my efforts to run (or port if needed) aclock to this platform. At the time of writing, the technology has been dead for several years now. However all the artifacts and documentation are still available on Microsoft’s website. Probably not for long, so a good moment to do it now, before everything gets deleted in to oblivion.
How to quickly deploy Nano Server and run command line apps on the console
Microsoft provides (soon to be deleted) Nano Server Quick Start. However the steps are trivial so you can totally skip that and just do this:
Launch PowerShell terminal window on the WS2016 host.
Run: Import-Module D:\NanoServer\NanoServerImageGenerator -Verbose (D:\ drive being where Windows Server CDROM is mounted)
Run: New-NanoServerImage -DeploymentType Guest -Edition Standard -MediaPath d:\ -BasePath c:\nano -TargetPath c:\nano.vhdx -ComputerName nano -Development (c:\nano folder and c:\nano.vhdx image will be created for you)
Done! This will build a .vhdx image that can be run under Hyper-V as “Gen-2” VM. For Gen-1 or to run it on any other hypervisor change .vhdx to .vhd in -TargetPath while running the PowerShell command.
The easy way: you can just download a pre-built VM image from here. There are VHD for Hyper-v Gen-1 and VHDX for Hyper-v Gen-2 and OVA for everything else.
First Boot
Once you boot it up you will be greeted with a PowerShell prompt. Just like that! You can type cmd to launch the good old cmd.exe shell. MS-DOS 2016?
Keep in mind, this is a developer mode (see -Development flag). Normally you would be greeted with a login prompt and a boring menu that allows to change some networking settings and not much beyond that. In production mode you need to resort to hacks (or this) to get stuff running, fortunately nothing like that needed here.
So what can you run on it?
Firstly in order to get some external utilities going, you can mount a SMB share using net use in cmd or New-SMBMapping in PS world. Nano being a server and all, you can also share out a folder via net share or use C$ (you may need to create a user by using either net user /add in cmd or New-LocalUser in PS). Alternatively you can install Posh-SSH and use SCP to transfer files. If you don’t have working network you can just shut it down, mount the vhd image on the host and copy stuff in to the image then detach the VHD.
Aclock worked on the first run, no issues, using standard win64 exe:
Wow! So looks like Nano console does have basic terminal controls. That opens quite a lot of possibilities. But can you run more complex apps? Text editors? Web browsers? GAMES?
Well, yes…, but likely not, but it really depends – on dependencies (read: DLLs).
The font is lacking line drawing characters. Some editors like YEdit allow to use ASCII drawing characters fortunately.
There is no reverse video. This manifests mostly in menus, etc. however it also applies to the cursor.
There is no cursor, or rather the cursor is an underscore and not transparent cell. Moving arrow left in the CLI doesn’t actually move the cursor it erases characters. There is no line editing.
Also related to reverse video, it appears Nano console has some weird issues with colors.
Missing DLLs. Nano Server not being a “Windows” OS is missing a lot of Windows DLLs and it has its own nano DLL hell. This has actually been acknowledged in MinWin. As such a lot of apps will not launch due to dependencies.
For example YEdit works remarkably well except for the menus, which use reverse video:
Update: Malcolm has fixed it in latest version of YEdit! Thank you!
Update: thanks to Ron Yorston you can also run BusyBox on Nano! All you need to do is get the 64bit version and before you run it set an environmental variable to disable ANSI emulation. In CMD set BB_SKIP_ANSI_EMULATION=0 in PS $env:BB_SKIP_ANSI_EMULATION=0. Done!
You even get ls colors and vi editor works flawlessly! Unix shell on Nano, thats awesome!
So what about games?
Initially nothing worked as expected. Either due to line drawing, colors or previously mentioned DLL hell. There was one game that actually worked – PowerShell adaptation of snake:
But I wanted something better. I had high hopes for ascii-patrol, which is pure text mode and they build it for win64. Unfortunately the game requires a bunch of multimedia / sound DLLs from Windows which are not present in Nano.
Thankfully Neozeed has stepped in, took the source code, amputated all the multimedia stuff, borrowed the Unix clock code and gettimeofday, and used an older Visual Studio to build it. But he managed to produce a fully working and playable version!!!! Truly amazing stuff!
The binary is available here. To play the game scroll down one screen to start a mission. If you enter profile customization simply press ESC to get out. Thanks again Neozeed!
I’m hoping readers can find more text mode/ascii apps and games that will work on the console. Please comment and send links!
In another dimension, having a working text editor, Yori shell, smb/scp, maybe with help of mingw64, sdk tools or borrowed compilers from Visual Studio, one could have a self hosted developer workstation with this.
For now please just download the pre-build image, or make one yourself and run it in your favorite hypervisor and have some fun with it!
With this, goodbye Nano Server! You will be always remembered. I know folks at Redmond tried really hard to make it such beautiful gem.
In my “C:\Program Files (x86)\Windows Kits\10\Emulation\Mobile\10.0.14393.0” directory I have a modest 2GB file called flash.vhd which contains the phone image. I copy it to where I run my VM’s and run it with the XDE emulator:
And I’m running in no time, I login, load some apps, then I notice the storage:
What?! the disk image is a paultry 10GB. I guess the idea is that you wouldn’t actually try to load up the emulator like it’s your daily driver, rather you load YOUR app and only YOUR app, and just pretend that this isn’t some weird offshoot nostalgia machine.
Well needless to say something needs to be done about this storage situation.
I look and find this package, vhdutils. I had to go to some sketchy site, but it did include source. I should put this somewhere more legit to take away from all those weird squatters.
So with stuff installed onto my phone I’m almost at 7GB physical 7.6 virtual space. I could go all crazy with 128 or 256GB but it’d largely be stuff I bought… which of course thanks to the magical world of DRM won’t play.
Yeah I guess you are welcome that I bought all those movies, and stuff but sure I wasn’t going to watch them on this phone… emulator. Thanks. thanks again.
So the resize vhd is quick. brutal. and efficient. I go with 64GB, because, why not? I could probably just grow it again if I needed to.
Now for the fun part. We need to attach the vhd, and resize the volume. I hope you like diskpart.
In the MMC I attach the disk image.. it’ll pop a few folders as it’s got a bunch of drive letters. I’ve never explored a phone, I don’t know if the ARM images are just as weird.
Even more strange, it’s MBR!
So if you were thinking, lots of partitions, and a clear win for GPT, sadly this isn’t it.
Sadly there is no free partitions (although one hiding could be deleted…?) And the UI doesn’t support expanding a logical drive (the green container). But diskpart does.
As indicated above the emulator’s vhd is disk3. You can see it’s the 64GB disk. Select it.
Next list the volumes. The Data disk (J:) is what we want so select Volume 10.
Literally just ‘select volume 10’ and ‘extend’. Don’t tell me this is difficult.
Listing the volumes again will show a 59GB Data partition. Congratulations we did it!
Back in the MMC, you’ll see it as well how the Data partition, along with the green extended partition is now taking up the entire disk. So we can now Detach the VHD, and run the emulator again!
And just like that we now have plenty of free space on the emulator.
I downloaded some games, and some music. It’s nice to be back home.
It’s not an extensive list as I didn’t game much on my phone but here is what I know works:
Final Fantasy 1
Heroes of Larkwood
Skulls of the Shogun
Sonic CD
FL Studio
Candy Crush Saga
Pixel Dungeon +
Halo Spartan Asslt just closes, and Asphalt 8: Airborne doesn’t get the screen size right so it’s impossible to click enough buttons.
It’s nice that sonic runs, (haha) although using a mouse makes it impossible to control.
Now one fun thing is that the emulator is x86, nor ARM based so I converted the VHD to a VMDK, ran it under VMware, and YES it RUNS… sort of.
Perhaps a format that never was to be, the Phone/Tablet but it boots quickly and is so responsive. Windows without most of the .. Windows bits. I guess the real experiment will have to be will it run on a Surface?
It’s all 32bit anyways, and such an evolutionary dead end. Pitty.