2021-12-25 22:36:38 +01:00
|
|
|
#include "core/stdafx.h"
|
|
|
|
#ifndef DEDICATED // This file should not be compiled for DEDICATED!
|
|
|
|
//------------------------------
|
|
|
|
#define STB_IMAGE_IMPLEMENTATION
|
2022-08-21 19:35:06 +02:00
|
|
|
#include "tier0/threadtools.h"
|
2022-04-09 16:16:40 +02:00
|
|
|
#include "tier1/cvar.h"
|
2021-12-25 22:36:38 +01:00
|
|
|
#include "windows/id3dx.h"
|
|
|
|
#include "windows/input.h"
|
|
|
|
#include "gameui/IConsole.h"
|
|
|
|
#include "gameui/IBrowser.h"
|
2023-01-30 20:18:11 +01:00
|
|
|
#include "engine/sys_mainwind.h"
|
2021-12-25 22:36:38 +01:00
|
|
|
#include "inputsystem/inputsystem.h"
|
2022-08-09 17:18:07 +02:00
|
|
|
#include "public/bitmap/stb_image.h"
|
2021-12-25 22:36:38 +01:00
|
|
|
|
|
|
|
/**********************************************************************************
|
|
|
|
-----------------------------------------------------------------------------------
|
|
|
|
File : id3dx.cpp
|
|
|
|
Date : 15:06:2021
|
|
|
|
Author : Kawe Mazidjatari
|
|
|
|
Purpose: Microsoft DirectX 11 'IDXGISwapChain::Present' hook implementation
|
|
|
|
-----------------------------------------------------------------------------------
|
|
|
|
History:
|
|
|
|
- 15:06:2021 | 14:56 : Created by Kawe Mazidjatari
|
|
|
|
- 17:06:2021 | 13:12 : Destroy / release objects with 'GetResizeBuffers' callback
|
|
|
|
|
|
|
|
**********************************************************************************/
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////
|
|
|
|
typedef BOOL(WINAPI* IPostMessageA)(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);
|
|
|
|
typedef BOOL(WINAPI* IPostMessageW)(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////
|
2023-01-30 20:18:11 +01:00
|
|
|
static BOOL s_bInitialized = false;
|
|
|
|
static BOOL s_bImGuiInitialized = false;
|
2021-12-25 22:36:38 +01:00
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////
|
2023-01-30 20:18:11 +01:00
|
|
|
static IPostMessageA s_oPostMessageA = NULL;
|
|
|
|
static IPostMessageW s_oPostMessageW = NULL;
|
2021-12-25 22:36:38 +01:00
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////
|
2023-01-30 22:08:01 +01:00
|
|
|
static IDXGIResizeBuffers s_fnResizeBuffers = NULL;
|
2023-01-30 20:18:11 +01:00
|
|
|
static IDXGISwapChainPresent s_fnSwapChainPresent = NULL;
|
2021-12-25 22:36:38 +01:00
|
|
|
|
|
|
|
//#################################################################################
|
|
|
|
// WINDOW PROCEDURE
|
|
|
|
//#################################################################################
|
|
|
|
|
|
|
|
LRESULT CALLBACK DXGIMsgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|
|
|
{
|
|
|
|
return DefWindowProc(hWnd, uMsg, wParam, lParam);
|
|
|
|
}
|
|
|
|
|
|
|
|
//#################################################################################
|
|
|
|
// POST MESSAGE
|
|
|
|
//#################################################################################
|
|
|
|
|
|
|
|
BOOL WINAPI HPostMessageA(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
|
|
|
|
{
|
|
|
|
if (g_bBlockInput && Msg == WM_MOUSEMOVE)
|
|
|
|
{
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2022-10-20 12:29:21 +02:00
|
|
|
return s_oPostMessageA(hWnd, Msg, wParam, lParam);
|
2021-12-25 22:36:38 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
BOOL WINAPI HPostMessageW(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
|
|
|
|
{
|
|
|
|
if (g_bBlockInput && Msg == WM_MOUSEMOVE)
|
|
|
|
{
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2022-10-20 12:29:21 +02:00
|
|
|
return s_oPostMessageW(hWnd, Msg, wParam, lParam);
|
2021-12-25 22:36:38 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
//#################################################################################
|
2023-01-30 20:18:11 +01:00
|
|
|
// IMGUI
|
2021-12-25 22:36:38 +01:00
|
|
|
//#################################################################################
|
|
|
|
|
|
|
|
void SetupImGui()
|
|
|
|
{
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
IMGUI_CHECKVERSION();
|
|
|
|
ImGui::CreateContext();
|
2023-01-30 20:18:11 +01:00
|
|
|
ImGui_ImplWin32_Init(*g_pGameWindow);
|
|
|
|
ImGui_ImplDX11_Init(*g_ppGameDevice, *g_ppImmediateContext);
|
2021-12-25 22:36:38 +01:00
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
2022-10-20 12:29:21 +02:00
|
|
|
ImGuiIO& io = ImGui::GetIO();
|
2023-02-18 15:50:12 +01:00
|
|
|
io.ImeWindowHandle = *g_pGameWindow;
|
2021-12-25 22:36:38 +01:00
|
|
|
io.ConfigFlags |= ImGuiConfigFlags_IsSRGB;
|
2022-05-07 17:13:37 +02:00
|
|
|
|
2022-10-20 12:29:21 +02:00
|
|
|
s_bImGuiInitialized = true;
|
2021-12-25 22:36:38 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void DrawImGui()
|
|
|
|
{
|
|
|
|
ImGui_ImplDX11_NewFrame();
|
|
|
|
ImGui_ImplWin32_NewFrame();
|
|
|
|
|
|
|
|
ImGui::NewFrame();
|
|
|
|
|
2023-01-29 19:07:02 +01:00
|
|
|
// This is required to disable the ctrl+tab menu as some users use this shortcut for other things in-game.
|
|
|
|
// See https://github.com/ocornut/imgui/issues/5641 for more details.
|
|
|
|
if (GImGui->ConfigNavWindowingKeyNext)
|
|
|
|
ImGui::SetShortcutRouting(GImGui->ConfigNavWindowingKeyNext, ImGuiKeyOwner_None);
|
|
|
|
if (GImGui->ConfigNavWindowingKeyPrev)
|
|
|
|
ImGui::SetShortcutRouting(GImGui->ConfigNavWindowingKeyPrev, ImGuiKeyOwner_None);
|
|
|
|
|
2022-08-20 01:48:42 +02:00
|
|
|
g_pBrowser->RunTask();
|
|
|
|
g_pConsole->RunTask();
|
|
|
|
|
2022-10-20 01:17:51 +02:00
|
|
|
g_pBrowser->RunFrame();
|
|
|
|
g_pConsole->RunFrame();
|
2021-12-25 22:36:38 +01:00
|
|
|
|
|
|
|
ImGui::EndFrame();
|
|
|
|
ImGui::Render();
|
|
|
|
|
|
|
|
ImGui_ImplDX11_RenderDrawData(ImGui::GetDrawData());
|
|
|
|
}
|
|
|
|
|
|
|
|
//#################################################################################
|
2023-01-30 20:18:11 +01:00
|
|
|
// IDXGI
|
2021-12-25 22:36:38 +01:00
|
|
|
//#################################################################################
|
|
|
|
|
|
|
|
HRESULT __stdcall Present(IDXGISwapChain* pSwapChain, UINT nSyncInterval, UINT nFlags)
|
|
|
|
{
|
2022-10-20 12:29:21 +02:00
|
|
|
if (!s_bInitialized)
|
2021-12-25 22:36:38 +01:00
|
|
|
{
|
2023-01-30 20:18:11 +01:00
|
|
|
SetupImGui();
|
2022-08-21 19:35:06 +02:00
|
|
|
g_ThreadRenderThreadID = GetCurrentThreadId();
|
2023-01-30 20:18:11 +01:00
|
|
|
s_bInitialized = true;
|
2021-12-25 22:36:38 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
DrawImGui();
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
2022-10-20 12:29:21 +02:00
|
|
|
return s_fnSwapChainPresent(pSwapChain, nSyncInterval, nFlags);
|
2021-12-25 22:36:38 +01:00
|
|
|
}
|
|
|
|
|
2023-01-30 22:08:01 +01:00
|
|
|
HRESULT __stdcall ResizeBuffers(IDXGISwapChain* pSwapChain, UINT nBufferCount, UINT nWidth, UINT nHeight, DXGI_FORMAT dxFormat, UINT nSwapChainFlags)
|
|
|
|
{
|
|
|
|
g_nWindowRect[0] = nWidth;
|
|
|
|
g_nWindowRect[1] = nHeight;
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
return s_fnResizeBuffers(pSwapChain, nBufferCount, nWidth, nHeight, dxFormat, nSwapChainFlags);
|
|
|
|
}
|
|
|
|
|
2023-01-30 20:18:11 +01:00
|
|
|
//#################################################################################
|
|
|
|
// INTERNALS
|
|
|
|
//#################################################################################
|
|
|
|
|
2021-12-25 22:36:38 +01:00
|
|
|
bool LoadTextureBuffer(unsigned char* buffer, int len, ID3D11ShaderResourceView** out_srv, int* out_width, int* out_height)
|
|
|
|
{
|
|
|
|
// Load PNG buffer to a raw RGBA buffer
|
2023-01-30 20:18:11 +01:00
|
|
|
int nImageWidth = 0;
|
|
|
|
int nImageHeight = 0;
|
|
|
|
unsigned char* pImageData = stbi_load_from_memory(buffer, len, &nImageWidth, &nImageHeight, NULL, 4);
|
2021-12-25 22:36:38 +01:00
|
|
|
|
2023-01-30 20:18:11 +01:00
|
|
|
if (!pImageData)
|
2021-12-25 22:36:38 +01:00
|
|
|
{
|
2023-01-30 20:18:11 +01:00
|
|
|
assert(pImageData);
|
2021-12-25 22:36:38 +01:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
2023-01-30 20:18:11 +01:00
|
|
|
ID3D11Texture2D* pTexture = nullptr;
|
2021-12-25 22:36:38 +01:00
|
|
|
D3D11_TEXTURE2D_DESC desc;
|
2022-10-20 12:29:21 +02:00
|
|
|
D3D11_SUBRESOURCE_DATA subResource;
|
2021-12-25 22:36:38 +01:00
|
|
|
D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
ZeroMemory(&desc, sizeof(desc));
|
2023-01-30 20:18:11 +01:00
|
|
|
desc.Width = nImageWidth;
|
|
|
|
desc.Height = nImageHeight;
|
|
|
|
desc.MipLevels = 1;
|
|
|
|
desc.ArraySize = 1;
|
|
|
|
desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB;
|
|
|
|
desc.SampleDesc.Count = 1;
|
|
|
|
desc.Usage = D3D11_USAGE_DEFAULT;
|
|
|
|
desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
|
|
|
|
desc.CPUAccessFlags = 0;
|
2021-12-25 22:36:38 +01:00
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
2023-01-30 20:18:11 +01:00
|
|
|
subResource.pSysMem = pImageData;
|
|
|
|
subResource.SysMemPitch = desc.Width * 4;
|
|
|
|
subResource.SysMemSlicePitch = 0;
|
|
|
|
(*g_ppGameDevice)->CreateTexture2D(&desc, &subResource, &pTexture);
|
2021-12-25 22:36:38 +01:00
|
|
|
|
|
|
|
// Create texture view
|
|
|
|
ZeroMemory(&srvDesc, sizeof(srvDesc));
|
2023-01-30 20:18:11 +01:00
|
|
|
srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB;
|
|
|
|
srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
|
|
|
|
srvDesc.Texture2D.MipLevels = desc.MipLevels;
|
2021-12-25 22:36:38 +01:00
|
|
|
srvDesc.Texture2D.MostDetailedMip = 0;
|
|
|
|
|
|
|
|
if (pTexture)
|
|
|
|
{
|
2023-01-30 20:18:11 +01:00
|
|
|
(*g_ppGameDevice)->CreateShaderResourceView(pTexture, &srvDesc, out_srv);
|
2021-12-25 22:36:38 +01:00
|
|
|
pTexture->Release();
|
|
|
|
}
|
|
|
|
|
2023-01-30 20:18:11 +01:00
|
|
|
*out_width = nImageWidth;
|
|
|
|
*out_height = nImageHeight;
|
|
|
|
stbi_image_free(pImageData);
|
2021-12-25 22:36:38 +01:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2022-10-20 01:17:51 +02:00
|
|
|
void ResetInput()
|
|
|
|
{
|
|
|
|
g_pInputSystem->EnableInput( // Enables the input system when both are not drawn.
|
|
|
|
!g_pBrowser->m_bActivate && !g_pConsole->m_bActivate);
|
|
|
|
}
|
|
|
|
|
2023-01-26 20:00:52 +01:00
|
|
|
bool PanelsVisible()
|
|
|
|
{
|
|
|
|
if (g_pBrowser->m_bActivate || g_pConsole->m_bActivate)
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2021-12-25 22:36:38 +01:00
|
|
|
//#################################################################################
|
2023-01-30 20:18:11 +01:00
|
|
|
// ENTRYPOINT
|
2021-12-25 22:36:38 +01:00
|
|
|
//#################################################################################
|
|
|
|
|
2023-01-30 20:18:11 +01:00
|
|
|
void DirectX_Init()
|
2021-12-25 22:36:38 +01:00
|
|
|
{
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
2022-10-20 12:29:21 +02:00
|
|
|
s_oPostMessageA = (IPostMessageA)DetourFindFunction("user32.dll", "PostMessageA");
|
|
|
|
s_oPostMessageW = (IPostMessageW)DetourFindFunction("user32.dll", "PostMessageW");
|
2021-12-25 22:36:38 +01:00
|
|
|
|
|
|
|
// Begin the detour transaction
|
|
|
|
DetourTransactionBegin();
|
|
|
|
DetourUpdateThread(GetCurrentThread());
|
|
|
|
|
|
|
|
// Hook PostMessage
|
2022-10-20 12:29:21 +02:00
|
|
|
DetourAttach(&(LPVOID&)s_oPostMessageA, (PBYTE)HPostMessageA);
|
|
|
|
DetourAttach(&(LPVOID&)s_oPostMessageW, (PBYTE)HPostMessageW);
|
2021-12-25 22:36:38 +01:00
|
|
|
|
|
|
|
// Hook SwapChain
|
2023-01-30 20:18:11 +01:00
|
|
|
|
|
|
|
DWORD_PTR* pSwapChainVtable = *reinterpret_cast<DWORD_PTR**>(g_ppSwapChain[0]);
|
|
|
|
|
|
|
|
int pIDX = static_cast<int>(DXGISwapChainVTbl::Present);
|
|
|
|
s_fnSwapChainPresent = reinterpret_cast<IDXGISwapChainPresent>(pSwapChainVtable[pIDX]);
|
|
|
|
|
2023-01-30 22:08:01 +01:00
|
|
|
int rIDX = static_cast<int>(DXGISwapChainVTbl::ResizeBuffers);
|
|
|
|
s_fnResizeBuffers = reinterpret_cast<IDXGIResizeBuffers>(pSwapChainVtable[rIDX]);
|
|
|
|
|
2022-10-20 12:29:21 +02:00
|
|
|
DetourAttach(&(LPVOID&)s_fnSwapChainPresent, (PBYTE)Present);
|
2023-01-30 22:08:01 +01:00
|
|
|
DetourAttach(&(LPVOID&)s_fnResizeBuffers, (PBYTE)ResizeBuffers);
|
2021-12-25 22:36:38 +01:00
|
|
|
|
|
|
|
// Commit the transaction
|
2022-09-14 01:14:51 +02:00
|
|
|
HRESULT hr = DetourTransactionCommit();
|
|
|
|
if (hr != NO_ERROR)
|
2021-12-25 22:36:38 +01:00
|
|
|
{
|
|
|
|
// Failed to hook into the process, terminate
|
2022-09-14 00:39:38 +02:00
|
|
|
Error(eDLL_T::COMMON, 0xBAD0C0DE, "Failed to detour process: error code = %08x\n", hr);
|
2021-12-25 22:36:38 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void DirectX_Shutdown()
|
|
|
|
{
|
|
|
|
// Begin the detour transaction
|
|
|
|
DetourTransactionBegin();
|
|
|
|
DetourUpdateThread(GetCurrentThread());
|
|
|
|
|
|
|
|
// Unhook PostMessage
|
2022-10-20 12:29:21 +02:00
|
|
|
DetourDetach(&(LPVOID&)s_oPostMessageA, (PBYTE)HPostMessageA);
|
|
|
|
DetourDetach(&(LPVOID&)s_oPostMessageW, (PBYTE)HPostMessageW);
|
2021-12-25 22:36:38 +01:00
|
|
|
|
|
|
|
// Unhook SwapChain
|
2022-10-20 12:29:21 +02:00
|
|
|
DetourDetach(&(LPVOID&)s_fnSwapChainPresent, (PBYTE)Present);
|
2023-01-30 22:08:01 +01:00
|
|
|
DetourDetach(&(LPVOID&)s_fnResizeBuffers, (PBYTE)ResizeBuffers);
|
2021-12-25 22:36:38 +01:00
|
|
|
|
|
|
|
// Commit the transaction
|
|
|
|
DetourTransactionCommit();
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Shutdown ImGui
|
2022-10-20 12:29:21 +02:00
|
|
|
if (s_bImGuiInitialized)
|
2022-05-07 17:13:37 +02:00
|
|
|
{
|
|
|
|
ImGui_ImplWin32_Shutdown();
|
|
|
|
ImGui_ImplDX11_Shutdown();
|
2022-10-20 12:29:21 +02:00
|
|
|
s_bImGuiInitialized = false;
|
2022-05-07 17:13:37 +02:00
|
|
|
}
|
2022-10-20 12:29:21 +02:00
|
|
|
s_bInitialized = false;
|
2021-12-25 22:36:38 +01:00
|
|
|
}
|
|
|
|
|
2022-07-21 16:56:25 +02:00
|
|
|
void VDXGI::GetAdr(void) const
|
2021-12-25 22:36:38 +01:00
|
|
|
{
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
2023-01-25 02:26:52 +01:00
|
|
|
LogFunAdr("IDXGISwapChain::Present", reinterpret_cast<uintptr_t>(s_fnSwapChainPresent));
|
2023-01-30 20:18:11 +01:00
|
|
|
LogVarAdr("g_pSwapChain", reinterpret_cast<uintptr_t>(g_ppSwapChain));
|
2023-01-30 16:10:46 +01:00
|
|
|
LogVarAdr("g_pGameDevice", reinterpret_cast<uintptr_t>(g_ppGameDevice));
|
|
|
|
LogVarAdr("g_pImmediateContext", reinterpret_cast<uintptr_t>(g_ppImmediateContext));
|
2021-12-25 22:36:38 +01:00
|
|
|
}
|
|
|
|
|
2023-01-30 20:18:11 +01:00
|
|
|
void VDXGI::GetVar(void) const
|
2021-12-25 22:36:38 +01:00
|
|
|
{
|
2023-01-30 20:18:11 +01:00
|
|
|
#if defined (GAMEDLL_S0) || defined (GAMEDLL_S1)
|
|
|
|
CMemory pBase = g_GameDll.FindPatternSIMD("48 89 4C 24 ?? 53 48 83 EC 50 48 8B 05 ?? ?? ?? ??");
|
|
|
|
#elif defined (GAMEDLL_S2) || defined (GAMEDLL_S3)
|
|
|
|
CMemory pBase = g_GameDll.FindPatternSIMD("4C 8B DC 49 89 4B 08 48 83 EC 58");
|
|
|
|
#endif
|
|
|
|
// Grab device pointers..
|
|
|
|
g_ppGameDevice = pBase.FindPattern("48 8D 05").ResolveRelativeAddressSelf(0x3, 0x7).RCast<ID3D11Device**>();
|
|
|
|
g_ppImmediateContext = pBase.FindPattern("48 89 0D", CMemory::Direction::DOWN, 512, 3).ResolveRelativeAddressSelf(0x3, 0x7).RCast<ID3D11DeviceContext**>();
|
|
|
|
|
|
|
|
// Grab swap chain..
|
|
|
|
pBase = g_GameDll.FindPatternSIMD("48 83 EC 28 48 8B 0D ?? ?? ?? ?? 45 33 C0 33 D2");
|
|
|
|
g_ppSwapChain = pBase.FindPattern("48 8B 0D").ResolveRelativeAddressSelf(0x3, 0x7).RCast<IDXGISwapChain**>();
|
2021-12-25 22:36:38 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
#endif // !DEDICATED
|