diff options
| author | inspectredc <inspectredc@gmail.com> | 2024-04-08 11:47:11 +0100 |
|---|---|---|
| committer | Lywx <kiritodev01@gmail.com> | 2024-04-08 13:40:32 -0600 |
| commit | b6eab060ff1865bea62838d07486e40919a8fd21 (patch) | |
| tree | 92b57f54f257dae8a9e3c528b6379daff065f00d | |
| parent | 4a1c3292d7f0567415cbad33db1734586b1e6ab6 (diff) | |
movtex factories
| -rw-r--r-- | src/Companion.cpp | 4 | ||||
| -rw-r--r-- | src/factories/ResourceType.h | 3 | ||||
| -rw-r--r-- | src/factories/sm64/CollisionFactory.cpp | 3 | ||||
| -rw-r--r-- | src/factories/sm64/MovtexFactory.cpp | 156 | ||||
| -rw-r--r-- | src/factories/sm64/MovtexFactory.h | 40 | ||||
| -rw-r--r-- | src/factories/sm64/MovtexQuadFactory.cpp | 106 | ||||
| -rw-r--r-- | src/factories/sm64/MovtexQuadFactory.h | 38 |
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) + }; + } +}; +} |
