Add TextureCache support to MP2 and 3

This commit is contained in:
Phillip Stephens 2020-04-11 00:53:04 -07:00
parent 416fec2367
commit 30bcdb2b2f
Signed by: Antidote
GPG Key ID: F8BEE4C83DACA60D
3 changed files with 144 additions and 6 deletions

View File

@ -66,6 +66,7 @@ struct TextureCache {
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 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());

View File

@ -11,6 +11,7 @@
#include "DNAMP1/CSNG.hpp"
#include "DNACommon/MAPU.hpp"
#include "DNACommon/PATH.hpp"
#include "DNACommon/TXTR.hpp"
#include "hecl/ClientProcess.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 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 {
bool checkStandaloneID(const char* id) const override {
if (!memcmp(id, "G2M", 3))
@ -249,6 +313,10 @@ struct SpecMP2 : SpecBase {
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;
}

View File

@ -1,13 +1,14 @@
#include <utility>
#include <set>
#include "SpecBase.hpp"
#include "DNAMP3/DNAMP3.hpp"
#include "DataSpec/SpecBase.hpp"
#include "DataSpec/DNAMP3/DNAMP3.hpp"
#include "DNAMP3/MLVL.hpp"
#include "DNAMP3/STRG.hpp"
#include "DNAMP3/MAPA.hpp"
#include "DNAMP2/STRG.hpp"
#include "DataSpec/DNAMP3/MLVL.hpp"
#include "DataSpec/DNAMP3/STRG.hpp"
#include "DataSpec/DNAMP3/MAPA.hpp"
#include "DataSpec/DNAMP2/STRG.hpp"
#include "DataSpec/DNACommon/TXTR.hpp"
#include "hecl/ClientProcess.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 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 {
bool checkStandaloneID(const char* id) const override {
if (!memcmp(id, "RM3", 3))
@ -409,6 +473,11 @@ struct SpecMP3 : SpecBase {
}
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;
}