#include #include #include #include #pragma comment(lib, "D3dcompiler.lib") #pragma comment(lib, "d3d11.lib") #pragma comment(lib, "winmm.lib") #include "imgui\imgui.h" #include "imgui\imgui_impl_win32.h" #include "imgui\imgui_impl_dx11.h" #include "Core.h" #include "FeatureManager.h" #include "VmtHook.h" typedef HRESULT(__stdcall* D3D11PresentHook) (IDXGISwapChain* pSwapChain, UINT SyncInterval, UINT Flags); D3D11PresentHook phookD3D11Present = nullptr; ID3D11Device* pDevice = nullptr; ID3D11DeviceContext* pContext = nullptr; DWORD_PTR* pSwapChainVtable = nullptr; Core* core = nullptr; #include "main.h" //helper funcs VOID WINAPI OnDllAttach(PVOID base) { #ifdef _DEBUG AllocConsole(); freopen_s((FILE**)stdin, "CONIN$", "r", stdin); freopen_s((FILE**)stdout, "CONOUT$", "w", stdout); SetConsoleTitleA("Age of Empires 2 DE - BDKPlayer"); #endif } VOID WINAPI OnDllDetach() { #ifdef _DEBUG fclose((FILE*)stdin); fclose((FILE*)stdout); HWND hw_ConsoleHwnd = GetConsoleWindow(); FreeConsole(); PostMessageW(hw_ConsoleHwnd, WM_CLOSE, 0, 0); #endif } extern LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); LRESULT CALLBACK hWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { if (ImGui_ImplWin32_WndProcHandler(hWnd, uMsg, wParam, lParam)) { return true; } return CallWindowProc(OriginalWndProcHandler, hWnd, uMsg, wParam, lParam); } HRESULT __stdcall hookD3D11Present(IDXGISwapChain* pSwapChain, UINT SyncInterval, UINT Flags) { if (firstTime) { firstTime = false; //only once //get device if (SUCCEEDED(pSwapChain->GetDevice(__uuidof(ID3D11Device), (void**)&pDevice))) { //SwapChain = pSwapChain; pSwapChain->GetDevice(__uuidof(pDevice), (void**)&pDevice); pDevice->GetImmediateContext(&pContext); } //imgui DXGI_SWAP_CHAIN_DESC sd; pSwapChain->GetDesc(&sd); ImGui::CreateContext(); ImGuiIO& io = ImGui::GetIO(); (void)io; ImGui::GetIO().WantCaptureMouse || ImGui::GetIO().WantTextInput || ImGui::GetIO().WantCaptureKeyboard; //control menu with mouse io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls window = sd.OutputWindow; //wndprochandler OriginalWndProcHandler = (WNDPROC)SetWindowLongPtr(window, GWLP_WNDPROC, (LONG_PTR)hWndProc); ImGui_ImplWin32_Init(window); ImGui_ImplDX11_Init(pDevice, pContext); ImGui::GetIO().ImeWindowHandle = window; // Create depthstencil state D3D11_DEPTH_STENCIL_DESC depthStencilDesc; depthStencilDesc.DepthEnable = TRUE; depthStencilDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL; depthStencilDesc.DepthFunc = D3D11_COMPARISON_ALWAYS; depthStencilDesc.StencilEnable = FALSE; depthStencilDesc.StencilReadMask = 0xFF; depthStencilDesc.StencilWriteMask = 0xFF; // Stencil operations if pixel is front-facing depthStencilDesc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP; depthStencilDesc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_INCR; depthStencilDesc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP; depthStencilDesc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS; // Stencil operations if pixel is back-facing depthStencilDesc.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP; depthStencilDesc.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_DECR; depthStencilDesc.BackFace.StencilPassOp = D3D11_STENCIL_OP_KEEP; depthStencilDesc.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS; pDevice->CreateDepthStencilState(&depthStencilDesc, &DepthStencilState_FALSE); //create depthbias rasterizer state D3D11_RASTERIZER_DESC rasterizer_desc; ZeroMemory(&rasterizer_desc, sizeof(rasterizer_desc)); rasterizer_desc.FillMode = D3D11_FILL_SOLID; rasterizer_desc.CullMode = D3D11_CULL_NONE; //D3D11_CULL_FRONT; rasterizer_desc.FrontCounterClockwise = false; float bias = 1000.0f; float bias_float = static_cast(-bias); bias_float /= 10000.0f; rasterizer_desc.DepthBias = DEPTH_BIAS_D32_FLOAT(*(DWORD*)&bias_float); rasterizer_desc.SlopeScaledDepthBias = 0.0f; rasterizer_desc.DepthBiasClamp = 0.0f; rasterizer_desc.DepthClipEnable = true; rasterizer_desc.ScissorEnable = false; rasterizer_desc.MultisampleEnable = false; rasterizer_desc.AntialiasedLineEnable = false; pDevice->CreateRasterizerState(&rasterizer_desc, &DEPTHBIASState_FALSE); //create normal rasterizer state D3D11_RASTERIZER_DESC nrasterizer_desc; ZeroMemory(&nrasterizer_desc, sizeof(nrasterizer_desc)); nrasterizer_desc.FillMode = D3D11_FILL_SOLID; //nrasterizer_desc.CullMode = D3D11_CULL_BACK; //flickering nrasterizer_desc.CullMode = D3D11_CULL_NONE; nrasterizer_desc.FrontCounterClockwise = false; nrasterizer_desc.DepthBias = 0; nrasterizer_desc.SlopeScaledDepthBias = 0.0f; nrasterizer_desc.DepthBiasClamp = 0.0f; nrasterizer_desc.DepthClipEnable = true; nrasterizer_desc.ScissorEnable = false; nrasterizer_desc.MultisampleEnable = false; nrasterizer_desc.AntialiasedLineEnable = false; pDevice->CreateRasterizerState(&nrasterizer_desc, &DEPTHBIASState_TRUE); //load cfg settings LoadCfg(); } //create rendertarget if (RenderTargetView == nullptr) { //viewport pContext->RSGetViewports(&vps, &viewport); ScreenCenterX = viewport.Width / 2.0f; ScreenCenterY = viewport.Height / 2.0f; //get backbuffer ID3D11Texture2D* backbuffer = nullptr; hr = pSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&backbuffer); if (FAILED(hr)) { Log("Failed to get BackBuffer"); return hr; } //create rendertargetview hr = pDevice->CreateRenderTargetView(backbuffer, nullptr, &RenderTargetView); backbuffer->Release(); if (FAILED(hr)) { Log("Failed to get RenderTarget"); return hr; } } else //call before you draw { pContext->OMSetRenderTargets(1, &RenderTargetView, nullptr); } //imgui ImGui_ImplWin32_NewFrame(); ImGui_ImplDX11_NewFrame(); ImGui::NewFrame(); if (!core) { core = new Core(); } core->OnPresent(); ImGui::EndFrame(); ImGui::Render(); ImGui_ImplDX11_RenderDrawData(ImGui::GetDrawData()); return phookD3D11Present(pSwapChain, SyncInterval, Flags); } const int MultisampleCount = 1; // Set to 1 to disable multisampling LRESULT CALLBACK DXGIMsgProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { return DefWindowProc(hwnd, uMsg, wParam, lParam); } DWORD __stdcall InitHooks(LPVOID hModule) { OnDllAttach(hModule); HMODULE hDXGIDLL = 0; do { hDXGIDLL = GetModuleHandleA("dxgi.dll"); Sleep(100); } while (!hDXGIDLL); IDXGISwapChain* pSwapChain; WNDCLASSEXA wc = { sizeof(WNDCLASSEX), CS_CLASSDC, DXGIMsgProc, 0L, 0L, GetModuleHandleA(NULL), NULL, NULL, NULL, NULL, "DX", NULL }; RegisterClassExA(&wc); HWND hWnd = CreateWindowA("DX", NULL, WS_OVERLAPPEDWINDOW, 100, 100, 300, 300, NULL, NULL, wc.hInstance, NULL); 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 = hWnd; scd.SampleDesc.Count = MultisampleCount; scd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; scd.Windowed = ((GetWindowLongPtr(hWnd, GWL_STYLE) & WS_POPUP) != 0) ? false : true; scd.BufferDesc.Width = 1; scd.BufferDesc.Height = 1; scd.BufferDesc.RefreshRate.Numerator = 0; scd.BufferDesc.RefreshRate.Denominator = 1; UINT createFlags = 0; #ifdef _DEBUG createFlags |= D3D11_CREATE_DEVICE_DEBUG; #endif IDXGISwapChain* d3dSwapChain = 0; if (FAILED(D3D11CreateDeviceAndSwapChain( nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr, createFlags, requestedLevels, sizeof(requestedLevels) / sizeof(D3D_FEATURE_LEVEL), D3D11_SDK_VERSION, &scd, &pSwapChain, &pDevice, &obtainedLevel, &pContext))) { MessageBoxA(hWnd, "Failed to create directX device and swapchain!", "Error", MB_ICONERROR); return NULL; } pSwapChainVtable = (DWORD_PTR*)pSwapChain; pSwapChainVtable = (DWORD_PTR*)pSwapChainVtable[0]; phookD3D11Present = (D3D11PresentHook)(DWORD_PTR*)pSwapChainVtable[8]; VmtHook presentHook = VmtHook((void**)pSwapChainVtable); presentHook.Hook(8, hookD3D11Present); pDevice->Release(); pContext->Release(); pSwapChain->Release(); while (!(GetAsyncKeyState(VK_F2) & 0x8000)) { Sleep(10); } FeatureManager::Get()->OnShutdown(); Sleep(200); core->OnShutdown(); Sleep(200); presentHook.Unhook(); (WNDPROC)SetWindowLongPtr(window, GWLP_WNDPROC, (LONG_PTR)OriginalWndProcHandler); FreeLibraryAndExitThread((HMODULE)hModule, 0); Sleep(100); } BOOL __stdcall DllMain(HINSTANCE hModule, DWORD dwReason, LPVOID lpReserved) { switch (dwReason) { case DLL_PROCESS_ATTACH: DisableThreadLibraryCalls(hModule); CreateThread(nullptr, 0, InitHooks, hModule, 0, nullptr); break; case DLL_PROCESS_DETACH: OnDllDetach(); break; default: break; } return TRUE; }