851 lines
16 KiB
NASM
851 lines
16 KiB
NASM
; ID_VL.ASM
|
||
|
||
IDEAL
|
||
MODEL MEDIUM,C
|
||
|
||
INCLUDE 'ID_VL.EQU'
|
||
|
||
SCREENSEG = 0a000h
|
||
|
||
DATASEG
|
||
|
||
EXTRN TimeCount:WORD ; incremented every 70th of a second
|
||
EXTRN linewidth:WORD
|
||
|
||
starttime dw ?
|
||
|
||
CODESEG
|
||
|
||
;===========================================================================
|
||
|
||
|
||
IF 1
|
||
|
||
;
|
||
; WaitVBL
|
||
; Wait for the vertical retrace (returns before the actual vertical sync)
|
||
; By Jason Blochowiak
|
||
;
|
||
PROC VL_WaitVBL num:WORD
|
||
PUBLIC VL_WaitVBL
|
||
|
||
@@wait:
|
||
mov dx,STATUS_REGISTER_1
|
||
mov bl,8 ; test VBL
|
||
mov bh,1 ; test DE
|
||
|
||
@@waitno:
|
||
in al,dx
|
||
test al,bl ; VBL?
|
||
jnz @@waitno ; Yep, keep waiting
|
||
mov cx,400 ; for 320x200 mode (200 lines are double-scanned)
|
||
|
||
@@waityes:
|
||
in al,dx
|
||
test al,bl ; VBL?
|
||
jnz @@done ; Yep, we're done
|
||
test al,bh ; No. Display enabled?
|
||
jz @@waityes ; Yes, keep checking
|
||
|
||
@@waitenable:
|
||
in al,dx ; No, wait for Display not enabled or VBL
|
||
test al,bl ; VBL?
|
||
jnz @@done ; Yep, done
|
||
test al,bh ; No. Display enabled?
|
||
jnz @@waitenable ; No, keep waiting
|
||
dec cx ; DE toggled state - decrement line abort count
|
||
jnz @@waityes ; If 0, we missed the VBL, so drop out,
|
||
; otherwise, go back to waiting for the VBL
|
||
@@done:
|
||
dec [num] ; wait multiple VBLs?
|
||
jnz @@wait
|
||
|
||
ret
|
||
|
||
ENDP
|
||
|
||
ELSE
|
||
|
||
;==============
|
||
;
|
||
; VL_WaitVBL
|
||
;
|
||
; Wait for the vertical retrace (returns before the actual vertical sync)
|
||
;
|
||
;==============
|
||
|
||
PROC VL_WaitVBL num:WORD
|
||
PUBLIC VL_WaitVBL
|
||
@@wait:
|
||
|
||
mov cx,[TimeCount] ; if timecount goes up by two, the retrace
|
||
add cx,2 ; period was missed (an interrupt covered it)
|
||
|
||
mov dx,STATUS_REGISTER_1
|
||
|
||
;
|
||
; wait for a display signal to make sure the raster isn't in the middle
|
||
; of a sync
|
||
;
|
||
@@waitdisplay:
|
||
in al,dx
|
||
test al,1 ;1 = display is disabled (HBL / VBL)
|
||
jnz @@waitdisplay
|
||
|
||
|
||
@@loop:
|
||
sti
|
||
jmp $+2
|
||
cli
|
||
|
||
cmp [timecount],cx ; will only happen if an interrupt is
|
||
jae @@done ; straddling the entire retrace period
|
||
|
||
;
|
||
; when several succesive display not enableds occur,
|
||
; the bottom of the screen has been hit
|
||
;
|
||
|
||
in al,dx
|
||
test al,8
|
||
jnz @@waitdisplay
|
||
test al,1
|
||
jz @@loop
|
||
|
||
in al,dx
|
||
test al,8
|
||
jnz @@waitdisplay
|
||
test al,1
|
||
jz @@loop
|
||
|
||
in al,dx
|
||
test al,8
|
||
jnz @@waitdisplay
|
||
test al,1
|
||
jz @@loop
|
||
|
||
in al,dx
|
||
test al,8
|
||
jnz @@waitdisplay
|
||
test al,1
|
||
jz @@loop
|
||
|
||
in al,dx
|
||
test al,8
|
||
jnz @@waitdisplay
|
||
test al,1
|
||
jz @@loop
|
||
|
||
in al,dx
|
||
test al,8
|
||
jnz @@waitdisplay
|
||
test al,1
|
||
jz @@loop
|
||
|
||
in al,dx
|
||
test al,8
|
||
jnz @@waitdisplay
|
||
test al,1
|
||
jz @@loop
|
||
|
||
in al,dx
|
||
test al,8
|
||
jnz @@waitdisplay
|
||
test al,1
|
||
jz @@loop
|
||
|
||
@@done:
|
||
dec [num] ; wait multiple VBLs?
|
||
jnz @@wait
|
||
|
||
sti
|
||
|
||
ret
|
||
|
||
ENDP
|
||
|
||
ENDIF
|
||
;===========================================================================
|
||
|
||
;==============
|
||
;
|
||
; VL_SetCRTC
|
||
;
|
||
;==============
|
||
|
||
PROC VL_SetCRTC crtc:WORD
|
||
PUBLIC VL_SetCRTC
|
||
|
||
;
|
||
; wait for a display signal to make sure the raster isn't in the middle
|
||
; of a sync
|
||
;
|
||
cli
|
||
|
||
mov dx,STATUS_REGISTER_1
|
||
|
||
@@waitdisplay:
|
||
in al,dx
|
||
test al,1 ;1 = display is disabled (HBL / VBL)
|
||
jnz @@waitdisplay
|
||
|
||
|
||
;
|
||
; set CRTC start
|
||
;
|
||
; for some reason, my XT's EGA card doesn't like word outs to the CRTC
|
||
; index...
|
||
;
|
||
mov cx,[crtc]
|
||
mov dx,CRTC_INDEX
|
||
mov al,0ch ;start address high register
|
||
out dx,al
|
||
inc dx
|
||
mov al,ch
|
||
out dx,al
|
||
dec dx
|
||
mov al,0dh ;start address low register
|
||
out dx,al
|
||
mov al,cl
|
||
inc dx
|
||
out dx,al
|
||
|
||
|
||
sti
|
||
|
||
ret
|
||
|
||
ENDP
|
||
|
||
|
||
|
||
;===========================================================================
|
||
|
||
;==============
|
||
;
|
||
; VL_SetScreen
|
||
;
|
||
;==============
|
||
|
||
PROC VL_SetScreen crtc:WORD, pel:WORD
|
||
PUBLIC VL_SetScreen
|
||
|
||
|
||
mov cx,[timecount] ; if timecount goes up by two, the retrace
|
||
add cx,2 ; period was missed (an interrupt covered it)
|
||
|
||
mov dx,STATUS_REGISTER_1
|
||
|
||
;
|
||
; wait for a display signal to make sure the raster isn't in the middle
|
||
; of a sync
|
||
;
|
||
@@waitdisplay:
|
||
in al,dx
|
||
test al,1 ;1 = display is disabled (HBL / VBL)
|
||
jnz @@waitdisplay
|
||
|
||
|
||
@@loop:
|
||
sti
|
||
jmp $+2
|
||
cli
|
||
|
||
cmp [timecount],cx ; will only happen if an interrupt is
|
||
jae @@setcrtc ; straddling the entire retrace period
|
||
|
||
;
|
||
; when several succesive display not enableds occur,
|
||
; the bottom of the screen has been hit
|
||
;
|
||
|
||
in al,dx
|
||
test al,8
|
||
jnz @@waitdisplay
|
||
test al,1
|
||
jz @@loop
|
||
|
||
in al,dx
|
||
test al,8
|
||
jnz @@waitdisplay
|
||
test al,1
|
||
jz @@loop
|
||
|
||
in al,dx
|
||
test al,8
|
||
jnz @@waitdisplay
|
||
test al,1
|
||
jz @@loop
|
||
|
||
in al,dx
|
||
test al,8
|
||
jnz @@waitdisplay
|
||
test al,1
|
||
jz @@loop
|
||
|
||
in al,dx
|
||
test al,8
|
||
jnz @@waitdisplay
|
||
test al,1
|
||
jz @@loop
|
||
|
||
|
||
@@setcrtc:
|
||
|
||
|
||
;
|
||
; set CRTC start
|
||
;
|
||
; for some reason, my XT's EGA card doesn't like word outs to the CRTC
|
||
; index...
|
||
;
|
||
mov cx,[crtc]
|
||
mov dx,CRTC_INDEX
|
||
mov al,0ch ;start address high register
|
||
out dx,al
|
||
inc dx
|
||
mov al,ch
|
||
out dx,al
|
||
dec dx
|
||
mov al,0dh ;start address low register
|
||
out dx,al
|
||
mov al,cl
|
||
inc dx
|
||
out dx,al
|
||
|
||
;
|
||
; set horizontal panning
|
||
;
|
||
mov dx,ATR_INDEX
|
||
mov al,ATR_PELPAN or 20h
|
||
out dx,al
|
||
jmp $+2
|
||
mov al,[BYTE pel] ;pel pan value
|
||
out dx,al
|
||
|
||
sti
|
||
|
||
ret
|
||
|
||
ENDP
|
||
|
||
|
||
;===========================================================================
|
||
|
||
|
||
;============================================================================
|
||
;
|
||
; VL_ScreenToScreen
|
||
;
|
||
; Basic block copy routine. Copies one block of screen memory to another,
|
||
; using write mode 1 (sets it and returns with write mode 0). bufferofs is
|
||
; NOT accounted for.
|
||
;
|
||
;============================================================================
|
||
|
||
PROC VL_ScreenToScreen source:WORD, dest:WORD, wide:WORD, height:WORD
|
||
PUBLIC VL_ScreenToScreen
|
||
USES SI,DI
|
||
|
||
pushf
|
||
cli
|
||
|
||
mov dx,SC_INDEX
|
||
mov ax,SC_MAPMASK+15*256
|
||
out dx,ax
|
||
mov dx,GC_INDEX
|
||
mov al,GC_MODE
|
||
out dx,al
|
||
inc dx
|
||
in al,dx
|
||
and al,NOT 3
|
||
or al,1
|
||
out dx,al
|
||
|
||
popf
|
||
|
||
mov bx,[linewidth]
|
||
sub bx,[wide]
|
||
|
||
mov ax,SCREENSEG
|
||
mov es,ax
|
||
mov ds,ax
|
||
|
||
mov si,[source]
|
||
mov di,[dest] ;start at same place in all planes
|
||
mov dx,[height] ;scan lines to draw
|
||
mov ax,[wide]
|
||
|
||
@@lineloop:
|
||
mov cx,ax
|
||
rep movsb
|
||
add si,bx
|
||
add di,bx
|
||
|
||
dec dx
|
||
jnz @@lineloop
|
||
|
||
mov dx,GC_INDEX+1
|
||
in al,dx
|
||
and al,NOT 3
|
||
out dx,al
|
||
|
||
mov ax,ss
|
||
mov ds,ax ;restore turbo's data segment
|
||
|
||
ret
|
||
|
||
ENDP
|
||
|
||
|
||
;===========================================================================
|
||
|
||
|
||
MASM
|
||
;<3B><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
;
|
||
; Name: VL_VideoID
|
||
;
|
||
; Function: Detects the presence of various video subsystems
|
||
;
|
||
; int VideoID;
|
||
;
|
||
; Subsystem ID values:
|
||
; 0 = (none)
|
||
; 1 = MDA
|
||
; 2 = CGA
|
||
; 3 = EGA
|
||
; 4 = MCGA
|
||
; 5 = VGA
|
||
; 80h = HGC
|
||
; 81h = HGC+
|
||
; 82h = Hercules InColor
|
||
;
|
||
;<3B><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
|
||
;<3B><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
;
|
||
; Equates
|
||
;
|
||
;<3B><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
VIDstruct STRUC ; corresponds to C data structure
|
||
|
||
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 ; subsystem types
|
||
CGA EQU 2
|
||
EGA EQU 3
|
||
MCGA EQU 4
|
||
VGA EQU 5
|
||
HGC EQU 80h
|
||
HGCPlus EQU 81h
|
||
InColor EQU 82h
|
||
|
||
MDADisplay EQU 1 ; display types
|
||
CGADisplay EQU 2
|
||
EGAColorDisplay EQU 3
|
||
PS2MonoDisplay EQU 4
|
||
PS2ColorDisplay EQU 5
|
||
|
||
TRUE EQU 1
|
||
FALSE EQU 0
|
||
|
||
;<3B><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
;
|
||
; Program
|
||
;
|
||
;<3B><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
|
||
Results VIDstruct <> ;results go here!
|
||
|
||
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 INT 10h func 1Ah
|
||
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 TRUE ; this list of flags and addresses
|
||
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
|
||
|
||
|
||
PUBLIC VL_VideoID
|
||
VL_VideoID PROC
|
||
|
||
push bp ; preserve caller registers
|
||
mov bp,sp
|
||
push ds
|
||
push si
|
||
push di
|
||
|
||
push cs
|
||
pop ds
|
||
ASSUME DS:@Code
|
||
|
||
; initialize the data structure that will contain the results
|
||
|
||
lea di,Results ; DS:DI -> start of data structure
|
||
|
||
mov Device0,0 ; zero these variables
|
||
mov Device1,0
|
||
|
||
; look for the various subsystems using the subroutines whose addresses are
|
||
; tabulated in TestSequence; each subroutine sets flags in TestSequence
|
||
; to indicate whether subsequent subroutines need to be called
|
||
|
||
mov byte ptr CGAflag,TRUE
|
||
mov byte ptr EGAflag,TRUE
|
||
mov byte ptr Monoflag,TRUE
|
||
|
||
mov cx,NumberOfTests
|
||
mov si,offset 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
|
||
|
||
mov al,Results.Video0Type
|
||
mov ah,0 ; was: Results.Display0Type
|
||
|
||
pop di ; restore caller registers and return
|
||
pop si
|
||
pop ds
|
||
mov sp,bp
|
||
pop bp
|
||
ret
|
||
|
||
VL_VideoID ENDP
|
||
|
||
|
||
;
|
||
; FindPS2
|
||
;
|
||
; This subroutine uses INT 10H function 1Ah to determine the video BIOS
|
||
; Display Combination Code (DCC) for each video subsystem present.
|
||
;
|
||
|
||
FindPS2 PROC near
|
||
|
||
mov ax,1A00h
|
||
int 10h ; call video BIOS for info
|
||
|
||
cmp al,1Ah
|
||
jne @@L13 ; exit if function not supported (i.e.,
|
||
; no MCGA or VGA in system)
|
||
|
||
; convert BIOS DCCs into specific subsystems & displays
|
||
|
||
mov cx,bx
|
||
xor bh,bh ; BX := DCC for active subsystem
|
||
|
||
or ch,ch
|
||
jz @@L11 ; jump if only one subsystem present
|
||
|
||
mov bl,ch ; BX := inactive DCC
|
||
add bx,bx
|
||
mov ax,[bx+offset DCCtable]
|
||
|
||
mov Device1,ax
|
||
|
||
mov bl,cl
|
||
xor bh,bh ; BX := active DCC
|
||
|
||
@@L11: add bx,bx
|
||
mov ax,[bx+offset 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 an 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 ; ... Hercules 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
|
||
; which doesn't exist in the default (MDA, CGA) BIOS.
|
||
|
||
FindEGA PROC near ; Caller: AH = flags
|
||
; Returns: AH = flags
|
||
; Video0Type and
|
||
; Display0Type updated
|
||
|
||
mov bl,10h ; BL := 10h (return EGA info)
|
||
mov ah,12h ; AH := INT 10H function number
|
||
int 10h ; call EGA BIOS for info
|
||
; if EGA BIOS is present,
|
||
; BL <> 10H
|
||
; CL = switch setting
|
||
cmp bl,10h
|
||
je @@L22 ; jump if EGA BIOS not present
|
||
|
||
mov al,cl
|
||
shr al,1 ; AL := switches/2
|
||
mov bx,offset EGADisplays
|
||
xlat ; determine display type from switches
|
||
mov ah,al ; AH := display type
|
||
mov al,EGA ; AL := subystem type
|
||
call FoundDevice
|
||
|
||
cmp ah,MDADisplay
|
||
je @@L21 ; jump if EGA has a monochrome display
|
||
|
||
mov CGAflag,FALSE ; no CGA if EGA has color display
|
||
jmp short @@L22
|
||
|
||
@@L21: mov Monoflag,FALSE ; EGA has a mono display, so MDA and
|
||
; Hercules are ruled out
|
||
@@L22: ret
|
||
|
||
FindEGA ENDP
|
||
|
||
;
|
||
; FindCGA
|
||
;
|
||
; This is done by looking for the CGA's 6845 CRTC at I/O port 3D4H.
|
||
;
|
||
FindCGA PROC near ; Returns: VIDstruct updated
|
||
|
||
mov dx,3D4h ; DX := CRTC address port
|
||
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 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 Status byte.
|
||
; This bit changes on Hercules adapters but does not change on an MDA.
|
||
;
|
||
; The various Hercules adapters are identified by bits 4 through 6 of
|
||
; the CRT Status value:
|
||
;
|
||
; 000b = HGC
|
||
; 001b = HGC+
|
||
; 101b = InColor card
|
||
;
|
||
|
||
FindMono PROC near ; Returns: VIDstruct updated
|
||
|
||
mov dx,3B4h ; DX := CRTC address port
|
||
call Find6845
|
||
jc @@L44 ; jump if not present
|
||
|
||
mov dl,0BAh ; 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
|
||
@@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, it's a Hercules
|
||
|
||
mov al,MDA ; if bit 7 didn't change, it's an MDA
|
||
mov ah,MDADisplay
|
||
call FoundDevice
|
||
jmp short @@L44
|
||
|
||
@@L42: in al,dx
|
||
mov dl,al ; DL := value from status port
|
||
and dl,01110000b ; mask bits 4 thru 6
|
||
|
||
mov ah,MDADisplay ; assume it's a monochrome display
|
||
|
||
mov al,HGCPlus ; look for an HGC+
|
||
cmp dl,00010000b
|
||
je @@L43 ; jump if it's an HGC+
|
||
|
||
mov al,HGC ; look for an InColor card or HGC
|
||
cmp dl,01010000b
|
||
jne @@L43 ; jump if it's not an InColor card
|
||
|
||
mov al,InColor ; it's an InColor card
|
||
mov ah,EGAColorDisplay
|
||
|
||
@@L43: call FoundDevice
|
||
|
||
@@L44: ret
|
||
|
||
FindMono ENDP
|
||
|
||
;
|
||
; Find6845
|
||
;
|
||
; This routine detects the presence of the CRTC on a MDA, CGA or HGC.
|
||
; The technique is to write and read register 0Fh of the chip (cursor
|
||
; low). If the same value is read as written, assume the chip is
|
||
; present at the specified port addr.
|
||
;
|
||
|
||
Find6845 PROC near ; Caller: DX = port addr
|
||
; Returns: cf set if not present
|
||
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 to 6845
|
||
|
||
mov cx,100h
|
||
@@L51: loop @@L51 ; 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
|
||
je @@L52 ; jump if it did (cf is reset)
|
||
|
||
stc ; set carry flag if no 6845 present
|
||
|
||
@@L52: ret
|
||
|
||
Find6845 ENDP
|
||
|
||
|
||
;
|
||
; FindActive
|
||
;
|
||
; This subroutine stores the currently active device as Device0. The
|
||
; current video mode determines which subsystem is active.
|
||
;
|
||
|
||
FindActive PROC near
|
||
|
||
cmp word ptr Device1,0
|
||
je @@L63 ; exit if only one subsystem
|
||
|
||
cmp Video0Type[di],4 ; exit if MCGA or VGA present
|
||
jge @@L63 ; (INT 10H function 1AH
|
||
cmp Video1Type[di],4 ; already did the work)
|
||
jge @@L63
|
||
|
||
mov ah,0Fh
|
||
int 10h ; AL := current BIOS video mode
|
||
|
||
and al,7
|
||
cmp al,7 ; jump if monochrome
|
||
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 monochrome
|
||
|
||
@@L62: mov ax,Device0 ; make Device0 currently active
|
||
xchg ax,Device1
|
||
mov Device0,ax
|
||
|
||
@@L63: ret
|
||
|
||
FindActive ENDP
|
||
|
||
|
||
;
|
||
; FoundDevice
|
||
;
|
||
; This routine updates the list of subsystems.
|
||
;
|
||
|
||
FoundDevice PROC near ; Caller: AH = display #
|
||
; AL = subsystem #
|
||
; Destroys: BX
|
||
lea bx,Video0Type[di]
|
||
cmp byte ptr [bx],0
|
||
je @@L71 ; jump if 1st subsystem
|
||
|
||
lea bx,Video1Type[di] ; must be 2nd subsystem
|
||
|
||
@@L71: mov [bx],ax ; update list entry
|
||
ret
|
||
|
||
FoundDevice ENDP
|
||
|
||
IDEAL
|
||
|
||
|
||
|
||
END
|