#include "CPakFile.hpp" namespace urde { static logvisor::Module Log("urde::CPakFile"); CPakFile::CPakFile(const std::string& filename, bool buildDepList, bool worldPak) : CDvdFile(filename.c_str()) { x28_24_buildDepList = buildDepList; x28_26_worldPak = worldPak; } const SObjectTag* CPakFile::GetResIdByName(const char* name) const { for (const std::pair& p : x54_nameList) if (!CStringExtras::CompareCaseInsensitive(p.first.c_str(), name)) return &p.second; return nullptr; } void CPakFile::LoadResourceTable(athena::io::MemoryReader& r) { x74_resList.reserve(std::max(size_t(64), size_t(ROUND_UP_32(x4c_resTableCount * sizeof(SResInfo)) + sizeof(SResInfo) - 1)) / sizeof(SResInfo)); if (x28_24_buildDepList) x64_depList.reserve(x4c_resTableCount); for (u32 i=0 ; i origSize) { x38_headerData.resize(newSize); x30_dvdReq = AsyncSeekRead(x38_headerData.data() + origSize, u32(x38_headerData.size() - origSize), ESeekOrigin::Begin, origSize); } else { DataLoad(); } }; void CPakFile::Warmup() { u32 length = std::min(u32(Length()), u32(8192)); x38_headerData.resize(length); x30_dvdReq = AsyncSeekRead(x38_headerData.data(), length, ESeekOrigin::Cur, 0); x2c_asyncLoadPhase = EAsyncPhase::InitialHeader; } const CPakFile::SResInfo* CPakFile::GetResInfoForLoadPreferForward(CAssetId id) const { if (!x28_27_worldPakInitialized) 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; }); if (search == x74_resList.end()) return nullptr; const SResInfo* bestInfo = &*search; s32 bestDelta = x84_currentSeek - bestInfo->GetOffset(); while (++search != x74_resList.end()) { const SResInfo* thisInfo = &*search; if (thisInfo->x0_id != id) break; s32 thisDelta = x84_currentSeek - bestInfo->GetOffset(); if ((bestDelta < 0 && (thisDelta > 0 || thisDelta > bestDelta)) || (bestDelta >= 0 && thisDelta > 0 && thisDelta < bestDelta)) { bestDelta = thisDelta; bestInfo = thisInfo; } } x84_currentSeek = bestInfo->GetOffset() + bestInfo->GetSize(); return bestInfo; } const CPakFile::SResInfo* CPakFile::GetResInfoForLoadDirectionless(CAssetId id) const { if (!x28_27_worldPakInitialized) 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; }); if (search == x74_resList.end()) return nullptr; const SResInfo* bestInfo = &*search; s32 bestDelta = std::abs(s32(x84_currentSeek - bestInfo->GetOffset())); while (++search != x74_resList.end()) { const SResInfo* thisInfo = &*search; if (thisInfo->x0_id != id) break; s32 thisDelta = std::abs(s32(x84_currentSeek - bestInfo->GetOffset())); if (thisDelta < bestDelta) { bestDelta = thisDelta; bestInfo = thisInfo; } } x84_currentSeek = bestInfo->GetOffset() + bestInfo->GetSize(); return bestInfo; } const CPakFile::SResInfo* CPakFile::GetResInfo(CAssetId id) const { if (x2c_asyncLoadPhase != EAsyncPhase::Loaded) return nullptr; if (!x28_27_worldPakInitialized) return nullptr; auto search = rstl::binary_find(x74_resList.begin(), x74_resList.end(), id, [](const SResInfo& i) { return i.x0_id; }); if (search == x74_resList.end()) return nullptr; return &*search; } void CPakFile::AsyncIdle() { if (x2c_asyncLoadPhase == EAsyncPhase::Loaded) return; if (x30_dvdReq && x30_dvdReq->IsComplete()) return; switch (x2c_asyncLoadPhase) { case EAsyncPhase::Warmup: Warmup(); break; case EAsyncPhase::InitialHeader: InitialHeaderLoad(); break; case EAsyncPhase::DataLoad: DataLoad(); break; default: break; } } }