diff --git a/src/backend/core/Mem.cpp b/src/backend/core/Mem.cpp index acd9f9ef..7e54003b 100644 --- a/src/backend/core/Mem.cpp +++ b/src/backend/core/Mem.cpp @@ -38,6 +38,9 @@ void Mem::Reset() { void Mem::LoadSRAM(SaveType save_type, fs::path path) { if(save_type == SAVE_SRAM_256k) { std::error_code error; + if (!savePath.empty()) { + path = savePath / path.filename(); + } sramPath = path.replace_extension(".sram").string(); if(saveData.is_mapped()) { saveData.sync(error); diff --git a/src/backend/core/mem/Flash.cpp b/src/backend/core/mem/Flash.cpp index 532555c7..1e652c0f 100644 --- a/src/backend/core/mem/Flash.cpp +++ b/src/backend/core/mem/Flash.cpp @@ -12,7 +12,11 @@ void Flash::Reset() { void Flash::Load(SaveType saveType, const std::string& path) { if(saveType == SAVE_FLASH_1m) { - flashPath = fs::path(path).replace_extension(".flash").string(); + fs::path flashPath_ = path; + if (!savePath.empty()) { + flashPath_ = savePath / flashPath_.filename(); + } + flashPath = flashPath_.replace_extension(".flash").string(); std::error_code error; if (saveData.is_mapped()) { saveData.sync(error); diff --git a/src/backend/core/mmio/PIF.cpp b/src/backend/core/mmio/PIF.cpp index 062f43ec..7b92782c 100644 --- a/src/backend/core/mmio/PIF.cpp +++ b/src/backend/core/mmio/PIF.cpp @@ -30,7 +30,11 @@ void PIF::Reset() { void PIF::MaybeLoadMempak() { if(!mempakOpen) { - mempakPath = fs::path(mempakPath).replace_extension(".mempak").string(); + fs::path mempakPath_ = mempakPath; + if (!savePath.empty()) { + mempakPath_ = savePath / mempakPath_.filename(); + } + mempakPath = mempakPath_.replace_extension(".mempak").string(); std::error_code error; if (mempak.is_mapped()) { mempak.sync(error); @@ -74,7 +78,11 @@ FORCE_INLINE size_t GetSaveSize(SaveType saveType) { void PIF::LoadEeprom(SaveType saveType, const std::string& path) { if(saveType == SAVE_EEPROM_16k || saveType == SAVE_EEPROM_4k) { - eepromPath = fs::path(path).replace_extension(".eeprom").string(); + fs::path eepromPath_ = path; + if (!savePath.empty()) { + eepromPath_ = savePath / eepromPath_.filename(); + } + eepromPath = eepromPath_.replace_extension(".eeprom").string(); std::error_code error; if (eeprom.is_mapped()) { eeprom.sync(error); diff --git a/src/common.hpp b/src/common.hpp index 989ae9d9..d0aa2b46 100644 --- a/src/common.hpp +++ b/src/common.hpp @@ -19,6 +19,7 @@ using m128i = __m128i; constexpr u32 N64_CPU_FREQ = 93750000; constexpr u16 KAIZEN_VERSION = 0x010; +extern std::string savePath; static FORCE_INLINE constexpr u32 GetCyclesPerFrame(bool pal) { if (pal) { diff --git a/src/frontend/JSONUtils.hpp b/src/frontend/JSONUtils.hpp index 8c052997..875eea93 100644 --- a/src/frontend/JSONUtils.hpp +++ b/src/frontend/JSONUtils.hpp @@ -16,6 +16,7 @@ static inline nlohmann::json JSONOpenOrCreate(const std::string& path) { } else { auto file = std::fstream(path, std::fstream::in | std::fstream::out | std::fstream::trunc); nlohmann::json json; + json["general"]["savePath"] = ""; json["audio"]["volumeL"] = 0.5; json["audio"]["volumeR"] = 0.5; json["audio"]["lock"] = true; diff --git a/src/frontend/SettingsWindow.cpp b/src/frontend/SettingsWindow.cpp index 7b2753c7..411f8efe 100644 --- a/src/frontend/SettingsWindow.cpp +++ b/src/frontend/SettingsWindow.cpp @@ -2,10 +2,16 @@ #include #include #include +#include +#include + +std::string savePath = ""; SettingsWindow::SettingsWindow() : QWidget(nullptr) { settings = JSONOpenOrCreate("resources/settings.json"); + savePath = JSONGetField(settings, "general", "savePath"); + if (objectName().isEmpty()) setObjectName("Settings"); @@ -15,9 +21,31 @@ SettingsWindow::SettingsWindow() : QWidget(nullptr) { cpuSettings = new CPUSettings(settings); audioSettings = new AudioSettings(settings); inputSettings = new InputSettings(settings); + generalSettings = new QWidget; keyMap = inputSettings->GetMappedKeys(); + folderLabelPrefix = new QLabel("Save files' path: "); + folderLabel = new QLabel(fmt::format("{}", savePath).c_str()); + + connect(folderBtn, &QPushButton::pressed, this, [&]() { + savePath = QFileDialog::getExistingDirectory(this, tr("Select directory")).toStdString(); + folderLabel->setText(fmt::format("{}", savePath).c_str()); + JSONSetField(settings, "general", "savePath", savePath); + apply->setEnabled(true); + }); + + auto generalLayout = new QHBoxLayout; + auto generalLayoutV = new QVBoxLayout; + generalLayout->addWidget(folderLabelPrefix); + generalLayout->addWidget(folderLabel); + generalLayout->addStretch(); + generalLayout->addWidget(folderBtn); + generalLayoutV->addLayout(generalLayout); + generalLayoutV->addStretch(); + generalSettings->setLayout(generalLayoutV); + auto* tabs = new QTabWidget; + tabs->addTab(generalSettings, tr("General")); tabs->addTab(cpuSettings, tr("CPU")); tabs->addTab(audioSettings, tr("Audio")); tabs->addTab(inputSettings, tr("Input")); diff --git a/src/frontend/SettingsWindow.hpp b/src/frontend/SettingsWindow.hpp index a2a13876..32c9c014 100644 --- a/src/frontend/SettingsWindow.hpp +++ b/src/frontend/SettingsWindow.hpp @@ -2,6 +2,7 @@ #include #include #include +#include #include #include #include @@ -9,6 +10,10 @@ class SettingsWindow : public QWidget { QPushButton* cancel = new QPushButton("Cancel"); QPushButton* apply = new QPushButton("Apply"); + QFileIconProvider* iconProv = new QFileIconProvider; + QPushButton* folderBtn = new QPushButton(iconProv->icon(QFileIconProvider::Folder), ""); + QLabel* folderLabelPrefix; + QLabel* folderLabel; Q_OBJECT public: float getVolumeL() { return float(audioSettings->volumeL->value()) / 100.f; } @@ -19,6 +24,7 @@ public: CPUSettings* cpuSettings; AudioSettings* audioSettings; InputSettings* inputSettings; + QWidget* generalSettings; Q_SIGNALS: void regrabKeyboard(); }; \ No newline at end of file