Fixed a few bugs with the memcard manager, and memcard classes:
- Now the GCMemcard class will use the backup dir/bat if the main one is outdated/corrupted. - I fixed a few bugs in Delete. It still doesn't work, but at least it doesn't make the program crash. I included a small changei n the sln so that debug/x64 builds use release/x64 njoy, this way there's no build errors annoying people trying to debug Dolphin. ;) git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@384 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
parent
53afa1f900
commit
06f0b02ecd
|
@ -32,11 +32,15 @@ END_EVENT_TABLE()
|
|||
CMemcardManager::CMemcardManager(wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& position, const wxSize& size, long style)
|
||||
: wxDialog(parent, id, title, position, size, style)
|
||||
{
|
||||
memoryCard[0]=NULL;
|
||||
memoryCard[1]=NULL;
|
||||
CreateGUIControls();
|
||||
}
|
||||
|
||||
CMemcardManager::~CMemcardManager()
|
||||
{
|
||||
if(memoryCard[0]) delete memoryCard[0];
|
||||
if(memoryCard[1]) delete memoryCard[1];
|
||||
}
|
||||
|
||||
void CMemcardManager::CreateGUIControls()
|
||||
|
@ -135,7 +139,7 @@ void CMemcardManager::CopyDeleteClick(wxCommandEvent& event)
|
|||
case ID_DELETERIGHT:
|
||||
if(index1 != -1)
|
||||
{
|
||||
memoryCard[1]->DeleteFile(index1);
|
||||
memoryCard[1]->RemoveFile(index1);
|
||||
memoryCard[1]->Save();
|
||||
ReloadMemcard(m_Memcard2Path->GetPath().mb_str(), 1);
|
||||
}
|
||||
|
@ -143,7 +147,7 @@ void CMemcardManager::CopyDeleteClick(wxCommandEvent& event)
|
|||
case ID_DELETELEFT:
|
||||
if(index0 != -1)
|
||||
{
|
||||
memoryCard[0]->DeleteFile(index0);
|
||||
memoryCard[0]->RemoveFile(index0);
|
||||
memoryCard[0]->Save();
|
||||
ReloadMemcard(m_Memcard1Path->GetPath().mb_str(), 0);
|
||||
}
|
||||
|
@ -153,6 +157,8 @@ void CMemcardManager::CopyDeleteClick(wxCommandEvent& event)
|
|||
|
||||
void CMemcardManager::ReloadMemcard(const char *fileName, int card)
|
||||
{
|
||||
if(memoryCard[card]) delete memoryCard[card];
|
||||
|
||||
// TODO: add error checking and banners/icons
|
||||
memoryCard[card] = new GCMemcard(fileName);
|
||||
|
||||
|
|
|
@ -32,7 +32,7 @@ u32 GCMemcard::GetNumFiles()
|
|||
{
|
||||
if(!mcdFile) return 0;
|
||||
|
||||
for(int i=0;i<127;i++)
|
||||
for(int i=0;i<126;i++)
|
||||
{
|
||||
if(BE32(dir.Dir[i].Gamecode)==0xFFFFFFFF)
|
||||
return i;
|
||||
|
@ -40,7 +40,7 @@ u32 GCMemcard::GetNumFiles()
|
|||
return 127;
|
||||
}
|
||||
|
||||
bool GCMemcard::DeleteFile(u32 index) //index in the directory array
|
||||
bool GCMemcard::RemoveFile(u32 index) //index in the directory array
|
||||
{
|
||||
if(!mcdFile) return false;
|
||||
|
||||
|
@ -71,17 +71,17 @@ bool GCMemcard::DeleteFile(u32 index) //index in the directory array
|
|||
while((block!=0xffff)&&(blocks_left>0));
|
||||
|
||||
//delete directory entry
|
||||
for(int i=index;i<126;i++)
|
||||
for(int i=index;i<125;i++)
|
||||
{
|
||||
dir.Dir[i]=dir.Dir[i+1];
|
||||
}
|
||||
memset(&(dir.Dir[126]),0xFF,sizeof(DEntry));
|
||||
memset(&(dir.Dir[125]),0xFF,sizeof(DEntry));
|
||||
|
||||
//pack blocks to remove free space partitioning, assume no fragmentation.
|
||||
u8 *mc_data2 = new u8[mc_data_size];
|
||||
|
||||
int firstFree=0;
|
||||
for(int i=0;i<127;i++)
|
||||
for(int i=0;i<126;i++)
|
||||
{
|
||||
if(BE32(dir.Dir[i].Gamecode)==0xFFFFFFFF)
|
||||
{
|
||||
|
@ -102,8 +102,8 @@ bool GCMemcard::DeleteFile(u32 index) //index in the directory array
|
|||
}
|
||||
bat.Map[firstFree+bc-1] = 0xFFFF;
|
||||
|
||||
dir.Dir[i].FirstBlock[0] = u8(firstFree>>8);
|
||||
dir.Dir[i].FirstBlock[1] = u8(firstFree);
|
||||
dir.Dir[i].FirstBlock[0] = u8((firstFree+5)>>8);
|
||||
dir.Dir[i].FirstBlock[1] = u8((firstFree+5));
|
||||
|
||||
firstFree += bc;
|
||||
}
|
||||
|
@ -126,6 +126,11 @@ bool GCMemcard::DeleteFile(u32 index) //index in the directory array
|
|||
bat.FreeBlocks[0] = u8(freespace1>>8);
|
||||
bat.FreeBlocks[1] = u8(freespace1);
|
||||
|
||||
// ... and update counter
|
||||
int updateCtr = BE16(dir.UpdateCounter)+1;
|
||||
dir.UpdateCounter[0] = u8(updateCtr>>8);
|
||||
dir.UpdateCounter[1] = u8(updateCtr);
|
||||
|
||||
//fix checksums
|
||||
u16 csum1=0,csum2=0;
|
||||
calc_checksumsBE((u16*)&dir,0xFFE,&csum1,&csum2);
|
||||
|
@ -139,6 +144,9 @@ bool GCMemcard::DeleteFile(u32 index) //index in the directory array
|
|||
bat.CheckSum2[0]=u8(csum2>>8);
|
||||
bat.CheckSum2[1]=u8(csum2);
|
||||
|
||||
dir_backup=dir;
|
||||
bat_backup=bat;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -167,7 +175,7 @@ u32 GCMemcard::ImportFile(DEntry& direntry, u8* contents)
|
|||
}
|
||||
|
||||
int firstFree3 = 0;
|
||||
for(int i=0;i<127;i++)
|
||||
for(int i=0;i<126;i++)
|
||||
{
|
||||
if(BE32(dir.Dir[i].Gamecode)==0xFFFFFFFF)
|
||||
{
|
||||
|
@ -182,6 +190,12 @@ u32 GCMemcard::ImportFile(DEntry& direntry, u8* contents)
|
|||
if(firstFree2 > firstFree1) firstFree1 = firstFree2;
|
||||
if(firstFree3 > firstFree1) firstFree1 = firstFree3;
|
||||
|
||||
if(firstFree1>=126)
|
||||
{
|
||||
// TODO: show messagebox about the error
|
||||
return 0;
|
||||
}
|
||||
|
||||
// find first free dir entry
|
||||
int index=-1;
|
||||
for(int i=0;i<127;i++)
|
||||
|
@ -192,6 +206,7 @@ u32 GCMemcard::ImportFile(DEntry& direntry, u8* contents)
|
|||
dir.Dir[i] = direntry;
|
||||
dir.Dir[i].FirstBlock[0] = u8(firstFree1>>8);
|
||||
dir.Dir[i].FirstBlock[1] = u8(firstFree1);
|
||||
dir.Dir[i].CopyCounter = dir.Dir[i].CopyCounter+1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -208,6 +223,11 @@ u32 GCMemcard::ImportFile(DEntry& direntry, u8* contents)
|
|||
bat.FreeBlocks[0] = u8(freespace1>>8);
|
||||
bat.FreeBlocks[1] = u8(freespace1);
|
||||
|
||||
// ... and update counter
|
||||
int updateCtr = BE16(dir.UpdateCounter)+1;
|
||||
dir.UpdateCounter[0] = u8(updateCtr>>8);
|
||||
dir.UpdateCounter[1] = u8(updateCtr);
|
||||
|
||||
//fix checksums
|
||||
u16 csum1=0,csum2=0;
|
||||
calc_checksumsBE((u16*)&dir,0xFFE,&csum1,&csum2);
|
||||
|
@ -309,25 +329,27 @@ u32 GCMemcard::TestChecksums()
|
|||
|
||||
u16 csum1=0,csum2=0;
|
||||
|
||||
u32 results = 0;
|
||||
|
||||
calc_checksumsBE((u16*)&hdr, 0xFE ,&csum1,&csum2);
|
||||
if(BE16(hdr.CheckSum1)!=csum1) return 1;
|
||||
if(BE16(hdr.CheckSum2)!=csum2) return 1;
|
||||
if(BE16(hdr.CheckSum1)!=csum1) results |= 1;
|
||||
if(BE16(hdr.CheckSum2)!=csum2) results |= 1;
|
||||
|
||||
calc_checksumsBE((u16*)&dir,0xFFE,&csum1,&csum2);
|
||||
if(BE16(dir.CheckSum1)!=csum1) return 2;
|
||||
if(BE16(dir.CheckSum2)!=csum2) return 2;
|
||||
if(BE16(dir.CheckSum1)!=csum1) results |= 2;
|
||||
if(BE16(dir.CheckSum2)!=csum2) results |= 2;
|
||||
|
||||
calc_checksumsBE((u16*)&dir_backup,0xFFE,&csum1,&csum2);
|
||||
if(BE16(dir_backup.CheckSum1)!=csum1) return 3;
|
||||
if(BE16(dir_backup.CheckSum2)!=csum2) return 3;
|
||||
if(BE16(dir_backup.CheckSum1)!=csum1) results |= 4;
|
||||
if(BE16(dir_backup.CheckSum2)!=csum2) results |= 4;
|
||||
|
||||
calc_checksumsBE((u16*)(((u8*)&bat)+4),0xFFE,&csum1,&csum2);
|
||||
if(BE16(bat.CheckSum1)!=csum1) return 4;
|
||||
if(BE16(bat.CheckSum2)!=csum2) return 4;
|
||||
if(BE16(bat.CheckSum1)!=csum1) results |= 8;
|
||||
if(BE16(bat.CheckSum2)!=csum2) results |= 8;
|
||||
|
||||
calc_checksumsBE((u16*)(((u8*)&bat_backup)+4),0xFFE,&csum1,&csum2);
|
||||
if(BE16(bat_backup.CheckSum1)!=csum1) return 5;
|
||||
if(BE16(bat_backup.CheckSum2)!=csum2) return 5;
|
||||
if(BE16(bat_backup.CheckSum1)!=csum1) results |= 16;
|
||||
if(BE16(bat_backup.CheckSum2)!=csum2) results |= 16;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -382,6 +404,56 @@ GCMemcard::GCMemcard(const char *filename)
|
|||
assert(fread(&bat, 1,0x2000,mcd)==0x2000);
|
||||
assert(fread(&bat_backup,1,0x2000,mcd)==0x2000);
|
||||
|
||||
u32 csums = TestChecksums();
|
||||
|
||||
if(csums&1)
|
||||
{
|
||||
// header checksum error!
|
||||
// TODO: fail to load
|
||||
}
|
||||
|
||||
if(csums&2) // directory checksum error!
|
||||
{
|
||||
if(csums&4)
|
||||
{
|
||||
// backup is also wrong!
|
||||
// TODO: fail to load
|
||||
}
|
||||
else
|
||||
{
|
||||
// backup is correct, restore
|
||||
dir = dir_backup;
|
||||
bat = bat_backup;
|
||||
|
||||
// update checksums
|
||||
csums = TestChecksums();
|
||||
}
|
||||
}
|
||||
|
||||
if(csums&8) // BAT checksum error!
|
||||
{
|
||||
if(csums&16)
|
||||
{
|
||||
// backup is also wrong!
|
||||
// TODO: fail to load
|
||||
}
|
||||
else
|
||||
{
|
||||
// backup is correct, restore
|
||||
dir = dir_backup;
|
||||
bat = bat_backup;
|
||||
|
||||
// update checksums
|
||||
csums = TestChecksums();
|
||||
}
|
||||
}
|
||||
|
||||
if(BE16(dir_backup.UpdateCounter) > BE16(dir.UpdateCounter)) //check if the backup is newer
|
||||
{
|
||||
dir = dir_backup;
|
||||
bat = bat_backup; // needed?
|
||||
}
|
||||
|
||||
fseek(mcd,0xa000,SEEK_SET);
|
||||
|
||||
mc_data_size=(((u32)BE16(hdr.Size)*16)-5)*0x2000;
|
||||
|
|
|
@ -146,7 +146,7 @@ public:
|
|||
bool GetFileData(u32 index, u8* buffer);
|
||||
|
||||
// delete a file from the directory
|
||||
bool DeleteFile(u32 index);
|
||||
bool RemoveFile(u32 index);
|
||||
|
||||
// adds the file to the directory and copies its contents
|
||||
u32 ImportFile(DEntry& direntry, u8* contents);
|
||||
|
|
|
@ -277,8 +277,8 @@ Global
|
|||
{805B34AA-82A5-4875-8DC7-3C85BDC0BCEE}.Release|x64.Build.0 = Release|x64
|
||||
{521498BE-6089-4780-8223-E67C22F4E068}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{521498BE-6089-4780-8223-E67C22F4E068}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{521498BE-6089-4780-8223-E67C22F4E068}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{521498BE-6089-4780-8223-E67C22F4E068}.Debug|x64.Build.0 = Debug|x64
|
||||
{521498BE-6089-4780-8223-E67C22F4E068}.Debug|x64.ActiveCfg = Release|x64
|
||||
{521498BE-6089-4780-8223-E67C22F4E068}.Debug|x64.Build.0 = Release|x64
|
||||
{521498BE-6089-4780-8223-E67C22F4E068}.DebugFast|Win32.ActiveCfg = DebugFast|Win32
|
||||
{521498BE-6089-4780-8223-E67C22F4E068}.DebugFast|Win32.Build.0 = DebugFast|Win32
|
||||
{521498BE-6089-4780-8223-E67C22F4E068}.DebugFast|x64.ActiveCfg = DebugFast|x64
|
||||
|
|
Loading…
Reference in New Issue