From ec3cfc01c1d87b038c72f162cefaa631cb788981 Mon Sep 17 00:00:00 2001 From: "Admiral H. Curtiss" Date: Thu, 9 Jun 2022 00:33:30 +0200 Subject: [PATCH] DiscIO/DirectoryBlob: Add callback to modify sys files before they're added to the disc. --- Source/Core/Core/Boot/Boot.cpp | 4 ++ Source/Core/DiscIO/DirectoryBlob.cpp | 67 ++++++++++++++++++++++++---- Source/Core/DiscIO/DirectoryBlob.h | 18 +++++--- 3 files changed, 74 insertions(+), 15 deletions(-) diff --git a/Source/Core/Core/Boot/Boot.cpp b/Source/Core/Core/Boot/Boot.cpp index 94b66bd687..ba1e901d61 100644 --- a/Source/Core/Core/Boot/Boot.cpp +++ b/Source/Core/Core/Boot/Boot.cpp @@ -700,6 +700,10 @@ void AddRiivolutionPatches(BootParameters* boot_params, auto& disc = std::get(boot_params->parameters); disc.volume = DiscIO::CreateDisc(DiscIO::DirectoryBlobReader::Create( std::move(disc.volume), + [&](std::vector* fst) { + DiscIO::Riivolution::ApplyPatchesToFiles( + riivolution_patches, DiscIO::Riivolution::PatchIndex::DolphinSysFiles, fst, nullptr); + }, [&](std::vector* fst, DiscIO::FSTBuilderNode* dol_node) { DiscIO::Riivolution::ApplyPatchesToFiles( riivolution_patches, DiscIO::Riivolution::PatchIndex::FileSystem, fst, dol_node); diff --git a/Source/Core/DiscIO/DirectoryBlob.cpp b/Source/Core/DiscIO/DirectoryBlob.cpp index c8facd37de..7decaac2e3 100644 --- a/Source/Core/DiscIO/DirectoryBlob.cpp +++ b/Source/Core/DiscIO/DirectoryBlob.cpp @@ -362,6 +362,7 @@ std::unique_ptr DirectoryBlobReader::Create(const std::stri std::unique_ptr DirectoryBlobReader::Create( std::unique_ptr volume, + const std::function* fst_nodes)>& sys_callback, const std::function* fst_nodes, FSTBuilderNode* dol_node)>& fst_callback) { @@ -369,7 +370,7 @@ std::unique_ptr DirectoryBlobReader::Create( return nullptr; return std::unique_ptr( - new DirectoryBlobReader(std::move(volume), fst_callback)); + new DirectoryBlobReader(std::move(volume), sys_callback, fst_callback)); } DirectoryBlobReader::DirectoryBlobReader(const std::string& game_partition_root, @@ -418,12 +419,14 @@ DirectoryBlobReader::DirectoryBlobReader(const std::string& game_partition_root, DirectoryBlobReader::DirectoryBlobReader( std::unique_ptr volume, + const std::function* fst_nodes)>& sys_callback, const std::function* fst_nodes, FSTBuilderNode* dol_node)>& fst_callback) : m_encryption_cache(this), m_wrapped_volume(std::move(volume)) { - DirectoryBlobPartition game_partition( - m_wrapped_volume.get(), m_wrapped_volume->GetGamePartition(), std::nullopt, fst_callback); + DirectoryBlobPartition game_partition(m_wrapped_volume.get(), + m_wrapped_volume->GetGamePartition(), std::nullopt, + sys_callback, fst_callback); m_is_wii = game_partition.IsWii(); if (!m_is_wii) @@ -463,7 +466,7 @@ DirectoryBlobReader::DirectoryBlobReader( if (type) { partitions.emplace_back( - DirectoryBlobPartition(m_wrapped_volume.get(), partition, m_is_wii, nullptr), + DirectoryBlobPartition(m_wrapped_volume.get(), partition, m_is_wii, nullptr, nullptr), static_cast(*type)); } } @@ -820,32 +823,80 @@ DirectoryBlobPartition::DirectoryBlobPartition(const std::string& root_directory BuildFSTFromFolder(m_root_directory + "files/", fst_address); } +static void FillSingleFileNode(FSTBuilderNode* node, std::vector data) +{ + std::vector contents; + const size_t size = data.size(); + contents.emplace_back(BuilderContentSource{0, size, ContentByteVector{std::move(data)}}); + node->m_size = size; + node->m_content = std::move(contents); +} + +static FSTBuilderNode BuildSingleFileNode(std::string filename, std::vector data, + void* userdata) +{ + FSTBuilderNode node{std::move(filename), 0, {}, userdata}; + FillSingleFileNode(&node, std::move(data)); + return node; +} + +static std::vector ExtractNodeToVector(std::vector* nodes, void* userdata) +{ + std::vector data; + const auto it = + std::find_if(nodes->begin(), nodes->end(), [&userdata](const FSTBuilderNode& node) { + return node.m_user_data == userdata; + }); + if (it == nodes->end() || !it->IsFile()) + return data; + + DiscContentContainer tmp; + for (auto& content : it->GetFileContent()) + tmp.Add(content.m_offset, content.m_size, std::move(content.m_source)); + data.resize(it->m_size); + tmp.Read(0, it->m_size, data.data()); + return data; +} + DirectoryBlobPartition::DirectoryBlobPartition( DiscIO::VolumeDisc* volume, const DiscIO::Partition& partition, std::optional is_wii, + const std::function* fst_nodes)>& sys_callback, const std::function* fst_nodes, FSTBuilderNode* dol_node)>& fst_callback) : m_wrapped_partition(partition) { + std::vector sys_nodes; + std::vector disc_header(DISCHEADER_SIZE); if (!volume->Read(DISCHEADER_ADDRESS, DISCHEADER_SIZE, disc_header.data(), partition)) disc_header.clear(); - SetDiscHeader(std::move(disc_header)); - SetDiscType(is_wii); + sys_nodes.emplace_back(BuildSingleFileNode("boot.bin", std::move(disc_header), &m_disc_header)); std::vector bi2(BI2_SIZE); if (!volume->Read(BI2_ADDRESS, BI2_SIZE, bi2.data(), partition)) bi2.clear(); - SetBI2(std::move(bi2)); + sys_nodes.emplace_back(BuildSingleFileNode("bi2.bin", std::move(bi2), &m_bi2)); std::vector apploader; const auto apploader_size = GetApploaderSize(*volume, partition); + auto& apploader_node = + sys_nodes.emplace_back(FSTBuilderNode{"apploader.img", 0, {}, &m_apploader}); if (apploader_size) { apploader.resize(*apploader_size); if (!volume->Read(APPLOADER_ADDRESS, *apploader_size, apploader.data(), partition)) apploader.clear(); + FillSingleFileNode(&apploader_node, std::move(apploader)); } - const u64 new_dol_address = SetApploader(apploader, "apploader"); + + if (sys_callback) + sys_callback(&sys_nodes); + + SetDiscHeader(ExtractNodeToVector(&sys_nodes, &m_disc_header)); + SetDiscType(is_wii); + SetBI2(ExtractNodeToVector(&sys_nodes, &m_bi2)); + const u64 new_dol_address = + SetApploader(ExtractNodeToVector(&sys_nodes, &m_apploader), "apploader"); FSTBuilderNode dol_node{"main.dol", 0, {}}; const auto dol_offset = GetBootDOLOffset(*volume, partition); diff --git a/Source/Core/DiscIO/DirectoryBlob.h b/Source/Core/DiscIO/DirectoryBlob.h index 31e3650b08..a06e60688f 100644 --- a/Source/Core/DiscIO/DirectoryBlob.h +++ b/Source/Core/DiscIO/DirectoryBlob.h @@ -190,10 +190,11 @@ class DirectoryBlobPartition public: DirectoryBlobPartition() = default; DirectoryBlobPartition(const std::string& root_directory, std::optional is_wii); - DirectoryBlobPartition(DiscIO::VolumeDisc* volume, const DiscIO::Partition& partition, - std::optional is_wii, - const std::function* fst_nodes, - FSTBuilderNode* dol_node)>& fst_callback); + DirectoryBlobPartition( + DiscIO::VolumeDisc* volume, const DiscIO::Partition& partition, std::optional is_wii, + const std::function* fst_nodes)>& sys_callback, + const std::function* fst_nodes, FSTBuilderNode* dol_node)>& + fst_callback); // We do not allow copying, because it might mess up the pointers inside DiscContents DirectoryBlobPartition(const DirectoryBlobPartition&) = delete; @@ -265,6 +266,7 @@ public: static std::unique_ptr Create(const std::string& dol_path); static std::unique_ptr Create( std::unique_ptr volume, + const std::function* fst_nodes)>& sys_callback, const std::function* fst_nodes, FSTBuilderNode* dol_node)>& fst_callback); @@ -303,9 +305,11 @@ private: explicit DirectoryBlobReader(const std::string& game_partition_root, const std::string& true_root); - explicit DirectoryBlobReader(std::unique_ptr volume, - const std::function* fst_nodes, - FSTBuilderNode* dol_node)>& fst_callback); + explicit DirectoryBlobReader( + std::unique_ptr volume, + const std::function* fst_nodes)>& sys_callback, + const std::function* fst_nodes, FSTBuilderNode* dol_node)>& + fst_callback); const DirectoryBlobPartition* GetPartition(u64 offset, u64 size, u64 partition_data_offset) const;