diff --git a/Runtime/CPlayerState.cpp b/Runtime/CPlayerState.cpp index 204e6e8f0..18e30f1e2 100644 --- a/Runtime/CPlayerState.cpp +++ b/Runtime/CPlayerState.cpp @@ -77,34 +77,50 @@ CPlayerState::CPlayerState(CBitStreamReader& in) in.readBytesToBuf(save, 0x3AC); { CBitStreamReader stream(save, 0x3AC); + std::string filename = athena::utility::sprintf("Game%i.dat", k + 1); + CBitStreamWriter w{filename}; printf("Game State\n"); for (u32 i = 0; i < 0x80; i++) - printf("%i\n", stream.ReadEncoded(8)); + { + u32 tmp = stream.ReadEncoded(8); + printf("%i\n", tmp); + w.WriteEncoded(tmp, 8); + } s32 tmp = stream.ReadEncoded(32); + w.WriteEncoded(tmp, 0x20); printf("%i\n", tmp); tmp = stream.ReadEncoded(1); + w.WriteEncoded(tmp, 1); printf("%i\n", tmp); tmp = stream.ReadEncoded(1); + w.WriteEncoded(tmp, 1); printf("%i\n", tmp); tmp = stream.ReadEncoded(32); + w.WriteEncoded(tmp, 0x20); printf("%f\n", *reinterpret_cast(&tmp)); tmp = stream.ReadEncoded(32); + w.WriteEncoded(tmp, 0x20); printf("%f\n", *reinterpret_cast(&tmp)); tmp = stream.ReadEncoded(32); printf("%x\n", tmp); + w.WriteEncoded(tmp, 0x20); printf("PlayerState\n"); x4_ = stream.ReadEncoded(0x20); + w.WriteEncoded(x4_, 0x20); printf("%x\n", tmp); tmp = stream.ReadEncoded(0x20); printf("Base health %f\n", *reinterpret_cast(&tmp)); xc_baseHealth = *reinterpret_cast(&tmp); + w.WriteEncoded(tmp, 0x20); x8_ = stream.ReadEncoded(CBitStreamReader::GetBitCount(5)); printf("%i\n", x8_); + w.WriteEncoded(x8_, CBitStreamReader::GetBitCount(5)); x20_ = stream.ReadEncoded(CBitStreamReader::GetBitCount(4)); printf("%i\n", x20_); + w.WriteEncoded(x20_, CBitStreamReader::GetBitCount(4)); x24_powerups.resize(41); printf("Powerups\n"); for (u32 i = 0; i < x24_powerups.size(); ++i) @@ -114,20 +130,27 @@ CPlayerState::CPlayerState(CBitStreamReader& in) u32 a = stream.ReadEncoded(CBitStreamReader::GetBitCount(PowerUpMaxes[i])); u32 b = stream.ReadEncoded(CBitStreamReader::GetBitCount(PowerUpMaxes[i])); + w.WriteEncoded(a, CBitStreamReader::GetBitCount(PowerUpMaxes[i])); + w.WriteEncoded(b, CBitStreamReader::GetBitCount(PowerUpMaxes[i])); x24_powerups[i] = CPowerUp(a, b); printf("%2i(%15s): a=%i b=%i\n", i, PowerUpNames[i], a, b); } - for (u32 i = 0; i < 0x34e; i++) + for (u32 i = 0; i < 0x304 * 8; i++) { u32 tmp = stream.ReadEncoded(1); printf("%i\n", tmp); + w.WriteEncoded(tmp, 1); } tmp = stream.ReadEncoded(CBitStreamReader::GetBitCount(0x100)); printf("%i\n", tmp); + w.WriteEncoded(tmp, CBitStreamReader::GetBitCount(0x100)); tmp = stream.ReadEncoded(CBitStreamReader::GetBitCount(0x100)); printf("%i\n", tmp); + w.WriteEncoded(tmp, CBitStreamReader::GetBitCount(0x100)); + + w.save(); } } } diff --git a/Runtime/IOStreams.cpp b/Runtime/IOStreams.cpp index b03e43a8f..b77f30dbf 100644 --- a/Runtime/IOStreams.cpp +++ b/Runtime/IOStreams.cpp @@ -29,12 +29,9 @@ s32 CBitStreamReader::ReadEncoded(u32 bitCount) if (x20_bitOffset != 32) baseVal = (1 << x20_bitOffset) - 1; - u32 bit = diff & 7; - baseVal &= (x1c_val >> (32 - x20_bitOffset)); - baseVal <<= diff; + baseVal = (baseVal & (x1c_val >> (32 - x20_bitOffset))) << diff; x20_bitOffset = 0; - u32 count = (diff >> 3) + ((-bit | bit) >> 31); - readUBytesToBuf(&x1c_val, count); + readUBytesToBuf(&x1c_val, 4); /* The game uses Big Endian, which doesn't work for us */ /* Little Endian sucks */ athena::utility::BigUint32(x1c_val); @@ -44,13 +41,47 @@ s32 CBitStreamReader::ReadEncoded(u32 bitCount) baseVal2 = (1 << diff) - 1; ret = baseVal | (baseVal2 & (x1c_val >> (32 - diff))) << x20_bitOffset; - x20_bitOffset = (count << 3) - diff; + x20_bitOffset = (4 << 3) - diff; x1c_val <<= diff; } return ret; } + +void CBitStreamWriter::WriteEncoded(u32 val, u32 bitCount) +{ + if (x18_bitOffset >= bitCount) + { + int baseVal = -1; + if (bitCount != 32) + baseVal = (1 << bitCount) - 1; + x14_val |= (val & baseVal) << (x18_bitOffset - bitCount); + x18_bitOffset -= bitCount; + } + else + { + u32 diff = bitCount - x18_bitOffset; + u32 baseVal = -1; + if (x18_bitOffset != 32) + baseVal = (1 << x18_bitOffset) - 1; + + x14_val |= (val >> diff) & baseVal; + x18_bitOffset = 0; + u32 tmp = x14_val; + athena::utility::BigUint32(tmp); + writeBytes(&tmp, 4); + + u32 rem = 32 - diff; + baseVal = -1; + if (diff != 32) + baseVal = (1 << diff) - 1; + + x14_val = (val & baseVal) << rem; + x18_bitOffset -= diff; + } +} + class CZipSupport { public: diff --git a/Runtime/IOStreams.hpp b/Runtime/IOStreams.hpp index f88079ba4..7dbd259e6 100644 --- a/Runtime/IOStreams.hpp +++ b/Runtime/IOStreams.hpp @@ -17,12 +17,12 @@ struct CBitStreamReader : athena::io::MemoryCopyReader u32 x1c_val = 0; u32 x20_bitOffset = 0; public: - static s32 GetBitCount(s32 unk) + static s32 GetBitCount(s32 maxVal) { s32 ret = 0; - while (unk != 0) + while (maxVal != 0) { - unk /= 2; + maxVal /= 2; ret++; } @@ -49,6 +49,32 @@ public: s32 ReadEncoded(u32 key); }; +class CBitStreamWriter : public athena::io::MemoryCopyWriter +{ +private: + u32 x14_val = 0; + u32 x18_bitOffset = 32; +public: + static inline u32 GetBitCount(u32 maxVal) { return CBitStreamReader::GetBitCount(maxVal); } + + CBitStreamWriter(atUint8* data = nullptr, atUint64 length=0x10) + : MemoryCopyWriter(data, length) + {} + + CBitStreamWriter(const std::string& filename) + : MemoryCopyWriter(filename) + {} + + void writeUBytes(const atUint8 *data, atUint64 len) + { + x14_val = 0; + x18_bitOffset = 0x20; + MemoryCopyWriter::writeUBytes(data, len); + } + + void WriteEncoded(u32 val, u32 bitCount); +}; + using CMemoryInStream = athena::io::MemoryReader; class CZipInputStream : public CInputStream diff --git a/hecl b/hecl index e9b881d42..5a83ba09d 160000 --- a/hecl +++ b/hecl @@ -1 +1 @@ -Subproject commit e9b881d42b42d0efa0cde85cfc0e029777df18a7 +Subproject commit 5a83ba09d46970db3452ab3084ff0b469b746490