This commit was manufactured by cvs2svn to create tag 'd2x-0_1_2'.
[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 "kconfig.h"
33 #include "timer.h"
34 #include "cdrom.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         #ifndef MACINTOSH       // macs don't use 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         #endif // endof ifdef macintosh for dealing with the .sng file
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                         #if 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         #if 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 #define REDBOOK_TITLE_TRACK                     2
225 #define REDBOOK_CREDITS_TRACK                   3
226 #define REDBOOK_FIRST_LEVEL_TRACK       (songs_haved2_cd()?4:1)
227
228 // songs_haved2_cd returns 1 if the descent 2 CD is in the drive and
229 // 0 otherwise
230
231 int songs_haved2_cd()
232 {
233         char temp[128],cwd[128];
234         
235         getcwd(cwd, 128);
236
237         strcpy(temp,CDROM_dir);
238
239         #ifndef MACINTOSH               //for PC, strip of trailing slash
240         if (temp[strlen(temp)-1] == '\\')
241                 temp[strlen(temp)-1] = 0;
242         #endif
243
244         if ( !chdir(temp) ) {
245                 chdir(cwd);
246                 return 1;
247         }
248         
249         return 0;
250 }
251         
252
253 void songs_play_song( int songnum, int repeat )
254 {
255         #ifndef SHAREWARE
256         Assert(songnum != SONG_ENDLEVEL && songnum != SONG_ENDGAME);    //not in full version
257         #endif
258
259         if ( !Songs_initialized ) 
260                 songs_init();
261
262         //stop any music already playing
263
264         songs_stop_all();
265
266         //do we want any of these to be redbook songs?
267
268         if (force_rb_register) {
269                 RBARegisterCD();                        //get new track list for new CD
270                 force_rb_register = 0;
271         }
272
273         if (songnum == SONG_TITLE)
274                 play_redbook_track(REDBOOK_TITLE_TRACK,0);
275         else if (songnum == SONG_CREDITS)
276                 play_redbook_track(REDBOOK_CREDITS_TRACK,0);
277
278         if (!Redbook_playing) {         //not playing redbook, so play midi
279
280                 #ifndef MACINTOSH
281                         digi_play_midi_song( Songs[songnum].filename, Songs[songnum].melodic_bank_file, Songs[songnum].drum_bank_file, repeat );
282                 #else
283                         digi_play_midi_song(songnum, repeat);
284                 #endif
285         }
286 }
287
288 int current_song_level;
289
290 void songs_play_level_song( int levelnum )
291 {
292         int songnum;
293         int n_tracks;
294
295         Assert( levelnum != 0 );
296
297         if ( !Songs_initialized )
298                 songs_init();
299
300         songs_stop_all();
301
302         current_song_level = levelnum;
303
304         songnum = (levelnum>0)?(levelnum-1):(-levelnum);
305         
306         if (!RBAEnabled() && Redbook_enabled && !FindArg("-noredbook"))
307                 reinit_redbook();
308
309         if (force_rb_register) {
310                 RBARegisterCD();                        //get new track list for new CD
311                 force_rb_register = 0;
312         }
313
314         if (Redbook_enabled && RBAEnabled() && (n_tracks = RBAGetNumberOfTracks()) > 1) {
315
316                 //try to play redbook
317
318                 mprintf((0,"n_tracks = %d\n",n_tracks));
319
320                 play_redbook_track(REDBOOK_FIRST_LEVEL_TRACK + (songnum % (n_tracks-REDBOOK_FIRST_LEVEL_TRACK+1)),1);
321         }
322
323         if (! Redbook_playing) {                        //not playing redbook, so play midi
324
325                 songnum = SONG_FIRST_LEVEL_SONG + (songnum % NumLevelSongs);
326
327                 #ifndef MACINTOSH
328                         digi_play_midi_song( Songs[songnum].filename, Songs[songnum].melodic_bank_file, Songs[songnum].drum_bank_file, 1 );
329                 #else
330                         digi_play_midi_song( songnum, 1 );
331                 #endif
332
333         }
334 }
335
336 //this should be called regularly to check for redbook restart
337 void songs_check_redbook_repeat()
338 {
339         static fix last_check_time;
340         fix current_time;
341
342         if (!Redbook_playing || Config_redbook_volume==0) return;
343
344         current_time = timer_get_fixed_seconds();
345         if (current_time < last_check_time || (current_time - last_check_time) >= F2_0) {
346                 if (!RBAPeekPlayStatus()) {
347                         stop_time();
348                         // if title ends, start credit music
349                         // if credits music ends, restart it
350                         if (Redbook_playing == REDBOOK_TITLE_TRACK || Redbook_playing == REDBOOK_CREDITS_TRACK)
351                                 play_redbook_track(REDBOOK_CREDITS_TRACK,0);
352                         else {
353                                 //songs_goto_next_song();
354         
355                                 //new code plays all tracks to end of disk, so if disk has
356                                 //stopped we must be at end.  So start again with level 1 song.
357         
358                                 songs_play_level_song(1);
359                         }
360                         start_time();
361                 }
362                 last_check_time = current_time;
363         }
364 }
365
366 //goto the next level song
367 void songs_goto_next_song()
368 {
369         if (Redbook_playing)            //get correct track
370                 current_song_level = RBAGetTrackNum() - REDBOOK_FIRST_LEVEL_TRACK + 1;
371
372         songs_play_level_song(current_song_level+1);
373
374 }
375
376 //goto the previous level song
377 void songs_goto_prev_song()
378 {
379         if (Redbook_playing)            //get correct track
380                 current_song_level = RBAGetTrackNum() - REDBOOK_FIRST_LEVEL_TRACK + 1;
381
382         if (current_song_level > 1)
383                 songs_play_level_song(current_song_level-1);
384
385 }
386