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