Metropoli BBS
VIEWER: detectgr.asm MODE: TEXT (ASCII)
;****************************************************************************
;*
;*						MegaGraph Graphics Library
;*
;*                  Copyright (C) 1993 Kendall Bennett.
;*							All rights reserved.
;*
;* Filename:	$RCSfile: detectgr.asm $
;* Version:		$Revision: 1.2 $
;*
;* Language:	80386 Assembler
;* Environment:	IBM PC (MS DOS)
;*
;* Description:	This module contains the auto detection routines to detect
;*				the presence of all the standard graphics adapters
;*				supported by the MegaGraph graphics library.
;*
;* $Id: detectgr.asm 1.2 1993/03/07 04:03:22 kjb Exp $
;*
;* Revision History:
;* -----------------
;*
;* $Log: detectgr.asm $
;* Revision 1.2  1993/03/07  04:03:22  kjb
;* Numerous bug fixes and enhancements.
;*
;* Revision 1.1  1993/03/03  10:45:16  kjb
;* Initial revision
;*
;****************************************************************************

		IDEAL
		JUMPS					; Fix jumps out of range
		P386					; Use 80386 instructions

INCLUDE "model.mac"				; Memory model macros

header	detectgr				; Set up memory model

;****************************************************************************
;
; Equates used by detectgraph routine.
;
;****************************************************************************

CRTC		EQU	3D4h			; Port of CRTC registers

INCLUDE	"MGRAPH.EQU"			; Include equates for Mgraph routines

begdataseg	detectgr

INCLUDE	"MGRAPH.VAR"			; Include variable references

enddataseg	detectgr

begcodeseg	detectgr			; Start of code segment

;****************************************************************************
;
; Global variables used by detectgraph routines.
;
;****************************************************************************

SaveDS			dw	?			; Place to save the value of DS register

VesaBuf			db	256 dup (?)	; VESA Video information block
VideoChipID		dw	0			; Internal SuperVGA chip ID
VideoMem		dw	256			; Size of video memory (kb)
VideoModes		dw	DefModes	; Pointer to list of available SuperVGA
PageFlip		dw	false		; True if page flipping is available
								; Video modes.
DacType			dw	grVGADAC	; Video DAC type
ForceDAC		dw	0			; Value to force dac with
old				db	0			; Scratch place to store values

;****************************************************************************
;
; Initialised data used by the detectgraph routines.
;
;****************************************************************************

; Delimited list of video modes for all supported video cards. This list
; may need to be modified depending on display memory restrictions etc.
;
; During chip identification, it may be found that the chipset detected
; does not support all of the specified modes. In this case, the
; unsupported video modes should be set to a zero (use the UnsupportedMode
; routine for this).
;
; HiColor and TrueColor modes should be specified after the particular
; chip in question. If the appropriate DAC is detected, a zero should
; be used to replace the -1 delimiter to add the list of HiColor or
; TrueColor video modes.

DefModes:		db	-1

AheadModes:		db	grSVGA_800x600x16,grSVGA_1024x768x16
				db	grSVGA_640x400x256,grSVGA_640x480x256
				db	grSVGA_800x600x256,grSVGA_1024x768x256,-1

ATIModes:		db	grSVGA_800x600x16,grSVGA_1024x768x16
				db	grSVGA_640x400x256,grSVGA_640x480x256
				db	grSVGA_800x600x256,grSVGA_1024x768x256
ATI32KModes:	db	-1,grSVGA_640x480x32k,grSVGA_800x600x32k,-1

ChipsModes:		db	grSVGA_800x600x16,grSVGA_1024x768x16
				db	grSVGA_640x400x256,grSVGA_640x480x256
				db	grSVGA_800x600x256,grSVGA_1024x768x256,-1

EverexModes:	db	grSVGA_800x600x16,grSVGA_1024x768x16,grSVGA_1280x1024x16
				db	grSVGA_640x350x256,grSVGA_640x400x256
				db	grSVGA_640x480x256,grSVGA_800x600x256
				db	grSVGA_1024x768x256
Everex32KModes:	db	-1,grSVGA_320x200x32k,grSVGA_640x480x32k
EverexTCModes:	db	-1,grSVGA_640x480x16m,-1

GenoaModes:		db	grSVGA_800x600x16,grSVGA_1024x768x16
				db	grSVGA_640x350x256,grSVGA_640x400x256
				db	grSVGA_640x480x256,grSVGA_800x600x256,-1

OAKModes:		db	grSVGA_800x600x16,grSVGA_1024x768x16
				db	grSVGA_640x480x256,grSVGA_800x600x256
				db	grSVGA_1024x768x256
OAK32KModes:	db	-1,grSVGA_640x400x32k,grSVGA_640x480x32k,-1

ParadiseModes:	db	grSVGA_800x600x16,grSVGA_1024x768x16,grSVGA_1280x1024x16
				db	grSVGA_640x400x256,grSVGA_640x480x256
				db	grSVGA_800x600x256,grSVGA_1024x768x256
Parad32KModes:	db	-1,grSVGA_640x480x32k,grSVGA_800x600x32k,-1

Trident88Modes:	db	grSVGA_800x600x16,grSVGA_1024x768x16
				db	grSVGA_640x400x256,grSVGA_640x480x256,-1

Trident89Modes:	db	grSVGA_800x600x16,grSVGA_1024x768x16
				db	grSVGA_640x400x256,grSVGA_640x480x256
				db	grSVGA_800x600x256,grSVGA_1024x768x256,-1

Video7Modes:	db	grSVGA_800x600x16,grSVGA_1024x768x16
				db	grSVGA_640x400x256,grSVGA_640x480x256
				db	grSVGA_800x600x256,grSVGA_1024x768x256,-1

ET3000Modes:	db	grSVGA_800x600x16,grSVGA_1024x768x16
				db	grSVGA_640x350x256,grSVGA_640x480x256
				db	grSVGA_800x600x256,-1

ET4000Modes:	db	grSVGA_800x600x16,grSVGA_1024x768x16,grSVGA_1280x1024x16
				db	grSVGA_640x350x256,grSVGA_640x400x256
				db	grSVGA_640x480x256,grSVGA_800x600x256
				db	grSVGA_1024x768x256
ET400032KModes:	db	-1,grSVGA_320x200x32k,grSVGA_640x350x32k
				db	grSVGA_640x400x32k,grSVGA_640x480x32k,grSVGA_800x600x32k
ET4000TCModes:	db	-1,grSVGA_640x350x16m,grSVGA_640x400x16m
				db	grSVGA_640x480x16m,-1

NCRModes:		db	grSVGA_800x600x16,grSVGA_1024x768x16,grSVGA_1280x1024x16
				db	grSVGA_640x400x256,grSVGA_640x480x256
				db	grSVGA_800x600x256,grSVGA_1024x768x256
				db	grSVGA_1280x1024x256
NCR32KModes:	db	-1,grSVGA_640x480x32k,grSVGA_800x600x32k,-1

S3Modes:		db	grSVGA_800x600x16,grSVGA_1024x768x16
				db	grSVGA_640x480x256,grSVGA_800x600x256
				db  grSVGA_1024x768x256
S332KModes:		db	-1,grSVGA_640x480x32k,-1
S3TCModes:		db	-1

CirrusModes:	db	grSVGA_800x600x16,grSVGA_1024x768x16,grSVGA_1280x1024x16
				db	grSVGA_640x480x256,grSVGA_800x600x256
				db	grSVGA_1024x768x256
Cirrus32kModes:	db	-1,grSVGA_640x480x32k,grSVGA_800x600x32k,-1
CirrusTCModes:	db	-1,grSVGA_320x200x16m,grSVGA_640x480x16m,-1

AcuMosModes:	db	grSVGA_800x600x16,grSVGA_1024x768x16
				db	grSVGA_640x400x256,grSVGA_640x480x256
				db	grSVGA_800x600x256,-1

AL2101Modes:	db  grSVGA_800x600x16,grSVGA_1024x768x16,grSVGA_1280x1024x16
				db	grSVGA_640x400x256,grSVGA_640x480x256
				db	grSVGA_800x600x256,grSVGA_1024x768x256
				db	grSVGA_1280x1024x256,-1

MXICModes:		db	grSVGA_800x600x16,grSVGA_1024x768x16
				db	grSVGA_640x350x256,grSVGA_640x400x256
				db	grSVGA_640x480x256,grSVGA_800x600x256
				db	grSVGA_1024x768x256,-1

P2000Modes:		db  grSVGA_800x600x16,grSVGA_1024x768x16,grSVGA_1280x1024x16
				db	grSVGA_640x400x256,grSVGA_640x480x256
				db	grSVGA_800x600x256,grSVGA_1024x768x256
				db	grSVGA_1280x1024x256
P200032KModes:	db	-1,grSVGA_640x350x32k,grSVGA_640x400x32k
				db	grSVGA_640x480x32k,grSVGA_800x600x32k,-1

RT3106Modes:	db  grSVGA_800x600x16,grSVGA_1024x768x16,grSVGA_1280x1024x16
				db	grSVGA_640x400x256,grSVGA_640x480x256
				db	grSVGA_800x600x256,grSVGA_1024x768x256
				db	grSVGA_1280x1024x256,-1

VesaModes:		db	20 dup (-1)

; Table to translate EGA display types

EGADisplays		db	grEGA,grEGA_640x200x16	; 0000b,0001b CGA Display
				db	grEGA,grEGA_640x350x16	; 0010b,0011b EGA Display
				db	grEGAMONO,0				; 0100b,0101b MDA Display
				db	grEGA,grEGA_640x200x16	; 0110b,0111b CGA Display
				db	grEGA,grEGA_640x350x16	; 1000b,1001b EGA Display
				db	grEGAMONO,0				; 1010b,1011b MDA Display

; Table of possible VESA video mode numbers and display memory required
; rounded up to the nearest half megabyte or megabyte depending on
; resolution. Cards generally have 256k, 512k, 1M, 2M or 4M on board.

AllVesaModes:	dw	100h, 256,  grSVGA_640x400x256
				dw	101h, 512,  grSVGA_640x480x256
				dw	102h, 256,  grSVGA_800x600x16
				dw	103h, 512,  grSVGA_800x600x256
				dw	104h, 512,  grSVGA_1024x768x16
				dw	105h, 1024, grSVGA_1024x768x256
				dw	106h, 1024, grSVGA_1280x1024x16
				dw	107h, 2048, grSVGA_1280x1024x256
				dw	10Dh, 256,  grSVGA_320x200x32k
				dw	10Fh, 256,  grSVGA_320x200x16m
				dw	110h, 1024, grSVGA_640x480x32k
				dw	112h, 1024, grSVGA_640x480x16m
				dw	113h, 1024, grSVGA_800x600x32k
				dw	115h, 2048, grSVGA_800x600x16m
				dw	116h, 2048, grSVGA_1024x768x32k
				dw	118h, 4096, grSVGA_1024x768x16m
				dw	119h, 4096, grSVGA_1280x1024x32k
				dw	11Bh, 4096, grSVGA_1280x1024x16m
				dw	0

;****************************************************************************
;
; Set of macros to make the following code more readable, but probably
; less efficient. Efficiency here is not a major concern, but correctness
; definately is :-).
;
;****************************************************************************

MACRO	check	boardName
		call	Find&boardName		; Check for a particular SuperVGA card
		jc		@@FoundOne
ENDM

; Macro to add the HiColor video modes for this video card to the mode
; table.

MACRO	Add32kColor	ModeTable
		local	NoHiColor
		cmp		[DacType],grHCDAC
		jl		NoHiColor
		mov		bx,offset ModeTable
		mov		[BYTE cs:bx],0		; Clear the -1 termination flag
NoHiColor:
ENDM

; Macro to add the TrueColor video modes for this video card to the mode
; table.

MACRO	AddTrueColor	ModeTable
		local	NoTrueColor
		cmp		[DacType],grTCDAC
		jl		NoTrueColor
		mov		bx,offset ModeTable
		mov		[BYTE cs:bx],0		; Clear the -1 termination flag
NoTrueColor:
ENDM

MACRO	ClearMode	Mode, ModeTable
		mov		al,Mode
		mov		bx,offset ModeTable
		call	UnsupportedMode		; Clear the unsupported video mode
ENDM

INCLUDE	"SV_PORTS.ASM"
INCLUDE "SV_MAXPG.ASM"

;----------------------------------------------------------------------------
; void MGL_detectGraph(int far *graphdriver,int far *chipID,int far *memory,
;	int far *dac,int far *graphmode);
;----------------------------------------------------------------------------
; Autodetects the standard graphics adapters supported by the MegaGraph
; graphics library.
;----------------------------------------------------------------------------
procstart	_MGL_detectGraph

		ARG		driver:DWORD, chipID:DWORD, memory:DWORD, dac:DWORD,	\
				mode:DWORD

		enter	0,0
		pusha
		push	ds

		mov		ax,DGROUP		; Save data segment for later use
		mov		[cs:SaveDS],ax

		lds		si,[dac]
		mov		ax,[si]
		mov		[ForceDAC],ax	; Save value of forced dac type

		lds		di,[driver]		; Load the address of driver in DS:DI
		les		si,[mode]		; Load the address of mode in ES:SI

		push	ds
		mov		ds,[cs:SaveDS]	; Address data segment
		mov		[__grResult],grOK
		pop		ds

; Look for the various subsystems using the subroutines in the order of
; highest performance first. Ie: look for PS/2's then EGA, CGA, then
; hercules monochrome.

		call	FindPS2			; Is an MCGA or VGA out there?
		jc		@@Exit
		call	FindEGA			; Is an EGA out there?
		jc		@@Exit
		call	FindCGA			; Is a CGA out there?
		jc		@@Exit
		call	FindHGC			; Is a Hercules out there?
		jc		@@Exit

		push	ds
		mov		ds,[cs:SaveDS]	; Address data segment
		mov		[__grResult],grNotDetected
		pop		ds

@@Exit:
		lds		si,[chipID]		; Load the address of chip ID in DS:SI
		mov		ax,[VideoChipID]; AX := value of internal chip ID
		mov		[si],ax			; Store the chip ID value
		lds		si,[memory]
		mov		ax,[VideoMem]
		mov		[si],ax
		lds		si,[dac]
		mov		ax,[DacType]
		mov		[si],ax			; Store dac type
		pop		ds
		popa
		leave
		ret

procend		_MGL_detectGraph

;----------------------------------------------------------------------------
; char far * _getSuperVGAModes(void)
;----------------------------------------------------------------------------
; Returns the address of the list of available video modes.
;----------------------------------------------------------------------------
procstart	__getSuperVGAModes

		mov		dx,seg DefModes
		mov		ax,[WORD VideoModes]
		ret

procend		__getSuperVGAModes

;----------------------------------------------------------------------------
; int _getSuperVGAPages(int mode,int memory,long *pagesize)
;----------------------------------------------------------------------------
; Returns the number of available video pages for a specific video mode.
; It also returns the size in bytes of each video page (rounded to the
; nearest bank value).
;----------------------------------------------------------------------------
procstart	__getSuperVGAPages

		ARG		mode:WORD, memory:WORD, pagesize:DWORD

		enter	0,0
		push	di

		mov		ax,[mode]
		mov		cx,ax
		and		ax,7Fh
		xor		ebx,ebx
		mov		bx,[memory]
		test	cx,80h
		jnz		@@ExtendedPageFlip
		cmp		[PageFlip],true
		je		@@ExtendedPageFlip

; Extended page flipping is not available, so calculate pages using only
; 256k of memory.

		cmp		ax,grVGA_320x200x256
		jl		@@VGAMode
		mov		ax,1
		jmp		@@Done

@@VGAMode:
		mov		bx,256

@@ExtendedPageFlip:
		shl		ebx,10
		call    numPages
		les		di,[pagesize]
		mov		[es:di],ebx			; Store the page size for later

@@Done:
		pop		di
		leave
		ret

procend		__getSuperVGAPages

;****************************************************************************
;
; Internal routines used by the detectgraph routine.
;
;****************************************************************************

;----------------------------------------------------------------------------
; FindPS2	Determine if a PS2 is out there, and get susbsystem types
;----------------------------------------------------------------------------
;
; Routine calls INT10h function 1Ah to determine the video BIOS
; Display Combination Code (DCC) for each video subsystem. If the
; PS2 BIOS is not out there, then none of the regs are changed. If
; it is out there, then 1Ah comes back in AL. If there is a PS/2 BIOS, we
; only use it to detect the VGA and MCGA adapters.
;
; Entry:		DS:DI	->	Address of driver variable
;				ES:SI	->	Address of mode variable
;
; Exit:			Carry flag is set if an MCGA,VGA,SVGA was detected
;
; Registers:	AX,BX,CX
;
;----------------------------------------------------------------------------
PROC	FindPS2 near

		mov		ax,1A00h        ; call video BIOS for info
		int		10h

		cmp		al,1Ah			; Is the BIOS out there (1Ah in AL)
		clc
		jne		@@Exit

; Determine if VGA,MCGA,SVGA present from BIOS DCC's

		mov		cl,bh			; BL := active subsystem, BH := inactive
		xor		bh,bh			; BX := DCC of active subsystem
		xor		ch,ch			; CX := DCC of inactive subsystem

		cmp		bx,07h			; Active VGA Mono?
		je		@@VGA
		cmp		cx,07h			; Inactive VGA Mono?
		je		@@VGA
		cmp		bx,08h			; Active VGA Color?
		je		@@VGA
		cmp		cx,08h			; Inactive VGA Color?
		jne		@@CheckMCGA
@@VGA:
		mov		[WORD DS:DI],grVGA
		mov		[WORD ES:SI],grVGA_640x480x16

		push	ds
		mov		ds,[cs:SaveDS]	; Address data segment
		cmp		[__ignoreSVGA],1
		pop		ds
		je		@@SkipSVGA

		call	FindSuperVGA	; Check to see if a SuperVGA is out there

@@SkipSVGA:
		stc     				; We at least found a VGA card
		jmp		@@Exit

@@CheckMCGA:
		cmp		bx,0Ch			; Active MCGA color?
		je		@@MCGA
		cmp		cx,0Ch			; Inactive MCGA color?
		clc
		jne		@@Exit

@@MCGA:
		mov		[WORD DS:DI],grMCGA
		mov		[WORD DS:SI],grVGA_320x200x256
		stc						; Set the carry flag

@@Exit:
		ret

ENDP	FindPS2

;----------------------------------------------------------------------------
; FindEGA	Determine if an EGA is out there and get system configuration
;----------------------------------------------------------------------------
;
; Routine calls INT10h function 12h to get the EGA BIOS to return system
; configuration info. If the EGA BIOS is not there, then the regs return
; unscathed. Specifically, if BH changes, then the EGA is out there.
;
; Entry:		DS:DI	->	Address of driver variable
;				ES:SI	->	Address of mode variable
;
; Exit:			Carry flag set if an EGA was detected
;
; Registers:	AX,BX,CX
;
;----------------------------------------------------------------------------
PROC	FindEGA near

		mov		bl,10h			; BL := 10h (return ega info)
		mov		ah,12h			; AH := INT10h function number
		int		10h				; Call EGA BIOS for info.
								; If EGA is present, BL <> 10h and
								; CL = EGA switch settings
		cmp		bl,10h
		clc
		je		@@Exit			; jump if EGA BIOS not present

		and		bl,3			; Mask out the Video Ram bits
		push	bx				; Save Video Ram bits on stack

		mov		al,cl			; AL := configuration switches
		xor		ah,ah			; AX := configuration switches
		and		al,11111110b	; Mask bit 1
		mov		bx,offset cs:EGADisplays
		add		bx,ax			; Index into table
		xor		ah,ah
		mov		al,[cs:bx]		; Translate code
		mov		[WORD DS:DI],ax
		mov		al,[cs:bx + 1]
		mov		[WORD ES:SI],ax

		pop		cx				; Restore Video Ram Bits
		or		cx,cx			; 64kb of EGA RAM?
		stc
		jne		@@Exit			; We are done...
		inc		[WORD DS:DI]	; Convert to EGA64 and EGA64MONO
		stc

@@Exit:
		ret

ENDP	FindEGA

;----------------------------------------------------------------------------
; FindCGA	Determine if a CGA adapter is out there and get info
;----------------------------------------------------------------------------
;
; Routine checks for a CGA by looking for the CGA's 6845 CRTC at I/O port
; 3D4h.
;
; Entry:		DS:DI	->	Address of driver variable
;				ES:SI	->	Address of mode variable
;
; Exit:			Carry flag set if a CGA was detected
;
; Registers:	AX,BX,CX,DX
;
;----------------------------------------------------------------------------
PROC	FindCGA		near

		mov		dx,3D4h			; DX := CRTC address port
		call	Find6845
		jnc		@@Exit

		mov		[WORD DS:DI],grCGA
		mov		[WORD ES:SI],0
		stc						; Set carry flag

@@Exit:
		ret

ENDP	FindCGA

;----------------------------------------------------------------------------
; FindHGC	Determine if a Hercules card is out there.
;----------------------------------------------------------------------------
;
; This is done by looking for the MDA's 6845 CRTC at I/O port 3B4h. If
; a 6845 is found, the subroutine distinguishes between an MDA and a
; Hercules adapter by monitoring bit 7 of the CRT Staus byte. This bit
; changes on Hercules adapters but does not change on an MDA.
;
; Entry:		DS:DI	->	Address of driver variable
;				ES:SI	->	Address of mode variable
;
; Exit:			Carry flag set if an HGC was detected
;
; Registers:	AX,BX,CX,DX
;
;----------------------------------------------------------------------------
PROC	FindHGC	near

		mov		dx,3B4h			; DX := CRTC address port
		call	Find6845
		jnc		@@Exit			; jump if not present

		mov		dx,3BAh			; DX := 3BAh (Status port)
		in		al,dx
		and		al,80h
		mov		ah,al			; AH := bit 7 (Vertical sync on HGC)
		mov		cx,8000h		; do this 32768 times

@@WaitForChange:
		in		al,dx
		and		al,80h			; isolate bit 7
		cmp		ah,al
		loope	@@WaitForChange	; wait for bit 7 to change

		clc
		je		@@Exit			; if bit 7 didn't change, it's an MDA

		mov		[WORD DS:DI],grHERCMONO
		mov		[WORD ES:SI],0
		stc

@@Exit:
		ret

ENDP	FindHGC

;----------------------------------------------------------------------------
; FindDAC	Routine to detect the presence of HiColor and TrueColor DAC's
;----------------------------------------------------------------------------
;
; This routine attempts to determine the type of RAM dac installed in the
; video card. This can be used by the following detection routines to
; determine if HiColor or TrueColor video mode support should be included
; in the video mode tables.
;
; Exit:			DacType updated with Video DAC type
;
; Registers:	AX,BX,CX,DX
;
;----------------------------------------------------------------------------
PROC	FindDAC

		push	si
		push	di

; Test for the SS24 TrueColor DAC first.

		DacToPel
		in		al,dx				; Wait for the same value twice
@@L1:	mov		bl,al
		in		al,dx
		cmp		al,bl
		jne		@@L1
		DacToCommand
		cmp		al,8Eh
		je		@@HaveSS24			; We have an SS24 TrueColor DAC
		mov		cx,8
@@L2:	in		al,dx
		cmp		al,8Eh
		je		@@HaveSS24			; Found an SS24 TrueColor DAC
		loop	@@L2

; Save the state of the command and PEL registers

		DacToCommand
		in		al,dx
		mov		si,ax				; SI := Old value of command register
		DacToPel
		in		al,dx
		mov		di,ax				; DI := Old value of PEL register

		mov		ax,si
		xor		al,0FFh				; AL := old command reg XOR FFh
		mov		bl,al				; Save value in BL
		out		dx,al				; Write value to PEL register
		DacToCommand
		in		al,dx				; Read value of command register
		cmp		al,bl				; If value are the same, Normal DAC
		je		@@NormalDAC			; Normal DAC, so reset PEL reg and exit

; We have a HiColor or TrueColor DAC of some type, so figure out what
; sort it is.

		DacToCommand
		mov		ax,si
		xor		al,60h				; AL := Old command reg XOR 60h
		mov		bl,al				; Save value in BL
		out		dx,al				; Write to command register
		DacToCommand
		in		al,dx
		and		al,0E0h
		and		bl,0E0h
		cmp		al,bl
		jne		@@HaveHiColor		; Found an SC11486 HiColor DAC

		in		al,dx
		mov		bl,al
		DacToPel
		in		al,dx
		cmp		al,bl
		je		@@HaveTrueColor		; Must be an ATT 20c491/2 or some other DAC

; Fall through for Sierra 32k/64k DAC's

@@HaveHiColor:
		mov		ax,grHCDAC			; DAC is HiColor
		mov		[DacType],ax
		jmp		@@ResetCommand

@@HaveTrueColor:
		mov		ax,grTCDAC			; DAC is TrueColor
		mov		[DacType],ax

@@ResetCommand:
		DacToCommand
		mov		ax,si				; AL := Old value of command register
		out		dx,al

@@NormalDAC:
		DacToPel
		mov		ax,di				; AL := Old value of PEL register
		out		dx,al				; Reset to old value
		jmp		@@Exit

@@HaveSS24:
		mov		ax,grTCDAC			; SS24 is TrueColor DAC
		mov		[DacType],ax
		jmp		@@Exit

@@Exit:
		mov		ax,[ForceDAC]		; Get value of forced DAC
		or		ax,ax				; Negative if we dont want to force
		js		@@1
		mov		[DacType],ax		; Force the dac type
@@1:	pop		si
		pop		di
		ret

ENDP	FindDAC

;----------------------------------------------------------------------------
; FindSuperVGA	Determine if a SuperVGA is out there, and get information
;----------------------------------------------------------------------------
;
; Routine performs a number of SuperVGA detection routines to determine
; if a SuperVGA video card is out there. If one is found, we set the driver
; variable to reflect this and exit. Note that we also detect how much
; memory is present on the card and what video modes are available.
;
; This code first appeared in John Bridges VGAKIT library, however it has
; been factorised into a number of independant functions to detect each
; video card.
;
; Entry:		DS:DI	->	Address of driver variable
;
; Exit:			Carry flag is set if a SuperVGA was detected
;
; Registers:	AX,BX,CX,DX
;
;----------------------------------------------------------------------------
PROC	FindSuperVGA	near

		push	ds
		push	es
		push	si
		push	di

		call	FindDAC				; Detect the Video DAC installed

		mov		[PageFlip],false	; Default to no page flipping

		push	ds
		mov		ds,[cs:SaveDS]		; Address data segment
		cmp		[__VESAFirst],1		; Check _VESAFirst flag
		pop		ds
		jne		@@SkipVESA

		check	VESA

@@SkipVESA:
		check	Chips
		check	Paradise
		check	Video7
		check	Genoa
		check	Everex
		check	Trident
		check	ATI
		check	Ahead
		check	NCR
		check	S3
		check	AL2101
		check	MXIC
		check	Cirrus
		check	AcuMos
		check	Tseng
		check	RT3106
		check	P2000
		check	Oaktech
		check	VESA

		pop		di
		pop		si
		pop		es
		pop		ds
		clc
		ret

@@FoundOne:
		pop		di
		pop		si
		pop		es
		pop		ds
		mov		[WORD ds:di],ax	; Store the SuperVGA card identifier
		stc
		ret

ENDP	FindSuperVGA

;----------------------------------------------------------------------------
; UnsupportedMode	Flags a video mode as unsupported for this card
;----------------------------------------------------------------------------
;
; Flags a video mode as unsupported for this video card, by writing a
; zero into the position where the mode is located.
;
; Entry:		AL	- Number of unsupported mode
;				BX	- Offset of video mode table
;
; Exit:			BX	- Offset of video mode table
;
; Registers:	AX,BX
;
;----------------------------------------------------------------------------
PROC	UnsupportedMode

; Find the index of the video mode

		push	bx
@@Loop:
		mov		ah,[BYTE cs:bx]
		cmp		ah,al				; Found the video mode?
		je		@@FoundIt
		cmp		ah,-1
		je		@@Exit
		inc		bx
		jmp		@@Loop

@@FoundIt:
		mov		[BYTE cs:bx],0
@@Exit:
		pop		bx
		ret

ENDP	UnsupportedMode

;----------------------------------------------------------------------------
; FindVESA	Detect the presence of VESA Compatible SuperVGA board
;----------------------------------------------------------------------------
;
; Routine detects if the SuperVGA boards is present and determines how much
; memory is on it.
;
; Exit:			Carry flag is set if board was detected
;
;				AX				- Video card identifier
;				[VideoMem]		- Amount of video memory on board
;
;----------------------------------------------------------------------------
PROC	FindVESA	near

; Check to see if a VESA extended video BIOS is out there. If it is,
; we have a Super VGA card.

		mov		ax,seg VesaBuf
		mov		es,ax
		mov		di,offset VesaBuf
		mov		ax,04F00h
		int		10h				; Call the VESA video BIOS
		cmp		ax,004Fh
		jne		@@NoVESA
		cmp		[WORD es:di],'EV'
		jne		@@NoVESA
		cmp		[WORD es:di+2],'AS'
		jne		@@NoVESA

; We have a VESA compatible SuperVGA, so determine how much memory must
; be on the video board by finding the amount of memory used by the
; highest resolution video mode supported.
;
; At the same time initialise the table of valid video modes for this
; SuperVGA, and bytes per line values for the video mode.

		push	ds
		push	bp
		mov		ax,[WORD es:di+16]
		mov		ds,ax
		mov		bp,[WORD es:di+14]	; DS:BP -> List of valid VESA modes
		mov     si,offset AllVesaModes
		mov		bx,offset VesaModes
		cld

@@VesaMemLoop:
		lods	[WORD cs:si]		; Load VESA mode number
		mov		cx,ax
		jcxz	@@EndVESA			; Finished when mode number is zero
		lods	[WORD cs:si]		; Load amount of memory required for mode
		push	ax                  ;   and save on stack
		lods	[WORD cs:si]		; Load MGL video mode number
		push	ax					;   and save on stack

; First check to see if the mode is a valid VESA mode.

		mov		di,bp				; DS:DI -> mode list
@@CheckMode:
		mov		ax,[WORD ds:di]
		inc		di
		inc		di
		cmp		ax,-1
		je		@@NotFound
		cmp		ax,cx
		je		@@FoundMode			; Yes mode was found
		jmp		@@CheckMode			; Loop for all valid modes

@@NotFound:
		pop		ax					; Restore stack
		pop		ax
		jmp		@@VesaMemLoop		; Continue loop

@@FoundMode:
		mov		ax,seg VesaBuf
		mov		es,ax
		mov		di,offset VesaBuf
		mov		ax,4F01h			; AX := Query Mode Information
		int		10h
		pop		dx					; DX := MGL Mode Number
		pop		cx					; CX := Video memory required
		or		ah,ah
		jnz		@@VesaMemLoop		; Mode not supported, try next one
		test	[BYTE es:di],1
		jz		@@VesaMemLoop		; Mode not supported, try next one

; Video mode is supported, so add to mode table.

		push	bx
		mov		bx,[WORD es:di+16]
		mov		ax,dx
		call	setBytesPerLine		; Set the bytes per line value for mode
		pop		bx
		mov		[BYTE cs:bx],dl		; Store the mode number
		inc		bx

		cmp		cx,[WORD VideoMem]
		jle		@@VesaMemLoop		; Memory is less, try next mode
		mov		[WORD VideoMem],cx	; Increase the memory size
		jmp		@@VesaMemLoop

@@EndVESA:
		pop		bp
		pop		ds
		call	checkVESAPageFlip	; Does VESA support page flipping?
		jc		@@NoFlip
		mov		[PageFlip],true

@@NoFlip:
		mov		[WORD VideoModes],offset VesaModes
		mov		ax,grSVGA
		stc
		ret

@@NoVESA:
		clc
		ret

ENDP	FindVESA

;----------------------------------------------------------------------------
; FindS3	Detect the presence of an S3 based SuperVGA board
;----------------------------------------------------------------------------
;
; Routine detects if the SuperVGA boards is present and determines how much
; memory is on it.
;
; Exit:			Carry flag is set if board was detected
;
;				AX				- Video card identifier
;				[VideoMem]		- Amount of video memory on board
;				[VideoChipID]	- Chip revision id
;
;----------------------------------------------------------------------------
PROC	FindS3	near

		wrinx	CRTC, 38h, 0	; Lock S3 extended registers
		tstinx	CRTC, 35h, 0Fh	; Check for locked S3 bank switch register
		jz		@@NoS3			; Bank reg was writeable, not an S3

		wrinx	CRTC, 38h, 48h	; Unlock S3 extended registers
		tstinx	CRTC, 35h, 0Fh	; Check for unlocked S3 bank switch register
		jnz		@@NoS3			; Test failed, not an S3

; Determine the chip ID for the video card and save it for later

		rdinx	CRTC, 30h		; Read chip ID register
		mov		bx,grS3_928
		cmp		al,90h
		je		@@FindMem		; We have an 86c928 chip
		mov		bx,grS3_801_805
		cmp		al,0A0h
		je		@@FindMem		; We have an 86c801/86c805 chip
		mov		bx,grS3_924
		cmp		al,82h
		je		@@FindMem		; We have an 86c924 chip
		mov		bx,grS3_911		; Fall through for the 86c911 chip

; Determine how much video RAM is on the card

@@FindMem:
		mov		[VideoChipID],bx; Save the chip ID
		rdinx	CRTC, 36h		; Read configuration register 1
		and		al,11100000b	; Mask out bits 7-5
		cmp		bx,grS3_924
		jle		@@Mem911

; We have an 86c801/805/928 based S3.

		mov		[WORD VideoMem],512
		cmp		al,11100000b
		je		@@DoneMem		; Card has 512k on board
		mov		[WORD VideoMem],1024
		cmp		al,11000000b
		je		@@DoneMem		; Card has 1Mb on board
		mov		[WORD VideoMem],2048
		cmp		al,10000000b
		je		@@DoneMem		; Card has 2Mb on board
		mov		[WORD VideoMem],3072
		cmp		al,01000000b
		je		@@DoneMem		; Card has 3Mb on board
		mov		[WORD VideoMem],4096
		jmp		@@DoneMem		; Card has 4Mb on board

; We have an 86c911/924.

@@Mem911:
		mov		[WORD VideoMem],512
		test	al,100000b		; Bit 5 is set for 512k
		jnz		@@DoneMem
		mov		[WORD VideoMem],1024

@@DoneMem:
		wrinx	CRTC, 38h, 0	; Lock S3 extended registers

		call	ModifyS3BytesPerLine
		mov		[PageFlip],true	; Card supports extended page flipping
		Add32kColor		S332KModes
		AddTrueColor	S3TCModes
		mov		[WORD VideoModes],offset S3Modes
		mov		ax,grSVGA_S3
		stc
		ret

@@NoS3:
		clc
		ret

ENDP	FindS3

;----------------------------------------------------------------------------
; FindATI	Detect the presence of an ATI Technologies SuperVGA board
;----------------------------------------------------------------------------
;
; Routine detects if the SuperVGA boards is present and determines how much
; memory is on it.
;
; Exit:			Carry flag is set if board was detected
;
;				AX				- Video card identifier
;				[VideoMem]		- Amount of video memory on board
;				[VideoChipID]	- Chip revision id
;
;----------------------------------------------------------------------------
PROC	FindATI	near

		mov		ax,0C000h
		mov		es,ax
		cmp		[WORD es:40h],'13'	; ATI Signature for VGA cards
		jne		@@NoATI

; Check for the ATI product code string '761295520'

		cmp		[WORD es:31h],'67'
		jne		@@NoATI
		cmp		[WORD es:31h+2],'21'
		jne		@@NoATI
		cmp		[WORD es:31h+4],'59'
		jne		@@NoATI
		cmp		[WORD es:31h+6],'25'
		jne		@@NoATI
		cmp		[BYTE es:31h+8],'0'
		jne		@@NoATI

		mov		dx,1CEh				; DX := port of ATI extended registers
		mov		bl,[BYTE es:43h]	; BL := ATI Chip Version
		cmp		bl,'3'
		jae		@@Ver6up			; Check for memory on later chip versions

		mov		[VideoChipID],grATI_18800_1
		cmp		bl,'1'
		jne		@@Not18800

; Remove unsupported video modes for (18800 chip)

		mov		[VideoChipID],grATI_18800
		ClearMode	grSVGA_1024x768x16, ATIModes

; Determine the memory size on chip versions 3-4 (18800, 18800-1)

@@Not18800:
		rdinx	1CEh, 0BBh			; Get RamSize bits
		and		al,20h
		jz		@@DoneATI

		mov		[WORD VideoMem],512	; Card has 512kb of memory
		jmp		@@DoneATI

; Determine memory size on chip versions 6+ (28800-2, 28800-4, 28800-5)

@@Ver6up:
		mov		[VideoChipID],grATI_28800_2
		rdinx	1CEh, 0B0h			; Get RamSize bits
		test	al,10h				; Check if RamSize is 256k or 512k
		jz		@@Ver7Check
		mov		[WORD VideoMem],512	; Card has at least 512k of memory

@@Ver7Check:
		cmp		bl,'4'
		jb		@@DoneATI			; Done for version 6 chips
		mov		[VideoChipID],grATI_28800_4
		cmp		bl,'5'
		jb		@@Not28800_5
		mov		[VideoChipID],grATI_28800_5

@@Not28800_5:
		test	al,8				; Check version 7+ chip memory size
		jz		@@DoneATI
		mov		[WORD VideoMem],1024; Card has 1024k of memory

@@DoneATI:
		mov		[DacType],grVGADAC	; Default to normal DAC
		test	[BYTE es:44h],8		; Check bit 7 for HiColor DAC
		jz		@@NoHiColor

		mov		[DacType],grHCDAC	; We have a 15 bit HiColor DAC
		Add32kColor	ATI32KModes

@@NoHiColor:
		mov		[PageFlip],true		; Card supports extended page flipping
		mov		[WORD VideoModes],offset ATIModes
		mov		ax,grSVGA_ATI
		stc
		ret

@@NoATI:
		clc
		ret

ENDP	FindATI

;----------------------------------------------------------------------------
; FindNCR	Detect the presence of the NCR 77C22E SuperVGA boards
;----------------------------------------------------------------------------
;
; Routine detects if the SuperVGA boards is present and determines how much
; memory is on it.
;
; Exit:			Carry flag is set if board was detected
;
;				AX				- Video card identifier
;				[VideoMem]		- Amount of video memory on board
;				[VideoChipID]	- Chip revision id
;
;----------------------------------------------------------------------------
PROC	FindNCR	near

		tstinx	3C4h, 5, 5			; Test for extended register enable chip
		jnz		@@NoNCR				; Check failed, so not an NCR

		wrinx	3C4h, 5, 0			; Disable extended registers
		tstinx	3C4h, 10h, 0FFh		; Test Cursor location y register
		jz		@@NoNCR				; Reg was writeable, so test failed

		wrinx	3C4h, 5, 1			; Enable extended registers
		tstinx	3C4h, 10h, 0FFh		; Test Cursor location y register
		jnz		@@NoNCR				; Reg was not writeable, so not NCR

; Determine the chip revision

		rdinx	3C4h, 8				; Get chip version number
		shr		al,4
		cmp		al,2
		jae		@@NCR77C22E

; We have an NCR77C20/21 chip. These do not support certain modes.

		ClearMode	grSVGA_1280x1024x16, NCRModes
		ClearMode	grSVGA_1024x768x256, NCRModes
		ClearMode	grSVGA_1280x1024x256, NCRModes

@@NCR77C22E:
		mov		ax,4096				; Maximum of 4Mb memory
		mov		bx,offset NCRSwitch	; Offset of bank switch routine
		mov		cx,5Eh				; Values to set 640x400x256
		xor		dx,dx
		call	CheckMem			; Manually check amount of memory

		mov		[PageFlip],true		; Card supports extended page flipping
		Add32kColor	NCR32KModes
		mov		[WORD VideoModes],offset NCRModes
		mov		ax,grSVGA_NCR
		stc
		ret

@@NoNCR:
		clc
		ret

ENDP	FindNCR

;----------------------------------------------------------------------------
; FindTrident	Detect the presence of the Trident SuperVGA boards
;----------------------------------------------------------------------------
;
; Routine detects if the SuperVGA boards is present and determines how much
; memory is on it.
;
; Exit:			Carry flag is set if board was detected
;
;				AX				- Video card identifier
;				[VideoMem]		- Amount of video memory on board
;				[VideoChipID]	- Chip revision id
;
;----------------------------------------------------------------------------
PROC	FindTrident	near

; When we force the old defintions on Trident TVGA's, they tend to hang up
; if you do it with a 16 bit port instruction. Doing it with 8 bit
; instructions fixes the problem (seems to happen on older cards).
;
; Note that the test in VGADOC that writes stuff to the bank switch
; registers causes some TVGA's to hang up severly (the one I tested it on
; it did). Seems that if you reset the card by setting a video mode before
; doing any bank switching, the problem goes away, but if you dont do this,
; the machine goes off into the never never ...

		mov		dx,3C4h
		mov		al,0Bh
		out		dx,al
		inc		dl
		xor		al,al
		out		dx,al				; Force old definitions
		in		al,dx				; Force new definitions
		and		al,0Fh
		cmp		al,2
		jb		@@NoTrident			; Trident 8800BR only has 128k banks
		cmp		al,2
		je		@@Trident88			; We have a Trident 8800CS

; Must be a Trident 8900, 8900C or 9000

		rdinx	CRTC, 1Fh			; Read memory size register
		and		al,3
		cmp		al,1
		jb		@@LowMem
		mov		[WORD VideoMem],512		; Card has 512kb of memory
		cmp		al,3
		jb		@@LowMem
		mov		[WORD VideoMem],1024	; Card has 1Mb of memory

@@LowMem:
		mov		[PageFlip],true		; Card supports extended page flipping
		mov		[WORD VideoModes],offset Trident89Modes
		mov		ax,grSVGA_TRIDENT89
		stc
		ret

@@Trident88:
		rdinx	CRTC, 1Fh			; Read memory size register
		and		al,2
		jz		@@LowMem88
		mov		[WORD VideoMem],512		; Card has 512kb of memory

@@LowMem88:
		mov		[PageFlip],true		; Card supports extended page flipping
		mov		[WORD VideoModes],offset Trident88Modes
		mov		ax,grSVGA_TRIDENT88
		stc
		ret

@@NoTrident:
		clc
		ret

ENDP	FindTrident

;----------------------------------------------------------------------------
; FindVideo7	Detect the presence of a Video7 SuperVGA board
;----------------------------------------------------------------------------
;
; Routine detects if the SuperVGA boards is present and determines how much
; memory is on it.
;
; Exit:			Carry flag is set if board was detected
;
;				AX				- Video card identifier
;				[VideoMem]		- Amount of video memory on board
;				[VideoChipID]	- Chip revision id
;
;----------------------------------------------------------------------------
PROC	FindVideo7	near

		mov		ax,6F00h
		xor		bx,bx
		int		10h
		cmp		bx,'V7'
		jnz		@@NoVideo7

		mov		ax,6F07h			; Determine how much memory is present
		int		10h
		and		ah,7Fh
		cmp		ah,2
		jb		@@1
		mov		[WORD VideoMem],512		; Card has 512kb of memory
@@1:	cmp		ah,4
		jb		@@2
		mov		[WORD VideoMem],1024
@@2:	mov		[WORD VideoModes],offset Video7Modes
		mov		[PageFlip],true		; Card supports extended page flipping
		mov		ax,grSVGA_VIDEO7
		stc
		ret

@@NoVideo7:
		clc
		ret

ENDP	FindVideo7

;----------------------------------------------------------------------------
; FindGenoa	Detect the presence of a Genoa GVGA SuperVGA board
;----------------------------------------------------------------------------
;
; Routine detects if the SuperVGA boards is present and determines how much
; memory is on it.
;
; Exit:			Carry flag is set if board was detected
;
;				AX				- Video card identifier
;				[VideoMem]		- Amount of video memory on board
;				[VideoChipID]	- Chip revision id
;
;----------------------------------------------------------------------------
PROC	FindGenoa	near

		mov		ax,0C000h
		mov		es,ax
		mov		bx,[es:37h]			; Get offset of information table
		cmp		[BYTE es:bx],77h
		jne		@@NoGenoa
		cmp		[WORD es:bx+2],6699h
		jne		@@NoGenoa

		mov		al,[BYTE es:bx+1]	; Get card version number
		or		al,al
		jz		@@HaveGenoa256		; Found a Genoa 62/300
		cmp		al,11h
		je		@@HaveGenoa512		; Found a Genoa 64/600
		cmp		al,22h
		je		@@HaveGenoa256		; Found a Genoa 6100
		jmp		@@NoGenoa			; Other Genoa's have Tseng chips

@@HaveGenoa512:
		mov		[WORD VideoMem],512

@@HaveGenoa256:
		mov		[WORD VideoModes],offset GenoaModes
		mov		ax,grSVGA_GENOA
		stc
		ret

@@NoGenoa:
		clc
		ret

ENDP	FindGenoa

;----------------------------------------------------------------------------
; FindParadise	Detect the presence of a Paradise SuperVGA board
;----------------------------------------------------------------------------
;
; Routine detects if the SuperVGA boards is present and determines how much
; memory is on it.
;
; Exit:			Carry flag is set if board was detected
;
;				AX				- Video card identifier
;				[VideoMem]		- Amount of video memory on board
;				[VideoChipID]	- Chip revision id
;
;----------------------------------------------------------------------------
PROC	FindParadise	near

		rdinx	3CEh, 0Fh			; Read old register value
		mov		[old],al			; Save old value
		modinx	3CEh, 0Fh, 17h, 0	; Lock paradise registers
		tstinx	3CEh, 9, 7Fh		; Test if bank register is there
		jz		@@NoParadise		; Register wrote, so not paradise

		wrinx	3CEh, 0Fh, 5		; Unlock paradise registers
		tstinx	3CEh, 9, 7Fh		; Test if bank register is there
		jnz		@@NoParadise		; Register wouldn't write, not paradise

; We have a Paradise SuperVGA, so determine what chip it is.

		rdinx	CRTC, 29h			; Read value of WD90Cxx register lock
		mov		[old],al			; Save old value
		modinx	CRTC, 29h, 8Fh, 85h	; Unlock WD90Cxx registers
		tstinx	CRTC, 2Bh, 0FFh		; Test WD90Cxx scratch register
		jnz		@@HavePVGA			; We have a PVGA1

		rdinx	3C4h, 6				; Read value of WD90C1x register
		mov		[old],al			; Save old value
		wrinx	3C4h, 6, 48h
		tstinx	3C4h, 7, 0F0h
		jnz		@@HaveWD90C00
		tstinx	3C4h, 10h, 0FFh
		jnz		@@HavePVGA			; WD90C2x has same modes as PVGA

		tstinx	3C4h, 14h, 0Fh
		jnz		@@HaveWD90C1x

		rdinx	CRTC, 37h
		cmp		al,31h
		mov		[VideoChipID],grPARA_90c31
		je		@@MemCheck			; Have a WD90C31

; Chip is a WD90C30.

		mov		[VideoChipID],grPARA_90c30
		wrinx	3C4h, 6, [old]		; Restore register value
		ClearMode	grSVGA_1280x1024x16, ParadiseModes
		jmp		@@MemCheck

@@HaveWD90C1x:
		wrinx	3C4h, 6, [old]		; Restore register value
		ClearMode	grSVGA_1280x1024x16, ParadiseModes
		ClearMode	grSVGA_1024x768x256, ParadiseModes
		mov		[VideoChipID],grPARA_90c10
		tstinx	3C4h, 0Ah, 04h
		jnz		@@MemCheck
		mov		[VideoChipID],grPARA_90c11
		jmp		@@MemCheck

@@HaveWD90C00:
		mov		[VideoChipID],grPARA_90c00
		wrinx	3C4h, 6, [old]		; Restore register value
		ClearMode	grSVGA_1280x1024x16, ParadiseModes
		ClearMode	grSVGA_1024x768x256, ParadiseModes
		jmp		@@MemCheck

@@HavePVGA:
		mov		[VideoChipID],grPARA_PVGA1A
		wrinx	CRTC, 29h, [old]	; Restore value of WD90Cxx register lock
		ClearMode	grSVGA_1024x768x16, ParadiseModes
		ClearMode	grSVGA_1280x1024x16, ParadiseModes
		ClearMode	grSVGA_800x600x256, ParadiseModes
		ClearMode	grSVGA_1024x768x256, ParadiseModes
		jmp		@@MemCheck

@@MemCheck:
		rdinx	3CEh, 0Bh			; Read memory size register
		shr		al,6
		cmp		al,2
		jb		@@DoneMem
		mov		[WORD VideoMem],512	; Card has 512kb of memory
		cmp		al,3
		jb		@@DoneMem
		mov		[WORD VideoMem],1024; Card has 1024kb of memory

@@DoneMem:
		mov		[PageFlip],true		; Card supports extended page flipping
		Add32kColor	Parad32KModes
		mov		[WORD VideoModes],offset ParadiseModes

; Ok, now check to see if the card is capable of 800x600x16 color mode. If
; it isn't, then the card is probably running on an LCD display, so we
; disable all modes above 640x480.

		call	saveMode
        mov     ax,58h or 80h       ; Don't clear the memory!
		int		10h
		call	CheckGraphics
		jc		@@Have800x600

		ClearMode	grSVGA_800x600x16, ParadiseModes
		ClearMode	grSVGA_1024x768x16, ParadiseModes
		ClearMode	grSVGA_800x600x256, ParadiseModes
		ClearMode	grSVGA_1024x768x256, ParadiseModes
		ClearMode	grSVGA_800x600x32k, ParadiseModes

@@Have800x600:
		call	restoreMode
		mov		ax,grSVGA_PARADISE
		stc
		ret

@@NoParadise:
		wrinx	3CEh, 15, [old]		; Restore old register value
		clc
		ret

ENDP	FindParadise

;----------------------------------------------------------------------------
; FindChips	Detect the presence of a Chips & Technologies SuperVGA board
;----------------------------------------------------------------------------
;
; Routine detects if the SuperVGA boards is present and determines how much
; memory is on it.
;
; Exit:			Carry flag is set if board was detected
;
;				AX				- Video card identifier
;				[VideoMem]		- Amount of video memory on board
;				[VideoChipID]	- Chip revision id
;
;----------------------------------------------------------------------------
PROC	FindChips	near

		mov		ax,5F00h			; Get controller info servic
		xor		bx,bx
		int		10h
		cmp		al,5Fh				; AL == 5F we have a Chips
		jnz		@@NoChips

; We have a Chips & Tech SuperVGA, so determine what chipset it is

		mov		[PageFlip],true		; Card supports extended page flipping

		shr		bl,4
		cmp		bl,0
		je		@@Have82c451
		cmp		bl,1
		je		@@Have82c452
		cmp		bl,2
		je		@@Have82c451		; 82c455 has same modes as 451
		cmp		bl,4
		je		@@Have82c451		; 82c456 has same modes as 451
		mov		[VideoChipID],grCHIPS_82c453
		jmp		@@CheckMem			; 82c453+ support all modes

@@Have82c451:
		mov		[PageFlip],false	; No page flipping on this chip
		ClearMode	grSVGA_1024x768x16, ChipsModes
		ClearMode	grSVGA_640x480x256, ChipsModes
		ClearMode	grSVGA_800x600x256, ChipsModes
		ClearMode	grSVGA_1024x768x256, ChipsModes
		mov		[VideoChipID],grCHIPS_82c451
		jmp		@@CheckMem

@@Have82c452:
		ClearMode	grSVGA_800x600x256, ChipsModes
		ClearMode	grSVGA_1024x768x256, ChipsModes
		mov		[VideoChipID],grCHIPS_82c452
		jmp		@@CheckMem

; Determine memory size

@@CheckMem:
		cmp		bh,1
		jb		@@DoneMem
		mov		[WORD VideoMem],512
		cmp		bh,2
		jb		@@DoneMem
		mov		[WORD VideoMem],1024

@@DoneMem:
		mov		[WORD VideoModes],offset ChipsModes
		mov		ax,grSVGA_CHIPS
		stc
		ret

@@NoChips:
		clc
		ret

ENDP	FindChips

;----------------------------------------------------------------------------
; FindTseng	Detect the presence of the ET3000 and ET4000 SuperVGA boards
;----------------------------------------------------------------------------
;
; Routine detects if the SuperVGA boards is present and determines how much
; memory is on it.
;
; Exit:			Carry flag is set if board was detected
;
;				AX				- Video card identifier
;				[VideoMem]		- Amount of video memory on board
;				[VideoChipID]	- Chip revision id
;
;----------------------------------------------------------------------------
PROC	FindTseng	near

		outp	3BFh, 3
		outp	3D8h, 0A0h			; Enable ET4000 extensions
		tstreg	3CDh, 3Fh			; Test bank switch register
		jnz		@@NoTseng			; Test failed, not a Tseng

; We have a Tseng card, so determine if it is an ET3000 or ET4000

		tstinx	CRTC, 33h, 0Fh		; Test for ET4000 extended start address
		jz		@@ET4000

; We have an ET3000 board, so check the amount of memory installed

		mov		ax,512				; Maximum of 512k on board
		mov		bx,offset ET3000Switch
		mov		cx,2Dh				; Values to set 640x350x256
		xor		dx,dx
		call	CheckMem

		mov		[PageFlip],true		; Card supports extended page flipping
		mov		[WORD VideoModes],offset ET3000Modes
		mov		ax,grSVGA_ET3000
		stc
		ret

; We have an ET4000 board, so determine the amount of memory installed

@@ET4000:
		rdinx	CRTC, 37h			; Read memory size bits
		and		al,0Bh
		cmp		al,0Ah
		jb		@@1
		mov		[WORD VideoMem],512
@@1:	cmp		al,0Bh
		jb		@@2
		mov		[WORD VideoMem],1024

; If the board has a 32k color DAC on board, check to see if we can set
; the 320x200 32k color mode which is not available on all boards.

@@2:
		mov		[VideoChipID],grET4000_MEGAEVA
		call	SaveMode
		cmp		[DacType],grHCDAC
		jl		@@Check1280
		mov		ax,10F0h
		mov		bx,13h or 80h
		int		10h
		cmp		ax,0010h
		je		@@CheckTC

		ClearMode	grSVGA_320x200x32k, ET400032KModes+1

; If the board has a 24 bit video DAC on board, determine what type of
; board it is (MegaEva/2, Speedstar 24, Genoa 7900), which all have
; different video mode numbers.

@@CheckTC:
		cmp		[DacType],grTCDAC
		jne		@@Check1280

; Assume board is a MegaEva/2, unless we find otherwise

		mov		ax,10E0h
		mov		bx,2Eh or 80h
		int		10h
		cmp		ax,0010h
		jne		@@CheckGenoa		; Not speedstar, check for Genoa 7900

; Board is a Diamond Speedstar 24

		mov		[VideoChipID],grET4000_SPEEDSTAR
		ClearMode	grSVGA_640x350x16m, ET4000TCModes+1
		ClearMode	grSVGA_640x400x16m, ET4000TCModes+1
		jmp		@@Check1280

@@CheckGenoa:
		mov		ax,10F0h
		mov		bx,3Eh or 80h
		int		10h
		cmp		ax,0010h
		jne		@@Check1280			; Not a Genoa, must be MegaEva/2...

; Board is a Genoa 7900

		mov		[VideoChipID],grET4000_GENOA
		ClearMode	grSVGA_640x350x16m, ET4000TCModes+1
		ClearMode	grSVGA_640x400x16m, ET4000TCModes+1

; Check to see if the 1280x1024x16 color video mode is available.

@@Check1280:
		mov		ax,03Dh or 80h		; 1280x1024x16 color video mode
		int		10h
		call	CheckGraphics
		jc		@@DoneCheck			; Yes, mode is available

		ClearMode	grSVGA_1280x1024x16, ET4000Modes

@@DoneCheck:
		call	RestoreMode

		mov		[PageFlip],true		; Card supports extended page flipping
		Add32kColor		ET400032KModes
		AddTrueColor	ET4000TCModes
		mov		[WORD VideoModes],offset ET4000Modes
		mov		ax,grSVGA_ET4000
		stc
		ret

@@NoTseng:
		clc
		ret

ENDP	FindTseng

;----------------------------------------------------------------------------
; FindEverex	Detect the presence of an Everex SuperVGA board
;----------------------------------------------------------------------------
;
; Routine detects if the SuperVGA boards is present and determines how much
; memory is on it.
;
; Exit:			Carry flag is set if board was detected
;
;				AX				- Video card identifier
;				[VideoMem]		- Amount of video memory on board
;				[VideoChipID]	- Chip revision id
;
;----------------------------------------------------------------------------
PROC	FindEverex	near

		mov		ax,7000h
		xor		bx,bx
		int		10h
		cmp		al,70h
		jnz		@@NoEverex

; Some Everex boards use Trident and ET4000 chipsets. These boards will be
; picked up by the low level INIT_everex routine. We do however determine
; the chipset type here, since all everex boards use the same video
; mode numbers.

		mov		[PageFlip],true		; Default to page flipping
		shr		dx,4
		mov		[VideoChipID],grEVEREX_Ev236
		cmp		dx,236h				; UltraGraphics - Trident Chip
		je		@@CheckMem
		mov		[VideoChipID],grEVEREX_Ev620
		cmp		dx,620h				; Vision VGA - Trident Chip
		je		@@CheckMem
		mov		[VideoChipID],grEVEREX_Ev629
		cmp		dx,629h				; ViewPoint TC - ET4000 Chip
		je		@@CheckMem
		mov		[VideoChipID],grEVEREX_Ev673
		cmp		dx,673h				; EVGA - Trident Chip
		je		@@CheckMem
		mov		[VideoChipID],grEVEREX_Ev678
		cmp		dx,678h				; Viewpoint - Trident Chip
		je		@@CheckMem

		mov		[VideoChipID],grEVEREX_EvNR
		mov		[PageFlip],false	; No page flipping on this card

@@CheckMem:
		shr		ch,6
		cmp		ch,1
		jb		@@DoneMem
		mov		[WORD VideoMem],512		; Card has 512kb of memory
		cmp		ch,2
		jb		@@DoneMem
		mov		[WORD VideoMem],1024	; Card has 1024kb of memory
		cmp		ch,3
		jb		@@DoneMem
		mov		[WORD VideoMem],2048	; Card has 2048kb of memory

@@DoneMem:
		Add32kColor		Everex32KModes
		AddTrueColor	EverexTCModes
		mov		[WORD VideoModes],offset EverexModes
		mov		ax,grSVGA_EVEREX
		stc
		ret

@@NoEverex:
		clc
		ret

ENDP	FindEverex

;----------------------------------------------------------------------------
; FindAhead	Detect the presence of a Ahead A or B SuperVGA board
;----------------------------------------------------------------------------
;
; Routine detects if the SuperVGA boards is present and determines how much
; memory is on it.
;
; Exit:			Carry flag is set if board was detected
;
;				AX				- Video card identifier
;				[VideoMem]		- Amount of video memory on board
;				[VideoChipID]	- Chip revision id
;
;----------------------------------------------------------------------------
PROC	FindAhead	near

		rdinx	3CEh, 0Fh
		mov		[old],al
		wrinx	3CEh, 0Fh, 0		; Disable extended registers
		tstinx	3CEh, 0Dh, 0FFh		; Test for bank switch register
		jz		@@NoAhead			; Register wrote, so not Ahead

		wrinx	3CEh, 0Fh, 20h		; Enable extended registers
		tstinx	3CEh, 0Dh, 0FFh		; Test for bank switch register
		jnz		@@NoAhead			; Register didn't write, so not Ahead

; SuperVGA is an Ahead, so determine type.

		rdinx	3CEh, 0Fh			; Read chip version register
		and		al,0Fh
		jnz		@@AheadB			; We have an Ahead B

		ClearMode	grSVGA_1024x768x256, AheadModes
		mov		ax,512				; Maximum of 512k on board
		mov		bx,offset AHEADASwitch
		mov		cx,60h				; Values to set 640x400x256
		xor		dx,dx
		call	CheckMem
		mov		[WORD VideoModes],offset AheadModes
		mov		ax,grSVGA_AHEADA
		stc
		ret

@@AheadB:
		mov		ax,1024				; Maximum of 1024k on board
		mov		bx,offset AHEADBSwitch
		mov		cx,60h				; Values to set 640x400x256
		xor		dx,dx
		call	CheckMem
		mov		[PageFlip],true		; Card supports extended page flipping
		mov		[WORD VideoModes],offset AheadModes
		mov		ax,grSVGA_AHEADB
		stc
		ret

@@NoAhead:
		wrinx	3CEh, 0Fh, [old]	; Restore register
		clc
		ret

ENDP	FindAhead

;----------------------------------------------------------------------------
; FindCirrus	Detect the presence of an Cirrus 54xx SuperVGA board
;----------------------------------------------------------------------------
;
; Routine detects if the SuperVGA boards is present and determines how much
; memory is on it.
;
; Exit:			Carry flag is set if board was detected
;
;				AX				- Video card identifier
;				[VideoMem]		- Amount of video memory on board
;				[VideoChipID]	- Chip revision id
;
;----------------------------------------------------------------------------
PROC	FindCirrus	near

		rdinx	3C4h, 6
		mov		[old],al			; Save of value of register
		wrinx	3C4h, 6, 12h		; Enable extended registers
		rdinx	3C4h, 6
		cmp		al,12h				; Check value in extended register lock
		jne		@@NoCirrus
		tstinx	3C4h, 1Eh, 3Fh
		jnz		@@NoCirrus			; Reg wasn't writeable, test failed
		tstinx	CRTC, 1Bh, 0FFh
		jnz		@@NoCirrus			; Reg wasn't writeable, test failed

; We have a Cirrus 54xx SuperVGA, so determine how much memory is on board

		rdinx	3C4h, 0Fh			; Get value of memory size register
		shr		al,3
		and		al,3
		cmp		al,1
		jb		@@DoneCirrus
		mov		[WORD VideoMem],512
		cmp		al,2
		jb		@@DoneCirrus
		mov		[WORD VideoMem],1024
		cmp		al,3

@@DoneCirrus:
		Add32kColor		Cirrus32KModes
		AddTrueColor	CirrusTCModes
		mov		[PageFlip],true		; Card supports page flipping
		mov		[WORD VideoModes],offset CirrusModes
		mov		[VideoChipID],grCIRRUS_5422
		mov		ax,grSVGA_CIRRUS54
		stc
		ret

@@NoCirrus:
		wrinx	3C4h, 6, [old]		; Restore extended register enable
		clc
		ret

ENDP	FindCirrus

;----------------------------------------------------------------------------
; FindAcuMos	Detect the presence of an AcuMos SuperVGA board
;----------------------------------------------------------------------------
;
; Routine detects if the SuperVGA boards is present and determines how much
; memory is on it.
;
; Exit:			Carry flag is set if board was detected
;
;				AX				- Video card identifier
;				[VideoMem]		- Amount of video memory on board
;				[VideoChipID]	- Chip revision id
;
;----------------------------------------------------------------------------
PROC	FindAcuMos	near

		rdinx	3C4h, 6
		mov		[old],al			; Save of value of register
		wrinx	3C4h, 6, 12h		; Enable extended registers
		tstinx	3CEh, 9, 30h		; Test scratchpad 9 again
		jnz		@@NoAcuMos			; Reg not wasn't writeable, test failed

; We have an AcuMos SuperVGA, so determine how much memory is on board

		rdinx	3C4h, 0Ah			; Get scratchpad index 10
		and		al,3
		cmp		al,1
		jb		@@DoneAcuMos
		mov		[WORD VideoMem],512
		cmp		al,2
		jb		@@DoneAcuMos
		mov		[WORD VideoMem],1024
		cmp		al,3
		jb		@@DoneAcuMos
		mov		[WORD VideoMem],2048

@@DoneAcuMos:
		mov		[WORD VideoModes],offset AcuMosModes
		mov		ax,grSVGA_ACUMOS
		stc
		ret

@@NoAcuMos:
		wrinx	3C4h, 6, [old]		; Restore extended register enable
		clc
		ret

ENDP	FindAcuMos

;----------------------------------------------------------------------------
; FindOaktech	Detect the presence of an Oak Technologies SuperVGA board
;----------------------------------------------------------------------------
;
; Routine detects if the SuperVGA boards is present and determines how much
; memory is on it.
;
; Exit:			Carry flag is set if board was detected
;
;				AX				- Video card identifier
;				[VideoMem]		- Amount of video memory on board
;				[VideoChipID]	- Chip revision id
;
;----------------------------------------------------------------------------
PROC	FindOaktech	near

		tstinx	3DEh, 0Dh, 38h		; Test for memory size register
		jnz		@@NoOakTech			; Do not have an OakTech board

; We have an Oak Technologies SuperVGA, so determine the type. The OTI-037C
; bank switching registers are read only, so the following test will fail
; for these cards.

		tstinx	3DEh, 11h, 0FFh		; Look for R/W bank switch register
		jnz		@@Have037C			; Have an OTI-037C

; We have an OAK SuperVGA, so determine what chipset it is

		rdinx	3DEh, 0Bh			; Read Chip Revision register
		shr		al,5
		cmp		al,5
		mov		[VideoChipID],grOAK_077
		je		@@Have077			; Chip is an OTI-077

		mov		[VideoChipID],grOAK_067
		ClearMode	grSVGA_1024x768x256, OAKModes

@@Have077:
		rdinx	3DEh, 0Dh			; Read memory size register
		shr		al,6
		or		al,al
		jz		@@DoneMem					; Board has 256k
		mov		[WORD VideoMem],512
		cmp		al,2
		je		@@DoneMem
		mov		[WORD VideoMem],1024
		jmp		@@DoneMem

; We have an OTI-037C SuperVGA. The only supported video mode is 800x600x16
; with 256k of memory.

@@Have037C:
		mov		[VideoChipID],grOAK_037C
		rdinx	3DEh, 0Dh			; Read memory size register
		shr		al,6
		or		al,al
		jz		@@DoneMem					; Board has 256k
		mov		[WORD VideoMem],512

@@DoneMem:
		Add32kColor	OAK32KModes
		mov		[WORD VideoModes],offset OAKModes
		mov		ax,grSVGA_OAKTECH
		stc
		ret

@@NoOaktech:
		clc
		ret

ENDP	FindOaktech

;----------------------------------------------------------------------------
; FindAL2101	Detect the presence of an Advance Logic 2101 SuperVGA board
;----------------------------------------------------------------------------
;
; Routine detects if the SuperVGA boards is present and determines how much
; memory is on it.
;
; Exit:			Carry flag is set if board was detected
;
;				AX				- Video card identifier
;				[VideoMem]		- Amount of video memory on board
;				[VideoChipID]	- Chip revision id
;
;----------------------------------------------------------------------------
PROC	FindAL2101	near

		tstreg	8286h, 0FFh			; Check for Start Pixel Low register
		jnz		@@NoAL2101			; Test failed, no AL2101
		tstinx	CRTC, 1Fh, 3Bh		; Check for Emulation register
		jnz		@@NoAL2101			; Test failed, no AL2101
		tstinx	3CEh, 0Dh, 0Fh		; Check for Fill Color register
		jnz		@@NoAL2101			; Test failed, no AL2101

; We have an AL2101 based SuperVGA

		rdinx	CRTC, 1Eh			; Read memory size register
		and		al,3
		cmp		al,1
		jb		@@DoneMem
		mov		[WORD VideoMem],512
		cmp		al,2
		jb		@@DoneMem
		mov		[WORD VideoMem],1024
		cmp		al,3
		jb		@@DoneMem
		mov		[WORD VideoMem],2048

@@DoneMem:
		mov		[DacType],grHC2DAC	; AL2101 has a 16 bit DAC
		mov		[WORD VideoModes],offset AL2101Modes
		mov		ax,grSVGA_AL2101
		stc
		ret

@@NoAL2101:
		clc
		ret

ENDP	FindAL2101

;----------------------------------------------------------------------------
; FindMXIC	Detect the presence of an MXIC 68010 SuperVGA board
;----------------------------------------------------------------------------
;
; Routine detects if the SuperVGA boards is present and determines how much
; memory is on it.
;
; Exit:			Carry flag is set if board was detected
;
;				AX				- Video card identifier
;				[VideoMem]		- Amount of video memory on board
;				[VideoChipID]	- Chip revision id
;
;----------------------------------------------------------------------------
PROC	FindMXIC	near

		rdinx	3C4h, 0A7h			; Read extend reg enable value
		mov		[old],al
		wrinx	3C4h, 0A7h, 0		; Disable extended registers
		tstinx	3C4h, 0C5h, 0FFh	; Test for bank switch register
		jz		@@NoMXIC			; Test passed, so not MXIC

		wrinx	3C4h, 0A7h, 87h		; Enable extended registers
		tstinx	3C4h, 0C5h, 0FFh	; Test for bank switch register
		jnz		@@NoMXIC			; Test failed, so not MXIC

; We have an MXIC SuperVGA.

		rdinx	3C4h, 0C2h			; Read memory size register
		shr		al,2
		and		al,3
		cmp		al,1
		jb		@@DoneMem
		mov		[WORD VideoMem],512
		cmp		al,2
		jb		@@DoneMem
		mov		[WORD VideoMem],1024

@@DoneMem:
		mov		[WORD VideoModes],offset MXICModes
		mov		ax,grSVGA_MXIC
		stc
		ret

@@NoMXIC:
		wrinx	3C4h, 0A7h, [old]	; Restore register
		clc
		ret

ENDP	FindMXIC

;----------------------------------------------------------------------------
; FindP2000	Detect the presence of a Primus 2000 SuperVGA board
;----------------------------------------------------------------------------
;
; Routine detects if the SuperVGA boards is present and determines how much
; memory is on it.
;
; Exit:			Carry flag is set if board was detected
;
;				AX				- Video card identifier
;				[VideoMem]		- Amount of video memory on board
;				[VideoChipID]	- Chip revision id
;
;----------------------------------------------------------------------------
PROC	FindP2000	near

		tstinx	3CEh, 3Dh, 03Fh		; Check for Status command register
		jnz		@@NoP2000			; Test failed, not P2000
		tstreg	3D6h, 01Fh			; Check for bank switch register
		jnz		@@NoP2000			; Test failed, not P2000
		tstreg	3D7h, 01Fh			; Check for bank switch register
		jnz		@@NoP2000			; Test failed, not P2000

; We have a Primus P2000 SuperVGA card.

		mov		ax,2048				; Maximum of 2048k on board
		mov		bx,offset P2000Switch
		mov		cx,2Ch				; Values to set 640x400x256
		xor		dx,dx
		call	CheckMem

		Add32kColor	P200032KModes
		mov		[PageFlip],true		; Card supports extended page flipping
		mov		[WORD VideoModes],offset P2000Modes
		mov		ax,grSVGA_P2000
		stc
		ret

@@NoP2000:
		clc
		ret

ENDP	FindP2000

;----------------------------------------------------------------------------
; FindRT3106	Detect the presence of a RealTek 3106 SuperVGA board
;----------------------------------------------------------------------------
;
; Routine detects if the SuperVGA boards is present and determines how much
; memory is on it.
;
; Exit:			Carry flag is set if board was detected
;
;				AX				- Video card identifier
;				[VideoMem]		- Amount of video memory on board
;				[VideoChipID]	- Chip revision id
;
;----------------------------------------------------------------------------
PROC	FindRT3106	near

		tstinx	CRTC, 1Fh, 3h		; Test for scratch register
		jnz		@@NoRT3106
		tstreg	3D6h, 0Fh			; Test for bank switch register
		jnz		@@NoRT3106
		tstreg	3D7h, 0Fh			; Test for bank switch register
		jnz		@@NoRT3106

; We have a RealTek 3106 SuperVGA

		rdinx	CRTC, 1Ah			; Get chip version number
		mov		bl,al				; Save chip version number
		shr		bl,6
		rdinx	CRTC, 1Eh			; Get memory size register
		and		al,15
		cmp		al,1
		jb		@@DoneMem
		mov		[WORD VideoMem],512
		cmp		al,2
		jb		@@DoneMem
		or		bl,bl
		jz		@@Version0
		mov		[WORD VideoMem],1024
		cmp		al,3
		jb		@@DoneMem
		mov		[WORD VideoMem],2048
		jmp		@@DoneMem

@@Version0:
		cmp		al,3
		jb		@@DoneMem
		mov		[WORD VideoMem],1024

@@DoneMem:
		mov		[WORD VideoModes],offset RT3106Modes
		mov		ax,grSVGA_RT3106
		stc
		ret

@@NoRT3106:
		clc
		ret

ENDP	FindRT3106

OldBIOSMode		db	?				; Old BIOS mode
Old50Lines		db	?
Oldx			db	?				; Old cursor position
Oldy			db	?

;----------------------------------------------------------------------------
; SaveMode	- Saves the current video BIOS mode, for later restoration
;----------------------------------------------------------------------------
;
; Registers:	none.
;
;----------------------------------------------------------------------------
PROC	SaveMode

		pusha

; Find the current video mode so that we can restore it easily

		mov		ah,0Fh				; Get current video mode service
		int		10h
		mov		[OldBIOSMode],al	; Save old video mode
		mov		ah,03h				; Get cursor position
		int		10h
		mov		[Oldx],dl
		mov		[Oldy],dh
		mov		[Old50Lines],0		; Default to non-50 line mode

		mov		ax,1130h			; AH := INT 10h function number
									; AL := Get character gen information
		mov		bh,00				; Get contents of INT 1Fh
		xor		dl,dl				; Clear dl
		int		10h					; Determine number of lines (in dl)
		cmp		dl,49				; 50 line mode?
		jne		@@Done				; No, must have been 25 lines
		mov		[Old50Lines],1		; Yes, 50 line mode was on

@@Done:
		popa
		ret

ENDP	SaveMode

;----------------------------------------------------------------------------
; RestoreMode	- Restores the VIDEO BIOS mode previously saved.
;----------------------------------------------------------------------------
;
; Registers:	none.
;
;----------------------------------------------------------------------------
PROC	RestoreMode

		pusha
		mov		ah,0				; Set video mode service
		mov		al,[OldBIOSMode]	; Get old BIOS mode number
		or		al,80h				; Set the don't clear memory bit
		int		10h					; Set the video mode

		cmp		[Old50Lines],0		; Was 50 line mode set?
		je		@@Exit				; No, don't set it up

		mov		ax,1112h			; AH := INT 10h function number
									; AL := 8x8 character set load
		mov		bl,0				; BL := block to load
		int		10h					; load 8x8 characters into RAM

@@Exit:
		mov		ah,02h
		mov		dl,[Oldx]
		mov		dh,[Oldy]
		xor		bh,bh
		int		10h					; Set cursor location
		popa
		ret

ENDP	RestoreMode

;----------------------------------------------------------------------------
; CheckGraphics	- Check to see if graphics mode is currently active.
;----------------------------------------------------------------------------
;
; This routine checks to see if a graphics mode was successfully set,
; setting the carry flag if it was.
;
; Exit:			carry - Set if graphics mode is set.
;
; Registers:	None.
;
;----------------------------------------------------------------------------
PROC	CheckGraphics

		push	ax
		mov		ax,40h
		mov		es,ax
		xor		ax,ax
		cmp		[BYTE es:49h],3		; Mode is still text mode, did not set
		ja		@@IsGraphics

		pop		ax
		clc
		ret

@@IsGraphics:
		pop		ax
		stc
		ret

ENDP	CheckGraphics

;----------------------------------------------------------------------------
; CheckMem	Performs a manual memory test
;----------------------------------------------------------------------------
;
; Does a manual memory test by attempting to read and write values at
; various places in memory, determining when they fail.
;
; Entry:		AX	- Maximum amount of memory installed
;				BX	- Offset of bank switching routine
;				CX	- Value in AX to set 256 color mode
;				DX	- Value in BX to set 256 color mode
;
; Exit:			[VideoMem] set to the correct value
;
; Registers:	AX,BX,CX,DX
;
;----------------------------------------------------------------------------
PROC	CheckMem

		push	si
		push	di
		push	bp

		push	ax
		push	bx
		push	cx
		push	dx

; Find the current video mode so that we can restore it easily

		mov		ah,0Fh				; Get current video mode service
		int		10h
		mov		[OldBIOSMode],al	; Save old video mode
		mov		[Old50Lines],0		; Default to non-50 line mode

		mov		ax,1130h			; AH := INT 10h function number
									; AL := Get character gen information
		mov		bh,00				; Get contents of INT 1Fh
		xor		dl,dl				; Clear dl
		int		10h					; Determine number of lines (in dl)
		cmp		dl,49				; 50 line mode?
		jne		@@SetMode			; No, must have been 25 lines
		mov		[Old50Lines],1		; Yes, 50 line mode was on

@@SetMode:
		pop		bx					; Pop value for BX
		pop		ax					; Pop value for AX
		int		10h					; Set the video mode

; Now perform the memory check

		mov		ax,0A000h
		mov		es,ax
		pop		bx
		pop		bp
		shr		bp,6				; BP := maximum number of 64k banks
		xor		di,di				; ES:DI -> offset in video RAM

		mov		dx,4				; Start by checking for 256k RAM

@@CheckLoop:
		mov		ax,dx
		dec		ax
		call	bx					; Setup to to read/write maxbank-1
		mov		cx,[es:di]			; Read a value from memory
		mov		si,cx				; Save the old value
		xor		cx,0AAAAh			; Modify the value
		mov		[es:di],cx			; Put the value back again
		mov		cx,[es:di]			; Read the value back again
		mov		[es:di],si			; Put the old value back
		xor		cx,0AAAAh			; Attempt to get old value back
		cmp		cx,si				; Old value the same?
		jne		@@TestFailed		; The test failed, so we ran outa memory!

		mov		ax,dx
		shr		ax,1
		dec		ax
		call	bx					; Setup for (bank/2) - 1
		mov		ax,si
		xor		ax,5555h
		mov		[es:di],ax			; Set modified value
		mov		ax,dx
		dec		ax
		call	bx					; Setup for bank-1
		mov		ax,[es:di]
		xor		ax,5555h
		cmp		ax,si
		je		@@TestFailed

		cmp		dx,bp				; Have we reached maximum amount?
		je		@@FullMemory		; Yes, so we have maximum memory...

		shl		dx,1				; Keep on trying
		jmp		@@CheckLoop

@@FullMemory:
		shl		dx,1				; Indicate that we would have failed
									;  on next bank
@@TestFailed:
		shl		dx,5				; DX := amount of video memory
		mov		[VideoMem],dx		; Save the memory value found

; Restore the old video mode before leaving

		mov		ah,0				; Set video mode service
		mov		al,[OldBIOSMode]	; Get old BIOS mode number
		int		10h					; Set the video mode

		cmp		[Old50Lines],0		; Was 50 line mode set?
		je		@@Exit				; No, don't set it up

		mov		ax,1112h			; AH := INT 10h function number
									; AL := 8x8 character set load
		mov		bl,0				; BL := block to load
		int		10h					; load 8x8 characters into RAM

@@Exit:
		pop		bp
		pop		di
		pop		si
		ret

ENDP	CheckMem

;----------------------------------------------------------------------------
; NCRSwitch	NCR 77C22E bank switching routine
;----------------------------------------------------------------------------
;
; Entry:		AL	- Bank number to switch to
;
;----------------------------------------------------------------------------
PROC	NCRSwitch

		push	dx
		shl		al,2				; Change 64k bank into 16k bank number
		mov		ah,al
		mov		al,18h
		mov		dx,3C4h
		out		dx,ax				; Set write bank number
		mov		al,1Ch
		out		dx,ax				; Set read bank number
		pop		dx
		ret

ENDP	NCRSwitch

;----------------------------------------------------------------------------
; ET3000Switch	ET3000 bank switching routine
;----------------------------------------------------------------------------
;
; Entry:		AL	- Bank number to switch to
;
;----------------------------------------------------------------------------
PROC	ET3000Switch

		push	dx
		and		al,7				; Mask out bottom 3 bits
		mov		ah,al				; Combine read and write bank values in al
		shl		ah,3
		or		al,ah
		or		al,40h				; Set bit 6 to select 64k segments
		mov		dx,3CDh				; Point to memory segment register
		out		dx,al				; Set the new bank value
		pop		dx
		ret

ENDP	ET3000Switch

;----------------------------------------------------------------------------
; AHEADASwitch	Ahead A bank switching routine
;----------------------------------------------------------------------------
;
; Entry:		AL	- Bank number to switch to
;
;----------------------------------------------------------------------------
PROC	AHEADASwitch

		push	dx
		mov		ch,al
		mov		dx,03CCh			; bit 0 in bit 5 of Misc Output reg
		in		al,dx				; Read Misc output register
		mov		dl,0C2h
		and		al,11011111b
		shr		ch,1				; Need to set the bit?
		jnc		@@SkpA				; No, so skip it
		or		al,00100000b
@@SkpA:	out		dx,al				; Set the new value
		mov		dx,3CEh				; bits 3-1 in bits 2-0 of Segment Reg
		mov		al,0Dh				; Index 0Dh for segment reg
		mov		ah,ch				; ch contains top three bits shr 1
		out		dx,ax				; Set the new value
		pop		dx
		ret

ENDP	AHEADASwitch

;----------------------------------------------------------------------------
; AHEADBSwitch	Ahead B bank switching routine
;----------------------------------------------------------------------------
;
; Entry:		AL	- Bank number to switch to
;
;----------------------------------------------------------------------------
PROC	AHEADBSwitch

		push	dx
		mov		ah,al				; Combine read/write bank numbers
		shl		ah,4
		or		ah,al
		mov		al,0Dh				; Index of Bank Switch register
		mov		dx,3CEh
		out		dx,ax				; Set the register
		pop		dx
		ret

ENDP	AHEADBSwitch

;----------------------------------------------------------------------------
; P2000Switch	Primus P2000 bank switching routine
;----------------------------------------------------------------------------
;
; Entry:		AL	- Bank number to switch to
;
;----------------------------------------------------------------------------
PROC	P2000Switch

		push	dx
		mov		dx,3D6h
		out		dx,al				; Set read bank
		inc		dx
		out		dx,al				; Set write bank
		pop		dx
		ret

ENDP	P2000Switch

;----------------------------------------------------------------------------
; Find6845	Determine if a 6845 CRTC is at the required port
;----------------------------------------------------------------------------
;
; Routine detects the presence of the CRTC on an MDA, CGA, or HGC.
; The technique is to write and read register 0Fh of the chip (Cursor
; Location Low). If the same value is read as written, assume the chip
; is present at the specified location.
;
; Entry:		DX = port address of 6845 CRTC
;
; Exit:			Carry flag is set if 6845 is present
;
; Registers:	AX,CX,DX
;
;----------------------------------------------------------------------------
PROC	Find6845 near

		mov		al,0Fh
		out		dx,al			; Select 6845 reg 0Fh (Cursor low)
		inc		dx

		in		al,dx			; AL := current Cursor Low value
		mov		ah,al			; Preserve in AH
		mov		al,66h			; AL := arbitrary value
		out		dx,al			; Try to write 6845

		mov		cx,100h
@@Wait:
		loop	@@Wait			; wait for 6845 to respond

		in		al,dx
		xchg	ah,al			; AH := returned value
								; AL := original value
		out		dx,al			; Restore original value

		cmp		ah,66h			; test whether 6845 responded
		jne		@@Exit			; Jump if it didn't (cf is reset)

		stc						; Set carry if 6845 present

@@Exit:
		ret

ENDP	Find6845

endcodeseg	detectgr

		END						; End of module
[ RETURN TO DIRECTORY ]