Skip to content

Commit

Permalink
Refactored vtx overlap function
Browse files Browse the repository at this point in the history
  • Loading branch information
KiritoDv committed Mar 10, 2024
1 parent a2d735c commit 371f814
Show file tree
Hide file tree
Showing 6 changed files with 135 additions and 24 deletions.
21 changes: 21 additions & 0 deletions src/Companion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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"]);
Expand Down Expand Up @@ -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;
Expand Down
1 change: 1 addition & 0 deletions src/Companion.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ class Companion {
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; };
Expand Down
87 changes: 64 additions & 23 deletions src/factories/DisplayListFactory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 },
Expand Down Expand Up @@ -146,6 +147,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();
Expand Down Expand Up @@ -387,39 +410,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);
}
}

Expand Down
1 change: 1 addition & 0 deletions src/factories/DisplayListFactory.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#include "BaseFactory.h"
#include "n64/CommandMacros.h"
#include <tuple>

class DListData : public IParsedData {
public:
Expand Down
41 changes: 41 additions & 0 deletions src/factories/DisplayListOverrides.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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()){
Expand Down Expand Up @@ -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();
}
}
8 changes: 7 additions & 1 deletion src/factories/DisplayListOverrides.h
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -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();
};

0 comments on commit 371f814

Please sign in to comment.