Click here if you are stuck in someone else's frames.
Selecting Video Mode 19 or 13h

The VGA card is a programmable video card, this means that we can send a series of commands through the I/O addresses of the video card to get it to display the video memory in whatever way we see fit (provided that it is capable).  However, directly programming the video card in this manner is a rather involved process, prone to mistakes.  Because of this, video cards are equipped with BIOS programs that enable us to put the display in any one of the standard video modes (CGA, EGA, VGA, etc.) via a standard programming interface (INT 16).  The following is all that is required to set the video card to any one of the standard modes:

     Load register AH with zero.  (mov ah, 0) This tells INT 16
     that we want to set the video mode.

     Load register AL with the video mode you want to switch to
     (in our case, it is 19).

     Call INT 16.

     That's it, in assembly, the instructions would be:

     mov ah, 0   ; Set video mode.
     mov al, 19  ; Use VGA (320x200x256) mode.
     int 16      ; Call interrupt to complete the process.

In assembly language programs, and almost any program that deals with interrupts, it is common to use hexadecimal numbers rather than decimal.  In this case, video mode 19 becomes 1316 in hexadecimal and interrupt number 16 becomes 1016 in hexadecimal.  Using hexadecimal notation, our previous program would be rewritten like so:

     mov ah, 0h  ; Set video mode.
     mov al, 13h ; Use VGA (320x200x256) mode.
     int 10h     ; Call interrupt to complete the process.

You can make the program even shorter by simply loading register AX with the video mode.  This is because AX is a combination of AH and AL.  Also, since all standard video modes have a number less than 256, loading AX with the video mode automatically loads AH with 0.

     mov ax, 13h ; Set video mode to VGA (320x200x256).
     int 10h     ; Call interrupt to complete the process.

All these assembly language examples for changing the video display mode is great.  But if you are not programming in assembly language (and most of us aren't), these examples are of little use to you.  Let's write an example using the C language.


Selecting video modes in C

Most C compilers now-a-days have built in assemblers that can compile assembly language programs inserted in your C programs.  Code written on these compilers can be written like this:

     void SetVideoMode(int mode)
     {
          asm {
               mov ax, mode  ;/* Set video mode to VGA (320x200x256) */
               int 0x10      ;/* Call interrupt to complete the task */
          }
     }

This works by passing the video mode you wish to display to the function which is then moved to register AX.  Of course, if your compiler does not support inline assembly there are other methods.  Using the DOS library of functions that are packaged in virtually all DOS based compilers, you can use the REGS union variable type with the function called int86.  An example of this would look like:

     void SetVideoMode(int mode)
     {
          union REGS regs;     /* Create register varables */

          regs.x.ax = mode;    /* Set video mode */

          /* Call interrupt to complete the task. */
          int86(0x10, &regs, &regs);
     }

This has a couple of advantages over the first example.  Since it isn't plain inline assembly, it will more than likely compile on a larger number of C compilers.  Also, during compile, the compiler can ensure that register values that need to be preserved, stay preserved.   When you call interrupts directly as our first example did, the compiler may not be able to anticipate what registers that the interrupt will modify.  If the interrupt modifies a register that the compiler was also using in your code somewhere else, it may result in subtle bugs that are impossible to find.

Another uncommon method that can be used involves a macro and register pseudovariables.  This will, of course, only work in compilers that support both of these techniques.

     void SetVideoMode(int mode)
     {
          _AX = mode;          /* Set video mode to VGA (320x200x256) */
          geninterrupt(0x10);  /* Call the interrupt to complete task */
     }

Compact code, yes.  This is just like the inline assembly language example shown above.  In fact, they work exactly the same.  This is because this function uses a register pseudovariable called _AX, which when compile directly references the AX register.  This means that this (and other register pseudovariables) are translated by the compiler into direct references to its corresponding register that it represents.  The second line is a macro that is replaced, upon compile, with an assembler call to the interrupt itself.  Because this function works just the same as the function above with the inline assembly, it is also succeptible to the same potential problems that could arise by the compiler not being able to predetermine which, if any, of the processor's register may be modified.

Recommendations

For size and speed, the first and the third examples of this functions are the best.  They are compact and fast, but not necessarily compatible with all compilers.  To ensure compatibility across compilers and to ensure a more stable operation after compile, the second example using the REGS union variable is often preferred.  It is also simpler to understand and doesn't require as much detailed knowledge of the computer as the others.  However, when writing video games, you must always learn as much as you can about the system you are programming on and optimize your code as much as possible for size and speed considerations.  Ultimately, I would still recommend the second function as the best choice.  The 'SetVideoMode' function is rarely called in most video games so it is not time critical (in fact, I could only think of two occasions that you would need to call it, to set the video mode to mode 19, and to return it to the text mode).  Also, since we know that this function is the most stable and compatible, we know that this function would provide a minimum of fuss.

Using these function in a program

Okay, before we move on let's make sure we have the basics down.

To switch to VGA mode 19, simply pass 19 to the 'SetVideoMode' function like so:

     SetVideoMode(19);   /* Use VGA 320x200x256 */

To switch back to the text (80x25) display mode, pass 3 to the 'SetVideoMode' function like so:

     SetVideoMode(3);   /* Use text mode */

Most people prefer to use defined constants, rather than numeric literals, when passing these values.  The ones I use come from André LaMothe's book "Teach Yourself Game Programming in 21 Days."

     #define TEXT_MODE 0x03
     #define VGA256    0x13

     SetVideoMode(VGA256);     /* VGA mode 19 */
     SetVideoMode(TEXT_MODE);  /* Text mode */

For QBasic / QuickBASIC programmers

Now some people in the QBasic and QuickBASIC land will be happy to know that the SCREEN statement supports VGA's mode 19.  The QBasic command to display this mode is simply:

     SCREEN 13

To return to text mode in QBasic, use this:

     SCREEN 0

No other commands or optimizations are necessary.

Previous Page | Main Page | Next page