summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Companion.cpp92
-rw-r--r--src/Companion.h24
-rw-r--r--src/factories/BaseFactory.h1
-rw-r--r--src/factories/DisplayListFactory.cpp4
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);
}