From f7f5066038447ae70a9b954139c11ccebfde8891 Mon Sep 17 00:00:00 2001 From: Jack Andersen Date: Sat, 8 Oct 2016 10:32:36 -1000 Subject: [PATCH] Better null-tag handling; integrate CSaveWorld and CMapWorld loading --- Editor/ProjectResourceFactoryBase.cpp | 27 +++++++++++++++++++++++++++ Editor/ProjectResourceFactoryMP1.cpp | 4 ++++ Runtime/AutoMapper/CMapWorld.cpp | 11 +++++++++++ Runtime/AutoMapper/CMapWorld.hpp | 3 +++ Runtime/CGameState.cpp | 9 +++++++++ Runtime/CGameState.hpp | 3 ++- Runtime/CMemoryCardSys.cpp | 3 +++ Runtime/CMemoryCardSys.hpp | 10 +++++----- Runtime/CSaveWorld.cpp | 7 +++++++ Runtime/CSaveWorld.hpp | 5 +++++ Runtime/CSimplePool.cpp | 3 +++ Runtime/RetroTypes.hpp | 2 +- Runtime/World/CWorld.cpp | 5 ++++- Runtime/World/IGameArea.cpp | 2 +- 14 files changed, 85 insertions(+), 9 deletions(-) diff --git a/Editor/ProjectResourceFactoryBase.cpp b/Editor/ProjectResourceFactoryBase.cpp index 4947d583d..8ab7e9de0 100644 --- a/Editor/ProjectResourceFactoryBase.cpp +++ b/Editor/ProjectResourceFactoryBase.cpp @@ -225,6 +225,7 @@ bool ProjectResourceFactoryBase::AddFileToIndex(const hecl::ProjectPath& path, SObjectTag pathTag = BuildTagFromPath(subPath, m_backgroundBlender); m_tagToPath[pathTag] = subPath; m_pathToTag[subPath.hash()] = pathTag; + WriteTag(cacheWriter, pathTag, subPath); #if DUMP_CACHE_FILL DumpCacheAdd(pathTag, subPath); #endif @@ -233,6 +234,7 @@ bool ProjectResourceFactoryBase::AddFileToIndex(const hecl::ProjectPath& path, pathTag = BuildTagFromPath(subPath, m_backgroundBlender); m_tagToPath[pathTag] = subPath; m_pathToTag[subPath.hash()] = pathTag; + WriteTag(cacheWriter, pathTag, subPath); #if DUMP_CACHE_FILL DumpCacheAdd(pathTag, subPath); #endif @@ -610,6 +612,9 @@ std::unique_ptr ProjectResourceFactoryBase::Build(const urde::SObjec const urde::CVParamTransfer& paramXfer, CObjectReference* selfRef) { + if ((tag.id & 0xffffffff) == 0xffffffff || !tag.id) + Log.report(logvisor::Fatal, "attempted to access null id"); + const hecl::ProjectPath* resPath = nullptr; if (!WaitForTagReady(tag, resPath)) return {}; @@ -673,11 +678,17 @@ void ProjectResourceFactoryBase::BuildAsync(const urde::SObjectTag& tag, urde::IObj** objOut, CObjectReference* selfRef) { + if ((tag.id & 0xffffffff) == 0xffffffff || !tag.id) + Log.report(logvisor::Fatal, "attempted to access null id"); + BuildAsyncInternal(tag, paramXfer, objOut, selfRef); } 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 */ const hecl::ProjectPath* resPath = nullptr; if (!WaitForTagReady(tag, resPath)) @@ -695,6 +706,8 @@ std::shared_ptr ProjectResourceFactoryBase::LoadResourceAsync(const urde::SObjectTag& tag, std::unique_ptr& 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()) return {}; return m_asyncLoadList.emplace(std::make_pair(tag, std::make_shared(*this, tag, target))).first->second; @@ -705,6 +718,8 @@ ProjectResourceFactoryBase::LoadResourcePartAsync(const urde::SObjectTag& tag, u32 size, u32 off, std::unique_ptr& 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()) return {}; return m_asyncLoadList.emplace(std::make_pair(tag, std::make_shared(*this, tag, target, size, off))).first->second; @@ -712,6 +727,9 @@ ProjectResourceFactoryBase::LoadResourcePartAsync(const urde::SObjectTag& tag, std::unique_ptr 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 */ const hecl::ProjectPath* resPath = nullptr; if (!WaitForTagReady(tag, resPath)) @@ -728,6 +746,9 @@ std::unique_ptr ProjectResourceFactoryBase::LoadResourceSync(const urde::S std::unique_ptr ProjectResourceFactoryBase::LoadResourcePartSync(const urde::SObjectTag& tag, 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 */ const hecl::ProjectPath* resPath = nullptr; if (!WaitForTagReady(tag, resPath)) @@ -750,6 +771,9 @@ void ProjectResourceFactoryBase::CancelBuild(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; if (!WaitForTagReady(tag, resPath)) return false; @@ -791,6 +815,9 @@ const urde::SObjectTag* ProjectResourceFactoryBase::GetResourceIdByName(const ch FourCC ProjectResourceFactoryBase::GetResourceTypeById(ResId id) const { + if ((id & 0xffffffff) == 0xffffffff || !id) + Log.report(logvisor::Fatal, "attempted to access null id"); + std::unique_lock lk(const_cast(this)->m_backgroundIndexMutex); SObjectTag searchTag = {FourCC(), id}; auto search = m_tagToPath.find(searchTag); diff --git a/Editor/ProjectResourceFactoryMP1.cpp b/Editor/ProjectResourceFactoryMP1.cpp index 7094ff95f..7133151b8 100644 --- a/Editor/ProjectResourceFactoryMP1.cpp +++ b/Editor/ProjectResourceFactoryMP1.cpp @@ -17,6 +17,8 @@ #include "Runtime/Character/CAllFormatsAnimSource.hpp" #include "Runtime/Character/CAnimPOIData.hpp" #include "Runtime/Collision/CCollidableOBBTreeGroup.hpp" +#include "Runtime/CSaveWorld.hpp" +#include "Runtime/AutoMapper/CMapWorld.hpp" #include "Audio/CAudioGroupSet.hpp" #include "Runtime/CDependencyGroup.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('STRG'), FFactoryFunc(FStringTableFactory)); 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) diff --git a/Runtime/AutoMapper/CMapWorld.cpp b/Runtime/AutoMapper/CMapWorld.cpp index a6f076579..df829faf1 100644 --- a/Runtime/AutoMapper/CMapWorld.cpp +++ b/Runtime/AutoMapper/CMapWorld.cpp @@ -2,6 +2,11 @@ namespace urde { + +CMapWorld::CMapWorld(CInputStream& in) +{ +} + u32 CMapWorld::GetNumAreas() const { 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::GetIObjObjectFor(std::make_unique(in)); +} + } diff --git a/Runtime/AutoMapper/CMapWorld.hpp b/Runtime/AutoMapper/CMapWorld.hpp index 887a9770f..48c550e9b 100644 --- a/Runtime/AutoMapper/CMapWorld.hpp +++ b/Runtime/AutoMapper/CMapWorld.hpp @@ -105,6 +105,9 @@ public: void ClearTraversedFlags() const; }; +CFactoryFnReturn FMapWorldFactory(const SObjectTag& tag, CInputStream& in, const CVParamTransfer& param, + CObjectReference* selfRef); + } #endif // __URDE_CMAPWORLD_HPP__ diff --git a/Runtime/CGameState.cpp b/Runtime/CGameState.cpp index 67ea7a410..61bd7d588 100644 --- a/Runtime/CGameState.cpp +++ b/Runtime/CGameState.cpp @@ -9,6 +9,15 @@ namespace urde { +CWorldState::CWorldState(ResId id) +: x0_mlvlId(id), x4_areaId(0) +{ + x8_relayTracker = std::make_shared(); + xc_mapWorldInfo = std::make_shared(); + x10_ = -1; + x14_ = std::make_shared(); +} + CWorldState::CWorldState(CBitStreamReader& reader, ResId mlvlId, const CSaveWorld& saveWorld) : x0_mlvlId(mlvlId) { diff --git a/Runtime/CGameState.hpp b/Runtime/CGameState.hpp index 0cecea31e..3f0153f41 100644 --- a/Runtime/CGameState.hpp +++ b/Runtime/CGameState.hpp @@ -20,6 +20,7 @@ class CWorldSomethingState u32 x10_bitCount = 0; std::vector x14_; public: + CWorldSomethingState() = default; CWorldSomethingState(CBitStreamReader& reader, const CSaveWorld& saveWorld) { u32 bitCount = reader.ReadEncoded(10); @@ -47,7 +48,7 @@ class CWorldState u32 x10_; std::shared_ptr x14_; public: - CWorldState(ResId id) : x0_mlvlId(id) {} + CWorldState(ResId id); CWorldState(CBitStreamReader& reader, ResId mlvlId, const CSaveWorld& saveWorld); ResId GetWorldAssetId() const {return x0_mlvlId;} void SetAreaId(TAreaId aid) { x4_areaId = aid; } diff --git a/Runtime/CMemoryCardSys.cpp b/Runtime/CMemoryCardSys.cpp index a5c71d83e..034a6ef19 100644 --- a/Runtime/CMemoryCardSys.cpp +++ b/Runtime/CMemoryCardSys.cpp @@ -54,6 +54,7 @@ bool CSaveWorldIntermediate::InitializePump() CMemoryCardSys::CMemoryCardSys() { + x0_hints = g_SimplePool->GetObj("HINT_Hints"); xc_memoryWorlds.reserve(16); x1c_worldInter.emplace(); x1c_worldInter->reserve(16); @@ -81,6 +82,8 @@ bool CMemoryCardSys::InitializePump() for (const auto& world : xc_memoryWorlds) { const CSaveWorldMemory& wld = world.second; + if (!wld.GetWorldName()) + continue; if (!wld.GetWorldName().IsLoaded() || !wld.GetWorldName().GetObj()) return false; diff --git a/Runtime/CMemoryCardSys.hpp b/Runtime/CMemoryCardSys.hpp index 1cc1d4b18..a5b1e84b8 100644 --- a/Runtime/CMemoryCardSys.hpp +++ b/Runtime/CMemoryCardSys.hpp @@ -18,7 +18,7 @@ class CSaveWorldMemory ResId x0_strgId = -1; ResId x4_savwId = -1; u32 x8_areaCount; - std::vector xc_areaIds; /* 4 byte element */ + std::vector xc_areaIds; /* 4 byte element */ std::vector x1c_; /* 16 byte element */ TLockedToken x2c_worldName; /* used to be optional */ TLockedToken x3c_saveWorld; /* used to be optional */ @@ -34,10 +34,10 @@ public: class CSaveWorldIntermediate { friend class CMemoryCardSys; - u32 x0_mlvlId; - u32 x4_strgId; - u32 x8_savwId; - std::vector xc_areaIds; + ResId x0_mlvlId; + ResId x4_strgId; + ResId x8_savwId; + std::vector xc_areaIds; std::vector x1c_; std::unique_ptr x2c_dummyWorld; TLockedToken x34_saveWorld; /* Used to be auto_ptr */ diff --git a/Runtime/CSaveWorld.cpp b/Runtime/CSaveWorld.cpp index eab2753c5..4e34b1b9c 100644 --- a/Runtime/CSaveWorld.cpp +++ b/Runtime/CSaveWorld.cpp @@ -1,4 +1,5 @@ #include "CSaveWorld.hpp" +#include "CToken.hpp" namespace urde { @@ -98,4 +99,10 @@ s32 CSaveWorld::GetDoorIndex(const TEditorId &id) const return x34_doors.begin() - it; } +CFactoryFnReturn FSaveWorldFactory(const SObjectTag& tag, CInputStream& in, const CVParamTransfer& param, + CObjectReference* selfRef) +{ + return TToken::GetIObjObjectFor(std::make_unique(in)); +} + } diff --git a/Runtime/CSaveWorld.hpp b/Runtime/CSaveWorld.hpp index 0dabc5205..301dd8368 100644 --- a/Runtime/CSaveWorld.hpp +++ b/Runtime/CSaveWorld.hpp @@ -3,6 +3,7 @@ #include "RetroTypes.hpp" #include "DNACommon/SAVWCommon.hpp" +#include "CFactoryMgr.hpp" namespace urde { @@ -43,6 +44,10 @@ public: u32 GetDoorCount() const; s32 GetDoorIndex(const TEditorId &id) const; }; + +CFactoryFnReturn FSaveWorldFactory(const SObjectTag& tag, CInputStream& in, const CVParamTransfer& param, + CObjectReference* selfRef); + } #endif // __URDE_CSAVEWORLD_HPP__ diff --git a/Runtime/CSimplePool.cpp b/Runtime/CSimplePool.cpp index b86d8ead3..2e7391873 100644 --- a/Runtime/CSimplePool.cpp +++ b/Runtime/CSimplePool.cpp @@ -11,6 +11,9 @@ CSimplePool::CSimplePool(IFactory& factory) CToken CSimplePool::GetObj(const SObjectTag& tag, const CVParamTransfer& paramXfer) { + if (!tag) + return {}; + auto iter = x4_resources.find(tag); if (iter != x4_resources.end()) return CToken(iter->second); diff --git a/Runtime/RetroTypes.hpp b/Runtime/RetroTypes.hpp index 3dda41ef7..a9d4a77b2 100644 --- a/Runtime/RetroTypes.hpp +++ b/Runtime/RetroTypes.hpp @@ -19,7 +19,7 @@ struct SObjectTag { FourCC type; 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; } SObjectTag() = default; diff --git a/Runtime/World/CWorld.cpp b/Runtime/World/CWorld.cpp index 13e25d9dd..36282d130 100644 --- a/Runtime/World/CWorld.cpp +++ b/Runtime/World/CWorld.cpp @@ -17,7 +17,7 @@ CWorld::CSoundGroupData::CSoundGroupData(int grpId, ResId agsc) } CDummyWorld::CDummyWorld(ResId mlvlId, bool loadMap) -: x4_loadMap(loadMap) +: x4_loadMap(loadMap), xc_mlvlId(mlvlId) { SObjectTag tag{FOURCC('MLVL'), mlvlId}; static_cast(g_ResFactory)->LoadResourceAsync(tag, x34_loadBuf); @@ -146,6 +146,9 @@ bool CDummyWorld::ICheckWorldComplete() if (x4_loadMap) x2c_mapWorld = g_SimplePool->GetObj(SObjectTag{FOURCC('MAPW'), x28_mapWorldId}); + r.readByte(); + r.readUint32Big(); + if (version > 10) { u32 audioGroupCount = r.readUint32Big(); diff --git a/Runtime/World/IGameArea.cpp b/Runtime/World/IGameArea.cpp index f8cb8bccf..4dbb78b8e 100644 --- a/Runtime/World/IGameArea.cpp +++ b/Runtime/World/IGameArea.cpp @@ -16,7 +16,7 @@ IGameArea::Dock::Dock(urde::CInputStream& in, const zeus::CTransform& xf) u32 vertCount = in.readUint32Big(); - for (u32 i = 0 ; i < vertCount ; i++) + for (u32 i = 0 ; i < vertCount ; i++) { zeus::CVector3f vert; vert.readBig(in);