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