1 /* Reconstructed Commander Keen 4-6 Source Code
\r
2 * Copyright (C) 2021 K1n9_Duk3
\r
4 * This file is primarily based on:
\r
5 * Catacomb 3-D Source Code
\r
6 * Copyright (C) 1993-2014 Flat Rock Software
\r
8 * This program is free software; you can redistribute it and/or modify
\r
9 * it under the terms of the GNU General Public License as published by
\r
10 * the Free Software Foundation; either version 2 of the License, or
\r
11 * (at your option) any later version.
\r
13 * This program is distributed in the hope that it will be useful,
\r
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\r
16 * GNU General Public License for more details.
\r
18 * You should have received a copy of the GNU General Public License along
\r
19 * with this program; if not, write to the Free Software Foundation, Inc.,
\r
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
\r
25 // ID_SD.c - Sound Manager
\r
27 // By Jason Blochowiak
\r
31 // This module handles dealing with generating sound on the appropriate
\r
34 // Depends on: User Mgr (for parm checking)
\r
38 // SoundSourcePresent - Sound Source thingie present?
\r
39 // SoundBlasterPresent - SoundBlaster card present?
\r
40 // AdLibPresent - AdLib card present?
\r
41 // SoundMode - What device is used for sound effects
\r
42 // (Use SM_SetSoundMode() to set)
\r
43 // MusicMode - What device is used for music
\r
44 // (Use SM_SetMusicMode() to set)
\r
46 // NeedsDigitized - load digitized sounds?
\r
47 // NeedsMusic - load music?
\r
50 #pragma hdrstop // Wierdo thing with MUSE
\r
54 #ifdef _MUSE_ // Will be defined in ID_Types.h
\r
57 #include "ID_HEADS.H"
\r
62 #define SDL_SoundFinished() {SoundNumber = SoundPriority = 0;}
\r
64 // Macros for AdLib stuff
\r
65 #define selreg(n) outportb(0x388,n)
\r
66 #define writereg(n) outportb(0x389,n)
\r
67 #define readstat() inportb(0x388)
\r
70 boolean SoundSourcePresent,SoundBlasterPresent,AdLibPresent,QuietFX,
\r
71 NeedsDigitized,NeedsMusic;
\r
76 word *SoundTable; // Really * _seg *SoundTable, but that don't work
\r
80 // Internal variables
\r
81 static boolean SD_Started;
\r
82 static boolean TimerDone;
\r
83 static word TimerVal,TimerDelay10,TimerDelay25,TimerDelay100;
\r
84 static longword TimerDivisor,TimerCount;
\r
85 static char *ParmStrings[] =
\r
91 static void (*SoundUserHook)(void);
\r
92 static word SoundNumber,SoundPriority;
\r
93 static void interrupt (*t0OldService)(void);
\r
94 //static word t0CountTable[] = {8,8,8,8,40,40};
\r
95 static long LocalTime;
\r
97 // PC Sound variables
\r
98 static byte pcLastSample,far *pcSound;
\r
99 static longword pcLengthLeft;
\r
100 static word pcSoundLookup[255];
\r
103 static boolean alNoCheck;
\r
104 static byte far *alSound;
\r
105 static word alBlock;
\r
106 static longword alLengthLeft;
\r
107 static longword alTimeCount;
\r
108 static Instrument alZeroInst;
\r
110 // This table maps channel numbers to carrier and modulator op cells
\r
111 static byte carriers[9] = { 3, 4, 5,11,12,13,19,20,21},
\r
112 modifiers[9] = { 0, 1, 2, 8, 9,10,16,17,18},
\r
113 // This table maps percussive voice numbers to op cells
\r
114 pcarriers[5] = {19,0xff,0xff,0xff,0xff},
\r
115 pmodifiers[5] = {16,17,18,20,21};
\r
117 // Sequencer variables
\r
118 static boolean sqActive;
\r
119 static word alFXReg;
\r
120 static ActiveTrack *tracks[sqMaxTracks],
\r
121 mytracks[sqMaxTracks];
\r
122 static word sqMode,sqFadeStep;
\r
123 static word far *sqHack,far *sqHackPtr,sqHackLen,sqHackSeqLen;
\r
124 static long sqHackTime;
\r
126 // Internal routines
\r
128 ///////////////////////////////////////////////////////////////////////////
\r
130 // SDL_SetTimer0() - Sets system timer 0 to the specified speed
\r
132 ///////////////////////////////////////////////////////////////////////////
\r
135 SDL_SetTimer0(word speed)
\r
137 #ifndef TPROF // If using Borland's profiling, don't screw with the timer
\r
138 outportb(0x43,0x36); // Change timer 0
\r
139 outportb(0x40,speed);
\r
140 outportb(0x40,speed >> 8);
\r
141 TimerDivisor = speed;
\r
143 TimerDivisor = 0x10000;
\r
147 ///////////////////////////////////////////////////////////////////////////
\r
149 // SDL_SetIntsPerSec() - Uses SDL_SetTimer0() to set the number of
\r
150 // interrupts generated by system timer 0 per second
\r
152 ///////////////////////////////////////////////////////////////////////////
\r
154 SDL_SetIntsPerSec(word ints)
\r
156 SDL_SetTimer0(1192030 / ints);
\r
159 ///////////////////////////////////////////////////////////////////////////
\r
161 // SDL_TimingService() - Used by SDL_InitDelay() to determine a timing
\r
162 // value for the current system that we're running on
\r
164 ///////////////////////////////////////////////////////////////////////////
\r
165 static void interrupt
\r
166 SDL_TimingService(void)
\r
171 outportb(0x20,0x20); // Ack interrupt
\r
175 ///////////////////////////////////////////////////////////////////////////
\r
177 // SDL_InitDelay() - Sets up TimerDelay's for SDL_Delay()
\r
179 ///////////////////////////////////////////////////////////////////////////
\r
181 SDL_InitDelay(void)
\r
186 setvect(8,SDL_TimingService); // Set to my timer 0 ISR
\r
188 SDL_SetIntsPerSec(1000); // Time 1ms
\r
190 for (i = 0,timer = 0;i < 10;i++) // Do timing test 10 times
\r
192 asm xor dx,dx // Zero DX
\r
193 asm mov cx,0xffff // Put starting value in CX
\r
194 asm mov [TimerDone],cx // TimerDone = false - 1
\r
196 asm or [TimerDone],0
\r
197 asm jnz startloop // Make sure we're at the start
\r
199 asm test [TimerDone],1 // See if TimerDone flag got hit
\r
200 asm jnz done // Yep - drop out of the loop
\r
204 if (0xffff - TimerVal > timer)
\r
205 timer = 0xffff - TimerVal;
\r
207 timer += timer / 2; // Use some slop
\r
208 TimerDelay10 = timer / (1000 / 10);
\r
209 TimerDelay25 = timer / (1000 / 25);
\r
210 TimerDelay100 = timer / (1000 / 100);
\r
212 SDL_SetTimer0(0); // Reset timer 0
\r
214 setvect(8,t0OldService); // Set back to old ISR
\r
217 ///////////////////////////////////////////////////////////////////////////
\r
219 // SDL_Delay() - Delays the specified amount of time
\r
221 ///////////////////////////////////////////////////////////////////////////
\r
223 SDL_Delay(word delay)
\r
230 asm test [TimerDone],0 // Useless code - just for timing equivilency
\r
241 ///////////////////////////////////////////////////////////////////////////
\r
243 // SDL_PCPlaySound() - Plays the specified sound on the PC speaker
\r
245 ///////////////////////////////////////////////////////////////////////////
\r
251 SDL_PCPlaySound(PCSound far *sound)
\r
257 pcLengthLeft = sound->common.length;
\r
258 pcSound = sound->data;
\r
263 ///////////////////////////////////////////////////////////////////////////
\r
265 // SDL_PCStopSound() - Stops the current sound playing on the PC Speaker
\r
267 ///////////////////////////////////////////////////////////////////////////
\r
273 SDL_PCStopSound(void)
\r
280 asm in al,0x61 // Turn the speaker off
\r
281 asm and al,0xfd // ~2
\r
287 ///////////////////////////////////////////////////////////////////////////
\r
289 // SDL_PCService() - Handles playing the next sample in a PC sound
\r
291 ///////////////////////////////////////////////////////////////////////////
\r
293 SDL_PCService(void)
\r
301 if (s != pcLastSample)
\r
307 if (s) // We have a frequency!
\r
309 t = pcSoundLookup[s];
\r
312 asm mov al,0xb6 // Write to channel 2 (speaker) timer
\r
315 asm out 42h,al // Low byte
\r
317 asm out 42h,al // High byte
\r
319 asm in al,0x61 // Turn the speaker & gate on
\r
323 else // Time for some silence
\r
325 asm in al,0x61 // Turn the speaker & gate off
\r
326 asm and al,0xfc // ~3
\r
333 if (!(--pcLengthLeft))
\r
336 SDL_SoundFinished();
\r
341 ///////////////////////////////////////////////////////////////////////////
\r
343 // SDL_ShutPC() - Turns off the pc speaker
\r
345 ///////////////////////////////////////////////////////////////////////////
\r
354 asm in al,0x61 // Turn the speaker & gate off
\r
355 asm and al,0xfc // ~3
\r
363 ///////////////////////////////////////////////////////////////////////////
\r
365 // alOut(n,b) - Puts b in AdLib card register n
\r
367 ///////////////////////////////////////////////////////////////////////////
\r
369 alOut(byte n,byte b)
\r
378 SDL_Delay(TimerDelay10);
\r
395 SDL_Delay(TimerDelay25);
\r
440 ///////////////////////////////////////////////////////////////////////////
\r
442 // SDL_SetInstrument() - Puts an instrument into a generator
\r
444 ///////////////////////////////////////////////////////////////////////////
\r
446 SDL_SetInstrument(int track,int which,Instrument far *inst,boolean percussive)
\r
452 c = pcarriers[which];
\r
453 m = pmodifiers[which];
\r
457 c = carriers[which];
\r
458 m = modifiers[which];
\r
461 tracks[track - 1]->inst = *inst;
\r
462 tracks[track - 1]->percussive = percussive;
\r
464 alOut(m + alChar,inst->mChar);
\r
465 alOut(m + alScale,inst->mScale);
\r
466 alOut(m + alAttack,inst->mAttack);
\r
467 alOut(m + alSus,inst->mSus);
\r
468 alOut(m + alWave,inst->mWave);
\r
470 // Most percussive instruments only use one cell
\r
473 alOut(c + alChar,inst->cChar);
\r
474 alOut(c + alScale,inst->cScale);
\r
475 alOut(c + alAttack,inst->cAttack);
\r
476 alOut(c + alSus,inst->cSus);
\r
477 alOut(c + alWave,inst->cWave);
\r
480 alOut(which + alFeedCon,inst->nConn); // DEBUG - I think this is right
\r
484 ///////////////////////////////////////////////////////////////////////////
\r
486 // SDL_ALStopSound() - Turns off any sound effects playing through the
\r
489 ///////////////////////////////////////////////////////////////////////////
\r
495 SDL_ALStopSound(void)
\r
501 alOut(alFreqH + 0,0);
\r
507 SDL_AlSetFXInst(Instrument far *inst)
\r
510 byte scale; // added for "quiet AdLib" mode
\r
514 alOut(m + alChar,inst->mChar);
\r
515 alOut(m + alScale,inst->mScale);
\r
516 alOut(m + alAttack,inst->mAttack);
\r
517 alOut(m + alSus,inst->mSus);
\r
518 alOut(m + alWave,inst->mWave);
\r
519 alOut(c + alChar,inst->cChar);
\r
521 // quiet AdLib code:
\r
522 scale = inst->cScale;
\r
525 scale = 0x3F-scale;
\r
526 scale = (scale>>1) + (scale>>2); // basically 'scale *= 0.75;'
\r
527 scale = 0x3F-scale;
\r
529 alOut(c + alScale,scale);
\r
532 alOut(c + alScale,inst->cScale);
\r
534 alOut(c + alAttack,inst->cAttack);
\r
535 alOut(c + alSus,inst->cSus);
\r
536 alOut(c + alWave,inst->cWave);
\r
537 // DEBUG!!! - I just put this in
\r
538 // alOut(alFeedCon,inst->nConn);
\r
541 ///////////////////////////////////////////////////////////////////////////
\r
543 // SDL_ALPlaySound() - Plays the specified sound on the AdLib card
\r
545 ///////////////////////////////////////////////////////////////////////////
\r
551 SDL_ALPlaySound(AdLibSound far *sound)
\r
553 Instrument far *inst;
\r
560 alLengthLeft = sound->common.length;
\r
561 alSound = sound->data;
\r
562 alBlock = ((sound->block & 7) << 2) | 0x20;
\r
563 inst = &sound->inst;
\r
565 if (!(inst->mSus | inst->cSus))
\r
568 Quit("SDL_ALPlaySound() - Bad instrument");
\r
571 SDL_AlSetFXInst(inst);
\r
576 ///////////////////////////////////////////////////////////////////////////
\r
578 // SDL_ALSoundService() - Plays the next sample out through the AdLib card
\r
580 ///////////////////////////////////////////////////////////////////////////
\r
582 SDL_ALSoundService(void)
\r
590 alOut(alFreqH + 0,0);
\r
593 alOut(alFreqL + 0,s);
\r
594 alOut(alFreqH + 0,alBlock);
\r
597 if (!(--alLengthLeft))
\r
600 alOut(alFreqH + 0,0);
\r
601 SDL_SoundFinished();
\r
607 ///////////////////////////////////////////////////////////////////////////
\r
609 // SDL_SelectMeasure() - sets up sequencing variables for a given track
\r
611 ///////////////////////////////////////////////////////////////////////////
\r
613 SDL_SelectMeasure(ActiveTrack *track)
\r
615 track->seq = track->moods[track->mood];
\r
616 track->nextevent = 0;
\r
621 SDL_ALService(void)
\r
629 while (sqHackLen && (sqHackTime <= alTimeCount))
\r
632 sqHackTime = alTimeCount + *sqHackPtr++;
\r
642 sqHackPtr = (word far *)sqHack;
\r
643 sqHackLen = sqHackSeqLen;
\r
644 alTimeCount = sqHackTime = 0;
\r
648 ///////////////////////////////////////////////////////////////////////////
\r
650 // SDL_ShutAL() - Shuts down the AdLib card for sound effects
\r
652 ///////////////////////////////////////////////////////////////////////////
\r
659 alOut(alEffects,0);
\r
660 alOut(alFreqH + 0,0);
\r
661 SDL_AlSetFXInst(&alZeroInst);
\r
667 ///////////////////////////////////////////////////////////////////////////
\r
669 // SDL_CleanAL() - Totally shuts down the AdLib card
\r
671 ///////////////////////////////////////////////////////////////////////////
\r
680 alOut(alEffects,0);
\r
681 for (i = 1;i < 0xf5;i++)
\r
687 ///////////////////////////////////////////////////////////////////////////
\r
689 // SDL_StartAL() - Starts up the AdLib card for sound effects
\r
691 ///////////////////////////////////////////////////////////////////////////
\r
696 alOut(alEffects,alFXReg);
\r
697 SDL_AlSetFXInst(&alZeroInst);
\r
700 ///////////////////////////////////////////////////////////////////////////
\r
702 // SDL_DetectAdLib() - Determines if there's an AdLib (or SoundBlaster
\r
703 // emulating an AdLib) present
\r
705 ///////////////////////////////////////////////////////////////////////////
\r
707 SDL_DetectAdLib(boolean force)
\r
709 byte status1,status2;
\r
712 alOut(4,0x60); // Reset T1 & T2
\r
713 alOut(4,0x80); // Reset IRQ
\r
714 status1 = readstat();
\r
715 alOut(2,0xff); // Set timer 1
\r
716 alOut(4,0x21); // Start timer 1
\r
718 SDL_Delay(TimerDelay100);
\r
729 status2 = readstat();
\r
733 if (force || (((status1 & 0xe0) == 0x00) && ((status2 & 0xe0) == 0xc0)))
\r
735 for (i = 1;i <= 0xf5;i++) // Zero all the registers
\r
738 alOut(1,0x20); // Set WSE=1
\r
739 alOut(8,0); // Set CSM=0 & SEL=0
\r
747 ///////////////////////////////////////////////////////////////////////////
\r
749 // SDL_t0Service() - My timer 0 ISR which handles the different timings and
\r
750 // dispatches to whatever other routines are appropriate
\r
752 ///////////////////////////////////////////////////////////////////////////
\r
753 static void interrupt
\r
754 SDL_t0Service(void)
\r
756 static word count = 1;
\r
758 #if 0 // for debugging
\r
759 asm mov dx,STATUS_REGISTER_1
\r
761 asm mov dx,ATR_INDEX
\r
762 asm mov al,ATR_OVERSCAN
\r
764 asm mov al,4 // red
\r
770 if (MusicMode == smm_AdLib)
\r
773 if (!(++count & 7))
\r
788 SDL_ALSoundService();
\r
795 if (!(++count & 1))
\r
808 SDL_ALSoundService();
\r
813 asm mov ax,[WORD PTR TimerCount]
\r
814 asm add ax,[WORD PTR TimerDivisor]
\r
815 asm mov [WORD PTR TimerCount],ax
\r
817 t0OldService(); // If we overflow a word, time to call old int handler
\r
820 outportb(0x20,0x20); // Ack the interrupt
\r
823 #if 0 // for debugging
\r
824 asm mov dx,STATUS_REGISTER_1
\r
826 asm mov dx,ATR_INDEX
\r
827 asm mov al,ATR_OVERSCAN
\r
829 asm mov al,3 // blue
\r
831 asm mov al,0x20 // normal
\r
836 ////////////////////////////////////////////////////////////////////////////
\r
838 // SDL_ShutDevice() - turns off whatever device was being used for sound fx
\r
840 ////////////////////////////////////////////////////////////////////////////
\r
842 SDL_ShutDevice(void)
\r
853 SoundMode = sdm_Off;
\r
856 ///////////////////////////////////////////////////////////////////////////
\r
858 // SDL_CleanDevice() - totally shuts down all sound devices
\r
860 ///////////////////////////////////////////////////////////////////////////
\r
862 SDL_CleanDevice(void)
\r
864 if ((SoundMode == sdm_AdLib) || (MusicMode == smm_AdLib))
\r
868 ///////////////////////////////////////////////////////////////////////////
\r
870 // SDL_StartDevice() - turns on whatever device is to be used for sound fx
\r
872 ///////////////////////////////////////////////////////////////////////////
\r
874 SDL_StartDevice(void)
\r
882 SoundNumber = SoundPriority = 0;
\r
886 SDL_SetTimerSpeed(void)
\r
890 if (MusicMode == smm_AdLib)
\r
891 rate = TickBase * 8;
\r
893 rate = TickBase * 2;
\r
894 SDL_SetIntsPerSec(rate);
\r
899 ///////////////////////////////////////////////////////////////////////////
\r
901 // SD_SetSoundMode() - Sets which sound hardware to use for sound effects
\r
903 ///////////////////////////////////////////////////////////////////////////
\r
905 SD_SetSoundMode(SDMode mode)
\r
916 NeedsDigitized = false;
\r
920 tableoffset = STARTPCSOUNDS;
\r
921 NeedsDigitized = false;
\r
927 tableoffset = STARTADLIBSOUNDS;
\r
928 NeedsDigitized = false;
\r
938 if (result && (mode != SoundMode))
\r
943 SoundTable = (word *)(&audiosegs[tableoffset]);
\r
948 SDL_SetTimerSpeed();
\r
953 ///////////////////////////////////////////////////////////////////////////
\r
955 // SD_SetMusicMode() - sets the device to use for background music
\r
957 ///////////////////////////////////////////////////////////////////////////
\r
959 SD_SetMusicMode(SMMode mode)
\r
964 while (SD_MusicPlaying())
\r
970 NeedsMusic = false;
\r
988 SDL_SetTimerSpeed();
\r
993 ///////////////////////////////////////////////////////////////////////////
\r
995 // SD_Startup() - starts up the Sound Mgr
\r
996 // Detects all additional sound hardware and installs my ISR
\r
998 ///////////////////////////////////////////////////////////////////////////
\r
1010 ssIsTandy = false;
\r
1011 alNoCheck = false;
\r
1013 for (i = 1;i < _argc;i++)
\r
1015 switch (US_CheckParm(_argv[i],ParmStrings))
\r
1017 case 0: // No AdLib detection
\r
1028 SoundUserHook = 0;
\r
1030 t0OldService = getvect(8); // Get old timer 0 ISR
\r
1032 //SDL_InitDelay(); // SDL_InitDelay() uses t0OldService
\r
1034 setvect(8,SDL_t0Service); // Set to my timer 0 ISR
\r
1035 LocalTime = TimeCount = alTimeCount = 0;
\r
1037 SD_SetSoundMode(sdm_Off);
\r
1038 SD_SetMusicMode(smm_Off);
\r
1041 AdLibPresent = SDL_DetectAdLib(alForce);
\r
1043 for (i = 0;i < 255;i++)
\r
1044 pcSoundLookup[i] = i * 60;
\r
1046 SD_Started = true;
\r
1049 ///////////////////////////////////////////////////////////////////////////
\r
1051 // SD_Default() - Sets up the default behaviour for the Sound Mgr whether
\r
1052 // the config file was present or not.
\r
1054 ///////////////////////////////////////////////////////////////////////////
\r
1056 SD_Default(boolean gotit,SDMode sd,SMMode sm)
\r
1058 boolean gotsd,gotsm;
\r
1060 gotsd = gotsm = gotit;
\r
1062 if (gotsd) // Make sure requested sound hardware is available
\r
1067 gotsd = AdLibPresent;
\r
1078 if (sd != SoundMode)
\r
1079 SD_SetSoundMode(sd);
\r
1082 if (gotsm) // Make sure requested music hardware is available
\r
1086 case sdm_AdLib: // BUG: this should use smm_AdLib!
\r
1087 gotsm = AdLibPresent;
\r
1098 if (sm != MusicMode)
\r
1099 SD_SetMusicMode(sm);
\r
1102 ///////////////////////////////////////////////////////////////////////////
\r
1104 // SD_Shutdown() - shuts down the Sound Mgr
\r
1105 // Removes sound ISR and turns off whatever sound hardware was active
\r
1107 ///////////////////////////////////////////////////////////////////////////
\r
1116 SDL_CleanDevice();
\r
1123 setvect(8,t0OldService);
\r
1127 SD_Started = false;
\r
1130 ///////////////////////////////////////////////////////////////////////////
\r
1132 // SD_SetUserHook() - sets the routine that the Sound Mgr calls every 1/70th
\r
1133 // of a second from its timer 0 ISR
\r
1135 ///////////////////////////////////////////////////////////////////////////
\r
1137 SD_SetUserHook(void (* hook)(void))
\r
1139 // BUG: interrupts should be disabled while setting SoundUserHook!
\r
1140 SoundUserHook = hook;
\r
1143 ///////////////////////////////////////////////////////////////////////////
\r
1145 // SD_PlaySound() - plays the specified sound on the appropriate hardware
\r
1147 ///////////////////////////////////////////////////////////////////////////
\r
1149 SD_PlaySound(soundnames sound)
\r
1151 SoundCommon far *s;
\r
1153 if ((SoundMode == sdm_Off) /*|| (sound == -1)*/)
\r
1156 s = MK_FP(SoundTable[sound],0);
\r
1158 Quit("SD_PlaySound() - Uncached sound");
\r
1160 Quit("SD_PlaySound() - Zero length sound");
\r
1161 if (s->priority < SoundPriority)
\r
1164 switch (SoundMode)
\r
1167 SDL_PCPlaySound((void far *)s);
\r
1170 SDL_ALPlaySound((void far *)s);
\r
1174 SoundNumber = sound;
\r
1175 SoundPriority = s->priority;
\r
1178 ///////////////////////////////////////////////////////////////////////////
\r
1180 // SD_SoundPlaying() - returns the sound number that's playing, or 0 if
\r
1181 // no sound is playing
\r
1183 ///////////////////////////////////////////////////////////////////////////
\r
1185 SD_SoundPlaying(void)
\r
1187 boolean result = false;
\r
1189 switch (SoundMode)
\r
1192 result = pcSound? true : false;
\r
1195 result = alSound? true : false;
\r
1200 return(SoundNumber);
\r
1205 ///////////////////////////////////////////////////////////////////////////
\r
1207 // SD_StopSound() - if a sound is playing, stops it
\r
1209 ///////////////////////////////////////////////////////////////////////////
\r
1211 SD_StopSound(void)
\r
1213 switch (SoundMode)
\r
1216 SDL_PCStopSound();
\r
1219 SDL_ALStopSound();
\r
1223 SDL_SoundFinished();
\r
1226 ///////////////////////////////////////////////////////////////////////////
\r
1228 // SD_WaitSoundDone() - waits until the current sound is done playing
\r
1230 ///////////////////////////////////////////////////////////////////////////
\r
1232 SD_WaitSoundDone(void)
\r
1234 while (SD_SoundPlaying())
\r
1238 ///////////////////////////////////////////////////////////////////////////
\r
1240 // SD_MusicOn() - turns on the sequencer
\r
1242 ///////////////////////////////////////////////////////////////////////////
\r
1249 ///////////////////////////////////////////////////////////////////////////
\r
1251 // SD_MusicOff() - turns off the sequencer and any playing notes
\r
1253 ///////////////////////////////////////////////////////////////////////////
\r
1260 switch (MusicMode)
\r
1264 alOut(alEffects,0);
\r
1265 for (i = 0;i < sqMaxTracks;i++)
\r
1266 alOut(alFreqH + i + 1,0);
\r
1272 ///////////////////////////////////////////////////////////////////////////
\r
1274 // SD_StartMusic() - starts playing the music pointed to
\r
1276 ///////////////////////////////////////////////////////////////////////////
\r
1278 SD_StartMusic(MusicGroup far *music)
\r
1284 if (MusicMode == smm_AdLib)
\r
1286 sqHackPtr = sqHack = music->values;
\r
1287 sqHackSeqLen = sqHackLen = music->length;
\r
1296 ///////////////////////////////////////////////////////////////////////////
\r
1298 // SD_FadeOutMusic() - starts fading out the music. Call SD_MusicPlaying()
\r
1299 // to see if the fadeout is complete
\r
1301 ///////////////////////////////////////////////////////////////////////////
\r
1303 SD_FadeOutMusic(void)
\r
1305 switch (MusicMode)
\r
1308 // DEBUG - quick hack to turn the music off
\r
1314 ///////////////////////////////////////////////////////////////////////////
\r
1316 // SD_MusicPlaying() - returns true if music is currently playing, false if
\r
1319 ///////////////////////////////////////////////////////////////////////////
\r
1321 SD_MusicPlaying(void)
\r
1325 switch (MusicMode)
\r
1329 // DEBUG - not written
\r