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.
24 /*---------------------------------------------------------------------------*/
26 /* Integer options. */
28 int CONFIG_FULLSCREEN;
35 int CONFIG_REFLECTION;
36 int CONFIG_MULTISAMPLE;
39 int CONFIG_BACKGROUND;
41 int CONFIG_AUDIO_BUFF;
42 int CONFIG_MOUSE_SENSE;
43 int CONFIG_MOUSE_INVERT;
45 int CONFIG_MOUSE_CAMERA_1;
46 int CONFIG_MOUSE_CAMERA_2;
47 int CONFIG_MOUSE_CAMERA_3;
48 int CONFIG_MOUSE_CAMERA_TOGGLE;
49 int CONFIG_MOUSE_CAMERA_L;
50 int CONFIG_MOUSE_CAMERA_R;
53 int CONFIG_SOUND_VOLUME;
54 int CONFIG_MUSIC_VOLUME;
56 int CONFIG_JOYSTICK_DEVICE;
57 int CONFIG_JOYSTICK_AXIS_X;
58 int CONFIG_JOYSTICK_AXIS_Y;
59 int CONFIG_JOYSTICK_AXIS_U;
60 int CONFIG_JOYSTICK_BUTTON_A;
61 int CONFIG_JOYSTICK_BUTTON_B;
62 int CONFIG_JOYSTICK_BUTTON_R;
63 int CONFIG_JOYSTICK_BUTTON_L;
64 int CONFIG_JOYSTICK_BUTTON_EXIT;
65 int CONFIG_JOYSTICK_CAMERA_1;
66 int CONFIG_JOYSTICK_CAMERA_2;
67 int CONFIG_JOYSTICK_CAMERA_3;
68 int CONFIG_JOYSTICK_DPAD_L;
69 int CONFIG_JOYSTICK_DPAD_R;
70 int CONFIG_JOYSTICK_DPAD_U;
71 int CONFIG_JOYSTICK_DPAD_D;
72 int CONFIG_JOYSTICK_CAMERA_TOGGLE;
73 int CONFIG_JOYSTICK_ROTATE_FAST;
74 int CONFIG_KEY_CAMERA_1;
75 int CONFIG_KEY_CAMERA_2;
76 int CONFIG_KEY_CAMERA_3;
77 int CONFIG_KEY_CAMERA_TOGGLE;
78 int CONFIG_KEY_CAMERA_R;
79 int CONFIG_KEY_CAMERA_L;
84 int CONFIG_ROTATE_FAST;
85 int CONFIG_ROTATE_SLOW;
86 int CONFIG_KEY_FORWARD;
87 int CONFIG_KEY_BACKWARD;
91 int CONFIG_KEY_RESTART;
92 int CONFIG_KEY_SCORE_NEXT;
93 int CONFIG_KEY_ROTATE_FAST;
97 int CONFIG_SCREENSHOT;
98 int CONFIG_LOCK_GOALS;
100 /* String options. */
103 int CONFIG_BALL_FILE;
104 int CONFIG_WIIMOTE_ADDR;
105 int CONFIG_REPLAY_NAME;
107 /*---------------------------------------------------------------------------*/
116 { &CONFIG_FULLSCREEN, "fullscreen", 0 },
117 { &CONFIG_WIDTH, "width", 800 },
118 { &CONFIG_HEIGHT, "height", 600 },
119 { &CONFIG_STEREO, "stereo", 0 },
120 { &CONFIG_CAMERA, "camera", 0 },
121 { &CONFIG_TEXTURES, "textures", 1 },
122 { &CONFIG_GEOMETRY, "geometry", 1 },
123 { &CONFIG_REFLECTION, "reflection", 1 },
124 { &CONFIG_MULTISAMPLE, "multisample", 0 },
125 { &CONFIG_MIPMAP, "mipmap", 0 },
126 { &CONFIG_ANISO, "aniso", 0 },
127 { &CONFIG_BACKGROUND, "background", 1 },
128 { &CONFIG_SHADOW, "shadow", 1 },
129 { &CONFIG_AUDIO_BUFF, "audio_buff", AUDIO_BUFF_HI },
130 { &CONFIG_MOUSE_SENSE, "mouse_sense", 300 },
131 { &CONFIG_MOUSE_INVERT, "mouse_invert", 0 },
132 { &CONFIG_VSYNC, "vsync", 1 },
134 { &CONFIG_MOUSE_CAMERA_1, "mouse_camera_1", 0 },
135 { &CONFIG_MOUSE_CAMERA_2, "mouse_camera_2", 0 },
136 { &CONFIG_MOUSE_CAMERA_3, "mouse_camera_3", 0 },
137 { &CONFIG_MOUSE_CAMERA_TOGGLE, "mouse_camera_toggle", SDL_BUTTON_MIDDLE },
138 { &CONFIG_MOUSE_CAMERA_L, "mouse_camera_l", SDL_BUTTON_LEFT },
139 { &CONFIG_MOUSE_CAMERA_R, "mouse_camera_r", SDL_BUTTON_RIGHT },
141 { &CONFIG_NICE, "nice", 0 },
142 { &CONFIG_FPS, "fps", 0 },
143 { &CONFIG_SOUND_VOLUME, "sound_volume", 10 },
144 { &CONFIG_MUSIC_VOLUME, "music_volume", 6 },
146 { &CONFIG_JOYSTICK, "joystick", 0 },
147 { &CONFIG_JOYSTICK_DEVICE, "joystick_device", 0 },
148 { &CONFIG_JOYSTICK_AXIS_X, "joystick_axis_x", 0 },
149 { &CONFIG_JOYSTICK_AXIS_Y, "joystick_axis_y", 1 },
150 { &CONFIG_JOYSTICK_AXIS_U, "joystick_axis_u", 2 },
151 { &CONFIG_JOYSTICK_BUTTON_A, "joystick_button_a", 0 },
152 { &CONFIG_JOYSTICK_BUTTON_B, "joystick_button_b", 1 },
153 { &CONFIG_JOYSTICK_BUTTON_R, "joystick_button_r", 2 },
154 { &CONFIG_JOYSTICK_BUTTON_L, "joystick_button_l", 3 },
155 { &CONFIG_JOYSTICK_BUTTON_EXIT, "joystick_button_exit", 4 },
156 { &CONFIG_JOYSTICK_CAMERA_1, "joystick_camera_1", 5 },
157 { &CONFIG_JOYSTICK_CAMERA_2, "joystick_camera_2", 6 },
158 { &CONFIG_JOYSTICK_CAMERA_3, "joystick_camera_3", 7 },
159 { &CONFIG_JOYSTICK_DPAD_L, "joystick_dpad_l", 8 },
160 { &CONFIG_JOYSTICK_DPAD_R, "joystick_dpad_r", 9 },
161 { &CONFIG_JOYSTICK_DPAD_U, "joystick_dpad_u", 10 },
162 { &CONFIG_JOYSTICK_DPAD_D, "joystick_dpad_d", 11 },
163 { &CONFIG_JOYSTICK_CAMERA_TOGGLE, "joystick_camera_toggle", 12 },
164 { &CONFIG_JOYSTICK_ROTATE_FAST, "joystick_rotate_fast", 13 },
166 { &CONFIG_KEY_CAMERA_1, "key_camera_1", SDLK_F1 },
167 { &CONFIG_KEY_CAMERA_2, "key_camera_2", SDLK_F2 },
168 { &CONFIG_KEY_CAMERA_3, "key_camera_3", SDLK_F3 },
169 { &CONFIG_KEY_CAMERA_TOGGLE, "key_camera_toggle", SDLK_e },
170 { &CONFIG_KEY_CAMERA_R, "key_camera_r", SDLK_d },
171 { &CONFIG_KEY_CAMERA_L, "key_camera_l", SDLK_s },
172 { &CONFIG_VIEW_FOV, "view_fov", 50 },
173 { &CONFIG_VIEW_DP, "view_dp", 75 },
174 { &CONFIG_VIEW_DC, "view_dc", 25 },
175 { &CONFIG_VIEW_DZ, "view_dz", 200 },
176 { &CONFIG_ROTATE_FAST, "rotate_fast", 200 },
177 { &CONFIG_ROTATE_SLOW, "rotate_slow", 100 },
178 { &CONFIG_KEY_FORWARD, "key_forward", SDLK_UP },
179 { &CONFIG_KEY_BACKWARD, "key_backward", SDLK_DOWN },
180 { &CONFIG_KEY_LEFT, "key_left", SDLK_LEFT },
181 { &CONFIG_KEY_RIGHT, "key_right", SDLK_RIGHT },
182 { &CONFIG_KEY_PAUSE, "key_pause", SDLK_ESCAPE },
183 { &CONFIG_KEY_RESTART, "key_restart", SDLK_r },
184 { &CONFIG_KEY_SCORE_NEXT, "key_score_next", SDLK_TAB },
185 { &CONFIG_KEY_ROTATE_FAST, "key_rotate_fast", SDLK_LSHIFT },
186 { &CONFIG_CHEAT, "cheat", 0 },
187 { &CONFIG_STATS, "stats", 0 },
188 { &CONFIG_UNIFORM, "uniform", 0 },
189 { &CONFIG_SCREENSHOT, "screenshot", 0 },
190 { &CONFIG_LOCK_GOALS, "lock_goals", 0 }
200 { &CONFIG_PLAYER, "player", "" },
201 { &CONFIG_BALL_FILE, "ball_file", "ball/basic-ball/basic-ball" },
202 { &CONFIG_WIIMOTE_ADDR, "wiimote_addr", "" },
203 { &CONFIG_REPLAY_NAME, "replay_name", "%s-%l" }
206 static int dirty = 0;
208 /*---------------------------------------------------------------------------*/
210 static void config_key(const char *s, int i)
214 config_set_d(i, option_d[i].def);
216 for (c = 0; c < SDLK_LAST; c++)
217 if (strcmp(s, SDL_GetKeyName((SDLKey) c)) == 0)
224 /*---------------------------------------------------------------------------*/
226 static void config_mouse(const char *s, int i)
228 if (strcmp(s, "none") == 0)
230 else if (strcmp(s, "left") == 0)
231 config_set_d(i, SDL_BUTTON_LEFT);
232 else if (strcmp(s, "right") == 0)
233 config_set_d(i, SDL_BUTTON_RIGHT);
234 else if (strcmp(s, "wheelup") == 0)
235 config_set_d(i, SDL_BUTTON_WHEELUP);
236 else if (strcmp(s, "middle") == 0)
237 config_set_d(i, SDL_BUTTON_MIDDLE);
238 else if (strcmp(s, "wheeldown") == 0)
239 config_set_d(i, SDL_BUTTON_WHEELDOWN);
241 config_set_d(i, atoi(s));
244 static const char *config_mouse_name(int b)
246 static char buff[sizeof ("256")];
248 sprintf(buff, "%d", b);
252 case 0: return "none"; break;
253 case SDL_BUTTON_LEFT: return "left"; break;
254 case SDL_BUTTON_RIGHT: return "right"; break;
255 case SDL_BUTTON_WHEELUP: return "wheelup"; break;
256 case SDL_BUTTON_MIDDLE: return "middle"; break;
257 case SDL_BUTTON_WHEELDOWN: return "wheeldown"; break;
258 default: return buff; break;
262 /*---------------------------------------------------------------------------*/
264 void config_init(void)
269 * Store index of each option in its associated config symbol and
270 * initialise current values with defaults.
273 for (i = 0; i < ARRAYSIZE(option_d); i++)
275 *option_d[i].sym = i;
276 config_set_d(i, option_d[i].def);
279 for (i = 0; i < ARRAYSIZE(option_s); i++)
281 *option_s[i].sym = i;
282 config_set_s(i, option_s[i].def);
287 * Scan a NUL-terminated string LINE according to the format
288 * '^<space>?<key><space><value>$' and store pointers to the start of key and
289 * value at DST_KEY and DST_VAL, respectively. No memory is allocated to store
290 * the strings; instead, the memory pointed to by LINE modified in-place as
293 * Return 1 if LINE matches the format, return 0 otherwise.
296 static int scan_key_and_value(char **dst_key, char **dst_val, char *line)
300 char *key, *val, *space;
302 for (key = line; *key && isspace(*key); key++);
312 for (space = key; *space && !isspace(*space); space++);
316 /* NUL-terminate the key, if necessary. */
327 for (val = space; *val && isspace(*val); val++);
343 void config_load(void)
347 if ((fp = fopen(config_user(USER_CONFIG_FILE), "r")))
349 char *line, *key, *val;
351 while (read_line(&line, fp))
353 if (scan_key_and_value(&key, &val, line))
357 /* Look up an integer option by that name. */
359 for (i = 0; i < ARRAYSIZE(option_d); i++)
361 if (strcmp(key, option_d[i].name) == 0)
363 /* Translate some strings to integers. */
365 if (i == CONFIG_MOUSE_CAMERA_1 ||
366 i == CONFIG_MOUSE_CAMERA_2 ||
367 i == CONFIG_MOUSE_CAMERA_3 ||
368 i == CONFIG_MOUSE_CAMERA_TOGGLE ||
369 i == CONFIG_MOUSE_CAMERA_L ||
370 i == CONFIG_MOUSE_CAMERA_R)
372 config_mouse(val, i);
374 else if (i == CONFIG_KEY_FORWARD ||
375 i == CONFIG_KEY_BACKWARD ||
376 i == CONFIG_KEY_LEFT ||
377 i == CONFIG_KEY_RIGHT ||
378 i == CONFIG_KEY_CAMERA_1 ||
379 i == CONFIG_KEY_CAMERA_2 ||
380 i == CONFIG_KEY_CAMERA_3 ||
381 i == CONFIG_KEY_CAMERA_TOGGLE ||
382 i == CONFIG_KEY_CAMERA_R ||
383 i == CONFIG_KEY_CAMERA_L ||
384 i == CONFIG_KEY_PAUSE ||
385 i == CONFIG_KEY_RESTART ||
386 i == CONFIG_KEY_SCORE_NEXT ||
387 i == CONFIG_KEY_ROTATE_FAST)
392 config_set_d(i, atoi(val));
400 /* Look up a string option by that name.*/
402 for (i = 0; i < ARRAYSIZE(option_s); i++)
404 if (strcmp(key, option_s[i].name) == 0)
406 config_set_s(i, val);
419 void config_save(void)
423 if (dirty && (fp = fopen(config_user(USER_CONFIG_FILE), "w")))
427 /* Write out integer options. */
429 for (i = 0; i < ARRAYSIZE(option_d); i++)
431 const char *s = NULL;
433 /* Translate some integers to strings. */
435 if (i == CONFIG_MOUSE_CAMERA_1 ||
436 i == CONFIG_MOUSE_CAMERA_2 ||
437 i == CONFIG_MOUSE_CAMERA_3 ||
438 i == CONFIG_MOUSE_CAMERA_TOGGLE ||
439 i == CONFIG_MOUSE_CAMERA_L ||
440 i == CONFIG_MOUSE_CAMERA_R)
442 s = config_mouse_name(option_d[i].cur);
444 else if (i == CONFIG_KEY_FORWARD ||
445 i == CONFIG_KEY_BACKWARD ||
446 i == CONFIG_KEY_LEFT ||
447 i == CONFIG_KEY_RIGHT ||
448 i == CONFIG_KEY_CAMERA_1 ||
449 i == CONFIG_KEY_CAMERA_2 ||
450 i == CONFIG_KEY_CAMERA_3 ||
451 i == CONFIG_KEY_CAMERA_TOGGLE ||
452 i == CONFIG_KEY_CAMERA_R ||
453 i == CONFIG_KEY_CAMERA_L ||
454 i == CONFIG_KEY_PAUSE ||
455 i == CONFIG_KEY_RESTART ||
456 i == CONFIG_KEY_SCORE_NEXT ||
457 i == CONFIG_KEY_ROTATE_FAST)
459 s = SDL_GetKeyName((SDLKey) option_d[i].cur);
461 else if (i == CONFIG_CHEAT)
468 fprintf(fp, "%-25s %s\n", option_d[i].name, s);
470 fprintf(fp, "%-25s %d\n", option_d[i].name, option_d[i].cur);
473 /* Write out string options. */
475 for (i = 0; i < ARRAYSIZE(option_s); i++)
477 if (option_s[i].cur && *option_s[i].cur)
478 fprintf(fp, "%-25s %s\n", option_s[i].name, option_s[i].cur);
487 /*---------------------------------------------------------------------------*/
489 void config_set_d(int i, int d)
495 void config_tgl_d(int i)
497 option_d[i].cur = (option_d[i].cur ? 0 : 1);
501 int config_tst_d(int i, int d)
503 return (option_d[i].cur == d) ? 1 : 0;
506 int config_get_d(int i)
508 return option_d[i].cur;
511 /*---------------------------------------------------------------------------*/
513 void config_set_s(int i, const char *src)
516 free(option_s[i].cur);
518 option_s[i].cur = strdup(src);
523 void config_get_s(int i, char *dst, int len)
525 strncpy(dst, option_s[i].cur, len);
528 /*---------------------------------------------------------------------------*/
530 int config_cheat(void)
532 return config_get_d(CONFIG_CHEAT);
535 void config_set_cheat(void)
537 config_set_d(CONFIG_CHEAT, 1);
540 void config_clr_cheat(void)
542 config_set_d(CONFIG_CHEAT, 0);
545 /*---------------------------------------------------------------------------*/
547 int config_screenshot(void)
549 return ++option_d[CONFIG_SCREENSHOT].cur;
552 /*---------------------------------------------------------------------------*/