To begin with you need to set the mode on the PC's video card. This function will achieve this:
void set_video_mode(int mode)
{
union REGS regs;
regs.x.ax = mode;
int86(0x10, ®s, ®s); //DOS interrupt to set video mode
}
We are using the popular Mode 13 because it allows 200X320 resolution
with 256 colours, so call this function with 13hex like this:
set_video_mode(0x013);
Finally, when the program is complete it is sensible to return to
the normal text video mode (remember this is a DOS program)
set_video_mode(0x03);
Download a working example
If you don't have DJGPP, download it
here
As you will want to see the pixels you draw you
must set the palette up (otherwise you will only draw black pixels).
Here is the code to put a colour into one of the palettes 256
indexes:
void set_palette_register(unsigned char index, rgb_color* color)
{
outportb(0x3c6, 0xff);
outportb(0x3c8, index);
outportb(0x3c9, color->red);
outportb(0x3c9, color->green);
outportb(0x3c9, color->blue);
}
The data type rgb_color
is one you will need to add a definition for:
typedef struct rgb_color_type
{
unsigned char red;
unsigned char green;
unsigned char blue;
} rgb_color;
Each component in the structure (red,green,blue) can have a value
from 0 to 63. An example is included in the next section.
Think of your screen as a pictorial view of video
memory. To display pixels you simply need to write a byte to video
memory. The value of the byte is an index for the 256 colour palette.
The screen is set up like this:
Here is the put_pixel
code:
void put_pixel(short int x, short int y, char color)
{
video_buffer[(y << 8) + (y << 6) + x] = color;
}
This should be all you need to draw a coloured pixel on the screen. Whoohoo!
Download a working example
It is worth writing all your pixels to a buffer
first and then copying the whole lot to video memory in one go.
Otherwise the screen will flicker with many things being drawn
at different times.
Define double_buffer
as an array the same size as video memory:
char *double_buffer;
double_buffer=(char *)malloc(64000);//(200*320)
The malloc
function used will dynamically (at run
time) allocate 64000 bytes of memory to the buffer. Because the
memory is allocated during runtime, it must also be freed at the
program end:
free(double_buffer);
Now change the pixel function...
void put_pixel(short int x, short int y, char color)
{
double_buffer[(y << 8) + (y << 6) + x] = color;
}
...so that it writes to the buffer. You can then
'draw' the whole lot in one go like this:
memcpy((char *)video_buffer,(char *)double_buffer,64000);
Download a working example
Rather than painstakingly setting up a colour palette,
just load a complete one from a bitmap file:
void loadPal256(char* fileName)
{
FILE* bmpFile = fopen(fileName, "rb");
short int i;
rgb_color col;
fseek(bmpFile, 54, SEEK_SET);
for (i = 0; i < 256; i++)
{
col.blue = fgetc(bmpFile) / 4;
col.green = fgetc(bmpFile) / 4;
col.red = fgetc(bmpFile) / 4;
fgetc(bmpFile); //reserved i.e. not used
set_palette_register(i, &col);
}
fclose(bmpFile);
}
Call this function with the name of a bitmap file. The
bitmap must be 256 colour format.
Download a working example