Building MAME 0.1 for MS-DOS / DJGPP

So as promised, a while back I had built a GCC 2.7.2.3 / Binutils 2.8.1 cross compiler toolchain suitable for building old Allegro based programs, such as MAME.  Of course the #1 reason why I’d want such a thing is that being able to do native builds on modern machines means that things compile in seconds, rather than an hour + compiling inside of DOSBox.

Why not use a more up to date version of both GCC/Binutils?  Well the problem is that the pre EGCS tools ended up with macro and inline assembly directives that were dumped along the way so that later versions simply will not assemble any of the later video code in Allegro, and a lot of the C needs updating too.  And it was easier to just get the older tool chain working.

It took a bit of messing around building certain portions inside of each step of the tools, but after a while I had a satisfactory chain capable of building what I had needed.

So for our fun, we will need my cross DJGPP v2 tool chain for win32, MAME 0.1, Allegro 3.12 and Synthetic Audio Library (SEAL) Development Kit 1.0.7 .

Lib Allegro is already pre-built in my cross compiler tool chain, all that I needed to add was SEAL, with only one change, 1.0.7 is expecting an EGCS compiler, which this is not, so the -mpentium flag won’t work, however -m486 will work fine.

Otherwise, in MAME all I did was alter some include paths to pickup both Allegro and SEAL, and in no time I had an executable.  And the best part is checking via DOSBox, it runs, with sound!

MAME 0.1 on DOSBox PACMAN hiding

Thankfully MAME has been really good about preserving prior releases, along with their source tree, and it’s pretty cool to be able to rebuild this using the era correct vintage tools, and I can’t stress how much more tolerable it is to build on faster equipment.

33 thoughts on “Building MAME 0.1 for MS-DOS / DJGPP

  1. MAME 0.1 only supported five games, right? Of course, later versions got more games but ran much slower. I think they dropped DOS target circa version 0.100 (2005??), and nowadays MAME is modern C++ (AFAIK).

    If you want “-mpentium”, you need at least GCC 2.8.1. And EGCS wasn’t merged in until 2.95 (circa 1999).

    DOSBox is bad for compiling, but presumably even QEMU is faster (or obviously VBox). How long would it take under QEMU + FreeDOS? How long does it take now, cross-compiling from scratch?

    The “current” stable DJGPP for a long time (until 2015) was 2.03p2. (I’m not sure I’d personally even risk trying anything older unless forced.) The “p2” part was backporting Win2k-compatible patches from “beta”. So 2.95.3 built by 2.03p2 was circa Dec. 2001, hence new enough to finally run on XP’s NTVDM without problems. I know that’s not quite “cross-compiling”, but it’s close enough. I know you already know this, but that’s the way most compilation was done back then.

    (Although I’m still partial to building stuff in native DOS, but Intel will kill the BIOS by 2020, so time’s running out there. Use a RAM disk and software cache, install compiler to RAM disk also, then it’s fairly fast. But presumably you don’t want to shutdown + reboot everything, though bootable USB makes it fairly easy.)

    DOSEMU2 has had a revival in recent months, but that’s Linux only.

    • For me the biggest thing is that I’ve been using x64 / 64bit versions of Windows since the first public beta of XP/2003 for the AMD64 platform, and later to the now defunct Itanium. And what I wanted is a tool chain that’ll run on Win64 machines with some ability to run 32bit exectuables, and as you know this precludes NTVDM. While Qemu/VMWare/VBOX are options, I’ve always found DJGPP to be not only incredibly slow, but easily corruptible due to running on MS-DOS. There is no getting around it, modern OS’s are just so much faster as the IO model in NT may have seemed like a massive step backwards in 1988, but it’s working pretty well in the present.

      I know much of the compilation was done via native tools under mixed mode hypervisors, as I too ran them under OS/2, the later Windows 95/Windows NT, and what always amazed me was how Windows / OS/2 native versions of GCC ran much faster. And much like how I did the Linux/386BSD cross compiler stuff, instead of the more traditional setting up binutils/gcc for cross compilation what I’ve been doing (and probably should have gone into more detail) was to take a build of these tools that is native buildable, and then re-building that on Windows. So this is not the stock GCC –target=i486-pc-djgpp –host=i686-pc-mingw32 type thing, but localized source re-built using MinGW, which I’ve found has given me much better levels of compatibility, especially getting GCC 1.40 up and running and cross building early Linux kernels.

      I should imagine with the UEFI only machines, that it should be possible to port the seabios to use that backend and provide some kind of bridge, much like how EFI/UEFI Mac’s can run Windows… Wasn’t there a hacked up project to bring MS-DOS/Windows to the Intel macs before bootcamp?

    • > DOSEMU2 has had a revival in recent months, but that’s Linux only.

      But Microsoft provide Linux for Windows now! I don’t know how well DOSEMU2 would work on that, I have no idea of its limitations. It would be funny if the best way to run DOS applications on Windows 10 64-bit eventually becomes via Linux.

    • Not StarTrek, the first Intel Macs were OS X only, and there was a hack to make a boot loader that emulated enough of the BIOS to load up Windows. But then Apple released bootcamp so it basically was lost as a project, the XOM, Xp On Mac.

  2. “incredibly slow” … yes, newer versions of GCC are not speedy overall, even compared to older ones, but that’s always been true. But DJGPP is not horribly worse than others, generally speaking (minus obvious lacks like “make -j4”).

    “easily corruptible” … actually, DJGPP is quite robust, stable and reliable, easy to install. I think there’s still a lot good about it, even if only for DOS proper.

    Even ignoring native DOS + BIOS, NTVDM, or cross-compilers (have you tried Roboard’s?), you do really have to be aware of QEMU/KVM and VirtualBox and even DOSEMU2 nowadays. AMD64 kinda botched the lack of proper 16-bit support (“brain dead” like the 286), but VT-X eventually added it back. I know most people aren’t sympathetic, but it’s still legacy, which was once extremely popular, so it’s fairly ubiquitous.

    • why would I give up a protected mode OS for real mode + dos extender to do development? Targeting it is one thing, but actually trying to program in MS-DOS with what, Qbasic editor?

      And yes, it is great doing -j4 or j16 on larger systems. The dos target really is just historic at this point, or just a “yes it could have worked, but with the rise of DirectX everyone ran away”.

      A win32 native chain targeting DJGPP will always run faster and far more reliably than anything actually running on MS-DOS, be it in v86 mode, or as a guest under a hypervisor. MS-DOS just sucks at opening a lot of files, and it’s disk access is down right primative. smartdrv cannot hope to compete with the NT kernel.

      • Win32 runs better because MS didn’t bother fixing anything else. Most other subsystems were also abandoned. You were not expected to target anything else beyond native Win32. They weren’t really trying to be compatible with competitors. (I guess that changed later with things like WSL.)

        I’m not nagging you to forcibly use anything, much less something you consider “worse”. I’m just saying that NTVDM was once widely used for DJGPP, but the popularity of Win64 broke that (plus Vista 32-bit wasn’t great either). Lacking NTVDM, you really need VT-X. That’s probably the only good rationale for totally abandoning the native BIOS.

        And no, you don’t have to use QB’s editor (although few other editors are still actively supported either): GNU Emacs, VIM, VILE, SETEDIT, JED, TDE, FTE, etc.

        Is it really that strange to want to develop natively? Cross compilation is cool, but honestly, I’ll take whatever I can get. Seriously, DJGPP is not what I’d call slow (except under emulator without VT-X, now that is painful).

      • > And yes, it is great doing -j4 or j16 on larger systems.

        When these old projects have to build different things when building on DOS, I imagine nobody ever did -j builds for DOS before and the dependencies could be broken. I’m not sure that I want to be the first person to ever try these parallel builds, fixing makefile bugs is no fun 🙂

    • Roboard’s stuff is on cygwin (yuck) and uses newer stuff which won’t build Allegro, nor anything of that era so it’s really not any use to me.

      • No, it has MinGW standalone versions, I’ve briefly tested that locally.

        Whether newer GCC will or won’t build ancient (and abandoned) Allegro is nobody’s fault, just an accident.

        It doesn’t have to support literally everything, just enough to be useful.

    • Never heard of it. Apparently it’s a 1991 arcade game by Konami.

      According to the MAMEDEV wiki, 0.1 supported five games: Pac Man, Ms. Pac Man (bootleg), Crush Roller, Pengo, Lady Bug.

      MAME 0.1 was released on 5 February 1997. (21 years ago!)

  3. Hi there, I’m trying to compile some Allegro 4.2.2 games targeting MS-DOS, but I can’t find an easy way to do so on a modern computer. I hope you can help:

    On a real DOS computer, using the latest set of files from the DJGPP website works fine, with the caveat that to get Allegro to compile the -fgnu89-inline flag is necessary whenever gcc is used to compile .c due to changed semantics. (As you mentioned.)

    However, whenever I try to make Allegro using DJGPP in DOSBOX or Virtualbox (with MS-DOS 6.22 or FreeDOS 1.2) I always get Allegro-based .exes that give me a SIGSEGV immediately on starting (such as the DEMO.EXE that lives in \ALLEGRO\DEMO\ or, during ‘make all’, the DAT2S.EXE utility that live in \ALLEGRO\TOOLS\). I can show you the dump message, but it seems to explode at 0x00000000 before anything even starts.

    What I’d like to do is be able to use DJGPP (or something else if necessary) to compile Allegro 4.2.2 (itself, and projects using it) targeting DOS with a couple of Sound Blaster bugfixes that were released after 4.2.2 was no longer maintained. Do you know what might be the best way to do this, either natively on Windows or Linux or through VirtualBox somehow?

    Cheers
    -MC

    • So far, I’ve tried simply extracting your toolchain to a directory and all422s.zip to an .\allegro subdirectory, editing env.cmd to match my path, then from a Command Prompt window running the following:

      env.cmd
      cd allegro
      fix.bat djgpp
      make -f makefile all

      (Without the ‘all’ target, it complains the the DJGPP environment variable isn’t set, but it is, which is weird.)

      With the target set, I also have to sneak into the makefiles themselves and define MAKE to be ‘make -f makefile’ to match the behaviour of your make. From there, I get tons of errors about it not liking __extension__ and __inline__. I think perhaps your GCC is just a little too old for what I’m trying to do 😛 and I need to retry this whole process with GCC >= 4.

        • Thanks for the archives! I’ve gotten something going now with MinGW-DJGPPv205-gcc401 I think.

          These are the steps I’ve taken:
          * fix.bat djgpp
          * add i386-pc-msdosdjgpp\bin to the PATH in env.bat
          * add -I./../i386-pc-msdosdjgpp/include to the compilation lines in makefile.dj
          * in the step ‘make init-asmtests’, it seems to want to run ‘as’ and use lines like ‘echo #define ALLEGRO_MMX >> obj\djgpp\asmcapa.h’ to populate asmcapa.h with defines relating to processor caps. I think there’s a bit of an issue with the echo.exe in your archive expecting unix slashes rather then dos slashes, but I just performed whatever steps the makefile wanted manually until it stopped complaining. 🙂
          * the makefile produces obj\djgpp\asmdef.exe as part of the compilation process which it then runs to produce a defines file called asmdef.inc. Since this is compiled by djgpp, it’ll be 16-bit so I had to use dosbox to run this file to produce its output (which I thought was pretty cute 😛 )
          * to fix ‘src/i386/icpus.s:70: Error: operand type mismatch for `fnstsw”, change %eax to %ax

          And finally make all produces liballeg.a!

          However, when I compile allegro\setup\setup.c with the line ‘gcc -o setup.exe setup.c -lalleg’ and run the result in DOSBOX or VirtualBox, it crashes with the same SIGSEGV I’ve been getting when compiling with DJGPP within DOSBOX. Hmm 🙁

          • When I say ‘a bit of an issue with the echo.exe’ I don’t mean there’s a bug or mistake in your stuff I just mean that the Allegro build process is expecting only real regular DOS 🙂

            • Same result with the 346 archive.

              https://imgur.com/a/kukbMj3

              This is the same error I get compiling allegro in VirtualBox or DOSBOX (with the latest DJGPP or the djdev gcc and binutils from 2007), or with either of your Windows djgpp compilers. I’m starting to think that I’m missing something else…

              • remember most MS-DOS based emulation stuff isnt going to do SSE or MMX….

                type obj\djgpp\asmcapa.h
                #define ALLEGRO_GENERATED_BY_MAKEFILE_TST

                You want that to be pretty bare bones.

                Anyways in Makefile.tst you can make it use ‘unix’ mode for echo to work right

                # testing capabilities.
                UNIX_TOOLS = 1

                And when it comes to MMX:

                test-mmx:
                false
                # as --defsym ASMCAPA_MMX_TEST=1 -o $(PLATFORM_DIR_U)/asmcapa$(OBJ) src/misc/asmcapa.s

                likewise for SSE:
                test-sse:
                false
                # as --defsym ASMCAPA_SSE_TEST=1 -o $(PLATFORM_DIR_U)/asmcapa$(OBJ) src/misc/asmcapa.s

                I use the MS-DOS Player> to run the MS-DOS asmdef/dat2s parts. At it’s high end it’s basically restricted to 486 opcodes… so dont get fancy! 🙂

                makefile.dj: msdos tools/dat2s.exe -p setup -o obj/djgpp/setupdat.s setup/setup.dat
                makefile.dj: msdos obj/djgpp/asmdef.exe obj/djgpp/asmdef.inc

                the ‘demo’ crashes on the line:

                data = load_datafile(buf2);

                I found that just by moving an exit(0) around the code… Not sure what is up with that, but there u go.

                Anyways ex12bit, test program, playfli. So it’s not totally broken.

                • Aha! That’s amazing – will have to check this out asap. The demo is supposed to come with a pretty large datafile. It seems like all422s is the anomaly in that it has a weird stub instead of the full thing; I assumed that it would be built as part of the allegro library building process, but in all4310s and all423s there’s a 390k~ demo.dat that has the voice clips, graphics and intro fanfare etc. Try copying that into the same dir as your demo.exe.

                  (That’s actually how I got interested in this mess. When I tried Allegro on real DOS for the first time (I was around for the WinXP Allegro era mostly 🙂 ), I immediately hit upon the SB1.0 regression I recorded here https://twitter.com/SkullKidUK/status/1120242885960568832 and wanted to make myself a fixed Allegro that’d work on my real comp.)

                  I didn’t know that MMX was so late.

                  • Aha! This is great! I can compile and run both the DEMO and the SETUP just fine now, using Allegro 4.2.3 with those tips you gave. Thank you!

                    You can reproduce the Soundblaster bug yourself if you use SETUP in Dosbox and set the card to a SoundBlaster 1.0, Vol 200, Channels 8 and use Test. The default SB16 card in Dosbox autodetected by Allegro isn’t affected so most folks wouldn’t notice. I noticed this bug on my Yamaha Audician 32 Plus hardware first before I tried it in Dosbox, so I know it’s an Allegro fault. (Plus you can see the allegro.cc thread I linked to on twitter as well.)

                    If you want a really bad experience, use SETUP to select a SB 1.0 and then save the config. Then copy the allegro.cfg file the setup generates into the demo directory and run DEMO. The default Allegro behaviour is to read the allegro.cfg file in the working directory and use that to select the sound driver to use – this will let you play the demo shooter with the SB 1.0 driver, and it’s not very nice. 🙂

                  • It’s one of those things, that sometimes newer isn’t better. Just as compiling stuff to plain 80386 sometimes is better as the instruction set is probably emulated better when it comes to edge cases.

                    Great that you were able to get your build working for you!

                    • I think it was the generated asmcapa.h falsely indicating that MMX and SSE were supported that was causing all my frustrating SIGSEGVs all along. After editing that file like you suggest I can compile Allegro libraries and examples fine in VirtualBox now.

                      The TESTS\TEST.EXE Allegro program reports ‘686 (GeniuneIntel) / cpuid / FPU / cmov / SSE / SSE2 / SSE3 / MMX / MMX+’ in VirtualBox, and ‘486 (GeniuneIntel) / cpuid / FPU’ in Dosbox.

                      I don’t know how Dosbox would end up with MMX and SSE showing up in its asmcapa.h from that… it’s possible that Allegro’s make process is misdetecting it since nobody tested it on real DOS 🙂 (I’ve got allegro compiling under Dosbox again now since I want to see what the generated asmcapa.h looks like. It’ll take a while though.)

                      This doesn’t explain why VirtualBox’s exes crashed before. I haven’t told VirtualBox to hide any capabilities of my processor (if that’s possible) so it ought to have MMX and SSE available to the guest. Maybe Allegro uses those instructions in such a way that isn’t compatible with how csdpmi sets up the processor/memory state? I don’t know much about this and I’m totally guessing.

                      As part of ‘make all’ in VirtualBox, makedoc.exe is crashing when handling allegro._tx but I suspect that’s an out-of-memory error or something like that if the help file is big, and it’s not important.

                      I’ll leave it there for now. Thanks again for the help.

                    • It’s more so that the assembler supports them, not that it’s actually detected at runtime. It’s a horrible system in retrospect.

                      At the same time I’ve been using these toolchains to build Quake/QuakeWorld/Quake II for MS-DOS, and those I use native, and I’d want the higher level CPU support as I expected it running on a P4 or higher.

                      But great that it’s all done then!

          • There is some weird stuff with the way it constructs the mmx test I recall doing it manually… Although it would say I don’t have it as my binutils is too old (and I don’t care, under full emulation why bother with mmx?)

            Usually it crashes from stack and runtime mismatches.

            I’ll have to try it later on if I can.

  4. I also tracked down another issue I had that was causing the SIGSEGVs:

    Turns out that the Allegro 4.2.2 sources hosted by DJGPP at v2tk/allegro/all422s.zip have mangled .dat resource files for SETUP and DEMO. Which was really a spanner in the works considering I was trying to test the sound card selection options and use the allegro.cfg it generates with the demo game!

    If you download Allegro sources recommended by DJGPP’s Zip Picker and use ‘fix djgpp’ ‘make all’, it’ll stop when it gets to the dat2s stage of make (which converts the setup.dat containing the background and font graphics for the SETUP sound card selection program) into a .s const block of data for inclusion in the final setup.exe).

    The sources for Allegro 4.2.3 from allegro.cc work nicely and have the correct .dats. (Though they don’t have the sb.c patch for SoundBlaster 1.0 which I need to apply.)

    The SIGSEGV was (probably) due to a correctly compiled dat2s.exe not handling a malformed .dat gracefully. I initially thought it was a bug in the .dat code as any of the example programs that used a .dat resource file blew up, or some strange effect due to VirtualBox, but since the dat code was the same in .2+.3, I checked both source trees for weirdness and found that it was DJGPP’s version of all the included .dat files – they were all truncated and invalid (either accidentally or deliberately if the DJ maintainers didn’t want to distribute the resources due to size or licensing?)

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.