VESA Video Modes

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
pcmattman
Member
Member
Posts: 2566
Joined: Sun Jan 14, 2007 9:15 pm
Libera.chat IRC: miselin
Location: Sydney, Australia (I come from a land down under!)
Contact:

VESA Video Modes

Post by pcmattman »

I have this in my VESA video mode driver, to find an LFB 800x600x24 mode:

Code: Select all

; loaded at 0x1000
org 0x1000

; 16-bit
bits 16

; entry point
_start:

	; get VBE2 information
	mov ax,0x4F00
	mov di,VbeInfoBlock
	push cs
	pop es
	int 0x10
	
	; check for errors
	cmp ax,0x4F
	jnz UseMode13
	
	; check for LFB modes
	cmp word [VbeVersion],0x102 ; must be > 1.2!
	lds si,[VideoModePtr]
	jb NoLFB ; no lfb!
	
	; decrement sp by 2
	sub sp,2
	
	; check the next mode
	CheckNextMode:
	
	; load a word
	lodsw
	
	; simulate word pop
	add sp,2
	
	; compare to 0xFFFF
	cmp ax,0xFFFF
	jz NoLFB ; no adequate mode!
	
	; push the code semgent
	push cs
	or ax,0100000000000000b ; LFB info
	mov di,ModeInfoBlock ; fill up modeinfo buffer
	mov cx,ax
	pop es
	push ax
	mov ax,0x4F01 ; video mode attributes
	int 0x10
	cmp ax,0x4F
	jnz UseMode13
	mov ax,[ModeAttributes]
	test al,1
	jz CheckNextMode
	test al,1000b
	jz CheckNextMode
	test al,10000b
	jz CheckNextMode
	test al,10000000b
	jz CheckNextMode
	
	; we want 800x600x24
	cmp word [XResolution],800
	jb CheckNextMode
	cmp word [YResolution],600
	jb CheckNextMode
	cmp word [BitsPerPixel],24
	jb CheckNextMode
	
	; we have a LFB 800x600x24 mode!
	pop bx
	mov ax,0x4F02
	int 0x10

; loop forever
NoLFB:
UseMode13:
	
	endloop:
	jmp endloop
	
VbeInfoBlock:
	VbeSignature		db "VBE2"
	VbeVersion			dw 0x300
	OemStringPtr		dd 0
	Capabilities		times 4 db 0
	VideoModePtr		dd 0
	TotalMemory			dw 0
	OemSoftwareRev		dw 0
	OemVendorNamePtr	dd 0
	OemProductNamePtr	dd 0
	OemProductRevPtr	dd 0
	Reserved0			times 222 db 0
	OemData				times 256 db 0

ModeInfoBlock:
	ModeAttributes		dw 0
	WinAAttributes		db 0
	WinBAttributes		db 0
	WinGranularity		dw 0
	WinSize				dw 0
	WinASegment			dw 0
	WinBSegment			dw 0
	WinFuncPtr			dd 0
	BytesPerScanLine	dw 0
	XResolution			dw 0
	YResolution			dw 0
	XCharSize			db 0
	YCharSize			db 0
	NumberOfPlanes		db 0
	BitsPerPixel		db 0
	NumberOfBanks		db 0
	MemoryModel			db 0
	BankSize			db 0
	NumberOfImagePages	db 0
	Reserved1			db 1
	RedMaskSize			db 0
	RedFieldPosition	db 0
	GreenMaskSize		db 0
	GreenFieldPosition	db 0
	BlueMaskSize		db 0
	BlueFieldPosition	db 0
	RsvdMaskSize		db 0
	RsvdFieldPosition	db 0
	DirectColorModeInfo	db 0
	PhysBasePtr			dd 0
	Reserved2			dd 0
	Reserved3			dw 0
	; VBE3
	LinBytesPerScanLine		dw 0
	BnkNumberOfImagePages	db 0
	LinNumberOfImagePages	db 0
	LinRedMaskSize			db 0
	LinRedFieldPosition		db 0
	LinGreeMaskSize			db 0
	LinGreenFieldPosition	db 0
	LinBlueMaskSize			db 0
	LinBlueFieldPosition	db 0
	LinRsvdMaskSize			db 0
	LinRsvdFieldPosition	db 0
	MaxPixelClock			dd 0
	Reserved4				times 189 db 0
It fails at this code, just jumps straight to NoLFB...

Code: Select all

	; check for LFB modes
	cmp word [VbeVersion],0x102 ; must be > 1.2!
	lds si,[VideoModePtr]
	jb NoLFB ; no lfb!
I've tried getting into the mode directly (function 2, no checking first) but I would prefer to find a valid mode (in case VBE isn't supported).
pcmattman
Member
Member
Posts: 2566
Joined: Sun Jan 14, 2007 9:15 pm
Libera.chat IRC: miselin
Location: Sydney, Australia (I come from a land down under!)
Contact:

Post by pcmattman »

Don't worry... I found a NASM example that works perfectly.

One question, though, how do I do something like int_v86()? I can figure out how to run the interrupt but how can I make sure that the caller doesn't keep running until the the interrupt is handled?

Edit: never mind, I figured it out...

Edit 2: Wow, I just got into 800x600x32 mode with a LFB (which was retrieved dynamically). And, to top it all off, I got into the mode via a VBE driver on my hard disk which I loaded via my FAT32 read routines :D

Best part is, the driver is portable, you just fill some registers then run it in virtual 8086 mode, no dependencies on the kernel (apart from int 0x80, which is how I get control back from the programs).
Post Reply