Merge pull request #1597 from unknownbrackets/gcz-tweaks
Tweaks to gcz compression / decompression
This commit is contained in:
commit
6df67bf38f
|
@ -66,7 +66,7 @@ private:
|
||||||
// Factory function - examines the path to choose the right type of IBlobReader, and returns one.
|
// Factory function - examines the path to choose the right type of IBlobReader, and returns one.
|
||||||
IBlobReader* CreateBlobReader(const std::string& filename);
|
IBlobReader* CreateBlobReader(const std::string& filename);
|
||||||
|
|
||||||
typedef void (*CompressCB)(const std::string& text, float percent, void* arg);
|
typedef bool (*CompressCB)(const std::string& text, float percent, void* arg);
|
||||||
|
|
||||||
bool CompressFileToBlob(const std::string& infile, const std::string& outfile, u32 sub_type = 0, int sector_size = 16384,
|
bool CompressFileToBlob(const std::string& infile, const std::string& outfile, u32 sub_type = 0, int sector_size = 16384,
|
||||||
CompressCB callback = nullptr, void *arg = nullptr);
|
CompressCB callback = nullptr, void *arg = nullptr);
|
||||||
|
|
|
@ -163,11 +163,18 @@ bool CompressFileToBlob(const std::string& infile, const std::string& outfile, u
|
||||||
scrubbing = true;
|
scrubbing = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
z_stream z = {};
|
||||||
|
if (deflateInit(&z, 9) != Z_OK)
|
||||||
|
return false;
|
||||||
|
|
||||||
File::IOFile inf(infile, "rb");
|
File::IOFile inf(infile, "rb");
|
||||||
File::IOFile f(outfile, "wb");
|
File::IOFile f(outfile, "wb");
|
||||||
|
|
||||||
if (!f || !inf)
|
if (!f || !inf)
|
||||||
|
{
|
||||||
|
deflateEnd(&z);
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
callback("Files opened, ready to compress.", 0, arg);
|
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_compressed = 0;
|
||||||
int num_stored = 0;
|
int num_stored = 0;
|
||||||
int progress_monitor = std::max<int>(1, header.num_blocks / 1000);
|
int progress_monitor = std::max<int>(1, header.num_blocks / 1000);
|
||||||
|
bool was_cancelled = false;
|
||||||
|
|
||||||
for (u32 i = 0; i < header.num_blocks; i++)
|
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);
|
ratio = (int)(100 * position / inpos);
|
||||||
|
|
||||||
std::string temp = StringFromFormat("%i of %i blocks. Compression ratio %i%%", i, header.num_blocks, ratio);
|
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;
|
offsets[i] = position;
|
||||||
// u64 start = i * header.block_size;
|
|
||||||
// u64 size = header.block_size;
|
size_t read_bytes;
|
||||||
std::fill(in_buf, in_buf + header.block_size, 0);
|
|
||||||
if (scrubbing)
|
if (scrubbing)
|
||||||
DiscScrubber::GetNextBlock(inf, in_buf);
|
read_bytes = DiscScrubber::GetNextBlock(inf, in_buf);
|
||||||
else
|
else
|
||||||
inf.ReadBytes(in_buf, header.block_size);
|
inf.ReadArray(in_buf, header.block_size, &read_bytes);
|
||||||
z_stream z;
|
if (read_bytes < header.block_size)
|
||||||
memset(&z, 0, sizeof(z));
|
std::fill(in_buf + read_bytes, in_buf + header.block_size, 0);
|
||||||
z.zalloc = Z_NULL;
|
|
||||||
z.zfree = Z_NULL;
|
int retval = deflateReset(&z);
|
||||||
z.opaque = Z_NULL;
|
|
||||||
z.next_in = in_buf;
|
z.next_in = in_buf;
|
||||||
z.avail_in = header.block_size;
|
z.avail_in = header.block_size;
|
||||||
z.next_out = out_buf;
|
z.next_out = out_buf;
|
||||||
z.avail_out = block_size;
|
z.avail_out = block_size;
|
||||||
int retval = deflateInit(&z, 9);
|
|
||||||
|
|
||||||
if (retval != Z_OK)
|
if (retval != Z_OK)
|
||||||
{
|
{
|
||||||
|
@ -255,17 +262,24 @@ bool CompressFileToBlob(const std::string& infile, const std::string& outfile, u
|
||||||
position += comp_size;
|
position += comp_size;
|
||||||
num_compressed++;
|
num_compressed++;
|
||||||
}
|
}
|
||||||
|
|
||||||
deflateEnd(&z);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
header.compressed_data_size = position;
|
header.compressed_data_size = position;
|
||||||
|
|
||||||
// Okay, go back and fill in headers
|
if (was_cancelled)
|
||||||
f.Seek(0, SEEK_SET);
|
{
|
||||||
f.WriteArray(&header, 1);
|
// Remove the incomplete output file.
|
||||||
f.WriteArray(offsets, header.num_blocks);
|
f.Close();
|
||||||
f.WriteArray(hashes, header.num_blocks);
|
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:
|
||||||
// Cleanup
|
// Cleanup
|
||||||
|
@ -274,6 +288,8 @@ cleanup:
|
||||||
delete[] offsets;
|
delete[] offsets;
|
||||||
delete[] hashes;
|
delete[] hashes;
|
||||||
|
|
||||||
|
deflateEnd(&z);
|
||||||
|
|
||||||
DiscScrubber::Cleanup();
|
DiscScrubber::Cleanup();
|
||||||
callback("Done compressing disc image.", 1.0f, arg);
|
callback("Done compressing disc image.", 1.0f, arg);
|
||||||
return true;
|
return true;
|
||||||
|
@ -299,22 +315,37 @@ bool DecompressBlobToFile(const std::string& infile, const std::string& outfile,
|
||||||
}
|
}
|
||||||
|
|
||||||
const CompressedBlobHeader &header = reader->GetHeader();
|
const CompressedBlobHeader &header = reader->GetHeader();
|
||||||
u8* buffer = new u8[header.block_size];
|
static const size_t BUFFER_BLOCKS = 32;
|
||||||
int progress_monitor = std::max<int>(1, header.num_blocks / 100);
|
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 < header.num_blocks; i++)
|
for (u64 i = 0; i < num_buffers; i++)
|
||||||
{
|
{
|
||||||
if (i % progress_monitor == 0)
|
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);
|
reader->Read(i * buffer_size, buffer_size, buffer);
|
||||||
f.WriteBytes(buffer, header.block_size);
|
f.WriteBytes(buffer, buffer_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
delete[] buffer;
|
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;
|
delete reader;
|
||||||
|
|
||||||
|
|
|
@ -124,24 +124,27 @@ bool SetupScrub(const std::string& filename, int block_size)
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GetNextBlock(File::IOFile& in, u8* buffer)
|
size_t GetNextBlock(File::IOFile& in, u8* buffer)
|
||||||
{
|
{
|
||||||
u64 CurrentOffset = m_BlockCount * m_BlockSize;
|
u64 CurrentOffset = m_BlockCount * m_BlockSize;
|
||||||
u64 i = CurrentOffset / CLUSTER_SIZE;
|
u64 i = CurrentOffset / CLUSTER_SIZE;
|
||||||
|
|
||||||
|
size_t ReadBytes = 0;
|
||||||
if (m_isScrubbing && m_FreeTable[i])
|
if (m_isScrubbing && m_FreeTable[i])
|
||||||
{
|
{
|
||||||
DEBUG_LOG(DISCIO, "Freeing 0x%016" PRIx64, CurrentOffset);
|
DEBUG_LOG(DISCIO, "Freeing 0x%016" PRIx64, CurrentOffset);
|
||||||
std::fill(buffer, buffer + m_BlockSize, 0xFF);
|
std::fill(buffer, buffer + m_BlockSize, 0xFF);
|
||||||
in.Seek(m_BlockSize, SEEK_CUR);
|
in.Seek(m_BlockSize, SEEK_CUR);
|
||||||
|
ReadBytes = m_BlockSize;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
DEBUG_LOG(DISCIO, "Used 0x%016" PRIx64, CurrentOffset);
|
DEBUG_LOG(DISCIO, "Used 0x%016" PRIx64, CurrentOffset);
|
||||||
in.ReadBytes(buffer, m_BlockSize);
|
in.ReadArray(buffer, m_BlockSize, &ReadBytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_BlockCount++;
|
m_BlockCount++;
|
||||||
|
return ReadBytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Cleanup()
|
void Cleanup()
|
||||||
|
|
|
@ -25,7 +25,7 @@ namespace DiscScrubber
|
||||||
{
|
{
|
||||||
|
|
||||||
bool SetupScrub(const std::string& filename, int block_size);
|
bool SetupScrub(const std::string& filename, int block_size);
|
||||||
void GetNextBlock(File::IOFile& in, u8* buffer);
|
size_t GetNextBlock(File::IOFile& in, u8* buffer);
|
||||||
void Cleanup();
|
void Cleanup();
|
||||||
|
|
||||||
} // namespace DiscScrubber
|
} // namespace DiscScrubber
|
||||||
|
|
|
@ -1123,14 +1123,14 @@ void CGameListCtrl::OnWiki(wxCommandEvent& WXUNUSED (event))
|
||||||
WxUtils::Launch(wikiUrl);
|
WxUtils::Launch(wikiUrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CGameListCtrl::MultiCompressCB(const std::string& text, float percent, void* arg)
|
bool CGameListCtrl::MultiCompressCB(const std::string& text, float percent, void* arg)
|
||||||
{
|
{
|
||||||
percent = (((float)m_currentItem) + percent) / (float)m_numberItem;
|
percent = (((float)m_currentItem) + percent) / (float)m_numberItem;
|
||||||
wxString textString(StrToWxStr(StringFromFormat("%s (%i/%i) - %s",
|
wxString textString(StrToWxStr(StringFromFormat("%s (%i/%i) - %s",
|
||||||
m_currentFilename.c_str(), (int)m_currentItem+1,
|
m_currentFilename.c_str(), (int)m_currentItem+1,
|
||||||
(int)m_numberItem, text.c_str())));
|
(int)m_numberItem, text.c_str())));
|
||||||
|
|
||||||
((wxProgressDialog*)arg)->Update((int)(percent*1000), textString);
|
return ((wxProgressDialog*)arg)->Update((int)(percent*1000), textString);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CGameListCtrl::OnMultiCompressISO(wxCommandEvent& /*event*/)
|
void CGameListCtrl::OnMultiCompressISO(wxCommandEvent& /*event*/)
|
||||||
|
@ -1162,6 +1162,7 @@ void CGameListCtrl::CompressSelection(bool _compress)
|
||||||
1000,
|
1000,
|
||||||
this,
|
this,
|
||||||
wxPD_APP_MODAL |
|
wxPD_APP_MODAL |
|
||||||
|
wxPD_CAN_ABORT |
|
||||||
wxPD_ELAPSED_TIME | wxPD_ESTIMATED_TIME | wxPD_REMAINING_TIME |
|
wxPD_ELAPSED_TIME | wxPD_ESTIMATED_TIME | wxPD_REMAINING_TIME |
|
||||||
wxPD_SMOOTH
|
wxPD_SMOOTH
|
||||||
);
|
);
|
||||||
|
@ -1235,9 +1236,9 @@ void CGameListCtrl::CompressSelection(bool _compress)
|
||||||
Update();
|
Update();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CGameListCtrl::CompressCB(const std::string& text, float percent, void* arg)
|
bool CGameListCtrl::CompressCB(const std::string& text, float percent, void* arg)
|
||||||
{
|
{
|
||||||
((wxProgressDialog*)arg)->
|
return ((wxProgressDialog*)arg)->
|
||||||
Update((int)(percent*1000), StrToWxStr(text));
|
Update((int)(percent*1000), StrToWxStr(text));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1300,6 +1301,7 @@ void CGameListCtrl::OnCompressISO(wxCommandEvent& WXUNUSED (event))
|
||||||
1000,
|
1000,
|
||||||
this,
|
this,
|
||||||
wxPD_APP_MODAL |
|
wxPD_APP_MODAL |
|
||||||
|
wxPD_CAN_ABORT |
|
||||||
wxPD_ELAPSED_TIME | wxPD_ESTIMATED_TIME | wxPD_REMAINING_TIME |
|
wxPD_ELAPSED_TIME | wxPD_ESTIMATED_TIME | wxPD_REMAINING_TIME |
|
||||||
wxPD_SMOOTH
|
wxPD_SMOOTH
|
||||||
);
|
);
|
||||||
|
|
|
@ -113,6 +113,6 @@ private:
|
||||||
static size_t m_currentItem;
|
static size_t m_currentItem;
|
||||||
static std::string m_currentFilename;
|
static std::string m_currentFilename;
|
||||||
static size_t m_numberItem;
|
static size_t m_numberItem;
|
||||||
static void CompressCB(const std::string& text, float percent, void* arg);
|
static bool CompressCB(const std::string& text, float percent, void* arg);
|
||||||
static void MultiCompressCB(const std::string& text, float percent, void* arg);
|
static bool MultiCompressCB(const std::string& text, float percent, void* arg);
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue