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