movtex factories

This commit is contained in:
inspectredc
2024-04-08 13:40:32 -06:00
committed by Lywx
parent 4a1c3292d7
commit b6eab060ff
7 changed files with 348 additions and 2 deletions
+4
View File
@@ -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>());
+3
View File
@@ -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
+1 -2
View File
@@ -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());
+156
View File
@@ -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);
}
+40
View File
@@ -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)
};
}
};
}
+106
View File
@@ -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);
}
+38
View File
@@ -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)
};
}
};
}