mirror of https://github.com/AxioDL/metaforce.git
re-balancing of DataSpec/DNA systems
This commit is contained in:
parent
94a6707dd3
commit
94d84d8991
|
@ -3,6 +3,7 @@
|
|||
|
||||
#include <Athena/DNA.hpp>
|
||||
#include "HECL/HECL.hpp"
|
||||
#include "HECL/Database.hpp"
|
||||
|
||||
namespace Retro
|
||||
{
|
||||
|
@ -178,6 +179,16 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
/* Resource extractor type */
|
||||
typedef struct
|
||||
{
|
||||
std::function<bool(PAKEntryReadStream&, const HECL::ProjectPath&)> func;
|
||||
const char* fileExt;
|
||||
} ResExtractor;
|
||||
|
||||
/* Resource cooker function */
|
||||
typedef std::function<bool(const HECL::ProjectPath&, const HECL::ProjectPath&)> ResCooker;
|
||||
|
||||
/* Language-identifiers */
|
||||
extern const HECL::FourCC ENGL;
|
||||
extern const HECL::FourCC FREN;
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include <angelscript.h>
|
||||
#include <HECL/HECL.hpp>
|
||||
#include <HECL/Database.hpp>
|
||||
#include <Athena/FileWriter.hpp>
|
||||
#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 <class SUBCLS>
|
||||
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 <class SUBCLS>
|
||||
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<ISTRG> LoadSTRG(Athena::io::IStreamReader& reader);
|
||||
|
||||
|
|
|
@ -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>, ".strg"};
|
||||
return {};
|
||||
}
|
||||
|
||||
bool PAKBridge::extractResources(const HECL::ProjectPath& dirOut)
|
||||
{
|
||||
for (const std::pair<UniqueID32, PAK::Entry*>& 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;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -57,6 +57,8 @@ struct STRG : ISTRG, BigDNA
|
|||
|
||||
bool readAngelScript(const AngelScript::asIScriptModule& in);
|
||||
void writeAngelScript(std::ofstream& out) const;
|
||||
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -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>, ".strg"};
|
||||
return {};
|
||||
}
|
||||
|
||||
bool PAKBridge::extractResources(const HECL::ProjectPath& dirOut)
|
||||
{
|
||||
for (const std::pair<UniqueID32, DNAMP1::PAK::Entry*>& 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;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,9 +1,76 @@
|
|||
#include <set>
|
||||
|
||||
#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<HECL::SystemString> 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>, ".strg"};
|
||||
return {};
|
||||
}
|
||||
|
||||
bool PAKBridge::extractResources(const HECL::ProjectPath& dirOut)
|
||||
{
|
||||
for (const std::pair<UniqueID64, PAK::Entry*>& 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;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -3,7 +3,8 @@
|
|||
namespace Retro
|
||||
{
|
||||
|
||||
bool SpecBase::canExtract(const ExtractPassInfo& info, std::vector<ExtractReport>& reps)
|
||||
bool SpecBase::canExtract(HECL::Database::Project& project,
|
||||
const ExtractPassInfo& info, std::vector<ExtractReport>& reps)
|
||||
{
|
||||
bool isWii;
|
||||
m_disc = NOD::OpenDiscFromImage(info.srcpath.c_str(), isWii);
|
||||
|
@ -38,14 +39,14 @@ bool SpecBase::canExtract(const ExtractPassInfo& info, std::vector<ExtractReport
|
|||
}
|
||||
|
||||
if (standalone)
|
||||
return checkFromStandaloneDisc(*m_disc.get(), *regstr, info.extractArgs, reps);
|
||||
return checkFromStandaloneDisc(project, *m_disc.get(), *regstr, info.extractArgs, reps);
|
||||
else
|
||||
return checkFromTrilogyDisc(*m_disc.get(), *regstr, info.extractArgs, reps);
|
||||
return checkFromTrilogyDisc(project, *m_disc.get(), *regstr, info.extractArgs, reps);
|
||||
}
|
||||
|
||||
void SpecBase::doExtract(const HECL::Database::Project& project, const ExtractPassInfo&)
|
||||
void SpecBase::doExtract(HECL::Database::Project& project, const ExtractPassInfo&)
|
||||
{
|
||||
extractFromDisc(*m_disc.get(), project);
|
||||
extractFromDisc(project, *m_disc.get());
|
||||
}
|
||||
|
||||
bool SpecBase::canCook(const HECL::Database::Project& project, const CookTaskInfo& info)
|
||||
|
|
|
@ -11,8 +11,9 @@ namespace Retro
|
|||
|
||||
struct SpecBase : HECL::Database::IDataSpec
|
||||
{
|
||||
bool canExtract(const ExtractPassInfo& info, std::vector<ExtractReport>& reps);
|
||||
void doExtract(const HECL::Database::Project& project, const ExtractPassInfo& info);
|
||||
bool canExtract(HECL::Database::Project& project, const ExtractPassInfo& info,
|
||||
std::vector<ExtractReport>& 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<HECL::SystemString>& args,
|
||||
std::vector<ExtractReport>& 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<HECL::SystemString>& args,
|
||||
std::vector<ExtractReport>& 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;
|
||||
|
|
|
@ -1,11 +1,8 @@
|
|||
#include <utility>
|
||||
#include <stdio.h>
|
||||
|
||||
#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<DiscPAK> m_paks;
|
||||
std::map<std::string, DiscPAK*, CaseInsensitiveCompare> m_orderedPaks;
|
||||
std::vector<DNAMP1::PAKBridge> m_paks;
|
||||
std::map<std::string, DNAMP1::PAKBridge*, CaseInsensitiveCompare> m_orderedPaks;
|
||||
|
||||
void buildPaks(NOD::DiscBase::IPartition::Node& root,
|
||||
void buildPaks(HECL::Database::Project& project,
|
||||
NOD::DiscBase::IPartition::Node& root,
|
||||
const std::vector<HECL::SystemString>& 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<std::string, DiscPAK*>& item : m_orderedPaks)
|
||||
for (const std::pair<std::string, DNAMP1::PAKBridge*>& 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<HECL::SystemString>& args,
|
||||
std::vector<ExtractReport>& 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<HECL::SystemString>& args,
|
||||
std::vector<ExtractReport>& 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<UniqueID32, DNAMP1::PAK::Entry*>& 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;
|
||||
|
|
|
@ -1,10 +1,7 @@
|
|||
#include <utility>
|
||||
|
||||
#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<DiscPAK> m_paks;
|
||||
std::map<std::string, DiscPAK*, CaseInsensitiveCompare> m_orderedPaks;
|
||||
std::vector<DNAMP2::PAKBridge> m_paks;
|
||||
std::map<std::string, DNAMP2::PAKBridge*, CaseInsensitiveCompare> m_orderedPaks;
|
||||
|
||||
void buildPaks(NOD::DiscBase::IPartition::Node& root,
|
||||
void buildPaks(HECL::Database::Project& project,
|
||||
NOD::DiscBase::IPartition::Node& root,
|
||||
const std::vector<HECL::SystemString>& 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<std::string, DiscPAK*>& item : m_orderedPaks)
|
||||
for (const std::pair<std::string, DNAMP2::PAKBridge*>& 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<HECL::SystemString>& args,
|
||||
std::vector<ExtractReport>& 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<HECL::SystemString>& args,
|
||||
std::vector<ExtractReport>& 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)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
@ -1,11 +1,8 @@
|
|||
#include <utility>
|
||||
#include <set>
|
||||
|
||||
#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<DiscPAK> m_paks;
|
||||
std::map<std::string, DiscPAK*, CaseInsensitiveCompare> m_orderedPaks;
|
||||
std::vector<DNAMP3::PAKBridge> m_paks;
|
||||
std::map<std::string, DNAMP3::PAKBridge*, CaseInsensitiveCompare> m_orderedPaks;
|
||||
|
||||
void buildPaks(NOD::DiscBase::IPartition::Node& root,
|
||||
void buildPaks(HECL::Database::Project& project,
|
||||
NOD::DiscBase::IPartition::Node& root,
|
||||
const std::vector<HECL::SystemString>& 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<std::string, DiscPAK*>& item : m_orderedPaks)
|
||||
for (const std::pair<std::string, DNAMP3::PAKBridge*>& 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<HECL::SystemString> 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<HECL::SystemString>& args,
|
||||
std::vector<ExtractReport>& 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<HECL::SystemString>& args,
|
||||
std::vector<ExtractReport>& 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)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
2
NODLib
2
NODLib
|
@ -1 +1 @@
|
|||
Subproject commit cbea8fe76471e19b7b98190b56932a2c369fefd8
|
||||
Subproject commit bcf67ca8eb94acbf3834fe01de033a4382626a13
|
Loading…
Reference in New Issue