Monday, April 03, 2006

C++/DOS: Video Programming with Turbo C++

I decided to build off of the Assembly example demonstrated here to show the same basic program written in a higher-level language. This program will make the same sprawling palette, then fade it out to black. The program was written in Turbo C++ 1.01, which is available for free under Borlands Antique Software Museum.

//dos.h is used to for the interupt calling functions, registers structure,
//and for input/output functions
#include < dos.h >

int main()
     //Used to store the palette entries. This could have easily
     //been done as a 3 dimensional array, but I feel conceptually
     //it is easier to use 3 seperate arrays for red, blue, and green
     unsigned char red[256], blue[256], green[256];

     //A far pointer used to work directly with the VGA screen memory
     //unsigned char far *VGA = (unsigned char *)MK_FP(0xA000, 0); //alternate declaration
     unsigned char far *VGA = (unsigned char *) 0xA0000000L;

     //counters, make sure they are unsigned
     unsigned int x, y, z;

     //used to represent the CPU registers, provided by dos.h
     union REGS regs;

     //set the registers for Interupt 10h, function 0, mode 13h
     //and call the interrupt to set the video mode to 320x200 256 colors
     regs.h.ah = 0; = 0x13;
     int86(0x10, ®s, &regs);

     //load the sprawling palette onto the screen
     for (x = 0; x < 200; x++)
          for (y = 0; y < 320; y++)
               //since the palette is only 256 colors, loop back
               //to the first color after 320
               if (y < 256)
                    VGA[(x * 320) + y] = y;
                    VGA[(x * 320) + y] = y - 320;

     //Now load the palette into memory. This will allow
     //us to manipulate the palette in memory and load into
     //the palette rather than having to read, change, then write
     //from the video ports
     for (x = 0; x < 255; x++)
          //port 3c7 signals palette read from port 3c9
          outp(0x3c7, x);

          red[x] = inp(0x3c9);
          green[x] = inp(0x3c9);
          blue[x] = inp(0x3c9);

     //What this will do is fade red out first, then blue, then green
      //X controls which color is fading, y controls the intensity, and
      //z is controlling which palette entry we are changing
      for (x = 0; x < 3; x++)
           for (y = 0; y < 64; y++)
                for (z = 1; z < 255; z++)
                    //based on the color to fade, subtract that color
                    switch (x)
                         case 0:
                              if (red[z] > 0)
                         case 1:
                              if (green[z] > 0)
                         case 2:
                              if (blue[z] > 0)
                         } //end switch

                    //port 3c8 signals 3c9 to recieve a new palette
                    //entry for color z
                    outp(0x3c8, z);
                    outp(0x3c9, red[z]);
                    outp(0x3c9, green[z]);
                    outp(0x3c9, blue[z]);
               } //end for

     //switch screen mode back to 80x25 text
     regs.h.ah = 0; = 0x3;
     int86(0x10, ®s, &regs);

     return 0;

The program touches on a few interesting points. It demonstrates how to communicate with hardware ports using the old DOS architecture and Turbo C++. It also demonstrates how pointers can be used to directly access hardware memory points, such as the VGA memory. It also demonstrates how to call DOS and hardware interrupts in a higher-level language using the dos.h header file. Something like this could have been written in assembler, however it would have been very difficult. In my next article, I will show how C++ and inline assembly can be used to accomplish the same task.


Vivek said...

can i control the external fan or bulb by c/c++ prog..i.e on or off..
if yes then help me..

John Ward said...

Yes. Its pretty easy to do. With an old school DOS program like this, your basically just going to write out the parallel port to trigger a simple switch circuit that is either powered by a relay or a transistor. If its done with a transistor, the input from your parallel port is going into the base. Plenty of documentation on using a transistor as a switch out there.