diff --git a/DataSpec/DNAMP1/MREA.cpp b/DataSpec/DNAMP1/MREA.cpp index 397eb7cd3..fa478898b 100644 --- a/DataSpec/DNAMP1/MREA.cpp +++ b/DataSpec/DNAMP1/MREA.cpp @@ -512,7 +512,6 @@ bool MREA::PCCook(const hecl::ProjectPath& outPath, if (!visiGood) { hecl::ProjectPath visiIntOut = outPath.getWithExtension(_S(".visiint")); - hecl::ProjectPath visiIn = inPath.getWithExtension(_S(".visi")); athena::io::FileWriter w(visiIntOut.getAbsolutePath()); w.writeUint32Big(meshes.size()); for (const DNACMDL::Mesh& mesh : meshes) @@ -568,15 +567,19 @@ bool MREA::PCCook(const hecl::ProjectPath& outPath, #endif const hecl::SystemChar* args[] = {VisiGenPath.c_str(), visiIntOut.getAbsolutePath().c_str(), - visiIn.getAbsolutePath().c_str(), + preVisiPath.getAbsolutePath().c_str(), thrIdx, parPid, nullptr}; if (0 == hecl::RunProcess(VisiGenPath.c_str(), args)) { - athena::io::FileReader r(visiIn.getAbsolutePath()); + athena::io::FileReader r(preVisiPath.getAbsolutePath()); size_t length = r.length(); secs.emplace_back(length, 0); r.readBytesToBuf(secs.back().data(), length); - visiGood = true; + visiGood = true; + } + else + { + Log.report(logvisor::Fatal, _S("Unable to launch %s"), VisiGenPath.c_str()); } } } diff --git a/DataSpec/SpecBase.cpp b/DataSpec/SpecBase.cpp index 017b75150..6650cd174 100644 --- a/DataSpec/SpecBase.cpp +++ b/DataSpec/SpecBase.cpp @@ -441,14 +441,7 @@ bool SpecBase::canPackage(const hecl::ProjectPath& path) auto components = path.getPathComponents(); if (components.size() <= 1) return false; - hecl::ProjectPath outDir(m_project.getProjectWorkingPath(), _S("out")); - - if (path.getPathType() == hecl::ProjectPath::Type::File && - !hecl::StrCmp(path.getLastComponent(), _S("!world.blend"))) - return true; - else if (path.getPathType() == hecl::ProjectPath::Type::Directory) - return true; - return false; + return path.isFile() || path.isDirectory(); } void SpecBase::recursiveBuildResourceList(std::vector& listOut, @@ -537,7 +530,7 @@ void SpecBase::doPackage(const hecl::ProjectPath& path, const hecl::Database::Da waitForIndexComplete(); /* Name pak based on root-relative components */ - auto components = path.getPathComponents(); + auto components = path.getWithExtension(_S(""), true).getPathComponents(); if (components.size() <= 1) return; hecl::ProjectPath outPath(m_project.getProjectWorkingPath(), @@ -582,6 +575,38 @@ void SpecBase::doPackage(const hecl::ProjectPath& path, const hecl::Database::Da for (int64_t i=0 ; i<32-rem ; ++i) pakOut.writeUByte(0xff); } + else if (path.getPathType() == hecl::ProjectPath::Type::File) /* One-file General PAK */ + { + /* Build resource list */ + std::vector subPaths; + flattenDependencies(path, subPaths, btok); + std::unordered_set addedTags; + std::vector> nameList; + for (const auto& subPath : subPaths) + { + if (urde::SObjectTag tag = tagFromPath(subPath, btok)) + { + if (addedTags.find(tag) != addedTags.end()) + continue; + addedTags.insert(tag); + buildList.push_back(tag); + } + } + + /* Build name list */ + for (const auto& item : buildList) + { + auto search = m_catalogTagToName.find(item); + if (search != m_catalogTagToName.end()) + nameList.emplace_back(item, search->second); + } + + /* Write resource list structure */ + buildPakList(btok, pakOut, buildList, nameList, resTableOffset); + if (int64_t rem = pakOut.position() % 32) + for (int64_t i=0 ; i<32-rem ; ++i) + pakOut.writeUByte(0xff); + } /* Async cook resource list if using ClientProcess */ if (cp) diff --git a/DataSpec/SpecMP1.cpp b/DataSpec/SpecMP1.cpp index 37a9da450..10c2d97da 100644 --- a/DataSpec/SpecMP1.cpp +++ b/DataSpec/SpecMP1.cpp @@ -1165,8 +1165,6 @@ struct SpecMP1 : SpecBase nameEnt.name = parentDir.getLastComponent(); nameEnt.write(w); - w.writeUint32Big(atUint32(count)); - resTableOffset = w.position(); for (const auto& area : mlvl.areas) for (const auto& dep : area.deps) listOut.push_back({dep.type, dep.id.toUint32()}); @@ -1231,6 +1229,8 @@ struct SpecMP1 : SpecBase listOut.push_back(worldTag); + w.writeUint32Big(atUint32(listOut.size())); + resTableOffset = w.position(); for (const auto& item : listOut) { DNAMP1::PAK::Entry ent; diff --git a/Editor/CMakeLists.txt b/Editor/CMakeLists.txt index ccb293ea4..94d013309 100644 --- a/Editor/CMakeLists.txt +++ b/Editor/CMakeLists.txt @@ -55,5 +55,7 @@ add_dependencies(urde visigen hecl) add_custom_command(TARGET urde POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy $ $) +add_custom_command(TARGET urde POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy $ $) add_custom_command(TARGET urde POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy $ $) \ No newline at end of file diff --git a/Editor/ProjectResourceFactoryBase.cpp b/Editor/ProjectResourceFactoryBase.cpp index d5c7b6a9b..22f4b1a4a 100644 --- a/Editor/ProjectResourceFactoryBase.cpp +++ b/Editor/ProjectResourceFactoryBase.cpp @@ -160,7 +160,7 @@ bool ProjectResourceFactoryBase::AsyncTask::AsyncPump() return m_failed; } -void ProjectResourceFactoryBase::AsyncTask::WaitForComplete() +void ProjectResourceFactoryBase::AsyncTask::WaitUntilComplete() { using ItType = std::unordered_map>::iterator>::iterator; @@ -365,37 +365,25 @@ u32 ProjectResourceFactoryBase::ResourceSize(const SObjectTag& tag) return fr->length(); } -std::shared_ptr -ProjectResourceFactoryBase::LoadResourceAsync(const urde::SObjectTag& tag, - std::unique_ptr& target) +std::shared_ptr +ProjectResourceFactoryBase::LoadResourceAsync(const urde::SObjectTag& tag, void* target) { if (!tag.id.IsValid()) Log.report(logvisor::Fatal, "attempted to access null id"); if (m_asyncLoadMap.find(tag) != m_asyncLoadMap.end()) return {}; - return _AddTask(std::make_shared(*this, tag, target)); + return std::static_pointer_cast(_AddTask(std::make_shared(*this, tag, reinterpret_cast(target)))); } -std::shared_ptr +std::shared_ptr ProjectResourceFactoryBase::LoadResourcePartAsync(const urde::SObjectTag& tag, - u32 size, u32 off, - std::unique_ptr& target) + u32 size, u32 off, void* target) { if (!tag.id.IsValid()) Log.report(logvisor::Fatal, "attempted to access null id"); if (m_asyncLoadMap.find(tag) != m_asyncLoadMap.end()) return {}; - return _AddTask(std::make_shared(*this, tag, target, size, off)); -} - -std::shared_ptr -ProjectResourceFactoryBase::LoadResourcePartAsync(const urde::SObjectTag& tag, u32 size, u32 off, u8* target) -{ - if (!tag.id.IsValid()) - Log.report(logvisor::Fatal, "attempted to access null id"); - if (m_asyncLoadMap.find(tag) != m_asyncLoadMap.end()) - return {}; - return _AddTask(std::make_shared(*this, tag, target, size, off)); + return std::static_pointer_cast(_AddTask(std::make_shared(*this, tag, reinterpret_cast(target), size, off))); } std::unique_ptr ProjectResourceFactoryBase::LoadResourceSync(const urde::SObjectTag& tag) diff --git a/Editor/ProjectResourceFactoryBase.hpp b/Editor/ProjectResourceFactoryBase.hpp index 320043dd6..870c36f3f 100644 --- a/Editor/ProjectResourceFactoryBase.hpp +++ b/Editor/ProjectResourceFactoryBase.hpp @@ -21,7 +21,7 @@ class ProjectResourceFactoryBase : public IFactory hecl::ClientProcess& m_clientProc; public: - struct AsyncTask + struct AsyncTask : urde::IDvdRequest { ProjectResourceFactoryBase& m_parent; @@ -52,6 +52,10 @@ public: : m_parent(parent), x0_tag(tag), xc_targetDataPtr(&ptr), x14_resSize(size), x14_resOffset(off) {} + AsyncTask(ProjectResourceFactoryBase& parent, const SObjectTag& tag, + u8* ptr) + : m_parent(parent), x0_tag(tag), xc_targetDataRawPtr(ptr) {} + AsyncTask(ProjectResourceFactoryBase& parent, const SObjectTag& tag, u8* ptr, u32 size, u32 off) : m_parent(parent), x0_tag(tag), xc_targetDataRawPtr(ptr), x14_resSize(size), @@ -69,7 +73,10 @@ public: const hecl::ProjectPath& path); void CookComplete(); bool AsyncPump(); - void WaitForComplete(); + void WaitUntilComplete(); + bool IsComplete() { return m_complete; } + void PostCancelRequest() {} + EMediaType GetMediaType() const { return EMediaType::Real; } }; protected: @@ -154,9 +161,8 @@ public: void EnumerateNamedResources(const std::function& lambda) const; u32 ResourceSize(const SObjectTag& tag); - std::shared_ptr LoadResourceAsync(const urde::SObjectTag& tag, std::unique_ptr& target); - std::shared_ptr LoadResourcePartAsync(const urde::SObjectTag& tag, u32 size, u32 off, std::unique_ptr& target); - std::shared_ptr LoadResourcePartAsync(const urde::SObjectTag& tag, u32 size, u32 off, u8* target); + std::shared_ptr LoadResourceAsync(const urde::SObjectTag& tag, void* target); + std::shared_ptr LoadResourcePartAsync(const urde::SObjectTag& tag, u32 size, u32 off, void* target); std::unique_ptr LoadResourceSync(const urde::SObjectTag& tag); std::unique_ptr LoadResourcePartSync(const urde::SObjectTag& tag, u32 size, u32 off); diff --git a/Runtime/CFactoryMgr.cpp b/Runtime/CFactoryMgr.cpp index f16148b63..cb30498e6 100644 --- a/Runtime/CFactoryMgr.cpp +++ b/Runtime/CFactoryMgr.cpp @@ -73,7 +73,7 @@ static const FourCC TypeTable[] = FOURCC('WPSC'), FOURCC('SWHC'), FOURCC('DPSC'), FOURCC('ELSC'), FOURCC('CRSC'), FOURCC('AFSM'), FOURCC('DCLN'), FOURCC('AGSC'), FOURCC('ATBL'), FOURCC('CSNG'), FOURCC('STRG'), FOURCC('SCAN'), FOURCC('PATH'), FOURCC('DGRP'), FOURCC('HMAP'), FOURCC('CTWK'), FOURCC('FRME'), FOURCC('HINT'), - FOURCC('MAPU'), FOURCC('DUMB') + FOURCC('MAPU'), FOURCC('DUMB'), FOURCC('OIDS') }; CFactoryMgr::ETypeTable CFactoryMgr::FourCCToTypeIdx(FourCC fcc) diff --git a/Runtime/CFactoryMgr.hpp b/Runtime/CFactoryMgr.hpp index bede6eb87..d2bc0de9e 100644 --- a/Runtime/CFactoryMgr.hpp +++ b/Runtime/CFactoryMgr.hpp @@ -30,14 +30,14 @@ public: enum class ETypeTable : s8 { - Invalid = -1, CLSN, CMDL, CSKR, ANIM, CINF, TXTR, PLTT, FONT, ANCS, EVNT, MADF, MLVL, MREA, MAPW, MAPA, SAVW, SAVA, PART, WPSC, SWHC, DPSC, ELSC, CRSC, AFSM, DCLN, AGSC, ATBL, CSNG, STRG, SCAN, PATH, DGRP, HMAP, CTWK, FRME, HINT, - MAPU, DUMB + MAPU, DUMB, OIDS, + Invalid = 127 }; static ETypeTable FourCCToTypeIdx(FourCC fcc); diff --git a/Runtime/CPakFile.cpp b/Runtime/CPakFile.cpp index 95316d78e..27f48e2b5 100644 --- a/Runtime/CPakFile.cpp +++ b/Runtime/CPakFile.cpp @@ -7,8 +7,12 @@ static logvisor::Module Log("urde::CPakFile"); CPakFile::CPakFile(const std::string& filename, bool buildDepList, bool worldPak) : CDvdFile(filename.c_str()) { + if (!CDvdFile::operator bool()) + Log.report(logvisor::Fatal, "%s: Unable to open", GetPath().c_str()); x28_24_buildDepList = buildDepList; + x28_24_buildDepList = true; // Always do this so URDE can rapidly pre-warm shaders x28_26_worldPak = worldPak; + x28_27_stashedInARAM = false; } const SObjectTag* CPakFile::GetResIdByName(const char* name) const @@ -79,7 +83,7 @@ void CPakFile::InitialHeaderLoad() x4c_resTableCount = r.readUint32Big(); x48_resTableOffset = u32(r.position()); x2c_asyncLoadPhase = EAsyncPhase::DataLoad; - u32 newSize = ROUND_UP_32(x4c_resTableCount * 16 + x48_resTableOffset); + u32 newSize = ROUND_UP_32(x4c_resTableCount * 20 + x48_resTableOffset); u32 origSize = u32(x38_headerData.size()); if (newSize > origSize) { @@ -103,10 +107,10 @@ void CPakFile::Warmup() const CPakFile::SResInfo* CPakFile::GetResInfoForLoadPreferForward(CAssetId id) const { - if (!x28_27_worldPakInitialized) + if (x28_27_stashedInARAM) return nullptr; - auto search = std::lower_bound(x74_resList.begin(), x74_resList.end(), id, - [](const SResInfo& left, const CAssetId& right) { return left.x0_id < right; }); + auto search = rstl::binary_find(x74_resList.begin(), x74_resList.end(), id, + [](const SResInfo& test) { return test.x0_id; }); if (search == x74_resList.end()) return nullptr; const SResInfo* bestInfo = &*search; @@ -130,10 +134,10 @@ const CPakFile::SResInfo* CPakFile::GetResInfoForLoadPreferForward(CAssetId id) const CPakFile::SResInfo* CPakFile::GetResInfoForLoadDirectionless(CAssetId id) const { - if (!x28_27_worldPakInitialized) + if (x28_27_stashedInARAM) return nullptr; - auto search = std::lower_bound(x74_resList.begin(), x74_resList.end(), id, - [](const SResInfo& left, const CAssetId& right) { return left.x0_id < right; }); + auto search = rstl::binary_find(x74_resList.begin(), x74_resList.end(), id, + [](const SResInfo& test) { return test.x0_id; }); if (search == x74_resList.end()) return nullptr; const SResInfo* bestInfo = &*search; @@ -158,7 +162,7 @@ const CPakFile::SResInfo* CPakFile::GetResInfo(CAssetId id) const { if (x2c_asyncLoadPhase != EAsyncPhase::Loaded) return nullptr; - if (!x28_27_worldPakInitialized) + if (x28_27_stashedInARAM) return nullptr; auto search = rstl::binary_find(x74_resList.begin(), x74_resList.end(), id, [](const SResInfo& i) { return i.x0_id; }); @@ -171,7 +175,7 @@ void CPakFile::AsyncIdle() { if (x2c_asyncLoadPhase == EAsyncPhase::Loaded) return; - if (x30_dvdReq && x30_dvdReq->IsComplete()) + if (x30_dvdReq && !x30_dvdReq->IsComplete()) return; switch (x2c_asyncLoadPhase) { diff --git a/Runtime/CPakFile.hpp b/Runtime/CPakFile.hpp index 9715226de..d3c84e8df 100644 --- a/Runtime/CPakFile.hpp +++ b/Runtime/CPakFile.hpp @@ -44,7 +44,7 @@ private: bool x28_24_buildDepList; bool x28_25_aramFile; bool x28_26_worldPak; - bool x28_27_worldPakInitialized; + bool x28_27_stashedInARAM; }; u32 _dummy = 0; }; diff --git a/Runtime/CResFactory.cpp b/Runtime/CResFactory.cpp index 2d0c62c89..f1f56cf81 100644 --- a/Runtime/CResFactory.cpp +++ b/Runtime/CResFactory.cpp @@ -3,6 +3,7 @@ namespace urde { +static logvisor::Module Log("CResFactory"); void CResFactory::AddToLoadList(SLoadingData&& data) { @@ -11,19 +12,22 @@ void CResFactory::AddToLoadList(SLoadingData&& data) CFactoryFnReturn CResFactory::BuildSync(const SObjectTag& tag, const CVParamTransfer& xfer, CObjectReference* selfRef) { + CFactoryFnReturn ret; if (x5c_factoryMgr.CanMakeMemory(tag)) { std::unique_ptr data; int size; x4_loader.LoadMemResourceSync(tag, data, &size); - return x5c_factoryMgr.MakeObjectFromMemory(tag, std::move(data), size, - x4_loader.GetResourceCompression(tag), xfer, selfRef); + ret = x5c_factoryMgr.MakeObjectFromMemory(tag, std::move(data), size, + x4_loader.GetResourceCompression(tag), xfer, selfRef); } else { auto rp = x4_loader.LoadNewResourceSync(tag, nullptr); - return x5c_factoryMgr.MakeObject(tag, *rp, xfer, selfRef); + ret = x5c_factoryMgr.MakeObject(tag, *rp, xfer, selfRef); } + Log.report(logvisor::Warning, "sync-built %.4s %08X", tag.type.getChars(), tag.id.Value()); + return ret; } bool CResFactory::PumpResource(SLoadingData& data) @@ -34,6 +38,7 @@ bool CResFactory::PumpResource(SLoadingData& data) x5c_factoryMgr.MakeObjectFromMemory(data.x0_tag, std::move(data.x10_loadBuffer), data.x14_resSize, data.m_compressed, data.x18_cvXfer, data.m_selfRef); + Log.report(logvisor::Info, "async-built %.4s %08X", data.x0_tag.type.getChars(), data.x0_tag.id.Value()); return true; } return false; @@ -60,13 +65,15 @@ void CResFactory::BuildAsync(const SObjectTag& tag, const CVParamTransfer& xfer, { SLoadingData data(tag, target, xfer, x4_loader.GetResourceCompression(tag), selfRef); data.x10_loadBuffer = std::unique_ptr(new u8[x4_loader.ResourceSize(tag)]); - x4_loader.LoadResourceAsync(tag, data.x10_loadBuffer.get()); + data.x8_dvdReq = x4_loader.LoadResourceAsync(tag, data.x10_loadBuffer.get()); AddToLoadList(std::move(data)); } } void CResFactory::AsyncIdle() { + if (m_loadList.empty()) + return; auto startTime = std::chrono::steady_clock::now(); while (std::chrono::duration_cast( std::chrono::steady_clock::now() - startTime).count() < 2) diff --git a/Runtime/CResFactory.hpp b/Runtime/CResFactory.hpp index 165a07d65..7a3942eb7 100644 --- a/Runtime/CResFactory.hpp +++ b/Runtime/CResFactory.hpp @@ -69,6 +69,16 @@ public: return x4_loader.LoadResourcePartSync(tag, size, off); } + std::shared_ptr LoadResourceAsync(const urde::SObjectTag& tag, void* target) + { + return x4_loader.LoadResourceAsync(tag, target); + } + + std::shared_ptr LoadResourcePartAsync(const urde::SObjectTag& tag, u32 size, u32 off, void* target) + { + return x4_loader.LoadResourcePartAsync(tag, size, off, target); + } + const SObjectTag* GetResourceIdByName(const char* name) const { return x4_loader.GetResourceIdByName(name); @@ -97,6 +107,9 @@ public: void LoadOriginalIDs(CSimplePool& sp); CAssetId TranslateOriginalToNew(CAssetId id) const; CAssetId TranslateNewToOriginal(CAssetId id) const; + + CResLoader* GetResLoader() { return &x4_loader; } + CFactoryMgr* GetFactoryMgr() { return &x5c_factoryMgr; } }; } diff --git a/Runtime/CResLoader.cpp b/Runtime/CResLoader.cpp index b3b5240bb..2ac9f7c7c 100644 --- a/Runtime/CResLoader.cpp +++ b/Runtime/CResLoader.cpp @@ -3,6 +3,7 @@ namespace urde { +static logvisor::Module Log("CResLoader"); CResLoader::CResLoader() { @@ -18,12 +19,12 @@ const std::vector* CResLoader::GetTagListForFile(const std::string& na return nullptr; } -void CResLoader::AddPakFileAsync(const std::string& name, bool samusPak, bool worldPak) +void CResLoader::AddPakFileAsync(const std::string& name, bool buildDepList, bool worldPak) { std::string namePak = name + ".upak"; if (CDvdFile::FileExists(namePak.c_str())) { - x30_pakLoadingList.emplace_back(new CPakFile(namePak, samusPak, worldPak)); + x30_pakLoadingList.emplace_back(new CPakFile(namePak, buildDepList, worldPak)); ++x44_pakLoadingCount; } } @@ -31,11 +32,16 @@ void CResLoader::AddPakFileAsync(const std::string& name, bool samusPak, bool wo void CResLoader::AddPakFile(const std::string& name, bool samusPak, bool worldPak) { AddPakFileAsync(name, samusPak, worldPak); + WaitForPakFileLoadingComplete(); +} + +void CResLoader::WaitForPakFileLoadingComplete() +{ while (x44_pakLoadingCount) AsyncIdlePakLoading(); } -std::unique_ptr CResLoader::LoadNewResourcePartSync(const SObjectTag& tag, int offset, int length, void* extBuf) +std::unique_ptr CResLoader::LoadNewResourcePartSync(const SObjectTag& tag, u32 length, u32 offset, void* extBuf) { void* buf = extBuf; CPakFile* file = FindResourceForLoad(tag); @@ -83,7 +89,7 @@ std::unique_ptr CResLoader::LoadNewResourceSync(const SObjectTag& return std::unique_ptr(newStrm); } -std::shared_ptr CResLoader::LoadResourcePartAsync(const SObjectTag& tag, int offset, int length, void* buf) +std::shared_ptr CResLoader::LoadResourcePartAsync(const SObjectTag& tag, u32 length, u32 offset, void* buf) { return FindResourceForLoad(tag.id)->AsyncSeekRead(buf, length, ESeekOrigin::Begin, x50_cachedResInfo->GetOffset() + offset); @@ -187,6 +193,7 @@ bool CResLoader::FindResource(CAssetId id) const return true; } + Log.report(logvisor::Fatal, "Unable to find asset %08X", id); return false; } @@ -207,6 +214,7 @@ CPakFile* CResLoader::FindResourceForLoad(CAssetId id) } } + Log.report(logvisor::Fatal, "Unable to find asset %08X", id); return nullptr; } diff --git a/Runtime/CResLoader.hpp b/Runtime/CResLoader.hpp index 087f4b663..0e60ec280 100644 --- a/Runtime/CResLoader.hpp +++ b/Runtime/CResLoader.hpp @@ -26,13 +26,14 @@ class CResLoader public: CResLoader(); const std::vector* GetTagListForFile(const std::string& name) const; - void AddPakFileAsync(const std::string& name, bool samusPak, bool worldPak); + void AddPakFileAsync(const std::string& name, bool buildDepList, bool worldPak); void AddPakFile(const std::string& name, bool samusPak, bool worldPak); - std::unique_ptr LoadNewResourcePartSync(const SObjectTag& tag, int offset, int length, void* extBuf); + void WaitForPakFileLoadingComplete(); + std::unique_ptr LoadNewResourcePartSync(const SObjectTag& tag, u32 length, u32 offset, void* extBuf); void LoadMemResourceSync(const SObjectTag& tag, std::unique_ptr& bufOut, int* sizeOut); std::unique_ptr LoadResourceFromMemorySync(const SObjectTag& tag, const void* buf); std::unique_ptr LoadNewResourceSync(const SObjectTag& tag, void* extBuf=nullptr); - std::shared_ptr LoadResourcePartAsync(const SObjectTag& tag, int offset, int length, void* buf); + std::shared_ptr LoadResourcePartAsync(const SObjectTag& tag, u32 length, u32 offset, void* buf); std::shared_ptr LoadResourceAsync(const SObjectTag& tag, void* buf); std::unique_ptr LoadResourceSync(const urde::SObjectTag& tag); std::unique_ptr LoadResourcePartSync(const urde::SObjectTag& tag, u32 size, u32 off); diff --git a/Runtime/Character/CAssetFactory.cpp b/Runtime/Character/CAssetFactory.cpp index f26f18e02..236daa73b 100644 --- a/Runtime/Character/CAssetFactory.cpp +++ b/Runtime/Character/CAssetFactory.cpp @@ -60,17 +60,17 @@ u32 CCharacterFactoryBuilder::CDummyFactory::ResourceSize(const urde::SObjectTag return 0; } -bool CCharacterFactoryBuilder::CDummyFactory::LoadResourceAsync(const urde::SObjectTag& tag, - std::unique_ptr& target) +std::shared_ptr CCharacterFactoryBuilder::CDummyFactory::LoadResourceAsync(const urde::SObjectTag& tag, + void* target) { - return false; + return {}; } -bool CCharacterFactoryBuilder::CDummyFactory::LoadResourcePartAsync(const urde::SObjectTag& tag, - u32 size, u32 off, - std::unique_ptr& target) +std::shared_ptr CCharacterFactoryBuilder::CDummyFactory::LoadResourcePartAsync(const urde::SObjectTag& tag, + u32 size, u32 off, + void* target) { - return false; + return {}; } std::unique_ptr CCharacterFactoryBuilder::CDummyFactory::LoadResourceSync(const urde::SObjectTag& tag) diff --git a/Runtime/Character/CAssetFactory.hpp b/Runtime/Character/CAssetFactory.hpp index 6d4c9952d..a9ed86dc1 100644 --- a/Runtime/Character/CAssetFactory.hpp +++ b/Runtime/Character/CAssetFactory.hpp @@ -28,8 +28,8 @@ public: void EnumerateNamedResources(const std::function& lambda) const; u32 ResourceSize(const urde::SObjectTag& tag); - bool LoadResourceAsync(const urde::SObjectTag& tag, std::unique_ptr& target); - bool LoadResourcePartAsync(const urde::SObjectTag& tag, u32 size, u32 off, std::unique_ptr& target); + std::shared_ptr LoadResourceAsync(const urde::SObjectTag& tag, void* target); + std::shared_ptr LoadResourcePartAsync(const urde::SObjectTag& tag, u32 size, u32 off, void* target); std::unique_ptr LoadResourceSync(const urde::SObjectTag& tag); std::unique_ptr LoadResourcePartSync(const urde::SObjectTag& tag, u32 size, u32 off); }; diff --git a/Runtime/Character/CCharacterFactory.cpp b/Runtime/Character/CCharacterFactory.cpp index 3a3c3bf17..24912135c 100644 --- a/Runtime/Character/CCharacterFactory.cpp +++ b/Runtime/Character/CCharacterFactory.cpp @@ -88,17 +88,17 @@ u32 CCharacterFactory::CDummyFactory::ResourceSize(const urde::SObjectTag& tag) return 0; } -bool CCharacterFactory::CDummyFactory::LoadResourceAsync(const urde::SObjectTag& tag, - std::unique_ptr& target) +std::shared_ptr CCharacterFactory::CDummyFactory::LoadResourceAsync(const urde::SObjectTag& tag, + void* target) { - return false; + return {}; } -bool CCharacterFactory::CDummyFactory::LoadResourcePartAsync(const urde::SObjectTag& tag, - u32 size, u32 off, - std::unique_ptr& target) +std::shared_ptr CCharacterFactory::CDummyFactory::LoadResourcePartAsync(const urde::SObjectTag& tag, + u32 size, u32 off, + void* target) { - return false; + return {}; } std::unique_ptr CCharacterFactory::CDummyFactory::LoadResourceSync(const urde::SObjectTag& tag) diff --git a/Runtime/Character/CCharacterFactory.hpp b/Runtime/Character/CCharacterFactory.hpp index 4387c81a5..7e8485f1c 100644 --- a/Runtime/Character/CCharacterFactory.hpp +++ b/Runtime/Character/CCharacterFactory.hpp @@ -37,8 +37,8 @@ public: void EnumerateNamedResources(const std::function& lambda) const; u32 ResourceSize(const urde::SObjectTag& tag); - bool LoadResourceAsync(const urde::SObjectTag& tag, std::unique_ptr& target); - bool LoadResourcePartAsync(const urde::SObjectTag& tag, u32 size, u32 off, std::unique_ptr& target); + std::shared_ptr LoadResourceAsync(const urde::SObjectTag& tag, void* target); + std::shared_ptr LoadResourcePartAsync(const urde::SObjectTag& tag, u32 size, u32 off, void* target); std::unique_ptr LoadResourceSync(const urde::SObjectTag& tag); std::unique_ptr LoadResourcePartSync(const urde::SObjectTag& tag, u32 size, u32 off); }; diff --git a/Runtime/IFactory.hpp b/Runtime/IFactory.hpp index 10ffcab48..6957511d7 100644 --- a/Runtime/IFactory.hpp +++ b/Runtime/IFactory.hpp @@ -13,6 +13,7 @@ class CObjectReference; class CResLoader; class CFactoryMgr; class CSimplePool; +class IDvdRequest; using CFactoryFnReturn = std::unique_ptr; using FFactoryFunc = std::function& lambda) const=0; virtual void EnumerateNamedResources(const std::function& lambda) const=0; - virtual CResLoader* GetResLoader() const { return nullptr; } - virtual CFactoryMgr* GetFactoryMgr() const { return nullptr; } + virtual CResLoader* GetResLoader() { return nullptr; } + virtual CFactoryMgr* GetFactoryMgr() { return nullptr; } virtual void LoadOriginalIDs(CSimplePool& sp) {} virtual void AsyncIdle() {} /* Non-factory versions, replaces CResLoader */ virtual u32 ResourceSize(const urde::SObjectTag& tag)=0; - //virtual bool LoadResourceAsync(const urde::SObjectTag& tag, std::unique_ptr& target)=0; - //virtual bool LoadResourcePartAsync(const urde::SObjectTag& tag, u32 size, u32 off, std::unique_ptr& target)=0; + virtual std::shared_ptr LoadResourceAsync(const urde::SObjectTag& tag, void* target)=0; + virtual std::shared_ptr LoadResourcePartAsync(const urde::SObjectTag& tag, u32 size, u32 off, void* target)=0; virtual std::unique_ptr LoadResourceSync(const urde::SObjectTag& tag)=0; virtual std::unique_ptr LoadResourcePartSync(const urde::SObjectTag& tag, u32 size, u32 off)=0; diff --git a/Runtime/IOStreams.cpp b/Runtime/IOStreams.cpp index 9417647b8..6ab674a94 100644 --- a/Runtime/IOStreams.cpp +++ b/Runtime/IOStreams.cpp @@ -149,13 +149,14 @@ atUint64 CZipInputStream::readUBytesToBuf(void *buf, atUint64 len) { x30_zstrm.next_out = (Bytef*)buf; x30_zstrm.avail_out = len; - if (!x30_zstrm.avail_in) + while (x30_zstrm.avail_out != 0) { atUint64 readSz = x28_strm->readUBytesToBuf(x24_compBuf.get(), 4096); x30_zstrm.avail_in = readSz; x30_zstrm.next_in = x24_compBuf.get(); + if (inflate(&x30_zstrm, Z_NO_FLUSH) != Z_OK) + break; } - inflate(&x30_zstrm, Z_NO_FLUSH); return x30_zstrm.total_out; } diff --git a/Runtime/MP1/CPauseScreen.cpp b/Runtime/MP1/CPauseScreen.cpp index 157a1a4b5..420657ef9 100644 --- a/Runtime/MP1/CPauseScreen.cpp +++ b/Runtime/MP1/CPauseScreen.cpp @@ -25,8 +25,8 @@ CPauseScreen::CPauseScreen(ESubScreen subscreen, { SObjectTag frmeTag(FOURCC('FRME'), x54_frmePauseScreenId); x58_frmePauseScreenBufSz = g_ResFactory->ResourceSize(frmeTag); - ProjectResourceFactoryBase& resFac = static_cast(*g_ResFactory); - x60_loadTok = resFac.LoadResourceAsync(frmeTag, x5c_frmePauseScreenBuf); + x5c_frmePauseScreenBuf.reset(new u8[x58_frmePauseScreenBufSz]); + x60_loadTok = g_ResFactory->LoadResourceAsync(frmeTag, x5c_frmePauseScreenBuf.get()); CSfxManager::SfxStart(1435, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); } @@ -89,7 +89,7 @@ bool CPauseScreen::CheckLoadComplete(const CStateManager& mgr) } if (x60_loadTok) { - if (!x60_loadTok->m_complete) + if (!x60_loadTok->IsComplete()) return false; for (int i=0 ; i<2 ; ++i) { diff --git a/Runtime/MP1/CPauseScreen.hpp b/Runtime/MP1/CPauseScreen.hpp index ab7fc4995..5092f21f5 100644 --- a/Runtime/MP1/CPauseScreen.hpp +++ b/Runtime/MP1/CPauseScreen.hpp @@ -45,7 +45,7 @@ private: CAssetId x54_frmePauseScreenId; u32 x58_frmePauseScreenBufSz; std::unique_ptr x5c_frmePauseScreenBuf; - std::shared_ptr x60_loadTok; + std::shared_ptr x60_loadTok; rstl::reserved_vector, 2> x64_frameInsts; u32 x78_activeIdx = 0; rstl::reserved_vector, 2> x7c_screens; diff --git a/Runtime/MP1/CPreFrontEnd.cpp b/Runtime/MP1/CPreFrontEnd.cpp index 99bb6c69e..356f695e8 100644 --- a/Runtime/MP1/CPreFrontEnd.cpp +++ b/Runtime/MP1/CPreFrontEnd.cpp @@ -21,7 +21,7 @@ CIOWin::EMessageReturn CPreFrontEnd::OnMessage(const CArchitectureMessage& msg, CMain* m = static_cast(g_Main); if (CResLoader* loader = g_ResFactory->GetResLoader()) - if (loader->AreAllPaksLoaded()) + if (!loader->AreAllPaksLoaded()) return EMessageReturn::Exit; if (!x14_resourceTweaksRegistered) { diff --git a/Runtime/MP1/CTweaks.cpp b/Runtime/MP1/CTweaks.cpp index 5f7cdaf4e..602fb78f4 100644 --- a/Runtime/MP1/CTweaks.cpp +++ b/Runtime/MP1/CTweaks.cpp @@ -38,93 +38,91 @@ static const SObjectTag& IDFromFactory(CResFactory& factory, const char* name) void CTweaks::RegisterTweaks() { - ProjectResourceFactoryMP1& factory = ProjectManager::g_SharedManager->resourceFactoryMP1(); std::experimental::optional strm; const SObjectTag* tag; /* Particle */ - tag = factory.GetResourceIdByName("Particle"); - strm.emplace(factory.LoadResourceSync(*tag).release(), factory.ResourceSize(*tag)); + tag = g_ResFactory->GetResourceIdByName("Particle"); + strm.emplace(g_ResFactory->LoadResourceSync(*tag).release(), g_ResFactory->ResourceSize(*tag), true); g_tweakParticle = new DataSpec::DNAMP1::CTweakParticle(*strm); /* Player */ - tag = factory.GetResourceIdByName("Player"); - strm.emplace(factory.LoadResourceSync(*tag).release(), factory.ResourceSize(*tag)); + tag = g_ResFactory->GetResourceIdByName("Player"); + strm.emplace(g_ResFactory->LoadResourceSync(*tag).release(), g_ResFactory->ResourceSize(*tag), true); g_tweakPlayer = new DataSpec::DNAMP1::CTweakPlayer(*strm); /* CameraBob */ - tag = factory.GetResourceIdByName("CameraBob"); - strm.emplace(factory.LoadResourceSync(*tag).release(), factory.ResourceSize(*tag)); + tag = g_ResFactory->GetResourceIdByName("CameraBob"); + strm.emplace(g_ResFactory->LoadResourceSync(*tag).release(), g_ResFactory->ResourceSize(*tag), true); CPlayerCameraBob::ReadTweaks(*strm); /* Ball */ - tag = factory.GetResourceIdByName("Ball"); - strm.emplace(factory.LoadResourceSync(*tag).release(), factory.ResourceSize(*tag)); + tag = g_ResFactory->GetResourceIdByName("Ball"); + strm.emplace(g_ResFactory->LoadResourceSync(*tag).release(), g_ResFactory->ResourceSize(*tag), true); g_tweakBall = new DataSpec::DNAMP1::CTweakBall(*strm); /* PlayerGun */ - tag = factory.GetResourceIdByName("PlayerGun"); - strm.emplace(factory.LoadResourceSync(*tag).release(), factory.ResourceSize(*tag)); + tag = g_ResFactory->GetResourceIdByName("PlayerGun"); + strm.emplace(g_ResFactory->LoadResourceSync(*tag).release(), g_ResFactory->ResourceSize(*tag), true); g_tweakPlayerGun = new DataSpec::DNAMP1::CTweakPlayerGun(*strm); /* Targeting */ - tag = factory.GetResourceIdByName("Targeting"); - strm.emplace(factory.LoadResourceSync(*tag).release(), factory.ResourceSize(*tag)); + tag = g_ResFactory->GetResourceIdByName("Targeting"); + strm.emplace(g_ResFactory->LoadResourceSync(*tag).release(), g_ResFactory->ResourceSize(*tag), true); g_tweakTargeting = new DataSpec::DNAMP1::CTweakTargeting(*strm); /* Game */ - tag = factory.GetResourceIdByName("Game"); - strm.emplace(factory.LoadResourceSync(*tag).release(), factory.ResourceSize(*tag)); + tag = g_ResFactory->GetResourceIdByName("Game"); + strm.emplace(g_ResFactory->LoadResourceSync(*tag).release(), g_ResFactory->ResourceSize(*tag), true); g_tweakGame = new DataSpec::DNAMP1::CTweakGame(*strm); /* GuiColors */ - tag = factory.GetResourceIdByName("GuiColors"); - strm.emplace(factory.LoadResourceSync(*tag).release(), factory.ResourceSize(*tag)); + tag = g_ResFactory->GetResourceIdByName("GuiColors"); + strm.emplace(g_ResFactory->LoadResourceSync(*tag).release(), g_ResFactory->ResourceSize(*tag), true); g_tweakGuiColors = new DataSpec::DNAMP1::CTweakGuiColors(*strm); /* AutoMapper */ - tag = factory.GetResourceIdByName("AutoMapper"); - strm.emplace(factory.LoadResourceSync(*tag).release(), factory.ResourceSize(*tag)); + tag = g_ResFactory->GetResourceIdByName("AutoMapper"); + strm.emplace(g_ResFactory->LoadResourceSync(*tag).release(), g_ResFactory->ResourceSize(*tag), true); g_tweakAutoMapper = new DataSpec::DNAMP1::CTweakAutoMapper(*strm); CMappableObject::ReadAutoMapperTweaks(*g_tweakAutoMapper); /* Gui */ - tag = factory.GetResourceIdByName("Gui"); - strm.emplace(factory.LoadResourceSync(*tag).release(), factory.ResourceSize(*tag)); + tag = g_ResFactory->GetResourceIdByName("Gui"); + strm.emplace(g_ResFactory->LoadResourceSync(*tag).release(), g_ResFactory->ResourceSize(*tag), true); g_tweakGui = new DataSpec::DNAMP1::CTweakGui(*strm); /* PlayerControls */ - tag = factory.GetResourceIdByName("PlayerControls"); - strm.emplace(factory.LoadResourceSync(*tag).release(), factory.ResourceSize(*tag)); + tag = g_ResFactory->GetResourceIdByName("PlayerControls"); + strm.emplace(g_ResFactory->LoadResourceSync(*tag).release(), g_ResFactory->ResourceSize(*tag), true); g_tweakPlayerControl = new DataSpec::DNAMP1::CTweakPlayerControl(*strm); /* PlayerControls2 */ - tag = factory.GetResourceIdByName("PlayerControls2"); - strm.emplace(factory.LoadResourceSync(*tag).release(), factory.ResourceSize(*tag)); + tag = g_ResFactory->GetResourceIdByName("PlayerControls2"); + strm.emplace(g_ResFactory->LoadResourceSync(*tag).release(), g_ResFactory->ResourceSize(*tag), true); g_tweakPlayerControlAlt = new DataSpec::DNAMP1::CTweakPlayerControl(*strm); g_currentPlayerControl = g_tweakPlayerControl; /* SlideShow */ - tag = factory.GetResourceIdByName("SlideShow"); - strm.emplace(factory.LoadResourceSync(*tag).release(), factory.ResourceSize(*tag)); + tag = g_ResFactory->GetResourceIdByName("SlideShow"); + strm.emplace(g_ResFactory->LoadResourceSync(*tag).release(), g_ResFactory->ResourceSize(*tag), true); g_tweakSlideShow = new DataSpec::DNAMP1::CTweakSlideShow(*strm); } void CTweaks::RegisterResourceTweaks() { - ProjectResourceFactoryMP1& factory = ProjectManager::g_SharedManager->resourceFactoryMP1(); std::experimental::optional strm; - const SObjectTag* tag = factory.GetResourceIdByName("GunRes"); - strm.emplace(factory.LoadResourceSync(*tag).release(), factory.ResourceSize(*tag)); + const SObjectTag* tag = g_ResFactory->GetResourceIdByName("GunRes"); + strm.emplace(g_ResFactory->LoadResourceSync(*tag).release(), g_ResFactory->ResourceSize(*tag), true); g_tweakGunRes = new DataSpec::DNAMP1::CTweakGunRes(*strm); - g_tweakGunRes->ResolveResources(factory); + g_tweakGunRes->ResolveResources(*g_ResFactory); - tag = factory.GetResourceIdByName("PlayerRes"); - strm.emplace(factory.LoadResourceSync(*tag).release(), factory.ResourceSize(*tag)); + tag = g_ResFactory->GetResourceIdByName("PlayerRes"); + strm.emplace(g_ResFactory->LoadResourceSync(*tag).release(), g_ResFactory->ResourceSize(*tag), true); g_tweakPlayerRes = new DataSpec::DNAMP1::CTweakPlayerRes(*strm); - g_tweakPlayerRes->ResolveResources(factory); + g_tweakPlayerRes->ResolveResources(*g_ResFactory); } } diff --git a/Runtime/MP1/MP1.cpp b/Runtime/MP1/MP1.cpp index b07f17036..7e9ee10aa 100644 --- a/Runtime/MP1/MP1.cpp +++ b/Runtime/MP1/MP1.cpp @@ -296,6 +296,8 @@ void CGameGlobalObjects::AddPaksAndFactories() loader->AddPakFileAsync("SamGunFx", true, false); loader->AddPakFileAsync("MidiData", false, false); loader->AddPakFileAsync("GGuiSys", false, false); + loader->AddPakFileAsync("!original_ids", false, false); + loader->WaitForPakFileLoadingComplete(); } if (CFactoryMgr* fmgr = g_ResFactory->GetFactoryMgr()) @@ -333,16 +335,19 @@ void CGameGlobalObjects::AddPaksAndFactories() void CMain::AddWorldPaks() { + CResLoader* loader = g_ResFactory->GetResLoader(); + if (!loader) + return; auto& pakPrefix = g_tweakGame->GetWorldPrefix(); for (int i=0 ; i<9 ; ++i) { std::string path = pakPrefix; if (i != 0) path += '0' + i; - if (CDvdFile::FileExists(path.c_str())) - if (CResLoader* loader = g_ResFactory->GetResLoader()) - loader->AddPakFileAsync(path, false, true); + if (CDvdFile::FileExists((path + ".upak").c_str())) + loader->AddPakFileAsync(path, false, true); } + loader->WaitForPakFileLoadingComplete(); } void CMain::ResetGameState() @@ -449,16 +454,24 @@ void CMain::WarmupShaders() }); m_warmupTags.reserve(modelCount); + std::unordered_set addedTags; + addedTags.reserve(modelCount); + g_ResFactory->EnumerateResources([&](const SObjectTag& tag) { if (tag.type == FOURCC('CMDL') || tag.type == FOURCC('MREA')) + { + if (addedTags.find(tag) != addedTags.end()) + return true; + addedTags.insert(tag); m_warmupTags.push_back(tag); + } return true; }); m_warmupIt = m_warmupTags.begin(); - WarmupLog.report(logvisor::Info, "Began warmup of %" PRISize " objects", modelCount); + WarmupLog.report(logvisor::Info, "Began warmup of %" PRISize " objects", m_warmupTags.size()); } bool CMain::Proc() diff --git a/Runtime/World/CGameArea.cpp b/Runtime/World/CGameArea.cpp index 13ef9fe26..e85a282bd 100644 --- a/Runtime/World/CGameArea.cpp +++ b/Runtime/World/CGameArea.cpp @@ -416,7 +416,7 @@ CGameArea::CGameArea(CAssetId mreaId) { while (StartStreamingMainArea()) for (auto& req : xf8_loadTransactions) - req->WaitForComplete(); + req->WaitUntilComplete(); MREAHeader header = VerifyHeader(); x12c_postConstructed->x4c_insts.resize(header.modelCount); @@ -794,8 +794,7 @@ u32 CGameArea::GetNumPartSizes() const void CGameArea::AllocNewAreaData(int offset, int size) { x110_mreaSecBufs.emplace_back(std::unique_ptr(new u8[size]), size); - xf8_loadTransactions.push_back( - static_cast(g_ResFactory)-> + xf8_loadTransactions.push_back(g_ResFactory-> LoadResourcePartAsync(SObjectTag{FOURCC('MREA'), x84_mrea}, size, offset, x110_mreaSecBufs.back().first.get())); } @@ -809,7 +808,7 @@ void CGameArea::CullDeadAreaRequests() { for (auto it = xf8_loadTransactions.begin() ; it != xf8_loadTransactions.end() ;) { - if ((*it)->m_complete) + if ((*it)->IsComplete()) { it = xf8_loadTransactions.erase(it); continue; @@ -856,7 +855,7 @@ void CGameArea::Validate(CStateManager& mgr) while (StartStreamingMainArea()) {} for (auto& req : xf8_loadTransactions) - req->WaitForComplete(); + req->WaitUntilComplete(); if (xdc_tokens.empty()) { diff --git a/Runtime/World/CGameArea.hpp b/Runtime/World/CGameArea.hpp index 0317d6a02..4e24c3dd0 100644 --- a/Runtime/World/CGameArea.hpp +++ b/Runtime/World/CGameArea.hpp @@ -123,7 +123,7 @@ class CGameArea : public IGameArea WaitForFinish } xf4_phase = EPhase::LoadHeader; - std::list> xf8_loadTransactions; + std::list> xf8_loadTransactions; public: diff --git a/Runtime/World/CWorld.cpp b/Runtime/World/CWorld.cpp index 94541d218..18bdfc61c 100644 --- a/Runtime/World/CWorld.cpp +++ b/Runtime/World/CWorld.cpp @@ -18,7 +18,8 @@ CWorld::CSoundGroupData::CSoundGroupData(int grpId, CAssetId agsc) : x0_groupId( CDummyWorld::CDummyWorld(CAssetId mlvlId, bool loadMap) : x4_loadMap(loadMap), xc_mlvlId(mlvlId) { SObjectTag tag{FOURCC('MLVL'), mlvlId}; - static_cast(g_ResFactory)->LoadResourceAsync(tag, x34_loadBuf); + x34_loadBuf.reset(new u8[g_ResFactory->ResourceSize(tag)]); + g_ResFactory->LoadResourceAsync(tag, x34_loadBuf.get()); } CAssetId CDummyWorld::IGetWorldAssetId() const { return xc_mlvlId; } @@ -186,7 +187,8 @@ CWorld::CWorld(IObjectStore& objStore, IFactory& resFactory, CAssetId mlvlId) { x70_24_currentAreaNeedsAllocation = true; SObjectTag tag{FOURCC('MLVL'), mlvlId}; - static_cast(resFactory).LoadResourceAsync(tag, x40_loadBuf); + x40_loadBuf.reset(new u8[resFactory.ResourceSize(tag)]); + resFactory.LoadResourceAsync(tag, x40_loadBuf.get()); } CAssetId CWorld::IGetWorldAssetId() const { return x8_mlvlId; } diff --git a/hecl b/hecl index 038917dc5..e6f5ea29c 160000 --- a/hecl +++ b/hecl @@ -1 +1 @@ -Subproject commit 038917dc59aaf50efed8925ff5fd53d62fd8cfe8 +Subproject commit e6f5ea29c23008f5eb4aa353b4adc8a82b4a0332