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