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;
85 int CONFIG_ROTATE_FAST;
86 int CONFIG_ROTATE_SLOW;
87 int CONFIG_KEY_FORWARD;
88 int CONFIG_KEY_BACKWARD;
92 int CONFIG_KEY_RESTART;
93 int CONFIG_KEY_SCORE_NEXT;
94 int CONFIG_KEY_ROTATE_FAST;
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_VIEW_FOV, "view_fov", 50 },
174 { &CONFIG_VIEW_DP, "view_dp", 75 },
175 { &CONFIG_VIEW_DC, "view_dc", 25 },
176 { &CONFIG_VIEW_DZ, "view_dz", 200 },
177 { &CONFIG_ROTATE_FAST, "rotate_fast", 300 },
178 { &CONFIG_ROTATE_SLOW, "rotate_slow", 150 },
179 { &CONFIG_KEY_FORWARD, "key_forward", SDLK_UP },
180 { &CONFIG_KEY_BACKWARD, "key_backward", SDLK_DOWN },
181 { &CONFIG_KEY_LEFT, "key_left", SDLK_LEFT },
182 { &CONFIG_KEY_RIGHT, "key_right", SDLK_RIGHT },
183 { &CONFIG_KEY_PAUSE, "key_pause", SDLK_ESCAPE },
184 { &CONFIG_KEY_RESTART, "key_restart", SDLK_r },
185 { &CONFIG_KEY_SCORE_NEXT, "key_score_next", SDLK_TAB },
186 { &CONFIG_KEY_ROTATE_FAST, "key_rotate_fast", SDLK_LSHIFT },
187 { &CONFIG_CHEAT, "cheat", 0 },
188 { &CONFIG_STATS, "stats", 0 },
189 { &CONFIG_UNIFORM, "uniform", 0 },
190 { &CONFIG_SCREENSHOT, "screenshot", 0 },
191 { &CONFIG_LOCK_GOALS, "lock_goals", 0 }
201 { &CONFIG_PLAYER, "player", "" },
202 { &CONFIG_BALL_FILE, "ball_file", "ball/basic-ball/basic-ball" },
203 { &CONFIG_WIIMOTE_ADDR, "wiimote_addr", "" },
204 { &CONFIG_REPLAY_NAME, "replay_name", "%s-%l" }
207 static int dirty = 0;
209 /*---------------------------------------------------------------------------*/
211 static void config_key(const char *s, int i)
215 config_set_d(i, option_d[i].def);
217 for (c = 0; c < SDLK_LAST; c++)
218 if (strcmp(s, SDL_GetKeyName((SDLKey) c)) == 0)
225 /*---------------------------------------------------------------------------*/
227 static void config_mouse(const char *s, int i)
229 if (strcmp(s, "none") == 0)
231 else if (strcmp(s, "left") == 0)
232 config_set_d(i, SDL_BUTTON_LEFT);
233 else if (strcmp(s, "right") == 0)
234 config_set_d(i, SDL_BUTTON_RIGHT);
235 else if (strcmp(s, "wheelup") == 0)
236 config_set_d(i, SDL_BUTTON_WHEELUP);
237 else if (strcmp(s, "middle") == 0)
238 config_set_d(i, SDL_BUTTON_MIDDLE);
239 else if (strcmp(s, "wheeldown") == 0)
240 config_set_d(i, SDL_BUTTON_WHEELDOWN);
242 config_set_d(i, atoi(s));
245 static const char *config_mouse_name(int b)
247 static char buff[sizeof ("256")];
249 sprintf(buff, "%d", b);
253 case 0: return "none"; break;
254 case SDL_BUTTON_LEFT: return "left"; break;
255 case SDL_BUTTON_RIGHT: return "right"; break;
256 case SDL_BUTTON_WHEELUP: return "wheelup"; break;
257 case SDL_BUTTON_MIDDLE: return "middle"; break;
258 case SDL_BUTTON_WHEELDOWN: return "wheeldown"; break;
259 default: return buff; break;
263 /*---------------------------------------------------------------------------*/
265 void config_init(void)
270 * Store index of each option in its associated config symbol and
271 * initialise current values with defaults.
274 for (i = 0; i < ARRAYSIZE(option_d); i++)
276 *option_d[i].sym = i;
277 config_set_d(i, option_d[i].def);
280 for (i = 0; i < ARRAYSIZE(option_s); i++)
282 *option_s[i].sym = i;
283 config_set_s(i, option_s[i].def);
288 * Scan a NUL-terminated string LINE according to the format
289 * '^<space>?<key><space><value>$' and store pointers to the start of key and
290 * value at DST_KEY and DST_VAL, respectively. No memory is allocated to store
291 * the strings; instead, the memory pointed to by LINE modified in-place as
294 * Return 1 if LINE matches the format, return 0 otherwise.
297 static int scan_key_and_value(char **dst_key, char **dst_val, char *line)
301 char *key, *val, *space;
303 for (key = line; *key && isspace(*key); key++);
313 for (space = key; *space && !isspace(*space); space++);
317 /* NUL-terminate the key, if necessary. */
328 for (val = space; *val && isspace(*val); val++);
344 void config_load(void)
348 if ((fh = fs_open(USER_CONFIG_FILE, "r")))
350 char *line, *key, *val;
352 while (read_line(&line, fh))
354 if (scan_key_and_value(&key, &val, line))
358 /* Look up an integer option by that name. */
360 for (i = 0; i < ARRAYSIZE(option_d); i++)
362 if (strcmp(key, option_d[i].name) == 0)
364 /* Translate some strings to integers. */
366 if (i == CONFIG_MOUSE_CAMERA_1 ||
367 i == CONFIG_MOUSE_CAMERA_2 ||
368 i == CONFIG_MOUSE_CAMERA_3 ||
369 i == CONFIG_MOUSE_CAMERA_TOGGLE ||
370 i == CONFIG_MOUSE_CAMERA_L ||
371 i == CONFIG_MOUSE_CAMERA_R)
373 config_mouse(val, i);
375 else if (i == CONFIG_KEY_FORWARD ||
376 i == CONFIG_KEY_BACKWARD ||
377 i == CONFIG_KEY_LEFT ||
378 i == CONFIG_KEY_RIGHT ||
379 i == CONFIG_KEY_CAMERA_1 ||
380 i == CONFIG_KEY_CAMERA_2 ||
381 i == CONFIG_KEY_CAMERA_3 ||
382 i == CONFIG_KEY_CAMERA_TOGGLE ||
383 i == CONFIG_KEY_CAMERA_R ||
384 i == CONFIG_KEY_CAMERA_L ||
385 i == CONFIG_KEY_PAUSE ||
386 i == CONFIG_KEY_RESTART ||
387 i == CONFIG_KEY_SCORE_NEXT ||
388 i == CONFIG_KEY_ROTATE_FAST)
393 config_set_d(i, atoi(val));
401 /* Look up a string option by that name.*/
403 for (i = 0; i < ARRAYSIZE(option_s); i++)
405 if (strcmp(key, option_s[i].name) == 0)
407 config_set_s(i, val);
420 void config_save(void)
424 if (dirty && (fh = fs_open(USER_CONFIG_FILE, "w")))
428 /* Write out integer options. */
430 for (i = 0; i < ARRAYSIZE(option_d); i++)
432 const char *s = NULL;
434 /* Translate some integers to strings. */
436 if (i == CONFIG_MOUSE_CAMERA_1 ||
437 i == CONFIG_MOUSE_CAMERA_2 ||
438 i == CONFIG_MOUSE_CAMERA_3 ||
439 i == CONFIG_MOUSE_CAMERA_TOGGLE ||
440 i == CONFIG_MOUSE_CAMERA_L ||
441 i == CONFIG_MOUSE_CAMERA_R)
443 s = config_mouse_name(option_d[i].cur);
445 else if (i == CONFIG_KEY_FORWARD ||
446 i == CONFIG_KEY_BACKWARD ||
447 i == CONFIG_KEY_LEFT ||
448 i == CONFIG_KEY_RIGHT ||
449 i == CONFIG_KEY_CAMERA_1 ||
450 i == CONFIG_KEY_CAMERA_2 ||
451 i == CONFIG_KEY_CAMERA_3 ||
452 i == CONFIG_KEY_CAMERA_TOGGLE ||
453 i == CONFIG_KEY_CAMERA_R ||
454 i == CONFIG_KEY_CAMERA_L ||
455 i == CONFIG_KEY_PAUSE ||
456 i == CONFIG_KEY_RESTART ||
457 i == CONFIG_KEY_SCORE_NEXT ||
458 i == CONFIG_KEY_ROTATE_FAST)
460 s = SDL_GetKeyName((SDLKey) option_d[i].cur);
462 else if (i == CONFIG_CHEAT)
469 fs_printf(fh, "%-25s %s\n", option_d[i].name, s);
471 fs_printf(fh, "%-25s %d\n", option_d[i].name, option_d[i].cur);
474 /* Write out string options. */
476 for (i = 0; i < ARRAYSIZE(option_s); i++)
478 if (option_s[i].cur && *option_s[i].cur)
479 fs_printf(fh, "%-25s %s\n", option_s[i].name, option_s[i].cur);
488 /*---------------------------------------------------------------------------*/
490 void config_set_d(int i, int d)
496 void config_tgl_d(int i)
498 option_d[i].cur = (option_d[i].cur ? 0 : 1);
502 int config_tst_d(int i, int d)
504 return (option_d[i].cur == d) ? 1 : 0;
507 int config_get_d(int i)
509 return option_d[i].cur;
512 /*---------------------------------------------------------------------------*/
514 void config_set_s(int i, const char *src)
517 free(option_s[i].cur);
519 option_s[i].cur = strdup(src);
524 const char *config_get_s(int i)
526 return option_s[i].cur;
529 /*---------------------------------------------------------------------------*/
531 int config_cheat(void)
533 return config_get_d(CONFIG_CHEAT);
536 void config_set_cheat(void)
538 config_set_d(CONFIG_CHEAT, 1);
541 void config_clr_cheat(void)
543 config_set_d(CONFIG_CHEAT, 0);
546 /*---------------------------------------------------------------------------*/
548 int config_screenshot(void)
550 return ++option_d[CONFIG_SCREENSHOT].cur;
553 /*---------------------------------------------------------------------------*/