Previous Table of Contents Next


Appendix A
VESA VBE VGA Programming

After its PS/2 product line introduction, the IBM VGA BIOS and display controller quickly became PC graphics de facto standards. Subsequently, numerous OEM VGA products appeared, each providing IBM VGA BIOS and/or register compatibility by preserving the original VGA I/O mapped registers, CPU address space video buffer location, DAC register I/O address locations and functions, etc. For product differentiation, these products also often implemented VGA extensions, including higher screen resolutions and enhanced color support. However, OEM vendors used different hardware approaches for these extensions and exploiting these various display controller extensions proved formidable.

Typically, only after successful video board identification could software exploit specific VGA extensions. Because no standard mechanism existed to identify video boards, software developers usually resorted to arcane, oblique tests such as reading and testing registers found at unique OEM-specified I/O addresses. Because foolproof testing proved technically difficult, if not impossible, for most application developers, they often abandoned VGA extension exploitation, resorting to lowest-common-denominator VGA services. Consequently, end users purchased Super VGA display controller cards and software that exhibited no capabilities beyond standard VGA capabilities.

VESA’s VBE standard directly addresses this situation. It provides a single uniform software interface to Super VGA display controllers even when they have vastly different extension designs. Hiding these hardware differences allows software to exploit varying VGA extensions using a well-defined, single, uniform approach. Meanwhile, for OEM vendors, the VBE preserves maximum standard VGA compatibility and minimizes existing VGA BIOS changes and allows RAM as well as ROM-based implementations.

Specifically, the VBE addresses:

Video Board Inquiries

VBE functions return system level information as well as specific video mode details.

Video Hardware Initialization and Programming

VBE provides several functions to exploit varying Super VGA hardware implementations.

Finally, VBE is fully upwards compatible so specific VBE version features are guaranteed to work in future versions. Hence, VBE provides a much needed stable video application programming interface (API).

Frame Buffer Granule (Bank) Switching

Standard VGA video boards provide up to 256 KBytes of frame buffer memory and well-defined frame buffer access mechanisms. Several VBE modes require additional memory but compatibility necessarily restricts frame buffer memory CPU visibility to the standard VGA address range. Frame buffer bank switching provides a mechanism for CPUs to access extended frame buffer memory within standard VGA address space range constraints.

Specifically, software invokes VBE frame buffer bank switching functions to swap (map) video memory granules into the narrow VGA address range for frame buffer memory read and write operations. Software determines the precise way to accomplish this by examining the information VBE Function 0x01 (Return Super VGA Mode Information) returns. Readers not wanting to understand the precise mechanics should note the sample programs contain functions that accomplish this manipulation.

Frame Buffer CPU Visibility Considerations

The standard CPU memory address range typically allotted to VGA display cards is 64 or 128 Kbytes, beginning at CPU memory segment 0xA000. This designated area, reserved for software VGA adapter frame buffer access operations, is referred to as the CPU video memory window. Mapping VGA frame buffer memory portions into the standard CPU video memory window using standard VGA program calls gives access to the entire standard VGA’s frame buffer memory which can be up to 256 KBytes in size.

Standard VGA BIOS functions allow software to specify the frame buffer memory address range to appear in the CPU address space range for subsequent software memory read and write activities. The trick then is to swap (map) a given scan line into the CPU address space subject to display adapter hardware constraints so software can read/write all or part of the scan line as necessary. A VBE display adapter achieves this by dividing up frame buffer memory into fixed size granules. A granule contains multiple display adapter scan lines and, depending on the CPU video memory window size, a window may display more than one granule.

Different VBE display adapters may have different-sized granules, but a given adapter has only one size referred to as the window mapping function granularity. Some adapters have 4 KByte granules while others have up to 64 KByte granules. The essential concept is that VBE Function 0x05, CPU Video Memory Window Control, makes desired frame buffer memory granules appear in the CPU’s 64 or 128 KByte VGA adapter address range under software control. This book’s sample programs only access one scan line at a time, greatly simplifying the code in exchange for performance penalties. Unfortunately, in some instances, scan lines may span two adjacent granules, requiring software bounds testing for proper scan-line access in those situations where only a scan-line portion is visible in the CPU video memory window.

Window A and Window B

VBE allows adapters to divide the CPU video memory into two separate windows referred to as Window A and Window B. When a display adapter supports two VBE windows, this guarantees two different granules can simultaneously appear within the CPU’s video memory window. VBE Function 0x01 (Return Super VGA Mode Information) returns indicators for each window’s CPU video memory window starting address and whether CPU software can read or write to each window.

When CPU software can only read one VBE window and write to the other, the software can copy from one window into another without repeated VBE Function 0x05 (CPU Video Memory Window Control) calls. In such instances, software repetitively reads scan-line data from one granule in one VBE window and writes scan-line data into the other VBE window’s granule. Otherwise, software would swap in the read granule, read data from it into main memory, swap in the write granule, and copy the data from main memory. This constant swapping and double data movement imposes significant performance penalties.

Finally, both VBE windows always appear in different CPU video memory window areas because each VBE window has its own starting memory segment address. When software swaps a granule into a window, video controller hardware aligns the granule’s first byte at the window’s starting segment address.

Hardware Window Type Summary

Independent of granule size differences, VBE supports three basic hardware windowing implementation types:

VBE Function 0x05 (CPU Video Memory Window Control) provides the information necessary for applications to detect the specific hardware implementation type an adapter provides and the read/write characteristics of each VBE window in dual window systems.

Super VGA Mode Number Overview

Standard VGA mode numbers reserve seven bit positions and range in value from 0x00 to 0x13. OEMs extend video mode range values from 0x14 to 0x7F. Because the standard VGA BIOS Function 0x00 (Set Video Mode) interprets bit 7 as a clear/don’t clear video memory flag, values ranging from 0x80 to 0xFF are not available to VBE. Therefore, VBE video mode numbers are 15 bits wide, beginning at 0x0100.

This mode numbering scheme incorporates standard VGA mode numbers and OEM-defined mode numbers as VESA mode-number subsets, allowing programs to initialize regular VGA modes using VBE Function 0x02 (Set Super VGA mode).

VESA Mode Number Format

Bit Range Meaning Comment
D8-D0 VBE Mode Indicator and Mode Value D8 == 1 indicates this is a VESA defined mode
D8 == 0 indicates this is not a VBE defined mode
D15  D14  D13  D12  D11  D10  D9  D8   D7  D6  D5  D4  D3  D2  D1  D0
 X   X    X   X    X    X    X   X . X   X  X   X   X   X  X   X
D15-D9 Reserved Reserved

where D0 is the low-order bit and D15 is the high-order bit as illustrated:

VESA 256-Color Packed Pixel Mode Numbers

VBE defines the following packed pixel modes that allow 256 maximum on-screen colors:

VBE Packed Pixel Mode Number Resolution (Cols x Rows)
0x100 640x400
0x101 640x480
0x103 800x600
0x105 1024x768
0x107 1280x1024

VESA Direct Color Mode Numbers

VBE supports five direct color screen resolutions:

VBE defines three pixel bit assignments for each of the five resolutions, for a total of 15 different modes. This allows each resolution to potentially provide the following different numbers of simultaneous colors:

Display adapters must have enough memory to support the given modes. The pixel bit assignments for each of the three VBE defined direct color modes are:

Total # Colors # Rsvd Bits # Red Bits # Green Bits # Blue Bits Bit Assgt. Notation Total Color Bits Comment
32K 1 5 5 5 (1:5:5:5) 15 15-bit color
64K 0 5 6 5 (5:6:5) 16 16-bit color
16M 0 8 8 8 (8:8:8) 24 24-bit color

The following table specifies the 15 VBE direct color modes and their resolutions and bit assignments:

VBE Direct Color Mode Number Resolution (Cols x Rows) Bit Assignment Number of Colors
0x10D 320x200 (1:5:5:5) 32K
0x10E 320x200 (5:6:5) 64K
0x10F 320x200 (8:8:8) 16.8M
0x110 640x480 (1:5:5:5) 32K
0x111 640x480 (5:6:5) 64K
0x112 640x480 (8:8:8) 16.8M
0x113 800x600 (1:5:5:5) 32K
0x114 800x600 (5:6:5) 64K
0x115 800x600 (8:8:8) 16.8M
0x116 1024x768 (1:5:5:5) 32K
0x117 1024x768 (5:6:5) 64K
0x118 1024x768 (8:8:8) 16.8M
0x119 1280x1024 (1:5:5:5) 32K
0x11A 1280x1024 (5:6:5) 64K
0x11B 1280x1024 (8:8:8) 16.8M

Finally, VBE provides a very flexible way for software to determine other direct color operating modes by using the RedMaskSize, RedFieldPosition, GreenMaskSize, GreenFieldPosition, BlueMaskSize, and BlueFieldPosition values VBE Function 0x01 (Return Super VGA Mode Information) returns.

Extended VGA BIOS Calls

VBE defines several new video function calls. For maximum standard VGA BIOS compatibility, these calls are grouped under one function number. The AH register passes this number, 0x4F, to the video int 10h handler. Standard VGA BIOSs do not recognize this value and ignore these calls.

1. VBE Function Return Status Information

The AX register returns status information for every VBE function call. The status word format follows:

Register Value Value Meaning
AH == 0x00 Function call successful
AH == 0x01 Function call failed
AL == 0x4F VBE function is supported
AL != 0x4F VBE function is not supported

Treat non-zero AH register values as general failure conditions, rather than testing for the specific 0x01 value.

2. VBE Function 0x00—Return Super VGA Information

This function returns Super VGA capability information by completing a 256-byte structure located at a caller specified address.

Input:

Register Value Comment
AH 0x4F VBE request indicator
AL 0x00 Return Super VGA information
ES:DI ES:DI Pointer to information structure

Output: AX: VBE status value
Comment: Preserves all other registers

The information structure follows:

#define USGI unsigned int
#define USGC unsigned char
#define USGL unsigned long

struct VesaInfoBlock
    {
        USGC  VesaSignature[4]; /* 'VESA'  */
        USGI  VesaVersion;      /* e.g. 0x0102 == 1.2    */
        char far *OemStringPtr; /* who dat?   */
        USGC  Capabilities[4];
        USGI far *VideoModePtr;
        USGI  Total64kMemoryBlocks;
        char  Reserved[256];    /* more than enough space */
    };

After successful completion:

VESASignature contains the characters “V,” “E,” “S,” and “A” for valid blocks.

VESAVersion specifies the VBE support level provided. The high-order byte specifies the major version number, and the low-order byte specifies the minor version number. Thus a 0x0102 value specifies VBE version 1.2.

OEMStringPtr is a far pointer to a null-terminated OEM-provided string. The string may identify the video chip, video board, memory configuration, etc. The string’s format has no restrictions.

Capabilities describes what features the video adapter supports. The bit definition follows:

Bit Position Meaning Comment
D0 Is DAC switchable? D0 == 1 indicates the DAC width is switchable
D0 == 0 indicates the DAC width is fixed to 6 bits per primary colorx
D31-D1 Reserved Reserved

VideoModePtr points to a Super VGA (VESA-defined and OEM-specific) supported mode list placed within ROM or RAM. A –1 (0xFFFF) terminates the mode number list and each enumerated mode number occupies one word (16 bits). Either the list is a static ROM string, or the list is generated and placed at run time in the RAM information block (see above). Software must verify the display adapter supports given modes using VBE Function 0x01 Return Super VGA Mode Information. Some enumerated modes may not be available because of video board frame buffer memory limitations and monitor characteristics.

TotalMemory returns the display adapter frame buffer size expressed in 64 KByte blocks. Multiplying this value by 65,536 yields the frame buffer size in bytes.

3. VBE Function 0x01—Return Super VGA Mode Information

This function returns information about specific Super VGA video modes, including OEM-unique, non-VESA video modes, returned by VBE Function 0x00 (Return Super VGA Information). This function returns information by completing a 256-byte maximum-size mode information structure located at a caller-specified address. To provide mode access, this function also returns additional mode information. Finally, pre-initialize the 256-byte buffer to zero before invoking Return Super VGA Mode Information.

Input:

Register Value Comment
AH 0x4F VBE request indicator
AL 0x01 Return Super VGA mode information
CX Mode Value Must be returned by VBE Function 0x00
ES:DI ES:DI Pointer to 256-byte structure

Output: AX: VBE status value
Comment: Preserves all other registers

The mode information block has the following structure:

#define USGI unsigned int
#define USGC unsigned char
#define USGL unsigned long

struct VesaModeInfoBlock
    {
        USGI ModeAttributes;
        USGC WinAAttributes;
        USGC WinBAttributes;
        USGI WinGranularity;
        USGI WinSize;
        USGI WinASegment;
        USGI WinBSegment;
        void ((far *WinFuncPtr)());
        USGI BytesPerScanLine;
        USGI XResolution;
        USGI YResolution;
        USGC XCharSize;
        USGC YCharSize;
        USGC NumberOfPlanes;
        USGC BitsPerPixel;
        USGC NumberOfBanks;
        USGC MemoryModel;
        USGC BankSize;
        USGC NumberOfImagePages;
        USGC ReservedForPageFunction;
        USGC RedMaskSize;
        USGC RedFieldPosition;
        USGC GreenMaskSize;
        USGC GreenFieldPosition;
        USGC BlueMaskSize;
        USGC BlueFieldPosition;
        USGC RsvdMaskSize;
        USGC RsvdFieldPosition;
        USGC DirectColorModeInfo;

        char Reserved[256]; /* more than enough space */
    };

ModeAttributes describes important video mode characteristics:

Bit Position Meaning Values Comment
D0 Mode available in present video configuration? 0= Mode not supported
1=Mode supported
Blocks video mode access when required hardware is not available (frame buffer memory, monitor types, etc.)
D1 Reserved. Must be set to 1. Must be set to 1.
D2 BIOS output functions availability indicator (TTY output, screen scroll, pixel output). 0= Output functions not supported
1=Output functions supported
If D2 is 1 then the BIOS supports all standard output functions in this mode
D3 Monochrome or color mode? 0= Monochrome mode
1=Color mode
 
D4 Mode type? 0= Text mode
1=Graphics mode
 
D15-D5 Reserved Reserved Reserved

WinAAttributes and WinBAttributes describe the CPU windowing scheme characteristics, indicating whether windows exist and whether they are individually readable and writeable. The field format for both window A and window B follows:

Bit Position Meaning Values Comment
D0 Window supported? 0= Window not supported
1=Window is supported
Indicates whether a window (A or B) is available.
D1 Window readable? 0= Window not readable
1=Window is readable
Indicates whether a window (A or B) is readable.
D2 Window writeable? 0= Window not writeable
1=Window is writable
Indicates whether a window (A or B) is writeable.
D7-D3 Reserved Reserved Reserved

If bit D0 = 0 for both Window A and Window B (windowing not supported), assume the frame buffer memory completely resides at the standard CPU address appropriate for the mode’s MemoryModel.

WinGranularity specifies the smallest boundary, in KBytes, on which the window can align in video memory. The field’s value is undefined when the appropriate WinAttributes field bit D0 has a zero value.

WinSize specifies the window size in KBytes.

WinASegment and WinBSegment specify CPU memory segment address window origins. When swapped in, granules align on these memory segment addresses.

WinFuncPtr specifies the CPU’s video memory windowing function address. VBE Function 0x05 (CPU Video Memory Window Control) or direct function calls can invoke windowing support. Direct calls provide faster hardware paging register access than VBE function 0x05, and are intended for high performance application use. When this field has a zero value (Null), use VBE Function 0x05 to set the memory window when paging is supported.

BytesPerScanline specifies the logical scan-line length in bytes. The logical scan line’s length is equal to or larger than the displayed scan line. When the logical scan line is longer than the display’s scan line, software can use VBE Function 0x07 (Set/Get Display Start) to pan left and right smoothly.

XResolution and YResolution specify video graphics mode width and height in pixels per visible scan line and total visible scan lines, respectively.

XCharCellSize and YCharCellSize specify character cell dimensions in pixels.

NumberOfPlanes specifies the number of available memory planes for the mode. For standard packed pixel and direct color modes, this is 1.

BitsPerPixel specifies the total number of bits defining one pixel. For example, packed pixel 256-color graphics mode specifies 8.

NumberOfBanks indicates the number of banks holding scan-line groups. When dividing a screen scan-line number by NumberOfBanks, the remainder is the bank number containing the screen scan line and the quotient is the scan-line number within the bank. For modes that don’t have scan-line banks, this field should contain one.

MemoryModel specifies the mode’s memory organization. MemoryModel values follow:

Value Value Meaning
0x00 Text mode
0x01 CGA graphics
0x02 Hercules graphics
0x03 4-plane planar
0x04 Packed pixel
0x05 Non-chain 4, 256 color
0x06 Direct Color
0x07 YUV
0x08-0x0F VESA reserved
0x10-0xFF OEM defined

Direct color modes should use the ModeInfoBlock MaskSize and FieldPosition fields to describe pixel formats. BitsPerPixelis always defined to be the total pixel memory size expressed in bits.

BankSize specifies the bank size in 1 KByte units. For modes that don’t have scan-line banks, this field should contain zero.

NumberOfImagePages specifies the number of complete display images that simultaneously fit into the VGA’s memory in this mode. The application may load more than one image into the VGA’s memory if this field is non-zero, and rapidly flip the display between them.

Reserved supports future VBE extension features and always contains one in VBE 1.2.

RedMaskSize, GreenMaskSize, BlueMaskSize, and RsvdMaskSize (collectively referred to as MaskSize) define direct color pixel red, green, blue, and reserved component sizes in bits. Simple shift arithmetic using MaskSize field information provides pixel bit masks. MaskSize values for direct color (5:6:5) modes are 5, 6, 5, and 0, for the red, green, blue, and reserved fields, respectively. When MemoryModel contains the YUV value, the Y field uses the green value, the U field uses the blue value, and the V field uses the red value. The MaskSize field values are 0 for MemoryModel modes not having component field pixels.

RedFieldPosition , GreenFieldPosition, BlueFieldPosition , and RsvdFieldPosition (collectively referred to as FieldPosition) define respective color component least-significant-bit positions within direct color or YUV pixels. Color values are properly aligned with pixels by shifting component values left by component FieldPosition values. FieldPosition values for Direct Color (5:6:5) modes would be 11, 5, 0, and 0, for the red, green, blue, and reserved fields, respectively. When MemoryModel contains the YUV value, the Y field uses the green value, the U field uses the blue value, and the V field uses the red value. The FieldPosition field values are 0 for MemoryModel modes not having component field pixels.

DirectColorModeInfo describes direct color (not packed pixel) mode characteristics. Bit D0 specifies whether the DAC color ramp is fixed or programmable. If the color ramp is fixed, then it cannot be changed. If the color ramp is programmable, standard VGA DAC color registers BIOS call (AX=0x1012) loads red, green, and blue look-up tables. Bit D1 specifies whether applications can use direct color pixel Rsvd field bits or whether they are reserved, hence unusable.

Bit Position Meaning Values
D0 Fixed color ramp? 0 == Color ramp is fixed
Color ramp is programmable
D1 Rsvd field bits usable? 0= Rsvd field bits not usable
1=Bits in Rsvd field usable
D7-D2 Reserved Reserved

4. VBE Function 0x02—Set Super VGA Video Mode

This function initializes the video mode the BX register specifies. If the video BIOS cannot set the mode, the video BIOS leaves the video environment unchanged, returning a failure error code.

Input:

Register Value Comment
AH 0x4F VBE request indicator
AL 0x02 Set Super VGA video mode

BX
Mode Value
D0-D14=VBE Video mode
D15=Clear memory flag
Only modes returned by VBE Function 0x00.
If D15==0, frame buffer is cleared to zeros.
If D15==1, frame buffer is not cleared.

Output: AX: VBE status value
Comment: Preserves all other registers

5. VBE Function 0x03—Return Current Video Mode

This function returns the current video mode in BX.

Input:

Register Value Comment
AH 0x4F VBE request indicator
AL 0x03 Return current video mode

Output: AX: VBE Status Value
BX: Current video mode
Comment: Preserves all other register

6. VBE Function 0x04—Save/Restore Super VGA Video State

These functions save and restore Super VGA video states and are a super-set of three standard VGA BIOS Function 0x1C (Save/Restore Video State) subfunctions. All Super VGA video states (except video memory) should be saveable/restorable by setting the requested state’s mask (in the CX register) to 0x000F. Software:

Save State(s) Buffer Requirement Determination Input:

Register Value Comment
AH 0x4F VBE request indicator
AL 0x04 Save/Restore Super VGA Video state request
DL 0x00 Return Save/Restore state buffer size
CX Requested State(s) Save Buffer Size D0= Save video hardware state
D1= Save/Restore video BIOS data state
D2= Save/Restore video DAC state
D3= Save/Restore Super VGA state

Output: AX: VBE status value
BX: Number of 64-byte blocks to hold the state buffer
Comment: Preserves all other registers

Save State Input:

Register Value Comment
AH 0x4F VBE request indicator
AL 0x04 Save/Restore Super VGA Video state(s)
DL 0x01 Save state(s)
CX Requested State(s) To Save D0= Save video hardware state
D1= Save video BIOS data state
D2= Save video DAC state
D3= Save Super VGA state
ES:BX Buffer Pointer  

Output: AX: VBE status value
Comment: Preserves all other registers

Restore State Input:

Register Value Comment
AH 0x4F VBE request indicator
AL 0x04 Save/Restore Super VGA Video state(s)
DL 0x02 Restore state(s)
CX Requested State(s) to Restore D0= Restore video hardware state
D1= Restore video BIOS data state
D2= Restore video DAC state
D3= Restore Super VGA state
ES:BX Buffer Pointer  
Output: AX: VBE status value
Comment: Preserves all other registers

7. VBE Function 0x05—CPU Video Memory Window Control

This function allows direct access to the hardware paging register and sets or gets the specified window position in video memory. VBE Function 0x01 (Return Super VGA Mode Information) provides window size, location, and granularity information essential to use this function properly.

For improved performance, software can access this function directly using far calls to the ModeInfoBlock WinFuncPtr address VBE Function 0x01 (Return Super VGA Mode Information) returns. When using far calls:

Select Window Input:

Register Value Comment
AH 0x4F VBE request indicator
AL 0x05 Super VGA video memory window control
BH 0x00 Select super VGA video memory window
BL Window Number 0= Window A
1= Window B
DX Video Memory Window Position Specified in window granularity units

Output: AX: VBE status value
DX: Window position in video memory (in window granularity units)
Comment: Preserves all other registers

Return Window Input:

Register Value Comment
AH 0x4F VBE request indicator
AL 0x05 Super VGA video memory window control
BH 0x01 Return super VGA video memory window
BL Window Number 0= Window A
1= Window B
DX Video Memory Window Position Specified in window granularity units

Output: AX: VBE status value
DX: Window position in video memory (in window granularity units)
Comment: Preserves all other registers

8. VBE Function 0x06—Set/Get Logical Scan-Line Length

This function sets or gets the current logical scan-line length. Setting a logical video memory buffer wider than the display scan-line length allows applications to smoothly pan horizontally and possibly vertically using VBE Function 0x07 (Set/Get Display Start) which allows applications to set the starting display position at and within logical scan lines.

Set Scan Line Length Input:

Register Value Comment
AH 0x4F VBE request indicator
AL 0x06 Logical scan-line length
BL 0x00 Set scan-line length
CX Desired Length Expressed in pixels

Output: AX: VBE status value
BX: Bytes per scan line
CX: Actual pixels per scan line
DX: Maximum number of scan lines
Comment: Preserves all other registers

Return Scan-Line Length Input:

Register Value Comment
AH 0x4 FVBE request indicator
AL 0x06 Logical scan-line length
BL 0x01 Return scan-line length
Output: AX: VBE status value
BX: Bytes per scan line
CX: Actual pixels per scan line
DX: Maximum number of scan lines
Comment: Preserves all other registers

When VGA hardware considerations preclude setting a requested scan-line length, the next larger scan-line length that accommodates the desired scan-line length is provided, and:

Software can use VBE function 0x07 (Set/Get Display Start) to smoothly pan vertically within these available scan lines.

9. VBE Function 0x07—Set/Get Display Start

This function selects the pixel from the current logical page the display presents in its upper left corner. This function allows applications to pan and scroll around logical screens larger than the display screen resolution. This function allows rapid switching between different frame buffer areas for double-buffered animation effects.

Select Display Start Input:

Register Value Comment
AH 0x4F VBE request indicator
AL 0x07 Super VGA video memory window control
BH 0x00 Reserved and must be 0
BL 0x00 Select Display Start
CX Pixel Number First displayed frame buffer scan-line pixel
DX Scan Line Number First displayed frame buffer scan line

Output: AX: VBE status value
DX: Window position in video memory (in window granularity units)
Comment: Preserves all other registers

Return Display Start Input:

AH 0x4 FVBE request indicator
AL 0x07 Super VGA video memory window control
BL 0x01 Return Display Start
CX Pixel Number First displayed frame buffer scan-line pixel
DX Scan Line Number First displayed frame buffer scan line

Output: AX: VBE status value
BH: 0x00 reserved and will be 0
CX: First displayed pixel in scan line
DX: First displayed scan line
Comment: Preserves all other registers

10. VBE Function 0x08—Set/Get DAC Palette Control

This function queries and selects the DAC width. The DAC palette width is always the standard VGA 6 bits per primary color after standard VGA or VBE Function 0x02 (Set Super VGA Mode) calls. Some DACs provide 6 bits, 8 bits, or more for primary colors.

Set DAC Width Input:

Register Value Comment
AH 0x4 FVBE request indicator
AL 0x08 Set/Get DAC palette control
BL 0x00 Set DAC palette width
BH DAC Width Desired number of bits per primary color (Standard VGA = 6)

Output: AX: VBE status value
BH: Current number of bits per primary color (Standard VGA = 6)
Comment: Preserves all other registers

Get DAC Width Input:

Register Value Comment
AH 0x4F VBE request indicator
AL 0x08 Set/Get DAC palette control
BL 0x01 Get DAC palette width

Output: AX: VBE status value
BH: Current number of bits per primary color (Standard VGA = 6)
Comment: Preserves all other registers

Applications can determine DAC width switching capability by querying the Capabilities field’s bit D0 in the VgaInfoBlock structure VBE Function 0x00 (Return Super VGA Information) returns. If DAC switching is supported, the application can then attempt to set the DAC palette width to a desired value. If the DAC cannot support the requested width, the next lower value the DAC supports is selected. BH returns the resulting palette width.

Sample VBE Application

The VESAEXAM.C program provides the logic necessary to query for, and determine the extent of, VBE support. Appendix D lists the VESA.H and PCX.H headers.

 /* 
               Copyright (C) 1995, W. David Schwaderer
Some rights reserved - see WdsLogo() for details
   Function: This program interrogates and documents VESA capabilities
             for a single user-specified video mode or all available
             video modes. Redirect the output to a file for hard copy.
             See the text description in:

              Digital Imaging in C and the World Wide Web
                         W. David Schwaderer
                     Wordware Publishing, Inc., 1997

   Compiler: Borland C++ 3.1

   Compile command: bcc -ml VesaExam.C

   Call to programmers...

     If you are interested enough to read this code, your name
     probably should be in it. I will place contributing programmer's
     names in source code when their suggestion(s) results in bug fixes
     or program enhancements. Contributions must be new. Send written
     suggestions on paper to W. David Schwaderer via Wordware Publishing,
     Inc.

     Complete or massive rewrites are not helpful (though possibly
     warranted!). Contributions become the property of W. David
     Schwaderer who reserves suggestion final disposition determination.

     Thanks in advance for the consideration.
                                             W. David Schwaderer

   Version 1.0 3/15/93
       Contributor                         Enhancement
   --------------------------------
----------------------------------------------------------
   Your name here...            Your edited suggestion here...
   Hometown, country            Your edited suggestion here...

*/

#include <mem.h>
#include <dos.h>
#include <stdio.h>
#include <stdlib.h>

#define USGI unsigned int
#define USGC unsigned char
#define USGL unsigned long
#include "vesa.h"

int main(int argc, char *argv[]);
int WdsLogo(void);
int VesaNotPresent(void);
int DisplayVesaInfo(void);
int FillVesaModeBlock(struct VesaModeInfoBlock *VesaModeInfoBlockPtr,
                                         USGI  ModeNumber);
int DisplayVesaModeAttributes(USGI VesaModeAttributes);
int DisplayVesaWindowAttributes(USGC VesaWindowAttributes);
int DisplayVesaModeInfo(USGI ModeNumber, USGI VesaModesOnlyFlag);
int ExitLogo(void);

struct VesaInfoBlock VesaInfo;

USGI   ModeValue;

int main(int argc, char *argv[])
{

    if(VesaNotPresent())
    {

        printf("\nmain: VESA support not detected, exiting...");
        ExitLogo();

    }

    printf("\nmain: VESA support detected...");

    if (argc > 1)
         sscanf(argv[1], "%x", &ModeValue);

    DisplayVesaInfo();

    WdsLogo();

    printf("\nmain: Returning...\n");

    return 0;

}

int WdsLogo(void)

{

    printf("\n");
    printf("\nCopyright (C) 1993 W. David Schwaderer, some rights reserved");
    printf("\nThis program uses source code from W. David Schwaderer's");
    printf("\n       'Digital Imaging in C and the World Wide Web");
    printf("\n            Wordware Publishing, Inc., 1997");
    printf("\nW. David Schwaderer grants an unrestricted executable
                           program");
    printf("\nuse-license for unmodified executable programs he releases.");
    printf("\nNon-commercial source code use-licenses are also granted to:");
    printf("\n - individuals for their non-commercial private use (enjoy!)");
    printf("\n - educational institutions for teaching materials  (learn!)");
    printf("\nprovided the WdsLogo() function is compiled (execution not");
    printf("\nrequired) without modification into derived executable");
    printf("\nmodules. Other source code uses, including 'shareware',");
    printf("\nare encouraged but strictly prohibited without W. David");
    printf("\nSchwaderer's explicit written permission, easily obtained");
    printf("\nwith appropriate book credit. Please contact David via");
    printf("\Wordware Publishing, Inc. for written permission requests.");
    printf("\nDeepest thanks for your cooperation.");
    printf("\n                                       W. David Schwaderer");
    printf("\n");

    return 0;

}

int VesaNotPresent()
{

    struct SREGS SegReg;
    union   REGS OutReg, InReg;

    InReg.h.ah  = VESA_FUNCTION;
    InReg.h.al = VESA_RETURN_INFO;

    SegReg.es   = FP_SEG(&VesaInfo);
    InReg.x.di = FP_OFF(&VesaInfo);

    int86x(VIDEO_INT, &InReg, &OutReg, &SegReg);

    if(OutReg.h.ah != VESA_CALL_SUCCESSFUL)
        return 1;

    if(OutReg.h.al != VESA_FUNCTION_SUPPORTED)
    {

        printf("\nVesaNotPresent: VESA Presence test not supported");
        return 1;

    }

    return 0;

}

int DisplayVesaInfo()
{

    USGI far *FarIntPtr,  *NearIntPtr,  Index1, Index2, Mask;
    char far *FarCharPtr, *NearCharPtr, LocalOemString[256];

         /*------------------- signature ------------------*/

    printf("\n\nDisplayVesaInfo: VesaSignature (hex) ==>");

    for (Index1 = 0;
         Index1 < sizeof(VesaInfo.VesaSignature);
         Index1++)
    {
         printf("%02X", VesaInfo.VesaSignature[Index1]);
         if (Index1 < (sizeof(VesaInfo.VesaSignature) - 1))
             putchar('.');

    }

    printf("<==  ('");

    for (Index1 = 0;
         Index1 < sizeof(VesaInfo.VesaSignature);
         Index1++)
            printf("%c", VesaInfo.VesaSignature[Index1]);

    printf("')");

           /*------------------- version -------------------*/

    printf("\nDisplayVesaInfo: VesaVersion == VBE %u.%u",
            ((VesaInfo.VesaVersion >> 8) & 0x00FF),
             (VesaInfo.VesaVersion)      & 0x00FF);

         /*------------------- OEM string -------------------*/

    printf("\nDisplayVesaInfo: OemString ==>");

    FarCharPtr = VesaInfo.OemStringPtr;

    while(*FarCharPtr)
        putchar(*FarCharPtr++);

    printf("<==");

         /*----------------- capabilities -----------------*/

    printf("\nDisplayVesaInfo: Capabilities ==>");

    for (Index1 = 0;
         Index1 < sizeof(VesaInfo.Capabilities);
         Index1++)

   {

       for ( Index2 = 0, Mask = 0x0080;
             Index2 < 8;
             Index2++,   Mask >>= 1)
           if (VesaInfo.Capabilities[Index1] & Mask)
               putchar('1');
           else
               putchar('0');

       if (Index1 != 3)
           putchar('.');
   }
    printf("<==");
    printf("\n                     - %s DAC width...",
             (VesaInfo.Capabilities[3] & VESA_DAC_WIDTH_TEST_BIT) ?
             "Switchable" : "Fixed (6 bits/primary color)");

         /*------------------- total memory -------------------*/

    printf("\nDisplayVesaInfo: Total64kMemoryBlocks == %u (%uKb total)...",
                       VesaInfo.Total64kMemoryBlocks,
                       VesaInfo.Total64kMemoryBlocks * 64);

         /*------------------- video modes -------------------*/

    FarIntPtr = VesaInfo.VideoModePtr;

    if (!ModeValue)
    {

        while(*FarIntPtr != 0xFFFF)
        {

            if (*FarIntPtr & VESA_VIDEO_MODE_TEST_BIT)
                DisplayVesaModeInfo(*FarIntPtr, !VESA_MODES_ONLY);

            FarIntPtr++;

        }
    } else
        DisplayVesaModeInfo(ModeValue, !VESA_MODES_ONLY);

    return 0;
}

int FillVesaModeBlock(struct VesaModeInfoBlock *VesaModeInfoBlockPtr,
                                         USGI  ModeNumber)

{

    struct SREGS SegReg;
    union   REGS OutReg, InReg;

    InReg.h.ah  = VESA_FUNCTION;
    InReg.h.al = VESA_RETURN_MODE_INFO;

    InReg.x.cx = ModeNumber;

    SegReg.es   = FP_SEG(VesaModeInfoBlockPtr);
    InReg.x.di = FP_OFF(VesaModeInfoBlockPtr);

    int86x(VIDEO_INT, &InReg, &OutReg, &SegReg);

    if(OutReg.h.ah != VESA_CALL_SUCCESSFUL)
        return 0;

    if(OutReg.h.al != VESA_FUNCTION_SUPPORTED)
    {
        printf("\n\nFillVesaModeBlock: VESA mode info request not
                             supported");
        return 0;

    }

    return 1;

}

int DisplayVesaModeAttributes(USGI VesaModeAttributes)
{

    printf("\n                   -Your hardware does%s support it...",
        (VesaModeAttributes & VESA_MODE_AVAILABLE_TEST_BIT) ?
                                       "" : "n't");

    if (!(VesaModeAttributes & VESA_MODE_AVAILABLE_TEST_BIT))
        return 0;

    printf("\n                   -Extended mode info is%s available...",
        (VesaModeAttributes & VESA_MODE_EXTENDED_INFO_AVAIL_TEST_BIT) ?
                                       "" : "n't");

    printf("\n                   -BIOS output functions are%s supported...",
        (VesaModeAttributes & VESA_MODE_OUTPUT_FUN_TEST_BIT) ?
                                       "" : "n't");

    printf("\n                   -%s mode...",
        (VesaModeAttributes & VESA_MODE_MONO_COLOR_TEST_BIT) ?
                                       "Color" : "Monochrome");

    printf("\n                   -%s mode type...",
        (VesaModeAttributes & VESA_MODE_MONO_TYPE_TEST_BIT) ?
                                       "Graphics" : "Text");

    return 0;

}

int DisplayVesaWindowAttributes(USGC VesaWindowAttributes)
{

    printf("\n                   - Window is%s supported...",
        (VesaWindowAttributes & VESA_WINDOW_SUPPORTED_TEST_BIT) ?
                                       "" : "n't");

    if (!(VesaWindowAttributes & VESA_WINDOW_SUPPORTED_TEST_BIT))
        return 0;

    printf("\n                   - Window is%s readable...",
        (VesaWindowAttributes & VESA_WINDOW_READABLE_TEST_BIT) ?
                                       "" : "n't");

    printf("\n                   - Window is%s writable...",
        (VesaWindowAttributes & VESA_WINDOW_WRITABLE_TEST_BIT) ?
                                       "" : "n't");

    return 1;

}

int DisplayVesaModeInfo(USGI ModeNumber, USGI VesaModesOnlyFlag)
{

    struct VesaModeInfoBlock VesaModeInfo;

    memset(&VesaModeInfo, '\x00', sizeof(VesaModeInfo));

    if (VesaModesOnlyFlag)

    {

        if (!(ModeNumber & VESA_VIDEO_MODE_TEST_BIT))

        {

            printf("\nDisplayVesaModeInfo: Mode %04X is not a VESA mode...",
                                            ModeNumber);

            return 1;

        }

    }

    FillVesaModeBlock(&VesaModeInfo, ModeNumber);

    printf("\n\nDisplayVesaModeInfo: *---------- Mode == 0x%04X ----------*",
                                                  ModeNumber);

    DisplayVesaModeAttributes(VesaModeInfo.ModeAttributes);

    printf("\nDisplayVesaModeInfo: Bytes per scan line == %u",
                                         VesaModeInfo.BytesPerScanLine);

           /*------------------ general window information ------------------*/

    printf("\nDisplayVesaModeInfo: Window Size == %uKb, Granularity == %uKb",
                                            VesaModeInfo.WinSize,
                                            VesaModeInfo.WinGranularity);

    printf("\nDisplayVesaModeInfo: Window function pointer == %04X:%04X",
                                            FP_SEG(VesaModeInfo.WinFuncPtr),
                                            FP_OFF(VesaModeInfo.WinFuncPtr));

                  /*----------------- window A -----------------*/

    printf("\nDisplayVesaModeInfo: Window A segment == 0x%04X",
                                             VesaModeInfo.WinASegment);

    DisplayVesaWindowAttributes(VesaModeInfo.WinAAttributes);

                 /*------------------ window B -----------------*/

    printf("\nDisplayVesaModeInfo: Window B segment == 0x%04X",
                                             VesaModeInfo.WinBSegment);

    DisplayVesaWindowAttributes(VesaModeInfo.WinBAttributes);

    /*------------------- extended mode information (preVBE 1.2) ------------------*/

    if (!(VesaModeInfo.ModeAttributes &
          VESA_MODE_EXTENDED_INFO_AVAIL_TEST_BIT))
        return 0;

    printf("\nDisplayVesaModeInfo: Resolutions  X == %u, Y == %u",
                                            VesaModeInfo.XResolution,
                                            VesaModeInfo.YResolution);

    printf("\nDisplayVesaModeInfo: Character cell Width == %u, Height == %u",
                                            VesaModeInfo.XCharSize,
                                            VesaModeInfo.YCharSize);

    printf("\nDisplayVesaModeInfo: Number of planes == %u",
                                            VesaModeInfo.NumberOfPlanes);

    printf("\nDisplayVesaModeInfo: Bits per pixel == %u",
                                      VesaModeInfo.BitsPerPixel);

    printf("\nDisplayVesaModeInfo: Number of banks == %u",
                                      VesaModeInfo.NumberOfBanks);

    printf("\nDisplayVesaModeInfo: Memory model == %u    ",
                                      VesaModeInfo.MemoryModel);

    switch(VesaModeInfo.MemoryModel)
    {

        case VESA_MODE_TEXT :
                                        printf("(Text mode)");
                                        break;
        case VESA_MODE_CGA_GRAPHICS :
                                        printf("(CGA graphics)");
                                        break;
        case VESA_MODE_HERCULES_GRAPHICS :
                                        printf("(Hercules graphics)");
                                        break;
        case VESA_MODE_4_PLANE_PLANAR :
                                        printf("(4-plane planar)");
                                        break;
        case VESA_MODE_PACKED_PIXEL :
                                        printf("(Packed pixel)");
                                        break;
        case VESA_MODE_NON_CHAIN_4_256_COLOR :
                                        printf("(Non-chain 4,  256 color)");
                                        break;
        case VESA_MODE_DIRECT_COLOR :
                                        printf("(Direct color)");
                                        break;
        case VESA_MODE_YCbCr :
                                        printf("(YCbCr)");
                                        break;
        default :
                    if (VesaModeInfo.MemoryModel < 0x10)
                        printf("(VESA reserved)");
                    else
                        printf("(OEM defined)");

    }

    printf("\nDisplayVesaModeInfo: Bank size == %u",
                                      VesaModeInfo.BankSize);

    printf("\nDisplayVesaModeInfo: Number of image pages == %u",
                                      VesaModeInfo.NumberOfImagePages);

    if (VesaModeInfo.MemoryModel == VESA_MODE_DIRECT_COLOR)
    {
        printf("\nDisplayVesaModeInfo: Mask sizes Red(%u), Green(%u)",
                       VesaModeInfo.RedMaskSize,
                       VesaModeInfo.GreenMaskSize);

        printf("\nDisplayVesaModeInfo: Mask sizes Blue(%u), Rsvd(%u)",
                       VesaModeInfo.BlueMaskSize,
                       VesaModeInfo.RsvdMaskSize);

        printf("\nDisplayVesaModeInfo: Field lsb position Red(%u), Green(%u)",
                       VesaModeInfo.RedFieldPosition,
                       VesaModeInfo.GreenFieldPosition);

        printf("\nDisplayVesaModeInfo: Field lsb position Blue(%u), Rsvd(%u)",
                      VesaModeInfo.BlueFieldPosition,
                      VesaModeInfo.RsvdFieldPosition);

        printf("\nDisplayVesaModeInfo: DirectColorModeInfo");

        if (VesaModeInfo.DirectColorModeInfo &
            VESA_PROGRAMMABLE_DIRECT_COLOR_RAMP_TEST_BIT)
              printf("\nDisplayVesaModeInfo:  - Color ramp is programmable");
        else
              printf("\nDisplayVesaModeInfo:  - Color ramp is fixed");

        if (VesaModeInfo.DirectColorModeInfo &
            VESA_RESERVED_BITS_ARE_USABLE_TEST_BIT)
              printf("\nDisplayVesaModeInfo:  - Reserved bits are usable");
        else
              printf("\nDisplayVesaModeInfo:  - Do not use reserved bits");
     }
     if (VesaModeInfo.MemoryModel == VESA_MODE_YCbCr)
     {
        printf("\nDisplayVesaModeInfo: Mask sizes Y(%u), U(%u)",
                      VesaModeInfo.GreenMaskSize,
                      VesaModeInfo.BlueMaskSize);

        printf("\nDisplayVesaModeInfo: Mask sizes V(%u), Rsvd(%u)",
                        VesaModeInfo.RedMaskSize,
                        VesaModeInfo.RsvdMaskSize);

        printf("\nDisplayVesaModeInfo: Field lsb position Y(%u), U(%u)",
                      VesaModeInfo.GreenFieldPosition,
                      VesaModeInfo.BlueFieldPosition);

        printf("\nDisplayVesaModeInfo: Field lsb position V(%u), Rsvd(%u)",
                        VesaModeInfo.RedFieldPosition,
                        VesaModeInfo.RsvdFieldPosition);
     }

     return 0;
 }

int ExitLogo(void)
{
    WdsLogo();

    exit(1);

    return 0;
}

/*======================== End of File ========================*/


Previous Table of Contents Next