mirror of https://github.com/AxioDL/metaforce.git
Add TextureCache support to MP2 and 3
This commit is contained in:
parent
416fec2367
commit
30bcdb2b2f
|
@ -66,6 +66,7 @@ struct TextureCache {
|
||||||
static void Generate(PAKRouter<DNAMP1::PAKBridge>& pakRouter, hecl::Database::Project& project, const hecl::ProjectPath& pakPath) {
|
static void Generate(PAKRouter<DNAMP1::PAKBridge>& pakRouter, hecl::Database::Project& project, const hecl::ProjectPath& pakPath) {
|
||||||
hecl::ProjectPath texturePath(pakPath, _SYS_STR("texture_cache.yaml"));
|
hecl::ProjectPath texturePath(pakPath, _SYS_STR("texture_cache.yaml"));
|
||||||
hecl::ProjectPath catalogPath(pakPath, _SYS_STR("!catalog.yaml"));
|
hecl::ProjectPath catalogPath(pakPath, _SYS_STR("!catalog.yaml"));
|
||||||
|
texturePath.makeDirChain(false);
|
||||||
|
|
||||||
if (const auto fp = hecl::FopenUnique(catalogPath.getAbsolutePath().data(), _SYS_STR("a"))) {
|
if (const auto fp = hecl::FopenUnique(catalogPath.getAbsolutePath().data(), _SYS_STR("a"))) {
|
||||||
fmt::print(fp.get(), fmt("TextureCache: {}\n"), texturePath.getRelativePathUTF8());
|
fmt::print(fp.get(), fmt("TextureCache: {}\n"), texturePath.getRelativePathUTF8());
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
#include "DNAMP1/CSNG.hpp"
|
#include "DNAMP1/CSNG.hpp"
|
||||||
#include "DNACommon/MAPU.hpp"
|
#include "DNACommon/MAPU.hpp"
|
||||||
#include "DNACommon/PATH.hpp"
|
#include "DNACommon/PATH.hpp"
|
||||||
|
#include "DNACommon/TXTR.hpp"
|
||||||
|
|
||||||
#include "hecl/ClientProcess.hpp"
|
#include "hecl/ClientProcess.hpp"
|
||||||
#include "hecl/Blender/Connection.hpp"
|
#include "hecl/Blender/Connection.hpp"
|
||||||
|
@ -27,6 +28,69 @@ static logvisor::Module Log("urde::SpecMP2");
|
||||||
extern hecl::Database::DataSpecEntry SpecEntMP2;
|
extern hecl::Database::DataSpecEntry SpecEntMP2;
|
||||||
extern hecl::Database::DataSpecEntry SpecEntMP2ORIG;
|
extern hecl::Database::DataSpecEntry SpecEntMP2ORIG;
|
||||||
|
|
||||||
|
struct TextureCache {
|
||||||
|
static void Generate(PAKRouter<DNAMP2::PAKBridge>& pakRouter, hecl::Database::Project& project, const hecl::ProjectPath& pakPath) {
|
||||||
|
hecl::ProjectPath texturePath(pakPath, _SYS_STR("texture_cache.yaml"));
|
||||||
|
hecl::ProjectPath catalogPath(pakPath, _SYS_STR("!catalog.yaml"));
|
||||||
|
texturePath.makeDirChain(false);
|
||||||
|
|
||||||
|
if (const auto fp = hecl::FopenUnique(catalogPath.getAbsolutePath().data(), _SYS_STR("a"))) {
|
||||||
|
fmt::print(fp.get(), fmt("TextureCache: {}\n"), texturePath.getRelativePathUTF8());
|
||||||
|
}
|
||||||
|
|
||||||
|
Log.report(logvisor::Level::Info, fmt("Gathering Texture metadata (this can take up to 10 seconds)..."));
|
||||||
|
std::unordered_map<UniqueID32, TXTR::Meta> metaMap;
|
||||||
|
|
||||||
|
pakRouter.enumerateResources([&](const DNAMP2::PAK::Entry* ent) {
|
||||||
|
if (ent->type == FOURCC('TXTR') && metaMap.find(ent->id) == metaMap.end()) {
|
||||||
|
PAKEntryReadStream rs = pakRouter.beginReadStreamForId(ent->id);
|
||||||
|
metaMap[ent->id] = TXTR::GetMetaData(rs);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
|
athena::io::YAMLDocWriter yamlW("MP2TextureCache");
|
||||||
|
for (const auto& pair : metaMap) {
|
||||||
|
hecl::ProjectPath path = pakRouter.getWorking(pair.first);
|
||||||
|
auto rec = yamlW.enterSubRecord(path.getRelativePathUTF8());
|
||||||
|
pair.second.write(yamlW);
|
||||||
|
}
|
||||||
|
|
||||||
|
athena::io::FileWriter fileW(texturePath.getAbsolutePath());
|
||||||
|
yamlW.finish(&fileW);
|
||||||
|
Log.report(logvisor::Level::Info, fmt("Done..."));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Cook(const hecl::ProjectPath& inPath, const hecl::ProjectPath& outPath) {
|
||||||
|
hecl::Database::Project& project = inPath.getProject();
|
||||||
|
athena::io::YAMLDocReader r;
|
||||||
|
athena::io::FileReader fr(inPath.getAbsolutePath());
|
||||||
|
if (!fr.isOpen() || !r.parse(&fr))
|
||||||
|
return;
|
||||||
|
|
||||||
|
std::vector<std::pair<UniqueID32, TXTR::Meta>> metaPairs;
|
||||||
|
metaPairs.reserve(r.getRootNode()->m_mapChildren.size());
|
||||||
|
for (const auto& node : r.getRootNode()->m_mapChildren) {
|
||||||
|
hecl::ProjectPath projectPath(project, node.first);
|
||||||
|
auto rec = r.enterSubRecord(node.first.c_str());
|
||||||
|
TXTR::Meta meta;
|
||||||
|
meta.read(r);
|
||||||
|
metaPairs.emplace_back(projectPath.parsedHash32(), meta);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::sort(metaPairs.begin(), metaPairs.end(), [](const auto& a, const auto& b) -> bool {
|
||||||
|
return a.first < b.first;
|
||||||
|
});
|
||||||
|
|
||||||
|
athena::io::FileWriter w(outPath.getAbsolutePath());
|
||||||
|
w.writeUint32Big(metaPairs.size());
|
||||||
|
for (const auto& pair : metaPairs) {
|
||||||
|
pair.first.write(w);
|
||||||
|
pair.second.write(w);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
struct SpecMP2 : SpecBase {
|
struct SpecMP2 : SpecBase {
|
||||||
bool checkStandaloneID(const char* id) const override {
|
bool checkStandaloneID(const char* id) const override {
|
||||||
if (!memcmp(id, "G2M", 3))
|
if (!memcmp(id, "G2M", 3))
|
||||||
|
@ -249,6 +313,10 @@ struct SpecMP2 : SpecBase {
|
||||||
|
|
||||||
process.waitUntilComplete();
|
process.waitUntilComplete();
|
||||||
|
|
||||||
|
/* Generate Texture Cache containing meta data for every texture file */
|
||||||
|
hecl::ProjectPath noAramPath(m_project.getProjectWorkingPath(), _SYS_STR("MP2/URDE"));
|
||||||
|
TextureCache::Generate(m_pakRouter, m_project, noAramPath);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,13 +1,14 @@
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <set>
|
#include <set>
|
||||||
|
|
||||||
#include "SpecBase.hpp"
|
#include "DataSpec/SpecBase.hpp"
|
||||||
#include "DNAMP3/DNAMP3.hpp"
|
#include "DataSpec/DNAMP3/DNAMP3.hpp"
|
||||||
|
|
||||||
#include "DNAMP3/MLVL.hpp"
|
#include "DataSpec/DNAMP3/MLVL.hpp"
|
||||||
#include "DNAMP3/STRG.hpp"
|
#include "DataSpec/DNAMP3/STRG.hpp"
|
||||||
#include "DNAMP3/MAPA.hpp"
|
#include "DataSpec/DNAMP3/MAPA.hpp"
|
||||||
#include "DNAMP2/STRG.hpp"
|
#include "DataSpec/DNAMP2/STRG.hpp"
|
||||||
|
#include "DataSpec/DNACommon/TXTR.hpp"
|
||||||
|
|
||||||
#include "hecl/ClientProcess.hpp"
|
#include "hecl/ClientProcess.hpp"
|
||||||
#include "hecl/Blender/Connection.hpp"
|
#include "hecl/Blender/Connection.hpp"
|
||||||
|
@ -24,6 +25,69 @@ static logvisor::Module Log("urde::SpecMP3");
|
||||||
extern hecl::Database::DataSpecEntry SpecEntMP3;
|
extern hecl::Database::DataSpecEntry SpecEntMP3;
|
||||||
extern hecl::Database::DataSpecEntry SpecEntMP3ORIG;
|
extern hecl::Database::DataSpecEntry SpecEntMP3ORIG;
|
||||||
|
|
||||||
|
struct TextureCache {
|
||||||
|
static void Generate(PAKRouter<DNAMP3::PAKBridge>& pakRouter, hecl::Database::Project& project, const hecl::ProjectPath& pakPath) {
|
||||||
|
hecl::ProjectPath texturePath(pakPath, _SYS_STR("texture_cache.yaml"));
|
||||||
|
hecl::ProjectPath catalogPath(pakPath, _SYS_STR("!catalog.yaml"));
|
||||||
|
texturePath.makeDirChain(false);
|
||||||
|
|
||||||
|
if (const auto fp = hecl::FopenUnique(catalogPath.getAbsolutePath().data(), _SYS_STR("a"))) {
|
||||||
|
fmt::print(fp.get(), fmt("TextureCache: {}\n"), texturePath.getRelativePathUTF8());
|
||||||
|
}
|
||||||
|
|
||||||
|
Log.report(logvisor::Level::Info, fmt("Gathering Texture metadata (this can take up to 10 seconds)..."));
|
||||||
|
std::unordered_map<UniqueID64, TXTR::Meta> metaMap;
|
||||||
|
|
||||||
|
pakRouter.enumerateResources([&](const DNAMP3::PAK::Entry* ent) {
|
||||||
|
if (ent->type == FOURCC('TXTR') && metaMap.find(ent->id) == metaMap.end()) {
|
||||||
|
PAKEntryReadStream rs = pakRouter.beginReadStreamForId(ent->id);
|
||||||
|
metaMap[ent->id] = TXTR::GetMetaData(rs);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
|
athena::io::YAMLDocWriter yamlW("MP3TextureCache");
|
||||||
|
for (const auto& pair : metaMap) {
|
||||||
|
hecl::ProjectPath path = pakRouter.getWorking(pair.first);
|
||||||
|
auto rec = yamlW.enterSubRecord(path.getRelativePathUTF8());
|
||||||
|
pair.second.write(yamlW);
|
||||||
|
}
|
||||||
|
|
||||||
|
athena::io::FileWriter fileW(texturePath.getAbsolutePath());
|
||||||
|
yamlW.finish(&fileW);
|
||||||
|
Log.report(logvisor::Level::Info, fmt("Done..."));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Cook(const hecl::ProjectPath& inPath, const hecl::ProjectPath& outPath) {
|
||||||
|
hecl::Database::Project& project = inPath.getProject();
|
||||||
|
athena::io::YAMLDocReader r;
|
||||||
|
athena::io::FileReader fr(inPath.getAbsolutePath());
|
||||||
|
if (!fr.isOpen() || !r.parse(&fr))
|
||||||
|
return;
|
||||||
|
|
||||||
|
std::vector<std::pair<UniqueID32, TXTR::Meta>> metaPairs;
|
||||||
|
metaPairs.reserve(r.getRootNode()->m_mapChildren.size());
|
||||||
|
for (const auto& node : r.getRootNode()->m_mapChildren) {
|
||||||
|
hecl::ProjectPath projectPath(project, node.first);
|
||||||
|
auto rec = r.enterSubRecord(node.first.c_str());
|
||||||
|
TXTR::Meta meta;
|
||||||
|
meta.read(r);
|
||||||
|
metaPairs.emplace_back(projectPath.parsedHash32(), meta);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::sort(metaPairs.begin(), metaPairs.end(), [](const auto& a, const auto& b) -> bool {
|
||||||
|
return a.first < b.first;
|
||||||
|
});
|
||||||
|
|
||||||
|
athena::io::FileWriter w(outPath.getAbsolutePath());
|
||||||
|
w.writeUint32Big(metaPairs.size());
|
||||||
|
for (const auto& pair : metaPairs) {
|
||||||
|
pair.first.write(w);
|
||||||
|
pair.second.write(w);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
struct SpecMP3 : SpecBase {
|
struct SpecMP3 : SpecBase {
|
||||||
bool checkStandaloneID(const char* id) const override {
|
bool checkStandaloneID(const char* id) const override {
|
||||||
if (!memcmp(id, "RM3", 3))
|
if (!memcmp(id, "RM3", 3))
|
||||||
|
@ -409,6 +473,11 @@ struct SpecMP3 : SpecBase {
|
||||||
}
|
}
|
||||||
|
|
||||||
process.waitUntilComplete();
|
process.waitUntilComplete();
|
||||||
|
|
||||||
|
/* Extract part of .dol for RandomStatic entropy */
|
||||||
|
hecl::ProjectPath noAramPath(m_project.getProjectWorkingPath(), _SYS_STR("MP3/URDE"));
|
||||||
|
/* Generate Texture Cache containing meta data for every texture file */
|
||||||
|
TextureCache::Generate(m_pakRouter, m_project, noAramPath);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue