mirror of
https://github.com/izzy2lost/Torch.git
synced 2026-07-06 00:18:35 -07:00
Add Mtx, float, and mk64 Factories (#43)
* Create MtxFactory.cpp * Add mtx factory * Implement mtx output * Changed implementation * Update comment * Finish Mtx factory * Add float factory * Add runtime error for untested code * Add DrivingBehaviour factory & fix bug * Remove limit * Add mk64 graphics * Changes * fix * Update * Improve error checking
This commit is contained in:
@@ -509,7 +509,7 @@ rgba* png2rgba(unsigned char* png_input, int size_input, int* width, int* height
|
||||
}
|
||||
|
||||
rgb* png2rgb(unsigned char* png_input, int size_input, int* width, int* height) {
|
||||
rgba* img = NULL;
|
||||
rgb* img = NULL;
|
||||
int w = 0;
|
||||
int h = 0;
|
||||
int channels = 0;
|
||||
@@ -538,11 +538,6 @@ rgb* png2rgb(unsigned char* png_input, int size_input, int* width, int* height)
|
||||
img[idx].red = data[channels * idx];
|
||||
img[idx].green = data[channels * idx + 1];
|
||||
img[idx].blue = data[channels * idx + 2];
|
||||
if (channels == 4) {
|
||||
img[idx].alpha = data[channels * idx + 3];
|
||||
} else {
|
||||
img[idx].alpha = 0xFF;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -13,6 +13,8 @@
|
||||
#include "factories/SampleFactory.h"
|
||||
#include "factories/SequenceFactory.h"
|
||||
#include "factories/VtxFactory.h"
|
||||
#include "factories/MtxFactory.h"
|
||||
#include "factories/FloatFactory.h"
|
||||
#include "factories/TextureFactory.h"
|
||||
#include "factories/DisplayListFactory.h"
|
||||
#include "factories/DisplayListOverrides.h"
|
||||
@@ -23,6 +25,7 @@
|
||||
#include "factories/mk64/Waypoints.h"
|
||||
#include "factories/mk64/TrackSections.h"
|
||||
#include "factories/mk64/SpawnData.h"
|
||||
#include "factories/mk64/DrivingBehaviour.h"
|
||||
#include "spdlog/spdlog.h"
|
||||
#include "hj/sha1.h"
|
||||
|
||||
@@ -59,6 +62,8 @@ void Companion::Init(const ExportType type) {
|
||||
this->RegisterFactory("BLOB", std::make_shared<BlobFactory>());
|
||||
this->RegisterFactory("TEXTURE", std::make_shared<TextureFactory>());
|
||||
this->RegisterFactory("VTX", std::make_shared<VtxFactory>());
|
||||
this->RegisterFactory("MTX", std::make_shared<MtxFactory>());
|
||||
this->RegisterFactory("F32", std::make_shared<FloatFactory>());
|
||||
this->RegisterFactory("LIGHTS", std::make_shared<LightsFactory>());
|
||||
this->RegisterFactory("GFX", std::make_shared<DListFactory>());
|
||||
this->RegisterFactory("AUDIO:HEADER", std::make_shared<AudioHeaderFactory>());
|
||||
@@ -79,6 +84,7 @@ void Companion::Init(const ExportType type) {
|
||||
this->RegisterFactory("MK64:TRACK_WAYPOINTS", std::make_shared<MK64::WaypointsFactory>());
|
||||
this->RegisterFactory("MK64:TRACK_SECTIONS", std::make_shared<MK64::TrackSectionsFactory>());
|
||||
this->RegisterFactory("MK64:SPAWN_DATA", std::make_shared<MK64::SpawnDataFactory>());
|
||||
this->RegisterFactory("MK64:DRIVING_BEHAVIOUR", std::make_shared<MK64::DrivingBehaviourFactory>());
|
||||
|
||||
// SF64 specific
|
||||
this->RegisterFactory("SF64:ANIM", std::make_shared<SF64::AnimFactory>());
|
||||
|
||||
@@ -52,7 +52,11 @@ std::optional<T> GetNode(YAML::Node& node, const std::string& key) {
|
||||
template<typename T>
|
||||
T GetSafeNode(YAML::Node& node, const std::string& key) {
|
||||
if(!node[key]) {
|
||||
throw std::runtime_error("Failed to find " + key + " in yaml");
|
||||
if (node["symbol"]) {
|
||||
throw std::runtime_error("Yaml asset missing the '" + key + "' node for '" + node["symbol"].as<std::string>() + "'");
|
||||
} else {
|
||||
throw std::runtime_error("Yaml asset missing the '" + key + "' node");
|
||||
}
|
||||
}
|
||||
|
||||
return node[key].as<T>();
|
||||
|
||||
@@ -0,0 +1,102 @@
|
||||
#include "FloatFactory.h"
|
||||
#include "spdlog/spdlog.h"
|
||||
|
||||
#include "Companion.h"
|
||||
#include "utils/Decompressor.h"
|
||||
|
||||
#define NUM(x) std::dec << std::setfill(' ') << std::setw(6) << x
|
||||
#define COL(c) std::dec << std::setfill(' ') << std::setw(3) << c
|
||||
|
||||
ExportResult FloatHeaderExporter::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 f32 " << symbol << "[];\n";
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
ExportResult FloatCodeExporter::Export(std::ostream &write, std::shared_ptr<IParsedData> raw, std::string& entryName, YAML::Node &node, std::string* replacement ) {
|
||||
auto f = std::static_pointer_cast<FloatData>(raw)->mFloats;
|
||||
const auto symbol = GetSafeNode(node, "symbol", entryName);
|
||||
auto offset = GetSafeNode<uint32_t>(node, "offset");
|
||||
|
||||
if (IS_SEGMENTED(offset)) {
|
||||
offset = SEGMENT_OFFSET(offset);
|
||||
}
|
||||
|
||||
if (Companion::Instance->IsDebug()) {
|
||||
if (IS_SEGMENTED(offset)) {
|
||||
offset = SEGMENT_OFFSET(offset);
|
||||
}
|
||||
write << "// 0x" << std::hex << std::uppercase << offset << "\n";
|
||||
}
|
||||
|
||||
write << "f32 " << symbol << "[] = {";
|
||||
|
||||
/**
|
||||
* f32 sym[] = {
|
||||
* 0.1, 0.2, 0.3,
|
||||
* };
|
||||
*
|
||||
*/
|
||||
for (int i = 0; i < f.size(); ++i) {
|
||||
|
||||
// Make a new line every fourth iteration
|
||||
if ((i % 4) == 0) {
|
||||
write << "\n" << fourSpaceTab;
|
||||
}
|
||||
|
||||
write << f[i] << ", ";
|
||||
|
||||
// if(i <= f.size() - 1) {
|
||||
// write << fourSpaceTab;
|
||||
// }
|
||||
}
|
||||
|
||||
write << "\n};\n";
|
||||
|
||||
if (Companion::Instance->IsDebug()) {
|
||||
write << "// count: " << std::to_string(f.size()) << " f32s\n";
|
||||
write << "// 0x" << std::hex << std::uppercase << (offset + (sizeof(float) * f.size())) << "\n";
|
||||
}
|
||||
|
||||
write << "\n";
|
||||
|
||||
return offset + f.size() * sizeof(float);
|
||||
}
|
||||
|
||||
ExportResult FloatBinaryExporter::Export(std::ostream &write, std::shared_ptr<IParsedData> raw, std::string& entryName, YAML::Node &node, std::string* replacement ) {
|
||||
auto f = std::static_pointer_cast<FloatData>(raw);
|
||||
auto writer = LUS::BinaryWriter();
|
||||
|
||||
WriteHeader(writer, LUS::ResourceType::Float, 0);
|
||||
writer.Write((uint32_t) f->mFloats.size());
|
||||
for(auto fl : f->mFloats) {
|
||||
writer.Write(fl);
|
||||
}
|
||||
throw std::runtime_error("Float factory untested for otr/o2r exporter");
|
||||
writer.Finish(write);
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::optional<std::shared_ptr<IParsedData>> FloatFactory::parse(std::vector<uint8_t>& buffer, YAML::Node& node) {
|
||||
auto count = GetSafeNode<size_t>(node, "count");
|
||||
|
||||
auto [_, segment] = Decompressor::AutoDecode(node, buffer);
|
||||
LUS::BinaryReader reader(segment.data, count * sizeof(float));
|
||||
|
||||
reader.SetEndianness(LUS::Endianness::Big);
|
||||
std::vector<float> floats;
|
||||
|
||||
for(size_t i = 0; i < count; i++) {
|
||||
auto f = reader.ReadFloat();
|
||||
|
||||
floats.push_back(f);
|
||||
}
|
||||
|
||||
return std::make_shared<FloatData>(floats);
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
#pragma once
|
||||
|
||||
#include "BaseFactory.h"
|
||||
|
||||
class FloatData : public IParsedData {
|
||||
public:
|
||||
std::vector<float> mFloats;
|
||||
|
||||
explicit FloatData(std::vector<float> floats) : mFloats(floats) {}
|
||||
};
|
||||
|
||||
class FloatHeaderExporter : public BaseExporter {
|
||||
ExportResult Export(std::ostream& write, std::shared_ptr<IParsedData> data, std::string& entryName, YAML::Node& node, std::string* replacement) override;
|
||||
};
|
||||
|
||||
class FloatBinaryExporter : public BaseExporter {
|
||||
ExportResult Export(std::ostream& write, std::shared_ptr<IParsedData> data, std::string& entryName, YAML::Node& node, std::string* replacement) override;
|
||||
};
|
||||
|
||||
class FloatCodeExporter : public BaseExporter {
|
||||
ExportResult Export(std::ostream& write, std::shared_ptr<IParsedData> data, std::string& entryName, YAML::Node& node, std::string* replacement) override;
|
||||
};
|
||||
|
||||
class FloatFactory : public BaseFactory {
|
||||
public:
|
||||
std::optional<std::shared_ptr<IParsedData>> parse(std::vector<uint8_t>& buffer, YAML::Node& data) override;
|
||||
std::optional<std::shared_ptr<IParsedData>> parse_modding(std::vector<uint8_t>& buffer, YAML::Node& data) override {
|
||||
return std::nullopt;
|
||||
}
|
||||
inline std::unordered_map<ExportType, std::shared_ptr<BaseExporter>> GetExporters() override {
|
||||
return {
|
||||
REGISTER(Code, FloatCodeExporter)
|
||||
REGISTER(Header, FloatHeaderExporter)
|
||||
REGISTER(Binary, FloatBinaryExporter)
|
||||
};
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,207 @@
|
||||
#include "MtxFactory.h"
|
||||
#include "spdlog/spdlog.h"
|
||||
|
||||
#include "Companion.h"
|
||||
#include "utils/Decompressor.h"
|
||||
|
||||
#define NUM(x) std::dec << std::setfill(' ') << std::setw(6) << x
|
||||
#define COL(c) std::dec << std::setfill(' ') << std::setw(3) << c
|
||||
|
||||
ExportResult MtxHeaderExporter::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 Mtx " << symbol << "[];\n";
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
ExportResult MtxCodeExporter::Export(std::ostream &write, std::shared_ptr<IParsedData> raw, std::string& entryName, YAML::Node &node, std::string* replacement ) {
|
||||
auto m = std::static_pointer_cast<MtxData>(raw)->mMtxs;
|
||||
const auto symbol = GetSafeNode(node, "symbol", entryName);
|
||||
auto offset = GetSafeNode<uint32_t>(node, "offset");
|
||||
|
||||
if (IS_SEGMENTED(offset)) {
|
||||
offset = SEGMENT_OFFSET(offset);
|
||||
}
|
||||
|
||||
if (Companion::Instance->IsDebug()) {
|
||||
if (IS_SEGMENTED(offset)) {
|
||||
offset = SEGMENT_OFFSET(offset);
|
||||
}
|
||||
write << "// 0x" << std::hex << std::uppercase << offset << "\n";
|
||||
}
|
||||
|
||||
#define fiveFourSpaceTabs fourSpaceTab << fourSpaceTab << fourSpaceTab << fourSpaceTab << fourSpaceTab << " "
|
||||
|
||||
/**
|
||||
* toFixedPointMatrix(1.0, 0.0, 0.0, 0.0,
|
||||
* 0.0, 1.0, 0.0, 0.0,
|
||||
* 0.0, 0.0, 1.0, 0.0,
|
||||
* 0.0, 0.0, 0.0, 1.0);
|
||||
*/
|
||||
|
||||
write << "Mtx " << symbol << "[] = {\n";
|
||||
|
||||
for (int i = 0; i < m.size(); ++i) {
|
||||
|
||||
write << fourSpaceTab << "toFixedPointMatrix(";
|
||||
|
||||
for (int j = 0; j < 16; ++j) {
|
||||
|
||||
// Turn 1, 3, and 6 into 1.0, 3.0, and 6.0. Unless it has a decimal number then leave it alone.
|
||||
if (std::abs(m[i].mtx[j] - static_cast<int>(m[i].mtx[j])) < 1e-6) {
|
||||
write << std::fixed << std::setprecision(1) << m[i].mtx[j];
|
||||
} else {
|
||||
write << std::fixed << std::setprecision(6) << m[i].mtx[j];
|
||||
}
|
||||
|
||||
// Add comma for all but the last arg
|
||||
if (j < 15) {
|
||||
write << ", ";
|
||||
}
|
||||
|
||||
// Add closing bracket for last arg in matrix
|
||||
if (j == 15) {
|
||||
write << "),\n";
|
||||
|
||||
// Do not add an extra \n on the last iteration.
|
||||
if (i < m.size() - 1) {
|
||||
write << "\n";
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// Add lots of spaces for start of a new line
|
||||
if ((j + 1) % 4 == 0) {
|
||||
write << "\n" << fiveFourSpaceTabs;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
write << "};\n";
|
||||
|
||||
if (Companion::Instance->IsDebug()) {
|
||||
write << "// count: " << std::to_string(m.size()) << " Mtxs\n";
|
||||
write << "// 0x" << std::hex << std::uppercase << (offset + (sizeof(MtxRaw) * m.size())) << "\n";
|
||||
}
|
||||
|
||||
write << "\n";
|
||||
|
||||
#undef fiveFourSpaceTabs
|
||||
|
||||
return offset + m.size() * sizeof(MtxRaw);
|
||||
}
|
||||
|
||||
ExportResult MtxBinaryExporter::Export(std::ostream &write, std::shared_ptr<IParsedData> raw, std::string& entryName, YAML::Node &node, std::string* replacement ) {
|
||||
auto mtx = std::static_pointer_cast<MtxData>(raw);
|
||||
auto writer = LUS::BinaryWriter();
|
||||
|
||||
WriteHeader(writer, LUS::ResourceType::Matrix, 0);
|
||||
writer.Write((uint32_t) mtx->mMtxs.size());
|
||||
for(auto m : mtx->mMtxs) {
|
||||
writer.Write(m.mtx[0]);
|
||||
writer.Write(m.mtx[1]);
|
||||
writer.Write(m.mtx[2]);
|
||||
writer.Write(m.mtx[3]);
|
||||
writer.Write(m.mtx[4]);
|
||||
writer.Write(m.mtx[5]);
|
||||
writer.Write(m.mtx[6]);
|
||||
writer.Write(m.mtx[7]);
|
||||
writer.Write(m.mtx[8]);
|
||||
writer.Write(m.mtx[9]);
|
||||
writer.Write(m.mtx[10]);
|
||||
writer.Write(m.mtx[11]);
|
||||
writer.Write(m.mtx[12]);
|
||||
writer.Write(m.mtx[13]);
|
||||
writer.Write(m.mtx[14]);
|
||||
writer.Write(m.mtx[15]);
|
||||
}
|
||||
throw std::runtime_error("Mtx not tested for otr/o2r.");
|
||||
writer.Finish(write);
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::optional<std::shared_ptr<IParsedData>> MtxFactory::parse(std::vector<uint8_t>& buffer, YAML::Node& node) {
|
||||
auto count = GetSafeNode<size_t>(node, "count");
|
||||
|
||||
auto [_, segment] = Decompressor::AutoDecode(node, buffer);
|
||||
LUS::BinaryReader reader(segment.data, count * sizeof(MtxRaw));
|
||||
|
||||
reader.SetEndianness(LUS::Endianness::Big);
|
||||
std::vector<MtxRaw> matrix;
|
||||
|
||||
#define FIXTOF(x) ((double)((x) / 65536.0))
|
||||
|
||||
// Reads the inteer portion, the fractional portion, puts each together into a fixed-point value, and finally converts to float.
|
||||
for(size_t i = 0; i < count; i++) {
|
||||
// Read the integer portion of the fixed-point value (ex. 4)
|
||||
auto i1 = reader.ReadInt16();
|
||||
auto i2 = reader.ReadInt16();
|
||||
auto i3 = reader.ReadInt16();
|
||||
auto i4 = reader.ReadInt16();
|
||||
auto i5 = reader.ReadInt16();
|
||||
auto i6 = reader.ReadInt16();
|
||||
auto i7 = reader.ReadInt16();
|
||||
auto i8 = reader.ReadInt16();
|
||||
auto i9 = reader.ReadInt16();
|
||||
auto i10 = reader.ReadInt16();
|
||||
auto i11 = reader.ReadInt16();
|
||||
auto i12 = reader.ReadInt16();
|
||||
auto i13 = reader.ReadInt16();
|
||||
auto i14 = reader.ReadInt16();
|
||||
auto i15 = reader.ReadInt16();
|
||||
auto i16 = reader.ReadInt16();
|
||||
|
||||
// Read the fractional portion of the fixed-point value (ex. 0.45)
|
||||
auto f1 = reader.ReadUInt16();
|
||||
auto f2 = reader.ReadUInt16();
|
||||
auto f3 = reader.ReadUInt16();
|
||||
auto f4 = reader.ReadUInt16();
|
||||
auto f5 = reader.ReadUInt16();
|
||||
auto f6 = reader.ReadUInt16();
|
||||
auto f7 = reader.ReadUInt16();
|
||||
auto f8 = reader.ReadUInt16();
|
||||
auto f9 = reader.ReadUInt16();
|
||||
auto f10 = reader.ReadUInt16();
|
||||
auto f11 = reader.ReadUInt16();
|
||||
auto f12 = reader.ReadUInt16();
|
||||
auto f13 = reader.ReadUInt16();
|
||||
auto f14 = reader.ReadUInt16();
|
||||
auto f15 = reader.ReadUInt16();
|
||||
auto f16 = reader.ReadUInt16();
|
||||
|
||||
// Place the integer and fractional portions together (ex 4.45) and convert to floating-point
|
||||
auto m1 = FIXTOF( (int32_t) ( (i1 << 16) | f1 ) );
|
||||
auto m2 = FIXTOF( (int32_t) ( (i2 << 16) | f2 ) );
|
||||
auto m3 = FIXTOF( (int32_t) ( (i3 << 16) | f3 ) );
|
||||
auto m4 = FIXTOF( (int32_t) ( (i4 << 16) | f4 ) );
|
||||
auto m5 = FIXTOF( (int32_t) ( (i5 << 16) | f5 ) );
|
||||
auto m6 = FIXTOF( (int32_t) ( (i6 << 16) | f6 ) );
|
||||
auto m7 = FIXTOF( (int32_t) ( (i7 << 16) | f7 ) );
|
||||
auto m8 = FIXTOF( (int32_t) ( (i8 << 16) | f8 ) );
|
||||
auto m9 = FIXTOF( (int32_t) ( (i9 << 16) | f9 ) );
|
||||
auto m10 = FIXTOF( (int32_t) ( (i10 << 16) | f10 ) );
|
||||
auto m11 = FIXTOF( (int32_t) ( (i11 << 16) | f11 ) );
|
||||
auto m12 = FIXTOF( (int32_t) ( (i12 << 16) | f12 ) );
|
||||
auto m13 = FIXTOF( (int32_t) ( (i13 << 16) | f13 ) );
|
||||
auto m14 = FIXTOF( (int32_t) ( (i14 << 16) | f14 ) );
|
||||
auto m15 = FIXTOF( (int32_t) ( (i15 << 16) | f15 ) );
|
||||
auto m16 = FIXTOF( (int32_t) ( (i16 << 16) | f16 ) );
|
||||
|
||||
|
||||
matrix.push_back(MtxRaw({
|
||||
m1, m2, m3, m4,
|
||||
m5, m6, m7, m8,
|
||||
m9, m10, m11, m12,
|
||||
m13, m14, m15, m16,
|
||||
}));
|
||||
}
|
||||
|
||||
#undef FIXTOF
|
||||
|
||||
return std::make_shared<MtxData>(matrix);
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
#pragma once
|
||||
|
||||
#include "BaseFactory.h"
|
||||
|
||||
struct MtxRaw {
|
||||
double mtx[16];
|
||||
};
|
||||
|
||||
class MtxData : public IParsedData {
|
||||
public:
|
||||
std::vector<MtxRaw> mMtxs;
|
||||
|
||||
explicit MtxData(std::vector<MtxRaw> mtxs) : mMtxs(mtxs) {}
|
||||
};
|
||||
|
||||
class MtxHeaderExporter : public BaseExporter {
|
||||
ExportResult Export(std::ostream& write, std::shared_ptr<IParsedData> data, std::string& entryName, YAML::Node& node, std::string* replacement) override;
|
||||
};
|
||||
|
||||
class MtxBinaryExporter : public BaseExporter {
|
||||
ExportResult Export(std::ostream& write, std::shared_ptr<IParsedData> data, std::string& entryName, YAML::Node& node, std::string* replacement) override;
|
||||
};
|
||||
|
||||
class MtxCodeExporter : public BaseExporter {
|
||||
ExportResult Export(std::ostream& write, std::shared_ptr<IParsedData> data, std::string& entryName, YAML::Node& node, std::string* replacement) override;
|
||||
};
|
||||
|
||||
class MtxFactory : public BaseFactory {
|
||||
public:
|
||||
std::optional<std::shared_ptr<IParsedData>> parse(std::vector<uint8_t>& buffer, YAML::Node& data) override;
|
||||
std::optional<std::shared_ptr<IParsedData>> parse_modding(std::vector<uint8_t>& buffer, YAML::Node& data) override {
|
||||
return std::nullopt;
|
||||
}
|
||||
inline std::unordered_map<ExportType, std::shared_ptr<BaseExporter>> GetExporters() override {
|
||||
return {
|
||||
REGISTER(Code, MtxCodeExporter)
|
||||
REGISTER(Header, MtxHeaderExporter)
|
||||
REGISTER(Binary, MtxBinaryExporter)
|
||||
};
|
||||
}
|
||||
};
|
||||
@@ -11,6 +11,7 @@ enum class ResourceType {
|
||||
DisplayList = 0x4F444C54, // ODLT
|
||||
Vertex = 0x4F565458, // OVTX
|
||||
Matrix = 0x4F4D5458, // OMTX
|
||||
Float = 0x4F464C54, // OFLT
|
||||
Array = 0x4F415252, // OARR
|
||||
Blob = 0x4F424C42, // OBLB
|
||||
Texture = 0x4F544558, // OTEX
|
||||
@@ -31,6 +32,7 @@ enum class ResourceType {
|
||||
Waypoints = 0x57505453, // WPTS
|
||||
Metadata = 0x4D444154, // MDAT
|
||||
SpawnData = 0x53444154, // SDAT
|
||||
DrivingBehaviour = 0x44424856, // DBHV
|
||||
|
||||
// SF64
|
||||
AnimData = 0x414E494D, // ANIM
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
#include "DrivingBehaviour.h"
|
||||
#include "spdlog/spdlog.h"
|
||||
|
||||
#include "Companion.h"
|
||||
#include "utils/Decompressor.h"
|
||||
|
||||
#define NUM(x) std::dec << std::setfill(' ') << std::setw(6) << x
|
||||
#define COL(c) std::dec << std::setfill(' ') << std::setw(3) << c
|
||||
|
||||
ExportResult MK64::DrivingBehaviourHeaderExporter::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 DrivingBehaviour " << symbol << "[];\n";
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
ExportResult MK64::DrivingBehaviourCodeExporter::Export(std::ostream &write, std::shared_ptr<IParsedData> raw, std::string& entryName, YAML::Node &node, std::string* replacement ) {
|
||||
auto bhv = std::static_pointer_cast<DrivingData>(raw);
|
||||
const auto symbol = GetSafeNode(node, "symbol", entryName);
|
||||
auto offset = GetSafeNode<uint32_t>(node, "offset");
|
||||
|
||||
if (IS_SEGMENTED(offset)) {
|
||||
offset = SEGMENT_OFFSET(offset);
|
||||
}
|
||||
|
||||
if (Companion::Instance->IsDebug()) {
|
||||
if (IS_SEGMENTED(offset)) {
|
||||
offset = SEGMENT_OFFSET(offset);
|
||||
}
|
||||
write << "// 0x" << std::hex << std::uppercase << offset << "\n";
|
||||
}
|
||||
|
||||
write << "DrivingBehaviour " << symbol << "[] = {\n";
|
||||
|
||||
|
||||
for(auto b : bhv->mBhvs) {
|
||||
auto w1 = b.waypoint1;
|
||||
auto w2 = b.waypoint2;
|
||||
auto id = b.bhv;
|
||||
|
||||
// { w1, w2, bhvId}
|
||||
write << fourSpaceTab << "{" << NUM(w1) << ", " << NUM(w2) << ", " << NUM(id) << "},\n";
|
||||
}
|
||||
|
||||
write << "};\n";
|
||||
|
||||
if (Companion::Instance->IsDebug()) {
|
||||
write << "// count: " << std::to_string(bhv->mBhvs.size()) << " Entries\n";
|
||||
write << "// 0x" << std::hex << std::uppercase << (offset + (sizeof(BhvRaw) * bhv->mBhvs.size())) << "\n";
|
||||
}
|
||||
|
||||
write << "\n";
|
||||
return offset + bhv->mBhvs.size() * sizeof(BhvRaw);
|
||||
}
|
||||
|
||||
ExportResult MK64::DrivingBehaviourBinaryExporter::Export(std::ostream &write, std::shared_ptr<IParsedData> raw, std::string& entryName, YAML::Node &node, std::string* replacement ) {
|
||||
auto bhv = std::static_pointer_cast<DrivingData>(raw);
|
||||
auto writer = LUS::BinaryWriter();
|
||||
|
||||
WriteHeader(writer, LUS::ResourceType::DrivingBehaviour, 0);
|
||||
writer.Write((uint32_t) bhv->mBhvs.size());
|
||||
for(auto b : bhv->mBhvs) {
|
||||
writer.Write(b.waypoint1);
|
||||
writer.Write(b.waypoint2);
|
||||
writer.Write(b.bhv);
|
||||
}
|
||||
|
||||
writer.Finish(write);
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::optional<std::shared_ptr<IParsedData>> MK64::DrivingBehaviourFactory::parse(std::vector<uint8_t>& buffer, YAML::Node& node) {
|
||||
auto [_, segment] = Decompressor::AutoDecode(node, buffer);
|
||||
LUS::BinaryReader reader(segment.data, segment.size);
|
||||
|
||||
reader.SetEndianness(LUS::Endianness::Big);
|
||||
std::vector<BhvRaw> behaviours;
|
||||
|
||||
while(1) {
|
||||
auto w1 = reader.ReadInt16();
|
||||
auto w2 = reader.ReadInt16();
|
||||
auto id = reader.ReadInt32();
|
||||
|
||||
behaviours.push_back( BhvRaw( {w1, w2, id} ) );
|
||||
|
||||
// Magic number for ending of array
|
||||
if ((w1 == -1) && (w2 == -1)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return std::make_shared<DrivingData>(behaviours);
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
#pragma once
|
||||
|
||||
#include "../BaseFactory.h"
|
||||
|
||||
namespace MK64 {
|
||||
|
||||
struct BhvRaw {
|
||||
int16_t waypoint1;
|
||||
int16_t waypoint2;
|
||||
int32_t bhv;
|
||||
};
|
||||
|
||||
class DrivingData : public IParsedData {
|
||||
public:
|
||||
std::vector<BhvRaw> mBhvs;
|
||||
|
||||
explicit DrivingData(std::vector<BhvRaw> bhvs) : mBhvs(bhvs) {}
|
||||
};
|
||||
|
||||
class DrivingBehaviourHeaderExporter : public BaseExporter {
|
||||
ExportResult Export(std::ostream& write, std::shared_ptr<IParsedData> data, std::string& entryName, YAML::Node& node, std::string* replacement) override;
|
||||
};
|
||||
|
||||
class DrivingBehaviourBinaryExporter : public BaseExporter {
|
||||
ExportResult Export(std::ostream& write, std::shared_ptr<IParsedData> data, std::string& entryName, YAML::Node& node, std::string* replacement) override;
|
||||
};
|
||||
|
||||
class DrivingBehaviourCodeExporter : public BaseExporter {
|
||||
ExportResult Export(std::ostream& write, std::shared_ptr<IParsedData> data, std::string& entryName, YAML::Node& node, std::string* replacement) override;
|
||||
};
|
||||
|
||||
class DrivingBehaviourFactory : public BaseFactory {
|
||||
public:
|
||||
std::optional<std::shared_ptr<IParsedData>> parse(std::vector<uint8_t>& buffer, YAML::Node& data) override;
|
||||
std::optional<std::shared_ptr<IParsedData>> parse_modding(std::vector<uint8_t>& buffer, YAML::Node& data) override {
|
||||
return std::nullopt;
|
||||
}
|
||||
inline std::unordered_map<ExportType, std::shared_ptr<BaseExporter>> GetExporters() override {
|
||||
return {
|
||||
REGISTER(Code, DrivingBehaviourCodeExporter)
|
||||
REGISTER(Header, DrivingBehaviourHeaderExporter)
|
||||
REGISTER(Binary, DrivingBehaviourBinaryExporter)
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user