summaryrefslogtreecommitdiff
path: root/Source/Core/DiscIO/CompressedBlob.cpp
diff options
context:
space:
mode:
authorLioncash <mathew1800@gmail.com>2014-12-01 03:18:24 -0500
committerLioncash <mathew1800@gmail.com>2014-12-01 03:18:24 -0500
commit6df67bf38f52151ee5efb64edb4bc60ecce601ef (patch)
treed1ca98e338aa1cb6cc69ff6d47054790108181de /Source/Core/DiscIO/CompressedBlob.cpp
parentf9ba7a0fb2d19d8a0dee6fe6098226745f746c77 (diff)
parent815b7bec967c773a3c8605dfe12a7cfefa844d31 (diff)
Merge pull request #1597 from unknownbrackets/gcz-tweaks
Tweaks to gcz compression / decompression
Diffstat (limited to 'Source/Core/DiscIO/CompressedBlob.cpp')
-rw-r--r--Source/Core/DiscIO/CompressedBlob.cpp85
1 files changed, 58 insertions, 27 deletions
diff --git a/Source/Core/DiscIO/CompressedBlob.cpp b/Source/Core/DiscIO/CompressedBlob.cpp
index be5647ef11..c3b79baf1c 100644
--- a/Source/Core/DiscIO/CompressedBlob.cpp
+++ b/Source/Core/DiscIO/CompressedBlob.cpp
@@ -163,11 +163,18 @@ bool CompressFileToBlob(const std::string& infile, const std::string& outfile, u
scrubbing = true;
}
+ z_stream z = {};
+ if (deflateInit(&z, 9) != Z_OK)
+ return false;
+
File::IOFile inf(infile, "rb");
File::IOFile f(outfile, "wb");
if (!f || !inf)
+ {
+ deflateEnd(&z);
return false;
+ }
callback("Files opened, ready to compress.", 0, arg);
@@ -195,6 +202,7 @@ bool CompressFileToBlob(const std::string& infile, const std::string& outfile, u
int num_compressed = 0;
int num_stored = 0;
int progress_monitor = std::max<int>(1, header.num_blocks / 1000);
+ bool was_cancelled = false;
for (u32 i = 0; i < header.num_blocks; i++)
{
@@ -206,27 +214,26 @@ bool CompressFileToBlob(const std::string& infile, const std::string& outfile, u
ratio = (int)(100 * position / inpos);
std::string temp = StringFromFormat("%i of %i blocks. Compression ratio %i%%", i, header.num_blocks, ratio);
- callback(temp, (float)i / (float)header.num_blocks, arg);
+ was_cancelled = !callback(temp, (float)i / (float)header.num_blocks, arg);
+ if (was_cancelled)
+ break;
}
offsets[i] = position;
- // u64 start = i * header.block_size;
- // u64 size = header.block_size;
- std::fill(in_buf, in_buf + header.block_size, 0);
+
+ size_t read_bytes;
if (scrubbing)
- DiscScrubber::GetNextBlock(inf, in_buf);
+ read_bytes = DiscScrubber::GetNextBlock(inf, in_buf);
else
- inf.ReadBytes(in_buf, header.block_size);
- z_stream z;
- memset(&z, 0, sizeof(z));
- z.zalloc = Z_NULL;
- z.zfree = Z_NULL;
- z.opaque = Z_NULL;
+ inf.ReadArray(in_buf, header.block_size, &read_bytes);
+ if (read_bytes < header.block_size)
+ std::fill(in_buf + read_bytes, in_buf + header.block_size, 0);
+
+ int retval = deflateReset(&z);
z.next_in = in_buf;
z.avail_in = header.block_size;
z.next_out = out_buf;
z.avail_out = block_size;
- int retval = deflateInit(&z, 9);
if (retval != Z_OK)
{
@@ -255,17 +262,24 @@ bool CompressFileToBlob(const std::string& infile, const std::string& outfile, u
position += comp_size;
num_compressed++;
}
-
- deflateEnd(&z);
}
header.compressed_data_size = position;
- // Okay, go back and fill in headers
- f.Seek(0, SEEK_SET);
- f.WriteArray(&header, 1);
- f.WriteArray(offsets, header.num_blocks);
- f.WriteArray(hashes, header.num_blocks);
+ if (was_cancelled)
+ {
+ // Remove the incomplete output file.
+ f.Close();
+ File::Delete(outfile);
+ }
+ else
+ {
+ // Okay, go back and fill in headers
+ f.Seek(0, SEEK_SET);
+ f.WriteArray(&header, 1);
+ f.WriteArray(offsets, header.num_blocks);
+ f.WriteArray(hashes, header.num_blocks);
+ }
cleanup:
// Cleanup
@@ -274,6 +288,8 @@ cleanup:
delete[] offsets;
delete[] hashes;
+ deflateEnd(&z);
+
DiscScrubber::Cleanup();
callback("Done compressing disc image.", 1.0f, arg);
return true;
@@ -299,22 +315,37 @@ bool DecompressBlobToFile(const std::string& infile, const std::string& outfile,
}
const CompressedBlobHeader &header = reader->GetHeader();
- u8* buffer = new u8[header.block_size];
- int progress_monitor = std::max<int>(1, header.num_blocks / 100);
-
- for (u64 i = 0; i < header.num_blocks; i++)
+ static const size_t BUFFER_BLOCKS = 32;
+ size_t buffer_size = header.block_size * BUFFER_BLOCKS;
+ u8* buffer = new u8[buffer_size];
+ u32 num_buffers = header.num_blocks / BUFFER_BLOCKS;
+ int progress_monitor = std::max<int>(1, num_buffers / 100);
+ bool was_cancelled = false;
+
+ for (u64 i = 0; i < num_buffers; i++)
{
if (i % progress_monitor == 0)
{
- callback("Unpacking", (float)i / (float)header.num_blocks, arg);
+ was_cancelled = !callback("Unpacking", (float)i / (float)num_buffers, arg);
+ if (was_cancelled)
+ break;
}
- reader->Read(i * header.block_size, header.block_size, buffer);
- f.WriteBytes(buffer, header.block_size);
+ reader->Read(i * buffer_size, buffer_size, buffer);
+ f.WriteBytes(buffer, buffer_size);
}
delete[] buffer;
- f.Resize(header.data_size);
+ if (was_cancelled)
+ {
+ // Remove the incomplete output file.
+ f.Close();
+ File::Delete(outfile);
+ }
+ else
+ {
+ f.Resize(header.data_size);
+ }
delete reader;