diff --git a/Source/Core/DolphinWX/Src/MemcardManager.cpp b/Source/Core/DolphinWX/Src/MemcardManager.cpp index 74cd045fd6..971dc64875 100644 --- a/Source/Core/DolphinWX/Src/MemcardManager.cpp +++ b/Source/Core/DolphinWX/Src/MemcardManager.cpp @@ -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; } diff --git a/Source/Core/DolphinWX/Src/MemoryCards/GCMemcard.cpp b/Source/Core/DolphinWX/Src/MemoryCards/GCMemcard.cpp index 2629be2c2a..1efbbd3dfd 100644 --- a/Source/Core/DolphinWX/Src/MemoryCards/GCMemcard.cpp +++ b/Source/Core/DolphinWX/Src/MemoryCards/GCMemcard.cpp @@ -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() diff --git a/Source/Core/DolphinWX/Src/MemoryCards/GCMemcard.h b/Source/Core/DolphinWX/Src/MemoryCards/GCMemcard.h index ecde3a233d..9f5196e8b0 100644 --- a/Source/Core/DolphinWX/Src/MemoryCards/GCMemcard.h +++ b/Source/Core/DolphinWX/Src/MemoryCards/GCMemcard.h @@ -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);