From 371f8140461ef46769a7a7c6e17b5fa02729aaad Mon Sep 17 00:00:00 2001 From: KiritoDv Date: Sat, 9 Mar 2024 23:12:39 -0600 Subject: [PATCH] Refactored vtx overlap function --- src/Companion.cpp | 21 +++++++ src/Companion.h | 1 + src/factories/DisplayListFactory.cpp | 87 +++++++++++++++++++------- src/factories/DisplayListFactory.h | 1 + src/factories/DisplayListOverrides.cpp | 41 ++++++++++++ src/factories/DisplayListOverrides.h | 8 ++- 6 files changed, 135 insertions(+), 24 deletions(-) diff --git a/src/Companion.cpp b/src/Companion.cpp index 7cf9b50c..73749e77 100644 --- a/src/Companion.cpp +++ b/src/Companion.cpp @@ -14,6 +14,7 @@ #include "factories/VtxFactory.h" #include "factories/TextureFactory.h" #include "factories/DisplayListFactory.h" +#include "factories/DisplayListOverrides.h" #include "factories/BlobFactory.h" #include "factories/LightsFactory.h" #include "factories/mk64/CourseVtx.h" @@ -482,6 +483,7 @@ void Companion::Process() { this->gConfig.segment.local.clear(); this->gFileHeader.clear(); this->gCurrentPad = 0; + GFXDOverride::ClearVtx(); if(root[":config"]) { this->ParseCurrentFileConfig(root[":config"]); @@ -783,6 +785,25 @@ std::optional> Companion::GetNodeByAddr(cons return this->gAddrMap[this->gCurrentFile][addr]; } +std::optional>> Companion::GetNodesByType(const std::string& type){ + std::vector> nodes; + + if(!this->gAddrMap.contains(this->gCurrentFile)){ + return nodes; + } + + for(auto& [addr, tpl] : this->gAddrMap[this->gCurrentFile]){ + auto [name, node] = tpl; + const auto n_type = GetSafeNode(node, "type"); + if(n_type == type){ + nodes.push_back(tpl); + } + } + + return nodes; + +} + std::string Companion::NormalizeAsset(const std::string& name) const { auto path = fs::path(this->gCurrentFile).stem().string() + "_" + name; return path; diff --git a/src/Companion.h b/src/Companion.h index fbde3512..8f8f98cc 100644 --- a/src/Companion.h +++ b/src/Companion.h @@ -76,6 +76,7 @@ class Companion { std::optional GetFileOffsetFromSegmentedAddr(uint8_t segment) const; std::optional> GetNodeByAddr(uint32_t addr); std::optional> GetFactory(const std::string& type); + std::optional>> GetNodesByType(const std::string& type); std::optional GetFileOffset(void) const { return this->gCurrentFileOffset; }; std::optional GetCurrSegmentNumber(void) const { return this->gCurrentSegmentNumber; }; diff --git a/src/factories/DisplayListFactory.cpp b/src/factories/DisplayListFactory.cpp index d5197cc6..cb1988fd 100644 --- a/src/factories/DisplayListFactory.cpp +++ b/src/factories/DisplayListFactory.cpp @@ -9,6 +9,7 @@ #include "n64/gbi-otr.h" #define C0(pos, width) ((w0 >> (pos)) & ((1U << width) - 1)) +#define ALIGN16(val) (((val) + 0xF) & ~0xF) std::unordered_map gF3DTable = { { "G_VTX", 0x04 }, @@ -146,6 +147,28 @@ void DebugDisplayList(uint32_t w0, uint32_t w1){ gfxd_execute(); } +std::optional> SearchVtx(uint32_t ptr){ + auto decs = Companion::Instance->GetNodesByType("VTX"); + + if(!decs.has_value()){ + return std::nullopt; + } + + for(auto& dec : decs.value()){ + auto [name, node] = dec; + + auto offset = GetSafeNode(node, "offset"); + auto count = GetSafeNode(node, "count"); + auto end = ALIGN16((count * sizeof(Vtx_t))); + + if(ptr > offset && ptr <= offset + end){ + return std::make_tuple(GetSafeNode(node, "symbol", name), node); + } + } + + return std::nullopt; +} + void DListBinaryExporter::Export(std::ostream &write, std::shared_ptr raw, std::string& entryName, YAML::Node &node, std::string* replacement ) { auto cmds = std::static_pointer_cast(raw)->mGfxs; auto writer = LUS::BinaryWriter(); @@ -387,39 +410,57 @@ std::optional> DListFactory::parse(std::vectorGetNodeByAddr(w1); - 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); + if(!decl.has_value()){ + auto search = SearchVtx(w1); - auto ptr = w1; - auto rom = Companion::Instance->GetRomData(); - auto factory = Companion::Instance->GetFactory("VTX")->get(); + if(search.has_value()){ + auto [path, vtx] = search.value(); - std::string output; - YAML::Node vtx; + SPDLOG_INFO("Path: {}", path); - if(Decompressor::IsSegmented(w1)){ - SPDLOG_INFO("Found segmented vtx at 0x{:X}", ptr); - ptr = w1; - output = Companion::Instance->NormalizeAsset("seg" + std::to_string(SEGMENT_NUMBER(w1)) +"_vtx_" + Torch::to_hex(SEGMENT_OFFSET(ptr), false)); + auto lOffset = GetSafeNode(vtx, "offset"); + auto lCount = GetSafeNode(vtx, "count"); + auto lSize = ALIGN16(lCount * sizeof(Vtx_t)); + + if(w1 > lOffset && w1 <= lOffset + lSize){ + SPDLOG_INFO("Found vtx at 0x{:X} matching last vtx at 0x{:X}", w1, lOffset); + GFXDOverride::RegisterVTXOverlap(w1, search.value()); + } } else { - SPDLOG_INFO("Found vtx at 0x{:X}", ptr); - output = Companion::Instance->NormalizeAsset("vtx_" + Torch::to_hex(w1, false)); - } + SPDLOG_INFO("Addr to Vtx array at 0x{:X} not in yaml, autogenerating it", w1); + + auto ptr = w1; + auto rom = Companion::Instance->GetRomData(); + auto factory = Companion::Instance->GetFactory("VTX")->get(); + + std::string output; + YAML::Node vtx; + + if(Decompressor::IsSegmented(w1)){ + SPDLOG_INFO("Creating segmented vtx from 0x{:X}", ptr); + ptr = w1; + output = Companion::Instance->NormalizeAsset("seg" + std::to_string(SEGMENT_NUMBER(w1)) +"_vtx_" + Torch::to_hex(SEGMENT_OFFSET(ptr), false)); + } else { + SPDLOG_INFO("Creating vtx from 0x{:X}", ptr); + output = Companion::Instance->NormalizeAsset("vtx_" + Torch::to_hex(w1, false)); + } - vtx["type"] = "VTX"; - vtx["offset"] = ptr; - vtx["count"] = nvtx; - vtx["symbol"] = output; - auto result = factory->parse(rom, vtx); - if(result.has_value()){ - Companion::Instance->RegisterAsset(output, vtx); + vtx["type"] = "VTX"; + vtx["offset"] = ptr; + vtx["count"] = nvtx; + vtx["symbol"] = output; + auto result = factory->parse(rom, vtx); + if(result.has_value()){ + Companion::Instance->RegisterAsset(output, vtx); + } } } else { - SPDLOG_WARN("Could not find vtx at 0x{:X}", w1); + SPDLOG_WARN("Found vtx at 0x{:X}", w1); } } diff --git a/src/factories/DisplayListFactory.h b/src/factories/DisplayListFactory.h index 3c9116e7..1bdc87ee 100644 --- a/src/factories/DisplayListFactory.h +++ b/src/factories/DisplayListFactory.h @@ -2,6 +2,7 @@ #include "BaseFactory.h" #include "n64/CommandMacros.h" +#include class DListData : public IParsedData { public: diff --git a/src/factories/DisplayListOverrides.cpp b/src/factories/DisplayListOverrides.cpp index 52a832d8..32c9b5c0 100644 --- a/src/factories/DisplayListOverrides.cpp +++ b/src/factories/DisplayListOverrides.cpp @@ -10,6 +10,8 @@ namespace GFXDOverride { +std::unordered_map> mVtxOverlaps; + void Triangle2(const Gfx* gfx) { auto w0 = gfx->words.w0; auto w1 = gfx->words.w1; @@ -47,6 +49,25 @@ void Quadrangle(const Gfx* gfx) { } int Vtx(uint32_t ptr, int32_t num) { + auto vtx = GetVtxOverlap(ptr); + + if(vtx.has_value()){ + auto symbol = std::get<0>(vtx.value()); + auto node = std::get<1>(vtx.value()); + + auto offset = GetSafeNode(node, "offset"); + auto count = GetSafeNode(node, "count"); + auto idx = (ptr - offset) / sizeof(Vtx_t); + + SPDLOG_INFO("Replaced Vtx Overlapped: 0x{:X} Symbol: {}", ptr, symbol); + gfxd_puts("&"); + gfxd_puts(symbol.c_str()); + gfxd_puts("["); + gfxd_puts(std::to_string(idx).c_str()); + gfxd_puts("]"); + return 1; + } + auto dec = Companion::Instance->GetNodeByAddr(ptr); if(dec.has_value()){ @@ -120,4 +141,24 @@ int DisplayList(uint32_t ptr) { SPDLOG_WARN("Could not find display list to override at 0x{:X}", ptr); return 0; } + +std::optional> GetVtxOverlap(uint32_t ptr){ + if(mVtxOverlaps.contains(ptr)){ + SPDLOG_INFO("Found overlap for ptr 0x{:X}", ptr); + return mVtxOverlaps[ptr]; + } + + SPDLOG_INFO("Failed to find overlap for ptr 0x{:X}", ptr); + + return std::nullopt; +} + +void RegisterVTXOverlap(uint32_t ptr, std::tuple& vtx){ + mVtxOverlaps[ptr] = vtx; + SPDLOG_INFO("Register overlap for ptr 0x{:X}", ptr); +} + +void ClearVtx(){ + mVtxOverlaps.clear(); +} } diff --git a/src/factories/DisplayListOverrides.h b/src/factories/DisplayListOverrides.h index 77734ca4..2da6c526 100644 --- a/src/factories/DisplayListOverrides.h +++ b/src/factories/DisplayListOverrides.h @@ -1,7 +1,10 @@ #pragma once -#include #include "DisplayListFactory.h" +#include +#include +#include +#include typedef struct { uint32_t w0; @@ -41,4 +44,7 @@ int Texture(uint32_t timg, int32_t fmt, int32_t siz, int32_t width, int32_t hei int Palette(uint32_t tlut, int32_t idx, int32_t count); int Light(uint32_t lightsn, int32_t count); int DisplayList(uint32_t dl); +void RegisterVTXOverlap(uint32_t ptr, std::tuple& vtx); +std::optional> GetVtxOverlap(uint32_t ptr); +void ClearVtx(); }; \ No newline at end of file