summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/Companion.cpp21
-rw-r--r--src/Companion.h1
-rw-r--r--src/factories/DisplayListFactory.cpp87
-rw-r--r--src/factories/DisplayListFactory.h1
-rw-r--r--src/factories/DisplayListOverrides.cpp41
-rw-r--r--src/factories/DisplayListOverrides.h8
6 files changed, 135 insertions, 24 deletions
diff --git a/src/Companion.cpp b/src/Companion.cpp
index 441f596..81044b3 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<std::tuple<std::string, YAML::Node>> Companion::GetNodeByAddr(cons
return this->gAddrMap[this->gCurrentFile][addr];
}
+std::optional<std::vector<std::tuple<std::string, YAML::Node>>> Companion::GetNodesByType(const std::string& type){
+ std::vector<std::tuple<std::string, YAML::Node>> 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<std::string>(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 fbde351..8f8f98c 100644
--- a/src/Companion.h
+++ b/src/Companion.h
@@ -76,6 +76,7 @@ public:
std::optional<std::uint32_t> GetFileOffsetFromSegmentedAddr(uint8_t segment) const;
std::optional<std::tuple<std::string, YAML::Node>> GetNodeByAddr(uint32_t addr);
std::optional<std::shared_ptr<BaseFactory>> GetFactory(const std::string& type);
+ std::optional<std::vector<std::tuple<std::string, YAML::Node>>> GetNodesByType(const std::string& type);
std::optional<std::uint32_t> GetFileOffset(void) const { return this->gCurrentFileOffset; };
std::optional<std::uint32_t> GetCurrSegmentNumber(void) const { return this->gCurrentSegmentNumber; };
diff --git a/src/factories/DisplayListFactory.cpp b/src/factories/DisplayListFactory.cpp
index 59e0321..2310588 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<std::string, uint8_t> gF3DTable = {
{ "G_VTX", 0x04 },
@@ -159,6 +160,28 @@ void DebugDisplayList(uint32_t w0, uint32_t w1){
gfxd_execute();
}
+std::optional<std::tuple<std::string, YAML::Node>> 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<uint32_t>(node, "offset");
+ auto count = GetSafeNode<uint32_t>(node, "count");
+ auto end = ALIGN16((count * sizeof(Vtx_t)));
+
+ if(ptr > offset && ptr <= offset + end){
+ return std::make_tuple(GetSafeNode<std::string>(node, "symbol", name), node);
+ }
+ }
+
+ return std::nullopt;
+}
+
void DListBinaryExporter::Export(std::ostream &write, std::shared_ptr<IParsedData> raw, std::string& entryName, YAML::Node &node, std::string* replacement ) {
auto cmds = std::static_pointer_cast<DListData>(raw)->mGfxs;
auto writer = LUS::BinaryWriter();
@@ -400,39 +423,57 @@ std::optional<std::shared_ptr<IParsedData>> DListFactory::parse(std::vector<uint
nvtx = C0(10, 6);
break;
default:
- nvtx = (C0(0, 16)) / sizeof(Vtx);
+ nvtx = (C0(0, 16)) / sizeof(Vtx_t);
break;
}
+ const auto decl = Companion::Instance->GetNodeByAddr(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<uint32_t>(vtx, "offset");
+ auto lCount = GetSafeNode<uint32_t>(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 3c9116e..1bdc87e 100644
--- a/src/factories/DisplayListFactory.h
+++ b/src/factories/DisplayListFactory.h
@@ -2,6 +2,7 @@
#include "BaseFactory.h"
#include "n64/CommandMacros.h"
+#include <tuple>
class DListData : public IParsedData {
public:
diff --git a/src/factories/DisplayListOverrides.cpp b/src/factories/DisplayListOverrides.cpp
index 52a832d..32c9b5c 100644
--- a/src/factories/DisplayListOverrides.cpp
+++ b/src/factories/DisplayListOverrides.cpp
@@ -10,6 +10,8 @@
namespace GFXDOverride {
+std::unordered_map<uint32_t, std::tuple<std::string, YAML::Node>> 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<uint32_t>(node, "offset");
+ auto count = GetSafeNode<uint32_t>(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<std::tuple<std::string, YAML::Node>> 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<std::string, YAML::Node>& 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 77734ca..2da6c52 100644
--- a/src/factories/DisplayListOverrides.h
+++ b/src/factories/DisplayListOverrides.h
@@ -1,7 +1,10 @@
#pragma once
-#include <cstdint>
#include "DisplayListFactory.h"
+#include <yaml-cpp/yaml.h>
+#include <cstdint>
+#include <tuple>
+#include <string>
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<std::string, YAML::Node>& vtx);
+std::optional<std::tuple<std::string, YAML::Node>> GetVtxOverlap(uint32_t ptr);
+void ClearVtx();
}; \ No newline at end of file