diff --git a/config/SZBE69/symbols.txt b/config/SZBE69/symbols.txt index 98c7cf61b..cdefaf267 100644 --- a/config/SZBE69/symbols.txt +++ b/config/SZBE69/symbols.txt @@ -39031,7 +39031,7 @@ __ct__16CharBonesSamplesFv = .text:0x804B1B20; // type:function size:0x64 __dt__16CharBonesSamplesFv = .text:0x804B1B84; // type:function size:0x7C Set__16CharBonesSamplesFRCQ211stlpmtx_std77vector>iQ29CharBones15CompressionType = .text:0x804B1C00; // type:function size:0x80 Clone__16CharBonesSamplesFRC16CharBonesSamples = .text:0x804B1C80; // type:function size:0x68 -fn_804B1CE8 = .text:0x804B1CE8; // type:function size:0x14 +SetStartFromRawData__16CharBonesSamplesFi = .text:0x804B1CE8; // type:function size:0x14 NumSamples__16CharBonesSamplesCFv = .text:0x804B1CFC; // type:function size:0x8 AllocateSize__16CharBonesSamplesFv = .text:0x804B1D04; // type:function size:0x10 FracToSample__16CharBonesSamplesCFPf = .text:0x804B1D14; // type:function size:0x160 diff --git a/src/system/char/CharBones.cpp b/src/system/char/CharBones.cpp index a453693a1..f28b8dd29 100644 --- a/src/system/char/CharBones.cpp +++ b/src/system/char/CharBones.cpp @@ -1,5 +1,10 @@ #include "char/CharBones.h" #include "char/CharClip.h" +#include "decomp.h" +#include "math/Mtx.h" +#include "math/Rot.h" +#include "math/Vec.h" +#include "utl/MakeString.h" #include "utl/Symbols.h" void TestDstComplain(Symbol s) { @@ -16,7 +21,7 @@ CharBones::CharBones() : mCompression(kCompressNone), mStart(0), mTotalSize(0) { } CharBones::Type CharBones::TypeOf(Symbol s) { - for (const char *p = s.Str(); p != 0; p++) { + for (const char *p = s.Str(); *p != 0; p++) { if (*p == '.') { switch (p[1]) { case 'p': @@ -26,9 +31,10 @@ CharBones::Type CharBones::TypeOf(Symbol s) { case 'q': return TYPE_QUAT; case 'r': { + // check if rot is x, y, or z unsigned char next = p[3]; - if (next + 0x88U <= 2) - return (Type)(next - 0x75); + if ((unsigned char)(next - 'x') <= 2) + return (Type)((char)next - 'u'); } default: break; @@ -100,32 +106,20 @@ void CharBones::ListBones(std::list &bones) const { void CharBones::Zero() { memset(mStart, 0, mTotalSize); } -// enum CompressionType { -// kCompressNone, -// kCompressRots, -// kCompressVects, -// kCompressQuats, -// kCompressAll -// }; - int CharBones::TypeSize(int i) const { - if (i < 2) { - if (mCompression < kCompressVects) - return 0xC; - else - return 6; - } - if (i != 2) { - if (mCompression == kCompressNone) - return 4; - else - return 2; + if(i > 1U){ + if(i != 2){ + if(mCompression != kCompressNone) return 2; + else return 4; + } + else { + if(mCompression >= kCompressQuats) return 4; + else if(mCompression != kCompressNone) return 8; + else return 16; + } } - if (mCompression > kCompressVects) - return 4; - if (mCompression == kCompressNone) - return 0x10; - return 8; + else if(mCompression >= kCompressVects) return 6; + else return 12; } int CharBones::FindOffset(Symbol s) const { @@ -173,12 +167,64 @@ void CharBones::SetCompression(CompressionType ty) { } } +DECOMP_FORCEACTIVE(CharBones, "!mCompression && !bones.mCompression") + +const char* CharBones::StringVal(Symbol s){ + void* ptr = FindPtr(s); + CharBones::Type t = TypeOf(s); + if(t < 2){ + if(mCompression >= 2){ + Vector3 vshort((short*)ptr); + return MakeString("%g %g %g", vshort.x, vshort.y, vshort.z); + } + else { + Vector3* vptr = (Vector3*)vptr; + return MakeString("%g %g %g", vptr->x, vptr->y, vptr->z); + } + } + else if(t == 2){ + Hmx::Quat q; + Hmx::Quat* qPtr = (Hmx::Quat*)ptr; + if(mCompression >= 3){ + ByteQuat* bqPtr = (ByteQuat*)qPtr; + bqPtr->ToQuat(q); + } + else if(mCompression != kCompressNone){ + ShortQuat* sqPtr = (ShortQuat*)qPtr; + sqPtr->ToQuat(q); + } + else q = *qPtr; + Vector3 v40; + MakeEuler(q, v40); + v40 *= RAD2DEG; + return MakeString("quat(%g %g %g %g) euler(%g %g %g)", q.x, q.y, q.z, q.w, v40.x, v40.y, v40.z); + } + else { + float floatVal; + if(mCompression != kCompressNone){ + floatVal = *((short*)ptr) * 0.00061035156f; + } + else { + floatVal = *((float*)ptr); + } + floatVal *= RAD2DEG; + if(mCompression != kCompressNone){ + return MakeString("deg %g raw %d", floatVal, *((short*)ptr)); + } + else { + return MakeString("deg %g rad %g", floatVal, *((float*)ptr)); + } + } +} + void CharBones::Print() { for (std::vector::iterator it = mBones.begin(); it != mBones.end(); ++it) { - MILO_LOG("%s %.2f: %s\n", (*it).name, (*it).weight, StringVal((*it).name)); + MILO_LOG("%s %.2f: %s\n", it->name, it->weight, StringVal(it->name)); } } +DECOMP_FORCEACTIVE(CharBones, "!mCompression", "false", "newSize == 4", "oldSize == 2", "end >= start") + void CharBones::ScaleAdd(CharClip *clip, float f1, float f2, float f3) { clip->ScaleAdd(*this, f1, f2, f3); } diff --git a/src/system/char/CharBones.h b/src/system/char/CharBones.h index 4fc84b0fa..d58d31eeb 100644 --- a/src/system/char/CharBones.h +++ b/src/system/char/CharBones.h @@ -73,6 +73,7 @@ class CharBones { char *RotYOffset() const { return mStart + mRotYOffset; } char *RotZOffset() const { return mStart + mRotZOffset; } char *EndOffset() const { return mStart + mEndOffset; } + char* SetStart(char* ptr){ mStart = ptr; } static Type TypeOf(Symbol); static const char *SuffixOf(Type); diff --git a/src/system/char/CharBonesSamples.cpp b/src/system/char/CharBonesSamples.cpp index e41c1d470..b2c0df614 100644 --- a/src/system/char/CharBonesSamples.cpp +++ b/src/system/char/CharBonesSamples.cpp @@ -1,5 +1,10 @@ #include "char/CharBonesSamples.h" +#include "char/CharBones.h" #include "decomp.h" +#include "math/Mtx.h" +#include "os/Debug.h" +#include "utl/BinStream.h" +#include "utl/MemMgr.h" #include "utl/Symbols.h" int gVer; @@ -12,6 +17,11 @@ DECOMP_FORCEACTIVE( "CharBonesSamples are already compressed, can't remove bones." ) +DECOMP_FORCEACTIVE(CharBonesSamples, + "FracToSample: sample is %d, clip only has %d samples, frac was %g, is %g", + "FracToSample: frac is %g, outside of 0 and 1" +) + CharBonesSamples::CharBonesSamples() : mNumSamples(0), mPreviewSample(0), mRawData(0) {} CharBonesSamples::~CharBonesSamples() { _MemFree(mRawData); } @@ -34,10 +44,9 @@ void CharBonesSamples::Clone(const CharBonesSamples &samp) { mFrames = samp.mFrames; } -#pragma push -#pragma force_active on -inline int CharBonesSamples::AllocateSize() { return mTotalSize * mNumSamples; } -#pragma pop +FORCE_LOCAL_INLINE +int CharBonesSamples::AllocateSize() { return mTotalSize * mNumSamples; } +END_FORCE_LOCAL_INLINE void CharBonesSamples::RotateBy(CharBones &bones, int i) { mStart = &mRawData[mTotalSize * i]; @@ -63,7 +72,7 @@ void CharBonesSamples::ScaleAddSample(CharBones &bones, float f1, int i, float f } void CharBonesSamples::Print() { - MILO_LOG( + TheDebug << MakeString( "samples: %d size: %d address: %x compression %d\n", mNumSamples, AllocateSize(), @@ -107,11 +116,159 @@ void CharBonesSamples::Load(BinStream &bs) { LoadData(bs); } +void CharBonesSamples::ReadCounts(BinStream& bs, int i2){ + int i = 0; + int numTypesToRead = Min(7, i2); + for(; i < numTypesToRead; i++){ + bs >> mCounts[i]; + } + for(int numTypesRead = i; numTypesRead < i2; numTypesRead++){ + int tmp; + bs >> tmp; + MILO_ASSERT((tmp - mCounts[NUM_TYPES - 1]) == 0, 0x2B2); + } + for(; i < 7; i++){ + mCounts[i] = 0; + } +} + +void CharBonesSamples::LoadHeader(BinStream& bs){ + _MemFree(mRawData); + int numBones; bs >> numBones; + mBones.resize(numBones); + if(gVer > 0xA){ + for(int i = 0; i < numBones; i++){ + bs >> mBones[i]; + } + } + else { + for(int i = 0; i < numBones; i++){ + bs >> mBones[i].name; + } + } + + if(gVer > 9){ + ReadCounts(bs, gVer > 0xF ? 7 : 10); + bs >> (int&)mCompression; + int numSamples; + bs >> numSamples; + MILO_ASSERT(numSamples < 32767, 0x2D7); + mNumSamples = numSamples; + } + else { + int i; + if (gVer > 5) { + int count; + if (gVer > 7) { + count = 9; + } else { + count = 10; + if (gVer > 6) + count = 6; + } + for(i = 0; i < count; i++){ + int sp14; + bs >> sp14; + } + bs >> (int&)mCompression; + int numSamples; + bs >> numSamples; + MILO_ASSERT(numSamples < 32767, 0x2F1); + mNumSamples = numSamples; + } + else { + int numSamples; + bs >> numSamples; + MILO_ASSERT(numSamples < 32767, 0x2FC); + mNumSamples = numSamples; + if(gVer > 3){ + bs >> (int&)mCompression; + } + } + for(i = 0; i < 7; i++){ + mCounts[i] = 0; + } + for(i = 0; i < mBones.size(); i++){ + mCounts[CharBones::TypeOf(mBones[i].name) + 1]++; + } + for(i = 1; i < 7; i++){ + mCounts[i] += mCounts[i-1]; + } + } + + if(gVer > 0xB){ + bs >> mFrames; + } + else mFrames.clear(); + RecomputeSizes(); + mRawData = (char*)_MemAlloc(AllocateSize(), 0); +} + +void CharBonesSamples::LoadData(BinStream& bs){ + if(gVer == 0xE){ + bool x; bs >> x; + } + for(int i = 0; i < mNumSamples; i++){ + SetStartFromRawData(Min(i, mNumSamples - 1)); + + if(mCompression >= kCompressVects){ + short* offset = (short*)QuatOffset(); + for(short* p = (short*)Start(); p < offset; p += 3){ + bs >> p[0] >> p[1] >> p[2]; + } + } + else { + Vector3* offset = (Vector3*)QuatOffset(); + for(Vector3* p = (Vector3*)Start(); p < offset; p++){ + bs >> *p; + } + } + + if(mCompression >= kCompressQuats){ + char* offset = RotXOffset(); + for(char* p = QuatOffset(); p < offset; p += 4){ + bs >> p[0] >> p[1] >> p[2] >> p[3]; + } + } + else if(mCompression != kCompressNone){ + short* offset = (short*)RotXOffset(); + for(short* p = (short*)QuatOffset(); p < offset; p += 4){ + bs >> p[0] >> p[1] >> p[2] >> p[3]; + } + } + else { + Hmx::Quat* offset = (Hmx::Quat*)RotXOffset(); + for(Hmx::Quat* p = (Hmx::Quat*)QuatOffset(); p < offset; p++){ + bs >> *p; + } + } + + if(mCompression != kCompressNone){ + short* offset = (short*)EndOffset(); + for(short* p = (short*)RotXOffset(); p < offset; p++){ + bs >> *p; + } + } + else { + float* offset = (float*)EndOffset(); + for(float* p = (float*)RotXOffset(); p < offset; p++){ + bs >> *p; + } + } + + if((i & 0x7F) == 0x7F){ + while(bs.Eof() == TempEof){ + Timer::Sleep(0); + } + } + } +} + void CharBonesSamples::SetPreview(int i) { int tmp = Clamp(0, mNumSamples - 1, i); MILO_ASSERT(mPreviewSample < 32767, 0x38B); mPreviewSample = tmp; - mStart = &mRawData[mTotalSize * tmp]; + mStart = &mRawData[mTotalSize * mPreviewSample]; } BEGIN_PROPSYNCS(CharBonesSamples) diff --git a/src/system/char/CharBonesSamples.h b/src/system/char/CharBonesSamples.h index ff791f089..1d2284c66 100644 --- a/src/system/char/CharBonesSamples.h +++ b/src/system/char/CharBonesSamples.h @@ -26,6 +26,18 @@ class CharBonesSamples : public CharBones { static void SetVer(int); int NumSamples() const { return mNumSamples; } + void SetStartFromRawData(int idx){ + SetStart(&mRawData[mTotalSize * idx]); + } + // set mStart to mRawData[mTotalSize * 2]; + +// void fn_804B1CE8(int param_1,int param_2) + +// { +// fn_8034D25C(param_1,*(param_1 + 0x54) + *(param_1 + 0x4c) * param_2); +// return; +// } + short mNumSamples; // 0x50 short mPreviewSample; // 0x52 char *mRawData; // 0x54 diff --git a/src/system/math/Mtx.h b/src/system/math/Mtx.h index ae0fa42f1..eca6bbee5 100644 --- a/src/system/math/Mtx.h +++ b/src/system/math/Mtx.h @@ -238,6 +238,17 @@ class ShortQuat { x = y = z = 0; w = 32767; } + void ToQuat(Hmx::Quat& q) const { + q.Set(x * 0.000030518509f, y * 0.000030518509f, z * 0.000030518509f, w * 0.000030518509f); + } +}; + +class ByteQuat { +public: + char x, y, z, w; + void ToQuat(Hmx::Quat& q) const { + q.Set(x * 0.0078740157f, y * 0.0078740157f, z * 0.0078740157f, w * 0.0078740157f); + } }; class TransformNoScale { diff --git a/src/system/math/Rot.h b/src/system/math/Rot.h index 24ce48da4..cd9fbbf9b 100644 --- a/src/system/math/Rot.h +++ b/src/system/math/Rot.h @@ -26,6 +26,7 @@ void MakeRotQuatUnitX(const Vector3 &, Hmx::Quat &); float GetXAngle(const Hmx::Matrix3 &); float GetYAngle(const Hmx::Matrix3 &); float GetZAngle(const Hmx::Matrix3 &); +void MakeEuler(const Hmx::Quat&, Vector3&); TextStream &operator<<(TextStream &ts, const Hmx::Quat &v); TextStream &operator<<(TextStream &ts, const Vector3 &v); diff --git a/src/system/math/Vec.h b/src/system/math/Vec.h index 162b7a65f..af6ec73b0 100644 --- a/src/system/math/Vec.h +++ b/src/system/math/Vec.h @@ -74,6 +74,14 @@ class Vector3 { Vector3() {} Vector3(float f1, float f2, float f3) : x(f1), y(f2), z(f3) {} // Vector3(const Vector3& v) : x(v.x), y(v.y), z(v.z) {} + + // used during decompression of CharBones vectors + Vector3(short* s){ + x = s[0] * 0.000030518509f * 1300.0f; + y = s[1] * 0.000030518509f * 1300.0f; + z = s[2] * 0.000030518509f * 1300.0f; + } + void Set(float f1, float f2, float f3) { x = f1; y = f2;