]> icculus.org git repositories - taylor/freespace2.git/blob - src/menuui/credits.cpp
fix special dot sliders in FS1
[taylor/freespace2.git] / src / menuui / credits.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/MenuUI/Credits.cpp $
11  * $Revision$
12  * $Date$
13  * $Author$
14  *
15  * C source file for displaying game credits
16  *
17  * $Log$
18  * Revision 1.9  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.8  2004/09/20 01:31:44  theoddone33
26  * GCC 3.4 fixes.
27  *
28  * Revision 1.7  2003/08/03 16:10:29  taylor
29  * cleanup; compile warning fixes
30  *
31  * Revision 1.6  2003/06/11 18:30:32  taylor
32  * plug memory leaks
33  *
34  * Revision 1.5  2003/05/25 02:30:42  taylor
35  * Freespace 1 support
36  *
37  * Revision 1.4  2002/06/09 04:41:22  relnev
38  * added copyright header
39  *
40  * Revision 1.3  2002/05/27 22:43:02  theoddone33
41  * Fix more glide symbols
42  *
43  * Revision 1.2  2002/05/07 03:16:46  theoddone33
44  * The Great Newline Fix
45  *
46  * Revision 1.1.1.1  2002/05/03 03:28:09  root
47  * Initial import.
48  *
49  * 
50  * 20    9/14/99 5:14a Dave
51  * Fixed credits drawing in Glide.
52  * 
53  * 19    9/13/99 1:53p Dave
54  * Fixed completely brain dead code in credits_init().
55  * 
56  * 18    9/09/99 10:55a Jefff
57  * 
58  * 17    9/03/99 11:45a Jefff
59  * 
60  * 16    9/01/99 5:28p Jefff
61  * hi res art shows up now
62  * 
63  * 15    9/01/99 4:20p Jefff
64  * mo' pictures
65  * 
66  * 14    9/01/99 12:19p Jefff
67  * text splitting for long lines
68  * 
69  * 13    7/19/99 2:13p Dave
70  * Added some new strings for Heiko.
71  * 
72  * 12    2/03/99 6:06p Dave
73  * Groundwork for FS2 PXO usertracker support.  Gametracker support next.
74  * 
75  * 11    2/03/99 11:44a Dave
76  * Fixed d3d transparent textures.
77  * 
78  * 10    2/01/99 5:55p Dave
79  * Removed the idea of explicit bitmaps for buttons. Fixed text
80  * highlighting for disabled gadgets.
81  * 
82  * 9     1/30/99 9:01p Dave
83  * Coord fixes.
84  * 
85  * 8     1/30/99 5:08p Dave
86  * More new hi-res stuff.Support for nice D3D textures.
87  * 
88  * 7     1/29/99 12:47a Dave
89  * Put in sounds for beam weapon. A bunch of interface screens (tech
90  * database stuff).
91  * 
92  * 6     1/28/99 1:46a Dave
93  * Updated coords and bitmaps.
94  * 
95  * 5     1/14/99 5:15p Neilk
96  * changed credits, command debrief interfaces to high resolution support
97  * 
98  * 4     11/20/98 4:08p Dave
99  * Fixed flak effect in multiplayer.
100  * 
101  * 3     10/13/98 9:28a Dave
102  * Started neatening up freespace.h. Many variables renamed and
103  * reorganized. Added AlphaColors.[h,cpp]
104  * 
105  * 2     10/07/98 10:53a Dave
106  * Initial checkin.
107  * 
108  * 1     10/07/98 10:49a Dave
109  * 
110  * 18    6/19/98 3:51p Lawrance
111  * deal with foreign chars in the credits
112  * 
113  * 17    6/01/98 11:43a John
114  * JAS & MK:  Classified all strings for localization.
115  * 
116  * 16    5/24/98 9:01p Lawrance
117  * Add commit sounds when accept is pressed
118  * 
119  * 15    5/20/98 1:04p Hoffoss
120  * Made credits screen use new artwork and removed rating field usage from
121  * Fred (a goal struct member).
122  * 
123  * 14    5/12/98 4:17p Hoffoss
124  * Make ctrl-arrows (up/down) switch between tech room screens.
125  * 
126  * 13    5/12/98 11:21a Hoffoss
127  * Disabled cutscene screen and simulator room.
128  * 
129  * 12    5/11/98 8:04p Hoffoss
130  * Fixed minor bugs.
131  * 
132  * 11    4/22/98 3:35p John
133  * String externalization marking
134  * 
135  * 10    4/22/98 10:46a Hoffoss
136  * Added images to credits screen.
137  * 
138  * 9     4/21/98 7:07p Hoffoss
139  * Fixed problem where when switching screens flashes old tab hilight once
140  * before switching to new state.
141  * 
142  * 8     4/17/98 3:28p Hoffoss
143  * Added new credits screen code.
144  * 
145  * 7     3/05/98 11:15p Hoffoss
146  * Changed non-game key checking to use game_check_key() instead of
147  * game_poll().
148  * 
149  * 6     2/22/98 12:19p John
150  * Externalized some strings
151  * 
152  * 5     1/05/98 2:30p John
153  * made credits.tbl display
154  * 
155  * 4     9/19/97 5:14p Lawrance
156  * use new naming convention for spooled music
157  * 
158  * 3     8/31/97 6:38p Lawrance
159  * pass in frametime to do_frame loop
160  * 
161  * 2     4/22/97 11:06a Lawrance
162  * credits music playing, credits screen is a separate state
163  *
164  * $NoKeywords: $
165  */
166
167 #include <stdlib.h>
168
169 #include "gamesequence.h"
170 #include "font.h"
171 #include "key.h"
172 #include "bmpman.h"
173 #include "2d.h"
174 #include "timer.h"
175 #include "gamesnd.h"
176 #include "audiostr.h"
177 #include "eventmusic.h" /* for Master_event_music_volume */
178 #include "cfile.h"
179 #include "ui.h"
180 #include "missionscreencommon.h"
181 #include "player.h"
182 #include "freespace.h"
183 #include "alphacolors.h"
184 #include "localize.h"
185
186 #define CREDITS_MUSIC_DELAY     2000
187 #define CREDITS_SCROLL_RATE     15.0f
188 #define CREDITS_ARTWORK_DISPLAY_TIME    9.0f
189 #define CREDITS_ARTWORK_FADE_TIME               1.0f
190
191 #define NUM_BUTTONS                             5
192 #define NUM_IMAGES                              46
193
194 #define TECH_DATABASE_BUTTON    0
195 #define SIMULATOR_BUTTON                1
196 #define CUTSCENES_BUTTON                2
197 #define CREDITS_BUTTON                  3
198 #define EXIT_BUTTON                             4
199
200 // inidicies for coordinates
201 #define CREDITS_X_COORD 0
202 #define CREDITS_Y_COORD 1
203 #define CREDITS_W_COORD 2
204 #define CREDITS_H_COORD 3
205
206 static const char* Credits_bitmap_fname[GR_NUM_RESOLUTIONS] = {
207         "Credits",                      // GR_640
208         "2_Credits"
209 };
210
211 static const char* Credits_bitmap_mask_fname[GR_NUM_RESOLUTIONS] = {
212         "Credits-M",                    // GR_640
213         "2_Credits-M"
214 };
215
216 int Credits_image_coords[GR_NUM_RESOLUTIONS][4] = {
217         {
218 #ifdef MAKE_FS1
219                 225, 15, 400, 292
220 #else
221                 219, 15, 394, 286                       // GR_640
222 #endif
223         },
224         {
225                 351, 25, 629, 455                       // GR_1024
226         }
227 };
228
229 // x, y, w, h
230 int Credits_text_coords[GR_NUM_RESOLUTIONS][4] = {
231         {
232 #ifdef MAKE_FS1
233                 46, 321, 450, 134
234 #else
235                 26, 316, 482, 157                       // GR_640
236 #endif
237         },
238         {
239                 144, 507, 568, 249                      // GR_640
240         }
241 };
242
243 struct credits_screen_buttons {
244         const char *filename;
245         int x, y, xt, yt;
246         int hotspot;
247         UI_BUTTON button;  // because we have a class inside this struct, we need the constructor below..
248
249         credits_screen_buttons(const char *name, int x1, int y1, int xt1, int yt1, int h) : filename(name), x(x1), y(y1), xt(xt1), yt(yt1), hotspot(h) {}
250 };
251
252 static int Background_bitmap;
253 #ifdef MAKE_FS1
254 static int CreditsWin01 = -1;
255 static int CreditsWin02 = -1;
256 static int CreditsWin03 = -1;
257 static int CreditsWin04 = -1;
258 #endif
259
260 static UI_WINDOW Ui_window;
261
262 static credits_screen_buttons Buttons[NUM_BUTTONS][GR_NUM_RESOLUTIONS] = {
263 //XSTR:OFF
264 #ifdef MAKE_FS1
265     {
266                         credits_screen_buttons("TDB_00", 0, 0, -1, -1, 0),              // GR_640
267                         credits_screen_buttons("2_TDB_00", 12, 5, 59, 12, 0)            // GR_1024
268     },
269     {
270                         credits_screen_buttons("TDB_01", 0, 19, -1, -1, 1),             // GR_640
271                         credits_screen_buttons("2_TDB_01", 12, 31, 59, 37, 1)           // GR_1024
272     },
273     {
274                         credits_screen_buttons("TDB_02", 0, 35, -1, -1, 2),             // GR_640
275                         credits_screen_buttons("2_TDB_02", 12, 56, 59, 62, 2)           // GR_1024
276     },
277     {
278                         credits_screen_buttons("TDB_03", 0, 56, -1, -1, 3),             // GR_640
279                         credits_screen_buttons("2_TDB_03", 12, 81, 59, 88, 3)           // GR_1024
280     },
281     {
282                         credits_screen_buttons("CRB_04", 561, 411, -1, -1, 4),  // GR_640
283                         credits_screen_buttons("2_CRB_04", 914, 681, 953, 68, 4)        // GR_1024
284     }
285 #else
286         {
287                         credits_screen_buttons("TDB_00", 7, 3, 37, 7, 0),                       // GR_640
288                         credits_screen_buttons("2_TDB_00", 12, 5, 59, 12, 0)                    // GR_1024
289         },
290         {
291                         credits_screen_buttons("TDB_01", 7, 18, 37, 23, 1),             // GR_640
292                         credits_screen_buttons("2_TDB_01", 12, 31, 59, 37, 1)           // GR_1024
293         },
294         {
295                         credits_screen_buttons("TDB_02", 7, 34, 37, 38, 2),             // GR_640
296                         credits_screen_buttons("2_TDB_02", 12, 56, 59, 62, 2)           // GR_1024
297         },
298         {
299                         credits_screen_buttons("TDB_03", 7, 49, 37, 54, 3),             // GR_640
300                         credits_screen_buttons("2_TDB_03", 12, 81, 59, 88, 3)           // GR_1024
301         },
302         {
303                         credits_screen_buttons("CRB_04", 571, 425, 588, 413, 4),        // GR_640
304                         credits_screen_buttons("2_CRB_04", 914, 681, 953, 668, 4)       // GR_1024
305         }
306 #endif
307 //XSTR:ON
308 };
309
310 static int      Credits_music_handle = -1;
311 static int      Credits_music_begin_timestamp;
312
313 static int      Credits_frametime;              // frametime of credits_do_frame() loop in ms
314 static int      Credits_last_time;              // timestamp used to calc frametime (in ms)
315 static float Credits_counter;
316 static int Credits_artwork_index;
317 static int Credits_bmps[NUM_IMAGES];
318
319 char *Credit_text = NULL;
320
321 // Positions for credits...
322 float Credit_start_pos, Credit_stop_pos, Credit_position = 0.0f;
323
324 void credits_stop_music()
325 {
326         if ( Credits_music_handle != -1 ) {
327                 audiostream_close_file(Credits_music_handle);
328                 Credits_music_handle = -1;
329         }
330 }
331
332 void credits_load_music(const char* fname)
333 {
334         if ( Credits_music_handle != -1 ){
335                 return;
336         }
337
338         if ( fname ){
339                 Credits_music_handle = audiostream_open( fname, ASF_EVENTMUSIC );
340         }
341 }
342
343 void credits_start_music()
344 {
345         if (Credits_music_handle != -1) {
346                 if ( !audiostream_is_playing(Credits_music_handle) ){
347                         audiostream_play(Credits_music_handle, Master_event_music_volume);
348                 }
349         } else {
350                 nprintf(("Warning", "Cannot play credits music\n"));
351         }
352 }
353
354 int credits_screen_button_pressed(int n)
355 {
356         switch (n) {
357         case TECH_DATABASE_BUTTON:
358                 gamesnd_play_iface(SND_SWITCH_SCREENS);
359                 gameseq_post_event(GS_EVENT_TECH_MENU);
360                 return 1;
361
362         case SIMULATOR_BUTTON:
363                 gamesnd_play_iface(SND_SWITCH_SCREENS);
364                 gameseq_post_event(GS_EVENT_SIMULATOR_ROOM);
365                 return 1;
366
367         case CUTSCENES_BUTTON:
368                 gamesnd_play_iface(SND_SWITCH_SCREENS);
369                 gameseq_post_event(GS_EVENT_GOTO_VIEW_CUTSCENES_SCREEN);
370                 return 1;
371
372         case EXIT_BUTTON:
373                 gamesnd_play_iface(SND_COMMIT_PRESSED);
374                 gameseq_post_event(GS_EVENT_MAIN_MENU);
375                 game_flush();
376                 break;
377         }
378
379         return 0;
380 }
381
382 void credits_init()
383 {
384         int i, w, h;
385         credits_screen_buttons *b;
386         char line[512] = "";    
387         char *linep1, *linep2;  
388
389         int credits_spooled_music_index = event_music_get_spooled_music_index("Cinema");        
390         if(credits_spooled_music_index != -1){
391                 char *credits_wavfile_name = Spooled_music[credits_spooled_music_index].filename;               
392                 if(credits_wavfile_name != NULL){
393                         credits_load_music(credits_wavfile_name);
394                 }
395         }
396
397         // Use this id to trigger the start of music playing on the briefing screen
398         Credits_music_begin_timestamp = timestamp(CREDITS_MUSIC_DELAY);
399
400         Credits_frametime = 0;
401         Credits_last_time = timer_get_milliseconds();
402
403         Credit_text = NULL;
404
405         // allocate enough space for credits text
406         CFILE *fp = cfopen( NOX("credits.tbl"), "rb" );
407         if(fp != NULL){
408                 int size;
409                 size = cfilelength(fp);
410                 Credit_text = (char *) malloc(size + 200);
411                 cfclose(fp);
412
413                 // open localization and parse
414                 lcl_ext_open();
415
416                 try {
417                         read_file_text("credits.tbl");
418                         reset_parse();
419
420                         // keep reading everything in
421                         SDL_strlcpy(Credit_text, "", size+200);
422 #ifndef MAKE_FS1
423                         while(!check_for_string_raw("#end")){
424 #else
425                         char *ugh = Mp;
426                         char ch;
427                         int line_count = 0;
428
429                         // get the line count, probably a crappy way to do it but it's the best way i've
430                         // found to step through the credits without crashing problems since there's no
431                         // definite end line in FS1
432                         while (*ugh && *ugh != EOF_CHAR) {
433                                 ch = *ugh;
434
435                                 if (ch == '\n'){
436                                         line_count++;
437                                 }
438                                 ugh++;
439                         }
440
441                         while(line_count > 0){
442                                 line_count--;
443 #endif
444                                 stuff_string_line(line, 511);
445                                 linep1 = line;
446
447                                 do {
448                                         linep2 = split_str_once(linep1, Credits_text_coords[gr_screen.res][2]);
449                                         SDL_strlcat(Credit_text, linep1, size+200);
450                                         SDL_strlcat(Credit_text, "\n", size+200);
451                                         linep1 = linep2;
452                                 } while (linep2 != NULL);
453                         }
454                 } catch (parse_error_t rval) {
455                         (void)rval;     // suppress unused warning in release build
456                         mprintf(("Error parsing 'credits.tbl'\nError code = %i.\n", (int)rval));
457                 }
458
459                 // close localization
460                 lcl_ext_close();        
461         } else {
462                 Credit_text = (char *) malloc(25 + 200);
463                 SDL_strlcpy(Credit_text, NOX("No credits available.\n"), 25+200);
464         }       
465
466         int ch;
467         for ( i = 0; Credit_text[i]; i++ ) {
468                         ch = Credit_text[i];
469                         switch (ch) {
470                         case -4:
471                                 ch = 129;
472                                 break;
473
474                         case -28:
475                                 ch = 132;
476                                 break;
477
478                         case -10:
479                                 ch = 148;
480                                 break;
481
482                         case -23:
483                                 ch = 130;
484                                 break;
485
486                         case -30:
487                                 ch = 131;
488                                 break;
489
490                         case -25:
491                                 ch = 135;
492                                 break;
493
494                         case -21:
495                                 ch = 137;
496                                 break;
497
498                         case -24:
499                                 ch = 138;
500                                 break;
501
502                         case -17:
503                                 ch = 139;
504                                 break;
505
506                         case -18:
507                                 ch = 140;
508                                 break;
509
510                         case -60:
511                                 ch = 142;
512                                 break;
513
514                         case -55:
515                                 ch = 144;
516                                 break;
517
518                         case -12:
519                                 ch = 147;
520                                 break;
521
522                         case -14:
523                                 ch = 149;
524                                 break;
525
526                         case -5:
527                                 ch = 150;
528                                 break;
529
530                         case -7:
531                                 ch = 151;
532                                 break;
533
534                         case -42:
535                                 ch = 153;
536                                 break;
537
538                         case -36:
539                                 ch = 154;
540                                 break;
541
542                         case -31:
543                                 ch = 160;
544                                 break;
545
546                         case -19:
547                                 ch = 161;
548                                 break;
549
550                         case -13:
551                                 ch = 162;
552                                 break;
553
554                         case -6:
555                                 ch = 163;
556                                 break;
557
558                         case -32:
559                                 ch = 133;
560                                 break;
561
562                         case -22:
563                                 ch = 136;
564                                 break;
565
566                         case -20:
567                                 ch = 141;
568                                 break;
569                         }
570                         Credit_text[i] = (char)ch;
571         }
572
573         gr_get_string_size(&w, &h, Credit_text);
574
575         Credit_start_pos = i2fl(Credits_text_coords[gr_screen.res][CREDITS_H_COORD]);
576         Credit_stop_pos = -i2fl(h);
577         Credit_position = Credit_start_pos;
578
579         Ui_window.create(0, 0, gr_screen.max_w, gr_screen.max_h, 0);
580         Ui_window.set_mask_bmap(Credits_bitmap_mask_fname[gr_screen.res]);
581         common_set_interface_palette("InterfacePalette");  // set the interface palette
582
583         for (i=0; i<NUM_BUTTONS; i++) {
584                 b = &Buttons[i][gr_screen.res];
585
586                 b->button.create(&Ui_window, "", b->x, b->y, 60, 30, (i < 2), 1);
587                 // set up callback for when a mouse first goes over a button
588                 b->button.set_highlight_action(common_play_highlight_sound);
589                 b->button.set_bmaps(b->filename);
590                 b->button.link_hotspot(b->hotspot);
591         }
592
593 #ifndef MAKE_FS1
594         // add some text
595         Ui_window.add_XSTR("Technical Database", 1055, Buttons[TECH_DATABASE_BUTTON][gr_screen.res].xt,  Buttons[TECH_DATABASE_BUTTON][gr_screen.res].yt, &Buttons[TECH_DATABASE_BUTTON][gr_screen.res].button, UI_XSTR_COLOR_GREEN);
596         Ui_window.add_XSTR("Mission Simulator", 1056, Buttons[SIMULATOR_BUTTON][gr_screen.res].xt,  Buttons[SIMULATOR_BUTTON][gr_screen.res].yt, &Buttons[SIMULATOR_BUTTON][gr_screen.res].button, UI_XSTR_COLOR_GREEN);
597         Ui_window.add_XSTR("Cutscenes", 1057, Buttons[CUTSCENES_BUTTON][gr_screen.res].xt,  Buttons[CUTSCENES_BUTTON][gr_screen.res].yt, &Buttons[CUTSCENES_BUTTON][gr_screen.res].button, UI_XSTR_COLOR_GREEN);
598         Ui_window.add_XSTR("Credits", 1058, Buttons[CREDITS_BUTTON][gr_screen.res].xt,  Buttons[CREDITS_BUTTON][gr_screen.res].yt, &Buttons[CREDITS_BUTTON][gr_screen.res].button, UI_XSTR_COLOR_GREEN);
599         Ui_window.add_XSTR("Exit", 1420, Buttons[EXIT_BUTTON][gr_screen.res].xt,  Buttons[EXIT_BUTTON][gr_screen.res].yt, &Buttons[EXIT_BUTTON][gr_screen.res].button, UI_XSTR_COLOR_PINK);
600 #endif
601
602         if (Player->flags & PLAYER_FLAGS_IS_MULTI) {
603                 Buttons[SIMULATOR_BUTTON][gr_screen.res].button.disable();
604                 Buttons[CUTSCENES_BUTTON][gr_screen.res].button.disable();
605         }
606
607         Buttons[EXIT_BUTTON][gr_screen.res].button.set_hotkey(KEY_CTRLED | SDLK_RETURN);
608
609         Background_bitmap = bm_load(Credits_bitmap_fname[gr_screen.res]);
610         Credits_artwork_index = rand() % NUM_IMAGES;
611         for (i=0; i<NUM_IMAGES; i++){
612                 Credits_bmps[i] = -1;
613         }
614
615 #ifdef MAKE_FS1
616         CreditsWin01 = bm_load(NOX("CreditsWin01"));
617         CreditsWin02 = bm_load(NOX("CreditsWin02"));
618         CreditsWin03 = bm_load(NOX("CreditsWin03"));
619         CreditsWin04 = bm_load(NOX("CreditsWin04"));
620 #endif
621 }
622
623 void credits_close()
624 {       
625         int i;
626
627 #ifdef MAKE_FS1
628         if (CreditsWin01 != -1){
629                 bm_unload(CreditsWin01);
630                 CreditsWin01 = -1;
631         }
632         if (CreditsWin02 != -1){
633                 bm_unload(CreditsWin02);
634                 CreditsWin02 = -1;
635         }
636         if (CreditsWin03 != -1){
637                 bm_unload(CreditsWin03);
638                 CreditsWin03 = -1;
639         }
640         if (CreditsWin04 != -1){
641                 bm_unload(CreditsWin04);
642                 CreditsWin04 = -1;
643         }
644 #endif
645
646         for (i=0; i<NUM_IMAGES; i++){
647                 if (Credits_bmps[i] >= 0){
648                         bm_unload(Credits_bmps[i]);
649                         Credits_bmps[i] = -1;
650                 }
651         }       
652
653         credits_stop_music();
654
655         if (Credit_text) {
656                 free(Credit_text);
657                 Credit_text = NULL;
658         }
659
660         if (Background_bitmap){
661                 bm_unload(Background_bitmap);
662         }
663
664         Ui_window.destroy();
665         common_free_interface_palette();                // restore game palette
666 }
667
668 void credits_do_frame(float frametime)
669 {
670         int i, k, next, percent, bm1, bm2;
671         int bx1, by1, bw1, bh1;
672         int bx2, by2, bw2, bh2;
673
674         // Use this id to trigger the start of music playing on the credits screen
675         if ( timestamp_elapsed(Credits_music_begin_timestamp) ) {
676                 Credits_music_begin_timestamp = 0;
677                 credits_start_music();
678         }
679
680         k = Ui_window.process();
681         switch (k) {
682         case SDLK_ESCAPE:
683                 gameseq_post_event(GS_EVENT_MAIN_MENU);
684                 key_flush();
685                 break;
686
687         case KEY_CTRLED | SDLK_UP:
688         case KEY_SHIFTED | SDLK_TAB:
689                 if ( !(Player->flags & PLAYER_FLAGS_IS_MULTI) ) {
690                         credits_screen_button_pressed(CUTSCENES_BUTTON);
691                         break;
692                 }
693                 // else, react like tab key.
694
695         case KEY_CTRLED | SDLK_DOWN:
696         case SDLK_TAB:
697                 credits_screen_button_pressed(TECH_DATABASE_BUTTON);
698                 break;
699
700         default:
701                 break;
702         } // end switch
703
704         for (i=0; i<NUM_BUTTONS; i++){
705                 if (Buttons[i][gr_screen.res].button.pressed()){
706                         if (credits_screen_button_pressed(i)){
707                                 return;
708                         }
709                 }
710         }
711
712         gr_reset_clip();        
713         GR_MAYBE_CLEAR_RES(Background_bitmap);
714         if (Background_bitmap >= 0) {
715                 gr_set_bitmap(Background_bitmap, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
716                 gr_bitmap(0, 0);
717         } 
718
719         percent = (int) (100.0f - (CREDITS_ARTWORK_DISPLAY_TIME - Credits_counter) * 100.0f / CREDITS_ARTWORK_FADE_TIME);
720         if (percent < 0){
721                 percent = 0;
722         }
723
724         next = Credits_artwork_index + 1;
725         if (next >= NUM_IMAGES){
726                 next = 0;
727         }
728
729         if (Credits_bmps[Credits_artwork_index] < 0) {
730                 char buf[40];
731
732                 if (gr_screen.res == GR_1024) {
733                         SDL_snprintf(buf, SDL_arraysize(buf), NOX("2_CrIm%.2d"), Credits_artwork_index);
734                 } else {
735                         SDL_snprintf(buf, SDL_arraysize(buf), NOX("CrIm%.2d"), Credits_artwork_index);
736                 }
737                 Credits_bmps[Credits_artwork_index] = bm_load(buf);
738         }
739
740         if (Credits_bmps[next] < 0) {
741                 char buf[40];
742
743                 if (gr_screen.res == GR_1024) {
744                         SDL_snprintf(buf, SDL_arraysize(buf), NOX("2_CrIm%.2d"), Credits_artwork_index);
745                 } else {
746                         SDL_snprintf(buf, SDL_arraysize(buf), NOX("CrIm%.2d"), next);
747                 }
748                 Credits_bmps[next] = bm_load(buf);
749         }
750
751         bm1 = Credits_bmps[Credits_artwork_index];
752         bm2 = Credits_bmps[next];
753
754         if((bm1 != -1) && (bm2 != -1)){
755                 SDL_assert(percent >= 0 && percent <= 100);
756
757                 // get width and height
758                 bm_get_info(bm1, &bw1, &bh1, NULL, NULL, NULL); 
759                 bm_get_info(bm2, &bw2, &bh2, NULL, NULL, NULL); 
760         
761                 // determine where to draw the coords
762                 bx1 = Credits_image_coords[gr_screen.res][CREDITS_X_COORD] + ((Credits_image_coords[gr_screen.res][CREDITS_W_COORD] - bw1)/2);
763                 by1 = Credits_image_coords[gr_screen.res][CREDITS_Y_COORD] + ((Credits_image_coords[gr_screen.res][CREDITS_H_COORD] - bh1)/2);
764                 bx2 = Credits_image_coords[gr_screen.res][CREDITS_X_COORD] + ((Credits_image_coords[gr_screen.res][CREDITS_W_COORD] - bw2)/2);
765                 by2 = Credits_image_coords[gr_screen.res][CREDITS_Y_COORD] + ((Credits_image_coords[gr_screen.res][CREDITS_H_COORD] - bh2)/2);
766
767                 gr_cross_fade(bm1, bm2, bx1, by1, bx2, by2, (float)percent / 100.0f);
768         }
769
770 #ifdef MAKE_FS1
771         if (CreditsWin01 != -1) {
772                 gr_set_bitmap(CreditsWin01, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
773                 gr_bitmap(233, 5);
774         }
775
776         if (CreditsWin02 != -1) {
777                 gr_set_bitmap(CreditsWin02, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
778                 gr_bitmap(616, 8);
779         }
780
781         if (CreditsWin03 != -1) {
782                 gr_set_bitmap(CreditsWin03, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
783                 gr_bitmap(233, 299);
784         }
785
786         if (CreditsWin04 != -1) {
787                 gr_set_bitmap(CreditsWin04, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
788                 gr_bitmap(215, 8);
789         }
790 #endif
791
792         Ui_window.draw();
793
794         for (i=TECH_DATABASE_BUTTON; i<=CREDITS_BUTTON; i++){
795                 if (Buttons[i][gr_screen.res].button.button_down()){
796                         break;
797                 }
798         }
799
800         if (i > CREDITS_BUTTON){
801                 Buttons[CREDITS_BUTTON][gr_screen.res].button.draw_forced(2);
802         }
803
804         gr_set_clip(Credits_text_coords[gr_screen.res][CREDITS_X_COORD], Credits_text_coords[gr_screen.res][CREDITS_Y_COORD], Credits_text_coords[gr_screen.res][CREDITS_W_COORD], Credits_text_coords[gr_screen.res][CREDITS_H_COORD]);
805         gr_set_font(FONT1);
806         gr_set_color_fast(&Color_normal);
807
808         int sy;
809         if ( Credit_position > 0 ) {
810                 sy = fl2i(Credit_position+0.5f);
811         } else {
812                 sy = fl2i(Credit_position-0.5f);
813         }
814
815         gr_string(0x8000, sy, Credit_text);
816
817         int temp_time;
818         temp_time = timer_get_milliseconds();
819
820         Credits_frametime = temp_time - Credits_last_time;
821         Credits_last_time = temp_time;
822         timestamp_inc(Credits_frametime / 1000.0f);
823
824         float fl_frametime = i2fl(Credits_frametime) / 1000.f;
825         if (key_pressed(SDLK_LSHIFT)) {
826                 Credit_position -= fl_frametime * CREDITS_SCROLL_RATE * 4.0f;
827         } else {
828                 Credit_position -= fl_frametime * CREDITS_SCROLL_RATE;
829         }
830
831         if (Credit_position < Credit_stop_pos){
832                 Credit_position = Credit_start_pos;
833         }
834
835         Credits_counter += fl_frametime;
836         while (Credits_counter >= CREDITS_ARTWORK_DISPLAY_TIME) {
837                 Credits_counter -= CREDITS_ARTWORK_DISPLAY_TIME;
838                 Credits_artwork_index = next;
839         }
840
841         gr_flip();
842 }
843