Merge r739:1104 from the s_dict branch.
[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, sizeof (option_d));
65     memset(option_s, 0, sizeof (option_s));
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_MULTISAMPLE,          DEFAULT_MULTISAMPLE);
76     config_set_d(CONFIG_BACKGROUND,           DEFAULT_BACKGROUND);
77     config_set_d(CONFIG_SHADOW,               DEFAULT_SHADOW);
78     config_set_d(CONFIG_AUDIO_RATE,           DEFAULT_AUDIO_RATE);
79     config_set_d(CONFIG_AUDIO_BUFF,           DEFAULT_AUDIO_BUFF);
80     config_set_d(CONFIG_MOUSE_SENSE,          DEFAULT_MOUSE_SENSE);
81     config_set_d(CONFIG_MOUSE_INVERT,         DEFAULT_MOUSE_INVERT);
82     config_set_d(CONFIG_NICE,                 DEFAULT_NICE);
83     config_set_d(CONFIG_FPS,                  DEFAULT_FPS);
84     config_set_d(CONFIG_SOUND_VOLUME,         DEFAULT_SOUND_VOLUME);
85     config_set_d(CONFIG_MUSIC_VOLUME,         DEFAULT_MUSIC_VOLUME);
86     config_set_d(CONFIG_JOYSTICK,             DEFAULT_JOYSTICK);
87     config_set_d(CONFIG_JOYSTICK_DEVICE,      DEFAULT_JOYSTICK_DEVICE);
88     config_set_d(CONFIG_JOYSTICK_AXIS_X,      DEFAULT_JOYSTICK_AXIS_X);
89     config_set_d(CONFIG_JOYSTICK_AXIS_Y,      DEFAULT_JOYSTICK_AXIS_Y);
90     config_set_d(CONFIG_JOYSTICK_BUTTON_A,    DEFAULT_JOYSTICK_BUTTON_A);
91     config_set_d(CONFIG_JOYSTICK_BUTTON_B,    DEFAULT_JOYSTICK_BUTTON_B);
92     config_set_d(CONFIG_JOYSTICK_BUTTON_L,    DEFAULT_JOYSTICK_BUTTON_L);
93     config_set_d(CONFIG_JOYSTICK_BUTTON_R,    DEFAULT_JOYSTICK_BUTTON_R);
94     config_set_d(CONFIG_JOYSTICK_BUTTON_EXIT, DEFAULT_JOYSTICK_BUTTON_EXIT);
95     config_set_d(CONFIG_JOYSTICK_CAMERA_1,    DEFAULT_JOYSTICK_CAMERA_1);
96     config_set_d(CONFIG_JOYSTICK_CAMERA_2,    DEFAULT_JOYSTICK_CAMERA_2);
97     config_set_d(CONFIG_JOYSTICK_CAMERA_3,    DEFAULT_JOYSTICK_CAMERA_3);
98     config_set_d(CONFIG_KEY_CAMERA_1,         DEFAULT_KEY_CAMERA_1);
99     config_set_d(CONFIG_KEY_CAMERA_2,         DEFAULT_KEY_CAMERA_2);
100     config_set_d(CONFIG_KEY_CAMERA_3,         DEFAULT_KEY_CAMERA_3);
101     config_set_d(CONFIG_KEY_CAMERA_R,         DEFAULT_KEY_CAMERA_R);
102     config_set_d(CONFIG_KEY_CAMERA_L,         DEFAULT_KEY_CAMERA_L);
103     config_set_d(CONFIG_VIEW_FOV,             DEFAULT_VIEW_FOV);
104     config_set_d(CONFIG_VIEW_DP,              DEFAULT_VIEW_DP);
105     config_set_d(CONFIG_VIEW_DC,              DEFAULT_VIEW_DC);
106     config_set_d(CONFIG_VIEW_DZ,              DEFAULT_VIEW_DZ);
107     config_set_d(CONFIG_ROTATE_FAST,          DEFAULT_ROTATE_FAST);
108     config_set_d(CONFIG_ROTATE_SLOW,          DEFAULT_ROTATE_SLOW);
109     config_set_d(CONFIG_MODE,                 DEFAULT_MODE);
110     config_set_d(CONFIG_CHEAT,                DEFAULT_CHEAT);
111     config_set_s(CONFIG_PLAYER,               DEFAULT_PLAYER);
112     config_set_s(CONFIG_BALL,                 DEFAULT_BALL);
113     config_set_s(CONFIG_BALL_BONUS,           DEFAULT_BALL_BONUS);
114     config_set_d(CONFIG_KEY_FORWARD,          DEFAULT_KEY_FORWARD);
115     config_set_d(CONFIG_KEY_BACKWARD,         DEFAULT_KEY_BACKWARD);
116     config_set_d(CONFIG_KEY_LEFT,             DEFAULT_KEY_LEFT);
117     config_set_d(CONFIG_KEY_RIGHT,            DEFAULT_KEY_RIGHT);
118     config_set_d(CONFIG_KEY_PAUSE,            DEFAULT_KEY_PAUSE);
119     config_set_d(CONFIG_KEY_RESTART,          DEFAULT_KEY_RESTART);
120 }
121
122 void config_load(void)
123 {
124     FILE *fp;
125
126     if ((fp = fopen(config_user(USER_CONFIG_FILE), "r")))
127     {
128         char buf[MAXSTR];
129         char key[MAXSTR];
130         char val[MAXSTR];
131
132         while (fgets(buf, MAXSTR, fp))
133             if (sscanf(buf, "%s %s", key, val) == 2)
134             {
135                 if      (strcmp(key, "fullscreen")            == 0)
136                     config_set_d(CONFIG_FULLSCREEN,           atoi(val));
137                 else if (strcmp(key, "width")                 == 0)
138                     config_set_d(CONFIG_WIDTH,                atoi(val));
139                 else if (strcmp(key, "height")                == 0)
140                     config_set_d(CONFIG_HEIGHT,               atoi(val));
141                 else if (strcmp(key, "stereo")                == 0)
142                     config_set_d(CONFIG_STEREO,               atoi(val));
143                 else if (strcmp(key, "camera")                == 0)
144                     config_set_d(CONFIG_CAMERA,               atoi(val));
145                 else if (strcmp(key, "textures")              == 0)
146                     config_set_d(CONFIG_TEXTURES,             atoi(val));
147                 else if (strcmp(key, "geometry")              == 0)
148                     config_set_d(CONFIG_GEOMETRY,             atoi(val));
149                 else if (strcmp(key, "reflection")            == 0)
150                     config_set_d(CONFIG_REFLECTION,           atoi(val));
151                 else if (strcmp(key, "multisample")           == 0)
152                     config_set_d(CONFIG_MULTISAMPLE,          atoi(val));
153                 else if (strcmp(key, "background")            == 0)
154                     config_set_d(CONFIG_BACKGROUND,           atoi(val));
155                 else if (strcmp(key, "shadow")                == 0)
156                     config_set_d(CONFIG_SHADOW,               atoi(val));
157                 else if (strcmp(key, "audio_rate")            == 0)
158                     config_set_d(CONFIG_AUDIO_RATE,           atoi(val));
159                 else if (strcmp(key, "audio_buff")            == 0)
160                     config_set_d(CONFIG_AUDIO_BUFF,           atoi(val));
161                 else if (strcmp(key, "mouse_sense")           == 0)
162                     config_set_d(CONFIG_MOUSE_SENSE,          atoi(val));
163                 else if (strcmp(key, "mouse_invert")          == 0)
164                     config_set_d(CONFIG_MOUSE_INVERT,         atoi(val));
165                 else if (strcmp(key, "nice")                  == 0)
166                     config_set_d(CONFIG_NICE,                 atoi(val));
167                 else if (strcmp(key, "fps")                   == 0)
168                     config_set_d(CONFIG_FPS,                  atoi(val));
169                 else if (strcmp(key, "sound_volume")          == 0)
170                     config_set_d(CONFIG_SOUND_VOLUME,         atoi(val));
171                 else if (strcmp(key, "music_volume")          == 0)
172                     config_set_d(CONFIG_MUSIC_VOLUME,         atoi(val));
173                 else if (strcmp(key, "joystick")              == 0)
174                     config_set_d(CONFIG_JOYSTICK,             atoi(val));
175                 else if (strcmp(key, "joystick_device")       == 0)
176                     config_set_d(CONFIG_JOYSTICK_DEVICE,      atoi(val));
177                 else if (strcmp(key, "joystick_axis_x")       == 0)
178                     config_set_d(CONFIG_JOYSTICK_AXIS_X,      atoi(val));
179                 else if (strcmp(key, "joystick_axis_y")       == 0)
180                     config_set_d(CONFIG_JOYSTICK_AXIS_Y,      atoi(val));
181                 else if (strcmp(key, "joystick_button_a")     == 0)
182                     config_set_d(CONFIG_JOYSTICK_BUTTON_A,    atoi(val));
183                 else if (strcmp(key, "joystick_button_b")     == 0)
184                     config_set_d(CONFIG_JOYSTICK_BUTTON_B,    atoi(val));
185                 else if (strcmp(key, "joystick_button_r")     == 0)
186                     config_set_d(CONFIG_JOYSTICK_BUTTON_R,    atoi(val));
187                 else if (strcmp(key, "joystick_button_l")     == 0)
188                     config_set_d(CONFIG_JOYSTICK_BUTTON_L,    atoi(val));
189                 else if (strcmp(key, "joystick_button_exit")  == 0)
190                     config_set_d(CONFIG_JOYSTICK_BUTTON_EXIT, atoi(val));
191                 else if (strcmp(key, "joystick_camera_1")     == 0)
192                     config_set_d(CONFIG_JOYSTICK_CAMERA_1,    atoi(val));
193                 else if (strcmp(key, "joystick_camera_2")     == 0)
194                     config_set_d(CONFIG_JOYSTICK_CAMERA_2,    atoi(val));
195                 else if (strcmp(key, "joystick_camera_3")     == 0)
196                     config_set_d(CONFIG_JOYSTICK_CAMERA_3,    atoi(val));
197                 else if (strcmp(key, "view_fov")              == 0)
198                     config_set_d(CONFIG_VIEW_FOV,             atoi(val));
199                 else if (strcmp(key, "view_dp")               == 0)
200                     config_set_d(CONFIG_VIEW_DP,              atoi(val));
201                 else if (strcmp(key, "view_dc")               == 0)
202                     config_set_d(CONFIG_VIEW_DC,              atoi(val));
203                 else if (strcmp(key, "view_dz")               == 0)
204                     config_set_d(CONFIG_VIEW_DZ,              atoi(val));
205                 else if (strcmp(key, "rotate_fast")           == 0)
206                     config_set_d(CONFIG_ROTATE_FAST,          atoi(val));
207                 else if (strcmp(key, "rotate_slow")           == 0)
208                     config_set_d(CONFIG_ROTATE_SLOW,          atoi(val));
209                 else if (strcmp(key, "mode")                  == 0)
210                     config_set_d(CONFIG_MODE,                 atoi(val));
211                 else if (strcmp(key, "cheat") == 0 && ALLOW_CHEAT)
212                     config_set_d(CONFIG_CHEAT,                atoi(val));
213
214                 else if (strcmp(key, "key_forward")  == 0)
215                     config_key(val, CONFIG_KEY_FORWARD, DEFAULT_KEY_FORWARD);
216                 else if (strcmp(key, "key_backward")  == 0)
217                     config_key(val, CONFIG_KEY_BACKWARD, DEFAULT_KEY_BACKWARD);
218                 else if (strcmp(key, "key_left")  == 0)
219                     config_key(val, CONFIG_KEY_LEFT, DEFAULT_KEY_LEFT);
220                 else if (strcmp(key, "key_right")  == 0)
221                     config_key(val, CONFIG_KEY_RIGHT, DEFAULT_KEY_RIGHT);
222
223                 else if (strcmp(key, "key_camera_1")  == 0)
224                     config_key(val, CONFIG_KEY_CAMERA_1, DEFAULT_KEY_CAMERA_1);
225                 else if (strcmp(key, "key_camera_2")  == 0)
226                     config_key(val, CONFIG_KEY_CAMERA_2, DEFAULT_KEY_CAMERA_2);
227                 else if (strcmp(key, "key_camera_3")  == 0)
228                     config_key(val, CONFIG_KEY_CAMERA_3, DEFAULT_KEY_CAMERA_3);
229                 else if (strcmp(key, "key_camera_r")  == 0)
230                     config_key(val, CONFIG_KEY_CAMERA_R, DEFAULT_KEY_CAMERA_R);
231                 else if (strcmp(key, "key_camera_l")  == 0)
232                     config_key(val, CONFIG_KEY_CAMERA_L, DEFAULT_KEY_CAMERA_L);
233
234                 else if (strcmp(key, "key_pause")  == 0)
235                     config_key(val, CONFIG_KEY_PAUSE,    DEFAULT_KEY_PAUSE);
236                 else if (strcmp(key, "key_restart")  == 0)
237                     config_key(val, CONFIG_KEY_RESTART,    DEFAULT_KEY_RESTART);
238
239                 else if (strcmp(key, "player")     == 0)
240                     config_set_s(CONFIG_PLAYER,     val);
241                 else if (strcmp(key, "ball")       == 0)
242                     config_set_s(CONFIG_BALL,       val);
243                 else if (strcmp(key, "ball_bonus") == 0)
244                     config_set_s(CONFIG_BALL_BONUS, val);
245             }
246
247         fclose(fp);
248
249         dirty = 0;
250     }
251 }
252
253 void config_save(void)
254 {
255     FILE *fp;
256
257     if (dirty && (fp = fopen(config_user(USER_CONFIG_FILE), "w")))
258     {
259         fprintf(fp, "fullscreen           %d\n",
260                 option_d[CONFIG_FULLSCREEN]);
261         fprintf(fp, "width                %d\n",
262                 option_d[CONFIG_WIDTH]);
263         fprintf(fp, "height               %d\n",
264                 option_d[CONFIG_HEIGHT]);
265         fprintf(fp, "stereo               %d\n",
266                 option_d[CONFIG_STEREO]);
267         fprintf(fp, "camera               %d\n",
268                 option_d[CONFIG_CAMERA]);
269         fprintf(fp, "textures             %d\n",
270                 option_d[CONFIG_TEXTURES]);
271         fprintf(fp, "geometry             %d\n",
272                 option_d[CONFIG_GEOMETRY]);
273         fprintf(fp, "reflection           %d\n",
274                 option_d[CONFIG_REFLECTION]);
275         fprintf(fp, "multisample          %d\n",
276                 option_d[CONFIG_MULTISAMPLE]);
277         fprintf(fp, "background           %d\n",
278                 option_d[CONFIG_BACKGROUND]);
279         fprintf(fp, "shadow               %d\n",
280                 option_d[CONFIG_SHADOW]);
281         fprintf(fp, "audio_rate           %d\n",
282                 option_d[CONFIG_AUDIO_RATE]);
283         fprintf(fp, "audio_buff           %d\n",
284                 option_d[CONFIG_AUDIO_BUFF]);
285         fprintf(fp, "mouse_sense          %d\n",
286                 option_d[CONFIG_MOUSE_SENSE]);
287         fprintf(fp, "mouse_invert         %d\n",
288                 option_d[CONFIG_MOUSE_INVERT]);
289         fprintf(fp, "nice                 %d\n",
290                 option_d[CONFIG_NICE]);
291         fprintf(fp, "fps                  %d\n",
292                 option_d[CONFIG_FPS]);
293         fprintf(fp, "sound_volume         %d\n",
294                 option_d[CONFIG_SOUND_VOLUME]);
295         fprintf(fp, "music_volume         %d\n",
296                 option_d[CONFIG_MUSIC_VOLUME]);
297         fprintf(fp, "joystick             %d\n",
298                 option_d[CONFIG_JOYSTICK]);
299         fprintf(fp, "joystick_device      %d\n",
300                 option_d[CONFIG_JOYSTICK_DEVICE]);
301         fprintf(fp, "joystick_axis_x      %d\n",
302                 option_d[CONFIG_JOYSTICK_AXIS_X]);
303         fprintf(fp, "joystick_axis_y      %d\n",
304                 option_d[CONFIG_JOYSTICK_AXIS_Y]);
305         fprintf(fp, "joystick_button_a    %d\n",
306                 option_d[CONFIG_JOYSTICK_BUTTON_A]);
307         fprintf(fp, "joystick_button_b    %d\n",
308                 option_d[CONFIG_JOYSTICK_BUTTON_B]);
309         fprintf(fp, "joystick_button_r    %d\n",
310                 option_d[CONFIG_JOYSTICK_BUTTON_R]);
311         fprintf(fp, "joystick_button_l    %d\n",
312                 option_d[CONFIG_JOYSTICK_BUTTON_L]);
313         fprintf(fp, "joystick_button_exit %d\n",
314                 option_d[CONFIG_JOYSTICK_BUTTON_EXIT]);
315         fprintf(fp, "joystick_camera_1    %d\n",
316                 option_d[CONFIG_JOYSTICK_CAMERA_1]);
317         fprintf(fp, "joystick_camera_2    %d\n",
318                 option_d[CONFIG_JOYSTICK_CAMERA_2]);
319         fprintf(fp, "joystick_camera_3    %d\n",
320                 option_d[CONFIG_JOYSTICK_CAMERA_3]);
321         fprintf(fp, "view_fov             %d\n",
322                 option_d[CONFIG_VIEW_FOV]);
323         fprintf(fp, "view_dp              %d\n",
324                 option_d[CONFIG_VIEW_DP]);
325         fprintf(fp, "view_dc              %d\n",
326                 option_d[CONFIG_VIEW_DC]);
327         fprintf(fp, "view_dz              %d\n",
328                 option_d[CONFIG_VIEW_DZ]);
329         fprintf(fp, "rotate_fast          %d\n",
330                 option_d[CONFIG_ROTATE_FAST]);
331         fprintf(fp, "rotate_slow          %d\n",
332                 option_d[CONFIG_ROTATE_SLOW]);
333         fprintf(fp, "mode                 %d\n",
334                 option_d[CONFIG_MODE]);
335
336         fprintf(fp, "key_forward          %s\n",
337                 SDL_GetKeyName(option_d[CONFIG_KEY_FORWARD]));
338         fprintf(fp, "key_backward         %s\n",
339                 SDL_GetKeyName(option_d[CONFIG_KEY_BACKWARD]));
340         fprintf(fp, "key_left             %s\n",
341                 SDL_GetKeyName(option_d[CONFIG_KEY_LEFT]));
342         fprintf(fp, "key_right            %s\n",
343                 SDL_GetKeyName(option_d[CONFIG_KEY_RIGHT]));
344
345         if (option_d[CONFIG_CHEAT])
346             fprintf(fp,
347                     "cheat                %d\n",
348                     option_d[CONFIG_CHEAT]);
349
350         fprintf(fp, "key_camera_1         %s\n",
351                 SDL_GetKeyName(option_d[CONFIG_KEY_CAMERA_1]));
352         fprintf(fp, "key_camera_2         %s\n",
353                 SDL_GetKeyName(option_d[CONFIG_KEY_CAMERA_2]));
354         fprintf(fp, "key_camera_3         %s\n",
355                 SDL_GetKeyName(option_d[CONFIG_KEY_CAMERA_3]));
356         fprintf(fp, "key_camera_r         %s\n",
357                 SDL_GetKeyName(option_d[CONFIG_KEY_CAMERA_R]));
358         fprintf(fp, "key_camera_l         %s\n",
359                 SDL_GetKeyName(option_d[CONFIG_KEY_CAMERA_L]));
360
361         fprintf(fp, "key_pause            %s\n",
362                 SDL_GetKeyName(option_d[CONFIG_KEY_PAUSE]));
363         fprintf(fp, "key_restart          %s\n",
364                 SDL_GetKeyName(option_d[CONFIG_KEY_RESTART]));
365
366         fprintf(fp, "player               %s\n", option_s[CONFIG_PLAYER]);
367         fprintf(fp, "ball                 %s\n", option_s[CONFIG_BALL]);
368         fprintf(fp, "ball_bonus           %s\n", option_s[CONFIG_BALL_BONUS]);
369
370         fclose(fp);
371     }
372
373     dirty = 0;
374 }
375
376 /*---------------------------------------------------------------------------*/
377
378 int check_extension(const char *needle)
379 {
380     const GLubyte *haystack, *c;
381
382     /* Search for the given string in the OpenGL extension strings. */
383
384     for (haystack = glGetString(GL_EXTENSIONS); *haystack; haystack++)
385     {
386         for (c = (const GLubyte *) needle; *c && *haystack; c++, haystack++)
387             if (*c != *haystack)
388                 break;
389
390         if ((*c == 0) && (*haystack == ' ' || *haystack == '\0'))
391             return 1;
392     }
393
394     return 0;
395 }
396
397 int config_mode(int f, int w, int h)
398 {
399     int stereo  = config_get_d(CONFIG_STEREO)      ? 1 : 0;
400     int stencil = config_get_d(CONFIG_REFLECTION)  ? 1 : 0;
401     int buffers = config_get_d(CONFIG_MULTISAMPLE) ? 1 : 0;
402     int samples = config_get_d(CONFIG_MULTISAMPLE);
403
404     SDL_GL_SetAttribute(SDL_GL_STEREO,             stereo);
405     SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE,       stencil);
406     SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, buffers);
407     SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, samples);
408
409     /* Try to set the currently specified mode. */
410
411     if (SDL_SetVideoMode(w, h, 0, SDL_OPENGL | (f ? SDL_FULLSCREEN : 0)))
412     {
413         config_set_d(CONFIG_FULLSCREEN, f);
414         config_set_d(CONFIG_WIDTH, w);
415         config_set_d(CONFIG_HEIGHT, h);
416
417         glViewport(0, 0, w, h);
418         glClearColor(0.0f, 0.0f, 0.1f, 0.0f);
419
420         glEnable(GL_NORMALIZE);
421         glEnable(GL_CULL_FACE);
422         glEnable(GL_DEPTH_TEST);
423         glEnable(GL_TEXTURE_2D);
424         glEnable(GL_LIGHTING);
425
426         /* If GL supports multisample, and SDL got a multisample buffer... */
427
428 #ifdef GL_ARB_multisample
429         if (check_extension("ARB_multisample"))
430         {
431             SDL_GL_GetAttribute(SDL_GL_MULTISAMPLEBUFFERS, &buffers);
432             if (buffers)
433                 glEnable(GL_MULTISAMPLE_ARB);
434         }
435 #endif
436
437         return 1;
438     }
439
440     /* If the mode failed, try it without stereo. */
441
442     else if (stereo)
443     {
444         config_set_d(CONFIG_STEREO, 0);
445         return config_mode(f, w, h);
446     }
447
448     /* If the mode failed, try decreasing the level of multisampling. */
449
450     else if (buffers)
451     {
452         config_set_d(CONFIG_MULTISAMPLE, samples / 2);
453         return config_mode(f, w, h);
454     }
455
456     /* If that mode failed, try it without reflections. */
457
458     else if (stencil)
459     {
460         config_set_d(CONFIG_REFLECTION, 0);
461         return config_mode(f, w, h);
462     }
463
464     /* If THAT mode failed, punt. */
465
466     return 0;
467 }
468
469 /*---------------------------------------------------------------------------*/
470
471 void config_set_d(int i, int d)
472 {
473     option_d[i] = d;
474     dirty = 1;
475 }
476
477 void config_tgl_d(int i)
478 {
479     option_d[i] = (option_d[i] ? 0 : 1);
480     dirty = 1;
481 }
482
483 int config_tst_d(int i, int d)
484 {
485     return (option_d[i] == d) ? 1 : 0;
486 }
487
488 int config_get_d(int i)
489 {
490     return option_d[i];
491 }
492
493 /*---------------------------------------------------------------------------*/
494
495 void config_set_s(int i, const char *src)
496 {
497     int len = (int) strlen(src);
498
499     if (option_s[i])
500         free(option_s[i]);
501
502     if ((option_s[i] = (char *) malloc(len + 1)))
503         strncpy(option_s[i], src, len + 1);
504
505     dirty = 1;
506 }
507
508 void config_get_s(int i, char *dst, int len)
509 {
510     strncpy(dst, option_s[i], len);
511 }
512
513 const char *config_simple_get_s(int i)
514 {
515     return option_s[i];
516 }
517
518 /*---------------------------------------------------------------------------*/
519
520 static int grabbed = 0;
521
522 void config_set_grab(int w)
523 {
524     if (w)
525         SDL_WarpMouse(config_get_d(CONFIG_WIDTH)  / 2,
526                       config_get_d(CONFIG_HEIGHT) / 2);
527     SDL_WM_GrabInput(SDL_GRAB_ON);
528     SDL_ShowCursor(SDL_DISABLE);
529     grabbed = 1;
530 }
531
532 void config_clr_grab(void)
533 {
534     SDL_WM_GrabInput(SDL_GRAB_OFF);
535     SDL_ShowCursor(SDL_ENABLE);
536     grabbed = 0;
537 }
538
539 int  config_get_grab(void)
540 {
541     return grabbed;
542 }
543
544 /*---------------------------------------------------------------------------*/
545
546 void config_push_persp(float fov, float n, float f)
547 {
548     GLdouble m[4][4];
549
550     GLdouble r = fov / 2 * V_PI / 180;
551     GLdouble s = sin(r);
552     GLdouble c = cos(r) / s;
553
554     GLdouble a = ((GLdouble) option_d[CONFIG_WIDTH] /
555                   (GLdouble) option_d[CONFIG_HEIGHT]);
556
557     glMatrixMode(GL_PROJECTION);
558     {
559         glPushMatrix();
560         glLoadIdentity();
561
562         m[0][0] =  c/a;
563         m[0][1] =  0.0;
564         m[0][2] =  0.0;
565         m[0][3] =  0.0;
566         m[1][0] =  0.0;
567         m[1][1] =    c;
568         m[1][2] =  0.0;
569         m[1][3] =  0.0;
570         m[2][0] =  0.0;
571         m[2][1] =  0.0;
572         m[2][2] = -(f + n) / (f - n);
573         m[2][3] = -1.0;
574         m[3][0] =  0.0;
575         m[3][1] =  0.0;
576         m[3][2] = -2.0 * n * f / (f - n);
577         m[3][3] =  0.0;
578
579         glMultMatrixd(&m[0][0]);
580     }
581     glMatrixMode(GL_MODELVIEW);
582 }
583
584 void config_push_ortho(void)
585 {
586     GLdouble w = (GLdouble) option_d[CONFIG_WIDTH];
587     GLdouble h = (GLdouble) option_d[CONFIG_HEIGHT];
588
589     glMatrixMode(GL_PROJECTION);
590     {
591         glPushMatrix();
592         glLoadIdentity();
593         glOrtho(0.0, w, 0.0, h, -1.0, +1.0);
594     }
595     glMatrixMode(GL_MODELVIEW);
596 }
597
598 void config_pop_matrix(void)
599 {
600     glMatrixMode(GL_PROJECTION);
601     {
602         glPopMatrix();
603     }
604     glMatrixMode(GL_MODELVIEW);
605 }
606
607 void config_clear(void)
608 {
609     if (option_d[CONFIG_REFLECTION])
610         glClear(GL_COLOR_BUFFER_BIT |
611                 GL_DEPTH_BUFFER_BIT |
612                 GL_STENCIL_BUFFER_BIT);
613     else
614         glClear(GL_COLOR_BUFFER_BIT |
615                 GL_DEPTH_BUFFER_BIT);
616 }
617
618 /*---------------------------------------------------------------------------*/