diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/Companion.cpp | 92 | ||||
| -rw-r--r-- | src/Companion.h | 24 | ||||
| -rw-r--r-- | src/factories/BaseFactory.h | 1 | ||||
| -rw-r--r-- | src/factories/DisplayListFactory.cpp | 4 |
4 files changed, 75 insertions, 46 deletions
diff --git a/src/Companion.cpp b/src/Companion.cpp index 2dca649..8a5b6d5 100644 --- a/src/Companion.cpp +++ b/src/Companion.cpp @@ -143,8 +143,7 @@ void Companion::ParseEnums(std::string& header) { } } -void Companion::ExtractNode(YAML::Node& node, std::string& name, SWrapper* binary) { - std::ostringstream stream; +void Companion::ExtractNode(YAML::Node node, std::string name, SWrapper* binary) { auto type = GetSafeNode<std::string>(node, "type"); std::transform(type.begin(), type.end(), type.begin(), ::toupper); @@ -164,7 +163,6 @@ void Companion::ExtractNode(YAML::Node& node, std::string& name, SWrapper* binar return; } - auto impl = factory->get(); auto exporter = impl->GetExporter(this->gConfig.exporterType); @@ -173,48 +171,60 @@ void Companion::ExtractNode(YAML::Node& node, std::string& name, SWrapper* binar return; } - std::optional<std::shared_ptr<IParsedData>> result; - if(this->gConfig.modding) { - if(impl->SupportModdedAssets() && this->gModdedAssetPaths.contains(name)) { + std::shared_future<ParseResult> result; - auto path = fs::path(this->gConfig.moddingPath) / this->gModdedAssetPaths[name]; - if(!fs::exists(path)) { - SPDLOG_ERROR("Modded asset {} not found", this->gModdedAssetPaths[name]); - return; - } + if(this->gConfig.modding && 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<uint8_t> data = std::vector<uint8_t>( std::istreambuf_iterator( input ), {}); - input.close(); + std::ifstream input(path, std::ios::binary); + std::vector<uint8_t> data = std::vector<uint8_t>( std::istreambuf_iterator( input ), {}); + input.close(); - result = factory->get()->parse_modding(data, node); - } else { - result = factory->get()->parse(this->gRomData, node); - } + result = this->gThreadPool.submit_task([&data, &node, factory]{ + return factory->get()->parse_modding(data, node); + }); } else { - result = factory->get()->parse(this->gRomData, node); + result = this->gThreadPool.submit_task([this, &node, factory, binary]{ + auto out = factory->get()->parse(this->gRomData, node); + + for (auto [fst, snd] : this->gAssetDependencies[this->gCurrentFile]) { + if(snd.second) { + continue; + } + std::string doutput = (this->gCurrentDirectory / fst).string(); + std::replace(doutput.begin(), doutput.end(), '\\', '/'); + this->gAssetDependencies[this->gCurrentFile][fst].second = true; + this->ExtractNode(snd.first, doutput, binary); + spdlog::set_pattern(regular); + SPDLOG_INFO("------------------------------------------------"); + spdlog::set_pattern(line); + } + return out; + }); } + + this->gParseFutures.push_back(AsyncExport { node, name, binary, result, impl, exporter->get()}); +} + +void Companion::ExportNode(AsyncExport async){ + auto [node, name, binary, future, impl, exporter] = async; + + std::ostringstream stream; + auto result = future.get(); + if(!result.has_value()){ SPDLOG_ERROR("Failed to process {}", name); return; } - for (auto [fst, snd] : this->gAssetDependencies[this->gCurrentFile]) { - if(snd.second) { - continue; - } - std::string doutput = (this->gCurrentDirectory / fst).string(); - std::replace(doutput.begin(), doutput.end(), '\\', '/'); - this->gAssetDependencies[this->gCurrentFile][fst].second = true; - this->ExtractNode(snd.first, doutput, binary); - spdlog::set_pattern(regular); - SPDLOG_INFO("------------------------------------------------"); - spdlog::set_pattern(line); - } - ExportResult endptr = std::nullopt; switch (this->gConfig.exporterType) { + case ExportType::Binary: { if(binary == nullptr) { break; @@ -222,7 +232,7 @@ void Companion::ExtractNode(YAML::Node& node, std::string& name, SWrapper* binar stream.str(""); stream.clear(); - exporter->get()->Export(stream, result.value(), name, node, &name); + exporter->Export(stream, result.value(), name, node, &name); auto data = stream.str(); binary->CreateFile(name, std::vector(data.begin(), data.end())); break; @@ -231,7 +241,7 @@ void Companion::ExtractNode(YAML::Node& node, std::string& name, SWrapper* binar stream.str(""); stream.clear(); std::string ogname = name; - exporter->get()->Export(stream, result.value(), name, node, &name); + exporter->Export(stream, result.value(), name, node, &name); auto data = stream.str(); if(data.empty()) { @@ -251,7 +261,7 @@ void Companion::ExtractNode(YAML::Node& node, std::string& name, SWrapper* binar break; } default: { - endptr = exporter->get()->Export(stream, result.value(), name, node, &name); + endptr = exporter->Export(stream, result.value(), name, node, &name); break; } } @@ -294,7 +304,7 @@ void Companion::ExtractNode(YAML::Node& node, std::string& name, SWrapper* binar } } } - this->gWriteMap[this->gCurrentFile][type].push_back(entry); + this->gWriteMap[this->gCurrentFile][GetSafeNode<std::string>(node, "type")].push_back(entry); } void Companion::ParseModdingConfig() { @@ -657,7 +667,6 @@ void Companion::Process() { continue; } - // Parse horizontal assets if(assetNode["files"]){ auto segment = assetNode["segment"] ? assetNode["segment"].as<uint8_t>() : -1; @@ -697,6 +706,11 @@ void Companion::Process() { spdlog::set_pattern(line); } + for (size_t i = 0; i < this->gParseFutures.size(); i++) { + const auto async = this->gParseFutures.at(i); + this->ExportNode(async); + } + auto fsout = fs::path(this->gConfig.outputPath); if(this->gConfig.exporterType == ExportType::Modding) { @@ -909,7 +923,7 @@ std::optional<std::tuple<std::string, YAML::Node>> Companion::RegisterAsset(cons if(!node["offset"]) { return std::nullopt; } - + gMutex.lock(); this->gAssetDependencies[this->gCurrentFile][name] = std::make_pair(node, false); auto output = (this->gCurrentDirectory / name).string(); @@ -917,7 +931,7 @@ std::optional<std::tuple<std::string, YAML::Node>> Companion::RegisterAsset(cons auto entry = std::make_tuple(output, node); this->gAddrMap[this->gCurrentFile][node["offset"].as<uint32_t>()] = entry; - + gMutex.unlock(); return entry; } diff --git a/src/Companion.h b/src/Companion.h index abe8ce9..f83cd80 100644 --- a/src/Companion.h +++ b/src/Companion.h @@ -4,12 +4,15 @@ #include <optional> #include <filesystem> #include <vector> +#include <future> #include <fstream> #include <unordered_map> #include <variant> -#include "factories/BaseFactory.h" #include "n64/Cartridge.h" #include "utils/Decompressor.h" +#include "factories/BaseFactory.h" +#include <mutex> +#include "thread-pool/BS_thread_pool.hpp" class SWrapper; namespace fs = std::filesystem; @@ -74,6 +77,15 @@ struct TorchConfig { bool modding; }; +struct AsyncExport { + YAML::Node node; + std::string name; + SWrapper* binary; + std::shared_future<ParseResult> future; + BaseFactory* factory; + BaseExporter* exporter; +}; + class Companion { public: static Companion* Instance; @@ -122,6 +134,7 @@ private: TorchConfig gConfig; YAML::Node gModdingConfig; fs::path gCurrentDirectory; + BS::thread_pool gThreadPool; std::vector<uint8_t> gRomData; std::filesystem::path gRomPath; std::shared_ptr<N64::Cartridge> gCartridge; @@ -132,14 +145,16 @@ private: std::string gFileHeader; bool gEnablePadGen = false; uint32_t gCurrentPad = 0; + std::vector<Table> gTables; uint32_t gCurrentFileOffset; uint32_t gCurrentSegmentNumber; std::optional<VRAMEntry> gCurrentVram; CompressionType gCurrentCompressionType; - std::vector<Table> gTables; + std::mutex gMutex; + std::vector<AsyncExport> gParseFutures; + std::unordered_map<std::string, std::string> gModdedAssetPaths; std::variant<std::vector<std::string>, std::string> gWriteOrder; std::unordered_map<std::string, std::shared_ptr<BaseFactory>> gFactories; - std::unordered_map<std::string, std::string> gModdedAssetPaths; std::unordered_map<std::string, std::map<std::string, std::vector<WriteEntry>>> gWriteMap; std::unordered_map<std::string, std::map<std::string, std::pair<YAML::Node, bool>>> gAssetDependencies; std::unordered_map<std::string, std::unordered_map<uint32_t, std::tuple<std::string, YAML::Node>>> gAddrMap; @@ -148,5 +163,6 @@ private: void ParseModdingConfig(); void ParseCurrentFileConfig(YAML::Node node); void RegisterFactory(const std::string& type, const std::shared_ptr<BaseFactory>& factory); - void ExtractNode(YAML::Node& node, std::string& name, SWrapper* binary); + void ExtractNode(YAML::Node node, std::string name, SWrapper* binary); + void ExportNode(AsyncExport async); }; diff --git a/src/factories/BaseFactory.h b/src/factories/BaseFactory.h index 1246c91..eeebbf4 100644 --- a/src/factories/BaseFactory.h +++ b/src/factories/BaseFactory.h @@ -32,6 +32,7 @@ struct OffsetEntry { }; typedef std::optional<std::variant<size_t, OffsetEntry>> ExportResult; +#define ParseResult std::optional<std::shared_ptr<IParsedData>> enum class ExportType { Header, diff --git a/src/factories/DisplayListFactory.cpp b/src/factories/DisplayListFactory.cpp index 29c1bf9..760c7ad 100644 --- a/src/factories/DisplayListFactory.cpp +++ b/src/factories/DisplayListFactory.cpp @@ -352,7 +352,7 @@ std::optional<std::shared_ptr<IParsedData>> DListFactory::parse(std::vector<uint // We need to process gsSPLight which is a subcommand inside G_MOVEMEM (0x03). if(opcode == GBI(G_MOVEMEM)) { // 0x03860000 or 0x03880000 subcommand will contain 0x86/0x88 for G_MV_L0 and G_MV_L1. Other subcommands also exist. - uint8_t subcommand = (w0 >> 16) & 0xFF; + uint8_t subcommand = (w0 >> 16) & 0xFF; uint8_t index = 0; uint8_t offset = 0; bool light = false; @@ -494,7 +494,5 @@ std::optional<std::shared_ptr<IParsedData>> DListFactory::parse(std::vector<uint gfxs.push_back(w1); } - - return std::make_shared<DListData>(gfxs); } |
