change mode names
[neverball] / share / config.c
1 /*
2  * Copyright (C) 2003 Robert Kooima
3  *
4  * NEVERBALL is  free software; you can redistribute  it and/or modify
5  * it under the  terms of the GNU General  Public License as published
6  * by the Free  Software Foundation; either version 2  of the License,
7  * or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT  ANY  WARRANTY;  without   even  the  implied  warranty  of
11  * MERCHANTABILITY or  FITNESS FOR A PARTICULAR PURPOSE.   See the GNU
12  * General Public License for more details.
13  */
14
15 #include <SDL.h>
16 #include <SDL_mixer.h>
17 #include <stdlib.h>
18 #include <string.h>
19 #include <stdio.h>
20 #include <errno.h>
21 #include <math.h>
22
23 #include "config.h"
24 #include "glext.h"
25 #include "vec3.h"
26
27 /*---------------------------------------------------------------------------*/
28
29 /* Define the mkdir symbol. */
30
31 #ifdef _WIN32
32 #include <direct.h>
33 #else
34 #include <sys/stat.h>
35 #endif
36
37 /*---------------------------------------------------------------------------*/
38
39 static int   option_d[CONFIG_OPTION_D_COUNT];
40 static char *option_s[CONFIG_OPTION_S_COUNT];
41
42 static int dirty = 0;
43
44 /*---------------------------------------------------------------------------*/
45
46 static void config_key(const char *s, int i, int d)
47 {
48     int c;
49
50     config_set_d(i, d);
51
52     for (c = 0; c < SDLK_LAST; c++)
53         if (strcmp(s, SDL_GetKeyName(c)) == 0)
54         {
55             config_set_d(i, c);
56             break;
57         }
58 }
59
60 /*---------------------------------------------------------------------------*/
61
62 void config_init(void)
63 {
64     memset(option_d, 0, CONFIG_OPTION_D_COUNT * sizeof (int));
65     memset(option_s, 0, CONFIG_OPTION_S_COUNT * sizeof (char *));
66
67     config_set_d(CONFIG_FULLSCREEN,           DEFAULT_FULLSCREEN);
68     config_set_d(CONFIG_WIDTH,                DEFAULT_WIDTH);
69     config_set_d(CONFIG_HEIGHT,               DEFAULT_HEIGHT);
70     config_set_d(CONFIG_STEREO,               DEFAULT_STEREO);
71     config_set_d(CONFIG_CAMERA,               DEFAULT_CAMERA);
72     config_set_d(CONFIG_TEXTURES,             DEFAULT_TEXTURES);
73     config_set_d(CONFIG_GEOMETRY,             DEFAULT_GEOMETRY);
74     config_set_d(CONFIG_REFLECTION,           DEFAULT_REFLECTION);
75     config_set_d(CONFIG_BACKGROUND,           DEFAULT_BACKGROUND);
76     config_set_d(CONFIG_SHADOW,               DEFAULT_SHADOW);
77     config_set_d(CONFIG_AUDIO_RATE,           DEFAULT_AUDIO_RATE);
78     config_set_d(CONFIG_AUDIO_BUFF,           DEFAULT_AUDIO_BUFF);
79     config_set_d(CONFIG_MOUSE_SENSE,          DEFAULT_MOUSE_SENSE);
80     config_set_d(CONFIG_MOUSE_INVERT,         DEFAULT_MOUSE_INVERT);
81     config_set_d(CONFIG_NICE,                 DEFAULT_NICE);
82     config_set_d(CONFIG_FPS,                  DEFAULT_FPS);
83     config_set_d(CONFIG_SOUND_VOLUME,         DEFAULT_SOUND_VOLUME);
84     config_set_d(CONFIG_MUSIC_VOLUME,         DEFAULT_MUSIC_VOLUME);
85     config_set_d(CONFIG_JOYSTICK,             DEFAULT_JOYSTICK);
86     config_set_d(CONFIG_JOYSTICK_DEVICE,      DEFAULT_JOYSTICK_DEVICE);
87     config_set_d(CONFIG_JOYSTICK_AXIS_X,      DEFAULT_JOYSTICK_AXIS_X);
88     config_set_d(CONFIG_JOYSTICK_AXIS_Y,      DEFAULT_JOYSTICK_AXIS_Y);
89     config_set_d(CONFIG_JOYSTICK_BUTTON_A,    DEFAULT_JOYSTICK_BUTTON_A);
90     config_set_d(CONFIG_JOYSTICK_BUTTON_B,    DEFAULT_JOYSTICK_BUTTON_B);
91     config_set_d(CONFIG_JOYSTICK_BUTTON_L,    DEFAULT_JOYSTICK_BUTTON_L);
92     config_set_d(CONFIG_JOYSTICK_BUTTON_R,    DEFAULT_JOYSTICK_BUTTON_R);
93     config_set_d(CONFIG_JOYSTICK_BUTTON_EXIT, DEFAULT_JOYSTICK_BUTTON_EXIT);
94     config_set_d(CONFIG_JOYSTICK_CAMERA_1,    DEFAULT_JOYSTICK_CAMERA_1);
95     config_set_d(CONFIG_JOYSTICK_CAMERA_2,    DEFAULT_JOYSTICK_CAMERA_2);
96     config_set_d(CONFIG_JOYSTICK_CAMERA_3,    DEFAULT_JOYSTICK_CAMERA_3);
97     config_set_d(CONFIG_KEY_CAMERA_1,         DEFAULT_KEY_CAMERA_1);
98     config_set_d(CONFIG_KEY_CAMERA_2,         DEFAULT_KEY_CAMERA_2);
99     config_set_d(CONFIG_KEY_CAMERA_3,         DEFAULT_KEY_CAMERA_3);
100     config_set_d(CONFIG_KEY_CAMERA_R,         DEFAULT_KEY_CAMERA_R);
101     config_set_d(CONFIG_KEY_CAMERA_L,         DEFAULT_KEY_CAMERA_L);
102     config_set_d(CONFIG_VIEW_FOV,             DEFAULT_VIEW_FOV);
103     config_set_d(CONFIG_VIEW_DP,              DEFAULT_VIEW_DP);
104     config_set_d(CONFIG_VIEW_DC,              DEFAULT_VIEW_DC);
105     config_set_d(CONFIG_VIEW_DZ,              DEFAULT_VIEW_DZ);
106     config_set_d(CONFIG_ROTATE_FAST,          DEFAULT_ROTATE_FAST);
107     config_set_d(CONFIG_ROTATE_SLOW,          DEFAULT_ROTATE_SLOW);
108     config_set_d(CONFIG_LAST_SET,             DEFAULT_LAST_SET);
109     config_set_d(CONFIG_MODE,                 DEFAULT_MODE);
110     config_set_s(CONFIG_PLAYER,               DEFAULT_PLAYER);
111     config_set_s(CONFIG_BALL,                 DEFAULT_BALL);
112     config_set_s(CONFIG_COIN,                 DEFAULT_COIN);
113     config_set_s(CONFIG_LANG,                 DEFAULT_LANG);
114 }
115
116 void config_load(void)
117 {
118     FILE *fp;
119
120     if ((fp = fopen(config_user(USER_CONFIG_FILE), "r")))
121     {
122         char buf[MAXSTR];
123         char key[MAXSTR];
124         char val[MAXSTR];
125
126         while (fgets(buf, MAXSTR, fp))
127             if (sscanf(buf, "%s %s", key, val) == 2)
128             {
129                 if      (strcmp(key, "fullscreen")            == 0)
130                     config_set_d(CONFIG_FULLSCREEN,           atoi(val));
131                 else if (strcmp(key, "width")                 == 0)
132                     config_set_d(CONFIG_WIDTH,                atoi(val));
133                 else if (strcmp(key, "height")                == 0)
134                     config_set_d(CONFIG_HEIGHT,               atoi(val));
135                 else if (strcmp(key, "stereo")                == 0)
136                     config_set_d(CONFIG_STEREO,               atoi(val));
137                 else if (strcmp(key, "camera")                == 0)
138                     config_set_d(CONFIG_CAMERA,               atoi(val));
139                 else if (strcmp(key, "textures")              == 0)
140                     config_set_d(CONFIG_TEXTURES,             atoi(val));
141                 else if (strcmp(key, "geometry")              == 0)
142                     config_set_d(CONFIG_GEOMETRY,             atoi(val));
143                 else if (strcmp(key, "reflection")            == 0)
144                     config_set_d(CONFIG_REFLECTION,           atoi(val));
145                 else if (strcmp(key, "background")            == 0)
146                     config_set_d(CONFIG_BACKGROUND,           atoi(val));
147                 else if (strcmp(key, "shadow")                == 0)
148                     config_set_d(CONFIG_SHADOW,               atoi(val));
149                 else if (strcmp(key, "audio_rate")            == 0)
150                     config_set_d(CONFIG_AUDIO_RATE,           atoi(val));
151                 else if (strcmp(key, "audio_buff")            == 0)
152                     config_set_d(CONFIG_AUDIO_BUFF,           atoi(val));
153                 else if (strcmp(key, "mouse_sense")           == 0)
154                     config_set_d(CONFIG_MOUSE_SENSE,          atoi(val));
155                 else if (strcmp(key, "mouse_invert")          == 0)
156                     config_set_d(CONFIG_MOUSE_INVERT,         atoi(val));
157                 else if (strcmp(key, "nice")                  == 0)
158                     config_set_d(CONFIG_NICE,                 atoi(val));
159                 else if (strcmp(key, "fps")                   == 0)
160                     config_set_d(CONFIG_FPS,                  atoi(val));
161                 else if (strcmp(key, "sound_volume")          == 0)
162                     config_set_d(CONFIG_SOUND_VOLUME,         atoi(val));
163                 else if (strcmp(key, "music_volume")          == 0)
164                     config_set_d(CONFIG_MUSIC_VOLUME,         atoi(val));
165                 else if (strcmp(key, "joystick")              == 0)
166                     config_set_d(CONFIG_JOYSTICK,             atoi(val));
167                 else if (strcmp(key, "joystick_device")       == 0)
168                     config_set_d(CONFIG_JOYSTICK_DEVICE,      atoi(val));
169                 else if (strcmp(key, "joystick_axis_x")       == 0)
170                     config_set_d(CONFIG_JOYSTICK_AXIS_X,      atoi(val));
171                 else if (strcmp(key, "joystick_axis_y")       == 0)
172                     config_set_d(CONFIG_JOYSTICK_AXIS_Y,      atoi(val));
173                 else if (strcmp(key, "joystick_button_a")     == 0)
174                     config_set_d(CONFIG_JOYSTICK_BUTTON_A,    atoi(val));
175                 else if (strcmp(key, "joystick_button_b")     == 0)
176                     config_set_d(CONFIG_JOYSTICK_BUTTON_B,    atoi(val));
177                 else if (strcmp(key, "joystick_button_r")     == 0)
178                     config_set_d(CONFIG_JOYSTICK_BUTTON_R,    atoi(val));
179                 else if (strcmp(key, "joystick_button_l")     == 0)
180                     config_set_d(CONFIG_JOYSTICK_BUTTON_L,    atoi(val));
181                 else if (strcmp(key, "joystick_button_exit")  == 0)
182                     config_set_d(CONFIG_JOYSTICK_BUTTON_EXIT, atoi(val));
183                 else if (strcmp(key, "joystick_camera_1")     == 0)
184                     config_set_d(CONFIG_JOYSTICK_CAMERA_1,    atoi(val));
185                 else if (strcmp(key, "joystick_camera_2")     == 0)
186                     config_set_d(CONFIG_JOYSTICK_CAMERA_2,    atoi(val));
187                 else if (strcmp(key, "joystick_camera_3")     == 0)
188                     config_set_d(CONFIG_JOYSTICK_CAMERA_3,    atoi(val));
189                 else if (strcmp(key, "view_fov")              == 0)
190                     config_set_d(CONFIG_VIEW_FOV,             atoi(val));
191                 else if (strcmp(key, "view_dp")               == 0)
192                     config_set_d(CONFIG_VIEW_DP,              atoi(val));
193                 else if (strcmp(key, "view_dc")               == 0)
194                     config_set_d(CONFIG_VIEW_DC,              atoi(val));
195                 else if (strcmp(key, "view_dz")               == 0)
196                     config_set_d(CONFIG_VIEW_DZ,              atoi(val));
197                 else if (strcmp(key, "rotate_fast")           == 0)
198                     config_set_d(CONFIG_ROTATE_FAST,          atoi(val));
199                 else if (strcmp(key, "rotate_slow")           == 0)
200                     config_set_d(CONFIG_ROTATE_SLOW,          atoi(val));
201                 else if (strcmp(key, "last_set")              == 0)
202                     config_set_d(CONFIG_LAST_SET,             atoi(val));
203                 else if (strcmp(key, "mode")                  == 0)
204                     config_set_d(CONFIG_MODE,                 atoi(val));
205
206                 else if (strcmp(key, "key_camera_1")  == 0)
207                     config_key(val, CONFIG_KEY_CAMERA_1, DEFAULT_KEY_CAMERA_1);
208                 else if (strcmp(key, "key_camera_2")  == 0)
209                     config_key(val, CONFIG_KEY_CAMERA_2, DEFAULT_KEY_CAMERA_2);
210                 else if (strcmp(key, "key_camera_3")  == 0)
211                     config_key(val, CONFIG_KEY_CAMERA_3, DEFAULT_KEY_CAMERA_3);
212                 else if (strcmp(key, "key_camera_r")  == 0)
213                     config_key(val, CONFIG_KEY_CAMERA_R, DEFAULT_KEY_CAMERA_R);
214                 else if (strcmp(key, "key_camera_l")  == 0)
215                     config_key(val, CONFIG_KEY_CAMERA_L, DEFAULT_KEY_CAMERA_L);
216
217                 else if (strcmp(key, "player") == 0)
218                     config_set_s(CONFIG_PLAYER, val);
219                 else if (strcmp(key, "ball")   == 0)
220                     config_set_s(CONFIG_BALL,   val);
221                 else if (strcmp(key, "coin")   == 0)
222                     config_set_s(CONFIG_COIN,   val);
223                 else if (strcmp(key, "lang")   == 0)
224                     config_set_s(CONFIG_LANG,   val);
225             }
226
227         fclose(fp);
228
229         dirty = 0;
230     }
231 }
232
233 void config_save(void)
234 {
235     FILE *fp;
236
237     if (dirty && (fp = fopen(config_user(USER_CONFIG_FILE), "w")))
238     {
239         fprintf(fp, "fullscreen           %d\n",
240                 option_d[CONFIG_FULLSCREEN]);
241         fprintf(fp, "width                %d\n",
242                 option_d[CONFIG_WIDTH]);
243         fprintf(fp, "height               %d\n",
244                 option_d[CONFIG_HEIGHT]);
245         fprintf(fp, "stereo               %d\n",
246                 option_d[CONFIG_STEREO]);
247         fprintf(fp, "camera               %d\n",
248                 option_d[CONFIG_CAMERA]);
249         fprintf(fp, "textures             %d\n",
250                 option_d[CONFIG_TEXTURES]);
251         fprintf(fp, "geometry             %d\n",
252                 option_d[CONFIG_GEOMETRY]);
253         fprintf(fp, "reflection           %d\n",
254                 option_d[CONFIG_REFLECTION]);
255         fprintf(fp, "background           %d\n",
256                 option_d[CONFIG_BACKGROUND]);
257         fprintf(fp, "shadow               %d\n",
258                 option_d[CONFIG_SHADOW]);
259         fprintf(fp, "audio_rate           %d\n",
260                 option_d[CONFIG_AUDIO_RATE]);
261         fprintf(fp, "audio_buff           %d\n",
262                 option_d[CONFIG_AUDIO_BUFF]);
263         fprintf(fp, "mouse_sense          %d\n",
264                 option_d[CONFIG_MOUSE_SENSE]);
265         fprintf(fp, "mouse_invert         %d\n",
266                 option_d[CONFIG_MOUSE_INVERT]);
267         fprintf(fp, "nice                 %d\n",
268                 option_d[CONFIG_NICE]);
269         fprintf(fp, "fps                  %d\n",
270                 option_d[CONFIG_FPS]);
271         fprintf(fp, "sound_volume         %d\n",
272                 option_d[CONFIG_SOUND_VOLUME]);
273         fprintf(fp, "music_volume         %d\n",
274                 option_d[CONFIG_MUSIC_VOLUME]);
275         fprintf(fp, "joystick             %d\n",
276                 option_d[CONFIG_JOYSTICK]);
277         fprintf(fp, "joystick_device      %d\n",
278                 option_d[CONFIG_JOYSTICK_DEVICE]);
279         fprintf(fp, "joystick_axis_x      %d\n",
280                 option_d[CONFIG_JOYSTICK_AXIS_X]);
281         fprintf(fp, "joystick_axis_y      %d\n",
282                 option_d[CONFIG_JOYSTICK_AXIS_Y]);
283         fprintf(fp, "joystick_button_a    %d\n",
284                 option_d[CONFIG_JOYSTICK_BUTTON_A]);
285         fprintf(fp, "joystick_button_b    %d\n",
286                 option_d[CONFIG_JOYSTICK_BUTTON_B]);
287         fprintf(fp, "joystick_button_r    %d\n",
288                 option_d[CONFIG_JOYSTICK_BUTTON_R]);
289         fprintf(fp, "joystick_button_l    %d\n",
290                 option_d[CONFIG_JOYSTICK_BUTTON_L]);
291         fprintf(fp, "joystick_button_exit %d\n",
292                 option_d[CONFIG_JOYSTICK_BUTTON_EXIT]);
293         fprintf(fp, "joystick_camera_1    %d\n",
294                 option_d[CONFIG_JOYSTICK_CAMERA_1]);
295         fprintf(fp, "joystick_camera_2    %d\n",
296                 option_d[CONFIG_JOYSTICK_CAMERA_2]);
297         fprintf(fp, "joystick_camera_3    %d\n",
298                 option_d[CONFIG_JOYSTICK_CAMERA_3]);
299         fprintf(fp, "view_fov             %d\n",
300                 option_d[CONFIG_VIEW_FOV]);
301         fprintf(fp, "view_dp              %d\n",
302                 option_d[CONFIG_VIEW_DP]);
303         fprintf(fp, "view_dc              %d\n",
304                 option_d[CONFIG_VIEW_DC]);
305         fprintf(fp, "view_dz              %d\n",
306                 option_d[CONFIG_VIEW_DZ]);
307         fprintf(fp, "rotate_fast          %d\n",
308                 option_d[CONFIG_ROTATE_FAST]);
309         fprintf(fp, "rotate_slow          %d\n",
310                 option_d[CONFIG_ROTATE_SLOW]);
311         fprintf(fp, "last_set             %d\n",
312                 option_d[CONFIG_LAST_SET]);
313         fprintf(fp, "mode                 %d\n",
314                 option_d[CONFIG_MODE]);
315
316         fprintf(fp, "key_camera_1         %s\n",
317                 SDL_GetKeyName(option_d[CONFIG_KEY_CAMERA_1]));
318         fprintf(fp, "key_camera_2         %s\n",
319                 SDL_GetKeyName(option_d[CONFIG_KEY_CAMERA_2]));
320         fprintf(fp, "key_camera_3         %s\n",
321                 SDL_GetKeyName(option_d[CONFIG_KEY_CAMERA_3]));
322         fprintf(fp, "key_camera_r         %s\n",
323                 SDL_GetKeyName(option_d[CONFIG_KEY_CAMERA_R]));
324         fprintf(fp, "key_camera_l         %s\n",
325                 SDL_GetKeyName(option_d[CONFIG_KEY_CAMERA_L]));
326
327         fprintf(fp, "player               %s\n", option_s[CONFIG_PLAYER]);
328         fprintf(fp, "ball                 %s\n", option_s[CONFIG_BALL]);
329         fprintf(fp, "coin                 %s\n", option_s[CONFIG_COIN]);
330         fprintf(fp, "lang                 %s\n", option_s[CONFIG_LANG]);
331
332         fclose(fp);
333     }
334
335     dirty = 0;
336 }
337
338 /*---------------------------------------------------------------------------*/
339
340 int config_mode(int f, int w, int h)
341 {
342     int stereo  = config_get_d(CONFIG_STEREO)     ? 1 : 0;
343     int stencil = config_get_d(CONFIG_REFLECTION) ? 1 : 0;
344
345     SDL_GL_SetAttribute(SDL_GL_STEREO,       stereo);
346     SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, stencil);
347
348     /* Try to set the currently specified mode. */
349
350     if (SDL_SetVideoMode(w, h, 0, SDL_OPENGL | (f ? SDL_FULLSCREEN : 0)))
351     {
352         config_set_d(CONFIG_FULLSCREEN, f);
353         config_set_d(CONFIG_WIDTH, w);
354         config_set_d(CONFIG_HEIGHT, h);
355
356         glViewport(0, 0, w, h);
357         glClearColor(0.0f, 0.0f, 0.1f, 0.0f);
358
359         glEnable(GL_NORMALIZE);
360         glEnable(GL_CULL_FACE);
361         glEnable(GL_DEPTH_TEST);
362         glEnable(GL_TEXTURE_2D);
363         glEnable(GL_LIGHTING);
364
365         return 1;
366     }
367
368     /* If the mode failed, try it without stereo. */
369
370     else if (stereo)
371     {
372         config_set_d(CONFIG_STEREO, 0);
373         return config_mode(f, w, h);
374     }
375
376     /* If that mode failed, try it without reflections. */
377
378     else if (stencil)
379     {
380         config_set_d(CONFIG_REFLECTION, 0);
381         return config_mode(f, w, h);
382     }
383
384     /* If THAT mode failed, punt. */
385
386     return 0;
387 }
388
389 /*---------------------------------------------------------------------------*/
390
391 static char data_path[MAXSTR];
392 static char user_path[MAXSTR];
393
394 /*
395  * Given  a path  and a  file name  relative to  that path,  create an
396  * absolute path name and return a temporary pointer to it.
397  */
398 static const char *config_file(const char *path, const char *file)
399 {
400     static char absolute[MAXSTR];
401
402     size_t d = strlen(path);
403
404     strncpy(absolute, path, MAXSTR - 1);
405     strncat(absolute, "/",  MAXSTR - d - 1);
406     strncat(absolute, file, MAXSTR - d - 2);
407
408     return absolute;
409 }
410
411 static int config_test(const char *path, const char *file)
412 {
413     if (file)
414     {
415         FILE *fp;
416
417         if ((fp = fopen(config_file(path, file), "r")))
418         {
419             fclose(fp);
420             return 1;
421         }
422         return 0;
423     }
424     return 1;
425 }
426
427 const char *config_data(const char *file)
428 {
429     return config_file(data_path, file);
430 }
431
432 const char *config_user(const char *file)
433 {
434     return config_file(user_path, file);
435 }
436
437 /*---------------------------------------------------------------------------*/
438
439 /*
440  * Attempt to find  the game data directory.  Search  the command line
441  * paramater,  the environment,  and the  hard-coded default,  in that
442  * order.  Confirm it by checking for presense of the named file.
443  */
444 int config_data_path(const char *path, const char *file)
445 {
446     char *dir;
447
448     if (path && config_test(path, file))
449     {
450         strncpy(data_path, path, MAXSTR);
451         return 1;
452     }
453
454     if ((dir = getenv("NEVERBALL_DATA")) && config_test(dir, file))
455     {
456         strncpy(data_path, dir, MAXSTR);
457         return 1;
458     }
459
460     if (CONFIG_DATA && config_test(CONFIG_DATA, file))
461     {
462         strncpy(data_path, CONFIG_DATA, MAXSTR);
463         return 1;
464     }
465
466     return 0;
467 }
468
469 /*
470  * Determine the location of  the user's home directory.  Ensure there
471  * is a  directory there for  storing configuration, high  scores, and
472  * replays.
473  *
474  * HACK: under Windows just assume the user has permission to write to
475  * the data  directory.  This is  more reliable than trying  to devine
476  * anything reasonable from the environment.
477  */
478 int config_user_path(const char *file)
479 {
480 #ifdef _WIN32
481     size_t d = strlen(CONFIG_USER);
482
483     strncpy(user_path, data_path,   MAXSTR - 1);
484     strncat(user_path, "\\",        MAXSTR - d - 1);
485     strncat(user_path, CONFIG_USER, MAXSTR - d - 2);
486
487     if ((mkdir(user_path) == 0) || (errno = EEXIST))
488         if (config_test(user_path, file))
489             return 1;
490 #else
491     char *dir;
492
493     if ((dir = getenv("HOME")))
494     {
495         size_t d = strlen(dir);
496
497         strncpy(user_path, getenv("HOME"), MAXSTR - 1);
498         strncat(user_path, "/",            MAXSTR - d - 1);
499         strncat(user_path, CONFIG_USER,    MAXSTR - d - 2);
500     }
501
502     if ((mkdir(user_path, 0777) == 0) || (errno = EEXIST))
503         if (config_test(user_path, file))
504             return 1;
505 #endif
506
507     return 0;
508 }
509
510 /*---------------------------------------------------------------------------*/
511
512 void config_set_d(int i, int d)
513 {
514     option_d[i] = d;
515     dirty = 1;
516 }
517
518 void config_tgl_d(int i)
519 {
520     option_d[i] = (option_d[i] ? 0 : 1);
521     dirty = 1;
522 }
523
524 int config_tst_d(int i, int d)
525 {
526     return (option_d[i] == d) ? 1 : 0;
527 }
528
529 int config_get_d(int i)
530 {
531     return option_d[i];
532 }
533
534 /*---------------------------------------------------------------------------*/
535
536 void config_set_s(int i, const char *src)
537 {
538     int len = (int) strlen(src);
539
540     if (option_s[i])
541         free(option_s[i]);
542
543     if ((option_s[i] = (char *) malloc(len + 1)))
544         strncpy(option_s[i], src, len + 1);
545
546     dirty = 1;
547 }
548
549 void config_get_s(int i, char *dst, int len)
550 {
551     strncpy(dst, option_s[i], len);
552 }
553
554 const char * config_simple_get_s(int i)
555 {
556         return option_s[i];
557 }
558
559 /*---------------------------------------------------------------------------*/
560
561 static int grabbed = 0;
562 static int paused  = 0;
563
564 void config_set_grab(void)
565 {
566     SDL_WarpMouse(config_get_d(CONFIG_WIDTH)  / 2,
567                   config_get_d(CONFIG_HEIGHT) / 2);
568     SDL_WM_GrabInput(SDL_GRAB_ON);
569     SDL_ShowCursor(SDL_DISABLE);
570     grabbed = 1;
571 }
572
573 void config_clr_grab(void)
574 {
575     SDL_WM_GrabInput(SDL_GRAB_OFF);
576     SDL_ShowCursor(SDL_ENABLE);
577     grabbed = 0;
578 }
579
580 int  config_get_grab(void)
581 {
582     return grabbed;
583 }
584
585 int  config_get_pause(void)
586 {
587     return paused;
588 }
589
590 void config_set_pause(void)
591 {
592     Mix_PauseMusic();
593     paused = 1;
594
595     if (grabbed)
596     {
597         SDL_ShowCursor(SDL_ENABLE);
598         SDL_WM_GrabInput(SDL_GRAB_OFF);
599     }
600 }
601
602 void config_clr_pause(void)
603 {
604     Mix_ResumeMusic();
605     paused = 0;
606
607     if (grabbed)
608     {
609         SDL_WM_GrabInput(SDL_GRAB_ON);
610         SDL_ShowCursor(SDL_DISABLE);
611     }
612 }
613
614 void config_tgl_pause(void)
615 {
616     if (paused)
617         config_clr_pause();
618     else
619         config_set_pause();
620 }
621 /*---------------------------------------------------------------------------*/
622
623 void config_push_persp(float fov, float n, float f)
624 {
625     GLdouble m[4][4];
626
627     GLdouble r = fov / 2 * V_PI / 180;
628     GLdouble s = sin(r);
629     GLdouble c = cos(r) / s;
630
631     GLdouble a = ((GLdouble) option_d[CONFIG_WIDTH] / 
632                   (GLdouble) option_d[CONFIG_HEIGHT]);
633
634     glMatrixMode(GL_PROJECTION);
635     {
636         glPushMatrix();
637         glLoadIdentity();
638
639         m[0][0] =  c/a;
640         m[0][1] =  0.0;
641         m[0][2] =  0.0;
642         m[0][3] =  0.0;
643         m[1][0] =  0.0;
644         m[1][1] =    c;
645         m[1][2] =  0.0;
646         m[1][3] =  0.0;
647         m[2][0] =  0.0;
648         m[2][1] =  0.0;
649         m[2][2] = -(f + n) / (f - n);
650         m[2][3] = -1.0;
651         m[3][0] =  0.0;
652         m[3][1] =  0.0;
653         m[3][2] = -2.0 * n * f / (f - n);
654         m[3][3] =  0.0;
655
656         glMultMatrixd(&m[0][0]);
657     }
658     glMatrixMode(GL_MODELVIEW);
659 }
660
661 void config_push_ortho(void)
662 {
663     GLdouble w = (GLdouble) option_d[CONFIG_WIDTH];
664     GLdouble h = (GLdouble) option_d[CONFIG_HEIGHT];
665
666     glMatrixMode(GL_PROJECTION);
667     {
668         glPushMatrix();
669         glLoadIdentity();
670         glOrtho(0.0, w, 0.0, h, -1.0, +1.0);
671     }
672     glMatrixMode(GL_MODELVIEW);
673 }
674
675 void config_pop_matrix(void)
676 {
677     glMatrixMode(GL_PROJECTION);
678     {
679         glPopMatrix();
680     }
681     glMatrixMode(GL_MODELVIEW);
682 }
683
684 void config_clear(void)
685 {
686     if (option_d[CONFIG_REFLECTION])
687         glClear(GL_COLOR_BUFFER_BIT |
688                 GL_DEPTH_BUFFER_BIT |
689                 GL_STENCIL_BUFFER_BIT);
690     else
691         glClear(GL_COLOR_BUFFER_BIT |
692                 GL_DEPTH_BUFFER_BIT);
693 }
694
695 /*---------------------------------------------------------------------------*/