diff --git a/src/common/config.cpp b/src/common/config.cpp index f04678eb7..614fe6bf1 100644 --- a/src/common/config.cpp +++ b/src/common/config.cpp @@ -61,6 +61,7 @@ static bool vkCrashDiagnostic = false; // Gui std::filesystem::path settings_install_dir = {}; std::filesystem::path settings_addon_install_dir = {}; +std::filesystem::path emulator_user_dir = {}; u32 main_window_geometry_x = 400; u32 main_window_geometry_y = 400; u32 main_window_geometry_w = 1280; @@ -301,9 +302,13 @@ void setMainWindowGeometry(u32 x, u32 y, u32 w, u32 h) { void setGameInstallDir(const std::filesystem::path& dir) { settings_install_dir = dir; } + void setAddonInstallDir(const std::filesystem::path& dir) { settings_addon_install_dir = dir; } +void setEmulatorUserDir(const std::filesystem::path& dir) { + emulator_user_dir = dir; +} void setMainWindowTheme(u32 theme) { mw_themes = theme; } @@ -367,6 +372,9 @@ std::filesystem::path getAddonInstallDir() { } return settings_addon_install_dir; } +std::filesystem::path getEmulatorUserDir() { + return emulator_user_dir; +} u32 getMainWindowTheme() { return mw_themes; } @@ -495,6 +503,7 @@ void load(const std::filesystem::path& path) { m_window_size_H = toml::find_or(gui, "mw_height", 0); settings_install_dir = toml::find_fs_path_or(gui, "installDir", {}); settings_addon_install_dir = toml::find_fs_path_or(gui, "addonInstallDir", {}); + emulator_user_dir = toml::find_fs_path_or(gui, "userDir", {}); main_window_geometry_x = toml::find_or(gui, "geometry_x", 0); main_window_geometry_y = toml::find_or(gui, "geometry_y", 0); main_window_geometry_w = toml::find_or(gui, "geometry_w", 0); @@ -571,6 +580,7 @@ void save(const std::filesystem::path& path) { data["GUI"]["installDir"] = std::string{fmt::UTF(settings_install_dir.u8string()).data}; data["GUI"]["addonInstallDir"] = std::string{fmt::UTF(settings_addon_install_dir.u8string()).data}; + data["GUI"]["userDir"] = std::string{fmt::UTF(emulator_user_dir.u8string()).data}; data["GUI"]["geometry_x"] = main_window_geometry_x; data["GUI"]["geometry_y"] = main_window_geometry_y; data["GUI"]["geometry_w"] = main_window_geometry_w; diff --git a/src/common/config.h b/src/common/config.h index 402b8660e..806038df3 100644 --- a/src/common/config.h +++ b/src/common/config.h @@ -77,6 +77,7 @@ bool vkCrashDiagnosticEnabled(); void setMainWindowGeometry(u32 x, u32 y, u32 w, u32 h); void setGameInstallDir(const std::filesystem::path& dir); void setAddonInstallDir(const std::filesystem::path& dir); +void setEmulatorUserDir(const std::filesystem::path& dir); void setMainWindowTheme(u32 theme); void setIconSize(u32 size); void setIconSizeGrid(u32 size); @@ -96,6 +97,7 @@ u32 getMainWindowGeometryW(); u32 getMainWindowGeometryH(); std::filesystem::path getGameInstallDir(); std::filesystem::path getAddonInstallDir(); +std::filesystem::path getEmulatorUserDir(); u32 getMainWindowTheme(); u32 getIconSize(); u32 getIconSizeGrid(); diff --git a/src/common/path_util.cpp b/src/common/path_util.cpp index f602f3513..60ed8892f 100644 --- a/src/common/path_util.cpp +++ b/src/common/path_util.cpp @@ -107,6 +107,16 @@ static auto UserPaths = [] { }; create_path(PathType::UserDir, user_dir); + +#ifdef _WIN32 + auto config_path = std::filesystem::path(getenv("APPDATA")) / "shadPS4"; +#elif __APPLE__ + auto config_path = user_dir; +#else + auto config_path = std::filesystem::current_path(); +#endif + create_path(PathType::ConfigDir, config_path); + create_path(PathType::LogDir, user_dir / LOG_DIR); create_path(PathType::ScreenshotsDir, user_dir / SCREENSHOTS_DIR); create_path(PathType::ShaderDir, user_dir / SHADER_DIR); diff --git a/src/common/path_util.h b/src/common/path_util.h index af0e91832..fcf45f9f5 100644 --- a/src/common/path_util.h +++ b/src/common/path_util.h @@ -14,6 +14,7 @@ namespace Common::FS { enum class PathType { UserDir, // Where shadPS4 stores its data. + ConfigDir, // Where shadPS4 stores its config. LogDir, // Where log files are stored. ScreenshotsDir, // Where screenshots are stored. ShaderDir, // Where shaders are stored. diff --git a/src/emulator.cpp b/src/emulator.cpp index b27c73867..47fc0b2ce 100644 --- a/src/emulator.cpp +++ b/src/emulator.cpp @@ -81,7 +81,7 @@ Emulator::Emulator() { } Emulator::~Emulator() { - const auto config_dir = Common::FS::GetUserPath(Common::FS::PathType::UserDir); + const auto config_dir = Common::FS::GetUserPath(Common::FS::PathType::ConfigDir); Config::save(config_dir / "config.toml"); } diff --git a/src/qt_gui/check_update.cpp b/src/qt_gui/check_update.cpp index b92974ba9..f96726079 100644 --- a/src/qt_gui/check_update.cpp +++ b/src/qt_gui/check_update.cpp @@ -252,9 +252,9 @@ void CheckUpdate::setupUI(const QString& downloadUrl, const QString& latestDate, autoUpdateCheckBox->setChecked(Config::autoUpdate()); connect(autoUpdateCheckBox, &QCheckBox::stateChanged, this, [](int state) { - const auto user_dir = Common::FS::GetUserPath(Common::FS::PathType::UserDir); + const auto config_dir = Common::FS::GetUserPath(Common::FS::PathType::ConfigDir); Config::setAutoUpdate(state == Qt::Checked); - Config::save(user_dir / "config.toml"); + Config::save(config_dir / "config.toml"); }); setLayout(layout); diff --git a/src/qt_gui/game_install_dialog.cpp b/src/qt_gui/game_install_dialog.cpp index 8f7ffd5d1..aec327843 100644 --- a/src/qt_gui/game_install_dialog.cpp +++ b/src/qt_gui/game_install_dialog.cpp @@ -19,6 +19,7 @@ GameInstallDialog::GameInstallDialog() : m_gamesDirectory(nullptr) { layout->addWidget(SetupGamesDirectory()); layout->addWidget(SetupAddonsDirectory()); + layout->addWidget(SetupUserDirectory()); layout->addStretch(); layout->addWidget(SetupDialogActions()); @@ -28,22 +29,13 @@ GameInstallDialog::GameInstallDialog() : m_gamesDirectory(nullptr) { GameInstallDialog::~GameInstallDialog() {} -void GameInstallDialog::BrowseGamesDirectory() { - auto path = QFileDialog::getExistingDirectory(this, tr("Directory to install games")); +void GameInstallDialog::Browse(const QString& browseTitle, QLineEdit* browseDir) { + auto path = QFileDialog::getExistingDirectory(this, browseTitle); if (!path.isEmpty()) { - m_gamesDirectory->setText(QDir::toNativeSeparators(path)); + browseDir->setText(QDir::toNativeSeparators(path)); } } - -void GameInstallDialog::BrowseAddonsDirectory() { - auto path = QFileDialog::getExistingDirectory(this, tr("Directory to install DLC")); - - if (!path.isEmpty()) { - m_addonsDirectory->setText(QDir::toNativeSeparators(path)); - } -} - QWidget* GameInstallDialog::SetupGamesDirectory() { auto group = new QGroupBox(tr("Directory to install games")); auto layout = new QHBoxLayout(group); @@ -60,7 +52,8 @@ QWidget* GameInstallDialog::SetupGamesDirectory() { // Browse button. auto browse = new QPushButton(tr("Browse")); - connect(browse, &QPushButton::clicked, this, &GameInstallDialog::BrowseGamesDirectory); + connect(browse, &QPushButton::clicked, this, + [this]() { Browse(tr("Directory to install games"), m_gamesDirectory); }); layout->addWidget(browse); @@ -83,7 +76,34 @@ QWidget* GameInstallDialog::SetupAddonsDirectory() { // Browse button. auto browse = new QPushButton(tr("Browse")); - connect(browse, &QPushButton::clicked, this, &GameInstallDialog::BrowseAddonsDirectory); + connect(browse, &QPushButton::clicked, this, + [this]() { Browse(tr("Directory to install DLC"), m_addonsDirectory); }); + + layout->addWidget(browse); + + return group; +} + +QWidget* GameInstallDialog::SetupUserDirectory() { + auto group = new QGroupBox(tr("Location of user directory")); + auto layout = new QHBoxLayout(group); + + m_userDirectory = new QLineEdit(); + QString user_dir; + std::filesystem::path default_path = Config::getEmulatorUserDir().empty() + ? Common::FS::GetUserPath(Common::FS::PathType::ConfigDir) + : Config::getEmulatorUserDir(); + Common::FS::PathToQString(user_dir, default_path); + m_userDirectory->setText(user_dir); + m_userDirectory->setMinimumWidth(400); + + layout->addWidget(m_userDirectory); + + // Browse button. + auto browse = new QPushButton(tr("Browse")); + + connect(browse, &QPushButton::clicked, this, + [this]() { Browse(tr("Location of user directory"), m_userDirectory); }); layout->addWidget(browse); @@ -103,11 +123,12 @@ void GameInstallDialog::Save() { // Check games directory. auto gamesDirectory = m_gamesDirectory->text(); auto addonsDirectory = m_addonsDirectory->text(); + auto userDirectory = m_userDirectory->text(); if (gamesDirectory.isEmpty() || !QDir(gamesDirectory).exists() || !QDir::isAbsolutePath(gamesDirectory)) { QMessageBox::critical(this, tr("Error"), - "The value for location to install games is not valid."); + tr("The value for location to install games is not valid.")); return; } @@ -118,9 +139,18 @@ void GameInstallDialog::Save() { return; } + if (!userDirectory.endsWith("user", Qt::CaseInsensitive) || !QDir(userDirectory).exists() || + !QDir::isAbsolutePath(userDirectory)) { + QMessageBox::critical(this, tr("Error"), + tr("The value for location of user directory is not valid.")); + return; + } + Config::setEmulatorUserDir(Common::FS::PathFromQString(userDirectory)); + Common::FS::SetUserPath(Common::FS::PathType::UserDir, Config::getEmulatorUserDir()); + Config::setGameInstallDir(Common::FS::PathFromQString(gamesDirectory)); Config::setAddonInstallDir(Common::FS::PathFromQString(addonsDirectory)); - const auto config_dir = Common::FS::GetUserPath(Common::FS::PathType::UserDir); + const auto config_dir = Common::FS::GetUserPath(Common::FS::PathType::ConfigDir); Config::save(config_dir / "config.toml"); accept(); } diff --git a/src/qt_gui/game_install_dialog.h b/src/qt_gui/game_install_dialog.h index 0a4e29357..7f7fbb782 100644 --- a/src/qt_gui/game_install_dialog.h +++ b/src/qt_gui/game_install_dialog.h @@ -16,16 +16,17 @@ public: ~GameInstallDialog(); private slots: - void BrowseGamesDirectory(); - void BrowseAddonsDirectory(); + void Browse(const QString& browseTitle, QLineEdit* browseDir); private: QWidget* SetupGamesDirectory(); QWidget* SetupAddonsDirectory(); + QWidget* SetupUserDirectory(); QWidget* SetupDialogActions(); void Save(); private: QLineEdit* m_gamesDirectory; QLineEdit* m_addonsDirectory; + QLineEdit* m_userDirectory; }; \ No newline at end of file diff --git a/src/qt_gui/main.cpp b/src/qt_gui/main.cpp index 8c565a19b..52ea86b1b 100644 --- a/src/qt_gui/main.cpp +++ b/src/qt_gui/main.cpp @@ -23,14 +23,14 @@ int main(int argc, char* argv[]) { QApplication a(argc, argv); // Load configurations and initialize Qt application - const auto user_dir = Common::FS::GetUserPath(Common::FS::PathType::UserDir); - Config::load(user_dir / "config.toml"); + const auto config_dir = Common::FS::GetUserPath(Common::FS::PathType::ConfigDir); + Config::load(config_dir / "config.toml"); // Check if elf or eboot.bin path was passed as a command line argument bool has_command_line_argument = argc > 1; // Check if the game install directory is set - if (Config::getGameInstallDir().empty() && !has_command_line_argument) { + if ((Config::getGameInstallDir().empty() || Config::getEmulatorUserDir().empty()) && !has_command_line_argument) { GameInstallDialog dlg; dlg.exec(); } diff --git a/src/qt_gui/main_window.cpp b/src/qt_gui/main_window.cpp index 6f4b8ae7e..67742fa0a 100644 --- a/src/qt_gui/main_window.cpp +++ b/src/qt_gui/main_window.cpp @@ -28,7 +28,8 @@ MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent), ui(new Ui::MainWi MainWindow::~MainWindow() { SaveWindowState(); - const auto config_dir = Common::FS::GetUserPath(Common::FS::PathType::UserDir); + Common::FS::SetUserPath(Common::FS::PathType::UserDir, Config::getEmulatorUserDir()); + const auto config_dir = Common::FS::GetUserPath(Common::FS::PathType::ConfigDir); Config::save(config_dir / "config.toml"); } @@ -967,8 +968,8 @@ void MainWindow::AddRecentFiles(QString filePath) { vec.pop_back(); } Config::setRecentFiles(vec); - const auto config_dir = Common::FS::GetUserPath(Common::FS::PathType::UserDir); - Config::save(config_dir / "config.toml"); + const auto config_dir = Common::FS::GetUserPath(Common::FS::PathType::ConfigDir); + Config::save(config_dir); CreateRecentGameActions(); // Refresh the QActions. } diff --git a/src/qt_gui/settings_dialog.cpp b/src/qt_gui/settings_dialog.cpp index 954762049..3f3c3ea58 100644 --- a/src/qt_gui/settings_dialog.cpp +++ b/src/qt_gui/settings_dialog.cpp @@ -51,7 +51,7 @@ SettingsDialog::SettingsDialog(std::span physical_devices, QWidge : QDialog(parent), ui(new Ui::SettingsDialog) { ui->setupUi(this); ui->tabWidgetSettings->setUsesScrollButtons(false); - const auto config_dir = Common::FS::GetUserPath(Common::FS::PathType::UserDir); + const auto config_dir = Common::FS::GetUserPath(Common::FS::PathType::ConfigDir); ui->buttonBox->button(QDialogButtonBox::StandardButton::Close)->setFocus();