home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / PROGRAMS / UTILS / HARDWARE / SHOW285.ZIP / VIDEO_ID.ASM < prev    next >
Encoding:
Assembly Source File  |  1990-04-02  |  8.0 KB  |  393 lines

  1. ;  Adapted from "Programmer's Guide to PC and PS/2 Video Systems",
  2. ;  by Richard Wilton and published by Microsoft Press in 1987.
  3. ;
  4.         public    FindPS2,FindEGA,FindCGA,FindMono,Find6845
  5.         public    FindActive,FoundDevice
  6.  
  7.  
  8.  
  9. ARGpVID        equ    word ptr [bp+4]    ; stack frame addressing
  10.  
  11. VIDstruct    struc            ; corresponds to C struc
  12.  
  13. Video0Type    db    ?        ; first subsystem type
  14. Display0Type    db    ?        ; display attached to first subsystem
  15. Video1Type    db    ?        ; second subsystem type
  16. Display1Type    db    ?        ; display attached to second subsystem
  17.  
  18. VIDstruct    ends
  19.  
  20. Device0        equ    word ptr Video0Type[di]
  21. Device1        equ    word ptr Video1Type[di]
  22.  
  23. MDA        equ    1
  24. CGA        equ    2
  25. EGA        equ    3
  26. MCGA        equ    4
  27. VGA        equ    5
  28. HGC        equ    80h
  29. HGCPlus        equ    81h
  30. InColor        equ    82h
  31. HGCclone    equ    83h
  32.  
  33. MDADisplay    equ    1
  34. CGADisplay    equ    2
  35. EGAColorDisplay    equ    3
  36. PS2MonoDisplay    equ    4
  37. PS2ColorDisplay    equ    5
  38.  
  39. TRUE        equ    1
  40. FALSE        equ    0
  41.  
  42. DGROUP        GROUP    _DATA
  43.  
  44. _TEXT        SEGMENT byte public 'CODE'
  45.         assume cs:_TEXT,ds:DGROUP
  46.  
  47.         public    _VideoID
  48. _VideoID    proc    near
  49.  
  50.         push    bp
  51.         mov    bp,sp
  52.         push    si
  53.         push    di
  54.  
  55. ; initialize the data structure that will contain the results
  56.  
  57.         mov    di,ARGpVID    ; DS;DI -> start of data structure
  58.  
  59.         mov    Device0,0
  60.         mov    Device1,0
  61.  
  62. ; look for the various subsystems using the subroutines whose addresses are
  63. ; tabulated in TestSequence; each subroutine sets flags in Test Sequence
  64. ; to indicate whether subsequent subroutines need to be called
  65.  
  66.         mov    byte ptr TestSequence,TRUE
  67.         mov    byte ptr CGAflag,TRUE
  68.         mov    byte ptr EGAflag,TRUE
  69.         mov    byte ptr Monoflag,TRUE
  70.         mov    cx,NumberOfTests
  71.         mov    si,offset DGROUP:TestSequence
  72.  
  73. L01:        lodsb            ; al := flag
  74.         test    al,al
  75.         lodsw            ; ax := subroutine address
  76.         jz    L02        ; skip subroutine if flag is false
  77.  
  78.         push    si
  79.         push    cx
  80.         call    ax        ; call subroutine to detect subsystem
  81.         pop    cx
  82.         pop    si
  83.  
  84. L02:        loop    L01
  85.  
  86. ; determine which subsystem is active
  87.  
  88.         call     FindActive
  89.         pop    di
  90.         pop    si
  91.         mov    sp,bp
  92.         pop    bp
  93.         ret
  94.  
  95. _VideoID    endp
  96.  
  97. ;
  98. ; FindPS2
  99. ;
  100. ;    This subroutine uses INT 10 function 1A to determine the video BIOS
  101. ;    DCC for each video subsystem.
  102. ;
  103. FindPS2        proc    near
  104.         mov    ax,1a00h
  105.         int    10h
  106.  
  107.         cmp    al,1ah
  108.         jne    L13        ; exit if 1A call not supported
  109.  
  110. ; convert DCC into specific subsystems and displays
  111.  
  112.         mov    cx,bx
  113.         xor    bh,bh        ; BX := DCC for active subsystem
  114.         or    ch,ch
  115.         jz    L11        ; jump if only on subsystem
  116.  
  117.         mov    bl,ch        ; BX := inactive DCC
  118.         add    bx,bx
  119.         mov    ax,[bx+offset DGROUP:DCCtable]
  120.         mov    Device1,ax
  121.  
  122.         mov    bl,cl
  123.         xor    bh,bh        ; BX := active DCC
  124.  
  125. L11:        add    bx,bx
  126.         mov    ax,[bx+offset DGROUP:DCCtable]
  127.         mov    Device0,ax
  128.  
  129. ; reset flags for subsystems that have been ruled out
  130.  
  131.         mov    byte ptr CGAflag,FALSE
  132.         mov    byte ptr EGAflag,FALSE
  133.         mov    byte ptr Monoflag,FALSE
  134.  
  135.         lea    bx,Video0Type[di]    ; if the BIOS reported and MDA
  136.         cmp    byte ptr [bx],MDA
  137.         je    L12
  138.  
  139.         lea    bx,Video1Type[di]
  140.         cmp    byte ptr [bx],MDA
  141.         jne    L13
  142.  
  143. L12:        mov    word ptr [bx],0        ; Herc can't be ruled out
  144.         mov    byte ptr Monoflag,TRUE
  145.  
  146. L13:        ret
  147.  
  148. FindPS2        endp
  149.  
  150. ; FindEGA
  151. ;    Look for an EGA.  This is done by making a call to an EGA BIOS 
  152. ;    function that doesn't exist on the planer BIOS.
  153. ;
  154.  
  155. FindEGA        proc    near            ; Caller:    AH = flags
  156.                         ; Returns:    AH = flags
  157.                         ;         Video0Type and
  158.                         ;        Display0Type
  159.                         ;        updated.
  160.  
  161.         mov    ah,12h            ; BIOS function 12
  162.         mov    bl,10h            ;
  163.         int    10h            ; if EGA BIOS is present,
  164.                         ; bl <> 10h, cl = switch
  165.  
  166.         cmp    bl,10h            ; is EGA BIOS present?
  167.         je    L22            ; no
  168.  
  169.         mov    al,cl
  170.         shr    al,1            ; al := switches/2
  171.         mov    bx,offset DGROUP:EGADisplays
  172.         xlat                ; determine display type
  173.                         ; from switches
  174.         mov    ah,al            ; ah := display type
  175.         mov    al,EGA            ; al := subsystem type
  176.         call    FoundDevice
  177.  
  178.         cmp    ah,MDADisplay        ; monochrome display?
  179.         je    L21            ; yes
  180.  
  181.         mov    CGAflag,FALSE        ; no CGA if EGA has color
  182.         jmp    short L22
  183.  
  184. L21:        mov    Monoflag,FALSE        ; no mono if EGA has mono
  185.  
  186. L22:        ret
  187.  
  188. FindEGA        endp
  189.  
  190. ; FindCGA
  191. ;    Look for a 6845 at I/O port 3D4h
  192. ;
  193. FindCGA        proc    near            ; returns:  VIDstruc updated
  194.  
  195.         mov    dx,3d4h            ; dx := 6845 address
  196.         call    Find6845
  197.         jc    L31            ; jump if not present
  198.  
  199.         mov    al,CGA
  200.         mov    ah,CGADisplay
  201.         call    FoundDevice
  202.  
  203. L31:        ret
  204.  
  205. FindCGA        endp
  206.  
  207. ; FindMono
  208. ;    This is done by looking for the MDA's 6845 at 3B4h.  If a 6845
  209. ;    is found, the subroutine distinguishes between an MDA and a 
  210. ;    Hercules adapter by monitoring bit 7 of the CRT Status byte.
  211. ;    This bit changes on Herc adapters, but not on an MDA.  The
  212. ;    various Herc adapters are identified by bits 4 through 6 of
  213. ;    the CRT Status value:
  214. ;                000b = HGC
  215. ;                001b = HGC+
  216. ;                101b = InColor Card
  217. ;
  218.  
  219. FindMono    proc    near
  220.  
  221.         mov    dx,3b4h
  222.         call    Find6845
  223.         jc    L44            ; jump if not present
  224.  
  225.         mov    dl,0bah            ; dx := 3ba (status port)
  226.         in    al,dx
  227.         and    al,80h
  228.         mov    ah,al            ; ah := bit 7 (herc Vsync)
  229.  
  230.         mov    cx,8000h        ; do this 8000h times
  231. L41:        in    al,dx
  232.         and    al,80h            ; isolate bit 7
  233.         cmp    ah,al
  234.         loope    L41            ; wait for bit 7 to change
  235.  
  236.         jne    L42            ; if bit 7 changed, its a herc
  237.  
  238.         mov    al,MDA            ; if not, it's an MDA
  239.         mov    ah,MDADisplay
  240.         call    FoundDevice
  241.         jmp    short L44
  242.  
  243. L42:        in    al,dx
  244.         mov    dl,al            ; dl := value from status port
  245.  
  246.         mov    ah,MDADisplay        ; assume it's a mono display
  247.  
  248.         mov    al,HGC            ; look for an HGC
  249.         and    dl,01110000b        ; mask off bits 4-6
  250.         jz    L43            ; it is an HGC
  251.  
  252.         mov    al,HGCPlus        ; look for an HGC+
  253.         cmp    dl,00010000b
  254.         je    L43            ; jump if HGC+
  255.  
  256.         mov    al,InColor        ; look for an InColor
  257.         mov    ah,EGAColorDisplay
  258.         cmp    dl,01010000b
  259.         je    L43            ; jump if Incolor
  260.  
  261.         mov    al,HGCclone        ; must be a Herc clone
  262.         mov    ah,MDADisplay
  263.  
  264. L43:        call    FoundDevice
  265.  
  266. L44:        ret
  267.  
  268. FindMono    endp
  269.  
  270. ; Find6845
  271.  
  272. Find6845    proc    near            ; Input:  DX = port address
  273.                         ; Return: c set if not present
  274.         mov    al,0fh
  275.         out    dx,al            ; select index 0f (cursor low)
  276.         inc    dx            ; data port
  277.  
  278.         in    al,dx            ; al := cursor low
  279.         mov    ah,al            ; save in ah
  280.         mov    al,66h            ; al = arbitrary value
  281.         out    dx,al            ; try to write to 6845
  282.  
  283.         mov    cx,100h
  284. L51:        loop    L51            ; wait for 6845
  285.  
  286.         in    al,dx
  287.         xchg    ah,al            ; ah := returned value
  288.                         ; al := original value
  289.         out    dx,al            ; restore original value
  290.  
  291.         cmp    ah,66h            ; did we get it back?
  292.         je    L52            ; yes
  293.  
  294.         stc                ; set carry if no 6845
  295.  
  296. L52:        ret
  297.  
  298. Find6845    endp
  299.  
  300. ; FindActive
  301.  
  302. FindActive    proc    near
  303.  
  304.         cmp    word ptr Device1,0    ; is there a 2nd subsystem?
  305.         je    L63            ; no
  306.  
  307.         cmp    Video0Type[di],4    ; exit if MCGA or VGA
  308.         jge    L63            ; (func 1A already did this)
  309.         cmp    Video1Type[di],4
  310.         jge    L63
  311.  
  312.         mov    ah,0fh
  313.         int    10h            ; get mode
  314.  
  315.         and    al,7
  316.         cmp    al,7            ; jump if mono
  317.         je    L61            ; (mode 7 or 0fh)
  318.  
  319.         cmp    Display0Type[di],MDADisplay
  320.         jne    L63            ; exit if Display0 is color
  321.         jmp    short L62
  322.  
  323. L61:        cmp    Display0Type[di],MDADisplay
  324.         je    L63            ; exit if Display0 is mono
  325.  
  326. L62:        mov    ax,Device0        ; make Device0 active
  327.         xchg    ax,Device1
  328.         mov    Device0,ax
  329.  
  330. L63:        ret
  331.  
  332. FindActive    endp
  333.  
  334. ; FoundDevice
  335. ;
  336. FoundDevice    proc    near            ; Input:  AH = display #
  337.                         ;      AL = subsystem #
  338.  
  339.         lea    bx,Video0Type[di]
  340.         cmp    byte ptr [bx],0
  341.         je    L71            ; jump if first subsystem
  342.  
  343.         lea    bx,Video1Type[di]    ; must be second subsystem
  344.  
  345. L71:        mov    [bx],ax            ; update list entry
  346.         ret
  347.  
  348. FoundDevice    endp
  349.  
  350. _TEXT        ends
  351.  
  352. _DATA        SEGMENT word public 'DATA'
  353.  
  354. EGADisplays    db    CGADisplay    ; 0000b, 0001b (EGA switch values)
  355.         db    EGAColorDisplay    ; 0010b, 0011b
  356.         db    MDADisplay    ; 0100b, 0101b
  357.         db    CGADisplay    ; 0110b, 0111b
  358.         db    EGAColorDisplay    ; 1000b, 1001b
  359.         db    MDADisplay    ; 1010b, 1011b
  360.  
  361. DCCtable    db    0,0        ; translate table for function 1A
  362.         db    MDA,MDADisplay
  363.         db    CGA,CGADisplay
  364.         db    0,0
  365.         db    EGA,EGAColorDisplay
  366.         db    EGA,MDADisplay
  367.         db    0,0
  368.         db    VGA,PS2MonoDisplay
  369.         db    VGA,PS2ColorDisplay
  370.         db    0,0
  371.         db    MCGA,EGAColorDisplay
  372.         db    MCGA,PS2MonoDisplay
  373.         db    MCGA,PS2ColorDisplay
  374.  
  375. TestSequence    db    ?        ; this list of flags and address
  376.         dw    FindPS2        ; determines the order in which this
  377.                     ; program looks for the various
  378. EGAflag        db    ?        ; subsystems
  379.         dw    FindEGA
  380.  
  381. CGAflag        db    ?
  382.         dw    FindCGA
  383.  
  384. Monoflag    db    ?
  385.         dw    FindMono
  386.  
  387. NumberOfTests    equ    ($-TestSequence)/3
  388.  
  389. _DATA        ends
  390.  
  391.         end
  392.