summaryrefslogtreecommitdiff
path: root/src/factories/DisplayListFactory.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/factories/DisplayListFactory.cpp')
-rw-r--r--src/factories/DisplayListFactory.cpp72
1 files changed, 59 insertions, 13 deletions
diff --git a/src/factories/DisplayListFactory.cpp b/src/factories/DisplayListFactory.cpp
index 60344f6..144d666 100644
--- a/src/factories/DisplayListFactory.cpp
+++ b/src/factories/DisplayListFactory.cpp
@@ -4,6 +4,7 @@
#include "spdlog/spdlog.h"
#include "Companion.h"
#include <fstream>
+#include <tuple>
#include "n64/gbi-otr.h"
#ifdef STANDALONE
@@ -195,21 +196,32 @@ void DebugDisplayList(uint32_t w0, uint32_t w1) {
#endif
std::optional<std::tuple<std::string, YAML::Node>> SearchVtx(uint32_t ptr) {
- auto decs = Companion::Instance->GetNodesByType("VTX");
-
- if (!decs.has_value()) {
+ const auto* decs = Companion::Instance->GetNodesByTypeRef("VTX", Companion::Instance->GetConfig().includeAutogen);
+ if (decs == nullptr) {
return std::nullopt;
}
- for (auto& dec : decs.value()) {
- auto [name, node] = dec;
+ auto realAddr = ptr;
+ bool hasRealAddr = false;
+ if (IS_SEGMENTED(realAddr) && Companion::Instance->GetCompressedSegmentOffset(&realAddr)) {
+ hasRealAddr = true;
+ }
+
+ for (const auto& dec : *decs) {
+ const auto& [name, node] = dec;
- auto offset = GetSafeNode<uint32_t>(node, "offset");
- auto count = GetSafeNode<uint32_t>(node, "count");
+ auto offset = GetSafeNode<uint32_t>(const_cast<YAML::Node&>(node), "offset");
+ auto count = GetSafeNode<uint32_t>(const_cast<YAML::Node&>(node), "count");
auto end = ALIGN16((count * sizeof(N64Vtx_t)));
- if (ptr > offset && ptr < offset + end) {
- return std::make_tuple(GetSafeNode<std::string>(node, "symbol", name), node);
+ // ptr == offset just means the block's first vertex — still a valid hit.
+ // The old strict > missed it, and that's what spawned every bogus
+ // "_seg1_vtx_0" autogen.
+ if (ptr >= offset && ptr < offset + end) {
+ return std::make_tuple(GetSafeNode<std::string>(const_cast<YAML::Node&>(node), "symbol", name), node);
+ }
+ if (hasRealAddr && realAddr >= offset && realAddr < offset + end) {
+ return std::make_tuple(GetSafeNode<std::string>(const_cast<YAML::Node&>(node), "symbol", name), node);
}
}
@@ -263,6 +275,14 @@ ExportResult DListBinaryExporter::Export(std::ostream& write, std::shared_ptr<IP
auto ptr = Companion::Instance->PatchVirtualAddr(w1);
auto overlap = GFXDOverride::GetVtxOverlap(ptr);
+ if (!overlap.has_value() && IS_SEGMENTED(ptr)) {
+ uint32_t flatPtr = ptr;
+ if (Companion::Instance->GetCompressedSegmentOffset(&flatPtr)) {
+ overlap = GFXDOverride::GetVtxOverlap(flatPtr);
+ if (overlap.has_value())
+ ptr = flatPtr;
+ }
+ }
if (overlap.has_value()) {
auto ovnode = std::get<1>(overlap.value());
auto path = Companion::Instance->RelativePath(std::get<0>(overlap.value()));
@@ -325,9 +345,15 @@ ExportResult DListBinaryExporter::Export(std::ostream& write, std::shared_ptr<IP
auto branch = (w0 >> 16) & G_DL_NO_PUSH;
// Export displaylist segment addresses as an index into a buffer of gfx
- value = gsSPDisplayListOTRHash(ptr);
- w0 = value.words.w0;
- w1 = value.words.w1;
+ if ((Companion::Instance->GetGBIMinorVersion() == GBIMinorVersion::Mk64) && (SEGMENT_NUMBER(w1) == 0x07)) {
+ value = gsSPDisplayListOTRIndex(w1);
+ w0 = value.words.w0;
+ w1 = value.words.w1;
+ } else {
+ value = gsSPDisplayListOTRHash(ptr);
+ w0 = value.words.w0;
+ w1 = value.words.w1;
+ }
writer.Write(w0);
writer.Write(w1);
@@ -413,6 +439,19 @@ ExportResult DListBinaryExporter::Export(std::ostream& write, std::shared_ptr<IP
uint32_t newW0 = (G_SETTIMG_OTR_HASH << 24) | (w0 & 0x00FFFFFF);
writer.Write(newW0);
writer.Write(ptr);
+ } else if ((Companion::Instance->GetGBIMinorVersion() == GBIMinorVersion::Mk64) &&
+ ((SEGMENT_NUMBER(w1) == 0x03) || (SEGMENT_NUMBER(w1) == 0x05))) {
+ // Export texture segment addresses as segmented addresses
+ w1 |= 1;
+ writer.Write(w0);
+ writer.Write(w1);
+ // Segment 4 and 0x0B-0x0F are BK64's runtime animated-texture slots.
+ // Nothing static to resolve, so the segmented address just passes through.
+ } else if ((Companion::Instance->GetGBIMinorVersion() == GBIMinorVersion::BK64) &&
+ (SEGMENT_NUMBER(w1) == 0x04 || (SEGMENT_NUMBER(w1) >= 0x0B && SEGMENT_NUMBER(w1) <= 0x0F))) {
+ w1 |= 1;
+ writer.Write(w0);
+ writer.Write(w1);
} else {
// Export texture segment addresses as segmented addresses
N64Gfx value = gsDPSetTextureOTRImage(C0(21, 3), C0(19, 2), C0(0, 10), ptr);
@@ -592,6 +631,13 @@ std::optional<std::shared_ptr<IParsedData>> DListFactory::parse(std::vector<uint
SPDLOG_INFO("Found vtx at 0x{:X} matching last vtx at 0x{:X}", adjPtr, lOffset);
GFXDOverride::RegisterVTXOverlap(adjPtr, search.value());
}
+
+ if (IS_SEGMENTED(adjPtr) && Companion::Instance->GetCompressedSegmentOffset(&adjPtr)) {
+ if (adjPtr > lOffset && adjPtr < lOffset + lSize) {
+ SPDLOG_INFO("Found vtx at 0x{:X} matching last vtx at 0x{:X}", adjPtr, lOffset);
+ GFXDOverride::RegisterVTXOverlap(adjPtr, search.value());
+ }
+ }
} else {
YAML::Node vtx;
vtx["type"] = "VTX";
@@ -600,7 +646,7 @@ std::optional<std::shared_ptr<IParsedData>> DListFactory::parse(std::vector<uint
Companion::Instance->AddAsset(vtx);
}
} else {
- SPDLOG_WARN("Found vtx at 0x{:X}", w1);
+ SPDLOG_INFO("Found registered vtx at 0x{:X}", w1);
}
}