Click here if you are stuck in someone else's frames.

If this page looks like garbage then you need one of these browsers...

Microsoft Internet Explorer

Netscape Navigator

Please sign my programmer's page guestbook.

Please sign my guestbook

View my guestbook entries

The VGA Color Palette

We need to cover a few more things before we wrap up the basics of the VGA graphics system. One of them deals with the VGA color palette. As you already know, the VGA card is capable of displaying 256 on screen colors, however what you may not have known is that the VGA card is capable of displaying much more than that, but not at one time.

Screen 13H, the 320x200x256 screen mode, is capable of 262,144 colors with 256 of them assigned to each of the 256 colors that can be displayed at one time. When the VGA card is put into mode 13H all 256 of the palettes are assigned one of the 262,144 total colors. For instance, color palette 1 is assigned the color blue and palette 15, high intensity white. For instance, the function SetPixel(0, 0, 1); will set a blue pixel in the upper left corner of the display. We can reassign another color to any one of these 256 attributes, the main question is how?

To answer that, first we must understand how each of the 262,144 colors are represented to the VGA card. If you're familiar with the 3 primary colors of light and how they can be mixed to create any color, then you already understand most of what the VGA color palette does. Basically, we tell it the intensity of each of the three primary colors and assign it to one of the attributes. Each of the three primary colors (red, green, and blue) can assume 64 unique values numbered 0 to 63. Since there are three colors, we get a total of 64 * 64 * 64 = 262,144 unique colors. The higher the number, the greater the intensity of that primary color.


Putting the knowledge to use

In order to change one of the palettes to assign another color, we must communicate our intention to the VGA card itself. There is no area of memory where all 256 color palettes are stored so we must assign these color palettes through the VGA port addresses. The VGA card has four port addresses for dealing with accessing and changing the color registers. These four I/O ports are defined below...

  #define PALETTE_MASK  0x3C6
  #define PALETTE_READ  0x3C7
  #define PALETTE_WRITE 0x3C8
  #define PALETTE_DATA  0x3C9
    

When we want to access and change one of the color palette registers, we must first send 0xFF to the PALETTE_MASK port address. This allows us to access all of the color registers for reading or writing. After that we must send index of the actual palette register that we wish to access or change. Depending on whether or not we wish to read or write to this palette, we will send this value to either the PALETTE_READ or the PALETTE_WRITE port. Then we simply read or write to the the PALETTE_DATA port three times, once for each primary color value.

Please note that you must make three consectutive read or write's to the PALETTE_DATA port otherwise the VGA card may go into an unpredictable state.

With that in mind, let's write the code...

  #include <conio.h>
  #include <dos.h>

  /* VGA256.C
   *
   *   Palette read and writing...
   */

  /* VGA Palette access port addresses */
  #define PALETTE_MASK  0x3C6
  #define PALETTE_READ  0x3C7
  #define PALETTE_WRITE 0x3C8
  #define PALETTE_DATA  0x3C9

  /* Useful structure to store the 3 primary color values */
  struct RGB_Color {
      unsigned char red;
      unsigned char green;
      unsigned char blue;
  };


  /* Sets a palette to one of the 262,144 colors */
  void SetPaletteRegister(int index, struct RGB_Color *color)
  {
      /* Disable interrupts */
      /* Okay to remove this line or substitute */
      /* asm cli; */
      disable();

      outp(PALETTE_MASK, 0xFF);

      /* Send color palette register index to write to */
      outp(PALETTE_WRITE, index);

      /* Write the color palette entry */
      outp(PALETTE_DATA, color->red);
      outp(PALETTE_DATA, color->green);
      outp(PALETTE_DATA, color->blue);

      /* Enable interrupts */
      /* Okay to remove this line or substitute */
      /* asm sti; */
      enable();
  }

  /* Gets the palette register value */
  void GetPaletteRegister(int index, struct RGB_Color *color)
  {
      /* Disable interrupts */
      /* Okay to remove this line or substitute */
      /* asm cli; */
      disable();

      outp(PALETTE_MASK, 0xFF);

      /* Write color palette register index to read from */
      outp(PALETTE_READ, index);

      /* Read color palette entry */
      color->red   = inp(PALETTE_DATA);
      color->green = inp(PALETTE_DATA);
      color->blue  = inp(PALETTE_DATA);

      /* Enable interrupts */
      /* Okay to remove this line or substitute */
      /* asm sti; */
      enable();
  }

  int main(void)
  {
    struct RGB_Color c;

    /* The next 2 functions assume that you have
       already included them in your source code.
       They are not included here because
       we are interested in only the palette
       functions.  They must be included if you
       want to run this sample program.
    */
    SetVideoMode(VGA256);    /* Set mode 13H */
    Line(0, 0, 319, 199, 1); /* Draw a single line */

    /* Now let's run through the spectrum of colors */
    for(c.red=0; c.red<64; c.red++)
      for(c.blue=0; c.blue<64; c.blue++)
        for(c.green=0; c.green<64; c.green++) {
          SetPaletteRegister(1, &c);
          /* Press any key to quit */
          if (kbhit()) {
            getch();
            SetVideoMode(TEXT_MODE);
            return 0;
          }
        }

    SetVideoMode(TEXT_MODE);
    return 0;
  }
    

By manipulating the palette entries, a lot of decent effects can be acheived. Effects such as fading and palette scrolling to name a couple. Both of these effects will be discussed along, with a few others, later on.


Send your questions, comments, or ideas to: wilkeg@gamewood.net

This page hosted by GeoCities Get your own Free Home Page
 | Next Back