Virtual Screens |
Virtual screens are a very powerful graphics programming tool. But what the hell are they?
Lets say you have a screen that involves some complex drawing, maybe it contains a number of animated sprites, that you continually have to redraw on the fly. Now, imagine the flicker that the user will be able to see with all of this going on. There will also be what is known as a "doubling" effect where you can see two copies of the same sprite next to each other.
Virtual screens are one of the many solutions to this problem, and they are by far the easiet ones to code.
Essentially, a virtual screen is nothing more than a section of memory set aside which is exactly the same as our VGA screen, onto which you draw everything, then you "flip" it onto the VGA screen. This was the user never actually sees things being drawn, they only see the end results!
In other graphics modes you automatically have a virtual page setup, but mode13h offers no such luxury. So for our purposes, we will create one using base memory.
Setting up of a virtual screen
As indicated earlier, the mode13h screen is 64000 bytes (320x200 = 64000). Now, you would think to set up a virtual screen the best thing to do would be to declare something like this to make a virtual screen:
unsigned char Virtual[64000].
Well, that may be the easiest way to type it, but there are problems. Firstly, many compilers won't allow you to have a variable that large. Secondly, it would leave you with almost no space for your other variables. So what we do is declare one like this:
unsigned char *Virtual = NULL;
This creates a pointer to our virtual screen. Of course, this isn't a virtual screen yet. You try using this and your program will most likely crash. Why? Because we haven't gotten the memory for it yet. We do that like this:
void SetupVirtual()
{
Virtual = (unsigned char *) calloc(64000,1);
}
This allocates the required memory for our virtual screen.
Now, naturally, we will want to free the memory used for our virtual screen after our program has finished. We do that like this:
void ShutdownVirtual()
{
free(vaddr);
}
This is important, because if you don't do it then other programs will have less memory to use.
Drawing to our virtual screen
This is very similar to drawing to our normal mode13h screen. The original PlotPixel went like this:
void PlotPixel(int x, int y, char colour)
{
int offset;
offset = (y*320) +x;
*(vga + offset)=colour;
}
To plot one to our virtual screen we do it like this:
void PlotPixel(int x, int y, char colour)
{
int offset;
offset = (y*320) +x;
*(Virtual + offset)=colour;
}
Simple! However, is it necessary to have 2 separate routines? Can we combine them to 1 routine? Of course we can. Here's how we do it:
void PlotPixel(int x, int y, char colour,
unsigned char *Where)
{
int offset;
offset = (y*320) +x;
*(Where + offset)=colour;
}
So now we can call our PlotPixel routine this way:
PlotPixel(160,100,50,vga); // plots a pixel
to the vga screen
PlotPixel(50,50,100, Virtual); // plots a pixel to the virtual
screen
By now you should know how to go back and change all our old drawing routines to support virtual screens. But wait! We can't actually SEE what's on our virtual screens yet! Guess I'd better show you how. ;)
Display virtual screens
To display our virtual screen, we use a process known as "flipping". This is where we flip one screen onto another. In mode13h we do this by simply copying the contents of our virtual screen to our screen using a straight memory copy, like so:
void Flip()
{
_fmemcpy(vga, Virtual, 64000);
}
This copies the contents of our Virtual screen to the vga screen. So whatever is on our Virtual screen is now visible.
There you have it! Virtual screens! I have included a small sample program that draws a bunch of circles to our virtual screen, then waits for a user keypress, then in flips the virtual screen to our vga screen. I have also rewritten our circle drawing routine to support virtual screens. You should be able to modify our other routines to support virtual screens. If anyone is having trouble with this, contact me and I will help you.
The sample program also has a routine that clears a screen, vga or virtual, to a specified colour.
Download the source code and example program here.