From 4d6744dcaca3bb1902a74e823353d7d79c6d3d39 Mon Sep 17 00:00:00 2001 From: inspectredc Date: Fri, 26 Apr 2024 01:06:37 +0100 Subject: Actual Painting Factory --- src/Companion.cpp | 2 + src/factories/ResourceType.h | 3 +- src/factories/sm64/PaintingFactory.cpp | 280 +++++++++++++++++++++++++++++ src/factories/sm64/PaintingFactory.h | 153 ++++++++++++++++ src/factories/sm64/WaterDropletFactory.cpp | 4 +- 5 files changed, 438 insertions(+), 4 deletions(-) create mode 100644 src/factories/sm64/PaintingFactory.cpp create mode 100644 src/factories/sm64/PaintingFactory.h diff --git a/src/Companion.cpp b/src/Companion.cpp index 136c536..ecc400e 100644 --- a/src/Companion.cpp +++ b/src/Companion.cpp @@ -40,6 +40,7 @@ #include "factories/sm64/MacroFactory.h" #include "factories/sm64/MovtexFactory.h" #include "factories/sm64/MovtexQuadFactory.h" +#include "factories/sm64/PaintingFactory.h" #include "factories/sm64/PaintingMapFactory.h" #include "factories/sm64/TrajectoryFactory.h" #include "factories/sm64/WaterDropletFactory.h" @@ -106,6 +107,7 @@ void Companion::Init(const ExportType type) { this->RegisterFactory("SM64:MACRO", std::make_shared()); this->RegisterFactory("SM64:MOVTEX_QUAD", std::make_shared()); this->RegisterFactory("SM64:MOVTEX", std::make_shared()); + this->RegisterFactory("SM64:PAINTING", std::make_shared()); this->RegisterFactory("SM64:PAINTING_MAP", std::make_shared()); this->RegisterFactory("SM64:TRAJECTORY", std::make_shared()); this->RegisterFactory("SM64:WATER_DROPLET", std::make_shared()); diff --git a/src/factories/ResourceType.h b/src/factories/ResourceType.h index de7f4f9..9d9fbca 100644 --- a/src/factories/ResourceType.h +++ b/src/factories/ResourceType.h @@ -35,7 +35,8 @@ enum class ResourceType { MacroObject = 0x4D41434F, // MACO Movtex = 0x4D4F5654, // MOVT MovtexQuad = 0x4D4F5651, // MOVQ - PaintingData = 0x5041494E, // PAIN + Painting = 0x504E5420, // PNT + PaintingData = 0x504E5444, // PNTD Trajectory = 0x5452414A, // TRAJ WaterDroplet = 0x57545244, // WTRD diff --git a/src/factories/sm64/PaintingFactory.cpp b/src/factories/sm64/PaintingFactory.cpp new file mode 100644 index 0000000..a8979d1 --- /dev/null +++ b/src/factories/sm64/PaintingFactory.cpp @@ -0,0 +1,280 @@ +#include "PaintingFactory.h" +#include "spdlog/spdlog.h" + +#include "Companion.h" +#include "utils/Decompressor.h" +#include "utils/TorchUtils.h" +#include + +ExportResult SM64::PaintingHeaderExporter::Export(std::ostream &write, std::shared_ptr 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 struct Painting " << symbol << "[];\n"; + return std::nullopt; +} + +ExportResult SM64::PaintingCodeExporter::Export(std::ostream &write, std::shared_ptr raw, std::string& entryName, YAML::Node &node, std::string* replacement ) { + const auto symbol = GetSafeNode(node, "symbol", entryName); + const auto offset = GetSafeNode(node, "offset"); + + auto painting = std::static_pointer_cast(raw); + + write << "struct Painting " << symbol << " = {\n"; + + std::stringstream textureType; + + if (painting->textureType == PAINTING_IMAGE) { + textureType << "PAINTING_IMAGE"; + } else if (painting->textureType == PAINTING_ENV_MAP) { + textureType << "PAINTING_ENV_MAP"; + } else { + textureType << painting->textureType; // should not reach this case, throw error? + } + + std::stringstream nDLSymbol; + { + auto dec = Companion::Instance->GetNodeByAddr(painting->normalDisplayList); + if (dec.has_value()) { + auto nDLNode = std::get<1>(dec.value()); + nDLSymbol << GetSafeNode(nDLNode, "symbol"); + } else { + SPDLOG_WARN("Cannot find node for ptr 0x{:X}", painting->normalDisplayList); + nDLSymbol << std::hex << "0x" << painting->normalDisplayList << std::dec; + } + } + + std::stringstream tMapSymbol; + { + auto dec = Companion::Instance->GetNodeByAddr(painting->textureMaps); + if (dec.has_value()) { + auto tMapNode = std::get<1>(dec.value()); + tMapSymbol << GetSafeNode(tMapNode, "symbol"); + } else { + SPDLOG_WARN("Cannot find node for ptr 0x{:X}", painting->textureMaps); + tMapSymbol << std::hex << "0x" << painting->textureMaps << std::dec; + } + } + + std::stringstream tArrSymbol; + { + auto dec = Companion::Instance->GetNodeByAddr(painting->textureArray); + if (dec.has_value()) { + auto tMapNode = std::get<1>(dec.value()); + tArrSymbol << GetSafeNode(tMapNode, "symbol"); + } else { + SPDLOG_WARN("Cannot find node for ptr 0x{:X}", painting->textureArray); + tArrSymbol << std::hex << "0x" << painting->textureArray << std::dec; + } + } + + std::stringstream rDLSymbol; + { + auto dec = Companion::Instance->GetNodeByAddr(painting->rippleDisplayList); + if (dec.has_value()) { + auto rDLNode = std::get<1>(dec.value()); + rDLSymbol << GetSafeNode(rDLNode, "symbol"); + } else { + SPDLOG_WARN("Cannot find node for ptr 0x{:X}", painting->rippleDisplayList); + rDLSymbol << std::hex << "0x" << painting->rippleDisplayList << std::dec; + } + } + + std::stringstream rippleTrigger; + if (painting->rippleTrigger == RIPPLE_TRIGGER_PROXIMITY) { + rippleTrigger << "RIPPLE_TRIGGER_PROXIMITY"; + } else if (painting->rippleTrigger == RIPPLE_TRIGGER_CONTINUOUS) { + rippleTrigger << "RIPPLE_TRIGGER_CONTINUOUS"; + } else { + rippleTrigger << painting->rippleTrigger; // should not reach this case, throw error? + } + + write << fourSpaceTab << "/* id */ " << std::hex << "0x" << painting->id << ",\n"; + write << fourSpaceTab << "/* Image Count */ " << std::hex << "0x" << (uint32_t)painting->imageCount << ",\n"; + write << fourSpaceTab << "/* Texture Type */ " << textureType.str() << ",\n"; + write << fourSpaceTab << "/* Floor Status */ " << std::hex << "0x" << (uint32_t)painting->lastFloor << ", " << std::hex << "0x" << (uint32_t)painting->currFloor << ", " << std::hex << "0x" << (uint32_t)painting->floorEntered << ",\n"; + write << fourSpaceTab << "/* Ripple Status */ " << (uint32_t)painting->state << ",\n"; + write << fourSpaceTab << "/* Rotation */ " << painting->pitch << ", " << painting->yaw << ",\n"; + write << fourSpaceTab << "/* Position */ " << painting->posX << ", " << painting->posY << ", " << painting->posZ << ",\n"; + write << fourSpaceTab << "/* Ripple Magnitude */ " << painting->currRippleMag << ", " << painting->passiveRippleMag << ", " << painting->entryRippleMag << ",\n"; + write << fourSpaceTab << "/* Ripple Decay */ " << painting->rippleDecay << ", " << painting->passiveRippleDecay << ", " << painting->entryRippleDecay << ",\n"; + write << fourSpaceTab << "/* Ripple Rate */ " << painting->currRippleRate << ", " << painting->passiveRippleRate << ", " << painting->entryRippleRate << ",\n"; + write << fourSpaceTab << "/* Ripple Dispersion */ " << painting->dispersionFactor << ", " << painting->passiveDispersionFactor << ", " << painting->entryDispersionFactor << ",\n"; + write << fourSpaceTab << "/* Curr Ripple Timer */ " << painting->rippleTimer << ",\n"; + write << fourSpaceTab << "/* Curr Ripple x, y */ " << painting->rippleX << ", " << painting->rippleY << ",\n"; + write << fourSpaceTab << "/* Normal DList */ " << nDLSymbol.str() << ",\n"; + write << fourSpaceTab << "/* Texture Maps */ " << tMapSymbol.str() << ",\n"; + write << fourSpaceTab << "/* Textures */ " << tArrSymbol.str() << ",\n"; + write << fourSpaceTab << "/* Texture w, h */ " << std::dec << painting->textureWidth << ", " << painting->textureHeight << ",\n"; + write << fourSpaceTab << "/* Ripple DList */ " << rDLSymbol.str() << ",\n"; + write << fourSpaceTab << "/* Ripple Trigger */ " << rippleTrigger.str() << ",\n"; + write << fourSpaceTab << "/* Alpha */ " << std::dec << (uint32_t)painting->alpha << ",\n"; + write << fourSpaceTab << "/* Mario Below */ " << std::hex << "0x" << (uint32_t)painting->marioWasUnder << ", " << std::hex << "0x" << (uint32_t)painting->marioIsUnder << ", " << std::hex << "0x" << (uint32_t)painting->marioWentUnder << ",\n"; + write << fourSpaceTab << "/* Size */ " << painting->size << ",\n"; + + write << "};\n"; + + return offset + 120; +} + +ExportResult SM64::PaintingBinaryExporter::Export(std::ostream &write, std::shared_ptr raw, std::string& entryName, YAML::Node &node, std::string* replacement ) { + auto writer = LUS::BinaryWriter(); + auto painting = std::static_pointer_cast(raw); + uint32_t ptr; + + WriteHeader(writer, LUS::ResourceType::Painting, 0); + + writer.Write(painting->id); + writer.Write(painting->imageCount); + writer.Write(painting->textureType); + writer.Write(painting->lastFloor); + writer.Write(painting->currFloor); + writer.Write(painting->floorEntered); + writer.Write(painting->state); + writer.Write(painting->pitch); + writer.Write(painting->yaw); + writer.Write(painting->posX); + writer.Write(painting->posY); + writer.Write(painting->posZ); + writer.Write(painting->currRippleMag); + writer.Write(painting->passiveRippleMag); + writer.Write(painting->entryRippleMag); + writer.Write(painting->rippleDecay); + writer.Write(painting->passiveRippleDecay); + writer.Write(painting->entryRippleDecay); + writer.Write(painting->currRippleRate); + writer.Write(painting->passiveRippleRate); + writer.Write(painting->entryRippleRate); + writer.Write(painting->dispersionFactor); + writer.Write(painting->passiveDispersionFactor); + writer.Write(painting->entryDispersionFactor); + writer.Write(painting->rippleTimer); + writer.Write(painting->rippleX); + writer.Write(painting->rippleY); + + ptr = painting->normalDisplayList; + { + auto dec = Companion::Instance->GetNodeByAddr(ptr); + if (dec.has_value()) { + uint64_t hash = CRC64(std::get<0>(dec.value()).c_str()); + SPDLOG_INFO("Found DisplayList: 0x{:X} Hash: 0x{:X} Path: {}", ptr, hash, std::get<0>(dec.value())); + writer.Write(hash); + } else { + SPDLOG_WARN("Could not find DisplayList at 0x{:X}", ptr); + } + } + + ptr = painting->textureMaps; + { + auto dec = Companion::Instance->GetNodeByAddr(ptr); + if (dec.has_value()) { + uint64_t hash = CRC64(std::get<0>(dec.value()).c_str()); + SPDLOG_INFO("Found Texture Maps: 0x{:X} Hash: 0x{:X} Path: {}", ptr, hash, std::get<0>(dec.value())); + writer.Write(hash); + } else { + SPDLOG_WARN("Could not find Texture Maps at 0x{:X}", ptr); + } + } + + ptr = painting->textureArray; + { + auto dec = Companion::Instance->GetNodeByAddr(ptr); + if (dec.has_value()) { + uint64_t hash = CRC64(std::get<0>(dec.value()).c_str()); + SPDLOG_INFO("Found Texture Arrays: 0x{:X} Hash: 0x{:X} Path: {}", ptr, hash, std::get<0>(dec.value())); + writer.Write(hash); + } else { + SPDLOG_WARN("Could not find Texture Arrays at 0x{:X}", ptr); + } + } + + writer.Write(painting->textureWidth); + writer.Write(painting->textureHeight); + + ptr = painting->rippleDisplayList; + { + auto dec = Companion::Instance->GetNodeByAddr(ptr); + if (dec.has_value()) { + uint64_t hash = CRC64(std::get<0>(dec.value()).c_str()); + SPDLOG_INFO("Found DisplayList: 0x{:X} Hash: 0x{:X} Path: {}", ptr, hash, std::get<0>(dec.value())); + writer.Write(hash); + } else { + SPDLOG_WARN("Could not find DisplayList at 0x{:X}", ptr); + } + } + + writer.Write(painting->rippleTrigger); + writer.Write(painting->alpha); + writer.Write(painting->marioWasUnder); + writer.Write(painting->marioIsUnder); + writer.Write(painting->marioWentUnder); + writer.Write(painting->size); + + writer.Finish(write); + return std::nullopt; +} + +std::optional> SM64::PaintingFactory::parse(std::vector& buffer, YAML::Node& node) { + auto [_, segment] = Decompressor::AutoDecode(node, buffer); + LUS::BinaryReader reader(segment.data, segment.size); + reader.SetEndianness(LUS::Endianness::Big); + + auto id = reader.ReadInt16(); + auto imageCount = reader.ReadInt8(); + auto textureType = reader.ReadInt8(); + auto lastFloor = reader.ReadInt8(); + auto currFloor = reader.ReadInt8(); + auto floorEntered = reader.ReadInt8(); + auto state = reader.ReadInt8(); + auto pitch = reader.ReadFloat(); + auto yaw = reader.ReadFloat(); + auto posX = reader.ReadFloat(); + auto posY = reader.ReadFloat(); + auto posZ = reader.ReadFloat(); + auto currRippleMag = reader.ReadFloat(); + auto passiveRippleMag = reader.ReadFloat(); + auto entryRippleMag = reader.ReadFloat(); + auto rippleDecay = reader.ReadFloat(); + auto passiveRippleDecay = reader.ReadFloat(); + auto entryRippleDecay = reader.ReadFloat(); + auto currRippleRate = reader.ReadFloat(); + auto passiveRippleRate = reader.ReadFloat(); + auto entryRippleRate = reader.ReadFloat(); + auto dispersionFactor = reader.ReadFloat(); + auto passiveDispersionFactor = reader.ReadFloat(); + auto entryDispersionFactor = reader.ReadFloat(); + auto rippleTimer = reader.ReadFloat(); + auto rippleX = reader.ReadFloat(); + auto rippleY = reader.ReadFloat(); + auto normalDisplayList = reader.ReadUInt32(); + auto textureMaps = reader.ReadUInt32(); + auto textureArray = reader.ReadUInt32(); + auto textureWidth = reader.ReadInt16(); + auto textureHeight = reader.ReadInt16(); + auto rippleDisplayList = reader.ReadUInt32(); + auto rippleTrigger = reader.ReadInt8(); + auto alpha = reader.ReadUByte(); + auto marioWasUnder = reader.ReadInt8(); + auto marioIsUnder = reader.ReadInt8(); + auto marioWentUnder = reader.ReadInt8(); + reader.ReadInt8(); // pad + reader.ReadInt8(); // pad + reader.ReadInt8(); // pad + auto size = reader.ReadFloat(); + + YAML::Node nDLNode; + nDLNode["type"] = "GFX"; + nDLNode["offset"] = normalDisplayList; + Companion::Instance->AddAsset(nDLNode); + + YAML::Node rDLNode; + rDLNode["type"] = "GFX"; + rDLNode["offset"] = rippleDisplayList; + Companion::Instance->AddAsset(rDLNode); + + return std::make_shared(id, imageCount, textureType, lastFloor, currFloor, floorEntered, state, pitch, yaw, posX, posY, posZ, currRippleMag, passiveRippleMag, entryRippleMag, rippleDecay, passiveRippleDecay, entryRippleDecay, currRippleRate, passiveRippleRate, entryRippleRate, dispersionFactor, passiveDispersionFactor, entryDispersionFactor, rippleTimer, rippleX, rippleY, normalDisplayList, textureMaps, textureArray, textureWidth, textureHeight, rippleDisplayList, rippleTrigger, alpha, marioWasUnder, marioIsUnder, marioWentUnder, size); +} diff --git a/src/factories/sm64/PaintingFactory.h b/src/factories/sm64/PaintingFactory.h new file mode 100644 index 0000000..8d0d6ad --- /dev/null +++ b/src/factories/sm64/PaintingFactory.h @@ -0,0 +1,153 @@ +// struct Painting ttm_slide_painting = { +// /* id */ 0x0000, +// /* Image Count */ 0x02, +// /* Texture Type */ PAINTING_IMAGE, +// /* Floor Status */ 0x00, 0x00, 0x00 /* which of the painting's nearby special floors Mario's on */, +// /* Ripple Status */ 0x00, +// /* Rotation */ 0.0f, 90.0f, +// /* Position */ 3072.0f, 921.6f, -819.2f, +// /* curr passive entry */ +// /* Ripple Magnitude */ 0.0f, 20.0f, 80.0f, +// /* Ripple Decay */ 1.0f, 0.9608f, 0.9524f, +// /* Ripple Rate */ 0.0f, 0.24f, 0.14f, +// /* Ripple Dispersion */ 0.0f, 40.0f, 30.0f, +// /* Curr Ripple Timer */ 0.0f, +// /* Curr Ripple x, y */ 0.0f, 0.0f, +// /* Normal DList */ ttm_seg7_painting_dl_07012E98, +// /* Texture Maps */ ttm_seg7_painting_texture_maps_07012E88, +// /* Textures */ ttm_seg7_painting_textures_07012EF8, +// /* Texture w, h */ 64, 32, +// /* Ripple DList */ ttm_seg7_painting_dl_07012430, +// /* Ripple Trigger */ RIPPLE_TRIGGER_PROXIMITY, +// /* Alpha */ 0xFF, +// /* Mario Below */ 0x00, 0x00, 0x00, /* Whether or not Mario is below the painting */ +// /* Size */ 460.8f, +// }; + +#pragma once + +#include "factories/BaseFactory.h" + +#define PAINTING_IMAGE 0 +#define PAINTING_ENV_MAP 1 + +#define RIPPLE_TRIGGER_PROXIMITY 10 +#define RIPPLE_TRIGGER_CONTINUOUS 20 + +namespace SM64 { + +class Painting : public IParsedData { +public: + int16_t id; + int8_t imageCount; + int8_t textureType; + int8_t lastFloor; + int8_t currFloor; + int8_t floorEntered; + int8_t state; + float pitch; + float yaw; + float posX; + float posY; + float posZ; + float currRippleMag; + float passiveRippleMag; + float entryRippleMag; + float rippleDecay; + float passiveRippleDecay; + float entryRippleDecay; + float currRippleRate; + float passiveRippleRate; + float entryRippleRate; + float dispersionFactor; + float passiveDispersionFactor; + float entryDispersionFactor; + float rippleTimer; + float rippleX; + float rippleY; + uint32_t normalDisplayList; + uint32_t textureMaps; + uint32_t textureArray; + int16_t textureWidth; + int16_t textureHeight; + uint32_t rippleDisplayList; + int8_t rippleTrigger; + uint8_t alpha; + int8_t marioWasUnder; + int8_t marioIsUnder; + int8_t marioWentUnder; + float size; + + Painting( + int16_t id, + int8_t imageCount, + int8_t textureType, + int8_t lastFloor, int8_t currFloor, int8_t floorEntered, + int8_t state, + float pitch, float yaw, + float posX, float posY, float posZ, + float currRippleMag, float passiveRippleMag, float entryRippleMag, + float rippleDecay, float passiveRippleDecay, float entryRippleDecay, + float currRippleRate, float passiveRippleRate, float entryRippleRate, + float dispersionFactor, float passiveDispersionFactor, float entryDispersionFactor, + float rippleTimer, + float rippleX, float rippleY, + uint32_t normalDisplayList, + uint32_t textureMaps, + uint32_t textureArray, + int16_t textureWidth, int16_t textureHeight, + uint32_t rippleDisplayList, + int8_t rippleTrigger, + uint8_t alpha, + int8_t marioWasUnder, int8_t marioIsUnder, int8_t marioWentUnder, + float size + ) : + id(id), + imageCount(imageCount), + textureType(textureType), + lastFloor(lastFloor), currFloor(currFloor), floorEntered(floorEntered), + state(state), + pitch(pitch), yaw(yaw), + posX(posX), posY(posY), posZ(posZ), + currRippleMag(currRippleMag), passiveRippleMag(passiveRippleMag), entryRippleMag(entryRippleMag), + rippleDecay(rippleDecay), passiveRippleDecay(passiveRippleDecay), entryRippleDecay(entryRippleDecay), + currRippleRate(currRippleRate), passiveRippleRate(passiveRippleRate), entryRippleRate(entryRippleRate), + dispersionFactor(dispersionFactor), passiveDispersionFactor(passiveDispersionFactor), entryDispersionFactor(entryDispersionFactor), + rippleTimer(rippleTimer), + rippleX(rippleX), rippleY(rippleY), + normalDisplayList(normalDisplayList), + textureMaps(textureMaps), + textureArray(textureArray), + textureWidth(textureWidth), textureHeight(textureHeight), + rippleDisplayList(rippleDisplayList), + rippleTrigger(rippleTrigger), + alpha(alpha), + marioWasUnder(marioWasUnder), marioIsUnder(marioIsUnder), marioWentUnder(marioWentUnder), + size(size) + {} +}; + +class PaintingHeaderExporter : public BaseExporter { + ExportResult Export(std::ostream& write, std::shared_ptr data, std::string& entryName, YAML::Node& node, std::string* replacement) override; +}; + +class PaintingBinaryExporter : public BaseExporter { + ExportResult Export(std::ostream& write, std::shared_ptr data, std::string& entryName, YAML::Node& node, std::string* replacement) override; +}; + +class PaintingCodeExporter : public BaseExporter { + ExportResult Export(std::ostream& write, std::shared_ptr data, std::string& entryName, YAML::Node& node, std::string* replacement) override; +}; + +class PaintingFactory : public BaseFactory { +public: + std::optional> parse(std::vector& buffer, YAML::Node& data) override; + inline std::unordered_map> GetExporters() override { + return { + REGISTER(Code, PaintingCodeExporter) + REGISTER(Header, PaintingHeaderExporter) + REGISTER(Binary, PaintingBinaryExporter) + }; + } +}; +} diff --git a/src/factories/sm64/WaterDropletFactory.cpp b/src/factories/sm64/WaterDropletFactory.cpp index ed34e64..ac3d6a2 100644 --- a/src/factories/sm64/WaterDropletFactory.cpp +++ b/src/factories/sm64/WaterDropletFactory.cpp @@ -109,9 +109,7 @@ ExportResult SM64::WaterDropletCodeExporter::Export(std::ostream &write, std::sh write << "};\n"; - size_t size = 0; - - return offset + size; + return offset + 36; } ExportResult SM64::WaterDropletBinaryExporter::Export(std::ostream &write, std::shared_ptr raw, std::string& entryName, YAML::Node &node, std::string* replacement ) { -- cgit v1.2.3