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;
|
||||
else if (toolName == _S("spec"))
|
||||
helpFunc = ToolSpec::Help;
|
||||
else if (toolName == _S("extract"))
|
||||
helpFunc = ToolExtract::Help;
|
||||
else if (toolName == _S("add"))
|
||||
helpFunc = ToolAdd::Help;
|
||||
else if (toolName == _S("remove") || toolName == _S("rm"))
|
||||
|
|
|
@ -45,7 +45,8 @@ public:
|
|||
return -1;
|
||||
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)
|
||||
{
|
||||
|
|
|
@ -23,6 +23,7 @@ SOURCES += \
|
|||
HEADERS += \
|
||||
ToolBase.hpp \
|
||||
ToolPackage.hpp \
|
||||
ToolExtract.hpp \
|
||||
ToolInit.hpp \
|
||||
ToolHelp.hpp \
|
||||
ToolGroup.hpp \
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include "ToolBase.hpp"
|
||||
#include "ToolInit.hpp"
|
||||
#include "ToolSpec.hpp"
|
||||
#include "ToolExtract.hpp"
|
||||
#include "ToolAdd.hpp"
|
||||
#include "ToolRemove.hpp"
|
||||
#include "ToolGroup.hpp"
|
||||
|
@ -180,6 +181,8 @@ int main(int argc, const char** argv)
|
|||
tool.reset(new ToolInit(info));
|
||||
else if (toolName == _S("spec"))
|
||||
tool.reset(new ToolSpec(info));
|
||||
else if (toolName == _S("extract"))
|
||||
tool.reset(new ToolExtract(info));
|
||||
else if (toolName == _S("add"))
|
||||
tool.reset(new ToolAdd(info));
|
||||
else if (toolName == _S("remove") || toolName == _S("rm"))
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
_hecl ()
|
||||
{
|
||||
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 ]
|
||||
then
|
||||
|
@ -12,7 +12,7 @@ _hecl ()
|
|||
elif [ $COMP_CWORD == 2 ]
|
||||
then
|
||||
case ${COMP_WORDS[1]} in
|
||||
init|add|remove|group|cook|clean|package)
|
||||
init|extract|add|remove|group|cook|clean|package)
|
||||
COMPREPLY=($(compgen -f -- "${word}"))
|
||||
;;
|
||||
spec)
|
||||
|
|
|
@ -262,6 +262,7 @@ public:
|
|||
Hash(int64_t hashin)
|
||||
: hash(hashin) {}
|
||||
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 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:
|
||||
SystemString m_absPath;
|
||||
SystemString m_relPath;
|
||||
size_t m_hash = 0;
|
||||
Hash m_hash = 0;
|
||||
#if HECL_UCS2
|
||||
std::string m_utf8AbsPath;
|
||||
const char* m_utf8RelPath;
|
||||
|
@ -404,10 +405,10 @@ public:
|
|||
void getGlobResults(std::vector<SystemString>& outPaths) const;
|
||||
|
||||
/**
|
||||
* @brief C++11 compatible runtime hash (NOT USED IN PACKAGES!!)
|
||||
* @return System-specific hash value
|
||||
* @brief HECL-specific blowfish hash
|
||||
* @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;}
|
||||
|
||||
|
@ -517,7 +518,7 @@ namespace std
|
|||
{
|
||||
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();}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include <map>
|
||||
#include <list>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <memory>
|
||||
#include <atomic>
|
||||
#include <stdexcept>
|
||||
|
@ -21,6 +22,7 @@ namespace HECL
|
|||
{
|
||||
namespace Database
|
||||
{
|
||||
class Project;
|
||||
|
||||
/**
|
||||
* @brief Nodegraph class for gathering dependency-resolved objects for packaging
|
||||
|
@ -35,7 +37,8 @@ public:
|
|||
NODE_DATA,
|
||||
NODE_GROUP
|
||||
} type;
|
||||
SystemString path;
|
||||
ProjectPath path;
|
||||
ProjectPath cookedPath;
|
||||
class ObjectBase* projectObj;
|
||||
Node* sub;
|
||||
Node* next;
|
||||
|
@ -56,21 +59,62 @@ public:
|
|||
class IDataSpec
|
||||
{
|
||||
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
|
||||
{
|
||||
SystemString srcpath;
|
||||
ProjectPath subpath;
|
||||
bool cookedonly;
|
||||
};
|
||||
virtual bool canExtract(const ExtractPassInfo& info) {(void)info;return false;}
|
||||
virtual void doExtract(const ExtractPassInfo& info) {(void)info;}
|
||||
virtual bool canExtract(const Project& project, const ExtractPassInfo& 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
|
||||
{
|
||||
PackageDepsgraph& depsgraph;
|
||||
const PackageDepsgraph& depsgraph;
|
||||
ProjectPath subpath;
|
||||
ProjectPath outpath;
|
||||
};
|
||||
virtual bool canPackage(const PackagePassInfo& info) {(void)info;return false;}
|
||||
virtual void doPackage(const PackagePassInfo& info) {(void)info;}
|
||||
virtual bool canPackage(const Project& project, const PackagePassInfo& 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;
|
||||
FILE* m_lockedFile = NULL;
|
||||
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();
|
||||
void addLine(const std::string& line);
|
||||
void removeLine(const std::string& refLine);
|
||||
|
|
|
@ -51,9 +51,7 @@ ProjectPath::ProjectPath(const ProjectRootPath& rootPath, const SystemString& pa
|
|||
if (*beginit == _S('/'))
|
||||
++beginit;
|
||||
m_relPath = SystemString(beginit, m_absPath.end());
|
||||
|
||||
std::hash<std::string> hash_fn;
|
||||
m_hash = hash_fn(std::string(m_relPath));
|
||||
m_hash = Hash(m_relPath);
|
||||
|
||||
#if HECL_UCS2
|
||||
m_utf8AbsPath = WideToUTF8(m_absPath);
|
||||
|
@ -205,7 +203,7 @@ std::unique_ptr<ProjectRootPath> SearchForProject(const SystemString& path)
|
|||
while (begin != end)
|
||||
{
|
||||
SystemString testPath(begin, end);
|
||||
SystemString testIndexPath = testPath + _S("/.hecl/index");
|
||||
SystemString testIndexPath = testPath + _S("/.hecl/beacon");
|
||||
struct stat theStat;
|
||||
if (!HECL::Stat(testIndexPath.c_str(), &theStat))
|
||||
{
|
||||
|
|
|
@ -40,9 +40,10 @@ static inline bool CheckNewLineAdvance(std::string::const_iterator& it)
|
|||
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()
|
||||
|
@ -184,7 +185,6 @@ Project::Project(const ProjectRootPath& rootPath)
|
|||
/* Create project directory structure */
|
||||
HECL::MakeDir(m_rootPath.getAbsolutePath() + _S("/.hecl"));
|
||||
HECL::MakeDir(m_rootPath.getAbsolutePath() + _S("/.hecl/cooked"));
|
||||
HECL::MakeDir(m_rootPath.getAbsolutePath() + _S("/.hecl/config"));
|
||||
|
||||
/* Ensure beacon is valid or created */
|
||||
FILE* bf = HECL::Fopen((m_rootPath.getAbsolutePath() + _S("/.hecl/beacon")).c_str(), _S("a+b"));
|
||||
|
|
Loading…
Reference in New Issue