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