home *** CD-ROM | disk | FTP | other *** search
/ 100 af Verdens Bedste Spil / 100Spil.iso / dos / wolf3d / source / wolfsrc.1 / ID_SD.C < prev    next >
C/C++ Source or Header  |  1993-02-04  |  50KB  |  2,368 lines

  1. //
  2. //    ID Engine
  3. //    ID_SD.c - Sound Manager for Wolfenstein 3D
  4. //    v1.2
  5. //    By Jason Blochowiak
  6. //
  7.  
  8. //
  9. //    This module handles dealing with generating sound on the appropriate
  10. //        hardware
  11. //
  12. //    Depends on: User Mgr (for parm checking)
  13. //
  14. //    Globals:
  15. //        For User Mgr:
  16. //            SoundSourcePresent - Sound Source thingie present?
  17. //            SoundBlasterPresent - SoundBlaster card present?
  18. //            AdLibPresent - AdLib card present?
  19. //            SoundMode - What device is used for sound effects
  20. //                (Use SM_SetSoundMode() to set)
  21. //            MusicMode - What device is used for music
  22. //                (Use SM_SetMusicMode() to set)
  23. //            DigiMode - What device is used for digitized sound effects
  24. //                (Use SM_SetDigiDevice() to set)
  25. //
  26. //        For Cache Mgr:
  27. //            NeedsDigitized - load digitized sounds?
  28. //            NeedsMusic - load music?
  29. //
  30.  
  31. #pragma hdrstop        // Wierdo thing with MUSE
  32.  
  33. #include <dos.h>
  34.  
  35. #ifdef    _MUSE_      // Will be defined in ID_Types.h
  36. #include "ID_SD.h"
  37. #else
  38. #include "ID_HEADS.H"
  39. #endif
  40. #pragma    hdrstop
  41. #pragma    warn    -pia
  42.  
  43. #ifdef    nil
  44. #undef    nil
  45. #endif
  46. #define    nil    0
  47.  
  48. #define    SDL_SoundFinished()    {SoundNumber = SoundPriority = 0;}
  49.  
  50. // Macros for SoundBlaster stuff
  51. #define    sbOut(n,b)    outportb((n) + sbLocation,b)
  52. #define    sbIn(n)        inportb((n) + sbLocation)
  53. #define    sbWriteDelay()    while (sbIn(sbWriteStat) & 0x80);
  54. #define    sbReadDelay()    while (sbIn(sbDataAvail) & 0x80);
  55.  
  56. // Macros for AdLib stuff
  57. #define    selreg(n)    outportb(alFMAddr,n)
  58. #define    writereg(n)    outportb(alFMData,n)
  59. #define    readstat()    inportb(alFMStatus)
  60.  
  61. //    Imports from ID_SD_A.ASM
  62. extern    void            SDL_SetDS(void),
  63.                         SDL_IndicatePC(boolean on);
  64. extern    void interrupt    SDL_t0ExtremeAsmService(void),
  65.                         SDL_t0FastAsmService(void),
  66.                         SDL_t0SlowAsmService(void);
  67.  
  68. //    Global variables
  69.     boolean        SoundSourcePresent,
  70.                 AdLibPresent,
  71.                 SoundBlasterPresent,SBProPresent,
  72.                 NeedsDigitized,NeedsMusic,
  73.                 SoundPositioned;
  74.     SDMode        SoundMode;
  75.     SMMode        MusicMode;
  76.     SDSMode        DigiMode;
  77.     longword    TimeCount;
  78.     word        HackCount;
  79.     word        *SoundTable;    // Really * _seg *SoundTable, but that don't work
  80.     boolean        ssIsTandy;
  81.     word        ssPort = 2;
  82.     int            DigiMap[LASTSOUND];
  83.  
  84. //    Internal variables
  85. static    boolean            SD_Started;
  86.         boolean            nextsoundpos;
  87.         longword        TimerDivisor,TimerCount;
  88. static    char            *ParmStrings[] =
  89.                         {
  90.                             "noal",
  91.                             "nosb",
  92.                             "nopro",
  93.                             "noss",
  94.                             "sst",
  95.                             "ss1",
  96.                             "ss2",
  97.                             "ss3",
  98.                             nil
  99.                         };
  100. static    void            (*SoundUserHook)(void);
  101.         soundnames        SoundNumber,DigiNumber;
  102.         word            SoundPriority,DigiPriority;
  103.         int                LeftPosition,RightPosition;
  104.         void interrupt    (*t0OldService)(void);
  105.         long            LocalTime;
  106.         word            TimerRate;
  107.  
  108.         word            NumDigi,DigiLeft,DigiPage;
  109.         word            _seg *DigiList;
  110.         word            DigiLastStart,DigiLastEnd;
  111.         boolean            DigiPlaying;
  112. static    boolean            DigiMissed,DigiLastSegment;
  113. static    memptr            DigiNextAddr;
  114. static    word            DigiNextLen;
  115.  
  116. //    SoundBlaster variables
  117. static    boolean                    sbNoCheck,sbNoProCheck;
  118. static    volatile boolean        sbSamplePlaying;
  119. static    byte                    sbOldIntMask = -1;
  120. static    volatile byte            huge *sbNextSegPtr;
  121. static    byte                    sbDMA = 1,
  122.                                 sbDMAa1 = 0x83,sbDMAa2 = 2,sbDMAa3 = 3,
  123.                                 sba1Vals[] = {0x87,0x83,0,0x82},
  124.                                 sba2Vals[] = {0,2,0,6},
  125.                                 sba3Vals[] = {1,3,0,7};
  126. static    int                        sbLocation = -1,sbInterrupt = 7,sbIntVec = 0xf,
  127.                                 sbIntVectors[] = {-1,-1,0xa,0xb,-1,0xd,-1,0xf,-1,-1,-1};
  128. static    volatile longword        sbNextSegLen;
  129. static    volatile SampledSound    huge *sbSamples;
  130. static    void interrupt            (*sbOldIntHand)(void);
  131. static    byte                    sbpOldFMMix,sbpOldVOCMix;
  132.  
  133. //    SoundSource variables
  134.         boolean                ssNoCheck;
  135.         boolean                ssActive;
  136.         word                ssControl,ssStatus,ssData;
  137.         byte                ssOn,ssOff;
  138.         volatile byte        far *ssSample;
  139.         volatile longword    ssLengthLeft;
  140.  
  141. //    PC Sound variables
  142.         volatile byte    pcLastSample,far *pcSound;
  143.         longword        pcLengthLeft;
  144.         word            pcSoundLookup[255];
  145.  
  146. //    AdLib variables
  147.         boolean            alNoCheck;
  148.         byte            far *alSound;
  149.         word            alBlock;
  150.         longword        alLengthLeft;
  151.         longword        alTimeCount;
  152.         Instrument        alZeroInst;
  153.  
  154. // This table maps channel numbers to carrier and modulator op cells
  155. static    byte            carriers[9] =  { 3, 4, 5,11,12,13,19,20,21},
  156.                         modifiers[9] = { 0, 1, 2, 8, 9,10,16,17,18},
  157. // This table maps percussive voice numbers to op cells
  158.                         pcarriers[5] = {19,0xff,0xff,0xff,0xff},
  159.                         pmodifiers[5] = {16,17,18,20,21};
  160.  
  161. //    Sequencer variables
  162.         boolean            sqActive;
  163. static    word            alFXReg;
  164. static    ActiveTrack        *tracks[sqMaxTracks],
  165.                         mytracks[sqMaxTracks];
  166. static    word            sqMode,sqFadeStep;
  167.         word            far *sqHack,far *sqHackPtr,sqHackLen,sqHackSeqLen;
  168.         long            sqHackTime;
  169.  
  170. //    Internal routines
  171.         void            SDL_DigitizedDone(void);
  172.  
  173. ///////////////////////////////////////////////////////////////////////////
  174. //
  175. //    SDL_SetTimer0() - Sets system timer 0 to the specified speed
  176. //
  177. ///////////////////////////////////////////////////////////////////////////
  178. #pragma    argsused
  179. static void
  180. SDL_SetTimer0(word speed)
  181. {
  182. #ifndef TPROF    // If using Borland's profiling, don't screw with the timer
  183. asm    pushf
  184. asm    cli
  185.  
  186.     outportb(0x43,0x36);                // Change timer 0
  187.     outportb(0x40,speed);
  188.     outportb(0x40,speed >> 8);
  189.     // Kludge to handle special case for digitized PC sounds
  190.     if (TimerDivisor == (1192030 / (TickBase * 100)))
  191.         TimerDivisor = (1192030 / (TickBase * 10));
  192.     else
  193.         TimerDivisor = speed;
  194.  
  195. asm    popf
  196. #else
  197.     TimerDivisor = 0x10000;
  198. #endif
  199. }
  200.  
  201. ///////////////////////////////////////////////////////////////////////////
  202. //
  203. //    SDL_SetIntsPerSec() - Uses SDL_SetTimer0() to set the number of
  204. //        interrupts generated by system timer 0 per second
  205. //
  206. ///////////////////////////////////////////////////////////////////////////
  207. static void
  208. SDL_SetIntsPerSec(word ints)
  209. {
  210.     TimerRate = ints;
  211.     SDL_SetTimer0(1192030 / ints);
  212. }
  213.  
  214. static void
  215. SDL_SetTimerSpeed(void)
  216. {
  217.     word    rate;
  218.     void interrupt    (*isr)(void);
  219.  
  220.     if ((DigiMode == sds_PC) && DigiPlaying)
  221.     {
  222.         rate = TickBase * 100;
  223.         isr = SDL_t0ExtremeAsmService;
  224.     }
  225.     else if
  226.     (
  227.         (MusicMode == smm_AdLib)
  228.     ||    ((DigiMode == sds_SoundSource) && DigiPlaying)
  229.     )
  230.     {
  231.         rate = TickBase * 10;
  232.         isr = SDL_t0FastAsmService;
  233.     }
  234.     else
  235.     {
  236.         rate = TickBase * 2;
  237.         isr = SDL_t0SlowAsmService;
  238.     }
  239.  
  240.     if (rate != TimerRate)
  241.     {
  242.         setvect(8,isr);
  243.         SDL_SetIntsPerSec(rate);
  244.         TimerRate = rate;
  245.     }
  246. }
  247.  
  248. //
  249. //    SoundBlaster code
  250. //
  251.  
  252. ///////////////////////////////////////////////////////////////////////////
  253. //
  254. //    SDL_SBStopSample() - Stops any active sampled sound and causes DMA
  255. //        requests from the SoundBlaster to cease
  256. //
  257. ///////////////////////////////////////////////////////////////////////////
  258. #ifdef    _MUSE_
  259. void
  260. #else
  261. static void
  262. #endif
  263. SDL_SBStopSample(void)
  264. {
  265.     byte    is;
  266.  
  267. asm    pushf
  268. asm    cli
  269.  
  270.     if (sbSamplePlaying)
  271.     {
  272.         sbSamplePlaying = false;
  273.  
  274.         sbWriteDelay();
  275.         sbOut(sbWriteCmd,0xd0);    // Turn off DSP DMA
  276.  
  277.         is = inportb(0x21);    // Restore interrupt mask bit
  278.         if (sbOldIntMask & (1 << sbInterrupt))
  279.             is |= (1 << sbInterrupt);
  280.         else
  281.             is &= ~(1 << sbInterrupt);
  282.         outportb(0x21,is);
  283.     }
  284.  
  285. asm    popf
  286. }
  287.  
  288. ///////////////////////////////////////////////////////////////////////////
  289. //
  290. //    SDL_SBPlaySeg() - Plays a chunk of sampled sound on the SoundBlaster
  291. //    Insures that the chunk doesn't cross a bank boundary, programs the DMA
  292. //     controller, and tells the SB to start doing DMA requests for DAC
  293. //
  294. ///////////////////////////////////////////////////////////////////////////
  295. static longword
  296. SDL_SBPlaySeg(volatile byte huge *data,longword length)
  297. {
  298.     unsigned        datapage;
  299.     longword        dataofs,uselen;
  300.  
  301.     uselen = length;
  302.     datapage = FP_SEG(data) >> 12;
  303.     dataofs = ((FP_SEG(data) & 0xfff) << 4) + FP_OFF(data);
  304.     if (dataofs >= 0x10000)
  305.     {
  306.         datapage++;
  307.         dataofs -= 0x10000;
  308.     }
  309.  
  310.     if (dataofs + uselen > 0x10000)
  311.         uselen = 0x10000 - dataofs;
  312.  
  313.     uselen--;
  314.  
  315.     // Program the DMA controller
  316. asm    pushf
  317. asm    cli
  318.     outportb(0x0a,sbDMA | 4);                    // Mask off DMA on channel sbDMA
  319.     outportb(0x0c,0);                            // Clear byte ptr flip-flop to lower byte
  320.     outportb(0x0b,0x49);                        // Set transfer mode for D/A conv
  321.     outportb(sbDMAa2,(byte)dataofs);            // Give LSB of address
  322.     outportb(sbDMAa2,(byte)(dataofs >> 8));        // Give MSB of address
  323.     outportb(sbDMAa1,(byte)datapage);            // Give page of address
  324.     outportb(sbDMAa3,(byte)uselen);                // Give LSB of length
  325.     outportb(sbDMAa3,(byte)(uselen >> 8));        // Give MSB of length
  326.     outportb(0x0a,sbDMA);                        // Re-enable DMA on channel sbDMA
  327.  
  328.     // Start playing the thing
  329.     sbWriteDelay();
  330.     sbOut(sbWriteCmd,0x14);
  331.     sbWriteDelay();
  332.     sbOut(sbWriteData,(byte)uselen);
  333.     sbWriteDelay();
  334.     sbOut(sbWriteData,(byte)(uselen >> 8));
  335. asm    popf
  336.  
  337.     return(uselen + 1);
  338. }
  339.  
  340. ///////////////////////////////////////////////////////////////////////////
  341. //
  342. //    SDL_SBService() - Services the SoundBlaster DMA interrupt
  343. //
  344. ///////////////////////////////////////////////////////////////////////////
  345. static void interrupt
  346. SDL_SBService(void)
  347. {
  348.     longword    used;
  349.  
  350.     sbIn(sbDataAvail);    // Ack interrupt to SB
  351.  
  352.     if (sbNextSegPtr)
  353.     {
  354.         used = SDL_SBPlaySeg(sbNextSegPtr,sbNextSegLen);
  355.         if (sbNextSegLen <= used)
  356.             sbNextSegPtr = nil;
  357.         else
  358.         {
  359.             sbNextSegPtr += used;
  360.             sbNextSegLen -= used;
  361.         }
  362.     }
  363.     else
  364.     {
  365.         SDL_SBStopSample();
  366.         SDL_DigitizedDone();
  367.     }
  368.  
  369.     outportb(0x20,0x20);    // Ack interrupt
  370. }
  371.  
  372. ///////////////////////////////////////////////////////////////////////////
  373. //
  374. //    SDL_SBPlaySample() - Plays a sampled sound on the SoundBlaster. Sets up
  375. //        DMA to play the sound
  376. //
  377. ///////////////////////////////////////////////////////////////////////////
  378. #ifdef    _MUSE_
  379. void
  380. #else
  381. static void
  382. #endif
  383. SDL_SBPlaySample(byte huge *data,longword len)
  384. {
  385.     longword    used;
  386.  
  387.     SDL_SBStopSample();
  388.  
  389. asm    pushf
  390. asm    cli
  391.  
  392.     used = SDL_SBPlaySeg(data,len);
  393.     if (len <= used)
  394.         sbNextSegPtr = nil;
  395.     else
  396.     {
  397.         sbNextSegPtr = data + used;
  398.         sbNextSegLen = len - used;
  399.     }
  400.  
  401.     // Save old interrupt status and unmask ours
  402.     sbOldIntMask = inportb(0x21);
  403.     outportb(0x21,sbOldIntMask & ~(1 << sbInterrupt));
  404.  
  405.     sbWriteDelay();
  406.     sbOut(sbWriteCmd,0xd4);                        // Make sure DSP DMA is enabled
  407.  
  408.     sbSamplePlaying = true;
  409.  
  410. asm    popf
  411. }
  412.  
  413. ///////////////////////////////////////////////////////////////////////////
  414. //
  415. //    SDL_PositionSBP() - Sets the attenuation levels for the left and right
  416. //        channels by using the mixer chip on the SB Pro. This hits a hole in
  417. //        the address map for normal SBs.
  418. //
  419. ///////////////////////////////////////////////////////////////////////////
  420. static void
  421. SDL_PositionSBP(int leftpos,int rightpos)
  422. {
  423.     byte    v;
  424.  
  425.     if (!SBProPresent)
  426.         return;
  427.  
  428.     leftpos = 15 - leftpos;
  429.     rightpos = 15 - rightpos;
  430.     v = ((leftpos & 0x0f) << 4) | (rightpos & 0x0f);
  431.  
  432. asm    pushf
  433. asm    cli
  434.  
  435.     sbOut(sbpMixerAddr,sbpmVoiceVol);
  436.     sbOut(sbpMixerData,v);
  437.  
  438. asm    popf
  439. }
  440.  
  441. ///////////////////////////////////////////////////////////////////////////
  442. //
  443. //    SDL_CheckSB() - Checks to see if a SoundBlaster resides at a
  444. //        particular I/O location
  445. //
  446. ///////////////////////////////////////////////////////////////////////////
  447. static boolean
  448. SDL_CheckSB(int port)
  449. {
  450.     int    i;
  451.  
  452.     sbLocation = port << 4;        // Initialize stuff for later use
  453.  
  454.     sbOut(sbReset,true);        // Reset the SoundBlaster DSP
  455. asm    mov    dx,0x388                // Wait >4usec
  456. asm    in    al, dx
  457. asm    in    al, dx
  458. asm    in    al, dx
  459. asm    in    al, dx
  460. asm    in    al, dx
  461. asm    in    al, dx
  462. asm    in    al, dx
  463. asm    in    al, dx
  464. asm    in    al, dx
  465.  
  466.     sbOut(sbReset,false);        // Turn off sb DSP reset
  467. asm    mov    dx,0x388                // Wait >100usec
  468. asm    mov    cx,100
  469. usecloop:
  470. asm    in    al,dx
  471. asm    loop usecloop
  472.  
  473.     for (i = 0;i < 100;i++)
  474.     {
  475.         if (sbIn(sbDataAvail) & 0x80)        // If data is available...
  476.         {
  477.             if (sbIn(sbReadData) == 0xaa)    // If it matches correct value
  478.                 return(true);
  479.             else
  480.             {
  481.                 sbLocation = -1;            // Otherwise not a SoundBlaster
  482.                 return(false);
  483.             }
  484.         }
  485.     }
  486.     sbLocation = -1;                        // Retry count exceeded - fail
  487.     return(false);
  488. }
  489.  
  490. ///////////////////////////////////////////////////////////////////////////
  491. //
  492. //    Checks to see if a SoundBlaster is in the system. If the port passed is
  493. //        -1, then it scans through all possible I/O locations. If the port
  494. //        passed is 0, then it uses the default (2). If the port is >0, then
  495. //        it just passes it directly to SDL_CheckSB()
  496. //
  497. ///////////////////////////////////////////////////////////////////////////
  498. static boolean
  499. SDL_DetectSoundBlaster(int port)
  500. {
  501.     int    i;
  502.  
  503.     if (port == 0)                    // If user specifies default, use 2
  504.         port = 2;
  505.     if (port == -1)
  506.     {
  507.         if (SDL_CheckSB(2))            // Check default before scanning
  508.             return(true);
  509.  
  510.         if (SDL_CheckSB(4))            // Check other SB Pro location before scan
  511.             return(true);
  512.  
  513.         for (i = 1;i <= 6;i++)        // Scan through possible SB locations
  514.         {
  515.             if ((i == 2) || (i == 4))
  516.                 continue;
  517.  
  518.             if (SDL_CheckSB(i))        // If found at this address,
  519.                 return(true);        //    return success
  520.         }
  521.         return(false);                // All addresses failed, return failure
  522.     }
  523.     else
  524.         return(SDL_CheckSB(port));    // User specified address or default
  525. }
  526.  
  527. ///////////////////////////////////////////////////////////////////////////
  528. //
  529. //    SDL_SBSetDMA() - Sets the DMA channel to be used by the SoundBlaster
  530. //        code. Sets up sbDMA, and sbDMAa1-sbDMAa3 (used by SDL_SBPlaySeg()).
  531. //
  532. ///////////////////////////////////////////////////////////////////////////
  533. void
  534. SDL_SBSetDMA(byte channel)
  535. {
  536.     if (channel > 3)
  537.         Quit("SDL_SBSetDMA() - invalid SoundBlaster DMA channel");
  538.  
  539.     sbDMA = channel;
  540.     sbDMAa1 = sba1Vals[channel];
  541.     sbDMAa2 = sba2Vals[channel];
  542.     sbDMAa3 = sba3Vals[channel];
  543. }
  544.  
  545. ///////////////////////////////////////////////////////////////////////////
  546. //
  547. //    SDL_StartSB() - Turns on the SoundBlaster
  548. //
  549. ///////////////////////////////////////////////////////////////////////////
  550. static void
  551. SDL_StartSB(void)
  552. {
  553.     byte    timevalue,test;
  554.  
  555.     sbIntVec = sbIntVectors[sbInterrupt];
  556.     if (sbIntVec < 0)
  557.         Quit("SDL_StartSB: Illegal or unsupported interrupt number for SoundBlaster");
  558.  
  559.     sbOldIntHand = getvect(sbIntVec);    // Get old interrupt handler
  560.     setvect(sbIntVec,SDL_SBService);    // Set mine
  561.  
  562.     sbWriteDelay();
  563.     sbOut(sbWriteCmd,0xd1);                // Turn on DSP speaker
  564.  
  565.     // Set the SoundBlaster DAC time constant for 7KHz
  566.     timevalue = 256 - (1000000 / 7000);
  567.     sbWriteDelay();
  568.     sbOut(sbWriteCmd,0x40);
  569.     sbWriteDelay();
  570.     sbOut(sbWriteData,timevalue);
  571.  
  572.     SBProPresent = false;
  573.     if (sbNoProCheck)
  574.         return;
  575.  
  576.     // Check to see if this is a SB Pro
  577.     sbOut(sbpMixerAddr,sbpmFMVol);
  578.     sbpOldFMMix = sbIn(sbpMixerData);
  579.     sbOut(sbpMixerData,0xbb);
  580.     test = sbIn(sbpMixerData);
  581.     if (test == 0xbb)
  582.     {
  583.         // Boost FM output levels to be equivilent with digitized output
  584.         sbOut(sbpMixerData,0xff);
  585.         test = sbIn(sbpMixerData);
  586.         if (test == 0xff)
  587.         {
  588.             SBProPresent = true;
  589.  
  590.             // Save old Voice output levels (SB Pro)
  591.             sbOut(sbpMixerAddr,sbpmVoiceVol);
  592.             sbpOldVOCMix = sbIn(sbpMixerData);
  593.  
  594.             // Turn SB Pro stereo DAC off
  595.             sbOut(sbpMixerAddr,sbpmControl);
  596.             sbOut(sbpMixerData,0);                // 0=off,2=on
  597.         }
  598.     }
  599. }
  600.  
  601. ///////////////////////////////////////////////////////////////////////////
  602. //
  603. //    SDL_ShutSB() - Turns off the SoundBlaster
  604. //
  605. ///////////////////////////////////////////////////////////////////////////
  606. static void
  607. SDL_ShutSB(void)
  608. {
  609.     SDL_SBStopSample();
  610.  
  611.     if (SBProPresent)
  612.     {
  613.         // Restore FM output levels (SB Pro)
  614.         sbOut(sbpMixerAddr,sbpmFMVol);
  615.         sbOut(sbpMixerData,sbpOldFMMix);
  616.  
  617.         // Restore Voice output levels (SB Pro)
  618.         sbOut(sbpMixerAddr,sbpmVoiceVol);
  619.         sbOut(sbpMixerData,sbpOldVOCMix);
  620.     }
  621.  
  622.     setvect(sbIntVec,sbOldIntHand);        // Set vector back
  623. }
  624.  
  625. //    Sound Source Code
  626.  
  627. ///////////////////////////////////////////////////////////////////////////
  628. //
  629. //    SDL_SSStopSample() - Stops a sample playing on the Sound Source
  630. //
  631. ///////////////////////////////////////////////////////////////////////////
  632. #ifdef    _MUSE_
  633. void
  634. #else
  635. static void
  636. #endif
  637. SDL_SSStopSample(void)
  638. {
  639. asm    pushf
  640. asm    cli
  641.  
  642.     (long)ssSample = 0;
  643.  
  644. asm    popf
  645. }
  646.  
  647. ///////////////////////////////////////////////////////////////////////////
  648. //
  649. //    SDL_SSService() - Handles playing the next sample on the Sound Source
  650. //
  651. ///////////////////////////////////////////////////////////////////////////
  652. static void
  653. SDL_SSService(void)
  654. {
  655.     boolean    gotit;
  656.     byte    v;
  657.  
  658.     while (ssSample)
  659.     {
  660.     asm    mov        dx,[ssStatus]    // Check to see if FIFO is currently empty
  661.     asm    in        al,dx
  662.     asm    test    al,0x40
  663.     asm    jnz        done            // Nope - don't push any more data out
  664.  
  665.         v = *ssSample++;
  666.         if (!(--ssLengthLeft))
  667.         {
  668.             (long)ssSample = 0;
  669.             SDL_DigitizedDone();
  670.         }
  671.  
  672.     asm    mov        dx,[ssData]        // Pump the value out
  673.     asm    mov        al,[v]
  674.     asm    out        dx,al
  675.  
  676.     asm    mov        dx,[ssControl]    // Pulse printer select
  677.     asm    mov        al,[ssOff]
  678.     asm    out        dx,al
  679.     asm    push    ax
  680.     asm    pop        ax
  681.     asm    mov        al,[ssOn]
  682.     asm    out        dx,al
  683.  
  684.     asm    push    ax                // Delay a short while
  685.     asm    pop        ax
  686.     asm    push    ax
  687.     asm    pop        ax
  688.     }
  689. done:;
  690. }
  691.  
  692. ///////////////////////////////////////////////////////////////////////////
  693. //
  694. //    SDL_SSPlaySample() - Plays the specified sample on the Sound Source
  695. //
  696. ///////////////////////////////////////////////////////////////////////////
  697. #ifdef    _MUSE_
  698. void
  699. #else
  700. static void
  701. #endif
  702. SDL_SSPlaySample(byte huge *data,longword len)
  703. {
  704. asm    pushf
  705. asm    cli
  706.  
  707.     ssLengthLeft = len;
  708.     ssSample = (volatile byte far *)data;
  709.  
  710. asm    popf
  711. }
  712.  
  713. ///////////////////////////////////////////////////////////////////////////
  714. //
  715. //    SDL_StartSS() - Sets up for and turns on the Sound Source
  716. //
  717. ///////////////////////////////////////////////////////////////////////////
  718. static void
  719. SDL_StartSS(void)
  720. {
  721.     if (ssPort == 3)
  722.         ssControl = 0x27a;    // If using LPT3
  723.     else if (ssPort == 2)
  724.         ssControl = 0x37a;    // If using LPT2
  725.     else
  726.         ssControl = 0x3be;    // If using LPT1
  727.     ssStatus = ssControl - 1;
  728.     ssData = ssStatus - 1;
  729.  
  730.     ssOn = 0x04;
  731.     if (ssIsTandy)
  732.         ssOff = 0x0e;                // Tandy wierdness
  733.     else
  734.         ssOff = 0x0c;                // For normal machines
  735.  
  736.     outportb(ssControl,ssOn);        // Enable SS
  737. }
  738.  
  739. ///////////////////////////////////////////////////////////////////////////
  740. //
  741. //    SDL_ShutSS() - Turns off the Sound Source
  742. //
  743. ///////////////////////////////////////////////////////////////////////////
  744. static void
  745. SDL_ShutSS(void)
  746. {
  747.     outportb(ssControl,ssOff);
  748. }
  749.  
  750. ///////////////////////////////////////////////////////////////////////////
  751. //
  752. //    SDL_CheckSS() - Checks to see if a Sound Source is present at the
  753. //        location specified by the sound source variables
  754. //
  755. ///////////////////////////////////////////////////////////////////////////
  756. static boolean
  757. SDL_CheckSS(void)
  758. {
  759.     boolean        present = false;
  760.     longword    lasttime;
  761.  
  762.     // Turn the Sound Source on and wait awhile (4 ticks)
  763.     SDL_StartSS();
  764.  
  765.     lasttime = TimeCount;
  766.     while (TimeCount < lasttime + 4)
  767.         ;
  768.  
  769. asm    mov        dx,[ssStatus]    // Check to see if FIFO is currently empty
  770. asm    in        al,dx
  771. asm    test    al,0x40
  772. asm    jnz        checkdone        // Nope - Sound Source not here
  773.  
  774. asm    mov        cx,32            // Force FIFO overflow (FIFO is 16 bytes)
  775. outloop:
  776. asm    mov        dx,[ssData]        // Pump a neutral value out
  777. asm    mov        al,0x80
  778. asm    out        dx,al
  779.  
  780. asm    mov        dx,[ssControl]    // Pulse printer select
  781. asm    mov        al,[ssOff]
  782. asm    out        dx,al
  783. asm    push    ax
  784. asm    pop        ax
  785. asm    mov        al,[ssOn]
  786. asm    out        dx,al
  787.  
  788. asm    push    ax                // Delay a short while before we do this again
  789. asm    pop        ax
  790. asm    push    ax
  791. asm    pop        ax
  792.  
  793. asm    loop    outloop
  794.  
  795. asm    mov        dx,[ssStatus]    // Is FIFO overflowed now?
  796. asm    in        al,dx
  797. asm    test    al,0x40
  798. asm    jz        checkdone        // Nope, still not - Sound Source not here
  799.  
  800.     present = true;            // Yes - it's here!
  801.  
  802. checkdone:
  803.     SDL_ShutSS();
  804.     return(present);
  805. }
  806.  
  807. static boolean
  808. SDL_DetectSoundSource(void)
  809. {
  810.     for (ssPort = 1;ssPort <= 3;ssPort++)
  811.         if (SDL_CheckSS())
  812.             return(true);
  813.     return(false);
  814. }
  815.  
  816. //
  817. //    PC Sound code
  818. //
  819.  
  820. ///////////////////////////////////////////////////////////////////////////
  821. //
  822. //    SDL_PCPlaySample() - Plays the specified sample on the PC speaker
  823. //
  824. ///////////////////////////////////////////////////////////////////////////
  825. #ifdef    _MUSE_
  826. void
  827. #else
  828. static void
  829. #endif
  830. SDL_PCPlaySample(byte huge *data,longword len)
  831. {
  832. asm    pushf
  833. asm    cli
  834.  
  835.     SDL_IndicatePC(true);
  836.  
  837.     pcLengthLeft = len;
  838.     pcSound = (volatile byte far *)data;
  839.  
  840. asm    popf
  841. }
  842.  
  843. ///////////////////////////////////////////////////////////////////////////
  844. //
  845. //    SDL_PCStopSample() - Stops a sample playing on the PC speaker
  846. //
  847. ///////////////////////////////////////////////////////////////////////////
  848. #ifdef    _MUSE_
  849. void
  850. #else
  851. static void
  852. #endif
  853. SDL_PCStopSample(void)
  854. {
  855. asm    pushf
  856. asm    cli
  857.  
  858.     (long)pcSound = 0;
  859.  
  860.     SDL_IndicatePC(false);
  861.  
  862. asm    in    al,0x61              // Turn the speaker off
  863. asm    and    al,0xfd            // ~2
  864. asm    out    0x61,al
  865.  
  866. asm    popf
  867. }
  868.  
  869. ///////////////////////////////////////////////////////////////////////////
  870. //
  871. //    SDL_PCPlaySound() - Plays the specified sound on the PC speaker
  872. //
  873. ///////////////////////////////////////////////////////////////////////////
  874. #ifdef    _MUSE_
  875. void
  876. #else
  877. static void
  878. #endif
  879. SDL_PCPlaySound(PCSound far *sound)
  880. {
  881. asm    pushf
  882. asm    cli
  883.  
  884.     pcLastSample = -1;
  885.     pcLengthLeft = sound->common.length;
  886.     pcSound = sound->data;
  887.  
  888. asm    popf
  889. }
  890.  
  891. ///////////////////////////////////////////////////////////////////////////
  892. //
  893. //    SDL_PCStopSound() - Stops the current sound playing on the PC Speaker
  894. //
  895. ///////////////////////////////////////////////////////////////////////////
  896. #ifdef    _MUSE_
  897. void
  898. #else
  899. static void
  900. #endif
  901. SDL_PCStopSound(void)
  902. {
  903. asm    pushf
  904. asm    cli
  905.  
  906.     (long)pcSound = 0;
  907.  
  908. asm    in    al,0x61              // Turn the speaker off
  909. asm    and    al,0xfd            // ~2
  910. asm    out    0x61,al
  911.  
  912. asm    popf
  913. }
  914.  
  915. #if 0
  916. ///////////////////////////////////////////////////////////////////////////
  917. //
  918. //    SDL_PCService() - Handles playing the next sample in a PC sound
  919. //
  920. ///////////////////////////////////////////////////////////////////////////
  921. static void
  922. SDL_PCService(void)
  923. {
  924.     byte    s;
  925.     word    t;
  926.  
  927.     if (pcSound)
  928.     {
  929.         s = *pcSound++;
  930.         if (s != pcLastSample)
  931.         {
  932.         asm    pushf
  933.         asm    cli
  934.  
  935.             pcLastSample = s;
  936.             if (s)                    // We have a frequency!
  937.             {
  938.                 t = pcSoundLookup[s];
  939.             asm    mov    bx,[t]
  940.  
  941.             asm    mov    al,0xb6            // Write to channel 2 (speaker) timer
  942.             asm    out    43h,al
  943.             asm    mov    al,bl
  944.             asm    out    42h,al            // Low byte
  945.             asm    mov    al,bh
  946.             asm    out    42h,al            // High byte
  947.  
  948.             asm    in    al,0x61            // Turn the speaker & gate on
  949.             asm    or    al,3
  950.             asm    out    0x61,al
  951.             }
  952.             else                    // Time for some silence
  953.             {
  954.             asm    in    al,0x61              // Turn the speaker & gate off
  955.             asm    and    al,0xfc            // ~3
  956.             asm    out    0x61,al
  957.             }
  958.  
  959.         asm    popf
  960.         }
  961.  
  962.         if (!(--pcLengthLeft))
  963.         {
  964.             SDL_PCStopSound();
  965.             SDL_SoundFinished();
  966.         }
  967.     }
  968. }
  969. #endif
  970.  
  971. ///////////////////////////////////////////////////////////////////////////
  972. //
  973. //    SDL_ShutPC() - Turns off the pc speaker
  974. //
  975. ///////////////////////////////////////////////////////////////////////////
  976. static void
  977. SDL_ShutPC(void)
  978. {
  979. asm    pushf
  980. asm    cli
  981.  
  982.     pcSound = 0;
  983.  
  984. asm    in    al,0x61              // Turn the speaker & gate off
  985. asm    and    al,0xfc            // ~3
  986. asm    out    0x61,al
  987.  
  988. asm    popf
  989. }
  990.  
  991. //
  992. //    Stuff for digitized sounds
  993. //
  994. memptr
  995. SDL_LoadDigiSegment(word page)
  996. {
  997.     memptr    addr;
  998.  
  999. #if 0    // for debugging
  1000. asm    mov    dx,STATUS_REGISTER_1
  1001. asm    in    al,dx
  1002. asm    mov    dx,ATR_INDEX
  1003. asm    mov    al,ATR_OVERSCAN
  1004. asm    out    dx,al
  1005. asm    mov    al,10    // bright green
  1006. asm    out    dx,al
  1007. #endif
  1008.  
  1009.     addr = PM_GetSoundPage(page);
  1010.     PM_SetPageLock(PMSoundStart + page,pml_Locked);
  1011.  
  1012. #if 0    // for debugging
  1013. asm    mov    dx,STATUS_REGISTER_1
  1014. asm    in    al,dx
  1015. asm    mov    dx,ATR_INDEX
  1016. asm    mov    al,ATR_OVERSCAN
  1017. asm    out    dx,al
  1018. asm    mov    al,3    // blue
  1019. asm    out    dx,al
  1020. asm    mov    al,0x20    // normal
  1021. asm    out    dx,al
  1022. #endif
  1023.  
  1024.     return(addr);
  1025. }
  1026.  
  1027. void
  1028. SDL_PlayDigiSegment(memptr addr,word len)
  1029. {
  1030.     switch (DigiMode)
  1031.     {
  1032.     case sds_PC:
  1033.         SDL_PCPlaySample(addr,len);
  1034.         break;
  1035.     case sds_SoundSource:
  1036.         SDL_SSPlaySample(addr,len);
  1037.         break;
  1038.     case sds_SoundBlaster:
  1039.         SDL_SBPlaySample(addr,len);
  1040.         break;
  1041.     }
  1042. }
  1043.  
  1044. void
  1045. SD_StopDigitized(void)
  1046. {
  1047.     int    i;
  1048.  
  1049. asm    pushf
  1050. asm    cli
  1051.  
  1052.     DigiLeft = 0;
  1053.     DigiNextAddr = nil;
  1054.     DigiNextLen = 0;
  1055.     DigiMissed = false;
  1056.     DigiPlaying = false;
  1057.     DigiNumber = DigiPriority = 0;
  1058.     SoundPositioned = false;
  1059.     if ((DigiMode == sds_PC) && (SoundMode == sdm_PC))
  1060.         SDL_SoundFinished();
  1061.  
  1062.     switch (DigiMode)
  1063.     {
  1064.     case sds_PC:
  1065.         SDL_PCStopSample();
  1066.         break;
  1067.     case sds_SoundSource:
  1068.         SDL_SSStopSample();
  1069.         break;
  1070.     case sds_SoundBlaster:
  1071.         SDL_SBStopSample();
  1072.         break;
  1073.     }
  1074.  
  1075. asm    popf
  1076.  
  1077.     for (i = DigiLastStart;i < DigiLastEnd;i++)
  1078.         PM_SetPageLock(i + PMSoundStart,pml_Unlocked);
  1079.     DigiLastStart = 1;
  1080.     DigiLastEnd = 0;
  1081. }
  1082.  
  1083. void
  1084. SD_Poll(void)
  1085. {
  1086.     if (DigiLeft && !DigiNextAddr)
  1087.     {
  1088.         DigiNextLen = (DigiLeft >= PMPageSize)? PMPageSize : (DigiLeft % PMPageSize);
  1089.         DigiLeft -= DigiNextLen;
  1090.         if (!DigiLeft)
  1091.             DigiLastSegment = true;
  1092.         DigiNextAddr = SDL_LoadDigiSegment(DigiPage++);
  1093.     }
  1094.     if (DigiMissed && DigiNextAddr)
  1095.     {
  1096.         SDL_PlayDigiSegment(DigiNextAddr,DigiNextLen);
  1097.         DigiNextAddr = nil;
  1098.         DigiMissed = false;
  1099.         if (DigiLastSegment)
  1100.         {
  1101.             DigiPlaying = false;
  1102.             DigiLastSegment = false;
  1103.         }
  1104.     }
  1105.     SDL_SetTimerSpeed();
  1106. }
  1107.  
  1108. void
  1109. SD_SetPosition(int leftpos,int rightpos)
  1110. {
  1111.     if
  1112.     (
  1113.         (leftpos < 0)
  1114.     ||    (leftpos > 15)
  1115.     ||    (rightpos < 0)
  1116.     ||    (rightpos > 15)
  1117.     ||    ((leftpos == 15) && (rightpos == 15))
  1118.     )
  1119.         Quit("SD_SetPosition: Illegal position");
  1120.  
  1121.     switch (DigiMode)
  1122.     {
  1123.     case sds_SoundBlaster:
  1124.         SDL_PositionSBP(leftpos,rightpos);
  1125.         break;
  1126.     }
  1127. }
  1128.  
  1129. void
  1130. SD_PlayDigitized(word which,int leftpos,int rightpos)
  1131. {
  1132.     word    len;
  1133.     memptr    addr;
  1134.  
  1135.     if (!DigiMode)
  1136.         return;
  1137.  
  1138.     SD_StopDigitized();
  1139.     if (which >= NumDigi)
  1140.         Quit("SD_PlayDigitized: bad sound number");
  1141.  
  1142.     SD_SetPosition(leftpos,rightpos);
  1143.  
  1144.     DigiPage = DigiList[(which * 2) + 0];
  1145.     DigiLeft = DigiList[(which * 2) + 1];
  1146.  
  1147.     DigiLastStart = DigiPage;
  1148.     DigiLastEnd = DigiPage + ((DigiLeft + (PMPageSize - 1)) / PMPageSize);
  1149.  
  1150.     len = (DigiLeft >= PMPageSize)? PMPageSize : (DigiLeft % PMPageSize);
  1151.     addr = SDL_LoadDigiSegment(DigiPage++);
  1152.  
  1153.     DigiPlaying = true;
  1154.     DigiLastSegment = false;
  1155.  
  1156.     SDL_PlayDigiSegment(addr,len);
  1157.     DigiLeft -= len;
  1158.     if (!DigiLeft)
  1159.         DigiLastSegment = true;
  1160.  
  1161.     SD_Poll();
  1162. }
  1163.  
  1164. void
  1165. SDL_DigitizedDone(void)
  1166. {
  1167.     if (DigiNextAddr)
  1168.     {
  1169.         SDL_PlayDigiSegment(DigiNextAddr,DigiNextLen);
  1170.         DigiNextAddr = nil;
  1171.         DigiMissed = false;
  1172.     }
  1173.     else
  1174.     {
  1175.         if (DigiLastSegment)
  1176.         {
  1177.             DigiPlaying = false;
  1178.             DigiLastSegment = false;
  1179.             if ((DigiMode == sds_PC) && (SoundMode == sdm_PC))
  1180.             {
  1181.                 SDL_SoundFinished();
  1182.             }
  1183.             else
  1184.                 DigiNumber = DigiPriority = 0;
  1185.             SoundPositioned = false;
  1186.         }
  1187.         else
  1188.             DigiMissed = true;
  1189.     }
  1190. }
  1191.  
  1192. void
  1193. SD_SetDigiDevice(SDSMode mode)
  1194. {
  1195.     boolean    devicenotpresent;
  1196.  
  1197.     if (mode == DigiMode)
  1198.         return;
  1199.  
  1200.     SD_StopDigitized();
  1201.  
  1202.     devicenotpresent = false;
  1203.     switch (mode)
  1204.     {
  1205.     case sds_SoundBlaster:
  1206.         if (!SoundBlasterPresent)
  1207.         {
  1208.             if (SoundSourcePresent)
  1209.                 mode = sds_SoundSource;
  1210.             else
  1211.                 devicenotpresent = true;
  1212.         }
  1213.         break;
  1214.     case sds_SoundSource:
  1215.         if (!SoundSourcePresent)
  1216.             devicenotpresent = true;
  1217.         break;
  1218.     }
  1219.  
  1220.     if (!devicenotpresent)
  1221.     {
  1222.         if (DigiMode == sds_SoundSource)
  1223.             SDL_ShutSS();
  1224.  
  1225.         DigiMode = mode;
  1226.  
  1227.         if (mode == sds_SoundSource)
  1228.             SDL_StartSS();
  1229.  
  1230.         SDL_SetTimerSpeed();
  1231.     }
  1232. }
  1233.  
  1234. void
  1235. SDL_SetupDigi(void)
  1236. {
  1237.     memptr    list;
  1238.     word    far *p,
  1239.             pg;
  1240.     int        i;
  1241.  
  1242.     PM_UnlockMainMem();
  1243.     MM_GetPtr(&list,PMPageSize);
  1244.     PM_CheckMainMem();
  1245.     p = (word far *)MK_FP(PM_GetPage(ChunksInFile - 1),0);
  1246.     _fmemcpy((void far *)list,(void far *)p,PMPageSize);
  1247.     pg = PMSoundStart;
  1248.     for (i = 0;i < PMPageSize / (sizeof(word) * 2);i++,p += 2)
  1249.     {
  1250.         if (pg >= ChunksInFile - 1)
  1251.             break;
  1252.         pg += (p[1] + (PMPageSize - 1)) / PMPageSize;
  1253.     }
  1254.     PM_UnlockMainMem();
  1255.     MM_GetPtr((memptr *)&DigiList,i * sizeof(word) * 2);
  1256.     _fmemcpy((void far *)DigiList,(void far *)list,i * sizeof(word) * 2);
  1257.     MM_FreePtr(&list);
  1258.     NumDigi = i;
  1259.  
  1260.     for (i = 0;i < LASTSOUND;i++)
  1261.         DigiMap[i] = -1;
  1262. }
  1263.  
  1264. //     AdLib Code
  1265.  
  1266. ///////////////////////////////////////////////////////////////////////////
  1267. //
  1268. //    alOut(n,b) - Puts b in AdLib card register n
  1269. //
  1270. ///////////////////////////////////////////////////////////////////////////
  1271. void
  1272. alOut(byte n,byte b)
  1273. {
  1274. asm    pushf
  1275. asm    cli
  1276.  
  1277. asm    mov    dx,0x388
  1278. asm    mov    al,[n]
  1279. asm    out    dx,al
  1280. asm    in    al,dx
  1281. asm    in    al,dx
  1282. asm    in    al,dx
  1283. asm    in    al,dx
  1284. asm    in    al,dx
  1285. asm    in    al,dx
  1286. asm    inc    dx
  1287. asm    mov    al,[b]
  1288. asm    out    dx,al
  1289.  
  1290. asm    popf
  1291.  
  1292. asm    dec    dx
  1293. asm    in    al,dx
  1294. asm    in    al,dx
  1295. asm    in    al,dx
  1296. asm    in    al,dx
  1297. asm    in    al,dx
  1298. asm    in    al,dx
  1299. asm    in    al,dx
  1300. asm    in    al,dx
  1301. asm    in    al,dx
  1302. asm    in    al,dx
  1303.  
  1304. asm    in    al,dx
  1305. asm    in    al,dx
  1306. asm    in    al,dx
  1307. asm    in    al,dx
  1308. asm    in    al,dx
  1309. asm    in    al,dx
  1310. asm    in    al,dx
  1311. asm    in    al,dx
  1312. asm    in    al,dx
  1313. asm    in    al,dx
  1314.  
  1315. asm    in    al,dx
  1316. asm    in    al,dx
  1317. asm    in    al,dx
  1318. asm    in    al,dx
  1319. asm    in    al,dx
  1320. asm    in    al,dx
  1321. asm    in    al,dx
  1322. asm    in    al,dx
  1323. asm    in    al,dx
  1324. asm    in    al,dx
  1325.  
  1326. asm    in    al,dx
  1327. asm    in    al,dx
  1328. asm    in    al,dx
  1329. asm    in    al,dx
  1330. asm    in    al,dx
  1331. }
  1332.  
  1333. #if 0
  1334. ///////////////////////////////////////////////////////////////////////////
  1335. //
  1336. //    SDL_SetInstrument() - Puts an instrument into a generator
  1337. //
  1338. ///////////////////////////////////////////////////////////////////////////
  1339. static void
  1340. SDL_SetInstrument(int track,int which,Instrument far *inst,boolean percussive)
  1341. {
  1342.     byte        c,m;
  1343.  
  1344.     if (percussive)
  1345.     {
  1346.         c = pcarriers[which];
  1347.         m = pmodifiers[which];
  1348.     }
  1349.     else
  1350.     {
  1351.         c = carriers[which];
  1352.         m = modifiers[which];
  1353.     }
  1354.  
  1355.     tracks[track - 1]->inst = *inst;
  1356.     tracks[track - 1]->percussive = percussive;
  1357.  
  1358.     alOut(m + alChar,inst->mChar);
  1359.     alOut(m + alScale,inst->mScale);
  1360.     alOut(m + alAttack,inst->mAttack);
  1361.     alOut(m + alSus,inst->mSus);
  1362.     alOut(m + alWave,inst->mWave);
  1363.  
  1364.     // Most percussive instruments only use one cell
  1365.     if (c != 0xff)
  1366.     {
  1367.         alOut(c + alChar,inst->cChar);
  1368.         alOut(c + alScale,inst->cScale);
  1369.         alOut(c + alAttack,inst->cAttack);
  1370.         alOut(c + alSus,inst->cSus);
  1371.         alOut(c + alWave,inst->cWave);
  1372.     }
  1373.  
  1374.     alOut(which + alFeedCon,inst->nConn);    // DEBUG - I think this is right
  1375. }
  1376. #endif
  1377.  
  1378. ///////////////////////////////////////////////////////////////////////////
  1379. //
  1380. //    SDL_ALStopSound() - Turns off any sound effects playing through the
  1381. //        AdLib card
  1382. //
  1383. ///////////////////////////////////////////////////////////////////////////
  1384. #ifdef    _MUSE_
  1385. void
  1386. #else
  1387. static void
  1388. #endif
  1389. SDL_ALStopSound(void)
  1390. {
  1391. asm    pushf
  1392. asm    cli
  1393.  
  1394.     (long)alSound = 0;
  1395.     alOut(alFreqH + 0,0);
  1396.  
  1397. asm    popf
  1398. }
  1399.  
  1400. static void
  1401. SDL_AlSetFXInst(Instrument far *inst)
  1402. {
  1403.     byte        c,m;
  1404.  
  1405.     m = modifiers[0];
  1406.     c = carriers[0];
  1407.     alOut(m + alChar,inst->mChar);
  1408.     alOut(m + alScale,inst->mScale);
  1409.     alOut(m + alAttack,inst->mAttack);
  1410.     alOut(m + alSus,inst->mSus);
  1411.     alOut(m + alWave,inst->mWave);
  1412.     alOut(c + alChar,inst->cChar);
  1413.     alOut(c + alScale,inst->cScale);
  1414.     alOut(c + alAttack,inst->cAttack);
  1415.     alOut(c + alSus,inst->cSus);
  1416.     alOut(c + alWave,inst->cWave);
  1417.  
  1418.     // Note: Switch commenting on these lines for old MUSE compatibility
  1419. //    alOut(alFeedCon,inst->nConn);
  1420.     alOut(alFeedCon,0);
  1421. }
  1422.  
  1423. ///////////////////////////////////////////////////////////////////////////
  1424. //
  1425. //    SDL_ALPlaySound() - Plays the specified sound on the AdLib card
  1426. //
  1427. ///////////////////////////////////////////////////////////////////////////
  1428. #ifdef    _MUSE_
  1429. void
  1430. #else
  1431. static void
  1432. #endif
  1433. SDL_ALPlaySound(AdLibSound far *sound)
  1434. {
  1435.     Instrument    far *inst;
  1436.     byte        huge *data;
  1437.  
  1438.     SDL_ALStopSound();
  1439.  
  1440. asm    pushf
  1441. asm    cli
  1442.  
  1443.     alLengthLeft = sound->common.length;
  1444.     data = sound->data;
  1445.     data++;
  1446.     data--;
  1447.     alSound = (byte far *)data;
  1448.     alBlock = ((sound->block & 7) << 2) | 0x20;
  1449.     inst = &sound->inst;
  1450.  
  1451.     if (!(inst->mSus | inst->cSus))
  1452.     {
  1453.     asm    popf
  1454.         Quit("SDL_ALPlaySound() - Bad instrument");
  1455.     }
  1456.  
  1457.     SDL_AlSetFXInst(&alZeroInst);    // DEBUG
  1458.     SDL_AlSetFXInst(inst);
  1459.  
  1460. asm    popf
  1461. }
  1462.  
  1463. #if 0
  1464. ///////////////////////////////////////////////////////////////////////////
  1465. //
  1466. //     SDL_ALSoundService() - Plays the next sample out through the AdLib card
  1467. //
  1468. ///////////////////////////////////////////////////////////////////////////
  1469. //static void
  1470. void
  1471. SDL_ALSoundService(void)
  1472. {
  1473.     byte    s;
  1474.  
  1475.     if (alSound)
  1476.     {
  1477.         s = *alSound++;
  1478.         if (!s)
  1479.             alOut(alFreqH + 0,0);
  1480.         else
  1481.         {
  1482.             alOut(alFreqL + 0,s);
  1483.             alOut(alFreqH + 0,alBlock);
  1484.         }
  1485.  
  1486.         if (!(--alLengthLeft))
  1487.         {
  1488.             (long)alSound = 0;
  1489.             alOut(alFreqH + 0,0);
  1490.             SDL_SoundFinished();
  1491.         }
  1492.     }
  1493. }
  1494. #endif
  1495.  
  1496. #if 0
  1497. void
  1498. SDL_ALService(void)
  1499. {
  1500.     byte    a,v;
  1501.     word    w;
  1502.  
  1503.     if (!sqActive)
  1504.         return;
  1505.  
  1506.     while (sqHackLen && (sqHackTime <= alTimeCount))
  1507.     {
  1508.         w = *sqHackPtr++;
  1509.         sqHackTime = alTimeCount + *sqHackPtr++;
  1510.     asm    mov    dx,[w]
  1511.     asm    mov    [a],dl
  1512.     asm    mov    [v],dh
  1513.         alOut(a,v);
  1514.         sqHackLen -= 4;
  1515.     }
  1516.     alTimeCount++;
  1517.     if (!sqHackLen)
  1518.     {
  1519.         sqHackPtr = (word far *)sqHack;
  1520.         sqHackLen = sqHackSeqLen;
  1521.         alTimeCount = sqHackTime = 0;
  1522.     }
  1523. }
  1524. #endif
  1525.  
  1526. ///////////////////////////////////////////////////////////////////////////
  1527. //
  1528. //    SDL_ShutAL() - Shuts down the AdLib card for sound effects
  1529. //
  1530. ///////////////////////////////////////////////////////////////////////////
  1531. static void
  1532. SDL_ShutAL(void)
  1533. {
  1534. asm    pushf
  1535. asm    cli
  1536.  
  1537.     alOut(alEffects,0);
  1538.     alOut(alFreqH + 0,0);
  1539.     SDL_AlSetFXInst(&alZeroInst);
  1540.     alSound = 0;
  1541.  
  1542. asm    popf
  1543. }
  1544.  
  1545. ///////////////////////////////////////////////////////////////////////////
  1546. //
  1547. //    SDL_CleanAL() - Totally shuts down the AdLib card
  1548. //
  1549. ///////////////////////////////////////////////////////////////////////////
  1550. static void
  1551. SDL_CleanAL(void)
  1552. {
  1553.     int    i;
  1554.  
  1555. asm    pushf
  1556. asm    cli
  1557.  
  1558.     alOut(alEffects,0);
  1559.     for (i = 1;i < 0xf5;i++)
  1560.         alOut(i,0);
  1561.  
  1562. asm    popf
  1563. }
  1564.  
  1565. ///////////////////////////////////////////////////////////////////////////
  1566. //
  1567. //    SDL_StartAL() - Starts up the AdLib card for sound effects
  1568. //
  1569. ///////////////////////////////////////////////////////////////////////////
  1570. static void
  1571. SDL_StartAL(void)
  1572. {
  1573.     alFXReg = 0;
  1574.     alOut(alEffects,alFXReg);
  1575.     SDL_AlSetFXInst(&alZeroInst);
  1576. }
  1577.  
  1578. ///////////////////////////////////////////////////////////////////////////
  1579. //
  1580. //    SDL_DetectAdLib() - Determines if there's an AdLib (or SoundBlaster
  1581. //        emulating an AdLib) present
  1582. //
  1583. ///////////////////////////////////////////////////////////////////////////
  1584. static boolean
  1585. SDL_DetectAdLib(void)
  1586. {
  1587.     byte    status1,status2;
  1588.     int        i;
  1589.  
  1590.     alOut(4,0x60);    // Reset T1 & T2
  1591.     alOut(4,0x80);    // Reset IRQ
  1592.     status1 = readstat();
  1593.     alOut(2,0xff);    // Set timer 1
  1594.     alOut(4,0x21);    // Start timer 1
  1595. #if 0
  1596.     SDL_Delay(TimerDelay100);
  1597. #else
  1598. asm    mov    dx,0x388
  1599. asm    mov    cx,100
  1600. usecloop:
  1601. asm    in    al,dx
  1602. asm    loop usecloop
  1603. #endif
  1604.  
  1605.     status2 = readstat();
  1606.     alOut(4,0x60);
  1607.     alOut(4,0x80);
  1608.  
  1609.     if (((status1 & 0xe0) == 0x00) && ((status2 & 0xe0) == 0xc0))
  1610.     {
  1611.         for (i = 1;i <= 0xf5;i++)    // Zero all the registers
  1612.             alOut(i,0);
  1613.  
  1614.         alOut(1,0x20);    // Set WSE=1
  1615.         alOut(8,0);        // Set CSM=0 & SEL=0
  1616.  
  1617.         return(true);
  1618.     }
  1619.     else
  1620.         return(false);
  1621. }
  1622.  
  1623. #if 0
  1624. ///////////////////////////////////////////////////////////////////////////
  1625. //
  1626. //    SDL_t0Service() - My timer 0 ISR which handles the different timings and
  1627. //        dispatches to whatever other routines are appropriate
  1628. //
  1629. ///////////////////////////////////////////////////////////////////////////
  1630. static void interrupt
  1631. SDL_t0Service(void)
  1632. {
  1633. static    word    count = 1;
  1634.  
  1635. #if 1    // for debugging
  1636. asm    mov    dx,STATUS_REGISTER_1
  1637. asm    in    al,dx
  1638. asm    mov    dx,ATR_INDEX
  1639. asm    mov    al,ATR_OVERSCAN
  1640. asm    out    dx,al
  1641. asm    mov    al,4    // red
  1642. asm    out    dx,al
  1643. #endif
  1644.  
  1645.     HackCount++;
  1646.  
  1647.     if ((MusicMode == smm_AdLib) || (DigiMode == sds_SoundSource))
  1648.     {
  1649.         SDL_ALService();
  1650.         SDL_SSService();
  1651. //        if (!(++count & 7))
  1652.         if (!(++count % 10))
  1653.         {
  1654.             LocalTime++;
  1655.             TimeCount++;
  1656.             if (SoundUserHook)
  1657.                 SoundUserHook();
  1658.         }
  1659. //        if (!(count & 3))
  1660.         if (!(count % 5))
  1661.         {
  1662.             switch (SoundMode)
  1663.             {
  1664.             case sdm_PC:
  1665.                 SDL_PCService();
  1666.                 break;
  1667.             case sdm_AdLib:
  1668.                 SDL_ALSoundService();
  1669.                 break;
  1670.             }
  1671.         }
  1672.     }
  1673.     else
  1674.     {
  1675.         if (!(++count & 1))
  1676.         {
  1677.             LocalTime++;
  1678.             TimeCount++;
  1679.             if (SoundUserHook)
  1680.                 SoundUserHook();
  1681.         }
  1682.         switch (SoundMode)
  1683.         {
  1684.         case sdm_PC:
  1685.             SDL_PCService();
  1686.             break;
  1687.         case sdm_AdLib:
  1688.             SDL_ALSoundService();
  1689.             break;
  1690.         }
  1691.     }
  1692.  
  1693. asm    mov    ax,[WORD PTR TimerCount]
  1694. asm    add    ax,[WORD PTR TimerDivisor]
  1695. asm    mov    [WORD PTR TimerCount],ax
  1696. asm    jnc    myack
  1697.     t0OldService();            // If we overflow a word, time to call old int handler
  1698. asm    jmp    olddone
  1699. myack:;
  1700.     outportb(0x20,0x20);    // Ack the interrupt
  1701. olddone:;
  1702.  
  1703. #if 1    // for debugging
  1704. asm    mov    dx,STATUS_REGISTER_1
  1705. asm    in    al,dx
  1706. asm    mov    dx,ATR_INDEX
  1707. asm    mov    al,ATR_OVERSCAN
  1708. asm    out    dx,al
  1709. asm    mov    al,3    // blue
  1710. asm    out    dx,al
  1711. asm    mov    al,0x20    // normal
  1712. asm    out    dx,al
  1713. #endif
  1714. }
  1715. #endif
  1716.  
  1717. ////////////////////////////////////////////////////////////////////////////
  1718. //
  1719. //    SDL_ShutDevice() - turns off whatever device was being used for sound fx
  1720. //
  1721. ////////////////////////////////////////////////////////////////////////////
  1722. static void
  1723. SDL_ShutDevice(void)
  1724. {
  1725.     switch (SoundMode)
  1726.     {
  1727.     case sdm_PC:
  1728.         SDL_ShutPC();
  1729.         break;
  1730.     case sdm_AdLib:
  1731.         SDL_ShutAL();
  1732.         break;
  1733.     }
  1734.     SoundMode = sdm_Off;
  1735. }
  1736.  
  1737. ///////////////////////////////////////////////////////////////////////////
  1738. //
  1739. //    SDL_CleanDevice() - totally shuts down all sound devices
  1740. //
  1741. ///////////////////////////////////////////////////////////////////////////
  1742. static void
  1743. SDL_CleanDevice(void)
  1744. {
  1745.     if ((SoundMode == sdm_AdLib) || (MusicMode == smm_AdLib))
  1746.         SDL_CleanAL();
  1747. }
  1748.  
  1749. ///////////////////////////////////////////////////////////////////////////
  1750. //
  1751. //    SDL_StartDevice() - turns on whatever device is to be used for sound fx
  1752. //
  1753. ///////////////////////////////////////////////////////////////////////////
  1754. static void
  1755. SDL_StartDevice(void)
  1756. {
  1757.     switch (SoundMode)
  1758.     {
  1759.     case sdm_AdLib:
  1760.         SDL_StartAL();
  1761.         break;
  1762.     }
  1763.     SoundNumber = SoundPriority = 0;
  1764. }
  1765.  
  1766. //    Public routines
  1767.  
  1768. ///////////////////////////////////////////////////////////////////////////
  1769. //
  1770. //    SD_SetSoundMode() - Sets which sound hardware to use for sound effects
  1771. //
  1772. ///////////////////////////////////////////////////////////////////////////
  1773. boolean
  1774. SD_SetSoundMode(SDMode mode)
  1775. {
  1776.     boolean    result = false;
  1777.     word    tableoffset;
  1778.  
  1779.     SD_StopSound();
  1780.  
  1781. #ifndef    _MUSE_
  1782.     if ((mode == sdm_AdLib) && !AdLibPresent)
  1783.         mode = sdm_PC;
  1784.  
  1785.     switch (mode)
  1786.     {
  1787.     case sdm_Off:
  1788.         NeedsDigitized = false;
  1789.         result = true;
  1790.         break;
  1791.     case sdm_PC:
  1792.         tableoffset = STARTPCSOUNDS;
  1793.         NeedsDigitized = false;
  1794.         result = true;
  1795.         break;
  1796.     case sdm_AdLib:
  1797.         if (AdLibPresent)
  1798.         {
  1799.             tableoffset = STARTADLIBSOUNDS;
  1800.             NeedsDigitized = false;
  1801.             result = true;
  1802.         }
  1803.         break;
  1804.     }
  1805. #else
  1806.     result = true;
  1807. #endif
  1808.  
  1809.     if (result && (mode != SoundMode))
  1810.     {
  1811.         SDL_ShutDevice();
  1812.         SoundMode = mode;
  1813. #ifndef    _MUSE_
  1814.         SoundTable = (word *)(&audiosegs[tableoffset]);
  1815. #endif
  1816.         SDL_StartDevice();
  1817.     }
  1818.  
  1819.     SDL_SetTimerSpeed();
  1820.  
  1821.     return(result);
  1822. }
  1823.  
  1824. ///////////////////////////////////////////////////////////////////////////
  1825. //
  1826. //    SD_SetMusicMode() - sets the device to use for background music
  1827. //
  1828. ///////////////////////////////////////////////////////////////////////////
  1829. boolean
  1830. SD_SetMusicMode(SMMode mode)
  1831. {
  1832.     boolean    result = false;
  1833.  
  1834.     SD_FadeOutMusic();
  1835.     while (SD_MusicPlaying())
  1836.         ;
  1837.  
  1838.     switch (mode)
  1839.     {
  1840.     case smm_Off:
  1841.         NeedsMusic = false;
  1842.         result = true;
  1843.         break;
  1844.     case smm_AdLib:
  1845.         if (AdLibPresent)
  1846.         {
  1847.             NeedsMusic = true;
  1848.             result = true;
  1849.         }
  1850.         break;
  1851.     }
  1852.  
  1853.     if (result)
  1854.         MusicMode = mode;
  1855.  
  1856.     SDL_SetTimerSpeed();
  1857.  
  1858.     return(result);
  1859. }
  1860.  
  1861. ///////////////////////////////////////////////////////////////////////////
  1862. //
  1863. //    SD_Startup() - starts up the Sound Mgr
  1864. //        Detects all additional sound hardware and installs my ISR
  1865. //
  1866. ///////////////////////////////////////////////////////////////////////////
  1867. void
  1868. SD_Startup(void)
  1869. {
  1870.     int    i;
  1871.  
  1872.     if (SD_Started)
  1873.         return;
  1874.  
  1875.     SDL_SetDS();
  1876.  
  1877.     ssIsTandy = false;
  1878.     ssNoCheck = false;
  1879.     alNoCheck = false;
  1880.     sbNoCheck = false;
  1881.     sbNoProCheck = false;
  1882. #ifndef    _MUSE_
  1883.     for (i = 1;i < _argc;i++)
  1884.     {
  1885.         switch (US_CheckParm(_argv[i],ParmStrings))
  1886.         {
  1887.         case 0:                        // No AdLib detection
  1888.             alNoCheck = true;
  1889.             break;
  1890.         case 1:                        // No SoundBlaster detection
  1891.             sbNoCheck = true;
  1892.             break;
  1893.         case 2:                        // No SoundBlaster Pro detection
  1894.             sbNoProCheck = true;
  1895.             break;
  1896.         case 3:
  1897.             ssNoCheck = true;        // No Sound Source detection
  1898.             break;
  1899.         case 4:                        // Tandy Sound Source handling
  1900.             ssIsTandy = true;
  1901.             break;
  1902.         case 5:                        // Sound Source present at LPT1
  1903.             ssPort = 1;
  1904.             ssNoCheck = SoundSourcePresent = true;
  1905.             break;
  1906.         case 6:                     // Sound Source present at LPT2
  1907.             ssPort = 2;
  1908.             ssNoCheck = SoundSourcePresent = true;
  1909.             break;
  1910.         case 7:                     // Sound Source present at LPT3
  1911.             ssPort = 3;
  1912.             ssNoCheck = SoundSourcePresent = true;
  1913.             break;
  1914.         }
  1915.     }
  1916. #endif
  1917.  
  1918.     SoundUserHook = 0;
  1919.  
  1920.     t0OldService = getvect(8);    // Get old timer 0 ISR
  1921.  
  1922.     LocalTime = TimeCount = alTimeCount = 0;
  1923.  
  1924.     SD_SetSoundMode(sdm_Off);
  1925.     SD_SetMusicMode(smm_Off);
  1926.  
  1927.     if (!ssNoCheck)
  1928.         SoundSourcePresent = SDL_DetectSoundSource();
  1929.  
  1930.     if (!alNoCheck)
  1931.     {
  1932.         AdLibPresent = SDL_DetectAdLib();
  1933.         if (AdLibPresent && !sbNoCheck)
  1934.         {
  1935.             int port = -1;
  1936.             char *env = getenv("BLASTER");
  1937.             if (env)
  1938.             {
  1939.                 long temp;
  1940.                 while (*env)
  1941.                 {
  1942.                     while (isspace(*env))
  1943.                         env++;
  1944.  
  1945.                     switch (toupper(*env))
  1946.                     {
  1947.                     case 'A':
  1948.                         temp = strtol(env + 1,&env,16);
  1949.                         if
  1950.                         (
  1951.                             (temp >= 0x210)
  1952.                         &&    (temp <= 0x260)
  1953.                         &&    (!(temp & 0x00f))
  1954.                         )
  1955.                             port = (temp - 0x200) >> 4;
  1956.                         else
  1957.                             Quit("SD_Startup: Unsupported address value in BLASTER");
  1958.                         break;
  1959.                     case 'I':
  1960.                         temp = strtol(env + 1,&env,10);
  1961.                         if
  1962.                         (
  1963.                             (temp >= 0)
  1964.                         &&    (temp <= 10)
  1965.                         &&    (sbIntVectors[temp] != -1)
  1966.                         )
  1967.                         {
  1968.                             sbInterrupt = temp;
  1969.                             sbIntVec = sbIntVectors[sbInterrupt];
  1970.                         }
  1971.                         else
  1972.                             Quit("SD_Startup: Unsupported interrupt value in BLASTER");
  1973.                         break;
  1974.                     case 'D':
  1975.                         temp = strtol(env + 1,&env,10);
  1976.                         if ((temp == 0) || (temp == 1) || (temp == 3))
  1977.                             SDL_SBSetDMA(temp);
  1978.                         else
  1979.                             Quit("SD_Startup: Unsupported DMA value in BLASTER");
  1980.                         break;
  1981.                     default:
  1982.                         while (isspace(*env))
  1983.                             env++;
  1984.                         while (*env && !isspace(*env))
  1985.                             env++;
  1986.                         break;
  1987.                     }
  1988.                 }
  1989.             }
  1990.             SoundBlasterPresent = SDL_DetectSoundBlaster(port);
  1991.         }
  1992.     }
  1993.  
  1994.     for (i = 0;i < 255;i++)
  1995.         pcSoundLookup[i] = i * 60;
  1996.  
  1997.     if (SoundBlasterPresent)
  1998.         SDL_StartSB();
  1999.  
  2000.     SDL_SetupDigi();
  2001.  
  2002.     SD_Started = true;
  2003. }
  2004.  
  2005. ///////////////////////////////////////////////////////////////////////////
  2006. //
  2007. //    SD_Default() - Sets up the default behaviour for the Sound Mgr whether
  2008. //        the config file was present or not.
  2009. //
  2010. ///////////////////////////////////////////////////////////////////////////
  2011. void
  2012. SD_Default(boolean gotit,SDMode sd,SMMode sm)
  2013. {
  2014.     boolean    gotsd,gotsm;
  2015.  
  2016.     gotsd = gotsm = gotit;
  2017.  
  2018.     if (gotsd)    // Make sure requested sound hardware is available
  2019.     {
  2020.         switch (sd)
  2021.         {
  2022.         case sdm_AdLib:
  2023.             gotsd = AdLibPresent;
  2024.             break;
  2025.         }
  2026.     }
  2027.     if (!gotsd)
  2028.     {
  2029.         if (AdLibPresent)
  2030.             sd = sdm_AdLib;
  2031.         else
  2032.             sd = sdm_PC;
  2033.     }
  2034.     if (sd != SoundMode)
  2035.         SD_SetSoundMode(sd);
  2036.  
  2037.  
  2038.     if (gotsm)    // Make sure requested music hardware is available
  2039.     {
  2040.         switch (sm)
  2041.         {
  2042.         case sdm_AdLib:
  2043.             gotsm = AdLibPresent;
  2044.             break;
  2045.         }
  2046.     }
  2047.     if (!gotsm)
  2048.     {
  2049.         if (AdLibPresent)
  2050.             sm = smm_AdLib;
  2051.     }
  2052.     if (sm != MusicMode)
  2053.         SD_SetMusicMode(sm);
  2054. }
  2055.  
  2056. ///////////////////////////////////////////////////////////////////////////
  2057. //
  2058. //    SD_Shutdown() - shuts down the Sound Mgr
  2059. //        Removes sound ISR and turns off whatever sound hardware was active
  2060. //
  2061. ///////////////////////////////////////////////////////////////////////////
  2062. void
  2063. SD_Shutdown(void)
  2064. {
  2065.     if (!SD_Started)
  2066.         return;
  2067.  
  2068.     SD_MusicOff();
  2069.     SD_StopSound();
  2070.     SDL_ShutDevice();
  2071.     SDL_CleanDevice();
  2072.  
  2073.     if (SoundBlasterPresent)
  2074.         SDL_ShutSB();
  2075.  
  2076.     if (SoundSourcePresent)
  2077.         SDL_ShutSS();
  2078.  
  2079.     asm    pushf
  2080.     asm    cli
  2081.  
  2082.     SDL_SetTimer0(0);
  2083.  
  2084.     setvect(8,t0OldService);
  2085.  
  2086.     asm    popf
  2087.  
  2088.     SD_Started = false;
  2089. }
  2090.  
  2091. ///////////////////////////////////////////////////////////////////////////
  2092. //
  2093. //    SD_SetUserHook() - sets the routine that the Sound Mgr calls every 1/70th
  2094. //        of a second from its timer 0 ISR
  2095. //
  2096. ///////////////////////////////////////////////////////////////////////////
  2097. void
  2098. SD_SetUserHook(void (* hook)(void))
  2099. {
  2100.     SoundUserHook = hook;
  2101. }
  2102.  
  2103. ///////////////////////////////////////////////////////////////////////////
  2104. //
  2105. //    SD_PositionSound() - Sets up a stereo imaging location for the next
  2106. //        sound to be played. Each channel ranges from 0 to 15.
  2107. //
  2108. ///////////////////////////////////////////////////////////////////////////
  2109. void
  2110. SD_PositionSound(int leftvol,int rightvol)
  2111. {
  2112.     LeftPosition = leftvol;
  2113.     RightPosition = rightvol;
  2114.     nextsoundpos = true;
  2115. }
  2116.  
  2117. ///////////////////////////////////////////////////////////////////////////
  2118. //
  2119. //    SD_PlaySound() - plays the specified sound on the appropriate hardware
  2120. //
  2121. ///////////////////////////////////////////////////////////////////////////
  2122. boolean
  2123. SD_PlaySound(soundnames sound)
  2124. {
  2125.     boolean        ispos;
  2126.     SoundCommon    far *s;
  2127.     int    lp,rp;
  2128.  
  2129.     lp = LeftPosition;
  2130.     rp = RightPosition;
  2131.     LeftPosition = 0;
  2132.     RightPosition = 0;
  2133.  
  2134.     ispos = nextsoundpos;
  2135.     nextsoundpos = false;
  2136.  
  2137.     if (sound == -1)
  2138.         return(false);
  2139.  
  2140.     s = MK_FP(SoundTable[sound],0);
  2141.     if ((SoundMode != sdm_Off) && !s)
  2142.         Quit("SD_PlaySound() - Uncached sound");
  2143.  
  2144.     if ((DigiMode != sds_Off) && (DigiMap[sound] != -1))
  2145.     {
  2146.         if ((DigiMode == sds_PC) && (SoundMode == sdm_PC))
  2147.         {
  2148.             if (s->priority < SoundPriority)
  2149.                 return(false);
  2150.  
  2151.             SDL_PCStopSound();
  2152.  
  2153.             SD_PlayDigitized(DigiMap[sound],lp,rp);
  2154.             SoundPositioned = ispos;
  2155.             SoundNumber = sound;
  2156.             SoundPriority = s->priority;
  2157.         }
  2158.         else
  2159.         {
  2160.         asm    pushf
  2161.         asm    cli
  2162.             if (DigiPriority && !DigiNumber)
  2163.             {
  2164.             asm    popf
  2165.                 Quit("SD_PlaySound: Priority without a sound");
  2166.             }
  2167.         asm    popf
  2168.  
  2169.             if (s->priority < DigiPriority)
  2170.                 return(false);
  2171.  
  2172.             SD_PlayDigitized(DigiMap[sound],lp,rp);
  2173.             SoundPositioned = ispos;
  2174.             DigiNumber = sound;
  2175.             DigiPriority = s->priority;
  2176.         }
  2177.  
  2178.         return(true);
  2179.     }
  2180.  
  2181.     if (SoundMode == sdm_Off)
  2182.         return(false);
  2183.     if (!s->length)
  2184.         Quit("SD_PlaySound() - Zero length sound");
  2185.     if (s->priority < SoundPriority)
  2186.         return(false);
  2187.  
  2188.     switch (SoundMode)
  2189.     {
  2190.     case sdm_PC:
  2191.         SDL_PCPlaySound((void far *)s);
  2192.         break;
  2193.     case sdm_AdLib:
  2194.         SDL_ALPlaySound((void far *)s);
  2195.         break;
  2196.     }
  2197.  
  2198.     SoundNumber = sound;
  2199.     SoundPriority = s->priority;
  2200.  
  2201.     return(false);
  2202. }
  2203.  
  2204. ///////////////////////////////////////////////////////////////////////////
  2205. //
  2206. //    SD_SoundPlaying() - returns the sound number that's playing, or 0 if
  2207. //        no sound is playing
  2208. //
  2209. ///////////////////////////////////////////////////////////////////////////
  2210. word
  2211. SD_SoundPlaying(void)
  2212. {
  2213.     boolean    result = false;
  2214.  
  2215.     switch (SoundMode)
  2216.     {
  2217.     case sdm_PC:
  2218.         result = pcSound? true : false;
  2219.         break;
  2220.     case sdm_AdLib:
  2221.         result = alSound? true : false;
  2222.         break;
  2223.     }
  2224.  
  2225.     if (result)
  2226.         return(SoundNumber);
  2227.     else
  2228.         return(false);
  2229. }
  2230.  
  2231. ///////////////////////////////////////////////////////////////////////////
  2232. //
  2233. //    SD_StopSound() - if a sound is playing, stops it
  2234. //
  2235. ///////////////////////////////////////////////////////////////////////////
  2236. void
  2237. SD_StopSound(void)
  2238. {
  2239.     if (DigiPlaying)
  2240.         SD_StopDigitized();
  2241.  
  2242.     switch (SoundMode)
  2243.     {
  2244.     case sdm_PC:
  2245.         SDL_PCStopSound();
  2246.         break;
  2247.     case sdm_AdLib:
  2248.         SDL_ALStopSound();
  2249.         break;
  2250.     }
  2251.  
  2252.     SoundPositioned = false;
  2253.  
  2254.     SDL_SoundFinished();
  2255. }
  2256.  
  2257. ///////////////////////////////////////////////////////////////////////////
  2258. //
  2259. //    SD_WaitSoundDone() - waits until the current sound is done playing
  2260. //
  2261. ///////////////////////////////////////////////////////////////////////////
  2262. void
  2263. SD_WaitSoundDone(void)
  2264. {
  2265.     while (SD_SoundPlaying())
  2266.         ;
  2267. }
  2268.  
  2269. ///////////////////////////////////////////////////////////////////////////
  2270. //
  2271. //    SD_MusicOn() - turns on the sequencer
  2272. //
  2273. ///////////////////////////////////////////////////////////////////////////
  2274. void
  2275. SD_MusicOn(void)
  2276. {
  2277.     sqActive = true;
  2278. }
  2279.  
  2280. ///////////////////////////////////////////////////////////////////////////
  2281. //
  2282. //    SD_MusicOff() - turns off the sequencer and any playing notes
  2283. //
  2284. ///////////////////////////////////////////////////////////////////////////
  2285. void
  2286. SD_MusicOff(void)
  2287. {
  2288.     word    i;
  2289.  
  2290.  
  2291.     switch (MusicMode)
  2292.     {
  2293.     case smm_AdLib:
  2294.         alFXReg = 0;
  2295.         alOut(alEffects,0);
  2296.         for (i = 0;i < sqMaxTracks;i++)
  2297.             alOut(alFreqH + i + 1,0);
  2298.         break;
  2299.     }
  2300.     sqActive = false;
  2301. }
  2302.  
  2303. ///////////////////////////////////////////////////////////////////////////
  2304. //
  2305. //    SD_StartMusic() - starts playing the music pointed to
  2306. //
  2307. ///////////////////////////////////////////////////////////////////////////
  2308. void
  2309. SD_StartMusic(MusicGroup far *music)
  2310. {
  2311.     SD_MusicOff();
  2312. asm    pushf
  2313. asm    cli
  2314.  
  2315.     if (MusicMode == smm_AdLib)
  2316.     {
  2317.         sqHackPtr = sqHack = music->values;
  2318.         sqHackSeqLen = sqHackLen = music->length;
  2319.         sqHackTime = 0;
  2320.         alTimeCount = 0;
  2321.         SD_MusicOn();
  2322.     }
  2323.  
  2324. asm    popf
  2325. }
  2326.  
  2327. ///////////////////////////////////////////////////////////////////////////
  2328. //
  2329. //    SD_FadeOutMusic() - starts fading out the music. Call SD_MusicPlaying()
  2330. //        to see if the fadeout is complete
  2331. //
  2332. ///////////////////////////////////////////////////////////////////////////
  2333. void
  2334. SD_FadeOutMusic(void)
  2335. {
  2336.     switch (MusicMode)
  2337.     {
  2338.     case smm_AdLib:
  2339.         // DEBUG - quick hack to turn the music off
  2340.         SD_MusicOff();
  2341.         break;
  2342.     }
  2343. }
  2344.  
  2345. ///////////////////////////////////////////////////////////////////////////
  2346. //
  2347. //    SD_MusicPlaying() - returns true if music is currently playing, false if
  2348. //        not
  2349. //
  2350. ///////////////////////////////////////////////////////////////////////////
  2351. boolean
  2352. SD_MusicPlaying(void)
  2353. {
  2354.     boolean    result;
  2355.  
  2356.     switch (MusicMode)
  2357.     {
  2358.     case smm_AdLib:
  2359.         result = false;
  2360.         // DEBUG - not written
  2361.         break;
  2362.     default:
  2363.         result = false;
  2364.     }
  2365.  
  2366.     return(result);
  2367. }
  2368.