mirror of https://github.com/AxioDL/metaforce.git
Work on CMemoryCardDriver
This commit is contained in:
parent
29222827c6
commit
9639ac75cc
|
@ -9,6 +9,7 @@ namespace urde
|
||||||
/** Options tracked persistently between game sessions */
|
/** Options tracked persistently between game sessions */
|
||||||
class CPersistentOptions
|
class CPersistentOptions
|
||||||
{
|
{
|
||||||
|
friend class CGameState;
|
||||||
bool x0_[98] = {};
|
bool x0_[98] = {};
|
||||||
bool x68_[64] = {};
|
bool x68_[64] = {};
|
||||||
std::vector<std::pair<ResId, TEditorId>> xac_cinematicStates; /* (MLVL, Cinematic) */
|
std::vector<std::pair<ResId, TEditorId>> xac_cinematicStates; /* (MLVL, Cinematic) */
|
||||||
|
@ -40,11 +41,16 @@ public:
|
||||||
CPersistentOptions(CBitStreamReader& stream);
|
CPersistentOptions(CBitStreamReader& stream);
|
||||||
|
|
||||||
void SetCinematicState(ResId mlvlId, TEditorId cineId, bool state);
|
void SetCinematicState(ResId mlvlId, TEditorId cineId, bool state);
|
||||||
bool PlayerHasHardMode() const { return xd0_25_hasHardMode; }
|
bool GetPlayerHasHardMode() const { return xd0_25_hasHardMode; }
|
||||||
bool PlayerBeatHardMode() const { return xd0_26_hardModeBeat; }
|
void SetPlayerHasHardMode(bool v) { xd0_25_hasHardMode = v; }
|
||||||
bool PlayerHasFusion() const { return xd0_28_hasFusion; }
|
bool GetPlayerBeatHardMode() const { return xd0_26_hardModeBeat; }
|
||||||
bool AllItemsCollected() const { return xd0_29_allItemsCollected; }
|
void SetPlayerBeatHardMode(bool v) { xd0_26_hardModeBeat = v; }
|
||||||
|
bool GetPlayerHasFusion() const { return xd0_28_hasFusion; }
|
||||||
|
void SetPlayerHasFusion(bool v) { xd0_28_hasFusion = v; }
|
||||||
|
bool GetAllItemsCollected() const { return xd0_29_allItemsCollected; }
|
||||||
|
void SetAllItemsCollected(bool v) { xd0_29_allItemsCollected = v; }
|
||||||
u32 GetLogScanCount() const { return xcc_logScanCount; }
|
u32 GetLogScanCount() const { return xcc_logScanCount; }
|
||||||
|
void SetLogScanCount(u32 v) { xcc_logScanCount = v; }
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Options tracked per game session */
|
/** Options tracked per game session */
|
||||||
|
|
|
@ -88,6 +88,52 @@ void CWorldState::PutTo(CBitStreamWriter& writer, const CSaveWorld& savw) const
|
||||||
x14_layerState->PutTo(writer);
|
x14_layerState->PutTo(writer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CGameState::GameFileStateInfo CGameState::LoadGameFileState(const u8* data)
|
||||||
|
{
|
||||||
|
CBitStreamReader stream(data, 4096);
|
||||||
|
GameFileStateInfo ret;
|
||||||
|
|
||||||
|
for (u32 i = 0; i < 128; i++)
|
||||||
|
stream.ReadEncoded(8);
|
||||||
|
ret.x14_timestamp = stream.ReadEncoded(32);
|
||||||
|
|
||||||
|
ret.x20_hardMode = stream.ReadEncoded(1);
|
||||||
|
stream.ReadEncoded(1);
|
||||||
|
ret.x8_mlvlId = stream.ReadEncoded(32);
|
||||||
|
|
||||||
|
union BitsToDouble
|
||||||
|
{
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
u32 low;
|
||||||
|
u32 high;
|
||||||
|
};
|
||||||
|
double doub;
|
||||||
|
} conv;
|
||||||
|
conv.low = stream.ReadEncoded(32);
|
||||||
|
conv.high = stream.ReadEncoded(32);
|
||||||
|
ret.x0_playTime = conv.doub;
|
||||||
|
|
||||||
|
CPlayerState playerState(stream);
|
||||||
|
ret.x10_energyTanks = playerState.GetItemCapacity(CPlayerState::EItemType::EnergyTanks);
|
||||||
|
|
||||||
|
u32 itemPercent;
|
||||||
|
if (ret.x8_mlvlId == 0x158EFE17)
|
||||||
|
itemPercent = 0;
|
||||||
|
else
|
||||||
|
itemPercent = playerState.CalculateItemCollectionRate() * 100 / playerState.GetPickupTotal();
|
||||||
|
ret.x18_itemPercent = itemPercent;
|
||||||
|
|
||||||
|
float somePercent;
|
||||||
|
if (playerState.GetTotalLogScans() == 0)
|
||||||
|
somePercent = 0.f;
|
||||||
|
else
|
||||||
|
somePercent = 100.f * playerState.GetLogScans() / float(playerState.GetTotalLogScans());
|
||||||
|
ret.x1c_scanPercent = somePercent;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
CGameState::CGameState()
|
CGameState::CGameState()
|
||||||
{
|
{
|
||||||
x98_playerState.reset(new CPlayerState());
|
x98_playerState.reset(new CPlayerState());
|
||||||
|
@ -137,6 +183,19 @@ CGameState::CGameState(CBitStreamReader& stream)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CGameState::MergePersistentOptions(const CPersistentOptions& opts)
|
||||||
|
{
|
||||||
|
if (opts.xd0_24_)
|
||||||
|
xa8_systemOptions.xd0_24_ = true;
|
||||||
|
if (opts.xd0_27_)
|
||||||
|
xa8_systemOptions.xd0_27_ = true;
|
||||||
|
if (&opts != &xa8_systemOptions)
|
||||||
|
memcpy(xa8_systemOptions.x0_, opts.x0_, 98);
|
||||||
|
xa8_systemOptions.SetLogScanCount(opts.GetLogScanCount());
|
||||||
|
xa8_systemOptions.SetAllItemsCollected(opts.GetAllItemsCollected());
|
||||||
|
xa8_systemOptions.SetPlayerHasHardMode(opts.GetPlayerHasHardMode());
|
||||||
|
xa8_systemOptions.SetPlayerBeatHardMode(opts.GetPlayerBeatHardMode());
|
||||||
|
}
|
||||||
|
|
||||||
void CGameState::PutTo(CBitStreamWriter& writer) const
|
void CGameState::PutTo(CBitStreamWriter& writer) const
|
||||||
{
|
{
|
||||||
|
|
|
@ -108,7 +108,21 @@ public:
|
||||||
CWorldState& CurrentWorldState() { return StateForWorld(x84_mlvlId); }
|
CWorldState& CurrentWorldState() { return StateForWorld(x84_mlvlId); }
|
||||||
ResId CurrentWorldAssetId() const { return x84_mlvlId; }
|
ResId CurrentWorldAssetId() const { return x84_mlvlId; }
|
||||||
void SetHardMode(bool v) { x228_24_hardMode = v; }
|
void SetHardMode(bool v) { x228_24_hardMode = v; }
|
||||||
|
void MergePersistentOptions(const CPersistentOptions& opts);
|
||||||
void PutTo(CBitStreamWriter& writer) const;
|
void PutTo(CBitStreamWriter& writer) const;
|
||||||
|
|
||||||
|
struct GameFileStateInfo
|
||||||
|
{
|
||||||
|
double x0_playTime;
|
||||||
|
u32 x8_mlvlId;
|
||||||
|
float xc_health;
|
||||||
|
u32 x10_energyTanks;
|
||||||
|
u32 x14_timestamp;
|
||||||
|
u32 x18_itemPercent;
|
||||||
|
float x1c_scanPercent;
|
||||||
|
bool x20_hardMode;
|
||||||
|
};
|
||||||
|
static GameFileStateInfo LoadGameFileState(const u8* data);
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -117,7 +117,7 @@ bool CMemoryCardSys::InitializePump()
|
||||||
|
|
||||||
x20_scanStates.reserve(x20_scanStates.size() + savw.GetScans().size());
|
x20_scanStates.reserve(x20_scanStates.size() + savw.GetScans().size());
|
||||||
for (const CSaveWorld::SScanState& scan : savw.GetScans())
|
for (const CSaveWorld::SScanState& scan : savw.GetScans())
|
||||||
x20_scanStates[scan.x0_id] = scan.x4_category;
|
x20_scanStates.emplace_back(scan.x0_id, scan.x4_category);
|
||||||
|
|
||||||
wldMemOut.x3c_saveWorld = std::move(world.x34_saveWorld);
|
wldMemOut.x3c_saveWorld = std::move(world.x34_saveWorld);
|
||||||
wldMemOut.x2c_worldName = g_SimplePool->GetObj(SObjectTag{FOURCC('STRG'), wldMemOut.x0_strgId});
|
wldMemOut.x2c_worldName = g_SimplePool->GetObj(SObjectTag{FOURCC('STRG'), wldMemOut.x0_strgId});
|
||||||
|
@ -157,4 +157,24 @@ CMemoryCardSys::ECardResult CMemoryCardSys::GetSerialNo(EMemoryCardPort port, u6
|
||||||
return ECardResult::CARD_RESULT_READY;
|
return ECardResult::CARD_RESULT_READY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CMemoryCardSys::ECardResult CMemoryCardSys::GetResultCode(EMemoryCardPort port)
|
||||||
|
{
|
||||||
|
return ECardResult::CARD_RESULT_READY;
|
||||||
|
}
|
||||||
|
|
||||||
|
CMemoryCardSys::ECardResult CMemoryCardSys::GetStatus(EMemoryCardPort port, int fileNo, CARDStat& statOut)
|
||||||
|
{
|
||||||
|
return ECardResult::CARD_RESULT_READY;
|
||||||
|
}
|
||||||
|
|
||||||
|
CMemoryCardSys::ECardResult CMemoryCardSys::DeleteFile(EMemoryCardPort port, const char* name)
|
||||||
|
{
|
||||||
|
return ECardResult::CARD_RESULT_READY;
|
||||||
|
}
|
||||||
|
|
||||||
|
CMemoryCardSys::ECardResult CMemoryCardSys::FastDeleteFile(EMemoryCardPort port, int fileNo)
|
||||||
|
{
|
||||||
|
return ECardResult::CARD_RESULT_READY;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,11 @@
|
||||||
#include "CSaveWorld.hpp"
|
#include "CSaveWorld.hpp"
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
// longest file name string excluding terminating zero
|
||||||
|
#define CARD_FILENAME_MAX 32
|
||||||
|
|
||||||
|
#define CARD_ICON_MAX 8
|
||||||
|
|
||||||
namespace urde
|
namespace urde
|
||||||
{
|
{
|
||||||
class CDummyWorld;
|
class CDummyWorld;
|
||||||
|
@ -53,10 +58,11 @@ class CMemoryCardSys
|
||||||
TLockedToken<CGameHintInfo> x0_hints;
|
TLockedToken<CGameHintInfo> x0_hints;
|
||||||
std::vector<std::pair<ResId, CSaveWorldMemory>> xc_memoryWorlds; /* MLVL as key */
|
std::vector<std::pair<ResId, CSaveWorldMemory>> xc_memoryWorlds; /* MLVL as key */
|
||||||
std::experimental::optional<std::vector<CSaveWorldIntermediate>> x1c_worldInter; /* used to be auto_ptr of vector */
|
std::experimental::optional<std::vector<CSaveWorldIntermediate>> x1c_worldInter; /* used to be auto_ptr of vector */
|
||||||
std::unordered_map<ResId, CSaveWorld::EScanCategory> x20_scanStates;
|
std::vector<std::pair<ResId, CSaveWorld::EScanCategory>> x20_scanStates;
|
||||||
public:
|
public:
|
||||||
const std::vector<CGameHintInfo::CGameHint>& GetHints() const { return x0_hints->GetHints(); }
|
const std::vector<CGameHintInfo::CGameHint>& GetHints() const { return x0_hints->GetHints(); }
|
||||||
const std::vector<std::pair<ResId, CSaveWorldMemory>>& GetMemoryWorlds() const { return xc_memoryWorlds; }
|
const std::vector<std::pair<ResId, CSaveWorldMemory>>& GetMemoryWorlds() const { return xc_memoryWorlds; }
|
||||||
|
const std::vector<std::pair<ResId, CSaveWorld::EScanCategory>>& GetScanStates() const { return x20_scanStates; }
|
||||||
CMemoryCardSys();
|
CMemoryCardSys();
|
||||||
bool InitializePump();
|
bool InitializePump();
|
||||||
|
|
||||||
|
@ -68,6 +74,7 @@ public:
|
||||||
|
|
||||||
enum class ECardResult
|
enum class ECardResult
|
||||||
{
|
{
|
||||||
|
CARD_RESULT_CRC_MISMATCH = -1003,
|
||||||
CARD_RESULT_FATAL_ERROR = -128,
|
CARD_RESULT_FATAL_ERROR = -128,
|
||||||
CARD_RESULT_ENCODING = -13,
|
CARD_RESULT_ENCODING = -13,
|
||||||
CARD_RESULT_BROKEN = -6,
|
CARD_RESULT_BROKEN = -6,
|
||||||
|
@ -85,11 +92,59 @@ public:
|
||||||
u32 x8_sectorSize; // in bytes
|
u32 x8_sectorSize; // in bytes
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct CARDStat
|
||||||
|
{
|
||||||
|
// read-only (Set by CARDGetStatus)
|
||||||
|
char x0_fileName[CARD_FILENAME_MAX];
|
||||||
|
u32 x20_length;
|
||||||
|
u32 x24_time; // seconds since 01/01/2000 midnight
|
||||||
|
u8 x28_gameName[4];
|
||||||
|
u8 x2c_company[2];
|
||||||
|
|
||||||
|
// read/write (Set by CARDGetStatus/CARDSetStatus)
|
||||||
|
u8 x2e_bannerFormat;
|
||||||
|
u8 x2f___padding;
|
||||||
|
u32 x30_iconAddr; // offset to the banner, bannerTlut, icon, iconTlut data set.
|
||||||
|
u16 x34_iconFormat;
|
||||||
|
u16 x36_iconSpeed;
|
||||||
|
u32 x38_commentAddr; // offset to the pair of 32 byte character strings.
|
||||||
|
|
||||||
|
// read-only (Set by CARDGetStatus)
|
||||||
|
u32 x3c_offsetBanner;
|
||||||
|
u32 x40_offsetBannerTlut;
|
||||||
|
u32 x44_offsetIcon[CARD_ICON_MAX];
|
||||||
|
u32 x64_offsetIconTlut;
|
||||||
|
u32 x68_offsetData;
|
||||||
|
|
||||||
|
u32 GetTime() const { return x24_time; }
|
||||||
|
u32 GetBannerFormat() const { return x2e_bannerFormat & 0x3; }
|
||||||
|
void SetBannerFormat(u32 fmt) { x2e_bannerFormat = (x2e_bannerFormat & ~0x3) | fmt; }
|
||||||
|
u32 GetIconFormat(int idx) const { return (x34_iconFormat >> (idx * 2)) & 0x3; }
|
||||||
|
void SetIconFormat(u32 fmt, int idx)
|
||||||
|
{
|
||||||
|
x34_iconFormat &= ~(0x3 << (idx * 2));
|
||||||
|
x34_iconFormat |= fmt << (idx * 2);
|
||||||
|
}
|
||||||
|
void SetIconSpeed(u32 sp, int idx)
|
||||||
|
{
|
||||||
|
x36_iconSpeed &= ~(0x3 << (idx * 2));
|
||||||
|
x36_iconSpeed |= sp << (idx * 2);
|
||||||
|
}
|
||||||
|
u32 GetIconAddr() const { return x30_iconAddr; }
|
||||||
|
void SetIconAddr(u32 addr) { x30_iconAddr = addr; }
|
||||||
|
u32 GetCommentAddr() const { return x38_commentAddr; }
|
||||||
|
void SetCommentAddr(u32 addr) { x38_commentAddr = addr; }
|
||||||
|
};
|
||||||
|
|
||||||
static CardProbeResults CardProbe(EMemoryCardPort port);
|
static CardProbeResults CardProbe(EMemoryCardPort port);
|
||||||
static ECardResult MountCard(EMemoryCardPort port);
|
static ECardResult MountCard(EMemoryCardPort port);
|
||||||
static ECardResult CheckCard(EMemoryCardPort port);
|
static ECardResult CheckCard(EMemoryCardPort port);
|
||||||
static ECardResult GetNumFreeBytes(EMemoryCardPort port, s32& freeBytes, s32& freeFiles);
|
static ECardResult GetNumFreeBytes(EMemoryCardPort port, s32& freeBytes, s32& freeFiles);
|
||||||
static ECardResult GetSerialNo(EMemoryCardPort port, u64& serialOut);
|
static ECardResult GetSerialNo(EMemoryCardPort port, u64& serialOut);
|
||||||
|
static ECardResult GetResultCode(EMemoryCardPort port);
|
||||||
|
static ECardResult GetStatus(EMemoryCardPort port, int fileNo, CARDStat& statOut);
|
||||||
|
static ECardResult DeleteFile(EMemoryCardPort port, const char* name);
|
||||||
|
static ECardResult FastDeleteFile(EMemoryCardPort port, int fileNo);
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -86,8 +86,8 @@ CPlayerState::CPlayerState(CBitStreamReader& stream)
|
||||||
x170_scanTimes[i].second = 0.f;
|
x170_scanTimes[i].second = 0.f;
|
||||||
}
|
}
|
||||||
|
|
||||||
x180_ = stream.ReadEncoded(CBitStreamReader::GetBitCount(0x100));
|
x180_logScans = stream.ReadEncoded(CBitStreamReader::GetBitCount(0x100));
|
||||||
x184_ = stream.ReadEncoded(CBitStreamReader::GetBitCount(0x100));
|
x184_totalLogScans = stream.ReadEncoded(CBitStreamReader::GetBitCount(0x100));
|
||||||
}
|
}
|
||||||
|
|
||||||
void CPlayerState::PutTo(CBitStreamWriter &stream)
|
void CPlayerState::PutTo(CBitStreamWriter &stream)
|
||||||
|
@ -112,8 +112,8 @@ void CPlayerState::PutTo(CBitStreamWriter &stream)
|
||||||
stream.WriteEncoded(false, 1);
|
stream.WriteEncoded(false, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
stream.WriteEncoded(x180_, CBitStreamWriter::GetBitCount(0x100));
|
stream.WriteEncoded(x180_logScans, CBitStreamWriter::GetBitCount(0x100));
|
||||||
stream.WriteEncoded(x184_, CBitStreamWriter::GetBitCount(0x100));
|
stream.WriteEncoded(x184_totalLogScans, CBitStreamWriter::GetBitCount(0x100));
|
||||||
}
|
}
|
||||||
|
|
||||||
static const float unk[]
|
static const float unk[]
|
||||||
|
|
|
@ -124,8 +124,8 @@ private:
|
||||||
EPlayerSuit x20_currentSuit = EPlayerSuit::Power;
|
EPlayerSuit x20_currentSuit = EPlayerSuit::Power;
|
||||||
rstl::reserved_vector<CPowerUp, 41> x24_powerups;
|
rstl::reserved_vector<CPowerUp, 41> x24_powerups;
|
||||||
rstl::reserved_vector<std::pair<u32, float>, 846> x170_scanTimes;
|
rstl::reserved_vector<std::pair<u32, float>, 846> x170_scanTimes;
|
||||||
u32 x180_ = 0;
|
u32 x180_logScans = 0;
|
||||||
u32 x184_ = 0;
|
u32 x184_totalLogScans = 0;
|
||||||
CStaticInterference x188_staticIntf;
|
CStaticInterference x188_staticIntf;
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
@ -166,6 +166,9 @@ public:
|
||||||
float CalculateHealth(u32 health);
|
float CalculateHealth(u32 health);
|
||||||
void ReInitalizePowerUp(EItemType type, u32 capacity);
|
void ReInitalizePowerUp(EItemType type, u32 capacity);
|
||||||
void InitializePowerUp(EItemType type, u32 capacity);
|
void InitializePowerUp(EItemType type, u32 capacity);
|
||||||
|
u32 GetLogScans() const { return x180_logScans; }
|
||||||
|
u32 GetTotalLogScans() const { return x184_totalLogScans; }
|
||||||
|
const rstl::reserved_vector<std::pair<u32, float>, 846>& GetScanTimes() const { return x170_scanTimes; }
|
||||||
CPlayerState() : x188_staticIntf(5) { x0_24_ = true; }
|
CPlayerState() : x188_staticIntf(5) { x0_24_ = true; }
|
||||||
CPlayerState(CBitStreamReader& stream);
|
CPlayerState(CBitStreamReader& stream);
|
||||||
void PutTo(CBitStreamWriter& stream);
|
void PutTo(CBitStreamWriter& stream);
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
#include "World/CScriptSpawnPoint.hpp"
|
#include "World/CScriptSpawnPoint.hpp"
|
||||||
#include "AutoMapper/CMapWorldInfo.hpp"
|
#include "AutoMapper/CMapWorldInfo.hpp"
|
||||||
#include "Particle/CGenDescription.hpp"
|
#include "Particle/CGenDescription.hpp"
|
||||||
|
#include "CMemoryCardSys.hpp"
|
||||||
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
|
||||||
|
@ -808,4 +809,23 @@ TUniqueId CStateManager::AllocateUniqueId()
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::pair<u32, u32> CStateManager::CalculateScanCompletionRate() const
|
||||||
|
{
|
||||||
|
u32 num = 0;
|
||||||
|
u32 denom = 0;
|
||||||
|
int idx = 0;
|
||||||
|
for (const std::pair<u32, float>& scan : x8b8_playerState->GetScanTimes())
|
||||||
|
{
|
||||||
|
CSaveWorld::EScanCategory category = g_MemoryCardSys->GetScanStates()[idx++].second;
|
||||||
|
if (category != CSaveWorld::EScanCategory::None &&
|
||||||
|
category != CSaveWorld::EScanCategory::Research)
|
||||||
|
{
|
||||||
|
++denom;
|
||||||
|
if (scan.second == 1.f)
|
||||||
|
++num;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {num, denom};
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -303,6 +303,8 @@ public:
|
||||||
CListeningAiList& GetListeningAiObjectList() const { return *x834_listenAiObjs; }
|
CListeningAiList& GetListeningAiObjectList() const { return *x834_listenAiObjs; }
|
||||||
CAiWaypointList& GetAiWaypointObjectList() const { return *x83c_aiWaypointObjs; }
|
CAiWaypointList& GetAiWaypointObjectList() const { return *x83c_aiWaypointObjs; }
|
||||||
CPlatformAndDoorList& GetPlatformAndDoorObjectList() const { return *x844_platformAndDoorObjs; }
|
CPlatformAndDoorList& GetPlatformAndDoorObjectList() const { return *x844_platformAndDoorObjs; }
|
||||||
|
|
||||||
|
std::pair<u32, u32> CalculateScanCompletionRate() const;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -277,7 +277,7 @@ void CFrontEndUI::SNewFileSelectFrame::ActivateNewGamePopup()
|
||||||
|
|
||||||
PlayAdvanceSfx();
|
PlayAdvanceSfx();
|
||||||
|
|
||||||
if (g_GameState->SystemOptions().PlayerHasHardMode())
|
if (g_GameState->SystemOptions().GetPlayerHasHardMode())
|
||||||
{
|
{
|
||||||
x48_textpane_popupadvance.SetPairText(g_MainStringTable->GetString(102));
|
x48_textpane_popupadvance.SetPairText(g_MainStringTable->GetString(102));
|
||||||
x50_textpane_popupcancel.SetPairText(g_MainStringTable->GetString(94));
|
x50_textpane_popupcancel.SetPairText(g_MainStringTable->GetString(94));
|
||||||
|
@ -414,7 +414,7 @@ void CFrontEndUI::SNewFileSelectFrame::DoPopupAdvance(CGuiTableGroup* caller)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (g_GameState->SystemOptions().PlayerHasHardMode())
|
if (g_GameState->SystemOptions().GetPlayerHasHardMode())
|
||||||
{
|
{
|
||||||
if (x40_tablegroup_popup->GetUserSelection() == 1)
|
if (x40_tablegroup_popup->GetUserSelection() == 1)
|
||||||
{
|
{
|
||||||
|
@ -502,7 +502,7 @@ void CFrontEndUI::SGBASupportFrame::FinishedLoading()
|
||||||
x2c_tablegroup_fusionsuit->SetIsActive(false);
|
x2c_tablegroup_fusionsuit->SetIsActive(false);
|
||||||
x2c_tablegroup_fusionsuit->SetIsVisible(false);
|
x2c_tablegroup_fusionsuit->SetIsVisible(false);
|
||||||
x2c_tablegroup_fusionsuit->SetD1(false);
|
x2c_tablegroup_fusionsuit->SetD1(false);
|
||||||
x2c_tablegroup_fusionsuit->SetUserSelection(g_GameState->SystemOptions().PlayerHasFusion());
|
x2c_tablegroup_fusionsuit->SetUserSelection(g_GameState->SystemOptions().GetPlayerHasFusion());
|
||||||
|
|
||||||
SetTableColors(x28_tablegroup_options);
|
SetTableColors(x28_tablegroup_options);
|
||||||
SetTableColors(x2c_tablegroup_fusionsuit);
|
SetTableColors(x2c_tablegroup_fusionsuit);
|
||||||
|
|
|
@ -1,24 +1,130 @@
|
||||||
#include "CMemoryCardDriver.hpp"
|
#include "CMemoryCardDriver.hpp"
|
||||||
#include "MP1.hpp"
|
#include "MP1.hpp"
|
||||||
|
#include "CCRC32.hpp"
|
||||||
|
|
||||||
namespace urde
|
namespace urde
|
||||||
{
|
{
|
||||||
namespace MP1
|
namespace MP1
|
||||||
{
|
{
|
||||||
|
|
||||||
CMemoryCardDriver::SMemoryCardSlotInfo::SMemoryCardSlotInfo(CMemoryCardSys::EMemoryCardPort parentIdx,
|
using ECardResult = CMemoryCardSys::ECardResult;
|
||||||
const std::string& name)
|
using EMemoryCardPort = CMemoryCardSys::EMemoryCardPort;
|
||||||
: x0_cardPort(parentIdx), x14_name(name)
|
|
||||||
{}
|
|
||||||
|
|
||||||
CMemoryCardDriver::CMemoryCardDriver(CMemoryCardSys::EMemoryCardPort cardPort, ResId saveBanner,
|
ECardResult CMemoryCardDriver::SFileInfo::Close()
|
||||||
ResId saveIcon0, ResId saveIcon1, bool flag)
|
|
||||||
: x0_cardPort(cardPort), x4_saveBanner(saveBanner),
|
|
||||||
x8_saveIcon0(saveIcon0), xc_saveIcon1(saveIcon1), x19d_flag(flag)
|
|
||||||
{
|
{
|
||||||
x100_mcSlotInfos.reserve(2);
|
auto backup = GetFileCardPort();
|
||||||
x100_mcSlotInfos.emplace_back(0, SMemoryCardSlotInfo(x0_cardPort, "MetroidPrime A"));
|
ECardResult result = ECardResult::CARD_RESULT_READY;
|
||||||
x100_mcSlotInfos.emplace_back(0, SMemoryCardSlotInfo(x0_cardPort, "MetroidPrime B"));
|
//result = CARDClose(backup);
|
||||||
|
x0_fileInfo.x0_cardPort = backup;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
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,
|
||||||
|
ResId saveIcon0, ResId saveIcon1, bool mergePersistent)
|
||||||
|
: x0_cardPort(cardPort), x4_saveBanner(saveBanner),
|
||||||
|
x8_saveIcon0(saveIcon0), xc_saveIcon1(saveIcon1), x19d_doMergePersistent(mergePersistent)
|
||||||
|
{
|
||||||
|
x100_mcFileInfos.reserve(2);
|
||||||
|
x100_mcFileInfos.emplace_back(0, SFileInfo(x0_cardPort, "MetroidPrime A"));
|
||||||
|
x100_mcFileInfos.emplace_back(0, SFileInfo(x0_cardPort, "MetroidPrime B"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void CMemoryCardDriver::FinishedLoading()
|
void CMemoryCardDriver::FinishedLoading()
|
||||||
|
@ -33,7 +139,7 @@ void CMemoryCardDriver::FinishedLoading2()
|
||||||
auto result = CMemoryCardSys::CardProbe(x0_cardPort);
|
auto result = CMemoryCardSys::CardProbe(x0_cardPort);
|
||||||
switch (result.x0_error)
|
switch (result.x0_error)
|
||||||
{
|
{
|
||||||
case CMemoryCardSys::ECardResult::CARD_RESULT_READY:
|
case ECardResult::CARD_RESULT_READY:
|
||||||
if (result.x8_sectorSize != 0x2000)
|
if (result.x8_sectorSize != 0x2000)
|
||||||
{
|
{
|
||||||
x10_state = EState::Twelve;
|
x10_state = EState::Twelve;
|
||||||
|
@ -43,9 +149,9 @@ void CMemoryCardDriver::FinishedLoading2()
|
||||||
x10_state = EState::Five;
|
x10_state = EState::Five;
|
||||||
MountCard();
|
MountCard();
|
||||||
break;
|
break;
|
||||||
case CMemoryCardSys::ECardResult::CARD_RESULT_BUSY:
|
case ECardResult::CARD_RESULT_BUSY:
|
||||||
break;
|
break;
|
||||||
case CMemoryCardSys::ECardResult::CARD_RESULT_WRONGDEVICE:
|
case ECardResult::CARD_RESULT_WRONGDEVICE:
|
||||||
x10_state = EState::Twelve;
|
x10_state = EState::Twelve;
|
||||||
x14_error = EError::Four;
|
x14_error = EError::Four;
|
||||||
break;
|
break;
|
||||||
|
@ -65,20 +171,97 @@ void CMemoryCardDriver::MountCard()
|
||||||
{
|
{
|
||||||
x10_state = EState::TwentySix;
|
x10_state = EState::TwentySix;
|
||||||
x14_error = EError::Zero;
|
x14_error = EError::Zero;
|
||||||
CMemoryCardSys::ECardResult result = CMemoryCardSys::MountCard(x0_cardPort);
|
ECardResult result = CMemoryCardSys::MountCard(x0_cardPort);
|
||||||
if (result != CMemoryCardSys::ECardResult::CARD_RESULT_READY)
|
if (result != ECardResult::CARD_RESULT_READY)
|
||||||
MountCardFailed(result);
|
Case26(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CMemoryCardDriver::MountCardFailed(CMemoryCardSys::ECardResult 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
auto ret = std::make_unique<CMemoryCardDriver::SGameFileSlot>();
|
||||||
|
in.readBytesToBuf(ret->x0_saveBuffer, 940);
|
||||||
|
ret->x944_fileInfo = CGameState::LoadGameFileState(ret->x0_saveBuffer);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
if (x19d_doMergePersistent)
|
||||||
|
MergePersistentOptions();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMemoryCardDriver::MergePersistentOptions()
|
||||||
|
{
|
||||||
|
CBitStreamReader r(x30_systemData, 174);
|
||||||
|
CPersistentOptions opts(r);
|
||||||
|
g_GameState->MergePersistentOptions(opts);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMemoryCardDriver::DeleteFile()
|
||||||
|
{
|
||||||
|
x14_error = EError::Zero;
|
||||||
|
x10_state = EState::Thirty;
|
||||||
|
SFileInfo& fileInfo = x100_mcFileInfos[bool(x194_fileIdx)].second;
|
||||||
|
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)
|
||||||
{
|
{
|
||||||
switch (result)
|
switch (result)
|
||||||
{
|
{
|
||||||
case CMemoryCardSys::ECardResult::CARD_RESULT_READY:
|
case ECardResult::CARD_RESULT_READY:
|
||||||
x10_state = EState::Six;
|
x10_state = EState::Six;
|
||||||
CheckCard();
|
CheckCard();
|
||||||
break;
|
break;
|
||||||
case CMemoryCardSys::ECardResult::CARD_RESULT_BROKEN:
|
case ECardResult::CARD_RESULT_BROKEN:
|
||||||
x10_state = EState::Six;
|
x10_state = EState::Six;
|
||||||
x14_error = EError::One;
|
x14_error = EError::One;
|
||||||
CheckCard();
|
CheckCard();
|
||||||
|
@ -89,27 +272,19 @@ void CMemoryCardDriver::MountCardFailed(CMemoryCardSys::ECardResult result)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CMemoryCardDriver::CheckCard()
|
void CMemoryCardDriver::Case27(ECardResult result)
|
||||||
{
|
|
||||||
CMemoryCardSys::ECardResult result = CMemoryCardSys::CheckCard(x0_cardPort);
|
|
||||||
if (result != CMemoryCardSys::ECardResult::CARD_RESULT_READY)
|
|
||||||
CheckCardFailed(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CMemoryCardDriver::CheckCardFailed(CMemoryCardSys::ECardResult result)
|
|
||||||
{
|
{
|
||||||
switch (result)
|
switch (result)
|
||||||
{
|
{
|
||||||
case CMemoryCardSys::ECardResult::CARD_RESULT_READY:
|
case ECardResult::CARD_RESULT_READY:
|
||||||
x10_state = EState::Seven;
|
x10_state = EState::Seven;
|
||||||
if (!GetCardFreeBytes())
|
if (!GetCardFreeBytes())
|
||||||
return;
|
return;
|
||||||
if (CMemoryCardSys::GetSerialNo(x0_cardPort, x28_cardSerial) ==
|
if (CMemoryCardSys::GetSerialNo(x0_cardPort, x28_cardSerial) == ECardResult::CARD_RESULT_READY)
|
||||||
CMemoryCardSys::ECardResult::CARD_RESULT_READY)
|
|
||||||
return;
|
return;
|
||||||
NoCardFound();
|
NoCardFound();
|
||||||
break;
|
break;
|
||||||
case CMemoryCardSys::ECardResult::CARD_RESULT_BROKEN:
|
case ECardResult::CARD_RESULT_BROKEN:
|
||||||
x10_state = EState::Fourteen;
|
x10_state = EState::Fourteen;
|
||||||
x14_error = EError::One;
|
x14_error = EError::One;
|
||||||
break;
|
break;
|
||||||
|
@ -118,32 +293,148 @@ void CMemoryCardDriver::CheckCardFailed(CMemoryCardSys::ECardResult result)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CMemoryCardDriver::Case28(ECardResult result)
|
||||||
|
{
|
||||||
|
if (result == ECardResult::CARD_RESULT_READY)
|
||||||
|
{
|
||||||
|
x100_mcFileInfos[x194_fileIdx].first = 1;
|
||||||
|
if (x100_mcFileInfos[bool(x194_fileIdx)].first == 3)
|
||||||
|
{
|
||||||
|
x10_state = EState::Seventeen;
|
||||||
|
GoTo28();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
x10_state = EState::Seven;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 fileIdx = bool(x194_fileIdx);
|
||||||
|
if (readRes == ECardResult::CARD_RESULT_READY)
|
||||||
|
{
|
||||||
|
x10_state = EState::One;
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
x10_state = EState::Seven;
|
||||||
|
GoTo17();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
x10_state = EState::Seventeen;
|
||||||
|
x14_error = EError::Nine;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
HandleCardError(result, EState::Seventeen);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMemoryCardDriver::Case30(ECardResult result)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMemoryCardDriver::Case31(ECardResult result)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMemoryCardDriver::Case32(ECardResult result)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMemoryCardDriver::Case33(ECardResult result)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMemoryCardDriver::Case34(ECardResult result)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMemoryCardDriver::Case35(ECardResult result)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMemoryCardDriver::Case36(ECardResult result)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMemoryCardDriver::Case37(ECardResult result)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMemoryCardDriver::GoTo17()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMemoryCardDriver::GoTo28()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
bool CMemoryCardDriver::GetCardFreeBytes()
|
bool CMemoryCardDriver::GetCardFreeBytes()
|
||||||
{
|
{
|
||||||
CMemoryCardSys::ECardResult result = CMemoryCardSys::GetNumFreeBytes(x0_cardPort,
|
ECardResult result = CMemoryCardSys::GetNumFreeBytes(x0_cardPort,
|
||||||
x18_cardFreeBytes,
|
x18_cardFreeBytes,
|
||||||
x1c_cardFreeFiles);
|
x1c_cardFreeFiles);
|
||||||
if (result == CMemoryCardSys::ECardResult::CARD_RESULT_READY)
|
if (result == ECardResult::CARD_RESULT_READY)
|
||||||
return true;
|
return true;
|
||||||
NoCardFound();
|
NoCardFound();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CMemoryCardDriver::HandleCardError(CMemoryCardSys::ECardResult result, EState state)
|
void CMemoryCardDriver::HandleCardError(ECardResult result, EState state)
|
||||||
{
|
{
|
||||||
switch (result)
|
switch (result)
|
||||||
{
|
{
|
||||||
case CMemoryCardSys::ECardResult::CARD_RESULT_WRONGDEVICE:
|
case ECardResult::CARD_RESULT_WRONGDEVICE:
|
||||||
x10_state = state;
|
x10_state = state;
|
||||||
x14_error = EError::Four;
|
x14_error = EError::Four;
|
||||||
break;
|
break;
|
||||||
case CMemoryCardSys::ECardResult::CARD_RESULT_NOCARD:
|
case ECardResult::CARD_RESULT_NOCARD:
|
||||||
NoCardFound();
|
NoCardFound();
|
||||||
break;
|
break;
|
||||||
case CMemoryCardSys::ECardResult::CARD_RESULT_IOERROR:
|
case ECardResult::CARD_RESULT_IOERROR:
|
||||||
x10_state = state;
|
x10_state = state;
|
||||||
x14_error = EError::Three;
|
x14_error = EError::Three;
|
||||||
case CMemoryCardSys::ECardResult::CARD_RESULT_ENCODING:
|
case ECardResult::CARD_RESULT_ENCODING:
|
||||||
x10_state = state;
|
x10_state = state;
|
||||||
x14_error = EError::Two;
|
x14_error = EError::Two;
|
||||||
break;
|
break;
|
||||||
|
@ -153,9 +444,9 @@ void CMemoryCardDriver::HandleCardError(CMemoryCardSys::ECardResult result, ESta
|
||||||
|
|
||||||
void CMemoryCardDriver::Update()
|
void CMemoryCardDriver::Update()
|
||||||
{
|
{
|
||||||
auto result = CMemoryCardSys::CardProbe(x0_cardPort);
|
CMemoryCardSys::CardProbeResults result = CMemoryCardSys::CardProbe(x0_cardPort);
|
||||||
|
|
||||||
if (result.x0_error == CMemoryCardSys::ECardResult::CARD_RESULT_NOCARD)
|
if (result.x0_error == ECardResult::CARD_RESULT_NOCARD)
|
||||||
{
|
{
|
||||||
if (x10_state != EState::Two)
|
if (x10_state != EState::Two)
|
||||||
NoCardFound();
|
NoCardFound();
|
||||||
|
@ -163,23 +454,65 @@ void CMemoryCardDriver::Update()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (x10_state == EState::TwentyFive)
|
||||||
|
{
|
||||||
|
FinishedLoading2();
|
||||||
|
static_cast<CMain*>(g_Main)->SetCardInserted(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ECardResult resultCode = g_MemoryCardSys->GetResultCode(x0_cardPort);
|
||||||
|
bool cardInserted = false;
|
||||||
|
|
||||||
|
if (InCardInsertedRange(x10_state))
|
||||||
|
{
|
||||||
|
cardInserted = true;
|
||||||
|
|
||||||
switch (x10_state)
|
switch (x10_state)
|
||||||
{
|
{
|
||||||
case EState::TwentySix:
|
case EState::TwentySix:
|
||||||
|
Case26(resultCode);
|
||||||
|
break;
|
||||||
case EState::TwentySeven:
|
case EState::TwentySeven:
|
||||||
|
Case27(resultCode);
|
||||||
|
break;
|
||||||
case EState::TwentyEight:
|
case EState::TwentyEight:
|
||||||
|
Case28(resultCode);
|
||||||
|
break;
|
||||||
case EState::TwentyNine:
|
case EState::TwentyNine:
|
||||||
|
Case29(resultCode);
|
||||||
|
break;
|
||||||
case EState::Thirty:
|
case EState::Thirty:
|
||||||
|
Case30(resultCode);
|
||||||
|
break;
|
||||||
case EState::ThirtyOne:
|
case EState::ThirtyOne:
|
||||||
|
Case31(resultCode);
|
||||||
|
break;
|
||||||
case EState::ThirtyTwo:
|
case EState::ThirtyTwo:
|
||||||
|
Case32(resultCode);
|
||||||
|
break;
|
||||||
case EState::ThirtyThree:
|
case EState::ThirtyThree:
|
||||||
|
Case33(resultCode);
|
||||||
|
break;
|
||||||
case EState::ThirtyFour:
|
case EState::ThirtyFour:
|
||||||
|
Case34(resultCode);
|
||||||
|
break;
|
||||||
case EState::ThirtyFive:
|
case EState::ThirtyFive:
|
||||||
|
Case35(resultCode);
|
||||||
|
break;
|
||||||
case EState::ThirtySix:
|
case EState::ThirtySix:
|
||||||
|
Case36(resultCode);
|
||||||
|
break;
|
||||||
case EState::ThirtySeven:
|
case EState::ThirtySeven:
|
||||||
|
Case37(resultCode);
|
||||||
|
break;
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static_cast<CMain*>(g_Main)->SetCardInserted(cardInserted);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#define __URDE_CMEMORYCARDDRIVER_HPP__
|
#define __URDE_CMEMORYCARDDRIVER_HPP__
|
||||||
|
|
||||||
#include "CMemoryCardSys.hpp"
|
#include "CMemoryCardSys.hpp"
|
||||||
|
#include "CGameState.hpp"
|
||||||
|
|
||||||
namespace urde
|
namespace urde
|
||||||
{
|
{
|
||||||
|
@ -23,6 +24,8 @@ public:
|
||||||
Twelve = 12,
|
Twelve = 12,
|
||||||
Thirteen = 13,
|
Thirteen = 13,
|
||||||
Fourteen = 14,
|
Fourteen = 14,
|
||||||
|
Fifteen = 15,
|
||||||
|
Seventeen = 17,
|
||||||
TwentyFive = 26,
|
TwentyFive = 26,
|
||||||
TwentySix = 26,
|
TwentySix = 26,
|
||||||
TwentySeven = 27,
|
TwentySeven = 27,
|
||||||
|
@ -53,14 +56,42 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct SMemoryCardSlotInfo
|
struct CARDFileInfo
|
||||||
{
|
{
|
||||||
CMemoryCardSys::EMemoryCardPort x0_cardPort;
|
CMemoryCardSys::EMemoryCardPort x0_cardPort;
|
||||||
u32 x4_ = -1;
|
int x4_fileNo = -1;
|
||||||
|
int x8_offset;
|
||||||
|
int xc_length;
|
||||||
|
u16 iBlock;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SFileInfo
|
||||||
|
{
|
||||||
|
CARDFileInfo x0_fileInfo;
|
||||||
std::string x14_name;
|
std::string x14_name;
|
||||||
std::vector<u8> x24_;
|
std::vector<u8> x24_saveFileData;
|
||||||
std::vector<u8> x34_;
|
std::vector<u8> x34_saveData;
|
||||||
SMemoryCardSlotInfo(CMemoryCardSys::EMemoryCardPort cardPort, const std::string& name);
|
SFileInfo(CMemoryCardSys::EMemoryCardPort cardPort, const std::string& name);
|
||||||
|
CMemoryCardSys::ECardResult Close();
|
||||||
|
CMemoryCardSys::EMemoryCardPort GetFileCardPort() const { return x0_fileInfo.x0_cardPort; }
|
||||||
|
int GetFileNo() const { return x0_fileInfo.x4_fileNo; }
|
||||||
|
CMemoryCardSys::ECardResult TryFileRead();
|
||||||
|
CMemoryCardSys::ECardResult FileRead();
|
||||||
|
CMemoryCardSys::ECardResult GetSaveDataOffset(u32& offOut);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SSaveHeader
|
||||||
|
{
|
||||||
|
u32 x0_;
|
||||||
|
u32 x4_[3];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SGameFileSlot
|
||||||
|
{
|
||||||
|
u8 x0_saveBuffer[940] = {};
|
||||||
|
CGameState::GameFileStateInfo x944_fileInfo;
|
||||||
|
SGameFileSlot();
|
||||||
|
void InitializeFromGameState();
|
||||||
};
|
};
|
||||||
|
|
||||||
CMemoryCardSys::EMemoryCardPort x0_cardPort;
|
CMemoryCardSys::EMemoryCardPort x0_cardPort;
|
||||||
|
@ -71,16 +102,16 @@ private:
|
||||||
EError x14_error = EError::Zero;
|
EError x14_error = EError::Zero;
|
||||||
s32 x18_cardFreeBytes = 0;
|
s32 x18_cardFreeBytes = 0;
|
||||||
s32 x1c_cardFreeFiles = 0;
|
s32 x1c_cardFreeFiles = 0;
|
||||||
u32 x20_ = 0;
|
u32 x20_fileTime = 0;
|
||||||
u32 x24_ = 0;
|
u32 x24_ = 0;
|
||||||
u64 x28_cardSerial = 0;
|
u64 x28_cardSerial = 0;
|
||||||
u8 x30_[174];
|
u8 x30_systemData[174] = {};
|
||||||
std::unique_ptr<u8> xe4_[3];
|
std::unique_ptr<SGameFileSlot> xe4_fileSlots[3];
|
||||||
std::vector<std::pair<u32, SMemoryCardSlotInfo>> x100_mcSlotInfos;
|
std::vector<std::pair<u32, SFileInfo>> x100_mcFileInfos;
|
||||||
u32 x194_ = -1;
|
u32 x194_fileIdx = -1;
|
||||||
u32 x198_ = 0;
|
u32 x198_ = 0;
|
||||||
bool x19c_ = false;
|
bool x19c_ = false;
|
||||||
bool x19d_flag;
|
bool x19d_doMergePersistent;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CMemoryCardDriver(CMemoryCardSys::EMemoryCardPort cardPort, ResId saveBanner,
|
CMemoryCardDriver(CMemoryCardSys::EMemoryCardPort cardPort, ResId saveBanner,
|
||||||
|
@ -89,12 +120,51 @@ public:
|
||||||
void FinishedLoading2();
|
void FinishedLoading2();
|
||||||
void NoCardFound();
|
void NoCardFound();
|
||||||
void MountCard();
|
void MountCard();
|
||||||
void MountCardFailed(CMemoryCardSys::ECardResult result);
|
|
||||||
void CheckCard();
|
void CheckCard();
|
||||||
void CheckCardFailed(CMemoryCardSys::ECardResult result);
|
|
||||||
|
CGameState::GameFileStateInfo* GetGameFileStateInfo(int idx);
|
||||||
|
static SSaveHeader LoadSaveHeader(CMemoryInStream& in);
|
||||||
|
static std::unique_ptr<SGameFileSlot> LoadSaveFile(CMemoryInStream& in);
|
||||||
|
void ReadFinished();
|
||||||
|
void MergePersistentOptions();
|
||||||
|
void DeleteFile();
|
||||||
|
void CheckCardCapacity();
|
||||||
|
|
||||||
|
void Case26(CMemoryCardSys::ECardResult result);
|
||||||
|
void Case27(CMemoryCardSys::ECardResult result);
|
||||||
|
void Case28(CMemoryCardSys::ECardResult result);
|
||||||
|
void Case29(CMemoryCardSys::ECardResult result);
|
||||||
|
void Case30(CMemoryCardSys::ECardResult result);
|
||||||
|
void Case31(CMemoryCardSys::ECardResult result);
|
||||||
|
void Case32(CMemoryCardSys::ECardResult result);
|
||||||
|
void Case33(CMemoryCardSys::ECardResult result);
|
||||||
|
void Case34(CMemoryCardSys::ECardResult result);
|
||||||
|
void Case35(CMemoryCardSys::ECardResult result);
|
||||||
|
void Case36(CMemoryCardSys::ECardResult result);
|
||||||
|
void Case37(CMemoryCardSys::ECardResult result);
|
||||||
|
|
||||||
|
void GoTo17();
|
||||||
|
void GoTo28();
|
||||||
|
|
||||||
bool GetCardFreeBytes();
|
bool GetCardFreeBytes();
|
||||||
void HandleCardError(CMemoryCardSys::ECardResult result, EState state);
|
void HandleCardError(CMemoryCardSys::ECardResult result, EState state);
|
||||||
void Update();
|
void Update();
|
||||||
|
|
||||||
|
static bool InCardInsertedRange(EState v)
|
||||||
|
{
|
||||||
|
return v >= EState::TwentySix && v <= EState::ThirtySeven;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool InRange2(EState v)
|
||||||
|
{
|
||||||
|
if (v < EState::TwentyFive)
|
||||||
|
return false;
|
||||||
|
if (v == EState::TwentySeven)
|
||||||
|
return false;
|
||||||
|
if (v == EState::TwentyNine)
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,22 +57,6 @@ bool CSaveUI::PumpLoad()
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool InRange1(EState v)
|
|
||||||
{
|
|
||||||
return v >= EState::TwentySix && v <= EState::ThirtySeven;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool InRange2(EState v)
|
|
||||||
{
|
|
||||||
if (v < EState::TwentyFive)
|
|
||||||
return false;
|
|
||||||
if (v == EState::TwentySeven)
|
|
||||||
return false;
|
|
||||||
if (v == EState::TwentyNine)
|
|
||||||
return false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
CSaveUI::UIType CSaveUI::SelectUIType() const
|
CSaveUI::UIType CSaveUI::SelectUIType() const
|
||||||
{
|
{
|
||||||
if (x6c_cardDriver->x10_state == EState::Two)
|
if (x6c_cardDriver->x10_state == EState::Two)
|
||||||
|
@ -87,9 +71,9 @@ CSaveUI::UIType CSaveUI::SelectUIType() const
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (InRange1(x6c_cardDriver->x10_state))
|
if (CMemoryCardDriver::InCardInsertedRange(x6c_cardDriver->x10_state))
|
||||||
{
|
{
|
||||||
if (!InRange2(x6c_cardDriver->x10_state))
|
if (!CMemoryCardDriver::InRange2(x6c_cardDriver->x10_state))
|
||||||
return UIType::Two;
|
return UIType::Two;
|
||||||
return UIType::One;
|
return UIType::One;
|
||||||
}
|
}
|
||||||
|
@ -156,7 +140,6 @@ void CSaveUI::ProcessUserInput(const CFinalInput& input)
|
||||||
|
|
||||||
void CSaveUI::StartGame(int idx)
|
void CSaveUI::StartGame(int idx)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSaveUI::EraseGame(int idx)
|
void CSaveUI::EraseGame(int idx)
|
||||||
|
@ -178,7 +161,7 @@ CSaveUI::CSaveUI(u32 instIdx, u32 a, u32 b)
|
||||||
x38_strgMemoryCard = g_SimplePool->GetObj("STRG_MemoryCard");
|
x38_strgMemoryCard = g_SimplePool->GetObj("STRG_MemoryCard");
|
||||||
x44_frmeGenericMenu = g_SimplePool->GetObj("FRME_GenericMenu");
|
x44_frmeGenericMenu = g_SimplePool->GetObj("FRME_GenericMenu");
|
||||||
|
|
||||||
x6c_cardDriver = ConstructCardDriver(x0_instIdx / 32);
|
x6c_cardDriver = ConstructCardDriver(x0_instIdx);
|
||||||
|
|
||||||
if (instIdx == 1)
|
if (instIdx == 1)
|
||||||
{
|
{
|
||||||
|
|
|
@ -174,9 +174,9 @@ u32 CSlideShow::SlideShowGalleryFlags()
|
||||||
ret |= 1;
|
ret |= 1;
|
||||||
if (g_GameState->SystemOptions().GetLogScanCount() == 100)
|
if (g_GameState->SystemOptions().GetLogScanCount() == 100)
|
||||||
ret |= 2;
|
ret |= 2;
|
||||||
if (g_GameState->SystemOptions().PlayerBeatHardMode())
|
if (g_GameState->SystemOptions().GetPlayerBeatHardMode())
|
||||||
ret |= 4;
|
ret |= 4;
|
||||||
if (g_GameState->SystemOptions().AllItemsCollected())
|
if (g_GameState->SystemOptions().GetAllItemsCollected())
|
||||||
ret |= 8;
|
ret |= 8;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue