DJGPP memory fouled

free: memory fouled

free: memory fouled

If you ever get this fun error while trying to exit or shell a program with DJGPP:

combinelo: memory fouled

free: memory fouled

You are mixing libraries built with a different version of the DJGPP runtime.  In my case, I built the allegro library with GCC 2.7.2.2 to use the older binutils but I’m cross compiling with GCC 5, so it’s using the newer runtime.

In my case I just needed to replace the contents of the lib directory with djcrx202.zip, and I was good to go.  I guess I could re-compile allegro, but that takes the better part of forever on DOSBox, and once was good enough.

[ANNOUNCE] DJGPP port of gcc-6.1.0

This is announcement of an update of DJGPP port of GCC-6.1.0

GCC used to stand for the GNU C Compiler, but since the
compiler supports several other languages aside from C,
it now stands for the GNU Compiler Collection.

See
https://gcc.gnu.org/ml/gcc/2016-04/msg00244.html
for original announcement of gcc-6.1.0 release


  • WARNING: This GCC port is for DJGPP v2.05 *
  • Build for DJGPP 2.03p2 is not and will not be available. *

Warning: DJGPP port of binutils-2.22 or newer is recommended.
Version 2.19 and 2.20 may work but are not tested
It is however recommended to use binutils-2.22
or newer

Use of DJGPP port of binutils-2.22 or newer is however required for

building gcc-6.1.0 for DJGPP.

Build for current stable version of DJGPP (djdev205) is
available
ftp://ftp.delorie.com/pub/djgpp/current/v2gnu/
and mirror sites (see http://www.delorie.com/djgpp/getting.html)

gcc610b.zip GNU GCC 6.1.0 for DJGPP V2
ftp://ftp.delorie.com/pub/djgpp/current/v2gnu/gcc610b.zip

gcc610d.zip Documentation for GNU C compiler
ftp://ftp.delorie.com/pub/djgpp/current/v2gnu/gcc610d.zip

gpp610b.zip GNU C++ Compiler 6.1.0 for DJGPP V2
ftp://ftp.delorie.com/pub/djgpp/current/v2gnu/gpp610b.zip

gfor610b.zip GNU Fortan 95 compiler 6.1.0 for DJGPP V2
ftp://ftp.delorie.com/pub/djgpp/current/v2gnu/gfor610b.zip

gcc610s.zip GNU GCC 6.1.0 sources for DJGPP
ftp://ftp.delorie.com/pub/djgpp/current/v2gnu/gcc610s.zip

objc610b.zip GNU Objective C and Objective C++ compiler and
runtime libraries v6.1.0
ftp://ftp.delorie.com/pub/djgpp/current/v2gnu/objc610b.zip

gfor610d.zip Documentation for GNU Fortran compiler
ftp://ftp.delorie.com/pub/djgpp/current/v2gnu/gfor610d.zip

ada610b.zip GNU Ada compiler
ftp://ftp.delorie.com/pub/djgpp/current/v2gnu/ada610b.zip

ada610d.zip Documentation for GNU Ada compiler
ftp://ftp.delorie.com/pub/djgpp/current/v2gnu/ada610d.zip

Binaries are built and tested mostly under Windows Vista Business (SP2)

Source RPMS needed for building Linux to DJGPP cross-compiler

Binary RPMs for both i686 and x86_64 are available. I built these binary RPMs
in CentOS 6.7 chroot under Fedora 23. Binaries are statically linked with GMP-6.1.0
MPFR-3.1.4 and MPC-1.0.3 to avoid unnecessary dependencies and increase
compatibility with other Linux distributions. For example they are expected
to work without problems in other reasonably recent Linux distributions
(like Fedora, RHEL-6 and newer, etc)

gcc610s2.zip is no more provided as patching GCC using DJGPP tools
has not been tested and even attempted by me for a long time.
DJGPP source file gcc610s.zip is a side product of building
gcc-6.1.0 Linux to DJGPP cross-compiler RPM packages. See source
RPM for patches applied to original FSF version of GCC-6.1.0.
You can find the same contents in the file

ftp://ftp.delorie.com/pub/djgpp/rpms/djcross-gcc-6.1.0/djcross-gcc-6.1.0.tar.bz2
Cross-compiler SRPM:

ftp://ftp.delorie.com/pub/djgpp/rpms/djcross-gcc-6.1.0/djcross-gcc-6.1.0-2ap.src.rpm

Cross-compiler binary RPMs (built under CentOS 5.11 i386, are expected to work on other recent enough RPM based Linux distributions, I myself have tried Fedora 19 x86_64):

GNU C compiler:
ftp://ftp.delori3.com/pub/djgpp/rpms/djcross-gcc-6.1.0/i686/djcross-gcc-6.1.0-2ap.i686.rpm

GNU C++ compiler:
ftp://ftp.delorie.com/pub/djgpp/rpms/djcross-gcc-6.1.0/i686/djcross-gcc-c++-6.1.0-2ap.i686.rpm

GNU Ada compiler:
ftp://ftp.delorie.com/pub/djgpp/rpms/djcross-gcc-6.1.0/i686/djcross-gcc-gnat-6.1.0-2ap.i686.rpm

GNU Fortran compiler:
ftp://ftp.delorie.com/pub/djgpp/rpms/djcross-gcc-6.1.0/i686/djcross-gcc-gfortran-6.1.0-2ap.i686.rpm

GNU Objective C and Objective C++ compilers:
ftp://ftp.delorie.com/pub/djgpp/rpms/djcross-gcc-6.1.0/i686/djcross-gcc-objc-6.1.0-2ap.i686.rpm

Tools for GCC 6.1.0 (currently only fixincl, most users do not need this):
ftp://ftp.delorie.com/pub/djgpp/rpms/djcross-gcc-6.1.0/i686/djcross-gcc-tools-6.1.0-2ap.i686.rpm

Info files of GCC-6.1.0 (a separate RPM file as these files are expected to
conflict with system compiler info files, but You do not need to install them…):
ftp://ftp.delorie.com/pub/djgpp/rpms/djcross-gcc-6.1.0/i686/djcross-gcc-info-6.1.0-2ap.i686.rpm

Substitute i686 with x86_64 For x86_64 binary RPMs in the URLs above.

You need also cross binutils (choose required binary RPM file or build from SRPM)
ftp://ftp.delorie.com/pub/djgpp/rpms/djcross-binutils-2.24-1ap.src.rpm
ftp://ftp.delorie.com/pub/djgpp/rpms/djcross-binutils-2.24-1ap.i686.rpm
ftp://ftp.delorie.com/pub/djgpp/rpms/djcross-binutils-2.24-1ap.x86_64.rpm

You need also DJGPP development libraries, include files and some tools (eg. stubify)
ftp://ftp.delorie.com/pub/djgpp/rpms/djcrx-2.05-5.i686.rpm
ftp://ftp.delorie.com/pub/djgpp/rpms/djcrx-2.05-5.x86_64.rpm
ftp://ftp.delorie.com/pub/djgpp/rpms/djcrx-2.05-5.src.rpm
Note that one can use
ftp://ftp.delorie.com/pub/djgpp/rpms/djcrx-bootstrap-2.05-1.src.rpm

for bootstrapping

See
http://gcc.gnu.org/gcc-6
for more information about GCC-6.1.0 and about changes in comparison
with earlier versions

Also see file gnu/gcc-6.10/readme.DJGPP (from gcc610b.zip and
gcc610s.zip) for more information about this port.

There is also my web page about DJGPP port of GCC

http://www.iki.fi/andris.pavenis/djgpp/gcc

I cannot promise however, that I’ll update it very often.
However new versions may appear there earlier (including ones not available
from ftp://ftp.delorie.com).

Andris Pavenis <andris DOT pavenis AT iki DOT fi>

System 16

A long long time ago, back when I got a Pentium 100 the wonderful world of emulation was really starting to be possible with such a high powered CPU.  First was the simple Game Boy emulators, then a Commodore 64 emulator, the incredible Amiga Emulator, the beginnings of SIMH (back when it was only a PDP-11 emulator), and then I found the SEGA emulator, System 16.

It was really cool being able to play 16bit arcade games on the desktop, although rather slowly.  From there everyone knows the rise of MAME.  But while looking around for a small 68000 C compiler, I came across the source code to an older version of System 16, 0.53 on archive.org.  Naturally it’s for MS-DOS, as was everything back in the day.  Also slightly interesting is the 68000 emulation, written by Bernd Schmitd of UAE fame.  So for the heck of it, I set about getting Thierry Lescot’s System 16 building again.  I’ve never used allegro before, so it was a bit of a fight to get a version of it to actually build.  It turns out that I should have been building version 2.11 with tools of that era (why on earth was I using GCC 4, and binutils 2.18?) and instead stick with GCC 2.7.2.2 and some much older binutils.  And in no time I had build the library, and it’s examples.  With that done, I was able to re-build System 16 with GCC 4.1.2 and get a binary!

Back in the day, I actually did have an Altered Beast arcade board.  Sadly it died in a move, someone near and dear just saw the PCB as “garbage” and tossed it.  Sigh, but I did have ROM dumps, as I did a refresh of it forever ago.  Anyways I still have the ROM files, so I guess that is nice.

Anyways I fired up the emulator and got what is known as the “jail bar” effect, which is from a bad ROM.

Corrupt tiles

Corrupt tiles

Notice the sprites

Notice the sprites

The System 16 splits it’s memory into a program space, a sprite memory bank, a tile memory bank, and RAM for stack and things like the palette.  As you can see the program is certainly running, and the sprites are good.  I did some poking around a bit later, and noticed that due to a logic bug, the texture ROMs are actually never loaded!

So a quick patch, and now we get Altered Beast up and running!

Altered Beast title screen

Altered Beast title screen

demo play

demo play

Well, now isn’t that great!

Not that I would imagine anyone would really care, I mean MAME is a thing, and even from the readme:

Altered Beast : No sound emulation

So it’s pretty quiet.  Additionally the source is pretty restrictive:

These sources can’t be used for commercial purpose, any new version of the
emulator done with these sources must specify my name somewhere on the screen
et docs and I must be informed about any new release of the emulator.

For anyone interested you can find the source & binaries out on sourceforge.

Porting Quake II to MS-DOS pt5 – 3DFX, GameSpy, Quake 2, and The Universe

The following is a guest post / wrap-up of the Q2DOS adventure by [HCI]Mara’akate.q2dos_3dfx_4
In the last update sezero and I([HCI]Mara’akate) tied up most loose ends with regards to Q2DOS.  Specifically: adding in DXE support for mods and cleaning up some code from the early efforts.  During this time, a forum user by the name of ggorts (strogg spelled backwards!) mentioned the possibility of using an old Mesa version with 3DFX support in DOS. I worked on separating the ref_soft from being statically linked into a DXE form and sezero cleaned up any potential problems there.

I mentioned the possibility of attempting the Mesa port to sezero and he thought it was probably a wasted effort and thought making a ref_glide depending only on glide3x.dxe would be a better way to go with less overhead.  I started some initial work on it but quickly abandoned this side-project as I have no real glide (or even OpenGL) knowledge and didn’t have enough time on my hands to play around with it.

Around this time, we also separated the GameSpy browser code into a separate DXE for potential legal issues.  The GameSpy code was publicly released, but never officially GPL’d.  Using this method, other port authors could link against a gamespy.dll to add in the browser capabilities that connect to my GameSpy master server emulator (see QDOS branch for source code to that particular project).

Ggorts also came up with some code for us to be able to finally use the banked modes and Mode-X 320×240.  Though 320×240 Mode-X seems to have some issues with certain emulator configurations, for the most part it works OK.  This also helped us to get some ASM rendering code in from Q1 and help clean up the original mess that was the SVGA driver; a lot of unused code from Q1 was removed and sezero found a clever way to send the video modes list between the game binary and renderer DXE.

In any event, one night I figured I’d take a stab at trying to get Mesa working in Q2DOS.  Checking out the Mesa3d FTP and researching the various changelogs it appears as if Mesa 5 series was the last true effort with Mesa 6.4.x series being the last maintained version with 3DFX specific code.  I got everything to compile but ran into hard-lock issues no matter what I attempted.  During this time, ggorts found out some various small, but now obvious issues. Including increasing the stack size to 1MB and he hard-coded the ref_gl to only work in 640×480.  It took a lot of pleading but eventually he released his source with a static compile for Voodoo 1 cards only as he was testing this on emulators like DOSBox with glide support and PCem dev branch.

I worked on cleaning up the source and he produced some glide3x libraries for me for Voodoo 2 and Voodoo 5 as these were the only cards I personally owned.  Imagine my surprise as I first loaded it up and it actually worked!  And it was smooth with no rendering issues!

q2dos_3dfx_3

At this point, sezero became involved and worked very hard to clean up the Mesa compile issues, including various scary warnings and helped to update us to the final glide3x commit pushed to the development branch and Mesa v6.4.3 which was an unreleased maintenance update for Mesa v6.4.2.

It was a long journey to get the code all working together just right, and a big thanks goes out to the early Mesa crew including Brian Paul, Daniel Borca, and “KoolSmoky” and the mysterious ggorts fellow who pushed hard for this feature.

To recap, Q2DOS from the last time we talked now has:

  • 3DFX Rendering with Mesa v6.4.3 for all Voodoo cards.
  • Separated renderer so it is no longer statically linked.
  • GameSpy is now a DXE.
  • WAV streaming, which is practically free as opposed to the OGG format.

q2dos_3dfx_1
q2dos_3dfx_8

We are about at the end of our Q2DOS journey.  A few odds and ends with Mesa and Voodoo 5 SLI issues remain (though nothing too show stopping) and there’s a small wishlist of some unnecessary features but it’s come a long way from the initial null driver effort!

q2dos_3dfx_2*Neozeed

I have to say it is simply incredible to see how Q2DOS went from a very primitive ‘wow it works’ port to a full featured port.  Simply amazing!

For those who missed the adventure it starts in Part 1, continued in Part 2, Part 3 and Part 4.

Porting Quake II to MS-DOS pt4

Bringing it all home for release day.

Bringing it all home for release day.

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:

* VGA
* SVGA (LFB modes only)
* Mouse
* Keyboard
* 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

And I should add, that it works GREAT on my MSI Z87 motherboard.

You can download Quake II for MS-DOS on bitbucket.  And as always the source is available here.

Don’t forget you can always make bootable USB stick with DOS, or CD-ROMs.

Continued in Part 5!

Porting Quake II to MS-DOS pt3

Well it mostly works now.  But did we ever have the biggest fun with the sound and SVGA.

So [HCI]Mara’akate integrated all the Q1 sound code, got it to compile, but nothing not a peep from the sound card.  While I was busy trashing the video code, he spent way too much time on the audio, and then for the heck of it I thought I’d look at the code, although I’m really stabbing in the dark when it comes to audio.  Imagine my surprise when I compiled the code, and ran it and got the sound blasting at full volume!  It turns out that I had my audio set to ‘high quality’ in the client, while he had his set to ‘low quality’.  What it does is govern the frequency between 11Khz and 22Khz.  And if you get this wrong you get *NO* audio. OOPS.  At least it was one of those feeling vindicated moments that his efforts for sound really did work.

Now with audio, it was my time to hurry up and get the video going.  I had basic VGA working so I figured I didn’t want to spend a lot of time on this, so I was going to go with the VESA 2.0 linear frame buffer.  Well this once more again proved to be a bit more involved as the only way I really have to test is emulation via DOSBox and Qemu.  And naturally both of them worked fine, but when [HCI]Mara’akate ran it on his real DOS Box (with GUS of course) it crashed wonderfully.

Now I had taken the VESA init code from Quake 1 to build a table of what 8bit modes are supported, and used the VESA code to switch, along with drawing to the buffer with a simple memcpy.  And we got nothing but crashes.

After looking more around, I found that you had to add 0x4000 to the VESA mode you want if you wanted to access it’s LFB.  Did that work? No still crashed.

Later in the adventure we noticed to get proper access you had enable ‘near pointer acess’ with a call to :

__djgpp_nearptr_enable();

So naturally I would disable it when I’m done, making the call look like this:

__djgpp_nearptr_enable();
memcpy(vid_resolutions[whatmodearewe].address+__djgpp_conventional_base,vid.buffer,(vid.height*vid.width));
__djgpp_nearptr_disable();

Right?

WRONG. Oh so WRONG.  Well OK technically it did work, but if sound is enabled (and why wouldn’t it be?) it would immediately crash with an error in the DMA code.  We ended up wasting over a day trying to figure this one out until I just said screw it, let’s never dsiable the nearpointer, leave it unprotected.  Naturally that actually worked.  The hint is in map_in_conventional_memory, where __djgpp_nearptr_enable(); is called, but of course there is no calls to __djgpp_nearptr_disable();  I’ve thought about going back through the source to ‘clean’ it up to make it lock and unlock memory as needed, but this is 2015 not 1997 so good enough is well, good enough.

So now with VESA and Sound, I thought this would be a great time to tackle the dynamic loading of gamex86.  We will have to re-compile whatever gamex86 DLLs are out there as of course DOS is DOS.  The HX DOS guy Japheth seems to have died, as his site and all the info on that extender seems to have mostly vanished.  I have an old copy, but I never could make it call DOS stuff if you had WIN32 stuff going on.  And if he’s really dead it’s too late to ask him.

Ages ago I remembered this DLL support for DJGPP called DLM, so I thought I’d give that a try.  I was able to take our ‘null’ version of Quake II, and get it to where it can load and unload the gamex86.dlm at will.  So I figured this was going to be an easy win, right?

Wrong again.  Once I started to put in the MS-DOS specific code I got this fun crash:

DLM -> Exiting due to signal SIGSEGV at
0x0014f59d SYM: _dos_lockmem+0x9 DLM: q2.exe [0xf5000]
possibly because of undefined reference to symbol ‘___djgpp_base_address’

DLM call frame traceback :
0x0014dcaf SYM: _Sys_PageInProgram+0x37 DLM: q2.exe [0xf5000]
0x0014e1c4 SYM: _main+0x18 DLM: q2.exe [0xf5000]
0x0000774e
0x00008b6e

So apparently it doesn’t export (or import) djgpp stuff like the base address calculations so we can’t do direct memory access, which means no video and no sound.  Ouch.  I’ll have to hit the lists to see about support.  I don’t like the DXE’s because they cannot be unloaded, so that isn’t much good.  And of course things like the JVM inside of gamex86.dll is right out as JAVA inside of MS-DOS? in 64MB of RAM? Dream on.

So for now, the gamex86.dll is statically linked into the executable.  You are restricted to vanilla gameplay for now.

As an added bonus, I used Rufus 2.2, to setup a bootable MS-DOS USB stick, slapped everything onto there, and booted up on my Xeon, and it works!

Quake II running on MS-DOS

Quake II running on MS-DOS

Now as a super bonus,  [HCI]Mara’akate went above and beyond by adding in a bunch of fixes, and updates from 3.24 and varous stuff from Knightmare.  And then the best part is integrating libogg, so it can now play the ogg sound track!  Really, just place the ogg files in the baseq2\music directory and away you go!

For those who care the bitbucket of the project is here, and binaries are here.

**UPDATE**

For anyone who is interested, I’ve updated the binaries, to include the latest version with built in quakespy technology!  Run an /slist2 and get a list of servers!

/slist2 in action!

/slist2 in action!

For the more adventurous trying to build from source, we are using GCC 2.95.3 and DJGPP 2.04.  All of the sub libraries that you need to build are already pre-compiled in source drop.

At this point the ‘alpha 2’ version contains:

  • VGA
  • SVGA
  • Mouse
  • Keyboard
  • SoundBlaster and Gravis UltraSound Family
  • CD-ROM music
  • OGG music
  • Networking (You need a packet driver)

Installing the packet driver will require a driver from the crynwr project.  You can find a description of some of the drivers here.  Sadly for new cards I think we are left in the dark.

I’ve also compiled a ‘server’ for Linux based on the code, and put it online @ 87.117.247.11:27910

Continued in pt4, and part 5.

Porting Quake II to MS-DOS pt2

Continuing in this series on porting Quake II to MS-DOS, we get to touch some of the fun stuff.  The first big ‘fun’ thing is networking.

Now in my prior work with the MS-DOS version of Quake, I had used the WATTCP library to bring networking to the otherwise Windows/UNIX specific fun of network deathmatch back to MS-DOS.  Quake by default had support for the Beame & Whiteside’s TCP/IP stack which for all intents and purposes has vanished from the face of the Earth (does anyone have a copy?!).  So at the time, I thought it’d be cool to try to interface WATTCP with Quake, and it worked on the first attempt as WATTCP is a very competent TCP/IP stack.

So I took the Linux networking file net_udp, and compiled it, and I got an executable!

When it comes to testing WATTCP though, I prefer to use Qemu instead of DOSBox as it can not only emulate various network cards to which I can find packet drivers (yes even the evil PCI NE2000!) but it has a built in SLiRP network stack that let’s me NAT on my desktop without any crazy network configs.

And for the sake of testing, I setup a ‘null’ text mode server, figured out some flags, and I was able to connect!

Quake II for MS-DOS running on Qemu connected to a dedicated OS X server.

Quake II for MS-DOS running on Qemu connected to a dedicated OS X server.

Very exciting stuff indeed!

Now for some interesting stuff.  First I noticed that MS-DOS 5.00 with himem.sys is almost unplayable because it is so slow.  MS-DOS 4.01 without himem.sys is actually faster.  No, I’m not kidding.

Next is that some levels LOVE to gobble up RAM.  Maps like city1 will need at least 192MB of ram.  I haven’t even tried playing with the virtual memory of DJGPP, and I really don’t want to.  And let’s face if, if you even try to load Quake II on a MS-DOS machine, it better be a ‘big’ one.  This means you should be using the ‘dos’ from Windows 98, or perhaps FreeDOS, although I haven’t tested that at all.

So far from our limited testing the networking seems to be pretty good.   And at least that is one function we didn’t have to really pour a lot of effort into.  Although the payoff of being able to connect to servers on the LAN and even the internet is a good thing.

Continued in pt3, pt4, and part 5.

Porting Quake II to MS-DOS pt1

(In this series, I’m going to go over the process of porting Quake II to MS-DOS.  Now of course the question will pop up why? And the answer is simple enough, after [HCI]Mara’akate added in gamespy support, something was noticeably off, and that is fewer and fewer people are playing Quake 1 these days.  So what to do?

Well apparently Quake II has an active following, so it’s time to move our creeky but favorite OS, MS-DOS into the Quake II Arena!

So the first thing to do is to grab a copy of the GPL source to Quake 2, along with a copy of the game, and get started on making a ‘null’ version of the game.  Null versions of the game have no graphical output, no sound, and ‘function’ at a very basic level.  It’s something to strive for as a first base in hitting that home run of a functional port.  Thankfully iD wrote really portable and modular software.  Unfortunately they tended to let their ports drift as they were writing the engine so the null code doesn’t actually work out of the box.  And the project makfiles leave a little to be desired for me, as they have a bunch of i386/Dec Alpha magic which doesn’t leave much in the room for weird ports like MS-DOS.

Now I should mention that before I’d gotten started the first thing I decided that like QuakeWorld for MS-DOS (and OS/2) I would use GCC as it is a known working compiler out of the box.  If you can, don’t fight so many battles of unknowns at once.  Another thing is that I am going to cross compile from OS X and test with DOSBox.  Of course you may want to use something else, and I know my tastes drift, but for now this is what I’m using. I’m using my old OSX to DJGPP cross compiler with GCC 2.95.3, which serves me well.

So the first thing was to compile and run the null version with native tools on OS X.  After a bit of struggle I got here:

$ ./q2
Added packfile ./baseq2/pak0.pak (3307 files)
Added packfile ./baseq2/pak1.pak (279 files)
Added packfile ./baseq2/pak2.pak (2 files)
Console initialized.
Sys_Error: ref_soft::R_BeginFrame() – catastrophic mode change failure

Well that’s great, how to figure this one out?

One thing I did to make it easier to work with the flow of Quake is to make the Sys_Error procedure contain a divide by zero.  Now why would I purposely put a divide by zero in the code?  Simple it lets me back trace the code when Quake catches it’s own faults so I can see what went wrong where, vs what would look like a clean exit.  From my example:

(lldb) bt
* thread #1: tid = 0xf14f9, 0x000c0853 q2`Sys_Error(error=0x000c17d4) + 98 at sys_null.c:28, queue = ‘com.apple.main-thread’, stop reason = EXC_ARITHMETIC (code=EXC_I386_DIV, subcode=0x0)
* frame #0: 0x000c0853 q2`Sys_Error(error=0x000c17d4) + 98 at sys_null.c:28
frame #1: 0x0003a0cb q2`Com_Error(code=0, fmt=0x000c17d4) + 368 at common.c:215
frame #2: 0x000c0523 q2`VID_Error(err_level=0, fmt=0x000cc8a8) + 81 at vid_null.c:45
frame #3: 0x000a6d38 q2`R_BeginFrame(camera_separation=0) + 592 at r_main.c:1145
frame #4: 0x000a4cfc q2`R_Init(hInstance=0x00000000, wndProc=0x00000000) + 276 at r_main.c:333
frame #5: 0x000c0740 q2`VID_Init + 362 at vid_null.c:122
frame #6: 0x00007900 q2`CL_Init + 55 at cl_main.c:1795
frame #7: 0x0003c2cb q2`Qcommon_Init(argc=1, argv=0xbffffc40) + 754 at common.c:1469
frame #8: 0x000c09ac q2`main(argc=1, argv=0xbffffc40) + 24 at sys_null.c:128
frame #9: 0x000019ad q2`_start + 212
frame #10: 0x000018d8 q2`start + 40
(lldb)

Now I know that R_BeginFrame was where the error was occurring, and looking at the code:

if ( ( err = SWimp_SetMode( &vid.width, &vid.height, sw_mode->value, vid_fullscreen->value ) ) == rserr_ok )
{

else
{
ri.Sys_Error( ERR_FATAL, “ref_soft::R_BeginFrame() – catastrophic mode change failure\n” );
}

We can see that the vid.width/vid.height aren’t being setup correctly.  Turns out there was a bunch more work to be done setting up vid_null!

 

After looking closer at the files, I notice as I’m stitching them together is that Quake II relies on DLL’s as part of it’s base functionality.  I drifted out of Quake after Quake 1, so I never played II before.  So I didn’t know this.  Obviously DJGPP doesn’t support DLL’s that can be loaded and un-loaded at will (Yes I know about DXE’s, but as the FAQ states, they cannot be un-loaded.  And I’m not going to fight DJGPP’s LIBC).  So looking further in the source, I saw these fun defines:

-DREF_HARD_LINKED -DGAME_HARD_LINKED

So at one point there was support for ‘hard linking’ in the ‘REF’ video driver, and the ‘game’ logic driver.  But it did kind of drift out of the code.  But looking at the Win32 version I could see that putting this functionality back in should be easy.  And to be honest if I learned any lesson from this, is that I should have been pulling the Win32 version apart by injecting null into it until it ran as a null platform, then use that as the basis.  Lesson learned.  Always start with a known good!  Quake II was built with Visual C++ 6, but I only have Visual C++ 4.2 installed on Crossover.  Yes I know again this is me being difficult.  But it didn’t take much time to get a simple project that has two DLL’s and a Win32 exe running.  Then I took on the ‘ref’ video driver and got that linking inside of the main EXE.  Now with one DLL ‘eliminated’ it was time to work on the game dll.

The game DLL posed the biggest challenge because it passes a reference to internal functions to it, and exports various functions back to the game engine.  So I ended up altering the engine to not call the game import/export directly but setting it up myself.  The hardest thing was that I couldn’t pull in the game header file, but rather I had to copy the prototypes myself.  Another interesting thing with the way Quake II works is that the game dll has to be able to be unloaded and loaded at will.  It wasn’t hard to simulate this, but I wasn’t expecting it.  Again this is probably because I never really played Quake II.

Now that I had Quake II building without DLL’s I could then take the next step of removing all the IO and re-replacing it with the null code, and now I had something that looked like it was doing something.

Added packfile ./baseq2/pak0.pak (3307 files)
Added packfile ./baseq2/pak1.pak (279 files)
Added packfile ./baseq2/pak2.pak (2 files)
execing default.cfg
execing config.cfg
NULLsock Initialized
Console initialized.
768k surface cache
ref_soft version: SOFT 0.01
——- sound initialization ——-
Sys_FindFirst [./baseq2/autoexec.cfg]: UNIMPLEMENTED!
==== InitGame ====
——- Server Initialization ——-
0 entities inhibited
0 teams with 0 entities
————————————-
====== Quake2 Initialized ======
loopback: client_connect
==== ShutdownGame ====
Sys_Error: Draw_Pic: bad coordinates

This turns out because I didn’t allocate the screen properly.  Looking at the code:

if ((x < 0) || (x + w > vid.width) ||
(y + h > vid.height))
{
ri.Sys_Error (ERR_FATAL,”Draw_Pic: bad coordinates”);
}

We can see it pretty plainly.

Now since we were going somewhere I started to write some MS-DOS code, and switch out of the null set of mind!

First a simple VGA mode 13 setup which gives us 320×200 resolution with 256 available colours.  And for good measure I did a simple VGA palette setup that I knew worked from a prior program.  Next we just blit our buffer onto the screen, and we get this:

Quake II on MS-DOS first screen

Quake II on MS-DOS first screen

Which is exciting and disappointing at the same time.  I then took the palette code from DOS Quake, and got something just as ugly.  I tried the code from OS/2. Same thing.  I tried all kinds of things and was going nowhere.

At this point Mara’akate added in the Linux clock code, and now we had this!

Quake II with a bad palette

Quake II with a bad palette

It wasn’t until much more digging around I saw some 320×240 screen setups that I realized there was something wrong there, and then I saw this gem in the linux port’s code:

/*
** SWimp_SetPalette
**
** System specific palette setting routine. A NULL palette means
** to use the existing palette. The palette is expected to be in
** a padded 4-byte xRGB format.
*/

In traditional VGA palette setups it’s 768 bytes that needs to be read/and pushed to the card.  I even checked Quake 1 is 768 bytes, but now in Quake II, it’s 1024 bytes!  OOPS!  Sometimes (ok a lot of times) you really need to check other ports or a ‘known good’ to see how they did things.

Quake II running on MS-DOS!

Quake II running on MS-DOS!

Pretty awesome!

So where to go from here? Obviously things like better keyboard input, the mouse, sound and networking need to be done.

Continued in pt2, pt3, pt4, and part5.

Announcing DJGPP 2.05 Beta 1

Yes, you read that right, not only is DJGPP still alive, but after the much stalled 2.04 beta cycle that has been going on for more than a decade, they have decided to push forward with 2.05 to get a release out there!

 

This is announcement of DJGPP 2.05 beta 1

It has numerous changes since previous DJGPP 2.04 beta 1 release in 2003.
(http://www.delorie.com/djgpp/mail-archives/browse.cgi?p=djgpp-announce/2003/12/06/22:18:05)
Unfortunately DJGPP v2.04 was never released and old beta version slowly
became almost unusable together with other newer DJGPP packages.

More information about changes in DJGPP 2.05 beta 1 is available at

http://www.delorie.com/djgpp/doc/kb/

both in sections about changes in 2.04 and 2.05. The same information is also
available in file info/kb.inf in djdev205.zip

It needs a lot of testing. Please test it if you have time and/or are
interested in any of the above features. Any level of testing would be
appreciated.

The beta is not available via the Zip Picker interface. You can download it
from here:

ftp://ftp.delorie.com/pub/djgpp/beta/v2

Additionally RPM packages (source and binary packages for i686 and x86_64) are
available from

ftp://ftp.delorie.com/pub/djgpp/rpms

Please see the README file for instructions on how to install the beta:

ftp://ftp.delorie.com/pub/djgpp/beta/v2/readme.1st

You can also download DJGPP 2.05 beta 1 packages from DJGPP mirror sites:

http://www.delorie.com/djgpp/getting.html

Thanks for all who have contributed to development of DJGPP

Andris Pavenis

I haven’t used it yet, but I see the following files in the beta directory:

djdev205 DJGPP V2 Development Kit and Runtime
djlsr205 DJGPP V2 Base Library Sources
djtst205 DJGPP V2 Test Programs (for testing the C library)
djcrx205 DJGPP V2 Cross-to-DOS Compiler Support Files (from djlsr/djdev)
djtzn205 DJGPP V2 Timezone Files
djtzs205 DJGPP V2 Timezone Sources

also floating around in the beta directory is GCC 5.1.0!

No doubt it’ll be a good excuse to rebuild and update some Quake related things to see how we fare in 21 century MS-DOS!