[gens-sdl] Options: Moved variables to a private class.
authorDavid Korth <gerbilsoft@gerbilsoft.com>
Mon, 7 Sep 2015 15:27:53 +0000 (11:27 -0400)
committerDavid Korth <gerbilsoft@gerbilsoft.com>
Mon, 7 Sep 2015 15:27:53 +0000 (11:27 -0400)
Added accessors for the internal variables.

Validate the color depth option. If it isn't 15, 16, or 32,
show an error and exit.

Sidenote: run_crazy_effect *was* handled in the previous commit,
even though I didn't mention it in the commit notes.

src/gens-sdl/EmuLoop.cpp
src/gens-sdl/EventLoop.cpp
src/gens-sdl/Options.cpp
src/gens-sdl/Options.hpp
src/gens-sdl/gens-sdl.cpp

index a898c75..af5ab02 100644 (file)
@@ -527,12 +527,13 @@ int EmuLoop::run(const Options *options)
        d->options = options;
        
        // Load the ROM image.
-       d->rom = new Rom(options->rom_filename.c_str());
+       const char *rom_filename = options->rom_filename().c_str();
+       d->rom = new Rom(rom_filename);
        if (!d->rom->isOpen()) {
                // Error opening the ROM.
                // TODO: Error code?
                fprintf(stderr, "Error opening ROM file %s: (TODO get error code)\n",
-                       options->rom_filename.c_str());
+                       rom_filename);
                delete d->rom;
                d->rom = nullptr;
                return EXIT_FAILURE;
@@ -548,7 +549,7 @@ int EmuLoop::run(const Options *options)
                // ROM format is not supported.
                const char *rom_format = romFormatToString(d->rom->romFormat());
                fprintf(stderr, "Error loading ROM file %s: ROM is in %s format.\nOnly plain binary and SMD-format ROMs are supported.\n",
-                       options->rom_filename.c_str(), rom_format);
+                       rom_filename, rom_format);
                return EXIT_FAILURE;
        }
 
@@ -557,7 +558,7 @@ int EmuLoop::run(const Options *options)
                // System is not supported.
                const char *rom_sysId = sysIdToString(d->rom->sysId());
                fprintf(stderr, "Error loading ROM file %s: ROM is for %s.\nOnly Mega Drive and Pico ROMs are supported.\n",
-                       options->rom_filename.c_str(), rom_sysId);
+                       rom_filename, rom_sysId);
                return EXIT_FAILURE;
        }
 
@@ -576,10 +577,14 @@ int EmuLoop::run(const Options *options)
                // Error loading the ROM into EmuMD.
                // TODO: Error code?
                fprintf(stderr, "Error initializing EmuContext for %s: (TODO get error code)\n",
-                       options->rom_filename.c_str());
+                       rom_filename);
                return EXIT_FAILURE;
        }
 
+       // Done using rom_filename. NULL it out to prevent
+       // issues with Options possibly deleting the string.
+       rom_filename = nullptr;
+
        // Initialize the SDL handlers.
        d->sdlHandler = new SdlHandler();
        if (d->sdlHandler->init_video() < 0)
index 8657fd7..6b45d57 100644 (file)
@@ -99,7 +99,7 @@ void EventLoopPrivate::doPauseProcessing(void)
        bool any = !!paused.data;
 
        // Set the paused effect.
-       if (options->paused_effect) {
+       if (options->paused_effect()) {
                vBackend->setPausedEffect(manual);
        } else {
                vBackend->setPausedEffect(false);
@@ -287,14 +287,14 @@ int EventLoop::processSdlEvent(const SDL_Event *event)
                                        break;
                                case SDL_WINDOWEVENT_FOCUS_LOST:
                                        // If AutoPause is enabled, pause the emulator.
-                                       if (d_ptr->options->auto_pause) {
+                                       if (d_ptr->options->auto_pause()) {
                                                d_ptr->doAutoPause(true);
                                        }
                                        break;
                                case SDL_WINDOWEVENT_FOCUS_GAINED:
                                        // If AutoPause is enabled, unpause the emulator.
                                        // TODO: Always run this, even if !autoPause?
-                                       if (d_ptr->options->auto_pause) {
+                                       if (d_ptr->options->auto_pause()) {
                                                d_ptr->doAutoPause(false);
                                        }
                                        break;
index 97cbe8f..52251f6 100644 (file)
@@ -37,7 +37,58 @@ using std::string;
 
 namespace GensSdl {
 
-Options::Options()
+class OptionsPrivate
+{
+       public:
+               OptionsPrivate();
+
+       private:
+               friend class Options;
+       private:
+               // Q_DISABLE_COPY() equivalent.
+               // TODO: Add GensSdl-specific version of Q_DISABLE_COPY().
+               OptionsPrivate(const OptionsPrivate &);
+               OptionsPrivate &operator=(const OptionsPrivate &);
+
+       public:
+               /**
+                * Reset all options to their default values.
+                */
+               void reset(void);
+
+       public:
+               // Options set by the caller.
+               bool rom_filename_required;
+
+               // NOTE: bool values are ints for compatibility
+               // with popt. The accessor functions normalize
+               // the ints to bool.
+               // TODO: Convert to bool to make access faster?
+               string rom_filename;            // ROM to load.
+               string tmss_rom_filename;       // TMSS ROM image.
+
+               // Audio options.
+               int sound_freq;                 // Sound frequency.
+               int stereo;                     // Stereo audio?
+
+               // Emulation options.
+               int sprite_limits;              // Enable sprite limits?
+               int auto_fix_checksum;          // Auto fix checksum?
+
+               // UI options.
+               int fps_counter;                // Enable FPS counter?
+               int auto_pause;                 // Auto pause?
+               int paused_effect;              // Paused effect?
+               int bpp;                        // Color depth. (15, 16, 32)
+
+               // Special run modes.
+               int run_crazy_effect;           // Run the Crazy Effect
+};
+
+/** OptionsPrivate **/
+
+OptionsPrivate::OptionsPrivate()
+       : rom_filename_required(true)
 {
        // Reset the options to the default values.
        reset();
@@ -45,15 +96,13 @@ Options::Options()
 
 /**
  * Reset all options to their default values.
+ * This does NOT include caller-set options.
  */
-void Options::reset(void)
+void OptionsPrivate::reset(void)
 {
-       rom_filename_required = true;
-
        // TODO: Swap with empty strings?
        rom_filename.clear();
        tmss_rom_filename.clear();
-       tmss_enabled = false;
 
        // Audio options.
        sound_freq = 44100;
@@ -73,6 +122,25 @@ void Options::reset(void)
        run_crazy_effect = false;
 }
 
+/** Options **/
+
+Options::Options()
+       : d(new OptionsPrivate())
+{ }
+
+Options::~Options()
+{
+       delete d;
+}
+
+/**
+ * Reset all options to their default values.
+ */
+void Options::reset(void)
+{
+       d->reset();
+}
+
 // TODO: Improve these.
 static void print_prg_info(void)
 {
@@ -123,43 +191,18 @@ int Options::parse(int argc, const char *argv[])
                return -EINVAL;
        }
 
+       // Reset the options.
+       reset();
+
        // Temporary internal option variables.
+       // Required for strings, since popt uses
+       // const char*, so we have to copy them
+       // to standard C++ strings later.
        struct {
-               // popt is a C library, so we have to use
-               // C strings here initially. Also, we can't
-               // use bool; we have to use int.
                const char *rom_filename;
                const char *tmss_rom_filename;
-               // tmss_enabled is implied by tmss_rom_filename.
-
-               // Audio options.
-               int sound_freq;
-               int stereo;
-
-               // Emulation options.
-               int sprite_limits;
-               int auto_fix_checksum;
-
-               // UI options.
-               int fps_counter;
-               int auto_pause;
-               int paused_effect;
-               int bpp;
-
-               // Special run modes.
-               int run_crazy_effect;
        } tmp;
-
-       // Set default values.
-       // TODO: Separate function for this?
        memset(&tmp, 0, sizeof(tmp));
-       tmp.sound_freq = 44100;
-       tmp.stereo = 1;
-       tmp.sprite_limits = 1;
-       tmp.auto_fix_checksum = 1;
-       tmp.fps_counter = 1;
-       tmp.paused_effect = 1;
-       tmp.bpp = 32;
 
        // NOTE: rom_filename is provided as a non-option parameter.
        // It will get parsed later.
@@ -174,50 +217,50 @@ int Options::parse(int argc, const char *argv[])
 
        // popt: audio options table.
        struct poptOption audioOptionsTable[] = {
-               {"frequency", 0, POPT_ARG_INT, &tmp.sound_freq, 0,
+               {"frequency", 0, POPT_ARG_INT, &d->sound_freq, 0,
                        "  Audio frequency.", "FREQ"},
-               {"mono", 0, POPT_ARG_VAL, &tmp.stereo, 0,
+               {"mono", 0, POPT_ARG_VAL, &d->stereo, 0,
                        "  Use monaural audio.", NULL},
-               {"stereo", 0, POPT_ARG_VAL, &tmp.stereo, 1,
+               {"stereo", 0, POPT_ARG_VAL, &d->stereo, 1,
                        "  Use stereo audio.", NULL},
                POPT_TABLEEND
        };
 
        // popt: emulation options table.
        struct poptOption emulationOptionsTable[] = {
-               {"sprite-limits", 0, POPT_ARG_VAL, &tmp.sprite_limits, 1,
+               {"sprite-limits", 0, POPT_ARG_VAL, &d->sprite_limits, 1,
                        "* Enable sprite limits.", NULL},
-               {"no-sprite-limits", 0, POPT_ARG_VAL, &tmp.sprite_limits, 0,
+               {"no-sprite-limits", 0, POPT_ARG_VAL, &d->sprite_limits, 0,
                        "  Disable sprite limits.", NULL},
-               {"auto-fix-checksum", 0, POPT_ARG_VAL, &tmp.auto_fix_checksum, 1,
+               {"auto-fix-checksum", 0, POPT_ARG_VAL, &d->auto_fix_checksum, 1,
                        "* Automatically fix checksums.", NULL},
-               {"no-auto-fix-checksum", 0, POPT_ARG_VAL, &tmp.auto_fix_checksum, 0,
+               {"no-auto-fix-checksum", 0, POPT_ARG_VAL, &d->auto_fix_checksum, 0,
                        "  Don't automatically fix checksums.", NULL},
                POPT_TABLEEND
        };
 
        // popt: UI options table.
        struct poptOption uiOptionsTable[] = {
-               {"fps", 0, POPT_ARG_VAL, &tmp.fps_counter, 1,
+               {"fps", 0, POPT_ARG_VAL, &d->fps_counter, 1,
                        "* Enable the FPS counter.", NULL},
-               {"no-fps", 0, POPT_ARG_VAL, &tmp.fps_counter, 0,
+               {"no-fps", 0, POPT_ARG_VAL, &d->fps_counter, 0,
                        "  Disable the FPS counter.", NULL},
-               {"auto-pause", 0, POPT_ARG_VAL, &tmp.auto_pause, 1,
+               {"auto-pause", 0, POPT_ARG_VAL, &d->auto_pause, 1,
                        "* Pause emulator when focus is lost.", NULL},
-               {"no-auto-pause", 0, POPT_ARG_VAL, &tmp.auto_pause, 0,
+               {"no-auto-pause", 0, POPT_ARG_VAL, &d->auto_pause, 0,
                        "  Don't pause emulator when focus is lost.", NULL},
-               {"paused-effect", 0, POPT_ARG_VAL, &tmp.paused_effect, 1,
+               {"paused-effect", 0, POPT_ARG_VAL, &d->paused_effect, 1,
                        "* Tint the window when paused.", NULL},
-               {"no-paused-effect", 0, POPT_ARG_VAL, &tmp.paused_effect, 0,
+               {"no-paused-effect", 0, POPT_ARG_VAL, &d->paused_effect, 0,
                        "  Don't tint the window when paused.", NULL},
-               {"bpp", 0, POPT_ARG_INT, &tmp.bpp, 0,
+               {"bpp", 0, POPT_ARG_INT, &d->bpp, 0,
                        "  Set the internal color depth. (15, 16, 32)", "BPP"},
                POPT_TABLEEND
        };
 
        // popt: Special run modes table.
        struct poptOption runModesTable[] = {
-               {"crazy-effect", 0, POPT_ARG_VAL, &tmp.run_crazy_effect, 1,
+               {"crazy-effect", 0, POPT_ARG_VAL, &d->run_crazy_effect, 1,
                        "  Run the \"Crazy\" Effect instead of loading a ROM.", NULL},
                POPT_TABLEEND
        };
@@ -242,7 +285,7 @@ int Options::parse(int argc, const char *argv[])
        // Create the popt context.
        poptContext optCon = poptGetContext(NULL, argc, argv, optionsTable, 0);
        poptSetOtherOptionHelp(optCon, "[rom_file]");
-       if (rom_filename_required && argc < 2) {
+       if (d->rom_filename_required && argc < 2) {
                poptPrintUsage(optCon, stderr, 0);
                return -EINVAL;
        }
@@ -310,8 +353,7 @@ int Options::parse(int argc, const char *argv[])
        // TMSS ROM filename.
        if (tmp.tmss_rom_filename != nullptr) {
                // TMSS ROM filename was specified.
-               this->tmss_rom_filename = string(tmss_rom_filename);
-               this->tmss_enabled = true;
+               d->tmss_rom_filename = string(tmp.tmss_rom_filename);
        }
 
        // Get the ROM filename.
@@ -321,8 +363,8 @@ int Options::parse(int argc, const char *argv[])
        tmp.rom_filename = poptGetArg(optCon);
        if (tmp.rom_filename != nullptr) {
                // ROM filename was specified.
-               this->rom_filename = string(tmp.rom_filename);
-       } else if (this->rom_filename_required && !tmp.run_crazy_effect) {
+               d->rom_filename = string(tmp.rom_filename);
+       } else if (d->rom_filename_required && !d->run_crazy_effect) {
                // A ROM is required, but wasn't specified.
                // (If --crazy-effect is specified, this is ignored.)
                fprintf(stderr, "%s: no ROM filename specified\n"
@@ -342,35 +384,85 @@ int Options::parse(int argc, const char *argv[])
                return -EINVAL;
        }
 
-       // Copy other arguments.
-       // TODO: Verify that they're valid.
-
-       // Audio options.
-       this->sound_freq = tmp.sound_freq;
-       this->stereo = !!tmp.stereo;
-
-       // Emulation options.
-       this->sprite_limits = !!tmp.sprite_limits;
-       this->auto_fix_checksum = !!tmp.auto_fix_checksum;
-
-       // UI options.
-       this->fps_counter = !!tmp.fps_counter;
-       this->auto_pause = !!tmp.auto_pause;
-       this->paused_effect = !!tmp.paused_effect;
-
-       if (tmp.bpp == 15 || tmp.bpp == 16 || tmp.bpp == 32) {
-               this->bpp = (uint8_t)tmp.bpp;
-       } else {
-               // TODO: Show an error.
-               this->bpp = 32;
+       // Verify certain options.
+       if (d->bpp != 15 && d->bpp != 16 && d->bpp != 32) {
+               // Invalid color depth.
+               fprintf(stderr, "%s: '--bpp=%d': invalid color depth\n"
+                       "Valid options are 15, 16, and 32.\n"
+                       "Try `%s --help` for more information.\n",
+                       argv[0], d->bpp, argv[0]);
+               poptFreeContext(optCon);
+               return -EINVAL;
        }
 
-       // Special run modes.
-       this->run_crazy_effect = !!tmp.run_crazy_effect;
-
        // Done parsing arguments.
        poptFreeContext(optCon);
        return 0;
 }
 
+/** Options set by the caller. **/
+
+/**
+ * Is a ROM filename required?
+ * @return True if a ROM filename is required; false if not.
+ */
+bool Options::is_rom_filename_required(void) const
+{
+       return d->rom_filename_required;
+}
+
+/**
+ * Set if a ROM filename should be required.
+ * @param rom_filename_required True if a ROM filename is required; false if not.
+ */
+void Options::set_rom_filename_required(bool rom_filename_required)
+{
+       d->rom_filename_required = rom_filename_required;
+}
+
+/** Parameter accessors. **/
+
+#define ACCESSOR(type, name) \
+type Options::name(void) const \
+{ \
+       return (type)d->name; \
+}
+
+#define ACCESSOR_BOOL(name) \
+bool Options::name(void) const \
+{ \
+       return !!d->name; \
+}
+
+/** General options. **/
+ACCESSOR(string, rom_filename)
+ACCESSOR(string, tmss_rom_filename)
+
+/**
+ * Is TMSS enabled?
+ * This option is implied by the presence of a TMSS ROM filename.
+ * @return True if TMSS is enabled; false if not.
+ */
+bool Options::is_tmss_enabled(void) const
+{
+       return !d->tmss_rom_filename.empty();
+}
+
+/** Audio options. **/
+ACCESSOR(int, sound_freq)
+ACCESSOR_BOOL(stereo)
+
+/** Emulation options. **/
+ACCESSOR_BOOL(sprite_limits)
+ACCESSOR_BOOL(auto_fix_checksum)
+
+/** UI options. **/
+ACCESSOR_BOOL(fps_counter)
+ACCESSOR_BOOL(auto_pause)
+ACCESSOR_BOOL(paused_effect)
+ACCESSOR(uint8_t, bpp)
+
+/** Special run modes. **/
+ACCESSOR_BOOL(run_crazy_effect)
+
 }
index da3b335..26a12b0 100644 (file)
 
 namespace GensSdl {
 
+class OptionsPrivate;
 class Options
 {
        public:
                Options();
+               ~Options();
 
        private:
+               friend class OptionsPrivate;
+               OptionsPrivate *const d;
+       private:
                // Q_DISABLE_COPY() equivalent.
                // TODO: Add GensSdl-specific version of Q_DISABLE_COPY().
                Options(const Options &);
@@ -53,36 +58,101 @@ class Options
                int parse(int argc, const char *argv[]);
 
        public:
+               /** Options set by the caller. **/
+
                /**
                 * Is a ROM filename required?
-                * Set this before calling parse().
+                * @return True if a ROM filename is required; false if not.
+                */
+               bool is_rom_filename_required(void) const;
+
+               /**
+                * Set if a ROM filename should be required.
+                * @param rom_filename_required True if a ROM filename is required; false if not.
                 */
-               bool rom_filename_required;
+               void set_rom_filename_required(bool rom_filename_required);
 
        public:
                /** Command line parameters. **/
-               // TODO: Use accessors instead?
-               std::string rom_filename;       // ROM to load.
-               std::string tmss_rom_filename;  // TMSS ROM image.
-               bool tmss_enabled;              // Enable TMSS?
-
-               // Audio options.
-               int sound_freq;                 // Sound frequency.
-               bool stereo;                    // Stereo audio?
-
-               // Emulation options.
-               bool sprite_limits;             // Enable sprite limits?
-               bool auto_fix_checksum;         // Auto fix checksum?
-
-               // UI options.
-               bool fps_counter;               // Enable FPS counter?
-               bool auto_pause;                // Auto pause?
-               bool paused_effect;             // Paused effect?
-               uint8_t bpp;                    // Color depth. (15, 16, 32)
-
-               // Special run modes.
-               bool run_crazy_effect;          // Run the Crazy Effect
-                                               // instead of loading a ROM?
+
+               /**
+                * Get the filename of the ROM to load.
+                */
+               std::string rom_filename(void) const;
+
+               /**
+                * Get the filename of the TMSS ROM to load.
+                */
+               std::string tmss_rom_filename(void) const;
+
+               /**
+                * Is TMSS enabled?
+                * This option is implied by the presence of a TMSS ROM filename.
+                * @return True if TMSS is enabled; false if not.
+                */
+               bool is_tmss_enabled(void) const;
+
+               /** Audio options. **/
+
+               /**
+                * Get the requested sound frequency.
+                * @return Sound frequency.
+                */
+               int sound_freq(void) const;
+
+               /**
+                * Use stereo audio?
+                * @return True for stereo; false for monaural.
+                */
+               bool stereo(void) const;
+
+               /** Emulation options. **/
+
+               /**
+                * Enable sprite limits?
+                * @return True to enable; false to disable.
+                */
+               bool sprite_limits(void) const;
+
+               /**
+                * Automatically fix checksums?
+                * @return True to auto-fix; false to not.
+                */
+               bool auto_fix_checksum(void) const;
+
+               /** UI options. **/
+
+               /**
+                * Enable the FPS counter?
+                * @return True to enable; false to disable.
+                */
+               bool fps_counter(void) const;
+
+               /**
+                * Automatically pause the emulator when focus is lost?
+                * @return True to automatically pause; false to not.
+                */
+               bool auto_pause(void) const;
+
+               /**
+                * Use the paused effect when the emulator is manually paused?
+                * @return True to use the paused effect; false to not.
+                */
+               bool paused_effect(void) const;
+
+               /**
+                * Color depth to use. (15, 16, 32)
+                * @return Color depth.
+                */
+               uint8_t bpp(void) const;
+
+               /** Special run modes. **/
+
+               /**
+                * Run the Crazy Effect instead of loading a ROM?
+                * @return True to run the Crazy Effect.
+                */
+               bool run_crazy_effect(void) const;
 };
 
 }
index 8169e6d..8bb0992 100644 (file)
@@ -174,7 +174,7 @@ int run(void)
        // Register the LibGens OSD handler.
        lg_set_osd_fn(gsdl_osd);
 
-       if (options->run_crazy_effect) {
+       if (options->run_crazy_effect()) {
                // Run the Crazy Effect.
                eventLoop = new CrazyEffectLoop();
        } else {
@@ -209,7 +209,7 @@ int main(int argc, char *argv[])
 
        // Parse command line options.
        GensSdl::options = new GensSdl::Options();
-       GensSdl::options->rom_filename_required = true;
+       GensSdl::options->set_rom_filename_required(true);
        int ret = GensSdl::options->parse(argc, (const char**)argv);
        if (ret != 0) {
                // Error parsing command line options.