Move directory options to g_owned_opts

* Moves most directory settings to g_owned_opts.
* Converts the DirectoriesConfig dialog to the new structure.
* Various includes clean-ups.

Breaking change: Loading a GB/GBC/GBA ROM when the ROM directory setting
is unset for that platform will now populate the per-platform ROM
directory setting.
This commit is contained in:
Fabrice de Gans 2023-04-04 15:51:35 -07:00 committed by Fabrice de Gans
parent 019fcda9c1
commit 928a61704f
14 changed files with 477 additions and 377 deletions

File diff suppressed because it is too large Load Diff

View File

@ -765,6 +765,7 @@ set(
config/option-observer.cpp
config/option.cpp
config/user-input.cpp
dialogs/directories-config.cpp
dialogs/display-config.cpp
dialogs/game-boy-config.cpp
widgets/group-check-box.cpp
@ -813,6 +814,7 @@ set(
config/option-proxy.h
config/option.h
config/user-input.h
dialogs/directories-config.h
dialogs/display-config.h
dialogs/game-boy-config.h
dialogs/validated-child.h

View File

@ -124,12 +124,11 @@ static void toggleBitVar(bool *menuValue, int *globalVar, int mask)
//// File menu
static int open_ft = 0;
static wxString open_dir;
EVT_HANDLER(wxID_OPEN, "Open ROM...")
{
open_dir = wxGetApp().GetAbsolutePath(gopts.gba_rom_dir);
static int open_ft = 0;
const wxString& gba_rom_dir = OPTION(kGBAROMDir);
// FIXME: ignore if non-existent or not a dir
wxString pats = _(
"Game Boy Advance Files (*.agb;*.gba;*.bin;*.elf;*.mb;*.zip;*.7z;*.rar)|"
@ -143,7 +142,7 @@ EVT_HANDLER(wxID_OPEN, "Open ROM...")
"*.dmg.z;*.gb.z;*.gbc.z;*.cgb.z;*.sgb.z;"
"*.zip;*.7z;*.rar|");
pats.append(wxALL_FILES);
wxFileDialog dlg(this, _("Open ROM file"), open_dir, wxT(""),
wxFileDialog dlg(this, _("Open ROM file"), gba_rom_dir, "",
pats,
wxFD_OPEN | wxFD_FILE_MUST_EXIST);
dlg.SetFilterIndex(open_ft);
@ -152,12 +151,16 @@ EVT_HANDLER(wxID_OPEN, "Open ROM...")
wxGetApp().pending_load = dlg.GetPath();
open_ft = dlg.GetFilterIndex();
open_dir = dlg.GetDirectory();
if (gba_rom_dir.empty()) {
OPTION(kGBAROMDir) = dlg.GetDirectory();
}
}
EVT_HANDLER(OpenGB, "Open GB...")
{
open_dir = wxGetApp().GetAbsolutePath(gopts.gb_rom_dir);
static int open_ft = 0;
const wxString& gb_rom_dir = OPTION(kGBROMDir);
// FIXME: ignore if non-existent or not a dir
wxString pats = _(
"Game Boy Files (*.dmg;*.gb;*.gbc;*.cgb;*.sgb;*.zip;*.7z;*.rar)|"
@ -166,7 +169,7 @@ EVT_HANDLER(OpenGB, "Open GB...")
"*.dmg.z;*.gb.z;*.gbc.z;*.cgb.z;*.sgb.z;"
"*.zip;*.7z;*.rar|");
pats.append(wxALL_FILES);
wxFileDialog dlg(this, _("Open GB ROM file"), open_dir, wxT(""),
wxFileDialog dlg(this, _("Open GB ROM file"), gb_rom_dir, "",
pats,
wxFD_OPEN | wxFD_FILE_MUST_EXIST);
dlg.SetFilterIndex(open_ft);
@ -175,12 +178,16 @@ EVT_HANDLER(OpenGB, "Open GB...")
wxGetApp().pending_load = dlg.GetPath();
open_ft = dlg.GetFilterIndex();
open_dir = dlg.GetDirectory();
if (gb_rom_dir.empty()) {
OPTION(kGBROMDir) = dlg.GetDirectory();
}
}
EVT_HANDLER(OpenGBC, "Open GBC...")
{
open_dir = wxGetApp().GetAbsolutePath(gopts.gbc_rom_dir);
static int open_ft = 0;
const wxString& gbc_rom_dir = OPTION(kGBGBCROMDir);
// FIXME: ignore if non-existent or not a dir
wxString pats = _(
"Game Boy Color Files (*.dmg;*.gb;*.gbc;*.cgb;*.sgb;*.zip;*.7z;*.rar)|"
@ -189,7 +196,7 @@ EVT_HANDLER(OpenGBC, "Open GBC...")
"*.dmg.z;*.gb.z;*.gbc.z;*.cgb.z;*.sgb.z;"
"*.zip;*.7z;*.rar|");
pats.append(wxALL_FILES);
wxFileDialog dlg(this, _("Open GBC ROM file"), open_dir, wxT(""),
wxFileDialog dlg(this, _("Open GBC ROM file"), gbc_rom_dir, "",
pats,
wxFD_OPEN | wxFD_FILE_MUST_EXIST);
dlg.SetFilterIndex(open_ft);
@ -198,7 +205,9 @@ EVT_HANDLER(OpenGBC, "Open GBC...")
wxGetApp().pending_load = dlg.GetPath();
open_ft = dlg.GetFilterIndex();
open_dir = dlg.GetDirectory();
if (gbc_rom_dir.empty()) {
OPTION(kGBGBCROMDir) = dlg.GetDirectory();
}
}
EVT_HANDLER(RecentReset, "Reset recent ROM list")
@ -1174,7 +1183,7 @@ EVT_HANDLER_MASK(ExportGamesharkSnapshot, "Export GameShark snapshot...", CMDEN_
EVT_HANDLER_MASK(ScreenCapture, "Screen capture...", CMDEN_GB | CMDEN_GBA)
{
wxString scap_path = GetGamePath(gopts.scrshot_dir);
wxString scap_path = GetGamePath(OPTION(kGenScreenshotDir));
wxString def_name = panel->game_name();
const int capture_format = OPTION(kPrefCaptureFormat);
@ -1250,7 +1259,7 @@ EVT_HANDLER_MASK(RecordSoundStartRecording, "Start sound recording...", CMDEN_NS
sound_extno = extno;
}
sound_path = GetGamePath(gopts.recording_dir);
sound_path = GetGamePath(OPTION(kGenRecordingDir));
wxString def_name = panel->game_name();
wxString extoff = sound_exts;
@ -1320,7 +1329,7 @@ EVT_HANDLER_MASK(RecordAVIStartRecording, "Start video recording...", CMDEN_NVRE
vid_extno = extno;
}
vid_path = GetGamePath(gopts.recording_dir);
vid_path = GetGamePath(OPTION(kGenRecordingDir));
wxString def_name = panel->game_name();
wxString extoff = vid_exts;
@ -1391,7 +1400,7 @@ EVT_HANDLER_MASK(RecordMovieStartRecording, "Start game recording...", CMDEN_NGR
mov_extno = extno;
}
mov_path = GetGamePath(gopts.recording_dir);
mov_path = GetGamePath(OPTION(kGenRecordingDir));
wxString def_name = panel->game_name();
wxString extoff = mov_exts;
@ -1457,7 +1466,7 @@ EVT_HANDLER_MASK(PlayMovieStartPlaying, "Start playing movie...", CMDEN_NGREC |
mov_extno = extno;
}
mov_path = GetGamePath(gopts.recording_dir);
mov_path = GetGamePath(OPTION(kGenRecordingDir));
systemStopGamePlayback();
wxString def_name = panel->game_name();
wxString extoff = mov_exts;
@ -2747,10 +2756,7 @@ EVT_HANDLER_MASK(SoundConfigure, "Sound options...", CMDEN_NREC_ANY)
EVT_HANDLER(EmulatorDirectories, "Directories...")
{
wxDialog* dlg = GetXRCDialog("DirectoriesConfig");
if (ShowModal(dlg) == wxID_OK)
update_opts();
ShowModal(GetXRCDialog("DirectoriesConfig"));
}
EVT_HANDLER(JoypadConfigure, "Joypad options...")

View File

@ -4,10 +4,11 @@
// separately. These should not be updated very often, so having these in a
// separate file improves incremental build time.
#include <wx/log.h>
#include <algorithm>
#include <limits>
#include <wx/log.h>
#include "../System.h"
#include "../gb/gbGlobals.h"
#include "opts.h"
@ -165,6 +166,11 @@ std::array<Option, kNbOptions>& Option::All() {
wxString gb_bios = wxEmptyString;
bool colorizer_hack = false;
wxString gbc_bios = wxEmptyString;
wxString gb_rom_dir = wxEmptyString;
wxString gbc_rom_dir = wxEmptyString;
/// GBA
wxString gba_rom_dir;
/// Core
bool agb_print = false;
@ -179,6 +185,10 @@ std::array<Option, kNbOptions>& Option::All() {
bool show_speed_transparent = false;
/// General
wxString battery_dir = wxEmptyString;
wxString recording_dir = wxEmptyString;
wxString screenshot_dir = wxEmptyString;
wxString state_dir = wxEmptyString;
uint32_t ini_version = kIniLatestVersion;
/// Geometry
@ -224,8 +234,8 @@ std::array<Option, kNbOptions>& Option::All() {
Option(OptionID::kGBPalette2, systemGbPalette + 16),
Option(OptionID::kGBPrintAutoPage, &gopts.print_auto_page),
Option(OptionID::kGBPrintScreenCap, &gopts.print_screen_cap),
Option(OptionID::kGBROMDir, &gopts.gb_rom_dir),
Option(OptionID::kGBGBCROMDir, &gopts.gbc_rom_dir),
Option(OptionID::kGBROMDir, &g_owned_opts.gb_rom_dir),
Option(OptionID::kGBGBCROMDir, &g_owned_opts.gbc_rom_dir),
/// GBA
Option(OptionID::kGBABiosFile, &gopts.gba_bios),
@ -240,16 +250,16 @@ std::array<Option, kNbOptions>& Option::All() {
Option(OptionID::kGBALinkTimeout, &gopts.link_timeout, 0, 9999999),
Option(OptionID::kGBALinkType, &gopts.gba_link_type, 0, 5),
#endif
Option(OptionID::kGBAROMDir, &gopts.gba_rom_dir),
Option(OptionID::kGBAROMDir, &g_owned_opts.gba_rom_dir),
/// General
Option(OptionID::kGenAutoLoadLastState, &gopts.autoload_state),
Option(OptionID::kGenBatteryDir, &gopts.battery_dir),
Option(OptionID::kGenBatteryDir, &g_owned_opts.battery_dir),
Option(OptionID::kGenFreezeRecent, &gopts.recent_freeze),
Option(OptionID::kGenRecordingDir, &gopts.recording_dir),
Option(OptionID::kGenRecordingDir, &g_owned_opts.recording_dir),
Option(OptionID::kGenRewindInterval, &gopts.rewind_interval, 0, 600),
Option(OptionID::kGenScreenshotDir, &gopts.scrshot_dir),
Option(OptionID::kGenStateDir, &gopts.state_dir),
Option(OptionID::kGenScreenshotDir, &g_owned_opts.screenshot_dir),
Option(OptionID::kGenStateDir, &g_owned_opts.state_dir),
Option(OptionID::kGenStatusBar, &gopts.statusbar),
Option(OptionID::kGenIniVersion, &g_owned_opts.ini_version, 0, std::numeric_limits<uint32_t>::max()),

View File

@ -247,7 +247,7 @@ public:
bool Set(const wxString& value) { return option_->SetString(value); }
bool operator=(wxString value) { return Set(value); }
operator wxString() const { return Get(); }
operator const wxString&() const { return Get(); }
private:
Option* option_;

View File

@ -0,0 +1,88 @@
#include "dialogs/directories-config.h"
#include <wx/filepicker.h>
#include <wx/xrc/xmlres.h>
#include "dialogs/validated-child.h"
#include "widgets/option-validator.h"
namespace dialogs {
namespace {
// Custom validator for a kString Option and a wxDirPickerCtrl widget.
class DirectoryStringValidator final : public widgets::OptionValidator {
public:
DirectoryStringValidator(config::OptionID option_id)
: widgets::OptionValidator(option_id) {
assert(option()->is_string());
}
~DirectoryStringValidator() final = default;
private:
// widgets::OptionValidator implementation.
wxObject* Clone() const final {
return new DirectoryStringValidator(option()->id());
}
bool IsWindowValueValid() final { return true; }
bool WriteToWindow() final {
wxDirPickerCtrl* dir_picker =
wxDynamicCast(GetWindow(), wxDirPickerCtrl);
assert(dir_picker);
dir_picker->SetPath(option()->GetString());
return true;
}
bool WriteToOption() final {
const wxDirPickerCtrl* dir_picker =
wxDynamicCast(GetWindow(), wxDirPickerCtrl);
assert(dir_picker);
return option()->SetString(dir_picker->GetPath());
}
};
void SetUpDirPicker(wxDirPickerCtrl* dir_picker,
const config::OptionID& option_id) {
dir_picker->SetValidator(DirectoryStringValidator(option_id));
dir_picker->GetPickerCtrl()->SetLabel(_("Browse"));
}
} // namespace
// static
DirectoriesConfig* DirectoriesConfig::NewInstance(wxWindow* parent) {
assert(parent);
return new DirectoriesConfig(parent);
}
DirectoriesConfig::DirectoriesConfig(wxWindow* parent)
: wxDialog(), keep_on_top_styler_(this) {
#if !wxCHECK_VERSION(3, 1, 0)
// This needs to be set before loading any element on the window. This also
// has no effect since wx 3.1.0, where it became the default.
this->SetExtraStyle(wxWS_EX_VALIDATE_RECURSIVELY);
#endif
wxXmlResource::Get()->LoadDialog(this, parent, "DirectoriesConfig");
SetUpDirPicker(GetValidatedChild<wxDirPickerCtrl>(this, "GBARoms"),
config::OptionID::kGBAROMDir);
SetUpDirPicker(GetValidatedChild<wxDirPickerCtrl>(this, "GBRoms"),
config::OptionID::kGBROMDir);
SetUpDirPicker(GetValidatedChild<wxDirPickerCtrl>(this, "GBCRoms"),
config::OptionID::kGBGBCROMDir);
SetUpDirPicker(GetValidatedChild<wxDirPickerCtrl>(this, "BatSaves"),
config::OptionID::kGenBatteryDir);
SetUpDirPicker(GetValidatedChild<wxDirPickerCtrl>(this, "StateSaves"),
config::OptionID::kGenStateDir);
SetUpDirPicker(GetValidatedChild<wxDirPickerCtrl>(this, "Screenshots"),
config::OptionID::kGenScreenshotDir);
SetUpDirPicker(GetValidatedChild<wxDirPickerCtrl>(this, "Recordings"),
config::OptionID::kGenRecordingDir);
this->Fit();
}
} // namespace dialogs

View File

@ -0,0 +1,27 @@
#ifndef VBAM_WX_DIALOGS_DIRECTORIES_CONFIG_H_
#define VBAM_WX_DIALOGS_DIRECTORIES_CONFIG_H_
#include <wx/dialog.h>
#include "widgets/keep-on-top-styler.h"
namespace dialogs {
// Manages the directories configuration dialog.
class DirectoriesConfig : public wxDialog {
public:
static DirectoriesConfig* NewInstance(wxWindow* parent);
~DirectoriesConfig() override = default;
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.
DirectoriesConfig(wxWindow* parent);
const widgets::KeepOnTopStyler keep_on_top_styler_;
};
} // namespace dialogs
#endif // VBAM_WX_DIALOGS_DIRECTORIES_CONFIG_H_

View File

@ -18,7 +18,6 @@
#include "dialogs/validated-child.h"
#include "widgets/group-check-box.h"
#include "widgets/option-validator.h"
#include "wx/object.h"
namespace dialogs {

View File

@ -1588,7 +1588,7 @@ public:
{
(void)ev; // unused params
GameArea* panel = wxGetApp().frame->GetPanel();
wxString bmp_save_dir = wxGetApp().frame->GetGamePath(gopts.scrshot_dir);
wxString bmp_save_dir = wxGetApp().frame->GetGamePath(OPTION(kGenScreenshotDir));
// no attempt is made here to translate the dialog type name
// it's just a suggested name, anyway
wxString def_name = panel->game_name() + wxT('-') + dname;
@ -1731,7 +1731,7 @@ public:
{
(void)ev; // unused params
GameArea* panel = wxGetApp().frame->GetPanel();
wxString bmp_save_dir = wxGetApp().frame->GetGamePath(gopts.scrshot_dir);
wxString bmp_save_dir = wxGetApp().frame->GetGamePath(OPTION(kGenScreenshotDir));
// no attempt is made here to translate the dialog type name
// it's just a suggested name, anyway
wxString def_name = panel->game_name() + wxT('-') + dname;

View File

@ -28,6 +28,7 @@
#include "config/option-proxy.h"
#include "config/option.h"
#include "config/user-input.h"
#include "dialogs/directories-config.h"
#include "dialogs/display-config.h"
#include "dialogs/game-boy-config.h"
#include "opts.h"
@ -2418,12 +2419,6 @@ void MainFrame::BindAppIcon() {
SetIcon(icon);
}
static void setCustomLabelForFilePicker(wxDirPickerCtrl* dp)
{
wxButton *pButt = static_cast<wxButton*>(dp->GetPickerCtrl());
if (pButt) pButt->SetLabel(_("Browse"));
}
// If there is a menubar, store all special menuitems
#define XRCITEM_I(id) menubar->FindItem(id, NULL)
#define XRCITEM_D(s) XRCITEM_I(XRCID_D(s))
@ -3317,30 +3312,7 @@ bool MainFrame::BindControls()
getsl("GBASoundFiltering", gopts.gba_sound_filter);
d->Fit();
}
wxDirPickerCtrl* dp;
#define getdp(n, o) \
do { \
dp = SafeXRCCTRL<wxDirPickerCtrl>(d, n); \
dp->SetValidator(wxFileDirPickerValidator(&o)); \
} while (0)
d = LoadXRCDialog("DirectoriesConfig");
{
getdp("GBARoms", gopts.gba_rom_dir);
setCustomLabelForFilePicker(dp);
getdp("GBRoms", gopts.gb_rom_dir);
setCustomLabelForFilePicker(dp);
getdp("GBCRoms", gopts.gbc_rom_dir);
setCustomLabelForFilePicker(dp);
getdp("BatSaves", gopts.battery_dir);
setCustomLabelForFilePicker(dp);
getdp("StateSaves", gopts.state_dir);
setCustomLabelForFilePicker(dp);
getdp("Screenshots", gopts.scrshot_dir);
setCustomLabelForFilePicker(dp);
getdp("Recordings", gopts.recording_dir);
setCustomLabelForFilePicker(dp);
d->Fit();
}
dialogs::DirectoriesConfig::NewInstance(this);
wxDialog* joyDialog = LoadXRCropertySheetDialog("JoypadConfig");
for (int i = 0; i < 4; i++) {

View File

@ -29,8 +29,6 @@ extern struct opts_t {
bool gb_lcd_filter = false;
bool print_auto_page = true;
bool print_screen_cap = false;
wxString gb_rom_dir;
wxString gbc_rom_dir;
/// GBA
wxString gba_bios;
@ -44,17 +42,12 @@ extern struct opts_t {
bool link_proto = false;
int link_timeout = 500;
int gba_link_type;
wxString gba_rom_dir;
/// General
bool autoload_state = false;
bool autoload_cheats = false;
wxString battery_dir;
bool recent_freeze = false;
wxString recording_dir;
int rewind_interval = 0;
wxString scrshot_dir;
wxString state_dir;
bool statusbar = false;
/// Joypad

View File

@ -134,9 +134,9 @@ GameArea::GameArea()
void GameArea::LoadGame(const wxString& name)
{
rom_scene_rls = wxT("-");
rom_scene_rls_name = wxT("-");
rom_name = wxT("");
rom_scene_rls = "-";
rom_scene_rls_name = "-";
rom_name = "";
// fex just crashes if file does not exist and it's compressed,
// so check first
wxFileName fnfn(name);
@ -147,18 +147,21 @@ void GameArea::LoadGame(const wxString& name)
wxString rp = fnfn.GetPath();
// can't really decide which dir to use, so try GBA first, then GB
if (!wxGetApp().GetAbsolutePath(gopts.gba_rom_dir).empty()) {
fnfn.SetPath(wxGetApp().GetAbsolutePath(gopts.gba_rom_dir) + wxT('/') + rp);
const wxString& gba_rom_dir = OPTION(kGBAROMDir);
if (!wxGetApp().GetAbsolutePath(gba_rom_dir).empty()) {
fnfn.SetPath(wxGetApp().GetAbsolutePath(gba_rom_dir) + '/' + rp);
badfile = !fnfn.IsFileReadable();
}
if (badfile && !wxGetApp().GetAbsolutePath(gopts.gb_rom_dir).empty()) {
fnfn.SetPath(wxGetApp().GetAbsolutePath(gopts.gb_rom_dir) + wxT('/') + rp);
const wxString& gb_rom_dir = OPTION(kGBROMDir);
if (badfile && !wxGetApp().GetAbsolutePath(gb_rom_dir).empty()) {
fnfn.SetPath(wxGetApp().GetAbsolutePath(gb_rom_dir) + '/' + rp);
badfile = !fnfn.IsFileReadable();
}
if (badfile && !wxGetApp().GetAbsolutePath(gopts.gbc_rom_dir).empty()) {
fnfn.SetPath(wxGetApp().GetAbsolutePath(gopts.gbc_rom_dir) + wxT('/') + rp);
const wxString& gbc_rom_dir = OPTION(kGBGBCROMDir);
if (badfile && !wxGetApp().GetAbsolutePath(gbc_rom_dir).empty()) {
fnfn.SetPath(wxGetApp().GetAbsolutePath(gbc_rom_dir) + '/' + rp);
badfile = !fnfn.IsFileReadable();
}
}
@ -549,24 +552,24 @@ void GameArea::SetFrameTitle()
void GameArea::recompute_dirs()
{
batdir = gopts.battery_dir;
batdir = OPTION(kGenBatteryDir);
if (!batdir.size()) {
if (batdir.empty()) {
batdir = loaded_game.GetPathWithSep();
} else {
batdir = wxGetApp().GetAbsolutePath(gopts.battery_dir);
batdir = wxGetApp().GetAbsolutePath(batdir);
}
if (!wxIsWritable(batdir)) {
batdir = wxGetApp().GetDataDir();
}
statedir = gopts.state_dir;
statedir = OPTION(kGenStateDir);
if (!statedir.size()) {
if (statedir.empty()) {
statedir = loaded_game.GetPathWithSep();
} else {
statedir = wxGetApp().GetAbsolutePath(gopts.state_dir);
statedir = wxGetApp().GetAbsolutePath(statedir);
}
if (!wxIsWritable(statedir)) {

View File

@ -547,7 +547,7 @@ void systemFrame()
void systemScreenCapture(int num)
{
GameArea* panel = wxGetApp().frame->GetPanel();
wxFileName fn = wxFileName(wxGetApp().frame->GetGamePath(gopts.scrshot_dir), wxEmptyString);
wxFileName fn = wxFileName(wxGetApp().frame->GetGamePath(OPTION(kGenScreenshotDir)), wxEmptyString);
const int capture_format = OPTION(kPrefCaptureFormat);
do {
@ -1104,7 +1104,7 @@ void systemGbPrint(uint8_t* data, int len, int pages, int feed, int pal, int con
}
if (gopts.print_screen_cap) {
wxFileName fn = wxFileName(wxGetApp().frame->GetGamePath(gopts.scrshot_dir), wxEmptyString);
wxFileName fn = wxFileName(wxGetApp().frame->GetGamePath(OPTION(kGenScreenshotDir)), wxEmptyString);
int num = 1;
const int capture_format = OPTION(kPrefCaptureFormat);

View File

@ -1168,7 +1168,7 @@ void GfxViewer::SaveBMP(wxCommandEvent& ev)
{
(void)ev; // unused params
GameArea* panel = wxGetApp().frame->GetPanel();
bmp_save_dir = wxGetApp().frame->GetGamePath(gopts.scrshot_dir);
bmp_save_dir = wxGetApp().frame->GetGamePath(OPTION(kGenScreenshotDir));
// no attempt is made here to translate the dialog type name
// it's just a suggested name, anyway
wxString def_name = panel->game_name() + wxT('-') + dname;