Non-factory resource loading; some CDummyWorld imps

This commit is contained in:
Jack Andersen 2016-07-23 11:41:18 -10:00
parent 8c9198ce1c
commit 9298ca7b99
14 changed files with 673 additions and 150 deletions

View File

@ -344,58 +344,20 @@ CFactoryFnReturn ProjectResourceFactoryBase::BuildSync(const SObjectTag& tag,
const hecl::ProjectPath& path,
const CVParamTransfer& paramXfer)
{
/* Ensure requested resource is on the filesystem */
if (path.getPathType() != hecl::ProjectPath::Type::File)
{
Log.report(logvisor::Error, _S("unable to find resource path '%s'"),
path.getAbsolutePath().c_str());
return {};
}
/* Last chance type validation */
urde::SObjectTag verifyTag = TagFromPath(path, hecl::SharedBlenderToken);
if (verifyTag.type != tag.type)
{
Log.report(logvisor::Error, _S("%s: expected type '%.4s', found '%.4s'"),
path.getRelativePath().c_str(),
tag.type.toString().c_str(), verifyTag.type.toString().c_str());
return {};
}
/* Get cooked representation path */
hecl::ProjectPath cooked = GetCookedPath(path, true);
/* Perform mod-time comparison */
if (cooked.getPathType() != hecl::ProjectPath::Type::File ||
cooked.getModtime() < path.getModtime())
{
/* Do a blocking cook here */
if (!SyncCook(path))
{
Log.report(logvisor::Error, _S("unable to cook resource path '%s'"),
path.getAbsolutePath().c_str());
return {};
}
}
/* Ensure cooked rep is on the filesystem */
athena::io::FileReader fr(cooked.getAbsolutePath(), 32 * 1024, false);
if (fr.hasError())
{
Log.report(logvisor::Error, _S("unable to open cooked resource path '%s'"),
cooked.getAbsolutePath().c_str());
std::experimental::optional<athena::io::FileReader> fr;
if (!PrepForReadSync(tag, path, fr))
return {};
}
/* All good, build resource */
if (m_factoryMgr.CanMakeMemory(tag))
{
u32 length = fr.length();
std::unique_ptr<u8[]> memBuf = fr.readUBytes(length);
u32 length = fr->length();
std::unique_ptr<u8[]> memBuf = fr->readUBytes(length);
return m_factoryMgr.MakeObjectFromMemory(tag, std::move(memBuf), length, false, paramXfer);
}
return m_factoryMgr.MakeObject(tag, fr, paramXfer);
return m_factoryMgr.MakeObject(tag, *fr, paramXfer);
}
void ProjectResourceFactoryBase::AsyncTask::EnsurePath(const urde::SObjectTag& tag,
@ -454,11 +416,11 @@ void ProjectResourceFactoryBase::AsyncTask::CookComplete()
}
/* Ready for buffer transaction at this point */
x14_resSize = fr.length();
x14_resSize = std::min(s32(x14_resSize), std::max(0, s32(fr.length()) - s32(x14_resOffset)));
x10_loadBuffer.reset(new u8[x14_resSize]);
m_bufTransaction = m_parent.m_clientProc.addBufferTransaction(m_cookedPath,
x10_loadBuffer.get(),
x14_resSize, 0);
x14_resSize, x14_resOffset);
}
bool ProjectResourceFactoryBase::AsyncTask::AsyncPump()
@ -483,89 +445,7 @@ bool ProjectResourceFactoryBase::AsyncTask::AsyncPump()
return m_failed;
}
std::unique_ptr<urde::IObj> ProjectResourceFactoryBase::Build(const urde::SObjectTag& tag,
const urde::CVParamTransfer& paramXfer)
{
std::unique_lock<std::mutex> lk(m_backgroundIndexMutex);
auto search = m_tagToPath.find(tag);
if (search == m_tagToPath.end())
{
if (m_backgroundRunning)
{
while (m_backgroundRunning)
{
lk.unlock();
lk.lock();
search = m_tagToPath.find(tag);
if (search != m_tagToPath.end())
break;
}
if (search == m_tagToPath.end())
return {};
}
else
return {};
}
lk.unlock();
auto asyncSearch = m_asyncLoadList.find(tag);
if (asyncSearch != m_asyncLoadList.end())
{
/* Async spinloop */
AsyncTask& task = asyncSearch->second;
task.EnsurePath(task.x0_tag, search->second);
/* Pump load pipeline (cooking if needed) */
while (!task.AsyncPump()) {std::this_thread::sleep_for(std::chrono::milliseconds(2));}
if (task.m_complete)
{
/* Load complete, build resource */
std::unique_ptr<IObj> newObj;
if (m_factoryMgr.CanMakeMemory(task.x0_tag))
{
newObj = m_factoryMgr.MakeObjectFromMemory(tag, std::move(task.x10_loadBuffer),
task.x14_resSize, false, task.x18_cvXfer);
}
else
{
athena::io::MemoryReader mr(task.x10_loadBuffer.get(), task.x14_resSize);
newObj = m_factoryMgr.MakeObject(task.x0_tag, mr, task.x18_cvXfer);
}
*task.xc_targetPtr = newObj.get();
Log.report(logvisor::Warning, "spin-built %.4s %08X",
task.x0_tag.type.toString().c_str(),
u32(task.x0_tag.id));
m_asyncLoadList.erase(asyncSearch);
return newObj;
}
Log.report(logvisor::Error, "unable to spin-build %.4s %08X",
task.x0_tag.type.toString().c_str(),
u32(task.x0_tag.id));
m_asyncLoadList.erase(asyncSearch);
return {};
}
/* Fall-back to sync build */
return BuildSync(tag, search->second, paramXfer);
}
void ProjectResourceFactoryBase::BuildAsync(const urde::SObjectTag& tag,
const urde::CVParamTransfer& paramXfer,
urde::IObj** objOut)
{
if (m_asyncLoadList.find(tag) != m_asyncLoadList.end())
return;
m_asyncLoadList.emplace(std::make_pair(tag, AsyncTask(*this, tag, objOut, paramXfer)));
}
void ProjectResourceFactoryBase::CancelBuild(const urde::SObjectTag& tag)
{
m_asyncLoadList.erase(tag);
}
bool ProjectResourceFactoryBase::CanBuild(const urde::SObjectTag& tag)
bool ProjectResourceFactoryBase::WaitForTagReady(const urde::SObjectTag& tag, const hecl::ProjectPath*& pathOut)
{
std::unique_lock<std::mutex> lk(m_backgroundIndexMutex);
auto search = m_tagToPath.find(tag);
@ -587,8 +467,200 @@ bool ProjectResourceFactoryBase::CanBuild(const urde::SObjectTag& tag)
else
return false;
}
lk.unlock();
pathOut = &search->second;
return true;
}
if (search->second.getPathType() == hecl::ProjectPath::Type::File)
bool
ProjectResourceFactoryBase::PrepForReadSync(const SObjectTag& tag,
const hecl::ProjectPath& path,
std::experimental::optional<athena::io::FileReader>& fr)
{
/* Ensure requested resource is on the filesystem */
if (path.getPathType() != hecl::ProjectPath::Type::File)
{
Log.report(logvisor::Error, _S("unable to find resource path '%s'"),
path.getAbsolutePath().c_str());
return false;
}
/* Last chance type validation */
urde::SObjectTag verifyTag = TagFromPath(path, hecl::SharedBlenderToken);
if (verifyTag.type != tag.type)
{
Log.report(logvisor::Error, _S("%s: expected type '%.4s', found '%.4s'"),
path.getRelativePath().c_str(),
tag.type.toString().c_str(), verifyTag.type.toString().c_str());
return false;
}
/* Get cooked representation path */
hecl::ProjectPath cooked = GetCookedPath(path, true);
/* Perform mod-time comparison */
if (cooked.getPathType() != hecl::ProjectPath::Type::File ||
cooked.getModtime() < path.getModtime())
{
/* Do a blocking cook here */
if (!SyncCook(path))
{
Log.report(logvisor::Error, _S("unable to cook resource path '%s'"),
path.getAbsolutePath().c_str());
return false;
}
}
/* Ensure cooked rep is on the filesystem */
fr.emplace(cooked.getAbsolutePath(), 32 * 1024, false);
if (fr->hasError())
{
Log.report(logvisor::Error, _S("unable to open cooked resource path '%s'"),
cooked.getAbsolutePath().c_str());
return false;
}
return true;
}
std::unique_ptr<urde::IObj> ProjectResourceFactoryBase::Build(const urde::SObjectTag& tag,
const urde::CVParamTransfer& paramXfer)
{
const hecl::ProjectPath* resPath = nullptr;
if (!WaitForTagReady(tag, resPath))
return {};
auto asyncSearch = m_asyncLoadList.find(tag);
if (asyncSearch != m_asyncLoadList.end())
{
/* Async spinloop */
AsyncTask& task = asyncSearch->second;
task.EnsurePath(task.x0_tag, *resPath);
/* Pump load pipeline (cooking if needed) */
while (!task.AsyncPump()) {std::this_thread::sleep_for(std::chrono::milliseconds(2));}
if (task.m_complete)
{
/* Load complete, build resource */
std::unique_ptr<IObj> newObj;
if (m_factoryMgr.CanMakeMemory(task.x0_tag))
{
newObj = m_factoryMgr.MakeObjectFromMemory(tag, std::move(task.x10_loadBuffer),
task.x14_resSize, false, task.x18_cvXfer);
}
else
{
athena::io::MemoryReader mr(task.x10_loadBuffer.get(), task.x14_resSize);
newObj = m_factoryMgr.MakeObject(task.x0_tag, mr, task.x18_cvXfer);
}
*task.xc_targetObjPtr = newObj.get();
Log.report(logvisor::Warning, "spin-built %.4s %08X",
task.x0_tag.type.toString().c_str(),
u32(task.x0_tag.id));
m_asyncLoadList.erase(asyncSearch);
return newObj;
}
Log.report(logvisor::Error, "unable to spin-build %.4s %08X",
task.x0_tag.type.toString().c_str(),
u32(task.x0_tag.id));
m_asyncLoadList.erase(asyncSearch);
return {};
}
/* Fall-back to sync build */
return BuildSync(tag, *resPath, paramXfer);
}
void ProjectResourceFactoryBase::BuildAsync(const urde::SObjectTag& tag,
const urde::CVParamTransfer& paramXfer,
urde::IObj** objOut)
{
if (m_asyncLoadList.find(tag) != m_asyncLoadList.end())
return;
m_asyncLoadList.emplace(std::make_pair(tag, AsyncTask(*this, tag, objOut, paramXfer)));
}
u32 ProjectResourceFactoryBase::ResourceSize(const SObjectTag& tag)
{
/* Ensure resource at requested path is indexed and not cooking */
const hecl::ProjectPath* resPath = nullptr;
if (!WaitForTagReady(tag, resPath))
return {};
/* Ensure cooked rep is on the filesystem */
std::experimental::optional<athena::io::FileReader> fr;
if (!PrepForReadSync(tag, *resPath, fr))
return {};
return fr->length();
}
bool ProjectResourceFactoryBase::LoadResourceAsync(const urde::SObjectTag& tag,
std::unique_ptr<u8[]>& target)
{
if (m_asyncLoadList.find(tag) != m_asyncLoadList.end())
return false;
m_asyncLoadList.emplace(std::make_pair(tag, AsyncTask(*this, tag, target)));
return true;
}
bool ProjectResourceFactoryBase::LoadResourcePartAsync(const urde::SObjectTag& tag,
u32 size, u32 off,
std::unique_ptr<u8[]>& target)
{
if (m_asyncLoadList.find(tag) != m_asyncLoadList.end())
return false;
m_asyncLoadList.emplace(std::make_pair(tag, AsyncTask(*this, tag, target, size, off)));
return true;
}
std::unique_ptr<u8[]> ProjectResourceFactoryBase::LoadResourceSync(const urde::SObjectTag& tag)
{
/* Ensure resource at requested path is indexed and not cooking */
const hecl::ProjectPath* resPath = nullptr;
if (!WaitForTagReady(tag, resPath))
return {};
/* Ensure cooked rep is on the filesystem */
std::experimental::optional<athena::io::FileReader> fr;
if (!PrepForReadSync(tag, *resPath, fr))
return {};
return fr->readUBytes(fr->length());
}
std::unique_ptr<u8[]> ProjectResourceFactoryBase::LoadResourcePartSync(const urde::SObjectTag& tag,
u32 size, u32 off)
{
/* Ensure resource at requested path is indexed and not cooking */
const hecl::ProjectPath* resPath = nullptr;
if (!WaitForTagReady(tag, resPath))
return {};
/* Ensure cooked rep is on the filesystem */
std::experimental::optional<athena::io::FileReader> fr;
if (!PrepForReadSync(tag, *resPath, fr))
return {};
s32 sz = std::min(s32(size), std::max(0, s32(fr->length()) - s32(off)));
fr->seek(off, athena::SeekOrigin::Begin);
return fr->readUBytes(sz);
}
void ProjectResourceFactoryBase::CancelBuild(const urde::SObjectTag& tag)
{
m_asyncLoadList.erase(tag);
}
bool ProjectResourceFactoryBase::CanBuild(const urde::SObjectTag& tag)
{
const hecl::ProjectPath* resPath = nullptr;
if (!WaitForTagReady(tag, resPath))
return false;
if (resPath->getPathType() == hecl::ProjectPath::Type::File)
return true;
return false;
@ -684,22 +756,34 @@ void ProjectResourceFactoryBase::AsyncIdle()
if (task.m_complete)
{
/* Load complete, build resource */
std::unique_ptr<IObj> newObj;
if (m_factoryMgr.CanMakeMemory(task.x0_tag))
if (task.xc_targetObjPtr)
{
newObj = m_factoryMgr.MakeObjectFromMemory(task.x0_tag, std::move(task.x10_loadBuffer),
task.x14_resSize, false, task.x18_cvXfer);
}
else
{
athena::io::MemoryReader mr(task.x10_loadBuffer.get(), task.x14_resSize);
newObj = m_factoryMgr.MakeObject(task.x0_tag, mr, task.x18_cvXfer);
}
/* Factory build */
std::unique_ptr<IObj> newObj;
if (m_factoryMgr.CanMakeMemory(task.x0_tag))
{
newObj = m_factoryMgr.MakeObjectFromMemory(task.x0_tag, std::move(task.x10_loadBuffer),
task.x14_resSize, false, task.x18_cvXfer);
}
else
{
athena::io::MemoryReader mr(task.x10_loadBuffer.get(), task.x14_resSize);
newObj = m_factoryMgr.MakeObject(task.x0_tag, mr, task.x18_cvXfer);
}
*task.xc_targetPtr = newObj.release();
Log.report(logvisor::Info, "async-built %.4s %08X",
task.x0_tag.type.toString().c_str(),
u32(task.x0_tag.id));
*task.xc_targetObjPtr = newObj.release();
Log.report(logvisor::Info, "async-built %.4s %08X",
task.x0_tag.type.toString().c_str(),
u32(task.x0_tag.id));
}
else if (task.xc_targetDataPtr)
{
/* Buffer only */
*task.xc_targetDataPtr = std::move(task.x10_loadBuffer);
Log.report(logvisor::Info, "async-loaded %.4s %08X",
task.x0_tag.type.toString().c_str(),
u32(task.x0_tag.id));
}
}
it = m_asyncLoadList.erase(it);
continue;

View File

@ -41,9 +41,11 @@ protected:
SObjectTag x0_tag;
//IDvdRequest* x8_dvdReq = nullptr;
IObj** xc_targetPtr = nullptr;
std::unique_ptr<u8[]>* xc_targetDataPtr = nullptr;
IObj** xc_targetObjPtr = nullptr;
std::unique_ptr<u8[]> x10_loadBuffer;
u32 x14_resSize = 0;
u32 x14_resSize = UINT32_MAX;
u32 x14_resOffset = 0;
CVParamTransfer x18_cvXfer;
hecl::ProjectPath m_workingPath;
@ -53,9 +55,18 @@ protected:
bool m_failed = false;
bool m_complete = false;
AsyncTask(ProjectResourceFactoryBase& parent, const SObjectTag& tag,
std::unique_ptr<u8[]>& ptr)
: m_parent(parent), x0_tag(tag), xc_targetDataPtr(&ptr) {}
AsyncTask(ProjectResourceFactoryBase& parent, const SObjectTag& tag,
std::unique_ptr<u8[]>& ptr, u32 size, u32 off)
: m_parent(parent), x0_tag(tag), xc_targetDataPtr(&ptr), x14_resSize(size),
x14_resOffset(off) {}
AsyncTask(ProjectResourceFactoryBase& parent, const SObjectTag& tag,
IObj** ptr, const CVParamTransfer& xfer)
: m_parent(parent), x0_tag(tag), xc_targetPtr(ptr), x18_cvXfer(xfer) {}
: m_parent(parent), x0_tag(tag), xc_targetObjPtr(ptr), x18_cvXfer(xfer) {}
void EnsurePath(const urde::SObjectTag& tag,
const hecl::ProjectPath& path);
@ -64,6 +75,12 @@ protected:
};
std::unordered_map<SObjectTag, AsyncTask> m_asyncLoadList;
bool WaitForTagReady(const urde::SObjectTag& tag, const hecl::ProjectPath*& pathOut);
bool
PrepForReadSync(const SObjectTag& tag,
const hecl::ProjectPath& path,
std::experimental::optional<athena::io::FileReader>& fr);
virtual SObjectTag TagFromPath(const hecl::ProjectPath& path, hecl::BlenderToken& btok) const=0;
void ReadCatalog(const hecl::ProjectPath& catalogPath,
@ -95,6 +112,12 @@ public:
const urde::SObjectTag* GetResourceIdByName(const char*) const;
FourCC GetResourceTypeById(ResId id) const;
u32 ResourceSize(const SObjectTag& tag);
bool LoadResourceAsync(const urde::SObjectTag& tag, std::unique_ptr<u8[]>& target);
bool LoadResourcePartAsync(const urde::SObjectTag& tag, u32 size, u32 off, std::unique_ptr<u8[]>& target);
std::unique_ptr<u8[]> LoadResourceSync(const urde::SObjectTag& tag);
std::unique_ptr<u8[]> LoadResourcePartSync(const urde::SObjectTag& tag, u32 size, u32 off);
void AsyncIdle();
void Shutdown() {CancelBackgroundIndex();}

View File

@ -1,4 +1,5 @@
set(AUTOMAPPER_SOURCES
CMapWorldInfo.hpp CMapWorldInfo.cpp)
CMapWorldInfo.hpp CMapWorldInfo.cpp
CMapWorld.hpp CMapWorld.cpp)
runtime_add_list(AutoMapper AUTOMAPPER_SOURCES)

View File

View File

@ -0,0 +1,17 @@
#ifndef __URDE_CMAPWORLD_HPP__
#define __URDE_CMAPWORLD_HPP__
namespace urde
{
class IWorld;
class CMapWorld
{
public:
void SetWhichMapAreasLoaded(const IWorld&, int, int);
bool IsMapAreasStreaming() const;
};
}
#endif // __URDE_CMAPWORLD_HPP__

View File

@ -42,6 +42,35 @@ FourCC CCharacterFactoryBuilder::CDummyFactory::GetResourceTypeById(ResId id) co
return {};
}
u32 CCharacterFactoryBuilder::CDummyFactory::ResourceSize(const urde::SObjectTag& tag)
{
return 0;
}
bool CCharacterFactoryBuilder::CDummyFactory::LoadResourceAsync(const urde::SObjectTag& tag,
std::unique_ptr<u8[]>& target)
{
return false;
}
bool CCharacterFactoryBuilder::CDummyFactory::LoadResourcePartAsync(const urde::SObjectTag& tag,
u32 size, u32 off,
std::unique_ptr<u8[]>& target)
{
return false;
}
std::unique_ptr<u8[]> CCharacterFactoryBuilder::CDummyFactory::LoadResourceSync(const urde::SObjectTag& tag)
{
return {};
}
std::unique_ptr<u8[]> CCharacterFactoryBuilder::CDummyFactory::LoadResourcePartSync(const urde::SObjectTag& tag,
u32 size, u32 off)
{
return {};
}
CCharacterFactoryBuilder::CCharacterFactoryBuilder() : x4_dummyStore(x0_dummyFactory) {}
TToken<CCharacterFactory> CCharacterFactoryBuilder::GetFactory(const CAnimRes& res)

View File

@ -23,6 +23,12 @@ public:
bool CanBuild(const SObjectTag&);
const SObjectTag* GetResourceIdByName(const char*) const;
FourCC GetResourceTypeById(ResId id) const;
u32 ResourceSize(const urde::SObjectTag& tag);
bool LoadResourceAsync(const urde::SObjectTag& tag, std::unique_ptr<u8[]>& target);
bool LoadResourcePartAsync(const urde::SObjectTag& tag, u32 size, u32 off, std::unique_ptr<u8[]>& target);
std::unique_ptr<u8[]> LoadResourceSync(const urde::SObjectTag& tag);
std::unique_ptr<u8[]> LoadResourcePartSync(const urde::SObjectTag& tag, u32 size, u32 off);
};
private:

View File

@ -72,6 +72,35 @@ FourCC CCharacterFactory::CDummyFactory::GetResourceTypeById(ResId id) const
return {};
}
u32 CCharacterFactory::CDummyFactory::ResourceSize(const urde::SObjectTag& tag)
{
return 0;
}
bool CCharacterFactory::CDummyFactory::LoadResourceAsync(const urde::SObjectTag& tag,
std::unique_ptr<u8[]>& target)
{
return false;
}
bool CCharacterFactory::CDummyFactory::LoadResourcePartAsync(const urde::SObjectTag& tag,
u32 size, u32 off,
std::unique_ptr<u8[]>& target)
{
return false;
}
std::unique_ptr<u8[]> CCharacterFactory::CDummyFactory::LoadResourceSync(const urde::SObjectTag& tag)
{
return {};
}
std::unique_ptr<u8[]> CCharacterFactory::CDummyFactory::LoadResourcePartSync(const urde::SObjectTag& tag,
u32 size, u32 off)
{
return {};
}
std::unique_ptr<CAnimData>
CCharacterFactory::CreateCharacter(int charIdx, bool loop,
const TLockedToken<CCharacterFactory>& factory,

View File

@ -32,6 +32,12 @@ public:
bool CanBuild(const SObjectTag&);
const SObjectTag* GetResourceIdByName(const char*) const;
FourCC GetResourceTypeById(ResId id) const;
u32 ResourceSize(const urde::SObjectTag& tag);
bool LoadResourceAsync(const urde::SObjectTag& tag, std::unique_ptr<u8[]>& target);
bool LoadResourcePartAsync(const urde::SObjectTag& tag, u32 size, u32 off, std::unique_ptr<u8[]>& target);
std::unique_ptr<u8[]> LoadResourceSync(const urde::SObjectTag& tag);
std::unique_ptr<u8[]> LoadResourcePartSync(const urde::SObjectTag& tag, u32 size, u32 off);
};
private:

View File

@ -27,6 +27,13 @@ public:
virtual bool CanBuild(const SObjectTag&)=0;
virtual const SObjectTag* GetResourceIdByName(const char*) const=0;
virtual FourCC GetResourceTypeById(ResId id) const=0;
/* Non-factory versions, replaces CResLoader */
virtual u32 ResourceSize(const urde::SObjectTag& tag)=0;
virtual bool LoadResourceAsync(const urde::SObjectTag& tag, std::unique_ptr<u8[]>& target)=0;
virtual bool LoadResourcePartAsync(const urde::SObjectTag& tag, u32 size, u32 off, std::unique_ptr<u8[]>& target)=0;
virtual std::unique_ptr<u8[]> LoadResourceSync(const urde::SObjectTag& tag)=0;
virtual std::unique_ptr<u8[]> LoadResourcePartSync(const urde::SObjectTag& tag, u32 size, u32 off)=0;
};
}

View File

@ -33,8 +33,29 @@ void CGameArea::CAreaFog::DisableFog()
{
}
CDummyGameArea::CDummyGameArea(CInputStream& in, int mlvlVersion)
CDummyGameArea::CDummyGameArea(CInputStream& in, int idx, int mlvlVersion)
{
x8_nameSTRG = in.readUint32Big();
x14_transform.read34RowMajor(in);
zeus::CAABox aabb;
aabb.readBoundingBoxBig(in);
xc_mrea = in.readUint32Big();
if (mlvlVersion > 15)
x10_areaId = in.readUint32Big();
u32 attachAreaCount = in.readUint32Big();
x44_attachedAreaIndices.reserve(attachAreaCount);
for (int i=0 ; i<attachAreaCount ; ++i)
x44_attachedAreaIndices.push_back(in.readUint16Big());
u32 depCount = in.readUint32Big();
for (int i=0 ; i<depCount ; ++i)
in.readUint32Big();
u32 dockCount = in.readUint32Big();
x54_docks.reserve(dockCount);
for (int i=0 ; i<dockCount ; ++i)
x54_docks.emplace_back(in, x14_transform);
}
bool CDummyGameArea::IGetScriptingMemoryAlways() const

View File

@ -21,8 +21,16 @@ enum class ERglFogMode
class CDummyGameArea : public IGameArea
{
int x4_mlvlVersion;
ResId x8_nameSTRG;
ResId xc_mrea;
ResId x10_areaId;
zeus::CTransform x14_transform;
std::vector<u16> x44_attachedAreaIndices;
std::vector<Dock> x54_docks;
public:
CDummyGameArea(CInputStream& in, int mlvlVersion);
CDummyGameArea(CInputStream& in, int idx, int mlvlVersion);
bool IGetScriptingMemoryAlways() const;
TAreaId IGetAreaId() const;

View File

@ -1,8 +1,219 @@
#include "CWorld.hpp"
#include "CGameArea.hpp"
#include "GameGlobalObjects.hpp"
#include "CSimplePool.hpp"
#include "AutoMapper/CMapWorld.hpp"
namespace urde
{
CDummyWorld::CDummyWorld(ResId mlvlId, bool loadMap)
: x4_loadMap(loadMap)
{
SObjectTag tag{FOURCC('MLVL'), mlvlId};
g_ResFactory->LoadResourceAsync(tag, x34_loadBuf);
}
ResId CDummyWorld::IGetWorldAssetId() const
{
}
ResId CDummyWorld::IGetStringTableAssetId() const
{
}
ResId CDummyWorld::IGetSaveWorldAssetId() const
{
}
const CMapWorld* CDummyWorld::IGetMapWorld() const
{
}
CMapWorld* CDummyWorld::IMapWorld()
{
}
IGameArea* CDummyWorld::IGetAreaAlways(TAreaId id) const
{
}
ResId CDummyWorld::IGetCurrentAreaId() const
{
}
int CDummyWorld::IGetAreaIndex(TAreaId id) const
{
}
std::vector<CWorld::CRelay> ReadMemoryRelays(athena::io::MemoryReader& r)
{
std::vector<CWorld::CRelay> ret;
u32 count = r.readUint32Big();
ret.reserve(count);
for (u32 i=0 ; i<count ; ++i)
ret.emplace_back(r);
return ret;
}
CWorldLayers ReadWorldLayers(athena::io::MemoryReader& r)
{
CWorldLayers ret;
u32 areaCount = r.readUint32Big();
ret.m_areas.reserve(areaCount);
for (u32 i=0 ; i<areaCount ; ++i)
{
ret.m_areas.emplace_back();
ret.m_areas.back().m_layerCount = r.readUint32Big();
ret.m_areas.back().m_layerBits = r.readUint64Big();
}
u32 nameCount = r.readUint32Big();
ret.m_names.reserve(areaCount);
for (u32 i=0 ; i<nameCount ; ++i)
ret.m_names.push_back(r.readString());
areaCount = r.readUint32Big();
for (u32 i=0 ; i<areaCount ; ++i)
ret.m_areas[i].m_startNameIdx = r.readUint32Big();
return ret;
}
bool CDummyWorld::ICheckWorldComplete()
{
switch (x8_phase)
{
case Phase::Loading:
{
if (!x34_loadBuf)
return false;
athena::io::MemoryReader r(x34_loadBuf.get(), UINT32_MAX, false);
r.readUint32Big();
int version = r.readUint32Big();
x10_strgId = r.readUint32Big();
if (version >= 15)
x14_savwId = r.readUint32Big();
if (version >= 12)
r.readUint32Big();
if (version >= 17)
ReadMemoryRelays(r);
u32 areaCount = r.readUint32Big();
r.readUint32Big();
x18_areas.reserve(areaCount);
for (u32 i=0 ; i<areaCount ; ++i)
x18_areas.emplace_back(r, i, version);
x28_mapWorldId = r.readUint32Big();
if (x4_loadMap)
{
x2c_mapWorld = g_SimplePool->GetObj(SObjectTag{FOURCC('MAPW'), x28_mapWorldId});
x2c_mapWorld.Lock();
}
if (version > 10)
{
u32 audioGroupCount = r.readUint32Big();
for (u32 i=0 ; i<audioGroupCount ; ++i)
{
r.readUint32Big();
r.readUint32Big();
}
}
if (version > 12)
r.readString();
ReadWorldLayers(r);
if (x4_loadMap)
x8_phase = Phase::LoadingMap;
else
{
x8_phase = Phase::Done;
return false;
}
}
case Phase::LoadingMap:
{
if (!x2c_mapWorld.IsLoaded() || !x2c_mapWorld.GetObj())
return false;
x2c_mapWorld->SetWhichMapAreasLoaded(*this, 0, 9999);
x8_phase = Phase::LoadingMapAreas;
}
case Phase::LoadingMapAreas:
{
if (x2c_mapWorld->IsMapAreasStreaming())
return false;
x8_phase = Phase::Done;
}
case Phase::Done:
return true;
default:
return false;
}
return false;
}
std::string CDummyWorld::IGetDefaultAudioTrack() const
{
}
int CDummyWorld::IGetAreaCount() const
{
}
ResId CWorld::IGetWorldAssetId() const
{
}
ResId CWorld::IGetStringTableAssetId() const
{
}
ResId CWorld::IGetSaveWorldAssetId() const
{
}
const CMapWorld* CWorld::IGetMapWorld() const
{
}
CMapWorld* CWorld::IMapWorld()
{
}
IGameArea* CWorld::IGetAreaAlways(TAreaId id) const
{
}
ResId CWorld::IGetCurrentAreaId() const
{
}
int CWorld::IGetAreaIndex(TAreaId id) const
{
}
bool CWorld::ICheckWorldComplete()
{
}
std::string CWorld::IGetDefaultAudioTrack() const
{
}
int CWorld::IGetAreaCount() const
{
}
bool CWorld::DoesAreaExist(TAreaId area) const
{
return (area >= 0 && area < x18_areas.size());

View File

@ -3,14 +3,68 @@
#include "RetroTypes.hpp"
#include "ScriptObjectSupport.hpp"
#include "CGameArea.hpp"
namespace urde
{
class CGameArea;
class IObjectStore;
class CResFactory;
class CMapWorld;
class IGameArea;
class CWorld
class IWorld
{
public:
virtual ~IWorld() = default;
virtual ResId IGetWorldAssetId() const=0;
virtual ResId IGetStringTableAssetId() const=0;
virtual ResId IGetSaveWorldAssetId() const=0;
virtual const CMapWorld* IGetMapWorld() const=0;
virtual CMapWorld* IMapWorld()=0;
virtual IGameArea* IGetAreaAlways(TAreaId id) const=0;
virtual ResId IGetCurrentAreaId() const=0;
virtual int IGetAreaIndex(TAreaId id) const=0;
virtual bool ICheckWorldComplete()=0;
virtual std::string IGetDefaultAudioTrack() const=0;
virtual int IGetAreaCount() const=0;
};
class CDummyWorld : public IWorld
{
bool x4_loadMap;
enum class Phase
{
Loading,
LoadingMap,
LoadingMapAreas,
Done,
} x8_phase = Phase::Loading;
ResId xc_mlvlId;
ResId x10_strgId;
ResId x14_savwId = -1;
std::vector<CDummyGameArea> x18_areas;
ResId x28_mapWorldId = -1;
TCachedToken<CMapWorld> x2c_mapWorld;
//AsyncTask x30_loadToken;
std::unique_ptr<uint8_t[]> x34_loadBuf;
//u32 x38_bufSz;
public:
CDummyWorld(ResId mlvlId, bool loadMap);
ResId IGetWorldAssetId() const;
ResId IGetStringTableAssetId() const;
ResId IGetSaveWorldAssetId() const;
const CMapWorld* IGetMapWorld() const;
CMapWorld* IMapWorld();
IGameArea* IGetAreaAlways(TAreaId id) const;
ResId IGetCurrentAreaId() const;
int IGetAreaIndex(TAreaId id) const;
bool ICheckWorldComplete();
std::string IGetDefaultAudioTrack() const;
int IGetAreaCount() const;
};
class CWorld : public IWorld
{
public:
class CRelay
@ -62,8 +116,35 @@ public:
CWorld(IObjectStore& objStore, CResFactory& resFactory, ResId);
bool DoesAreaExist(TAreaId area) const;
std::vector<std::unique_ptr<CGameArea>>& GetGameAreas() {return x18_areas;}
ResId IGetWorldAssetId() const;
ResId IGetStringTableAssetId() const;
ResId IGetSaveWorldAssetId() const;
const CMapWorld* IGetMapWorld() const;
CMapWorld* IMapWorld();
IGameArea* IGetAreaAlways(TAreaId id) const;
ResId IGetCurrentAreaId() const;
int IGetAreaIndex(TAreaId id) const;
bool ICheckWorldComplete();
std::string IGetDefaultAudioTrack() const;
int IGetAreaCount() const;
};
std::vector<CWorld::CRelay> ReadMemoryRelays(athena::io::MemoryReader& r);
struct CWorldLayers
{
struct Area
{
u32 m_startNameIdx;
u32 m_layerCount;
u64 m_layerBits;
};
std::vector<Area> m_areas;
std::vector<std::string> m_names;
};
CWorldLayers ReadWorldLayers(athena::io::MemoryReader& r);
}
#endif // __URDE_CWORLD_HPP__