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