2016-12-19 19:20:30 +00:00
|
|
|
#include "CMemoryCardDriver.hpp"
|
|
|
|
#include "MP1.hpp"
|
2016-12-20 21:51:50 +00:00
|
|
|
#include "CCRC32.hpp"
|
2016-12-19 19:20:30 +00:00
|
|
|
|
|
|
|
namespace urde
|
|
|
|
{
|
|
|
|
namespace MP1
|
|
|
|
{
|
|
|
|
|
2016-12-23 06:41:39 +00:00
|
|
|
static const char* SaveFileNames[] =
|
|
|
|
{
|
|
|
|
"MetroidPrime A",
|
|
|
|
"MetroidPrime B"
|
|
|
|
};
|
|
|
|
|
2016-12-20 21:51:50 +00:00
|
|
|
using ECardResult = CMemoryCardSys::ECardResult;
|
|
|
|
using EMemoryCardPort = CMemoryCardSys::EMemoryCardPort;
|
2016-12-19 19:20:30 +00:00
|
|
|
|
2016-12-23 06:41:39 +00:00
|
|
|
ECardResult CMemoryCardDriver::SFileInfo::Open()
|
|
|
|
{
|
|
|
|
//CARDOpen(GetFileCardPort(), x14_name.data(), &x0_fileInfo);
|
|
|
|
return ECardResult::CARD_RESULT_READY;
|
|
|
|
}
|
|
|
|
|
2016-12-20 21:51:50 +00:00
|
|
|
ECardResult CMemoryCardDriver::SFileInfo::Close()
|
|
|
|
{
|
|
|
|
auto backup = GetFileCardPort();
|
|
|
|
ECardResult result = ECardResult::CARD_RESULT_READY;
|
|
|
|
//result = CARDClose(backup);
|
|
|
|
x0_fileInfo.x0_cardPort = backup;
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2016-12-23 06:41:39 +00:00
|
|
|
CMemoryCardSys::ECardResult CMemoryCardDriver::SFileInfo::StartRead()
|
|
|
|
{
|
|
|
|
CMemoryCardSys::CARDStat stat = {};
|
|
|
|
ECardResult result = CMemoryCardSys::GetStatus(GetFileCardPort(), GetFileNo(), stat);
|
|
|
|
if (result != ECardResult::CARD_RESULT_READY)
|
|
|
|
return result;
|
|
|
|
|
|
|
|
u32 length = stat.GetFileLength();
|
|
|
|
x34_saveData.clear();
|
|
|
|
x24_saveFileData.resize(length);
|
|
|
|
//return CARDReadAsync(&x0_fileInfo, x24_saveFileData.data(), length, 0, 0);
|
|
|
|
return ECardResult::CARD_RESULT_READY;
|
|
|
|
}
|
|
|
|
|
2016-12-20 21:51:50 +00:00
|
|
|
ECardResult CMemoryCardDriver::SFileInfo::TryFileRead()
|
|
|
|
{
|
|
|
|
ECardResult res = CMemoryCardSys::GetResultCode(GetFileCardPort());
|
|
|
|
if (res == ECardResult::CARD_RESULT_READY)
|
|
|
|
res = FileRead();
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
ECardResult CMemoryCardDriver::SFileInfo::FileRead()
|
|
|
|
{
|
|
|
|
x34_saveData.clear();
|
|
|
|
u32 existingCrc = hecl::SBig(*reinterpret_cast<u32*>(x24_saveFileData.data()));
|
|
|
|
u32 newCrc = CCRC32::Calculate(x24_saveFileData.data() + 4, x24_saveFileData.size() - 4);
|
|
|
|
if (existingCrc == newCrc)
|
|
|
|
{
|
|
|
|
u32 saveDataOff;
|
|
|
|
ECardResult result = GetSaveDataOffset(saveDataOff);
|
|
|
|
if (result != ECardResult::CARD_RESULT_READY)
|
|
|
|
{
|
|
|
|
x24_saveFileData.clear();
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
u32 saveSize = x24_saveFileData.size() - saveDataOff;
|
|
|
|
x34_saveData.resize(saveSize);
|
|
|
|
memmove(x34_saveData.data(), x24_saveFileData.data() + saveDataOff, saveSize);
|
|
|
|
x24_saveFileData.clear();
|
|
|
|
return ECardResult::CARD_RESULT_READY;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
x24_saveFileData.clear();
|
|
|
|
return ECardResult::CARD_RESULT_CRC_MISMATCH;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ECardResult CMemoryCardDriver::SFileInfo::GetSaveDataOffset(u32& offOut)
|
|
|
|
{
|
|
|
|
CMemoryCardSys::CARDStat stat = {};
|
|
|
|
ECardResult result = CMemoryCardSys::GetStatus(GetFileCardPort(), GetFileNo(), stat);
|
|
|
|
if (result != ECardResult::CARD_RESULT_READY)
|
|
|
|
{
|
|
|
|
offOut = -1;
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
offOut = 4;
|
|
|
|
offOut += 64;
|
|
|
|
switch (stat.GetBannerFormat())
|
|
|
|
{
|
|
|
|
case 1:
|
|
|
|
offOut += 3584;
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
offOut += 6144;
|
|
|
|
break;
|
|
|
|
default: break;
|
|
|
|
}
|
|
|
|
|
|
|
|
int idx = 0;
|
|
|
|
bool paletteIcon = false;
|
|
|
|
while (u32 fmt = stat.GetIconFormat(idx))
|
|
|
|
{
|
|
|
|
if (fmt == 1)
|
|
|
|
{
|
|
|
|
paletteIcon = true;
|
|
|
|
offOut += 1024;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
offOut += 2048;
|
|
|
|
++idx;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (paletteIcon)
|
|
|
|
offOut += 512;
|
|
|
|
|
|
|
|
return ECardResult::CARD_RESULT_READY;
|
|
|
|
}
|
|
|
|
|
|
|
|
CMemoryCardDriver::SGameFileSlot::SGameFileSlot()
|
|
|
|
{
|
|
|
|
InitializeFromGameState();
|
|
|
|
}
|
|
|
|
|
2016-12-20 22:09:02 +00:00
|
|
|
CMemoryCardDriver::SGameFileSlot::SGameFileSlot(CMemoryInStream& in)
|
|
|
|
{
|
|
|
|
in.readBytesToBuf(x0_saveBuffer, 940);
|
|
|
|
x944_fileInfo = CGameState::LoadGameFileState(x0_saveBuffer);
|
|
|
|
}
|
|
|
|
|
2016-12-20 21:51:50 +00:00
|
|
|
void CMemoryCardDriver::SGameFileSlot::InitializeFromGameState()
|
|
|
|
{
|
|
|
|
CBitStreamWriter w(x0_saveBuffer, 940);
|
|
|
|
g_GameState->PutTo(w);
|
|
|
|
x944_fileInfo = CGameState::LoadGameFileState(x0_saveBuffer);
|
|
|
|
}
|
|
|
|
|
|
|
|
CMemoryCardDriver::SFileInfo::SFileInfo(EMemoryCardPort port,
|
|
|
|
const std::string& name)
|
|
|
|
: x14_name(name)
|
|
|
|
{
|
|
|
|
x0_fileInfo.x0_cardPort = port;
|
|
|
|
}
|
|
|
|
|
|
|
|
CMemoryCardDriver::CMemoryCardDriver(EMemoryCardPort cardPort, ResId saveBanner,
|
2016-12-23 06:41:39 +00:00
|
|
|
ResId saveIcon0, ResId saveIcon1, bool importPersistent)
|
2016-12-19 19:20:30 +00:00
|
|
|
: x0_cardPort(cardPort), x4_saveBanner(saveBanner),
|
2016-12-23 06:41:39 +00:00
|
|
|
x8_saveIcon0(saveIcon0), xc_saveIcon1(saveIcon1), x19d_doImportPersistent(importPersistent)
|
2016-12-19 19:20:30 +00:00
|
|
|
{
|
2016-12-20 21:51:50 +00:00
|
|
|
x100_mcFileInfos.reserve(2);
|
2016-12-23 06:41:39 +00:00
|
|
|
x100_mcFileInfos.emplace_back(0, SFileInfo(x0_cardPort, SaveFileNames[0]));
|
|
|
|
x100_mcFileInfos.emplace_back(0, SFileInfo(x0_cardPort, SaveFileNames[1]));
|
2016-12-19 19:20:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void CMemoryCardDriver::FinishedLoading()
|
|
|
|
{
|
|
|
|
x10_state = EState::TwentyFive;
|
|
|
|
x14_error = EError::Zero;
|
|
|
|
FinishedLoading2();
|
|
|
|
}
|
|
|
|
|
|
|
|
void CMemoryCardDriver::FinishedLoading2()
|
|
|
|
{
|
|
|
|
auto result = CMemoryCardSys::CardProbe(x0_cardPort);
|
|
|
|
switch (result.x0_error)
|
|
|
|
{
|
2016-12-20 21:51:50 +00:00
|
|
|
case ECardResult::CARD_RESULT_READY:
|
2016-12-19 19:20:30 +00:00
|
|
|
if (result.x8_sectorSize != 0x2000)
|
|
|
|
{
|
|
|
|
x10_state = EState::Twelve;
|
|
|
|
x14_error = EError::Seven;
|
|
|
|
return;
|
|
|
|
}
|
2016-12-23 06:41:39 +00:00
|
|
|
x10_state = EState::CardNeedsMount;
|
2016-12-19 19:20:30 +00:00
|
|
|
MountCard();
|
|
|
|
break;
|
2016-12-20 21:51:50 +00:00
|
|
|
case ECardResult::CARD_RESULT_BUSY:
|
2016-12-19 19:20:30 +00:00
|
|
|
break;
|
2016-12-20 21:51:50 +00:00
|
|
|
case ECardResult::CARD_RESULT_WRONGDEVICE:
|
2016-12-19 19:20:30 +00:00
|
|
|
x10_state = EState::Twelve;
|
|
|
|
x14_error = EError::Four;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
NoCardFound();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void CMemoryCardDriver::NoCardFound()
|
|
|
|
{
|
2016-12-23 06:41:39 +00:00
|
|
|
x10_state = EState::NoCard;
|
2016-12-19 19:20:30 +00:00
|
|
|
static_cast<CMain*>(g_Main)->SetCardInserted(false);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CMemoryCardDriver::MountCard()
|
|
|
|
{
|
2016-12-23 06:41:39 +00:00
|
|
|
x10_state = EState::CardMount;
|
2016-12-19 19:20:30 +00:00
|
|
|
x14_error = EError::Zero;
|
2016-12-20 21:51:50 +00:00
|
|
|
ECardResult result = CMemoryCardSys::MountCard(x0_cardPort);
|
|
|
|
if (result != ECardResult::CARD_RESULT_READY)
|
|
|
|
Case26(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CMemoryCardDriver::CheckCard()
|
|
|
|
{
|
|
|
|
ECardResult result = CMemoryCardSys::CheckCard(x0_cardPort);
|
|
|
|
if (result != ECardResult::CARD_RESULT_READY)
|
|
|
|
Case27(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
CGameState::GameFileStateInfo* CMemoryCardDriver::GetGameFileStateInfo(int idx)
|
|
|
|
{
|
|
|
|
SGameFileSlot* slot = xe4_fileSlots[idx].get();
|
|
|
|
if (!slot)
|
|
|
|
return nullptr;
|
|
|
|
return &slot->x944_fileInfo;
|
2016-12-19 19:20:30 +00:00
|
|
|
}
|
|
|
|
|
2016-12-20 21:51:50 +00:00
|
|
|
CMemoryCardDriver::SSaveHeader CMemoryCardDriver::LoadSaveHeader(CMemoryInStream& in)
|
|
|
|
{
|
|
|
|
SSaveHeader ret;
|
|
|
|
ret.x0_ = in.readUint32Big();
|
|
|
|
for (int i=0 ; i<3 ; ++i)
|
|
|
|
ret.x4_[i] = in.readBool();
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::unique_ptr<CMemoryCardDriver::SGameFileSlot> CMemoryCardDriver::LoadSaveFile(CMemoryInStream& in)
|
|
|
|
{
|
2016-12-20 22:09:02 +00:00
|
|
|
return std::make_unique<CMemoryCardDriver::SGameFileSlot>(in);
|
2016-12-20 21:51:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void CMemoryCardDriver::ReadFinished()
|
|
|
|
{
|
|
|
|
CMemoryCardSys::CARDStat stat = {};
|
|
|
|
SFileInfo& fileInfo = x100_mcFileInfos[x194_fileIdx].second;
|
|
|
|
if (CMemoryCardSys::GetStatus(x0_cardPort, fileInfo.GetFileNo(), stat) != ECardResult::CARD_RESULT_READY)
|
|
|
|
{
|
|
|
|
NoCardFound();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
x20_fileTime = stat.GetTime();
|
|
|
|
CMemoryInStream r(fileInfo.x34_saveData.data(), 3004);
|
|
|
|
SSaveHeader header = LoadSaveHeader(r);
|
|
|
|
r.readBytesToBuf(x30_systemData, 174);
|
|
|
|
|
|
|
|
for (int i=0 ; i<3 ; ++i)
|
|
|
|
xe4_fileSlots[i] = LoadSaveFile(r);
|
|
|
|
|
2016-12-23 06:41:39 +00:00
|
|
|
if (x19d_doImportPersistent)
|
|
|
|
ImportPersistentOptions();
|
2016-12-20 21:51:50 +00:00
|
|
|
}
|
|
|
|
|
2016-12-23 06:41:39 +00:00
|
|
|
void CMemoryCardDriver::ImportPersistentOptions()
|
2016-12-20 21:51:50 +00:00
|
|
|
{
|
|
|
|
CBitStreamReader r(x30_systemData, 174);
|
|
|
|
CPersistentOptions opts(r);
|
2016-12-23 06:41:39 +00:00
|
|
|
g_GameState->ImportPersistentOptions(opts);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CMemoryCardDriver::ExportPersistentOptions()
|
|
|
|
{
|
|
|
|
CBitStreamReader r(x30_systemData, 174);
|
|
|
|
CPersistentOptions opts(r);
|
|
|
|
g_GameState->ExportPersistentOptions(opts);
|
|
|
|
CBitStreamWriter w(x30_systemData, 174);
|
|
|
|
opts.PutTo(w);
|
2016-12-20 21:51:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void CMemoryCardDriver::DeleteFile()
|
|
|
|
{
|
|
|
|
x14_error = EError::Zero;
|
|
|
|
x10_state = EState::Thirty;
|
2016-12-23 06:41:39 +00:00
|
|
|
SFileInfo& fileInfo = x100_mcFileInfos[!bool(x194_fileIdx)].second;
|
2016-12-20 21:51:50 +00:00
|
|
|
ECardResult result = CMemoryCardSys::FastDeleteFile(x0_cardPort, fileInfo.GetFileNo());
|
|
|
|
if (result != ECardResult::CARD_RESULT_READY)
|
|
|
|
Case30(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CMemoryCardDriver::CheckCardCapacity()
|
|
|
|
{
|
|
|
|
if (x18_cardFreeBytes < 0x2000 || !x1c_cardFreeFiles)
|
|
|
|
x14_error = EError::Six;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CMemoryCardDriver::Case26(ECardResult result)
|
2016-12-19 19:20:30 +00:00
|
|
|
{
|
|
|
|
switch (result)
|
|
|
|
{
|
2016-12-20 21:51:50 +00:00
|
|
|
case ECardResult::CARD_RESULT_READY:
|
2016-12-23 06:41:39 +00:00
|
|
|
x10_state = EState::CardMountDone;
|
2016-12-19 19:20:30 +00:00
|
|
|
CheckCard();
|
|
|
|
break;
|
2016-12-20 21:51:50 +00:00
|
|
|
case ECardResult::CARD_RESULT_BROKEN:
|
2016-12-23 06:41:39 +00:00
|
|
|
x10_state = EState::CardMountDone;
|
2016-12-19 19:20:30 +00:00
|
|
|
x14_error = EError::One;
|
|
|
|
CheckCard();
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
HandleCardError(result, EState::Thirteen);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-12-20 21:51:50 +00:00
|
|
|
void CMemoryCardDriver::Case27(ECardResult result)
|
2016-12-19 19:20:30 +00:00
|
|
|
{
|
|
|
|
switch (result)
|
|
|
|
{
|
2016-12-20 21:51:50 +00:00
|
|
|
case ECardResult::CARD_RESULT_READY:
|
2016-12-23 06:41:39 +00:00
|
|
|
x10_state = EState::SelectCardFile;
|
2016-12-19 19:20:30 +00:00
|
|
|
if (!GetCardFreeBytes())
|
|
|
|
return;
|
2016-12-20 21:51:50 +00:00
|
|
|
if (CMemoryCardSys::GetSerialNo(x0_cardPort, x28_cardSerial) == ECardResult::CARD_RESULT_READY)
|
2016-12-19 19:20:30 +00:00
|
|
|
return;
|
|
|
|
NoCardFound();
|
|
|
|
break;
|
2016-12-20 21:51:50 +00:00
|
|
|
case ECardResult::CARD_RESULT_BROKEN:
|
2016-12-19 19:20:30 +00:00
|
|
|
x10_state = EState::Fourteen;
|
|
|
|
x14_error = EError::One;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
HandleCardError(result, EState::Fourteen);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-12-20 21:51:50 +00:00
|
|
|
void CMemoryCardDriver::Case28(ECardResult result)
|
|
|
|
{
|
|
|
|
if (result == ECardResult::CARD_RESULT_READY)
|
|
|
|
{
|
|
|
|
x100_mcFileInfos[x194_fileIdx].first = 1;
|
2016-12-23 06:41:39 +00:00
|
|
|
if (x100_mcFileInfos[!bool(x194_fileIdx)].first == 3)
|
2016-12-20 21:51:50 +00:00
|
|
|
{
|
|
|
|
x10_state = EState::Seventeen;
|
|
|
|
GoTo28();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2016-12-23 06:41:39 +00:00
|
|
|
x10_state = EState::SelectCardFile;
|
2016-12-20 21:51:50 +00:00
|
|
|
if (!GetCardFreeBytes())
|
|
|
|
return;
|
|
|
|
GoTo17();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
HandleCardError(result, EState::Fifteen);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CMemoryCardDriver::Case29(ECardResult result)
|
|
|
|
{
|
|
|
|
if (result == ECardResult::CARD_RESULT_READY)
|
|
|
|
{
|
|
|
|
auto& fileInfo = x100_mcFileInfos[x194_fileIdx];
|
|
|
|
ECardResult readRes = fileInfo.second.TryFileRead();
|
|
|
|
if (fileInfo.second.Close() != ECardResult::CARD_RESULT_READY)
|
|
|
|
{
|
|
|
|
NoCardFound();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2016-12-23 06:41:39 +00:00
|
|
|
u32 fileIdx = !bool(x194_fileIdx);
|
2016-12-20 21:51:50 +00:00
|
|
|
if (readRes == ECardResult::CARD_RESULT_READY)
|
|
|
|
{
|
2016-12-23 06:41:39 +00:00
|
|
|
x10_state = EState::Ready;
|
2016-12-20 21:51:50 +00:00
|
|
|
ReadFinished();
|
|
|
|
u32 fileId = x100_mcFileInfos[fileIdx].first;
|
|
|
|
if (fileId == 1)
|
|
|
|
CheckCardCapacity();
|
|
|
|
else
|
|
|
|
DeleteFile();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (readRes == ECardResult::CARD_RESULT_CRC_MISMATCH)
|
|
|
|
{
|
|
|
|
x100_mcFileInfos[x194_fileIdx].first = 3;
|
|
|
|
if (x100_mcFileInfos[fileIdx].first == 2)
|
|
|
|
{
|
2016-12-23 06:41:39 +00:00
|
|
|
x10_state = EState::SelectCardFile;
|
2016-12-20 21:51:50 +00:00
|
|
|
GoTo17();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
x10_state = EState::Seventeen;
|
|
|
|
x14_error = EError::Nine;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
HandleCardError(result, EState::Seventeen);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CMemoryCardDriver::Case30(ECardResult result)
|
|
|
|
{
|
2016-12-23 06:41:39 +00:00
|
|
|
if (result == ECardResult::CARD_RESULT_READY)
|
|
|
|
{
|
|
|
|
x10_state = EState::Ready;
|
|
|
|
if (GetCardFreeBytes())
|
|
|
|
CheckCardCapacity();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
HandleCardError(result, EState::Sixteen);
|
2016-12-20 21:51:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void CMemoryCardDriver::Case31(ECardResult result)
|
|
|
|
{
|
2016-12-23 06:41:39 +00:00
|
|
|
if (result == ECardResult::CARD_RESULT_READY)
|
|
|
|
{
|
|
|
|
x10_state = EState::WillWrite;
|
|
|
|
GoTo32();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
HandleCardError(result, EState::Eighteen);
|
2016-12-20 21:51:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void CMemoryCardDriver::Case32(ECardResult result)
|
|
|
|
{
|
2016-12-23 06:41:39 +00:00
|
|
|
if (result == ECardResult::CARD_RESULT_READY)
|
|
|
|
{
|
|
|
|
ECardResult xferResult = x198_fileInfo->PumpCardTransfer();
|
|
|
|
if (xferResult == ECardResult::CARD_RESULT_READY)
|
|
|
|
{
|
|
|
|
x10_state = EState::Ready;
|
|
|
|
if (x198_fileInfo->Close() == ECardResult::CARD_RESULT_READY)
|
|
|
|
return;
|
|
|
|
NoCardFound();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (xferResult == ECardResult::CARD_RESULT_BUSY)
|
|
|
|
return;
|
|
|
|
if (xferResult == ECardResult::CARD_RESULT_IOERROR)
|
|
|
|
{
|
|
|
|
x10_state = EState::Nineteen;
|
|
|
|
x14_error = EError::Three;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
NoCardFound();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
HandleCardError(result, EState::Nineteen);
|
2016-12-20 21:51:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void CMemoryCardDriver::Case33(ECardResult result)
|
|
|
|
{
|
2016-12-23 06:41:39 +00:00
|
|
|
if (result == ECardResult::CARD_RESULT_READY)
|
|
|
|
{
|
|
|
|
x10_state = EState::Nine;
|
|
|
|
GoTo34();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
HandleCardError(result, EState::Twenty);
|
2016-12-20 21:51:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void CMemoryCardDriver::Case34(ECardResult result)
|
|
|
|
{
|
2016-12-23 06:41:39 +00:00
|
|
|
if (result == ECardResult::CARD_RESULT_READY)
|
|
|
|
{
|
|
|
|
ECardResult xferResult = x198_fileInfo->PumpCardTransfer();
|
|
|
|
if (xferResult == ECardResult::CARD_RESULT_READY)
|
|
|
|
{
|
|
|
|
x10_state = EState::Ten;
|
|
|
|
if (x198_fileInfo->Close() != ECardResult::CARD_RESULT_READY)
|
|
|
|
{
|
|
|
|
NoCardFound();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
GoTo35();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (xferResult == ECardResult::CARD_RESULT_BUSY)
|
|
|
|
return;
|
|
|
|
if (xferResult == ECardResult::CARD_RESULT_IOERROR)
|
|
|
|
{
|
|
|
|
x10_state = EState::TwentyOne;
|
|
|
|
x14_error = EError::Three;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
NoCardFound();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
HandleCardError(result, EState::TwentyOne);
|
2016-12-20 21:51:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void CMemoryCardDriver::Case35(ECardResult result)
|
|
|
|
{
|
2016-12-23 06:41:39 +00:00
|
|
|
if (result == ECardResult::CARD_RESULT_READY)
|
|
|
|
{
|
|
|
|
x10_state = EState::Eleven;
|
|
|
|
if (GetCardFreeBytes())
|
|
|
|
GoTo36();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
HandleCardError(result, EState::TwentyTwo);
|
2016-12-20 21:51:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void CMemoryCardDriver::Case36(ECardResult result)
|
|
|
|
{
|
2016-12-23 06:41:39 +00:00
|
|
|
if (result == ECardResult::CARD_RESULT_READY)
|
|
|
|
{
|
|
|
|
x10_state = EState::RuntimeBackup;
|
|
|
|
WriteBackupBuf();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
HandleCardError(result, EState::TwentyThree);
|
2016-12-20 21:51:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void CMemoryCardDriver::Case37(ECardResult result)
|
|
|
|
{
|
2016-12-23 06:41:39 +00:00
|
|
|
if (result == ECardResult::CARD_RESULT_READY)
|
|
|
|
x10_state = EState::CardFormatted;
|
|
|
|
else if (result == ECardResult::CARD_RESULT_BROKEN)
|
|
|
|
{
|
|
|
|
x10_state = EState::CardFormatBroken;
|
|
|
|
x14_error = EError::Three;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
HandleCardError(result, EState::CardFormatBroken);
|
2016-12-20 21:51:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void CMemoryCardDriver::GoTo17()
|
|
|
|
{
|
2016-12-23 06:41:39 +00:00
|
|
|
x14_error = EError::Zero;
|
|
|
|
for (std::pair<u32, SFileInfo>& info : x100_mcFileInfos)
|
|
|
|
{
|
|
|
|
if (info.first == 0)
|
|
|
|
{
|
|
|
|
ECardResult result = info.second.Open();
|
|
|
|
if (result == ECardResult::CARD_RESULT_NOFILE)
|
|
|
|
{
|
|
|
|
info.first = 1;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
else if (result == ECardResult::CARD_RESULT_READY)
|
|
|
|
{
|
|
|
|
CMemoryCardSys::CARDStat stat = {};
|
|
|
|
if (CMemoryCardSys::GetStatus(x0_cardPort, info.second.GetFileNo(), stat) ==
|
|
|
|
ECardResult::CARD_RESULT_READY)
|
|
|
|
{
|
|
|
|
u32 comment = stat.GetCommentAddr();
|
|
|
|
if (comment == -1)
|
|
|
|
info.first = 3;
|
|
|
|
else
|
|
|
|
info.first = 2;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
NoCardFound();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (info.second.Close() == ECardResult::CARD_RESULT_NOCARD)
|
|
|
|
{
|
|
|
|
NoCardFound();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
NoCardFound();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-12-20 21:51:50 +00:00
|
|
|
|
2016-12-23 06:41:39 +00:00
|
|
|
if (x100_mcFileInfos[0].first == 2)
|
|
|
|
{
|
|
|
|
if (x100_mcFileInfos[1].first == 2)
|
|
|
|
{
|
|
|
|
CMemoryCardSys::CARDStat stat = {};
|
|
|
|
if (CMemoryCardSys::GetStatus(x0_cardPort, x100_mcFileInfos[0].second.GetFileNo(), stat) ==
|
|
|
|
ECardResult::CARD_RESULT_READY)
|
|
|
|
{
|
|
|
|
u32 timeA = stat.GetTime();
|
|
|
|
if (CMemoryCardSys::GetStatus(x0_cardPort, x100_mcFileInfos[1].second.GetFileNo(), stat) ==
|
|
|
|
ECardResult::CARD_RESULT_READY)
|
|
|
|
{
|
|
|
|
u32 timeB = stat.GetTime();
|
|
|
|
if (timeA > timeB)
|
|
|
|
x194_fileIdx = 0;
|
|
|
|
else
|
|
|
|
x194_fileIdx = 1;
|
|
|
|
GoTo29();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
NoCardFound();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
NoCardFound();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
x194_fileIdx = 0;
|
|
|
|
GoTo29();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (x100_mcFileInfos[1].first == 2)
|
|
|
|
{
|
|
|
|
x194_fileIdx = 1;
|
|
|
|
GoTo29();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (x100_mcFileInfos[0].first == 3 || x100_mcFileInfos[1].first == 3)
|
|
|
|
{
|
|
|
|
x10_state = EState::Seventeen;
|
|
|
|
x14_error = EError::Nine;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
x10_state = EState::Seventeen;
|
|
|
|
x14_error = EError::Eight;
|
|
|
|
}
|
2016-12-20 21:51:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void CMemoryCardDriver::GoTo28()
|
|
|
|
{
|
2016-12-23 06:41:39 +00:00
|
|
|
x14_error = EError::Zero;
|
|
|
|
x10_state = EState::TwentyEight;
|
|
|
|
int idx = 0;
|
|
|
|
for (std::pair<u32, SFileInfo>& info : x100_mcFileInfos)
|
|
|
|
{
|
|
|
|
if (info.first == 3)
|
|
|
|
{
|
|
|
|
x194_fileIdx = idx;
|
|
|
|
ECardResult result = CMemoryCardSys::FastDeleteFile(x0_cardPort, info.second.GetFileNo());
|
|
|
|
if (result != ECardResult::CARD_RESULT_READY)
|
|
|
|
{
|
|
|
|
Case28(result);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
++idx;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void CMemoryCardDriver::GoTo29()
|
|
|
|
{
|
|
|
|
x14_error = EError::Zero;
|
|
|
|
x10_state = EState::TwentyNine;
|
|
|
|
ECardResult result = x100_mcFileInfos[x194_fileIdx].second.Open();
|
|
|
|
if (result != ECardResult::CARD_RESULT_READY)
|
|
|
|
{
|
|
|
|
Case29(result);
|
|
|
|
return;
|
|
|
|
}
|
2016-12-20 21:51:50 +00:00
|
|
|
|
2016-12-23 06:41:39 +00:00
|
|
|
result = x100_mcFileInfos[x194_fileIdx].second.StartRead();
|
|
|
|
if (result != ECardResult::CARD_RESULT_READY)
|
|
|
|
Case29(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CMemoryCardDriver::GoTo32()
|
|
|
|
{
|
|
|
|
x14_error = EError::Zero;
|
|
|
|
x10_state = EState::Write;
|
|
|
|
ECardResult result = x198_fileInfo->Write();
|
|
|
|
if (result != ECardResult::CARD_RESULT_READY)
|
|
|
|
Case32(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CMemoryCardDriver::GoTo33()
|
|
|
|
{
|
|
|
|
x14_error = EError::Zero;
|
|
|
|
x10_state = EState::ThirtyThree;
|
|
|
|
ClearFileInfo();
|
|
|
|
if (x18_cardFreeBytes < 8192 || !x1c_cardFreeFiles)
|
|
|
|
{
|
|
|
|
x10_state = EState::Twenty;
|
|
|
|
x14_error = EError::Five;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
x198_fileInfo = std::make_unique<CMemoryCardSys::CCardFileInfo>(x0_cardPort, SaveFileNames[x194_fileIdx]);
|
|
|
|
InitializeFileInfo();
|
|
|
|
ECardResult result = x198_fileInfo->CreateFile();
|
|
|
|
if (result != ECardResult::CARD_RESULT_READY)
|
|
|
|
Case33(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CMemoryCardDriver::GoTo34()
|
|
|
|
{
|
|
|
|
x14_error = EError::Zero;
|
|
|
|
x10_state = EState::ThirtyFour;
|
|
|
|
ECardResult result = x198_fileInfo->Write();
|
|
|
|
if (result != ECardResult::CARD_RESULT_READY)
|
|
|
|
Case34(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CMemoryCardDriver::GoTo35()
|
|
|
|
{
|
|
|
|
x14_error = EError::Zero;
|
|
|
|
x10_state = EState::ThirtyFive;
|
|
|
|
ECardResult result = CMemoryCardSys::DeleteFile(x0_cardPort,
|
|
|
|
SaveFileNames[!bool(x194_fileIdx)]);
|
|
|
|
if (result != ECardResult::CARD_RESULT_READY)
|
|
|
|
Case35(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CMemoryCardDriver::GoTo36()
|
|
|
|
{
|
|
|
|
if (x194_fileIdx == 1)
|
|
|
|
{
|
|
|
|
x14_error = EError::Zero;
|
|
|
|
x10_state = EState::ThirtySix;
|
|
|
|
ECardResult result = CMemoryCardSys::Rename(x0_cardPort,
|
|
|
|
SaveFileNames[x194_fileIdx],
|
|
|
|
SaveFileNames[!bool(x194_fileIdx)]);
|
|
|
|
if (result != ECardResult::CARD_RESULT_READY)
|
|
|
|
Case36(result);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
x10_state = EState::RuntimeBackup;
|
|
|
|
WriteBackupBuf();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void CMemoryCardDriver::GoTo37()
|
|
|
|
{
|
|
|
|
x14_error = EError::Zero;
|
|
|
|
x10_state = EState::CardFormat;
|
|
|
|
ECardResult result = CMemoryCardSys::FormatCard(x0_cardPort);
|
|
|
|
if (result != ECardResult::CARD_RESULT_READY)
|
|
|
|
Case37(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CMemoryCardDriver::InitializeFileInfo()
|
|
|
|
{
|
|
|
|
ExportPersistentOptions();
|
|
|
|
/* TODO: Finish */
|
|
|
|
}
|
|
|
|
|
|
|
|
void CMemoryCardDriver::WriteBackupBuf()
|
|
|
|
{
|
|
|
|
g_GameState->WriteBackupBuf();
|
|
|
|
g_GameState->SetCardSerial(x28_cardSerial);
|
2016-12-20 21:51:50 +00:00
|
|
|
}
|
|
|
|
|
2016-12-19 19:20:30 +00:00
|
|
|
bool CMemoryCardDriver::GetCardFreeBytes()
|
|
|
|
{
|
2016-12-20 21:51:50 +00:00
|
|
|
ECardResult result = CMemoryCardSys::GetNumFreeBytes(x0_cardPort,
|
|
|
|
x18_cardFreeBytes,
|
|
|
|
x1c_cardFreeFiles);
|
|
|
|
if (result == ECardResult::CARD_RESULT_READY)
|
2016-12-19 19:20:30 +00:00
|
|
|
return true;
|
|
|
|
NoCardFound();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2016-12-20 21:51:50 +00:00
|
|
|
void CMemoryCardDriver::HandleCardError(ECardResult result, EState state)
|
2016-12-19 19:20:30 +00:00
|
|
|
{
|
|
|
|
switch (result)
|
|
|
|
{
|
2016-12-20 21:51:50 +00:00
|
|
|
case ECardResult::CARD_RESULT_WRONGDEVICE:
|
2016-12-19 19:20:30 +00:00
|
|
|
x10_state = state;
|
|
|
|
x14_error = EError::Four;
|
|
|
|
break;
|
2016-12-20 21:51:50 +00:00
|
|
|
case ECardResult::CARD_RESULT_NOCARD:
|
2016-12-19 19:20:30 +00:00
|
|
|
NoCardFound();
|
|
|
|
break;
|
2016-12-20 21:51:50 +00:00
|
|
|
case ECardResult::CARD_RESULT_IOERROR:
|
2016-12-19 19:20:30 +00:00
|
|
|
x10_state = state;
|
|
|
|
x14_error = EError::Three;
|
2016-12-20 21:51:50 +00:00
|
|
|
case ECardResult::CARD_RESULT_ENCODING:
|
2016-12-19 19:20:30 +00:00
|
|
|
x10_state = state;
|
|
|
|
x14_error = EError::Two;
|
|
|
|
break;
|
|
|
|
default: break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void CMemoryCardDriver::Update()
|
|
|
|
{
|
2016-12-20 21:51:50 +00:00
|
|
|
CMemoryCardSys::CardProbeResults result = CMemoryCardSys::CardProbe(x0_cardPort);
|
2016-12-19 19:20:30 +00:00
|
|
|
|
2016-12-20 21:51:50 +00:00
|
|
|
if (result.x0_error == ECardResult::CARD_RESULT_NOCARD)
|
2016-12-19 19:20:30 +00:00
|
|
|
{
|
2016-12-23 06:41:39 +00:00
|
|
|
if (x10_state != EState::NoCard)
|
2016-12-19 19:20:30 +00:00
|
|
|
NoCardFound();
|
|
|
|
static_cast<CMain*>(g_Main)->SetCardInserted(false);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2016-12-20 21:51:50 +00:00
|
|
|
if (x10_state == EState::TwentyFive)
|
2016-12-19 19:20:30 +00:00
|
|
|
{
|
2016-12-20 21:51:50 +00:00
|
|
|
FinishedLoading2();
|
|
|
|
static_cast<CMain*>(g_Main)->SetCardInserted(false);
|
|
|
|
return;
|
2016-12-19 19:20:30 +00:00
|
|
|
}
|
2016-12-20 21:51:50 +00:00
|
|
|
|
|
|
|
|
|
|
|
ECardResult resultCode = g_MemoryCardSys->GetResultCode(x0_cardPort);
|
|
|
|
bool cardInserted = false;
|
|
|
|
|
|
|
|
if (InCardInsertedRange(x10_state))
|
|
|
|
{
|
|
|
|
cardInserted = true;
|
|
|
|
|
|
|
|
switch (x10_state)
|
|
|
|
{
|
2016-12-23 06:41:39 +00:00
|
|
|
case EState::CardMount:
|
2016-12-20 21:51:50 +00:00
|
|
|
Case26(resultCode);
|
|
|
|
break;
|
|
|
|
case EState::TwentySeven:
|
|
|
|
Case27(resultCode);
|
|
|
|
break;
|
|
|
|
case EState::TwentyEight:
|
|
|
|
Case28(resultCode);
|
|
|
|
break;
|
|
|
|
case EState::TwentyNine:
|
|
|
|
Case29(resultCode);
|
|
|
|
break;
|
|
|
|
case EState::Thirty:
|
|
|
|
Case30(resultCode);
|
|
|
|
break;
|
|
|
|
case EState::ThirtyOne:
|
|
|
|
Case31(resultCode);
|
|
|
|
break;
|
2016-12-23 06:41:39 +00:00
|
|
|
case EState::Write:
|
2016-12-20 21:51:50 +00:00
|
|
|
Case32(resultCode);
|
|
|
|
break;
|
|
|
|
case EState::ThirtyThree:
|
|
|
|
Case33(resultCode);
|
|
|
|
break;
|
|
|
|
case EState::ThirtyFour:
|
|
|
|
Case34(resultCode);
|
|
|
|
break;
|
|
|
|
case EState::ThirtyFive:
|
|
|
|
Case35(resultCode);
|
|
|
|
break;
|
|
|
|
case EState::ThirtySix:
|
|
|
|
Case36(resultCode);
|
|
|
|
break;
|
2016-12-23 06:41:39 +00:00
|
|
|
case EState::CardFormat:
|
2016-12-20 21:51:50 +00:00
|
|
|
Case37(resultCode);
|
|
|
|
break;
|
|
|
|
default: break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static_cast<CMain*>(g_Main)->SetCardInserted(cardInserted);
|
2016-12-19 19:20:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|