// used: [d3d] api #include #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(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(MEM::ResolveRelativeAddress(pCreateInterface, 0x3, 0x7)); } template 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(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(pInterface); #else L_PRINT(LOG_INFO) << CS_XOR("captured \"") << pRegister->szName << CS_XOR("\" interface"); #endif return static_cast(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(MEM::GetExportAddress(pTier0Handle, CS_XOR("g_pMemAlloc"))); bSuccess &= (MemAlloc != nullptr); const auto pSchemaSystemRegisterList = GetRegisterList(SCHEMASYSTEM_DLL); if (pSchemaSystemRegisterList == nullptr) return false; SchemaSystem = Capture(pSchemaSystemRegisterList, SCHEMA_SYSTEM); bSuccess &= (SchemaSystem != nullptr); const auto pInputSystemRegisterList = GetRegisterList(INPUTSYSTEM_DLL); if (pInputSystemRegisterList == nullptr) return false; InputSystem = Capture(pInputSystemRegisterList, INPUT_SYSTEM_VERSION); bSuccess &= (InputSystem != nullptr); const auto pEngineRegisterList = GetRegisterList(ENGINE2_DLL); if (pEngineRegisterList == nullptr) return false; GameResourceService = Capture(pEngineRegisterList, GAME_RESOURCE_SERVICE_CLIENT); bSuccess &= (GameResourceService != nullptr); Engine = Capture(pEngineRegisterList, SOURCE2_ENGINE_TO_CLIENT); bSuccess &= (Engine != nullptr); NetworkClientService = Capture(pEngineRegisterList, NETWORK_CLIENT_SERVICE); bSuccess &= (NetworkClientService != nullptr); const auto pTier0RegisterList = GetRegisterList(TIER0_DLL); if (pTier0RegisterList == nullptr) return false; Cvar = Capture(pTier0RegisterList, ENGINE_CVAR); bSuccess &= (Cvar != nullptr); const auto pClientRegister = GetRegisterList(CLIENT_DLL); if (pClientRegister == nullptr) return false; Client = Capture(pClientRegister, SOURCE2_CLIENT); bSuccess &= (Client != nullptr); const auto pMaterialSystem2Register = GetRegisterList(MATERIAL_SYSTEM2_DLL); if (pMaterialSystem2Register == nullptr) return false; MaterialSystem2 = Capture(pMaterialSystem2Register, MATERIAL_SYSTEM2); bSuccess &= (MaterialSystem2 != nullptr); const auto pResourceSystemRegisterList = GetRegisterList(RESOURCESYSTEM_DLL); if (pResourceSystemRegisterList == nullptr) return false; ResourceSystem = Capture(pResourceSystemRegisterList, RESOURCE_SYSTEM); bSuccess &= (ResourceSystem != nullptr); if (ResourceSystem != nullptr) { ResourceHandleUtils = reinterpret_cast(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(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(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(MEM::ResolveRelativeAddress(MEM::FindPattern(CLIENT_DLL, CS_XOR("48 89 0D ? ? ? ? 48 89 41")), 0x3, 0x7)); bSuccess &= (GlobalVars != nullptr); PVS = reinterpret_cast(MEM::ResolveRelativeAddress(MEM::FindPattern(ENGINE2_DLL, CS_XOR("48 8D 0D ? ? ? ? 33 D2 FF 50")), 0x3, 0x7)); bSuccess &= (PVS != nullptr); GameTraceManager = *reinterpret_cast(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(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; } }