diff --git a/DataSpec/DNAMP1/ANIM.cpp b/DataSpec/DNAMP1/ANIM.cpp
index c0835ee95..738b5479e 100644
--- a/DataSpec/DNAMP1/ANIM.cpp
+++ b/DataSpec/DNAMP1/ANIM.cpp
@@ -287,40 +287,82 @@ void ANIM::ANIM2::read(athena::io::IStreamReader& reader)
bones.reserve(head.boneChannelCount);
channels.clear();
channels.reserve(head.boneChannelCount);
- atUint16 keyframeCount = 0;
- for (size_t b=0 ; b
> 8;
+ chan.q[0] = desc.QinitRX & 0xff;
+ chan.i[1] = atInt32(desc.QinitRY) >> 8;
+ chan.q[1] = desc.QinitRY & 0xff;
+ chan.i[2] = atInt32(desc.QinitRZ) >> 8;
+ chan.q[2] = desc.QinitRZ & 0xff;
+ }
+ keyframeCount = std::max(keyframeCount, desc.keyCount1);
+
+ if (desc.keyCount2)
+ {
+ channels.emplace_back();
+ DNAANIM::Channel& chan = channels.back();
+ chan.type = DNAANIM::Channel::Type::Translation;
+ chan.id = desc.id;
+ chan.i[0] = atInt32(desc.QinitTX) >> 8;
+ chan.q[0] = desc.QinitTX & 0xff;
+ chan.i[1] = atInt32(desc.QinitTY) >> 8;
+ chan.q[1] = desc.QinitTY & 0xff;
+ chan.i[2] = atInt32(desc.QinitTZ) >> 8;
+ chan.q[2] = desc.QinitTZ & 0xff;
+ }
}
- keyframeCount = std::max(keyframeCount, desc.keyCount1);
-
- if (desc.keyCount2)
+ }
+ else
+ {
+ for (size_t b=0 ; b& bone : bones)
+
+ if (m_version == 3)
{
- 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)
+ for (const std::pair& bone : bones)
{
+ ChannelDescPC desc;
+ desc.id = bone.first;
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.keyCount1 = keyframeCount;
+ desc.QinitRX = (chan.i[0] << 8) | chan.q[0];
+ desc.QinitRY = (chan.i[1] << 8) | chan.q[1];
+ desc.QinitRZ = (chan.i[2] << 8) | chan.q[2];
+ if (bone.second)
+ {
+ DNAANIM::Channel& chan = *cit++;
+ desc.keyCount2 = keyframeCount;
+ desc.QinitTX = (chan.i[0] << 8) | chan.q[0];
+ desc.QinitTY = (chan.i[1] << 8) | chan.q[1];
+ desc.QinitTZ = (chan.i[2] << 8) | chan.q[2];
+ }
+ desc.write(writer);
+ }
+ }
+ else
+ {
+ 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);
}
- desc.write(writer);
}
writer.writeUBytes(bsData.get(), bsSize);
@@ -414,11 +482,23 @@ size_t ANIM::ANIM2::binarySize(size_t __isz) const
__isz = head.binarySize(__isz);
__isz = keyBmp.binarySize(__isz);
__isz += 8;
- for (const std::pair& bone : bones)
+ if (m_version == 3)
{
- __isz += 17;
- if (bone.second)
- __isz += 9;
+ for (const std::pair& bone : bones)
+ {
+ __isz += 24;
+ if (bone.second)
+ __isz += 12;
+ }
+ }
+ else
+ {
+ for (const std::pair& bone : bones)
+ {
+ __isz += 17;
+ if (bone.second)
+ __isz += 9;
+ }
}
return __isz + DNAANIM::ComputeBitstreamSize(frames.size(), channels);
diff --git a/DataSpec/DNAMP1/ANIM.hpp b/DataSpec/DNAMP1/ANIM.hpp
index 31a70e765..7f11ebf47 100644
--- a/DataSpec/DNAMP1/ANIM.hpp
+++ b/DataSpec/DNAMP1/ANIM.hpp
@@ -141,6 +141,58 @@ struct ANIM : BigDNA
return __isz;
}
};
+
+ struct ChannelDescPC : BigDNA
+ {
+ Delete expl;
+ Value id = 0;
+ Value keyCount1 = 0;
+ Value QinitRX = 0;
+ Value QinitRY = 0;
+ Value QinitRZ = 0;
+ Value keyCount2 = 0;
+ Value QinitTX = 0;
+ Value QinitTY = 0;
+ Value QinitTZ = 0;
+
+ void read(athena::io::IStreamReader& reader)
+ {
+ id = reader.readUint32Big();
+ keyCount1 = reader.readUint32Big();
+ QinitRX = reader.readUint32Big();
+ QinitRY = reader.readUint32Big();
+ QinitRZ = reader.readUint32Big();
+ keyCount2 = reader.readUint32Big();
+ if (keyCount2)
+ {
+ QinitTX = reader.readUint32Big();
+ QinitTY = reader.readUint32Big();
+ QinitTZ = reader.readUint32Big();
+ }
+ }
+ void write(athena::io::IStreamWriter& writer) const
+ {
+ writer.writeUint32Big(id);
+ writer.writeUint32Big(keyCount1);
+ writer.writeUint32Big(QinitRX);
+ writer.writeUint32Big(QinitRY);
+ writer.writeUint32Big(QinitRZ);
+ writer.writeUint32Big(keyCount2);
+ if (keyCount2)
+ {
+ writer.writeUint32Big(QinitTX);
+ writer.writeUint32Big(QinitTY);
+ writer.writeUint32Big(QinitTZ);
+ }
+ }
+ size_t binarySize(size_t __isz) const
+ {
+ __isz += 24;
+ if (keyCount2)
+ __isz += 12;
+ return __isz;
+ }
+ };
};
std::unique_ptr m_anim;
diff --git a/Runtime/Character/CFBStreamedAnimReader.cpp b/Runtime/Character/CFBStreamedAnimReader.cpp
index 60b16e0a9..c122c91e0 100644
--- a/Runtime/Character/CFBStreamedAnimReader.cpp
+++ b/Runtime/Character/CFBStreamedAnimReader.cpp
@@ -3,6 +3,19 @@
namespace urde
{
+void CFBStreamedAnimReaderTotals::Allocate(u32 chanCount)
+{
+ u32 chan16 = chanCount * 16;
+ u32 chan2 = chanCount * 2;
+ u32 chan32 = chanCount * 32;
+
+ x0_buffer.reset(new u8[chan16 + chanCount + chan2 + chan32]);
+ x4_first16 = x0_buffer.get();
+ x8_second1 = x4_first16 + chan16;
+ xc_third2 = x8_second1 + chanCount;
+ x10_fourth32 = xc_third2 + chan2;
+}
+
CFBStreamedAnimReaderTotals::CFBStreamedAnimReaderTotals(const CFBStreamedCompression& source)
{
const CFBStreamedCompression::Header* header =
@@ -16,13 +29,12 @@ CFBStreamedAnimReaderTotals::CFBStreamedAnimReaderTotals(const CFBStreamedCompre
const u8* chans = reinterpret_cast(bitmap + bitmapWordCount + 1);
u32 boneChanCount = *reinterpret_cast(chans);
x24_boneChanCount = boneChanCount;
+ Allocate(x24_boneChanCount);
}
CFBStreamedPairOfTotals::CFBStreamedPairOfTotals(const TSubAnimTypeToken& source)
: x0_source(source), xc_rotsAndOffs(source->xc_rotsAndOffs.get()), x14_(*source), x3c_(*source)
{
- x0_source.Lock();
-
const u32* bitmap = reinterpret_cast(source->xc_rotsAndOffs.get() + 9);
u32 bitmapWordCount = (bitmap[0] + 31) / 32;
@@ -30,15 +42,29 @@ CFBStreamedPairOfTotals::CFBStreamedPairOfTotals(const TSubAnimTypeToken(chans);
chans += 4;
- for (int b=0 ; bm_pc)
{
- chans += 15;
+ for (int b=0 ; b(chans);
- chans += 2;
+ u32 tCount = *reinterpret_cast(chans);
+ chans += 4;
+ if (tCount)
+ chans += 12;
+ }
+ }
+ else
+ {
+ for (int b=0 ; b(chans);
+ chans += 2;
+ if (tCount)
+ chans += 9;
+ }
}
x88_ = chans;
@@ -54,7 +80,6 @@ CFBStreamedAnimReader::CFBStreamedAnimReader(const TSubAnimTypeToken>(source), time),
x54_source(source), x7c_(source), x114_(x7c_.x10_ ? x7c_.x14_ : x7c_.x3c_)
{
- x54_source.Lock();
x64_steadyStateInfo.x64_duration = x54_source->GetAnimationDuration();
x64_steadyStateInfo.x6c_curRootOffset = x54_source->x14_rootOffset;
diff --git a/Runtime/Character/CFBStreamedAnimReader.hpp b/Runtime/Character/CFBStreamedAnimReader.hpp
index 1926876b5..f06970fad 100644
--- a/Runtime/Character/CFBStreamedAnimReader.hpp
+++ b/Runtime/Character/CFBStreamedAnimReader.hpp
@@ -24,15 +24,16 @@ public:
class CFBStreamedAnimReaderTotals
{
std::unique_ptr x0_buffer;
- u32 x4_ = 0;
- u32 x8_ = 0;
- u32 xc_ = 0;
- u32 x10_ = 0;
+ u8* x4_first16;
+ u8* x8_second1;
+ u8* xc_third2;
+ u8* x10_fourth32;
u32 x14_rotDiv;
float x18_transMult;
u32 x1c_ = 0;
bool x20_ = false;
u32 x24_boneChanCount;
+ void Allocate(u32 chanCount);
public:
CFBStreamedAnimReaderTotals(const CFBStreamedCompression& source);
};
diff --git a/Runtime/Character/CFBStreamedCompression.cpp b/Runtime/Character/CFBStreamedCompression.cpp
index 047a95e19..8f36d74de 100644
--- a/Runtime/Character/CFBStreamedCompression.cpp
+++ b/Runtime/Character/CFBStreamedCompression.cpp
@@ -3,7 +3,8 @@
namespace urde
{
-CFBStreamedCompression::CFBStreamedCompression(CInputStream& in, IObjectStore& objStore)
+CFBStreamedCompression::CFBStreamedCompression(CInputStream& in, IObjectStore& objStore, bool pc)
+: m_pc(pc)
{
x0_scratchSize = in.readUint32Big();
x4_evnt = in.readUint32Big();
@@ -47,28 +48,46 @@ u8* CFBStreamedCompression::ReadBoneChannelDescriptors(u8* out, CInputStream& in
*reinterpret_cast(out) = boneChanCount;
out += 4;
- for (int b=0 ; b(out) = in.readUint32Big();
- out += 4;
-
- *reinterpret_cast(out) = in.readUint16Big();
- out += 2;
-
- for (int i=0 ; i<3 ; ++i)
+ for (int b=0 ; b(out) = in.readInt16Big();
- out += 2;
- *reinterpret_cast(out) = in.readUByte();
- out += 1;
+ *reinterpret_cast(out) = in.readUint32Big();
+ out += 4;
+
+ *reinterpret_cast(out) = in.readUint32Big();
+ out += 4;
+
+ for (int i=0 ; i<3 ; ++i)
+ {
+ *reinterpret_cast(out) = in.readUint32Big();
+ out += 4;
+ }
+
+ u32 tCount = in.readUint32Big();
+ *reinterpret_cast(out) = tCount;
+ out += 4;
+
+ if (tCount)
+ {
+ for (int i=0 ; i<3 ; ++i)
+ {
+ *reinterpret_cast(out) = in.readUint32Big();
+ out += 4;
+ }
+ }
}
-
- u16 tCount = in.readUint16Big();
- *reinterpret_cast(out) = tCount;
- out += 2;
-
- if (tCount)
+ }
+ else
+ {
+ for (int b=0 ; b(out) = in.readUint32Big();
+ out += 4;
+
+ *reinterpret_cast(out) = in.readUint16Big();
+ out += 2;
+
for (int i=0 ; i<3 ; ++i)
{
*reinterpret_cast(out) = in.readInt16Big();
@@ -76,6 +95,21 @@ u8* CFBStreamedCompression::ReadBoneChannelDescriptors(u8* out, CInputStream& in
*reinterpret_cast(out) = in.readUByte();
out += 1;
}
+
+ u16 tCount = in.readUint16Big();
+ *reinterpret_cast(out) = tCount;
+ out += 2;
+
+ if (tCount)
+ {
+ for (int i=0 ; i<3 ; ++i)
+ {
+ *reinterpret_cast(out) = in.readInt16Big();
+ out += 2;
+ *reinterpret_cast(out) = in.readUByte();
+ out += 1;
+ }
+ }
}
}
@@ -87,22 +121,47 @@ u32 CFBStreamedCompression::ComputeBitstreamWords(const u8* chans)
u32 boneChanCount = *reinterpret_cast(chans);
chans += 4;
- u16 keyCount = *reinterpret_cast(chans);
+ u32 keyCount;
u32 totalBits = 0;
- for (u32 c=0 ; c(chans + 0x8);
- totalBits += *reinterpret_cast(chans + 0xb);
- totalBits += *reinterpret_cast(chans + 0xe);
- u16 tKeyCount = *reinterpret_cast(chans + 0xf);
- chans += 0x11;
- if (tKeyCount)
+ keyCount = *reinterpret_cast(chans + 0x4);
+ for (u32 c=0 ; c(chans) & 0xff;
+ totalBits += *reinterpret_cast(chans + 0x4) & 0xff;
+ totalBits += *reinterpret_cast(chans + 0x8) & 0xff;
+ u32 tKeyCount = *reinterpret_cast(chans + 0xc);
+ chans += 0x10;
+ if (tKeyCount)
+ {
+ totalBits += *reinterpret_cast(chans) & 0xff;
+ totalBits += *reinterpret_cast(chans + 0x4) & 0xff;
+ totalBits += *reinterpret_cast(chans + 0x8) & 0xff;
+ chans += 0xc;
+ }
+ }
+ }
+ else
+ {
+ keyCount = *reinterpret_cast(chans + 0x4);
+ for (u32 c=0 ; c(chans + 0x2);
totalBits += *reinterpret_cast(chans + 0x5);
totalBits += *reinterpret_cast(chans + 0x8);
- chans += 0x9;
+ u16 tKeyCount = *reinterpret_cast(chans + 0x9);
+ chans += 0xb;
+ if (tKeyCount)
+ {
+ totalBits += *reinterpret_cast(chans + 0x2);
+ totalBits += *reinterpret_cast(chans + 0x5);
+ totalBits += *reinterpret_cast(chans + 0x8);
+ chans += 0x9;
+ }
}
}
diff --git a/Runtime/Character/CFBStreamedCompression.hpp b/Runtime/Character/CFBStreamedCompression.hpp
index cff98c756..8e6f08cd4 100644
--- a/Runtime/Character/CFBStreamedCompression.hpp
+++ b/Runtime/Character/CFBStreamedCompression.hpp
@@ -51,17 +51,18 @@ class CFBStreamedCompression
}
};
+ bool m_pc;
u32 x0_scratchSize;
ResId x4_evnt;
TLockedToken x8_evntToken;
std::unique_ptr xc_rotsAndOffs;
zeus::CVector3f x14_rootOffset;
- static u8* ReadBoneChannelDescriptors(u8* out, CInputStream& in);
- static std::unique_ptr GetRotationsAndOffsets(u32 words, CInputStream& in);
- static u32 ComputeBitstreamWords(const u8* chans);
+ u8* ReadBoneChannelDescriptors(u8* out, CInputStream& in);
+ u32 ComputeBitstreamWords(const u8* chans);
+ std::unique_ptr GetRotationsAndOffsets(u32 words, CInputStream& in);
public:
- CFBStreamedCompression(CInputStream& in, IObjectStore& objStore);
+ CFBStreamedCompression(CInputStream& in, IObjectStore& objStore, bool pc);
CCharAnimTime GetAnimationDuration() const { return reinterpret_cast(xc_rotsAndOffs.get())->duration; }
const TLockedToken& GetPOIToken() const { return x8_evntToken; }
};
diff --git a/Runtime/Character/IAnimReader.hpp b/Runtime/Character/IAnimReader.hpp
index e0d5275e5..912140ee0 100644
--- a/Runtime/Character/IAnimReader.hpp
+++ b/Runtime/Character/IAnimReader.hpp
@@ -38,7 +38,7 @@ struct CSteadyStateAnimInfo
};
template
-using TSubAnimTypeToken = TCachedToken;
+using TSubAnimTypeToken = TLockedToken;
class IAnimReader
{