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