From 70a6bb7cf1a93609bcb92f14673c064d98ff9cf5 Mon Sep 17 00:00:00 2001 From: KiritoDv Date: Wed, 21 Feb 2024 12:51:47 -0600 Subject: Added asset mods support --- src/Companion.cpp | 92 +++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 89 insertions(+), 3 deletions(-) (limited to 'src/Companion.cpp') diff --git a/src/Companion.cpp b/src/Companion.cpp index c7be9b6..a6e9aa3 100644 --- a/src/Companion.cpp +++ b/src/Companion.cpp @@ -18,6 +18,7 @@ #include "factories/LightsFactory.h" #include "factories/mk64/WaypointFactory.h" #include "spdlog/spdlog.h" +#include "hj/sha1.h" #include #include @@ -79,7 +80,29 @@ void Companion::ExtractNode(YAML::Node& node, std::string& name, SWrapper* binar return; } - auto result = factory->get()->parse(this->gRomData, node); + auto impl = factory->get(); + + std::optional> result; + if(this->gConfig.modding) { + if(impl->SupportModdedAssets() && this->gModdedAssetPaths.contains(name)) { + + auto path = fs::path(this->gConfig.moddingPath) / this->gModdedAssetPaths[name]; + if(!fs::exists(path)) { + SPDLOG_ERROR("Modded asset {} not found", this->gModdedAssetPaths[name]); + return; + } + + std::ifstream input(path, std::ios::binary); + std::vector data = std::vector( std::istreambuf_iterator( input ), {}); + input.close(); + + result = factory->get()->parse_modding(data, node); + } else { + result = factory->get()->parse(this->gRomData, node); + } + } else { + result = factory->get()->parse(this->gRomData, node); + } if(!result.has_value()){ SPDLOG_ERROR("Failed to process {}", name); return; @@ -117,6 +140,29 @@ void Companion::ExtractNode(YAML::Node& node, std::string& name, SWrapper* binar binary->CreateFile(name, std::vector(data.begin(), data.end())); break; } + case ExportType::Modding: { + stream.str(""); + stream.clear(); + std::string ogname = name; + exporter->get()->Export(stream, result.value(), name, node, &name); + + auto data = stream.str(); + if(data.empty()) { + break; + } + + std::string dpath = Instance->GetOutputPath() + "/" + name; + if(!exists(fs::path(dpath).parent_path())){ + create_directories(fs::path(dpath).parent_path()); + } + + this->gModdedAssetPaths[ogname] = name; + + std::ofstream file(dpath, std::ios::binary); + file.write(data.c_str(), data.size()); + file.close(); + break; + } default: { exporter->get()->Export(stream, result.value(), name, node, &name); @@ -141,6 +187,20 @@ void Companion::ExtractNode(YAML::Node& node, std::string& name, SWrapper* binar } } +void Companion::ParseModdingConfig() { + auto path = fs::path(this->gConfig.moddingPath) / "modding.yml"; + if(!fs::exists(path)) { + throw std::runtime_error("No modding config found, please run in export mode first"); + } + auto modding = YAML::LoadFile(path); + for(auto assets = modding["assets"].begin(); assets != modding["assets"].end(); ++assets) { + auto name = assets->first.as(); + auto asset = assets->second.as(); + this->gModdedAssetPaths[name] = asset; + } +} + + void Companion::ParseCurrentFileConfig(YAML::Node node) { if(node["segments"]) { for(auto segment = node["segments"].begin(); segment != node["segments"].end(); ++segment) { @@ -214,7 +274,9 @@ void Companion::Process() { auto path = rom["path"].as(); auto opath = cfg["output"]; auto gbi = cfg["gbi"]; + auto modding_path = opath && opath["modding"] ? opath["modding"].as() : "modding"; + this->gConfig.moddingPath = modding_path; switch (this->gConfig.exporterType) { case ExportType::Binary: { this->gConfig.outputPath = opath && opath["binary"] ? opath["binary"].as() : "generic.otr"; @@ -228,6 +290,10 @@ void Companion::Process() { this->gConfig.outputPath = opath && opath["code"] ? opath["code"].as() : "code"; break; } + case ExportType::Modding: { + this->gConfig.outputPath = modding_path; + break; + } } if(gbi) { @@ -264,6 +330,10 @@ void Companion::Process() { }; } + if(this->gConfig.exporterType == ExportType::Code && this->gConfig.modding) { + this->ParseModdingConfig(); + } + if(std::holds_alternative>(this->gWriteOrder)) { for (auto& [key, _] : this->gFactories) { auto entries = std::get>(this->gWriteOrder); @@ -415,8 +485,20 @@ void Companion::Process() { spdlog::set_pattern(line); } - if(this->gConfig.exporterType != ExportType::Binary){ - auto fsout = fs::path(this->gConfig.outputPath); + auto fsout = fs::path(this->gConfig.outputPath); + + if(this->gConfig.exporterType == ExportType::Modding) { + fsout /= "modding.yml"; + YAML::Node modding; + + for (const auto& [key, value] : this->gModdedAssetPaths) { + modding["assets"][key] = value; + } + + std::ofstream file(fsout.string(), std::ios::binary); + file << modding; + file.close(); + } else if(this->gConfig.exporterType != ExportType::Binary){ std::string filename = this->gCurrentDirectory.filename().string(); switch (this->gConfig.exporterType) { @@ -627,4 +709,8 @@ std::optional> Companion::GetNodeByAddr(cons std::string Companion::NormalizeAsset(const std::string& name) const { auto path = fs::path(this->gCurrentFile).stem().string() + "_" + name; return path; +} + +std::string Companion::CalculateHash(const std::vector& data) { + return Chocobo1::SHA1().addData(data).finalize().toString(); } \ No newline at end of file -- cgit v1.2.3