metaforce/Runtime/CResLoader.cpp

318 lines
9.3 KiB
C++
Raw Normal View History

2015-08-23 23:58:07 +00:00
#include "CResLoader.hpp"
#include "CPakFile.hpp"
2016-03-04 23:04:53 +00:00
namespace urde
2015-08-23 23:58:07 +00:00
{
2017-10-27 10:10:32 +00:00
static logvisor::Module Log("CResLoader");
2015-08-23 23:58:07 +00:00
2017-10-26 05:37:46 +00:00
CResLoader::CResLoader()
{
x48_curPak = x18_pakLoadedList.end();
}
2017-11-13 06:19:18 +00:00
const std::vector<CAssetId>* CResLoader::GetTagListForFile(std::string_view name) const
2015-08-23 23:58:07 +00:00
{
2017-11-13 06:19:18 +00:00
std::string namePak = std::string(name) + ".upak";
2017-02-08 06:48:43 +00:00
for (const std::unique_ptr<CPakFile>& pak : x18_pakLoadedList)
2016-03-07 03:12:32 +00:00
if (!CStringExtras::CompareCaseInsensitive(namePak, pak->x18_path))
2015-08-23 23:58:07 +00:00
return &pak->GetDepList();
return nullptr;
}
2017-11-13 06:19:18 +00:00
void CResLoader::AddPakFileAsync(std::string_view name, bool buildDepList, bool worldPak)
2015-08-23 23:58:07 +00:00
{
2017-11-13 06:19:18 +00:00
std::string namePak = std::string(name) + ".upak";
2015-08-23 23:58:07 +00:00
if (CDvdFile::FileExists(namePak.c_str()))
{
2017-10-27 10:10:32 +00:00
x30_pakLoadingList.emplace_back(new CPakFile(namePak, buildDepList, worldPak));
2015-08-23 23:58:07 +00:00
++x44_pakLoadingCount;
}
}
2017-11-13 06:19:18 +00:00
void CResLoader::AddPakFile(std::string_view name, bool samusPak, bool worldPak)
2015-08-23 23:58:07 +00:00
{
2017-02-08 06:48:43 +00:00
AddPakFileAsync(name, samusPak, worldPak);
2017-10-27 10:10:32 +00:00
WaitForPakFileLoadingComplete();
}
void CResLoader::WaitForPakFileLoadingComplete()
{
2015-08-23 23:58:07 +00:00
while (x44_pakLoadingCount)
AsyncIdlePakLoading();
}
2017-10-27 10:10:32 +00:00
std::unique_ptr<CInputStream> CResLoader::LoadNewResourcePartSync(const SObjectTag& tag, u32 length, u32 offset, void* extBuf)
2015-08-23 23:58:07 +00:00
{
void* buf = extBuf;
CPakFile* file = FindResourceForLoad(tag);
if (!buf)
2016-04-15 20:42:40 +00:00
buf = new u8[length];
2017-10-26 05:37:46 +00:00
file->SyncSeekRead(buf, length, ESeekOrigin::Begin, x50_cachedResInfo->GetOffset() + offset);
return std::unique_ptr<CInputStream>(new athena::io::MemoryReader((atUint8*)buf, length, !extBuf));
2015-08-23 23:58:07 +00:00
}
2017-10-26 05:37:46 +00:00
void CResLoader::LoadMemResourceSync(const SObjectTag& tag, std::unique_ptr<u8[]>& bufOut, int* sizeOut)
2015-08-23 23:58:07 +00:00
{
2017-10-28 07:08:48 +00:00
if (CPakFile* file = FindResourceForLoad(tag))
{
bufOut = std::unique_ptr<u8[]>(new u8[x50_cachedResInfo->GetSize()]);
file->SyncSeekRead(bufOut.get(), x50_cachedResInfo->GetSize(), ESeekOrigin::Begin,
x50_cachedResInfo->GetOffset());
*sizeOut = x50_cachedResInfo->GetSize();
}
2015-08-23 23:58:07 +00:00
}
2017-10-26 05:37:46 +00:00
std::unique_ptr<CInputStream> CResLoader::LoadResourceFromMemorySync(const SObjectTag& tag, const void* buf)
2015-08-23 23:58:07 +00:00
{
FindResourceForLoad(tag);
2017-10-26 05:37:46 +00:00
CInputStream* newStrm = new athena::io::MemoryReader((atUint8*)buf, x50_cachedResInfo->GetSize());
if (x50_cachedResInfo->IsCompressed())
2015-08-23 23:58:07 +00:00
{
newStrm->readUint32Big();
newStrm = new CZipInputStream(std::unique_ptr<CInputStream>(newStrm));
2015-08-23 23:58:07 +00:00
}
2017-10-26 05:37:46 +00:00
return std::unique_ptr<CInputStream>(newStrm);
2015-08-23 23:58:07 +00:00
}
2017-10-26 05:37:46 +00:00
std::unique_ptr<CInputStream> CResLoader::LoadNewResourceSync(const SObjectTag& tag, void* extBuf)
2015-08-23 23:58:07 +00:00
{
void* buf = extBuf;
2017-10-28 07:08:48 +00:00
if (CPakFile* file = FindResourceForLoad(tag))
2015-08-23 23:58:07 +00:00
{
2017-10-28 07:08:48 +00:00
size_t resSz = ROUND_UP_32(x50_cachedResInfo->GetSize());
if (!buf)
buf = new u8[resSz];
file->SyncSeekRead(buf, resSz, ESeekOrigin::Begin, x50_cachedResInfo->GetOffset());
CInputStream* newStrm = new athena::io::MemoryReader((atUint8*) buf, resSz, !extBuf);
if (x50_cachedResInfo->IsCompressed())
{
newStrm->readUint32Big();
newStrm = new CZipInputStream(std::unique_ptr<CInputStream>(newStrm));
}
return std::unique_ptr<CInputStream>(newStrm);
2015-08-23 23:58:07 +00:00
}
2017-10-28 07:08:48 +00:00
return {};
2015-08-23 23:58:07 +00:00
}
2017-11-07 08:08:26 +00:00
std::shared_ptr<IDvdRequest> CResLoader::LoadResourcePartAsync(const SObjectTag& tag, u32 off, u32 size, void* buf)
2015-08-23 23:58:07 +00:00
{
2017-11-07 08:08:26 +00:00
CPakFile* file = FindResourceForLoad(tag.id);
return file->AsyncSeekRead(buf, size, ESeekOrigin::Begin, x50_cachedResInfo->GetOffset() + off);
2015-08-23 23:58:07 +00:00
}
2016-03-07 03:12:32 +00:00
std::shared_ptr<IDvdRequest> CResLoader::LoadResourceAsync(const SObjectTag& tag, void* buf)
2015-08-23 23:58:07 +00:00
{
2017-11-07 08:08:26 +00:00
CPakFile* file = FindResourceForLoad(tag.id);
return file->AsyncSeekRead(buf, ROUND_UP_32(x50_cachedResInfo->GetSize()),
ESeekOrigin::Begin, x50_cachedResInfo->GetOffset());
2015-08-23 23:58:07 +00:00
}
std::unique_ptr<u8[]> CResLoader::LoadResourceSync(const urde::SObjectTag& tag)
{
CPakFile* file = FindResourceForLoad(tag.id);
u32 size = ROUND_UP_32(x50_cachedResInfo->GetSize());
std::unique_ptr<u8[]> ret(new u8[size]);
file->SyncSeekRead(ret.get(), size, ESeekOrigin::Begin, x50_cachedResInfo->GetOffset());
return ret;
}
2017-11-05 02:08:05 +00:00
std::unique_ptr<u8[]> CResLoader::LoadNewResourcePartSync(const urde::SObjectTag& tag, u32 off, u32 size)
{
CPakFile* file = FindResourceForLoad(tag.id);
std::unique_ptr<u8[]> ret(new u8[size]);
file->SyncSeekRead(ret.get(), size, ESeekOrigin::Begin, x50_cachedResInfo->GetOffset() + off);
return ret;
}
2017-10-28 07:08:48 +00:00
void CResLoader::GetTagListForFile(const char* pakName, std::vector<SObjectTag>& out) const
{
std::string path = std::string(pakName) + ".upak";
for (const std::unique_ptr<CPakFile>& file : x18_pakLoadedList)
{
if (!CStringExtras::CompareCaseInsensitive(file->GetPath(), path))
{
auto& depList = file->GetDepList();
out.reserve(depList.size());
for (const auto& dep : depList)
{
auto resInfo = file->GetResInfo(dep);
out.emplace_back(resInfo->GetType(), dep);
}
return;
}
}
}
2015-08-23 23:58:07 +00:00
bool CResLoader::GetResourceCompression(const SObjectTag& tag)
{
if (FindResource(tag.id))
2017-10-26 05:37:46 +00:00
return x50_cachedResInfo->IsCompressed();
2015-08-23 23:58:07 +00:00
return false;
}
u32 CResLoader::ResourceSize(const SObjectTag& tag)
{
if (FindResource(tag.id))
2017-10-26 05:37:46 +00:00
return x50_cachedResInfo->GetSize();
return 0;
2015-08-23 23:58:07 +00:00
}
bool CResLoader::ResourceExists(const SObjectTag& tag)
{
return FindResource(tag.id);
}
2017-08-13 05:26:14 +00:00
FourCC CResLoader::GetResourceTypeById(CAssetId id) const
2015-08-23 23:58:07 +00:00
{
2017-11-15 04:12:13 +00:00
if (id.IsValid() && FindResource(id))
2017-10-26 05:37:46 +00:00
return x50_cachedResInfo->GetType();
return {};
2015-08-23 23:58:07 +00:00
}
2017-11-13 06:19:18 +00:00
const SObjectTag* CResLoader::GetResourceIdByName(std::string_view name) const
2015-08-23 23:58:07 +00:00
{
2017-02-08 06:48:43 +00:00
for (const std::unique_ptr<CPakFile>& file : x18_pakLoadedList)
2017-11-16 03:24:20 +00:00
if (const SObjectTag* id = file->GetResIdByName(name))
2015-08-23 23:58:07 +00:00
return id;
2015-08-28 00:11:31 +00:00
return nullptr;
2015-08-23 23:58:07 +00:00
}
bool CResLoader::AreAllPaksLoaded() const
{
return x44_pakLoadingCount == 0;
}
void CResLoader::AsyncIdlePakLoading()
{
2017-02-08 06:48:43 +00:00
for (auto it=x30_pakLoadingList.begin();
2017-11-07 08:08:26 +00:00
it != x30_pakLoadingList.end();)
2015-08-23 23:58:07 +00:00
{
(*it)->AsyncIdle();
2015-11-21 01:16:07 +00:00
if ((*it)->x2c_asyncLoadPhase == CPakFile::EAsyncPhase::Loaded)
2015-08-23 23:58:07 +00:00
{
MoveToCorrectLoadedList(std::move(*it));
2017-02-08 06:48:43 +00:00
it = x30_pakLoadingList.erase(it);
2015-08-23 23:58:07 +00:00
--x44_pakLoadingCount;
2017-11-07 08:08:26 +00:00
continue;
2015-08-23 23:58:07 +00:00
}
2017-11-07 08:08:26 +00:00
++it;
2015-08-23 23:58:07 +00:00
}
}
2017-08-13 05:26:14 +00:00
bool CResLoader::FindResource(CAssetId id) const
2015-08-23 23:58:07 +00:00
{
2017-10-26 05:37:46 +00:00
if (x4c_cachedResId == id)
return true;
if (x48_curPak != x18_pakLoadedList.end())
if (CacheFromPak(**x48_curPak, id))
2015-08-23 23:58:07 +00:00
return true;
2017-10-26 05:37:46 +00:00
for (auto it = x18_pakLoadedList.begin() ; it != x18_pakLoadedList.end() ; ++it)
{
if (it == x48_curPak)
continue;
if (CacheFromPak(**it, id))
return true;
}
Log.report(logvisor::Warning, "Unable to find asset %08X", id);
2015-08-23 23:58:07 +00:00
return false;
}
2017-08-13 05:26:14 +00:00
CPakFile* CResLoader::FindResourceForLoad(CAssetId id)
2015-08-23 23:58:07 +00:00
{
2017-10-26 05:37:46 +00:00
if (x48_curPak != x18_pakLoadedList.end())
if (CacheFromPakForLoad(**x48_curPak, id))
return &**x48_curPak;
for (auto it = x18_pakLoadedList.begin() ; it != x18_pakLoadedList.end() ; ++it)
{
if (it == x48_curPak)
continue;
if (CacheFromPakForLoad(**it, id))
{
x48_curPak = it;
return &**it;
}
}
2017-10-28 07:08:48 +00:00
Log.report(logvisor::Error, "Unable to find asset %08X", id);
2015-08-23 23:58:07 +00:00
return nullptr;
}
CPakFile* CResLoader::FindResourceForLoad(const SObjectTag& tag)
{
return FindResourceForLoad(tag.id);
}
2017-08-13 05:26:14 +00:00
bool CResLoader::CacheFromPakForLoad(CPakFile& file, CAssetId id)
2015-08-23 23:58:07 +00:00
{
2017-10-26 05:37:46 +00:00
const CPakFile::SResInfo* info;
if (x54_forwardSeek)
{
info = file.GetResInfoForLoadPreferForward(id);
x54_forwardSeek = false;
}
else
{
info = file.GetResInfoForLoadDirectionless(id);
}
2015-08-23 23:58:07 +00:00
if (info)
{
x4c_cachedResId = id;
x50_cachedResInfo = info;
return true;
}
return false;
}
2017-10-26 05:37:46 +00:00
bool CResLoader::CacheFromPak(const CPakFile& file, CAssetId id) const
2015-08-23 23:58:07 +00:00
{
const CPakFile::SResInfo* info = file.GetResInfo(id);
if (info)
{
x4c_cachedResId = id;
x50_cachedResInfo = info;
return true;
}
return false;
}
void CResLoader::MoveToCorrectLoadedList(std::unique_ptr<CPakFile>&& file)
{
2017-02-08 06:48:43 +00:00
x18_pakLoadedList.push_back(std::move(file));
2015-08-23 23:58:07 +00:00
}
std::vector<std::pair<std::string, SObjectTag>> CResLoader::GetResourceIdToNameList() const
{
std::vector<std::pair<std::string, SObjectTag>> ret;
for (auto it = x18_pakLoadedList.begin() ; it != x18_pakLoadedList.end() ; ++it)
for (const auto& name : (*it)->GetNameList())
ret.push_back(name);
return ret;
}
void CResLoader::EnumerateResources(const std::function<bool(const SObjectTag&)>& lambda) const
{
for (auto it = x18_pakLoadedList.begin() ; it != x18_pakLoadedList.end() ; ++it)
{
for (const CAssetId& id : (*it)->GetDepList())
{
SObjectTag fcc(GetResourceTypeById(id), id);
if (!lambda(fcc))
return;
}
}
}
2017-11-13 06:19:18 +00:00
void CResLoader::EnumerateNamedResources(const std::function<bool(std::string_view, const SObjectTag&)>& lambda) const
{
for (auto it = x18_pakLoadedList.begin() ; it != x18_pakLoadedList.end() ; ++it)
for (const auto& name : (*it)->GetNameList())
if (!lambda(name.first, name.second))
return;
}
2015-08-23 23:58:07 +00:00
}