From f2c38c0e67720ece41c317e0c04e80aea7fd3f36 Mon Sep 17 00:00:00 2001 From: JosJuice Date: Sun, 17 May 2020 15:34:50 +0200 Subject: [PATCH] RVZ: Make m_rvz a template parameter Needed for the next commit. --- Source/Core/DiscIO/Blob.cpp | 3 +- Source/Core/DiscIO/Blob.h | 10 +- Source/Core/DiscIO/WIABlob.cpp | 284 +++++++++++++++--------- Source/Core/DiscIO/WIABlob.h | 53 ++--- Source/Core/DolphinQt/ConvertDialog.cpp | 38 ++-- Source/Core/DolphinQt/ConvertDialog.h | 4 +- 6 files changed, 222 insertions(+), 170 deletions(-) diff --git a/Source/Core/DiscIO/Blob.cpp b/Source/Core/DiscIO/Blob.cpp index c2c44caa60..50146c9c91 100644 --- a/Source/Core/DiscIO/Blob.cpp +++ b/Source/Core/DiscIO/Blob.cpp @@ -207,8 +207,9 @@ std::unique_ptr CreateBlobReader(const std::string& filename) case WBFS_MAGIC: return WbfsFileReader::Create(std::move(file), filename); case WIA_MAGIC: - case RVZ_MAGIC: return WIAFileReader::Create(std::move(file), filename); + case RVZ_MAGIC: + return RVZFileReader::Create(std::move(file), filename); default: if (auto directory_blob = DirectoryBlobReader::Create(filename)) return std::move(directory_blob); diff --git a/Source/Core/DiscIO/Blob.h b/Source/Core/DiscIO/Blob.h index 149df2afc3..e2a1c3c9e9 100644 --- a/Source/Core/DiscIO/Blob.h +++ b/Source/Core/DiscIO/Blob.h @@ -25,7 +25,7 @@ namespace DiscIO { -enum class WIACompressionType : u32; +enum class WIARVZCompressionType : u32; // Increment CACHE_REVISION (GameFileCache.cpp) if the enum below is modified enum class BlobType @@ -176,9 +176,9 @@ bool ConvertToGCZ(BlobReader* infile, const std::string& infile_path, bool ConvertToPlain(BlobReader* infile, const std::string& infile_path, const std::string& outfile_path, CompressCB callback = nullptr, void* arg = nullptr); -bool ConvertToWIA(BlobReader* infile, const std::string& infile_path, - const std::string& outfile_path, bool rvz, WIACompressionType compression_type, - int compression_level, int chunk_size, CompressCB callback = nullptr, - void* arg = nullptr); +bool ConvertToWIAOrRVZ(BlobReader* infile, const std::string& infile_path, + const std::string& outfile_path, bool rvz, + WIARVZCompressionType compression_type, int compression_level, + int chunk_size, CompressCB callback = nullptr, void* arg = nullptr); } // namespace DiscIO diff --git a/Source/Core/DiscIO/WIABlob.cpp b/Source/Core/DiscIO/WIABlob.cpp index 48731d69c1..6af49b202f 100644 --- a/Source/Core/DiscIO/WIABlob.cpp +++ b/Source/Core/DiscIO/WIABlob.cpp @@ -42,15 +42,31 @@ namespace DiscIO { -std::pair GetAllowedCompressionLevels(WIACompressionType compression_type) +static void PushBack(std::vector* vector, const u8* begin, const u8* end) +{ + const size_t offset_in_vector = vector->size(); + vector->resize(offset_in_vector + (end - begin)); + std::copy(begin, end, vector->data() + offset_in_vector); +} + +template +static void PushBack(std::vector* vector, const T& x) +{ + static_assert(std::is_trivially_copyable_v); + + const u8* x_ptr = reinterpret_cast(&x); + PushBack(vector, x_ptr, x_ptr + sizeof(T)); +} + +std::pair GetAllowedCompressionLevels(WIARVZCompressionType compression_type) { switch (compression_type) { - case WIACompressionType::Bzip2: - case WIACompressionType::LZMA: - case WIACompressionType::LZMA2: + case WIARVZCompressionType::Bzip2: + case WIARVZCompressionType::LZMA: + case WIARVZCompressionType::LZMA2: return {1, 9}; - case WIACompressionType::Zstd: + case WIARVZCompressionType::Zstd: // The actual minimum level can be gotten by calling ZSTD_minCLevel(). However, returning that // would make the UI rather weird, because it is a negative number with very large magnitude. // Note: Level 0 is a special number which means "default level" (level 3 as of this writing). @@ -60,27 +76,28 @@ std::pair GetAllowedCompressionLevels(WIACompressionType compression_t } } -WIAFileReader::WIAFileReader(File::IOFile file, const std::string& path) +template +WIARVZFileReader::WIARVZFileReader(File::IOFile file, const std::string& path) : m_file(std::move(file)), m_encryption_cache(this) { m_valid = Initialize(path); } -WIAFileReader::~WIAFileReader() = default; +template +WIARVZFileReader::~WIARVZFileReader() = default; -bool WIAFileReader::Initialize(const std::string& path) +template +bool WIARVZFileReader::Initialize(const std::string& path) { if (!m_file.Seek(0, SEEK_SET) || !m_file.ReadArray(&m_header_1, 1)) return false; - if (m_header_1.magic != WIA_MAGIC && m_header_1.magic != RVZ_MAGIC) + if ((!RVZ && m_header_1.magic != WIA_MAGIC) || (RVZ && m_header_1.magic != RVZ_MAGIC)) return false; - m_rvz = m_header_1.magic == RVZ_MAGIC; - - const u32 version = m_rvz ? RVZ_VERSION : WIA_VERSION; + const u32 version = RVZ ? RVZ_VERSION : WIA_VERSION; const u32 version_read_compatible = - m_rvz ? RVZ_VERSION_READ_COMPATIBLE : WIA_VERSION_READ_COMPATIBLE; + RVZ ? RVZ_VERSION_READ_COMPATIBLE : WIA_VERSION_READ_COMPATIBLE; const u32 file_version = Common::swap32(m_header_1.version); const u32 file_version_compatible = Common::swap32(m_header_1.version_compatible); @@ -128,16 +145,16 @@ bool WIAFileReader::Initialize(const std::string& path) const u32 chunk_size = Common::swap32(m_header_2.chunk_size); const auto is_power_of_two = [](u32 x) { return (x & (x - 1)) == 0; }; - if ((!m_rvz || chunk_size < VolumeWii::BLOCK_TOTAL_SIZE || !is_power_of_two(chunk_size)) && + if ((!RVZ || chunk_size < VolumeWii::BLOCK_TOTAL_SIZE || !is_power_of_two(chunk_size)) && chunk_size % VolumeWii::GROUP_TOTAL_SIZE != 0) { return false; } const u32 compression_type = Common::swap32(m_header_2.compression_type); - m_compression_type = static_cast(compression_type); - if (m_compression_type > (m_rvz ? WIACompressionType::Zstd : WIACompressionType::LZMA2) || - (m_rvz && m_compression_type == WIACompressionType::Purge)) + m_compression_type = static_cast(compression_type); + if (m_compression_type > (RVZ ? WIARVZCompressionType::Zstd : WIARVZCompressionType::LZMA2) || + (RVZ && m_compression_type == WIARVZCompressionType::Purge)) { ERROR_LOG(DISCIO, "Unsupported compression type %u in %s", compression_type, path.c_str()); return false; @@ -221,7 +238,8 @@ bool WIAFileReader::Initialize(const std::string& path) return true; } -bool WIAFileReader::HasDataOverlap() const +template +bool WIARVZFileReader::HasDataOverlap() const { for (size_t i = 0; i < m_partition_entries.size(); ++i) { @@ -256,18 +274,22 @@ bool WIAFileReader::HasDataOverlap() const return false; } -std::unique_ptr WIAFileReader::Create(File::IOFile file, const std::string& path) +template +std::unique_ptr> WIARVZFileReader::Create(File::IOFile file, + const std::string& path) { - std::unique_ptr blob(new WIAFileReader(std::move(file), path)); + std::unique_ptr blob(new WIARVZFileReader(std::move(file), path)); return blob->m_valid ? std::move(blob) : nullptr; } -BlobType WIAFileReader::GetBlobType() const +template +BlobType WIARVZFileReader::GetBlobType() const { - return m_rvz ? BlobType::RVZ : BlobType::WIA; + return RVZ ? BlobType::RVZ : BlobType::WIA; } -bool WIAFileReader::Read(u64 offset, u64 size, u8* out_ptr) +template +bool WIARVZFileReader::Read(u64 offset, u64 size, u8* out_ptr) { if (offset + size > Common::swap64(m_header_1.iso_file_size)) return false; @@ -368,12 +390,15 @@ bool WIAFileReader::Read(u64 offset, u64 size, u8* out_ptr) return true; } -bool WIAFileReader::SupportsReadWiiDecrypted() const +template +bool WIARVZFileReader::SupportsReadWiiDecrypted() const { return !m_partition_entries.empty(); } -bool WIAFileReader::ReadWiiDecrypted(u64 offset, u64 size, u8* out_ptr, u64 partition_data_offset) +template +bool WIARVZFileReader::ReadWiiDecrypted(u64 offset, u64 size, u8* out_ptr, + u64 partition_data_offset) { const u64 chunk_size = Common::swap32(m_header_2.chunk_size) * VolumeWii::BLOCK_DATA_SIZE / VolumeWii::BLOCK_TOTAL_SIZE; @@ -408,9 +433,11 @@ bool WIAFileReader::ReadWiiDecrypted(u64 offset, u64 size, u8* out_ptr, u64 part return size == 0; } -bool WIAFileReader::ReadFromGroups(u64* offset, u64* size, u8** out_ptr, u64 chunk_size, - u32 sector_size, u64 data_offset, u64 data_size, u32 group_index, - u32 number_of_groups, u32 exception_lists) +template +bool WIARVZFileReader::ReadFromGroups(u64* offset, u64* size, u8** out_ptr, u64 chunk_size, + u32 sector_size, u64 data_offset, u64 data_size, + u32 group_index, u32 number_of_groups, + u32 exception_lists) { if (data_offset + data_size <= *offset) return true; @@ -445,7 +472,7 @@ bool WIAFileReader::ReadFromGroups(u64* offset, u64* size, u8** out_ptr, u64 chu { const u64 group_offset_in_file = static_cast(Common::swap32(group.data_offset)) << 2; Chunk& chunk = ReadCompressedData(group_offset_in_file, group_data_size, chunk_size, - exception_lists, m_rvz, group_offset_in_data); + exception_lists, RVZ, group_offset_in_data); if (!chunk.Read(offset_in_group, bytes_to_read, *out_ptr)) { m_cached_chunk_offset = std::numeric_limits::max(); // Invalidate the cache @@ -471,9 +498,11 @@ bool WIAFileReader::ReadFromGroups(u64* offset, u64* size, u8** out_ptr, u64 chu return true; } -WIAFileReader::Chunk& WIAFileReader::ReadCompressedData(u64 offset_in_file, u64 compressed_size, - u64 decompressed_size, u32 exception_lists, - bool rvz_pack, u64 data_offset) +template +typename WIARVZFileReader::Chunk& +WIARVZFileReader::ReadCompressedData(u64 offset_in_file, u64 compressed_size, + u64 decompressed_size, u32 exception_lists, bool rvz_pack, + u64 data_offset) { if (offset_in_file == m_cached_chunk_offset) return m_cached_chunk; @@ -481,29 +510,29 @@ WIAFileReader::Chunk& WIAFileReader::ReadCompressedData(u64 offset_in_file, u64 std::unique_ptr decompressor; switch (m_compression_type) { - case WIACompressionType::None: + case WIARVZCompressionType::None: decompressor = std::make_unique(); break; - case WIACompressionType::Purge: + case WIARVZCompressionType::Purge: decompressor = std::make_unique(decompressed_size); break; - case WIACompressionType::Bzip2: + case WIARVZCompressionType::Bzip2: decompressor = std::make_unique(); break; - case WIACompressionType::LZMA: + case WIARVZCompressionType::LZMA: decompressor = std::make_unique(false, m_header_2.compressor_data, m_header_2.compressor_data_size); break; - case WIACompressionType::LZMA2: + case WIARVZCompressionType::LZMA2: decompressor = std::make_unique(true, m_header_2.compressor_data, m_header_2.compressor_data_size); break; - case WIACompressionType::Zstd: + case WIARVZCompressionType::Zstd: decompressor = std::make_unique(); break; } - const bool compressed_exception_lists = m_compression_type > WIACompressionType::Purge; + const bool compressed_exception_lists = m_compression_type > WIARVZCompressionType::Purge; m_cached_chunk = Chunk(&m_file, offset_in_file, compressed_size, decompressed_size, exception_lists, @@ -512,7 +541,8 @@ WIAFileReader::Chunk& WIAFileReader::ReadCompressedData(u64 offset_in_file, u64 return m_cached_chunk; } -std::string WIAFileReader::VersionToString(u32 version) +template +std::string WIARVZFileReader::VersionToString(u32 version) { const u8 a = version >> 24; const u8 b = (version >> 16) & 0xff; @@ -525,12 +555,14 @@ std::string WIAFileReader::VersionToString(u32 version) return StringFromFormat("%u.%02x.%02x.beta%u", a, b, c, d); } -WIAFileReader::Chunk::Chunk() = default; +template +WIARVZFileReader::Chunk::Chunk() = default; -WIAFileReader::Chunk::Chunk(File::IOFile* file, u64 offset_in_file, u64 compressed_size, - u64 decompressed_size, u32 exception_lists, - bool compressed_exception_lists, bool rvz_pack, u64 data_offset, - std::unique_ptr decompressor) +template +WIARVZFileReader::Chunk::Chunk(File::IOFile* file, u64 offset_in_file, u64 compressed_size, + u64 decompressed_size, u32 exception_lists, + bool compressed_exception_lists, bool rvz_pack, u64 data_offset, + std::unique_ptr decompressor) : m_file(file), m_offset_in_file(offset_in_file), m_exception_lists(exception_lists), m_compressed_exception_lists(compressed_exception_lists), m_rvz_pack(rvz_pack), m_data_offset(data_offset), m_decompressor(std::move(decompressor)) @@ -547,7 +579,8 @@ WIAFileReader::Chunk::Chunk(File::IOFile* file, u64 offset_in_file, u64 compress m_out.data.resize(decompressed_size + m_out_bytes_allocated_for_exceptions); } -bool WIAFileReader::Chunk::Read(u64 offset, u64 size, u8* out_ptr) +template +bool WIARVZFileReader::Chunk::Read(u64 offset, u64 size, u8* out_ptr) { if (!m_decompressor || !m_file || offset + size > m_out.data.size() - m_out_bytes_allocated_for_exceptions) @@ -655,7 +688,8 @@ bool WIAFileReader::Chunk::Read(u64 offset, u64 size, u8* out_ptr) return true; } -bool WIAFileReader::Chunk::Decompress() +template +bool WIARVZFileReader::Chunk::Decompress() { if (m_rvz_pack && m_exception_lists == 0) { @@ -675,8 +709,10 @@ bool WIAFileReader::Chunk::Decompress() return m_decompressor->Decompress(m_in, &m_out, &m_in_bytes_read); } -bool WIAFileReader::Chunk::HandleExceptions(const u8* data, size_t bytes_allocated, - size_t bytes_written, size_t* bytes_used, bool align) +template +bool WIARVZFileReader::Chunk::HandleExceptions(const u8* data, size_t bytes_allocated, + size_t bytes_written, size_t* bytes_used, + bool align) { while (m_exception_lists > 0) { @@ -709,8 +745,10 @@ bool WIAFileReader::Chunk::HandleExceptions(const u8* data, size_t bytes_allocat return true; } -void WIAFileReader::Chunk::GetHashExceptions(std::vector* exception_list, - u64 exception_list_index, u16 additional_offset) const +template +void WIARVZFileReader::Chunk::GetHashExceptions( + std::vector* exception_list, u64 exception_list_index, + u16 additional_offset) const { ASSERT(m_exception_lists == 0); @@ -736,7 +774,8 @@ void WIAFileReader::Chunk::GetHashExceptions(std::vector* ex m_in_bytes_used_for_exceptions)); } -bool WIAFileReader::ApplyHashExceptions( +template +bool WIARVZFileReader::ApplyHashExceptions( const std::vector& exception_list, VolumeWii::HashBlock hash_blocks[VolumeWii::BLOCKS_PER_GROUP]) { @@ -759,7 +798,8 @@ bool WIAFileReader::ApplyHashExceptions( return true; } -bool WIAFileReader::PadTo4(File::IOFile* file, u64* bytes_written) +template +bool WIARVZFileReader::PadTo4(File::IOFile* file, u64* bytes_written) { constexpr u32 ZEROES = 0; const u64 bytes_to_write = Common::AlignUp(*bytes_written, 4) - *bytes_written; @@ -770,9 +810,10 @@ bool WIAFileReader::PadTo4(File::IOFile* file, u64* bytes_written) return file->WriteBytes(&ZEROES, bytes_to_write); } -void WIAFileReader::AddRawDataEntry(u64 offset, u64 size, int chunk_size, u32* total_groups, - std::vector* raw_data_entries, - std::vector* data_entries) +template +void WIARVZFileReader::AddRawDataEntry(u64 offset, u64 size, int chunk_size, u32* total_groups, + std::vector* raw_data_entries, + std::vector* data_entries) { constexpr size_t SKIP_SIZE = sizeof(WIAHeader2::disc_header); const u64 skip = offset < SKIP_SIZE ? std::min(SKIP_SIZE - offset, size) : 0; @@ -792,7 +833,8 @@ void WIAFileReader::AddRawDataEntry(u64 offset, u64 size, int chunk_size, u32* t Common::swap32(group_index), Common::swap32(groups)}); } -WIAFileReader::PartitionDataEntry WIAFileReader::CreatePartitionDataEntry( +template +typename WIARVZFileReader::PartitionDataEntry WIARVZFileReader::CreatePartitionDataEntry( u64 offset, u64 size, u32 index, int chunk_size, u32* total_groups, const std::vector& partition_entries, std::vector* data_entries) { @@ -807,7 +849,8 @@ WIAFileReader::PartitionDataEntry WIAFileReader::CreatePartitionDataEntry( Common::swap32(group_index), Common::swap32(groups)}; } -ConversionResultCode WIAFileReader::SetUpDataEntriesForWriting( +template +ConversionResultCode WIARVZFileReader::SetUpDataEntriesForWriting( const VolumeDisc* volume, int chunk_size, u64 iso_size, u32* total_groups, std::vector* partition_entries, std::vector* raw_data_entries, std::vector* data_entries, std::vector* partition_file_systems) @@ -924,8 +967,9 @@ ConversionResultCode WIAFileReader::SetUpDataEntriesForWriting( return ConversionResultCode::Success; } -std::optional> WIAFileReader::Compress(Compressor* compressor, const u8* data, - size_t size) +template +std::optional> WIARVZFileReader::Compress(Compressor* compressor, + const u8* data, size_t size) { if (compressor) { @@ -939,23 +983,24 @@ std::optional> WIAFileReader::Compress(Compressor* compressor, c return std::vector(data, data + size); } -void WIAFileReader::SetUpCompressor(std::unique_ptr* compressor, - WIACompressionType compression_type, int compression_level, - WIAHeader2* header_2) +template +void WIARVZFileReader::SetUpCompressor(std::unique_ptr* compressor, + WIARVZCompressionType compression_type, + int compression_level, WIAHeader2* header_2) { switch (compression_type) { - case WIACompressionType::None: + case WIARVZCompressionType::None: *compressor = nullptr; break; - case WIACompressionType::Purge: + case WIARVZCompressionType::Purge: *compressor = std::make_unique(); break; - case WIACompressionType::Bzip2: + case WIARVZCompressionType::Bzip2: *compressor = std::make_unique(compression_level); break; - case WIACompressionType::LZMA: - case WIACompressionType::LZMA2: + case WIARVZCompressionType::LZMA: + case WIARVZCompressionType::LZMA2: { u8* compressor_data = nullptr; u8* compressor_data_size = nullptr; @@ -966,19 +1011,21 @@ void WIAFileReader::SetUpCompressor(std::unique_ptr* compressor, compressor_data_size = &header_2->compressor_data_size; } - const bool lzma2 = compression_type == WIACompressionType::LZMA2; + const bool lzma2 = compression_type == WIARVZCompressionType::LZMA2; *compressor = std::make_unique(lzma2, compression_level, compressor_data, compressor_data_size); break; } - case WIACompressionType::Zstd: + case WIARVZCompressionType::Zstd: *compressor = std::make_unique(compression_level); break; } } -bool WIAFileReader::TryReuse(std::map* reusable_groups, - std::mutex* reusable_groups_mutex, OutputParametersEntry* entry) +template +bool WIARVZFileReader::TryReuse(std::map* reusable_groups, + std::mutex* reusable_groups_mutex, + OutputParametersEntry* entry) { if (entry->reused_group) return true; @@ -1020,9 +1067,10 @@ static bool AllSame(const u8* begin, const u8* end) return AllAre(begin, end, *begin); }; -void WIAFileReader::RVZPack(const u8* in, OutputParametersEntry* out, u64 bytes_per_chunk, - size_t chunks, u64 total_size, u64 data_offset, u64 in_offset, - bool allow_junk_reuse, bool compression, const FileSystem* file_system) +template +static void RVZPack(const u8* in, OutputParametersEntry* out, u64 bytes_per_chunk, size_t chunks, + u64 total_size, u64 data_offset, u64 in_offset, bool allow_junk_reuse, + bool compression, const FileSystem* file_system) { using Seed = std::array; struct JunkInfo @@ -1140,19 +1188,23 @@ void WIAFileReader::RVZPack(const u8* in, OutputParametersEntry* out, u64 bytes_ } } -void WIAFileReader::RVZPack(const u8* in, OutputParametersEntry* out, u64 size, u64 data_offset, - bool allow_junk_reuse, bool compression, const FileSystem* file_system) +template +static void RVZPack(const u8* in, OutputParametersEntry* out, u64 size, u64 data_offset, + bool allow_junk_reuse, bool compression, const FileSystem* file_system) { RVZPack(in, out, size, 1, size, data_offset, 0, allow_junk_reuse, compression, file_system); } -ConversionResult WIAFileReader::ProcessAndCompress( - CompressThreadState* state, CompressParameters parameters, - const std::vector& partition_entries, - const std::vector& data_entries, const FileSystem* file_system, - std::map* reusable_groups, std::mutex* reusable_groups_mutex, - u64 chunks_per_wii_group, u64 exception_lists_per_chunk, bool compressed_exception_lists, - bool compression, bool rvz) +template +ConversionResult::OutputParameters> +WIARVZFileReader::ProcessAndCompress(CompressThreadState* state, CompressParameters parameters, + const std::vector& partition_entries, + const std::vector& data_entries, + const FileSystem* file_system, + std::map* reusable_groups, + std::mutex* reusable_groups_mutex, + u64 chunks_per_wii_group, u64 exception_lists_per_chunk, + bool compressed_exception_lists, bool compression) { std::vector output_entries; @@ -1164,7 +1216,7 @@ ConversionResult WIAFileReader::ProcessAndCompr if (AllSame(data)) entry.reuse_id = ReuseID{nullptr, data.size(), false, data.front()}; - if (rvz) + if constexpr (RVZ) { RVZPack(data.data(), output_entries.data(), data.size(), parameters.data_offset, true, compression, file_system); @@ -1315,9 +1367,9 @@ ConversionResult WIAFileReader::ProcessAndCompr compare_hashes(offsetof(HashBlock, padding_2), sizeof(HashBlock::padding_2)); } - static_assert(std::is_trivially_copyable_v); - if (rvz) + if constexpr (RVZ) { // We must not store junk efficiently for chunks that may get reused at a position // which has a different value of data_offset % VolumeWii::BLOCK_TOTAL_SIZE @@ -1471,11 +1523,12 @@ ConversionResult WIAFileReader::ProcessAndCompr return OutputParameters{std::move(output_entries), parameters.bytes_read, parameters.group_index}; } -ConversionResultCode WIAFileReader::Output(std::vector* entries, - File::IOFile* outfile, - std::map* reusable_groups, - std::mutex* reusable_groups_mutex, - GroupEntry* group_entry, u64* bytes_written) +template +ConversionResultCode WIARVZFileReader::Output(std::vector* entries, + File::IOFile* outfile, + std::map* reusable_groups, + std::mutex* reusable_groups_mutex, + GroupEntry* group_entry, u64* bytes_written) { for (OutputParametersEntry& entry : *entries) { @@ -1518,9 +1571,10 @@ ConversionResultCode WIAFileReader::Output(std::vector* e return ConversionResultCode::Success; } -ConversionResultCode WIAFileReader::RunCallback(size_t groups_written, u64 bytes_read, - u64 bytes_written, u32 total_groups, u64 iso_size, - CompressCB callback, void* arg) +template +ConversionResultCode +WIARVZFileReader::RunCallback(size_t groups_written, u64 bytes_read, u64 bytes_written, + u32 total_groups, u64 iso_size, CompressCB callback, void* arg) { int ratio = 0; if (bytes_read != 0) @@ -1536,8 +1590,9 @@ ConversionResultCode WIAFileReader::RunCallback(size_t groups_written, u64 bytes ConversionResultCode::Canceled; } -bool WIAFileReader::WriteHeader(File::IOFile* file, const u8* data, size_t size, u64 upper_bound, - u64* bytes_written, u64* offset_out) +template +bool WIARVZFileReader::WriteHeader(File::IOFile* file, const u8* data, size_t size, + u64 upper_bound, u64* bytes_written, u64* offset_out) { // The first part of the check is to prevent this from running more than once. If *bytes_written // is past the upper bound, we are already at the end of the file, so we don't need to do anything @@ -1556,10 +1611,12 @@ bool WIAFileReader::WriteHeader(File::IOFile* file, const u8* data, size_t size, return PadTo4(file, bytes_written); } +template ConversionResultCode -WIAFileReader::ConvertToWIA(BlobReader* infile, const VolumeDisc* infile_volume, - File::IOFile* outfile, bool rvz, WIACompressionType compression_type, - int compression_level, int chunk_size, CompressCB callback, void* arg) +WIARVZFileReader::Convert(BlobReader* infile, const VolumeDisc* infile_volume, + File::IOFile* outfile, WIARVZCompressionType compression_type, + int compression_level, int chunk_size, CompressCB callback, + void* arg) { ASSERT(infile->IsDataSizeAccurate()); ASSERT(chunk_size > 0); @@ -1567,7 +1624,7 @@ WIAFileReader::ConvertToWIA(BlobReader* infile, const VolumeDisc* infile_volume, const u64 iso_size = infile->GetDataSize(); const u64 chunks_per_wii_group = std::max(1, VolumeWii::GROUP_TOTAL_SIZE / chunk_size); const u64 exception_lists_per_chunk = std::max(1, chunk_size / VolumeWii::GROUP_TOTAL_SIZE); - const bool compressed_exception_lists = compression_type > WIACompressionType::Purge; + const bool compressed_exception_lists = compression_type > WIARVZCompressionType::Purge; u64 bytes_read = 0; u64 bytes_written = 0; @@ -1631,12 +1688,12 @@ WIAFileReader::ConvertToWIA(BlobReader* infile, const VolumeDisc* infile_volume, partition_file_systems[data_entry.index] : non_partition_file_system; - const bool compression = compression_type != WIACompressionType::None; + const bool compression = compression_type != WIARVZCompressionType::None; return ProcessAndCompress(state, std::move(parameters), partition_entries, data_entries, file_system, &reusable_groups, &reusable_groups_mutex, chunks_per_wii_group, exception_lists_per_chunk, - compressed_exception_lists, compression, rvz); + compressed_exception_lists, compression); }; const auto output = [&](OutputParameters parameters) { @@ -1820,10 +1877,10 @@ WIAFileReader::ConvertToWIA(BlobReader* infile, const VolumeDisc* infile_volume, header_2.group_entries_offset = Common::swap64(group_entries_offset); header_2.group_entries_size = Common::swap32(static_cast(compressed_group_entries->size())); - header_1.magic = rvz ? RVZ_MAGIC : WIA_MAGIC; - header_1.version = Common::swap32(rvz ? RVZ_VERSION : WIA_VERSION); + header_1.magic = RVZ ? RVZ_MAGIC : WIA_MAGIC; + header_1.version = Common::swap32(RVZ ? RVZ_VERSION : WIA_VERSION); header_1.version_compatible = - Common::swap32(rvz ? RVZ_VERSION_WRITE_COMPATIBLE : WIA_VERSION_WRITE_COMPATIBLE); + Common::swap32(RVZ ? RVZ_VERSION_WRITE_COMPATIBLE : WIA_VERSION_WRITE_COMPATIBLE); header_1.header_2_size = Common::swap32(sizeof(WIAHeader2)); mbedtls_sha1_ret(reinterpret_cast(&header_2), sizeof(header_2), header_1.header_2_hash.data()); @@ -1843,9 +1900,10 @@ WIAFileReader::ConvertToWIA(BlobReader* infile, const VolumeDisc* infile_volume, return ConversionResultCode::Success; } -bool ConvertToWIA(BlobReader* infile, const std::string& infile_path, - const std::string& outfile_path, bool rvz, WIACompressionType compression_type, - int compression_level, int chunk_size, CompressCB callback, void* arg) +bool ConvertToWIAOrRVZ(BlobReader* infile, const std::string& infile_path, + const std::string& outfile_path, bool rvz, + WIARVZCompressionType compression_type, int compression_level, + int chunk_size, CompressCB callback, void* arg) { File::IOFile outfile(outfile_path, "wb"); if (!outfile) @@ -1859,9 +1917,10 @@ bool ConvertToWIA(BlobReader* infile, const std::string& infile_path, std::unique_ptr infile_volume = CreateDisc(infile_path); + const auto convert = rvz ? RVZFileReader::Convert : WIAFileReader::Convert; const ConversionResultCode result = - WIAFileReader::ConvertToWIA(infile, infile_volume.get(), &outfile, rvz, compression_type, - compression_level, chunk_size, callback, arg); + convert(infile, infile_volume.get(), &outfile, compression_type, compression_level, + chunk_size, callback, arg); if (result == ConversionResultCode::ReadFailed) PanicAlertT("Failed to read from the input file \"%s\".", infile_path.c_str()); @@ -1883,4 +1942,7 @@ bool ConvertToWIA(BlobReader* infile, const std::string& infile_path, return result == ConversionResultCode::Success; } +template class WIARVZFileReader; +template class WIARVZFileReader; + } // namespace DiscIO diff --git a/Source/Core/DiscIO/WIABlob.h b/Source/Core/DiscIO/WIABlob.h index 3103a19795..d7e3573e7c 100644 --- a/Source/Core/DiscIO/WIABlob.h +++ b/Source/Core/DiscIO/WIABlob.h @@ -25,7 +25,7 @@ namespace DiscIO class FileSystem; class VolumeDisc; -enum class WIACompressionType : u32 +enum class WIARVZCompressionType : u32 { None = 0, Purge = 1, @@ -35,17 +35,18 @@ enum class WIACompressionType : u32 Zstd = 5, }; -std::pair GetAllowedCompressionLevels(WIACompressionType compression_type); +std::pair GetAllowedCompressionLevels(WIARVZCompressionType compression_type); constexpr u32 WIA_MAGIC = 0x01414957; // "WIA\x1" (byteswapped to little endian) constexpr u32 RVZ_MAGIC = 0x015A5652; // "RVZ\x1" (byteswapped to little endian) -class WIAFileReader : public BlobReader +template +class WIARVZFileReader : public BlobReader { public: - ~WIAFileReader(); + ~WIARVZFileReader(); - static std::unique_ptr Create(File::IOFile file, const std::string& path); + static std::unique_ptr Create(File::IOFile file, const std::string& path); BlobType GetBlobType() const override; @@ -60,11 +61,10 @@ public: bool SupportsReadWiiDecrypted() const override; bool ReadWiiDecrypted(u64 offset, u64 size, u8* out_ptr, u64 partition_data_offset) override; - static ConversionResultCode ConvertToWIA(BlobReader* infile, const VolumeDisc* infile_volume, - File::IOFile* outfile, bool rvz, - WIACompressionType compression_type, - int compression_level, int chunk_size, - CompressCB callback, void* arg); + static ConversionResultCode Convert(BlobReader* infile, const VolumeDisc* infile_volume, + File::IOFile* outfile, WIARVZCompressionType compression_type, + int compression_level, int chunk_size, CompressCB callback, + void* arg); private: using SHA1 = std::array; @@ -209,7 +209,7 @@ private: u64 m_data_offset = 0; }; - explicit WIAFileReader(File::IOFile file, const std::string& path); + explicit WIARVZFileReader(File::IOFile file, const std::string& path); bool Initialize(const std::string& path); bool HasDataOverlap() const; @@ -306,15 +306,10 @@ private: u64* bytes_written, u64* offset_out); static void SetUpCompressor(std::unique_ptr* compressor, - WIACompressionType compression_type, int compression_level, + WIARVZCompressionType compression_type, int compression_level, WIAHeader2* header_2); static bool TryReuse(std::map* reusable_groups, std::mutex* reusable_groups_mutex, OutputParametersEntry* entry); - static void RVZPack(const u8* in, OutputParametersEntry* out, u64 bytes_per_chunk, size_t chunks, - u64 total_size, u64 data_offset, u64 in_offset, bool allow_junk_reuse, - bool compression, const FileSystem* file_system); - static void RVZPack(const u8* in, OutputParametersEntry* out, u64 size, u64 data_offset, - bool allow_junk_reuse, bool compression, const FileSystem* file_system); static ConversionResult ProcessAndCompress(CompressThreadState* state, CompressParameters parameters, const std::vector& partition_entries, @@ -322,7 +317,7 @@ private: std::map* reusable_groups, std::mutex* reusable_groups_mutex, u64 chunks_per_wii_group, u64 exception_lists_per_chunk, bool compressed_exception_lists, - bool compression, bool rvz); + bool compression); static ConversionResultCode Output(std::vector* entries, File::IOFile* outfile, std::map* reusable_groups, @@ -332,25 +327,8 @@ private: u32 total_groups, u64 iso_size, CompressCB callback, void* arg); - static void PushBack(std::vector* vector, const u8* begin, const u8* end) - { - const size_t offset_in_vector = vector->size(); - vector->resize(offset_in_vector + (end - begin)); - std::copy(begin, end, vector->data() + offset_in_vector); - } - - template - static void PushBack(std::vector* vector, const T& x) - { - static_assert(std::is_trivially_copyable_v); - - const u8* x_ptr = reinterpret_cast(&x); - PushBack(vector, x_ptr, x_ptr + sizeof(T)); - } - bool m_valid; - bool m_rvz; - WIACompressionType m_compression_type; + WIARVZCompressionType m_compression_type; File::IOFile m_file; Chunk m_cached_chunk; @@ -382,4 +360,7 @@ private: static constexpr u32 RVZ_VERSION_READ_COMPATIBLE = 0x00020000; }; +using WIAFileReader = WIARVZFileReader; +using RVZFileReader = WIARVZFileReader; + } // namespace DiscIO diff --git a/Source/Core/DolphinQt/ConvertDialog.cpp b/Source/Core/DolphinQt/ConvertDialog.cpp index a587af0deb..d7676cc81a 100644 --- a/Source/Core/DolphinQt/ConvertDialog.cpp +++ b/Source/Core/DolphinQt/ConvertDialog.cpp @@ -139,7 +139,8 @@ void ConvertDialog::AddToBlockSizeComboBox(int size) m_block_size->setCurrentIndex(m_block_size->count() - 1); } -void ConvertDialog::AddToCompressionComboBox(const QString& name, DiscIO::WIACompressionType type) +void ConvertDialog::AddToCompressionComboBox(const QString& name, + DiscIO::WIARVZCompressionType type) { m_compression->addItem(name, static_cast(type)); } @@ -227,7 +228,7 @@ void ConvertDialog::OnFormatChanged() { case DiscIO::BlobType::GCZ: m_compression->setEnabled(true); - AddToCompressionComboBox(QStringLiteral("Deflate"), DiscIO::WIACompressionType::None); + AddToCompressionComboBox(QStringLiteral("Deflate"), DiscIO::WIARVZCompressionType::None); break; case DiscIO::BlobType::WIA: case DiscIO::BlobType::RVZ: @@ -237,15 +238,22 @@ void ConvertDialog::OnFormatChanged() // i18n: %1 is the name of a compression method (e.g. LZMA) const QString slow = tr("%1 (slow)"); - AddToCompressionComboBox(tr("No Compression"), DiscIO::WIACompressionType::None); + AddToCompressionComboBox(tr("No Compression"), DiscIO::WIARVZCompressionType::None); + if (format == DiscIO::BlobType::WIA) - AddToCompressionComboBox(QStringLiteral("Purge"), DiscIO::WIACompressionType::Purge); - AddToCompressionComboBox(slow.arg(QStringLiteral("bzip2")), DiscIO::WIACompressionType::Bzip2); - AddToCompressionComboBox(slow.arg(QStringLiteral("LZMA")), DiscIO::WIACompressionType::LZMA); - AddToCompressionComboBox(slow.arg(QStringLiteral("LZMA2")), DiscIO::WIACompressionType::LZMA2); + AddToCompressionComboBox(QStringLiteral("Purge"), DiscIO::WIARVZCompressionType::Purge); + + AddToCompressionComboBox(slow.arg(QStringLiteral("bzip2")), + DiscIO::WIARVZCompressionType::Bzip2); + + AddToCompressionComboBox(slow.arg(QStringLiteral("LZMA")), DiscIO::WIARVZCompressionType::LZMA); + + AddToCompressionComboBox(slow.arg(QStringLiteral("LZMA2")), + DiscIO::WIARVZCompressionType::LZMA2); + if (format == DiscIO::BlobType::RVZ) { - AddToCompressionComboBox(QStringLiteral("Zstandard"), DiscIO::WIACompressionType::Zstd); + AddToCompressionComboBox(QStringLiteral("Zstandard"), DiscIO::WIARVZCompressionType::Zstd); m_compression->setCurrentIndex(m_compression->count() - 1); } @@ -269,7 +277,7 @@ void ConvertDialog::OnCompressionChanged() m_compression_level->clear(); const auto compression_type = - static_cast(m_compression->currentData().toInt()); + static_cast(m_compression->currentData().toInt()); const std::pair range = DiscIO::GetAllowedCompressionLevels(compression_type); @@ -299,8 +307,8 @@ void ConvertDialog::Convert() { const DiscIO::BlobType format = static_cast(m_format->currentData().toInt()); const int block_size = m_block_size->currentData().toInt(); - const DiscIO::WIACompressionType compression = - static_cast(m_compression->currentData().toInt()); + const DiscIO::WIARVZCompressionType compression = + static_cast(m_compression->currentData().toInt()); const int compression_level = m_compression_level->currentData().toInt(); const bool scrub = m_scrub->isChecked(); @@ -477,10 +485,10 @@ void ConvertDialog::Convert() case DiscIO::BlobType::WIA: case DiscIO::BlobType::RVZ: good = std::async(std::launch::async, [&] { - const bool good = - DiscIO::ConvertToWIA(blob_reader.get(), original_path, dst_path.toStdString(), - format == DiscIO::BlobType::RVZ, compression, compression_level, - block_size, &CompressCB, &progress_dialog); + const bool good = DiscIO::ConvertToWIAOrRVZ( + blob_reader.get(), original_path, dst_path.toStdString(), + format == DiscIO::BlobType::RVZ, compression, compression_level, block_size, + &CompressCB, &progress_dialog); progress_dialog.Reset(); return good; }); diff --git a/Source/Core/DolphinQt/ConvertDialog.h b/Source/Core/DolphinQt/ConvertDialog.h index b14ecb6c52..9a53265f86 100644 --- a/Source/Core/DolphinQt/ConvertDialog.h +++ b/Source/Core/DolphinQt/ConvertDialog.h @@ -16,7 +16,7 @@ class QComboBox; namespace DiscIO { -enum class WIACompressionType : u32; +enum class WIARVZCompressionType : u32; } namespace UICommon @@ -39,7 +39,7 @@ private slots: private: void AddToBlockSizeComboBox(int size); - void AddToCompressionComboBox(const QString& name, DiscIO::WIACompressionType type); + void AddToCompressionComboBox(const QString& name, DiscIO::WIARVZCompressionType type); void AddToCompressionLevelComboBox(int level); bool ShowAreYouSureDialog(const QString& text);