home *** CD-ROM | disk | FTP | other *** search
/ Microsoft Programmer's Library 1.3 / Microsoft-Programers-Library-v1.3.iso / sampcode / video / c / c_1.asm next >
Encoding:
Assembly Source File  |  1988-08-11  |  9.8 KB  |  464 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     byte ptr CGAflag,TRUE
  107.                 mov     byte ptr EGAflag,TRUE
  108.                 mov     byte ptr Monoflag,TRUE
  109.  
  110.         mov    cx,NumberOfTests
  111.         mov    si,offset DGROUP:TestSequence
  112.  
  113. L01:        lodsb            ; AL := flag
  114.         test    al,al
  115.         lodsw            ; AX := subroutine address
  116.         jz    L02        ; skip subroutine if flag is false
  117.  
  118.         push    si
  119.         push    cx
  120.         call    ax        ; call subroutine to detect subsystem
  121.         pop    cx
  122.         pop    si
  123.  
  124. L02:        loop    L01
  125.  
  126. ; determine which subsystem is active
  127.  
  128.         call    FindActive
  129.  
  130.         pop    di        ; restore caller registers and return
  131.         pop    si
  132.         mov    sp,bp
  133.         pop    bp
  134.         ret
  135.  
  136. _VideoID    ENDP
  137.  
  138.  
  139. ;
  140. ; FindPS2
  141. ;
  142. ;     This subroutine uses INT 10H function 1Ah to determine the video BIOS
  143. ;     Display Combination Code (DCC) for each video subsystem present.
  144. ;
  145.  
  146. FindPS2        PROC    near
  147.  
  148.         mov    ax,1A00h
  149.         int    10h        ; call video BIOS for info
  150.  
  151.         cmp    al,1Ah
  152.         jne    L13        ; exit if function not supported (i.e.,
  153.                     ;  no MCGA or VGA in system)
  154.  
  155. ; convert BIOS DCCs into specific subsystems & displays
  156.  
  157.         mov    cx,bx
  158.         xor    bh,bh        ; BX := DCC for active subsystem
  159.  
  160.         or    ch,ch
  161.         jz    L11        ; jump if only one subsystem present
  162.  
  163.         mov    bl,ch        ; BX := inactive DCC
  164.         add    bx,bx
  165.         mov    ax,[bx+offset DGROUP:DCCtable]
  166.  
  167.         mov    Device1,ax
  168.  
  169.         mov    bl,cl
  170.         xor    bh,bh        ; BX := active DCC
  171.  
  172. L11:        add    bx,bx
  173.         mov    ax,[bx+offset DGROUP:DCCtable]
  174.  
  175.         mov    Device0,ax
  176.  
  177. ; reset flags for subsystems that have been ruled out
  178.  
  179.         mov    byte ptr CGAflag,FALSE
  180.         mov    byte ptr EGAflag,FALSE
  181.         mov    byte ptr Monoflag,FALSE
  182.  
  183.         lea    bx,Video0Type[di]  ; if the BIOS reported an MDA ...
  184.         cmp    byte ptr [bx],MDA
  185.         je    L12
  186.  
  187.         lea    bx,Video1Type[di]
  188.         cmp    byte ptr [bx],MDA
  189.         jne    L13
  190.  
  191. L12:        mov    word ptr [bx],0    ; ... Hercules can't be ruled out
  192.         mov    byte ptr Monoflag,TRUE
  193.  
  194. L13:        ret
  195.  
  196. FindPS2        ENDP
  197.  
  198.  
  199. ;
  200. ; FindEGA
  201. ;
  202. ; Look for an EGA.  This is done by making a call to an EGA BIOS function
  203. ;  which doesn't exist in the default (MDA, CGA) BIOS.
  204.  
  205. FindEGA        PROC    near        ; Caller:    AH = flags
  206.                     ; Returns:    AH = flags
  207.                     ;        Video0Type and
  208.                     ;         Display0Type updated
  209.  
  210.         mov    bl,10h        ; BL := 10h (return EGA info)
  211.         mov    ah,12h        ; AH := INT 10H function number
  212.         int    10h        ; call EGA BIOS for info
  213.                     ; if EGA BIOS is present,
  214.                     ;  BL <> 10H
  215.                     ;  CL = switch setting
  216.         cmp    bl,10h
  217.         je    L22        ; jump if EGA BIOS not present
  218.  
  219.         mov    al,cl
  220.         shr    al,1        ; AL := switches/2
  221.         mov    bx,offset DGROUP:EGADisplays
  222.         xlat            ; determine display type from switches
  223.         mov    ah,al        ; AH := display type
  224.         mov    al,EGA        ; AL := subystem type
  225.         call    FoundDevice
  226.  
  227.         cmp    ah,MDADisplay
  228.         je    L21        ; jump if EGA has a monochrome display
  229.  
  230.         mov    CGAflag,FALSE    ; no CGA if EGA has color display
  231.         jmp    short L22
  232.  
  233. L21:        mov    Monoflag,FALSE    ; EGA has a mono display, so MDA and
  234.                     ;  Hercules are ruled out
  235. L22:        ret
  236.  
  237. FindEGA        ENDP
  238.  
  239.  
  240. ;
  241. ; FindCGA
  242. ;
  243. ;    This is done by looking for the CGA's 6845 CRTC at I/O port 3D4H.
  244. ;
  245.  
  246. FindCGA        PROC    near        ; Returns:    VIDstruct updated
  247.  
  248.         mov    dx,3D4h        ; DX := CRTC address port
  249.         call    Find6845
  250.         jc    L31        ; jump if not present
  251.  
  252.         mov    al,CGA
  253.         mov    ah,CGADisplay
  254.         call    FoundDevice
  255.  
  256. L31:        ret
  257.  
  258. FindCGA        ENDP
  259.  
  260.  
  261. ;
  262. ; FindMono
  263. ;
  264. ;    This is done by looking for the MDA's 6845 CRTC at I/O port 3B4H.  If
  265. ;    a 6845 is found, the subroutine distinguishes between an MDA
  266. ;    and a Hercules adapter by monitoring bit 7 of the CRT Status byte.
  267. ;    This bit changes on Hercules adapters but does not change on an MDA.
  268. ;
  269. ;    The various Hercules adapters are identified by bits 4 through 6 of
  270. ;    the CRT Status value:
  271. ;
  272. ;        000b = HGC
  273. ;        001b = HGC+
  274. ;        101b = InColor card
  275. ;
  276.  
  277. FindMono    PROC    near        ; Returns:    VIDstruct updated
  278.  
  279.         mov    dx,3B4h        ; DX := CRTC address port
  280.         call    Find6845
  281.         jc    L44        ; jump if not present
  282.  
  283.         mov    dl,0BAh        ; DX := 3BAh (status port)
  284.         in    al,dx
  285.         and    al,80h
  286.         mov    ah,al        ; AH := bit 7 (vertical sync on HGC)
  287.  
  288.         mov    cx,8000h    ; do this 32768 times 
  289. L41:        in    al,dx
  290.         and    al,80h        ; isolate bit 7
  291.         cmp    ah,al
  292.         loope    L41        ; wait for bit 7 to change
  293.  
  294.         jne    L42        ; if bit 7 changed, it's a Hercules
  295.  
  296.         mov    al,MDA        ; if bit 7 didn't change, it's an MDA
  297.         mov    ah,MDADisplay
  298.         call    FoundDevice
  299.         jmp    short L44
  300.  
  301. L42:        in    al,dx
  302.         mov    dl,al        ; DL := value from status port
  303.  
  304.         mov    ah,MDADisplay    ; assume it's a monochrome display
  305.  
  306.         mov    al,HGC        ; look for an HGC
  307.         and    dl,01110000b    ; mask off bits 4 thru 6
  308.         jz    L43
  309.  
  310.         mov    al,HGCPlus    ; look for an HGC+
  311.         cmp    dl,00010000b
  312.         je    L43        ; jump if it's an HGC+
  313.  
  314.         mov    al,InColor    ; it's an InColor card
  315.         mov    ah,EGAColorDisplay
  316.  
  317. L43:        call    FoundDevice
  318.  
  319. L44:        ret
  320.  
  321. FindMono    ENDP
  322.  
  323.  
  324. ;
  325. ; Find6845
  326. ;
  327. ;    This routine detects the presence of the CRTC on a MDA, CGA or HGC.
  328. ;    The technique is to write and read register 0Fh of the chip (cursor
  329. ;    low).  If the same value is read as written, assume the chip is
  330. ;    present at the specified port addr.
  331. ;
  332.  
  333. Find6845    PROC    near        ; Caller:    DX = port addr
  334.                     ; Returns:    cf set if not present
  335.         mov    al,0Fh
  336.         out    dx,al        ; select 6845 reg 0Fh (Cursor Low)
  337.         inc    dx
  338.         in    al,dx        ; AL := current Cursor Low value
  339.         mov    ah,al        ; preserve in AH
  340.         mov    al,66h        ; AL := arbitrary value
  341.         out    dx,al        ; try to write to 6845
  342.  
  343.         mov    cx,100h
  344. L51:        loop    L51        ; wait for 6845 to respond
  345.  
  346.         in    al,dx
  347.         xchg    ah,al        ; AH := returned value
  348.                     ; AL := original value
  349.         out    dx,al        ; restore original value
  350.  
  351.         cmp    ah,66h        ; test whether 6845 responded
  352.         je    L52        ; jump if it did (cf is reset)
  353.  
  354.         stc            ; set carry flag if no 6845 present
  355.  
  356. L52:        ret    
  357.     
  358. Find6845    ENDP
  359.  
  360.  
  361. ;
  362. ; FindActive
  363. ;
  364. ;    This subroutine stores the currently active device as Device0.  The
  365. ;    current video mode determines which subsystem is active.
  366. ;
  367.  
  368. FindActive    PROC    near
  369.  
  370.         cmp    word ptr Device1,0
  371.         je    L63            ; exit if only one subsystem
  372.  
  373.         cmp    Video0Type[di],4    ; exit if MCGA or VGA present
  374.         jge    L63            ;  (INT 10H function 1AH
  375.         cmp    Video1Type[di],4    ;  already did the work)
  376.         jge    L63
  377.  
  378.         mov    ah,0Fh
  379.         int    10h            ; AL := current BIOS video mode
  380.  
  381.         and    al,7
  382.         cmp    al,7            ; jump if monochrome
  383.         je    L61            ;  (mode 7 or 0Fh)
  384.  
  385.         cmp    Display0Type[di],MDADisplay
  386.         jne    L63            ; exit if Display0 is color
  387.         jmp    short L62
  388.  
  389. L61:        cmp    Display0Type[di],MDADisplay
  390.         je    L63            ; exit if Display0 is monochrome
  391.  
  392. L62:        mov    ax,Device0        ; make Device0 currently active
  393.         xchg    ax,Device1
  394.         mov    Device0,ax
  395.  
  396. L63:        ret
  397.  
  398. FindActive    ENDP
  399.  
  400.  
  401. ;
  402. ; FoundDevice
  403. ;
  404. ;    This routine updates the list of subsystems.
  405. ;
  406.  
  407. FoundDevice    PROC    near            ; Caller:    AH = display #
  408.                         ;         AL = subsystem #
  409.                         ; Destroys:  BX
  410.         lea    bx,Video0Type[di]
  411.         cmp    byte ptr [bx],0
  412.         je    L71            ; jump if 1st subsystem
  413.  
  414.         lea    bx,Video1Type[di]    ; must be 2nd subsystem
  415.  
  416. L71:        mov    [bx],ax            ; update list entry
  417.         ret
  418.  
  419. FoundDevice    ENDP
  420.  
  421. _TEXT        ENDS
  422.  
  423.  
  424. _DATA        SEGMENT    word public 'DATA'
  425.  
  426. EGADisplays    DB    CGADisplay    ; 0000b, 0001b    (EGA switch values)
  427.         DB    EGAColorDisplay    ; 0010b, 0011b
  428.         DB    MDADisplay    ; 0100b, 0101b
  429.         DB    CGADisplay    ; 0110b, 0111b
  430.         DB    EGAColorDisplay    ; 1000b, 1001b
  431.         DB    MDADisplay    ; 1010b, 1011b
  432.  
  433. DCCtable    DB    0,0        ; translate table for INT 10h func 1Ah
  434.         DB    MDA,MDADisplay
  435.         DB    CGA,CGADisplay
  436.         DB    0,0
  437.         DB    EGA,EGAColorDisplay
  438.         DB    EGA,MDADisplay
  439.         DB    0,0
  440.         DB    VGA,PS2MonoDisplay
  441.         DB    VGA,PS2ColorDisplay
  442.         DB    0,0
  443.         DB    MCGA,EGAColorDisplay
  444.         DB    MCGA,PS2MonoDisplay
  445.         DB    MCGA,PS2ColorDisplay
  446.  
  447. TestSequence    DB      TRUE            ; this list of flags and addresses
  448.         DW    FindPS2        ;  determines the order in which this
  449.                     ;  program looks for the various
  450. EGAflag         DB      ?               ;  subsystems
  451.         DW    FindEGA
  452.  
  453. CGAflag         DB      ?
  454.         DW    FindCGA
  455.  
  456. Monoflag        DB      ?
  457.         DW    FindMono
  458.  
  459. NumberOfTests    EQU    ($-TestSequence)/3
  460.  
  461. _DATA        ENDS
  462.  
  463.         END
  464.