Correct logic of BSP back/front tests
[neverball] / share / config.c
index 2615c25..7c112d0 100644 (file)
 #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"
 
 /*---------------------------------------------------------------------------*/
 
@@ -115,6 +117,7 @@ void config_init(void)
     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);
@@ -129,18 +132,74 @@ void config_init(void)
     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)
 {
     FILE *fp;
 
     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));
@@ -255,6 +314,8 @@ void config_load(void)
                     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)
                     config_set_d(CONFIG_CHEAT, atoi(val));
@@ -268,6 +329,9 @@ void config_load(void)
                     config_set_d(CONFIG_LOCK_GOALS, atoi(val));
             }
 
+            free(line);
+        }
+
         fclose(fp);
 
         dirty = 0;
@@ -358,7 +422,7 @@ void config_save(void)
                 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",
@@ -393,6 +457,8 @@ void config_save(void)
             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]);
@@ -435,11 +501,13 @@ int config_mode(int f, int w, int h)
     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. */
 
@@ -466,8 +534,13 @@ int config_mode(int f, int w, int h)
         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... */