mirror of https://github.com/AxioDL/metaforce.git
Additional extract directory tier for level names
This commit is contained in:
parent
b1f55c2733
commit
2893eb7e76
|
@ -55,31 +55,44 @@ struct UniqueResult
|
||||||
enum Type
|
enum Type
|
||||||
{
|
{
|
||||||
UNIQUE_NOTFOUND,
|
UNIQUE_NOTFOUND,
|
||||||
|
UNIQUE_PAK,
|
||||||
UNIQUE_LEVEL,
|
UNIQUE_LEVEL,
|
||||||
UNIQUE_AREA,
|
UNIQUE_AREA,
|
||||||
UNIQUE_LAYER
|
UNIQUE_LAYER
|
||||||
} type = UNIQUE_NOTFOUND;
|
} type = UNIQUE_NOTFOUND;
|
||||||
|
const HECL::SystemString* levelName = nullptr;
|
||||||
const HECL::SystemString* areaName = nullptr;
|
const HECL::SystemString* areaName = nullptr;
|
||||||
const HECL::SystemString* layerName = nullptr;
|
const HECL::SystemString* layerName = nullptr;
|
||||||
UniqueResult() = default;
|
UniqueResult() = default;
|
||||||
UniqueResult(Type tp) : type(tp) {}
|
UniqueResult(Type tp) : type(tp) {}
|
||||||
HECL::ProjectPath uniquePath(const HECL::ProjectPath& pakPath) const
|
HECL::ProjectPath uniquePath(const HECL::ProjectPath& pakPath) const
|
||||||
{
|
{
|
||||||
|
if (type == UNIQUE_PAK)
|
||||||
|
return pakPath;
|
||||||
|
|
||||||
|
HECL::ProjectPath levelDir;
|
||||||
|
if (levelName)
|
||||||
|
levelDir.assign(pakPath, *levelName);
|
||||||
|
else
|
||||||
|
levelDir = pakPath;
|
||||||
|
levelDir.makeDir();
|
||||||
|
|
||||||
if (type == UNIQUE_AREA)
|
if (type == UNIQUE_AREA)
|
||||||
{
|
{
|
||||||
HECL::ProjectPath areaDir(pakPath, *areaName);
|
HECL::ProjectPath areaDir(levelDir, *areaName);
|
||||||
areaDir.makeDir();
|
areaDir.makeDir();
|
||||||
return areaDir;
|
return areaDir;
|
||||||
}
|
}
|
||||||
else if (type == UNIQUE_LAYER)
|
else if (type == UNIQUE_LAYER)
|
||||||
{
|
{
|
||||||
HECL::ProjectPath areaDir(pakPath, *areaName);
|
HECL::ProjectPath areaDir(levelDir, *areaName);
|
||||||
areaDir.makeDir();
|
areaDir.makeDir();
|
||||||
HECL::ProjectPath layerDir(areaDir, *layerName);
|
HECL::ProjectPath layerDir(areaDir, *layerName);
|
||||||
layerDir.makeDir();
|
layerDir.makeDir();
|
||||||
return layerDir;
|
return layerDir;
|
||||||
}
|
}
|
||||||
return pakPath;
|
|
||||||
|
return levelDir;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -56,55 +56,88 @@ UniqueResult PAKBridge::uniqueCheck(const PAK::Entry& entry)
|
||||||
{
|
{
|
||||||
UniqueResult::Type result = UniqueResult::UNIQUE_NOTFOUND;
|
UniqueResult::Type result = UniqueResult::UNIQUE_NOTFOUND;
|
||||||
bool foundOneLayer = false;
|
bool foundOneLayer = false;
|
||||||
|
const HECL::SystemString* levelName = nullptr;
|
||||||
|
UniqueID32 levelId;
|
||||||
UniqueID32 areaId;
|
UniqueID32 areaId;
|
||||||
unsigned layerIdx;
|
unsigned layerIdx;
|
||||||
for (const auto& pair : m_areaDeps)
|
for (const auto& lpair : m_levelDeps)
|
||||||
{
|
{
|
||||||
unsigned l=0;
|
levelName = &lpair.second.name;
|
||||||
for (const auto& layer : pair.second.layers)
|
if (entry.id == lpair.first)
|
||||||
{
|
{
|
||||||
if (layer.resources.find(entry.id) != layer.resources.end())
|
result = UniqueResult::UNIQUE_LEVEL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto& pair : lpair.second.areas)
|
||||||
|
{
|
||||||
|
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 if (levelId == lpair.first)
|
||||||
|
{
|
||||||
|
result = UniqueResult::UNIQUE_LEVEL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return {UniqueResult::UNIQUE_PAK};
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
result = UniqueResult::UNIQUE_LAYER;
|
||||||
|
levelId = lpair.first;
|
||||||
|
areaId = pair.first;
|
||||||
|
layerIdx = l;
|
||||||
|
foundOneLayer = true;
|
||||||
|
}
|
||||||
|
++l;
|
||||||
|
}
|
||||||
|
if (pair.second.resources.find(entry.id) != pair.second.resources.end())
|
||||||
{
|
{
|
||||||
if (foundOneLayer)
|
if (foundOneLayer)
|
||||||
{
|
{
|
||||||
if (areaId == pair.first)
|
if (areaId == pair.first)
|
||||||
|
{
|
||||||
result = UniqueResult::UNIQUE_AREA;
|
result = UniqueResult::UNIQUE_AREA;
|
||||||
|
}
|
||||||
|
else if (levelId == lpair.first)
|
||||||
|
{
|
||||||
|
result = UniqueResult::UNIQUE_LEVEL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
return {UniqueResult::UNIQUE_LEVEL};
|
{
|
||||||
|
return {UniqueResult::UNIQUE_PAK};
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
result = UniqueResult::UNIQUE_LAYER;
|
result = UniqueResult::UNIQUE_AREA;
|
||||||
|
levelId = lpair.first;
|
||||||
areaId = pair.first;
|
areaId = pair.first;
|
||||||
layerIdx = l;
|
|
||||||
foundOneLayer = true;
|
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};
|
UniqueResult retval = {result};
|
||||||
|
retval.levelName = levelName;
|
||||||
if (result == UniqueResult::UNIQUE_LAYER || result == UniqueResult::UNIQUE_AREA)
|
if (result == UniqueResult::UNIQUE_LAYER || result == UniqueResult::UNIQUE_AREA)
|
||||||
{
|
{
|
||||||
const PAKBridge::Area& area = m_areaDeps[areaId];
|
const PAKBridge::Level::Area& area = m_levelDeps[levelId].areas[areaId];
|
||||||
retval.areaName = &area.name;
|
retval.areaName = &area.name;
|
||||||
if (result == UniqueResult::UNIQUE_LAYER)
|
if (result == UniqueResult::UNIQUE_LAYER)
|
||||||
{
|
{
|
||||||
const PAKBridge::Area::Layer& layer = area.layers[layerIdx];
|
const PAKBridge::Level::Area::Layer& layer = area.layers[layerIdx];
|
||||||
retval.layerName = &layer.name;
|
retval.layerName = &layer.name;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -131,10 +164,17 @@ void PAKBridge::build()
|
||||||
{
|
{
|
||||||
if (entry.type == FOURCC('MLVL'))
|
if (entry.type == FOURCC('MLVL'))
|
||||||
{
|
{
|
||||||
|
PAKBridge::Level& level = m_levelDeps[entry.id];
|
||||||
|
|
||||||
PAKEntryReadStream rs = entry.beginReadStream(m_node);
|
PAKEntryReadStream rs = entry.beginReadStream(m_node);
|
||||||
MLVL mlvl;
|
MLVL mlvl;
|
||||||
mlvl.read(rs);
|
mlvl.read(rs);
|
||||||
m_areaDeps.reserve(mlvl.areaCount);
|
#if HECL_UCS2
|
||||||
|
level.name = HECL::UTF8ToWide(m_pak.bestEntryName(entry));
|
||||||
|
#else
|
||||||
|
level.name = m_pak.bestEntryName(entry);
|
||||||
|
#endif
|
||||||
|
level.areas.reserve(mlvl.areaCount);
|
||||||
unsigned layerIdx = 0;
|
unsigned layerIdx = 0;
|
||||||
|
|
||||||
/* Pre-pass: find duplicate area names */
|
/* Pre-pass: find duplicate area names */
|
||||||
|
@ -160,7 +200,7 @@ void PAKBridge::build()
|
||||||
/* Main-pass: index areas */
|
/* Main-pass: index areas */
|
||||||
for (const MLVL::Area& area : mlvl.areas)
|
for (const MLVL::Area& area : mlvl.areas)
|
||||||
{
|
{
|
||||||
Area& areaDeps = m_areaDeps[area.areaMREAId];
|
Level::Area& areaDeps = level.areas[area.areaMREAId];
|
||||||
const PAK::Entry* areaNameEnt = m_pak.lookupEntry(area.areaNameId);
|
const PAK::Entry* areaNameEnt = m_pak.lookupEntry(area.areaNameId);
|
||||||
if (areaNameEnt)
|
if (areaNameEnt)
|
||||||
{
|
{
|
||||||
|
@ -199,7 +239,7 @@ void PAKBridge::build()
|
||||||
for (unsigned l=1 ; l<area.depLayerCount ; ++l)
|
for (unsigned l=1 ; l<area.depLayerCount ; ++l)
|
||||||
{
|
{
|
||||||
areaDeps.layers.emplace_back();
|
areaDeps.layers.emplace_back();
|
||||||
Area::Layer& layer = areaDeps.layers.back();
|
Level::Area::Layer& layer = areaDeps.layers.back();
|
||||||
layer.name = LayerName(mlvl.layerNames[layerIdx++]);
|
layer.name = LayerName(mlvl.layerNames[layerIdx++]);
|
||||||
/* Trim possible trailing whitespace */
|
/* Trim possible trailing whitespace */
|
||||||
#if HECL_UCS2
|
#if HECL_UCS2
|
||||||
|
|
|
@ -17,18 +17,23 @@ class PAKBridge
|
||||||
HECL::Database::Project& m_project;
|
HECL::Database::Project& m_project;
|
||||||
const NOD::DiscBase::IPartition::Node& m_node;
|
const NOD::DiscBase::IPartition::Node& m_node;
|
||||||
PAK m_pak;
|
PAK m_pak;
|
||||||
struct Area
|
struct Level
|
||||||
{
|
{
|
||||||
HECL::SystemString name;
|
HECL::SystemString name;
|
||||||
struct Layer
|
struct Area
|
||||||
{
|
{
|
||||||
HECL::SystemString name;
|
HECL::SystemString name;
|
||||||
|
struct Layer
|
||||||
|
{
|
||||||
|
HECL::SystemString name;
|
||||||
|
std::unordered_set<UniqueID32> resources;
|
||||||
|
};
|
||||||
|
std::vector<Layer> layers;
|
||||||
std::unordered_set<UniqueID32> resources;
|
std::unordered_set<UniqueID32> resources;
|
||||||
};
|
};
|
||||||
std::vector<Layer> layers;
|
std::unordered_map<UniqueID32, Area> areas;
|
||||||
std::unordered_set<UniqueID32> resources;
|
|
||||||
};
|
};
|
||||||
std::unordered_map<UniqueID32, Area> m_areaDeps;
|
std::unordered_map<UniqueID32, Level> m_levelDeps;
|
||||||
HECL::SystemString m_levelString;
|
HECL::SystemString m_levelString;
|
||||||
UniqueResult uniqueCheck(const PAK::Entry& entry);
|
UniqueResult uniqueCheck(const PAK::Entry& entry);
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -54,55 +54,88 @@ UniqueResult PAKBridge::uniqueCheck(const DNAMP1::PAK::Entry& entry)
|
||||||
{
|
{
|
||||||
UniqueResult::Type result = UniqueResult::UNIQUE_NOTFOUND;
|
UniqueResult::Type result = UniqueResult::UNIQUE_NOTFOUND;
|
||||||
bool foundOneLayer = false;
|
bool foundOneLayer = false;
|
||||||
|
const HECL::SystemString* levelName = nullptr;
|
||||||
|
UniqueID32 levelId;
|
||||||
UniqueID32 areaId;
|
UniqueID32 areaId;
|
||||||
unsigned layerIdx;
|
unsigned layerIdx;
|
||||||
for (const auto& pair : m_areaDeps)
|
for (const auto& lpair : m_levelDeps)
|
||||||
{
|
{
|
||||||
unsigned l=0;
|
levelName = &lpair.second.name;
|
||||||
for (const auto& layer : pair.second.layers)
|
if (entry.id == lpair.first)
|
||||||
{
|
{
|
||||||
if (layer.resources.find(entry.id) != layer.resources.end())
|
result = UniqueResult::UNIQUE_LEVEL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto& pair : lpair.second.areas)
|
||||||
|
{
|
||||||
|
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 if (levelId == lpair.first)
|
||||||
|
{
|
||||||
|
result = UniqueResult::UNIQUE_LEVEL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return {UniqueResult::UNIQUE_PAK};
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
result = UniqueResult::UNIQUE_LAYER;
|
||||||
|
levelId = lpair.first;
|
||||||
|
areaId = pair.first;
|
||||||
|
layerIdx = l;
|
||||||
|
foundOneLayer = true;
|
||||||
|
}
|
||||||
|
++l;
|
||||||
|
}
|
||||||
|
if (pair.second.resources.find(entry.id) != pair.second.resources.end())
|
||||||
{
|
{
|
||||||
if (foundOneLayer)
|
if (foundOneLayer)
|
||||||
{
|
{
|
||||||
if (areaId == pair.first)
|
if (areaId == pair.first)
|
||||||
|
{
|
||||||
result = UniqueResult::UNIQUE_AREA;
|
result = UniqueResult::UNIQUE_AREA;
|
||||||
|
}
|
||||||
|
else if (levelId == lpair.first)
|
||||||
|
{
|
||||||
|
result = UniqueResult::UNIQUE_LEVEL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
return {UniqueResult::UNIQUE_LEVEL};
|
{
|
||||||
|
return {UniqueResult::UNIQUE_PAK};
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
result = UniqueResult::UNIQUE_LAYER;
|
result = UniqueResult::UNIQUE_AREA;
|
||||||
|
levelId = lpair.first;
|
||||||
areaId = pair.first;
|
areaId = pair.first;
|
||||||
layerIdx = l;
|
|
||||||
foundOneLayer = true;
|
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};
|
UniqueResult retval = {result};
|
||||||
|
retval.levelName = levelName;
|
||||||
if (result == UniqueResult::UNIQUE_LAYER || result == UniqueResult::UNIQUE_AREA)
|
if (result == UniqueResult::UNIQUE_LAYER || result == UniqueResult::UNIQUE_AREA)
|
||||||
{
|
{
|
||||||
const PAKBridge::Area& area = m_areaDeps[areaId];
|
const PAKBridge::Level::Area& area = m_levelDeps[levelId].areas[areaId];
|
||||||
retval.areaName = &area.name;
|
retval.areaName = &area.name;
|
||||||
if (result == UniqueResult::UNIQUE_LAYER)
|
if (result == UniqueResult::UNIQUE_LAYER)
|
||||||
{
|
{
|
||||||
const PAKBridge::Area::Layer& layer = area.layers[layerIdx];
|
const PAKBridge::Level::Area::Layer& layer = area.layers[layerIdx];
|
||||||
retval.layerName = &layer.name;
|
retval.layerName = &layer.name;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -129,10 +162,17 @@ void PAKBridge::build()
|
||||||
{
|
{
|
||||||
if (entry.type == FOURCC('MLVL'))
|
if (entry.type == FOURCC('MLVL'))
|
||||||
{
|
{
|
||||||
|
PAKBridge::Level& level = m_levelDeps[entry.id];
|
||||||
|
|
||||||
PAKEntryReadStream rs = entry.beginReadStream(m_node);
|
PAKEntryReadStream rs = entry.beginReadStream(m_node);
|
||||||
MLVL mlvl;
|
MLVL mlvl;
|
||||||
mlvl.read(rs);
|
mlvl.read(rs);
|
||||||
m_areaDeps.reserve(mlvl.areaCount);
|
#if HECL_UCS2
|
||||||
|
level.name = HECL::UTF8ToWide(m_pak.bestEntryName(entry));
|
||||||
|
#else
|
||||||
|
level.name = m_pak.bestEntryName(entry);
|
||||||
|
#endif
|
||||||
|
level.areas.reserve(mlvl.areaCount);
|
||||||
unsigned layerIdx = 0;
|
unsigned layerIdx = 0;
|
||||||
|
|
||||||
/* Pre-pass: find duplicate area names */
|
/* Pre-pass: find duplicate area names */
|
||||||
|
@ -158,7 +198,7 @@ void PAKBridge::build()
|
||||||
/* Main-pass: index areas */
|
/* Main-pass: index areas */
|
||||||
for (const MLVL::Area& area : mlvl.areas)
|
for (const MLVL::Area& area : mlvl.areas)
|
||||||
{
|
{
|
||||||
Area& areaDeps = m_areaDeps[area.areaMREAId];
|
Level::Area& areaDeps = level.areas[area.areaMREAId];
|
||||||
const DNAMP1::PAK::Entry* areaNameEnt = m_pak.lookupEntry(area.areaNameId);
|
const DNAMP1::PAK::Entry* areaNameEnt = m_pak.lookupEntry(area.areaNameId);
|
||||||
if (areaNameEnt)
|
if (areaNameEnt)
|
||||||
{
|
{
|
||||||
|
@ -205,7 +245,7 @@ void PAKBridge::build()
|
||||||
for (unsigned l=1 ; l<area.depLayerCount ; ++l)
|
for (unsigned l=1 ; l<area.depLayerCount ; ++l)
|
||||||
{
|
{
|
||||||
areaDeps.layers.emplace_back();
|
areaDeps.layers.emplace_back();
|
||||||
Area::Layer& layer = areaDeps.layers.back();
|
Level::Area::Layer& layer = areaDeps.layers.back();
|
||||||
layer.name = LayerName(mlvl.layerNames[layerIdx++]);
|
layer.name = LayerName(mlvl.layerNames[layerIdx++]);
|
||||||
/* Trim possible trailing whitespace */
|
/* Trim possible trailing whitespace */
|
||||||
#if HECL_UCS2
|
#if HECL_UCS2
|
||||||
|
|
|
@ -17,18 +17,23 @@ class PAKBridge
|
||||||
HECL::Database::Project& m_project;
|
HECL::Database::Project& m_project;
|
||||||
const NOD::DiscBase::IPartition::Node& m_node;
|
const NOD::DiscBase::IPartition::Node& m_node;
|
||||||
DNAMP1::PAK m_pak;
|
DNAMP1::PAK m_pak;
|
||||||
struct Area
|
struct Level
|
||||||
{
|
{
|
||||||
HECL::SystemString name;
|
HECL::SystemString name;
|
||||||
struct Layer
|
struct Area
|
||||||
{
|
{
|
||||||
HECL::SystemString name;
|
HECL::SystemString name;
|
||||||
|
struct Layer
|
||||||
|
{
|
||||||
|
HECL::SystemString name;
|
||||||
|
std::unordered_set<UniqueID32> resources;
|
||||||
|
};
|
||||||
|
std::vector<Layer> layers;
|
||||||
std::unordered_set<UniqueID32> resources;
|
std::unordered_set<UniqueID32> resources;
|
||||||
};
|
};
|
||||||
std::vector<Layer> layers;
|
std::unordered_map<UniqueID32, Area> areas;
|
||||||
std::unordered_set<UniqueID32> resources;
|
|
||||||
};
|
};
|
||||||
std::unordered_map<UniqueID32, Area> m_areaDeps;
|
std::unordered_map<UniqueID32, Level> m_levelDeps;
|
||||||
HECL::SystemString m_levelString;
|
HECL::SystemString m_levelString;
|
||||||
UniqueResult uniqueCheck(const DNAMP1::PAK::Entry& entry);
|
UniqueResult uniqueCheck(const DNAMP1::PAK::Entry& entry);
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -62,55 +62,88 @@ UniqueResult PAKBridge::uniqueCheck(const PAK::Entry& entry)
|
||||||
{
|
{
|
||||||
UniqueResult::Type result = UniqueResult::UNIQUE_NOTFOUND;
|
UniqueResult::Type result = UniqueResult::UNIQUE_NOTFOUND;
|
||||||
bool foundOneLayer = false;
|
bool foundOneLayer = false;
|
||||||
|
const HECL::SystemString* levelName = nullptr;
|
||||||
|
UniqueID64 levelId;
|
||||||
UniqueID64 areaId;
|
UniqueID64 areaId;
|
||||||
unsigned layerIdx;
|
unsigned layerIdx;
|
||||||
for (const auto& pair : m_areaDeps)
|
for (const auto& lpair : m_levelDeps)
|
||||||
{
|
{
|
||||||
unsigned l=0;
|
levelName = &lpair.second.name;
|
||||||
for (const auto& layer : pair.second.layers)
|
if (entry.id == lpair.first)
|
||||||
{
|
{
|
||||||
if (layer.resources.find(entry.id) != layer.resources.end())
|
result = UniqueResult::UNIQUE_LEVEL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto& pair : lpair.second.areas)
|
||||||
|
{
|
||||||
|
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 if (levelId == lpair.first)
|
||||||
|
{
|
||||||
|
result = UniqueResult::UNIQUE_LEVEL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return {UniqueResult::UNIQUE_PAK};
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
result = UniqueResult::UNIQUE_LAYER;
|
||||||
|
levelId = lpair.first;
|
||||||
|
areaId = pair.first;
|
||||||
|
layerIdx = l;
|
||||||
|
foundOneLayer = true;
|
||||||
|
}
|
||||||
|
++l;
|
||||||
|
}
|
||||||
|
if (pair.second.resources.find(entry.id) != pair.second.resources.end())
|
||||||
{
|
{
|
||||||
if (foundOneLayer)
|
if (foundOneLayer)
|
||||||
{
|
{
|
||||||
if (areaId == pair.first)
|
if (areaId == pair.first)
|
||||||
|
{
|
||||||
result = UniqueResult::UNIQUE_AREA;
|
result = UniqueResult::UNIQUE_AREA;
|
||||||
|
}
|
||||||
|
else if (levelId == lpair.first)
|
||||||
|
{
|
||||||
|
result = UniqueResult::UNIQUE_LEVEL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
return {UniqueResult::UNIQUE_LEVEL};
|
{
|
||||||
|
return {UniqueResult::UNIQUE_PAK};
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
result = UniqueResult::UNIQUE_LAYER;
|
result = UniqueResult::UNIQUE_AREA;
|
||||||
|
levelId = lpair.first;
|
||||||
areaId = pair.first;
|
areaId = pair.first;
|
||||||
layerIdx = l;
|
|
||||||
foundOneLayer = true;
|
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};
|
UniqueResult retval = {result};
|
||||||
|
retval.levelName = levelName;
|
||||||
if (result == UniqueResult::UNIQUE_LAYER || result == UniqueResult::UNIQUE_AREA)
|
if (result == UniqueResult::UNIQUE_LAYER || result == UniqueResult::UNIQUE_AREA)
|
||||||
{
|
{
|
||||||
const PAKBridge::Area& area = m_areaDeps[areaId];
|
const PAKBridge::Level::Area& area = m_levelDeps[levelId].areas[areaId];
|
||||||
retval.areaName = &area.name;
|
retval.areaName = &area.name;
|
||||||
if (result == UniqueResult::UNIQUE_LAYER)
|
if (result == UniqueResult::UNIQUE_LAYER)
|
||||||
{
|
{
|
||||||
const PAKBridge::Area::Layer& layer = area.layers[layerIdx];
|
const PAKBridge::Level::Area::Layer& layer = area.layers[layerIdx];
|
||||||
retval.layerName = &layer.name;
|
retval.layerName = &layer.name;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -137,10 +170,17 @@ void PAKBridge::build()
|
||||||
{
|
{
|
||||||
if (entry.type == FOURCC('MLVL'))
|
if (entry.type == FOURCC('MLVL'))
|
||||||
{
|
{
|
||||||
|
PAKBridge::Level& level = m_levelDeps[entry.id];
|
||||||
|
|
||||||
PAKEntryReadStream rs = entry.beginReadStream(m_node);
|
PAKEntryReadStream rs = entry.beginReadStream(m_node);
|
||||||
MLVL mlvl;
|
MLVL mlvl;
|
||||||
mlvl.read(rs);
|
mlvl.read(rs);
|
||||||
m_areaDeps.reserve(mlvl.areaCount);
|
#if HECL_UCS2
|
||||||
|
level.name = HECL::UTF8ToWide(m_pak.bestEntryName(entry));
|
||||||
|
#else
|
||||||
|
level.name = m_pak.bestEntryName(entry);
|
||||||
|
#endif
|
||||||
|
level.areas.reserve(mlvl.areaCount);
|
||||||
unsigned layerIdx = 0;
|
unsigned layerIdx = 0;
|
||||||
|
|
||||||
/* Pre-pass: find duplicate area names */
|
/* Pre-pass: find duplicate area names */
|
||||||
|
@ -167,7 +207,7 @@ void PAKBridge::build()
|
||||||
auto layerFlagsIt = mlvl.layerFlags.begin();
|
auto layerFlagsIt = mlvl.layerFlags.begin();
|
||||||
for (const MLVL::Area& area : mlvl.areas)
|
for (const MLVL::Area& area : mlvl.areas)
|
||||||
{
|
{
|
||||||
Area& areaDeps = m_areaDeps[area.areaMREAId];
|
Level::Area& areaDeps = level.areas[area.areaMREAId];
|
||||||
const PAK::Entry* areaNameEnt = m_pak.lookupEntry(area.areaNameId);
|
const PAK::Entry* areaNameEnt = m_pak.lookupEntry(area.areaNameId);
|
||||||
if (areaNameEnt)
|
if (areaNameEnt)
|
||||||
{
|
{
|
||||||
|
@ -216,7 +256,7 @@ void PAKBridge::build()
|
||||||
for (unsigned l=0 ; l<areaLayers.layerCount ; ++l)
|
for (unsigned l=0 ; l<areaLayers.layerCount ; ++l)
|
||||||
{
|
{
|
||||||
areaDeps.layers.emplace_back();
|
areaDeps.layers.emplace_back();
|
||||||
Area::Layer& layer = areaDeps.layers.back();
|
Level::Area::Layer& layer = areaDeps.layers.back();
|
||||||
layer.name = LayerName(mlvl.layerNames[layerIdx++]);
|
layer.name = LayerName(mlvl.layerNames[layerIdx++]);
|
||||||
/* Trim possible trailing whitespace */
|
/* Trim possible trailing whitespace */
|
||||||
#if HECL_UCS2
|
#if HECL_UCS2
|
||||||
|
|
|
@ -19,18 +19,23 @@ class PAKBridge
|
||||||
PAK m_pak;
|
PAK m_pak;
|
||||||
UniqueResult uniqueCheck(const PAK::Entry& entry);
|
UniqueResult uniqueCheck(const PAK::Entry& entry);
|
||||||
public:
|
public:
|
||||||
struct Area
|
struct Level
|
||||||
{
|
{
|
||||||
HECL::SystemString name;
|
HECL::SystemString name;
|
||||||
struct Layer
|
struct Area
|
||||||
{
|
{
|
||||||
HECL::SystemString name;
|
HECL::SystemString name;
|
||||||
|
struct Layer
|
||||||
|
{
|
||||||
|
HECL::SystemString name;
|
||||||
|
std::unordered_set<UniqueID64> resources;
|
||||||
|
};
|
||||||
|
std::vector<Layer> layers;
|
||||||
std::unordered_set<UniqueID64> resources;
|
std::unordered_set<UniqueID64> resources;
|
||||||
};
|
};
|
||||||
std::vector<Layer> layers;
|
std::unordered_map<UniqueID64, Area> areas;
|
||||||
std::unordered_set<UniqueID64> resources;
|
|
||||||
};
|
};
|
||||||
std::unordered_map<UniqueID64, Area> m_areaDeps;
|
std::unordered_map<UniqueID64, Level> m_levelDeps;
|
||||||
HECL::SystemString m_levelString;
|
HECL::SystemString m_levelString;
|
||||||
|
|
||||||
PAKBridge(HECL::Database::Project& project, const NOD::DiscBase::IPartition::Node& node);
|
PAKBridge(HECL::Database::Project& project, const NOD::DiscBase::IPartition::Node& node);
|
||||||
|
|
|
@ -315,7 +315,7 @@ bool MREA::Extract(const SpecBase& dataSpec,
|
||||||
return conn.saveBlend();
|
return conn.saveBlend();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MREA::ExtractLayerDeps(PAKEntryReadStream& rs, PAKBridge::Area& areaOut)
|
bool MREA::ExtractLayerDeps(PAKEntryReadStream& rs, PAKBridge::Level::Area& areaOut)
|
||||||
{
|
{
|
||||||
/* Do extract */
|
/* Do extract */
|
||||||
Header head;
|
Header head;
|
||||||
|
@ -335,7 +335,7 @@ bool MREA::ExtractLayerDeps(PAKEntryReadStream& rs, PAKBridge::Area& areaOut)
|
||||||
unsigned r=0;
|
unsigned r=0;
|
||||||
for (unsigned l=1 ; l<deps.depLayerCount ; ++l)
|
for (unsigned l=1 ; l<deps.depLayerCount ; ++l)
|
||||||
{
|
{
|
||||||
PAKBridge::Area::Layer& layer = areaOut.layers.at(l-1);
|
PAKBridge::Level::Area::Layer& layer = areaOut.layers.at(l-1);
|
||||||
layer.resources.reserve(deps.depLayers[l] - r);
|
layer.resources.reserve(deps.depLayers[l] - r);
|
||||||
for (; r<deps.depLayers[l] ; ++r)
|
for (; r<deps.depLayers[l] ; ++r)
|
||||||
layer.resources.emplace(deps.deps[r].id);
|
layer.resources.emplace(deps.deps[r].id);
|
||||||
|
|
|
@ -114,7 +114,7 @@ struct MREA
|
||||||
bool,
|
bool,
|
||||||
std::function<void(const HECL::SystemChar*)>);
|
std::function<void(const HECL::SystemChar*)>);
|
||||||
|
|
||||||
static bool ExtractLayerDeps(PAKEntryReadStream& rs, PAKBridge::Area& areaOut);
|
static bool ExtractLayerDeps(PAKEntryReadStream& rs, PAKBridge::Level::Area& areaOut);
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue