VBE Information

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