1 //-------------------------------------------------------------------------
2 /*
3 Copyright (C) 1996, 2003 - 3D Realms Entertainment
4 Copyright (C) 2017-2019 Nuke.YKT
5 
6 This file is part of Duke Nukem 3D version 1.5 - Atomic Edition
7 
8 Duke Nukem 3D is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License
10 as published by the Free Software Foundation; either version 2
11 of the License, or (at your option) any later version.
12 
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16 
17 See the GNU General Public License for more details.
18 
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22 
23 Original Source: 1996 - Todd Replogle
24 Prepared for public release: 03/21/2003 - Charlie Wiederhold, 3D Realms
25 */
26 //-------------------------------------------------------------------------
27 
28 #include <conio.h>
29 #include <stdio.h>
30 #include <string.h>
31 #include "types.h"
32 #include "sndcards.h"
33 #include "fx_man.h"
34 #include "music.h"
35 #include "util_lib.h"
36 #include "duke3d.h"
37 
38 
39 #define LOUDESTVOLUME 150
40 
41 long backflag,numenvsnds;
42 
43 /*
44 ===================
45 =
46 = SoundStartup
47 =
48 ===================
49 */
50 
SoundStartup(void)51 void SoundStartup( void )
52    {
53    int32 status;
54 
55    // if they chose None lets return
56    if (FXDevice == NumSoundCards) return;
57 
58    // Do special Sound Blaster, AWE32 stuff
59    if (
60          ( FXDevice == SoundBlaster ) ||
61          ( FXDevice == Awe32 )
62       )
63       {
64       int MaxVoices;
65       int MaxBits;
66       int MaxChannels;
67 
68       status = FX_SetupSoundBlaster
69                   (
70                   BlasterConfig, (int *)&MaxVoices, (int *)&MaxBits, (int *)&MaxChannels
71                   );
72       }
73    else
74       {
75       status = FX_Ok;
76       }
77 
78    if ( status == FX_Ok )
79       {
80       if ( eightytwofifty && numplayers > 1)
81          {
82          status = FX_Init( FXDevice, min( NumVoices,4 ), 1, 8, 8000 );
83          }
84       else
85          {
86          status = FX_Init( FXDevice, NumVoices, NumChannels, NumBits, MixRate );
87          }
88       if ( status == FX_Ok )
89          {
90 
91          FX_SetVolume( FXVolume );
92          if (ReverseStereo == 1)
93             {
94             FX_SetReverseStereo(!FX_GetReverseStereo());
95             }
96          }
97       }
98    if ( status != FX_Ok )
99       {
100       Error( FX_ErrorString( FX_Error ));
101       }
102 
103    status = FX_SetCallBack( testcallback );
104 
105    if ( status != FX_Ok )
106       {
107       Error( FX_ErrorString( FX_Error ));
108       }
109    }
110 
111 /*
112 ===================
113 =
114 = SoundShutdown
115 =
116 ===================
117 */
118 
SoundShutdown(void)119 void SoundShutdown( void )
120    {
121    int32 status;
122 
123    // if they chose None lets return
124    if (FXDevice == NumSoundCards)
125       return;
126 
127    status = FX_Shutdown();
128    if ( status != FX_Ok )
129       {
130       Error( FX_ErrorString( FX_Error ));
131       }
132    }
133 
134 /*
135 ===================
136 =
137 = MusicStartup
138 =
139 ===================
140 */
141 
MusicStartup(void)142 void MusicStartup( void )
143    {
144    int32 status;
145 
146    // if they chose None lets return
147    if ((MusicDevice == NumSoundCards) || (eightytwofifty && numplayers > 1) )
148       return;
149 
150    // satisfy AWE32 and WAVEBLASTER stuff
151    BlasterConfig.Midi = MidiPort;
152 
153    // Do special Sound Blaster, AWE32 stuff
154    if (
155          ( FXDevice == SoundBlaster ) ||
156          ( FXDevice == Awe32 )
157       )
158       {
159       int MaxVoices;
160       int MaxBits;
161       int MaxChannels;
162 
163       FX_SetupSoundBlaster
164                   (
165                   BlasterConfig, (int *)&MaxVoices, (int *)&MaxBits, (int *)&MaxChannels
166                   );
167       }
168    status = MUSIC_Init( MusicDevice, MidiPort );
169 
170    if ( status == MUSIC_Ok )
171       {
172       MUSIC_SetVolume( MusicVolume );
173       }
174    else
175    {
176        Error(MUSIC_ErrorString(MUSIC_ErrorCode));
177    }
178 }
179 
180 /*
181 ===================
182 =
183 = MusicShutdown
184 =
185 ===================
186 */
187 
MusicShutdown(void)188 void MusicShutdown( void )
189    {
190    int32 status;
191 
192    // if they chose None lets return
193    if ((MusicDevice == NumSoundCards) || (eightytwofifty && numplayers > 1) )
194       return;
195 
196    status = MUSIC_Shutdown();
197    if ( status != MUSIC_Ok )
198       {
199       Error( MUSIC_ErrorString( MUSIC_ErrorCode ));
200       }
201    }
202 
USRHOOKS_GetMem(char ** ptr,unsigned long size)203 int USRHOOKS_GetMem(char **ptr, unsigned long size )
204 {
205    *ptr = SafeMalloc(size);
206 
207    if (*ptr == NULL)
208       return(USRHOOKS_Error);
209 
210    return( USRHOOKS_Ok);
211 
212 }
213 
USRHOOKS_FreeMem(char * ptr)214 int USRHOOKS_FreeMem(char *ptr)
215 {
216    SafeFree(ptr);
217    return( USRHOOKS_Ok);
218 }
219 
220 char menunum=0;
221 
intomenusounds(void)222 void intomenusounds(void)
223 {
224     short i;
225     short menusnds[] =
226     {
227         390,
228         390,
229         390,
230         390,
231         390,
232         390,
233         390,
234         390,
235         390,
236         390,
237         390,
238         390,
239         390,
240         390,
241         390,
242         390,
243         390,
244     };
245     sound(menusnds[menunum++]);
246     menunum %= 17;
247 }
248 
playmusic(char * fn)249 void playmusic(char *fn)
250 {
251     short      fp;
252     long        l;
253 }
254 
loadsound(unsigned short num)255 char loadsound(unsigned short num)
256 {
257     long   fp, l;
258 
259     if(num >= NUM_SOUNDS || SoundToggle == 0) return 0;
260     if (FXDevice == NumSoundCards) return 0;
261 
262     fp = kopen4load(sounds[num],loadfromgrouponly);
263     if(fp == -1)
264     {
265         sprintf(&fta_quotes[113][0],"Sound %s(#%ld) not found.",sounds[num],num);
266         FTA(113,&ps[myconnectindex]);
267         return 0;
268     }
269 
270     l = kfilelength( fp );
271     soundsiz[num] = l;
272 
273     Sound[num].lock = 200;
274 
275     allocache((long *)&Sound[num].ptr,l,&Sound[num].lock);
276     kread( fp, Sound[num].ptr , l);
277     kclose( fp );
278     return 1;
279 }
280 
xyzsound(short num,short i,long x,long y,long z)281 int xyzsound(short num,short i,long x,long y,long z)
282 {
283     long sndist, cx, cy, cz, j,k;
284     short pitche,pitchs,cs;
285     int voice, sndang, ca, pitch;
286 
287 //    if(num != 358) return 0;
288 
289     if( num >= NUM_SOUNDS ||
290         FXDevice == NumSoundCards ||
291         ( (soundm[num]&8) && ud.lockout ) ||
292         SoundToggle == 0 ||
293         Sound[num].num > 3 ||
294         FX_VoiceAvailable(soundpr[num]) == 0 ||
295         (ps[myconnectindex].timebeforeexit > 0 && ps[myconnectindex].timebeforeexit <= 26*3) ||
296         ps[myconnectindex].gm&MODE_MENU) return -1;
297 
298     if( soundm[num]&4 )
299     {
300         if(VoiceToggle==0 || (ud.multimode > 1 && PN == APLAYER && sprite[i].yvel != screenpeek && ud.coop != 1) ) return -1;
301 
302         for(j=0;j<NUM_SOUNDS;j++)
303           for(k=0;k<Sound[j].num;k++)
304             if( (Sound[j].num > 0) && (soundm[j]&4) )
305               return -1;
306     }
307 
308     cx = ps[screenpeek].oposx;
309     cy = ps[screenpeek].oposy;
310     cz = ps[screenpeek].oposz;
311     cs = ps[screenpeek].cursectnum;
312     ca = ps[screenpeek].ang+ps[screenpeek].look_ang;
313 
314     sndist = FindDistance3D((cx-x),(cy-y),(cz-z)>>4);
315 
316     if( i >= 0 && (soundm[num]&16) == 0 && PN == MUSICANDSFX && SLT < 999 && (sector[SECT].lotag&0xff) < 9 )
317         sndist = divscale14(sndist,(SHT+1));
318 
319     pitchs = soundps[num];
320     pitche = soundpe[num];
321     cx = klabs(pitche-pitchs);
322 
323     if(cx)
324     {
325         if( pitchs < pitche )
326              pitch = pitchs + ( rand()%cx );
327         else pitch = pitche + ( rand()%cx );
328     }
329     else pitch = pitchs;
330 
331     sndist += soundvo[num];
332     if( sndist && PN != MUSICANDSFX && !cansee(cx,cy,cz-(24<<8),cs,SX,SY,SZ-(24<<8),SECT) )
333         sndist += sndist>>2;
334 
335     switch(num)
336     {
337         case PIPEBOMB_EXPLODE:
338         case LASERTRIP_EXPLODE:
339         case RPG_EXPLODE:
340             if(sndist > (6144) )
341                 sndist = 6144;
342             if(sector[ps[screenpeek].cursectnum].lotag == 2)
343                 pitch -= 1024;
344             break;
345         default:
346             if(sector[ps[screenpeek].cursectnum].lotag == 2 && (soundm[num]&4) == 0)
347                 pitch = -768;
348             if( sndist > 31444 && PN != MUSICANDSFX)
349                 return -1;
350             break;
351     }
352 
353 
354     if( Sound[num].num > 0 && PN != MUSICANDSFX )
355     {
356         if( SoundOwner[num][0].i == i ) stopsound(num);
357         else if( Sound[num].num > 1 ) stopsound(num);
358         else if( badguy(&sprite[i]) && sprite[i].extra <= 0 ) stopsound(num);
359     }
360 
361     if( PN == APLAYER && sprite[i].yvel == screenpeek )
362     {
363         sndang = 0;
364         sndist = 0;
365     }
366     else
367     {
368         sndang = 2048 + ca - getangle(cx-x,cy-y);
369         sndang &= 2047;
370     }
371 
372     if(Sound[num].ptr == 0) { if( loadsound(num) == 0 ) return 0; }
373     else
374     {
375        if (Sound[num].lock < 200)
376           Sound[num].lock = 200;
377        else Sound[num].lock++;
378     }
379 
380     if( soundm[num]&16 ) sndist = 0;
381 
382     if(sndist < ((255-LOUDESTVOLUME)<<6) )
383         sndist = ((255-LOUDESTVOLUME)<<6);
384 
385     if( soundm[num]&1 )
386     {
387         unsigned short start;
388 
389         if(Sound[num].num > 0) return -1;
390 
391         start = *(unsigned short *)(Sound[num].ptr + 0x14);
392 
393         if(*Sound[num].ptr == 'C')
394             voice = FX_PlayLoopedVOC( Sound[num].ptr, start, start + soundsiz[num],
395                     pitch,sndist>>6,sndist>>6,0,soundpr[num],num);
396         else
397             voice = FX_PlayLoopedWAV( Sound[num].ptr, start, start + soundsiz[num],
398                     pitch,sndist>>6,sndist>>6,0,soundpr[num],num);
399     }
400     else
401     {
402         if( *Sound[num].ptr == 'C')
403             voice = FX_PlayVOC3D( Sound[ num ].ptr,pitch,sndang>>6,sndist>>6, soundpr[num], num );
404         else voice = FX_PlayWAV3D( Sound[ num ].ptr,pitch,sndang>>6,sndist>>6, soundpr[num], num );
405     }
406 
407     if ( voice > FX_Ok )
408     {
409         SoundOwner[num][Sound[num].num].i = i;
410         SoundOwner[num][Sound[num].num].voice = voice;
411         Sound[num].num++;
412     }
413     else Sound[num].lock--;
414     return (voice);
415 }
416 
sound(short num)417 void sound(short num)
418 {
419     short pitch,pitche,pitchs,cx;
420     int voice;
421     long start;
422 
423     if (FXDevice == NumSoundCards) return;
424     if(SoundToggle==0) return;
425     if(VoiceToggle==0 && (soundm[num]&4) ) return;
426     if( (soundm[num]&8) && ud.lockout ) return;
427     if(FX_VoiceAvailable(soundpr[num]) == 0) return;
428 
429     pitchs = soundps[num];
430     pitche = soundpe[num];
431     cx = klabs(pitche-pitchs);
432 
433     if(cx)
434     {
435         if( pitchs < pitche )
436              pitch = pitchs + ( rand()%cx );
437         else pitch = pitche + ( rand()%cx );
438     }
439     else pitch = pitchs;
440 
441     if(Sound[num].ptr == 0) { if( loadsound(num) == 0 ) return; }
442     else
443     {
444        if (Sound[num].lock < 200)
445           Sound[num].lock = 200;
446        else Sound[num].lock++;
447     }
448 
449     if( soundm[num]&1 )
450     {
451         if(*Sound[num].ptr == 'C')
452         {
453             start = (long)*(unsigned short *)(Sound[num].ptr + 0x14);
454             voice = FX_PlayLoopedVOC( Sound[num].ptr, start, start + soundsiz[num],
455                     pitch,LOUDESTVOLUME,LOUDESTVOLUME,LOUDESTVOLUME,soundpr[num],num);
456         }
457         else
458         {
459             start = (long)*(unsigned short *)(Sound[num].ptr + 0x14);
460             voice = FX_PlayLoopedWAV( Sound[num].ptr, start, start + soundsiz[num],
461                     pitch,LOUDESTVOLUME,LOUDESTVOLUME,LOUDESTVOLUME,soundpr[num],num);
462         }
463     }
464     else
465     {
466         if(*Sound[num].ptr == 'C')
467             voice = FX_PlayVOC3D( Sound[ num ].ptr, pitch,0,255-LOUDESTVOLUME,soundpr[num], num );
468         else
469             voice = FX_PlayWAV3D( Sound[ num ].ptr, pitch,0,255-LOUDESTVOLUME,soundpr[num], num );
470     }
471 
472     if(voice > FX_Ok) return;
473     Sound[num].lock--;
474 }
475 
spritesound(unsigned short num,short i)476 int spritesound(unsigned short num, short i)
477 {
478     if(num >= NUM_SOUNDS) return -1;
479     return xyzsound(num,i,SX,SY,SZ);
480 }
481 
stopsound(short num)482 void stopsound(short num)
483 {
484     if(Sound[num].num > 0)
485     {
486         FX_StopSound(SoundOwner[num][Sound[num].num-1].voice);
487         testcallback(num);
488     }
489 }
490 
stopenvsound(short num,short i)491 void stopenvsound(short num,short i)
492 {
493     short j, k;
494 
495     if(Sound[num].num > 0)
496     {
497         k = Sound[num].num;
498         for(j=0;j<k;j++)
499            if(SoundOwner[num][j].i == i)
500         {
501             FX_StopSound(SoundOwner[num][j].voice);
502             break;
503         }
504     }
505 }
506 
pan3dsound(void)507 void pan3dsound(void)
508 {
509     long sndist, sx, sy, sz, cx, cy, cz;
510     short sndang,ca,j,k,i,cs;
511 
512     numenvsnds = 0;
513 
514     if(ud.camerasprite == -1)
515     {
516         cx = ps[screenpeek].oposx;
517         cy = ps[screenpeek].oposy;
518         cz = ps[screenpeek].oposz;
519         cs = ps[screenpeek].cursectnum;
520         ca = ps[screenpeek].ang+ps[screenpeek].look_ang;
521     }
522     else
523     {
524         cx = sprite[ud.camerasprite].x;
525         cy = sprite[ud.camerasprite].y;
526         cz = sprite[ud.camerasprite].z;
527         cs = sprite[ud.camerasprite].sectnum;
528         ca = sprite[ud.camerasprite].ang;
529     }
530 
531     for(j=0;j<NUM_SOUNDS;j++) for(k=0;k<Sound[j].num;k++)
532     {
533         i = SoundOwner[j][k].i;
534 
535         sx = sprite[i].x;
536         sy = sprite[i].y;
537         sz = sprite[i].z;
538 
539         if( PN == APLAYER && sprite[i].yvel == screenpeek)
540         {
541             sndang = 0;
542             sndist = 0;
543         }
544         else
545         {
546             sndang = 2048 + ca - getangle(cx-sx,cy-sy);
547             sndang &= 2047;
548             sndist = FindDistance3D((cx-sx),(cy-sy),(cz-sz)>>4);
549             if( i >= 0 && (soundm[j]&16) == 0 && PN == MUSICANDSFX && SLT < 999 && (sector[SECT].lotag&0xff) < 9 )
550                 sndist = divscale14(sndist,(SHT+1));
551         }
552 
553         sndist += soundvo[j];
554 
555         if( sndist && PN != MUSICANDSFX && !cansee(cx,cy,cz-(24<<8),cs,sx,sy,sz-(24<<8),SECT) )
556             sndist += sndist>>2;
557 
558         if(PN == MUSICANDSFX && SLT < 999)
559             numenvsnds++;
560 
561         switch(j)
562         {
563             case PIPEBOMB_EXPLODE:
564             case LASERTRIP_EXPLODE:
565             case RPG_EXPLODE:
566                 if(sndist > (6144)) sndist = (6144);
567                 break;
568             default:
569                 if( sndist > 31444 && PN != MUSICANDSFX)
570                 {
571                     stopsound(j);
572                     continue;
573                 }
574         }
575 
576         if(Sound[j].ptr == 0 && loadsound(j) == 0 ) continue;
577         if( soundm[j]&16 ) sndist = 0;
578 
579         if(sndist < ((255-LOUDESTVOLUME)<<6) )
580             sndist = ((255-LOUDESTVOLUME)<<6);
581 
582         FX_Pan3D(SoundOwner[j][k].voice,sndang>>6,sndist>>6);
583     }
584 }
585 
testcallback(long num)586 void testcallback(long num)
587 {
588     int tempi,tempj,tempk;
589 
590         if(num < 0)
591         {
592             if(lumplockbyte[-num] >= 200)
593                 lumplockbyte[-num]--;
594             return;
595         }
596 
597         if(Sound[num].num > 0)
598         {
599             tempk = Sound[num].num;
600 
601             if( (soundm[num]&16) == 0)
602                 for(tempj=0;tempj<tempk;tempj++)
603             {
604                 tempi = SoundOwner[num][tempj].i;
605                 if(sprite[tempi].picnum == MUSICANDSFX && sector[sprite[tempi].sectnum].lotag < 3 && sprite[tempi].lotag < 999)
606                 {
607                     hittype[tempi].temp_data[0] = 0;
608                     if( (tempj + 1) < tempk )
609                     {
610                         SoundOwner[num][tempj].voice = SoundOwner[num][tempk-1].voice;
611                         SoundOwner[num][tempj].i     = SoundOwner[num][tempk-1].i;
612                     }
613                     break;
614                 }
615             }
616 
617             Sound[num].num--;
618             SoundOwner[num][tempk-1].i = -1;
619         }
620 
621         Sound[num].lock--;
622 }
623 
clearsoundlocks(void)624 void clearsoundlocks(void)
625 {
626     long i;
627 
628     for(i=0;i<NUM_SOUNDS;i++)
629         if(Sound[i].lock >= 200)
630             Sound[i].lock = 199;
631 
632     for(i=0;i<11;i++)
633         if(lumplockbyte[i] >= 200)
634             lumplockbyte[i] = 199;
635 }
636 
637