2 * Copyright (C) 2003 Robert Kooima
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.
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.
29 /*---------------------------------------------------------------------------*/
31 /* Define the mkdir symbol. */
39 /*---------------------------------------------------------------------------*/
41 static int option_d[CONFIG_OPTION_D_COUNT];
42 static char *option_s[CONFIG_OPTION_S_COUNT];
46 /*---------------------------------------------------------------------------*/
48 static void config_key(const char *s, int i, int d)
54 for (c = 0; c < SDLK_LAST; c++)
55 if (strcmp(s, SDL_GetKeyName((SDLKey) c)) == 0)
62 /*---------------------------------------------------------------------------*/
64 void config_init(void)
66 memset(option_d, 0, sizeof (option_d));
67 memset(option_s, 0, sizeof (option_s));
69 config_set_d(CONFIG_FULLSCREEN, DEFAULT_FULLSCREEN);
70 config_set_d(CONFIG_WIDTH, DEFAULT_WIDTH);
71 config_set_d(CONFIG_HEIGHT, DEFAULT_HEIGHT);
72 config_set_d(CONFIG_STEREO, DEFAULT_STEREO);
73 config_set_d(CONFIG_CAMERA, DEFAULT_CAMERA);
74 config_set_d(CONFIG_TEXTURES, DEFAULT_TEXTURES);
75 config_set_d(CONFIG_GEOMETRY, DEFAULT_GEOMETRY);
76 config_set_d(CONFIG_REFLECTION, DEFAULT_REFLECTION);
77 config_set_d(CONFIG_MULTISAMPLE, DEFAULT_MULTISAMPLE);
78 config_set_d(CONFIG_MIPMAP, DEFAULT_MIPMAP);
79 config_set_d(CONFIG_ANISO, DEFAULT_ANISO);
80 config_set_d(CONFIG_BACKGROUND, DEFAULT_BACKGROUND);
81 config_set_d(CONFIG_SHADOW, DEFAULT_SHADOW);
82 config_set_d(CONFIG_AUDIO_BUFF, DEFAULT_AUDIO_BUFF);
83 config_set_d(CONFIG_MOUSE_SENSE, DEFAULT_MOUSE_SENSE);
84 config_set_d(CONFIG_MOUSE_INVERT, DEFAULT_MOUSE_INVERT);
85 config_set_d(CONFIG_VSYNC, DEFAULT_VSYNC);
86 config_set_d(CONFIG_NICE, DEFAULT_NICE);
87 config_set_d(CONFIG_FPS, DEFAULT_FPS);
88 config_set_d(CONFIG_SOUND_VOLUME, DEFAULT_SOUND_VOLUME);
89 config_set_d(CONFIG_MUSIC_VOLUME, DEFAULT_MUSIC_VOLUME);
90 config_set_d(CONFIG_JOYSTICK, DEFAULT_JOYSTICK);
91 config_set_d(CONFIG_JOYSTICK_DEVICE, DEFAULT_JOYSTICK_DEVICE);
92 config_set_d(CONFIG_JOYSTICK_AXIS_X, DEFAULT_JOYSTICK_AXIS_X);
93 config_set_d(CONFIG_JOYSTICK_AXIS_Y, DEFAULT_JOYSTICK_AXIS_Y);
94 config_set_d(CONFIG_JOYSTICK_BUTTON_A, DEFAULT_JOYSTICK_BUTTON_A);
95 config_set_d(CONFIG_JOYSTICK_BUTTON_B, DEFAULT_JOYSTICK_BUTTON_B);
96 config_set_d(CONFIG_JOYSTICK_BUTTON_L, DEFAULT_JOYSTICK_BUTTON_L);
97 config_set_d(CONFIG_JOYSTICK_BUTTON_R, DEFAULT_JOYSTICK_BUTTON_R);
98 config_set_d(CONFIG_JOYSTICK_BUTTON_EXIT, DEFAULT_JOYSTICK_BUTTON_EXIT);
99 config_set_d(CONFIG_JOYSTICK_CAMERA_1, DEFAULT_JOYSTICK_CAMERA_1);
100 config_set_d(CONFIG_JOYSTICK_CAMERA_2, DEFAULT_JOYSTICK_CAMERA_2);
101 config_set_d(CONFIG_JOYSTICK_CAMERA_3, DEFAULT_JOYSTICK_CAMERA_3);
102 config_set_d(CONFIG_JOYSTICK_DPAD_L, DEFAULT_JOYSTICK_DPAD_L);
103 config_set_d(CONFIG_JOYSTICK_DPAD_R, DEFAULT_JOYSTICK_DPAD_R);
104 config_set_d(CONFIG_JOYSTICK_DPAD_U, DEFAULT_JOYSTICK_DPAD_U);
105 config_set_d(CONFIG_JOYSTICK_DPAD_D, DEFAULT_JOYSTICK_DPAD_D);
106 config_set_d(CONFIG_KEY_CAMERA_1, DEFAULT_KEY_CAMERA_1);
107 config_set_d(CONFIG_KEY_CAMERA_2, DEFAULT_KEY_CAMERA_2);
108 config_set_d(CONFIG_KEY_CAMERA_3, DEFAULT_KEY_CAMERA_3);
109 config_set_d(CONFIG_KEY_CAMERA_R, DEFAULT_KEY_CAMERA_R);
110 config_set_d(CONFIG_KEY_CAMERA_L, DEFAULT_KEY_CAMERA_L);
111 config_set_d(CONFIG_VIEW_FOV, DEFAULT_VIEW_FOV);
112 config_set_d(CONFIG_VIEW_DP, DEFAULT_VIEW_DP);
113 config_set_d(CONFIG_VIEW_DC, DEFAULT_VIEW_DC);
114 config_set_d(CONFIG_VIEW_DZ, DEFAULT_VIEW_DZ);
115 config_set_d(CONFIG_ROTATE_FAST, DEFAULT_ROTATE_FAST);
116 config_set_d(CONFIG_ROTATE_SLOW, DEFAULT_ROTATE_SLOW);
117 config_set_s(CONFIG_PLAYER, DEFAULT_PLAYER);
118 config_set_s(CONFIG_BALL, DEFAULT_BALL);
119 config_set_s(CONFIG_WIIMOTE_ADDR, DEFAULT_WIIMOTE_ADDR);
120 config_set_s(CONFIG_REPLAY_NAME, DEFAULT_REPLAY_NAME);
121 config_set_d(CONFIG_CHEAT, DEFAULT_CHEAT);
122 config_set_d(CONFIG_STATS, DEFAULT_STATS);
123 config_set_d(CONFIG_UNIFORM, DEFAULT_UNIFORM);
124 config_set_d(CONFIG_KEY_FORWARD, DEFAULT_KEY_FORWARD);
125 config_set_d(CONFIG_KEY_BACKWARD, DEFAULT_KEY_BACKWARD);
126 config_set_d(CONFIG_KEY_LEFT, DEFAULT_KEY_LEFT);
127 config_set_d(CONFIG_KEY_RIGHT, DEFAULT_KEY_RIGHT);
128 config_set_d(CONFIG_KEY_PAUSE, DEFAULT_KEY_PAUSE);
129 config_set_d(CONFIG_KEY_RESTART, DEFAULT_KEY_RESTART);
130 config_set_d(CONFIG_KEY_SCORE_NEXT, DEFAULT_KEY_SCORE_NEXT);
131 config_set_d(CONFIG_SCREENSHOT, DEFAULT_SCREENSHOT);
132 config_set_d(CONFIG_LOCK_GOALS, DEFAULT_LOCK_GOALS);
136 * Scan a NUL-terminated string LINE according to the format
137 * '^<space>?<key><space><value>$' and store pointers to the start of key and
138 * value at DST_KEY and DST_VAL, respectively. No memory is allocated to store
139 * the strings; instead, the memory pointed to by LINE modified in-place as
142 * Return 1 if LINE matches the format, return 0 otherwise.
145 static int scan_key_and_value(char **dst_key, char **dst_val, char *line)
149 char *key, *val, *space;
151 for (key = line; *key && isspace(*key); key++);
161 for (space = key; *space && !isspace(*space); space++);
165 /* NUL-terminate the key, if necessary. */
176 for (val = space; *val && isspace(*val); val++);
192 void config_load(void)
196 if ((fp = fopen(config_user(USER_CONFIG_FILE), "r")))
198 char *line, *key, *val;
200 while (read_line(&line, fp))
202 if (scan_key_and_value(&key, &val, line))
204 if (strcmp(key, "fullscreen") == 0)
205 config_set_d(CONFIG_FULLSCREEN, atoi(val));
206 else if (strcmp(key, "width") == 0)
207 config_set_d(CONFIG_WIDTH, atoi(val));
208 else if (strcmp(key, "height") == 0)
209 config_set_d(CONFIG_HEIGHT, atoi(val));
210 else if (strcmp(key, "stereo") == 0)
211 config_set_d(CONFIG_STEREO, atoi(val));
212 else if (strcmp(key, "camera") == 0)
213 config_set_d(CONFIG_CAMERA, atoi(val));
214 else if (strcmp(key, "textures") == 0)
215 config_set_d(CONFIG_TEXTURES, atoi(val));
216 else if (strcmp(key, "geometry") == 0)
217 config_set_d(CONFIG_GEOMETRY, atoi(val));
218 else if (strcmp(key, "reflection") == 0)
219 config_set_d(CONFIG_REFLECTION, atoi(val));
220 else if (strcmp(key, "multisample") == 0)
221 config_set_d(CONFIG_MULTISAMPLE, atoi(val));
222 else if (strcmp(key, "mipmap") == 0)
223 config_set_d(CONFIG_MIPMAP, atoi(val));
224 else if (strcmp(key, "aniso") == 0)
225 config_set_d(CONFIG_ANISO, atoi(val));
226 else if (strcmp(key, "background") == 0)
227 config_set_d(CONFIG_BACKGROUND, atoi(val));
228 else if (strcmp(key, "shadow") == 0)
229 config_set_d(CONFIG_SHADOW, atoi(val));
230 else if (strcmp(key, "audio_buff") == 0)
231 config_set_d(CONFIG_AUDIO_BUFF, atoi(val));
232 else if (strcmp(key, "mouse_sense") == 0)
233 config_set_d(CONFIG_MOUSE_SENSE, atoi(val));
234 else if (strcmp(key, "mouse_invert") == 0)
235 config_set_d(CONFIG_MOUSE_INVERT, atoi(val));
236 else if (strcmp(key, "vsync") == 0)
237 config_set_d(CONFIG_VSYNC, atoi(val));
238 else if (strcmp(key, "nice") == 0)
239 config_set_d(CONFIG_NICE, atoi(val));
240 else if (strcmp(key, "fps") == 0)
241 config_set_d(CONFIG_FPS, atoi(val));
242 else if (strcmp(key, "sound_volume") == 0)
243 config_set_d(CONFIG_SOUND_VOLUME, atoi(val));
244 else if (strcmp(key, "music_volume") == 0)
245 config_set_d(CONFIG_MUSIC_VOLUME, atoi(val));
246 else if (strcmp(key, "joystick") == 0)
247 config_set_d(CONFIG_JOYSTICK, atoi(val));
248 else if (strcmp(key, "joystick_device") == 0)
249 config_set_d(CONFIG_JOYSTICK_DEVICE, atoi(val));
250 else if (strcmp(key, "joystick_axis_x") == 0)
251 config_set_d(CONFIG_JOYSTICK_AXIS_X, atoi(val));
252 else if (strcmp(key, "joystick_axis_y") == 0)
253 config_set_d(CONFIG_JOYSTICK_AXIS_Y, atoi(val));
254 else if (strcmp(key, "joystick_button_a") == 0)
255 config_set_d(CONFIG_JOYSTICK_BUTTON_A, atoi(val));
256 else if (strcmp(key, "joystick_button_b") == 0)
257 config_set_d(CONFIG_JOYSTICK_BUTTON_B, atoi(val));
258 else if (strcmp(key, "joystick_button_r") == 0)
259 config_set_d(CONFIG_JOYSTICK_BUTTON_R, atoi(val));
260 else if (strcmp(key, "joystick_button_l") == 0)
261 config_set_d(CONFIG_JOYSTICK_BUTTON_L, atoi(val));
262 else if (strcmp(key, "joystick_button_exit") == 0)
263 config_set_d(CONFIG_JOYSTICK_BUTTON_EXIT, atoi(val));
264 else if (strcmp(key, "joystick_camera_1") == 0)
265 config_set_d(CONFIG_JOYSTICK_CAMERA_1, atoi(val));
266 else if (strcmp(key, "joystick_camera_2") == 0)
267 config_set_d(CONFIG_JOYSTICK_CAMERA_2, atoi(val));
268 else if (strcmp(key, "joystick_camera_3") == 0)
269 config_set_d(CONFIG_JOYSTICK_CAMERA_3, atoi(val));
270 else if (strcmp(key, "view_fov") == 0)
271 config_set_d(CONFIG_VIEW_FOV, atoi(val));
272 else if (strcmp(key, "view_dp") == 0)
273 config_set_d(CONFIG_VIEW_DP, atoi(val));
274 else if (strcmp(key, "view_dc") == 0)
275 config_set_d(CONFIG_VIEW_DC, atoi(val));
276 else if (strcmp(key, "view_dz") == 0)
277 config_set_d(CONFIG_VIEW_DZ, atoi(val));
278 else if (strcmp(key, "rotate_fast") == 0)
279 config_set_d(CONFIG_ROTATE_FAST, atoi(val));
280 else if (strcmp(key, "rotate_slow") == 0)
281 config_set_d(CONFIG_ROTATE_SLOW, atoi(val));
283 else if (strcmp(key, "key_forward") == 0)
284 config_key(val, CONFIG_KEY_FORWARD, DEFAULT_KEY_FORWARD);
285 else if (strcmp(key, "key_backward") == 0)
286 config_key(val, CONFIG_KEY_BACKWARD, DEFAULT_KEY_BACKWARD);
287 else if (strcmp(key, "key_left") == 0)
288 config_key(val, CONFIG_KEY_LEFT, DEFAULT_KEY_LEFT);
289 else if (strcmp(key, "key_right") == 0)
290 config_key(val, CONFIG_KEY_RIGHT, DEFAULT_KEY_RIGHT);
292 else if (strcmp(key, "key_camera_1") == 0)
293 config_key(val, CONFIG_KEY_CAMERA_1, DEFAULT_KEY_CAMERA_1);
294 else if (strcmp(key, "key_camera_2") == 0)
295 config_key(val, CONFIG_KEY_CAMERA_2, DEFAULT_KEY_CAMERA_2);
296 else if (strcmp(key, "key_camera_3") == 0)
297 config_key(val, CONFIG_KEY_CAMERA_3, DEFAULT_KEY_CAMERA_3);
298 else if (strcmp(key, "key_camera_r") == 0)
299 config_key(val, CONFIG_KEY_CAMERA_R, DEFAULT_KEY_CAMERA_R);
300 else if (strcmp(key, "key_camera_l") == 0)
301 config_key(val, CONFIG_KEY_CAMERA_L, DEFAULT_KEY_CAMERA_L);
303 else if (strcmp(key, "key_pause") == 0)
304 config_key(val, CONFIG_KEY_PAUSE, DEFAULT_KEY_PAUSE);
305 else if (strcmp(key, "key_restart") == 0)
306 config_key(val, CONFIG_KEY_RESTART, DEFAULT_KEY_RESTART);
308 else if (strcmp(key, "key_score_next") == 0)
309 config_key(val, CONFIG_KEY_SCORE_NEXT, DEFAULT_KEY_SCORE_NEXT);
311 else if (strcmp(key, "player") == 0)
312 config_set_s(CONFIG_PLAYER, val);
313 else if (strcmp(key, "ball_file") == 0)
314 config_set_s(CONFIG_BALL, val);
315 else if (strcmp(key, "wiimote_addr") == 0)
316 config_set_s(CONFIG_WIIMOTE_ADDR, val);
317 else if (strcmp(key, "replay_name") == 0)
318 config_set_s(CONFIG_REPLAY_NAME, val);
320 else if (strcmp(key, "cheat") == 0)
321 config_set_d(CONFIG_CHEAT, atoi(val));
322 else if (strcmp(key, "stats") == 0)
323 config_set_d(CONFIG_STATS, atoi(val));
324 else if (strcmp(key, "uniform") == 0)
325 config_set_d(CONFIG_UNIFORM, atoi(val));
326 else if (strcmp(key, "screenshot") == 0)
327 config_set_d(CONFIG_SCREENSHOT, atoi(val));
328 else if (strcmp(key, "lock_goals") == 0)
329 config_set_d(CONFIG_LOCK_GOALS, atoi(val));
341 void config_save(void)
345 if (dirty && (fp = fopen(config_user(USER_CONFIG_FILE), "w")))
347 fprintf(fp, "fullscreen %d\n",
348 option_d[CONFIG_FULLSCREEN]);
349 fprintf(fp, "width %d\n",
350 option_d[CONFIG_WIDTH]);
351 fprintf(fp, "height %d\n",
352 option_d[CONFIG_HEIGHT]);
353 fprintf(fp, "stereo %d\n",
354 option_d[CONFIG_STEREO]);
355 fprintf(fp, "camera %d\n",
356 option_d[CONFIG_CAMERA]);
357 fprintf(fp, "textures %d\n",
358 option_d[CONFIG_TEXTURES]);
359 fprintf(fp, "geometry %d\n",
360 option_d[CONFIG_GEOMETRY]);
361 fprintf(fp, "reflection %d\n",
362 option_d[CONFIG_REFLECTION]);
363 fprintf(fp, "multisample %d\n",
364 option_d[CONFIG_MULTISAMPLE]);
365 fprintf(fp, "mipmap %d\n",
366 option_d[CONFIG_MIPMAP]);
367 fprintf(fp, "aniso %d\n",
368 option_d[CONFIG_ANISO]);
369 fprintf(fp, "background %d\n",
370 option_d[CONFIG_BACKGROUND]);
371 fprintf(fp, "shadow %d\n",
372 option_d[CONFIG_SHADOW]);
373 fprintf(fp, "audio_buff %d\n",
374 option_d[CONFIG_AUDIO_BUFF]);
375 fprintf(fp, "mouse_sense %d\n",
376 option_d[CONFIG_MOUSE_SENSE]);
377 fprintf(fp, "mouse_invert %d\n",
378 option_d[CONFIG_MOUSE_INVERT]);
379 fprintf(fp, "vsync %d\n",
380 option_d[CONFIG_VSYNC]);
381 fprintf(fp, "nice %d\n",
382 option_d[CONFIG_NICE]);
383 fprintf(fp, "fps %d\n",
384 option_d[CONFIG_FPS]);
385 fprintf(fp, "sound_volume %d\n",
386 option_d[CONFIG_SOUND_VOLUME]);
387 fprintf(fp, "music_volume %d\n",
388 option_d[CONFIG_MUSIC_VOLUME]);
389 fprintf(fp, "joystick %d\n",
390 option_d[CONFIG_JOYSTICK]);
391 fprintf(fp, "joystick_device %d\n",
392 option_d[CONFIG_JOYSTICK_DEVICE]);
393 fprintf(fp, "joystick_axis_x %d\n",
394 option_d[CONFIG_JOYSTICK_AXIS_X]);
395 fprintf(fp, "joystick_axis_y %d\n",
396 option_d[CONFIG_JOYSTICK_AXIS_Y]);
397 fprintf(fp, "joystick_button_a %d\n",
398 option_d[CONFIG_JOYSTICK_BUTTON_A]);
399 fprintf(fp, "joystick_button_b %d\n",
400 option_d[CONFIG_JOYSTICK_BUTTON_B]);
401 fprintf(fp, "joystick_button_r %d\n",
402 option_d[CONFIG_JOYSTICK_BUTTON_R]);
403 fprintf(fp, "joystick_button_l %d\n",
404 option_d[CONFIG_JOYSTICK_BUTTON_L]);
405 fprintf(fp, "joystick_button_exit %d\n",
406 option_d[CONFIG_JOYSTICK_BUTTON_EXIT]);
407 fprintf(fp, "joystick_camera_1 %d\n",
408 option_d[CONFIG_JOYSTICK_CAMERA_1]);
409 fprintf(fp, "joystick_camera_2 %d\n",
410 option_d[CONFIG_JOYSTICK_CAMERA_2]);
411 fprintf(fp, "joystick_camera_3 %d\n",
412 option_d[CONFIG_JOYSTICK_CAMERA_3]);
413 fprintf(fp, "view_fov %d\n",
414 option_d[CONFIG_VIEW_FOV]);
415 fprintf(fp, "view_dp %d\n",
416 option_d[CONFIG_VIEW_DP]);
417 fprintf(fp, "view_dc %d\n",
418 option_d[CONFIG_VIEW_DC]);
419 fprintf(fp, "view_dz %d\n",
420 option_d[CONFIG_VIEW_DZ]);
421 fprintf(fp, "rotate_fast %d\n",
422 option_d[CONFIG_ROTATE_FAST]);
423 fprintf(fp, "rotate_slow %d\n",
424 option_d[CONFIG_ROTATE_SLOW]);
426 fprintf(fp, "key_forward %s\n",
427 SDL_GetKeyName((SDLKey) option_d[CONFIG_KEY_FORWARD]));
428 fprintf(fp, "key_backward %s\n",
429 SDL_GetKeyName((SDLKey) option_d[CONFIG_KEY_BACKWARD]));
430 fprintf(fp, "key_left %s\n",
431 SDL_GetKeyName((SDLKey) option_d[CONFIG_KEY_LEFT]));
432 fprintf(fp, "key_right %s\n",
433 SDL_GetKeyName((SDLKey) option_d[CONFIG_KEY_RIGHT]));
435 fprintf(fp, "key_camera_1 %s\n",
436 SDL_GetKeyName((SDLKey) option_d[CONFIG_KEY_CAMERA_1]));
437 fprintf(fp, "key_camera_2 %s\n",
438 SDL_GetKeyName((SDLKey) option_d[CONFIG_KEY_CAMERA_2]));
439 fprintf(fp, "key_camera_3 %s\n",
440 SDL_GetKeyName((SDLKey) option_d[CONFIG_KEY_CAMERA_3]));
441 fprintf(fp, "key_camera_r %s\n",
442 SDL_GetKeyName((SDLKey) option_d[CONFIG_KEY_CAMERA_R]));
443 fprintf(fp, "key_camera_l %s\n",
444 SDL_GetKeyName((SDLKey) option_d[CONFIG_KEY_CAMERA_L]));
446 fprintf(fp, "key_pause %s\n",
447 SDL_GetKeyName((SDLKey) option_d[CONFIG_KEY_PAUSE]));
448 fprintf(fp, "key_restart %s\n",
449 SDL_GetKeyName((SDLKey) option_d[CONFIG_KEY_RESTART]));
451 fprintf(fp, "key_score_next %s\n",
452 SDL_GetKeyName((SDLKey) option_d[CONFIG_KEY_SCORE_NEXT]));
454 if (strlen(option_s[CONFIG_PLAYER]) > 0)
455 fprintf(fp, "player %s\n", option_s[CONFIG_PLAYER]);
456 if (strlen(option_s[CONFIG_BALL]) > 0)
457 fprintf(fp, "ball_file %s\n", option_s[CONFIG_BALL]);
458 if (strlen(option_s[CONFIG_WIIMOTE_ADDR]) > 0)
459 fprintf(fp, "wiimote_addr %s\n", option_s[CONFIG_WIIMOTE_ADDR]);
460 if (strlen(option_s[CONFIG_REPLAY_NAME]) > 0)
461 fprintf(fp, "replay_name %s\n", option_s[CONFIG_REPLAY_NAME]);
463 fprintf(fp, "stats %d\n", option_d[CONFIG_STATS]);
464 fprintf(fp, "uniform %d\n", option_d[CONFIG_UNIFORM]);
465 fprintf(fp, "screenshot %d\n", option_d[CONFIG_SCREENSHOT]);
466 fprintf(fp, "lock_goals %d\n", option_d[CONFIG_LOCK_GOALS]);
469 fprintf(fp, "cheat %d\n", option_d[CONFIG_CHEAT]);
477 /*---------------------------------------------------------------------------*/
479 int check_extension(const char *needle)
481 const GLubyte *haystack, *c;
483 /* Search for the given string in the OpenGL extension strings. */
485 for (haystack = glGetString(GL_EXTENSIONS); *haystack; haystack++)
487 for (c = (const GLubyte *) needle; *c && *haystack; c++, haystack++)
491 if ((*c == 0) && (*haystack == ' ' || *haystack == '\0'))
498 int config_mode(int f, int w, int h)
500 int stereo = config_get_d(CONFIG_STEREO) ? 1 : 0;
501 int stencil = config_get_d(CONFIG_REFLECTION) ? 1 : 0;
502 int buffers = config_get_d(CONFIG_MULTISAMPLE) ? 1 : 0;
503 int samples = config_get_d(CONFIG_MULTISAMPLE);
504 int vsync = config_get_d(CONFIG_VSYNC) ? 1 : 0;
506 SDL_GL_SetAttribute(SDL_GL_STEREO, stereo);
507 SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, stencil);
508 SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, buffers);
509 SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, samples);
510 SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, vsync);
512 /* Try to set the currently specified mode. */
514 if (SDL_SetVideoMode(w, h, 0, SDL_OPENGL | (f ? SDL_FULLSCREEN : 0)))
516 config_set_d(CONFIG_FULLSCREEN, f);
517 config_set_d(CONFIG_WIDTH, w);
518 config_set_d(CONFIG_HEIGHT, h);
520 glViewport(0, 0, w, h);
521 glClearColor(0.0f, 0.0f, 0.1f, 0.0f);
523 glEnable(GL_NORMALIZE);
524 glEnable(GL_CULL_FACE);
525 glEnable(GL_DEPTH_TEST);
526 glEnable(GL_TEXTURE_2D);
527 glEnable(GL_LIGHTING);
530 glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,
531 GL_SEPARATE_SPECULAR_COLOR);
532 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 1);
534 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
535 glDepthFunc(GL_LEQUAL);
538 * Mac OS X might still need this, because apparently SDL doesn't do
539 * SDL_GL_SWAP_CONTROL on OS X. TODO: investigate.
542 if (vsync) sync_init();
545 /* If GL supports multisample, and SDL got a multisample buffer... */
547 #ifdef GL_ARB_multisample
548 if (check_extension("ARB_multisample"))
550 SDL_GL_GetAttribute(SDL_GL_MULTISAMPLEBUFFERS, &buffers);
552 glEnable(GL_MULTISAMPLE_ARB);
559 /* If the mode failed, try it without stereo. */
563 config_set_d(CONFIG_STEREO, 0);
564 return config_mode(f, w, h);
567 /* If the mode failed, try decreasing the level of multisampling. */
571 config_set_d(CONFIG_MULTISAMPLE, samples / 2);
572 return config_mode(f, w, h);
575 /* If that mode failed, try it without reflections. */
579 config_set_d(CONFIG_REFLECTION, 0);
580 return config_mode(f, w, h);
583 /* If THAT mode failed, punt. */
588 /*---------------------------------------------------------------------------*/
593 static int ticks = 0;
594 static int frames = 0;
596 int config_perf(void)
601 void config_swap(void)
605 SDL_GL_SwapBuffers();
607 /* Accumulate time passed and frames rendered. */
609 dt = (int) SDL_GetTicks() - last;
615 /* Average over 250ms. */
619 /* Round the frames-per-second value to the nearest integer. */
621 double k = 1000.0 * frames / ticks;
625 /* Compute frame time and frames-per-second stats. */
627 fps = (int) ((c - k < k - f) ? c : f);
628 ms = (float) ticks / (float) frames;
630 /* Reset the counters for the next update. */
635 /* Output statistics if configured. */
637 if (option_d[CONFIG_STATS])
638 fprintf(stdout, "%4d %8.4f\n", fps, ms);
642 /*---------------------------------------------------------------------------*/
644 void config_set_d(int i, int d)
650 void config_tgl_d(int i)
652 option_d[i] = (option_d[i] ? 0 : 1);
656 int config_tst_d(int i, int d)
658 return (option_d[i] == d) ? 1 : 0;
661 int config_get_d(int i)
666 /*---------------------------------------------------------------------------*/
668 void config_set_s(int i, const char *src)
673 option_s[i] = strdup(src);
678 void config_get_s(int i, char *dst, int len)
680 strncpy(dst, option_s[i], len);
683 /*---------------------------------------------------------------------------*/
685 static int grabbed = 0;
687 void config_set_grab(int w)
691 SDL_EventState(SDL_MOUSEMOTION, SDL_IGNORE);
693 SDL_WarpMouse(config_get_d(CONFIG_WIDTH) / 2,
694 config_get_d(CONFIG_HEIGHT) / 2);
696 SDL_EventState(SDL_MOUSEMOTION, SDL_ENABLE);
699 SDL_WM_GrabInput(SDL_GRAB_ON);
700 SDL_ShowCursor(SDL_DISABLE);
705 void config_clr_grab(void)
707 SDL_WM_GrabInput(SDL_GRAB_OFF);
708 SDL_ShowCursor(SDL_ENABLE);
712 int config_get_grab(void)
717 /*---------------------------------------------------------------------------*/
719 int config_cheat(void)
721 return config_get_d(CONFIG_CHEAT);
724 void config_set_cheat(void)
726 config_set_d(CONFIG_CHEAT, 1);
729 void config_clr_cheat(void)
731 config_set_d(CONFIG_CHEAT, 0);
734 /*---------------------------------------------------------------------------*/
736 int config_screenshot(void)
738 return ++option_d[CONFIG_SCREENSHOT];
741 /*---------------------------------------------------------------------------*/
743 void config_push_persp(float fov, float n, float f)
747 GLdouble r = fov / 2 * V_PI / 180;
749 GLdouble c = cos(r) / s;
751 GLdouble a = ((GLdouble) option_d[CONFIG_WIDTH] /
752 (GLdouble) option_d[CONFIG_HEIGHT]);
754 glMatrixMode(GL_PROJECTION);
769 m[2][2] = -(f + n) / (f - n);
773 m[3][2] = -2.0 * n * f / (f - n);
776 glMultMatrixd(&m[0][0]);
778 glMatrixMode(GL_MODELVIEW);
781 void config_push_ortho(void)
783 GLdouble w = (GLdouble) option_d[CONFIG_WIDTH];
784 GLdouble h = (GLdouble) option_d[CONFIG_HEIGHT];
786 glMatrixMode(GL_PROJECTION);
790 glOrtho(0.0, w, 0.0, h, -1.0, +1.0);
792 glMatrixMode(GL_MODELVIEW);
795 void config_pop_matrix(void)
797 glMatrixMode(GL_PROJECTION);
801 glMatrixMode(GL_MODELVIEW);
804 void config_clear(void)
806 if (option_d[CONFIG_REFLECTION])
807 glClear(GL_COLOR_BUFFER_BIT |
808 GL_DEPTH_BUFFER_BIT |
809 GL_STENCIL_BUFFER_BIT);
811 glClear(GL_COLOR_BUFFER_BIT |
812 GL_DEPTH_BUFFER_BIT);
815 /*---------------------------------------------------------------------------*/