fixed a few bugs. (One of them thanks to a patch from Ricardo). Made more code cleanu...
[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 - January 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/types.h>
27 #include <sys/stat.h>
28 #include <ctype.h>
29 #endif
30
31 #include "defines.h"
32 #include "globals.h"
33 #include "setup.h"
34 #include "screen.h"
35 #include "texture.h"
36
37 /* Local function prototypes: */
38
39 void seticon(void);
40 void usage(char * prog, int ret);
41
42 /* Does the given file exist and is it accessible? */
43 int faccessible(char *filename)
44 {
45   struct stat filestat;
46   if (stat(filename, &filestat) == -1)
47     return NO;
48   else
49     return YES;
50 }
51
52
53 /* --- SETUP --- */
54
55 void st_directory_setup(void)
56 {
57
58   /* Set SuperTux configuration and save directories */
59
60   /* Get home directory (from $HOME variable)... if we can't determine it,
61      use the current directory ("."): */
62   char *home;
63   if (getenv("HOME") != NULL)
64     home = getenv("HOME");
65   else
66     home = ".";
67
68   st_dir = (char *) malloc(sizeof(char) * (strlen(home) +
69                            strlen("/.supertux") + 1));
70   strcpy(st_dir, home);
71   strcat(st_dir, "/.supertux");
72
73   st_save_dir = (char *) malloc(sizeof(char) * (strlen(st_dir) + strlen("/save") + 1));
74
75   strcpy(st_save_dir,st_dir);
76   strcat(st_save_dir,"/save");
77
78   /* Create them. In the case they exist it won't destroy anything. */
79 #ifdef LINUX
80
81   mkdir(st_dir, 0755);
82   mkdir(st_save_dir, 0755);
83 #else
84   #ifdef WIN32
85
86   mkdir(st_dir);
87   mkdir(st_save_dir);
88 #endif
89 #endif
90 }
91
92 void st_general_setup(void)
93 {
94   /* Seed random number generator: */
95
96   srand(SDL_GetTicks());
97
98   /* Load global images: */
99
100   letters_black = load_image(DATA_PREFIX "/images/status/letters-black.png",
101                              USE_ALPHA);
102
103   letters_gold = load_image(DATA_PREFIX "/images/status/letters-gold.png",
104                             USE_ALPHA);/*
105       if (tux_x < 0)
106         tux_x = 0;*/
107
108   letters_blue = load_image(DATA_PREFIX "/images/status/letters-blue.png",
109                             USE_ALPHA);
110
111   letters_red = load_image(DATA_PREFIX "/images/status/letters-red.png",
112                            USE_ALPHA);
113
114
115   /* Set icon image: */
116
117   seticon();
118
119 }
120
121 void st_video_setup(void)
122 {
123
124 if(screen != NULL)
125    SDL_FreeSurface(screen); 
126
127   /* Init SDL Video: */
128
129   if (SDL_Init(SDL_INIT_VIDEO) < 0)
130     {
131       fprintf(stderr,
132               "\nError: I could not initialize video!\n"
133               "The Simple DirectMedia error that occured was:\n"
134               "%s\n\n", SDL_GetError());
135       exit(1);
136     }
137
138   /* Open display: */
139
140   if(use_gl)
141   st_video_setup_gl();
142   else
143   st_video_setup_sdl();
144   
145   texture_setup();
146     
147   /* Set window manager stuff: */
148
149   SDL_WM_SetCaption("Super Tux", "Super Tux");
150
151 }
152
153 void st_video_setup_sdl(void)
154 {
155   if (use_fullscreen == YES)
156     {
157       screen = SDL_SetVideoMode(640, 480, 16, SDL_FULLSCREEN ) ; /* | SDL_HWSURFACE); */
158       if (screen == NULL)
159         {
160           fprintf(stderr,
161                   "\nWarning: I could not set up fullscreen video for "
162                   "640x480 mode.\n"
163                   "The Simple DirectMedia error that occured was:\n"
164                   "%s\n\n", SDL_GetError());
165           use_fullscreen = NO;
166         }
167     }
168     else
169     {
170       screen = SDL_SetVideoMode(640, 480, 16, SDL_HWSURFACE | SDL_DOUBLEBUF );
171
172       if (screen == NULL)
173         {
174           fprintf(stderr,
175                   "\nError: I could not set up video for 640x480 mode.\n"
176                   "The Simple DirectMedia error that occured was:\n"
177                   "%s\n\n", SDL_GetError());
178           exit(1);
179         }
180     }
181 }
182
183 void st_video_setup_gl(void)
184 {
185 #ifndef NOOPENGL
186
187         SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 5);
188         SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 5);
189         SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5);
190         SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);
191         SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
192                 
193   if (use_fullscreen == YES)
194     {
195       screen = SDL_SetVideoMode(640, 480, 32, SDL_FULLSCREEN | SDL_OPENGL ) ; /* | SDL_HWSURFACE); */
196       if (screen == NULL)
197         {
198           fprintf(stderr,
199                   "\nWarning: I could not set up fullscreen video for "
200                   "640x480 mode.\n"
201                   "The Simple DirectMedia error that occured was:\n"
202                   "%s\n\n", SDL_GetError());
203           use_fullscreen = NO;
204         }
205     }
206     else
207     {
208       screen = SDL_SetVideoMode(640, 480, 32, SDL_HWSURFACE | SDL_OPENGL | SDL_OPENGLBLIT  );
209
210       if (screen == NULL)
211         {
212           fprintf(stderr,
213                   "\nError: I could not set up video for 640x480 mode.\n"
214                   "The Simple DirectMedia error that occured was:\n"
215                   "%s\n\n", SDL_GetError());
216           exit(1);
217         }
218     }
219     
220     /* Initialisierung von OpenGL * /
221         glViewport(0, 0, screen->w, screen->h);
222
223         glMatrixMode(GL_PROJECTION);
224         glLoadIdentity();
225         glOrtho(0, screen->w, screen->h, 0, -1.0, 1.0);
226
227         glMatrixMode(GL_MODELVIEW);
228         glLoadIdentity();
229 */
230         /*
231          * Set up OpenGL for 2D rendering.
232          */
233         glDisable(GL_DEPTH_TEST);
234         glDisable(GL_CULL_FACE);
235
236         glViewport(0, 0, screen->w, screen->h);
237         glMatrixMode(GL_PROJECTION);
238         glLoadIdentity();
239         glOrtho(0, screen->w, screen->h, 0, -1.0, 1.0);
240
241         glMatrixMode(GL_MODELVIEW);
242         glLoadIdentity();
243         glTranslatef(0.0f, 0.0f, 0.0f);
244
245 #endif
246 }
247
248 void st_joystick_setup(void)
249 {
250
251   /* Init Joystick: */
252
253 #ifdef JOY_YES
254   use_joystick = YES;
255
256   if (SDL_Init(SDL_INIT_JOYSTICK) < 0)
257     {
258       fprintf(stderr, "Warning: I could not initialize joystick!\n"
259               "The Simple DirectMedia error that occured was:\n"
260               "%s\n\n", SDL_GetError());
261
262       use_joystick = NO;
263     }
264   else
265     {
266       /* Open joystick: */
267
268       if (SDL_NumJoysticks() <= 0)
269         {
270           fprintf(stderr, "Warning: No joysticks are available.\n");
271
272           use_joystick = NO;
273         }
274       else
275         {
276           js = SDL_JoystickOpen(0);
277
278           if (js == NULL)
279             {
280               fprintf(stderr, "Warning: Could not open joystick 1.\n"
281                       "The Simple DirectMedia error that occured was:\n"
282                       "%s\n\n", SDL_GetError());
283
284               use_joystick = NO;
285             }
286           else
287             {
288               /* Check for proper joystick configuration: */
289
290               if (SDL_JoystickNumAxes(js) < 2)
291                 {
292                   fprintf(stderr,
293                           "Warning: Joystick does not have enough axes!\n");
294
295                   use_joystick = NO;
296                 }
297               else
298                 {
299                   if (SDL_JoystickNumButtons(js) < 2)
300                     {
301                       fprintf(stderr,
302                               "Warning: "
303                               "Joystick does not have enough buttons!\n");
304
305                       use_joystick = NO;
306                     }
307                 }
308             }
309         }
310     }
311 #endif
312
313 }
314
315 void st_audio_setup(void)
316 {
317
318   /* Init SDL Audio silently even if --disable-sound : */
319
320   if (audio_device == YES)
321     {
322       if (SDL_Init(SDL_INIT_AUDIO) < 0)
323         {
324           /* only print out message if sound or music
325              was not disabled at command-line
326            */
327           if (use_sound == YES || use_music == YES)
328             {
329               fprintf(stderr,
330                       "\nWarning: I could not initialize audio!\n"
331                       "The Simple DirectMedia error that occured was:\n"
332                       "%s\n\n", SDL_GetError());
333             }
334           /* keep the programming logic the same :-)
335              because in this case, use_sound & use_music' values are ignored
336              when there's no available audio device
337           */
338           use_sound = NO;
339           use_music = NO;
340           audio_device = NO;
341         }
342     }
343
344
345   /* Open sound silently regarless the value of "use_sound": */
346
347   if (audio_device == YES)
348     {
349       if (open_audio(44100, AUDIO_S16, 2, 512) < 0)
350         {
351           /* only print out message if sound or music
352              was not disabled at command-line
353            */
354           if ((use_sound == YES) || (use_music == YES))
355             {
356               fprintf(stderr,
357                       "\nWarning: I could not set up audio for 44100 Hz "
358                       "16-bit stereo.\n"
359                       "The Simple DirectMedia error that occured was:\n"
360                       "%s\n\n", SDL_GetError());
361             }
362           use_sound = NO;
363           use_music = NO;
364           audio_device = NO;
365         }
366     }
367
368 }
369
370
371 /* --- SHUTDOWN --- */
372
373 void st_shutdown(void)
374 {
375   close_audio();
376   SDL_Quit();
377 }
378
379
380 /* --- ABORT! --- */
381
382 void st_abort(char * reason, char * details)
383 {
384   fprintf(stderr, "\nError: %s\n%s\n\n", reason, details);
385   st_shutdown();
386   exit(1);
387 }
388
389
390 /* Set Icon (private) */
391
392 void seticon(void)
393 {
394   int masklen;
395   Uint8 * mask;
396   SDL_Surface * icon;
397
398
399   /* Load icon into a surface: */
400
401   icon = IMG_Load(DATA_PREFIX "/images/icon.png");
402   if (icon == NULL)
403     {
404       fprintf(stderr,
405               "\nError: I could not load the icon image: %s\n"
406               "The Simple DirectMedia error that occured was:\n"
407               "%s\n\n", DATA_PREFIX "images/icon.png", SDL_GetError());
408       exit(1);
409     }
410
411
412   /* Create mask: */
413
414   masklen = (((icon -> w) + 7) / 8) * (icon -> h);
415   mask = malloc(masklen * sizeof(Uint8));
416   memset(mask, 0xFF, masklen);
417
418
419   /* Set icon: */
420
421   SDL_WM_SetIcon(icon, mask);
422
423
424   /* Free icon surface & mask: */
425
426   free(mask);
427   SDL_FreeSurface(icon);
428 }
429
430
431 /* Parse command-line arguments: */
432
433 void parseargs(int argc, char * argv[])
434 {
435   int i;
436
437   /* Set defaults: */
438
439
440   debug_mode = NO;
441   use_fullscreen = NO;
442   show_fps = NO;
443   use_gl = NO;    
444
445 #ifndef NOSOUND
446
447   use_sound = YES;
448   use_music = YES;
449   audio_device = YES;
450 #else
451
452   use_sound = NO;
453   use_music = NO;
454   audio_device = NO;
455 #endif
456
457   /* Parse arguments: */
458
459   for (i = 1; i < argc; i++)
460     {
461       if (strcmp(argv[i], "--fullscreen") == 0 ||
462           strcmp(argv[i], "-f") == 0)
463         {
464           /* Use full screen: */
465
466           use_fullscreen = YES;
467         }
468       else if (strcmp(argv[i], "--show-fps") == 0)
469         {
470           /* Use full screen: */
471
472           show_fps = YES;
473         }
474       else if (strcmp(argv[i], "--opengl") == 0 ||
475           strcmp(argv[i], "-gl") == 0)
476         {
477         #ifndef NOOPENGL
478           /* Use OpengGL: */
479
480           use_gl = YES;
481         #endif
482         }
483       else if (strcmp(argv[i], "--usage") == 0)
484         {
485           /* Show usage: */
486
487           usage(argv[0], 0);
488         }
489       else if (strcmp(argv[i], "--version") == 0)
490         {
491           /* Show version: */
492
493           printf("Super Tux - version " VERSION "\n");
494           exit(0);
495         }
496       else if (strcmp(argv[i], "--disable-sound") == 0)
497         {
498           /* Disable the compiled in sound feature */
499 #ifndef NOSOUND
500           printf("Sounds disabled \n");
501           use_sound = NO;
502 #else
503
504           printf("Warning: Sounds feature is not compiled in \n");
505 #endif
506
507         }
508       else if (strcmp(argv[i], "--disable-music") == 0)
509         {
510           /* Disable the compiled in sound feature */
511 #ifndef NOSOUND
512           printf("Music disabled \n");
513           use_music = NO;
514 #else
515
516           printf("Warning: Music feature is not compiled in \n");
517 #endif
518
519         }
520       else if (strcmp(argv[i], "--debug-mode") == 0)
521         {
522           /* Enable the debug-mode */
523           debug_mode = YES;
524
525         }
526       else if (strcmp(argv[i], "--help") == 0)
527         {         /* Show help: */
528
529           printf("Super Tux " VERSION "\n\n");
530
531           printf("----------  Command-line options  ----------\n\n");
532
533           printf("  --opengl            - If opengl support was compiled in, this will enable the EXPERIMENTAL OpenGL mode.\n\n");
534           
535           printf("  --disable-sound     - If sound support was compiled in,  this will\n                        disable sound for this session of the game.\n\n");
536
537           printf("  --disable-music     - Like above, but this will disable music.\n\n");
538
539           printf("  --fullscreen        - Run in fullscreen mode.\n\n");
540
541           printf("  --debug-mode        - Enables the debug-mode, which is useful for developers.\n\n");
542
543           printf("  --help              - Display a help message summarizing command-line\n                        options, license and game controls.\n\n");
544
545           printf("  --usage             - Display a brief message summarizing command-line options.\n\n");
546
547           printf("  --version           - Display the version of SuperTux you're running.\n\n\n");
548
549
550           printf("----------          License       ----------\n\n");
551           printf("  This program comes with ABSOLUTELY NO WARRANTY.\n");
552           printf("  This is free software, and you are welcome to redistribute\n");
553           printf("  or modify it under certain conditions. See the file \n");
554           printf("  \"COPYING.txt\" for more details.\n\n\n");
555
556           printf("----------      Game controls     ----------\n\n");
557           printf("  Please see the file \"README.txt\"\n\n");
558
559           exit(0);
560         }
561       else
562         {
563           /* Unknown - complain! */
564
565           usage(argv[0], 1);
566         }
567     }
568 }
569
570
571 /* Display usage: */
572
573 void usage(char * prog, int ret)
574 {
575   FILE * fi;
576
577
578   /* Determine which stream to write to: */
579
580   if (ret == 0)
581     fi = stdout;
582   else
583     fi = stderr;
584
585
586   /* Display the usage message: */
587
588   fprintf(fi, "Usage: %s [--fullscreen] [--opengl] [--disable-sound] [--disable-music] [--debug-mode] | [--usage | --help | --version]\n",
589           prog);
590
591
592   /* Quit! */
593
594   exit(ret);
595 }
596