mirror of https://github.com/AxioDL/metaforce.git
Work on CMemoryCardDriver
This commit is contained in:
parent
c92223301c
commit
d7f79d6ec3
|
@ -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);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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(),
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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++)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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)));
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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')));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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();}
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)));
|
||||
}
|
||||
|
||||
|
|
|
@ -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)));
|
||||
}
|
||||
|
||||
|
|
|
@ -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)));
|
||||
}
|
||||
|
||||
|
|
|
@ -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)));
|
||||
}
|
||||
|
||||
|
|
|
@ -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)));
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue