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, RedMaskSize, RedFieldPos, GreenMaskSize, GreenFieldSize, BlueMaskSize, BlueFieldSize, ReservedMaskSize, ReservedMaskPos, 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 have to follow this form: 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.