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