mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2024-11-14 21:37:52 -07:00
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:
parent
e069e5997a
commit
482cc819fb
@ -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;
|
||||
}
|
||||
|
@ -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()
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user