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