Refactored code and added per file config

This commit is contained in:
KiritoDv
2024-01-31 12:05:40 -06:00
committed by Lywx
parent 242f8acf21
commit 4668cf08fb
22 changed files with 321 additions and 751 deletions
+3 -3
View File
@@ -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
View File
@@ -1,5 +1,4 @@
#include "BankFactory.h"
#include "utils/MIODecoder.h"
#include "Companion.h"
#include "audio/samples_table.h"
+27
View File
@@ -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>
+5 -15
View File
@@ -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);
}
+51 -109
View File
@@ -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);
}
}
+5 -5
View File
@@ -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;
+7 -9
View File
@@ -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
View File
@@ -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();
+6 -7
View File
@@ -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);
}
+16 -24
View File
@@ -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){
+7 -9
View File
@@ -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;
+6 -8
View File
@@ -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;
+9 -10
View File
@@ -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());
+7 -9
View File
@@ -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);
+5 -6
View File
@@ -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 -2
View File
@@ -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;
-485
View File
@@ -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();
+6 -8
View File
@@ -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);
+124
View File
@@ -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();
}
+36
View File
@@ -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