154 lines
6.5 KiB
NASM
154 lines
6.5 KiB
NASM
comment ^
|
|
Sample code to show how one might detect video cards by
|
|
using search strings.
|
|
^
|
|
.model small
|
|
.stack 400h
|
|
.data
|
|
;/***************************************************************************
|
|
; some handy equates
|
|
;***************************************************************************/
|
|
VID_BIOS_SEG equ 0c000h ; the video BIOS segment
|
|
|
|
SEARCH_AREA equ 0400h ; when we look for the video BIOS
|
|
; ID, we only seach this many bytes
|
|
|
|
CMP_LENGTH equ 7 ; the number of "significant"
|
|
; characters to compare in each
|
|
; string
|
|
|
|
DOS_INT equ 21h ; DOS' interrupt
|
|
VIDEO_INT equ 10h ; BIOS' video services int
|
|
|
|
VID_80x25 equ 03h ; 80x25 text mode number
|
|
|
|
;/***************************************************************************
|
|
; data
|
|
;***************************************************************************/
|
|
UnknownCardMsg db 'Your video card is not supported.',13,10,'$'
|
|
|
|
mode1 db 053h ; 640 x 480 x 256 mode for Oak
|
|
card1 db 'OAK VGA','$'
|
|
mode2 db 05dh ; 640 x 480 x 256 mode for Trident
|
|
card2 db 'TRIDENT','$'
|
|
|
|
cards dw card1, card2, 0
|
|
|
|
;/***************************************************************************
|
|
; some handy macros
|
|
;***************************************************************************/
|
|
@DosPrint MACRO msgptr
|
|
mov dx,msgptr ; handy macro for printing
|
|
mov ah,9 ; '$' terminated strings
|
|
int DOS_INT ; under DOS
|
|
ENDM
|
|
|
|
@SetVidMode MACRO vmode
|
|
ifnb <vmode>
|
|
mov ax,(vmode AND 0ffh)
|
|
else
|
|
xor ah,ah
|
|
endif
|
|
int VIDEO_INT
|
|
ENDM
|
|
|
|
.code
|
|
;/***************************************************************************
|
|
; main
|
|
; This is the main procedure in the code. It identifies (or
|
|
; attempts to identify) the type of video card, then switches into
|
|
; the appropriate video mode for that type of card. Right now, it
|
|
; doesn't actually do anything in that mode, but simply returns
|
|
; and restores the video mode to a fairly standard 80x25 text
|
|
; mode. Mostly as an aid to troubleshooting, the current version
|
|
; also prints out the name of the video card as discovered in the
|
|
; video BIOS area.
|
|
;
|
|
;***************************************************************************/
|
|
main proc
|
|
.STARTUP ; do the usual startup stuff
|
|
call IDVideoBios ; identify video BIOS
|
|
or si,si ; Q: unknown card?
|
|
jz NoSupport ; Y: tell the user the bad news
|
|
dec si ; point to video mode (mode1, mode2)
|
|
lodsb ; load into al & increment si
|
|
@SetVidMode ; change video mode
|
|
;
|
|
; snazzy graphics code goes here
|
|
;
|
|
@SetVidMode <VID_80x25> ; switch back to 80x25 text mode
|
|
@DosPrint <si> ; print ID string
|
|
.EXIT 0 ; exit with error code = 0
|
|
|
|
NoSupport:
|
|
@DosPrint <offset UnknownCardMsg> ; print unknown card message
|
|
.EXIT 1 ; exit with error code = 1
|
|
main endp
|
|
|
|
;/***************************************************************************
|
|
; IDVideoBios
|
|
;
|
|
; This procedure searches the first SEARCH_AREA bytes in the video
|
|
; BIOS for a byte sequence which uniquely identifies a video
|
|
; card's manufacturer. If no known card name is found, the
|
|
; function returns a null pointer.
|
|
;
|
|
; Entry: DS contains the segment of the cards array
|
|
;
|
|
; Exit: If a match was found,
|
|
; DS:SI ==> matching sequence
|
|
; otherwise
|
|
; SI = 0
|
|
;
|
|
; Destroyed: none
|
|
;
|
|
;***************************************************************************/
|
|
IDVideoBios proc
|
|
push ax ; save used regs
|
|
push bx ;
|
|
push cx ;
|
|
push es ;
|
|
mov ax,VID_BIOS_SEG ; point to video BIOS
|
|
mov es,ax ;
|
|
mov bx,OFFSET cards ; point to first card entry
|
|
cld ; we'll be scanning forward
|
|
next_card:
|
|
mov si,[bx] ;
|
|
or si,si ; Q: is it a NULL pointer?
|
|
jz @@exit ; Y: we're done, so exit now
|
|
xor di,di ; es:di ==> video BIOS area
|
|
mov cx,SEARCH_AREA ;
|
|
mov al,[si] ; get the first letter
|
|
scan:
|
|
repne scasb ; scan for AL in es:di
|
|
jnz nofind ; if we didn't find it, skip over
|
|
;
|
|
; if we got here, ES:DI points to one letter after the matching letter
|
|
; in the video BIOS. We need to compare the rest to assure that we have
|
|
; a complete match.
|
|
;
|
|
push cx ; temporarily save regs
|
|
push di ;
|
|
push si ;
|
|
inc si ; point to next letter
|
|
mov cx,CMP_LENGTH-1 ; compare the rest the string
|
|
repe cmpsb ; do it
|
|
pop si ; restore regs
|
|
pop di ;
|
|
pop cx ;
|
|
jz @@exit ; if match, we're done
|
|
nofind:
|
|
or cx,cx ; Q: is the count down to zero?
|
|
jnz scan ; N: keep scanning
|
|
inc bx ; Y: point to next card
|
|
inc bx ; point to next card entry
|
|
jmp next_card ; go back for more
|
|
@@exit:
|
|
pop es ; restore used registers
|
|
pop cx ;
|
|
pop bx ;
|
|
pop ax ;
|
|
ret ;
|
|
IDVideoBios endp
|
|
|
|
end |