Additional extract directory tier for level names

This commit is contained in:
Jack Andersen 2015-09-23 12:59:12 -10:00
parent b1f55c2733
commit 2893eb7e76
9 changed files with 253 additions and 105 deletions

View File

@ -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;
} }
}; };

View File

@ -56,9 +56,20 @@ 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)
{
levelName = &lpair.second.name;
if (entry.id == lpair.first)
{
result = UniqueResult::UNIQUE_LEVEL;
break;
}
for (const auto& pair : lpair.second.areas)
{ {
unsigned l=0; unsigned l=0;
for (const auto& layer : pair.second.layers) for (const auto& layer : pair.second.layers)
@ -68,13 +79,23 @@ UniqueResult PAKBridge::uniqueCheck(const PAK::Entry& entry)
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_LAYER;
levelId = lpair.first;
areaId = pair.first; areaId = pair.first;
layerIdx = l; layerIdx = l;
foundOneLayer = true; foundOneLayer = true;
@ -86,25 +107,37 @@ UniqueResult PAKBridge::uniqueCheck(const PAK::Entry& entry)
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_AREA; result = UniqueResult::UNIQUE_AREA;
levelId = lpair.first;
areaId = pair.first; areaId = pair.first;
foundOneLayer = true; 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

View File

@ -17,6 +17,9 @@ 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 Level
{
HECL::SystemString name;
struct Area struct Area
{ {
HECL::SystemString name; HECL::SystemString name;
@ -28,7 +31,9 @@ class PAKBridge
std::vector<Layer> layers; std::vector<Layer> layers;
std::unordered_set<UniqueID32> resources; std::unordered_set<UniqueID32> resources;
}; };
std::unordered_map<UniqueID32, Area> m_areaDeps; std::unordered_map<UniqueID32, Area> areas;
};
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:

View File

@ -54,9 +54,20 @@ 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)
{
levelName = &lpair.second.name;
if (entry.id == lpair.first)
{
result = UniqueResult::UNIQUE_LEVEL;
break;
}
for (const auto& pair : lpair.second.areas)
{ {
unsigned l=0; unsigned l=0;
for (const auto& layer : pair.second.layers) for (const auto& layer : pair.second.layers)
@ -66,13 +77,23 @@ UniqueResult PAKBridge::uniqueCheck(const DNAMP1::PAK::Entry& entry)
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_LAYER;
levelId = lpair.first;
areaId = pair.first; areaId = pair.first;
layerIdx = l; layerIdx = l;
foundOneLayer = true; foundOneLayer = true;
@ -84,25 +105,37 @@ UniqueResult PAKBridge::uniqueCheck(const DNAMP1::PAK::Entry& entry)
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_AREA; result = UniqueResult::UNIQUE_AREA;
levelId = lpair.first;
areaId = pair.first; areaId = pair.first;
foundOneLayer = true; 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

View File

@ -17,6 +17,9 @@ 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 Level
{
HECL::SystemString name;
struct Area struct Area
{ {
HECL::SystemString name; HECL::SystemString name;
@ -28,7 +31,9 @@ class PAKBridge
std::vector<Layer> layers; std::vector<Layer> layers;
std::unordered_set<UniqueID32> resources; std::unordered_set<UniqueID32> resources;
}; };
std::unordered_map<UniqueID32, Area> m_areaDeps; std::unordered_map<UniqueID32, Area> areas;
};
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:

View File

@ -62,9 +62,20 @@ 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)
{
levelName = &lpair.second.name;
if (entry.id == lpair.first)
{
result = UniqueResult::UNIQUE_LEVEL;
break;
}
for (const auto& pair : lpair.second.areas)
{ {
unsigned l=0; unsigned l=0;
for (const auto& layer : pair.second.layers) for (const auto& layer : pair.second.layers)
@ -74,13 +85,23 @@ UniqueResult PAKBridge::uniqueCheck(const PAK::Entry& entry)
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_LAYER;
levelId = lpair.first;
areaId = pair.first; areaId = pair.first;
layerIdx = l; layerIdx = l;
foundOneLayer = true; foundOneLayer = true;
@ -92,25 +113,37 @@ UniqueResult PAKBridge::uniqueCheck(const PAK::Entry& entry)
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_AREA; result = UniqueResult::UNIQUE_AREA;
levelId = lpair.first;
areaId = pair.first; areaId = pair.first;
foundOneLayer = true; 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

View File

@ -19,6 +19,9 @@ class PAKBridge
PAK m_pak; PAK m_pak;
UniqueResult uniqueCheck(const PAK::Entry& entry); UniqueResult uniqueCheck(const PAK::Entry& entry);
public: public:
struct Level
{
HECL::SystemString name;
struct Area struct Area
{ {
HECL::SystemString name; HECL::SystemString name;
@ -30,7 +33,9 @@ public:
std::vector<Layer> layers; std::vector<Layer> layers;
std::unordered_set<UniqueID64> resources; std::unordered_set<UniqueID64> resources;
}; };
std::unordered_map<UniqueID64, Area> m_areaDeps; std::unordered_map<UniqueID64, Area> areas;
};
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);

View File

@ -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);

View File

@ -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);
}; };
} }