80f5c339dfc7b1f234320e372e9b996c7b6ad0f9
[supertux.git] / src / setup.c
1 /*
2   setup.c
3   
4   Super Tux - Setup
5   
6   by Bill Kendrick
7   bill@newbreedsoftware.com
8   http://www.newbreedsoftware.com/supertux/
9   
10   April 11, 2000 - February 1st, 2004
11 */
12
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <string.h>
16 #include <errno.h>
17 #include <unistd.h>
18 #include <SDL.h>
19 #include <SDL_image.h>
20 #ifndef NOOPENGL
21 #include <SDL_opengl.h>
22 #endif
23
24 #ifdef LINUX
25 #include <pwd.h>
26 #include <sys/stat.h>
27 #include <sys/types.h>
28 #include <dirent.h>
29 #include <ctype.h>
30 #endif
31
32 #include "defines.h"
33 #include "globals.h"
34 #include "setup.h"
35 #include "screen.h"
36 #include "texture.h"
37 #include "menu.h"
38 #include "gameloop.h"
39
40 /* Local function prototypes: */
41
42 void seticon(void);
43 void usage(char * prog, int ret);
44
45 /* Does the given file exist and is it accessible? */
46 int faccessible(char *filename)
47 {
48   struct stat filestat;
49   if (stat(filename, &filestat) == -1)
50     return NO;
51   else
52     return YES;
53 }
54
55 /* Can we write to this location? */
56 int fwriteable(char *filename)
57 {
58   FILE* fi;
59   fi = fopen(filename, "wa");
60   if (fi == NULL)
61     {
62       return NO;
63     }
64   return YES;
65 }
66
67 /* Makes sure a directory is created in either the SuperTux base directory or the SuperTux base directory.*/
68 int fcreatedir(char* relative_dir)
69 {
70   char path[1024];
71   snprintf(path, 1024, "%s/%s/", st_dir, relative_dir);
72   if(mkdir(path,0755) != 0)
73     {
74       snprintf(path, 1024, "%s/%s/", DATA_PREFIX, relative_dir);
75       if(mkdir(path,0755) != 0)
76         {
77           return NO;
78         }
79       else
80         {
81           return YES;
82         }
83     }
84   else
85     {
86       return YES;
87     }
88 }
89
90 /* Get all names of sub-directories in a certain directory. */
91 /* Returns the number of sub-directories found. */
92 /* Note: The user has to free the allocated space. */
93 string_list_type dsubdirs(char *rel_path, char* expected_file)
94 {
95   DIR *dirStructP;
96   struct dirent *direntp;
97   int i = 0;
98   string_list_type sdirs;
99   char filename[1024];
100   char path[1024];
101
102   string_list_init(&sdirs);
103   sprintf(path,"%s/%s",st_dir,rel_path);
104   if((dirStructP = opendir(path)) != NULL)
105     {
106       while((direntp = readdir(dirStructP)) != NULL)
107         {
108           char absolute_filename[1024];
109           struct stat buf;
110
111           sprintf(absolute_filename, "%s/%s", path, direntp->d_name);
112
113           if (stat(absolute_filename, &buf) == 0 && S_ISDIR(buf.st_mode))
114             {
115               if(expected_file != NULL)
116                 {
117                   sprintf(filename,"%s/%s/%s",path,direntp->d_name,expected_file);
118                   if(!faccessible(filename))
119                     continue;
120                 }
121
122               string_list_add_item(&sdirs,direntp->d_name);
123             }
124         }
125       closedir(dirStructP);
126     }
127
128   sprintf(path,"%s/%s",DATA_PREFIX,rel_path);
129   if((dirStructP = opendir(path)) != NULL)
130     {
131       while((direntp = readdir(dirStructP)) != NULL)
132         {
133           char absolute_filename[1024];
134           struct stat buf;
135
136           sprintf(absolute_filename, "%s/%s", path, direntp->d_name);
137
138           if (stat(absolute_filename, &buf) == 0 && S_ISDIR(buf.st_mode))
139             {
140               if(expected_file != NULL)
141                 {
142                   sprintf(filename,"%s/%s/%s",path,direntp->d_name,expected_file);
143                   if(!faccessible(filename))
144                     {
145                       continue;
146                     }
147                   else
148                     {
149                       sprintf(filename,"%s/%s/%s/%s",st_dir,rel_path,direntp->d_name,expected_file);
150                       if(faccessible(filename))
151                         continue;
152                     }
153                 }
154
155               string_list_add_item(&sdirs,direntp->d_name);
156             }
157         }
158       closedir(dirStructP);
159     }
160
161   return sdirs;
162 }
163
164 string_list_type dfiles(char *rel_path, char* glob, char* exception_str)
165 {
166   DIR *dirStructP;
167   struct dirent *direntp;
168   int i = 0;
169   string_list_type sdirs;
170   char filename[1024];
171   char path[1024];
172
173   string_list_init(&sdirs);
174   sprintf(path,"%s/%s",st_dir,rel_path);
175   if((dirStructP = opendir(path)) != NULL)
176     {
177       while((direntp = readdir(dirStructP)) != NULL)
178         {
179           char absolute_filename[1024];
180           struct stat buf;
181
182           sprintf(absolute_filename, "%s/%s", path, direntp->d_name);
183
184           if (stat(absolute_filename, &buf) == 0 && S_ISREG(buf.st_mode))
185             {
186               if(exception_str != NULL)
187                 {
188                   if(strstr(direntp->d_name,exception_str) != NULL)
189                     continue;
190                 }
191               if(glob != NULL)
192                 if(strstr(direntp->d_name,glob) == NULL)
193                   continue;
194
195               string_list_add_item(&sdirs,direntp->d_name);
196             }
197         }
198       closedir(dirStructP);
199     }
200
201   sprintf(path,"%s/%s",DATA_PREFIX,rel_path);
202   if((dirStructP = opendir(path)) != NULL)
203     {
204       while((direntp = readdir(dirStructP)) != NULL)
205         {
206           char absolute_filename[1024];
207           struct stat buf;
208
209           sprintf(absolute_filename, "%s/%s", path, direntp->d_name);
210
211           if (stat(absolute_filename, &buf) == 0 && S_ISREG(buf.st_mode))
212             {
213               if(exception_str != NULL)
214                 {
215                   if(strstr(direntp->d_name,exception_str) != NULL)
216                     continue;
217                 }
218               if(glob != NULL)
219                 if(strstr(direntp->d_name,glob) == NULL)
220                   continue;
221
222               string_list_add_item(&sdirs,direntp->d_name);
223             }
224         }
225       closedir(dirStructP);
226     }
227
228   return sdirs;
229 }
230
231 void free_strings(char **strings, int num)
232 {
233   int i;
234   for(i=0; i < num; ++i)
235     free(strings[i]);
236 }
237
238 /* --- SETUP --- */
239 /* Set SuperTux configuration and save directories */
240 void st_directory_setup(void)
241 {
242   char *home;
243   char str[1024];
244   /* Get home directory (from $HOME variable)... if we can't determine it,
245      use the current directory ("."): */
246   if (getenv("HOME") != NULL)
247     home = getenv("HOME");
248   else
249     home = ".";
250
251   st_dir = (char *) malloc(sizeof(char) * (strlen(home) +
252                            strlen("/.supertux") + 1));
253   strcpy(st_dir, home);
254   strcat(st_dir, "/.supertux");
255
256   st_save_dir = (char *) malloc(sizeof(char) * (strlen(st_dir) + strlen("/save") + 1));
257
258   strcpy(st_save_dir,st_dir);
259   strcat(st_save_dir,"/save");
260
261   /* Create them. In the case they exist they won't destroy anything. */
262 #ifdef LINUX
263
264   mkdir(st_dir, 0755);
265   mkdir(st_save_dir, 0755);
266
267   sprintf(str, "%s/levels", st_dir);
268   mkdir(str, 0755);
269 #else
270   #ifdef WIN32
271
272   mkdir(st_dir);
273   mkdir(st_save_dir);
274   sprintf(str, "%s/levels", st_dir);
275   mkdir(str);
276 #endif
277 #endif
278
279 }
280
281 /* Create and setup menus. */
282 void st_menu(void)
283 {
284   menu_init(&main_menu);
285   menu_additem(&main_menu,menu_item_create(MN_LABEL,"Main Menu",0,0));
286   menu_additem(&main_menu,menu_item_create(MN_HL,"",0,0));
287   menu_additem(&main_menu,menu_item_create(MN_ACTION,"Start Game",0,0));
288   menu_additem(&main_menu,menu_item_create(MN_GOTO,"Load Game",0,&load_game_menu));
289   menu_additem(&main_menu,menu_item_create(MN_GOTO,"Options",0,&options_menu));
290   menu_additem(&main_menu,menu_item_create(MN_ACTION,"Level editor",0,0));
291   menu_additem(&main_menu,menu_item_create(MN_HL,"",0,0));
292   menu_additem(&main_menu,menu_item_create(MN_ACTION,"Quit",0,0));
293
294   menu_init(&options_menu);
295   menu_additem(&options_menu,menu_item_create(MN_LABEL,"Options",0,0));
296   menu_additem(&options_menu,menu_item_create(MN_HL,"",0,0));
297   menu_additem(&options_menu,menu_item_create(MN_TOGGLE,"Fullscreen",use_fullscreen,0));
298   if(audio_device == YES)
299     {
300       menu_additem(&options_menu,menu_item_create(MN_TOGGLE,"Sound     ",use_sound,0));
301       menu_additem(&options_menu,menu_item_create(MN_TOGGLE,"Music     ",use_music,0));
302     }
303   else
304     {
305       menu_additem(&options_menu,menu_item_create(MN_DEACTIVE,"Sound     ",use_sound,0));
306       menu_additem(&options_menu,menu_item_create(MN_DEACTIVE,"Music     ",use_music,0));
307     }
308   menu_additem(&options_menu,menu_item_create(MN_TOGGLE,"Show FPS  ",show_fps,0));
309   menu_additem(&options_menu,menu_item_create(MN_HL,"",0,0));
310   menu_additem(&options_menu,menu_item_create(MN_BACK,"Back",0,0));
311
312   menu_init(&load_game_menu);
313   menu_additem(&load_game_menu,menu_item_create(MN_LABEL,"Load Game",0,0));
314   menu_additem(&load_game_menu,menu_item_create(MN_HL,"",0,0));
315   menu_additem(&load_game_menu,menu_item_create(MN_DEACTIVE,"Slot 1",0,0));
316   menu_additem(&load_game_menu,menu_item_create(MN_DEACTIVE,"Slot 2",0,0));
317   menu_additem(&load_game_menu,menu_item_create(MN_DEACTIVE,"Slot 3",0,0));
318   menu_additem(&load_game_menu,menu_item_create(MN_DEACTIVE,"Slot 4",0,0));
319   menu_additem(&load_game_menu,menu_item_create(MN_DEACTIVE,"Slot 5",0,0));
320   menu_additem(&load_game_menu,menu_item_create(MN_HL,"",0,0));
321   menu_additem(&load_game_menu,menu_item_create(MN_BACK,"Back",0,0));
322
323   menu_init(&save_game_menu);
324   menu_additem(&save_game_menu,menu_item_create(MN_LABEL,"Save Game",0,0));
325   menu_additem(&save_game_menu,menu_item_create(MN_HL,"",0,0));
326   menu_additem(&save_game_menu,menu_item_create(MN_DEACTIVE,"Slot 1",0,0));
327   menu_additem(&save_game_menu,menu_item_create(MN_DEACTIVE,"Slot 2",0,0));
328   menu_additem(&save_game_menu,menu_item_create(MN_DEACTIVE,"Slot 3",0,0));
329   menu_additem(&save_game_menu,menu_item_create(MN_DEACTIVE,"Slot 4",0,0));
330   menu_additem(&save_game_menu,menu_item_create(MN_DEACTIVE,"Slot 5",0,0));
331   menu_additem(&save_game_menu,menu_item_create(MN_HL,"",0,0));
332   menu_additem(&save_game_menu,menu_item_create(MN_BACK,"Back",0,0));
333
334   menu_init(&game_menu);
335   menu_additem(&game_menu,menu_item_create(MN_LABEL,"InGame Menu",0,0));
336   menu_additem(&game_menu,menu_item_create(MN_HL,"",0,0));
337   menu_additem(&game_menu,menu_item_create(MN_ACTION,"Return To Game",0,0));
338   menu_additem(&game_menu,menu_item_create(MN_GOTO,"Save Game",0,&save_game_menu));
339   menu_additem(&game_menu,menu_item_create(MN_GOTO,"Load Game",0,&load_game_menu));
340   menu_additem(&game_menu,menu_item_create(MN_GOTO,"Options",0,&options_menu));
341   menu_additem(&game_menu,menu_item_create(MN_HL,"",0,0));
342   menu_additem(&game_menu,menu_item_create(MN_ACTION,"Quit Game",0,0));
343
344   menu_init(&highscore_menu);
345   menu_additem(&highscore_menu,menu_item_create(MN_TEXTFIELD,"Enter your name:",0,0));
346
347 }
348
349 void update_load_save_game_menu(menu_type* pmenu, int load)
350 {
351   int i;
352
353   for(i = 2; i < 7; ++i)
354     {
355       char *tmp;
356       slotinfo(&tmp,i-1);
357       if(load && strlen(tmp) == strlen("Slot X - Free") )
358         pmenu->item[i].kind = MN_DEACTIVE;
359       else
360         pmenu->item[i].kind = MN_ACTION;
361       menu_item_change_text(&pmenu->item[i],tmp);
362       free(tmp);
363     }
364 }
365
366 void process_save_load_game_menu(int save)
367 {
368   int slot;
369   switch (slot = menu_check(save ? &save_game_menu : &load_game_menu))
370     {
371     default:
372       if(slot != -1)
373         {
374           if(save == YES)
375             {
376               savegame(slot);
377             }
378           else
379             {
380               if(game_started == NO)
381                 gameloop("whatever",slot,ST_GL_LOAD_GAME);
382               else
383                 loadgame(slot);
384             }
385           st_pause_ticks_stop();
386         }
387       break;
388     }
389 }
390
391 /* Handle changes made to global settings in the options menu. */
392 void process_options_menu(void)
393 {
394   switch (menu_check(&options_menu))
395     {
396     case 2:
397       if(use_fullscreen != options_menu.item[2].toggled)
398         {
399           use_fullscreen = !use_fullscreen;
400           st_video_setup();
401         }
402       break;
403     case 3:
404       if(use_sound != options_menu.item[3].toggled)
405         use_sound = !use_sound;
406       break;
407     case 4:
408       if(use_music != options_menu.item[4].toggled)
409         {
410           if(use_music == YES)
411             {
412               if(playing_music())
413                 {
414                   halt_music();
415                 }
416               use_music = NO;
417             }
418           else
419             {
420               use_music = YES;
421               if (!playing_music())
422                 {
423                   play_current_music();
424                 }
425             }
426         }
427       break;
428     case 5:
429       if(show_fps != options_menu.item[5].toggled)
430         show_fps = !show_fps;
431       break;
432     }
433 }
434
435 void st_general_setup(void)
436 {
437   /* Seed random number generator: */
438
439   srand(SDL_GetTicks());
440
441   /* Load global images: */
442
443   text_load(&black_text,DATA_PREFIX "/images/status/letters-black.png", TEXT_TEXT, 16,18);
444   text_load(&gold_text,DATA_PREFIX "/images/status/letters-gold.png", TEXT_TEXT, 16,18);
445   text_load(&blue_text,DATA_PREFIX "/images/status/letters-blue.png", TEXT_TEXT, 16,18);
446   text_load(&red_text,DATA_PREFIX "/images/status/letters-red.png", TEXT_TEXT, 16,18);
447   text_load(&white_text,DATA_PREFIX "/images/status/letters-white.png", TEXT_TEXT, 16,18);
448   text_load(&white_small_text,DATA_PREFIX "/images/status/letters-white-small.png", TEXT_TEXT, 8,9);
449   text_load(&white_big_text,DATA_PREFIX "/images/status/letters-white-big.png", TEXT_TEXT, 20,23);
450   text_load(&yellow_nums,DATA_PREFIX "/images/status/numbers.png", TEXT_NUM, 32,32);
451
452   /* Load GUI/menu images: */
453   texture_load(&checkbox, DATA_PREFIX "/images/status/checkbox.png", USE_ALPHA);
454   texture_load(&checkbox_checked, DATA_PREFIX "/images/status/checkbox-checked.png", USE_ALPHA);
455   texture_load(&back, DATA_PREFIX "/images/status/back.png", USE_ALPHA);
456   texture_load(&arrow_left, DATA_PREFIX "/images/icons/left.png", USE_ALPHA);
457   texture_load(&arrow_right, DATA_PREFIX "/images/icons/right.png", USE_ALPHA);
458
459   /* Set icon image: */
460
461   seticon();
462   SDL_EnableUNICODE(1);
463
464 }
465
466 void st_general_free(void)
467 {
468
469   /* Free global images: */
470
471   text_free(&black_text);
472   text_free(&gold_text);
473   text_free(&white_text);
474   text_free(&blue_text);
475   text_free(&red_text);
476   text_free(&white_small_text);
477   text_free(&white_big_text);
478
479   /* Free GUI/menu images: */
480   texture_free(&checkbox);
481   texture_free(&checkbox_checked);
482   texture_free(&back);
483   texture_free(&arrow_left);
484   texture_free(&arrow_right);
485   
486   /* Free menus */
487
488   menu_free(&main_menu);
489   menu_free(&game_menu);
490   menu_free(&options_menu);
491   menu_free(&highscore_menu);
492   menu_free(&save_game_menu);
493   menu_free(&load_game_menu);
494
495 }
496
497 void st_video_setup(void)
498 {
499
500   if(screen != NULL)
501     SDL_FreeSurface(screen);
502
503   /* Init SDL Video: */
504
505   if (SDL_Init(SDL_INIT_VIDEO) < 0)
506     {
507       fprintf(stderr,
508               "\nError: I could not initialize video!\n"
509               "The Simple DirectMedia error that occured was:\n"
510               "%s\n\n", SDL_GetError());
511       exit(1);
512     }
513
514   /* Open display: */
515
516   if(use_gl)
517     st_video_setup_gl();
518   else
519     st_video_setup_sdl();
520
521   texture_setup();
522
523   /* Set window manager stuff: */
524
525   SDL_WM_SetCaption("Super Tux", "Super Tux");
526
527 }
528
529 void st_video_setup_sdl(void)
530 {
531   SDL_FreeSurface(screen);
532
533   if (use_fullscreen == YES)
534     {
535       screen = SDL_SetVideoMode(640, 480, 16, SDL_FULLSCREEN ) ; /* | SDL_HWSURFACE); */
536       if (screen == NULL)
537         {
538           fprintf(stderr,
539                   "\nWarning: I could not set up fullscreen video for "
540                   "640x480 mode.\n"
541                   "The Simple DirectMedia error that occured was:\n"
542                   "%s\n\n", SDL_GetError());
543           use_fullscreen = NO;
544         }
545     }
546   else
547     {
548       screen = SDL_SetVideoMode(640, 480, 16, SDL_HWSURFACE | SDL_DOUBLEBUF );
549
550       if (screen == NULL)
551         {
552           fprintf(stderr,
553                   "\nError: I could not set up video for 640x480 mode.\n"
554                   "The Simple DirectMedia error that occured was:\n"
555                   "%s\n\n", SDL_GetError());
556           exit(1);
557         }
558     }
559 }
560
561 void st_video_setup_gl(void)
562 {
563 #ifndef NOOPENGL
564
565   SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 5);
566   SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 5);
567   SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5);
568   SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);
569   SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
570
571   if (use_fullscreen == YES)
572     {
573       screen = SDL_SetVideoMode(640, 480, 32, SDL_FULLSCREEN | SDL_OPENGL) ; /* | SDL_HWSURFACE); */
574       if (screen == NULL)
575         {
576           fprintf(stderr,
577                   "\nWarning: I could not set up fullscreen video for "
578                   "640x480 mode.\n"
579                   "The Simple DirectMedia error that occured was:\n"
580                   "%s\n\n", SDL_GetError());
581           use_fullscreen = NO;
582         }
583     }
584   else
585     {
586       screen = SDL_SetVideoMode(640, 480, 32, SDL_OPENGL);
587
588       if (screen == NULL)
589         {
590           fprintf(stderr,
591                   "\nError: I could not set up video for 640x480 mode.\n"
592                   "The Simple DirectMedia error that occured was:\n"
593                   "%s\n\n", SDL_GetError());
594           exit(1);
595         }
596     }
597
598   /*
599    * Set up OpenGL for 2D rendering.
600    */
601   glDisable(GL_DEPTH_TEST);
602   glDisable(GL_CULL_FACE);
603
604   glViewport(0, 0, screen->w, screen->h);
605   glMatrixMode(GL_PROJECTION);
606   glLoadIdentity();
607   glOrtho(0, screen->w, screen->h, 0, -1.0, 1.0);
608
609   glMatrixMode(GL_MODELVIEW);
610   glLoadIdentity();
611   glTranslatef(0.0f, 0.0f, 0.0f);
612
613 #endif
614
615 }
616
617 void st_joystick_setup(void)
618 {
619
620   /* Init Joystick: */
621
622 #ifdef JOY_YES
623   use_joystick = YES;
624
625   if (SDL_Init(SDL_INIT_JOYSTICK) < 0)
626     {
627       fprintf(stderr, "Warning: I could not initialize joystick!\n"
628               "The Simple DirectMedia error that occured was:\n"
629               "%s\n\n", SDL_GetError());
630
631       use_joystick = NO;
632     }
633   else
634     {
635       /* Open joystick: */
636
637       if (SDL_NumJoysticks() <= 0)
638         {
639           fprintf(stderr, "Warning: No joysticks are available.\n");
640
641           use_joystick = NO;
642         }
643       else
644         {
645           js = SDL_JoystickOpen(0);
646
647           if (js == NULL)
648             {
649               fprintf(stderr, "Warning: Could not open joystick 1.\n"
650                       "The Simple DirectMedia error that occured was:\n"
651                       "%s\n\n", SDL_GetError());
652
653               use_joystick = NO;
654             }
655           else
656             {
657               /* Check for proper joystick configuration: */
658
659               if (SDL_JoystickNumAxes(js) < 2)
660                 {
661                   fprintf(stderr,
662                           "Warning: Joystick does not have enough axes!\n");
663
664                   use_joystick = NO;
665                 }
666               else
667                 {
668                   if (SDL_JoystickNumButtons(js) < 2)
669                     {
670                       fprintf(stderr,
671                               "Warning: "
672                               "Joystick does not have enough buttons!\n");
673
674                       use_joystick = NO;
675                     }
676                 }
677             }
678         }
679     }
680 #endif
681
682 }
683
684 void st_audio_setup(void)
685 {
686
687   /* Init SDL Audio silently even if --disable-sound : */
688
689   if (audio_device == YES)
690     {
691       if (SDL_Init(SDL_INIT_AUDIO) < 0)
692         {
693           /* only print out message if sound or music
694              was not disabled at command-line
695            */
696           if (use_sound == YES || use_music == YES)
697             {
698               fprintf(stderr,
699                       "\nWarning: I could not initialize audio!\n"
700                       "The Simple DirectMedia error that occured was:\n"
701                       "%s\n\n", SDL_GetError());
702             }
703           /* keep the programming logic the same :-)
704              because in this case, use_sound & use_music' values are ignored
705              when there's no available audio device
706           */
707           use_sound = NO;
708           use_music = NO;
709           audio_device = NO;
710         }
711     }
712
713
714   /* Open sound silently regarless the value of "use_sound": */
715
716   if (audio_device == YES)
717     {
718       if (open_audio(44100, AUDIO_S16, 2, 2048) < 0)
719         {
720           /* only print out message if sound or music
721              was not disabled at command-line
722            */
723           if ((use_sound == YES) || (use_music == YES))
724             {
725               fprintf(stderr,
726                       "\nWarning: I could not set up audio for 44100 Hz "
727                       "16-bit stereo.\n"
728                       "The Simple DirectMedia error that occured was:\n"
729                       "%s\n\n", SDL_GetError());
730             }
731           use_sound = NO;
732           use_music = NO;
733           audio_device = NO;
734         }
735     }
736
737 }
738
739
740 /* --- SHUTDOWN --- */
741
742 void st_shutdown(void)
743 {
744   close_audio();
745   SDL_Quit();
746 }
747
748
749 /* --- ABORT! --- */
750
751 void st_abort(char * reason, char * details)
752 {
753   fprintf(stderr, "\nError: %s\n%s\n\n", reason, details);
754   st_shutdown();
755   exit(1);
756 }
757
758
759 /* Set Icon (private) */
760
761 void seticon(void)
762 {
763   int masklen;
764   Uint8 * mask;
765   SDL_Surface * icon;
766
767
768   /* Load icon into a surface: */
769
770   icon = IMG_Load(DATA_PREFIX "/images/icon.png");
771   if (icon == NULL)
772     {
773       fprintf(stderr,
774               "\nError: I could not load the icon image: %s\n"
775               "The Simple DirectMedia error that occured was:\n"
776               "%s\n\n", DATA_PREFIX "images/icon.png", SDL_GetError());
777       exit(1);
778     }
779
780
781   /* Create mask: */
782
783   masklen = (((icon -> w) + 7) / 8) * (icon -> h);
784   mask = (Uint8*) malloc(masklen * sizeof(Uint8));
785   memset(mask, 0xFF, masklen);
786
787
788   /* Set icon: */
789
790   SDL_WM_SetIcon(icon, mask);
791
792
793   /* Free icon surface & mask: */
794
795   free(mask);
796   SDL_FreeSurface(icon);
797 }
798
799
800 /* Parse command-line arguments: */
801
802 void parseargs(int argc, char * argv[])
803 {
804   int i;
805
806   /* Set defaults: */
807
808
809   debug_mode = NO;
810   use_fullscreen = NO;
811   show_fps = NO;
812   use_gl = NO;
813
814 #ifndef NOSOUND
815
816   use_sound = YES;
817   use_music = YES;
818   audio_device = YES;
819 #else
820
821   use_sound = NO;
822   use_music = NO;
823   audio_device = NO;
824 #endif
825
826   /* Parse arguments: */
827
828   for (i = 1; i < argc; i++)
829     {
830       if (strcmp(argv[i], "--fullscreen") == 0 ||
831           strcmp(argv[i], "-f") == 0)
832         {
833           /* Use full screen: */
834
835           use_fullscreen = YES;
836         }
837       else if (strcmp(argv[i], "--show-fps") == 0)
838         {
839           /* Use full screen: */
840
841           show_fps = YES;
842         }
843       else if (strcmp(argv[i], "--opengl") == 0 ||
844                strcmp(argv[i], "-gl") == 0)
845         {
846 #ifndef NOOPENGL
847           /* Use OpengGL: */
848
849           use_gl = YES;
850 #endif
851
852         }
853       else if (strcmp(argv[i], "--usage") == 0)
854         {
855           /* Show usage: */
856
857           usage(argv[0], 0);
858         }
859       else if (strcmp(argv[i], "--version") == 0)
860         {
861           /* Show version: */
862
863           printf("Super Tux - version " VERSION "\n");
864           exit(0);
865         }
866       else if (strcmp(argv[i], "--disable-sound") == 0)
867         {
868           /* Disable the compiled in sound feature */
869 #ifndef NOSOUND
870           printf("Sounds disabled \n");
871           use_sound = NO;
872 #else
873
874           printf("Warning: Sounds feature is not compiled in \n");
875 #endif
876
877         }
878       else if (strcmp(argv[i], "--disable-music") == 0)
879         {
880           /* Disable the compiled in sound feature */
881 #ifndef NOSOUND
882           printf("Music disabled \n");
883           use_music = NO;
884 #else
885
886           printf("Warning: Music feature is not compiled in \n");
887 #endif
888
889         }
890       else if (strcmp(argv[i], "--debug-mode") == 0)
891         {
892           /* Enable the debug-mode */
893           debug_mode = YES;
894
895         }
896       else if (strcmp(argv[i], "--help") == 0)
897         {         /* Show help: */
898
899           printf("Super Tux " VERSION "\n\n");
900
901           printf("----------  Command-line options  ----------\n\n");
902
903           printf("  --opengl            - If opengl support was compiled in, this will enable the EXPERIMENTAL OpenGL mode.\n\n");
904
905           printf("  --disable-sound     - If sound support was compiled in,  this will\n                        disable sound for this session of the game.\n\n");
906
907           printf("  --disable-music     - Like above, but this will disable music.\n\n");
908
909           printf("  --fullscreen        - Run in fullscreen mode.\n\n");
910
911           printf("  --debug-mode        - Enables the debug-mode, which is useful for developers.\n\n");
912
913           printf("  --help              - Display a help message summarizing command-line\n                        options, license and game controls.\n\n");
914
915           printf("  --usage             - Display a brief message summarizing command-line options.\n\n");
916
917           printf("  --version           - Display the version of SuperTux you're running.\n\n\n");
918
919
920           printf("----------          License       ----------\n\n");
921           printf("  This program comes with ABSOLUTELY NO WARRANTY.\n");
922           printf("  This is free software, and you are welcome to redistribute\n");
923           printf("  or modify it under certain conditions. See the file \n");
924           printf("  \"COPYING.txt\" for more details.\n\n\n");
925
926           printf("----------      Game controls     ----------\n\n");
927           printf("  Please see the file \"README.txt\"\n\n");
928
929           exit(0);
930         }
931       else
932         {
933           /* Unknown - complain! */
934
935           usage(argv[0], 1);
936         }
937     }
938 }
939
940
941 /* Display usage: */
942
943 void usage(char * prog, int ret)
944 {
945   FILE * fi;
946
947
948   /* Determine which stream to write to: */
949
950   if (ret == 0)
951     fi = stdout;
952   else
953     fi = stderr;
954
955
956   /* Display the usage message: */
957
958   fprintf(fi, "Usage: %s [--fullscreen] [--opengl] [--disable-sound] [--disable-music] [--debug-mode] | [--usage | --help | --version]\n",
959           prog);
960
961
962   /* Quit! */
963
964   exit(ret);
965 }
966