mirror of
https://github.com/izzy2lost/Torch.git
synced 2026-07-06 00:18:35 -07:00
Fixed geo layout factory bugs and some sm64 related stuff
This commit is contained in:
+8
-4
@@ -1079,11 +1079,14 @@ std::optional<YAML::Node> Companion::AddAsset(YAML::Node asset) {
|
||||
}
|
||||
|
||||
auto rom = this->GetRomData();
|
||||
auto factory = this->GetFactory(type)->get();
|
||||
auto factory = this->GetFactory(type);
|
||||
|
||||
if(!factory.has_value()) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::string output;
|
||||
std::string typeId = ConvertType(type);
|
||||
int index;
|
||||
|
||||
if(symbol != "") {
|
||||
output = symbol;
|
||||
@@ -1095,10 +1098,11 @@ std::optional<YAML::Node> Companion::AddAsset(YAML::Node asset) {
|
||||
asset["autogen"] = true;
|
||||
asset["symbol"] = output;
|
||||
|
||||
auto result = factory->parse(rom, asset);
|
||||
auto result = this->RegisterAsset(output, asset);
|
||||
|
||||
if(result.has_value()){
|
||||
return std::get<1>(this->RegisterAsset(output, asset).value());
|
||||
asset["path"] = std::get<0>(result.value());
|
||||
return std::get<1>(result.value());
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
|
||||
@@ -655,13 +655,13 @@ void AudioManager::create_aifc(int32_t index, LUS::BinaryWriter &out) {
|
||||
}
|
||||
|
||||
AudioBankSample AudioManager::get_aifc(int32_t index) {
|
||||
int32_t idx = -1;
|
||||
int32_t idx = 0;
|
||||
for(auto &sample_bank : this->loaded_tbl.banks){
|
||||
auto offsets = PyUtils::keys(sample_bank->entries);
|
||||
std::sort(offsets.begin(), offsets.end());
|
||||
|
||||
for(auto &offset : offsets){
|
||||
if(++idx == index){
|
||||
if(idx++ == index){
|
||||
return *sample_bank->entries[offset];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,5 +5,5 @@
|
||||
|
||||
std::optional<std::shared_ptr<IParsedData>> AudioHeaderFactory::parse(std::vector<uint8_t>& buffer, YAML::Node& data) {
|
||||
AudioManager::Instance->initialize(buffer, data);
|
||||
return std::nullopt;
|
||||
return std::make_shared<IParsedData>();
|
||||
}
|
||||
@@ -2,10 +2,26 @@
|
||||
|
||||
#include "BaseFactory.h"
|
||||
|
||||
class AudioDummyExporter : public BaseExporter {
|
||||
public:
|
||||
ExportResult Export(std::ostream& write, std::shared_ptr<IParsedData> data, std::string& entryName, YAML::Node& node, std::string* replacement) override {
|
||||
return std::nullopt;
|
||||
}
|
||||
};
|
||||
|
||||
class AudioHeaderFactory : public BaseFactory {
|
||||
public:
|
||||
std::optional<std::shared_ptr<IParsedData>> parse(std::vector<uint8_t>& buffer, YAML::Node& data) override;
|
||||
inline std::unordered_map<ExportType, std::shared_ptr<BaseExporter>> GetExporters() override {
|
||||
return {};
|
||||
std::optional<std::shared_ptr<IParsedData>> parse_modding(std::vector<uint8_t>& buffer, YAML::Node& data) override {
|
||||
return std::nullopt;
|
||||
}
|
||||
std::unordered_map<ExportType, std::shared_ptr<BaseExporter>> GetExporters() override {
|
||||
return {
|
||||
REGISTER(Modding, AudioDummyExporter)
|
||||
REGISTER(Header, AudioDummyExporter)
|
||||
REGISTER(Binary, AudioDummyExporter)
|
||||
REGISTER(Code, AudioDummyExporter)
|
||||
};
|
||||
}
|
||||
bool SupportModdedAssets() override { return true; }
|
||||
};
|
||||
@@ -111,7 +111,8 @@ ExportResult DListCodeExporter::Export(std::ostream &write, std::shared_ptr<IPar
|
||||
gfxd_timg_callback(GFXDOverride::Texture);
|
||||
gfxd_dl_callback(GFXDOverride::DisplayList);
|
||||
gfxd_tlut_callback(GFXDOverride::Palette);
|
||||
gfxd_lightsn_callback(GFXDOverride::Light);
|
||||
gfxd_lightsn_callback(GFXDOverride::Lights);
|
||||
gfxd_light_callback(GFXDOverride::Light);
|
||||
GFXDSetGBIVersion();
|
||||
|
||||
gfxd_puts(("Gfx " + symbol + "[] = {\n").c_str());
|
||||
@@ -123,6 +124,8 @@ ExportResult DListCodeExporter::Export(std::ostream &write, std::shared_ptr<IPar
|
||||
|
||||
if (Companion::Instance->IsDebug()) {
|
||||
write << "// count: " << std::to_string(sz / 8) << " Gfx\n";
|
||||
} else {
|
||||
write << "\n";
|
||||
}
|
||||
|
||||
return offset + sz;
|
||||
@@ -318,64 +321,28 @@ std::optional<std::shared_ptr<IParsedData>> DListFactory::parse(std::vector<uint
|
||||
processing = false;
|
||||
}
|
||||
|
||||
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();
|
||||
auto factory = Companion::Instance->GetFactory("GFX")->get();
|
||||
|
||||
std::string output;
|
||||
YAML::Node dl;
|
||||
uint32_t ptr = w1;
|
||||
|
||||
if(Decompressor::IsSegmented(w1)){
|
||||
SPDLOG_INFO("Found segmented display list at 0x{:X}", w1);
|
||||
output = Companion::Instance->NormalizeAsset("seg" + std::to_string(SEGMENT_NUMBER(ptr)) +"_dl_" + Torch::to_hex(SEGMENT_OFFSET(ptr), false));
|
||||
} else {
|
||||
SPDLOG_INFO("Found display list at 0x{:X}", ptr);
|
||||
output = Companion::Instance->NormalizeAsset("dl_" + Torch::to_hex(ptr, false));
|
||||
}
|
||||
|
||||
dl["type"] = "GFX";
|
||||
dl["offset"] = ptr;
|
||||
dl["symbol"] = output;
|
||||
dl["autogen"] = true;
|
||||
|
||||
auto result = factory->parse(rom, dl);
|
||||
|
||||
if(!result.has_value()){
|
||||
continue;
|
||||
}
|
||||
|
||||
Companion::Instance->RegisterAsset(output, dl);
|
||||
} else {
|
||||
SPDLOG_WARN("Could not find display list at 0x{:X}", w1);
|
||||
}
|
||||
YAML::Node gfx;
|
||||
gfx["type"] = "GFX";
|
||||
gfx["offset"] = w1;
|
||||
Companion::Instance->AddAsset(gfx);
|
||||
}
|
||||
|
||||
// This opcode is generally used as part of multiple macros such as gsSPSetLights1.
|
||||
// We need to process gsSPLight which is a subcommand inside G_MOVEMEM (0x03).
|
||||
if(opcode == GBI(G_MOVEMEM)) {
|
||||
// 0x03860000 or 0x03880000 subcommand will contain 0x86/0x88 for G_MV_L0 and G_MV_L1. Other subcommands also exist.
|
||||
uint8_t subcommand = (w0 >> 16) & 0xFF;
|
||||
uint8_t subcommand = (w0 >> 16) & 0xFF;
|
||||
uint8_t index = 0;
|
||||
uint8_t offset = 0;
|
||||
bool light = false;
|
||||
|
||||
switch (Companion::Instance->GetGBIVersion()) {
|
||||
case GBIVersion::f3d:
|
||||
index = C0(16, 8);
|
||||
|
||||
if(index == GBI(G_MV_L0) || index == GBI(G_MV_L1)) {
|
||||
light = true;
|
||||
}
|
||||
|
||||
break;
|
||||
// If needing light generation on G_MV_L0 then we'll need to walk the DL ptr forward/backward to check for 0xBC
|
||||
// Otherwise mk64 will break.
|
||||
// PD: Mega, this works for sm64 too, why you didn't implement it? >:(
|
||||
// PD: Im jk, <3
|
||||
case GBIVersion::f3d:
|
||||
case GBIVersion::f3dex:
|
||||
offset = w1;
|
||||
|
||||
/*
|
||||
* Only generate lights on the second gsSPLight.
|
||||
* gsSPSetLights1(name) outputs three macros:
|
||||
@@ -397,34 +364,11 @@ std::optional<std::shared_ptr<IParsedData>> DListFactory::parse(std::vector<uint
|
||||
break;
|
||||
}
|
||||
|
||||
if(const auto decl = Companion::Instance->GetNodeByAddr(w1); !decl.has_value() && light){
|
||||
SPDLOG_INFO("Addr to Lights1 command at 0x{:X} not in yaml, autogenerating it", w1);
|
||||
auto rom = Companion::Instance->GetRomData();
|
||||
auto factory = Companion::Instance->GetFactory("LIGHTS")->get();
|
||||
|
||||
std::string output;
|
||||
YAML::Node light;
|
||||
uint32_t ptr = w1;
|
||||
|
||||
if(Decompressor::IsSegmented(w1)){
|
||||
SPDLOG_INFO("Found segmented lights at 0x{:X}", w1);
|
||||
ptr = w1;
|
||||
output = Companion::Instance->NormalizeAsset("seg" + std::to_string(SEGMENT_NUMBER(w1)) +"_lights1_" + Torch::to_hex(SEGMENT_OFFSET(ptr), false));
|
||||
} else {
|
||||
SPDLOG_INFO("Found lights at 0x{:X}", ptr);
|
||||
output = Companion::Instance->NormalizeAsset("lights1_" + Torch::to_hex(w1, false));
|
||||
}
|
||||
|
||||
light["type"] = "lights";
|
||||
light["offset"] = ptr;
|
||||
light["symbol"] = output;
|
||||
light["autogen"] = true;
|
||||
auto result = factory->parse(rom, light);
|
||||
if(result.has_value()){
|
||||
Companion::Instance->RegisterAsset(output, light);
|
||||
}
|
||||
} else {
|
||||
SPDLOG_WARN("Could not find lights at 0x{:X}", w1);
|
||||
if(light){
|
||||
YAML::Node lnode;
|
||||
lnode["type"] = "LIGHTS";
|
||||
lnode["offset"] = w1;
|
||||
Companion::Instance->AddAsset(lnode);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -462,33 +406,11 @@ std::optional<std::shared_ptr<IParsedData>> DListFactory::parse(std::vector<uint
|
||||
GFXDOverride::RegisterVTXOverlap(w1, search.value());
|
||||
}
|
||||
} else {
|
||||
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["offset"] = w1;
|
||||
vtx["count"] = nvtx;
|
||||
vtx["symbol"] = output;
|
||||
vtx["autogen"] = true;
|
||||
auto result = factory->parse(rom, vtx);
|
||||
if(result.has_value()){
|
||||
Companion::Instance->RegisterAsset(output, vtx);
|
||||
}
|
||||
Companion::Instance->AddAsset(vtx);
|
||||
}
|
||||
} else {
|
||||
SPDLOG_WARN("Found vtx at 0x{:X}", w1);
|
||||
|
||||
@@ -112,17 +112,42 @@ int Palette(uint32_t ptr, int32_t idx, int32_t count) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Light(uint32_t ptr, int32_t count) {
|
||||
int Lights(uint32_t ptr, int32_t count) {
|
||||
auto dec = Companion::Instance->GetNodeByAddr(ptr);
|
||||
|
||||
if(dec.has_value()){
|
||||
auto node = std::get<1>(dec.value());
|
||||
auto symbol = GetSafeNode<std::string>(node, "symbol");
|
||||
SPDLOG_INFO("Found Light: 0x{:X} Symbol: {}", ptr, symbol);
|
||||
SPDLOG_INFO("Found Lightsn: 0x{:X} Symbol: {}", ptr, symbol);
|
||||
gfxd_puts(symbol.c_str());
|
||||
return 1;
|
||||
}
|
||||
|
||||
SPDLOG_WARN("Could not find lights at 0x{:X}", ptr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Light(uint32_t ptr) {
|
||||
auto res = Companion::Instance->GetNodeByAddr(ptr);
|
||||
|
||||
if(res.has_value()){
|
||||
auto node = std::get<1>(res.value());
|
||||
auto symbol = GetSafeNode<std::string>(node, "symbol");
|
||||
SPDLOG_INFO("Found Light A Ptr: 0x{:X} Symbol: {}", ptr, symbol);
|
||||
gfxd_puts(("&" + symbol + ".a").c_str());
|
||||
return 1;
|
||||
}
|
||||
|
||||
res = Companion::Instance->GetNodeByAddr(ptr - 0x8);
|
||||
|
||||
if(res.has_value()){
|
||||
auto node = std::get<1>(res.value());
|
||||
auto symbol = GetSafeNode<std::string>(node, "symbol");
|
||||
SPDLOG_INFO("Found Light L Ptr: 0x{:X} Symbol: {}", ptr, symbol);
|
||||
gfxd_puts(("&" + symbol + ".l").c_str());
|
||||
return 1;
|
||||
}
|
||||
|
||||
SPDLOG_WARN("Could not find light at 0x{:X}", ptr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -42,7 +42,8 @@ void Triangle2(const Gfx* gfx);
|
||||
int Vtx(uint32_t vtx, int32_t num);
|
||||
int Texture(uint32_t timg, int32_t fmt, int32_t siz, int32_t width, int32_t height, int32_t pal);
|
||||
int Palette(uint32_t tlut, int32_t idx, int32_t count);
|
||||
int Light(uint32_t lightsn, int32_t count);
|
||||
int Lights(uint32_t lightsn, int32_t count);
|
||||
int Light(uint32_t light);
|
||||
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);
|
||||
|
||||
@@ -20,7 +20,7 @@ ExportResult LightsCodeExporter::Export(std::ostream &write, std::shared_ptr<IPa
|
||||
auto light = std::static_pointer_cast<LightsData>(raw)->mLights;
|
||||
auto symbol = GetSafeNode(node, "symbol", entryName);
|
||||
|
||||
write << "Lights1 " << symbol << " = gdSPDefLights1 (\n";
|
||||
write << "Lights1 " << symbol << " = gdSPDefLights1(\n";
|
||||
|
||||
// Ambient
|
||||
auto r = (int16_t) light.a.l.col[0];
|
||||
|
||||
@@ -55,6 +55,8 @@ ExportResult VtxCodeExporter::Export(std::ostream &write, std::shared_ptr<IParse
|
||||
|
||||
if (Companion::Instance->IsDebug()) {
|
||||
write << "// count: " << std::to_string(vtx.size()) << " Vtxs\n";
|
||||
} else {
|
||||
write << "\n";
|
||||
}
|
||||
|
||||
return offset + vtx.size() * sizeof(VtxRaw);
|
||||
|
||||
@@ -6,85 +6,136 @@
|
||||
#include "geo/GeoUtils.h"
|
||||
#include "utils/TorchUtils.h"
|
||||
|
||||
uint64_t RegisterOrLoadGeoLayout(uint32_t ptr) {
|
||||
|
||||
auto dec = Companion::Instance->GetNodeByAddr(Torch::translate(ptr));
|
||||
if(dec.has_value()){
|
||||
uint64_t hash = CRC64(std::get<0>(dec.value()).c_str());
|
||||
SPDLOG_INFO("Found Geo Layout: 0x{:X} Hash: 0x{:X} Path: {}", ptr, hash, std::get<0>(dec.value()));
|
||||
return hash;
|
||||
uint64_t RegisterAutoGen(uint32_t ptr, std::string type) {
|
||||
if(!Companion::Instance->IsOTRMode()) {
|
||||
return ptr;
|
||||
}
|
||||
|
||||
SPDLOG_INFO("Addr to Geo Layout at 0x{:X} not in yaml, autogenerating it", ptr);
|
||||
auto addr = Companion::Instance->GetFileOffsetFromSegmentedAddr(SEGMENT_NUMBER(ptr));
|
||||
if(!addr.has_value()) {
|
||||
SPDLOG_ERROR("Segment data missing from game config\nPlease add an entry for segment {}", SEGMENT_NUMBER(ptr));
|
||||
return 0;
|
||||
}
|
||||
YAML::Node node;
|
||||
node["type"] = type;
|
||||
node["offset"] = ptr;
|
||||
const auto result = Companion::Instance->AddAsset(node);
|
||||
|
||||
auto rom = Companion::Instance->GetRomData();
|
||||
auto factory = Companion::Instance->GetFactory("SM64:GEO_LAYOUT")->get();
|
||||
std::string output = Companion::Instance->NormalizeAsset("seg" + std::to_string(SEGMENT_NUMBER(ptr)) +"_geo_" + Torch::to_hex(ptr, false));
|
||||
YAML::Node dl;
|
||||
dl["type"] = "SM64:GEO_LAYOUT";
|
||||
dl["offset"] = ptr;
|
||||
dl["symbol"] = output;
|
||||
auto result = factory->parse(rom, dl);
|
||||
|
||||
if(!result.has_value()){
|
||||
return 0;
|
||||
}
|
||||
|
||||
auto ndec = Companion::Instance->RegisterAsset(output, dl);
|
||||
|
||||
if(ndec.has_value()){
|
||||
uint64_t hash = CRC64(std::get<0>(ndec.value()).c_str());
|
||||
SPDLOG_INFO("Found Geo Layout: 0x{:X} Hash: 0x{:X} Path: {}", ptr, hash, std::get<0>(ndec.value()));
|
||||
if(result.has_value()){
|
||||
auto path = GetSafeNode<std::string>(node, "path");
|
||||
uint64_t hash = CRC64(path.c_str());
|
||||
SPDLOG_INFO("Found {}: 0x{:X} Hash: 0x{:X} Path: {}", type, ptr, hash, path);
|
||||
return hash;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint64_t RegisterOrLoadDisplayList(uint32_t ptr) {
|
||||
ExportResult SM64::GeoCodeExporter::Export(std::ostream&write, std::shared_ptr<IParsedData> data, std::string&entryName, YAML::Node&node, std::string* replacement) {
|
||||
const auto cmds = std::static_pointer_cast<GeoLayout>(data)->commands;
|
||||
const auto symbol = GetSafeNode(node, "symbol", entryName);
|
||||
auto offset = GetSafeNode<uint32_t>(node, "offset");
|
||||
size_t size = 0;
|
||||
uint32_t indentCount = 1;
|
||||
uint32_t cmdCount = 0;
|
||||
|
||||
auto dec = Companion::Instance->GetNodeByAddr(Torch::translate(ptr));
|
||||
if(dec.has_value()){
|
||||
uint64_t hash = CRC64(std::get<0>(dec.value()).c_str());
|
||||
SPDLOG_INFO("Found Display List: 0x{:X} Hash: 0x{:X} Path: {}", ptr, hash, std::get<0>(dec.value()));
|
||||
return hash;
|
||||
write << "GeoLayout " << symbol << "[] = {\n";
|
||||
|
||||
for(auto& [opcode, arguments] : cmds) {
|
||||
bool commaFlag = false;
|
||||
|
||||
for (uint32_t i = 0; i < indentCount; ++i) {
|
||||
write << fourSpaceTab;
|
||||
}
|
||||
|
||||
if (opcode == GeoOpcode::CloseNode) {
|
||||
--indentCount;
|
||||
} else if (opcode == GeoOpcode::OpenNode) {
|
||||
++indentCount;
|
||||
}
|
||||
|
||||
write << opcode << "(";
|
||||
for(auto& args : arguments) {
|
||||
if (commaFlag) {
|
||||
write << ", ";
|
||||
} else {
|
||||
commaFlag = true;
|
||||
}
|
||||
|
||||
switch(static_cast<GeoArgumentType>(args.index())) {
|
||||
case GeoArgumentType::U8: {
|
||||
write << static_cast<uint32_t>(std::get<uint8_t>(args));
|
||||
break;
|
||||
}
|
||||
case GeoArgumentType::S8: {
|
||||
write << static_cast<uint32_t>(std::get<int8_t>(args));
|
||||
break;
|
||||
}
|
||||
case GeoArgumentType::U16: {
|
||||
write << std::get<uint16_t>(args);
|
||||
break;
|
||||
}
|
||||
case GeoArgumentType::S16: {
|
||||
write << std::get<int16_t>(args);
|
||||
break;
|
||||
}
|
||||
case GeoArgumentType::U32: {
|
||||
write << "0x" << std::hex << std::get<uint32_t>(args);
|
||||
break;
|
||||
}
|
||||
case GeoArgumentType::S32: {
|
||||
write << std::get<int32_t>(args);
|
||||
break;
|
||||
}
|
||||
case GeoArgumentType::U64: {
|
||||
write << "0x" << std::hex << std::get<uint64_t>(args);
|
||||
break;
|
||||
}
|
||||
case GeoArgumentType::VEC2F: {
|
||||
const auto [x, y] = std::get<Vec2f>(args);
|
||||
write << x << ", " << y;
|
||||
break;
|
||||
}
|
||||
case GeoArgumentType::VEC3F: {
|
||||
const auto [x, y, z] = std::get<Vec3f>(args);
|
||||
write << x << ", " << y << ", " << z;
|
||||
break;
|
||||
}
|
||||
case GeoArgumentType::VEC3S: {
|
||||
const auto [x, y, z] = std::get<Vec3s>(args);
|
||||
write << x << ", " << y << ", " << z;
|
||||
break;
|
||||
}
|
||||
case GeoArgumentType::VEC3I: {
|
||||
const auto [x, y, z] = std::get<Vec3i>(args);
|
||||
write << x << ", " << y << ", " << z;
|
||||
break;
|
||||
}
|
||||
case GeoArgumentType::VEC4F: {
|
||||
const auto [x, y, z, w] = std::get<Vec4f>(args);
|
||||
write << x << ", " << y << ", " << z << ", " << w;
|
||||
break;
|
||||
}
|
||||
case GeoArgumentType::VEC4S: {
|
||||
const auto [x, y, z, w] = std::get<Vec4s>(args);
|
||||
write << x << ", " << y << ", " << z << ", " << w;
|
||||
break;
|
||||
}
|
||||
case GeoArgumentType::STRING: {
|
||||
write << std::get<std::string>(args);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
write << "),\n";
|
||||
++cmdCount;
|
||||
}
|
||||
|
||||
SPDLOG_INFO("Addr to Display List at 0x{:X} not in yaml, autogenerating it", ptr);
|
||||
auto addr = Companion::Instance->GetFileOffsetFromSegmentedAddr(SEGMENT_NUMBER(ptr));
|
||||
if(!addr.has_value()) {
|
||||
SPDLOG_ERROR("Segment data missing from game config\nPlease add an entry for segment {}", SEGMENT_NUMBER(ptr));
|
||||
return 0;
|
||||
write << "};\n";
|
||||
|
||||
if (Companion::Instance->IsDebug()) {
|
||||
write << "// count: " << std::to_string(cmdCount) << " GeoLayout\n";
|
||||
}
|
||||
|
||||
auto rom = Companion::Instance->GetRomData();
|
||||
auto factory = Companion::Instance->GetFactory("GFX")->get();
|
||||
std::string output = Companion::Instance->NormalizeAsset("seg" + std::to_string(SEGMENT_NUMBER(ptr)) +"_dl_" + Torch::to_hex(ptr, false));
|
||||
YAML::Node dl;
|
||||
dl["type"] = "GFX";
|
||||
dl["mio0"] = addr.value();
|
||||
dl["offset"] = SEGMENT_OFFSET(ptr);
|
||||
dl["symbol"] = output;
|
||||
auto result = factory->parse(rom, dl);
|
||||
|
||||
if(!result.has_value()){
|
||||
return 0;
|
||||
}
|
||||
|
||||
auto ndec = Companion::Instance->RegisterAsset(output, dl);
|
||||
|
||||
if(ndec.has_value()){
|
||||
uint64_t hash = CRC64(std::get<0>(ndec.value()).c_str());
|
||||
SPDLOG_INFO("Found Display List: 0x{:X} Hash: 0x{:X} Path: {}", ptr, hash, std::get<0>(ndec.value()));
|
||||
return hash;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return offset + size;
|
||||
}
|
||||
|
||||
ExportResult SM64::GeoBinaryExporter::Export(std::ostream&write, std::shared_ptr<IParsedData> data, std::string&entryName, YAML::Node&node, std::string* replacement) {
|
||||
@@ -96,63 +147,63 @@ ExportResult SM64::GeoBinaryExporter::Export(std::ostream&write, std::shared_ptr
|
||||
writer.Write(static_cast<uint8_t>(opcode));
|
||||
|
||||
for(auto& args : arguments) {
|
||||
switch(args.index()) {
|
||||
case 0: {
|
||||
switch(static_cast<GeoArgumentType>(args.index())) {
|
||||
case GeoArgumentType::U8: {
|
||||
writer.Write(std::get<uint8_t>(args));
|
||||
break;
|
||||
}
|
||||
case 1: {
|
||||
case GeoArgumentType::S8: {
|
||||
writer.Write(std::get<int8_t>(args));
|
||||
break;
|
||||
}
|
||||
case 2: {
|
||||
case GeoArgumentType::U16: {
|
||||
writer.Write(std::get<uint16_t>(args));
|
||||
break;
|
||||
}
|
||||
case 3: {
|
||||
case GeoArgumentType::S16: {
|
||||
writer.Write(std::get<int16_t>(args));
|
||||
break;
|
||||
}
|
||||
case 4: {
|
||||
case GeoArgumentType::U32: {
|
||||
writer.Write(std::get<uint32_t>(args));
|
||||
break;
|
||||
}
|
||||
case 5: {
|
||||
case GeoArgumentType::S32: {
|
||||
writer.Write(std::get<int32_t>(args));
|
||||
break;
|
||||
}
|
||||
case 6: {
|
||||
case GeoArgumentType::U64: {
|
||||
writer.Write(std::get<uint64_t>(args));
|
||||
break;
|
||||
}
|
||||
case 7: {
|
||||
case GeoArgumentType::VEC2F: {
|
||||
const auto [x, y] = std::get<Vec2f>(args);
|
||||
writer.Write(x);
|
||||
writer.Write(y);
|
||||
break;
|
||||
}
|
||||
case 8: {
|
||||
case GeoArgumentType::VEC3F: {
|
||||
const auto [x, y, z] = std::get<Vec3f>(args);
|
||||
writer.Write(x);
|
||||
writer.Write(y);
|
||||
writer.Write(z);
|
||||
break;
|
||||
}
|
||||
case 9: {
|
||||
case GeoArgumentType::VEC3S: {
|
||||
const auto [x, y, z] = std::get<Vec3s>(args);
|
||||
writer.Write(x);
|
||||
writer.Write(y);
|
||||
writer.Write(z);
|
||||
break;
|
||||
}
|
||||
case 10: {
|
||||
case GeoArgumentType::VEC3I: {
|
||||
const auto [x, y, z] = std::get<Vec3i>(args);
|
||||
writer.Write(x);
|
||||
writer.Write(y);
|
||||
writer.Write(z);
|
||||
break;
|
||||
}
|
||||
case 11: {
|
||||
case GeoArgumentType::VEC4F: {
|
||||
const auto [x, y, z, w] = std::get<Vec4f>(args);
|
||||
writer.Write(x);
|
||||
writer.Write(y);
|
||||
@@ -160,7 +211,7 @@ ExportResult SM64::GeoBinaryExporter::Export(std::ostream&write, std::shared_ptr
|
||||
writer.Write(w);
|
||||
break;
|
||||
}
|
||||
case 12: {
|
||||
case GeoArgumentType::VEC4S: {
|
||||
const auto [x, y, z, w] = std::get<Vec4s>(args);
|
||||
writer.Write(x);
|
||||
writer.Write(y);
|
||||
@@ -193,8 +244,9 @@ ExportResult SM64::GeoHeaderExporter::Export(std::ostream&write, std::shared_ptr
|
||||
}
|
||||
|
||||
std::optional<std::shared_ptr<IParsedData>> SM64::GeoLayoutFactory::parse(std::vector<uint8_t>& buffer, YAML::Node& node) {
|
||||
const size_t offset = Torch::translate(GetSafeNode<uint32_t>(node, "offset"));
|
||||
auto cmd = buffer.data() + offset;
|
||||
auto [_, segment] = Decompressor::AutoDecode(node, buffer);
|
||||
auto cmd = segment.data;
|
||||
|
||||
bool processing = true;
|
||||
std::vector<GeoCommand> commands;
|
||||
|
||||
@@ -207,9 +259,8 @@ std::optional<std::shared_ptr<IParsedData>> SM64::GeoLayoutFactory::parse(std::v
|
||||
|
||||
switch(opcode){
|
||||
case GeoOpcode::BranchAndLink: {
|
||||
uint32_t ptr = cur_geo_cmd_u32(0x04);
|
||||
arguments.emplace_back(ptr);
|
||||
arguments.emplace_back(RegisterOrLoadGeoLayout(ptr));
|
||||
auto ptr = cur_geo_cmd_u32(0x04);
|
||||
arguments.emplace_back(RegisterAutoGen(ptr, "SM64:GEO_LAYOUT"));
|
||||
|
||||
cmd += 0x08 << CMD_SIZE_SHIFT;
|
||||
break;
|
||||
@@ -223,7 +274,7 @@ std::optional<std::shared_ptr<IParsedData>> SM64::GeoLayoutFactory::parse(std::v
|
||||
auto ptr = cur_geo_cmd_u32(0x04);
|
||||
|
||||
arguments.emplace_back(jmp);
|
||||
arguments.emplace_back(RegisterOrLoadGeoLayout(ptr));
|
||||
arguments.emplace_back(RegisterAutoGen(ptr, "SM64:GEO_LAYOUT"));
|
||||
|
||||
cmd += 0x08 << CMD_SIZE_SHIFT;
|
||||
break;
|
||||
@@ -350,7 +401,7 @@ std::optional<std::shared_ptr<IParsedData>> SM64::GeoLayoutFactory::parse(std::v
|
||||
Vec3s translation = {};
|
||||
Vec3s rotation = {};
|
||||
auto params = cur_geo_cmd_u8(0x01);
|
||||
auto cmd_pos = reinterpret_cast<int16_t *>(&cmd[0x04]);
|
||||
auto cmd_pos = reinterpret_cast<int16_t *>(cmd);
|
||||
|
||||
arguments.emplace_back(params);
|
||||
|
||||
@@ -371,7 +422,7 @@ std::optional<std::shared_ptr<IParsedData>> SM64::GeoLayoutFactory::parse(std::v
|
||||
break;
|
||||
case 3:
|
||||
arguments.emplace_back(cmd_pos[1]);
|
||||
cmd_pos += 2 << CMD_SIZE_SHIFT;
|
||||
cmd_pos += 0x04 << CMD_SIZE_SHIFT;
|
||||
break;
|
||||
default: {
|
||||
break;
|
||||
@@ -380,7 +431,7 @@ std::optional<std::shared_ptr<IParsedData>> SM64::GeoLayoutFactory::parse(std::v
|
||||
|
||||
if (params & 0x80) {
|
||||
auto ptr = BSWAP32(*reinterpret_cast<uint32_t*>(&cmd_pos[0]));
|
||||
arguments.emplace_back(RegisterOrLoadDisplayList(ptr));
|
||||
arguments.emplace_back(RegisterAutoGen(ptr, "GFX"));
|
||||
cmd_pos += 2 << CMD_SIZE_SHIFT;
|
||||
}
|
||||
|
||||
@@ -401,7 +452,7 @@ std::optional<std::shared_ptr<IParsedData>> SM64::GeoLayoutFactory::parse(std::v
|
||||
|
||||
if (params & 0x80) {
|
||||
auto ptr = BSWAP32(*reinterpret_cast<uint32_t*>(&cmd_pos[0]));
|
||||
arguments.emplace_back(RegisterOrLoadDisplayList(ptr));
|
||||
arguments.emplace_back(RegisterAutoGen(ptr, "GFX"));
|
||||
cmd_pos += 2 << CMD_SIZE_SHIFT;
|
||||
}
|
||||
|
||||
@@ -416,7 +467,7 @@ std::optional<std::shared_ptr<IParsedData>> SM64::GeoLayoutFactory::parse(std::v
|
||||
auto cmd_pos = reinterpret_cast<int16_t*>(cmd);
|
||||
|
||||
arguments.emplace_back(layer);
|
||||
arguments.emplace_back(RegisterOrLoadDisplayList(ptr));
|
||||
arguments.emplace_back(RegisterAutoGen(ptr, "GFX"));
|
||||
|
||||
read_vec3s(translation, &cmd_pos[1]);
|
||||
arguments.emplace_back(translation);
|
||||
@@ -430,14 +481,14 @@ std::optional<std::shared_ptr<IParsedData>> SM64::GeoLayoutFactory::parse(std::v
|
||||
auto params = cur_geo_cmd_u8(0x01);
|
||||
auto cmd_pos = reinterpret_cast<int16_t*>(cmd);
|
||||
|
||||
read_vec3s(translation, &cmd_pos[1]);
|
||||
cmd_pos = read_vec3s(translation, &cmd_pos[1]);
|
||||
|
||||
arguments.emplace_back(params);
|
||||
arguments.emplace_back(translation);
|
||||
|
||||
if (params & 0x80) {
|
||||
auto ptr = BSWAP32(*reinterpret_cast<uint32_t*>(&cmd_pos[0]));
|
||||
arguments.emplace_back(RegisterOrLoadDisplayList(ptr));
|
||||
arguments.emplace_back(RegisterAutoGen(ptr, "GFX"));
|
||||
cmd_pos += 0x02 << CMD_SIZE_SHIFT;
|
||||
}
|
||||
|
||||
@@ -449,7 +500,7 @@ std::optional<std::shared_ptr<IParsedData>> SM64::GeoLayoutFactory::parse(std::v
|
||||
auto ptr = cur_geo_cmd_u32(0x04);
|
||||
|
||||
arguments.emplace_back(layer);
|
||||
arguments.emplace_back(RegisterOrLoadDisplayList(ptr));
|
||||
arguments.emplace_back(RegisterAutoGen(ptr, "GFX"));
|
||||
|
||||
cmd += 0x08 << CMD_SIZE_SHIFT;
|
||||
break;
|
||||
@@ -527,7 +578,7 @@ std::optional<std::shared_ptr<IParsedData>> SM64::GeoLayoutFactory::parse(std::v
|
||||
|
||||
if (params & 0x80) {
|
||||
auto ptr = cur_geo_cmd_u32(0x08);
|
||||
arguments.emplace_back(RegisterOrLoadDisplayList(ptr));
|
||||
arguments.emplace_back(RegisterAutoGen(ptr, "GFX"));
|
||||
cmd += 0x04 << CMD_SIZE_SHIFT;
|
||||
}
|
||||
|
||||
@@ -551,8 +602,8 @@ std::optional<std::shared_ptr<IParsedData>> SM64::GeoLayoutFactory::parse(std::v
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
SPDLOG_ERROR("Unknown geo command {}", opcode);
|
||||
throw std::runtime_error("Unknown geo command");
|
||||
SPDLOG_ERROR("Unknown geo command '{}'", opcode);
|
||||
throw std::runtime_error("Unknown geo command " + std::to_string(static_cast<uint8_t>(opcode)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,11 @@
|
||||
#include <vector>
|
||||
#include <variant>
|
||||
|
||||
typedef std::variant<uint8_t, int8_t, uint16_t, int16_t, uint32_t, int32_t, uint64_t, Vec2f, Vec3f, Vec3s, Vec3i, Vec4f, Vec4s> GeoArgument;
|
||||
typedef std::variant<uint8_t, int8_t, uint16_t, int16_t, uint32_t, int32_t, uint64_t, Vec2f, Vec3f, Vec3s, Vec3i, Vec4f, Vec4s, std::string> GeoArgument;
|
||||
|
||||
enum class GeoArgumentType {
|
||||
U8, S8, U16, S16, U32, S32, U64, VEC2F, VEC3F, VEC3S, VEC3I, VEC4F, VEC4S, STRING
|
||||
};
|
||||
|
||||
namespace SM64 {
|
||||
|
||||
@@ -21,6 +25,10 @@ public:
|
||||
explicit GeoLayout(std::vector<GeoCommand> commands) : commands(std::move(commands)) {}
|
||||
};
|
||||
|
||||
class GeoCodeExporter : public BaseExporter {
|
||||
ExportResult Export(std::ostream& write, std::shared_ptr<IParsedData> data, std::string& entryName, YAML::Node& node, std::string* replacement) override;
|
||||
};
|
||||
|
||||
class GeoHeaderExporter : public BaseExporter {
|
||||
ExportResult Export(std::ostream& write, std::shared_ptr<IParsedData> data, std::string& entryName, YAML::Node& node, std::string* replacement) override;
|
||||
};
|
||||
@@ -36,6 +44,7 @@ public:
|
||||
return {
|
||||
REGISTER(Header, GeoHeaderExporter)
|
||||
REGISTER(Binary, GeoBinaryExporter)
|
||||
REGISTER(Code, GeoCodeExporter)
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user