From a8ec85d53690978765fcd38824a4be03874f8eba Mon Sep 17 00:00:00 2001 From: Fabrice de Gans Date: Sun, 24 Nov 2024 12:15:26 -0800 Subject: [PATCH] [GB] Add support for per-game overrides (#1370) * [GB] Add support for per-game overrides Alleyway is a buggy game that does not work properly when a Game Boy Printer is connected. In order to work around this issue, this adds upport for built-in per-software Game Boy overrides. In addition, this renames various variables to make their meaning clearer. * This only supports built-in overrides. External INI files are not supported. * Only the Game Boy Printer option is supported, this only takes effect on game startup and the general configuration option is restored when the game is unloaded. * As a result, it is possible to override the per-game override by manually setting the option while the game is running, this is working as intended. * Future refactors of the option handling will manage overrides better. * Switch `gbPrinterEnabled` default to off. Fixes #1368 --- src/core/base/system.h | 2 +- src/core/gb/gb.cpp | 2 +- src/gb-over.ini | 4 ++++ src/libretro/libretro.cpp | 2 +- src/sdl/ConfigManager.cpp | 6 ++--- src/wx/CMakeLists.txt | 7 ++++++ src/wx/cmdevents.cpp | 8 +++---- src/wx/config/internal/option-internal.cpp | 2 +- src/wx/panel.cpp | 16 +++++++++++-- src/wx/wxvbam.cpp | 26 +++++++++++++--------- src/wx/wxvbam.h | 9 +++++--- 11 files changed, 57 insertions(+), 27 deletions(-) create mode 100644 src/gb-over.ini diff --git a/src/core/base/system.h b/src/core/base/system.h index c5a3440e..fa4b2762 100644 --- a/src/core/base/system.h +++ b/src/core/base/system.h @@ -70,7 +70,7 @@ extern struct CoreOptions { int skipSaveGameBattery = 1; int skipSaveGameCheats = 0; int useBios = 0; - int winGbPrinterEnabled = 1; + int gbPrinterEnabled = 0; uint32_t speedup_throttle = 100; uint32_t speedup_frame_skip = 9; uint32_t throttle = 100; diff --git a/src/core/gb/gb.cpp b/src/core/gb/gb.cpp index ccbaa6e9..d7e91459 100644 --- a/src/core/gb/gb.cpp +++ b/src/core/gb/gb.cpp @@ -1416,7 +1416,7 @@ void gbWriteMemory(uint16_t address, uint8_t value) EmuReseted = false; gbMemory[0xff02] = value; if (gbSerialOn && (GetLinkMode() == LINK_GAMEBOY_IPC || GetLinkMode() == LINK_GAMEBOY_SOCKET - || GetLinkMode() == LINK_DISCONNECTED || coreOptions.winGbPrinterEnabled)) { + || GetLinkMode() == LINK_DISCONNECTED || coreOptions.gbPrinterEnabled)) { gbSerialTicks = GBSERIAL_CLOCK_TICKS; diff --git a/src/gb-over.ini b/src/gb-over.ini new file mode 100644 index 00000000..69f70820 --- /dev/null +++ b/src/gb-over.ini @@ -0,0 +1,4 @@ +# Game Boy Overrrides + +[ALLEY WAY] +gbPrinter = 0 diff --git a/src/libretro/libretro.cpp b/src/libretro/libretro.cpp index 6fefd82c..c8411ffc 100644 --- a/src/libretro/libretro.cpp +++ b/src/libretro/libretro.cpp @@ -590,7 +590,7 @@ void retro_init(void) coreOptions.parseDebug = true; coreOptions.cheatsEnabled = 0; coreOptions.skipSaveGameBattery = 0; - coreOptions.winGbPrinterEnabled = 0; + coreOptions.gbPrinterEnabled = 0; struct retro_log_callback log; struct retro_rumble_interface rumble; diff --git a/src/sdl/ConfigManager.cpp b/src/sdl/ConfigManager.cpp index 74841161..a4374a3d 100644 --- a/src/sdl/ConfigManager.cpp +++ b/src/sdl/ConfigManager.cpp @@ -189,7 +189,7 @@ struct option argOptions[] = { { "gb-emulator-type", required_argument, 0, OPT_GB_EMULATOR_TYPE }, { "gb-frame-skip", required_argument, 0, OPT_GB_FRAME_SKIP }, { "gb-palette-option", required_argument, 0, OPT_GB_PALETTE_OPTION }, - { "gb-printer", no_argument, &coreOptions.winGbPrinterEnabled, 1 }, + { "gb-printer", no_argument, &coreOptions.gbPrinterEnabled, 1 }, { "gdb", required_argument, 0, 'G' }, { "help", no_argument, &optPrintUsage, 1 }, { "ifb-filter", required_argument, 0, 'I' }, @@ -236,7 +236,7 @@ struct option argOptions[] = { { "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 }, + { "win-gb-printer-enabled", no_argument, &coreOptions.gbPrinterEnabled, 1 }, { NULL, no_argument, NULL, 0 } @@ -351,7 +351,7 @@ void LoadConfig() coreOptions.speedup_throttle_frame_skip = ReadPref("speedupThrottleFrameSkip", 0); coreOptions.speedup_mute = ReadPref("speedupMute", 1); coreOptions.useBios = ReadPrefHex("useBiosGBA"); - coreOptions.winGbPrinterEnabled = ReadPref("gbPrinter", 0); + coreOptions.gbPrinterEnabled = ReadPref("gbPrinter", 0); int soundQuality = (ReadPrefHex("soundQuality", 1)); switch (soundQuality) { diff --git a/src/wx/CMakeLists.txt b/src/wx/CMakeLists.txt index 1913f995..f549ccdf 100644 --- a/src/wx/CMakeLists.txt +++ b/src/wx/CMakeLists.txt @@ -59,6 +59,7 @@ set(VBAM_WX_COMMON ${VBAM_GENERATED_DIR}/wx/builtin-over.h ${VBAM_GENERATED_DIR}/wx/cmdhandlers.h ${VBAM_GENERATED_DIR}/wx/cmd-evtable.h + ${VBAM_GENERATED_DIR}/wx/gb-builtin-over.h ) if(NOT ZIP_PROGRAM) @@ -642,6 +643,12 @@ add_custom_command( DEPENDS ${CMAKE_SOURCE_DIR}/src/vba-over.ini ${BIN2C} ) +add_custom_command( + OUTPUT ${VBAM_GENERATED_DIR}/wx/gb-builtin-over.h + COMMAND ${BIN2C} ${CMAKE_SOURCE_DIR}/src/gb-over.ini ${VBAM_GENERATED_DIR}/wx/gb-builtin-over.h gb_builtin_over + DEPENDS ${CMAKE_SOURCE_DIR}/src/gb-over.ini ${BIN2C} +) + set(VBAM_LOCALIZABLE_FILES ${VBAM_WX_COMMON} ${VBAM_LOCALIZABLE_WX_CONFIG_FILES}) list(APPEND VBAM_LOCALIZABLE_FILES audio/internal/dsound.cpp diff --git a/src/wx/cmdevents.cpp b/src/wx/cmdevents.cpp index 36f69d01..907f485d 100644 --- a/src/wx/cmdevents.cpp +++ b/src/wx/cmdevents.cpp @@ -1990,7 +1990,7 @@ EVT_HANDLER(GameBoyAdvanceConfigure, "Game Boy Advance options...") XRCCTRL(*dlg, "GameCode", wxControl) ->SetLabel(s); cmt = wxString((const char*)&g_rom[0xa0], wxConvLibc, 12); - wxFileConfig* cfg = wxGetApp().overrides; + wxFileConfig* cfg = wxGetApp().overrides_.get(); if (cfg->HasGroup(s)) { cfg->SetPath(s); @@ -2024,7 +2024,7 @@ EVT_HANDLER(GameBoyAdvanceConfigure, "Game Boy Advance options...") if (panel->game_type() == IMAGE_GBA) { agbPrintEnable(OPTION(kPrefAgbPrint)); wxString s = wxString((const char*)&g_rom[0xac], wxConvLibc, 4); - wxFileConfig* cfg = wxGetApp().overrides; + wxFileConfig* cfg = wxGetApp().overrides_.get(); bool chg; if (cfg->HasGroup(s)) { @@ -2297,7 +2297,7 @@ EVT_HANDLER(RetainAspect, "Retain aspect ratio when resizing") EVT_HANDLER(Printer, "Enable printer emulation") { - GetMenuOptionInt("Printer", &coreOptions.winGbPrinterEnabled, 1); + GetMenuOptionInt("Printer", &coreOptions.gbPrinterEnabled, 1); #if (defined __WIN32__ || defined _WIN32) #ifndef NO_LINK gbSerialFunction = gbStartLink; @@ -2305,7 +2305,7 @@ EVT_HANDLER(Printer, "Enable printer emulation") gbSerialFunction = NULL; #endif #endif - if (coreOptions.winGbPrinterEnabled) + if (coreOptions.gbPrinterEnabled) gbSerialFunction = gbPrinterSend; update_opts(); diff --git a/src/wx/config/internal/option-internal.cpp b/src/wx/config/internal/option-internal.cpp index f5fd9b88..24774beb 100644 --- a/src/wx/config/internal/option-internal.cpp +++ b/src/wx/config/internal/option-internal.cpp @@ -312,7 +312,7 @@ std::array& Option::All() { Option(OptionID::kPrefFlashSize, &g_owned_opts.flash_size, 0, 1), Option(OptionID::kPrefFrameSkip, &g_owned_opts.frame_skip, -1, 9), Option(OptionID::kPrefGBPaletteOption, &gbPaletteOption, 0, 2), - Option(OptionID::kPrefGBPrinter, &coreOptions.winGbPrinterEnabled, 0, 1), + Option(OptionID::kPrefGBPrinter, &coreOptions.gbPrinterEnabled, 0, 1), Option(OptionID::kPrefGDBBreakOnLoad, &g_owned_opts.gdb_break_on_load), Option(OptionID::kPrefGDBPort, &gopts.gdb_port, 0, 65535), #ifndef NO_LINK diff --git a/src/wx/panel.cpp b/src/wx/panel.cpp index a14a21fb..46e5409c 100644 --- a/src/wx/panel.cpp +++ b/src/wx/panel.cpp @@ -287,6 +287,15 @@ void GameArea::LoadGame(const wxString& name) gbApplyPatch(UTF8(pfn.GetFullPath())); } + // Apply overrides. + wxFileConfig* cfg = wxGetApp().gb_overrides_.get(); + const std::string& title = g_gbCartData.title(); + if (cfg->HasGroup(title)) { + cfg->SetPath(title); + coreOptions.gbPrinterEnabled = cfg->Read("gbPrinter", coreOptions.gbPrinterEnabled); + cfg->SetPath("/"); + } + // start sound; this must happen before CPU stuff gb_effects_config.enabled = OPTION(kSoundGBEnableEffects); gb_effects_config.surround = OPTION(kSoundGBSurround); @@ -359,7 +368,7 @@ void GameArea::LoadGame(const wxString& name) gbaUpdateRomSize(size); } - wxFileConfig* cfg = wxGetApp().overrides; + wxFileConfig* cfg = wxGetApp().overrides_.get(); wxString id = wxString((const char*)&g_rom[0xac], wxConvLibc, 4); if (cfg->HasGroup(id)) { @@ -456,7 +465,7 @@ void GameArea::LoadGame(const wxString& name) SuspendScreenSaver(); // probably only need to do this for GB carts - if (coreOptions.winGbPrinterEnabled) + if (coreOptions.gbPrinterEnabled) gbSerialFunction = gbPrinterSend; // probably only need to do this for GBA carts @@ -666,6 +675,9 @@ void GameArea::UnloadGame(bool destruct) if (loaded == IMAGE_GB) { gbCleanUp(); gbCheatRemoveAll(); + + // Reset overrides. + coreOptions.gbPrinterEnabled = OPTION(kPrefGBPrinter); } else if (loaded == IMAGE_GBA) { CPUCleanUp(); cheatsDeleteAll(false); diff --git a/src/wx/wxvbam.cpp b/src/wx/wxvbam.cpp index 3e55f2be..c4fc28ed 100644 --- a/src/wx/wxvbam.cpp +++ b/src/wx/wxvbam.cpp @@ -31,6 +31,7 @@ #include "components/user_config/user_config.h" #include "core/gba/gbaSound.h" +#include "wx/gb-builtin-over.h" #include "wx/builtin-over.h" #include "wx/builtin-xrc.h" #include "wx/config/cmdtab.h" @@ -470,13 +471,17 @@ bool wxvbamApp::OnInit() { } } + // load gb-over.ini + wxMemoryInputStream stream(gb_builtin_over, sizeof(gb_builtin_over)); + gb_overrides_ = std::make_unique(stream); + // load vba-over.ini // rather than dealing with wxConfig's broken search path, just use // the same one that the xrc overrides use // this also allows us to override a group at a time, add commments, and // add the file from which the group came wxMemoryInputStream mis(builtin_over, sizeof(builtin_over)); - overrides = new wxFileConfig(mis); + overrides_ = std::make_unique(mis); wxRegEx cmtre; // not the most efficient thing to do: read entire file into a string // just to parse the comments out @@ -486,8 +491,8 @@ bool wxvbamApp::OnInit() { long grp_idx; #define CMT_RE_START wxT("(^|[\n\r])# ?([^\n\r]*)(\r?\n|\r)\\[") - for (cont = overrides->GetFirstGroup(s, grp_idx); cont; - cont = overrides->GetNextGroup(s, grp_idx)) { + for (cont = overrides_->GetFirstGroup(s, grp_idx); cont; + cont = overrides_->GetNextGroup(s, grp_idx)) { // apparently even MacOSX sometimes uses the old \r by itself wxString cmt(CMT_RE_START); cmt += s + wxT("\\]"); @@ -497,7 +502,7 @@ bool wxvbamApp::OnInit() { else cmt = wxEmptyString; - overrides->Write(s + wxT("/comment"), cmt); + overrides_->Write(s + wxT("/comment"), cmt); } if (vba_over.FileExists()) { @@ -513,10 +518,10 @@ bool wxvbamApp::OnInit() { for (cont = ov.GetFirstGroup(s, grp_idx); cont; cont = ov.GetNextGroup(s, grp_idx)) { - overrides->DeleteGroup(s); - overrides->SetPath(s); + overrides_->DeleteGroup(s); + overrides_->SetPath(s); ov.SetPath(s); - overrides->Write(wxT("path"), GetConfigurationPath()); + overrides_->Write(wxT("path"), GetConfigurationPath()); // apparently even MacOSX sometimes uses \r by itself wxString cmt(CMT_RE_START); cmt += s + wxT("\\]"); @@ -526,15 +531,15 @@ bool wxvbamApp::OnInit() { else cmt = wxEmptyString; - overrides->Write(wxT("comment"), cmt); + overrides_->Write(wxT("comment"), cmt); long ent_idx; for (cont = ov.GetFirstEntry(s, ent_idx); cont; cont = ov.GetNextEntry(s, ent_idx)) - overrides->Write(s, ov.Read(s, wxEmptyString)); + overrides_->Write(s, ov.Read(s, wxEmptyString)); ov.SetPath(wxT("/")); - overrides->SetPath(wxT("/")); + overrides_->SetPath(wxT("/")); } } @@ -822,7 +827,6 @@ wxvbamApp::~wxvbamApp() { free(home); home = NULL; } - delete overrides; #ifndef NO_ONLINEUPDATES shutdownAutoupdater(); diff --git a/src/wx/wxvbam.h b/src/wx/wxvbam.h index 93c35e57..be39204c 100644 --- a/src/wx/wxvbam.h +++ b/src/wx/wxvbam.h @@ -1,11 +1,13 @@ #ifndef VBAM_WX_WXVBAM_H_ #define VBAM_WX_WXVBAM_H_ +#include +#include #include +#include #include #include -#include -#include + #include #include #include @@ -106,7 +108,8 @@ public: widgets::SdlPoller* sdl_poller() { return &sdl_poller_; } // vba-over.ini - wxFileConfig* overrides = nullptr; + std::unique_ptr overrides_; + std::unique_ptr gb_overrides_; wxFileName rom_database; wxFileName rom_database_scene;