2025-07-29 20:23:06 +03:00

252 lines
8.6 KiB
C++

// used: [d3d] api
#include <d3d11.h>
#include "interfaces.h"
// used: findpattern, callvirtual, getvfunc...
#include "../utilities/memory.h"
// used: l_print
#include "../utilities/log.h"
// used: iswapchaindx11
#include "../sdk/interfaces/iswapchaindx11.h"
#include "../sdk/interfaces/iresourcesystem.h"
#pragma region interfaces_get
using InstantiateInterfaceFn_t = void* (*)();
class CInterfaceRegister
{
public:
InstantiateInterfaceFn_t fnCreate;
const char* szName;
CInterfaceRegister* pNext;
};
static const CInterfaceRegister* GetRegisterList(const wchar_t* wszModuleName)
{
void* hModule = MEM::GetModuleBaseHandle(wszModuleName);
if (hModule == nullptr)
return nullptr;
std::uint8_t* pCreateInterface = reinterpret_cast<std::uint8_t*>(MEM::GetExportAddress(hModule, CS_XOR("CreateInterface")));
if (pCreateInterface == nullptr)
{
L_PRINT(LOG_ERROR) << CS_XOR("failed to get \"CreateInterface\" address");
return nullptr;
}
return *reinterpret_cast<CInterfaceRegister**>(MEM::ResolveRelativeAddress(pCreateInterface, 0x3, 0x7));
}
template <typename T = void*>
T* Capture(const CInterfaceRegister* pModuleRegister, const char* szInterfaceName)
{
for (const CInterfaceRegister* pRegister = pModuleRegister; pRegister != nullptr; pRegister = pRegister->pNext)
{
if (const std::size_t nInterfaceNameLength = CRT::StringLength(szInterfaceName);
// found needed interface
CRT::StringCompareN(szInterfaceName, pRegister->szName, nInterfaceNameLength) == 0 &&
// and we've given full name with hardcoded digits
(CRT::StringLength(pRegister->szName) == nInterfaceNameLength ||
// or it contains digits after name
CRT::StringToInteger<int>(pRegister->szName + nInterfaceNameLength, nullptr, 10) > 0))
{
// capture our interface
void* pInterface = pRegister->fnCreate();
#ifdef _DEBUG
// log interface address
L_PRINT(LOG_INFO) << CS_XOR("captured \"") << pRegister->szName << CS_XOR("\" interface at address: ") << L::AddFlags(LOG_MODE_INT_SHOWBASE | LOG_MODE_INT_FORMAT_HEX) << reinterpret_cast<std::uintptr_t>(pInterface);
#else
L_PRINT(LOG_INFO) << CS_XOR("captured \"") << pRegister->szName << CS_XOR("\" interface");
#endif
return static_cast<T*>(pInterface);
}
}
L_PRINT(LOG_ERROR) << CS_XOR("failed to find interface \"") << szInterfaceName << CS_XOR("\"");
return nullptr;
}
#pragma endregion
bool I::Setup()
{
bool bSuccess = true;
#pragma region interface_game_exported
const auto pTier0Handle = MEM::GetModuleBaseHandle(TIER0_DLL);
if (pTier0Handle == nullptr)
return false;
MemAlloc = *reinterpret_cast<IMemAlloc**>(MEM::GetExportAddress(pTier0Handle, CS_XOR("g_pMemAlloc")));
bSuccess &= (MemAlloc != nullptr);
const auto pSchemaSystemRegisterList = GetRegisterList(SCHEMASYSTEM_DLL);
if (pSchemaSystemRegisterList == nullptr)
return false;
SchemaSystem = Capture<ISchemaSystem>(pSchemaSystemRegisterList, SCHEMA_SYSTEM);
bSuccess &= (SchemaSystem != nullptr);
const auto pInputSystemRegisterList = GetRegisterList(INPUTSYSTEM_DLL);
if (pInputSystemRegisterList == nullptr)
return false;
InputSystem = Capture<IInputSystem>(pInputSystemRegisterList, INPUT_SYSTEM_VERSION);
bSuccess &= (InputSystem != nullptr);
const auto pEngineRegisterList = GetRegisterList(ENGINE2_DLL);
if (pEngineRegisterList == nullptr)
return false;
GameResourceService = Capture<IGameResourceService>(pEngineRegisterList, GAME_RESOURCE_SERVICE_CLIENT);
bSuccess &= (GameResourceService != nullptr);
Engine = Capture<IEngineClient>(pEngineRegisterList, SOURCE2_ENGINE_TO_CLIENT);
bSuccess &= (Engine != nullptr);
NetworkClientService = Capture<INetworkClientService>(pEngineRegisterList, NETWORK_CLIENT_SERVICE);
bSuccess &= (NetworkClientService != nullptr);
const auto pTier0RegisterList = GetRegisterList(TIER0_DLL);
if (pTier0RegisterList == nullptr)
return false;
Cvar = Capture<IEngineCVar>(pTier0RegisterList, ENGINE_CVAR);
bSuccess &= (Cvar != nullptr);
const auto pClientRegister = GetRegisterList(CLIENT_DLL);
if (pClientRegister == nullptr)
return false;
Client = Capture<ISource2Client>(pClientRegister, SOURCE2_CLIENT);
bSuccess &= (Client != nullptr);
const auto pMaterialSystem2Register = GetRegisterList(MATERIAL_SYSTEM2_DLL);
if (pMaterialSystem2Register == nullptr)
return false;
MaterialSystem2 = Capture<IMaterialSystem2>(pMaterialSystem2Register, MATERIAL_SYSTEM2);
bSuccess &= (MaterialSystem2 != nullptr);
const auto pResourceSystemRegisterList = GetRegisterList(RESOURCESYSTEM_DLL);
if (pResourceSystemRegisterList == nullptr)
return false;
ResourceSystem = Capture<IResourceSystem>(pResourceSystemRegisterList, RESOURCE_SYSTEM);
bSuccess &= (ResourceSystem != nullptr);
if (ResourceSystem != nullptr)
{
ResourceHandleUtils = reinterpret_cast<CResourceHandleUtils*>(ResourceSystem->QueryInterface(RESOURCE_HANDLE_UTILS));
bSuccess &= (ResourceHandleUtils != nullptr);
}
#pragma endregion
// @ida: #STR: "r_gpu_mem_stats", "-threads", "CTSListBase: Misaligned list\n", "CTSQueue: Misaligned queue\n", "Display GPU memory usage.", "-r_max_device_threads"
SwapChain = **reinterpret_cast<ISwapChainDx11***>(MEM::ResolveRelativeAddress(MEM::FindPattern(RENDERSYSTEM_DLL, CS_XOR("66 0F 7F 0D ? ? ? ? 66 0F 7F 05 ? ? ? ? 0F 1F 40")), 0x4, 0x8));
bSuccess &= (SwapChain != nullptr);
// grab's d3d11 interfaces for later use
if (SwapChain != nullptr)
{
if (FAILED(SwapChain->pDXGISwapChain->GetDevice(__uuidof(ID3D11Device), (void**)&Device)))
{
L_PRINT(LOG_ERROR) << CS_XOR("failed to get device from swapchain");
CS_ASSERT(false);
return false;
}
else
// we successfully got device, so we can get immediate context
Device->GetImmediateContext(&DeviceContext);
}
bSuccess &= (Device != nullptr && DeviceContext != nullptr);
Input = *reinterpret_cast<CCSGOInput**>(MEM::ResolveRelativeAddress(MEM::FindPattern(CLIENT_DLL, CS_XOR("48 8B 0D ? ? ? ? E8 ? ? ? ? 8B BE 84 12 00 00")), 0x3, 0x7));
bSuccess &= (Input != nullptr);
// @ida: STR '%s: %f tick(%d) curtime(%f) OnSequenceCycleChanged: %s : %d=[%s]'
GlobalVars = *reinterpret_cast<IGlobalVars**>(MEM::ResolveRelativeAddress(MEM::FindPattern(CLIENT_DLL, CS_XOR("48 89 0D ? ? ? ? 48 89 41")), 0x3, 0x7));
bSuccess &= (GlobalVars != nullptr);
PVS = reinterpret_cast<CPVS*>(MEM::ResolveRelativeAddress(MEM::FindPattern(ENGINE2_DLL, CS_XOR("48 8D 0D ? ? ? ? 33 D2 FF 50")), 0x3, 0x7));
bSuccess &= (PVS != nullptr);
GameTraceManager = *reinterpret_cast<CGameTraceManager**>(MEM::GetAbsoluteAddress(MEM::FindPattern(CLIENT_DLL, CS_XOR("4C 8B 3D ? ? ? ? 24 C9 0C 49 66 0F 7F 45")), 0x3, 0x0));
bSuccess &= (GameTraceManager != nullptr);
return bSuccess;
}
void I::CreateRenderTarget()
{
if (FAILED(SwapChain->pDXGISwapChain->GetDevice(__uuidof(ID3D11Device), (void**)&Device)))
{
L_PRINT(LOG_ERROR) << CS_XOR("failed to get device from swapchain");
CS_ASSERT(false);
}
else
// we successfully got device, so we can get immediate context
Device->GetImmediateContext(&DeviceContext);
// @note: i dont use this anywhere else so lambda is fine
static const auto GetCorrectDXGIFormat = [](DXGI_FORMAT eCurrentFormat)
{
switch (eCurrentFormat)
{
case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
return DXGI_FORMAT_R8G8B8A8_UNORM;
}
return eCurrentFormat;
};
DXGI_SWAP_CHAIN_DESC sd;
SwapChain->pDXGISwapChain->GetDesc(&sd);
ID3D11Texture2D* pBackBuffer = nullptr;
if (SUCCEEDED(SwapChain->pDXGISwapChain->GetBuffer(0, IID_PPV_ARGS(&pBackBuffer))))
{
if (pBackBuffer)
{
D3D11_RENDER_TARGET_VIEW_DESC desc{};
desc.Format = static_cast<DXGI_FORMAT>(GetCorrectDXGIFormat(sd.BufferDesc.Format));
desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
if (FAILED(Device->CreateRenderTargetView(pBackBuffer, &desc, &RenderTargetView)))
{
L_PRINT(LOG_WARNING) << CS_XOR("failed to create render target view with D3D11_RTV_DIMENSION_TEXTURE2D...");
L_PRINT(LOG_INFO) << CS_XOR("retrying to create render target view with D3D11_RTV_DIMENSION_TEXTURE2DMS...");
desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DMS;
if (FAILED(Device->CreateRenderTargetView(pBackBuffer, &desc, &RenderTargetView)))
{
L_PRINT(LOG_WARNING) << CS_XOR("failed to create render target view with D3D11_RTV_DIMENSION_TEXTURE2D...");
L_PRINT(LOG_INFO) << CS_XOR("retrying...");
if (FAILED(Device->CreateRenderTargetView(pBackBuffer, NULL, &RenderTargetView)))
{
L_PRINT(LOG_ERROR) << CS_XOR("failed to create render target view");
CS_ASSERT(false);
}
}
}
pBackBuffer->Release();
pBackBuffer = nullptr;
}
}
}
void I::DestroyRenderTarget()
{
if (RenderTargetView != nullptr)
{
RenderTargetView->Release();
RenderTargetView = nullptr;
}
}