C Graphics


Home

About the Author

General Programming

Pascal

Delphi

C&C++

Visual Basic

SQL

JAVA Script

Links

 

[ C Graphics ] C Math ] C Misc ] Common C&C++ Pitfalls ] Ponter Tutorial ]

  1. Mode 13h
  2. Setting the palette in mode 13h
  3. Mode 13h putpixel

Just a quick note. Most of the code in this graphics section only works with the DJGPP compiler. Maybe with a bit of modification you can get it to work in other compilers.
Any questions send mail to cplus@teentwo.8m.com


1. The video mode 13h, What is 13h?

Many computer games have used it such as DOOM and DOOM2, the original C&C the DOS version of C&C-RedAlert. It's also Quake's standard resolution, and QuakeII's non 3d excelerated standard resolution. So as you can see, it's a very widely used video mode... at least it WAS, until Microsoft came over and made direct-x, which by the way is about twice as slow as just programming the graphics support your self, it's just that you probably can't tell the difference because of how fast computers are now-a-days anyway.

One of the more interesting questions that comes up about 13h is "What is it?". There is a very simple answer to that question: 320x200x256. The only problem with that answer is the fact that not every body knows what it means.The answer to that question is not quite so simple to answer, although once known is so simple that you will never forget what it means.

The first number in the list, 320, tells us the horizontal resolution. Just incase you don't know what a horizontal resolution is, I'll tell you: it is the number of pixels per row on the screen.

The second number, 200, tells us the vertical resolution. The vertical resolution is the number of pixels per column on the screen.

The last number, 256, is the amount of possible colors to be displayed on the screen at once. it is commonly referred to as the "color palette".

So how do I change the video mode to 13h?
Well, this one is something that there is only one efficient way to do, so I'll just give you the code right here:
int init_vga_mode(void)
{

union REGS regs;
__djgpp_nearptr_enable();
vgamemory=(char *)(0xA0000 + __djgpp_conventional_base);
if((vgabuffer=(char *)malloc(320*200))==NULL)
{

return(1);

}
regs.h.ah=0x00; //Procedure 0x00: Set Video Mode
regs.h.al=0x13; //The mode to set (0x# = #h)
int86(0x10, regs, regs); //Call BIOS intr 0x10
return(0);

}
The code above will work with DJGPP if you include the following:

dos.h
bios.h
dpmi.h
stdio.h
conio.h
math.h
stdlib.h
go32.h
pc.h
sys/nearptr.h

And then you also have to declare the following global pointers:

char *vgamemory;
char *vgabuffer;

Of course one main question does come to mind... what does all that code do? Well, it changes the video mode to 13h... But what does each individual line do?! Well, I'll show you:
The first line is obvious:
int init_vga_mode(void)
It sets up the function, and if you don't know what "setting up a function" means then you shouldn't be reading this until you do.
The second line (after the "{" ) which is:
union REGS regs;
sets up a union of the type REGS with the name regs. That union will be later used to store the address of the hardware function that we want to execute.
The third line:
__djgpp_nearptr_enable();
enables the "real memory access by way of pointers" mode. Since DJGPP compiles protected mode programs, we can't directly access the computer hardware and memory, so we must use this function to allow use to access them indirectly by using pointers. Again, if you don't know what a pointer is, you shouldn't be reading this until you do.
Now the third line:
vgamemory=(char *)(0xA0000 + __djgpp_conventional_base);
tells your program that "vgamemory" points to the video memory (which starts at 0xA0000) plus the djgpp conventional base. The DJGPP conventional base is one of the things that the __djgpp_nearptr_enable() function initializes, we use the DJGPP conventional base to point to certain sections of memory by adding it to the real-mode address. So basicly this line makes vgamemory point to a pointer that is pointing to the video memory (wow, that was a breath full).
The 4th line:
if((vgabuffer=(char *)malloc(320*200))==0)
sets up the video buffer which is actually not needed, but if your going to program real time graphics then it is (especially with game programming). All it does is it ask if it can allocate 320*200 bytes of memory for the video buffer, and if it can, then it does. Well, actually it does something a little different, but it ends out the same way.
The 5th line:
return(1);
is within the above if statement, and this will let you know that it couldn't allocate any memory for the video buffer because it returns 1 and exits the function if it can't.
The 6th line:
regs.h.ah=0x00;
puts the byte 0x00 into the h.ah section of regs (whcih, if you remember, is a union). 0x00 is the hardware operation that tells the computer that you are about to change the video mode. Right now this won't do anything, but we need it there for the int86 function (which is coming).
Now the 7th line:
regs.h.al=0x13;
basically does the same thing as the 6th line except it puts a different byte into a different section of "regs". The byte 0x13 represents the 13h video mode, this is what will be past into the 0x00 function so that it knows which video mode to change to.
The 8th line:
int86(0x10, regs, regs);
calls the bios interrupt 0x10, and passes regs.h.ah to 0x10 as the hardware function to run, and then it passes regs.h.al to 0x10 (which is basically "run hardware procedure/function") so that 0x10 will pass it to what ever is in regs.h.ah (in our case 0x00). So this is the part of our function that actually CHANGES the video mode... all the stuff before this was just preparing to change it.
The 9th (and last) line:
return(0);
just returns 0, which means that our function has successfully changed the video mode :)
Now how do I change the video mode back?
Well, all you really have to do is call the "video mode changing" hardware function (0x00) with the text mode byte in regs.h.al, un-allocate the video buffer, and then turn off the "real memory access by way of pointers" mode. So how do I do that?! Well, here's the code for you:
void done_vga_mode(void)
{

union REGS regs;
regs.h.ah=0x00; //Procedure 0x00: Set Video Mode
regs.h.al=0x03; //The mode to set (0x# = #h)
int86(0x10, regs, regs); //Call BIOS intr 0x10
free(vgabuffer);
__djgpp_nearptr_disable();

}
So what does each line in that do? It does what I just said above: it calls the video mode changing hardware function with the text mode byte in regs.h.al, un-allocates the video buffer, and then turns off the "real memory access by way of pointers" mode.
How does this help me when I don't even know how to plot a pixel?
It doesn't, but if you don't know how to change the color palette then pixel plotting doesn't help you either.

Any questions send mail to cplus@teentwo.8m.com


2. Setting the palette in mode 13h

What is the color palette?

The color palette is a hardware array (in other words, it's built into your computers hardware) of pointers that point towards a set of RGB(Red Green Blue) values. Each pointer in the array points to (as I stated above) an RGB value.

So there are actually 3 values in an RGB value:
R=amount of red in the color=a value that can range from 0-63 (0 being lowest and 63 being highest)
G=amount of green in the color=a value that can range from 0-63 (0 being lowest and 63 being highest)
B=amount of blue in the color=a value that can range from 0-63 (0 being lowest and 63 being highest)

Therefor a full red would look like this: 63,0,0. And a full green would look like this: 0,63,0. And a full blue would look like this: 0,0,63. Get the idea? Good.
So it's just like in art class when you mixed red, yellow and blue paint together to make different colors... except for two things:
1) Instead of yellow you have green.
2) Your not working with matter, your working with light.

Now I'm guessing that you know what the 1st difference means, but you might not know what the second means. Basically it means that when you mix all of them together at there highest strength (63,63,63) you get white (instead of black like with the paint in art class) and instead of seeing the white paper when there was no paint on it (0,0,0) you get black. Another way to look at it is by imagining the following:
A white piece of paper in a pitch black room.

  1. Now when you shine a red light on it (63,0,0), it makes the paper red..
  2. When you shine a green light on it (0,63,0), it makes it green..
  3. When you shine a blue light on it (0,0,63), it makes is blue..
  4. When you shine all of the lights on it (63,63,63), it lets you see the real papers color which is white..
  5. When you don't shine any light on it (0,0,0), the room is pitch dark.

So how do I change the palette's colors?
Well, there are several different ways to do it, my favorite (and the only one that I actually know the code for) is the following:

void set_palette(int index, int red, int green, int blue)
{

outp(RGB_RESET, 0xFF); //Prepare the VGA card for the color change
outp(RGB_WRITE, index); //Tell which palette register to write to
//The following values can be anywhere from 0 to 63
outp(RGB_DATA, red); //change the red value
outp(RGB_DATA, green); //change the green value
outp(RGB_DATA, blue); //change the blue value

}

And the code above should work with DJGPP as long as you include the following:

dos.h
bios.h
dpmi.h
stdio.h
conio.h
math.h
stdlib.h
go32.h
pc.h
sys/nearptr.h

and you define the following:

#define RGB_RESET 0x03C6
#define RGB_READ 0x03C7
#define RGB_WRITE 0x03C8
#define RGB_DATA 0x03C9

Of course I also have to tell you how to use this function... basically you tell it which color you want to change (index) and then you give it the RGB values (red, green, blue) which can each range from 0-63. So if you wanted to change the color 58 to a RGB value of 20,20,20 (which would be a light gray) you would call the function like this:
set_palette(58, 20, 20, 20);

Now some of you might be wondering how many colors there are in the color palette... well, we're working with mode 320x200x256, so that means that we have 256 colors to work with, which are 0 through 255. So the highest number that you can enter into the index parameter is 255 and the lowest is 0. Now don't get me wrong here, the number of the color has nothing to do with what the color actually is, it's just a way to place, find and use the color. example:
In one game you may have a color palette that is set up like so:
0=<0,0,0>
1=<1,1,1>
2=<2,2,2>
etc......
64=<1,0,0>
65=<2,0,0>
66=<3,0,0>
etc......
128=<0,1,0>
129=<0,2,0>
130=<0,3,0>
etc......
192=<0,0,1>
193=<0,0,2>
194=<0,0,3>
etc....... until 255
and then you might have another palette in a different game that's set up like this:
0=<3,7,2>
1=<7,2,5>
2=<9,1,3>
etc....... until 255
So as you can see that there are no restrictions as to which color you can put where, it's all up to you. The indexes are just there so that your colors are organized and so that you know where each color is on your color palette.

Now I will show you what the palette changing code does step by step.
The first line of code:
void set_palette(int index, int red, int green, int blue)
just sets up the function and it's parameters.
The second line (which is after the "{"):
outp(RGB_RESET, 0xFF); //Prepare the VGA card for the color change
does exactly what the comment says: it prepares the VGA card for the palette change. But how does it do that? It does that by calling 0xFF (which is a standard bios call which is related to the VGA card) and passing 0x03C6 to it, which tells the VGA card that we want to change the color palette.
The third line of code:
outp(RGB_WRITE, index); //Tell which palette register to write to
passes the value of our variable "index" to 0x03C8 which tells the VGA card which color we want to change.
The fourth line of code:
outp(RGB_DATA, red); //change the red value
passes the value of "red" to 0x03C9. 0x03C9 is a hardware function that takes what ever value is given to it and puts that value into the next color value in line, and in this case since nothing has been edited since we called 0x03C8 it puts the value of "red" into the R color value (remember "RGB"?).
The 5th line of code:
outp(RGB_DATA, green); //change the green value
does the same thing as the 4th except since 0x03C9 HAS been called once, it will now put the value into the G color value instead of the R color value.
the 6th line of code:
outp(RGB_DATA, blue); //change the blue value
changes the B (from RGB) color value.

Color Rotation
Ah, color rotation... the signature of a pro. So what is it? Many older games used it to make it look like water was moving since they couldn't update each pixel on the screen (computers were very slow back then). SO WHAT IS IT!? Color rotation... one of the finest effects one could ever hope to achieve.Well, color rotation is when you change the color palette to give the affect of movement.

example:
You want to make it look like a water fall was actually falling, and lets say you've already used up to many compute cycles to be able to afford to update the screen anymore (yea right, like that could ever happen with a Pentium. But this is hypothetical... remember?). So what would you do? Well, all you have to do is make lines of color down the water fall, and each line is a different color palette index like this:
90,90,90,90,90,90
91,91,91,91,91,91
92,92,92,92,92,92
93,93,93,93,93,93
94,94,94,94,94,94
95,95,95,95,95,95
96,96,96,96,96,96
97,97,97,97,97,97
So now we just rotate the colors 90 through 97 so that the RGB value that was in 90 goes into 91 and the RGB value that was in 91 goes into 92, and 93 goes into 94, etc. and then at the end 97 goes back into 90. All you have to do is to do this each frame and it will look like the water fall is falling. Of course strait lines don't look like a water fall, but you get the idea. You can also do it to achieve different movement effects like a pixel moving across the screen:

90, 91, 92, 93, 94, 95, 96, 97
And now you make the back ground black (0,0,0) and have all except one of the other colors be black also and have the one that's not black be white or something like that and then rotate 90 through 97. When you do that it gives the effect that a white pixel is moving across the screen against a black back ground.

Any questions send mail to cplus@teentwo.8m.com


3. Mode 13h putpixel

There are faster ways to do this but this is by far the easiets. This code will work in most compilers and not just DJGPP.

void putpixel(int x, int y, int color)
{

union REGS inregs,outregs;

inregs.h.ah = 12;
inregs.h.al = color;
inregs.x.cx = x;
inregs.x.dx = y;
int86(0x10, &inregs, &outregs);

}

Any questions send mail to cplus@teentwo.8m.com

Link of the week 
http://www.cpp-
programming.
com/
Newsgroups
comp.lang.c
comp.lang.c++
comp.programming

This page is best viewed in 800x600x256. This page was last edited Saturday, July 15, 2000