-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 77728ca
Showing
8 changed files
with
342 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
cmake_minimum_required(VERSION 3.27) | ||
project(Source2Schema) | ||
|
||
include("cmake/global-flags.cmake") | ||
if (MSVC) | ||
include("cmake/msvc-flags.cmake") | ||
endif() | ||
|
||
set_property(GLOBAL PROPERTY USE_FOLDERS ON) | ||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake") | ||
|
||
file(GLOB_RECURSE SOURCES "src/*.cpp") | ||
|
||
add_library(Source2Schema STATIC ${SOURCES}) | ||
|
||
target_include_directories(Source2Schema PRIVATE headers) | ||
|
||
target_compile_definitions(Source2Schema PRIVATE WIN32_LEAN_AND_MEAN) # Remove shit from Windows headers |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
# Source2 Schema Parser | ||
WIP Schema parsing for Source2 Engine games | ||
|
||
_Если че у меня фетиш на const_ | ||
|
||
### Advanced scopes | ||
Define `SCHEMA_CS2` if you need to parse matchmaking.dll scope | ||
|
||
### Example | ||
```cpp | ||
#include <SchemaSystem.h> | ||
|
||
const SchemaSystem* schemaSystem = SchemaSystem::Create(); | ||
const SchemaScope* scope = schemaSystem->Get<Scopes::Client>(); | ||
printf("Scope: %s\n", scope->Name()); | ||
|
||
const CUtlVector<const SchemaClass*> classes = scope->Classes(); | ||
printf("Classes: %zu\n", classes.Size); | ||
for (SIZE_T j = 0; j < classes.Size; j++) { | ||
const SchemaClass* pClass = classes[j]; | ||
PCSTR className = pClass->Name(); | ||
|
||
const std::vector<SchemaField> fields = pClass->Fields(); | ||
for (SIZE_T n = 0; n < fields.size(); n++) { | ||
const SchemaField field = fields[n]; | ||
PCSTR fieldName = field.Name(); | ||
|
||
printf("%s->%s = %X\n", className, fieldName, field.Offset()); | ||
} | ||
} | ||
``` | ||
### Pictures | ||
 |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
set(CMAKE_CXX_STANDARD 17) | ||
set(CMAKE_CXX_STANDARD_REQUIRED ON) | ||
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/dist") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
if (DEBUG) | ||
add_link_options("/DEBUG:FULL") # Bigger PDB information (for debugging) | ||
endif() | ||
add_link_options("/SUBSYSTEM:WINDOWS") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
#pragma once | ||
|
||
#include <Windows.h> | ||
|
||
typedef PVOID(*InterfaceInstanceFn)(); | ||
|
||
struct InterfaceEntry { | ||
InterfaceInstanceFn CreateFunction; | ||
PCSTR Name; | ||
InterfaceEntry* Next; | ||
}; | ||
|
||
template<typename T> | ||
__forceinline T* CreateInterface(const char* moduleName, const char* name) { | ||
// Also can find export using GetProcAddress and call - CreateInterface("SchemaSystem_001", nullptr); | ||
const HMODULE schemaSystemModuleHandle = GetModuleHandle(moduleName); | ||
const auto createInterfaceAddress = reinterpret_cast<ULONGLONG>(GetProcAddress(schemaSystemModuleHandle, "CreateInterface")); | ||
const ULONGLONG interfaces = createInterfaceAddress + *reinterpret_cast<int*>(createInterfaceAddress + 3) + 7; | ||
for (const InterfaceEntry* current = *reinterpret_cast<InterfaceEntry**>(interfaces); current; current = current->Next) | ||
if (strcmp(current->Name, name) == 0) | ||
return reinterpret_cast<T*>(current->CreateFunction()); | ||
|
||
return nullptr; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,164 @@ | ||
#pragma once | ||
|
||
#include "Interface.h" | ||
#include <type_traits> | ||
#include <exception> | ||
#include <vector> | ||
|
||
#define PADDING_INSERT(x, y) x ## y | ||
#define PADDING_DEFINE(x, y) PADDING_INSERT(x, y) | ||
#define PRIVATE_PADDING(size) private: \ | ||
BYTE PADDING_DEFINE(__pad_, __LINE__)[size]; | ||
#define PADDING(size) PRIVATE_PADDING(size) \ | ||
public: \ | ||
|
||
template<typename T> | ||
struct CUtlVector { | ||
public: | ||
T& operator[](unsigned int index) { | ||
return Buffer[index]; | ||
} | ||
|
||
T& operator[](unsigned int index) const { | ||
return Buffer[index]; | ||
} | ||
public: | ||
SIZE_T Size; | ||
T* Buffer; | ||
}; | ||
|
||
class SchemaField { | ||
public: | ||
PCSTR Name() const; | ||
|
||
PVOID Type() const; | ||
|
||
UINT Offset() const; | ||
|
||
UINT MetadataSize() const; | ||
|
||
PVOID Metadata() const; | ||
private: | ||
PCSTR name; | ||
PVOID type; | ||
UINT offset; | ||
UINT metadataSize; | ||
PVOID metadata; | ||
}; | ||
|
||
class SchemaClass { | ||
public: | ||
PCSTR Name() const; | ||
|
||
PCSTR ScopeName() const; | ||
|
||
UINT Size() const; | ||
|
||
std::vector<SchemaField> Fields() const; | ||
|
||
template<typename T> | ||
T Get(IN PCSTR name) const { | ||
SchemaField field{}; | ||
if (!FindField(name, &field)) | ||
return {}; | ||
|
||
if constexpr (std::is_base_of_v<SchemaField, T>) | ||
return field; | ||
else if (std::is_same_v<UINT, T>) | ||
return field.Offset(); | ||
else | ||
throw std::exception("Type is not supported! Use one of: SchemaField or unsigned int\n"); | ||
} | ||
private: | ||
bool FindField(IN const char* name, OUT SchemaField* field) const; | ||
private: | ||
PVOID vfptr; | ||
PCSTR name; | ||
PCSTR scopeName; | ||
UINT size; | ||
WORD fieldCount; | ||
WORD unknown0; | ||
WORD unknown1; | ||
WORD unknown2; | ||
UINT unknown3; | ||
SchemaField* declaredFields; | ||
}; | ||
|
||
class SchemaScope { | ||
public: | ||
PCSTR Name() const; | ||
|
||
const CUtlVector<const SchemaClass*> Classes() const; | ||
|
||
const SchemaClass* Get(IN const char* className) const; | ||
private: | ||
class SchemaDeclaredClass { | ||
public: | ||
constexpr SchemaClass* Class() const { | ||
return pClass; | ||
} | ||
private: | ||
PVOID vfptr; | ||
PCSTR name; | ||
PCSTR unknown0; | ||
PCSTR unknown1; | ||
SchemaClass* pClass; | ||
}; | ||
|
||
class SchemaDeclaredClassEntry { | ||
public: | ||
constexpr SchemaDeclaredClass* DeclaredClass() const { | ||
return declaredClass; | ||
} | ||
private: | ||
ULONGLONG hash[2]; | ||
SchemaDeclaredClass* declaredClass; | ||
}; | ||
private: | ||
PVOID vfptr; | ||
CHAR name[256]; | ||
PRIVATE_PADDING(0x338); | ||
SchemaDeclaredClassEntry* declaredClasses; | ||
PRIVATE_PADDING(0xE); | ||
WORD declaredClassesCount; | ||
}; | ||
|
||
enum class Scopes { | ||
Client, | ||
Engine2, | ||
SchemaSystem, | ||
Tier0, | ||
#if defined(SCHEMA_CS2) | ||
Matchmaking, | ||
#endif | ||
}; | ||
|
||
class SchemaSystem { | ||
public: | ||
CUtlVector<const SchemaScope*> Scopes() const; | ||
|
||
const SchemaScope* Get(IN const char* scopeName) const; | ||
|
||
template<enum Scopes scope> | ||
const SchemaScope* Get() const { | ||
if constexpr (scope == Scopes::Client) | ||
return Get("client.dll"); | ||
else if constexpr (scope == Scopes::Engine2) | ||
return Get("engine2.dll"); | ||
else if constexpr (scope == Scopes::Tier0) | ||
return Get("tier0.dll"); | ||
#if defined(SCHEMA_CS2) | ||
else if constexpr (scope == Scopes::Matchmaking) | ||
return Get("matchmaking.dll"); | ||
#endif | ||
else | ||
return nullptr; | ||
} | ||
private: | ||
PRIVATE_PADDING(0x188); // @ida: sigscan 41 0F B7 BD + 4 | ||
CUtlVector<const SchemaScope*> scopes{}; | ||
public: | ||
static const SchemaSystem* Create() { | ||
return CreateInterface<SchemaSystem>("schemasystem.dll", "SchemaSystem_001"); | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
#include "SchemaSystem.h" | ||
|
||
CUtlVector<const SchemaScope*> SchemaSystem::Scopes() const { | ||
return scopes; | ||
} | ||
|
||
const SchemaScope* SchemaSystem::Get(const char* scopeName) const { | ||
for (SIZE_T i = 0; i < scopes.Size; i++) | ||
if (strcmp(scopes[i]->Name(), scopeName) == 0) | ||
return scopes[i]; | ||
|
||
return nullptr; | ||
} | ||
|
||
PCSTR SchemaScope::Name() const { | ||
return name; | ||
} | ||
|
||
const CUtlVector<const SchemaClass*> SchemaScope::Classes() const { | ||
static CUtlVector<const SchemaClass*> classes{}; | ||
classes.Size = declaredClassesCount; | ||
classes.Buffer = new const SchemaClass*[declaredClassesCount]; | ||
|
||
for (WORD i = 0; i < declaredClassesCount; i++) { | ||
const SchemaDeclaredClassEntry entry = declaredClasses[i]; | ||
const SchemaDeclaredClass* declaredClass = entry.DeclaredClass(); | ||
SchemaClass* pClass = declaredClass->Class(); | ||
|
||
classes.Buffer[i] = pClass; | ||
} | ||
|
||
return classes; | ||
} | ||
|
||
const SchemaClass* SchemaScope::Get(const char* className) const { | ||
const CUtlVector<const SchemaClass*> classes = Classes(); | ||
for (SIZE_T i = 0; i < classes.Size; i++) | ||
if (strcmp(classes.Buffer[i]->Name(), className) == 0) | ||
return classes.Buffer[i]; | ||
|
||
return nullptr; | ||
} | ||
|
||
bool SchemaClass::FindField(const char* name, SchemaField* field) const { | ||
const std::vector<SchemaField> fields = Fields(); | ||
for (SIZE_T i = 0; i < fields.size(); i++) { | ||
if (strcmp(fields[i].Name(), name) == 0) { | ||
*field = fields[i]; | ||
return true; | ||
} | ||
} | ||
|
||
return false; | ||
} | ||
|
||
PCSTR SchemaClass::Name() const { | ||
return name; | ||
} | ||
|
||
PCSTR SchemaClass::ScopeName() const { | ||
return scopeName; | ||
} | ||
|
||
UINT SchemaClass::Size() const { | ||
return size; | ||
} | ||
|
||
std::vector<SchemaField> SchemaClass::Fields() const { | ||
std::vector<SchemaField> fields(fieldCount); | ||
|
||
for (WORD i = 0; i < fieldCount; i++) | ||
fields[i] = declaredFields[i]; | ||
|
||
return fields; | ||
} | ||
|
||
PCSTR SchemaField::Name() const { | ||
return name; | ||
} | ||
|
||
PVOID SchemaField::Type() const { | ||
return type; | ||
} | ||
|
||
UINT SchemaField::Offset() const { | ||
return offset; | ||
} | ||
|
||
UINT SchemaField::MetadataSize() const { | ||
return metadataSize; | ||
} | ||
|
||
PVOID SchemaField::Metadata() const { | ||
return metadata; | ||
} |