Work on CMemoryCardDriver

This commit is contained in:
Jack Andersen 2016-12-22 20:41:39 -10:00
parent c92223301c
commit d7f79d6ec3
25 changed files with 929 additions and 82 deletions

View File

@ -12,6 +12,21 @@ namespace urde
using OSTime = s64;
struct OSCalendarTime
{
int x0_sec; // seconds after the minute [0, 61]
int x4_min; // minutes after the hour [0, 59]
int x8_hour; // hours since midnight [0, 23]
int xc_mday; // day of the month [1, 31]
int x10_mon; // month since January [0, 11]
int x14_year; // years in AD [1, ...]
int x18_wday; // days since Sunday [0, 6]
int x1c_yday; // days since January 1 [0, 365]
int x20_msec; // milliseconds after the second [0,999]
int x24_usec; // microseconds after the millisecond [0,999]
};
class CBasics
{
public:
@ -23,6 +38,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);
};
}

View File

@ -59,4 +59,11 @@ std::chrono::system_clock::time_point CBasics::FromWiiTime(OSTime wiiTime)
return std::chrono::system_clock::from_time_t(time - tzDiff);
}
OSCalendarTime CBasics::ToCalendarTime(OSTime time)
{
OSCalendarTime ret = {};
/* TODO: Finsh */
return ret;
}
}

View File

@ -54,6 +54,48 @@ CPersistentOptions::CPersistentOptions(CBitStreamReader& stream)
}
}
void CPersistentOptions::PutTo(CBitStreamWriter& w) const
{
for (int b=0 ; b<98 ; ++b)
w.WriteEncoded(x0_[b], 1);
for (int b=0 ; b<64 ; ++b)
w.WriteEncoded(x68_[b], 1);
w.WriteEncoded(xc0_, 2);
w.WriteEncoded(xc4_, 2);
w.WriteEncoded(xc8_, 1);
w.WriteEncoded(xcc_logScanCount, 7);
w.WriteEncoded(xd0_24_, 1);
w.WriteEncoded(xd0_25_hasHardMode, 1);
w.WriteEncoded(xd0_26_hardModeBeat, 1);
w.WriteEncoded(xd0_27_, 1);
w.WriteEncoded(xd0_28_hasFusion, 1);
w.WriteEncoded(xd0_29_allItemsCollected, 1);
w.WriteEncoded(xbc_, 2);
auto& memWorlds = g_MemoryCardSys->GetMemoryWorlds();
for (const auto& world : memWorlds)
{
TLockedToken<CSaveWorld> saveWorld =
g_SimplePool->GetObj(SObjectTag{FOURCC('SAVW'), world.first});
for (TEditorId cineId : saveWorld->GetCinematics())
w.WriteEncoded(GetCinematicState(world.first, cineId), 1);
}
}
bool CPersistentOptions::GetCinematicState(ResId mlvlId, TEditorId cineId) const
{
auto existing = std::find_if(xac_cinematicStates.cbegin(), xac_cinematicStates.cend(),
[&](const std::pair<ResId, TEditorId>& pair) -> bool
{
return pair.first == mlvlId && pair.second == cineId;
});
return existing != xac_cinematicStates.cend();
}
void CPersistentOptions::SetCinematicState(ResId mlvlId, TEditorId cineId, bool state)
{
auto existing = std::find_if(xac_cinematicStates.cbegin(), xac_cinematicStates.cend(),

View File

@ -40,6 +40,7 @@ public:
CPersistentOptions() = default;
CPersistentOptions(CBitStreamReader& stream);
bool GetCinematicState(ResId mlvlId, TEditorId cineId) const;
void SetCinematicState(ResId mlvlId, TEditorId cineId, bool state);
bool GetPlayerHasHardMode() const { return xd0_25_hasHardMode; }
void SetPlayerHasHardMode(bool v) { xd0_25_hasHardMode = v; }
@ -51,6 +52,7 @@ public:
void SetAllItemsCollected(bool v) { xd0_29_allItemsCollected = v; }
u32 GetLogScanCount() const { return xcc_logScanCount; }
void SetLogScanCount(u32 v) { xcc_logScanCount = v; }
void PutTo(CBitStreamWriter& w) const;
};
/** Options tracked per game session */

View File

@ -183,7 +183,7 @@ CGameState::CGameState(CBitStreamReader& stream)
}
}
void CGameState::MergePersistentOptions(const CPersistentOptions& opts)
void CGameState::ImportPersistentOptions(const CPersistentOptions& opts)
{
if (opts.xd0_24_)
xa8_systemOptions.xd0_24_ = true;
@ -197,6 +197,24 @@ void CGameState::MergePersistentOptions(const CPersistentOptions& opts)
xa8_systemOptions.SetPlayerBeatHardMode(opts.GetPlayerBeatHardMode());
}
void CGameState::ExportPersistentOptions(CPersistentOptions& opts) const
{
if (xa8_systemOptions.xd0_24_)
opts.xd0_24_ = true;
if (xa8_systemOptions.xd0_27_)
opts.xd0_27_ = true;
if (&opts != &xa8_systemOptions)
memcpy(opts.x0_, xa8_systemOptions.x0_, 98);
opts.SetPlayerHasFusion(xa8_systemOptions.GetPlayerHasFusion());
}
void CGameState::WriteBackupBuf()
{
x218_backupBuf.resize(940);
CBitStreamWriter w(x218_backupBuf.data(), 940);
PutTo(w);
}
void CGameState::PutTo(CBitStreamWriter& writer) const
{
for (u32 i = 0; i < 128; i++)

View File

@ -80,8 +80,8 @@ class CGameState
CPersistentOptions xa8_systemOptions;
CGameOptions x17c_gameOptions;
CHintOptions x1f8_hintOptions;
u32 x210_;
u32 x214_;
u64 x210_cardSerial;
std::vector<u8> x218_backupBuf;
union
{
@ -108,7 +108,10 @@ public:
CWorldState& CurrentWorldState() { return StateForWorld(x84_mlvlId); }
ResId CurrentWorldAssetId() const { return x84_mlvlId; }
void SetHardMode(bool v) { x228_24_hardMode = v; }
void MergePersistentOptions(const CPersistentOptions& opts);
void ImportPersistentOptions(const CPersistentOptions& opts);
void ExportPersistentOptions(CPersistentOptions& opts) const;
void WriteBackupBuf();
void SetCardSerial(u64 serial) { x210_cardSerial = serial; }
void PutTo(CBitStreamWriter& writer) const;
struct GameFileStateInfo

View File

@ -3,6 +3,8 @@
#include "CSimplePool.hpp"
#include "CGameState.hpp"
#include "GuiSys/CStringTable.hpp"
#include "CCRC32.hpp"
#include "Graphics/CTexture.hpp"
namespace urde
{
@ -132,6 +134,199 @@ bool CMemoryCardSys::InitializePump()
return false;
}
void CMemoryCardSys::CCardFileInfo::LockBannerToken(ResId bannerTxtr, CSimplePool& sp)
{
x3c_bannerTex = bannerTxtr;
x40_bannerTok.emplace(sp.GetObj({FOURCC('TXTR'), bannerTxtr}, m_texParam));
}
CMemoryCardSys::CCardFileInfo::Icon::Icon(ResId id, u32 speed, CSimplePool& sp, const CVParamTransfer& cv)
: x0_id(id), x4_speed(speed), x8_tex(sp.GetObj({FOURCC('TXTR'), id}, cv)) {}
void CMemoryCardSys::CCardFileInfo::LockIconToken(ResId iconTxtr, u32 speed, CSimplePool& sp)
{
x50_iconToks.emplace_back(iconTxtr, speed, sp, m_texParam);
}
u32 CMemoryCardSys::CCardFileInfo::CalculateBannerDataSize() const
{
u32 ret = 68;
if (x3c_bannerTex != -1)
{
if ((*x40_bannerTok)->GetMemoryCardTexelFormat() == ETexelFormat::RGB5A3)
ret = 6212;
else
ret = 3652;
}
bool paletteTex = false;
for (const Icon& icon : x50_iconToks)
{
if (icon.x8_tex->GetMemoryCardTexelFormat() == ETexelFormat::RGB5A3)
ret += 2048;
else
{
ret += 1024;
paletteTex = true;
}
}
if (paletteTex)
ret += 512;
return ret;
}
u32 CMemoryCardSys::CCardFileInfo::CalculateTotalDataSize() const
{
return (CalculateBannerDataSize() + xf4_saveBuffer.size() + 8191) & ~8191;
}
void CMemoryCardSys::CCardFileInfo::BuildCardBuffer()
{
u32 bannerSz = CalculateBannerDataSize();
x104_cardBuffer.resize((bannerSz + xf4_saveBuffer.size() + 8191) & ~8191);
CMemoryOutStream w(x104_cardBuffer.data(), x104_cardBuffer.size());
w.writeUint32Big(0);
char name[64];
strncpy(name, x28_name2.data(), 64);
w.writeBytes(name, 64);
WriteBannerData(w);
WriteIconData(w);
memmove(x104_cardBuffer.data() + bannerSz, xf4_saveBuffer.data(), xf4_saveBuffer.size());
reinterpret_cast<u32&>(*x104_cardBuffer.data()) =
hecl::SBig(CCRC32::Calculate(x104_cardBuffer.data() + 4, x104_cardBuffer.size() - 4));
xf4_saveBuffer.clear();
}
void CMemoryCardSys::CCardFileInfo::WriteBannerData(CMemoryOutStream& out) const
{
if (x3c_bannerTex != -1)
{
const TLockedToken<CTexture>& tex = *x40_bannerTok;
u32 bufSz;
ETexelFormat fmt;
std::unique_ptr<u8[]> palette;
std::unique_ptr<u8[]> texels = tex->BuildMemoryCardTex(bufSz, fmt, palette);
if (fmt == ETexelFormat::RGB5A3)
out.writeBytes(texels.get(), 6144);
else
out.writeBytes(texels.get(), 3072);
if (fmt == ETexelFormat::C8)
out.writeBytes(palette.get(), 512);
}
}
void CMemoryCardSys::CCardFileInfo::WriteIconData(CMemoryOutStream& out) const
{
std::unique_ptr<u8[]> palette;
for (const Icon& icon : x50_iconToks)
{
u32 bufSz;
ETexelFormat fmt;
std::unique_ptr<u8[]> texels = icon.x8_tex->BuildMemoryCardTex(bufSz, fmt, palette);
if (fmt == ETexelFormat::RGB5A3)
out.writeBytes(texels.get(), 2048);
else
out.writeBytes(texels.get(), 1024);
}
if (palette)
out.writeBytes(palette.get(), 512);
}
CMemoryCardSys::ECardResult CMemoryCardSys::CCardFileInfo::PumpCardTransfer()
{
if (x0_status == EStatus::Standby)
return ECardResult::CARD_RESULT_READY;
else if (x0_status == EStatus::Transferring)
{
ECardResult result = CMemoryCardSys::GetResultCode(GetCardPort());
if (result != ECardResult::CARD_RESULT_BUSY)
x104_cardBuffer.clear();
if (result != ECardResult::CARD_RESULT_READY)
return result;
x0_status = EStatus::Done;
CARDStat stat = {};
result = GetStatus(stat);
if (result != ECardResult::CARD_RESULT_READY)
return result;
result = CMemoryCardSys::SetStatus(GetCardPort(), GetFileNo(), stat);
if (result != ECardResult::CARD_RESULT_READY)
return result;
return ECardResult::CARD_RESULT_BUSY;
}
else
{
ECardResult result = CMemoryCardSys::GetResultCode(GetCardPort());
if (result == ECardResult::CARD_RESULT_READY)
x0_status = EStatus::Standby;
return result;
}
}
CMemoryCardSys::ECardResult CMemoryCardSys::CCardFileInfo::GetStatus(CARDStat& stat) const
{
ECardResult result = CMemoryCardSys::GetStatus(GetCardPort(), GetFileNo(), stat);
if (result != ECardResult::CARD_RESULT_READY)
return result;
stat.SetCommentAddr(4);
stat.SetIconAddr(68);
u32 bannerFmt;
if (x3c_bannerTex != -1)
{
if ((*x40_bannerTok)->GetMemoryCardTexelFormat() == ETexelFormat::RGB5A3)
bannerFmt = 2;
else
bannerFmt = 1;
}
else
bannerFmt = 0;
stat.SetBannerFormat(bannerFmt);
int idx = 0;
for (const Icon& icon : x50_iconToks)
{
stat.SetIconFormat(icon.x8_tex->GetMemoryCardTexelFormat() == ETexelFormat::RGB5A3 ? 2 : 1, idx);
stat.SetIconSpeed(icon.x4_speed, idx);
++idx;
}
if (idx < 8)
{
stat.SetIconFormat(0, idx);
stat.SetIconSpeed(0, idx);
}
return ECardResult::CARD_RESULT_READY;
}
CMemoryCardSys::ECardResult CMemoryCardSys::CCardFileInfo::CreateFile()
{
return ECardResult::CARD_RESULT_READY;
}
CMemoryCardSys::ECardResult CMemoryCardSys::CCardFileInfo::Write()
{
BuildCardBuffer();
//DCStoreRange(info.x104_cardBuffer.data(), info.x104_cardBuffer.size());
//CARDWriteAsync(&info.x4_info, info.x104_cardBuffer.data(), info.x104_cardBuffer.size(), 0, 0);
return ECardResult::CARD_RESULT_READY;
}
CMemoryCardSys::ECardResult CMemoryCardSys::CCardFileInfo::Close()
{
EMemoryCardPort port = GetCardPort();
//CARDClose(port);
x4_info.chan = port;
return ECardResult::CARD_RESULT_READY;
}
CMemoryCardSys::CardProbeResults CMemoryCardSys::CardProbe(EMemoryCardPort port)
{
return {};
@ -167,6 +362,11 @@ CMemoryCardSys::ECardResult CMemoryCardSys::GetStatus(EMemoryCardPort port, int
return ECardResult::CARD_RESULT_READY;
}
CMemoryCardSys::ECardResult CMemoryCardSys::SetStatus(EMemoryCardPort port, int fileNo, const CARDStat& stat)
{
return ECardResult::CARD_RESULT_READY;
}
CMemoryCardSys::ECardResult CMemoryCardSys::DeleteFile(EMemoryCardPort port, const char* name)
{
return ECardResult::CARD_RESULT_READY;
@ -177,4 +377,14 @@ CMemoryCardSys::ECardResult CMemoryCardSys::FastDeleteFile(EMemoryCardPort port,
return ECardResult::CARD_RESULT_READY;
}
CMemoryCardSys::ECardResult CMemoryCardSys::Rename(EMemoryCardPort port, const char* oldName, const char* newName)
{
return ECardResult::CARD_RESULT_READY;
}
CMemoryCardSys::ECardResult CMemoryCardSys::FormatCard(EMemoryCardPort port)
{
return ECardResult::CARD_RESULT_READY;
}
}

View File

@ -16,6 +16,7 @@ namespace urde
{
class CDummyWorld;
class CStringTable;
class CSimplePool;
class CSaveWorldMemory
{
@ -79,6 +80,7 @@ public:
CARD_RESULT_ENCODING = -13,
CARD_RESULT_BROKEN = -6,
CARD_RESULT_IOERROR = -5,
CARD_RESULT_NOFILE = -4,
CARD_RESULT_NOCARD = -3,
CARD_RESULT_WRONGDEVICE = -2,
CARD_RESULT_BUSY = -1,
@ -116,6 +118,7 @@ public:
u32 x64_offsetIconTlut;
u32 x68_offsetData;
u32 GetFileLength() const { return x20_length; }
u32 GetTime() const { return x24_time; }
u32 GetBannerFormat() const { return x2e_bannerFormat & 0x3; }
void SetBannerFormat(u32 fmt) { x2e_bannerFormat = (x2e_bannerFormat & ~0x3) | fmt; }
@ -136,6 +139,68 @@ public:
void SetCommentAddr(u32 addr) { x38_commentAddr = addr; }
};
struct CARDFileInfo
{
EMemoryCardPort chan;
s32 fileNo = -1;
s32 offset;
s32 length;
u16 iBlock;
u16 __padding;
CARDFileInfo(EMemoryCardPort port) : chan(port) {}
};
struct CCardFileInfo
{
struct Icon
{
ResId x0_id;
u32 x4_speed;
TLockedToken<CTexture> x8_tex;
Icon(ResId id, u32 speed, CSimplePool& sp, const CVParamTransfer& cv);
};
enum class EStatus
{
Standby,
Transferring,
Done
};
EStatus x0_status = EStatus::Standby;
CARDFileInfo x4_info;
std::string x18_name;
std::string x28_name2;
ResId x3c_bannerTex = -1;
std::experimental::optional<TLockedToken<CTexture>> x40_bannerTok;
rstl::reserved_vector<Icon, 8> x50_iconToks;
std::vector<u8> xf4_saveBuffer;
std::vector<u8> x104_cardBuffer;
CVParamTransfer m_texParam = {new TObjOwnerParam<u32>(SBIG('OTEX'))};
CCardFileInfo(EMemoryCardPort port, const std::string& name)
: x4_info(port), x18_name(name) {}
void LockBannerToken(ResId bannerTxtr, CSimplePool& sp);
void LockIconToken(ResId iconTxtr, u32 speed, CSimplePool& sp);
EMemoryCardPort GetCardPort() const { return x4_info.chan; }
int GetFileNo() const { return x4_info.fileNo; }
u32 CalculateBannerDataSize() const;
u32 CalculateTotalDataSize() const;
void BuildCardBuffer();
void WriteBannerData(CMemoryOutStream& out) const;
void WriteIconData(CMemoryOutStream& out) const;
ECardResult PumpCardTransfer();
ECardResult GetStatus(CARDStat& stat) const;
ECardResult CreateFile();
ECardResult Write();
ECardResult Close();
};
static CardProbeResults CardProbe(EMemoryCardPort port);
static ECardResult MountCard(EMemoryCardPort port);
static ECardResult CheckCard(EMemoryCardPort port);
@ -143,8 +208,11 @@ public:
static ECardResult GetSerialNo(EMemoryCardPort port, u64& serialOut);
static ECardResult GetResultCode(EMemoryCardPort port);
static ECardResult GetStatus(EMemoryCardPort port, int fileNo, CARDStat& statOut);
static ECardResult SetStatus(EMemoryCardPort port, int fileNo, const CARDStat& stat);
static ECardResult DeleteFile(EMemoryCardPort port, const char* name);
static ECardResult FastDeleteFile(EMemoryCardPort port, int fileNo);
static ECardResult Rename(EMemoryCardPort port, const char* oldName, const char* newName);
static ECardResult FormatCard(EMemoryCardPort port);
};
}

View File

@ -72,9 +72,7 @@ CFactoryFnReturn AnimSourceFactory(const SObjectTag& tag, CInputStream& in,
const CVParamTransfer& params,
CObjectReference* selfRef)
{
CSimplePool* sp = static_cast<CSimplePool*>(
static_cast<TObjOwnerParam<IObjectStore*>*>(
params.GetObj())->GetParam());
CSimplePool* sp = params.GetOwnedObj<CSimplePool*>();
return TToken<CAllFormatsAnimSource>::GetIObjObjectFor(
std::make_unique<CAllFormatsAnimSource>(in, *sp, tag));
}

View File

@ -22,8 +22,7 @@ CFactoryFnReturn CCharacterFactory::CDummyFactory::Build(const SObjectTag& tag,
CObjectReference* selfRef)
{
const CCharacterInfo& charInfo =
*static_cast<TObjOwnerParam<const CCharacterInfo*>&>(*params.GetObj()).GetParam();
const CCharacterInfo& charInfo = *params.GetOwnedObj<const CCharacterInfo*>();
switch (tag.type.toUint32() & 0x1)
{

View File

@ -284,7 +284,7 @@ FourCC CCollisionResponseData::UncookedResType()
CFactoryFnReturn FCollisionResponseDataFactory(const SObjectTag& tag, CInputStream& in, const CVParamTransfer& vparms)
{
CSimplePool* sp = static_cast<CSimplePool*>(static_cast<TObjOwnerParam<IObjectStore*>*>(vparms.GetObj())->GetParam());
CSimplePool* sp = vparms.GetOwnedObj<CSimplePool*>();
return TToken<CCollisionResponseData>::GetIObjObjectFor(std::unique_ptr<CCollisionResponseData>(new CCollisionResponseData(in, sp)));
}

View File

@ -9,6 +9,7 @@
#include "Graphics/CBooRenderer.hpp"
#include "Character/CSkinRules.hpp"
#include "GameGlobalObjects.hpp"
#include "CSimplePool.hpp"
#include <array>
namespace urde
@ -807,8 +808,8 @@ CFactoryFnReturn FModelFactory(const urde::SObjectTag& tag,
const urde::CVParamTransfer& vparms,
CObjectReference* selfRef)
{
IObjectStore* store = static_cast<TObjOwnerParam<IObjectStore*>*>(vparms.GetObj())->GetParam();
CFactoryFnReturn ret = TToken<CModel>::GetIObjObjectFor(std::make_unique<CModel>(std::move(in), len, store, selfRef));
CSimplePool* sp = vparms.GetOwnedObj<CSimplePool*>();
CFactoryFnReturn ret = TToken<CModel>::GetIObjObjectFor(std::make_unique<CModel>(std::move(in), len, sp, selfRef));
return ret;
}

View File

@ -21,6 +21,7 @@ class CTexture
boo::GraphicsDataToken m_booToken;
boo::ITexture* m_booTex;
boo::ITexture* m_paletteTex;
std::unique_ptr<u8[]> m_otex;
size_t ComputeMippedTexelCount();
size_t ComputeMippedBlockCountDXT1();
@ -39,18 +40,22 @@ class CTexture
void BuildC8(const void* data, size_t length);
public:
CTexture(std::unique_ptr<u8[]>&& in, u32 length);
CTexture(std::unique_ptr<u8[]>&& in, u32 length, bool otex);
enum class EClampMode
{
None,
One
};
ETexelFormat GetTexelFormat() const {return x0_fmt;}
ETexelFormat GetMemoryCardTexelFormat() const
{return x0_fmt == ETexelFormat::C8PC ? ETexelFormat::C8 : ETexelFormat::RGB5A3;}
u16 GetWidth() const {return x4_w;}
u16 GetHeight() const {return x6_h;}
void Load(int slot, EClampMode clamp) const;
boo::ITexture* GetBooTexture() {return m_booTex;}
boo::ITexture* GetPaletteTexture() {return m_paletteTex;}
std::unique_ptr<u8[]> BuildMemoryCardTex(u32& sizeOut, ETexelFormat& fmtOut,
std::unique_ptr<u8[]>& paletteOut) const;
};
CFactoryFnReturn FTextureFactory(const urde::SObjectTag& tag,

View File

@ -684,7 +684,7 @@ void CTexture::BuildC8(const void* data, size_t length)
});
}
CTexture::CTexture(std::unique_ptr<u8[]>&& in, u32 length)
CTexture::CTexture(std::unique_ptr<u8[]>&& in, u32 length, bool otex)
{
std::unique_ptr<u8[]> owned = std::move(in);
athena::io::MemoryReader r(owned.get(), length);
@ -737,6 +737,9 @@ CTexture::CTexture(std::unique_ptr<u8[]>&& in, u32 length)
default:
Log.report(logvisor::Fatal, "invalid texture type %d for boo", int(x0_fmt));
}
if (otex)
m_otex = std::move(owned);
}
void CTexture::Load(int slot, EClampMode clamp) const
@ -744,12 +747,125 @@ void CTexture::Load(int slot, EClampMode clamp) const
}
std::unique_ptr<u8[]> CTexture::BuildMemoryCardTex(u32& sizeOut, ETexelFormat& fmtOut,
std::unique_ptr<u8[]>& paletteOut) const
{
if (!m_otex)
Log.report(logvisor::Fatal, "MemoryCard TXTR not loaded with 'otex'");
size_t texelCount = x4_w * x6_h;
std::unique_ptr<u8[]> ret;
if (x0_fmt == ETexelFormat::RGBA8PC)
{
sizeOut = texelCount * 2;
fmtOut = ETexelFormat::RGB5A3;
ret.reset(new u8[sizeOut]);
u16* texel = reinterpret_cast<u16*>(ret.get());
int w = x4_w;
int h = x6_h;
const RGBA8* sourceMip = reinterpret_cast<const RGBA8*>(m_otex.get() + 12);
int bwidth = (w + 3) / 4;
int bheight = (h + 3) / 4;
for (int by=0 ; by<bheight ; ++by)
{
int baseY = by * 4;
for (int bx=0 ; bx<bwidth ; ++bx)
{
int baseX = bx * 4;
for (int y=0 ; y<4 ; ++y)
{
const RGBA8* source = sourceMip + (baseY + y) * w + baseX;
for (int x=0 ; x<4 ; ++x)
{
if (source[x].a == 0xff)
{
*texel++ = hecl::SBig(u16((source[x].r >> 3 << 10) |
(source[x].g >> 3 << 5) |
(source[x].b >> 3)));
}
else
{
*texel++ = hecl::SBig(u16((source[x].r >> 4 << 8) |
(source[x].g >> 4 << 4) |
(source[x].b >> 4) |
(source[x].a >> 5 << 12)));
}
}
}
}
}
}
else if (x0_fmt == ETexelFormat::C8PC)
{
sizeOut = texelCount;
fmtOut = ETexelFormat::C8;
ret.reset(new u8[sizeOut]);
paletteOut.reset(new u8[512]);
u8* texel = ret.get();
u16* paletteColors = reinterpret_cast<u16*>(paletteOut.get());
int w = x4_w;
int h = x6_h;
const u8* data = m_otex.get() + 12;
u32 nentries = hecl::SBig(*reinterpret_cast<const u32*>(data));
const RGBA8* paletteTexels = reinterpret_cast<const RGBA8*>(data + 4);
const u8* sourceMip = data + 4 + nentries * 4;
for (int i=0; i<256; ++i)
{
u16& color = paletteColors[i];
if (i < nentries)
color = 0;
else
{
const RGBA8& colorIn = paletteTexels[i];
if (colorIn.a == 0xff)
{
color = hecl::SBig(u16((colorIn.r >> 3 << 10) |
(colorIn.g >> 3 << 5) |
(colorIn.b >> 3)));
}
else
{
color = hecl::SBig(u16((colorIn.r >> 4 << 8) |
(colorIn.g >> 4 << 4) |
(colorIn.b >> 4) |
(colorIn.a >> 5 << 12)));
}
}
}
int bwidth = (w + 7) / 8;
int bheight = (h + 3) / 4;
for (int by=0 ; by<bheight ; ++by)
{
int baseY = by * 4;
for (int bx=0 ; bx<bwidth ; ++bx)
{
int baseX = bx * 8;
for (int y=0 ; y<4 ; ++y)
{
const u8* source = sourceMip + (baseY + y) * w + baseX;
for (int x=0 ; x<8 ; ++x)
*texel++ = source[x];
}
}
}
}
else
Log.report(logvisor::Fatal, "MemoryCard texture may only use RGBA8PC or C8PC format");
return ret;
}
CFactoryFnReturn FTextureFactory(const urde::SObjectTag& tag,
std::unique_ptr<u8[]>&& in, u32 len,
const urde::CVParamTransfer& vparms,
CObjectReference* selfRef)
{
return TToken<CTexture>::GetIObjObjectFor(std::make_unique<CTexture>(std::move(in), len));
return TToken<CTexture>::GetIObjObjectFor(std::make_unique<CTexture>(std::move(in), len,
vparms.GetOwnedObj<u32>() == SBIG('OTEX')));
}
}

View File

@ -184,7 +184,7 @@ std::unique_ptr<IObj> RGuiFrameFactoryInGame(const SObjectTag& tag, CInputStream
const CVParamTransfer& cvParms,
CObjectReference* selfRef)
{
CSimplePool* sp = static_cast<CSimplePool*>(static_cast<TObjOwnerParam<IObjectStore*>*>(cvParms.GetObj())->GetParam());
CSimplePool* sp = cvParms.GetOwnedObj<CSimplePool*>();
std::unique_ptr<CGuiFrame> frame(CGuiFrame::CreateFrame(tag.id, *g_GuiSys, in, sp));
return TToken<CGuiFrame>::GetIObjObjectFor(std::move(frame));
}

View File

@ -2,6 +2,7 @@
#include "CDrawStringOptions.hpp"
#include "CTextRenderBuffer.hpp"
#include "Graphics/CTexture.hpp"
#include "CSimplePool.hpp"
namespace urde
{
@ -195,8 +196,8 @@ void CRasterFont::GetSize(const CDrawStringOptions& opts, int& width, int& heigh
std::unique_ptr<IObj> FRasterFontFactory(const SObjectTag& tag, CInputStream& in, const CVParamTransfer& vparms,
CObjectReference* selfRef)
{
return TToken<CRasterFont>::GetIObjObjectFor(
std::make_unique<CRasterFont>(in, *static_cast<TObjOwnerParam<IObjectStore*>*>(vparms.GetObj())->GetParam()));
CSimplePool* sp = vparms.GetOwnedObj<CSimplePool*>();
return TToken<CRasterFont>::GetIObjObjectFor(std::make_unique<CRasterFont>(in, *sp));
}
}

View File

@ -13,6 +13,15 @@ public:
virtual ~IVParamObj() {}
};
template<class T>
class TObjOwnerParam : public IVParamObj
{
T m_param;
public:
TObjOwnerParam(T&& obj) : m_param(std::move(obj)) {}
T& GetParam() {return m_param;}
};
class CVParamTransfer
{
std::shared_ptr<IVParamObj> m_ref;
@ -23,16 +32,10 @@ public:
IVParamObj* GetObj() const {return m_ref.get();}
CVParamTransfer ShareTransferRef() {return CVParamTransfer(*this);}
static CVParamTransfer Null() {return CVParamTransfer();}
};
template <class T>
class TObjOwnerParam : public IVParamObj
{
T m_param;
public:
TObjOwnerParam(T&& obj) : m_param(std::move(obj)) {}
T& GetParam() {return m_param;}
T& GetOwnedObj() const {return static_cast<TObjOwnerParam<T>*>(GetObj())->GetParam();}
static CVParamTransfer Null() {return CVParamTransfer();}
};
}

View File

@ -7,9 +7,21 @@ namespace urde
namespace MP1
{
static const char* SaveFileNames[] =
{
"MetroidPrime A",
"MetroidPrime B"
};
using ECardResult = CMemoryCardSys::ECardResult;
using EMemoryCardPort = CMemoryCardSys::EMemoryCardPort;
ECardResult CMemoryCardDriver::SFileInfo::Open()
{
//CARDOpen(GetFileCardPort(), x14_name.data(), &x0_fileInfo);
return ECardResult::CARD_RESULT_READY;
}
ECardResult CMemoryCardDriver::SFileInfo::Close()
{
auto backup = GetFileCardPort();
@ -19,6 +31,20 @@ ECardResult CMemoryCardDriver::SFileInfo::Close()
return result;
}
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;
}
ECardResult CMemoryCardDriver::SFileInfo::TryFileRead()
{
ECardResult res = CMemoryCardSys::GetResultCode(GetFileCardPort());
@ -124,13 +150,13 @@ CMemoryCardDriver::SFileInfo::SFileInfo(EMemoryCardPort port,
}
CMemoryCardDriver::CMemoryCardDriver(EMemoryCardPort cardPort, ResId saveBanner,
ResId saveIcon0, ResId saveIcon1, bool mergePersistent)
ResId saveIcon0, ResId saveIcon1, bool importPersistent)
: x0_cardPort(cardPort), x4_saveBanner(saveBanner),
x8_saveIcon0(saveIcon0), xc_saveIcon1(saveIcon1), x19d_doMergePersistent(mergePersistent)
x8_saveIcon0(saveIcon0), xc_saveIcon1(saveIcon1), x19d_doImportPersistent(importPersistent)
{
x100_mcFileInfos.reserve(2);
x100_mcFileInfos.emplace_back(0, SFileInfo(x0_cardPort, "MetroidPrime A"));
x100_mcFileInfos.emplace_back(0, SFileInfo(x0_cardPort, "MetroidPrime B"));
x100_mcFileInfos.emplace_back(0, SFileInfo(x0_cardPort, SaveFileNames[0]));
x100_mcFileInfos.emplace_back(0, SFileInfo(x0_cardPort, SaveFileNames[1]));
}
void CMemoryCardDriver::FinishedLoading()
@ -152,7 +178,7 @@ void CMemoryCardDriver::FinishedLoading2()
x14_error = EError::Seven;
return;
}
x10_state = EState::Five;
x10_state = EState::CardNeedsMount;
MountCard();
break;
case ECardResult::CARD_RESULT_BUSY:
@ -169,13 +195,13 @@ void CMemoryCardDriver::FinishedLoading2()
void CMemoryCardDriver::NoCardFound()
{
x10_state = EState::Two;
x10_state = EState::NoCard;
static_cast<CMain*>(g_Main)->SetCardInserted(false);
}
void CMemoryCardDriver::MountCard()
{
x10_state = EState::TwentySix;
x10_state = EState::CardMount;
x14_error = EError::Zero;
ECardResult result = CMemoryCardSys::MountCard(x0_cardPort);
if (result != ECardResult::CARD_RESULT_READY)
@ -229,22 +255,31 @@ void CMemoryCardDriver::ReadFinished()
for (int i=0 ; i<3 ; ++i)
xe4_fileSlots[i] = LoadSaveFile(r);
if (x19d_doMergePersistent)
MergePersistentOptions();
if (x19d_doImportPersistent)
ImportPersistentOptions();
}
void CMemoryCardDriver::MergePersistentOptions()
void CMemoryCardDriver::ImportPersistentOptions()
{
CBitStreamReader r(x30_systemData, 174);
CPersistentOptions opts(r);
g_GameState->MergePersistentOptions(opts);
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);
}
void CMemoryCardDriver::DeleteFile()
{
x14_error = EError::Zero;
x10_state = EState::Thirty;
SFileInfo& fileInfo = x100_mcFileInfos[bool(x194_fileIdx)].second;
SFileInfo& fileInfo = x100_mcFileInfos[!bool(x194_fileIdx)].second;
ECardResult result = CMemoryCardSys::FastDeleteFile(x0_cardPort, fileInfo.GetFileNo());
if (result != ECardResult::CARD_RESULT_READY)
Case30(result);
@ -261,11 +296,11 @@ void CMemoryCardDriver::Case26(ECardResult result)
switch (result)
{
case ECardResult::CARD_RESULT_READY:
x10_state = EState::Six;
x10_state = EState::CardMountDone;
CheckCard();
break;
case ECardResult::CARD_RESULT_BROKEN:
x10_state = EState::Six;
x10_state = EState::CardMountDone;
x14_error = EError::One;
CheckCard();
break;
@ -280,7 +315,7 @@ void CMemoryCardDriver::Case27(ECardResult result)
switch (result)
{
case ECardResult::CARD_RESULT_READY:
x10_state = EState::Seven;
x10_state = EState::SelectCardFile;
if (!GetCardFreeBytes())
return;
if (CMemoryCardSys::GetSerialNo(x0_cardPort, x28_cardSerial) == ECardResult::CARD_RESULT_READY)
@ -301,14 +336,14 @@ 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)
if (x100_mcFileInfos[!bool(x194_fileIdx)].first == 3)
{
x10_state = EState::Seventeen;
GoTo28();
}
else
{
x10_state = EState::Seven;
x10_state = EState::SelectCardFile;
if (!GetCardFreeBytes())
return;
GoTo17();
@ -330,10 +365,10 @@ void CMemoryCardDriver::Case29(ECardResult result)
return;
}
u32 fileIdx = bool(x194_fileIdx);
u32 fileIdx = !bool(x194_fileIdx);
if (readRes == ECardResult::CARD_RESULT_READY)
{
x10_state = EState::One;
x10_state = EState::Ready;
ReadFinished();
u32 fileId = x100_mcFileInfos[fileIdx].first;
if (fileId == 1)
@ -348,7 +383,7 @@ void CMemoryCardDriver::Case29(ECardResult result)
x100_mcFileInfos[x194_fileIdx].first = 3;
if (x100_mcFileInfos[fileIdx].first == 2)
{
x10_state = EState::Seven;
x10_state = EState::SelectCardFile;
GoTo17();
}
else
@ -364,52 +399,347 @@ void CMemoryCardDriver::Case29(ECardResult result)
void CMemoryCardDriver::Case30(ECardResult result)
{
if (result == ECardResult::CARD_RESULT_READY)
{
x10_state = EState::Ready;
if (GetCardFreeBytes())
CheckCardCapacity();
}
else
HandleCardError(result, EState::Sixteen);
}
void CMemoryCardDriver::Case31(ECardResult result)
{
if (result == ECardResult::CARD_RESULT_READY)
{
x10_state = EState::WillWrite;
GoTo32();
}
else
HandleCardError(result, EState::Eighteen);
}
void CMemoryCardDriver::Case32(ECardResult result)
{
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);
}
void CMemoryCardDriver::Case33(ECardResult result)
{
if (result == ECardResult::CARD_RESULT_READY)
{
x10_state = EState::Nine;
GoTo34();
}
else
HandleCardError(result, EState::Twenty);
}
void CMemoryCardDriver::Case34(ECardResult result)
{
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);
}
void CMemoryCardDriver::Case35(ECardResult result)
{
if (result == ECardResult::CARD_RESULT_READY)
{
x10_state = EState::Eleven;
if (GetCardFreeBytes())
GoTo36();
}
else
HandleCardError(result, EState::TwentyTwo);
}
void CMemoryCardDriver::Case36(ECardResult result)
{
if (result == ECardResult::CARD_RESULT_READY)
{
x10_state = EState::RuntimeBackup;
WriteBackupBuf();
}
else
HandleCardError(result, EState::TwentyThree);
}
void CMemoryCardDriver::Case37(ECardResult result)
{
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);
}
void CMemoryCardDriver::GoTo17()
{
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;
}
}
}
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;
}
}
void CMemoryCardDriver::GoTo28()
{
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;
}
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);
}
bool CMemoryCardDriver::GetCardFreeBytes()
@ -451,7 +781,7 @@ void CMemoryCardDriver::Update()
if (result.x0_error == ECardResult::CARD_RESULT_NOCARD)
{
if (x10_state != EState::Two)
if (x10_state != EState::NoCard)
NoCardFound();
static_cast<CMain*>(g_Main)->SetCardInserted(false);
return;
@ -474,7 +804,7 @@ void CMemoryCardDriver::Update()
switch (x10_state)
{
case EState::TwentySix:
case EState::CardMount:
Case26(resultCode);
break;
case EState::TwentySeven:
@ -492,7 +822,7 @@ void CMemoryCardDriver::Update()
case EState::ThirtyOne:
Case31(resultCode);
break;
case EState::ThirtyTwo:
case EState::Write:
Case32(resultCode);
break;
case EState::ThirtyThree:
@ -507,7 +837,7 @@ void CMemoryCardDriver::Update()
case EState::ThirtySix:
Case36(resultCode);
break;
case EState::ThirtySeven:
case EState::CardFormat:
Case37(resultCode);
break;
default: break;

View File

@ -15,30 +15,44 @@ class CMemoryCardDriver
public:
enum class EState
{
Zero,
One = 1,
Two = 2,
Five = 5,
Six = 6,
Seven = 7,
Initial,
Ready = 1,
NoCard = 2,
RuntimeBackup = 3,
CardFormatted = 4,
CardNeedsMount = 5,
CardMountDone = 6,
SelectCardFile = 7,
WillWrite = 8,
Nine = 9,
Ten = 10,
Eleven = 11,
Twelve = 12,
Thirteen = 13,
Fourteen = 14,
Fifteen = 15,
Sixteen = 16,
Seventeen = 17,
TwentyFive = 26,
TwentySix = 26,
Eighteen = 18,
Nineteen = 19,
Twenty = 20,
TwentyOne = 21,
TwentyTwo = 22,
TwentyThree = 23,
CardFormatBroken = 24,
TwentyFive = 25,
CardMount = 26,
TwentySeven = 27,
TwentyEight = 28,
TwentyNine = 29,
Thirty = 30,
ThirtyOne = 31,
ThirtyTwo = 32,
Write = 32,
ThirtyThree = 33,
ThirtyFour = 34,
ThirtyFive = 35,
ThirtySix = 36,
ThirtySeven = 37
CardFormat = 37
};
enum class EError
@ -72,9 +86,11 @@ private:
std::vector<u8> x24_saveFileData;
std::vector<u8> x34_saveData;
SFileInfo(CMemoryCardSys::EMemoryCardPort cardPort, const std::string& name);
CMemoryCardSys::ECardResult Open();
CMemoryCardSys::ECardResult Close();
CMemoryCardSys::EMemoryCardPort GetFileCardPort() const { return x0_fileInfo.x0_cardPort; }
int GetFileNo() const { return x0_fileInfo.x4_fileNo; }
CMemoryCardSys::ECardResult StartRead();
CMemoryCardSys::ECardResult TryFileRead();
CMemoryCardSys::ECardResult FileRead();
CMemoryCardSys::ECardResult GetSaveDataOffset(u32& offOut);
@ -99,7 +115,7 @@ private:
ResId x4_saveBanner;
ResId x8_saveIcon0;
ResId xc_saveIcon1;
EState x10_state = EState::Zero;
EState x10_state = EState::Initial;
EError x14_error = EError::Zero;
s32 x18_cardFreeBytes = 0;
s32 x1c_cardFreeFiles = 0;
@ -110,13 +126,13 @@ private:
std::unique_ptr<SGameFileSlot> xe4_fileSlots[3];
std::vector<std::pair<u32, SFileInfo>> x100_mcFileInfos;
u32 x194_fileIdx = -1;
u32 x198_ = 0;
std::unique_ptr<CMemoryCardSys::CCardFileInfo> x198_fileInfo;
bool x19c_ = false;
bool x19d_doMergePersistent;
bool x19d_doImportPersistent;
public:
CMemoryCardDriver(CMemoryCardSys::EMemoryCardPort cardPort, ResId saveBanner,
ResId saveIcon0, ResId saveIcon1, bool flag);
ResId saveIcon0, ResId saveIcon1, bool importPersistent);
void FinishedLoading();
void FinishedLoading2();
void NoCardFound();
@ -127,7 +143,8 @@ public:
static SSaveHeader LoadSaveHeader(CMemoryInStream& in);
static std::unique_ptr<SGameFileSlot> LoadSaveFile(CMemoryInStream& in);
void ReadFinished();
void MergePersistentOptions();
void ImportPersistentOptions();
void ExportPersistentOptions();
void DeleteFile();
void CheckCardCapacity();
@ -146,14 +163,24 @@ public:
void GoTo17();
void GoTo28();
void GoTo29();
void GoTo32();
void GoTo33();
void GoTo34();
void GoTo35();
void GoTo36();
void GoTo37();
void ClearFileInfo() { x198_fileInfo.reset(); }
void InitializeFileInfo();
void WriteBackupBuf();
bool GetCardFreeBytes();
void HandleCardError(CMemoryCardSys::ECardResult result, EState state);
void Update();
static bool InCardInsertedRange(EState v)
{
return v >= EState::TwentySix && v <= EState::ThirtySeven;
return v >= EState::CardMount && v <= EState::CardFormat;
}
static bool InRange2(EState v)

View File

@ -59,7 +59,7 @@ bool CSaveUI::PumpLoad()
CSaveUI::UIType CSaveUI::SelectUIType() const
{
if (x6c_cardDriver->x10_state == EState::Two)
if (x6c_cardDriver->x10_state == EState::NoCard)
return UIType::Three;
switch (x10_uiType)
@ -78,7 +78,7 @@ CSaveUI::UIType CSaveUI::SelectUIType() const
return UIType::One;
}
if (x6c_cardDriver->x10_state == EState::One)
if (x6c_cardDriver->x10_state == EState::Ready)
{
if (x6c_cardDriver->x14_error == CMemoryCardDriver::EError::Six)
return UIType::Twelve;

View File

@ -139,7 +139,7 @@ void CDecalDataFactory::GetQuadDecalInfo(CInputStream& in, CSimplePool* resPool,
CFactoryFnReturn FDecalDataFactory(const SObjectTag &tag, CInputStream &in, const CVParamTransfer &vparms)
{
CSimplePool* sp = static_cast<CSimplePool*>(static_cast<TObjOwnerParam<IObjectStore*>*>(vparms.GetObj())->GetParam());
CSimplePool* sp = vparms.GetOwnedObj<CSimplePool*>();
return TToken<CDecalDescription>::GetIObjObjectFor(std::unique_ptr<CDecalDescription>(CDecalDataFactory::GetGeneratorDesc(in, sp)));
}

View File

@ -1160,7 +1160,7 @@ CFactoryFnReturn FParticleFactory(const SObjectTag& tag, CInputStream& in,
const CVParamTransfer& vparms,
CObjectReference* selfRef)
{
CSimplePool* sp = static_cast<CSimplePool*>(static_cast<TObjOwnerParam<IObjectStore*>*>(vparms.GetObj())->GetParam());
CSimplePool* sp = vparms.GetOwnedObj<CSimplePool*>();
return TToken<CGenDescription>::GetIObjObjectFor(std::unique_ptr<CGenDescription>(CParticleDataFactory::GetGeneratorDesc(in, sp)));
}

View File

@ -134,7 +134,7 @@ void CParticleElectricDataFactory::LoadELSMTokens(CElectricDescription* desc)
CFactoryFnReturn FParticleElectricDataFactory(const SObjectTag &tag, CInputStream &in, const CVParamTransfer &vparms)
{
CSimplePool* sp = static_cast<CSimplePool*>(static_cast<TObjOwnerParam<IObjectStore*>*>(vparms.GetObj())->GetParam());
CSimplePool* sp = vparms.GetOwnedObj<CSimplePool*>();
return TToken<CElectricDescription>::GetIObjObjectFor(std::unique_ptr<CElectricDescription>(CParticleElectricDataFactory::GetGeneratorDesc(in, sp)));
}

View File

@ -139,7 +139,7 @@ bool CParticleSwooshDataFactory::CreateWPSM(CSwooshDescription* desc, CInputStre
CFactoryFnReturn FParticleSwooshDataFactory(const SObjectTag &tag, CInputStream &in, const CVParamTransfer &vparms)
{
CSimplePool* sp = static_cast<CSimplePool*>(static_cast<TObjOwnerParam<IObjectStore*>*>(vparms.GetObj())->GetParam());
CSimplePool* sp = vparms.GetOwnedObj<CSimplePool*>();
return TToken<CSwooshDescription>::GetIObjObjectFor(std::unique_ptr<CSwooshDescription>(CParticleSwooshDataFactory::GetGeneratorDesc(in, sp)));
}

View File

@ -166,7 +166,7 @@ bool CProjectileWeaponDataFactory::CreateWPSM(CWeaponDescription* desc, CInputSt
CFactoryFnReturn FProjectileWeaponDataFactory(const SObjectTag& tag, CInputStream& in, const CVParamTransfer& vparms)
{
CSimplePool* sp = static_cast<CSimplePool*>(static_cast<TObjOwnerParam<IObjectStore*>*>(vparms.GetObj())->GetParam());
CSimplePool* sp = vparms.GetOwnedObj<CSimplePool*>();
return TToken<CWeaponDescription>::GetIObjObjectFor(std::unique_ptr<CWeaponDescription>(CProjectileWeaponDataFactory::GetGeneratorDesc(in, sp)));
}