home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
World of Graphics
/
WOGRAPH.BIN
/
437.UNIVESA.ASM
< prev
next >
Wrap
Assembly Source File
|
1993-03-07
|
34KB
|
1,238 lines
;****************************************************************************
;*
;* The Universal VESA TSR
;*
;* Copyright (C) 1993 Kendall Bennett.
;* All rights reserved.
;*
;* Filename: $RCSfile: univesa.asm $
;* Version: $Revision: 1.2 $
;*
;* Language: 80386 Assembler
;* Environment: IBM PC (MS DOS)
;*
;* Description: This source file contains the code for a Universal VESA
;* TSR's, to implement the VESA video BIOS extensions for
;* supported SuperVGA's.
;*
;* Must be assembled in the large memory model.
;*
;* $Id: univesa.asm 1.2 1993/03/07 04:05:36 kjb Exp $
;*
;* Revision History:
;* -----------------
;*
;* $Log: univesa.asm $
;* Revision 1.2 1993/03/07 04:05:36 kjb
;* Bug fixes.
;*
;* Revision 1.1 1993/03/03 10:27:33 kjb
;* Initial revision
;*
;****************************************************************************
IDEAL
DOSSEG
JUMPS
P386 ; Use 386 instructions
INCLUDE "MODEL.MAC" ; Memory model macros
header uvesa ; Link with uvesa.c
;----------------------------------------------------------------------------
; Internal Equates and Macros
;----------------------------------------------------------------------------
INCLUDE "MGRAPH.EQU" ; Include Equates for Mgraph Routines
CRTC EQU 3D4h ; Port of CRTC registers
VGABufferSeg EQU 0A000h ; Segment of VGA display memory
NL EQU <0dh, 0ah> ; New Line marker
EOS EQU '$' ; End of String marker
PSPSize EQU 100h ; Size of program PSP
SUCCESS EQU 004Fh ; Return value on success
FAILURE EQU 014Fh ; Return value on failure
VESA_FUNCTIONS EQU 04Fh ; VESA Control function value (AH)
MAX_FUNCTION EQU 7 ; Highest VESA function number supported
VESA_VERSION EQU 0102h ; Version 1.2
; Macro to get the value of an interrupt vector. Returns the result in
; ES:BX.
MACRO GetVector intnum
mov ah,35h
mov al,intnum
int 21h
ENDM
; Macro to set the value of an interrupt vector.
MACRO SetVector intnum, handler
push ds
mov dx,seg handler
mov ds,dx
mov dx,offset handler
mov ah,25h
mov al,intnum
int 21h
pop ds
ENDM
begcodeseg uvesa
EXTRN _testISR:FAR
endcodeseg uvesa
begcodeseg modes
EXTRN _MGL_availableModes:FAR
endcodeseg modes
begcodeseg uvesa
;----------------------------------------------------------------------------
; Resident Data
;----------------------------------------------------------------------------
; Signature used to determine if the TSR is already installed.
Signature: db 'Universal VESA TSR',0
SigLen = $-Signature
LABEL OldInt10 DWORD
OldInt10off dw ? ; Place to save int 10h vector
OldInt10seg dw ?
; Globals used by resident generic SuperVGA routines
CntDriver dw 0 ; Graphics driver number
CntMode dw 0 ; Graphics mode number
CntDAC dw 0 ; Video DAC ID
CntChipID dw 0 ; Graphics driver chip ID
CntColors dw 0 ; Current color mode
CntVESAMode dw 0 ; Current VESA mode number
CntMemory dw 0 ; Amount of memory on chip
CntStartX dw 0 ; Current display start X
CntStartY dw 0 ; Current display start Y
; Dispatch table for supported function calls
DispatchTable dw offset SuperVGAInfo
dw offset SuperVGAModeInfo
dw offset SuperVGASetMode
dw offset SuperVGAGetMode
dw offset SuperVGAVideoState
dw offset SuperVGABankSwitch
dw offset SuperVGAScanlineLength
dw offset SuperVGADisplayStart
Status dw 0 ; Return status code
; VGA Information block returned to the user program
VGAInfo db 'VESA' ; Signature value
dw VESA_VERSION ; VESA Version number
dw offset Signature ; OEM Name offset
dw seg Signature ; OEM Name segment
db 4 DUP (0) ; Capabilities bits
dw offset ModeTable ; Video mode table offset
dw seg ModeTable ; Video mode table segment
VGAInfoSize = $-VGAInfo
; List of all possible supported VESA video modes. If any of the modes
; are not supported by the installed SuperVGA, they are zeroed from the
; table.
ModeTable dw 100h ; grSVGA_640x400x256
dw 101h ; grSVGA_640x480x256
dw 102h ; grSVGA_800x600x16
dw 103h ; grSVGA_800x600x256
dw 104h ; grSVGA_1024x768x16
dw 105h ; grSVGA_1024x768x256
dw 106h ; grSVGA_1280x1024x16
dw 107h ; grSVGA_1280x1024x256
dw 10Dh ; grSVGA_320x200x32k
dw 10Fh ; grSVGA_320x200x16m
dw 110h ; grSVGA_640x480x32k
dw 112h ; grSVGA_640x480x16m
dw 113h ; grSVGA_800x600x32k
dw 115h ; grSVGA_800x600x16m
dw 116h ; grSVGA_1024x768x32k
dw 118h ; grSVGA_1024x768x16m
dw 119h ; grSVGA_1280x1024x32k
dw 11Bh ; grSVGA_1280x1024x16m
dw 0FFFFh ; Terminate the list
; Define the memory model type numbers
memPL16 EQU 3 ; Planar
memPK256 EQU 4 ; Packed pixel
memPKD EQU 6 ; Direct
; Video mode information for the currently active video mode. BIOS
; output is generally supported by most video modes, but we can never
; be sure so we turn this off for all modes.
ModeInfo dw 011011b ; Mode Attributes
db 0111b ; Window A attributes
WinBAttr db 0011b ; Window B attributes
dw 64 ; Window granularity (in K)
dw 64 ; Window size (in K)
dw VGABufferSeg ; Start segment of Window A
dw VGABufferSeg ; Start segment of Window B
dw offset SuperVGABankSwitch
dw seg SuperVGABankSwitch
BytesPerLine dw 0 ; Bytes per logical scanline
XRes dw 0 ; X resolution
YRes dw 0 ; Y resolution
CWidth db 8 ; Character width
CHeight db 8 ; Character height
Planes db 0 ; Number of planes
BitsPerPixel db 0 ; Bits per pixel
Banks db 0 ; Number of banks??
MemMode db 0 ; Memory mode
db 0
Pages db 0 ; Number of image pages
ModeInfoSize = $-ModeInfo
; Lookup table for filling in the optional mode information in the above
; structure.
mode800x600x16 dw 800,600
db 8,8,4,4,1,memPL16
mode1024x768x16 dw 1024,768
db 8,8,4,4,1,memPL16
mode1280x1024x16 dw 1280,1024
db 8,8,4,4,1,memPL16
PartialInfoSize = $-mode1280x1024x16
mode640x350x256 dw 640,350
db 8,8,1,8,1,memPK256
mode640x400x256 dw 640,400
db 8,8,1,8,1,memPK256
mode640x480x256 dw 640,480
db 8,8,1,8,1,memPK256
mode800x600x256 dw 800,600
db 8,8,1,8,1,memPK256
mode1024x768x256 dw 1024,768
db 8,8,1,8,1,memPK256
mode1280x1024x256 dw 1280,1024
db 8,8,1,8,1,memPK256
mode320x200x32k dw 320,200
db 8,8,1,15,1,memPKD
mode640x350x32k dw 640,350
db 8,8,1,15,1,memPKD
mode640x400x32k dw 640,400
db 8,8,1,15,1,memPKD
mode640x480x32k dw 640,480
db 8,8,1,15,1,memPKD
mode800x600x32k dw 800,600
db 8,8,1,15,1,memPKD
mode1024x768x32k dw 1024,768
db 8,8,1,15,1,memPKD
mode1280x1024x32k dw 1280,1024
db 8,8,1,15,1,memPKD
mode320x200x16m dw 320,200
db 8,8,1,24,1,memPKD
mode640x350x16m dw 640,350
db 8,8,1,24,1,memPKD
mode640x400x16m dw 640,400
db 8,8,1,24,1,memPKD
mode640x480x16m dw 640,480
db 8,8,1,24,1,memPKD
mode800x600x16m dw 800,600
db 8,8,1,24,1,memPKD
mode1024x768x16m dw 1024,768
db 8,8,1,24,1,memPKD
mode1280x1024x16m dw 1280,1024
db 8,8,1,24,1,memPKD
;----------------------------------------------------------------------------
; Resident Code
;----------------------------------------------------------------------------
ASSUME cs:uvesa_TEXT, ds:NOTHING, es:NOTHING
INCLUDE "SV_PORTS.ASM"
INCLUDE "SV_BANKS.ASM"
INCLUDE "SV_MODES.ASM"
INCLUDE "SV_PAGE.ASM"
INCLUDE "SV_MAXPG.ASM"
;----------------------------------------------------------------------------
; Int10ISR - Video BIOS hook.
;----------------------------------------------------------------------------
;
; This routine is called whenever an application program makes a call to
; the Video BIOS routines. We check to see if the calls and VESA functions
; calls, and handle them appropriately, or else we simply pass the call
; to the old Video BIOS handler.
;
;----------------------------------------------------------------------------
PROC Int10ISR far
cmp ah,VESA_FUNCTIONS ; Is this a VESA function?
je @@VesaFunction ; Yes, so handle it
; Check to see if this is the Set Video Mode function, in which case we
; need to check if we are trying to set a standard VGA video mode.
or ah,ah
jnz @@ToOldBIOS
cmp al,13h
ja @@ToOldBIOS
; Attempting to set a standard VGA video mode, so pass this call onto the
; SuperVGASetMode routine.
mov bx,ax ; BX := video mode number
call SuperVGASetMode ; Set the video mode
iret
@@ToOldBIOS:
jmp [OldInt10] ; Jump to old VIDEO BIOS
; This is a VESA function, so dispatch to the appropriate routine depending
; on the subfunction number.
@@VesaFunction:
cmp al,MAX_FUNCTION
ja @@NotSupported ; VESA Function is not supported
cmp al,5 ; Bank Switching call?
jne @@NotBankSwitch ; No, handle normally
; The bank switch routine can be called as a far function, so we can't
; handle this routine with a simple lookup table.
call far SuperVGABankSwitch
iret
@@NotBankSwitch:
xor ah,ah
shl al,1 ; AX := index into table
xchg ax,bx
mov bx,[DispatchTable + bx]
xchg ax,bx
mov [Status],FAILURE
push ds ; Save value of DS
call ax ; Call the appropriate function
pop ds ; Restor value of DS
mov ax,[Status] ; Return status code
iret
@@NotSupported:
xor al,al ; Function is not supported
iret
ENDP Int10ISR
;----------------------------------------------------------------------------
; SuperVGAInfo - Get SuperVGA Information
;----------------------------------------------------------------------------
;
; Function to return information about the SuperVGA video card.
;
; Entry: ES:DI -> 256byte buffer for SuperVGA information
;
; Exit: AX - VESA status code
;
;----------------------------------------------------------------------------
PROC SuperVGAInfo near
pusha ; Save register values
push ds ; Save DS
cld
mov ax,cs
mov ds,ax
mov si,offset VGAInfo ; DS:SI -> VGAInfo Table
mov cx,VGAInfoSize
rep movsb ; Copy the data across
mov [Status],SUCCESS ; Return status code
pop ds ; Restore DS
popa ; Restore register values
ret
ENDP SuperVGAInfo
;----------------------------------------------------------------------------
; SuperVGAModeInfo - Get SuperVGA Video Mode Information
;----------------------------------------------------------------------------
;
; Function to return information about a specific VESA SuperVGA video mode.
;
; Entry: CX - SuperVGA video mode
; ES:DI -> 256 byte buffer for mode information
;
; Exit: AX - VESA status code
;
;----------------------------------------------------------------------------
PROC SuperVGAModeInfo near
pusha ; Save register values
call VESAToMGLMode ; AX := MGL mode number
cmp ax,-1
je @@Invalid ; Mode is invalid to us!
push [BytesPerLine] ; Save current bytes per line value
push ax ; Save MGL mode number
xor ebx,ebx
mov bx,[CntMemory]
shl ebx,10 ; EBX := memory in bytes
call numPages ; Compute number of video pages
mov [Pages],al ; Store number of video pages
mov [BytesPerLine],cx ; Stote bytes per line value
; Copy the information specific to the video mode
pop ax ; AX := MGL mode number
sub ax,grSVGA_800x600x16
mov cx,PartialInfoSize
mul cl
mov si,offset mode800x600x16
add si,ax
push es ; Save ES:DI
push di
mov ax,cs
mov ds,ax ; DS:SI -> correct mode info
mov es,ax
mov di,offset XRes ; ES:DI -> mode specific info
cld
rep movsb ; Copy the data across
pop di ; Restore ES:DI
pop es
; Copy the mode information across
mov si,offset ModeInfo ; DS:SI -> VGAInfo Table
mov cx,ModeInfoSize
rep movsb ; Copy the data across
pop [BytesPerLine] ; Restore bytes per line value
mov [Status],SUCCESS
popa
ret
; The video mode is invalid, but the underlying video BIOS may be VESA
; compatible, and the mode number may mean something to it, so we pass it
; on to it.
@@Invalid:
popa
mov ax,4F01h
pushf
call [OldInt10] ; Call the old BIOS
mov [Status],ax ; Save the status of the call
ret
ENDP SuperVGAModeInfo
;----------------------------------------------------------------------------
; SuperVGASetMode - Set SuperVGA Video Mode
;----------------------------------------------------------------------------
;
; Function to set a specific VESA SuperVGA video mode. Only graphics modes
; are supported by this TSR.
;
; Entry: BX - VESA video mode number (bit 15 means don't clear mem).
;
; Exit: AX - VESA status code.
;
;----------------------------------------------------------------------------
PROC SuperVGASetMode near
pusha ; Save register values
push es
mov cx,bx
and cl,07Fh
cmp cx,13h
ja @@VesaMode
; Attempting to set a standard VGA video mode, so convert the mode number
; into an MGL video mode number and skip the stuff below to set a
; VESA video mode.
push cx
push bx
push cs
pop es
mov di,offset VGAModes ; ES:DI -> list of VGA video modes
mov ax,cx
mov cx,12
repne scasw ; Search for entry
inc cx
shr cx,1
sub cx,6
neg cx ; CX := MGL mode number
mov [CntMode],cx
pop ax
pushf
call [OldInt10] ; Set the video mode
pop cx
jmp @@StandardVGAMode
@@VesaMode:
push bx ; Save VESA mode number for later
mov cx,bx
and ch,07Fh ; Clear memory clear bit
push cx
call VESAToMGLMode ; AX := internal MGL video mode
cmp ax,-1
jne @@1
pop bx
pop bx
jmp @@InvalidMode ; Video mode is invalid to us!
@@1: mov [CntMode],ax ; Save internal MGL video mode
mov bx,ax ; BX := current video mode
mov ax,[CntDriver] ; AX := current video driver
call loadSVGAMode ; AX,BX := correct value for Int 10h
pop cx ; CX := VESA mode number
and ch,80h ; isolate clear memory bit
jz @@SetMode ; Bit is not set, so simply set the mode
; Request was made to _not_ clear the video memory, so attempt to set the
; correct bit for the OEM video modes.
or bx,bx ; BX := 0, so AX := video mode number
jz @@SetAX
or bh,bh
jz @@SetBL
or bh,80h ; Set the memory clear bit
jmp @@SetMode
@@SetAX:
or al,80h ; Set the memory clear bit
jmp @@SetMode
@@SetBL:
or bl,80h ; Set the memory clear bit
@@SetMode:
pushf
call [OldInt10] ; Set the video mode
pop cx ; CX := VESA mode number
mov ax,40h
mov es,ax
cmp [BYTE es:49h],3 ; Mode is still text mode, did not set
jbe @@ModeSetFailed
@@StandardVGAMode:
mov [CntVESAMode],cx ; Save VESA mode now set
call SetupBanks
call [InitSVGA] ; Initialise bank switching on SuperVGA's
call SetupPaging
mov ax,[CntMode] ; AX := current video mode number
mov ebx,4096 shl 10 ; Compute with maximum video memory
call numPages ; Compute bytes per line value
mov [BytesPerLine],cx ; Save BytesPerLine value
; Determine the color resolution of the video mode and save for later
mov ax,[CntMode] ; AX := current MGL video mode
cmp ax,grVGA_320x200x256
je @@Colors256
cmp ax,grSVGA_1280x1024x16
jbe @@Colors16
cmp ax,grSVGA_1280x1024x256
jbe @@Colors256
cmp ax,grSVGA_1280x1024x32k
jbe @@Colors32k
mov [CntColors],gr16mColor
jmp @@Done
@@Colors16:
mov [CntColors],gr16Color
jmp @@Done
@@Colors256:
mov [CntColors],gr256Color
jmp @@Done
@@Colors32k:
mov [CntColors],gr32kColor
@@Done:
mov [CntStartX],0
mov [CntStartY],0
mov [Status],SUCCESS
@@ModeSetFailed:
pop es
popa
ret
; The mode number was invalid to us, but may make sense to an underlying
; VESA compatible BIOS.
@@InvalidMode:
pop es
popa
mov ax,4F02h
pushf
call [OldInt10] ; Call the old BIOS
mov [Status],ax ; Save the status value
mov [CntVESAMode],-1 ; Flag that mode is unknown to us!
ret
ENDP SuperVGASetMode
;----------------------------------------------------------------------------
; SuperVGAGetMode - Get Current SuperVGA Video Mode
;----------------------------------------------------------------------------
;
; Function to return the mode number of the current set video mode. If the
; mode is a normal VGA video mode, the normal mode number is returned,
; otherwise the VESA video mode number for the mode is returned.
;
; Exit: AX - VESA status code
; BX - Current video mode
;
;----------------------------------------------------------------------------
PROC SuperVGAGetMode near
push es
mov ax,40h
mov es,ax
xor bx,bx
mov bl,[BYTE es:49h]
cmp bl,13h
mov [Status],SUCCESS
jbe @@VGAMode
mov bx,[CntVESAMode] ; VESA Video mode is active, so return it
cmp bx,-1
jne @@VGAMode
; The mode was not know to us, so it may be an underlying VESA video mode.
mov ax,4F03h
pushf
call [OldInt10]
mov [Status],ax
@@VGAMode:
pop es
ret
ENDP SuperVGAGetMode
;----------------------------------------------------------------------------
; SuperVGAVideoState - Save/Restore SuperVGA video state
;----------------------------------------------------------------------------
;
; Function to save save/restore the SuperVGA video state. This function
; would be very tricky to implement for all supported SuperVGA's if we
; want to save the entire state. In order to do as best as job as possible,
; we save the state of the hardware as much as possible using the normal
; Video BIOS routines, along with the current video BIOS mode number. To
; restore the state we first reset the current video mode, then call the
; BIOS to reset the hardware state, which should work correctly for most
; SuperVGA situations.
;
; Entry: DL - Subfunction number
; 00h - Get state buffer size
; 01h - Save video state
; 02h - Restore video state
; ES:BX -> Video buffer to save state in
; CX - Flags for what to save
; bit 0 - Video hardware state
; bit 1 - Video BIOS state
; bit 2 - Video DAC state
; bit 3 - SuperVGA state
;
; Exit: AH - VESA Status code
; BX - Number of 64 byte blocks needed to save state
;
;----------------------------------------------------------------------------
PROC SuperVGAVideoState near
; First try calling the underlying video BIOS which may be VESA compatible.
pusha
pushf
call [OldInt10] ; Call the old BIOS
mov [Status],ax
popa
cmp [Status],SUCCESS
je @@Done ; Succeeded, we are all done!
; Otherwise try to do as much as possible with as little knowledge as
; possible.
push dx
push cx
mov ah,1Ch ; Save/Restore video state BIOS call
mov al,dl ; AL := subfunction number
pushf
call [OldInt10] ; Call the old BIOS
pop cx
pop dx
cmp al,1Ch
jne @@Failure
test cx,010b
jz @@Done
cmp dl,2
jne @@Done
; The Video BIOS state was saved, so call the BIOS to set the current
; video mode again, and then restore the video state once more to complete
; things.
push cx
push dx
push es
mov ax,40h
mov es,ax
xor ah,ah
mov al,[BYTE es:49h]
pushf
call [OldInt10] ; Set the old video mode
pop es
pop dx
pop cx
mov ah,1Ch
mov al,2
pushf
call [OldInt10] ; Restore video state again
@@Done:
mov [Status],SUCCESS
@@Failure:
ret
ENDP SuperVGAVideoState
;----------------------------------------------------------------------------
; SuperVGABankSwitch - CPU Video Memory Control
;----------------------------------------------------------------------------
;
; Function to switch video banks for the SuperVGA. This function can be
; called as a far function call, rather than through the Int 10h mechanism
; for speed.
;
; Entry: BH - Subfunction number
; 00h - Select video memory window
; 01h - Get video memory window
; BL - Window number
; 00h - Window A
; 01h - Window B
; DX - Window address in video memory (granularity units)
;
; Exit: AX - VESA status code.
; DX - Window address in video memory (when requested)
;
;----------------------------------------------------------------------------
PROC SuperVGABankSwitch far
pusha
or bh,bh
jnz @@Done ; Simply return the current window
mov ax,dx ; AX := bank number
or bl,bl
jnz @@WindowB
call [NewBank] ; Set new read/write bank
jmp @@Done
@@WindowB:
call [ReadBank] ; Set new read bank
@@Done:
popa
mov dx,[CurBank] ; Return the current bank number
mov [Status],SUCCESS
mov ax,SUCCESS
ret
ENDP SuperVGABankSwitch
;----------------------------------------------------------------------------
; SuperVGAScanlineWidth - Get/Set Logical Scanline Length
;----------------------------------------------------------------------------
;
; Function to get/set the logical scanline length. This value is specified
; in pixels, but may require rounding to the next available value. The
; actual value set will be returned.
;
; Entry: BL - Subfunction number
; 00h - Set scanline length
; 01h - Get scanline length
; CX - Desired scanline length in pixels
;
; Exit: AX - VESA status code
; BX - Bytes per scanline
; CX - Pixels per scanline
; DX - Maximum number of scanlines
;
;----------------------------------------------------------------------------
PROC SuperVGAScanlineLength near
pusha
mov ax,[CntColors]
mov [Status],SUCCESS
or bh,bh
jnz @@GetScanlineLength
; We are attempting to set the scanline width for the mode. First we need
; to adjust the value into bytes, and then set the CRTC offset register
cmp ax,gr16Color
je @@Colors16
cmp ax,gr256Color
je @@SetOffsetReg
cmp ax,gr32kColor
je @@Colors32k
mov ax,cx
shl cx,1
add cx,ax ; CX := bytes per scanline
and cx,0FFF8h ; Mask off bottom three bits
mov [BytesPerLine],cx ; Save BytesPerLine value
shr cx,3 ; Shift value for offset register
jmp @@SetOffsetReg
@@Colors16:
shr cx,3
and cx,0FFF0h ; Mask off bottom four bits
mov [BytesPerLine],cx ; Save BytesPerLine value
shr cx,4 ; Shift value for offset register
jmp @@SetOffsetReg ; CX := bytes per scanline
@@Colors256:
and cx,0FFF8h ; Mask off bottom three bits
mov [BytesPerLine],cx ; Save BytesPerLine value
shr cx,3 ; Shift value for offset register
jmp @@SetOffsetReg
@@Colors32k:
shl cx,1
and cx,0FFF8h ; Mask off bottom three bits
mov [BytesPerLine],cx ; Save BytesPerLine value
shr cx,3 ; Shift value for offset register
@@SetOffsetReg:
mov dx,CRTC
mov ah,cl
mov al,13h
out dx,ax ; Program the CRTC offset value
; Now return the scanline length
@@GetScanlineLength:
popa
mov bx,[BytesPerLine] ; BX := bytes per scanline
cmp ax,gr16Color
je @@GetColors16
cmp ax,gr256Color
je @@GetColors256
cmp ax,gr32kColor
je @@GetColors32k
mov ax,cx
shr cx,1
sub cx,ax ; CX := pixels per scanline
ret
@@GetColors16:
shl cx,3 ; CX := pixels per scanline
ret
@@GetColors256:
ret
@@GetColors32k:
shr cx,1 ; CX := pixels per scanline
ret
ENDP SuperVGAScanlineLength
;----------------------------------------------------------------------------
; SuperVGADisplayStart - Get/Set Display Start
;----------------------------------------------------------------------------
;
; Set the display start address for the current SuperVGA video mode.
;
; Entry: BH - 00h
; BL - Subfunction number
; 00h - Set display start
; 01h - Get display start
; CX - Leftmost displayed pixel in scanline
; DX - First displayed scanline
;
; Exit: CX - Leftmost displayed pixel in scanline
; DX - First displayed scanline
;
;----------------------------------------------------------------------------
PROC SuperVGADisplayStart
cmp [NewPage],offset NONE_page
je @@Failure
pusha
or bh,bh
jnz @@GetDisplayStart
; Set the starting display address.
xor eax,eax
and edx,0FFFFh ; EDX := first scanline
and ecx,0FFFFh ; ECX := leftmost pixel
mov ax,[BytesPerLine]
mul edx ; EAX := y * bytesPerLine
mov bx,[CntColors]
cmp bx,gr16Color
je @@Colors16
cmp bx,gr256Color
je @@Colors256
cmp bx,gr32kColor
je @@Colors32k
; Video mode is a 24 bit video mode
add eax,ecx ; EAX := x + y * bytesPerLine
shl ecx,1
add eax,ecx ; EAX := x * 3 + y * bytesPerLine
shr eax,2 ; Adjust to lie on plane boundary
jmp @@SetDisplayStart
; Video mode is a 16 color video mode
@@Colors16:
shr ecx,3
add eax,ecx ; EAX := x/8 + y * bytesPerLine
jmp @@SetDisplayStart
; Video mode is a 256 color video mode
@@Colors256:
add eax,ecx ; EAX := x + y * bytesPerLine
shr eax,2 ; Adjust to lie on plane boundary
jmp @@SetDisplayStart
; Video mode is a 32k color video mode
@@Colors32k:
shl ecx,1
add eax,ecx ; EAX := x + y * bytesPerLine
shr eax,2 ; Adjust to lie on plane boundary
@@SetDisplayStart:
mov cl,0Ch ; CL := Start Address High register
mov ch,ah ; CH := high byte of new address
mov bh,al ; BH := low byte of new address
mov bl,0Dh ; BL := Start Address Low register
shr eax,16
mov si,ax ; SI := Bits 16+ for SuperVGA's
call [NewPage] ; Program the start address
mov [CntStartX],cx ; Save the display starting coordinates
mov [CntStartY],dx
mov [Status],SUCCESS
popa
ret
@@GetDisplayStart:
popa
mov cx,[CntStartX] ; Return saved starting coordinates
mov dx,[CntStartY]
mov [Status],SUCCESS
@@Failure:
ret
ENDP SuperVGADisplayStart
;----------------------------------------------------------------------------
; VESAToMGLMode - Converts a VESA mode number to an MGL mode number
;----------------------------------------------------------------------------
;
; Internal routine to convert a VESA mode number to an MGL mode number.
; MGL Mode numbers are the ones that we use internally, since the code is
; based on that from the MegaGraph graphics library.
;
; Entry: CX - VESA mode number
;
; Exit: AX - MGL mode number (-1 if not found)
;
; Registers: AX,CX
;
;----------------------------------------------------------------------------
PROC VESAToMGLMode near
push bx
push ds
push si
push di
; First check to ensure that the VESA mode number is valid for the currently
; installed SuperVGA adapter.
push cs
pop ds
mov si,offset ModeTable ; DS:SI -> Valid VESA mode table
@@VESALoop:
lodsw ; Load next valid VESA mode number
cmp ax,-1
je @@InvalidMode ; Hit the end of the table
cmp ax,cx ; Is this the one?
je @@ValidMode ; Yes, so mode is valid
jmp @@VesaLoop ; No, so keep looking...
; Convert the VESA mode number to the MGL mode number by searching the
; conversion table.
@@ValidMode:
mov si,offset VesaModes ; DS:SI -> VESA/MGL mode table
@@ModeLoop:
lodsw ; AX := VESA mode number
or ax,ax
jz @@InvalidMode ; Exit if mode is invalid
mov bx,ax ; BX := VESA mode number
lodsw ; AX := MGL mode number
cmp bx,cx ; Found the video mode?
je @@Exit ; Yes, found the mode...
jmp @@ModeLoop
@@InvalidMode:
mov ax,-1 ; Video mode not found
@@Exit:
pop di
pop si
pop ds
pop bx
ret
ENDP VESAToMGLMode
EndResident: ; End of resident code
;----------------------------------------------------------------------------
; Transient Code.
;----------------------------------------------------------------------------
ASSUME cs:uvesa_TEXT, ds:DGROUP, es:NOTHING
;----------------------------------------------------------------------------
; bool isLoaded(void)
;----------------------------------------------------------------------------
; Returns true if the Universal VESA TSR is already loaded in memory.
;----------------------------------------------------------------------------
procstart _isLoaded
enter 0,0
push ds
GetVector 10h ; ES:BX -> Current INT10h vector
mov di,bx
sub di,offset Int10ISR - offset Signature
; ES:DI -> Signature in loaded TSR
push cs
pop ds
mov si,offset Signature ; DS:SI -> Signature in .COM file
mov cx,SigLen ; CX := length of signature string
cld
mov ax,1 ; Assume already loaded
repe cmpsb
jcxz @@AlreadyLoaded ; Driver is already loaded!
xor ax,ax ; Driver is not loaded
@@AlreadyLoaded:
pop ds
leave
ret
procend _isLoaded
;----------------------------------------------------------------------------
; void goTSR(int driver,int chipID,int memory,int dac)
;----------------------------------------------------------------------------
;
; This routine installs the VESA driver for the specified SuperVGA
; configuration, and exits to the operating system leaving the required
; code resident in memory.
;
; If we are in testing mode, the routine does not go TSR but simply
; calls the 'C' testing routine, unhooks the interrupts and exits.
;
; Registers: all
;
;----------------------------------------------------------------------------
procstart _goTSR
ARG driver:WORD, chipID:WORD, memory:WORD, dac:WORD
enter 0,0
; Store the values for the SuperVGA configuration.
mov ax,[driver]
mov [CntDriver],ax
mov ax,[chipID]
mov [CntChipID],ax
mov ax,[memory]
mov [CntMemory],ax
mov ax,[dac]
mov [CntDac],ax
; Now determine the list of available video modes for this adapter.
push [CntMemory]
push [CntDriver]
call _MGL_availableModes ; Determine available video modes
add sp,4
push ds
mov ds,dx
mov si,ax ; DS:SI -> MGL video mode table
push cs
pop es
mov di,offset ModeTable ; ES:DI -> Video Mode Table
mov bx,offset VesaModes ; CS:BX -> All VESA Modes
@@ModeLoop:
mov cx,[cs:bx] ; CX := VESA Mode Number
jcxz @@DoneModes ; Quit when table exhausted
mov dx,[cs:bx+2] ; DX := MGL Mode Number
add bx,4 ; CS:BX -> next mode in table
push si ; Save start of MGL mode table
@@FindMode:
lodsw ; AX := MGL video mode number
cmp ax,-1
je @@NotFound ; Mode was not found
cmp ax,dx
je @@Found ; Mode number was found
jmp @@FindMode ; Continue till mode is found
@@Found:
mov ax,cx
stosw ; Store the appropriate mode number
@@NotFound:
pop si ; DS:SI -> MGL video mode table
jmp @@ModeLoop ; Continue till table exhausted
; Setup the bank switching and page flipping code, and determine if dual
; banking is supported, modifying the video mode information table if
; not.
@@DoneModes:
mov ax,0FFFFh
stosw ; Terminate the mode list
pop ds ; Restore DS
call SetupBanks ; Setup bank switching
call [InitSVGA] ; Initialise SuperVGA code
call SetupPaging ; Setup page flipping
cmp [TwoBanks],true
je @@DualBank
mov [WinBAttr],0 ; Remove support for second video bank
@@DualBank:
call HookVectors ; Hook interrupt vectors
ifndef TESTING
; Now setup to go TSR with resident code.
mov ah,31h
xor al,al
mov dx,offset EndResident
add dx,PSPSize + 15 ; PSP is always resident!!
shr dx,4
int 21h ; Go TSR!
else
; Call the C testing routine, unhook vectors and quit.
call _testISR ; Call the test routine
call UnhookVectors ; Unhook vectors
mov ah,04Ch
mov al,1 ; Error code of 1
int 21h ; Exit to DOS
endif
procend _goTSR
;----------------------------------------------------------------------------
; HookVectors - Hook into the interrupt vectors that we require.
;----------------------------------------------------------------------------
;
; Saves the value of the old interrupt vectors that we require, and
; install's hooks to our code for the vectors.
;
; Registers: all
;
;----------------------------------------------------------------------------
PROC HookVectors near
; Save old interrupt vectors
GetVector 10h
mov [cs:OldInt10Off],bx
mov [cs:OldInt10Seg],es
; Insert our interrupt vectors into vector table
SetVector 10h, Int10ISR
ret
ENDP HookVectors
;----------------------------------------------------------------------------
; UnhookVectors - Unhook from all interrupt vectors that we own.
;----------------------------------------------------------------------------
;
; Restores the interrupt vector table to what it was before we installed
; ourselves.
;
; Registers: all
;
;----------------------------------------------------------------------------
PROC UnhookVectors
push ds
mov dx,[OldInt10Seg]
mov ds,dx
mov dx,[OldInt10Off]
mov ah,25h
mov al,10h
int 21h
pop ds
ret
ENDP UnhookVectors
endcodeseg uvesa
END