[gens-sdl] EventLoop: New function processSdlEventQueue().
authorDavid Korth <gerbilsoft@gerbilsoft.com>
Thu, 3 Sep 2015 04:27:14 +0000 (00:27 -0400)
committerDavid Korth <gerbilsoft@gerbilsoft.com>
Thu, 3 Sep 2015 04:27:14 +0000 (00:27 -0400)
This consolidates the pause, OSD processing, and video expose handling
from EmuLoop and CrazyEffectLoop into a single function.

TODO:
- Wait for what would be the next frame when emulation is paused?
  (This is in EmuLoop and CrazyEffectLoop, not processSdlEventQueue().)
- paused_t: Add assign/copy constructors and operator==(), or are they
  even needed?

src/gens-sdl/CrazyEffectLoop.cpp
src/gens-sdl/EmuLoop.cpp
src/gens-sdl/EventLoop.cpp
src/gens-sdl/EventLoop.hpp
src/gens-sdl/EventLoop_p.hpp

index 917a06b..6fdf8a0 100644 (file)
@@ -134,50 +134,23 @@ int CrazyEffectLoop::run(const char *rom_filename)
        // TODO: Move some more common stuff back to gens-sdl.cpp.
        d->running = true;
        while (d->running) {
-               SDL_Event event;
-               int ret;
-               if (d->paused.data) {
-                       // Emulation is paused.
-                       if (!d->vBackend->has_osd_messages()) {
-                               // No OSD messages.
-                               // Wait for an SDL event.
-                               ret = SDL_WaitEvent(&event);
-                               if (ret) {
-                                       processSdlEvent(&event);
-                               }
-                       }
-
-                       // Process OSD messages.
-                       d->vBackend->process_osd_messages();
-               }
-               if (!d->running)
+               // Process the SDL event queue.
+               processSdlEventQueue();
+               if (!d->running) {
+                       // Emulation has stopped.
                        break;
-
-               // Poll for SDL events, and wait for the queue
-               // to empty. This ensures that we don't end up
-               // only processing one event per frame.
-               do {
-                       ret = SDL_PollEvent(&event);
-                       if (ret) {
-                               processSdlEvent(&event);
-                       }
-               } while (d->running && ret != 0);
-               if (!d->running)
+               }
+               if (!d->running) {
+                       // Emulation has stopped.
                        break;
-
+               }
                if (d->paused.data) {
                        // Emulation is paused.
-                       // Only update video if the VBackend is dirty
-                       // or the SDL window has been exposed.
-                       d->sdlHandler->update_video_paused(d->exposed);
-
                        // Don't run any frames.
+                       // TODO: Wait for what would be the next frame?
                        continue;
                }
 
-               // Clear the 'exposed' flag.
-               d->exposed = false;
-
                // New start time.
                d->clks.new_clk = d->clks.timing.getTime();
 
index aea8715..483aaf6 100644 (file)
@@ -97,6 +97,11 @@ class EmuLoopPrivate : public EventLoopPrivate
                // Keymaps.
                static const GensKey_t keyMap_md[];
                static const GensKey_t keyMap_pico[];
+
+               // Last 'paused' value.
+               // Used to determine if SRAM/EEPROM
+               // should be autosaved.
+               paused_t last_paused;
 };
 
 /** EmuLoopPrivate **/
@@ -122,7 +127,9 @@ EmuLoopPrivate::EmuLoopPrivate()
        , emuContext(nullptr)
        , keyManager(nullptr)
        , saveSlot_selected(0)
-{ }
+{
+       last_paused.data = 0;
+}
 
 EmuLoopPrivate::~EmuLoopPrivate()
 {
@@ -582,62 +589,36 @@ int EmuLoop::run(const char *rom_filename)
        }
 
        // TODO: Move some more common stuff back to gens-sdl.cpp.
-       uint8_t old_paused = 0;
        d->running = true;
+       d->paused.data = 0;
+       d->last_paused.data = 0;
        while (d->running) {
-               SDL_Event event;
-               int ret;
-               if (d->paused.data) {
-                       // Emulation is paused.
-                       if (!d->vBackend->has_osd_messages()) {
-                               // No OSD messages.
-                               // Wait for an SDL event.
-                               ret = SDL_WaitEvent(&event);
-                               if (ret) {
-                                       processSdlEvent(&event);
-                               }
-                       }
-
-                       // Process OSD messages.
-                       d->vBackend->process_osd_messages();
-               }
-               if (!d->running)
-                       break;
-
-               // Poll for SDL events, and wait for the queue
-               // to empty. This ensures that we don't end up
-               // only processing one event per frame.
-               do {
-                       ret = SDL_PollEvent(&event);
-                       if (ret) {
-                               processSdlEvent(&event);
-                       }
-               } while (d->running && ret != 0);
-               if (!d->running)
+               // Process the SDL event queue.
+               processSdlEventQueue();
+               if (!d->running) {
+                       // Emulation has stopped.
                        break;
+               }
 
                // Check if the 'paused' state was changed.
                // If it was, autosave SRAM/EEPROM.
-               if (old_paused != d->paused.data) {
+               if (d->last_paused.data != d->paused.data) {
                        // 'paused' state was changed.
                        // (TODO: Only if paused == true?)
+                       // TODO: Evaluate both fields as boolean,
+                       // so switching from manual to manual+auto
+                       // or vice-versa doesn't trigger an autosave?
                        d->emuContext->autoSaveData(-1);
-                       old_paused = d->paused.data;
+                       d->last_paused.data = d->paused.data;
                }
 
                if (d->paused.data) {
                        // Emulation is paused.
-                       // Only update video if the VBackend is dirty
-                       // or the SDL window has been exposed.
-                       d->sdlHandler->update_video_paused(d->exposed);
-
                        // Don't run any frames.
+                       // TODO: Wait for what would be the next frame?
                        continue;
                }
 
-               // Clear the 'exposed' flag.
-               d->exposed = false;
-
                // New start time.
                d->clks.new_clk = d->clks.timing.getTime();
 
index 3328771..a102045 100644 (file)
@@ -292,4 +292,54 @@ int EventLoop::processSdlEvent(const SDL_Event *event)
        return ret;
 }
 
+/**
+ * Process the SDL event queue.
+ * If emulation is paused and the OSD message,
+ * list is empty, SDL_WaitEvent() will be used
+ * to wait for the next event.
+ */
+void EventLoop::processSdlEventQueue(void)
+{
+       SDL_Event event;
+       int ret;
+       if (d_ptr->paused.data) {
+               // Emulation is paused.
+               if (!d_ptr->vBackend->has_osd_messages()) {
+                       // No OSD messages.
+                       // Wait for an SDL event.
+                       ret = SDL_WaitEvent(&event);
+                       if (ret) {
+                               processSdlEvent(&event);
+                       }
+               }
+
+               // Process OSD messages.
+               d_ptr->vBackend->process_osd_messages();
+       }
+       if (!d_ptr->running)
+               return;
+
+       // Poll for SDL events, and wait for the queue
+       // to empty. This ensures that we don't end up
+       // only processing one event per frame.
+       do {
+               ret = SDL_PollEvent(&event);
+               if (ret) {
+                       processSdlEvent(&event);
+               }
+       } while (d_ptr->running && ret != 0);
+       if (!d_ptr->running)
+               return;
+
+       if (d_ptr->paused.data) {
+               // Emulation is paused.
+               // Only update video if the VBackend is dirty
+               // or the SDL window has been exposed.
+               d_ptr->sdlHandler->update_video_paused(d_ptr->exposed);
+       }
+
+       // Clear the 'exposed' flag.
+       d_ptr->exposed = false;
+}
+
 }
index 408de79..2935f32 100644 (file)
@@ -73,6 +73,14 @@ class EventLoop
                 * @return 0 if the event was handled; non-zero if it wasn't.
                 */
                virtual int processSdlEvent(const SDL_Event *event);
+
+               /**
+                * Process the SDL event queue.
+                * If emulation is paused and the OSD message,
+                * list is empty, SDL_WaitEvent() will be used
+                * to wait for the next event.
+                */
+               void processSdlEventQueue(void);
 };
 
 }
index f4f0e19..6a91801 100644 (file)
@@ -110,8 +110,9 @@ class EventLoopPrivate
                                uint8_t focus   : 1;    // Auto pause when focus is lost.
                        };
                        uint8_t data;
+                       // TODO: Add assign/copy constructors and operator==()?
                };
-               paused_t paused;
+               paused_t paused;        // Current 'paused' value.
 
                // Automatically pause when the window loses focus?
                bool autoPause;