home *** CD-ROM | disk | FTP | other *** search
/ Microsoft Programmer's Library 1.3 / Microsoft-Programers-Library-v1.3.iso / sampcode / video / demo / c_1.asm < prev    next >
Encoding:
Assembly Source File  |  1988-08-11  |  9.6 KB  |  460 lines

  1.         TITLE    'Listing C-1'
  2.         NAME    VideoID
  3.         PAGE    55,132
  4.  
  5. ;
  6. ; Name:        VideoID
  7. ;
  8. ; Function:    Detects the presence of various video subsystems and associated
  9. ;        monitors.
  10. ;
  11. ; Caller:    Microsoft C:
  12. ;
  13. ;            void VideoID(VIDstruct);
  14. ;
  15. ;            struct
  16. ;            {
  17. ;              char VideoSubsystem;
  18. ;              char Display;
  19. ;            }
  20. ;                *VIDstruct[2];
  21. ;
  22. ;        Subsystem ID values:
  23. ;                 0  = (none)
  24. ;                 1  = MDA
  25. ;                 2  = CGA
  26. ;                 3  = EGA
  27. ;                 4  = MCGA
  28. ;                 5  = VGA
  29. ;                80h = HGC
  30. ;                81h = HGC+
  31. ;                82h = Hercules InColor
  32. ;
  33. ;        Display types:     0  = (none)
  34. ;                 1  = MDA-compatible monochrome
  35. ;                 2  = CGA-compatible color
  36. ;                 3  = EGA-compatible color
  37. ;                 4  = PS/2-compatible monochrome
  38. ;                 5  = PS/2-compatible color
  39. ;                 
  40. ;
  41. ;    The values returned in VIDstruct[0].VideoSubsystem and
  42. ;    VIDstruct[0].Display indicate the currently active subsystem.
  43. ;
  44.  
  45. ARGpVID        EQU    word ptr [bp+4]    ; stack frame addressing
  46.  
  47.  
  48. VIDstruct    STRUC            ; corresponds to C data structure
  49.  
  50. Video0Type    DB    ?        ; first subsystem type
  51. Display0Type    DB    ?         ; display attached to first subsystem
  52.  
  53. Video1Type    DB    ?        ; second subsystem type
  54. Display1Type    DB    ?        ; display attached to second subsystem
  55.  
  56. VIDstruct    ENDS
  57.  
  58.  
  59. Device0        EQU    word ptr Video0Type[di]
  60. Device1        EQU    word ptr Video1Type[di]
  61.  
  62.  
  63. MDA        EQU    1        ; subsystem types        
  64. CGA        EQU    2
  65. EGA        EQU    3
  66. MCGA        EQU    4
  67. VGA        EQU    5
  68. HGC        EQU    80h
  69. HGCPlus        EQU    81h
  70. InColor        EQU    82h
  71.  
  72. MDADisplay    EQU    1        ; display types
  73. CGADisplay    EQU    2
  74. EGAColorDisplay    EQU    3
  75. PS2MonoDisplay    EQU    4
  76. PS2ColorDisplay    EQU    5
  77.  
  78. TRUE        EQU    1
  79. FALSE        EQU    0
  80.  
  81.  
  82. DGROUP        GROUP    _DATA
  83.  
  84. _TEXT        SEGMENT    byte public 'CODE'
  85.         ASSUME    cs:_TEXT,ds:DGROUP
  86.  
  87.         PUBLIC    _VideoID
  88. _VideoID    PROC    near
  89.  
  90.         push    bp        ; preserve caller registers
  91.         mov    bp,sp
  92.         push    si
  93.         push    di
  94.  
  95. ; initialize the data structure that will contain the results
  96.  
  97.         mov    di,ARGpVID    ; DS:DI -> start of data structure
  98.  
  99.         mov    Device0,0    ; zero these variables
  100.         mov    Device1,0
  101.  
  102. ; look for the various subsystems using the subroutines whose addresses are
  103. ;  tabulated in TestSequence; each subroutine sets flags in TestSequence
  104. ;  to indicate whether subsequent subroutines need to be called
  105.  
  106.         mov    cx,NumberOfTests
  107.         mov    si,offset DGROUP:TestSequence
  108.  
  109. L01:        lodsb            ; AL := flag
  110.         test    al,al
  111.         lodsw            ; AX := subroutine address
  112.         jz    L02        ; skip subroutine if flag is false
  113.  
  114.         push    si
  115.         push    cx
  116.         call    ax        ; call subroutine to detect subsystem
  117.         pop    cx
  118.         pop    si
  119.  
  120. L02:        loop    L01
  121.  
  122. ; determine which subsystem is active
  123.  
  124.         call    FindActive
  125.  
  126.         pop    di        ; restore caller registers and return
  127.         pop    si
  128.         mov    sp,bp
  129.         pop    bp
  130.         ret
  131.  
  132. _VideoID    ENDP
  133.  
  134.  
  135. ;
  136. ; FindPS2
  137. ;
  138. ;     This subroutine uses INT 10H function 1Ah to determine the video BIOS
  139. ;     Display Combination Code (DCC) for each video subsystem present.
  140. ;
  141.  
  142. FindPS2        PROC    near
  143.  
  144.         mov    ax,1A00h
  145.         int    10h        ; call video BIOS for info
  146.  
  147.         cmp    al,1Ah
  148.         jne    L13        ; exit if function not supported (i.e.,
  149.                     ;  no MCGA or VGA in system)
  150.  
  151. ; convert BIOS DCCs into specific subsystems & displays
  152.  
  153.         mov    cx,bx
  154.         xor    bh,bh        ; BX := DCC for active subsystem
  155.  
  156.         or    ch,ch
  157.         jz    L11        ; jump if only one subsystem present
  158.  
  159.         mov    bl,ch        ; BX := inactive DCC
  160.         add    bx,bx
  161.         mov    ax,[bx+offset DGROUP:DCCtable]
  162.  
  163.         mov    Device1,ax
  164.  
  165.         mov    bl,cl
  166.         xor    bh,bh        ; BX := active DCC
  167.  
  168. L11:        add    bx,bx
  169.         mov    ax,[bx+offset DGROUP:DCCtable]
  170.  
  171.         mov    Device0,ax
  172.  
  173. ; reset flags for subsystems that have been ruled out
  174.  
  175.         mov    byte ptr CGAflag,FALSE
  176.         mov    byte ptr EGAflag,FALSE
  177.         mov    byte ptr Monoflag,FALSE
  178.  
  179.         lea    bx,Video0Type[di]  ; if the BIOS reported an MDA ...
  180.         cmp    byte ptr [bx],MDA
  181.         je    L12
  182.  
  183.         lea    bx,Video1Type[di]
  184.         cmp    byte ptr [bx],MDA
  185.         jne    L13
  186.  
  187. L12:        mov    word ptr [bx],0    ; ... Hercules can't be ruled out
  188.         mov    byte ptr Monoflag,TRUE
  189.  
  190. L13:        ret
  191.  
  192. FindPS2        ENDP
  193.  
  194.  
  195. ;
  196. ; FindEGA
  197. ;
  198. ; Look for an EGA.  This is done by making a call to an EGA BIOS function
  199. ;  which doesn't exist in the default (MDA, CGA) BIOS.
  200.  
  201. FindEGA        PROC    near        ; Caller:    AH = flags
  202.                     ; Returns:    AH = flags
  203.                     ;        Video0Type and
  204.                     ;         Display0Type updated
  205.  
  206.         mov    bl,10h        ; BL := 10h (return EGA info)
  207.         mov    ah,12h        ; AH := INT 10H function number
  208.         int    10h        ; call EGA BIOS for info
  209.                     ; if EGA BIOS is present,
  210.                     ;  BL <> 10H
  211.                     ;  CL = switch setting
  212.         cmp    bl,10h
  213.         je    L22        ; jump if EGA BIOS not present
  214.  
  215.         mov    al,cl
  216.         shr    al,1        ; AL := switches/2
  217.         mov    bx,offset DGROUP:EGADisplays
  218.         xlat            ; determine display type from switches
  219.         mov    ah,al        ; AH := display type
  220.         mov    al,EGA        ; AL := subystem type
  221.         call    FoundDevice
  222.  
  223.         cmp    ah,MDADisplay
  224.         je    L21        ; jump if EGA has a monochrome display
  225.  
  226.         mov    CGAflag,FALSE    ; no CGA if EGA has color display
  227.         jmp    short L22
  228.  
  229. L21:        mov    Monoflag,FALSE    ; EGA has a mono display, so MDA and
  230.                     ;  Hercules are ruled out
  231. L22:        ret
  232.  
  233. FindEGA        ENDP
  234.  
  235.  
  236. ;
  237. ; FindCGA
  238. ;
  239. ;    This is done by looking for the CGA's 6845 CRTC at I/O port 3D4H.
  240. ;
  241.  
  242. FindCGA        PROC    near        ; Returns:    VIDstruct updated
  243.  
  244.         mov    dx,3D4h        ; DX := CRTC address port
  245.         call    Find6845
  246.         jc    L31        ; jump if not present
  247.  
  248.         mov    al,CGA
  249.         mov    ah,CGADisplay
  250.         call    FoundDevice
  251.  
  252. L31:        ret
  253.  
  254. FindCGA        ENDP
  255.  
  256.  
  257. ;
  258. ; FindMono
  259. ;
  260. ;    This is done by looking for the MDA's 6845 CRTC at I/O port 3B4H.  If
  261. ;    a 6845 is found, the subroutine distinguishes between an MDA
  262. ;    and a Hercules adapter by monitoring bit 7 of the CRT Status byte.
  263. ;    This bit changes on Hercules adapters but does not change on an MDA.
  264. ;
  265. ;    The various Hercules adapters are identified by bits 4 through 6 of
  266. ;    the CRT Status value:
  267. ;
  268. ;        000b = HGC
  269. ;        001b = HGC+
  270. ;        101b = InColor card
  271. ;
  272.  
  273. FindMono    PROC    near        ; Returns:    VIDstruct updated
  274.  
  275.         mov    dx,3B4h        ; DX := CRTC address port
  276.         call    Find6845
  277.         jc    L44        ; jump if not present
  278.  
  279.         mov    dl,0BAh        ; DX := 3BAh (status port)
  280.         in    al,dx
  281.         and    al,80h
  282.         mov    ah,al        ; AH := bit 7 (vertical sync on HGC)
  283.  
  284.         mov    cx,8000h    ; do this 32768 times 
  285. L41:        in    al,dx
  286.         and    al,80h        ; isolate bit 7
  287.         cmp    ah,al
  288.         loope    L41        ; wait for bit 7 to change
  289.  
  290.         jne    L42        ; if bit 7 changed, it's a Hercules
  291.  
  292.         mov    al,MDA        ; if bit 7 didn't change, it's an MDA
  293.         mov    ah,MDADisplay
  294.         call    FoundDevice
  295.         jmp    short L44
  296.  
  297. L42:        in    al,dx
  298.         mov    dl,al        ; DL := value from status port
  299.  
  300.         mov    ah,MDADisplay    ; assume it's a monochrome display
  301.  
  302.         mov    al,HGC        ; look for an HGC
  303.         and    dl,01110000b    ; mask off bits 4 thru 6
  304.         jz    L43
  305.  
  306.         mov    al,HGCPlus    ; look for an HGC+
  307.         cmp    dl,00010000b
  308.         je    L43        ; jump if it's an HGC+
  309.  
  310.         mov    al,InColor    ; it's an InColor card
  311.         mov    ah,EGAColorDisplay
  312.  
  313. L43:        call    FoundDevice
  314.  
  315. L44:        ret
  316.  
  317. FindMono    ENDP
  318.  
  319.  
  320. ;
  321. ; Find6845
  322. ;
  323. ;    This routine detects the presence of the CRTC on a MDA, CGA or HGC.
  324. ;    The technique is to write and read register 0Fh of the chip (cursor
  325. ;    low).  If the same value is read as written, assume the chip is
  326. ;    present at the specified port addr.
  327. ;
  328.  
  329. Find6845    PROC    near        ; Caller:    DX = port addr
  330.                     ; Returns:    cf set if not present
  331.         mov    al,0Fh
  332.         out    dx,al        ; select 6845 reg 0Fh (Cursor Low)
  333.         inc    dx
  334.         in    al,dx        ; AL := current Cursor Low value
  335.         mov    ah,al        ; preserve in AH
  336.         mov    al,66h        ; AL := arbitrary value
  337.         out    dx,al        ; try to write to 6845
  338.  
  339.         mov    cx,100h
  340. L51:        loop    L51        ; wait for 6845 to respond
  341.  
  342.         in    al,dx
  343.         xchg    ah,al        ; AH := returned value
  344.                     ; AL := original value
  345.         out    dx,al        ; restore original value
  346.  
  347.         cmp    ah,66h        ; test whether 6845 responded
  348.         je    L52        ; jump if it did (cf is reset)
  349.  
  350.         stc            ; set carry flag if no 6845 present
  351.  
  352. L52:        ret    
  353.     
  354. Find6845    ENDP
  355.  
  356.  
  357. ;
  358. ; FindActive
  359. ;
  360. ;    This subroutine stores the currently active device as Device0.  The
  361. ;    current video mode determines which subsystem is active.
  362. ;
  363.  
  364. FindActive    PROC    near
  365.  
  366.         cmp    word ptr Device1,0
  367.         je    L63            ; exit if only one subsystem
  368.  
  369.         cmp    Video0Type[di],4    ; exit if MCGA or VGA present
  370.         jge    L63            ;  (INT 10H function 1AH
  371.         cmp    Video1Type[di],4    ;  already did the work)
  372.         jge    L63
  373.  
  374.         mov    ah,0Fh
  375.         int    10h            ; AL := current BIOS video mode
  376.  
  377.         and    al,7
  378.         cmp    al,7            ; jump if monochrome
  379.         je    L61            ;  (mode 7 or 0Fh)
  380.  
  381.         cmp    Display0Type[di],MDADisplay
  382.         jne    L63            ; exit if Display0 is color
  383.         jmp    short L62
  384.  
  385. L61:        cmp    Display0Type[di],MDADisplay
  386.         je    L63            ; exit if Display0 is monochrome
  387.  
  388. L62:        mov    ax,Device0        ; make Device0 currently active
  389.         xchg    ax,Device1
  390.         mov    Device0,ax
  391.  
  392. L63:        ret
  393.  
  394. FindActive    ENDP
  395.  
  396.  
  397. ;
  398. ; FoundDevice
  399. ;
  400. ;    This routine updates the list of subsystems.
  401. ;
  402.  
  403. FoundDevice    PROC    near            ; Caller:    AH = display #
  404.                         ;         AL = subsystem #
  405.                         ; Destroys:  BX
  406.         lea    bx,Video0Type[di]
  407.         cmp    byte ptr [bx],0
  408.         je    L71            ; jump if 1st subsystem
  409.  
  410.         lea    bx,Video1Type[di]    ; must be 2nd subsystem
  411.  
  412. L71:        mov    [bx],ax            ; update list entry
  413.         ret
  414.  
  415. FoundDevice    ENDP
  416.  
  417. _TEXT        ENDS
  418.  
  419.  
  420. _DATA        SEGMENT    word public 'DATA'
  421.  
  422. EGADisplays    DB    CGADisplay    ; 0000b, 0001b    (EGA switch values)
  423.         DB    EGAColorDisplay    ; 0010b, 0011b
  424.         DB    MDADisplay    ; 0100b, 0101b
  425.         DB    CGADisplay    ; 0110b, 0111b
  426.         DB    EGAColorDisplay    ; 1000b, 1001b
  427.         DB    MDADisplay    ; 1010b, 1011b
  428.  
  429. DCCtable    DB    0,0        ; translate table for INT 10h func 1Ah
  430.         DB    MDA,MDADisplay
  431.         DB    CGA,CGADisplay
  432.         DB    0,0
  433.         DB    EGA,EGAColorDisplay
  434.         DB    EGA,MDADisplay
  435.         DB    0,0
  436.         DB    VGA,PS2MonoDisplay
  437.         DB    VGA,PS2ColorDisplay
  438.         DB    0,0
  439.         DB    MCGA,EGAColorDisplay
  440.         DB    MCGA,PS2MonoDisplay
  441.         DB    MCGA,PS2ColorDisplay
  442.  
  443. TestSequence    DB    TRUE        ; this list of flags and addresses
  444.         DW    FindPS2        ;  determines the order in which this
  445.                     ;  program looks for the various
  446. EGAflag        DB    TRUE        ;  subsystems
  447.         DW    FindEGA
  448.  
  449. CGAflag        DB    TRUE
  450.         DW    FindCGA
  451.  
  452. Monoflag    DB    TRUE
  453.         DW    FindMono
  454.  
  455. NumberOfTests    EQU    ($-TestSequence)/3
  456.  
  457. _DATA        ENDS
  458.  
  459.         END
  460.