#include <stdio.h>
#include <errno.h>
#include <math.h>
+#include <ctype.h>
#include "config.h"
#include "glext.h"
#include "vec3.h"
#include "sync.h"
+#include "common.h"
/*---------------------------------------------------------------------------*/
config_set_s(CONFIG_PLAYER, DEFAULT_PLAYER);
config_set_s(CONFIG_BALL, DEFAULT_BALL);
config_set_s(CONFIG_WIIMOTE_ADDR, DEFAULT_WIIMOTE_ADDR);
+ config_set_s(CONFIG_REPLAY_NAME, DEFAULT_REPLAY_NAME);
config_set_d(CONFIG_CHEAT, DEFAULT_CHEAT);
config_set_d(CONFIG_STATS, DEFAULT_STATS);
+ config_set_d(CONFIG_UNIFORM, DEFAULT_UNIFORM);
config_set_d(CONFIG_KEY_FORWARD, DEFAULT_KEY_FORWARD);
config_set_d(CONFIG_KEY_BACKWARD, DEFAULT_KEY_BACKWARD);
config_set_d(CONFIG_KEY_LEFT, DEFAULT_KEY_LEFT);
config_set_d(CONFIG_KEY_RIGHT, DEFAULT_KEY_RIGHT);
config_set_d(CONFIG_KEY_PAUSE, DEFAULT_KEY_PAUSE);
config_set_d(CONFIG_KEY_RESTART, DEFAULT_KEY_RESTART);
+ config_set_d(CONFIG_KEY_SCORE_NEXT, DEFAULT_KEY_SCORE_NEXT);
+ config_set_d(CONFIG_SCREENSHOT, DEFAULT_SCREENSHOT);
+ config_set_d(CONFIG_LOCK_GOALS, DEFAULT_LOCK_GOALS);
+}
+
+/*
+ * Scan a NUL-terminated string LINE according to the format
+ * '^<space>?<key><space><value>$' and store pointers to the start of key and
+ * value at DST_KEY and DST_VAL, respectively. No memory is allocated to store
+ * the strings; instead, the memory pointed to by LINE modified in-place as
+ * needed.
+ *
+ * Return 1 if LINE matches the format, return 0 otherwise.
+ */
+
+static int scan_key_and_value(char **dst_key, char **dst_val, char *line)
+{
+ if (line)
+ {
+ char *key, *val, *space;
+
+ for (key = line; *key && isspace(*key); key++);
+
+ if (*key)
+ {
+ if (dst_key)
+ *dst_key = key;
+ }
+ else
+ return 0;
+
+ for (space = key; *space && !isspace(*space); space++);
+
+ if (*space)
+ {
+ /* NUL-terminate the key, if necessary. */
+
+ if (dst_key)
+ {
+ *space = '\0';
+ space++;
+ }
+ }
+ else
+ return 0;
+
+ for (val = space; *val && isspace(*val); val++);
+
+ if (*val)
+ {
+ if (dst_val)
+ *dst_val = val;
+ }
+ else
+ return 0;
+
+ return 1;
+ }
+
+ return 0;
}
void config_load(void)
if ((fp = fopen(config_user(USER_CONFIG_FILE), "r")))
{
- char buf[MAXSTR];
- char key[MAXSTR];
- char val[MAXSTR];
+ char *line, *key, *val;
- while (fgets(buf, MAXSTR, fp))
- if (sscanf(buf, "%s %s", key, val) == 2)
+ while (read_line(&line, fp))
+ {
+ if (scan_key_and_value(&key, &val, line))
{
if (strcmp(key, "fullscreen") == 0)
config_set_d(CONFIG_FULLSCREEN, atoi(val));
else if (strcmp(key, "key_restart") == 0)
config_key(val, CONFIG_KEY_RESTART, DEFAULT_KEY_RESTART);
+ else if (strcmp(key, "key_score_next") == 0)
+ config_key(val, CONFIG_KEY_SCORE_NEXT, DEFAULT_KEY_SCORE_NEXT);
+
else if (strcmp(key, "player") == 0)
config_set_s(CONFIG_PLAYER, val);
- else if (strcmp(key, "ball") == 0)
+ else if (strcmp(key, "ball_file") == 0)
config_set_s(CONFIG_BALL, val);
else if (strcmp(key, "wiimote_addr") == 0)
config_set_s(CONFIG_WIIMOTE_ADDR, val);
+ else if (strcmp(key, "replay_name") == 0)
+ config_set_s(CONFIG_REPLAY_NAME, val);
- else if (strcmp(key, "cheat") == 0)
+ else if (strcmp(key, "cheat") == 0)
config_set_d(CONFIG_CHEAT, atoi(val));
- else if (strcmp(key, "stats") == 0)
+ else if (strcmp(key, "stats") == 0)
config_set_d(CONFIG_STATS, atoi(val));
+ else if (strcmp(key, "uniform") == 0)
+ config_set_d(CONFIG_UNIFORM, atoi(val));
+ else if (strcmp(key, "screenshot") == 0)
+ config_set_d(CONFIG_SCREENSHOT, atoi(val));
+ else if (strcmp(key, "lock_goals") == 0)
+ config_set_d(CONFIG_LOCK_GOALS, atoi(val));
}
+ free(line);
+ }
+
fclose(fp);
dirty = 0;
option_d[CONFIG_ROTATE_FAST]);
fprintf(fp, "rotate_slow %d\n",
option_d[CONFIG_ROTATE_SLOW]);
-
+
fprintf(fp, "key_forward %s\n",
SDL_GetKeyName((SDLKey) option_d[CONFIG_KEY_FORWARD]));
fprintf(fp, "key_backward %s\n",
fprintf(fp, "key_restart %s\n",
SDL_GetKeyName((SDLKey) option_d[CONFIG_KEY_RESTART]));
+ fprintf(fp, "key_score_next %s\n",
+ SDL_GetKeyName((SDLKey) option_d[CONFIG_KEY_SCORE_NEXT]));
+
if (strlen(option_s[CONFIG_PLAYER]) > 0)
fprintf(fp, "player %s\n", option_s[CONFIG_PLAYER]);
if (strlen(option_s[CONFIG_BALL]) > 0)
- fprintf(fp, "ball %s\n", option_s[CONFIG_BALL]);
+ fprintf(fp, "ball_file %s\n", option_s[CONFIG_BALL]);
if (strlen(option_s[CONFIG_WIIMOTE_ADDR]) > 0)
fprintf(fp, "wiimote_addr %s\n", option_s[CONFIG_WIIMOTE_ADDR]);
+ if (strlen(option_s[CONFIG_REPLAY_NAME]) > 0)
+ fprintf(fp, "replay_name %s\n", option_s[CONFIG_REPLAY_NAME]);
+
+ fprintf(fp, "stats %d\n", option_d[CONFIG_STATS]);
+ fprintf(fp, "uniform %d\n", option_d[CONFIG_UNIFORM]);
+ fprintf(fp, "screenshot %d\n", option_d[CONFIG_SCREENSHOT]);
+ fprintf(fp, "lock_goals %d\n", option_d[CONFIG_LOCK_GOALS]);
- fprintf(fp, "stats %d\n",
- option_d[CONFIG_STATS]);
if (config_cheat())
fprintf(fp, "cheat %d\n", option_d[CONFIG_CHEAT]);
int stencil = config_get_d(CONFIG_REFLECTION) ? 1 : 0;
int buffers = config_get_d(CONFIG_MULTISAMPLE) ? 1 : 0;
int samples = config_get_d(CONFIG_MULTISAMPLE);
+ int vsync = config_get_d(CONFIG_VSYNC) ? 1 : 0;
SDL_GL_SetAttribute(SDL_GL_STEREO, stereo);
SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, stencil);
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, buffers);
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, samples);
+ SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, vsync);
/* Try to set the currently specified mode. */
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glDepthFunc(GL_LEQUAL);
- if (config_get_d(CONFIG_VSYNC))
- sync_init();
+ /*
+ * Mac OS X might still need this, because apparently SDL doesn't do
+ * SDL_GL_SWAP_CONTROL on OS X. TODO: investigate.
+ */
+#if 0
+ if (vsync) sync_init();
+#endif
/* If GL supports multisample, and SDL got a multisample buffer... */
void config_set_grab(int w)
{
if (w)
+ {
+ SDL_EventState(SDL_MOUSEMOTION, SDL_IGNORE);
+
SDL_WarpMouse(config_get_d(CONFIG_WIDTH) / 2,
config_get_d(CONFIG_HEIGHT) / 2);
+
+ SDL_EventState(SDL_MOUSEMOTION, SDL_ENABLE);
+ }
+
SDL_WM_GrabInput(SDL_GRAB_ON);
SDL_ShowCursor(SDL_DISABLE);
+
grabbed = 1;
}
/*---------------------------------------------------------------------------*/
+int config_screenshot(void)
+{
+ return ++option_d[CONFIG_SCREENSHOT];
+}
+
+/*---------------------------------------------------------------------------*/
+
void config_push_persp(float fov, float n, float f)
{
GLdouble m[4][4];