From c5091bfe00c241b6432367aeaea020d4e3d40d28 Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Sat, 22 Dec 2018 21:28:56 -0500 Subject: [PATCH] patch_manager: Add support for loading cheats lists Uses load///cheats as root dir, file name is all upper or lower hex first 8 bytes build ID. --- src/core/file_sys/patch_manager.cpp | 52 +++++++++++++++++++++++++++++ src/core/file_sys/patch_manager.h | 4 +++ 2 files changed, 56 insertions(+) diff --git a/src/core/file_sys/patch_manager.cpp b/src/core/file_sys/patch_manager.cpp index 61706966e..f0fb28e2f 100644 --- a/src/core/file_sys/patch_manager.cpp +++ b/src/core/file_sys/patch_manager.cpp @@ -7,6 +7,7 @@ #include #include +#include "common/file_util.h" #include "common/hex_util.h" #include "common/logging/log.h" #include "core/file_sys/content_archive.h" @@ -232,6 +233,57 @@ bool PatchManager::HasNSOPatch(const std::array& build_id_) const { return !CollectPatches(patch_dirs, build_id).empty(); } +static std::optional ReadCheatFileFromFolder(u64 title_id, + const std::array& build_id_, + const VirtualDir& base_path, bool upper) { + const auto build_id_raw = Common::HexArrayToString(build_id_, upper); + const auto build_id = build_id_raw.substr(0, sizeof(u64) * 2); + const auto file = base_path->GetFile(fmt::format("{}.txt", build_id)); + + if (file == nullptr) { + LOG_INFO(Common_Filesystem, "No cheats file found for title_id={:016X}, build_id={}", + title_id, build_id); + return std::nullopt; + } + + std::vector data(file->GetSize()); + if (file->Read(data.data(), data.size()) != data.size()) { + LOG_INFO(Common_Filesystem, "Failed to read cheats file for title_id={:016X}, build_id={}", + title_id, build_id); + return std::nullopt; + } + + TextCheatParser parser; + return parser.Parse(data); +} + +std::vector PatchManager::CreateCheatList(const std::array& build_id_) const { + std::vector out; + + const auto load_dir = Service::FileSystem::GetModificationLoadRoot(title_id); + auto patch_dirs = load_dir->GetSubdirectories(); + std::sort(patch_dirs.begin(), patch_dirs.end(), + [](const VirtualDir& l, const VirtualDir& r) { return l->GetName() < r->GetName(); }); + + out.reserve(patch_dirs.size()); + for (const auto& subdir : patch_dirs) { + auto cheats_dir = subdir->GetSubdirectory("cheats"); + if (cheats_dir != nullptr) { + auto res = ReadCheatFileFromFolder(title_id, build_id_, cheats_dir, true); + if (res.has_value()) { + out.push_back(std::move(*res)); + continue; + } + + res = ReadCheatFileFromFolder(title_id, build_id_, cheats_dir, false); + if (res.has_value()) + out.push_back(std::move(*res)); + } + } + + return out; +} + static void ApplyLayeredFS(VirtualFile& romfs, u64 title_id, ContentRecordType type) { const auto load_dir = Service::FileSystem::GetModificationLoadRoot(title_id); if ((type != ContentRecordType::Program && type != ContentRecordType::Data) || diff --git a/src/core/file_sys/patch_manager.h b/src/core/file_sys/patch_manager.h index b8a1652fd..3e3ac6aca 100644 --- a/src/core/file_sys/patch_manager.h +++ b/src/core/file_sys/patch_manager.h @@ -8,6 +8,7 @@ #include #include #include "common/common_types.h" +#include "core/file_sys/cheat_engine.h" #include "core/file_sys/nca_metadata.h" #include "core/file_sys/vfs.h" @@ -45,6 +46,9 @@ public: // Used to prevent expensive copies in NSO loader. bool HasNSOPatch(const std::array& build_id) const; + // Creates a CheatList object with all + std::vector CreateCheatList(const std::array& build_id) const; + // Currently tracked RomFS patches: // - Game Updates // - LayeredFS