Good news, it actually works! I was using the version 1.1 WAD, so honestly weird crashes really aren’t unexpected. I haven’t looked much at what to do with audio, but I was really impressed compared to the Qauake II wars, it was really surprising to not only see DooM run on the first shot in real metal, but the keyboard works as well. Well enough for me to pick a level, and get killed.
Naturally it doesn’t work under Windows, however it runs fine with MS-DOS mode.
Around the time of the x68000 port of DooM, I was cutting down the DooM source for a null/portable version. I never could get it to actually run either using EMX or DJGPP 1.03, as I couldn’t get it to link to save my life with a constant never ending battle of unresolved symbols. After a while I just used what I had towards the x68000 version and concentrated on getting it up and running, and just shelved the null/portable effort.
Later on I wanted to get it running again as part of messing with another cross compiler, as DooM isn’t a trivial application to port and verify correct operation. And in the process of trying to get the null version to build and run on Windows using TDM GCC, I wanted to make sure it at least kept compiling with GCC v1.x.
Once more again I was able to compile individual files but unable to link. But this time, I just looked at the diffs for binutils, I thought it should be somewhat easy to get hosted on Windows. Although versions may point to binutils 1.0, I had to use binutils-1.9.tar.gz even though the diffs are against Mar 24 1991, and the source for 1.9 is dated April 17 1991.
My first effort gave me a linker that would happily link, but go32 would either refuse to run the executable, or just crash. I was going to give up again, but I found mention in another file that DJGPP actually uses the linker from G++, the C++ compiler which was a separate thing in the late ’80s and early’90’s. This time it worked, and I could link a trivial hello world style application!
Now that I finally had a cross linker actually working, I didn’t want to compile under emulation, so looking at the other diffs, they didn’t look too extensive. I went ahead ,and took DJGPP v1.06 and patched up the compiler & assembler to get a full cross toolchain. And in no time, I had a null version of DooM running on MS-DOS well at least tested on DOSBox.
This was fun, and all but I didn’t see any easy way to do fun things like hook interrupts so I could get the keyboard & clock like any good MS-DOS program. DPMI greatly eased this kind of stuff, so looking at the DJGPP history, DJGPP v1 version 1.10 actually adds preliminary DPMI support! And in the next version, DPMI was much more better supported, however the binary format had changed from a.out to COFF as part of the move to v1.11. I was able to take the memory, and DPMI portions from the final v1.12 libc, and manually build and run them against the v1.06 library / dev tools.
And much to my surprise, it actually worked! At least having the wrong format didn’t have any effect on how GO32 worked for me.
So feeling lazy, I snagged some of the support code from Maraakate’s revamp of DooM, just to make sure of the timer code, and the keyboard code, and again verified that I can build with the keyboard & timer ISR and I’m able to play the v1.9 shareware & commercial levels fine. I haven’t done a thing to clean up or update the DooM source itself against all the dozens of bugs and issues with Ultimate DooM, or other games like Chex Quest etc.
I’m sure 99% of people wouldn’t care but you can download it here:
Although I’m using DPMI to drive realtime events, if I looked further at the GO32 v1.06 environments I could either figure out how it operates it’s timer, or modify the extender directly to drive the PIC timer and keyboard as I need. But overlooking that, the vintage 1991 software is more than capable of running DooM.
Digital Equipment Computer Users’ Society (DECUS), used to put out tapes of interesting things to it’s members. Back when everyone didn’t have an internet connection, or even if they did a high speed one.
I was looking for stuff where I only had a patch, but not the original files. So it was great for me to not only dig out an ancient sed from the era, but also bison, and gas. The ancient binutils are great for people who need to manipulate the a.out format, although the later binutils version 2 supports far more formats by virtue of it’s “BFD” or binary file database or as it was known as back then a ‘big fucking deal’
If you have ancient and or obsolete stuff, GNU stuff can fill the void of the often missing vendor development tools. It’s crazy how many people sold the tools that kept their systems relevant, although needless to say that attitude pretty much solidified the end of their existence..
I haven’t tried to build any of it, but I figured for the time being, it may be easier to make some tap files for SIMH, and maybe someone else will do the hard work for me. Or it’ll be a lazy day type thing.
Date: Sun, 22 Mar 87 10:56:56 EST
From: rms (Richard M. Stallman)
The GNU C compiler is now available for ftp from the file
/u2/emacs/gcc.tar on prep.ai.mit.edu. This includes machine
descriptions for vax and sun, 60 pages of documentation on writing
machine descriptions (internals.texinfo, internals.dvi and Info
This also contains the ANSI standard (Nov 86) C preprocessor and 30
pages of reference manual for it.
This compiler compiles itself correctly on the 68020 and did so
recently on the vax. It recently compiled Emacs correctly on the
68020, and has also compiled tex-in-C and Kyoto Common Lisp.
However, it probably still has numerous bugs that I hope you will
find for me.
I will be away for a month, so bugs reported now will not be
handled until then.
If you can’t ftp, you can order a compiler beta-test tape from the
Free Software Foundation for $150 (plus 5% sales tax in
Massachusetts, or plus $15 overseas if you want air mail).
Free Software Foundation
1000 Mass Ave
Cambridge, MA 02138
[tapes are generally in Unix tar format. If you have other needs,
write to the above address, and ask if they can be met. -len]
And indeed, the files are dated 22/03/1987 making this the first public release of GCC.
GNU CC is a fairly portable optimizing C compiler intended for
machines with 32-bit words that have several registers and address
memory in terms of 8-bit bytes. It supports full ANSI standard C, not
including libraries (which we do not consider to be part of a
Currently we have working machine descriptions for the Vax and for
the 68000/68020 (including 68881 support).
Optimizations performed by GNU CC include:
Invariant code motion out of loops.
Common subexpression elimination.
Automatic register packing (register declarations are unnecessary
Constant propagation and elimination of consequent dead code.
Elimination of dead stores.
Jump optimization including cross-jumping.
Delaying of stack adjustments after function calls.
Arithmetic performed in subword types when appropriate.
Many local optimizations.
GNU CC runs about as fast as PCC.
Most of the optimizations are machine-independent or controlled by a
machine description. GNU CC takes advantage of all the 68020
addressing modes that we can see how to make the Sun assembler
assemble. Debugging output for DBX is available whether you request
optimization or not.
Seeing as 4.3BSD didn’t ship until 1988, I went ahead and set out to build this on 4.2BSD. The first stumbling block I hit is that GCC needs bison. The oldest version of bison I have is 1.25 which honestly is just too new! However in the same location as GCC is this file gnu1988.tar.bz2 which contains all of the current GNU software of 1988! And what is on that tape?
So this is probably as old as it is going to get, so I downloaded and went to compile bison, however getopt is a missing call! A creative search found getopt.c and even better PCC liked it enough to get a running bison so I could then configure GCC.
Configuring GCC is a manual process, but not too involved:
Make a symbolic link from file `config.h’ to the top-level
config file for the machine you are using. Its name should be
`config-MACHINE.h’. This file is responsible for
defining information about the host machine. It includes
Make a symbolic link from `tm.h’ to the machine-description
macro file for your machine (its name should be
Make a symbolic link from `md’ to the
machine description pattern file (its name should be
Make a symbolic link from
`aux-output.c’ to the output-subroutine file for your machine
(its name should be `MACHINE-output.c’).Make sure the Bison parser generator is installed.Build the compiler. Just type `make’ in the compiler directory.
And in a minute I had GCC compiled. I ran it with -v and got this output:
# gcc -v
ld /lib/crt0.o -lc
It really is nowhere near as featured as 1.21 that is for sure! So time to do a simple hello world program:
So first thing is to build GCC 2… I couldn’t find any of the Linux patches for 2.0, 2.1 or 2.2.. I only tried to build 2.0 from source as targeting a.out i386 but it looks like the 2.0 files on the FSF’s site are missing files?
Anyways GCC 2.3.3 actually includes builtin support of Linux! I was able to build most of it, but just like GCC 2.5.8 for OS/2 EMX, But this time I used the gcc driver from GCC 2.6.3, which added support for Windows NT 3.5 native builds, and I now had my GCC cross compiler!
D:\aoutgcc\src>gcc2 -v -c hi.c -o hi
gcc version 2.6.3 -Linux 2.3.3
cpp2 -lang-c -v -undef -D__GNUC__=2 -Dunix -Di386 -Dlinux -D__unix__ -D__i386__ -D__linux__ -D__unix -D__i386 -D__linux hi.c C:\Temp\cca09324.i
GNU CPP version 2.3.3 (80386, BSD syntax)
cc12 C:\Temp\cca09324.i -quiet -dumpbase hi.c -version -o C:\Temp\cca09324.s
GNU C version 2.3.3 (80386, BSD syntax) compiled by GNU C version 5.1.0.
a386 -o hi C:\Temp\cca09324.s
Thankfully the prior binutils and assembler I was using in my GCC 1.40 cross compiler, still cooperated just fine, and I could happily build and link just fine.
From there it was a matter of fighting the makefiles as for some reason as make calls other makefiles they are not passing variables, so I just cheated, and changed the paths, along with editing the dependencies to finding stuff in a more sane manner. Plus all the Makefiles have include paths hard coded into the build process as expected. After fighting for a while, it linked and even better, it runs!
So yeah, using the MCC hard disk image from oldlinux.org and it boots!
Cool stuff, indeed!
As an added bonus I was also able to get 0.97 & 0.98 to compile as well!
Since the last update we got some help in a few fields that have really fleshed out this ‘experimental’ port into a full fledged port. First RayerR helped us with the fun of getting us onto the latest deployment of DJGPP, 2.05 (rc1). It’s always nice to be in the latest available release. Next in a passing comment, Ruslan Starodubov had mentioned that he had gotten a much older build of our QDOS to support the Intel HDA sound chipset via the MPXPlay sound library. I wrote to the author of MPXPlay, Pádár Attila asking for us to distribute his source in our project, and he granted permission.
So at this point things were looking good. The only ‘feature’ that modern OS’s really held over us was the ability to dynamically load and unload game modules on the fly. I had tried to use DLM, but it stripped the DPMI functionality out of the MS-DOS Extender making the port really useless. I tried to build the newer DXE3 support but had no luck. I suspect now my native tool chain was interfering with the build process. But Maraakate managed to get it to not only build, but to run!
Adding in DX3 support was relatively painless. I first looked at DJGPP’s FAQ and downloaded the example code. In the example code there was small helper functions to make unions and check the symbols. If they didn’t exist a printf was spit out to alert you about it. To resolve the issue you simply just add DXE_EXPORT to the other list of missing exports.
Compiling the game code was easy, again referring to the example I saw that basically they compiled it the same, but at link time you use DX3GEN and -U flag to ignore unresolved symbols.
The biggest head scratcher was the Sys_GetGameAPI failing to find GetGameAPI from the DX3. After some piddling around I noticed that it listed GetGameAPI as _GetGameAPI inside the DX3 itself. I added the underscore and it worked!
Other things that were relatively to easy to import was R1Q2’s HTTP downloading code. Compiling CURL was kind of tricky because of the linking order, but thankfully neozeed figured it out quickly.
All of Yamagi’s Quake 2 updated game DLLs were all diff’d by hand using BeyondCompare to make sure I didn’t clash using some newer functions that weren’t available in DJGPP. I also merged their Zaero code with their baseq2 code by comparing Zaeros code to the Quake 2 SDK, marking every thing that was changed. The result is a really stable Zaero game code. If you haven’t played Zaero check it out. I think it’s a lot better than Rogue, but Xatrix is probably my favourite (even over stock Q2).
Other cool things I’m glad to get into the code was the GameSpy Browser. It took me quite a bit of work to get it where it is, but it’s really nice to just be able to ping to a master server (a custom GameSpy emulator I wrote specifically for Q2DOS. Source is not finalized yet, but will be available soon for those curious), pick a server and go! All in DOS!
So here we are at the end of the journey. Or at least safe enough for a 1.0 release.
To recap, we have:
* SVGA (LFB modes only)
* SoundBlaster and Gravis UltraSound Family
* CD-ROM music
* OGG music
* Networking (You need a packet driver)
* Loading/unloading game DLLs in DX3 format.
* Intel HDA support -hda
* Mouse wheel support with -mwheel
I’m not talking about MingGW, Cygwin or anything else like that, but rather when support for Windows NT first appeared, it had to be compiled with Microsoft Visual C++ 1.0 of all things.
It was back in the 2.6 days of GCC, right before the stagnation that led to EGCS.
This version requires a GAS that has not yet been released. Until
it is, you can get a prebuilt binary version via anonymous ftp from
`cs.washington.edu:pub/gnat' or `cs.nyu.edu:pub/gnat'. You must
also use the Microsoft header files from the Windows NT 3.5 SDK.
Find these on the CDROM in the `/mstools/h' directory dated
9/4/94. You must use a fixed version of Microsoft linker made
especially for NT 3.5, which is also is available on the NT 3.5
SDK CDROM. If you do not have this linker, can you also use the
linker from Visual C/C++ 1.0 or 2.0.
Installing GNU CC for NT builds a wrapper linker, called `ld.exe',
which mimics the behaviour of Unix `ld' in the specification of
libraries (`-L' and `-l'). `ld.exe' looks for both Unix and
Microsoft named libraries. For example, if you specify `-lfoo',
`ld.exe' will look first for `libfoo.a' and then for `foo.lib'.
You may install GNU CC for Windows NT in one of two ways,
depending on whether or not you have a Unix-like shell and various
1. If you do not have a Unix-like shell and few Unix-like
utilities, you will use a DOS style batch script called
`configure.bat'. Invoke it as `configure winnt' from an
MSDOS console window or from the program manager dialog box.
`configure.bat' assumes you have already installed and have
in your path a Unix-like `sed' program which is used to
create a working `Makefile' from `Makefile.in'.
`Makefile' uses the Microsoft Nmake program maintenance
utility and the Visual C/C++ V8.00 compiler to build GNU CC.
You need only have the utilities `sed' and `touch' to use
this installation method, which only automatically builds the
compiler itself. You must then examine what `fixinc.winnt'
does, edit the header files by hand and build `libgcc.a'
2. The second type of installation assumes you are running a
Unix-like shell, have a complete suite of Unix-like utilities
in your path, and have a previous version of GNU CC already
installed, either through building it via the above
installation method or acquiring a pre-built binary. In this
case, use the `configure' script in the normal fashion.
Well that is quite the tall order! I can’t believe I somehow managed to build it back then, and out of curiosity I managed to build it again. And as you can see you need a ‘beta’ release of the GAS assembler, which is kind of impossible to find now, but it was part of the GNAT project, which used to distribute binary builds of the GCC core back in the day. Luckily I have a version stuffed away, although it’s from GCC 2.8.1, not as ancient as it would have when GCC 2.6 was a new thing. But it at lest assembles enough for my simple Hello World experiment.
To build GCC you need a working SED, which surprisingly CL 8.0 from the Win32s SDK, and it runs fine on Windows 7 x64 of all things. I had to mess with some of the files, and substitute the linker & headder files from Visual C++ 2.0 but much to my amazement not only can I build GCC along with libgcc.a, it also builds incredibly fast. On my machine I can compile GCC in about 5 seconds. I remember in 1995 building this on Windows 95 (I was crazy) and it taking HOURS and HOURS.
So one nice thing about these binaries is that you don’t need any external DLL’s Even the import section of a simple hello world exe is tiny: