2
0
mirror of https://github.com/AxioDL/metaforce.git synced 2025-12-08 21:47:42 +00:00

Initial work on GameCube package targeting

This commit is contained in:
Jack Andersen
2018-03-27 22:09:41 -10:00
parent 7c0bf75f7a
commit 7a2fbfc582
27 changed files with 1891 additions and 283 deletions

View File

@@ -39,12 +39,13 @@ static const hecl::SystemChar* MomErr[] =
};
constexpr uint32_t MomErrCount = std::extent<decltype(MomErr)>::value;
SpecBase::SpecBase(const hecl::Database::DataSpecEntry* specEntry, hecl::Database::Project& project, bool pc)
: hecl::Database::IDataSpec(specEntry), m_project(project), m_pc(pc),
m_masterShader(project.getProjectWorkingPath(), ".hecl/RetroMasterShader.blend")
{
AssetNameMap::InitAssetNameMap();
DataSpec::UniqueIDBridge::setThreadProject(m_project);
SpecBase::setThreadProject();
}
SpecBase::~SpecBase()
@@ -59,9 +60,75 @@ static const hecl::SystemString regP = _S("PAL");
void SpecBase::setThreadProject()
{
UniqueIDBridge::setThreadProject(m_project);
UniqueIDBridge::SetThreadProject(m_project);
}
template <typename IDType>
IDRestorer<IDType>::IDRestorer(const hecl::ProjectPath& yamlPath, const hecl::Database::Project& project)
{
using ValType = typename IDType::value_type;
if (!yamlPath.isFile())
return;
athena::io::YAMLDocReader r;
athena::io::FileReader fr(yamlPath.getAbsolutePath());
if (!fr.isOpen() || !r.parse(&fr))
return;
m_newToOrig.reserve(r.getRootNode()->m_mapChildren.size());
m_origToNew.reserve(r.getRootNode()->m_mapChildren.size());
for (const auto& node : r.getRootNode()->m_mapChildren)
{
char* end = const_cast<char*>(node.first.c_str());
ValType id = strtoull(end, &end, 16);
if (end != node.first.c_str() + sizeof(ValType) * 2)
continue;
hecl::ProjectPath path(project.getProjectWorkingPath(), node.second->m_scalarString.c_str());
m_newToOrig.push_back(std::make_pair(IDType{path.hash().valT<ValType>(), true}, IDType{id, true}));
m_origToNew.push_back(std::make_pair(IDType{id, true}, IDType{path.hash().valT<ValType>(), true}));
}
std::sort(m_newToOrig.begin(), m_newToOrig.end(),
[](const std::pair<IDType, IDType>& a, const std::pair<IDType, IDType>& b) {
return a.first < b.first;
});
std::sort(m_origToNew.begin(), m_origToNew.end(),
[](const std::pair<IDType, IDType>& a, const std::pair<IDType, IDType>& b) {
return a.first < b.first;
});
Log.report(logvisor::Info, _S("Loaded Original IDs '%s'"), yamlPath.getRelativePath().data());
}
template <typename IDType>
IDType IDRestorer<IDType>::newToOriginal(IDType id) const
{
if (!id)
return {};
auto search = rstl::binary_find(m_newToOrig.cbegin(), m_newToOrig.cend(), id,
[](const auto& id) { return id.first; });
if (search == m_newToOrig.cend())
return {};
return search->second;
}
template <typename IDType>
IDType IDRestorer<IDType>::originalToNew(IDType id) const
{
if (!id)
return {};
auto search = rstl::binary_find(m_origToNew.cbegin(), m_origToNew.cend(), id,
[](const auto& id) { return id.first; });
if (search == m_origToNew.cend())
return {};
return search->second;
}
template class IDRestorer<UniqueID32>;
template class IDRestorer<UniqueID64>;
template class IDRestorer<UniqueID128>;
bool SpecBase::canExtract(const ExtractPassInfo& info, std::vector<ExtractReport>& reps)
{
m_disc = nod::OpenDiscFromImage(info.srcpath, m_isWii);
@@ -340,9 +407,95 @@ void SpecBase::doCook(const hecl::ProjectPath& path, const hecl::ProjectPath& co
}
}
void SpecBase::flattenDependenciesBlend(const hecl::ProjectPath& in,
std::vector<hecl::ProjectPath>& pathsOut,
hecl::blender::Token& btok,
int charIdx)
{
hecl::blender::Connection& conn = btok.getBlenderConnection();
if (!conn.openBlend(in))
return;
switch (conn.getBlendType())
{
case hecl::blender::BlendType::Mesh:
{
hecl::blender::DataStream ds = conn.beginData();
std::vector<hecl::ProjectPath> texs = ds.getTextures();
for (const hecl::ProjectPath& tex : texs)
pathsOut.push_back(tex);
break;
}
case hecl::blender::BlendType::Actor:
{
hecl::ProjectPath asGlob = in.getWithExtension(_S(".*"), true);
hecl::blender::DataStream ds = conn.beginData();
hecl::blender::Actor actor = ds.compileActorCharacterOnly();
auto doSubtype = [&](Actor::Subtype& sub)
{
if (sub.armature >= 0)
{
pathsOut.push_back(sub.mesh);
hecl::SystemStringConv chSysName(sub.name);
pathsOut.push_back(asGlob.ensureAuxInfo(hecl::SystemString(chSysName.sys_str()) + _S(".CSKR")));
const auto& arm = actor.armatures[sub.armature];
hecl::SystemStringConv armSysName(arm.name);
pathsOut.push_back(asGlob.ensureAuxInfo(hecl::SystemString(armSysName.sys_str()) + _S(".CINF")));
for (const auto& overlay : sub.overlayMeshes)
{
hecl::SystemStringConv ovelaySys(overlay.first);
pathsOut.push_back(overlay.second);
pathsOut.push_back(asGlob.ensureAuxInfo(hecl::SystemString(chSysName.sys_str()) + _S('.') +
ovelaySys.c_str() + _S(".CSKR")));
}
}
};
if (charIdx < 0)
for (auto& sub : actor.subtypes)
doSubtype(sub);
else if (charIdx < actor.subtypes.size())
doSubtype(actor.subtypes[charIdx]);
auto actNames = ds.getActionNames();
for (const auto& act : actNames)
{
hecl::SystemStringConv actSysName(act);
pathsOut.push_back(asGlob.ensureAuxInfo(hecl::SystemString(actSysName.sys_str()) + _S(".ANIM")));
hecl::ProjectPath evntPath = asGlob.getWithExtension(
hecl::SysFormat(_S(".%s.evnt.yaml"), actSysName.c_str()).c_str(), true);
if (evntPath.isFile())
pathsOut.push_back(evntPath);
}
ds.close();
hecl::ProjectPath yamlPath = asGlob.getWithExtension(_S(".yaml"), true);
if (yamlPath.isFile())
{
athena::io::FileReader reader(yamlPath.getAbsolutePath());
flattenDependenciesANCSYAML(reader, pathsOut, charIdx);
}
pathsOut.push_back(asGlob);
return;
}
case hecl::blender::BlendType::Area:
{
hecl::blender::DataStream ds = conn.beginData();
std::vector<hecl::ProjectPath> texs = ds.getTextures();
for (const hecl::ProjectPath& tex : texs)
pathsOut.push_back(tex);
break;
}
default: break;
}
}
void SpecBase::flattenDependencies(const hecl::ProjectPath& path,
std::vector<hecl::ProjectPath>& pathsOut,
hecl::blender::Token& btok)
hecl::blender::Token& btok,
int charIdx)
{
DataSpec::g_curSpec.reset(this);
g_ThreadBlenderToken.reset(&btok);
@@ -355,77 +508,7 @@ void SpecBase::flattenDependencies(const hecl::ProjectPath& path,
if (hecl::IsPathBlend(asBlend))
{
hecl::blender::Connection& conn = btok.getBlenderConnection();
if (!conn.openBlend(asBlend))
return;
switch (conn.getBlendType())
{
case hecl::blender::BlendType::Mesh:
{
hecl::blender::DataStream ds = conn.beginData();
std::vector<hecl::ProjectPath> texs = ds.getTextures();
for (const hecl::ProjectPath& tex : texs)
pathsOut.push_back(tex);
break;
}
case hecl::blender::BlendType::Actor:
{
hecl::ProjectPath asGlob = path.getWithExtension(_S(".*"), true);
hecl::blender::DataStream ds = conn.beginData();
hecl::blender::Actor actor = ds.compileActorCharacterOnly();
for (auto& sub : actor.subtypes)
{
if (sub.armature >= 0)
{
pathsOut.push_back(sub.mesh);
hecl::SystemStringConv chSysName(sub.name);
pathsOut.push_back(asGlob.ensureAuxInfo(hecl::SystemString(chSysName.sys_str()) + _S(".CSKR")));
const auto& arm = actor.armatures[sub.armature];
hecl::SystemStringConv armSysName(arm.name);
pathsOut.push_back(asGlob.ensureAuxInfo(hecl::SystemString(armSysName.sys_str()) + _S(".CINF")));
for (const auto& overlay : sub.overlayMeshes)
{
hecl::SystemStringConv ovelaySys(overlay.first);
pathsOut.push_back(overlay.second);
pathsOut.push_back(asGlob.ensureAuxInfo(hecl::SystemString(chSysName.sys_str()) + _S('.') +
ovelaySys.c_str() + _S(".CSKR")));
}
}
}
auto actNames = ds.getActionNames();
for (const auto& act : actNames)
{
hecl::SystemStringConv actSysName(act);
pathsOut.push_back(asGlob.ensureAuxInfo(hecl::SystemString(actSysName.sys_str()) + _S(".ANIM")));
hecl::ProjectPath evntPath = asGlob.getWithExtension(
hecl::SysFormat(_S(".%s.evnt.yaml"), actSysName.c_str()).c_str(), true);
if (evntPath.isFile())
pathsOut.push_back(evntPath);
}
ds.close();
hecl::ProjectPath yamlPath = asGlob.getWithExtension(_S(".yaml"), true);
if (yamlPath.isFile())
{
athena::io::FileReader reader(yamlPath.getAbsolutePath());
flattenDependenciesANCSYAML(reader, pathsOut);
}
pathsOut.push_back(asGlob);
return;
}
case hecl::blender::BlendType::Area:
{
hecl::blender::DataStream ds = conn.beginData();
std::vector<hecl::ProjectPath> texs = ds.getTextures();
for (const hecl::ProjectPath& tex : texs)
pathsOut.push_back(tex);
break;
}
default: break;
}
flattenDependenciesBlend(asBlend, pathsOut, btok, charIdx);
}
else if (hecl::IsPathYAML(path))
{
@@ -436,18 +519,18 @@ void SpecBase::flattenDependencies(const hecl::ProjectPath& path,
pathsOut.push_back(path);
}
void SpecBase::flattenDependencies(const UniqueID32& id, std::vector<hecl::ProjectPath>& pathsOut)
void SpecBase::flattenDependencies(const UniqueID32& id, std::vector<hecl::ProjectPath>& pathsOut, int charIdx)
{
hecl::ProjectPath path = UniqueIDBridge::TranslatePakIdToPath(id);
if (path)
flattenDependencies(path, pathsOut, *g_ThreadBlenderToken.get());
flattenDependencies(path, pathsOut, *g_ThreadBlenderToken.get(), charIdx);
}
void SpecBase::flattenDependencies(const UniqueID64& id, std::vector<hecl::ProjectPath>& pathsOut)
void SpecBase::flattenDependencies(const UniqueID64& id, std::vector<hecl::ProjectPath>& pathsOut, int charIdx)
{
hecl::ProjectPath path = UniqueIDBridge::TranslatePakIdToPath(id);
if (path)
flattenDependencies(path, pathsOut, *g_ThreadBlenderToken.get());
flattenDependencies(path, pathsOut, *g_ThreadBlenderToken.get(), charIdx);
}
bool SpecBase::canPackage(const hecl::ProjectPath& path)
@@ -550,8 +633,13 @@ void SpecBase::doPackage(const hecl::ProjectPath& path, const hecl::Database::Da
auto components = path.getWithExtension(_S(""), true).getPathComponents();
if (components.size() <= 1)
return;
hecl::ProjectPath outPath(m_project.getProjectWorkingPath(),
_S("out/") + components[0] + _S("/") + components[1] + _S(".upak"));
hecl::ProjectPath outPath;
if (hecl::ProjectPath(m_project.getProjectWorkingPath(), _S("out/files/") + components[0]).isDirectory())
outPath.assign(m_project.getProjectWorkingPath(),
_S("out/files/") + components[0] + _S("/") + components[1] + entry->m_pakExt.data());
else
outPath.assign(m_project.getProjectWorkingPath(),
_S("out/files/") + components[1] + entry->m_pakExt.data());
outPath.makeDirChain(false);
/* Output file */