Better null-tag handling; integrate CSaveWorld and CMapWorld loading

This commit is contained in:
Jack Andersen 2016-10-08 10:32:36 -10:00
parent 647643f579
commit f7f5066038
14 changed files with 85 additions and 9 deletions

View File

@ -225,6 +225,7 @@ bool ProjectResourceFactoryBase::AddFileToIndex(const hecl::ProjectPath& path,
SObjectTag pathTag = BuildTagFromPath(subPath, m_backgroundBlender); SObjectTag pathTag = BuildTagFromPath(subPath, m_backgroundBlender);
m_tagToPath[pathTag] = subPath; m_tagToPath[pathTag] = subPath;
m_pathToTag[subPath.hash()] = pathTag; m_pathToTag[subPath.hash()] = pathTag;
WriteTag(cacheWriter, pathTag, subPath);
#if DUMP_CACHE_FILL #if DUMP_CACHE_FILL
DumpCacheAdd(pathTag, subPath); DumpCacheAdd(pathTag, subPath);
#endif #endif
@ -233,6 +234,7 @@ bool ProjectResourceFactoryBase::AddFileToIndex(const hecl::ProjectPath& path,
pathTag = BuildTagFromPath(subPath, m_backgroundBlender); pathTag = BuildTagFromPath(subPath, m_backgroundBlender);
m_tagToPath[pathTag] = subPath; m_tagToPath[pathTag] = subPath;
m_pathToTag[subPath.hash()] = pathTag; m_pathToTag[subPath.hash()] = pathTag;
WriteTag(cacheWriter, pathTag, subPath);
#if DUMP_CACHE_FILL #if DUMP_CACHE_FILL
DumpCacheAdd(pathTag, subPath); DumpCacheAdd(pathTag, subPath);
#endif #endif
@ -610,6 +612,9 @@ std::unique_ptr<urde::IObj> ProjectResourceFactoryBase::Build(const urde::SObjec
const urde::CVParamTransfer& paramXfer, const urde::CVParamTransfer& paramXfer,
CObjectReference* selfRef) CObjectReference* selfRef)
{ {
if ((tag.id & 0xffffffff) == 0xffffffff || !tag.id)
Log.report(logvisor::Fatal, "attempted to access null id");
const hecl::ProjectPath* resPath = nullptr; const hecl::ProjectPath* resPath = nullptr;
if (!WaitForTagReady(tag, resPath)) if (!WaitForTagReady(tag, resPath))
return {}; return {};
@ -673,11 +678,17 @@ void ProjectResourceFactoryBase::BuildAsync(const urde::SObjectTag& tag,
urde::IObj** objOut, urde::IObj** objOut,
CObjectReference* selfRef) CObjectReference* selfRef)
{ {
if ((tag.id & 0xffffffff) == 0xffffffff || !tag.id)
Log.report(logvisor::Fatal, "attempted to access null id");
BuildAsyncInternal(tag, paramXfer, objOut, selfRef); BuildAsyncInternal(tag, paramXfer, objOut, selfRef);
} }
u32 ProjectResourceFactoryBase::ResourceSize(const SObjectTag& tag) u32 ProjectResourceFactoryBase::ResourceSize(const SObjectTag& tag)
{ {
if ((tag.id & 0xffffffff) == 0xffffffff || !tag.id)
Log.report(logvisor::Fatal, "attempted to access null id");
/* Ensure resource at requested path is indexed and not cooking */ /* Ensure resource at requested path is indexed and not cooking */
const hecl::ProjectPath* resPath = nullptr; const hecl::ProjectPath* resPath = nullptr;
if (!WaitForTagReady(tag, resPath)) if (!WaitForTagReady(tag, resPath))
@ -695,6 +706,8 @@ std::shared_ptr<ProjectResourceFactoryBase::AsyncTask>
ProjectResourceFactoryBase::LoadResourceAsync(const urde::SObjectTag& tag, ProjectResourceFactoryBase::LoadResourceAsync(const urde::SObjectTag& tag,
std::unique_ptr<u8[]>& target) std::unique_ptr<u8[]>& target)
{ {
if ((tag.id & 0xffffffff) == 0xffffffff || !tag.id)
Log.report(logvisor::Fatal, "attempted to access null id");
if (m_asyncLoadList.find(tag) != m_asyncLoadList.end()) if (m_asyncLoadList.find(tag) != m_asyncLoadList.end())
return {}; return {};
return m_asyncLoadList.emplace(std::make_pair(tag, std::make_shared<AsyncTask>(*this, tag, target))).first->second; return m_asyncLoadList.emplace(std::make_pair(tag, std::make_shared<AsyncTask>(*this, tag, target))).first->second;
@ -705,6 +718,8 @@ ProjectResourceFactoryBase::LoadResourcePartAsync(const urde::SObjectTag& tag,
u32 size, u32 off, u32 size, u32 off,
std::unique_ptr<u8[]>& target) std::unique_ptr<u8[]>& target)
{ {
if ((tag.id & 0xffffffff) == 0xffffffff || !tag.id)
Log.report(logvisor::Fatal, "attempted to access null id");
if (m_asyncLoadList.find(tag) != m_asyncLoadList.end()) if (m_asyncLoadList.find(tag) != m_asyncLoadList.end())
return {}; return {};
return m_asyncLoadList.emplace(std::make_pair(tag, std::make_shared<AsyncTask>(*this, tag, target, size, off))).first->second; return m_asyncLoadList.emplace(std::make_pair(tag, std::make_shared<AsyncTask>(*this, tag, target, size, off))).first->second;
@ -712,6 +727,9 @@ ProjectResourceFactoryBase::LoadResourcePartAsync(const urde::SObjectTag& tag,
std::unique_ptr<u8[]> ProjectResourceFactoryBase::LoadResourceSync(const urde::SObjectTag& tag) std::unique_ptr<u8[]> ProjectResourceFactoryBase::LoadResourceSync(const urde::SObjectTag& tag)
{ {
if ((tag.id & 0xffffffff) == 0xffffffff || !tag.id)
Log.report(logvisor::Fatal, "attempted to access null id");
/* Ensure resource at requested path is indexed and not cooking */ /* Ensure resource at requested path is indexed and not cooking */
const hecl::ProjectPath* resPath = nullptr; const hecl::ProjectPath* resPath = nullptr;
if (!WaitForTagReady(tag, resPath)) if (!WaitForTagReady(tag, resPath))
@ -728,6 +746,9 @@ std::unique_ptr<u8[]> ProjectResourceFactoryBase::LoadResourceSync(const urde::S
std::unique_ptr<u8[]> ProjectResourceFactoryBase::LoadResourcePartSync(const urde::SObjectTag& tag, std::unique_ptr<u8[]> ProjectResourceFactoryBase::LoadResourcePartSync(const urde::SObjectTag& tag,
u32 size, u32 off) u32 size, u32 off)
{ {
if ((tag.id & 0xffffffff) == 0xffffffff || !tag.id)
Log.report(logvisor::Fatal, "attempted to access null id");
/* Ensure resource at requested path is indexed and not cooking */ /* Ensure resource at requested path is indexed and not cooking */
const hecl::ProjectPath* resPath = nullptr; const hecl::ProjectPath* resPath = nullptr;
if (!WaitForTagReady(tag, resPath)) if (!WaitForTagReady(tag, resPath))
@ -750,6 +771,9 @@ void ProjectResourceFactoryBase::CancelBuild(const urde::SObjectTag& tag)
bool ProjectResourceFactoryBase::CanBuild(const urde::SObjectTag& tag) bool ProjectResourceFactoryBase::CanBuild(const urde::SObjectTag& tag)
{ {
if ((tag.id & 0xffffffff) == 0xffffffff || !tag.id)
Log.report(logvisor::Fatal, "attempted to access null id");
const hecl::ProjectPath* resPath = nullptr; const hecl::ProjectPath* resPath = nullptr;
if (!WaitForTagReady(tag, resPath)) if (!WaitForTagReady(tag, resPath))
return false; return false;
@ -791,6 +815,9 @@ const urde::SObjectTag* ProjectResourceFactoryBase::GetResourceIdByName(const ch
FourCC ProjectResourceFactoryBase::GetResourceTypeById(ResId id) const FourCC ProjectResourceFactoryBase::GetResourceTypeById(ResId id) const
{ {
if ((id & 0xffffffff) == 0xffffffff || !id)
Log.report(logvisor::Fatal, "attempted to access null id");
std::unique_lock<std::mutex> lk(const_cast<ProjectResourceFactoryBase*>(this)->m_backgroundIndexMutex); std::unique_lock<std::mutex> lk(const_cast<ProjectResourceFactoryBase*>(this)->m_backgroundIndexMutex);
SObjectTag searchTag = {FourCC(), id}; SObjectTag searchTag = {FourCC(), id};
auto search = m_tagToPath.find(searchTag); auto search = m_tagToPath.find(searchTag);

View File

@ -17,6 +17,8 @@
#include "Runtime/Character/CAllFormatsAnimSource.hpp" #include "Runtime/Character/CAllFormatsAnimSource.hpp"
#include "Runtime/Character/CAnimPOIData.hpp" #include "Runtime/Character/CAnimPOIData.hpp"
#include "Runtime/Collision/CCollidableOBBTreeGroup.hpp" #include "Runtime/Collision/CCollidableOBBTreeGroup.hpp"
#include "Runtime/CSaveWorld.hpp"
#include "Runtime/AutoMapper/CMapWorld.hpp"
#include "Audio/CAudioGroupSet.hpp" #include "Audio/CAudioGroupSet.hpp"
#include "Runtime/CDependencyGroup.hpp" #include "Runtime/CDependencyGroup.hpp"
#include "DataSpec/DNACommon/TXTR.hpp" #include "DataSpec/DNACommon/TXTR.hpp"
@ -48,6 +50,8 @@ ProjectResourceFactoryMP1::ProjectResourceFactoryMP1(hecl::ClientProcess& client
m_factoryMgr.AddFactory(FOURCC('AGSC'), FMemFactoryFunc(FAudioGroupSetDataFactory)); m_factoryMgr.AddFactory(FOURCC('AGSC'), FMemFactoryFunc(FAudioGroupSetDataFactory));
m_factoryMgr.AddFactory(FOURCC('STRG'), FFactoryFunc(FStringTableFactory)); m_factoryMgr.AddFactory(FOURCC('STRG'), FFactoryFunc(FStringTableFactory));
m_factoryMgr.AddFactory(FOURCC('HINT'), FFactoryFunc(FHintFactory)); m_factoryMgr.AddFactory(FOURCC('HINT'), FFactoryFunc(FHintFactory));
m_factoryMgr.AddFactory(FOURCC('SAVW'), FFactoryFunc(FSaveWorldFactory));
m_factoryMgr.AddFactory(FOURCC('MAPW'), FFactoryFunc(FMapWorldFactory));
} }
void ProjectResourceFactoryMP1::IndexMP1Resources(hecl::Database::Project& proj) void ProjectResourceFactoryMP1::IndexMP1Resources(hecl::Database::Project& proj)

View File

@ -2,6 +2,11 @@
namespace urde namespace urde
{ {
CMapWorld::CMapWorld(CInputStream& in)
{
}
u32 CMapWorld::GetNumAreas() const u32 CMapWorld::GetNumAreas() const
{ {
return x0_areas.size(); return x0_areas.size();
@ -81,4 +86,10 @@ void CMapWorld::ClearTraversedFlags() const
} }
CFactoryFnReturn FMapWorldFactory(const SObjectTag& tag, CInputStream& in, const CVParamTransfer& param,
CObjectReference* selfRef)
{
return TToken<CMapWorld>::GetIObjObjectFor(std::make_unique<CMapWorld>(in));
}
} }

View File

@ -105,6 +105,9 @@ public:
void ClearTraversedFlags() const; void ClearTraversedFlags() const;
}; };
CFactoryFnReturn FMapWorldFactory(const SObjectTag& tag, CInputStream& in, const CVParamTransfer& param,
CObjectReference* selfRef);
} }
#endif // __URDE_CMAPWORLD_HPP__ #endif // __URDE_CMAPWORLD_HPP__

View File

@ -9,6 +9,15 @@
namespace urde namespace urde
{ {
CWorldState::CWorldState(ResId id)
: x0_mlvlId(id), x4_areaId(0)
{
x8_relayTracker = std::make_shared<CRelayTracker>();
xc_mapWorldInfo = std::make_shared<CMapWorldInfo>();
x10_ = -1;
x14_ = std::make_shared<CWorldSomethingState>();
}
CWorldState::CWorldState(CBitStreamReader& reader, ResId mlvlId, const CSaveWorld& saveWorld) CWorldState::CWorldState(CBitStreamReader& reader, ResId mlvlId, const CSaveWorld& saveWorld)
: x0_mlvlId(mlvlId) : x0_mlvlId(mlvlId)
{ {

View File

@ -20,6 +20,7 @@ class CWorldSomethingState
u32 x10_bitCount = 0; u32 x10_bitCount = 0;
std::vector<u32> x14_; std::vector<u32> x14_;
public: public:
CWorldSomethingState() = default;
CWorldSomethingState(CBitStreamReader& reader, const CSaveWorld& saveWorld) CWorldSomethingState(CBitStreamReader& reader, const CSaveWorld& saveWorld)
{ {
u32 bitCount = reader.ReadEncoded(10); u32 bitCount = reader.ReadEncoded(10);
@ -47,7 +48,7 @@ class CWorldState
u32 x10_; u32 x10_;
std::shared_ptr<CWorldSomethingState> x14_; std::shared_ptr<CWorldSomethingState> x14_;
public: public:
CWorldState(ResId id) : x0_mlvlId(id) {} CWorldState(ResId id);
CWorldState(CBitStreamReader& reader, ResId mlvlId, const CSaveWorld& saveWorld); CWorldState(CBitStreamReader& reader, ResId mlvlId, const CSaveWorld& saveWorld);
ResId GetWorldAssetId() const {return x0_mlvlId;} ResId GetWorldAssetId() const {return x0_mlvlId;}
void SetAreaId(TAreaId aid) { x4_areaId = aid; } void SetAreaId(TAreaId aid) { x4_areaId = aid; }

View File

@ -54,6 +54,7 @@ bool CSaveWorldIntermediate::InitializePump()
CMemoryCardSys::CMemoryCardSys() CMemoryCardSys::CMemoryCardSys()
{ {
x0_hints = g_SimplePool->GetObj("HINT_Hints");
xc_memoryWorlds.reserve(16); xc_memoryWorlds.reserve(16);
x1c_worldInter.emplace(); x1c_worldInter.emplace();
x1c_worldInter->reserve(16); x1c_worldInter->reserve(16);
@ -81,6 +82,8 @@ bool CMemoryCardSys::InitializePump()
for (const auto& world : xc_memoryWorlds) for (const auto& world : xc_memoryWorlds)
{ {
const CSaveWorldMemory& wld = world.second; const CSaveWorldMemory& wld = world.second;
if (!wld.GetWorldName())
continue;
if (!wld.GetWorldName().IsLoaded() || if (!wld.GetWorldName().IsLoaded() ||
!wld.GetWorldName().GetObj()) !wld.GetWorldName().GetObj())
return false; return false;

View File

@ -18,7 +18,7 @@ class CSaveWorldMemory
ResId x0_strgId = -1; ResId x0_strgId = -1;
ResId x4_savwId = -1; ResId x4_savwId = -1;
u32 x8_areaCount; u32 x8_areaCount;
std::vector<TAreaId> xc_areaIds; /* 4 byte element */ std::vector<ResId> xc_areaIds; /* 4 byte element */
std::vector<u32> x1c_; /* 16 byte element */ std::vector<u32> x1c_; /* 16 byte element */
TLockedToken<CStringTable> x2c_worldName; /* used to be optional */ TLockedToken<CStringTable> x2c_worldName; /* used to be optional */
TLockedToken<CSaveWorld> x3c_saveWorld; /* used to be optional */ TLockedToken<CSaveWorld> x3c_saveWorld; /* used to be optional */
@ -34,10 +34,10 @@ public:
class CSaveWorldIntermediate class CSaveWorldIntermediate
{ {
friend class CMemoryCardSys; friend class CMemoryCardSys;
u32 x0_mlvlId; ResId x0_mlvlId;
u32 x4_strgId; ResId x4_strgId;
u32 x8_savwId; ResId x8_savwId;
std::vector<TAreaId> xc_areaIds; std::vector<ResId> xc_areaIds;
std::vector<u32> x1c_; std::vector<u32> x1c_;
std::unique_ptr<CDummyWorld> x2c_dummyWorld; std::unique_ptr<CDummyWorld> x2c_dummyWorld;
TLockedToken<CSaveWorld> x34_saveWorld; /* Used to be auto_ptr */ TLockedToken<CSaveWorld> x34_saveWorld; /* Used to be auto_ptr */

View File

@ -1,4 +1,5 @@
#include "CSaveWorld.hpp" #include "CSaveWorld.hpp"
#include "CToken.hpp"
namespace urde namespace urde
{ {
@ -98,4 +99,10 @@ s32 CSaveWorld::GetDoorIndex(const TEditorId &id) const
return x34_doors.begin() - it; return x34_doors.begin() - it;
} }
CFactoryFnReturn FSaveWorldFactory(const SObjectTag& tag, CInputStream& in, const CVParamTransfer& param,
CObjectReference* selfRef)
{
return TToken<CSaveWorld>::GetIObjObjectFor(std::make_unique<CSaveWorld>(in));
}
} }

View File

@ -3,6 +3,7 @@
#include "RetroTypes.hpp" #include "RetroTypes.hpp"
#include "DNACommon/SAVWCommon.hpp" #include "DNACommon/SAVWCommon.hpp"
#include "CFactoryMgr.hpp"
namespace urde namespace urde
{ {
@ -43,6 +44,10 @@ public:
u32 GetDoorCount() const; u32 GetDoorCount() const;
s32 GetDoorIndex(const TEditorId &id) const; s32 GetDoorIndex(const TEditorId &id) const;
}; };
CFactoryFnReturn FSaveWorldFactory(const SObjectTag& tag, CInputStream& in, const CVParamTransfer& param,
CObjectReference* selfRef);
} }
#endif // __URDE_CSAVEWORLD_HPP__ #endif // __URDE_CSAVEWORLD_HPP__

View File

@ -11,6 +11,9 @@ CSimplePool::CSimplePool(IFactory& factory)
CToken CSimplePool::GetObj(const SObjectTag& tag, const CVParamTransfer& paramXfer) CToken CSimplePool::GetObj(const SObjectTag& tag, const CVParamTransfer& paramXfer)
{ {
if (!tag)
return {};
auto iter = x4_resources.find(tag); auto iter = x4_resources.find(tag);
if (iter != x4_resources.end()) if (iter != x4_resources.end())
return CToken(iter->second); return CToken(iter->second);

View File

@ -19,7 +19,7 @@ struct SObjectTag
{ {
FourCC type; FourCC type;
ResId id = -1; ResId id = -1;
operator bool() const { return id != -1; } operator bool() const { return (id & 0xffffffff) != 0xffffffff; }
bool operator!=(const SObjectTag& other) const { return id != other.id; } bool operator!=(const SObjectTag& other) const { return id != other.id; }
bool operator==(const SObjectTag& other) const { return id == other.id; } bool operator==(const SObjectTag& other) const { return id == other.id; }
SObjectTag() = default; SObjectTag() = default;

View File

@ -17,7 +17,7 @@ CWorld::CSoundGroupData::CSoundGroupData(int grpId, ResId agsc)
} }
CDummyWorld::CDummyWorld(ResId mlvlId, bool loadMap) CDummyWorld::CDummyWorld(ResId mlvlId, bool loadMap)
: x4_loadMap(loadMap) : x4_loadMap(loadMap), xc_mlvlId(mlvlId)
{ {
SObjectTag tag{FOURCC('MLVL'), mlvlId}; SObjectTag tag{FOURCC('MLVL'), mlvlId};
static_cast<ProjectResourceFactoryBase*>(g_ResFactory)->LoadResourceAsync(tag, x34_loadBuf); static_cast<ProjectResourceFactoryBase*>(g_ResFactory)->LoadResourceAsync(tag, x34_loadBuf);
@ -146,6 +146,9 @@ bool CDummyWorld::ICheckWorldComplete()
if (x4_loadMap) if (x4_loadMap)
x2c_mapWorld = g_SimplePool->GetObj(SObjectTag{FOURCC('MAPW'), x28_mapWorldId}); x2c_mapWorld = g_SimplePool->GetObj(SObjectTag{FOURCC('MAPW'), x28_mapWorldId});
r.readByte();
r.readUint32Big();
if (version > 10) if (version > 10)
{ {
u32 audioGroupCount = r.readUint32Big(); u32 audioGroupCount = r.readUint32Big();

View File

@ -16,7 +16,7 @@ IGameArea::Dock::Dock(urde::CInputStream& in, const zeus::CTransform& xf)
u32 vertCount = in.readUint32Big(); u32 vertCount = in.readUint32Big();
for (u32 i = 0 ; i < vertCount ; i++) for (u32 i = 0 ; i < vertCount ; i++)
{ {
zeus::CVector3f vert; zeus::CVector3f vert;
vert.readBig(in); vert.readBig(in);