You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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