Introduction
Historically, the evolution of computer graphics has been driven by various hardware and software standards. Two of the most important graphics standards in PC history are VGA (Video Graphics Array) and VBE (VESA BIOS Extensions). These technologies form the foundation of video output in early computers and remain relevant today in boot processes and compatibility modes.
VGA (Video Graphics Array):
- VGA is an older standard that was prevalent during the era of DOS and early Windows systems.
- It primarily supports lower resolution modes (such as 320x200, 640x480) with limited color depth (commonly 16 colors or 256 colors).
- VGA was originally introduced by IBM in 1987 and became a widely adopted standard for video display in personal computers.
For more information, have a look at this article: https://thejat.in/learn/vga-in-real-mode
VESA (Video Electronics Standards Association):
- VESA standards, including VESA BIOS Extensions (VBE), were developed to address the limitations of VGA and to provide extended capabilities for video display.
- VESA BIOS Extensions introduced a standardized way for software to access and control advanced video modes, including higher resolutions (such as 800x600, 1024x768, or higher) and increased color depths (24-bit true color).
- VESA VBE also facilitated linear framebuffer access, which allows for more efficient graphics rendering compared to the bank switching methods used in VGA.
VESA (Video Electronics Standards Association) functions, specifically referring to VESA BIOS Extensions (VBE), provide a standardized interface for software to interact with graphics hardware.
For more information explore this article: https://thejat.in/learn/vesa-bios-extensions-vbe
VBE Functions:
VBE got a lot of functions which we can use to get general information about hardware, supported video modes, setting a particular video modes and a lot more. We will explore some of them here.
1️⃣ GetVbeInfo:
Function Purpose: Retrieves general information about the VESA BIOS Extensions (VBE) supported by the system.
Function Prototype:
Function: GetVbeInfo
Input: AX = 4F00h
ES:DI = Pointer to a buffer (VBEInfoBlock)
512 bytes data structure
Output: VBEInfoBlock filled with VBE information
Return: AX = VBE Status (Success or Error Code)
AL = 4Fh - If the function is supported
AH = 00h - Function successful
Usage:
- Description: The
GetVbeInfo
function is used to query the system's VBE capabilities and configuration details. - Input: Set AX to 4F00h to indicate the request for VBE information.
- Output: The function populates a structure (
VBEInfoBlock
) pointed to by ES with detailed information such as VBE version, supported video modes, display memory information, and capabilities. - Return Value: AX upon return contains a status code indicating success (00h) or an error code if the function fails.
Here is the complete code:
vesa.inc
:
Defining the structure and initialization of the structure
First we will define the structure where our data will be stored:
; Structure Definitions
struc VbeControllerStruct
.Signature resb 4
.Version resw 1
.OemNamePtr resd 1
.Capabilities resd 1
.ModeListPtr resd 1 ; List of WORDS terminated by 0xFFFF
.Num64KBlocksMem resw 1
.ReservedSpace resb 492
endstruc
; ****************************
; VBE Structures, initialization
; ****************************
VesaControllerInfo:
istruc VbeControllerStruct
at VbeControllerStruct.Signature, db 0, 0, 0, 0
at VbeControllerStruct.Version, dw 0
at VbeControllerStruct.OemNamePtr, dd 0
at VbeControllerStruct.Capabilities, dd 0
at VbeControllerStruct.ModeListPtr, dd 0 ; List of WORDS terminated by 0xFFFF
at VbeControllerStruct.Num64KBlocksMem, dw 0
at VbeControllerStruct.ReservedSpace, times 492 db 0
iend
Call the interrupt
; Setup buffer
xor eax, eax
xor edi, edi
mov es, ax
mov edi, VesaControllerInfo ; The area where bios information will
; be stored
; Get Controller Info, 0x4f00
call VesaControllerInfo
test eax, eax
jne .Fail
; **************************
; VesaGetVideoModes
; IN:
; - ES:DI: Buffer
; OUT:
; - EAX: 0 for success
; **************************
VesaGetVideoModes:
; Save state
pushad
; Setup for INT
xor eax, eax
mov ax, 0x4F00
int 0x10
; Check if success
test ah, ah
jne .NoVesa
cmp al, 0x4F
jne .NoVesa
; game on.
popad
;; Store the VBE Controller Info address for future references.
mov dword [BootHeader + MultiBoot.VBEControllerInfo], edi
mov eax, 0
ret
; old school system
.NoVesa:
popad
mov eax, 1
ret
From this function we got the address where the list of video mode id's is stored which is at address pointed by the VesaControllerInfo + VbeControllerStruct.ModeListPtr
. This ModeListPtr
is pointing to the all the video mode id list supported by the graphics card. Now we need to parse this list by using this address.
We will use this address and every list at this address is of word
(16-bit
) in size means first 16-bit contains the first video mode id, then next 16-bit contains the second video mode id, and 0xFFFF
denotes the end of the list. We will pass these id in a loop to the next function 0x4f01
to get information about video mode by its id and read it in a buffer.
2️⃣ GetVideoModeList
Function Purpose: Retrieves a list of supported video modes by querying the VBE. The VBE function 4F01h
is used to retrieve detailed information about a specific video mode supported by the VESA BIOS Extensions (VBE). This function provides detailed information such as resolution, color depth, and other characteristics of a particular video mode.
Function Prototype:
Function: GetVideoModeList
Input: AX = 4F01h
CX = Video mode index (0-based, start with 0)
ES:DI = Pointer to a buffer (ModeInfoBlock)
Output: ModeInfoBlock filled with video mode information
256 bytes in size.
Return: AX = VBE Status (Success or Error Code)
Usage:
- Description: The
GetVideoModeList
function allows software to obtain a list of supported video modes from the VBE. - Input: Set AX to 4F01h to indicate the request for video mode information. Set CX to the index of the video mode to query (starting from 0).
- Output: The function fills a structure (
ModeInfoBlock
) pointed to by ES with details about the specified video mode, including resolution, color depth, memory layout, and other characteristics. - Return Value: AX upon return indicates the status of the operation—success (00h) or an error code if the function fails.
Code:
First we define a structure for reading the video mode information, we can use memory buffer as well. However reading at particular offset is easy in structure by just using the name as the offset rather than using immediate value in case of memory buffer.
;; Definition
struc VbeModeStruct
.Attributes resw 1
.WindowAttribsA resb 1
.WindowAttribsB resb 1
.WindowGranKb resw 1
.WindowSizeKb resw 1
.WindowASegment resw 1
.WindowBSegment resw 1
.FuncPtrPosition resd 1
.BytesPerScanline resw 1
.ResolutionX resw 1
.ResolutionY resw 1
.CharCellWidth resb 1
.CharCellHeight resb 1
.NumPlanes resb 1
.Bpp resb 1
.NumBanks resb 1
.MemoryModel resb 1
.BankSizeKb resb 1
.MaxImagePages resb 1
.Reserved resb 1
.RedMaskSize resb 1
.RedFieldPos resb 1
.GreenMaskSize resb 1
.GreenFieldPos resb 1
.BlueMaskSize resb 1
.BlueFieldPos resb 1
.AlphaMaskSize resb 1
.AlphaFieldPos resb 1
.DirectColorAttribs resb 1
.FrameBuffer resd 1
.Reserved1 resd 1
.Reserved2 resw 1
.ReservedSpace resb 213
endstruc
;; Initialization
VesaModeInfo:
istruc VbeModeStruct
at VbeModeStruct.Attributes, dw 0
at VbeModeStruct.WindowAttribsA, db 0
at VbeModeStruct.WindowAttribsB, db 0
at VbeModeStruct.WindowGranKb, dw 0
at VbeModeStruct.WindowSizeKb, dw 0
at VbeModeStruct.WindowASegment, dw 0
at VbeModeStruct.WindowBSegment, dw 0
at VbeModeStruct.FuncPtrPosition, dd 0
at VbeModeStruct.BytesPerScanline, dw 0
at VbeModeStruct.ResolutionX, dw 0
at VbeModeStruct.ResolutionY, dw 0
at VbeModeStruct.CharCellWidth, db 0
at VbeModeStruct.CharCellHeight, db 0
at VbeModeStruct.NumPlanes, db 0
at VbeModeStruct.Bpp, db 0
at VbeModeStruct.NumBanks, db 0
at VbeModeStruct.MemoryModel, db 0
at VbeModeStruct.BankSizeKb, db 0
at VbeModeStruct.MaxImagePages, db 0
at VbeModeStruct.Reserved, db 0
at VbeModeStruct.RedMaskSize, db 0
at VbeModeStruct.RedFieldPos, db 0
at VbeModeStruct.GreenMaskSize, db 0
at VbeModeStruct.GreenFieldPos, db 0
at VbeModeStruct.BlueMaskSize, db 0
at VbeModeStruct.BlueFieldPos, db 0
at VbeModeStruct.AlphaMaskSize, db 0
at VbeModeStruct.AlphaFieldPos, db 0
at VbeModeStruct.DirectColorAttribs,db 0
at VbeModeStruct.FrameBuffer, dd 0
at VbeModeStruct.Reserved1, dd 0
at VbeModeStruct.Reserved2, dw 0
at VbeModeStruct.ReservedSpace, times 213 db 0
iend
; Etc
wOptimizedVesaMode dw 0
wCurrentResX dw 0
wCurrentResY dw 0
; Now parse list
xor eax, eax
mov es, ax
mov esi, dword [VesaControllerInfo + VbeControllerStruct.ModeListPtr]
call VesaFindBestSuitableMode
; **************************
; VesaFindBestSuitableMode
; IN:
; - ES:SI: List of Modes
; **************************
VesaFindBestSuitableMode:
; Save state
pushad
.modeListLoop:
; Null the buffer
push esi
xor eax, eax
mov edi, VesaModeInfo ; Structure to read mode information
mov ecx, 63 ; size of structure
rep stosd
pop esi
; Load mode
mov cx, word [es:si] ; Read first 16-bit from the
; ModeListPtr of 0x4F00 function.
; It should have a video mode id
; End of list?
cmp cx, 0xFFFF ; Check if it is end of the list.
je .Done
; Get Video mode info by its id
mov ax, 0x4F01
mov edi, VesaModeInfo
int 0x10
; Did it work?
test ah, ah
jne .NextEntry
cmp al, 0x4F
jne .NextEntry
; Now lets parse
mov ax, word [VesaModeInfo + VbeModeStruct.Attributes]
; We want Color, Graphics, LFB
and ax, 0x009B
cmp ax, 0x009B
jne .NextEntry
; We want 32 bit modes!! ALPHA FTW
mov al, byte [VesaModeInfo + VbeModeStruct.Bpp]
cmp al, 0x20
jne .NextEntry
; Ok... The modes we are looking for are:
; 1920x1080
; 1600x900
; 1280x720
; 1024x768
mov ax, word [VesaModeInfo + VbeModeStruct.ResolutionX]
mov bx, word [VesaModeInfo + VbeModeStruct.ResolutionY]
; Check 1024x768
cmp ax, 0x0400
jne .Check1280
cmp bx, 0x0300
jne .Check1280
jmp .ValidateEntry
; Ok, so this is 1024x768
.Check1280:
cmp ax, 0x0500
jne .Check1600
cmp bx, 0x02D0
jne .Check1600
jmp .ValidateEntry
.Check1600:
cmp ax, 0x0640
jne .Check1920
cmp bx, 0x0384
jne .Check1920
jmp .ValidateEntry
.Check1920:
cmp ax, 0x0780
jne .NextEntry
cmp bx, 0x0438
jne .NextEntry
.ValidateEntry:
; Check if we have better stored
cmp ax, word [wCurrentResX]
jbe .NextEntry
cmp bx, word [wCurrentResY]
jbe .NextEntry
; Save
mov word [wCurrentResX], ax
mov word [wCurrentResY], bx
mov word [wOptimizedVesaMode], cx
.NextEntry:
; Increase esi
add esi, 2
jmp .modeListLoop
.Done:
; Return
popad
ret