comment ^
        Sample code to show how one might detect video cards by
        using search strings.

        written on Sat  09-02-1995  by Ed Beroset
        and released to the public domain by the author

^
        .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
