aboutsummaryrefslogtreecommitdiff
path: root/NorthstarDLL
diff options
context:
space:
mode:
Diffstat (limited to 'NorthstarDLL')
-rw-r--r--NorthstarDLL/NorthstarDLL.vcxproj1
-rw-r--r--NorthstarDLL/NorthstarDLL.vcxproj.filters3
-rw-r--r--NorthstarDLL/filesystem.h29
-rw-r--r--NorthstarDLL/pch.h1
-rw-r--r--NorthstarDLL/r2engine.h40
-rw-r--r--NorthstarDLL/r2server.h24
-rw-r--r--NorthstarDLL/structs.h63
7 files changed, 106 insertions, 55 deletions
diff --git a/NorthstarDLL/NorthstarDLL.vcxproj b/NorthstarDLL/NorthstarDLL.vcxproj
index 9d66b854..c1532157 100644
--- a/NorthstarDLL/NorthstarDLL.vcxproj
+++ b/NorthstarDLL/NorthstarDLL.vcxproj
@@ -558,6 +558,7 @@
<ClInclude Include="sourceinterface.h" />
<ClInclude Include="squirrel.h" />
<ClInclude Include="exploitfixes_utf8parser.cpp" />
+ <ClInclude Include="structs.h" />
<ClInclude Include="squirrelautobind.h" />
<ClInclude Include="tier0.h" />
<ClInclude Include="vector.h" />
diff --git a/NorthstarDLL/NorthstarDLL.vcxproj.filters b/NorthstarDLL/NorthstarDLL.vcxproj.filters
index 024274cf..8ff5f461 100644
--- a/NorthstarDLL/NorthstarDLL.vcxproj.filters
+++ b/NorthstarDLL/NorthstarDLL.vcxproj.filters
@@ -1494,6 +1494,9 @@
<ClInclude Include="keyvalues.h">
<Filter>Header Files</Filter>
</ClInclude>
+ <ClInclude Include="structs.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
<ClInclude Include="loghooks.h">
<Filter>Header Files\Console</Filter>
</ClInclude>
diff --git a/NorthstarDLL/filesystem.h b/NorthstarDLL/filesystem.h
index c326b419..9a22893a 100644
--- a/NorthstarDLL/filesystem.h
+++ b/NorthstarDLL/filesystem.h
@@ -5,25 +5,32 @@
typedef void* FileHandle_t;
#pragma pack(push, 1)
-struct VPKFileEntry
+
+// clang-format off
+OFFSET_STRUCT(VPKFileEntry)
{
- char* directory;
- char* filename;
- char* extension;
- unsigned char unknown[0x38];
+ STRUCT_SIZE(0x44);
+ FIELDS(0x0,
+ char* directory;
+ char* filename;
+ char* extension;
+ )
};
+// clang-format on
#pragma pack(pop)
#pragma pack(push, 1)
+// clang-format off
struct VPKData
{
- unsigned char unknown[5];
- char path[255];
- unsigned char unknown2[0x134];
- int32_t numEntries;
- unsigned char unknown3[12];
- VPKFileEntry* entries;
+ STRUCT_SIZE(0x50);
+ FIELDS(0x0,
+ char* directory;
+ char* filename;
+ char* extension;
+ )
};
+// clang-format on
#pragma pack(pop)
enum SearchPathAdd_t
diff --git a/NorthstarDLL/pch.h b/NorthstarDLL/pch.h
index e07c5598..824aaee8 100644
--- a/NorthstarDLL/pch.h
+++ b/NorthstarDLL/pch.h
@@ -20,6 +20,7 @@
namespace fs = std::filesystem;
+#include "structs.h"
#include "color.h"
#include "spdlog/spdlog.h"
#include "logging.h"
diff --git a/NorthstarDLL/r2engine.h b/NorthstarDLL/r2engine.h
index e428e1cc..2614b4cc 100644
--- a/NorthstarDLL/r2engine.h
+++ b/NorthstarDLL/r2engine.h
@@ -157,39 +157,17 @@ namespace R2
READY_REMOTE
};
-#pragma pack(push, 1)
- struct CBaseClient // 0x2D728 bytes
+ // clang-format off
+ OFFSET_STRUCT(CBaseClient)
{
- char pad0[0x16];
-
- // +0x16
- char m_Name[64];
-
- // +0x56
- char pad1[0x202];
-
- KeyValues* m_ConVars; // this is a KeyValues* object but not got that struct mapped out atm
-
- char pad2[0x240];
-
- // +0x4A0
- ePersistenceReady m_iPersistenceReady;
- // +0x4A1
-
- char pad3[0x59];
-
- // +0x4FA
- char m_PersistenceBuffer[PERSISTENCE_MAX_SIZE];
-
- char pad4[0x1239];
-
- // +0xF500
- char m_UID[32];
- // +0xF520
-
- char pad5[0x1E208];
+ STRUCT_SIZE(0x2D728)
+ FIELD(0x16, char m_Name[64])
+ FIELD(0x258, KeyValues* m_ConVars)
+ FIELD(0x4A0, ePersistenceReady m_iPersistenceReady)
+ FIELD(0x4FA, char m_PersistenceBuffer[PERSISTENCE_MAX_SIZE])
+ FIELD(0xF500, char m_UID[32])
};
-#pragma pack(pop)
+ // clang-format on
extern CBaseClient* g_pClientArray;
diff --git a/NorthstarDLL/r2server.h b/NorthstarDLL/r2server.h
index 235dde7f..aadfdefe 100644
--- a/NorthstarDLL/r2server.h
+++ b/NorthstarDLL/r2server.h
@@ -9,22 +9,20 @@ namespace R2
class CBaseEntity;
extern CBaseEntity* (*Server_GetEntityByIndex)(int index);
-#pragma pack(push, 1)
- struct CBasePlayer
+ // clang-format off
+ OFFSET_STRUCT(CBasePlayer)
{
- char pad[0x58];
- uint32_t m_nPlayerIndex;
+ STRUCT_SIZE(0x1D02);
+ FIELD(0x58, uint32_t m_nPlayerIndex)
- // +0x5C
- char pad1[0x1C34];
- bool m_hasBadReputation; // 0x1C90
- char m_communityName[64]; // 0x1C91
- char m_communityClanTag[16]; // 0x1CD1
- char m_factionName[16]; // 0x1CE1
- char m_hardwareIcon[16]; // 0x1CF1
- bool m_happyHourActive; // 0x1D01
+ FIELD(0x1C90, bool m_hasBadReputation)
+ FIELD(0x1C91, char m_communityName[64])
+ FIELD(0x1CD1, char m_communityClanTag[16])
+ FIELD(0x1CE1, char m_factionName[16])
+ FIELD(0x1CF1, char m_hardwareIcon[16])
+ FIELD(0x1D01, bool m_happyHourActive)
};
-#pragma pack(pop)
+ // clang-format on
extern CBasePlayer*(__fastcall* UTIL_PlayerByIndex)(int playerIndex);
} // namespace R2
diff --git a/NorthstarDLL/structs.h b/NorthstarDLL/structs.h
new file mode 100644
index 00000000..939fd302
--- /dev/null
+++ b/NorthstarDLL/structs.h
@@ -0,0 +1,63 @@
+#pragma once
+//clang-format off
+// About this file:
+// This file contains several macros used to define reversed structs
+// The reason we use these macros is to make it easier to update existing structs
+// when new fields are reversed
+// This means we dont have to manually add padding, and recalculate when updating
+
+// Technical note:
+// While functionally, these structs act like a regular struct, they are actually
+// defined as unions with anonymous structs in them.
+// This means that each field is essentially an offset into a union.
+// We acknowledge that this goes against C++'s active-member guideline for unions
+// However, this is not such a big deal here as these structs will not be constructed
+
+// Usage:
+// To use these macros, define a struct like so:
+/*
+OFFSET_STRUCT(Name)
+{
+ STRUCT_SIZE(0x100) // Total in-memory struct size
+ FIELD(0x0, int field) // offset, signature
+}
+*/
+
+#define OFFSET_STRUCT(name) union name
+#define STRUCT_SIZE(size) char __size[size];
+#define STRUCT_FIELD_OFFSET(offset, signature) \
+ struct \
+ { \
+ char CONCAT2(pad, __LINE__)[offset]; \
+ signature; \
+ };
+
+// Special case for a 0-offset field
+#define STRUCT_FIELD_NOOFFSET(offset, signature) signature;
+
+// Based on: https://stackoverflow.com/questions/11632219/c-preprocessor-macro-specialisation-based-on-an-argument
+// Yes, this is hacky, but it works quite well actually
+// This basically makes sure that when the offset is 0x0, no padding field gets generated
+#define OFFSET_0x0 ()
+
+#define IIF(c) CONCAT2(IIF_, c)
+#define IIF_0(t, ...) __VA_ARGS__
+#define IIF_1(t, ...) t
+
+#define PROBE(x) x, 1
+
+#define MSVC_VA_ARGS_WORKAROUND(define, args) define args
+#define CHECK(...) MSVC_VA_ARGS_WORKAROUND(CHECK_N, (__VA_ARGS__, 0))
+#define CHECK_N(x, n, ...) n
+
+#define DO_PROBE(offset) PROBE_PROXY(OFFSET_##offset) // concatenate prefix with offset
+#define PROBE_PROXY(...) PROBE_PRIMITIVE(__VA_ARGS__) // expand arguments
+#define PROBE_PRIMITIVE(x) PROBE_COMBINE_##x // merge
+#define PROBE_COMBINE_(...) PROBE(~) // if merge successful, expand to probe
+
+#define IS_0(offset) CHECK(DO_PROBE(offset))
+
+#define FIELD(offset, signature) IIF(IS_0(offset))(STRUCT_FIELD_NOOFFSET, STRUCT_FIELD_OFFSET)(offset, signature)
+#define FIELDS FIELD
+
+//clang-format on