- fixed file extension, removed pwd.h header
[supertux.git] / src / gameloop.cpp
1 /*
2   gameloop.c
3   
4   Super Tux - Game Loop!
5   
6   by Bill Kendrick & Tobias Glaesser
7   bill@newbreedsoftware.com
8   http://www.newbreedsoftware.com/supertux/
9   
10   April 11, 2000 - March 15, 2004
11  */
12
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <string.h>
16 #include <errno.h>
17 #include <unistd.h>
18 #include <time.h>
19 #include <SDL.h>
20
21 #ifndef WIN32
22 #include <sys/types.h>
23 #include <ctype.h>
24 #endif
25
26 #include "defines.h"
27 #include "globals.h"
28 #include "gameloop.h"
29 #include "screen.h"
30 #include "setup.h"
31 #include "high_scores.h"
32 #include "menu.h"
33 #include "badguy.h"
34 #include "world.h"
35 #include "special.h"
36 #include "player.h"
37 #include "level.h"
38 #include "scene.h"
39 #include "collision.h"
40
41 /* extern variables */
42
43 st_level current_level;
44 int game_started = NO;
45
46 /* Local variables: */
47
48 static texture_type img_waves[3], img_water, img_pole, img_poletop, img_flag[2];
49 static texture_type img_cloud[2][4];
50 static SDL_Event event;
51 static SDLKey key;
52 static char level_subset[100];
53 static char str[60];
54 static float fps_fps;
55 static int st_gl_mode;
56 static unsigned int last_update_time;
57 static unsigned int update_time;
58 static int pause_menu_frame;
59 static int debug_fps;
60
61 /* Local function prototypes: */
62
63 void levelintro(void);
64 void loadshared(void);
65 void unloadshared(void);
66 void drawstatus(void);
67 void drawendscreen(void);
68 void drawresultscreen(void);
69
70 #define JOYSTICK_DEAD_ZONE 4096
71
72 void levelintro(void)
73 {
74   /* Level Intro: */
75
76   clearscreen(0, 0, 0);
77
78   sprintf(str, "LEVEL %d", level);
79   text_drawf(&blue_text, str, 0, 200, A_HMIDDLE, A_TOP, 1, NO_UPDATE);
80
81   sprintf(str, "%s", current_level.name.c_str());
82   text_drawf(&gold_text, str, 0, 224, A_HMIDDLE, A_TOP, 1, NO_UPDATE);
83
84   sprintf(str, "TUX x %d", tux.lives);
85   text_drawf(&white_text, str, 0, 256, A_HMIDDLE, A_TOP, 1, NO_UPDATE);
86
87   flipscreen();
88
89   SDL_Delay(1000);
90 }
91
92 /* Reset Timers */
93 void start_timers(void)
94 {
95   timer_start(&time_left,current_level.time_left*1000);
96   st_pause_ticks_init();
97   update_time = st_get_ticks();
98 }
99
100 void activate_bad_guys(void)
101 {
102   int x,y;
103
104   /* Activate bad guys: */
105
106   for (y = 0; y < 15; y++)
107     {
108       for (x = 0; x < current_level.width; x++)
109         {
110           if (current_level.tiles[y][x] >= '0' && current_level.tiles[y][x] <= '9')
111             {
112               add_bad_guy(x * 32, y * 32, current_level.tiles[y][x] - '0');
113               current_level.tiles[y][x] = '.';
114             }
115         }
116     }
117
118 }
119
120 /* --- GAME EVENT! --- */
121
122 void game_event(void)
123 {
124   while (SDL_PollEvent(&event))
125     {
126       switch(event.type)
127         {
128         case SDL_QUIT:        /* Quit event - quit: */
129           quit = 1;
130           break;
131         case SDL_KEYDOWN:     /* A keypress! */
132           key = event.key.keysym.sym;
133
134           /* Check for menu-events, if the menu is shown */
135           if(show_menu)
136             menu_event(&event.key.keysym);
137
138           if(player_key_event(&tux,key,DOWN))
139             break;
140
141           switch(key)
142             {
143             case SDLK_ESCAPE:    /* Escape: Open/Close the menu: */
144               if(!game_pause)
145                 {
146                   if(st_gl_mode == ST_GL_TEST)
147                     quit = 1;
148                   else if(show_menu)
149                     {
150                       menu_set_current(&game_menu);
151                       show_menu = 0;
152                       st_pause_ticks_stop();
153                     }
154                   else
155                     {
156                       menu_set_current(&game_menu);
157                       show_menu = 1;
158                       st_pause_ticks_start();
159                     }
160                 }
161               break;
162             default:
163               break;
164             }
165           break;
166         case SDL_KEYUP:      /* A keyrelease! */
167           key = event.key.keysym.sym;
168
169           if(player_key_event(&tux,key,UP))
170             break;
171
172           switch(key)
173             {
174             case SDLK_p:
175               if(!show_menu)
176                 {
177                   if(game_pause)
178                     {
179                       game_pause = 0;
180                       st_pause_ticks_stop();
181                     }
182                   else
183                     {
184                       game_pause = 1;
185                       st_pause_ticks_start();
186                     }
187                 }
188               break;
189             case SDLK_TAB:
190               if(debug_mode == YES)
191                 {
192                   tux.size = !tux.size;
193                   if(tux.size == BIG)
194                     {
195                       tux.base.height = 64;
196                     }
197                   else
198                     tux.base.height = 32;
199                 }
200               break;
201             case SDLK_END:
202               if(debug_mode == YES)
203                 distros += 50;
204               break;
205             case SDLK_SPACE:
206               if(debug_mode == YES)
207                 next_level = 1;
208               break;
209             case SDLK_DELETE:
210               if(debug_mode == YES)
211                 tux.got_coffee = 1;
212               break;
213             case SDLK_INSERT:
214               if(debug_mode == YES)
215                 timer_start(&tux.invincible_timer,TUX_INVINCIBLE_TIME);
216               break;
217             case SDLK_l:
218               if(debug_mode == YES)
219                 --tux.lives;
220               break;
221             case SDLK_s:
222               if(debug_mode == YES)
223                 score += 1000;
224             case SDLK_f:
225               if(debug_fps == YES)
226               debug_fps = NO;
227               else
228               debug_fps = YES;
229               break;          
230             default:
231               break;
232             }
233           break;
234 #ifdef JOY_YES
235
236         case SDL_JOYAXISMOTION:
237           switch(event.jaxis.axis)
238             {
239             case JOY_X:
240               if (event.jaxis.value < -JOYSTICK_DEAD_ZONE)
241                 tux.input.left = DOWN;
242               else if (event.jaxis.value > JOYSTICK_DEAD_ZONE)
243                 tux.input.left = UP;
244
245               if (event.jaxis.value > JOYSTICK_DEAD_ZONE)
246                 tux.input.right = DOWN;
247               else if (event.jaxis.value < -JOYSTICK_DEAD_ZONE)
248                 tux.input.right = UP;
249               break;
250             case JOY_Y:
251               if (event.jaxis.value > JOYSTICK_DEAD_ZONE)
252                 tux.input.down = DOWN;
253               else if (event.jaxis.value < -JOYSTICK_DEAD_ZONE)
254                 tux.input.down = UP;
255
256               /* Handle joystick for the menu */
257               if(show_menu)
258                 {
259                   if(tux.input.down == DOWN)
260                     menuaction = MN_DOWN;
261                   else
262                     menuaction = MN_UP;
263                 }
264               break;
265             default:
266               break;
267             }
268           break;
269         case SDL_JOYBUTTONDOWN:
270           if (event.jbutton.button == JOY_A)
271             tux.input.up = DOWN;
272           else if (event.jbutton.button == JOY_B)
273             tux.input.fire = DOWN;
274           break;
275         case SDL_JOYBUTTONUP:
276           if (event.jbutton.button == JOY_A)
277             tux.input.up = UP;
278           else if (event.jbutton.button == JOY_B)
279             tux.input.fire = UP;
280
281           if(show_menu)
282             menuaction = MN_HIT;
283           break;
284
285 #endif
286         default:
287           break;
288
289         }  /* switch */
290
291     } /* while */
292
293 }
294
295 /* --- GAME ACTION! --- */
296
297 int game_action(void)
298 {
299   int i;
300
301   /* (tux_dying || next_level) */
302   if (tux.dying || next_level)
303     {
304       /* Tux either died, or reached the end of a level! */
305
306       halt_music();
307
308
309       if (next_level)
310         {
311           /* End of a level! */
312           level++;
313           next_level = 0;
314           if(st_gl_mode != ST_GL_TEST)
315             {
316               drawresultscreen();
317             }
318           else
319             {
320               level_free_gfx();
321               level_free(&current_level);
322               level_free_song();
323               unloadshared();
324               arrays_free();
325               return(0);
326             }
327           player_level_begin(&tux);
328         }
329       else
330         {
331           player_dying(&tux);
332
333           /* No more lives!? */
334
335           if (tux.lives < 0)
336             {
337               if(st_gl_mode != ST_GL_TEST)
338                 drawendscreen();
339
340               if(st_gl_mode != ST_GL_TEST)
341                 {
342                   if (score > hs_score)
343                     save_hs(score);
344                 }
345               level_free_gfx();
346               level_free(&current_level);
347               level_free_song();
348               unloadshared();
349               arrays_free();
350               return(0);
351             } /* if (lives < 0) */
352         }
353
354       /* Either way, (re-)load the (next) level... */
355
356       player_level_begin(&tux);
357       set_defaults();
358       level_free(&current_level);
359
360       if (st_gl_mode == ST_GL_LOAD_LEVEL_FILE)
361         {
362           if(level_load(&current_level, level_subset) != 0)
363             return 0;
364         }
365       else
366         {
367           if(level_load(&current_level,level_subset,level) != 0)
368             return 0;
369         }
370
371       arrays_free();
372       arrays_init();
373       activate_bad_guys();
374       level_free_gfx();
375       level_load_gfx(&current_level);
376       level_free_song();
377       level_load_song(&current_level);
378       if(st_gl_mode != ST_GL_TEST)
379         levelintro();
380       start_timers();
381       /* Play music: */
382       play_current_music();
383     }
384
385   player_action(&tux);
386
387   /* Handle bouncy distros: */
388
389   for (i = 0; i < num_bouncy_distros; i++)
390     {
391       bouncy_distro_action(&bouncy_distros[i]);
392     }
393
394
395   /* Handle broken bricks: */
396
397   for (i = 0; i < num_broken_bricks; i++)
398     {
399       broken_brick_action(&broken_bricks[i]);
400     }
401
402
403   /* Handle distro counting: */
404
405   if (counting_distros == YES)
406     {
407       distro_counter--;
408
409       if (distro_counter <= 0)
410         counting_distros = -1;
411     }
412
413
414   /* Handle bouncy bricks: */
415
416   for (i = 0; i < num_bouncy_bricks; i++)
417     {
418       bouncy_brick_action(&bouncy_bricks[i]);
419     }
420
421
422   /* Handle floating scores: */
423
424   for (i = 0; i < num_floating_scores; i++)
425     {
426       floating_score_action(&floating_scores[i]);
427     }
428
429
430   /* Handle bullets: */
431
432   for (i = 0; i < num_bullets; ++i)
433     {
434       bullet_action(&bullets[i]);
435     }
436
437   /* Handle upgrades: */
438
439   for (i = 0; i < num_upgrades; i++)
440     {
441       upgrade_action(&upgrades[i]);
442     }
443
444
445   /* Handle bad guys: */
446
447   for (i = 0; i < num_bad_guys; i++)
448     {
449       badguy_action(&bad_guys[i]);
450     }
451
452   /* Handle all possible collisions. */
453   collision_handler();
454
455   return -1;
456 }
457
458 /* --- GAME DRAW! --- */
459
460 void game_draw(void)
461 {
462   int  x, y, i, s;
463
464   /* Draw screen: */
465
466   if (tux.dying && (frame % 4) == 0)
467     clearscreen(255, 255, 255);
468   else if(timer_check(&super_bkgd_timer))
469     texture_draw(&img_super_bkgd, 0, 0, NO_UPDATE);
470   else
471     {
472       /* Draw the real background */
473       if(current_level.bkgd_image[0] != '\0')
474         {
475           s = (int)scroll_x / 30;
476           texture_draw_part(&img_bkgd,s,0,0,0,img_bkgd.w - s, img_bkgd.h, NO_UPDATE);
477           texture_draw_part(&img_bkgd,0,0,screen->w - s ,0,s,img_bkgd.h, NO_UPDATE);
478         }
479       else
480         {
481           clearscreen(current_level.bkgd_red, current_level.bkgd_green, current_level.bkgd_blue);
482         }
483     }
484
485   /* Draw background: */
486
487   for (y = 0; y < 15; ++y)
488     {
489       for (x = 0; x < 21; ++x)
490         {
491           drawshape(x * 32 - ((int)scroll_x % 32), y * 32,
492                     current_level.tiles[(int)y][(int)x + (int)(scroll_x / 32)]);
493         }
494     }
495
496
497   /* (Bouncy bricks): */
498
499   for (i = 0; i < num_bouncy_bricks; ++i)
500     {
501       bouncy_brick_draw(&bouncy_bricks[i]);
502     }
503
504
505   /* (Bad guys): */
506
507   for (i = 0; i < num_bad_guys; ++i)
508     {
509       badguy_draw(&bad_guys[i]);
510     }
511
512   /* (Tux): */
513
514   player_draw(&tux);
515
516   /* (Bullets): */
517
518   for (i = 0; i < num_bullets; ++i)
519     {
520       bullet_draw(&bullets[i]);
521     }
522
523   /* (Floating scores): */
524
525   for (i = 0; i < num_floating_scores; ++i)
526     {
527       floating_score_draw(&floating_scores[i]);
528     }
529
530
531   /* (Upgrades): */
532
533   for (i = 0; i < num_upgrades; ++i)
534     {
535       upgrade_draw(&upgrades[i]);
536     }
537
538
539   /* (Bouncy distros): */
540
541   for (i = 0; i < num_bouncy_distros; ++i)
542     {
543       bouncy_distro_draw(&bouncy_distros[i]);
544     }
545
546
547   /* (Broken bricks): */
548
549   for (i = 0; i < num_broken_bricks; ++i)
550     {
551       broken_brick_draw(&broken_bricks[i]);
552     }
553
554   drawstatus();
555
556
557   if(game_pause)
558     {
559       x = screen->h / 20;
560       for(i = 0; i < x; ++i)
561         {
562           fillrect(i % 2 ? (pause_menu_frame * i)%screen->w : -((pause_menu_frame * i)%screen->w) ,(i*20+pause_menu_frame)%screen->h,screen->w,10,20,20,20, rand() % 20 + 1);
563         }
564       fillrect(0,0,screen->w,screen->h,rand() % 50, rand() % 50, rand() % 50, 128);
565       text_drawf(&blue_text, "PAUSE - Press 'P' To Play", 0, 230, A_HMIDDLE, A_TOP, 1, NO_UPDATE);
566     }
567
568   if(show_menu)
569     menu_process_current();
570
571   /* (Update it all!) */
572
573   updatescreen();
574
575
576 }
577
578 /* --- GAME LOOP! --- */
579
580 int gameloop(const char * subset, int levelnb, int mode)
581 {
582   int fps_cnt, jump, done;
583   timer_type fps_timer, frame_timer;
584   timer_init(&fps_timer, YES);
585   timer_init(&frame_timer, YES);
586
587   game_started = YES;
588
589   st_gl_mode = mode;
590   level = levelnb;
591
592   /* Init the game: */
593   arrays_init();
594   set_defaults();
595
596   strcpy(level_subset,subset);
597
598   if (st_gl_mode == ST_GL_LOAD_LEVEL_FILE)
599     {
600       if (level_load(&current_level, level_subset))
601         exit(1);
602     }
603   else
604     {
605       if(level_load(&current_level, level_subset, level) != 0)
606         exit(1);
607     }
608
609   level_load_gfx(&current_level);
610   activate_bad_guys();
611   level_load_song(&current_level);
612
613   player_init(&tux);
614
615   if(st_gl_mode != ST_GL_TEST)
616     load_hs();
617
618   loadshared();
619
620   if(st_gl_mode == ST_GL_PLAY || st_gl_mode == ST_GL_LOAD_LEVEL_FILE)
621     levelintro();
622
623   timer_init(&time_left,YES);
624   start_timers();
625
626   if(st_gl_mode == ST_GL_LOAD_GAME)
627     loadgame(levelnb);
628
629
630   /* --- MAIN GAME LOOP!!! --- */
631
632   jump = NO;
633   done = 0;
634   quit = 0;
635   frame = 0;
636   game_pause = 0;
637   timer_init(&fps_timer,YES);
638   timer_init(&frame_timer,YES);
639   fps_cnt = 0;
640
641   /* Clear screen: */
642
643   clearscreen(0, 0, 0);
644   updatescreen();
645
646   /* Play music: */
647   play_current_music();
648
649
650   while (SDL_PollEvent(&event))
651   {}
652
653   game_draw();
654   do
655     {
656       jump = NO;
657
658       /* Calculate the movement-factor */
659       frame_ratio = ((double)(update_time-last_update_time))/((double)FRAME_RATE);
660       if(frame_ratio > 1.5) /* Quick hack to correct the unprecise CPU clocks a little bit. */
661       frame_ratio = 1.5 + (frame_ratio - 1.5) * 0.85;
662       
663       if(!timer_check(&frame_timer))
664         {
665           timer_start(&frame_timer,25);
666           ++frame;
667         }
668
669       /* Handle events: */
670
671       tux.input.old_fire = tux.input.fire;
672
673       game_event();
674
675       if(show_menu)
676         {
677           if(current_menu == &game_menu)
678             {
679               switch (menu_check(&game_menu))
680                 {
681                 case 2:
682                   st_pause_ticks_stop();
683                   break;
684                 case 3:
685                   update_load_save_game_menu(&save_game_menu, NO);
686                   break;
687                 case 4:
688                   update_load_save_game_menu(&load_game_menu, YES);
689                   break;
690                 case 7:
691                   st_pause_ticks_stop();
692                   done = 1;
693                   break;
694                 }
695             }
696           else if(current_menu == &options_menu)
697             {
698               process_options_menu();
699             }
700           else if(current_menu == &save_game_menu )
701             {
702               process_save_load_game_menu(YES);
703             }
704           else if(current_menu == &load_game_menu )
705             {
706               process_save_load_game_menu(NO);
707             }
708         }
709
710
711       /* Handle actions: */
712
713       if(!game_pause && !show_menu)
714         {
715         /*float z = frame_ratio;
716         frame_ratio = 1;
717         while(z >= 1)
718         {*/
719           if (game_action() == 0)
720             {
721               /* == 0: no more lives */
722               /* == -1: continues */
723               return 0;
724             }
725           /*  --z;
726             }*/
727         }
728       else
729         {
730           ++pause_menu_frame;
731           SDL_Delay(50);
732         }
733
734       if(debug_mode && debug_fps == YES)
735         SDL_Delay(60);
736
737       /*Draw the current scene to the screen */
738       /*If the machine running the game is too slow
739         skip the drawing of the frame (so the calculations are more precise and
740       the FPS aren't affected).*/
741       /*if( ! fps_fps < 50.0 )
742       game_draw();
743       else
744       jump = YES;*/ /*FIXME: Implement this tweak right.*/
745       game_draw();
746
747       /* Time stops in pause mode */
748       if(game_pause || show_menu )
749         {
750           continue;
751         }
752
753       /* Set the time of the last update and the time of the current update */
754       last_update_time = update_time;
755       update_time = st_get_ticks();
756
757
758       /* Pause till next frame, if the machine running the game is too fast: */
759       /* FIXME: Works great for in OpenGl mode, where the CPU doesn't have to do that much. But
760                 the results in SDL mode aren't perfect (thought the 100 FPS are reached), even on an AMD2500+. */
761       if(last_update_time >= update_time - 12 && jump != YES )
762         SDL_Delay(10);
763       /*if((update_time - last_update_time) < 10)
764           SDL_Delay((11 - (update_time - last_update_time))/2);*/
765
766
767
768       /* Handle time: */
769
770       if (timer_check(&time_left))
771         {
772           /* are we low on time ? */
773           if ((timer_get_left(&time_left) < TIME_WARNING)
774               && (get_current_music() != HURRYUP_MUSIC))     /* play the fast music */
775              {
776               set_current_music(HURRYUP_MUSIC);
777               play_current_music();
778              }
779
780         }
781       else
782         player_kill(&tux,KILL);
783
784
785       /* Calculate frames per second */
786       if(show_fps)
787         {
788           ++fps_cnt;
789           fps_fps = (1000.0 / (float)timer_get_gone(&fps_timer)) * (float)fps_cnt;
790
791           if(!timer_check(&fps_timer))
792             {
793               timer_start(&fps_timer,1000);
794               fps_cnt = 0;
795             }
796         }
797
798     }
799   while (!done && !quit);
800
801   halt_music();
802
803   level_free_gfx();
804   level_free(&current_level);
805   level_free_song();
806   unloadshared();
807   arrays_free();
808
809   game_started = NO;
810
811   return(quit);
812 }
813
814
815 /* Load graphics/sounds shared between all levels: */
816
817 void loadshared(void)
818 {
819   int i;
820
821   /* Tuxes: */
822   texture_load(&tux_right[0], datadir + "/images/shared/tux-right-0.png", USE_ALPHA);
823   texture_load(&tux_right[1], datadir + "/images/shared/tux-right-1.png", USE_ALPHA);
824   texture_load(&tux_right[2], datadir + "/images/shared/tux-right-2.png", USE_ALPHA);
825
826   texture_load(&tux_left[0], datadir + "/images/shared/tux-left-0.png", USE_ALPHA);
827   texture_load(&tux_left[1], datadir + "/images/shared/tux-left-1.png", USE_ALPHA);
828   texture_load(&tux_left[2], datadir + "/images/shared/tux-left-2.png", USE_ALPHA);
829
830   texture_load(&firetux_right[0], datadir + "/images/shared/firetux-right-0.png", USE_ALPHA);
831   texture_load(&firetux_right[1], datadir + "/images/shared/firetux-right-1.png", USE_ALPHA);
832   texture_load(&firetux_right[2], datadir + "/images/shared/firetux-right-2.png", USE_ALPHA);
833
834   texture_load(&firetux_left[0], datadir + "/images/shared/firetux-left-0.png", USE_ALPHA);
835   texture_load(&firetux_left[1], datadir + "/images/shared/firetux-left-1.png", USE_ALPHA);
836   texture_load(&firetux_left[2], datadir + "/images/shared/firetux-left-2.png", USE_ALPHA);
837
838
839   texture_load(&cape_right[0], datadir + "/images/shared/cape-right-0.png",
840                USE_ALPHA);
841
842   texture_load(&cape_right[1], datadir + "/images/shared/cape-right-1.png",
843                USE_ALPHA);
844
845   texture_load(&cape_left[0], datadir + "/images/shared/cape-left-0.png",
846                USE_ALPHA);
847
848   texture_load(&cape_left[1], datadir + "/images/shared/cape-left-1.png",
849                USE_ALPHA);
850
851   texture_load(&bigtux_right[0], datadir + "/images/shared/bigtux-right-0.png",
852                USE_ALPHA);
853
854   texture_load(&bigtux_right[1], datadir + "/images/shared/bigtux-right-1.png",
855                USE_ALPHA);
856
857   texture_load(&bigtux_right[2], datadir + "/images/shared/bigtux-right-2.png",
858                USE_ALPHA);
859
860   texture_load(&bigtux_right_jump, datadir + "/images/shared/bigtux-right-jump.png", USE_ALPHA);
861
862   texture_load(&bigtux_left[0], datadir + "/images/shared/bigtux-left-0.png",
863                USE_ALPHA);
864
865   texture_load(&bigtux_left[1], datadir + "/images/shared/bigtux-left-1.png",
866                USE_ALPHA);
867
868   texture_load(&bigtux_left[2], datadir + "/images/shared/bigtux-left-2.png",
869                USE_ALPHA);
870
871   texture_load(&bigtux_left_jump, datadir + "/images/shared/bigtux-left-jump.png", USE_ALPHA);
872
873   texture_load(&bigcape_right[0], datadir + "/images/shared/bigcape-right-0.png",
874                USE_ALPHA);
875
876   texture_load(&bigcape_right[1], datadir + "/images/shared/bigcape-right-1.png",
877                USE_ALPHA);
878
879   texture_load(&bigcape_left[0], datadir + "/images/shared/bigcape-left-0.png",
880                USE_ALPHA);
881
882   texture_load(&bigcape_left[1], datadir + "/images/shared/bigcape-left-1.png",
883                USE_ALPHA);
884
885   texture_load(&bigfiretux_right[0], datadir + "/images/shared/bigfiretux-right-0.png",
886                USE_ALPHA);
887
888   texture_load(&bigfiretux_right[1], datadir + "/images/shared/bigfiretux-right-1.png",
889                USE_ALPHA);
890
891   texture_load(&bigfiretux_right[2], datadir + "/images/shared/bigfiretux-right-2.png",
892                USE_ALPHA);
893
894   texture_load(&bigfiretux_right_jump, datadir + "/images/shared/bigfiretux-right-jump.png", USE_ALPHA);
895
896   texture_load(&bigfiretux_left[0], datadir + "/images/shared/bigfiretux-left-0.png",
897                USE_ALPHA);
898
899   texture_load(&bigfiretux_left[1], datadir + "/images/shared/bigfiretux-left-1.png",
900                USE_ALPHA);
901
902   texture_load(&bigfiretux_left[2], datadir + "/images/shared/bigfiretux-left-2.png",
903                USE_ALPHA);
904
905   texture_load(&bigfiretux_left_jump, datadir + "/images/shared/bigfiretux-left-jump.png", USE_ALPHA);
906
907   texture_load(&bigcape_right[0], datadir + "/images/shared/bigcape-right-0.png",
908                USE_ALPHA);
909
910   texture_load(&bigcape_right[1], datadir + "/images/shared/bigcape-right-1.png",
911                USE_ALPHA);
912
913   texture_load(&bigcape_left[0], datadir + "/images/shared/bigcape-left-0.png",
914                USE_ALPHA);
915
916   texture_load(&bigcape_left[1], datadir + "/images/shared/bigcape-left-1.png",
917                USE_ALPHA);
918
919
920   texture_load(&ducktux_right, datadir +
921                "/images/shared/ducktux-right.png",
922                USE_ALPHA);
923
924   texture_load(&ducktux_left, datadir +
925                "/images/shared/ducktux-left.png",
926                USE_ALPHA);
927
928   texture_load(&skidtux_right, datadir +
929                "/images/shared/skidtux-right.png",
930                USE_ALPHA);
931
932   texture_load(&skidtux_left, datadir +
933                "/images/shared/skidtux-left.png",
934                USE_ALPHA);
935
936   texture_load(&duckfiretux_right, datadir +
937                "/images/shared/duckfiretux-right.png",
938                USE_ALPHA);
939
940   texture_load(&duckfiretux_left, datadir +
941                "/images/shared/duckfiretux-left.png",
942                USE_ALPHA);
943
944   texture_load(&skidfiretux_right, datadir +
945                "/images/shared/skidfiretux-right.png",
946                USE_ALPHA);
947
948   texture_load(&skidfiretux_left, datadir +
949                "/images/shared/skidfiretux-left.png",
950                USE_ALPHA);
951
952
953   /* Boxes: */
954
955   texture_load(&img_box_full, datadir + "/images/shared/box-full.png",
956                IGNORE_ALPHA);
957   texture_load(&img_box_empty, datadir + "/images/shared/box-empty.png",
958                IGNORE_ALPHA);
959
960
961   /* Water: */
962
963
964   texture_load(&img_water, datadir + "/images/shared/water.png", IGNORE_ALPHA);
965
966   texture_load(&img_waves[0], datadir + "/images/shared/waves-0.png",
967                USE_ALPHA);
968
969   texture_load(&img_waves[1], datadir + "/images/shared/waves-1.png",
970                USE_ALPHA);
971
972   texture_load(&img_waves[2], datadir + "/images/shared/waves-2.png",
973                USE_ALPHA);
974
975
976   /* Pole: */
977
978   texture_load(&img_pole, datadir + "/images/shared/pole.png", USE_ALPHA);
979   texture_load(&img_poletop, datadir + "/images/shared/poletop.png",
980                USE_ALPHA);
981
982
983   /* Flag: */
984
985   texture_load(&img_flag[0], datadir + "/images/shared/flag-0.png",
986                USE_ALPHA);
987   texture_load(&img_flag[1], datadir + "/images/shared/flag-1.png",
988                USE_ALPHA);
989
990
991   /* Cloud: */
992
993   texture_load(&img_cloud[0][0], datadir + "/images/shared/cloud-00.png",
994                USE_ALPHA);
995
996   texture_load(&img_cloud[0][1], datadir + "/images/shared/cloud-01.png",
997                USE_ALPHA);
998
999   texture_load(&img_cloud[0][2], datadir + "/images/shared/cloud-02.png",
1000                USE_ALPHA);
1001
1002   texture_load(&img_cloud[0][3], datadir + "/images/shared/cloud-03.png",
1003                USE_ALPHA);
1004
1005
1006   texture_load(&img_cloud[1][0], datadir + "/images/shared/cloud-10.png",
1007                USE_ALPHA);
1008
1009   texture_load(&img_cloud[1][1], datadir + "/images/shared/cloud-11.png",
1010                USE_ALPHA);
1011
1012   texture_load(&img_cloud[1][2], datadir + "/images/shared/cloud-12.png",
1013                USE_ALPHA);
1014
1015   texture_load(&img_cloud[1][3], datadir + "/images/shared/cloud-13.png",
1016                USE_ALPHA);
1017
1018
1019   /* Bad guys: */
1020
1021   /* (BSOD) */
1022
1023   texture_load(&img_bsod_left[0], datadir +
1024                "/images/shared/bsod-left-0.png",
1025                USE_ALPHA);
1026
1027   texture_load(&img_bsod_left[1], datadir +
1028                "/images/shared/bsod-left-1.png",
1029                USE_ALPHA);
1030
1031   texture_load(&img_bsod_left[2], datadir +
1032                "/images/shared/bsod-left-2.png",
1033                USE_ALPHA);
1034
1035   texture_load(&img_bsod_left[3], datadir +
1036                "/images/shared/bsod-left-3.png",
1037                USE_ALPHA);
1038
1039   texture_load(&img_bsod_right[0], datadir +
1040                "/images/shared/bsod-right-0.png",
1041                USE_ALPHA);
1042
1043   texture_load(&img_bsod_right[1], datadir +
1044                "/images/shared/bsod-right-1.png",
1045                USE_ALPHA);
1046
1047   texture_load(&img_bsod_right[2], datadir +
1048                "/images/shared/bsod-right-2.png",
1049                USE_ALPHA);
1050
1051   texture_load(&img_bsod_right[3], datadir +
1052                "/images/shared/bsod-right-3.png",
1053                USE_ALPHA);
1054
1055   texture_load(&img_bsod_squished_left, datadir +
1056                "/images/shared/bsod-squished-left.png",
1057                USE_ALPHA);
1058
1059   texture_load(&img_bsod_squished_right, datadir +
1060                "/images/shared/bsod-squished-right.png",
1061                USE_ALPHA);
1062
1063   texture_load(&img_bsod_falling_left, datadir +
1064                "/images/shared/bsod-falling-left.png",
1065                USE_ALPHA);
1066
1067   texture_load(&img_bsod_falling_right, datadir +
1068                "/images/shared/bsod-falling-right.png",
1069                USE_ALPHA);
1070
1071
1072   /* (Laptop) */
1073
1074   texture_load(&img_laptop_left[0], datadir +
1075                "/images/shared/laptop-left-0.png",
1076                USE_ALPHA);
1077
1078   texture_load(&img_laptop_left[1], datadir +
1079                "/images/shared/laptop-left-1.png",
1080                USE_ALPHA);
1081
1082   texture_load(&img_laptop_left[2], datadir +
1083                "/images/shared/laptop-left-2.png",
1084                USE_ALPHA);
1085
1086   texture_load(&img_laptop_right[0], datadir +
1087                "/images/shared/laptop-right-0.png",
1088                USE_ALPHA);
1089
1090   texture_load(&img_laptop_right[1], datadir +
1091                "/images/shared/laptop-right-1.png",
1092                USE_ALPHA);
1093
1094   texture_load(&img_laptop_right[2], datadir +
1095                "/images/shared/laptop-right-2.png",
1096                USE_ALPHA);
1097
1098   texture_load(&img_laptop_flat_left, datadir +
1099                "/images/shared/laptop-flat-left.png",
1100                USE_ALPHA);
1101
1102   texture_load(&img_laptop_flat_right, datadir +
1103                "/images/shared/laptop-flat-right.png",
1104                USE_ALPHA);
1105
1106   texture_load(&img_laptop_falling_left, datadir +
1107                "/images/shared/laptop-falling-left.png",
1108                USE_ALPHA);
1109
1110   texture_load(&img_laptop_falling_right, datadir +
1111                "/images/shared/laptop-falling-right.png",
1112                USE_ALPHA);
1113
1114
1115   /* (Money) */
1116
1117   texture_load(&img_money_left[0], datadir +
1118                "/images/shared/bag-left-0.png",
1119                USE_ALPHA);
1120
1121   texture_load(&img_money_left[1], datadir +
1122                "/images/shared/bag-left-1.png",
1123                USE_ALPHA);
1124
1125   texture_load(&img_money_right[0], datadir +
1126                "/images/shared/bag-right-0.png",
1127                USE_ALPHA);
1128
1129   texture_load(&img_money_right[1], datadir +
1130                "/images/shared/bag-right-1.png",
1131                USE_ALPHA);
1132
1133
1134
1135   /* Upgrades: */
1136
1137   texture_load(&img_mints, datadir + "/images/shared/mints.png", USE_ALPHA);
1138   texture_load(&img_coffee, datadir + "/images/shared/coffee.png", USE_ALPHA);
1139
1140
1141   /* Weapons: */
1142
1143   texture_load(&img_bullet, datadir + "/images/shared/bullet.png", USE_ALPHA);
1144
1145   texture_load(&img_red_glow, datadir + "/images/shared/red-glow.png",
1146                USE_ALPHA);
1147
1148
1149
1150   /* Distros: */
1151
1152   texture_load(&img_distro[0], datadir + "/images/shared/distro-0.png",
1153                USE_ALPHA);
1154
1155   texture_load(&img_distro[1], datadir + "/images/shared/distro-1.png",
1156                USE_ALPHA);
1157
1158   texture_load(&img_distro[2], datadir + "/images/shared/distro-2.png",
1159                USE_ALPHA);
1160
1161   texture_load(&img_distro[3], datadir + "/images/shared/distro-3.png",
1162                USE_ALPHA);
1163
1164
1165   /* Tux life: */
1166
1167   texture_load(&tux_life, datadir + "/images/shared/tux-life.png",
1168                USE_ALPHA);
1169
1170   /* Herring: */
1171
1172   texture_load(&img_golden_herring, datadir + "/images/shared/golden-herring.png",
1173                USE_ALPHA);
1174
1175
1176   /* Super background: */
1177
1178   texture_load(&img_super_bkgd, datadir + "/images/shared/super-bkgd.png",
1179                IGNORE_ALPHA);
1180
1181
1182   /* Sound effects: */
1183
1184   /* if (use_sound) // this will introduce SERIOUS bugs here ! because "load_sound"
1185                     // initialize sounds[i] with the correct pointer's value:
1186                     // NULL or something else. And it will be dangerous to
1187                     // play with not-initialized pointers.
1188                     // This is also true with if (use_music)
1189      Send a mail to me: neoneurone@users.sf.net, if you have another opinion. :)
1190   */
1191   for (i = 0; i < NUM_SOUNDS; i++)
1192     sounds[i] = load_sound(datadir + soundfilenames[i]);
1193
1194   /* Herring song */
1195   herring_song = load_song(datadir + "/music/SALCON.MOD");
1196 }
1197
1198
1199 /* Free shared data: */
1200
1201 void unloadshared(void)
1202 {
1203   int i;
1204
1205   for (i = 0; i < 3; i++)
1206     {
1207       texture_free(&tux_right[i]);
1208       texture_free(&tux_left[i]);
1209       texture_free(&bigtux_right[i]);
1210       texture_free(&bigtux_left[i]);
1211     }
1212
1213   texture_free(&bigtux_right_jump);
1214   texture_free(&bigtux_left_jump);
1215
1216   for (i = 0; i < 2; i++)
1217     {
1218       texture_free(&cape_right[i]);
1219       texture_free(&cape_left[i]);
1220       texture_free(&bigcape_right[i]);
1221       texture_free(&bigcape_left[i]);
1222     }
1223
1224   texture_free(&ducktux_left);
1225   texture_free(&ducktux_right);
1226
1227   texture_free(&skidtux_left);
1228   texture_free(&skidtux_right);
1229
1230   for (i = 0; i < 4; i++)
1231     {
1232       texture_free(&img_bsod_left[i]);
1233       texture_free(&img_bsod_right[i]);
1234     }
1235
1236   texture_free(&img_bsod_squished_left);
1237   texture_free(&img_bsod_squished_right);
1238
1239   texture_free(&img_bsod_falling_left);
1240   texture_free(&img_bsod_falling_right);
1241
1242   for (i = 0; i < 3; i++)
1243     {
1244       texture_free(&img_laptop_left[i]);
1245       texture_free(&img_laptop_right[i]);
1246     }
1247
1248   texture_free(&img_laptop_flat_left);
1249   texture_free(&img_laptop_flat_right);
1250
1251   texture_free(&img_laptop_falling_left);
1252   texture_free(&img_laptop_falling_right);
1253
1254   for (i = 0; i < 2; i++)
1255     {
1256       texture_free(&img_money_left[i]);
1257       texture_free(&img_money_right[i]);
1258     }
1259
1260   texture_free(&img_box_full);
1261   texture_free(&img_box_empty);
1262
1263   texture_free(&img_water);
1264   for (i = 0; i < 3; i++)
1265     texture_free(&img_waves[i]);
1266
1267   texture_free(&img_pole);
1268   texture_free(&img_poletop);
1269
1270   for (i = 0; i < 2; i++)
1271     texture_free(&img_flag[i]);
1272
1273   texture_free(&img_mints);
1274   texture_free(&img_coffee);
1275
1276   for (i = 0; i < 4; i++)
1277     {
1278       texture_free(&img_distro[i]);
1279       texture_free(&img_cloud[0][i]);
1280       texture_free(&img_cloud[1][i]);
1281     }
1282
1283   texture_free(&img_golden_herring);
1284
1285   for (i = 0; i < NUM_SOUNDS; i++)
1286     free_chunk(sounds[i]);
1287
1288   /* free the herring song */
1289   free_music( herring_song );
1290 }
1291
1292
1293 /* Draw a tile on the screen: */
1294
1295 void drawshape(float x, float y, unsigned char c)
1296 {
1297   int z;
1298
1299   if (c == 'X' || c == 'x')
1300     texture_draw(&img_brick[0], x, y, NO_UPDATE);
1301   else if (c == 'Y' || c == 'y')
1302     texture_draw(&img_brick[1], x, y, NO_UPDATE);
1303   else if (c == 'A' || c =='B' || c == '!')
1304     texture_draw(&img_box_full, x, y, NO_UPDATE);
1305   else if (c == 'a')
1306     texture_draw(&img_box_empty, x, y, NO_UPDATE);
1307   else if (c >= 'C' && c <= 'F')
1308     texture_draw(&img_cloud[0][c - 'C'], x, y, NO_UPDATE);
1309   else if (c >= 'c' && c <= 'f')
1310     texture_draw(&img_cloud[1][c - 'c'], x, y, NO_UPDATE);
1311   else if (c >= 'G' && c <= 'J')
1312     texture_draw(&img_bkgd_tile[0][c - 'G'], x, y, NO_UPDATE);
1313   else if (c >= 'g' && c <= 'j')
1314     texture_draw(&img_bkgd_tile[1][c - 'g'], x, y, NO_UPDATE);
1315   else if (c == '#')
1316     texture_draw(&img_solid[0], x, y, NO_UPDATE);
1317   else if (c == '[')
1318     texture_draw(&img_solid[1], x, y, NO_UPDATE);
1319   else if (c == '=')
1320     texture_draw(&img_solid[2], x, y, NO_UPDATE);
1321   else if (c == ']')
1322     texture_draw(&img_solid[3], x, y, NO_UPDATE);
1323   else if (c == '$')
1324     {
1325
1326       z = (frame / 2) % 6;
1327
1328       if (z < 4)
1329         texture_draw(&img_distro[z], x, y, NO_UPDATE);
1330       else if (z == 4)
1331         texture_draw(&img_distro[2], x, y, NO_UPDATE);
1332       else if (z == 5)
1333         texture_draw(&img_distro[1], x, y, NO_UPDATE);
1334     }
1335   else if (c == '^')
1336     {
1337       z = (frame / 3) % 3;
1338
1339       texture_draw(&img_waves[z], x, y, NO_UPDATE);
1340     }
1341   else if (c == '*')
1342     texture_draw(&img_poletop, x, y, NO_UPDATE);
1343   else if (c == '|')
1344     {
1345       texture_draw(&img_pole, x, y, NO_UPDATE);
1346
1347     }
1348   else if (c == '\\')
1349     {
1350       z = (frame / 3) % 2;
1351
1352       texture_draw(&img_flag[z], x + 16, y, NO_UPDATE);
1353     }
1354   else if (c == '&')
1355     texture_draw(&img_water, x, y, NO_UPDATE);
1356 }
1357
1358
1359 /* What shape is at some position? */
1360
1361 unsigned char shape(float x, float y)
1362 {
1363
1364   int xx, yy;
1365   unsigned char c;
1366
1367   yy = ((int)y / 32);
1368   xx = ((int)x / 32);
1369
1370   if (yy >= 0 && yy < 15 && xx >= 0 && xx <= current_level.width)
1371     {
1372       c = current_level.tiles[yy][xx];
1373     }
1374   else
1375     c = '.';
1376
1377   return(c);
1378 }
1379
1380 /* Is is ground? */
1381
1382
1383 int issolid(float x, float y)
1384 {
1385   if (isbrick(x, y) ||
1386       isice(x, y) ||
1387       (shape(x, y) == '[') ||
1388       (shape(x, y) == '=') ||
1389       (shape(x, y) == ']') ||
1390       (shape(x, y) == 'A') ||
1391       (shape(x, y) == 'B') ||
1392       (shape(x, y) == '!') ||
1393       (shape(x, y) == 'a'))
1394     {
1395       return YES;
1396     }
1397
1398   return NO;
1399 }
1400
1401
1402 /* Is it a brick? */
1403
1404 int isbrick(float x, float y)
1405 {
1406   if (shape(x, y) == 'X' ||
1407       shape(x, y) == 'x' ||
1408       shape(x, y) == 'Y' ||
1409       shape(x, y) == 'y')
1410     {
1411       return YES;
1412     }
1413
1414   return NO;
1415 }
1416
1417
1418 /* Is it ice? */
1419
1420 int isice(float x, float y)
1421 {
1422   if (shape(x, y) == '#')
1423     {
1424       return YES;
1425     }
1426
1427   return NO;
1428 }
1429
1430
1431 /* Is it a full box? */
1432
1433 int isfullbox(float x, float y)
1434 {
1435   if (shape(x, y) == 'A' ||
1436       shape(x, y) == 'B' ||
1437       shape(x, y) == '!')
1438     {
1439       return YES;
1440     }
1441
1442   return NO;
1443 }
1444
1445 /* Break a brick: */
1446
1447 void trybreakbrick(float x, float y)
1448 {
1449   if (isbrick(x, y))
1450     {
1451       if (shape(x, y) == 'x' || shape(x, y) == 'y')
1452         {
1453           /* Get a distro from it: */
1454
1455           add_bouncy_distro(((int)(x + 1) / 32) * 32,
1456                             (int)(y / 32) * 32);
1457
1458           if (counting_distros == NO)
1459             {
1460               counting_distros = YES;
1461               distro_counter = 50;
1462             }
1463
1464           if (distro_counter <= 0)
1465             level_change(&current_level,x, y, 'a');
1466
1467           play_sound(sounds[SND_DISTRO], SOUND_CENTER_SPEAKER);
1468           score = score + SCORE_DISTRO;
1469           distros++;
1470         }
1471       else
1472         {
1473           /* Get rid of it: */
1474
1475           level_change(&current_level,x, y,'.');
1476         }
1477
1478
1479       /* Replace it with broken bits: */
1480
1481       add_broken_brick(((int)(x + 1) / 32) * 32,
1482                        (int)(y / 32) * 32);
1483
1484
1485       /* Get some score: */
1486
1487       play_sound(sounds[SND_BRICK], SOUND_CENTER_SPEAKER);
1488       score = score + SCORE_BRICK;
1489     }
1490 }
1491
1492
1493 /* Bounce a brick: */
1494
1495 void bumpbrick(float x, float y)
1496 {
1497   add_bouncy_brick(((int)(x + 1) / 32) * 32,
1498                    (int)(y / 32) * 32);
1499
1500   play_sound(sounds[SND_BRICK], SOUND_CENTER_SPEAKER);
1501
1502 }
1503
1504
1505 /* Empty a box: */
1506
1507 void tryemptybox(float x, float y, int col_side)
1508 {
1509 if (!isfullbox(x, y))
1510   return;
1511
1512 // according to the collision side, set the upgrade direction
1513
1514 if(col_side == LEFT)
1515   col_side = RIGHT;
1516 else
1517   col_side = LEFT;
1518
1519 switch(shape(x,y))
1520   {
1521   case 'A':      /* Box with a distro! */
1522     add_bouncy_distro(((int)(x + 1) / 32) * 32, (int)(y / 32) * 32 - 32);
1523     play_sound(sounds[SND_DISTRO], SOUND_CENTER_SPEAKER);
1524     score = score + SCORE_DISTRO;
1525     distros++;
1526     break;
1527   case 'B':      /* Add an upgrade! */
1528     if (tux.size == SMALL)     /* Tux is small, add mints! */
1529       add_upgrade((int)((x + 1) / 32) * 32, (int)(y / 32) * 32 - 32, col_side, UPGRADE_MINTS);
1530     else     /* Tux is big, add coffee: */
1531       add_upgrade((int)((x + 1) / 32) * 32, (int)(y / 32) * 32 - 32, col_side, UPGRADE_COFFEE);
1532     play_sound(sounds[SND_UPGRADE], SOUND_CENTER_SPEAKER);
1533     break;
1534   case '!':     /* Add a golden herring */
1535     add_upgrade((int)((x + 1) / 32) * 32, (int)(y / 32) * 32 - 32, col_side, UPGRADE_HERRING);
1536     break;
1537   default:
1538     break;
1539   }
1540
1541 /* Empty the box: */
1542 level_change(&current_level,x, y, 'a');
1543 }
1544
1545
1546 /* Try to grab a distro: */
1547
1548 void trygrabdistro(float x, float y, int bounciness)
1549 {
1550   if (shape(x, y) == '$')
1551     {
1552       level_change(&current_level,x, y, '.');
1553       play_sound(sounds[SND_DISTRO], SOUND_CENTER_SPEAKER);
1554
1555       if (bounciness == BOUNCE)
1556         {
1557           add_bouncy_distro(((int)(x + 1) / 32) * 32,
1558                             (int)(y / 32) * 32);
1559         }
1560
1561       score = score + SCORE_DISTRO;
1562       distros++;
1563     }
1564 }
1565
1566 /* Try to bump a bad guy from below: */
1567
1568 void trybumpbadguy(float x, float y)
1569 {
1570   int i;
1571
1572
1573   /* Bad guys: */
1574
1575   for (i = 0; i < num_bad_guys; i++)
1576     {
1577       if (bad_guys[i].base.alive &&
1578           bad_guys[i].base.x >= x - 32 && bad_guys[i].base.x <= x + 32 &&
1579           bad_guys[i].base.y >= y - 16 && bad_guys[i].base.y <= y + 16)
1580         {
1581           if (bad_guys[i].kind == BAD_BSOD ||
1582               bad_guys[i].kind == BAD_LAPTOP)
1583             {
1584               bad_guys[i].dying = FALLING;
1585               bad_guys[i].base.ym = -8;
1586               play_sound(sounds[SND_FALL], SOUND_CENTER_SPEAKER);
1587             }
1588         }
1589     }
1590
1591
1592   /* Upgrades: */
1593
1594   for (i = 0; i < num_upgrades; i++)
1595     {
1596       if (upgrades[i].base.alive && upgrades[i].base.height == 32 &&
1597           upgrades[i].base.x >= x - 32 && upgrades[i].base.x <= x + 32 &&
1598           upgrades[i].base.y >= y - 16 && upgrades[i].base.y <= y + 16)
1599         {
1600           upgrades[i].base.xm = -upgrades[i].base.xm;
1601           upgrades[i].base.ym = -8;
1602           play_sound(sounds[SND_BUMP_UPGRADE], SOUND_CENTER_SPEAKER);
1603         }
1604     }
1605 }
1606
1607 /* (Status): */
1608 void drawstatus(void)
1609 {
1610   int i;
1611
1612   sprintf(str, "%d", score);
1613   text_draw(&white_text, "SCORE", 0, 0, 1, NO_UPDATE);
1614   text_draw(&gold_text, str, 96, 0, 1, NO_UPDATE);
1615
1616   if(st_gl_mode != ST_GL_TEST)
1617     {
1618       sprintf(str, "%d", hs_score);
1619       text_draw(&white_text, "HIGH", 0, 20, 1, NO_UPDATE);
1620       text_draw(&gold_text, str, 96, 20, 1, NO_UPDATE);
1621     }
1622   else
1623     {
1624       text_draw(&white_text,"Press ESC To Return",0,20,1, NO_UPDATE);
1625     }
1626
1627   if (timer_get_left(&time_left) > TIME_WARNING || (frame % 10) < 5)
1628     {
1629       sprintf(str, "%d", timer_get_left(&time_left) / 1000 );
1630       text_draw(&white_text, "TIME", 224, 0, 1, NO_UPDATE);
1631       text_draw(&gold_text, str, 304, 0, 1, NO_UPDATE);
1632     }
1633
1634   sprintf(str, "%d", distros);
1635   text_draw(&white_text, "DISTROS", screen->h, 0, 1, NO_UPDATE);
1636   text_draw(&gold_text, str, 608, 0, 1, NO_UPDATE);
1637
1638   text_draw(&white_text, "LIVES", screen->h, 20, 1, NO_UPDATE);
1639
1640   if(show_fps)
1641     {
1642       sprintf(str, "%2.1f", fps_fps);
1643       text_draw(&white_text, "FPS", screen->h, 40, 1, NO_UPDATE);
1644       text_draw(&gold_text, str, screen->h + 60, 40, 1, NO_UPDATE);
1645     }
1646
1647   for(i=0; i < tux.lives; ++i)
1648     {
1649       texture_draw(&tux_life,565+(18*i),20,NO_UPDATE);
1650     }
1651 }
1652
1653
1654 void drawendscreen(void)
1655 {
1656   char str[80];
1657
1658   clearscreen(0, 0, 0);
1659
1660   text_drawf(&blue_text, "GAMEOVER", 0, 200, A_HMIDDLE, A_TOP, 1, NO_UPDATE);
1661
1662   sprintf(str, "SCORE: %d", score);
1663   text_drawf(&gold_text, str, 0, 224, A_HMIDDLE, A_TOP, 1, NO_UPDATE);
1664
1665   sprintf(str, "DISTROS: %d", distros);
1666   text_drawf(&gold_text, str, 0, 256, A_HMIDDLE, A_TOP, 1, NO_UPDATE);
1667
1668   flipscreen();
1669   SDL_Delay(2000);
1670 }
1671
1672 void drawresultscreen(void)
1673 {
1674   char str[80];
1675
1676   clearscreen(0, 0, 0);
1677
1678   text_drawf(&blue_text, "Result:", 0, 200, A_HMIDDLE, A_TOP, 1, NO_UPDATE);
1679
1680   sprintf(str, "SCORE: %d", score);
1681   text_drawf(&gold_text, str, 0, 224, A_HMIDDLE, A_TOP, 1, NO_UPDATE);
1682
1683   sprintf(str, "DISTROS: %d", distros);
1684   text_drawf(&gold_text, str, 0, 256, A_HMIDDLE, A_TOP, 1, NO_UPDATE);
1685
1686   flipscreen();
1687   SDL_Delay(2000);
1688 }
1689
1690 void savegame(int slot)
1691 {
1692   char savefile[1024];
1693   FILE* fi;
1694   unsigned int ui;
1695
1696   sprintf(savefile,"%s/slot%d.save",st_save_dir,slot);
1697
1698   fi = fopen(savefile, "wb");
1699
1700   if (fi == NULL)
1701     {
1702       fprintf(stderr, "Warning: I could not open the slot file ");
1703
1704     }
1705   else
1706     {
1707       fputs(level_subset, fi);
1708       fputs("\n", fi);
1709       fwrite(&level,sizeof(int),1,fi);
1710       fwrite(&score,sizeof(int),1,fi);
1711       fwrite(&distros,sizeof(int),1,fi);
1712       fwrite(&scroll_x,sizeof(float),1,fi);
1713       fwrite(&tux,sizeof(player_type),1,fi);
1714       timer_fwrite(&tux.invincible_timer,fi);
1715       timer_fwrite(&tux.skidding_timer,fi);
1716       timer_fwrite(&tux.safe_timer,fi);
1717       timer_fwrite(&tux.frame_timer,fi);
1718       timer_fwrite(&time_left,fi);
1719       ui = st_get_ticks();
1720       fwrite(&ui,sizeof(int),1,fi);
1721     }
1722   fclose(fi);
1723
1724 }
1725
1726 void loadgame(int slot)
1727 {
1728   char savefile[1024];
1729   char str[100];
1730   FILE* fi;
1731   unsigned int ui;
1732
1733   sprintf(savefile,"%s/slot%d.save",st_save_dir,slot);
1734
1735   fi = fopen(savefile, "rb");
1736
1737   if (fi == NULL)
1738     {
1739       fprintf(stderr, "Warning: I could not open the slot file ");
1740
1741     }
1742   else
1743     {
1744
1745
1746       fgets(str, 100, fi);
1747       strcpy(level_subset, str);
1748       level_subset[strlen(level_subset)-1] = '\0';
1749       fread(&level,sizeof(int),1,fi);
1750
1751       set_defaults();
1752       level_free(&current_level);
1753       if(level_load(&current_level,level_subset,level) != 0)
1754         exit(1);
1755       arrays_free();
1756       arrays_init();
1757       activate_bad_guys();
1758       level_free_gfx();
1759       level_load_gfx(&current_level);
1760       level_free_song();
1761       level_load_song(&current_level);
1762       levelintro();
1763       update_time = st_get_ticks();
1764
1765       fread(&score,sizeof(int),1,fi);
1766       fread(&distros,sizeof(int),1,fi);
1767       fread(&scroll_x,sizeof(float),1,fi);
1768       fread(&tux,sizeof(player_type),1,fi);
1769       timer_fread(&tux.invincible_timer,fi);
1770       timer_fread(&tux.skidding_timer,fi);
1771       timer_fread(&tux.safe_timer,fi);
1772       timer_fread(&tux.frame_timer,fi);
1773       timer_fread(&time_left,fi);
1774       fread(&ui,sizeof(int),1,fi);
1775       tux.hphysic.start_time += st_get_ticks() - ui;
1776       tux.vphysic.start_time += st_get_ticks() - ui;
1777       fclose(fi);
1778     }
1779
1780 }
1781
1782 void slotinfo(char **pinfo, int slot)
1783 {
1784   FILE* fi;
1785   char slotfile[1024];
1786   char tmp[200];
1787   char str[5];
1788   int slot_level;
1789   sprintf(slotfile,"%s/slot%d.save",st_save_dir,slot);
1790
1791   fi = fopen(slotfile, "rb");
1792
1793   sprintf(tmp,"Slot %d - ",slot);
1794
1795   if (fi == NULL)
1796     {
1797       strcat(tmp,"Free");
1798     }
1799   else
1800     {
1801       fgets(str, 100, fi);
1802       str[strlen(str)-1] = '\0';
1803       strcat(tmp, str);
1804       strcat(tmp, " / Level:");
1805       fread(&slot_level,sizeof(int),1,fi);
1806       sprintf(str,"%d",slot_level);
1807       strcat(tmp,str);
1808       fclose(fi);
1809     }
1810
1811   *pinfo = (char*) malloc(sizeof(char) * (strlen(tmp)+1));
1812   strcpy(*pinfo,tmp);
1813
1814 }
1815