#### Advanced SVGA I by Anthony Tyler 07.03.99

Most of you probably remember the three articles on SVGA that Aaron Severn wrote. These articles touched on the basics of SVGA programming. I am hoping to go into a more in depth look at the SVGA. I will teach you how to program the SVGA by creating a library of SVGA functions. First of all, you will need an assembler, such as TASM or MASM. This is pretty important, but since most people don't have one I will write my code using the Call Absolute command. You will also need a SVGA card with at least 1 MB of video memory (512 kb might be okay). It's a good idea to get UNIVBE if you don't have a VESA card.

## A recap of svga basics

 Review of basic SVGA First, I will review the basics of SVGA. If you grasped Aaron's articles well, then you could skip this part, but I suggest you read over it anyways. Since Aaron went into this well, I will not go into detail on this subject. Just the hard facts. Detecting the VESA When dealing with the VESA we must first check to see if the computer has a VESA card. We do this by calling VESA function 00h(remember all VESA functions are preceded by &H4F). VESA function 00h is also used, for finding information on the VESA card. We find information on the card by setting a TYPE. TYPE VGAInfoBlock VESASignature AS STRING * 4 VESAVersion AS INTEGER OEMStringPTR AS LONG Capabilities AS STRING * 4 VideoModePTR AS LONG TotalMemory AS INTEGER Reserved AS STRING * 236 END TYPE The segment and offset of the VGAInfoBlock is loaded into the ES and DI registers, respectively. We do this by doing the following: Regs.AX = &H4F00 ' VESA function 00h Regs.ES = VARSEG(VGAInfoBlock) Regs.DI = VARPTR(VGAInfoBlock) CALL InterruptX (&H10, Regs, Regs) Don't forget to put in the beginning of the programming a DIM SHARED Regs as RegTypeX. Because, this allows us to use the InterruptX procedure. If a VESA is found then it returns &H4F in AX, if any other value is found then there is not a VESA card on the computer. After this function, is called, it stores at ES:DI the following information. VESASignature: always 'VESA' if there is a VESA card VESAVersion: returns the VESA version number usually 1.2 or higher. OEMStringPTR: pointer to a string that can be used to identify the video chip, video board, memory configuration, etc. Capabilities: describes the capabilities of the video card VideoModePTR: a pointer to a list of supported screen modes TotalMemory: the total memory of the video card in 64 kb blocks. Reserved: Reserved for future use. So our complete DetectVESA function is as follows. '\$INCLUDE: 'QB.BI' TYPE VGAInfoBlock VESASignature AS STRING * 4 VESAVersion AS INTEGER OEMStringPTR AS LONG Capabilities AS STRING * 4 VideoModePTR AS LONG TotalMemory AS INTEGER Reserved AS STRING * 236 END TYPE DIM SHARED Regs as RegTypeX, VGAInfo as VGAInfoBlock DEFINT A-Z FUNCTION DetectVESA% RegsX.ax = &H4F00 RegsX.es = VARSEG(VGAInfo) RegsX.di = VARPTR(VGAInfo) CALL INTERRUPTX(&H10, RegsX, RegsX) IF RegsX.ax = &H4F AND VGAInfo.VESASignature = "VESA" THEN DetectVESA = 1 ELSE DetectVESA = 0 END IF PRINT "VESA Version:"; RTRIM\$(STR\$(VGAInfo.VESAVersion \ 255)); "."; PRINT LTRIM\$(STR\$(VGAInfo.VESAVersion AND 255)) END FUNCTION Finding information on, and setting a VESA screen mode. The next step we need to take in our VESA library, is to set a VESA screen mode. Here is a list of VESA screen modes, not all of them are supported on all cards, or monitors. ``` VESA Mode Resolution Colors 100h 640x400 256 101h 640x480 256 102h 800x600 16 103h 800x600 256 104h 1024x768 16 105h 1024x768 256 106h 1280x1024 16 107h 1280x1024 256 108h 80x60 text 109h 132x25 text 10Ah 132x43 text 10Bh 132x50 text 10Ch 132x60 text 10Dh 320x200 32k 10Eh 320x200 64k 10Fh 320x200 16.8m 110h 640x480 32k 111h 640x480 64k 112h 640x480 16.8m 113h 800x600 32k 114h 800x600 64k 115h 800x600 16.8m 116h 1024x768 32k 117h 1024x768 64k 118h 1024x768 16.8m 119h 1280x1024 32k 11Ah 1280x1024 64k 11Bh 1280x1024 16.8m ``` Before we set the screen mode, we need to find information on the mode. We do this by using VESA function 01h. In this function we set CX to the desired mode(see above) and ES and DI to the segment and offset of the following TYPE. TYPE ModeInfoBlock ModeAttributes AS INTEGER WinAAttributes AS STRING * 1 WinBAttributes AS STRING * 1 WinGranularity AS INTEGER WinSize AS INTEGER WinASegment AS INTEGER WinBSegment AS INTEGER WinFuncPointer AS LONG BytesPerScanLine AS INTEGER XResolution AS INTEGER YResolution AS INTEGER XCharSize AS STRING * 1 YCharSize AS STRING * 1 NumberOfPlanes AS STRING * 1 BitsPerPixel AS STRING * 1 NumberOfBanks AS STRING * 1 MemoryModel AS STRING * 1 BankSize AS STRING * 1 NumberOfImagePages AS STRING * 1 SizeOfBank AS STRING * 1 RedMaskSize AS STRING * 1 RedFieldPosition AS STRING * 1 GreenMaskSize AS STRING * 1 GreenFieldPosition AS STRING * 1 BlueMaskSize AS STRING * 1 BlueFieldPosition AS STRING * 1 RsvdMaskSize AS STRING * 1 RsvdFieldPosition AS STRING * 1 DirectColorModeInfo AS STRING * 1 Reserved AS STRING * 216 END TYPE For time reasons, I will not explain all of these(see Aaron's articles if you need information on these). I will only explain the important ones: MemoryModel is used for detecting if the mode is available XResolution is the amount of pixels going across YResolution is the amount of pixels going down NumberOfImagePages is the most important one, it tells how many pages of video memory can be used(more about this later). To actually set the mode we use VESA function 02h. In BX we store the desired mode. AX returns 4Fh if the operation was successful. This makes our set mode function as follows. '\$INCLUDE: 'qb.bi' COMMON SHARED xRes, yRes TYPE ModeInfoBlock ModeAttributes AS INTEGER WinAAttributes AS STRING * 1 WinBAttributes AS STRING * 1 WinGranularity AS INTEGER WinSize AS INTEGER WinASegment AS INTEGER WinBSegment AS INTEGER WinFuncPointer AS LONG BytesPerScanLine AS INTEGER XResolution AS INTEGER YResolution AS INTEGER XCharSize AS STRING * 1 YCharSize AS STRING * 1 NumberOfPlanes AS STRING * 1 BitsPerPixel AS STRING * 1 NumberOfBanks AS STRING * 1 MemoryModel AS STRING * 1 BankSize AS STRING * 1 NumberOfImagePages AS STRING * 1 SizeOfBank AS STRING * 1 RedMaskSize AS STRING * 1 RedFieldPosition AS STRING * 1 GreenMaskSize AS STRING * 1 GreenFieldPosition AS STRING * 1 BlueMaskSize AS STRING * 1 BlueFieldPosition AS STRING * 1 RsvdMaskSize AS STRING * 1 RsvdFieldPosition AS STRING * 1 DirectColorModeInfo AS STRING * 1 Reserved AS STRING * 216 END TYPE DIM Regs as RegTypeX, ModeInfo as ModeInfoBlock DEFINT A-Z FUNCTION SetMode (mode) Regs.AX = &H4F01 Regs.CX = mode Regs.ES = VARSEG(ModeInfo) Regs.DI = VARPTR(ModeInfo) CALL INTERRUPTX(&H10, Regs, Regs) IF ModeInfo.ModeAttributes AND 1 = 0 THEN PRINT "Cannot access mode" xRes = ModeInfo.XResolution yRes = ModeInfo.YResolution IF ModeInfo.WinSize < 64 THEN PRINT "This program only works with those modes with more than 64k of window" SetMode = 0 EXIT FUNCTION 'these routines. END IF IF ASC(ModeInfo.MemoryModel) <> 6 THEN PRINT "This Screen Mode is not available" SetMode = 0 EXIT FUNCTION END IF Regs.AX = &H4F02 'Set the mode. Regs.BX = mode CALL INTERRUPT(&H10, Regs, Regs) IF Regs.AX <> &H4F THEN 'Make sure it worked. PRINT "Screen mode could not be initialized" SetMode = 0 EXIT FUNCTION END IF SetMode = ASC(ModeInfo.NumberOfImagePages) + 1 END FUNCTION This function returns the amount of video pages and sets the screen mode. This is all we have time for today, sorry I didn't get to anything new, but the next part of the article will be completely new. (Editor: Look for the next part of this series coming very soon).