From b5d96f70409751689253d869bfa27909147da83c Mon Sep 17 00:00:00 2001 From: Jack Andersen Date: Thu, 13 Aug 2015 17:00:51 -1000 Subject: [PATCH] ANIM fixes and explicit-endian refactor --- DataSpec/DNACommon/ANCS.hpp | 2 +- DataSpec/DNACommon/CMDL.hpp | 12 +- DataSpec/DNACommon/DNACommon.hpp | 18 +- DataSpec/DNACommon/STRG.cpp | 5 +- DataSpec/DNACommon/TXTR.cpp | 9 +- DataSpec/DNAMP1/ANCS.cpp | 162 +++++++------- DataSpec/DNAMP1/ANCS.hpp | 25 ++- DataSpec/DNAMP1/ANIM.cpp | 24 +- DataSpec/DNAMP1/ANIM.hpp | 46 ++-- DataSpec/DNAMP1/CMDLMaterials.hpp | 30 ++- DataSpec/DNAMP1/PAK.cpp | 18 +- DataSpec/DNAMP1/STRG.cpp | 28 ++- DataSpec/DNAMP2/ANCS.hpp | 87 ++++++++ DataSpec/DNAMP2/ANIM.cpp | 352 ++++++++++++++++++++++++++++++ DataSpec/DNAMP2/ANIM.hpp | 174 +++++++++++++++ DataSpec/DNAMP2/CMakeLists.txt | 3 + DataSpec/DNAMP2/DNAMP2.cpp | 5 +- DataSpec/DNAMP2/STRG.cpp | 40 ++-- DataSpec/DNAMP3/PAK.cpp | 20 +- DataSpec/DNAMP3/STRG.cpp | 44 ++-- 20 files changed, 858 insertions(+), 246 deletions(-) create mode 100644 DataSpec/DNAMP2/ANCS.hpp create mode 100644 DataSpec/DNAMP2/ANIM.cpp create mode 100644 DataSpec/DNAMP2/ANIM.hpp diff --git a/DataSpec/DNACommon/ANCS.hpp b/DataSpec/DNACommon/ANCS.hpp index 20ff8c316..aeab1e108 100644 --- a/DataSpec/DNACommon/ANCS.hpp +++ b/DataSpec/DNACommon/ANCS.hpp @@ -58,7 +58,7 @@ bool ReadANCSToBlender(HECL::BlenderConnection& conn, } /* Establish ANCS blend */ - if (!conn.createBlend(outPath.getAbsolutePath() + ".blend")) + if (!conn.createBlend(outPath.getAbsolutePath())) return false; HECL::BlenderConnection::PyOutStream os = conn.beginPythonOut(true); diff --git a/DataSpec/DNACommon/CMDL.hpp b/DataSpec/DNACommon/CMDL.hpp index 69e77e7a0..c042f9bc6 100644 --- a/DataSpec/DNACommon/CMDL.hpp +++ b/DataSpec/DNACommon/CMDL.hpp @@ -301,8 +301,6 @@ bool ReadCMDLToBlender(HECL::BlenderConnection& conn, const HECL::ProjectPath& masterShader, const RIGPAIR* rp=nullptr) { - reader.setEndian(Athena::BigEndian); - Header head; head.read(reader); @@ -523,7 +521,7 @@ bool ReadCMDLToBlender(HECL::BlenderConnection& conn, /* Positions */ for (size_t i=0 ; i<=maxIdxs.pos ; ++i) { - atVec3f pos = reader.readVec3f(); + atVec3f pos = reader.readVec3fBig(); os.format("vert = bm.verts.new((%f,%f,%f))\n", pos.vec[0], pos.vec[1], pos.vec[2]); if (rp) @@ -541,7 +539,7 @@ bool ReadCMDLToBlender(HECL::BlenderConnection& conn, for (size_t i=0 ; i LoadSTRG(Athena::io::IStreamReader& reader) { - reader.setEndian(Athena::BigEndian); - uint32_t magic = reader.readUint32(); + uint32_t magic = reader.readUint32Big(); if (magic != 0x87654321) { LogDNACommon.report(LogVisor::Error, "invalid STRG magic"); return std::unique_ptr(); } - uint32_t version = reader.readUint32(); + uint32_t version = reader.readUint32Big(); switch (version) { case 0: diff --git a/DataSpec/DNACommon/TXTR.cpp b/DataSpec/DNACommon/TXTR.cpp index d63e6606c..2ddf9fc47 100644 --- a/DataSpec/DNACommon/TXTR.cpp +++ b/DataSpec/DNACommon/TXTR.cpp @@ -481,11 +481,10 @@ static void PNGWarn(png_structp png, png_const_charp msg) bool TXTR::Extract(const SpecBase& dataspec, PAKEntryReadStream& rs, const HECL::ProjectPath& outPath) { - rs.setEndian(Athena::BigEndian); - uint32_t format = rs.readUint32(); - uint16_t width = rs.readUint16(); - uint16_t height = rs.readUint16(); - uint32_t numMips = rs.readUint32(); + uint32_t format = rs.readUint32Big(); + uint16_t width = rs.readUint16Big(); + uint16_t height = rs.readUint16Big(); + uint32_t numMips = rs.readUint32Big(); FILE* fp = HECL::Fopen(outPath.getAbsolutePath().c_str(), _S("wb")); if (!fp) diff --git a/DataSpec/DNAMP1/ANCS.cpp b/DataSpec/DNAMP1/ANCS.cpp index ebdc08136..31d258ed3 100644 --- a/DataSpec/DNAMP1/ANCS.cpp +++ b/DataSpec/DNAMP1/ANCS.cpp @@ -7,23 +7,23 @@ namespace DNAMP1 void ANCS::CharacterSet::CharacterInfo::PASDatabase::AnimState::ParmInfo::read(Athena::io::IStreamReader& reader) { - parmType = reader.readUint32(); - unk1 = reader.readUint32(); - unk2 = reader.readFloat(); + parmType = reader.readUint32Big(); + unk1 = reader.readUint32Big(); + unk2 = reader.readFloatBig(); switch (DataType(parmType)) { case DataType::DTInt32: - parmVals[0].int32 = reader.readInt32(); - parmVals[1].int32 = reader.readInt32(); + parmVals[0].int32 = reader.readInt32Big(); + parmVals[1].int32 = reader.readInt32Big(); break; case DataType::DTUInt32: case DataType::DTEnum: - parmVals[0].uint32 = reader.readUint32(); - parmVals[1].uint32 = reader.readUint32(); + parmVals[0].uint32 = reader.readUint32Big(); + parmVals[1].uint32 = reader.readUint32Big(); break; case DataType::DTFloat: - parmVals[0].float32 = reader.readFloat(); - parmVals[1].float32 = reader.readFloat(); + parmVals[0].float32 = reader.readFloatBig(); + parmVals[1].float32 = reader.readFloatBig(); break; case DataType::DTBool: parmVals[0].bool1 = reader.readBool(); @@ -34,23 +34,23 @@ void ANCS::CharacterSet::CharacterInfo::PASDatabase::AnimState::ParmInfo::read(A void ANCS::CharacterSet::CharacterInfo::PASDatabase::AnimState::ParmInfo::write(Athena::io::IStreamWriter& writer) const { - writer.writeUint32(parmType); - writer.writeUint32(unk1); - writer.writeFloat(unk2); + writer.writeUint32Big(parmType); + writer.writeUint32Big(unk1); + writer.writeFloatBig(unk2); switch (DataType(parmType)) { case DataType::DTInt32: - writer.writeInt32(parmVals[0].int32); - writer.writeInt32(parmVals[1].int32); + writer.writeInt32Big(parmVals[0].int32); + writer.writeInt32Big(parmVals[1].int32); break; case DataType::DTUInt32: case DataType::DTEnum: - writer.writeUint32(parmVals[0].uint32); - writer.writeUint32(parmVals[0].uint32); + writer.writeUint32Big(parmVals[0].uint32); + writer.writeUint32Big(parmVals[0].uint32); break; case DataType::DTFloat: - writer.writeFloat(parmVals[0].float32); - writer.writeFloat(parmVals[0].float32); + writer.writeFloatBig(parmVals[0].float32); + writer.writeFloatBig(parmVals[0].float32); break; case DataType::DTBool: writer.writeBool(parmVals[0].bool1); @@ -120,9 +120,9 @@ void ANCS::CharacterSet::CharacterInfo::PASDatabase::AnimState::ParmInfo::toYAML void ANCS::CharacterSet::CharacterInfo::PASDatabase::AnimState::read(Athena::io::IStreamReader& reader) { - id = reader.readUint32(); - atUint32 parmInfoCount = reader.readUint32(); - atUint32 animInfoCount = reader.readUint32(); + id = reader.readUint32Big(); + atUint32 parmInfoCount = reader.readUint32Big(); + atUint32 animInfoCount = reader.readUint32Big(); reader.enumerate(parmInfos, parmInfoCount); @@ -131,21 +131,21 @@ void ANCS::CharacterSet::CharacterInfo::PASDatabase::AnimState::read(Athena::io: reader.enumerate(animInfos, animInfoCount, [this, parmInfoCount](Athena::io::IStreamReader& reader, AnimInfo& ai) { - ai.id = reader.readUint32(); + ai.id = reader.readUint32Big(); ai.parmVals.reserve(parmInfoCount); for (const ParmInfo& pi : parmInfos) { switch (ParmInfo::DataType(pi.parmType)) { case ParmInfo::DTInt32: - ai.parmVals.emplace_back(reader.readInt32()); + ai.parmVals.emplace_back(reader.readInt32Big()); break; case ParmInfo::DTUInt32: case ParmInfo::DTEnum: - ai.parmVals.emplace_back(reader.readUint32()); + ai.parmVals.emplace_back(reader.readUint32Big()); break; case ParmInfo::DTFloat: - ai.parmVals.emplace_back(reader.readFloat()); + ai.parmVals.emplace_back(reader.readFloatBig()); break; case ParmInfo::DTBool: ai.parmVals.emplace_back(reader.readBool()); @@ -158,16 +158,16 @@ void ANCS::CharacterSet::CharacterInfo::PASDatabase::AnimState::read(Athena::io: void ANCS::CharacterSet::CharacterInfo::PASDatabase::AnimState::write(Athena::io::IStreamWriter& writer) const { - writer.writeUint32(id); - writer.writeUint32(parmInfos.size()); - writer.writeUint32(animInfos.size()); + writer.writeUint32Big(id); + writer.writeUint32Big(parmInfos.size()); + writer.writeUint32Big(animInfos.size()); for (const ParmInfo& pi : parmInfos) pi.write(writer); for (const AnimInfo& ai : animInfos) { - writer.writeUint32(ai.id); + writer.writeUint32Big(ai.id); auto it = ai.parmVals.begin(); for (const ParmInfo& pi : parmInfos) { @@ -177,14 +177,14 @@ void ANCS::CharacterSet::CharacterInfo::PASDatabase::AnimState::write(Athena::io switch (ParmInfo::DataType(pi.parmType)) { case ParmInfo::DTInt32: - writer.writeInt32(pVal.int32); + writer.writeInt32Big(pVal.int32); break; case ParmInfo::DTUInt32: case ParmInfo::DTEnum: - writer.writeUint32(pVal.uint32); + writer.writeUint32Big(pVal.uint32); break; case ParmInfo::DTFloat: - writer.writeFloat(pVal.float32); + writer.writeFloatBig(pVal.float32); break; case ParmInfo::DTBool: writer.writeBool(pVal.bool1); @@ -276,52 +276,52 @@ void ANCS::CharacterSet::CharacterInfo::PASDatabase::AnimState::toYAML(Athena::i void ANCS::CharacterSet::CharacterInfo::read(Athena::io::IStreamReader& reader) { - idx = reader.readUint32(); - atUint16 sectionCount = reader.readUint16(); + idx = reader.readUint32Big(); + atUint16 sectionCount = reader.readUint16Big(); name = reader.readString(); cmdl.read(reader); cskr.read(reader); cinf.read(reader); - atUint32 animationCount = reader.readUint32(); + atUint32 animationCount = reader.readUint32Big(); reader.enumerate(animations, animationCount); pasDatabase.read(reader); - atUint32 partCount = reader.readUint32(); + atUint32 partCount = reader.readUint32Big(); reader.enumerate(partResData.part, partCount); - atUint32 swhcCount = reader.readUint32(); + atUint32 swhcCount = reader.readUint32Big(); reader.enumerate(partResData.swhc, swhcCount); - atUint32 unkCount = reader.readUint32(); + atUint32 unkCount = reader.readUint32Big(); reader.enumerate(partResData.unk, unkCount); partResData.elsc.clear(); if (sectionCount > 5) { - atUint32 elscCount = reader.readUint32(); + atUint32 elscCount = reader.readUint32Big(); reader.enumerate(partResData.elsc, elscCount); } - unk1 = reader.readUint32(); + unk1 = reader.readUint32Big(); if (sectionCount > 9) { - unk2 = reader.readUint32(); - unk3 = reader.readUint32(); + unk2 = reader.readUint32Big(); + unk3 = reader.readUint32Big(); } animAABBs.clear(); if (sectionCount > 1) { - atUint32 aabbCount = reader.readUint32(); + atUint32 aabbCount = reader.readUint32Big(); reader.enumerate(animAABBs, aabbCount); } effects.clear(); if (sectionCount > 2) { - atUint32 effectCount = reader.readUint32(); + atUint32 effectCount = reader.readUint32Big(); reader.enumerate(effects, effectCount); } @@ -334,14 +334,14 @@ void ANCS::CharacterSet::CharacterInfo::read(Athena::io::IStreamReader& reader) animIdxs.clear(); if (sectionCount > 4) { - atUint32 aidxCount = reader.readUint32(); - reader.enumerate(animIdxs, aidxCount); + atUint32 aidxCount = reader.readUint32Big(); + reader.enumerateBig(animIdxs, aidxCount); } } void ANCS::CharacterSet::CharacterInfo::write(Athena::io::IStreamWriter& writer) const { - writer.writeUint32(idx); + writer.writeUint32Big(idx); atUint16 sectionCount; if (unk2 || unk3) @@ -358,49 +358,49 @@ void ANCS::CharacterSet::CharacterInfo::write(Athena::io::IStreamWriter& writer) sectionCount = 2; else sectionCount = 1; - writer.writeUint16(sectionCount); + writer.writeUint16Big(sectionCount); writer.writeString(name); cmdl.write(writer); cskr.write(writer); cinf.write(writer); - writer.writeUint32(animations.size()); + writer.writeUint32Big(animations.size()); writer.enumerate(animations); pasDatabase.write(writer); - writer.writeUint32(partResData.part.size()); + writer.writeUint32Big(partResData.part.size()); writer.enumerate(partResData.part); - writer.writeUint32(partResData.swhc.size()); + writer.writeUint32Big(partResData.swhc.size()); writer.enumerate(partResData.swhc); - writer.writeUint32(partResData.unk.size()); + writer.writeUint32Big(partResData.unk.size()); writer.enumerate(partResData.unk); if (sectionCount > 5) { - writer.writeUint32(partResData.elsc.size()); + writer.writeUint32Big(partResData.elsc.size()); writer.enumerate(partResData.elsc); } - writer.writeUint32(unk1); + writer.writeUint32Big(unk1); if (sectionCount > 9) { - writer.writeUint32(unk2); - writer.writeUint32(unk3); + writer.writeUint32Big(unk2); + writer.writeUint32Big(unk3); } if (sectionCount > 1) { - writer.writeUint32(animAABBs.size()); + writer.writeUint32Big(animAABBs.size()); writer.enumerate(animAABBs); } if (sectionCount > 2) { - writer.writeUint32(effects.size()); + writer.writeUint32Big(effects.size()); writer.enumerate(effects); } @@ -412,9 +412,9 @@ void ANCS::CharacterSet::CharacterInfo::write(Athena::io::IStreamWriter& writer) if (sectionCount > 4) { - writer.writeUint32(animIdxs.size()); + writer.writeUint32Big(animIdxs.size()); for (atUint32 idx : animIdxs) - writer.writeUint32(idx); + writer.writeUint32Big(idx); } } @@ -563,7 +563,7 @@ void ANCS::CharacterSet::CharacterInfo::toYAML(Athena::io::YAMLDocWriter& writer void ANCS::AnimationSet::MetaAnimFactory::read(Athena::io::IStreamReader& reader) { - IMetaAnim::Type type(IMetaAnim::Type(reader.readUint32())); + IMetaAnim::Type type(IMetaAnim::Type(reader.readUint32Big())); switch (type) { case IMetaAnim::MAPrimitive: @@ -596,7 +596,7 @@ void ANCS::AnimationSet::MetaAnimFactory::write(Athena::io::IStreamWriter& write { if (!m_anim) return; - writer.writeInt32(m_anim->m_type); + writer.writeInt32Big(m_anim->m_type); m_anim->write(writer); } @@ -646,7 +646,7 @@ void ANCS::AnimationSet::MetaAnimFactory::toYAML(Athena::io::YAMLDocWriter& writ void ANCS::AnimationSet::MetaTransFactory::read(Athena::io::IStreamReader& reader) { - IMetaTrans::Type type(IMetaTrans::Type(reader.readUint32())); + IMetaTrans::Type type(IMetaTrans::Type(reader.readUint32Big())); switch (type) { case IMetaTrans::MTMetaAnim: @@ -672,10 +672,10 @@ void ANCS::AnimationSet::MetaTransFactory::write(Athena::io::IStreamWriter& writ { if (!m_trans) { - writer.writeInt32(IMetaTrans::MTNoTrans); + writer.writeInt32Big(IMetaTrans::MTNoTrans); return; } - writer.writeInt32(m_trans->m_type); + writer.writeInt32Big(m_trans->m_type); m_trans->write(writer); } @@ -718,35 +718,35 @@ void ANCS::AnimationSet::MetaTransFactory::toYAML(Athena::io::YAMLDocWriter& wri void ANCS::AnimationSet::read(Athena::io::IStreamReader& reader) { - atUint16 sectionCount = reader.readUint16(); + atUint16 sectionCount = reader.readUint16Big(); - atUint32 animationCount = reader.readUint32(); + atUint32 animationCount = reader.readUint32Big(); reader.enumerate(animations, animationCount); - atUint32 transitionCount = reader.readUint32(); + atUint32 transitionCount = reader.readUint32Big(); reader.enumerate(transitions, transitionCount); defaultTransition.read(reader); additiveAnims.clear(); if (sectionCount > 1) { - atUint32 additiveAnimCount = reader.readUint32(); + atUint32 additiveAnimCount = reader.readUint32Big(); reader.enumerate(additiveAnims, additiveAnimCount); - floatA = reader.readFloat(); - floatB = reader.readFloat(); + floatA = reader.readFloatBig(); + floatB = reader.readFloatBig(); } halfTransitions.clear(); if (sectionCount > 2) { - atUint32 halfTransitionCount = reader.readUint32(); + atUint32 halfTransitionCount = reader.readUint32Big(); reader.enumerate(halfTransitions, halfTransitionCount); } animResources.clear(); if (sectionCount > 3) { - atUint32 animResourcesCount = reader.readUint32(); + atUint32 animResourcesCount = reader.readUint32Big(); reader.enumerate(animResources, animResourcesCount); } } @@ -763,32 +763,32 @@ void ANCS::AnimationSet::write(Athena::io::IStreamWriter& writer) const else sectionCount = 1; - writer.writeUint16(sectionCount); + writer.writeUint16Big(sectionCount); - writer.writeUint32(animations.size()); + writer.writeUint32Big(animations.size()); writer.enumerate(animations); - writer.writeUint32(transitions.size()); + writer.writeUint32Big(transitions.size()); writer.enumerate(transitions); defaultTransition.write(writer); if (sectionCount > 1) { - writer.writeUint32(additiveAnims.size()); + writer.writeUint32Big(additiveAnims.size()); writer.enumerate(additiveAnims); - writer.writeFloat(floatA); - writer.writeFloat(floatB); + writer.writeFloatBig(floatA); + writer.writeFloatBig(floatB); } if (sectionCount > 2) { - writer.writeUint32(halfTransitions.size()); + writer.writeUint32Big(halfTransitions.size()); writer.enumerate(halfTransitions); } if (sectionCount > 3) { - writer.writeUint32(animResources.size()); + writer.writeUint32Big(animResources.size()); writer.enumerate(animResources); } } diff --git a/DataSpec/DNAMP1/ANCS.hpp b/DataSpec/DNAMP1/ANCS.hpp index 28983bdec..7ab6a5974 100644 --- a/DataSpec/DNAMP1/ANCS.hpp +++ b/DataSpec/DNAMP1/ANCS.hpp @@ -382,14 +382,25 @@ struct ANCS : BigYAML { ANCS ancs; ancs.read(rs); - FILE* fp = HECL::Fopen((outPath.getAbsolutePath() + ".yaml").c_str(), _S("wb")); - ancs.toYAMLFile(fp); - fclose(fp); - HECL::BlenderConnection& conn = HECL::BlenderConnection::SharedConnection(); - DNAANCS::ReadANCSToBlender, ANCS, MaterialSet, 2> - (conn, ancs, outPath, pakRouter, entry, dataSpec.getMasterShaderPath(), force); - return conn.saveBlend(); + HECL::ProjectPath yamlPath = outPath.getWithExtension(_S(".yaml")); + if (force || yamlPath.getPathType() == HECL::ProjectPath::PT_NONE) + { + FILE* fp = HECL::Fopen(yamlPath.getAbsolutePath().c_str(), _S("wb")); + ancs.toYAMLFile(fp); + fclose(fp); + } + + HECL::ProjectPath blendPath = outPath.getWithExtension(_S(".blend")); + if (force || blendPath.getPathType() == HECL::ProjectPath::PT_NONE) + { + HECL::BlenderConnection& conn = HECL::BlenderConnection::SharedConnection(); + DNAANCS::ReadANCSToBlender, ANCS, MaterialSet, 2> + (conn, ancs, blendPath, pakRouter, entry, dataSpec.getMasterShaderPath(), force); + return conn.saveBlend(); + } + + return true; } }; diff --git a/DataSpec/DNAMP1/ANIM.cpp b/DataSpec/DNAMP1/ANIM.cpp index b0e36df93..d29414422 100644 --- a/DataSpec/DNAMP1/ANIM.cpp +++ b/DataSpec/DNAMP1/ANIM.cpp @@ -89,7 +89,7 @@ void ANIM::ANIM0::read(Athena::io::IStreamReader& reader) boneMap[idx] = b; } - atUint32 boneCount = reader.readUint32(); + atUint32 boneCount = reader.readUint32Big(); bones.clear(); bones.reserve(boneCount); channels.clear(); @@ -109,7 +109,7 @@ void ANIM::ANIM0::read(Athena::io::IStreamReader& reader) } } - reader.readUint32(); + reader.readUint32Big(); chanKeys.clear(); chanKeys.reserve(channels.size()); for (const std::pair& bone : bones) @@ -117,13 +117,13 @@ void ANIM::ANIM0::read(Athena::io::IStreamReader& reader) chanKeys.emplace_back(); std::vector& keys = chanKeys.back(); for (size_t k=0 ; k& bone : bones) { @@ -132,7 +132,7 @@ void ANIM::ANIM0::read(Athena::io::IStreamReader& reader) { std::vector& keys = *kit++; for (size_t k=0 ; k& bone : bones) { @@ -184,7 +184,7 @@ void ANIM::ANIM0::write(Athena::io::IStreamWriter& writer) const ++boneIdx; } - writer.writeUint32(bones.size() * head.keyCount); + writer.writeUint32Big(bones.size() * head.keyCount); auto cit = chanKeys.begin(); atUint32 transKeyCount = 0; for (const std::pair& bone : bones) @@ -192,7 +192,7 @@ void ANIM::ANIM0::write(Athena::io::IStreamWriter& writer) const const std::vector& keys = *cit++; auto kit = keys.begin(); for (size_t k=0 ; k& bone : bones) { @@ -210,7 +210,7 @@ void ANIM::ANIM0::write(Athena::io::IStreamWriter& writer) const const std::vector& keys = *cit++; auto kit = keys.begin(); for (size_t k=0 ; k& bone : bones) { diff --git a/DataSpec/DNAMP1/ANIM.hpp b/DataSpec/DNAMP1/ANIM.hpp index f0157ebdc..8040f3a7a 100644 --- a/DataSpec/DNAMP1/ANIM.hpp +++ b/DataSpec/DNAMP1/ANIM.hpp @@ -43,9 +43,9 @@ struct ANIM : BigDNA Value unk0; Value interval; Value unk1; - Value boneSlotCount; - Value unk2; Value keyCount; + Value unk2; + Value boneSlotCount; }; }; @@ -92,43 +92,43 @@ struct ANIM : BigDNA void read(Athena::io::IStreamReader& reader) { - id = reader.readUint32(); - keyCount1 = reader.readUint16(); - initRX = reader.readUint16(); + id = reader.readUint32Big(); + keyCount1 = reader.readUint16Big(); + initRX = reader.readUint16Big(); qRX = reader.readUByte(); - initRY = reader.readUint16(); + initRY = reader.readUint16Big(); qRY = reader.readUByte(); - initRZ = reader.readUint16(); + initRZ = reader.readUint16Big(); qRZ = reader.readUByte(); - keyCount2 = reader.readUint16(); + keyCount2 = reader.readUint16Big(); if (keyCount2) { - initTX = reader.readUint16(); + initTX = reader.readUint16Big(); qTX = reader.readUByte(); - initTY = reader.readUint16(); + initTY = reader.readUint16Big(); qTY = reader.readUByte(); - initTZ = reader.readUint16(); + initTZ = reader.readUint16Big(); qTZ = reader.readUByte(); } } void write(Athena::io::IStreamWriter& writer) const { - writer.writeUint32(id); - writer.writeUint16(keyCount1); - writer.writeUint16(initRX); + writer.writeUint32Big(id); + writer.writeUint16Big(keyCount1); + writer.writeUint16Big(initRX); writer.writeUByte(qRX); - writer.writeUint16(initRY); + writer.writeUint16Big(initRY); writer.writeUByte(qRY); - writer.writeUint16(initRZ); + writer.writeUint16Big(initRZ); writer.writeUByte(qRZ); - writer.writeUint16(keyCount2); + writer.writeUint16Big(keyCount2); if (keyCount2) { - writer.writeUint16(initTX); + writer.writeUint16Big(initTX); writer.writeUByte(qTX); - writer.writeUint16(initTY); + writer.writeUint16Big(initTY); writer.writeUByte(qTY); - writer.writeUint16(initTZ); + writer.writeUint16Big(initTZ); writer.writeUByte(qTZ); } } @@ -138,8 +138,7 @@ struct ANIM : BigDNA std::unique_ptr m_anim; void read(Athena::io::IStreamReader& reader) { - reader.setEndian(Athena::BigEndian); - atUint32 version = reader.readUint32(); + atUint32 version = reader.readUint32Big(); switch (version) { case 0: @@ -158,8 +157,7 @@ struct ANIM : BigDNA void write(Athena::io::IStreamWriter& writer) const { - writer.setEndian(Athena::BigEndian); - writer.writeUint32(m_anim->m_version); + writer.writeUint32Big(m_anim->m_version); m_anim->write(writer); } diff --git a/DataSpec/DNAMP1/CMDLMaterials.hpp b/DataSpec/DNAMP1/CMDLMaterials.hpp index 4c8e24658..42ad94734 100644 --- a/DataSpec/DNAMP1/CMDLMaterials.hpp +++ b/DataSpec/DNAMP1/CMDLMaterials.hpp @@ -250,8 +250,7 @@ struct MaterialSet : BigDNA float vals[4]; void read(Athena::io::IStreamReader& reader) { - reader.setEndian(Athena::BigEndian); - mode = Mode(reader.readUint32()); + mode = Mode(reader.readUint32Big()); switch (mode) { case ANIM_MV_INV_NOTRANS: @@ -261,22 +260,21 @@ struct MaterialSet : BigDNA case ANIM_SCROLL: case ANIM_HSTRIP: case ANIM_VSTRIP: - vals[0] = reader.readFloat(); - vals[1] = reader.readFloat(); - vals[2] = reader.readFloat(); - vals[3] = reader.readFloat(); + vals[0] = reader.readFloatBig(); + vals[1] = reader.readFloatBig(); + vals[2] = reader.readFloatBig(); + vals[3] = reader.readFloatBig(); break; case ANIM_ROTATION: case ANIM_MODE_WHO_MUST_NOT_BE_NAMED: - vals[0] = reader.readFloat(); - vals[1] = reader.readFloat(); + vals[0] = reader.readFloatBig(); + vals[1] = reader.readFloatBig(); break; } } void write(Athena::io::IStreamWriter& writer) const { - writer.setEndian(Athena::BigEndian); - writer.writeUint32(mode); + writer.writeUint32Big(mode); switch (mode) { case ANIM_MV_INV_NOTRANS: @@ -286,15 +284,15 @@ struct MaterialSet : BigDNA case ANIM_SCROLL: case ANIM_HSTRIP: case ANIM_VSTRIP: - writer.writeFloat(vals[0]); - writer.writeFloat(vals[1]); - writer.writeFloat(vals[2]); - writer.writeFloat(vals[3]); + writer.writeFloatBig(vals[0]); + writer.writeFloatBig(vals[1]); + writer.writeFloatBig(vals[2]); + writer.writeFloatBig(vals[3]); break; case ANIM_ROTATION: case ANIM_MODE_WHO_MUST_NOT_BE_NAMED: - writer.writeFloat(vals[0]); - writer.writeFloat(vals[1]); + writer.writeFloatBig(vals[0]); + writer.writeFloatBig(vals[1]); break; } } diff --git a/DataSpec/DNAMP1/PAK.cpp b/DataSpec/DNAMP1/PAK.cpp index 00f2009bd..987175760 100644 --- a/DataSpec/DNAMP1/PAK.cpp +++ b/DataSpec/DNAMP1/PAK.cpp @@ -10,13 +10,12 @@ namespace DNAMP1 void PAK::read(Athena::io::IStreamReader& reader) { - reader.setEndian(Athena::BigEndian); - atUint32 version = reader.readUint32(); + atUint32 version = reader.readUint32Big(); if (version != 0x00030005) Log.report(LogVisor::FatalError, "unexpected PAK magic"); - reader.readUint32(); + reader.readUint32Big(); - atUint32 nameCount = reader.readUint32(); + atUint32 nameCount = reader.readUint32Big(); m_nameEntries.clear(); m_nameEntries.reserve(nameCount); for (atUint32 n=0 ; n readLangs; readLangs.reserve(langCount); @@ -28,7 +28,7 @@ void STRG::_read(Athena::io::IStreamReader& reader) std::vector strs; reader.seek(strCount * 4 + 4); for (atUint32 s=0 ; s>& lang : langs) { lang.first.write(writer); - writer.writeUint32(offset); + writer.writeUint32Big(offset); offset += strCount * 4 + 4; atUint32 langStrCount = lang.second.size(); for (atUint32 s=0 ; s +#include "../DNACommon/DNACommon.hpp" +#include "../DNACommon/ANCS.hpp" +#include "CMDLMaterials.hpp" +#include "BlenderConnection.hpp" +#include "CINF.hpp" +#include "CSKR.hpp" +#include "ANIM.hpp" +#include "../DNAMP1/ANCS.hpp" + +namespace Retro +{ +namespace DNAMP2 +{ + +struct ANCS : BigYAML +{ + using CINFType = CINF; + using CSKRType = CSKR; + using ANIMType = ANIM; + + DECL_YAML + Value version; + + DNAMP1::ANCS::CharacterSet characterSet; + DNAMP1::ANCS::AnimationSet animationSet; + + void getCharacterResInfo(std::vector>& out) const + { + out.clear(); + out.reserve(characterSet.characters.size()); + for (const DNAMP1::ANCS::CharacterSet::CharacterInfo& ci : characterSet.characters) + { + out.emplace_back(); + DNAANCS::CharacterResInfo& chOut = out.back(); + chOut.name = ci.name; + chOut.cmdl = ci.cmdl; + chOut.cskr = ci.cskr; + chOut.cinf = ci.cinf; + } + } + + void getAnimationResInfo(std::map>& out) const + { + out.clear(); + for (const DNAMP1::ANCS::AnimationSet::Animation& ai : animationSet.animations) + ai.metaAnim.m_anim->gatherPrimitives(out); + } + + static bool Extract(const SpecBase& dataSpec, + PAKEntryReadStream& rs, + const HECL::ProjectPath& outPath, + PAKRouter& pakRouter, + const DNAMP1::PAK::Entry& entry, + bool force) + { + ANCS ancs; + ancs.read(rs); + + HECL::ProjectPath yamlPath = outPath.getWithExtension(_S(".yaml")); + if (force || yamlPath.getPathType() == HECL::ProjectPath::PT_NONE) + { + FILE* fp = HECL::Fopen(yamlPath.getAbsolutePath().c_str(), _S("wb")); + ancs.toYAMLFile(fp); + fclose(fp); + } + + HECL::ProjectPath blendPath = outPath.getWithExtension(_S(".blend")); + if (force || blendPath.getPathType() == HECL::ProjectPath::PT_NONE) + { + HECL::BlenderConnection& conn = HECL::BlenderConnection::SharedConnection(); + DNAANCS::ReadANCSToBlender, ANCS, MaterialSet, 4> + (conn, ancs, blendPath, pakRouter, entry, dataSpec.getMasterShaderPath(), force); + return conn.saveBlend(); + } + + return true; + } +}; + +} +} + +#endif // _DNAMP2_ANCS_HPP_ diff --git a/DataSpec/DNAMP2/ANIM.cpp b/DataSpec/DNAMP2/ANIM.cpp new file mode 100644 index 000000000..6cb2c26c8 --- /dev/null +++ b/DataSpec/DNAMP2/ANIM.cpp @@ -0,0 +1,352 @@ +#include "ANIM.hpp" + +namespace Retro +{ +namespace DNAMP2 +{ + +void ANIM::IANIM::sendANIMToBlender(HECL::BlenderConnection::PyOutStream& os, const CINF& cinf) const +{ + os.format("act.hecl_fps = round(%f)\n", (1.0f / mainInterval)); + + auto kit = chanKeys.begin(); + for (const std::pair& bone : bones) + { + os.format("bone_string = '%s'\n", cinf.getBoneNameFromId(bone.first)->c_str()); + os << "action_group = act.groups.new(bone_string)\n" + "\n" + "rotCurves = []\n" + "rotCurves.append(act.fcurves.new('pose.bones[\"'+bone_string+'\"].rotation_quaternion', index=0, action_group=bone_string))\n" + "rotCurves.append(act.fcurves.new('pose.bones[\"'+bone_string+'\"].rotation_quaternion', index=1, action_group=bone_string))\n" + "rotCurves.append(act.fcurves.new('pose.bones[\"'+bone_string+'\"].rotation_quaternion', index=2, action_group=bone_string))\n" + "rotCurves.append(act.fcurves.new('pose.bones[\"'+bone_string+'\"].rotation_quaternion', index=3, action_group=bone_string))\n" + "\n"; + + if (bone.second) + os << "bone_trans_head = (0.0,0.0,0.0)\n" + "if arm_obj.data.bones[bone_string].parent is not None:\n" + " bone_trans_head = Vector(arm_obj.data.bones[bone_string].head_local) - Vector(arm_obj.data.bones[bone_string].parent.head_local)\n" + "transCurves = []\n" + "transCurves.append(act.fcurves.new('pose.bones[\"'+bone_string+'\"].location', index=0, action_group=bone_string))\n" + "transCurves.append(act.fcurves.new('pose.bones[\"'+bone_string+'\"].location', index=1, action_group=bone_string))\n" + "transCurves.append(act.fcurves.new('pose.bones[\"'+bone_string+'\"].location', index=2, action_group=bone_string))\n" + "\n"; + + os << "crv = act.fcurves.new('pose.bones[\"'+bone_string+'\"].rotation_mode', action_group=bone_string)\n" + "crv.keyframe_points.add()\n" + "crv.keyframe_points[-1].co = (0, 0)\n" + "crv.keyframe_points[-1].interpolation = 'LINEAR'\n" + "\n"; + + const std::vector& rotKeys = *kit++; + auto frameit = frames.begin(); + for (const DNAANIM::Value& val : rotKeys) + { + atUint32 frame = *frameit++; + for (int c=0 ; c<4 ; ++c) + os.format("crv = rotCurves[%d]\n" + "crv.keyframe_points.add()\n" + "crv.keyframe_points[-1].interpolation = 'LINEAR'\n" + "crv.keyframe_points[-1].co = (%u, %f)\n", + c, frame, val.v4.vec[c]); + } + + if (bone.second) + { + const std::vector& transKeys = *kit++; + auto frameit = frames.begin(); + for (const DNAANIM::Value& val : transKeys) + { + atUint32 frame = *frameit++; + for (int c=0 ; c<3 ; ++c) + os.format("crv = transCurves[%d]\n" + "crv.keyframe_points.add()\n" + "crv.keyframe_points[-1].interpolation = 'LINEAR'\n" + "crv.keyframe_points[-1].co = (%u, %f - bone_trans_head[%d])\n", + c, frame, val.v4.vec[c], c); + } + } + } +} + +void ANIM::ANIM0::read(Athena::io::IStreamReader& reader) +{ + Header head; + head.read(reader); + mainInterval = head.interval; + + frames.clear(); + frames.reserve(head.keyCount); + for (size_t k=0 ; k boneMap; + for (size_t b=0 ; b& bone : bones) + { + chanKeys.emplace_back(); + std::vector& keys = chanKeys.back(); + for (size_t k=0 ; k& bone : bones) + { + ++kit; + if (bone.second) + { + std::vector& keys = *kit++; + for (size_t k=0 ; k& bone : bones) + maxId = MAX(maxId, bone.first); + head.boneSlotCount = maxId + 1; + head.write(writer); + + for (size_t s=0 ; s& bone : bones) + { + if (s == bone.first) + { + writer.writeUByte(boneIdx); + found = true; + break; + } + ++boneIdx; + } + if (!found) + writer.writeUByte(0xff); + } + + writer.writeUint32Big(bones.size()); + size_t boneIdx = 0; + for (const std::pair& bone : bones) + { + if (bone.second) + writer.writeUByte(boneIdx); + else + writer.writeUByte(0xff); + ++boneIdx; + } + + writer.writeUint32Big(bones.size() * head.keyCount); + auto cit = chanKeys.begin(); + atUint32 transKeyCount = 0; + for (const std::pair& bone : bones) + { + const std::vector& keys = *cit++; + auto kit = keys.begin(); + for (size_t k=0 ; k& bone : bones) + { + ++cit; + if (bone.second) + { + const std::vector& keys = *cit++; + auto kit = keys.begin(); + for (size_t k=0 ; k bsData = reader.readUBytes(bsSize); + DNAANIM::BitstreamReader bsReader; + chanKeys = bsReader.read(bsData.get(), keyframeCount, channels, head.rotDiv, head.translationMult); +} + +void ANIM::ANIM2::write(Athena::io::IStreamWriter& writer) const +{ + Header head; + head.evnt = evnt; + head.unk0 = 1; + head.interval = mainInterval; + head.unk1 = 3; + head.unk2 = 0; + head.unk3 = 1; + + WordBitmap keyBmp; + size_t frameCount = 0; + for (atUint32 frame : frames) + { + while (keyBmp.getBit(frame)) + ++frame; + keyBmp.setBit(frame); + frameCount = frame + 1; + } + head.keyBitmapBitCount = frameCount; + head.duration = frameCount * mainInterval; + head.boneChannelCount = bones.size(); + + size_t keyframeCount = frames.size(); + std::vector qChannels = channels; + DNAANIM::BitstreamWriter bsWriter; + size_t bsSize; + std::unique_ptr bsData = bsWriter.write(chanKeys, keyframeCount, qChannels, + head.rotDiv, head.translationMult, bsSize); + + /* TODO: Figure out proper scratch size computation */ + head.scratchSize = keyframeCount * channels.size() * 16; + + head.write(writer); + keyBmp.write(writer); + writer.writeUint32Big(head.boneChannelCount); + writer.writeUint32Big(head.boneChannelCount); + auto cit = qChannels.begin(); + for (const std::pair& bone : bones) + { + ChannelDesc desc; + desc.id = bone.first; + DNAANIM::Channel& chan = *cit++; + desc.keyCount1 = keyframeCount; + desc.initRX = chan.i[0]; + desc.qRX = chan.q[0]; + desc.initRY = chan.i[1]; + desc.qRY = chan.q[1]; + desc.initRZ = chan.i[2]; + desc.qRZ = chan.q[2]; + if (bone.second) + { + DNAANIM::Channel& chan = *cit++; + desc.keyCount2 = keyframeCount; + desc.initTX = chan.i[0]; + desc.qTX = chan.q[0]; + desc.initTY = chan.i[1]; + desc.qTY = chan.q[1]; + desc.initTZ = chan.i[2]; + desc.qTZ = chan.q[2]; + } + desc.write(writer); + } + + writer.writeUBytes(bsData.get(), bsSize); +} + +} +} diff --git a/DataSpec/DNAMP2/ANIM.hpp b/DataSpec/DNAMP2/ANIM.hpp new file mode 100644 index 000000000..c5b88d8ec --- /dev/null +++ b/DataSpec/DNAMP2/ANIM.hpp @@ -0,0 +1,174 @@ +#ifndef _DNAMP2_ANIM_HPP_ +#define _DNAMP2_ANIM_HPP_ + +#include "BlenderConnection.hpp" +#include "DNAMP2.hpp" +#include "../DNACommon/ANIM.hpp" +#include "CINF.hpp" + +namespace Retro +{ +namespace DNAMP2 +{ + +struct ANIM : BigDNA +{ + Delete expl; + + struct IANIM : BigDNA + { + Delete expl; + atUint32 m_version; + IANIM(atUint32 version) : m_version(version) {} + + std::vector> bones; + std::vector frames; + std::vector channels; + std::vector> chanKeys; + float mainInterval = 0.0; + UniqueID32 evnt; + + void sendANIMToBlender(HECL::BlenderConnection::PyOutStream&, const CINF&) const; + }; + + struct ANIM0 : IANIM + { + DECL_EXPLICIT_DNA + ANIM0() : IANIM(0) {} + + struct Header : BigDNA + { + DECL_DNA + Value duration; + Value unk0; + Value interval; + Value unk1; + Value keyCount; + Value unk2; + Value boneSlotCount; + }; + }; + + struct ANIM2 : IANIM + { + DECL_EXPLICIT_DNA + ANIM2() : IANIM(2) {} + + struct Header : BigDNA + { + DECL_DNA + Value scratchSize; + UniqueID32 evnt; + Value unk0; + Value duration; + Value interval; + Value unk1; + Value unk2; + Value rotDiv; + Value translationMult; + Value boneChannelCount; + Value unk3; + Value keyBitmapBitCount; + }; + + struct ChannelDesc : BigDNA + { + Delete expl; + Value id = 0; + Value keyCount1 = 0; + Value initRX = 0; + Value qRX = 0; + Value initRY = 0; + Value qRY = 0; + Value initRZ = 0; + Value qRZ = 0; + Value keyCount2 = 0; + Value initTX = 0; + Value qTX = 0; + Value initTY = 0; + Value qTY = 0; + Value initTZ = 0; + Value qTZ = 0; + + void read(Athena::io::IStreamReader& reader) + { + id = reader.readUint32Big(); + keyCount1 = reader.readUint16Big(); + initRX = reader.readUint16Big(); + qRX = reader.readUByte(); + initRY = reader.readUint16Big(); + qRY = reader.readUByte(); + initRZ = reader.readUint16Big(); + qRZ = reader.readUByte(); + keyCount2 = reader.readUint16Big(); + if (keyCount2) + { + initTX = reader.readUint16Big(); + qTX = reader.readUByte(); + initTY = reader.readUint16Big(); + qTY = reader.readUByte(); + initTZ = reader.readUint16Big(); + qTZ = reader.readUByte(); + } + } + void write(Athena::io::IStreamWriter& writer) const + { + writer.writeUint32Big(id); + writer.writeUint16Big(keyCount1); + writer.writeUint16Big(initRX); + writer.writeUByte(qRX); + writer.writeUint16Big(initRY); + writer.writeUByte(qRY); + writer.writeUint16Big(initRZ); + writer.writeUByte(qRZ); + writer.writeUint16Big(keyCount2); + if (keyCount2) + { + writer.writeUint16Big(initTX); + writer.writeUByte(qTX); + writer.writeUint16Big(initTY); + writer.writeUByte(qTY); + writer.writeUint16Big(initTZ); + writer.writeUByte(qTZ); + } + } + }; + }; + + std::unique_ptr m_anim; + void read(Athena::io::IStreamReader& reader) + { + atUint32 version = reader.readUint32Big(); + switch (version) + { + case 0: + m_anim.reset(new struct ANIM0); + m_anim->read(reader); + break; + case 2: + m_anim.reset(new struct ANIM2); + m_anim->read(reader); + break; + default: + Log.report(LogVisor::Error, "unrecognized ANIM version"); + break; + } + } + + void write(Athena::io::IStreamWriter& writer) const + { + writer.writeUint32Big(m_anim->m_version); + m_anim->write(writer); + } + + void sendANIMToBlender(HECL::BlenderConnection::PyOutStream& os, const CINF& cinf) const + { + m_anim->sendANIMToBlender(os, cinf); + } + +}; + +} +} + +#endif // _DNAMP2_ANIM_HPP_ diff --git a/DataSpec/DNAMP2/CMakeLists.txt b/DataSpec/DNAMP2/CMakeLists.txt index d23079bfb..f48bc1aa3 100644 --- a/DataSpec/DNAMP2/CMakeLists.txt +++ b/DataSpec/DNAMP2/CMakeLists.txt @@ -1,10 +1,13 @@ make_dnalist(liblist MLVL + ANIM + ANCS CMDLMaterials CINF CSKR) add_library(DNAMP2 DNAMP2.hpp DNAMP2.cpp ${liblist} + ANIM.cpp CMDL.hpp STRG.hpp STRG.cpp) diff --git a/DataSpec/DNAMP2/DNAMP2.cpp b/DataSpec/DNAMP2/DNAMP2.cpp index 21635de30..550b7a90c 100644 --- a/DataSpec/DNAMP2/DNAMP2.cpp +++ b/DataSpec/DNAMP2/DNAMP2.cpp @@ -3,6 +3,7 @@ #include "STRG.hpp" #include "MLVL.hpp" #include "CMDL.hpp" +#include "ANCS.hpp" #include "../DNACommon/TXTR.hpp" namespace Retro @@ -188,7 +189,9 @@ ResExtractor PAKBridge::LookupExtractor(const DNAMP1::PAK::Entry& ent case SBIG('TXTR'): return {TXTR::Extract, nullptr, ".png"}; case SBIG('CMDL'): - return {nullptr, CMDL::Extract, ".blend", 1}; + return {nullptr, CMDL::Extract, ".blend", 2}; + case SBIG('ANCS'): + return {nullptr, ANCS::Extract, nullptr, 1}; } return {}; } diff --git a/DataSpec/DNAMP2/STRG.cpp b/DataSpec/DNAMP2/STRG.cpp index 063c7348d..a7ae582ad 100644 --- a/DataSpec/DNAMP2/STRG.cpp +++ b/DataSpec/DNAMP2/STRG.cpp @@ -8,8 +8,8 @@ namespace DNAMP2 void STRG::_read(Athena::io::IStreamReader& reader) { - atUint32 langCount = reader.readUint32(); - atUint32 strCount = reader.readUint32(); + atUint32 langCount = reader.readUint32Big(); + atUint32 strCount = reader.readUint32Big(); std::vector readLangs; readLangs.reserve(langCount); @@ -21,8 +21,8 @@ void STRG::_read(Athena::io::IStreamReader& reader) reader.seek(8); } - atUint32 nameCount = reader.readUint32(); - atUint32 nameTableSz = reader.readUint32(); + atUint32 nameCount = reader.readUint32Big(); + atUint32 nameTableSz = reader.readUint32Big(); std::unique_ptr nameTableBuf(new uint8_t[nameTableSz]); reader.readUBytesToBuf(nameTableBuf.get(), nameTableSz); struct NameIdxEntry @@ -43,7 +43,7 @@ void STRG::_read(Athena::io::IStreamReader& reader) std::vector strs; reader.seek(strCount * 4); for (atUint32 s=0 ; s>& lang : langs) { lang.first.write(writer); - writer.writeUint32(offset); + writer.writeUint32Big(offset); offset += strCount * 4 + 4; atUint32 langStrCount = lang.second.size(); atUint32 tableSz = strCount * 4; @@ -98,19 +96,19 @@ void STRG::write(Athena::io::IStreamWriter& writer) const tableSz += 1; } } - writer.writeUint32(tableSz); + writer.writeUint32Big(tableSz); } atUint32 nameTableSz = names.size() * 8; for (const std::pair& name : names) nameTableSz += name.first.size() + 1; - writer.writeUint32(names.size()); - writer.writeUint32(nameTableSz); + writer.writeUint32Big(names.size()); + writer.writeUint32Big(nameTableSz); offset = names.size() * 8; for (const std::pair& name : names) { - writer.writeUint32(offset); - writer.writeInt32(name.second); + writer.writeUint32Big(offset); + writer.writeInt32Big(name.second); offset += name.first.size() + 1; } for (const std::pair& name : names) @@ -122,7 +120,7 @@ void STRG::write(Athena::io::IStreamWriter& writer) const atUint32 langStrCount = lang.second.size(); for (atUint32 s=0 ; s nameTableBuf(new uint8_t[nameTableSz]); @@ -40,9 +40,9 @@ void STRG::_read(Athena::io::IStreamReader& reader) std::unique_ptr strOffs(new atUint32[langCount * strCount]); for (atUint32 l=0 ; l= lang.second.size()) { - writer.writeUint32(1); + writer.writeUint32Big(1); writer.writeUByte(0); } else { const std::string& str = lang.second[s]; - writer.writeUint32(str.size() + 1); + writer.writeUint32Big(str.size() + 1); writer.writeString(str); } }