mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-01-10 08:09:26 +01:00
another patch from baby.lueshi: DiscScrubber doesn't modify original file anymore, and just returns the "real" or "free'd" buffer inline with compression - so it should be a little faster too :)
git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@5032 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
parent
98ddeadbbf
commit
5f19fb22b2
@ -158,6 +158,8 @@ void CompressedBlobReader::GetBlock(u64 block_num, u8 *out_ptr)
|
||||
bool CompressFileToBlob(const char* infile, const char* outfile, u32 sub_type,
|
||||
int block_size, CompressCB callback, void* arg)
|
||||
{
|
||||
bool scrubbing = false;
|
||||
|
||||
if (IsCompressedBlob(infile))
|
||||
{
|
||||
PanicAlert("%s is already compressed! Cannot compress it further.", infile);
|
||||
@ -166,11 +168,13 @@ bool CompressFileToBlob(const char* infile, const char* outfile, u32 sub_type,
|
||||
|
||||
if (sub_type == 1)
|
||||
{
|
||||
if (!DiscScrubber::Scrub(infile, callback, arg))
|
||||
if (!DiscScrubber::SetupScrub(infile, block_size))
|
||||
{
|
||||
PanicAlert("%s failed to be scrubbed. Probably the image is corrupt.", infile);
|
||||
return false;
|
||||
}
|
||||
|
||||
scrubbing = true;
|
||||
}
|
||||
|
||||
FILE* inf = fopen(infile, "rb");
|
||||
@ -230,7 +234,10 @@ bool CompressFileToBlob(const char* infile, const char* outfile, u32 sub_type,
|
||||
// u64 start = i * header.block_size;
|
||||
// u64 size = header.block_size;
|
||||
std::fill(in_buf, in_buf + header.block_size, 0);
|
||||
fread(in_buf, header.block_size, 1, inf);
|
||||
if (scrubbing)
|
||||
DiscScrubber::GetNextBlock(inf, in_buf);
|
||||
else
|
||||
fread(in_buf, header.block_size, 1, inf);
|
||||
z_stream z;
|
||||
memset(&z, 0, sizeof(z));
|
||||
z.zalloc = Z_NULL;
|
||||
@ -289,6 +296,7 @@ cleanup:
|
||||
delete[] hashes;
|
||||
fclose(f);
|
||||
fclose(inf);
|
||||
DiscScrubber::Cleanup();
|
||||
callback("Done compressing disc image.", 1.0f, arg);
|
||||
return true;
|
||||
}
|
||||
|
@ -32,12 +32,15 @@ namespace DiscScrubber
|
||||
|
||||
#define CLUSTER_SIZE 0x8000
|
||||
|
||||
static u8* m_Sector1;
|
||||
static u8* m_FreeTable;
|
||||
static u64 m_FileSize;
|
||||
u8* m_FreeTable = NULL;
|
||||
u64 m_FileSize;
|
||||
u64 m_BlockCount;
|
||||
u32 m_BlockSize;
|
||||
int m_BlocksPerCluster;
|
||||
bool m_isScrubbing = false;
|
||||
|
||||
static std::string m_Filename;
|
||||
static IVolume* m_Disc = NULL;
|
||||
std::string m_Filename;
|
||||
IVolume* m_Disc = NULL;
|
||||
|
||||
struct SPartitionHeader
|
||||
{
|
||||
@ -72,12 +75,11 @@ struct SPartitionGroup
|
||||
u64 PartitionsOffset;
|
||||
std::vector<SPartition> PartitionsVec;
|
||||
};
|
||||
static SPartitionGroup PartitionGroup[4];
|
||||
SPartitionGroup PartitionGroup[4];
|
||||
|
||||
|
||||
void MarkAsUsed(u64 _Offset, u64 _Size);
|
||||
void MarkAsUsedE(u64 _PartitionDataOffset, u64 _Offset, u64 _Size);
|
||||
bool MarkAsScrubbed(const char* filename);
|
||||
void ReadFromDisc(u64 _Offset, u64 _Length, u32& _Buffer);
|
||||
void ReadFromDisc(u64 _Offset, u64 _Length, u64& _Buffer);
|
||||
void ReadFromVolume(u64 _Offset, u64 _Length, u32& _Buffer);
|
||||
@ -102,10 +104,19 @@ u32 IsScrubbed(const char* filename)
|
||||
return ScrubbedFlag;
|
||||
}
|
||||
|
||||
bool Scrub(const char* filename, CompressCB callback, void* arg)
|
||||
bool SetupScrub(const char* filename, int block_size)
|
||||
{
|
||||
bool success = true;
|
||||
m_Filename = std::string(filename);
|
||||
m_BlockSize = block_size;
|
||||
|
||||
if (CLUSTER_SIZE % m_BlockSize != 0)
|
||||
{
|
||||
ERROR_LOG(DISCIO, "block size %i is not a factor of 0x8000, scrubbing not possible", m_BlockSize);
|
||||
return false;
|
||||
}
|
||||
|
||||
m_BlocksPerCluster = CLUSTER_SIZE / m_BlockSize;
|
||||
|
||||
u32 version = IsScrubbed(filename);
|
||||
if (version && version < SCRUBBER_VERSION)
|
||||
@ -115,7 +126,6 @@ bool Scrub(const char* filename, CompressCB callback, void* arg)
|
||||
}
|
||||
else if (version)
|
||||
{
|
||||
callback("DiscScrubber: This disc is already scrubbed", 0, arg);
|
||||
NOTICE_LOG(DISCIO, "%s is already scrubbed, skipping...", filename);
|
||||
return success;
|
||||
}
|
||||
@ -132,75 +142,53 @@ bool Scrub(const char* filename, CompressCB callback, void* arg)
|
||||
// Table of free blocks
|
||||
m_FreeTable = new u8[numClusters];
|
||||
std::fill(m_FreeTable, m_FreeTable + numClusters, 1);
|
||||
// Fill the dummy all 1 block
|
||||
m_Sector1 = new u8[CLUSTER_SIZE];
|
||||
std::fill(m_Sector1, m_Sector1 + CLUSTER_SIZE, 0xFF);
|
||||
|
||||
// Fill out table of free blocks
|
||||
callback("DiscScrubber: Parsing...", 0, arg);
|
||||
success = ParseDisc();
|
||||
// Done with it; need it closed for the next part
|
||||
delete m_Disc;
|
||||
m_Disc = NULL;
|
||||
|
||||
// Open file
|
||||
FILE* pFile = fopen(filename, "r+b");
|
||||
if (!pFile)
|
||||
{
|
||||
ERROR_LOG(DISCIO, "DiscScrubber failed to open %s", filename);
|
||||
success = false;
|
||||
}
|
||||
m_BlockCount = 0;
|
||||
|
||||
// Let's not touch the file if we've failed up to here :p
|
||||
if (!success)
|
||||
goto cleanup;
|
||||
|
||||
// Modify file, obeying the table of free blocks
|
||||
NOTICE_LOG(DISCIO, "Removing garbage data...go get some coffee :)");
|
||||
for (u32 i = 0; i < numClusters; i++)
|
||||
{
|
||||
u64 CurrentOffset = (u64)i * CLUSTER_SIZE;
|
||||
|
||||
if (m_FreeTable[i])
|
||||
{
|
||||
DEBUG_LOG(DISCIO, "Freeing 0x%016llx", CurrentOffset);
|
||||
// Area is unused so fill with 1s
|
||||
fseek(pFile, CurrentOffset, SEEK_SET);
|
||||
success |= fwrite(m_Sector1, CLUSTER_SIZE, 1, pFile) == CLUSTER_SIZE;
|
||||
|
||||
if (!success)
|
||||
{
|
||||
PanicAlert("DiscScrubber failure");
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG_LOG(DISCIO, "Used 0x%016llx", CurrentOffset);
|
||||
}
|
||||
|
||||
// Update progress dialog
|
||||
if (i % (numClusters / 1000) == 0)
|
||||
{
|
||||
char temp[512];
|
||||
sprintf(temp, "DiscScrubber: %x/%x (%s)", i, numClusters, m_FreeTable[i] ? "Free" : "Used");
|
||||
callback(temp, (float)i / (float)numClusters, arg);
|
||||
}
|
||||
}
|
||||
NOTICE_LOG(DISCIO, "Done removing garbage data");
|
||||
|
||||
if (success)
|
||||
if (!MarkAsScrubbed(filename))
|
||||
ERROR_LOG(DISCIO, "Really weird - failed to mark scrubbed disk as scrubbed :s");
|
||||
|
||||
cleanup:
|
||||
if (pFile) fclose(pFile);
|
||||
delete[] m_Sector1;
|
||||
delete[] m_FreeTable;
|
||||
Cleanup();
|
||||
|
||||
m_isScrubbing = success;
|
||||
return success;
|
||||
}
|
||||
|
||||
void GetNextBlock(FILE* in, u8* buffer)
|
||||
{
|
||||
u64 CurrentOffset = m_BlockCount * m_BlockSize;
|
||||
u64 i = CurrentOffset / CLUSTER_SIZE;
|
||||
|
||||
if (m_isScrubbing && m_FreeTable[i])
|
||||
{
|
||||
DEBUG_LOG(DISCIO, "Freeing 0x%016llx", CurrentOffset);
|
||||
std::fill(buffer, buffer + m_BlockSize, 0xFF);
|
||||
fseek(in, m_BlockSize, SEEK_CUR);
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG_LOG(DISCIO, "Used 0x%016llx", CurrentOffset);
|
||||
fread(buffer, m_BlockSize, 1, in);
|
||||
}
|
||||
|
||||
m_BlockCount++;
|
||||
}
|
||||
|
||||
void Cleanup()
|
||||
{
|
||||
if (m_FreeTable) delete[] m_FreeTable;
|
||||
m_FreeTable = NULL;
|
||||
m_FileSize = 0;
|
||||
m_BlockCount = 0;
|
||||
m_BlockSize = 0;
|
||||
m_BlocksPerCluster = 0;
|
||||
m_isScrubbing = false;
|
||||
}
|
||||
|
||||
void MarkAsUsed(u64 _Offset, u64 _Size)
|
||||
{
|
||||
u64 CurrentOffset = _Offset;
|
||||
@ -233,20 +221,6 @@ void MarkAsUsedE(u64 _PartitionDataOffset, u64 _Offset, u64 _Size)
|
||||
MarkAsUsed(Offset, Size);
|
||||
}
|
||||
|
||||
bool MarkAsScrubbed(const char* filename)
|
||||
{
|
||||
FILE* f = fopen(filename, "r+b");
|
||||
|
||||
if (!f)
|
||||
return false;
|
||||
|
||||
u8 ScrubbedFlag[1] = {SCRUBBER_VERSION};
|
||||
fseek(f, 0x80, SEEK_SET);
|
||||
bool success = fwrite(ScrubbedFlag, 1, 1, f) == 1;
|
||||
fclose(f);
|
||||
return success;
|
||||
}
|
||||
|
||||
// Helper functions for RAW reading the BE discs
|
||||
void ReadFromDisc(u64 _Offset, u64 _Length, u32& _Buffer)
|
||||
{
|
||||
|
@ -39,7 +39,9 @@ namespace DiscScrubber
|
||||
|
||||
u32 IsScrubbed(const char* filename);
|
||||
|
||||
bool Scrub(const char* filename, CompressCB callback = 0, void* arg = 0);
|
||||
bool SetupScrub(const char* filename, int block_size);
|
||||
void GetNextBlock(FILE* in, u8* buffer);
|
||||
void Cleanup();
|
||||
|
||||
} // namespace DiscScrubber
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user