VBE is essentially a video BIOS extension. VBE specific functions are assigned a special function number, distinct from other VGA BIOS function numbers. It was intended that VBE would retain full compatibility with the standard BIOS, in the sense that they can co-exist. A VBE-aware application uses the VBE functions instead of the equivalent standard BIOS function where available, and uses the standard VGA BIOS for functions which VBE does not provide, or which are common across all video modes.
VBE can be implemented in two ways: hardware or software. The hardware solution requires that VBE capability be encoded into a Super VGA card's (or other framebuffer device, possibly not VGA compatible) BIOS. This method is very common among newer cards. The software solution requires that a memory resident program (a TSR in DOS terminology) be loaded to provide the services. This is obviously very operating-system dependent.
Note that VBE was designed to take away card specific problems while leaving common tasks to the application programmer. The main reason for this choice was increased speed and decreased memory needed by the VBE implementation. There are some disadvantages to this approach; the program must be flexible enough to accomodate differences in implementations, and no use of extended coprocessor-like capabilities of video cards is made.
Also note that the VBE standard document was publicly available up to version 1.2. Version 2.0 appears to have no public release, although I recently managed to obtain version 3.0 from the VESA web site. This document is therefore based mainly on the 1.2 and 3.0 standards, with 2.0 information taken from other sources. Also note that other extension standards which have not been made public (such as VBE/AF, the accelerator function standard) have not been covered.
The purpose was not just to document VBE - that's already been done - but to provide useful information and techniques so that the VBE may actually be put to use. Unfortunately, the actual specification is remarkable vague in some places (for a so called 'standard' it is very vague). I've attempted, with this document, to resolve some of the ambiguities and solve some of the problems.
'Super VGA' has come to mean a VGA chip capable of having more than 256KB memory and supporting modes of a higher resolution or number of colours. The addition of more memory to the standard 256KB does however present a problem: How is the additional memory to be accessed? The plane selection abilities of a VGA allow only 4 planes, and the memory window of a standard VGA is only 64KB in size, allowing a maximum memory access of (4 planes x 64KB) 256KB. Without using planes (by using the special chain-4 mode) only 64KB is accessible, hence the wide use of 320x200x256 mode.
The limitation can easily be overcome, usually by making the 64KB memory window 'moveable'; that is, the window can be made to point into any section of the video card's entire memory space (while remaining at a fixed address within the system memory address space). Many texts call this technique "banking" however I prefer to call it "window sliding" to avoid confusion with those old video modes which use line banks (CGA, Hercules).
It is possible when using window sliding to expand the window to 128KB (using the B000:0000 - B000:FFFF region normally reserved for monochrome video memory). It should also be mentioned that some cards allow a division of the single window memory space into a dual-window access system. This makes copying between different areas of video memory more efficient.
Some newer cards, particularly PCI-bus based cards (and possibly VLB?) also allow (as an alternative to window sliding) the mapping of the entire video memory to an address in system memory address space (usually to an area beyond that occupied by system RAM), thus providing a "linear framebuffer". Because the method used is video card specific, VBE must be used to ensure compatibility across the majority of cards. Note the latter method is supported only by VBE 2.0+.
AX = 4F00h; ES:DI = pointer to 256 byte buffer
INT 10h
The contents of the buffer are unimportant unless information about VBE
versions greater than 1.2 are required - in this case, the four-byte
signature "VBE2" must be stored at offset 0 in the buffer, which must be
512 bytes instead of 256; otherwise, a newer VBE extension will emulate a
version 1.2 extension for this call. The purpose of this is, presumably, to
prevent programs which "required VBE version 1.2" from refusing to run when
confronted with a newer version; personally I think this is a bad decision as
it complicates the specification and causes some system diagnostic software
to report the wrong VBE version (Microsoft's MSD [v2.00] for one, though MSD
even incorrectly reports version 1.2 as 1.02).Return is with AX 004Fh if the call is supported and was successful; in this case it can be assumed that a VESA driver or extension is present. No other registers should be changed, whether the call was successful or not. This AX return value reflects a status value available from all VESA calls (unless otherwise stated); AL holds the value 4Fh if the function is supported and AH holds 00 if the function was successful (it is conceivable that a function may be supported but for some reason fails). Unless otherwise noted, it can be assumed that a function will always be successful unless it is provided with invalid parameters (or it is not supported). All function calls detailed here must be supported by a VBE implementation of the appropriate version, unless otherwise noted.
The returned buffer (if the call is successful) will be formatted as follows:
| Offset | Name | Size | Meaning |
| 00 | VESASignature | 4 BYTEs | Signature: should = "VESA" |
| 04 | VESAVersion | WORD | version. See below |
| 06h | OEMStringPtr | DWORD | Oem manufacturer (pointer to ASCIIZ string) (see note) |
| 0Ah | Capabilities | DWORD | See below |
| 0Eh | VideoModePtr | DWORD | Pointer to supported modes (see below) |
| 12h | TotalMemory | WORD | Number of 64KB blocks of video memory |
| 14h | OemSoftwareRev | WORD | (v2.0+) OEM software version. BCD, LSB first |
| 16h | OemVendorNamePtr | DWORD | (v2.0+) Product vendor (pointer to ASCIIZ string) |
| 1Ah | OemProductNamePtr | DWORD | (v2.0+) Product name (pointer to ASCIIZ string) |
| 1Eh | OemProductRevPtr | DWORD | (v2.0+) Production revision (pointer to ASCIIZ string) |
| 22h | Reserved | 222 bytes | |
| 100h | OemData | 100h bytes | (v2.0+) May be used by the VBE routine |
Note: If v2.0+ information is requested, a v2.0+ implementation must ensure that the OEM string is stored within the OemData, that the video mode list is in the "unused" area or statically stored, and that the Oem vendor name, product name and product revision are stored in OemData or statically.
04 - VESAVersion: The high byte specifies the major version and the low byte specifies the minor version. So, a value of 0102h specifies a version of 1.2 (not version 1.02).
0A - Capabilities: bit 0 specifies whether the DAC colour table width is fixed at 6 bits (0) or programmable (1). A programmable-width colour table must default to 6 bits width on any mode switch. Version 2.0+: bit 1 is a flag indicating a "non VGA controller" (not port compatible with VGAs) and bit 2: "program DAC with blank bit" indicates that, particularly for large changes, pallette manipulation should be performed during retrace (see pallette manipulation functions).
0E - VideoModePtr: A pointer to a list of (WORD size) mode numbers, terminated by the value 0FFFFh. More information about specific modes can be found using another function call. Modes listed are not necessarily available for use under current hardware configuration. Note that some implementations (incorrectly) store the mode list within the "unused" portion of the first 100h bytes of the buffer; it would be more appropriate to store it in the 100h byte OEM scratchpad, but this is only available in version 2.0+.
A VESA application will attempt to detect VESA, in doing so gaining a list of mode numbers. It may then use the list of mode numbers to find a mode suitable to its purposes (or to provide the user with a list of possible modes; exact use is up to the programmer). Note that certain mode numbers are assosciated with definite resolutions, number of colours and mode type (text or graphic). It is possible to find a required mode by looking for the mode number; however this would not allow the use of video modes specific to the video card (How to find specifications about both types of mode is revealed below).
| Number (hex) | Assosciation |
| 100 | 640x400x256 graphics |
| 101 | 640x480x256 graphics |
| 102 and 6A | 800x600x16 graphics |
| 103 | 800x600x256 graphics |
| 104 | 1024x768x16 graphics |
| 105 | 1024x768x256 graphics |
| 106 | 1280x1024x16 graphics |
| 107 | 1280x1024x256 graphics |
| 108 | 80x60 text |
| 109 | 132x25 text |
| 10A | 132x43 text |
| 10B | 132x50 text |
| 10C | 132x60 text |
| Following use direct colour memory model, see memory model discussion. All are graphics modes. 32K is 1:5:5:5 scheme, 64K is 5:6:5, 16.8M is 8:8:8 | |
| 10D | 320x200x32K |
| 10E | 320x200x64K |
| 10F | 320x200x16.8M |
| 110 | 640x480x32K |
| 111 | 640x480x64K |
| 112 | 640x480x16.8M |
| 113 | 800x600x32K |
| 114 | 800x600x64K |
| 115 | 800x600x16.8M |
| 116 | 1024x768x32K |
| 117 | 1024x768x64K |
| 118 | 1024x768x16.8M |
| 119 | 1280x1024x32K |
| 11A | 1280x1024x64K |
| 11B | 1280x1024x16.8M |
| 120 | (v2.0+) 1600x1200x256 graphics |
| 81FFh | (v2.0+) any mode which grants access to all of video memory. Setting this mode does not clear video memory. |
AX = 4F01h; ES:DI = pointer to 256 byte buffer;
CX = mode number
INT 10h
On return, all registers except AX are preserved. The format of the buffer, when it has been filled in by the function call, is as follows:
| Offset (hex) | Name | Size | Meaning |
| 00 | ModeAttributes | WORD | see below |
| 02 | WinAAttributes | BYTE | see below |
| 03 | WinBAttributes | BYTE | see below |
| 04 | WinGranularity | WORD | see below |
| 06 | WinSize | WORD | Size of each window in KB (1024 bytes) |
| 08 | WinASegment | WORD | Segment through which window A is accessed |
| 0A | WinBSegment | WORD | Segment through which window B is accessed |
| 0C | WinFuncPtr | DWORD | see below |
| 10 | BytesPerScanLine | WORD | Bytes per scan line (screen row) |
| 12 | XResolution | WORD | see below |
| 14 | YResolution | WORD | see below |
| 16 | XCharSize | BYTE | Character width in pixels |
| 17 | YCharSize | BYTE | Character height in pixels |
| 18 | NumberOfPlanes | BYTE | Number of memory planes |
| 19 | BitsPerPixel | BYTE | Total bits per pixel |
| 1A | NumberOfBanks | BYTE | see below |
| 1B | MemoryModel | BYTE | see below |
| 1C | BankSize | BYTE | Size of each bank in KB, 0 for non-banked. |
| 1D | NumberOfImagePages | BYTE | Number of video 'pages' possible less one. That is, the number of times a full screenful of data can be fit into available video memory in this mode. |
| 1E | Reserved | BYTE | Should contain the value 1. |
| The following pertain only to direct colour modes | |||
| 1F | RedMaskSize | BYTE | Number of red definition bits |
| 20 | RedFieldPosition | BYTE | LSBit of red definition in pixel memory cell |
| 21 | GreenMaskSize | BYTE | Number of green definition bits |
| 22 | GreenFieldPosition | BYTE | LSBit of green definition in pixel memory cell |
| 23 | BlueMaskSize | BYTE | Number of blue definition bits |
| 24 | BlueFieldPosition | BYTE | LSBit of blue definition in pixel memory cell |
| 25 | RsvdMaskSize | BYTE | Number of 'reserved' bits in pixel memory cell |
| 26 | RsvdFieldPosition | BYTE | LSBit number of reserved field; this was omitted from VBE 1.2 spec |
| 27 | DirectColorModeInfo | BYTE | see below |
| 28 | PhysBasePtr | DWORD | (v2.0+) Physical address of linear framebuffer |
| 2C | OffScreenMemOffset | DWORD | (v2.0+) Offset from start of frame buffer to first application usable video memory which is not normally visible. It is possible that there will be offsets between normal onscreen memory and this field value which should not be altered. |
| 30 | OffScreenMemSize | WORD | (v2.0+) Number of kilobytes of application usable offscreen memory. |
| 32 | Reserved | 206 BYTEs | Unused (0) |
| Bit number | Description |
| 0 | Set (1) if mode is available |
| 1 | Always set |
| 2 | Set if all standard BIOS drawing & text output functions are supported in this mode. |
| 3 | Set if the mode is a colour mode. Monochrome modes with 2 bits per pixel (or text modes) support high intensity and blinking characteristics in the normal fashion. Monochrome modes have the CRT controller port address at 3B4h (as opposed to colour modes at 3D4h). |
| 4 | Set if the mode is a graphics mode (clear for text mode). |
| 5 | (v2.0+) Set if the mode is "not VGA compatible" (in terms of IO ports etc) |
| 6 | (v2.0+) Set if bank-switched (window sliding) mode not supported |
| 7 | (v2.0+) Set if linear framebuffer mode supported |
| Bit number | Description |
| 0 | Set if window is supported (exists). It may be that no windows are flagged as existing; in this case the video buffer resides at the default address for the memory model or (for v2.0+) at the address specified in the Win[X]Segment field. |
| 1 | Set if window is readable |
| 2 | Set if window writable |
WinGranularity specifies the granularity, in kilobytes, of the window(s). The granularity refers to the spacing between each successive possible window start address. Quite often, this is the size of the window itself.
WinFuncPtr gives the (far) address of a callable subroutine to change the start address in video memory of a window. This is also possible through a VESA function, but using this method may be slightly faster. If this address is Null (0000:0000), the call is not supported. To call the function, BH must be set to 0 to set the window address (BL set to the window number - 0 for A, 1 for B - DX = position in units of granularity) or 1 to get the window address (BL set to window number, DX returns the address in units of granularity).
XResolution and YResolution gives the resolution of the screen mode in pixels for graphics modes or characters for text modes. The XResolution may not be the same as the logical X resolution (that is, there may be more memory allocated to one screen display line than is necessary to hold the number of pixels or characters given by X resolution). This memory amount can be found in the BytesPerScanLine field.
NumberOfBanks specifies the number of 'banks' into which the scan lines are grouped in this mode. Banking occurs mainly in the old CGA and Hercules video modes. When banking is enabled, memory representation of the screen is not contiguous - there are several banks, and each bank holds a group of scan lines. To find which bank a physical scan line belongs in, divide the line number by NumberOfBanks and take the remainder as the bank, and the quotient as the effective line number within the bank. This field is set to 1 for modes in which banking is not used.
The MemoryModel field specifies the 'memory model' of the mode, that is, the format in which visual information is stored in video memory. The following values are possible:
|
(Model numbers 8 - 15 reserved by VESA for expansion. See discussion of memory models below for further information). |
The DirectColourModeInfo gives information about direct colour modes.
| Bit number | Description |
| 0 | Set if programmable colour ramp - that is, values can be loaded into the DAC (pallette) table which all red, green and blue colour values (as stored in the pixel memory cells) will be indexed into to find the actual intensity to be used. |
| 1 | Set if the 'reserved' bits in the pixel memory cell can be used by an application for its own purposes. |
'CGA graphics' is a standard 2 or 4 colour CGA graphics mode. The colours available are the same as those available with a standard CGA mode (it is possible to select between two different pallettes in 4 colour modes, using standard CGA techniques).
| colour index | Pallette #1 | Pallette #2 |
| 1 | Cyan | Green |
| 2 | Violet | Red |
| 3 | White | Yellow |
Colour index 0, in CGA modes, refers to the selected background colour (which is one of the 16 standard colours, as per EGA/VGA/text modes). Graphic modes are packed pixel format (two sequential bits index one pixel colour), and are divided into two banks. The default memory window is at B800:0000.
'Hercules graphics' refers to a standard set by the Hercules graphics card. The format in video memory is generally 4 banks (monochrome), and the default memory window is at B000:0000.
'4-plane planar' refers to 4 bits-per-pixel modes with each bit in a corresponding 'bit plane' in memory (the bits for sequential pixels in any given plane are stored sequentially). The planes can be selected using the standard EGA/VGA methods, and it can be assumed that all read/write techniques applicable to standard planar EGA/VGA modes are valid in 4-plane planar modes. It can be safely assumed that no banking is used (though this is not specified in the standard).
'Packed Pixel' refers to modes where all the bits of an individual pixel are stored sequentially, and all pixels are stored sequentially and can be read/written directly (without planing techniques). It can be safely assumed, although it is not specified in the standard, that no banking is used. An example is the standard VGA 320x200 256 colour mode.
'Non-chain 4, 256 colour' refers to 256 colour modes which have chain-4 turned off. The result is planing techniques must be used. The first pixel index resides in the first byte of the first plane, the next in the first of the second plane, then the third plane and fourth until the fifth pixel which is stored in the second byte of the first plane, and so on. It is safe to assume no banking, 8 bits per pixel.
'Direct Colour' indicates modes in which each pixel is represented not as an index into a colour value but as a colour value (of varying precision) itself. The red, green, and blue intensities are stored as part of the pixel value - each is shifted by a certain amount and combined together (bitwise OR'd) to form a colour value, which is generally 15, 16, 24 or 32 bits in size. Each pixel is stored sequentially.
'YUV' refers to an (apparently rare) mode similar to direct mode, but which instead of red green and blue values operates on luminance (the Y value - refers to the brightness) and chrominance (U and V - affect the colour).
I believe the conversion from RGB to YUV and vice versa looks something like this:
Y = 0.299R + 0.587G + 0.114BR = Y + 1.402( V - 128 )
G = Y - 0.34414( U - 128) - 0.71414( V - 128 )
B = Y + 1.772( U - 128 )
U = 128 - 0.1687R - 0.3313G + 0.5B
V = 0.5R - 0.41876G - 0.0813B + 128
AX = 4F02h
BX = Video mode number
(bit 15 set to preserve video memory)
(v2.0+: bit 14 set to enable linear framebuffer)
On return, AX is status (004Fh if the mode was valid) and all other registers
are unchanged. Not all modes support linear framebuffer; check return of
"Get Mode Info" call. AX = 4F06h
BL = 0 (or 2 for v2.0+)
CX = desired width (in pixels if BL=0, or bytes if BL=2)
On return: AX = status (004F if ok, other value if error). BX is the bytes per scan line, CX is the number of pixels per scan line (which may be greater than requested), and DX is the maximum number of scan lines. The following is used to obtain the present logical scan line length:
AX = 4F06h
BL = 1
On return, AX = status = 004Fh, all other values as for above.Note that for text modes, the width must still be in pixels (so the number of characters must be multiplied by the width in pixels of each character).
VBE Version 2.0 also provides the following call to get the maximum possible scan line width:
AX = 4F06h
BL = 3
Which returns with BX = maximum bytes per scan line, CX = maximum pixels per
scan line. AX = 4F08h
BL = 0
BH = desired width (6 to 8)
If the desired width is not attainable, the next highest or
lowest will be selected.
On return, AX = status = 004Fh & BH = selected width.
To retrieve the current width:
AX = 4F08h
BL = 1
On return, AX = 004Fh and BH = the current width.The main complication is the multitude of different mode types and the variation within modes. The only real solution is to mould as much of the necessary information, eg sprite formats and co-ordinates, to the selected screen mode as possible - or write a program which can operate in only one (or a few selected) screen modes (this approach is pretty popular).
Things to consider when drawing are: What is the memory model? What is the windowing situation? What is the banking situation?
Depending on the task, the situations will be handled in different ways. For instance, an operation copying an image from one area of the screen to another will ideally look for both a read and write window, and might need to incorporate seperate code for a single window system, whereas a simple line drawing routine needs only a writable window.
There seems to be serious problems. Must seperate code for every envisagable situation be written? It really depends on how the far the programmer is prepared to go. In some cases, a universal piece of code may be written, even though certain cards may allow greater efficiency to be achieved. Writing code for a specific mode eliminates half the problem (especially as the screen size is then also known), but it is possible to write the various necessary low-level routines for a variety of mode styles and then use, for example, pointers to functions in order to efficiently select the correct routines.
VESA function 05h is used to position the video memory window:
AX = 4F05h
BH = 0
BL = window (0 = A, 1 = B)
DX = window position in granularity units
(VBE2.0+ 32-bit version) ES = selector for memory-mapped registers
For the 32-bit version and the "direct call" version, AX and DX may be
destroyed (they do not return status information), however the normal
implementation return is with AX = status = 004Fh, DX = window position in
granularity units, all other registers preserved.Except for the 32-bit VBE2.0+ version, this function can also be called with BH = 1 (and DX undefined) in order to find the present window position (returned in DX).
If this function is called when using a linear framebuffer mode, it will fail with return code 03h (AX = 0300h).
Note: Most implementations also include a 'fast window positioning' function (see 'Selecting a Video Mode') which can be used instead of this call.
AX = 4F09h
BL = 0 (set pallette), 1 (get pallette), 2 ("set secondary pallette date"),
3, ("get secondary pallette data"), or 80h (set pallette during
vertical retrace).
CX = number of entries to change or read
DX = starting pallette index
ES:DI = pointer to array with each entry of the form:
BYTE alignment byte
BYTE red
BYTE green
BYTE blue
AX = 4F07h
BX = 0 (or for v2.0+, 80h -> perform during vertical retrace)
CX = first displayed pixel within logical scan line
DX = first displayed logical scan line
For VBE2.0+ 32-bit version:
CX = bit 0-15 of display start address (LSW)
DX = bit 16-31 of display start address (MSW)
Returns with AX = status = 004Fh and other registers preserved. Under VBE
v2.0+ (32-bit or otherwisw), BX = 80h will perform the same function, but
will wait for vertical retrace to begin before altering the screen start
position.The "display start address" is the video memory address normally programmed into the VGA CRTC start address register. For memory models '4 plane planar' and 'non-chain 4, 256 color' this is the same as the offset you use to access the desired pixel. For packed pixel and direct colour modes, it is the offset divided by 4. For other memory models, who knows? Incidentally it is not generally possible to choose display starts with a granularity of 1 pixel with this method (so the 16-bit call may be preferable).
The current display start can be retrieved with the following (except under the 32-bit version):
AX = 4F07h
BL = 1
This returns with CX = first displayed pixel within scan line, DX = first
displayed scan line, BH = 0 (reserved) and AX = status = 004Fh.For text modes, the values are still in pixels, so the first pixel in the scan line must be found by multiplying the first character by the character width, and the first displayed scan line must be found by multiplying the first displayed text line by the character height.
Note that VESA retains full compatibility with the standard VGA BIOS. This means that the standard save/restore video state functions will save the VGA state, but not the super VGA state. It also means that any application attempting to obtain the current video mode using the standard function, while a super VGA mode is active, will be returned a 7 bit rather than 15 bit number. Generally, this number will be specific for the mode and can be used to reset the mode.
AX = 4F03hOn return, AX gives the status (004Fh) and BX returns the current VBE video mode number (a standard number if a standard mode has been set). bit 15 may be set if the last call to set the mode had bit 15 of the mode number set. v2.0+: bit 14 indicates that the linear framebuffer is active.
AX = 4F04h
DL = 0 (get buffer size) or 1 (save state) or 2 (restore state)
CX = states to save
bit 0 = 1 = Save hardware state
bit 1 = 1 = Save BIOS data
bit 2 = 1 = Save DAC
bit 3 = 1 = Save Super VGA state
(if DL <> 0:) ES:BX = Pointer to buffer
(Function DL = 0 returns with BX set to the number of 64 byte blocks needed). All functions return with AX being status and all other registers unchanged. The 'hardware' state is the registers on the video card; BIOS data is data such as current video mode, cursor positions which are stored in the BIOS data segment at 0040:0000h; DAC is the pallette table or colour ramp and Super VGA state is information specific to the VESA extension (ie, current 15 bit mode number) which cannot be stored in the BIOS data segment.The following call is made:
AX = 4F0Ah
BL = 0
On return, AX is the status (004Fh if successful), ES:DI points to a real
mode table (below) and CX contains the length of the table.
| Offset | Size | Description |
| 00h | WORD | Offset of function 05h (Set Window position) |
| 02h | WORD | Offset of function 07h (Set display start) |
| 04h | WORD | Offset of function 09h (Set primary pallette data) |
| 06h | WORD | Offset of table of ports and memory locations to which access is required, not including standard VGA ports/locations, also not including the framebuffer address. See below. May be 0 to indicate empty list. |
| 08h | ? | Code, data |
[WORD] port, port...., 0FFFFh, [DWORD] mem location start [WORD] (length - 1) .... [WORD] 0FFFFh.
There can be at most one memory location specified.
example: DE 03 DF 03 FF FF 00 E8 0D 00 00 02 FF FF
The functions are called with a 32-bit near call. On calling any of the functions, CS/DS/ES/SS should all be valid 32-bit selectors. ES or DS (depending on the function, see the function description) must be set to a selector whose base is the physical memory location given in the port/memory usage table, if any. Undefined registers apart from ESI,EBP,DS,SS are destroyed.
2150 North First Street, Suite 360
Phone: (408) 435-0333
Fax: (408) 435-8225