From e2cf6ecba63ef994e565f8d991f938436bdeb5b9 Mon Sep 17 00:00:00 2001 From: Rafael Kitover Date: Mon, 1 Jul 2024 20:09:35 +0000 Subject: [PATCH] Add option to mute sound during speedup Add core option to mute sound during speedup, implemented in the gba core. Link the option to the SDL port as well. Add the new Mute Sound option as a checkbox to the xrc for the Speedup/Turbo dialog and improve the dialog appearance. Fix the max values for the options speedup_throttle and speedup_frame_skip. Add base class for numeric OptionProxy types implementing the +=, -= operators, increment/decrement operators and operator T(). Add tests for these operators on numeric types. Move Speedup/Turbo dialog code from guiinit.cpp to a dialog class and rewrite it using validators. Remove the "GL VIEWPORT" debug prints from panel.cpp. Fix #865 Signed-off-by: Rafael Kitover --- src/core/base/system.h | 3 +- src/core/gba/gba.cpp | 21 ++- src/sdl/ConfigManager.cpp | 8 +- src/wx/CMakeLists.txt | 2 + src/wx/config/internal/option-internal.cpp | 7 +- src/wx/config/option-id.h | 1 + src/wx/config/option-proxy.h | 63 +++++---- src/wx/config/option-test.cpp | 106 ++++++++++++++ src/wx/dialogs/speedup-config.cpp | 154 +++++++++++++++++++++ src/wx/dialogs/speedup-config.h | 54 ++++++++ src/wx/guiinit.cpp | 120 +--------------- src/wx/panel.cpp | 7 - src/wx/xrc/SpeedupConfig.xrc | 47 +++++-- 13 files changed, 423 insertions(+), 170 deletions(-) create mode 100644 src/wx/dialogs/speedup-config.cpp create mode 100644 src/wx/dialogs/speedup-config.h diff --git a/src/core/base/system.h b/src/core/base/system.h index af0e7a26..c5a3440e 100644 --- a/src/core/base/system.h +++ b/src/core/base/system.h @@ -59,6 +59,7 @@ extern struct CoreOptions { bool speedHack = false; bool speedup = false; bool speedup_throttle_frame_skip = false; + bool speedup_mute = true; int cheatsEnabled = 1; int cpuDisableSfx = 0; int cpuSaveType = 0; @@ -125,4 +126,4 @@ extern int systemSpeed; #define SYSTEM_SAVE_UPDATED 30 #define SYSTEM_SAVE_NOT_UPDATED 0 -#endif // VBAM_CORE_BASE_SYSTEM_H_ \ No newline at end of file +#endif // VBAM_CORE_BASE_SYSTEM_H_ diff --git a/src/core/gba/gba.cpp b/src/core/gba/gba.cpp index c09e9b6b..c3f0f36a 100644 --- a/src/core/gba/gba.cpp +++ b/src/core/gba/gba.cpp @@ -3845,6 +3845,8 @@ void CPULoop(int ticks) bool turbo_button_pressed = (joy >> 10) & 1; #ifndef __LIBRETRO__ static uint32_t last_throttle; + static bool current_volume_saved = false; + static float current_volume; if (turbo_button_pressed) { if (coreOptions.speedup_frame_skip) @@ -3859,10 +3861,23 @@ void CPULoop(int ticks) if (coreOptions.speedup_throttle_frame_skip) framesToSkip += static_cast(std::ceil(double(coreOptions.speedup_throttle) / 100.0) - 1); } + + if (coreOptions.speedup_mute && !current_volume_saved) { + current_volume = soundGetVolume(); + current_volume_saved = true; + soundSetVolume(0); + } } - else if (speedup_throttle_set) { - soundSetThrottle(DowncastU16(last_throttle)); - speedup_throttle_set = false; + else { + if (current_volume_saved) { + soundSetVolume(current_volume); + current_volume_saved = false; + } + + if (speedup_throttle_set) { + soundSetThrottle(DowncastU16(last_throttle)); + speedup_throttle_set = false; + } } #else if (turbo_button_pressed) diff --git a/src/sdl/ConfigManager.cpp b/src/sdl/ConfigManager.cpp index a0944a94..74841161 100644 --- a/src/sdl/ConfigManager.cpp +++ b/src/sdl/ConfigManager.cpp @@ -98,7 +98,8 @@ enum named_opts OPT_SOUND_FILTERING, OPT_SPEEDUP_THROTTLE, OPT_SPEEDUP_FRAME_SKIP, - OPT_NO_SPEEDUP_THROTTLE_FRAME_SKIP + OPT_NO_SPEEDUP_THROTTLE_FRAME_SKIP, + OPT_NO_SPEEDUP_MUTE }; #define SOUND_MAX_VOLUME 2.0 @@ -232,6 +233,7 @@ struct option argOptions[] = { { "speedup-throttle", required_argument, 0, OPT_SPEEDUP_THROTTLE }, { "speedup-frame-skip", required_argument, 0, OPT_SPEEDUP_FRAME_SKIP }, { "no-speedup-throttle-frame-skip", no_argument, 0, OPT_NO_SPEEDUP_THROTTLE_FRAME_SKIP }, + { "no-speedup-mute", no_argument, 0, OPT_NO_SPEEDUP_MUTE }, { "use-bios", no_argument, &coreOptions.useBios, 1 }, { "verbose", required_argument, 0, 'v' }, { "win-gb-printer-enabled", no_argument, &coreOptions.winGbPrinterEnabled, 1 }, @@ -347,6 +349,7 @@ void LoadConfig() coreOptions.speedup_throttle = ReadPref("speedupThrottle", 100); coreOptions.speedup_frame_skip = ReadPref("speedupFrameSkip", 9); coreOptions.speedup_throttle_frame_skip = ReadPref("speedupThrottleFrameSkip", 0); + coreOptions.speedup_mute = ReadPref("speedupMute", 1); coreOptions.useBios = ReadPrefHex("useBiosGBA"); coreOptions.winGbPrinterEnabled = ReadPref("gbPrinter", 0); @@ -990,6 +993,9 @@ int ReadOpts(int argc, char ** argv) case OPT_NO_SPEEDUP_THROTTLE_FRAME_SKIP: coreOptions.speedup_throttle_frame_skip = false; break; + case OPT_NO_SPEEDUP_MUTE: + coreOptions.speedup_mute = false; + break; } } return op; diff --git a/src/wx/CMakeLists.txt b/src/wx/CMakeLists.txt index f6f0cd5e..518508a9 100644 --- a/src/wx/CMakeLists.txt +++ b/src/wx/CMakeLists.txt @@ -31,6 +31,8 @@ set(VBAM_WX_COMMON dialogs/joypad-config.h dialogs/sound-config.cpp dialogs/sound-config.h + dialogs/speedup-config.cpp + dialogs/speedup-config.h drawing.h extra-translations.cpp gfxviewers.cpp diff --git a/src/wx/config/internal/option-internal.cpp b/src/wx/config/internal/option-internal.cpp index 3609541a..f5fd9b88 100644 --- a/src/wx/config/internal/option-internal.cpp +++ b/src/wx/config/internal/option-internal.cpp @@ -328,9 +328,10 @@ std::array& Option::All() { Option(OptionID::kPrefSkipSaveGameCheats, &coreOptions.skipSaveGameCheats, 0, 1), Option(OptionID::kPrefSkipSaveGameBattery, &coreOptions.skipSaveGameBattery, 0, 1), Option(OptionID::kPrefThrottle, &coreOptions.throttle, 0, 450), - Option(OptionID::kPrefSpeedupThrottle, &coreOptions.speedup_throttle, 0, 3000), - Option(OptionID::kPrefSpeedupFrameSkip, &coreOptions.speedup_frame_skip, 0, 300), + Option(OptionID::kPrefSpeedupThrottle, &coreOptions.speedup_throttle, 0, 450), + Option(OptionID::kPrefSpeedupFrameSkip, &coreOptions.speedup_frame_skip, 0, 40), Option(OptionID::kPrefSpeedupThrottleFrameSkip, &coreOptions.speedup_throttle_frame_skip), + Option(OptionID::kPrefSpeedupMute, &coreOptions.speedup_mute), Option(OptionID::kPrefUseBiosGB, &g_owned_opts.use_bios_file_gb), Option(OptionID::kPrefUseBiosGBA, &g_owned_opts.use_bios_file_gba), Option(OptionID::kPrefUseBiosGBC, &g_owned_opts.use_bios_file_gbc), @@ -531,6 +532,8 @@ const std::array kAllOptionsData = { "throttle)")}, OptionData{"preferences/speedupThrottleFrameSkip", "", _("Use frame skip for speedup throttle")}, + OptionData{"preferences/speedupMute", "", + _("Mute sound during speedup")}, OptionData{"preferences/useBiosGB", "BootRomGB", _("Use the specified BIOS file for Game Boy")}, OptionData{"preferences/useBiosGBA", "BootRomEn", _("Use the specified BIOS file")}, OptionData{"preferences/useBiosGBC", "BootRomGBC", diff --git a/src/wx/config/option-id.h b/src/wx/config/option-id.h index 6b4a922b..630a8171 100644 --- a/src/wx/config/option-id.h +++ b/src/wx/config/option-id.h @@ -99,6 +99,7 @@ enum class OptionID { kPrefSpeedupThrottle, kPrefSpeedupFrameSkip, kPrefSpeedupThrottleFrameSkip, + kPrefSpeedupMute, kPrefUseBiosGB, kPrefUseBiosGBA, kPrefUseBiosGBC, diff --git a/src/wx/config/option-proxy.h b/src/wx/config/option-proxy.h index 5eb9731e..1940480c 100644 --- a/src/wx/config/option-proxy.h +++ b/src/wx/config/option-proxy.h @@ -103,6 +103,7 @@ static constexpr std::array kOptionsTypes = { /*kPrefSpeedupThrottle*/ Option::Type::kUnsigned, /*kPrefSpeedupFrameSkip*/ Option::Type::kUnsigned, /*kPrefSpeedupThrottleFrameSkip*/ Option::Type::kBool, + /*kPrefSpeedupMute*/ Option::Type::kBool, /*kPrefUseBiosGB*/ Option::Type::kBool, /*kPrefUseBiosGBA*/ Option::Type::kBool, /*kPrefUseBiosGBC*/ Option::Type::kBool, @@ -174,11 +175,43 @@ private: Option* option_; }; +template +class OptionProxyNumeric { +public: + virtual T Get() const = 0; + virtual bool Set(T value) = 0; + virtual T Min() const = 0; + virtual T Max() const = 0; + + bool operator++() { return *this += 1; } + bool operator--() { return *this -= 1; } + bool operator++(int) { return *this += 1; } + bool operator--(int) { return *this -= 1; } + bool operator+=(T value) { + const int new_value = Get() + value; + if (new_value > Max()) { + return Set(Max()); + } else { + return Set(new_value); + } + } + bool operator-=(T value) { + const int new_value = Get() - value; + if (new_value < Min()) { + return Set(Min()); + } else { + return Set(new_value); + } + } + + operator T() const { return Get(); } +}; + template class OptionProxy< ID, typename std::enable_if(ID)] == - Option::Type::kDouble>::type> { + Option::Type::kDouble>::type> : public OptionProxyNumeric { public: OptionProxy() : option_(Option::ByID(ID)) {} ~OptionProxy() = default; @@ -187,9 +220,7 @@ public: bool Set(double value) { return option_->SetDouble(value); } double Min() const { return option_->GetDoubleMin(); } double Max() const { return option_->GetDoubleMax(); } - bool operator=(double value) { return Set(value); } - operator double() const { return Get(); } private: Option* option_; @@ -199,7 +230,7 @@ template class OptionProxy< ID, typename std::enable_if(ID)] == - Option::Type::kInt>::type> { + Option::Type::kInt>::type> : public OptionProxyNumeric { public: OptionProxy() : option_(Option::ByID(ID)) {} ~OptionProxy() = default; @@ -208,25 +239,7 @@ public: bool Set(int32_t value) { return option_->SetInt(value); } int32_t Min() const { return option_->GetIntMin(); } int32_t Max() const { return option_->GetIntMax(); } - bool operator=(int32_t value) { return Set(value); } - bool operator+=(int32_t value) { - const int new_value = Get() + value; - if (new_value > Max()) { - return Set(Max()); - } else { - return Set(new_value); - } - } - bool operator-=(int32_t value) { - const int new_value = Get() - value; - if (new_value < Min()) { - return Set(Min()); - } else { - return Set(new_value); - } - } - operator int32_t() const { return Get(); } private: Option* option_; @@ -236,7 +249,7 @@ template class OptionProxy< ID, typename std::enable_if(ID)] == - Option::Type::kUnsigned>::type> { + Option::Type::kUnsigned>::type> : public OptionProxyNumeric { public: OptionProxy() : option_(Option::ByID(ID)) {} ~OptionProxy() = default; @@ -245,9 +258,7 @@ public: bool Set(uint32_t value) { return option_->SetUnsigned(value); } uint32_t Min() const { return option_->GetUnsignedMin(); } uint32_t Max() const { return option_->GetUnsignedMax(); } - - bool operator=(int32_t value) { return Set(value); } - operator int32_t() const { return Get(); } + bool operator=(uint32_t value) { return Set(value); } private: Option* option_; diff --git a/src/wx/config/option-test.cpp b/src/wx/config/option-test.cpp index 0b9b0a2c..706397d5 100644 --- a/src/wx/config/option-test.cpp +++ b/src/wx/config/option-test.cpp @@ -353,3 +353,109 @@ TEST(OptionProxyTest, MatchingTypes) { EXPECT_EQ(option->type(), proxy_type); } } + +TEST(OptionProxyTest, NumericOperators) { + wxLogNull disable_logging; + + int32_t int_opt = OPTION(kDispMaxThreads); + + int_opt++; + OPTION(kDispMaxThreads)++; + EXPECT_EQ(int_opt, OPTION(kDispMaxThreads)); + + int_opt--; + OPTION(kDispMaxThreads)--; + EXPECT_EQ(int_opt, OPTION(kDispMaxThreads)); + + ++int_opt; + OPTION(kDispMaxThreads)++; + EXPECT_EQ(int_opt, OPTION(kDispMaxThreads)); + + --int_opt; + OPTION(kDispMaxThreads)--; + EXPECT_EQ(int_opt, OPTION(kDispMaxThreads)); + + int_opt += 2; + OPTION(kDispMaxThreads) += 2; + EXPECT_EQ(int_opt, OPTION(kDispMaxThreads)); + + int_opt -= 2; + OPTION(kDispMaxThreads) -= 2; + EXPECT_EQ(int_opt, OPTION(kDispMaxThreads)); + + OPTION(kDispMaxThreads) = OPTION(kDispMaxThreads).Max(); + OPTION(kDispMaxThreads)++; + EXPECT_EQ(OPTION(kDispMaxThreads), OPTION(kDispMaxThreads).Max()); + + OPTION(kDispMaxThreads) = OPTION(kDispMaxThreads).Min(); + OPTION(kDispMaxThreads)--; + EXPECT_EQ(OPTION(kDispMaxThreads), OPTION(kDispMaxThreads).Min()); + + uint32_t unsigned_opt = OPTION(kJoyDefault); + + unsigned_opt++; + OPTION(kJoyDefault)++; + EXPECT_EQ(unsigned_opt, OPTION(kJoyDefault)); + + unsigned_opt--; + OPTION(kJoyDefault)--; + EXPECT_EQ(unsigned_opt, OPTION(kJoyDefault)); + + ++unsigned_opt; + OPTION(kJoyDefault)++; + EXPECT_EQ(unsigned_opt, OPTION(kJoyDefault)); + + --unsigned_opt; + OPTION(kJoyDefault)--; + EXPECT_EQ(unsigned_opt, OPTION(kJoyDefault)); + + unsigned_opt += 2; + OPTION(kJoyDefault) += 2; + EXPECT_EQ(unsigned_opt, OPTION(kJoyDefault)); + + unsigned_opt -= 2; + OPTION(kJoyDefault) -= 2; + EXPECT_EQ(unsigned_opt, OPTION(kJoyDefault)); + + OPTION(kJoyDefault) = OPTION(kJoyDefault).Max(); + OPTION(kJoyDefault)++; + EXPECT_EQ(OPTION(kJoyDefault), OPTION(kJoyDefault).Max()); + + OPTION(kJoyDefault) = OPTION(kJoyDefault).Min(); + OPTION(kJoyDefault)--; + EXPECT_EQ(OPTION(kJoyDefault), OPTION(kJoyDefault).Min()); + + double double_opt = OPTION(kDispScale); + + double_opt++; + OPTION(kDispScale)++; + EXPECT_EQ(double_opt, OPTION(kDispScale)); + + double_opt--; + OPTION(kDispScale)--; + EXPECT_EQ(double_opt, OPTION(kDispScale)); + + ++double_opt; + OPTION(kDispScale)++; + EXPECT_EQ(double_opt, OPTION(kDispScale)); + + --double_opt; + OPTION(kDispScale)--; + EXPECT_EQ(double_opt, OPTION(kDispScale)); + + double_opt += 2; + OPTION(kDispScale) += 2; + EXPECT_EQ(double_opt, OPTION(kDispScale)); + + double_opt -= 2; + OPTION(kDispScale) -= 2; + EXPECT_EQ(double_opt, OPTION(kDispScale)); + + OPTION(kDispScale) = OPTION(kDispScale).Max(); + OPTION(kDispScale)++; + EXPECT_EQ(OPTION(kDispScale), OPTION(kDispScale).Max()); + + OPTION(kDispScale) = OPTION(kDispScale).Min(); + OPTION(kDispScale)--; + EXPECT_EQ(OPTION(kDispScale), OPTION(kDispScale).Min()); +} diff --git a/src/wx/dialogs/speedup-config.cpp b/src/wx/dialogs/speedup-config.cpp new file mode 100644 index 00000000..92d5c3de --- /dev/null +++ b/src/wx/dialogs/speedup-config.cpp @@ -0,0 +1,154 @@ +#include "wx/dialogs/speedup-config.h" + +#include +#include +#include + +#include "core/base/check.h" +#include "wx/config/option-proxy.h" +#include "wx/dialogs/base-dialog.h" +#include "wx/widgets/option-validator.h" + +// This dialog has a spin control representing the speedup value as it feels +// like to the user. Values below 450 can be an actual throttle or a number of +// frames to skip depending on whether the Frame Skip checkbox is checked. The +// number of frames is the spin control value divided by 100, for example 300 +// with the Frame Skip checkbox checked means 3 frames to skip. Values above 450 +// are always the number of frames to skip, for example 900 means 9 frames to skip. +// +// The config option SpeedupThrottle is the throttle value, if frame skip is +// used it is 0. The config option SpeedupFrameSkip is the number of frames to +// skip, if throttle is used it is 0. The config option SpeedupThrottleFrameSkip +// represents the Frame Skip checkbox for values under 450, that is if they are +// interpreted as a frame skip or a throttle. + +namespace dialogs { + +bool SpeedupConfigValidator::TransferToWindow() { + uint32_t opt_frame_skip = OPTION(kPrefSpeedupFrameSkip); + uint32_t opt_throttle = OPTION(kPrefSpeedupThrottle); + bool opt_throttle_frame_skip = OPTION(kPrefSpeedupThrottleFrameSkip); + + auto dialog = static_cast(GetWindow()); + + dialog->prev_frame_skip_cb_ = opt_throttle_frame_skip; + + if (opt_frame_skip != 0) { + dialog->speedup_throttle_spin_->SetValue(opt_frame_skip * 100); + dialog->prev_throttle_spin_ = opt_frame_skip * 100; + + dialog->frame_skip_cb_->SetValue(true); + dialog->frame_skip_cb_->Disable(); + } else { + dialog->speedup_throttle_spin_->SetValue(opt_throttle); + dialog->prev_throttle_spin_ = opt_throttle; + + dialog->frame_skip_cb_->SetValue(opt_throttle_frame_skip); + + if (opt_throttle != 0) + dialog->frame_skip_cb_->Enable(); + else + dialog->frame_skip_cb_->Disable(); + } + + return true; +} + +bool SpeedupConfigValidator::TransferFromWindow() { + auto dialog = static_cast(GetWindow()); + + uint32_t val = dialog->speedup_throttle_spin_->GetValue(); + + VBAM_CHECK(val >= 0); + + if (val == 0) { + OPTION(kPrefSpeedupThrottle) = 0; + OPTION(kPrefSpeedupFrameSkip) = 0; + OPTION(kPrefSpeedupThrottleFrameSkip) = false; + } else if (val <= OPTION(kPrefSpeedupThrottle).Max()) { + OPTION(kPrefSpeedupThrottle) = val; + OPTION(kPrefSpeedupFrameSkip) = 0; + OPTION(kPrefSpeedupThrottleFrameSkip) = dialog->frame_skip_cb_->GetValue(); + } else { // val > throttle_max + OPTION(kPrefSpeedupThrottle) = 100; + OPTION(kPrefSpeedupFrameSkip) = val / 100; + OPTION(kPrefSpeedupThrottleFrameSkip) = false; + } + + return true; +} + +// static +SpeedupConfig* SpeedupConfig::NewInstance(wxWindow* parent) { + VBAM_CHECK(parent); + return new SpeedupConfig(parent); +} + +SpeedupConfig::SpeedupConfig(wxWindow* parent) + : BaseDialog(parent, "SpeedupConfig") { + + speedup_throttle_spin_ = GetValidatedChild("SpeedupThrottleSpin"); + frame_skip_cb_ = GetValidatedChild("SpeedupThrottleFrameSkip"); + + speedup_throttle_spin_->SetRange(OPTION(kPrefSpeedupThrottle).Min(), OPTION(kPrefSpeedupFrameSkip).Max() * 100); + + speedup_throttle_spin_->SetWindowStyle(wxSP_ARROW_KEYS); + +#ifdef wxTE_PROCESS_ENTER + speedup_throttle_spin_->SetWindowStyleFlag(wxTE_PROCESS_ENTER); +#endif + + GetValidatedChild("SpeedupMute")->SetValidator(widgets::OptionBoolValidator(config::OptionID::kPrefSpeedupMute)); + + using namespace std::placeholders; + + Bind(wxEVT_SPIN_UP, std::bind(&SpeedupConfig::SetSpeedupThrottle, this, _1), XRCID("SpeedupThrottleSpin")); + Bind(wxEVT_SPIN_DOWN, std::bind(&SpeedupConfig::SetSpeedupThrottle, this, _1), XRCID("SpeedupThrottleSpin")); + Bind(wxEVT_SPIN, std::bind(&SpeedupConfig::SetSpeedupThrottle, this, _1), XRCID("SpeedupThrottleSpin")); + Bind(wxEVT_TEXT, std::bind(&SpeedupConfig::SetSpeedupThrottle, this, _1), XRCID("SpeedupThrottleSpin")); + Bind(wxEVT_CHECKBOX, std::bind(&SpeedupConfig::ToggleSpeedupFrameSkip, this), XRCID("SpeedupThrottleFrameSkip")); + + SetValidator(SpeedupConfigValidator()); + + Fit(); +} + +void SpeedupConfig::SetSpeedupThrottle(wxCommandEvent& evt) +{ + VBAM_CHECK(evt.GetEventObject() == speedup_throttle_spin_); + + uint32_t val = speedup_throttle_spin_->GetValue(); + + VBAM_CHECK(val >= 0); + + if (val == 0) { + frame_skip_cb_->SetValue(false); + frame_skip_cb_->Disable(); + } else if (val <= OPTION(kPrefSpeedupThrottle).Max()) { + frame_skip_cb_->SetValue(prev_frame_skip_cb_); + frame_skip_cb_->Enable(); + } else { // val > throttle_max + if (val > prev_throttle_spin_) + val += 100; + + val = std::floor((double)val / 100) * 100; + + uint32_t max = speedup_throttle_spin_->GetMax(); + + if (val > max) + val = max; + + frame_skip_cb_->SetValue(true); + frame_skip_cb_->Disable(); + } + + speedup_throttle_spin_->SetValue(val); + prev_throttle_spin_ = val; +} + +void SpeedupConfig::ToggleSpeedupFrameSkip() +{ + prev_frame_skip_cb_ = frame_skip_cb_->GetValue(); +} + +} // namespace dialogs diff --git a/src/wx/dialogs/speedup-config.h b/src/wx/dialogs/speedup-config.h new file mode 100644 index 00000000..156ece7b --- /dev/null +++ b/src/wx/dialogs/speedup-config.h @@ -0,0 +1,54 @@ +#ifndef VBAM_WX_DIALOGS_SPEEDUP_CONFIG_H_ +#define VBAM_WX_DIALOGS_SPEEDUP_CONFIG_H_ + +// Manages the Speedup/Turbo configuration dialog. +// +// See the explanation for the implementation in the .cpp file. + +#include +#include "wx/dialogs/base-dialog.h" +#include +#include + +namespace dialogs { + +class SpeedupConfigValidator : public wxValidator { +public: + SpeedupConfigValidator() = default; + ~SpeedupConfigValidator() override = default; + + bool TransferToWindow() override; + bool TransferFromWindow() override; + + bool Validate([[maybe_unused]]wxWindow* parent) override { return true; } + +private: + wxObject* Clone() const override { return new SpeedupConfigValidator(); } +}; + +class SpeedupConfig : public BaseDialog { +public: + static SpeedupConfig* NewInstance(wxWindow* parent); + ~SpeedupConfig() override = default; + + void ToggleSpeedupFrameSkip(); + void ToggleSpeedupMute(); + void SetSpeedupThrottle(wxCommandEvent& evt); + +private: + // The constructor is private so initialization has to be done via the + // static method. This is because this class is destroyed when its + // owner, `parent` is destroyed. This prevents accidental deletion. + SpeedupConfig(wxWindow* parent); + + wxSpinCtrl* speedup_throttle_spin_; + wxCheckBox* frame_skip_cb_; + bool prev_frame_skip_cb_; + unsigned prev_throttle_spin_; + + friend class SpeedupConfigValidator; +}; + +} // namespace dialogs + +#endif // VBAM_WX_DIALOGS_SPEEDUP_CONFIG_H_ diff --git a/src/wx/guiinit.cpp b/src/wx/guiinit.cpp index 2b699d4b..e3cee561 100644 --- a/src/wx/guiinit.cpp +++ b/src/wx/guiinit.cpp @@ -48,6 +48,7 @@ #include "wx/dialogs/gb-rom-info.h" #include "wx/dialogs/joypad-config.h" #include "wx/dialogs/sound-config.h" +#include "wx/dialogs/speedup-config.h" #include "wx/opts.h" #include "wx/widgets/checkedlistctrl.h" #include "wx/widgets/option-validator.h" @@ -1483,92 +1484,6 @@ public: } } throttle_ctrl; -static class SpeedupThrottleCtrl_t : public wxEvtHandler { -public: - wxSpinCtrl* speedup_throttle_spin; - wxCheckBox* frame_skip_cb; - - void SetSpeedupThrottle(wxCommandEvent& evt) - { - unsigned val = speedup_throttle_spin->GetValue(); - - evt.Skip(false); - - if (val == 0) { - coreOptions.speedup_throttle = 0; - coreOptions.speedup_frame_skip = 0; - coreOptions.speedup_throttle_frame_skip = false; - - frame_skip_cb->SetValue(false); - frame_skip_cb->Disable(); - - if (evt.GetEventType() == wxEVT_TEXT) - return; // Do not update value if user cleared text box. - } - else if (val <= 450) { - coreOptions.speedup_throttle = val; - coreOptions.speedup_frame_skip = 0; - - frame_skip_cb->SetValue(prev_frame_skip_cb); - frame_skip_cb->Enable(); - } - else { // val > 450 - coreOptions.speedup_throttle = 100; - coreOptions.speedup_throttle_frame_skip = false; - - unsigned rounded = std::round((double)val / 100) * 100; - - coreOptions.speedup_frame_skip = rounded / 100 - 1; - - // Round up or down to the nearest 100%. - // For example, when the up/down buttons are pressed on the spin - // control. - if ((int)(val - rounded) > 0) - coreOptions.speedup_frame_skip++; - else if ((int)(val - rounded) < 0) - coreOptions.speedup_frame_skip--; - - frame_skip_cb->SetValue(true); - frame_skip_cb->Disable(); - - val = (coreOptions.speedup_frame_skip + 1) * 100; - } - - speedup_throttle_spin->SetValue(val); - } - - void SetSpeedupFrameSkip(wxCommandEvent& evt) - { - (void)evt; // Unused param. - - bool checked = frame_skip_cb->GetValue(); - - coreOptions.speedup_throttle_frame_skip = prev_frame_skip_cb = checked; - } - - void Init(wxShowEvent& ev) - { - if (coreOptions.speedup_frame_skip != 0) { - speedup_throttle_spin->SetValue((coreOptions.speedup_frame_skip + 1) * 100); - frame_skip_cb->SetValue(true); - frame_skip_cb->Disable(); - } - else { - speedup_throttle_spin->SetValue(coreOptions.speedup_throttle); - frame_skip_cb->SetValue(coreOptions.speedup_throttle_frame_skip); - - if (coreOptions.speedup_throttle != 0) - frame_skip_cb->Enable(); - else - frame_skip_cb->Disable(); - } - - ev.Skip(); - } -private: - bool prev_frame_skip_cb = coreOptions.speedup_throttle_frame_skip; -} speedup_throttle_ctrl; - ///////////////////////////// //Check if a pointer from the XRC file is valid. If it's not, throw an error telling the user. template @@ -2376,38 +2291,6 @@ bool MainFrame::BindControls() d->Fit(); } - // SpeedUp Key Config - d = LoadXRCDialog("SpeedupConfig"); - { - speedup_throttle_ctrl.frame_skip_cb = SafeXRCCTRL(d, "SpeedupThrottleFrameSkip"); - speedup_throttle_ctrl.speedup_throttle_spin = SafeXRCCTRL(d, "SpeedupThrottleSpin"); - - speedup_throttle_ctrl.speedup_throttle_spin->Connect(wxEVT_SPIN_UP, - wxCommandEventHandler(SpeedupThrottleCtrl_t::SetSpeedupThrottle), - NULL, &speedup_throttle_ctrl); - - speedup_throttle_ctrl.speedup_throttle_spin->Connect(wxEVT_SPIN_DOWN, - wxCommandEventHandler(SpeedupThrottleCtrl_t::SetSpeedupThrottle), - NULL, &speedup_throttle_ctrl); - - speedup_throttle_ctrl.speedup_throttle_spin->Connect(wxEVT_SPIN, - wxCommandEventHandler(SpeedupThrottleCtrl_t::SetSpeedupThrottle), - NULL, &speedup_throttle_ctrl); - - speedup_throttle_ctrl.speedup_throttle_spin->Connect(wxEVT_TEXT, - wxCommandEventHandler(SpeedupThrottleCtrl_t::SetSpeedupThrottle), - NULL, &speedup_throttle_ctrl); - - speedup_throttle_ctrl.frame_skip_cb->Connect(wxEVT_CHECKBOX, - wxCommandEventHandler(SpeedupThrottleCtrl_t::SetSpeedupFrameSkip), - NULL, &speedup_throttle_ctrl); - - d->Connect(wxEVT_SHOW, wxShowEventHandler(SpeedupThrottleCtrl_t::Init), - NULL, &speedup_throttle_ctrl); - - d->Fit(); - } - wxMenuItem* suspend_scr_saver_mi = XRCITEM("SuspendScreenSaver"); if (suspend_scr_saver_mi) { @@ -2470,6 +2353,7 @@ bool MainFrame::BindControls() dialogs::SoundConfig::NewInstance(this); dialogs::DirectoriesConfig::NewInstance(this); dialogs::JoypadConfig::NewInstance(this, std::bind(&wxvbamApp::bindings, &wxGetApp())); + dialogs::SpeedupConfig::NewInstance(this); #ifndef NO_LINK d = LoadXRCDialog("LinkConfig"); diff --git a/src/wx/panel.cpp b/src/wx/panel.cpp index 91cbff3f..bb9e7874 100644 --- a/src/wx/panel.cpp +++ b/src/wx/panel.cpp @@ -2368,13 +2368,6 @@ void GLDrawingPanel::AdjustViewport() int x, y; widgets::GetRealPixelClientSize(this, &x, &y); glViewport(0, 0, x, y); - -#ifdef DEBUG - // you can use this to check that the gl surface is indeed high res - GLint m_viewport[4]; - glGetIntegerv(GL_VIEWPORT, m_viewport); - wxLogDebug(wxT("GL VIEWPORT: %d, %d, %d, %d"), m_viewport[0], m_viewport[1], m_viewport[2], m_viewport[3]); -#endif } void GLDrawingPanel::RefreshGL() diff --git a/src/wx/xrc/SpeedupConfig.xrc b/src/wx/xrc/SpeedupConfig.xrc index 48ccec60..c2a97730 100644 --- a/src/wx/xrc/SpeedupConfig.xrc +++ b/src/wx/xrc/SpeedupConfig.xrc @@ -11,7 +11,7 @@ bold - wxALL + wxALL|wxALIGN_CENTRE_HORIZONTAL 5 @@ -32,9 +32,7 @@ - 0 - 0 - 4000 + 40,-1d wxALL|wxALIGN_CENTRE_VERTICAL 5 @@ -46,23 +44,48 @@ 5 - - + + 1 + 2 + 0 + 0,1 + + + + + wxALL + 5 + + + + + + wxALL + 5 + - wxALL + wxALL|wxEXPAND 5 - wxALL|wxEXPAND - 5 - - + + 1 + 2 + 0 + 0,1 + + wxALL + 10 - + + wxALL|wxALIGN_RIGHT + 10 + wxALL|wxEXPAND + 10