patch_manager: Make use of type aliases

We can use these to avoid typing the same type redundantly. This way, if
these ever change, only a single location needs to be modified.
This commit is contained in:
Lioncash 2020-09-14 19:09:49 -04:00
parent 637ab14ae6
commit a4392c24cf
2 changed files with 79 additions and 69 deletions

View file

@ -73,6 +73,44 @@ VirtualDir FindSubdirectoryCaseless(const VirtualDir dir, std::string_view name)
return nullptr; return nullptr;
#endif #endif
} }
std::optional<std::vector<Core::Memory::CheatEntry>> ReadCheatFileFromFolder(
const Core::System& system, u64 title_id, const PatchManager::BuildID& build_id_,
const VirtualDir& base_path, bool upper) {
const auto build_id_raw = Common::HexToString(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<u8> 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;
}
Core::Memory::TextCheatParser parser;
return parser.Parse(system,
std::string_view(reinterpret_cast<const char*>(data.data()), data.size()));
}
void AppendCommaIfNotEmpty(std::string& to, std::string_view with) {
if (to.empty()) {
to += with;
} else {
to += ", ";
to += with;
}
}
bool IsDirValidAndNonEmpty(const VirtualDir& dir) {
return dir != nullptr && (!dir->GetFiles().empty() || !dir->GetSubdirectories().empty());
}
} // Anonymous namespace } // Anonymous namespace
PatchManager::PatchManager(u64 title_id) : title_id(title_id) {} PatchManager::PatchManager(u64 title_id) : title_id(title_id) {}
@ -255,7 +293,7 @@ std::vector<u8> PatchManager::PatchNSO(const std::vector<u8>& nso, const std::st
return out; return out;
} }
bool PatchManager::HasNSOPatch(const std::array<u8, 32>& build_id_) const { bool PatchManager::HasNSOPatch(const BuildID& build_id_) const {
const auto build_id_raw = Common::HexToString(build_id_); const auto build_id_raw = Common::HexToString(build_id_);
const auto build_id = build_id_raw.substr(0, build_id_raw.find_last_not_of('0') + 1); const auto build_id = build_id_raw.substr(0, build_id_raw.find_last_not_of('0') + 1);
@ -275,36 +313,8 @@ bool PatchManager::HasNSOPatch(const std::array<u8, 32>& build_id_) const {
return !CollectPatches(patch_dirs, build_id).empty(); return !CollectPatches(patch_dirs, build_id).empty();
} }
namespace {
std::optional<std::vector<Core::Memory::CheatEntry>> ReadCheatFileFromFolder(
const Core::System& system, u64 title_id, const std::array<u8, 0x20>& build_id_,
const VirtualDir& base_path, bool upper) {
const auto build_id_raw = Common::HexToString(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<u8> 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;
}
Core::Memory::TextCheatParser parser;
return parser.Parse(system,
std::string_view(reinterpret_cast<const char*>(data.data()), data.size()));
}
} // Anonymous namespace
std::vector<Core::Memory::CheatEntry> PatchManager::CreateCheatList( std::vector<Core::Memory::CheatEntry> PatchManager::CreateCheatList(
const Core::System& system, const std::array<u8, 32>& build_id_) const { const Core::System& system, const BuildID& build_id_) const {
const auto load_dir = system.GetFileSystemController().GetModificationLoadRoot(title_id); const auto load_dir = system.GetFileSystemController().GetModificationLoadRoot(title_id);
if (load_dir == nullptr) { if (load_dir == nullptr) {
LOG_ERROR(Loader, "Cannot load mods for invalid title_id={:016X}", title_id); LOG_ERROR(Loader, "Cannot load mods for invalid title_id={:016X}", title_id);
@ -445,21 +455,11 @@ VirtualFile PatchManager::PatchRomFS(VirtualFile romfs, u64 ivfc_offset, Content
return romfs; return romfs;
} }
static void AppendCommaIfNotEmpty(std::string& to, const std::string& with) { PatchManager::PatchVersionNames PatchManager::GetPatchVersionNames(VirtualFile update_raw) const {
if (to.empty()) if (title_id == 0) {
to += with;
else
to += ", " + with;
}
static bool IsDirValidAndNonEmpty(const VirtualDir& dir) {
return dir != nullptr && (!dir->GetFiles().empty() || !dir->GetSubdirectories().empty());
}
std::map<std::string, std::string, std::less<>> PatchManager::GetPatchVersionNames(
VirtualFile update_raw) const {
if (title_id == 0)
return {}; return {};
}
std::map<std::string, std::string, std::less<>> out; std::map<std::string, std::string, std::less<>> out;
const auto& installed = Core::System::GetInstance().GetContentProvider(); const auto& installed = Core::System::GetInstance().GetContentProvider();
const auto& disabled = Settings::values.disabled_addons[title_id]; const auto& disabled = Settings::values.disabled_addons[title_id];
@ -571,41 +571,47 @@ std::optional<u32> PatchManager::GetGameVersion() const {
return installed.GetEntryVersion(title_id); return installed.GetEntryVersion(title_id);
} }
std::pair<std::unique_ptr<NACP>, VirtualFile> PatchManager::GetControlMetadata() const { PatchManager::Metadata PatchManager::GetControlMetadata() const {
const auto& installed = Core::System::GetInstance().GetContentProvider(); const auto& installed = Core::System::GetInstance().GetContentProvider();
const auto base_control_nca = installed.GetEntry(title_id, ContentRecordType::Control); const auto base_control_nca = installed.GetEntry(title_id, ContentRecordType::Control);
if (base_control_nca == nullptr) if (base_control_nca == nullptr) {
return {}; return {};
}
return ParseControlNCA(*base_control_nca); return ParseControlNCA(*base_control_nca);
} }
std::pair<std::unique_ptr<NACP>, VirtualFile> PatchManager::ParseControlNCA(const NCA& nca) const { PatchManager::Metadata PatchManager::ParseControlNCA(const NCA& nca) const {
const auto base_romfs = nca.GetRomFS(); const auto base_romfs = nca.GetRomFS();
if (base_romfs == nullptr) if (base_romfs == nullptr) {
return {}; return {};
}
const auto romfs = PatchRomFS(base_romfs, nca.GetBaseIVFCOffset(), ContentRecordType::Control); const auto romfs = PatchRomFS(base_romfs, nca.GetBaseIVFCOffset(), ContentRecordType::Control);
if (romfs == nullptr) if (romfs == nullptr) {
return {}; return {};
}
const auto extracted = ExtractRomFS(romfs); const auto extracted = ExtractRomFS(romfs);
if (extracted == nullptr) if (extracted == nullptr) {
return {}; return {};
}
auto nacp_file = extracted->GetFile("control.nacp"); auto nacp_file = extracted->GetFile("control.nacp");
if (nacp_file == nullptr) if (nacp_file == nullptr) {
nacp_file = extracted->GetFile("Control.nacp"); nacp_file = extracted->GetFile("Control.nacp");
}
auto nacp = nacp_file == nullptr ? nullptr : std::make_unique<NACP>(nacp_file); auto nacp = nacp_file == nullptr ? nullptr : std::make_unique<NACP>(nacp_file);
VirtualFile icon_file; VirtualFile icon_file;
for (const auto& language : FileSys::LANGUAGE_NAMES) { for (const auto& language : FileSys::LANGUAGE_NAMES) {
icon_file = extracted->GetFile("icon_" + std::string(language) + ".dat"); icon_file = extracted->GetFile(std::string("icon_").append(language).append(".dat"));
if (icon_file != nullptr) if (icon_file != nullptr) {
break; break;
} }
}
return {std::move(nacp), icon_file}; return {std::move(nacp), icon_file};
} }

View file

@ -25,54 +25,58 @@ class NACP;
// A centralized class to manage patches to games. // A centralized class to manage patches to games.
class PatchManager { class PatchManager {
public: public:
using BuildID = std::array<u8, 0x20>;
using Metadata = std::pair<std::unique_ptr<NACP>, VirtualFile>;
using PatchVersionNames = std::map<std::string, std::string, std::less<>>;
explicit PatchManager(u64 title_id); explicit PatchManager(u64 title_id);
~PatchManager(); ~PatchManager();
u64 GetTitleID() const; [[nodiscard]] u64 GetTitleID() const;
// Currently tracked ExeFS patches: // Currently tracked ExeFS patches:
// - Game Updates // - Game Updates
VirtualDir PatchExeFS(VirtualDir exefs) const; [[nodiscard]] VirtualDir PatchExeFS(VirtualDir exefs) const;
// Currently tracked NSO patches: // Currently tracked NSO patches:
// - IPS // - IPS
// - IPSwitch // - IPSwitch
std::vector<u8> PatchNSO(const std::vector<u8>& nso, const std::string& name) const; [[nodiscard]] std::vector<u8> PatchNSO(const std::vector<u8>& nso,
const std::string& name) const;
// Checks to see if PatchNSO() will have any effect given the NSO's build ID. // Checks to see if PatchNSO() will have any effect given the NSO's build ID.
// Used to prevent expensive copies in NSO loader. // Used to prevent expensive copies in NSO loader.
bool HasNSOPatch(const std::array<u8, 0x20>& build_id) const; [[nodiscard]] bool HasNSOPatch(const BuildID& build_id) const;
// Creates a CheatList object with all // Creates a CheatList object with all
std::vector<Core::Memory::CheatEntry> CreateCheatList( [[nodiscard]] std::vector<Core::Memory::CheatEntry> CreateCheatList(
const Core::System& system, const std::array<u8, 0x20>& build_id) const; const Core::System& system, const BuildID& build_id) const;
// Currently tracked RomFS patches: // Currently tracked RomFS patches:
// - Game Updates // - Game Updates
// - LayeredFS // - LayeredFS
VirtualFile PatchRomFS(VirtualFile base, u64 ivfc_offset, [[nodiscard]] VirtualFile PatchRomFS(VirtualFile base, u64 ivfc_offset,
ContentRecordType type = ContentRecordType::Program, ContentRecordType type = ContentRecordType::Program,
VirtualFile update_raw = nullptr) const; VirtualFile update_raw = nullptr) const;
// Returns a vector of pairs between patch names and patch versions. // Returns a vector of pairs between patch names and patch versions.
// i.e. Update 3.2.2 will return {"Update", "3.2.2"} // i.e. Update 3.2.2 will return {"Update", "3.2.2"}
std::map<std::string, std::string, std::less<>> GetPatchVersionNames( [[nodiscard]] PatchVersionNames GetPatchVersionNames(VirtualFile update_raw = nullptr) const;
VirtualFile update_raw = nullptr) const;
// If the game update exists, returns the u32 version field in its Meta-type NCA. If that fails, // If the game update exists, returns the u32 version field in its Meta-type NCA. If that fails,
// it will fallback to the Meta-type NCA of the base game. If that fails, the result will be // it will fallback to the Meta-type NCA of the base game. If that fails, the result will be
// std::nullopt // std::nullopt
std::optional<u32> GetGameVersion() const; [[nodiscard]] std::optional<u32> GetGameVersion() const;
// Given title_id of the program, attempts to get the control data of the update and parse // Given title_id of the program, attempts to get the control data of the update and parse
// it, falling back to the base control data. // it, falling back to the base control data.
std::pair<std::unique_ptr<NACP>, VirtualFile> GetControlMetadata() const; [[nodiscard]] Metadata GetControlMetadata() const;
// Version of GetControlMetadata that takes an arbitrary NCA // Version of GetControlMetadata that takes an arbitrary NCA
std::pair<std::unique_ptr<NACP>, VirtualFile> ParseControlNCA(const NCA& nca) const; [[nodiscard]] Metadata ParseControlNCA(const NCA& nca) const;
private: private:
std::vector<VirtualFile> CollectPatches(const std::vector<VirtualDir>& patch_dirs, [[nodiscard]] std::vector<VirtualFile> CollectPatches(const std::vector<VirtualDir>& patch_dirs,
const std::string& build_id) const; const std::string& build_id) const;
u64 title_id; u64 title_id;