home *** CD-ROM | disk | FTP | other *** search
- ; Adapted from "Programmer's Guide to PC and PS/2 Video Systems",
- ; by Richard Wilton and published by Microsoft Press in 1987.
- ;
- public FindPS2,FindEGA,FindCGA,FindMono,Find6845
- public FindActive,FoundDevice
-
-
-
- ARGpVID equ word ptr [bp+4] ; stack frame addressing
-
- VIDstruct struc ; corresponds to C struc
-
- Video0Type db ? ; first subsystem type
- Display0Type db ? ; display attached to first subsystem
- Video1Type db ? ; second subsystem type
- Display1Type db ? ; display attached to second subsystem
-
- VIDstruct ends
-
- Device0 equ word ptr Video0Type[di]
- Device1 equ word ptr Video1Type[di]
-
- MDA equ 1
- CGA equ 2
- EGA equ 3
- MCGA equ 4
- VGA equ 5
- HGC equ 80h
- HGCPlus equ 81h
- InColor equ 82h
- HGCclone equ 83h
-
- MDADisplay equ 1
- CGADisplay equ 2
- EGAColorDisplay equ 3
- PS2MonoDisplay equ 4
- PS2ColorDisplay equ 5
-
- TRUE equ 1
- FALSE equ 0
-
- DGROUP GROUP _DATA
-
- _TEXT SEGMENT byte public 'CODE'
- assume cs:_TEXT,ds:DGROUP
-
- public _VideoID
- _VideoID proc near
-
- push bp
- mov bp,sp
- push si
- push di
-
- ; initialize the data structure that will contain the results
-
- mov di,ARGpVID ; DS;DI -> start of data structure
-
- mov Device0,0
- mov Device1,0
-
- ; look for the various subsystems using the subroutines whose addresses are
- ; tabulated in TestSequence; each subroutine sets flags in Test Sequence
- ; to indicate whether subsequent subroutines need to be called
-
- mov byte ptr TestSequence,TRUE
- mov byte ptr CGAflag,TRUE
- mov byte ptr EGAflag,TRUE
- mov byte ptr Monoflag,TRUE
- mov cx,NumberOfTests
- mov si,offset DGROUP:TestSequence
-
- L01: lodsb ; al := flag
- test al,al
- lodsw ; ax := subroutine address
- jz L02 ; skip subroutine if flag is false
-
- push si
- push cx
- call ax ; call subroutine to detect subsystem
- pop cx
- pop si
-
- L02: loop L01
-
- ; determine which subsystem is active
-
- call FindActive
- pop di
- pop si
- mov sp,bp
- pop bp
- ret
-
- _VideoID endp
-
- ;
- ; FindPS2
- ;
- ; This subroutine uses INT 10 function 1A to determine the video BIOS
- ; DCC for each video subsystem.
- ;
- FindPS2 proc near
- mov ax,1a00h
- int 10h
-
- cmp al,1ah
- jne L13 ; exit if 1A call not supported
-
- ; convert DCC into specific subsystems and displays
-
- mov cx,bx
- xor bh,bh ; BX := DCC for active subsystem
- or ch,ch
- jz L11 ; jump if only on subsystem
-
- mov bl,ch ; BX := inactive DCC
- add bx,bx
- mov ax,[bx+offset DGROUP:DCCtable]
- mov Device1,ax
-
- mov bl,cl
- xor bh,bh ; BX := active DCC
-
- L11: add bx,bx
- mov ax,[bx+offset DGROUP:DCCtable]
- mov Device0,ax
-
- ; reset flags for subsystems that have been ruled out
-
- mov byte ptr CGAflag,FALSE
- mov byte ptr EGAflag,FALSE
- mov byte ptr Monoflag,FALSE
-
- lea bx,Video0Type[di] ; if the BIOS reported and MDA
- cmp byte ptr [bx],MDA
- je L12
-
- lea bx,Video1Type[di]
- cmp byte ptr [bx],MDA
- jne L13
-
- L12: mov word ptr [bx],0 ; Herc can't be ruled out
- mov byte ptr Monoflag,TRUE
-
- L13: ret
-
- FindPS2 endp
-
- ; FindEGA
- ; Look for an EGA. This is done by making a call to an EGA BIOS
- ; function that doesn't exist on the planer BIOS.
- ;
-
- FindEGA proc near ; Caller: AH = flags
- ; Returns: AH = flags
- ; Video0Type and
- ; Display0Type
- ; updated.
-
- mov ah,12h ; BIOS function 12
- mov bl,10h ;
- int 10h ; if EGA BIOS is present,
- ; bl <> 10h, cl = switch
-
- cmp bl,10h ; is EGA BIOS present?
- je L22 ; no
-
- mov al,cl
- shr al,1 ; al := switches/2
- mov bx,offset DGROUP:EGADisplays
- xlat ; determine display type
- ; from switches
- mov ah,al ; ah := display type
- mov al,EGA ; al := subsystem type
- call FoundDevice
-
- cmp ah,MDADisplay ; monochrome display?
- je L21 ; yes
-
- mov CGAflag,FALSE ; no CGA if EGA has color
- jmp short L22
-
- L21: mov Monoflag,FALSE ; no mono if EGA has mono
-
- L22: ret
-
- FindEGA endp
-
- ; FindCGA
- ; Look for a 6845 at I/O port 3D4h
- ;
- FindCGA proc near ; returns: VIDstruc updated
-
- mov dx,3d4h ; dx := 6845 address
- call Find6845
- jc L31 ; jump if not present
-
- mov al,CGA
- mov ah,CGADisplay
- call FoundDevice
-
- L31: ret
-
- FindCGA endp
-
- ; FindMono
- ; This is done by looking for the MDA's 6845 at 3B4h. If a 6845
- ; is found, the subroutine distinguishes between an MDA and a
- ; Hercules adapter by monitoring bit 7 of the CRT Status byte.
- ; This bit changes on Herc adapters, but not on an MDA. The
- ; various Herc adapters are identified by bits 4 through 6 of
- ; the CRT Status value:
- ; 000b = HGC
- ; 001b = HGC+
- ; 101b = InColor Card
- ;
-
- FindMono proc near
-
- mov dx,3b4h
- call Find6845
- jc L44 ; jump if not present
-
- mov dl,0bah ; dx := 3ba (status port)
- in al,dx
- and al,80h
- mov ah,al ; ah := bit 7 (herc Vsync)
-
- mov cx,8000h ; do this 8000h times
- L41: in al,dx
- and al,80h ; isolate bit 7
- cmp ah,al
- loope L41 ; wait for bit 7 to change
-
- jne L42 ; if bit 7 changed, its a herc
-
- mov al,MDA ; if not, it's an MDA
- mov ah,MDADisplay
- call FoundDevice
- jmp short L44
-
- L42: in al,dx
- mov dl,al ; dl := value from status port
-
- mov ah,MDADisplay ; assume it's a mono display
-
- mov al,HGC ; look for an HGC
- and dl,01110000b ; mask off bits 4-6
- jz L43 ; it is an HGC
-
- mov al,HGCPlus ; look for an HGC+
- cmp dl,00010000b
- je L43 ; jump if HGC+
-
- mov al,InColor ; look for an InColor
- mov ah,EGAColorDisplay
- cmp dl,01010000b
- je L43 ; jump if Incolor
-
- mov al,HGCclone ; must be a Herc clone
- mov ah,MDADisplay
-
- L43: call FoundDevice
-
- L44: ret
-
- FindMono endp
-
- ; Find6845
- ;
-
- Find6845 proc near ; Input: DX = port address
- ; Return: c set if not present
- mov al,0fh
- out dx,al ; select index 0f (cursor low)
- inc dx ; data port
-
- in al,dx ; al := cursor low
- mov ah,al ; save in ah
- mov al,66h ; al = arbitrary value
- out dx,al ; try to write to 6845
-
- mov cx,100h
- L51: loop L51 ; wait for 6845
-
- in al,dx
- xchg ah,al ; ah := returned value
- ; al := original value
- out dx,al ; restore original value
-
- cmp ah,66h ; did we get it back?
- je L52 ; yes
-
- stc ; set carry if no 6845
-
- L52: ret
-
- Find6845 endp
-
- ; FindActive
-
- FindActive proc near
-
- cmp word ptr Device1,0 ; is there a 2nd subsystem?
- je L63 ; no
-
- cmp Video0Type[di],4 ; exit if MCGA or VGA
- jge L63 ; (func 1A already did this)
- cmp Video1Type[di],4
- jge L63
-
- mov ah,0fh
- int 10h ; get mode
-
- and al,7
- cmp al,7 ; jump if mono
- je L61 ; (mode 7 or 0fh)
-
- cmp Display0Type[di],MDADisplay
- jne L63 ; exit if Display0 is color
- jmp short L62
-
- L61: cmp Display0Type[di],MDADisplay
- je L63 ; exit if Display0 is mono
-
- L62: mov ax,Device0 ; make Device0 active
- xchg ax,Device1
- mov Device0,ax
-
- L63: ret
-
- FindActive endp
-
- ; FoundDevice
- ;
- FoundDevice proc near ; Input: AH = display #
- ; AL = subsystem #
-
- lea bx,Video0Type[di]
- cmp byte ptr [bx],0
- je L71 ; jump if first subsystem
-
- lea bx,Video1Type[di] ; must be second subsystem
-
- L71: mov [bx],ax ; update list entry
- ret
-
- FoundDevice endp
-
- _TEXT ends
-
- _DATA SEGMENT word public 'DATA'
-
- EGADisplays db CGADisplay ; 0000b, 0001b (EGA switch values)
- db EGAColorDisplay ; 0010b, 0011b
- db MDADisplay ; 0100b, 0101b
- db CGADisplay ; 0110b, 0111b
- db EGAColorDisplay ; 1000b, 1001b
- db MDADisplay ; 1010b, 1011b
-
- DCCtable db 0,0 ; translate table for function 1A
- db MDA,MDADisplay
- db CGA,CGADisplay
- db 0,0
- db EGA,EGAColorDisplay
- db EGA,MDADisplay
- db 0,0
- db VGA,PS2MonoDisplay
- db VGA,PS2ColorDisplay
- db 0,0
- db MCGA,EGAColorDisplay
- db MCGA,PS2MonoDisplay
- db MCGA,PS2ColorDisplay
-
- TestSequence db ? ; this list of flags and address
- dw FindPS2 ; determines the order in which this
- ; program looks for the various
- EGAflag db ? ; subsystems
- dw FindEGA
-
- CGAflag db ?
- dw FindCGA
-
- Monoflag db ?
- dw FindMono
-
- NumberOfTests equ ($-TestSequence)/3
-
- _DATA ends
-
- end