summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorinspectredc <inspectredc@gmail.com>2024-04-08 11:47:11 +0100
committerLywx <kiritodev01@gmail.com>2024-04-08 13:40:32 -0600
commitb6eab060ff1865bea62838d07486e40919a8fd21 (patch)
tree92b57f54f257dae8a9e3c528b6379daff065f00d
parent4a1c3292d7f0567415cbad33db1734586b1e6ab6 (diff)
movtex factories
-rw-r--r--src/Companion.cpp4
-rw-r--r--src/factories/ResourceType.h3
-rw-r--r--src/factories/sm64/CollisionFactory.cpp3
-rw-r--r--src/factories/sm64/MovtexFactory.cpp156
-rw-r--r--src/factories/sm64/MovtexFactory.h40
-rw-r--r--src/factories/sm64/MovtexQuadFactory.cpp106
-rw-r--r--src/factories/sm64/MovtexQuadFactory.h38
7 files changed, 348 insertions, 2 deletions
diff --git a/src/Companion.cpp b/src/Companion.cpp
index 9a3c233..53c1fb8 100644
--- a/src/Companion.cpp
+++ b/src/Companion.cpp
@@ -34,6 +34,8 @@
#include "factories/sm64/DictionaryFactory.h"
#include "factories/sm64/TextFactory.h"
#include "factories/sm64/GeoLayoutFactory.h"
+#include "factories/sm64/MovtexFactory.h"
+#include "factories/sm64/MovtexQuadFactory.h"
#include "factories/mk64/CourseVtx.h"
#include "factories/mk64/Waypoints.h"
@@ -91,6 +93,8 @@ void Companion::Init(const ExportType type) {
this->RegisterFactory("SM64:ANIM", std::make_shared<SM64::AnimationFactory>());
this->RegisterFactory("SM64:COLLISION", std::make_shared<SM64::CollisionFactory>());
this->RegisterFactory("SM64:GEO_LAYOUT", std::make_shared<SM64::GeoLayoutFactory>());
+ this->RegisterFactory("SM64:MOVTEX_QUAD", std::make_shared<SM64::MovtexQuadFactory>());
+ this->RegisterFactory("SM64:MOVTEX", std::make_shared<SM64::MovtexFactory>());
// MK64 specific
this->RegisterFactory("MK64:COURSE_VTX", std::make_shared<MK64::CourseVtxFactory>());
diff --git a/src/factories/ResourceType.h b/src/factories/ResourceType.h
index 8388766..4cc2ee4 100644
--- a/src/factories/ResourceType.h
+++ b/src/factories/ResourceType.h
@@ -28,6 +28,9 @@ enum class ResourceType {
SDialog = 0x53444C47, // SDLG
Dictionary = 0x44494354, // DICT
GeoLayout = 0x47454F20, // GEO
+ Collision = 0x434F4C20, // COL
+ Movtex = 0x4D4F5654, // MOVT
+ MovtexQuad = 0x4D4F5651, // MOVQ
// MK64
CourseVertex = 0x43565458, // CVTX
diff --git a/src/factories/sm64/CollisionFactory.cpp b/src/factories/sm64/CollisionFactory.cpp
index 41fa0b1..53dd0f5 100644
--- a/src/factories/sm64/CollisionFactory.cpp
+++ b/src/factories/sm64/CollisionFactory.cpp
@@ -259,7 +259,6 @@ ExportResult SM64::CollisionBinaryExporter::Export(std::ostream &write, std::sha
const auto collision = std::static_pointer_cast<Collision>(data).get();
auto writer = LUS::BinaryWriter();
- writer.SetEndianness(LUS::Endianness::Big);
writer.Write((int16_t)COL_INIT());
@@ -340,7 +339,7 @@ ExportResult SM64::CollisionBinaryExporter::Export(std::ostream &write, std::sha
writer.Close();
LUS::BinaryWriter output = LUS::BinaryWriter();
- WriteHeader(output, LUS::ResourceType::Blob, 0);
+ WriteHeader(output, LUS::ResourceType::Collision, 0);
output.Write(static_cast<uint32_t>(buffer.size()));
output.Write(buffer.data(), buffer.size());
diff --git a/src/factories/sm64/MovtexFactory.cpp b/src/factories/sm64/MovtexFactory.cpp
new file mode 100644
index 0000000..c0babe6
--- /dev/null
+++ b/src/factories/sm64/MovtexFactory.cpp
@@ -0,0 +1,156 @@
+#include "MovtexFactory.h"
+#include "spdlog/spdlog.h"
+
+#include "Companion.h"
+#include "utils/Decompressor.h"
+#include "utils/TorchUtils.h"
+#include <regex>
+
+ExportResult SM64::MovtexHeaderExporter::Export(std::ostream &write, std::shared_ptr<IParsedData> raw, std::string& entryName, YAML::Node &node, std::string* replacement) {
+ const auto symbol = GetSafeNode(node, "symbol", entryName);
+
+ if(Companion::Instance->IsOTRMode()){
+ write << "static const char " << symbol << "[] = \"__OTR__" << (*replacement) << "\";\n\n";
+ return std::nullopt;
+ }
+
+ write << "extern Movtex " << symbol << "[];\n";
+ return std::nullopt;
+}
+
+ExportResult SM64::MovtexCodeExporter::Export(std::ostream &write, std::shared_ptr<IParsedData> raw, std::string& entryName, YAML::Node &node, std::string* replacement ) {
+ const auto symbol = GetSafeNode(node, "symbol", entryName);
+ const auto offset = GetSafeNode<uint32_t>(node, "offset");
+
+ auto movtex = std::static_pointer_cast<SM64::MovtexData>(raw);
+
+ write << "static Movtex " << symbol << "[] = {";
+
+ if (movtex->mIsQuad) {
+ auto numLists = movtex->mMovtexData.at(0);
+ write << "MOV_TEX_INIT_LOAD(" << numLists << "),\n";
+ for (int16_t i = 0; i < numLists; ++i) {
+ write << "MOV_TEX_ROT_SPEED(" << movtex->mMovtexData.at(i * 14 + 1) << "),\n";
+ write << "MOV_TEX_ROT_SCALE(" << movtex->mMovtexData.at(i * 14 + 2) << "),\n";
+ write << "MOV_TEX_4_BOX_TRIS(" << movtex->mMovtexData.at(i * 14 + 3) << ", " << movtex->mMovtexData.at(i * 14 + 4) << "),\n";
+ write << "MOV_TEX_4_BOX_TRIS(" << movtex->mMovtexData.at(i * 14 + 5) << ", " << movtex->mMovtexData.at(i * 14 + 6) << "),\n";
+ write << "MOV_TEX_4_BOX_TRIS(" << movtex->mMovtexData.at(i * 14 + 7) << ", " << movtex->mMovtexData.at(i * 14 + 8) << "),\n";
+ write << "MOV_TEX_4_BOX_TRIS(" << movtex->mMovtexData.at(i * 14 + 9) << ", " << movtex->mMovtexData.at(i * 14 + 10) << "),\n";
+ write << "MOV_TEX_ROT(" << movtex->mMovtexData.at(i * 14 + 11) << "),\n";
+ write << "MOV_TEX_ALPHA(" << movtex->mMovtexData.at(i * 14 + 12) << "),\n";
+ write << "MOV_TEX_DEFINE(" << movtex->mMovtexData.at(i * 14 + 13) << "),\n";
+ write << "MOV_TEX_END(),\n";
+ }
+ } else {
+ write << "MOV_TEX_SPEED(" << movtex->mMovtexData.at(0) << "),\n";
+ if (movtex->mHasColor) {
+ for (uint32_t i = 0; i < movtex->mVertexCount; ++i) {
+ // There is also a MOV_TEX_LIGHT_TRIS macro, however this is identical in result to using MOV_TEX_ROT_TRIS and would require more params on the yaml
+ write << "MOV_TEX_ROT_TRIS(";
+ write << movtex->mMovtexData.at(i * 8 + 0 + 1) << ", ";
+ write << movtex->mMovtexData.at(i * 8 + 1 + 1) << ", ";
+ write << movtex->mMovtexData.at(i * 8 + 2 + 1) << ", ";
+ write << movtex->mMovtexData.at(i * 8 + 3 + 1) << ", ";
+ write << movtex->mMovtexData.at(i * 8 + 4 + 1) << ", ";
+ write << movtex->mMovtexData.at(i * 8 + 5 + 1) << ", ";
+ write << movtex->mMovtexData.at(i * 8 + 6 + 1) << ", ";
+ write << movtex->mMovtexData.at(i * 8 + 7 + 1) << "),\n";
+ }
+ } else {
+ for (uint32_t i = 0; i < movtex->mVertexCount; ++i) {
+ write << "MOV_TEX_TRIS(";
+ write << movtex->mMovtexData.at(i * 8 + 0 + 1) << ", ";
+ write << movtex->mMovtexData.at(i * 8 + 1 + 1) << ", ";
+ write << movtex->mMovtexData.at(i * 8 + 2 + 1) << ", ";
+ write << movtex->mMovtexData.at(i * 8 + 3 + 1) << ", ";
+ write << movtex->mMovtexData.at(i * 8 + 4 + 1) << "),\n";
+ }
+ }
+ write << "MOV_TEX_END(),\n";
+ }
+
+ write << "\n};\n";
+
+ size_t size = (movtex->mMovtexData.size() + 1) * sizeof(int16_t);
+
+ return offset + size;
+}
+
+ExportResult SM64::MovtexBinaryExporter::Export(std::ostream &write, std::shared_ptr<IParsedData> raw, std::string& entryName, YAML::Node &node, std::string* replacement ) {
+ auto writer = LUS::BinaryWriter();
+ auto movtex = std::static_pointer_cast<SM64::MovtexData>(raw);
+
+ WriteHeader(writer, LUS::ResourceType::Movtex, 0);
+
+ // May want extra info, but importer should just be mMovtexData with an extra 0 (or 2) at the end
+ // if (movtex->mIsQuad) {
+ // writer.Write(0);
+ // writer.Write(0);
+ // } else {
+ // writer.Write(movtex->mVertexCount);
+ // writer.Write((uint32_t)(movtex->mHasColor ? 1 : 0));
+ // }
+
+ for (auto datum : movtex->mMovtexData) {
+ writer.Write(datum);
+ }
+
+ writer.Finish(write);
+ return std::nullopt;
+}
+
+std::optional<std::shared_ptr<IParsedData>> SM64::MovtexFactory::parse(std::vector<uint8_t>& buffer, YAML::Node& node) {
+ const auto offset = GetSafeNode<uint32_t>(node, "offset");
+ const auto symbol = GetSafeNode<std::string>(node, "symbol");
+ bool isQuad = false;
+ uint32_t count = 0;
+ bool hasColor = false;
+
+ // If quad we can generate automatically
+ if (node["quad"]) {
+ isQuad = GetSafeNode<bool>(node, "quad");
+ }
+ // Otherwise we need to know the count of vertices and the colour attribute
+ if (!isQuad) {
+ if (node["count"]) {
+ count = GetSafeNode<uint32_t>(node, "quad");
+ } else {
+ SPDLOG_WARN("Non quad movtex needs count field");
+ }
+ if (node["has_color"]) {
+ hasColor = GetSafeNode<bool>(node, "has_color");
+ } else {
+ SPDLOG_WARN("Non quad movtex needs has_color field");
+ }
+ }
+ auto [_, segment] = Decompressor::AutoDecode(node, buffer);
+ LUS::BinaryReader reader(segment.data, segment.size);
+ reader.SetEndianness(LUS::Endianness::Big);
+
+ std::vector<int16_t> movtexData;
+
+ if (isQuad) {
+ auto numLists = reader.ReadInt16();
+ movtexData.emplace_back(numLists);
+ // movtex quad data has 14 elements
+ for (int16_t i = 0; i < numLists * 14; ++i) {
+ movtexData.emplace_back(reader.ReadInt16());
+ }
+ if (reader.ReadInt16() != 0) {
+ SPDLOG_WARN("Incorrect end to movtex quad found at symbol: {}, offset: 0x{:X}", symbol, offset);
+ }
+ } else {
+ auto speed = reader.ReadInt16();
+ movtexData.emplace_back(speed);
+ size_t triSize = hasColor ? 8 : 5;
+ for (size_t i = 0; i < count * triSize; ++i) {
+ movtexData.emplace_back(reader.ReadInt16());
+ }
+
+ if (reader.ReadInt16() != 0) {
+ SPDLOG_WARN("Incorrect end to movtex object found at symbol: {}, offset: 0x{:X}", symbol, offset);
+ }
+ }
+
+ return std::make_shared<SM64::MovtexData>(movtexData, isQuad, count, hasColor);
+}
diff --git a/src/factories/sm64/MovtexFactory.h b/src/factories/sm64/MovtexFactory.h
new file mode 100644
index 0000000..219e189
--- /dev/null
+++ b/src/factories/sm64/MovtexFactory.h
@@ -0,0 +1,40 @@
+#pragma once
+
+#include "factories/BaseFactory.h"
+#include "types/Vec3D.h"
+
+namespace SM64 {
+
+class MovtexData : public IParsedData {
+public:
+ std::vector<int16_t> mMovtexData;
+ bool mIsQuad;
+ uint32_t mVertexCount;
+ bool mHasColor;
+ MovtexData(std::vector<int16_t> movtexData, bool isQuad, uint32_t count, bool hasColor) : mMovtexData(std::move(movtexData)), mIsQuad(isQuad), mVertexCount(count), mHasColor(hasColor) {}
+};
+
+class MovtexHeaderExporter : public BaseExporter {
+ ExportResult Export(std::ostream& write, std::shared_ptr<IParsedData> data, std::string& entryName, YAML::Node& node, std::string* replacement) override;
+};
+
+class MovtexBinaryExporter : public BaseExporter {
+ ExportResult Export(std::ostream& write, std::shared_ptr<IParsedData> data, std::string& entryName, YAML::Node& node, std::string* replacement) override;
+};
+
+class MovtexCodeExporter : public BaseExporter {
+ ExportResult Export(std::ostream& write, std::shared_ptr<IParsedData> data, std::string& entryName, YAML::Node& node, std::string* replacement) override;
+};
+
+class MovtexFactory : 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 {
+ REGISTER(Code, MovtexCodeExporter)
+ REGISTER(Header, MovtexHeaderExporter)
+ REGISTER(Binary, MovtexBinaryExporter)
+ };
+ }
+};
+}
diff --git a/src/factories/sm64/MovtexQuadFactory.cpp b/src/factories/sm64/MovtexQuadFactory.cpp
new file mode 100644
index 0000000..3b8a2dd
--- /dev/null
+++ b/src/factories/sm64/MovtexQuadFactory.cpp
@@ -0,0 +1,106 @@
+#include "MovtexQuadFactory.h"
+#include "spdlog/spdlog.h"
+
+#include "Companion.h"
+#include "utils/Decompressor.h"
+#include "utils/TorchUtils.h"
+#include <regex>
+
+ExportResult SM64::MovtexQuadHeaderExporter::Export(std::ostream &write, std::shared_ptr<IParsedData> raw, std::string& entryName, YAML::Node &node, std::string* replacement) {
+ const auto symbol = GetSafeNode(node, "symbol", entryName);
+
+ if(Companion::Instance->IsOTRMode()){
+ write << "static const char " << symbol << "[] = \"__OTR__" << (*replacement) << "\";\n\n";
+ return std::nullopt;
+ }
+
+ write << "extern MovtexQuadCollection " << symbol << "[];\n";
+ return std::nullopt;
+}
+
+ExportResult SM64::MovtexQuadCodeExporter::Export(std::ostream &write, std::shared_ptr<IParsedData> raw, std::string& entryName, YAML::Node &node, std::string* replacement ) {
+ const auto symbol = GetSafeNode(node, "symbol", entryName);
+ const auto offset = GetSafeNode<uint32_t>(node, "offset");
+
+ auto quadData = std::static_pointer_cast<SM64::MovtexQuadData>(raw);
+
+ write << "const struct MovtexQuadCollection " << symbol << "[] = {";
+
+ for (auto &quad: quadData->mMovtexQuads) {
+ write << "{" << quad.first << ", ";
+ if (quad.second == 0) {
+ write << "NULL";
+ } else {
+ auto dec = Companion::Instance->GetNodeByAddr(quad.second);
+ if (dec.has_value()) {
+ auto movtexNode = std::get<1>(dec.value());
+ auto movtexSymbol = GetSafeNode<std::string>(movtexNode, "symbol");
+ write << movtexSymbol;
+ } else {
+ SPDLOG_WARN("Could not find movtex at 0x{:X}", quad.second);
+ write << "0x" << std::hex << std::uppercase << quad.second << std::nouppercase << std::dec;
+ }
+ }
+ write << "},\n";
+ }
+
+ write << "\n};\n";
+
+ if (Companion::Instance->IsDebug()) {
+ write << "// MovtexQuad count: " << quadData->mMovtexQuads.size() << "\n";
+ }
+
+ return offset + quadData->mMovtexQuads.size() * 4;
+}
+
+ExportResult SM64::MovtexQuadBinaryExporter::Export(std::ostream &write, std::shared_ptr<IParsedData> raw, std::string& entryName, YAML::Node &node, std::string* replacement ) {
+ auto writer = LUS::BinaryWriter();
+ auto quadData = std::static_pointer_cast<SM64::MovtexQuadData>(raw);
+
+ WriteHeader(writer, LUS::ResourceType::MovtexQuad, 0);
+ writer.Write((uint32_t) quadData->mMovtexQuads.size());
+
+ for (auto &quad: quadData->mMovtexQuads) {
+ writer.Write(quad.first);
+ if (quad.second == 0) {
+ writer.Write((uint64_t) quad.second);
+ } else {
+ auto dec = Companion::Instance->GetNodeByAddr(quad.second);
+ if (dec.has_value()) {
+ uint64_t hash = CRC64(std::get<0>(dec.value()).c_str());
+ SPDLOG_INFO("Found movtex: 0x{:X} Hash: 0x{:X} Path: {}", quad.second, hash, std::get<0>(dec.value()));
+ writer.Write(hash);
+ } else {
+ SPDLOG_WARN("Could not find movtex at 0x{:X}", quad.second);
+ }
+ }
+ write << "},\n";
+ }
+
+ writer.Finish(write);
+ return std::nullopt;
+}
+
+std::optional<std::shared_ptr<IParsedData>> SM64::MovtexQuadFactory::parse(std::vector<uint8_t>& buffer, YAML::Node& node) {
+ const auto offset = GetSafeNode<uint32_t>(node, "offset");
+ const auto symbol = GetSafeNode<std::string>(node, "symbol");
+ const auto count = GetSafeNode<size_t>(node, "count");
+ auto [_, segment] = Decompressor::AutoDecode(node, buffer);
+ LUS::BinaryReader reader(segment.data, segment.size);
+ reader.SetEndianness(LUS::Endianness::Big);
+ std::vector<std::pair<int16_t, uint32_t>> movtexQuads;
+
+ for (size_t i = 0; i < count; ++i) {
+ auto id = reader.ReadInt16();
+ auto movtexPtr = reader.ReadUInt32();
+ movtexQuads.emplace_back(std::make_pair(id, movtexPtr));
+
+ YAML::Node movtexNode;
+ movtexNode["type"] = "SM64:MOVTEX";
+ movtexNode["offset"] = movtexPtr;
+ movtexNode["quad"] = true;
+ Companion::Instance->AddAsset(movtexNode);
+ }
+
+ return std::make_shared<SM64::MovtexQuadData>(movtexQuads);
+}
diff --git a/src/factories/sm64/MovtexQuadFactory.h b/src/factories/sm64/MovtexQuadFactory.h
new file mode 100644
index 0000000..806c080
--- /dev/null
+++ b/src/factories/sm64/MovtexQuadFactory.h
@@ -0,0 +1,38 @@
+#pragma once
+
+#include "factories/BaseFactory.h"
+#include "types/Vec3D.h"
+
+namespace SM64 {
+
+class MovtexQuadData : public IParsedData {
+public:
+ std::vector<std::pair<int16_t, uint32_t>> mMovtexQuads;
+
+ MovtexQuadData(std::vector<std::pair<int16_t, uint32_t>> movtexQuads) : mMovtexQuads(std::move(movtexQuads)) {}
+};
+
+class MovtexQuadHeaderExporter : public BaseExporter {
+ ExportResult Export(std::ostream& write, std::shared_ptr<IParsedData> data, std::string& entryName, YAML::Node& node, std::string* replacement) override;
+};
+
+class MovtexQuadBinaryExporter : public BaseExporter {
+ ExportResult Export(std::ostream& write, std::shared_ptr<IParsedData> data, std::string& entryName, YAML::Node& node, std::string* replacement) override;
+};
+
+class MovtexQuadCodeExporter : public BaseExporter {
+ ExportResult Export(std::ostream& write, std::shared_ptr<IParsedData> data, std::string& entryName, YAML::Node& node, std::string* replacement) override;
+};
+
+class MovtexQuadFactory : 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 {
+ REGISTER(Code, MovtexQuadCodeExporter)
+ REGISTER(Header, MovtexQuadHeaderExporter)
+ REGISTER(Binary, MovtexQuadBinaryExporter)
+ };
+ }
+};
+}