diff options
| author | KiritoDv <kiritodev01@gmail.com> | 2024-03-26 00:11:46 -0600 |
|---|---|---|
| committer | KiritoDv <kiritodev01@gmail.com> | 2024-03-26 00:11:46 -0600 |
| commit | eb2dca9c14247da51a5fdac1f1e3f66cf0c660c4 (patch) | |
| tree | ed7d203d728f66a2ad55b44087696bdda97874f5 | |
| parent | aa22c0803efa346b7886e8c2d44a04eddb020b3c (diff) | |
Fixed geo layout factory bugs and some sm64 related stuff
| -rw-r--r-- | src/Companion.cpp | 12 | ||||
| -rw-r--r-- | src/audio/AudioManager.cpp | 4 | ||||
| -rw-r--r-- | src/factories/AudioHeaderFactory.cpp | 2 | ||||
| -rw-r--r-- | src/factories/AudioHeaderFactory.h | 20 | ||||
| -rw-r--r-- | src/factories/DisplayListFactory.cpp | 116 | ||||
| -rw-r--r-- | src/factories/DisplayListOverrides.cpp | 29 | ||||
| -rw-r--r-- | src/factories/DisplayListOverrides.h | 3 | ||||
| -rw-r--r-- | src/factories/LightsFactory.cpp | 2 | ||||
| -rw-r--r-- | src/factories/VtxFactory.cpp | 2 | ||||
| -rw-r--r-- | src/factories/sm64/GeoLayoutFactory.cpp | 237 | ||||
| -rw-r--r-- | src/factories/sm64/GeoLayoutFactory.h | 11 |
11 files changed, 234 insertions, 204 deletions
diff --git a/src/Companion.cpp b/src/Companion.cpp index b6d2605..225c4a1 100644 --- a/src/Companion.cpp +++ b/src/Companion.cpp @@ -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; diff --git a/src/audio/AudioManager.cpp b/src/audio/AudioManager.cpp index c4b612c..686403d 100644 --- a/src/audio/AudioManager.cpp +++ b/src/audio/AudioManager.cpp @@ -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]; } } diff --git a/src/factories/AudioHeaderFactory.cpp b/src/factories/AudioHeaderFactory.cpp index d1cceb5..1644a35 100644 --- a/src/factories/AudioHeaderFactory.cpp +++ b/src/factories/AudioHeaderFactory.cpp @@ -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>(); }
\ No newline at end of file diff --git a/src/factories/AudioHeaderFactory.h b/src/factories/AudioHeaderFactory.h index 5372eb5..ce61413 100644 --- a/src/factories/AudioHeaderFactory.h +++ b/src/factories/AudioHeaderFactory.h @@ -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; } };
\ No newline at end of file diff --git a/src/factories/DisplayListFactory.cpp b/src/factories/DisplayListFactory.cpp index b83ea75..b5d71dd 100644 --- a/src/factories/DisplayListFactory.cpp +++ b/src/factories/DisplayListFactory.cpp @@ -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); diff --git a/src/factories/DisplayListOverrides.cpp b/src/factories/DisplayListOverrides.cpp index 32c9b5c..4e7d1a7 100644 --- a/src/factories/DisplayListOverrides.cpp +++ b/src/factories/DisplayListOverrides.cpp @@ -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; } diff --git a/src/factories/DisplayListOverrides.h b/src/factories/DisplayListOverrides.h index 2da6c52..5b938c1 100644 --- a/src/factories/DisplayListOverrides.h +++ b/src/factories/DisplayListOverrides.h @@ -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); diff --git a/src/factories/LightsFactory.cpp b/src/factories/LightsFactory.cpp index a26a17a..b1cd91e 100644 --- a/src/factories/LightsFactory.cpp +++ b/src/factories/LightsFactory.cpp @@ -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]; diff --git a/src/factories/VtxFactory.cpp b/src/factories/VtxFactory.cpp index 928f1c7..d09e23f 100644 --- a/src/factories/VtxFactory.cpp +++ b/src/factories/VtxFactory.cpp @@ -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); diff --git a/src/factories/sm64/GeoLayoutFactory.cpp b/src/factories/sm64/GeoLayoutFactory.cpp index 5f23254..3a0e524 100644 --- a/src/factories/sm64/GeoLayoutFactory.cpp +++ b/src/factories/sm64/GeoLayoutFactory.cpp @@ -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; - } - - 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; +uint64_t RegisterAutoGen(uint32_t ptr, std::string type) { + if(!Companion::Instance->IsOTRMode()) { + return ptr; } - 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); + YAML::Node node; + node["type"] = type; + node["offset"] = ptr; + const auto result = Companion::Instance->AddAsset(node); - 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"; - 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; - } + 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; + } - 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; + 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; } - auto ndec = Companion::Instance->RegisterAsset(output, dl); + write << "};\n"; - 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; + if (Companion::Instance->IsDebug()) { + write << "// count: " << std::to_string(cmdCount) << " GeoLayout\n"; } - 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))); } } diff --git a/src/factories/sm64/GeoLayoutFactory.h b/src/factories/sm64/GeoLayoutFactory.h index e769b64..2cc7120 100644 --- a/src/factories/sm64/GeoLayoutFactory.h +++ b/src/factories/sm64/GeoLayoutFactory.h @@ -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) }; } }; |
