Update directorys and BlockAllocs correctly, use the most uptodate directory/bat instead of always the first

Signed-off-by: LPFaint99 <lpfaint99@gmail.com>
This commit is contained in:
LPFaint99 2012-02-06 17:27:49 -08:00
parent 1fe67e19ab
commit 3d20c57458
3 changed files with 164 additions and 187 deletions

View File

@ -227,6 +227,28 @@ GCMemcard::GCMemcard(const char *filename, bool forceCreation, bool sjis)
} }
mcdFile.Close(); 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 bool GCMemcard::IsAsciiEncoding() const
@ -321,7 +343,7 @@ u8 GCMemcard::GetNumFiles() const
u8 j = 0; u8 j = 0;
for (int i = 0; i < DIRLEN; i++) for (int i = 0; i < DIRLEN; i++)
{ {
if (BE32(dir.Dir[i].Gamecode)!= 0xFFFFFFFF) if (BE32(CurrentDir->Dir[i].Gamecode)!= 0xFFFFFFFF)
j++; j++;
} }
return j; return j;
@ -335,7 +357,7 @@ u8 GCMemcard::GetFileIndex(u8 fileNumber) const
u8 j = 0; u8 j = 0;
for (u8 i = 0; i < DIRLEN; i++) for (u8 i = 0; i < DIRLEN; i++)
{ {
if (BE32(dir.Dir[i].Gamecode)!= 0xFFFFFFFF) if (BE32(CurrentDir->Dir[i].Gamecode)!= 0xFFFFFFFF)
{ {
if (j == fileNumber) if (j == fileNumber)
{ {
@ -353,7 +375,7 @@ u16 GCMemcard::GetFreeBlocks() const
if (!m_valid) if (!m_valid)
return 0; return 0;
return BE16(bat.FreeBlocks); return BE16(CurrentBat->FreeBlocks);
} }
u8 GCMemcard::TitlePresent(DEntry d) const u8 GCMemcard::TitlePresent(DEntry d) const
@ -364,8 +386,8 @@ u8 GCMemcard::TitlePresent(DEntry d) const
u8 i = 0; u8 i = 0;
while(i < DIRLEN) while(i < DIRLEN)
{ {
if ((BE32(dir.Dir[i].Gamecode) == BE32(d.Gamecode)) && if ((BE32(CurrentDir->Dir[i].Gamecode) == BE32(d.Gamecode)) &&
(!memcmp(dir.Dir[i].Filename, d.Filename, 32))) (!memcmp(CurrentDir->Dir[i].Filename, d.Filename, 32)))
{ {
break; break;
} }
@ -376,9 +398,9 @@ u8 GCMemcard::TitlePresent(DEntry d) const
bool GCMemcard::GCI_FileName(u8 index, std::string &filename) 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; 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; return true;
} }
@ -389,14 +411,14 @@ std::string GCMemcard::DEntry_GameCode(u8 index) const
{ {
if (!m_valid || index > DIRLEN) if (!m_valid || index > DIRLEN)
return ""; 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 std::string GCMemcard::DEntry_Makercode(u8 index) const
{ {
if (!m_valid || index > DIRLEN) if (!m_valid || index > DIRLEN)
return ""; 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 std::string GCMemcard::DEntry_BIFlags(u8 index) const
@ -405,7 +427,7 @@ std::string GCMemcard::DEntry_BIFlags(u8 index) const
return ""; return "";
std::string flags; std::string flags;
int x = dir.Dir[index].BIFlags; int x = CurrentDir->Dir[index].BIFlags;
for (int i = 0; i < 8; i++) for (int i = 0; i < 8; i++)
{ {
flags.push_back((x & 0x80) ? '1' : '0'); flags.push_back((x & 0x80) ? '1' : '0');
@ -419,32 +441,32 @@ std::string GCMemcard::DEntry_FileName(u8 index) const
{ {
if (!m_valid || index > DIRLEN) if (!m_valid || index > DIRLEN)
return ""; 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 u32 GCMemcard::DEntry_ModTime(u8 index) const
{ {
if (!m_valid || index > DIRLEN) if (!m_valid || index > DIRLEN)
return 0xFFFFFFFF; return 0xFFFFFFFF;
return BE32(dir.Dir[index].ModTime); return BE32(CurrentDir->Dir[index].ModTime);
} }
u32 GCMemcard::DEntry_ImageOffset(u8 index) const u32 GCMemcard::DEntry_ImageOffset(u8 index) const
{ {
if (!m_valid || index > DIRLEN) if (!m_valid || index > DIRLEN)
return 0xFFFFFFFF; return 0xFFFFFFFF;
return BE32(dir.Dir[index].ImageOffset); return BE32(CurrentDir->Dir[index].ImageOffset);
} }
std::string GCMemcard::DEntry_IconFmt(u8 index) const std::string GCMemcard::DEntry_IconFmt(u8 index) const
{ {
if (!m_valid || index > DIRLEN) if (!m_valid || index > DIRLEN)
return ""; return "";
int x = dir.Dir[index].IconFmt[0]; int x = CurrentDir->Dir[index].IconFmt[0];
std::string format; std::string format;
for(int i = 0; i < 16; i++) 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'); format.push_back((x & 0x80) ? '1' : '0');
x = x << 1; x = x << 1;
} }
@ -456,14 +478,14 @@ u16 GCMemcard::DEntry_AnimSpeed(u8 index) const
{ {
if (!m_valid || index > DIRLEN) if (!m_valid || index > DIRLEN)
return 0xFF; return 0xFF;
return BE16(dir.Dir[index].AnimSpeed); return BE16(CurrentDir->Dir[index].AnimSpeed);
} }
std::string GCMemcard::DEntry_Permissions(u8 index) const std::string GCMemcard::DEntry_Permissions(u8 index) const
{ {
if (!m_valid || index > DIRLEN) if (!m_valid || index > DIRLEN)
return ""; return "";
u8 Permissions = dir.Dir[index].Permissions; u8 Permissions = CurrentDir->Dir[index].Permissions;
std::string permissionsString; std::string permissionsString;
permissionsString.push_back((Permissions & 16) ? 'x' : 'M'); permissionsString.push_back((Permissions & 16) ? 'x' : 'M');
permissionsString.push_back((Permissions & 8) ? 'x' : 'C'); permissionsString.push_back((Permissions & 8) ? 'x' : 'C');
@ -476,7 +498,7 @@ u8 GCMemcard::DEntry_CopyCounter(u8 index) const
{ {
if (!m_valid || index > DIRLEN) if (!m_valid || index > DIRLEN)
return 0xFF; return 0xFF;
return dir.Dir[index].CopyCounter; return CurrentDir->Dir[index].CopyCounter;
} }
u16 GCMemcard::DEntry_FirstBlock(u8 index) const u16 GCMemcard::DEntry_FirstBlock(u8 index) const
@ -484,7 +506,7 @@ u16 GCMemcard::DEntry_FirstBlock(u8 index) const
if (!m_valid || index > DIRLEN) if (!m_valid || index > DIRLEN)
return 0xFFFF; return 0xFFFF;
u16 block = BE16(dir.Dir[index].FirstBlock); u16 block = BE16(CurrentDir->Dir[index].FirstBlock);
if (block > (u16) maxBlock) return 0xFFFF; if (block > (u16) maxBlock) return 0xFFFF;
return block; return block;
} }
@ -494,7 +516,7 @@ u16 GCMemcard::DEntry_BlockCount(u8 index) const
if (!m_valid || index > DIRLEN) if (!m_valid || index > DIRLEN)
return 0xFFFF; return 0xFFFF;
u16 blocks = BE16(dir.Dir[index].BlockCount); u16 blocks = BE16(CurrentDir->Dir[index].BlockCount);
if (blocks > (u16) maxBlock) return 0xFFFF; if (blocks > (u16) maxBlock) return 0xFFFF;
return blocks; return blocks;
} }
@ -503,7 +525,7 @@ u32 GCMemcard::DEntry_CommentsAddress(u8 index) const
{ {
if (!m_valid || index > DIRLEN) if (!m_valid || index > DIRLEN)
return 0xFFFF; return 0xFFFF;
return BE32(dir.Dir[index].CommentsAddr); return BE32(CurrentDir->Dir[index].CommentsAddr);
} }
std::string GCMemcard::GetSaveComment1(u8 index) const std::string GCMemcard::GetSaveComment1(u8 index) const
@ -511,8 +533,8 @@ std::string GCMemcard::GetSaveComment1(u8 index) const
if (!m_valid || index > DIRLEN) if (!m_valid || index > DIRLEN)
return ""; return "";
u32 Comment1 = BE32(dir.Dir[index].CommentsAddr); u32 Comment1 = BE32(CurrentDir->Dir[index].CommentsAddr);
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)) if ((DataBlock > maxBlock) || (Comment1 == 0xFFFFFFFF))
{ {
return ""; return "";
@ -525,9 +547,9 @@ std::string GCMemcard::GetSaveComment2(u8 index) const
if (!m_valid || index > DIRLEN) if (!m_valid || index > DIRLEN)
return ""; return "";
u32 Comment1 = BE32(dir.Dir[index].CommentsAddr); u32 Comment1 = BE32(CurrentDir->Dir[index].CommentsAddr);
u32 Comment2 = Comment1 + DENTRY_STRLEN; 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)) if ((DataBlock > maxBlock) || (Comment1 == 0xFFFFFFFF))
{ {
return ""; return "";
@ -539,44 +561,47 @@ bool GCMemcard::GetDEntry(u8 index, DEntry &dest) const
{ {
if (!m_valid || index > DIRLEN) if (!m_valid || index > DIRLEN)
return false; return false;
dest = dir.Dir[index]; dest = CurrentDir->Dir[index];
return true; return true;
} }
u16 GCMemcard::BlockAlloc::GetNextBlock(u16 Block) const
u16 GCMemcard::GetNextBlock(u16 Block) const
{ {
if ((Block < MC_FST_BLOCKS) || (Block > maxBlock)) if ((Block < MC_FST_BLOCKS) || (Block > 4091))
return 0; 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) 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; return i;
} }
bool GCMemcard::ClearBlocks(u16 FirstBlock, u16 BlockCount) bool GCMemcard::BlockAlloc::ClearBlocks(u16 FirstBlock, u16 BlockCount)
{ {
std::vector<u16> blocks; std::vector<u16> blocks;
while (FirstBlock != 0xFF && FirstBlock != 0) while (FirstBlock != 0xFFFF && FirstBlock != 0)
{ {
blocks.push_back(FirstBlock); blocks.push_back(FirstBlock);
FirstBlock = GetNextBlock(FirstBlock); FirstBlock = GetNextBlock(FirstBlock);
} }
if (FirstBlock > 0) if (FirstBlock > 0)
{ {
size_t length = blocks.size(); size_t length = blocks.size();
if (length != BlockCount) if (length != BlockCount)
{
return false; 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);
} }
for (int i = 0; i < length; ++i)
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 u32 GCMemcard::GetSaveData(u8 index, std::vector<GCMBlock> & Blocks) const
{ {
if (!m_valid) if (!m_valid)
@ -597,13 +622,13 @@ u32 GCMemcard::GetSaveData(u8 index, std::vector<GCMBlock> & Blocks) const
if ((!nextBlock) || (nextBlock == 0xFFFF)) if ((!nextBlock) || (nextBlock == 0xFFFF))
return FAIL; return FAIL;
Blocks.push_back(mc_data_blocks[nextBlock-MC_FST_BLOCKS]); Blocks.push_back(mc_data_blocks[nextBlock-MC_FST_BLOCKS]);
nextBlock = GetNextBlock(nextBlock); nextBlock = CurrentBat->GetNextBlock(nextBlock);
} }
return SUCCESS; return SUCCESS;
} }
// End DEntry functions // 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) if (!m_valid)
return NOMEMCARD; return NOMEMCARD;
@ -612,11 +637,11 @@ u32 GCMemcard::ImportFile(DEntry& direntry, std::vector<GCMBlock> &saveBlocks, i
{ {
return OUTOFDIRENTRIES; return OUTOFDIRENTRIES;
} }
if (BE16(bat.FreeBlocks) < BE16(direntry.BlockCount)) if (BE16(CurrentBat->FreeBlocks) < BE16(direntry.BlockCount))
{ {
return OUTOFBLOCKS; return OUTOFBLOCKS;
} }
if (!remove && (TitlePresent(direntry) != DIRLEN)) if (TitlePresent(direntry) != DIRLEN)
{ {
return TITLEPRESENT; 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 totalspace = (((u32)BE16(hdr.SizeMb) * MBIT_TO_BLOCKS) - MC_FST_BLOCKS);
//int firstFree1 = BE16(bat.LastAllocated) + 1; //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 // find first free dir entry
int index = -1; int index = -1;
for (int i=0; i < DIRLEN; i++) for (int i=0; i < DIRLEN; i++)
{ {
if (BE32(dir.Dir[i].Gamecode) == 0xFFFFFFFF) if (BE32(UpdatedDir.Dir[i].Gamecode) == 0xFFFFFFFF)
{ {
index = i; index = i;
dir.Dir[i] = direntry; UpdatedDir.Dir[i] = direntry;
*(u16*)&dir.Dir[i].FirstBlock = BE16(firstBlock); *(u16*)&UpdatedDir.Dir[i].FirstBlock = BE16(firstBlock);
if (!remove) UpdatedDir.Dir[i].CopyCounter = UpdatedDir.Dir[i].CopyCounter+1;
{
dir.Dir[i].CopyCounter = dir.Dir[i].CopyCounter+1;
}
dir_backup = dir;
break; 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); int fileBlocks = BE16(direntry.BlockCount);
BlockAlloc UpdatedBat = *CurrentBat;
u16 nextBlock; u16 nextBlock;
// keep assuming no freespace fragmentation, and copy over all the data // keep assuming no freespace fragmentation, and copy over all the data
for (int i = 0; i < fileBlocks; ++i) 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) if (i == fileBlocks-1)
nextBlock = 0xFFFF; nextBlock = 0xFFFF;
else else
nextBlock = NextFreeBlock(firstBlock+1); nextBlock = UpdatedBat.NextFreeBlock(firstBlock+1);
bat.Map[firstBlock - MC_FST_BLOCKS] = BE16(nextBlock); UpdatedBat.Map[firstBlock - MC_FST_BLOCKS] = BE16(nextBlock);
firstBlock = nextBlock; firstBlock = nextBlock;
} }
*(u16*)&UpdatedBat.FreeBlocks = BE16(BE16(UpdatedBat.FreeBlocks) - fileBlocks);
bat_backup = bat; *(u16*)&UpdatedBat.UpdateCounter = BE16(BE16(UpdatedBat.UpdateCounter) + 1);
/* u16 last = BE16(bat_backup.LastAllocated); *PreviousBat = UpdatedBat;
u16 i = (last - 4); if (PreviousBat == &bat )
int j = 2;
while(j < BE16(direntry.BlockCount) + 1)
{ {
bat_backup.Map[i] = BE16(last + (u16)j); CurrentBat = &bat;
i++; PreviousBat = &bat_backup;
j++;
} }
bat_backup.Map[i++] = 0xFFFF; else
//Set bat.map to 0 for each block that was removed
for (int k = 0; k < remove; k++)
{ {
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; return SUCCESS;
} }
@ -717,86 +720,58 @@ u32 GCMemcard::RemoveFile(u8 index) //index in the directory array
if (index >= DIRLEN) if (index >= DIRLEN)
return DELETE_FAIL; return DELETE_FAIL;
dir_backup = dir;
bat_backup = bat;
u16 startingblock = BE16(dir.Dir[index].FirstBlock); u16 startingblock = BE16(dir.Dir[index].FirstBlock);
u16 numberofblocks = BE16(dir.Dir[index].BlockCount); u16 numberofblocks = BE16(dir.Dir[index].BlockCount);
if (!ClearBlocks(startingblock, numberofblocks))
BlockAlloc UpdatedBat = *CurrentBat;
if (!UpdatedBat.ClearBlocks(startingblock, numberofblocks))
return DELETE_FAIL; 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);
memset(&(dir.Dir[index]), 0xFF, DENTRY_SIZE); *PreviousDir = UpdatedDir;
if (PreviousDir == &dir )
*(u16*)&dir.UpdateCounter = BE16(BE16(dir.UpdateCounter) + 1); {
*(u16*)&bat.UpdateCounter = BE16(BE16(bat.UpdateCounter) + 1); 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;
}
return SUCCESS; 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) u32 GCMemcard::CopyFrom(const GCMemcard& source, u8 index)
@ -820,7 +795,7 @@ u32 GCMemcard::CopyFrom(const GCMemcard& source, u8 index)
case NOMEMCARD: case NOMEMCARD:
return NOMEMCARD; return NOMEMCARD;
default: 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; ret = WRITEFAIL;
} }
else else
ret = ImportFile(tempDEntry, saveData, 0); ret = ImportFile(tempDEntry, saveData);
return ret; return ret;
} }
@ -1053,7 +1028,7 @@ bool GCMemcard::ReadBannerRGBA8(u8 index, u32* buffer) const
if (!m_valid) if (!m_valid)
return false; 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 // Timesplitters 2 is the only game that I see this in
// May be a hack // May be a hack
if (flags == 0xFB) flags = ~flags; if (flags == 0xFB) flags = ~flags;
@ -1063,8 +1038,8 @@ bool GCMemcard::ReadBannerRGBA8(u8 index, u32* buffer) const
if (bnrFormat == 0) if (bnrFormat == 0)
return false; return false;
u32 DataOffset = BE32(dir.Dir[index].ImageOffset); u32 DataOffset = BE32(CurrentDir->Dir[index].ImageOffset);
u32 DataBlock = BE16(dir.Dir[index].FirstBlock) - MC_FST_BLOCKS; u32 DataBlock = BE16(CurrentDir->Dir[index].FirstBlock) - MC_FST_BLOCKS;
if ((DataBlock > maxBlock) || (DataOffset == 0xFFFFFFFF)) 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 // Sonic Heroes it the only game I have seen that tries to use a CI8 and RGB5A3 icon
int fmtCheck = 0; int fmtCheck = 0;
int formats = BE16(dir.Dir[index].IconFmt); int formats = BE16(CurrentDir->Dir[index].IconFmt);
int fdelays = BE16(dir.Dir[index].AnimSpeed); 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 // Timesplitters 2 is the only game that I see this in
// May be a hack // May be a hack
if (flags == 0xFB) flags = ~flags; if (flags == 0xFB) flags = ~flags;
int bnrFormat = (flags&3); int bnrFormat = (flags&3);
u32 DataOffset = BE32(dir.Dir[index].ImageOffset); u32 DataOffset = BE32(CurrentDir->Dir[index].ImageOffset);
u32 DataBlock = BE16(dir.Dir[index].FirstBlock) - MC_FST_BLOCKS; u32 DataBlock = BE16(CurrentDir->Dir[index].FirstBlock) - MC_FST_BLOCKS;
if ((DataBlock > maxBlock) || (DataOffset == 0xFFFFFFFF)) if ((DataBlock > maxBlock) || (DataOffset == 0xFFFFFFFF))
{ {

View File

@ -157,6 +157,7 @@ private:
u16 Checksum_Inv; //0x1ffe 2 Inverse Checksum u16 Checksum_Inv; //0x1ffe 2 Inverse Checksum
} dir, dir_backup; } dir, dir_backup;
Directory *CurrentDir, *PreviousDir;
struct BlockAlloc { struct BlockAlloc {
u16 Checksum; //0x0000 2 Additive Checksum u16 Checksum; //0x0000 2 Additive Checksum
u16 Checksum_Inv; //0x0002 2 Inverse Checksum u16 Checksum_Inv; //0x0002 2 Inverse Checksum
@ -164,7 +165,12 @@ private:
u8 FreeBlocks[2]; //0x0006 2 free Blocks u8 FreeBlocks[2]; //0x0006 2 free Blocks
u8 LastAllocated[2];//0x0008 2 last allocated Block u8 LastAllocated[2];//0x0008 2 last allocated Block
u16 Map[BAT_SIZE]; //0x000a 0x1ff8 Map of allocated Blocks 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; } bat,bat_backup;
BlockAlloc *CurrentBat, *PreviousBat;
struct GCMC_Header struct GCMC_Header
{ {
Header *hdr; Header *hdr;
@ -219,9 +225,6 @@ public:
std::string GetSaveComment2(u8 index) const; std::string GetSaveComment2(u8 index) const;
// Copies a DEntry from u8 index to DEntry& data // Copies a DEntry from u8 index to DEntry& data
bool GetDEntry(u8 index, DEntry &dest) const; 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 // assumes there's enough space in buffer
// old determines if function uses old or new method of copying data // 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; u32 GetSaveData(u8 index, std::vector<GCMBlock> &saveBlocks) const;
// adds the file to the directory and copies its contents // 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);
u32 ImportFile(DEntry& direntry, std::vector<GCMBlock> &saveBlocks, int remove);
// delete a file from the directory // delete a file from the directory
u32 RemoveFile(u8 index); u32 RemoveFile(u8 index);

View File

@ -730,8 +730,8 @@ bool CMemcardManager::ReloadMemcard(const char *fileName, int card)
wxBlock.Printf(wxT("%10d"), blocks); wxBlock.Printf(wxT("%10d"), blocks);
m_MemcardList[card]->SetItem(index,COLUMN_BLOCKS, wxBlock); m_MemcardList[card]->SetItem(index,COLUMN_BLOCKS, wxBlock);
firstblock = memoryCard[card]->DEntry_FirstBlock(fileIndex); firstblock = memoryCard[card]->DEntry_FirstBlock(fileIndex);
if (firstblock == 0xFFFF) firstblock = 3; // to make firstblock -1 //if (firstblock == 0xFFFF) firstblock = 3; // to make firstblock -1
wxFirstBlock.Printf(wxT("%15d"), firstblock-4); wxFirstBlock.Printf(wxT("%15d"), firstblock);
m_MemcardList[card]->SetItem(index, COLUMN_FIRSTBLOCK, wxFirstBlock); m_MemcardList[card]->SetItem(index, COLUMN_FIRSTBLOCK, wxFirstBlock);
m_MemcardList[card]->SetItem(index, COLUMN_ICON, wxEmptyString); m_MemcardList[card]->SetItem(index, COLUMN_ICON, wxEmptyString);