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