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