From d29a89261ce353fcf810553eceb25492820b0be6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anil=20D=C3=B6kmetas?= <111908128+JohnnyTheCoder1@users.noreply.github.com> Date: Fri, 24 Oct 2025 20:43:48 +0000 Subject: [PATCH 1/8] CI: trigger workflow for DX11 present capture/init guards From ddb8bd6ebe17294f9e19bc5dbd7f3e15bc0db675 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anil=20D=C3=B6kmetas?= <111908128+JohnnyTheCoder1@users.noreply.github.com> Date: Fri, 24 Oct 2025 20:54:59 +0000 Subject: [PATCH 2/8] Link against d3d11 for Present hook bootstrap --- Alien Isolation/Util/Hooks.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Alien Isolation/Util/Hooks.cpp b/Alien Isolation/Util/Hooks.cpp index dcc16c4..42ca99e 100644 --- a/Alien Isolation/Util/Hooks.cpp +++ b/Alien Isolation/Util/Hooks.cpp @@ -8,6 +8,8 @@ #include #include +#pragma comment(lib, "d3d11.lib") + // Function definitions typedef HRESULT(__stdcall* tIDXGISwapChain_Present)(IDXGISwapChain*, UINT, UINT); typedef BOOL(WINAPI* tSetCursorPos)(int, int); From 1d51f452f98a48ffa21ec7626e18a1d4de73cfd8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anil=20D=C3=B6kmetas?= <111908128+JohnnyTheCoder1@users.noreply.github.com> Date: Fri, 24 Oct 2025 21:18:10 +0000 Subject: [PATCH 3/8] DX11: log present hook install and capture status --- Alien Isolation/Main.cpp | 3 +++ Alien Isolation/Util/Hooks.cpp | 13 +++++++++++++ Alien Isolation/Util/Util.h | 1 + 3 files changed, 17 insertions(+) diff --git a/Alien Isolation/Main.cpp b/Alien Isolation/Main.cpp index 258836c..edaadee 100644 --- a/Alien Isolation/Main.cpp +++ b/Alien Isolation/Main.cpp @@ -196,6 +196,9 @@ bool Main::Initialize() if (!g_d3d11Device || !g_d3d11Context || !g_dxgiSwapChain) { util::log::Error("Failed to capture DirectX interfaces via Present hook fallback"); + util::log::Error("Present hook installed: %s | Device 0x%p | Context 0x%p | SwapChain 0x%p", + util::hooks::IsPresentHookInstalled() ? "yes" : "no", + g_d3d11Device, g_d3d11Context, g_dxgiSwapChain); return false; } diff --git a/Alien Isolation/Util/Hooks.cpp b/Alien Isolation/Util/Hooks.cpp index 42ca99e..a05de69 100644 --- a/Alien Isolation/Util/Hooks.cpp +++ b/Alien Isolation/Util/Hooks.cpp @@ -35,6 +35,7 @@ tIDXGISwapChain_Present oIDXGISwapChain_Present = nullptr; HRESULT __stdcall hIDXGISwapChain_Present(IDXGISwapChain* pSwapchain, UINT SyncInterval, UINT Flags) { static bool loggedDeviceFailure = false; + static bool loggedFirstPresent = false; if (!g_dxgiSwapChain) g_dxgiSwapChain = pSwapchain; @@ -52,6 +53,12 @@ HRESULT __stdcall hIDXGISwapChain_Present(IDXGISwapChain* pSwapchain, UINT SyncI if (g_d3d11Device && !g_d3d11Context) g_d3d11Device->GetImmediateContext(&g_d3d11Context); + if (!loggedFirstPresent) + { + util::log::Write("Present hook triggered; capturing DirectX interfaces"); + loggedFirstPresent = true; + } + if (!g_shutdown && g_mainHandle) { CTRenderer* pRenderer = g_mainHandle->GetRenderer(); @@ -334,6 +341,7 @@ static bool CreateDXGIPresentHook() return false; g_presentHookCreated = true; + util::log::Ok("Installed DXGI Present hook via dummy device"); return true; } @@ -379,6 +387,11 @@ bool util::hooks::Init() return true; } +bool util::hooks::IsPresentHookInstalled() +{ + return g_presentHookCreated; +} + void util::hooks::InstallGameHooks() { if (g_gameHooksInstalled) diff --git a/Alien Isolation/Util/Util.h b/Alien Isolation/Util/Util.h index 66a3c72..8da4225 100644 --- a/Alien Isolation/Util/Util.h +++ b/Alien Isolation/Util/Util.h @@ -26,6 +26,7 @@ namespace util bool Init(); void InstallGameHooks(); + bool IsPresentHookInstalled(); // if name is empty, then perform on all hooks void SetHookState(bool enabled, std::string const& name = ""); From aeb6b71cccf221a9d8c3fb1ffdf73ff2374af445 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anil=20D=C3=B6kmetas?= <111908128+JohnnyTheCoder1@users.noreply.github.com> Date: Sat, 25 Oct 2025 15:54:57 +0000 Subject: [PATCH 4/8] DX11: detail present hook capture logging --- Alien Isolation/Util/Hooks.cpp | 36 ++++++++++++++++++++++++++++++---- 1 file changed, 32 insertions(+), 4 deletions(-) diff --git a/Alien Isolation/Util/Hooks.cpp b/Alien Isolation/Util/Hooks.cpp index a05de69..6c6a299 100644 --- a/Alien Isolation/Util/Hooks.cpp +++ b/Alien Isolation/Util/Hooks.cpp @@ -36,22 +36,50 @@ HRESULT __stdcall hIDXGISwapChain_Present(IDXGISwapChain* pSwapchain, UINT SyncI { static bool loggedDeviceFailure = false; static bool loggedFirstPresent = false; + static bool loggedSwapChainCapture = false; if (!g_dxgiSwapChain) g_dxgiSwapChain = pSwapchain; + if (g_dxgiSwapChain == pSwapchain && !loggedSwapChainCapture) + { + util::log::Ok("Captured IDXGISwapChain from Present hook (0x%p)", g_dxgiSwapChain); + loggedSwapChainCapture = true; + } + if (!g_d3d11Device) { - HRESULT hr = pSwapchain->GetDevice(__uuidof(ID3D11Device), reinterpret_cast(&g_d3d11Device)); - if (FAILED(hr) && !loggedDeviceFailure) + ID3D11Device* pDevice = nullptr; + HRESULT hr = pSwapchain->GetDevice(__uuidof(ID3D11Device), reinterpret_cast(&pDevice)); + if (FAILED(hr)) + { + if (!loggedDeviceFailure) + { + util::log::Warning("SwapChain::GetDevice failed while capturing interfaces, HRESULT 0x%X", hr); + loggedDeviceFailure = true; + } + } + else if (!pDevice) { - util::log::Warning("SwapChain::GetDevice failed while capturing interfaces, HRESULT 0x%X", hr); - loggedDeviceFailure = true; + if (!loggedDeviceFailure) + { + util::log::Warning("SwapChain::GetDevice succeeded but returned null device pointer"); + loggedDeviceFailure = true; + } + } + else + { + g_d3d11Device = pDevice; + util::log::Ok("Captured ID3D11Device from Present hook (0x%p)", g_d3d11Device); } } if (g_d3d11Device && !g_d3d11Context) + { g_d3d11Device->GetImmediateContext(&g_d3d11Context); + if (g_d3d11Context) + util::log::Ok("Captured ID3D11DeviceContext from Present hook (0x%p)", g_d3d11Context); + } if (!loggedFirstPresent) { From 437352334faa3d98e3a6cd57fb875996bab599d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anil=20D=C3=B6kmetas?= <111908128+JohnnyTheCoder1@users.noreply.github.com> Date: Sat, 25 Oct 2025 16:15:08 +0000 Subject: [PATCH 5/8] DX11: trace present hook invocation and vtable address --- Alien Isolation/Util/Hooks.cpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/Alien Isolation/Util/Hooks.cpp b/Alien Isolation/Util/Hooks.cpp index 6c6a299..e3777eb 100644 --- a/Alien Isolation/Util/Hooks.cpp +++ b/Alien Isolation/Util/Hooks.cpp @@ -38,6 +38,12 @@ HRESULT __stdcall hIDXGISwapChain_Present(IDXGISwapChain* pSwapchain, UINT SyncI static bool loggedFirstPresent = false; static bool loggedSwapChainCapture = false; + if (!loggedFirstPresent) + { + util::log::Write(">>> Present hook CALLED! pSwapchain=0x%p SyncInterval=%u Flags=%u", pSwapchain, SyncInterval, Flags); + loggedFirstPresent = true; + } + if (!g_dxgiSwapChain) g_dxgiSwapChain = pSwapchain; @@ -81,12 +87,6 @@ HRESULT __stdcall hIDXGISwapChain_Present(IDXGISwapChain* pSwapchain, UINT SyncI util::log::Ok("Captured ID3D11DeviceContext from Present hook (0x%p)", g_d3d11Context); } - if (!loggedFirstPresent) - { - util::log::Write("Present hook triggered; capturing DirectX interfaces"); - loggedFirstPresent = true; - } - if (!g_shutdown && g_mainHandle) { CTRenderer* pRenderer = g_mainHandle->GetRenderer(); @@ -358,6 +358,8 @@ static bool CreateDXGIPresentHook() } void** vtbl = *reinterpret_cast(pSwapChain); + util::log::Write("SwapChain vtable at 0x%p, Present at slot 8 is 0x%p", vtbl, vtbl[8]); + bool hookCreated = CreateHook("SwapChainPresent", (int)vtbl[8], hIDXGISwapChain_Present, &oIDXGISwapChain_Present); pSwapChain->Release(); From da901c8f689faffd49f4ec3a1b8ea8f807b461d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anil=20D=C3=B6kmetas?= <111908128+JohnnyTheCoder1@users.noreply.github.com> Date: Sun, 26 Oct 2025 12:03:00 +0000 Subject: [PATCH 6/8] DX11: hook IDXGISwapChain1::Present1 fallback --- Alien Isolation/Util/Hooks.cpp | 138 ++++++++++++++++++++------------- 1 file changed, 86 insertions(+), 52 deletions(-) diff --git a/Alien Isolation/Util/Hooks.cpp b/Alien Isolation/Util/Hooks.cpp index e3777eb..db165d8 100644 --- a/Alien Isolation/Util/Hooks.cpp +++ b/Alien Isolation/Util/Hooks.cpp @@ -4,6 +4,7 @@ #include "../AlienIsolation.h" #include #include +#include #include #include #include @@ -12,6 +13,7 @@ // Function definitions typedef HRESULT(__stdcall* tIDXGISwapChain_Present)(IDXGISwapChain*, UINT, UINT); +typedef HRESULT(__stdcall* tIDXGISwapChain1_Present1)(IDXGISwapChain1*, UINT, UINT, const DXGI_PRESENT_PARAMETERS*); typedef BOOL(WINAPI* tSetCursorPos)(int, int); typedef int(__thiscall* tCameraUpdate)(CATHODE::AICameraManager*); @@ -31,80 +33,94 @@ typedef bool(__thiscall* tCombatManagerUpdate)(void*, CATHODE::Character*); // on top, like the tools UI. tIDXGISwapChain_Present oIDXGISwapChain_Present = nullptr; +tIDXGISwapChain1_Present1 oIDXGISwapChain1_Present1 = nullptr; -HRESULT __stdcall hIDXGISwapChain_Present(IDXGISwapChain* pSwapchain, UINT SyncInterval, UINT Flags) +namespace { - static bool loggedDeviceFailure = false; - static bool loggedFirstPresent = false; - static bool loggedSwapChainCapture = false; - - if (!loggedFirstPresent) + void HandlePresent(IDXGISwapChain* pSwapchain, UINT SyncInterval, UINT Flags) { - util::log::Write(">>> Present hook CALLED! pSwapchain=0x%p SyncInterval=%u Flags=%u", pSwapchain, SyncInterval, Flags); - loggedFirstPresent = true; - } + static bool loggedDeviceFailure = false; + static bool loggedFirstPresent = false; + static bool loggedSwapChainCapture = false; - if (!g_dxgiSwapChain) - g_dxgiSwapChain = pSwapchain; + if (!loggedFirstPresent) + { + util::log::Write(">>> Present hook CALLED! pSwapchain=0x%p SyncInterval=%u Flags=%u", pSwapchain, SyncInterval, Flags); + loggedFirstPresent = true; + } - if (g_dxgiSwapChain == pSwapchain && !loggedSwapChainCapture) - { - util::log::Ok("Captured IDXGISwapChain from Present hook (0x%p)", g_dxgiSwapChain); - loggedSwapChainCapture = true; - } + if (!g_dxgiSwapChain) + g_dxgiSwapChain = pSwapchain; - if (!g_d3d11Device) - { - ID3D11Device* pDevice = nullptr; - HRESULT hr = pSwapchain->GetDevice(__uuidof(ID3D11Device), reinterpret_cast(&pDevice)); - if (FAILED(hr)) + if (g_dxgiSwapChain == pSwapchain && !loggedSwapChainCapture) { - if (!loggedDeviceFailure) - { - util::log::Warning("SwapChain::GetDevice failed while capturing interfaces, HRESULT 0x%X", hr); - loggedDeviceFailure = true; - } + util::log::Ok("Captured IDXGISwapChain from Present hook (0x%p)", g_dxgiSwapChain); + loggedSwapChainCapture = true; } - else if (!pDevice) + + if (!g_d3d11Device) { - if (!loggedDeviceFailure) + ID3D11Device* pDevice = nullptr; + HRESULT hr = pSwapchain->GetDevice(__uuidof(ID3D11Device), reinterpret_cast(&pDevice)); + if (FAILED(hr)) + { + if (!loggedDeviceFailure) + { + util::log::Warning("SwapChain::GetDevice failed while capturing interfaces, HRESULT 0x%X", hr); + loggedDeviceFailure = true; + } + } + else if (!pDevice) + { + if (!loggedDeviceFailure) + { + util::log::Warning("SwapChain::GetDevice succeeded but returned null device pointer"); + loggedDeviceFailure = true; + } + } + else { - util::log::Warning("SwapChain::GetDevice succeeded but returned null device pointer"); - loggedDeviceFailure = true; + g_d3d11Device = pDevice; + util::log::Ok("Captured ID3D11Device from Present hook (0x%p)", g_d3d11Device); } } - else + + if (g_d3d11Device && !g_d3d11Context) { - g_d3d11Device = pDevice; - util::log::Ok("Captured ID3D11Device from Present hook (0x%p)", g_d3d11Device); + g_d3d11Device->GetImmediateContext(&g_d3d11Context); + if (g_d3d11Context) + util::log::Ok("Captured ID3D11DeviceContext from Present hook (0x%p)", g_d3d11Context); } - } - - if (g_d3d11Device && !g_d3d11Context) - { - g_d3d11Device->GetImmediateContext(&g_d3d11Context); - if (g_d3d11Context) - util::log::Ok("Captured ID3D11DeviceContext from Present hook (0x%p)", g_d3d11Context); - } - - if (!g_shutdown && g_mainHandle) - { - CTRenderer* pRenderer = g_mainHandle->GetRenderer(); - UI* pUI = g_mainHandle->GetUI(); - CameraManager* pCameraManager = g_mainHandle->GetCameraManager(); - if (pRenderer && pRenderer->IsReady() && pUI && pUI->IsReady() && pCameraManager) + if (!g_shutdown && g_mainHandle) { - pUI->BindRenderTarget(); - pRenderer->UpdateMatrices(); - //g_mainHandle->GetCameraManager()->DrawTrack(); - pUI->Draw(); + CTRenderer* pRenderer = g_mainHandle->GetRenderer(); + UI* pUI = g_mainHandle->GetUI(); + CameraManager* pCameraManager = g_mainHandle->GetCameraManager(); + + if (pRenderer && pRenderer->IsReady() && pUI && pUI->IsReady() && pCameraManager) + { + pUI->BindRenderTarget(); + pRenderer->UpdateMatrices(); + //g_mainHandle->GetCameraManager()->DrawTrack(); + pUI->Draw(); + } } } +} +HRESULT __stdcall hIDXGISwapChain_Present(IDXGISwapChain* pSwapchain, UINT SyncInterval, UINT Flags) +{ + HandlePresent(pSwapchain, SyncInterval, Flags); return oIDXGISwapChain_Present(pSwapchain, SyncInterval, Flags); } +HRESULT __stdcall hIDXGISwapChain1_Present1(IDXGISwapChain1* pSwapchain, UINT SyncInterval, UINT Flags, const DXGI_PRESENT_PARAMETERS* pPresentParameters) +{ + HandlePresent(pSwapchain, SyncInterval, Flags); + return oIDXGISwapChain1_Present1(pSwapchain, SyncInterval, Flags, pPresentParameters); +} + ////////////////////////// //// CAMERA HOOKS //// ////////////////////////// @@ -362,6 +378,24 @@ static bool CreateDXGIPresentHook() bool hookCreated = CreateHook("SwapChainPresent", (int)vtbl[8], hIDXGISwapChain_Present, &oIDXGISwapChain_Present); + if (hookCreated) + { + IDXGISwapChain1* pSwapChain1 = nullptr; + HRESULT qiHr = pSwapChain->QueryInterface(__uuidof(IDXGISwapChain1), reinterpret_cast(&pSwapChain1)); + if (SUCCEEDED(qiHr) && pSwapChain1) + { + void** vtbl1 = *reinterpret_cast(pSwapChain1); + util::log::Write("SwapChain1 vtable at 0x%p, Present1 at slot 22 is 0x%p", vtbl1, vtbl1[22]); + if (CreateHook("SwapChainPresent1", (int)vtbl1[22], hIDXGISwapChain1_Present1, &oIDXGISwapChain1_Present1)) + util::log::Ok("Installed DXGI Present1 hook via dummy device"); + pSwapChain1->Release(); + } + else + { + util::log::Warning("IDXGISwapChain1 interface unavailable for Present1 hook, HRESULT 0x%X", qiHr); + } + } + pSwapChain->Release(); pDevice->Release(); pContext->Release(); From b30ec5e71a421e5c635ef8ef74d12a1a0ac2ec0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anil=20D=C3=B6kmetas?= <111908128+JohnnyTheCoder1@users.noreply.github.com> Date: Sun, 26 Oct 2025 12:10:05 +0000 Subject: [PATCH 7/8] DX11: try reference driver when building dummy swapchain --- Alien Isolation/Util/Hooks.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Alien Isolation/Util/Hooks.cpp b/Alien Isolation/Util/Hooks.cpp index db165d8..6dbb3c4 100644 --- a/Alien Isolation/Util/Hooks.cpp +++ b/Alien Isolation/Util/Hooks.cpp @@ -366,6 +366,12 @@ static bool CreateDXGIPresentHook() featureLevels, _countof(featureLevels), D3D11_SDK_VERSION, &desc, &pSwapChain, &pDevice, &obtainedLevel, &pContext); } + if (FAILED(hr)) + { + hr = D3D11CreateDeviceAndSwapChain(nullptr, D3D_DRIVER_TYPE_REFERENCE, nullptr, createFlags, + featureLevels, _countof(featureLevels), D3D11_SDK_VERSION, &desc, &pSwapChain, &pDevice, &obtainedLevel, &pContext); + } + if (FAILED(hr)) { util::log::Error("Failed to create dummy D3D11 device for Present hook, HRESULT 0x%X", hr); From a9a36b837238c0647668ad915ae7066737d030eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anil=20D=C3=B6kmetas?= <111908128+JohnnyTheCoder1@users.noreply.github.com> Date: Mon, 27 Oct 2025 20:47:21 +0000 Subject: [PATCH 8/8] DX11: guard legacy patches and log hook targets --- Alien Isolation/Main.cpp | 12 ++---------- Alien Isolation/Util/Hooks.cpp | 13 +++++++++++++ 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/Alien Isolation/Main.cpp b/Alien Isolation/Main.cpp index edaadee..cc4ec3f 100644 --- a/Alien Isolation/Main.cpp +++ b/Alien Isolation/Main.cpp @@ -208,17 +208,9 @@ bool Main::Initialize() // This disables the object glow thing // Apply small byte patch, but only if target lies within module image { - BYTE GlowPatch[7] = { 0x80, 0xB9, 0x65, 0x70, 0x02, 0x00, 0x01 }; void* patchAddr = (void*)((int)g_gameHandle + 0x3A3494); - if (util::IsAddressInModule(g_gameHandle, patchAddr, sizeof(GlowPatch))) - { - if (!util::WriteMemory((DWORD_PTR)patchAddr, GlowPatch, (DWORD)sizeof(GlowPatch))) - util::log::Warning("Glow patch VirtualProtect/WriteMemory failed at %p", patchAddr); - } - else - { - util::log::Warning("Skipping glow patch: address %p outside module image (possible version mismatch)", patchAddr); - } + if (util::IsAddressInModule(g_gameHandle, patchAddr, 7)) + util::log::Warning("Skipping legacy glow patch at %p (offset 0x3A3494) to avoid version mismatch", patchAddr); } // Make timescale writable diff --git a/Alien Isolation/Util/Hooks.cpp b/Alien Isolation/Util/Hooks.cpp index 6dbb3c4..bd03b4b 100644 --- a/Alien Isolation/Util/Hooks.cpp +++ b/Alien Isolation/Util/Hooks.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #pragma comment(lib, "d3d11.lib") @@ -478,6 +479,18 @@ void util::hooks::InstallGameHooks() util::log::Warning("Skipping hook %s: address 0x%X outside module image", name, addr); return; } + + BYTE preview[6] = { 0 }; + if (!util::IsPtrReadable(reinterpret_cast(addr), sizeof(preview))) + { + util::log::Warning("Skipping hook %s: target 0x%X unreadable", name, addr); + return; + } + + memcpy(preview, reinterpret_cast(addr), sizeof(preview)); + util::log::Write("Hook %s targeting 0x%X bytes %02X %02X %02X %02X %02X %02X", name, addr, + preview[0], preview[1], preview[2], preview[3], preview[4], preview[5]); + CreateHook(name, addr, hook, original); };