Friday, February 21, 2020 | Toby Opferman

## Super VGA Tutorial

```Toby Opferman
http://www.opferman.net
programming@opferman.net

How To Use Super VGA (VESA 1.x Non-Linear)

First, we set the Video Mode we want, in our example,
we will be using 640x480x256 since it is a common mode.

MOV AX, 04F02h      ; Set VESA Video Mode
MOV BX, 101h        ; 640x480x256
INT 10h             ; Video Interrupt
CMP AX, 04Fh        ; AX = 04Fh ?
JNE MODE_ERROR      ;    If No Then Video Error

We Call Function 4Fh and SubFunction 02h of Interrupt 10h.
Function 4Fh = Vesa Functions, SubFunction 02h = Set Video Mode

Now, you have successfully set the Video Mode.  But, there
is one problem.  The Video Buffer is at A000:0000!  That is a 64k Segment.
640*480 > 64k!!!  So, how can you display shit on the screen if the video
screen isn't large enough to hold the image?  Well, there is something called
bank switching.

Bank Switching allows you to switch to another Window of the screen.

-----------------------------------------------------------|
|                                                          |
|                                                          |
|                 Bank 0                                   |
|                                                          |
|----------------------------------------------------------|
|                                                          |
|                 Bank 1                                   |
|                                                          |
|                                                          |
|----------------------------------------------------------|
|                                                          |
|                 Bank 2                                   |
|                                                          |
|                                                          |
|----------------------------------------------------------|
|                                                          |
|                 Bank 3                                   |
|                                                          |
|                                                          |
|----------------------------------------------------------|
|                                                          |
|                 Bank 4                                   |
|----------------------------------------------------------|

There is a SubFunction to Bank Switch, 05h.

MOV AX, 04F05h       ; Bank Switch
XOR BX, BX           ; Page Number 0
MOV DX, BankNumber   ; Bank Number
INT 10h              ; Video Interrupt

To Plot a Pixel, just let the Offset Wrap around.
in C, specify a SHORT type (65535) so that it will wrap around when
it hits the top marker and it will be in the correct position for the
plot.

short Offset;
Offset =  X + (Y*640);
or
Offset =  X + (Y<<7) + (Y<<9);

This isn't too bad so far, but there is more.  Every video card
is differnt and doesn't lable the Banks 0, 1, 2, 3, 4 (Some Do).
It All depends on the Window Granularity.  Each Card has a Differnt Bank
Granularity.

To Get the BankNumber it is:
BankNumber = (64/Window Granularity) * Bank;

Where Bank is 0 - 4

To Get The Window Granularity, takes a call to SubFunction 1 of
VESA.  But, you need to allocate an entire structure because you get more
than just the window Granularity.

Here is a Example of one in C:

/* VESA Mode Information Structure */
typedef struct vesa_type {
short ModeAttrib;
char WindowA_Attrib, WindowB_Attrib;
short WinGran, WinSize, SegWinA, SegWinB;
long WindowPointer;
short Bits_Per_Scanline, HorzRes, VertRes;

char Width, Height, MemPlanes,
BPP, NumBanks, MemType,
SizeBank, NumberPages, Reserved,
DirectColorModeInfo, ReservedBlock[216];

} VesaInfo, *VesaInfoPtr;

WinGran is the Window Granularity.

Here is a call to get the Window Granularity:
MOV AX, Seg VESAStructure    ; Get Structure Segment
MOV ES, AX                   ; Set ES to Segment
MOV DI, Offset VESAStructure ; Set DI To Offset
; ES:DI = VesaStructure

MOV AX, 04F01h     ; VESA Mode Structure
MOV CX, 101h       ; Mode 101h (640x480x256)
INT 10h            ; Video Interrupt

Now you have the Video Granularity.

VESAStructure.WinGran

You may now either BankSwitch = 64/VESAStructure.WinGran;
and do BankSwitch*Bank every time to get the BankNumber.
Or, The Window Granularity is a Power of 2. So, a divison
of 64 would give you a multiler that would really be like
shifting the bank.  The Following C switch statement illustrates.

switch(VESA->WinGran)
{
case 1 : Shifter = 6;
break;

case 2 : Shifter = 5;
break;

case 4 : Shifter = 4;
break;

case 8 : Shifter = 3;
break;

case 16 : Shifter = 2;
break;

case 32 : Shifter = 1;
break;

case 64 : Shifter = 0;
break;

default:
return 0xFF;  /* Error */
}

So, now to find out the BankNumber:

Bank<<=Shifter;
or
BankNumber = Bank<<Shifter;

That should be used for faster executable code.
Now you know how to use VESA (8-bit Colour modes, for other modes,
it is the same except the offset calculations should be differnt
based on how many bits per pixel is used.)

Now, you can plot to the screen using a double buffer, and every time
you plot 64k, bank switch.  If you want to plot one pixel at a time, you will

long Offset;

Offset = (Y<<9) + (Y<<7) + X;

Now, the high word of Offset (Offset is 32 bit) will be the bank number.

You see, there are 65536 bytes in 64k (0-65535), and, once you get to
65536, you are actually in the next bank!  And that number is:
10000h  Which is offset 0000h (Cause real mode offsets are 16 bit).

Notice what we can do tho.

Offset = (Y<<9) + (Y<<7) + X;

Calculate the offset in a 32 bit integer.  Then, to get the bank:

Bank = Offset>>16; /* To get the Bank, we need the High Word of Offset */

Offset&=0xFFFF;  /* The 16 Bit offset is the Low Word of Offset */

And that's how it's done.  Then just

BankSwitch as told above using the Shifter on Bank then calling the Interrupt.

Then plot at A000h:Offset (16 bit Offset) your Colour.

```

Professional software engineer with over 15 years...

Codeproject Articles

Programming related articles...

Articles »
Resume

Resume »
Contact

Email: codeproject(at)opferman(dot)com