mirror of
https://github.com/SunsetMkt/Akebi-GC.git
synced 2025-09-19 03:56:05 +08:00
minor changes
- cheat-base: add support dx12 add several utility modifications - cheat-library: refactored sniffer. Check: https://github.com/Akebi-Group/Akebi-PacketSniffer
This commit is contained in:
@ -125,7 +125,7 @@
|
||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||
<LanguageStandard>stdcpp20</LanguageStandard>
|
||||
<AdditionalIncludeDirectories>$(ProjectDir)framework\;$(ProjectDir)src\;$(ProjectDir)vendor\detours\;$(ProjectDir)vendor\fmt\include\;$(ProjectDir)vendor\imgui\;$(ProjectDir)vendor\magic_enum\include\;$(ProjectDir)vendor\simpleIni\;$(ProjectDir)vendor\json\single_include\;$(ProjectDir)vendor\imgui-notify-v2\;$(ProjectDir)vendor\stb\</AdditionalIncludeDirectories>
|
||||
<LanguageStandard_C>stdc17</LanguageStandard_C>
|
||||
<LanguageStandard_C>Default</LanguageStandard_C>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>
|
||||
@ -158,7 +158,7 @@
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<OmitFramePointers>false</OmitFramePointers>
|
||||
<LanguageStandard_C>stdc17</LanguageStandard_C>
|
||||
<LanguageStandard_C>Default</LanguageStandard_C>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>
|
||||
@ -193,7 +193,7 @@
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<OmitFramePointers>false</OmitFramePointers>
|
||||
<LanguageStandard_C>stdc17</LanguageStandard_C>
|
||||
<LanguageStandard_C>Default</LanguageStandard_C>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>
|
||||
@ -222,7 +222,7 @@
|
||||
<PreprocessorDefinitions>_DEBUG;_SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING;_SILENCE_ALL_CXX17_DEPRECATION_WARNINGS;_CRT_SECURE_NO_WARNINGS;_MBCS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||
<LanguageStandard_C>stdc17</LanguageStandard_C>
|
||||
<LanguageStandard_C>Default</LanguageStandard_C>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<SupportJustMyCode>false</SupportJustMyCode>
|
||||
<BufferSecurityCheck>false</BufferSecurityCheck>
|
||||
@ -242,7 +242,7 @@
|
||||
<PreprocessorDefinitions>_SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING;_SILENCE_ALL_CXX17_DEPRECATION_WARNINGS;_CRT_SECURE_NO_WARNINGS;_MBCS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||
<LanguageStandard_C>stdc17</LanguageStandard_C>
|
||||
<LanguageStandard_C>Default</LanguageStandard_C>
|
||||
</ClCompile>
|
||||
<Lib>
|
||||
<AdditionalDependencies>detours-$(PlatformShortName).lib</AdditionalDependencies>
|
||||
@ -259,7 +259,7 @@
|
||||
<PreprocessorDefinitions>_SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING;_SILENCE_ALL_CXX17_DEPRECATION_WARNINGS;_CRT_SECURE_NO_WARNINGS;_MBCS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||
<LanguageStandard_C>stdc17</LanguageStandard_C>
|
||||
<LanguageStandard_C>Default</LanguageStandard_C>
|
||||
</ClCompile>
|
||||
<Lib>
|
||||
<AdditionalDependencies>detours-$(PlatformShortName).lib</AdditionalDependencies>
|
||||
@ -298,6 +298,8 @@
|
||||
<ClInclude Include="src\cheat-base\events\joins\handlereventjoin.hpp" />
|
||||
<ClInclude Include="src\cheat-base\inject\load-library.h" />
|
||||
<ClInclude Include="src\cheat-base\inject\manual-map.h" />
|
||||
<ClInclude Include="src\cheat-base\ISerializable.h" />
|
||||
<ClInclude Include="src\cheat-base\render\backend\dx12-hook.h" />
|
||||
<ClInclude Include="src\cheat-base\ResourceLoader.h" />
|
||||
<ClInclude Include="src\cheat-base\Hotkey.h" />
|
||||
<ClInclude Include="src\cheat-base\render\ImageLoader.h" />
|
||||
@ -335,6 +337,7 @@
|
||||
<ClInclude Include="vendor\imgui-notify-v2\font_awesome_5.h" />
|
||||
<ClInclude Include="vendor\imgui-notify-v2\imgui_notify.h" />
|
||||
<ClInclude Include="vendor\imgui\backends\imgui_impl_dx11.h" />
|
||||
<ClInclude Include="vendor\imgui\backends\imgui_impl_dx12.h" />
|
||||
<ClInclude Include="vendor\imgui\backends\imgui_impl_win32.h" />
|
||||
<ClInclude Include="vendor\imgui\imconfig.h" />
|
||||
<ClInclude Include="vendor\imgui\imgui.h" />
|
||||
@ -365,6 +368,7 @@
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\cheat-base\inject\load-library.cpp" />
|
||||
<ClCompile Include="src\cheat-base\inject\manual-map.cpp" />
|
||||
<ClCompile Include="src\cheat-base\render\backend\dx12-hook.cpp" />
|
||||
<ClCompile Include="src\cheat-base\ResourceLoader.cpp" />
|
||||
<ClCompile Include="src\cheat-base\Hotkey.cpp" />
|
||||
<ClCompile Include="src\cheat-base\render\ImageLoader.cpp" />
|
||||
@ -410,6 +414,14 @@
|
||||
<PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release_WS|Win32'">pch.h</PrecompiledHeaderFile>
|
||||
<PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">pch.h</PrecompiledHeaderFile>
|
||||
</ClCompile>
|
||||
<ClCompile Include="vendor\imgui\backends\imgui_impl_dx12.cpp">
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release_WS|Win32'">NotUsing</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release_WS|x64'">NotUsing</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="vendor\imgui\backends\imgui_impl_win32.cpp">
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release_WS|x64'">NotUsing</PrecompiledHeader>
|
||||
|
@ -243,6 +243,15 @@
|
||||
<ClInclude Include="src\cheat-base\inject\load-library.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\cheat-base\ISerializable.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\cheat-base\render\backend\dx12-hook.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="vendor\imgui\backends\imgui_impl_dx12.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="src\cheat-base\util.cpp">
|
||||
@ -335,5 +344,11 @@
|
||||
<ClCompile Include="src\cheat-base\inject\load-library.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\cheat-base\render\backend\dx12-hook.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="vendor\imgui\backends\imgui_impl_dx12.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
@ -17,7 +17,7 @@ public:
|
||||
}
|
||||
|
||||
template <typename Fn>
|
||||
[[nodiscard]] static Fn getOrigin(Fn handler, const char* callerName = nullptr) noexcept
|
||||
static Fn getOrigin(Fn handler, const char* callerName = nullptr) noexcept
|
||||
{
|
||||
if (holderMap.count(reinterpret_cast<void*>(handler)) == 0) {
|
||||
LOG_WARNING("Origin not found for handler: %s. Maybe racing bug.", callerName == nullptr ? "<Unknown>" : callerName);
|
||||
@ -27,14 +27,17 @@ public:
|
||||
}
|
||||
|
||||
template <typename Fn>
|
||||
[[nodiscard]] static void detach(Fn handler) noexcept
|
||||
static void detach(Fn handler) noexcept
|
||||
{
|
||||
disable(handler);
|
||||
holderMap.erase(reinterpret_cast<void*>(handler));
|
||||
}
|
||||
|
||||
// I don't know why
|
||||
#ifdef _WIN64
|
||||
|
||||
template <typename RType, typename... Params>
|
||||
[[nodiscard]] static RType call(RType(*handler)(Params...), const char* callerName = nullptr, Params... params)
|
||||
static RType call(RType(*handler)(Params...), const char* callerName = nullptr, Params... params)
|
||||
{
|
||||
auto origin = getOrigin(handler, callerName);
|
||||
if (origin != nullptr)
|
||||
@ -43,6 +46,30 @@ public:
|
||||
return RType();
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
template <typename RType, typename... Params>
|
||||
static RType call(RType(__cdecl *handler)(Params...), const char* callerName = nullptr, Params... params)
|
||||
{
|
||||
auto origin = getOrigin(handler, callerName);
|
||||
if (origin != nullptr)
|
||||
return origin(params...);
|
||||
|
||||
return RType();
|
||||
}
|
||||
|
||||
template <typename RType, typename... Params>
|
||||
static RType call(RType(__stdcall *handler)(Params...), const char* callerName = nullptr, Params... params)
|
||||
{
|
||||
auto origin = getOrigin(handler, callerName);
|
||||
if (origin != nullptr)
|
||||
return origin(params...);
|
||||
|
||||
return RType();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static void detachAll() noexcept
|
||||
{
|
||||
for (const auto &[key, value] : holderMap)
|
||||
|
20
cheat-base/src/cheat-base/ISerializable.h
Normal file
20
cheat-base/src/cheat-base/ISerializable.h
Normal file
@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
class ISerializable
|
||||
{
|
||||
public:
|
||||
virtual void to_json(nlohmann::json& j) const = 0;
|
||||
virtual void from_json(const nlohmann::json& j) = 0;
|
||||
};
|
||||
|
||||
inline void to_json(nlohmann::json& j, const ISerializable& ser)
|
||||
{
|
||||
ser.to_json(j);
|
||||
}
|
||||
|
||||
inline void from_json(const nlohmann::json& j, ISerializable& ser)
|
||||
{
|
||||
ser.from_json(j);
|
||||
}
|
@ -16,18 +16,22 @@ PipeTransfer::PipeTransfer(const std::string& name)
|
||||
|
||||
PipeTransfer::~PipeTransfer()
|
||||
{
|
||||
if (m_Pipe)
|
||||
CloseHandle(m_Pipe);
|
||||
Close();
|
||||
}
|
||||
|
||||
bool PipeTransfer::Create()
|
||||
{
|
||||
if (m_Pipe)
|
||||
CloseHandle(m_Pipe);
|
||||
Close();
|
||||
m_Pipe = CreateNamedPipe(m_Name.c_str(), PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, 1, 256 * 1024, 16, INFINITE, NULL);
|
||||
return IsPipeOpened();
|
||||
}
|
||||
|
||||
void PipeTransfer::Close()
|
||||
{
|
||||
if (m_Pipe)
|
||||
CloseHandle(m_Pipe);
|
||||
}
|
||||
|
||||
bool PipeTransfer::IsPipeOpened()
|
||||
{
|
||||
return m_Pipe && m_Pipe != INVALID_HANDLE_VALUE;
|
||||
|
@ -20,6 +20,7 @@ public:
|
||||
~PipeTransfer();
|
||||
|
||||
bool Create();
|
||||
void Close();
|
||||
bool Connect();
|
||||
bool WaitForConnection();
|
||||
bool IsPipeOpened();
|
||||
|
@ -10,9 +10,9 @@
|
||||
namespace cheat
|
||||
{
|
||||
|
||||
void CheatManagerBase::Init(LPBYTE pFontData, DWORD dFontDataSize)
|
||||
void CheatManagerBase::Init(LPBYTE pFontData, DWORD dFontDataSize, renderer::DXVersion dxVersion)
|
||||
{
|
||||
renderer::Init(pFontData, dFontDataSize);
|
||||
renderer::Init(pFontData, dFontDataSize, dxVersion);
|
||||
|
||||
events::RenderEvent += MY_METHOD_HANDLER(CheatManagerBase::OnRender);
|
||||
events::KeyUpEvent += MY_METHOD_HANDLER(CheatManagerBase::OnKeyUp);
|
||||
|
@ -2,6 +2,7 @@
|
||||
#include <cheat-base/cheat/Feature.h>
|
||||
#include <cheat-base/config/Config.h>
|
||||
#include <cheat-base/events/event.hpp>
|
||||
#include <cheat-base/render/renderer.h>
|
||||
|
||||
#include <vector>
|
||||
#include <map>
|
||||
@ -30,7 +31,7 @@ namespace cheat
|
||||
void OnWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, bool& cancelled);
|
||||
void OnRender();
|
||||
|
||||
void Init(LPBYTE pFontData, DWORD dFontDataSize);
|
||||
void Init(LPBYTE pFontData, DWORD dFontDataSize, renderer::DXVersion dxVersion = renderer::DXVersion::D3D11);
|
||||
|
||||
virtual void CursorSetVisibility(bool visibility) = 0;
|
||||
virtual bool CursorGetVisibility() = 0;
|
||||
|
@ -6,7 +6,11 @@
|
||||
#include "fields/Toggle.h"
|
||||
#include "fields/Enum.h"
|
||||
|
||||
#define NFEX(field, friendName, name, section, defaultValue, shared) field##(config::CreateField<decltype(##field##)::_ValueType>(friendName, name, section, shared, defaultValue))
|
||||
#define SNFEX(field, friendName, name, section, defaultValue, shared) config::CreateField<decltype(##field##)::_ValueType>(friendName, name, section, shared, defaultValue)
|
||||
#define SNFB(field, name, section, defaultValue, shared) SNFEX(field, name, config::internal::FixFieldName(#field), section, defaultValue, shared)
|
||||
#define SNF(field, name, section, defaultValue) SNFB(field, name, section, defaultValue, false)
|
||||
|
||||
#define NFEX(field, friendName, name, section, defaultValue, shared) field##(SNFEX(field, friendName, name, section, defaultValue, shared))
|
||||
#define NFEXUP(field, friendName, name, section, shared, ...) field##(config::CreateField<decltype(##field##)::_ValueType>(friendName, name, section, shared, __VA_ARGS__))
|
||||
|
||||
#define NFB(field, name, section, defaultValue, shared) NFEX(field, name, config::internal::FixFieldName(#field), section, defaultValue, shared)
|
||||
|
@ -112,6 +112,13 @@ namespace config::internal
|
||||
return *this;
|
||||
}
|
||||
|
||||
FieldBase<T>& operator=(T&& other)
|
||||
{
|
||||
p_Container->m_Value = std::move(other);
|
||||
p_Container->FireChanged();
|
||||
return *this;
|
||||
}
|
||||
|
||||
FieldBase<T>& operator=(std::shared_ptr<FieldSerialize<T>>& other)
|
||||
{
|
||||
p_Container->ChangedEvent -= MY_METHOD_HANDLER(FieldBase<T>::OnFieldChanged);
|
||||
|
@ -5,6 +5,18 @@
|
||||
|
||||
namespace config::internal
|
||||
{
|
||||
namespace CHECK
|
||||
{
|
||||
struct No {};
|
||||
template<typename T, typename Arg> No operator== (const T&, const Arg&);
|
||||
|
||||
template<typename T, typename Arg = T>
|
||||
struct EqualExists
|
||||
{
|
||||
enum { value = !std::is_same<decltype(std::declval<T>() == std::declval<Arg>()), No>::value };
|
||||
};
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
class FieldSerialize : public FieldEntry
|
||||
{
|
||||
@ -14,8 +26,12 @@ namespace config::internal
|
||||
|
||||
nlohmann::json ToJson() override
|
||||
{
|
||||
if (m_Value == m_DefaultValue)
|
||||
return {};
|
||||
if constexpr (CHECK::EqualExists<T>::value)
|
||||
{
|
||||
if (m_Value == m_DefaultValue)
|
||||
return {};
|
||||
}
|
||||
|
||||
|
||||
return converters::ToJson(m_Value);
|
||||
}
|
||||
|
@ -4,7 +4,6 @@
|
||||
#include <cstdio>
|
||||
|
||||
#include <cheat-base/HookManager.h>
|
||||
|
||||
#pragma comment(lib, "D3dcompiler.lib")
|
||||
#pragma comment(lib, "d3d11.lib")
|
||||
#pragma comment(lib, "winmm.lib")
|
||||
@ -18,37 +17,55 @@ extern LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam
|
||||
static IDXGISwapChainPresent fnIDXGISwapChainPresent;
|
||||
static ID3D11Device* pDevice = nullptr;
|
||||
|
||||
static HRESULT __stdcall Present(IDXGISwapChain* pChain, const UINT SyncInterval, const UINT Flags)
|
||||
static HRESULT __stdcall Present_Hook(IDXGISwapChain* pChain, const UINT SyncInterval, const UINT Flags)
|
||||
{
|
||||
static BOOL g_bInitialised = false;
|
||||
|
||||
// Main D3D11 Objects
|
||||
static ID3D11DeviceContext* pContext = nullptr;
|
||||
|
||||
if (!g_bInitialised) {
|
||||
pChain->GetDevice(__uuidof(pDevice), reinterpret_cast<void**>(&pDevice));
|
||||
pDevice->GetImmediateContext(&pContext);
|
||||
|
||||
if (!g_bInitialised)
|
||||
{
|
||||
auto result = (HRESULT)pChain->GetDevice(__uuidof(pDevice), reinterpret_cast<void**>(&pDevice));
|
||||
|
||||
DXGI_SWAP_CHAIN_DESC sd;
|
||||
pChain->GetDesc(&sd);
|
||||
if (SUCCEEDED(result))
|
||||
{
|
||||
pDevice->GetImmediateContext(&pContext);
|
||||
|
||||
backend::DX11Events::InitializeEvent(sd.OutputWindow, pDevice, pContext, pChain);
|
||||
DXGI_SWAP_CHAIN_DESC sd;
|
||||
pChain->GetDesc(&sd);
|
||||
|
||||
g_bInitialised = true;
|
||||
backend::DX11Events::InitializeEvent(sd.OutputWindow, pDevice, pContext, pChain);
|
||||
|
||||
g_bInitialised = true;
|
||||
}
|
||||
}
|
||||
|
||||
// render function
|
||||
backend::DX11Events::RenderEvent(pContext);
|
||||
if (g_bInitialised)
|
||||
backend::DX11Events::RenderEvent(pContext);
|
||||
|
||||
return CALL_ORIGIN(Present, pChain, SyncInterval, Flags);
|
||||
return CALL_ORIGIN(Present_Hook, pChain, SyncInterval, Flags);
|
||||
}
|
||||
|
||||
static IDXGISwapChainPresent findDirect11Present()
|
||||
{
|
||||
const HWND hWnd = GetForegroundWindow();
|
||||
WNDCLASSEX wc{ 0 };
|
||||
wc.cbSize = sizeof(wc);
|
||||
wc.lpfnWndProc = DefWindowProc;
|
||||
wc.lpszClassName = TEXT("Class");
|
||||
|
||||
if (!RegisterClassEx(&wc))
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
HWND hWnd = CreateWindow(wc.lpszClassName, TEXT(""), WS_DISABLED, 0, 0, 0, 0, NULL, NULL, NULL, nullptr);
|
||||
|
||||
IDXGISwapChain* pSwapChain;
|
||||
|
||||
constexpr D3D_FEATURE_LEVEL featureLevel = D3D_FEATURE_LEVEL_11_0;
|
||||
D3D_FEATURE_LEVEL featureLevel;
|
||||
DXGI_SWAP_CHAIN_DESC swapChainDesc;
|
||||
ZeroMemory(&swapChainDesc, sizeof(swapChainDesc));
|
||||
swapChainDesc.BufferCount = 1;
|
||||
@ -64,11 +81,15 @@ static IDXGISwapChainPresent findDirect11Present()
|
||||
// Main D3D11 Objects
|
||||
ID3D11DeviceContext* pContext = nullptr;
|
||||
ID3D11Device* pDevice = nullptr;
|
||||
if (FAILED(D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_WARP, NULL, NULL, &featureLevel, 1,
|
||||
D3D11_SDK_VERSION, &swapChainDesc, &pSwapChain, &pDevice, NULL, &pContext)) &&
|
||||
FAILED(D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, NULL, &featureLevel, 1,
|
||||
D3D11_SDK_VERSION, &swapChainDesc, &pSwapChain, &pDevice, NULL, &pContext)))
|
||||
|
||||
if (/*FAILED(D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_WARP, NULL, NULL, &featureLevel, 1,
|
||||
D3D11_SDK_VERSION, &swapChainDesc, &pSwapChain, &pDevice, NULL, &pContext)) &&*/
|
||||
FAILED(D3D11CreateDeviceAndSwapChain(nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr, 0, nullptr, 0, D3D11_SDK_VERSION,
|
||||
&swapChainDesc, &pSwapChain, &pDevice, &featureLevel, nullptr)))
|
||||
{
|
||||
DestroyWindow(swapChainDesc.OutputWindow);
|
||||
UnregisterClass(wc.lpszClassName, GetModuleHandle(nullptr));
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@ -78,9 +99,12 @@ static IDXGISwapChainPresent findDirect11Present()
|
||||
auto swapChainPresent = reinterpret_cast<IDXGISwapChainPresent>(pSwapChainVtable[8]);
|
||||
|
||||
pDevice->Release();
|
||||
pContext->Release();
|
||||
//pContext->Release();
|
||||
pSwapChain->Release();
|
||||
|
||||
DestroyWindow(swapChainDesc.OutputWindow);
|
||||
UnregisterClass(wc.lpszClassName, GetModuleHandle(nullptr));
|
||||
|
||||
return swapChainPresent;
|
||||
}
|
||||
|
||||
@ -95,7 +119,7 @@ void backend::InitializeDX11Hooks()
|
||||
}
|
||||
LOG_DEBUG("SwapChain Present: %p", fnIDXGISwapChainPresent);
|
||||
|
||||
HookManager::install(fnIDXGISwapChainPresent, Present);
|
||||
HookManager::install(fnIDXGISwapChainPresent, Present_Hook);
|
||||
LOG_DEBUG("Initializing D3D11 hook: done.");
|
||||
}
|
||||
|
||||
|
@ -2,6 +2,8 @@
|
||||
#include <Windows.h>
|
||||
|
||||
#include <d3d11.h>
|
||||
#include <d3d12.h>
|
||||
|
||||
#include <d3dcompiler.h>
|
||||
|
||||
#include <cheat-base/events/event.hpp>
|
||||
@ -18,5 +20,6 @@ namespace backend
|
||||
public:
|
||||
inline static TEvent<ID3D11DeviceContext*> RenderEvent{};
|
||||
inline static TEvent<HWND, ID3D11Device*, ID3D11DeviceContext*, IDXGISwapChain*> InitializeEvent{};
|
||||
inline static TEvent<> FailedEvent{};
|
||||
};
|
||||
}
|
||||
|
515
cheat-base/src/cheat-base/render/backend/dx12-hook.cpp
Normal file
515
cheat-base/src/cheat-base/render/backend/dx12-hook.cpp
Normal file
@ -0,0 +1,515 @@
|
||||
#include <pch.h>
|
||||
#include "dx12-hook.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstdint>
|
||||
|
||||
#include <cheat-base/HookManager.h>
|
||||
|
||||
#include <dxgi1_4.h>
|
||||
|
||||
#pragma comment(lib, "D3dcompiler.lib")
|
||||
#pragma comment(lib, "d3d12.lib")
|
||||
#pragma comment(lib, "winmm.lib")
|
||||
|
||||
// D3X HOOK DEFINITIONS
|
||||
typedef HRESULT(APIENTRY* IDXGISwapChainPresent)(IDXGISwapChain3* pSwapChain, UINT SyncInterval, UINT Flags);
|
||||
typedef void(APIENTRY* DrawInstanced)(ID3D12GraphicsCommandList* dCommandList, UINT VertexCountPerInstance, UINT InstanceCount, UINT StartVertexLocation, UINT StartInstanceLocation);
|
||||
typedef void(APIENTRY* DrawIndexedInstanced)(ID3D12GraphicsCommandList* dCommandList, UINT IndexCountPerInstance, UINT InstanceCount, UINT StartIndexLocation, INT BaseVertexLocation, UINT StartInstanceLocation);
|
||||
typedef void(APIENTRY* ExecuteCommandLists)(ID3D12CommandQueue* queue, UINT NumCommandLists, ID3D12CommandList* ppCommandLists);
|
||||
|
||||
struct DirectX12MainFunctions
|
||||
{
|
||||
IDXGISwapChainPresent presentFunc;
|
||||
DrawInstanced drawInstancedFunc;
|
||||
DrawIndexedInstanced drawIndexedInstancedFunc;
|
||||
ExecuteCommandLists executeCommandListFunc;
|
||||
};
|
||||
|
||||
// Definition of WndProc Hook. Its here to avoid dragging dependencies on <windows.h> types.
|
||||
extern LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
|
||||
|
||||
namespace DirectX12Interface {
|
||||
ID3D12Device* Device = nullptr;
|
||||
ID3D12DescriptorHeap* DescriptorHeapBackBuffers;
|
||||
ID3D12DescriptorHeap* DescriptorHeapImGuiRender;
|
||||
ID3D12GraphicsCommandList* CommandList;
|
||||
ID3D12CommandQueue* CommandQueue;
|
||||
|
||||
struct _FrameContext {
|
||||
ID3D12CommandAllocator* CommandAllocator;
|
||||
ID3D12Resource* Resource;
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE DescriptorHandle;
|
||||
};
|
||||
|
||||
UINT BuffersCounts = -1;
|
||||
_FrameContext* FrameContext;
|
||||
}
|
||||
|
||||
static HRESULT __stdcall Present_Hook(IDXGISwapChain3* pChain, const UINT SyncInterval, const UINT Flags)
|
||||
{
|
||||
static BOOL g_bInitialised = false;
|
||||
|
||||
if (!g_bInitialised)
|
||||
{
|
||||
auto result = (HRESULT)pChain->GetDevice(__uuidof(DirectX12Interface::Device), reinterpret_cast<void**>(&DirectX12Interface::Device));
|
||||
LOG_DEBUG("Result of GetDevice: %x", HRESULT_CODE(result));
|
||||
|
||||
if (SUCCEEDED(result))
|
||||
{
|
||||
DXGI_SWAP_CHAIN_DESC Desc;
|
||||
pChain->GetDesc(&Desc);
|
||||
Desc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;
|
||||
Desc.Windowed = ((GetWindowLongPtr(Desc.OutputWindow, GWL_STYLE) & WS_POPUP) != 0) ? false : true;
|
||||
|
||||
DirectX12Interface::BuffersCounts = Desc.BufferCount;
|
||||
DirectX12Interface::FrameContext = new DirectX12Interface::_FrameContext[DirectX12Interface::BuffersCounts];
|
||||
|
||||
D3D12_DESCRIPTOR_HEAP_DESC DescriptorImGuiRender = {};
|
||||
DescriptorImGuiRender.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
|
||||
DescriptorImGuiRender.NumDescriptors = DirectX12Interface::BuffersCounts;
|
||||
DescriptorImGuiRender.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;
|
||||
|
||||
if (DirectX12Interface::Device->CreateDescriptorHeap(&DescriptorImGuiRender, IID_PPV_ARGS(&DirectX12Interface::DescriptorHeapImGuiRender)) != S_OK)
|
||||
return CALL_ORIGIN(Present_Hook, pChain, SyncInterval, Flags);
|
||||
|
||||
ID3D12CommandAllocator* Allocator;
|
||||
if (DirectX12Interface::Device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&Allocator)) != S_OK)
|
||||
return CALL_ORIGIN(Present_Hook, pChain, SyncInterval, Flags);
|
||||
|
||||
for (size_t i = 0; i < DirectX12Interface::BuffersCounts; i++) {
|
||||
DirectX12Interface::FrameContext[i].CommandAllocator = Allocator;
|
||||
}
|
||||
|
||||
if (DirectX12Interface::Device->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, Allocator, NULL, IID_PPV_ARGS(&DirectX12Interface::CommandList)) != S_OK ||
|
||||
DirectX12Interface::CommandList->Close() != S_OK)
|
||||
return CALL_ORIGIN(Present_Hook, pChain, SyncInterval, Flags);
|
||||
|
||||
D3D12_DESCRIPTOR_HEAP_DESC DescriptorBackBuffers;
|
||||
DescriptorBackBuffers.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV;
|
||||
DescriptorBackBuffers.NumDescriptors = DirectX12Interface::BuffersCounts;
|
||||
DescriptorBackBuffers.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE;
|
||||
DescriptorBackBuffers.NodeMask = 1;
|
||||
|
||||
if (DirectX12Interface::Device->CreateDescriptorHeap(&DescriptorBackBuffers, IID_PPV_ARGS(&DirectX12Interface::DescriptorHeapBackBuffers)) != S_OK)
|
||||
return CALL_ORIGIN(Present_Hook, pChain, SyncInterval, Flags);
|
||||
|
||||
const auto RTVDescriptorSize = DirectX12Interface::Device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV);
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE RTVHandle = DirectX12Interface::DescriptorHeapBackBuffers->GetCPUDescriptorHandleForHeapStart();
|
||||
|
||||
for (size_t i = 0; i < DirectX12Interface::BuffersCounts; i++) {
|
||||
ID3D12Resource* pBackBuffer = nullptr;
|
||||
DirectX12Interface::FrameContext[i].DescriptorHandle = RTVHandle;
|
||||
pChain->GetBuffer(i, IID_PPV_ARGS(&pBackBuffer));
|
||||
DirectX12Interface::Device->CreateRenderTargetView(pBackBuffer, nullptr, RTVHandle);
|
||||
DirectX12Interface::FrameContext[i].Resource = pBackBuffer;
|
||||
RTVHandle.ptr += RTVDescriptorSize;
|
||||
}
|
||||
|
||||
backend::DX12Events::InitializeEvent(Desc.OutputWindow, DirectX12Interface::Device, DirectX12Interface::BuffersCounts, DirectX12Interface::DescriptorHeapImGuiRender);
|
||||
|
||||
g_bInitialised = true;
|
||||
}
|
||||
}
|
||||
|
||||
// render function
|
||||
if (!g_bInitialised || DirectX12Interface::CommandQueue == nullptr)
|
||||
return CALL_ORIGIN(Present_Hook, pChain, SyncInterval, Flags);
|
||||
|
||||
backend::DX12Events::PreRenderEvent();
|
||||
|
||||
DirectX12Interface::_FrameContext& CurrentFrameContext = DirectX12Interface::FrameContext[pChain->GetCurrentBackBufferIndex()];
|
||||
CurrentFrameContext.CommandAllocator->Reset();
|
||||
|
||||
D3D12_RESOURCE_BARRIER Barrier;
|
||||
Barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
|
||||
Barrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
|
||||
Barrier.Transition.pResource = CurrentFrameContext.Resource;
|
||||
Barrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
|
||||
Barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_PRESENT;
|
||||
Barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_RENDER_TARGET;
|
||||
|
||||
DirectX12Interface::CommandList->Reset(CurrentFrameContext.CommandAllocator, nullptr);
|
||||
DirectX12Interface::CommandList->ResourceBarrier(1, &Barrier);
|
||||
DirectX12Interface::CommandList->OMSetRenderTargets(1, &CurrentFrameContext.DescriptorHandle, FALSE, nullptr);
|
||||
DirectX12Interface::CommandList->SetDescriptorHeaps(1, &DirectX12Interface::DescriptorHeapImGuiRender);
|
||||
|
||||
backend::DX12Events::PostRenderEvent(DirectX12Interface::CommandList);
|
||||
|
||||
Barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_RENDER_TARGET;
|
||||
Barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_PRESENT;
|
||||
DirectX12Interface::CommandList->ResourceBarrier(1, &Barrier);
|
||||
DirectX12Interface::CommandList->Close();
|
||||
DirectX12Interface::CommandQueue->ExecuteCommandLists(1, reinterpret_cast<ID3D12CommandList* const*>(&DirectX12Interface::CommandList));
|
||||
|
||||
return CALL_ORIGIN(Present_Hook, pChain, SyncInterval, Flags);
|
||||
}
|
||||
|
||||
void ExecuteCommandLists_Hook(ID3D12CommandQueue* queue, UINT NumCommandLists, ID3D12CommandList* ppCommandLists) {
|
||||
if (!DirectX12Interface::CommandQueue)
|
||||
DirectX12Interface::CommandQueue = queue;
|
||||
|
||||
CALL_ORIGIN(ExecuteCommandLists_Hook, queue, NumCommandLists, ppCommandLists);
|
||||
}
|
||||
|
||||
static void GetHardwareAdapter(IDXGIFactory4* pFactory, IDXGIAdapter1** ppAdapter)
|
||||
{
|
||||
*ppAdapter = nullptr;
|
||||
for (UINT adapterIndex = 0; ; ++adapterIndex)
|
||||
{
|
||||
IDXGIAdapter1* pAdapter = nullptr;
|
||||
if (DXGI_ERROR_NOT_FOUND == pFactory->EnumAdapters1(adapterIndex, &pAdapter))
|
||||
{
|
||||
// No more adapters to enumerate.
|
||||
break;
|
||||
}
|
||||
|
||||
// Check to see if the adapter supports Direct3D 12, but don't create the
|
||||
// actual device yet.
|
||||
if (SUCCEEDED(D3D12CreateDevice(pAdapter, D3D_FEATURE_LEVEL_11_0, _uuidof(ID3D12Device), nullptr)))
|
||||
{
|
||||
*ppAdapter = pAdapter;
|
||||
return;
|
||||
}
|
||||
pAdapter->Release();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
WNDCLASSEX WindowClass;
|
||||
HWND WindowHwnd;
|
||||
|
||||
bool InitWindow() {
|
||||
|
||||
WindowClass.cbSize = sizeof(WNDCLASSEX);
|
||||
WindowClass.style = CS_HREDRAW | CS_VREDRAW;
|
||||
WindowClass.lpfnWndProc = DefWindowProc;
|
||||
WindowClass.cbClsExtra = 0;
|
||||
WindowClass.cbWndExtra = 0;
|
||||
WindowClass.hInstance = GetModuleHandle(NULL);
|
||||
WindowClass.hIcon = NULL;
|
||||
WindowClass.hCursor = NULL;
|
||||
WindowClass.hbrBackground = NULL;
|
||||
WindowClass.lpszMenuName = NULL;
|
||||
WindowClass.lpszClassName = "MJ";
|
||||
WindowClass.hIconSm = NULL;
|
||||
RegisterClassEx(&WindowClass);
|
||||
WindowHwnd = CreateWindow(WindowClass.lpszClassName, "DirectX Window", WS_OVERLAPPEDWINDOW, 0, 0, 100, 100, NULL, NULL, WindowClass.hInstance, NULL);
|
||||
if (WindowHwnd == NULL) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool DeleteWindow() {
|
||||
DestroyWindow(WindowHwnd);
|
||||
UnregisterClass(WindowClass.lpszClassName, WindowClass.hInstance);
|
||||
if (WindowHwnd != NULL) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FindFunctions(DirectX12MainFunctions& mainFunctions) {
|
||||
|
||||
if (InitWindow() == false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
HMODULE D3D12Module = GetModuleHandle("d3d12.dll");
|
||||
HMODULE DXGIModule = GetModuleHandle("dxgi.dll");
|
||||
if (D3D12Module == NULL || DXGIModule == NULL) {
|
||||
DeleteWindow();
|
||||
return false;
|
||||
}
|
||||
|
||||
void* CreateDXGIFactory = GetProcAddress(DXGIModule, "CreateDXGIFactory");
|
||||
if (CreateDXGIFactory == NULL) {
|
||||
DeleteWindow();
|
||||
return false;
|
||||
}
|
||||
|
||||
IDXGIFactory* Factory;
|
||||
if (((long(__stdcall*)(const IID&, void**))(CreateDXGIFactory))(__uuidof(IDXGIFactory), (void**)&Factory) < 0) {
|
||||
DeleteWindow();
|
||||
return false;
|
||||
}
|
||||
|
||||
IDXGIAdapter* Adapter;
|
||||
if (Factory->EnumAdapters(0, &Adapter) == DXGI_ERROR_NOT_FOUND) {
|
||||
DeleteWindow();
|
||||
return false;
|
||||
}
|
||||
|
||||
void* D3D12CreateDevice = GetProcAddress(D3D12Module, "D3D12CreateDevice");
|
||||
if (D3D12CreateDevice == NULL) {
|
||||
DeleteWindow();
|
||||
return false;
|
||||
}
|
||||
|
||||
ID3D12Device* Device;
|
||||
if (((long(__stdcall*)(IUnknown*, D3D_FEATURE_LEVEL, const IID&, void**))(D3D12CreateDevice))(Adapter, D3D_FEATURE_LEVEL_11_0, __uuidof(ID3D12Device), (void**)&Device) < 0) {
|
||||
DeleteWindow();
|
||||
return false;
|
||||
}
|
||||
|
||||
D3D12_COMMAND_QUEUE_DESC QueueDesc;
|
||||
QueueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT;
|
||||
QueueDesc.Priority = 0;
|
||||
QueueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE;
|
||||
QueueDesc.NodeMask = 0;
|
||||
|
||||
ID3D12CommandQueue* CommandQueue;
|
||||
if (Device->CreateCommandQueue(&QueueDesc, __uuidof(ID3D12CommandQueue), (void**)&CommandQueue) < 0) {
|
||||
DeleteWindow();
|
||||
return false;
|
||||
}
|
||||
|
||||
ID3D12CommandAllocator* CommandAllocator;
|
||||
if (Device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, __uuidof(ID3D12CommandAllocator), (void**)&CommandAllocator) < 0) {
|
||||
DeleteWindow();
|
||||
return false;
|
||||
}
|
||||
|
||||
ID3D12GraphicsCommandList* CommandList;
|
||||
if (Device->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, CommandAllocator, NULL, __uuidof(ID3D12GraphicsCommandList), (void**)&CommandList) < 0) {
|
||||
DeleteWindow();
|
||||
return false;
|
||||
}
|
||||
|
||||
DXGI_RATIONAL RefreshRate;
|
||||
RefreshRate.Numerator = 60;
|
||||
RefreshRate.Denominator = 1;
|
||||
|
||||
DXGI_MODE_DESC BufferDesc;
|
||||
BufferDesc.Width = 100;
|
||||
BufferDesc.Height = 100;
|
||||
BufferDesc.RefreshRate = RefreshRate;
|
||||
BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
|
||||
BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
|
||||
|
||||
DXGI_SAMPLE_DESC SampleDesc;
|
||||
SampleDesc.Count = 1;
|
||||
SampleDesc.Quality = 0;
|
||||
|
||||
DXGI_SWAP_CHAIN_DESC SwapChainDesc = {};
|
||||
SwapChainDesc.BufferDesc = BufferDesc;
|
||||
SwapChainDesc.SampleDesc = SampleDesc;
|
||||
SwapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
|
||||
SwapChainDesc.BufferCount = 2;
|
||||
SwapChainDesc.OutputWindow = WindowHwnd;
|
||||
SwapChainDesc.Windowed = 1;
|
||||
SwapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
|
||||
SwapChainDesc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;
|
||||
|
||||
IDXGISwapChain* SwapChain;
|
||||
if (Factory->CreateSwapChain(CommandQueue, &SwapChainDesc, &SwapChain) < 0) {
|
||||
DeleteWindow();
|
||||
return false;
|
||||
}
|
||||
|
||||
typedef uint64_t uintx_t;
|
||||
auto MethodsTable = (uintx_t*)::calloc(150, sizeof(uintx_t));
|
||||
memcpy(MethodsTable, *(uintx_t**)Device, 44 * sizeof(uintx_t));
|
||||
memcpy(MethodsTable + 44, *(uintx_t**)CommandQueue, 19 * sizeof(uintx_t));
|
||||
memcpy(MethodsTable + 44 + 19, *(uintx_t**)CommandAllocator, 9 * sizeof(uintx_t));
|
||||
memcpy(MethodsTable + 44 + 19 + 9, *(uintx_t**)CommandList, 60 * sizeof(uintx_t));
|
||||
memcpy(MethodsTable + 44 + 19 + 9 + 60, *(uintx_t**)SwapChain, 18 * sizeof(uintx_t));
|
||||
|
||||
mainFunctions.presentFunc = reinterpret_cast<decltype(mainFunctions.presentFunc)>(MethodsTable[140]);
|
||||
mainFunctions.drawInstancedFunc = reinterpret_cast<decltype(mainFunctions.drawInstancedFunc)>(MethodsTable[84]);
|
||||
mainFunctions.drawIndexedInstancedFunc = reinterpret_cast<decltype(mainFunctions.drawIndexedInstancedFunc)>(MethodsTable[85]);
|
||||
mainFunctions.executeCommandListFunc = reinterpret_cast<decltype(mainFunctions.executeCommandListFunc)>(MethodsTable[54]);
|
||||
|
||||
free(MethodsTable);
|
||||
|
||||
Device->Release();
|
||||
Device = NULL;
|
||||
CommandQueue->Release();
|
||||
CommandQueue = NULL;
|
||||
CommandAllocator->Release();
|
||||
CommandAllocator = NULL;
|
||||
CommandList->Release();
|
||||
CommandList = NULL;
|
||||
SwapChain->Release();
|
||||
SwapChain = NULL;
|
||||
DeleteWindow();
|
||||
return true;
|
||||
}
|
||||
|
||||
void backend::InitializeDX12Hooks()
|
||||
{
|
||||
LOG_DEBUG("Initializing D3D12 hook: started.");
|
||||
|
||||
DirectX12MainFunctions mainFuncs;
|
||||
if (!FindFunctions(mainFuncs))
|
||||
{
|
||||
LOG_ERROR("Failed to find 'Present' function for D3D12.");
|
||||
return;
|
||||
}
|
||||
|
||||
LOG_DEBUG("IDXGISwapChainPresent Present: %p", mainFuncs.presentFunc);
|
||||
LOG_DEBUG("DrawInstanced Present: %p", mainFuncs.drawInstancedFunc);
|
||||
LOG_DEBUG("DrawIndexedInstanced Present: %p", mainFuncs.drawIndexedInstancedFunc);
|
||||
LOG_DEBUG("ExecuteCommandLists Present: %p", mainFuncs.executeCommandListFunc);
|
||||
|
||||
HookManager::install(mainFuncs.presentFunc, Present_Hook);
|
||||
HookManager::install(mainFuncs.executeCommandListFunc, ExecuteCommandLists_Hook);
|
||||
|
||||
LOG_DEBUG("Initializing D3D12 hook: done.");
|
||||
}
|
||||
|
||||
bool backend::LoadTextureFromMemory(LPBYTE image_data, int image_width, int image_height, D3D12_CPU_DESCRIPTOR_HANDLE srv_cpu_handle,
|
||||
ID3D12Resource** out_tex_resource, int* out_width, int* out_height)
|
||||
{
|
||||
if (DirectX12Interface::Device == nullptr)
|
||||
return false;
|
||||
|
||||
// Create texture resource
|
||||
D3D12_HEAP_PROPERTIES props;
|
||||
memset(&props, 0, sizeof(D3D12_HEAP_PROPERTIES));
|
||||
props.Type = D3D12_HEAP_TYPE_DEFAULT;
|
||||
props.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
|
||||
props.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
|
||||
|
||||
D3D12_RESOURCE_DESC desc;
|
||||
ZeroMemory(&desc, sizeof(desc));
|
||||
desc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
|
||||
desc.Alignment = 0;
|
||||
desc.Width = image_width;
|
||||
desc.Height = image_height;
|
||||
desc.DepthOrArraySize = 1;
|
||||
desc.MipLevels = 1;
|
||||
desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
desc.SampleDesc.Count = 1;
|
||||
desc.SampleDesc.Quality = 0;
|
||||
desc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN;
|
||||
desc.Flags = D3D12_RESOURCE_FLAG_NONE;
|
||||
|
||||
ID3D12Resource* pTexture = NULL;
|
||||
DirectX12Interface::Device->CreateCommittedResource(&props, D3D12_HEAP_FLAG_NONE, &desc,
|
||||
D3D12_RESOURCE_STATE_COPY_DEST, NULL, IID_PPV_ARGS(&pTexture));
|
||||
|
||||
// Create a temporary upload resource to move the data in
|
||||
UINT uploadPitch = (image_width * 4 + D3D12_TEXTURE_DATA_PITCH_ALIGNMENT - 1u) & ~(D3D12_TEXTURE_DATA_PITCH_ALIGNMENT - 1u);
|
||||
UINT uploadSize = image_height * uploadPitch;
|
||||
desc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
|
||||
desc.Alignment = 0;
|
||||
desc.Width = uploadSize;
|
||||
desc.Height = 1;
|
||||
desc.DepthOrArraySize = 1;
|
||||
desc.MipLevels = 1;
|
||||
desc.Format = DXGI_FORMAT_UNKNOWN;
|
||||
desc.SampleDesc.Count = 1;
|
||||
desc.SampleDesc.Quality = 0;
|
||||
desc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
|
||||
desc.Flags = D3D12_RESOURCE_FLAG_NONE;
|
||||
|
||||
props.Type = D3D12_HEAP_TYPE_UPLOAD;
|
||||
props.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
|
||||
props.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
|
||||
|
||||
ID3D12Resource* uploadBuffer = NULL;
|
||||
HRESULT hr = DirectX12Interface::Device->CreateCommittedResource(&props, D3D12_HEAP_FLAG_NONE, &desc,
|
||||
D3D12_RESOURCE_STATE_GENERIC_READ, NULL, IID_PPV_ARGS(&uploadBuffer));
|
||||
IM_ASSERT(SUCCEEDED(hr));
|
||||
|
||||
// Write pixels into the upload resource
|
||||
void* mapped = NULL;
|
||||
D3D12_RANGE range = { 0, uploadSize };
|
||||
hr = uploadBuffer->Map(0, &range, &mapped);
|
||||
IM_ASSERT(SUCCEEDED(hr));
|
||||
for (int y = 0; y < image_height; y++)
|
||||
memcpy((void*)((uintptr_t)mapped + y * uploadPitch), image_data + y * image_width * 4, image_width * 4);
|
||||
uploadBuffer->Unmap(0, &range);
|
||||
|
||||
// Copy the upload resource content into the real resource
|
||||
D3D12_TEXTURE_COPY_LOCATION srcLocation = {};
|
||||
srcLocation.pResource = uploadBuffer;
|
||||
srcLocation.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT;
|
||||
srcLocation.PlacedFootprint.Footprint.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
srcLocation.PlacedFootprint.Footprint.Width = image_width;
|
||||
srcLocation.PlacedFootprint.Footprint.Height = image_height;
|
||||
srcLocation.PlacedFootprint.Footprint.Depth = 1;
|
||||
srcLocation.PlacedFootprint.Footprint.RowPitch = uploadPitch;
|
||||
|
||||
D3D12_TEXTURE_COPY_LOCATION dstLocation = {};
|
||||
dstLocation.pResource = pTexture;
|
||||
dstLocation.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
|
||||
dstLocation.SubresourceIndex = 0;
|
||||
|
||||
D3D12_RESOURCE_BARRIER barrier = {};
|
||||
barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
|
||||
barrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
|
||||
barrier.Transition.pResource = pTexture;
|
||||
barrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
|
||||
barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_COPY_DEST;
|
||||
barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE;
|
||||
|
||||
// Create a temporary command queue to do the copy with
|
||||
ID3D12Fence* fence = NULL;
|
||||
hr = DirectX12Interface::Device->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&fence));
|
||||
IM_ASSERT(SUCCEEDED(hr));
|
||||
|
||||
HANDLE event = CreateEvent(0, 0, 0, 0);
|
||||
IM_ASSERT(event != NULL);
|
||||
|
||||
D3D12_COMMAND_QUEUE_DESC queueDesc = {};
|
||||
queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT;
|
||||
queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE;
|
||||
queueDesc.NodeMask = 1;
|
||||
|
||||
ID3D12CommandQueue* cmdQueue = NULL;
|
||||
hr = DirectX12Interface::Device->CreateCommandQueue(&queueDesc, IID_PPV_ARGS(&cmdQueue));
|
||||
IM_ASSERT(SUCCEEDED(hr));
|
||||
|
||||
ID3D12CommandAllocator* cmdAlloc = NULL;
|
||||
hr = DirectX12Interface::Device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&cmdAlloc));
|
||||
IM_ASSERT(SUCCEEDED(hr));
|
||||
|
||||
ID3D12GraphicsCommandList* cmdList = NULL;
|
||||
hr = DirectX12Interface::Device->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, cmdAlloc, NULL, IID_PPV_ARGS(&cmdList));
|
||||
IM_ASSERT(SUCCEEDED(hr));
|
||||
|
||||
cmdList->CopyTextureRegion(&dstLocation, 0, 0, 0, &srcLocation, NULL);
|
||||
cmdList->ResourceBarrier(1, &barrier);
|
||||
|
||||
hr = cmdList->Close();
|
||||
IM_ASSERT(SUCCEEDED(hr));
|
||||
|
||||
// Execute the copy
|
||||
cmdQueue->ExecuteCommandLists(1, (ID3D12CommandList* const*)&cmdList);
|
||||
hr = cmdQueue->Signal(fence, 1);
|
||||
IM_ASSERT(SUCCEEDED(hr));
|
||||
|
||||
// Wait for everything to complete
|
||||
fence->SetEventOnCompletion(1, event);
|
||||
WaitForSingleObject(event, INFINITE);
|
||||
|
||||
// Tear down our temporary command queue and release the upload resource
|
||||
cmdList->Release();
|
||||
cmdAlloc->Release();
|
||||
cmdQueue->Release();
|
||||
CloseHandle(event);
|
||||
fence->Release();
|
||||
uploadBuffer->Release();
|
||||
|
||||
// Create a shader resource view for the texture
|
||||
D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc;
|
||||
ZeroMemory(&srvDesc, sizeof(srvDesc));
|
||||
srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
|
||||
srvDesc.Texture2D.MipLevels = desc.MipLevels;
|
||||
srvDesc.Texture2D.MostDetailedMip = 0;
|
||||
srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
|
||||
DirectX12Interface::Device->CreateShaderResourceView(pTexture, &srvDesc, srv_cpu_handle);
|
||||
|
||||
// Return results
|
||||
*out_tex_resource = pTexture;
|
||||
*out_width = image_width;
|
||||
*out_height = image_height;
|
||||
|
||||
return true;
|
||||
}
|
27
cheat-base/src/cheat-base/render/backend/dx12-hook.h
Normal file
27
cheat-base/src/cheat-base/render/backend/dx12-hook.h
Normal file
@ -0,0 +1,27 @@
|
||||
#pragma once
|
||||
#include <Windows.h>
|
||||
|
||||
#include <d3d12.h>
|
||||
|
||||
#include <d3dcompiler.h>
|
||||
|
||||
#include <cheat-base/events/event.hpp>
|
||||
|
||||
namespace backend
|
||||
{
|
||||
void InitializeDX12Hooks();
|
||||
|
||||
// Thanks to https://github.com/ocornut/imgui/wiki/Image-Loading-and-Displaying-Examples#example-for-directx11-users
|
||||
bool LoadTextureFromMemory(LPBYTE image_data, int image_width, int image_height, D3D12_CPU_DESCRIPTOR_HANDLE srv_cpu_handle,
|
||||
ID3D12Resource** out_tex_resource, int* out_width, int* out_height);
|
||||
|
||||
class DX12Events
|
||||
{
|
||||
public:
|
||||
inline static TEvent<> PreRenderEvent{};
|
||||
inline static TEvent<ID3D12GraphicsCommandList*> PostRenderEvent{};
|
||||
inline static TEvent<HWND, ID3D12Device*, UINT, ID3D12DescriptorHeap*> InitializeEvent{};
|
||||
};
|
||||
|
||||
|
||||
}
|
@ -2,10 +2,15 @@
|
||||
#include "renderer.h"
|
||||
|
||||
#include <backends/imgui_impl_dx11.h>
|
||||
#pragma comment(lib, "dxgi")
|
||||
#include <backends/imgui_impl_dx12.h>
|
||||
|
||||
#include <backends/imgui_impl_win32.h>
|
||||
|
||||
#include <cheat-base/util.h>
|
||||
#include <cheat-base/render/backend/dx11-hook.h>
|
||||
#include <cheat-base/render/backend/dx12-hook.h>
|
||||
|
||||
#include <cheat-base/ResourceLoader.h>
|
||||
|
||||
extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
|
||||
@ -33,19 +38,39 @@ namespace renderer
|
||||
static WNDPROC OriginalWndProcHandler;
|
||||
static ID3D11RenderTargetView* mainRenderTargetView;
|
||||
|
||||
static void OnRender(ID3D11DeviceContext* pContext);
|
||||
static void OnDX11Initialize(HWND window, ID3D11Device* pDevice, ID3D11DeviceContext* pContext, IDXGISwapChain* pChain);
|
||||
static void OnRenderDX11(ID3D11DeviceContext* pContext);
|
||||
static void OnInitializeDX11(HWND window, ID3D11Device* pDevice, ID3D11DeviceContext* pContext, IDXGISwapChain* pChain);
|
||||
|
||||
static void OnPreRenderDX12();
|
||||
static void OnPostRenderDX12(ID3D12GraphicsCommandList* commandList);
|
||||
static void OnInitializeDX12(HWND window, ID3D12Device* pDevice, UINT buffersCounts, ID3D12DescriptorHeap* pDescriptorHeapImGuiRender);
|
||||
|
||||
void Init(LPBYTE fontData, DWORD fontDataSize)
|
||||
|
||||
|
||||
void Init(LPBYTE fontData, DWORD fontDataSize, DXVersion version)
|
||||
{
|
||||
_customFontData = { fontData, fontDataSize };
|
||||
|
||||
LOG_DEBUG("Initialize IMGui...");
|
||||
|
||||
backend::DX11Events::RenderEvent += FUNCTION_HANDLER(OnRender);
|
||||
backend::DX11Events::InitializeEvent += FUNCTION_HANDLER(OnDX11Initialize);
|
||||
|
||||
backend::InitializeDX11Hooks();
|
||||
switch (version)
|
||||
{
|
||||
case renderer::DXVersion::D3D11:
|
||||
backend::DX11Events::RenderEvent += FUNCTION_HANDLER(OnRenderDX11);
|
||||
backend::DX11Events::InitializeEvent += FUNCTION_HANDLER(OnInitializeDX11);
|
||||
backend::InitializeDX11Hooks();
|
||||
break;
|
||||
case renderer::DXVersion::D3D12:
|
||||
backend::DX12Events::InitializeEvent += FUNCTION_HANDLER(OnInitializeDX12);
|
||||
backend::DX12Events::PreRenderEvent += FUNCTION_HANDLER(OnPreRenderDX12);
|
||||
backend::DX12Events::PostRenderEvent += FUNCTION_HANDLER(OnPostRenderDX12);
|
||||
backend::InitializeDX12Hooks();
|
||||
break;
|
||||
case renderer::DXVersion::D3D9:
|
||||
case renderer::DXVersion::D3D10:
|
||||
default:
|
||||
LOG_ERROR("Used unsupported version of DX.");
|
||||
}
|
||||
}
|
||||
|
||||
void SetInputLock(void* id, bool value)
|
||||
@ -134,7 +159,53 @@ namespace renderer
|
||||
static void SetupImGuiStyle();
|
||||
static LRESULT CALLBACK hWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
||||
|
||||
static void OnDX11Initialize(HWND window, ID3D11Device* pDevice, ID3D11DeviceContext* pContext, IDXGISwapChain* pChain)
|
||||
void OnPreRenderDX12()
|
||||
{
|
||||
ImGui_ImplDX12_NewFrame();
|
||||
ImGui_ImplWin32_NewFrame();
|
||||
|
||||
ImGuiIO& io = ImGui::GetIO(); (void)io;
|
||||
io.FontDefault = GetFontBySize(_globalFontSize);
|
||||
ImGui::NewFrame();
|
||||
|
||||
events::RenderEvent();
|
||||
|
||||
ImGui::EndFrame();
|
||||
}
|
||||
|
||||
void OnPostRenderDX12(ID3D12GraphicsCommandList* commandList)
|
||||
{
|
||||
ImGui::Render();
|
||||
ImGui_ImplDX12_RenderDrawData(ImGui::GetDrawData(), commandList);
|
||||
}
|
||||
|
||||
void OnInitializeDX12(HWND window, ID3D12Device* pDevice, UINT buffersCounts, ID3D12DescriptorHeap* pDescriptorHeapImGuiRender)
|
||||
{
|
||||
LOG_DEBUG("ImGUI: DirectX12 backend initialized successfully.");
|
||||
|
||||
ImGui::CreateContext();
|
||||
ImGuiIO& io = ImGui::GetIO(); (void)io;
|
||||
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;
|
||||
|
||||
LoadCustomFont();
|
||||
SetupImGuiStyle();
|
||||
|
||||
//Set OriginalWndProcHandler to the Address of the Original WndProc function
|
||||
OriginalWndProcHandler = reinterpret_cast<WNDPROC>(SetWindowLongPtr(window, GWLP_WNDPROC,
|
||||
reinterpret_cast<LONG_PTR>(hWndProc)));
|
||||
|
||||
ImGui_ImplWin32_Init(window);
|
||||
ImGui_ImplDX12_Init(pDevice, buffersCounts, DXGI_FORMAT_R8G8B8A8_UNORM,
|
||||
pDescriptorHeapImGuiRender,
|
||||
pDescriptorHeapImGuiRender->GetCPUDescriptorHandleForHeapStart(),
|
||||
pDescriptorHeapImGuiRender->GetGPUDescriptorHandleForHeapStart());
|
||||
|
||||
ImGui_ImplDX12_CreateDeviceObjects();
|
||||
ImGui::GetIO().ImeWindowHandle = window;
|
||||
io.SetPlatformImeDataFn = nullptr; // F**king bug take 4 hours of my life
|
||||
}
|
||||
|
||||
static void OnInitializeDX11(HWND window, ID3D11Device* pDevice, ID3D11DeviceContext* pContext, IDXGISwapChain* pChain)
|
||||
{
|
||||
|
||||
LOG_DEBUG("ImGUI: DirectX11 backend initialized successfully.");
|
||||
@ -161,7 +232,7 @@ namespace renderer
|
||||
io.SetPlatformImeDataFn = nullptr; // F**king bug take 4 hours of my life
|
||||
}
|
||||
|
||||
static void OnRender(ID3D11DeviceContext* pContext)
|
||||
static void OnRenderDX11(ID3D11DeviceContext* pContext)
|
||||
{
|
||||
ImGui_ImplDX11_NewFrame();
|
||||
ImGui_ImplWin32_NewFrame();
|
||||
|
@ -5,7 +5,15 @@
|
||||
|
||||
namespace renderer
|
||||
{
|
||||
void Init(LPBYTE pFontData, DWORD dFontDataSize);
|
||||
enum class DXVersion
|
||||
{
|
||||
D3D9,
|
||||
D3D10,
|
||||
D3D11,
|
||||
D3D12
|
||||
};
|
||||
|
||||
void Init(LPBYTE pFontData, DWORD dFontDataSize, DXVersion version = DXVersion::D3D11);
|
||||
|
||||
// Font sizing
|
||||
ImFont* GetFontBySize(float fontSize);
|
||||
|
@ -272,6 +272,18 @@ namespace util
|
||||
return static_cast<int64_t>(timezoneInfo.Bias) * 60;
|
||||
}
|
||||
|
||||
void OpenConsole()
|
||||
{
|
||||
AllocConsole();
|
||||
freopen_s((FILE**)stdout, "CONOUT$", "w", stdout);
|
||||
freopen_s((FILE**)stderr, "CONOUT$", "w", stderr);
|
||||
|
||||
auto consoleWindow = GetConsoleWindow();
|
||||
SetForegroundWindow(consoleWindow);
|
||||
ShowWindow(consoleWindow, SW_RESTORE);
|
||||
ShowWindow(consoleWindow, SW_SHOW);
|
||||
}
|
||||
|
||||
void OpenURL(const char* url)
|
||||
{
|
||||
ShellExecute(nullptr, nullptr, url, nullptr, nullptr, SW_SHOW);
|
||||
|
@ -45,6 +45,7 @@ namespace util
|
||||
|
||||
int64_t GetTimezoneBias();
|
||||
|
||||
void OpenConsole();
|
||||
|
||||
template<typename ... Args>
|
||||
std::string string_format(const std::string& format, Args ... args)
|
||||
|
Reference in New Issue
Block a user