]> icculus.org git repositories - btb/d2x.git/blob - main/movie.c
Descent I briefings mostly working
[btb/d2x.git] / main / movie.c
1 /* $Id: movie.c,v 1.22 2003-02-25 04:45:31 btb 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 #ifdef HAVE_CONFIG_H
16 #include <conf.h>
17 #endif
18
19 #ifdef RCS
20 static char rcsid[] = "$Id: movie.c,v 1.22 2003-02-25 04:45:31 btb Exp $";
21 #endif
22
23 #define DEBUG_LEVEL CON_NORMAL
24
25 #include <string.h>
26 #include <sys/types.h>
27 #include <sys/stat.h>
28 #include <fcntl.h>
29 #include <unistd.h>
30 #include <ctype.h>
31
32 #include "movie.h"
33 #include "console.h"
34 #include "args.h"
35 #include "key.h"
36 #include "digi.h"
37 #include "songs.h"
38 #include "inferno.h"
39 #include "palette.h"
40 #include "strutil.h"
41 #include "error.h"
42 #include "u_mem.h"
43 #include "byteswap.h"
44 #include "gr.h"
45 #include "gamefont.h"
46 #include "cfile.h"
47 #include "menu.h"
48 #include "libmve.h"
49 #include "text.h"
50 #include "fileutil.h"
51 #include "screens.h"
52
53 extern int MenuHiresAvailable;
54 extern char CDROM_dir[];
55
56 #define VID_PLAY 0
57 #define VID_PAUSE 1
58
59 int Vid_State;
60
61
62 // Subtitle data
63 typedef struct {
64         short first_frame,last_frame;
65         char *msg;
66 } subtitle;
67
68 #define MAX_SUBTITLES 500
69 #define MAX_ACTIVE_SUBTITLES 3
70 subtitle Subtitles[MAX_SUBTITLES];
71 int Num_subtitles;
72
73
74 // Movielib data
75 typedef struct {
76         char name[FILENAME_LEN];
77         int offset,len;
78 } ml_entry;
79
80 #define MLF_ON_CD    1
81 #define MAX_MOVIES_PER_LIB    50    //determines size of malloc
82
83 typedef struct {
84         char     name[100]; //[FILENAME_LEN];
85         int      n_movies;
86         ubyte    flags,pad[3];
87         ml_entry *movies;
88 } movielib;
89
90 #ifdef D2_OEM
91 char movielib_files[][FILENAME_LEN] = {"intro-l.mvl","other-l.mvl","robots-l.mvl","oem-l.mvl"};
92 #else
93 char movielib_files[][FILENAME_LEN] = {"intro-l.mvl","other-l.mvl","robots-l.mvl"};
94 #endif
95
96 #define N_BUILTIN_MOVIE_LIBS (sizeof(movielib_files)/sizeof(*movielib_files))
97 #define N_MOVIE_LIBS (N_BUILTIN_MOVIE_LIBS+1)
98 #define EXTRA_ROBOT_LIB N_BUILTIN_MOVIE_LIBS
99 movielib *movie_libs[N_MOVIE_LIBS];
100
101
102 //do we have the robot movies available
103 int robot_movies = 0; //0 means none, 1 means lowres, 2 means hires
104
105 int MovieHires = 0;   //default for now is lores
106
107 int RoboFile = 0, RoboFilePos = 0;
108
109 // Function Prototypes
110 int RunMovie(char *filename, int highres_flag, int allow_abort,int dx,int dy);
111
112 int open_movie_file(char *filename,int must_have);
113 int reset_movie_file(int handle);
114
115 void change_filename_ext( char *dest, char *src, char *ext );
116 void decode_text_line(char *p);
117 void draw_subtitles(int frame_num);
118
119
120 //-----------------------------------------------------------------------
121
122
123 //filename will actually get modified to be either low-res or high-res
124 //returns status.  see values in movie.h
125 int PlayMovie(const char *filename, int must_have)
126 {
127         char name[FILENAME_LEN],*p;
128         int c, ret;
129
130 #ifndef RELEASE
131         if (FindArg("-nomovies"))
132                 return MOVIE_NOT_PLAYED;
133 #endif
134
135         strcpy(name,filename);
136
137         if ((p=strchr(name,'.')) == NULL)               //add extension, if missing
138                 strcat(name,".mve");
139
140         //check for escape already pressed & abort if so
141         while ((c=key_inkey()) != 0)
142                 if (c == KEY_ESC)
143                         return MOVIE_ABORTED;
144
145         // Stop all digital sounds currently playing.
146         digi_stop_all();
147
148         // Stop all songs
149         songs_stop_all();
150
151         digi_close();
152
153         // Start sound
154         if (!FindArg("-nosound"))
155                 MVE_sndInit(1);
156         else
157                 MVE_sndInit(-1);
158
159         ret = RunMovie(name,MovieHires,must_have,-1,-1);
160
161         if (!FindArg("-nosound"))
162                 digi_init();
163
164         Screen_mode = -1;               //force screen reset
165
166         return ret;
167 }
168
169
170 #if 0
171 typedef struct bkg {
172         short x, y, w, h;           // The location of the menu.
173         grs_bitmap * bmp;               // The background under the menu.
174 } bkg;
175
176 bkg movie_bg = {0,0,0,0,NULL};
177 #endif
178
179 #define BOX_BORDER (MenuHires?40:20)
180
181
182 void show_pause_message(char *msg)
183 {
184         int w,h,aw;
185         int x,y;
186
187         gr_set_current_canvas(NULL);
188         gr_set_curfont( SMALL_FONT );
189
190         gr_get_string_size(msg,&w,&h,&aw);
191
192         x = (grd_curscreen->sc_w-w)/2;
193         y = (grd_curscreen->sc_h-h)/2;
194
195 #if 0
196         if (movie_bg.bmp) {
197                 gr_free_bitmap(movie_bg.bmp);
198                 movie_bg.bmp = NULL;
199         }
200
201         // Save the background of the display
202         movie_bg.x=x; movie_bg.y=y; movie_bg.w=w; movie_bg.h=h;
203
204         movie_bg.bmp = gr_create_bitmap( w+BOX_BORDER, h+BOX_BORDER );
205
206         gr_bm_ubitblt(w+BOX_BORDER, h+BOX_BORDER, 0, 0, x-BOX_BORDER/2, y-BOX_BORDER/2, &(grd_curcanv->cv_bitmap), movie_bg.bmp );
207 #endif
208
209         gr_setcolor(0);
210         gr_rect(x-BOX_BORDER/2,y-BOX_BORDER/2,x+w+BOX_BORDER/2-1,y+h+BOX_BORDER/2-1);
211
212         gr_set_fontcolor( 255, -1 );
213
214         gr_ustring( 0x8000, y, msg );
215
216         gr_update();
217 }
218
219 void clear_pause_message()
220 {
221 #if 0
222         if (movie_bg.bmp) {
223
224                 gr_bitmap(movie_bg.x-BOX_BORDER/2, movie_bg.y-BOX_BORDER/2, movie_bg.bmp);
225
226                 gr_free_bitmap(movie_bg.bmp);
227                 movie_bg.bmp = NULL;
228         }
229 #endif
230 }
231
232
233 //returns status.  see movie.h
234 int RunMovie(char *filename, int hires_flag, int must_have,int dx,int dy)
235 {
236         int filehndl;
237         int result=1,aborted=0;
238         int track = 0;
239         int frame_num;
240         int key;
241
242         result=1;
243
244         // Open Movie file.  If it doesn't exist, no movie, just return.
245
246         filehndl = open_movie_file(filename,must_have);
247
248         if (filehndl == -1) {
249                 if (must_have)
250                         Warning("movie: RunMovie: Cannot open movie <%s>\n",filename);
251                 return MOVIE_NOT_PLAYED;
252         }
253
254         if (hires_flag) {
255                 gr_set_mode(SM(640,480));
256         } else {
257                 gr_set_mode(SM(320,200));
258         }
259
260         if (MVE_rmPrepMovie(filehndl, dx, dy, track)) {
261                 Int3();
262                 return MOVIE_NOT_PLAYED;
263         }
264
265         frame_num = 0;
266
267         FontHires = FontHiresAvailable && hires_flag;
268
269         while((result = MVE_rmStepMovie()) == 0) {
270
271                 draw_subtitles(frame_num);
272
273                 gr_update();
274
275                 key = key_inkey();
276
277                 // If ESCAPE pressed, then quit movie.
278                 if (key == KEY_ESC) {
279                         result = aborted = 1;
280                         break;
281                 }
282
283                 // If PAUSE pressed, then pause movie
284                 if (key == KEY_PAUSE) {
285                         MVE_rmHoldMovie();
286                         show_pause_message(TXT_PAUSE);
287                         while (!key_inkey()) ;
288                         clear_pause_message();
289                 }
290
291 #ifdef GR_SUPPORTS_FULLSCREEN_TOGGLE
292                 if ((key == KEY_CTRLED+KEY_SHIFTED+KEY_PADENTER) ||
293                         (key == KEY_ALTED+KEY_CTRLED+KEY_PADENTER) ||
294                         (key == KEY_ALTED+KEY_SHIFTED+KEY_PADENTER))
295                         gr_toggle_fullscreen();
296 #endif
297
298                 frame_num++;
299         }
300
301         Assert(aborted || result == MVE_ERR_EOF);        ///movie should be over
302
303     MVE_rmEndMovie();
304
305         close(filehndl);                           // Close Movie File
306
307         // Restore old graphic state
308
309         Screen_mode=-1;  //force reset of screen mode
310
311         return (aborted?MOVIE_ABORTED:MOVIE_PLAYED_FULL);
312 }
313
314
315 int InitMovieBriefing()
316 {
317 #if 0
318         if (MenuHires)
319                 gr_set_mode(SM(640,480));
320         else
321                 gr_set_mode(SM(320,200));
322
323         gr_init_sub_canvas( &VR_screen_pages[0], &grd_curscreen->sc_canvas, 0, 0, grd_curscreen->sc_w, grd_curscreen->sc_h );
324         gr_init_sub_canvas( &VR_screen_pages[1], &grd_curscreen->sc_canvas, 0, 0, grd_curscreen->sc_w, grd_curscreen->sc_h );
325 #endif
326
327         return 1;
328 }
329
330
331 //returns 1 if frame updated ok
332 int RotateRobot()
333 {
334         int err;
335
336         err = MVE_rmStepMovie();
337
338         if (err == MVE_ERR_EOF)     //end of movie, so reset
339         {
340                 reset_movie_file(RoboFile);
341                 if (MVE_rmPrepMovie(RoboFile, MenuHires?280:140, MenuHires?200:80, 0)) {
342                         Int3();
343                         return 0;
344                 }
345         }
346         else if (err) {
347                 Int3();
348                 return 0;
349         }
350
351         return 1;
352 }
353
354
355 void DeInitRobotMovie(void)
356 {
357         MVE_rmEndMovie();
358         close(RoboFile);                           // Close Movie File
359 }
360
361
362 int InitRobotMovie(char *filename)
363 {
364         if (FindArg("-nomovies"))
365                 return 0;
366
367         con_printf(DEBUG_LEVEL, "RoboFile=%s\n", filename);
368
369         MVE_sndInit(-1);        //tell movies to play no sound for robots
370
371         RoboFile = open_movie_file(filename, 1);
372
373         if (RoboFile == -1) {
374                 Warning("movie: InitRobotMovie: Cannot open movie file <%s>",filename);
375                 return MOVIE_NOT_PLAYED;
376         }
377
378         Vid_State = VID_PLAY;
379
380         if (MVE_rmPrepMovie(RoboFile, MenuHires?280:140, MenuHires?200:80, 0)) {
381                 Int3();
382                 return 0;
383         }
384
385         RoboFilePos=lseek (RoboFile,0L,SEEK_CUR);
386
387         con_printf(DEBUG_LEVEL, "RoboFilePos=%d!\n", RoboFilePos);
388
389         return 1;
390 }
391
392
393 /*
394  *              Subtitle system code
395  */
396
397 ubyte *subtitle_raw_data;
398
399
400 //search for next field following whitespace 
401 ubyte *next_field(ubyte *p)
402 {
403         while (*p && !isspace(*p))
404                 p++;
405
406         if (!*p)
407                 return NULL;
408
409         while (*p && isspace(*p))
410                 p++;
411
412         if (!*p)
413                 return NULL;
414
415         return p;
416 }
417
418
419 int init_subtitles(char *filename)
420 {
421         CFILE *ifile;
422         int size,read_count;
423         ubyte *p;
424         int have_binary = 0;
425
426         Num_subtitles = 0;
427
428         if (! FindArg("-subtitles"))
429                 return 0;
430
431         ifile = cfopen(filename,"rb");          //try text version
432
433         if (!ifile) {                                                           //no text version, try binary version
434                 char filename2[FILENAME_LEN];
435                 change_filename_ext(filename2,filename,".TXB");
436                 ifile = cfopen(filename2,"rb");
437                 if (!ifile)
438                         return 0;
439                 have_binary = 1;
440         }
441
442         size = cfilelength(ifile);
443
444         MALLOC (subtitle_raw_data, ubyte, size+1);
445
446         read_count = cfread(subtitle_raw_data, 1, size, ifile);
447
448         cfclose(ifile);
449
450         subtitle_raw_data[size] = 0;
451
452         if (read_count != size) {
453                 d_free(subtitle_raw_data);
454                 return 0;
455         }
456
457         p = subtitle_raw_data;
458
459         while (p && p < subtitle_raw_data+size) {
460                 char *endp;
461
462                 endp = strchr(p,'\n'); 
463                 if (endp) {
464                         if (endp[-1] == '\r')
465                                 endp[-1] = 0;           //handle 0d0a pair
466                         *endp = 0;                      //string termintor
467                 }
468
469                 if (have_binary)
470                         decode_text_line(p);
471
472                 if (*p != ';') {
473                         Subtitles[Num_subtitles].first_frame = atoi(p);
474                         p = next_field(p); if (!p) continue;
475                         Subtitles[Num_subtitles].last_frame = atoi(p);
476                         p = next_field(p); if (!p) continue;
477                         Subtitles[Num_subtitles].msg = p;
478
479                         Assert(Num_subtitles==0 || Subtitles[Num_subtitles].first_frame >= Subtitles[Num_subtitles-1].first_frame);
480                         Assert(Subtitles[Num_subtitles].last_frame >= Subtitles[Num_subtitles].first_frame);
481
482                         Num_subtitles++;
483                 }
484
485                 p = endp+1;
486
487         }
488
489         return 1;
490 }
491
492
493 void close_subtitles()
494 {
495         if (subtitle_raw_data)
496                 d_free(subtitle_raw_data);
497         subtitle_raw_data = NULL;
498         Num_subtitles = 0;
499 }
500
501
502 //draw the subtitles for this frame
503 void draw_subtitles(int frame_num)
504 {
505         static int active_subtitles[MAX_ACTIVE_SUBTITLES];
506         static int num_active_subtitles,next_subtitle,line_spacing;
507         int t,y;
508         int must_erase=0;
509
510         if (frame_num == 0) {
511                 num_active_subtitles = 0;
512                 next_subtitle = 0;
513                 gr_set_curfont( GAME_FONT );
514                 line_spacing = grd_curcanv->cv_font->ft_h + (grd_curcanv->cv_font->ft_h >> 2);
515                 gr_set_fontcolor(255,-1);
516         }
517
518         //get rid of any subtitles that have expired
519         for (t=0;t<num_active_subtitles;)
520                 if (frame_num > Subtitles[active_subtitles[t]].last_frame) {
521                         int t2;
522                         for (t2=t;t2<num_active_subtitles-1;t2++)
523                                 active_subtitles[t2] = active_subtitles[t2+1];
524                         num_active_subtitles--;
525                         must_erase = 1;
526                 }
527                 else
528                         t++;
529
530         //get any subtitles new for this frame 
531         while (next_subtitle < Num_subtitles && frame_num >= Subtitles[next_subtitle].first_frame) {
532                 if (num_active_subtitles >= MAX_ACTIVE_SUBTITLES)
533                         Error("Too many active subtitles!");
534                 active_subtitles[num_active_subtitles++] = next_subtitle;
535                 next_subtitle++;
536         }
537
538         //find y coordinate for first line of subtitles
539         y = grd_curcanv->cv_bitmap.bm_h-((line_spacing+1)*MAX_ACTIVE_SUBTITLES+2);
540
541         //erase old subtitles if necessary
542         if (must_erase) {
543                 gr_setcolor(0);
544                 gr_rect(0,y,grd_curcanv->cv_bitmap.bm_w-1,grd_curcanv->cv_bitmap.bm_h-1);
545         }
546
547         //now draw the current subtitles
548         for (t=0;t<num_active_subtitles;t++)
549                 if (active_subtitles[t] != -1) {
550                         gr_string(0x8000,y,Subtitles[active_subtitles[t]].msg);
551                         y += line_spacing+1;
552                 }
553 }
554
555
556 movielib *init_new_movie_lib(char *filename,FILE *fp)
557 {
558         int nfiles,offset;
559         int i,n;
560         movielib *table;
561
562         //read movie file header
563
564         nfiles = file_read_int(fp);             //get number of files
565
566         //table = d_malloc(sizeof(*table) + sizeof(ml_entry)*nfiles);
567         MALLOC(table, movielib, 1);
568         MALLOC(table->movies, ml_entry, nfiles);
569
570         strcpy(table->name,filename);
571         table->n_movies = nfiles;
572
573         offset = 4+4+nfiles*(13+4);     //id + nfiles + nfiles * (filename + size)
574
575         for (i=0;i<nfiles;i++) {
576                 int len;
577
578                 n = fread( table->movies[i].name, 13, 1, fp );
579                 if ( n != 1 )
580                         break;          //end of file (probably)
581
582                 len = file_read_int(fp);
583
584                 table->movies[i].len = len;
585                 table->movies[i].offset = offset;
586
587                 offset += table->movies[i].len;
588
589         }
590
591         fclose(fp);
592
593         table->flags = 0;
594
595         return table;
596
597 }
598
599
600 movielib *init_old_movie_lib(char *filename,FILE *fp)
601 {
602         int nfiles,size;
603         int i;
604         movielib *table,*table2;
605
606         nfiles = 0;
607
608         //allocate big table
609         table = d_malloc(sizeof(*table) + sizeof(ml_entry)*MAX_MOVIES_PER_LIB);
610
611         while( 1 ) {
612                 int len;
613
614                 i = fread( table->movies[nfiles].name, 13, 1, fp );
615                 if ( i != 1 )
616                         break;          //end of file (probably)
617
618                 i = fread( &len, 4, 1, fp );
619                 if ( i != 1 )
620                         Error("error reading movie library <%s>",filename);
621
622                 table->movies[nfiles].len = INTEL_INT(len);
623                 table->movies[nfiles].offset = ftell( fp );
624
625                 fseek( fp, INTEL_INT(len), SEEK_CUR );          //skip data
626
627                 nfiles++;
628         }
629
630         //allocate correct-sized table
631         size = sizeof(*table) + sizeof(ml_entry)*nfiles;
632         table2 = d_malloc(size);
633         memcpy(table2,table,size);
634         d_free(table);
635         table = table2;
636
637         strcpy(table->name,filename);
638
639         table->n_movies = nfiles;
640
641         fclose(fp);
642
643         table->flags = 0;
644
645         return table;
646
647 }
648
649
650 //find the specified movie library, and read in list of movies in it
651 movielib *init_movie_lib(char *filename)
652 {
653         //note: this based on cfile_init_hogfile()
654
655         char id[4];
656         FILE * fp;
657
658         fp = fopen( filename, "rb" );
659
660         if ((fp == NULL) && (AltHogdir_initialized)) {
661                 char temp[128];
662                 strcpy(temp, AltHogDir);
663                 strcat(temp, "/");
664                 strcat(temp, filename);
665                 fp = fopen(temp, "rb");
666         }
667
668         if ( fp == NULL )
669                 return NULL;
670
671         fread( id, 4, 1, fp );
672         if ( !strncmp( id, "DMVL", 4 ) )
673                 return init_new_movie_lib(filename,fp);
674         else if ( !strncmp( id, "DHF", 3 ) ) {
675                 fseek(fp,-1,SEEK_CUR);          //old file had 3 char id
676                 return init_old_movie_lib(filename,fp);
677         }
678         else {
679                 fclose(fp);
680                 return NULL;
681         }
682 }
683
684
685 void close_movie(int i)
686 {
687         if (movie_libs[i]) {
688                 d_free(movie_libs[i]->movies);
689                 d_free(movie_libs[i]);
690         }
691 }
692
693
694 void close_movies()
695 {
696         int i;
697
698         for (i=0;i<N_MOVIE_LIBS;i++)
699                 close_movie(i);
700 }
701
702
703 //ask user to put the D2 CD in.
704 //returns -1 if ESC pressed, 0 if OK chosen
705 //CD may not have been inserted
706 int request_cd(void)
707 {
708 #if 0
709         ubyte save_pal[256*3];
710         grs_canvas *save_canv,*tcanv;
711         int ret,was_faded=gr_palette_faded_out;
712
713         gr_palette_clear();
714
715         save_canv = grd_curcanv;
716         tcanv = gr_create_canvas(grd_curcanv->cv_w,grd_curcanv->cv_h);
717
718         gr_set_current_canvas(tcanv);
719         gr_ubitmap(0,0,&save_canv->cv_bitmap);
720         gr_set_current_canvas(save_canv);
721
722         gr_clear_canvas(BM_XRGB(0,0,0));
723
724         memcpy(save_pal,gr_palette,sizeof(save_pal));
725
726         memcpy(gr_palette,last_palette_for_color_fonts,sizeof(gr_palette));
727
728  try_again:;
729
730         ret = nm_messagebox( "CD ERROR", 1, "Ok", "Please insert your Descent II CD");
731
732         if (ret == -1) {
733                 int ret2;
734
735                 ret2 = nm_messagebox( "CD ERROR", 2, "Try Again", "Leave Game", "You must insert your\nDescent II CD to Continue");
736
737                 if (ret2 == -1 || ret2 == 0)
738                         goto try_again;
739         }
740
741         force_rb_register = 1;  //disc has changed; force register new CD
742
743         gr_palette_clear();
744
745         memcpy(gr_palette,save_pal,sizeof(save_pal));
746
747         gr_ubitmap(0,0,&tcanv->cv_bitmap);
748
749         if (!was_faded)
750                 gr_palette_load(gr_palette);
751
752         gr_free_canvas(tcanv);
753
754         return ret;
755 #else
756         con_printf(DEBUG_LEVEL, "STUB: movie: request_cd\n");
757         return 0;
758 #endif
759 }
760
761
762 void init_movie(char *filename,int libnum,int is_robots,int required)
763 {
764         int high_res;
765         int try = 0;
766
767 #ifndef RELEASE
768         if (FindArg("-nomovies")) {
769                 movie_libs[libnum] = NULL;
770                 return;
771         }
772 #endif
773
774         //for robots, load highres versions if highres menus set
775         if (is_robots)
776                 high_res = MenuHiresAvailable;
777         else
778                 high_res = MovieHires;
779
780         if (high_res)
781                 strchr(filename,'.')[-1] = 'h';
782
783 try_again:;
784
785         if ((movie_libs[libnum] = init_movie_lib(filename)) == NULL) {
786                 char name2[100];
787
788                 strcpy(name2,CDROM_dir);
789                 strcat(name2,filename);
790                 movie_libs[libnum] = init_movie_lib(name2);
791
792                 if (movie_libs[libnum] != NULL)
793                         movie_libs[libnum]->flags |= MLF_ON_CD;
794                 else {
795                         if (required) {
796                                 Warning("Cannot open movie file <%s>\n",filename);
797                         }
798
799                         if (!try) {                                         // first try
800                                 if (strchr(filename, '.')[-1] == 'h') {         // try again with lowres
801                                         strchr(filename, '.')[-1] = 'l';
802                                         high_res = 0;
803                                         Warning("Trying to open movie file <%s> instead\n", filename);
804                                         try++;
805                                         goto try_again;
806                                 } else if (strchr(filename, '.')[-1] == 'l') {  // try again with highres
807                                         strchr(filename, '.')[-1] = 'h';
808                                         high_res = 1;
809                                         Warning("Trying to open movie file <%s> instead\n", filename);
810                                         try++;
811                                         goto try_again;
812                                 }
813                         }
814                 }
815         }
816
817         if (is_robots && movie_libs[libnum]!=NULL)
818                 robot_movies = high_res?2:1;
819 }
820
821
822 //find and initialize the movie libraries
823 void init_movies()
824 {
825         int i;
826         int is_robots;
827
828         for (i=0;i<N_BUILTIN_MOVIE_LIBS;i++) {
829
830                 if (!strnicmp(movielib_files[i],"robot",5))
831                         is_robots = 1;
832                 else
833                         is_robots = 0;
834
835                 init_movie(movielib_files[i],i,is_robots,1);
836         }
837
838         movie_libs[EXTRA_ROBOT_LIB] = NULL;
839
840         atexit(close_movies);
841 }
842
843
844 void init_extra_robot_movie(char *filename)
845 {
846         close_movie(EXTRA_ROBOT_LIB);
847         init_movie(filename,EXTRA_ROBOT_LIB,1,0);
848 }
849
850
851 int movie_handle,movie_start;
852
853 //looks through a movie library for a movie file
854 //returns filehandle, with fileposition at movie, or -1 if can't find
855 int search_movie_lib(movielib *lib,char *filename,int must_have)
856 {
857         int i;
858         int filehandle;
859
860         if (lib == NULL)
861                 return -1;
862
863         for (i=0;i<lib->n_movies;i++)
864                 if (!stricmp(filename,lib->movies[i].name)) {   //found the movie in a library 
865                         int from_cd;
866
867                         from_cd = (lib->flags & MLF_ON_CD);
868
869                         if (from_cd)
870                                 songs_stop_redbook();           //ready to read from CD
871
872                         do {            //keep trying until we get the file handle
873
874 #ifdef O_BINARY
875                                 movie_handle = filehandle = open(lib->name, O_RDONLY | O_BINARY);
876 #else
877                                 movie_handle = filehandle = open(lib->name, O_RDONLY);
878 #endif
879
880                                 if ((filehandle == -1) && (AltHogdir_initialized)) {
881                                         char temp[128];
882                                         strcpy(temp, AltHogDir);
883                                         strcat(temp, "/");
884                                         strcat(temp, lib->name);
885 #ifdef O_BINARY
886                                         movie_handle = filehandle = open(temp, O_RDONLY | O_BINARY);
887 #else
888                                         movie_handle = filehandle = open(temp, O_RDONLY);
889 #endif
890                                 }
891
892                                 if (must_have && from_cd && filehandle == -1) {         //didn't get file!
893
894                                         if (request_cd() == -1)         //ESC from requester
895                                                 break;                                          //bail from here. will get error later
896                                 }
897
898                         } while (must_have && from_cd && filehandle == -1);
899
900                         if (filehandle != -1)
901                                 lseek(filehandle,(movie_start=lib->movies[i].offset),SEEK_SET);
902
903                         return filehandle;
904                 }
905
906         return -1;
907 }
908
909
910 //returns file handle
911 int open_movie_file(char *filename,int must_have)
912 {
913         int filehandle,i;
914
915         for (i=0;i<N_MOVIE_LIBS;i++) {
916                 if ((filehandle = search_movie_lib(movie_libs[i],filename,must_have)) != -1)
917                         return filehandle;
918         }
919
920         return -1;              //couldn't find it
921 }
922
923 //sets the file position to the start of this already-open file
924 int reset_movie_file(int handle)
925 {
926         Assert(handle == movie_handle);
927
928         lseek(handle,movie_start,SEEK_SET);
929
930         return 0;       //everything is cool
931 }