summaryrefslogtreecommitdiff
path: root/src/factories/bk64/AnimFactory.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/factories/bk64/AnimFactory.cpp')
-rw-r--r--src/factories/bk64/AnimFactory.cpp212
1 files changed, 212 insertions, 0 deletions
diff --git a/src/factories/bk64/AnimFactory.cpp b/src/factories/bk64/AnimFactory.cpp
new file mode 100644
index 0000000..b45e342
--- /dev/null
+++ b/src/factories/bk64/AnimFactory.cpp
@@ -0,0 +1,212 @@
+#include "AnimFactory.h"
+
+#include "Companion.h"
+#include "spdlog/spdlog.h"
+#include "types/RawBuffer.h"
+#include "utils/Decompressor.h"
+#include "utils/TorchUtils.h"
+
+namespace BK64 {
+
+ExportResult AnimHeaderExporter::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 ALIGN_ASSET(2) char " << symbol << "[] = \"__OTR__" << (*replacement) << "\";\n\n";
+ return std::nullopt;
+ }
+
+ return std::nullopt;
+}
+
+ExportResult AnimCodeExporter::Export(std::ostream& write, std::shared_ptr<IParsedData> raw, std::string& entryName,
+ YAML::Node& node, std::string* replacement) {
+ auto offset = GetSafeNode<uint32_t>(node, "offset");
+ auto anim = std::static_pointer_cast<AnimData>(raw);
+ const auto symbol = GetSafeNode(node, "symbol", entryName);
+
+ write << "AnimationFile " << symbol << "_File = { " << anim->mStartFrame << ", " << anim->mEndFrame << ", "
+ << anim->mFiles.size() << " };\n\n";
+
+ write << "AnimationFileElement " << symbol << "_Data[] = {\n";
+ for (const auto& file : anim->mFiles) {
+ write << fourSpaceTab << "{\n";
+ write << fourSpaceTab << fourSpaceTab << file.mBoneIndex << ", " << file.mTransformType << ", "
+ << file.mData.size() << ",\n";
+ for (const auto& fileData : file.mData) {
+ write << fourSpaceTab << fourSpaceTab << "{ ";
+ write << (uint32_t)fileData.unk0_15 << ", " << (uint32_t)fileData.unk0_14 << ", " << fileData.unk0_13
+ << ", " << fileData.unk2;
+ write << " },\n";
+ }
+ write << fourSpaceTab << "},\n";
+ }
+
+ write << "};\n\n";
+
+ return offset;
+}
+
+ExportResult BK64::AnimBinaryExporter::Export(std::ostream& write, std::shared_ptr<IParsedData> raw,
+ std::string& entryName, YAML::Node& node, std::string* replacement) {
+ auto writer = LUS::BinaryWriter();
+ const auto anim = std::static_pointer_cast<AnimData>(raw);
+
+ WriteHeader(writer, Torch::ResourceType::BKAnimation, 0);
+
+ writer.Write(anim->mStartFrame);
+ writer.Write(anim->mEndFrame);
+ writer.Write((uint32_t)anim->mFiles.size());
+
+ for (const auto& file : anim->mFiles) {
+ writer.Write(file.mBoneIndex);
+ writer.Write(file.mTransformType);
+ writer.Write((uint32_t)file.mData.size());
+ for (const auto& fileData : file.mData) {
+ writer.Write(static_cast<uint8_t>(fileData.unk0_15));
+ writer.Write(static_cast<uint8_t>(fileData.unk0_14));
+ writer.Write(static_cast<uint16_t>(fileData.unk0_13));
+ writer.Write(fileData.unk2);
+ }
+ }
+
+ writer.Finish(write);
+ return std::nullopt;
+}
+
+ExportResult BK64::AnimModdingExporter::Export(std::ostream& write, std::shared_ptr<IParsedData> raw,
+ std::string& entryName, YAML::Node& node, std::string* replacement) {
+ const auto anim = std::static_pointer_cast<AnimData>(raw);
+ const auto symbol = GetSafeNode(node, "symbol", entryName);
+
+ *replacement += ".yaml";
+
+ YAML::Emitter out;
+ out << YAML::BeginMap;
+ out << YAML::Key << symbol;
+ out << YAML::Value;
+ out.SetIndent(2);
+
+ out << YAML::BeginMap;
+ out << YAML::Key << "StartFrame";
+ out << YAML::Value << anim->mStartFrame;
+ out << YAML::Key << "EndFrame";
+ out << YAML::Value << anim->mEndFrame;
+ out << YAML::Key << "Elements";
+ out << YAML::Value;
+
+ out << YAML::BeginSeq;
+ for (const auto& file : anim->mFiles) {
+ out << YAML::BeginMap;
+ out << YAML::Key << "BoneIndex";
+ out << YAML::Value << file.mBoneIndex;
+ out << YAML::Key << "TransformType";
+ out << YAML::Value << file.mTransformType;
+ out << YAML::Key << "Data";
+ out << YAML::Value;
+ out << YAML::BeginSeq;
+ for (const auto& fileData : file.mData) {
+ out << YAML::Flow << YAML::BeginSeq;
+ out << YAML::Value << (uint32_t)fileData.unk0_15;
+ out << YAML::Value << (uint32_t)fileData.unk0_14;
+ out << YAML::Value << fileData.unk0_13;
+ out << YAML::Value << fileData.unk2;
+ out << YAML::EndSeq;
+ }
+ out << YAML::EndSeq;
+ out << YAML::EndMap;
+ }
+ out << YAML::EndSeq;
+ out << YAML::EndMap;
+ out << YAML::EndMap;
+
+ write.write(out.c_str(), out.size());
+
+ return std::nullopt;
+}
+
+std::optional<std::shared_ptr<IParsedData>> AnimFactory::parse(std::vector<uint8_t>& buffer, YAML::Node& node) {
+ auto [_, segment] = Decompressor::AutoDecode(node, buffer);
+ LUS::BinaryReader reader(segment.data, segment.size);
+ reader.SetEndianness(Torch::Endianness::Big);
+ const auto symbol = GetSafeNode<std::string>(node, "symbol");
+
+ int16_t startFrame = reader.ReadInt16();
+ int16_t endFrame = reader.ReadInt16();
+ int16_t fileCount = reader.ReadInt16();
+ reader.ReadInt16();
+
+ std::vector<AnimationFile> animFiles;
+ for (int16_t i = 0; i < fileCount; i++) {
+ int16_t fileElementBitField = reader.ReadInt16();
+ int16_t dataCount = reader.ReadInt16();
+ int16_t boneIndex = (fileElementBitField & 0xFFF0) >> 4;
+ int16_t transformType = fileElementBitField & 0xF;
+
+ std::vector<AnimationFileData> fileData;
+
+ for (int16_t j = 0; j < dataCount; j++) {
+ AnimationFileData data;
+ int16_t fileDataBitField = reader.ReadInt16();
+
+ data.unk0_15 = (fileDataBitField & 0b1000000000000000) >> 15;
+ data.unk0_14 = (fileDataBitField & 0b0100000000000000) >> 14;
+ data.unk0_13 = fileDataBitField & 0b0011111111111111;
+ data.unk2 = reader.ReadInt16();
+
+ fileData.emplace_back(data);
+ }
+
+ animFiles.emplace_back(boneIndex, transformType, fileData);
+ }
+
+ return std::make_shared<AnimData>(startFrame, endFrame, animFiles);
+}
+
+std::optional<std::shared_ptr<IParsedData>> AnimFactory::parse_modding(std::vector<uint8_t>& buffer, YAML::Node& node) {
+ YAML::Node assetNode;
+
+ try {
+ std::string text((char*)buffer.data(), buffer.size());
+ assetNode = YAML::Load(text.c_str());
+ } catch (YAML::ParserException& e) {
+ SPDLOG_ERROR("Failed to parse message data: {}", e.what());
+ SPDLOG_ERROR("{}", (char*)buffer.data());
+ return std::nullopt;
+ }
+
+ const auto info = assetNode.begin()->second;
+
+ auto startFrame = info["StartFrame"].as<int16_t>();
+ auto endFrame = info["EndFrame"].as<int16_t>();
+
+ auto elements = info["Elements"];
+
+ std::vector<AnimationFile> animFiles;
+
+ for (YAML::iterator it = elements.begin(); it != elements.end(); ++it) {
+ auto elem = *it;
+
+ auto boneIndex = elem["BoneIndex"].as<int16_t>();
+ auto transformType = elem["TransformType"].as<int16_t>();
+ auto data = elem["Data"];
+
+ std::vector<AnimationFileData> fileData;
+ for (YAML::iterator jt = data.begin(); jt != data.end(); ++jt) {
+ AnimationFileData animFileData;
+
+ animFileData.unk0_15 = (*jt)[0].as<uint32_t>();
+ animFileData.unk0_14 = (*jt)[1].as<uint32_t>();
+ animFileData.unk0_13 = (*jt)[2].as<uint16_t>();
+ animFileData.unk2 = (*jt)[3].as<int16_t>();
+
+ fileData.push_back(animFileData);
+ }
+ animFiles.emplace_back(boneIndex, transformType, fileData);
+ }
+
+ return std::make_shared<AnimData>(startFrame, endFrame, animFiles);
+}
+
+} // namespace BK64