Update for GetFileData to check for incorrect values

in the first block, so no more crashing if your memcard
tries to use an invalid dir entry. Fixed titlePresent so
it checks the full filename instead of just the first
4 characters.

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@1211 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
LPFaint99
2008-11-19 06:37:35 +00:00
parent e069e5997a
commit 482cc819fb
3 changed files with 167 additions and 57 deletions

View File

@ -83,21 +83,40 @@ u32 GCMemcard::GetNumFiles()
return j;
}
bool GCMemcard::titlePresent(u32 gameCode)
bool GCMemcard::titlePresent(DEntry d)
{
if (!mcdFile) return 0;
//TODO: Clean up this function
bool equal = false;
if (!mcdFile) return false;
for (int i = 0; i < 127; i++)
{
if (BE32(dir.Dir[i].Gamecode) == gameCode)
return true;
if (BE32(dir.Dir[i].Gamecode) == BE32(d.Gamecode))
{
for ( int j = 0; j < 32; j++)
{
if (dir.Dir[i].Filename[j] != d.Filename[j])
{
equal = false;
break;
}
else
{
equal = true;
}
}
if (equal)
{
return true;
}
}
}
return false;
}
bool GCMemcard::RemoveFile(u32 index) //index in the directory array
u32 GCMemcard::RemoveFile(u32 index) //index in the directory array
{
if (!mcdFile) return false;
if (!mcdFile) return NOMEMCARD;
//backup the directory and bat (not really needed here but meh :P
dir_backup = dir;
@ -124,9 +143,14 @@ bool GCMemcard::RemoveFile(u32 index) //index in the directory array
bat.FreeBlocks[0] = u8(freeBlock >> 8);
bat.FreeBlocks[1] = u8(freeBlock);
t = new u8[GetFileSize(i) * 0x2000];
if (!GetFileData(i, t, true))
switch (GetFileData(i, t, true))
{
case NOMEMCARD:
delete[] t;
break;
case FAIL:
return FAIL;
break;
}
}
memset(&(dir.Dir[i]), 0xFF, 0x40);
@ -157,7 +181,7 @@ bool GCMemcard::RemoveFile(u32 index) //index in the directory array
FixChecksums();
Save();
return true;
return SUCCESS;
}
u32 GCMemcard::ImportFile(DEntry& direntry, u8* contents, int remove)
@ -172,7 +196,7 @@ u32 GCMemcard::ImportFile(DEntry& direntry, u8* contents, int remove)
{
return OUTOFBLOCKS;
}
if (!remove && titlePresent(BE32(direntry.Gamecode))) return TITLEPRESENT;
if (!remove && titlePresent(direntry)) return TITLEPRESENT;
// find first free data block -- assume no freespace fragmentation
int totalspace = (((u32)BE16(hdr.Size) * 16) - 5);
@ -265,38 +289,43 @@ u32 GCMemcard::ImportFile(DEntry& direntry, u8* contents, int remove)
return fileBlocks;
}
bool GCMemcard::GetFileData(u32 index, u8*dest, bool old) //index in the directory array
u32 GCMemcard::GetFileData(u32 index, u8*dest, bool old) //index in the directory array
{
if (!mcdFile) return false;
if (!mcdFile) return NOMEMCARD;
int block = BE16(dir.Dir[index].FirstBlock);
int saveLength = BE16(dir.Dir[index].BlockCount);
int memcardSize = BE16(hdr.Size) * 0x0010;
if (block + saveLength > memcardSize)
{
return FAIL;
}
if (!old)
{
int block = BE16(dir.Dir[index].FirstBlock);
int saveLength = BE16(dir.Dir[index].BlockCount) * 2000;
memcpy(dest,mc_data + 0x2000*(block-5), saveLength);
memcpy(dest,mc_data + 0x2000*(block-5), saveLength*0x2000);
}
else
{
int block = BE16(dir.Dir[index].FirstBlock);
int saveLength = BE16(dir.Dir[index].BlockCount);
int memcardSize = BE16(hdr.Size) * 0x0010;
assert(block != 0xFFFF);
assert(block > 0);
assert(block != 0xFFFF);
assert(block > 0);
do
{
memcpy(dest,mc_data + 0x2000 * (block - 5), 0x2000);
dest+=0x2000;
int nextblock = bswap16(bat.Map[block - 5]);
if(block + saveLength != memcardSize && nextblock > 0)
{ //Fixes for older memcards that were not initialized with FF
block = nextblock;
int nextblock = bswap16(bat.Map[block - 5]);
if (block + saveLength != memcardSize && nextblock > 0)
{//Fixes for older memcards that were not initialized with FF
block = nextblock;
}
else block = 0xffff;
}
while (block != 0xffff);
}
return true;
return SUCCESS;
}
u32 GCMemcard::GetFileSize(u32 index) //index in the directory array
@ -614,14 +643,23 @@ bool GCMemcard::FixChecksums()
}
u32 GCMemcard::CopyFrom(GCMemcard& source, u32 index)
{
if (!mcdFile) return 0;
if (!mcdFile) return NOMEMCARD;
DEntry d;
if (!source.GetFileInfo(index, d)) return 0;
u8 *t = new u8[source.GetFileSize(index) * 0x2000];
if(!source.GetFileData(index, t, true)) return 0;
switch (source.GetFileData(index, t, true))
{
case FAIL:
return FAIL;
case NOMEMCARD:
return NOMEMCARD;
default:
break;
}
u32 ret = ImportFile(d,t,0);
delete[] t;
@ -745,24 +783,34 @@ s32 GCMemcard::ImportGci(const char *fileName, std::string fileName2)
return ret;
}
bool GCMemcard::ExportGci(u32 index, const char *fileName)
u32 GCMemcard::ExportGci(u32 index, const char *fileName)
{
FILE *gci = fopen(fileName, "wb");
if (!gci) return false;
if (!gci) return NOFILE;
fseek(gci, 0, SEEK_SET);
DEntry d;
if (!this->GetFileInfo(index, d)) return false;
if (!this->GetFileInfo(index, d)) return NOMEMCARD;
assert(fwrite(&d, 1, 0x40, gci) == 0x40);
u8 *t = new u8[this->GetFileSize(index) * 0x2000];
if (!this->GetFileData(index, t, true)) return false;
switch(GetFileData(index, t, true))
{
case FAIL:
return FAIL;
case NOMEMCARD:
return NOMEMCARD;
default:
break;
}
fseek(gci, 0x40, SEEK_SET);
assert(fwrite(t, 1, 0x2000 * BE16(d.BlockCount), gci)== (unsigned) (0x2000 * BE16(d.BlockCount)));
fclose(gci);
delete []t;
return true;
return SUCCESS;
}
bool GCMemcard::Save()

View File

@ -32,9 +32,13 @@ enum
OUTOFBLOCKS,
OUTOFDIRENTRIES,
NOMEMCARD,
TITLEPRESENT
NOFILE,
TITLEPRESENT,
SUCCESS = 0x2000,
FAIL
};
class GCMemcard
{
void* mcdFile;
@ -144,7 +148,7 @@ public:
u32 GetNumFiles();
// Returns true if title already on memcard
bool titlePresent(u32 gameCode);
bool titlePresent(DEntry d);
// read directory entry
bool GetFileInfo(u32 index, DEntry& data);
@ -165,10 +169,10 @@ public:
// old determines if function uses old or new method of copying data
// some functions only work with old way, some only work with new way
// TODO: find a function that works for all calls or split into 2 functions
bool GetFileData(u32 index, u8* buffer, bool old);
u32 GetFileData(u32 index, u8* buffer, bool old);
// delete a file from the directory
bool RemoveFile(u32 index);
u32 RemoveFile(u32 index);
// adds the file to the directory and copies its contents
// if remove > 0 it will pad bat.map with 0's sifeof remove
@ -178,7 +182,7 @@ public:
u32 CopyFrom(GCMemcard& source, u32 index);
// writes a .gci file to disk containing index
bool ExportGci(u32 index, const char* fileName);
u32 ExportGci(u32 index, const char* fileName);
// reads a .gci/.gcs/.sav file and calls ImportFile or saves out a gci file
s32 ImportGci(const char* fileName, std::string fileName2);