2
0
mirror of https://github.com/AxioDL/metaforce.git synced 2025-05-17 05:11:21 +00:00

Additional memory card imps

This commit is contained in:
Jack Andersen 2016-12-23 14:45:51 -10:00
parent 513d283bee
commit a7322e8916
8 changed files with 234 additions and 54 deletions

View File

@ -39,7 +39,8 @@ public:
static OSTime ToWiiTime(std::chrono::system_clock::time_point time); static OSTime ToWiiTime(std::chrono::system_clock::time_point time);
static std::chrono::system_clock::time_point FromWiiTime(OSTime wiiTime); static std::chrono::system_clock::time_point FromWiiTime(OSTime wiiTime);
static OSCalendarTime ToCalendarTime(OSTime time); static OSCalendarTime ToCalendarTime(OSTime time) { return ToCalendarTime(FromWiiTime(time)); }
static OSCalendarTime ToCalendarTime(std::chrono::system_clock::time_point time);
}; };
} }

View File

@ -24,45 +24,88 @@ const char* CBasics::Stringize(const char* fmt, ...)
const u64 CBasics::SECONDS_TO_2000 = 946684800LL; const u64 CBasics::SECONDS_TO_2000 = 946684800LL;
const u64 CBasics::TICKS_PER_SECOND = 60750000LL; const u64 CBasics::TICKS_PER_SECOND = 60750000LL;
#ifndef _WIN32
static struct tm* localtime_r(const time_t& time, struct tm& timeSt, long& gmtOff)
{
auto ret = localtime_r(&time, &timeSt);
if (!ret)
return nullptr;
gmtOff = ret->tm_gmtoff;
return ret;
}
#else
static struct tm* localtime_r(const time_t& time, struct tm& timeSt, long& gmtOff)
{
struct tm _gmSt;
auto reta = localtime_s(&timeSt, &time);
auto retb = gmtime_s(&_gmSt, &time);
if (reta || retb)
return nullptr;
gmtOff = mktime(&timeSt) - mktime(&_gmSt);
return &timeSt;
}
#endif
OSTime CBasics::ToWiiTime(std::chrono::system_clock::time_point time) OSTime CBasics::ToWiiTime(std::chrono::system_clock::time_point time)
{ {
time_t sysTime, tzDiff; auto sec = std::chrono::time_point_cast<std::chrono::seconds>(time);
struct tm* gmTime; auto us = std::chrono::duration_cast<std::chrono::microseconds>((time - sec)).count();
time_t sysTime = std::chrono::system_clock::to_time_t(sec);
sysTime = std::chrono::system_clock::to_time_t(time); struct tm _timeSt;
// Account for DST where needed long gmtOff;
gmTime = localtime(&sysTime); struct tm* timeSt = localtime_r(sysTime, _timeSt, gmtOff);
if (!gmTime) if (!timeSt)
return 0; return 0;
// Lazy way to get local time in sec /* Returning local */
gmTime = gmtime(&sysTime); return OSTime(TICKS_PER_SECOND * ((sysTime + gmtOff) - SECONDS_TO_2000) +
tzDiff = sysTime - mktime(gmTime); us * TICKS_PER_SECOND / 1000000);
return OSTime(TICKS_PER_SECOND * ((sysTime + tzDiff) - SECONDS_TO_2000));
} }
std::chrono::system_clock::time_point CBasics::FromWiiTime(OSTime wiiTime) std::chrono::system_clock::time_point CBasics::FromWiiTime(OSTime wiiTime)
{ {
time_t time = SECONDS_TO_2000 + wiiTime / TICKS_PER_SECOND; auto div = std::lldiv(SECONDS_TO_2000 + wiiTime, TICKS_PER_SECOND);
time_t time = time_t(div.quot);
time_t sysTime = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now()); time_t sysTime = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
// Account for DST where needed struct tm _timeSt;
struct tm* gmTime = localtime(&sysTime); long gmtOff;
if (!gmTime) struct tm* timeSt = localtime_r(sysTime, _timeSt, gmtOff);
if (!timeSt)
return std::chrono::system_clock::from_time_t(0); return std::chrono::system_clock::from_time_t(0);
// Lazy way to get local time in sec /* Returning GMT */
gmTime = gmtime(&sysTime); return std::chrono::system_clock::from_time_t(time - gmtOff) +
time_t tzDiff = sysTime - mktime(gmTime); std::chrono::microseconds(div.rem * 1000000 / TICKS_PER_SECOND);
return std::chrono::system_clock::from_time_t(time - tzDiff);
} }
OSCalendarTime CBasics::ToCalendarTime(OSTime time) OSCalendarTime CBasics::ToCalendarTime(std::chrono::system_clock::time_point time)
{ {
OSCalendarTime ret = {}; OSCalendarTime ret;
/* TODO: Finsh */
auto sec = std::chrono::time_point_cast<std::chrono::seconds>(time);
auto us = std::chrono::duration_cast<std::chrono::microseconds>((time - sec)).count();
time_t sysTime = std::chrono::system_clock::to_time_t(sec);
struct tm _timeSt;
long gmtOff;
struct tm* timeSt = localtime_r(sysTime, _timeSt, gmtOff);
if (!timeSt)
return {};
ret.x0_sec = timeSt->tm_sec;
ret.x4_min = timeSt->tm_min;
ret.x8_hour = timeSt->tm_hour;
ret.xc_mday = timeSt->tm_mday;
ret.x10_mon = timeSt->tm_mon;
ret.x14_year = timeSt->tm_year + 1900;
ret.x18_wday = timeSt->tm_wday;
ret.x1c_yday = timeSt->tm_yday;
auto div = std::ldiv(us, 1000);
ret.x20_msec = div.quot;
ret.x24_usec = div.rem;
return ret; return ret;
} }

View File

@ -189,9 +189,9 @@ void CMemoryCardSys::CCardFileInfo::BuildCardBuffer()
CMemoryOutStream w(x104_cardBuffer.data(), x104_cardBuffer.size()); CMemoryOutStream w(x104_cardBuffer.data(), x104_cardBuffer.size());
w.writeUint32Big(0); w.writeUint32Big(0);
char name[64]; char comment[64];
strncpy(name, x28_name2.data(), 64); strncpy(comment, x28_comment.data(), 64);
w.writeBytes(name, 64); w.writeBytes(comment, 64);
WriteBannerData(w); WriteBannerData(w);
WriteIconData(w); WriteIconData(w);
memmove(x104_cardBuffer.data() + bannerSz, xf4_saveBuffer.data(), xf4_saveBuffer.size()); memmove(x104_cardBuffer.data() + bannerSz, xf4_saveBuffer.data(), xf4_saveBuffer.size());

View File

@ -172,8 +172,8 @@ public:
EStatus x0_status = EStatus::Standby; EStatus x0_status = EStatus::Standby;
CARDFileInfo x4_info; CARDFileInfo x4_info;
std::string x18_name; std::string x18_fileName;
std::string x28_name2; std::string x28_comment;
ResId x3c_bannerTex = -1; ResId x3c_bannerTex = -1;
std::experimental::optional<TLockedToken<CTexture>> x40_bannerTok; std::experimental::optional<TLockedToken<CTexture>> x40_bannerTok;
rstl::reserved_vector<Icon, 8> x50_iconToks; rstl::reserved_vector<Icon, 8> x50_iconToks;
@ -183,7 +183,7 @@ public:
CVParamTransfer m_texParam = {new TObjOwnerParam<u32>(SBIG('OTEX'))}; CVParamTransfer m_texParam = {new TObjOwnerParam<u32>(SBIG('OTEX'))};
CCardFileInfo(EMemoryCardPort port, const std::string& name) CCardFileInfo(EMemoryCardPort port, const std::string& name)
: x4_info(port), x18_name(name) {} : x4_info(port), x18_fileName(name) {}
void LockBannerToken(ResId bannerTxtr, CSimplePool& sp); void LockBannerToken(ResId bannerTxtr, CSimplePool& sp);
void LockIconToken(ResId iconTxtr, u32 speed, CSimplePool& sp); void LockIconToken(ResId iconTxtr, u32 speed, CSimplePool& sp);
@ -195,11 +195,18 @@ public:
void BuildCardBuffer(); void BuildCardBuffer();
void WriteBannerData(CMemoryOutStream& out) const; void WriteBannerData(CMemoryOutStream& out) const;
void WriteIconData(CMemoryOutStream& out) const; void WriteIconData(CMemoryOutStream& out) const;
void SetComment(const std::string& c) { x28_comment = c; }
ECardResult PumpCardTransfer(); ECardResult PumpCardTransfer();
ECardResult GetStatus(CARDStat& stat) const; ECardResult GetStatus(CARDStat& stat) const;
ECardResult CreateFile(); ECardResult CreateFile();
ECardResult Write(); ECardResult Write();
ECardResult Close(); ECardResult Close();
CMemoryOutStream BeginMemoryOut(u32 sz)
{
xf4_saveBuffer.resize(sz);
return CMemoryOutStream(xf4_saveBuffer.data(), sz);
}
}; };
static CardProbeResults CardProbe(EMemoryCardPort port); static CardProbeResults CardProbe(EMemoryCardPort port);

View File

@ -226,9 +226,9 @@ CGameState::GameFileStateInfo* CMemoryCardDriver::GetGameFileStateInfo(int idx)
CMemoryCardDriver::SSaveHeader CMemoryCardDriver::LoadSaveHeader(CMemoryInStream& in) CMemoryCardDriver::SSaveHeader CMemoryCardDriver::LoadSaveHeader(CMemoryInStream& in)
{ {
SSaveHeader ret; SSaveHeader ret;
ret.x0_ = in.readUint32Big(); ret.x0_version = in.readUint32Big();
for (int i=0 ; i<3 ; ++i) for (int i=0 ; i<3 ; ++i)
ret.x4_[i] = in.readBool(); ret.x4_savePresent[i] = in.readBool();
return ret; return ret;
} }
@ -655,10 +655,28 @@ void CMemoryCardDriver::GoTo29()
Case29(result); Case29(result);
} }
void CMemoryCardDriver::GoTo31()
{
x14_error = EError::Zero;
x10_state = EState::ThirtyOne;
if (x18_cardFreeBytes < 8192 || x1c_cardFreeFiles < 2)
{
x10_state = EState::Eighteen;
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)
Case31(result);
}
void CMemoryCardDriver::GoTo32() void CMemoryCardDriver::GoTo32()
{ {
x14_error = EError::Zero; x14_error = EError::Zero;
x10_state = EState::Write; x10_state = EState::ThirtyTwo;
ECardResult result = x198_fileInfo->Write(); ECardResult result = x198_fileInfo->Write();
if (result != ECardResult::CARD_RESULT_READY) if (result != ECardResult::CARD_RESULT_READY)
Case32(result); Case32(result);
@ -667,7 +685,7 @@ void CMemoryCardDriver::GoTo32()
void CMemoryCardDriver::GoTo33() void CMemoryCardDriver::GoTo33()
{ {
x14_error = EError::Zero; x14_error = EError::Zero;
x10_state = EState::ThirtyThree; x10_state = EState::FileBuild;
ClearFileInfo(); ClearFileInfo();
if (x18_cardFreeBytes < 8192 || !x1c_cardFreeFiles) if (x18_cardFreeBytes < 8192 || !x1c_cardFreeFiles)
{ {
@ -686,7 +704,7 @@ void CMemoryCardDriver::GoTo33()
void CMemoryCardDriver::GoTo34() void CMemoryCardDriver::GoTo34()
{ {
x14_error = EError::Zero; x14_error = EError::Zero;
x10_state = EState::ThirtyFour; x10_state = EState::FileWrite;
ECardResult result = x198_fileInfo->Write(); ECardResult result = x198_fileInfo->Write();
if (result != ECardResult::CARD_RESULT_READY) if (result != ECardResult::CARD_RESULT_READY)
Case34(result); Case34(result);
@ -707,7 +725,7 @@ void CMemoryCardDriver::GoTo36()
if (x194_fileIdx == 1) if (x194_fileIdx == 1)
{ {
x14_error = EError::Zero; x14_error = EError::Zero;
x10_state = EState::ThirtySix; x10_state = EState::FileRename;
ECardResult result = CMemoryCardSys::Rename(x0_cardPort, ECardResult result = CMemoryCardSys::Rename(x0_cardPort,
SaveFileNames[x194_fileIdx], SaveFileNames[x194_fileIdx],
SaveFileNames[!bool(x194_fileIdx)]); SaveFileNames[!bool(x194_fileIdx)]);
@ -733,7 +751,31 @@ void CMemoryCardDriver::GoTo37()
void CMemoryCardDriver::InitializeFileInfo() void CMemoryCardDriver::InitializeFileInfo()
{ {
ExportPersistentOptions(); ExportPersistentOptions();
/* TODO: Finish */
OSCalendarTime time = CBasics::ToCalendarTime(std::chrono::system_clock::now());
char timeString[32];
snprintf(timeString, 32, "%02d.%02d.%02d %02d:%02d",
time.x10_mon + 1, time.xc_mday, time.x14_year % 100,
time.x8_hour, time.x4_min);
std::string comment("Metroid Prime ");
comment += timeString;
x198_fileInfo->SetComment(comment);
x198_fileInfo->LockBannerToken(x4_saveBanner, *g_SimplePool);
x198_fileInfo->LockIconToken(x8_saveIcon0, 2, *g_SimplePool);
CMemoryOutStream w = x198_fileInfo->BeginMemoryOut(3004);
SSaveHeader header;
for (int i=0 ; i<3 ; ++i)
header.x4_savePresent[i] = xe4_fileSlots[i].operator bool();
header.DoPut(w);
w.writeBytes(x30_systemData, 174);
for (int i=0 ; i<3 ; ++i)
if (xe4_fileSlots[i])
xe4_fileSlots[i]->DoPut(w);
} }
void CMemoryCardDriver::WriteBackupBuf() void CMemoryCardDriver::WriteBackupBuf()
@ -822,19 +864,19 @@ void CMemoryCardDriver::Update()
case EState::ThirtyOne: case EState::ThirtyOne:
Case31(resultCode); Case31(resultCode);
break; break;
case EState::Write: case EState::ThirtyTwo:
Case32(resultCode); Case32(resultCode);
break; break;
case EState::ThirtyThree: case EState::FileBuild:
Case33(resultCode); Case33(resultCode);
break; break;
case EState::ThirtyFour: case EState::FileWrite:
Case34(resultCode); Case34(resultCode);
break; break;
case EState::ThirtyFive: case EState::ThirtyFive:
Case35(resultCode); Case35(resultCode);
break; break;
case EState::ThirtySix: case EState::FileRename:
Case36(resultCode); Case36(resultCode);
break; break;
case EState::CardFormat: case EState::CardFormat:

View File

@ -47,11 +47,11 @@ public:
TwentyNine = 29, TwentyNine = 29,
Thirty = 30, Thirty = 30,
ThirtyOne = 31, ThirtyOne = 31,
Write = 32, ThirtyTwo = 32,
ThirtyThree = 33, FileBuild = 33,
ThirtyFour = 34, FileWrite = 34,
ThirtyFive = 35, ThirtyFive = 35,
ThirtySix = 36, FileRename = 36,
CardFormat = 37 CardFormat = 37
}; };
@ -98,8 +98,14 @@ private:
struct SSaveHeader struct SSaveHeader
{ {
u32 x0_; u32 x0_version = 0;
u32 x4_[3]; bool x4_savePresent[3];
void DoPut(CMemoryOutStream& out) const
{
out.writeUint32Big(x0_version);
for (int i=0 ; i<3 ; ++i)
out.writeBool(x4_savePresent[i]);
}
}; };
struct SGameFileSlot struct SGameFileSlot
@ -109,6 +115,10 @@ private:
SGameFileSlot(); SGameFileSlot();
SGameFileSlot(CMemoryInStream& in); SGameFileSlot(CMemoryInStream& in);
void InitializeFromGameState(); void InitializeFromGameState();
void DoPut(CMemoryOutStream& w) const
{
w.writeBytes(x0_saveBuffer, 940);
}
}; };
CMemoryCardSys::EMemoryCardPort x0_cardPort; CMemoryCardSys::EMemoryCardPort x0_cardPort;
@ -164,6 +174,7 @@ public:
void GoTo17(); void GoTo17();
void GoTo28(); void GoTo28();
void GoTo29(); void GoTo29();
void GoTo31();
void GoTo32(); void GoTo32();
void GoTo33(); void GoTo33();
void GoTo34(); void GoTo34();

View File

@ -12,9 +12,84 @@ namespace MP1
{ {
using EState = CMemoryCardDriver::EState; using EState = CMemoryCardDriver::EState;
using EError = CMemoryCardDriver::EError;
void CSaveUI::ResetCardDriver()
{
x92_ = false;
x6c_cardDriver.reset();
bool flag = (x0_instIdx == 0 && !x90_needsDriverReset);
x6c_cardDriver = ConstructCardDriver(flag);
x6c_cardDriver->FinishedLoading();
x10_uiType = UIType::Zero;
FinishedLoading();
}
CIOWin::EMessageReturn CSaveUI::Update(float dt) CIOWin::EMessageReturn CSaveUI::Update(float dt)
{ {
if (PumpLoad())
return CIOWin::EMessageReturn::Normal;
x50_loadedFrame->Update(dt);
x6c_cardDriver->Update();
if (x6c_cardDriver->x10_state == EState::RuntimeBackup)
{
if (x90_needsDriverReset)
{
ResetCardDriver();
x90_needsDriverReset = false;
}
else
x80_iowRet = CIOWin::EMessageReturn::Exit;
}
else if (x6c_cardDriver->x10_state == EState::SelectCardFile && x10_uiType != UIType::Fourteen)
{
if (x6c_cardDriver->x28_cardSerial && x8_serial)
{
if (x93_secondaryInst)
{
x10_uiType = UIType::Fourteen;
x91_ = true;
}
else
{
x8_serial = x6c_cardDriver->x28_cardSerial;
x6c_cardDriver->GoTo17();
}
}
}
else if (x6c_cardDriver->x10_state == EState::Ready)
{
if (x90_needsDriverReset)
x6c_cardDriver->GoTo33();
}
if (x80_iowRet != CIOWin::EMessageReturn::Normal)
return x80_iowRet;
UIType oldTp = x10_uiType;
x10_uiType = SelectUIType();
if (oldTp == x10_uiType || x91_)
FinishedLoading();
if (x6c_cardDriver->x10_state == EState::NoCard)
{
auto res = CMemoryCardSys::CardProbe(CMemoryCardSys::EMemoryCardPort::SlotA);
if (res.x0_error == CMemoryCardSys::ECardResult::CARD_RESULT_READY ||
res.x0_error == CMemoryCardSys::ECardResult::CARD_RESULT_WRONGDEVICE)
ResetCardDriver();
}
else if (x6c_cardDriver->x10_state == EState::CardFormatted)
{
ResetCardDriver();
}
else if (x6c_cardDriver->x10_state == EState::Seventeen &&
x6c_cardDriver->x14_error == EError::Eight)
{
x6c_cardDriver->GoTo31();
}
return CIOWin::EMessageReturn::Normal; return CIOWin::EMessageReturn::Normal;
} }
@ -152,8 +227,8 @@ void* CSaveUI::GetGameData(int idx) const
return nullptr; return nullptr;
} }
CSaveUI::CSaveUI(u32 instIdx, u32 a, u32 b) CSaveUI::CSaveUI(u32 instIdx, u64 serial)
: x0_instIdx(instIdx), x8_a(a), xc_b(b) : x0_instIdx(instIdx), x8_serial(serial)
{ {
x14_txtrSaveBanner = g_SimplePool->GetObj("TXTR_SaveBanner"); x14_txtrSaveBanner = g_SimplePool->GetObj("TXTR_SaveBanner");
x20_txtrSaveIcon0 = g_SimplePool->GetObj("TXTR_SaveIcon0"); x20_txtrSaveIcon0 = g_SimplePool->GetObj("TXTR_SaveIcon0");

View File

@ -59,8 +59,7 @@ public:
private: private:
u32 x0_instIdx; u32 x0_instIdx;
u32 x8_a; u64 x8_serial;
u32 xc_b;
UIType x10_uiType = UIType::Zero; UIType x10_uiType = UIType::Zero;
TLockedToken<CTexture> x14_txtrSaveBanner; TLockedToken<CTexture> x14_txtrSaveBanner;
TLockedToken<CTexture> x20_txtrSaveIcon0; TLockedToken<CTexture> x20_txtrSaveIcon0;
@ -76,15 +75,17 @@ private:
CGuiTextPane* x68_textpane_choice3; CGuiTextPane* x68_textpane_choice3;
std::unique_ptr<CMemoryCardDriver> x6c_cardDriver; std::unique_ptr<CMemoryCardDriver> x6c_cardDriver;
std::vector<TLockedToken<CSaveWorld>> x70_saveWorlds; std::vector<TLockedToken<CSaveWorld>> x70_saveWorlds;
u32 x80_ = 0; CIOWin::EMessageReturn x80_iowRet = CIOWin::EMessageReturn::Normal;
u32 x84_navConfirmSfx = 1460; u32 x84_navConfirmSfx = 1460;
u32 x88_navMoveSfx = 1461; u32 x88_navMoveSfx = 1461;
u32 x8c_navBackSfx = 1459; u32 x8c_navBackSfx = 1459;
bool x90_ = false; bool x90_needsDriverReset = false;
bool x91_ = false; bool x91_ = false;
bool x92_ = false; bool x92_ = false;
bool x93_secondaryInst; bool x93_secondaryInst;
void ResetCardDriver();
public: public:
static std::unique_ptr<CMemoryCardDriver> ConstructCardDriver(bool flag); static std::unique_ptr<CMemoryCardDriver> ConstructCardDriver(bool flag);
CIOWin::EMessageReturn Update(float dt); CIOWin::EMessageReturn Update(float dt);
@ -101,7 +102,7 @@ public:
void EraseGame(int idx); void EraseGame(int idx);
void* GetGameData(int idx) const; void* GetGameData(int idx) const;
UIType GetUIType() const { return x10_uiType; } UIType GetUIType() const { return x10_uiType; }
CSaveUI(u32 inst, u32 a, u32 b); CSaveUI(u32 inst, u64 serial);
}; };
} }