mirror of
https://github.com/AxioDL/metaforce.git
synced 2025-12-08 16:24:55 +00:00
Added area/layer directory indexing for MP1/2
This commit is contained in:
@@ -16,11 +16,8 @@ PAKBridge::PAKBridge(HECL::Database::Project& project, const NOD::DiscBase::IPar
|
||||
{
|
||||
NOD::AthenaPartReadStream rs(node.beginReadStream());
|
||||
m_pak.read(rs);
|
||||
}
|
||||
|
||||
HECL::SystemString PAKBridge::getLevelString() const
|
||||
{
|
||||
HECL::SystemString retval;
|
||||
/* Append Level String */
|
||||
for (const DNAMP1::PAK::Entry& entry : m_pak.m_entries)
|
||||
{
|
||||
if (entry.type == Retro::MLVL)
|
||||
@@ -34,23 +31,143 @@ HECL::SystemString PAKBridge::getLevelString() const
|
||||
PAKEntryReadStream rs = nameEnt->beginReadStream(m_node);
|
||||
STRG mlvlName;
|
||||
mlvlName.read(rs);
|
||||
if (retval.size())
|
||||
retval += _S(", ");
|
||||
retval += mlvlName.getSystemString(ENGL, 0);
|
||||
if (m_levelString.size())
|
||||
m_levelString += _S(", ");
|
||||
m_levelString += mlvlName.getSystemString(ENGL, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UniqueResult PAKBridge::uniqueCheck(const DNAMP1::PAK::Entry& entry)
|
||||
{
|
||||
UniqueResult::Type result = UniqueResult::UNIQUE_NOTFOUND;
|
||||
bool foundOneLayer = false;
|
||||
UniqueID32 areaId;
|
||||
unsigned layerIdx;
|
||||
for (const auto& pair : m_areaDeps)
|
||||
{
|
||||
unsigned l=0;
|
||||
for (const auto& layer : pair.second.layers)
|
||||
{
|
||||
if (layer.resources.find(entry.id) != layer.resources.end())
|
||||
{
|
||||
if (foundOneLayer)
|
||||
{
|
||||
if (areaId == pair.first)
|
||||
result = UniqueResult::UNIQUE_AREA;
|
||||
else
|
||||
return {UniqueResult::UNIQUE_LEVEL};
|
||||
continue;
|
||||
}
|
||||
else
|
||||
result = UniqueResult::UNIQUE_LAYER;
|
||||
areaId = pair.first;
|
||||
layerIdx = l;
|
||||
foundOneLayer = true;
|
||||
}
|
||||
++l;
|
||||
}
|
||||
if (pair.second.resources.find(entry.id) != pair.second.resources.end())
|
||||
{
|
||||
if (foundOneLayer)
|
||||
{
|
||||
if (areaId == pair.first)
|
||||
result = UniqueResult::UNIQUE_AREA;
|
||||
else
|
||||
return {UniqueResult::UNIQUE_LEVEL};
|
||||
continue;
|
||||
}
|
||||
else
|
||||
result = UniqueResult::UNIQUE_AREA;
|
||||
areaId = pair.first;
|
||||
foundOneLayer = true;
|
||||
}
|
||||
}
|
||||
UniqueResult retval = {result};
|
||||
if (result == UniqueResult::UNIQUE_LAYER || result == UniqueResult::UNIQUE_AREA)
|
||||
{
|
||||
const PAKBridge::Area& area = m_areaDeps[areaId];
|
||||
retval.areaName = &area.name;
|
||||
if (result == UniqueResult::UNIQUE_LAYER)
|
||||
{
|
||||
const PAKBridge::Area::Layer& layer = area.layers[layerIdx];
|
||||
retval.layerName = &layer.name;
|
||||
}
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
ResExtractor PAKBridge::LookupExtractor(const DNAMP1::PAK::Entry& entry)
|
||||
static HECL::SystemString LayerName(const std::string& name)
|
||||
{
|
||||
#if HECL_UCS2
|
||||
HECL::SystemString ret = HECL::UTF8ToWide(mlvl.layerNames[layerIdx++]);
|
||||
#else
|
||||
HECL::SystemString ret = name;
|
||||
#endif
|
||||
for (auto& ch : ret)
|
||||
if (ch == _S('/') || ch == _S('\\'))
|
||||
ch = _S('-');
|
||||
return ret;
|
||||
}
|
||||
|
||||
void PAKBridge::build()
|
||||
{
|
||||
/* First pass: build per-area/per-layer dependency map */
|
||||
for (const DNAMP1::PAK::Entry& entry : m_pak.m_entries)
|
||||
{
|
||||
if (entry.type == Retro::MLVL)
|
||||
{
|
||||
PAKEntryReadStream rs = entry.beginReadStream(m_node);
|
||||
MLVL mlvl;
|
||||
mlvl.read(rs);
|
||||
m_areaDeps.reserve(mlvl.areaCount);
|
||||
unsigned layerIdx = 0;
|
||||
for (const MLVL::Area& area : mlvl.areas)
|
||||
{
|
||||
Area& areaDeps = m_areaDeps[area.areaMREAId];
|
||||
const DNAMP1::PAK::Entry* areaNameEnt = m_pak.lookupEntry(area.areaNameId);
|
||||
if (areaNameEnt)
|
||||
{
|
||||
STRG areaName;
|
||||
PAKEntryReadStream rs = areaNameEnt->beginReadStream(m_node);
|
||||
areaName.read(rs);
|
||||
areaDeps.name = areaName.getSystemString(Retro::ENGL, 0);
|
||||
}
|
||||
|
||||
areaDeps.layers.reserve(area.depLayerCount-1);
|
||||
unsigned r=0;
|
||||
for (unsigned l=1 ; l<area.depLayerCount ; ++l)
|
||||
{
|
||||
areaDeps.layers.emplace_back();
|
||||
Area::Layer& layer = areaDeps.layers.back();
|
||||
layer.name = LayerName(mlvl.layerNames[layerIdx++]);
|
||||
layer.resources.reserve(area.depLayers[l] - r);
|
||||
for (; r<area.depLayers[l] ; ++r)
|
||||
layer.resources.emplace(area.deps[r].id);
|
||||
}
|
||||
areaDeps.resources.reserve(area.depCount - r);
|
||||
for (; r<area.depCount ; ++r)
|
||||
areaDeps.resources.emplace(area.deps[r].id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Second pass: cross-compare uniqueness */
|
||||
for (DNAMP1::PAK::Entry& entry : m_pak.m_entries)
|
||||
{
|
||||
entry.unique = uniqueCheck(entry);
|
||||
}
|
||||
}
|
||||
|
||||
ResExtractor<PAKBridge> PAKBridge::LookupExtractor(const DNAMP1::PAK::Entry& entry)
|
||||
{
|
||||
switch (entry.type.toUint32())
|
||||
{
|
||||
case SBIG('STRG'):
|
||||
return {STRG::Extract, ".as"};
|
||||
return {STRG::Extract, nullptr, ".as"};
|
||||
case SBIG('TXTR'):
|
||||
return {TXTR::Extract, ".png"};
|
||||
return {TXTR::Extract, nullptr, ".png"};
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
@@ -17,11 +17,26 @@ class PAKBridge
|
||||
HECL::Database::Project& m_project;
|
||||
const NOD::DiscBase::IPartition::Node& m_node;
|
||||
DNAMP1::PAK m_pak;
|
||||
struct Area
|
||||
{
|
||||
HECL::SystemString name;
|
||||
struct Layer
|
||||
{
|
||||
HECL::SystemString name;
|
||||
std::unordered_set<UniqueID32> resources;
|
||||
};
|
||||
std::vector<Layer> layers;
|
||||
std::unordered_set<UniqueID32> resources;
|
||||
};
|
||||
std::unordered_map<UniqueID32, Area> m_areaDeps;
|
||||
HECL::SystemString m_levelString;
|
||||
UniqueResult uniqueCheck(const DNAMP1::PAK::Entry& entry);
|
||||
public:
|
||||
PAKBridge(HECL::Database::Project& project, const NOD::DiscBase::IPartition::Node& node);
|
||||
static ResExtractor LookupExtractor(const DNAMP1::PAK::Entry& entry);
|
||||
const std::string& getName() const {return m_node.getName();}
|
||||
HECL::SystemString getLevelString() const;
|
||||
void build();
|
||||
static ResExtractor<PAKBridge> LookupExtractor(const DNAMP1::PAK::Entry& entry);
|
||||
inline const std::string& getName() const {return m_node.getName();}
|
||||
inline const HECL::SystemString& getLevelString() const {return m_levelString;}
|
||||
|
||||
typedef DNAMP1::PAK PAKType;
|
||||
inline const PAKType& getPAK() const {return m_pak;}
|
||||
|
||||
@@ -70,6 +70,7 @@ struct MLVL : BigDNA
|
||||
|
||||
String<-1> internalAreaName;
|
||||
};
|
||||
Vector<Area, DNA_COUNT(areaCount)> areas;
|
||||
|
||||
UniqueID32 worldMap;
|
||||
Value<atUint8> unknown2;
|
||||
|
||||
Reference in New Issue
Block a user