diff --git a/CHANGES b/CHANGES
index 60e577875..4b991547a 100644
--- a/CHANGES
+++ b/CHANGES
@@ -14,6 +14,7 @@ Features:
- Remappable controls for tilt and gyroscope sensors
- Status messages for actions taken while a game is running (e.g. save/load state)
- Memory inspector
+ - Screensaver can now be suspended while a game is running
Bugfixes:
- GBA: Fix timers not updating timing when writing to only the reload register
- All: Fix sanitize-deb script not cleaning up after itself
diff --git a/src/gba/supervisor/config.c b/src/gba/supervisor/config.c
index 437f0e104..b497218ab 100644
--- a/src/gba/supervisor/config.c
+++ b/src/gba/supervisor/config.c
@@ -204,6 +204,9 @@ void GBAConfigMap(const struct GBAConfig* config, struct GBAOptions* opts) {
if (_lookupIntValue(config, "resampleVideo", &fakeBool)) {
opts->resampleVideo = fakeBool;
}
+ if (_lookupIntValue(config, "suspendScreensaver", &fakeBool)) {
+ opts->suspendScreensaver = fakeBool;
+ }
if (_lookupIntValue(config, "mute", &fakeBool)) {
opts->mute = fakeBool;
}
@@ -251,6 +254,7 @@ void GBAConfigLoadDefaults(struct GBAConfig* config, const struct GBAOptions* op
ConfigurationSetIntValue(&config->defaultsTable, 0, "mute", opts->mute);
ConfigurationSetIntValue(&config->defaultsTable, 0, "lockAspectRatio", opts->lockAspectRatio);
ConfigurationSetIntValue(&config->defaultsTable, 0, "resampleVideo", opts->resampleVideo);
+ ConfigurationSetIntValue(&config->defaultsTable, 0, "suspendScreensaver", opts->suspendScreensaver);
switch (opts->idleOptimization) {
case IDLE_LOOP_IGNORE:
diff --git a/src/gba/supervisor/config.h b/src/gba/supervisor/config.h
index fd3eaba82..86c5a93cc 100644
--- a/src/gba/supervisor/config.h
+++ b/src/gba/supervisor/config.h
@@ -35,6 +35,7 @@ struct GBAOptions {
int height;
bool lockAspectRatio;
bool resampleVideo;
+ bool suspendScreensaver;
int volume;
bool mute;
diff --git a/src/platform/qt/ConfigController.cpp b/src/platform/qt/ConfigController.cpp
index 559c9fc6c..ba4978bac 100644
--- a/src/platform/qt/ConfigController.cpp
+++ b/src/platform/qt/ConfigController.cpp
@@ -114,6 +114,7 @@ ConfigController::ConfigController(QObject* parent)
m_opts.rewindBufferInterval = 0;
m_opts.rewindBufferCapacity = 0;
m_opts.useBios = true;
+ m_opts.suspendScreensaver = true;
GBAConfigLoadDefaults(&m_config, &m_opts);
GBAConfigLoad(&m_config);
GBAConfigMap(&m_config, &m_opts);
diff --git a/src/platform/qt/InputController.cpp b/src/platform/qt/InputController.cpp
index 2c378b586..9cb20f999 100644
--- a/src/platform/qt/InputController.cpp
+++ b/src/platform/qt/InputController.cpp
@@ -469,3 +469,17 @@ void InputController::clearPendingEvent(GBAKey key) {
bool InputController::hasPendingEvent(GBAKey key) const {
return m_pendingEvents.contains(key);
}
+
+#if defined(BUILD_SDL) && SDL_VERSION_ATLEAST(2, 0, 0)
+void InputController::suspendScreensaver() {
+ GBASDLSuspendScreensaver(&s_sdlEvents);
+}
+
+void InputController::resumeScreensaver() {
+ GBASDLResumeScreensaver(&s_sdlEvents);
+}
+
+void InputController::setScreensaverSuspendable(bool suspendable) {
+ GBASDLSetScreensaverSuspendable(&s_sdlEvents, suspendable);
+}
+#endif
diff --git a/src/platform/qt/InputController.h b/src/platform/qt/InputController.h
index ab8fb12d8..05493db8e 100644
--- a/src/platform/qt/InputController.h
+++ b/src/platform/qt/InputController.h
@@ -80,6 +80,13 @@ public:
public slots:
void testGamepad(int type);
+#if defined(BUILD_SDL) && SDL_VERSION_ATLEAST(2, 0, 0)
+ // TODO: Move these to somewhere that makes sense
+ void suspendScreensaver();
+ void resumeScreensaver();
+ void setScreensaverSuspendable(bool);
+#endif
+
private:
void postPendingEvent(GBAKey);
void clearPendingEvent(GBAKey);
diff --git a/src/platform/qt/SettingsView.cpp b/src/platform/qt/SettingsView.cpp
index 44aa13a20..e18e4a686 100644
--- a/src/platform/qt/SettingsView.cpp
+++ b/src/platform/qt/SettingsView.cpp
@@ -34,6 +34,7 @@ SettingsView::SettingsView(ConfigController* controller, QWidget* parent)
loadSetting("rewindBufferCapacity", m_ui.rewindCapacity);
loadSetting("resampleVideo", m_ui.resampleVideo);
loadSetting("allowOpposingDirections", m_ui.allowOpposingDirections);
+ loadSetting("suspendScreensaver", m_ui.suspendScreensaver);
QString idleOptimization = loadSetting("idleOptimization");
if (idleOptimization == "ignore") {
@@ -87,6 +88,7 @@ void SettingsView::updateConfig() {
saveSetting("rewindBufferCapacity", m_ui.rewindCapacity);
saveSetting("resampleVideo", m_ui.resampleVideo);
saveSetting("allowOpposingDirections", m_ui.allowOpposingDirections);
+ saveSetting("suspendScreensaver", m_ui.suspendScreensaver);
switch (m_ui.idleOptimization->currentIndex() + IDLE_LOOP_IGNORE) {
case IDLE_LOOP_IGNORE:
diff --git a/src/platform/qt/SettingsView.ui b/src/platform/qt/SettingsView.ui
index b7e371dea..3d9b1d22f 100644
--- a/src/platform/qt/SettingsView.ui
+++ b/src/platform/qt/SettingsView.ui
@@ -6,8 +6,8 @@
0
0
- 374
- 608
+ 656
+ 366
@@ -21,21 +21,21 @@
-
-
-
- QFormLayout::ExpandingFieldsGrow
-
-
-
-
-
- BIOS file:
+
+
-
+
+
+ QFormLayout::ExpandingFieldsGrow
-
-
- -
-
-
-
-
+
-
+
+
+ Audio driver:
+
+
+
+ -
+
0
@@ -44,346 +44,371 @@
- -
-
+
-
+
- Browse
+ Audio buffer:
-
-
- -
-
-
- Skip BIOS intro
-
-
-
- -
-
-
- Use BIOS file
-
-
- true
-
-
-
- -
-
-
- Qt::Horizontal
-
-
-
- -
-
-
- Audio driver:
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
-
- -
-
-
- Audio buffer:
-
-
-
- -
-
-
-
-
-
- true
-
-
- 2048
-
-
- 2
-
+
-
+
-
-
- 512
-
+
+
+ true
+
+
+ 2048
+
+
+ 2
+
+
-
+
+ 512
+
+
+ -
+
+ 1024
+
+
+ -
+
+ 2048
+
+
+ -
+
+ 4096
+
+
+
-
-
- 1024
-
+
+
+ samples
+
+
- -
-
- 2048
-
-
- -
-
- 4096
-
-
-
+
- -
-
+
-
+
- samples
+ Volume:
-
-
- -
-
-
- Volume:
-
-
-
- -
-
-
-
-
-
- 256
-
-
- 16
-
-
- 256
-
+
-
+
+
-
+
+
+ 256
+
+
+ 16
+
+
+ 256
+
+
+ Qt::Horizontal
+
+
+
+ -
+
+
+ Mute
+
+
+
+
+
+ -
+
Qt::Horizontal
- -
-
+
-
+
- Mute
+ Sync:
+
+
+
+ -
+
+
-
+
+
+ Video
+
+
+
+ -
+
+
+ Audio
+
+
+
+
+
+ -
+
+
+ Frameskip:
+
+
+
+ -
+
+
-
+
+
+ Skip every
+
+
+
+ -
+
+
+ -
+
+
+ frames
+
+
+
+
+
+ -
+
+
+ FPS target:
+
+
+
+ -
+
+
-
+
+
+ 240
+
+
+ 60
+
+
+
+ -
+
+
+ frames per second
+
+
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ -
+
+
+ Lock aspect ratio
+
+
+
+ -
+
+
+ Resample video
+
+
+
+ -
+
+
+ Suspend screensaver
+
+
+ true
- -
-
+
-
+
- Qt::Horizontal
+ Qt::Vertical
- -
-
-
- Sync:
-
-
-
- -
-
-
-
-
+
-
+
+
-
+
- Video
+ BIOS file:
- -
-
+
-
+
+
-
+
+
+
+ 0
+ 0
+
+
+
+
+ -
+
+
+ Browse
+
+
+
+
+
+ -
+
- Audio
+ Skip BIOS intro
+ -
+
+
+ Use BIOS file
+
+
+ true
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ -
+
+
+ Enable rewind
+
+
+
+ -
+
+
+ Rewind interval:
+
+
+
+ -
+
+
-
+
+
+ Every
+
+
+
+ -
+
+
+ -
+
+
+ frames
+
+
+
+
+
+ -
+
+
+ Rewind length:
+
+
+
+ -
+
+
-
+
+
+ -
+
+
+ intervals
+
+
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ -
+
+
+ Allow opposing input directions
+
+
+
+ -
+
+
+ Idle loops
+
+
+
+ -
+
+
-
+
+ Run all
+
+
+ -
+
+ Remove known
+
+
+ -
+
+ Detect and remove
+
+
+
+
- -
-
-
- Frameskip:
-
-
-
- -
-
-
-
-
-
- Skip every
-
-
-
- -
-
-
- -
-
-
- frames
-
-
-
-
-
- -
-
-
- FPS target:
-
-
-
- -
-
-
-
-
-
- 240
-
-
- 60
-
-
-
- -
-
-
- frames per second
-
-
-
-
-
- -
-
-
- Lock aspect ratio
-
-
-
- -
-
-
- Resample video
-
-
-
- -
-
-
- Qt::Horizontal
-
-
-
- -
-
-
- Enable rewind
-
-
-
- -
-
-
- Rewind interval:
-
-
-
- -
-
-
-
-
-
- Every
-
-
-
- -
-
-
- -
-
-
- frames
-
-
-
-
-
- -
-
-
- Rewind length:
-
-
-
- -
-
-
-
-
-
- -
-
-
- intervals
-
-
-
-
-
- -
-
-
- Allow opposing input directions
-
-
-
- -
-
-
- Qt::Horizontal
-
-
-
- -
-
-
- Idle loops
-
-
-
- -
-
-
-
-
- Run all
-
-
- -
-
- Remove known
-
-
- -
-
- Detect and remove
-
-
-
-
-
diff --git a/src/platform/qt/Window.cpp b/src/platform/qt/Window.cpp
index 04d4163f4..0cd569ee8 100644
--- a/src/platform/qt/Window.cpp
+++ b/src/platform/qt/Window.cpp
@@ -89,8 +89,10 @@ Window::Window(ConfigController* config, int playerId, QWidget* parent)
}
connect(m_controller, SIGNAL(gameStarted(GBAThread*)), this, SLOT(gameStarted(GBAThread*)));
+ connect(m_controller, SIGNAL(gameStarted(GBAThread*)), &m_inputController, SLOT(suspendScreensaver()));
connect(m_controller, SIGNAL(gameStopped(GBAThread*)), m_display, SLOT(stopDrawing()));
connect(m_controller, SIGNAL(gameStopped(GBAThread*)), this, SLOT(gameStopped()));
+ connect(m_controller, SIGNAL(gameStopped(GBAThread*)), &m_inputController, SLOT(resumeScreensaver()));
connect(m_controller, SIGNAL(stateLoaded(GBAThread*)), m_display, SLOT(forceDraw()));
connect(m_controller, SIGNAL(rewound(GBAThread*)), m_display, SLOT(forceDraw()));
connect(m_controller, SIGNAL(gamePaused(GBAThread*)), m_display, SLOT(pauseDrawing()));
@@ -102,7 +104,9 @@ Window::Window(ConfigController* config, int playerId, QWidget* parent)
}
});
#endif
+ connect(m_controller, SIGNAL(gamePaused(GBAThread*)), &m_inputController, SLOT(resumeScreensaver()));
connect(m_controller, SIGNAL(gameUnpaused(GBAThread*)), m_display, SLOT(unpauseDrawing()));
+ connect(m_controller, SIGNAL(gameUnpaused(GBAThread*)), &m_inputController, SLOT(suspendScreensaver()));
connect(m_controller, SIGNAL(postLog(int, const QString&)), m_logView, SLOT(postLog(int, const QString&)));
connect(m_controller, SIGNAL(frameAvailable(const uint32_t*)), this, SLOT(recordFrame()));
connect(m_controller, SIGNAL(frameAvailable(const uint32_t*)), m_display, SLOT(framePosted(const uint32_t*)));
@@ -192,6 +196,8 @@ void Window::loadConfig() {
enterFullScreen();
}
+ m_inputController.setScreensaverSuspendable(opts->suspendScreensaver);
+
m_mruFiles = m_config->getMRU();
updateMRU();
diff --git a/src/platform/sdl/main.c b/src/platform/sdl/main.c
index ac060f2e0..d192a97ae 100644
--- a/src/platform/sdl/main.c
+++ b/src/platform/sdl/main.c
@@ -117,6 +117,11 @@ int main(int argc, char** argv) {
GBASDLPlayerLoadConfig(&renderer.player, GBAConfigGetInput(&config));
context.overrides = GBAConfigGetOverrides(&config);
+#if SDL_VERSION_ATLEAST(2, 0, 0)
+ GBASDLSetScreensaverSuspendable(&renderer.events, opts.suspendScreensaver);
+ GBASDLSuspendScreensaver(&renderer.events);
+#endif
+
int didFail = 0;
if (GBAThreadStart(&context)) {
renderer.runloop(&context, &renderer);
@@ -126,6 +131,11 @@ int main(int argc, char** argv) {
printf("Could not run game. Are you sure the file exists and is a Game Boy Advance game?\n");
}
+#if SDL_VERSION_ATLEAST(2, 0, 0)
+ GBASDLResumeScreensaver(&renderer.events);
+ GBASDLSetScreensaverSuspendable(&renderer.events, false);
+#endif
+
if (GBAThreadHasCrashed(&context)) {
didFail = 1;
printf("The game crashed!\n");
diff --git a/src/platform/sdl/sdl-events.c b/src/platform/sdl/sdl-events.c
index c14ec665c..99e2e0bc1 100644
--- a/src/platform/sdl/sdl-events.c
+++ b/src/platform/sdl/sdl-events.c
@@ -32,7 +32,7 @@ static void _GBASDLRotationSample(struct GBARotationSource* source);
bool GBASDLInitEvents(struct GBASDLEvents* context) {
int subsystem = SDL_INIT_JOYSTICK;
#if SDL_VERSION_ATLEAST(2, 0, 0)
- subsystem |= SDL_INIT_HAPTIC;
+ subsystem |= SDL_INIT_HAPTIC | SDL_INIT_VIDEO;
#endif
if (SDL_InitSubSystem(subsystem) < 0) {
return false;
@@ -68,6 +68,8 @@ bool GBASDLInitEvents(struct GBASDLEvents* context) {
#if !SDL_VERSION_ATLEAST(2, 0, 0)
SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
+#else
+ context->screensaverSuspendDepth = 0;
#endif
return true;
}
@@ -582,3 +584,33 @@ static void _GBASDLRotationSample(struct GBARotationSource* source) {
CircleBufferWrite32(&rotation->zHistory, theta.i);
rotation->zDelta += theta.f - oldZ;
}
+
+#if SDL_VERSION_ATLEAST(2, 0, 0)
+void GBASDLSuspendScreensaver(struct GBASDLEvents* events) {
+ if (events->screensaverSuspendDepth == 0 && events->screensaverSuspendable) {
+ SDL_DisableScreenSaver();
+ }
+ ++events->screensaverSuspendDepth;
+}
+
+void GBASDLResumeScreensaver(struct GBASDLEvents* events) {
+ --events->screensaverSuspendDepth;
+ if (events->screensaverSuspendDepth == 0 && events->screensaverSuspendable) {
+ SDL_EnableScreenSaver();
+ }
+}
+
+void GBASDLSetScreensaverSuspendable(struct GBASDLEvents* events, bool suspendable) {
+ bool wasSuspendable = events->screensaverSuspendable;
+ events->screensaverSuspendable = suspendable;
+ if (events->screensaverSuspendDepth > 0) {
+ if (suspendable && !wasSuspendable) {
+ SDL_DisableScreenSaver();
+ } else if (!suspendable && wasSuspendable) {
+ SDL_EnableScreenSaver();
+ }
+ } else {
+ SDL_EnableScreenSaver();
+ }
+}
+#endif
diff --git a/src/platform/sdl/sdl-events.h b/src/platform/sdl/sdl-events.h
index fbddda439..247c38f0f 100644
--- a/src/platform/sdl/sdl-events.h
+++ b/src/platform/sdl/sdl-events.h
@@ -29,6 +29,8 @@ struct GBASDLEvents {
size_t joysticksClaimed[MAX_PLAYERS];
#if SDL_VERSION_ATLEAST(2, 0, 0)
SDL_Haptic** haptic;
+ int screensaverSuspendDepth;
+ bool screensaverSuspendable;
#endif
};
@@ -82,4 +84,10 @@ void GBASDLPlayerSaveConfig(const struct GBASDLPlayer*, struct Configuration*);
void GBASDLHandleEvent(struct GBAThread* context, struct GBASDLPlayer* sdlContext, const union SDL_Event* event);
+#if SDL_VERSION_ATLEAST(2, 0, 0)
+void GBASDLSuspendScreensaver(struct GBASDLEvents*);
+void GBASDLResumeScreensaver(struct GBASDLEvents*);
+void GBASDLSetScreensaverSuspendable(struct GBASDLEvents*, bool suspendable);
+#endif
+
#endif