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