diff --git a/TemplateFactory.cpp b/TemplateFactory.cpp new file mode 100644 index 0000000..1d89a6f --- /dev/null +++ b/TemplateFactory.cpp @@ -0,0 +1,38 @@ +#include "TemplateFactory.h" +#include "spdlog/spdlog.h" + +#include "Companion.h" +#include "utils/Decompressor.h" +#include "utils/TorchUtils.h" + +TypeData::TypeData(uint32_t data): mData(data) { + +} + +void TypeHeaderExporter::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; + } + + write << "extern Type " << symbol << ";\n"; + // write << "extern Type " << symbol << "[];\n"; +} + +void TypeCodeExporter::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 data = std::static_pointer_cast(raw); + +} + +void TypeBinaryExporter::Export(std::ostream &write, std::shared_ptr raw, std::string& entryName, YAML::Node &node, std::string* replacement ) { + +} + +std::optional> TypeFactory::parse(std::vector& buffer, YAML::Node& node) { + + return std::make_shared(); +} diff --git a/TemplateFactory.h b/TemplateFactory.h new file mode 100644 index 0000000..34bb960 --- /dev/null +++ b/TemplateFactory.h @@ -0,0 +1,41 @@ +#pragma once + +#include "../BaseFactory.h" + +// namespace GAME { + +class TypeData : public IParsedData { +public: + uint32_t mData; + + explicit TypeData(uint32_t data) {} +}; + +class TypeHeaderExporter : public BaseExporter { + void Export(std::ostream& write, std::shared_ptr data, std::string& entryName, YAML::Node& node, std::string* replacement) override; +}; + +class TypeBinaryExporter : public BaseExporter { + void Export(std::ostream& write, std::shared_ptr data, std::string& entryName, YAML::Node& node, std::string* replacement) override; +}; + +class TypeCodeExporter : public BaseExporter { + void Export(std::ostream& write, std::shared_ptr data, std::string& entryName, YAML::Node& node, std::string* replacement) override; +}; + +class TypeFactory : public BaseFactory { +public: + std::optional> parse(std::vector& buffer, YAML::Node& data) override; + std::optional> parse_modding(std::vector& buffer, YAML::Node& data) override { + return std::nullopt; + } + inline std::unordered_map> GetExporters() override { + return { + REGISTER(Code, TypeCodeExporter) + REGISTER(Header, TypeHeaderExporter) + REGISTER(Binary, TypeBinaryExporter) + }; + } + bool SupportModdedAssets() override { return false; } +}; +// } diff --git a/src/Companion.cpp b/src/Companion.cpp index ea14184..9fda03e 100644 --- a/src/Companion.cpp +++ b/src/Companion.cpp @@ -2,8 +2,7 @@ #include "storm/SWrapper.h" #include "utils/Decompressor.h" -#include "factories/sf64/SkeletonFactory.h" -#include "factories/sf64/AnimFactory.h" + #include "factories/sm64/AnimationFactory.h" #include "factories/sm64/DialogFactory.h" #include "factories/sm64/DictionaryFactory.h" @@ -31,6 +30,9 @@ #include #include "factories/sf64/MessageFactory.h" #include "factories/sf64/MessageLookupFactory.h" +#include "factories/sf64/SkeletonFactory.h" +#include "factories/sf64/AnimFactory.h" +#include "factories/sf64/ScriptFactory.h" using namespace std::chrono; namespace fs = std::filesystem; @@ -72,6 +74,8 @@ void Companion::Init(const ExportType type) { this->RegisterFactory("SF64:SKELETON", std::make_shared()); this->RegisterFactory("SF64:MESSAGE", std::make_shared()); this->RegisterFactory("SF64:MSG_TABLE", std::make_shared()); + this->RegisterFactory("SF64:SCRIPT", std::make_shared()); + this->Process(); } diff --git a/src/factories/sf64/ScriptFactory.cpp b/src/factories/sf64/ScriptFactory.cpp new file mode 100644 index 0000000..1bf676c --- /dev/null +++ b/src/factories/sf64/ScriptFactory.cpp @@ -0,0 +1,113 @@ +#include "ScriptFactory.h" +#include "spdlog/spdlog.h" + +#include "Companion.h" +#include "utils/Decompressor.h" +#include "utils/TorchUtils.h" + +SF64::ScriptData::ScriptData(std::vector ptrs, std::vector cmds, std::map sizeMap, uint32_t ptrsStart, uint32_t cmdsStart): mPtrs(ptrs), mCmds(cmds), mSizeMap(sizeMap), mPtrsStart(ptrsStart), mCmdsStart(cmdsStart) { + +} + +void SF64::ScriptHeaderExporter::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; + } + + write << "extern u16* " << symbol << "[];\n"; +} + +std::string MakeScriptCmd(uint16_t s1, uint16_t s2) { + auto opcode = (s1 & 0xFE00) >> 9; + auto arg1 = s1 & 0x1FF; + std::ostringstream cmd; + + cmd << "EVENT_CMD(EVOP_" << std::left << std::setw(3) << std::dec << opcode << ", " << std::right << std::setw(3) << std::dec << arg1 << ", " << std::setw(5) << std::dec << s2 << ")"; + + return cmd.str(); +} + +void SF64::ScriptCodeExporter::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 script = std::static_pointer_cast(raw); + auto sortedPtrs = script->mPtrs; + std::sort(sortedPtrs.begin(), sortedPtrs.end()); + std::vector scriptNames; + auto cmdOff = script->mCmdsStart; + auto cmdIndex = 0; + + if(IS_SEGMENTED(cmdOff)) { + cmdOff = SEGMENT_OFFSET(cmdOff); + } + + for(int i = 0; i < sortedPtrs.size(); i++) { + std::ostringstream scriptDefaultName; + scriptDefaultName << symbol << "_cmds_" << std::uppercase << std::hex << cmdOff + 2 * cmdIndex; + write << "u16 " << scriptDefaultName.str() << "[] = {"; + + for(int j = 0; j < script->mSizeMap[sortedPtrs[i]] / 2; j++, cmdIndex+=2) { + if((j % 3) == 0) { + write << "\n" << fourSpaceTab; + } + write << MakeScriptCmd(script->mCmds[cmdIndex], script->mCmds[cmdIndex + 1]) << ", "; + } + scriptNames.push_back(scriptDefaultName.str()); + write << "\n};\n\n"; + } + write << "u16* " << symbol << "[] = {"; + for(int i = 0; i < script->mPtrs.size(); i++) { + if((i % 5) == 0) { + write << "\n" << fourSpaceTab; + } + write << scriptNames[i] << ", "; + } + write << "\n};\n\n"; + +} + +void SF64::ScriptBinaryExporter::Export(std::ostream &write, std::shared_ptr raw, std::string& entryName, YAML::Node &node, std::string* replacement ) { + +} + +std::optional> SF64::ScriptFactory::parse(std::vector& buffer, YAML::Node& node) { + const auto offset = GetSafeNode(node, "offset"); + auto ptrsStart = offset; + YAML::Node scriptNode; + std::vector scriptPtrs; + std::vector scriptCmds; + std::map sizeMap; + auto [_, segment] = Decompressor::AutoDecode(node, buffer, 0x1000); + LUS::BinaryReader reader(segment.data, segment.size); + reader.SetEndianness(LUS::Endianness::Big); + auto ptr = reader.ReadUInt32(); + + while(SEGMENT_NUMBER(ptr) == SEGMENT_NUMBER(offset)) { + scriptPtrs.push_back(ptr); + ptr = reader.ReadUInt32(); + } + + auto sortedPtrs = scriptPtrs; + std::sort(sortedPtrs.begin(), sortedPtrs.end()); + + auto cmdsStart = sortedPtrs[0]; + + for(int i = 0; i < sortedPtrs.size() - 1; i++) { + sizeMap[sortedPtrs[i]] = (sortedPtrs[i+1] - sortedPtrs[i]) / sizeof(uint16_t); + } + sizeMap[sortedPtrs[sortedPtrs.size() - 1]] = (ptrsStart - sortedPtrs[sortedPtrs.size() - 1]) / sizeof(uint16_t); + + auto scriptLen = (ptrsStart - cmdsStart) / sizeof(uint16_t); + + scriptNode["offset"] = cmdsStart; + auto [__, scriptSegment] = Decompressor::AutoDecode(scriptNode, buffer, scriptLen * sizeof(uint16_t)); + LUS::BinaryReader scriptReader(scriptSegment.data, scriptSegment.size); + scriptReader.SetEndianness(LUS::Endianness::Big); + for(int i = 0; i < scriptLen; i++) { + scriptCmds.push_back(scriptReader.ReadUInt16()); + } + return std::make_shared(scriptPtrs, scriptCmds, sizeMap, ptrsStart, cmdsStart); +} diff --git a/src/factories/sf64/ScriptFactory.h b/src/factories/sf64/ScriptFactory.h new file mode 100644 index 0000000..24eaf71 --- /dev/null +++ b/src/factories/sf64/ScriptFactory.h @@ -0,0 +1,45 @@ +#pragma once + +#include "../BaseFactory.h" + +namespace SF64 { + +class ScriptData : public IParsedData { +public: + std::vector mPtrs; + std::vector mCmds; + std::map mSizeMap; + uint32_t mCmdsStart; + uint32_t mPtrsStart; + + ScriptData(std::vector ptrs, std::vector cmds, std::map sizeMap, uint32_t ptrsStart, uint32_t cmdsStart); +}; + +class ScriptHeaderExporter : public BaseExporter { + void Export(std::ostream& write, std::shared_ptr data, std::string& entryName, YAML::Node& node, std::string* replacement) override; +}; + +class ScriptBinaryExporter : public BaseExporter { + void Export(std::ostream& write, std::shared_ptr data, std::string& entryName, YAML::Node& node, std::string* replacement) override; +}; + +class ScriptCodeExporter : public BaseExporter { + void Export(std::ostream& write, std::shared_ptr data, std::string& entryName, YAML::Node& node, std::string* replacement) override; +}; + +class ScriptFactory : public BaseFactory { +public: + std::optional> parse(std::vector& buffer, YAML::Node& data) override; + std::optional> parse_modding(std::vector& buffer, YAML::Node& data) override { + return std::nullopt; + } + inline std::unordered_map> GetExporters() override { + return { + REGISTER(Code, ScriptCodeExporter) + REGISTER(Header, ScriptHeaderExporter) + REGISTER(Binary, ScriptBinaryExporter) + }; + } + bool SupportModdedAssets() override { return false; } +}; +}