3c298faa78c98e9aac1925b09590ecfccade251b
[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 void trybreakbrick(float x, float y, bool small)
1348 {
1349   Tile* tile = gettile(x, y);
1350   if (tile->brick)
1351     {
1352       if (tile->data > 0)
1353         {
1354           /* Get a distro from it: */
1355           add_bouncy_distro(((int)(x + 1) / 32) * 32,
1356                             (int)(y / 32) * 32);
1357
1358           if (!counting_distros)
1359             {
1360               counting_distros = true;
1361               distro_counter = 50;
1362             }
1363
1364           if (distro_counter <= 0)
1365             level_change(&current_level,x, y, TM_IA, tile->next_tile);
1366
1367           play_sound(sounds[SND_DISTRO], SOUND_CENTER_SPEAKER);
1368           score = score + SCORE_DISTRO;
1369           distros++;
1370         }
1371       else if (!small)
1372         {
1373           /* Get rid of it: */
1374           level_change(&current_level,x, y, TM_IA, tile->next_tile);
1375           
1376           /* Replace it with broken bits: */
1377           add_broken_brick(((int)(x + 1) / 32) * 32,
1378                            (int)(y / 32) * 32);
1379           
1380           /* Get some score: */
1381           play_sound(sounds[SND_BRICK], SOUND_CENTER_SPEAKER);
1382           score = score + SCORE_BRICK;
1383         }
1384     }
1385 }
1386
1387
1388 /* Bounce a brick: */
1389
1390 void bumpbrick(float x, float y)
1391 {
1392   add_bouncy_brick(((int)(x + 1) / 32) * 32,
1393                    (int)(y / 32) * 32);
1394
1395   play_sound(sounds[SND_BRICK], SOUND_CENTER_SPEAKER);
1396
1397 }
1398
1399
1400 /* Empty a box: */
1401 void tryemptybox(float x, float y, int col_side)
1402 {
1403   Tile* tile = gettile(x,y);
1404   if (!tile->fullbox)
1405     return;
1406
1407   // according to the collision side, set the upgrade direction
1408   if(col_side == LEFT)
1409     col_side = RIGHT;
1410   else
1411     col_side = LEFT;
1412
1413   switch(tile->data)
1414     {
1415     case 1: //'A':      /* Box with a distro! */
1416       add_bouncy_distro(((int)(x + 1) / 32) * 32, (int)(y / 32) * 32 - 32);
1417       play_sound(sounds[SND_DISTRO], SOUND_CENTER_SPEAKER);
1418       score = score + SCORE_DISTRO;
1419       distros++;
1420       break;
1421
1422     case 2: // 'B':      /* Add an upgrade! */
1423       if (tux.size == SMALL)     /* Tux is small, add mints! */
1424         add_upgrade((int)((x + 1) / 32) * 32, (int)(y / 32) * 32 - 32, col_side, UPGRADE_MINTS);
1425       else     /* Tux is big, add coffee: */
1426         add_upgrade((int)((x + 1) / 32) * 32, (int)(y / 32) * 32 - 32, col_side, UPGRADE_COFFEE);
1427       play_sound(sounds[SND_UPGRADE], SOUND_CENTER_SPEAKER);
1428       break;
1429
1430     case 3:// '!':     /* Add a golden herring */
1431       add_upgrade((int)((x + 1) / 32) * 32, (int)(y / 32) * 32 - 32, col_side, UPGRADE_HERRING);
1432       break;
1433     default:
1434       break;
1435     }
1436
1437   /* Empty the box: */
1438   level_change(&current_level,x, y, TM_IA, tile->next_tile);
1439 }
1440
1441 /* Try to grab a distro: */
1442 void trygrabdistro(float x, float y, int bounciness)
1443 {
1444   Tile* tile = gettile(x, y);
1445   if (tile && tile->distro)
1446     {
1447       level_change(&current_level,x, y, TM_IA, tile->next_tile);
1448       play_sound(sounds[SND_DISTRO], SOUND_CENTER_SPEAKER);
1449
1450       if (bounciness == BOUNCE)
1451         {
1452           add_bouncy_distro(((int)(x + 1) / 32) * 32,
1453                             (int)(y / 32) * 32);
1454         }
1455
1456       score = score + SCORE_DISTRO;
1457       distros++;
1458     }
1459 }
1460
1461 /* Try to bump a bad guy from below: */
1462 void trybumpbadguy(float x, float y)
1463 {
1464   /* Bad guys: */
1465   for (unsigned int i = 0; i < bad_guys.size(); i++)
1466     {
1467       if (bad_guys[i].base.x >= x - 32 && bad_guys[i].base.x <= x + 32 &&
1468           bad_guys[i].base.y >= y - 16 && bad_guys[i].base.y <= y + 16)
1469         {
1470           bad_guys[i].collision(&tux, CO_PLAYER, COLLISION_BUMP);
1471         }
1472     }
1473
1474
1475   /* Upgrades: */
1476   for (unsigned int i = 0; i < upgrades.size(); i++)
1477     {
1478       if (upgrades[i].base.height == 32 &&
1479           upgrades[i].base.x >= x - 32 && upgrades[i].base.x <= x + 32 &&
1480           upgrades[i].base.y >= y - 16 && upgrades[i].base.y <= y + 16)
1481         {
1482           upgrades[i].base.xm = -upgrades[i].base.xm;
1483           upgrades[i].base.ym = -8;
1484           play_sound(sounds[SND_BUMP_UPGRADE], SOUND_CENTER_SPEAKER);
1485         }
1486     }
1487 }
1488
1489 /* (Status): */
1490 void drawstatus(void)
1491 {
1492   char str[60];
1493
1494   sprintf(str, "%d", score);
1495   text_draw(&white_text, "SCORE", 0, 0, 1);
1496   text_draw(&gold_text, str, 96, 0, 1);
1497
1498   if(st_gl_mode != ST_GL_TEST)
1499     {
1500       sprintf(str, "%d", hs_score);
1501       text_draw(&white_text, "HIGH", 0, 20, 1);
1502       text_draw(&gold_text, str, 96, 20, 1);
1503     }
1504   else
1505     {
1506       text_draw(&white_text,"Press ESC To Return",0,20,1);
1507     }
1508
1509   if (timer_get_left(&time_left) > TIME_WARNING || (global_frame_counter % 10) < 5)
1510     {
1511       sprintf(str, "%d", timer_get_left(&time_left) / 1000 );
1512       text_draw(&white_text, "TIME", 224, 0, 1);
1513       text_draw(&gold_text, str, 304, 0, 1);
1514     }
1515
1516   sprintf(str, "%d", distros);
1517   text_draw(&white_text, "DISTROS", screen->h, 0, 1);
1518   text_draw(&gold_text, str, 608, 0, 1);
1519
1520   text_draw(&white_text, "LIVES", screen->h, 20, 1);
1521
1522   if(show_fps)
1523     {
1524       sprintf(str, "%2.1f", fps_fps);
1525       text_draw(&white_text, "FPS", screen->h, 40, 1);
1526       text_draw(&gold_text, str, screen->h + 60, 40, 1);
1527     }
1528
1529   for(int i=0; i < tux.lives; ++i)
1530     {
1531       texture_draw(&tux_life,565+(18*i),20);
1532     }
1533 }
1534
1535
1536 void drawendscreen(void)
1537 {
1538   char str[80];
1539
1540   clearscreen(0, 0, 0);
1541
1542   text_drawf(&blue_text, "GAMEOVER", 0, 200, A_HMIDDLE, A_TOP, 1);
1543
1544   sprintf(str, "SCORE: %d", score);
1545   text_drawf(&gold_text, str, 0, 224, A_HMIDDLE, A_TOP, 1);
1546
1547   sprintf(str, "DISTROS: %d", distros);
1548   text_drawf(&gold_text, str, 0, 256, A_HMIDDLE, A_TOP, 1);
1549
1550   flipscreen();
1551   SDL_Delay(2000);
1552 }
1553
1554 void drawresultscreen(void)
1555 {
1556   char str[80];
1557
1558   clearscreen(0, 0, 0);
1559
1560   text_drawf(&blue_text, "Result:", 0, 200, A_HMIDDLE, A_TOP, 1);
1561
1562   sprintf(str, "SCORE: %d", score);
1563   text_drawf(&gold_text, str, 0, 224, A_HMIDDLE, A_TOP, 1);
1564
1565   sprintf(str, "DISTROS: %d", distros);
1566   text_drawf(&gold_text, str, 0, 256, A_HMIDDLE, A_TOP, 1);
1567
1568   flipscreen();
1569   SDL_Delay(2000);
1570 }
1571
1572 void savegame(int slot)
1573 {
1574   char savefile[1024];
1575   FILE* fi;
1576   unsigned int ui;
1577
1578   sprintf(savefile,"%s/slot%d.save",st_save_dir,slot);
1579
1580   fi = fopen(savefile, "wb");
1581
1582   if (fi == NULL)
1583     {
1584       fprintf(stderr, "Warning: I could not open the slot file ");
1585     }
1586   else
1587     {
1588       fputs(level_subset, fi);
1589       fputs("\n", fi);
1590       fwrite(&level,sizeof(int),1,fi);
1591       fwrite(&score,sizeof(int),1,fi);
1592       fwrite(&distros,sizeof(int),1,fi);
1593       fwrite(&scroll_x,sizeof(float),1,fi);
1594       fwrite(&tux,sizeof(Player),1,fi);
1595       timer_fwrite(&tux.invincible_timer,fi);
1596       timer_fwrite(&tux.skidding_timer,fi);
1597       timer_fwrite(&tux.safe_timer,fi);
1598       timer_fwrite(&tux.frame_timer,fi);
1599       timer_fwrite(&time_left,fi);
1600       ui = st_get_ticks();
1601       fwrite(&ui,sizeof(int),1,fi);
1602     }
1603   fclose(fi);
1604
1605 }
1606
1607 void loadgame(int slot)
1608 {
1609   char savefile[1024];
1610   char str[100];
1611   FILE* fi;
1612   unsigned int ui;
1613
1614   sprintf(savefile,"%s/slot%d.save",st_save_dir,slot);
1615
1616   fi = fopen(savefile, "rb");
1617
1618   if (fi == NULL)
1619     {
1620       fprintf(stderr, "Warning: I could not open the slot file ");
1621
1622     }
1623   else
1624     {
1625       fgets(str, 100, fi);
1626       strcpy(level_subset, str);
1627       level_subset[strlen(level_subset)-1] = '\0';
1628       fread(&level,sizeof(int),1,fi);
1629
1630       set_defaults();
1631       level_free(&current_level);
1632       if(level_load(&current_level,level_subset,level) != 0)
1633         exit(1);
1634       arrays_free();
1635       arrays_init();
1636       activate_bad_guys();
1637       activate_particle_systems();
1638       level_free_gfx();
1639       level_load_gfx(&current_level);
1640       level_free_song();
1641       level_load_song(&current_level);
1642       levelintro();
1643       update_time = st_get_ticks();
1644
1645       fread(&score,sizeof(int),1,fi);
1646       fread(&distros,sizeof(int),1,fi);
1647       fread(&scroll_x,sizeof(float),1,fi);
1648       fread(&tux, sizeof(Player), 1, fi);
1649       timer_fread(&tux.invincible_timer,fi);
1650       timer_fread(&tux.skidding_timer,fi);
1651       timer_fread(&tux.safe_timer,fi);
1652       timer_fread(&tux.frame_timer,fi);
1653       timer_fread(&time_left,fi);
1654       fread(&ui,sizeof(int),1,fi);
1655       tux.hphysic.start_time += st_get_ticks() - ui;
1656       tux.vphysic.start_time += st_get_ticks() - ui;
1657       fclose(fi);
1658     }
1659
1660 }
1661
1662 void slotinfo(char **pinfo, int slot)
1663 {
1664   FILE* fi;
1665   char slotfile[1024];
1666   char tmp[200];
1667   char str[5];
1668   int slot_level;
1669   sprintf(slotfile,"%s/slot%d.save",st_save_dir,slot);
1670
1671   fi = fopen(slotfile, "rb");
1672
1673   sprintf(tmp,"Slot %d - ",slot);
1674
1675   if (fi == NULL)
1676     {
1677       strcat(tmp,"Free");
1678     }
1679   else
1680     {
1681       fgets(str, 100, fi);
1682       str[strlen(str)-1] = '\0';
1683       strcat(tmp, str);
1684       strcat(tmp, " / Level:");
1685       fread(&slot_level,sizeof(int),1,fi);
1686       sprintf(str,"%d",slot_level);
1687       strcat(tmp,str);
1688       fclose(fi);
1689     }
1690
1691   *pinfo = (char*) malloc(sizeof(char) * (strlen(tmp)+1));
1692   strcpy(*pinfo,tmp);
1693 }
1694