comment ~
*****************************************************************************
VESA library containing three basic functions
File: VESA.ASM
Author: Adam Seychell
System: DOS32
Version: 1.00
This library uses the VBE protected mode interface (func 0Ah) to obtain
an near pointer directly calling the 32bit VBE funcs 05h and 07h.
Calling the 32bit functions directly removes overhead of having to emulating
a real mode interrupt and I have measured it to be over 15 times faster!
My friends P90 rates over a 50 times speed increase!
Currently very few video cards are supporting the new protected mode
interface of the VBE v2.0 interface. An excellent VESA driver is availible
for just about all video cards and is called UniVBE. Versions 5.1+ of
UniVBE support the VBE 2.0 protected mode interface allowing ultrafast
VBE function calls in SVGA modes and if your card is Vesa Loacal bus
or PCI bus you can use the linear frame buffer and avoid bank switching
all togehter.
To set the bank or start address use the macros SetBank and SetStart
defined in VESA.INC.
*****************************************************************************
Function: CheckVbeMode
Expects: Eax = VESA video mode number (bits 16..31 ignored).
If bit 14 set then use linear memory mapping.
Returns: if successful;
EAX = near pointer to video address
Carry = 0
if unsuccessful;
EAX = zero
Carry = 1
DL = error code. 1 = VBE not installed
2 = mode not supported.
3 = mode incompatible.
Description: Checks to see if the VBE video mode can be used. if so then
will return a pointer to video mapping address.
Notes: * All registers are preserved.
* If linear frame buffer is selected then EAX will point to
the linear frame buffer. The SetBank macro function is
undefined and should not be used.
*****************************************************************************
Function: SetVbeMode
Expects: Nothing.
Returns: Nothing.
Description: Set video mode to the mode number specified to last successful
call to CheckVbeMode.
Notes: All registers are preserved.
*****************************************************************************
Function: VbeFunc06
Input: BL = 00h Set Scan Line Length in Pixels
= 01h Get Scan Line Length
= 02h Set Scan Line Length in Bytes
= 03h Get Maximum Scan Line Length
CX = If BL=00h Desired Width in Pixels
If BL=02h Desired Width in Bytes
(Ignored for Get Functions)
Output: AX = VBE Return Status
BX = Bytes Per Scan Line
CX = Actual Pixels Per Scan Line
(truncated to nearest complete pixel)
DX = Maximum Number of Scan Lines
Description: VBE Function 06h - Set/Get Logical Scan Line Length
Notes: directly calls INT 10h AX=4F06h;
Calling this function saves the "Bytes Per Scan Line" returned
in BX which is required for correct operation of the
SetStart macro.
*****************************************************************************
~
.386
.MODEL FLAT , C
Include vesa.inc
_BSS SEGMENT
PmodeSetStart DD ?
file_buffer DD ?
ProgramBaseAddress DD ?
_BankSetTable DD 128 DUP (?)
VideoModeNumber DW ?
Total64Kbocks DW ?
Current_Bank DB ?
VBE_StarPerPixelFactor DB ?
DOS_segs LABEL DWORD
Real_ES DW ?
Real_DS DW ?
_BSS ENDS
.CODE
align 4
VBE_BytesPerScanLine DD 0
VbeSetBank DD Offset SetBank_RealMode
VbeSetStart DD Offset SetStart_RealMode
Old_PhysBasePtr DD -1
;--------------------------------------------------------
; Call real mode set video bank function
; Note: very very slow....
;----------------------------------------------------------
SetBank_RealMode PROC
push ebx
xor ebx,ebx
mov ax,04F05h
int 10h
pop ebx
Ret
SetBank_RealMode ENDP
;--------------------------------------------------------
; Call real mode set display start bank function
; CX=pixel in scan line
; DX=scan line number
; Note: very very slow....
;----------------------------------------------------------
SetStart_RealMode PROC
push ebx
xor ebx,ebx
mov ax,04F07h
int 10h
pop ebx
Ret
SetStart_RealMode ENDP
;--------------------------------------------------------
; Call Protected mode set display start bank function
; ECX=pixel in scan line
; EDX=scan line number
;----------------------------------------------------------
SetStart_ProtectedMode PROC
push ebx
xor ebx,ebx
imul edx,[VBE_BytesPerScanLine]
add edx,ecx
mov cl,[VBE_StarPerPixelFactor]
shr edx,cl
mov cx,dx
shr edx,16
mov ax,04F07h
Call [PmodeSetStart]
pop ebx
Ret
SetStart_ProtectedMode ENDP
;------------------------------------------------------------
; Procudure to call a DOS interrupt.
;
; Expects the intrrupt number pushed on the stack.
;
; e.g push 10h
; call DOSinterrupt
; jc error
; Real mode ES and DS registers are passed via varibles Real_ES and Real_DS.
;
;
; As explained in the DOS32 documentaion, DOS32 initally handles all interrupts
; such that calling a protected mode interrupt will automatically call
; the same interrupt number in real mode. However, using this method there
; is no way to specify the values of the real mode SEGMENT registers.
; Some of the VESA calls require ES:DI to point to buffers and so
; we need to use INT31h AX=300h service to call a real mode interrupt.
; The procedure below does exactly that...
;
;------------------------------------------------------------
DOSinterrupt PROC
push dword ptr 0 ; ignore SS, SP
lea esp,[esp - 8] ; ignore CS, IP ,FS, GS
push [DOS_segs] ; push DS and ES
pushfw
pushad
mov edi,esp
mov ax,0300h
xor cx,cx
movzx Ebx,Byte Ptr [esp+36h] ; Get int number from stack param
int 31h ; Emulate Real Mode Interrupt
popad
popfw
pop [DOS_segs] ; get DS and ES
lea esp,[esp+12] ; Ignore SS,SP,CS,IP,FS,GS
ret 4 ; return ingnoring parameter
DOSinterrupt ENDP
;
; VBE Function 06h - Set/Get Logical Scan Line Length
;
VbeFunc06 PROC
mov ax,4F06h
int 10h
cmp ah,00h
jne @@J1
mov Word Ptr [VBE_BytesPerScanLine],BX
@@J1: ret
VbeFunc06 ENDP
CheckVbeMode PROC
; Some of the vesa bios functions require a transfer of data in the
; real mode address space. The best way to do this is by taking advantage
; of the 8Kb file buffer initally setup by DOS32. As explained in the API.DOC
; this 8Kb buffer is in the real mode address space and may be use to temporary
; hold information.
;
pushad
mov VideoModeNumber,ax
mov ax,0EE02h ; GET REAL MODE SEGMENT OF FILE I/O BUFFER
int 31h
; returns AX = real mode segment of 8Kb buffer.
; EBX = program linear base address.
mov ProgramBaseAddress,ebx
mov Real_ES,ax
And Eax,0FFFFh
shl Eax,4
sub eax,ebx
Mov file_buffer,eax ; save near address of 8Kb file buffer.
;
; GET VESA INFORMATION
;
mov ax,4F00h
mov di,0 ; (real mode) ES:DI -> 256 byte buffer
push 10h
call DOSinterrupt
Cmp AX,004Fh
jne NoVESA
;
; Search video mode list for 640x480x256 ( VESA mode 101h )
; The vesa driver Func 4F00h fills in the buffer with the information.
; Offset 0Eh of this buffer contains a real mode SEG:OFS of the video
; mode list. This list consists of each supported VESA mode and
; terminates with 0FFFFh.
;
mov EBP,[file_buffer] ; save video mem size
mov dx,[ VbeInfoBlock.TotalMemory + EBP]
mov [Total64Kbocks],dx
; Get the real mode far pointer of the video mode list and
; convert the real mode SEG:OFS address into a 32bit near pointer.
;
Movzx edx,Word Ptr [ VbeInfoBlock.VideoModePtr + EBP + 2]
shl edx,4
sub edx,ProgramBaseAddress
Movzx ebx,Word Ptr [ VbeInfoBlock.VideoModePtr + EBP ]
add edx,ebx ; EDX points to video mode list.
mov bx,VideoModeNumber
and bx,0111111111b ; read bits 0..8
xor eax,eax
Loop01: Mov ax,[Edx] ; Read video mode from list
Cmp Ax,0FFFFh
je @@ModeNotFound
add Edx,2
cmp Ax,Bx
jne Loop01
;
; Get VBE MODE information
; Note, the mode information block is also stored in the file buffer
;
mov ax,4F01h
mov cx,VideoModeNumber
and cx,0111111111b ; read bits 0..8
mov di,0 ; ES:DI -> 256 byte buffer
push 10h
call DOSinterrupt
Cmp AX,004Fh
jne ModeNotGood
Mov EBP,file_buffer ; EBP -> ModeInfoBlock
;
; Determine to use windowing or linear memory mapping.
;
test VideoModeNumber,0100000000000000b
jz DoWithBanks
; ******************************************************
; Setup for linear memory mapping mode.
; ******************************************************
Test [ ModeInfoBlock.ModeAttributes + EBP],10000000b
jz ModeNotGood
;
; Calulate a near pointer to physical linear mapping address.
;
Mov ebx,[ ModeInfoBlock.PhysBasePtr + EBP]
Mov eax,[Old_PhysBasePtr]
cmp eax,ebx
je Jskip06
mov [Old_PhysBasePtr],ebx
mov cx,bx
shr ebx,16
mov si,Total64Kbocks
xor edi,edi
mov ax,0800h ; map physical memory
int 31h
jc ModeNotGood
shl ebx,16
mov bx,cx
mov eax,ebx ; eax = linear address
Jskip06:
mov [esp+4*7],eax ; save eax in stack
jmp Finished
DoWithBanks:
; ******************************************************
; Setup for windowing mode.
; ******************************************************
; check is windowing is avalible ( writable and availible )
;
Test [ ModeInfoBlock.ModeAttributes + EBP],01000000b
jnz ModeNotGood
Mov bl,[ ModeInfoBlock.WinAAttributes + EBP]
and bl,0000101b
cmp bl,0000101b
jne ModeNotGood
;
; Setup Bank Numbering table
;
Movzx eax,[ ModeInfoBlock.WinSize + EBP]
Movzx ebx,[ ModeInfoBlock.WinGranularity + EBP]
xor edx,edx
div ebx
xor edx,edx
xor ecx,ecx
@@loop01:
mov _BankSetTable[ECX*4],edx
add edx,eax
inc ecx
cmp ecx,LENGTH _BankSetTable
jb @@loop01
;
; Calulate 32bit linear pointer to CPU video memory WindowA
;
Movzx eax,[ ModeInfoBlock.WinASegment + EBP]
shl eax,4
mov [esp+4*7],eax ; save eax in stack
Finished:
;
; If 32bit VBE inteface is availible then use the bloody thing
;
mov ax,4F0Ah
mov BL,0 ; return pmode interface
push 10h
call DOSinterrupt
Cmp AX,004Fh
jne No32bitInterface
movzx Esi,Real_ES ; convert ES:DI to 32bit near ptr
shl esi,4
and edi,0ffffh
add esi,edi
sub esi,ProgramBaseAddress ; ESI -> protected mode table.
; Use protected mode bank proc only for zero length memory list.
;
movzx edi,Word Ptr [ESI+06] ; get port/memory table list
and edi,edi
jz @@usePmodeBanks
@@L5: cmp Word Ptr [ESI+EDI],0FFFFh ; search port list
lea edi,[edi+2]
jne @@L5
cmp Word Ptr [ESI+EDI],0FFFFh ; see if mem list is zero
jne @@SkipPmodeBanks
@@usePmodeBanks:
movzx eax,Word Ptr [ESI+00]
add eax,esi
mov [VbeSetBank],eax ; save Set Bank code address.
@@SkipPmodeBanks:
; Save Set display start code address.
;
movzx eax,Word Ptr [ESI+02]
add eax,esi
mov [PmodeSetStart],eax
mov [VbeSetStart],Offset SetStart_ProtectedMode
; Get bytes per scan line for the protected mode SetStart function.
;
mov ax,[ ModeInfoBlock.BytesPerScanLine + EBP]
mov Word Ptr [VBE_BytesPerScanLine],ax
; adjust for plane boundary for 8 bit+ modes
;
mov [VBE_StarPerPixelFactor],0
Cmp [ ModeInfoBlock.BitsPerPixel + EBP],4
je @@1
mov [VBE_StarPerPixelFactor],2
@@1:
No32bitInterface:
mov eax,ProgramBaseAddress ; convert linear pointer to near
sub [esp+4*7],eax
popad
clc
ret
;------------------------ Error messages ---------------------------------
ModeNotGood:
popad
mov dl,3
jmp Abort
@@ModeNotFound:
popad
mov dl,2
jmp Abort
NoVESA:
popad
mov dl,1
Abort:
xor eax,eax
stc
ret
CheckVbeMode ENDP
SetVbeMode PROC
;
; Set VIDEO mode
;
pushad
xor eax,eax
xor ebx,ebx
xor ecx,ecx
xor edx,edx
mov BX,VideoModeNumber
mov ax,4F02h
Int 10h
popad
Ret
SetVbeMode ENDP
End