1 /*
2 Copyright (C) 1994-1995 Apogee Software, Ltd.
3 
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8 
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 
13 See the GNU General Public License for more details.
14 
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18 
19 */
20 #include "rt_def.h"
21 #include "rt_sound.h"
22 #include "_rt_soun.h"
23 #include "fx_man.h"
24 #include "music.h"
25 #include "z_zone.h"
26 #include "w_wad.h"
27 #include "rt_main.h"
28 #include "rt_ted.h"
29 #include "rt_menu.h"
30 #include "rt_playr.h"
31 #include "rt_util.h"
32 #include "rt_rand.h"
33 #include "watcom.h"
34 #include <stdio.h>
35 #include <stdlib.h>
36 
37 #if PLATFORM_DOS
38 #include <mem.h>
39 #include <io.h>
40 #elif PLATFORM_UNIX
41 #include <unistd.h>
42 #endif
43 
44 #include "rt_cfg.h"
45 #include "isr.h"
46 #include "develop.h"
47 #include "rt_net.h"
48 
49 #include "rt_str.h"
50 
51 #if (SHAREWARE==0)
52 #include "snd_reg.h"
53 #else
54 #include "snd_shar.h"
55 #endif
56 //MED
57 #include "memcheck.h"
58 
59 // Local Variables
60 
61 static int soundstart;
62 static int soundtype;
63 int SD_Started=false;
64 static boolean PositionStored=false;
65 static int NumBadSounds=0;
66 static int remotestart;
67 static boolean SoundsRemapped = false;
68 
69 int musicnums[ 11 ] = {
70    -1, UltraSound, SoundBlaster, SoundMan16, ProAudioSpectrum,
71    Awe32, SoundScape, WaveBlaster, GenMidi, SoundCanvas, Adlib
72    };
73 
74 int fxnums[ 11 ] = {
75    -1, UltraSound, SoundBlaster, SoundMan16, ProAudioSpectrum,
76    Awe32, SoundScape, Adlib, SoundSource, TandySoundSource, PC
77    };
78 
79 void MU_SetupGUSInitFile( void );
80 
MUSIC_GetPosition(void)81 int MUSIC_GetPosition( void ) {
82    songposition pos;
83 
84    MUSIC_GetSongPosition( &pos );
85    return pos.milliseconds;
86 }
87 
MUSIC_SetPosition(int time)88 void MUSIC_SetPosition( int time ) {
89    MUSIC_SetSongTime( ( unsigned long )time );
90 }
91 
92 
93 //***************************************************************************
94 //
95 // SoundNumber
96 //
97 //***************************************************************************
98 
SoundNumber(int x)99 int SoundNumber ( int x )
100 {
101    if ((x>=SD_REMOTEM1SND) && (x<=SD_REMOTEM10SND))
102       return remotestart + x - SD_REMOTEM1SND;
103 //      sounds[x].snds[soundtype]+remotestart;
104    else
105       return sounds[x].snds[soundtype]+soundstart;
106 }
107 
108 
109 //***************************************************************************
110 //
111 // SD_MakeCacheable - Make a sound that has just finished playing cacheable again
112 //
113 //***************************************************************************
SD_MakeCacheable(unsigned long sndnum)114 void SD_MakeCacheable( unsigned long sndnum )
115 {
116    if (sndnum == (unsigned long) -1)
117       {
118       return;
119       }
120 
121    if (sndnum>=MAXSOUNDS)
122       {
123       SoftError ("Illegal sound value in SD_MakeCacheable value=%ld\n",sndnum);
124       return;
125       }
126    sounds[sndnum].count--;
127    if (sounds[sndnum].count>0)
128       return;
129    else
130       W_CacheLumpNum(SoundNumber(sndnum),PU_CACHE, CvtFixme, 1);
131 }
132 
133 #if 0
134 //***************************************************************************
135 //
136 // SD_PrintActive
137 //
138 //***************************************************************************
139 void SD_PrintActive ( void )
140 {
141    int i;
142 
143    myprintf("Active Sounds\n");
144    for (i=0;i<MAXSOUNDS;i++)
145       {
146       if (sounds[i].count>0)
147          {
148          myprintf("sound active #%ld\n",i);
149          }
150       }
151 }
152 #endif
153 
154 //***************************************************************************
155 //
156 // SD_SetupFXCard - Initialize sound Tables and start up sound card
157 //
158 //***************************************************************************
159 
SD_SetupFXCard(int * numvoices,int * numbits,int * numchannels)160 int SD_SetupFXCard ( int * numvoices, int * numbits, int * numchannels)
161 {
162    fx_device device;
163    int status;
164    int card;
165 
166    if (SD_Started==true)
167       SD_Shutdown();
168 
169    if ( ( FXMode < 0 ) || ( FXMode >= 11 ) )
170       {
171       return( 0 );
172       }
173 
174    card = fxnums[ FXMode ];
175    if (card==-1) // Check if it is off
176       return (0);
177    if ( ( card == SoundBlaster ) || ( card == Awe32 ) )
178       {
179       extern fx_blaster_config SBSettings;
180 
181       status = FX_SetupSoundBlaster( SBSettings, numvoices,
182          numbits, numchannels );
183       }
184    else
185       {
186       status=FX_SetupCard( card, &device );
187       if ( status == FX_Ok )
188          {
189          *numvoices=device.MaxVoices;
190          *numbits=device.MaxSampleBits;
191          *numchannels=device.MaxChannels;
192          }
193       }
194 
195    return (status);
196    }
197 
198 //***************************************************************************
199 //
200 // SD_Startup - Initialize sound Tables and start up sound card
201 //
202 //***************************************************************************
203 
SD_Startup(boolean bombonerror)204 int SD_Startup ( boolean bombonerror )
205 {
206    int status;
207    int card;
208    int voices;
209    int channels;
210    int bits;
211    int i;
212    extern boolean IS8250;
213 
214    if (SD_Started==true)
215       SD_Shutdown();
216 
217    if ( ( FXMode < 0 ) || ( FXMode >= 11 ) )
218       {
219       return( 0 );
220       }
221    card = fxnums[ FXMode ];
222    if (card==-1) // Check if it is off
223       return (0);
224 
225    switch (card)
226       {
227       case UltraSound:
228       case SoundBlaster:
229       case SoundMan16:
230       case ProAudioSpectrum:
231       case Awe32:
232       case SoundSource:
233       case TandySoundSource:
234       case SoundScape:
235          soundstart=W_GetNumForName("digistrt")+1;
236          soundtype=fx_digital;
237          break;
238       case Adlib:
239          soundstart=W_GetNumForName("adstart")+1;
240          soundtype=fx_muse;
241          break;
242       case PC:
243          soundstart=W_GetNumForName("pcstart")+1;
244          soundtype=fx_muse;
245          break;
246       default:
247          Error("FX: Unsupported Card number %d",FXMode);
248          break;
249       }
250 
251    if ( soundtype == fx_digital )
252       {
253       if ( SoundsRemapped == false )
254          {
255          for( i = 0; i < SD_LASTSOUND; i++ )
256             {
257             int snd;
258 
259             snd = sounds[ i ].snds[ fx_digital ];
260             if ( snd >= 0)
261                {
262                sounds[ i ].snds[ fx_digital ] = W_GetNumForName(
263                   W_GetNameForNum( snd + soundstart ) );
264                }
265             }
266          SoundsRemapped = true;
267          }
268       soundstart = 0;
269       }
270 
271    voices   = NumVoices;
272    channels = NumChannels;
273    bits     = NumBits;
274 
275    if ( IS8250 )
276       {
277       voices   = max( voices, 4 );
278       channels = 1;
279       bits     = 8;
280       }
281 
282 #ifdef DOS
283    status=FX_Init( card, voices, channels, bits, 11000 );
284 #else
285    status=FX_Init( card, voices, channels, bits, 11025 );
286 #endif
287 
288    if (status != FX_Ok)
289       {
290       if (bombonerror)
291          {
292          DeleteSoundFile ();
293          Error( "%s\n", FX_ErrorString( status ) );
294          }
295 
296       return (status);
297       }
298 
299    if (stereoreversed == true)
300       {
301       FX_SetReverseStereo(!FX_GetReverseStereo());
302       }
303 
304    FX_SetCallBack( SD_MakeCacheable );
305 
306    remotestart=W_GetNumForName("remostrt")+1;
307 
308    SD_Started=true;
309 
310    FX_SetVolume (FXvolume);
311 
312    return (0);
313 }
314 
315 //***************************************************************************
316 //
317 // SD_SoundOkay - checks to see if the sound is okay
318 //
319 //***************************************************************************
320 
SD_SoundOkay(int sndnum)321 boolean SD_SoundOkay ( int sndnum )
322 {
323    if (SD_Started==false)
324       return false;
325 
326    if (sndnum>=MAXSOUNDS)
327       Error ("Illegal sound number, sound number = %d\n",sndnum);
328 
329    if (SoundOffset(sndnum)==-1)
330       return false;
331 
332    if ( ( sounds[ sndnum ].flags & SD_PLAYONCE ) &&
333       ( SD_SoundActive( sounds[ sndnum ].prevhandle ) ) )
334       {
335       return false;
336       }
337 
338    return true;
339 }
340 
341 //***************************************************************************
342 //
343 // SD_PlayIt - Play a pre-setup sound
344 //
345 //***************************************************************************
346 
SD_PlayIt(int sndnum,int angle,int distance,int pitch)347 int SD_PlayIt ( int sndnum, int angle, int distance, int pitch )
348 {
349    int voice;
350    byte * snd;
351 
352 #if (DEVELOPMENT == 1)
353 #if (SOUNDTEST == 1)
354    SoftError("SOUND =%d \n",sndnum);
355 #endif
356 #endif
357 
358    if (!(sounds[sndnum].flags & SD_WRITE))
359       {
360       if (sounds[sndnum].count)
361          {
362          if (distance<=sounds[sndnum].prevdistance)
363             FX_StopSound(sounds[sndnum].prevhandle);
364          else
365             return 0;
366          }
367       }
368 
369    if ( !FX_VoiceAvailable( sounds[sndnum].priority ) )
370       {
371       return( 0 );
372       }
373 
374    sounds[sndnum].count++;
375 
376    snd=W_CacheLumpNum(SoundNumber(sndnum),PU_STATIC, CvtNull, 1);
377 
378 #ifdef DOS
379    if ( *snd == 'C' )
380       {
381       voice = FX_PlayVOC3D( snd, pitch, angle, distance,
382          sounds[sndnum].priority, (unsigned long) sndnum );
383       }
384    else
385       {
386       voice = FX_PlayWAV3D( snd, pitch, angle, distance,
387          sounds[sndnum].priority, (unsigned long) sndnum );
388       }
389 #else
390 /*
391    Oh boy.  The library used to implement these functions may need a
392    file size.  So, let's just hack these in!
393  */
394    if ( *snd == 'C' )
395       {
396       voice = FX_PlayVOC3D_ROTT( snd, W_LumpLength(SoundNumber(sndnum)),
397          pitch, angle, distance,
398          sounds[sndnum].priority, (unsigned long) sndnum );
399       }
400    else
401       {
402       voice = FX_PlayWAV3D_ROTT( snd, W_LumpLength(SoundNumber(sndnum)),
403          pitch, angle, distance,
404          sounds[sndnum].priority, (unsigned long) sndnum );
405       }
406 #endif
407 
408    if ( voice < FX_Ok )
409       {
410 #if (DEVELOPMENT == 1)
411 /*
412       if (MV_ErrorCode == MV_InvalidVOCFile)
413          {
414          Error("SD_PlayIt: Invalid VOC File snd=%p sndnum=%ld lump=%ld\n",snd,sndnum,SoundNumber(sndnum));
415          }
416 */
417       NumBadSounds++;
418       SoftError("SD_PlayIt: Error/Warning %s\n",FX_ErrorString( FX_Error ));
419       SoftError("BadSoundNumber %ld time %ld\n",NumBadSounds,GetTicCount());
420 #endif
421       SD_MakeCacheable( sndnum );
422 
423       return 0;
424       }
425 
426    NumBadSounds=0;
427 
428    if (!(sounds[sndnum].flags & SD_WRITE))
429       {
430       sounds[sndnum].prevhandle=voice;
431       sounds[sndnum].prevdistance=distance;
432       }
433    return voice;
434 }
435 
436 
437 //***************************************************************************
438 //
439 // SD_Play - Play a sample
440 //
441 //***************************************************************************
442 
SD_Play(int sndnum)443 int SD_Play ( int sndnum )
444 {
445    int voice;
446    int pitch;
447 
448    if ( SD_SoundOkay ( sndnum ) == false )
449       return 0;
450 
451    pitch = 0;
452 
453    if ( !( sounds[ sndnum ].flags & SD_PITCHSHIFTOFF ) )
454       {
455       pitch = PitchOffset();
456       }
457 
458    voice = SD_PlayIt ( sndnum, 0, 0, pitch );
459 
460    return voice;
461 
462 }
463 
464 //***************************************************************************
465 //
466 // SD_Play3D - Play a positioned sample
467 //
468 //***************************************************************************
469 
SD_Play3D(int sndnum,int angle,int distance)470 int SD_Play3D ( int sndnum, int angle, int distance )
471 {
472    int voice;
473    int pitch;
474 
475    if ( SD_SoundOkay ( sndnum ) == false )
476       return 0;
477 
478    pitch = 0;
479    if ( !( sounds[ sndnum ].flags & SD_PITCHSHIFTOFF ) )
480       {
481       pitch = PitchOffset();
482       }
483 
484    voice = SD_PlayIt ( sndnum, angle, distance, pitch );
485 
486    return voice;
487 
488 }
489 
490 //***************************************************************************
491 //
492 // SD_PlayPositionedSound - Play a positioned sample
493 //
494 //***************************************************************************
495 
SD_PlayPositionedSound(int sndnum,int px,int py,int x,int y)496 int SD_PlayPositionedSound ( int sndnum, int px, int py, int x, int y )
497 {
498    int voice;
499    int angle;
500    int distance;
501    int dx;
502    int dy;
503    int pitch;
504 
505    if ( SD_SoundOkay ( sndnum ) == false )
506       return 0;
507 
508    dx=(x-px);
509    dy=(py-y);
510 
511    distance=FindDistance(dx,dy) >> SD_DISTANCESHIFT;
512 
513    if (distance>255)
514       return 0;
515 
516    if (distance!=0)
517       {
518       angle = ( atan2_appx(dx,dy) & (FINEANGLES-1) ) >> 6;
519       }
520    else
521       {
522       angle=0;
523       }
524 
525    pitch = 0;
526 
527    if ( !( sounds[ sndnum ].flags & SD_PITCHSHIFTOFF ) )
528       {
529       pitch = PitchOffset();
530       }
531 
532    voice = SD_PlayIt ( sndnum, angle, distance, pitch );
533 
534    return voice;
535 
536 }
537 
538 //***************************************************************************
539 //
540 // SD_PlaySoundRTP - Play a positioned sample relative to the player
541 //
542 //***************************************************************************
543 
SD_PlaySoundRTP(int sndnum,int x,int y)544 int SD_PlaySoundRTP ( int sndnum, int x, int y )
545 {
546    int voice;
547    int angle;
548    int distance;
549    int dx;
550    int dy;
551    int pitch;
552 
553 
554    if ( SD_SoundOkay ( sndnum ) == false )
555       return 0;
556 
557    dx=(x-player->x);
558    dy=(player->y-y);
559 
560    distance=FindDistance(dx,dy) >> SD_DISTANCESHIFT;
561 
562    if (distance>255)
563       return 0;
564 
565    if (distance!=0)
566       {
567       angle = ( (player->angle - atan2_appx(dx,dy)) & (FINEANGLES-1) ) >> 6;
568       }
569    else
570       {
571       angle=0;
572       }
573 
574    pitch = 0;
575 
576    if ( !( sounds[ sndnum ].flags & SD_PITCHSHIFTOFF ) )
577       {
578       pitch = PitchOffset();
579       }
580 
581    voice = SD_PlayIt ( sndnum, angle, distance, pitch );
582 
583    return voice;
584 }
585 
586 //***************************************************************************
587 //
588 // SD_PlayPitchedSound - Play a pitched sample
589 //
590 //***************************************************************************
591 
SD_PlayPitchedSound(int sndnum,int volume,int pitch)592 int SD_PlayPitchedSound ( int sndnum, int volume, int pitch )
593 {
594    int voice;
595    int distance;
596 
597    if ( SD_SoundOkay ( sndnum ) == false )
598       return 0;
599 
600    distance = 255 - volume;
601 
602    voice = SD_PlayIt ( sndnum, 0, distance, pitch );
603 
604    return voice;
605 }
606 
607 //***************************************************************************
608 //
609 // SD_SetSoundPitch - sets the pitch of a sound
610 //
611 //***************************************************************************
612 
SD_SetSoundPitch(int sndnum,int pitch)613 void SD_SetSoundPitch ( int sndnum, int pitch )
614 {
615    int status;
616 
617    if (SD_Started==false)
618       return;
619 
620    if (!FX_SoundActive(sndnum))
621       return;
622 
623    status=FX_SetPitch( sndnum, pitch );
624    if (status != FX_Ok)
625       {
626 #if (DEVELOPMENT == 1)
627       SoftError("SD_SetSoundPitch : %s\n",FX_ErrorString( status ));
628 #endif
629       }
630 }
631 
632 //***************************************************************************
633 //
634 // SD_PanRTP Sound - pan a positioned sample relative to the player
635 //
636 //***************************************************************************
637 
SD_PanRTP(int handle,int x,int y)638 void SD_PanRTP ( int handle, int x, int y )
639 {
640    int angle;
641    int distance;
642    int dx;
643    int dy;
644    int status;
645 
646    if (SD_Started==false)
647       return;
648 
649    if (!FX_SoundActive(handle))
650       return;
651 
652    dx=(x-player->x);
653    dy=(player->y-y);
654 
655    distance=FindDistance(dx,dy) >> SD_DISTANCESHIFT;
656 
657    if (distance>255)
658       return;
659 
660    if (distance!=0)
661       {
662       angle = ( (player->angle - atan2_appx(dx,dy)) & (FINEANGLES-1) ) >> 6;
663       }
664    else
665       {
666       angle = 0;
667       }
668 
669    status = FX_Pan3D ( handle, angle, distance );
670 
671    if (status != FX_Ok)
672       {
673 #if (DEVELOPMENT == 1)
674       SoftError("SD_PanPositionedSound: %s\n",FX_ErrorString( status ));
675 #endif
676       }
677 }
678 
679 //***************************************************************************
680 //
681 // SD_SetPan - set the pan of a sample
682 //
683 //***************************************************************************
684 
SD_SetPan(int handle,int vol,int left,int right)685 void SD_SetPan ( int handle, int vol, int left, int right )
686 {
687    int status;
688 
689    if (SD_Started==false)
690       return;
691 
692    if (!FX_SoundActive(handle))
693       return;
694 
695    status=FX_SetPan( handle, vol, left, right );
696 
697    if (status != FX_Ok)
698       {
699 #if (DEVELOPMENT == 1)
700       SoftError("SD_SetPan: %s\n",FX_ErrorString( status ));
701 #endif
702       }
703 }
704 
705 //***************************************************************************
706 //
707 // SD_PanPositioned Sound - pan a positioned sample
708 //
709 //***************************************************************************
710 
SD_PanPositionedSound(int handle,int px,int py,int x,int y)711 void SD_PanPositionedSound ( int handle, int px, int py, int x, int y )
712 {
713    int angle;
714    int distance;
715    int dx;
716    int dy;
717    int status;
718 
719    if (SD_Started==false)
720       return;
721 
722    if (!FX_SoundActive(handle))
723       return;
724 
725    dx=(x-px);
726    dy=(py-y);
727 
728    distance=FindDistance(dx,dy) >> SD_DISTANCESHIFT;
729 
730    if (distance>255)
731       return;
732 
733    if (distance!=0)
734       {
735       angle = ( atan2_appx(dx,dy) & (FINEANGLES-1) ) >> 6;
736       }
737    else
738       {
739       angle = 0;
740       }
741 
742    status=FX_Pan3D( handle, angle, distance );
743 
744    if (status != FX_Ok)
745       {
746 #if (DEVELOPMENT == 1)
747       SoftError("SD_PanPositionedSound: %s\n",FX_ErrorString( status ));
748 #endif
749       }
750 }
751 
752 
753 //***************************************************************************
754 //
755 // SD_StopSound - Stop the current sound from playing
756 //
757 //***************************************************************************
758 
SD_StopSound(int handle)759 void SD_StopSound ( int handle )
760 {
761    int status;
762 
763    if (SD_Started==false)
764       return;
765 
766    status=FX_StopSound( handle);
767 
768    if (status != FX_Ok)
769       {
770 #if (DEVELOPMENT == 1)
771       SoftError("SD_StopSound: %s\n",FX_ErrorString( status ));
772 #endif
773       }
774 }
775 
776 //***************************************************************************
777 //
778 // SD_StopAllSounds - Stop All the sounds currently playing
779 //
780 //***************************************************************************
781 
SD_StopAllSounds(void)782 void  SD_StopAllSounds ( void )
783 {
784    int status;
785 
786    if (SD_Started==false)
787       return;
788 
789    status=FX_StopAllSounds();
790 
791    if (status != FX_Ok)
792       {
793 #if (DEVELOPMENT == 1)
794       SoftError("SD_StopAllSounds: %s\n",FX_ErrorString( status ));
795 #endif
796       }
797 }
798 
799 //***************************************************************************
800 //
801 // SD_SoundActive - See if a sound is active
802 //
803 //***************************************************************************
804 
SD_SoundActive(int handle)805 int SD_SoundActive ( int handle )
806 {
807    if (SD_Started==false)
808       {
809       return false;
810       }
811    else
812       {
813       return (FX_SoundActive(handle));
814       }
815 }
816 
817 //***************************************************************************
818 //
819 // SD_WaitSound - wait until a sound has finished
820 //
821 //***************************************************************************
SD_WaitSound(int handle)822 void SD_WaitSound ( int handle )
823 {
824    int time;
825 
826    IN_ClearKeysDown();
827 
828    while (FX_SoundActive(handle)!=0)
829       {
830       time=GetTicCount()+1;
831       while (time>GetTicCount()) {}
832       if ((LastScan) || IN_GetMouseButtons())
833          break;
834       }
835 }
836 
837 
838 //***************************************************************************
839 //
840 // SD_Shutdown - Shutdown the sound system
841 //
842 //***************************************************************************
843 
SD_Shutdown(void)844 void SD_Shutdown (void)
845 {
846    if (SD_Started==false)
847       return;
848 
849    FX_Shutdown();
850    SD_Started=false;
851 }
852 
853 
854 //***************************************************************************
855 //
856 // SD_PreCacheSound - PreCache sound
857 //
858 //***************************************************************************
859 
SD_PreCacheSound(int num)860 void SD_PreCacheSound ( int num )
861 {
862    if ( SD_SoundOkay ( num ) == false )
863       return;
864 
865    PreCacheLump(SoundNumber(num),PU_CACHESOUNDS+sounds[num].priority);
866 }
867 
868 //***************************************************************************
869 //
870 // SD_PreCacheSoundGroup - PreCache sound group
871 //
872 //***************************************************************************
873 
SD_PreCacheSoundGroup(int lo,int hi)874 void SD_PreCacheSoundGroup ( int lo, int hi )
875 {
876    int i;
877 
878    if (SD_Started==false)
879       return;
880 
881    for (i=lo;i<=hi;i++)
882       SD_PreCacheSound(i);
883 }
884 
885 
886 #if (SHAREWARE == 1)
887 #define MAXSONGS 18
888 static song_t rottsongs[MAXSONGS] = {
889       { loop_no,  song_apogee  ,"FANFARE2","Apogee Fanfare"},
890       { loop_yes, song_title   ,"RISE",    "Rise"},
891       { loop_yes, song_menu    ,"MMMENU",  "MMMenu"},
892       { loop_yes, song_christmas,"DEADLY", "Deadly Gentlemen"},
893       { loop_yes, song_elevator,"GOINGUP", "Going up?"},
894       { loop_yes, song_endlevel,"HOWDIDO", "How'd I do?"},
895       { loop_yes, song_secretmenu,"FISHPOLK","Fish Polka"},
896       { loop_yes, song_gameover,"YOUSUCK", "You Suck"},
897       { loop_yes, song_youwin  ,"WATZNEXT","Watz Next?"},
898       { loop_no,  song_gason   ,"GAZZ!",   "Gazz!"},
899       { loop_yes, song_level   ,"FASTWAY", "Goin' Down The Fast Way"},
900       { loop_yes, song_level   ,"MISTACHE","Mist Ache"},
901       { loop_yes, song_level   ,"OWW",     "Oww!!!"},
902       { loop_yes, song_level   ,"SMOKE",   "Smoke And Mirrors"},
903       { loop_yes, song_level   ,"SPRAY",   "Spray"},
904       { loop_yes, song_level   ,"RUNLIKE", "Run Like Smeg"},
905       { loop_yes, song_level   ,"SMOOTH",  "Havana Smooth"},
906       { loop_yes, song_level   ,"CHANT",   "Chant"},
907       };
908 #else
909 #define MAXSONGS 34
910 static song_t rottsongs[MAXSONGS] = {
911       { loop_no,  song_apogee  ,"FANFARE2","Apogee Fanfare"},
912       { loop_yes, song_title   ,"RISE",    "Rise"},
913       { loop_yes, song_menu    ,"MMMENU",  "MMMenu"},
914       { loop_yes, song_christmas,"DEADLY", "Deadly Gentlemen"},
915       { loop_yes, song_elevator,"GOINGUP", "Going up?"},
916       { loop_yes, song_secretmenu,"FISHPOLK","Fish Polka"},
917       { loop_yes, song_endlevel,"HOWDIDO", "How'd I do?"},
918       { loop_yes, song_gameover,"YOUSUCK", "You Suck"},
919       { loop_yes, song_cinematic2,"WATZNEXT","Watz Next?"},
920       { loop_no,  song_gason   ,"GAZZ!",   "Gazz!"},
921       { loop_yes, song_level   ,"FASTWAY", "Goin' Down The Fast Way"},
922       { loop_yes, song_level   ,"MISTACHE","Mist Ache"},
923       { loop_yes, song_level   ,"OWW",     "Oww!!!"},
924       { loop_yes, song_level   ,"SMOKE",   "Smoke And Mirrors"},
925       { loop_yes, song_level   ,"SPRAY",   "Spray"},
926       { loop_yes, song_level   ,"RUNLIKE", "Run Like Smeg"},
927       { loop_yes, song_level   ,"SMOOTH",  "Havana Smooth"},
928       { loop_yes, song_level   ,"CHANT",   "Chant"},
929       { loop_yes, song_level   ,"MEDIEV1A","Funeral of Queen Mary"},
930       { loop_yes, song_level   ,"TASKFORC","Task Force"},
931       { loop_yes, song_level   ,"KISSOFF", "KISS Off"},
932       { loop_yes, song_level   ,"RADAGIO", "Adagio For Strings"},
933       { loop_yes, song_level   ,"SHARDS",  "Shards"},
934       { loop_yes, song_level   ,"STAIRS",  "I Choose the Stairs"},
935       { loop_yes, song_level   ,"SUCKTHIS","Suck This"},
936       { loop_yes, song_level   ,"EXCALIBR","Excalibur"},
937       { loop_yes, song_level   ,"CCCOOL",   "CCCool"},
938       { loop_yes, song_level   ,"WORK_DAY","Work Day"},
939       { loop_yes, song_level   ,"WHERIZIT","Where Iz It?"},
940       { loop_no,  song_bossdie,"BOSSBLOW", "Boss Blow"},
941       { loop_yes, song_bosssee ,"HELLERO", "Hellero"},
942       { loop_yes, song_cinematic1,"EVINRUDE","Evin Rude"},
943       { loop_yes, song_youwin  ,"VICTORY", "Victory!"},
944       { loop_yes, song_dogend  ,"HERE_BOY","Here Boy"}
945       };
946 #endif
947 
948 static byte * currentsong;
949 static int MU_Started=false;
950 static int lastsongnumber=-1;
951 int storedposition=0;
952 
953 //****************************************************************************
954 //
955 // MU_JukeBoxMenu()
956 //
957 //****************************************************************************
958 
MU_PlayJukeBoxSong(int which)959 void MU_PlayJukeBoxSong
960    (
961    int which
962    )
963 
964    {
965    if ( ( MusicMode > 0 ) && ( MU_Started == true ) )
966       {
967       SetMenuHeader( rottsongs[ which ].songname );
968       MU_PlaySong( which );
969       }
970    }
971 
972 
973 //****************************************************************************
974 //
975 // MU_JukeBoxMenu()
976 //
977 //****************************************************************************
978 
MU_JukeBoxRedraw(void)979 void MU_JukeBoxRedraw
980    (
981    void
982    )
983 
984    {
985    if ( ( MusicMode > 0 ) && ( MU_Started == true ) )
986       {
987       SetMenuHeader( rottsongs[ lastsongnumber ].songname );
988       }
989    }
990 
991 
992 //****************************************************************************
993 //
994 // MU_JukeBoxMenu()
995 //
996 //****************************************************************************
997 
MU_JukeBoxMenu(void)998 void MU_JukeBoxMenu
999    (
1000    void
1001    )
1002 
1003    {
1004    char *SongNames[ MAXSONGS ];
1005    int   i;
1006 
1007    for( i = 0; i < MAXSONGS; i++ )
1008       {
1009       SongNames[ i ] = rottsongs[ i ].songname;
1010       }
1011 
1012    HandleMultiPageCustomMenu( SongNames, MAXSONGS, lastsongnumber,
1013       "Jukebox", MU_PlayJukeBoxSong, MU_JukeBoxRedraw, false );
1014 
1015    if ( rottsongs[ lastsongnumber ].loopflag == loop_no )
1016       {
1017       MU_StartSong(song_level);
1018       }
1019    }
1020 
1021 //***************************************************************************
1022 //
1023 // MusicStarted - see if the music is started
1024 //
1025 //***************************************************************************
MusicStarted(void)1026 boolean MusicStarted( void )
1027 {
1028    return MU_Started;
1029 }
1030 
1031 //***************************************************************************
1032 //
1033 // MU_Startup - Initialize music stuff
1034 //
1035 //***************************************************************************
1036 
MU_Startup(boolean bombonerror)1037 int MU_Startup ( boolean bombonerror )
1038 {
1039    int status;
1040    int card;
1041 
1042    if (MU_Started==true)
1043       {
1044       MU_StopSong();
1045       MU_Shutdown();
1046       }
1047    if ( ( MusicMode < 0 ) || ( MusicMode >= 11 ) )
1048       {
1049       return( 0 );
1050       }
1051    card = musicnums[ MusicMode ];
1052    if (card==-1) // Check if it is off
1053       return (0);
1054 
1055    if ( ( card == SoundBlaster ) || ( card == Awe32 ) || ( card == WaveBlaster ) )
1056       {
1057       if ( SD_Started == false )
1058          {
1059          extern fx_blaster_config SBSettings;
1060          int numvoices;
1061          int numbits;
1062          int numchannels;
1063 
1064          FX_SetupSoundBlaster( SBSettings, &numvoices,
1065             &numbits, &numchannels );
1066          }
1067       }
1068 
1069    if (card== UltraSound)
1070       {
1071       MU_SetupGUSInitFile();
1072       }
1073 
1074    status=MUSIC_Init( card, MidiAddress );
1075 
1076    if (status != MUSIC_Ok) {
1077       if (bombonerror)
1078          {
1079          DeleteSoundFile ();
1080          Error( "%s\n", MUSIC_ErrorString( status ) );
1081          }
1082       else
1083          return (status);
1084    }
1085 
1086    currentsong=0;
1087 
1088    MU_Started=true;
1089 
1090    MU_SetVolume (MUvolume);
1091 
1092    return (0);
1093 }
1094 
1095 //***************************************************************************
1096 //
1097 // MU_Shutdown - Shutdown the music system
1098 //
1099 //***************************************************************************
1100 
MU_Shutdown(void)1101 void MU_Shutdown (void)
1102 {
1103    if (MU_Started==false)
1104       return;
1105    MUSIC_Shutdown();
1106    MU_Started=false;
1107 }
1108 //***************************************************************************
1109 //
1110 // MU_SetupGUSInitFile - initialize GUS stuff
1111 //
1112 //***************************************************************************
1113 
MU_SetupGUSInitFile(void)1114 void MU_SetupGUSInitFile( void )
1115 {
1116    char filename[ 128 ];
1117 
1118    GetPathFromEnvironment( filename, ApogeePath, GUSMIDIINIFILE );
1119    if (access (filename, F_OK) != 0)
1120       {
1121       int lump;
1122 
1123       lump=W_GetNumForName("gusmidi");
1124 
1125       SaveFile (filename, W_CacheLumpNum(lump,PU_CACHE, CvtNull, 1), W_LumpLength(lump));
1126       }
1127 }
1128 
1129 //***************************************************************************
1130 //
1131 // MU_GetNumForType - returns number of song in rottsongs of specific type
1132 //
1133 //***************************************************************************
MU_GetNumForType(int type)1134 int MU_GetNumForType ( int type )
1135 {
1136    int i;
1137 
1138    for (i=0;i<MAXSONGS;i++)
1139       {
1140       if (rottsongs[i].songtype == type)
1141          return i;
1142       }
1143    Error("MU_GetNumForType: could not find song type in list\n");
1144    return -1;
1145 }
1146 
1147 
1148 //***************************************************************************
1149 //
1150 // MU_PlaySong - Play a specific song number
1151 //
1152 //***************************************************************************
1153 
MU_PlaySong(int num)1154 void MU_PlaySong ( int num )
1155 {
1156    int lump;
1157    int size;
1158 
1159    if (MU_Started==false)
1160       return;
1161 
1162    if (num<0)
1163       return;
1164 
1165    if (num>=MAXSONGS)
1166       Error("Song number out of range\n");
1167 
1168    MU_StopSong();
1169 
1170    lastsongnumber=num;
1171 
1172    lump = W_GetNumForName(rottsongs[num].lumpname);
1173    size = W_LumpLength(lump);
1174 
1175    currentsong=W_CacheLumpNum(lump,PU_STATIC, CvtFixme, 1);
1176 
1177 #ifdef PLATFORM_DOS
1178    if (rottsongs[num].loopflag == loop_yes)
1179       MUSIC_PlaySong(currentsong,size,MUSIC_LoopSong);
1180    else
1181       MUSIC_PlaySong(currentsong,size,MUSIC_PlayOnce);
1182 #else
1183    if (rottsongs[num].loopflag == loop_yes)
1184       MUSIC_PlaySongROTT(currentsong,size,MUSIC_LoopSong);
1185    else
1186       MUSIC_PlaySongROTT(currentsong,size,MUSIC_PlayOnce);
1187 #endif
1188 
1189    MU_SetVolume (MUvolume);
1190 }
1191 
1192 //***************************************************************************
1193 //
1194 // MU_StopSong - Play a specific song number
1195 //
1196 //***************************************************************************
1197 
MU_StopSong(void)1198 void MU_StopSong ( void )
1199 {
1200    if (MU_Started==false)
1201       return;
1202 
1203    MUSIC_StopSong ();
1204    if (currentsong)
1205       {
1206       W_CacheLumpName(rottsongs[lastsongnumber].lumpname,PU_CACHE, CvtFixme, 1);
1207       currentsong=0;
1208       }
1209 }
1210 
1211 //***************************************************************************
1212 //
1213 // MU_GetSongNumber - get current song number
1214 //
1215 //***************************************************************************
1216 
MU_GetSongNumber(void)1217 int MU_GetSongNumber ( void )
1218 {
1219    return lastsongnumber;
1220 }
1221 
1222 
1223 //***************************************************************************
1224 //
1225 // MU_FadeToSong - Fade to a specific song in a certain time
1226 //
1227 //***************************************************************************
1228 
MU_FadeToSong(int num,int time)1229 void MU_FadeToSong ( int num, int time )
1230 {
1231    int t;
1232 
1233    if (MU_Started==false)
1234       return;
1235 
1236    MU_FadeOut(time>>1);
1237 
1238    while (MU_FadeActive())
1239       {
1240       t=GetTicCount();
1241       while (GetTicCount()==t) {}
1242       }
1243 
1244    MU_FadeIn (num,time>>1);
1245 }
1246 
1247 //***************************************************************************
1248 //
1249 // MU_FadeIn - Fade in
1250 //
1251 //***************************************************************************
1252 
MU_FadeIn(int num,int time)1253 void MU_FadeIn ( int num, int time )
1254 {
1255    if (MU_Started==false)
1256       return;
1257 
1258    MUSIC_SetVolume(0);
1259    MU_PlaySong ( num );
1260    MUSIC_FadeVolume (MUvolume, time);
1261 }
1262 
1263 //***************************************************************************
1264 //
1265 // MU_FadeOut - Fade out
1266 //
1267 //***************************************************************************
1268 
MU_FadeOut(int time)1269 void MU_FadeOut ( int time )
1270 {
1271    if (MU_Started==false)
1272       return;
1273    if (!MUSIC_SongPlaying())
1274       {
1275 #if (DEVELOPMENT == 1)
1276       SoftError("Called FadeOut with no song playing\n");
1277 #endif
1278       return;
1279       }
1280    MUSIC_FadeVolume(0,time);
1281 }
1282 
1283 
1284 //***************************************************************************
1285 //
1286 // MU_StartSong - Start a context sensitive song
1287 //
1288 //***************************************************************************
1289 
MU_StartSong(int songtype)1290 void MU_StartSong ( int songtype )
1291 {
1292    int songnum;
1293 
1294    if (MU_Started==false)
1295       return;
1296 
1297    MU_StopSong();
1298 
1299    songnum = MU_GetNumForType ( songtype );
1300    switch (songtype)
1301       {
1302       case song_level:
1303          if (IsChristmas())
1304             {
1305             songnum = MU_GetNumForType ( song_christmas );
1306             }
1307          else
1308             {
1309             songnum += GetSongForLevel ();
1310             }
1311          break;
1312       }
1313    MU_PlaySong (songnum);
1314 }
1315 
1316 //***************************************************************************
1317 //
1318 // MU_StoreSongPostition - Save off Song Position
1319 //
1320 //***************************************************************************
1321 
MU_StoreSongPosition(void)1322 void MU_StoreSongPosition ( void )
1323 {
1324    if (MU_Started==false)
1325       return;
1326    PositionStored=true;
1327    storedposition=MUSIC_GetPosition();
1328 }
1329 
1330 //***************************************************************************
1331 //
1332 // MU_RestoreSongPostition - Save off Song Position
1333 //
1334 //***************************************************************************
1335 
MU_RestoreSongPosition(void)1336 void MU_RestoreSongPosition ( void )
1337 {
1338    if (MU_Started==false)
1339       return;
1340    if (PositionStored==false)
1341       return;
1342    PositionStored=false;
1343 
1344    MUSIC_SetPosition(storedposition);
1345 }
1346 
1347 //***************************************************************************
1348 //
1349 // MU_GetStoredPostition - Get Stored song Position
1350 //
1351 //***************************************************************************
1352 
MU_GetStoredPosition(void)1353 int MU_GetStoredPosition ( void )
1354 {
1355    if (PositionStored)
1356       return storedposition;
1357    else
1358       return -1;
1359 }
1360 
1361 //***************************************************************************
1362 //
1363 // MU_SetStoredPostition - Get Stored song Position
1364 //
1365 //***************************************************************************
1366 
MU_SetStoredPosition(int position)1367 void MU_SetStoredPosition ( int position )
1368 {
1369    if (MU_Started==false)
1370       return;
1371    if (position==-1)
1372       return;
1373    PositionStored=true;
1374    storedposition=position;
1375 }
1376 
1377 
1378 
1379 //***************************************************************************
1380 //
1381 // MU_GetSongPostition - Get Song Position
1382 //
1383 //***************************************************************************
1384 
MU_GetSongPosition(void)1385 int MU_GetSongPosition ( void )
1386 {
1387    if (MU_Started==false)
1388       return 0;
1389    return MUSIC_GetPosition();
1390 }
1391 
1392 //***************************************************************************
1393 //
1394 // MU_SetSongPostition - Set Song Position
1395 //
1396 //***************************************************************************
1397 
MU_SetSongPosition(int position)1398 void MU_SetSongPosition ( int position )
1399 {
1400    if (MU_Started==false)
1401       return;
1402    MUSIC_SetPosition(position);
1403 }
1404 
1405 //***************************************************************************
1406 //
1407 // MU_SaveMusic
1408 //
1409 //***************************************************************************
1410 
MU_SaveMusic(byte ** buf,int * size)1411 void MU_SaveMusic (byte ** buf, int * size)
1412 {
1413    int unitsize;
1414    byte *ptr;
1415    int vsize;
1416    int i;
1417 
1418    //
1419    // Size
1420    //
1421 
1422    unitsize=0;
1423 
1424 	unitsize+=sizeof(i);
1425 	unitsize+=sizeof(i);
1426 	unitsize+=sizeof(i);
1427 
1428 
1429    *size = unitsize;
1430    *buf = (byte *) SafeMalloc (*size);
1431 
1432    ptr = *buf;
1433 
1434    i=MU_GetSongNumber();
1435    if (rottsongs[i].songtype == song_menu)
1436       {
1437       i = MU_GetNumForType ( song_level );
1438       if (IsChristmas())
1439          {
1440          i = MU_GetNumForType ( song_christmas );
1441          }
1442       else
1443          {
1444          i += GetSongForLevel ();
1445          }
1446       vsize=sizeof(i);
1447       memcpy(ptr,&i,vsize);
1448       ptr+=vsize;
1449 
1450       i=MU_GetStoredPosition();
1451       vsize=sizeof(i);
1452       memcpy(ptr,&i,vsize);
1453       ptr+=vsize;
1454 
1455       i=-1;
1456       vsize=sizeof(i);
1457       memcpy(ptr,&i,vsize);
1458       ptr+=vsize;
1459       }
1460    else
1461       {
1462       vsize=sizeof(i);
1463       memcpy(ptr,&i,vsize);
1464       ptr+=vsize;
1465 
1466       i=MU_GetSongPosition();
1467       vsize=sizeof(i);
1468       memcpy(ptr,&i,vsize);
1469       ptr+=vsize;
1470 
1471       i=MU_GetStoredPosition();
1472       vsize=sizeof(i);
1473       memcpy(ptr,&i,vsize);
1474       ptr+=vsize;
1475       }
1476 }
1477 
1478 
1479 //***************************************************************************
1480 //
1481 // MU_LoadMusic
1482 //
1483 //***************************************************************************
1484 
MU_LoadMusic(byte * buf,int size)1485 void MU_LoadMusic (byte * buf, int size)
1486 {
1487    int unitsize;
1488    byte *ptr;
1489    int i;
1490    int songnumber;
1491    boolean differentsong=false;
1492    int vsize;
1493 
1494    //
1495    // Size
1496    //
1497 
1498    unitsize=0;
1499 
1500 	unitsize+=sizeof(i);
1501 	unitsize+=sizeof(i);
1502 	unitsize+=sizeof(i);
1503 
1504    if (size!=unitsize)
1505       Error("LoadMusic: Different number of parameters\n");
1506 
1507    ptr  = buf;
1508 
1509    vsize=sizeof(songnumber);
1510    memcpy(&songnumber,ptr,vsize);
1511    ptr+=vsize;
1512    if (MU_GetSongNumber () != songnumber)
1513       {
1514       MU_PlaySong(songnumber);
1515       differentsong=true;
1516       }
1517 
1518    vsize=sizeof(i);
1519    memcpy(&i,ptr,vsize);
1520    ptr+=vsize;
1521    if (differentsong==true)
1522       {
1523       MU_SetSongPosition(i);
1524       }
1525 
1526    vsize=sizeof(i);
1527    memcpy(&i,ptr,vsize);
1528    ptr+=vsize;
1529    MU_SetStoredPosition(i);
1530 
1531    // Check if game was saved with NOSOUND
1532 
1533    if (MU_GetSongNumber () != songnumber)
1534       {
1535       MU_StartSong ( song_level );
1536       }
1537 }
1538