mirror of
https://github.com/izzy2lost/dolphin.git
synced 2026-06-19 01:16:48 -07:00
Added CopyReader to BlobReader and all subclasses
A deep-copy method CopyReader has been added to BlobReader (virtual) and all of its subclasses (override). This should create a second BlobReader to open the same set of data but with an independent read pointer so that it doesn't interfere with any reads done on the original Reader. As part of this, IOFile has added code to create a deep copy IOFile pointer onto the same file, with code based on the platform in question to find the file ID from the file pointer and open a new one. There has also been a small piece added to FileInfo to enable a deep copy, but its only subclass at this time already had a copy constructor so this was relatively minor.
This commit is contained in:
@@ -101,6 +101,15 @@ bool IOFile::Close()
|
||||
return m_good;
|
||||
}
|
||||
|
||||
IOFile IOFile::Duplicate(const char openmode[]) const
|
||||
{
|
||||
#ifdef _WIN32
|
||||
return IOFile(_fdopen(_dup(_fileno(m_file)), openmode));
|
||||
#else // _WIN32
|
||||
return IOFile(fdopen(dup(fileno(m_file)), openmode));
|
||||
#endif // _WIN32
|
||||
}
|
||||
|
||||
void IOFile::SetHandle(std::FILE* file)
|
||||
{
|
||||
Close();
|
||||
|
||||
@@ -51,6 +51,8 @@ public:
|
||||
SharedAccess sh = SharedAccess::Default);
|
||||
bool Close();
|
||||
|
||||
IOFile Duplicate(const char openmode[]) const;
|
||||
|
||||
template <typename T>
|
||||
bool ReadArray(T* elements, size_t count, size_t* num_read = nullptr)
|
||||
{
|
||||
|
||||
@@ -64,6 +64,7 @@ public:
|
||||
virtual ~BlobReader() {}
|
||||
|
||||
virtual BlobType GetBlobType() const = 0;
|
||||
virtual std::unique_ptr<BlobReader> CopyReader() const = 0;
|
||||
|
||||
virtual u64 GetRawSize() const = 0;
|
||||
virtual u64 GetDataSize() const = 0;
|
||||
|
||||
@@ -40,6 +40,11 @@ std::unique_ptr<CISOFileReader> CISOFileReader::Create(File::IOFile file)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::unique_ptr<BlobReader> CISOFileReader::CopyReader() const
|
||||
{
|
||||
return Create(m_file.Duplicate("rb"));
|
||||
}
|
||||
|
||||
u64 CISOFileReader::GetDataSize() const
|
||||
{
|
||||
return static_cast<u64>(CISO_MAP_SIZE) * m_block_size;
|
||||
|
||||
@@ -36,6 +36,7 @@ public:
|
||||
static std::unique_ptr<CISOFileReader> Create(File::IOFile file);
|
||||
|
||||
BlobType GetBlobType() const override { return BlobType::CISO; }
|
||||
std::unique_ptr<BlobReader> CopyReader() const override;
|
||||
|
||||
u64 GetRawSize() const override;
|
||||
u64 GetDataSize() const override;
|
||||
|
||||
@@ -74,6 +74,11 @@ CompressedBlobReader::~CompressedBlobReader()
|
||||
{
|
||||
}
|
||||
|
||||
std::unique_ptr<BlobReader> CompressedBlobReader::CopyReader() const
|
||||
{
|
||||
return Create(m_file.Duplicate("rb"), m_file_name);
|
||||
}
|
||||
|
||||
// IMPORTANT: Calling this function invalidates all earlier pointers gotten from this function.
|
||||
u64 CompressedBlobReader::GetBlockCompressedSize(u64 block_num) const
|
||||
{
|
||||
|
||||
@@ -50,6 +50,7 @@ public:
|
||||
const CompressedBlobHeader& GetHeader() const { return m_header; }
|
||||
|
||||
BlobType GetBlobType() const override { return BlobType::GCZ; }
|
||||
std::unique_ptr<BlobReader> CopyReader() const override;
|
||||
|
||||
u64 GetRawSize() const override { return m_file_size; }
|
||||
u64 GetDataSize() const override { return m_header.data_size; }
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -46,13 +46,13 @@ struct ContentFile
|
||||
u64 m_offset = 0;
|
||||
};
|
||||
|
||||
// Content chunk that's just a direct block of memory
|
||||
typedef std::shared_ptr<std::vector<u8>> ContentMemory;
|
||||
|
||||
// Content chunk that loads data from a DirectoryBlobReader.
|
||||
// Intented for representing a partition within a disc.
|
||||
struct ContentPartition
|
||||
{
|
||||
// The reader to read data from.
|
||||
DirectoryBlobReader* m_reader;
|
||||
|
||||
// Offset from the start of the partition for the first byte represented by this chunk.
|
||||
u64 m_offset = 0;
|
||||
|
||||
@@ -66,9 +66,6 @@ struct ContentVolume
|
||||
// Offset from the start of the volume for the first byte represented by this chunk.
|
||||
u64 m_offset = 0;
|
||||
|
||||
// The volume to read data from.
|
||||
const Volume* m_volume = nullptr;
|
||||
|
||||
// The partition passed to the Volume's Read() method.
|
||||
Partition m_partition;
|
||||
};
|
||||
@@ -80,18 +77,11 @@ struct ContentFixedByte
|
||||
u8 m_byte = 0;
|
||||
};
|
||||
|
||||
// Content chunk representing an arbitrary byte sequence that's stored within the struct itself.
|
||||
struct ContentByteVector
|
||||
{
|
||||
std::vector<u8> m_bytes;
|
||||
};
|
||||
|
||||
using ContentSource = std::variant<ContentFile, // File
|
||||
const u8*, // Memory
|
||||
ContentMemory, // Memory/Byte Sequence
|
||||
ContentPartition, // Partition
|
||||
ContentVolume, // Volume
|
||||
ContentFixedByte, // Fixed value padding
|
||||
ContentByteVector // Byte sequence
|
||||
ContentFixedByte // Fixed value padding
|
||||
>;
|
||||
|
||||
struct BuilderContentSource
|
||||
@@ -147,7 +137,7 @@ public:
|
||||
u64 GetOffset() const;
|
||||
u64 GetEndOffset() const;
|
||||
u64 GetSize() const;
|
||||
bool Read(u64* offset, u64* length, u8** buffer) const;
|
||||
bool Read(u64* offset, u64* length, u8** buffer, DirectoryBlobReader* blob) const;
|
||||
|
||||
bool operator==(const DiscContent& other) const { return GetEndOffset() == other.GetEndOffset(); }
|
||||
bool operator!=(const DiscContent& other) const { return !(*this == other); }
|
||||
@@ -170,16 +160,16 @@ private:
|
||||
class DiscContentContainer
|
||||
{
|
||||
public:
|
||||
template <typename T>
|
||||
void AddReference(u64 offset, const std::vector<T>& vector)
|
||||
void Add(u64 offset, std::vector<u8> vector)
|
||||
{
|
||||
return Add(offset, vector.size() * sizeof(T), reinterpret_cast<const u8*>(vector.data()));
|
||||
size_t vector_size = vector.size();
|
||||
return Add(offset, vector_size, std::make_shared<std::vector<u8>>(std::move(vector)));
|
||||
}
|
||||
void Add(u64 offset, u64 size, ContentSource source);
|
||||
u64 CheckSizeAndAdd(u64 offset, const std::string& path);
|
||||
u64 CheckSizeAndAdd(u64 offset, u64 max_size, const std::string& path);
|
||||
|
||||
bool Read(u64 offset, u64 length, u8* buffer) const;
|
||||
bool Read(u64 offset, u64 length, u8* buffer, DirectoryBlobReader* blob) const;
|
||||
|
||||
private:
|
||||
std::set<DiscContent> m_contents;
|
||||
@@ -194,11 +184,11 @@ public:
|
||||
DiscIO::VolumeDisc* volume, const DiscIO::Partition& partition, std::optional<bool> is_wii,
|
||||
const std::function<void(std::vector<FSTBuilderNode>* fst_nodes)>& sys_callback,
|
||||
const std::function<void(std::vector<FSTBuilderNode>* fst_nodes, FSTBuilderNode* dol_node)>&
|
||||
fst_callback);
|
||||
fst_callback,
|
||||
DirectoryBlobReader* blob);
|
||||
|
||||
// We do not allow copying, because it might mess up the pointers inside DiscContents
|
||||
DirectoryBlobPartition(const DirectoryBlobPartition&) = delete;
|
||||
DirectoryBlobPartition& operator=(const DirectoryBlobPartition&) = delete;
|
||||
DirectoryBlobPartition(const DirectoryBlobPartition&) = default;
|
||||
DirectoryBlobPartition& operator=(const DirectoryBlobPartition&) = default;
|
||||
DirectoryBlobPartition(DirectoryBlobPartition&&) = default;
|
||||
DirectoryBlobPartition& operator=(DirectoryBlobPartition&&) = default;
|
||||
|
||||
@@ -206,7 +196,6 @@ public:
|
||||
u64 GetDataSize() const { return m_data_size; }
|
||||
void SetDataSize(u64 size) { m_data_size = size; }
|
||||
const std::string& GetRootDirectory() const { return m_root_directory; }
|
||||
const std::vector<u8>& GetHeader() const { return m_disc_header; }
|
||||
const DiscContentContainer& GetContents() const { return m_contents; }
|
||||
const std::optional<DiscIO::Partition>& GetWrappedPartition() const
|
||||
{
|
||||
@@ -217,9 +206,7 @@ public:
|
||||
void SetKey(std::array<u8, VolumeWii::AES_KEY_SIZE> key) { m_key = key; }
|
||||
|
||||
private:
|
||||
void SetDiscHeaderFromFile(const std::string& boot_bin_path);
|
||||
void SetDiscHeader(std::vector<u8> boot_bin);
|
||||
void SetDiscType(std::optional<bool> is_wii);
|
||||
void SetDiscType(std::optional<bool> is_wii, const std::vector<u8>& disc_header);
|
||||
void SetBI2FromFile(const std::string& bi2_path);
|
||||
void SetBI2(std::vector<u8> bi2);
|
||||
|
||||
@@ -227,25 +214,24 @@ private:
|
||||
u64 SetApploaderFromFile(const std::string& path);
|
||||
u64 SetApploader(std::vector<u8> apploader, const std::string& log_path);
|
||||
// Returns FST address
|
||||
u64 SetDOLFromFile(const std::string& path, u64 dol_address);
|
||||
u64 SetDOL(FSTBuilderNode dol_node, u64 dol_address);
|
||||
u64 SetDOLFromFile(const std::string& path, u64 dol_address, std::vector<u8>* disc_header);
|
||||
u64 SetDOL(FSTBuilderNode dol_node, u64 dol_address, std::vector<u8>* disc_header);
|
||||
|
||||
void BuildFSTFromFolder(const std::string& fst_root_path, u64 fst_address);
|
||||
void BuildFST(std::vector<FSTBuilderNode> root_nodes, u64 fst_address);
|
||||
void BuildFSTFromFolder(const std::string& fst_root_path, u64 fst_address,
|
||||
std::vector<u8>* disc_header);
|
||||
void BuildFST(std::vector<FSTBuilderNode> root_nodes, u64 fst_address,
|
||||
std::vector<u8>* disc_header);
|
||||
|
||||
// FST creation
|
||||
void WriteEntryData(u32* entry_offset, u8 type, u32 name_offset, u64 data_offset, u64 length,
|
||||
u32 address_shift);
|
||||
void WriteEntryName(u32* name_offset, const std::string& name, u64 name_table_offset);
|
||||
void WriteDirectory(std::vector<FSTBuilderNode>* parent_entries, u32* fst_offset,
|
||||
u32* name_offset, u64* data_offset, u32 parent_entry_index,
|
||||
void WriteEntryData(std::vector<u8>* fst_data, u32* entry_offset, u8 type, u32 name_offset,
|
||||
u64 data_offset, u64 length, u32 address_shift);
|
||||
void WriteEntryName(std::vector<u8>* fst_data, u32* name_offset, const std::string& name,
|
||||
u64 name_table_offset);
|
||||
void WriteDirectory(std::vector<u8>* fst_data, std::vector<FSTBuilderNode>* parent_entries,
|
||||
u32* fst_offset, u32* name_offset, u64* data_offset, u32 parent_entry_index,
|
||||
u64 name_table_offset);
|
||||
|
||||
DiscContentContainer m_contents;
|
||||
std::vector<u8> m_disc_header;
|
||||
std::vector<u8> m_bi2;
|
||||
std::vector<u8> m_apploader;
|
||||
std::vector<u8> m_fst_data;
|
||||
|
||||
std::array<u8, VolumeWii::AES_KEY_SIZE> m_key{};
|
||||
|
||||
@@ -271,9 +257,6 @@ public:
|
||||
const std::function<void(std::vector<FSTBuilderNode>* 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;
|
||||
DirectoryBlobReader& operator=(const DirectoryBlobReader&) = delete;
|
||||
DirectoryBlobReader(DirectoryBlobReader&&) = default;
|
||||
DirectoryBlobReader& operator=(DirectoryBlobReader&&) = default;
|
||||
|
||||
@@ -282,6 +265,7 @@ public:
|
||||
bool ReadWiiDecrypted(u64 offset, u64 size, u8* buffer, u64 partition_data_offset) override;
|
||||
|
||||
BlobType GetBlobType() const override;
|
||||
std::unique_ptr<BlobReader> CopyReader() const override;
|
||||
|
||||
u64 GetRawSize() const override;
|
||||
u64 GetDataSize() const override;
|
||||
@@ -311,6 +295,7 @@ private:
|
||||
const std::function<void(std::vector<FSTBuilderNode>* fst_nodes)>& sys_callback,
|
||||
const std::function<void(std::vector<FSTBuilderNode>* fst_nodes, FSTBuilderNode* dol_node)>&
|
||||
fst_callback);
|
||||
explicit DirectoryBlobReader(const DirectoryBlobReader& rhs);
|
||||
|
||||
const DirectoryBlobPartition* GetPartition(u64 offset, u64 size, u64 partition_data_offset) const;
|
||||
|
||||
@@ -326,6 +311,8 @@ private:
|
||||
void SetPartitions(std::vector<PartitionWithType>&& partitions);
|
||||
void SetPartitionHeader(DirectoryBlobPartition* partition, u64 partition_address);
|
||||
|
||||
DiscIO::VolumeDisc* GetWrappedVolume() { return m_wrapped_volume.get(); }
|
||||
|
||||
// For GameCube:
|
||||
DirectoryBlobPartition m_gamecube_pseudopartition;
|
||||
|
||||
@@ -337,11 +324,6 @@ private:
|
||||
bool m_is_wii;
|
||||
bool m_encrypted;
|
||||
|
||||
std::vector<u8> m_disc_header_nonpartition;
|
||||
std::vector<u8> m_partition_table;
|
||||
std::vector<u8> m_wii_region_data;
|
||||
std::vector<std::vector<u8>> m_extra_data;
|
||||
|
||||
u64 m_data_size;
|
||||
|
||||
std::unique_ptr<DiscIO::VolumeDisc> m_wrapped_volume;
|
||||
|
||||
@@ -22,7 +22,6 @@
|
||||
namespace DiscIO
|
||||
{
|
||||
DiscScrubber::DiscScrubber() = default;
|
||||
DiscScrubber::~DiscScrubber() = default;
|
||||
|
||||
bool DiscScrubber::SetupScrub(const Volume& disc)
|
||||
{
|
||||
|
||||
@@ -27,7 +27,6 @@ class DiscScrubber final
|
||||
{
|
||||
public:
|
||||
DiscScrubber();
|
||||
~DiscScrubber();
|
||||
|
||||
bool SetupScrub(const Volume& disc);
|
||||
|
||||
|
||||
@@ -28,6 +28,11 @@ std::unique_ptr<PlainFileReader> PlainFileReader::Create(File::IOFile file)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::unique_ptr<BlobReader> PlainFileReader::CopyReader() const
|
||||
{
|
||||
return Create(m_file.Duplicate("rb"));
|
||||
}
|
||||
|
||||
bool PlainFileReader::Read(u64 offset, u64 nbytes, u8* out_ptr)
|
||||
{
|
||||
if (m_file.Seek(offset, File::SeekOrigin::Begin) && m_file.ReadBytes(out_ptr, nbytes))
|
||||
|
||||
@@ -19,6 +19,7 @@ public:
|
||||
static std::unique_ptr<PlainFileReader> Create(File::IOFile file);
|
||||
|
||||
BlobType GetBlobType() const override { return BlobType::PLAIN; }
|
||||
std::unique_ptr<BlobReader> CopyReader() const override;
|
||||
|
||||
u64 GetRawSize() const override { return m_size; }
|
||||
u64 GetDataSize() const override { return m_size; }
|
||||
|
||||
@@ -160,11 +160,20 @@ std::unique_ptr<NFSFileReader> NFSFileReader::Create(File::IOFile first_file,
|
||||
NFSFileReader::NFSFileReader(std::vector<NFSLBARange> lba_ranges, std::vector<File::IOFile> files,
|
||||
Key key, u64 raw_size)
|
||||
: m_lba_ranges(std::move(lba_ranges)), m_files(std::move(files)),
|
||||
m_aes_context(Common::AES::CreateContextDecrypt(key.data())), m_raw_size(raw_size)
|
||||
m_aes_context(Common::AES::CreateContextDecrypt(key.data())), m_raw_size(raw_size), m_key(key)
|
||||
{
|
||||
m_data_size = CalculateExpectedDataSize(m_lba_ranges);
|
||||
}
|
||||
|
||||
std::unique_ptr<BlobReader> NFSFileReader::CopyReader() const
|
||||
{
|
||||
std::vector<File::IOFile> new_files{};
|
||||
for (const File::IOFile& file : m_files)
|
||||
new_files.push_back(file.Duplicate("rb"));
|
||||
return std::unique_ptr<NFSFileReader>(
|
||||
new NFSFileReader(m_lba_ranges, std::move(new_files), m_key, m_raw_size));
|
||||
}
|
||||
|
||||
u64 NFSFileReader::GetDataSize() const
|
||||
{
|
||||
return m_data_size;
|
||||
|
||||
@@ -45,6 +45,7 @@ public:
|
||||
const std::string& directory_path);
|
||||
|
||||
BlobType GetBlobType() const override { return BlobType::NFS; }
|
||||
std::unique_ptr<BlobReader> CopyReader() const override;
|
||||
|
||||
u64 GetRawSize() const override;
|
||||
u64 GetDataSize() const override;
|
||||
@@ -86,6 +87,7 @@ private:
|
||||
std::unique_ptr<Common::AES::Context> m_aes_context;
|
||||
u64 m_raw_size;
|
||||
u64 m_data_size;
|
||||
Key m_key;
|
||||
};
|
||||
|
||||
} // namespace DiscIO
|
||||
|
||||
@@ -234,13 +234,23 @@ static void SplitAt(BuilderContentSource* before, BuilderContentSource* after, u
|
||||
after->m_offset += before->m_size;
|
||||
after->m_size = end - split_at;
|
||||
if (std::holds_alternative<ContentFile>(after->m_source))
|
||||
{
|
||||
std::get<ContentFile>(after->m_source).m_offset += before->m_size;
|
||||
else if (std::holds_alternative<const u8*>(after->m_source))
|
||||
std::get<const u8*>(after->m_source) += before->m_size;
|
||||
}
|
||||
else if (std::holds_alternative<ContentMemory>(after->m_source))
|
||||
{
|
||||
after->m_source = std::make_shared<std::vector<u8>>(
|
||||
std::get<ContentMemory>(after->m_source)->begin() + before->m_size,
|
||||
std::get<ContentMemory>(after->m_source)->end());
|
||||
}
|
||||
else if (std::holds_alternative<ContentPartition>(after->m_source))
|
||||
{
|
||||
std::get<ContentPartition>(after->m_source).m_offset += before->m_size;
|
||||
}
|
||||
else if (std::holds_alternative<ContentVolume>(after->m_source))
|
||||
{
|
||||
std::get<ContentVolume>(after->m_source).m_offset += before->m_size;
|
||||
}
|
||||
}
|
||||
|
||||
static void ApplyPatchToFile(const Patch& patch, DiscIO::FSTBuilderNode* file_node,
|
||||
|
||||
@@ -37,6 +37,11 @@ std::unique_ptr<ScrubbedBlob> ScrubbedBlob::Create(const std::string& path)
|
||||
return std::unique_ptr<ScrubbedBlob>(new ScrubbedBlob(std::move(blob), std::move(scrubber)));
|
||||
}
|
||||
|
||||
std::unique_ptr<BlobReader> ScrubbedBlob::CopyReader() const
|
||||
{
|
||||
return std::unique_ptr<ScrubbedBlob>(new ScrubbedBlob(m_blob_reader->CopyReader(), m_scrubber));
|
||||
}
|
||||
|
||||
bool ScrubbedBlob::Read(u64 offset, u64 size, u8* out_ptr)
|
||||
{
|
||||
while (size > 0)
|
||||
|
||||
@@ -19,6 +19,7 @@ public:
|
||||
static std::unique_ptr<ScrubbedBlob> Create(const std::string& path);
|
||||
|
||||
BlobType GetBlobType() const override { return m_blob_reader->GetBlobType(); }
|
||||
std::unique_ptr<BlobReader> CopyReader() const override;
|
||||
|
||||
u64 GetRawSize() const override { return m_blob_reader->GetRawSize(); }
|
||||
u64 GetDataSize() const override { return m_blob_reader->GetDataSize(); }
|
||||
|
||||
@@ -56,6 +56,17 @@ std::unique_ptr<SplitPlainFileReader> SplitPlainFileReader::Create(std::string_v
|
||||
return std::unique_ptr<SplitPlainFileReader>(new SplitPlainFileReader(std::move(files)));
|
||||
}
|
||||
|
||||
std::unique_ptr<BlobReader> SplitPlainFileReader::CopyReader() const
|
||||
{
|
||||
std::vector<SingleFile> new_files{};
|
||||
for (const SingleFile& file : m_files)
|
||||
{
|
||||
new_files.push_back(
|
||||
{.file = file.file.Duplicate("rb"), .offset = file.offset, .size = file.size});
|
||||
}
|
||||
return std::unique_ptr<SplitPlainFileReader>(new SplitPlainFileReader(std::move(new_files)));
|
||||
}
|
||||
|
||||
bool SplitPlainFileReader::Read(u64 offset, u64 nbytes, u8* out_ptr)
|
||||
{
|
||||
if (offset >= m_size)
|
||||
|
||||
@@ -21,6 +21,7 @@ public:
|
||||
static std::unique_ptr<SplitPlainFileReader> Create(std::string_view first_file_path);
|
||||
|
||||
BlobType GetBlobType() const override { return BlobType::SPLIT_PLAIN; }
|
||||
std::unique_ptr<BlobReader> CopyReader() const override;
|
||||
|
||||
u64 GetRawSize() const override { return m_size; }
|
||||
u64 GetDataSize() const override { return m_size; }
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user