]> icculus.org git repositories - taylor/freespace2.git/blob - src/cutscene/cutscenes.cpp
Freespace 1 support
[taylor/freespace2.git] / src / cutscene / cutscenes.cpp
1 /*
2  * Copyright (C) Volition, Inc. 1999.  All rights reserved.
3  *
4  * All source code herein is the property of Volition, Inc. You may not sell 
5  * or otherwise commercially exploit the source or things you created based on
6  * the source.
7  */
8
9 /*
10  * $Logfile: /Freespace2/code/Cutscene/Cutscenes.cpp $
11  * $Revision$
12  * $Date$
13  * $Author$
14  *
15  * Code for the cutscenes viewer screen
16  *
17  * $Log$
18  * Revision 1.7  2003/05/25 02:30:42  taylor
19  * Freespace 1 support
20  *
21  * Revision 1.6  2002/07/24 00:20:41  relnev
22  * nothing interesting
23  *
24  * Revision 1.5  2002/06/09 04:41:15  relnev
25  * added copyright header
26  *
27  * Revision 1.4  2002/06/02 04:26:34  relnev
28  * warning cleanup
29  *
30  * Revision 1.3  2002/05/26 22:06:17  relnev
31  * makefile: disable stand_gui for now.
32  *
33  * rest: staticize some globals
34  *
35  * Revision 1.2  2002/05/07 03:16:43  theoddone33
36  * The Great Newline Fix
37  *
38  * Revision 1.1.1.1  2002/05/03 03:28:08  root
39  * Initial import.
40  *
41  * 
42  * 15    6/16/00 3:15p Jefff
43  * sim of the year dvd version changes, a few german soty localization
44  * fixes
45  * 
46  * 14    10/13/99 10:20a Jefff
47  * fixed bug where intro cutscene showed 2x after getting bad ending
48  * 
49  * 13    10/06/99 10:30a Jefff
50  * OEM updates
51  * 
52  * 12    9/30/99 6:01p Jefff
53  * OEM updates
54  * 
55  * 11    9/07/99 1:10p Mikek
56  * Make movie check not hang in ~RELEASE_REAL build.
57  * 
58  * 10    9/06/99 6:38p Dave
59  * Improved CD detection code.
60  * 
61  * 9     9/06/99 1:16a Dave
62  * Make sure the user sees the intro movie.
63  * 
64  * 8     9/03/99 1:31a Dave
65  * CD checking by act. Added support to play 2 cutscenes in a row
66  * seamlessly. Fixed super low level cfile bug related to files in the
67  * root directory of a CD. Added cheat code to set campaign mission # in
68  * main hall.
69  * 
70  * 7     7/19/99 2:13p Dave
71  * Added some new strings for Heiko.
72  * 
73  * 6     6/01/99 3:52p Dave
74  * View footage screen. Fixed xstrings to not display the & symbol. Popup,
75  * dead popup, pxo find player popup, pxo private room popup.
76  * 
77  * 5     1/30/99 5:08p Dave
78  * More new hi-res stuff.Support for nice D3D textures.
79  * 
80  * 4     10/23/98 3:51p Dave
81  * Full support for tstrings.tbl and foreign languages. All that remains
82  * is to make it active in Fred.
83  * 
84  * 3     10/13/98 9:28a Dave
85  * Started neatening up freespace.h. Many variables renamed and
86  * reorganized. Added AlphaColors.[h,cpp]
87  * 
88  * 2     10/07/98 10:52a Dave
89  * Initial checkin.
90  * 
91  * 1     10/07/98 10:48a Dave
92  * 
93  * 18    6/09/98 10:31a Hoffoss
94  * Created index numbers for all xstr() references.  Any new xstr() stuff
95  * added from here on out should be added to the end if the list.  The
96  * current list count can be found in FreeSpace.cpp (search for
97  * XSTR_SIZE).
98  * 
99  * 17    6/01/98 11:43a John
100  * JAS & MK:  Classified all strings for localization.
101  * 
102  * 16    5/24/98 9:01p Lawrance
103  * Add commit sounds when accept is pressed
104  * 
105  * 15    5/21/98 8:05p Allender
106  * fix possible bug with number of cutscenes shown in the list
107  * 
108  * 14    5/21/98 12:35a Lawrance
109  * Tweak how CD is checked for
110  * 
111  * 13    5/20/98 1:34p Hoffoss
112  * Added cutscene description rendering.
113  * 
114  * 12    5/19/98 12:19p Mike
115  * Cheat codes!
116  * 
117  * 11    5/12/98 4:17p Hoffoss
118  * Make ctrl-arrows (up/down) switch between tech room screens.
119  * 
120  * 10    5/11/98 8:04p Hoffoss
121  * Fixed minor bugs.
122  * 
123  * 9     5/10/98 10:05p Allender
124  * only show cutscenes which have been seen before.  Made Fred able to
125  * write missions anywhere, defaulting to player misison folder, not data
126  * mission folder.  Fix FreeSpace code to properly read missions from
127  * correct locations
128  * 
129  * 8     5/08/98 5:30p Lawrance
130  * add CD checks for movie playing
131  * 
132  * 7     5/08/98 4:07p Allender
133  * more cutscene stuff
134  * 
135  * 6     5/07/98 2:33p Hoffoss
136  * Removed help and options buttons.
137  * 
138  * 5     4/30/98 4:53p John
139  * Restructured and cleaned up cfile code.  Added capability to read off
140  * of CD-ROM drive and out of multiple pack files.
141  * 
142  * 4     4/23/98 8:27p Allender
143  * basic support for cutscene playback.  Into movie code in place.  Tech
144  * room can view cutscenes stored in CDROM_dir variable
145  * 
146  * 3     4/21/98 7:07p Hoffoss
147  * Fixed problem where when switching screens flashes old tab hilight once
148  * before switching to new state.
149  * 
150  * 2     4/17/98 6:33p Hoffoss
151  * Made changes to the tech room group of screens.  Cutscenes screen is
152  * now in a new file.
153  *
154  * $NoKeywords: $
155  */
156
157 #include "cutscenes.h"
158 #include "ui.h"
159 #include "cfile.h"
160 #include "gamesnd.h"
161 #include "gamesequence.h"
162 #include "freespace.h"
163 #include "key.h"
164 #include "bmpman.h"
165 #include "movie.h"
166 #include "popup.h"
167 #include "mainhallmenu.h"
168 #include "alphacolors.h"
169 #include "localize.h"
170
171 char *Cutscene_bitmap_name[GR_NUM_RESOLUTIONS] = {
172         "ViewFootage",
173         "2_ViewFootage"
174 };
175 char *Cutscene_mask_name[GR_NUM_RESOLUTIONS] = {
176         "ViewFootage-m",
177         "2_ViewFootage-m"
178 };
179
180 int Num_cutscenes;
181 int Cutscenes_viewable;
182 int Description_index;
183 cutscene_info Cutscenes[MAX_CUTSCENES];
184
185 extern int All_movies_enabled;          //      If set, all movies may be viewed.  Keyed off cheat code.
186
187 // initialization stuff for cutscenes
188 void cutscene_init()
189 {
190 #ifndef FS1_DEMO  // no cuscenes in FS1 demo
191         char buf[MULTITEXT_LENGTH];
192         int rval;
193
194         if ((rval = setjmp(parse_abort)) != 0) {
195                 Error(LOCATION, "Error parsing 'rank.tbl'\r\nError code = %i.\r\n", rval);
196         } 
197
198         // open localization
199         lcl_ext_open();
200
201         read_file_text("cutscenes.tbl");
202         reset_parse();
203
204         // parse in all the rank names
205         Num_cutscenes = 0;
206         skip_to_string("#Cutscenes");
207         ignore_white_space();
208         while ( required_string_either("#End", "$Filename:") ) {
209                 Assert ( Num_cutscenes < MAX_CUTSCENES );
210                 required_string("$Filename:");
211                 stuff_string( Cutscenes[Num_cutscenes].filename, F_PATHNAME, NULL );
212                 required_string("$Name:");
213                 stuff_string( Cutscenes[Num_cutscenes].name, F_NAME, NULL );
214                 required_string("$Description:");
215                 stuff_string(buf, F_MULTITEXT, NULL);
216                 drop_white_space(buf);
217                 compact_multitext_string(buf);
218                 Cutscenes[Num_cutscenes].description = strdup(buf);
219                 required_string("$cd:");
220                 stuff_int( &Cutscenes[Num_cutscenes].cd );
221
222                 Num_cutscenes++;
223         }
224
225         required_string("#End");
226
227         Cutscenes_viewable = INTRO_CUTSCENE_FLAG;
228
229         // close localization
230         lcl_ext_close();
231 #endif  // FS1_DEMO
232 }
233
234 // function to return 0 based index of which CD a particular movie is on
235 // returns -1 on failure.
236 int cutscenes_get_cd_num( char *filename )
237 {
238 #if defined(OEM_BUILD)
239         return 0;                               // only 1 cd for OEM
240 #else
241         int i;
242
243         for (i = 0; i < Num_cutscenes; i++ ) {
244                 if ( !stricmp(Cutscenes[i].filename, filename) ) {
245                         return (Cutscenes[i].cd - 1);
246                 }
247         }
248
249         return -1;
250 #endif // defined(OEM_BUILD)
251 }
252
253 // marks a cutscene as viewable
254 void cutscene_mark_viewable(char *filename)
255 {
256         int i;
257
258         for (i = 0; i < Num_cutscenes; i++ ) {
259                 if ( !stricmp(Cutscenes[i].filename, filename) ) {
260                         Cutscenes_viewable |= (1<<i);
261                         return;
262                 }
263         }
264 }
265
266 #define NUM_BUTTONS                             8
267
268 #define TECH_DATABASE_BUTTON    0
269 #define SIMULATOR_BUTTON                1
270 #define CUTSCENES_BUTTON                2
271 #define CREDITS_BUTTON                  3
272
273 #define SCROLL_UP_BUTTON                4
274 #define SCROLL_DOWN_BUTTON              5
275 #define PLAY_BUTTON                             6
276 #define EXIT_BUTTON                             7
277
278 static int Num_files;
279 static int Cutscene_list[MAX_CUTSCENES];
280 static int Selected_line = 0;  // line that is currently selected for binding
281 static int Scroll_offset;
282 static int Background_bitmap;
283 static UI_BUTTON List_region;
284 static UI_WINDOW Ui_window;
285
286 static ui_button_info Buttons[GR_NUM_RESOLUTIONS][NUM_BUTTONS] = {
287         { // GR_640
288 #ifdef MAKE_FS1
289                 ui_button_info("TDB_00",        0,              0,              -1,     -1,     0),             // technical database tab
290                 ui_button_info("TDB_01",        0,              19,             -1,     -1,     1),             // mission simulator tab
291                 ui_button_info("TDB_02",        0,              35,             -1,     -1,     2),             // cutscenes tab
292                 ui_button_info("TDB_03",        0,              56,             -1,     -1,     3),             // credits tab
293
294                 ui_button_info("VFB_04",        570,    304,    -1,     -1,     4),             // scroll up
295                 ui_button_info("VFB_05",        600,    304,    -1,     -1,     5),             // scroll down
296                 ui_button_info("VFB_06",        573,    347,    -1,     -1,     6),             // play
297                 ui_button_info("VFB_07",        566,    411,    -1,     -1,     7),             // exit
298 #else
299                 ui_button_info("TDB_00",        7,              5,              37,     7,              0),                     // tech database 1
300                 ui_button_info("TDB_01",        7,              19,     37,     23,     1),                     // tech database 2
301                 ui_button_info("TDB_02",        7,              34,     37,     38,     2),                     // tech database 3
302                 ui_button_info("TDB_03",        7,              49,     37,     54,     3),                     // tech database 4
303
304                 ui_button_info("VFB_04",        6,              318,    -1,     -1,     4),                     // scroll up
305                 ui_button_info("VFB_05",        36,     318,    -1,     -1,     5),                     // scroll down
306                 ui_button_info("VFB_06",        578,    319,    587,    366,    6),                     // play
307                 ui_button_info("VFB_07",        574,    431,    587,    413,    7),                     // exit
308 #endif
309         },
310         { // GR_1024
311                 ui_button_info("2_TDB_00",      12,     7,              59,     12,     0),                     // tech database 1
312                 ui_button_info("2_TDB_01",      12,     31,     59,     37,     1),                     // tech database 2
313                 ui_button_info("2_TDB_02",      12,     56,     59,     62,     2),                     // tech database 3
314                 ui_button_info("2_TDB_03",      12,     81,     59,     88,     3),                     // tech database 4
315
316                 ui_button_info("2_VFB_04",      9,              509,    -1,     -1,     4),                     // scroll up
317                 ui_button_info("2_VFB_05",      58,     509,    -1,     -1,     5),                     // scroll down
318                 ui_button_info("2_VFB_06",      925,    511,    940,    586,    6),                     // play
319                 ui_button_info("2_VFB_07",      918,    689,    940,    661,    7),                     // exit
320         }
321 };
322
323 // text
324 #ifdef MAKE_FS1
325         #define NUM_CUTSCENE_TEXT                       0
326 #else
327         #define NUM_CUTSCENE_TEXT                       6
328 #endif
329 UI_XSTR Cutscene_text[GR_NUM_RESOLUTIONS][NUM_CUTSCENE_TEXT] = {
330         { // GR_640
331                 // nothing needed for FS1
332 #ifndef MAKE_FS1
333                 {"Technical Database",          1055,           37,     7,              UI_XSTR_COLOR_GREEN, -1, &Buttons[0][TECH_DATABASE_BUTTON].button },
334                 {"Mission Simulator",           1056,           37,     23,     UI_XSTR_COLOR_GREEN, -1, &Buttons[0][SIMULATOR_BUTTON].button },
335                 {"Cutscenes",                                   1057,           37,     38,     UI_XSTR_COLOR_GREEN, -1, &Buttons[0][CUTSCENES_BUTTON].button },
336                 {"Credits",                                             1058,           37,     54,     UI_XSTR_COLOR_GREEN, -1, &Buttons[0][CREDITS_BUTTON].button },
337                 
338                 {"Play",                                                        1335,           587,    366,    UI_XSTR_COLOR_GREEN, -1, &Buttons[0][PLAY_BUTTON].button },
339                 {"Exit",                                                        1419,           587,    413,    UI_XSTR_COLOR_PINK, -1, &Buttons[0][EXIT_BUTTON].button },                      
340 #endif
341         },
342         { // GR_1024
343                 // nothing needed for FS1
344 #ifndef MAKE_FS1
345                 {"Technical Database",          1055,           59,     12,     UI_XSTR_COLOR_GREEN, -1, &Buttons[1][TECH_DATABASE_BUTTON].button },
346                 {"Mission Simulator",           1056,           59,     37,     UI_XSTR_COLOR_GREEN, -1, &Buttons[1][SIMULATOR_BUTTON].button },
347                 {"Cutscenes",                                   1057,           59,     62,     UI_XSTR_COLOR_GREEN, -1, &Buttons[1][CUTSCENES_BUTTON].button },
348                 {"Credits",                                             1058,           59,     88,     UI_XSTR_COLOR_GREEN, -1, &Buttons[1][CREDITS_BUTTON].button },
349                 
350                 {"Play",                                                        1335,           940,    586,    UI_XSTR_COLOR_GREEN, -1, &Buttons[1][PLAY_BUTTON].button },
351                 {"Exit",                                                        1419,           940,    661,    UI_XSTR_COLOR_PINK, -1, &Buttons[1][EXIT_BUTTON].button },                      
352 #endif
353         }
354 };
355
356 int Cutscene_list_coords[GR_NUM_RESOLUTIONS][4] = {
357         { // GR_640
358 #ifdef MAKE_FS1
359                 25, 119, 542, 193
360 #else
361                 9,      117,    621,    198
362 #endif
363         },
364         { // GR_1024
365                 14,     188,    994,    316
366         }
367 };
368
369 int Cutscene_desc_coords[GR_NUM_RESOLUTIONS][4] = {
370         { // GR_640
371 #ifdef MAKE_FS1
372                 19, 356, 465, 40
373 #else
374                 9,      378, 484, 73
375 #endif
376         },
377         { // GR_1024
378                 14, 605, 775, 117
379         }
380 };
381
382 #define MAX_TEXT_LINES          20
383 int Cutscene_max_text_lines[GR_NUM_RESOLUTIONS] = {
384         10,
385         MAX_TEXT_LINES
386 };
387 #define MAX_TEXT_LINE_LEN       256
388
389 static int Text_size;
390 static int Text_offset = 0;
391 static int Text_line_size[MAX_TEXT_LINES];
392 static char *Text_lines[MAX_TEXT_LINES];
393
394
395 int cutscenes_validate_cd(char *mve_name, int prompt_for_cd)
396 {
397         int cd_present = 0;
398         int cd_drive_num;
399         int cd_mve_is_on;
400         char volume_name[128];
401
402 #ifdef RELEASE_REAL
403         int num_attempts = 0;
404 #endif
405
406         while(1) {
407                 int path_set_ok;
408
409                 cd_mve_is_on = cutscenes_get_cd_num(mve_name);
410                 if ((cd_mve_is_on != 0) && (cd_mve_is_on != 1) && (cd_mve_is_on != 2)) {
411                         cd_present = 0;
412                         break;
413                 }
414
415 #if defined(OEM_BUILD)
416                 sprintf(volume_name, NOX("FS2_OEM"));
417 #else
418                 sprintf(volume_name, NOX("FREESPACE2_%c"), '1' + cd_mve_is_on);
419 #endif
420
421
422                 cd_drive_num = find_freespace_cd(volume_name);
423                 path_set_ok = set_cdrom_path(cd_drive_num);
424
425                 if ( path_set_ok ) {
426                         cd_present = 1;
427                         break;
428                 }
429
430 #ifdef RELEASE_REAL
431                 if ( !prompt_for_cd ) {
432                         cd_present = 0;
433                         break;
434                 }
435
436                 // no CD found, so prompt user
437                 char popup_msg[256];
438                 int popup_rval;
439
440 #if defined(DVD_MESSAGE_HACK)
441                 sprintf(popup_msg, XSTR( "Movie not found\n\nInsert FreeSpace DVD to continue", 203));
442 #else 
443                 sprintf(popup_msg, XSTR( "Movie not found\n\nInsert FreeSpace CD #%d to continue", 203), cd_mve_is_on+1);
444 #endif
445
446                 popup_rval = popup(PF_BODY_BIG, 2, POPUP_CANCEL, POPUP_OK, popup_msg);
447                 if ( popup_rval != 1 ) {
448                         cd_present = 0;
449                         break;
450                 }
451
452                 if ( num_attempts++ > 5 ) {
453                         cd_present = 0;
454                         break;
455                 }
456 #else
457                 cd_present = 0;
458                 break;
459 #endif
460
461         }
462
463         return cd_present;
464 }
465
466 void cutscenes_screen_play()
467 {
468         char name[MAX_FILENAME_LEN], *full_name;
469         int which_cutscene;
470
471         Assert( (Selected_line >= 0) && (Selected_line < Num_files) );
472         which_cutscene = Cutscene_list[Selected_line];
473
474         strcpy(name, Cutscenes[which_cutscene].filename );
475         full_name = cf_add_ext(name, NOX(".mve"));
476
477         int rval = movie_play(full_name);
478         if ( !rval ) {
479                 char str[256];
480
481                 sprintf(str, XSTR( "Unable to play movie %s.", 204), Cutscenes[which_cutscene].name );
482                 popup(0, 1, POPUP_OK, str );
483         }
484 }
485
486 void cutscenes_screen_scroll_line_up()
487 {
488         if (Selected_line) {
489                 Selected_line--;
490                 gamesnd_play_iface(SND_SCROLL);
491
492         } else
493                 gamesnd_play_iface(SND_GENERAL_FAIL);
494         
495         if (Selected_line < Scroll_offset)
496                 Scroll_offset = Selected_line;
497 }
498
499 void cutscenes_screen_scroll_line_down()
500 {
501         int h;
502
503         if (Selected_line < Num_files - 1) {
504                 Selected_line++;
505                 gamesnd_play_iface(SND_SCROLL);
506
507         } else
508                 gamesnd_play_iface(SND_GENERAL_FAIL);
509         
510         h = Cutscene_list_coords[gr_screen.res][3] / gr_get_font_height();
511         if (Selected_line >= Scroll_offset + h){
512                 Scroll_offset++;
513         }
514 }
515
516 void cutscenes_screen_scroll_screen_up()
517 {
518         int h;
519
520         if (Scroll_offset) {
521                 Scroll_offset--;
522                 Assert(Selected_line > Scroll_offset);
523                 h = Cutscene_list_coords[gr_screen.res][3] / gr_get_font_height();
524                 while (Selected_line >= Scroll_offset + h){
525                         Selected_line--;
526                 }
527
528                 gamesnd_play_iface(SND_SCROLL);
529
530         } else {
531                 gamesnd_play_iface(SND_GENERAL_FAIL);
532         }
533 }
534
535 void cutscenes_screen_scroll_screen_down()
536 {
537         int h;
538
539         h = Cutscene_list_coords[gr_screen.res][3] / gr_get_font_height();
540         if (Scroll_offset + h < Num_files) {
541                 Scroll_offset++;
542                 if (Selected_line < Scroll_offset){
543                         Selected_line = Scroll_offset;
544                 }
545
546                 gamesnd_play_iface(SND_SCROLL);
547         } else {
548                 gamesnd_play_iface(SND_GENERAL_FAIL);
549         }
550 }
551
552 int cutscenes_screen_button_pressed(int n)
553 {
554         switch (n) {
555                 case TECH_DATABASE_BUTTON:
556                         gamesnd_play_iface(SND_SWITCH_SCREENS);
557                         gameseq_post_event(GS_EVENT_TECH_MENU);
558                         return 1;
559
560                 case SIMULATOR_BUTTON:
561                         gamesnd_play_iface(SND_SWITCH_SCREENS);
562                         gameseq_post_event(GS_EVENT_SIMULATOR_ROOM);
563                         return 1;
564
565                 case CREDITS_BUTTON:
566                         gamesnd_play_iface(SND_SWITCH_SCREENS);
567                         gameseq_post_event(GS_EVENT_CREDITS);
568                         return 1;
569
570                 case SCROLL_UP_BUTTON:
571                         cutscenes_screen_scroll_screen_up();
572                         break;
573
574                 case SCROLL_DOWN_BUTTON:
575                         cutscenes_screen_scroll_screen_down();
576                         break;
577
578                 case PLAY_BUTTON:
579                         cutscenes_screen_play();
580                         break;
581
582                 case EXIT_BUTTON:
583                         gamesnd_play_iface(SND_COMMIT_PRESSED);
584                         gameseq_post_event(GS_EVENT_MAIN_MENU);
585                         game_flush();
586                         break;
587         }
588
589         return 0;
590 }
591
592 void cutscenes_screen_init()
593 {
594         int i;
595         ui_button_info *b;
596
597         Ui_window.create(0, 0, gr_screen.max_w, gr_screen.max_h, 0);
598         Ui_window.set_mask_bmap(Cutscene_mask_name[gr_screen.res]);
599
600         for (i=0; i<NUM_BUTTONS; i++) {
601                 b = &Buttons[gr_screen.res][i];
602
603                 b->button.create(&Ui_window, "", b->x, b->y, 60, 30, (i < 2), 1);
604                 // set up callback for when a mouse first goes over a button
605                 b->button.set_highlight_action(common_play_highlight_sound);
606                 b->button.set_bmaps(b->filename);
607                 b->button.link_hotspot(b->hotspot);
608         }
609
610         // add xstrs
611         for(i=0; i<NUM_CUTSCENE_TEXT; i++){
612                 Ui_window.add_XSTR(&Cutscene_text[gr_screen.res][i]);
613         }
614
615         Buttons[gr_screen.res][EXIT_BUTTON].button.set_hotkey(KEY_CTRLED | KEY_ENTER);
616         Buttons[gr_screen.res][SCROLL_UP_BUTTON].button.set_hotkey(KEY_PAGEUP);
617         Buttons[gr_screen.res][SCROLL_DOWN_BUTTON].button.set_hotkey(KEY_PAGEDOWN);     
618
619         List_region.create(&Ui_window, "", Cutscene_list_coords[gr_screen.res][0], Cutscene_list_coords[gr_screen.res][1], Cutscene_list_coords[gr_screen.res][2], Cutscene_list_coords[gr_screen.res][3], 0, 1);
620         List_region.hide();
621
622         // set up hotkeys for buttons so we draw the correct animation frame when a key is pressed
623         Buttons[gr_screen.res][SCROLL_UP_BUTTON].button.set_hotkey(KEY_PAGEUP);
624         Buttons[gr_screen.res][SCROLL_DOWN_BUTTON].button.set_hotkey(KEY_PAGEDOWN);
625
626         Background_bitmap = bm_load(Cutscene_bitmap_name[gr_screen.res]);
627         Scroll_offset = Selected_line = 0;
628         Description_index = -1;
629
630         // when doing a debug version, just put all of the movie files here.
631 #ifndef NDEBUG
632         //Cutscenes_viewable = 0xffffffff;                      // makes all cutscenes viewble.
633 #endif
634
635         if (All_movies_enabled)
636                 Cutscenes_viewable = 0xffffffff;                //      Cheat code enables all movies.
637
638         Num_files = 0;
639         for ( i = 0; i < Num_cutscenes; i++ ) {
640                 if ( Cutscenes_viewable & (1<<i) ) {
641                         Cutscene_list[Num_files] = i;
642                         Num_files++;
643                 }
644         }
645 }
646
647 void cutscenes_screen_close()
648 {
649         if (Background_bitmap)
650                 bm_unload(Background_bitmap);
651
652         Ui_window.destroy();
653 }
654
655 void cutscenes_screen_do_frame()
656 {
657         int i, k, y, z;
658         int font_height = gr_get_font_height();
659         int select_tease_line = -1;
660
661         k = Ui_window.process();
662         switch (k) {
663                 case KEY_DOWN:  // select next line
664                         cutscenes_screen_scroll_line_down();
665                         break;
666
667                 case KEY_UP:  // select previous line
668                         cutscenes_screen_scroll_line_up();
669                         break;
670
671                 case KEY_TAB:
672                 case KEY_CTRLED | KEY_DOWN:
673                         cutscenes_screen_button_pressed(CREDITS_BUTTON);
674                         break;
675
676                 case KEY_SHIFTED | KEY_TAB:
677                 case KEY_CTRLED | KEY_UP:
678                         cutscenes_screen_button_pressed(SIMULATOR_BUTTON);
679                         break;
680
681                 case KEY_ENTER:
682                         cutscenes_screen_play();
683                         break;
684
685                 case KEY_ESC:  // cancel
686                         gameseq_post_event(GS_EVENT_MAIN_MENU);
687                         game_flush();
688                         break;
689
690                 case KEY_F1:  // show help overlay
691                         break;
692
693                 case KEY_F2:  // goto options screen
694                         gameseq_post_event(GS_EVENT_OPTIONS_MENU);
695                         break;
696         }       // end switch
697
698         for (i=0; i<NUM_BUTTONS; i++){
699                 if (Buttons[gr_screen.res][i].button.pressed()){
700                         if (cutscenes_screen_button_pressed(i)){
701                                 return;
702                         }
703                 }
704         }
705
706         if (List_region.button_down()) {
707                 List_region.get_mouse_pos(NULL, &y);
708                 z = Scroll_offset + y / font_height;
709                 if ((z >= 0) && (z < Num_files))
710                         select_tease_line = z;
711         }
712         
713         if (List_region.pressed()) {
714                 List_region.get_mouse_pos(NULL, &y);
715                 z = Scroll_offset + y / font_height;
716                 if ((z >= 0) && (z < Num_files))
717                         Selected_line = z;
718         }
719
720         GR_MAYBE_CLEAR_RES(Background_bitmap);
721         if (Background_bitmap >= 0) {
722                 gr_set_bitmap(Background_bitmap);
723                 gr_bitmap(0, 0);
724         } 
725
726         Ui_window.draw();
727
728         for (i=TECH_DATABASE_BUTTON; i<=CREDITS_BUTTON; i++){
729                 if (Buttons[gr_screen.res][i].button.button_down()){
730                         break;
731                 }
732         }
733
734         if (i > CREDITS_BUTTON){
735                 Buttons[gr_screen.res][CUTSCENES_BUTTON].button.draw_forced(2);
736         }
737
738         y = 0;
739         z = Scroll_offset;
740         while (y + font_height <= Cutscene_list_coords[gr_screen.res][3]) {
741                 if (z >= Num_files){
742                         break;
743                 }
744
745                 if (z == Selected_line){
746                         gr_set_color_fast(&Color_text_selected);
747                 } else if (z == select_tease_line) {
748                         gr_set_color_fast(&Color_text_subselected);
749                 } else {
750                         gr_set_color_fast(&Color_text_normal);
751                 }
752
753                 gr_printf(Cutscene_list_coords[gr_screen.res][0], Cutscene_list_coords[gr_screen.res][1] + y, Cutscenes[Cutscene_list[z]].name);
754
755                 y += font_height;
756                 z++;
757         }
758
759         if (Description_index != Selected_line) {
760                 char *src;
761
762                 Description_index = Selected_line;
763                 Text_size = 0;
764                 src = Cutscenes[Cutscene_list[Description_index]].description;
765                 if (src) {
766                         Text_size = split_str(src, Cutscene_desc_coords[gr_screen.res][2], Text_line_size, Text_lines, Cutscene_max_text_lines[gr_screen.res]);
767                         Assert(Text_size >= 0 && Text_size < Cutscene_max_text_lines[gr_screen.res]);
768                 }
769         }
770
771         if (Description_index >= 0) {
772                 int len;
773                 char line[MAX_TEXT_LINE_LEN + 1];
774
775                 gr_set_color_fast(&Color_text_normal);
776
777                 y = 0;
778                 z = Text_offset;
779                 while (y + font_height <= Cutscene_desc_coords[gr_screen.res][3]) {
780                         if (z >= Text_size)
781                                 break;
782
783                         len = Text_line_size[z];
784                         if (len > MAX_TEXT_LINE_LEN)
785                                 len = MAX_TEXT_LINE_LEN;
786
787                         strncpy(line, Text_lines[z], len);
788                         line[len] = 0;
789                         gr_string(Cutscene_desc_coords[gr_screen.res][0], Cutscene_desc_coords[gr_screen.res][1] + y, line);
790
791                         y += font_height;
792                         z++;
793                 }
794         }
795
796         gr_flip();
797 }
798