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