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