[Option] Add Proxy template class for Option

This removes the global accessors for individual options in favor of a
proxy template class with a simpler per-type API. This adds compile-time
checks to validate that the right option is used with the right type
when accessing it directly.
This commit is contained in:
Fabrice de Gans 2022-10-29 15:01:39 -07:00 committed by Rafael Kitover
parent f84a164072
commit 2b950e282f
12 changed files with 775 additions and 582 deletions

File diff suppressed because it is too large Load Diff

View File

@ -806,6 +806,7 @@ set(
config/internal/option-internal.h
config/option-id.h
config/option-observer.h
config/option-proxy.h
config/option.h
config/user-input.h
dialogs/display-config.h

View File

@ -14,6 +14,7 @@
#include "../common/version_cpp.h"
#include "../gb/gbPrinter.h"
#include "../gba/agbprint.h"
#include "config/option-proxy.h"
#include "config/option.h"
#if (wxMAJOR_VERSION < 3)
@ -2558,32 +2559,32 @@ EVT_HANDLER(GameBoyConfigure, "Game Boy options...")
EVT_HANDLER(SetSize1x, "1x")
{
config::OptDispScale()->SetDouble(1);
config::Proxy<config::OptionID::kDispScale>().Set(1);
}
EVT_HANDLER(SetSize2x, "2x")
{
config::OptDispScale()->SetDouble(2);
config::Proxy<config::OptionID::kDispScale>().Set(2);
}
EVT_HANDLER(SetSize3x, "3x")
{
config::OptDispScale()->SetDouble(3);
config::Proxy<config::OptionID::kDispScale>().Set(3);
}
EVT_HANDLER(SetSize4x, "4x")
{
config::OptDispScale()->SetDouble(4);
config::Proxy<config::OptionID::kDispScale>().Set(4);
}
EVT_HANDLER(SetSize5x, "5x")
{
config::OptDispScale()->SetDouble(5);
config::Proxy<config::OptionID::kDispScale>().Set(5);
}
EVT_HANDLER(SetSize6x, "6x")
{
config::OptDispScale()->SetDouble(6);
config::Proxy<config::OptionID::kDispScale>().Set(6);
}
EVT_HANDLER(GameBoyAdvanceConfigure, "Game Boy Advance options...")
@ -2763,12 +2764,12 @@ EVT_HANDLER_MASK(DisplayConfigure, "Display options...", CMDEN_NREC_ANY)
EVT_HANDLER_MASK(ChangeFilter, "Change Pixel Filter", CMDEN_NREC_ANY)
{
config::OptDispFilter()->NextFilter();
config::Proxy<config::OptionID::kDispFilter>().Next();
}
EVT_HANDLER_MASK(ChangeIFB, "Change Interframe Blending", CMDEN_NREC_ANY)
{
config::OptDispIFB()->NextInterframe();
config::Proxy<config::OptionID::kDispIFB>().Next();
}
EVT_HANDLER_MASK(SoundConfigure, "Sound options...", CMDEN_NREC_ANY)

View File

@ -167,6 +167,7 @@ std::array<Option, kNbOptions>& Option::All() {
// error since kNbOptions is automatically updated.
// This will be initialized on the first call, in load_opts(), ensuring the
// translation initialization has already happened.
// clang-format off
static std::array<Option, kNbOptions> g_all_opts = {
/// Display
Option(OptionID::kDispBilinear, &gopts.bilinear),
@ -213,22 +214,20 @@ std::array<Option, kNbOptions>& Option::All() {
Option(OptionID::kGenBatteryDir, &gopts.battery_dir),
Option(OptionID::kGenFreezeRecent, &gopts.recent_freeze),
Option(OptionID::kGenRecordingDir, &gopts.recording_dir),
Option(OptionID::kGenRewindInterval, &gopts.rewind_interval, 0,
600),
Option(OptionID::kGenRewindInterval, &gopts.rewind_interval, 0, 600),
Option(OptionID::kGenScreenshotDir, &gopts.scrshot_dir),
Option(OptionID::kGenStateDir, &gopts.state_dir),
Option(OptionID::kGenStatusBar, &gopts.statusbar),
/// Joypad
Option(OptionID::kJoy),
Option(OptionID::kJoyAutofireThrottle, &gopts.autofire_rate, 1,
1000),
Option(OptionID::kJoyAutofireThrottle, &gopts.autofire_rate, 1, 1000),
Option(OptionID::kJoyDefault, &gopts.default_stick, 1, 4),
/// Keyboard
Option(OptionID::kKeyboard),
// Core
/// Core
Option(OptionID::kPrefAgbPrint, &agbPrint, 0, 1),
Option(OptionID::kPrefAutoFrameSkip, &autoFrameSkip, 0, 1),
Option(OptionID::kPrefAutoPatch, &autoPatch, 0, 1),
@ -237,8 +236,7 @@ std::array<Option, kNbOptions>& Option::All() {
Option(OptionID::kPrefBorderOn, &gbBorderOn, 0, 1),
Option(OptionID::kPrefCaptureFormat, &captureFormat, 0, 1),
Option(OptionID::kPrefCheatsEnabled, &coreOptions.cheatsEnabled, 0, 1),
Option(OptionID::kPrefDisableStatus, &disableStatusMessages, 0,
1),
Option(OptionID::kPrefDisableStatus, &disableStatusMessages, 0, 1),
Option(OptionID::kPrefEmulatorType, &gbEmulatorType, 0, 5),
Option(OptionID::kPrefFlashSize, &optFlashSize, 0, 1),
Option(OptionID::kPrefFrameSkip, &frameSkip, -1, 9),
@ -258,17 +256,12 @@ std::array<Option, kNbOptions>& Option::All() {
Option(OptionID::kPrefShowSpeedTransparent,
&showSpeedTransparent, 0, 1),
Option(OptionID::kPrefSkipBios, &coreOptions.skipBios, 0, 1),
Option(OptionID::kPrefSkipSaveGameCheats, &coreOptions.skipSaveGameCheats, 0,
1),
Option(OptionID::kPrefSkipSaveGameBattery, &coreOptions.skipSaveGameBattery,
0, 1),
Option(OptionID::kPrefSkipSaveGameCheats, &coreOptions.skipSaveGameCheats, 0, 1),
Option(OptionID::kPrefSkipSaveGameBattery, &coreOptions.skipSaveGameBattery, 0, 1),
Option(OptionID::kPrefThrottle, &throttle, 0, 450),
Option(OptionID::kPrefSpeedupThrottle, &speedup_throttle, 0,
3000),
Option(OptionID::kPrefSpeedupFrameSkip, &speedup_frame_skip, 0,
300),
Option(OptionID::kPrefSpeedupThrottleFrameSkip,
&coreOptions.speedup_throttle_frame_skip),
Option(OptionID::kPrefSpeedupThrottle, &speedup_throttle, 0, 3000),
Option(OptionID::kPrefSpeedupFrameSkip, &speedup_frame_skip, 0, 300),
Option(OptionID::kPrefSpeedupThrottleFrameSkip, &coreOptions.speedup_throttle_frame_skip),
Option(OptionID::kPrefUseBiosGB, &gopts.use_bios_file_gb),
Option(OptionID::kPrefUseBiosGBA, &gopts.use_bios_file_gba),
Option(OptionID::kPrefUseBiosGBC, &gopts.use_bios_file_gbc),
@ -283,10 +276,8 @@ std::array<Option, kNbOptions>& Option::All() {
Option(OptionID::kGeomWindowY, &g_owned_opts.window_pos_y, -1, 99999),
/// UI
Option(OptionID::kUIAllowKeyboardBackgroundInput,
&allowKeyboardBackgroundInput),
Option(OptionID::kUIAllowJoystickBackgroundInput,
&allowJoystickBackgroundInput),
Option(OptionID::kUIAllowKeyboardBackgroundInput, &allowKeyboardBackgroundInput),
Option(OptionID::kUIAllowJoystickBackgroundInput, &allowJoystickBackgroundInput),
Option(OptionID::kUIHideMenuBar, &gopts.hide_menu_bar),
/// Sound
@ -298,13 +289,13 @@ std::array<Option, kNbOptions>& Option::All() {
Option(OptionID::kSoundGBAInterpolation, &gopts.soundInterpolation),
Option(OptionID::kSoundGBDeclicking, &gopts.gb_declick),
Option(OptionID::kSoundGBEcho, &gopts.gb_echo, 0, 100),
Option(OptionID::kSoundGBEnableEffects,
&gopts.gb_effects_config_enabled),
Option(OptionID::kSoundGBEnableEffects, &gopts.gb_effects_config_enabled),
Option(OptionID::kSoundGBStereo, &gopts.gb_stereo, 0, 100),
Option(OptionID::kSoundGBSurround, &gopts.gb_effects_config_surround),
Option(OptionID::kSoundQuality, &gopts.sound_qual),
Option(OptionID::kSoundVolume, &gopts.sound_vol, 0, 200),
};
// clang-format on
return g_all_opts;
}
@ -316,282 +307,233 @@ namespace internal {
const std::array<OptionData, kNbOptions + 1> kAllOptionsData = {
/// Display
OptionData{"Display/Bilinear", "Bilinear",
_("Use bilinear filter with 3d renderer"), Option::Type::kBool},
OptionData{"Display/Filter", "", _("Full-screen filter to apply"),
Option::Type::kFilter},
OptionData{"Display/FilterPlugin", "", _("Filter plugin library"),
Option::Type::kString},
OptionData{"Display/IFB", "", _("Interframe blending function"),
Option::Type::kInterframe},
OptionData{"Display/KeepOnTop", "KeepOnTop", _("Keep window on top"),
Option::Type::kBool},
_("Use bilinear filter with 3d renderer")},
OptionData{"Display/Filter", "", _("Full-screen filter to apply")},
OptionData{"Display/FilterPlugin", "", _("Filter plugin library")},
OptionData{"Display/IFB", "", _("Interframe blending function")},
OptionData{"Display/KeepOnTop", "KeepOnTop", _("Keep window on top")},
OptionData{"Display/MaxThreads", "Multithread",
_("Maximum number of threads to run filters in"),
Option::Type::kInt},
_("Maximum number of threads to run filters in")},
OptionData{"Display/RenderMethod", "",
_("Render method; if unsupported, simple method will be used"),
Option::Type::kRenderMethod},
OptionData{"Display/Scale", "", _("Default scale factor"),
Option::Type::kDouble},
_("Render method; if unsupported, simple method will be used")},
OptionData{"Display/Scale", "", _("Default scale factor")},
OptionData{"Display/Stretch", "RetainAspect",
_("Retain aspect ratio when resizing"), Option::Type::kBool},
_("Retain aspect ratio when resizing")},
/// GB
OptionData{"GB/BiosFile", "", _("BIOS file to use for Game Boy, if enabled"),
Option::Type::kString},
OptionData{"GB/BiosFile", "",
_("BIOS file to use for Game Boy, if enabled")},
OptionData{"GB/ColorOption", "GBColorOption",
_("Game Boy color enhancement, if enabled"), Option::Type::kInt},
_("Game Boy color enhancement, if enabled")},
OptionData{"GB/ColorizerHack", "ColorizerHack",
_("Enable DX Colorization Hacks"), Option::Type::kInt},
OptionData{"GB/LCDFilter", "GBLcdFilter", _("Apply LCD filter, if enabled"),
Option::Type::kBool},
OptionData{"GB/GBCBiosFile", "", _("BIOS file to use for Game Boy Color, if enabled"),
Option::Type::kString},
_("Enable DX Colorization Hacks")},
OptionData{"GB/LCDFilter", "GBLcdFilter",
_("Apply LCD filter, if enabled")},
OptionData{"GB/GBCBiosFile", "",
_("BIOS file to use for Game Boy Color, if enabled")},
OptionData{"GB/Palette0", "",
_("The default palette, as 8 comma-separated 4-digit hex "
"integers (rgb555)."),
Option::Type::kGbPalette},
"integers (rgb555).")},
OptionData{"GB/Palette1", "",
_("The first user palette, as 8 comma-separated 4-digit hex "
"integers (rgb555)."),
Option::Type::kGbPalette},
"integers (rgb555).")},
OptionData{"GB/Palette2", "",
_("The second user palette, as 8 comma-separated 4-digit hex "
"integers (rgb555)."),
Option::Type::kGbPalette},
"integers (rgb555).")},
OptionData{"GB/PrintAutoPage", "PrintGather",
_("Automatically gather a full page before printing"),
Option::Type::kBool},
OptionData{
"GB/PrintScreenCap", "PrintSnap",
_("Automatically save printouts as screen captures with -print suffix"),
Option::Type::kBool},
OptionData{"GB/ROMDir", "", _("Directory to look for ROM files"),
Option::Type::kString},
OptionData{"GB/GBCROMDir", "", _("Directory to look for Game Boy Color ROM files"),
Option::Type::kString},
_("Automatically gather a full page before printing")},
OptionData{"GB/PrintScreenCap", "PrintSnap",
_("Automatically save printouts as screen captures with -print "
"suffix")},
OptionData{"GB/ROMDir", "", _("Directory to look for ROM files")},
OptionData{"GB/GBCROMDir", "",
_("Directory to look for Game Boy Color ROM files")},
/// GBA
OptionData{"GBA/BiosFile", "", _("BIOS file to use, if enabled"),
Option::Type::kString},
OptionData{"GBA/LCDFilter", "GBALcdFilter",
_("Apply LCD filter, if enabled"), Option::Type::kBool},
OptionData{"GBA/BiosFile", "", _("BIOS file to use, if enabled")},
OptionData{
"GBA/LCDFilter",
"GBALcdFilter",
_("Apply LCD filter, if enabled"),
},
#ifndef NO_LINK
OptionData{"GBA/LinkAuto", "LinkAuto", _("Enable link at boot"),
Option::Type::kBool},
OptionData{"GBA/LinkFast", "SpeedOn",
_("Enable faster network protocol by default"),
Option::Type::kBool},
OptionData{"GBA/LinkHost", "", _("Default network link client host"),
Option::Type::kString},
OptionData{"GBA/ServerIP", "", _("Default network link server IP to bind"),
Option::Type::kString},
OptionData{
"GBA/LinkAuto",
"LinkAuto",
_("Enable link at boot"),
},
OptionData{
"GBA/LinkFast",
"SpeedOn",
_("Enable faster network protocol by default"),
},
OptionData{"GBA/LinkHost", "", _("Default network link client host")},
OptionData{"GBA/ServerIP", "", _("Default network link server IP to bind")},
OptionData{"GBA/LinkPort", "",
_("Default network link port (server and client)"),
Option::Type::kUnsigned},
OptionData{"GBA/LinkProto", "LinkProto", _("Default network protocol"),
Option::Type::kBool},
OptionData{"GBA/LinkTimeout", "LinkTimeout", _("Link timeout (ms)"),
Option::Type::kInt},
OptionData{"GBA/LinkType", "LinkType", _("Link cable type"),
Option::Type::kInt},
_("Default network link port (server and client)")},
OptionData{"GBA/LinkProto", "LinkProto", _("Default network protocol")},
OptionData{"GBA/LinkTimeout", "LinkTimeout", _("Link timeout (ms)")},
OptionData{"GBA/LinkType", "LinkType", _("Link cable type")},
#endif
OptionData{"GBA/ROMDir", "", _("Directory to look for ROM files"),
Option::Type::kString},
OptionData{"GBA/ROMDir", "", _("Directory to look for ROM files")},
/// General
OptionData{"General/AutoLoadLastState", "",
_("Automatically load last saved state"), Option::Type::kBool},
_("Automatically load last saved state")},
OptionData{"General/BatteryDir", "",
_("Directory to store game save files (relative paths are "
"relative to ROM; blank is config dir)"),
Option::Type::kString},
OptionData{"General/FreezeRecent", "", _("Freeze recent load list"),
Option::Type::kBool},
"relative to ROM; blank is config dir)")},
OptionData{"General/FreezeRecent", "", _("Freeze recent load list")},
OptionData{"General/RecordingDir", "",
_("Directory to store A / V and game recordings (relative paths "
"are relative to ROM)"),
Option::Type::kString},
"are relative to ROM)")},
OptionData{"General/RewindInterval", "",
_("Number of seconds between rewind snapshots (0 to disable)"),
Option::Type::kInt},
_("Number of seconds between rewind snapshots (0 to disable)")},
OptionData{"General/ScreenshotDir", "",
_("Directory to store screenshots (relative paths are relative "
"to ROM)"),
Option::Type::kString},
"to ROM)")},
OptionData{"General/StateDir", "",
_("Directory to store saved state files (relative paths are "
"relative to BatteryDir)"),
Option::Type::kString},
OptionData{"General/StatusBar", "StatusBar", _("Enable status bar"),
Option::Type::kBool},
"relative to BatteryDir)")},
OptionData{"General/StatusBar", "StatusBar", _("Enable status bar")},
/// Joypad
OptionData{"Joypad/*/*", "",
_("The parameter Joypad/<n>/<button> contains a comma-separated "
"list of key names which map to joypad #<n> button <button>. "
"Button is one of Up, Down, Left, Right, A, B, L, R, Select, "
"Start, Motion Up, Motion Down, Motion Left, Motion Right, Autofire A, "
"Autofire B, Speed, Capture, GS"),
Option::Type::kNone},
"Start, MotionUp, MotionDown, MotionLeft, MotionRight, AutoA, "
"AutoB, Speed, Capture, GS")},
OptionData{"Joypad/AutofireThrottle", "",
_("The autofire toggle period, in frames (1 / 60 s)"),
Option::Type::kInt},
_("The autofire toggle period, in frames (1/60 s)")},
OptionData{"Joypad/Default", "",
_("The number of the stick to use in single-player mode"),
Option::Type::kInt},
_("The number of the stick to use in single-player mode")},
/// Keyboard
OptionData{"Keyboard/*", "",
_("The parameter Keyboard/<cmd> contains a comma-separated list "
"of key names (e.g. Alt + Shift + F1). When the named key is "
"pressed, the command <cmd> is executed."),
Option::Type::kNone},
"of key names (e.g. Alt-Shift-F1). When the named key is "
"pressed, the command <cmd> is executed.")},
// Core
/// Core
OptionData{"preferences/agbPrint", "AGBPrinter",
_("Enable AGB debug print"), Option::Type::kInt},
_("Enable AGB debug print")},
OptionData{"preferences/autoFrameSkip", "FrameSkipAuto",
_("Auto skip frames"), Option::Type::kInt},
_("Auto skip frames")},
OptionData{"preferences/autoPatch", "ApplyPatches",
_("Apply IPS / UPS / IPF patches if found"), Option::Type::kInt},
_("Apply IPS / UPS / IPF patches if found")},
OptionData{"preferences/autoSaveLoadCheatList", "",
_("Automatically save and load cheat list"),
Option::Type::kBool},
OptionData{"preferences/borderAutomatic", "",
_("Automatically enable border for Super Game Boy games"),
Option::Type::kInt},
OptionData{"preferences/borderOn", "", _("Always enable border"),
Option::Type::kInt},
OptionData{"preferences/captureFormat", "", _("Screen capture file format"),
Option::Type::kInt},
OptionData{"preferences/cheatsEnabled", "", _("Enable cheats"),
Option::Type::kInt},
_("Automatically save and load cheat list")},
OptionData{
"preferences/borderAutomatic",
"",
_("Automatically enable border for Super Game Boy games"),
},
OptionData{"preferences/borderOn", "", _("Always enable border")},
OptionData{"preferences/captureFormat", "",
_("Screen capture file format")},
OptionData{"preferences/cheatsEnabled", "", _("Enable cheats")},
OptionData{"preferences/disableStatus", "NoStatusMsg",
_("Disable on-screen status messages"), Option::Type::kInt},
OptionData{"preferences/emulatorType", "", _("Type of system to emulate"),
Option::Type::kInt},
OptionData{"preferences/flashSize", "", _("Flash size 0 = 64 KB 1 = 128 KB"),
Option::Type::kInt},
_("Disable on-screen status messages")},
OptionData{"preferences/emulatorType", "", _("Type of system to emulate")},
OptionData{"preferences/flashSize", "",
_("Flash size 0 = 64 KB 1 = 128 KB")},
OptionData{"preferences/frameSkip", "FrameSkip",
_("Skip frames. Values are 0-9 or -1 to skip automatically "
"based on time."),
Option::Type::kInt},
OptionData{"preferences/gbPaletteOption", "", _("The palette to use"),
Option::Type::kInt},
"based on time.")},
OptionData{"preferences/gbPaletteOption", "", _("The palette to use")},
OptionData{"preferences/gbPrinter", "Printer",
_("Enable printer emulation"), Option::Type::kInt},
_("Enable printer emulation")},
OptionData{"preferences/gdbBreakOnLoad", "DebugGDBBreakOnLoad",
_("Break into GDB after loading the game."), Option::Type::kBool},
_("Break into GDB after loading the game.")},
OptionData{"preferences/gdbPort", "DebugGDBPort",
_("Port to connect GDB to."), Option::Type::kInt},
_("Port to connect GDB to.")},
#ifndef NO_LINK
OptionData{"preferences/LinkNumPlayers", "",
_("Number of players in network"), Option::Type::kInt},
_("Number of players in network")},
#endif
OptionData{"preferences/maxScale", "",
_("Maximum scale factor (0 = no limit)"), Option::Type::kInt},
_("Maximum scale factor (0 = no limit)")},
OptionData{"preferences/pauseWhenInactive", "PauseWhenInactive",
_("Pause game when main window loses focus"),
Option::Type::kInt},
_("Pause game when main window loses focus")},
OptionData{"preferences/rtcEnabled", "RTC",
_("Enable RTC (vba-over.ini override is rtcEnabled"),
Option::Type::kInt},
_("Enable RTC (vba-over.ini override is rtcEnabled")},
OptionData{"preferences/saveType", "",
_("Native save (\"battery\") hardware type"),
Option::Type::kInt},
OptionData{"preferences/showSpeed", "", _("Show speed indicator"),
Option::Type::kInt},
_("Native save (\"battery\") hardware type")},
OptionData{"preferences/showSpeed", "", _("Show speed indicator")},
OptionData{"preferences/showSpeedTransparent", "Transparent",
_("Draw on-screen messages transparently"), Option::Type::kInt},
_("Draw on-screen messages transparently")},
OptionData{"preferences/skipBios", "SkipIntro",
_("Skip BIOS initialization"), Option::Type::kInt},
_("Skip BIOS initialization")},
OptionData{"preferences/skipSaveGameCheats", "",
_("Do not overwrite cheat list when loading state"),
Option::Type::kInt},
_("Do not overwrite cheat list when loading state")},
OptionData{"preferences/skipSaveGameBattery", "",
_("Do not overwrite native (battery) save when loading state"),
Option::Type::kInt},
_("Do not overwrite native (battery) save when loading state")},
OptionData{"preferences/throttle", "",
_("Throttle game speed, even when accelerated (0-450 %, 0 = no "
"throttle)"),
Option::Type::kUnsigned},
"throttle)")},
OptionData{"preferences/speedupThrottle", "",
_("Set throttle for speedup key (0-3000 %, 0 = no throttle)"),
Option::Type::kUnsigned},
_("Set throttle for speedup key (0-3000 %, 0 = no throttle)")},
OptionData{"preferences/speedupFrameSkip", "",
_("Number of frames to skip with speedup (instead of speedup "
"throttle)"),
Option::Type::kUnsigned},
"throttle)")},
OptionData{"preferences/speedupThrottleFrameSkip", "",
_("Use frame skip for speedup throttle"), Option::Type::kBool},
_("Use frame skip for speedup throttle")},
OptionData{"preferences/useBiosGB", "BootRomGB",
_("Use the specified BIOS file for Game Boy"), Option::Type::kBool},
_("Use the specified BIOS file for Game Boy")},
OptionData{"preferences/useBiosGBA", "BootRomEn",
_("Use the specified BIOS file"), Option::Type::kBool},
_("Use the specified BIOS file")},
OptionData{"preferences/useBiosGBC", "BootRomGBC",
_("Use the specified BIOS file for Game Boy Color"), Option::Type::kBool},
OptionData{"preferences/vsync", "VSync", _("Wait for vertical sync"),
Option::Type::kBool},
_("Use the specified BIOS file for Game Boy Color")},
OptionData{"preferences/vsync", "VSync", _("Wait for vertical sync")},
/// Geometry
OptionData{"geometry/fullScreen", "Fullscreen",
_("Enter fullscreen mode at startup"), Option::Type::kInt},
OptionData{"geometry/isMaximized", "Maximized", _("Window maximized"),
Option::Type::kBool},
OptionData{"geometry/windowHeight", "Height", _("Window height at startup"),
Option::Type::kUnsigned},
OptionData{"geometry/windowWidth", "Width", _("Window width at startup"),
Option::Type::kUnsigned},
OptionData{"geometry/windowX", "X", _("Window axis X position at startup"),
Option::Type::kInt},
OptionData{"geometry/windowY", "Y", _("Window axis Y position at startup"),
Option::Type::kInt},
_("Enter fullscreen mode at startup")},
OptionData{"geometry/isMaximized", "Maximized", _("Window maximized")},
OptionData{"geometry/windowHeight", "Height",
_("Window height at startup")},
OptionData{"geometry/windowWidth", "Width", _("Window width at startup")},
OptionData{"geometry/windowX", "X", _("Window axis X position at startup")},
OptionData{"geometry/windowY", "Y", _("Window axis Y position at startup")},
/// UI
OptionData{
"ui/allowKeyboardBackgroundInput", "AllowKeyboardBackgroundInput",
_("Capture key events while on background"), Option::Type::kBool},
OptionData{
"ui/allowJoystickBackgroundInput", "AllowJoystickBackgroundInput",
_("Capture joy events while on background"), Option::Type::kBool},
OptionData{"ui/hideMenuBar", "", _("Hide menu bar when mouse is inactive"),
Option::Type::kBool},
OptionData{"ui/allowKeyboardBackgroundInput",
"AllowKeyboardBackgroundInput",
_("Capture key events while on background")},
OptionData{"ui/allowJoystickBackgroundInput",
"AllowJoystickBackgroundInput",
_("Capture joy events while on background")},
OptionData{"ui/hideMenuBar", "", _("Hide menu bar when mouse is inactive")},
/// Sound
OptionData{"Sound/AudioAPI", "",
_("Sound API; if unsupported, default API will be used"),
Option::Type::kAudioApi},
_("Sound API; if unsupported, default API will be used")},
OptionData{"Sound/AudioDevice", "",
_("Device ID of chosen audio device for chosen driver"),
Option::Type::kString},
OptionData{"Sound/Buffers", "", _("Number of sound buffers"),
Option::Type::kInt},
OptionData{"Sound/Enable", "", _("Bit mask of sound channels to enable"),
Option::Type::kInt},
OptionData{"Sound/GBAFiltering", "", _("Game Boy Advance sound filtering (%)"),
Option::Type::kInt},
_("Device ID of chosen audio device for chosen driver")},
OptionData{"Sound/Buffers", "", _("Number of sound buffers")},
OptionData{"Sound/Enable", "", _("Bit mask of sound channels to enable")},
OptionData{"Sound/GBAFiltering", "",
_("Game Boy Advance sound filtering (%)")},
OptionData{"Sound/GBAInterpolation", "GBASoundInterpolation",
_("Game Boy Advance sound interpolation"), Option::Type::kBool},
OptionData{"Sound/GBDeclicking", "GBDeclicking", _("Game Boy sound declicking"),
Option::Type::kBool},
OptionData{"Sound/GBEcho", "", _("Game Boy echo effect (%)"), Option::Type::kInt},
_("Game Boy Advance sound interpolation")},
OptionData{"Sound/GBDeclicking", "GBDeclicking",
_("Game Boy sound declicking")},
OptionData{"Sound/GBEcho", "", _("Game Boy echo effect (%)")},
OptionData{"Sound/GBEnableEffects", "GBEnhanceSound",
_("Enable Game Boy sound effects"), Option::Type::kBool},
OptionData{"Sound/GBStereo", "", _("Game Boy stereo effect (%)"),
Option::Type::kInt},
_("Enable Game Boy sound effects")},
OptionData{"Sound/GBStereo", "", _("Game Boy stereo effect (%)")},
OptionData{"Sound/GBSurround", "GBSurround",
_("Game Boy surround sound effect (%)"), Option::Type::kBool},
OptionData{"Sound/Quality", "", _("Sound sample rate (kHz)"),
Option::Type::kSoundQuality},
OptionData{"Sound/Volume", "", _("Sound volume (%)"), Option::Type::kInt},
_("Game Boy surround sound effect (%)")},
OptionData{"Sound/Quality", "", _("Sound sample rate (kHz)")},
OptionData{"Sound/Volume", "", _("Sound volume (%)")},
// Last. This should never be used, it actually maps to OptionID::kLast.
// This is to prevent a memory access violation error in case something
// attempts to instantiate a OptionID::kLast. It will trigger a check
// in the Option constructor, but that is after the constructor has
// accessed this entry.
OptionData{"", "", "", Option::Type::kNone},
OptionData{"", "", ""},
};
nonstd::optional<OptionID> StringToOptionId(const wxString& input) {
@ -613,19 +555,19 @@ nonstd::optional<OptionID> StringToOptionId(const wxString& input) {
wxString FilterToString(const Filter& value) {
const size_t size_value = static_cast<size_t>(value);
assert(size_value >= 0 && size_value < kNbFilters);
assert(size_value < kNbFilters);
return kFilterStrings[size_value];
}
wxString InterframeToString(const Interframe& value) {
const size_t size_value = static_cast<size_t>(value);
assert(size_value >= 0 && size_value < kNbInterframes);
assert(size_value < kNbInterframes);
return kInterframeStrings[size_value];
}
wxString RenderMethodToString(const RenderMethod& value) {
const size_t size_value = static_cast<size_t>(value);
assert(size_value >= 0 && size_value < kNbRenderMethods);
assert(size_value < kNbRenderMethods);
return kRenderMethodStrings[size_value];
}
@ -643,8 +585,7 @@ Filter StringToFilter(const wxString& config_name, const wxString& input) {
static std::map<wxString, Filter> kStringToFilter;
if (kStringToFilter.empty()) {
for (size_t i = 0; i < kNbFilters; i++) {
kStringToFilter.emplace(kFilterStrings[i],
static_cast<Filter>(i));
kStringToFilter.emplace(kFilterStrings[i], static_cast<Filter>(i));
}
assert(kStringToFilter.size() == kNbFilters);
}

View File

@ -16,7 +16,6 @@ struct OptionData {
const wxString config_name;
const wxString command;
const wxString ux_helper;
const Option::Type type;
};
// Static data to initialize global values.

View File

@ -62,7 +62,7 @@ enum class OptionID {
/// Keyboard
kKeyboard,
// Core
/// Core
kPrefAgbPrint,
kPrefAutoFrameSkip,
kPrefAutoPatch,
@ -71,7 +71,6 @@ enum class OptionID {
kPrefBorderOn,
kPrefCaptureFormat,
kPrefCheatsEnabled,
kPrefDisableStatus,
kPrefEmulatorType,
kPrefFlashSize,

View File

@ -0,0 +1,279 @@
#ifndef VBAM_WX_CONFIG_OPTION_PROXY_H_
#define VBAM_WX_CONFIG_OPTION_PROXY_H_
#include <array>
#include <type_traits>
#include "config/option-id.h"
#include "config/option.h"
namespace config {
static constexpr std::array<Option::Type, kNbOptions> kOptionsTypes = {
/// Display
/*kDispBilinear*/ Option::Type::kBool,
/*kDispFilter*/ Option::Type::kFilter,
/*kDispFilterPlugin*/ Option::Type::kString,
/*kDispIFB*/ Option::Type::kInterframe,
/*kDispKeepOnTop*/ Option::Type::kBool,
/*kDispMaxThreads*/ Option::Type::kInt,
/*kDispRenderMethod*/ Option::Type::kRenderMethod,
/*kDispScale*/ Option::Type::kDouble,
/*kDispStretch*/ Option::Type::kBool,
/// GB
/*kGBBiosFile*/ Option::Type::kString,
/*kGBColorOption*/ Option::Type::kInt,
/*kGBColorizerHack*/ Option::Type::kInt,
/*kGBLCDFilter*/ Option::Type::kBool,
/*kGBGBCBiosFile*/ Option::Type::kString,
/*kGBPalette0*/ Option::Type::kGbPalette,
/*kGBPalette1*/ Option::Type::kGbPalette,
/*kGBPalette2*/ Option::Type::kGbPalette,
/*kGBPrintAutoPage*/ Option::Type::kBool,
/*kGBPrintScreenCap*/ Option::Type::kBool,
/*kGBROMDir*/ Option::Type::kString,
/*kGBGBCROMDir*/ Option::Type::kString,
/// GBA
/*kGBABiosFile*/ Option::Type::kString,
/*kGBALCDFilter*/ Option::Type::kBool,
#ifndef NO_LINK
/*kGBALinkAuto*/ Option::Type::kBool,
/*kGBALinkFast*/ Option::Type::kBool,
/*kGBALinkHost*/ Option::Type::kString,
/*kGBAServerIP*/ Option::Type::kString,
/*kGBALinkPort*/ Option::Type::kUnsigned,
/*kGBALinkProto*/ Option::Type::kBool,
/*kGBALinkTimeout*/ Option::Type::kInt,
/*kGBALinkType*/ Option::Type::kInt,
#endif
/*kGBAROMDir*/ Option::Type::kString,
/// General
/*kGenAutoLoadLastState*/ Option::Type::kBool,
/*kGenBatteryDir*/ Option::Type::kString,
/*kGenFreezeRecent*/ Option::Type::kBool,
/*kGenRecordingDir*/ Option::Type::kString,
/*kGenRewindInterval*/ Option::Type::kInt,
/*kGenScreenshotDir*/ Option::Type::kString,
/*kGenStateDir*/ Option::Type::kString,
/*kGenStatusBar*/ Option::Type::kBool,
/// Joypad
/*kJoy*/ Option::Type::kNone,
/*kJoyAutofireThrottle*/ Option::Type::kInt,
/*kJoyDefault*/ Option::Type::kInt,
/// Keyboard
/*kKeyboard*/ Option::Type::kNone,
/// Core
/*kPrefAgbPrint*/ Option::Type::kInt,
/*kPrefAutoFrameSkip*/ Option::Type::kInt,
/*kPrefAutoPatch*/ Option::Type::kInt,
/*kPrefAutoSaveLoadCheatList*/ Option::Type::kBool,
/*kPrefBorderAutomatic*/ Option::Type::kInt,
/*kPrefBorderOn*/ Option::Type::kInt,
/*kPrefCaptureFormat*/ Option::Type::kInt,
/*kPrefCheatsEnabled*/ Option::Type::kInt,
/*kPrefDisableStatus*/ Option::Type::kInt,
/*kPrefEmulatorType*/ Option::Type::kInt,
/*kPrefFlashSize*/ Option::Type::kInt,
/*kPrefFrameSkip*/ Option::Type::kInt,
/*kPrefGBPaletteOption*/ Option::Type::kInt,
/*kPrefGBPrinter*/ Option::Type::kInt,
/*kPrefGDBBreakOnLoad*/ Option::Type::kBool,
/*kPrefGDBPort*/ Option::Type::kInt,
#ifndef NO_LINK
/*kPrefLinkNumPlayers*/ Option::Type::kInt,
#endif
/*kPrefMaxScale*/ Option::Type::kInt,
/*kPrefPauseWhenInactive*/ Option::Type::kInt,
/*kPrefRTCEnabled*/ Option::Type::kInt,
/*kPrefSaveType*/ Option::Type::kInt,
/*kPrefShowSpeed*/ Option::Type::kInt,
/*kPrefShowSpeedTransparent*/ Option::Type::kInt,
/*kPrefSkipBios*/ Option::Type::kInt,
/*kPrefSkipSaveGameCheats*/ Option::Type::kInt,
/*kPrefSkipSaveGameBattery*/ Option::Type::kInt,
/*kPrefThrottle*/ Option::Type::kUnsigned,
/*kPrefSpeedupThrottle*/ Option::Type::kUnsigned,
/*kPrefSpeedupFrameSkip*/ Option::Type::kUnsigned,
/*kPrefSpeedupThrottleFrameSkip*/ Option::Type::kBool,
/*kPrefUseBiosGB*/ Option::Type::kBool,
/*kPrefUseBiosGBA*/ Option::Type::kBool,
/*kPrefUseBiosGBC*/ Option::Type::kBool,
/*kPrefVsync*/ Option::Type::kBool,
/// Geometry
/*kGeomFullScreen*/ Option::Type::kInt,
/*kGeomIsMaximized*/ Option::Type::kBool,
/*kGeomWindowHeight*/ Option::Type::kUnsigned,
/*kGeomWindowWidth*/ Option::Type::kUnsigned,
/*kGeomWindowX*/ Option::Type::kInt,
/*kGeomWindowY*/ Option::Type::kInt,
/// UI
/*kUIAllowKeyboardBackgroundInput*/ Option::Type::kBool,
/*kUIAllowJoystickBackgroundInput*/ Option::Type::kBool,
/*kUIHideMenuBar*/ Option::Type::kBool,
/// Sound
/*kSoundAudioAPI*/ Option::Type::kAudioApi,
/*kSoundAudioDevice*/ Option::Type::kString,
/*kSoundBuffers*/ Option::Type::kInt,
/*kSoundEnable*/ Option::Type::kInt,
/*kSoundGBAFiltering*/ Option::Type::kInt,
/*kSoundGBAInterpolation*/ Option::Type::kBool,
/*kSoundGBDeclicking*/ Option::Type::kBool,
/*kSoundGBEcho*/ Option::Type::kInt,
/*kSoundGBEnableEffects*/ Option::Type::kBool,
/*kSoundGBStereo*/ Option::Type::kInt,
/*kSoundGBSurround*/ Option::Type::kBool,
/*kSoundQuality*/ Option::Type::kSoundQuality,
/*kSoundVolume*/ Option::Type::kInt,
};
// Less verbose accessor for a specific OptionID with compile-time type checks.
//
// Sample usage:
// if (Proxy<OptionID::kDispBilinear>::Get()) {
// // Do something if bilinear filter is on.
// }
//
// Proxy<OptionID::kDispBilinear>::Set(false);
template <OptionID ID, typename = void>
class Proxy {};
template <OptionID ID>
class Proxy<
ID,
typename std::enable_if<kOptionsTypes[static_cast<size_t>(ID)] == Option::Type::kBool>::type> {
public:
Proxy() : option_(Option::ByID(ID)) {}
~Proxy() = default;
bool Get() { return option_->GetBool(); }
bool Set(bool value) { return option_->SetBool(value); }
private:
Option* option_;
};
template <OptionID ID>
class Proxy<ID,
typename std::enable_if<kOptionsTypes[static_cast<size_t>(ID)] ==
Option::Type::kDouble>::type> {
public:
Proxy() : option_(Option::ByID(ID)) {}
~Proxy() = default;
double Get() { return option_->GetDouble(); }
bool Set(double value) { return option_->SetDouble(value); }
double Min() const { return option_->GetDoubleMin(); }
double Max() const { return option_->GetDoubleMax(); }
private:
Option* option_;
};
template <OptionID ID>
class Proxy<
ID,
typename std::enable_if<kOptionsTypes[static_cast<size_t>(ID)] == Option::Type::kInt>::type> {
public:
Proxy() : option_(Option::ByID(ID)) {}
~Proxy() = default;
int32_t Get() { return option_->GetInt(); }
bool Set(int32_t value) { return option_->SetInt(value); }
int32_t Min() const { return option_->GetIntMin(); }
int32_t Max() const { return option_->GetIntMax(); }
private:
Option* option_;
};
template <OptionID ID>
class Proxy<ID,
typename std::enable_if<kOptionsTypes[static_cast<size_t>(ID)] ==
Option::Type::kUnsigned>::type> {
public:
Proxy() : option_(Option::ByID(ID)) {}
~Proxy() = default;
uint32_t Get() { return option_->GetUnsigned(); }
bool Set(uint32_t value) { return option_->SetUnsigned(value); }
uint32_t Min() const { return option_->GetUnsignedMin(); }
uint32_t Max() const { return option_->GetUnsignedMax(); }
private:
Option* option_;
};
template <OptionID ID>
class Proxy<ID,
typename std::enable_if<kOptionsTypes[static_cast<size_t>(ID)] ==
Option::Type::kString>::type> {
public:
Proxy() : option_(Option::ByID(ID)) {}
~Proxy() = default;
const wxString& Get() { return option_->GetString(); }
bool Set(const wxString& value) { return option_->SetString(value); }
private:
Option* option_;
};
template <OptionID ID>
class Proxy<ID,
typename std::enable_if<kOptionsTypes[static_cast<size_t>(ID)] ==
Option::Type::kFilter>::type> {
public:
Proxy() : option_(Option::ByID(ID)) {}
~Proxy() = default;
Filter Get() { return option_->GetFilter(); }
bool Set(Filter value) { return option_->SetFilter(value); }
void Next() { option_->NextFilter(); }
private:
Option* option_;
};
template <OptionID ID>
class Proxy<ID,
typename std::enable_if<kOptionsTypes[static_cast<size_t>(ID)] ==
Option::Type::kInterframe>::type> {
public:
Proxy() : option_(Option::ByID(ID)) {}
~Proxy() = default;
Interframe Get() { return option_->GetInterframe(); }
bool Set(Interframe value) { return option_->SetInterframe(value); }
void Next() { option_->NextInterframe(); }
private:
Option* option_;
};
template <OptionID ID>
class Proxy<ID,
typename std::enable_if<kOptionsTypes[static_cast<size_t>(ID)] ==
Option::Type::kRenderMethod>::type> {
public:
Proxy() : option_(Option::ByID(ID)) {}
~Proxy() = default;
RenderMethod Get() { return option_->GetRenderMethod(); }
bool Set(RenderMethod value) { return option_->SetRenderMethod(value); }
private:
Option* option_;
};
} // namespace config
#endif // VBAM_WX_CONFIG_OPTION_PROXY_H_

View File

@ -9,6 +9,8 @@
#include "config/internal/option-internal.h"
#undef VBAM_OPTION_INTERNAL_INCLUDE
#include "config/option-proxy.h"
namespace config {
// static
@ -45,7 +47,7 @@ Option::Option(OptionID id)
command_(internal::kAllOptionsData[static_cast<size_t>(id)].command),
ux_helper_(wxGetTranslation(
internal::kAllOptionsData[static_cast<size_t>(id)].ux_helper)),
type_(internal::kAllOptionsData[static_cast<size_t>(id)].type),
type_(kOptionsTypes[static_cast<size_t>(id)]),
value_(),
min_(),
max_() {
@ -60,7 +62,7 @@ Option::Option(OptionID id, bool* option)
command_(internal::kAllOptionsData[static_cast<size_t>(id)].command),
ux_helper_(wxGetTranslation(
internal::kAllOptionsData[static_cast<size_t>(id)].ux_helper)),
type_(internal::kAllOptionsData[static_cast<size_t>(id)].type),
type_(kOptionsTypes[static_cast<size_t>(id)]),
value_(option),
min_(),
max_() {
@ -75,7 +77,7 @@ Option::Option(OptionID id, double* option, double min, double max)
command_(internal::kAllOptionsData[static_cast<size_t>(id)].command),
ux_helper_(wxGetTranslation(
internal::kAllOptionsData[static_cast<size_t>(id)].ux_helper)),
type_(internal::kAllOptionsData[static_cast<size_t>(id)].type),
type_(kOptionsTypes[static_cast<size_t>(id)]),
value_(option),
min_(min),
max_(max) {
@ -93,7 +95,7 @@ Option::Option(OptionID id, int32_t* option, int32_t min, int32_t max)
command_(internal::kAllOptionsData[static_cast<size_t>(id)].command),
ux_helper_(wxGetTranslation(
internal::kAllOptionsData[static_cast<size_t>(id)].ux_helper)),
type_(internal::kAllOptionsData[static_cast<size_t>(id)].type),
type_(kOptionsTypes[static_cast<size_t>(id)]),
value_(option),
min_(min),
max_(max) {
@ -111,7 +113,7 @@ Option::Option(OptionID id, uint32_t* option, uint32_t min, uint32_t max)
command_(internal::kAllOptionsData[static_cast<size_t>(id)].command),
ux_helper_(wxGetTranslation(
internal::kAllOptionsData[static_cast<size_t>(id)].ux_helper)),
type_(internal::kAllOptionsData[static_cast<size_t>(id)].type),
type_(kOptionsTypes[static_cast<size_t>(id)]),
value_(option),
min_(min),
max_(max) {
@ -129,7 +131,7 @@ Option::Option(OptionID id, wxString* option)
command_(internal::kAllOptionsData[static_cast<size_t>(id)].command),
ux_helper_(wxGetTranslation(
internal::kAllOptionsData[static_cast<size_t>(id)].ux_helper)),
type_(internal::kAllOptionsData[static_cast<size_t>(id)].type),
type_(kOptionsTypes[static_cast<size_t>(id)]),
value_(option),
min_(),
max_() {
@ -144,7 +146,7 @@ Option::Option(OptionID id, Filter* option)
command_(internal::kAllOptionsData[static_cast<size_t>(id)].command),
ux_helper_(wxGetTranslation(
internal::kAllOptionsData[static_cast<size_t>(id)].ux_helper)),
type_(internal::kAllOptionsData[static_cast<size_t>(id)].type),
type_(kOptionsTypes[static_cast<size_t>(id)]),
value_(option),
min_(0),
max_(internal::MaxForType(type_)) {
@ -159,7 +161,7 @@ Option::Option(OptionID id, Interframe* option)
command_(internal::kAllOptionsData[static_cast<size_t>(id)].command),
ux_helper_(wxGetTranslation(
internal::kAllOptionsData[static_cast<size_t>(id)].ux_helper)),
type_(internal::kAllOptionsData[static_cast<size_t>(id)].type),
type_(kOptionsTypes[static_cast<size_t>(id)]),
value_(option),
min_(0),
max_(internal::MaxForType(type_)) {
@ -174,7 +176,7 @@ Option::Option(OptionID id, RenderMethod* option)
command_(internal::kAllOptionsData[static_cast<size_t>(id)].command),
ux_helper_(wxGetTranslation(
internal::kAllOptionsData[static_cast<size_t>(id)].ux_helper)),
type_(internal::kAllOptionsData[static_cast<size_t>(id)].type),
type_(kOptionsTypes[static_cast<size_t>(id)]),
value_(option),
min_(0),
max_(internal::MaxForType(type_)) {
@ -189,7 +191,7 @@ Option::Option(OptionID id, int* option)
command_(internal::kAllOptionsData[static_cast<size_t>(id)].command),
ux_helper_(wxGetTranslation(
internal::kAllOptionsData[static_cast<size_t>(id)].ux_helper)),
type_(internal::kAllOptionsData[static_cast<size_t>(id)].type),
type_(kOptionsTypes[static_cast<size_t>(id)]),
value_(option),
min_(0),
max_(internal::MaxForType(type_)) {
@ -207,7 +209,7 @@ Option::Option(OptionID id, uint16_t* option)
command_(internal::kAllOptionsData[static_cast<size_t>(id)].command),
ux_helper_(wxGetTranslation(
internal::kAllOptionsData[static_cast<size_t>(id)].ux_helper)),
type_(internal::kAllOptionsData[static_cast<size_t>(id)].type),
type_(kOptionsTypes[static_cast<size_t>(id)]),
value_(option),
min_(),
max_() {

View File

@ -261,42 +261,6 @@ private:
const nonstd::variant<nonstd::monostate, double, int32_t, uint32_t> max_;
};
// Convenience direct accessors. These are used to make direct access to
// individual options less verbose.
inline Option* OptDispFilter() {
return Option::ByID(OptionID::kDispFilter);
}
inline Option* OptDispIFB() {
return Option::ByID(OptionID::kDispIFB);
}
inline Option* OptDispFilterPlugin() {
return Option::ByID(OptionID::kDispFilterPlugin);
}
inline Option* OptDispRenderMethod() {
return Option::ByID(OptionID::kDispRenderMethod);
}
inline Option* OptDispScale() {
return Option::ByID(OptionID::kDispScale);
}
inline Option* OptGeomFullScreen() {
return Option::ByID(OptionID::kGeomFullScreen);
}
inline Option* OptGeomIsMaximized() {
return Option::ByID(OptionID::kGeomIsMaximized);
}
inline Option* OptGeomWindowHeight() {
return Option::ByID(OptionID::kGeomWindowHeight);
}
inline Option* OptGeomWindowWidth() {
return Option::ByID(OptionID::kGeomWindowWidth);
}
inline Option* OptGeomWindowX() {
return Option::ByID(OptionID::kGeomWindowX);
}
inline Option* OptGeomWindowY() {
return Option::ByID(OptionID::kGeomWindowY);
}
} // namespace config
#endif // VBAM_WX_CONFIG_OPTIONS_H_

View File

@ -15,6 +15,8 @@
#include <wx/xrc/xmlres.h>
#include "config/option-id.h"
#include "config/option-proxy.h"
#include "config/option.h"
#include "rpi.h"
#include "wayland.h"
@ -352,8 +354,7 @@ void DisplayConfig::PopulatePluginOptions() {
plugin_selector_->Clear();
plugin_selector_->Append(_("None"), new wxStringClientData());
const wxString& selected_plugin =
config::OptDispFilterPlugin()->GetString();
const wxString& selected_plugin = config::Proxy<config::OptionID::kDispFilterPlugin>().Get();
bool is_plugin_selected = false;
for (const wxString& plugin : plugins) {
@ -388,7 +389,7 @@ void DisplayConfig::PopulatePluginOptions() {
}
if (!is_plugin_selected) {
config::OptDispFilterPlugin()->SetString(wxEmptyString);
config::Proxy<config::OptionID::kDispFilterPlugin>().Set(wxEmptyString);
}
plugin_selector_->SetValidator(PluginSelectorValidator());
@ -443,14 +444,14 @@ void DisplayConfig::HidePluginOptions() {
if (filter_selector_->GetCount() == config::kNbFilters) {
// Make sure we have not selected the plugin option. The validator
// will take care of updating the selector value.
if (config::OptDispFilter()->GetFilter() == config::Filter::kPlugin) {
config::OptDispFilter()->SetFilter(config::Filter::kNone);
if (config::Proxy<config::OptionID::kDispFilter>().Get() == config::Filter::kPlugin) {
config::Proxy<config::OptionID::kDispFilter>().Set(config::Filter::kNone);
}
filter_selector_->Delete(config::kNbFilters - 1);
}
// Also erase the Plugin value to avoid issues down the line.
config::OptDispFilterPlugin()->SetString(wxEmptyString);
config::Proxy<config::OptionID::kDispFilterPlugin>().Set(wxEmptyString);
}
void DisplayConfig::ShowPluginOptions() {

View File

@ -29,6 +29,7 @@
#include "../sdl/text.h"
#include "background-input.h"
#include "config/game-control.h"
#include "config/option-proxy.h"
#include "config/option.h"
#include "config/user-input.h"
#include "drawing.h"
@ -46,7 +47,7 @@
namespace {
double GetFilterScale() {
switch (config::OptDispFilter()->GetFilter()) {
switch (config::Proxy<config::OptionID::kDispFilter>().Get()) {
case config::Filter::kNone:
return 1.0;
case config::Filter::k2xsai:
@ -387,7 +388,7 @@ void GameArea::LoadGame(const wxString& name)
emusys = &GBASystem;
}
if (config::OptGeomFullScreen()->GetInt()) {
if (config::Proxy<config::OptionID::kGeomFullScreen>().Get()) {
GameArea::ShowFullScreen(true);
}
@ -793,7 +794,7 @@ void GameArea::AdjustMinSize()
{
wxWindow* frame = wxGetApp().frame;
double dpi_scale_factor = widgets::DPIScaleFactorForWindow(this);
double display_scale = config::OptDispScale()->GetDouble();
double display_scale = config::Proxy<config::OptionID::kDispScale>().Get();
// note: could safely set min size to 1x or less regardless of video_scale
// but setting it to scaled size makes resizing to default easier
@ -829,7 +830,7 @@ void GameArea::AdjustSize(bool force)
return;
double dpi_scale_factor = widgets::DPIScaleFactorForWindow(this);
double display_scale = config::OptDispScale()->GetDouble();
double display_scale = config::Proxy<config::OptionID::kDispScale>().Get();
const wxSize newsz(
(std::ceil(basic_width * display_scale) * dpi_scale_factor),
@ -1095,7 +1096,7 @@ void GameArea::OnIdle(wxIdleEvent& event)
return;
if (!panel) {
switch (config::OptDispRenderMethod()->GetRenderMethod()) {
switch (config::Proxy<config::OptionID::kDispRenderMethod>().Get()) {
case config::RenderMethod::kSimple:
panel = new BasicDrawingPanel(this, basic_width, basic_height);
break;
@ -1411,9 +1412,9 @@ DrawingPanelBase::DrawingPanelBase(int _width, int _height)
rpi_(nullptr) {
memset(delta, 0xff, sizeof(delta));
if (config::OptDispFilter()->GetFilter() == config::Filter::kPlugin) {
if (config::Proxy<config::OptionID::kDispFilter>().Get() == config::Filter::kPlugin) {
rpi_ = widgets::MaybeLoadFilterPlugin(
config::OptDispFilterPlugin()->GetString(), &filter_plugin_);
config::Proxy<config::OptionID::kDispFilterPlugin>().Get(), &filter_plugin_);
if (rpi_) {
rpi_->Flags &= ~RPI_565_SUPP;
@ -1433,13 +1434,13 @@ DrawingPanelBase::DrawingPanelBase(int _width, int _height)
scale *= (rpi_->Flags & RPI_OUT_SCLMSK) >> RPI_OUT_SCLSH;
} else {
// This is going to delete the object. Do nothing more here.
config::OptDispFilterPlugin()->SetString(wxEmptyString);
config::OptDispFilter()->SetFilter(config::Filter::kNone);
config::Proxy<config::OptionID::kDispFilterPlugin>().Set(wxEmptyString);
config::Proxy<config::OptionID::kDispFilter>().Set(config::Filter::kNone);
return;
}
}
if (config::OptDispFilter()->GetFilter() != config::Filter::kPlugin) {
if (config::Proxy<config::OptionID::kDispFilter>().Get() != config::Filter::kPlugin) {
scale *= GetFilterScale();
systemColorDepth = 32;
}
@ -1558,7 +1559,7 @@ public:
delta_ += instride * procy;
// FIXME: fugly hack
if (config::OptDispRenderMethod()->GetRenderMethod() ==
if (config::Proxy<config::OptionID::kDispRenderMethod>().Get() ==
config::RenderMethod::kOpenGL) {
dst_ += (int)std::ceil(outstride * (procy + 1) * scale_);
} else {
@ -1578,7 +1579,7 @@ public:
// added procy param to provide offset into accum buffers
ApplyInterframe(instride, procy);
if (config::OptDispFilter()->GetFilter() == config::Filter::kNone) {
if (config::Proxy<config::OptionID::kDispFilter>().Get() == config::Filter::kNone) {
if (nthreads_ == 1)
return 0;
@ -1607,7 +1608,7 @@ private:
// definitely not thread safe by default
// added procy param to provide offset into accum buffers
void ApplyInterframe(int instride, int procy) {
switch (config::OptDispIFB()->GetInterframe()) {
switch (config::Proxy<config::OptionID::kDispIFB>().Get()) {
case config::Interframe::kNone:
break;
@ -1635,7 +1636,7 @@ private:
// naturally, any of these with accumulation buffers like those
// of the IFB filters will screw up royally as well
void ApplyFilter(int instride, int outstride) {
switch (config::OptDispFilter()->GetFilter()) {
switch (config::Proxy<config::OptionID::kDispFilter>().Get()) {
case config::Filter::k2xsai:
_2xSaI32(src_, instride, delta_, dst_, outstride, width_,
height_);
@ -1797,7 +1798,7 @@ void DrawingPanelBase::DrawArea(uint8_t** data)
pixbuf2 = (uint8_t*)calloc(allocstride, std::ceil((alloch + 2) * scale));
}
if (config::OptDispFilter()->GetFilter() == config::Filter::kNone) {
if (config::Proxy<config::OptionID::kDispFilter>().Get() == config::Filter::kNone) {
todraw = *data;
// *data is assigned below, after old buf has been processed
pixbuf1 = pixbuf2;
@ -1810,8 +1811,8 @@ void DrawingPanelBase::DrawArea(uint8_t** data)
// First, apply filters, if applicable, in parallel, if enabled
// FIXME: && (gopts.ifb != FF_MOTION_BLUR || !renderer_can_motion_blur)
if (config::OptDispFilter()->GetFilter() != config::Filter::kNone ||
config::OptDispIFB()->GetInterframe() != config::Interframe::kNone) {
if (config::Proxy<config::OptionID::kDispFilter>().Get() != config::Filter::kNone ||
config::Proxy<config::OptionID::kDispIFB>().Get() != config::Interframe::kNone) {
if (nthreads != gopts.max_threads) {
if (nthreads) {
if (nthreads > 1)
@ -1883,7 +1884,7 @@ void DrawingPanelBase::DrawArea(uint8_t** data)
}
// swap buffers now that src has been processed
if (config::OptDispFilter()->GetFilter() == config::Filter::kNone) {
if (config::Proxy<config::OptionID::kDispFilter>().Get() == config::Filter::kNone) {
*data = pixbuf1;
}
@ -2069,8 +2070,8 @@ BasicDrawingPanel::BasicDrawingPanel(wxWindow* parent, int _width, int _height)
{
// wxImage is 24-bit RGB, so 24-bit is preferred. Filters require
// 16 or 32, though
if (config::OptDispFilter()->GetFilter() == config::Filter::kNone &&
config::OptDispIFB()->GetInterframe() == config::Interframe::kNone) {
if (config::Proxy<config::OptionID::kDispFilter>().Get() == config::Filter::kNone &&
config::Proxy<config::OptionID::kDispIFB>().Get() == config::Interframe::kNone) {
// changing from 32 to 24 does not require regenerating color tables
systemColorDepth = 32;
}
@ -2101,7 +2102,7 @@ void BasicDrawingPanel::DrawArea(wxWindowDC& dc)
src += 2; // skip rhs border
}
} else if (config::OptDispFilter()->GetFilter() != config::Filter::kNone) {
} else if (config::Proxy<config::OptionID::kDispFilter>().Get() != config::Filter::kNone) {
// scaled by filters, top/right borders, transform to 24-bit
im = new wxImage(std::ceil(width * scale), std::ceil(height * scale), false);
uint32_t* src = (uint32_t*)todraw + (int)std::ceil(width * scale) + 1; // skip top border

View File

@ -30,10 +30,11 @@
// The built-in vba-over.ini
#include "builtin-over.h"
#include "config/game-control.h"
#include "config/option-proxy.h"
#include "config/option.h"
#include "config/user-input.h"
#include "strutils.h"
#include "config/game-control.h"
#include "config/option.h"
#include "wayland.h"
#ifdef __WXMSW__
@ -361,7 +362,7 @@ bool wxvbamApp::OnInit() {
// wxGLCanvas segfaults under wayland before wx 3.2
#if defined(HAVE_WAYLAND_SUPPORT) && !defined(HAVE_WAYLAND_EGL)
if (UsingWayland()) {
config::OptDispRenderMethod()->SetRenderMethod(
config::Proxy<config::OptionID::kDispRenderMethod>().Set(
config::RenderMethod::kSimple);
}
#endif
@ -471,12 +472,14 @@ bool wxvbamApp::OnInit() {
config::GameControlState::Instance().OnGameBindingsChanged();
// create the main window
int x = config::OptGeomWindowX()->GetInt();
int y = config::OptGeomWindowY()->GetInt();
int width = config::OptGeomWindowWidth()->GetUnsigned();
int height = config::OptGeomWindowHeight()->GetUnsigned();
bool isFullscreen = config::OptGeomFullScreen()->GetInt();
bool isMaximized = config::OptGeomIsMaximized()->GetBool();
int x = config::Proxy<config::OptionID::kGeomWindowX>().Get();
int y = config::Proxy<config::OptionID::kGeomWindowY>().Get();
int width = config::Proxy<config::OptionID::kGeomWindowHeight>().Get();
int height = config::Proxy<config::OptionID::kGeomWindowHeight>().Get();
bool isFullscreen =
config::Proxy<config::OptionID::kGeomFullScreen>().Get();
bool isMaximized =
config::Proxy<config::OptionID::kGeomIsMaximized>().Get();
frame = wxDynamicCast(xr->LoadFrame(nullptr, "MainFrame"), MainFrame);
if (!frame) {
@ -839,8 +842,8 @@ void MainFrame::OnMove(wxMoveEvent&) {
if (!IsFullScreen() && !IsMaximized()) {
if (window_pos.x >= 0 && window_pos.y >= 0) {
config::OptGeomWindowX()->SetInt(window_pos.x);
config::OptGeomWindowY()->SetInt(window_pos.y);
config::Proxy<config::OptionID::kGeomWindowX>().Set(window_pos.x);
config::Proxy<config::OptionID::kGeomWindowY>().Set(window_pos.y);
}
}
}
@ -850,22 +853,24 @@ void MainFrame::OnSize(wxSizeEvent& event)
wxFrame::OnSize(event);
wxRect window_rect = GetRect();
wxPoint window_pos = GetScreenPosition();
config::Option* window_x = config::OptGeomWindowX();
config::Option* window_y = config::OptGeomWindowY();
config::Proxy<config::OptionID::kGeomWindowX> window_x;
config::Proxy<config::OptionID::kGeomWindowY> window_y;
if (!IsFullScreen() && !IsMaximized()) {
if (window_rect.GetHeight() > 0 && window_rect.GetWidth() > 0) {
config::OptGeomWindowHeight()->SetUnsigned(window_rect.GetHeight());
config::OptGeomWindowWidth()->SetUnsigned(window_rect.GetWidth());
config::Proxy<config::OptionID::kGeomWindowHeight>().Set(
window_rect.GetHeight());
config::Proxy<config::OptionID::kGeomWindowWidth>().Set(
window_rect.GetWidth());
}
if (window_pos.x >= 0 && window_pos.y >= 0) {
window_x->SetInt(window_pos.x);
window_y->SetInt(window_pos.y);
window_x.Set(window_pos.x);
window_y.Set(window_pos.y);
}
}
config::OptGeomIsMaximized()->SetBool(IsMaximized());
config::OptGeomFullScreen()->SetInt(IsFullScreen());
config::Proxy<config::OptionID::kGeomIsMaximized>().Set(IsMaximized());
config::Proxy<config::OptionID::kGeomFullScreen>().Set(IsFullScreen());
}
int MainFrame::FilterEvent(wxEvent& event)