summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKiritoDv <kiritodev01@gmail.com>2024-01-30 23:03:23 -0600
committerLywx <kiritodev01@gmail.com>2024-01-31 12:05:40 -0600
commit4668cf08fb240da4abaafc073ba08d9d13ac0fa5 (patch)
tree8ef2781da88920eeb1267225e73406e25a3c17b6
parent242f8acf212d143443dc2ce846507bdb82571902 (diff)
Refactored code and added per file config
-rw-r--r--src/Companion.cpp6
-rw-r--r--src/factories/BankFactory.cpp1
-rw-r--r--src/factories/BaseFactory.h27
-rw-r--r--src/factories/BlobFactory.cpp20
-rw-r--r--src/factories/DisplayListFactory.cpp160
-rw-r--r--src/factories/DisplayListOverrides.cpp10
-rw-r--r--src/factories/LightsFactory.cpp16
-rw-r--r--src/factories/SampleFactory.cpp1
-rw-r--r--src/factories/SequenceFactory.cpp13
-rw-r--r--src/factories/TextureFactory.cpp40
-rw-r--r--src/factories/VtxFactory.cpp16
-rw-r--r--src/factories/mk64/WaypointFactory.cpp14
-rw-r--r--src/factories/sm64/AnimationFactory.cpp19
-rw-r--r--src/factories/sm64/DialogFactory.cpp16
-rw-r--r--src/factories/sm64/DictionaryFactory.cpp11
-rw-r--r--src/factories/sm64/GeoLayoutFactory.cpp3
-rw-r--r--src/factories/sm64/Original.old485
-rw-r--r--src/factories/sm64/TextFactory.cpp14
-rw-r--r--src/utils/Decompressor.cpp124
-rw-r--r--src/utils/Decompressor.h36
-rw-r--r--src/utils/MIODecoder.cpp28
-rw-r--r--src/utils/MIODecoder.h12
22 files changed, 321 insertions, 751 deletions
diff --git a/src/Companion.cpp b/src/Companion.cpp
index 17f4862..be70629 100644
--- a/src/Companion.cpp
+++ b/src/Companion.cpp
@@ -1,7 +1,7 @@
#include "Companion.h"
#include "storm/SWrapper.h"
-#include "utils/MIODecoder.h"
+#include "utils/Decompressor.h"
#include "factories/sm64/AnimationFactory.h"
#include "factories/sm64/DialogFactory.h"
#include "factories/sm64/DictionaryFactory.h"
@@ -61,7 +61,7 @@ void Companion::Init(const ExportType type) {
void Companion::ExtractNode(YAML::Node& node, std::string& name, SWrapper* binary) {
std::ostringstream stream;
- auto type = node["type"].as<std::string>();
+ auto type = GetSafeNode<std::string>(node, "type");
std::transform(type.begin(), type.end(), type.begin(), ::toupper);
if(node["offset"]) {
@@ -408,7 +408,7 @@ void Companion::Process() {
spdlog::set_pattern(regular);
SPDLOG_INFO("------------------------------------------------");
- MIO0Decoder::ClearCache();
+ Decompressor::ClearCache();
this->gCartridge = nullptr;
Instance = nullptr;
}
diff --git a/src/factories/BankFactory.cpp b/src/factories/BankFactory.cpp
index 53f4869..7c8c2e8 100644
--- a/src/factories/BankFactory.cpp
+++ b/src/factories/BankFactory.cpp
@@ -1,5 +1,4 @@
#include "BankFactory.h"
-#include "utils/MIODecoder.h"
#include "Companion.h"
#include "audio/samples_table.h"
diff --git a/src/factories/BaseFactory.h b/src/factories/BaseFactory.h
index 902b02e..b5e5b65 100644
--- a/src/factories/BaseFactory.h
+++ b/src/factories/BaseFactory.h
@@ -28,6 +28,33 @@ enum class ExportType {
Binary,
};
+template<typename T>
+std::optional<T> GetNode(YAML::Node& node, const std::string& key) {
+ if(!node[key]) {
+ return std::nullopt;
+ }
+
+ return std::optional<T>(node[key].as<T>());
+}
+
+template<typename T>
+T GetSafeNode(YAML::Node& node, const std::string& key) {
+ if(!node[key]) {
+ throw std::runtime_error("Failed to find entry");
+ }
+
+ return node[key].as<T>();
+}
+
+template<typename T>
+T GetSafeNode(YAML::Node& node, const std::string& key, const T& def) {
+ if(!node[key]) {
+ return def;
+ }
+
+ return node[key].as<T>();
+}
+
class IParsedData {};
template<typename T>
diff --git a/src/factories/BlobFactory.cpp b/src/factories/BlobFactory.cpp
index 886a206..cd644bf 100644
--- a/src/factories/BlobFactory.cpp
+++ b/src/factories/BlobFactory.cpp
@@ -1,5 +1,5 @@
#include "BlobFactory.h"
-#include "utils/MIODecoder.h"
+#include "utils/Decompressor.h"
#include <iomanip>
void BlobCodeExporter::Export(std::ostream &write, std::shared_ptr<IParsedData> raw, std::string& entryName, YAML::Node &node, std::string* replacement ) {
@@ -26,18 +26,8 @@ void BlobBinaryExporter::Export(std::ostream &write, std::shared_ptr<IParsedData
writer.Finish(write);
}
-std::optional<std::shared_ptr<IParsedData>> BlobFactory::parse(std::vector<uint8_t>& buffer, YAML::Node& data) {
- auto size = data["size"].as<uint32_t>();
- auto offset = data["offset"].as<uint32_t>();
- std::shared_ptr<RawBuffer> result;
-
- if(data["mio0"]){
- auto decoded = MIO0Decoder::Decode(buffer, offset);
- auto cursor = data["mio0"].as<uint32_t>();
- result = std::make_shared<RawBuffer>(decoded.data() + cursor, size);
- } else {
- result = std::make_shared<RawBuffer>(buffer.data() + offset, size);
- }
-
- return result;
+std::optional<std::shared_ptr<IParsedData>> BlobFactory::parse(std::vector<uint8_t>& buffer, YAML::Node& node) {
+ auto size = GetSafeNode<size_t>(node, "size");
+ auto [_, segment] = Decompressor::AutoDecode(node, buffer);
+ return std::make_shared<RawBuffer>(segment.data, segment.size);
} \ No newline at end of file
diff --git a/src/factories/DisplayListFactory.cpp b/src/factories/DisplayListFactory.cpp
index 2481d46..ccb7199 100644
--- a/src/factories/DisplayListFactory.cpp
+++ b/src/factories/DisplayListFactory.cpp
@@ -1,6 +1,6 @@
#include "DisplayListFactory.h"
#include "DisplayListOverrides.h"
-#include "utils/MIODecoder.h"
+#include "utils/Decompressor.h"
#include "spdlog/spdlog.h"
#include "Companion.h"
#include <gfxd.h>
@@ -64,7 +64,7 @@ void GFXDSetGBIVersion(){
}
void DListHeaderExporter::Export(std::ostream &write, std::shared_ptr<IParsedData> raw, std::string& entryName, YAML::Node &node, std::string* replacement) {
- const auto symbol = node["symbol"] ? node["symbol"].as<std::string>() : entryName;
+ const auto symbol = GetSafeNode(node, "symbol", entryName);
if(Companion::Instance->IsOTRMode()){
write << "static const char " << symbol << "[] = \"__OTR__" << (*replacement) << "\";\n\n";
@@ -76,8 +76,9 @@ void DListHeaderExporter::Export(std::ostream &write, std::shared_ptr<IParsedDat
void DListCodeExporter::Export(std::ostream &write, std::shared_ptr<IParsedData> raw, std::string& entryName, YAML::Node &node, std::string* replacement ) {
const auto cmds = std::static_pointer_cast<DListData>(raw)->mGfxs;
- const auto symbol = node["symbol"].as<std::string>();
- const auto offset = node["offset"].as<uint32_t>();
+ const auto symbol = GetSafeNode(node, "symbol", entryName);
+ const auto offset = GetSafeNode<uint32_t>(node, "offset");
+
char out[0xFFFF] = {0};
gfxd_input_buffer(cmds.data(), sizeof(uint32_t) * cmds.size());
@@ -163,11 +164,12 @@ void DListBinaryExporter::Export(std::ostream &write, std::shared_ptr<IParsedDat
if(opcode == GBI(G_VTX)) {
auto nvtx = (C0(0, 16)) / sizeof(Vtx);
auto didx = C0(16, 4);
- uint32_t ptr = SEGMENT_OFFSET(w1);
+ auto ptr = Decompressor::TranslateAddr(w1);
+ auto dec = Companion::Instance->GetNodeByAddr(ptr);
- if(const auto decl = Companion::Instance->GetNodeByAddr(ptr); decl.has_value()){
- uint64_t hash = CRC64(std::get<0>(decl.value()).c_str());
- SPDLOG_INFO("Found vtx: 0x{:X} Hash: 0x{:X} Path: {}", ptr, hash, std::get<0>(decl.value()));
+ if(dec.has_value()){
+ uint64_t hash = CRC64(std::get<0>(dec.value()).c_str());
+ SPDLOG_INFO("Found vtx: 0x{:X} Hash: 0x{:X} Path: {}", ptr, hash, std::get<0>(dec.value()));
// TODO: Find a better way to do this because its going to break on other games
Gfx value = gsSPVertexOTR(didx, nvtx, 0);
@@ -188,7 +190,7 @@ void DListBinaryExporter::Export(std::ostream &write, std::shared_ptr<IParsedDat
}
if(opcode == GBI(G_DL)) {
- auto ptr = SEGMENT_OFFSET(w1);
+ auto ptr = Decompressor::TranslateAddr(w1);
auto dec = Companion::Instance->GetNodeByAddr(ptr);
Gfx value = gsSPDisplayListOTRHash(ptr);
@@ -209,8 +211,7 @@ void DListBinaryExporter::Export(std::ostream &write, std::shared_ptr<IParsedDat
}
if(opcode == GBI(G_MOVEMEM)) {
- uint32_t ptr = SEGMENT_OFFSET(w1);
-
+ auto ptr = Decompressor::TranslateAddr(w1);
auto dec = Companion::Instance->GetNodeByAddr(ptr);
w0 &= 0x00FFFFFF;
@@ -231,7 +232,7 @@ void DListBinaryExporter::Export(std::ostream &write, std::shared_ptr<IParsedDat
}
if(opcode == GBI(G_SETTIMG)) {
- auto ptr = SEGMENT_OFFSET(w1);
+ auto ptr = Decompressor::TranslateAddr(w1);
auto dec = Companion::Instance->GetNodeByAddr(ptr);
Gfx value = gsDPSetTextureOTRImage(C0(21, 3), C0(19, 2), C0(0, 10), ptr);
@@ -261,32 +262,11 @@ void DListBinaryExporter::Export(std::ostream &write, std::shared_ptr<IParsedDat
std::optional<std::shared_ptr<IParsedData>> DListFactory::parse(std::vector<uint8_t>& raw_buffer, YAML::Node& node) {
const auto gbi = Companion::Instance->GetGBIVersion();
- auto offset = node["offset"].as<uint32_t>();
- const bool isCompressed = node["mio0"] ? true : false;
-
- std::vector<uint8_t> buffer;
-
- if(IS_SEGMENTED(offset)){
- const auto segment = Companion::Instance->GetSegmentedAddr(SEGMENT_NUMBER(offset));
-
- if(!segment.has_value()) {
- SPDLOG_ERROR("Segment data missing from game config\nPlease add an entry for segment {}", SEGMENT_NUMBER(offset));
- return std::nullopt;
- }
-
- offset = segment.value() + SEGMENT_OFFSET(offset);
- }
-
- if(isCompressed){
- const auto mio0 = node["mio0"].as<uint32_t>();
- buffer = MIO0Decoder::Decode(raw_buffer, mio0);
- } else {
- buffer = raw_buffer;
- }
-
- LUS::BinaryReader reader(buffer.data(), buffer.size());
+ auto [_, segment] = Decompressor::AutoDecode(node, raw_buffer);
+ LUS::BinaryReader reader(segment.data, segment.size);
reader.SetEndianness(LUS::Endianness::Big);
- reader.Seek(offset, LUS::SeekOffsetType::Start);
+ // Validate this
+ // reader.Seek(offset, LUS::SeekOffsetType::Start);
std::vector<uint32_t> gfxs;
auto processing = true;
@@ -304,24 +284,8 @@ std::optional<std::shared_ptr<IParsedData>> DListFactory::parse(std::vector<uint
if(opcode == GBI(G_DL)) {
std::optional<uint32_t> segment;
- uint32_t ptr;
-
- if(IS_SEGMENTED(w1)){
- segment = Companion::Instance->GetSegmentedAddr(SEGMENT_NUMBER(w1));
-
- if(!segment.has_value()) {
- SPDLOG_ERROR("Segment data missing from game config\nPlease add an entry for segment {}", SEGMENT_NUMBER(w1));
- continue;
- }
-
- ptr = SEGMENT_OFFSET(w1);
- } else {
- ptr = w1;
- }
-
- auto dec = Companion::Instance->GetNodeByAddr(w1);
- if(!dec.has_value()){
+ if(const auto decl = Companion::Instance->GetNodeByAddr(w1); !decl.has_value()){
SPDLOG_INFO("Addr to Display list command at 0x{:X} not in yaml, autogenerating it", w1);
auto rom = Companion::Instance->GetRomData();
@@ -329,22 +293,17 @@ std::optional<std::shared_ptr<IParsedData>> DListFactory::parse(std::vector<uint
std::string output;
YAML::Node dl;
+ uint32_t ptr = Decompressor::TranslateAddr(w1);
- if(isCompressed){
- dl["mio0"] = segment.has_value() ? segment.value() : ptr;
- if(segment.has_value()) {
- SPDLOG_INFO("Found compressed and segmented display list at 0x{:X}", ptr);
- output = Companion::Instance->NormalizeAsset("seg" + std::to_string(SEGMENT_NUMBER(w1)) +"_dl_" + Torch::to_hex(segment.value() + w1, false));
- } else {
- SPDLOG_INFO("Found compressed display list at 0x{:X}", ptr);
- output = Companion::Instance->NormalizeAsset("dl_" + Torch::to_hex(w1, false));
- }
+ if(Decompressor::IsSegmented(w1)){
+ SPDLOG_INFO("Found segmented display list at 0x{:X}", w1);
+ output = Companion::Instance->NormalizeAsset("seg" + std::to_string(SEGMENT_NUMBER(w1)) +"_dl_" + Torch::to_hex(ptr, false));
} else {
SPDLOG_INFO("Found display list at 0x{:X}", ptr);
output = Companion::Instance->NormalizeAsset("dl_" + Torch::to_hex(w1, false));
}
-
+ Decompressor::CopyCompression(node, dl);
dl["type"] = "GFX";
dl["offset"] = ptr;
dl["symbol"] = output;
@@ -357,14 +316,13 @@ std::optional<std::shared_ptr<IParsedData>> DListFactory::parse(std::vector<uint
Companion::Instance->RegisterAsset(output, dl);
} else {
- SPDLOG_WARN("Warning: Could not find display list at 0x{:X}", ptr);
+ SPDLOG_WARN("Warning: Could not find display list at 0x{:X}", w1);
}
}
if(opcode == GBI(G_MOVEMEM)) {
uint8_t index = 0;
uint8_t offset = 0;
- uint32_t ptr = SEGMENT_OFFSET(w1);
switch (Companion::Instance->GetGBIVersion()) {
case GBIVersion::f3d:
@@ -385,26 +343,33 @@ std::optional<std::shared_ptr<IParsedData>> DListFactory::parse(std::vector<uint
}
}
-
- if(const auto decl = Companion::Instance->GetNodeByAddr(ptr); !decl.has_value()){
+ if(const auto decl = Companion::Instance->GetNodeByAddr(w1); !decl.has_value()){
SPDLOG_INFO("Addr to Lights1 command at 0x{:X} not in yaml, autogenerating it", w1);
- auto addr = Companion::Instance->GetSegmentedAddr(SEGMENT_NUMBER(w1));
- if(!addr.has_value()) {
- SPDLOG_ERROR("Segment data missing from game config\nPlease add an entry for segment {}", SEGMENT_NUMBER(w1));
- continue;
- }
auto rom = Companion::Instance->GetRomData();
auto factory = Companion::Instance->GetFactory("LIGHTS")->get();
- std::string output = Companion::Instance->NormalizeAsset("seg" + std::to_string(SEGMENT_NUMBER(w1)) +"_lights1_" + Torch::to_hex(addr.value() + w1, false));
+
+ std::string output;
YAML::Node light;
+ uint32_t ptr = Decompressor::TranslateAddr(w1);
+
+ if(Decompressor::IsSegmented(w1)){
+ SPDLOG_INFO("Found segmented lights at 0x{:X}", w1);
+ output = Companion::Instance->NormalizeAsset("seg" + std::to_string(SEGMENT_NUMBER(w1)) +"_lights1_" + Torch::to_hex(ptr, false));
+ } else {
+ SPDLOG_INFO("Found lights at 0x{:X}", ptr);
+ output = Companion::Instance->NormalizeAsset("lights1_" + Torch::to_hex(w1, false));
+ }
+
+ Decompressor::CopyCompression(node, light);
light["type"] = "lights";
- light["mio0"] = addr.value();
light["offset"] = ptr;
light["symbol"] = output;
auto result = factory->parse(rom, light);
if(result.has_value()){
Companion::Instance->RegisterAsset(output, light);
}
+ } else {
+ SPDLOG_WARN("Warning: Could not find lights at 0x{:X}", w1);
}
}
@@ -424,50 +389,25 @@ std::optional<std::shared_ptr<IParsedData>> DListFactory::parse(std::vector<uint
break;
}
- std::optional<uint32_t> segment;
- uint32_t ptr;
-
- if(IS_SEGMENTED(w1)){
- segment = Companion::Instance->GetSegmentedAddr(SEGMENT_NUMBER(w1));
-
- if(!segment.has_value()) {
- SPDLOG_ERROR("Segment data missing from game config\nPlease add an entry for segment {}", SEGMENT_NUMBER(w1));
- continue;
- }
-
- ptr = SEGMENT_OFFSET(w1);
- } else {
- ptr = w1;
- }
-
- if(const auto decl = Companion::Instance->GetNodeByAddr(ptr); !decl.has_value()){
- SPDLOG_INFO("Addr to Vtx array at 0x{:X} not in yaml, autogenerating it", w1);
- auto addr = Companion::Instance->GetSegmentedAddr(SEGMENT_NUMBER(w1));
- if(!addr.has_value()) {
- SPDLOG_ERROR("Segment data missing from game config\nPlease add an entry for segment {}", SEGMENT_NUMBER(w1));
- break;
- }
+ if(const auto decl = Companion::Instance->GetNodeByAddr(w1); !decl.has_value()){
+ SPDLOG_INFO("Addr to Vtx array at 0x{:X} not in yaml, autogenerating it", w1);
+ auto ptr = Decompressor::TranslateAddr(w1);
auto rom = Companion::Instance->GetRomData();
auto factory = Companion::Instance->GetFactory("VTX")->get();
std::string output;
YAML::Node vtx;
- if(isCompressed){
- vtx["mio0"] = segment.has_value() ? segment.value() : ptr;
- if(segment.has_value()) {
- SPDLOG_INFO("Found compressed and segmented display list at 0x{:X}", ptr);
- output = Companion::Instance->NormalizeAsset("seg" + std::to_string(SEGMENT_NUMBER(w1)) +"_vtx_" + Torch::to_hex(segment.value() + w1, false));
- } else {
- SPDLOG_INFO("Found compressed display list at 0x{:X}", ptr);
- output = Companion::Instance->NormalizeAsset("vtx_" + Torch::to_hex(w1, false));
- }
+ if(Decompressor::IsSegmented(w1)){
+ SPDLOG_INFO("Found segmented vtx at 0x{:X}", ptr);
+ output = Companion::Instance->NormalizeAsset("seg" + std::to_string(SEGMENT_NUMBER(w1)) +"_vtx_" + Torch::to_hex(ptr, false));
} else {
- SPDLOG_INFO("Found display list at 0x{:X}", ptr);
- output = Companion::Instance->NormalizeAsset("dl_" + Torch::to_hex(w1, false));
+ SPDLOG_INFO("Found vtx at 0x{:X}", ptr);
+ output = Companion::Instance->NormalizeAsset("vtx_" + Torch::to_hex(w1, false));
}
+ Decompressor::CopyCompression(node, vtx);
vtx["type"] = "VTX";
vtx["offset"] = ptr;
vtx["count"] = nvtx;
@@ -476,6 +416,8 @@ std::optional<std::shared_ptr<IParsedData>> DListFactory::parse(std::vector<uint
if(result.has_value()){
Companion::Instance->RegisterAsset(output, vtx);
}
+ } else {
+ SPDLOG_WARN("Warning: Could not find vtx at 0x{:X}", w1);
}
}
diff --git a/src/factories/DisplayListOverrides.cpp b/src/factories/DisplayListOverrides.cpp
index 7da6ecf..cdfaba0 100644
--- a/src/factories/DisplayListOverrides.cpp
+++ b/src/factories/DisplayListOverrides.cpp
@@ -14,7 +14,7 @@ void Triangle2(const Gfx* gfx) {
auto w1 = gfx->words.w1;
auto v1 = std::to_string( ((w0 >> 16) & 0xFF) / 2 );
- auto v2 = std::to_string( ((w0 >> 8) & 0xFF) / 2 );
+ auto v2 = std::to_string( ((w0 >> 8) & 0xFF) / 2 );
auto v3 = std::to_string( (w0 & 0xFF) / 2 );
auto v4 = std::to_string( ((w1 >> 16) & 0xFF) / 2 );
@@ -49,7 +49,7 @@ int Vtx(uint32_t vtx, int32_t num) {
uint32_t ptr = SEGMENT_OFFSET(vtx);
if(const auto decl = Companion::Instance->GetNodeByAddr(ptr); decl.has_value()){
auto node = std::get<1>(decl.value());
- auto symbol = node["symbol"].as<std::string>();
+ auto symbol = GetSafeNode<std::string>(node, "symbol");
SPDLOG_INFO("Wrote vtx: 0x{:X} Symbol: {}", ptr, symbol);
gfxd_puts(symbol.c_str());
return 1;
@@ -63,7 +63,7 @@ int Texture(uint32_t timg, int32_t fmt, int32_t siz, int32_t width, int32_t heig
uint32_t ptr = SEGMENT_OFFSET(timg);
if(const auto decl = Companion::Instance->GetNodeByAddr(ptr); decl.has_value()){
auto node = std::get<1>(decl.value());
- auto symbol = node["symbol"].as<std::string>();
+ auto symbol = GetSafeNode<std::string>(node, "symbol");
SPDLOG_INFO("Wrote texture: 0x{:X} Symbol: {}", ptr, symbol);
gfxd_puts(symbol.c_str());
return 1;
@@ -77,7 +77,7 @@ int Light(uint32_t lightsn, int32_t count) {
uint32_t ptr = SEGMENT_OFFSET(lightsn);
if(const auto decl = Companion::Instance->GetNodeByAddr(ptr); decl.has_value()){
auto node = std::get<1>(decl.value());
- auto symbol = node["symbol"].as<std::string>();
+ auto symbol = GetSafeNode<std::string>(node, "symbol");
SPDLOG_INFO("Wrote light: 0x{:X} Symbol: {}", ptr, symbol);
gfxd_puts(symbol.c_str());
return 1;
@@ -91,7 +91,7 @@ int DisplayList(uint32_t dl) {
uint32_t ptr = SEGMENT_OFFSET(dl);
if(const auto decl = Companion::Instance->GetNodeByAddr(ptr); decl.has_value()){
auto node = std::get<1>(decl.value());
- auto symbol = node["symbol"].as<std::string>();
+ auto symbol = GetSafeNode<std::string>(node, "symbol");
SPDLOG_INFO("Wrote display list: 0x{:X} Symbol: {}", ptr, symbol);
gfxd_puts(symbol.c_str());
return 1;
diff --git a/src/factories/LightsFactory.cpp b/src/factories/LightsFactory.cpp
index bcabbe8..0e8265c 100644
--- a/src/factories/LightsFactory.cpp
+++ b/src/factories/LightsFactory.cpp
@@ -1,11 +1,11 @@
#include "LightsFactory.h"
-#include "utils/MIODecoder.h"
+#include "utils/Decompressor.h"
#include "spdlog/spdlog.h"
#include "Companion.h"
void LightsHeaderExporter::Export(std::ostream &write, std::shared_ptr<IParsedData> raw, std::string& entryName, YAML::Node &node, std::string* replacement) {
- const auto symbol = node["symbol"] ? node["symbol"].as<std::string>() : entryName;
+ const auto symbol = GetSafeNode(node, "symbol", entryName);
if(Companion::Instance->IsOTRMode()){
write << "static const char " << symbol << "[] = \"__OTR__" << (*replacement) << "\";\n\n";
@@ -17,7 +17,7 @@ void LightsHeaderExporter::Export(std::ostream &write, std::shared_ptr<IParsedDa
void LightsCodeExporter::Export(std::ostream &write, std::shared_ptr<IParsedData> raw, std::string& entryName, YAML::Node &node, std::string* replacement ) {
auto light = std::static_pointer_cast<LightsData>(raw)->mLights;
- auto symbol = node["symbol"].as<std::string>();
+ auto symbol = GetSafeNode(node, "symbol", entryName);
write << "Lights1 " << symbol << " = gdSPDefLights1 (\n";
@@ -68,11 +68,9 @@ void LightsBinaryExporter::Export(std::ostream &write, std::shared_ptr<IParsedDa
}
std::optional<std::shared_ptr<IParsedData>> LightsFactory::parse(std::vector<uint8_t>& buffer, YAML::Node& node) {
- auto mio0 = node["mio0"].as<size_t>();
- auto offset = node["offset"].as<uint32_t>();
-
- auto decoded = MIO0Decoder::Decode(buffer, offset);
- LUS::BinaryReader reader(decoded.data() + mio0, sizeof(Lights1Raw));
+ auto decoded = Decompressor::AutoDecode(node, buffer);
+ auto [_, segment] = Decompressor::AutoDecode(node, buffer);
+ LUS::BinaryReader reader(segment.data, sizeof(Lights1Raw));
reader.SetEndianness(LUS::Endianness::Big);
Lights1Raw lights;
@@ -90,7 +88,6 @@ std::optional<std::shared_ptr<IParsedData>> LightsFactory::parse(std::vector<uin
auto g2 = reader.ReadUByte();
auto b2 = reader.ReadUByte();
-
reader.Seek(5, LUS::SeekOffsetType::Current);
// Direction
@@ -98,6 +95,7 @@ std::optional<std::shared_ptr<IParsedData>> LightsFactory::parse(std::vector<uin
auto y = reader.ReadInt8();
auto z = reader.ReadInt8();
+ // TODO: This is a hack, but it works for now.
// The struct has several copies/padding. The zeros skip those for gdSPDefLights1.
lights = {r, g, b, 0, 0, 0, 0, 0, r2, g2, b2, 0, 0, 0, 0, 0, x, y, z};
diff --git a/src/factories/SampleFactory.cpp b/src/factories/SampleFactory.cpp
index 100c7da..f367a1e 100644
--- a/src/factories/SampleFactory.cpp
+++ b/src/factories/SampleFactory.cpp
@@ -1,5 +1,4 @@
#include "SampleFactory.h"
-#include "utils/MIODecoder.h"
void SampleBinaryExporter::Export(std::ostream &write, std::shared_ptr<IParsedData> raw, std::string& entryName, YAML::Node &node, std::string* replacement ) {
auto writer = LUS::BinaryWriter();
diff --git a/src/factories/SequenceFactory.cpp b/src/factories/SequenceFactory.cpp
index 46ed35e..17b1ac6 100644
--- a/src/factories/SequenceFactory.cpp
+++ b/src/factories/SequenceFactory.cpp
@@ -1,25 +1,24 @@
#include "SequenceFactory.h"
-#include "utils/MIODecoder.h"
void SequenceBinaryExporter::Export(std::ostream &write, std::shared_ptr<IParsedData> raw, std::string& entryName, YAML::Node &node, std::string* replacement ) {
auto writer = LUS::BinaryWriter();
- auto sequence = std::static_pointer_cast<SequenceData>(raw);
+ const auto sequence = std::static_pointer_cast<SequenceData>(raw);
WriteHeader(writer, LUS::ResourceType::Sequence, 0);
- writer.Write((uint32_t) sequence->mId);
- writer.Write((uint32_t) sequence->mBanks.size());
+ writer.Write(sequence->mId);
+ writer.Write(static_cast<uint32_t>(sequence->mBanks.size()));
for (auto& bank : sequence->mBanks) {
writer.Write(bank);
}
- writer.Write((uint32_t) sequence->mSize);
- writer.Write((char*) sequence->mBuffer.data(), sequence->mSize);
+ writer.Write( sequence->mSize);
+ writer.Write(reinterpret_cast<char*>(sequence->mBuffer.data()), sequence->mSize);
writer.Finish(write);
}
std::optional<std::shared_ptr<IParsedData>> SequenceFactory::parse(std::vector<uint8_t>& buffer, YAML::Node& data) {
auto id = data["id"].as<uint32_t>();
auto size = data["size"].as<size_t>();
- auto offset = data["offset"].as<size_t>();
+ const auto offset = data["offset"].as<size_t>();
auto banks = data["banks"].as<std::vector<std::string>>();
return std::make_shared<SequenceData>(id, size, buffer.data() + offset, banks);
} \ No newline at end of file
diff --git a/src/factories/TextureFactory.cpp b/src/factories/TextureFactory.cpp
index 3759737..c08c26c 100644
--- a/src/factories/TextureFactory.cpp
+++ b/src/factories/TextureFactory.cpp
@@ -1,5 +1,5 @@
#include "TextureFactory.h"
-#include "utils/MIODecoder.h"
+#include "utils/Decompressor.h"
#include "spdlog/spdlog.h"
#include "Companion.h"
#include <iomanip>
@@ -45,7 +45,7 @@ std::vector<uint8_t> alloc_ia8_text_from_i1(uint16_t *in, int16_t width, int16_t
}
void TextureHeaderExporter::Export(std::ostream &write, std::shared_ptr<IParsedData> raw, std::string& entryName, YAML::Node &node, std::string* replacement) {
- auto symbol = node["symbol"] ? node["symbol"].as<std::string>() : entryName;
+ auto symbol = GetSafeNode(node, "symbol", entryName);
auto data = std::static_pointer_cast<TextureData>(raw)->mBuffer;
if(Companion::Instance->IsOTRMode()){
@@ -58,8 +58,8 @@ void TextureHeaderExporter::Export(std::ostream &write, std::shared_ptr<IParsedD
void TextureCodeExporter::Export(std::ostream &write, std::shared_ptr<IParsedData> raw, std::string& entryName, YAML::Node &node, std::string* replacement) {
auto data = std::static_pointer_cast<TextureData>(raw)->mBuffer;
- auto symbol = node["symbol"] ? node["symbol"].as<std::string>() : entryName;
- auto format = node["format"].as<std::string>();
+ auto symbol = GetSafeNode(node, "symbol", entryName);
+ auto format = GetSafeNode<std::string>(node, "format");
std::transform(format.begin(), format.end(), format.begin(), tolower);
(*replacement) += "." + format;
@@ -107,11 +107,11 @@ void TextureBinaryExporter::Export(std::ostream &write, std::shared_ptr<IParsedD
}
std::optional<std::shared_ptr<IParsedData>> TextureFactory::parse(std::vector<uint8_t>& buffer, YAML::Node& node) {
- auto format = node["format"].as<std::string>();
- auto width = node["width"].as<uint32_t>();
- auto height = node["height"].as<uint32_t>();
- auto size = node["size"].as<size_t>();
- auto offset = node["offset"].as<size_t>();
+ auto format = GetSafeNode<std::string>(node, "format");
+ auto width = GetSafeNode<uint32_t>(node, "width");
+ auto height = GetSafeNode<uint32_t>(node, "height");
+ auto size = GetSafeNode<uint32_t>(node, "size");
+ auto offset = GetSafeNode<uint32_t>(node, "offset");
if (format.empty()) {
SPDLOG_ERROR("Texture entry at {:X} in yaml missing format node\n\
@@ -126,26 +126,18 @@ std::optional<std::shared_ptr<IParsedData>> TextureFactory::parse(std::vector<ui
TextureType type = gTextureTypes.at(format);
+ auto [_, segment] = Decompressor::AutoDecode(node, buffer);
std::vector<uint8_t> result;
- if(node["mio0"]){
- auto decoded = MIO0Decoder::Decode(buffer, offset);
- auto mio0 = node["mio0"].as<size_t>();
- auto data = decoded.data() + mio0;
-
- if(type == TextureType::GrayscaleAlpha1bpp){
- result = alloc_ia8_text_from_i1((uint16_t*) data, 8, 16);
- } else {
- result = std::vector(data, data + size);
- }
-
- } else {
- result = std::vector(buffer.data() + offset, buffer.data() + offset + size);
- }
+ if(type == TextureType::GrayscaleAlpha1bpp){
+ result = alloc_ia8_text_from_i1((uint16_t*) segment.data, 8, 16);
+ } else {
+ result = std::vector(segment.data, segment.data + segment.size);
+ }
SPDLOG_INFO("Texture: {} {}x{} {}", format, width, height, size);
SPDLOG_INFO("Offset: {}", offset);
- SPDLOG_INFO("Has MIO0: {}", node["mio0"] ? "true" : "false");
+ SPDLOG_INFO("Has MIO0: {}", Decompressor::IsCompressed(node) ? "true" : "false");
SPDLOG_INFO("Size: {}", result.size());
if(result.size() == 0){
diff --git a/src/factories/VtxFactory.cpp b/src/factories/VtxFactory.cpp
index e5214c5..e3ec716 100644
--- a/src/factories/VtxFactory.cpp
+++ b/src/factories/VtxFactory.cpp
@@ -1,13 +1,13 @@
#include "VtxFactory.h"
#include "Companion.h"
-#include "utils/MIODecoder.h"
+#include "utils/Decompressor.h"
#define NUM(x) std::dec << std::setfill(' ') << std::setw(6) << x
#define COL(c) "0x" << std::hex << std::setw(2) << std::setfill('0') << c
void VtxHeaderExporter::Export(std::ostream &write, std::shared_ptr<IParsedData> raw, std::string& entryName, YAML::Node &node, std::string* replacement) {
- const auto symbol = node["symbol"] ? node["symbol"].as<std::string>() : entryName;
+ const auto symbol = GetSafeNode(node, "symbol", entryName);
if(Companion::Instance->IsOTRMode()){
write << "static const char " << symbol << "[] = \"__OTR__" << (*replacement) << "\";\n\n";
@@ -19,8 +19,8 @@ void VtxHeaderExporter::Export(std::ostream &write, std::shared_ptr<IParsedData>
void VtxCodeExporter::Export(std::ostream &write, std::shared_ptr<IParsedData> raw, std::string& entryName, YAML::Node &node, std::string* replacement ) {
auto vtx = std::static_pointer_cast<VtxData>(raw)->mVtxs;
- const auto symbol = node["symbol"].as<std::string>();
- const auto offset = node["offset"].as<uint32_t>();
+ const auto symbol = GetSafeNode(node, "symbol", entryName);
+ const auto offset = GetSafeNode<uint32_t>(node, "offset");
if (Companion::Instance->IsDebug()) {
write << "// 0x" << std::hex << std::uppercase << offset << "\n";
@@ -83,12 +83,10 @@ void VtxBinaryExporter::Export(std::ostream &write, std::shared_ptr<IParsedData>
}
std::optional<std::shared_ptr<IParsedData>> VtxFactory::parse(std::vector<uint8_t>& buffer, YAML::Node& node) {
- auto mio0 = node["mio0"].as<size_t>();
- auto offset = node["offset"].as<uint32_t>();
- auto count = node["count"].as<size_t>();
+ auto count = GetSafeNode<size_t>(node, "count");
- auto decoded = MIO0Decoder::Decode(buffer, offset);
- LUS::BinaryReader reader(decoded.data() + mio0, count * sizeof(VtxRaw) );
+ auto [_, segment] = Decompressor::AutoDecode(node, buffer);
+ LUS::BinaryReader reader(segment.data, count * sizeof(VtxRaw));
reader.SetEndianness(LUS::Endianness::Big);
std::vector<VtxRaw> vertices;
diff --git a/src/factories/mk64/WaypointFactory.cpp b/src/factories/mk64/WaypointFactory.cpp
index ea84ede..9fdcd12 100644
--- a/src/factories/mk64/WaypointFactory.cpp
+++ b/src/factories/mk64/WaypointFactory.cpp
@@ -1,13 +1,13 @@
#include "WaypointFactory.h"
#include "Companion.h"
-#include "utils/MIODecoder.h"
+#include "utils/Decompressor.h"
#define NUM(x) std::dec << std::setfill(' ') << std::setw(6) << x
#define COL(c) "0x" << std::hex << std::setw(2) << std::setfill('0') << c
void MK64::WaypointHeaderExporter::Export(std::ostream &write, std::shared_ptr<IParsedData> raw, std::string& entryName, YAML::Node &node, std::string* replacement) {
- const auto symbol = node["symbol"] ? node["symbol"].as<std::string>() : entryName;
+ const auto symbol = GetSafeNode(node, "symbol", entryName);
if(Companion::Instance->IsOTRMode()){
write << "static const char " << symbol << "[] = \"__OTR__" << (*replacement) << "\";\n\n";
@@ -19,7 +19,7 @@ void MK64::WaypointHeaderExporter::Export(std::ostream &write, std::shared_ptr<I
void MK64::WaypointCodeExporter::Export(std::ostream &write, std::shared_ptr<IParsedData> raw, std::string& entryName, YAML::Node &node, std::string* replacement ) {
auto waypoints = std::static_pointer_cast<WaypointData>(raw)->mWaypoints;
- auto symbol = node["symbol"].as<std::string>();
+ auto symbol = GetSafeNode(node, "symbol", entryName);
write << "TrackWaypoint " << symbol << "[] = {\n";
@@ -58,12 +58,10 @@ void MK64::WaypointBinaryExporter::Export(std::ostream &write, std::shared_ptr<I
}
std::optional<std::shared_ptr<IParsedData>> MK64::WaypointFactory::parse(std::vector<uint8_t>& buffer, YAML::Node& node) {
- auto mio0 = node["mio0"].as<size_t>();
- auto offset = node["offset"].as<uint32_t>();
- auto count = node["count"].as<size_t>();
+ auto count = GetSafeNode<size_t>(node, "count");
- auto decoded = MIO0Decoder::Decode(buffer, offset);
- LUS::BinaryReader reader(decoded.data() + mio0, count * sizeof(MK64::TrackWaypoint) );
+ auto [_, segment] = Decompressor::AutoDecode(node, buffer);
+ LUS::BinaryReader reader(segment.data, count * sizeof(MK64::TrackWaypoint));
reader.SetEndianness(LUS::Endianness::Big);
std::vector<MK64::TrackWaypoint> waypoints;
diff --git a/src/factories/sm64/AnimationFactory.cpp b/src/factories/sm64/AnimationFactory.cpp
index cdbdedf..368de1f 100644
--- a/src/factories/sm64/AnimationFactory.cpp
+++ b/src/factories/sm64/AnimationFactory.cpp
@@ -1,10 +1,9 @@
#include "AnimationFactory.h"
-#include "utils/MIODecoder.h"
#include "spdlog/spdlog.h"
void SM64::AnimationBinaryExporter::Export(std::ostream &write, std::shared_ptr<IParsedData> raw, std::string& entryName, YAML::Node &node, std::string* replacement ) {
auto writer = LUS::BinaryWriter();
- auto anim = std::static_pointer_cast<AnimationData>(raw);
+ const auto anim = std::static_pointer_cast<AnimationData>(raw);
WriteHeader(writer, LUS::ResourceType::Anim, 0);
writer.Write(anim->mFlags);
@@ -29,11 +28,11 @@ void SM64::AnimationBinaryExporter::Export(std::ostream &write, std::shared_ptr<
}
std::optional<std::shared_ptr<IParsedData>> SM64::AnimationFactory::parse(std::vector<uint8_t>& buffer, YAML::Node& node) {
- auto headerNode = node["header"];
- auto valuesNode = node["values"];
- auto indexNode = node["indices"];
+ auto headerNode = GetSafeNode<YAML::Node>(node, "header");
+ auto valuesNode = GetSafeNode<YAML::Node>(node, "values");
+ auto indexNode = GetSafeNode<YAML::Node>(node, "indices");
- LUS::BinaryReader header(reinterpret_cast<char *>(buffer.data()) + headerNode["offset"].as<uint32_t>(), headerNode["size"].as<uint32_t>());
+ LUS::BinaryReader header(reinterpret_cast<char *>(buffer.data()) + GetSafeNode<uint32_t>(headerNode, "offset"), GetSafeNode<uint32_t>(headerNode, "size"));
header.SetEndianness(LUS::Endianness::Big);
auto flags = header.ReadInt16();
@@ -46,17 +45,17 @@ std::optional<std::shared_ptr<IParsedData>> SM64::AnimationFactory::parse(std::v
header.ReadUInt32();
auto length = header.ReadUInt32();
- LUS::BinaryReader indices(reinterpret_cast<char*>(buffer.data()) + indexNode["offset"].as<uint32_t>(), indexNode["size"].as<uint32_t>());
+ LUS::BinaryReader indices(reinterpret_cast<char*>(buffer.data()) + GetSafeNode<uint32_t>(indexNode, "offset"), GetSafeNode<uint32_t>(indexNode, "size"));
indices.SetEndianness(LUS::Endianness::Big);
- size_t indexLength = indexNode["size"].as<uint32_t>() / sizeof(int16_t);
+ size_t indexLength = GetSafeNode<uint32_t>(indexNode, "size") / sizeof(int16_t);
std::vector<int16_t> indicesData;
for (size_t i = 0; i < indexLength; i++) {
indicesData.push_back(indices.ReadInt16());
}
- LUS::BinaryReader values((char*) buffer.data() + valuesNode["offset"].as<uint32_t>(), valuesNode["size"].as<uint32_t>());
+ LUS::BinaryReader values(reinterpret_cast<char*>(buffer.data()) + GetSafeNode<uint32_t>(valuesNode, "offset"), GetSafeNode<uint32_t>(valuesNode, "size"));
values.SetEndianness(LUS::Endianness::Big);
- size_t entries = valuesNode["size"].as<uint32_t>() / sizeof(uint16_t);
+ size_t entries = GetSafeNode<uint32_t>(valuesNode, "size") / sizeof(uint16_t);
std::vector<uint16_t> valuesData;
for (size_t i = 0; i < entries; i++) {
valuesData.push_back(values.ReadUInt16());
diff --git a/src/factories/sm64/DialogFactory.cpp b/src/factories/sm64/DialogFactory.cpp
index 066b575..8cfdcd0 100644
--- a/src/factories/sm64/DialogFactory.cpp
+++ b/src/factories/sm64/DialogFactory.cpp
@@ -1,6 +1,6 @@
#include "DialogFactory.h"
-#include "utils/MIODecoder.h"
#include "spdlog/spdlog.h"
+#include "utils/Decompressor.h"
void SM64::DialogBinaryExporter::Export(std::ostream &write, std::shared_ptr<IParsedData> raw, std::string& entryName, YAML::Node &node, std::string* replacement ) {
auto writer = LUS::BinaryWriter();
@@ -18,14 +18,12 @@ void SM64::DialogBinaryExporter::Export(std::ostream &write, std::shared_ptr<IPa
}
std::optional<std::shared_ptr<IParsedData>> SM64::DialogFactory::parse(std::vector<uint8_t>& buffer, YAML::Node& node) {
- auto offset = node["offset"].as<int32_t>();
- auto mio0 = node["mio0"].as<size_t>();
+ auto [root, segment] = Decompressor::AutoDecode(node, buffer);
- auto decoded = MIO0Decoder::Decode(buffer, offset);
- auto bytes = (uint8_t*) decoded.data();
- LUS::BinaryReader reader(bytes, decoded.size());
+ LUS::BinaryReader reader(segment.data, segment.size);
reader.SetEndianness(LUS::Endianness::Big);
- reader.Seek(mio0, LUS::SeekOffsetType::Start);
+ // Validate this
+ // reader.Seek(mio0, LUS::SeekOffsetType::Start);
auto unused = reader.ReadUInt32();
auto linesPerBox = reader.ReadUByte();
@@ -38,8 +36,8 @@ std::optional<std::shared_ptr<IParsedData>> SM64::DialogFactory::parse(std::vect
auto str = SEGMENT_OFFSET(reader.ReadInt32());
std::vector<uint8_t> text;
- while(bytes[str] != 0xFF){
- auto c = bytes[str++];
+ while(root->data[str] != 0xFF){
+ auto c = root->data[str++];
text.push_back(c);
}
text.push_back(0xFF);
diff --git a/src/factories/sm64/DictionaryFactory.cpp b/src/factories/sm64/DictionaryFactory.cpp
index 39d6055..2b723ef 100644
--- a/src/factories/sm64/DictionaryFactory.cpp
+++ b/src/factories/sm64/DictionaryFactory.cpp
@@ -1,17 +1,16 @@
#include "DictionaryFactory.h"
-#include "utils/MIODecoder.h"
void SM64::DictionaryBinaryExporter::Export(std::ostream &write, std::shared_ptr<IParsedData> raw, std::string& entryName, YAML::Node &node, std::string* replacement ) {
auto writer = LUS::BinaryWriter();
- auto data = std::static_pointer_cast<DictionaryData>(raw);
+ const auto data = std::static_pointer_cast<DictionaryData>(raw);
WriteHeader(writer, LUS::ResourceType::Dictionary, 0);
- writer.Write((uint32_t) data->mDictionary.size());
+ writer.Write(static_cast<uint32_t>(data->mDictionary.size()));
for(auto& [key, value] : data->mDictionary){
writer.Write(key);
- writer.Write((uint32_t) value.size());
- writer.Write((char*) value.data(), value.size());
+ writer.Write(static_cast<uint32_t>(value.size()));
+ writer.Write(reinterpret_cast<char*>(value.data()), value.size());
}
writer.Finish(write);
}
@@ -24,7 +23,7 @@ std::optional<std::shared_ptr<IParsedData>> SM64::DictionaryFactory::parse(std::
auto offset = it->second.as<size_t>();
std::vector<uint8_t> text;
- auto bytes = (uint8_t*) buffer.data();
+ const auto bytes = buffer.data();
while(bytes[offset] != 0xFF){
auto c = bytes[offset++];
diff --git a/src/factories/sm64/GeoLayoutFactory.cpp b/src/factories/sm64/GeoLayoutFactory.cpp
index 03606bd..520b973 100644
--- a/src/factories/sm64/GeoLayoutFactory.cpp
+++ b/src/factories/sm64/GeoLayoutFactory.cpp
@@ -1,7 +1,6 @@
#include "GeoLayoutFactory.h"
#include "spdlog/spdlog.h"
-#include "utils/MIODecoder.h"
#include "geo/GeoCommand.h"
#include "Companion.h"
#include "geo/GeoUtils.h"
@@ -193,7 +192,7 @@ void SM64::GeoHeaderExporter::Export(std::ostream&write, std::shared_ptr<IParsed
}
std::optional<std::shared_ptr<IParsedData>> SM64::GeoLayoutFactory::parse(std::vector<uint8_t>& buffer, YAML::Node& node) {
- const size_t offset = Torch::translate(node["offset"].as<uint32_t>());
+ const size_t offset = Torch::translate(GetSafeNode<uint32_t>(node, "offset"));
auto cmd = buffer.data() + offset;
bool processing = true;
std::vector<GeoCommand> commands;
diff --git a/src/factories/sm64/Original.old b/src/factories/sm64/Original.old
deleted file mode 100644
index 9f59aa4..0000000
--- a/src/factories/sm64/Original.old
+++ /dev/null
@@ -1,485 +0,0 @@
-
-int current_tab_size = 0;
-
-static inline void print_cmd(GeoCommand cmd, std::string c){
- if(cmd == GeoCommand::CLOSE_NODE){
- current_tab_size--;
- }
-
- for(int i = 0; i < current_tab_size; i++){
- std::cout << "\t";
- }
-
- if(cmd == GeoCommand::OPEN_NODE){
- current_tab_size++;
- }
-
- std::cout << "GEO_" << c << "()" << std::endl;
-}
-
-typedef uint32_t GeoLayout;
-
- auto offset = data["offset"].as<size_t>();
- auto cmd = (uint8_t*) buffer.data() + offset;
- auto processing = true;
-
- std::vector<GeoLayout> layout;
- auto geo_writer = new LUS::BinaryWriter();
-
-// #define GeoWrite(x) layout.insert(layout.end(), {x})
-//
-// while(processing){
-// auto opcode = cmd[0x00];
-// switch (opcode) {
-// case CMD_INFO(BRANCH_AND_LINK) {
-// geo_writer->Write((uint8_t) BRANCH_AND_LINK_OTR);
-// uint32_t ptr = SEGMENT_OFFSET(BSWAP32(cur_geo_cmd_u32(0x04)));
-// auto decl = Companion::Instance->GetNodeByAddr(ptr);
-//
-// if(decl.has_value()){
-// uint64_t hash = CRC64(std::get<0>(decl.value()).c_str());
-// SPDLOG_INFO("Found geo: 0x{:X} Hash: 0x{:X} Path: {}", ptr, hash, std::get<0>(decl.value()));
-// geo_writer->Write(hash);
-// } else {
-// SPDLOG_INFO("Warning: Could not find geo at 0x{:X}", ptr);
-// geo_writer->Write((uint64_t) 0);
-// }
-//
-// cmd += 0x08 << CMD_SIZE_SHIFT;
-// break;
-// }
-// case CMD_INFO(BRANCH) {
-// geo_writer->Write((uint8_t) BRANCH_OTR);
-// geo_writer->Write(cur_geo_cmd_u8(0x01));
-//
-// int32_t ptr = SEGMENT_OFFSET(BSWAP32(cur_geo_cmd_u32(0x04)));
-// auto decl = Companion::Instance->GetNodeByAddr(ptr);
-//
-// if(decl.has_value()){
-// uint64_t hash = CRC64(std::get<0>(decl.value()).c_str());
-// SPDLOG_INFO("Found geo: 0x{:X} Hash: 0x{:X} Path: {}", ptr, hash, std::get<0>(decl.value()));
-// geo_writer->Write(hash);
-// } else {
-// SPDLOG_INFO("Warning: Could not find geo at 0x{:X}", ptr);
-// geo_writer->Write((uint64_t) 0);
-// }
-//
-// cmd += 0x08 << CMD_SIZE_SHIFT;
-// break;
-// }
-// case CMD_INFO(END)
-// geo_writer->Write((uint8_t) END);
-// processing = false;
-// break;
-// case CMD_INFO(RETURN)
-// geo_writer->Write((uint8_t) RETURN);
-// processing = false;
-// break;
-// case CMD_NOP(OPEN_NODE)
-// case CMD_NOP(CLOSE_NODE)
-// case CMD_INFO(ASSIGN_AS_VIEW) {
-// geo_writer->Write(ASSIGN_AS_VIEW);
-// geo_writer->Write(cur_geo_cmd_s16(0x02));
-// break;
-// }
-// case CMD_INFO(UPDATE_NODE_FLAGS) {
-// geo_writer->Write((uint8_t) UPDATE_NODE_FLAGS);
-// geo_writer->Write(cur_geo_cmd_u8(0x01));
-// geo_writer->Write(cur_geo_cmd_s16(0x02));
-// break;
-// }
-// case CMD_INFO(NODE_ROOT) {
-// auto a1 = cur_geo_cmd_s16(0x02);
-// auto a2 = cur_geo_cmd_s16(0x04);
-// auto a3 = cur_geo_cmd_s16(0x06);
-// auto a4 = cur_geo_cmd_s16(0x08);
-// auto a5 = cur_geo_cmd_s16(0x0A);
-// GeoWrite(GEO_NODE_SCREEN_AREA(a1, a2, a3, a4, a5));
-// cmd += 0x0C << CMD_SIZE_SHIFT;
-// processing = false;
-// }
-// case CMD_INFO(NODE_ORTHO_PROJECTION) {
-// geo_writer->Write((uint8_t) NODE_ORTHO_PROJECTION);
-// geo_writer->Write(cur_geo_cmd_s16(0x02));
-// cmd += 0x04 << CMD_SIZE_SHIFT;
-// break;
-// }
-// case CMD_INFO(NODE_PERSPECTIVE) {
-// geo_writer->Write((uint8_t) NODE_PERSPECTIVE);
-// auto param = cur_geo_cmd_u8(0x01);
-// auto fov = cur_geo_cmd_s16(0x02);
-// auto near = cur_geo_cmd_s16(0x04);
-// auto far = cur_geo_cmd_s16(0x06);
-//
-// geo_writer->Write(param);
-// geo_writer->Write(fov);
-// geo_writer->Write(near);
-// geo_writer->Write(far);
-//
-// if (param != 0) {
-// auto func = cur_geo_cmd_u32(0x08);
-// geo_writer->Write(func);
-// cmd += 4 << CMD_SIZE_SHIFT;
-// }
-//
-// cmd += 0x08 << CMD_SIZE_SHIFT;
-// break;
-// }
-// case CMD_NOP(NODE_START)
-// case CMD_INFO(NODE_MASTER_LIST) {
-// geo_writer->Write((uint8_t) NODE_MASTER_LIST);
-// geo_writer->Write(cur_geo_cmd_u8(0x01));
-// cmd += 0x04 << CMD_SIZE_SHIFT;
-// break;
-// }
-// case CMD_INFO(NODE_LEVEL_OF_DETAIL) {
-// geo_writer->Write((uint8_t) NODE_LEVEL_OF_DETAIL);
-// int16_t minDistance = cur_geo_cmd_s16(0x04);
-// int16_t maxDistance = cur_geo_cmd_s16(0x06);
-//
-// geo_writer->Write(minDistance);
-// geo_writer->Write(maxDistance);
-//
-// cmd += 0x08 << CMD_SIZE_SHIFT;
-// break;
-// }
-// case CMD_INFO(NODE_SWITCH_CASE) {
-// geo_writer->Write((uint8_t) NODE_SWITCH_CASE_OTR);
-// auto cs = cur_geo_cmd_s16(0x02);
-// auto ptr = cur_geo_cmd_u32(0x04);
-//
-// geo_writer->Write(cs);
-// geo_writer->Write(ptr);
-//
-// cmd += 0x08 << CMD_SIZE_SHIFT;
-// break;
-// }
-// case CMD_INFO(NODE_CAMERA) {
-// geo_writer->Write((uint8_t) NODE_CAMERA_OTR);
-// auto cmd_pos = (int16_t *) &cmd[4];
-// auto mode = cur_geo_cmd_s16(0x02);
-//
-// geo_writer->Write(mode);
-//
-// Vec3f pos, focus;
-//
-// cmd_pos = read_vec3s_to_vec3f(pos, cmd_pos);
-// read_vec3s_to_vec3f(focus, cmd_pos);
-//
-// geo_writer->Write(pos[0]);
-// geo_writer->Write(pos[1]);
-// geo_writer->Write(pos[2]);
-// geo_writer->Write(focus[0]);
-// geo_writer->Write(focus[1]);
-// geo_writer->Write(focus[2]);
-//
-// auto ptr = SEGMENT_OFFSET(BSWAP32(cur_geo_cmd_u32(0x10)));
-// geo_writer->Write(ptr);
-//
-// cmd += 0x14 << CMD_SIZE_SHIFT;
-// break;
-// }
-// case CMD_INFO(NODE_TRANSLATION_ROTATION) {
-// geo_writer->Write(NODE_TRANSLATION_ROTATION_OTR);
-// auto params = cur_geo_cmd_u8(0x01);
-// auto cmd_pos = (int16_t*) cmd;
-//
-// Vec3s translation, rotation;
-//
-// geo_writer->Write(params);
-//
-// switch ((params & 0x70) >> 4) {
-// case 0:
-// cmd_pos = read_vec3s(translation, &cmd_pos[2]);
-// geo_writer->Write(translation[0]);
-// geo_writer->Write(translation[1]);
-// geo_writer->Write(translation[2]);
-// cmd_pos = read_vec3s_angle(rotation, cmd_pos);
-// geo_writer->Write(rotation[0]);
-// geo_writer->Write(rotation[1]);
-// geo_writer->Write(rotation[2]);
-// break;
-// case 1:
-// cmd_pos = read_vec3s(translation, &cmd_pos[1]);
-// geo_writer->Write(translation[0]);
-// geo_writer->Write(translation[1]);
-// geo_writer->Write(translation[2]);
-// break;
-// case 2:
-// cmd_pos = read_vec3s_angle(rotation, &cmd_pos[1]);
-// geo_writer->Write(rotation[0]);
-// geo_writer->Write(rotation[1]);
-// geo_writer->Write(rotation[2]);
-// break;
-// case 3:
-// cmd_pos += 2 << CMD_SIZE_SHIFT;
-// break;
-// }
-//
-// if (params & 0x80) {
-// auto dlist = SEGMENT_OFFSET(BSWAP32(*(uint32_t*) &cmd_pos[0]));
-// auto decl = Companion::Instance->GetNodeByAddr(dlist);
-// if(decl.has_value()){
-// uint64_t hash = CRC64(std::get<0>(decl.value()).c_str());
-// SPDLOG_INFO("Found display list: 0x{:X} Hash: 0x{:X} Path: {}", dlist, hash, std::get<0>(decl.value()));
-// geo_writer->Write(hash);
-// } else {
-// SPDLOG_INFO("Warning: Could not find display list at 0x{:X}", dlist);
-// geo_writer->Write((uint64_t) 0);
-// }
-// cmd_pos += 2 << CMD_SIZE_SHIFT;
-// }
-//
-// cmd = (uint8_t*) cmd_pos;
-// break;
-// }
-// case CMD_INFO(NODE_TRANSLATION) {
-// geo_writer->Write(NODE_TRANSLATION_OTR);
-// auto params = cur_geo_cmd_u8(0x01);
-// auto cmd_pos = (int16_t*) cmd;
-//
-// Vec3s translation;
-// cmd_pos = read_vec3s(translation, &cmd_pos[1]);
-//
-// geo_writer->Write(translation[0]);
-// geo_writer->Write(translation[1]);
-// geo_writer->Write(translation[2]);
-//
-// if (params & 0x80) {
-// auto dlist = SEGMENT_OFFSET(BSWAP32(*(uint32_t*) &cmd_pos[0]));
-// auto decl = Companion::Instance->GetNodeByAddr(dlist);
-// if(decl.has_value()){
-// uint64_t hash = CRC64(std::get<0>(decl.value()).c_str());
-// SPDLOG_INFO("Found display list: 0x{:X} Hash: 0x{:X} Path: {}", dlist, hash, std::get<0>(decl.value()));
-// geo_writer->Write(hash);
-// } else {
-// SPDLOG_INFO("Warning: Could not find display list at 0x{:X}", dlist);
-// geo_writer->Write((uint64_t) 0);
-// }
-// cmd_pos += 2 << CMD_SIZE_SHIFT;
-// }
-//
-// cmd = (uint8_t*) cmd_pos;
-// break;
-// }
-// case CMD_INFO(NODE_ROTATION) {
-// geo_writer->Write(NODE_ROTATION_OTR);
-// auto params = cur_geo_cmd_u8(0x01);
-// auto cmd_pos = (int16_t*) cmd;
-//
-// Vec3s sp2c;
-// cmd_pos = read_vec3s(sp2c, &cmd_pos[1]);
-//
-// geo_writer->Write(sp2c[0]);
-// geo_writer->Write(sp2c[1]);
-// geo_writer->Write(sp2c[2]);
-//
-// if (params & 0x80) {
-// auto dlist = SEGMENT_OFFSET(BSWAP32(*(uint32_t*) &cmd_pos[0]));
-// auto decl = Companion::Instance->GetNodeByAddr(dlist);
-// if(decl.has_value()){
-// uint64_t hash = CRC64(std::get<0>(decl.value()).c_str());
-// SPDLOG_INFO("Found display list: 0x{:X} Hash: 0x{:X} Path: {}", dlist, hash, std::get<0>(decl.value()));
-// geo_writer->Write(hash);
-// } else {
-// SPDLOG_INFO("Warning: Could not find display list at 0x{:X}", dlist);
-// geo_writer->Write((uint64_t) 0);
-// }
-// cmd_pos += 2 << CMD_SIZE_SHIFT;
-// }
-//
-// cmd = (uint8_t*) cmd_pos;
-// break;
-// }
-// case CMD_INFO(NODE_ANIMATED_PART) {
-// geo_writer->Write(NODE_ANIMATED_PART_OTR);
-//
-// auto layer = cur_geo_cmd_u8(0x01);
-// auto ptr = cur_geo_cmd_u32(0x08);
-//
-// geo_writer->Write(layer);
-// geo_writer->Write(ptr);
-//
-// auto dlist = SEGMENT_OFFSET(BSWAP32(cur_geo_cmd_u32(0x08)));
-// auto decl = Companion::Instance->GetNodeByAddr(dlist);
-// if(decl.has_value()){
-// uint64_t hash = CRC64(std::get<0>(decl.value()).c_str());
-// SPDLOG_INFO("Found display list: 0x{:X} Hash: 0x{:X} Path: {}", dlist, hash, std::get<0>(decl.value()));
-// geo_writer->Write(hash);
-// } else {
-// SPDLOG_INFO("Warning: Could not find display list at 0x{:X}", dlist);
-// geo_writer->Write((uint64_t) 0);
-// }
-//
-// cmd += 0x0C << CMD_SIZE_SHIFT;
-// break;
-// }
-// case CMD_INFO(NODE_BILLBOARD) {
-// geo_writer->Write(NODE_BILLBOARD_OTR);
-//
-// Vec3s translation;
-// auto params = cur_geo_cmd_u8(0x01);
-// auto cmd_pos = (int16_t*) cmd;
-//
-// cmd_pos = read_vec3s(translation, &cmd_pos[1]);
-// geo_writer->Write(params);
-// if (params & 0x80) {
-// auto dlist = SEGMENT_OFFSET(BSWAP32(*(uint32_t*) &cmd_pos[0]));
-// auto decl = Companion::Instance->GetNodeByAddr(dlist);
-// if (decl.has_value()) {
-// uint64_t hash = CRC64(std::get<0>(decl.value()).c_str());
-// SPDLOG_INFO("Found display list: 0x{:X} Hash: 0x{:X} Path: {}", dlist, hash,
-// std::get<0>(decl.value()));
-// geo_writer->Write(hash);
-// } else {
-// SPDLOG_INFO("Warning: Could not find display list at 0x{:X}", dlist);
-// geo_writer->Write((uint64_t) 0);
-// }
-//
-// cmd_pos += 2 << CMD_SIZE_SHIFT;
-// }
-//
-// cmd = (uint8_t*) cmd_pos;
-// break;
-// }
-// case CMD_INFO(NODE_DISPLAY_LIST) {
-// geo_writer->Write((uint8_t) NODE_DISPLAY_LIST_OTR);
-//
-// int32_t layer = cur_geo_cmd_u8(0x01);
-// auto ptr = SEGMENT_OFFSET(BSWAP32(cur_geo_cmd_u32(0x04)));
-//
-// geo_writer->Write(layer);
-//
-// auto decl = Companion::Instance->GetNodeByAddr(ptr);
-//
-// if(decl.has_value()){
-// uint64_t hash = CRC64(std::get<0>(decl.value()).c_str());
-// SPDLOG_INFO("Found display list: 0x{:X} Hash: 0x{:X} Path: {}", ptr, hash, std::get<0>(decl.value()));
-// geo_writer->Write(hash);
-// } else {
-// SPDLOG_INFO("Warning: Could not find display list at 0x{:X}", ptr);
-// geo_writer->Write((uint64_t) 0);
-// }
-//
-// cmd += 0x08 << CMD_SIZE_SHIFT;
-// break;
-// }
-// case CMD_INFO(NODE_SHADOW) {
-// geo_writer->Write((uint8_t) NODE_SHADOW);
-// auto type = cur_geo_cmd_s16(0x02);
-// auto solidity = cur_geo_cmd_s16(0x04);
-// auto scale = cur_geo_cmd_s16(0x06);
-//
-// geo_writer->Write(type);
-// geo_writer->Write(solidity);
-// geo_writer->Write(scale);
-//
-// cmd += 0x08 << CMD_SIZE_SHIFT;
-// break;
-// }
-// case CMD_NOP(NODE_OBJECT_PARENT)
-// case CMD_INFO(NODE_ASM) {
-// geo_writer->Write(NODE_ASM_OTR);
-// auto param = cur_geo_cmd_s16(0x02);
-// auto ptr = cur_geo_cmd_u32(0x04);
-//
-// geo_writer->Write(param);
-// geo_writer->Write(SEGMENT_OFFSET(BSWAP32(ptr)));
-// cmd += 0x08 << CMD_SIZE_SHIFT;
-// break;
-// }
-// case CMD_INFO(NODE_BACKGROUND) {
-// geo_writer->Write((uint8_t) NODE_BACKGROUND_OTR);
-// auto bg = cur_geo_cmd_s16(0x02);
-// geo_writer->Write(bg);
-//
-// auto ptr = SEGMENT_OFFSET(BSWAP32(cur_geo_cmd_u32(0x04)));
-// geo_writer->Write(ptr);
-//
-// cmd += 0x08 << CMD_SIZE_SHIFT;
-// break;
-// }
-// case CMD_INFO(NOP) {
-// geo_writer->Write((uint8_t) NOP);
-// geo_writer->Write((uint32_t) 0);
-// geo_writer->Write((uint32_t) 0);
-// cmd += 0x08 << CMD_SIZE_SHIFT;
-// break;
-// }
-// case CMD_INFO(COPY_VIEW) {
-// geo_writer->Write((uint32_t) COPY_VIEW);
-// auto idx = cur_geo_cmd_s16(0x02);
-// geo_writer->Write(idx);
-// break;
-// }
-// case CMD_INFO(NODE_HELD_OBJ) {
-// geo_writer->Write((uint8_t) NODE_HELD_OBJ_OTR);
-//
-// auto idx = cur_geo_cmd_u8(0x01);
-// geo_writer->Write(idx);
-//
-// Vec3s c_offset;
-// read_vec3s(c_offset, (int16_t*) &cmd[0x02]);
-//
-// geo_writer->Write(c_offset[0]);
-// geo_writer->Write(c_offset[1]);
-// geo_writer->Write(c_offset[2]);
-//
-// auto ptr = SEGMENT_OFFSET(BSWAP32(cur_geo_cmd_u32(0x08)));
-// geo_writer->Write(ptr);
-//
-// cmd += 0x0C << CMD_SIZE_SHIFT;
-// break;
-// }
-// case CMD_INFO(NODE_SCALE) {
-// geo_writer->Write(NODE_SCALE_OTR);
-// auto params = cur_geo_cmd_u8(0x01);
-// auto scale = cur_geo_cmd_u32(0x04);
-//
-// geo_writer->Write(params);
-// geo_writer->Write(scale);
-//
-// if (params & 0x80) {
-// auto dlist = SEGMENT_OFFSET(BSWAP32(cur_geo_cmd_u32(0x08)));
-// auto decl = Companion::Instance->GetNodeByAddr(dlist);
-// if(decl.has_value()){
-// uint64_t hash = CRC64(std::get<0>(decl.value()).c_str());
-// SPDLOG_INFO("Found display list: 0x{:X} Hash: 0x{:X} Path: {}", dlist, hash, std::get<0>(decl.value()));
-// geo_writer->Write(hash);
-// } else {
-// SPDLOG_INFO("Warning: Could not find display list at 0x{:X}", dlist);
-// geo_writer->Write((uint64_t) 0);
-// }
-// cmd += 4 << CMD_SIZE_SHIFT;
-// }
-// break;
-// }
-// case CMD_INFO(NOP2) {
-// geo_writer->Write((uint8_t) NOP2);
-// geo_writer->Write((uint32_t) 0);
-// geo_writer->Write((uint32_t) 0);
-// cmd += 0x08 << CMD_SIZE_SHIFT;
-// break;
-// }
-// case CMD_INFO(NOP3) {
-// geo_writer->Write((uint8_t) NOP3);
-// geo_writer->Write((uint32_t) 0);
-// geo_writer->Write((uint32_t) 0);
-// geo_writer->Write((uint32_t) 0);
-// cmd += 0x10 << CMD_SIZE_SHIFT;
-// break;
-// }
-// case CMD_INFO(NODE_CULLING_RADIUS) {
-// geo_writer->Write((uint8_t) NODE_CULLING_RADIUS);
-// auto radius = cur_geo_cmd_s16(0x02);
-// geo_writer->Write(radius);
-// break;
-// }
-// default:
-// std::cout << "Unknown command: " << std::hex << (int) cmd[0x00] << std::endl;
-// break;
-// }
-// }
-
- // auto size = geo_writer->GetLength();
- // auto data_ptr = geo_writer->ToVector(); \ No newline at end of file
diff --git a/src/factories/sm64/TextFactory.cpp b/src/factories/sm64/TextFactory.cpp
index e32d3ce..303cdac 100644
--- a/src/factories/sm64/TextFactory.cpp
+++ b/src/factories/sm64/TextFactory.cpp
@@ -1,5 +1,5 @@
#include "TextFactory.h"
-#include "utils/MIODecoder.h"
+#include "utils/Decompressor.h"
void SM64::TextBinaryExporter::Export(std::ostream &write, std::shared_ptr<IParsedData> raw, std::string& entryName, YAML::Node &node, std::string* replacement ) {
auto writer = LUS::BinaryWriter();
@@ -11,16 +11,14 @@ void SM64::TextBinaryExporter::Export(std::ostream &write, std::shared_ptr<IPars
writer.Finish(write);
}
-std::optional<std::shared_ptr<IParsedData>> SM64::TextFactory::parse(std::vector<uint8_t>& buffer, YAML::Node& data) {
- auto offset = data["offset"].as<size_t>();
- auto mio0 = data["mio0"].as<size_t>();
+std::optional<std::shared_ptr<IParsedData>> SM64::TextFactory::parse(std::vector<uint8_t>& buffer, YAML::Node& node) {
std::vector<uint8_t> text;
- auto decoded = MIO0Decoder::Decode(buffer, offset);
- auto bytes = (uint8_t*) decoded.data();
+ auto [_, segment] = Decompressor::AutoDecode(node, buffer);
+ size_t idx = 0;
- while(bytes[mio0] != 0xFF){
- auto c = bytes[mio0++];
+ while(segment.data[idx] != 0xFF){
+ auto c = segment.data[idx++];
text.push_back(c);
}
text.push_back(0xFF);
diff --git a/src/utils/Decompressor.cpp b/src/utils/Decompressor.cpp
new file mode 100644
index 0000000..064adc6
--- /dev/null
+++ b/src/utils/Decompressor.cpp
@@ -0,0 +1,124 @@
+#include "Decompressor.h"
+
+#include <stdexcept>
+#include "spdlog/spdlog.h"
+#include <Companion.h>
+
+extern "C" {
+#include <libmio0/mio0.h>
+}
+
+std::unordered_map<uint32_t, DataChunk*> gCachedChunks;
+
+DataChunk* Decompressor::Decode(const std::vector<uint8_t>& buffer, const uint32_t offset, const CompressionType type) {
+
+ if(gCachedChunks.contains(offset)){
+ return gCachedChunks[offset];
+ }
+
+ const unsigned char* in_buf = buffer.data() + offset;
+
+ switch (type) {
+ case CompressionType::MIO0: {
+
+ mio0_header_t head;
+ if(!mio0_decode_header(in_buf, &head)){
+ throw std::runtime_error("Failed to decode MIO0 header");
+ }
+
+ const auto decompressed = new uint8_t[head.dest_size];
+ mio0_decode(in_buf, decompressed, nullptr);
+ gCachedChunks[offset] = new DataChunk{ decompressed, head.dest_size };
+ return gCachedChunks[offset];
+ }
+ default:
+ throw std::runtime_error("Unknown compression type");
+ }
+}
+
+DecompressedData Decompressor::AutoDecode(YAML::Node& node, std::vector<uint8_t>& buffer) {
+ if(!node["offset"]){
+ throw std::runtime_error("Failed to find offset");
+ }
+
+ const auto offset = TranslateAddr(node["offset"].as<uint32_t>());
+
+ if(node["mio0"]){
+ const auto mio0 = node["mio0"].as<uint32_t>();
+ auto decoded = Decode(buffer, offset, CompressionType::MIO0);
+ auto size = node["size"] ? node["size"].as<size_t>() : decoded->size - mio0;
+
+ return {
+ .root = decoded,
+ .segment = { decoded->data + mio0, size }
+ };
+ }
+
+ if(node["yay0"]){
+ throw std::runtime_error("Yay0 not implemented");
+ }
+
+ if(node["yaz0"]){
+ throw std::runtime_error("Yaz0 not implemented");
+ }
+
+ return {
+ .root = nullptr,
+ .segment = { buffer.data() + offset, buffer.size() - offset }
+ };
+}
+
+uint32_t Decompressor::TranslateAddr(uint32_t addr){
+ if(IS_SEGMENTED(addr)){
+ const auto segment = Companion::Instance->GetSegmentedAddr(SEGMENT_NUMBER(addr));
+
+ if(!segment.has_value()) {
+ SPDLOG_ERROR("Segment data missing from game config\nPlease add an entry for segment {}", SEGMENT_NUMBER(addr));
+ return 0;
+ }
+
+ return segment.value() + SEGMENT_OFFSET(addr);
+ }
+
+ return addr;
+}
+
+bool Decompressor::IsSegmented(uint32_t addr) {
+ if(IS_SEGMENTED(addr)){
+ const auto segment = Companion::Instance->GetSegmentedAddr(SEGMENT_NUMBER(addr));
+
+ if(!segment.has_value()) {
+ SPDLOG_ERROR("Segment data missing from game config\nPlease add an entry for segment {}", SEGMENT_NUMBER(addr));
+ return false;
+ }
+
+ return true;
+ }
+
+ return false;
+}
+
+bool Decompressor::IsCompressed(YAML::Node& node) {
+ return node["mio0"] || node["yay0"] || node["yaz0"];
+}
+
+void Decompressor::CopyCompression(YAML::Node& from, YAML::Node& to){
+ if(from["mio0"]){
+ to["mio0"] = from["mio0"];
+ }
+
+ if(from["yay0"]){
+ to["yay0"] = from["yay0"];
+ }
+
+ if(from["yaz0"]){
+ to["yaz0"] = from["yaz0"];
+ }
+}
+
+void Decompressor::ClearCache() {
+ for(auto& [key, value] : gCachedChunks){
+ delete value->data;
+ }
+ gCachedChunks.clear();
+}
diff --git a/src/utils/Decompressor.h b/src/utils/Decompressor.h
new file mode 100644
index 0000000..1bd5c05
--- /dev/null
+++ b/src/utils/Decompressor.h
@@ -0,0 +1,36 @@
+#pragma once
+
+#include <vector>
+#include <cstdint>
+#include <unordered_map>
+#include <yaml-cpp/yaml.h>
+
+enum class CompressionType {
+ MIO0,
+ Yay0,
+ Yaz0,
+ None,
+};
+
+
+struct DataChunk {
+ uint8_t* data;
+ size_t size;
+};
+
+struct DecompressedData {
+ DataChunk* root;
+ DataChunk segment;
+};
+
+class Decompressor {
+public:
+ static DataChunk* Decode(const std::vector<uint8_t>& buffer, uint32_t offset, CompressionType type);
+ static DecompressedData AutoDecode(YAML::Node& node, std::vector<uint8_t>& buffer);
+ static uint32_t TranslateAddr(uint32_t addr);
+ static bool IsSegmented(uint32_t addr);
+ static bool IsCompressed(YAML::Node& node);
+ static void CopyCompression(YAML::Node& from, YAML::Node& to);
+
+ static void ClearCache();
+}; \ No newline at end of file
diff --git a/src/utils/MIODecoder.cpp b/src/utils/MIODecoder.cpp
deleted file mode 100644
index 7574e55..0000000
--- a/src/utils/MIODecoder.cpp
+++ /dev/null
@@ -1,28 +0,0 @@
-#include "MIODecoder.h"
-#include <stdexcept>
-
-extern "C" {
-#include <libmio0/mio0.h>
-}
-
-std::unordered_map<uint32_t, std::vector<uint8_t>> MIO0Decoder::gCachedChunks;
-
-std::vector<uint8_t>& MIO0Decoder::Decode(std::vector<uint8_t>& buffer, uint32_t offset) {
- const unsigned char* in_buf = buffer.data() + offset;
-
- mio0_header_t head;
- if(!mio0_decode_header(in_buf, &head)){
- throw std::runtime_error("Failed to decode MIO0 header");
- }
-
- auto decompressed = new uint8_t[head.dest_size];
- mio0_decode(in_buf, decompressed, nullptr);
- gCachedChunks[offset] = std::vector<uint8_t>(decompressed, decompressed + head.dest_size);
-
- delete[] decompressed;
- return gCachedChunks[offset];
-}
-
-void MIO0Decoder::ClearCache() {
- gCachedChunks.clear();
-}
diff --git a/src/utils/MIODecoder.h b/src/utils/MIODecoder.h
deleted file mode 100644
index ecf2ca4..0000000
--- a/src/utils/MIODecoder.h
+++ /dev/null
@@ -1,12 +0,0 @@
-#pragma once
-
-#include <vector>
-#include <unordered_map>
-#include <cstdint>
-
-class MIO0Decoder {
-public:
- static std::unordered_map<uint32_t, std::vector<uint8_t>> gCachedChunks;
- static std::vector<uint8_t>& Decode(std::vector<uint8_t>& buffer, uint32_t offset);
- static void ClearCache();
-};