From 62e8066a63e2ce638a92aa584256985eee1720b6 Mon Sep 17 00:00:00 2001 From: Phillip Stephens Date: Sat, 19 Mar 2016 12:19:43 -0700 Subject: [PATCH] Initial CPlayerState RE --- DataSpec/DNAMP1/Tweaks/CTweakGame.hpp | 21 +++++ Editor/main.cpp | 1 - Runtime/CGameState.cpp | 2 +- Runtime/CGameState.hpp | 2 +- Runtime/CPlayerState.cpp | 127 +++++++++++++++++++++++++- Runtime/CPlayerState.hpp | 31 +++++-- Runtime/IOStreams.cpp | 63 +++++++------ Runtime/IOStreams.hpp | 38 +++++++- Runtime/MP1/CTweaks.cpp | 6 +- 9 files changed, 243 insertions(+), 48 deletions(-) diff --git a/DataSpec/DNAMP1/Tweaks/CTweakGame.hpp b/DataSpec/DNAMP1/Tweaks/CTweakGame.hpp index 4ceac5dda..ea5f4318e 100644 --- a/DataSpec/DNAMP1/Tweaks/CTweakGame.hpp +++ b/DataSpec/DNAMP1/Tweaks/CTweakGame.hpp @@ -13,6 +13,27 @@ struct CTweakGame : ITweakGame DECL_YAML String<-1> m_worldPrefix; String<-1> m_ruinsArea; // ???? + Value m_fov; + Value unknown1; + Value unknown2; + Value unknown3; + Value unknown4; + Value unknown5; + Value unknown6; + Value unknown7; + Value unknown8; + Value unknown9; + Value unknown10; + Value unknown11; + Value unknown12; + Value unknown13; + Value unknown14; + Value unknown15; + Value unknown16; + Value unknown17; + Value unknown18; + Value hardmodeDamageMult; + Value hardmodeWeaponMult; virtual const std::string& GetWorldPrefix() const { return m_worldPrefix; } CTweakGame(athena::io::IStreamReader& in) { this->read(in); } diff --git a/Editor/main.cpp b/Editor/main.cpp index df24afed5..80e6ca8e8 100644 --- a/Editor/main.cpp +++ b/Editor/main.cpp @@ -5,7 +5,6 @@ #include "Runtime/CGameAllocator.hpp" #include #include "ViewManager.hpp" -#include "Runtime/Particle/CElementGen.hpp" static logvisor::Module AthenaLog("Athena"); static void AthenaExc(athena::error::Level level, const char* file, diff --git a/Runtime/CGameState.cpp b/Runtime/CGameState.cpp index 18e92e328..f14f545c9 100644 --- a/Runtime/CGameState.cpp +++ b/Runtime/CGameState.cpp @@ -4,7 +4,7 @@ namespace urde { -CGameState::CGameState(CInputStream& stream) +CGameState::CGameState(CBitStreamReader& stream) : m_stateFlag(stream.readUint32Big()), m_playerState(stream), m_gameTime(stream.readFloatBig()) {} diff --git a/Runtime/CGameState.hpp b/Runtime/CGameState.hpp index 10d32051a..f996dd816 100644 --- a/Runtime/CGameState.hpp +++ b/Runtime/CGameState.hpp @@ -19,7 +19,7 @@ class CGameState CGameOptions m_gameOpts; public: CGameState() {} - CGameState(CInputStream& stream); + CGameState(CBitStreamReader& stream); void SetCurrentWorldId(unsigned int id, const std::string& name); CWorldTransManager& WorldTransitionManager() {return m_transManager;} }; diff --git a/Runtime/CPlayerState.cpp b/Runtime/CPlayerState.cpp index 8a155f72c..204e6e8f0 100644 --- a/Runtime/CPlayerState.cpp +++ b/Runtime/CPlayerState.cpp @@ -1,12 +1,135 @@ #include "CPlayerState.hpp" +#include "IOStreams.hpp" namespace urde { +/* TODO: Implement this properly */ +/* NOTE: This is only to be used as a reference, + * and is not indicative of how the actual format is structured + * a proper RE is still required! + */ -CPlayerState::CPlayerState(CInputStream& stream) -: m_staticIntf(5) +const u32 CPlayerState::PowerUpMaxes[41] = +{ 1, 1, 1, 1, 250, 1, 1, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 14, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 +}; + +const char* PowerUpNames[41]= { + "Unknown", + "Unknown", + "Unknown", + "Unknown", + "Missiles", + "Unknown", + "Unknown", + "Power Bombs", + "Unknown", + "Unknown", + "Unknown", + "Unknown", + "Unknown", + "Unknown", + "Unknown", + "Unknown", + "Unknown", + "Unknown", + "Unknown", + "Unknown", + "Unknown", + "Unknown", + "Unknown", + "Unknown", + "Energy Tanks", + "Unknown", + "Unknown", + "Unknown", + "Unknown", + "Unknown", + "Unknown", + "Unknown", + "Unknown", + "Unknown", + "Unknown", + "Unknown", + "Unknown", + "Unknown", + "Unknown", + "Unknown", + "Unknown", +}; +CPlayerState::CPlayerState(CBitStreamReader& in) + : x188_staticIntf(5) +{ + x0_24_ = true; + in.readUint32Big(); + in.readBool(); + in.readBool(); + in.readBool(); + + atInt8 data[0xAE]; + in.readBytesToBuf(data, 0xAE); + for (u32 k = 0; k < 3; k++) + { + printf("Game %i\n", k+1); + atInt8 save[0x3AC]; + in.readBytesToBuf(save, 0x3AC); + { + CBitStreamReader stream(save, 0x3AC); + + printf("Game State\n"); + for (u32 i = 0; i < 0x80; i++) + printf("%i\n", stream.ReadEncoded(8)); + + s32 tmp = stream.ReadEncoded(32); + printf("%i\n", tmp); + tmp = stream.ReadEncoded(1); + printf("%i\n", tmp); + tmp = stream.ReadEncoded(1); + printf("%i\n", tmp); + tmp = stream.ReadEncoded(32); + printf("%f\n", *reinterpret_cast(&tmp)); + tmp = stream.ReadEncoded(32); + printf("%f\n", *reinterpret_cast(&tmp)); + tmp = stream.ReadEncoded(32); + printf("%x\n", tmp); + + printf("PlayerState\n"); + x4_ = stream.ReadEncoded(0x20); + printf("%x\n", tmp); + tmp = stream.ReadEncoded(0x20); + printf("Base health %f\n", *reinterpret_cast(&tmp)); + xc_baseHealth = *reinterpret_cast(&tmp); + x8_ = stream.ReadEncoded(CBitStreamReader::GetBitCount(5)); + printf("%i\n", x8_); + x20_ = stream.ReadEncoded(CBitStreamReader::GetBitCount(4)); + printf("%i\n", x20_); + x24_powerups.resize(41); + printf("Powerups\n"); + for (u32 i = 0; i < x24_powerups.size(); ++i) + { + if (PowerUpMaxes[i] == 0) + continue; + + u32 a = stream.ReadEncoded(CBitStreamReader::GetBitCount(PowerUpMaxes[i])); + u32 b = stream.ReadEncoded(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++) + { + u32 tmp = stream.ReadEncoded(1); + printf("%i\n", tmp); + } + + tmp = stream.ReadEncoded(CBitStreamReader::GetBitCount(0x100)); + printf("%i\n", tmp); + tmp = stream.ReadEncoded(CBitStreamReader::GetBitCount(0x100)); + printf("%i\n", tmp); + } + } } } diff --git a/Runtime/CPlayerState.hpp b/Runtime/CPlayerState.hpp index ef3731509..abe232cfc 100644 --- a/Runtime/CPlayerState.hpp +++ b/Runtime/CPlayerState.hpp @@ -5,28 +5,43 @@ #include "CBasics.hpp" #include "CStaticInterference.hpp" #include "IOStreams.hpp" +#include "rstl.hpp" namespace urde { class CPlayerState { - CStaticInterference m_staticIntf; + static const u32 PowerUpMaxes[41]; class CPowerUp { - int m_a = 0; - int m_b = 0; + int x0_a = 0; + int x4_b = 0; public: CPowerUp() {} - CPowerUp(int a, int b) : m_a(a), m_b(b) {} + CPowerUp(int a, int b) : x0_a(a), x4_b(b) {} + }; + union + { + struct { bool x0_24_ : 1; bool x0_25_ : 1; bool x0_26_; }; + u32 dummy = 0; }; - CPowerUp m_powerups[29]; + u32 x4_ = 0; + u32 x8_ = 0; + float xc_baseHealth = 99.f; + float x10_ = 50.f; + u32 x14_ = 0; + u32 x18_ = x14_; + float x1c_ = 0.2f; + u32 x20_ = 0; + rstl::reserved_vector x24_powerups; + + CStaticInterference x188_staticIntf; public: - CPlayerState() : m_staticIntf(5) {} - CPlayerState(CInputStream& stream); + CPlayerState() : x188_staticIntf(5) { x0_24_ = true; } + CPlayerState(CBitStreamReader& stream); }; - } #endif // __PSHAG_CPLAYERSTATE_HPP__ diff --git a/Runtime/IOStreams.cpp b/Runtime/IOStreams.cpp index c1200edde..b03e43a8f 100644 --- a/Runtime/IOStreams.cpp +++ b/Runtime/IOStreams.cpp @@ -3,42 +3,49 @@ namespace urde { - -s32 DecryptionCtx::DecryptRead(CInputStream& in, s32 key) +/*! + * \brief CBitStreamReader::ReadBit + * Reads and decodes an encoded value from a bitstream. + * \param bitCount How many bits to read + * \return s32 The encoded value + */ +s32 CBitStreamReader::ReadEncoded(u32 bitCount) { - int ret = 0; - if (x20_encShift >= key) + s32 ret = 0; + if (bitCount < x20_bitOffset) { - int diff = x20_encShift - 0x20; - int baseVal = -1; - if (x20_encShift != 0x20) - baseVal = 1 << (x20_encShift - 1); - x20_encShift = key - x20_encShift; - ret = baseVal | (x1c_encVal >> diff); + u32 diff = 0x20 - bitCount; + u32 baseVal = -1; + if (x20_bitOffset != 0x20) + baseVal = (1 << bitCount) - 1; + x20_bitOffset -= bitCount; + ret = baseVal & (x1c_val >> diff); + x1c_val <<= bitCount; } else { - int diff = x20_encShift - key; - int rem = x20_encShift - 0x20; - int baseVal1 = -1; - if (x20_encShift != 0x20) - baseVal1 = 1 << (x20_encShift - 1); + u32 diff = bitCount - x20_bitOffset; + u32 baseVal = -1; + if (x20_bitOffset != 32) + baseVal = (1 << x20_bitOffset) - 1; - int bit = diff & 7; - x20_encShift = 0; - int count = (diff >> 3) + ((-bit | bit) >> 31); - int baseVal2 = (baseVal1 & (x1c_encVal >> rem)) << diff; - in.readBytesToBuf(&x1c_encVal, count); + u32 bit = diff & 7; + baseVal &= (x1c_val >> (32 - x20_bitOffset)); + baseVal <<= diff; + x20_bitOffset = 0; + u32 count = (diff >> 3) + ((-bit | bit) >> 31); + readUBytesToBuf(&x1c_val, count); + /* The game uses Big Endian, which doesn't work for us */ + /* Little Endian sucks */ + athena::utility::BigUint32(x1c_val); - int baseVal3 = -1; - if (diff != 0x20) - baseVal3 = 1 << (diff - 1); + u32 baseVal2 = -1; + if (diff != 32) + baseVal2 = (1 << diff) - 1; - int tmpShift = x20_encShift; - x20_encShift = (count << 3); - ret = baseVal2 | (baseVal3 & (x1c_encVal >> (diff - 0x20))) << tmpShift; - x20_encShift = diff - x20_encShift; - x1c_encVal = x1c_encVal >> diff; + ret = baseVal | (baseVal2 & (x1c_val >> (32 - diff))) << x20_bitOffset; + x20_bitOffset = (count << 3) - diff; + x1c_val <<= diff; } return ret; diff --git a/Runtime/IOStreams.hpp b/Runtime/IOStreams.hpp index cbc1586de..f88079ba4 100644 --- a/Runtime/IOStreams.hpp +++ b/Runtime/IOStreams.hpp @@ -12,11 +12,41 @@ namespace urde using CInputStream = athena::io::IStreamReader; using COutputStream = athena::io::IStreamWriter; -struct DecryptionCtx +struct CBitStreamReader : athena::io::MemoryCopyReader { - s32 x1c_encVal; - s32 x20_encShift; - s32 DecryptRead(CInputStream& in, s32 key); + u32 x1c_val = 0; + u32 x20_bitOffset = 0; +public: + static s32 GetBitCount(s32 unk) + { + s32 ret = 0; + while (unk != 0) + { + unk /= 2; + ret++; + } + + return ret; + } + + CBitStreamReader(const void* data, atUint64 length) + : MemoryCopyReader(data, length) + { + } + + CBitStreamReader(const std::string& filename) + : MemoryCopyReader(filename) + { + } + + atUint64 readUBytesToBuf(void *buf, atUint64 len) + { + x20_bitOffset = 0; + atUint64 tmp = MemoryCopyReader::readUBytesToBuf(buf, len); + return tmp; + } + + s32 ReadEncoded(u32 key); }; using CMemoryInStream = athena::io::MemoryReader; diff --git a/Runtime/MP1/CTweaks.cpp b/Runtime/MP1/CTweaks.cpp index 70d55c58c..df9fbe502 100644 --- a/Runtime/MP1/CTweaks.cpp +++ b/Runtime/MP1/CTweaks.cpp @@ -34,14 +34,14 @@ void CTweaks::RegisterTweaks() std::unique_ptr strm; strm.reset(loader.LoadNewResourceSync(IDFromFactory(factory, "Game"), nullptr)); - TOneStatic game(*strm); + TOneStatic game(*strm); g_tweakGame = game.GetAllocSpace(); strm.reset(loader.LoadNewResourceSync(IDFromFactory(factory, "Player"), nullptr)); - TOneStatic player(*strm); + TOneStatic player(*strm); g_tweakPlayer = player.GetAllocSpace(); strm.reset(loader.LoadNewResourceSync(IDFromFactory(factory, "PlayerControls"), nullptr)); - TOneStatic playerControl(*strm); + TOneStatic playerControl(*strm); g_tweakPlayerControl = playerControl.GetAllocSpace(); #endif }