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.
25 /*---------------------------------------------------------------------------*/
27 /* Integer options. */
29 int CONFIG_FULLSCREEN;
36 int CONFIG_REFLECTION;
37 int CONFIG_MULTISAMPLE;
40 int CONFIG_BACKGROUND;
42 int CONFIG_AUDIO_BUFF;
43 int CONFIG_MOUSE_SENSE;
44 int CONFIG_MOUSE_INVERT;
46 int CONFIG_MOUSE_CAMERA_1;
47 int CONFIG_MOUSE_CAMERA_2;
48 int CONFIG_MOUSE_CAMERA_3;
49 int CONFIG_MOUSE_CAMERA_TOGGLE;
50 int CONFIG_MOUSE_CAMERA_L;
51 int CONFIG_MOUSE_CAMERA_R;
54 int CONFIG_SOUND_VOLUME;
55 int CONFIG_MUSIC_VOLUME;
57 int CONFIG_JOYSTICK_DEVICE;
58 int CONFIG_JOYSTICK_AXIS_X;
59 int CONFIG_JOYSTICK_AXIS_Y;
60 int CONFIG_JOYSTICK_AXIS_U;
61 int CONFIG_JOYSTICK_BUTTON_A;
62 int CONFIG_JOYSTICK_BUTTON_B;
63 int CONFIG_JOYSTICK_BUTTON_R;
64 int CONFIG_JOYSTICK_BUTTON_L;
65 int CONFIG_JOYSTICK_BUTTON_EXIT;
66 int CONFIG_JOYSTICK_CAMERA_1;
67 int CONFIG_JOYSTICK_CAMERA_2;
68 int CONFIG_JOYSTICK_CAMERA_3;
69 int CONFIG_JOYSTICK_DPAD_L;
70 int CONFIG_JOYSTICK_DPAD_R;
71 int CONFIG_JOYSTICK_DPAD_U;
72 int CONFIG_JOYSTICK_DPAD_D;
73 int CONFIG_JOYSTICK_CAMERA_TOGGLE;
74 int CONFIG_JOYSTICK_ROTATE_FAST;
75 int CONFIG_KEY_CAMERA_1;
76 int CONFIG_KEY_CAMERA_2;
77 int CONFIG_KEY_CAMERA_3;
78 int CONFIG_KEY_CAMERA_TOGGLE;
79 int CONFIG_KEY_CAMERA_R;
80 int CONFIG_KEY_CAMERA_L;
81 int CONFIG_KEY_FORWARD;
82 int CONFIG_KEY_BACKWARD;
86 int CONFIG_KEY_RESTART;
87 int CONFIG_KEY_SCORE_NEXT;
88 int CONFIG_KEY_ROTATE_FAST;
93 int CONFIG_ROTATE_FAST;
94 int CONFIG_ROTATE_SLOW;
98 int CONFIG_SCREENSHOT;
99 int CONFIG_LOCK_GOALS;
101 /* String options. */
104 int CONFIG_BALL_FILE;
105 int CONFIG_WIIMOTE_ADDR;
106 int CONFIG_REPLAY_NAME;
108 /*---------------------------------------------------------------------------*/
117 { &CONFIG_FULLSCREEN, "fullscreen", 0 },
118 { &CONFIG_WIDTH, "width", 800 },
119 { &CONFIG_HEIGHT, "height", 600 },
120 { &CONFIG_STEREO, "stereo", 0 },
121 { &CONFIG_CAMERA, "camera", 0 },
122 { &CONFIG_TEXTURES, "textures", 1 },
123 { &CONFIG_GEOMETRY, "geometry", 1 },
124 { &CONFIG_REFLECTION, "reflection", 1 },
125 { &CONFIG_MULTISAMPLE, "multisample", 0 },
126 { &CONFIG_MIPMAP, "mipmap", 0 },
127 { &CONFIG_ANISO, "aniso", 0 },
128 { &CONFIG_BACKGROUND, "background", 1 },
129 { &CONFIG_SHADOW, "shadow", 1 },
130 { &CONFIG_AUDIO_BUFF, "audio_buff", AUDIO_BUFF_HI },
131 { &CONFIG_MOUSE_SENSE, "mouse_sense", 300 },
132 { &CONFIG_MOUSE_INVERT, "mouse_invert", 0 },
133 { &CONFIG_VSYNC, "vsync", 1 },
135 { &CONFIG_MOUSE_CAMERA_1, "mouse_camera_1", 0 },
136 { &CONFIG_MOUSE_CAMERA_2, "mouse_camera_2", 0 },
137 { &CONFIG_MOUSE_CAMERA_3, "mouse_camera_3", 0 },
138 { &CONFIG_MOUSE_CAMERA_TOGGLE, "mouse_camera_toggle", SDL_BUTTON_MIDDLE },
139 { &CONFIG_MOUSE_CAMERA_L, "mouse_camera_l", SDL_BUTTON_LEFT },
140 { &CONFIG_MOUSE_CAMERA_R, "mouse_camera_r", SDL_BUTTON_RIGHT },
142 { &CONFIG_NICE, "nice", 0 },
143 { &CONFIG_FPS, "fps", 0 },
144 { &CONFIG_SOUND_VOLUME, "sound_volume", 10 },
145 { &CONFIG_MUSIC_VOLUME, "music_volume", 6 },
147 { &CONFIG_JOYSTICK, "joystick", 1 },
148 { &CONFIG_JOYSTICK_DEVICE, "joystick_device", 0 },
149 { &CONFIG_JOYSTICK_AXIS_X, "joystick_axis_x", 0 },
150 { &CONFIG_JOYSTICK_AXIS_Y, "joystick_axis_y", 1 },
151 { &CONFIG_JOYSTICK_AXIS_U, "joystick_axis_u", 2 },
152 { &CONFIG_JOYSTICK_BUTTON_A, "joystick_button_a", 0 },
153 { &CONFIG_JOYSTICK_BUTTON_B, "joystick_button_b", 1 },
154 { &CONFIG_JOYSTICK_BUTTON_R, "joystick_button_r", 2 },
155 { &CONFIG_JOYSTICK_BUTTON_L, "joystick_button_l", 3 },
156 { &CONFIG_JOYSTICK_BUTTON_EXIT, "joystick_button_exit", 4 },
157 { &CONFIG_JOYSTICK_CAMERA_1, "joystick_camera_1", 5 },
158 { &CONFIG_JOYSTICK_CAMERA_2, "joystick_camera_2", 6 },
159 { &CONFIG_JOYSTICK_CAMERA_3, "joystick_camera_3", 7 },
160 { &CONFIG_JOYSTICK_DPAD_L, "joystick_dpad_l", 8 },
161 { &CONFIG_JOYSTICK_DPAD_R, "joystick_dpad_r", 9 },
162 { &CONFIG_JOYSTICK_DPAD_U, "joystick_dpad_u", 10 },
163 { &CONFIG_JOYSTICK_DPAD_D, "joystick_dpad_d", 11 },
164 { &CONFIG_JOYSTICK_CAMERA_TOGGLE, "joystick_camera_toggle", 12 },
165 { &CONFIG_JOYSTICK_ROTATE_FAST, "joystick_rotate_fast", 13 },
167 { &CONFIG_KEY_CAMERA_1, "key_camera_1", SDLK_F1 },
168 { &CONFIG_KEY_CAMERA_2, "key_camera_2", SDLK_F2 },
169 { &CONFIG_KEY_CAMERA_3, "key_camera_3", SDLK_F3 },
170 { &CONFIG_KEY_CAMERA_TOGGLE, "key_camera_toggle", SDLK_e },
171 { &CONFIG_KEY_CAMERA_R, "key_camera_r", SDLK_d },
172 { &CONFIG_KEY_CAMERA_L, "key_camera_l", SDLK_s },
173 { &CONFIG_KEY_FORWARD, "key_forward", SDLK_UP },
174 { &CONFIG_KEY_BACKWARD, "key_backward", SDLK_DOWN },
175 { &CONFIG_KEY_LEFT, "key_left", SDLK_LEFT },
176 { &CONFIG_KEY_RIGHT, "key_right", SDLK_RIGHT },
177 { &CONFIG_KEY_PAUSE, "key_pause", SDLK_ESCAPE },
178 { &CONFIG_KEY_RESTART, "key_restart", SDLK_r },
179 { &CONFIG_KEY_SCORE_NEXT, "key_score_next", SDLK_TAB },
180 { &CONFIG_KEY_ROTATE_FAST, "key_rotate_fast", SDLK_LSHIFT },
182 { &CONFIG_VIEW_FOV, "view_fov", 50 },
183 { &CONFIG_VIEW_DP, "view_dp", 75 },
184 { &CONFIG_VIEW_DC, "view_dc", 25 },
185 { &CONFIG_VIEW_DZ, "view_dz", 200 },
186 { &CONFIG_ROTATE_FAST, "rotate_fast", 300 },
187 { &CONFIG_ROTATE_SLOW, "rotate_slow", 150 },
188 { &CONFIG_CHEAT, "cheat", 0 },
189 { &CONFIG_STATS, "stats", 0 },
190 { &CONFIG_UNIFORM, "uniform", 0 },
191 { &CONFIG_SCREENSHOT, "screenshot", 0 },
192 { &CONFIG_LOCK_GOALS, "lock_goals", 0 }
202 { &CONFIG_PLAYER, "player", "" },
203 { &CONFIG_BALL_FILE, "ball_file", "ball/basic-ball/basic-ball" },
204 { &CONFIG_WIIMOTE_ADDR, "wiimote_addr", "" },
205 { &CONFIG_REPLAY_NAME, "replay_name", "%s-%l" }
208 static int dirty = 0;
210 /*---------------------------------------------------------------------------*/
212 static void config_key(const char *s, int i)
216 config_set_d(i, option_d[i].def);
218 for (c = 0; c < SDLK_LAST; c++)
219 if (strcmp(s, SDL_GetKeyName((SDLKey) c)) == 0)
226 /*---------------------------------------------------------------------------*/
228 static void config_mouse(const char *s, int i)
230 if (strcmp(s, "none") == 0)
232 else if (strcmp(s, "left") == 0)
233 config_set_d(i, SDL_BUTTON_LEFT);
234 else if (strcmp(s, "right") == 0)
235 config_set_d(i, SDL_BUTTON_RIGHT);
236 else if (strcmp(s, "wheelup") == 0)
237 config_set_d(i, SDL_BUTTON_WHEELUP);
238 else if (strcmp(s, "middle") == 0)
239 config_set_d(i, SDL_BUTTON_MIDDLE);
240 else if (strcmp(s, "wheeldown") == 0)
241 config_set_d(i, SDL_BUTTON_WHEELDOWN);
243 config_set_d(i, atoi(s));
246 static const char *config_mouse_name(int b)
248 static char buff[sizeof ("256")];
250 sprintf(buff, "%d", b);
254 case 0: return "none"; break;
255 case SDL_BUTTON_LEFT: return "left"; break;
256 case SDL_BUTTON_RIGHT: return "right"; break;
257 case SDL_BUTTON_WHEELUP: return "wheelup"; break;
258 case SDL_BUTTON_MIDDLE: return "middle"; break;
259 case SDL_BUTTON_WHEELDOWN: return "wheeldown"; break;
260 default: return buff; break;
264 /*---------------------------------------------------------------------------*/
266 void config_init(void)
271 * Store index of each option in its associated config symbol and
272 * initialise current values with defaults.
275 for (i = 0; i < ARRAYSIZE(option_d); i++)
277 *option_d[i].sym = i;
278 config_set_d(i, option_d[i].def);
281 for (i = 0; i < ARRAYSIZE(option_s); i++)
283 *option_s[i].sym = i;
284 config_set_s(i, option_s[i].def);
289 * Scan a NUL-terminated string LINE according to the format
290 * '^<space>?<key><space><value>$' and store pointers to the start of key and
291 * value at DST_KEY and DST_VAL, respectively. No memory is allocated to store
292 * the strings; instead, the memory pointed to by LINE modified in-place as
295 * Return 1 if LINE matches the format, return 0 otherwise.
298 static int scan_key_and_value(char **dst_key, char **dst_val, char *line)
302 char *key, *val, *space;
304 for (key = line; *key && isspace(*key); key++);
314 for (space = key; *space && !isspace(*space); space++);
318 /* NUL-terminate the key, if necessary. */
329 for (val = space; *val && isspace(*val); val++);
345 void config_load(void)
349 if ((fh = fs_open(USER_CONFIG_FILE, "r")))
351 char *line, *key, *val;
353 while (read_line(&line, fh))
355 if (scan_key_and_value(&key, &val, line))
359 /* Look up an integer option by that name. */
361 for (i = 0; i < ARRAYSIZE(option_d); i++)
363 if (strcmp(key, option_d[i].name) == 0)
365 /* Translate some strings to integers. */
367 if (i == CONFIG_MOUSE_CAMERA_1 ||
368 i == CONFIG_MOUSE_CAMERA_2 ||
369 i == CONFIG_MOUSE_CAMERA_3 ||
370 i == CONFIG_MOUSE_CAMERA_TOGGLE ||
371 i == CONFIG_MOUSE_CAMERA_L ||
372 i == CONFIG_MOUSE_CAMERA_R)
374 config_mouse(val, i);
376 else if (i == CONFIG_KEY_FORWARD ||
377 i == CONFIG_KEY_BACKWARD ||
378 i == CONFIG_KEY_LEFT ||
379 i == CONFIG_KEY_RIGHT ||
380 i == CONFIG_KEY_CAMERA_1 ||
381 i == CONFIG_KEY_CAMERA_2 ||
382 i == CONFIG_KEY_CAMERA_3 ||
383 i == CONFIG_KEY_CAMERA_TOGGLE ||
384 i == CONFIG_KEY_CAMERA_R ||
385 i == CONFIG_KEY_CAMERA_L ||
386 i == CONFIG_KEY_PAUSE ||
387 i == CONFIG_KEY_RESTART ||
388 i == CONFIG_KEY_SCORE_NEXT ||
389 i == CONFIG_KEY_ROTATE_FAST)
394 config_set_d(i, atoi(val));
402 /* Look up a string option by that name.*/
404 for (i = 0; i < ARRAYSIZE(option_s); i++)
406 if (strcmp(key, option_s[i].name) == 0)
408 config_set_s(i, val);
421 void config_save(void)
425 if (dirty && (fh = fs_open(USER_CONFIG_FILE, "w")))
429 /* Write out integer options. */
431 for (i = 0; i < ARRAYSIZE(option_d); i++)
433 const char *s = NULL;
435 /* Translate some integers to strings. */
437 if (i == CONFIG_MOUSE_CAMERA_1 ||
438 i == CONFIG_MOUSE_CAMERA_2 ||
439 i == CONFIG_MOUSE_CAMERA_3 ||
440 i == CONFIG_MOUSE_CAMERA_TOGGLE ||
441 i == CONFIG_MOUSE_CAMERA_L ||
442 i == CONFIG_MOUSE_CAMERA_R)
444 s = config_mouse_name(option_d[i].cur);
446 else if (i == CONFIG_KEY_FORWARD ||
447 i == CONFIG_KEY_BACKWARD ||
448 i == CONFIG_KEY_LEFT ||
449 i == CONFIG_KEY_RIGHT ||
450 i == CONFIG_KEY_CAMERA_1 ||
451 i == CONFIG_KEY_CAMERA_2 ||
452 i == CONFIG_KEY_CAMERA_3 ||
453 i == CONFIG_KEY_CAMERA_TOGGLE ||
454 i == CONFIG_KEY_CAMERA_R ||
455 i == CONFIG_KEY_CAMERA_L ||
456 i == CONFIG_KEY_PAUSE ||
457 i == CONFIG_KEY_RESTART ||
458 i == CONFIG_KEY_SCORE_NEXT ||
459 i == CONFIG_KEY_ROTATE_FAST)
461 s = SDL_GetKeyName((SDLKey) option_d[i].cur);
463 else if (i == CONFIG_CHEAT)
470 fs_printf(fh, "%-25s %s\n", option_d[i].name, s);
472 fs_printf(fh, "%-25s %d\n", option_d[i].name, option_d[i].cur);
475 /* Write out string options. */
477 for (i = 0; i < ARRAYSIZE(option_s); i++)
479 if (option_s[i].cur && *option_s[i].cur)
480 fs_printf(fh, "%-25s %s\n", option_s[i].name, option_s[i].cur);
489 /*---------------------------------------------------------------------------*/
491 void config_set_d(int i, int d)
497 void config_tgl_d(int i)
499 option_d[i].cur = (option_d[i].cur ? 0 : 1);
503 int config_tst_d(int i, int d)
505 return (option_d[i].cur == d) ? 1 : 0;
508 int config_get_d(int i)
510 return option_d[i].cur;
513 /*---------------------------------------------------------------------------*/
515 void config_set_s(int i, const char *src)
518 free(option_s[i].cur);
520 option_s[i].cur = strdup(src);
525 const char *config_get_s(int i)
527 return option_s[i].cur;
530 /*---------------------------------------------------------------------------*/
532 int config_cheat(void)
534 return config_get_d(CONFIG_CHEAT);
537 void config_set_cheat(void)
539 config_set_d(CONFIG_CHEAT, 1);
542 void config_clr_cheat(void)
544 config_set_d(CONFIG_CHEAT, 0);
547 /*---------------------------------------------------------------------------*/
549 int config_screenshot(void)
551 return ++option_d[CONFIG_SCREENSHOT].cur;
554 /*---------------------------------------------------------------------------*/