Made the SuperTux library again a bit more selfstanding.
[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 GUI/menu images: */
350   checkbox = new Surface(datadir + "/images/status/checkbox.png", true);
351   checkbox_checked = new Surface(datadir + "/images/status/checkbox-checked.png", true);
352   back = new Surface(datadir + "/images/status/back.png", true);
353   arrow_left = new Surface(datadir + "/images/icons/left.png", true);
354   arrow_right = new Surface(datadir + "/images/icons/right.png", true);
355
356   /* Load the mouse-cursor */
357   mouse_cursor = new MouseCursor( datadir + "/images/status/mousecursor.png",1);
358   MouseCursor::set_current(mouse_cursor);
359   
360 }
361
362 void Setup::general_free(void)
363 {
364
365   /* Free GUI/menu images: */
366   delete checkbox;
367   delete checkbox_checked;
368   delete back;
369   delete arrow_left;
370   delete arrow_right;
371
372   /* Free mouse-cursor */
373   delete mouse_cursor;
374   
375 }
376
377 void Setup::video(unsigned int screen_w, unsigned int screen_h)
378 {
379   /* Init SDL Video: */
380   if (SDL_Init(SDL_INIT_VIDEO) < 0)
381     {
382       fprintf(stderr,
383               "\nError: I could not initialize video!\n"
384               "The Simple DirectMedia error that occured was:\n"
385               "%s\n\n", SDL_GetError());
386       exit(1);
387     }
388
389   /* Open display: */
390   if(use_gl)
391     video_gl(screen_w, screen_h);
392   else
393     video_sdl(screen_w, screen_h);
394
395   Surface::reload_all();
396
397   /* Set window manager stuff: */
398   SDL_WM_SetCaption((package_name + " " + package_version).c_str(), package_name.c_str());
399 }
400
401 void Setup::video_sdl(unsigned int screen_w, unsigned int screen_h)
402 {
403   if (use_fullscreen)
404     {
405       screen = SDL_SetVideoMode(screen_w, screen_h, 0, SDL_FULLSCREEN ) ; /* | SDL_HWSURFACE); */
406       if (screen == NULL)
407         {
408           fprintf(stderr,
409                   "\nWarning: I could not set up fullscreen video for "
410                   "800x600 mode.\n"
411                   "The Simple DirectMedia error that occured was:\n"
412                   "%s\n\n", SDL_GetError());
413           use_fullscreen = false;
414         }
415     }
416   else
417     {
418       screen = SDL_SetVideoMode(screen_w, screen_h, 0, SDL_HWSURFACE | SDL_DOUBLEBUF );
419
420       if (screen == NULL)
421         {
422           fprintf(stderr,
423                   "\nError: I could not set up video for 800x600 mode.\n"
424                   "The Simple DirectMedia error that occured was:\n"
425                   "%s\n\n", SDL_GetError());
426           exit(1);
427         }
428     }
429 }
430
431 void Setup::video_gl(unsigned int screen_w, unsigned int screen_h)
432 {
433 #ifndef NOOPENGL
434
435   SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 5);
436   SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 5);
437   SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5);
438   SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);
439   SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
440
441   if (use_fullscreen)
442     {
443       screen = SDL_SetVideoMode(screen_w, screen_h, 0, SDL_FULLSCREEN | SDL_OPENGL) ; /* | SDL_HWSURFACE); */
444       if (screen == NULL)
445         {
446           fprintf(stderr,
447                   "\nWarning: I could not set up fullscreen video for "
448                   "640x480 mode.\n"
449                   "The Simple DirectMedia error that occured was:\n"
450                   "%s\n\n", SDL_GetError());
451           use_fullscreen = false;
452         }
453     }
454   else
455     {
456       screen = SDL_SetVideoMode(screen_w, screen_h, 0, SDL_OPENGL);
457
458       if (screen == NULL)
459         {
460           fprintf(stderr,
461                   "\nError: I could not set up video for 640x480 mode.\n"
462                   "The Simple DirectMedia error that occured was:\n"
463                   "%s\n\n", SDL_GetError());
464           exit(1);
465         }
466     }
467
468   /*
469    * Set up OpenGL for 2D rendering.
470    */
471   glDisable(GL_DEPTH_TEST);
472   glDisable(GL_CULL_FACE);
473
474   glViewport(0, 0, screen->w, screen->h);
475   glMatrixMode(GL_PROJECTION);
476   glLoadIdentity();
477   glOrtho(0, screen->w, screen->h, 0, -1.0, 1.0);
478
479   glMatrixMode(GL_MODELVIEW);
480   glLoadIdentity();
481   glTranslatef(0.0f, 0.0f, 0.0f);
482
483 #endif
484
485 }
486
487 void Setup::joystick(void)
488 {
489
490   /* Init Joystick: */
491
492   use_joystick = true;
493
494   if (SDL_Init(SDL_INIT_JOYSTICK) < 0)
495     {
496       fprintf(stderr, "Warning: I could not initialize joystick!\n"
497               "The Simple DirectMedia error that occured was:\n"
498               "%s\n\n", SDL_GetError());
499
500       use_joystick = false;
501     }
502   else
503     {
504       /* Open joystick: */
505       if (SDL_NumJoysticks() <= 0)
506         {
507           fprintf(stderr, "Info: No joysticks were found.\n");
508
509           use_joystick = false;
510         }
511       else
512         {
513           js = SDL_JoystickOpen(joystick_num);
514
515           if (js == NULL)
516             {
517               fprintf(stderr, "Warning: Could not open joystick %d.\n"
518                       "The Simple DirectMedia error that occured was:\n"
519                       "%s\n\n", joystick_num, SDL_GetError());
520
521               use_joystick = false;
522             }
523           else
524             {
525               if (SDL_JoystickNumAxes(js) < 2)
526                 {
527                   fprintf(stderr,
528                           "Warning: Joystick does not have enough axes!\n");
529
530                   use_joystick = false;
531                 }
532               else
533                 {
534                   if (SDL_JoystickNumButtons(js) < 2)
535                     {
536                       fprintf(stderr,
537                               "Warning: "
538                               "Joystick does not have enough buttons!\n");
539
540                       use_joystick = false;
541                     }
542                 }
543             }
544         }
545     }
546 }
547
548 void Setup::audio(void)
549 {
550
551   /* Init SDL Audio silently even if --disable-sound : */
552
553   if (SoundManager::get()->audio_device_available())
554     {
555       if (SDL_Init(SDL_INIT_AUDIO) < 0)
556         {
557           /* only print out message if sound or music
558              was not disabled at command-line
559            */
560           if (SoundManager::get()->sound_enabled() || SoundManager::get()->music_enabled())
561             {
562               fprintf(stderr,
563                       "\nWarning: I could not initialize audio!\n"
564                       "The Simple DirectMedia error that occured was:\n"
565                       "%s\n\n", SDL_GetError());
566             }
567           /* keep the programming logic the same :-)
568              because in this case, use_sound & use_music' values are ignored
569              when there's no available audio device
570           */
571           SoundManager::get()->enable_sound(false);
572           SoundManager::get()->enable_music(false);
573           SoundManager::get()->set_audio_device_available(false);
574         }
575     }
576
577
578   /* Open sound silently regarless the value of "use_sound": */
579
580   if (SoundManager::get()->audio_device_available())
581     {
582       if (SoundManager::get()->open_audio(44100, AUDIO_S16, 2, 2048) < 0)
583         {
584           /* only print out message if sound or music
585              was not disabled at command-line
586            */
587           if (SoundManager::get()->sound_enabled() || SoundManager::get()->music_enabled())
588             {
589               fprintf(stderr,
590                       "\nWarning: I could not set up audio for 44100 Hz "
591                       "16-bit stereo.\n"
592                       "The Simple DirectMedia error that occured was:\n"
593                       "%s\n\n", SDL_GetError());
594             }
595           SoundManager::get()->enable_sound(false);
596           SoundManager::get()->enable_music(false);
597           SoundManager::get()->set_audio_device_available(false);
598         }
599     }
600
601 }
602
603
604 /* --- SHUTDOWN --- */
605
606 void Termination::shutdown(void)
607 {
608   SoundManager::get()->close_audio();
609   SDL_Quit();
610   config->save();
611 }
612
613 /* --- ABORT! --- */
614
615 void Termination::abort(const std::string& reason, const std::string& details)
616 {
617   fprintf(stderr, "\nError: %s\n%s\n\n", reason.c_str(), details.c_str());
618   shutdown();
619   ::abort();
620 }
621
622 /* Set Icon (private) */
623
624 void seticon(void)
625 {
626 //  int masklen;
627 //  Uint8 * mask;
628   SDL_Surface * icon;
629
630
631   /* Load icon into a surface: */
632
633   icon = IMG_Load((datadir + "/images/" + package_symbol_name + ".xpm").c_str());
634   if (icon == NULL)
635     {
636       fprintf(stderr,
637               "\nError: I could not load the icon image: %s%s\n"
638               "The Simple DirectMedia error that occured was:\n"
639               "%s\n\n", datadir.c_str(), ("/images/" + package_symbol_name + ".xpm").c_str(), SDL_GetError());
640       exit(1);
641     }
642
643
644   /* Create mask: */
645 /*
646   masklen = (((icon -> w) + 7) / 8) * (icon -> h);
647   mask = (Uint8*) malloc(masklen * sizeof(Uint8));
648   memset(mask, 0xFF, masklen);
649 */
650
651   /* Set icon: */
652
653   SDL_WM_SetIcon(icon, NULL);//mask);
654
655
656   /* Free icon surface & mask: */
657
658 //  free(mask);
659   SDL_FreeSurface(icon);
660 }
661
662
663 /* Parse command-line arguments: */
664
665 void Setup::parseargs(int argc, char * argv[])
666 {
667   int i;
668
669   config->load();
670
671   /* Parse arguments: */
672
673   for (i = 1; i < argc; i++)
674     {
675       if (strcmp(argv[i], "--fullscreen") == 0 ||
676           strcmp(argv[i], "-f") == 0)
677         {
678           use_fullscreen = true;
679         }
680       else if (strcmp(argv[i], "--window") == 0 ||
681                strcmp(argv[i], "-w") == 0)
682         {
683           use_fullscreen = false;
684         }
685       else if (strcmp(argv[i], "--joystick") == 0 || strcmp(argv[i], "-j") == 0)
686         {
687           assert(i+1 < argc);
688           joystick_num = atoi(argv[++i]);
689         }
690       else if (strcmp(argv[i], "--joymap") == 0)
691         {
692           assert(i+1 < argc);
693           if (sscanf(argv[++i],
694                      "%d:%d:%d:%d:%d", 
695                      &joystick_keymap.x_axis, 
696                      &joystick_keymap.y_axis, 
697                      &joystick_keymap.a_button, 
698                      &joystick_keymap.b_button, 
699                      &joystick_keymap.start_button) != 5)
700             {
701               puts("Warning: Invalid or incomplete joymap, should be: 'XAXIS:YAXIS:A:B:START'");
702             }
703           else
704             {
705               std::cout << "Using new joymap:\n"
706                         << "  X-Axis:       " << joystick_keymap.x_axis << "\n"
707                         << "  Y-Axis:       " << joystick_keymap.y_axis << "\n"
708                         << "  A-Button:     " << joystick_keymap.a_button << "\n"
709                         << "  B-Button:     " << joystick_keymap.b_button << "\n"
710                         << "  Start-Button: " << joystick_keymap.start_button << std::endl;
711             }
712         }
713       else if (strcmp(argv[i], "--leveleditor") == 0)
714         {
715           launch_leveleditor_mode = true;
716         }
717       else if (strcmp(argv[i], "--worldmap") == 0)
718         {
719           launch_worldmap_mode = true;
720         }
721       else if (strcmp(argv[i], "--datadir") == 0 
722                || strcmp(argv[i], "-d") == 0 )
723         {
724           assert(i+1 < argc);
725           datadir = argv[++i];
726         }
727       else if (strcmp(argv[i], "--show-fps") == 0)
728         {
729           /* Use full screen: */
730
731           show_fps = true;
732         }
733       else if (strcmp(argv[i], "--opengl") == 0 ||
734                strcmp(argv[i], "-gl") == 0)
735         {
736 #ifndef NOOPENGL
737           /* Use OpengGL: */
738
739           use_gl = true;
740 #endif
741         }
742       else if (strcmp(argv[i], "--sdl") == 0)
743           {
744             use_gl = false;
745           }
746       else if (strcmp(argv[i], "--usage") == 0)
747         {
748           /* Show usage: */
749
750           usage(argv[0], 0);
751         }
752       else if (strcmp(argv[i], "--version") == 0)
753         {
754           /* Show version: */
755           printf((package_name + package_version + "\n").c_str() );
756           exit(0);
757         }
758       else if (strcmp(argv[i], "--disable-sound") == 0)
759         {
760           /* Disable the compiled in sound feature */
761           printf("Sounds disabled \n");
762           SoundManager::get()->enable_sound(false); 
763         }
764       else if (strcmp(argv[i], "--disable-music") == 0)
765         {
766           /* Disable the compiled in sound feature */
767           printf("Music disabled \n");
768           SoundManager::get()->enable_music(false); 
769         }
770       else if (strcmp(argv[i], "--debug") == 0)
771         {
772           /* Enable the debug-mode */
773           debug_mode = true;
774
775         }
776       else if (strcmp(argv[i], "--help") == 0)
777         {     /* Show help: */
778           puts(_("  SuperTux  " VERSION "\n"
779                "  Please see the file \"README.txt\" for more details.\n"));
780           printf(_("Usage: %s [OPTIONS] FILENAME\n\n"), argv[0]);
781           puts(_("Display Options:\n"
782                "  -f, --fullscreen    Run in fullscreen mode.\n"
783                "  -w, --window        Run in window mode.\n"
784                "  --opengl            If OpenGL support was compiled in, this will tell\n"
785                "                      SuperTux to make use of it.\n"
786                "  --sdl               Use the SDL software graphical renderer\n"
787                "\n"
788                "Sound Options:\n"
789                "  --disable-sound     If sound support was compiled in,  this will\n"
790                "                      disable sound for this session of the game.\n"
791                "  --disable-music     Like above, but this will disable music.\n"
792                "\n"
793                "Misc Options:\n"
794                "  -j, --joystick NUM  Use joystick NUM (default: 0)\n" 
795                "  --joymap XAXIS:YAXIS:A:B:START\n"
796                "                      Define how joystick buttons and axis should be mapped\n"
797                "  --leveleditor       Opens the leveleditor in a file.\n"
798                "  --worldmap          Opens the specified worldmap file.\n"
799                "  -d, --datadir DIR   Load Game data from DIR (default: automatic)\n"
800                "  --debug             Enables the debug mode, which is useful for developers.\n"
801                "  --help              Display a help message summarizing command-line\n"
802                "                      options, license and game controls.\n"
803                "  --usage             Display a brief message summarizing command-line options.\n"
804                "  --version           Display the version of SuperTux you're running.\n\n"
805                ));
806           exit(0);
807         }
808       else if (argv[i][0] != '-')
809         {
810           level_startup_file = argv[i];
811         }
812       else
813         {
814           /* Unknown - complain! */
815
816           usage(argv[0], 1);
817         }
818     }
819 }
820
821
822 /* Display usage: */
823
824 void usage(char * prog, int ret)
825 {
826   FILE * fi;
827
828
829   /* Determine which stream to write to: */
830
831   if (ret == 0)
832     fi = stdout;
833   else
834     fi = stderr;
835
836
837   /* Display the usage message: */
838
839   fprintf(fi, _("Usage: %s [--fullscreen] [--opengl] [--disable-sound] [--disable-music] [--debug] | [--usage | --help | --version] [--leveleditor] [--worldmap] FILENAME\n"),
840           prog);
841
842
843   /* Quit! */
844
845   exit(ret);
846 }
847
848 std::vector<std::string> FileSystem::read_directory(const std::string& pathname)
849 {
850   std::vector<std::string> dirnames;
851   
852   DIR* dir = opendir(pathname.c_str());
853   if (dir)
854     {
855       struct dirent *direntp;
856       
857       while((direntp = readdir(dir)))
858         {
859           dirnames.push_back(direntp->d_name);
860         }
861       
862       closedir(dir);
863     }
864
865   return dirnames;
866 }
867
868 /* EOF */