Skip to content

Commit

Permalink
Update to x64
Browse files Browse the repository at this point in the history
  • Loading branch information
johnathon-walnut committed May 11, 2024
1 parent fa7be1a commit 7fc3970
Show file tree
Hide file tree
Showing 15 changed files with 293 additions and 108 deletions.
6 changes: 6 additions & 0 deletions skinchangerStandalone.sln
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,18 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "skinchangerStandalone", "sk
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{87CC1B6D-257A-4874-B962-E514D3B8B4F0}.Debug|x64.ActiveCfg = Debug|x64
{87CC1B6D-257A-4874-B962-E514D3B8B4F0}.Debug|x64.Build.0 = Debug|x64
{87CC1B6D-257A-4874-B962-E514D3B8B4F0}.Debug|x86.ActiveCfg = Debug|Win32
{87CC1B6D-257A-4874-B962-E514D3B8B4F0}.Debug|x86.Build.0 = Debug|Win32
{87CC1B6D-257A-4874-B962-E514D3B8B4F0}.Release|x64.ActiveCfg = Release|x64
{87CC1B6D-257A-4874-B962-E514D3B8B4F0}.Release|x64.Build.0 = Release|x64
{87CC1B6D-257A-4874-B962-E514D3B8B4F0}.Release|x86.ActiveCfg = Release|Win32
{87CC1B6D-257A-4874-B962-E514D3B8B4F0}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
Expand Down
6 changes: 4 additions & 2 deletions skinchangerStandalone.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -112,8 +112,9 @@
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;SKINCHANGERSTANDALONE_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
<LanguageStandard>stdcpp20</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
Expand All @@ -129,8 +130,9 @@
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;SKINCHANGERSTANDALONE_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
<LanguageStandard>stdcpp20</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
Expand Down
39 changes: 38 additions & 1 deletion src/app/Hooks/CL_CallPostDataUpdates.cpp
Original file line number Diff line number Diff line change
@@ -1,10 +1,47 @@
#include "../SkinChanger/SkinChanger.h"

#ifndef _WIN64
SIGNATURE(CL_CallPostDataUpdates, "engine.dll", "55 8B EC 8B 45 ? 53 33 DB");

HOOK(CL_CallPostDataUpdates, Sigs::CL_CallPostDataUpdates, void, __cdecl, void* u)
{
g_SkinChanger.ApplySkins();

CALL_ORIGINAL(u);
}
}
#else
// On x64, CL_CallPostDataUpdates is inlined into CL_ProcessPacketEntities - whereas, ClientDLL_FrameStageNotify is not - we can call this in the same place just before FRAME_NET_UPDATE_POSTDATAUPDATE_END - hoping this doesn't get hooked by anything else like CL_CallPostDataUpdates doesn't

/*
* engine/cl_ents_parse.cpp - line 664
*
ClientDLL_FrameStageNotify( FRAME_NET_UPDATE_POSTDATAUPDATE_START );
// call PostDataUpdate() for each entity
CL_CallPostDataUpdates( u );
ClientDLL_FrameStageNotify( FRAME_NET_UPDATE_POSTDATAUPDATE_END );
*
*
*/

SIGNATURE(ClientDLL_FrameStageNotify, "engine.dll", "4C 8B DC 56 48 83 EC");
SIGNATURE(CL_ProcessPacketEntitites_FSN_Call, "engine.dll", "E8 ? ? ? ? 48 8B 0D ? ? ? ? 48 8B 01 FF 50 ? 44 8B F0", 5); // Return address of FSN(3) call

#include <intrin.h>

HOOK(ClientDLL_FrameStageNotify, Sigs::ClientDLL_FrameStageNotify, void, __fastcall, int stage)
{
static bool done = false;
if (I::EngineClient->IsInGame() && !done)
{
g_Netvars.DumpTables();
done = true;
}

if (std::uintptr_t(_ReturnAddress()) == Sigs::CL_ProcessPacketEntitites_FSN_Call.Get())
g_SkinChanger.ApplySkins();

CALL_ORIGINAL(stage);
}
#endif
85 changes: 56 additions & 29 deletions src/app/SkinChanger/SkinChanger.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -625,24 +625,40 @@ enum ETFWeapons
Misc_t_Saxxy = 423,
};

//SIGNATURE(C_EconEntity_OnDataChanged, "client.dll", "55 8B EC 83 EC ? 53 56 8B 75 ? 8B D9 89 5D ? 85 F6 75 ? 8D 4B");
//SIGNATURE(ISchemaAttributeType_OnIterateAttributeValue, "client.dll", "55 8B EC 8B 4D ? 8B 45 ? 8B 11 FF 30 FF 75 ? 8B 42 ? FF D0 5D C2 ? ? CC CC CC CC CC CC CC 55 8B EC 8B 4D ? 8B 45 ? 51", 0);
//SIGNATURE(GetPaintKitMaterialOverride, "client.dll", "55 8B EC 83 EC ? 56 8B 75 ? 8D 45 ? 57 50");
//SIGNATURE(CTFItemDefinition_GetValidPaintKits, "client.dll", "55 8B EC 83 EC ? 53 8B D9 56 57 89 5D ? 80 BB ? ? ? ? ? 0F 85 ? ? ? ? C6 83");
//SIGNATURE(ItemSystem, "client.dll", "A1 ? ? ? ? 85 C0 75 ? 56");
#ifndef _WIN64
SIGNATURE(GetItemSchema, "client.dll", "E8 ? ? ? ? 83 C0 ? C3 CC");
SIGNATURE(CEconItemSchema_GetAttributeDefinition, "client.dll", "55 8B EC 83 EC ? 53 56 8B D9 8D 4D ? 57 E8 ? ? ? ? 8B 45");
SIGNATURE(CAttributeList_SetRuntimeAttributeValue, "client.dll", "55 8B EC 83 EC ? 33 C0 53 8B D9 56 57 8B 7D");
#else
SIGNATURE(GetItemSchema, "client.dll", "48 83 EC ? E8 ? ? ? ? 48 83 C0 ? 48 83 C4 ? C3 CC CC CC");
SIGNATURE(CEconItemSchema_GetAttributeDefinition, "client.dll", "89 54 24 ? 53 48 83 EC ? 48 8B D9 48 8D 54 24 ? 48 81 C1 ? ? ? ? E8 ? ? ? ? 8B D0 3B 83 ? ? ? ? 73 ? 8B 83 ? ? ? ? 83 F8 ? 74 ? 3B D0 7F ? 48 81 C3 ? ? ? ? 44 8B C2 83 FA ? 74 ? 48 8B 03 8B CA");
SIGNATURE(CAttributeList_SetRuntimeAttributeValue, "client.dll", "48 89 5C 24 ? 48 89 74 24 ? 48 89 7C 24 ? 55 48 8B EC 48 83 EC ? 44 8B 49");
#endif

/*
m_iAttributeDefinitionIndex = 0x8
m_iRawValue32 = 0x12
m_flValue = 0x12
m_nRefundableCurrency = 0x16
*/

class CAttribute
class CEconItemAttribute
{
public:
void* pad = 0;
#ifndef _WIN64
uint16_t m_iAttributeDefinitionIndex;
float m_flValue;
unsigned int pad2 = 0;
#else
unsigned int m_iAttributeDefinitionIndex;
#endif
union
{
int m_iRawValue32;
float m_flValue;
};
int m_nRefundableCurrency = 0;

inline CAttribute(uint16_t iAttributeDefinitionIndex, float flValue)
inline CEconItemAttribute(uint16_t iAttributeDefinitionIndex, float flValue)
{
m_iAttributeDefinitionIndex = iAttributeDefinitionIndex;
m_flValue = flValue;
Expand All @@ -653,21 +669,28 @@ class CAttributeList
{
public:
void* pad;
CUtlVector<CAttribute, CUtlMemory<CAttribute>> m_Attributes;
CUtlVector<CEconItemAttribute, CUtlMemory<CEconItemAttribute>> m_Attributes;
void* m_pManager;

inline void AddAttribute(int iIndex, float flValue)
{
if (m_Attributes.Count() > 14)
return;

CAttribute attr(iIndex, flValue);
CEconItemAttribute attr(iIndex, flValue);

m_Attributes.AddToTail(attr);
}

#ifndef _WIN64
using GetItemSchemaFN = void* (__cdecl*)();
using GetAttributeDefinitionFN = void* (__thiscall*)(void*, int);
using SetRuntimeAttributeValueFN = void(__thiscall*)(CAttributeList*, void*, float);
#else
using GetItemSchemaFN = void* (__fastcall*)();
using GetAttributeDefinitionFN = void* (__fastcall*)(void*, int);
using SetRuntimeAttributeValueFN = void(__fastcall*)(CAttributeList*, void*, float);
#endif

void SetAttribute(int index, float value)
{
Expand Down Expand Up @@ -723,12 +746,16 @@ void SkinChanger::ApplySkin(Weapon* pWeapon)
int& nWeaponIndex = pWeapon->m_iItemDefinitionIndex();
RedirectIndex(nWeaponIndex);

#ifndef _WIN64
auto attributeList = reinterpret_cast<CAttributeList*>(reinterpret_cast<std::uintptr_t>(pWeapon) + 0x9C4);
#else
auto attributeList = reinterpret_cast<CAttributeList*>(reinterpret_cast<std::uintptr_t>(pWeapon) + 3512);
#endif
if (!attributeList)
return;

#ifdef _DEBUG
if (attributeList->m_Attributes.Count() > 0 && m_Skins.find(nWeaponIndex) == m_Skins.end())
if (attributeList->m_Attributes.Count() > 0 && m_Skins.find(nWeaponIndex) == m_Skins.end())
{
// This weapon seems to already have a skin applied, but we don't have it in our map
// Let's print out what attributes it has
Expand All @@ -742,29 +769,29 @@ void SkinChanger::ApplySkin(Weapon* pWeapon)
#endif

auto PreFilledAttributeCount = [&](int index) -> int
{
// Most weapons have no attributes, some have more than one.
// Seems all snipers have this "no_jump" attribute
switch (index)
{
case Sniper_m_TheBazaarBargain:
case Sniper_m_SniperRifle:
case Sniper_m_SniperRifleR:
return 1;

default: return 0;
}
};

// If we have attributes, we've already applied the skin
// Most weapons have no attributes, some have more than one.
// Seems all snipers have this "no_jump" attribute
switch (index)
{
case Sniper_m_TheBazaarBargain:
case Sniper_m_SniperRifle:
case Sniper_m_SniperRifleR:
return 1;

default: return 0;
}
};

// If we have attributes, we've already applied all the attributes we want
if (attributeList->m_Attributes.Count() > PreFilledAttributeCount(m_nCurrentWeaponIndex))
return;

// Not a weapon we plan to skin
// Not a weapon we plan to add attributes to
if (m_Skins.find(nWeaponIndex) == m_Skins.end())
return;

// Apply the skin
// Apply the attributes if we have requested attributes for it
const auto& vecAttributes = m_Skins[nWeaponIndex].m_Attributes;
if (vecAttributes.empty())
return;
Expand Down Expand Up @@ -800,7 +827,7 @@ void SkinChanger::ApplySkins()

m_nCurrentWeaponIndex = nWeaponIndex;

auto m_hMyWeapons = pLocal->m_hMyWeapons();
const auto& m_hMyWeapons = pLocal->m_hMyWeapons();
for (int i = 0; m_hMyWeapons[i].IsValid(); i++)
{
auto pWeapon = m_hMyWeapons[i].Get();
Expand Down
16 changes: 10 additions & 6 deletions src/app/SkinChanger/SkinChanger.h
Original file line number Diff line number Diff line change
Expand Up @@ -95,13 +95,13 @@ class Weapon;

#define NETVAR(_name, type, table, name) inline type &_name() \
{ \
static int offset = g_Netvars.GetNetvar(table, name); \
return *reinterpret_cast<type *>(reinterpret_cast<DWORD>(this) + offset); \
static std::size_t offset = g_Netvars.GetNetvar(table, name); \
return *reinterpret_cast<type *>(reinterpret_cast<std::uintptr_t>(this) + offset); \
}

#define NETVAR_OFFSET(_name, type, name, offset) inline type &_name() \
{ \
return *reinterpret_cast<type *>(reinterpret_cast<DWORD>(this) + offset); \
return *reinterpret_cast<type *>(reinterpret_cast<std::uintptr_t>(this) + offset); \
}

#define MAX_WEAPONS 48
Expand All @@ -118,13 +118,17 @@ class Player
class Weapon
{
public:
// For wahtever reason CEconEntity -> m_iItemDefinitionIndex only has an offset of like 0x24 bytes
#ifndef _WIN64
// For whatever reason CEconEntity -> m_iItemDefinitionIndex only has an offset of like 0x24 bytes - netvars probably messed up :)
NETVAR_OFFSET(m_iItemDefinitionIndex, int, "m_iItemDefinitionIndex", 2364);
#else
NETVAR_OFFSET(m_iItemDefinitionIndex, int, "m_iItemDefinitionIndex", 3344);
#endif
};

class SkinChanger
{
std::unordered_map<int, SkinInfo> m_Skins;
std::unordered_map<int, SkinInfo> m_Skins = {};
bool m_bForceFullUpdate = false;
int m_nCurrentWeaponIndex = -1;
bool m_bInitialSkinLoad = false;
Expand All @@ -138,7 +142,7 @@ class SkinChanger

void SetAttribute(int index, std::string attributeStr, float value);
void RemoveAttribute(int index, std::string attributeStr);
inline const SkinInfo& GetSkinInfo(int index)
inline const SkinInfo& GetSkinInfo(int index)
{
if (m_Skins.find(index) == m_Skins.end())
{
Expand Down
5 changes: 5 additions & 0 deletions src/dllmain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,13 @@

DWORD WINAPI MainThread(LPVOID lpParam)
{
#ifndef _WIN64
while (!GetModuleHandle(L"mss32.dll"))
Sleep(500); // In the wise words of spook953: we sleepin'
#else
while (!GetModuleHandle(L"GameUI.dll")) //mss32.dll doesn't get loaded in 64-bit, this seems to be the next latest thing to get called before the game is fully loaded
Sleep(500);
#endif

g_App.Init();

Expand Down
12 changes: 8 additions & 4 deletions src/sdk/Interfaces/Interfaces.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,12 @@ Interface::Interface(const char* szName, void** pInterfacePtr, const char* szMod
}

SignatureInterface::SignatureInterface(const char* szName, void** pInterfacePtr, const char* szModule,
const char* szSignature, size_t nDereferenceCount, size_t nOffset) : Interface(szName, pInterfacePtr, szModule)
const char* szSignature, size_t nDereferenceCount, size_t nOffset, bool bRelative) : Interface(szName, pInterfacePtr, szModule)
{
this->m_szSignature = szSignature;
this->m_nDereferenceCount = nDereferenceCount;
this->m_nOffset = nOffset;
this->m_bRelative = bRelative;
}

VersionInterface::VersionInterface(const char* szName, void** pInterfacePtr, const char* szModule, const char* szVersion) : Interface(szName, pInterfacePtr, szModule)
Expand Down Expand Up @@ -43,14 +44,17 @@ void Interfaces::Init()

if (auto signatureInterface = dynamic_cast<SignatureInterface*>(pInterface))
{
auto dwAddress = g_Memory.FindSignature(pInterface->m_szModule, signatureInterface->m_szSignature);
if (!dwAddress)
auto pAddress = g_Memory.FindSignature(pInterface->m_szModule, signatureInterface->m_szSignature);
if (!pAddress)
{
printf("Failed to find %s in %s\n", signatureInterface->m_szName, signatureInterface->m_szModule);
exit(EXIT_FAILURE);
}

*pInterface->m_pInterfacePtr = reinterpret_cast<void*>(dwAddress + signatureInterface->m_nOffset);
if (signatureInterface->m_bRelative)
pAddress = pAddress + 7u + *reinterpret_cast<std::int32_t*>(pAddress + 3u);

*pInterface->m_pInterfacePtr = reinterpret_cast<void*>(pAddress + signatureInterface->m_nOffset);

for (size_t dereference = 0; dereference < signatureInterface->m_nDereferenceCount; dereference++)
*pInterface->m_pInterfacePtr = *reinterpret_cast<void**>(*pInterface->m_pInterfacePtr);
Expand Down
7 changes: 4 additions & 3 deletions src/sdk/Interfaces/Interfaces.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,10 @@ class SignatureInterface : public Interface
size_t m_nOffset = 0x0;
size_t m_nDereferenceCount = 0x0;
const char* m_szSignature = nullptr;
bool m_bRelative = false;

public:
SignatureInterface(const char* szName, void** pInterfacePtr, const char* szModule, const char* szSignature, size_t nDereferenceCount = 0x0, size_t nOffset = 0x0);
SignatureInterface(const char* szName, void** pInterfacePtr, const char* szModule, const char* szSignature, size_t nDereferenceCount = 0x0, size_t nOffset = 0x0, bool bRelative = false);
};

class VersionInterface : public Interface
Expand Down Expand Up @@ -66,10 +67,10 @@ namespace _I \
inline VersionInterface name##_Initializer(#name, (void**)&I::name, module, version); \
}

#define SIGNATURE_INTERFACE(name, type, module, signature, dereferenceCount, offset) namespace I { \
#define SIGNATURE_INTERFACE(name, type, module, signature, dereferenceCount, offset, ...) namespace I { \
inline type name = nullptr; \
} \
namespace _I \
{ \
inline SignatureInterface name##_Initializer(#name, (void**)&I::name, module, signature, dereferenceCount, offset); \
inline SignatureInterface name##_Initializer(#name, (void**)&I::name, module, signature, dereferenceCount, offset, __VA_ARGS__); \
}
9 changes: 9 additions & 0 deletions src/sdk/Maths.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ namespace Maths
{
inline void SinCos(float radians, float* sine, float* cosine)
{
#ifndef _WIN64
_asm
{
fld DWORD PTR[radians]
Expand All @@ -24,11 +25,19 @@ namespace Maths
fstp DWORD PTR[edx]
fstp DWORD PTR[eax]
}
#else
* sine = sin(radians);
*cosine = cos(radians);
#endif
}
inline double __declspec (naked) __fastcall FastSqrt(double n)
{
#ifndef _WIN64
_asm fld qword ptr[esp + 4]
_asm fsqrt
_asm ret 8
#else
return sqrt(n);
#endif
}
}
Loading

0 comments on commit 7fc3970

Please sign in to comment.