Finish CPakFile and CResLoader

This commit is contained in:
Jack Andersen 2017-10-25 19:37:46 -10:00
parent e274cd12b9
commit 7c3fb4174f
20 changed files with 561 additions and 124 deletions

View File

@ -315,6 +315,10 @@ bool MLVL::Cook(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPat
}
}
urde::SObjectTag pathTag = g_curSpec->buildTagFromPath(areaPath.ensureAuxInfo(_S("PATH")), btok);
if (pathTag.id.IsValid())
areaOut.deps.emplace_back(pathTag.id.Value(), pathTag.type);
urde::SObjectTag tag = g_curSpec->buildTagFromPath(areaPath, btok);
if (tag.id.IsValid())
areaOut.deps.emplace_back(tag.id.Value(), tag.type);

View File

@ -365,6 +365,7 @@ void SpecBase::flattenDependencies(const hecl::ProjectPath& path,
}
case hecl::BlenderConnection::BlendType::Actor:
{
hecl::ProjectPath asGlob = path.getWithExtension(_S(".*"), true);
hecl::BlenderConnection::DataStream ds = conn.beginData();
hecl::BlenderConnection::DataStream::Actor actor = ds.compileActorCharacterOnly();
for (auto& sub : actor.subtypes)
@ -374,20 +375,32 @@ void SpecBase::flattenDependencies(const hecl::ProjectPath& path,
pathsOut.push_back(sub.mesh);
hecl::SystemStringView chSysName(sub.name);
pathsOut.push_back(path.ensureAuxInfo(chSysName.sys_str() + _S(".CSKR")));
pathsOut.push_back(asGlob.ensureAuxInfo(chSysName.sys_str() + _S(".CSKR")));
const auto& arm = actor.armatures[sub.armature];
hecl::SystemStringView armSysName(arm.name);
pathsOut.push_back(path.ensureAuxInfo(armSysName.sys_str() + _S(".CINF")));
pathsOut.push_back(asGlob.ensureAuxInfo(armSysName.sys_str() + _S(".CINF")));
for (const auto& overlay : sub.overlayMeshes)
{
pathsOut.push_back(overlay.second);
pathsOut.push_back(path.ensureAuxInfo(chSysName.sys_str() + _S('.') +
overlay.first + _S(".CSKR")));
pathsOut.push_back(asGlob.ensureAuxInfo(chSysName.sys_str() + _S('.') +
overlay.first + _S(".CSKR")));
}
}
}
break;
auto actNames = ds.getActionNames();
for (const auto& act : actNames)
{
hecl::SystemStringView actSysName(act);
pathsOut.push_back(asGlob.ensureAuxInfo(actSysName.sys_str() + _S(".ANIM")));
hecl::ProjectPath evntPath = asGlob.getWithExtension(
hecl::SysFormat(_S(".%s.evnt.yaml"), actSysName.c_str()).c_str(), true);
if (evntPath.isFile())
pathsOut.push_back(evntPath);
}
pathsOut.push_back(asGlob);
return;
}
case hecl::BlenderConnection::BlendType::Area:
{
@ -439,6 +452,7 @@ bool SpecBase::canPackage(const hecl::ProjectPath& path)
}
void SpecBase::recursiveBuildResourceList(std::vector<urde::SObjectTag>& listOut,
std::unordered_set<urde::SObjectTag>& addedTags,
const hecl::ProjectPath& path,
hecl::BlenderToken& btok)
{
@ -448,9 +462,24 @@ void SpecBase::recursiveBuildResourceList(std::vector<urde::SObjectTag>& listOut
{
hecl::ProjectPath childPath(path, ent.m_name);
if (ent.m_isDir)
recursiveBuildResourceList(listOut, childPath, btok);
else if (urde::SObjectTag tag = tagFromPath(childPath, btok))
listOut.push_back(tag);
{
recursiveBuildResourceList(listOut, addedTags, childPath, btok);
}
else
{
std::vector<hecl::ProjectPath> subPaths;
flattenDependencies(childPath, subPaths, btok);
for (const auto& subPath : subPaths)
{
if (urde::SObjectTag tag = tagFromPath(subPath, btok))
{
if (addedTags.find(tag) != addedTags.end())
continue;
addedTags.insert(tag);
listOut.push_back(tag);
}
}
}
}
}
@ -535,7 +564,8 @@ void SpecBase::doPackage(const hecl::ProjectPath& path, const hecl::Database::Da
else if (path.getPathType() == hecl::ProjectPath::Type::Directory) /* General PAK */
{
/* Build resource list */
recursiveBuildResourceList(buildList, path, btok);
std::unordered_set<urde::SObjectTag> addedTags;
recursiveBuildResourceList(buildList, addedTags, path, btok);
std::vector<std::pair<urde::SObjectTag, std::string>> nameList;
/* Build name list */
@ -556,12 +586,19 @@ void SpecBase::doPackage(const hecl::ProjectPath& path, const hecl::Database::Da
/* Async cook resource list if using ClientProcess */
if (cp)
{
std::unordered_set<urde::SObjectTag> addedTags;
addedTags.reserve(buildList.size());
Log.report(logvisor::Info, _S("Validating resources"));
size_t loadIdx = 0;
for (auto& tag : buildList)
{
fprintf(stderr, "\r %" PRISize " / %" PRISize " %.4s %08X", ++loadIdx, buildList.size(),
tag.type.getChars(), (unsigned int)tag.id.Value());
if (addedTags.find(tag) != addedTags.end())
continue;
addedTags.insert(tag);
hecl::ProjectPath depPath = pathFromTag(tag);
if (!depPath)
{

View File

@ -187,6 +187,7 @@ protected:
void backgroundIndexProc();
void recursiveBuildResourceList(std::vector<urde::SObjectTag>& listOut,
std::unordered_set<urde::SObjectTag>& addedTags,
const hecl::ProjectPath& path,
hecl::BlenderToken& btok);
void copyBuildListData(std::vector<std::tuple<size_t, size_t, bool>>& fileIndex,

View File

@ -538,6 +538,15 @@ struct SpecMP1 : SpecBase
return {SBIG('AGSC'), glob.hash().val32()};
}
}
if (ext[0] == _S('*') || !hecl::StrCmp(ext, _S("mid")))
{
if (path.getWithExtension(_S(".mid"), true).isFile() &&
path.getWithExtension(_S(".yaml"), true).isFile())
{
hecl::ProjectPath glob = path.getWithExtension(_S(".*"), true);
return {SBIG('CSNG'), glob.hash().val32()};
}
}
}
hecl::ProjectPath asBlend;
@ -562,13 +571,13 @@ struct SpecMP1 : SpecBase
if (path.getAuxInfo().size())
{
if (hecl::StringUtils::EndsWith(path.getAuxInfo(), _S(".CINF")))
return {SBIG('CINF'), path.hash().val32()};
return {SBIG('CINF'), path.getWithExtension(_S(".*"), true).hash().val32()};
else if (hecl::StringUtils::EndsWith(path.getAuxInfo(), _S(".CSKR")))
return {SBIG('CSKR'), path.hash().val32()};
return {SBIG('CSKR'), path.getWithExtension(_S(".*"), true).hash().val32()};
else if (hecl::StringUtils::EndsWith(path.getAuxInfo(), _S(".ANIM")))
return {SBIG('ANIM'), path.hash().val32()};
return {SBIG('ANIM'), path.getWithExtension(_S(".*"), true).hash().val32()};
}
return {SBIG('ANCS'), path.hash().val32()};
return {SBIG('ANCS'), path.getWithExtension(_S(".*"), true).hash().val32()};
case hecl::BlenderConnection::BlendType::Area:
{
if (hecl::StringUtils::EndsWith(path.getAuxInfo(), _S("PATH")))
@ -580,11 +589,11 @@ struct SpecMP1 : SpecBase
if (path.getAuxInfo().size())
{
if (hecl::StringUtils::EndsWith(path.getAuxInfo(), _S("MAPW")))
return {SBIG('MAPW'), path.hash().val32()};
return {SBIG('MAPW'), path.getWithExtension(_S(".*"), true).hash().val32()};
else if (hecl::StringUtils::EndsWith(path.getAuxInfo(), _S("SAVW")))
return {SBIG('SAVW'), path.hash().val32()};
return {SBIG('SAVW'), path.getWithExtension(_S(".*"), true).hash().val32()};
}
return {SBIG('MLVL'), path.hash().val32()};
return {SBIG('MLVL'), path.getWithExtension(_S(".*"), true).hash().val32()};
}
case hecl::BlenderConnection::BlendType::MapArea:
return {SBIG('MAPA'), path.hash().val32()};
@ -1023,7 +1032,7 @@ struct SpecMP1 : SpecBase
mSeeds.read(reader);
WriteTweak(mSeeds, out);
}
else if (!classStr.compare(DNAMP1::MazeSeeds::DNAType()))
else if (!classStr.compare(DNAMP1::SnowForces::DNAType()))
{
DNAMP1::SnowForces sForces;
sForces.read(reader);
@ -1204,6 +1213,7 @@ struct SpecMP1 : SpecBase
urde::SObjectTag skyboxTag(FOURCC('CMDL'), mlvl.worldSkyboxId.toUint32());
if (skyboxTag)
{
listOut.push_back(skyboxTag);
hecl::ProjectPath skyboxPath = pathFromTag(skyboxTag);
if (btok.getBlenderConnection().openBlend(skyboxPath))
{
@ -1217,7 +1227,6 @@ struct SpecMP1 : SpecBase
listOut.push_back(texTag);
}
}
listOut.push_back(skyboxTag);
}
listOut.push_back(worldTag);

View File

@ -34,6 +34,7 @@
#include "Runtime/CDependencyGroup.hpp"
#include "DataSpec/DNACommon/TXTR.hpp"
#include "CSimplePool.hpp"
#include "MP1/MP1OriginalIDs.hpp"
#include "GameGlobalObjects.hpp"
namespace DataSpec
@ -45,57 +46,6 @@ extern hecl::Database::DataSpecEntry SpecEntMP1PC;
namespace urde
{
class MP1OriginalIDs
{
std::vector<std::pair<CAssetId, CAssetId>> m_origToNew;
std::vector<std::pair<CAssetId, CAssetId>> m_newToOrig;
public:
MP1OriginalIDs(CInputStream& in)
{
u32 count = in.readUint32Big();
m_origToNew.reserve(count);
for (u32 i=0 ; i<count ; ++i)
{
CAssetId a = in.readUint32Big();
CAssetId b = in.readUint32Big();
m_origToNew.push_back(std::make_pair(a, b));
}
m_newToOrig.reserve(count);
for (u32 i=0 ; i<count ; ++i)
{
CAssetId a = in.readUint32Big();
CAssetId b = in.readUint32Big();
m_newToOrig.push_back(std::make_pair(a, b));
}
}
CAssetId TranslateOriginalToNew(CAssetId id) const
{
auto search = rstl::binary_find(m_origToNew.cbegin(), m_origToNew.cend(), id,
[](const auto& id) { return id.first; });
if (search == m_origToNew.cend())
return -1;
return search->second;
}
CAssetId TranslateNewToOriginal(CAssetId id) const
{
auto search = rstl::binary_find(m_newToOrig.cbegin(), m_newToOrig.cend(), id,
[](const auto& id) { return id.first; });
if (search == m_newToOrig.cend())
return -1;
return search->second;
}
};
CFactoryFnReturn FMP1OriginalIDsFactory(const SObjectTag& tag, CInputStream& in,
const CVParamTransfer& param,
CObjectReference* selfRef)
{
return TToken<MP1OriginalIDs>::GetIObjObjectFor(std::make_unique<MP1OriginalIDs>(in));
}
ProjectResourceFactoryMP1::ProjectResourceFactoryMP1(hecl::ClientProcess& clientProc)
: ProjectResourceFactoryBase(clientProc)
{

View File

@ -65,4 +65,31 @@ CFactoryFnReturn CFactoryMgr::MakeObjectFromMemory(const SObjectTag& tag, std::u
}
}
static const FourCC TypeTable[] =
{
FOURCC('CLSN'), FOURCC('CMDL'), FOURCC('CSKR'), FOURCC('ANIM'), FOURCC('CINF'), FOURCC('TXTR'),
FOURCC('PLTT'), FOURCC('FONT'), FOURCC('ANCS'), FOURCC('EVNT'), FOURCC('MADF'), FOURCC('MLVL'),
FOURCC('MREA'), FOURCC('MAPW'), FOURCC('MAPA'), FOURCC('SAVW'), FOURCC('SAVA'), FOURCC('PART'),
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')
};
CFactoryMgr::ETypeTable CFactoryMgr::FourCCToTypeIdx(FourCC fcc)
{
for (int i=0 ; i<4 ; ++i)
fcc.getChars()[i] = char(std::toupper(fcc.getChars()[i]));
auto search = std::find_if(std::begin(TypeTable), std::end(TypeTable),
[fcc](const FourCC& test) { return test == fcc; });
if (search == std::end(TypeTable))
return ETypeTable::Invalid;
return ETypeTable(search - std::begin(TypeTable));
}
FourCC CFactoryMgr::TypeIdxToFourCC(ETypeTable fcc)
{
return TypeTable[int(fcc)];
}
}

View File

@ -27,6 +27,21 @@ public:
CObjectReference* selfRef);
void AddFactory(FourCC key, FFactoryFunc func) {m_factories[key] = func;}
void AddFactory(FourCC key, FMemFactoryFunc func) {m_memFactories[key] = func;}
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
};
static ETypeTable FourCCToTypeIdx(FourCC fcc);
static FourCC TypeIdxToFourCC(ETypeTable fcc);
};
}

View File

@ -2,6 +2,7 @@
namespace urde
{
static logvisor::Module Log("urde::CPakFile");
CPakFile::CPakFile(const std::string& filename, bool buildDepList, bool worldPak)
: CDvdFile(filename.c_str())
@ -18,6 +19,154 @@ const SObjectTag* CPakFile::GetResIdByName(const char* name) const
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<x4c_resTableCount ; ++i)
{
u32 flags = r.readUint32Big();
FourCC fcc;
r.readBytesToBuf(&fcc, 4);
CAssetId id = r.readUint32Big();
u32 size = r.readUint32Big();
u32 offset = r.readUint32Big();
x74_resList.emplace_back(id, fcc, offset, size, flags);
if (x28_24_buildDepList)
x64_depList.push_back(id);
}
std::sort(x74_resList.begin(), x74_resList.end(), [](const auto& a, const auto& b) { return a.x0_id < b.x0_id; });
}
void CPakFile::DataLoad()
{
x30_dvdReq.reset();
athena::io::MemoryReader r(x38_headerData.data() + x48_resTableOffset, x38_headerData.size() - x48_resTableOffset);
LoadResourceTable(r);
x2c_asyncLoadPhase = EAsyncPhase::Loaded;
if (x28_26_worldPak)
{
// Allocate ARAM space DMA x74_resList to ARAM
}
x38_headerData.clear();
}
void CPakFile::InitialHeaderLoad()
{
athena::io::MemoryReader r(x38_headerData.data(), x38_headerData.size());
x30_dvdReq.reset();
u32 version = r.readUint32Big();
if (version != 0x80030005)
{
Log.report(logvisor::Fatal, "%s: Incompatible pak file version -- Current version is %x, you're using %x",
GetPath().c_str(), 0x80030005, version);
return;
}
r.readUint32Big();
u32 nameCount = r.readUint32Big();
x54_nameList.reserve(nameCount);
for (u32 i=0 ; i<nameCount ; ++i)
{
SObjectTag tag(r);
u32 nameLen = r.readUint32Big();
auto name = r.readString(nameLen);
x54_nameList.emplace_back(name, tag);
}
x4c_resTableCount = r.readUint32Big();
x48_resTableOffset = u32(r.position());
x2c_asyncLoadPhase = EAsyncPhase::DataLoad;
u32 newSize = ROUND_UP_32(x4c_resTableCount * 16 + x48_resTableOffset);
u32 origSize = u32(x38_headerData.size());
if (newSize > 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)

View File

@ -6,6 +6,7 @@
#include "CStringExtras.hpp"
#include "CDvdFile.hpp"
#include "CDvdRequest.hpp"
#include "CFactoryMgr.hpp"
namespace urde
{
@ -16,10 +17,24 @@ class CPakFile : public CDvdFile
public:
struct SResInfo
{
FourCC x0_type;
u32 x4_offset;
u32 x8_size;
bool xb_compressed;
CAssetId x0_id;
bool x4_compressed : 1;
CFactoryMgr::ETypeTable x4_typeIdx : 7;
u32 x5_offsetDiv32 : 27;
u32 x7_sizeDiv32 : 27;
SResInfo(CAssetId id, FourCC fcc, u32 offset, u32 size, u32 flags)
: x0_id(id)
{
x4_compressed = flags != 0;
x4_typeIdx = CFactoryMgr::FourCCToTypeIdx(fcc);
x5_offsetDiv32 = offset / 32;
x7_sizeDiv32 = size / 32;
}
u32 GetOffset() const { return x5_offsetDiv32 * 32; }
u32 GetSize() const { return x7_sizeDiv32 * 32; }
FourCC GetType() const { return CFactoryMgr::TypeIdxToFourCC(x4_typeIdx); }
bool IsCompressed() const { return x4_compressed; }
CAssetId GetId() const { return x0_id; }
};
private:
union
@ -39,25 +54,28 @@ private:
InitialHeader = 1,
DataLoad = 2,
Loaded = 3
} x2c_asyncLoadPhase;
} x2c_asyncLoadPhase = EAsyncPhase::Warmup;
std::shared_ptr<IDvdRequest> x30_dvdReq; // Used to be auto_ptr
std::vector<u8> x38_headerData;
u32 x48_resTableOffset = 0;
u32 x4c_resTableCount = 0;
int x50_ = -1;
int x50_aramBase = -1;
std::vector<std::pair<std::string, SObjectTag>> x54_nameList;
std::vector<CAssetId> x64_depList;
std::vector<std::pair<CAssetId, SResInfo>> x74_resList;
std::vector<SResInfo> x74_resList;
mutable s32 x84_currentSeek = -1;
void LoadResourceTable(athena::io::MemoryReader& r);
void DataLoad();
void InitialHeaderLoad();
void Warmup();
public:
CPakFile(const std::string& filename, bool buildDepList, bool worldPak);
const std::vector<CAssetId>& GetDepList() const { return x64_depList; }
const SObjectTag* GetResIdByName(const char* name) const;
const SResInfo* GetResInfoForLoad(CAssetId id) { return nullptr; }
const SResInfo* GetResInfo(CAssetId id) const { return nullptr; }
const SResInfo* GetResInfoForLoadPreferForward(CAssetId id) const;
const SResInfo* GetResInfoForLoadDirectionless(CAssetId id) const;
const SResInfo* GetResInfo(CAssetId id) const;
u32 GetFakeStaticSize() const { return 0; }
void DataLoad() {}
void InitialHeaderLoad() {}
void Warmup() {}
void AsyncIdle();
};

View File

@ -4,6 +4,11 @@
namespace urde
{
CResLoader::CResLoader()
{
x48_curPak = x18_pakLoadedList.end();
}
const std::vector<CAssetId>* CResLoader::GetTagListForFile(const std::string& name) const
{
std::string namePak = name + ".pak";
@ -30,79 +35,78 @@ void CResLoader::AddPakFile(const std::string& name, bool samusPak, bool worldPa
AsyncIdlePakLoading();
}
CInputStream* CResLoader::LoadNewResourcePartSync(const SObjectTag& tag, int offset, int length, void* extBuf)
std::unique_ptr<CInputStream> CResLoader::LoadNewResourcePartSync(const SObjectTag& tag, int offset, int length, void* extBuf)
{
void* buf = extBuf;
CPakFile* file = FindResourceForLoad(tag);
if (!buf)
buf = new u8[length];
file->SyncSeekRead(buf, length, ESeekOrigin::Begin, x50_cachedResInfo->x4_offset + offset);
return new CMemoryInStream((atUint8*)buf, length, !extBuf);
file->SyncSeekRead(buf, length, ESeekOrigin::Begin, x50_cachedResInfo->GetOffset() + offset);
return std::unique_ptr<CInputStream>(new athena::io::MemoryReader((atUint8*)buf, length, !extBuf));
}
void CResLoader::LoadMemResourceSync(const SObjectTag& tag, void** bufOut, int* sizeOut)
void CResLoader::LoadMemResourceSync(const SObjectTag& tag, std::unique_ptr<u8[]>& bufOut, int* sizeOut)
{
CPakFile* file = FindResourceForLoad(tag);
void* buf = new u8[x50_cachedResInfo->x8_size];
file->SyncSeekRead(buf, x50_cachedResInfo->x8_size, ESeekOrigin::Begin,
x50_cachedResInfo->x4_offset);
*bufOut = buf;
*sizeOut = x50_cachedResInfo->x8_size;
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();
}
CInputStream* CResLoader::LoadResourceFromMemorySync(const SObjectTag& tag, const void* buf)
std::unique_ptr<CInputStream> CResLoader::LoadResourceFromMemorySync(const SObjectTag& tag, const void* buf)
{
FindResourceForLoad(tag);
CInputStream* newStrm = new CMemoryInStream((atUint8*)buf, x50_cachedResInfo->x8_size);
if (x50_cachedResInfo->xb_compressed)
CInputStream* newStrm = new athena::io::MemoryReader((atUint8*)buf, x50_cachedResInfo->GetSize());
if (x50_cachedResInfo->IsCompressed())
{
newStrm->readUint32Big();
newStrm = new CZipInputStream(std::unique_ptr<CInputStream>(newStrm));
}
return newStrm;
return std::unique_ptr<CInputStream>(newStrm);
}
CInputStream* CResLoader::LoadNewResourceSync(const SObjectTag& tag, void* extBuf)
std::unique_ptr<CInputStream> CResLoader::LoadNewResourceSync(const SObjectTag& tag, void* extBuf)
{
void* buf = extBuf;
CPakFile* file = FindResourceForLoad(tag);
size_t resSz = ROUND_UP_32(x50_cachedResInfo->x8_size);
size_t resSz = ROUND_UP_32(x50_cachedResInfo->GetSize());
if (!buf)
buf = new u8[resSz];
file->SyncSeekRead(buf, resSz, ESeekOrigin::Begin, x50_cachedResInfo->x4_offset);
CInputStream* newStrm = new CMemoryInStream((atUint8*)buf, resSz, !extBuf);
if (x50_cachedResInfo->xb_compressed)
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 newStrm;
return std::unique_ptr<CInputStream>(newStrm);
}
std::shared_ptr<IDvdRequest> CResLoader::LoadResourcePartAsync(const SObjectTag& tag, int offset, int length, void* buf)
{
return FindResourceForLoad(tag.id)->AsyncSeekRead(buf, length,
ESeekOrigin::Begin, x50_cachedResInfo->x4_offset + offset);
ESeekOrigin::Begin, x50_cachedResInfo->GetOffset() + offset);
}
std::shared_ptr<IDvdRequest> CResLoader::LoadResourceAsync(const SObjectTag& tag, void* buf)
{
return FindResourceForLoad(tag.id)->AsyncSeekRead(buf, ROUND_UP_32(x50_cachedResInfo->x8_size),
ESeekOrigin::Begin, x50_cachedResInfo->x4_offset);
return FindResourceForLoad(tag.id)->AsyncSeekRead(buf, ROUND_UP_32(x50_cachedResInfo->GetSize()),
ESeekOrigin::Begin, x50_cachedResInfo->GetOffset());
}
bool CResLoader::GetResourceCompression(const SObjectTag& tag)
{
if (FindResource(tag.id))
return x50_cachedResInfo->xb_compressed;
return x50_cachedResInfo->IsCompressed();
return false;
}
u32 CResLoader::ResourceSize(const SObjectTag& tag)
{
if (FindResource(tag.id))
return x50_cachedResInfo->x8_size;
return false;
return x50_cachedResInfo->GetSize();
return 0;
}
bool CResLoader::ResourceExists(const SObjectTag& tag)
@ -113,7 +117,7 @@ bool CResLoader::ResourceExists(const SObjectTag& tag)
FourCC CResLoader::GetResourceTypeById(CAssetId id) const
{
if (FindResource(id))
return x50_cachedResInfo->x0_type;
return x50_cachedResInfo->GetType();
return FourCC();
}
@ -151,17 +155,41 @@ void CResLoader::AsyncIdlePakLoading()
bool CResLoader::FindResource(CAssetId id) const
{
for (const std::unique_ptr<CPakFile>& file : x18_pakLoadedList)
if (const_cast<CResLoader*>(this)->CacheFromPak(*file, id))
if (x4c_cachedResId == id)
return true;
if (x48_curPak != x18_pakLoadedList.end())
if (CacheFromPak(**x48_curPak, id))
return true;
for (auto it = x18_pakLoadedList.begin() ; it != x18_pakLoadedList.end() ; ++it)
{
if (it == x48_curPak)
continue;
if (CacheFromPak(**it, id))
return true;
}
return false;
}
CPakFile* CResLoader::FindResourceForLoad(CAssetId id)
{
for (std::unique_ptr<CPakFile>& file : x18_pakLoadedList)
if (CacheFromPakForLoad(*file, id))
return file.get();
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;
}
}
return nullptr;
}
@ -172,7 +200,16 @@ CPakFile* CResLoader::FindResourceForLoad(const SObjectTag& tag)
bool CResLoader::CacheFromPakForLoad(CPakFile& file, CAssetId id)
{
const CPakFile::SResInfo* info = file.GetResInfoForLoad(id);
const CPakFile::SResInfo* info;
if (x54_forwardSeek)
{
info = file.GetResInfoForLoadPreferForward(id);
x54_forwardSeek = false;
}
else
{
info = file.GetResInfoForLoadDirectionless(id);
}
if (info)
{
x4c_cachedResId = id;
@ -182,7 +219,7 @@ bool CResLoader::CacheFromPakForLoad(CPakFile& file, CAssetId id)
return false;
}
bool CResLoader::CacheFromPak(const CPakFile& file, CAssetId id)
bool CResLoader::CacheFromPak(const CPakFile& file, CAssetId id) const
{
const CPakFile::SResInfo* info = file.GetResInfo(id);
if (info)

View File

@ -19,16 +19,19 @@ class CResLoader
std::list<std::unique_ptr<CPakFile>> x18_pakLoadedList;
std::list<std::unique_ptr<CPakFile>> x30_pakLoadingList;
u32 x44_pakLoadingCount = 0;
CAssetId x4c_cachedResId;
const CPakFile::SResInfo* x50_cachedResInfo = nullptr;
std::list<std::unique_ptr<CPakFile>>::iterator x48_curPak;
mutable CAssetId x4c_cachedResId;
mutable const CPakFile::SResInfo* x50_cachedResInfo = nullptr;
bool x54_forwardSeek = false;
public:
CResLoader();
const std::vector<CAssetId>* GetTagListForFile(const std::string& name) const;
void AddPakFileAsync(const std::string& name, bool samusPak, bool worldPak);
void AddPakFile(const std::string& name, bool samusPak, bool worldPak);
CInputStream* LoadNewResourcePartSync(const SObjectTag& tag, int offset, int length, void* extBuf);
void LoadMemResourceSync(const SObjectTag& tag, void** bufOut, int* sizeOut);
CInputStream* LoadResourceFromMemorySync(const SObjectTag& tag, const void* buf);
CInputStream* LoadNewResourceSync(const SObjectTag& tag, void* extBuf=nullptr);
std::unique_ptr<CInputStream> LoadNewResourcePartSync(const SObjectTag& tag, int offset, int length, void* extBuf);
void LoadMemResourceSync(const SObjectTag& tag, std::unique_ptr<u8[]>& bufOut, int* sizeOut);
std::unique_ptr<CInputStream> LoadResourceFromMemorySync(const SObjectTag& tag, const void* buf);
std::unique_ptr<CInputStream> LoadNewResourceSync(const SObjectTag& tag, void* extBuf=nullptr);
std::shared_ptr<IDvdRequest> LoadResourcePartAsync(const SObjectTag& tag, int offset, int length, void* buf);
std::shared_ptr<IDvdRequest> LoadResourceAsync(const SObjectTag& tag, void* buf);
bool GetResourceCompression(const SObjectTag& tag);
@ -42,7 +45,7 @@ public:
CPakFile* FindResourceForLoad(CAssetId id);
CPakFile* FindResourceForLoad(const SObjectTag& tag);
bool CacheFromPakForLoad(CPakFile& file, CAssetId id);
bool CacheFromPak(const CPakFile& file, CAssetId id);
bool CacheFromPak(const CPakFile& file, CAssetId id) const;
void MoveToCorrectLoadedList(std::unique_ptr<CPakFile>&& file);
};

View File

@ -10,6 +10,8 @@ namespace urde
class CVParamTransfer;
class IObj;
class CObjectReference;
class CResLoader;
class CFactoryMgr;
using CFactoryFnReturn = std::unique_ptr<IObj>;
using FFactoryFunc = std::function<CFactoryFnReturn(const urde::SObjectTag& tag,
@ -33,6 +35,8 @@ public:
virtual FourCC GetResourceTypeById(CAssetId id) const=0;
virtual void EnumerateResources(const std::function<bool(const SObjectTag&)>& lambda) const=0;
virtual void EnumerateNamedResources(const std::function<bool(const std::string&, const SObjectTag&)>& lambda) const=0;
virtual CResLoader* GetResLoader() const { return nullptr; }
virtual CFactoryMgr* GetFactoryMgr() const { return nullptr; }
/* Non-factory versions, replaces CResLoader */
virtual u32 ResourceSize(const urde::SObjectTag& tag)=0;

View File

@ -42,6 +42,7 @@ set(MP1_SOURCES
CSamusDoll.hpp CSamusDoll.cpp
CGameCubeDoll.hpp CGameCubeDoll.cpp
CArtifactDoll.hpp CArtifactDoll.cpp
MP1OriginalIDs.hpp MP1OriginalIDs.cpp
MP1.hpp MP1.cpp
${MP1_PLAT_SOURCES}
${MP1_WORLD_SOURCES})

View File

@ -20,8 +20,9 @@ CIOWin::EMessageReturn CPreFrontEnd::OnMessage(const CArchitectureMessage& msg,
return EMessageReturn::Normal;
CMain* m = static_cast<CMain*>(g_Main);
//if (CResLoader::AreAllPaksLoaded())
// return EMessageReturn::Exit;
if (CResLoader* loader = g_ResFactory->GetResLoader())
if (loader->AreAllPaksLoaded())
return EMessageReturn::Exit;
if (!x14_resourceTweaksRegistered)
{
m->RegisterResourceTweaks();

View File

@ -20,7 +20,39 @@
#include "Graphics/Shaders/CParticleSwooshShaders.hpp"
#include "Audio/CStreamAudioManager.hpp"
#include "CGBASupport.hpp"
#include "CGameHintInfo.hpp"
#include "Particle/CParticleDataFactory.hpp"
#include "Particle/CGenDescription.hpp"
#include "Particle/CElectricDescription.hpp"
#include "Particle/CSwooshDescription.hpp"
#include "Particle/CParticleElectricDataFactory.hpp"
#include "Particle/CParticleSwooshDataFactory.hpp"
#include "Particle/CWeaponDescription.hpp"
#include "Particle/CProjectileWeaponDataFactory.hpp"
#include "Particle/CDecalDataFactory.hpp"
#include "GuiSys/CGuiFrame.hpp"
#include "GuiSys/CRasterFont.hpp"
#include "GuiSys/CStringTable.hpp"
#include "Graphics/CModel.hpp"
#include "Graphics/CTexture.hpp"
#include "Character/CCharLayoutInfo.hpp"
#include "Character/CSkinRules.hpp"
#include "Character/CAnimCharacterSet.hpp"
#include "Character/CAllFormatsAnimSource.hpp"
#include "Character/CAnimPOIData.hpp"
#include "Collision/CCollidableOBBTreeGroup.hpp"
#include "Collision/CCollisionResponseData.hpp"
#include "CSaveWorld.hpp"
#include "AutoMapper/CMapWorld.hpp"
#include "AutoMapper/CMapArea.hpp"
#include "AutoMapper/CMapUniverse.hpp"
#include "CScannableObjectInfo.hpp"
#include "Audio/CAudioGroupSet.hpp"
#include "Audio/CSfxManager.hpp"
#include "Audio/CMidiManager.hpp"
#include "CDependencyGroup.hpp"
#include "MP1OriginalIDs.hpp"
namespace urde
{
@ -248,6 +280,72 @@ CMain::BooSetter::BooSetter(boo::IGraphicsDataFactory* factory,
void CMain::RegisterResourceTweaks()
{
}
void CGameGlobalObjects::AddPaksAndFactories()
{
CGraphics::SetViewPointMatrix(zeus::CTransform::Identity());
CGraphics::SetModelMatrix(zeus::CTransform::Identity());
if (CResLoader* loader = g_ResFactory->GetResLoader())
{
loader->AddPakFileAsync("Tweaks", false, false);
loader->AddPakFileAsync("NoARAM", false, false);
loader->AddPakFileAsync("AudioGrp", false, false);
loader->AddPakFileAsync("MiscData", false, false);
loader->AddPakFileAsync("SamusGun", true, false);
loader->AddPakFileAsync("TestAnim", true, false);
loader->AddPakFileAsync("SamGunFx", true, false);
loader->AddPakFileAsync("MidiData", false, false);
loader->AddPakFileAsync("GGuiSys", false, false);
}
if (CFactoryMgr* fmgr = g_ResFactory->GetFactoryMgr())
{
fmgr->AddFactory(FOURCC('TXTR'), FMemFactoryFunc(FTextureFactory));
fmgr->AddFactory(FOURCC('PART'), FFactoryFunc(FParticleFactory));
fmgr->AddFactory(FOURCC('FRME'), FFactoryFunc(RGuiFrameFactoryInGame));
fmgr->AddFactory(FOURCC('FONT'), FFactoryFunc(FRasterFontFactory));
fmgr->AddFactory(FOURCC('CMDL'), FMemFactoryFunc(FModelFactory));
fmgr->AddFactory(FOURCC('CINF'), FFactoryFunc(FCharLayoutInfo));
fmgr->AddFactory(FOURCC('CSKR'), FFactoryFunc(FSkinRulesFactory));
fmgr->AddFactory(FOURCC('ANCS'), FFactoryFunc(FAnimCharacterSet));
fmgr->AddFactory(FOURCC('ANIM'), FFactoryFunc(AnimSourceFactory));
fmgr->AddFactory(FOURCC('EVNT'), FFactoryFunc(AnimPOIDataFactory));
fmgr->AddFactory(FOURCC('DCLN'), FFactoryFunc(FCollidableOBBTreeGroupFactory));
fmgr->AddFactory(FOURCC('DGRP'), FFactoryFunc(FDependencyGroupFactory));
fmgr->AddFactory(FOURCC('AGSC'), FMemFactoryFunc(FAudioGroupSetDataFactory));
fmgr->AddFactory(FOURCC('CSNG'), FFactoryFunc(FMidiDataFactory));
fmgr->AddFactory(FOURCC('ATBL'), FFactoryFunc(FAudioTranslationTableFactory));
fmgr->AddFactory(FOURCC('STRG'), FFactoryFunc(FStringTableFactory));
fmgr->AddFactory(FOURCC('HINT'), FFactoryFunc(FHintFactory));
fmgr->AddFactory(FOURCC('SAVW'), FFactoryFunc(FSaveWorldFactory));
fmgr->AddFactory(FOURCC('MAPW'), FFactoryFunc(FMapWorldFactory));
fmgr->AddFactory(FOURCC('OIDS'), FFactoryFunc(FMP1OriginalIDsFactory));
fmgr->AddFactory(FOURCC('SCAN'), FFactoryFunc(FScannableObjectInfoFactory));
fmgr->AddFactory(FOURCC('CRSC'), FFactoryFunc(FCollisionResponseDataFactory));
fmgr->AddFactory(FOURCC('SWHC'), FFactoryFunc(FParticleSwooshDataFactory));
fmgr->AddFactory(FOURCC('ELSC'), FFactoryFunc(FParticleElectricDataFactory));
fmgr->AddFactory(FOURCC('WPSC'), FFactoryFunc(FProjectileWeaponDataFactory));
fmgr->AddFactory(FOURCC('DPSC'), FFactoryFunc(FDecalDataFactory));
fmgr->AddFactory(FOURCC('MAPA'), FFactoryFunc(FMapAreaFactory));
fmgr->AddFactory(FOURCC('MAPU'), FFactoryFunc(FMapUniverseFactory));
}
}
void CMain::AddWorldPaks()
{
auto& pakPrefix = g_tweakGame->GetWorldPrefix();
for (int i=0 ; i<9 ; ++i)
{
std::string path = pakPrefix;
if (i != 0)
path += '0' + i;
path += ".upak";
if (CDvdFile::FileExists(path.c_str()))
if (CResLoader* loader = g_ResFactory->GetResLoader())
loader->AddPakFileAsync(path, false, true);
}
}
void CMain::ResetGameState()
{
CPersistentOptions sysOpts = g_GameState->SystemOptions();
@ -325,6 +423,7 @@ void CMain::Init(const hecl::Runtime::FileStoreManager& storeMgr,
x128_globalObjects.PostInitialize();
x70_tweaks.RegisterTweaks();
x70_tweaks.RegisterResourceTweaks();
AddWorldPaks();
FillInAssetIDs();
x164_archSupport.reset(new CGameArchitectureSupport(*this, voiceEngine, backend));
g_archSupport = x164_archSupport.get();

View File

@ -66,6 +66,7 @@ class CGameGlobalObjects
x13c_mainStringTable = g_SimplePool->GetObj("STRG_Main");
g_MainStringTable = x13c_mainStringTable.GetObj();
}
void AddPaksAndFactories();
static IRenderer*
AllocateRenderer(IObjectStore& store, IFactory& resFactory)
{
@ -89,6 +90,7 @@ public:
void PostInitialize()
{
AddPaksAndFactories();
LoadStringTable();
m_renderer.reset(AllocateRenderer(xcc_simplePool, x4_resFactory));
CScriptMazeNode::LoadMazeSeeds();
@ -253,6 +255,7 @@ public:
boo::IGraphicsCommandQueue* cmdQ,
boo::ITextureR* spareTex);
void RegisterResourceTweaks();
void AddWorldPaks();
void ResetGameState();
void StreamNewGameState(CBitStreamReader&, u32 idx);
void CheckTweakManagerDebugOptions() {}

View File

@ -0,0 +1,51 @@
#include "MP1OriginalIDs.hpp"
#include "CToken.hpp"
namespace urde
{
MP1OriginalIDs::MP1OriginalIDs(CInputStream& in)
{
u32 count = in.readUint32Big();
m_origToNew.reserve(count);
for (u32 i=0 ; i<count ; ++i)
{
CAssetId a = in.readUint32Big();
CAssetId b = in.readUint32Big();
m_origToNew.push_back(std::make_pair(a, b));
}
m_newToOrig.reserve(count);
for (u32 i=0 ; i<count ; ++i)
{
CAssetId a = in.readUint32Big();
CAssetId b = in.readUint32Big();
m_newToOrig.push_back(std::make_pair(a, b));
}
}
CAssetId MP1OriginalIDs::TranslateOriginalToNew(CAssetId id) const
{
auto search = rstl::binary_find(m_origToNew.cbegin(), m_origToNew.cend(), id,
[](const auto& id) { return id.first; });
if (search == m_origToNew.cend())
return -1;
return search->second;
}
CAssetId MP1OriginalIDs::TranslateNewToOriginal(CAssetId id) const
{
auto search = rstl::binary_find(m_newToOrig.cbegin(), m_newToOrig.cend(), id,
[](const auto& id) { return id.first; });
if (search == m_newToOrig.cend())
return -1;
return search->second;
}
CFactoryFnReturn FMP1OriginalIDsFactory(const SObjectTag& tag, CInputStream& in,
const CVParamTransfer& param,
CObjectReference* selfRef)
{
return TToken<MP1OriginalIDs>::GetIObjObjectFor(std::make_unique<MP1OriginalIDs>(in));
}
}

View File

@ -0,0 +1,27 @@
#ifndef URDE_MP1ORIGINALIDS_HPP
#define URDE_MP1ORIGINALIDS_HPP
#include "RetroTypes.hpp"
#include "IFactory.hpp"
namespace urde
{
class MP1OriginalIDs
{
std::vector<std::pair<CAssetId, CAssetId>> m_origToNew;
std::vector<std::pair<CAssetId, CAssetId>> m_newToOrig;
public:
MP1OriginalIDs(CInputStream& in);
CAssetId TranslateOriginalToNew(CAssetId id) const;
CAssetId TranslateNewToOriginal(CAssetId id) const;
};
CFactoryFnReturn FMP1OriginalIDsFactory(const SObjectTag& tag, CInputStream& in,
const CVParamTransfer& param,
CObjectReference* selfRef);
}
#endif // URDE_MP1ORIGINALIDS_HPP

2
hecl

@ -1 +1 @@
Subproject commit 70b73855bf906c81d18bdf70c9b701bba996314e
Subproject commit 038917dc59aaf50efed8925ff5fd53d62fd8cfe8

View File

@ -323,6 +323,7 @@ std::vector<uint8_t> VISIBuilder::build(const zeus::CAABox& fullAabb,
Progress prog(updatePercent);
#ifndef _WIN32
parentPid = getppid();
auto terminate = [this, parentPid]()
{
return renderCache.m_renderer.m_terminate || (parentPid ? kill(parentPid, 0) : false);