From 4bbc4325062cd627415fc45042aa6e81b9090d71 Mon Sep 17 00:00:00 2001 From: LPFaint99 Date: Sat, 18 Jul 2009 01:16:17 +0000 Subject: [PATCH] Add log for MEMCARD_MANAGER (requires an almost complete rebuild :( sorry) Fix a crash when trying to delete a save from a memcard that the DEntry order does not match the starting block order add the option to export saves as GCS and SAV Buildfix for external MEMCARD_MANAGER git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@3826 8ced0084-cf51-0410-be5f-012b33b47a6e --- Externals/Memcard Manager/Memcard Manager.sln | 8 + .../Memcard Manager/Memcard Manager.vcproj | 297 ++++++++++++++++++ Externals/Memcard Manager/src/MCMdebug.cpp | 2 +- Source/Core/Common/Src/Log.h | 3 +- Source/Core/Common/Src/LogManager.cpp | 7 +- Source/Core/DolphinWX/Src/MemcardManager.cpp | 6 +- .../DolphinWX/Src/MemoryCards/GCMemcard.cpp | 122 +++++-- .../DolphinWX/Src/MemoryCards/GCMemcard.h | 4 + 8 files changed, 408 insertions(+), 41 deletions(-) diff --git a/Externals/Memcard Manager/Memcard Manager.sln b/Externals/Memcard Manager/Memcard Manager.sln index 37a17fe460..47ebf646de 100644 --- a/Externals/Memcard Manager/Memcard Manager.sln +++ b/Externals/Memcard Manager/Memcard Manager.sln @@ -4,11 +4,19 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MemCardManager", "Memcard M EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 Release|Win32 = Release|Win32 Release|x64 = Release|x64 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution + {413653C3-59A4-4E3A-ABB0-56558B323DFE}.Debug|Win32.ActiveCfg = Debug|Win32 + {413653C3-59A4-4E3A-ABB0-56558B323DFE}.Debug|Win32.Build.0 = Debug|Win32 + {413653C3-59A4-4E3A-ABB0-56558B323DFE}.Debug|x64.ActiveCfg = Debug|x64 + {413653C3-59A4-4E3A-ABB0-56558B323DFE}.Debug|x64.Build.0 = Debug|x64 + {413653C3-59A4-4E3A-ABB0-56558B323DFE}.Release|Win32.ActiveCfg = Release|Win32 {413653C3-59A4-4E3A-ABB0-56558B323DFE}.Release|Win32.Build.0 = Release|Win32 + {413653C3-59A4-4E3A-ABB0-56558B323DFE}.Release|x64.ActiveCfg = Release|x64 {413653C3-59A4-4E3A-ABB0-56558B323DFE}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution diff --git a/Externals/Memcard Manager/Memcard Manager.vcproj b/Externals/Memcard Manager/Memcard Manager.vcproj index b5dd2a6dcf..6b4492bcf8 100644 --- a/Externals/Memcard Manager/Memcard Manager.vcproj +++ b/Externals/Memcard Manager/Memcard Manager.vcproj @@ -246,6 +246,234 @@ ExcludedFromBuild="false" /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -295,6 +523,14 @@ Name="VCCustomBuildTool" /> + + + + + + + + + + + + + + + + + + + + + + + + + + + hdr.deviceID[0],memoryCard[card]->hdr.deviceID[1]); wx_Size.Printf(wxT("%02X, %02X"), - memoryCard[card]->hdr.Size[0],memoryCard[card]->hdr.Size[1]); + memoryCard[card]->hdr.SizeMb[0],memoryCard[card]->hdr.SizeMb[1]); wx_Encoding.Printf( wxT("%02X, %02X"), memoryCard[card]->hdr.Encoding[0],memoryCard[card]->hdr.Encoding[1]); diff --git a/Source/Core/Common/Src/Log.h b/Source/Core/Common/Src/Log.h index 2933a324c6..607b3d31cb 100644 --- a/Source/Core/Common/Src/Log.h +++ b/Source/Core/Common/Src/Log.h @@ -38,7 +38,7 @@ enum LOG_TYPE { DISCIO, DSPHLE, DSPLLE, - DSP_MAIL, + DSP_MAIL, DSPINTERFACE, DVDINTERFACE, DYNA_REC, @@ -48,6 +48,7 @@ enum LOG_TYPE { HLE, MASTER_LOG, MEMMAP, + MEMCARD_MANAGER, OSREPORT, PAD, PERIPHERALINTERFACE, diff --git a/Source/Core/Common/Src/LogManager.cpp b/Source/Core/Common/Src/LogManager.cpp index b9dad4be6d..80504b3b0a 100644 --- a/Source/Core/Common/Src/LogManager.cpp +++ b/Source/Core/Common/Src/LogManager.cpp @@ -53,7 +53,7 @@ LogManager::LogManager()\ m_Log[LogTypes::HLE] = new LogContainer("HLE", "HLE"); m_Log[LogTypes::DSPHLE] = new LogContainer("DSPHLE", "DSP HLE"); m_Log[LogTypes::DSPLLE] = new LogContainer("DSPLLE", "DSP LLE"); - m_Log[LogTypes::DSP_MAIL] = new LogContainer("DSPMails", "DSP Mails"); + m_Log[LogTypes::DSP_MAIL] = new LogContainer("DSPMails", "DSP Mails"); m_Log[LogTypes::VIDEO] = new LogContainer("Video", "Video Plugin"); m_Log[LogTypes::AUDIO] = new LogContainer("Audio", "Audio Plugin"); m_Log[LogTypes::DYNA_REC] = new LogContainer("JIT", "Dynamic Recompiler"); @@ -69,8 +69,9 @@ LogManager::LogManager()\ m_Log[LogTypes::WII_IPC_SD] = new LogContainer("WII_IPC_SD", "WII IPC SD"); m_Log[LogTypes::WII_IPC_STM] = new LogContainer("WII_IPC_STM", "WII IPC STM"); m_Log[LogTypes::WII_IPC_NET] = new LogContainer("WII_IPC_NET", "WII IPC NET"); - m_Log[LogTypes::WII_IPC_WIIMOTE] = new LogContainer("WII_IPC_WIIMOTE","WII IPC WIIMOTE"); - m_Log[LogTypes::ACTIONREPLAY] = new LogContainer("ActionReplay", "ActionReplay"); + m_Log[LogTypes::WII_IPC_WIIMOTE] = new LogContainer("WII_IPC_WIIMOTE","WII IPC WIIMOTE"); + m_Log[LogTypes::ACTIONREPLAY] = new LogContainer("ActionReplay", "ActionReplay"); + m_Log[LogTypes::MEMCARD_MANAGER] = new LogContainer("MemCard Manger", "MemCard Manger"); m_fileLog = new FileLogListener(MAIN_LOG_FILE); m_consoleLog = new ConsoleListener(); diff --git a/Source/Core/DolphinWX/Src/MemcardManager.cpp b/Source/Core/DolphinWX/Src/MemcardManager.cpp index e9b6d19755..73b696c910 100644 --- a/Source/Core/DolphinWX/Src/MemcardManager.cpp +++ b/Source/Core/DolphinWX/Src/MemcardManager.cpp @@ -591,10 +591,12 @@ void CMemcardManager::CopyDeleteClick(wxCommandEvent& event) memoryCard[slot]->DEntry_GameCode(index,tempC); memoryCard[slot]->DEntry_FileName(index,tempC2); sprintf(tempC, "%s_%s.gci", tempC, tempC2); - wxString temp = wxFileSelector(_T("Save GCI as.."), wxString::FromAscii(DefaultIOPath.c_str()), + wxString temp = wxFileSelector(_T("Export save as.."), wxString::FromAscii(DefaultIOPath.c_str()), wxString::FromAscii(tempC), _T(".gci"), wxString::Format ( - _T("GCI File(*.gci)|*.gci"), + _T("Native GCI files (*.gci)|*.gci|" + "MadCatz Gameshark files(*.gcs)|*.gcs|" + "Datel MaxDrive/Pro files(*.sav)|*.sav"), wxFileSelectorDefaultWildcardStr, wxFileSelectorDefaultWildcardStr ), diff --git a/Source/Core/DolphinWX/Src/MemoryCards/GCMemcard.cpp b/Source/Core/DolphinWX/Src/MemoryCards/GCMemcard.cpp index a938909071..5108a0ccf9 100644 --- a/Source/Core/DolphinWX/Src/MemoryCards/GCMemcard.cpp +++ b/Source/Core/DolphinWX/Src/MemoryCards/GCMemcard.cpp @@ -665,6 +665,16 @@ u32 GCMemcard::RemoveFile(u8 index) //index in the directory array { if (!mcdFile) return NOMEMCARD; + + //error checking + u16 startingblock = 0; + for (int i = 0; i < DIRLEN; i++) + { + if (startingblock > BE16(dir.Dir[i].FirstBlock)) + return FAIL; + startingblock = BE16(dir.Dir[i].FirstBlock); + } + //backup the directory and bat (not really needed here but meh :P dir_backup = dir; bat_backup = bat; @@ -812,39 +822,8 @@ u32 GCMemcard::ImportGci(const char *fileName, std::string fileName2) int length = (int) ftell(gci) - fStart; fseek(gci, offset + DENTRY_SIZE, SEEK_SET); - switch(offset){ - case GCS: - { // field containing the Block count as displayed within - // the GameSaves software is not stored in the GCS file. - // It is stored only within the corresponding GSV file. - // If the GCS file is added without using the GameSaves software, - // the value stored is always "1" - int blockCount = length / BLOCK_SIZE; - tempDEntry->BlockCount[0] = u8(blockCount >> 8); - tempDEntry->BlockCount[1] = u8(blockCount); - } - break; - case SAV: - // swap byte pairs - // 0x2C and 0x2D, 0x2E and 0x2F, 0x30 and 0x31, 0x32 and 0x33, - // 0x34 and 0x35, 0x36 and 0x37, 0x38 and 0x39, 0x3A and 0x3B, - // 0x3C and 0x3D,0x3E and 0x3F. - // It seems that sav files also swap the BIFlags... - ByteSwap(&tempDEntry->Unused1, &tempDEntry->BIFlags); - ArrayByteSwap((tempDEntry->ImageOffset)); - ArrayByteSwap(&(tempDEntry->ImageOffset[2])); - ArrayByteSwap((tempDEntry->IconFmt)); - ArrayByteSwap((tempDEntry->AnimSpeed)); - ByteSwap(&tempDEntry->Permissions, &tempDEntry->CopyCounter); - ArrayByteSwap((tempDEntry->FirstBlock)); - ArrayByteSwap((tempDEntry->BlockCount)); - ArrayByteSwap((tempDEntry->Unused2)); - ArrayByteSwap((tempDEntry->CommentsAddr)); - ArrayByteSwap(&(tempDEntry->CommentsAddr[2])); - break; - default: - break; - } + Gcs_SavConvert(tempDEntry, offset, length); + if (length != BE16(tempDEntry->BlockCount) * BLOCK_SIZE) { return LENGTHFAIL; @@ -885,6 +864,7 @@ u32 GCMemcard::ImportGci(const char *fileName, std::string fileName2) u32 GCMemcard::ExportGci(u8 index, const char *fileName, std::string *fileName2) { FILE *gci; + int offset = GCI; if (!strcasecmp(fileName,".")) { if (BE32(dir.Dir[index].Gamecode) == 0xFFFFFFFF) return SUCCESS; @@ -901,15 +881,51 @@ u32 GCMemcard::ExportGci(u8 index, const char *fileName, std::string *fileName2) else { gci = fopen(fileName, "wb"); + + std::string fileType; + SplitPath(fileName, NULL, NULL, &fileType); + if (!strcasecmp(fileType.c_str(), ".gcs")) + { + offset = GCS; + } + else if (!strcasecmp(fileType.c_str(), ".sav")) + { + offset = SAV; + } } if (!gci) return OPENFAIL; bool completeWrite = true; fseek(gci, 0, SEEK_SET); + + switch(offset) + { + case GCS: + { + u8 gcsHDR[GCS]; + memset(gcsHDR, 0, GCS); + memcpy(gcsHDR, "GCSAVE", 6); + if (fwrite(gcsHDR, 1, GCS, gci) != GCS) completeWrite = false; + break; + } + case SAV: + { + u8 savHDR[SAV]; + memset(savHDR, 0, SAV); + memcpy(savHDR, "DATELGC_SAVE", 0xC); + if (fwrite(savHDR, 1, SAV, gci) != SAV) completeWrite = false; + } + break; + default: + break; + } DEntry tempDEntry; if (!DEntry_Copy(index, tempDEntry)) return NOMEMCARD; + + + Gcs_SavConvert(&tempDEntry, offset); if (fwrite(&tempDEntry, 1, DENTRY_SIZE, gci) != DENTRY_SIZE) completeWrite = false; u32 size = DEntry_BlockCount(index); @@ -930,7 +946,7 @@ u32 GCMemcard::ExportGci(u8 index, const char *fileName, std::string *fileName2) default: break; } - fseek(gci, DENTRY_SIZE, SEEK_SET); + fseek(gci, DENTRY_SIZE + offset, SEEK_SET); if (fwrite(tempSaveData, 1, size, gci) != size) completeWrite = false; fclose(gci); @@ -940,6 +956,44 @@ u32 GCMemcard::ExportGci(u8 index, const char *fileName, std::string *fileName2) } +void GCMemcard::Gcs_SavConvert(DEntry* tempDEntry, int saveType, int length) +{ + switch(saveType) + { + case GCS: + { // field containing the Block count as displayed within + // the GameSaves software is not stored in the GCS file. + // It is stored only within the corresponding GSV file. + // If the GCS file is added without using the GameSaves software, + // the value stored is always "1" + int blockCount = length / BLOCK_SIZE; + tempDEntry->BlockCount[0] = u8(blockCount >> 8); + tempDEntry->BlockCount[1] = u8(blockCount); + } + break; + case SAV: + // swap byte pairs + // 0x2C and 0x2D, 0x2E and 0x2F, 0x30 and 0x31, 0x32 and 0x33, + // 0x34 and 0x35, 0x36 and 0x37, 0x38 and 0x39, 0x3A and 0x3B, + // 0x3C and 0x3D,0x3E and 0x3F. + // It seems that sav files also swap the BIFlags... + ByteSwap(&tempDEntry->Unused1, &tempDEntry->BIFlags); + ArrayByteSwap((tempDEntry->ImageOffset)); + ArrayByteSwap(&(tempDEntry->ImageOffset[2])); + ArrayByteSwap((tempDEntry->IconFmt)); + ArrayByteSwap((tempDEntry->AnimSpeed)); + ByteSwap(&tempDEntry->Permissions, &tempDEntry->CopyCounter); + ArrayByteSwap((tempDEntry->FirstBlock)); + ArrayByteSwap((tempDEntry->BlockCount)); + ArrayByteSwap((tempDEntry->Unused2)); + ArrayByteSwap((tempDEntry->CommentsAddr)); + ArrayByteSwap(&(tempDEntry->CommentsAddr[2])); + break; + default: + break; + } +} + bool GCMemcard::ReadBannerRGBA8(u8 index, u32* buffer) { if (!mcdFile) return false; diff --git a/Source/Core/DolphinWX/Src/MemoryCards/GCMemcard.h b/Source/Core/DolphinWX/Src/MemoryCards/GCMemcard.h index 1faca37c3e..0b5951d6b1 100644 --- a/Source/Core/DolphinWX/Src/MemoryCards/GCMemcard.h +++ b/Source/Core/DolphinWX/Src/MemoryCards/GCMemcard.h @@ -242,6 +242,10 @@ public: // writes a .gci file to disk containing index u32 ExportGci(u8 index, const char* fileName, std::string* fileName2); + // GCI files are untouched, SAV files are byteswapped + // GCS files have the block count set, default is 1 (For export as GCS) + void Gcs_SavConvert(DEntry* tempDEntry, int saveType, int length = BLOCK_SIZE); + // reads the banner image bool ReadBannerRGBA8(u8 index, u32* buffer);