Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 19 additions & 6 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
cmake_minimum_required(VERSION 3.26)

file(READ VERSION OMATH_VERSION)
project(omath VERSION ${OMATH_VERSION} LANGUAGES CXX)

Expand Down Expand Up @@ -31,9 +30,10 @@ option(OMATH_SUPRESS_SAFETY_CHECKS
option(OMATH_ENABLE_COVERAGE "Enable coverage" OFF)
option(OMATH_ENABLE_FORCE_INLINE
"Will for compiler to make some functions to be force inlined no matter what" ON)

option(OMATH_ENABLE_LUA
"omath bindings for lua" OFF)
option(OMATH_ENABLE_HOOKING "omath will HooksManager that can hook DirectX automatically" OFF)

if(VCPKG_MANIFEST_FEATURES)
foreach(omath_feature IN LISTS VCPKG_MANIFEST_FEATURES)
if(omath_feature STREQUAL "imgui")
Expand All @@ -48,6 +48,8 @@ if(VCPKG_MANIFEST_FEATURES)
set(OMATH_BUILD_EXAMPLES ON)
elseif(omath_feature STREQUAL "lua")
set(OMATH_ENABLE_LUA ON)
elseif(omath_feature STREQUAL "hooking")
set(OMATH_ENABLE_HOOKING ON)
endif()

endforeach()
Expand Down Expand Up @@ -80,6 +82,10 @@ if(${PROJECT_IS_TOP_LEVEL})
message(STATUS "[${PROJECT_NAME}]: Lua feature status ${OMATH_ENABLE_LUA}")
endif()

if(OMATH_STATIC_MSVC_RUNTIME_LIBRARY)
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>" CACHE STRING "" FORCE)
endif()

file(GLOB_RECURSE OMATH_SOURCES CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/source/*.cpp")
file(GLOB_RECURSE OMATH_HEADERS CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/include/*.hpp")

Expand All @@ -100,6 +106,17 @@ if (OMATH_ENABLE_LUA)
target_include_directories(${PROJECT_NAME} PRIVATE ${SOL2_INCLUDE_DIRS})
endif ()

if (OMATH_ENABLE_HOOKING)
target_compile_definitions(${PROJECT_NAME} PUBLIC OMATH_ENABLE_HOOKING)

find_package(safetyhook CONFIG REQUIRED)
target_link_libraries(${PROJECT_NAME} PRIVATE safetyhook::safetyhook)

if (WIN32)
target_link_libraries(${PROJECT_NAME} PRIVATE d3d9 d3d11 d3d12 dxgi)
endif ()
endif ()

add_library(${PROJECT_NAME}::${PROJECT_NAME} ALIAS ${PROJECT_NAME})

target_compile_definitions(${PROJECT_NAME} PUBLIC OMATH_VERSION="${PROJECT_VERSION}")
Expand Down Expand Up @@ -147,10 +164,6 @@ set_target_properties(
CXX_STANDARD 23
CXX_STANDARD_REQUIRED ON)

if(OMATH_STATIC_MSVC_RUNTIME_LIBRARY)
set_target_properties(${PROJECT_NAME} PROPERTIES MSVC_RUNTIME_LIBRARY
"MultiThreaded$<$<CONFIG:Debug>:Debug>")
endif()

if(OMATH_USE_AVX2)
if(MSVC)
Expand Down
16 changes: 10 additions & 6 deletions CMakePresets.json
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,9 @@
"hidden": true,
"inherits": ["windows-base", "vcpkg-base"],
"cacheVariables": {
"VCPKG_MANIFEST_FEATURES": "tests;imgui;avx2;examples"
"VCPKG_TARGET_TRIPLET": "x64-windows-static",
"VCPKG_MANIFEST_FEATURES": "tests;imgui;avx2;examples;hooking",
"OMATH_STATIC_MSVC_RUNTIME_LIBRARY": "ON"
}
},
{
Expand Down Expand Up @@ -89,9 +91,10 @@
"strategy": "external"
},
"cacheVariables": {
"VCPKG_TARGET_TRIPLET": "x86-windows",
"VCPKG_TARGET_TRIPLET": "x86-windows-static",
"VCPKG_HOST_TRIPLET": "x64-windows",
"VCPKG_MANIFEST_FEATURES": "tests;imgui;avx2;examples"
"VCPKG_MANIFEST_FEATURES": "tests;imgui;avx2;examples",
"OMATH_STATIC_MSVC_RUNTIME_LIBRARY": "ON"
}
},
{
Expand All @@ -114,9 +117,10 @@
"strategy": "external"
},
"cacheVariables": {
"VCPKG_TARGET_TRIPLET": "arm64-windows",
"VCPKG_HOST_TRIPLET": "arm64-windows",
"VCPKG_MANIFEST_FEATURES": "tests;imgui;examples"
"VCPKG_TARGET_TRIPLET": "arm64-windows-static",
"VCPKG_HOST_TRIPLET": "arm64-windows-static",
"VCPKG_MANIFEST_FEATURES": "tests;imgui;examples",
"OMATH_STATIC_MSVC_RUNTIME_LIBRARY": "ON"
}
},
{
Expand Down
13 changes: 13 additions & 0 deletions examples/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,19 @@ add_subdirectory(example_proj_mat_builder)
add_subdirectory(example_signature_scan)
add_subdirectory(example_hud)

if(OMATH_ENABLE_HOOKING AND WIN32)
# Requires imgui with dx9-binding, dx11-binding, dx12-binding, win32-binding.
# Install via: vcpkg install imgui[dx9-binding,dx11-binding,dx12-binding,win32-binding]
find_package(imgui CONFIG QUIET)
if(imgui_FOUND)
add_subdirectory(example_dx9_hook)
add_subdirectory(example_dx11_hook)
add_subdirectory(example_dx12_hook)
else()
message(STATUS "[omath] imgui not found — DX hook examples skipped")
endif()
endif()

if(OMATH_ENABLE_VALGRIND)
omath_setup_valgrind(example_projection_matrix_builder)
omath_setup_valgrind(example_signature_scan)
Expand Down
13 changes: 13 additions & 0 deletions examples/example_dx11_hook/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
project(example_dx11_hook)

add_library(${PROJECT_NAME} SHARED dllmain.cpp)

set_target_properties(${PROJECT_NAME} PROPERTIES
CXX_STANDARD 23
MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>"
ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/out/${CMAKE_BUILD_TYPE}"
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/out/${CMAKE_BUILD_TYPE}"
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/out/${CMAKE_BUILD_TYPE}")

find_package(imgui CONFIG REQUIRED)
target_link_libraries(${PROJECT_NAME} PRIVATE omath::omath imgui::imgui d3d11 dxgi)
138 changes: 138 additions & 0 deletions examples/example_dx11_hook/dllmain.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
#include <Windows.h>
#include <d3d11.h>
#include <dxgi.h>
#include <imgui.h>
#include <imgui_impl_dx11.h>
#include <imgui_impl_win32.h>

#include "omath/hooks/hooks_manager.hpp"

extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND, UINT, WPARAM, LPARAM);

namespace
{
bool g_initialized = false;
bool g_init_attempted = false;

ID3D11Device* g_device = nullptr;
ID3D11DeviceContext* g_context = nullptr;
ID3D11RenderTargetView* g_render_target_view = nullptr;

void create_render_target(IDXGISwapChain* swap_chain)
{
ID3D11Texture2D* back_buffer = nullptr;
if (FAILED(swap_chain->GetBuffer(0, IID_PPV_ARGS(&back_buffer))))
return;
g_device->CreateRenderTargetView(back_buffer, nullptr, &g_render_target_view);
back_buffer->Release();
}

void init(IDXGISwapChain* swap_chain)
{
g_init_attempted = true;

if (FAILED(swap_chain->GetDevice(IID_PPV_ARGS(&g_device))))
return;

g_device->GetImmediateContext(&g_context);

DXGI_SWAP_CHAIN_DESC desc{};
swap_chain->GetDesc(&desc);

create_render_target(swap_chain);

ImGui::CreateContext();
ImGui::StyleColorsDark();
ImGui::GetIO().IniFilename = nullptr;
ImGui::GetIO().LogFilename = nullptr;
ImGui::GetIO().ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange;

ImGui_ImplWin32_Init(desc.OutputWindow);
ImGui_ImplDX11_Init(g_device, g_context);

auto& mgr = omath::hooks::HooksManager::get();
mgr.set_on_wnd_proc([](HWND h, UINT msg, WPARAM wp, LPARAM lp) -> std::optional<LRESULT> {
if (ImGui_ImplWin32_WndProcHandler(h, msg, wp, lp))
return 0;
return std::nullopt;
});
mgr.hook_wnd_proc(desc.OutputWindow);

g_initialized = true;
}

void on_present(IDXGISwapChain* swap_chain, UINT, UINT)
{
if (!g_initialized)
{
if (!g_init_attempted)
init(swap_chain);
return;
}

if (!g_render_target_view)
create_render_target(swap_chain);

g_context->OMSetRenderTargets(1, &g_render_target_view, nullptr);

ImGui_ImplDX11_NewFrame();
ImGui_ImplWin32_NewFrame();
ImGui::NewFrame();

ImGui::SetNextWindowSize({300.f, 80.f}, ImGuiCond_Once);
ImGui::SetNextWindowPos({10.f, 10.f}, ImGuiCond_Once);
ImGui::Begin("omath | DX11 hook");
ImGui::Text("Hook active");
ImGui::Text("FPS: %.1f", ImGui::GetIO().Framerate);
ImGui::End();

ImGui::Render();
ImGui_ImplDX11_RenderDrawData(ImGui::GetDrawData());
}

void on_resize_buffers(IDXGISwapChain*, UINT, UINT, UINT, DXGI_FORMAT, UINT)
{
if (g_render_target_view)
{
g_render_target_view->Release();
g_render_target_view = nullptr;
}
}
} // namespace

BOOL WINAPI DllMain(HINSTANCE h_instance, DWORD reason, LPVOID)
{
if (reason == DLL_PROCESS_ATTACH)
{
DisableThreadLibraryCalls(h_instance);
CreateThread(nullptr, 0, [](LPVOID) -> DWORD
{
while (!GetModuleHandle("d3d11.dll"))
Sleep(100);

auto& mgr = omath::hooks::HooksManager::get();
mgr.set_on_present(on_present);
mgr.set_on_resize_buffers(on_resize_buffers);
mgr.hook_dx11();
return 0;
}, nullptr, 0, nullptr);
}
else if (reason == DLL_PROCESS_DETACH)
{
auto& mgr = omath::hooks::HooksManager::get();
mgr.unhook_wnd_proc();
mgr.unhook_dx11();

if (g_initialized)
{
ImGui_ImplDX11_Shutdown();
ImGui_ImplWin32_Shutdown();
ImGui::DestroyContext();
}

if (g_render_target_view) { g_render_target_view->Release(); g_render_target_view = nullptr; }
if (g_context) { g_context->Release(); g_context = nullptr; }
if (g_device) { g_device->Release(); g_device = nullptr; }
}
return TRUE;
}
13 changes: 13 additions & 0 deletions examples/example_dx12_hook/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
project(example_dx12_hook)

add_library(${PROJECT_NAME} MODULE dllmain.cpp)

set_target_properties(${PROJECT_NAME} PROPERTIES
CXX_STANDARD 23
MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>"
ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/out/${CMAKE_BUILD_TYPE}"
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/out/${CMAKE_BUILD_TYPE}"
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/out/${CMAKE_BUILD_TYPE}")

find_package(imgui CONFIG REQUIRED)
target_link_libraries(${PROJECT_NAME} PRIVATE omath::omath imgui::imgui d3d12 dxgi)
Loading
Loading