From e3f1de023f44b2cba8a2cd6d4a5faa4c665329dc Mon Sep 17 00:00:00 2001 From: "Admiral H. Curtiss" Date: Wed, 22 Sep 2021 04:51:16 +0200 Subject: [PATCH] DiscIO/DirectoryBlob: Add a callback that allows patching the main.dol and FST of the game partition during blob construction. --- Source/Core/DiscIO/DirectoryBlob.cpp | 45 +++++++++++++++++----------- Source/Core/DiscIO/DirectoryBlob.h | 14 +++++++-- 2 files changed, 39 insertions(+), 20 deletions(-) diff --git a/Source/Core/DiscIO/DirectoryBlob.cpp b/Source/Core/DiscIO/DirectoryBlob.cpp index b41a00cf66..80bd173ae0 100644 --- a/Source/Core/DiscIO/DirectoryBlob.cpp +++ b/Source/Core/DiscIO/DirectoryBlob.cpp @@ -356,13 +356,16 @@ std::unique_ptr DirectoryBlobReader::Create(const std::stri return std::unique_ptr(new DirectoryBlobReader(partition_root, true_root)); } -std::unique_ptr -DirectoryBlobReader::Create(std::unique_ptr volume) +std::unique_ptr DirectoryBlobReader::Create( + std::unique_ptr volume, + const std::function* fst_nodes, FSTBuilderNode* dol_node)>& + fst_callback) { if (!volume) return nullptr; - return std::unique_ptr(new DirectoryBlobReader(std::move(volume))); + return std::unique_ptr( + new DirectoryBlobReader(std::move(volume), fst_callback)); } DirectoryBlobReader::DirectoryBlobReader(const std::string& game_partition_root, @@ -409,11 +412,14 @@ DirectoryBlobReader::DirectoryBlobReader(const std::string& game_partition_root, } } -DirectoryBlobReader::DirectoryBlobReader(std::unique_ptr volume) +DirectoryBlobReader::DirectoryBlobReader( + std::unique_ptr volume, + 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); + DirectoryBlobPartition game_partition( + m_wrapped_volume.get(), m_wrapped_volume->GetGamePartition(), std::nullopt, fst_callback); m_is_wii = game_partition.IsWii(); if (!m_is_wii) @@ -452,8 +458,9 @@ DirectoryBlobReader::DirectoryBlobReader(std::unique_ptr vol auto type = m_wrapped_volume->GetPartitionType(partition); if (type) { - partitions.emplace_back(DirectoryBlobPartition(m_wrapped_volume.get(), partition, m_is_wii), - static_cast(*type)); + partitions.emplace_back( + DirectoryBlobPartition(m_wrapped_volume.get(), partition, m_is_wii, nullptr), + static_cast(*type)); } } @@ -809,9 +816,10 @@ DirectoryBlobPartition::DirectoryBlobPartition(const std::string& root_directory BuildFSTFromFolder(m_root_directory + "files/", fst_address); } -DirectoryBlobPartition::DirectoryBlobPartition(DiscIO::VolumeDisc* volume, - const DiscIO::Partition& partition, - std::optional is_wii) +DirectoryBlobPartition::DirectoryBlobPartition( + DiscIO::VolumeDisc* volume, const DiscIO::Partition& partition, std::optional is_wii, + const std::function* fst_nodes, FSTBuilderNode* dol_node)>& + fst_callback) : m_wrapped_partition(partition) { std::vector disc_header(DISCHEADER_SIZE); @@ -849,14 +857,17 @@ DirectoryBlobPartition::DirectoryBlobPartition(DiscIO::VolumeDisc* volume, dol_node.m_content = std::move(dol_contents); } } - const u64 new_fst_address = SetDOL(std::move(dol_node), new_dol_address); - - const FileSystem* fs = volume->GetFileSystem(partition); - if (!fs || !fs->IsValid()) - return; std::vector nodes; - GenerateBuilderNodesFromFileSystem(*volume, partition, &nodes, fs->GetRoot()); + + const FileSystem* fs = volume->GetFileSystem(partition); + if (fs && fs->IsValid()) + GenerateBuilderNodesFromFileSystem(*volume, partition, &nodes, fs->GetRoot()); + + if (fst_callback) + fst_callback(&nodes, &dol_node); + + const u64 new_fst_address = SetDOL(std::move(dol_node), new_dol_address); BuildFST(std::move(nodes), new_fst_address); } diff --git a/Source/Core/DiscIO/DirectoryBlob.h b/Source/Core/DiscIO/DirectoryBlob.h index db88367d8c..b8ec90b4f7 100644 --- a/Source/Core/DiscIO/DirectoryBlob.h +++ b/Source/Core/DiscIO/DirectoryBlob.h @@ -5,6 +5,7 @@ #include #include +#include #include #include #include @@ -182,7 +183,9 @@ 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); + std::optional is_wii, + 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; @@ -252,7 +255,10 @@ class DirectoryBlobReader : public BlobReader public: static std::unique_ptr Create(const std::string& dol_path); - static std::unique_ptr Create(std::unique_ptr volume); + static std::unique_ptr Create( + std::unique_ptr volume, + const std::function* fst_nodes, FSTBuilderNode* dol_node)>& + fst_callback); // We do not allow copying, because it might mess up the pointers inside DiscContents DirectoryBlobReader(const DirectoryBlobReader&) = delete; @@ -288,7 +294,9 @@ private: explicit DirectoryBlobReader(const std::string& game_partition_root, const std::string& true_root); - explicit DirectoryBlobReader(std::unique_ptr volume); + explicit DirectoryBlobReader(std::unique_ptr volume, + const std::function* fst_nodes, + FSTBuilderNode* dol_node)>& fst_callback); const DirectoryBlobPartition* GetPartition(u64 offset, u64 size, u64 partition_data_offset) const;