mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-07-23 14:19:46 -06:00
WIA: Reuse groups when writing
This is useful for the way Dolphin scrubs Wii discs. The encrypted data is what gets zeroed out, but this zeroed out data then gets decrypted before being stored, and the resulting data does not compress well. However, each block of decrypted scrubbed data is identical given the same encryption key, and there's nothing stopping us from making multiple group entries point to the same offset in the file, so we only have to store one copy of this data per partition. For reference, wit zeroes out the decrypted data, but Dolphin's WIA writer can't do this because it currently doesn't know which parts of the disc are scrubbed. This is also useful for things such as storing Datel discs full of 0x55 blocks (repesenting unreadable blocks) without compression enabled.
This commit is contained in:
@ -8,6 +8,7 @@
|
||||
#include <limits>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <utility>
|
||||
|
||||
#include <bzlib.h>
|
||||
@ -389,6 +390,33 @@ private:
|
||||
|
||||
static u32 LZMA2DictionarySize(u8 p);
|
||||
|
||||
struct ReuseID
|
||||
{
|
||||
bool operator==(const ReuseID& other) const
|
||||
{
|
||||
return std::tie(partition_key, data_size, decrypted, value) ==
|
||||
std::tie(other.partition_key, other.data_size, other.decrypted, other.value);
|
||||
}
|
||||
bool operator<(const ReuseID& other) const
|
||||
{
|
||||
return std::tie(partition_key, data_size, decrypted, value) <
|
||||
std::tie(other.partition_key, other.data_size, other.decrypted, other.value);
|
||||
}
|
||||
bool operator>(const ReuseID& other) const
|
||||
{
|
||||
return std::tie(partition_key, data_size, decrypted, value) >
|
||||
std::tie(other.partition_key, other.data_size, other.decrypted, other.value);
|
||||
}
|
||||
bool operator!=(const ReuseID& other) const { return !operator==(other); }
|
||||
bool operator>=(const ReuseID& other) const { return !operator<(other); }
|
||||
bool operator<=(const ReuseID& other) const { return !operator>(other); }
|
||||
|
||||
const WiiKey* partition_key;
|
||||
u64 data_size;
|
||||
bool decrypted;
|
||||
u8 value;
|
||||
};
|
||||
|
||||
static bool PadTo4(File::IOFile* file, u64* bytes_written);
|
||||
static void AddRawDataEntry(u64 offset, u64 size, int chunk_size, u32* total_groups,
|
||||
std::vector<RawDataEntry>* raw_data_entries,
|
||||
@ -402,12 +430,14 @@ private:
|
||||
std::vector<PartitionEntry>* partition_entries,
|
||||
std::vector<RawDataEntry>* raw_data_entries,
|
||||
std::vector<DataEntry>* data_entries);
|
||||
static ConversionResult CompressAndWriteGroup(File::IOFile* file, u64* bytes_written,
|
||||
std::vector<GroupEntry>* group_entries,
|
||||
size_t* groups_written, Compressor* compressor,
|
||||
bool compressed_exception_lists,
|
||||
const std::vector<u8>& exception_lists,
|
||||
const std::vector<u8>& main_data);
|
||||
static bool TryReuseGroup(std::vector<GroupEntry>* group_entries, size_t* groups_written,
|
||||
std::map<ReuseID, GroupEntry>* reusable_groups,
|
||||
std::optional<ReuseID> reuse_id);
|
||||
static ConversionResult CompressAndWriteGroup(
|
||||
File::IOFile* file, u64* bytes_written, std::vector<GroupEntry>* group_entries,
|
||||
size_t* groups_written, Compressor* compressor, bool compressed_exception_lists,
|
||||
const std::vector<u8>& exception_lists, const std::vector<u8>& main_data,
|
||||
std::map<ReuseID, GroupEntry>* reusable_groups, std::optional<ReuseID> reuse_id);
|
||||
static ConversionResult CompressAndWrite(File::IOFile* file, u64* bytes_written,
|
||||
Compressor* compressor, const u8* data, size_t size,
|
||||
size_t* size_out);
|
||||
|
Reference in New Issue
Block a user