1 // Copyright 2008 Dolphin Emulator Project
2 // Licensed under GPLv2+
3 // Refer to the license.txt file included.
4 
5 // WARNING Code not big-endian safe.
6 
7 // To create new compressed BLOBs, use CompressFileToBlob.
8 
9 // File format
10 // * Header
11 // * [Block Pointers interleaved with block hashes (hash of decompressed data)]
12 // * [Data]
13 
14 #pragma once
15 
16 #include <memory>
17 #include <string>
18 #include <vector>
19 
20 #include "Common/CommonTypes.h"
21 #include "Common/File.h"
22 #include "DiscIO/Blob.h"
23 
24 namespace DiscIO
25 {
26 static constexpr u32 GCZ_MAGIC = 0xB10BC001;
27 
28 // GCZ file structure:
29 // BlobHeader
30 // u64 offsetsToBlocks[n], top bit specifies whether the block is compressed, or not.
31 // compressed data
32 
33 // Blocks that won't compress to less than 97% of the original size are stored as-is.
34 struct CompressedBlobHeader  // 32 bytes
35 {
36   u32 magic_cookie;  // 0xB10BB10B
37   u32 sub_type;      // GC image, whatever
38   u64 compressed_data_size;
39   u64 data_size;
40   u32 block_size;
41   u32 num_blocks;
42 };
43 
44 class CompressedBlobReader : public SectorReader
45 {
46 public:
47   static std::unique_ptr<CompressedBlobReader> Create(File::IOFile file,
48                                                       const std::string& filename);
49   ~CompressedBlobReader();
50 
GetHeader()51   const CompressedBlobHeader& GetHeader() const { return m_header; }
52 
GetBlobType()53   BlobType GetBlobType() const override { return BlobType::GCZ; }
54 
GetRawSize()55   u64 GetRawSize() const override { return m_file_size; }
GetDataSize()56   u64 GetDataSize() const override { return m_header.data_size; }
IsDataSizeAccurate()57   bool IsDataSizeAccurate() const override { return true; }
58 
GetBlockSize()59   u64 GetBlockSize() const override { return m_header.block_size; }
HasFastRandomAccessInBlock()60   bool HasFastRandomAccessInBlock() const override { return false; }
GetCompressionMethod()61   std::string GetCompressionMethod() const override { return "Deflate"; }
62 
63   u64 GetBlockCompressedSize(u64 block_num) const;
64   bool GetBlock(u64 block_num, u8* out_ptr) override;
65 
66 private:
67   CompressedBlobReader(File::IOFile file, const std::string& filename);
68 
69   CompressedBlobHeader m_header;
70   std::vector<u64> m_block_pointers;
71   std::vector<u32> m_hashes;
72   int m_data_offset;
73   File::IOFile m_file;
74   u64 m_file_size;
75   std::vector<u8> m_zlib_buffer;
76   std::string m_file_name;
77 };
78 
79 }  // namespace DiscIO
80