From 3d20c5745896f0787ed0d974e73d20f11d240de9 Mon Sep 17 00:00:00 2001
From: LPFaint99 <lpfaint99@gmail.com>
Date: Mon, 6 Feb 2012 17:27:49 -0800
Subject: [PATCH] Update directorys and BlockAllocs correctly, use the most
 uptodate directory/bat instead of always the first

Signed-off-by: LPFaint99 <lpfaint99@gmail.com>
---
 Source/Core/Core/Src/HW/GCMemcard.cpp        | 335 +++++++++----------
 Source/Core/Core/Src/HW/GCMemcard.h          |  12 +-
 Source/Core/DolphinWX/Src/MemcardManager.cpp |   4 +-
 3 files changed, 164 insertions(+), 187 deletions(-)

diff --git a/Source/Core/Core/Src/HW/GCMemcard.cpp b/Source/Core/Core/Src/HW/GCMemcard.cpp
index 2926017b2a..9b9d39fc02 100644
--- a/Source/Core/Core/Src/HW/GCMemcard.cpp
+++ b/Source/Core/Core/Src/HW/GCMemcard.cpp
@@ -227,6 +227,28 @@ GCMemcard::GCMemcard(const char *filename, bool forceCreation, bool sjis)
 	}
 
 	mcdFile.Close();
+
+	if (BE16(dir.UpdateCounter) > (BE16(dir_backup.UpdateCounter)))
+	{
+		CurrentDir = &dir;
+		PreviousDir = &dir_backup;
+	}
+	else
+	{
+		CurrentDir = &dir_backup;
+		PreviousDir = &dir;
+	}
+	if (BE16(bat.UpdateCounter) > BE16(bat_backup.UpdateCounter))
+	{
+		PanicAlert("jere, %x, %x",BE16(bat.UpdateCounter) , BE16(bat_backup.UpdateCounter));
+		CurrentBat = &bat;
+		PreviousBat = &bat_backup;
+	}
+	else
+	{
+		CurrentBat = &bat_backup;
+		PreviousBat = &bat;
+	}
 }
 
 bool GCMemcard::IsAsciiEncoding() const
@@ -321,7 +343,7 @@ u8 GCMemcard::GetNumFiles() const
 	u8 j = 0;
 	for (int i = 0; i < DIRLEN; i++)
 	{
-		if (BE32(dir.Dir[i].Gamecode)!= 0xFFFFFFFF)
+		if (BE32(CurrentDir->Dir[i].Gamecode)!= 0xFFFFFFFF)
 			 j++;
 	}
 	return j;
@@ -335,7 +357,7 @@ u8 GCMemcard::GetFileIndex(u8 fileNumber) const
 		u8 j = 0;
 		for (u8 i = 0; i < DIRLEN; i++)
 		{
-			if (BE32(dir.Dir[i].Gamecode)!= 0xFFFFFFFF)
+			if (BE32(CurrentDir->Dir[i].Gamecode)!= 0xFFFFFFFF)
 			{
 				if (j == fileNumber)
 				{
@@ -353,7 +375,7 @@ u16 GCMemcard::GetFreeBlocks() const
 	if (!m_valid)
 		return 0;
 
-	return BE16(bat.FreeBlocks);
+	return BE16(CurrentBat->FreeBlocks);
 }
 
 u8 GCMemcard::TitlePresent(DEntry d) const
@@ -364,8 +386,8 @@ u8 GCMemcard::TitlePresent(DEntry d) const
 	u8 i = 0;
 	while(i < DIRLEN)
 	{
-		if ((BE32(dir.Dir[i].Gamecode) == BE32(d.Gamecode)) &&
-			(!memcmp(dir.Dir[i].Filename, d.Filename, 32)))
+		if ((BE32(CurrentDir->Dir[i].Gamecode) == BE32(d.Gamecode)) &&
+			(!memcmp(CurrentDir->Dir[i].Filename, d.Filename, 32)))
 		{
 			break;
 		}
@@ -376,9 +398,9 @@ u8 GCMemcard::TitlePresent(DEntry d) const
 
 bool GCMemcard::GCI_FileName(u8 index, std::string &filename) const
 {
-	if (!m_valid || index > DIRLEN || (BE32(dir.Dir[index].Gamecode) == 0xFFFFFFFF))
+	if (!m_valid || index > DIRLEN || (BE32(CurrentDir->Dir[index].Gamecode) == 0xFFFFFFFF))
 		return false;
-	filename = std::string((char*)dir.Dir[index].Gamecode, 4) + '_' + (char*)dir.Dir[index].Filename + ".gci";
+	filename = std::string((char*)CurrentDir->Dir[index].Gamecode, 4) + '_' + (char*)CurrentDir->Dir[index].Filename + ".gci";
 	return true;
 }
 
@@ -389,14 +411,14 @@ std::string GCMemcard::DEntry_GameCode(u8 index) const
 {
 	if (!m_valid || index > DIRLEN)
 		return "";
-	return std::string((const char*)dir.Dir[index].Gamecode, 4);
+	return std::string((const char*)CurrentDir->Dir[index].Gamecode, 4);
 }
 
 std::string GCMemcard::DEntry_Makercode(u8 index) const
 {
 	if (!m_valid || index > DIRLEN)
 		return "";
-	return std::string((const char*)dir.Dir[index].Makercode, 2);
+	return std::string((const char*)CurrentDir->Dir[index].Makercode, 2);
 }
 
 std::string GCMemcard::DEntry_BIFlags(u8 index) const
@@ -405,7 +427,7 @@ std::string GCMemcard::DEntry_BIFlags(u8 index) const
 		return "";
 
 	std::string flags;
-	int x = dir.Dir[index].BIFlags;
+	int x = CurrentDir->Dir[index].BIFlags;
 	for (int i = 0; i < 8; i++)
 	{
 		flags.push_back((x & 0x80) ? '1' : '0');
@@ -419,32 +441,32 @@ std::string GCMemcard::DEntry_FileName(u8 index) const
 {
 	if (!m_valid || index > DIRLEN)
 		return "";
-	return std::string((const char*)dir.Dir[index].Filename, DENTRY_STRLEN);
+	return std::string((const char*)CurrentDir->Dir[index].Filename, DENTRY_STRLEN);
 }
 
 u32 GCMemcard::DEntry_ModTime(u8 index) const
 {
 	if (!m_valid || index > DIRLEN)
 		return 0xFFFFFFFF;
-	return BE32(dir.Dir[index].ModTime);
+	return BE32(CurrentDir->Dir[index].ModTime);
 }
 
 u32 GCMemcard::DEntry_ImageOffset(u8 index) const
 {
 	if (!m_valid || index > DIRLEN)
 		return 0xFFFFFFFF;
-	return BE32(dir.Dir[index].ImageOffset);
+	return BE32(CurrentDir->Dir[index].ImageOffset);
 }
 
 std::string GCMemcard::DEntry_IconFmt(u8 index) const
 {
 	if (!m_valid || index > DIRLEN)
 		return "";
-	int x = dir.Dir[index].IconFmt[0];
+	int x = CurrentDir->Dir[index].IconFmt[0];
 	std::string format;
 	for(int i = 0; i < 16; i++)
 	{
-		if (i == 8) x = dir.Dir[index].IconFmt[1];
+		if (i == 8) x = CurrentDir->Dir[index].IconFmt[1];
 		format.push_back((x & 0x80) ? '1' : '0');
 		x = x << 1;
 	}
@@ -456,14 +478,14 @@ u16 GCMemcard::DEntry_AnimSpeed(u8 index) const
 {
 	if (!m_valid || index > DIRLEN)
 		return 0xFF;
-	return BE16(dir.Dir[index].AnimSpeed);
+	return BE16(CurrentDir->Dir[index].AnimSpeed);
 }
 
 std::string GCMemcard::DEntry_Permissions(u8 index) const
 {
 	if (!m_valid || index > DIRLEN)
 		return "";
-	u8 Permissions = dir.Dir[index].Permissions;
+	u8 Permissions = CurrentDir->Dir[index].Permissions;
 	std::string permissionsString;
 	permissionsString.push_back((Permissions & 16) ? 'x' : 'M');
 	permissionsString.push_back((Permissions &  8) ? 'x' : 'C');
@@ -476,7 +498,7 @@ u8 GCMemcard::DEntry_CopyCounter(u8 index) const
 {
 	if (!m_valid || index > DIRLEN)
 		return 0xFF;
-	return dir.Dir[index].CopyCounter;
+	return CurrentDir->Dir[index].CopyCounter;
 }
 
 u16 GCMemcard::DEntry_FirstBlock(u8 index) const
@@ -484,7 +506,7 @@ u16 GCMemcard::DEntry_FirstBlock(u8 index) const
 	if (!m_valid || index > DIRLEN)
 		return 0xFFFF;
 
-	u16 block = BE16(dir.Dir[index].FirstBlock);
+	u16 block = BE16(CurrentDir->Dir[index].FirstBlock);
 	if (block > (u16) maxBlock) return 0xFFFF;
 	return block;
 }
@@ -494,7 +516,7 @@ u16 GCMemcard::DEntry_BlockCount(u8 index) const
 	if (!m_valid || index > DIRLEN)
 		return 0xFFFF;
 
-	u16 blocks = BE16(dir.Dir[index].BlockCount);
+	u16 blocks = BE16(CurrentDir->Dir[index].BlockCount);
 	if (blocks > (u16) maxBlock) return 0xFFFF;
 	return blocks;
 }
@@ -503,7 +525,7 @@ u32 GCMemcard::DEntry_CommentsAddress(u8 index) const
 {
 	if (!m_valid || index > DIRLEN)
 		return 0xFFFF;
-	return BE32(dir.Dir[index].CommentsAddr);
+	return BE32(CurrentDir->Dir[index].CommentsAddr);
 }
 
 std::string GCMemcard::GetSaveComment1(u8 index) const
@@ -511,8 +533,8 @@ std::string GCMemcard::GetSaveComment1(u8 index) const
 	if (!m_valid || index > DIRLEN)
 		return "";
 
-	u32 Comment1 = BE32(dir.Dir[index].CommentsAddr);
-	u32 DataBlock = BE16(dir.Dir[index].FirstBlock) - MC_FST_BLOCKS;
+	u32 Comment1 = BE32(CurrentDir->Dir[index].CommentsAddr);
+	u32 DataBlock = BE16(CurrentDir->Dir[index].FirstBlock) - MC_FST_BLOCKS;
 	if ((DataBlock > maxBlock) || (Comment1 == 0xFFFFFFFF))
 	{
 		return "";
@@ -525,9 +547,9 @@ std::string GCMemcard::GetSaveComment2(u8 index) const
 	if (!m_valid || index > DIRLEN)
 		return "";
 
-	u32 Comment1 = BE32(dir.Dir[index].CommentsAddr);
+	u32 Comment1 = BE32(CurrentDir->Dir[index].CommentsAddr);
 	u32 Comment2 = Comment1 + DENTRY_STRLEN;
-	u32 DataBlock = BE16(dir.Dir[index].FirstBlock) - MC_FST_BLOCKS;
+	u32 DataBlock = BE16(CurrentDir->Dir[index].FirstBlock) - MC_FST_BLOCKS;
 	if ((DataBlock > maxBlock) || (Comment1 == 0xFFFFFFFF))
 	{
 		return "";
@@ -539,44 +561,47 @@ bool GCMemcard::GetDEntry(u8 index, DEntry &dest) const
 {
 	if (!m_valid || index > DIRLEN)
 		return false;
-	dest = dir.Dir[index];
+	dest = CurrentDir->Dir[index];
 	return true;
 }
-
-u16 GCMemcard::GetNextBlock(u16 Block) const
+u16 GCMemcard::BlockAlloc::GetNextBlock(u16 Block) const
 {
-	if ((Block < MC_FST_BLOCKS) || (Block > maxBlock))
+	if ((Block < MC_FST_BLOCKS) || (Block > 4091))
 		return 0;
-	return Common::swap16(bat.Map[Block-MC_FST_BLOCKS]);
+	return Common::swap16(Map[Block-MC_FST_BLOCKS]);
 }
 
-u16 GCMemcard::NextFreeBlock(u16 StartingBlock) const
+u16 GCMemcard::BlockAlloc::NextFreeBlock(u16 StartingBlock) const
 {
 	for (u16 i = StartingBlock; i < BAT_SIZE; ++i)
-		if (bat.Map[i-MC_FST_BLOCKS] == 0)
+		if (Map[i-MC_FST_BLOCKS] == 0)
 			return i;
 }
 
-bool GCMemcard::ClearBlocks(u16 FirstBlock, u16 BlockCount)
+bool GCMemcard::BlockAlloc::ClearBlocks(u16 FirstBlock, u16 BlockCount)
 {
 	std::vector<u16> blocks;
-	while (FirstBlock != 0xFF && FirstBlock != 0)
+	while (FirstBlock != 0xFFFF && FirstBlock != 0)
 	{
 		blocks.push_back(FirstBlock);
 		FirstBlock = GetNextBlock(FirstBlock);
 	}
-
 	if (FirstBlock > 0)
 	{
 		size_t length = blocks.size();
 		if (length != BlockCount)
+		{
 			return false;
+		}
 		for (int i = 0; i < length; ++i)
-			bat.Map[blocks.at(i)-MC_FST_BLOCKS] = 0;
-		*(u16*)&bat.FreeBlocks = BE16(BE16(bat.FreeBlocks) - BlockCount);
+			Map[blocks.at(i)-MC_FST_BLOCKS] = 0;
+		*(u16*)&FreeBlocks = BE16(BE16(FreeBlocks) + BlockCount);
+
+		return true;
 	}
-	return true;
+	return false;
 }
+
 u32 GCMemcard::GetSaveData(u8 index,  std::vector<GCMBlock> & Blocks) const
 {
 	if (!m_valid)
@@ -597,13 +622,13 @@ u32 GCMemcard::GetSaveData(u8 index,  std::vector<GCMBlock> & Blocks) const
 		if ((!nextBlock) || (nextBlock == 0xFFFF))
 			return FAIL;
 		Blocks.push_back(mc_data_blocks[nextBlock-MC_FST_BLOCKS]);
-		nextBlock = GetNextBlock(nextBlock);
+		nextBlock = CurrentBat->GetNextBlock(nextBlock);
 	}
 	return SUCCESS;
 }
 // End DEntry functions
 
-u32 GCMemcard::ImportFile(DEntry& direntry, std::vector<GCMBlock> &saveBlocks, int remove)
+u32 GCMemcard::ImportFile(DEntry& direntry, std::vector<GCMBlock> &saveBlocks)
 {
 	if (!m_valid)
 		return NOMEMCARD;
@@ -612,11 +637,11 @@ u32 GCMemcard::ImportFile(DEntry& direntry, std::vector<GCMBlock> &saveBlocks, i
 	{
 		return OUTOFDIRENTRIES;
 	}
-	if (BE16(bat.FreeBlocks) < BE16(direntry.BlockCount))
+	if (BE16(CurrentBat->FreeBlocks) < BE16(direntry.BlockCount))
 	{
 		return OUTOFBLOCKS;
 	}
-	if (!remove && (TitlePresent(direntry) != DIRLEN))
+	if (TitlePresent(direntry) != DIRLEN)
 	{
 		return TITLEPRESENT;
 	}
@@ -625,44 +650,40 @@ u32 GCMemcard::ImportFile(DEntry& direntry, std::vector<GCMBlock> &saveBlocks, i
 	//int totalspace = (((u32)BE16(hdr.SizeMb) * MBIT_TO_BLOCKS) - MC_FST_BLOCKS);
 	//int firstFree1 = BE16(bat.LastAllocated) + 1;
 
+	u16 firstBlock = CurrentBat->NextFreeBlock();
 
+	Directory UpdatedDir = *CurrentDir;
 	
-/*	for (int i = 0; i < DIRLEN; i++)
-	{
-		if (BE32(dir.Dir[i].Gamecode) == 0xFFFFFFFF)
-		{
-			break;
-		}
-		else
-		{
-			firstFree2 = max<int>(firstFree2,
-				(int)(BE16(dir.Dir[i].FirstBlock) + BE16(dir.Dir[i].BlockCount)));
-		}
-	}
-	firstFree1 = max<int>(firstFree1, firstFree2);
-	*/
-	u16 firstBlock = NextFreeBlock();
 	// find first free dir entry
 	int index = -1;
 	for (int i=0; i < DIRLEN; i++)
 	{
-		if (BE32(dir.Dir[i].Gamecode) == 0xFFFFFFFF)
+		if (BE32(UpdatedDir.Dir[i].Gamecode) == 0xFFFFFFFF)
 		{
 			index = i;
-			dir.Dir[i] = direntry;
-			*(u16*)&dir.Dir[i].FirstBlock = BE16(firstBlock);
-			if (!remove)
-			{
-				dir.Dir[i].CopyCounter = dir.Dir[i].CopyCounter+1;
-			}
-			dir_backup = dir;
+			UpdatedDir.Dir[i] = direntry;
+			*(u16*)&UpdatedDir.Dir[i].FirstBlock = BE16(firstBlock);
+			UpdatedDir.Dir[i].CopyCounter = UpdatedDir.Dir[i].CopyCounter+1;
 			break;
 		}
 	}
-
+	*(u16*)&UpdatedDir.UpdateCounter = BE16(BE16(UpdatedDir.UpdateCounter) + 1);
+	*PreviousDir = UpdatedDir;
+	if (PreviousDir == &dir )
+	{
+		CurrentDir = &dir;
+		PreviousDir = &dir_backup;
+	}
+	else
+	{
+		CurrentDir = &dir_backup;
+		PreviousDir = &dir;
+	}
 
 	int fileBlocks = BE16(direntry.BlockCount);
 
+
+	BlockAlloc UpdatedBat = *CurrentBat;
 	u16 nextBlock;
 	// keep assuming no freespace fragmentation, and copy over all the data
 	for (int i = 0; i < fileBlocks; ++i)
@@ -671,42 +692,24 @@ u32 GCMemcard::ImportFile(DEntry& direntry, std::vector<GCMBlock> &saveBlocks, i
 		if (i == fileBlocks-1)
 			nextBlock = 0xFFFF;
 		else
-			nextBlock = NextFreeBlock(firstBlock+1);		
-		bat.Map[firstBlock - MC_FST_BLOCKS] = BE16(nextBlock);
+			nextBlock = UpdatedBat.NextFreeBlock(firstBlock+1);		
+		UpdatedBat.Map[firstBlock - MC_FST_BLOCKS] = BE16(nextBlock);
 		firstBlock = nextBlock;
 	}
-
-	bat_backup = bat;
-/*	u16 last = BE16(bat_backup.LastAllocated);
-	u16 i = (last - 4);
-	int j = 2;
-	while(j < BE16(direntry.BlockCount) + 1)
+	*(u16*)&UpdatedBat.FreeBlocks = BE16(BE16(UpdatedBat.FreeBlocks)  - fileBlocks);
+	*(u16*)&UpdatedBat.UpdateCounter = BE16(BE16(UpdatedBat.UpdateCounter) + 1);
+	*PreviousBat = UpdatedBat;
+	if (PreviousBat == &bat )
 	{
-		bat_backup.Map[i] = BE16(last + (u16)j);
-		i++;
-		j++;
+		CurrentBat = &bat;
+		PreviousBat = &bat_backup;
 	}
-	bat_backup.Map[i++] = 0xFFFF;
-	//Set bat.map to 0 for each block that was removed
-	for (int k = 0; k < remove; k++)
+	else
 	{
-		bat_backup.Map[i++] = 0x0000;
+		CurrentBat = &bat_backup;
+		PreviousBat = &bat;
 	}
-	*/
-	//update last allocated block
-/*	*(u16*)&bat_backup.LastAllocated = BE16(BE16(bat_backup.LastAllocated) + j - 1);
-*/
-	//update freespace counter
-	*(u16*)&bat_backup.FreeBlocks = BE16(BE16(bat_backup.FreeBlocks)  - fileBlocks);
 
-	
-	if (!remove)
-	{	// ... and dir update counter
-		*(u16*)&dir_backup.UpdateCounter = BE16(BE16(dir_backup.UpdateCounter) + 1);
-		// ... and bat update counter
-		*(u16*)&bat_backup.UpdateCounter = BE16(BE16(bat_backup.UpdateCounter) + 1);
-	}
-	bat = bat_backup;
 	return SUCCESS;
 }
 
@@ -716,87 +719,59 @@ u32 GCMemcard::RemoveFile(u8 index) //index in the directory array
 		return NOMEMCARD;
 	if (index >= DIRLEN)
 		return DELETE_FAIL;
-	
-	dir_backup = dir;
-	bat_backup = bat;
 
 	u16 startingblock = BE16(dir.Dir[index].FirstBlock);
 	u16 numberofblocks = BE16(dir.Dir[index].BlockCount);
-	if (!ClearBlocks(startingblock, numberofblocks))
+
+	BlockAlloc UpdatedBat = *CurrentBat;
+	if (!UpdatedBat.ClearBlocks(startingblock, numberofblocks))
 		return DELETE_FAIL;
+	*(u16*)&UpdatedBat.UpdateCounter = BE16(BE16(UpdatedBat.UpdateCounter) + 1);
+	*PreviousBat = UpdatedBat;
+	if (PreviousBat == &bat )
+	{
+		CurrentBat = &bat;
+		PreviousBat = &bat_backup;
+	}
+	else
+	{
+		CurrentBat = &bat_backup;
+		PreviousBat = &bat;
+	}
+
+	Directory UpdatedDir = *CurrentDir;
+	*(u32*)&UpdatedDir.Dir[index].Gamecode = 0;
+	*(u16*)&UpdatedDir.Dir[index].Makercode = 0;
+	memset(UpdatedDir.Dir[index].Filename, 0, 0x20);
+	strcpy((char*)UpdatedDir.Dir[index].Filename, "Broken File000");
+	*(u16*)&UpdatedDir.UpdateCounter = BE16(BE16(UpdatedDir.UpdateCounter) + 1);
+
+	*PreviousDir = UpdatedDir;
+	if (PreviousDir == &dir )
+	{
+		CurrentDir = &dir;
+		PreviousDir = &dir_backup;
+	}
+	else
+	{
+		CurrentDir = &dir_backup;
+		PreviousDir = &dir;
+	}
+	memset(&(UpdatedDir.Dir[index]), 0xFF, DENTRY_SIZE);
+	*(u16*)&UpdatedDir.UpdateCounter = BE16(BE16(UpdatedDir.UpdateCounter) + 1);
+	*PreviousDir = UpdatedDir;
+	if (PreviousDir == &dir )
+	{
+		CurrentDir = &dir;
+		PreviousDir = &dir_backup;
+	}
+	else
+	{
+		CurrentDir = &dir_backup;
+		PreviousDir = &dir;
+	}
 
-	
-	memset(&(dir.Dir[index]), 0xFF, DENTRY_SIZE);
-	
-	*(u16*)&dir.UpdateCounter = BE16(BE16(dir.UpdateCounter) + 1);
-	*(u16*)&bat.UpdateCounter = BE16(BE16(bat.UpdateCounter) + 1);
-	
 	return SUCCESS;
-	/*
-	//error checking
-	u16 startingblock = 0;
-	for (int i = 0; i < DIRLEN; i++)
-	{
-		if (startingblock > BE16(dir.Dir[i].FirstBlock))
-			return DELETE_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;
-
-	//free the blocks
-	int blocks_left = BE16(dir.Dir[index].BlockCount);
-	*(u16*)&bat.LastAllocated = BE16(BE16(dir.Dir[index].FirstBlock) - 1);
-
-	u8 nextIndex = index + 1;
-	memset(&(dir.Dir[index]), 0xFF, DENTRY_SIZE);
-
-	while (nextIndex < DIRLEN)
-	{
-		DEntry tempDEntry;
-		GetDEntry(nextIndex, tempDEntry);
-		std::vector<GCMBlock> saveData;
-		u16 size = 0;
-		//Only get file data if it is a valid dir entry
-		if (BE16(tempDEntry.FirstBlock) != 0xFFFF)
-		{
-			*(u16*)&bat.FreeBlocks = BE16(BE16(bat.FreeBlocks) - BE16(tempDEntry.BlockCount));
-
-			size = DEntry_BlockCount(nextIndex);
-			if (size != 0xFFFF)
-			{
-				saveData.reserve(size);
-				switch (GetSaveData(nextIndex, saveData))
-				{
-				case NOMEMCARD:
-					break;
-				case FAIL:
-					return FAIL;
-				}
-			}
-		}
-		memset(&(dir.Dir[nextIndex]), 0xFF, DENTRY_SIZE);
-		//Only call import file if GetSaveData returns SUCCESS
-		if (saveData.size() == size)
-		{
-			ImportFile(tempDEntry, saveData, blocks_left);
-		}
-		nextIndex++;
-
-	}
-	//Added to clean up if removing last file
-	if (BE16(bat.LastAllocated) == (u16)4)
-	{
-		for (int j = 0; j < blocks_left; j++)
-		{
-			bat.Map[j] = 0x0000;
-		}
-	}
-	// increment update counter
-	*(u16*)&dir.UpdateCounter = BE16(BE16(dir.UpdateCounter) + 1);
-	*/
 }
 
 u32 GCMemcard::CopyFrom(const GCMemcard& source, u8 index)
@@ -820,7 +795,7 @@ u32 GCMemcard::CopyFrom(const GCMemcard& source, u8 index)
 	case NOMEMCARD:
 		return NOMEMCARD;
 	default:
-		return ImportFile(tempDEntry, saveData, 0);
+		return ImportFile(tempDEntry, saveData);
 	}
 }
 
@@ -922,7 +897,7 @@ u32 GCMemcard::ImportGciInternal(FILE* gcih, const char *inputFile, const std::s
 			ret = WRITEFAIL;
 	}
 	else 
-		ret = ImportFile(tempDEntry, saveData, 0);
+		ret = ImportFile(tempDEntry, saveData);
 
 	return ret;
 }
@@ -1053,7 +1028,7 @@ bool GCMemcard::ReadBannerRGBA8(u8 index, u32* buffer) const
 	if (!m_valid)
 		return false;
 
-	int flags = dir.Dir[index].BIFlags;
+	int flags = CurrentDir->Dir[index].BIFlags;
 	// Timesplitters 2 is the only game that I see this in
 	// May be a hack
 	if (flags == 0xFB) flags = ~flags;
@@ -1063,8 +1038,8 @@ bool GCMemcard::ReadBannerRGBA8(u8 index, u32* buffer) const
 	if (bnrFormat == 0)
 		return false;
 
-	u32 DataOffset = BE32(dir.Dir[index].ImageOffset);
-	u32 DataBlock = BE16(dir.Dir[index].FirstBlock) - MC_FST_BLOCKS;
+	u32 DataOffset = BE32(CurrentDir->Dir[index].ImageOffset);
+	u32 DataBlock = BE16(CurrentDir->Dir[index].FirstBlock) - MC_FST_BLOCKS;
 
 	if ((DataBlock > maxBlock) || (DataOffset == 0xFFFFFFFF))
 	{
@@ -1098,17 +1073,17 @@ u32 GCMemcard::ReadAnimRGBA8(u8 index, u32* buffer, u8 *delays) const
 	// Sonic Heroes it the only game I have seen that tries to use a CI8 and RGB5A3 icon
 	int fmtCheck = 0; 
 
-	int formats = BE16(dir.Dir[index].IconFmt);
-	int fdelays  = BE16(dir.Dir[index].AnimSpeed);
+	int formats = BE16(CurrentDir->Dir[index].IconFmt);
+	int fdelays  = BE16(CurrentDir->Dir[index].AnimSpeed);
 
-	int flags = dir.Dir[index].BIFlags;
+	int flags = CurrentDir->Dir[index].BIFlags;
 	// Timesplitters 2 is the only game that I see this in
 	// May be a hack
 	if (flags == 0xFB) flags = ~flags;
 	int bnrFormat = (flags&3);
 
-	u32 DataOffset = BE32(dir.Dir[index].ImageOffset);
-	u32 DataBlock = BE16(dir.Dir[index].FirstBlock) - MC_FST_BLOCKS;
+	u32 DataOffset = BE32(CurrentDir->Dir[index].ImageOffset);
+	u32 DataBlock = BE16(CurrentDir->Dir[index].FirstBlock) - MC_FST_BLOCKS;
 
 	if ((DataBlock > maxBlock) || (DataOffset == 0xFFFFFFFF))
 	{
diff --git a/Source/Core/Core/Src/HW/GCMemcard.h b/Source/Core/Core/Src/HW/GCMemcard.h
index e66f77887e..dfa6bd6f65 100644
--- a/Source/Core/Core/Src/HW/GCMemcard.h
+++ b/Source/Core/Core/Src/HW/GCMemcard.h
@@ -157,6 +157,7 @@ private:
 		u16 Checksum_Inv;	//0x1ffe	2	Inverse Checksum
 	} dir, dir_backup;
 
+	Directory *CurrentDir, *PreviousDir;
 	struct BlockAlloc {
 		u16 Checksum;		//0x0000	2	Additive Checksum
 		u16 Checksum_Inv;	//0x0002	2	Inverse Checksum
@@ -164,7 +165,12 @@ private:
 		u8 FreeBlocks[2];	//0x0006	2	free Blocks
 		u8 LastAllocated[2];//0x0008	2	last allocated Block
 		u16 Map[BAT_SIZE];		//0x000a	0x1ff8	Map of allocated Blocks
+		u16 GetNextBlock(u16 Block) const;
+		u16 NextFreeBlock(u16 StartingBlock=MC_FST_BLOCKS) const;
+		bool ClearBlocks(u16 StartingBlock, u16 Length);
 	} bat,bat_backup;
+
+	BlockAlloc *CurrentBat, *PreviousBat;
 	struct GCMC_Header
 	{
 		Header *hdr;
@@ -219,9 +225,6 @@ public:
 	std::string GetSaveComment2(u8 index) const;
 	// Copies a DEntry from u8 index to DEntry& data
 	bool GetDEntry(u8 index, DEntry &dest) const;
-	u16 GetNextBlock(u16 Block) const;
-	u16 NextFreeBlock(u16 StartingBlock=MC_FST_BLOCKS) const;
-	bool ClearBlocks(u16 StartingBlock, u16 Length);
 
 	// assumes there's enough space in buffer
 	// old determines if function uses old or new method of copying data
@@ -230,8 +233,7 @@ public:
 	u32 GetSaveData(u8 index, std::vector<GCMBlock> &saveBlocks) const;
 
 	// adds the file to the directory and copies its contents
-	// if remove > 0 it will pad bat.map with 0's sizeof remove
-	u32 ImportFile(DEntry& direntry, std::vector<GCMBlock> &saveBlocks, int remove);
+	u32 ImportFile(DEntry& direntry, std::vector<GCMBlock> &saveBlocks);
 
 	// delete a file from the directory
 	u32 RemoveFile(u8 index);
diff --git a/Source/Core/DolphinWX/Src/MemcardManager.cpp b/Source/Core/DolphinWX/Src/MemcardManager.cpp
index 84e6eb8b1d..a6ed1513c6 100644
--- a/Source/Core/DolphinWX/Src/MemcardManager.cpp
+++ b/Source/Core/DolphinWX/Src/MemcardManager.cpp
@@ -730,8 +730,8 @@ bool CMemcardManager::ReloadMemcard(const char *fileName, int card)
 		wxBlock.Printf(wxT("%10d"), blocks);
 		m_MemcardList[card]->SetItem(index,COLUMN_BLOCKS, wxBlock);
 		firstblock = memoryCard[card]->DEntry_FirstBlock(fileIndex);
-		if (firstblock == 0xFFFF) firstblock = 3;	// to make firstblock -1
-		wxFirstBlock.Printf(wxT("%15d"), firstblock-4);
+		//if (firstblock == 0xFFFF) firstblock = 3;	// to make firstblock -1
+		wxFirstBlock.Printf(wxT("%15d"), firstblock);
 		m_MemcardList[card]->SetItem(index, COLUMN_FIRSTBLOCK, wxFirstBlock);
 		m_MemcardList[card]->SetItem(index, COLUMN_ICON, wxEmptyString);