From 57f61f8e659196586c0bf33bb00765ece006ef9d Mon Sep 17 00:00:00 2001 From: KiritoDv Date: Tue, 21 Nov 2023 00:27:23 -0600 Subject: [PATCH] Added WIP Geo Layout Exporter and some code cleanups --- src/Companion.cpp | 27 +- src/Companion.h | 2 +- src/factories/DisplayListFactory.cpp | 25 +- src/factories/ResourceType.h | 2 +- src/factories/sm64/GeoCommands.h | 436 ----------------- src/factories/sm64/GeoFactory.cpp.old | 594 ------------------------ src/factories/sm64/GeoFactory.h.old | 9 - src/factories/sm64/GeoLayoutFactory.cpp | 561 ++++++++++++++++++++++ src/factories/sm64/GeoLayoutFactory.h | 40 ++ src/factories/sm64/Original.old | 485 +++++++++++++++++++ src/factories/sm64/geo/GeoCommand.h | 208 +++++++++ src/factories/sm64/geo/GeoUtils.cpp | 24 + src/factories/sm64/geo/GeoUtils.h | 8 + src/main.cpp | 6 +- src/utils/TorchUtils.cpp | 20 + src/utils/TorchUtils.h | 23 + 16 files changed, 1400 insertions(+), 1070 deletions(-) delete mode 100644 src/factories/sm64/GeoCommands.h delete mode 100644 src/factories/sm64/GeoFactory.cpp.old delete mode 100644 src/factories/sm64/GeoFactory.h.old create mode 100644 src/factories/sm64/GeoLayoutFactory.cpp create mode 100644 src/factories/sm64/GeoLayoutFactory.h create mode 100644 src/factories/sm64/Original.old create mode 100644 src/factories/sm64/geo/GeoCommand.h create mode 100644 src/factories/sm64/geo/GeoUtils.cpp create mode 100644 src/factories/sm64/geo/GeoUtils.h create mode 100644 src/utils/TorchUtils.cpp create mode 100644 src/utils/TorchUtils.h diff --git a/src/Companion.cpp b/src/Companion.cpp index 5780d29..992445a 100644 --- a/src/Companion.cpp +++ b/src/Companion.cpp @@ -6,6 +6,7 @@ #include "factories/sm64/DialogFactory.h" #include "factories/sm64/DictionaryFactory.h" #include "factories/sm64/TextFactory.h" +#include "factories/sm64/GeoLayoutFactory.h" #include "factories/BankFactory.h" #include "factories/AudioHeaderFactory.h" #include "factories/SampleFactory.h" @@ -49,7 +50,7 @@ void Companion::Init(const ExportType type) { this->RegisterFactory("SM64:TEXT", std::make_shared()); this->RegisterFactory("SM64:DICTIONARY", std::make_shared()); this->RegisterFactory("SM64:ANIM", std::make_shared()); - // this->RegisterFactory("GEO_LAYOUT", new SGeoFactory()); + this->RegisterFactory("SM64:GEO_LAYOUT", std::make_shared()); // MK64 specific this->RegisterFactory("MK64:TRACKWAYPOINTS", std::make_shared()); @@ -61,10 +62,15 @@ void Companion::ExtractNode(YAML::Node& node, std::string& name, SWrapper* binar std::ostringstream stream; auto type = node["type"].as(); - auto offset = node["offset"].as(); std::transform(type.begin(), type.end(), type.begin(), ::toupper); - SPDLOG_INFO("[{}] Processing {} at 0x{:X}", type, name, offset); + if(node["offset"]) { + auto offset = node["offset"].as(); + SPDLOG_INFO("[{}] Processing {} at 0x{:X}", type, name, offset); + } else { + SPDLOG_INFO("[{}] Processing {}", type, name); + } + auto factory = this->GetFactory(type); if(!factory.has_value()){ SPDLOG_ERROR("No factory found for {}", name); @@ -108,7 +114,9 @@ void Companion::ExtractNode(YAML::Node& node, std::string& name, SWrapper* binar } SPDLOG_INFO("Processed {}", name); - this->gWriteMap[this->gCurrentFile][type].emplace_back(node["offset"].as(), stream.str()); + if(node["offset"]) { + this->gWriteMap[this->gCurrentFile][type].emplace_back(node["offset"].as(), stream.str()); + } } void Companion::Process() { @@ -403,13 +411,18 @@ void Companion::Pack(const std::string& folder, const std::string& output) { wrapper.Close(); } -void Companion::RegisterAsset(const std::string& name, YAML::Node& node) { - if(!node["offset"]) return; +std::optional> Companion::RegisterAsset(const std::string& name, YAML::Node& node) { + if(!node["offset"]) return std::nullopt; + this->gAssetDependencies[this->gCurrentFile][name] = std::make_pair(node, false); auto output = (this->gCurrentDirectory / name).string(); std::replace(output.begin(), output.end(), '\\', '/'); - this->gAddrMap[this->gCurrentFile][node["offset"].as()] = std::make_tuple(output, node); + + auto entry = std::make_tuple(output, node); + this->gAddrMap[this->gCurrentFile][node["offset"].as()] = entry; + + return entry; } void Companion::RegisterFactory(const std::string& type, const std::shared_ptr& factory) { diff --git a/src/Companion.h b/src/Companion.h index 1223f91..f15dcfc 100644 --- a/src/Companion.h +++ b/src/Companion.h @@ -45,7 +45,7 @@ public: static void Pack(const std::string& folder, const std::string& output); std::string NormalizeAsset(const std::string& name) const; - void RegisterAsset(const std::string& name, YAML::Node& node); + std::optional> RegisterAsset(const std::string& name, YAML::Node& node); private: bool gOTRMode = false; bool gIsDebug = false; diff --git a/src/factories/DisplayListFactory.cpp b/src/factories/DisplayListFactory.cpp index ec28ed0..4f01f94 100644 --- a/src/factories/DisplayListFactory.cpp +++ b/src/factories/DisplayListFactory.cpp @@ -5,23 +5,10 @@ #include "Companion.h" #include #include +#include #define C0(pos, width) ((w0 >> (pos)) & ((1U << width) - 1)) -template< typename T > -std::string to_hex(T number, const bool append0x = true) { - std::stringstream stream; - if(append0x) { - stream << "0x"; - } - stream << std::setfill ('0') << std::setw(sizeof(T)*2) - << std::hex << number; - - auto format = stream.str(); - std::transform(format.begin(), format.end(), format.begin(), ::toupper); - return format; -} - void GFXDSetGBIVersion(){ switch (Companion::Instance->GetGBIVersion()) { case GBIVersion::f3d: @@ -270,7 +257,7 @@ std::optional> DListFactory::parse(std::vectorGetNodeByAddr(ptr); if(!dec.has_value()){ - SPDLOG_INFO("Addr to Display list command at 0x{:X} not in yaml, autogenerating it", w1); + SPDLOG_INFO("Addr to Display list command at 0x{:X} not in yaml, autogenerating it", w1); auto addr = Companion::Instance->GetSegmentedAddr(SEGMENT_NUMBER(w1)); if(!addr.has_value()) { SPDLOG_ERROR("Segment data missing from game config\nPlease add an entry for segment {}", SEGMENT_NUMBER(w1)); @@ -279,7 +266,7 @@ std::optional> DListFactory::parse(std::vectorGetRomData(); auto factory = Companion::Instance->GetFactory("GFX")->get(); - std::string output = Companion::Instance->NormalizeAsset("seg" + std::to_string(SEGMENT_NUMBER(w1)) +"_dl_" + to_hex(w1, false)); + std::string output = Companion::Instance->NormalizeAsset("seg" + std::to_string(SEGMENT_NUMBER(w1)) +"_dl_" + Torch::to_hex(w1, false)); YAML::Node dl; dl["type"] = "GFX"; dl["mio0"] = addr.value(); @@ -307,7 +294,7 @@ std::optional> DListFactory::parse(std::vectorGetNodeByAddr(ptr); !decl.has_value()){ - SPDLOG_INFO("Addr to Lights1 command at 0x{:X} not in yaml, autogenerating it", w1); + SPDLOG_INFO("Addr to Lights1 command at 0x{:X} not in yaml, autogenerating it", w1); auto addr = Companion::Instance->GetSegmentedAddr(SEGMENT_NUMBER(w1)); if(!addr.has_value()) { SPDLOG_ERROR("Segment data missing from game config\nPlease add an entry for segment {}", SEGMENT_NUMBER(w1)); @@ -315,7 +302,7 @@ std::optional> DListFactory::parse(std::vectorGetRomData(); auto factory = Companion::Instance->GetFactory("LIGHTS")->get(); - std::string output = Companion::Instance->NormalizeAsset("seg" + std::to_string(SEGMENT_NUMBER(w1)) +"_lights1_" + to_hex(w1, false)); + std::string output = Companion::Instance->NormalizeAsset("seg" + std::to_string(SEGMENT_NUMBER(w1)) +"_lights1_" + Torch::to_hex(w1, false)); YAML::Node light; light["type"] = "lights"; light["mio0"] = addr.value(); @@ -356,7 +343,7 @@ std::optional> DListFactory::parse(std::vectorGetRomData(); auto factory = Companion::Instance->GetFactory("VTX")->get(); - std::string output = Companion::Instance->NormalizeAsset("seg" + std::to_string(SEGMENT_NUMBER(w1)) +"_vtx_" + to_hex(w1, false)); + std::string output = Companion::Instance->NormalizeAsset("seg" + std::to_string(SEGMENT_NUMBER(w1)) +"_vtx_" + Torch::to_hex(w1, false)); YAML::Node vtx; vtx["type"] = "VTX"; vtx["mio0"] = addr.value(); diff --git a/src/factories/ResourceType.h b/src/factories/ResourceType.h index 62a55ce..4e0fb9d 100644 --- a/src/factories/ResourceType.h +++ b/src/factories/ResourceType.h @@ -23,7 +23,7 @@ enum class ResourceType { Anim = 0x414E494D, // ANIM SDialog = 0x53444C47, // SDLG Dictionary = 0x44494354, // DICT - Geo = 0x47454F20, // GEO + GeoLayout = 0x47454F20, // GEO // MK64 Waypoints = 0x46665666, // TrackWaypoints diff --git a/src/factories/sm64/GeoCommands.h b/src/factories/sm64/GeoCommands.h deleted file mode 100644 index e10e2a0..0000000 --- a/src/factories/sm64/GeoCommands.h +++ /dev/null @@ -1,436 +0,0 @@ -#pragma once - -#include "n64/CommandMacros.h" - -typedef float Vec2f[2]; -typedef float Vec3f[3]; // X, Y, Z, where Y is up -typedef int16_t Vec3s[3]; -typedef int32_t Vec3i[3]; -typedef float Vec4f[4]; -typedef int16_t Vec4s[4]; - -#define cur_geo_cmd_u8(offset) \ - (cmd[CMD_PROCESS_OFFSET(offset)]) - -#define cur_geo_cmd_s16(offset) \ - BSWAP16((*(int16_t *) &cmd[CMD_PROCESS_OFFSET(offset)])) - -#define cur_geo_cmd_i32(offset) \ - (*(int32_t *) &cmd[CMD_PROCESS_OFFSET(offset)]) - -#define cur_geo_cmd_u32(offset) \ - BSWAP32((*(uint32_t *) &cmd[CMD_PROCESS_OFFSET(offset)])) - -#define CMD_NOP(c) GeoCommand::c: writer->Write((uint32_t) GeoCommand::c); cmd += 0x04 << CMD_SIZE_SHIFT; print_cmd(c, #c); break; -//#define CMD_NOP(c) GeoCommand::c: cmd += 0x04 << CMD_SIZE_SHIFT; print_cmd(c, #c); break; -#define CMD_INFO(c) GeoCommand::c: print_cmd(c, #c); -#define next_s16_in_geo_script(src) ((uint32_t)(*(*src)++)) - -#define cur_geo_cmd_s32(offset) \ - (*(s32 *) &cmd[CMD_PROCESS_OFFSET(offset)]) - -/** - * 0x00: Branch and store return address - * 0x04: scriptTarget, segment address of geo layout - */ -#define GEO_BRANCH_AND_LINK(scriptTarget) \ - CMD_BBH(0x00, 0x00, 0x0000), \ - CMD_PTR(scriptTarget) - -/** - * 0x01: Terminate geo layout - * 0x01-0x03: unused - */ -#define GEO_END() \ - CMD_BBH(0x01, 0x00, 0x0000) - -/** - * 0x02: Branch - * 0x01: if 1, store next geo layout address on stack - * 0x02-0x03: unused - * 0x04: scriptTarget, segment address of geo layout - */ -#define GEO_BRANCH(type, scriptTarget) \ - CMD_BBH(0x02, type, 0x0000), \ - CMD_PTR(scriptTarget) - -/** - * 0x03: Return from branch - * 0x01-0x03: unused - */ -#define GEO_RETURN() \ - CMD_BBH(0x03, 0x00, 0x0000) - -/** - * 0x04: Open node - * 0x01-0x03: unused - */ -#define GEO_OPEN_NODE() \ - CMD_BBH(0x04, 0x00, 0x0000) - -/** - * 0x05: Close node - * 0x01-0x03: unused - */ -#define GEO_CLOSE_NODE() \ - CMD_BBH(0x05, 0x00, 0x0000) - -/** - * 0x06: Register the current node at the given index in the gGeoViews array - * 0x01: unused - * 0x02: s16 index - */ -#define GEO_ASSIGN_AS_VIEW(index) \ - CMD_BBH(0x06, 0x00, index) - -/** - * 0x07: Update current scene graph node flags - * 0x01: u8 operation (0 = reset, 1 = set, 2 = clear) - * 0x02: s16 bits - */ -#define GEO_UPDATE_NODE_FLAGS(operation, flagBits) \ - CMD_BBH(0x07, operation, flagBits) - -/** - * 0x08: Create screen area scene graph node - * 0x01: unused - * 0x02: s16 num entries (+2) to allocate - * 0x04: s16 x - * 0x06: s16 y - * 0x08: s16 width - * 0x0A: s16 height - */ -#define GEO_NODE_SCREEN_AREA(numEntries, x, y, width, height) \ - CMD_BBH(0x08, 0x00, numEntries), \ - CMD_HH(x, y), \ - CMD_HH(width, height) - -/** - * 0x09: Create orthographic projection scene graph node - * 0x02: s16 scale as percentage - */ -#define GEO_NODE_ORTHO(scale) \ - CMD_BBH(0x09, 0x00, scale) - -/** - * 0x0A: Create camera frustum scene graph node - * 0x01: u8 if nonzero, enable function field - * 0x02: s16 field of view - * 0x04: s16 near - * 0x06: s16 far - * 0x08: [GraphNodeFunc function] -*/ -#define GEO_CAMERA_FRUSTUM(fov, near, far) \ - CMD_BBH(0x0A, 0x00, fov), \ - CMD_HH(near, far) - -#define GEO_CAMERA_FRUSTUM_WITH_FUNC(fov, near, far, func) \ - CMD_BBH(0x0A, 0x01, fov), \ - CMD_HH(near, far), \ - CMD_PTR(func) - -/** - * 0x0B: Create a root scene graph node - * 0x01-0x03: unused - */ -#define GEO_NODE_START() \ - CMD_BBH(0x0B, 0x00, 0x0000) - -/** - * 0x0C: Create zbuffer-toggling scene graph node - * 0x01: u8 enableZBuffer (1 = on, 0 = off) - * 0x02-0x03: unused - */ -#define GEO_ZBUFFER(enable) \ - CMD_BBH(0x0C, enable, 0x0000) - -/** - * 0x0D: Create render range scene graph node - * 0x01-0x03: unused - * 0x04: s16 minDistance - * 0x06: s16 maxDistance - */ -#define GEO_RENDER_RANGE(minDistance, maxDistance) \ - CMD_BBH(0x0D, 0x00, 0x0000), \ - CMD_HH(minDistance, maxDistance) - -/** - * 0x0E: Create switch-case scene graph node - * 0x01: unused - * 0x02: s16 numCases - * 0x04: GraphNodeFunc caseSelectorFunc - */ -#define GEO_SWITCH_CASE(count, function) \ - CMD_BBH(0x0E, 0x00, count), \ - CMD_PTR(function) - -/** - * 0x0F: Create a camera scene graph node. - * 0x01: unused - * 0x02: s16 camera type - * 0x04: s16 posX - * 0x06: s16 posY - * 0x08: s16 posZ - * 0x0A: s16 focusX - * 0x0C: s16 focusY - * 0x0E: s16 focusZ - * 0x10: GraphNodeFunc function - */ -#define GEO_CAMERA(type, x1, y1, z1, x2, y2, z2, function) \ - CMD_BBH(0x0F, 0x00, type), \ - CMD_HHHHHH(x1, y1, z1, x2, y2, z2), \ - CMD_PTR(function) - -/** - * 0x10: Create translation & rotation scene graph node with optional display list - * Four different versions of 0x10 - * cmd+0x01: u8 params - * 0b1000_0000: if set, enable displayList field and drawingLayer - * 0b0111_0000: fieldLayout (determines how rest of data is formatted - * 0b0000_1111: drawingLayer - * - * fieldLayout = 0: Translate & Rotate - * 0x04: s16 xTranslation - * 0x06: s16 yTranslation - * 0x08: s16 zTranslation - * 0x0A: s16 xRotation - * 0x0C: s16 yRotation - * 0x0E: s16 zRotation - * 0x10: [u32 displayList: if MSbit of params set, display list segmented address] - */ -#define GEO_TRANSLATE_ROTATE(layer, tx, ty, tz, rx, ry, rz) \ - CMD_BBH(0x10, (0x00 | layer), 0x0000), \ - CMD_HHHHHH(tx, ty, tz, rx, ry, rz) -#define GEO_TRANSLATE_ROTATE_WITH_DL(layer, tx, ty, tz, rx, ry, rz, displayList) \ - CMD_BBH(0x10, (0x00 | layer | 0x80), 0x0000), \ - CMD_HHHHHH(tx, ty, tz, rx, ry, rz), \ - CMD_PTR(displayList) - -/** - * fieldLayout = 1: Translate - * 0x02: s16 xTranslation - * 0x04: s16 yTranslation - * 0x06: s16 zTranslation - * 0x08: [u32 displayList: if MSbit of params set, display list segmented address] - */ -#define GEO_TRANSLATE(layer, tx, ty, tz) \ - CMD_BBH(0x10, (0x10 | layer), tx), \ - CMD_HH(ty, tz) -#define GEO_TRANSLATE_WITH_DL(layer, tx, ty, tz, displayList) \ - CMD_BBH(0x10, (0x10 | layer | 0x80), tx), \ - CMD_HH(ty, tz), \ - CMD_PTR(displayList) - -/** - * fieldLayout = 2: Rotate - * 0x02: s16 xRotation - * 0x04: s16 yRotation - * 0x06: s16 zRotation - * 0x08: [u32 displayList: if MSbit of params set, display list segmented address] - */ -#define GEO_ROTATE(layer, rx, ry, rz) \ - CMD_BBH(0x10, (0x20 | layer), rx), \ - CMD_HH(ry, rz) -#define GEO_ROTATE_WITH_DL(layer, rx, ry, rz, displayList) \ - CMD_BBH(0x10, (0x20 | layer | 0x80), rx), \ - CMD_HH(ry, rz), \ - CMD_PTR(displayList) - -/** - * fieldLayout = 3: Rotate Y - * 0x02: s16 yRotation - * 0x04: [u32 displayList: if MSbit of params set, display list segmented address] - */ -#define GEO_ROTATE_Y(layer, ry) \ - CMD_BBH(0x10, (0x30 | layer), ry) -#define GEO_ROTATE_Y_WITH_DL(layer, ry, displayList) \ - CMD_BBH(0x10, (0x30 | layer | 0x80), ry), \ - CMD_PTR(displayList) - -/** - * 0x11: Create translation scene graph node with optional display list - * 0x01: u8 params - * 0b1000_0000: if set, enable displayList field and drawingLayer - * 0b0000_1111: drawingLayer - * 0x02: s16 translationX - * 0x04: s16 translationY - * 0x06: s16 translationZ - * 0x08: [u32 displayList: if MSbit of params set, display list segmented address] - */ -#define GEO_TRANSLATE_NODE(layer, ux, uy, uz) \ - CMD_BBH(0x11, layer, ux), \ - CMD_HH(uy, uz) -#define GEO_TRANSLATE_NODE_WITH_DL(layer, ux, uy, uz, displayList) \ - CMD_BBH(0x11, (layer | 0x80), ux), \ - CMD_HH(uy, uz), \ - CMD_PTR(displayList) - -/** - * 0x12: Create rotation scene graph node with optional display list - * 0x01: u8 params - * 0b1000_0000: if set, enable displayList field and drawingLayer - * 0b0000_1111: drawingLayer - * 0x02: s16 rotationX - * 0x04: s16 rotationY - * 0x06: s16 rotationZ - * 0x08: [u32 displayList: if MSbit of params set, display list segmented address] - */ -#define GEO_ROTATION_NODE(layer, ux, uy, uz) \ - CMD_BBH(0x12, layer, ux), \ - CMD_HH(uy, uz) -#define GEO_ROTATION_NODE_WITH_DL(layer, ux, uy, uz, displayList) \ - CMD_BBH(0x12, (layer | 0x80), ux), \ - CMD_HH(uy, uz), \ - CMD_PTR(displayList) - -/** - * 0x13: Create a scene graph node that is rotated by the object's animation. - * 0x01: u8 drawingLayer - * 0x02: s16 xTranslation - * 0x04: s16 yTranslation - * 0x06: s16 zTranslation - * 0x08: u32 displayList: dislay list segmented address - */ -#define GEO_ANIMATED_PART(layer, x, y, z, displayList) \ - CMD_BBH(0x13, layer, x), \ - CMD_HH(y, z), \ - CMD_PTR(displayList) - -/** - * 0x14: Create billboarding node with optional display list - * 0x01: u8 params - * 0b1000_0000: if set, enable displayList field and drawingLayer - * 0b0000_1111: drawingLayer - * 0x02: s16 xTranslation - * 0x04: s16 yTranslation - * 0x06: s16 zTranslation - * 0x08: [u32 displayList: if MSbit of params is set, display list segmented address] - */ -#define GEO_BILLBOARD_WITH_PARAMS(layer, tx, ty, tz) \ - CMD_BBH(0x14, layer, tx), \ - CMD_HH(ty, tz) -#define GEO_BILLBOARD_WITH_PARAMS_AND_DL(layer, tx, ty, tz, displayList) \ - CMD_BBH(0x14, (layer | 0x80), tx), \ - CMD_HH(ty, tz), \ - CMD_PTR(displayList) -#define GEO_BILLBOARD() \ - GEO_BILLBOARD_WITH_PARAMS(0, 0, 0, 0) - -/** - * 0x15: Create plain display list scene graph node - * 0x01: u8 drawingLayer - * 0x02-0x03: unused - * 0x04: u32 displayList: display list segmented address - */ -#define GEO_DISPLAY_LIST(layer, displayList) \ - CMD_BBH(0x15, layer, 0x0000), \ - CMD_PTR(displayList) - -/** - * 0x16: Create shadow scene graph node - * 0x01: unused - * 0x02: s16 shadowType (cast to u8) - * 0x04: s16 shadowSolidity (cast to u8) - * 0x06: s16 shadowScale - */ -#define GEO_SHADOW(type, solidity, scale) \ - CMD_BBH(0x16, 0x00, type), \ - CMD_HH(solidity, scale) - -/** - * 0x17: Create render object scene graph node - * 0x01-0x03: unused - */ -#define GEO_RENDER_OBJ() \ - CMD_BBH(0x17, 0x00, 0x0000) - -/** - * 0x18: Create dynamically generated displaylist scene graph node - * 0x01: unused - * 0x02: s16 parameter - * 0x04: GraphNodeFunc function - */ -#define GEO_ASM(param, function) \ - CMD_BBH(0x18, 0x00, param), \ - CMD_PTR(function) - -/** - * 0x19: Create background scene graph node - * 0x02: s16 background: background ID, or RGBA5551 color if backgroundFunc is null - * 0x04: GraphNodeFunc backgroundFunc - */ -#define GEO_BACKGROUND(background, function) \ - CMD_BBH(0x19, 0x00, background), \ - CMD_PTR(function) -#define GEO_BACKGROUND_COLOR(background) \ - GEO_BACKGROUND(background, NULL) - -/** - * 0x1A: No operation - */ -#define GEO_NOP_1A() \ - CMD_BBH(0x1A, 0x00, 0x0000), \ - CMD_HH(0x0000, 0x0000) - -/** - * 0x1B: Copy the shared children from an object parent node from a specific view - * to a newly created object parent. - * 0x02: s16 index of array - */ -#define GEO_COPY_VIEW(index) \ - CMD_BBH(0x1B, 0x00, index) - -/** - * 0x1C: Create a held object scene graph node - * cmd+0x01: u8 unused - * cmd+0x02: s16 offsetX - * cmd+0x04: s16 offsetY - * cmd+0x06: s16 offsetZ - * cmd+0x08: GraphNodeFunc nodeFunc - */ -#define GEO_HELD_OBJECT(param, ux, uy, uz, nodeFunc) \ - CMD_BBH(0x1C, param, ux), \ - CMD_HH(uy, uz), \ - CMD_PTR(nodeFunc) - -/** - * 0x1D: Create scale scene graph node with optional display list - * 0x01: u8 params - * 0b1000_0000: if set, enable displayList field and drawingLayer - * 0b0000_1111: drawingLayer - * 0x02-0x03: unused - * 0x04: u32 scale (0x10000 = 1.0) - * 0x08: [u32 displayList: if MSbit of params is set, display list segment address] - */ -#define GEO_SCALE(layer, scale) \ - CMD_BBH(0x1D, layer, 0x0000), \ - CMD_W(scale) -#define GEO_SCALE_WITH_DL(layer, scale, displayList) \ - CMD_BBH(0x1D, (layer | 0x80), 0x0000), \ - CMD_W(scale), \ - CMD_PTR(displayList) - -/** - * 0x1E: No operation - */ -#define GEO_NOP_1E() \ - CMD_BBH(0x1E, 0x00, 0x0000), \ - CMD_HH(0x0000, 0x0000) - -/** - * 0x1F: No operation - */ -#define GEO_NOP_1F() \ - CMD_BBH(0x1F, 0x00, 0x0000), \ - CMD_HH(0x0000, 0x0000), \ - CMD_HH(0x0000, 0x0000), \ - CMD_HH(0x0000, 0x0000) - -/** - * 0x20: Create a scene graph node that specifies for an object the radius that - * is used for frustum culling. - * 0x01: unused - * 0x02: s16 cullingRadius - */ -#define GEO_CULLING_RADIUS(cullingRadius) \ - CMD_BBH(0x20, 0x00, cullingRadius) \ No newline at end of file diff --git a/src/factories/sm64/GeoFactory.cpp.old b/src/factories/sm64/GeoFactory.cpp.old deleted file mode 100644 index e30f73a..0000000 --- a/src/factories/sm64/GeoFactory.cpp.old +++ /dev/null @@ -1,594 +0,0 @@ -#include "SGeoFactory.h" - -#include "spdlog/spdlog.h" -#include "utils/MIODecoder.h" -#include "GeoCommands.h" -#include "Companion.h" -#include - -namespace fs = std::filesystem; - -enum GeoCommand { - BRANCH_AND_LINK, - END, - BRANCH, - RETURN, - OPEN_NODE, - CLOSE_NODE, - ASSIGN_AS_VIEW, - UPDATE_NODE_FLAGS, - NODE_ROOT, - NODE_ORTHO_PROJECTION, - NODE_PERSPECTIVE, - NODE_START, - NODE_MASTER_LIST, - NODE_LEVEL_OF_DETAIL, - NODE_SWITCH_CASE, - NODE_CAMERA, - NODE_TRANSLATION_ROTATION, - NODE_TRANSLATION, - NODE_ROTATION, - NODE_ANIMATED_PART, - NODE_BILLBOARD, - NODE_DISPLAY_LIST, - NODE_SHADOW, - NODE_OBJECT_PARENT, - NODE_ASM, - NODE_BACKGROUND, - NOP, - COPY_VIEW, - NODE_HELD_OBJ, - NODE_SCALE, - NOP2, - NOP3, - NODE_CULLING_RADIUS, - // Custom - BRANCH_AND_LINK_OTR, - BRANCH_OTR, - NODE_SWITCH_CASE_OTR, - NODE_CAMERA_OTR, - NODE_TRANSLATION_ROTATION_OTR, - NODE_TRANSLATION_OTR, - NODE_ROTATION_OTR, - NODE_ANIMATED_PART_OTR, - NODE_BILLBOARD_OTR, - NODE_DISPLAY_LIST_OTR, - NODE_ASM_OTR, - NODE_BACKGROUND_OTR, - NODE_HELD_OBJ_OTR, - NODE_SCALE_OTR -}; - -Vec3s gVec3sZero = { 0, 0, 0 }; - -int16_t *read_vec3s_to_vec3f(Vec3f dst, int16_t *src) { - dst[0] = next_s16_in_geo_script(&src); - dst[1] = next_s16_in_geo_script(&src); - dst[2] = next_s16_in_geo_script(&src); - return src; -} - -int16_t *read_vec3s(Vec3s dst, int16_t *src) { - dst[0] = next_s16_in_geo_script(&src); - dst[1] = next_s16_in_geo_script(&src); - dst[2] = next_s16_in_geo_script(&src); - return src; -} - -int16_t *read_vec3s_angle(Vec3s dst, int16_t *src) { - dst[0] = next_s16_in_geo_script(&src); - dst[1] = next_s16_in_geo_script(&src); - dst[2] = next_s16_in_geo_script(&src); - return src; -} - -void vec3s_copy(Vec3s dest, Vec3s src) { - dest[0] = src[0]; - dest[1] = src[1]; - dest[2] = src[2]; -} - -void vec3s_set(Vec3s dest, int16_t x, int16_t y, int16_t z) { - dest[0] = x; - dest[1] = y; - dest[2] = z; -} - -int current_tab_size = 0; - -static inline void print_cmd(GeoCommand cmd, std::string c){ - if(cmd == GeoCommand::CLOSE_NODE){ - current_tab_size--; - } - - for(int i = 0; i < current_tab_size; i++){ - std::cout << "\t"; - } - - if(cmd == GeoCommand::OPEN_NODE){ - current_tab_size++; - } - - std::cout << "GEO_" << c << "()" << std::endl; -} - -typedef uint32_t GeoLayout; - -bool SGeoFactory::process(LUS::BinaryWriter* writer, YAML::Node& data, std::vector& buffer) { - - WriteHeader(writer, LUS::ResourceType::Blob, 0); - - auto offset = data["offset"].as(); - auto cmd = (uint8_t*) buffer.data() + offset; - auto processing = true; - - std::vector layout; - auto geo_writer = new LUS::BinaryWriter(); - -#define GeoWrite(x) layout.insert(layout.end(), {x}) - - while(processing){ - auto opcode = cmd[0x00]; - switch (opcode) { - case CMD_INFO(BRANCH_AND_LINK) { - geo_writer->Write((uint8_t) BRANCH_AND_LINK_OTR); - uint32_t ptr = SEGMENT_OFFSET(BSWAP32(cur_geo_cmd_u32(0x04))); - auto decl = Companion::Instance->GetNodeByAddr(ptr); - - if(decl.has_value()){ - uint64_t hash = CRC64(std::get<0>(decl.value()).c_str()); - SPDLOG_INFO("Found geo: 0x{:X} Hash: 0x{:X} Path: {}", ptr, hash, std::get<0>(decl.value())); - geo_writer->Write(hash); - } else { - SPDLOG_INFO("Warning: Could not find geo at 0x{:X}", ptr); - geo_writer->Write((uint64_t) 0); - } - - cmd += 0x08 << CMD_SIZE_SHIFT; - break; - } - case CMD_INFO(BRANCH) { - geo_writer->Write((uint8_t) BRANCH_OTR); - geo_writer->Write(cur_geo_cmd_u8(0x01)); - - int32_t ptr = SEGMENT_OFFSET(BSWAP32(cur_geo_cmd_u32(0x04))); - auto decl = Companion::Instance->GetNodeByAddr(ptr); - - if(decl.has_value()){ - uint64_t hash = CRC64(std::get<0>(decl.value()).c_str()); - SPDLOG_INFO("Found geo: 0x{:X} Hash: 0x{:X} Path: {}", ptr, hash, std::get<0>(decl.value())); - geo_writer->Write(hash); - } else { - SPDLOG_INFO("Warning: Could not find geo at 0x{:X}", ptr); - geo_writer->Write((uint64_t) 0); - } - - cmd += 0x08 << CMD_SIZE_SHIFT; - break; - } - case CMD_INFO(END) - geo_writer->Write((uint8_t) END); - processing = false; - break; - case CMD_INFO(RETURN) - geo_writer->Write((uint8_t) RETURN); - processing = false; - break; - case CMD_NOP(OPEN_NODE) - case CMD_NOP(CLOSE_NODE) - case CMD_INFO(ASSIGN_AS_VIEW) { - geo_writer->Write(ASSIGN_AS_VIEW); - geo_writer->Write(cur_geo_cmd_s16(0x02)); - break; - } - case CMD_INFO(UPDATE_NODE_FLAGS) { - geo_writer->Write((uint8_t) UPDATE_NODE_FLAGS); - geo_writer->Write(cur_geo_cmd_u8(0x01)); - geo_writer->Write(cur_geo_cmd_s16(0x02)); - break; - } - case CMD_INFO(NODE_ROOT) { - auto a1 = cur_geo_cmd_s16(0x02); - auto a2 = cur_geo_cmd_s16(0x04); - auto a3 = cur_geo_cmd_s16(0x06); - auto a4 = cur_geo_cmd_s16(0x08); - auto a5 = cur_geo_cmd_s16(0x0A); - GeoWrite(GEO_NODE_SCREEN_AREA(a1, a2, a3, a4, a5)); - cmd += 0x0C << CMD_SIZE_SHIFT; - processing = false; - } - case CMD_INFO(NODE_ORTHO_PROJECTION) { - geo_writer->Write((uint8_t) NODE_ORTHO_PROJECTION); - geo_writer->Write(cur_geo_cmd_s16(0x02)); - cmd += 0x04 << CMD_SIZE_SHIFT; - break; - } - case CMD_INFO(NODE_PERSPECTIVE) { - geo_writer->Write((uint8_t) NODE_PERSPECTIVE); - auto param = cur_geo_cmd_u8(0x01); - auto fov = cur_geo_cmd_s16(0x02); - auto near = cur_geo_cmd_s16(0x04); - auto far = cur_geo_cmd_s16(0x06); - - geo_writer->Write(param); - geo_writer->Write(fov); - geo_writer->Write(near); - geo_writer->Write(far); - - if (param != 0) { - auto func = cur_geo_cmd_u32(0x08); - geo_writer->Write(func); - cmd += 4 << CMD_SIZE_SHIFT; - } - - cmd += 0x08 << CMD_SIZE_SHIFT; - break; - } - case CMD_NOP(NODE_START) - case CMD_INFO(NODE_MASTER_LIST) { - geo_writer->Write((uint8_t) NODE_MASTER_LIST); - geo_writer->Write(cur_geo_cmd_u8(0x01)); - cmd += 0x04 << CMD_SIZE_SHIFT; - break; - } - case CMD_INFO(NODE_LEVEL_OF_DETAIL) { - geo_writer->Write((uint8_t) NODE_LEVEL_OF_DETAIL); - int16_t minDistance = cur_geo_cmd_s16(0x04); - int16_t maxDistance = cur_geo_cmd_s16(0x06); - - geo_writer->Write(minDistance); - geo_writer->Write(maxDistance); - - cmd += 0x08 << CMD_SIZE_SHIFT; - break; - } - case CMD_INFO(NODE_SWITCH_CASE) { - geo_writer->Write((uint8_t) NODE_SWITCH_CASE_OTR); - auto cs = cur_geo_cmd_s16(0x02); - auto ptr = cur_geo_cmd_u32(0x04); - - geo_writer->Write(cs); - geo_writer->Write(ptr); - - cmd += 0x08 << CMD_SIZE_SHIFT; - break; - } - case CMD_INFO(NODE_CAMERA) { - geo_writer->Write((uint8_t) NODE_CAMERA_OTR); - auto cmd_pos = (int16_t *) &cmd[4]; - auto mode = cur_geo_cmd_s16(0x02); - - geo_writer->Write(mode); - - Vec3f pos, focus; - - cmd_pos = read_vec3s_to_vec3f(pos, cmd_pos); - read_vec3s_to_vec3f(focus, cmd_pos); - - geo_writer->Write(pos[0]); - geo_writer->Write(pos[1]); - geo_writer->Write(pos[2]); - geo_writer->Write(focus[0]); - geo_writer->Write(focus[1]); - geo_writer->Write(focus[2]); - - auto ptr = SEGMENT_OFFSET(BSWAP32(cur_geo_cmd_u32(0x10))); - geo_writer->Write(ptr); - - cmd += 0x14 << CMD_SIZE_SHIFT; - break; - } - case CMD_INFO(NODE_TRANSLATION_ROTATION) { - geo_writer->Write(NODE_TRANSLATION_ROTATION_OTR); - auto params = cur_geo_cmd_u8(0x01); - auto cmd_pos = (int16_t*) cmd; - - Vec3s translation, rotation; - - geo_writer->Write(params); - - switch ((params & 0x70) >> 4) { - case 0: - cmd_pos = read_vec3s(translation, &cmd_pos[2]); - geo_writer->Write(translation[0]); - geo_writer->Write(translation[1]); - geo_writer->Write(translation[2]); - cmd_pos = read_vec3s_angle(rotation, cmd_pos); - geo_writer->Write(rotation[0]); - geo_writer->Write(rotation[1]); - geo_writer->Write(rotation[2]); - break; - case 1: - cmd_pos = read_vec3s(translation, &cmd_pos[1]); - geo_writer->Write(translation[0]); - geo_writer->Write(translation[1]); - geo_writer->Write(translation[2]); - break; - case 2: - cmd_pos = read_vec3s_angle(rotation, &cmd_pos[1]); - geo_writer->Write(rotation[0]); - geo_writer->Write(rotation[1]); - geo_writer->Write(rotation[2]); - break; - case 3: - cmd_pos += 2 << CMD_SIZE_SHIFT; - break; - } - - if (params & 0x80) { - auto dlist = SEGMENT_OFFSET(BSWAP32(*(uint32_t*) &cmd_pos[0])); - auto decl = Companion::Instance->GetNodeByAddr(dlist); - if(decl.has_value()){ - uint64_t hash = CRC64(std::get<0>(decl.value()).c_str()); - SPDLOG_INFO("Found display list: 0x{:X} Hash: 0x{:X} Path: {}", dlist, hash, std::get<0>(decl.value())); - geo_writer->Write(hash); - } else { - SPDLOG_INFO("Warning: Could not find display list at 0x{:X}", dlist); - geo_writer->Write((uint64_t) 0); - } - cmd_pos += 2 << CMD_SIZE_SHIFT; - } - - cmd = (uint8_t*) cmd_pos; - break; - } - case CMD_INFO(NODE_TRANSLATION) { - geo_writer->Write(NODE_TRANSLATION_OTR); - auto params = cur_geo_cmd_u8(0x01); - auto cmd_pos = (int16_t*) cmd; - - Vec3s translation; - cmd_pos = read_vec3s(translation, &cmd_pos[1]); - - geo_writer->Write(translation[0]); - geo_writer->Write(translation[1]); - geo_writer->Write(translation[2]); - - if (params & 0x80) { - auto dlist = SEGMENT_OFFSET(BSWAP32(*(uint32_t*) &cmd_pos[0])); - auto decl = Companion::Instance->GetNodeByAddr(dlist); - if(decl.has_value()){ - uint64_t hash = CRC64(std::get<0>(decl.value()).c_str()); - SPDLOG_INFO("Found display list: 0x{:X} Hash: 0x{:X} Path: {}", dlist, hash, std::get<0>(decl.value())); - geo_writer->Write(hash); - } else { - SPDLOG_INFO("Warning: Could not find display list at 0x{:X}", dlist); - geo_writer->Write((uint64_t) 0); - } - cmd_pos += 2 << CMD_SIZE_SHIFT; - } - - cmd = (uint8_t*) cmd_pos; - break; - } - case CMD_INFO(NODE_ROTATION) { - geo_writer->Write(NODE_ROTATION_OTR); - auto params = cur_geo_cmd_u8(0x01); - auto cmd_pos = (int16_t*) cmd; - - Vec3s sp2c; - cmd_pos = read_vec3s(sp2c, &cmd_pos[1]); - - geo_writer->Write(sp2c[0]); - geo_writer->Write(sp2c[1]); - geo_writer->Write(sp2c[2]); - - if (params & 0x80) { - auto dlist = SEGMENT_OFFSET(BSWAP32(*(uint32_t*) &cmd_pos[0])); - auto decl = Companion::Instance->GetNodeByAddr(dlist); - if(decl.has_value()){ - uint64_t hash = CRC64(std::get<0>(decl.value()).c_str()); - SPDLOG_INFO("Found display list: 0x{:X} Hash: 0x{:X} Path: {}", dlist, hash, std::get<0>(decl.value())); - geo_writer->Write(hash); - } else { - SPDLOG_INFO("Warning: Could not find display list at 0x{:X}", dlist); - geo_writer->Write((uint64_t) 0); - } - cmd_pos += 2 << CMD_SIZE_SHIFT; - } - - cmd = (uint8_t*) cmd_pos; - break; - } - case CMD_INFO(NODE_ANIMATED_PART) { - geo_writer->Write(NODE_ANIMATED_PART_OTR); - - auto layer = cur_geo_cmd_u8(0x01); - auto ptr = cur_geo_cmd_u32(0x08); - - geo_writer->Write(layer); - geo_writer->Write(ptr); - - auto dlist = SEGMENT_OFFSET(BSWAP32(cur_geo_cmd_u32(0x08))); - auto decl = Companion::Instance->GetNodeByAddr(dlist); - if(decl.has_value()){ - uint64_t hash = CRC64(std::get<0>(decl.value()).c_str()); - SPDLOG_INFO("Found display list: 0x{:X} Hash: 0x{:X} Path: {}", dlist, hash, std::get<0>(decl.value())); - geo_writer->Write(hash); - } else { - SPDLOG_INFO("Warning: Could not find display list at 0x{:X}", dlist); - geo_writer->Write((uint64_t) 0); - } - - cmd += 0x0C << CMD_SIZE_SHIFT; - break; - } - case CMD_INFO(NODE_BILLBOARD) { - geo_writer->Write(NODE_BILLBOARD_OTR); - - Vec3s translation; - auto params = cur_geo_cmd_u8(0x01); - auto cmd_pos = (int16_t*) cmd; - - cmd_pos = read_vec3s(translation, &cmd_pos[1]); - geo_writer->Write(params); - if (params & 0x80) { - auto dlist = SEGMENT_OFFSET(BSWAP32(*(uint32_t*) &cmd_pos[0])); - auto decl = Companion::Instance->GetNodeByAddr(dlist); - if (decl.has_value()) { - uint64_t hash = CRC64(std::get<0>(decl.value()).c_str()); - SPDLOG_INFO("Found display list: 0x{:X} Hash: 0x{:X} Path: {}", dlist, hash, - std::get<0>(decl.value())); - geo_writer->Write(hash); - } else { - SPDLOG_INFO("Warning: Could not find display list at 0x{:X}", dlist); - geo_writer->Write((uint64_t) 0); - } - - cmd_pos += 2 << CMD_SIZE_SHIFT; - } - - cmd = (uint8_t*) cmd_pos; - break; - } - case CMD_INFO(NODE_DISPLAY_LIST) { - geo_writer->Write((uint8_t) NODE_DISPLAY_LIST_OTR); - - int32_t layer = cur_geo_cmd_u8(0x01); - auto ptr = SEGMENT_OFFSET(BSWAP32(cur_geo_cmd_u32(0x04))); - - geo_writer->Write(layer); - - auto decl = Companion::Instance->GetNodeByAddr(ptr); - - if(decl.has_value()){ - uint64_t hash = CRC64(std::get<0>(decl.value()).c_str()); - SPDLOG_INFO("Found display list: 0x{:X} Hash: 0x{:X} Path: {}", ptr, hash, std::get<0>(decl.value())); - geo_writer->Write(hash); - } else { - SPDLOG_INFO("Warning: Could not find display list at 0x{:X}", ptr); - geo_writer->Write((uint64_t) 0); - } - - cmd += 0x08 << CMD_SIZE_SHIFT; - break; - } - case CMD_INFO(NODE_SHADOW) { - geo_writer->Write((uint8_t) NODE_SHADOW); - auto type = cur_geo_cmd_s16(0x02); - auto solidity = cur_geo_cmd_s16(0x04); - auto scale = cur_geo_cmd_s16(0x06); - - geo_writer->Write(type); - geo_writer->Write(solidity); - geo_writer->Write(scale); - - cmd += 0x08 << CMD_SIZE_SHIFT; - break; - } - case CMD_NOP(NODE_OBJECT_PARENT) - case CMD_INFO(NODE_ASM) { - geo_writer->Write(NODE_ASM_OTR); - auto param = cur_geo_cmd_s16(0x02); - auto ptr = cur_geo_cmd_u32(0x04); - - geo_writer->Write(param); - geo_writer->Write(SEGMENT_OFFSET(BSWAP32(ptr))); - cmd += 0x08 << CMD_SIZE_SHIFT; - break; - } - case CMD_INFO(NODE_BACKGROUND) { - geo_writer->Write((uint8_t) NODE_BACKGROUND_OTR); - auto bg = cur_geo_cmd_s16(0x02); - geo_writer->Write(bg); - - auto ptr = SEGMENT_OFFSET(BSWAP32(cur_geo_cmd_u32(0x04))); - geo_writer->Write(ptr); - - cmd += 0x08 << CMD_SIZE_SHIFT; - break; - } - case CMD_INFO(NOP) { - geo_writer->Write((uint8_t) NOP); - geo_writer->Write((uint32_t) 0); - geo_writer->Write((uint32_t) 0); - cmd += 0x08 << CMD_SIZE_SHIFT; - break; - } - case CMD_INFO(COPY_VIEW) { - geo_writer->Write((uint32_t) COPY_VIEW); - auto idx = cur_geo_cmd_s16(0x02); - geo_writer->Write(idx); - break; - } - case CMD_INFO(NODE_HELD_OBJ) { - geo_writer->Write((uint8_t) NODE_HELD_OBJ_OTR); - - auto idx = cur_geo_cmd_u8(0x01); - geo_writer->Write(idx); - - Vec3s c_offset; - read_vec3s(c_offset, (int16_t*) &cmd[0x02]); - - geo_writer->Write(c_offset[0]); - geo_writer->Write(c_offset[1]); - geo_writer->Write(c_offset[2]); - - auto ptr = SEGMENT_OFFSET(BSWAP32(cur_geo_cmd_u32(0x08))); - geo_writer->Write(ptr); - - cmd += 0x0C << CMD_SIZE_SHIFT; - break; - } - case CMD_INFO(NODE_SCALE) { - geo_writer->Write(NODE_SCALE_OTR); - auto params = cur_geo_cmd_u8(0x01); - auto scale = cur_geo_cmd_u32(0x04); - - geo_writer->Write(params); - geo_writer->Write(scale); - - if (params & 0x80) { - auto dlist = SEGMENT_OFFSET(BSWAP32(cur_geo_cmd_u32(0x08))); - auto decl = Companion::Instance->GetNodeByAddr(dlist); - if(decl.has_value()){ - uint64_t hash = CRC64(std::get<0>(decl.value()).c_str()); - SPDLOG_INFO("Found display list: 0x{:X} Hash: 0x{:X} Path: {}", dlist, hash, std::get<0>(decl.value())); - geo_writer->Write(hash); - } else { - SPDLOG_INFO("Warning: Could not find display list at 0x{:X}", dlist); - geo_writer->Write((uint64_t) 0); - } - cmd += 4 << CMD_SIZE_SHIFT; - } - break; - } - case CMD_INFO(NOP2) { - geo_writer->Write((uint8_t) NOP2); - geo_writer->Write((uint32_t) 0); - geo_writer->Write((uint32_t) 0); - cmd += 0x08 << CMD_SIZE_SHIFT; - break; - } - case CMD_INFO(NOP3) { - geo_writer->Write((uint8_t) NOP3); - geo_writer->Write((uint32_t) 0); - geo_writer->Write((uint32_t) 0); - geo_writer->Write((uint32_t) 0); - cmd += 0x10 << CMD_SIZE_SHIFT; - break; - } - case CMD_INFO(NODE_CULLING_RADIUS) { - geo_writer->Write((uint8_t) NODE_CULLING_RADIUS); - auto radius = cur_geo_cmd_s16(0x02); - geo_writer->Write(radius); - break; - } - default: - std::cout << "Unknown command: " << std::hex << (int) cmd[0x00] << std::endl; - break; - } - } - - auto size = geo_writer->GetLength(); - auto data_ptr = geo_writer->ToVector(); -// auto s = size + layout.size() * sizeof(GeoLayout); -// writer->Write(s); -// writer->Write(data_ptr.data(), size); - - writer->Write((uint32_t) layout.size()); - writer->Write((char*) layout.data(), layout.size() * sizeof(GeoLayout)); - geo_writer->Close(); - - return true; -} diff --git a/src/factories/sm64/GeoFactory.h.old b/src/factories/sm64/GeoFactory.h.old deleted file mode 100644 index 331e072..0000000 --- a/src/factories/sm64/GeoFactory.h.old +++ /dev/null @@ -1,9 +0,0 @@ -#pragma once - -#include "../RawFactory.h" - -class SGeoFactory : public RawFactory { -public: - SGeoFactory() = default; - bool process(LUS::BinaryWriter* write, YAML::Node& data, std::vector& buffer) override; -}; \ No newline at end of file diff --git a/src/factories/sm64/GeoLayoutFactory.cpp b/src/factories/sm64/GeoLayoutFactory.cpp new file mode 100644 index 0000000..db73be4 --- /dev/null +++ b/src/factories/sm64/GeoLayoutFactory.cpp @@ -0,0 +1,561 @@ +#include "GeoLayoutFactory.h" + +#include "spdlog/spdlog.h" +#include "utils/MIODecoder.h" +#include "geo/GeoCommand.h" +#include "Companion.h" +#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->GetSegmentedAddr(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; + } + + 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())); + return hash; + } + + return 0; +} + +uint64_t RegisterOrLoadDisplayList(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 Display List: 0x{:X} Hash: 0x{:X} Path: {}", ptr, hash, std::get<0>(dec.value())); + return hash; + } + + SPDLOG_INFO("Addr to Display List at 0x{:X} not in yaml, autogenerating it", ptr); + auto addr = Companion::Instance->GetSegmentedAddr(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; + } + + 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"] = 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; +} + +void SM64::GeoBinaryExporter::Export(std::ostream&write, std::shared_ptr data, std::string&entryName, YAML::Node&node, std::string* replacement) { + const auto layout = std::static_pointer_cast(data).get(); + + auto writer = LUS::BinaryWriter(); + + for(auto& [opcode, arguments] : layout->commands) { + writer.Write(static_cast(opcode)); + + for(auto& args : arguments) { + switch(args.index()) { + case 0: { + writer.Write(std::get(args)); + break; + } + case 1: { + writer.Write(std::get(args)); + break; + } + case 2: { + writer.Write(std::get(args)); + break; + } + case 3: { + writer.Write(std::get(args)); + break; + } + case 4: { + writer.Write(std::get(args)); + break; + } + case 5: { + writer.Write(std::get(args)); + break; + } + case 6: { + writer.Write(std::get(args)); + break; + } + case 7: { + const auto [x, y] = std::get(args); + writer.Write(x); + writer.Write(y); + break; + } + case 8: { + const auto [x, y, z] = std::get(args); + writer.Write(x); + writer.Write(y); + writer.Write(z); + break; + } + case 9: { + const auto [x, y, z] = std::get(args); + writer.Write(x); + writer.Write(y); + writer.Write(z); + break; + } + case 10: { + const auto [x, y, z] = std::get(args); + writer.Write(x); + writer.Write(y); + writer.Write(z); + break; + } + case 11: { + const auto [x, y, z, w] = std::get(args); + writer.Write(x); + writer.Write(y); + writer.Write(z); + writer.Write(w); + break; + } + case 12: { + const auto [x, y, z, w] = std::get(args); + writer.Write(x); + writer.Write(y); + writer.Write(z); + writer.Write(w); + break; + } + default: { + break; + } + } + } + } + + std::vector buffer = writer.ToVector(); + writer.Close(); + + LUS::BinaryWriter output = LUS::BinaryWriter(); + WriteHeader(output, LUS::ResourceType::Blob, 0); + + output.Write(static_cast(buffer.size())); + output.Write(buffer.data(), buffer.size()); + output.Finish(write); + output.Close(); +} + +void SM64::GeoHeaderExporter::Export(std::ostream&write, std::shared_ptr data, std::string&entryName, YAML::Node&node, std::string* replacement) { + +} + +std::optional> SM64::GeoLayoutFactory::parse(std::vector& buffer, YAML::Node& node) { + const size_t offset = Torch::translate(node["offset"].as()); + auto cmd = buffer.data() + offset; + bool processing = true; + std::vector commands; + + while(processing) { + auto opcode = static_cast(cmd[0x00]); + + SPDLOG_INFO("Processing Command {}", opcode); + + std::vector arguments; + + switch(opcode){ + case GeoOpcode::BranchAndLink: { + uint32_t ptr = cur_geo_cmd_u32(0x04); + arguments.emplace_back(ptr); + arguments.emplace_back(RegisterOrLoadGeoLayout(ptr)); + + cmd += 0x08 << CMD_SIZE_SHIFT; + break; + } + case GeoOpcode::End: { + processing = false; + break; + } + case GeoOpcode::Branch: { + auto jmp = cur_geo_cmd_u8(0x01); + auto ptr = cur_geo_cmd_u32(0x04); + + arguments.emplace_back(jmp); + arguments.emplace_back(RegisterOrLoadGeoLayout(ptr)); + + cmd += 0x08 << CMD_SIZE_SHIFT; + break; + } + case GeoOpcode::Return: + case GeoOpcode::OpenNode: + case GeoOpcode::CloseNode: { + cmd += 0x04 << CMD_SIZE_SHIFT; + break; + } + case GeoOpcode::AssignAsView: { + auto idx = cur_geo_cmd_s16(0x02); + arguments.emplace_back(idx); + + cmd += 0x04 << CMD_SIZE_SHIFT; + break; + } + case GeoOpcode::UpdateNodeFlags: { + auto operation = cur_geo_cmd_u8(0x01); + auto flags = cur_geo_cmd_s16(0x02); + arguments.emplace_back(operation); + arguments.emplace_back(flags); + + cmd += 0x04 << CMD_SIZE_SHIFT; + break; + } + case GeoOpcode::NodeRoot: { + auto views = cur_geo_cmd_s16(0x02); + auto x = cur_geo_cmd_s16(0x04); + auto y = cur_geo_cmd_s16(0x06); + auto width = cur_geo_cmd_s16(0x08); + auto height = cur_geo_cmd_s16(0x0A); + + arguments.emplace_back(views); + arguments.emplace_back(x); + arguments.emplace_back(y); + arguments.emplace_back(width); + arguments.emplace_back(height); + + cmd += 0x0C << CMD_SIZE_SHIFT; + break; + } + case GeoOpcode::NodeOrthoProjection: { + auto scale = cur_geo_cmd_s16(0x02); + arguments.emplace_back(scale); + + cmd += 0x04 << CMD_SIZE_SHIFT; + break; + } + case GeoOpcode::NodePerspective: { + auto opt = cur_geo_cmd_u8(0x01); + auto fov = cur_geo_cmd_s16(0x02); + auto near = cur_geo_cmd_s16(0x04); + auto far = cur_geo_cmd_s16(0x06); + + arguments.emplace_back(opt); + arguments.emplace_back(fov); + arguments.emplace_back(near); + arguments.emplace_back(far); + + if (opt != 0) { + // optional asm function + auto ptr = cur_geo_cmd_u32(0x08); + arguments.emplace_back(ptr); + + cmd += 0x04 << CMD_SIZE_SHIFT; + } + + cmd += 0x08 << CMD_SIZE_SHIFT; + break; + } + case GeoOpcode::NodeStart: { + cmd += 0x04 << CMD_SIZE_SHIFT; + break; + } + case GeoOpcode::NodeMasterList: { + auto list = cur_geo_cmd_u8(0x01); + arguments.emplace_back(list); + + cmd += 0x04 << CMD_SIZE_SHIFT; + break; + } + case GeoOpcode::NodeLevelOfDetail: { + auto min = cur_geo_cmd_s16(0x02); + auto max = cur_geo_cmd_s16(0x04); + + arguments.emplace_back(min); + arguments.emplace_back(max); + + cmd += 0x08 << CMD_SIZE_SHIFT; + break; + } + case GeoOpcode::NodeSwitchCase: { + auto cs = cur_geo_cmd_s16(0x02); + auto ptr = cur_geo_cmd_u32(0x04); + + arguments.emplace_back(cs); + arguments.emplace_back(ptr); + + cmd += 0x08 << CMD_SIZE_SHIFT; + break; + } + case GeoOpcode::NodeCamera: { + auto cmd_pos = reinterpret_cast(&cmd[4]); + + Vec3f pos = {}; + Vec3f focus = {}; + cmd_pos = read_vec3s_to_vec3f(pos, cmd_pos); + read_vec3s_to_vec3f(focus, cmd_pos); + + auto ptr = cur_geo_cmd_u32(0x10); + auto type = cur_geo_cmd_s16(0x02); + + arguments.emplace_back(pos); + arguments.emplace_back(focus); + arguments.emplace_back(ptr); + arguments.emplace_back(type); + + cmd += 0x14 << CMD_SIZE_SHIFT; + break; + } + case GeoOpcode::NodeTranslationRotation: { + + Vec3s translation = {}; + Vec3s rotation = {}; + auto params = cur_geo_cmd_u8(0x01); + auto cmd_pos = reinterpret_cast(&cmd[0x04]); + + arguments.emplace_back(params); + + switch ((params & 0x70) >> 4) { + case 0: + cmd_pos = read_vec3s(translation, &cmd_pos[2]); + cmd_pos = read_vec3s_angle(rotation, cmd_pos); + arguments.emplace_back(translation); + arguments.emplace_back(rotation); + break; + case 1: + cmd_pos = read_vec3s(translation, &cmd_pos[1]); + arguments.emplace_back(translation); + break; + case 2: + cmd_pos = read_vec3s_angle(rotation, &cmd_pos[1]); + arguments.emplace_back(rotation); + break; + case 3: + arguments.emplace_back(cmd_pos[1]); + cmd_pos += 2 << CMD_SIZE_SHIFT; + break; + default: { + break; + } + } + + if (params & 0x80) { + auto ptr = *reinterpret_cast(&cmd_pos[0]); + arguments.emplace_back(RegisterOrLoadDisplayList(ptr)); + cmd_pos += 2 << CMD_SIZE_SHIFT; + } + + cmd = reinterpret_cast(cmd_pos); + break; + } + case GeoOpcode::NodeTranslation: + case GeoOpcode::NodeRotation: { + Vec3s vector = {}; + auto params = cur_geo_cmd_u8(0x01); + auto cmd_pos = reinterpret_cast(cmd); + + arguments.emplace_back(params); + + cmd_pos = read_vec3s_angle(vector, &cmd_pos[1]); + + if (params & 0x80) { + auto ptr = *reinterpret_cast(&cmd_pos[0]); + arguments.emplace_back(RegisterOrLoadDisplayList(ptr)); + cmd_pos += 2 << CMD_SIZE_SHIFT; + } + + cmd = reinterpret_cast(cmd_pos); + break; + } + case GeoOpcode::NodeAnimatedPart: { + + Vec3s translation = {}; + auto layer = cur_geo_cmd_u8(0x01); + auto ptr = cur_geo_cmd_u32(0x08); + auto cmd_pos = reinterpret_cast(cmd); + + arguments.emplace_back(layer); + arguments.emplace_back(RegisterOrLoadDisplayList(ptr)); + + read_vec3s(translation, &cmd_pos[1]); + arguments.emplace_back(translation); + + cmd += 0x0C << CMD_SIZE_SHIFT; + break; + } + case GeoOpcode::NodeBillboard: { + + Vec3s translation = {}; + auto params = cur_geo_cmd_u8(0x01); + auto cmd_pos = reinterpret_cast(cmd); + + read_vec3s(translation, &cmd_pos[1]); + + arguments.emplace_back(params); + arguments.emplace_back(translation); + + if (params & 0x80) { + auto ptr = *reinterpret_cast(&cmd_pos[0]); + arguments.emplace_back(RegisterOrLoadDisplayList(ptr)); + cmd_pos += 0x02 << CMD_SIZE_SHIFT; + } + + cmd = reinterpret_cast(cmd_pos); + break; + } + case GeoOpcode::NodeDisplayList: { + auto layer = cur_geo_cmd_u8(0x01); + auto ptr = cur_geo_cmd_u32(0x04); + + arguments.emplace_back(layer); + arguments.emplace_back(RegisterOrLoadDisplayList(ptr)); + + cmd += 0x08 << CMD_SIZE_SHIFT; + break; + } + case GeoOpcode::NodeShadow: { + auto type = cur_geo_cmd_s16(0x02); + auto solidity = cur_geo_cmd_s16(0x04); + auto scale = cur_geo_cmd_s16(0x06); + + arguments.emplace_back(type); + arguments.emplace_back(solidity); + arguments.emplace_back(scale); + + cmd += 0x08 << CMD_SIZE_SHIFT; + break; + } + case GeoOpcode::NodeObjectParent: { + cmd += 0x04 << CMD_SIZE_SHIFT; + break; + } + case GeoOpcode::NodeAsm: { + auto param = cur_geo_cmd_s16(0x02); + auto ptr = cur_geo_cmd_u32(0x04); + + arguments.emplace_back(param); + arguments.emplace_back(ptr); + SPDLOG_INFO("Found ASM: 0x{:X}", ptr); + + cmd += 0x08 << CMD_SIZE_SHIFT; + break; + } + case GeoOpcode::NodeBackground: { + auto bg = cur_geo_cmd_s16(0x02); + auto ptr = cur_geo_cmd_u32(0x04); + + arguments.emplace_back(bg); + arguments.emplace_back(ptr); + + cmd += 0x08 << CMD_SIZE_SHIFT; + break; + } + case GeoOpcode::NOP: { + cmd += 0x08 << CMD_SIZE_SHIFT; + break; + } + case GeoOpcode::CopyView: { + auto idx = cur_geo_cmd_s16(0x02); + + arguments.emplace_back(idx); + + cmd += 0x04 << CMD_SIZE_SHIFT; + break; + } + case GeoOpcode::NodeHeldObj: { + auto ptr = cur_geo_cmd_u32(0x08); + auto player = cur_geo_cmd_u8(0x01); + + arguments.emplace_back(ptr); + arguments.emplace_back(player); + + Vec3s vec = {}; + read_vec3s(vec, reinterpret_cast(&cmd[0x02])); + + arguments.emplace_back(vec); + + cmd += 0x0C << CMD_SIZE_SHIFT; + break; + } + case GeoOpcode::NodeScale: { + auto params = cur_geo_cmd_u8(0x01); + auto scale = cur_geo_cmd_u32(0x04); + + arguments.emplace_back(params); + arguments.emplace_back(scale); + + if (params & 0x80) { + auto ptr = cur_geo_cmd_u32(0x08); + arguments.emplace_back(RegisterOrLoadDisplayList(ptr)); + cmd += 0x04 << CMD_SIZE_SHIFT; + } + + cmd += 0x08 << CMD_SIZE_SHIFT; + break; + } + case GeoOpcode::NOP2: { + cmd += 0x08 << CMD_SIZE_SHIFT; + break; + } + case GeoOpcode::NOP3: { + cmd += 0x10 << CMD_SIZE_SHIFT; + break; + } + case GeoOpcode::NodeCullingRadius: { + auto radius = cur_geo_cmd_s16(0x02); + + arguments.emplace_back(radius); + + cmd += 0x04 << CMD_SIZE_SHIFT; + break; + } + default: { + SPDLOG_ERROR("Unknown geo command {}", opcode); + throw std::runtime_error("Unknown geo command"); + } + } + + commands.push_back({opcode, arguments}); + } + + return std::make_shared(commands); +} diff --git a/src/factories/sm64/GeoLayoutFactory.h b/src/factories/sm64/GeoLayoutFactory.h new file mode 100644 index 0000000..24956de --- /dev/null +++ b/src/factories/sm64/GeoLayoutFactory.h @@ -0,0 +1,40 @@ +#pragma once + +#include "../BaseFactory.h" +#include "geo/GeoCommand.h" + +namespace SM64 { + +typedef std::variant GeoArgument; + +struct GeoCommand { + GeoOpcode opcode; + std::vector arguments; +}; + +class GeoLayout : public IParsedData { +public: + std::vector commands; + + explicit GeoLayout(std::vector commands) : commands(std::move(commands)) {} +}; + +class GeoHeaderExporter : public BaseExporter { + void Export(std::ostream& write, std::shared_ptr data, std::string& entryName, YAML::Node& node, std::string* replacement) override; +}; + +class GeoBinaryExporter : public BaseExporter { + void Export(std::ostream& write, std::shared_ptr data, std::string& entryName, YAML::Node& node, std::string* replacement) override; +}; + +class GeoLayoutFactory : public BaseFactory { +public: + std::optional> parse(std::vector& buffer, YAML::Node& data) override; + std::unordered_map> GetExporters() override { + return { + REGISTER(Header, GeoHeaderExporter) + REGISTER(Binary, GeoBinaryExporter) + }; + } +}; +} diff --git a/src/factories/sm64/Original.old b/src/factories/sm64/Original.old new file mode 100644 index 0000000..9f59aa4 --- /dev/null +++ b/src/factories/sm64/Original.old @@ -0,0 +1,485 @@ + +int current_tab_size = 0; + +static inline void print_cmd(GeoCommand cmd, std::string c){ + if(cmd == GeoCommand::CLOSE_NODE){ + current_tab_size--; + } + + for(int i = 0; i < current_tab_size; i++){ + std::cout << "\t"; + } + + if(cmd == GeoCommand::OPEN_NODE){ + current_tab_size++; + } + + std::cout << "GEO_" << c << "()" << std::endl; +} + +typedef uint32_t GeoLayout; + + auto offset = data["offset"].as(); + auto cmd = (uint8_t*) buffer.data() + offset; + auto processing = true; + + std::vector layout; + auto geo_writer = new LUS::BinaryWriter(); + +// #define GeoWrite(x) layout.insert(layout.end(), {x}) +// +// while(processing){ +// auto opcode = cmd[0x00]; +// switch (opcode) { +// case CMD_INFO(BRANCH_AND_LINK) { +// geo_writer->Write((uint8_t) BRANCH_AND_LINK_OTR); +// uint32_t ptr = SEGMENT_OFFSET(BSWAP32(cur_geo_cmd_u32(0x04))); +// auto decl = Companion::Instance->GetNodeByAddr(ptr); +// +// if(decl.has_value()){ +// uint64_t hash = CRC64(std::get<0>(decl.value()).c_str()); +// SPDLOG_INFO("Found geo: 0x{:X} Hash: 0x{:X} Path: {}", ptr, hash, std::get<0>(decl.value())); +// geo_writer->Write(hash); +// } else { +// SPDLOG_INFO("Warning: Could not find geo at 0x{:X}", ptr); +// geo_writer->Write((uint64_t) 0); +// } +// +// cmd += 0x08 << CMD_SIZE_SHIFT; +// break; +// } +// case CMD_INFO(BRANCH) { +// geo_writer->Write((uint8_t) BRANCH_OTR); +// geo_writer->Write(cur_geo_cmd_u8(0x01)); +// +// int32_t ptr = SEGMENT_OFFSET(BSWAP32(cur_geo_cmd_u32(0x04))); +// auto decl = Companion::Instance->GetNodeByAddr(ptr); +// +// if(decl.has_value()){ +// uint64_t hash = CRC64(std::get<0>(decl.value()).c_str()); +// SPDLOG_INFO("Found geo: 0x{:X} Hash: 0x{:X} Path: {}", ptr, hash, std::get<0>(decl.value())); +// geo_writer->Write(hash); +// } else { +// SPDLOG_INFO("Warning: Could not find geo at 0x{:X}", ptr); +// geo_writer->Write((uint64_t) 0); +// } +// +// cmd += 0x08 << CMD_SIZE_SHIFT; +// break; +// } +// case CMD_INFO(END) +// geo_writer->Write((uint8_t) END); +// processing = false; +// break; +// case CMD_INFO(RETURN) +// geo_writer->Write((uint8_t) RETURN); +// processing = false; +// break; +// case CMD_NOP(OPEN_NODE) +// case CMD_NOP(CLOSE_NODE) +// case CMD_INFO(ASSIGN_AS_VIEW) { +// geo_writer->Write(ASSIGN_AS_VIEW); +// geo_writer->Write(cur_geo_cmd_s16(0x02)); +// break; +// } +// case CMD_INFO(UPDATE_NODE_FLAGS) { +// geo_writer->Write((uint8_t) UPDATE_NODE_FLAGS); +// geo_writer->Write(cur_geo_cmd_u8(0x01)); +// geo_writer->Write(cur_geo_cmd_s16(0x02)); +// break; +// } +// case CMD_INFO(NODE_ROOT) { +// auto a1 = cur_geo_cmd_s16(0x02); +// auto a2 = cur_geo_cmd_s16(0x04); +// auto a3 = cur_geo_cmd_s16(0x06); +// auto a4 = cur_geo_cmd_s16(0x08); +// auto a5 = cur_geo_cmd_s16(0x0A); +// GeoWrite(GEO_NODE_SCREEN_AREA(a1, a2, a3, a4, a5)); +// cmd += 0x0C << CMD_SIZE_SHIFT; +// processing = false; +// } +// case CMD_INFO(NODE_ORTHO_PROJECTION) { +// geo_writer->Write((uint8_t) NODE_ORTHO_PROJECTION); +// geo_writer->Write(cur_geo_cmd_s16(0x02)); +// cmd += 0x04 << CMD_SIZE_SHIFT; +// break; +// } +// case CMD_INFO(NODE_PERSPECTIVE) { +// geo_writer->Write((uint8_t) NODE_PERSPECTIVE); +// auto param = cur_geo_cmd_u8(0x01); +// auto fov = cur_geo_cmd_s16(0x02); +// auto near = cur_geo_cmd_s16(0x04); +// auto far = cur_geo_cmd_s16(0x06); +// +// geo_writer->Write(param); +// geo_writer->Write(fov); +// geo_writer->Write(near); +// geo_writer->Write(far); +// +// if (param != 0) { +// auto func = cur_geo_cmd_u32(0x08); +// geo_writer->Write(func); +// cmd += 4 << CMD_SIZE_SHIFT; +// } +// +// cmd += 0x08 << CMD_SIZE_SHIFT; +// break; +// } +// case CMD_NOP(NODE_START) +// case CMD_INFO(NODE_MASTER_LIST) { +// geo_writer->Write((uint8_t) NODE_MASTER_LIST); +// geo_writer->Write(cur_geo_cmd_u8(0x01)); +// cmd += 0x04 << CMD_SIZE_SHIFT; +// break; +// } +// case CMD_INFO(NODE_LEVEL_OF_DETAIL) { +// geo_writer->Write((uint8_t) NODE_LEVEL_OF_DETAIL); +// int16_t minDistance = cur_geo_cmd_s16(0x04); +// int16_t maxDistance = cur_geo_cmd_s16(0x06); +// +// geo_writer->Write(minDistance); +// geo_writer->Write(maxDistance); +// +// cmd += 0x08 << CMD_SIZE_SHIFT; +// break; +// } +// case CMD_INFO(NODE_SWITCH_CASE) { +// geo_writer->Write((uint8_t) NODE_SWITCH_CASE_OTR); +// auto cs = cur_geo_cmd_s16(0x02); +// auto ptr = cur_geo_cmd_u32(0x04); +// +// geo_writer->Write(cs); +// geo_writer->Write(ptr); +// +// cmd += 0x08 << CMD_SIZE_SHIFT; +// break; +// } +// case CMD_INFO(NODE_CAMERA) { +// geo_writer->Write((uint8_t) NODE_CAMERA_OTR); +// auto cmd_pos = (int16_t *) &cmd[4]; +// auto mode = cur_geo_cmd_s16(0x02); +// +// geo_writer->Write(mode); +// +// Vec3f pos, focus; +// +// cmd_pos = read_vec3s_to_vec3f(pos, cmd_pos); +// read_vec3s_to_vec3f(focus, cmd_pos); +// +// geo_writer->Write(pos[0]); +// geo_writer->Write(pos[1]); +// geo_writer->Write(pos[2]); +// geo_writer->Write(focus[0]); +// geo_writer->Write(focus[1]); +// geo_writer->Write(focus[2]); +// +// auto ptr = SEGMENT_OFFSET(BSWAP32(cur_geo_cmd_u32(0x10))); +// geo_writer->Write(ptr); +// +// cmd += 0x14 << CMD_SIZE_SHIFT; +// break; +// } +// case CMD_INFO(NODE_TRANSLATION_ROTATION) { +// geo_writer->Write(NODE_TRANSLATION_ROTATION_OTR); +// auto params = cur_geo_cmd_u8(0x01); +// auto cmd_pos = (int16_t*) cmd; +// +// Vec3s translation, rotation; +// +// geo_writer->Write(params); +// +// switch ((params & 0x70) >> 4) { +// case 0: +// cmd_pos = read_vec3s(translation, &cmd_pos[2]); +// geo_writer->Write(translation[0]); +// geo_writer->Write(translation[1]); +// geo_writer->Write(translation[2]); +// cmd_pos = read_vec3s_angle(rotation, cmd_pos); +// geo_writer->Write(rotation[0]); +// geo_writer->Write(rotation[1]); +// geo_writer->Write(rotation[2]); +// break; +// case 1: +// cmd_pos = read_vec3s(translation, &cmd_pos[1]); +// geo_writer->Write(translation[0]); +// geo_writer->Write(translation[1]); +// geo_writer->Write(translation[2]); +// break; +// case 2: +// cmd_pos = read_vec3s_angle(rotation, &cmd_pos[1]); +// geo_writer->Write(rotation[0]); +// geo_writer->Write(rotation[1]); +// geo_writer->Write(rotation[2]); +// break; +// case 3: +// cmd_pos += 2 << CMD_SIZE_SHIFT; +// break; +// } +// +// if (params & 0x80) { +// auto dlist = SEGMENT_OFFSET(BSWAP32(*(uint32_t*) &cmd_pos[0])); +// auto decl = Companion::Instance->GetNodeByAddr(dlist); +// if(decl.has_value()){ +// uint64_t hash = CRC64(std::get<0>(decl.value()).c_str()); +// SPDLOG_INFO("Found display list: 0x{:X} Hash: 0x{:X} Path: {}", dlist, hash, std::get<0>(decl.value())); +// geo_writer->Write(hash); +// } else { +// SPDLOG_INFO("Warning: Could not find display list at 0x{:X}", dlist); +// geo_writer->Write((uint64_t) 0); +// } +// cmd_pos += 2 << CMD_SIZE_SHIFT; +// } +// +// cmd = (uint8_t*) cmd_pos; +// break; +// } +// case CMD_INFO(NODE_TRANSLATION) { +// geo_writer->Write(NODE_TRANSLATION_OTR); +// auto params = cur_geo_cmd_u8(0x01); +// auto cmd_pos = (int16_t*) cmd; +// +// Vec3s translation; +// cmd_pos = read_vec3s(translation, &cmd_pos[1]); +// +// geo_writer->Write(translation[0]); +// geo_writer->Write(translation[1]); +// geo_writer->Write(translation[2]); +// +// if (params & 0x80) { +// auto dlist = SEGMENT_OFFSET(BSWAP32(*(uint32_t*) &cmd_pos[0])); +// auto decl = Companion::Instance->GetNodeByAddr(dlist); +// if(decl.has_value()){ +// uint64_t hash = CRC64(std::get<0>(decl.value()).c_str()); +// SPDLOG_INFO("Found display list: 0x{:X} Hash: 0x{:X} Path: {}", dlist, hash, std::get<0>(decl.value())); +// geo_writer->Write(hash); +// } else { +// SPDLOG_INFO("Warning: Could not find display list at 0x{:X}", dlist); +// geo_writer->Write((uint64_t) 0); +// } +// cmd_pos += 2 << CMD_SIZE_SHIFT; +// } +// +// cmd = (uint8_t*) cmd_pos; +// break; +// } +// case CMD_INFO(NODE_ROTATION) { +// geo_writer->Write(NODE_ROTATION_OTR); +// auto params = cur_geo_cmd_u8(0x01); +// auto cmd_pos = (int16_t*) cmd; +// +// Vec3s sp2c; +// cmd_pos = read_vec3s(sp2c, &cmd_pos[1]); +// +// geo_writer->Write(sp2c[0]); +// geo_writer->Write(sp2c[1]); +// geo_writer->Write(sp2c[2]); +// +// if (params & 0x80) { +// auto dlist = SEGMENT_OFFSET(BSWAP32(*(uint32_t*) &cmd_pos[0])); +// auto decl = Companion::Instance->GetNodeByAddr(dlist); +// if(decl.has_value()){ +// uint64_t hash = CRC64(std::get<0>(decl.value()).c_str()); +// SPDLOG_INFO("Found display list: 0x{:X} Hash: 0x{:X} Path: {}", dlist, hash, std::get<0>(decl.value())); +// geo_writer->Write(hash); +// } else { +// SPDLOG_INFO("Warning: Could not find display list at 0x{:X}", dlist); +// geo_writer->Write((uint64_t) 0); +// } +// cmd_pos += 2 << CMD_SIZE_SHIFT; +// } +// +// cmd = (uint8_t*) cmd_pos; +// break; +// } +// case CMD_INFO(NODE_ANIMATED_PART) { +// geo_writer->Write(NODE_ANIMATED_PART_OTR); +// +// auto layer = cur_geo_cmd_u8(0x01); +// auto ptr = cur_geo_cmd_u32(0x08); +// +// geo_writer->Write(layer); +// geo_writer->Write(ptr); +// +// auto dlist = SEGMENT_OFFSET(BSWAP32(cur_geo_cmd_u32(0x08))); +// auto decl = Companion::Instance->GetNodeByAddr(dlist); +// if(decl.has_value()){ +// uint64_t hash = CRC64(std::get<0>(decl.value()).c_str()); +// SPDLOG_INFO("Found display list: 0x{:X} Hash: 0x{:X} Path: {}", dlist, hash, std::get<0>(decl.value())); +// geo_writer->Write(hash); +// } else { +// SPDLOG_INFO("Warning: Could not find display list at 0x{:X}", dlist); +// geo_writer->Write((uint64_t) 0); +// } +// +// cmd += 0x0C << CMD_SIZE_SHIFT; +// break; +// } +// case CMD_INFO(NODE_BILLBOARD) { +// geo_writer->Write(NODE_BILLBOARD_OTR); +// +// Vec3s translation; +// auto params = cur_geo_cmd_u8(0x01); +// auto cmd_pos = (int16_t*) cmd; +// +// cmd_pos = read_vec3s(translation, &cmd_pos[1]); +// geo_writer->Write(params); +// if (params & 0x80) { +// auto dlist = SEGMENT_OFFSET(BSWAP32(*(uint32_t*) &cmd_pos[0])); +// auto decl = Companion::Instance->GetNodeByAddr(dlist); +// if (decl.has_value()) { +// uint64_t hash = CRC64(std::get<0>(decl.value()).c_str()); +// SPDLOG_INFO("Found display list: 0x{:X} Hash: 0x{:X} Path: {}", dlist, hash, +// std::get<0>(decl.value())); +// geo_writer->Write(hash); +// } else { +// SPDLOG_INFO("Warning: Could not find display list at 0x{:X}", dlist); +// geo_writer->Write((uint64_t) 0); +// } +// +// cmd_pos += 2 << CMD_SIZE_SHIFT; +// } +// +// cmd = (uint8_t*) cmd_pos; +// break; +// } +// case CMD_INFO(NODE_DISPLAY_LIST) { +// geo_writer->Write((uint8_t) NODE_DISPLAY_LIST_OTR); +// +// int32_t layer = cur_geo_cmd_u8(0x01); +// auto ptr = SEGMENT_OFFSET(BSWAP32(cur_geo_cmd_u32(0x04))); +// +// geo_writer->Write(layer); +// +// auto decl = Companion::Instance->GetNodeByAddr(ptr); +// +// if(decl.has_value()){ +// uint64_t hash = CRC64(std::get<0>(decl.value()).c_str()); +// SPDLOG_INFO("Found display list: 0x{:X} Hash: 0x{:X} Path: {}", ptr, hash, std::get<0>(decl.value())); +// geo_writer->Write(hash); +// } else { +// SPDLOG_INFO("Warning: Could not find display list at 0x{:X}", ptr); +// geo_writer->Write((uint64_t) 0); +// } +// +// cmd += 0x08 << CMD_SIZE_SHIFT; +// break; +// } +// case CMD_INFO(NODE_SHADOW) { +// geo_writer->Write((uint8_t) NODE_SHADOW); +// auto type = cur_geo_cmd_s16(0x02); +// auto solidity = cur_geo_cmd_s16(0x04); +// auto scale = cur_geo_cmd_s16(0x06); +// +// geo_writer->Write(type); +// geo_writer->Write(solidity); +// geo_writer->Write(scale); +// +// cmd += 0x08 << CMD_SIZE_SHIFT; +// break; +// } +// case CMD_NOP(NODE_OBJECT_PARENT) +// case CMD_INFO(NODE_ASM) { +// geo_writer->Write(NODE_ASM_OTR); +// auto param = cur_geo_cmd_s16(0x02); +// auto ptr = cur_geo_cmd_u32(0x04); +// +// geo_writer->Write(param); +// geo_writer->Write(SEGMENT_OFFSET(BSWAP32(ptr))); +// cmd += 0x08 << CMD_SIZE_SHIFT; +// break; +// } +// case CMD_INFO(NODE_BACKGROUND) { +// geo_writer->Write((uint8_t) NODE_BACKGROUND_OTR); +// auto bg = cur_geo_cmd_s16(0x02); +// geo_writer->Write(bg); +// +// auto ptr = SEGMENT_OFFSET(BSWAP32(cur_geo_cmd_u32(0x04))); +// geo_writer->Write(ptr); +// +// cmd += 0x08 << CMD_SIZE_SHIFT; +// break; +// } +// case CMD_INFO(NOP) { +// geo_writer->Write((uint8_t) NOP); +// geo_writer->Write((uint32_t) 0); +// geo_writer->Write((uint32_t) 0); +// cmd += 0x08 << CMD_SIZE_SHIFT; +// break; +// } +// case CMD_INFO(COPY_VIEW) { +// geo_writer->Write((uint32_t) COPY_VIEW); +// auto idx = cur_geo_cmd_s16(0x02); +// geo_writer->Write(idx); +// break; +// } +// case CMD_INFO(NODE_HELD_OBJ) { +// geo_writer->Write((uint8_t) NODE_HELD_OBJ_OTR); +// +// auto idx = cur_geo_cmd_u8(0x01); +// geo_writer->Write(idx); +// +// Vec3s c_offset; +// read_vec3s(c_offset, (int16_t*) &cmd[0x02]); +// +// geo_writer->Write(c_offset[0]); +// geo_writer->Write(c_offset[1]); +// geo_writer->Write(c_offset[2]); +// +// auto ptr = SEGMENT_OFFSET(BSWAP32(cur_geo_cmd_u32(0x08))); +// geo_writer->Write(ptr); +// +// cmd += 0x0C << CMD_SIZE_SHIFT; +// break; +// } +// case CMD_INFO(NODE_SCALE) { +// geo_writer->Write(NODE_SCALE_OTR); +// auto params = cur_geo_cmd_u8(0x01); +// auto scale = cur_geo_cmd_u32(0x04); +// +// geo_writer->Write(params); +// geo_writer->Write(scale); +// +// if (params & 0x80) { +// auto dlist = SEGMENT_OFFSET(BSWAP32(cur_geo_cmd_u32(0x08))); +// auto decl = Companion::Instance->GetNodeByAddr(dlist); +// if(decl.has_value()){ +// uint64_t hash = CRC64(std::get<0>(decl.value()).c_str()); +// SPDLOG_INFO("Found display list: 0x{:X} Hash: 0x{:X} Path: {}", dlist, hash, std::get<0>(decl.value())); +// geo_writer->Write(hash); +// } else { +// SPDLOG_INFO("Warning: Could not find display list at 0x{:X}", dlist); +// geo_writer->Write((uint64_t) 0); +// } +// cmd += 4 << CMD_SIZE_SHIFT; +// } +// break; +// } +// case CMD_INFO(NOP2) { +// geo_writer->Write((uint8_t) NOP2); +// geo_writer->Write((uint32_t) 0); +// geo_writer->Write((uint32_t) 0); +// cmd += 0x08 << CMD_SIZE_SHIFT; +// break; +// } +// case CMD_INFO(NOP3) { +// geo_writer->Write((uint8_t) NOP3); +// geo_writer->Write((uint32_t) 0); +// geo_writer->Write((uint32_t) 0); +// geo_writer->Write((uint32_t) 0); +// cmd += 0x10 << CMD_SIZE_SHIFT; +// break; +// } +// case CMD_INFO(NODE_CULLING_RADIUS) { +// geo_writer->Write((uint8_t) NODE_CULLING_RADIUS); +// auto radius = cur_geo_cmd_s16(0x02); +// geo_writer->Write(radius); +// break; +// } +// default: +// std::cout << "Unknown command: " << std::hex << (int) cmd[0x00] << std::endl; +// break; +// } +// } + + // auto size = geo_writer->GetLength(); + // auto data_ptr = geo_writer->ToVector(); \ No newline at end of file diff --git a/src/factories/sm64/geo/GeoCommand.h b/src/factories/sm64/geo/GeoCommand.h new file mode 100644 index 0000000..66526dc --- /dev/null +++ b/src/factories/sm64/geo/GeoCommand.h @@ -0,0 +1,208 @@ +#pragma once + +#include "endianness.h" +#include "n64/CommandMacros.h" +#include +#include +#include +#include + +struct Vec2f { + float x; + float y; +}; + +struct Vec3f { + float x; + float y; + float z; +}; + +struct Vec3s { + int16_t x; + int16_t y; + int16_t z; +}; + +struct Vec3i { + int32_t x; + int32_t y; + int32_t z; +}; + +struct Vec4f { + float x; + float y; + float z; + float w; +}; + +struct Vec4s { + int16_t x; + int16_t y; + int16_t z; + int16_t w; +}; + +enum class GeoOpcode { + BranchAndLink, + End, + Branch, + Return, + OpenNode, + CloseNode, + AssignAsView, + UpdateNodeFlags, + NodeRoot, + NodeOrthoProjection, + NodePerspective, + NodeStart, + NodeMasterList, + NodeLevelOfDetail, + NodeSwitchCase, + NodeCamera, + NodeTranslationRotation, + NodeTranslation, + NodeRotation, + NodeAnimatedPart, + NodeBillboard, + NodeDisplayList, + NodeShadow, + NodeObjectParent, + NodeAsm, + NodeBackground, + NOP, + CopyView, + NodeHeldObj, + NodeScale, + NOP2, + NOP3, + NodeCullingRadius, +}; + +inline std::ostream& operator<<(std::ostream& out, const GeoOpcode& opcode) { + std::string output; + switch (opcode) { + case GeoOpcode::BranchAndLink: + output = "GEO_BRANCH_AND_LINK"; + break; + case GeoOpcode::End: + output = "GEO_END"; + break; + case GeoOpcode::Branch: + output = "GEO_BRANCH"; + break; + case GeoOpcode::Return: + output = "GEO_RETURN"; + break; + case GeoOpcode::OpenNode: + output = "GEO_OPEN_NODE"; + break; + case GeoOpcode::CloseNode: + output = "GEO_CLOSE_NODE"; + break; + case GeoOpcode::AssignAsView: + output = "GEO_ASSIGN_AS_VIEW"; + break; + case GeoOpcode::UpdateNodeFlags: + output = "GEO_UPDATE_NODE_FLAGS"; + break; + case GeoOpcode::NodeRoot: + output = "GEO_NODE_SCREEN_AREA"; + break; + case GeoOpcode::NodeOrthoProjection: + output = "GEO_NODE_ORTHO"; + break; + case GeoOpcode::NodePerspective: + output = "GEO_CAMERA_FRUSTUM"; + break; + case GeoOpcode::NodeStart: + output = "GEO_NODE_START"; + break; + case GeoOpcode::NodeMasterList: + output = "GEO_ZBUFFER"; + break; + case GeoOpcode::NodeLevelOfDetail: + output = "GEO_RENDER_RANGE"; + break; + case GeoOpcode::NodeSwitchCase: + output = "GEO_SWITCH_CASE"; + break; + case GeoOpcode::NodeCamera: + output = "GEO_CAMERA"; + break; + case GeoOpcode::NodeTranslationRotation: + output = "GEO_TRANSLATE_ROTATE"; + break; + case GeoOpcode::NodeTranslation: + output = "GEO_TRANSLATE"; + break; + case GeoOpcode::NodeRotation: + output = "GEO_ROTATE"; + break; + case GeoOpcode::NodeAnimatedPart: + output = "GEO_ANIMATED_PART"; + break; + case GeoOpcode::NodeBillboard: + output = "GEO_BILLBOARD"; + break; + case GeoOpcode::NodeDisplayList: + output = "GEO_DISPLAY_LIST"; + break; + case GeoOpcode::NodeShadow: + output = "GEO_SHADOW"; + break; + case GeoOpcode::NodeObjectParent: + output = "GEO_RENDER_OBJ"; + break; + case GeoOpcode::NodeAsm: + output = "GEO_ASM"; + break; + case GeoOpcode::NodeBackground: + output = "GEO_BACKGROUND"; + break; + case GeoOpcode::NOP: + output = "GEO_NOP_1A"; + break; + case GeoOpcode::CopyView: + output = "GEO_COPY_VIEW"; + break; + case GeoOpcode::NodeHeldObj: + output = "GEO_HELD_OBJECT"; + break; + case GeoOpcode::NodeScale: + output = "GEO_SCALE"; + break; + case GeoOpcode::NOP2: + output = "GEO_NOP_1E"; + break; + case GeoOpcode::NOP3: + output = "GEO_NOP_1F"; + break; + case GeoOpcode::NodeCullingRadius: + output = "GEO_CULLING_RADIUS"; + break; + default: + throw std::runtime_error("Unknown Opcode"); + } + + return out << output; +} + +#define cur_geo_cmd_u8(offset) \ + (cmd[CMD_PROCESS_OFFSET(offset)]) + +#define cur_geo_cmd_s16(offset) \ + BSWAP16((*(int16_t *) &cmd[CMD_PROCESS_OFFSET(offset)])) + +#define cur_geo_cmd_s32(offset) \ + BSWAP32((*(s32 *) &cmd[CMD_PROCESS_OFFSET(offset)])) + +#define cur_geo_cmd_u32(offset) \ + BSWAP32((*(uint32_t *) &cmd[CMD_PROCESS_OFFSET(offset)])) + +class GeoLayoutCommand { +public: + virtual void Print(std::ostream& out) = 0; + virtual void Write(LUS::BinaryWriter& write) = 0; +}; \ No newline at end of file diff --git a/src/factories/sm64/geo/GeoUtils.cpp b/src/factories/sm64/geo/GeoUtils.cpp new file mode 100644 index 0000000..91f4158 --- /dev/null +++ b/src/factories/sm64/geo/GeoUtils.cpp @@ -0,0 +1,24 @@ +#include "GeoUtils.h" + +#define next_s16_in_geo_script(src) BSWAP16((*(*src)++)) + +int16_t* read_vec3s_to_vec3f(Vec3f& dst, int16_t *src) { + dst.x = next_s16_in_geo_script(&src); + dst.y = next_s16_in_geo_script(&src); + dst.z = next_s16_in_geo_script(&src); + return src; +} + +int16_t* read_vec3s(Vec3s& dst, int16_t *src) { + dst.x = next_s16_in_geo_script(&src); + dst.y = next_s16_in_geo_script(&src); + dst.z = next_s16_in_geo_script(&src); + return src; +} + +int16_t* read_vec3s_angle(Vec3s& dst, int16_t *src) { + dst.x = next_s16_in_geo_script(&src); + dst.y = next_s16_in_geo_script(&src); + dst.z = next_s16_in_geo_script(&src); + return src; +} \ No newline at end of file diff --git a/src/factories/sm64/geo/GeoUtils.h b/src/factories/sm64/geo/GeoUtils.h new file mode 100644 index 0000000..a629962 --- /dev/null +++ b/src/factories/sm64/geo/GeoUtils.h @@ -0,0 +1,8 @@ +#pragma once + +#include +#include "GeoCommand.h" + +int16_t* read_vec3s_to_vec3f(Vec3f& dst, int16_t *src); +int16_t* read_vec3s(Vec3s& dst, int16_t *src); +int16_t* read_vec3s_angle(Vec3s& dst, int16_t *src); \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 7cab502..c39ff8c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -19,7 +19,7 @@ int main(int argc, char *argv[]) { bool header = false; app.require_subcommand(); - + /* Generate an OTR */ auto otr = app.add_subcommand("otr", "OTR - Generates an otr\n"); @@ -38,9 +38,9 @@ int main(int argc, char *argv[]) { } else { instance->Init(ExportType::Binary); } - + if (!folder.empty()) { - Companion::Pack(folder, target); + Companion::Pack(folder, target); } }); diff --git a/src/utils/TorchUtils.cpp b/src/utils/TorchUtils.cpp new file mode 100644 index 0000000..d63fa0b --- /dev/null +++ b/src/utils/TorchUtils.cpp @@ -0,0 +1,20 @@ +#include "TorchUtils.h" + +#include +#include +#include "spdlog/spdlog.h" + +uint32_t Torch::translate(const uint32_t offset) { + if(SEGMENT_NUMBER(offset) > 0x01) { + auto segment = SEGMENT_NUMBER(offset); + const auto addr = Companion::Instance->GetSegmentedAddr(segment); + if(!addr.has_value()) { + SPDLOG_ERROR("Segment data missing from game config\nPlease add an entry for segment {}", segment); + throw std::runtime_error("Failed to find offset"); + } + + return addr.value() + SEGMENT_OFFSET(offset); + } + + return offset; +} diff --git a/src/utils/TorchUtils.h b/src/utils/TorchUtils.h new file mode 100644 index 0000000..330c7fa --- /dev/null +++ b/src/utils/TorchUtils.h @@ -0,0 +1,23 @@ +#pragma once + +#include +#include +#include + +namespace Torch { +template< typename T > +std::string to_hex(T number, const bool append0x = true) { + std::stringstream stream; + if(append0x) { + stream << "0x"; + } + stream << std::setfill ('0') << std::setw(sizeof(T)*2) + << std::hex << number; + + auto format = stream.str(); + std::transform(format.begin(), format.end(), format.begin(), ::toupper); + return format; +} + +uint32_t translate(uint32_t offset); +}; \ No newline at end of file