Game Programming in DOS using the C Language

Written by: Antonio Maiorano
April 8, 1999


Who is this tutorial for?

    This tutorial targets anyone who has C programming experience in DOS using either 16-bit compilers (i.e. Turbo C/C++), or 32-bit compilers (i.e. Watcom C/C++). I assume you know the syntax fairly well (or that you have a good reference book near you), and that you are somewhat familiar with pointers, since using pointers is an integral part of game programming. I also assume that you have NO experience programming in a graphics mode (as oppose to text mode).
 

What do you need?

    To learn the most from this tutorial, you should have the following:

- a computer
- a 16-bit or 32-bit C/C++ compiler (preferably 32-bit such as Watcom or DJGPP)
- some imagination!

    Personally, I use the Watcom 10.5 C/C++ compiler, which is a 32-bit DOS compiler.
 

What's the difference between a 16-bit and a 32-bit compiler?

    Without getting too technical, a 32-bit compiler allows you to access ALL the RAM (main memory) available in the computer. Since most computers today have at least 16 megabytes of RAM, that means you can allocate large buffers of memory without worrying about whether or not you'll run out of it. In a 16-bit compiler, on the other hand, you are limited to about 1 megabyte of RAM! This is fine for small programs (or for the games of old, which used extensive optimizations and often swapped data from hard disk to memory and back), but if you want to make really cool games, I suggest you get your hands on a 32-bit compiler.

    Another advantage of 32-bit compilers is that you no longer have to worry about near and far pointers, since all the RAM is immediately available (if you don't know what this means, don't worry, it's not important).

    If you don't want to pay for a 32-bit compiler such as Watcom, then I suggest you download DJGPP, which is a free 32-bit DOS compiler made available by delorie software.
 

Graphics Mode 13h

    Up to now, you're probably used to programming in a pure text mode environment, such as the one used by DOS. Perhaps by experimenting with certain libraries, you've managed to spice up the output by changing the background color, the font color, etc. However, if you want to make games, DOS text mode just won't cut it.

    To program games, you must first learn to work in a graphical environment. This is accomplished by writing a few lines of code that tells the VGA card that you want to change the graphics mode. As a beginner, the easiest graphics mode to program in is Mode 13h. The function we'll need to switch to this mode is written in assembly language. If you don't know any assembly, don't worry, it really doesn't matter. Just copy these lines, and use the function as you would any regular C function:
 

#define MODE13h    0x13
#define TEXTMODE  0x03

void SetVideoMode(int mode)
{
  extern void SetMode(int);
  #pragma aux SetMode ="int 10h"\
  parm [eax];
}

    To use the function, you would do the following:

void main(void)
{
  SetVideoMode(MODE13H); // Switch to mode 13h

  ... // Do your graphics stuff here

  SetVideoMode(TEXTMODE); // Switch back to DOS text mode
}

    Okay, so now we're in Mode 13h. But what does that mean? Specifically, Mode 13h is a graphics mode with resolution 320x200 and 256 colors.
 

Resolution

    The resolution of a screen is how many pixels (those little squares on your screen) are being displayed. In our case, using Mode 13h, we can display 320 pixels in width, by 200 pixels in height for a grand total of 320*200 = 64000 pixels.

    Our screen is like a 2-dimensional array with coordinates (0,0) in the upper left corner, and coordinates (319, 199) in the bottom right. This resembles the first quadrant of a cartesian plane, except that the y-axis is flipped. That means that as you move down the screen, the y value increases as is shown below:

(0,0) (1,0) (2,0) ... (318, 0) (319, 0)
(1,0) (2,0)
(2,0)
  ...
(199, 0)          ...              (319,199)


 

Colors

    Mode 13h is known as a palettized mode. This concept often confuses most beginners, so I will try to explain it in detail and will use analogies to make it clearer.

    As stated before, there are 256 colors available in this graphics mode. However, as you are probably aware, today VGA cards can display up to more than 4 billion colors! So at first it would seem as though the 256 colors available to you are probably a well-chosen fixed set of these 4 billion colors. However, this is not true.

    Instead of picturing 256 colors, picture 256 paint buckets. Each of these paint buckets are labelled from 0 to 255, and each one can hold a color. Specifically, a paint bucket can hold any one of the 4 billion colors available on the VGA card. As a programmer, you can place any color you want into the paint buckets by simply supplying the color's ID number. For now, though, you do not neet to worry about the changing the colors in the paint bukets since a default set of colors is available as soon as you switch to Mode 13h.

    The set of colors in your 256 paint buckets is called the palette. In the next section, you will learn how to use this palette in order to display graphics to the screen.
 

Displaying to the screen

    Finally, the good stuff! So far I have discussed many details of Mode 13h. In summary, we saw that Mode 13h provides the following:

- a resolution of 320 pixels in width by 200 pixels in height, (0,0) being the (x,y) coordinate of the upper-left corner of the screen, and (319, 199) the lower-right;

- a set of 256 colors known as the palette.

    I earlier stated that the screen is like a 2-dimensional array. Although we can visulaize it as such, this is not actually the case. What is displayed on the screen is actually stored in a memory buffer on the VGA card linearly (as a 1-dimensional array). Consequently, the data stored in this VGA buffer is repeatedly copied pixel by pixel to the screen. So if we could somehow find a way to manipulate this 1-dimensional buffer on the VGA card, then we would be able to display our graphics to the screen!

    The way this is accomplished is by first creating a pointer to this VGA buffer as follows:

32-bit compiler:

unsigned char *VGA = (unsigned char *)0xA0000; // Pointer to VGA

16-bit compiler:

unsigned char far *VGA = (unsigned char far *)0xA0000000L; // Pointer to VGA

    If this looks really strange, don't be alarmed. Let's analyze the 32-bit declaration: first we declare a pointer to an unsigned char called VGA. The first question that should come to your mind is "Why unsigned char?". The reason is that an unsigned char is an 8-bit memory location which can hold the values 0 to 255 (since 2^8 = 256). Those are precisely the same values that are used to label the 256 paint buckets in our palette! In other words, this VGA pointer will point to a location that holds the value of the color we wish to display. If this is not clear to you right now, don't worry, it should become clearer in the upcoming examples.

    The declaration of the VGA pointer is also initialized to point to 0xA0000. This is simply the address of the first location of the memory buffer on the VGA card. So now we have a pointer called VGA that points to the first location of the VGA card's memory buffer! How big is this memory buffer? Well, there are 320*200 = 64000 locations, each location being one byte (8 bits) large. So the buffer is 64 000 bytes large.

    Since the memory in this buffer is linear, we can picture it as a large unsigned character array with 64000 locations. The first 320 locations correspond to the first row of pixels on the screen; the following 320 locations correspond to the second row of pixels on the screen and so on. So using our VGA pointer, we can see that VGA[0] corresponds to the very first pixel in the top-left corner of the screen; VGA[319] is the very last pixel in the top-right corner of the screen; VGA[320] is the very first pixel on the left of the second row on the screen, and so on.
 

TO BE CONTINUED...