git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@367 8ced0084-cf51-0410-be5f-012b33b47a6e

This commit is contained in:
XTra.KrazzY 2008-08-28 07:42:48 +00:00
parent e764723832
commit 8a33d6787b
2 changed files with 154 additions and 101 deletions

View File

@ -25,151 +25,195 @@
ChunkFile::ChunkFile(const char *filename, ChunkFileMode _mode) ChunkFile::ChunkFile(const char *filename, ChunkFileMode _mode)
{ {
mode = _mode; mode = _mode;
data = 0; data = 0;
didFail = false; didFail = false;
f = fopen(filename, mode == MODE_WRITE ? "wb" : "rb"); f = fopen(filename, mode == MODE_WRITE ? "wb" : "rb");
if (!f) { if (!f) {
didFail = true; didFail = true;
return; return;
} }
fseek(f, 0, SEEK_END); fseek(f, 0, SEEK_END);
size = ftell(f); size = ftell(f);
eof = size; eof = size;
stack_ptr = 0; stack_ptr = 0;
} }
ChunkFile::~ChunkFile() ChunkFile::~ChunkFile()
{ {
if (f) if (f)
fclose(f); fclose(f);
} }
int ChunkFile::ReadInt() int ChunkFile::ReadInt()
{ {
int x; int x;
fread(&x, 4, 1, f); fread(&x, 4, 1, f);
return x; return x;
} }
void ChunkFile::WriteInt(int x) void ChunkFile::WriteInt(int x)
{ {
fwrite(&x, 4, 1, f); fwrite(&x, 4, 1, f);
} }
bool ChunkFile::Do(void *ptr, int size) bool ChunkFile::Do(void *ptr, int size)
{ {
int sz; int sz;
switch (mode) { switch (mode) {
case MODE_READ: case MODE_READ:
sz = ReadInt(); sz = ReadInt();
if (sz != size) if (sz != size)
return false; return false;
fread(ptr, size, 1, f); fread(ptr, size, 1, f);
fseek(f, ((size + 3) & ~3) - size, SEEK_CUR); fseek(f, ((size + 3) & ~3) - size, SEEK_CUR);
break; break;
case MODE_WRITE: case MODE_WRITE:
WriteInt(size); WriteInt(size);
fwrite(ptr, size, 1, f); fwrite(ptr, size, 1, f);
fseek(f, ((size + 3) & ~3) - size, SEEK_CUR); fseek(f, ((size + 3) & ~3) - size, SEEK_CUR);
break; break;
case MODE_VERIFY: case MODE_VERIFY:
sz = ReadInt(); sz = ReadInt();
if (sz != size) if (sz != size)
return false; return false;
fseek(f, (size + 3) & ~3, SEEK_CUR); fseek(f, (size + 3) & ~3, SEEK_CUR);
break; break;
} }
return true; return true;
}
// Do variable size array (probably heap-allocated)
bool DoArray(void *ptr, int size, int arrSize) {
int sz;
if(ptr == NULL)
return false;
switch (mode) {
case MODE_READ:
sz = ReadInt();
if (sz != size)
return false;
sz = ReadInt();
if (sz != arrSize)
return false;
for(int i = 0; i < arrSize; i++) {
fread(ptr[i], size, 1, f);
fseek(f, ((size + 3) & ~3) - size, SEEK_CUR);
}
break;
case MODE_WRITE:
WriteInt(size);
WriteInt(arrSize);
for(int i = 0; i < arrSize; i++) {
fwrite(ptr[i], size, 1, f);
fseek(f, ((size + 3) & ~3) - size, SEEK_CUR);
}
break;
case MODE_VERIFY:
sz = ReadInt();
if (sz != size)
return false;
sz = ReadInt();
if (sz != arrSize)
return false;
for(int i = 0; i < arrSize; i++)
fseek(f, (size + 3) & ~3, SEEK_CUR);
break;
}
return true;
} }
//let's get into the business //let's get into the business
bool ChunkFile::Descend(const char *cid) bool ChunkFile::Descend(const char *cid)
{ {
unsigned int id = *reinterpret_cast<const unsigned int*>(cid); unsigned int id = *reinterpret_cast<const unsigned int*>(cid);
if (mode == MODE_READ) if (mode == MODE_READ)
{ {
bool found = false; bool found = false;
int startPos = ftell(f); int startPos = ftell(f);
ChunkInfo temp = stack[stack_ptr]; ChunkInfo temp = stack[stack_ptr];
//save information to restore after the next Ascend //save information to restore after the next Ascend
stack[stack_ptr].parentStartLocation = startPos; stack[stack_ptr].parentStartLocation = startPos;
stack[stack_ptr].parentEOF = eof; stack[stack_ptr].parentEOF = eof;
unsigned int firstID = 0; unsigned int firstID = 0;
//let's search through children.. //let's search through children..
while (ftell(f) < eof) while (ftell(f) < eof)
{ {
stack[stack_ptr].ID = ReadInt(); stack[stack_ptr].ID = ReadInt();
if (firstID == 0) if (firstID == 0)
firstID = stack[stack_ptr].ID|1; firstID = stack[stack_ptr].ID|1;
stack[stack_ptr].length = ReadInt(); stack[stack_ptr].length = ReadInt();
stack[stack_ptr].startLocation = ftell(f); stack[stack_ptr].startLocation = ftell(f);
if (stack[stack_ptr].ID == id) if (stack[stack_ptr].ID == id)
{ {
found = true; found = true;
break; break;
} }
else else
{ {
fseek(f, stack[stack_ptr].length, SEEK_CUR); //try next block fseek(f, stack[stack_ptr].length, SEEK_CUR); //try next block
} }
} }
//if we found nothing, return false so the caller can skip this //if we found nothing, return false so the caller can skip this
if (!found) if (!found)
{ {
stack[stack_ptr] = temp; stack[stack_ptr] = temp;
fseek(f, stack[stack_ptr].parentStartLocation, SEEK_SET); fseek(f, stack[stack_ptr].parentStartLocation, SEEK_SET);
return false; return false;
} }
//descend into it //descend into it
//pos was set inside the loop above //pos was set inside the loop above
eof = stack[stack_ptr].startLocation + stack[stack_ptr].length; eof = stack[stack_ptr].startLocation + stack[stack_ptr].length;
stack_ptr++; stack_ptr++;
return true; return true;
} }
else else
{ {
//write a chunk id, and prepare for filling in length later //write a chunk id, and prepare for filling in length later
WriteInt(id); WriteInt(id);
WriteInt(0); //will be filled in by Ascend WriteInt(0); //will be filled in by Ascend
stack[stack_ptr].startLocation = ftell(f); stack[stack_ptr].startLocation = ftell(f);
stack_ptr++; stack_ptr++;
return true; return true;
} }
} }
//let's ascend out //let's ascend out
void ChunkFile::Ascend() void ChunkFile::Ascend()
{ {
if (mode == MODE_READ) if (mode == MODE_READ)
{ {
//ascend, and restore information //ascend, and restore information
stack_ptr--; stack_ptr--;
fseek(f, stack[stack_ptr].parentStartLocation, SEEK_SET); fseek(f, stack[stack_ptr].parentStartLocation, SEEK_SET);
eof = stack[stack_ptr].parentEOF; eof = stack[stack_ptr].parentEOF;
} }
else else
{ {
stack_ptr--; stack_ptr--;
//now fill in the written length automatically //now fill in the written length automatically
int posNow = ftell(f); int posNow = ftell(f);
fseek(f, stack[stack_ptr].startLocation - 4, SEEK_SET); fseek(f, stack[stack_ptr].startLocation - 4, SEEK_SET);
WriteInt(posNow - stack[stack_ptr].startLocation); WriteInt(posNow - stack[stack_ptr].startLocation);
fseek(f, posNow, SEEK_SET); fseek(f, posNow, SEEK_SET);
} }
} }
int ChunkFile::GetCurrentChunkSize() int ChunkFile::GetCurrentChunkSize()
{ {
if (stack_ptr) if (stack_ptr)
return stack[stack_ptr - 1].length; return stack[stack_ptr - 1].length;
else else
return 0; return 0;
} }

View File

@ -80,26 +80,35 @@ public:
//void Do(int &i); //void Do(int &i);
//bool Do(std::string &s); //bool Do(std::string &s);
bool Do(void *ptr, int size); bool Do(void *ptr, int size);
bool DoArray(void *ptr, int size, int arrSize);
// Future // Future
// bool DoCompressed(void *ptr, int size) // bool DoCompressed(void *ptr, int size)
// Store maps to file. Very useful. // Store maps to file. Very useful.
template<class T> template<class T>
void Do(std::map<u32, T> &x) { bool Do(std::map<u32, T> &x) {
return false;
} }
// Store vectors. // Store vectors.
template<class T> template<class T>
void Do(std::vector<T> &x) { bool Do(std::vector<T> &x) {
return false;
} }
// Disable size checks to save size for variable size array storing
template<clsas T>
bool DoArray(T *x, int size, int arrSize) {
return DoArray((void *)x, size, arrSize);
}
// Handle everything else // Handle everything else
template<class T> template<class T>
void Do(T &x) { bool Do(T &x) {
Do((void *)&x, sizeof(x)); return Do((void *)&x, sizeof(x));
} }
int GetCurrentChunkSize(); int GetCurrentChunkSize();