DOS coding

October 21, 2017 —

Last month I picked up a copy of Fabien Sanglard's Game Engine Black Book: Wolfenstein 3D. In fact, I was eagerly waiting for the day I could order a copy. When it arrived I was totally engrossed in it the whole way through. It's an amazing book, well written and well worth the read for anyone interested in those kinds of topics. Fabien really did a great job with it and I'm eagerly awaiting the next book in the series which will cover the DOOM engine.

It also got me thinking about some DOS code I had started to write a couple months prior and then set aside temporarily. I had begun writing a simple VGA Mode 13h library I had called "DGL" for "DOS Game Library" because naming is not a strong suit of mine. So, I'm going to pick it up again and hopefully continue writing about it here as I work on it and then soon after, some little game demos written with it also.

Of course, there's absolutely no good reason to re-invent the wheel from scratch like this. Libraries such as Allegro exist and any of the 3.x or 4.x versions for DOS would perfectly meet all my requirements and is probably far better implemented than anything I'd cook up myself. But that would be less fun.

Anyway, what I want out of this library is:

  • Support for VGA mode 13h (320x200x256)
  • Primitive drawing (pixels, lines, boxes, circles, polygons, etc)
  • Bitmap/Sprite drawing (aka. "bitblit"-ing)
  • Palette manipulation (loading, rotating, fading)
  • BMP, PCX, IFF image support (period-correct file formats)
  • Font rendering (using BIOS font format). Also add non-fixed width support?
  • Keyboard, Mouse, Joystick input device support
  • PC Speaker sound (maybe even rip off QBasic's PLAY command?)
  • Sound Blaster (and compatible) support (MIDI music, FM synth and digitized audio sound effects)
  • Math function suite (vectors, matrix, etc)

The only thing in this list that I think is (currently) outside my skillset (but totally possible to learn, of course) is the Sound Blaster stuff... simply because I've actually never written an audio engine of any sort, and certainly not ever written code directly for Sound Blaster hardware.

In fact, the only time I've added audio to game projects of mine was via DirectX. Not sure how DirectX is nowadays, but I remember at the time I was using Visual Basic 6 and the libraries for it had play/pause/stop functions for both sound effects and background music out of the box, so it was extremely simple to hook into the projects I worked on. Most game projects of mine tend to get dropped before I get to the point where I need to add audio, heh. And in more recent years, it was always my intent to use something like SDL_Mixer to take care of the lower-level details anyway, but I just never got around to it.

So, needless to say, when it comes to audio for this project I have a bit of fundamentals learning work to do.

Also on the topic of audio, I would like to look into adding support for Gravis Ultrasound cards. These cards are interesting as I think they were the first sound card for PCs to have full hardware audio mixing support. As I understand it, Sound Blasters lacked hardware mixing capability, so game engines would do this in software. But this will be a nice optional extra for later if I feel like it.

Originally, I had planned to use Borland C++ for this and do it all in real-mode DOS code. That probably sounds like totally unnecessary pain to anyone who understands the differences that brings along with it. I even went and bought a copy of Borland C++ 4.0 off eBay:

However, after fiddling around with it for a while I remembered how easy it was to crash your system with real-mode C code and how the debuggers of the time were helpful, but not that helpful in tracking down these types of bugs. This was less clear in my memory prior to this because during this time period I was primarily using QBasic which obviously shielded you from these types of bugs much more.

So instead, I plan to continue using a period-correct version of DJGPP (meaning, a version from the late 90's). Better debugger support for dealing with these types of crash bugs. Still possible to crash your system in weird and wonderful ways of course, but more support than Borland for catching these bugs. Plus having a 32-bit flat memory model is obviously very nice.

I plan to keep the code for this library on Github somewhere when there is something to show for it.