2
0
mirror of https://github.com/AxioDL/metaforce.git synced 2025-12-09 15:47:46 +00:00

Merge branch 'master' of ssh://git.axiodl.com:6431/AxioDL/urde

This commit is contained in:
Jack Andersen
2019-08-31 10:40:41 -10:00
616 changed files with 6419 additions and 5156 deletions

View File

@@ -69,6 +69,7 @@ static const std::unordered_set<uint32_t> IndividualOrigIDs = {
struct OriginalIDs {
static void Generate(PAKRouter<DNAMP1::PAKBridge>& pakRouter, hecl::Database::Project& project) {
Log.report(logvisor::Level::Info, fmt("Generating Original ID mappings..."));
std::unordered_set<UniqueID32> addedIDs;
std::vector<UniqueID32> originalIDs;
@@ -93,6 +94,7 @@ struct OriginalIDs {
path.makeDirChain(false);
athena::io::FileWriter fileW(path.getAbsolutePath());
yamlW.finish(&fileW);
Log.report(logvisor::Level::Info, fmt("Done"));
}
static void Cook(const hecl::ProjectPath& inPath, const hecl::ProjectPath& outPath) {
@@ -136,8 +138,65 @@ struct OriginalIDs {
}
};
struct TextureCache {
static void Generate(PAKRouter<DNAMP1::PAKBridge>& pakRouter, hecl::Database::Project& project) {
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 DNAMP1::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("MP1TextureCache");
for (const auto& pair : metaMap) {
hecl::ProjectPath path = pakRouter.getWorking(pair.first);
auto rec = yamlW.enterSubRecord(path.getRelativePathUTF8().data());
pair.second.write(yamlW);
}
hecl::ProjectPath path(project.getProjectWorkingPath(), "MP1/!texture_cache.yaml");
path.makeDirChain(false);
athena::io::FileWriter fileW(path.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.push_back(std::make_pair(projectPath.hash().val32(), 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 SpecMP1 : SpecBase {
bool checkStandaloneID(const char* id) const { return !memcmp(id, "GM8", 3); }
bool checkStandaloneID(const char* id) const override { return !memcmp(id, "GM8", 3); }
std::vector<const nod::Node*> m_nonPaks;
std::vector<DNAMP1::PAKBridge> m_paks;
@@ -153,7 +212,7 @@ struct SpecMP1 : SpecBase {
std::unordered_map<hecl::Hash, hecl::blender::Matrix4f> m_mreaPathToXF;
void setThreadProject() {
void setThreadProject() override {
SpecBase::setThreadProject();
UniqueIDBridge::SetIDRestorer(&m_idRestorer);
}
@@ -233,7 +292,7 @@ struct SpecMP1 : SpecBase {
}
bool checkFromStandaloneDisc(nod::DiscBase& disc, const hecl::SystemString& regstr,
const std::vector<hecl::SystemString>& args, std::vector<ExtractReport>& reps) {
const std::vector<hecl::SystemString>& args, std::vector<ExtractReport>& reps) override {
nod::IPartition* partition = disc.getDataPartition();
m_dolBuf = partition->getDOLBuf();
const char* buildInfo = (char*)memmem(m_dolBuf.get(), partition->getDOLSize(), "MetroidBuildInfo", 16) + 19;
@@ -260,7 +319,7 @@ struct SpecMP1 : SpecBase {
}
bool checkFromTrilogyDisc(nod::DiscBase& disc, const hecl::SystemString& regstr,
const std::vector<hecl::SystemString>& args, std::vector<ExtractReport>& reps) {
const std::vector<hecl::SystemString>& args, std::vector<ExtractReport>& reps) override {
std::vector<hecl::SystemString> mp1args;
bool doExtract = false;
if (args.size()) {
@@ -319,7 +378,7 @@ struct SpecMP1 : SpecBase {
return true;
}
bool extractFromDisc(nod::DiscBase& disc, bool force, const hecl::MultiProgressPrinter& progress) {
bool extractFromDisc(nod::DiscBase& disc, bool force, const hecl::MultiProgressPrinter& progress) override {
m_project.enableDataSpecs({_SYS_STR("MP1-PC")});
nod::ExtractionContext ctx = {force, nullptr};
@@ -397,21 +456,23 @@ struct SpecMP1 : SpecBase {
/* Generate original ID mapping for MLVL and SCAN entries - marks complete project */
OriginalIDs::Generate(m_pakRouter, m_project);
/* Generate Texture Cache containing meta data for every texture file */
TextureCache::Generate(m_pakRouter, m_project);
return true;
}
const hecl::Database::DataSpecEntry& getOriginalSpec() const { return SpecEntMP1; }
const hecl::Database::DataSpecEntry& getOriginalSpec() const override { return SpecEntMP1; }
const hecl::Database::DataSpecEntry& getUnmodifiedSpec() const { return SpecEntMP1ORIG; }
const hecl::Database::DataSpecEntry& getUnmodifiedSpec() const override { return SpecEntMP1ORIG; }
hecl::ProjectPath getWorking(class UniqueID32& id) { return m_pakRouter.getWorking(id); }
hecl::ProjectPath getWorking(class UniqueID32& id) override { return m_pakRouter.getWorking(id); }
bool checkPathPrefix(const hecl::ProjectPath& path) const {
bool checkPathPrefix(const hecl::ProjectPath& path) const override {
return path.getRelativePath().compare(0, 4, _SYS_STR("MP1/")) == 0;
}
bool validateYAMLDNAType(athena::io::IStreamReader& fp) const {
bool validateYAMLDNAType(athena::io::IStreamReader& fp) const override {
athena::io::YAMLDocReader reader;
yaml_parser_set_input(reader.getParser(), (yaml_read_handler_t*)athena::io::YAMLAthenaReader, &fp);
return reader.ClassTypeOperation([](const char* classType) {
@@ -479,11 +540,13 @@ struct SpecMP1 : SpecBase {
return true;
else if (!strcmp(classType, "MP1OriginalIDs"))
return true;
else if (!strcmp(classType, "MP1TextureCache"))
return true;
return false;
});
}
urde::SObjectTag buildTagFromPath(const hecl::ProjectPath& path) const {
urde::SObjectTag buildTagFromPath(const hecl::ProjectPath& path) const override {
if (hecl::StringUtils::EndsWith(path.getAuxInfo(), _SYS_STR(".CINF")))
return {SBIG('CINF'), path.hash().val32()};
else if (hecl::StringUtils::EndsWith(path.getAuxInfo(), _SYS_STR(".CSKR")))
@@ -553,12 +616,13 @@ struct SpecMP1 : SpecBase {
} else if (hecl::IsPathPNG(path)) {
return {SBIG('TXTR'), path.hash().val32()};
} else if (hecl::IsPathYAML(path)) {
FILE* fp = hecl::Fopen(path.getAbsolutePath().data(), _SYS_STR("r"));
if (!fp)
auto fp = hecl::FopenUnique(path.getAbsolutePath().data(), _SYS_STR("r"));
if (fp == nullptr) {
return {};
}
athena::io::YAMLDocReader reader;
yaml_parser_set_input_file(reader.getParser(), fp);
yaml_parser_set_input_file(reader.getParser(), fp.get());
urde::SObjectTag resTag;
if (reader.ClassTypeOperation([&](const char* className) -> bool {
@@ -632,20 +696,22 @@ struct SpecMP1 : SpecBase {
} else if (!strcmp(className, "MP1OriginalIDs")) {
resTag.type = SBIG('OIDS');
return true;
} else if (!strcmp(className, "MP1TextureCache")) {
resTag.type = SBIG('TMET');
return true;
}
return false;
})) {
resTag.id = path.hash().val32();
fclose(fp);
fp.reset();
return resTag;
}
fclose(fp);
}
return {};
}
void getTagListForFile(const char* pakName, std::vector<urde::SObjectTag>& out) const {
void getTagListForFile(const char* pakName, std::vector<urde::SObjectTag>& out) const override {
std::string pathPrefix("MP1/");
pathPrefix += pakName;
pathPrefix += '/';
@@ -657,7 +723,7 @@ struct SpecMP1 : SpecBase {
}
void cookMesh(const hecl::ProjectPath& out, const hecl::ProjectPath& in, BlendStream& ds, bool fast,
hecl::blender::Token& btok, FCookProgress progress) {
hecl::blender::Token& btok, FCookProgress progress) override {
Mesh mesh = ds.compileMesh(fast ? hecl::HMDLTopology::Triangles : hecl::HMDLTopology::TriStrips, m_pc ? 16 : -1);
if (m_pc)
@@ -667,21 +733,21 @@ struct SpecMP1 : SpecBase {
}
void cookColMesh(const hecl::ProjectPath& out, const hecl::ProjectPath& in, BlendStream& ds, bool fast,
hecl::blender::Token& btok, FCookProgress progress) {
hecl::blender::Token& btok, FCookProgress progress) override {
std::vector<ColMesh> mesh = ds.compileColMeshes();
ds.close();
DNAMP1::DCLN::Cook(out, mesh);
}
void cookPathMesh(const hecl::ProjectPath& out, const hecl::ProjectPath& in, BlendStream& ds, bool fast,
hecl::blender::Token& btok, FCookProgress progress) {
hecl::blender::Token& btok, FCookProgress progress) override {
PathMesh mesh = ds.compilePathMesh();
ds.close();
DNAMP1::PATH::Cook(out, in, mesh, btok);
}
void cookActor(const hecl::ProjectPath& out, const hecl::ProjectPath& in, BlendStream& ds, bool fast,
hecl::blender::Token& btok, FCookProgress progress) {
hecl::blender::Token& btok, FCookProgress progress) override {
if (hecl::StringUtils::EndsWith(in.getAuxInfo(), _SYS_STR(".CINF"))) {
Actor actor = ds.compileActorCharacterOnly();
DNAMP1::ANCS::CookCINF(out, in, actor);
@@ -733,7 +799,7 @@ struct SpecMP1 : SpecBase {
}
void cookArea(const hecl::ProjectPath& out, const hecl::ProjectPath& in, BlendStream& ds, bool fast,
hecl::blender::Token& btok, FCookProgress progress) {
hecl::blender::Token& btok, FCookProgress progress) override {
std::vector<std::string> meshes = ds.getMeshList();
std::vector<Mesh> meshCompiles;
meshCompiles.reserve(meshes.size());
@@ -747,8 +813,8 @@ struct SpecMP1 : SpecBase {
progress(_SYS_STR("Collision Mesh"));
continue;
}
meshCompiles.push_back(ds.compileMesh(
mesh, fast ? hecl::HMDLTopology::Triangles : hecl::HMDLTopology::TriStrips, -1, !m_pc));
meshCompiles.push_back(
ds.compileMesh(mesh, fast ? hecl::HMDLTopology::Triangles : hecl::HMDLTopology::TriStrips, -1, !m_pc));
}
if (!colMesh)
@@ -769,7 +835,7 @@ struct SpecMP1 : SpecBase {
}
void cookWorld(const hecl::ProjectPath& out, const hecl::ProjectPath& in, BlendStream& ds, bool fast,
hecl::blender::Token& btok, FCookProgress progress) {
hecl::blender::Token& btok, FCookProgress progress) override {
if (hecl::StringUtils::EndsWith(in.getAuxInfo(), _SYS_STR("MAPW"))) {
hecl::blender::World world = ds.compileWorld();
ds.close();
@@ -786,7 +852,7 @@ struct SpecMP1 : SpecBase {
}
void cookGuiFrame(const hecl::ProjectPath& out, const hecl::ProjectPath& in, BlendStream& ds,
hecl::blender::Token& btok, FCookProgress progress) {
hecl::blender::Token& btok, FCookProgress progress) override {
auto data = ds.compileGuiFrame(0);
athena::io::MemoryReader r(data.data(), data.size());
DNAMP1::FRME frme;
@@ -796,7 +862,7 @@ struct SpecMP1 : SpecBase {
}
void cookYAML(const hecl::ProjectPath& out, const hecl::ProjectPath& in, athena::io::IStreamReader& fin,
FCookProgress progress) {
FCookProgress progress) override {
athena::io::YAMLDocReader reader;
if (reader.parse(&fin)) {
std::string classStr = reader.readString("DNAType");
@@ -922,12 +988,14 @@ struct SpecMP1 : SpecBase {
DNAMP1::AFSM::Cook(in, out);
} else if (!classStr.compare("MP1OriginalIDs")) {
OriginalIDs::Cook(in, out);
} else if (!classStr.compare("MP1TextureCache")) {
TextureCache::Cook(in, out);
}
}
progress(_SYS_STR("Done"));
}
void flattenDependenciesYAML(athena::io::IStreamReader& fin, std::vector<hecl::ProjectPath>& pathsOut) {
void flattenDependenciesYAML(athena::io::IStreamReader& fin, std::vector<hecl::ProjectPath>& pathsOut) override {
athena::io::YAMLDocReader reader;
if (reader.parse(&fin)) {
std::string classStr = reader.readString("DNAType");
@@ -980,7 +1048,7 @@ struct SpecMP1 : SpecBase {
}
void flattenDependenciesANCSYAML(athena::io::IStreamReader& fin, std::vector<hecl::ProjectPath>& pathsOut,
int charIdx) {
int charIdx) override {
athena::io::YAMLDocReader reader;
if (reader.parse(&fin)) {
std::string classStr = reader.readString("DNAType");
@@ -1008,7 +1076,8 @@ struct SpecMP1 : SpecBase {
void buildWorldPakList(const hecl::ProjectPath& worldPath, const hecl::ProjectPath& worldPathCooked,
hecl::blender::Token& btok, athena::io::FileWriter& w, std::vector<urde::SObjectTag>& listOut,
atUint64& resTableOffset, std::unordered_map<urde::CAssetId, std::vector<uint8_t>>& mlvlData) {
atUint64& resTableOffset,
std::unordered_map<urde::CAssetId, std::vector<uint8_t>>& mlvlData) override {
DNAMP1::MLVL mlvl;
{
athena::io::FileReader r(worldPathCooked.getAbsolutePath());
@@ -1166,7 +1235,7 @@ struct SpecMP1 : SpecBase {
}
void buildPakList(hecl::blender::Token& btok, athena::io::FileWriter& w, const std::vector<urde::SObjectTag>& list,
const std::vector<std::pair<urde::SObjectTag, std::string>>& nameList, atUint64& resTableOffset) {
const std::vector<std::pair<urde::SObjectTag, std::string>>& nameList, atUint64& resTableOffset) override {
w.writeUint32Big(m_pc ? 0x80030005 : 0x00030005);
w.writeUint32Big(0);
@@ -1194,7 +1263,7 @@ struct SpecMP1 : SpecBase {
}
void writePakFileIndex(athena::io::FileWriter& w, const std::vector<urde::SObjectTag>& tags,
const std::vector<std::tuple<size_t, size_t, bool>>& index, atUint64 resTableOffset) {
const std::vector<std::tuple<size_t, size_t, bool>>& index, atUint64 resTableOffset) override {
w.seek(resTableOffset, athena::Begin);
auto it = tags.begin();
@@ -1211,7 +1280,7 @@ struct SpecMP1 : SpecBase {
}
std::pair<std::unique_ptr<uint8_t[]>, size_t> compressPakData(const urde::SObjectTag& tag, const uint8_t* data,
size_t len) {
size_t len) override {
bool doCompress = false;
switch (tag.type.toUint32()) {
case SBIG('TXTR'):
@@ -1244,18 +1313,18 @@ struct SpecMP1 : SpecBase {
return ret;
};
void cookAudioGroup(const hecl::ProjectPath& out, const hecl::ProjectPath& in, FCookProgress progress) {
void cookAudioGroup(const hecl::ProjectPath& out, const hecl::ProjectPath& in, FCookProgress progress) override {
DNAMP1::AGSC::Cook(in, out);
progress(_SYS_STR("Done"));
}
void cookSong(const hecl::ProjectPath& out, const hecl::ProjectPath& in, FCookProgress progress) {
void cookSong(const hecl::ProjectPath& out, const hecl::ProjectPath& in, FCookProgress progress) override {
DNAMP1::CSNG::Cook(in, out);
progress(_SYS_STR("Done"));
}
void cookMapArea(const hecl::ProjectPath& out, const hecl::ProjectPath& in, BlendStream& ds,
hecl::blender::Token& btok, FCookProgress progress) {
hecl::blender::Token& btok, FCookProgress progress) override {
hecl::blender::MapArea mapa = ds.compileMapArea();
ds.close();
DNAMP1::MAPA::Cook(mapa, out);
@@ -1263,7 +1332,7 @@ struct SpecMP1 : SpecBase {
}
void cookMapUniverse(const hecl::ProjectPath& out, const hecl::ProjectPath& in, BlendStream& ds,
hecl::blender::Token& btok, FCookProgress progress) {
hecl::blender::Token& btok, FCookProgress progress) override {
hecl::blender::MapUniverse mapu = ds.compileMapUniverse();
ds.close();
DNAMAPU::MAPU::Cook(mapu, out);