THE PALETTE & HOW IT WORKS

Colours, as seen by the human eye, are made up from different intensities of the three 'Primary' colours: Red, Green and Blue. These 3 colours are referred to as "components" of any visible colour you want to see. For instance, if you wanted to get a deep yellow colour you would use full Red intensity ('full intensity' being the highest amount of this colour you can get ... this amount varies depending on the display/video mode you use but it should always gives you the same colour) and full green intensity. The resulting combination is seen by the human eye as yellow.
In this system, black is represented by each component beign of zero intensity, and white is represented by having each component have full intensity.

Here's the numbers I used to represent the colours you (hopefully) saw in the above paragraph as highlighted words (in hexadecimal ... 'FF' is the highest value 00 is the lowest). The components are lined up in R:G:B order so the digits are reserved as RRGGBB

FF0000 + 00FF00 = FFFF00

When you are in a 256 colour graphics video mode (such as VGA's 320x200) it takes up only one byte to represent the colour of each pixel on the screen. One byte only has 8 bits in it and so you cannot directly store all three components of a colour (RGB) into one byte in a practical way. The solution is to use a palette ... it's called this because it works just like a painter's palette in the sense that you have a reserved space that contains samples of all the colours you want to be available to you while drawing to the screen.
When you set the value of a byte in VGA memory, that byte is not directly a colour value, but instead indexes one of the colours in the palette. Since there is one byte per pixel you can index 256 possible palette values (0 to 255). You can think of it like this, the VGA has space for 256 colour values and they are stored one after another in RGB format. Pretend for a moment that you are the VGA chip, and are scanning video memory. You would have an array of 256 colours, and each colour would have 3 components.

//Let's pretend to be the VGA ...
//We have an R, G, and B value for each colour ...
typedef struct {
  char red;
  char green;
  char blue;
} RGBColour;

//And we would have 256 of them ...
RGBColour VGAPalette[256];

//Don't forget the memory at 0xA000:0x0000 to read from
//(pretend that this array is somehow located at that address and
// we modify its contents when we draw to VGA memory;)
char VGAMemory[320*200];
Now, as the video data is sent to the actual monitor it must be converted to RGB. The VGA would read the value at each byte in video-memory and index the appropriate palette register. Here's some pseudo-code (not real) that shows how this might work if it were written as software ... but keep in mind that all this stuff I'm pretending to do is really etched into a VGA chip in a much more efficient manner (the entire process happens about 60 times a second) ...

//For every byte in VGA memory ...
for( byte=0; byte < 320*200; byte++) {

//Get the value at the current byte
   palIndex = VGAMemory[byte];

//Send the Red Green and Blue components in the palette value
//that that byte points to
   sendVideoPixelToMonitor( VGAPalette[palIndex].red,
                            VGAPalette[palIndex].green,
                            VGAPalette[palIndex].blue  );
}
That's the basic sense of how a bunch of one-byte values are converted into three-byte RGB values that the monitor can use to show you lots of colours. The main limitation of this technique is that you can never have more than 256 colours being displayed on the screen at any one time. This is due to the 8-bit wrap around (incrementing a byte containing 255 makes it wrap to 0).

The VGA palette always has default values in it after you set a 256 colour video mode. You can download ShowPal.exe (I use Norton AntiVirus 95 so it's clean) for a display of all the available colours in the default palette. They aren't layed out in a way which is practical for graphics so if you are making a program that depends on a good colour model (such as any program that requires shading from one colour to another) then you will need to Modify the Palette to your own list of RGB colours.

The VGA's 256 colour palette uses 6-bit components, not 8-bit. This means that when defining the intensities of the colours you want in your customized palette 63 is the most intense value you can have for R, G, or B because 26 is 64. The colour white would be represented by (int R:G:B format) the numbers 63:63:63 ...

This fact is noted again in "How to Modify the Palette".

Incase you're still not familiar with how colours are represented by RGB, here's a table of colours and what intensities of each component give you the colour.

RedGreenBlue = Colour
000 = black
323232 = grey
636363 = white
6300 = red
0630 = green
0063 = blue
63630 = yellow
06363 = cyan
63063 = magenta
32063 = purple
63320 = orange
04832 = turquoise

Hopefully, by now you've got a good idea of how colours are defined (incase you already didn't) and how palette indexes are turned into RGB colours.

Changing an individual pixel to be brighter/darker than it current is in a paletted mode is difficult to do without changing the RGB components of that colour's palette index, but if you did modify the index's value itself then that would cause all other pixels of that colour on the screen to change also (which you often don't want).

One way is to simply take a palette index value, compare its colour value to all other colours in the palette, and then find the closest match that is a little bit brigheter/darker.
This would work but it's extremely slow for doing real-time graphics such as texture-mapping etc.

How can we create a fast way to find the index of a brighter/darker version of any pixel on the screen? I think I know a good answer (but have yet to implement it). Define your program's normal palette, but then make two arrays of values with 256 elements in each. These arrays could be called lookup_Brighter[256] and lookup_Darker. You would initialize each member of the array so that if we indexed it with the current pixel value, the actual value in the array would be the new colour index we should use.
We could use this table-of-values successively to get increasing steps of brighness/darkness.

Someone recently told me that the Sony Playstation uses something like this in it's graphics engine, hmm....