mirror of
https://github.com/izzy2lost/Torch.git
synced 2026-07-06 00:18:35 -07:00
Refactored code and added per file config
This commit is contained in:
+3
-3
@@ -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;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
#include "BankFactory.h"
|
||||
#include "utils/MIODecoder.h"
|
||||
#include "Companion.h"
|
||||
#include "audio/samples_table.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>
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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};
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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){
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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++];
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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();
|
||||
};
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user