From 94d84d8991dd0c6b5fdb5557476eb4c3421d7b09 Mon Sep 17 00:00:00 2001 From: Jack Andersen Date: Thu, 16 Jul 2015 14:01:05 -1000 Subject: [PATCH] re-balancing of DataSpec/DNA systems --- DataSpec/DNACommon/DNACommon.hpp | 11 +++++ DataSpec/DNACommon/STRG.hpp | 24 +++++++++ DataSpec/DNAMP1/DNAMP1.cpp | 58 ++++++++++++++++++++++ DataSpec/DNAMP1/DNAMP1.hpp | 17 +++++++ DataSpec/DNAMP1/PAK.hpp | 11 +++++ DataSpec/DNAMP1/STRG.hpp | 2 + DataSpec/DNAMP2/DNAMP2.cpp | 59 ++++++++++++++++++++++ DataSpec/DNAMP2/DNAMP2.hpp | 17 +++++++ DataSpec/DNAMP3/DNAMP3.cpp | 67 +++++++++++++++++++++++++ DataSpec/DNAMP3/DNAMP3.hpp | 17 +++++++ DataSpec/DNAMP3/PAK.hpp | 11 +++++ DataSpec/SpecBase.cpp | 11 +++-- DataSpec/SpecBase.hpp | 13 +++-- DataSpec/SpecMP1.cpp | 85 ++++++++------------------------ DataSpec/SpecMP2.cpp | 64 +++++++----------------- DataSpec/SpecMP3.cpp | 70 +++++++------------------- NODLib | 2 +- 17 files changed, 364 insertions(+), 175 deletions(-) diff --git a/DataSpec/DNACommon/DNACommon.hpp b/DataSpec/DNACommon/DNACommon.hpp index 35b5df426..26d028219 100644 --- a/DataSpec/DNACommon/DNACommon.hpp +++ b/DataSpec/DNACommon/DNACommon.hpp @@ -3,6 +3,7 @@ #include #include "HECL/HECL.hpp" +#include "HECL/Database.hpp" namespace Retro { @@ -178,6 +179,16 @@ public: } }; +/* Resource extractor type */ +typedef struct +{ + std::function func; + const char* fileExt; +} ResExtractor; + +/* Resource cooker function */ +typedef std::function ResCooker; + /* Language-identifiers */ extern const HECL::FourCC ENGL; extern const HECL::FourCC FREN; diff --git a/DataSpec/DNACommon/STRG.hpp b/DataSpec/DNACommon/STRG.hpp index 2f2601335..e6bbe38e1 100644 --- a/DataSpec/DNACommon/STRG.hpp +++ b/DataSpec/DNACommon/STRG.hpp @@ -6,6 +6,7 @@ #include #include #include +#include #include "DNACommon.hpp" namespace Retro @@ -22,6 +23,29 @@ struct ISTRG virtual bool readAngelScript(const AngelScript::asIScriptModule& in)=0; virtual void writeAngelScript(std::ofstream& out) const=0; + + template + static bool Extract(PAKEntryReadStream& rs, const HECL::ProjectPath& outPath) + { + SUBCLS strg; + strg.read(rs); + std::ofstream strgOut(outPath.getAbsolutePath()); + strg.writeAngelScript(strgOut); + return true; + } + + template + static bool Cook(const HECL::ProjectPath& inPath, const HECL::ProjectPath& outPath) + { + SUBCLS strg; + HECL::Database::ASUniqueModule mod = HECL::Database::ASUniqueModule::CreateFromPath(inPath); + if (!mod) + return false; + strg.readAngelScript(mod); + Athena::io::FileWriter ws(outPath.getAbsolutePath()); + strg.write(ws); + return true; + } }; std::unique_ptr LoadSTRG(Athena::io::IStreamReader& reader); diff --git a/DataSpec/DNAMP1/DNAMP1.cpp b/DataSpec/DNAMP1/DNAMP1.cpp index f714e961f..45cc4ef76 100644 --- a/DataSpec/DNAMP1/DNAMP1.cpp +++ b/DataSpec/DNAMP1/DNAMP1.cpp @@ -1,9 +1,67 @@ +#define NOD_ATHENA 1 #include "DNAMP1.hpp" +#include "STRG.hpp" +#include "MLVL.hpp" namespace Retro { namespace DNAMP1 { LogVisor::LogModule Log("Retro::DNAMP1"); + +PAKBridge::PAKBridge(HECL::Database::Project& project, const NOD::DiscBase::IPartition::Node& node) +: m_project(project), m_node(node) +{ + NOD::AthenaPartReadStream rs(node.beginReadStream()); + m_pak.read(rs); +} + +std::string PAKBridge::getLevelString() const +{ + std::string retval; + for (const PAK::Entry& entry : m_pak.m_entries) + { + if (entry.type == Retro::MLVL) + { + PAKEntryReadStream rs = entry.beginReadStream(m_node); + MLVL mlvl; + mlvl.read(rs); + const PAK::Entry* nameEnt = m_pak.lookupEntry(mlvl.worldNameId); + if (nameEnt) + { + PAKEntryReadStream rs = nameEnt->beginReadStream(m_node); + STRG mlvlName; + mlvlName.read(rs); + if (retval.size()) + retval += _S(", "); + retval += mlvlName.getSystemString(ENGL, 0); + } + } + } + return retval; +} + +ResExtractor PAKBridge::LookupExtractor(const PAK::Entry& entry) +{ + if (entry.type == Retro::STRG) + return {STRG::Extract, ".strg"}; + return {}; +} + +bool PAKBridge::extractResources(const HECL::ProjectPath& dirOut) +{ + for (const std::pair& item : m_pak.m_idMap) + { + ResExtractor extractor = LookupExtractor(*item.second); + if (extractor.func) + { + PAKEntryReadStream strgIn = item.second->beginReadStream(m_node); + HECL::ProjectPath resPath(dirOut, m_pak.bestEntryName(*item.second) + extractor.fileExt); + extractor.func(strgIn, resPath); + } + } + return true; +} + } } diff --git a/DataSpec/DNAMP1/DNAMP1.hpp b/DataSpec/DNAMP1/DNAMP1.hpp index ffc0146a5..54a7316ff 100644 --- a/DataSpec/DNAMP1/DNAMP1.hpp +++ b/DataSpec/DNAMP1/DNAMP1.hpp @@ -2,6 +2,7 @@ #define __DNAMP1_HPP__ #include "../DNACommon/DNACommon.hpp" +#include "PAK.hpp" namespace Retro { @@ -10,6 +11,22 @@ namespace DNAMP1 extern LogVisor::LogModule Log; +/* MP1-specific, one-shot PAK traversal/extraction class */ +class PAKBridge +{ + HECL::Database::Project& m_project; + const NOD::DiscBase::IPartition::Node& m_node; + PAK m_pak; + + static ResExtractor LookupExtractor(const PAK::Entry& entry); + +public: + PAKBridge(HECL::Database::Project& project, const NOD::DiscBase::IPartition::Node& node); + const std::string& getName() const {return m_node.getName();} + std::string getLevelString() const; + bool extractResources(const HECL::ProjectPath& dirOut); +}; + } } diff --git a/DataSpec/DNAMP1/PAK.hpp b/DataSpec/DNAMP1/PAK.hpp index 08ac1d6d4..42ad62b4a 100644 --- a/DataSpec/DNAMP1/PAK.hpp +++ b/DataSpec/DNAMP1/PAK.hpp @@ -61,6 +61,17 @@ struct PAK : BigDNA return result->second; return nullptr; } + + inline std::string bestEntryName(const Entry& entry) const + { + /* Prefer named entries first */ + for (const NameEntry& nentry : m_nameEntries) + if (nentry.id == entry.id) + return nentry.name; + + /* Otherwise return ID format string */ + return entry.id.toString(); + } }; } diff --git a/DataSpec/DNAMP1/STRG.hpp b/DataSpec/DNAMP1/STRG.hpp index b4f72f244..d14e10dc9 100644 --- a/DataSpec/DNAMP1/STRG.hpp +++ b/DataSpec/DNAMP1/STRG.hpp @@ -57,6 +57,8 @@ struct STRG : ISTRG, BigDNA bool readAngelScript(const AngelScript::asIScriptModule& in); void writeAngelScript(std::ofstream& out) const; + + }; } diff --git a/DataSpec/DNAMP2/DNAMP2.cpp b/DataSpec/DNAMP2/DNAMP2.cpp index 50b8de396..9add94371 100644 --- a/DataSpec/DNAMP2/DNAMP2.cpp +++ b/DataSpec/DNAMP2/DNAMP2.cpp @@ -1,9 +1,68 @@ +#define NOD_ATHENA 1 #include "DNAMP2.hpp" +#include "STRG.hpp" +#include "MLVL.hpp" namespace Retro { namespace DNAMP2 { + LogVisor::LogModule Log("Retro::DNAMP2"); + +PAKBridge::PAKBridge(HECL::Database::Project& project, const NOD::DiscBase::IPartition::Node& node) +: m_project(project), m_node(node) +{ + NOD::AthenaPartReadStream rs(node.beginReadStream()); + m_pak.read(rs); +} + +std::string PAKBridge::getLevelString() const +{ + std::string retval; + 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); + const DNAMP1::PAK::Entry* nameEnt = m_pak.lookupEntry(mlvl.worldNameId); + if (nameEnt) + { + PAKEntryReadStream rs = nameEnt->beginReadStream(m_node); + STRG mlvlName; + mlvlName.read(rs); + if (retval.size()) + retval += _S(", "); + retval += mlvlName.getSystemString(ENGL, 0); + } + } + } + return retval; +} + +ResExtractor PAKBridge::LookupExtractor(const DNAMP1::PAK::Entry& entry) +{ + if (entry.type == Retro::STRG) + return {STRG::Extract, ".strg"}; + return {}; +} + +bool PAKBridge::extractResources(const HECL::ProjectPath& dirOut) +{ + for (const std::pair& item : m_pak.m_idMap) + { + ResExtractor extractor = LookupExtractor(*item.second); + if (extractor.func) + { + PAKEntryReadStream strgIn = item.second->beginReadStream(m_node); + HECL::ProjectPath resPath(dirOut, m_pak.bestEntryName(*item.second) + extractor.fileExt); + extractor.func(strgIn, resPath); + } + } + return true; +} + } } diff --git a/DataSpec/DNAMP2/DNAMP2.hpp b/DataSpec/DNAMP2/DNAMP2.hpp index 68b1a6444..1f82651d4 100644 --- a/DataSpec/DNAMP2/DNAMP2.hpp +++ b/DataSpec/DNAMP2/DNAMP2.hpp @@ -2,6 +2,7 @@ #define __DNAMP2_HPP__ #include "../DNACommon/DNACommon.hpp" +#include "../DNAMP1/PAK.hpp" namespace Retro { @@ -10,6 +11,22 @@ namespace DNAMP2 extern LogVisor::LogModule Log; +/* MP2-specific, one-shot PAK traversal/extraction class */ +class PAKBridge +{ + HECL::Database::Project& m_project; + const NOD::DiscBase::IPartition::Node& m_node; + DNAMP1::PAK m_pak; + + static ResExtractor LookupExtractor(const DNAMP1::PAK::Entry& entry); + +public: + PAKBridge(HECL::Database::Project& project, const NOD::DiscBase::IPartition::Node& node); + const std::string& getName() const {return m_node.getName();} + std::string getLevelString() const; + bool extractResources(const HECL::ProjectPath& dirOut); +}; + } } diff --git a/DataSpec/DNAMP3/DNAMP3.cpp b/DataSpec/DNAMP3/DNAMP3.cpp index 6b124d481..f6a0a278a 100644 --- a/DataSpec/DNAMP3/DNAMP3.cpp +++ b/DataSpec/DNAMP3/DNAMP3.cpp @@ -1,9 +1,76 @@ +#include + +#define NOD_ATHENA 1 #include "DNAMP3.hpp" +#include "STRG.hpp" +#include "MLVL.hpp" namespace Retro { namespace DNAMP3 { + LogVisor::LogModule Log("Retro::DNAMP3"); + +PAKBridge::PAKBridge(HECL::Database::Project& project, const NOD::DiscBase::IPartition::Node& node) +: m_project(project), m_node(node) +{ + NOD::AthenaPartReadStream rs(node.beginReadStream()); + m_pak.read(rs); +} + +std::string PAKBridge::getLevelString() const +{ + std::string retval; + std::set worldNames; + for (const PAK::Entry& entry : m_pak.m_entries) + { + if (entry.type == Retro::MLVL) + { + PAKEntryReadStream rs = entry.beginReadStream(m_node); + MLVL mlvl; + mlvl.read(rs); + const PAK::Entry* nameEnt = m_pak.lookupEntry(mlvl.worldNameId); + if (nameEnt) + { + PAKEntryReadStream rs = nameEnt->beginReadStream(m_node); + STRG mlvlName; + mlvlName.read(rs); + worldNames.emplace(mlvlName.getSystemString(ENGL, 0)); + } + } + } + + for (const std::string& name : worldNames) + { + if (retval.size()) + retval += _S(", "); + retval += name; + } + return retval; +} + +ResExtractor PAKBridge::LookupExtractor(const PAK::Entry& entry) +{ + if (entry.type == Retro::STRG) + return {STRG::Extract, ".strg"}; + return {}; +} + +bool PAKBridge::extractResources(const HECL::ProjectPath& dirOut) +{ + for (const std::pair& item : m_pak.m_idMap) + { + ResExtractor extractor = LookupExtractor(*item.second); + if (extractor.func) + { + PAKEntryReadStream strgIn = item.second->beginReadStream(m_node); + HECL::ProjectPath resPath(dirOut, m_pak.bestEntryName(*item.second) + extractor.fileExt); + extractor.func(strgIn, resPath); + } + } + return true; +} + } } diff --git a/DataSpec/DNAMP3/DNAMP3.hpp b/DataSpec/DNAMP3/DNAMP3.hpp index 4561d4832..3f008970b 100644 --- a/DataSpec/DNAMP3/DNAMP3.hpp +++ b/DataSpec/DNAMP3/DNAMP3.hpp @@ -2,6 +2,7 @@ #define __DNAMP3_HPP__ #include "../DNACommon/DNACommon.hpp" +#include "PAK.hpp" namespace Retro { @@ -10,6 +11,22 @@ namespace DNAMP3 extern LogVisor::LogModule Log; +/* MP3-specific, one-shot PAK traversal/extraction class */ +class PAKBridge +{ + HECL::Database::Project& m_project; + const NOD::DiscBase::IPartition::Node& m_node; + PAK m_pak; + + static ResExtractor LookupExtractor(const PAK::Entry& entry); + +public: + PAKBridge(HECL::Database::Project& project, const NOD::DiscBase::IPartition::Node& node); + const std::string& getName() const {return m_node.getName();} + std::string getLevelString() const; + bool extractResources(const HECL::ProjectPath& dirOut); +}; + } } diff --git a/DataSpec/DNAMP3/PAK.hpp b/DataSpec/DNAMP3/PAK.hpp index f27251dca..c70227169 100644 --- a/DataSpec/DNAMP3/PAK.hpp +++ b/DataSpec/DNAMP3/PAK.hpp @@ -72,6 +72,17 @@ struct PAK : BigDNA return result->second; return nullptr; } + + inline std::string bestEntryName(const Entry& entry) const + { + /* Prefer named entries first */ + for (const NameEntry& nentry : m_nameEntries) + if (nentry.id == entry.id) + return nentry.name; + + /* Otherwise return ID format string */ + return entry.id.toString(); + } }; } diff --git a/DataSpec/SpecBase.cpp b/DataSpec/SpecBase.cpp index 6c4316308..06c1eed5a 100644 --- a/DataSpec/SpecBase.cpp +++ b/DataSpec/SpecBase.cpp @@ -3,7 +3,8 @@ namespace Retro { -bool SpecBase::canExtract(const ExtractPassInfo& info, std::vector& reps) +bool SpecBase::canExtract(HECL::Database::Project& project, + const ExtractPassInfo& info, std::vector& reps) { bool isWii; m_disc = NOD::OpenDiscFromImage(info.srcpath.c_str(), isWii); @@ -38,14 +39,14 @@ bool SpecBase::canExtract(const ExtractPassInfo& info, std::vector& reps); - void doExtract(const HECL::Database::Project& project, const ExtractPassInfo& info); + bool canExtract(HECL::Database::Project& project, const ExtractPassInfo& info, + std::vector& reps); + void doExtract(HECL::Database::Project& project, const ExtractPassInfo& info); bool canCook(const HECL::Database::Project& project, const CookTaskInfo& info); void doCook(const HECL::Database::Project& project, const CookTaskInfo& info); @@ -23,15 +24,17 @@ struct SpecBase : HECL::Database::IDataSpec void doPackage(const HECL::Database::Project& project, const PackagePassInfo& info); virtual bool checkStandaloneID(const char* id) const=0; - virtual bool checkFromStandaloneDisc(NOD::DiscBase& disc, + virtual bool checkFromStandaloneDisc(HECL::Database::Project& project, + NOD::DiscBase& disc, const HECL::SystemString& regstr, const std::vector& args, std::vector& reps)=0; - virtual bool checkFromTrilogyDisc(NOD::DiscBase& disc, + virtual bool checkFromTrilogyDisc(HECL::Database::Project& project, + NOD::DiscBase& disc, const HECL::SystemString& regstr, const std::vector& args, std::vector& reps)=0; - virtual bool extractFromDisc(NOD::DiscBase& disc, const HECL::Database::Project& project)=0; + virtual bool extractFromDisc(HECL::Database::Project& project, NOD::DiscBase& disc)=0; virtual bool checkFromProject(HECL::Database::Project& proj)=0; virtual bool readFromProject(HECL::Database::Project& proj)=0; diff --git a/DataSpec/SpecMP1.cpp b/DataSpec/SpecMP1.cpp index 3c3bc4d90..085cbfc8d 100644 --- a/DataSpec/SpecMP1.cpp +++ b/DataSpec/SpecMP1.cpp @@ -1,11 +1,8 @@ #include #include -#define NOD_ATHENA 1 #include "SpecBase.hpp" -#include "DNAMP1/PAK.hpp" -#include "DNAMP1/MLVL.hpp" -#include "DNAMP1/STRG.hpp" +#include "DNAMP1/DNAMP1.hpp" namespace Retro { @@ -21,16 +18,11 @@ struct SpecMP1 : SpecBase return false; } - struct DiscPAK - { - const NOD::DiscBase::IPartition::Node& node; - DNAMP1::PAK pak; - DiscPAK(const NOD::DiscBase::IPartition::Node& n) : node(n) {} - }; - std::vector m_paks; - std::map m_orderedPaks; + std::vector m_paks; + std::map m_orderedPaks; - void buildPaks(NOD::DiscBase::IPartition::Node& root, + void buildPaks(HECL::Database::Project& project, + NOD::DiscBase::IPartition::Node& root, const std::vector& args, ExtractReport& rep) { @@ -83,51 +75,29 @@ struct SpecMP1 : SpecBase } if (good) - { - m_paks.emplace_back(child); - NOD::AthenaPartReadStream rs(child.beginReadStream()); - m_paks.back().pak.read(rs); - } + m_paks.emplace_back(project, child); + } } } /* Sort PAKs alphabetically */ m_orderedPaks.clear(); - for (DiscPAK& dpak : m_paks) - m_orderedPaks[dpak.node.getName()] = &dpak; + for (DNAMP1::PAKBridge& dpak : m_paks) + m_orderedPaks[dpak.getName()] = &dpak; /* Assemble extract report */ - for (const std::pair& item : m_orderedPaks) + for (const std::pair& item : m_orderedPaks) { rep.childOpts.emplace_back(); ExtractReport& childRep = rep.childOpts.back(); childRep.name = item.first; - - DNAMP1::PAK& pak = item.second->pak; - for (DNAMP1::PAK::Entry& entry : pak.m_entries) - { - if (entry.type == MLVL) - { - PAKEntryReadStream rs = entry.beginReadStream(item.second->node); - DNAMP1::MLVL mlvl; - mlvl.read(rs); - const DNAMP1::PAK::Entry* nameEnt = pak.lookupEntry(mlvl.worldNameId); - if (nameEnt) - { - PAKEntryReadStream rs = nameEnt->beginReadStream(item.second->node); - DNAMP1::STRG mlvlName; - mlvlName.read(rs); - if (childRep.desc.size()) - childRep.desc += _S(", "); - childRep.desc += mlvlName.getSystemString(ENGL, 0); - } - } - } + childRep.desc = item.second->getLevelString(); } } - bool checkFromStandaloneDisc(NOD::DiscBase& disc, + bool checkFromStandaloneDisc(HECL::Database::Project& project, + NOD::DiscBase& disc, const HECL::SystemString& regstr, const std::vector& args, std::vector& reps) @@ -150,12 +120,13 @@ struct SpecMP1 : SpecBase /* Iterate PAKs and build level options */ NOD::DiscBase::IPartition::Node& root = partition->getFSTRoot(); - buildPaks(root, args, rep); + buildPaks(project, root, args, rep); return true; } - bool checkFromTrilogyDisc(NOD::DiscBase& disc, + bool checkFromTrilogyDisc(HECL::Database::Project& project, + NOD::DiscBase& disc, const HECL::SystemString& regstr, const std::vector& args, std::vector& reps) @@ -204,37 +175,23 @@ struct SpecMP1 : SpecBase NOD::DiscBase::IPartition::Node::DirectoryIterator mp1It = root.find("MP1"); if (mp1It == root.end()) return false; - buildPaks(*mp1It, mp1args, rep); + buildPaks(project, *mp1It, mp1args, rep); return true; } - bool extractFromDisc(NOD::DiscBase& disc, const HECL::Database::Project& project) + bool extractFromDisc(HECL::Database::Project& project, NOD::DiscBase& disc) { HECL::ProjectPath mp1Path(project.getProjectRootPath(), "MP1"); - for (const DiscPAK& pak : m_paks) + for (DNAMP1::PAKBridge& pak : m_paks) { - const std::string& name = pak.node.getName(); + const std::string& name = pak.getName(); std::string::const_iterator extit = name.end() - 4; std::string baseName(name.begin(), extit); HECL::ProjectPath pakPath(mp1Path, baseName); - - for (const std::pair& item : pak.pak.m_idMap) - { - if (item.second->type == STRG) - { - DNAMP1::STRG strg; - PAKEntryReadStream strgIn = item.second->beginReadStream(pak.node); - strg.read(strgIn); - - HECL::SystemChar strgPath[1024]; - HECL::SNPrintf(strgPath, 1024, _S("%s/%08X.strg"), pakPath.getAbsolutePath().c_str(), item.second->id.toUint32()); - std::ofstream strgOut(strgPath); - strg.writeAngelScript(strgOut); - } - } + pak.extractResources(pakPath); } return true; diff --git a/DataSpec/SpecMP2.cpp b/DataSpec/SpecMP2.cpp index 23c053d3c..85588a6d1 100644 --- a/DataSpec/SpecMP2.cpp +++ b/DataSpec/SpecMP2.cpp @@ -1,10 +1,7 @@ #include -#define NOD_ATHENA 1 #include "SpecBase.hpp" -#include "DNAMP1/PAK.hpp" -#include "DNAMP2/MLVL.hpp" -#include "DNAMP2/STRG.hpp" +#include "DNAMP2/DNAMP2.hpp" namespace Retro { @@ -20,16 +17,11 @@ struct SpecMP2 : SpecBase return false; } - struct DiscPAK - { - const NOD::DiscBase::IPartition::Node& node; - DNAMP1::PAK pak; - DiscPAK(const NOD::DiscBase::IPartition::Node& n) : node(n) {} - }; - std::vector m_paks; - std::map m_orderedPaks; + std::vector m_paks; + std::map m_orderedPaks; - void buildPaks(NOD::DiscBase::IPartition::Node& root, + void buildPaks(HECL::Database::Project& project, + NOD::DiscBase::IPartition::Node& root, const std::vector& args, ExtractReport& rep) { @@ -82,51 +74,28 @@ struct SpecMP2 : SpecBase } if (good) - { - m_paks.emplace_back(child); - NOD::AthenaPartReadStream rs(child.beginReadStream()); - m_paks.back().pak.read(rs); - } + m_paks.emplace_back(project, child); } } } /* Sort PAKs alphabetically */ m_orderedPaks.clear(); - for (DiscPAK& dpak : m_paks) - m_orderedPaks[dpak.node.getName()] = &dpak; + for (DNAMP2::PAKBridge& dpak : m_paks) + m_orderedPaks[dpak.getName()] = &dpak; /* Assemble extract report */ - for (const std::pair& item : m_orderedPaks) + for (const std::pair& item : m_orderedPaks) { rep.childOpts.emplace_back(); ExtractReport& childRep = rep.childOpts.back(); childRep.name = item.first; - - DNAMP1::PAK& pak = item.second->pak; - for (DNAMP1::PAK::Entry& entry : pak.m_entries) - { - if (entry.type == MLVL) - { - PAKEntryReadStream rs = entry.beginReadStream(item.second->node); - DNAMP2::MLVL mlvl; - mlvl.read(rs); - const DNAMP1::PAK::Entry* nameEnt = pak.lookupEntry(mlvl.worldNameId); - if (nameEnt) - { - PAKEntryReadStream rs = nameEnt->beginReadStream(item.second->node); - DNAMP2::STRG mlvlName; - mlvlName.read(rs); - if (childRep.desc.size()) - childRep.desc += _S(", "); - childRep.desc += mlvlName.getSystemString(ENGL, 0); - } - } - } + childRep.desc = item.second->getLevelString(); } } - bool checkFromStandaloneDisc(NOD::DiscBase& disc, + bool checkFromStandaloneDisc(HECL::Database::Project& project, + NOD::DiscBase& disc, const HECL::SystemString& regstr, const std::vector& args, std::vector& reps) @@ -149,12 +118,13 @@ struct SpecMP2 : SpecBase /* Iterate PAKs and build level options */ NOD::DiscBase::IPartition::Node& root = partition->getFSTRoot(); - buildPaks(root, args, rep); + buildPaks(project, root, args, rep); return true; } - bool checkFromTrilogyDisc(NOD::DiscBase& disc, + bool checkFromTrilogyDisc(HECL::Database::Project& project, + NOD::DiscBase& disc, const HECL::SystemString& regstr, const std::vector& args, std::vector& reps) @@ -203,12 +173,12 @@ struct SpecMP2 : SpecBase NOD::DiscBase::IPartition::Node::DirectoryIterator mp2It = root.find("MP2"); if (mp2It == root.end()) return false; - buildPaks(*mp2It, mp2args, rep); + buildPaks(project, *mp2It, mp2args, rep); return true; } - bool extractFromDisc(NOD::DiscBase& disc, const HECL::Database::Project& project) + bool extractFromDisc(HECL::Database::Project& project, NOD::DiscBase& disc) { } diff --git a/DataSpec/SpecMP3.cpp b/DataSpec/SpecMP3.cpp index 923895c29..74896531a 100644 --- a/DataSpec/SpecMP3.cpp +++ b/DataSpec/SpecMP3.cpp @@ -1,11 +1,8 @@ #include #include -#define NOD_ATHENA 1 #include "SpecBase.hpp" -#include "DNAMP3/PAK.hpp" -#include "DNAMP3/MLVL.hpp" -#include "DNAMP3/STRG.hpp" +#include "DNAMP3/DNAMP3.hpp" namespace Retro { @@ -21,16 +18,11 @@ struct SpecMP3 : SpecBase return false; } - struct DiscPAK - { - const NOD::DiscBase::IPartition::Node& node; - DNAMP3::PAK pak; - DiscPAK(const NOD::DiscBase::IPartition::Node& n) : node(n) {} - }; - std::vector m_paks; - std::map m_orderedPaks; + std::vector m_paks; + std::map m_orderedPaks; - void buildPaks(NOD::DiscBase::IPartition::Node& root, + void buildPaks(HECL::Database::Project& project, + NOD::DiscBase::IPartition::Node& root, const std::vector& args, ExtractReport& rep) { @@ -83,22 +75,18 @@ struct SpecMP3 : SpecBase } if (good) - { - m_paks.emplace_back(child); - NOD::AthenaPartReadStream rs(child.beginReadStream()); - m_paks.back().pak.read(rs); - } + m_paks.emplace_back(project, child); } } } /* Sort PAKs alphabetically */ m_orderedPaks.clear(); - for (DiscPAK& dpak : m_paks) - m_orderedPaks[dpak.node.getName()] = &dpak; + for (DNAMP3::PAKBridge& dpak : m_paks) + m_orderedPaks[dpak.getName()] = &dpak; /* Assemble extract report */ - for (const std::pair& item : m_orderedPaks) + for (const std::pair& item : m_orderedPaks) { rep.childOpts.emplace_back(); ExtractReport& childRep = rep.childOpts.back(); @@ -111,37 +99,12 @@ struct SpecMP3 : SpecBase childRep.desc = _S("Phaaze"); continue; } - - std::set worldNames; - DNAMP3::PAK& pak = item.second->pak; - for (DNAMP3::PAK::Entry& entry : pak.m_entries) - { - if (entry.type == MLVL) - { - PAKEntryReadStream rs = entry.beginReadStream(item.second->node); - DNAMP3::MLVL mlvl; - mlvl.read(rs); - const DNAMP3::PAK::Entry* nameEnt = pak.lookupEntry(mlvl.worldNameId); - if (nameEnt) - { - PAKEntryReadStream rs = nameEnt->beginReadStream(item.second->node); - DNAMP3::STRG mlvlName; - mlvlName.read(rs); - worldNames.emplace(mlvlName.getSystemString(ENGL, 0)); - } - } - } - - for (const std::string& name : worldNames) - { - if (childRep.desc.size()) - childRep.desc += _S(", "); - childRep.desc += name; - } + childRep.desc = item.second->getLevelString(); } } - bool checkFromStandaloneDisc(NOD::DiscBase& disc, + bool checkFromStandaloneDisc(HECL::Database::Project& project, + NOD::DiscBase& disc, const HECL::SystemString& regstr, const std::vector& args, std::vector& reps) @@ -164,12 +127,13 @@ struct SpecMP3 : SpecBase /* Iterate PAKs and build level options */ NOD::DiscBase::IPartition::Node& root = partition->getFSTRoot(); - buildPaks(root, args, rep); + buildPaks(project, root, args, rep); return true; } - bool checkFromTrilogyDisc(NOD::DiscBase& disc, + bool checkFromTrilogyDisc(HECL::Database::Project& project, + NOD::DiscBase& disc, const HECL::SystemString& regstr, const std::vector& args, std::vector& reps) @@ -218,12 +182,12 @@ struct SpecMP3 : SpecBase NOD::DiscBase::IPartition::Node::DirectoryIterator mp3It = root.find("MP3"); if (mp3It == root.end()) return false; - buildPaks(*mp3It, mp3args, rep); + buildPaks(project, *mp3It, mp3args, rep); return true; } - bool extractFromDisc(NOD::DiscBase& disc, const HECL::Database::Project& project) + bool extractFromDisc(HECL::Database::Project& project, NOD::DiscBase& disc) { } diff --git a/NODLib b/NODLib index cbea8fe76..bcf67ca8e 160000 --- a/NODLib +++ b/NODLib @@ -1 +1 @@ -Subproject commit cbea8fe76471e19b7b98190b56932a2c369fefd8 +Subproject commit bcf67ca8eb94acbf3834fe01de033a4382626a13