]> icculus.org git repositories - btb/d2x.git/blob - main/songs.c
remove rcs tags
[btb/d2x.git] / main / songs.c
1 /*
2 THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
3 SOFTWARE CORPORATION ("PARALLAX").  PARALLAX, IN DISTRIBUTING THE CODE TO
4 END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
5 ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
6 IN USING, DISPLAYING,  AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
7 SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
8 FREE PURPOSES.  IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
9 CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES.  THE END-USER UNDERSTANDS
10 AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.
11 COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION.  ALL RIGHTS RESERVED.
12 */
13
14 /*
15  *
16  * Routines to manage the songs in Descent.
17  *
18  */
19
20
21 #ifdef HAVE_CONFIG_H
22 #include <conf.h>
23 #endif
24
25 #include <stdlib.h>
26 #include <stdio.h>
27 #include <string.h>
28 #include <ctype.h>
29 #if !defined(_MSC_VER) && !defined(macintosh)
30 #include <unistd.h>
31 #endif
32
33 #include "inferno.h"
34 #include "error.h"
35 #include "pstypes.h"
36 #include "args.h"
37 #include "songs.h"
38 #include "mono.h"
39 #include "cfile.h"
40 #include "digi.h"
41 #include "rbaudio.h"
42 #include "kconfig.h"
43 #include "timer.h"
44
45 song_info Songs[MAX_NUM_SONGS];
46 int Songs_initialized = 0;
47
48 #ifndef MACINTOSH
49 int Num_songs;
50 #endif
51
52 extern void digi_stop_current_song();
53
54 cvar_t Redbook_enabled = { "RedbookEnabled", "1", 1 };
55
56 //0 if redbook is no playing, else the track number
57 int Redbook_playing = 0;
58
59 #define NumLevelSongs (Num_songs - SONG_FIRST_LEVEL_SONG)
60
61 extern int CD_blast_mixer();
62
63 #ifndef MACINTOSH
64 #define REDBOOK_VOLUME_SCALE  (255/3)           //255 is MAX
65 #else
66 #define REDBOOK_VOLUME_SCALE    (255)
67 #endif
68
69 //takes volume in range 0..8
70 void set_redbook_volume(int volume)
71 {
72         #ifndef MACINTOSH
73         RBASetVolume(0);                // makes the macs sound really funny
74         #endif
75         RBASetVolume(volume*REDBOOK_VOLUME_SCALE/8);
76 }
77
78 extern char CDROM_dir[];
79
80 void songs_init()
81 {
82         int i;
83         char inputline[80+1];
84         CFILE * fp;
85
86         if ( Songs_initialized ) return;
87
88
89         #if !defined(MACINTOSH) && !defined(WINDOWS)    // don't crank it if on a macintosh!!!!!
90                 if (!FindArg("-nomixer"))
91                         CD_blast_mixer();   // Crank it!
92         #endif
93
94
95         if (cfexist("descent.sng")) {   // mac (demo?) datafiles don't have the .sng file
96                 fp = cfopen( "descent.sng", "rb" );
97                 if ( fp == NULL )
98                 {
99                         Error( "Couldn't open descent.sng" );
100                 }
101                 i = 0;
102                 while (cfgets(inputline, 80, fp ))
103                 {
104                         if ( strlen( inputline ) )
105                         {
106                                 Assert( i < MAX_NUM_SONGS );
107                                 sscanf( inputline, "%s %s %s",
108                                                 Songs[i].filename,
109                                                 Songs[i].melodic_bank_file,
110                                                 Songs[i].drum_bank_file );
111                                 //printf( "%d. '%s' '%s' '%s'\n",i,Songs[i].filename,Songs[i].melodic_bank_file,Songs[i].drum_bank_file );
112                                 i++;
113                         }
114                 }
115                 Num_songs = i;
116                 if (Num_songs <= SONG_FIRST_LEVEL_SONG)
117                         Error("Must have at least %d songs",SONG_FIRST_LEVEL_SONG+1);
118                 cfclose(fp);
119         }
120
121         Songs_initialized = 1;
122
123         //      RBA Hook
124                 if (FindArg("-noredbook"))
125                 {
126                         cvar_setint( &Redbook_enabled, 0 );
127                 }
128                 else    // use redbook
129                 {
130                         #ifndef __MSDOS__ // defined(WINDOWS) || defined(MACINTOSH)
131                                 RBAInit();
132                         #else
133                                 RBAInit(toupper(CDROM_dir[0]) - 'A');
134                         #endif
135
136                                 if (RBAEnabled())
137                         {
138                                 set_redbook_volume(Config_redbook_volume.intval);
139                                 RBARegisterCD();
140                         }
141                 }
142                 atexit(RBAStop);    // stop song on exit
143 }
144
145 #define FADE_TIME (f1_0/2)
146
147 //stop the redbook, so we can read off the CD
148 void songs_stop_redbook(void)
149 {
150         int old_volume = Config_redbook_volume.intval * REDBOOK_VOLUME_SCALE / 8;
151         fix old_time = timer_get_fixed_seconds();
152
153         if (Redbook_playing) {          //fade out volume
154                 int new_volume;
155                 do {
156                         fix t = timer_get_fixed_seconds();
157
158                         new_volume = fixmuldiv(old_volume,(FADE_TIME - (t-old_time)),FADE_TIME);
159
160                         if (new_volume < 0)
161                                 new_volume = 0;
162
163                         RBASetVolume(new_volume);
164
165                 } while (new_volume > 0);
166         }
167
168         RBAStop();                      // Stop CD, if playing
169
170         RBASetVolume(old_volume);       //restore volume
171
172         Redbook_playing = 0;            
173
174 }
175
176 //stop any songs - midi or redbook - that are currently playing
177 void songs_stop_all(void)
178 {
179         digi_stop_current_song();       // Stop midi song, if playing
180
181         songs_stop_redbook();                   // Stop CD, if playing
182 }
183
184 int force_rb_register=0;
185
186 void reinit_redbook()
187 {
188         #ifndef __MSDOS__ // defined(WINDOWS) || defined(MACINTOSH)
189                 RBAInit();
190         #else
191                 RBAInit(toupper(CDROM_dir[0]) - 'A');
192         #endif
193
194         if (RBAEnabled())
195         {
196                 set_redbook_volume(Config_redbook_volume.intval);
197                 RBARegisterCD();
198                 force_rb_register=0;
199         }
200 }
201
202
203 //returns 1 if track started sucessfully
204 //start at tracknum.  if keep_playing set, play to end of disc.  else
205 //play only specified track
206 int play_redbook_track(int tracknum,int keep_playing)
207 {
208         Redbook_playing = 0;
209
210         if (!RBAEnabled() && Redbook_enabled.intval && !FindArg("-noredbook"))
211                 reinit_redbook();
212
213         if (force_rb_register) {
214                 RBARegisterCD();                        //get new track list for new CD
215                 force_rb_register = 0;
216         }
217
218         if (Redbook_enabled.intval && RBAEnabled()) {
219                 int num_tracks = RBAGetNumberOfTracks();
220                 if (tracknum <= num_tracks)
221                         if (RBAPlayTracks(tracknum,keep_playing?num_tracks:tracknum))  {
222                                 Redbook_playing = tracknum;
223                         }
224         }
225
226         return (Redbook_playing != 0);
227 }
228
229
230 #if 0
231
232 #define REDBOOK_TITLE_TRACK         2
233 #define REDBOOK_CREDITS_TRACK       3
234 #define REDBOOK_FIRST_LEVEL_TRACK   (songs_haved2_cd()?4:1)
235
236 // songs_haved2_cd returns 1 if the descent 2 CD is in the drive and
237 // 0 otherwise
238 int songs_haved2_cd()
239 {
240         char temp[128],cwd[128];
241         
242         getcwd(cwd, 128);
243
244         strcpy(temp,CDROM_dir);
245
246         #ifndef MACINTOSH               //for PC, strip of trailing slash
247         if (temp[strlen(temp)-1] == '\\')
248                 temp[strlen(temp)-1] = 0;
249         #endif
250
251         if ( !chdir(temp) ) {
252                 chdir(cwd);
253                 return 1;
254         }
255
256         return 0;
257 }
258
259 #else
260
261
262 /* Redbook versions of 13 songs from Descent 1 as found on the Macintosh version.
263    All the same tracklist, but some versions have tracks mixed to different lengths
264  1:  Data
265  2:  Primitive Rage
266  3:  Outer Limits
267  4:  The Escape (aka Close Call)
268  5:  Ether in the Air (aka The Darkness of Space)
269  6:  Robotic Menace (aka Get It On)
270  7:  Virtual Tension (aka Fight)
271  8:  Time for the Big Guns (aka Death Lurks Beneath)
272  9:  Mystery Metal (aka C-4 Home Recipe)
273  10: Hydraulic Pressure (aka Escape)
274  11: Not That Button! (aka Backwards Time)
275  12: Industrial Accident (aka Crazyfactory)
276  13: Overdrive (aka Machine Gun)
277  14: A Big Problem (aka Insanity)
278  */
279 #define D1_DISCID_1         0xb60d990e
280 #define D1_DISCID_2         0xde0feb0e
281 #define D1_DISCID_3         0xb70ee40e
282
283 #define D1_RB_TITLE             2
284 #define D1_RB_BRIEFING          3
285 #define D1_RB_ENDLEVEL          4
286 #define D1_RB_ENDGAME           3
287 #define D1_RB_CREDITS           5
288 #define D1_RB_FIRST_LEVEL_SONG  6
289
290 /* Descent II
291  1:  Data
292  2:  Title
293  3:  Crawl
294  4:  Glut
295  5:  Gunner Down
296  6:  Cold Reality
297  7:  Ratzez
298  8:  Crush
299  9:  Untitled
300  10: Haunted (Instrumental Remix)
301  11: Are You Descent?
302  12: Techno Industry
303  13: Robot Jungle
304  */
305 #define D2_DISCID_1         0x22115710 // Mac version, has some extended versions and 3 bonus tracks
306 #define D2_DISCID_2         0xac0bc30d
307 #define D2_DISCID_3         0xc40c0a0d
308 #define D2_DISCID_4         0xc610080d
309 #define D2_DISCID_5         0xcc101b0d
310 #define D2_DISCID_6         0xd00bf30d
311 #define D2_DISCID_7         0xd2101d0d
312 #define D2_DISCID_8         0xd410070d
313 #define D2_DISCID_9         0xda10370d
314
315 #define D2_RB_TITLE            2
316 #define D2_RB_CREDITS          3
317 #define D2_RB_FIRST_LEVEL_SONG 4
318
319 /* Same as above, but all tracks shifted by one
320  1:  Data
321  2:  Data
322  3:  Title
323  4:  Crawl
324  5:  Glut
325  6:  Gunner Down
326  7:  Cold Reality
327  8:  Ratzez
328  9:  Crush
329  10: Untitled
330  11: Haunted (Instrumental Remix)
331  12: Are You Descent?
332  13: Techno Industry
333  14: Robot Jungle
334  */
335 #define D2_2_DISCID_1       0xe010a30e
336
337 #define D2_2_RB_TITLE               3
338 #define D2_2_RB_CREDITS             4
339 #define D2_2_RB_FIRST_LEVEL_SONG    5
340
341 /* Descent II: The Infinite Abyss
342  1:  Data
343  2:  Title
344  3:  Cold Reality - Extended Remix
345  4:  Crawl - Extended Remix
346  5:  Gunner Down - Extended Remix
347  6:  Ratzez - Extended Remix
348  7:  Techno Industry - Extended Remix
349  8:  Are You Descent? - Extended Remix
350  9:  Robot Jungle - Extended Remix
351  */
352 #define D2_IA_DISCID_1      0x7d0ff809
353 #define D2_IA_DISCID_2      0x8110ec09
354 #define D2_IA_DISCID_3      0x82104909
355 #define D2_IA_DISCID_4      0x85101d09
356 #define D2_IA_DISCID_5      0x87102209
357
358 #define D2_IA_RB_TITLE              2
359 #define D2_IA_RB_CREDITS            3
360 #define D2_IA_RB_FIRST_LEVEL_SONG   4
361
362 /* Descent II: Vertigo Series
363  1:  Data
364  2:  Crush - Extended Remix
365  3:  Glut - Extended Remix
366  4:  Haunted - Instrumental Re-Remix
367  5:  New Song #1
368  6:  Untitled - Extended Remix
369  7:  New Song #2
370  8:  New Song #3
371  */
372 #define D2_X_DISCID_1       0x53078208
373 #define D2_X_DISCID_2       0x64071408
374
375 #define D2_X_RB_FIRST_LEVEL_SONG    2
376
377
378 int songs_redbook_track(int songnum)
379 {
380         uint32_t discid;
381
382         if (!Redbook_enabled.intval)
383                 return 0;
384
385         discid = RBAGetDiscID();
386
387         switch (discid) {
388                 case D1_DISCID_1:
389                 case D1_DISCID_2:
390                 case D1_DISCID_3:
391                         switch (songnum) {
392                                 case SONG_TITLE:            return D1_RB_TITLE;
393                                 case SONG_BRIEFING:         return D1_RB_BRIEFING;
394                                 case SONG_ENDLEVEL:         return D1_RB_ENDLEVEL;
395                                 case SONG_ENDGAME:          return D1_RB_ENDGAME;
396                                 case SONG_CREDITS:          return D1_RB_CREDITS;
397                                 case SONG_FIRST_LEVEL_SONG: return D1_RB_FIRST_LEVEL_SONG;
398                                 default: Int3(); break;
399                         }
400                 case D2_DISCID_1:
401                 case D2_DISCID_2:
402                 case D2_DISCID_3:
403                 case D2_DISCID_4:
404                 case D2_DISCID_5:
405                 case D2_DISCID_6:
406                 case D2_DISCID_7:
407                 case D2_DISCID_8:
408                 case D2_DISCID_9:
409                         switch (songnum) {
410                                 case SONG_TITLE:            return D2_RB_TITLE;
411                                 case SONG_CREDITS:          return D2_RB_CREDITS;
412                                 case SONG_FIRST_LEVEL_SONG: return D2_RB_FIRST_LEVEL_SONG;
413                                 default: Int3(); break;
414                         }
415                 case D2_2_DISCID_1:
416                         switch (songnum) {
417                                 case SONG_TITLE:            return D2_2_RB_TITLE;
418                                 case SONG_CREDITS:          return D2_2_RB_CREDITS;
419                                 case SONG_FIRST_LEVEL_SONG: return D2_2_RB_FIRST_LEVEL_SONG;
420                                 default: Int3(); break;
421                         }
422                 case D2_IA_DISCID_1:
423                 case D2_IA_DISCID_2:
424                 case D2_IA_DISCID_3:
425                 case D2_IA_DISCID_4:
426                 case D2_IA_DISCID_5:
427                         switch (songnum) {
428                                 case SONG_TITLE:            return D2_IA_RB_TITLE;
429                                 case SONG_CREDITS:          return D2_IA_RB_CREDITS;
430                                 case SONG_FIRST_LEVEL_SONG: return D2_IA_RB_FIRST_LEVEL_SONG;
431                                 default: Int3(); break;
432                         }
433                 case D2_X_DISCID_1:
434                 case D2_X_DISCID_2:
435                         return D2_X_RB_FIRST_LEVEL_SONG;
436
437                 default:
438                         con_printf(CON_DEBUG, "Unknown CD. discid: %x\n", discid);
439                         return 1;
440         }
441         return 1;
442 }
443
444 #define REDBOOK_TITLE_TRACK         (songs_redbook_track(SONG_TITLE))
445 #define REDBOOK_CREDITS_TRACK       (songs_redbook_track(SONG_CREDITS))
446 #define REDBOOK_FIRST_LEVEL_TRACK   (songs_redbook_track(SONG_FIRST_LEVEL_SONG))
447
448 #endif
449
450
451 void songs_play_song( int songnum, int repeat )
452 {
453         #ifndef SHAREWARE
454         //Assert(songnum != SONG_ENDLEVEL && songnum != SONG_ENDGAME);  //not in full version
455         #endif
456
457         if ( !Songs_initialized )
458                 songs_init();
459
460         //stop any music already playing
461
462         songs_stop_all();
463
464         //do we want any of these to be redbook songs?
465
466         if (force_rb_register) {
467                 RBARegisterCD();                        //get new track list for new CD
468                 force_rb_register = 0;
469         }
470
471         if (songnum == SONG_TITLE)
472                 play_redbook_track(REDBOOK_TITLE_TRACK,0);
473         else if (songnum == SONG_CREDITS)
474                 play_redbook_track(REDBOOK_CREDITS_TRACK,0);
475
476         if (!Redbook_playing) {         //not playing redbook, so play midi
477
478                 #ifndef MACINTOSH
479                         digi_play_midi_song( Songs[songnum].filename, Songs[songnum].melodic_bank_file, Songs[songnum].drum_bank_file, repeat );
480                 #else
481                         digi_play_midi_song(songnum, repeat);
482                 #endif
483         }
484 }
485
486 int current_song_level;
487
488 void songs_play_level_song( int levelnum )
489 {
490         int songnum;
491         int n_tracks;
492
493         Assert( levelnum != 0 );
494
495         if ( !Songs_initialized )
496                 songs_init();
497
498         songs_stop_all();
499
500         current_song_level = levelnum;
501
502         songnum = (levelnum>0)?(levelnum-1):(-levelnum);
503
504         if (!RBAEnabled() && Redbook_enabled.intval && !FindArg("-noredbook"))
505                 reinit_redbook();
506
507         if (force_rb_register) {
508                 RBARegisterCD();                        //get new track list for new CD
509                 force_rb_register = 0;
510         }
511
512         if (Redbook_enabled.intval && RBAEnabled() && (n_tracks = RBAGetNumberOfTracks()) > 1) {
513
514                 //try to play redbook
515
516                 mprintf((0,"n_tracks = %d\n",n_tracks));
517
518                 play_redbook_track(REDBOOK_FIRST_LEVEL_TRACK + (songnum % (n_tracks-REDBOOK_FIRST_LEVEL_TRACK+1)),1);
519         }
520
521         if (! Redbook_playing) {                        //not playing redbook, so play midi
522
523                 songnum = SONG_FIRST_LEVEL_SONG + (songnum % NumLevelSongs);
524
525                 #ifndef MACINTOSH
526                         digi_play_midi_song( Songs[songnum].filename, Songs[songnum].melodic_bank_file, Songs[songnum].drum_bank_file, 1 );
527                 #else
528                         digi_play_midi_song( songnum, 1 );
529                 #endif
530
531         }
532 }
533
534 //this should be called regularly to check for redbook restart
535 void songs_check_redbook_repeat()
536 {
537         static fix last_check_time;
538         fix current_time;
539
540         if (!Redbook_playing || Config_redbook_volume.intval==0) return;
541
542         current_time = timer_get_fixed_seconds();
543         if (current_time < last_check_time || (current_time - last_check_time) >= F2_0) {
544                 if (!RBAPeekPlayStatus()) {
545                         stop_time();
546                         // if title ends, start credit music
547                         // if credits music ends, restart it
548                         if (Redbook_playing == REDBOOK_TITLE_TRACK || Redbook_playing == REDBOOK_CREDITS_TRACK)
549                                 play_redbook_track(REDBOOK_CREDITS_TRACK,0);
550                         else {
551                                 //songs_goto_next_song();
552         
553                                 //new code plays all tracks to end of disk, so if disk has
554                                 //stopped we must be at end.  So start again with level 1 song.
555         
556                                 songs_play_level_song(1);
557                         }
558                         start_time();
559                 }
560                 last_check_time = current_time;
561         }
562 }
563
564 //goto the next level song
565 void songs_goto_next_song()
566 {
567         if (Redbook_playing)            //get correct track
568                 current_song_level = RBAGetTrackNum() - REDBOOK_FIRST_LEVEL_TRACK + 1;
569
570         songs_play_level_song(current_song_level+1);
571
572 }
573
574 //goto the previous level song
575 void songs_goto_prev_song()
576 {
577         if (Redbook_playing)            //get correct track
578                 current_song_level = RBAGetTrackNum() - REDBOOK_FIRST_LEVEL_TRACK + 1;
579
580         if (current_song_level > 1)
581                 songs_play_level_song(current_song_level-1);
582
583 }
584