mirror of https://github.com/AxioDL/metaforce.git
added extract tool
This commit is contained in:
parent
8de863fcba
commit
4b13e9da9d
|
@ -0,0 +1,50 @@
|
||||||
|
#ifndef CTOOL_EXTRACT
|
||||||
|
#define CTOOL_EXTRACT
|
||||||
|
|
||||||
|
#include "ToolBase.hpp"
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
class ToolExtract final : public ToolBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ToolExtract(const ToolPassInfo& info)
|
||||||
|
: ToolBase(info)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Help(HelpOutput& help)
|
||||||
|
{
|
||||||
|
help.secHead(_S("NAME"));
|
||||||
|
help.beginWrap();
|
||||||
|
help.wrap(_S("hecl-extract - Extract objects from supported package/image formats\n"));
|
||||||
|
help.endWrap();
|
||||||
|
|
||||||
|
help.secHead(_S("SYNOPSIS"));
|
||||||
|
help.beginWrap();
|
||||||
|
help.wrap(_S("hecl extract <packagefile>[/<subnode>...]\n"));
|
||||||
|
help.endWrap();
|
||||||
|
|
||||||
|
help.secHead(_S("DESCRIPTION"));
|
||||||
|
help.beginWrap();
|
||||||
|
help.wrap(_S("This command recursively extracts all or part of a dataspec-supported "
|
||||||
|
"package format.\n\n"));
|
||||||
|
help.endWrap();
|
||||||
|
|
||||||
|
help.secHead(_S("OPTIONS"));
|
||||||
|
help.optionHead(_S("<packagefile>[/<subnode>...]"), _S("input file"));
|
||||||
|
help.beginWrap();
|
||||||
|
help.wrap(_S("Specifies the package file or disc image to source data from. "
|
||||||
|
"An optional subnode specifies a named hierarchical-node specific "
|
||||||
|
"to the game architecture (levels/areas)."));
|
||||||
|
help.endWrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
HECL::SystemString toolName() const {return _S("extract");}
|
||||||
|
|
||||||
|
int run()
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CTOOL_EXTRACT
|
|
@ -60,6 +60,8 @@ public:
|
||||||
helpFunc = ToolInit::Help;
|
helpFunc = ToolInit::Help;
|
||||||
else if (toolName == _S("spec"))
|
else if (toolName == _S("spec"))
|
||||||
helpFunc = ToolSpec::Help;
|
helpFunc = ToolSpec::Help;
|
||||||
|
else if (toolName == _S("extract"))
|
||||||
|
helpFunc = ToolExtract::Help;
|
||||||
else if (toolName == _S("add"))
|
else if (toolName == _S("add"))
|
||||||
helpFunc = ToolAdd::Help;
|
helpFunc = ToolAdd::Help;
|
||||||
else if (toolName == _S("remove") || toolName == _S("rm"))
|
else if (toolName == _S("remove") || toolName == _S("rm"))
|
||||||
|
|
|
@ -45,7 +45,8 @@ public:
|
||||||
return -1;
|
return -1;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
HECL::Database::Project(HECL::ProjectRootPath(*m_dir));
|
HECL::Database::Project proj((HECL::ProjectRootPath(*m_dir)));
|
||||||
|
proj.enableDataSpecs({_S("hecl-little")});
|
||||||
}
|
}
|
||||||
catch (HECL::Exception& e)
|
catch (HECL::Exception& e)
|
||||||
{
|
{
|
||||||
|
|
|
@ -23,6 +23,7 @@ SOURCES += \
|
||||||
HEADERS += \
|
HEADERS += \
|
||||||
ToolBase.hpp \
|
ToolBase.hpp \
|
||||||
ToolPackage.hpp \
|
ToolPackage.hpp \
|
||||||
|
ToolExtract.hpp \
|
||||||
ToolInit.hpp \
|
ToolInit.hpp \
|
||||||
ToolHelp.hpp \
|
ToolHelp.hpp \
|
||||||
ToolGroup.hpp \
|
ToolGroup.hpp \
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
#include "ToolBase.hpp"
|
#include "ToolBase.hpp"
|
||||||
#include "ToolInit.hpp"
|
#include "ToolInit.hpp"
|
||||||
#include "ToolSpec.hpp"
|
#include "ToolSpec.hpp"
|
||||||
|
#include "ToolExtract.hpp"
|
||||||
#include "ToolAdd.hpp"
|
#include "ToolAdd.hpp"
|
||||||
#include "ToolRemove.hpp"
|
#include "ToolRemove.hpp"
|
||||||
#include "ToolGroup.hpp"
|
#include "ToolGroup.hpp"
|
||||||
|
@ -180,6 +181,8 @@ int main(int argc, const char** argv)
|
||||||
tool.reset(new ToolInit(info));
|
tool.reset(new ToolInit(info));
|
||||||
else if (toolName == _S("spec"))
|
else if (toolName == _S("spec"))
|
||||||
tool.reset(new ToolSpec(info));
|
tool.reset(new ToolSpec(info));
|
||||||
|
else if (toolName == _S("extract"))
|
||||||
|
tool.reset(new ToolExtract(info));
|
||||||
else if (toolName == _S("add"))
|
else if (toolName == _S("add"))
|
||||||
tool.reset(new ToolAdd(info));
|
tool.reset(new ToolAdd(info));
|
||||||
else if (toolName == _S("remove") || toolName == _S("rm"))
|
else if (toolName == _S("remove") || toolName == _S("rm"))
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
_hecl ()
|
_hecl ()
|
||||||
{
|
{
|
||||||
local word=${COMP_WORDS[COMP_CWORD]}
|
local word=${COMP_WORDS[COMP_CWORD]}
|
||||||
local filecmds=(init spec add remove group cook clean package)
|
local filecmds=(init spec extract add remove group cook clean package)
|
||||||
|
|
||||||
if [ $COMP_CWORD == 1 ]
|
if [ $COMP_CWORD == 1 ]
|
||||||
then
|
then
|
||||||
|
@ -12,7 +12,7 @@ _hecl ()
|
||||||
elif [ $COMP_CWORD == 2 ]
|
elif [ $COMP_CWORD == 2 ]
|
||||||
then
|
then
|
||||||
case ${COMP_WORDS[1]} in
|
case ${COMP_WORDS[1]} in
|
||||||
init|add|remove|group|cook|clean|package)
|
init|extract|add|remove|group|cook|clean|package)
|
||||||
COMPREPLY=($(compgen -f -- "${word}"))
|
COMPREPLY=($(compgen -f -- "${word}"))
|
||||||
;;
|
;;
|
||||||
spec)
|
spec)
|
||||||
|
|
|
@ -262,6 +262,7 @@ public:
|
||||||
Hash(int64_t hashin)
|
Hash(int64_t hashin)
|
||||||
: hash(hashin) {}
|
: hash(hashin) {}
|
||||||
Hash(const Hash& other) {hash = other.hash;}
|
Hash(const Hash& other) {hash = other.hash;}
|
||||||
|
inline size_t val() const {return hash;}
|
||||||
inline Hash& operator=(const Hash& other) {hash = other.hash; return *this;}
|
inline Hash& operator=(const Hash& other) {hash = other.hash; return *this;}
|
||||||
inline bool operator==(const Hash& other) const {return hash == other.hash;}
|
inline bool operator==(const Hash& other) const {return hash == other.hash;}
|
||||||
inline bool operator!=(const Hash& other) const {return hash != other.hash;}
|
inline bool operator!=(const Hash& other) const {return hash != other.hash;}
|
||||||
|
@ -309,7 +310,7 @@ class ProjectPath
|
||||||
protected:
|
protected:
|
||||||
SystemString m_absPath;
|
SystemString m_absPath;
|
||||||
SystemString m_relPath;
|
SystemString m_relPath;
|
||||||
size_t m_hash = 0;
|
Hash m_hash = 0;
|
||||||
#if HECL_UCS2
|
#if HECL_UCS2
|
||||||
std::string m_utf8AbsPath;
|
std::string m_utf8AbsPath;
|
||||||
const char* m_utf8RelPath;
|
const char* m_utf8RelPath;
|
||||||
|
@ -404,10 +405,10 @@ public:
|
||||||
void getGlobResults(std::vector<SystemString>& outPaths) const;
|
void getGlobResults(std::vector<SystemString>& outPaths) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief C++11 compatible runtime hash (NOT USED IN PACKAGES!!)
|
* @brief HECL-specific blowfish hash
|
||||||
* @return System-specific hash value
|
* @return unique hash value
|
||||||
*/
|
*/
|
||||||
inline size_t hash() const {return m_hash;}
|
inline size_t hash() const {return m_hash.val();}
|
||||||
inline bool operator==(const ProjectPath& other) const {return m_hash == other.m_hash;}
|
inline bool operator==(const ProjectPath& other) const {return m_hash == other.m_hash;}
|
||||||
inline bool operator!=(const ProjectPath& other) const {return m_hash != other.m_hash;}
|
inline bool operator!=(const ProjectPath& other) const {return m_hash != other.m_hash;}
|
||||||
|
|
||||||
|
@ -517,7 +518,7 @@ namespace std
|
||||||
{
|
{
|
||||||
template <> struct hash<HECL::ProjectPath>
|
template <> struct hash<HECL::ProjectPath>
|
||||||
{
|
{
|
||||||
size_t operator()(const HECL::ProjectPath& val) const noexcept
|
inline size_t operator()(const HECL::ProjectPath& val) const noexcept
|
||||||
{return val.hash();}
|
{return val.hash();}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
#include <unordered_set>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
@ -21,6 +22,7 @@ namespace HECL
|
||||||
{
|
{
|
||||||
namespace Database
|
namespace Database
|
||||||
{
|
{
|
||||||
|
class Project;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Nodegraph class for gathering dependency-resolved objects for packaging
|
* @brief Nodegraph class for gathering dependency-resolved objects for packaging
|
||||||
|
@ -35,7 +37,8 @@ public:
|
||||||
NODE_DATA,
|
NODE_DATA,
|
||||||
NODE_GROUP
|
NODE_GROUP
|
||||||
} type;
|
} type;
|
||||||
SystemString path;
|
ProjectPath path;
|
||||||
|
ProjectPath cookedPath;
|
||||||
class ObjectBase* projectObj;
|
class ObjectBase* projectObj;
|
||||||
Node* sub;
|
Node* sub;
|
||||||
Node* next;
|
Node* next;
|
||||||
|
@ -56,21 +59,62 @@ public:
|
||||||
class IDataSpec
|
class IDataSpec
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
/**
|
||||||
|
* @brief Extract Pass Info
|
||||||
|
*
|
||||||
|
* An extract pass iterates through a source package or image and
|
||||||
|
* reverses the cooking process by emitting editable resources
|
||||||
|
*/
|
||||||
struct ExtractPassInfo
|
struct ExtractPassInfo
|
||||||
{
|
{
|
||||||
SystemString srcpath;
|
SystemString srcpath;
|
||||||
ProjectPath subpath;
|
ProjectPath subpath;
|
||||||
|
bool cookedonly;
|
||||||
};
|
};
|
||||||
virtual bool canExtract(const ExtractPassInfo& info) {(void)info;return false;}
|
virtual bool canExtract(const Project& project, const ExtractPassInfo& info,
|
||||||
virtual void doExtract(const ExtractPassInfo& info) {(void)info;}
|
SystemString& reasonNo)
|
||||||
|
{(void)project;(void)info;reasonNo=_S("not implemented");return false;}
|
||||||
|
virtual void doExtract(const Project& project, const ExtractPassInfo& info)
|
||||||
|
{(void)project;(void)info;}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Cook Task Info
|
||||||
|
*
|
||||||
|
* A cook task takes a single tracked path and generates the
|
||||||
|
* corresponding cooked version
|
||||||
|
*/
|
||||||
|
struct CookTaskInfo
|
||||||
|
{
|
||||||
|
ProjectPath path;
|
||||||
|
ProjectPath cookedPath;
|
||||||
|
};
|
||||||
|
virtual bool canCook(const Project& project, const CookTaskInfo& info,
|
||||||
|
SystemString& reasonNo)
|
||||||
|
{(void)project;(void)info;reasonNo=_S("not implemented");return false;}
|
||||||
|
virtual void doCook(const Project& project, const CookTaskInfo& info)
|
||||||
|
{(void)project;(void)info;}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Package Pass Info
|
||||||
|
*
|
||||||
|
* A package pass performs last-minute queries of source resources,
|
||||||
|
* gathers dependencies and packages cooked data together in the
|
||||||
|
* most efficient form for the dataspec
|
||||||
|
*/
|
||||||
struct PackagePassInfo
|
struct PackagePassInfo
|
||||||
{
|
{
|
||||||
PackageDepsgraph& depsgraph;
|
const PackageDepsgraph& depsgraph;
|
||||||
ProjectPath subpath;
|
ProjectPath subpath;
|
||||||
|
ProjectPath outpath;
|
||||||
};
|
};
|
||||||
virtual bool canPackage(const PackagePassInfo& info) {(void)info;return false;}
|
virtual bool canPackage(const Project& project, const PackagePassInfo& info,
|
||||||
virtual void doPackage(const PackagePassInfo& info) {(void)info;}
|
SystemString& reasonNo)
|
||||||
|
{(void)project;(void)info;reasonNo=_S("not implemented");return false;}
|
||||||
|
virtual void gatherDependencies(const Project& project, const PackagePassInfo& info,
|
||||||
|
std::unordered_set<ProjectPath>& implicitsOut)
|
||||||
|
{(void)project;(void)info;(void)implicitsOut;}
|
||||||
|
virtual void doPackage(const Project& project, const PackagePassInfo& info)
|
||||||
|
{(void)project;(void)info;}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -189,7 +233,8 @@ public:
|
||||||
std::list<std::string> m_lines;
|
std::list<std::string> m_lines;
|
||||||
FILE* m_lockedFile = NULL;
|
FILE* m_lockedFile = NULL;
|
||||||
public:
|
public:
|
||||||
ConfigFile(const Project& project, const SystemString& name);
|
ConfigFile(const Project& project, const SystemString& name,
|
||||||
|
const SystemString& subdir=_S("/.hecl/"));
|
||||||
std::list<std::string>& lockAndRead();
|
std::list<std::string>& lockAndRead();
|
||||||
void addLine(const std::string& line);
|
void addLine(const std::string& line);
|
||||||
void removeLine(const std::string& refLine);
|
void removeLine(const std::string& refLine);
|
||||||
|
|
|
@ -51,9 +51,7 @@ ProjectPath::ProjectPath(const ProjectRootPath& rootPath, const SystemString& pa
|
||||||
if (*beginit == _S('/'))
|
if (*beginit == _S('/'))
|
||||||
++beginit;
|
++beginit;
|
||||||
m_relPath = SystemString(beginit, m_absPath.end());
|
m_relPath = SystemString(beginit, m_absPath.end());
|
||||||
|
m_hash = Hash(m_relPath);
|
||||||
std::hash<std::string> hash_fn;
|
|
||||||
m_hash = hash_fn(std::string(m_relPath));
|
|
||||||
|
|
||||||
#if HECL_UCS2
|
#if HECL_UCS2
|
||||||
m_utf8AbsPath = WideToUTF8(m_absPath);
|
m_utf8AbsPath = WideToUTF8(m_absPath);
|
||||||
|
@ -205,7 +203,7 @@ std::unique_ptr<ProjectRootPath> SearchForProject(const SystemString& path)
|
||||||
while (begin != end)
|
while (begin != end)
|
||||||
{
|
{
|
||||||
SystemString testPath(begin, end);
|
SystemString testPath(begin, end);
|
||||||
SystemString testIndexPath = testPath + _S("/.hecl/index");
|
SystemString testIndexPath = testPath + _S("/.hecl/beacon");
|
||||||
struct stat theStat;
|
struct stat theStat;
|
||||||
if (!HECL::Stat(testIndexPath.c_str(), &theStat))
|
if (!HECL::Stat(testIndexPath.c_str(), &theStat))
|
||||||
{
|
{
|
||||||
|
|
|
@ -40,9 +40,10 @@ static inline bool CheckNewLineAdvance(std::string::const_iterator& it)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Project::ConfigFile::ConfigFile(const Project& project, const SystemString& name)
|
Project::ConfigFile::ConfigFile(const Project& project, const SystemString& name,
|
||||||
|
const SystemString& subdir)
|
||||||
{
|
{
|
||||||
m_filepath = project.m_rootPath.getAbsolutePath() + _S("/.hecl/config/") + name;
|
m_filepath = project.m_rootPath.getAbsolutePath() + subdir + name;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::list<std::string>& Project::ConfigFile::lockAndRead()
|
std::list<std::string>& Project::ConfigFile::lockAndRead()
|
||||||
|
@ -184,7 +185,6 @@ Project::Project(const ProjectRootPath& rootPath)
|
||||||
/* Create project directory structure */
|
/* Create project directory structure */
|
||||||
HECL::MakeDir(m_rootPath.getAbsolutePath() + _S("/.hecl"));
|
HECL::MakeDir(m_rootPath.getAbsolutePath() + _S("/.hecl"));
|
||||||
HECL::MakeDir(m_rootPath.getAbsolutePath() + _S("/.hecl/cooked"));
|
HECL::MakeDir(m_rootPath.getAbsolutePath() + _S("/.hecl/cooked"));
|
||||||
HECL::MakeDir(m_rootPath.getAbsolutePath() + _S("/.hecl/config"));
|
|
||||||
|
|
||||||
/* Ensure beacon is valid or created */
|
/* Ensure beacon is valid or created */
|
||||||
FILE* bf = HECL::Fopen((m_rootPath.getAbsolutePath() + _S("/.hecl/beacon")).c_str(), _S("a+b"));
|
FILE* bf = HECL::Fopen((m_rootPath.getAbsolutePath() + _S("/.hecl/beacon")).c_str(), _S("a+b"));
|
||||||
|
|
Loading…
Reference in New Issue