home *** CD-ROM | disk | FTP | other *** search
/ Point Programming 1 / PPROG1.ISO / c / pas_sdk1 / pas / subs / mixers / fyi / mixers.asm < prev    next >
Encoding:
Assembly Source File  |  1992-06-28  |  44.8 KB  |  1,735 lines

  1. ;$Author:   DCODY  $
  2. ;$Date:   28 Jun 1992 11:36:42  $
  3. ;$Header:   W:/sccs/mixers/mixers.asv   1.2   28 Jun 1992 11:36:42   DCODY  $
  4. ;$Log:   W:/sccs/mixers/mixers.asv  $
  5. ;  
  6. ;     Rev 1.2   28 Jun 1992 11:36:42   DCODY
  7. ;  fixed FM split, and made SB channel assigment changes on entry to SETMIXER
  8. ;  
  9. ;     Rev 1.1   23 Jun 1992 16:45:28   DCODY
  10. ;  PAS2 update
  11. ;  
  12. ;     Rev 1.0   15 Jun 1992 09:41:36   BCRANE
  13. ;  Initial revision.
  14. ;$Logfile:   W:/sccs/mixers/mixers.asv  $
  15. ;$Modtimes$
  16. ;$Revision:   1.2  $
  17.  
  18.     Title    MIXERS    --  Games Authors interface to MIXER/VOLUME/CROSS/FILTER
  19.     page    64,131
  20.  
  21. ;   /*\
  22. ;---|*|----====< MIXERS >====----
  23. ;---|*|
  24. ;---|*|  This module contains the code for supporting the mixers,filter,
  25. ;---|*|  volume control, and PCM I/O.
  26. ;---|*|
  27. ;   |*|  Media Vision, Inc. Copyright (c) 1991, All Rights Reserved
  28. ;---|*|
  29. ;   \*/
  30. ;
  31. if1
  32.   %out      ***********************************************************
  33.   %out       *                                                         *
  34.   %out       *        ----====< Programming Caveat >====----           *
  35.   %out       *                                                         *
  36.   %out       * This code is provided as documentation ONLY. Attempting *
  37.   %out       * to use this in your program will make you hardware      *
  38.   %out       * dependent!!!. Please use the identical API located in   *
  39.   %out       * in MVHxLIB for mixer control. Here are the library      *
  40.   %out       * function names:                                         *
  41.   %out       *                                                         *
  42.   %out       *     int (far *MVSetMixerFunction)  ();                  *
  43.   %out       *     int (far *MVSetVolumeFunction) ();                  *
  44.   %out       *     int (far *MVSetFilterFunction) ();                  *
  45.   %out       *     int (far *MVSetCrossChannel)   ();                  *
  46.   %out       *     int (far *MVGetMixerFunction)  ();                  *
  47.   %out       *     int (far *MVGetVolumeFunction) ();                  *
  48.   %out       *     int (far *MVGetFilterFunction) ();                  *
  49.   %out       *     int (far *MVGetCrossChannel)   ();                  *
  50.   %out       *     int (far *MVRealSoundSwitch)   ();                  *
  51.   %out       *     int (far *MVFMSplitSwitch)     ();                  *
  52.   %out       *                                                         *
  53.   %out       ***********************************************************
  54.         .err
  55. endif
  56.  
  57. ;
  58. ;   /*\
  59. ;---|*|
  60. ;---|*|----=======================================================---------
  61. ;---|*|----====< MVSOUND.SYS function table entry conditions:
  62. ;---|*|----=======================================================---------
  63. ;---|*|
  64. ;---|*| This function returns a segment:offset to the table of 10 functions
  65. ;---|*| The table is made up of 32 bit pointers to the ten far routines.
  66. ;---|*| Each routine has different register requirements:
  67. ;---|*|
  68. ;---|*|  Function #1 Set a Mixer.
  69. ;---|*|
  70. ;---|*|         Entry Condition:
  71. ;---|*|         BX is the setting      (0% - 100%)
  72. ;---|*|         CX is the mixer select (BI_OUTPUTMIXER | BI_INPUTMIXER)
  73. ;---|*|         DX is the channel      (ex: BI_L_FM, BI_R_FM, etc.)
  74. ;---|*|
  75. ;---|*|         Exit Condition:
  76. ;---|*|         All other registers are unchanged.
  77. ;---|*|
  78. ;---|*|  Function #2 Set the Volume/Equalizer device.
  79. ;---|*|
  80. ;---|*|         Entry Condition:
  81. ;---|*|         BX is the setting      (0% - 100%)
  82. ;---|*|         CX is the volume channel select:
  83. ;---|*|
  84. ;---|*|             BI_VOLLOUD
  85. ;---|*|             BI_VOLENHANCE
  86. ;---|*|             BI_VOLBASS
  87. ;---|*|             BI_VOLTREBLE
  88. ;---|*|             BI_VOLLEFT
  89. ;---|*|             BI_VOLRIGHT
  90. ;---|*|
  91. ;---|*|         Since some of the devices are swithes, a 0% turns it
  92. ;---|*|         off, and a 100% turns it on. The switches are:
  93. ;---|*|
  94. ;---|*|             BI_VOLLOUD      --  ENHANCED STEREO switch
  95. ;---|*|             BI_VOLENHANCE --  LOUDNESS switch
  96. ;---|*|
  97. ;---|*|         Exit Condition:
  98. ;---|*|         All other registers are unchanged.
  99. ;---|*|
  100. ;---|*|  Function #3 Set the Filter.
  101. ;---|*|
  102. ;---|*|         Entry Condition:
  103. ;---|*|         BX is a new setting    (0% - 100%)
  104. ;---|*|
  105. ;---|*|         0% filters out anything higher than 0k hz (is mute)
  106. ;---|*|           100% filters out anything higher than 20 khz
  107. ;---|*|
  108. ;---|*|         Exit Condition:
  109. ;---|*|         All other registers are unchanged.
  110. ;---|*|
  111. ;---|*|  Function #4 Set the Cross Channel.
  112. ;---|*|
  113. ;---|*|         Entry Condition:
  114. ;---|*|         BX holds the new cross channel mask bits:
  115. ;---|*|
  116. ;---|*|            00000001b Right to Right
  117. ;---|*|            00000010b Left  to Right
  118. ;---|*|            00000100b Right to Left
  119. ;---|*|            00001000b Left  to Left
  120. ;---|*|
  121. ;---|*|            A set bit turns ON the connection.
  122. ;---|*|            A clear bit turns OFF the connection.
  123. ;---|*|
  124. ;---|*|         Exit Condition:
  125. ;---|*|         All other registers are unchanged.
  126. ;---|*|
  127. ;---|*|  Function #5 Get a Mixer setting.
  128. ;---|*|
  129. ;---|*|         Entry Condition:
  130. ;---|*|         CX is the mixer select (BI_OUTPUTMIXER | BI_INPUTMIXER)
  131. ;---|*|         DX is the channel      (ex: BI_L_FM, BI_R_FM, etc.)
  132. ;---|*|
  133. ;---|*|         Exit Condition:
  134. ;---|*|         BL is the setting      (0% - 100%)
  135. ;---|*|         BH is 0 for off, FF for on.
  136. ;---|*|         All other registers are unchanged.
  137. ;---|*|
  138. ;---|*|  Function #6 Get the Volume/Equalizer setting.
  139. ;---|*|
  140. ;---|*|         Entry Condition:
  141. ;---|*|         CX is the volume channel select:
  142. ;---|*|
  143. ;---|*|             BI_VOLLOUD
  144. ;---|*|             BI_VOLENHANCE
  145. ;---|*|             BI_VOLBASS
  146. ;---|*|             BI_VOLTREBLE
  147. ;---|*|             BI_VOLLEFT
  148. ;---|*|             BI_VOLRIGHT
  149. ;---|*|                     BI_VOLMODE
  150. ;---|*|
  151. ;---|*|         Since some of the devices are swithes, a 0% turns it
  152. ;---|*|         off, and a 100% turns it on. The switches are:
  153. ;---|*|
  154. ;---|*|             BI_VOLLOUD      --  ENHANCED STEREO switch
  155. ;---|*|             BI_VOLENHANCE --  LOUDNESS switch
  156. ;---|*|
  157. ;---|*|         Exit Condition:
  158. ;---|*|         BX is the setting      (0% - 100%)
  159. ;---|*|         All other registers are unchanged.
  160. ;---|*|
  161. ;---|*|  Function #7 Get the Filter setting.
  162. ;---|*|
  163. ;---|*|         Entry Condition:
  164. ;---|*|           None
  165. ;---|*|
  166. ;---|*|         Exit Condition:
  167. ;---|*|         BX is a new setting    (0% - 100%)
  168. ;---|*|         0% filters out anything higher than 0k hz (is mute)
  169. ;---|*|           100% filters out anything higher than 20 khz
  170. ;---|*|
  171. ;---|*|           All other registers are unchanged.
  172. ;---|*|
  173. ;---|*|  Function #8 Get the Cross Channel setting
  174. ;---|*|
  175. ;---|*|         Entry Condition:
  176. ;---|*|         None
  177. ;---|*|
  178. ;---|*|         Exit Condition:
  179. ;---|*|         BX holds the new cross channel mask bits:
  180. ;---|*|
  181. ;---|*|            00000001b Right to Right
  182. ;---|*|            00000010b Left  to Right
  183. ;---|*|            00000100b Right to Left
  184. ;---|*|            00001000b Left  to Left
  185. ;---|*|
  186. ;---|*|            A set bit turns ON the connection.
  187. ;---|*|            A clear bit turns OFF the connection.
  188. ;---|*|
  189. ;---|*|         All other registers are unchanged.
  190. ;---|*|
  191. ;---|*|  Function #9 Get/Set the Real Sound bit.
  192. ;---|*|
  193. ;---|*|         Entry Condition:
  194. ;---|*|         BX may hold 0 to turn off realsound, 100 to turn it on.
  195. ;---|*|         CX determines if the switch is read or written. If cx
  196. ;---|*|            is 0, the switch is read. If cx is not zero, the
  197. ;---|*|            switch is written.
  198. ;---|*|
  199. ;---|*|         Exit Condition:
  200. ;---|*|         If the switch is read, BX holds 0 for off, 100 for on.
  201. ;---|*|         All other registers are unchanged.
  202. ;---|*|
  203. ;---|*|  Function #10 Get/Set the Split FM chips bit.
  204. ;---|*|
  205. ;---|*|         Entry Condition:
  206. ;---|*|         BX may hold 0 to split the chips, 100 to have mono chips
  207. ;---|*|         CX determines if the switch is read or written. If cx
  208. ;---|*|            is 0, the switch is read. If cx is not zero, the
  209. ;---|*|            switch is written.
  210. ;---|*|
  211. ;---|*|         Exit Condition:
  212. ;---|*|         If the switch is read, BX holds 0 for split, 100 for mono.
  213. ;---|*|         All other registers are unchanged.
  214. ;---|*|
  215. ;   \*/
  216.  
  217. ;
  218. ; The following equate sets up the compiled model size for this code:
  219. ;
  220.     MODELSIZE equ 0
  221.  
  222.         include model.inc
  223.         include masm.inc                ; masm equates, etc
  224.         include common.inc              ; hardware equates module
  225.     include state.inc        ; state table
  226.     include binary.inc        ; int2f binary interface module
  227.  
  228.         .code
  229.         assume ds:@code
  230.     assume es:@code
  231.  
  232. ;
  233. ; The following address is the entrypoint into the static mixer driver.
  234. ; This driver was provided as the static linked mixer driver embedded in
  235. ; MIXERC.C. This code compiles into a .COM format, then is translated into
  236. ; a header file to be included into MIXERC.C.
  237. ;
  238.     org    0h            ; The original driver worked
  239.                     ; with a zero offset.
  240.     public    StartingAddress     ; The driver was initialized by
  241. StartingAddress label    far        ; a far call to offset 0 of the driver.
  242.  
  243.     jmp    near ptr doinit     ; go do it...
  244.  
  245.         db    0        ; filler to align on next dword
  246.  
  247. signature    db    "MVPROAS01"     ; 8 byte signature
  248.  
  249.  
  250. ;   /*\
  251. ;---|*|--------------------====< Data Section >====--------------------
  252. ;   \*/
  253.  
  254. FunctionTable    label    near
  255. smixerfunc     dd    offset dosetmixer  ; set the mixers
  256. svolumefunc     dd    offset dosetvolume ; set the volume
  257. sfilterfunc     dd    offset dosetfilter ; set the filter
  258. scrossfunc     dd    offset dosetcross  ; set the cross channel
  259. gmixerfunc     dd    offset dogetmixer  ; get the mixers
  260. gvolumefunc     dd    offset dogetvolume ; get the volume
  261. gfilterfunc     dd    offset dogetfilter ; get the filter
  262. gcrossfunc     dd    offset dogetcross  ; get the cross channel
  263. realsound     dd    offset dorealsound ; get/set the realsound bit
  264. fmsplit      dd    offset dofmsplit   ; get/set the FM split bit
  265.  
  266. TheDMAChannel     db    DEFAULTDMA    ; default DMA channel
  267. TheIRQChannel     db    DEFAULTIRQ    ; default IRQ channel
  268.  
  269. ;
  270. ; These variable hold the current mixer hardware state
  271. ;
  272. _inmixertbl    dw    16 dup(0f0fh)    ; input mixer indexes, settings
  273. _outmixertbl    dw    16 dup(0f0fh)    ; output mixer indexes, settings
  274. _currmixer    db    16 dup(0fh)    ; pointer to the other tables
  275. _voltbl     dw    8  dup(000fh)    ; total volume indexes, settings
  276. _filtidx    db    0        ; filter index (0 - 6)
  277.  
  278. HardwareShadowTable    MVState <0>
  279. mvhwShadowPointer    dd    0    ; far pointer to the state table
  280. mvhwFunctionTable    dd    0    ; far pointer to the function table
  281.  
  282. HardwareType    dw    0          ; hardware feature bits
  283. ORIGPAS     equ    0000000000000000b ; all feature bits are zero
  284. bMVA508     equ    0000000000000001b ; new mixer chip
  285. CDPC        equ    0000000100000000b ; CDPC  installed at original address
  286. PAS16        equ    0000001000000000b ; PAS16 installed at original address
  287. PAS8        equ    0000010000000000b ; PAS8  installed at original address
  288.  
  289. sbleft        db    0        ; SB left mixer connection
  290. sbright     db    0        ; SB right mixer connection
  291.  
  292. ;
  293. ; a table of maximum physical settings for each of the volume control device.
  294. ;
  295. _voltblmax      db      02
  296.         db    03
  297.         db    EQUALIZERMAX
  298.         db    EQUALIZERMAX
  299. _volleftmax    db    ?        ; volume max changes between
  300. _volritmax    db    ?        ; mixer chips
  301.         db    06
  302.         db    00
  303. ;
  304. ; a linear table of filter values - from mute to high for the 8 bit filter
  305. ;
  306. tableof label    byte
  307.     db     000000b            ; mute - goes to PC speaker
  308.     db     100100b            ; 20hz to  2.9khz
  309.     db     111001b            ; 20hz to  5.9khz
  310.     db     110001b            ; 20hz to  8.9khz
  311.     db     101001b            ; 20hz to 11.9khz
  312.     db     100010b            ; 20hz to 15.9khz
  313.     db     100001b            ; 20hz to 17.8khz
  314.  
  315. ;
  316. ; National Semi's Mixer Volume settings (0 - 12)
  317. ;
  318. mixersettings    label    byte
  319.     db    0            ; level 0
  320.     db    20H            ; level 1
  321.     db    10H            ; level 2
  322.     db    08H            ; level 3
  323.     db    04H            ; level 4
  324.     db    02H            ; level 5
  325.     db    12H            ; level 6
  326.     db    2AH            ; level 7
  327.     db    16H            ; level 8
  328.     db    01H            ; level 9
  329.     db    29H            ; level A
  330.     db    1DH            ; level B
  331.     db    2FH            ; level C
  332.  
  333.  
  334. ;   /*\
  335. ;---|*|--------------------====< Code Section >====--------------------
  336. ;   \*/
  337.  
  338. ;   /*\
  339. ;---|*|------------------------==================-------------------------
  340. ;---|*|------------------------====< doinit >====-------------------------
  341. ;---|*|------------------------==================-------------------------
  342. ;---|*|
  343. ;---|*| This routine is only called if the DOS driver is not loaded, so
  344. ;---|*| we must init the various stuff...
  345. ;---|*|
  346. ;---|*| Entry Conditions:
  347. ;---|*|     None
  348. ;---|*|
  349. ;---|*| Exit Conditions:
  350. ;---|*|     DX:AX point to the function table
  351. ;---|*|     BX holds the DMA channel #
  352. ;---|*|     CX holds the IRQ channel #
  353. ;---|*|
  354. ;   \*/
  355.  
  356. invmso_done    db    0        ; perform this code just once!
  357.  
  358.     public    doinit
  359. doinit  proc    far
  360.     push    ds
  361.  
  362.         push    cs                      ; all data is stored locally.
  363.     pop    ds
  364. ;
  365. ; perform the hardware code initialization
  366. ; this code can only be processed once
  367. ;
  368.     cmp    [invmso_done],0     ; have we been here?
  369.     jjnz    inmv_done        ; yes, don't do this again
  370.     inc    [invmso_done]        ; no, so pass by just once
  371. ;
  372. ; determine the hardware and setup for default stand-alone operation
  373. ;
  374.         mov     bx,ORIGPAS              ; bx holds the flags
  375.  
  376.         mov     dx,INTRCTLR             ; check the board rev bits
  377.     in    al,dx
  378.     test    al,fICrevbits        ; non-zero means we have new hardware
  379.     jz    foundthehardware
  380.  
  381.     mov    bx,CDPC
  382.     mov    dx,MASTERMODRD        ; check for the CDPC
  383.     in    al,dx
  384.     test    al,bMMRDmsmd        ; master/slave bit set?
  385.     jnz    foundthehardware
  386.  
  387.     mov    bx,PAS8         ; check for the 8 bit card
  388.     mov    dx,SLAVEMODRD        ; check for the CDPC
  389.     in    al,dx
  390.     test    al,bSMRDdactyp        ; 16 bit DAC?
  391.     jz    foundthehardware    ; no, so it's the PAS16 card
  392.     mov    bx,PAS16+bMVA508    ; check for the 8 bit card
  393.     ;
  394.     foundthehardware:
  395.     mov    [HardwareType],bx    ; save the type
  396.  
  397.     test    bx,PAS16        ; is a PAS16 with the new mixer?
  398.  
  399.         mov     bl,MVVOLUMEMAX          ; (default to new mixer)
  400.     mov    ax,(L_FREE*256)+R_FREE    ; SB is FREE for mva508 types
  401.  
  402.         jnz     @F
  403.  
  404.         mov     bl,NSVOLUMEMAX                  ; no, use the NS mixer data
  405.     mov    ax,(L_SPEAKER*256)+R_SPEAKER    ; SB is SPEAKER for others
  406.     ;
  407.     @@:
  408.     mov    [_volleftmax],bl    ; save the maximum volume setting
  409.     mov    [_volritmax],bl
  410.     mov    [sbleft],ah        ; save the sb connections
  411.     mov    [sbright],al
  412. ;
  413. ; we must complete the 32 bit addresses in the vector table
  414. ;
  415.     push    es
  416.     push    di
  417.  
  418.     mov    ax,cs            ; ax holds the segment for storing
  419.     lea    bx,FunctionTable
  420.     mov    wptr [mvhwFunctionTable+0],bx ; save a copy of the table
  421.     mov    wptr [mvhwFunctionTable+2],ax ; pointer in our code
  422.  
  423.     mov    es,ax            ; es:di points to the local table
  424.     mov    di,bx
  425.     mov    cx,10            ; update just ten entries
  426.     cld
  427.     ;
  428.     @@:
  429.     inc    di            ; pass the offset
  430.         inc     di
  431.     stosw                ; store the segment
  432.     loop    @B
  433.  
  434.     pop    di
  435.     pop    es
  436. ;
  437. ; setup a pointer to our local hardware state table
  438. ;
  439.     lea    bx,HardwareShadowTable
  440.     mov    wptr [mvhwShadowPointer+0],bx
  441.     mov    wptr [mvhwShadowPointer+2],cs
  442. ;
  443. ; find the int 2F interface
  444. ;
  445.     mov    ax,0bc00h        ; load the registers to check if
  446.     mov    bx,'??'                 ; MVSOUND.SYS is loaded.
  447.     sub    cx,cx            ; this is a unique enough approach
  448.     sub    dx,dx
  449.  
  450.         int     2fh                     ; get the response
  451.  
  452.         xor     bx,cx                   ; merge the response into BX
  453.     xor    bx,dx
  454.     cmp    bx,'MV'                 ; is the int 2F interface here?
  455.     jnz    inmv_done        ; no, exit home
  456. ;
  457. ; the int 2F interface is there, so get the state table.
  458. ;
  459.     mov    ax,0bc02h        ; get the state table pointer
  460.         int     2fh
  461.     mov    wptr [mvhwShadowPointer+0],bx
  462.     mov    wptr [mvhwShadowPointer+2],dx
  463.  
  464.     mov    ax,0bc03h        ; get the function pointer
  465.     int    2fh
  466.     mov    wptr [mvhwFunctionTable+0],bx
  467.     mov    wptr [mvhwFunctionTable+2],dx
  468.  
  469.         mov     ax,0bc04h               ; get the DMA and IRQ numbers
  470.     int    2fh
  471.     mov    TheDMAChannel,bl    ; save the correct DMA & IRQ
  472.     mov    TheIRQChannel,cl
  473. ;
  474. inmv_done:
  475.     mov    ax,wptr [mvhwFunctionTable+0]
  476.     mov    dx,wptr [mvhwFunctionTable+2]
  477.  
  478.         pop     ds
  479.     retf
  480.  
  481. doinit    endp
  482.  
  483. ;
  484. ;   /*\
  485. ;---|*|-------------------------===================-------------------------
  486. ;---|*|-----------------------====< dogetcross >====-------------------------
  487. ;---|*|-------------------------===================-------------------------
  488. ;---|*|
  489. ;---|*| Return the Cross channel mask
  490. ;---|*|
  491. ;---|*| Entry Conditions:
  492. ;---|*|     None
  493. ;---|*|
  494. ;---|*| Exit Conditions:
  495. ;---|*|     BX holds the old cross channel mask bits:
  496. ;---|*|
  497. ;---|*|     00000001b Right to Right
  498. ;---|*|     00000010b Right to Left
  499. ;---|*|     00000100b Left    to Right
  500. ;---|*|     00001000b Left    to Left
  501. ;---|*|
  502. ;---|*|     A set bit means the connection is ON.
  503. ;---|*|     A clear bit means the connection is OFF.
  504. ;---|*|
  505. ;   \*/
  506.  
  507.     public    dogetcross
  508. dogetcross    proc    far
  509.  
  510.     push    ax              ; save everything
  511.     push    cx
  512.     push    dx
  513.     push    ds
  514.  
  515.         push    es
  516.     push    di
  517.  
  518.     les    di,cs:[mvhwShadowPointer] ; get the pointer
  519.     mov    bl,es:[di._crosschannel]
  520.     and    bx,0000fh
  521.  
  522.         pop     di
  523.     pop    es
  524. ;
  525. far_return_less_bx    label    near
  526.     pop    ds
  527.     pop    dx
  528.     pop    cx
  529.     pop    ax
  530.     retf
  531.  
  532. dogetcross    endp
  533.  
  534. ;
  535. ;   /*\
  536. ;---|*|-------------------------===================-------------------------
  537. ;---|*|-----------------------====< dosetcross >====-------------------------
  538. ;---|*|-------------------------===================-------------------------
  539. ;---|*|
  540. ;---|*| Load a new cross channel mask
  541. ;---|*|
  542. ;---|*| Entry Conditions:
  543. ;---|*|     BX holds the new cross channel mask bits:
  544. ;---|*|
  545. ;---|*|     00000001b Right to Right
  546. ;---|*|     00000010b Right to Left
  547. ;---|*|     00000100b Left    to Right
  548. ;---|*|     00001000b Left    to Left
  549. ;---|*|
  550. ;---|*|     A set bit turns ON the connection.
  551. ;---|*|     A clear bit turns OFF the connection.
  552. ;---|*|
  553. ;---|*| Exit Conditions:
  554. ;---|*|     None
  555. ;---|*|
  556. ;   \*/
  557.  
  558.     public    dosetcross
  559. dosetcross      proc    far
  560.  
  561.         push    ax
  562.     push    bx
  563.     push    cx
  564.     push    dx
  565.     push    ds
  566.  
  567.         push    es
  568.     push    di
  569.     pushf
  570.  
  571.     les    di,cs:[mvhwShadowPointer]    ; get the pointer
  572.     mov    dx,CROSSCHANNEL
  573.     xchg    ax,bx
  574.  
  575.     cli                    ; kill ints until popf
  576.     mov    ah,es:[di._crosschannel]
  577.     and    ax,0f00fh
  578.     or    al,ah
  579.     mov    es:[di._crosschannel],al
  580.     out    dx,al
  581.  
  582.     popf
  583.         pop     di
  584.     pop    es
  585.  
  586.     jmp    far_return
  587.  
  588. dosetcross    endp
  589.  
  590. ;
  591. ;   /*\
  592. ;---|*|------------------------====================------------------------
  593. ;---|*|----------------------====< dogetfilter >====------------------------
  594. ;---|*|------------------------====================------------------------
  595. ;---|*|
  596. ;---|*| Return the current filter settings, from 0 to 100 %, where
  597. ;---|*| 0 is mute and 100 % is CD quality
  598. ;---|*|
  599. ;---|*| Entry Conditions:
  600. ;---|*|     None
  601. ;---|*|
  602. ;---|*| Exit Conditions:
  603. ;---|*|     BX holds the value
  604. ;---|*|
  605. ;   \*/
  606.  
  607.     public    dogetfilter
  608. dogetfilter    proc    far
  609.  
  610.         push    ax                      ; save everything
  611.     push    cx
  612.     push    dx
  613.     push    ds
  614.  
  615.         push    es
  616.     push    di
  617.     les    di,cs:[mvhwShadowPointer] ; get the pointer
  618.     mov    al,es:[di._audiofilt]
  619.         pop     di
  620.     pop    es
  621.  
  622.     sub    bx,bx            ; ax starts with mute
  623.     test    al,20h            ; mute bit clear
  624.     jz    dogefi_done        ; yes, we have the value
  625.  
  626.     mov    bx,17
  627.     cmp    al,24h            ; male voice?
  628.     jz    dogefi_done
  629.  
  630.     mov    bx,34
  631.     cmp    al,39h            ; Telephone?
  632.     jz    dogefi_done
  633.  
  634.     mov    bx,50
  635.     cmp    al,31h            ; AM Radio?
  636.     jz    dogefi_done
  637.  
  638.     mov    bx,67
  639.     cmp    al,29h            ; FM Radio?
  640.     jz    dogefi_done
  641.  
  642.     mov    bx,84
  643.     cmp    al,22h            ; Cassette?
  644.     jz    dogefi_done
  645.  
  646.     mov    bx,100            ; CD = 100 %
  647.  
  648. dogefi_done:
  649.     jmp    short far_return_less_bx
  650.  
  651. dogetfilter    endp
  652.  
  653. ;
  654. ;   /*\
  655. ;---|*|------------------------====================------------------------
  656. ;---|*|----------------------====< dosetfilter >====------------------------
  657. ;---|*|------------------------====================------------------------
  658. ;---|*|
  659. ;---|*| Set the filter to a setting from 0 to 100 %, where 0 is mute, 100 %
  660. ;---|*| is no filtering at all.
  661. ;---|*|
  662. ;---|*| Entry Conditions:
  663. ;---|*|     BX holds the value
  664. ;---|*|
  665. ;---|*| Exit Conditions:
  666. ;---|*|     None
  667. ;---|*|
  668. ;   \*/
  669.  
  670.     public    dosetfilter
  671. dosetfilter     proc    far
  672.     push    ax            ; save everything
  673.     push    bx
  674.     push    cx
  675.     push    dx
  676.     push    ds
  677.  
  678.         push    cs                      ; all data is stored locally.
  679.     pop    ds
  680.  
  681.     mov    ax,6            ; translate 0-100 % into 0-6
  682.     mov    bh,ah            ; flush the top half
  683.     xchg    ax,bx
  684.     or    ax,ax            ; if mute, skip the math...
  685.     jz    @F
  686.     mul    bx
  687.         mov     bl,100
  688.     div    bx            ; ax holds the new setting
  689. ;
  690. @@:
  691.         push    ax
  692.     call    SetFilter
  693.     pop    ax
  694.     jmp    far_return
  695.  
  696. dosetfilter       endp
  697.  
  698. ;
  699. ;   /*\
  700. ;---|*|------------------------===================------------------------
  701. ;---|*|----------------------====< dogetmixer >====------------------------
  702. ;---|*|------------------------===================------------------------
  703. ;---|*|
  704. ;---|*| Return the channel setting in either the input or output mixer.
  705. ;---|*| The return value will be 0 - 100 %
  706. ;---|*|
  707. ;---|*| Entry Conditions:
  708. ;---|*|     CX holds the mixer select (BI_OUTPUTMIXER or BI_INPUTMIXER)
  709. ;---|*|     DX holds the channel      (ex: L_LEFTFM, R_LEFTFM, etc.)
  710. ;---|*|
  711. ;---|*| Exit Conditions:
  712. ;---|*|     BX returns the volume     (0 - 100%)
  713. ;---|*|
  714. ;   \*/
  715.  
  716.     public    dogetmixer
  717. dogetmixer      proc    far
  718.     push    ax            ; save everything
  719.     push    cx
  720.     push    dx
  721.     push    ds
  722.  
  723.         push    cs                      ; all data is stored locally.
  724.     pop    ds
  725.  
  726.     mov    bx,dx
  727.         and     bx,0fh                  ; make sure the channel is legit
  728.     lea    ax,_inmixertbl
  729.     cmp    cx,BI_INPUTMIXER
  730.     jz    @F
  731.     lea    ax,_outmixertbl
  732.     ;
  733.     @@:
  734.     sub    cl,_currmixer[bx]    ; get the current channel selection
  735.         add     bx,ax
  736.     mov    al,[bx]         ; get the current value
  737.  
  738.         mov     bx,100                  ; translate 0-31 into 0-100%
  739.     cbw
  740.     mul    bx
  741.     or    ax,ax
  742.     jz    @F
  743.         mov     bl,31
  744.     div    bx            ; ax holds the new setting
  745.     ;
  746.     @@:
  747.     call    rounduppct        ; psuedo round up
  748.     xchg    ax,bx            ; bl holds the result
  749.     cmp    cl,1            ; carry set if Z, clear if NZ
  750.     sbb    bh,bh            ; bh holds the ON/OFF flag
  751.     jmp    far_return_less_bx
  752.  
  753. dogetmixer    endp
  754.  
  755. ;
  756. ;   /*\
  757. ;---|*|------------------------===================------------------------
  758. ;---|*|----------------------====< dosetmixer >====------------------------
  759. ;---|*|------------------------===================------------------------
  760. ;---|*|
  761. ;---|*| Set an input or output mixer channel from 0 to 100%
  762. ;---|*|
  763. ;---|*| Entry Conditions:
  764. ;---|*|     BX holds the volume       (0 - 100%)
  765. ;---|*|     CX holds the mixer select (BI_OUTPUTMIXER or BI_INPUTMIXER)
  766. ;---|*|     DX holds the channel      (ex: L_LEFTFM, R_LEFTFM, etc.)
  767. ;---|*|
  768. ;---|*| Exit Conditions:
  769. ;---|*|     None
  770. ;---|*|
  771. ;   \*/
  772.  
  773.     public    dosetmixer
  774. dosetmixer      proc    far
  775.  
  776.         push    ax                      ; save everything
  777.     push    bx
  778.     push    cx
  779.     push    dx
  780.     push    ds
  781.  
  782.         push    cs                      ; all data is stored locally.
  783.     pop    ds
  784. ;
  785. ; special case the variable channel assignments here...
  786. ;
  787.     cmp    cl,BI_L_SBDAC        ; if left SB
  788.     jnz    @F
  789.     mov    cl,[sbleft]        ; force it to be true
  790.     jmp    chgdone
  791.     ;
  792.     @@:
  793.     cmp    cl,BI_R_SBDAC        ; if right SB
  794.     jnz    @F
  795.     mov    cl,[sbright]        ; force it to be true
  796.     ;
  797.     chgdone:
  798. ;
  799. ; perform the mixer settings now...
  800. ;
  801.     push    dx            ; save the channels
  802.     push    dx            ; and one more copy
  803.  
  804.         mov     ax,31                   ; translate 0-100% into 0-31
  805.         mov     bh,ah                   ; flush the top half
  806.     xchg    ax,bx
  807.     or    ax,ax            ; if mute, skip the math...
  808.     jz    @F
  809.     mul    bx
  810.     mov    bl,100
  811.     div    bx            ; ax holds the new setting
  812. ;
  813. @@:
  814.     pop    bx            ; get the channel
  815.     and    bx,0fh            ; make sure the channel is legit
  816.  
  817.     lea    dx,_inmixertbl
  818.     mov    ch,INPUTMIXER
  819.     cmp    cl,BI_INPUTMIXER
  820.     jz    @F
  821.     lea    dx,_outmixertbl
  822.     mov    ch,OUTPUTMIXER
  823.     ;
  824.     @@:
  825.     mov    _currmixer[bx],cl    ; save the channel selection
  826.     add    bx,dx
  827.  
  828.     call    FetchMixLevel        ; on the National chip, convert to 0-12
  829.     mov    [bx],ax         ; save the new value
  830.  
  831.     xchg    ah,al            ; let ax hold the converted value
  832.     cbw
  833.  
  834.     mov    cl,ch            ; cl holds the parameter
  835.     mov    bx,ax            ; bx holds the channel setting
  836.     pop    ax            ; ax holds the channel #
  837.     call    SetMixer        ; set the mixer
  838. ;
  839. far_return      label   near            ; here for convienience sake
  840.     pop    ds
  841.         pop     dx
  842.     pop    cx
  843.     pop    bx
  844.     pop    ax
  845.     retf
  846.  
  847. dosetmixer    endp
  848.  
  849. ;
  850. ;   /*\
  851. ;---|*|------------------------====================------------------------
  852. ;---|*|----------------------====< dogetvolume >====------------------------
  853. ;---|*|------------------------====================------------------------
  854. ;---|*|
  855. ;---|*| Return with one of the volume register settings
  856. ;---|*|
  857. ;---|*| Entry Conditions:
  858. ;---|*|     CX holds the channel
  859. ;---|*|
  860. ;---|*| Exit Conditions:
  861. ;---|*|     BX holds the value
  862. ;---|*|
  863. ;   \*/
  864. ;
  865.     .errnz    VOLMUTE-40h            ; volume devices have bit 6 set
  866.     .errnz    BI_VOLENHANCE-BI_VOLLOUD-1  ; LOUDNESS=0, ENHANCED=1
  867.  
  868.     public    dogetvolume
  869. dogetvolume    proc    far
  870.  
  871.         push    ax                      ; save everything
  872.     push    cx
  873.     push    dx
  874.     push    ds
  875.  
  876.         push    cs                      ; all data is stored locally.
  877.     pop    ds
  878. ;
  879. ; convert the channel number to the table index
  880. ;
  881.     and    cx,07h            ; make it legit
  882.     mov    bx,cx            ; load the index into bx
  883.     cmp    cl,1            ; if it's BI_VOLLOUD, make it BI_VOLEHN...
  884.     sbb    ax,ax            ; ax = ffff if 0, 0000 if 1
  885.     adc    bl,0            ; if bl = 40, bl++
  886.     shl    bx,1            ; word indexing...
  887.  
  888.     mov    bx,[_voltbl+bx]     ; get the setting
  889. ;
  890. ; convert the volume settings into 0 - 100 % values
  891. ;
  892.     dec    cx            ; if 1, then it's loudness, enhanced
  893.     jle    dogvo_loudness        ; go do it...
  894.     mov    al,12
  895.     sub    cl,2            ; if LE,then it's BASS or TREBLE scale
  896.     jle    dogvo_scale
  897.         mov     al,40
  898. ;
  899. ; volume or equalizer settings
  900. ;
  901.     dogvo_scale:
  902.     xchg    ax,bx            ; ax = the current setting, bx the max
  903.     or    ax,ax
  904.     jz    dogvo_done
  905.     mov    cx,100
  906.     mul    cx
  907.     div    bx
  908.     jmp    short dogvo_done
  909. ;
  910. ; loudness and enhanced buttons
  911. ;
  912.     dogvo_loudness:
  913.     not    ax
  914.     and    al,1            ; al = 0 for volloud, 1 for enhanced
  915.     inc    al            ; al = 1 for volloud, 2 for enhanced
  916.  
  917.     and    al,bl            ; al holds the bit
  918.     neg    al            ; set carry on zero
  919.     sbb    al,al
  920.     and    ax,100            ; ax = 0 for off, 100 for on
  921. ;
  922. dogvo_done:
  923.     call    rounduppct        ; psuedo rounding
  924.     xchg    ax,bx            ; bx holds the result
  925.     jmp    far_return_less_bx
  926.  
  927. dogetvolume    endp
  928.  
  929. ;
  930. ;   /*\
  931. ;---|*|------------------------====================------------------------
  932. ;---|*|----------------------====< dosetvolume >====------------------------
  933. ;---|*|------------------------====================------------------------
  934. ;---|*|
  935. ;---|*| Set one of the volume register with stufff...
  936. ;---|*|
  937. ;---|*| Entry Conditions:
  938. ;---|*|     BX holds the value
  939. ;---|*|     CX holds the channel
  940. ;---|*|
  941. ;---|*| Exit Conditions:
  942. ;---|*|     None
  943. ;---|*|
  944. ;   \*/
  945. ;
  946.     .errnz    VOLMUTE-40h            ; volume devices have bit 6 set
  947.     .errnz    BI_VOLENHANCE-BI_VOLLOUD-1  ; LOUDNESS=0, ENHANCED=1
  948.  
  949.     public    dosetvolume
  950. dosetvolume     proc    far
  951.  
  952.         push    ax                      ; save everything
  953.     push    bx
  954.     push    cx
  955.     push    dx
  956.     push    ds
  957.  
  958.         push    cs                      ; all data is stored locally.
  959.     pop    ds
  960.  
  961.         sub     bh,bh                   ; make sure its a low value
  962. ;
  963. ; convert the channel number to something close
  964. ;
  965.     or    cl,40h            ; add in the National device select bit
  966. ;
  967. ; volume settings
  968. ;
  969.     cmp    cl,BI_VOLLEFT+40H
  970.     jz    dovo_volume
  971.     cmp    cl,BI_VOLRIGHT+40H
  972.     jnz    dovo_notvolume
  973.     ;
  974.     dovo_volume:
  975.     mov    al,[_volleftmax]    ; xlat 0-100% to the physical max
  976.     cbw
  977.     xchg    ax,bx
  978.     or    ax,ax
  979.     jz    dovo_sendit
  980.     mul    bx
  981.     mov    bl,100
  982.     div    bx
  983.     jmp    short dovo_sendit
  984. ;
  985. dovo_notvolume:
  986. ;
  987. ; bass/treble settings
  988. ;
  989.     cmp    cl,BI_VOLBASS+40H
  990.     jz    dovo_bass
  991.     cmp    cl,BI_VOLTREBLE+40H
  992.     jnz    dovo_not_basstreble
  993.     ;
  994.     dovo_bass:
  995.     mov    ax,12            ; xlat 0-100% to 0-12
  996.     xchg    ax,bx
  997.     or    ax,ax
  998.     jz    dovo_sendit
  999.     mul    bx
  1000.     mov    bl,100
  1001.     div    bx
  1002.     jmp    short dovo_sendit
  1003. ;
  1004. dovo_not_basstreble:
  1005. ;
  1006. ; loudness and enhanced buttons
  1007. ;
  1008.     mov    ax,0fe01h        ; load a mask for stripping/saving bits
  1009.     cmp    cl,BI_VOLLOUD+40H    ; loudness?
  1010.     jz    dovo_loudness        ; yes, use it
  1011.     cmp    cl,BI_VOLENHANCE+40H    ; enhanced?
  1012.     jnz    dovo_bad        ; no, bomb out...
  1013.     mov    ax,0fd02h        ; load a mask for stripping/saving bits
  1014.     ;
  1015.     dovo_loudness:
  1016.  
  1017.         or      cl,01                   ; calc the true volume register
  1018.     .errnz    (VOLLOUDENH AND 0BFh) - 1 ; make sure the above ADD works
  1019.  
  1020.     and    ah,byte ptr [_voltbl+2]     ; get all other bits
  1021.     .errnz    VOLLOUDENH-41h        ; must be entry #2
  1022.  
  1023.     neg    bl            ; sets carry if not zero
  1024.     sbb    bl,bl            ; bl = 0000 if 0, else ffff for 1
  1025.     and    al,bl
  1026.     or    al,ah            ; al holds the new value
  1027. ;
  1028. dovo_sendit:
  1029.     sub    ch,ch            ; guarrenteed goodness...
  1030.     sub    ah,ah            ; guarrenteed goodness...
  1031.     mov    bx,cx            ; bx holds the channel, ax the value
  1032.     xchg    ax,bx            ; for keeping the parameters straight...
  1033.         call    SetVolume
  1034. ;
  1035. dovo_bad:
  1036.     jmp    far_return
  1037.  
  1038. dosetvolume    endp
  1039.  
  1040. ;
  1041. ;   /*\
  1042. ;---|*|------------------===============================-----------------------
  1043. ;---|*|----------------====< dorealsound/dofmsplit >======---------------------
  1044. ;---|*|------------------===============================-----------------------
  1045. ;---|*|
  1046. ;---|*| Set/Get the realsound and FM bit settings
  1047. ;---|*|
  1048. ;---|*| Entry Conditions:
  1049. ;---|*|     BX holds the 0 for off, ~0 for ON
  1050. ;---|*|     CX holds 0 to get, 1 to set the bit
  1051. ;---|*|
  1052. ;---|*| Exit Conditions:
  1053. ;---|*|     BX may return the value
  1054. ;---|*|
  1055. ;   \*/
  1056. ;
  1057.     public    dorealsound
  1058. dorealsound     proc    far
  1059.  
  1060.         push    ax                      ; save everything
  1061.     push    cx
  1062.     push    dx
  1063.     push    ds
  1064.  
  1065.     mov    ah,bMIspkrint        ; realsound bit
  1066.  
  1067.         push    cs                      ; all data is stored locally.
  1068.     pop    ds
  1069.  
  1070.     push    es
  1071.     push    di
  1072.     les    di,mvhwShadowPointer    ; get the pointer
  1073. ;
  1074. finish_common_code:
  1075.     jcxz    dogetrealorfm        ; if not set, go get the bit
  1076.  
  1077.     push    bx            ; since this is a SET we can't flush bx
  1078. ;
  1079. ; create an AND / OR mask to set/clear the bit
  1080. ;
  1081.     neg    bx            ; set carry if nonzero
  1082.     sbb    al,al            ; al = 0000 for 0, ffff for 1
  1083.     and    al,ah            ; al holds the OR bit mask
  1084.     not    ah            ; ah holds the AND bit mask
  1085.  
  1086.         mov     dx,AUDIOMIXR
  1087.  
  1088.         pushf
  1089.     cli
  1090.  
  1091.     and    ah,es:[di._audiomixr]    ; get all but the realsound/fm bit
  1092.  
  1093.         or      al,ah                   ; merge into the one bit
  1094.  
  1095.     out    dx,al
  1096.     mov    es:[di._audiomixr],al    ; save the new bit
  1097.  
  1098.     popf
  1099.     pop    bx                 ; restore bx
  1100.     jmp    short dogetrealdone
  1101.     ;
  1102.     dogetrealorfm:
  1103.  
  1104.     and    ah,es:[di._audiomixr]    ; get the bit
  1105.     neg    ah            ; carry set if nonzero
  1106.     sbb    bx,bx            ; bx = ffff for ~0, 0000 for 0
  1107.     and    bx,100            ; bx = 0 or 100%
  1108.     ;
  1109.     dogetrealdone:
  1110.     pop    di
  1111.     pop    es
  1112.     jmp    far_return_less_bx
  1113.  
  1114. ;
  1115. ;----====< dofmsplit entrypoint >====----
  1116. ;
  1117.  
  1118. dofmsplit    label far
  1119.     push    ax            ; save everything
  1120.     push    cx
  1121.     push    dx
  1122.     push    ds
  1123.  
  1124.     mov    ah,bMImonofm        ; fm bit
  1125.  
  1126.         push    cs                      ; all data is stored locally.
  1127.     pop    ds
  1128. ;
  1129. ; check the different hardware versions.
  1130. ;
  1131.     push    es
  1132.     push    di
  1133.     les    di,mvhwShadowPointer    ; get the pointer
  1134.  
  1135.     test    es:[di._intrctlr],fICidbits ; rev 2+ ?
  1136.     jz    finish_common_code        ; no, handle as PAS1
  1137.     jcxz    finish_common_code        ; also, GETs will go that way...
  1138. ;
  1139. ; OPL3 board, so do the switch at the OPL3 chip
  1140. ;
  1141.     mov    ax,bx            ; save BX
  1142.     neg    ax            ; set carry to turn off
  1143.     sbb    ax,ax            ; al = 0 for OFF, FF for ON
  1144.     and    ah,1            ; ah = 0 for OFF, 01 for ON
  1145.     xor    ah,1            ; flip for the OPL 3
  1146. ;
  1147. ; maintain compatibility with the old mixer setup.
  1148. ;
  1149.     and    al,bMImonofm        ; save just that bit
  1150.  
  1151.     and    es:[di._audiomixr],NOT bMImonofm ; flush the bit
  1152.     or    es:[di._audiomixr],al         ; maybe set the bit
  1153.  
  1154.     mov    al,05h
  1155.     mov    dx,RFMADDR        ; write to the new bit in the OPL3
  1156.     out    dx,al            ; index first...
  1157.     inc    dx
  1158.  
  1159.         in      al,dx                   ; waste time...
  1160.         in      al,dx                   ; waste time...
  1161.  
  1162.     mov    al,ah            ; data next...
  1163.     out    dx,al
  1164.  
  1165.     jmp    short dogetrealdone    ; exit via common code
  1166.  
  1167. dorealsound     endp
  1168.  
  1169. ;
  1170. ;   /*\
  1171. ;---|*|----====< int SetCrossChannel >====----
  1172. ;---|*|
  1173. ;---|*| Output New Cross Channel Select Bits
  1174. ;---|*|
  1175. ;---|*| Entry Conditions:
  1176. ;---|*|     AX holds the channel bit
  1177. ;---|*|     DX holds the state (0 or -1)
  1178. ;---|*|     DS holds our data segment
  1179. ;---|*|
  1180. ;---|*| Exit Conditions:
  1181. ;---|*|     AX,DX modified.
  1182. ;---|*|     h/w channel select modified
  1183. ;---|*|
  1184. ;   \*/
  1185.  
  1186.     public    SetCrossChannel
  1187. SetCrossChannel proc
  1188.     push    es
  1189.     push    di
  1190.     les    di,mvhwShadowPointer    ; get the pointer
  1191.  
  1192.         mov     ah,al                   ; ah = AND mask al = XOR mask
  1193.     not    ah
  1194.     and    al,dl            ; al = 00 to clear, else 0X to set
  1195.  
  1196.         mov     dx,CROSSCHANNEL
  1197.  
  1198.     disable
  1199.  
  1200.     and    ah,es:[di._crosschannel]
  1201.     xor    al,ah
  1202.     out    dx,al
  1203.     mov    es:[di._crosschannel],al ; save the new value, & return the old
  1204.  
  1205.         enable
  1206.  
  1207.     pop    di
  1208.     pop    es
  1209.     ret
  1210.  
  1211. SetCrossChannel endp
  1212.  
  1213. ;
  1214. ;   /*\
  1215. ;---|*|----====< void SetFilter (int setting ) >===----
  1216. ;---|*|
  1217. ;---|*|       This routine selects a filter setting from mute to high freq filter.
  1218. ;---|*|
  1219. ;---|*| Entry Conditions:
  1220. ;---|*|     AX is a value from 0 - 6
  1221. ;---|*|     DS holds our data segment
  1222. ;---|*|
  1223. ;---|*| Exit Conditions:
  1224. ;---|*|     None
  1225. ;---|*|
  1226. ;---|*|
  1227. ;   \*/
  1228.  
  1229.     public    SetFilter
  1230. SetFilter       proc
  1231.     push    es
  1232.     push    di
  1233.     les    di,mvhwShadowPointer    ; get the pointer
  1234.  
  1235.         mov     bx,ax
  1236.     cmp    bx,6            ; validate the user index
  1237.     ja    sfbadval
  1238.  
  1239.     mov    _filtidx,bl
  1240.     mov    ah,tableof[bx]        ; grab an appropriate value
  1241.     mov    dx,AUDIOFILT        ; and toss it out...
  1242.  
  1243.     disable
  1244.  
  1245.     mov    al,es:[di._audiofilt]    ; get the shadowed gates
  1246.  
  1247.         and     al,not (fFIdatabits+fFImutebits) ; save the non-filter bits
  1248.     or    al,ah            ; merge in the filter bits
  1249.         out     dx,al
  1250.  
  1251.     mov    es:[di._audiofilt],al    ; shadow it too...
  1252.  
  1253.         enable
  1254. ;
  1255. sfbadval:
  1256.     pop    di
  1257.     pop    es
  1258.         ret
  1259.  
  1260. SetFilter    endp
  1261.  
  1262. ;
  1263. ;   /*\
  1264. ;---|*|----====< void SetMixer >====----
  1265. ;---|*|
  1266. ;---|*| Set the selected channel within the MVA508 Mixers & Volume device
  1267. ;---|*|
  1268. ;---|*| Entry Conditions:
  1269. ;---|*|     AX holds the channel (0 - 15)
  1270. ;---|*|     BX holds the volume  (0 - 31)
  1271. ;---|*|     CL holds the device: OUTPUTMIXER or INPUTMIXER or DEFMIXER
  1272. ;---|*|     DS holds our data segment
  1273. ;---|*|
  1274. ;---|*| Exit Conditions:
  1275. ;---|*|     AX,BX,CX,DX modified
  1276. ;---|*|
  1277. ;   \*/
  1278.  
  1279.     public    SetMixer
  1280. SetMixer        proc    near
  1281.     push    es
  1282.     push    di
  1283.     les    di,mvhwShadowPointer    ; get the pointer
  1284.  
  1285.         xchg    bx,ax                   ; bx = channel #, al = volume
  1286.         mov     ah,al                   ; ah = real, al = simulated
  1287.  
  1288.         test    [hardwaretype],bMVA508
  1289.     jjz    nsSetMixer
  1290.     ;
  1291.     ; we scale down the mixer settings to make them
  1292.     ; sound more like the National part.
  1293.     ;
  1294.         mov     ch,ah                   ; multiply the value by 1.25  We take
  1295.     shr    ch,1            ; the value, divide in half, then
  1296.         shr     ch,1                    ; the value, divide in half, then
  1297.     add    ah,ch            ; add it back in.
  1298.     cmp    ah,1Fh            ; not maxed out, just use it...
  1299.         jbe     @F
  1300.     mov    ah,1Fh            ; max it out...
  1301.     ;
  1302.     @@:
  1303. ;
  1304. ; send out the mixer channel #
  1305. ;
  1306.     mov    al,cs:mv510table[bx]    ; get the true mixer channel
  1307.     mov    dx,pAUDIOMIXR        ; parallel mixer address
  1308.     out    dx,al
  1309. ;
  1310. ; convert the mixer select from the National definition to the MVA508
  1311. ;
  1312.     .errnz    OUTPUTMIXER        ; must always be zero
  1313.     .erre    INPUTMIXER        ; must always be non-zero
  1314.     .erre    pmINPUTMIXER        ; must always be non-zero
  1315.  
  1316.     neg    cl            ; CY if INPUT mixer, NC for OUTPUT mixer
  1317.     sbb    al,al
  1318.     and    al,pmINPUTMIXER     ; al now holds the proper bit field
  1319.     or    al,ah            ; real mixer channel volume level
  1320.     out    dx,al
  1321.  
  1322.     mov    es:[di._paudiomixr],al    ; shadow it...
  1323. ;
  1324. semi_exit:
  1325.     pop    di
  1326.     pop    es
  1327.         ret
  1328. ;
  1329. ; National Semi Mixer setting code
  1330. ;
  1331. nsSetMixer:
  1332.     push    ax            ; save the channel setting
  1333.     push    cx            ; save the INPUTMIXER/OUTPUTMIXER bits
  1334. ;
  1335. ; send out the mixer channel #
  1336. ;
  1337.     test    cs:[hardwaretype],CDPC    ; CDPC mixer L/R connections are
  1338.     jz    @F            ; backwards...
  1339.     mov    bl,cs:[cdpcmixer+bx]    ; We will straighten them out.
  1340.     @@:
  1341.     mov    ah,bl            ; restore the register #
  1342.     or    ah,080h         ; OR 080h  d7=channel #
  1343.     or    ah,cl            ; merge in the mixer select
  1344.         call    lmix                    ;  (lvol looks for 80h)
  1345. ;
  1346. ; send out the mixer data
  1347. ;
  1348.     pop    cx            ; get the INPUTMIXER/OUTPUTMIXER
  1349.     pop    ax            ; get the channel setting in AH
  1350.         or      ah,cl                   ; merge in the mixer select
  1351.         call    lmix
  1352. ;
  1353. _semi_exit:
  1354.     pop    di
  1355.     pop    es
  1356.     ret
  1357. ;
  1358. ; This table reverses the mixer settings so left is now right & visa versa.
  1359. ;
  1360. cdpcmixer       label   byte
  1361.     db    15            ;  nothing
  1362.     db    08            ; Left FM
  1363.     db    09            ; Left input mixer
  1364.     db    10            ; Left External
  1365.     db    11            ; Left Internal
  1366.     db    12            ; Left Mic
  1367.     db    13            ; Left PCM
  1368.     db    14            ; Left Speaker
  1369.  
  1370.     db    0            ;  nothing
  1371.     db    01            ; Right FM
  1372.     db    02            ; Right Input Mixer
  1373.     db    03            ; Right External
  1374.     db    04            ; Right Internal
  1375.     db    05            ; Right Mic
  1376.     db    06            ; Right PCM
  1377.     db    07            ; Right Speaker
  1378.  
  1379. pmADMI    equ    <pmADDRSELECT+pmMIXERSELECT>
  1380.  
  1381. mv510table    label    byte        ;Ch #; PAS   ; MVA508
  1382.     db    07+pmCHANNELL+pmADMI    ;  0 ; L_FREE;    7 - Now the SB connect
  1383.     db    00+pmCHANNELL+pmADMI    ;  1 ; L_FM  ;    0
  1384.     db    01+pmCHANNELL+pmADMI    ;  2 ; L_Mix ;    1
  1385.     db    02+pmCHANNELL+pmADMI    ;  3 ; L_Ext ;    2
  1386.     db    03+pmCHANNELL+pmADMI    ;  4 ; L_Int ;    4
  1387.     db    04+pmCHANNELL+pmADMI    ;  5 ; L_Mic ;    3
  1388.     db    05+pmCHANNELL+pmADMI    ;  6 ; L_PCM ;    5
  1389.     db    06+pmCHANNELL+pmADMI    ;  7 ; L_Spk ;    6
  1390.     db    00+pmCHANNELR+pmADMI    ;  8 ; R_FM  ;    0
  1391.     db    01+pmCHANNELR+pmADMI    ;  9 ; R_Mix ;    1
  1392.     db    02+pmCHANNELR+pmADMI    ;  A ; R_Ext ;    2
  1393.     db    03+pmCHANNELR+pmADMI    ;  B ; R_Int ;    4
  1394.     db    04+pmCHANNELR+pmADMI    ;  C ; R_Mic ;    3
  1395.     db    05+pmCHANNELR+pmADMI    ;  D ; R_PCM ;    5
  1396.     db    06+pmCHANNELR+pmADMI    ;  E ; R_Spk ;    6
  1397.     db    07+pmCHANNELR+pmADMI    ;  F ; R_FREE;    7 - Now the SB connect
  1398.  
  1399. SetMixer    endp
  1400.  
  1401. ;
  1402. ;   /*\
  1403. ;---|*|----====< void SetVolume >====----
  1404. ;---|*|
  1405. ;---|*|       This routine outputs a new setting for a volume channel.
  1406. ;---|*|
  1407. ;---|*| Entry Conditions:
  1408. ;---|*|     AX is a register select value from 0 - 7
  1409. ;---|*|     BX is a value to be written to the control
  1410. ;---|*|     DS points to our data segment
  1411. ;---|*|
  1412. ;---|*| Exit Conditions:
  1413. ;---|*|     AX,BX,CX,DX may be modified
  1414. ;---|*|
  1415. ;   \*/
  1416.  
  1417.     public    SetVolume
  1418. SetVolume       proc
  1419.     push    es
  1420.     push    di
  1421.     les    di,mvhwShadowPointer    ; get the pointer
  1422.  
  1423.     test    [hardwaretype],bMVA508
  1424.     jjz    _nsSetVolume
  1425.  
  1426.         xchg    ax,bx                   ; ax = data, bx = channel
  1427.  
  1428.         and     bl,10111111b            ; knock out the Volume ID bit
  1429.  
  1430.         shl     bx,1
  1431.         mov     _voltbl[bx],ax          ; save this channel's volume setting
  1432.     shr    bx,1            ; restore bx & go
  1433.  
  1434.         mov     ah,cs:mva508vol[bx]     ; get the channel number for the MVA508
  1435.     xchg    ah,al            ; al = channel, ah = data
  1436.     cmp    al,-1            ; is there an actual channel?
  1437.     jz    sevo_exit        ; no, just skip it...
  1438.     ;
  1439.     ; special case the loudness and enhanced stereo switches for the MVA508
  1440.     ;
  1441.     cmp    bl,VOLLOUDENH AND 7    ; volume enhance switches?
  1442.     jnz    @F            ; no, continue on...
  1443.     shr    ah,1            ; yes, swap the bit positions
  1444.     sbb    dl,dl
  1445.     and    dl,2
  1446.     or    ah,dl
  1447.     shl    ah,1
  1448.     ;
  1449.     @@:
  1450.         mov     dx,pAUDIOMIXR           ; parallel audio mixer interface
  1451.     out    dx,al            ; write the index
  1452.         xchg    ah,al                   ; al = data, ah = channel
  1453.     out    dx,al            ; write the data
  1454.  
  1455.         mov     es:[di._paudiomixr],al  ; shadow it...
  1456. ;
  1457. sevo_exit:
  1458.     pop    di
  1459.     pop    es
  1460.         ret
  1461. ;
  1462. ; National Semi's total volume control
  1463. ;
  1464. _nsSetVolume:
  1465.     xchg    ax,bx            ; ax = data, bx = channel
  1466.  
  1467.         and     bl,10111111b            ; knock out the Volume ID bit
  1468.     shl    bx,1
  1469.  
  1470.         mov     _voltbl[bx],ax          ; save this channel's volume setting
  1471.  
  1472.     shr    bx,1            ; restore bx & go
  1473.     or    bl,01000000b        ; replace the Volume ID bit
  1474.     mov    ah,al            ; ah = data
  1475.     call    lvol            ; call the read hardware routine
  1476.  
  1477.         jmp     short sevo_exit
  1478.  
  1479. ;
  1480. ; MVA580 mixer channel assignments
  1481. ;
  1482. mva508vol    label    byte           ; ch #  ;  PAS     ; MVA508
  1483.     db    02+pmADDRSELECT+pmCHANNELLR;  0    ; MUTE     ;  VOLB
  1484.     db    05+pmADDRSELECT        ;  1    ; LOUD/ENH ;   5
  1485.     db    03+pmADDRSELECT        ;  2    ; BASS     ;   3
  1486.     db    04+pmADDRSELECT        ;  3    ; TREBLE   ;   4
  1487.     db    01+pmADDRSELECT+pmCHANNELL ;  4    ; L-VOL    ;   1,CC=01
  1488.     db    01+pmADDRSELECT+pmCHANNELR ;  5    ; R-VOl    ;   1,CC=02
  1489.     db    -1               ;  6    ; MODE     ;  N/A
  1490.     db    -1               ;  7    ; N/A      ;  N/A
  1491.  
  1492. SetVolume       endp
  1493.  
  1494. ;
  1495. ;---------------------====================================---------------------
  1496. ;---------------------====< Local Subroutine Section >====---------------------
  1497. ;---------------------====================================---------------------
  1498. ;
  1499.  
  1500. ;   /*\
  1501. ;---|*|----====< FetchMixLevel >====----
  1502. ;---|*|
  1503. ;---|*| Remap mixer level from 0-31 into 0-12
  1504. ;---|*|
  1505. ;---|*| Entry Conditions:
  1506. ;---|*|     AX holds the volume level - guarrenteed to be 0 - 31
  1507. ;---|*|     DS holds our data segment
  1508. ;---|*|
  1509. ;---|*| Exit Condtions:
  1510. ;---|*|     CY = 1, invalid volume level.
  1511. ;---|*|     CY = 0, good volume level.
  1512. ;---|*|      AH holds the converted value.
  1513. ;---|*|      AL the orig index.
  1514. ;---|*|
  1515. ;   \*/
  1516.  
  1517.     public    FetchMixLevel
  1518. FetchMixLevel   proc    near
  1519. ;
  1520. ; ignore if the new mixer
  1521. ;
  1522.     mov    ah,al            ; ah may return the whole thing
  1523.     test    [HardwareType],bMVA508    ; if this is the MVA508
  1524.     jnz    @F
  1525. ;
  1526. ; do the converion for the old mixer
  1527. ;
  1528.         push    bx
  1529.     push    dx
  1530.     push    ax
  1531. ;
  1532. ; remap 0-31 into 0-12: index = (index * 10) / 2.5
  1533. ;
  1534.     mov    dl,10
  1535.     mul    dl
  1536.     mov    dl,25
  1537.     div    dl            ; effectely divides 31 by 2.5
  1538. ;
  1539. ; read the table of hosed values
  1540. ;
  1541.     mov    bl,al
  1542.     sub    bh,bh
  1543.  
  1544.     pop    ax            ; al holds the original index
  1545.     mov    ah,mixersettings[bx]    ; ah holds the real setting
  1546.  
  1547.     pop    dx
  1548.     pop    bx
  1549. ;
  1550. @@:
  1551.     clc
  1552.         ret
  1553.  
  1554. FetchMixLevel    endp
  1555.  
  1556.  
  1557. ;   /*\
  1558. ;---|*|----====< lmix >====----
  1559. ;   \*/
  1560.  
  1561. ;
  1562. ; -- Load The Mixer
  1563. ;
  1564. ; Entry Conditions
  1565. ;    es:di point to the state table
  1566. ;    ah = index/data
  1567. ;    al = to mixer:
  1568. ;        al = INPUTMIXER  (04h) - goes to input mixer
  1569. ;        al = OUTPUTMIXER (08h) - goes to output mixer
  1570. ;
  1571. ; Exit Conditions:
  1572. ;    No registers modified
  1573. ;
  1574.     public    lmix
  1575. lmix    proc    near
  1576.     push    ax
  1577.     push    cx
  1578.     push    dx
  1579.  
  1580.     disable             ; make sure we clock in all data
  1581. ;
  1582. ; all clocks and ; strobes should be 1
  1583. ;
  1584.     mov    dx,AUDIOMIXR        ; load mixer port
  1585.  
  1586.         mov     al,es:[di._audiomixr]   ; save the realsound & dual fm bits
  1587.  
  1588.         and     al,bMIspkrint+bMImonofm
  1589.     or    al,not (bMIspkrint+bMImonofm)
  1590.  
  1591.         mov     cx,8                    ; load bit count
  1592.     out    dx,al            ; set initial clocks
  1593.  
  1594. @@:    xor    al,bMIclock        ; toggle output mixer clock
  1595.         pause
  1596.     out    dx,al            ; output clock is zero
  1597.     ror    al,1            ; make room for data
  1598.     ror    ah,1            ; get bit of data
  1599.     adc    al,al            ; shift into register
  1600.     out    dx,al            ; send data to mixer
  1601.     xor    al,bMIclock        ; toggle clock again
  1602.         pause
  1603.     out    dx,al            ; clock sould be 1 now
  1604.     loop    @B            ; do all 8 bits this way
  1605.  
  1606.         xor     al,bMImistrb            ; toggle strobe low
  1607.     out    dx,al            ; which loads data into mixer
  1608.     pause
  1609.     xor    al,bMImistrb        ; toggle strobe high
  1610.     out    dx,al            ; loading complete
  1611.  
  1612.     mov    es:[di._audiomixr],al    ; save the last state
  1613.  
  1614.         enable
  1615.  
  1616.     pop    dx
  1617.     pop    cx
  1618.     pop    ax
  1619.         ret
  1620.  
  1621. lmix    endp
  1622.  
  1623. ;
  1624. ;   /*\
  1625. ;---|*|----====< lvol >====----
  1626. ;   \*/
  1627.  
  1628. ;
  1629. ; lvol    -- Load Volume control Register
  1630. ;
  1631. ; Entry Conditions:
  1632. ;    bl = parameter register (volume control channel 0-7)
  1633. ;    ah = data to transfer    (new channel setting)
  1634. ;
  1635. ; Exit Conditions:
  1636. ;    AX,BX,CX,DX modified
  1637. ;
  1638.     public    lvol
  1639. lvol    proc    near
  1640. ;
  1641. ; pass everything, but left/right volume directly to the device
  1642. ;
  1643.     cmp    bl,44h            ; left & right volume are presented
  1644.     jz    @F            ; to the logical level as 0 - 40,
  1645.     cmp    bl,45h            ; where 0 is the lowest, and 40 is
  1646.     jnz    lvolout         ; the highest. In reality, this
  1647. @@:    sub    ah,40            ; is backwards, that is, 40 is the
  1648.     neg    ah            ; lowest, and 0 is the highest. We will
  1649. ;                    ; correct the value here...
  1650. ; Perform the volume control output
  1651. ;
  1652. lvolout label    near
  1653.     mov    dx,AUDIOMIXR        ; load mixer port
  1654. ;
  1655. ; all 1s but volume enable and clock
  1656. ;
  1657.     mov    al,es:[di._audiomixr]    ; save the realsound & dual fm bits
  1658.  
  1659.         and     al,bMIspkrint+bMImonofm
  1660.     or    al,not (bMIspkrint+bMImonofm+bMIvol+bMIclock)
  1661.  
  1662.     disable             ; do it all at once, no interruptions
  1663.  
  1664.         out     dx,al                   ; set initial clocks
  1665.     mov    cx,8            ; load bit count for address
  1666. @@:    xor    al,bMIclock        ; toggle volume control clock
  1667.     ror    al,1            ; make room for data
  1668.     ror    bl,1            ; get bit of data
  1669.     adc    al,al            ; shift into register
  1670.     out    dx,al            ; send data to volume control
  1671.     pause
  1672.         xor     al,bMIclock             ; toggle the clock again
  1673.     out    dx,al            ; clock should be 1 now
  1674.     loop    @B            ; do all 8 bits this way...
  1675.     xor    al,bMIvol        ; toggle volume control enable
  1676.         pause
  1677.     out    dx,al            ; which starts data loading
  1678.     mov    cl,8            ; load bit count for data
  1679. @@:    xor    al,bMIclock        ; toggle volume control clock
  1680.     ror    al,1            ; make room for data
  1681.     ror    ah,1            ; get bit of data
  1682.     adc    al,al            ; shift into register
  1683.     out    dx,al            ; send data to volume control
  1684.         pause
  1685.     xor    al,bMIclock        ; toggle clock again
  1686.     out    dx,al            ; clock should be 1 now
  1687.     loop    @B            ; doall a 8 bits this way...
  1688.         pause
  1689.     mov    cl,12            ; load bit count for data
  1690. @@:    out    dx,al            ; need to stall for 6 microseconds
  1691.         pause
  1692.     loop    @B            ; waiting...
  1693.     xor    al,bMIvol        ; toggle volume control enable
  1694.     out    dx,al            ; to prepare
  1695.         pause
  1696.     out    dx,al            ; need to stall
  1697.         pause
  1698.     out    dx,al
  1699.         pause
  1700.     out    dx,al
  1701.         pause
  1702.     xor    al,bMIvol        ; toggle volume control enable
  1703.     out    dx,al            ; which loads data
  1704.  
  1705.     mov    es:[di._audiomixr],al    ; save the last state
  1706.  
  1707.         enable
  1708.  
  1709.         ret
  1710.  
  1711. lvol    endp
  1712.  
  1713. ;
  1714. ;----====< rounduppct >====----
  1715. ;
  1716. rounduppct    proc    near
  1717.     cmp    al,0            ; skip out if less than zero
  1718.     jle    @F
  1719.     cmp    al,100            ; skip out if greater/equal to 100
  1720.     jge    @F
  1721.     inc    al
  1722. ;
  1723. @@:
  1724.     ret
  1725.  
  1726. rounduppct    endp
  1727.  
  1728.  
  1729. ;   /*\
  1730. ;---|*|----====< end of MIXERS.ASM >====----
  1731. ;   \*/
  1732.  
  1733.     end
  1734.  
  1735.