Home | Sales | Downloads | Forum | FAQ | Links | Terms | Email
     
 
Navigation
Programming

VESA Graphics Programming
Here you can learn how to use 640*480 resolution graphics. Intermediate programming knowledge is assumed. We recommend users to go through the tutorial in sequence and check all the examples.

Whats VESA?

VESA is a standard which provides programmers with a single method for using many different video cards. With VESA you need not worry about the secific hardware in different cards, you only need to understand the VESA funcitons. Anyone old enough will remember having to install a VESA driver for therir video card, these days it's implemented in hardware though - so that's another thing you need not worry about. We highly recommend that anyone attempting this tutorial gets a copy of the official VESA 2.0 specification. This tutorial should get you up and running even if you don't understand a word of it though!

Vesa Infomation Structures

To begin with you need 2 structures to store infomation returned to you by the video card. Just copy ours. VESA_INFO will store infomation about your video card. MODE_INFO will hold infomation about the graphics mode you are using. The use of many fields should be fairly obvious:

typedef struct VESA_INFO
{
unsigned char VESASignature[4] __attribute__ ((packed));
unsigned short VESAVersion __attribute__ ((packed));
unsigned long OEMStringPtr __attribute__ ((packed));
unsigned char Capabilities[4] __attribute__ ((packed));
unsigned long VideoModePtr __attribute__ ((packed));
unsigned short TotalMemory __attribute__ ((packed));
unsigned short OemSoftwareRev __attribute__ ((packed));
unsigned long OemVendorNamePtr __attribute__ ((packed));
unsigned long OemProductNamePtr __attribute__ ((packed));
unsigned long OemProductRevPtr __attribute__ ((packed));
unsigned char Reserved[222] __attribute__ ((packed));
unsigned char OemData[256] __attribute__ ((packed));
}VESA_INFO;

typedef struct MODE_INFO
{
unsigned short ModeAttributes __attribute__ ((packed));
unsigned char WinAAttributes __attribute__ ((packed));
unsigned char WinBAttributes __attribute__ ((packed));
unsigned short WinGranularity __attribute__ ((packed));
unsigned short WinSize __attribute__ ((packed));
unsigned short WinASegment __attribute__ ((packed));
unsigned short WinBSegment __attribute__ ((packed));
unsigned long WinFuncPtr __attribute__ ((packed));
unsigned short BytesPerScanLine __attribute__ ((packed));
unsigned short XResolution __attribute__ ((packed));
unsigned short YResolution __attribute__ ((packed));
unsigned char XCharSize __attribute__ ((packed));
unsigned char YCharSize __attribute__ ((packed));
unsigned char NumberOfPlanes __attribute__ ((packed));
unsigned char BitsPerPixel __attribute__ ((packed));
unsigned char NumberOfBanks __attribute__ ((packed));
unsigned char MemoryModel __attribute__ ((packed));
unsigned char BankSize __attribute__ ((packed));
unsigned char NumberOfImagePages __attribute__ ((packed));
unsigned char Reserved_page __attribute__ ((packed));
unsigned char RedMaskSize __attribute__ ((packed));
unsigned char RedMaskPos __attribute__ ((packed));
unsigned char GreenMaskSize __attribute__ ((packed));
unsigned char GreenMaskPos __attribute__ ((packed));
unsigned char BlueMaskSize __attribute__ ((packed));
unsigned char BlueMaskPos __attribute__ ((packed));
unsigned char ReservedMaskSize __attribute__ ((packed));
unsigned char ReservedMaskPos __attribute__ ((packed));
unsigned char DirectColorModeInfo __attribute__ ((packed));
unsigned long PhysBasePtr __attribute__ ((packed));
unsigned long OffScreenMemOffset __attribute__ ((packed));
unsigned short OffScreenMemSize __attribute__ ((packed));
unsigned char Reserved[206] __attribute__ ((packed));
}MODE_INFO;

Testing for VESA

We will use the VESA_INFO structure when we first check for valid VESA infomation with this function:

VESA_INFO vesa_info;//info will be stored in here

int get_vesa_info()
{
__dpmi_regs r;
long dosbuf;
int c;
dosbuf = __tb & 0xFFFFF;
for (c=0; c<sizeof(VESA_INFO); c++)
_farpokeb(_dos_ds, dosbuf+c, 0);
dosmemput("VBE2", 4, dosbuf);
r.x.ax = 0x4F00;
r.x.di = dosbuf & 0xF;
r.x.es = (dosbuf>>4) & 0xFFFF;
__dpmi_int(0x10, &r);
if (r.h.ah)
return -1;
dosmemget(dosbuf, sizeof(VESA_INFO), &vesa_info);
if (strncmp(vesa_info.VESASignature, "VESA", 4) != 0)
return -1;
return 0;//OK
}

Here we are using the dos interrupt 10 Hex. All VESA funtion are called though this combined with a value loaded into the AX register. This function returns zero if valid VESA info is found.

Setting VESA modes

Once you have validated VESA compatability you are ready to set and check for the various resolutions available:

int set_vesa_mode(int mode)
{
__dpmi_regs r;
r.x.ax = 0x4F02;
r.x.bx = mode;
__dpmi_int(0x10, &r);
if (r.h.ah)
return -1;
return 0;
}

int get_vesa_mode()
{
__dpmi_regs r;
r.x.ax = 0x4F03;
__dpmi_int(0x10, &r);
if (r.h.ah)
return -1;
return r.x.bx;
}

The following get_mode_info fuction can be used in conjuntion with these to get specific details about a mode:

int get_mode_info()
{
__dpmi_regs r;
long dosbuf;
int c;
dosbuf = __tb & 0xFFFFF;
for (c=0; c<sizeof(MODE_INFO); c++)
_farpokeb(_dos_ds, dosbuf+c, 0);
r.x.ax = 0x4F01;
r.x.di = dosbuf & 0xF;
r.x.es = (dosbuf>>4) & 0xFFFF;
r.x.cx = 257;
__dpmi_int(0x10, &r);
if (r.h.ah)
return 0;
dosmemget(dosbuf, sizeof(MODE_INFO), &mode_info);
return 1;
}


It may be worth going through this example which includes calls to all the code so far.

Drawing

Initially you may draw to a buffer as in the VGA examples earlier in this tutorial. When we come to display that buffer there are new considerations. The video memory for high resolutions is split into a number of banks (the reason for this lies in limitions of PC architechture). The 640*480 buffer will have to be copied in (probably 4) chunks. The following code will do this:

void copy_to_vesa_screen(char *memory_buffer)
{
int bank_number=0;
int todo=307200;
int copy_size;
while (todo>0)
{
set_vesa_bank(bank_number);
if (todo>65536)
copy_size=65536;
else
copy_size=todo;
dosmemput(memory_buffer, copy_size, 0xA0000);
todo-=copy_size;
memory_buffer+=copy_size;
bank_number++;
}
}


Note the use of set_vesa_bank function detailed here:

void set_vesa_bank(int bank_number)
{
__dpmi_regs r;
r.x.ax = 0x4F05;
r.x.bx = 0;
r.x.dx = bank_number;
__dpmi_int(0x10, &r);
}


We now have all the tools to display pictures in 640 * 480 resolutions. Have a look at this example which includes setting the pallette and using a bitmap.

All product names and logos are registered trademarks of their respective owners.
All content www.retro-games.co.uk
Search




Links


Our freeware
DJGPP
VESA