diff options
Diffstat (limited to 'src/qt_common')
| -rw-r--r-- | src/qt_common/CMakeLists.txt | 3 | ||||
| -rw-r--r-- | src/qt_common/abstract/frontend.cpp (renamed from src/qt_common/abstract/qt_frontend_util.cpp) | 2 | ||||
| -rw-r--r-- | src/qt_common/abstract/frontend.h (renamed from src/qt_common/abstract/qt_frontend_util.h) | 6 | ||||
| -rw-r--r-- | src/qt_common/qt_common.cpp | 10 | ||||
| -rw-r--r-- | src/qt_common/qt_string_lookup.h | 23 | ||||
| -rw-r--r-- | src/qt_common/util/content.cpp | 6 | ||||
| -rw-r--r-- | src/qt_common/util/content.h | 6 | ||||
| -rw-r--r-- | src/qt_common/util/fs.cpp | 130 | ||||
| -rw-r--r-- | src/qt_common/util/fs.h | 22 | ||||
| -rw-r--r-- | src/qt_common/util/game.cpp | 2 | ||||
| -rw-r--r-- | src/qt_common/util/path.cpp | 2 |
11 files changed, 197 insertions, 15 deletions
diff --git a/src/qt_common/CMakeLists.txt b/src/qt_common/CMakeLists.txt index 39dd1a7460..75ef717583 100644 --- a/src/qt_common/CMakeLists.txt +++ b/src/qt_common/CMakeLists.txt @@ -20,13 +20,14 @@ add_library(qt_common STATIC util/applet.h util/applet.cpp util/compress.h util/compress.cpp - abstract/qt_frontend_util.h abstract/qt_frontend_util.cpp + abstract/frontend.h abstract/frontend.cpp abstract/qt_progress_dialog.h abstract/qt_progress_dialog.cpp qt_string_lookup.h qt_compat.h discord/discord.h + util/fs.h util/fs.cpp ) create_target_directory_groups(qt_common) diff --git a/src/qt_common/abstract/qt_frontend_util.cpp b/src/qt_common/abstract/frontend.cpp index 3fe0ba0a80..2ed76f8ea9 100644 --- a/src/qt_common/abstract/qt_frontend_util.cpp +++ b/src/qt_common/abstract/frontend.cpp @@ -1,7 +1,7 @@ // SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later -#include "qt_frontend_util.h" +#include "frontend.h" #include "qt_common/qt_common.h" #ifdef YUZU_QT_WIDGETS diff --git a/src/qt_common/abstract/qt_frontend_util.h b/src/qt_common/abstract/frontend.h index 59e8f15a4e..b496b37cbe 100644 --- a/src/qt_common/abstract/qt_frontend_util.h +++ b/src/qt_common/abstract/frontend.h @@ -1,8 +1,8 @@ // SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later -#ifndef QT_FRONTEND_UTIL_H -#define QT_FRONTEND_UTIL_H +#ifndef FRONTEND_H +#define FRONTEND_H #include <QGuiApplication> #include "qt_common/qt_common.h" @@ -136,4 +136,4 @@ const QString GetSaveFileName(const QString &title, Options options = Options()); } // namespace QtCommon::Frontend -#endif // QT_FRONTEND_UTIL_H +#endif // FRONTEND_H diff --git a/src/qt_common/qt_common.cpp b/src/qt_common/qt_common.cpp index 1fa3df98cf..f2091df866 100644 --- a/src/qt_common/qt_common.cpp +++ b/src/qt_common/qt_common.cpp @@ -3,11 +3,14 @@ #include "qt_common.h" #include "common/fs/fs.h" +#include "common/fs/ryujinx_compat.h" #include <QGuiApplication> #include <QStringLiteral> #include "common/logging/log.h" #include "core/frontend/emu_window.h" +#include "qt_common/abstract/frontend.h" +#include "qt_common/qt_string_lookup.h" #include <QFile> @@ -33,7 +36,8 @@ std::unique_ptr<Core::System> system = nullptr; std::shared_ptr<FileSys::RealVfsFilesystem> vfs = nullptr; std::unique_ptr<FileSys::ManualContentProvider> provider = nullptr; -Core::Frontend::WindowSystemType GetWindowSystemType() { +Core::Frontend::WindowSystemType GetWindowSystemType() +{ // Determine WSI type based on Qt platform. QString platform_name = QGuiApplication::platformName(); if (platform_name == QStringLiteral("windows")) @@ -101,9 +105,11 @@ void Init(QObject* root) provider = std::make_unique<FileSys::ManualContentProvider>(); } -std::filesystem::path GetEdenCommand() { +std::filesystem::path GetEdenCommand() +{ std::filesystem::path command; + // TODO: flatpak? QString appimage = QString::fromLocal8Bit(getenv("APPIMAGE")); if (!appimage.isEmpty()) { command = std::filesystem::path{appimage.toStdString()}; diff --git a/src/qt_common/qt_string_lookup.h b/src/qt_common/qt_string_lookup.h index 7756bcdaf2..42d71e6f9d 100644 --- a/src/qt_common/qt_string_lookup.h +++ b/src/qt_common/qt_string_lookup.h @@ -42,9 +42,18 @@ enum StringKey { MigrationTooltipClearOld, MigrationTooltipLinkOld, + // ryujinx + KvdbNonexistent, + KvdbNoHeader, + KvdbInvalidMagic, + KvdbMisaligned, + KvdbNoImens, + RyujinxNoSaveId, + }; -static const frozen::map<StringKey, frozen::string, 21> strings = { +static const constexpr frozen::map<StringKey, frozen::string, 27> strings = { + // 0-4 {SavesTooltip, QT_TR_NOOP("Contains game save data. DO NOT REMOVE UNLESS YOU KNOW WHAT YOU'RE DOING!")}, {ShadersTooltip, @@ -54,6 +63,7 @@ static const frozen::map<StringKey, frozen::string, 21> strings = { {ModsTooltip, QT_TR_NOOP("Contains game mods, patches, and cheats.")}, // Key install + // 5-9 {KeyInstallSuccess, QT_TR_NOOP("Decryption Keys were successfully installed")}, {KeyInstallInvalidDir, QT_TR_NOOP("Unable to read key directory, aborting")}, {KeyInstallErrorFailedCopy, QT_TR_NOOP("One or more keys failed to copy.")}, @@ -65,6 +75,7 @@ static const frozen::map<StringKey, frozen::string, 21> strings = { "re-dump keys.")}, // fw install + // 10-14 {FwInstallSuccess, QT_TR_NOOP("Successfully installed firmware version %1")}, {FwInstallNoNCAs, QT_TR_NOOP("Unable to locate potential firmware NCA files")}, {FwInstallFailedDelete, QT_TR_NOOP("Failed to delete one or more firmware files.")}, @@ -75,6 +86,7 @@ static const frozen::map<StringKey, frozen::string, 21> strings = { "Eden or re-install firmware.")}, // migrator + // 15-20 {MigrationPromptPrefix, QT_TR_NOOP("Eden has detected user data for the following emulators:")}, {MigrationPrompt, QT_TR_NOOP("Would you like to migrate your data for use in Eden?\n" @@ -93,6 +105,15 @@ static const frozen::map<StringKey, frozen::string, 21> strings = { {MigrationTooltipLinkOld, QT_TR_NOOP("Creates a filesystem link between the old directory and Eden directory.\n" "This is recommended if you want to share data between emulators.")}, + + // why am I writing these comments again + // 21-26 + {KvdbNonexistent, QT_TR_NOOP("Ryujinx title database does not exist.")}, + {KvdbNoHeader, QT_TR_NOOP("Invalid header on Ryujinx title database.")}, + {KvdbInvalidMagic, QT_TR_NOOP("Invalid magic header on Ryujinx title database.")}, + {KvdbMisaligned, QT_TR_NOOP("Invalid byte alignment on Ryujinx title database.")}, + {KvdbNoImens, QT_TR_NOOP("No items found in Ryujinx title database.")}, + {RyujinxNoSaveId, QT_TR_NOOP("Title %1 not found in Ryujinx title database.")}, }; static inline const QString Lookup(StringKey key) diff --git a/src/qt_common/util/content.cpp b/src/qt_common/util/content.cpp index 4360efeef0..df4435f567 100644 --- a/src/qt_common/util/content.cpp +++ b/src/qt_common/util/content.cpp @@ -11,7 +11,7 @@ #include "frontend_common/firmware_manager.h" #include "compress.h" -#include "qt_common/abstract/qt_frontend_util.h" +#include "qt_common/abstract/frontend.h" #include "qt_common/abstract/qt_progress_dialog.h" #include "qt_common/qt_common.h" @@ -404,7 +404,7 @@ void ExportDataDir(FrontendCommon::DataManager::DataDir data_dir, std::function<void()> callback) { using namespace QtCommon::Frontend; - const std::string dir = FrontendCommon::DataManager::GetDataDir(data_dir, user_id); + const std::string dir = FrontendCommon::DataManager::GetDataDirString(data_dir, user_id); const QString zip_dump_location = GetSaveFileName(tr("Select Export Location"), tr("%1.zip").arg(name), @@ -468,7 +468,7 @@ void ImportDataDir(FrontendCommon::DataManager::DataDir data_dir, const std::string& user_id, std::function<void()> callback) { - const std::string dir = FrontendCommon::DataManager::GetDataDir(data_dir, user_id); + const std::string dir = FrontendCommon::DataManager::GetDataDirString(data_dir, user_id); using namespace QtCommon::Frontend; diff --git a/src/qt_common/util/content.h b/src/qt_common/util/content.h index d1384546e1..4102737fb1 100644 --- a/src/qt_common/util/content.h +++ b/src/qt_common/util/content.h @@ -25,7 +25,8 @@ enum class FirmwareInstallResult { inline const QString GetFirmwareInstallResultString(FirmwareInstallResult result) { - return QtCommon::StringLookup::Lookup(static_cast<StringLookup::StringKey>((int) result + (int) QtCommon::StringLookup::FwInstallSuccess)); + return QtCommon::StringLookup::Lookup(static_cast<StringLookup::StringKey>( + (int) result + (int) QtCommon::StringLookup::FwInstallSuccess)); } /** @@ -36,7 +37,8 @@ inline const QString GetFirmwareInstallResultString(FirmwareInstallResult result inline const QString GetKeyInstallResultString(FirmwareManager::KeyInstallResult result) { // this can probably be made into a common function of sorts - return QtCommon::StringLookup::Lookup(static_cast<StringLookup::StringKey>((int) result + (int) QtCommon::StringLookup::KeyInstallSuccess)); + return QtCommon::StringLookup::Lookup(static_cast<StringLookup::StringKey>( + (int) result + (int) QtCommon::StringLookup::KeyInstallSuccess)); } void InstallFirmware(const QString &location, bool recursive); diff --git a/src/qt_common/util/fs.cpp b/src/qt_common/util/fs.cpp new file mode 100644 index 0000000000..da59a4e675 --- /dev/null +++ b/src/qt_common/util/fs.cpp @@ -0,0 +1,130 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#include <filesystem> +#include "fs.h" +#include "common/fs/ryujinx_compat.h" +#include "common/fs/symlink.h" +#include "frontend_common/data_manager.h" +#include "qt_common/abstract/frontend.h" +#include "qt_common/qt_string_lookup.h" + +namespace fs = std::filesystem; + +namespace QtCommon::FS { + +void LinkRyujinx(std::filesystem::path &from, std::filesystem::path &to) +{ + std::error_code ec; + + // "ignore" errors--if the dir fails to be deleted, error handling later will handle it + fs::remove_all(to, ec); + + if (Common::FS::CreateSymlink(from, to)) { + QtCommon::Frontend::Information(tr("Linked Save Data"), tr("Save data has been linked.")); + } else { + QtCommon::Frontend::Critical( + tr("Failed to link save data"), + tr("Could not link directory:\n\t%1\nTo:\n\t%2").arg(QString::fromStdString(from.string()), QString::fromStdString(to.string()))); + } +} + +bool CheckUnlink(const fs::path &eden_dir, const fs::path &ryu_dir) +{ + bool eden_link = Common::FS::IsSymlink(eden_dir); + bool ryu_link = Common::FS::IsSymlink(ryu_dir); + + if (!(eden_link || ryu_link)) + return false; + + auto result = QtCommon::Frontend::Warning( + tr("Already Linked"), + tr("This title is already linked to Ryujinx. Would you like to unlink it?"), + QtCommon::Frontend::StandardButton::Yes | QtCommon::Frontend::StandardButton::No); + + if (result != QtCommon::Frontend::StandardButton::Yes) + return true; + + fs::path linked; + fs::path orig; + + if (eden_link) { + linked = eden_dir; + orig = ryu_dir; + } else { + linked = ryu_dir; + orig = eden_dir; + } + + // first cleanup the symlink/junction, + try { + // NB: do NOT use remove_all, as Windows treats this as a remove_all to the target, + // NOT the junction + fs::remove(linked); + } catch (std::exception &e) { + QtCommon::Frontend::Critical( + tr("Failed to unlink old directory"), + tr("OS returned error: %1").arg(QString::fromStdString(e.what()))); + return true; + } + + // then COPY the other dir + try { + fs::copy(orig, linked, fs::copy_options::recursive); + } catch (std::exception &e) { + QtCommon::Frontend::Critical( + tr("Failed to copy save data"), + tr("OS returned error: %1").arg(QString::fromStdString(e.what()))); + } + + QtCommon::Frontend::Information( + tr("Unlink Successful"), + tr("Successfully unlinked Ryujinx save data. Save data has been kept intact.")); + + return true; +} + +u64 GetRyujinxSaveID(const u64 &program_id) +{ + auto path = Common::FS::GetKvdbPath(); + std::vector<Common::FS::IMEN> imens; + Common::FS::IMENReadResult res = Common::FS::ReadKvdb(path, imens); + + if (res == Common::FS::IMENReadResult::Success) { + // TODO: this can probably be done with std::find_if but I'm lazy + for (const Common::FS::IMEN &imen : imens) { + if (imen.title_id == program_id) + return imen.save_id; + } + + QtCommon::Frontend::Critical( + tr("Could not find Ryujinx save data"), + StringLookup::Lookup(StringLookup::RyujinxNoSaveId).arg(program_id, 0, 16)); + } else { + // TODO: make this long thing a function or something + QString caption = StringLookup::Lookup( + static_cast<StringLookup::StringKey>((int) res + (int) StringLookup::KvdbNonexistent)); + QtCommon::Frontend::Critical(tr("Could not find Ryujinx save data"), caption); + } + + return -1; +} + +std::optional<std::pair<fs::path, fs::path> > GetEmuPaths( + const u64 program_id, const u64 save_id, const std::string &user_id) +{ + fs::path ryu_dir = Common::FS::GetRyuSavePath(save_id); + + if (user_id.empty()) + return std::nullopt; + + std::string hex_program = fmt::format("{:016X}", program_id); + fs::path eden_dir + = FrontendCommon::DataManager::GetDataDir(FrontendCommon::DataManager::DataDir::Saves, + user_id) + / hex_program; + + return std::make_pair(eden_dir, ryu_dir); +} + +} // namespace QtCommon::FS diff --git a/src/qt_common/util/fs.h b/src/qt_common/util/fs.h new file mode 100644 index 0000000000..ee8859a2e5 --- /dev/null +++ b/src/qt_common/util/fs.h @@ -0,0 +1,22 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "common/common_types.h" +#include <filesystem> +#include <optional> + +#pragma once + +namespace QtCommon::FS { + +void LinkRyujinx(std::filesystem::path &from, std::filesystem::path &to); +u64 GetRyujinxSaveID(const u64 &program_id); + +/// @brief {eden, ryu} +std::optional<std::pair<std::filesystem::path, std::filesystem::path>> GetEmuPaths( + const u64 program_id, const u64 save_id, const std::string &user_id); + +/// returns FALSE if the dirs are NOT linked +bool CheckUnlink(const std::filesystem::path &eden_dir, const std::filesystem::path &ryu_dir); + +} // namespace QtCommon::FS diff --git a/src/qt_common/util/game.cpp b/src/qt_common/util/game.cpp index e5018d24cb..e34a388993 100644 --- a/src/qt_common/util/game.cpp +++ b/src/qt_common/util/game.cpp @@ -8,7 +8,7 @@ #include "core/file_sys/savedata_factory.h" #include "core/hle/service/am/am_types.h" #include "frontend_common/content_manager.h" -#include "qt_common/abstract/qt_frontend_util.h" +#include "qt_common/abstract/frontend.h" #include "qt_common/config/uisettings.h" #include "qt_common/qt_common.h" #include "yuzu/util/util.h" diff --git a/src/qt_common/util/path.cpp b/src/qt_common/util/path.cpp index 93e8007eb9..73689058c6 100644 --- a/src/qt_common/util/path.cpp +++ b/src/qt_common/util/path.cpp @@ -7,7 +7,7 @@ #include <QUrl> #include "common/fs/fs.h" #include "common/fs/path_util.h" -#include "qt_common/abstract/qt_frontend_util.h" +#include "qt_common/abstract/frontend.h" #include <fmt/format.h> namespace QtCommon::Path { |
