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

@ -215,17 +215,40 @@ void CMemcardManager::CopyDeleteClick(wxCommandEvent& event)
case ID_COPYTOLEFT:
if ((index1 != -1) && (memoryCard[0] != NULL))
{
memoryCard[0]->CopyFrom(*memoryCard[1], index1);
memoryCard[0]->Save();
ReloadMemcard(m_Memcard1Path->GetPath().mb_str(), 0);
switch (memoryCard[0]->CopyFrom(*memoryCard[1], index1))
{
case FAIL:
wxMessageBox(wxT("Invalid bat.map or dir entry"), wxT("Failure"), wxOK);
break;
case NOMEMCARD:
wxMessageBox(wxT("File is not recognized as a memcard"), wxT("Failure"), wxOK);
break;
case SUCCESS:
memoryCard[0]->Save();
ReloadMemcard(m_Memcard1Path->GetPath().mb_str(), 0);
break;
}
}
break;
case ID_COPYTORIGHT:
if ((index0 != -1) && (memoryCard[1] != NULL))
{
memoryCard[1]->CopyFrom(*memoryCard[0], index0);
memoryCard[1]->Save();
ReloadMemcard(m_Memcard2Path->GetPath().mb_str(), 1);
switch (memoryCard[1]->CopyFrom(*memoryCard[0], index0))
{
case FAIL:
wxMessageBox(wxT("Invalid bat.map or dir entry"),
wxT("Error"), wxOK|wxICON_ERROR);
break;
case NOMEMCARD:
wxMessageBox(wxT("File is not recognized as a memcard"),
wxT("Error"), wxOK|wxICON_ERROR);
break;
case SUCCESS:
memoryCard[1]->Save();
ReloadMemcard(m_Memcard2Path->GetPath().mb_str(), 1);
break;
}
}
break;
case ID_FIXCHECKSUM:
@ -279,39 +302,43 @@ void CMemcardManager::CopyDeleteClick(wxCommandEvent& event)
break;
case GCSFAIL:
wxMessageBox(wxT("Imported file has gsc extension\nbut"
" does not have a correct header"), wxT("Error"),
wxOK|wxICON_ERROR);
" does not have a correct header"),
wxT("Error"), wxOK|wxICON_ERROR);
break;
case SAVFAIL:
wxMessageBox(wxT("Imported file has sav extension\nbut"
" does not have a correct header"), wxT("Error"),
wxOK|wxICON_ERROR);
" does not have a correct header"),
wxT("Error"), wxOK|wxICON_ERROR);
break;
case OPENFAIL:
wxMessageBox(wxT("Imported file could not be opened\nor"
" does not have a valid extension"), wxT("Error"),
wxOK|wxICON_ERROR);
" does not have a valid extension"),
wxT("Error"), wxOK|wxICON_ERROR);
break;
case GCS:
wxMessageBox(wxT("File converted to .gci"),
wxT("Success"),wxOK);
wxT("Success"), wxOK);
break;
case OUTOFBLOCKS:
freeBlocks = BE16(memoryCard[slot]->bat.FreeBlocks);
blocksOpen.Printf(wxT("Only %d blocks available"), freeBlocks);
wxMessageBox(blocksOpen,wxT("Failure"),wxOK);
wxMessageBox(blocksOpen, wxT("Error"), wxOK|wxICON_ERROR);
break;
case OUTOFDIRENTRIES:
wxMessageBox(wxT("No free dir index entries"),
wxT("Failure"),wxOK);
wxT("Error"), wxOK|wxICON_ERROR);
break;
case NOMEMCARD:
wxMessageBox(wxT("File is not recognized as a memcard"),
wxT("Failure"),wxOK);
wxT("Error"), wxOK|wxICON_ERROR);
break;
case TITLEPRESENT:
wxMessageBox(wxT("Memcard already has a save for this title"),
wxT("Failure"),wxOK);
wxT("Error"), wxOK|wxICON_ERROR);
break;
case FAIL:
wxMessageBox(wxT("Invalid bat.map or dir entry"),
wxT("Error"), wxOK|wxICON_ERROR);
break;
default:
memoryCard[slot]->Save();
@ -339,7 +366,26 @@ void CMemcardManager::CopyDeleteClick(wxCommandEvent& event)
const char * fileName = temp.ToAscii();
if (temp.length() > 0)
memoryCard[slot]->ExportGci(index2, fileName);
{
switch (memoryCard[slot]->ExportGci(index2, fileName))
{
case NOMEMCARD:
wxMessageBox(wxT("File is not recognized as a memcard"),
wxT("Error"), wxOK|wxICON_ERROR);
break;
case NOFILE:
wxMessageBox(wxT("Could not open gci for writing"),
wxT("Error"), wxOK|wxICON_ERROR);
break;
case FAIL:
//TODO: delete file if fails
wxMessageBox(wxT("Invalid bat.map or dir entry"),
wxT("Error"), wxOK|wxICON_ERROR);
break;
default:
break;
}
}
}
break;
case ID_DELETELEFT:
@ -348,10 +394,22 @@ void CMemcardManager::CopyDeleteClick(wxCommandEvent& event)
case ID_DELETERIGHT:
if (index2 != -1)
{
memoryCard[slot]->RemoveFile(index2);
memoryCard[slot]->Save();
slot == 1 ? ReloadMemcard(m_Memcard2Path->GetPath().mb_str(), 1)
switch (memoryCard[slot]->RemoveFile(index2))
{
case NOMEMCARD:
wxMessageBox(wxT("File is not recognized as a memcard"),
wxT("Error"), wxOK|wxICON_ERROR);
break;
case FAIL:
wxMessageBox(wxT("Invalid bat.map or dir entry"),
wxT("Error"), wxOK|wxICON_ERROR);
break;
case SUCCESS:
memoryCard[slot]->Save();
slot == 1 ? ReloadMemcard(m_Memcard2Path->GetPath().mb_str(), 1)
: ReloadMemcard(m_Memcard1Path->GetPath().mb_str(), 0);
break;
}
}
break;
}

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);