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:
parent
1fe67e19ab
commit
3d20c57458
|
@ -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))
|
||||||
{
|
{
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue