mirror of https://github.com/AxioDL/metaforce.git
Additional memory card imps
This commit is contained in:
parent
513d283bee
commit
a7322e8916
|
@ -39,7 +39,8 @@ public:
|
|||
static OSTime ToWiiTime(std::chrono::system_clock::time_point time);
|
||||
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);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -24,45 +24,88 @@ const char* CBasics::Stringize(const char* fmt, ...)
|
|||
const u64 CBasics::SECONDS_TO_2000 = 946684800LL;
|
||||
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)
|
||||
{
|
||||
time_t sysTime, tzDiff;
|
||||
struct tm* gmTime;
|
||||
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);
|
||||
|
||||
sysTime = std::chrono::system_clock::to_time_t(time);
|
||||
// Account for DST where needed
|
||||
gmTime = localtime(&sysTime);
|
||||
if (!gmTime)
|
||||
struct tm _timeSt;
|
||||
long gmtOff;
|
||||
struct tm* timeSt = localtime_r(sysTime, _timeSt, gmtOff);
|
||||
if (!timeSt)
|
||||
return 0;
|
||||
|
||||
// Lazy way to get local time in sec
|
||||
gmTime = gmtime(&sysTime);
|
||||
tzDiff = sysTime - mktime(gmTime);
|
||||
|
||||
return OSTime(TICKS_PER_SECOND * ((sysTime + tzDiff) - SECONDS_TO_2000));
|
||||
/* Returning local */
|
||||
return OSTime(TICKS_PER_SECOND * ((sysTime + gmtOff) - SECONDS_TO_2000) +
|
||||
us * TICKS_PER_SECOND / 1000000);
|
||||
}
|
||||
|
||||
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());
|
||||
// Account for DST where needed
|
||||
struct tm* gmTime = localtime(&sysTime);
|
||||
if (!gmTime)
|
||||
struct tm _timeSt;
|
||||
long gmtOff;
|
||||
struct tm* timeSt = localtime_r(sysTime, _timeSt, gmtOff);
|
||||
if (!timeSt)
|
||||
return std::chrono::system_clock::from_time_t(0);
|
||||
|
||||
// Lazy way to get local time in sec
|
||||
gmTime = gmtime(&sysTime);
|
||||
time_t tzDiff = sysTime - mktime(gmTime);
|
||||
|
||||
return std::chrono::system_clock::from_time_t(time - tzDiff);
|
||||
/* Returning GMT */
|
||||
return std::chrono::system_clock::from_time_t(time - gmtOff) +
|
||||
std::chrono::microseconds(div.rem * 1000000 / TICKS_PER_SECOND);
|
||||
}
|
||||
|
||||
OSCalendarTime CBasics::ToCalendarTime(OSTime time)
|
||||
OSCalendarTime CBasics::ToCalendarTime(std::chrono::system_clock::time_point time)
|
||||
{
|
||||
OSCalendarTime ret = {};
|
||||
/* TODO: Finsh */
|
||||
OSCalendarTime ret;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -189,9 +189,9 @@ void CMemoryCardSys::CCardFileInfo::BuildCardBuffer()
|
|||
|
||||
CMemoryOutStream w(x104_cardBuffer.data(), x104_cardBuffer.size());
|
||||
w.writeUint32Big(0);
|
||||
char name[64];
|
||||
strncpy(name, x28_name2.data(), 64);
|
||||
w.writeBytes(name, 64);
|
||||
char comment[64];
|
||||
strncpy(comment, x28_comment.data(), 64);
|
||||
w.writeBytes(comment, 64);
|
||||
WriteBannerData(w);
|
||||
WriteIconData(w);
|
||||
memmove(x104_cardBuffer.data() + bannerSz, xf4_saveBuffer.data(), xf4_saveBuffer.size());
|
||||
|
|
|
@ -172,8 +172,8 @@ public:
|
|||
|
||||
EStatus x0_status = EStatus::Standby;
|
||||
CARDFileInfo x4_info;
|
||||
std::string x18_name;
|
||||
std::string x28_name2;
|
||||
std::string x18_fileName;
|
||||
std::string x28_comment;
|
||||
ResId x3c_bannerTex = -1;
|
||||
std::experimental::optional<TLockedToken<CTexture>> x40_bannerTok;
|
||||
rstl::reserved_vector<Icon, 8> x50_iconToks;
|
||||
|
@ -183,7 +183,7 @@ public:
|
|||
CVParamTransfer m_texParam = {new TObjOwnerParam<u32>(SBIG('OTEX'))};
|
||||
|
||||
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 LockIconToken(ResId iconTxtr, u32 speed, CSimplePool& sp);
|
||||
|
@ -195,11 +195,18 @@ public:
|
|||
void BuildCardBuffer();
|
||||
void WriteBannerData(CMemoryOutStream& out) const;
|
||||
void WriteIconData(CMemoryOutStream& out) const;
|
||||
void SetComment(const std::string& c) { x28_comment = c; }
|
||||
ECardResult PumpCardTransfer();
|
||||
ECardResult GetStatus(CARDStat& stat) const;
|
||||
ECardResult CreateFile();
|
||||
ECardResult Write();
|
||||
ECardResult Close();
|
||||
|
||||
CMemoryOutStream BeginMemoryOut(u32 sz)
|
||||
{
|
||||
xf4_saveBuffer.resize(sz);
|
||||
return CMemoryOutStream(xf4_saveBuffer.data(), sz);
|
||||
}
|
||||
};
|
||||
|
||||
static CardProbeResults CardProbe(EMemoryCardPort port);
|
||||
|
|
|
@ -226,9 +226,9 @@ CGameState::GameFileStateInfo* CMemoryCardDriver::GetGameFileStateInfo(int idx)
|
|||
CMemoryCardDriver::SSaveHeader CMemoryCardDriver::LoadSaveHeader(CMemoryInStream& in)
|
||||
{
|
||||
SSaveHeader ret;
|
||||
ret.x0_ = in.readUint32Big();
|
||||
ret.x0_version = in.readUint32Big();
|
||||
for (int i=0 ; i<3 ; ++i)
|
||||
ret.x4_[i] = in.readBool();
|
||||
ret.x4_savePresent[i] = in.readBool();
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -655,10 +655,28 @@ void CMemoryCardDriver::GoTo29()
|
|||
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()
|
||||
{
|
||||
x14_error = EError::Zero;
|
||||
x10_state = EState::Write;
|
||||
x10_state = EState::ThirtyTwo;
|
||||
ECardResult result = x198_fileInfo->Write();
|
||||
if (result != ECardResult::CARD_RESULT_READY)
|
||||
Case32(result);
|
||||
|
@ -667,7 +685,7 @@ void CMemoryCardDriver::GoTo32()
|
|||
void CMemoryCardDriver::GoTo33()
|
||||
{
|
||||
x14_error = EError::Zero;
|
||||
x10_state = EState::ThirtyThree;
|
||||
x10_state = EState::FileBuild;
|
||||
ClearFileInfo();
|
||||
if (x18_cardFreeBytes < 8192 || !x1c_cardFreeFiles)
|
||||
{
|
||||
|
@ -686,7 +704,7 @@ void CMemoryCardDriver::GoTo33()
|
|||
void CMemoryCardDriver::GoTo34()
|
||||
{
|
||||
x14_error = EError::Zero;
|
||||
x10_state = EState::ThirtyFour;
|
||||
x10_state = EState::FileWrite;
|
||||
ECardResult result = x198_fileInfo->Write();
|
||||
if (result != ECardResult::CARD_RESULT_READY)
|
||||
Case34(result);
|
||||
|
@ -707,7 +725,7 @@ void CMemoryCardDriver::GoTo36()
|
|||
if (x194_fileIdx == 1)
|
||||
{
|
||||
x14_error = EError::Zero;
|
||||
x10_state = EState::ThirtySix;
|
||||
x10_state = EState::FileRename;
|
||||
ECardResult result = CMemoryCardSys::Rename(x0_cardPort,
|
||||
SaveFileNames[x194_fileIdx],
|
||||
SaveFileNames[!bool(x194_fileIdx)]);
|
||||
|
@ -733,7 +751,31 @@ void CMemoryCardDriver::GoTo37()
|
|||
void CMemoryCardDriver::InitializeFileInfo()
|
||||
{
|
||||
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()
|
||||
|
@ -822,19 +864,19 @@ void CMemoryCardDriver::Update()
|
|||
case EState::ThirtyOne:
|
||||
Case31(resultCode);
|
||||
break;
|
||||
case EState::Write:
|
||||
case EState::ThirtyTwo:
|
||||
Case32(resultCode);
|
||||
break;
|
||||
case EState::ThirtyThree:
|
||||
case EState::FileBuild:
|
||||
Case33(resultCode);
|
||||
break;
|
||||
case EState::ThirtyFour:
|
||||
case EState::FileWrite:
|
||||
Case34(resultCode);
|
||||
break;
|
||||
case EState::ThirtyFive:
|
||||
Case35(resultCode);
|
||||
break;
|
||||
case EState::ThirtySix:
|
||||
case EState::FileRename:
|
||||
Case36(resultCode);
|
||||
break;
|
||||
case EState::CardFormat:
|
||||
|
|
|
@ -47,11 +47,11 @@ public:
|
|||
TwentyNine = 29,
|
||||
Thirty = 30,
|
||||
ThirtyOne = 31,
|
||||
Write = 32,
|
||||
ThirtyThree = 33,
|
||||
ThirtyFour = 34,
|
||||
ThirtyTwo = 32,
|
||||
FileBuild = 33,
|
||||
FileWrite = 34,
|
||||
ThirtyFive = 35,
|
||||
ThirtySix = 36,
|
||||
FileRename = 36,
|
||||
CardFormat = 37
|
||||
};
|
||||
|
||||
|
@ -98,8 +98,14 @@ private:
|
|||
|
||||
struct SSaveHeader
|
||||
{
|
||||
u32 x0_;
|
||||
u32 x4_[3];
|
||||
u32 x0_version = 0;
|
||||
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
|
||||
|
@ -109,6 +115,10 @@ private:
|
|||
SGameFileSlot();
|
||||
SGameFileSlot(CMemoryInStream& in);
|
||||
void InitializeFromGameState();
|
||||
void DoPut(CMemoryOutStream& w) const
|
||||
{
|
||||
w.writeBytes(x0_saveBuffer, 940);
|
||||
}
|
||||
};
|
||||
|
||||
CMemoryCardSys::EMemoryCardPort x0_cardPort;
|
||||
|
@ -164,6 +174,7 @@ public:
|
|||
void GoTo17();
|
||||
void GoTo28();
|
||||
void GoTo29();
|
||||
void GoTo31();
|
||||
void GoTo32();
|
||||
void GoTo33();
|
||||
void GoTo34();
|
||||
|
|
|
@ -12,9 +12,84 @@ namespace MP1
|
|||
{
|
||||
|
||||
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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -152,8 +227,8 @@ void* CSaveUI::GetGameData(int idx) const
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
CSaveUI::CSaveUI(u32 instIdx, u32 a, u32 b)
|
||||
: x0_instIdx(instIdx), x8_a(a), xc_b(b)
|
||||
CSaveUI::CSaveUI(u32 instIdx, u64 serial)
|
||||
: x0_instIdx(instIdx), x8_serial(serial)
|
||||
{
|
||||
x14_txtrSaveBanner = g_SimplePool->GetObj("TXTR_SaveBanner");
|
||||
x20_txtrSaveIcon0 = g_SimplePool->GetObj("TXTR_SaveIcon0");
|
||||
|
|
|
@ -59,8 +59,7 @@ public:
|
|||
|
||||
private:
|
||||
u32 x0_instIdx;
|
||||
u32 x8_a;
|
||||
u32 xc_b;
|
||||
u64 x8_serial;
|
||||
UIType x10_uiType = UIType::Zero;
|
||||
TLockedToken<CTexture> x14_txtrSaveBanner;
|
||||
TLockedToken<CTexture> x20_txtrSaveIcon0;
|
||||
|
@ -76,15 +75,17 @@ private:
|
|||
CGuiTextPane* x68_textpane_choice3;
|
||||
std::unique_ptr<CMemoryCardDriver> x6c_cardDriver;
|
||||
std::vector<TLockedToken<CSaveWorld>> x70_saveWorlds;
|
||||
u32 x80_ = 0;
|
||||
CIOWin::EMessageReturn x80_iowRet = CIOWin::EMessageReturn::Normal;
|
||||
u32 x84_navConfirmSfx = 1460;
|
||||
u32 x88_navMoveSfx = 1461;
|
||||
u32 x8c_navBackSfx = 1459;
|
||||
bool x90_ = false;
|
||||
bool x90_needsDriverReset = false;
|
||||
bool x91_ = false;
|
||||
bool x92_ = false;
|
||||
bool x93_secondaryInst;
|
||||
|
||||
void ResetCardDriver();
|
||||
|
||||
public:
|
||||
static std::unique_ptr<CMemoryCardDriver> ConstructCardDriver(bool flag);
|
||||
CIOWin::EMessageReturn Update(float dt);
|
||||
|
@ -101,7 +102,7 @@ public:
|
|||
void EraseGame(int idx);
|
||||
void* GetGameData(int idx) const;
|
||||
UIType GetUIType() const { return x10_uiType; }
|
||||
CSaveUI(u32 inst, u32 a, u32 b);
|
||||
CSaveUI(u32 inst, u64 serial);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue