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_AXIS_X_INVERT;
62 int CONFIG_JOYSTICK_AXIS_Y_INVERT;
63 int CONFIG_JOYSTICK_AXIS_U_INVERT;
64 int CONFIG_JOYSTICK_BUTTON_A;
65 int CONFIG_JOYSTICK_BUTTON_B;
66 int CONFIG_JOYSTICK_BUTTON_R;
67 int CONFIG_JOYSTICK_BUTTON_L;
68 int CONFIG_JOYSTICK_BUTTON_EXIT;
69 int CONFIG_JOYSTICK_CAMERA_1;
70 int CONFIG_JOYSTICK_CAMERA_2;
71 int CONFIG_JOYSTICK_CAMERA_3;
72 int CONFIG_JOYSTICK_DPAD_L;
73 int CONFIG_JOYSTICK_DPAD_R;
74 int CONFIG_JOYSTICK_DPAD_U;
75 int CONFIG_JOYSTICK_DPAD_D;
76 int CONFIG_JOYSTICK_CAMERA_TOGGLE;
77 int CONFIG_JOYSTICK_ROTATE_FAST;
78 int CONFIG_KEY_CAMERA_1;
79 int CONFIG_KEY_CAMERA_2;
80 int CONFIG_KEY_CAMERA_3;
81 int CONFIG_KEY_CAMERA_TOGGLE;
82 int CONFIG_KEY_CAMERA_R;
83 int CONFIG_KEY_CAMERA_L;
84 int CONFIG_KEY_FORWARD;
85 int CONFIG_KEY_BACKWARD;
89 int CONFIG_KEY_RESTART;
90 int CONFIG_KEY_SCORE_NEXT;
91 int CONFIG_KEY_ROTATE_FAST;
96 int CONFIG_ROTATE_FAST;
97 int CONFIG_ROTATE_SLOW;
101 int CONFIG_SCREENSHOT;
102 int CONFIG_LOCK_GOALS;
104 /* String options. */
107 int CONFIG_BALL_FILE;
108 int CONFIG_WIIMOTE_ADDR;
109 int CONFIG_REPLAY_NAME;
111 /*---------------------------------------------------------------------------*/
120 { &CONFIG_FULLSCREEN, "fullscreen", 0 },
121 { &CONFIG_WIDTH, "width", 800 },
122 { &CONFIG_HEIGHT, "height", 600 },
123 { &CONFIG_STEREO, "stereo", 0 },
124 { &CONFIG_CAMERA, "camera", 0 },
125 { &CONFIG_TEXTURES, "textures", 1 },
126 { &CONFIG_GEOMETRY, "geometry", 1 },
127 { &CONFIG_REFLECTION, "reflection", 1 },
128 { &CONFIG_MULTISAMPLE, "multisample", 0 },
129 { &CONFIG_MIPMAP, "mipmap", 0 },
130 { &CONFIG_ANISO, "aniso", 0 },
131 { &CONFIG_BACKGROUND, "background", 1 },
132 { &CONFIG_SHADOW, "shadow", 1 },
133 { &CONFIG_AUDIO_BUFF, "audio_buff", AUDIO_BUFF_HI },
134 { &CONFIG_MOUSE_SENSE, "mouse_sense", 300 },
135 { &CONFIG_MOUSE_INVERT, "mouse_invert", 0 },
136 { &CONFIG_VSYNC, "vsync", 1 },
138 { &CONFIG_MOUSE_CAMERA_1, "mouse_camera_1", 0 },
139 { &CONFIG_MOUSE_CAMERA_2, "mouse_camera_2", 0 },
140 { &CONFIG_MOUSE_CAMERA_3, "mouse_camera_3", 0 },
141 { &CONFIG_MOUSE_CAMERA_TOGGLE, "mouse_camera_toggle", SDL_BUTTON_MIDDLE },
142 { &CONFIG_MOUSE_CAMERA_L, "mouse_camera_l", SDL_BUTTON_LEFT },
143 { &CONFIG_MOUSE_CAMERA_R, "mouse_camera_r", SDL_BUTTON_RIGHT },
145 { &CONFIG_NICE, "nice", 0 },
146 { &CONFIG_FPS, "fps", 0 },
147 { &CONFIG_SOUND_VOLUME, "sound_volume", 10 },
148 { &CONFIG_MUSIC_VOLUME, "music_volume", 6 },
150 { &CONFIG_JOYSTICK, "joystick", 1 },
151 { &CONFIG_JOYSTICK_DEVICE, "joystick_device", 0 },
152 { &CONFIG_JOYSTICK_AXIS_X, "joystick_axis_x", 0 },
153 { &CONFIG_JOYSTICK_AXIS_Y, "joystick_axis_y", 1 },
154 { &CONFIG_JOYSTICK_AXIS_U, "joystick_axis_u", 2 },
155 { &CONFIG_JOYSTICK_AXIS_X_INVERT, "joystick_axis_x_invert", 0 },
156 { &CONFIG_JOYSTICK_AXIS_Y_INVERT, "joystick_axis_y_invert", 0 },
157 { &CONFIG_JOYSTICK_AXIS_U_INVERT, "joystick_axis_u_invert", 0 },
158 { &CONFIG_JOYSTICK_BUTTON_A, "joystick_button_a", 0 },
159 { &CONFIG_JOYSTICK_BUTTON_B, "joystick_button_b", 1 },
160 { &CONFIG_JOYSTICK_BUTTON_R, "joystick_button_r", 2 },
161 { &CONFIG_JOYSTICK_BUTTON_L, "joystick_button_l", 3 },
162 { &CONFIG_JOYSTICK_BUTTON_EXIT, "joystick_button_exit", 4 },
163 { &CONFIG_JOYSTICK_CAMERA_1, "joystick_camera_1", 5 },
164 { &CONFIG_JOYSTICK_CAMERA_2, "joystick_camera_2", 6 },
165 { &CONFIG_JOYSTICK_CAMERA_3, "joystick_camera_3", 7 },
166 { &CONFIG_JOYSTICK_DPAD_L, "joystick_dpad_l", 8 },
167 { &CONFIG_JOYSTICK_DPAD_R, "joystick_dpad_r", 9 },
168 { &CONFIG_JOYSTICK_DPAD_U, "joystick_dpad_u", 10 },
169 { &CONFIG_JOYSTICK_DPAD_D, "joystick_dpad_d", 11 },
170 { &CONFIG_JOYSTICK_CAMERA_TOGGLE, "joystick_camera_toggle", 12 },
171 { &CONFIG_JOYSTICK_ROTATE_FAST, "joystick_rotate_fast", 13 },
173 { &CONFIG_KEY_CAMERA_1, "key_camera_1", SDLK_F1 },
174 { &CONFIG_KEY_CAMERA_2, "key_camera_2", SDLK_F2 },
175 { &CONFIG_KEY_CAMERA_3, "key_camera_3", SDLK_F3 },
176 { &CONFIG_KEY_CAMERA_TOGGLE, "key_camera_toggle", SDLK_e },
177 { &CONFIG_KEY_CAMERA_R, "key_camera_r", SDLK_d },
178 { &CONFIG_KEY_CAMERA_L, "key_camera_l", SDLK_s },
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 },
188 { &CONFIG_VIEW_FOV, "view_fov", 50 },
189 { &CONFIG_VIEW_DP, "view_dp", 75 },
190 { &CONFIG_VIEW_DC, "view_dc", 25 },
191 { &CONFIG_VIEW_DZ, "view_dz", 200 },
192 { &CONFIG_ROTATE_FAST, "rotate_fast", 300 },
193 { &CONFIG_ROTATE_SLOW, "rotate_slow", 150 },
194 { &CONFIG_CHEAT, "cheat", 0 },
195 { &CONFIG_STATS, "stats", 0 },
196 { &CONFIG_UNIFORM, "uniform", 0 },
197 { &CONFIG_SCREENSHOT, "screenshot", 0 },
198 { &CONFIG_LOCK_GOALS, "lock_goals", 0 }
208 { &CONFIG_PLAYER, "player", "" },
209 { &CONFIG_BALL_FILE, "ball_file", "ball/basic-ball/basic-ball" },
210 { &CONFIG_WIIMOTE_ADDR, "wiimote_addr", "" },
211 { &CONFIG_REPLAY_NAME, "replay_name", "%s-%l" }
214 static int dirty = 0;
216 /*---------------------------------------------------------------------------*/
218 static void config_key(const char *s, int i)
222 config_set_d(i, option_d[i].def);
224 for (c = 0; c < SDLK_LAST; c++)
225 if (strcmp(s, SDL_GetKeyName((SDLKey) c)) == 0)
232 /*---------------------------------------------------------------------------*/
234 static void config_mouse(const char *s, int i)
236 if (strcmp(s, "none") == 0)
238 else if (strcmp(s, "left") == 0)
239 config_set_d(i, SDL_BUTTON_LEFT);
240 else if (strcmp(s, "right") == 0)
241 config_set_d(i, SDL_BUTTON_RIGHT);
242 else if (strcmp(s, "wheelup") == 0)
243 config_set_d(i, SDL_BUTTON_WHEELUP);
244 else if (strcmp(s, "middle") == 0)
245 config_set_d(i, SDL_BUTTON_MIDDLE);
246 else if (strcmp(s, "wheeldown") == 0)
247 config_set_d(i, SDL_BUTTON_WHEELDOWN);
249 config_set_d(i, atoi(s));
252 static const char *config_mouse_name(int b)
254 static char buff[sizeof ("256")];
256 sprintf(buff, "%d", b);
260 case 0: return "none"; break;
261 case SDL_BUTTON_LEFT: return "left"; break;
262 case SDL_BUTTON_RIGHT: return "right"; break;
263 case SDL_BUTTON_WHEELUP: return "wheelup"; break;
264 case SDL_BUTTON_MIDDLE: return "middle"; break;
265 case SDL_BUTTON_WHEELDOWN: return "wheeldown"; break;
266 default: return buff; break;
270 /*---------------------------------------------------------------------------*/
272 void config_init(void)
277 * Store index of each option in its associated config symbol and
278 * initialise current values with defaults.
281 for (i = 0; i < ARRAYSIZE(option_d); i++)
283 *option_d[i].sym = i;
284 config_set_d(i, option_d[i].def);
287 for (i = 0; i < ARRAYSIZE(option_s); i++)
289 *option_s[i].sym = i;
290 config_set_s(i, option_s[i].def);
295 * Scan an option string and store pointers to the start of key and
296 * value at the passed-in locations. No memory is allocated to store
297 * the strings; instead, the option string is modified in-place as
298 * needed. Return 1 on success, 0 on error.
300 static int scan_key_and_value(char **dst_key, char **dst_val, char *line)
310 sscanf(line, " %n%*s%n %n", &ks, &ke, &vs);
312 if (ks < 0 || ke < 0 || vs < 0)
320 *dst_key = line + ks;
321 *dst_val = line + vs;
329 void config_load(void)
333 if ((fh = fs_open(USER_CONFIG_FILE, "r")))
335 char *line, *key, *val;
337 while (read_line(&line, fh))
339 if (scan_key_and_value(&key, &val, line))
343 /* Look up an integer option by that name. */
345 for (i = 0; i < ARRAYSIZE(option_d); i++)
347 if (strcmp(key, option_d[i].name) == 0)
349 /* Translate some strings to integers. */
351 if (i == CONFIG_MOUSE_CAMERA_1 ||
352 i == CONFIG_MOUSE_CAMERA_2 ||
353 i == CONFIG_MOUSE_CAMERA_3 ||
354 i == CONFIG_MOUSE_CAMERA_TOGGLE ||
355 i == CONFIG_MOUSE_CAMERA_L ||
356 i == CONFIG_MOUSE_CAMERA_R)
358 config_mouse(val, i);
360 else if (i == CONFIG_KEY_FORWARD ||
361 i == CONFIG_KEY_BACKWARD ||
362 i == CONFIG_KEY_LEFT ||
363 i == CONFIG_KEY_RIGHT ||
364 i == CONFIG_KEY_CAMERA_1 ||
365 i == CONFIG_KEY_CAMERA_2 ||
366 i == CONFIG_KEY_CAMERA_3 ||
367 i == CONFIG_KEY_CAMERA_TOGGLE ||
368 i == CONFIG_KEY_CAMERA_R ||
369 i == CONFIG_KEY_CAMERA_L ||
370 i == CONFIG_KEY_PAUSE ||
371 i == CONFIG_KEY_RESTART ||
372 i == CONFIG_KEY_SCORE_NEXT ||
373 i == CONFIG_KEY_ROTATE_FAST)
378 config_set_d(i, atoi(val));
386 /* Look up a string option by that name.*/
388 for (i = 0; i < ARRAYSIZE(option_s); i++)
390 if (strcmp(key, option_s[i].name) == 0)
392 config_set_s(i, val);
405 void config_save(void)
409 if (dirty && (fh = fs_open(USER_CONFIG_FILE, "w")))
413 /* Write out integer options. */
415 for (i = 0; i < ARRAYSIZE(option_d); i++)
417 const char *s = NULL;
419 /* Translate some integers to strings. */
421 if (i == CONFIG_MOUSE_CAMERA_1 ||
422 i == CONFIG_MOUSE_CAMERA_2 ||
423 i == CONFIG_MOUSE_CAMERA_3 ||
424 i == CONFIG_MOUSE_CAMERA_TOGGLE ||
425 i == CONFIG_MOUSE_CAMERA_L ||
426 i == CONFIG_MOUSE_CAMERA_R)
428 s = config_mouse_name(option_d[i].cur);
430 else if (i == CONFIG_KEY_FORWARD ||
431 i == CONFIG_KEY_BACKWARD ||
432 i == CONFIG_KEY_LEFT ||
433 i == CONFIG_KEY_RIGHT ||
434 i == CONFIG_KEY_CAMERA_1 ||
435 i == CONFIG_KEY_CAMERA_2 ||
436 i == CONFIG_KEY_CAMERA_3 ||
437 i == CONFIG_KEY_CAMERA_TOGGLE ||
438 i == CONFIG_KEY_CAMERA_R ||
439 i == CONFIG_KEY_CAMERA_L ||
440 i == CONFIG_KEY_PAUSE ||
441 i == CONFIG_KEY_RESTART ||
442 i == CONFIG_KEY_SCORE_NEXT ||
443 i == CONFIG_KEY_ROTATE_FAST)
445 s = SDL_GetKeyName((SDLKey) option_d[i].cur);
447 else if (i == CONFIG_CHEAT)
454 fs_printf(fh, "%-25s %s\n", option_d[i].name, s);
456 fs_printf(fh, "%-25s %d\n", option_d[i].name, option_d[i].cur);
459 /* Write out string options. */
461 for (i = 0; i < ARRAYSIZE(option_s); i++)
463 if (option_s[i].cur && *option_s[i].cur)
464 fs_printf(fh, "%-25s %s\n", option_s[i].name, option_s[i].cur);
473 /*---------------------------------------------------------------------------*/
475 void config_set_d(int i, int d)
481 void config_tgl_d(int i)
483 option_d[i].cur = (option_d[i].cur ? 0 : 1);
487 int config_tst_d(int i, int d)
489 return (option_d[i].cur == d) ? 1 : 0;
492 int config_get_d(int i)
494 return option_d[i].cur;
497 /*---------------------------------------------------------------------------*/
499 void config_set_s(int i, const char *src)
502 free(option_s[i].cur);
504 option_s[i].cur = strdup(src);
509 const char *config_get_s(int i)
511 return option_s[i].cur;
514 /*---------------------------------------------------------------------------*/
516 int config_cheat(void)
518 return config_get_d(CONFIG_CHEAT);
521 void config_set_cheat(void)
523 config_set_d(CONFIG_CHEAT, 1);
526 void config_clr_cheat(void)
528 config_set_d(CONFIG_CHEAT, 0);
531 /*---------------------------------------------------------------------------*/
533 int config_screenshot(void)
535 return ++option_d[CONFIG_SCREENSHOT].cur;
538 /*---------------------------------------------------------------------------*/