2
0
mirror of https://github.com/AxioDL/metaforce.git synced 2025-12-10 00:27:43 +00:00

Added area/layer directory indexing for MP1/2

This commit is contained in:
Jack Andersen
2015-08-03 16:14:47 -10:00
parent 7b1ec6c4b9
commit 6e58666a80
13 changed files with 455 additions and 73 deletions

View File

@@ -206,13 +206,51 @@ public:
}
};
/* Resource extractor type */
typedef struct
struct UniqueResult
{
std::function<bool(PAKEntryReadStream&, const HECL::ProjectPath&)> func;
enum Type
{
UNIQUE_NOTFOUND,
UNIQUE_LEVEL,
UNIQUE_AREA,
UNIQUE_LAYER
} type = UNIQUE_NOTFOUND;
const HECL::SystemString* areaName = nullptr;
const HECL::SystemString* layerName = nullptr;
UniqueResult() = default;
UniqueResult(Type tp) : type(tp) {}
inline HECL::ProjectPath uniquePath(const HECL::ProjectPath& pakPath) const
{
if (type == UNIQUE_AREA)
{
HECL::ProjectPath areaDir(pakPath, *areaName);
areaDir.makeDir();
return areaDir;
}
else if (type == UNIQUE_LAYER)
{
HECL::ProjectPath areaDir(pakPath, *areaName);
areaDir.makeDir();
HECL::ProjectPath layerDir(areaDir, *layerName);
layerDir.makeDir();
return layerDir;
}
return pakPath;
}
};
template <class BRIDGETYPE>
class PAKRouter;
/* Resource extractor type */
template <class PAKBRIDGE>
struct ResExtractor
{
std::function<bool(PAKEntryReadStream&, const HECL::ProjectPath&)> func_a;
std::function<bool(PAKEntryReadStream&, const HECL::ProjectPath&, PAKRouter<PAKBRIDGE>&)> func_b;
const char* fileExt;
unsigned weight;
} ResExtractor;
};
/* PAKRouter (for detecting shared entry locations) */
template <class BRIDGETYPE>
@@ -232,14 +270,17 @@ public:
PAKRouter(const HECL::ProjectPath& working, const HECL::ProjectPath& cooked)
: m_gameWorking(working), m_gameCooked(cooked),
m_sharedWorking(working, "Shared"), m_sharedCooked(cooked, "Shared") {}
void build(const std::vector<BRIDGETYPE>& bridges, std::function<void(float)> progress)
void build(std::vector<BRIDGETYPE>& bridges, std::function<void(float)> progress)
{
m_uniqueEntries.clear();
m_sharedEntries.clear();
size_t count = 0;
float bridgesSz = bridges.size();
for (const BRIDGETYPE& bridge : bridges)
/* Route entries unique/shared per-pak */
for (BRIDGETYPE& bridge : bridges)
{
bridge.build();
const typename BRIDGETYPE::PAKType& pak = bridge.getPAK();
for (const auto& entry : pak.m_idMap)
{
@@ -274,7 +315,7 @@ public:
}
HECL::ProjectPath getWorking(const typename BRIDGETYPE::PAKType::Entry* entry,
const ResExtractor& extractor) const
const ResExtractor<BRIDGETYPE>& extractor) const
{
if (!m_pak)
LogDNACommon.report(LogVisor::FatalError,
@@ -282,10 +323,11 @@ public:
auto uniqueSearch = m_uniqueEntries.find(entry->id);
if (uniqueSearch != m_uniqueEntries.end())
{
HECL::ProjectPath uniquePath = entry->unique.uniquePath(m_pakWorking);
HECL::SystemString entName = m_pak->bestEntryName(*entry);
if (extractor.fileExt)
entName += extractor.fileExt;
return HECL::ProjectPath(m_pakWorking, entName);
return HECL::ProjectPath(uniquePath, entName);
}
auto sharedSearch = m_sharedEntries.find(entry->id);
if (sharedSearch != m_sharedEntries.end())
@@ -295,7 +337,7 @@ public:
entName += extractor.fileExt;
HECL::ProjectPath sharedPath(m_sharedWorking, entName);
HECL::ProjectPath uniquePath(m_pakWorking, entName);
if (extractor.func)
if (extractor.func_a || extractor.func_b)
uniquePath.makeLinkTo(sharedPath);
m_sharedWorking.makeDir();
return sharedPath;
@@ -312,7 +354,8 @@ public:
auto uniqueSearch = m_uniqueEntries.find(entry->id);
if (uniqueSearch != m_uniqueEntries.end())
{
return HECL::ProjectPath(m_pakCooked, m_pak->bestEntryName(*entry));
HECL::ProjectPath uniquePath = entry->unique.uniquePath(m_pakCooked);
return HECL::ProjectPath(uniquePath, m_pak->bestEntryName(*entry));
}
auto sharedSearch = m_sharedEntries.find(entry->id);
if (sharedSearch != m_sharedEntries.end())
@@ -334,7 +377,7 @@ public:
{
for (const auto& item : m_pak->m_idMap)
{
ResExtractor extractor = BRIDGETYPE::LookupExtractor(*item.second);
ResExtractor<BRIDGETYPE> extractor = BRIDGETYPE::LookupExtractor(*item.second);
if (extractor.weight != w)
continue;
@@ -348,12 +391,20 @@ public:
}
HECL::ProjectPath working = getWorking(item.second, extractor);
if (extractor.func)
if (extractor.func_a) /* Doesn't need PAKRouter access */
{
if (force || working.getPathType() == HECL::ProjectPath::PT_NONE)
{
PAKEntryReadStream s = item.second->beginReadStream(*m_node);
extractor.func(s, working);
extractor.func_a(s, working);
}
}
else if (extractor.func_b) /* Needs PAKRouter access */
{
if (force || working.getPathType() == HECL::ProjectPath::PT_NONE)
{
PAKEntryReadStream s = item.second->beginReadStream(*m_node);
extractor.func_b(s, working, *this);
}
}