205 lines
6.7 KiB
C++
Executable File
205 lines
6.7 KiB
C++
Executable File
// DX11Hook.cpp
|
|
#include "stdafx.h"
|
|
|
|
|
|
|
|
float DX11Hook::ScrX = 0, DX11Hook::ScrY = 0;
|
|
float DX11Hook::ScrWidth = 0, DX11Hook::ScrHeight = 0;
|
|
static BOOLEAN MenuInitialized = FALSE;
|
|
|
|
//==========================================================================================================================
|
|
|
|
typedef HRESULT(WINAPI *D3D11PresentHook) (IDXGISwapChain* pSwapChain, UINT SyncInterval, UINT Flags);
|
|
D3D11PresentHook originalD3D11PresentHook = NULL;
|
|
|
|
HRESULT WINAPI detourD3D11PresentHook(IDXGISwapChain* pSwapChain, UINT SyncInterval, UINT Flags)
|
|
{
|
|
static BOOLEAN Initialized = FALSE;
|
|
if (!Initialized) Initialized = DX11->InitDX11RenderStuff(pSwapChain);
|
|
DX11->DX11RenderScene();
|
|
return originalD3D11PresentHook(pSwapChain, SyncInterval, Flags);
|
|
}
|
|
|
|
//==========================================================================================================================
|
|
|
|
void DX11Hook::DX11RenderScene()
|
|
{
|
|
try
|
|
{
|
|
// if (Hooking::GetGameState() == GameStatePlaying)
|
|
{
|
|
// Init Menu
|
|
// if (!MenuInitialized) MenuInitialized = Menu::Init();
|
|
|
|
// Render Menu
|
|
Menu::Render();
|
|
}
|
|
}
|
|
catch (const std::exception &e)
|
|
{
|
|
DEBUGMSG(e.what());
|
|
}
|
|
}
|
|
|
|
//==========================================================================================================================
|
|
|
|
DWORD DX11Hook::InitDevice(HWND hWindow)
|
|
{
|
|
// Get window size
|
|
RECT rc;
|
|
GetWindowRect(hWindow, &rc);
|
|
ScrX = (float)rc.left;
|
|
ScrY = (float)rc.top;
|
|
ScrWidth = (float)(rc.right - rc.left);
|
|
ScrHeight = (float)(rc.bottom - rc.top);
|
|
|
|
IDXGISwapChain* pSwapChain;
|
|
D3D_FEATURE_LEVEL requestedLevels[] = { D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_10_1 };
|
|
D3D_FEATURE_LEVEL obtainedLevel;
|
|
ID3D11Device* d3dDevice = nullptr;
|
|
ID3D11DeviceContext* d3dContext = nullptr;
|
|
|
|
DXGI_SWAP_CHAIN_DESC scd;
|
|
ZeroMemory(&scd, sizeof(scd));
|
|
scd.BufferCount = 1;
|
|
scd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
|
scd.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
|
|
scd.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
|
|
scd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
|
|
|
|
scd.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;
|
|
scd.OutputWindow = hWindow;
|
|
scd.SampleDesc.Count = 1; // Set to 1 to disable multisampling
|
|
scd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
|
|
scd.Windowed = true; // ((GetWindowLongPtr(hWindow, GWL_STYLE) & WS_POPUP) != 0) ? false : true;
|
|
|
|
// LibOVR 0.4.3 requires that the width and height for the backbuffer is set even if
|
|
// you use windowed mode, despite being optional according to the D3D11 documentation.
|
|
scd.BufferDesc.Width = 1;
|
|
scd.BufferDesc.Height = 1;
|
|
scd.BufferDesc.RefreshRate.Numerator = 0;
|
|
scd.BufferDesc.RefreshRate.Denominator = 1;
|
|
|
|
UINT createFlags = 0;
|
|
#ifdef _DEBUG
|
|
// This flag gives you some quite wonderful debug text. Not wonderful for performance, though!
|
|
createFlags |= D3D11_CREATE_DEVICE_DEBUG;
|
|
#endif
|
|
|
|
IDXGISwapChain* d3dSwapChain = 0;
|
|
HRESULT x = D3D11CreateDeviceAndSwapChain(
|
|
nullptr,
|
|
D3D_DRIVER_TYPE_HARDWARE,
|
|
nullptr,
|
|
createFlags,
|
|
requestedLevels,
|
|
sizeof(requestedLevels) / sizeof(D3D_FEATURE_LEVEL),
|
|
D3D11_SDK_VERSION,
|
|
&scd,
|
|
&pSwapChain,
|
|
&DX11Device,
|
|
&obtainedLevel,
|
|
&DX11DeviceContext);
|
|
|
|
if (FAILED(x))
|
|
{
|
|
if (x == DXGI_ERROR_SDK_COMPONENT_MISSING)
|
|
{
|
|
MessageBox(hWindow, L"Failed to create directX device and swapchain: DXGI_ERROR_SDK_COMPONENT_MISSING\n\nYou seem to be missing some DirectX SDKs. If you are on Windows 8 or 10, see this article for information on enabling DirectX debug: https://goo.gl/tSeSif", L"Error", MB_ICONERROR);
|
|
}
|
|
else
|
|
{
|
|
MessageBox(hWindow, L"Failed to create directX device and swapchain!", L"Error", MB_ICONERROR);
|
|
}
|
|
|
|
Log::Msg("Failed DirectX with %d", x);
|
|
return NULL;
|
|
}
|
|
Log::Msg("Created Device / Swap Chain");
|
|
|
|
SwapChainVtable = (DWORD_PTR*)pSwapChain;
|
|
Log::Msg("Swap Chain VTable: 0x%I64X", SwapChainVtable);
|
|
SwapChainVtable = (DWORD_PTR*)SwapChainVtable[0];
|
|
Log::Msg("Swap Chain VTable: 0x%I64X", SwapChainVtable);
|
|
Log::Msg("Hooking Present Hook");
|
|
Log::Msg("Hooking From: 0x%I64X", (DWORD_PTR*)SwapChainVtable[8]);
|
|
Log::Msg("Hooking From: 0x%I64X", (DWORD64)&SwapChainVtable[8]);
|
|
Log::Msg("Hooking To : 0x%I64X", reinterpret_cast<void**>(&originalD3D11PresentHook));
|
|
Log::Msg("Hooking To : 0x%I64X", &originalD3D11PresentHook);
|
|
if (MH_CreateHook((DWORD_PTR*)SwapChainVtable[8], detourD3D11PresentHook, reinterpret_cast<void**>(&originalD3D11PresentHook)) != MH_OK) { return 1; }
|
|
if (MH_EnableHook((DWORD_PTR*)SwapChainVtable[8]) != MH_OK) { return 1; }
|
|
|
|
DWORD dwOld;
|
|
VirtualProtect(originalD3D11PresentHook, 2, PAGE_EXECUTE_READWRITE, &dwOld);
|
|
Log::Msg("Hooked!");
|
|
while (true) {
|
|
Sleep(10);
|
|
}
|
|
|
|
DX11Device->Release();
|
|
DX11DeviceContext->Release();
|
|
pSwapChain->Release();
|
|
|
|
return NULL;
|
|
}
|
|
|
|
void DX11Hook::CreateRenderTarget()
|
|
{
|
|
DXGI_SWAP_CHAIN_DESC sd;
|
|
DX11SwapChain->GetDesc(&sd);
|
|
|
|
// Create the render target
|
|
ID3D11Texture2D* pBackBuffer;
|
|
D3D11_RENDER_TARGET_VIEW_DESC render_target_view_desc;
|
|
ZeroMemory(&render_target_view_desc, sizeof(render_target_view_desc));
|
|
render_target_view_desc.Format = sd.BufferDesc.Format;
|
|
render_target_view_desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
|
|
DX11SwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&pBackBuffer);
|
|
DX11Device->CreateRenderTargetView(pBackBuffer, &render_target_view_desc, &DX11RenderTargetView);
|
|
DX11DeviceContext->OMSetRenderTargets(1, &DX11RenderTargetView, NULL);
|
|
pBackBuffer->Release();
|
|
}
|
|
|
|
BOOLEAN DX11Hook::InitDX11RenderStuff(IDXGISwapChain* _SwapChain)
|
|
{
|
|
DX11SwapChain = _SwapChain;
|
|
DX11SwapChain->GetDevice(__uuidof(DX11Device), (void**)&DX11Device);
|
|
DX11Device->GetImmediateContext(&DX11DeviceContext);
|
|
CreateRenderTarget();
|
|
|
|
// Setup ImGui binding
|
|
ImGui_ImplDX11_Init(Hooking::getWindow(), DX11Device, DX11DeviceContext);
|
|
|
|
Initialized = TRUE;
|
|
return TRUE;
|
|
}
|
|
|
|
void DX11Hook::CleanupRenderTarget()
|
|
{
|
|
if (DX11RenderTargetView) { DX11RenderTargetView->Release(); DX11RenderTargetView = NULL; }
|
|
}
|
|
|
|
void DX11Hook::CleanupDeviceD3D()
|
|
{
|
|
CleanupRenderTarget();
|
|
if (DX11SwapChain) { DX11SwapChain->Release(); DX11SwapChain = NULL; }
|
|
if (DX11DeviceContext) { DX11DeviceContext->Release(); DX11DeviceContext = NULL; }
|
|
if (DX11Device) { DX11Device->Release(); DX11Device = NULL; }
|
|
if (MH_DisableHook((DWORD_PTR*)SwapChainVtable[8]) != MH_OK) { return; }
|
|
}
|
|
|
|
void DX11Hook::ResizeBuffers(UINT width, UINT height)
|
|
{
|
|
if (DX11Device != NULL)
|
|
{
|
|
ImGui_ImplDX11_InvalidateDeviceObjects();
|
|
CleanupRenderTarget();
|
|
DX11SwapChain->ResizeBuffers(0, width, height, DXGI_FORMAT_UNKNOWN, 0);
|
|
CreateRenderTarget();
|
|
ImGui_ImplDX11_CreateDeviceObjects();
|
|
}
|
|
}
|
|
|
|
std::unique_ptr<DX11Hook> DX11;
|
|
|