ANIM fixes and explicit-endian refactor

This commit is contained in:
Jack Andersen 2015-08-13 17:00:51 -10:00
parent 5b38596595
commit b5d96f7040
20 changed files with 858 additions and 246 deletions

View File

@ -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);

View File

@ -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<normCount ; ++i)
{
os.format("norm_list.append((%f,%f,%f))\n",
reader.readInt16(), reader.readInt16(), reader.readInt16());
reader.readInt16Big(), reader.readInt16Big(), reader.readInt16Big());
}
}
else
@ -549,7 +547,7 @@ bool ReadCMDLToBlender(HECL::BlenderConnection& conn,
size_t normCount = head.secSizes[s] / 12;
for (size_t i=0 ; i<normCount ; ++i)
{
atVec3f norm = reader.readVec3f();
atVec3f norm = reader.readVec3fBig();
os.format("norm_list.append((%f,%f,%f))\n",
norm.vec[0], norm.vec[1], norm.vec[2]);
}
@ -568,7 +566,7 @@ bool ReadCMDLToBlender(HECL::BlenderConnection& conn,
size_t uvCount = head.secSizes[s] / 8;
for (size_t i=0 ; i<uvCount ; ++i)
{
atVec2f uv = reader.readVec2f();
atVec2f uv = reader.readVec2fBig();
os.format("uv_list.append((%f,%f))\n",
uv.vec[0], uv.vec[1]);
}
@ -584,7 +582,7 @@ bool ReadCMDLToBlender(HECL::BlenderConnection& conn,
for (size_t i=0 ; i<uvCount ; ++i)
{
os.format("suv_list.append((%f,%f))\n",
reader.readInt16(), reader.readInt16());
reader.readInt16Big(), reader.readInt16Big());
}
break;
}

View File

@ -48,9 +48,9 @@ public:
Delete expl;
inline operator bool() const {return m_id != 0xffffffff;}
inline void read(Athena::io::IStreamReader& reader)
{m_id = reader.readUint32();}
{m_id = reader.readUint32Big();}
inline void write(Athena::io::IStreamWriter& writer) const
{writer.writeUint32(m_id);}
{writer.writeUint32Big(m_id);}
inline void fromYAML(Athena::io::YAMLDocReader& reader)
{m_id = reader.readUint32(nullptr);}
inline void toYAML(Athena::io::YAMLDocWriter& writer) const
@ -75,9 +75,9 @@ public:
Delete expl;
inline operator bool() const {return m_id != 0xffffffffffffffff;}
inline void read(Athena::io::IStreamReader& reader)
{m_id = reader.readUint64();}
{m_id = reader.readUint64Big();}
inline void write(Athena::io::IStreamWriter& writer) const
{writer.writeUint64(m_id);}
{writer.writeUint64Big(m_id);}
inline bool operator!=(const UniqueID64& other) const {return m_id != other.m_id;}
inline bool operator==(const UniqueID64& other) const {return m_id == other.m_id;}
@ -107,13 +107,13 @@ public:
{return m_id[0] != 0xffffffffffffffff && m_id[1] != 0xffffffffffffffff;}
inline void read(Athena::io::IStreamReader& reader)
{
m_id[0] = reader.readUint64();
m_id[1] = reader.readUint64();
m_id[0] = reader.readUint64Big();
m_id[1] = reader.readUint64Big();
}
inline void write(Athena::io::IStreamWriter& writer) const
{
writer.writeUint64(m_id[0]);
writer.writeUint64(m_id[1]);
writer.writeUint64Big(m_id[0]);
writer.writeUint64Big(m_id[1]);
}
inline bool operator!=(const UniqueID128& other) const
@ -182,7 +182,7 @@ struct WordBitmap
m_words.clear();
m_words.reserve(wordCount);
for (size_t w=0 ; w<wordCount ; ++w)
m_words.push_back(reader.readUint32());
m_words.push_back(reader.readUint32Big());
}
void write(Athena::io::IStreamWriter& writer) const
{

View File

@ -8,15 +8,14 @@ namespace Retro
std::unique_ptr<ISTRG> 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<ISTRG>();
}
uint32_t version = reader.readUint32();
uint32_t version = reader.readUint32Big();
switch (version)
{
case 0:

View File

@ -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)

View File

@ -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<AnimInfo>(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);
}
}

View File

@ -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<PAKRouter<PAKBridge>, 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<PAKRouter<PAKBridge>, ANCS, MaterialSet, 2>
(conn, ancs, blendPath, pakRouter, entry, dataSpec.getMasterShaderPath(), force);
return conn.saveBlend();
}
return true;
}
};

View File

@ -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<atUint32, bool>& bone : bones)
@ -117,13 +117,13 @@ void ANIM::ANIM0::read(Athena::io::IStreamReader& reader)
chanKeys.emplace_back();
std::vector<DNAANIM::Value>& keys = chanKeys.back();
for (size_t k=0 ; k<head.keyCount ; ++k)
keys.emplace_back(reader.readVec4f());
keys.emplace_back(reader.readVec4fBig());
if (bone.second)
chanKeys.emplace_back();
}
reader.readUint32();
reader.readUint32Big();
auto kit = chanKeys.begin();
for (const std::pair<atUint32, bool>& bone : bones)
{
@ -132,7 +132,7 @@ void ANIM::ANIM0::read(Athena::io::IStreamReader& reader)
{
std::vector<DNAANIM::Value>& keys = *kit++;
for (size_t k=0 ; k<head.keyCount ; ++k)
keys.emplace_back(reader.readVec3f());
keys.emplace_back(reader.readVec3fBig());
}
}
@ -173,7 +173,7 @@ void ANIM::ANIM0::write(Athena::io::IStreamWriter& writer) const
writer.writeUByte(0xff);
}
writer.writeUint32(bones.size());
writer.writeUint32Big(bones.size());
size_t boneIdx = 0;
for (const std::pair<atUint32, bool>& 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<atUint32, bool>& bone : bones)
@ -192,7 +192,7 @@ void ANIM::ANIM0::write(Athena::io::IStreamWriter& writer) const
const std::vector<DNAANIM::Value>& keys = *cit++;
auto kit = keys.begin();
for (size_t k=0 ; k<head.keyCount ; ++k)
writer.writeVec4f((*kit++).v4);
writer.writeVec4fBig((*kit++).v4);
if (bone.second)
{
transKeyCount += head.keyCount;
@ -200,7 +200,7 @@ void ANIM::ANIM0::write(Athena::io::IStreamWriter& writer) const
}
}
writer.writeUint32(transKeyCount);
writer.writeUint32Big(transKeyCount);
cit = chanKeys.begin();
for (const std::pair<atUint32, bool>& bone : bones)
{
@ -210,7 +210,7 @@ void ANIM::ANIM0::write(Athena::io::IStreamWriter& writer) const
const std::vector<DNAANIM::Value>& keys = *cit++;
auto kit = keys.begin();
for (size_t k=0 ; k<head.keyCount ; ++k)
writer.writeVec3f((*kit++).v3);
writer.writeVec3fBig((*kit++).v3);
}
}
@ -316,8 +316,8 @@ void ANIM::ANIM2::write(Athena::io::IStreamWriter& writer) const
head.write(writer);
keyBmp.write(writer);
writer.writeUint32(head.boneChannelCount);
writer.writeUint32(head.boneChannelCount);
writer.writeUint32Big(head.boneChannelCount);
writer.writeUint32Big(head.boneChannelCount);
auto cit = qChannels.begin();
for (const std::pair<atUint32, bool>& bone : bones)
{

View File

@ -43,9 +43,9 @@ struct ANIM : BigDNA
Value<atUint32> unk0;
Value<float> interval;
Value<atUint32> unk1;
Value<atUint32> boneSlotCount;
Value<atUint32> unk2;
Value<atUint32> keyCount;
Value<atUint32> unk2;
Value<atUint32> 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<IANIM> 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);
}

View File

@ -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;
}
}

View File

@ -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<nameCount ; ++n)
@ -25,7 +24,7 @@ void PAK::read(Athena::io::IStreamReader& reader)
m_nameEntries.back().read(reader);
}
atUint32 count = reader.readUint32();
atUint32 count = reader.readUint32Big();
m_entries.clear();
m_entries.reserve(count);
m_idMap.clear();
@ -53,18 +52,17 @@ void PAK::read(Athena::io::IStreamReader& reader)
void PAK::write(Athena::io::IStreamWriter& writer) const
{
writer.setEndian(Athena::BigEndian);
writer.writeUint32(0x00030005);
writer.writeUint32(0);
writer.writeUint32Big(0x00030005);
writer.writeUint32Big(0);
writer.writeUint32((atUint32)m_nameEntries.size());
writer.writeUint32Big((atUint32)m_nameEntries.size());
for (const NameEntry& entry : m_nameEntries)
{
((NameEntry&)entry).nameLen = entry.name.size();
entry.write(writer);
}
writer.writeUint32(m_entries.size());
writer.writeUint32Big(m_entries.size());
for (const Entry& entry : m_entries)
{
Entry tmp = entry;

View File

@ -8,8 +8,8 @@ namespace DNAMP1
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<FourCC> readLangs;
readLangs.reserve(langCount);
@ -28,7 +28,7 @@ void STRG::_read(Athena::io::IStreamReader& reader)
std::vector<std::wstring> strs;
reader.seek(strCount * 4 + 4);
for (atUint32 s=0 ; s<strCount ; ++s)
strs.emplace_back(reader.readWString());
strs.emplace_back(reader.readWStringBig());
langs.emplace_back(lang, strs);
}
@ -40,12 +40,11 @@ void STRG::_read(Athena::io::IStreamReader& reader)
void STRG::read(Athena::io::IStreamReader& reader)
{
reader.setEndian(Athena::BigEndian);
atUint32 magic = reader.readUint32();
atUint32 magic = reader.readUint32Big();
if (magic != 0x87654321)
Log.report(LogVisor::Error, "invalid STRG magic");
atUint32 version = reader.readUint32();
atUint32 version = reader.readUint32Big();
if (version != 0)
Log.report(LogVisor::Error, "invalid STRG version");
@ -54,18 +53,17 @@ void STRG::read(Athena::io::IStreamReader& reader)
void STRG::write(Athena::io::IStreamWriter& writer) const
{
writer.setEndian(Athena::BigEndian);
writer.writeUint32(0x87654321);
writer.writeUint32(0);
writer.writeUint32(langs.size());
writer.writeUint32Big(0x87654321);
writer.writeUint32Big(0);
writer.writeUint32Big(langs.size());
atUint32 strCount = STRG::count();
writer.writeUint32(strCount);
writer.writeUint32Big(strCount);
atUint32 offset = 0;
for (const std::pair<FourCC, std::vector<std::wstring>>& 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<strCount ; ++s)
@ -89,12 +87,12 @@ void STRG::write(Athena::io::IStreamWriter& writer) const
else
tableSz += 1;
}
writer.writeUint32(tableSz);
writer.writeUint32Big(tableSz);
offset = strCount * 4;
for (atUint32 s=0 ; s<strCount ; ++s)
{
writer.writeUint32(offset);
writer.writeUint32Big(offset);
if (s < langStrCount)
offset += lang.second[s].size() * 2 + 1;
else
@ -104,7 +102,7 @@ void STRG::write(Athena::io::IStreamWriter& writer) const
for (atUint32 s=0 ; s<strCount ; ++s)
{
if (s < langStrCount)
writer.writeWString(lang.second[s]);
writer.writeWStringBig(lang.second[s]);
else
writer.writeUByte(0);
}

87
DataSpec/DNAMP2/ANCS.hpp Normal file
View File

@ -0,0 +1,87 @@
#ifndef _DNAMP2_ANCS_HPP_
#define _DNAMP2_ANCS_HPP_
#include <map>
#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<atUint16> version;
DNAMP1::ANCS::CharacterSet characterSet;
DNAMP1::ANCS::AnimationSet animationSet;
void getCharacterResInfo(std::vector<DNAANCS::CharacterResInfo<UniqueID32>>& out) const
{
out.clear();
out.reserve(characterSet.characters.size());
for (const DNAMP1::ANCS::CharacterSet::CharacterInfo& ci : characterSet.characters)
{
out.emplace_back();
DNAANCS::CharacterResInfo<UniqueID32>& chOut = out.back();
chOut.name = ci.name;
chOut.cmdl = ci.cmdl;
chOut.cskr = ci.cskr;
chOut.cinf = ci.cinf;
}
}
void getAnimationResInfo(std::map<atUint32, std::pair<std::string, UniqueID32>>& 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<PAKBridge>& 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<PAKRouter<PAKBridge>, ANCS, MaterialSet, 4>
(conn, ancs, blendPath, pakRouter, entry, dataSpec.getMasterShaderPath(), force);
return conn.saveBlend();
}
return true;
}
};
}
}
#endif // _DNAMP2_ANCS_HPP_

352
DataSpec/DNAMP2/ANIM.cpp Normal file
View File

@ -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<atUint32, bool>& 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<DNAANIM::Value>& 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<DNAANIM::Value>& 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<head.keyCount ; ++k)
frames.push_back(k);
std::map<atUint8, atUint32> boneMap;
for (size_t b=0 ; b<head.boneSlotCount ; ++b)
{
atUint8 idx = reader.readUByte();
if (idx == 0xff)
continue;
boneMap[idx] = b;
}
atUint32 boneCount = reader.readUint32Big();
bones.clear();
bones.reserve(boneCount);
channels.clear();
for (size_t b=0 ; b<boneCount ; ++b)
{
bones.emplace_back(boneMap[b], false);
atUint8 idx = reader.readUByte();
channels.emplace_back();
DNAANIM::Channel& chan = channels.back();
chan.type = DNAANIM::Channel::ROTATION;
if (idx != 0xff)
{
bones.back().second = true;
channels.emplace_back();
DNAANIM::Channel& chan = channels.back();
chan.type = DNAANIM::Channel::TRANSLATION;
}
}
reader.readUint32Big();
chanKeys.clear();
chanKeys.reserve(channels.size());
for (const std::pair<atUint32, bool>& bone : bones)
{
chanKeys.emplace_back();
std::vector<DNAANIM::Value>& keys = chanKeys.back();
for (size_t k=0 ; k<head.keyCount ; ++k)
keys.emplace_back(reader.readVec4fBig());
if (bone.second)
chanKeys.emplace_back();
}
reader.readUint32Big();
auto kit = chanKeys.begin();
for (const std::pair<atUint32, bool>& bone : bones)
{
++kit;
if (bone.second)
{
std::vector<DNAANIM::Value>& keys = *kit++;
for (size_t k=0 ; k<head.keyCount ; ++k)
keys.emplace_back(reader.readVec3fBig());
}
}
evnt.read(reader);
}
void ANIM::ANIM0::write(Athena::io::IStreamWriter& writer) const
{
Header head;
head.unk0 = 0;
head.unk1 = 0;
head.unk2 = 0;
head.keyCount = frames.size();
head.duration = head.keyCount * mainInterval;
head.interval = mainInterval;
atUint32 maxId = 0;
for (const std::pair<atUint32, bool>& bone : bones)
maxId = MAX(maxId, bone.first);
head.boneSlotCount = maxId + 1;
head.write(writer);
for (size_t s=0 ; s<head.boneSlotCount ; ++s)
{
size_t boneIdx = 0;
bool found = false;
for (const std::pair<atUint32, bool>& 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<atUint32, bool>& 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<atUint32, bool>& bone : bones)
{
const std::vector<DNAANIM::Value>& keys = *cit++;
auto kit = keys.begin();
for (size_t k=0 ; k<head.keyCount ; ++k)
writer.writeVec4fBig((*kit++).v4);
if (bone.second)
{
transKeyCount += head.keyCount;
++cit;
}
}
writer.writeUint32Big(transKeyCount);
cit = chanKeys.begin();
for (const std::pair<atUint32, bool>& bone : bones)
{
++cit;
if (bone.second)
{
const std::vector<DNAANIM::Value>& keys = *cit++;
auto kit = keys.begin();
for (size_t k=0 ; k<head.keyCount ; ++k)
writer.writeVec3fBig((*kit++).v3);
}
}
evnt.write(writer);
}
void ANIM::ANIM2::read(Athena::io::IStreamReader& reader)
{
Header head;
head.read(reader);
evnt = head.evnt;
mainInterval = head.interval;
WordBitmap keyBmp;
keyBmp.read(reader, head.keyBitmapBitCount);
frames.clear();
atUint32 frameAccum = 0;
for (bool bit : keyBmp)
{
if (bit)
frames.push_back(frameAccum);
++frameAccum;
}
reader.seek(8);
bones.clear();
bones.reserve(head.boneChannelCount);
channels.clear();
channels.reserve(head.boneChannelCount);
size_t keyframeCount = 0;
for (size_t b=0 ; b<head.boneChannelCount ; ++b)
{
ChannelDesc desc;
desc.read(reader);
bones.emplace_back(desc.id, desc.keyCount2);
if (desc.keyCount1)
{
channels.emplace_back();
DNAANIM::Channel& chan = channels.back();
chan.type = DNAANIM::Channel::ROTATION;
chan.i[0] = desc.initRX;
chan.q[0] = desc.qRX;
chan.i[1] = desc.initRY;
chan.q[1] = desc.qRY;
chan.i[2] = desc.initRZ;
chan.q[2] = desc.qRZ;
}
keyframeCount = MAX(keyframeCount, desc.keyCount1);
if (desc.keyCount2)
{
channels.emplace_back();
DNAANIM::Channel& chan = channels.back();
chan.type = DNAANIM::Channel::TRANSLATION;
chan.i[0] = desc.initTX;
chan.q[0] = desc.qTX;
chan.i[1] = desc.initTY;
chan.q[1] = desc.qTY;
chan.i[2] = desc.initTZ;
chan.q[2] = desc.qTZ;
}
}
size_t bsSize = DNAANIM::ComputeBitstreamSize(keyframeCount, channels);
std::unique_ptr<atUint8[]> 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<DNAANIM::Channel> qChannels = channels;
DNAANIM::BitstreamWriter bsWriter;
size_t bsSize;
std::unique_ptr<atUint8[]> 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<atUint32, bool>& 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);
}
}
}

174
DataSpec/DNAMP2/ANIM.hpp Normal file
View File

@ -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<std::pair<atUint32, bool>> bones;
std::vector<atUint32> frames;
std::vector<DNAANIM::Channel> channels;
std::vector<std::vector<DNAANIM::Value>> 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<float> duration;
Value<atUint32> unk0;
Value<float> interval;
Value<atUint32> unk1;
Value<atUint32> keyCount;
Value<atUint32> unk2;
Value<atUint32> boneSlotCount;
};
};
struct ANIM2 : IANIM
{
DECL_EXPLICIT_DNA
ANIM2() : IANIM(2) {}
struct Header : BigDNA
{
DECL_DNA
Value<atUint32> scratchSize;
UniqueID32 evnt;
Value<atUint32> unk0;
Value<float> duration;
Value<float> interval;
Value<atUint32> unk1;
Value<atUint32> unk2;
Value<atUint32> rotDiv;
Value<float> translationMult;
Value<atUint32> boneChannelCount;
Value<atUint32> unk3;
Value<atUint32> keyBitmapBitCount;
};
struct ChannelDesc : BigDNA
{
Delete expl;
Value<atUint32> id = 0;
Value<atUint16> keyCount1 = 0;
Value<atUint16> initRX = 0;
Value<atUint8> qRX = 0;
Value<atUint16> initRY = 0;
Value<atUint8> qRY = 0;
Value<atUint16> initRZ = 0;
Value<atUint8> qRZ = 0;
Value<atUint16> keyCount2 = 0;
Value<atUint16> initTX = 0;
Value<atUint8> qTX = 0;
Value<atUint16> initTY = 0;
Value<atUint8> qTY = 0;
Value<atUint16> initTZ = 0;
Value<atUint8> 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<IANIM> 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_

View File

@ -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)

View File

@ -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> 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 {};
}

View File

@ -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<FourCC> 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<uint8_t[]> 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<std::wstring> strs;
reader.seek(strCount * 4);
for (atUint32 s=0 ; s<strCount ; ++s)
strs.emplace_back(reader.readWString());
strs.emplace_back(reader.readWStringBig());
langs.emplace_back(lang, strs);
}
@ -55,12 +55,11 @@ void STRG::_read(Athena::io::IStreamReader& reader)
void STRG::read(Athena::io::IStreamReader& reader)
{
reader.setEndian(Athena::BigEndian);
atUint32 magic = reader.readUint32();
atUint32 magic = reader.readUint32Big();
if (magic != 0x87654321)
Log.report(LogVisor::Error, "invalid STRG magic");
atUint32 version = reader.readUint32();
atUint32 version = reader.readUint32Big();
if (version != 1)
Log.report(LogVisor::Error, "invalid STRG version");
@ -69,18 +68,17 @@ void STRG::read(Athena::io::IStreamReader& reader)
void STRG::write(Athena::io::IStreamWriter& writer) const
{
writer.setEndian(Athena::BigEndian);
writer.writeUint32(0x87654321);
writer.writeUint32(1);
writer.writeUint32(langs.size());
writer.writeUint32Big(0x87654321);
writer.writeUint32Big(1);
writer.writeUint32Big(langs.size());
atUint32 strCount = STRG::count();
writer.writeUint32(strCount);
writer.writeUint32Big(strCount);
atUint32 offset = 0;
for (const std::pair<FourCC, std::vector<std::wstring>>& 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<std::string, int32_t>& 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<std::string, int32_t>& 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<std::string, int32_t>& name : names)
@ -122,7 +120,7 @@ void STRG::write(Athena::io::IStreamWriter& writer) const
atUint32 langStrCount = lang.second.size();
for (atUint32 s=0 ; s<strCount ; ++s)
{
writer.writeUint32(offset);
writer.writeUint32Big(offset);
if (s < langStrCount)
offset += lang.second[s].size() * 2 + 1;
else
@ -132,7 +130,7 @@ void STRG::write(Athena::io::IStreamWriter& writer) const
for (atUint32 s=0 ; s<strCount ; ++s)
{
if (s < langStrCount)
writer.writeWString(lang.second[s]);
writer.writeWStringBig(lang.second[s]);
else
writer.writeUByte(0);
}

View File

@ -10,20 +10,19 @@ const HECL::FourCC CMPD("CMPD");
void PAK::read(Athena::io::IStreamReader& reader)
{
reader.setEndian(Athena::BigEndian);
m_header.read(reader);
if (m_header.version != 2)
Log.report(LogVisor::FatalError, "unexpected PAK magic");
reader.seek(8, Athena::Current);
atUint32 strgSz = reader.readUint32();
atUint32 strgSz = reader.readUint32Big();
reader.seek(4, Athena::Current);
atUint32 rshdSz = reader.readUint32();
atUint32 rshdSz = reader.readUint32Big();
reader.seek(44, Athena::Current);
atUint32 dataOffset = 128 + strgSz + rshdSz;
atUint64 strgBase = reader.position();
atUint32 nameCount = reader.readUint32();
atUint32 nameCount = reader.readUint32Big();
m_nameEntries.clear();
m_nameEntries.reserve(nameCount);
for (atUint32 n=0 ; n<nameCount ; ++n)
@ -36,7 +35,7 @@ void PAK::read(Athena::io::IStreamReader& reader)
atUint64 end = reader.position();
atUint64 diff = end - start;
atUint32 count = reader.readUint32();
atUint32 count = reader.readUint32Big();
m_entries.clear();
m_entries.reserve(count);
m_idMap.clear();
@ -61,7 +60,6 @@ void PAK::read(Athena::io::IStreamReader& reader)
}
void PAK::write(Athena::io::IStreamWriter& writer) const
{
writer.setEndian(Athena::BigEndian);
m_header.write(writer);
FourCC("STRG").write(writer);
@ -70,13 +68,13 @@ void PAK::write(Athena::io::IStreamWriter& writer) const
strgSz += (atUint32)entry.name.size() + 13;
atUint32 strgPad = ((strgSz + 63) & ~63) - strgSz;
strgSz += strgPad;
writer.writeUint32(strgSz);
writer.writeUint32Big(strgSz);
FourCC("RSHD").write(writer);
atUint32 rshdSz = 4 + 24 * m_entries.size();
atUint32 rshdPad = ((rshdSz + 63) & ~63) - rshdSz;
rshdSz += rshdPad;
writer.writeUint32(rshdSz);
writer.writeUint32Big(rshdSz);
atUint32 dataOffset = 128 + strgSz + rshdSz;
FourCC("DATA").write(writer);
@ -85,15 +83,15 @@ void PAK::write(Athena::io::IStreamWriter& writer) const
dataSz += (entry.size + 63) & ~63;
atUint32 dataPad = ((dataSz + 63) & ~63) - dataSz;
dataSz += dataPad;
writer.writeUint32(dataSz);
writer.writeUint32Big(dataSz);
writer.seek(36, Athena::Current);
writer.writeUint32((atUint32)m_nameEntries.size());
writer.writeUint32Big((atUint32)m_nameEntries.size());
for (const NameEntry& entry : m_nameEntries)
entry.write(writer);
writer.seek(strgPad, Athena::Current);
writer.writeUint32((atUint32)m_entries.size());
writer.writeUint32Big((atUint32)m_entries.size());
for (const Entry& entry : m_entries)
{
Entry copy = entry;

View File

@ -8,11 +8,11 @@ namespace DNAMP3
void STRG::_read(Athena::io::IStreamReader& reader)
{
atUint32 langCount = reader.readUint32();
atUint32 strCount = reader.readUint32();
atUint32 langCount = reader.readUint32Big();
atUint32 strCount = reader.readUint32Big();
atUint32 nameCount = reader.readUint32();
atUint32 nameTableSz = reader.readUint32();
atUint32 nameCount = reader.readUint32Big();
atUint32 nameTableSz = reader.readUint32Big();
if (nameTableSz)
{
std::unique_ptr<uint8_t[]> nameTableBuf(new uint8_t[nameTableSz]);
@ -40,9 +40,9 @@ void STRG::_read(Athena::io::IStreamReader& reader)
std::unique_ptr<atUint32[]> strOffs(new atUint32[langCount * strCount]);
for (atUint32 l=0 ; l<langCount ; ++l)
{
reader.readUint32();
reader.readUint32Big();
for (atUint32 s=0 ; s<strCount ; ++s)
strOffs[l*strCount+s] = reader.readUint32();
strOffs[l*strCount+s] = reader.readUint32Big();
}
atUint64 strBase = reader.position();
@ -54,7 +54,7 @@ void STRG::_read(Athena::io::IStreamReader& reader)
for (atUint32 s=0 ; s<strCount ; ++s)
{
reader.seek(strBase + strOffs[l*strCount+s], Athena::Begin);
atUint32 len = reader.readUint32();
atUint32 len = reader.readUint32Big();
strs.emplace_back(reader.readString(len));
}
langs.emplace_back(readLangs[l], strs);
@ -68,15 +68,14 @@ void STRG::_read(Athena::io::IStreamReader& reader)
void STRG::read(Athena::io::IStreamReader& reader)
{
reader.setEndian(Athena::BigEndian);
atUint32 magic = reader.readUint32();
atUint32 magic = reader.readUint32Big();
if (magic != 0x87654321)
{
Log.report(LogVisor::Error, "invalid STRG magic");
return;
}
atUint32 version = reader.readUint32();
atUint32 version = reader.readUint32Big();
if (version != 3)
{
Log.report(LogVisor::Error, "invalid STRG version");
@ -154,23 +153,22 @@ void STRG::fromYAML(Athena::io::YAMLDocReader& reader)
void STRG::write(Athena::io::IStreamWriter& writer) const
{
writer.setEndian(Athena::BigEndian);
writer.writeUint32(0x87654321);
writer.writeUint32(3);
writer.writeUint32(langs.size());
writer.writeUint32Big(0x87654321);
writer.writeUint32Big(3);
writer.writeUint32Big(langs.size());
atUint32 strCount = STRG::count();
writer.writeUint32(strCount);
writer.writeUint32Big(strCount);
atUint32 nameTableSz = names.size() * 8;
for (const auto& name : names)
nameTableSz += name.first.size() + 1;
writer.writeUint32(names.size());
writer.writeUint32(nameTableSz);
writer.writeUint32Big(names.size());
writer.writeUint32Big(nameTableSz);
atUint32 offset = names.size() * 8;
for (const auto& name : names)
{
writer.writeUint32(offset);
writer.writeInt32(name.second);
writer.writeUint32Big(offset);
writer.writeInt32Big(name.second);
offset += name.first.size() + 1;
}
for (const auto& name : names)
@ -185,11 +183,11 @@ void STRG::write(Athena::io::IStreamWriter& writer) const
atUint32 langSz = 0;
for (const std::string& str : lang.second)
langSz += str.size() + 5;
writer.writeUint32(langSz);
writer.writeUint32Big(langSz);
for (const std::string& str : lang.second)
{
writer.writeUint32(offset);
writer.writeUint32Big(offset);
offset += str.size() + 5;
}
}
@ -200,13 +198,13 @@ void STRG::write(Athena::io::IStreamWriter& writer) const
{
if (s >= 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);
}
}