83be24430925449efd15a31c9fcd9dbb24cc8717
[supertux.git] / lib / app / setup.cpp
1 //  $Id$
2 //
3 //  SuperTux -  A Jump'n Run
4 //  Copyright (C) 2000 Bill Kendrick <bill@newbreedsoftware.com>
5 //
6 //  This program is free software; you can redistribute it and/or
7 //  modify it under the terms of the GNU General Public License
8 //  as published by the Free Software Foundation; either version 2
9 //  of the License, or (at your option) any later version.
10 //
11 //  This program is distributed in the hope that it will be useful,
12 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
13 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 //  GNU General Public License for more details.
15 //
16 //  You should have received a copy of the GNU General Public License
17 //  along with this program; if not, write to the Free Software
18 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19
20 #include <cassert>
21 #include <cstdio>
22 #include <iostream>
23 #include <cstdio>
24 #include <cstdlib>
25 #include <cstring>
26 #include <cerrno>
27 #include <unistd.h>
28
29 #include "SDL.h"
30 #include "SDL_image.h"
31 #ifndef NOOPENGL
32 #include "SDL_opengl.h"
33 #endif
34
35 #include <sys/stat.h>
36 #include <sys/types.h>
37 #include <dirent.h>
38 #ifndef WIN32
39 #include <libgen.h>
40 #endif
41
42 #include <cctype>
43
44 #include "../app/globals.h"
45 #include "../app/defines.h"
46 #include "../app/setup.h"
47 #include "../video/screen.h"
48 #include "../video/surface.h"
49 #include "../gui/menu.h"
50 #include "../utils/configfile.h"
51 #include "../audio/sound_manager.h"
52 #include "../app/gettext.h"
53
54 using namespace SuperTux;
55
56 #ifdef WIN32
57 #define mkdir(dir, mode)    mkdir(dir)
58 // on win32 we typically don't want LFS paths
59 #undef DATA_PREFIX
60 #define DATA_PREFIX "./data/"
61 #endif
62
63 /* Local function prototypes: */
64
65 void seticon(void);
66 void usage(char * prog, int ret);
67
68 /* Does the given file exist and is it accessible? */
69 int FileSystem::faccessible(const char *filename)
70 {
71   struct stat filestat;
72   if (stat(filename, &filestat) == -1)
73     {
74       return false;
75     }
76   else
77     {
78       if(S_ISREG(filestat.st_mode))
79         return true;
80       else
81         return false;
82     }
83 }
84
85 /* Can we write to this location? */
86 int FileSystem::fwriteable(const char *filename)
87 {
88   FILE* fi;
89   fi = fopen(filename, "wa");
90   if (fi == NULL)
91     {
92       return false;
93     }
94   return true;
95 }
96
97 /* Makes sure a directory is created in either the SuperTux home directory or the SuperTux base directory.*/
98 int FileSystem::fcreatedir(const char* relative_dir)
99 {
100   char path[1024];
101   snprintf(path, 1024, "%s/%s/", st_dir, relative_dir);
102   if(mkdir(path,0755) != 0)
103     {
104       snprintf(path, 1024, "%s/%s/", datadir.c_str(), relative_dir);
105       if(mkdir(path,0755) != 0)
106         {
107           return false;
108         }
109       else
110         {
111           return true;
112         }
113     }
114   else
115     {
116       return true;
117     }
118 }
119
120 /* Get all names of sub-directories in a certain directory. */
121 /* Returns the number of sub-directories found. */
122 /* Note: The user has to free the allocated space. */
123 string_list_type FileSystem::dsubdirs(const char *rel_path,const  char* expected_file)
124 {
125   DIR *dirStructP;
126   struct dirent *direntp;
127   string_list_type sdirs;
128   char filename[1024];
129   char path[1024];
130
131   string_list_init(&sdirs);
132   sprintf(path,"%s/%s",st_dir,rel_path);
133   if((dirStructP = opendir(path)) != NULL)
134     {
135       while((direntp = readdir(dirStructP)) != NULL)
136         {
137           char absolute_filename[1024];
138           struct stat buf;
139
140           sprintf(absolute_filename, "%s/%s", path, direntp->d_name);
141
142           if (stat(absolute_filename, &buf) == 0 && S_ISDIR(buf.st_mode))
143             {
144               if(expected_file != NULL)
145                 {
146                   sprintf(filename,"%s/%s/%s",path,direntp->d_name,expected_file);
147                   if(!faccessible(filename))
148                     continue;
149                 }
150
151               string_list_add_item(&sdirs,direntp->d_name);
152             }
153         }
154       closedir(dirStructP);
155     }
156
157   sprintf(path,"%s/%s",datadir.c_str(),rel_path);
158   if((dirStructP = opendir(path)) != NULL)
159     {
160       while((direntp = readdir(dirStructP)) != NULL)
161         {
162           char absolute_filename[1024];
163           struct stat buf;
164
165           sprintf(absolute_filename, "%s/%s", path, direntp->d_name);
166
167           if (stat(absolute_filename, &buf) == 0 && S_ISDIR(buf.st_mode))
168             {
169               if(expected_file != NULL)
170                 {
171                   sprintf(filename,"%s/%s/%s",path,direntp->d_name,expected_file);
172                   if(!faccessible(filename))
173                     {
174                       continue;
175                     }
176                   else
177                     {
178                       sprintf(filename,"%s/%s/%s/%s",st_dir,rel_path,direntp->d_name,expected_file);
179                       if(faccessible(filename))
180                         continue;
181                     }
182                 }
183
184               string_list_add_item(&sdirs,direntp->d_name);
185             }
186         }
187       closedir(dirStructP);
188     }
189
190   return sdirs;
191 }
192
193 string_list_type FileSystem::dfiles(const char *rel_path, const  char* glob, const  char* exception_str)
194 {
195   DIR *dirStructP;
196   struct dirent *direntp;
197   string_list_type sdirs;
198   char path[1024];
199
200   string_list_init(&sdirs);
201   sprintf(path,"%s/%s",st_dir,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   sprintf(path,"%s/%s",datadir.c_str(),rel_path);
229   if((dirStructP = opendir(path)) != NULL)
230     {
231       while((direntp = readdir(dirStructP)) != NULL)
232         {
233           char absolute_filename[1024];
234           struct stat buf;
235
236           sprintf(absolute_filename, "%s/%s", path, direntp->d_name);
237
238           if (stat(absolute_filename, &buf) == 0 && S_ISREG(buf.st_mode))
239             {
240               if(exception_str != NULL)
241                 {
242                   if(strstr(direntp->d_name,exception_str) != NULL)
243                     continue;
244                 }
245               if(glob != NULL)
246                 if(strstr(direntp->d_name,glob) == NULL)
247                   continue;
248
249               string_list_add_item(&sdirs,direntp->d_name);
250             }
251         }
252       closedir(dirStructP);
253     }
254
255   return sdirs;
256 }
257
258 void Setup::info(const std::string& _package_name, const std::string& _package_symbol_name, const std::string& _package_version)
259 {
260 package_name = _package_name;
261 package_symbol_name = _package_symbol_name;
262 package_version = _package_version;
263 }
264
265 /* --- SETUP --- */
266 /* Set SuperTux configuration and save directories */
267 void Setup::directories(void)
268 {
269   char *home;
270   char str[1024];
271   /* Get home directory (from $HOME variable)... if we can't determine it,
272      use the current directory ("."): */
273   if (getenv("HOME") != NULL)
274     home = getenv("HOME");
275   else
276     home = ".";
277
278   std::string st_dir_tmp = "/." + package_symbol_name;
279   st_dir = (char *) malloc(sizeof(char) * (strlen(home) +
280                                            strlen(st_dir_tmp.c_str()) + 1));
281   strcpy(st_dir, home);
282   strcat(st_dir,st_dir_tmp.c_str());
283
284   /* Remove .supertux config-file from old SuperTux versions */
285   if(FileSystem::faccessible(st_dir))
286     {
287       remove
288         (st_dir);
289     }
290
291   st_save_dir = (char *) malloc(sizeof(char) * (strlen(st_dir) + strlen("/save") + 1));
292
293   strcpy(st_save_dir,st_dir);
294   strcat(st_save_dir,"/save");
295
296   /* Create them. In the case they exist they won't destroy anything. */
297   mkdir(st_dir, 0755);
298   mkdir(st_save_dir, 0755);
299
300   sprintf(str, "%s/levels", st_dir);
301   mkdir(str, 0755);
302
303   // User has not that a datadir, so we try some magic
304   if (datadir.empty())
305     {
306 #ifndef WIN32
307       // Detect datadir
308       char exe_file[PATH_MAX];
309       if (readlink("/proc/self/exe", exe_file, PATH_MAX) < 0)
310         {
311           puts("Couldn't read /proc/self/exe, using default path: " DATA_PREFIX);
312           datadir = DATA_PREFIX;
313         }
314       else
315         {
316           std::string exedir = std::string(dirname(exe_file)) + "/";
317           
318           datadir = exedir + "../data"; // SuperTux run from source dir
319           if (access(datadir.c_str(), F_OK) != 0)
320             {
321               datadir = exedir + "../share/" + package_symbol_name; // SuperTux run from PATH
322               if (access(datadir.c_str(), F_OK) != 0) 
323                 { // If all fails, fall back to compiled path
324                   datadir = DATA_PREFIX; 
325                 }
326             }
327         }
328 #else
329   datadir = DATA_PREFIX;
330 #endif
331     }
332   printf("Datadir: %s\n", datadir.c_str());
333 }
334
335 void Setup::general(void)
336 {
337   /* Seed random number generator: */
338
339   srand(SDL_GetTicks());
340
341   /* Set icon image: */
342
343   seticon();
344
345   /* Unicode needed for input handling: */
346
347   SDL_EnableUNICODE(1);
348
349   /* Load global images: */
350   gold_text = new Font(datadir + "/images/fonts/gold.png", Font::TEXT, 16,18);
351   blue_text = new Font(datadir + "/images/fonts/blue.png", Font::TEXT, 16,18,3);
352   white_text  = new Font(datadir + "/images/fonts/white.png",
353       Font::TEXT, 16,18);
354   gray_text  = new Font(datadir + "/images/fonts/gray.png",
355       Font::TEXT, 16,18);
356   white_small_text = new Font(datadir + "/images/fonts/white-small.png",
357           Font::TEXT, 8,9, 1);
358   white_big_text   = new Font(datadir + "/images/fonts/white-big.png",
359       Font::TEXT, 20,22, 3);
360   yellow_nums = new Font(datadir + "/images/fonts/numbers.png",
361       Font::NUM, 32,32);
362
363   /* Load GUI/menu images: */
364   checkbox = new Surface(datadir + "/images/status/checkbox.png", true);
365   checkbox_checked = new Surface(datadir + "/images/status/checkbox-checked.png", true);
366   back = new Surface(datadir + "/images/status/back.png", true);
367   arrow_left = new Surface(datadir + "/images/icons/left.png", true);
368   arrow_right = new Surface(datadir + "/images/icons/right.png", true);
369
370   /* Load the mouse-cursor */
371   mouse_cursor = new MouseCursor( datadir + "/images/status/mousecursor.png",1);
372   MouseCursor::set_current(mouse_cursor);
373   
374 }
375
376 void Setup::general_free(void)
377 {
378
379   /* Free global images: */
380   delete gold_text;
381   delete white_text;
382   delete blue_text;
383   delete gray_text;
384   delete white_small_text;
385   delete white_big_text;
386   delete yellow_nums;
387
388   /* Free GUI/menu images: */
389   delete checkbox;
390   delete checkbox_checked;
391   delete back;
392   delete arrow_left;
393   delete arrow_right;
394
395   /* Free mouse-cursor */
396   delete mouse_cursor;
397   
398 }
399
400 void Setup::video(unsigned int screen_w, unsigned int screen_h)
401 {
402   /* Init SDL Video: */
403   if (SDL_Init(SDL_INIT_VIDEO) < 0)
404     {
405       fprintf(stderr,
406               "\nError: I could not initialize video!\n"
407               "The Simple DirectMedia error that occured was:\n"
408               "%s\n\n", SDL_GetError());
409       exit(1);
410     }
411
412   /* Open display: */
413   if(use_gl)
414     video_gl(screen_w, screen_h);
415   else
416     video_sdl(screen_w, screen_h);
417
418   Surface::reload_all();
419
420   /* Set window manager stuff: */
421   SDL_WM_SetCaption((package_name + " " + package_version).c_str(), package_name.c_str());
422 }
423
424 void Setup::video_sdl(unsigned int screen_w, unsigned int screen_h)
425 {
426   if (use_fullscreen)
427     {
428       screen = SDL_SetVideoMode(screen_w, screen_h, 0, SDL_FULLSCREEN ) ; /* | SDL_HWSURFACE); */
429       if (screen == NULL)
430         {
431           fprintf(stderr,
432                   "\nWarning: I could not set up fullscreen video for "
433                   "800x600 mode.\n"
434                   "The Simple DirectMedia error that occured was:\n"
435                   "%s\n\n", SDL_GetError());
436           use_fullscreen = false;
437         }
438     }
439   else
440     {
441       screen = SDL_SetVideoMode(screen_w, screen_h, 0, SDL_HWSURFACE | SDL_DOUBLEBUF );
442
443       if (screen == NULL)
444         {
445           fprintf(stderr,
446                   "\nError: I could not set up video for 800x600 mode.\n"
447                   "The Simple DirectMedia error that occured was:\n"
448                   "%s\n\n", SDL_GetError());
449           exit(1);
450         }
451     }
452 }
453
454 void Setup::video_gl(unsigned int screen_w, unsigned int screen_h)
455 {
456 #ifndef NOOPENGL
457
458   SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 5);
459   SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 5);
460   SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5);
461   SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);
462   SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
463
464   if (use_fullscreen)
465     {
466       screen = SDL_SetVideoMode(screen_w, screen_h, 0, SDL_FULLSCREEN | SDL_OPENGL) ; /* | SDL_HWSURFACE); */
467       if (screen == NULL)
468         {
469           fprintf(stderr,
470                   "\nWarning: I could not set up fullscreen video for "
471                   "640x480 mode.\n"
472                   "The Simple DirectMedia error that occured was:\n"
473                   "%s\n\n", SDL_GetError());
474           use_fullscreen = false;
475         }
476     }
477   else
478     {
479       screen = SDL_SetVideoMode(screen_w, screen_h, 0, SDL_OPENGL);
480
481       if (screen == NULL)
482         {
483           fprintf(stderr,
484                   "\nError: I could not set up video for 640x480 mode.\n"
485                   "The Simple DirectMedia error that occured was:\n"
486                   "%s\n\n", SDL_GetError());
487           exit(1);
488         }
489     }
490
491   /*
492    * Set up OpenGL for 2D rendering.
493    */
494   glDisable(GL_DEPTH_TEST);
495   glDisable(GL_CULL_FACE);
496
497   glViewport(0, 0, screen->w, screen->h);
498   glMatrixMode(GL_PROJECTION);
499   glLoadIdentity();
500   glOrtho(0, screen->w, screen->h, 0, -1.0, 1.0);
501
502   glMatrixMode(GL_MODELVIEW);
503   glLoadIdentity();
504   glTranslatef(0.0f, 0.0f, 0.0f);
505
506 #endif
507
508 }
509
510 void Setup::joystick(void)
511 {
512
513   /* Init Joystick: */
514
515   use_joystick = true;
516
517   if (SDL_Init(SDL_INIT_JOYSTICK) < 0)
518     {
519       fprintf(stderr, "Warning: I could not initialize joystick!\n"
520               "The Simple DirectMedia error that occured was:\n"
521               "%s\n\n", SDL_GetError());
522
523       use_joystick = false;
524     }
525   else
526     {
527       /* Open joystick: */
528       if (SDL_NumJoysticks() <= 0)
529         {
530           fprintf(stderr, "Info: No joysticks were found.\n");
531
532           use_joystick = false;
533         }
534       else
535         {
536           js = SDL_JoystickOpen(joystick_num);
537
538           if (js == NULL)
539             {
540               fprintf(stderr, "Warning: Could not open joystick %d.\n"
541                       "The Simple DirectMedia error that occured was:\n"
542                       "%s\n\n", joystick_num, SDL_GetError());
543
544               use_joystick = false;
545             }
546           else
547             {
548               if (SDL_JoystickNumAxes(js) < 2)
549                 {
550                   fprintf(stderr,
551                           "Warning: Joystick does not have enough axes!\n");
552
553                   use_joystick = false;
554                 }
555               else
556                 {
557                   if (SDL_JoystickNumButtons(js) < 2)
558                     {
559                       fprintf(stderr,
560                               "Warning: "
561                               "Joystick does not have enough buttons!\n");
562
563                       use_joystick = false;
564                     }
565                 }
566             }
567         }
568     }
569 }
570
571 void Setup::audio(void)
572 {
573
574   /* Init SDL Audio silently even if --disable-sound : */
575
576   if (SoundManager::get()->audio_device_available())
577     {
578       if (SDL_Init(SDL_INIT_AUDIO) < 0)
579         {
580           /* only print out message if sound or music
581              was not disabled at command-line
582            */
583           if (SoundManager::get()->sound_enabled() || SoundManager::get()->music_enabled())
584             {
585               fprintf(stderr,
586                       "\nWarning: I could not initialize audio!\n"
587                       "The Simple DirectMedia error that occured was:\n"
588                       "%s\n\n", SDL_GetError());
589             }
590           /* keep the programming logic the same :-)
591              because in this case, use_sound & use_music' values are ignored
592              when there's no available audio device
593           */
594           SoundManager::get()->enable_sound(false);
595           SoundManager::get()->enable_music(false);
596           SoundManager::get()->set_audio_device_available(false);
597         }
598     }
599
600
601   /* Open sound silently regarless the value of "use_sound": */
602
603   if (SoundManager::get()->audio_device_available())
604     {
605       if (SoundManager::get()->open_audio(44100, AUDIO_S16, 2, 2048) < 0)
606         {
607           /* only print out message if sound or music
608              was not disabled at command-line
609            */
610           if (SoundManager::get()->sound_enabled() || SoundManager::get()->music_enabled())
611             {
612               fprintf(stderr,
613                       "\nWarning: I could not set up audio for 44100 Hz "
614                       "16-bit stereo.\n"
615                       "The Simple DirectMedia error that occured was:\n"
616                       "%s\n\n", SDL_GetError());
617             }
618           SoundManager::get()->enable_sound(false);
619           SoundManager::get()->enable_music(false);
620           SoundManager::get()->set_audio_device_available(false);
621         }
622     }
623
624 }
625
626
627 /* --- SHUTDOWN --- */
628
629 void Termination::shutdown(void)
630 {
631   SoundManager::get()->close_audio();
632   SDL_Quit();
633   config->save();
634 }
635
636 /* --- ABORT! --- */
637
638 void Termination::abort(const std::string& reason, const std::string& details)
639 {
640   fprintf(stderr, "\nError: %s\n%s\n\n", reason.c_str(), details.c_str());
641   shutdown();
642   ::abort();
643 }
644
645 /* Set Icon (private) */
646
647 void seticon(void)
648 {
649 //  int masklen;
650 //  Uint8 * mask;
651   SDL_Surface * icon;
652
653
654   /* Load icon into a surface: */
655
656   icon = IMG_Load((datadir + "/images/" + package_symbol_name + ".xpm").c_str());
657   if (icon == NULL)
658     {
659       fprintf(stderr,
660               "\nError: I could not load the icon image: %s%s\n"
661               "The Simple DirectMedia error that occured was:\n"
662               "%s\n\n", datadir.c_str(), ("/images/" + package_symbol_name + ".xpm").c_str(), SDL_GetError());
663       exit(1);
664     }
665
666
667   /* Create mask: */
668 /*
669   masklen = (((icon -> w) + 7) / 8) * (icon -> h);
670   mask = (Uint8*) malloc(masklen * sizeof(Uint8));
671   memset(mask, 0xFF, masklen);
672 */
673
674   /* Set icon: */
675
676   SDL_WM_SetIcon(icon, NULL);//mask);
677
678
679   /* Free icon surface & mask: */
680
681 //  free(mask);
682   SDL_FreeSurface(icon);
683 }
684
685
686 /* Parse command-line arguments: */
687
688 void Setup::parseargs(int argc, char * argv[])
689 {
690   int i;
691
692   config->load();
693
694   /* Parse arguments: */
695
696   for (i = 1; i < argc; i++)
697     {
698       if (strcmp(argv[i], "--fullscreen") == 0 ||
699           strcmp(argv[i], "-f") == 0)
700         {
701           use_fullscreen = true;
702         }
703       else if (strcmp(argv[i], "--window") == 0 ||
704                strcmp(argv[i], "-w") == 0)
705         {
706           use_fullscreen = false;
707         }
708       else if (strcmp(argv[i], "--joystick") == 0 || strcmp(argv[i], "-j") == 0)
709         {
710           assert(i+1 < argc);
711           joystick_num = atoi(argv[++i]);
712         }
713       else if (strcmp(argv[i], "--joymap") == 0)
714         {
715           assert(i+1 < argc);
716           if (sscanf(argv[++i],
717                      "%d:%d:%d:%d:%d", 
718                      &joystick_keymap.x_axis, 
719                      &joystick_keymap.y_axis, 
720                      &joystick_keymap.a_button, 
721                      &joystick_keymap.b_button, 
722                      &joystick_keymap.start_button) != 5)
723             {
724               puts("Warning: Invalid or incomplete joymap, should be: 'XAXIS:YAXIS:A:B:START'");
725             }
726           else
727             {
728               std::cout << "Using new joymap:\n"
729                         << "  X-Axis:       " << joystick_keymap.x_axis << "\n"
730                         << "  Y-Axis:       " << joystick_keymap.y_axis << "\n"
731                         << "  A-Button:     " << joystick_keymap.a_button << "\n"
732                         << "  B-Button:     " << joystick_keymap.b_button << "\n"
733                         << "  Start-Button: " << joystick_keymap.start_button << std::endl;
734             }
735         }
736       else if (strcmp(argv[i], "--leveleditor") == 0)
737         {
738           launch_leveleditor_mode = true;
739         }
740       else if (strcmp(argv[i], "--worldmap") == 0)
741         {
742           launch_worldmap_mode = true;
743         }
744       else if (strcmp(argv[i], "--datadir") == 0 
745                || strcmp(argv[i], "-d") == 0 )
746         {
747           assert(i+1 < argc);
748           datadir = argv[++i];
749         }
750       else if (strcmp(argv[i], "--show-fps") == 0)
751         {
752           /* Use full screen: */
753
754           show_fps = true;
755         }
756       else if (strcmp(argv[i], "--opengl") == 0 ||
757                strcmp(argv[i], "-gl") == 0)
758         {
759 #ifndef NOOPENGL
760           /* Use OpengGL: */
761
762           use_gl = true;
763 #endif
764         }
765       else if (strcmp(argv[i], "--sdl") == 0)
766           {
767             use_gl = false;
768           }
769       else if (strcmp(argv[i], "--usage") == 0)
770         {
771           /* Show usage: */
772
773           usage(argv[0], 0);
774         }
775       else if (strcmp(argv[i], "--version") == 0)
776         {
777           /* Show version: */
778           printf((package_name + package_version + "\n").c_str() );
779           exit(0);
780         }
781       else if (strcmp(argv[i], "--disable-sound") == 0)
782         {
783           /* Disable the compiled in sound feature */
784           printf("Sounds disabled \n");
785           SoundManager::get()->enable_sound(false); 
786         }
787       else if (strcmp(argv[i], "--disable-music") == 0)
788         {
789           /* Disable the compiled in sound feature */
790           printf("Music disabled \n");
791           SoundManager::get()->enable_music(false); 
792         }
793       else if (strcmp(argv[i], "--debug") == 0)
794         {
795           /* Enable the debug-mode */
796           debug_mode = true;
797
798         }
799       else if (strcmp(argv[i], "--help") == 0)
800         {     /* Show help: */
801           puts(_("  SuperTux  " VERSION "\n"
802                "  Please see the file \"README.txt\" for more details.\n"));
803           printf(_("Usage: %s [OPTIONS] FILENAME\n\n"), argv[0]);
804           puts(_("Display Options:\n"
805                "  -f, --fullscreen    Run in fullscreen mode.\n"
806                "  -w, --window        Run in window mode.\n"
807                "  --opengl            If OpenGL support was compiled in, this will tell\n"
808                "                      SuperTux to make use of it.\n"
809                "  --sdl               Use the SDL software graphical renderer\n"
810                "\n"
811                "Sound Options:\n"
812                "  --disable-sound     If sound support was compiled in,  this will\n"
813                "                      disable sound for this session of the game.\n"
814                "  --disable-music     Like above, but this will disable music.\n"
815                "\n"
816                "Misc Options:\n"
817                "  -j, --joystick NUM  Use joystick NUM (default: 0)\n" 
818                "  --joymap XAXIS:YAXIS:A:B:START\n"
819                "                      Define how joystick buttons and axis should be mapped\n"
820                "  --leveleditor       Opens the leveleditor in a file.\n"
821                "  --worldmap          Opens the specified worldmap file.\n"
822                "  -d, --datadir DIR   Load Game data from DIR (default: automatic)\n"
823                "  --debug             Enables the debug mode, which is useful for developers.\n"
824                "  --help              Display a help message summarizing command-line\n"
825                "                      options, license and game controls.\n"
826                "  --usage             Display a brief message summarizing command-line options.\n"
827                "  --version           Display the version of SuperTux you're running.\n\n"
828                ));
829           exit(0);
830         }
831       else if (argv[i][0] != '-')
832         {
833           level_startup_file = argv[i];
834         }
835       else
836         {
837           /* Unknown - complain! */
838
839           usage(argv[0], 1);
840         }
841     }
842 }
843
844
845 /* Display usage: */
846
847 void usage(char * prog, int ret)
848 {
849   FILE * fi;
850
851
852   /* Determine which stream to write to: */
853
854   if (ret == 0)
855     fi = stdout;
856   else
857     fi = stderr;
858
859
860   /* Display the usage message: */
861
862   fprintf(fi, _("Usage: %s [--fullscreen] [--opengl] [--disable-sound] [--disable-music] [--debug] | [--usage | --help | --version] [--leveleditor] [--worldmap] FILENAME\n"),
863           prog);
864
865
866   /* Quit! */
867
868   exit(ret);
869 }
870
871 std::vector<std::string> FileSystem::read_directory(const std::string& pathname)
872 {
873   std::vector<std::string> dirnames;
874   
875   DIR* dir = opendir(pathname.c_str());
876   if (dir)
877     {
878       struct dirent *direntp;
879       
880       while((direntp = readdir(dir)))
881         {
882           dirnames.push_back(direntp->d_name);
883         }
884       
885       closedir(dir);
886     }
887
888   return dirnames;
889 }
890
891 /* EOF */