]> icculus.org git repositories - btb/d2x.git/blob - main/songs.c
comments/whitespace
[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 #ifdef HAVE_CONFIG_H
15 #include <conf.h>
16 #endif
17
18 #include <stdlib.h>
19 #include <stdio.h>
20 #include <string.h>
21 #include <ctype.h>
22 #include <unistd.h>
23
24 #include "inferno.h"
25 #include "error.h"
26 #include "pstypes.h"
27 #include "args.h"
28 #include "songs.h"
29 #include "mono.h"
30 #include "cfile.h"
31 #include "digi.h"
32 #include "rbaudio.h"
33 #include "kconfig.h"
34 #include "timer.h"
35
36 song_info Songs[MAX_NUM_SONGS];
37 int Songs_initialized = 0;
38
39 #ifndef MACINTOSH
40 int Num_songs;
41 #endif
42
43 extern void digi_stop_current_song();
44
45 int Redbook_enabled = 1;
46
47 //0 if redbook is no playing, else the track number
48 int Redbook_playing = 0;
49
50 #define NumLevelSongs (Num_songs - SONG_FIRST_LEVEL_SONG)
51
52 extern int CD_blast_mixer();
53
54 #ifndef MACINTOSH
55 #define REDBOOK_VOLUME_SCALE  (255/3)           //255 is MAX
56 #else
57 #define REDBOOK_VOLUME_SCALE    (255)
58 #endif
59
60 //takes volume in range 0..8
61 void set_redbook_volume(int volume)
62 {
63         #ifndef MACINTOSH
64         RBASetVolume(0);                // makes the macs sound really funny
65         #endif
66         RBASetVolume(volume*REDBOOK_VOLUME_SCALE/8);
67 }
68
69 extern char CDROM_dir[];
70
71 void songs_init()
72 {
73         int i;
74         char inputline[80+1];
75         CFILE * fp;
76
77         if ( Songs_initialized ) return;
78
79
80         #if !defined(MACINTOSH) && !defined(WINDOWS)    // don't crank it if on a macintosh!!!!!
81                 if (!FindArg("-nomixer"))
82                         CD_blast_mixer();   // Crank it!
83         #endif
84
85
86         if (cfexist("descent.sng")) {   // mac (demo?) datafiles don't have the .sng file
87                 fp = cfopen( "descent.sng", "rb" );
88                 if ( fp == NULL )
89                 {
90                         Error( "Couldn't open descent.sng" );
91                 }
92                 i = 0;
93                 while (cfgets(inputline, 80, fp ))
94                 {
95                         char *p = strchr(inputline,'\n');
96                         if (p) *p = '\0';
97                         if ( strlen( inputline ) )
98                         {
99                                 Assert( i < MAX_NUM_SONGS );
100                                 sscanf( inputline, "%s %s %s",
101                                                 Songs[i].filename,
102                                                 Songs[i].melodic_bank_file,
103                                                 Songs[i].drum_bank_file );
104                                 //printf( "%d. '%s' '%s' '%s'\n",i,Songs[i].filename,Songs[i].melodic_bank_file,Songs[i].drum_bank_file );
105                                 i++;
106                         }
107                 }
108                 Num_songs = i;
109                 if (Num_songs <= SONG_FIRST_LEVEL_SONG)
110                         Error("Must have at least %d songs",SONG_FIRST_LEVEL_SONG+1);
111                 cfclose(fp);
112         }
113
114         Songs_initialized = 1;
115
116         //      RBA Hook
117         #if !defined(SHAREWARE) || ( defined(SHAREWARE) && defined(APPLE_DEMO) )
118                 if (FindArg("-noredbook"))
119                 {
120                         Redbook_enabled = 0;
121                 }
122                 else    // use redbook
123                 {
124                         #ifndef __MSDOS__ // defined(WINDOWS) || defined(MACINTOSH)
125                                 RBAInit();
126                         #else
127                                 RBAInit(toupper(CDROM_dir[0]) - 'A');
128                         #endif
129
130                                 if (RBAEnabled())
131                         {
132                                 set_redbook_volume(Config_redbook_volume);
133                                 RBARegisterCD();
134                         }
135                 }
136                 //atexit(RBAStop);      // stop song on exit
137         #endif  // endof ifndef SHAREWARE, ie ifdef SHAREWARE
138 }
139
140 #define FADE_TIME (f1_0/2)
141
142 //stop the redbook, so we can read off the CD
143 void songs_stop_redbook(void)
144 {
145         int old_volume = Config_redbook_volume*REDBOOK_VOLUME_SCALE/8;
146         fix old_time = timer_get_fixed_seconds();
147
148         if (Redbook_playing) {          //fade out volume
149                 int new_volume;
150                 do {
151                         fix t = timer_get_fixed_seconds();
152
153                         new_volume = fixmuldiv(old_volume,(FADE_TIME - (t-old_time)),FADE_TIME);
154
155                         if (new_volume < 0)
156                                 new_volume = 0;
157
158                         RBASetVolume(new_volume);
159
160                 } while (new_volume > 0);
161         }
162
163         //RBAStop();                                            // Stop CD, if playing
164
165         RBASetVolume(old_volume);       //restore volume
166
167         Redbook_playing = 0;            
168
169 }
170
171 //stop any songs - midi or redbook - that are currently playing
172 void songs_stop_all(void)
173 {
174         digi_stop_current_song();       // Stop midi song, if playing
175
176         songs_stop_redbook();                   // Stop CD, if playing
177 }
178
179 int force_rb_register=0;
180
181 void reinit_redbook()
182 {
183         #ifndef __MSDOS__ // defined(WINDOWS) || defined(MACINTOSH)
184                 RBAInit();
185         #else
186                 RBAInit(toupper(CDROM_dir[0]) - 'A');
187         #endif
188
189         if (RBAEnabled())
190         {
191                 set_redbook_volume(Config_redbook_volume);
192                 RBARegisterCD();
193                 force_rb_register=0;
194         }
195 }
196
197
198 //returns 1 if track started sucessfully
199 //start at tracknum.  if keep_playing set, play to end of disc.  else
200 //play only specified track
201 int play_redbook_track(int tracknum,int keep_playing)
202 {
203         Redbook_playing = 0;
204
205         if (!RBAEnabled() && Redbook_enabled && !FindArg("-noredbook"))
206                 reinit_redbook();
207
208         if (force_rb_register) {
209                 RBARegisterCD();                        //get new track list for new CD
210                 force_rb_register = 0;
211         }
212
213         if (Redbook_enabled && RBAEnabled()) {
214                 int num_tracks = RBAGetNumberOfTracks();
215                 if (tracknum <= num_tracks)
216                         if (RBAPlayTracks(tracknum,keep_playing?num_tracks:tracknum))  {
217                                 Redbook_playing = tracknum;
218                         }
219         }
220
221         return (Redbook_playing != 0);
222 }
223
224 /*
225  * Some of these have different Track listings!
226  * Which one is the "correct" order?
227  */
228 #define D2_1_DISCID         0x7d0ff809 // Descent II
229 #define D2_2_DISCID         0xe010a30e // Descent II
230 #define D2_3_DISCID         0xd410070d // Descent II
231 #define D2_4_DISCID         0xc610080d // Descent II
232 #define D2_DEF_DISCID       0x87102209 // Definitive collection Disc 2
233 #define D2_OEM_DISCID       0xac0bc30d // Destination: Quartzon
234 #define D2_OEM2_DISCID      0xc40c0a0d // Destination: Quartzon
235 #define D2_VERTIGO_DISCID   0x53078208 // Vertigo
236 #define D2_VERTIGO2_DISCID  0x64071408 // Vertigo + DMB
237 #define D2_MAC_DISCID       0xb70ee40e // Macintosh
238 #define D2_IPLAY_DISCID     0x22115710 // iPlay for Macintosh
239
240 #define REDBOOK_TITLE_TRACK         2
241 #define REDBOOK_CREDITS_TRACK       3
242 #define REDBOOK_FIRST_LEVEL_TRACK   (songs_haved2_cd()?4:1)
243
244 // songs_haved2_cd returns 1 if the descent 2 CD is in the drive and
245 // 0 otherwise
246
247 #if 1
248 int songs_haved2_cd()
249 {
250         int discid;
251
252         if (!Redbook_enabled)
253                 return 0;
254
255         discid = RBAGetDiscID();
256
257         switch (discid) {
258         case D2_1_DISCID:
259         case D2_2_DISCID:
260         case D2_3_DISCID:
261         case D2_4_DISCID:
262         case D2_DEF_DISCID:
263         case D2_OEM_DISCID:
264         case D2_OEM2_DISCID:
265         case D2_VERTIGO_DISCID:
266         case D2_VERTIGO2_DISCID:
267         case D2_MAC_DISCID:
268         case D2_IPLAY_DISCID:
269                 printf("Found D2 CD! discid: %x\n", discid);
270                 return 1;
271         default:
272                 printf("Unknown CD! discid: %x\n", discid);
273                 return 0;
274         }
275 }
276 #else
277 int songs_haved2_cd()
278 {
279         char temp[128],cwd[128];
280         
281         getcwd(cwd, 128);
282
283         strcpy(temp,CDROM_dir);
284
285         #ifndef MACINTOSH               //for PC, strip of trailing slash
286         if (temp[strlen(temp)-1] == '\\')
287                 temp[strlen(temp)-1] = 0;
288         #endif
289
290         if ( !chdir(temp) ) {
291                 chdir(cwd);
292                 return 1;
293         }
294         
295         return 0;
296 }
297 #endif
298
299
300 void songs_play_song( int songnum, int repeat )
301 {
302         #ifndef SHAREWARE
303         //Assert(songnum != SONG_ENDLEVEL && songnum != SONG_ENDGAME);  //not in full version
304         #endif
305
306         if ( !Songs_initialized ) 
307                 songs_init();
308
309         //stop any music already playing
310
311         songs_stop_all();
312
313         //do we want any of these to be redbook songs?
314
315         if (force_rb_register) {
316                 RBARegisterCD();                        //get new track list for new CD
317                 force_rb_register = 0;
318         }
319
320         if (songnum == SONG_TITLE)
321                 play_redbook_track(REDBOOK_TITLE_TRACK,0);
322         else if (songnum == SONG_CREDITS)
323                 play_redbook_track(REDBOOK_CREDITS_TRACK,0);
324
325         if (!Redbook_playing) {         //not playing redbook, so play midi
326
327                 #ifndef MACINTOSH
328                         digi_play_midi_song( Songs[songnum].filename, Songs[songnum].melodic_bank_file, Songs[songnum].drum_bank_file, repeat );
329                 #else
330                         digi_play_midi_song(songnum, repeat);
331                 #endif
332         }
333 }
334
335 int current_song_level;
336
337 void songs_play_level_song( int levelnum )
338 {
339         int songnum;
340         int n_tracks;
341
342         Assert( levelnum != 0 );
343
344         if ( !Songs_initialized )
345                 songs_init();
346
347         songs_stop_all();
348
349         current_song_level = levelnum;
350
351         songnum = (levelnum>0)?(levelnum-1):(-levelnum);
352
353         if (!RBAEnabled() && Redbook_enabled && !FindArg("-noredbook"))
354                 reinit_redbook();
355
356         if (force_rb_register) {
357                 RBARegisterCD();                        //get new track list for new CD
358                 force_rb_register = 0;
359         }
360
361         if (Redbook_enabled && RBAEnabled() && (n_tracks = RBAGetNumberOfTracks()) > 1) {
362
363                 //try to play redbook
364
365                 mprintf((0,"n_tracks = %d\n",n_tracks));
366
367                 play_redbook_track(REDBOOK_FIRST_LEVEL_TRACK + (songnum % (n_tracks-REDBOOK_FIRST_LEVEL_TRACK+1)),1);
368         }
369
370         if (! Redbook_playing) {                        //not playing redbook, so play midi
371
372                 songnum = SONG_FIRST_LEVEL_SONG + (songnum % NumLevelSongs);
373
374                 #ifndef MACINTOSH
375                         digi_play_midi_song( Songs[songnum].filename, Songs[songnum].melodic_bank_file, Songs[songnum].drum_bank_file, 1 );
376                 #else
377                         digi_play_midi_song( songnum, 1 );
378                 #endif
379
380         }
381 }
382
383 //this should be called regularly to check for redbook restart
384 void songs_check_redbook_repeat()
385 {
386         static fix last_check_time;
387         fix current_time;
388
389         if (!Redbook_playing || Config_redbook_volume==0) return;
390
391         current_time = timer_get_fixed_seconds();
392         if (current_time < last_check_time || (current_time - last_check_time) >= F2_0) {
393                 if (!RBAPeekPlayStatus()) {
394                         stop_time();
395                         // if title ends, start credit music
396                         // if credits music ends, restart it
397                         if (Redbook_playing == REDBOOK_TITLE_TRACK || Redbook_playing == REDBOOK_CREDITS_TRACK)
398                                 play_redbook_track(REDBOOK_CREDITS_TRACK,0);
399                         else {
400                                 //songs_goto_next_song();
401         
402                                 //new code plays all tracks to end of disk, so if disk has
403                                 //stopped we must be at end.  So start again with level 1 song.
404         
405                                 songs_play_level_song(1);
406                         }
407                         start_time();
408                 }
409                 last_check_time = current_time;
410         }
411 }
412
413 //goto the next level song
414 void songs_goto_next_song()
415 {
416         if (Redbook_playing)            //get correct track
417                 current_song_level = RBAGetTrackNum() - REDBOOK_FIRST_LEVEL_TRACK + 1;
418
419         songs_play_level_song(current_song_level+1);
420
421 }
422
423 //goto the previous level song
424 void songs_goto_prev_song()
425 {
426         if (Redbook_playing)            //get correct track
427                 current_song_level = RBAGetTrackNum() - REDBOOK_FIRST_LEVEL_TRACK + 1;
428
429         if (current_song_level > 1)
430                 songs_play_level_song(current_song_level-1);
431
432 }
433