Fixed geo layout factory bugs and some sm64 related stuff

This commit is contained in:
KiritoDv
2024-03-26 00:11:46 -06:00
parent aa22c0803e
commit eb2dca9c14
11 changed files with 237 additions and 207 deletions
+8 -4
View File
@@ -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;
+2 -2
View File
@@ -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];
}
}
+1 -1
View File
@@ -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>();
}
+18 -2
View File
@@ -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; }
};
+19 -97
View File
@@ -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);
+27 -2
View File
@@ -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;
}
+2 -1
View File
@@ -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);
+1 -1
View File
@@ -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];
+2
View File
@@ -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);
+147 -96
View File
@@ -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)));
}
}
+10 -1
View File
@@ -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)
};
}
};