home *** CD-ROM | disk | FTP | other *** search
/ DP Tool Club 19 / CD_ASCQ_19_010295.iso / dos / prg / midas / wss.asm < prev   
Assembly Source File  |  1994-08-06  |  12KB  |  566 lines

  1. ;*    WSS.ASM
  2. ;*
  3. ;* Windows Sound System Sound Device, v1.10
  4. ;*
  5. ;* Copyright 1994 Petteri Kangaslampi and Jarno Paananen
  6. ;*
  7. ;* This file is part of the MIDAS Sound System, and may only be
  8. ;* used, modified and distributed under the terms of the MIDAS
  9. ;* Sound System license, LICENSE.TXT. By continuing to use,
  10. ;* modify or distribute this file you indicate that you have
  11. ;* read the license and understand and accept it fully.
  12. ;*
  13.  
  14.  
  15.  
  16. IDEAL
  17. P386
  18. JUMPS
  19.  
  20. INCLUDE "lang.inc"
  21. INCLUDE "errors.inc"
  22. INCLUDE "sdevice.inc"
  23. INCLUDE "dsm.inc"
  24. INCLUDE "dma.inc"
  25.  
  26.  
  27. ;/***************************************************************************\
  28. ;*       enum wssFunctIDs
  29. ;*       ----------------
  30. ;* Description:  ID numbers for WSS Sound Device functions
  31. ;\***************************************************************************/
  32.  
  33. enum    wssFunctIDs \
  34.         ID_wssDetect = ID_wss, \
  35.         ID_wssInit, \
  36.         ID_wssClose
  37.  
  38.  
  39.  
  40. DATASEG
  41.  
  42. wssSpd        DB    ?        ; WSS speed value
  43. wssRate     DW    ?        ; WSS actual playing rate
  44. wssOLMute    DB    ?        ; WSS old left channel mute value
  45. wssORMute    DB    ?        ; WSS old right channel mute value
  46.  
  47.  
  48.  
  49.  
  50. IDATASEG
  51.  
  52.  
  53. GLOBAL    WSS : SoundDevice
  54.  
  55. WSS        SoundDevice    < \
  56.     0, 530h, 09h, 03h, sdUnInitialized, \
  57.     sdMono or sdStereo or sd8bit or sd16bit or sdNormalQ, \
  58.     far ptr wssID, \
  59.     far ptr wssDetect, \
  60.     far ptr wssInit, \
  61.     far ptr wssClose, \
  62.     far ptr dsmGetMixRate, \
  63.     far ptr dsmGetMode, \
  64.     far ptr dsmOpenChannels, \
  65.     far ptr dsmCloseChannels, \
  66.     far ptr dsmClearChannels, \
  67.     far ptr dsmMute, \
  68.     far ptr dsmPause, \
  69.     far ptr dsmSetMasterVolume, \
  70.     far ptr dsmPlaySound, \
  71.     far ptr dsmStopSound, \
  72.     far ptr dsmSetRate, \
  73.     far ptr dsmGetRate, \
  74.     far ptr dsmSetVolume, \
  75.     far ptr dsmSetInstrument, \
  76.     far ptr dsmSetPosition, \
  77.     far ptr dsmGetPosition, \
  78.     far ptr dsmSetPanning, \
  79.     far ptr dsmGetPanning, \
  80.     far ptr dsmMuteChannel, \
  81.     far ptr dsmAddInstrument, \
  82.     far ptr dsmRemInstrument, \
  83.     far ptr dsmSetUpdRate, \
  84.     far ptr dsmPlay >
  85.  
  86.  
  87. LABEL    wssRates    WORD        ; sampling rates for WSS
  88.     DW     8000, 00h
  89.     DW     5513, 01h
  90.     DW    16000, 02h
  91.     DW    11025, 03h
  92.     DW    27429, 04h
  93.     DW    18900, 05h
  94.     DW    32000, 06h
  95.     DW    22050, 07h
  96.     DW        0, 08h        ; not supported
  97.     DW    37800, 09h
  98.     DW        0, 0Ah
  99.     DW    44100, 0Bh
  100.     DW    48000, 0Ch
  101.     DW    33075, 0Dh
  102.     DW     9600, 0Eh
  103.     DW     6615, 0Fh
  104.  
  105. wssID   db      "Windows Sound System Sound Device v1.10",0
  106.  
  107. CODESEG
  108.  
  109.  
  110.  
  111. PUBLIC    wssDetect
  112. PUBLIC    wssInit
  113. PUBLIC    wssClose
  114.  
  115.  
  116.  
  117. ;/***************************************************************************\
  118. ;*
  119. ;* Function:    NOLANGUAGE
  120. ;*
  121. ;* Description: Waits until the WSS CODEC finishes initializing
  122. ;*
  123. ;* Returns:    carry set if error, otherwise carry clear
  124. ;*
  125. ;* Destroys:    ax, cx, dx
  126. ;*
  127. ;\***************************************************************************/
  128.  
  129. PROC NOLANGUAGE WaitCODEC    NEAR    ; waits until CODEC finishes
  130.                     ;  initializing. Carry set if error
  131.     clc
  132.  
  133.     mov    dx,[WSS.port]        ; dx = CODEC Index Address Register
  134.     add    dx,4
  135.  
  136.     mov    cx,2000h
  137.  
  138. @@wait: in    al,dx
  139.     or    al,al            ; wait until bit 7 is zero or 2000h
  140.     jns    @@ok            ; reads
  141.     loop    @@wait
  142.  
  143.     stc                ; if read 2000h times, there is a
  144.                     ; problem with the CODEC
  145. @@ok:    ret
  146.  
  147. ENDP
  148.  
  149.  
  150.  
  151.  
  152. ;/***************************************************************************\
  153. ;*
  154. ;* Function:    int wssDetect(int *result);
  155. ;*
  156. ;* Description: Detects Windows Sound System soundcard
  157. ;*
  158. ;* Returns:     MIDAS error code.
  159. ;*              1 stored to *result if WSS was detected, 0 if not.
  160. ;*
  161. ;\***************************************************************************/
  162.  
  163. PROC    wssDetect       FAR     result : dword
  164.  
  165.         les     bx,[result]             ; store 0 in *result - no detection
  166.         mov     [word es:bx],0
  167.  
  168.         xor     ax,ax
  169.     ret
  170. ENDP
  171.  
  172.  
  173.  
  174.  
  175. ;/***************************************************************************\
  176. ;*
  177. ;* Function:    int wssInit(ushort mixRate, ushort mode);
  178. ;*
  179. ;* Description: Initializes Windows Sound System
  180. ;*
  181. ;* Input:    mixRate     mixing rate
  182. ;*        mode        output mode (see enum sdMode)
  183. ;*
  184. ;* Returns:     MIDAS error code
  185. ;*
  186. ;\***************************************************************************/
  187.  
  188. PROC    wssInit     FAR    mixRate : word, mode : word
  189. USES    si,di
  190. LOCAL    wssMode : word
  191.  
  192.     mov    [wssMode],0
  193.  
  194.     test    [mode],sd8bit        ; force 8-bit?
  195.     jnz    @@8b
  196.     or    [wssMode],sd16bit    ; if not, use 16 bits
  197.     jmp    @@bit
  198. @@8b:    or    [wssMode],sd8bit
  199.  
  200. @@bit:    test    [mode],sdMono        ; force mono?
  201.     jnz    @@mono
  202.     or    [wssMode],sdStereo    ; if not, use stereo
  203.     jmp    @@mst
  204. @@mono: or    [wssMode],sdMono
  205.  
  206. @@mst:    test    [mode],sdLowQ        ; force low or high quality?
  207.     jnz    @@lowq
  208.     test    [mode],sdHighQ
  209.     jnz    @@highq
  210.     or    [wssMode],sdNormalQ    ; if not, use normal quality
  211.     jmp    @@mode
  212. @@lowq: or    [wssMode],sdLowQ
  213.     jmp    @@mode
  214. @@highq:
  215.     or    [wssMode],sdHighQ
  216.  
  217. @@mode: ; wssMode set up OK
  218.  
  219.     mov    dx,[WSS.port]
  220.     add    dx,4            ; dx = CODEC Index Address Register
  221.     in    al,dx            ; is the CODEC busy?
  222.     or    al,al
  223.         jns     @@notbusy
  224.  
  225.         mov     ax,errSDFailure         ; CODEC busy - failure
  226.         jmp     @@err
  227.  
  228. @@notbusy:
  229.     mov    al,0Ch            ; select misc. register
  230.     out    dx,al
  231.     inc    dx
  232.     in    al,dx            ; AL = CODEC version
  233.  
  234.     mov    bl,al
  235.  
  236.     xor    al,al
  237.     out    dx,al            ; write 0 to misc. register
  238.     in    al,dx            ; and read it back
  239.     cmp    al,bl            ; if value changed this is not a
  240.         je      @@codecok               ; CODEC
  241.  
  242.         mov     ax,errSDFailure         ; value changed - not a CODEC
  243.         jmp     @@err
  244.  
  245. @@codecok:
  246.     mov    bl,[WSS.IRQ]
  247.     cmp    bl,7
  248.     je    @@IRQ7
  249.     cmp    bl,9
  250.     je    @@IRQ9
  251.     cmp    bl,10
  252.     je    @@IRQ10
  253.     cmp    bl,11
  254.     je    @@IRQ11
  255.  
  256.         mov     ax,errSDFailure         ; invalid IRQ number
  257.         jmp     @@err
  258.  
  259. @@IRQ7: mov    al,08h            ; IRQ value for CODEC configuration
  260.     jmp    @@IRQd
  261.  
  262. @@IRQ9: mov    al,10h            ; IRQ value for CODEC configuration
  263.     jmp    @@IRQd
  264.  
  265. @@IRQ10:
  266.     mov    al,18h            ; IRQ value for CODEC configuration
  267.     jmp    @@IRQd
  268.  
  269. @@IRQ11:
  270.     mov    al,20h            ; IRQ value for CODEC configuration
  271.  
  272.  
  273. @@IRQd:
  274.     mov    bl,[WSS.DMA]
  275.     cmp    bl,0
  276.     je    @@DMA0
  277.     cmp    bl,1
  278.     je    @@DMA1
  279.     cmp    bl,3
  280.     je    @@DMA3
  281.  
  282.         mov     ax,errSDFailure         ; invalid DMA number
  283.         jmp     @@err
  284.  
  285. @@DMA0: or    al,01h            ; DMA value for CODEC configuration
  286.     jmp    @@DMAd
  287.  
  288. @@DMA1: or    al,02h            ; DMA value for CODEC configuration
  289.     jmp    @@DMAd
  290.  
  291. @@DMA3: or    al,03h            ; DMA value for CODEC configuration
  292.  
  293. @@DMAd: mov    dx,[WSS.port]
  294.     out    dx,al            ; set IRQ and DMA numbers
  295.  
  296.     ; WSS does _NOT_ seem to use any interrupts if using autoinit
  297.     ; DMA, so setting a IRQ-handler is unnecessary.
  298.  
  299.     ; now search for closest match of the mixing rate from the wssRates
  300.     ; table
  301.  
  302.     mov    cx,16            ; 16 possible values
  303.     xor    si,si            ; pointer to rate table
  304.     mov    dx,32767        ; distance from best match
  305.     xor    bx,bx            ; rate number for best match
  306.  
  307. @@rl:    mov    ax,[wssRates+si]    ; get a rate from table
  308.     add    si,2
  309.     sub    ax,[mixRate]        ; distance from wanted mixing rate
  310.     js    @@1            ; if this rate is smaller, ignore
  311.     cmp    ax,dx            ; is distance greater than best match?
  312.     jae    @@1            ; if is, ignore
  313.  
  314.     mov    bx,[wssRates+si]    ; rate number for this match
  315.     mov    dx,ax            ; distance
  316.  
  317. @@1:    add    si,2            ; next rate
  318.     loop    @@rl
  319.  
  320.     mov    [wssSpd],bl        ; store rate number
  321.     shl    bx,2
  322.     mov    ax,[wssRates+bx]    ; get actual mixing rate from table
  323.     mov    [wssRate],ax        ; store actual mixing rate
  324.  
  325.         ; initialize DSM:
  326.     call    dsmInit LANG, [wssRate], [wssMode]
  327.         test    ax,ax
  328.         jnz     @@err
  329.  
  330.         ; start playing the DMA buffer:
  331.         movzx   ax,[WSS.DMA]
  332.     call    dmaPlayBuffer LANG, seg dsmBuffer offset dsmBuffer, \
  333.                 ax, 1
  334.         test    ax,ax
  335.         jnz     @@err
  336.  
  337.     mov    dx,[WSS.port]
  338.     add    dx,4
  339.     mov    al,0Ah
  340.     out    dx,al
  341.     inc    dx
  342.     in    al,dx            ; external mute on
  343.     or    al,40h
  344.     out    dx,al
  345.  
  346.     mov    cx,1200h        ; delay to prevent clicks (value from
  347.                     ;  CODEC.ASM, ExtMute, WSS SDK 1.0)
  348. @@w1:    in    al,84h            ; a "safe" I/O port
  349.     loop    @@w1
  350.  
  351.  
  352.     mov    si,2
  353.  
  354.     ; For some unknown reason this has to be done twice. Don't ask me
  355.     ; why. Apparently something isn't initialized quite as it should
  356.     ; be, but this seems to work fine this way.
  357.  
  358. @@ratelp:
  359.     call    WaitCODEC
  360.  
  361.     mov    dx,[WSS.port]
  362.     add    dx,4            ; enable MCE and select Clock and
  363.     mov    al,48h            ; Data Format Register (08h)
  364.     out    dx,al
  365.  
  366.     inc    dx
  367.     mov    al,[wssSpd]        ; Clock Frequency Source & Divide
  368.     test    [wssMode],sd16bit
  369.     jz    @@no16
  370.     or    al,40h            ; 16-bit signed linear (0 - 8-bit
  371.                     ; unsigned linear)
  372. @@no16:
  373.     test    [wssMode],sdStereo    ; stereo?
  374.     jz    @@nostereo
  375.     or    al,10h            ; if yes, set stereo bit 1
  376.  
  377. @@nostereo:
  378.     out    dx,al
  379.  
  380.     call    WaitCODEC
  381.  
  382.     dec    si            ; do it again...
  383.     jnz    @@ratelp
  384.  
  385.     mov    dx,[WSS.port]
  386.     add    dx,4
  387.     mov    al,49h            ; retain MCE
  388.     out    dx,al
  389.     inc    dx
  390.     mov    al,04h or 08h        ; single DMA channel, enable
  391.     out    dx,al            ; autocalibration
  392.  
  393.     call    WaitCODEC
  394.  
  395.     mov    dx,[WSS.port]
  396.     add    dx,4
  397.     mov    al,08h            ; disable MCE
  398.     out    dx,al
  399.  
  400. @@wacal:
  401.     mov    dx,[WSS.port]
  402.     add    dx,4
  403.     mov    al,11
  404.     out    dx,al            ; wait until autocalibration is
  405.     inc    dx            ; finished
  406.     in    al,dx
  407.     test    al,32
  408.     jnz    @@wacal
  409.  
  410.  
  411.     mov    cx,1200h        ; delay to prevent clicks (value from
  412.                     ;  CODEC.ASM, ExtMute, WSS SDK 1.0)
  413. @@w2:    in    al,84h            ; a "safe" I/O port
  414.     loop    @@w2
  415.  
  416.     mov    dx,[WSS.port]
  417.     add    dx,4
  418.     mov    al,0Ah
  419.     out    dx,al
  420.     inc    dx            ; external mute off
  421.     in    al,dx
  422.     and    al,NOT 40h
  423.     out    dx,al
  424.  
  425.  
  426.     mov    dx,[WSS.port]
  427.     add    dx,6            ; acknowledge CODEC interrupt (just
  428.     xor    al,al            ;  for safety...)
  429.     out    dx,al
  430.  
  431.  
  432.     mov    dx,[WSS.port]
  433.     add    dx,4            ; select the lower base count
  434.     mov    al,0Fh
  435.     out    dx,al
  436.     inc    dx
  437.     mov    al,255            ; set the low byte of count (DMAC
  438.     out    dx,al            ; takes care of wrapping)
  439.  
  440.     dec    dx
  441.     mov    al,0Eh            ; select the upper base count
  442.     out    dx,al
  443.     inc    dx
  444.     mov    al,255            ; set the high byte of count
  445.     out    dx,al
  446.  
  447.  
  448.     mov    dx,[WSS.port]
  449.     add    dx,4            ; write to the Interface Configuration
  450.     mov    al,09h
  451.     out    dx,al
  452.  
  453.     inc    dx
  454.     mov    al,05h            ; use DMA playback
  455.     out    dx,al
  456.  
  457.     dec    dx
  458.     mov    al,06h
  459.     out    dx,al            ; mute off from left channel
  460.     inc    dx
  461.     in    al,dx
  462.     mov    [wssOLMute],al
  463.     and    al,NOT 128
  464.     out    dx,al
  465.  
  466.     dec    dx
  467.     mov    al,07h
  468.     out    dx,al            ; mute off from right channel
  469.     inc    dx
  470.     in    al,dx
  471.     mov    [wssORMute],al
  472.     and    al,NOT 128
  473.     out    dx,al
  474.  
  475. @@ok:
  476.     mov    [WSS.status],sdOK
  477.         xor     ax,ax                   ; WSS succesfully initialized
  478.         jmp     @@done
  479.  
  480.  
  481. @@err:  ERROR   ID_wssInit
  482.  
  483. @@done:
  484.     ret
  485. ENDP
  486.  
  487.  
  488.  
  489.  
  490. ;/***************************************************************************\
  491. ;*
  492. ;* Function:    int wssClose(void)
  493. ;*
  494. ;* Description: Uninitializes Windows Sound System
  495. ;*
  496. ;* Returns:     MIDAS error code
  497. ;*
  498. ;\***************************************************************************/
  499.  
  500. PROC    wssClose    FAR
  501.  
  502.         cmp     [WSS.status],sdOK
  503.         je      @@sok
  504.  
  505.         mov     ax,errSDFailure
  506.         jmp     @@err
  507.  
  508. @@sok:
  509.     mov    dx,[WSS.port]
  510.     add    dx,4
  511.  
  512.     mov    al,06h
  513.     out    dx,al            ; old mute setting to left channel
  514.     inc    dx
  515.     mov    al,[wssOLMute]
  516.     out    dx,al
  517.  
  518.     dec    dx
  519.     mov    al,07h
  520.     out    dx,al            ; old mute setting to right channel
  521.     inc    dx
  522.     mov    al,[wssORMute]
  523.     out    dx,al
  524.  
  525.     dec    dx            ; Pin Control Register
  526.     mov    al,0Ah
  527.     out    dx,al
  528.     inc    dx
  529.     xor    al,al            ; turn off interrupts
  530.     out    dx,al
  531.  
  532.     inc    dx
  533.     out    dx,al            ; acnowledge outstanding interrupts
  534.  
  535.     sub    dx,2
  536.     mov    al,09h            ; Interface Configuration Register
  537.     out    dx,al
  538.     inc    dx
  539.     xor    al,al            ; turn off CODEC's DMA
  540.     out    dx,al
  541.  
  542.     movzx    ax,[WSS.DMA]
  543.     call    dmaStop LANG, ax    ; stop DMA playing
  544.         test    ax,ax
  545.         jnz     @@err
  546.  
  547.     call    dsmClose LANG        ; uninitialize DSM
  548.         test    ax,ax
  549.         jnz     @@err
  550.  
  551.     mov    [WSS.status],sdUnInitialized
  552.  
  553.         xor     ax,ax
  554.         jmp     @@done
  555.  
  556.  
  557. @@err:  ERROR   ID_wssClose
  558.  
  559. @@done:
  560.     ret
  561. ENDP
  562.  
  563.  
  564.  
  565. END
  566.