removing some compiler warnings
[drnoksnes] / platform / config.cpp
index f21fd7d..6caa569 100644 (file)
@@ -8,6 +8,10 @@
 #include "snes9x.h"
 #include "display.h"
 
+#if CONF_GUI
+#include "osso.h"
+#endif
+
 #define DIE(format, ...) do { \
                fprintf(stderr, "Died at %s:%d: ", __FILE__, __LINE__ ); \
                fprintf(stderr, format "\n", ## __VA_ARGS__); \
 
 struct config Config;
 
-static const struct poptOption optionsTable[] = {
+/** Path to current rom file, with extension. */
+static char * romFile;
+/** Path to rom file, without extension.
+ *  Used as a simple optimization to S9xGetFilename
+ */
+static char * basePath;
+
+static struct poptOption commonOptionsTable[] = {
        { "disable-audio", 'a', POPT_ARG_NONE, 0, 1,
        "disable emulation and output of audio", 0 },
        { "display-framerate", 'r', POPT_ARG_NONE, 0, 2,
-       "Show frames per second counter in lower left corner", 0 },
+       "show frames per second counter in lower left corner", 0 },
        { "skip-frames", 's', POPT_ARG_INT, 0, 3,
-       "Render only 1 in every N frames", "NUM" },
+       "render only 1 in every N frames", "NUM" },
        { "fullscreen", 'f', POPT_ARG_NONE, 0, 4,
-       "Start in fullscreen mode", 0 },
+       "start in fullscreen mode", 0 },
        { "transparency", 'y', POPT_ARG_NONE, 0, 5,
-       "Enable transparency effects (slower)", 0 },
-       { "hacks", 'h', POPT_ARG_STRING | POPT_ARGFLAG_OPTIONAL, 0, 6,
-       "Enable hacks (yes, speed-only, no)", "option" },
+       "enable transparency effects (slower)", 0 },
+       { "scaler", 'S', POPT_ARG_STRING, 0, 6,
+       "select scaler to use", 0 },
        { "pal", 'p', POPT_ARG_NONE, 0, 7,
-       "Run in PAL mode", 0 },
+       "run in PAL mode", 0 },
        { "ntsc", 'n', POPT_ARG_NONE, 0, 8,
-       "Run in NTSC mode", 0 },
+       "run in NTSC mode", 0 },
        { "turbo", 't', POPT_ARG_NONE, 0, 9,
-       "Turbo mode (do not try to sleep between frames)", 0 },
+       "turbo mode (do not try to sleep between frames)", 0 },
        { "conf", 'c', POPT_ARG_STRING, 0, 10,
-       "Load extra configuration file", "FILE" },
+       "extra configuration file to load", "FILE" },
+       { "mouse", 'm', POPT_ARG_INT | POPT_ARGFLAG_OPTIONAL, 0, 11,
+       "enable mouse on controller NUM", "NUM"},
+       { "superscope", 'e', POPT_ARG_NONE, 0, 12,
+       "enable SuperScope", 0},
+       { "snapshot", 'o', POPT_ARG_NONE, 0, 13,
+       "unfreeze previous game on start and freeze game on exit", 0 },
+       { "audio-rate", 'u', POPT_ARG_INT, 0, 14,
+       "audio output rate", "HZ" },
+       { "audio-buffer-size", 'b', POPT_ARG_INT, 0, 15,
+       "audio output buffer size", "SAMPLES" },
+       { "touchscreen", 'd', POPT_ARG_NONE, 0, 16,
+       "enable touchscreen controls", 0 },
+       { "touchscreen-grid", 'D', POPT_ARG_NONE, 0, 17,
+       "enable touchscreen controls and show grid", 0 },
+       { "hacks", 'h', POPT_ARG_NONE, 0, 18,
+       "enable safe subset of speedhacks", 0 },
+       { "all-hacks", 'H', POPT_ARG_NONE, 0, 19,
+       "enable all speedhacks (may break sound)", 0 },
+       { "saver", 'R', POPT_ARG_NONE, 0, 20,
+       "save&exit when the emulator window is unfocused", 0 },
+       POPT_TABLEEND
+};
+
+static struct poptOption configOptionsTable[] = {
        { "scancode", '\0', POPT_ARG_INT, 0, 100,
-       "Scancode to map", "CODE" },
+       "scancode to map", "CODE" },
        { "button", '\0', POPT_ARG_STRING, 0, 101,
        "SNES Button to press (A, B, X, Y, L, R, Up, Down, Left, Right)", "name" },
-       { "action", '\0', POPT_ARG_STRING, 0, 102,
-       "Emulator action to do (fullscreen, quit, ...)", "action" },
+       { "button2", '\0', POPT_ARG_STRING, 0, 102,
+       "SNES Button to press for joypad 2", "name" },
+       { "action", '\0', POPT_ARG_STRING, 0, 110,
+       "emulator action to do (fullscreen, quit, ...)", "action" },
        { "hacks-file", '\0', POPT_ARG_STRING, 0, 200,
-       "Path to snesadvance.dat file", "FILE" },
+       "path to snesadvance.dat file", "FILE" },
+       POPT_TABLEEND
+};
+
+static struct poptOption optionsTable[] = {
+       { 0, '\0', POPT_ARG_INCLUDE_TABLE, commonOptionsTable, 0,
+       "Common options", 0 },
+       { 0, '\0', POPT_ARG_INCLUDE_TABLE, configOptionsTable, 0,
+       "Configuration file options", 0 },
        POPT_AUTOHELP
        POPT_TABLEEND
 };
@@ -84,38 +129,57 @@ static unsigned char actionNameToBit(const char *s) {
                return kActionQuit;
        } else if (strcasecmp(s, "fullscreen") == 0) {
                return kActionToggleFullscreen;
+       } else if (strcasecmp(s, "quickload1") == 0) {
+               return kActionQuickLoad1;
+       } else if (strcasecmp(s, "quicksave1") == 0) {
+               return kActionQuickSave1;
+       } else if (strcasecmp(s, "quickload2") == 0) {
+               return kActionQuickLoad2;
+       } else if (strcasecmp(s, "quicksave2") == 0) {
+               return kActionQuickSave2;
        } else {
                DIE("Bad action name: %s\n", s);
        }
 }
 
-const char * S9xFiletitle(const char * f)
+const char * S9xGetFilename(FileTypes file)
 {
-       if (!f) return 0;
-       
-       const char * p = strrchr (f, '.');
-
-       if (p)
-               return p + 1;
-
-       return f;
-}
-
-const char * S9xBasename(const char * f)
-{
-       const char * p = strrchr (f, '/');
-
-       if (p)
-               return p + 1;
+       static char filename[PATH_MAX + 1];
+       const char * ext;
+       switch (file) {
+               case FILE_ROM:
+                       return romFile;
+               case FILE_SRAM:
+                       ext = "srm";
+                       break;
+               case FILE_FREEZE:
+                       ext = "frz.gz";
+                       break;
+               case FILE_CHT:
+                       ext = "cht";
+                       break;
+               case FILE_IPS:
+                       ext = "ips";
+                       break;
+               case FILE_SCREENSHOT:
+                       ext = "png";
+                       break;
+               case FILE_SDD1_DAT:
+                       ext = "dat";
+                       break;
+               default:
+                       ext = "???";
+                       break;
+       }
 
-       return f;
+       snprintf(filename, PATH_MAX, "%s.%s", basePath, ext);
+       return filename;
 }
 
-const char * S9xGetFilename(const char * ext)
+const char * S9xGetQuickSaveFilename(unsigned int slot)
 {
-       static char filename [PATH_MAX + 1];
-       sprintf(filename, "%s%s", Config.romFile, ext);
-
+       static char filename[PATH_MAX + 1];
+       snprintf(filename, PATH_MAX, "%s.frz.%u.gz", basePath, slot);
        return filename;
 }
 
@@ -124,50 +188,33 @@ static void loadDefaults()
        ZeroMemory(&Settings, sizeof(Settings));
        ZeroMemory(&Config, sizeof(Config)); 
        
-       Config.quitting = false;
+       romFile = 0;
+       basePath = 0;
+
        Config.enableAudio = true;
-       Config.fullscreen = false;
-       Config.xsp = false;
 
-       Settings.JoystickEnabled = FALSE;
        Settings.SoundPlaybackRate = 22050;
        Settings.Stereo = TRUE;
-       Settings.SoundBufferSize = 0;
+       Settings.SoundBufferSize = 512; // in samples
        Settings.CyclesPercentage = 100;
-       Settings.DisableSoundEcho = FALSE;
-       Settings.APUEnabled = FALSE;
+       Settings.APUEnabled = FALSE;            // We'll enable it later
        Settings.H_Max = SNES_CYCLES_PER_SCANLINE;
        Settings.SkipFrames = AUTO_FRAMERATE;
        Settings.Shutdown = Settings.ShutdownMaster = TRUE;
-       Settings.FrameTimePAL = 20000;  // in usecs
-       Settings.FrameTimeNTSC = 16667;
+       Settings.FrameTimePAL = 20;     // in msecs
+       Settings.FrameTimeNTSC = 16;
        Settings.FrameTime = Settings.FrameTimeNTSC;
-       Settings.DisableSampleCaching = FALSE;
-       Settings.DisableMasterVolume = FALSE;
-       Settings.Mouse = FALSE;
-       Settings.SuperScope = FALSE;
-       Settings.MultiPlayer5 = FALSE;
-       //      Settings.ControllerOption = SNES_MULTIPLAYER5;
-       Settings.ControllerOption = 0;
-       
-       Settings.ForceTransparency = FALSE;
+       Settings.ControllerOption = SNES_JOYPAD;
+
+       Settings.ForceTransparency = FALSE;     // We'll enable those later
        Settings.Transparency = FALSE;
        Settings.SixteenBit = TRUE;
-       
+
        Settings.SupportHiRes = FALSE;
-       Settings.NetPlay = FALSE;
-       Settings.ServerName [0] = 0;
-       Settings.AutoSaveDelay = 30;
        Settings.ApplyCheats = FALSE;
        Settings.TurboMode = FALSE;
        Settings.TurboSkipFrames = 15;
-       Settings.ThreadSound = FALSE;
-       Settings.SoundSync = FALSE;
-       //Settings.NoPatch = true;
-       
-    Settings.ApplyCheats = FALSE;
-    Settings.TurboMode = FALSE;
-    
+
     Settings.ForcePAL = FALSE;
     Settings.ForceNTSC = FALSE;
 
@@ -179,42 +226,35 @@ static void loadDefaults()
        Settings.AutoSaveDelay = 15*60; // Autosave each 15 minutes.
 }
 
-static void setRomFile(const char * path)
+void S9xSetRomFile(const char * path)
 {
-       char drive[1], dir[PATH_MAX], fname[PATH_MAX], ext[PATH_MAX];
-       
-       _splitpath (path, drive, dir, fname, ext);
-       sprintf(Config.romFile, "%s%s%s", dir, strlen(dir) > 0 ? "/" : "", fname);
-}
+       if (romFile) {
+               free(romFile);
+               free(basePath);
+       }
 
-static bool gotRomFile() 
-{
-       return Config.romFile[0] != '\0';
+       romFile = strndup(path, PATH_MAX);
+       basePath = strdup(romFile);
+
+       // Truncate base path at the last '.' char
+       char * c = strrchr(basePath, '.');
+       if (c) {
+               if (strcasecmp(c, ".gz") == 0) {
+                       // Ignore the .gz part when truncating
+                       *c = '\0';
+                       c = strrchr(basePath, '.');
+                       if (c) {
+                               *c = '\0';
+                       }
+               } else {
+                       *c = '\0';
+               }
+       }
 }
 
-static void setHacks(const char * value)
+static bool gotRomFile() 
 {
-       // Unconditionally enable hacks even if no argument passed
-       Settings.HacksEnabled = TRUE;
-
-       if (!value) return;
-
-       if (strcasecmp(value, "speed-only") == 0 ||
-               strcasecmp(value, "speed") == 0 ||
-               strcasecmp(value, "s") == 0) {
-                       Settings.HacksFilter = TRUE;
-       } else if (strcasecmp(value, "yes") == 0 ||
-               strcasecmp(value, "y") == 0) {
-                       // Do nothing
-       } else if (strcasecmp(value, "no") == 0 ||
-               strcasecmp(value, "n") == 0) {
-                       Settings.HacksEnabled = FALSE;
-       } else {
-               // Hack: the user probably wants to enable hacks
-               // and use this argument as the ROM file.
-               // Wonder why popt does not support this or if there's a better way.
-               setRomFile(value);
-       }
+       return romFile ? true : false;
 }
 
 static void loadConfig(poptContext optCon, const char * file)
@@ -239,6 +279,7 @@ static void loadConfig(poptContext optCon, const char * file)
        poptStuffArgs(optCon, newargv);
 
        free(out);
+       fclose(fp);
        /* XXX: currently leaking newargv */
 }
 
@@ -248,6 +289,7 @@ static void parseArgs(poptContext optCon)
        unsigned char scancode = 0;
        
        while ((rc = poptGetNextOpt(optCon)) > 0) {
+               const char * val;
                switch (rc) {
                        case 1:
                                Config.enableAudio = false;
@@ -266,8 +308,8 @@ static void parseArgs(poptContext optCon)
                                Settings.Transparency = TRUE;
                                break;
                        case 6:
-                               Settings.HacksEnabled = TRUE;
-                               setHacks(poptGetOptArg(optCon));
+                               free(Config.scaler);
+                               Config.scaler = strdup(poptGetOptArg(optCon));
                                break;
                        case 7:
                                Settings.ForcePAL = TRUE;
@@ -281,19 +323,69 @@ static void parseArgs(poptContext optCon)
                        case 10:
                                loadConfig(optCon, poptGetOptArg(optCon));
                                break;
+                       case 11:
+                               val = poptGetOptArg(optCon);
+                               Settings.Mouse = TRUE;
+                               if (!val || atoi(val) <= 1) {
+                                       // Enable mouse on first controller
+                                       Settings.ControllerOption = SNES_MOUSE_SWAPPED;
+                               } else {
+                                       // Enable mouse on second controller
+                                       Settings.ControllerOption = SNES_MOUSE;
+                               }
+                               break;
+                       case 12:
+                               Settings.SuperScope = TRUE;
+                               Settings.ControllerOption = SNES_SUPERSCOPE;
+                               break;
+                       case 13:
+                               Config.snapshotLoad = true;
+                               Config.snapshotSave = true;
+                               break;
+                       case 14:
+                               Settings.SoundPlaybackRate = atoi(poptGetOptArg(optCon));
+                               break;
+                       case 15:
+                               Settings.SoundBufferSize = atoi(poptGetOptArg(optCon));
+                               break;
+                       case 16:
+                               Config.touchscreenInput = 1;
+                               break;
+                       case 17:
+                               Config.touchscreenInput = 1;
+                               Config.touchscreenShow = true;
+                               break;
+                       case 18:
+                               Settings.HacksEnabled = TRUE;
+                               Settings.HacksFilter = TRUE;
+                               break;
+                       case 19:
+                               Settings.HacksEnabled = TRUE;
+                               Settings.HacksFilter = FALSE;
+                               break;
+                       case 20:
+                               Config.saver = true;
+                               break;
                        case 100:
                                scancode = atoi(poptGetOptArg(optCon));
                                break;
                        case 101:
-                               Config.joypad1Mapping[scancode] |= 
+                               Config.joypad1Mapping[scancode] |=
                                        buttonNameToBit(poptGetOptArg(optCon));
+                               Config.joypad1Enabled = true;
                                break;
                        case 102:
+                               Config.joypad2Mapping[scancode] |=
+                                       buttonNameToBit(poptGetOptArg(optCon));
+                               Config.joypad2Enabled = true;
+                               break;
+                       case 110:
                                Config.action[scancode] |= 
                                        actionNameToBit(poptGetOptArg(optCon));
                                break;
                        case 200:
-                               strcpy(Config.hacksFile, poptGetOptArg(optCon));
+                               free(Config.hacksFile);
+                               Config.hacksFile = strdup(poptGetOptArg(optCon));
                                break;
                        default:
                                DIE("Invalid popt argument (this is a bug): %d", rc);
@@ -312,33 +404,55 @@ static void parseArgs(poptContext optCon)
        /* if there's an extra unparsed arg it's our rom file */
        const char * extra_arg = poptGetArg(optCon);
        if (extra_arg) 
-               setRomFile(extra_arg);
+               S9xSetRomFile(extra_arg);
 }
 
-void S9xLoadConfig(int argc, const char ** argv)
+void S9xLoadConfig(int argc, char ** argv)
 {
-       poptContext optCon =
-               poptGetContext("drnoksnes", argc, argv, optionsTable, 0);
+       poptContext optCon = poptGetContext("drnoksnes",
+               argc, const_cast<const char **>(argv), optionsTable, 0);
        poptSetOtherOptionHelp(optCon, "<rom>");
 
        // Builtin defaults
        loadDefaults();
 
-       // Read config file ~/apps/DrNokSnes.txt
+       // Read config file ~/.config/drnoksnes.conf
        char defConfFile[PATH_MAX];
-       sprintf(defConfFile, "%s/%s", getenv("HOME"), "apps/DrNokSnes.txt");
+       sprintf(defConfFile, "%s/%s", getenv("HOME"), ".config/drnoksnes.conf");
        loadConfig(optCon, defConfFile);
 
        // Command line parameters (including --conf args)
        parseArgs(optCon);
 
-       if (!gotRomFile()) {
-               fprintf(stderr, "You need to specify a ROM, like this:\n");
-               poptPrintUsage(optCon, stdout, 0);
-               poptFreeContext(optCon); 
-               exit(2);
+#if CONF_GUI
+       if (!OssoOk())
+#endif
+       {
+               if (!gotRomFile()) {
+                       // User did not specify a ROM file in the command line
+                       fprintf(stderr, "You need to specify a ROM, like this:\n");
+                       poptPrintUsage(optCon, stdout, 0);
+                       poptFreeContext(optCon);
+                       exit(2);
+               }
        }
 
        poptFreeContext(optCon);
 }
 
+void S9xUnloadConfig()
+{
+       if (romFile) {
+               free(romFile);
+               romFile = 0;
+       }
+       if (basePath) {
+               free(basePath);
+               basePath = 0;
+       }
+       if (Config.hacksFile) {
+               free(Config.hacksFile);
+               Config.hacksFile = 0;
+       }
+}
+