mirror of https://github.com/AxioDL/metaforce.git
Non-factory resource loading; some CDummyWorld imps
This commit is contained in:
parent
8c9198ce1c
commit
9298ca7b99
|
@ -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;
|
||||
|
|
|
@ -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();}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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__
|
|
@ -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)
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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__
|
||||
|
|
Loading…
Reference in New Issue