#include "CFBStreamedCompression.hpp" namespace urde { CFBStreamedCompression::CFBStreamedCompression(CInputStream& in, IObjectStore& objStore, bool pc) : m_pc(pc) { x0_scratchSize = in.readUint32Big(); x4_evnt = in.readUint32Big(); xc_rotsAndOffs = GetRotationsAndOffsets(x0_scratchSize / 4 + 1, in); if (x4_evnt) x8_evntToken = objStore.GetObj(SObjectTag{FOURCC('EVNT'), x4_evnt}); } const u32* CFBStreamedCompression::GetTimes() const { return reinterpret_cast(xc_rotsAndOffs.get() + 9); } const u8* CFBStreamedCompression::GetPerChannelHeaders() const { const u32* bitmap = reinterpret_cast(xc_rotsAndOffs.get() + 9); u32 bitmapWordCount = (bitmap[0] + 31) / 32; return reinterpret_cast(bitmap + bitmapWordCount + 1); } const u8* CFBStreamedCompression::GetBitstreamPointer() const { const u32* bitmap = reinterpret_cast(xc_rotsAndOffs.get() + 9); u32 bitmapWordCount = (bitmap[0] + 31) / 32; const u8* chans = reinterpret_cast(bitmap + bitmapWordCount + 1); u32 boneChanCount = *reinterpret_cast(chans); chans += 4; if (m_pc) { for (int b=0 ; b(chans); chans += 4; if (tCount) chans += 12; } } else { for (int b=0 ; b(chans); chans += 2; if (tCount) chans += 9; } } return chans; } std::unique_ptr CFBStreamedCompression::GetRotationsAndOffsets(u32 words, CInputStream& in) { std::unique_ptr ret(new u32[words]); Header head; head.read(in); *reinterpret_cast(ret.get()) = head; u32* bitmapOut = &ret[9]; u32 bitmapBitCount = in.readUint32Big(); bitmapOut[0] = bitmapBitCount; u32 bitmapWordCount = (bitmapBitCount + 31) / 32; for (u32 i=0 ; i(bitmapOut + bitmapWordCount + 1); u8* bs = ReadBoneChannelDescriptors(chans, in); u32 bsWords = ComputeBitstreamWords(chans); u32* bsPtr = reinterpret_cast(bs); for (u32 w=0 ; w(out) = boneChanCount; out += 4; if (m_pc) { for (int b=0 ; b(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; } } } } 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(); out += 2; *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; } } } } return out; } u32 CFBStreamedCompression::ComputeBitstreamWords(const u8* chans) { u32 boneChanCount = *reinterpret_cast(chans); chans += 4; u32 keyCount; u32 totalBits = 0; if (m_pc) { 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); 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; } } } return (totalBits * keyCount + 31) / 32; } }