diff --git a/DataSpec/DNACommon/DNACommon.hpp b/DataSpec/DNACommon/DNACommon.hpp index 289a6cb75..c06e41fd3 100644 --- a/DataSpec/DNACommon/DNACommon.hpp +++ b/DataSpec/DNACommon/DNACommon.hpp @@ -2,7 +2,7 @@ #define __DNA_COMMON_HPP__ #include -#include +#include #include #include "HECL/HECL.hpp" #include "HECL/Database.hpp" @@ -14,9 +14,10 @@ extern LogVisor::LogModule LogDNACommon; /* This comes up a great deal */ typedef Athena::io::DNA BigDNA; +typedef Athena::io::DNAYaml BigYAML; /* FourCC with DNA read/write */ -class FourCC final : public BigDNA, public HECL::FourCC +class FourCC final : public BigYAML, public HECL::FourCC { public: FourCC() : HECL::FourCC() {} @@ -30,10 +31,14 @@ public: {reader.readUBytesToBuf(fcc, 4);} inline void write(Athena::io::IStreamWriter& writer) const {writer.writeUBytes((atUint8*)fcc, 4);} + inline void fromYAML(Athena::io::YAMLDocReader& reader) + {std::string rs = reader.readString(nullptr); strncpy(fcc, rs.c_str(), 4);} + inline void toYAML(Athena::io::YAMLDocWriter& writer) const + {writer.writeString(nullptr, std::string(fcc, 4));} }; /* PAK 32-bit Unique ID */ -class UniqueID32 : public BigDNA +class UniqueID32 : public BigYAML { uint32_t m_id; public: @@ -42,6 +47,10 @@ public: {m_id = reader.readUint32();} inline void write(Athena::io::IStreamWriter& writer) const {writer.writeUint32(m_id);} + inline void fromYAML(Athena::io::YAMLDocReader& reader) + {m_id = reader.readUint32(nullptr);} + inline void toYAML(Athena::io::YAMLDocWriter& writer) const + {writer.writeUint32(nullptr, m_id);} inline bool operator!=(const UniqueID32& other) const {return m_id != other.m_id;} inline bool operator==(const UniqueID32& other) const {return m_id == other.m_id;} diff --git a/DataSpec/DNAMP1/DNAMP1.cpp b/DataSpec/DNAMP1/DNAMP1.cpp index 3a586cbfc..467f57a14 100644 --- a/DataSpec/DNAMP1/DNAMP1.cpp +++ b/DataSpec/DNAMP1/DNAMP1.cpp @@ -50,7 +50,7 @@ ResExtractor PAKBridge::LookupExtractor(const PAK::Entry& entry) switch (entry.type.toUint32()) { case SBIG('STRG'): - return {STRG::Extract, ".as"}; + return {STRG::Extract, ".yaml"}; case SBIG('TXTR'): return {TXTR::Extract, ".png"}; case SBIG('CMDL'): diff --git a/DataSpec/DNAMP1/MLVL.hpp b/DataSpec/DNAMP1/MLVL.hpp index 84c74699e..8832c85f6 100644 --- a/DataSpec/DNAMP1/MLVL.hpp +++ b/DataSpec/DNAMP1/MLVL.hpp @@ -8,9 +8,9 @@ namespace Retro namespace DNAMP1 { -struct MLVL : BigDNA +struct MLVL : BigYAML { - DECL_DNA + DECL_YAML Value magic; Value version; UniqueID32 worldNameId; @@ -18,9 +18,9 @@ struct MLVL : BigDNA UniqueID32 worldSkyboxId; Value memRelayLinkCount; - struct MemRelayLink : BigDNA + struct MemRelayLink : BigYAML { - DECL_DNA + DECL_YAML Value memRelayId; Value targetId; Value msg; @@ -30,9 +30,9 @@ struct MLVL : BigDNA Value areaCount; Value unknown1; - struct Area : BigDNA + struct Area : BigYAML { - DECL_DNA + DECL_YAML UniqueID32 areaNameId; Value transformMtx[3]; Value aabb[2]; @@ -44,9 +44,9 @@ struct MLVL : BigDNA Value padding; Value depCount; - struct Dependency : BigDNA + struct Dependency : BigYAML { - DECL_DNA + DECL_YAML UniqueID32 id; FourCC type; }; @@ -56,13 +56,13 @@ struct MLVL : BigDNA Vector depLayers; Value dockCount; - struct Dock : BigDNA + struct Dock : BigYAML { - DECL_DNA + DECL_YAML Value endpointCount; - struct Endpoint : BigDNA + struct Endpoint : BigYAML { - DECL_DNA + DECL_YAML Value areaIdx; Value dockIdx; }; @@ -80,9 +80,9 @@ struct MLVL : BigDNA Value unknown3; Value audioGroupCount; - struct AudioGroup : BigDNA + struct AudioGroup : BigYAML { - DECL_DNA + DECL_YAML Value unknown; UniqueID32 agscId; }; @@ -90,9 +90,9 @@ struct MLVL : BigDNA String<-1> unkString; Value layerFlagCount; - struct LayerFlags : BigDNA + struct LayerFlags : BigYAML { - DECL_DNA + DECL_YAML Value layerCount; Value flags; }; diff --git a/DataSpec/DNAMP1/STRG.cpp b/DataSpec/DNAMP1/STRG.cpp index 8aad7c375..be516bc3a 100644 --- a/DataSpec/DNAMP1/STRG.cpp +++ b/DataSpec/DNAMP1/STRG.cpp @@ -111,6 +111,69 @@ void STRG::write(Athena::io::IStreamWriter& writer) const } } +void STRG::fromYAML(Athena::io::YAMLDocReader& reader) +{ + std::wstring_convert> wconv; + const Athena::io::YAMLNode* root = reader.getRootNode(); + + /* Validate Pass */ + if (root->m_type == YAML_MAPPING_NODE) + { + for (const auto& lang : root->m_mapChildren) + { + if (lang.first.size() != 4) + { + Log.report(LogVisor::Warning, "STRG language string '%s' must be exactly 4 characters; skipping", lang.first.c_str()); + return; + } + if (lang.second->m_type != YAML_SEQUENCE_NODE) + { + Log.report(LogVisor::Warning, "STRG language string '%s' must contain a sequence; skipping", lang.first.c_str()); + return; + } + for (const auto& str : lang.second->m_seqChildren) + { + if (str->m_type != YAML_SCALAR_NODE) + { + Log.report(LogVisor::Warning, "STRG language '%s' must contain all scalars; skipping", lang.first.c_str()); + return; + } + } + } + } + else + { + Log.report(LogVisor::Warning, "STRG must have a mapping root node; skipping"); + return; + } + + /* Read Pass */ + langs.clear(); + for (const auto& lang : root->m_mapChildren) + { + std::vector strs; + for (const auto& str : lang.second->m_seqChildren) + strs.emplace_back(wconv.from_bytes(str->m_scalarString)); + langs.emplace_back(FourCC(lang.first.c_str()), strs); + } + + langMap.clear(); + langMap.reserve(langs.size()); + for (std::pair>& item : langs) + langMap.emplace(item.first, &item.second); +} + +void STRG::toYAML(Athena::io::YAMLDocWriter& writer) const +{ + for (const std::pair>& lang : langs) + { + writer.enterSubVector(lang.first.toString().c_str()); + for (const std::wstring& str : lang.second) + writer.writeWString(nullptr, str); + writer.leaveSubVector(); + } +} + bool STRG::readAngelScript(const AngelScript::asIScriptModule& in) { std::wstring_convert> wconv; diff --git a/DataSpec/DNAMP1/STRG.hpp b/DataSpec/DNAMP1/STRG.hpp index 9d6ee0c96..1bc98058c 100644 --- a/DataSpec/DNAMP1/STRG.hpp +++ b/DataSpec/DNAMP1/STRG.hpp @@ -10,9 +10,10 @@ namespace Retro namespace DNAMP1 { -struct STRG : ISTRG, BigDNA +struct STRG : ISTRG, BigYAML { DECL_EXPLICIT_DNA + DECL_EXPLICIT_YAML void _read(Athena::io::IStreamReader& reader); std::vector>> langs; std::unordered_map*> langMap; @@ -63,18 +64,18 @@ struct STRG : ISTRG, BigDNA { STRG strg; strg.read(rs); - std::ofstream strgOut(outPath.getAbsolutePath()); - strg.writeAngelScript(strgOut); + FILE* fp = HECL::Fopen(outPath.getAbsolutePath().c_str(), _S("w")); + strg.toYAMLFile(fp); + fclose(fp); return true; } static bool Cook(const HECL::ProjectPath& inPath, const HECL::ProjectPath& outPath) { STRG strg; - HECL::Database::ASUniqueModule mod = HECL::Database::ASUniqueModule::CreateFromPath(inPath); - if (!mod) - return false; - strg.readAngelScript(mod); + FILE* fp = HECL::Fopen(inPath.getAbsolutePath().c_str(), _S("r")); + strg.fromYAMLFile(fp); + fclose(fp); Athena::io::FileWriter ws(outPath.getAbsolutePath()); strg.write(ws); return true;