So I quickly built it with my MinGW32-DJGPP using GCC 3.4.5. And this version needs the Allegro library as it has sound effects audio! Although building Allegro needed GCC 22.214.171.124 and Binutils 2.8.1. Using other versions just led to nothing but trouble. I ended up just installing DJGPP on DOSBox to build Allegro which took … a whlie to build. Although being able to cross compile dosdoom from Windows was far far far quicker.
So yeah, it runs. With sound. It’s great. Allegro integration isn’t anywhere as near complete at this point it’s just the sound files. I took a much later version of dosdoom’s MIDI code, which required the Allegro timer, which interfered with my older timer IRQ hook. Converting the whole thing to use the Allegro timer, and keyboard wasn’t too difficult, and that gives my DooM source fork a really full feeling when using DJGPP v2.
Although I’m having issues uploading from China at the moment.
Ok, so since I’ve been playing around with the Freedoom assets, I wanted to process all the assets and then make them into an iwad. And for the graphics this meant generating a simple color cube palette and then transforming all of the images to match that palette. And the results were, while recognizable as DooM, they are drab.
And yes, it’s gray, and drab. So UK. And there is another problem, many of the ‘graphics’ assets were a mix of PNG and GIF, and it turns out that in the GIF format you usually have a single color set as your transparent color, and it’ll get cut out automatically. In this case the transparent color is cyan. However there is some cyan still in the image!
So the best way I figured to ‘fix’ this was to do a straight conversion using Imagemagick. So I loaded up paintbrush of all things and noticed that for some reason the colors had bled on the gif’s I had from the Freedoom pack I’d downloaded. And that there were actually 3 cyan colors that needed to be purged. In this case in hex they are 0x00fefe, 0x00f2f2, 0x02f6f5, and the one that they should have been, 0x00ffffff
So I had to run convert like this against all the GIFs that I needed to fill in the graphics that I’m currently not processing in Python. Now the images actually look right, no surprise cyan, but my palette still sucks
Although the Freedoom team has told me that it’s far easier to just use the DooM palette as their assets use that palette and it’ll just work. But I’m too stupid for that. One great feature of Imagemagick is that you can hand it an image, and ask it to reduce it to any arbitrary number of colors, and it’ll do a great job of it. And while that is great for a single image, that doesn’t help me when I’m talking about thousands of images. Except Imagemagick also has another great ability which is to paste a new image to the right of an existing one. So with a little creative use of the make command I can then build a single giant image that contains all of the artwork. Isn’t that great?
Although great care and detail went into the original DooM palette selection we can throw all of that away, and let a program stitch everything together, and then have it analyze the entire mess, and come up with the ‘ultimate palette’ that works best with everything. Although one word of warning it takes well over an hour on an i7 to just stitch the images together (I should have setup a RAM disk) but it only took about 10 minutes for Imagemagick to process the blob image to come up with 255 colors that work best across the entire image set.
With the reduction done, the next thing to do is to create a ‘palette image’, which is one pixel for each color. This is the palette that we will use to ‘reduce’ all the images against. It’s more so to let Imagemagick do the hard work of selecting a palette.
And then the next step is to process this palette with dmutils dcolors. While it is primarily designed to use the LMB file format from Amiga fame, it wasn’t too hard to modify it to read a palette file directly, and let it add in the ‘red pain’ color shift, along with the green ‘bio hazard suit’ effect. The color map it generates is totally corrupt at the moment, so I’m using the old perl program to generate one based off of the palettes.
Indeed it is something so crazy that I really don’t want to even do it a second time to make sure my process was reproducible. However compared to before, I think the results speak for themselves:
So while it does take the better part of forever to go through all the images like this, it certainly gives zeeDoom a little more ‘building the world from scratch’ type feel.
So I missed all the updates over on doomworld about Freedoom, and deutex has been updated to support PNG files. Which certainly explains why all the assets were in PNG. I had thought they were still going the way of prBoom+ or some other ‘limit extending’ engine, but it turns out that they are wanting to target ‘vanilla’ LinuxDOOM derived engines.
So I tweeked my Makefiles where needed, and didn’t have enough Python to regenerate the text the way they do, so for now all the text assets are from a significantly older version. At any rate, here we go with the new assets:
Now what is great is that the Feeedoom folks have had the whole ‘apple pie’ stance to their project, with everything included. However they have drifted tools, build processes and other methodologies through the years. But thankfully the full archives are online, so I could go through and piece stuff together to my liking. Of course this all needs various tools, and oh boy does it ever need tools. You need:
a C pre-processor
A Unix’y build environment, I used the ancient MSYS
And probably many more I’m forgetting.
The first was to compile the levels. I used Ron Rossbach’s ancient IDBSP, a C port of iD’s command line Objective C level compiler. I did run into two slight issues, the first is that Ron’s tool expects their to be a line in the level’s dwd file telling us the name of the wad it’ll compile to, which of course is missing. The other is that I suck a makefiles, and just cheated forcing the tool to use a .wad extension on whatever .dwg it converts. And with that out of the way, I had the levels all built.
However that is where I found out the hard way that Freedoom doesn’t target something like my goal of being able to run this wad with the original DooM v1.1 release. The first problem is that Freedoom uses a different palette set, where it looks like it should be deeper? I’m not sure, but one thing was for sure everything looked like a rainbow sea of wrong and any vanilla or chocolate engines. And that is where I got a fun chance to play with ImageMagik. It really is quite powerful.
The first problem of course is the palette. Buried in the Python build scripts is a Perl fragment for generating a palette, and the all important playpal.lmp & colormap.lmp. I also got to spend a lot of time trying to extract that palette and do something useful with it to no avail. But googling led me to VGA_palette_with_black_borders.png, on Wikipedia of all things. So using this as a base I could convert, dither, and re-map the higher color Freedoom artwork into something that would play nice with Vanilla Doom. The downsite is that I didn’t try to find out exactly what assets a DooM version 1 wad needs, so I converted them all. On a good Xeon or i7 it takes about 10-20 minutes all the images. I can’t even think about how slow this would be using a 486, 68040 or MIPS.
Vanilla DooM v1.1 only plays audio at 11,000 Hz, 8bit deep. All the later ones needless to say use better sampling, and once more again Freedoom was at a higher level. I used sox to re-sample all the audio into the lower frequencies.
Later engines also are capable of directly playing MIDI files, and taking advantage of OPL3 chips, instead of v1.1’s OPL2 level. Thankfully Natt’s midi3mus is still online, and I was able to use this to convert Freedoom’s MIDI into the more restricted MUS format.
Inspired by Building and using a 29-year-old compiler on a modern system, i thought I too could get this ancient version of GCC working. At the time I never had bothered with the older version as I had always assumed that there were many fixes and adaptations to GCC for it to run on MS-DOS via GO32/DJGPP. However after doing this, its obvious that GO32/DJGPP was rather built around GCC’s stock output, which would sure make a lot more sense.
And it turns out that the target machine being an i386 Sequent running BSD is the best match, both in turns of underscores, and debugging format. At first I had tried the AT&T SYSV i386 target, however it couldn’t link anything from the standard libraries that DJGPP has as they all have a leading underscore. After starting to mess with internal macros to turn things on and off, and re-define how various portions of assembly are emittied, I found the Sequent target and went with that and everything was fine, and using the existing build infrastructure for GCC 1.39 I now could actually run hello world!
gcc_v1 -v -E hello.c -o hello.i
gcc version 1.39
cpp_v1 -v -undef -D__GNUC__ -DGNUDOS -Dunix -Di386 -D__unix__ -D__i386__ hello.c -o hello.i
GNU CPP version 1.39
gcc_v1 -v -S hello.i -o hello.s
gcc version 1.39
cc1_v1 hello.i -quiet -version -o hello.s
GNU C version 1.27 (80386, BSD syntax) compiled by GNU C version 5.1.0.
gcc_v1 -v -c hello.s -o hello.o
gcc version 1.39
as -o hello.o hello.s
gcc_v1 -v -o hello hello.o
gcc version 1.39
ld -o hello C:/dos/xdjgpp.v1/lib/crt0.o hello.o -lc
go32 version 1.12.maint3 Copyright (C) 1994 DJ Delorie
hello from DJGPP v1/GCC 1.39!
Wasn’t that great? Then going through my ‘test’ programs I went to try to build the infocom interpreter, and that is when things went off the rails.
funcs.o: Undefined symbol __udivsi3 referenced from text segment
options.o: Undefined symbol __divsi3 referenced from text segment
options.o: Undefined symbol __divsi3 referenced from text segment
print.o: Undefined symbol __divsi3 referenced from text segment
print.o: Undefined symbol __udivsi3 referenced from text segment
support.o: Undefined symbol __divsi3 referenced from text segment
gcc_v1: Program ld got fatal signal 1.
I’ve had some issues with GCC and these ‘built in’ functions before. This was an early major stumbling block back in the x68000 GCC days, where after a lot of searching I was able to find 68000 versions of various math routines that were in the native Hudson Soft assembler to link in. While GCC 1.x does have a libgnu/gnulib to include these functions it warns you over and over to not use GCC to build them, but rather the native CC. But the problem is that I don’t have a native CC.
But I managed to save myself after googling around by finding srt0.c from 386BSD. Namely these two:
I ended up having to removing a single underscore, but now I could link infocom, and even better it runs!
Wanting to try something far more exciting, I went ahead and tried to build DooM. However GCC 1.27 has an issue with m_fixed.c I fired up GDB to at least take a look, although I’m not sure where the fault lies.
This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information.
Breakpoint 1, 0x752c5ad5 in msvcrt!_exit () from C:\WINDOWS\System32\msvcrt.dll
#0 0x752c5ad5 in msvcrt!_exit () from C:\WINDOWS\System32\msvcrt.dll
#1 0x752bb379 in msvcrt!abort () from C:\WINDOWS\System32\msvcrt.dll
#2 0x0045805c in final (first=0xe066a0, file=0x75312688 <msvcrt!_iob+128>, write_symbols=NO_DEBUG, optimize=0)
#3 0x00403198 in rest_of_compilation (decl=0x722718) at toplev.c:1296
#4 0x0040fbce in finish_function () at c-decl.c:3272
#5 0x004040c0 in yyparse () at c-parse.y:224
#6 0x0040239d in compile_file (name=0xe00def "C:/dos/xdjgpp.v1/tmp/cca02992.cpp") at toplev.c:837
#7 0x00403a33 in main (argc=11, argv=0xe00f90, envp=0xe01598) at toplev.c:1556
With the code being:
if (! constrain_operands (insn_code_number))
So I assume some error with constrain_operands? Not that it makes it any better. However I know this one file compiles fine with 1.39, and since we are on the i386 another alternative is just to used the assembly version that was hiding in the readme..
And much to my amazement, it works! Keeping in mind that this is using an a.out tool chain, along with the last DPMI enabled GO32 extender.
Considering the compiler dates back from September 5th, 1988 it’s really great to see it running.
I’ll have to upload source (GCC 1.27/DooM) & binaries later. But I imagine it should also run on EMX/RSX for a Win32 version.
It has cut down the video rendering obviously, but still has some of the C enemy AI logic, it’s a bit more like Wolf in that there is no height in the cut down levels, but wow it’s still amazing to see. The sound effects were re-cut from the PC speaker stuff, and yes, even reduced versions of the MIDI music make the cut!
Naturally this won’t run on a stock 20, rather you need to get the maximum 37kb of RAM, and it requires a floppy disk drive.
It’s really cool to check out, and yes it runs on VICE.
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.