Examining Windows 1.0 HELLO.C

The following is a guest post by NCommander of SoylentNews fame!

For those who’ve been long-time readers of SoylentNews, it’s not exactly a secret that I have a personal interest in retro computing and documenting the history and evolution of the Personal Computer. About three years ago, I ran a series of articles about restoring Xenix 2.2.3c, and I’m far overdue on writing a new one. For those who do programming work of any sort, you’ll also be familiar with “Hello World”, the first program most, if not all, programmers write in their careers.

A sample hello world program might look like the following:

#include <stdio.h>


int main() {
 printf("Hello world\n");
 return 0;
}

Recently, I was inspired to investigate the original HELLO.C for Windows 1.0, a 125 line behemoth that was talked about in hush tones. To that end, I recorded a video on YouTube that provides a look into the world of programming for Windows 1.0, and then testing the backward compatibility of Windows through to Windows 10.

For those less inclined to watch a video, my write-up of the experience is past the fold and an annotated version of the file is available on GitHub (https://github.com/NCommander/win1-hello-world-annotations)


Bring Out Your Dinosaurs – DOS 3.3

Before we even get into the topic of HELLO.C though, there’s a fair bit to be said about these ancient versions of Windows. Windows 1.0, like all pre-95 versions, required DOS to be pre-installed. One quirk however with this specific version of Windows is that it blows up when run on anything later than DOS 3.3. Part of this is due to an internal version check which can be worked around with SETVER. However, even if this version check is bypassed, there are supposedly known issues with running COMMAND.COM. To reduce the number of potential headaches, I decided to simply install PC-DOS 3.3, and give Windows what it wants.

You might notice I didn’t say Microsoft DOS 3.3. The reason is that DOS didn’t exist as a standalone product at the time. Instead, system builders would license the DOS OEM Adaptation Kit and create their own DOS such as Compaq DOS 3.3. Given that PC-DOS was built for IBM’s own line of PCs, it’s generally considered the most “generic” version of the pre-DOS 5.0 versions, and this version was chosen for our base. However, due to its age, it has some quirks that would disappear with the later and more common DOS versions.

PC DOS 3.3 loaded just fine in VirtualBox and — with the single 720 KiB floppy being bootable — immediately dropped me to a command prompt. Likewise, FDISK and FORMAT were available to partition the hard drive for installation. Each individual partition is limited, however, to 32 MiB. Even at the time, this was somewhat constrained and Compaq DOS was the first (to the best of my knowledge) to remove this limitation. Running FORMAT C: /S created a bootable drive, but something oft-forgotten was that IBM actually provided an installation utility known as SELECT.

SELECT’s obscurity primarily lies in its non-obvious name or usage, nor the fact that it’s actually needed to install DOS; it’s sufficient to simply copy the files to the hard disk. However, SELECT does create CONFIG.SYS and AUTOEXEC.BAT so it’s handy to use. Compared to the later DOS setup, SELECT requires a relatively arcane invocation with the target installation folder, keyboard layout, and country-code entered as arguments and simply errors out if these are incorrect. Once the correct runes are typed, SELECT formats the target drive, copies DOS, and finishes installation.

Without much fanfare, the first hurdle was crossed, and we’re off to installing Windows.

Windows 1.0 Installation/Mouse Woes

With DOS installed, it was on to Windows. Compared to the minimalist SELECT command, Windows 1.0 comes with a dedicated installer and a simple text-based interface. This bit of polish was likely due to the fact that most users would be expected to install Windows themselves instead of having it pre-installed.

Another interesting quirk was that Windows could be installed to a second floppy disk due to the rarity of hard drives of the era, something that we would see later with Microsoft C 4.0. Installation went (mostly) smoothly, although it took me two tries to get a working install due to a typo. Typing WIN brought me to the rather spartan interface of Windows 1.0.

Although functional, what was missing was mouse support. Due to its age, Windows predates the mouse as a standard piece of equipment and predates the PS/2 mouse protocol; only serial and bus mice were supported out of the box. There are two ways to solve this problem:

The first, which is what I used, involves copying MOUSE.DRV from Windows 2.0 to the Windows 1.0 installation media, and then reinstalling, selecting the “Microsoft Mouse” option from the menu. Re-installation is required because WIN.COM is statically linked as part of installation with only the necessary drivers included; there is no option to change settings afterward. The SDK documentation details the static linking process, and how to run Windows in “slow mode” for driver development, but the end result is the same. If you want to reconfigure, you need to re-install.

The second option, which I was unaware of until after producing my video is to use the PS/2 release of Windows 1.0. Like DOS of the era, Windows was licensed to OEMs who could adapt it to their individual hardware. IBM did in fact do so for their then-new PS/2 line of computers, adding in PS/2 mouse support at the time. Despite being for the PS/2 line, this version of Windows is known to run on AT-compatible machines.

Regardless, the second hurdle had been passed, and I had a working mouse. This made exploring Windows 1.0 much easier.

The Windows 1.0 Experience

If you’re interested in trying Windows 1.0, I’d recommend heading over to PCjs.org and using their browser-based emulator to play with it as it already has working mouse support and doesn’t require acquiring 35 year old software. Likewise, there are numerous write-ups about this version, but I’d be remiss if I didn’t spend at least a little time talking about it, at least from a technical level.

Compared to even the slightly later Windows 2.0, Windows 1.0 is much closer to DOSSHELL than any other version of Windows, and is essentially a graphical bolt-on to DOS although through deep magic, it is capable of cooperative multitasking. This was done entirely with software trickery as Windows pre-dates the 80286, and ran on the original 8086. COMMAND.COM could be run as a text-based application, however, most DOS applications would launch a full-screen session and take control of the UI.

This is likely why Windows 1.0 has issues on later versions of DOS as it’s likely taking control of internal structures within DOS to perform borderline magic on a processor that had no concept of memory protection.

Another oddity is that this version of Windows doesn’t actually have “windows” per say. Instead applications are tiled, with only dialogue boxes appearing as free-floating Windows. Overlapping Windows would appear in 2.0, but it’s clear from the API that they were at least planned for at some point. Most notable, the CreateWindow() function call has arguments for x and y coordinates.

My best guess is Microsoft wished to avoid the wrath of Apple who had gone on a legal warpath of any company that too-closely copied the UI of the then-new Apple Macintosh. Compared to later versions, there are also almost no included applications. The most notable applications that were included are: NOTEPAD, PAINT, WRITE, and CARDFILE.

While NOTEPAD is essentially unchanged from its modern version, Write could be best considered a stripped-down version of Word, and would remain a mainstay until Windows 95 where it was replaced with Wordpad. CARDFILE likewise was a digital Rolodex. CARDFILE remained part of the default install until Windows 3.1, and remained on the CD-ROM for 95, 98, and ME before disappearing entirely.

PAINT, on the other hand, is entirely different from the Paintbrush application that would become a mainstay. Specifically, it’s limited to monochrome graphics, and files are saved in MSP format. Part of this is due to limitations of the Windows API of the era: for drawing bitmaps to the screen, Windows provided Display Independent Bitmaps or DIBs. These had no concept of a palette and were limited to the 8 colors that Windows uses as part of the EGA palette. Color support appears to have been a late addition to Windows, and seemingly wasn’t fully realized until Windows 3.0.

Paintbrush (and the later and confusingly-named Paint) was actually a third party application created by ZSoft which had DOS and Windows 1.0 versions. ZSoft Paintbrush was very similar to what shipped in Windows 3.0 and used a bit of technical trickery to take advantage of the full EGA palette.

With that quick look completed, let’s go back to actually getting to HELLO.C, and that involved getting the SDK installed.

The Windows SDK and Microsoft C 4.0

Getting the Windows SDK setup is something of an experience. Most of Microsoft’s documentation for this era has been lost, but the OS/2 Museum has scanned copies of some of the reference binders, and the second disk in the SDK has both a README file and an installation batch file that managed to have most of the necessary information needed.

Unlike later SDK versions, it was the responsibility of the programmer to provide a compiler. Officially, Microsoft supported the following tools:

  • Microsoft Macro Assembler (MASM) 4
  • Microsoft C 4.0 (not to be confused with MSC++4, or Visual C++)
  • Microsoft Pascal 3.3

Unofficially (and unconfirmed), there were versions of Borland C that could also be used, although this was untested, and appeared to not have been documented beyond some notes on USENET. More interestingly, all the above tools were compilers for DOS, and didn’t have any specific support for Windows. Instead, a replacement linker was shipped in the SDK that could create Windows 1.0 “NE” New Executables, an executable format that would also be used on early OS/2 before being replaced by Portable (PE) and Linear Executables (LX) respectively.

For the purposes of compiling HELLO.C, Microsoft C 4.0 was installed. Like Windows, MSC could be run from floppy disk, albeit it with a lot of disk swapping. No installer is provided, instead, the surviving PDFs have several pages of COPY commands combined with edits to AUTOEXEC.BAT and CONFIG.SYS for hard drive installation. It was also at this point I installed SLED, a full screen editor as DOS 3.3 only shipped with EDLIN. EDIT wouldn’t appear until DOS 5.0

After much disk feeding and some troubleshooting, I managed to compile a quick and dirty Hello World program for DOS. One other interesting quirk of MSC 4.0 was it did not include a standalone assembler; MASM was a separate retail product at the time. With the compiler sorted, it was time for the SDK.

Fortunately, an installation script is provided. Like SELECT, it required listing out a bunch of folders, but otherwise was simple enough to use. For reasons that probably only made sense in 1985, both the script and the README file was on Disk 2, and not Disk 1. This was confirmed not to be a labeling error as the script immediately asks for Disk 1 to be inserted.

The install script copies files from four of the seven disks before returning to a command line. Disk 5 contains the debug build of Windows, which are roughly equivalent to checked builds of modern Windows. Disk 6 and 7 have sample code, including HELLO.C.

With the final hurdle passed, it wasn’t too hard to get to compiled HELLO.EXE.

Dissecting HELLO.C

I’m going to go through these at a high level, my annotated hello.c goes into much more detail on all these points.

General Notes

Now that we can build it, it’s time to take a look at what actually makes up the nuts and bolts of a 16-bit Windows application. The first major difference, simply due to age is that HELLO.C uses K&R C simply on the basis of pre-dating the ANSI C function. It’s also clear that certain conventions weren’t commonplace yet: for example, windows.h lacks inclusion guards.

NEAR and FAR pointers

long FAR PASCAL HelloWndProc(HWND, unsigned, WORD, LONG);

Oh boy, the bane of anyone coding in real mode, near and far pointers are a “feature” that many would simply like to forget. The difference is seemingly simple, a near pointer is nearly identical to a standard pointer in C, except it refers to memory within a known segment, and a far pointer is a pointer that includes the segment selector. Clear right?

Yeah, I didn’t think so. To actually understand what these are, we need to segue into the 8086’s 20-bit memory map. Internally, the 8086 was a 16-bit processor, and thus could directly address 2^16 bits of memory at a time, or 64 kilobytes in total. Various tricks were done to break the 16-bit memory barrier such as bank switching, or in the case of the 8086, segmentation.

Instead of making all 20-bits directly accessible, memory pointers are divided into a selector which forms the base of a given pointer, and an offset from that base, allowing the full address space to be mapped. In effect, the 8086 gave four independent windows into system memory through the use of the Code Segment (CS), Data Segment (DS), Stack Segment (SS), and the Extra Segment (ES).

Near pointers thus are used in cases where data or a function call is in the same segment and only contain the offset; they’re functionally identical to normal C pointers within a given segment. Far pointers include both segment and offset, and the 8086 had special opcodes for using these. Of note is the far call, which automatically pushed and popped the code segment for jumping between locations in memory. This will be relevant later.

HelloWndProc is a forward declaration for the Hello Window callback, a standard feature of Windows programming. Callback functions always had to be declared FAR as Windows would need to load the correct segment when jumping into application code from the task manager. Hence the far declaration. Windows 1.0 and 2.0, in addition, had other rules we’ll look at below.

WinMain Decleration:

int PASCAL WinMain( hInstance, hPrevInstance, lpszCmdLine, cmdShow )
HANDLE hInstance, hPrevInstance;
LPSTR lpszCmdLine;
int cmdShow;

PASCAL Calling Convention

Windows API functions are all declared as PASCAL calling convention, also known as STDCALL on modern Windows. Under normal circumstances, the C programming language has a nominal calling convention (known as CDECL) which primarily relates to how the stack is cleaned up after a function call. In CDECL-declared functions, its the responsibility of the calling function to clean the stack. This is necessary for vardiac functions (aka, functions that take a variable number of arguments) to work as the callee won’t know how many were pushed onto the stack.

The downside to CDECL is that it requires additional prologue and epilogue instructions for each and every function call, thereby slowing down execution speed and increasing disk space requirements. Conversely, PASCAL calling convention left cleanup to be performed by the called function and usually only needed a single opcode to clean the stack at function end. It was likely due to execution and disk space concerns that Windows standardized on this convention (and in fact still uses it on 32-bit Windows.

hPrevInstance

if (!hPrevInstance) {
/* Call initialization procedure if this is the first instance */
if (!HelloInit( hInstance ))
return FALSE;
} else {
/* Copy data from previous instance */
GetInstanceData( hPrevInstance, (PSTR)szAppName, 10 );
GetInstanceData( hPrevInstance, (PSTR)szAbout, 10 );
GetInstanceData( hPrevInstance, (PSTR)szMessage, 15 );
GetInstanceData( hPrevInstance, (PSTR)&MessageLength, sizeof(int) );
}

hPrevInstance has been a vestigial organ in modern Windows for decades. It’s set to NULL on program start, and has no purpose in Win32. Of course, that doesn’t mean it was always meaningless. Applications on 16-bit Windows existed in a general soup of shared address space. Furthermore, Windows didn’t immediately reclaim memory that was marked unused. Applications thus could have pieces of themselves remain resident beyond the lifespan of the application.

hPrevInstance was a pointer to these previous instances. If an application still happened to have its resources registered to the Windows Resource Manager, it could reclaim them instead of having to load them fresh from disk. hPrevInstance was set to NULL if no previous instance was loaded, thereby instructing the application to reload everything it needs. Resources are registered with a global key so trying to register the same resource twice would lead to an initialization failure.

I’ve also gotten the impression that resources could be shared across applications although I haven’t explicitly confirmed this.

Local/Global Memory Allocations

NOTE: Mostly cribbled off Raymond Chen’s blog, a great read for why Windows works the way it does.

pHelloClass = (PWNDCLASS)LocalAlloc( LPTR, sizeof(WNDCLASS) );
LocalFree( (HANDLE)pHelloClass );

Another concept that’s essentially gone is that memory allocations were classified as either local to an application or global. Due to the segmented architecture, applications have multiple heaps: a local heap that is initialized with the program and exists in the local data segment, and a global heap which requires a far pointer to make access to and from.

Every executable and DLL got their own local heaps, but global heaps could be shared across process boundaries, and as best I can tell, weren’t automatically deallocated when a process ended. HEAPWALK could be used to see who allocated what and find leaks in the address space. It could also be combined with SHAKER which rearranged blocks of memories in an attempt to shake loose bugs. This is similar to more modern-day tools like valgrind on Linux, or Microsoft’s Application Testing tools.

MakeProcInstance

lpprocAbout = MakeProcInstance( (FARPROC)About, hInstance );

Oh boy, this is a real stinker and an entirely unnecessary one at that. MakeProcInstance didn’t even make it to Windows 3.1 and its entire existence is because Microsoft forgot details of their own operating environment. To explain, we’re going to need to dig a bit deeper into segmented mode programming.

MakeProcInstance’s purpose was to register a function suitable as a callback. Only functions that have been marked with MPI or declared as an EXPORT in the module file can be safely called across process boundaries. The reason for this is that Windows needs to register the Code Segment and Data Segment to a global store to make function calls safely. Remember, each application had its own local heap which lived in its own selector in DS.

In real mode, doing a CALL FAR to jump to a far pointer automatically push and popped the code segment as needed, but the data segment was left unchanged. As such, a mechanism was required to store the additional information needed to find the local heap. So far, this is sounding relatively reasonable.

The problem is that 16-bit Windows has this as an invariant: DS = SS …

If you’re a real mode programmer, that might make it clear where I’m going with this. The Stack Segment selector is used to denote where in memory the stack is living. SS also got pushed to the stack during a function call across process boundaries along with the previous SP. You might begin to see why MakeProcInstance becomes entirely unnecessary.

Instead of needing a global registration system for function calls, an application could just look at the stack base pointer (bp) and retrieve the previous SS from there. Since SS = DS, the previous data segment was in fact saved and no registration is required, just a change to how Windows handles function epilogs and prologs. This was actually found by a third party, and a tool FixDS was released by Michael Geary that rewrote function code to do what I just described. Microsoft eventually incorporated his fix directly into Windows, and MakeProcInstance disappeared as a necessity.

Other Oddities

From Raymond Chen’s blog and other sources, one interesting aspect of 16-bit Windows was it was actually designed with the possibility that applications would have their own address space, and there was talk that Windows would be ported to run on top of XENIX, Microsoft’s UNIX-based operating system. It’s unclear if OS/2’s Presentation Manager shared code with 16-bit Windows although several design aspects and API names were closely linked together.

From the design of 16-bit Windows and playing with it, what’s clear is this was actually future-proofing for Protected Mode on the 80286, sometimes known as segmented protection mode. On 286’s Protected Mode, while the processor was 32-bit, the memory address space was still segmented into 64-kilobyte windows. The primary difference was that the segment selectors became logical instead of physical addresses.

Had the 80286 actually succeeded, 32-bit Windows would have been essentially identical to 16-bit Windows due to how this processor worked. In truth, separate address spaces would have to wait for the 80386 and Windows NT to see the light of day, and this potential ability was never used. The 80386 both removed the 64-kilobyte limit and introduced a flat address space through paging which brought the x86 processor more inline with other architectures.

Backwards Compatibility on Windows 3.1

While Microsoft’s backward compatibility is a thing of legend, in truth, it didn’t actually start existing until Windows 3.1 and later. Since Windows 1.0 and 2.0 applications ran in real mode, they could directly manipulate the hardware and perform operations that would crash under Protected Mode.

Microsoft originally released Windows 286, and 386 to add support for the 80286 and 80386, functionality that would be merged together in Windows 3.0 as Standard Mode, and 386 Enhanced Mode along with legacy “Real Mode” support. Due to running parts of the operating system in Protected Mode, many of the tricks applications could perform would cause a General Protection Fault and simply fail. This wasn’t seen as a problem as early versions of Windows were not popular, and Microsoft actually dropped support for 1.x and 2.x applications in Windows 95.

Windows for Workgroups was installed in a fresh virtual machine, and HELLO.EXE, plus two more example applications, CARDFILE and FONTTEST were copied with it. Upon loading, Windows did not disappoint throwing up a compatibility warning right at the get-go.

Accepting the warning showing that all three applications ran fine, albeit it with a broken resolution due to 0,0 being passed into CreateWindow().

However, there’s a bit more to explore here. The Windows 3.1 SDK included a utility known as MARK. MARK was used, as the name suggests, to mark legacy applications as being OK to run under Protected Mode. It also could enable the use of TrueType fonts, a feature introduced back in Windows 3.0.

The effect is clear, HELLO.EXE now renders in TrueType fonts. The reason TrueType fonts are not immediately enabled can be see in FONTTEST, where the system typeface now overruns several dialog fields.

The question now was, can we go further?

35 Years Later …

As previously noted, Windows 95 dropped support for 1.x and 2.x binaries. The same however was not true for Windows NT, which modern versions of Windows are based upon. However, running 16-bit applications is complicated by the fact that NTVDM is not available on 64-bit installations. As such, a fresh copy of Windows 10 32-bit was installed.

Some pain was suffered convincing Windows that I didn’t want to use a Microsoft account to sign in. Inserting the same floppy disk as used in the previous test, I double-clicked HELLO and Feature Installer popped up asking to install NTVDM. After letting NTVDM install, a second attempt shows, yes, it is possible to run Windows 1.x applications on Windows 10.

FONTTEST also worked without issue, although the TrueType fonts from Windows 3.1 had disappeared. CARDFILE loaded but immediately died with an initialization error. I did try debugging the issue and found WinDbg at least has partial support for working with these ancient binaries, although the story of why CARDFILE dies will have to wait for another day.

In Closing …

I do hope you enjoyed this look at ancient Windows and HELLO.C. I’m happy to answer questions, and the next topic I’m likely going to cover is a more in-depth look at the differences between Windows 3.1 and Windows for Workgroups combined with demonstrating how networking worked in those versions.

Any feedback on either the article, or the video is welcome to help me improve my content in the future.

Until next time,

73 de NCommander

Free386 (386|DOS-Extender – RUN386 compatible)

I just found this late last night. The world can always use another DOS Extender, and here we go, out of Japan with Free386!

  • Version: 0.61
  • Date: 2016/12/28
  • Author: [email protected]
  • Machine: PC/AT(DOS/V)
  • Machine in Japanese: FM-TOWNS, PC-9801/PC-9821
  • Compatible: MS-DOS and XMS and VCPI (with HIMEM.SYS and EMM386.EXE)
  • Language: NASM (Full assembly language)
  • Licence: PDS (Free386.com and Free386’s source files)

You can find it here: https://github.com/nabe-abk/free386

Poorly machine translated readme as follows:


From the futon, I thought i’d publish the “Free386” of dos-extender that I had made before to GitHub.

If you want to publish it anyway, NASM and alink also included together and if there is a DOS environment, i thought that anyone can assemble it is out of luck. I found a bug in alink when generating flat mode.exe/.com file. It’s around here that i started to go crazy in a lot of ways(laughs)

Patching alink was done on Linux. I then used TOWNS-gcc to generate alink.exp, but i used the MP header format that TOWNS-gcc generates. We found a bug that the EXP file cannot run on its own. If this is not corrected, it is not possible to distribute including the development environment because it does not usually have the EXP execution environment. When I checked, there was a bug in how to allocate memory, and when the memory capacity started to exceed 8MB, i was allocating memory space that does not exist in the back.

In fact, Free386 at the time was a lot of files that didn’t work properly, and i was worried because it became unstable, it was a mistake in the allocation of memory that is not. However, to examine this, i created a tool to dump memory maps and paging (i.e., it’s included), it was quite a bit of a hassle.

Now, when the memory allocation bug is fixed, almost all DOS generic EXP files and many TOWNS software now work. However, towns-OS’s biggest mystery system is the CoCo/NSD driver around the moss, and the software written in F-BASIC386 does not start. When you come this far, you want to move it.

So we start editing the CoCo/NSD driver. After a little research, I immediately found out the following.

  • CoCo.EXE resides in DOS memory (real memory).
  • NSDD resides in extended memory.

This means that CoCo is presumed to load nsd files into extended memory and manage that information. Now the question is how to get that management information. Is there information in coco memory that resides like SYSINIT? I thought.

For now, to check the area, Free386, i attached the ability to dump the register status before and after the int service was executed by hooking up the interrupt. We analyzed \hcopy\deldrv.exp, which has the ability to remove the specified NSD driver, as “we need to find the NSD driver and the structure seems simpler” in the mechanism.

------------------------------------------------------------------
Int = 0000_008E  CS:EIP = 000C:0000_1ADC   SS:ESP = 0014:0001_0B88
 DS = 0014        ES = 0060        FS = 0014        GS = 0014
EAX = 0000_C003  EBX = 0000_0001  ECX = 0000_0000  EDX = 0000_66EC
ESI = 0000_0246  EDI = 2074_6E00  EBP = 0001_0C48  FLG = 0000_0046
CR0 = 8000_0021  CR2 = 0000_0000  CR3 = 0002_9000    D0 S1 P1 C0  
------------------------------------------------------------------
*Ret:*
 DS = 0014        ES = 0014        FS = 0014        GS = 0014
EAX = 0000_0003  EBX = 0000_0010  ECX = 0000_0000  EDX = 0001_0C18
ESI = 0000_0246  EDI = 2074_6E00  EBP = 0001_0C48  FLG = 0000_0006
CR0 = 8000_0021  CR2 = 0000_0000  CR3 = 0002_9000    D0 S0 P1 C0  
------------------------------------------------------------------

Information like this comes out a lot in turn. If you look at the changes in coco’s residency and other changes in behavior, you can see that int 8eh/AX=Cx0x is a CoCo service. At the same time, log int 8eh and make a resident.com file (included) run386. I also looked at the behavior of the EXE and explored the commonalities of both of them, and i thought, “How would I design the mechanism if I were you?” We looked up coco services from the perspective of “**.

Then we traced to a service that provides driver resident information called int 8eh/AX=C103h. Using this information, the NSD driver in extended memory could be correctly pasted into memory and implemented on the selector. To verify, I ran deldrv.exp using Free386 and was able to uninstall the NSD driver correctly.

Great. End.

…… I wish I had solved it in that way.

TOWNS-OS is an OS of a mysterious structure, and even though there is a BIOS (TBIOS) of 32bit Native mode for graphicprocessing, some services such as timers use the BIOS of FM-R compatible 16-bit operation as it is. It has an incomprehensible structure to use it from the 32bit program side while managing resources, such as a 16-bit timer BIOS.

In terrible cases, each time the processing and interrupt of real-mode resources such as timers and keyboards, switch the CPU to real mode, if during those real-mode BIOS processing, interrupt the PROCESSING of the BIOS, such as FM sound source or VSYNC occurs, it seems to return to protected mode once.

NSD driver called forRBIOS (for Real BIOS) is the intermediary for this incomprehensible structure. Just as DOS-Extender acts as an intermediary for 32-bit programs and MS-DOS, it acts as a real-mode BIOS and a 32bit program intermediary.

In a RUN386 environment, when forRBIOS.NSD is built in, interrupt vectors such as int 8eh are rewritten so that the NSD driver gets the interrupt. **Where is this information? ** That was a mystery that was left behind. However, RUN386 is a . No matter how much the INT log is done until you run EXP, it doesn’t look like it. If you look at the memory of the coco that is resident, there is no information that seems to be it.

If you’re not going to initialize the resident NSD itself. I thought, i patched the entry of the resident forRBIOS, and when the service routine was called, i tried to use the rough business of falling into an infinite loop was bingo.

Finally, you can now run exp files generated by F-BASIC386 and so on. The analysis results are recorded in the doc. By the way, when you run a program that does not require forRBIOS (written in High-C, etc.), the whole process is slower than when you initialize forRBIOS. I really think this is the specs of TOWNS-OS (laughs)

This is the first time in more than a decade since the development was suspended in 2001, and the DOS-Extender, which is compatible with RUN386, was made.

What is with the price of retro Japanese software?

So I was lucky enough to get to Beep before it close, and I picked out a couple of FM Towns titles (and a junker!), and I thought ‘Return to Zork’ would be a good title, something to compare the MacOS & MS-DOS versions against.

Although slightly faded, it does come in this nice box, which reminds me of the NEOGEO… which is probably an apt comparison.

The artwork has faded, although the CD-ROM inside was still sealed, never before opened. I picked this up for an eye watering ¥3,480 but flipping the box over revealed the launch price of an astonishing ¥12,800! I’m not sure what the exchange rate from 1994 was, but even at a generous 100:1 JPY to USD that’s half the price of the old multimedia kits which included the drive, sound card and so many came bundled with Return to Zork.

Another random title I grabbed was even more insane!

¥ 14,800 for Silent Möbius: Case: Titanic!

I need to get a RGB monitor & keyboard to see if this thing even works, meanwhile I fought with UNZ to get it running, and the mouse tracking is totally broken unless you change the DPI scaling, credit to this post in the UNZ ‘BBS’.

One thing is sure, the voice acting in the Japanese version is so terrible.

As people complain about ‘AAA’ games, and paying $60, just look at this! $134 USD for some cartoon boat game thing.. Although I’ve never heard of Silent Möbius or played it, I just saw it was available for the x68000 and PC-98. So I guess it’s one of those Lowest Common Denominator games.

One interesting thing about the FM TOWNS is that they have that ROM DOS with CD-ROM drivers, and their apparently blanket licensing for PharLap 386. Although while I was wasting time looking at cartoon rabbits, someone else scooped but the 386 BASIC kit. Darn.

But in the Return to Zork world, the ‘made.exe’ is in fact a Pharlap 386 EXP, meaning that it runs in 386 protected mode, so you don’t have to struggle with emm386, himem.sys and trying to get a ludercus 580-600kb of conventional memory. Seriously it was such a chore to get this running the manual has a big section on setting up a boot disk. It’s a shame they didn’t license a DOS extender for the US PC platform, although I can see why they chose that route on the FM Towns (and I believe PC98), as there is a RTZ9821 directory there which includes an EXP. Shame it was never relased state side as a patch, as it would have been a GREAT user change. Well that or a Win32 executable.

Games! Games! Games!


Come on Sal, never miss a game!

Yeah! Over the MS-DOS collection over at archive.org is well over 2,500! Isn’t that great?!?

Well let’s take a peek at a few favorites…

Sadly DataEast’s greatest hit RoboCop doesn’t work correctly on the site, however if you were to do something evil like open up the inspector, and manually download the asset yourself it’ll load fine in actual DosBox. It’s a great side scroller, even 30 years later. Yes, 1989 was a long long time ago.

Buck Rogers – Matrix Cubed was a great fun SSI Action/RPG of the day, more of a maze crawler unlike Buck Rogers: Countdown to Doomsday being more older style top down. And speaking of, for any SSI/Buck Rogers fans out there I hope you have checked out I am not a Monster: Complete Edition, which rides the fun line of homage & parody.

And speaking of SSI, Curse of the Azure Bonds and it’s ilk are available as well! I’m not sure how a board game company with a vast library (and IP rights licensed) could possibly fail so hard. Maybe the games were too difficult? Maybe they were too involved? I guess I’m guilty of it too, as I’m the uncleansed masses that preferred Fallout 3 to 1&2. Just as Diablo took off as it removed the clock, and turned it into action.

Project-X was a favorite shoot-em-up on the Amiga, although it being PAL was surprisingly significantly harder to play on my NTSC Amiga, with not being able to see all the screen, running faster, and the insane blinking of some timing with the sprites. I didn’t know there was a PC version, but yeah it looks pretty much like the Amiga version. And it was one of the larger issues that a 386 PC with VGA & a SoundBlaster really not only was as good as an Amiga, but was just plain better as PC hardware kept on improving while Commodore trapped in their downward spiral just didn’t innovate.

Rise of the Triad – The Hunt Begins, this was a soso shooter, but where it really shone was it’s multiplayer maps and combat. It was a awesome time waster on the LAN. I never tried it dialup, or even in modern times, but many fond memories of this game. And it didn’t need insane requirements, unlike say Quake. And it was surprisingly more fast paced than DooM. I wonder sometimes if they had released the source code to ROTT (2002) much sooner than ID released DooM (1997), or around the same time if it’d have achieved more retro popularity? Or was it more of as LAN game, and my experience with it kind of lacking in single player the prevalent feeling?

MechWarrior was at first this incredible 3D game where you could pilot a battle mech in the 31st century! How awesome! It changed the world from the table top rules of BattleTech – The Crescent Hawk’s Inception into something action based. Amazingly the genre for some reason never seems to get the massive appeal I always felt it should have. Although Mark Kern is trying to do something with Mechs & Kaiju over at Em-8er.

3D games like NASCAR Racing arriving in 1994 were really pushing the boundaries of what you could realistically do in MS-DOS with 3D. And of course Quake basically drew the boundary of MS-DOS into Windows with the primary reason being better and uniform 3D drivers. You need a STRONG MS-DOS machine for this, so for me at least DosBox in javascript on a 2006 Mac Pro just wasn’t really up to the task.

Turbo Out Run, a SEGA classic game. The graphics are … well caught in a world between 1987 and 1990. I guess they either didn’t want to push the PC too hard, or accidentally release a superior game on a non SEGA platform? It could have looked better. It should have sounded better. It’s ‘fine’ but I kind of call shenanigans. Golden Axe is way better.

So this is by no means an exhaustive list, I left out a LOT, as 2,500 is way too much to give any reasonable review without it turning into a book, but I scanned the first hundred or so and picked out what caught my eye.

AVGN reviews Chex Quest

Okay that was funny. I never thought of even trying Brutal DooM + Chex Quest. Sounds awesome.

Although I’d played a little with Chex Quest before, I never tried it on the DooM source. Oddly enough it’s Ultimate DooM. In d_main.c you can do some simple test for chex.wad and pass it off as the ‘retail’ version.

	if ( !access (chex,R_OK) )
	{
		gamemode = retail;
		D_AddFile (chex);
		return;
	}

Or you can simply just rename chex.wad to doom.wad or doomu.wad. Many of the strings for DooM are compiled into the EXE, not taken from the WAD file (although it could have been, I guess it was to prevent people from making overtly cheeky mods?).

So firing up the wad under my crappy DooM port thing to MS-DOS (for the sane people just use some other Win64/OSX/Linux thing like zdoom), and when selecting an episode you’ll see the Ultimate DooM levels.

Chex Quest, Thy Flesh Consumed!

Wait? What? I though Chex Quest was a ‘total conversion’ WAD. Well it turns out that it is, and it isn’t. They replaced a lot of the default stuff from a retail version of Ultimate DooM. And what they didn’t replace, well it’s still there. And yes that does mean everything outside of the first 5 levels are the original DooM levels. And that includes the music as well!

E2M2 from Chex Quest

Well isn’t that surprising! And yes that means that it’s possible to just replace the first 5 levels with the default DooM levels and have that reverse conversion. In the same way the menu screens are very Chexy too:

It certainly gives that kid like feeling to it. Although the replacement Barrons of Hell are a little too big so they do look kind of silly.

E1M8

So as always I’m late to the party. I’m sure someone out there didn’t have the retail version of DooM and instead used Chex Quest for those LAN games. Although it does detect that the WAD has been modified so I don’t think it would just be all that fine.

Not that finding the original WAD files, or source to the maps, and just compiling them yourself is all that difficult, but I guess it is something else to load up.

PCem v15 released!

The new dynamic recompiler appears to be much more faster, although if you want maximum performance, make sure to set your video card to the fastest possible performance.

I was doing my typical DooM thing, and the performance was abysmal. But I did have an 8bit VGA card selected, so what would I really expect? Interestingly enough in ‘low resolution’ mode it performed quite well, but setting it to the artificial ‘fastest PCI/VLB’ speed it was performing just great.

PCem v15 released. Changes from v14 :

  • New machines added – Zenith Data SupersPort, Bull Micral 45, Tulip AT Compact, Amstrad PPC512/640, Packard Bell PB410A, ASUS P/I-P55TVP4, ASUS P/I-P55T2P4, Epox P55-VA, FIC VA-503+
  • New graphics cards added – Image Manager 1024, Sigma Designs Color 400, Trigem Korean VGA
  • Added emulation of AMD K6 family and IDT Winchip 2
  • New CPU recompiler. This provides several optimisations, and the new design allows for greater portability and more scope for optimisation in the future
  • Experimental ARM and ARM64 host support
  • Read-only cassette emulation for IBM PC and PCjr
  • Numerous bug fixes

Thanks to dns2kv2, Greatpsycho, Greg V, John Elliott, Koutakun, leilei, Martin_Riarte, rene, Tale and Tux for contributions towards this release.

As always PCem can be downloaded here:

Early MSDN CD’s on archive.org

I ran across this, and thought it was cool. These CD’s are getting harder and harder to find, and unless you want the old physical disks, getting ISO images is, of course the next best thing.

Granted these disks replaced the much older Microsoft Programmer’s Library. The new CD’s use a Windows based search & interface program removing the clunky old MS-DOS program that made it feel like trying to view the world through a straw. (Although the up side of the MS-DOS version is that you could easily dump the video RAM and save the contents to plain text).

And in this brave new post Windows 3.0 centric world of Microsoft just about everything regarding OS/2 was dumped, and the seeding of Win32 via Windows NT had started.

Naturally after winning this war, Microsoft withdrew many low end products and just couldn’t compete with the tidalwave that was GNU/Linux.

At any rate for the curious kids down the road that want to see what all the fuss was with Win16, and how Windows 3.0 had changed the landscape removing the force of IBM it’s worth a look.

Quake 2 for MS-DOS full playthrough

Playthrough by TheSlipGateUser

I was just alerted to this playthrough of Quake 2 for MS-DOS by TheSlipGateUser which showcases the game play under DOSBox.

Honestly I’m terrible at Quake, QuakeWorld and Quake 2, but it’s great to see someone who knows that they are doing, and more so that under emulation the game is holding up.

I know the MS-DOS port isn’t exactly the most popular in the world, although I suspect if it had been a thing in 1997 there would have been an audience with people that didn’t want to have Windows in the background as a distraction.

That said, any new people will of course want to check out the excellent (if I do say so myself!) series “Porting Quake II to MS-DOS“.

Microsoft Bookshelf (1991)

I found this online a while ago, although it’s taken about half a year to pick it up, but here we are.

What is kind of cool about this, is that being from 1991 this is not for Windows, that this reference library instead targets MS-DOS using the MSL/Microsoft Library from the Programmer’s Library.  So the same advantage holds true, that the content can be scraped from the text mode video RAM.

Factbook: Hong Kong

So yeah, back in the day this was some really amazing stuff, the ability to search a few books in some incredibly fast and convenient, although as always lacking super depth.

Back then online services were crazy expensive, charging by the minute, and of course just like the stock MS-DOS client preventing you from being able to easily copy the text.  Outside of anything beyond gradeschool I couldn’t imagine the ‘encyclopedia’ being of all that much worth but the dictionary/thesaurus & quotations is okay enough, although in 2018 it really is showing it’s age.

Having your own private reference back then was a big deal, something like this would have been more apt in a library, but you’d have to wait in line, no doubt as the ability to look up stuff just by typing would have been great.  While using this online would have cost quite a bit quickly justifying the cost of a CD-ROM drive along with the program.

The common carrier and lower costs of delivering content over the internet has really made something like this an oddity of time, but for anyone that needs to work 100% offline, these are a real gem.

Another great use of extracting the books from the CD-ROM, is that you can take, say the “American Heritage Dictionary“, a 30MB file, and compress it with 7zip, yielding a file just under 4MB, or an 87%, or a 7.76:1 compression ratio.  So unlike other ‘dictionary’ test compression sets, this is using an actual dictionary.

For anyone wanting to take a dive, I put it on archive.org

MS-DOS v1.25 and v2.0 Source Code now on github

This repo contains the original source-code and compiled binaries for MS-DOS 1.25 and MS-DOS 2.0.

These are the same files originally shared at the Computer History Museum on March 25th 2014 and are being (re)published in this repo to make them easier to find, reference-to in external writing and works, and to allow exploration and experimentation for those interested in early PC Operating Systems.

License

All files within this repo are released under the MIT (OSI) License as per the LICENSE file stored in the root of this repo.


At first I just thought it was simply just another mirror of the original source that had been released that had some incredible restrictions.

Original license:
To access this material, you must agree to the terms of the license displayed here, which permits only non-commercial use and does not give you the right to license it to third parties by posting copies elsewhere on the web.

However the restrictions have been lifted, and MS-DOS 1.25 & 2.0 are now available under a MIT license.

So this is actually very awesome!

You can download it here: https://github.com/Microsoft/MS-DOS.