home *** CD-ROM | disk | FTP | other *** search
- ;****************************************************************************
- ;*
- ;* 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
-