3 // ID_SD.c - Sound Manager for Wolfenstein 3D
\r
5 // By Jason Blochowiak
\r
9 // This module handles dealing with generating sound on the appropriate
\r
12 // Depends on: User Mgr (for parm checking)
\r
16 // SoundSourcePresent - Sound Source thingie present?
\r
17 // SoundBlasterPresent - SoundBlaster card present?
\r
18 // AdLibPresent - AdLib card present?
\r
19 // SoundMode - What device is used for sound effects
\r
20 // (Use SM_SetSoundMode() to set)
\r
21 // MusicMode - What device is used for music
\r
22 // (Use SM_SetMusicMode() to set)
\r
23 // DigiMode - What device is used for digitized sound effects
\r
24 // (Use SM_SetDigiDevice() to set)
\r
27 // NeedsDigitized - load digitized sounds?
\r
28 // NeedsMusic - load music?
\r
31 #pragma hdrstop // Wierdo thing with MUSE
\r
35 #ifdef _MUSE_ // Will be defined in ID_Types.h
\r
38 #include "ID_HEADS.H"
\r
48 #define SDL_SoundFinished() {SoundNumber = SoundPriority = 0;}
\r
50 // Macros for SoundBlaster stuff
\r
51 #define sbOut(n,b) outportb((n) + sbLocation,b)
\r
52 #define sbIn(n) inportb((n) + sbLocation)
\r
53 #define sbWriteDelay() while (sbIn(sbWriteStat) & 0x80);
\r
54 #define sbReadDelay() while (sbIn(sbDataAvail) & 0x80);
\r
56 // Macros for AdLib stuff
\r
57 #define selreg(n) outportb(alFMAddr,n)
\r
58 #define writereg(n) outportb(alFMData,n)
\r
59 #define readstat() inportb(alFMStatus)
\r
61 // Imports from ID_SD_A.ASM
\r
62 extern void SDL_SetDS(void),
\r
63 SDL_IndicatePC(boolean on);
\r
64 extern void interrupt SDL_t0ExtremeAsmService(void),
\r
65 SDL_t0FastAsmService(void),
\r
66 SDL_t0SlowAsmService(void);
\r
69 boolean SoundSourcePresent,
\r
71 SoundBlasterPresent,SBProPresent,
\r
72 NeedsDigitized,NeedsMusic,
\r
79 word *SoundTable; // Really * _seg *SoundTable, but that don't work
\r
82 int DigiMap[LASTSOUND];
\r
84 // Internal variables
\r
85 static boolean SD_Started;
\r
86 boolean nextsoundpos;
\r
87 longword TimerDivisor,TimerCount;
\r
88 static char *ParmStrings[] =
\r
100 static void (*SoundUserHook)(void);
\r
101 soundnames SoundNumber,DigiNumber;
\r
102 word SoundPriority,DigiPriority;
\r
103 int LeftPosition,RightPosition;
\r
104 void interrupt (*t0OldService)(void);
\r
108 word NumDigi,DigiLeft,DigiPage;
\r
109 word _seg *DigiList;
\r
110 word DigiLastStart,DigiLastEnd;
\r
111 boolean DigiPlaying;
\r
112 static boolean DigiMissed,DigiLastSegment;
\r
113 static memptr DigiNextAddr;
\r
114 static word DigiNextLen;
\r
116 // SoundBlaster variables
\r
117 static boolean sbNoCheck,sbNoProCheck;
\r
118 static volatile boolean sbSamplePlaying;
\r
119 static byte sbOldIntMask = -1;
\r
120 static volatile byte huge *sbNextSegPtr;
\r
121 static byte sbDMA = 1,
\r
122 sbDMAa1 = 0x83,sbDMAa2 = 2,sbDMAa3 = 3,
\r
123 sba1Vals[] = {0x87,0x83,0,0x82},
\r
124 sba2Vals[] = {0,2,0,6},
\r
125 sba3Vals[] = {1,3,0,7};
\r
126 static int sbLocation = -1,sbInterrupt = 7,sbIntVec = 0xf,
\r
127 sbIntVectors[] = {-1,-1,0xa,0xb,-1,0xd,-1,0xf,-1,-1,-1};
\r
128 static volatile longword sbNextSegLen;
\r
129 static volatile SampledSound huge *sbSamples;
\r
130 static void interrupt (*sbOldIntHand)(void);
\r
131 static byte sbpOldFMMix,sbpOldVOCMix;
\r
133 // SoundSource variables
\r
136 word ssControl,ssStatus,ssData;
\r
138 volatile byte far *ssSample;
\r
139 volatile longword ssLengthLeft;
\r
141 // PC Sound variables
\r
142 volatile byte pcLastSample,far *pcSound;
\r
143 longword pcLengthLeft;
\r
144 word pcSoundLookup[255];
\r
150 longword alLengthLeft;
\r
151 longword alTimeCount;
\r
152 Instrument alZeroInst;
\r
154 // This table maps channel numbers to carrier and modulator op cells
\r
155 static byte carriers[9] = { 3, 4, 5,11,12,13,19,20,21},
\r
156 modifiers[9] = { 0, 1, 2, 8, 9,10,16,17,18},
\r
157 // This table maps percussive voice numbers to op cells
\r
158 pcarriers[5] = {19,0xff,0xff,0xff,0xff},
\r
159 pmodifiers[5] = {16,17,18,20,21};
\r
161 // Sequencer variables
\r
163 static word alFXReg;
\r
164 static ActiveTrack *tracks[sqMaxTracks],
\r
165 mytracks[sqMaxTracks];
\r
166 static word sqMode,sqFadeStep;
\r
167 word far *sqHack,far *sqHackPtr,sqHackLen,sqHackSeqLen;
\r
170 // Internal routines
\r
171 void SDL_DigitizedDone(void);
\r
173 ///////////////////////////////////////////////////////////////////////////
\r
175 // SDL_SetTimer0() - Sets system timer 0 to the specified speed
\r
177 ///////////////////////////////////////////////////////////////////////////
\r
180 SDL_SetTimer0(word speed)
\r
182 #ifndef TPROF // If using Borland's profiling, don't screw with the timer
\r
186 outportb(0x43,0x36); // Change timer 0
\r
187 outportb(0x40,speed);
\r
188 outportb(0x40,speed >> 8);
\r
189 // Kludge to handle special case for digitized PC sounds
\r
190 if (TimerDivisor == (1192030 / (TickBase * 100)))
\r
191 TimerDivisor = (1192030 / (TickBase * 10));
\r
193 TimerDivisor = speed;
\r
197 TimerDivisor = 0x10000;
\r
201 ///////////////////////////////////////////////////////////////////////////
\r
203 // SDL_SetIntsPerSec() - Uses SDL_SetTimer0() to set the number of
\r
204 // interrupts generated by system timer 0 per second
\r
206 ///////////////////////////////////////////////////////////////////////////
\r
208 SDL_SetIntsPerSec(word ints)
\r
211 SDL_SetTimer0(1192030 / ints);
\r
215 SDL_SetTimerSpeed(void)
\r
218 void interrupt (*isr)(void);
\r
220 if ((DigiMode == sds_PC) && DigiPlaying)
\r
222 rate = TickBase * 100;
\r
223 isr = SDL_t0ExtremeAsmService;
\r
227 (MusicMode == smm_AdLib)
\r
228 || ((DigiMode == sds_SoundSource) && DigiPlaying)
\r
231 rate = TickBase * 10;
\r
232 isr = SDL_t0FastAsmService;
\r
236 rate = TickBase * 2;
\r
237 isr = SDL_t0SlowAsmService;
\r
240 if (rate != TimerRate)
\r
243 SDL_SetIntsPerSec(rate);
\r
249 // SoundBlaster code
\r
252 ///////////////////////////////////////////////////////////////////////////
\r
254 // SDL_SBStopSample() - Stops any active sampled sound and causes DMA
\r
255 // requests from the SoundBlaster to cease
\r
257 ///////////////////////////////////////////////////////////////////////////
\r
263 SDL_SBStopSample(void)
\r
270 if (sbSamplePlaying)
\r
272 sbSamplePlaying = false;
\r
275 sbOut(sbWriteCmd,0xd0); // Turn off DSP DMA
\r
277 is = inportb(0x21); // Restore interrupt mask bit
\r
278 if (sbOldIntMask & (1 << sbInterrupt))
\r
279 is |= (1 << sbInterrupt);
\r
281 is &= ~(1 << sbInterrupt);
\r
288 ///////////////////////////////////////////////////////////////////////////
\r
290 // SDL_SBPlaySeg() - Plays a chunk of sampled sound on the SoundBlaster
\r
291 // Insures that the chunk doesn't cross a bank boundary, programs the DMA
\r
292 // controller, and tells the SB to start doing DMA requests for DAC
\r
294 ///////////////////////////////////////////////////////////////////////////
\r
296 SDL_SBPlaySeg(volatile byte huge *data,longword length)
\r
299 longword dataofs,uselen;
\r
302 datapage = FP_SEG(data) >> 12;
\r
303 dataofs = ((FP_SEG(data) & 0xfff) << 4) + FP_OFF(data);
\r
304 if (dataofs >= 0x10000)
\r
307 dataofs -= 0x10000;
\r
310 if (dataofs + uselen > 0x10000)
\r
311 uselen = 0x10000 - dataofs;
\r
315 // Program the DMA controller
\r
318 outportb(0x0a,sbDMA | 4); // Mask off DMA on channel sbDMA
\r
319 outportb(0x0c,0); // Clear byte ptr flip-flop to lower byte
\r
320 outportb(0x0b,0x49); // Set transfer mode for D/A conv
\r
321 outportb(sbDMAa2,(byte)dataofs); // Give LSB of address
\r
322 outportb(sbDMAa2,(byte)(dataofs >> 8)); // Give MSB of address
\r
323 outportb(sbDMAa1,(byte)datapage); // Give page of address
\r
324 outportb(sbDMAa3,(byte)uselen); // Give LSB of length
\r
325 outportb(sbDMAa3,(byte)(uselen >> 8)); // Give MSB of length
\r
326 outportb(0x0a,sbDMA); // Re-enable DMA on channel sbDMA
\r
328 // Start playing the thing
\r
330 sbOut(sbWriteCmd,0x14);
\r
332 sbOut(sbWriteData,(byte)uselen);
\r
334 sbOut(sbWriteData,(byte)(uselen >> 8));
\r
337 return(uselen + 1);
\r
340 ///////////////////////////////////////////////////////////////////////////
\r
342 // SDL_SBService() - Services the SoundBlaster DMA interrupt
\r
344 ///////////////////////////////////////////////////////////////////////////
\r
345 static void interrupt
\r
346 SDL_SBService(void)
\r
350 sbIn(sbDataAvail); // Ack interrupt to SB
\r
354 used = SDL_SBPlaySeg(sbNextSegPtr,sbNextSegLen);
\r
355 if (sbNextSegLen <= used)
\r
356 sbNextSegPtr = nil;
\r
359 sbNextSegPtr += used;
\r
360 sbNextSegLen -= used;
\r
365 SDL_SBStopSample();
\r
366 SDL_DigitizedDone();
\r
369 outportb(0x20,0x20); // Ack interrupt
\r
372 ///////////////////////////////////////////////////////////////////////////
\r
374 // SDL_SBPlaySample() - Plays a sampled sound on the SoundBlaster. Sets up
\r
375 // DMA to play the sound
\r
377 ///////////////////////////////////////////////////////////////////////////
\r
383 SDL_SBPlaySample(byte huge *data,longword len)
\r
387 SDL_SBStopSample();
\r
392 used = SDL_SBPlaySeg(data,len);
\r
394 sbNextSegPtr = nil;
\r
397 sbNextSegPtr = data + used;
\r
398 sbNextSegLen = len - used;
\r
401 // Save old interrupt status and unmask ours
\r
402 sbOldIntMask = inportb(0x21);
\r
403 outportb(0x21,sbOldIntMask & ~(1 << sbInterrupt));
\r
406 sbOut(sbWriteCmd,0xd4); // Make sure DSP DMA is enabled
\r
408 sbSamplePlaying = true;
\r
413 ///////////////////////////////////////////////////////////////////////////
\r
415 // SDL_PositionSBP() - Sets the attenuation levels for the left and right
\r
416 // channels by using the mixer chip on the SB Pro. This hits a hole in
\r
417 // the address map for normal SBs.
\r
419 ///////////////////////////////////////////////////////////////////////////
\r
421 SDL_PositionSBP(int leftpos,int rightpos)
\r
428 leftpos = 15 - leftpos;
\r
429 rightpos = 15 - rightpos;
\r
430 v = ((leftpos & 0x0f) << 4) | (rightpos & 0x0f);
\r
435 sbOut(sbpMixerAddr,sbpmVoiceVol);
\r
436 sbOut(sbpMixerData,v);
\r
441 ///////////////////////////////////////////////////////////////////////////
\r
443 // SDL_CheckSB() - Checks to see if a SoundBlaster resides at a
\r
444 // particular I/O location
\r
446 ///////////////////////////////////////////////////////////////////////////
\r
448 SDL_CheckSB(int port)
\r
452 sbLocation = port << 4; // Initialize stuff for later use
\r
454 sbOut(sbReset,true); // Reset the SoundBlaster DSP
\r
455 asm mov dx,0x388 // Wait >4usec
\r
466 sbOut(sbReset,false); // Turn off sb DSP reset
\r
467 asm mov dx,0x388 // Wait >100usec
\r
473 for (i = 0;i < 100;i++)
\r
475 if (sbIn(sbDataAvail) & 0x80) // If data is available...
\r
477 if (sbIn(sbReadData) == 0xaa) // If it matches correct value
\r
481 sbLocation = -1; // Otherwise not a SoundBlaster
\r
486 sbLocation = -1; // Retry count exceeded - fail
\r
490 ///////////////////////////////////////////////////////////////////////////
\r
492 // Checks to see if a SoundBlaster is in the system. If the port passed is
\r
493 // -1, then it scans through all possible I/O locations. If the port
\r
494 // passed is 0, then it uses the default (2). If the port is >0, then
\r
495 // it just passes it directly to SDL_CheckSB()
\r
497 ///////////////////////////////////////////////////////////////////////////
\r
499 SDL_DetectSoundBlaster(int port)
\r
503 if (port == 0) // If user specifies default, use 2
\r
507 if (SDL_CheckSB(2)) // Check default before scanning
\r
510 if (SDL_CheckSB(4)) // Check other SB Pro location before scan
\r
513 for (i = 1;i <= 6;i++) // Scan through possible SB locations
\r
515 if ((i == 2) || (i == 4))
\r
518 if (SDL_CheckSB(i)) // If found at this address,
\r
519 return(true); // return success
\r
521 return(false); // All addresses failed, return failure
\r
524 return(SDL_CheckSB(port)); // User specified address or default
\r
527 ///////////////////////////////////////////////////////////////////////////
\r
529 // SDL_SBSetDMA() - Sets the DMA channel to be used by the SoundBlaster
\r
530 // code. Sets up sbDMA, and sbDMAa1-sbDMAa3 (used by SDL_SBPlaySeg()).
\r
532 ///////////////////////////////////////////////////////////////////////////
\r
534 SDL_SBSetDMA(byte channel)
\r
537 Quit("SDL_SBSetDMA() - invalid SoundBlaster DMA channel");
\r
540 sbDMAa1 = sba1Vals[channel];
\r
541 sbDMAa2 = sba2Vals[channel];
\r
542 sbDMAa3 = sba3Vals[channel];
\r
545 ///////////////////////////////////////////////////////////////////////////
\r
547 // SDL_StartSB() - Turns on the SoundBlaster
\r
549 ///////////////////////////////////////////////////////////////////////////
\r
553 byte timevalue,test;
\r
555 sbIntVec = sbIntVectors[sbInterrupt];
\r
557 Quit("SDL_StartSB: Illegal or unsupported interrupt number for SoundBlaster");
\r
559 sbOldIntHand = getvect(sbIntVec); // Get old interrupt handler
\r
560 setvect(sbIntVec,SDL_SBService); // Set mine
\r
563 sbOut(sbWriteCmd,0xd1); // Turn on DSP speaker
\r
565 // Set the SoundBlaster DAC time constant for 7KHz
\r
566 timevalue = 256 - (1000000 / 7000);
\r
568 sbOut(sbWriteCmd,0x40);
\r
570 sbOut(sbWriteData,timevalue);
\r
572 SBProPresent = false;
\r
576 // Check to see if this is a SB Pro
\r
577 sbOut(sbpMixerAddr,sbpmFMVol);
\r
578 sbpOldFMMix = sbIn(sbpMixerData);
\r
579 sbOut(sbpMixerData,0xbb);
\r
580 test = sbIn(sbpMixerData);
\r
583 // Boost FM output levels to be equivilent with digitized output
\r
584 sbOut(sbpMixerData,0xff);
\r
585 test = sbIn(sbpMixerData);
\r
588 SBProPresent = true;
\r
590 // Save old Voice output levels (SB Pro)
\r
591 sbOut(sbpMixerAddr,sbpmVoiceVol);
\r
592 sbpOldVOCMix = sbIn(sbpMixerData);
\r
594 // Turn SB Pro stereo DAC off
\r
595 sbOut(sbpMixerAddr,sbpmControl);
\r
596 sbOut(sbpMixerData,0); // 0=off,2=on
\r
601 ///////////////////////////////////////////////////////////////////////////
\r
603 // SDL_ShutSB() - Turns off the SoundBlaster
\r
605 ///////////////////////////////////////////////////////////////////////////
\r
609 SDL_SBStopSample();
\r
613 // Restore FM output levels (SB Pro)
\r
614 sbOut(sbpMixerAddr,sbpmFMVol);
\r
615 sbOut(sbpMixerData,sbpOldFMMix);
\r
617 // Restore Voice output levels (SB Pro)
\r
618 sbOut(sbpMixerAddr,sbpmVoiceVol);
\r
619 sbOut(sbpMixerData,sbpOldVOCMix);
\r
622 setvect(sbIntVec,sbOldIntHand); // Set vector back
\r
625 // Sound Source Code
\r
627 ///////////////////////////////////////////////////////////////////////////
\r
629 // SDL_SSStopSample() - Stops a sample playing on the Sound Source
\r
631 ///////////////////////////////////////////////////////////////////////////
\r
637 SDL_SSStopSample(void)
\r
642 (long)ssSample = 0;
\r
647 ///////////////////////////////////////////////////////////////////////////
\r
649 // SDL_SSService() - Handles playing the next sample on the Sound Source
\r
651 ///////////////////////////////////////////////////////////////////////////
\r
653 SDL_SSService(void)
\r
660 asm mov dx,[ssStatus] // Check to see if FIFO is currently empty
\r
663 asm jnz done // Nope - don't push any more data out
\r
666 if (!(--ssLengthLeft))
\r
668 (long)ssSample = 0;
\r
669 SDL_DigitizedDone();
\r
672 asm mov dx,[ssData] // Pump the value out
\r
676 asm mov dx,[ssControl] // Pulse printer select
\r
684 asm push ax // Delay a short while
\r
692 ///////////////////////////////////////////////////////////////////////////
\r
694 // SDL_SSPlaySample() - Plays the specified sample on the Sound Source
\r
696 ///////////////////////////////////////////////////////////////////////////
\r
702 SDL_SSPlaySample(byte huge *data,longword len)
\r
707 ssLengthLeft = len;
\r
708 ssSample = (volatile byte far *)data;
\r
713 ///////////////////////////////////////////////////////////////////////////
\r
715 // SDL_StartSS() - Sets up for and turns on the Sound Source
\r
717 ///////////////////////////////////////////////////////////////////////////
\r
722 ssControl = 0x27a; // If using LPT3
\r
723 else if (ssPort == 2)
\r
724 ssControl = 0x37a; // If using LPT2
\r
726 ssControl = 0x3be; // If using LPT1
\r
727 ssStatus = ssControl - 1;
\r
728 ssData = ssStatus - 1;
\r
732 ssOff = 0x0e; // Tandy wierdness
\r
734 ssOff = 0x0c; // For normal machines
\r
736 outportb(ssControl,ssOn); // Enable SS
\r
739 ///////////////////////////////////////////////////////////////////////////
\r
741 // SDL_ShutSS() - Turns off the Sound Source
\r
743 ///////////////////////////////////////////////////////////////////////////
\r
747 outportb(ssControl,ssOff);
\r
750 ///////////////////////////////////////////////////////////////////////////
\r
752 // SDL_CheckSS() - Checks to see if a Sound Source is present at the
\r
753 // location specified by the sound source variables
\r
755 ///////////////////////////////////////////////////////////////////////////
\r
759 boolean present = false;
\r
762 // Turn the Sound Source on and wait awhile (4 ticks)
\r
765 lasttime = TimeCount;
\r
766 while (TimeCount < lasttime + 4)
\r
769 asm mov dx,[ssStatus] // Check to see if FIFO is currently empty
\r
772 asm jnz checkdone // Nope - Sound Source not here
\r
774 asm mov cx,32 // Force FIFO overflow (FIFO is 16 bytes)
\r
776 asm mov dx,[ssData] // Pump a neutral value out
\r
780 asm mov dx,[ssControl] // Pulse printer select
\r
788 asm push ax // Delay a short while before we do this again
\r
795 asm mov dx,[ssStatus] // Is FIFO overflowed now?
\r
798 asm jz checkdone // Nope, still not - Sound Source not here
\r
800 present = true; // Yes - it's here!
\r
808 SDL_DetectSoundSource(void)
\r
810 for (ssPort = 1;ssPort <= 3;ssPort++)
\r
820 ///////////////////////////////////////////////////////////////////////////
\r
822 // SDL_PCPlaySample() - Plays the specified sample on the PC speaker
\r
824 ///////////////////////////////////////////////////////////////////////////
\r
830 SDL_PCPlaySample(byte huge *data,longword len)
\r
835 SDL_IndicatePC(true);
\r
837 pcLengthLeft = len;
\r
838 pcSound = (volatile byte far *)data;
\r
843 ///////////////////////////////////////////////////////////////////////////
\r
845 // SDL_PCStopSample() - Stops a sample playing on the PC speaker
\r
847 ///////////////////////////////////////////////////////////////////////////
\r
853 SDL_PCStopSample(void)
\r
860 SDL_IndicatePC(false);
\r
862 asm in al,0x61 // Turn the speaker off
\r
863 asm and al,0xfd // ~2
\r
869 ///////////////////////////////////////////////////////////////////////////
\r
871 // SDL_PCPlaySound() - Plays the specified sound on the PC speaker
\r
873 ///////////////////////////////////////////////////////////////////////////
\r
879 SDL_PCPlaySound(PCSound far *sound)
\r
885 pcLengthLeft = sound->common.length;
\r
886 pcSound = sound->data;
\r
891 ///////////////////////////////////////////////////////////////////////////
\r
893 // SDL_PCStopSound() - Stops the current sound playing on the PC Speaker
\r
895 ///////////////////////////////////////////////////////////////////////////
\r
901 SDL_PCStopSound(void)
\r
908 asm in al,0x61 // Turn the speaker off
\r
909 asm and al,0xfd // ~2
\r
916 ///////////////////////////////////////////////////////////////////////////
\r
918 // SDL_PCService() - Handles playing the next sample in a PC sound
\r
920 ///////////////////////////////////////////////////////////////////////////
\r
922 SDL_PCService(void)
\r
930 if (s != pcLastSample)
\r
936 if (s) // We have a frequency!
\r
938 t = pcSoundLookup[s];
\r
941 asm mov al,0xb6 // Write to channel 2 (speaker) timer
\r
944 asm out 42h,al // Low byte
\r
946 asm out 42h,al // High byte
\r
948 asm in al,0x61 // Turn the speaker & gate on
\r
952 else // Time for some silence
\r
954 asm in al,0x61 // Turn the speaker & gate off
\r
955 asm and al,0xfc // ~3
\r
962 if (!(--pcLengthLeft))
\r
965 SDL_SoundFinished();
\r
971 ///////////////////////////////////////////////////////////////////////////
\r
973 // SDL_ShutPC() - Turns off the pc speaker
\r
975 ///////////////////////////////////////////////////////////////////////////
\r
984 asm in al,0x61 // Turn the speaker & gate off
\r
985 asm and al,0xfc // ~3
\r
992 // Stuff for digitized sounds
\r
995 SDL_LoadDigiSegment(word page)
\r
999 #if 0 // for debugging
\r
1000 asm mov dx,STATUS_REGISTER_1
\r
1002 asm mov dx,ATR_INDEX
\r
1003 asm mov al,ATR_OVERSCAN
\r
1005 asm mov al,10 // bright green
\r
1009 addr = PM_GetSoundPage(page);
\r
1010 PM_SetPageLock(PMSoundStart + page,pml_Locked);
\r
1012 #if 0 // for debugging
\r
1013 asm mov dx,STATUS_REGISTER_1
\r
1015 asm mov dx,ATR_INDEX
\r
1016 asm mov al,ATR_OVERSCAN
\r
1018 asm mov al,3 // blue
\r
1020 asm mov al,0x20 // normal
\r
1028 SDL_PlayDigiSegment(memptr addr,word len)
\r
1033 SDL_PCPlaySample(addr,len);
\r
1035 case sds_SoundSource:
\r
1036 SDL_SSPlaySample(addr,len);
\r
1038 case sds_SoundBlaster:
\r
1039 SDL_SBPlaySample(addr,len);
\r
1045 SD_StopDigitized(void)
\r
1053 DigiNextAddr = nil;
\r
1055 DigiMissed = false;
\r
1056 DigiPlaying = false;
\r
1057 DigiNumber = DigiPriority = 0;
\r
1058 SoundPositioned = false;
\r
1059 if ((DigiMode == sds_PC) && (SoundMode == sdm_PC))
\r
1060 SDL_SoundFinished();
\r
1065 SDL_PCStopSample();
\r
1067 case sds_SoundSource:
\r
1068 SDL_SSStopSample();
\r
1070 case sds_SoundBlaster:
\r
1071 SDL_SBStopSample();
\r
1077 for (i = DigiLastStart;i < DigiLastEnd;i++)
\r
1078 PM_SetPageLock(i + PMSoundStart,pml_Unlocked);
\r
1079 DigiLastStart = 1;
\r
1086 if (DigiLeft && !DigiNextAddr)
\r
1088 DigiNextLen = (DigiLeft >= PMPageSize)? PMPageSize : (DigiLeft % PMPageSize);
\r
1089 DigiLeft -= DigiNextLen;
\r
1091 DigiLastSegment = true;
\r
1092 DigiNextAddr = SDL_LoadDigiSegment(DigiPage++);
\r
1094 if (DigiMissed && DigiNextAddr)
\r
1096 SDL_PlayDigiSegment(DigiNextAddr,DigiNextLen);
\r
1097 DigiNextAddr = nil;
\r
1098 DigiMissed = false;
\r
1099 if (DigiLastSegment)
\r
1101 DigiPlaying = false;
\r
1102 DigiLastSegment = false;
\r
1105 SDL_SetTimerSpeed();
\r
1109 SD_SetPosition(int leftpos,int rightpos)
\r
1116 || (rightpos > 15)
\r
1117 || ((leftpos == 15) && (rightpos == 15))
\r
1119 Quit("SD_SetPosition: Illegal position");
\r
1123 case sds_SoundBlaster:
\r
1124 SDL_PositionSBP(leftpos,rightpos);
\r
1130 SD_PlayDigitized(word which,int leftpos,int rightpos)
\r
1138 SD_StopDigitized();
\r
1139 if (which >= NumDigi)
\r
1140 Quit("SD_PlayDigitized: bad sound number");
\r
1142 SD_SetPosition(leftpos,rightpos);
\r
1144 DigiPage = DigiList[(which * 2) + 0];
\r
1145 DigiLeft = DigiList[(which * 2) + 1];
\r
1147 DigiLastStart = DigiPage;
\r
1148 DigiLastEnd = DigiPage + ((DigiLeft + (PMPageSize - 1)) / PMPageSize);
\r
1150 len = (DigiLeft >= PMPageSize)? PMPageSize : (DigiLeft % PMPageSize);
\r
1151 addr = SDL_LoadDigiSegment(DigiPage++);
\r
1153 DigiPlaying = true;
\r
1154 DigiLastSegment = false;
\r
1156 SDL_PlayDigiSegment(addr,len);
\r
1159 DigiLastSegment = true;
\r
1165 SDL_DigitizedDone(void)
\r
1169 SDL_PlayDigiSegment(DigiNextAddr,DigiNextLen);
\r
1170 DigiNextAddr = nil;
\r
1171 DigiMissed = false;
\r
1175 if (DigiLastSegment)
\r
1177 DigiPlaying = false;
\r
1178 DigiLastSegment = false;
\r
1179 if ((DigiMode == sds_PC) && (SoundMode == sdm_PC))
\r
1181 SDL_SoundFinished();
\r
1184 DigiNumber = DigiPriority = 0;
\r
1185 SoundPositioned = false;
\r
1188 DigiMissed = true;
\r
1193 SD_SetDigiDevice(SDSMode mode)
\r
1195 boolean devicenotpresent;
\r
1197 if (mode == DigiMode)
\r
1200 SD_StopDigitized();
\r
1202 devicenotpresent = false;
\r
1205 case sds_SoundBlaster:
\r
1206 if (!SoundBlasterPresent)
\r
1208 if (SoundSourcePresent)
\r
1209 mode = sds_SoundSource;
\r
1211 devicenotpresent = true;
\r
1214 case sds_SoundSource:
\r
1215 if (!SoundSourcePresent)
\r
1216 devicenotpresent = true;
\r
1220 if (!devicenotpresent)
\r
1222 if (DigiMode == sds_SoundSource)
\r
1227 if (mode == sds_SoundSource)
\r
1230 SDL_SetTimerSpeed();
\r
1235 SDL_SetupDigi(void)
\r
1242 PM_UnlockMainMem();
\r
1243 MM_GetPtr(&list,PMPageSize);
\r
1244 PM_CheckMainMem();
\r
1245 p = (word far *)MK_FP(PM_GetPage(ChunksInFile - 1),0);
\r
1246 _fmemcpy((void far *)list,(void far *)p,PMPageSize);
\r
1247 pg = PMSoundStart;
\r
1248 for (i = 0;i < PMPageSize / (sizeof(word) * 2);i++,p += 2)
\r
1250 if (pg >= ChunksInFile - 1)
\r
1252 pg += (p[1] + (PMPageSize - 1)) / PMPageSize;
\r
1254 PM_UnlockMainMem();
\r
1255 MM_GetPtr((memptr *)&DigiList,i * sizeof(word) * 2);
\r
1256 _fmemcpy((void far *)DigiList,(void far *)list,i * sizeof(word) * 2);
\r
1257 MM_FreePtr(&list);
\r
1260 for (i = 0;i < LASTSOUND;i++)
\r
1266 ///////////////////////////////////////////////////////////////////////////
\r
1268 // alOut(n,b) - Puts b in AdLib card register n
\r
1270 ///////////////////////////////////////////////////////////////////////////
\r
1272 alOut(byte n,byte b)
\r
1334 ///////////////////////////////////////////////////////////////////////////
\r
1336 // SDL_SetInstrument() - Puts an instrument into a generator
\r
1338 ///////////////////////////////////////////////////////////////////////////
\r
1340 SDL_SetInstrument(int track,int which,Instrument far *inst,boolean percussive)
\r
1346 c = pcarriers[which];
\r
1347 m = pmodifiers[which];
\r
1351 c = carriers[which];
\r
1352 m = modifiers[which];
\r
1355 tracks[track - 1]->inst = *inst;
\r
1356 tracks[track - 1]->percussive = percussive;
\r
1358 alOut(m + alChar,inst->mChar);
\r
1359 alOut(m + alScale,inst->mScale);
\r
1360 alOut(m + alAttack,inst->mAttack);
\r
1361 alOut(m + alSus,inst->mSus);
\r
1362 alOut(m + alWave,inst->mWave);
\r
1364 // Most percussive instruments only use one cell
\r
1367 alOut(c + alChar,inst->cChar);
\r
1368 alOut(c + alScale,inst->cScale);
\r
1369 alOut(c + alAttack,inst->cAttack);
\r
1370 alOut(c + alSus,inst->cSus);
\r
1371 alOut(c + alWave,inst->cWave);
\r
1374 alOut(which + alFeedCon,inst->nConn); // DEBUG - I think this is right
\r
1378 ///////////////////////////////////////////////////////////////////////////
\r
1380 // SDL_ALStopSound() - Turns off any sound effects playing through the
\r
1383 ///////////////////////////////////////////////////////////////////////////
\r
1389 SDL_ALStopSound(void)
\r
1394 (long)alSound = 0;
\r
1395 alOut(alFreqH + 0,0);
\r
1401 SDL_AlSetFXInst(Instrument far *inst)
\r
1407 alOut(m + alChar,inst->mChar);
\r
1408 alOut(m + alScale,inst->mScale);
\r
1409 alOut(m + alAttack,inst->mAttack);
\r
1410 alOut(m + alSus,inst->mSus);
\r
1411 alOut(m + alWave,inst->mWave);
\r
1412 alOut(c + alChar,inst->cChar);
\r
1413 alOut(c + alScale,inst->cScale);
\r
1414 alOut(c + alAttack,inst->cAttack);
\r
1415 alOut(c + alSus,inst->cSus);
\r
1416 alOut(c + alWave,inst->cWave);
\r
1418 // Note: Switch commenting on these lines for old MUSE compatibility
\r
1419 // alOut(alFeedCon,inst->nConn);
\r
1420 alOut(alFeedCon,0);
\r
1423 ///////////////////////////////////////////////////////////////////////////
\r
1425 // SDL_ALPlaySound() - Plays the specified sound on the AdLib card
\r
1427 ///////////////////////////////////////////////////////////////////////////
\r
1433 SDL_ALPlaySound(AdLibSound far *sound)
\r
1435 Instrument far *inst;
\r
1438 SDL_ALStopSound();
\r
1443 alLengthLeft = sound->common.length;
\r
1444 data = sound->data;
\r
1447 alSound = (byte far *)data;
\r
1448 alBlock = ((sound->block & 7) << 2) | 0x20;
\r
1449 inst = &sound->inst;
\r
1451 if (!(inst->mSus | inst->cSus))
\r
1454 Quit("SDL_ALPlaySound() - Bad instrument");
\r
1457 SDL_AlSetFXInst(&alZeroInst); // DEBUG
\r
1458 SDL_AlSetFXInst(inst);
\r
1464 ///////////////////////////////////////////////////////////////////////////
\r
1466 // SDL_ALSoundService() - Plays the next sample out through the AdLib card
\r
1468 ///////////////////////////////////////////////////////////////////////////
\r
1471 SDL_ALSoundService(void)
\r
1479 alOut(alFreqH + 0,0);
\r
1482 alOut(alFreqL + 0,s);
\r
1483 alOut(alFreqH + 0,alBlock);
\r
1486 if (!(--alLengthLeft))
\r
1488 (long)alSound = 0;
\r
1489 alOut(alFreqH + 0,0);
\r
1490 SDL_SoundFinished();
\r
1498 SDL_ALService(void)
\r
1506 while (sqHackLen && (sqHackTime <= alTimeCount))
\r
1509 sqHackTime = alTimeCount + *sqHackPtr++;
\r
1519 sqHackPtr = (word far *)sqHack;
\r
1520 sqHackLen = sqHackSeqLen;
\r
1521 alTimeCount = sqHackTime = 0;
\r
1526 ///////////////////////////////////////////////////////////////////////////
\r
1528 // SDL_ShutAL() - Shuts down the AdLib card for sound effects
\r
1530 ///////////////////////////////////////////////////////////////////////////
\r
1537 alOut(alEffects,0);
\r
1538 alOut(alFreqH + 0,0);
\r
1539 SDL_AlSetFXInst(&alZeroInst);
\r
1545 ///////////////////////////////////////////////////////////////////////////
\r
1547 // SDL_CleanAL() - Totally shuts down the AdLib card
\r
1549 ///////////////////////////////////////////////////////////////////////////
\r
1558 alOut(alEffects,0);
\r
1559 for (i = 1;i < 0xf5;i++)
\r
1565 ///////////////////////////////////////////////////////////////////////////
\r
1567 // SDL_StartAL() - Starts up the AdLib card for sound effects
\r
1569 ///////////////////////////////////////////////////////////////////////////
\r
1574 alOut(alEffects,alFXReg);
\r
1575 SDL_AlSetFXInst(&alZeroInst);
\r
1578 ///////////////////////////////////////////////////////////////////////////
\r
1580 // SDL_DetectAdLib() - Determines if there's an AdLib (or SoundBlaster
\r
1581 // emulating an AdLib) present
\r
1583 ///////////////////////////////////////////////////////////////////////////
\r
1585 SDL_DetectAdLib(void)
\r
1587 byte status1,status2;
\r
1590 alOut(4,0x60); // Reset T1 & T2
\r
1591 alOut(4,0x80); // Reset IRQ
\r
1592 status1 = readstat();
\r
1593 alOut(2,0xff); // Set timer 1
\r
1594 alOut(4,0x21); // Start timer 1
\r
1596 SDL_Delay(TimerDelay100);
\r
1605 status2 = readstat();
\r
1609 if (((status1 & 0xe0) == 0x00) && ((status2 & 0xe0) == 0xc0))
\r
1611 for (i = 1;i <= 0xf5;i++) // Zero all the registers
\r
1614 alOut(1,0x20); // Set WSE=1
\r
1615 alOut(8,0); // Set CSM=0 & SEL=0
\r
1624 ///////////////////////////////////////////////////////////////////////////
\r
1626 // SDL_t0Service() - My timer 0 ISR which handles the different timings and
\r
1627 // dispatches to whatever other routines are appropriate
\r
1629 ///////////////////////////////////////////////////////////////////////////
\r
1630 static void interrupt
\r
1631 SDL_t0Service(void)
\r
1633 static word count = 1;
\r
1635 #if 1 // for debugging
\r
1636 asm mov dx,STATUS_REGISTER_1
\r
1638 asm mov dx,ATR_INDEX
\r
1639 asm mov al,ATR_OVERSCAN
\r
1641 asm mov al,4 // red
\r
1647 if ((MusicMode == smm_AdLib) || (DigiMode == sds_SoundSource))
\r
1651 // if (!(++count & 7))
\r
1652 if (!(++count % 10))
\r
1656 if (SoundUserHook)
\r
1659 // if (!(count & 3))
\r
1662 switch (SoundMode)
\r
1668 SDL_ALSoundService();
\r
1675 if (!(++count & 1))
\r
1679 if (SoundUserHook)
\r
1682 switch (SoundMode)
\r
1688 SDL_ALSoundService();
\r
1693 asm mov ax,[WORD PTR TimerCount]
\r
1694 asm add ax,[WORD PTR TimerDivisor]
\r
1695 asm mov [WORD PTR TimerCount],ax
\r
1697 t0OldService(); // If we overflow a word, time to call old int handler
\r
1700 outportb(0x20,0x20); // Ack the interrupt
\r
1703 #if 1 // for debugging
\r
1704 asm mov dx,STATUS_REGISTER_1
\r
1706 asm mov dx,ATR_INDEX
\r
1707 asm mov al,ATR_OVERSCAN
\r
1709 asm mov al,3 // blue
\r
1711 asm mov al,0x20 // normal
\r
1717 ////////////////////////////////////////////////////////////////////////////
\r
1719 // SDL_ShutDevice() - turns off whatever device was being used for sound fx
\r
1721 ////////////////////////////////////////////////////////////////////////////
\r
1723 SDL_ShutDevice(void)
\r
1725 switch (SoundMode)
\r
1734 SoundMode = sdm_Off;
\r
1737 ///////////////////////////////////////////////////////////////////////////
\r
1739 // SDL_CleanDevice() - totally shuts down all sound devices
\r
1741 ///////////////////////////////////////////////////////////////////////////
\r
1743 SDL_CleanDevice(void)
\r
1745 if ((SoundMode == sdm_AdLib) || (MusicMode == smm_AdLib))
\r
1749 ///////////////////////////////////////////////////////////////////////////
\r
1751 // SDL_StartDevice() - turns on whatever device is to be used for sound fx
\r
1753 ///////////////////////////////////////////////////////////////////////////
\r
1755 SDL_StartDevice(void)
\r
1757 switch (SoundMode)
\r
1763 SoundNumber = SoundPriority = 0;
\r
1766 // Public routines
\r
1768 ///////////////////////////////////////////////////////////////////////////
\r
1770 // SD_SetSoundMode() - Sets which sound hardware to use for sound effects
\r
1772 ///////////////////////////////////////////////////////////////////////////
\r
1774 SD_SetSoundMode(SDMode mode)
\r
1776 boolean result = false;
\r
1782 if ((mode == sdm_AdLib) && !AdLibPresent)
\r
1788 NeedsDigitized = false;
\r
1792 tableoffset = STARTPCSOUNDS;
\r
1793 NeedsDigitized = false;
\r
1799 tableoffset = STARTADLIBSOUNDS;
\r
1800 NeedsDigitized = false;
\r
1809 if (result && (mode != SoundMode))
\r
1814 SoundTable = (word *)(&audiosegs[tableoffset]);
\r
1816 SDL_StartDevice();
\r
1819 SDL_SetTimerSpeed();
\r
1824 ///////////////////////////////////////////////////////////////////////////
\r
1826 // SD_SetMusicMode() - sets the device to use for background music
\r
1828 ///////////////////////////////////////////////////////////////////////////
\r
1830 SD_SetMusicMode(SMMode mode)
\r
1832 boolean result = false;
\r
1834 SD_FadeOutMusic();
\r
1835 while (SD_MusicPlaying())
\r
1841 NeedsMusic = false;
\r
1847 NeedsMusic = true;
\r
1856 SDL_SetTimerSpeed();
\r
1861 ///////////////////////////////////////////////////////////////////////////
\r
1863 // SD_Startup() - starts up the Sound Mgr
\r
1864 // Detects all additional sound hardware and installs my ISR
\r
1866 ///////////////////////////////////////////////////////////////////////////
\r
1877 ssIsTandy = false;
\r
1878 ssNoCheck = false;
\r
1879 alNoCheck = false;
\r
1880 sbNoCheck = false;
\r
1881 sbNoProCheck = false;
\r
1883 for (i = 1;i < _argc;i++)
\r
1885 switch (US_CheckParm(_argv[i],ParmStrings))
\r
1887 case 0: // No AdLib detection
\r
1890 case 1: // No SoundBlaster detection
\r
1893 case 2: // No SoundBlaster Pro detection
\r
1894 sbNoProCheck = true;
\r
1897 ssNoCheck = true; // No Sound Source detection
\r
1899 case 4: // Tandy Sound Source handling
\r
1902 case 5: // Sound Source present at LPT1
\r
1904 ssNoCheck = SoundSourcePresent = true;
\r
1906 case 6: // Sound Source present at LPT2
\r
1908 ssNoCheck = SoundSourcePresent = true;
\r
1910 case 7: // Sound Source present at LPT3
\r
1912 ssNoCheck = SoundSourcePresent = true;
\r
1918 SoundUserHook = 0;
\r
1920 t0OldService = getvect(8); // Get old timer 0 ISR
\r
1922 LocalTime = TimeCount = alTimeCount = 0;
\r
1924 SD_SetSoundMode(sdm_Off);
\r
1925 SD_SetMusicMode(smm_Off);
\r
1928 SoundSourcePresent = SDL_DetectSoundSource();
\r
1932 AdLibPresent = SDL_DetectAdLib();
\r
1933 if (AdLibPresent && !sbNoCheck)
\r
1936 char *env = getenv("BLASTER");
\r
1942 while (isspace(*env))
\r
1945 switch (toupper(*env))
\r
1948 temp = strtol(env + 1,&env,16);
\r
1952 && (temp <= 0x260)
\r
1953 && (!(temp & 0x00f))
\r
1955 port = (temp - 0x200) >> 4;
\r
1957 Quit("SD_Startup: Unsupported address value in BLASTER");
\r
1960 temp = strtol(env + 1,&env,10);
\r
1965 && (sbIntVectors[temp] != -1)
\r
1968 sbInterrupt = temp;
\r
1969 sbIntVec = sbIntVectors[sbInterrupt];
\r
1972 Quit("SD_Startup: Unsupported interrupt value in BLASTER");
\r
1975 temp = strtol(env + 1,&env,10);
\r
1976 if ((temp == 0) || (temp == 1) || (temp == 3))
\r
1977 SDL_SBSetDMA(temp);
\r
1979 Quit("SD_Startup: Unsupported DMA value in BLASTER");
\r
1982 while (isspace(*env))
\r
1984 while (*env && !isspace(*env))
\r
1990 SoundBlasterPresent = SDL_DetectSoundBlaster(port);
\r
1994 for (i = 0;i < 255;i++)
\r
1995 pcSoundLookup[i] = i * 60;
\r
1997 if (SoundBlasterPresent)
\r
2002 SD_Started = true;
\r
2005 ///////////////////////////////////////////////////////////////////////////
\r
2007 // SD_Default() - Sets up the default behaviour for the Sound Mgr whether
\r
2008 // the config file was present or not.
\r
2010 ///////////////////////////////////////////////////////////////////////////
\r
2012 SD_Default(boolean gotit,SDMode sd,SMMode sm)
\r
2014 boolean gotsd,gotsm;
\r
2016 gotsd = gotsm = gotit;
\r
2018 if (gotsd) // Make sure requested sound hardware is available
\r
2023 gotsd = AdLibPresent;
\r
2034 if (sd != SoundMode)
\r
2035 SD_SetSoundMode(sd);
\r
2038 if (gotsm) // Make sure requested music hardware is available
\r
2043 gotsm = AdLibPresent;
\r
2052 if (sm != MusicMode)
\r
2053 SD_SetMusicMode(sm);
\r
2056 ///////////////////////////////////////////////////////////////////////////
\r
2058 // SD_Shutdown() - shuts down the Sound Mgr
\r
2059 // Removes sound ISR and turns off whatever sound hardware was active
\r
2061 ///////////////////////////////////////////////////////////////////////////
\r
2071 SDL_CleanDevice();
\r
2073 if (SoundBlasterPresent)
\r
2076 if (SoundSourcePresent)
\r
2084 setvect(8,t0OldService);
\r
2088 SD_Started = false;
\r
2091 ///////////////////////////////////////////////////////////////////////////
\r
2093 // SD_SetUserHook() - sets the routine that the Sound Mgr calls every 1/70th
\r
2094 // of a second from its timer 0 ISR
\r
2096 ///////////////////////////////////////////////////////////////////////////
\r
2098 SD_SetUserHook(void (* hook)(void))
\r
2100 SoundUserHook = hook;
\r
2103 ///////////////////////////////////////////////////////////////////////////
\r
2105 // SD_PositionSound() - Sets up a stereo imaging location for the next
\r
2106 // sound to be played. Each channel ranges from 0 to 15.
\r
2108 ///////////////////////////////////////////////////////////////////////////
\r
2110 SD_PositionSound(int leftvol,int rightvol)
\r
2112 LeftPosition = leftvol;
\r
2113 RightPosition = rightvol;
\r
2114 nextsoundpos = true;
\r
2117 ///////////////////////////////////////////////////////////////////////////
\r
2119 // SD_PlaySound() - plays the specified sound on the appropriate hardware
\r
2121 ///////////////////////////////////////////////////////////////////////////
\r
2123 SD_PlaySound(soundnames sound)
\r
2126 SoundCommon far *s;
\r
2129 lp = LeftPosition;
\r
2130 rp = RightPosition;
\r
2132 RightPosition = 0;
\r
2134 ispos = nextsoundpos;
\r
2135 nextsoundpos = false;
\r
2140 s = MK_FP(SoundTable[sound],0);
\r
2141 if ((SoundMode != sdm_Off) && !s)
\r
2142 Quit("SD_PlaySound() - Uncached sound");
\r
2144 if ((DigiMode != sds_Off) && (DigiMap[sound] != -1))
\r
2146 if ((DigiMode == sds_PC) && (SoundMode == sdm_PC))
\r
2148 if (s->priority < SoundPriority)
\r
2151 SDL_PCStopSound();
\r
2153 SD_PlayDigitized(DigiMap[sound],lp,rp);
\r
2154 SoundPositioned = ispos;
\r
2155 SoundNumber = sound;
\r
2156 SoundPriority = s->priority;
\r
2162 if (DigiPriority && !DigiNumber)
\r
2165 Quit("SD_PlaySound: Priority without a sound");
\r
2169 if (s->priority < DigiPriority)
\r
2172 SD_PlayDigitized(DigiMap[sound],lp,rp);
\r
2173 SoundPositioned = ispos;
\r
2174 DigiNumber = sound;
\r
2175 DigiPriority = s->priority;
\r
2181 if (SoundMode == sdm_Off)
\r
2184 Quit("SD_PlaySound() - Zero length sound");
\r
2185 if (s->priority < SoundPriority)
\r
2188 switch (SoundMode)
\r
2191 SDL_PCPlaySound((void far *)s);
\r
2194 SDL_ALPlaySound((void far *)s);
\r
2198 SoundNumber = sound;
\r
2199 SoundPriority = s->priority;
\r
2204 ///////////////////////////////////////////////////////////////////////////
\r
2206 // SD_SoundPlaying() - returns the sound number that's playing, or 0 if
\r
2207 // no sound is playing
\r
2209 ///////////////////////////////////////////////////////////////////////////
\r
2211 SD_SoundPlaying(void)
\r
2213 boolean result = false;
\r
2215 switch (SoundMode)
\r
2218 result = pcSound? true : false;
\r
2221 result = alSound? true : false;
\r
2226 return(SoundNumber);
\r
2231 ///////////////////////////////////////////////////////////////////////////
\r
2233 // SD_StopSound() - if a sound is playing, stops it
\r
2235 ///////////////////////////////////////////////////////////////////////////
\r
2237 SD_StopSound(void)
\r
2240 SD_StopDigitized();
\r
2242 switch (SoundMode)
\r
2245 SDL_PCStopSound();
\r
2248 SDL_ALStopSound();
\r
2252 SoundPositioned = false;
\r
2254 SDL_SoundFinished();
\r
2257 ///////////////////////////////////////////////////////////////////////////
\r
2259 // SD_WaitSoundDone() - waits until the current sound is done playing
\r
2261 ///////////////////////////////////////////////////////////////////////////
\r
2263 SD_WaitSoundDone(void)
\r
2265 while (SD_SoundPlaying())
\r
2269 ///////////////////////////////////////////////////////////////////////////
\r
2271 // SD_MusicOn() - turns on the sequencer
\r
2273 ///////////////////////////////////////////////////////////////////////////
\r
2280 ///////////////////////////////////////////////////////////////////////////
\r
2282 // SD_MusicOff() - turns off the sequencer and any playing notes
\r
2284 ///////////////////////////////////////////////////////////////////////////
\r
2291 switch (MusicMode)
\r
2295 alOut(alEffects,0);
\r
2296 for (i = 0;i < sqMaxTracks;i++)
\r
2297 alOut(alFreqH + i + 1,0);
\r
2303 ///////////////////////////////////////////////////////////////////////////
\r
2305 // SD_StartMusic() - starts playing the music pointed to
\r
2307 ///////////////////////////////////////////////////////////////////////////
\r
2309 SD_StartMusic(MusicGroup far *music)
\r
2315 if (MusicMode == smm_AdLib)
\r
2317 sqHackPtr = sqHack = music->values;
\r
2318 sqHackSeqLen = sqHackLen = music->length;
\r
2327 ///////////////////////////////////////////////////////////////////////////
\r
2329 // SD_FadeOutMusic() - starts fading out the music. Call SD_MusicPlaying()
\r
2330 // to see if the fadeout is complete
\r
2332 ///////////////////////////////////////////////////////////////////////////
\r
2334 SD_FadeOutMusic(void)
\r
2336 switch (MusicMode)
\r
2339 // DEBUG - quick hack to turn the music off
\r
2345 ///////////////////////////////////////////////////////////////////////////
\r
2347 // SD_MusicPlaying() - returns true if music is currently playing, false if
\r
2350 ///////////////////////////////////////////////////////////////////////////
\r
2352 SD_MusicPlaying(void)
\r
2356 switch (MusicMode)
\r
2360 // DEBUG - not written
\r