diff --git a/src/common/config.cpp b/src/common/config.cpp index 0d9ff093..f04678eb 100644 --- a/src/common/config.cpp +++ b/src/common/config.cpp @@ -8,6 +8,7 @@ #include // for wstring support #include #include "common/logging/formatter.h" +#include "common/path_util.h" #include "config.h" namespace toml { @@ -59,6 +60,7 @@ static bool vkCrashDiagnostic = false; // Gui std::filesystem::path settings_install_dir = {}; +std::filesystem::path settings_addon_install_dir = {}; u32 main_window_geometry_x = 400; u32 main_window_geometry_y = 400; u32 main_window_geometry_w = 1280; @@ -299,6 +301,9 @@ 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 setMainWindowTheme(u32 theme) { mw_themes = theme; } @@ -355,6 +360,13 @@ u32 getMainWindowGeometryH() { std::filesystem::path getGameInstallDir() { return settings_install_dir; } +std::filesystem::path getAddonInstallDir() { + if (settings_addon_install_dir.empty()) { + // Default for users without a config file or a config file from before this option existed + return Common::FS::GetUserPath(Common::FS::PathType::UserDir) / "addcont"; + } + return settings_addon_install_dir; +} u32 getMainWindowTheme() { return mw_themes; } @@ -482,6 +494,7 @@ void load(const std::filesystem::path& path) { m_window_size_W = toml::find_or(gui, "mw_width", 0); 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", {}); 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); @@ -556,6 +569,8 @@ void save(const std::filesystem::path& path) { data["GUI"]["mw_width"] = m_window_size_W; data["GUI"]["mw_height"] = m_window_size_H; 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"]["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 eeeff0b2..402b8660 100644 --- a/src/common/config.h +++ b/src/common/config.h @@ -76,6 +76,7 @@ bool vkCrashDiagnosticEnabled(); // Gui 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 setMainWindowTheme(u32 theme); void setIconSize(u32 size); void setIconSizeGrid(u32 size); @@ -94,6 +95,7 @@ u32 getMainWindowGeometryY(); u32 getMainWindowGeometryW(); u32 getMainWindowGeometryH(); std::filesystem::path getGameInstallDir(); +std::filesystem::path getAddonInstallDir(); u32 getMainWindowTheme(); u32 getIconSize(); u32 getIconSizeGrid(); diff --git a/src/common/path_util.cpp b/src/common/path_util.cpp index d7274fc7..f602f351 100644 --- a/src/common/path_util.cpp +++ b/src/common/path_util.cpp @@ -119,7 +119,6 @@ static auto UserPaths = [] { create_path(PathType::CapturesDir, user_dir / CAPTURES_DIR); create_path(PathType::CheatsDir, user_dir / CHEATS_DIR); create_path(PathType::PatchesDir, user_dir / PATCHES_DIR); - create_path(PathType::AddonsDir, user_dir / ADDONS_DIR); create_path(PathType::MetaDataDir, user_dir / METADATA_DIR); return paths; diff --git a/src/common/path_util.h b/src/common/path_util.h index d40f4aab..af0e9183 100644 --- a/src/common/path_util.h +++ b/src/common/path_util.h @@ -26,7 +26,6 @@ enum class PathType { CapturesDir, // Where rdoc captures are stored. CheatsDir, // Where cheats are stored. PatchesDir, // Where patches are stored. - AddonsDir, // Where additional content is stored. MetaDataDir, // Where game metadata (e.g. trophies and menu backgrounds) is stored. }; diff --git a/src/core/libraries/app_content/app_content.cpp b/src/core/libraries/app_content/app_content.cpp index 754343ee..f912639e 100644 --- a/src/core/libraries/app_content/app_content.cpp +++ b/src/core/libraries/app_content/app_content.cpp @@ -5,6 +5,7 @@ #include "app_content.h" #include "common/assert.h" +#include "common/config.h" #include "common/io_file.h" #include "common/logging/log.h" #include "common/path_util.h" @@ -59,8 +60,7 @@ int PS4_SYSV_ABI sceAppContentAddcontMount(u32 service_label, OrbisAppContentMountPoint* mount_point) { LOG_INFO(Lib_AppContent, "called"); - const auto& mount_dir = Common::FS::GetUserPath(Common::FS::PathType::AddonsDir) / title_id / - entitlement_label->data; + const auto& mount_dir = Config::getAddonInstallDir() / title_id / entitlement_label->data; auto* mnt = Common::Singleton::Instance(); for (int i = 0; i < addcont_count; i++) { @@ -246,7 +246,7 @@ int PS4_SYSV_ABI sceAppContentInitialize(const OrbisAppContentInitParam* initPar LOG_ERROR(Lib_AppContent, "(DUMMY) called"); auto* param_sfo = Common::Singleton::Instance(); - const auto addons_dir = Common::FS::GetUserPath(Common::FS::PathType::AddonsDir); + const auto addons_dir = Config::getAddonInstallDir(); if (const auto value = param_sfo->GetString("TITLE_ID"); value.has_value()) { title_id = *value; } else { diff --git a/src/qt_gui/game_install_dialog.cpp b/src/qt_gui/game_install_dialog.cpp index d8cc7a83..8f7ffd5d 100644 --- a/src/qt_gui/game_install_dialog.cpp +++ b/src/qt_gui/game_install_dialog.cpp @@ -18,6 +18,7 @@ GameInstallDialog::GameInstallDialog() : m_gamesDirectory(nullptr) { auto layout = new QVBoxLayout(this); layout->addWidget(SetupGamesDirectory()); + layout->addWidget(SetupAddonsDirectory()); layout->addStretch(); layout->addWidget(SetupDialogActions()); @@ -27,7 +28,7 @@ GameInstallDialog::GameInstallDialog() : m_gamesDirectory(nullptr) { GameInstallDialog::~GameInstallDialog() {} -void GameInstallDialog::Browse() { +void GameInstallDialog::BrowseGamesDirectory() { auto path = QFileDialog::getExistingDirectory(this, tr("Directory to install games")); if (!path.isEmpty()) { @@ -35,6 +36,14 @@ void GameInstallDialog::Browse() { } } +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); @@ -51,7 +60,30 @@ QWidget* GameInstallDialog::SetupGamesDirectory() { // Browse button. auto browse = new QPushButton(tr("Browse")); - connect(browse, &QPushButton::clicked, this, &GameInstallDialog::Browse); + connect(browse, &QPushButton::clicked, this, &GameInstallDialog::BrowseGamesDirectory); + + layout->addWidget(browse); + + return group; +} + +QWidget* GameInstallDialog::SetupAddonsDirectory() { + auto group = new QGroupBox(tr("Directory to install DLC")); + auto layout = new QHBoxLayout(group); + + // Input. + m_addonsDirectory = new QLineEdit(); + QString install_dir; + Common::FS::PathToQString(install_dir, Config::getAddonInstallDir()); + m_addonsDirectory->setText(install_dir); + m_addonsDirectory->setMinimumWidth(400); + + layout->addWidget(m_addonsDirectory); + + // Browse button. + auto browse = new QPushButton(tr("Browse")); + + connect(browse, &QPushButton::clicked, this, &GameInstallDialog::BrowseAddonsDirectory); layout->addWidget(browse); @@ -70,6 +102,7 @@ QWidget* GameInstallDialog::SetupDialogActions() { void GameInstallDialog::Save() { // Check games directory. auto gamesDirectory = m_gamesDirectory->text(); + auto addonsDirectory = m_addonsDirectory->text(); if (gamesDirectory.isEmpty() || !QDir(gamesDirectory).exists() || !QDir::isAbsolutePath(gamesDirectory)) { @@ -78,7 +111,15 @@ void GameInstallDialog::Save() { return; } + if (addonsDirectory.isEmpty() || !QDir(addonsDirectory).exists() || + !QDir::isAbsolutePath(addonsDirectory)) { + QMessageBox::critical(this, tr("Error"), + "The value for location to install DLC is not valid."); + return; + } + Config::setGameInstallDir(Common::FS::PathFromQString(gamesDirectory)); + Config::setAddonInstallDir(Common::FS::PathFromQString(addonsDirectory)); const auto config_dir = Common::FS::GetUserPath(Common::FS::PathType::UserDir); 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 6f439e81..0a4e2935 100644 --- a/src/qt_gui/game_install_dialog.h +++ b/src/qt_gui/game_install_dialog.h @@ -16,13 +16,16 @@ public: ~GameInstallDialog(); private slots: - void Browse(); + void BrowseGamesDirectory(); + void BrowseAddonsDirectory(); private: QWidget* SetupGamesDirectory(); + QWidget* SetupAddonsDirectory(); QWidget* SetupDialogActions(); void Save(); private: QLineEdit* m_gamesDirectory; + QLineEdit* m_addonsDirectory; }; \ No newline at end of file diff --git a/src/qt_gui/main_window.cpp b/src/qt_gui/main_window.cpp index 837cdece..6f4b8ae7 100644 --- a/src/qt_gui/main_window.cpp +++ b/src/qt_gui/main_window.cpp @@ -687,8 +687,8 @@ void MainWindow::InstallDragDropPkg(std::filesystem::path file, int pkgNum, int } std::string entitlement_label = Common::SplitString(content_id, '-')[2]; - auto addon_extract_path = Common::FS::GetUserPath(Common::FS::PathType::AddonsDir) / - pkg.GetTitleID() / entitlement_label; + auto addon_extract_path = + Config::getAddonInstallDir() / pkg.GetTitleID() / entitlement_label; QString addonDirPath; Common::FS::PathToQString(addonDirPath, addon_extract_path); QDir addon_dir(addonDirPath);