home *** CD-ROM | disk | FTP | other *** search
/ DP Tool Club 21 / CD_ASCQ_21_040595.iso / dos / prg / c / soundss3 / detsound.asm < prev    next >
Assembly Source File  |  1995-03-10  |  33KB  |  1,337 lines

  1.  
  2. .MODEL MEDIUM
  3. UGROUP0 GROUP CODE_SEG0
  4. ASSUME CS:UGROUP0, DS:UGROUP0, SS:UGROUP0
  5.  
  6. .386
  7. CODE_SEG0 SEGMENT PAGE USE16
  8. LOCALS xx
  9. ;-----------------------------------------------------------------------------
  10. ; Main Routine and Interface
  11. ; IN:  ES:BX = Zeiger auf Struktur
  12. ; OUT: AX = SoundcardType    ;0=NO,1=SB/SBPRO,2=SB16,3=PAS,4=GUS
  13. ;
  14. ;    meaning        offset    size
  15. ;    baseport     0    dw 0
  16. ;    dma_number     2    db 0
  17. ;    irq_number     3    db 0
  18. ;    samplerate     4    dw 0
  19. ;    intern_type     6    db 0
  20. ;    irq_type     7    db 0
  21. ;    start_pos     8    db 0
  22. ;    loop_pos     9    db 0
  23. ;    song_mod    10    db 0
  24. ;    char master_vol    11    db 0
  25. ;    char music_vol    12    db 0
  26. ;    char fx_vol    13    db 0
  27. ;-----------------------------------------------------------------------------
  28.  
  29. PUBLIC _MAIN0
  30. _MAIN0 PROC FAR
  31.     CALL    DetectSound
  32.     SETC    DL
  33.     XOR    DH,DH
  34.     MOV    AX,CS:SoundPort
  35.     MOV    ES:[BX],AX
  36.     MOV    AL,CS:SoundDMA
  37.     MOV    ES:[BX+2],AL
  38.     MOV    AL,CS:SoundIRQ
  39.     MOV    ES:[BX+3],AL
  40.     MOV    AX,22222
  41.     MOV    ES:[BX+4],AX        ;DEFAULT SAMPLERATE = 22222
  42.     XOR    AX,AX
  43.     MOV    ES:[BX+6],AL        ;DEFAULT INTERN TYPE =  0
  44.     MOV    ES:[BX+8],AL        ;START_POS = 0
  45.     MOV    ES:[BX+9],AL        ;LOOP_POS = 0 (ENDLESS LOOPING)
  46.     MOV    ES:[BX+10],AL        ;SONG_MOD = 0
  47.     INC    AL
  48.     MOV    ES:[BX+7],AL        ;IRQ DEFAULT TO WINDOWS (TIMER)
  49.     DEC    AL
  50.     DEC    AL
  51.     MOV    ES:[BX+11],AL        ;VOLUMES TO MAX
  52.     MOV    ES:[BX+12],AL
  53.     MOV    ES:[BX+13],AL
  54.     MOV    AL,CS:SoundType
  55.     CMP    AL,2
  56.     JB    SHORT MEND
  57.     JA    SHORT MT1
  58.     DEC    AL
  59.     MOV    ES:[BX+6],AL
  60.     JMP    SHORT MEND
  61. MT1:    CMP    AL,3
  62.     JNE    SHORT MT2
  63.     INC    AL
  64.     JMP    SHORT MEND
  65. MT2:    CMP    AL,4
  66.     JNE    SHORT MT3
  67.     DEC    AL
  68.     JMP    SHORT MEND
  69. MT3:    CMP    AL,5
  70.     JNE    SHORT MEND
  71.     MOV    AL,2
  72. MEND:    RETF
  73.  
  74. SoundType       db      0    ;0=no,1=SB,2=SBPro,3=GUS,4=PAS16,5=SB16
  75. SoundPort       dw      0
  76. SoundDMA        db      0
  77. SoundIRQ        db      0
  78.  
  79. _MAIN0 ENDP
  80.  
  81. ;-----------------------------------------------------------------------------
  82. ;(Auto)detect Soundkarte: c=0 ok
  83.  
  84. DetectSound proc near
  85.                 pusha
  86.                 push    ds es cs
  87.                 pop     es
  88.                 mov     di,offset xxULTRASND
  89.                 call    GetEnv
  90.                 jnc     short xxGUSEnv
  91. xxSBNoGUS:      mov     di,offset xxBLASTER
  92.                 call    GetEnv
  93.                 jnc     short xxSBEnv
  94.                 xor     dx,dx
  95.                 mov     cs:SoundType,3
  96.                 call    DetGUSHW
  97.                 mov     cs:SoundPort,dx
  98.                 jnc     xxEndDetect
  99.                 mov     cs:SoundType,4
  100.         call    detectPAS
  101.         jnc    xxEndDetect
  102.                 mov     cs:SoundType,1
  103.  
  104. xxSBHW:         call    detectSBProHW
  105.                 jnc     xxEndDetect
  106.                 call    detectSBHW
  107.                 jnc     xxEndDetect
  108.                 jmp     xxErrorDetect
  109.  
  110. xxGUSEnv:       mov     cs:SoundType,3
  111.                 call    GetValue
  112.                 mov     cs:SoundPort,ax
  113.                 jc      short xxSBNoGUS
  114.                 call    GetValue
  115.                 mov     cs:SoundDMA,al
  116.                 jc      short xxSBNoGUS
  117.                 call    GetValue
  118.                 jc      short xxSBNoGUS
  119.                 call    GetValue
  120.                 mov     cs:SoundIRQ,al
  121.                 jc      short xxSBNoGUS
  122.  
  123.                 mov     dx,cs:SoundPort
  124.                 call    DetGUSHW
  125.                 jc      short xxSBNoGUS
  126.                 jmp     short xxEndDetect
  127.  
  128. xxSBEnv:        mov     cs:SoundType,1
  129. xxNextSB:       lodsb
  130.                 cmp     al,0
  131.                 je      short xxSBEnd
  132.                 and     al,11011111b
  133.  
  134.                 cmp     al,'A'
  135.                 jne     short xxNoA
  136.                 call    GetValue
  137.                 mov     cs:SoundPort,ax
  138.                 jnc     short xxNextSB
  139.                 jmp     short xxSBEnd
  140.  
  141. xxNoA:          cmp     al,'I'
  142.                 jne     short xxNoI
  143.                 call    GetValue
  144.                 mov     cs:SoundIRQ,al
  145.                 jnc     short xxNextSB
  146.                 jmp     short xxSBEnd
  147.  
  148. xxNoI:          cmp     al,'D'
  149.                 jne     short xxNoD
  150.                 call    GetValue
  151.                 mov     cs:SoundDMA,al
  152.                 jnc     short xxNextSB
  153.                 jmp     short xxSBEnd
  154.  
  155. xxNoD:          cmp     al,'T'
  156.                 jne     short xxNextSB
  157.                 call    GetValue
  158.                 pushf
  159.                 cmp     al,3
  160.                 jb      short xxSBOld
  161.                 mov     cs:SoundType,2
  162.                 cmp     al,4
  163.                 jb      short xxSBOld
  164.                 mov     cs:SoundType,5
  165. xxSBOld:        popf
  166.                 jnc     short xxNextSB
  167.  
  168. xxSBEnd:        xor     ax,ax
  169.                 cmp     cs:SoundPort,ax
  170.                 je      xxSBHW
  171.                 cmp     cs:SoundIRQ,al
  172.                 je      xxSBHW
  173.                 cmp     cs:SoundDMA,al
  174.                 je      xxSBHW
  175.  
  176. xxEndDetect:    xor    ax,ax
  177.         cmp     cs:SoundPort,ax
  178.                 je      short xxErrorDetect
  179.                 cmp     cs:SoundIRQ,al
  180.                 je      short xxErrorDetect
  181.                 cmp     cs:SoundDMA,al
  182.                 je      short xxErrorDetect
  183.                 clc
  184.                 pop     es ds
  185.                 popa
  186.                 ret
  187.  
  188. xxErrorDetect:  stc
  189.                 mov     cs:SoundType,0
  190.                 jmp     short xxEndDetect
  191.  
  192. xxBLASTER       db      "BLASTER",0
  193. xxULTRASND      db      "ULTRASND",0
  194.  
  195. DetectSound endp
  196.  
  197. ;------------------------------------------------------------------------------
  198. ;Liest Wert (hex) ab ds:si, zurück in ax, c=1 String mit 0 terminiert
  199.  
  200. GetValue proc near
  201.  
  202.                 push    bx
  203.  
  204.                 xor     ax,ax
  205.                 xor     bx,bx
  206.  
  207. xxNoStart:      lodsb
  208.                 cmp     al,' '
  209.                 je      short xxNoStart
  210.                 jmp     short xxEntry
  211.  
  212. xxNext:         lodsb
  213. xxEntry:        cmp     al,' '
  214.                 je      short xxEnd2
  215.                 cmp     al,','
  216.                 je      short xxEnd2
  217.                 and     al,11011111b
  218.                 cmp     al,40h
  219.                 jb      short xxNoChar
  220.                 add     al,9
  221. xxNoChar:       and     al,0fh
  222.                 shl     bx,4
  223.                 add     bx,ax
  224.                 jmp     short xxNext
  225.  
  226. xxEnd1:         stc
  227.                 mov     ax,bx
  228.                 pop     bx
  229.                 ret
  230.  
  231. xxEnd2:         clc
  232.                 mov     ax,bx
  233.                 pop     bx
  234.                 ret
  235.  
  236. GetValue endp
  237.  
  238. ;------------------------------------------------------------------------------
  239. ;holt Umgebungsvariable es:di, ds:si zeigt auf erstes Zeichen, c=1 Fehler
  240.  
  241. GetEnv proc near
  242.  
  243.                 push    bx
  244.                 push    di
  245.                 push    es
  246.  
  247.                 mov     ah,62h          ;ds:si points at dos env.
  248.                 int     21h
  249.                 mov     ds,bx
  250.                 mov     ds,ds:2ch
  251.                 xor     si,si
  252.  
  253. xxLoop3:        xor     bx,bx
  254. xxLoop:         lodsb
  255.                 cmp     al,0
  256.                 je      short xxError
  257.                 cmp     al,es:[di+bx]
  258.                 jne     short xxNextOne
  259.                 inc     bx
  260.                 jmp     short xxLoop
  261. xxNextOne:      cmp     al,'='
  262.                 jne     short xxLoop2
  263.                 cmp     es:[di+bx],byte ptr 0
  264.                 je      short xxGotIt
  265. xxLoop2:        lodsb
  266.                 cmp     al,0
  267.                 jne     short xxLoop2
  268.                 jmp     short xxLoop3
  269.  
  270. xxError:        stc
  271.                 jmp     short xxEnde
  272.  
  273. xxGotIt:        clc
  274.  
  275. xxEnde:         pop     es
  276.                 pop     di
  277.                 pop     bx
  278.                 ret
  279. GetEnv endp
  280.  
  281. ;------------------------------------------------------------------------------
  282. ;Autodetect/Check GUS
  283. ;dx = port, dx = 0 -> autodetect, else check port
  284.  
  285. DetGUSHW proc near
  286.  
  287.                 pusha
  288.                 push    ds
  289.                 push    es
  290.  
  291.                 mov     bp,1
  292.                 mov     si,dx
  293.                 xor     di,di
  294.                 cmp     dx,di
  295.                 jne     short xxnoAutodetect
  296.                 mov     si,210h
  297.                 mov     bp,6
  298.                 mov     di,-1
  299.  
  300. xxnoAutodetect: mov bx,si
  301.  
  302.                 mov cs:xxBasePort,bx
  303.                 add bx,6h
  304.                 mov cs:xxStatusPort,bx
  305.                 add bx,2+1+100h-9h+3
  306.                 mov cs:xxCommandPort,bx
  307.                 inc bx
  308.                 mov cs:xxDataLowPort,bx
  309.                 inc bx
  310.                 mov cs:xxDataHighPort,bx
  311.                 add bx,2
  312.                 mov cs:xxDRAMIOPort,bx
  313.  
  314.                 mov bx,cs:xxCommandPort
  315.                 mov cx,cs:xxDataHighPort
  316.                 mov dx,bx
  317.                 mov al,4ch      ;Initialize
  318.                 out dx,al
  319.                 mov dx,cx
  320.                 mov al,0
  321.                 out dx,al
  322.                 mov dx,cs:xxBasePort
  323.                 REPT 8
  324.                 in al,dx
  325.                 ENDM
  326.  
  327.                 mov dx,bx
  328.                 mov al,4Ch
  329.                 out dx,al
  330.                 mov dx,cx
  331.                 mov al,1
  332.                 out dx,al
  333.                 mov dx,cs:xxBasePort
  334.                 REPT 8
  335.                 in al,dx
  336.                 ENDM
  337.  
  338.                 mov dx,bx
  339.                 mov al,41h      ;DMACtrl
  340.                 out dx,al
  341.                 mov dx,cx
  342.                 mov al,0
  343.                 out dx,al
  344.                 mov dx,bx
  345.                 mov al,45h
  346.                 out dx,al
  347.                 mov dx,cx
  348.                 mov al,0
  349.                 out dx,al
  350.                 mov dx,bx
  351.                 mov al,49h
  352.                 out dx,al
  353.                 mov dx,cx
  354.                 mov al,0
  355.                 out dx,al
  356.  
  357.                 mov dx,bx
  358.                 mov al,0eh      ;VoicesActive
  359.                 out dx,al
  360.                 mov dx,cx
  361.                 mov al,20       ;NumVoices
  362.                 dec al
  363.                 or  al,0C0h
  364.                 out dx,al
  365.  
  366.                 mov dx,cs:xxStatusPort
  367.                 in  al,dx
  368.                 mov dx,bx
  369.                 mov al,41h      ;DMACtrl
  370.                 out dx,al
  371.                 mov dx,cx
  372.                 in  al,dx
  373.                 mov dx,bx
  374.                 mov al,49h
  375.                 out dx,al
  376.                 mov dx,cx
  377.                 in  al,dx
  378.                 mov dx,bx
  379.                 mov al,8Fh
  380.                 out dx,al
  381.                 mov dx,cx
  382.                 in  al,dx
  383.  
  384.                 mov dx,bx
  385.                 mov al,4ch
  386.                 out dx,al
  387.                 mov dx,cx
  388.                 mov al,7
  389.                 out dx,al
  390.  
  391.                 mov dx,cs:xxCommandPort
  392.                 mov al,43h      ;DRAMAddrLo
  393.                 out dx,al
  394.                 mov dx,cs:xxDataLowPort
  395.                 mov ax,113h
  396.                 out dx,ax
  397.  
  398.                 mov dx,cs:xxCommandPort
  399.                 mov al,44h      ;DRAMAddrHi
  400.                 out dx,al
  401.                 mov dx,cs:xxDataHighPort
  402.                 xor al,al
  403.                 out dx,al
  404.  
  405.                 mov dx,cs:xxDRAMIOPort
  406.                 mov al,0d4h                             ;testwert 1 d4h
  407.                 out dx,al
  408.  
  409.                 mov dx,cs:xxCommandPort
  410.                 mov al,43h      ;DRAMAddrLo
  411.                 out dx,al
  412.                 mov dx,cs:xxDataLowPort
  413.                 mov ax,12h                              ;testweise mal 12h beschreiben
  414.                 out dx,ax
  415.  
  416.                 mov dx,cs:xxCommandPort
  417.                 mov al,44h      ;DRAMAddrHi
  418.                 out dx,al
  419.                 mov dx,cs:xxDataHighPort
  420.                 xor al,al
  421.                 out dx,al
  422.  
  423.                 mov dx,cs:xxDRAMIOPort
  424.                 mov al,53h                              ;testwert 2 53h
  425.                 out dx,al
  426.  
  427.  
  428.                 mov dx,cs:xxCommandPort
  429.                 mov al,43h      ;DRAMAddrLo
  430.                 out dx,al
  431.                 mov dx,cs:xxDataLowPort
  432.                 mov ax,113h                             ;also testwert 1 lesen
  433.                 out dx,ax
  434.  
  435.                 mov dx,cs:xxCommandPort
  436.                 mov al,44h      ;DRAMAddrHi
  437.                 out dx,al
  438.                 mov dx,cs:xxDataHighPort
  439.                 xor al,al
  440.                 out dx,al
  441.  
  442.                 mov dx,cs:xxDRAMIOPort
  443.                 in  al,dx                               ;speicher lesen
  444.                 cmp al,0d4h                             ;testwert Ok ?
  445.                 jne short xxnotfound
  446.  
  447.                 mov dx,cs:xxCommandPort
  448.                 mov al,43h      ;DRAMAddrLo
  449.                 out dx,al
  450.                 mov dx,cs:xxDataLowPort
  451.                 mov ax,12h                              ;testoffset 2
  452.                 out dx,ax
  453.  
  454.                 mov dx,cs:xxCommandPort
  455.                 mov al,44h      ;DRAMAddrHi
  456.                 out dx,al
  457.                 mov dx,cs:xxDataHighPort
  458.                 xor al,al
  459.                 out dx,al
  460.  
  461.                 mov dx,cs:xxDRAMIOPort
  462.                 in  al,dx
  463.                 cmp al,53h                              ;wert = testwert 2 ?
  464.                 jne short xxnotfound                    ;nö, nicht gefunden
  465.                 jmp short xxfoundGUS
  466. xxnotfound:
  467.                 cmp di,0ffffh
  468.                 jne short xxno
  469.                 add si,10h
  470.                 dec bp
  471.                 jnz xxnoAutodetect
  472. xxno:
  473.                 pop es
  474.                 pop ds
  475.                 popa
  476.                 xor dx,dx
  477.                 stc                                     ;Carry setzen
  478.                 ret
  479.  
  480. xxfoundGUS:     pop     es
  481.                 pop     ds
  482.                 popa
  483.                 mov dx,cs:xxBasePort
  484.                 clc
  485.                 ret
  486.  
  487. xxBasePort      dw      0
  488. xxStatusPort    dw      0
  489. xxCommandPort   dw      0
  490. xxDataLowPort   dw      0
  491. xxDataHighPort  dw      0
  492. xxDRAMIOPort    dw      0
  493.  
  494. DetGUSHW endp
  495.  
  496. ; /***********************************************************************
  497. ; *
  498. ; *     File        : DETSBHW.ASM
  499. ; *
  500. ; *     Description : Sound Blaster hardware detection routines
  501. ; *
  502. ; ************************************************************************
  503.  
  504. waitSB MACRO
  505.     local    l1
  506. l1:
  507.     in    al,dx
  508.     or    al,al
  509.         js      short l1
  510. ENDM
  511.  
  512. waitSBport MACRO
  513.     local    l1
  514.  
  515.         mov     dx,cs:SoundPort
  516.     add    dx,0Ch
  517. l1:
  518.     in    al,dx
  519.     or    al,al
  520.         js      short l1
  521. ENDM
  522.  
  523. waitSBPROport MACRO
  524.     local    l1
  525.  
  526.         mov     dx,cs:SoundPort
  527.     add    dx,0Ch
  528. l1:
  529.     in    al,dx
  530.     or    al,al
  531.         js      short l1
  532. ENDM
  533.  
  534. ;/*************************************************************************
  535. ; *
  536. ; *    Function    :     checkPort_SB
  537. ; *
  538. ; *    Description :   Checks if given address is SB's I/O address
  539. ; *
  540. ; *    Input       :     DX = port to check
  541. ; *
  542. ; *    Returns     :    AX = 0    successful
  543. ; *                  AX = 1    unsuccessful
  544. ; *
  545. ; ************************************************************************/
  546.  
  547. checkPort_SB proc near
  548.  
  549.     push    dx
  550.     add    dl,6            ; Init Sound Blaster
  551.     mov    al,1
  552.     out    dx,al
  553.     in    al,dx            ; Wait for awhile
  554.     in    al,dx
  555.     in    al,dx
  556.     in    al,dx
  557.     in    al,dx
  558.     mov    al,0
  559.     out    dx,al
  560.     sub    dl,6
  561.  
  562.     add    dl,0Eh              ; DSP data available status
  563.     mov    cx,1000
  564. xxloop:
  565.     in    al,dx            ; port 22Eh
  566.     or    al,al
  567.         js      short xx10
  568.         loop    short xxloop
  569.  
  570.     mov    ax,1
  571.         jmp     short xxexit
  572. xx10:
  573.     sub    dl,4
  574.     in    al,dx            ; port 22Ah
  575.     cmp    al,0AAh            ; Is ID 0AAh?
  576.     mov    ax,0
  577.         je      short xxexit
  578.     mov    ax,1
  579. xxexit:
  580.     pop    dx
  581.     or    ax,ax            ; Set zero-flag accordingly
  582.     ret
  583.  
  584. checkPort_SB endp
  585.  
  586. ;/*************************************************************************
  587. ; *
  588. ; *    Function    :     findDMAIRQ_SB
  589. ; *
  590. ; *    Description :    Finds SB's DMA interrupt number
  591. ; *
  592. ; *    Returns     :    AX = 0    error
  593. ; *            AX = port number (2,3,5,7)
  594. ; *
  595. ; ************************************************************************/
  596.  
  597. findDMAIRQ_SB proc near
  598.  
  599.         push    ds
  600.         push    es
  601.  
  602.     mov    ah,35h
  603.     mov    al,8+2
  604.     int    21h
  605.         mov     cs:xxsaveVect+2,es
  606.         mov     cs:xxsaveVect,bx
  607.     mov    al,8+3
  608.     int    21h
  609.         mov     cs:xxsaveVect+6,es
  610.         mov     cs:xxsaveVect+4,bx
  611.     mov    al,8+5
  612.     int    21h
  613.         mov     cs:xxsaveVect+10,es
  614.         mov     cs:xxsaveVect+8,bx
  615.     mov    al,8+7
  616.     int    21h
  617.         mov     cs:xxsaveVect+14,es
  618.         mov     cs:xxsaveVect+12,bx
  619.  
  620.     mov    ah,25h
  621.     mov    dx,offset DMA2        ; Set vectors
  622.     mov    al,8+2
  623.     int    21h
  624.     mov    dx,offset DMA3
  625.     mov    al,8+3
  626.     int    21h
  627.     mov    dx,offset DMA5
  628.     mov    al,8+5
  629.     int    21h
  630.     mov    dx,offset DMA7
  631.     mov    al,8+7
  632.     int    21h
  633.  
  634.     in    al,21h
  635.         mov     cs:xxintMask,al            ; Save interrupt mask
  636.     mov    al,0FFh
  637.     out    21h,al            ; Mask out all interrupts
  638.     cli                ; Disable interrupts
  639.  
  640.         mov     al,cs:xxintMask
  641.     and    al,01010011b        ; Allow DMA interrupts (2,3,5 & 7)
  642.     out    21h,al
  643.     sti                ; Set DMA up
  644.  
  645.     mov    al,5
  646.     out    0Ah,al            ; Break on
  647.     mov    al,0
  648.     out    0Ch,al            ; Reset counter
  649.     mov    al,49h
  650.     out    0Bh,al            ; DMA -> DSP (output)
  651.     mov    al,0
  652.     out    83h,al            ; page 0
  653.     mov    al,0
  654.     out    2,al            ; offset 0
  655.     mov    al,0
  656.     out    2,al            ; whole address is 0000:0000
  657.     mov    al,1
  658.     out    3,al            ; count = 1
  659.     mov    al,0
  660.     out    3,al
  661.     mov    al,1
  662.     out    0Ah,al            ; Break off
  663.  
  664.         mov     dx,cs:SoundPort
  665.     add    dx,0Ch
  666.     waitSB
  667.     mov    al,40h                  ; Set DSP speed
  668.     out    dx,al
  669.     waitSB
  670.     mov    al,0D3h            ; 22222 Hz
  671.     out    dx,al
  672.     waitSB
  673.     mov    al,14h            ; 14h = output command
  674.     out    dx,al
  675.     waitSB
  676.     mov    al,1            ; digitize 1 byte
  677.     out    dx,al
  678.     waitSB
  679.     mov    al,0
  680.     out    dx,al
  681.     mov    cx,0FFFFh        ; Big loop
  682.         mov     cs:SoundIRQ,byte ptr 0  ; Clear interrupt value
  683. xxloop:
  684.         cmp     cs:SoundIRQ,byte ptr 0  ; Wait dmaIRQ to change
  685.         loope   short xxloop            ; loop if it doesn't
  686.         mov     dx,cs:SoundPort
  687.     add    dl,0Eh
  688.     in    al,dx            ; Reset SB
  689.  
  690.         mov     al,cs:xxintMask
  691.     out    21h,al            ; Restore interrupt mask
  692.     sti                ; Allow interrupts
  693.  
  694.         push    ds
  695.     mov    ah,25h
  696.         lds     dx,dword ptr cs:xxsaveVect
  697.     mov    al,8+2
  698.     int    21h
  699.         lds     dx,dword ptr cs:xxsaveVect+4
  700.     mov    al,8+3
  701.     int    21h
  702.         lds     dx,dword ptr cs:xxsaveVect+8
  703.     mov    al,8+5
  704.     int    21h
  705.         lds     dx,dword ptr cs:xxsaveVect+12
  706.     mov    al,8+7
  707.     int    21h
  708.         pop     ds
  709.  
  710.         pop     es
  711.         pop     ds
  712.  
  713.     sub    ax,ax
  714.         mov     al,cs:SoundIRQ             ; Return with interrupt number
  715.         ret
  716.  
  717. xxsaveVect      dw      8 dup(0)
  718. xxintMask       db      0
  719.  
  720. findDMAIRQ_SB endp
  721.  
  722. ;/*************************************************************************
  723. ; *
  724. ; *    Function    :     findDMAIRQ_SBpro
  725. ; *
  726. ; *    Description :    Finds SBpro's DMA interrupt number
  727. ; *
  728. ; *    Returns     :    AX = 0    error
  729. ; *                     AX = IRQ number (2,3,5,7,10)
  730. ; *
  731. ; ************************************************************************/
  732.  
  733. findDMAIRQ_SBpro proc near
  734.  
  735.         push    ds
  736.         push    es
  737.  
  738.     mov    ah,35h
  739.     mov    al,8+2
  740.     int    21h
  741.         mov     cs:xxsaveVect+2,es
  742.         mov     cs:xxsaveVect,bx
  743.     mov    al,8+5
  744.     int    21h
  745.         mov     cs:xxsaveVect+6,es
  746.         mov     cs:xxsaveVect+4,bx
  747.     mov    al,8+7
  748.     int    21h
  749.         mov     cs:xxsaveVect+10,es
  750.         mov     cs:xxsaveVect+8,bx
  751.     mov    al,72h
  752.     int    21h
  753.         mov     cs:xxsaveVect+14,es
  754.         mov     cs:xxsaveVect+12,bx
  755.  
  756.     in    al,21h
  757.         mov     cs:xxintMask1,al           ; Save interrupt mask
  758.     mov    al,0FFh
  759.     out    21h,al            ; Mask out all interrupts
  760.     in    al,0A1h
  761.         mov     cs:xxintMask2,al           ; Save interrupt mask
  762.     mov    al,0FFh
  763.     out    0A1h,al            ; Mask out all interrupts
  764.     cli                ; Disable interrupts
  765.  
  766.         push    cs
  767.         pop     ds
  768.     mov    ah,25h
  769.     mov    dx,offset DMA2        ; Set vectors
  770.     mov    al,8+2
  771.     int    21h
  772.     mov    dx,offset DMA5
  773.     mov    al,8+5
  774.     int    21h
  775.     mov    dx,offset DMA7
  776.     mov    al,8+7
  777.     int    21h
  778.     mov    dx,offset DMA10
  779.     mov    al,72h
  780.     int    21h
  781.  
  782.         mov     al,cs:xxintMask1
  783.     and    al,01010011b        ; Allow DMA interrupts (2,3,5 & 7)
  784.     out    21h,al
  785.         mov     al,cs:xxintMask2
  786.     and    al,11111011b        ; Allow DMA interrupt 10
  787.     out    0A1h,al
  788.     sti
  789.  
  790.     mov    cx,1000
  791. xxwaitloop:
  792.     in    al,21h
  793.         loop    short xxwaitloop
  794.  
  795.     mov    al,4
  796.     out    0Ah,al            ; Break on
  797.     mov    al,5
  798.     out    0Ah,al            ; Break on
  799.     mov    al,7
  800.     out    0Ah,al            ; Break on
  801.  
  802.         mov     dx,cs:SoundPort
  803.     add    dx,0Ch
  804.     waitSB
  805.     mov    al,40h                  ; Set DSP speed
  806.     out    dx,al
  807.     waitSB
  808.     mov    al,0D3h            ; 22222 Hz
  809.     out    dx,al
  810.     waitSB
  811.     mov    al,14h            ; 14h = output command
  812.     out    dx,al
  813.     waitSB
  814.     mov    al,10            ; digitize 1 byte
  815.     out    dx,al
  816.     waitSB
  817.     mov    al,0
  818.     out    dx,al
  819.     sti
  820.  
  821.     mov    ax,1            ; Check for DMA channel 1
  822.         call    findDMAchannel_SBpro
  823.     or    ax,ax
  824.         jnz     short xxchannelFound
  825.     mov    ax,0            ; Channel 0
  826.         call    findDMAchannel_SBpro
  827.     or    ax,ax
  828.         jnz     short xxchannelFound
  829.     mov    ax,3            ; Channel 3
  830.         call    findDMAchannel_SBpro
  831.     or    ax,ax
  832.         jnz     short xxchannelFound
  833.         mov     cs:SoundIRQ,0
  834. xxchannelFound:
  835.         mov     cs:SoundDMA,al
  836.  
  837.         mov     dx,cs:SoundPort
  838.     add    dl,6            ; Init Sound Blaster
  839.     mov    al,1
  840.     out    dx,al
  841.     in    al,dx            ; Wait for awhile
  842.     in    al,dx
  843.     in    al,dx
  844.     in    al,dx
  845.     in    al,dx
  846.     mov    al,0
  847.     out    dx,al
  848.     sub    dl,6
  849.  
  850.     add    dx,0Eh            ; Reset SB
  851.     in    al,dx
  852.  
  853.         push    ds
  854.     mov    ah,25h
  855.         lds     dx,dword ptr cs:xxsaveVect
  856.     mov    al,8+2
  857.     int    21h
  858.         lds     dx,dword ptr cs:xxsaveVect+4
  859.     mov    al,8+5
  860.     int    21h
  861.         lds     dx,dword ptr cs:xxsaveVect+8
  862.     mov    al,8+7
  863.     int    21h
  864.         lds     dx,dword ptr cs:xxsaveVect+12
  865.     mov    al,72h
  866.     int    21h
  867.         pop     ds
  868.  
  869.         mov     al,cs:xxintMask1
  870.     out    21h,al            ; Restore interrupt mask
  871.         mov     al,cs:xxintMask2
  872.     out    0A1h,al            ; Restore interrupt mask
  873.         sti                             ; Allow interrupts
  874.  
  875.         pop     es
  876.         pop     ds
  877.  
  878.     sub    ax,ax
  879.         mov     al,cs:SoundIRQ        ; Return with interrupt number
  880.         ret
  881.  
  882. xxsaveVect      dw      8 dup(0)
  883. xxintMask1      db      0
  884. xxintMask2      db      0
  885.  
  886. findDMAIRQ_SBpro endp
  887.  
  888. ;/*************************************************************************
  889. ; *
  890. ; *    Function    :    findDMAchannel_SBpro
  891. ; *
  892. ; *    Description :    Checks if given channel is the channel SBPro uses
  893. ; *
  894. ; *    Input       :    AX = Channel to test
  895. ; *
  896. ; *    Returns     :    AX = 0 if error
  897. ; *            AX = channel if OK
  898. ; *
  899. ; ************************************************************************/
  900.  
  901. findDMAchannel_SBpro proc near
  902.  
  903.         mov     cs:xxchannel,al
  904.     add    al,4
  905.     out    0Ah,al            ; Break on
  906.     mov    al,0
  907.     out    0Ch,al            ; Reset counter
  908.     mov    al,48h
  909.         add     al,cs:xxchannel
  910.     out    0Bh,al            ; DMA -> DSP (output)
  911.     mov    dx,87h
  912.         cmp     cs:xxchannel,byte ptr 0
  913.         je      short xx10
  914.     mov    dx,83h
  915.         cmp     cs:xxchannel,byte ptr 1
  916.         je      short xx10
  917.     mov    dx,82h            ; Channel is 3
  918. xx10:
  919.     mov    al,0
  920.     out    dx,al            ; page 0
  921.         mov     dl,cs:xxchannel
  922.     shl    dx,1
  923.     mov    al,0
  924.     out    dx,al            ; offset 0
  925.     mov    al,0
  926.     out    dx,al            ; whole address is 0000:0000
  927.     inc    dx
  928.     mov    al,10
  929.     out    dx,al            ; count = 10
  930.     mov    al,0
  931.     out    dx,al
  932.         mov     al,cs:xxchannel
  933.     out    0Ah,al            ; Break off
  934.  
  935.     mov    cx,0FFFFh        ; Big loop
  936.         mov     cs:SoundIRQ,byte ptr 0  ; Clear interrupt value
  937. xxloop:
  938.         cmp     cs:SoundIRQ,byte ptr 0  ; Wait dmaIRQ to change
  939.         loope   short xxloop            ; loop if it doesn't
  940.  
  941.         mov     al,cs:xxchannel
  942.     add    al,4
  943.     out    0Ah,al            ; Break on
  944.     mov    al,0
  945.     out    0Ch,al            ; Reset counter
  946.         mov     al,cs:xxchannel
  947.     out    0Ah,al            ; Break off
  948.  
  949.     sub    ax,ax
  950.         cmp     cs:SoundIRQ,byte ptr 0
  951.         je      short xxexit
  952.     inc    ah            ; Indicate success
  953.         mov     al,cs:xxchannel
  954. xxexit:
  955.     ret
  956.  
  957. xxchannel       db      0
  958.  
  959. findDMAchannel_SBpro endp
  960.  
  961. ;/*************************************************************************
  962. ; *
  963. ; *    Function    :     DMAint_SB
  964. ; *
  965. ; *    Description :    Interrupt function that determines SB's interrupt
  966. ; *
  967. ; ************************************************************************/
  968.  
  969. DMAint_SB proc near
  970.  
  971. DMA2:
  972.         push    ds
  973.     push    ax
  974.         mov     cs:SoundIRQ,byte ptr 2               ; Set interrupt number
  975.         jmp     short xxDMAdone
  976. DMA3:
  977.         push    ds
  978.     push    ax
  979.         mov     cs:SoundIRQ,byte ptr 3
  980.         jmp     short xxDMAdone
  981. DMA5:
  982.         push    ds
  983.     push    ax
  984.         mov     cs:SoundIRQ,byte ptr 5
  985.         jmp     short xxDMAdone
  986. DMA7:
  987.         push    ds
  988.     push    ax
  989.         mov     cs:SoundIRQ,byte ptr 7
  990.         jmp     short xxDMAdone
  991. DMA10:
  992.         push    ds
  993.     push    ax
  994.         mov     cs:SoundIRQ,byte ptr 10
  995.     mov    al,20h
  996.     out    0A0h,al
  997. xxDMAdone:
  998.     mov    al,20h
  999.     out    20h,al            ; EOI (end of interrupt)
  1000.     pop    ax
  1001.         pop     ds
  1002.     iret
  1003.  
  1004. DMAint_SB endp
  1005.  
  1006. ;/*************************************************************************
  1007. ; *
  1008. ; *    Function    :    detectSB
  1009. ; *
  1010. ; *    Description :    Checks for presence of SB.
  1011. ; *
  1012. ; *    Returns     :    c=0  if succesful
  1013. ; *            c=1  on error (no card found)
  1014. ; *
  1015. ; ************************************************************************/
  1016.  
  1017. detectSBHW proc near
  1018.  
  1019.         mov     cs:xxretvalue,word ptr -1           ; Assume failure
  1020.     mov    dx,220h
  1021.     call    checkPort_SB
  1022.         jz      short xxOK
  1023.     mov    dx,210h
  1024.     call    checkPort_SB        ; Check for every possible I/O value
  1025.         jz      short xxOK
  1026.     mov    dx,230h
  1027.     call    checkPort_SB
  1028.         jz      short xxOK
  1029.     mov    dx,240h
  1030.     call    checkPort_SB
  1031.         jz      short xxOK
  1032.     mov    dx,250h
  1033.     call    checkPort_SB
  1034.         jz      short xxOK
  1035.     mov    dx,260h
  1036.     call    checkPort_SB
  1037.         jnz     short xxexit                  ; No match found, error exit
  1038. xxOK:
  1039.         mov     cs:SoundPort,dx       ; ioPort is for internal use only
  1040.  
  1041.         push    es
  1042.     push    di
  1043.         call    findDMAIRQ_SB           ; Find DMA interrupt number
  1044.     pop    di
  1045.         pop     es
  1046.     or    ax,ax            ; 0 = error
  1047.         jz      short xxexit
  1048.         mov     cs:SoundIRQ,al
  1049.         mov     cs:SoundDMA,1
  1050.  
  1051.         mov     cs:xxretrycount,word ptr 10
  1052. xxretry:
  1053.         dec     word ptr cs:xxretrycount
  1054.         jnz     short xxcontinue
  1055.     mov    ax,0            ; not found
  1056.         jmp     short xxdone
  1057. xxcontinue:
  1058.         mov     dx,cs:SoundPort
  1059.     add    dx,0Ch
  1060.     waitSB
  1061.     mov    al,0E1h            ; Read version number
  1062.     out    dx,al
  1063.  
  1064.     add    dl,2            ; DX = 22Eh
  1065.     sub    al,al
  1066.     mov    cx,1000
  1067. xx10:
  1068.         in      al,dx                   ; Read version high
  1069.     or    al,al
  1070.         js      short xx10ok
  1071.         loop    short xx10
  1072.         jmp     short xxretry
  1073. xx10ok:
  1074.     mov    cx,1000
  1075.     sub    dl,4
  1076.     in    al,dx
  1077.     mov    ah,al
  1078.  
  1079.     add    dl,4
  1080.     sub    al,al
  1081. xx20:
  1082.     in    al,dx            ; Read version low
  1083.     or    al,al
  1084.         js      short xx20ok
  1085.         loop    short xx20
  1086.         jmp     short xxretry
  1087. xx20ok:
  1088.     sub    dl,4
  1089.     in    al,dx
  1090. xxdone:
  1091.         mov     cs:xxretvalue,word ptr 0
  1092. xxexit:
  1093.         mov     ax,cs:xxretvalue
  1094.         or      ax,ax
  1095.         jne     short xxexiterror
  1096.         clc
  1097.     ret
  1098. xxexiterror:
  1099.         stc
  1100.         ret
  1101.  
  1102. xxretvalue      dw      0
  1103. xxretrycount    dw      0
  1104.  
  1105. detectSBHW endp
  1106.  
  1107. ;/*************************************************************************
  1108. ; *
  1109. ; *     Function    :   detectSBProHW
  1110. ; *
  1111. ; *    Description :    Checks for presence of SB Pro.
  1112. ; *
  1113. ; *    Returns     :    c=0  if succesful
  1114. ; *            c=1  on error (no card found)
  1115. ; *
  1116. ; ************************************************************************/
  1117.  
  1118. detectSBProHW proc near
  1119.  
  1120.         mov     cs:xxretvalue,word ptr -1           ; Assume failure
  1121.     mov    dx,220h
  1122.     call    checkPort_SB
  1123.         jz      short xxOK
  1124.     mov    dx,210h
  1125.     call    checkPort_SB        ; Check for every possible I/O value
  1126.         jz      short xxOK
  1127.     mov    dx,230h
  1128.     call    checkPort_SB
  1129.         jz      short xxOK
  1130.     mov    dx,240h
  1131.     call    checkPort_SB
  1132.         jz      short xxOK
  1133.     mov    dx,250h
  1134.     call    checkPort_SB
  1135.         jz      short xxOK
  1136.     mov    dx,260h
  1137.     call    checkPort_SB
  1138.         jnz     xxexit                  ; No match found, error exit
  1139. xxOK:
  1140.         mov     cs:SoundPort,dx       ; ioPort is for internal use only
  1141.  
  1142.         mov     cs:xxretrycount,word ptr 10
  1143. xxretry:
  1144.         dec     word ptr cs:xxretrycount
  1145.         jnz     short xxcontinue
  1146.     mov    ax,0            ; not found
  1147.         jmp     short xxdone
  1148. xxcontinue:
  1149.         mov     dx,cs:SoundPort
  1150.     add    dx,0Ch
  1151.     waitSB
  1152.     mov    al,0E1h            ; Read version number
  1153.     out    dx,al
  1154.  
  1155.     add    dl,2            ; DX = 22Eh
  1156.     sub    al,al
  1157.     mov    cx,1000
  1158. xx10:
  1159.     in    al,dx            ; Read version high
  1160.     or    al,al
  1161.         js      short xx10ok
  1162.         loop    short xx10
  1163.         jmp     short xxretry
  1164. xx10ok:
  1165.     mov    cx,1000
  1166.     sub    dl,4
  1167.     in    al,dx
  1168.     mov    ah,al
  1169.  
  1170.     add    dl,4
  1171.     sub    al,al
  1172. xx20:
  1173.     in    al,dx            ; Read version low
  1174.     or    al,al
  1175.         js      short xx20ok
  1176.         loop    short xx20
  1177.         jmp     short xxretry
  1178. xx20ok:
  1179.     sub    dl,4
  1180.     in    al,dx
  1181. xxdone:
  1182.     cmp    ax,0300h
  1183.         jl      short xxexit            ; Not SBpro
  1184.     mov    cs:SoundType,2        ;is sb16
  1185.     cmp    ax,0400h
  1186.     jl    short xxpro
  1187.     mov    cs:SoundType,5        ;is sb16
  1188. xxpro:
  1189.         push    es
  1190.         push    di
  1191.         call    findDMAIRQ_SBpro        ; Find DMA interrupt number
  1192.     pop    di
  1193.         pop     es
  1194.     or    ax,ax            ; 0 = error
  1195.         jz      short xxexit
  1196.         mov     cs:SoundIRQ,al
  1197.  
  1198.         mov     cs:xxretvalue,word ptr 0
  1199. xxexit:
  1200.         mov     ax,cs:xxretvalue
  1201.         or      ax,ax
  1202.         jne     short xxexiterror
  1203.         clc
  1204.     ret
  1205. xxexiterror:
  1206.         stc
  1207.         ret
  1208.  
  1209. xxretvalue      dw      0
  1210. xxretrycount    dw      0
  1211.  
  1212. detectSBProHW endp
  1213.  
  1214. ;/*************************************************************************
  1215. ; *
  1216. ; *     Function    :   detectPAS
  1217. ; *
  1218. ; *    Description :    Checks for presence of PAS16.
  1219. ; *
  1220. ; *    Returns     :    c=0  if successful
  1221. ; *            c=1  on error (no card found)
  1222. ; *
  1223. ; ************************************************************************/
  1224.  
  1225. DEFAULT_BASE    EQU    00388h        ;; default base I/O address
  1226. ALT_BASE_1    EQU    00384h        ;; first alternate address
  1227. ALT_BASE_2    EQU    0038Ch        ;; second alternate address
  1228. ALT_BASE_3    EQU    00288h        ;; third alternate address
  1229. ALT_BASE_4    EQU    00280h        ;; 4th alternate address
  1230. ALT_BASE_5    EQU    00284h        ;; 5th alternate address
  1231. ALT_BASE_6    EQU    0028Ch        ;; 6th alternate address
  1232. INTRCTLR    EQU    00B8Bh        ;; Interrupt Control Register write
  1233. fICrevbits    EQU    11100000B    ;; revision mask field bits
  1234.  
  1235. detectPAS proc near
  1236.         mov     di,DEFAULT_BASE         ; try the first address
  1237.     mov    SoundPort,di
  1238.     call    SearchHWVersion
  1239.     jnc    xxpas_ok
  1240.  
  1241.     mov    di,ALT_BASE_1        ; try the first alternate
  1242.     mov    SoundPort,di
  1243.     call    SearchHWVersion
  1244.     jnc    xxpas_ok
  1245.  
  1246.     mov    di,ALT_BASE_2        ; try the second alternate
  1247.     mov    SoundPort,di
  1248.     call    SearchHWVersion
  1249.     jnc    xxpas_ok
  1250.  
  1251.     mov    di,ALT_BASE_3        ; try the third alternate
  1252.     mov    SoundPort,di
  1253.     call    SearchHWVersion
  1254.     jnc    xxpas_ok
  1255.  
  1256.     mov    di,ALT_BASE_4        ; try the 4th alternate
  1257.     mov    SoundPort,di
  1258.     call    SearchHWVersion
  1259.     jnc    xxpas_ok
  1260.  
  1261.     mov    di,ALT_BASE_5        ; try the 5th alternate
  1262.     mov    SoundPort,di
  1263.     call    SearchHWVersion
  1264.     jnc    xxpas_ok
  1265.  
  1266.     mov    di,ALT_BASE_6        ; try the 6th alternate
  1267.     mov    SoundPort,di
  1268.     call    SearchHWVersion
  1269. xxpas_ok:
  1270.     ret
  1271. detectPAS endp
  1272.  
  1273. ;   /*\
  1274. ;---|*|----====< SearchHWVersion >====----
  1275. ;---|*|
  1276. ;---|*| Given a specific I/O address, this routine will see if the
  1277. ;---|*| hardware exists at this address.
  1278. ;---|*|
  1279. ;---|*| Entry Conditions:
  1280. ;---|*|     DI holds the I/O address to test
  1281. ;---|*|
  1282. ;---|*| Exit Conditions:
  1283. ;---|*|     c=0 ok
  1284. ;---|*|     c=1 no card found
  1285. ;   \*/
  1286.  
  1287. SearchHWVersion proc near
  1288. ;
  1289. ; calculate the translation code
  1290. ;
  1291.     xor    di,DEFAULT_BASE     ; di holds the translation code
  1292.     mov    ax,0BC00H        ; make sure MVSOUND.SYS is loaded
  1293.     mov    bx,'??'                 ; this is our way of knowing if the
  1294.     xor    cx,cx            ; hardware is actually present.
  1295.     xor    dx,dx
  1296.     int    2fh            ; get the ID pattern
  1297.     xor    bx,cx            ; build the result
  1298.     xor    bx,dx
  1299.     cmp    bx,'MV'                 ; if not here, exit...
  1300.     jnz    xxbad
  1301. ;
  1302. ; get the MVSOUND.SYS specified DMA and IRQ channel
  1303. ;
  1304.         mov     ax,0bc04h               ; get the DMA and IRQ numbers
  1305.     int    2fh
  1306.     mov    cs:SoundDMA,bl        ; save the correct DMA & IRQ
  1307.     mov    cs:SoundIRQ,cl
  1308. ;
  1309. ; grab the version # in the interrupt mask. The top few bits hold the version #
  1310. ;
  1311.         mov     dx,INTRCTLR             ; board ID is in MSB 3 bits
  1312.     xor    dx,di            ; adjust to other address
  1313.     in    al,dx
  1314.     cmp    al,-1            ; bus float meaning not present?
  1315.     je    xxbad            ; yes, there is no card here
  1316.     mov    ah,al            ; save an original copy
  1317.     xor    al,fICrevbits        ; the top bits wont change
  1318.     out    dx,al            ; send out the inverted bits
  1319.     jmp    xxl1
  1320. xxl1:    jmp    xxl2
  1321. xxl2:    in    al,dx            ; get it back...
  1322.     cmp    al,ah            ; both should match now...
  1323.     xchg    al,ah            ; (restore without touching the flags)
  1324.     out    dx,al
  1325.     jnz    xxbad            ; we have a bad board
  1326. ;
  1327. ; We do have hardware! Load the product bit definitions
  1328. ;
  1329.     clc
  1330.     ret
  1331. xxbad:    stc
  1332.     ret
  1333. SearchHWVersion endp
  1334.  
  1335. CODE_SEG0 ENDS
  1336.  
  1337. END _MAIN0