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:
parent
d975e5ee58
commit
4d44b45b7e
@ -125,7 +125,7 @@
|
|||||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||||
<LanguageStandard>stdcpp20</LanguageStandard>
|
<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>
|
<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>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<SubSystem>
|
<SubSystem>
|
||||||
@ -158,7 +158,7 @@
|
|||||||
<Optimization>MaxSpeed</Optimization>
|
<Optimization>MaxSpeed</Optimization>
|
||||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
<OmitFramePointers>false</OmitFramePointers>
|
<OmitFramePointers>false</OmitFramePointers>
|
||||||
<LanguageStandard_C>stdc17</LanguageStandard_C>
|
<LanguageStandard_C>Default</LanguageStandard_C>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<SubSystem>
|
<SubSystem>
|
||||||
@ -193,7 +193,7 @@
|
|||||||
<Optimization>MaxSpeed</Optimization>
|
<Optimization>MaxSpeed</Optimization>
|
||||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
<OmitFramePointers>false</OmitFramePointers>
|
<OmitFramePointers>false</OmitFramePointers>
|
||||||
<LanguageStandard_C>stdc17</LanguageStandard_C>
|
<LanguageStandard_C>Default</LanguageStandard_C>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<SubSystem>
|
<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>
|
<PreprocessorDefinitions>_DEBUG;_SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING;_SILENCE_ALL_CXX17_DEPRECATION_WARNINGS;_CRT_SECURE_NO_WARNINGS;_MBCS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||||
<LanguageStandard_C>stdc17</LanguageStandard_C>
|
<LanguageStandard_C>Default</LanguageStandard_C>
|
||||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||||
<SupportJustMyCode>false</SupportJustMyCode>
|
<SupportJustMyCode>false</SupportJustMyCode>
|
||||||
<BufferSecurityCheck>false</BufferSecurityCheck>
|
<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>
|
<PreprocessorDefinitions>_SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING;_SILENCE_ALL_CXX17_DEPRECATION_WARNINGS;_CRT_SECURE_NO_WARNINGS;_MBCS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||||
<LanguageStandard_C>stdc17</LanguageStandard_C>
|
<LanguageStandard_C>Default</LanguageStandard_C>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Lib>
|
<Lib>
|
||||||
<AdditionalDependencies>detours-$(PlatformShortName).lib</AdditionalDependencies>
|
<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>
|
<PreprocessorDefinitions>_SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING;_SILENCE_ALL_CXX17_DEPRECATION_WARNINGS;_CRT_SECURE_NO_WARNINGS;_MBCS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||||
<LanguageStandard_C>stdc17</LanguageStandard_C>
|
<LanguageStandard_C>Default</LanguageStandard_C>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Lib>
|
<Lib>
|
||||||
<AdditionalDependencies>detours-$(PlatformShortName).lib</AdditionalDependencies>
|
<AdditionalDependencies>detours-$(PlatformShortName).lib</AdditionalDependencies>
|
||||||
@ -298,6 +298,8 @@
|
|||||||
<ClInclude Include="src\cheat-base\events\joins\handlereventjoin.hpp" />
|
<ClInclude Include="src\cheat-base\events\joins\handlereventjoin.hpp" />
|
||||||
<ClInclude Include="src\cheat-base\inject\load-library.h" />
|
<ClInclude Include="src\cheat-base\inject\load-library.h" />
|
||||||
<ClInclude Include="src\cheat-base\inject\manual-map.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\ResourceLoader.h" />
|
||||||
<ClInclude Include="src\cheat-base\Hotkey.h" />
|
<ClInclude Include="src\cheat-base\Hotkey.h" />
|
||||||
<ClInclude Include="src\cheat-base\render\ImageLoader.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\font_awesome_5.h" />
|
||||||
<ClInclude Include="vendor\imgui-notify-v2\imgui_notify.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_dx11.h" />
|
||||||
|
<ClInclude Include="vendor\imgui\backends\imgui_impl_dx12.h" />
|
||||||
<ClInclude Include="vendor\imgui\backends\imgui_impl_win32.h" />
|
<ClInclude Include="vendor\imgui\backends\imgui_impl_win32.h" />
|
||||||
<ClInclude Include="vendor\imgui\imconfig.h" />
|
<ClInclude Include="vendor\imgui\imconfig.h" />
|
||||||
<ClInclude Include="vendor\imgui\imgui.h" />
|
<ClInclude Include="vendor\imgui\imgui.h" />
|
||||||
@ -365,6 +368,7 @@
|
|||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="src\cheat-base\inject\load-library.cpp" />
|
<ClCompile Include="src\cheat-base\inject\load-library.cpp" />
|
||||||
<ClCompile Include="src\cheat-base\inject\manual-map.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\ResourceLoader.cpp" />
|
||||||
<ClCompile Include="src\cheat-base\Hotkey.cpp" />
|
<ClCompile Include="src\cheat-base\Hotkey.cpp" />
|
||||||
<ClCompile Include="src\cheat-base\render\ImageLoader.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_WS|Win32'">pch.h</PrecompiledHeaderFile>
|
||||||
<PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">pch.h</PrecompiledHeaderFile>
|
<PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">pch.h</PrecompiledHeaderFile>
|
||||||
</ClCompile>
|
</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">
|
<ClCompile Include="vendor\imgui\backends\imgui_impl_win32.cpp">
|
||||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
|
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
|
||||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release_WS|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">
|
<ClInclude Include="src\cheat-base\inject\load-library.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</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>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="src\cheat-base\util.cpp">
|
<ClCompile Include="src\cheat-base\util.cpp">
|
||||||
@ -335,5 +344,11 @@
|
|||||||
<ClCompile Include="src\cheat-base\inject\load-library.cpp">
|
<ClCompile Include="src\cheat-base\inject\load-library.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</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>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
@ -17,7 +17,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename Fn>
|
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) {
|
if (holderMap.count(reinterpret_cast<void*>(handler)) == 0) {
|
||||||
LOG_WARNING("Origin not found for handler: %s. Maybe racing bug.", callerName == nullptr ? "<Unknown>" : callerName);
|
LOG_WARNING("Origin not found for handler: %s. Maybe racing bug.", callerName == nullptr ? "<Unknown>" : callerName);
|
||||||
@ -27,14 +27,17 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename Fn>
|
template <typename Fn>
|
||||||
[[nodiscard]] static void detach(Fn handler) noexcept
|
static void detach(Fn handler) noexcept
|
||||||
{
|
{
|
||||||
disable(handler);
|
disable(handler);
|
||||||
holderMap.erase(reinterpret_cast<void*>(handler));
|
holderMap.erase(reinterpret_cast<void*>(handler));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// I don't know why
|
||||||
|
#ifdef _WIN64
|
||||||
|
|
||||||
template <typename RType, typename... Params>
|
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);
|
auto origin = getOrigin(handler, callerName);
|
||||||
if (origin != nullptr)
|
if (origin != nullptr)
|
||||||
@ -43,6 +46,30 @@ public:
|
|||||||
return RType();
|
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
|
static void detachAll() noexcept
|
||||||
{
|
{
|
||||||
for (const auto &[key, value] : holderMap)
|
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()
|
PipeTransfer::~PipeTransfer()
|
||||||
{
|
{
|
||||||
if (m_Pipe)
|
Close();
|
||||||
CloseHandle(m_Pipe);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PipeTransfer::Create()
|
bool PipeTransfer::Create()
|
||||||
{
|
{
|
||||||
if (m_Pipe)
|
Close();
|
||||||
CloseHandle(m_Pipe);
|
|
||||||
m_Pipe = CreateNamedPipe(m_Name.c_str(), PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, 1, 256 * 1024, 16, INFINITE, NULL);
|
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();
|
return IsPipeOpened();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PipeTransfer::Close()
|
||||||
|
{
|
||||||
|
if (m_Pipe)
|
||||||
|
CloseHandle(m_Pipe);
|
||||||
|
}
|
||||||
|
|
||||||
bool PipeTransfer::IsPipeOpened()
|
bool PipeTransfer::IsPipeOpened()
|
||||||
{
|
{
|
||||||
return m_Pipe && m_Pipe != INVALID_HANDLE_VALUE;
|
return m_Pipe && m_Pipe != INVALID_HANDLE_VALUE;
|
||||||
|
@ -20,6 +20,7 @@ public:
|
|||||||
~PipeTransfer();
|
~PipeTransfer();
|
||||||
|
|
||||||
bool Create();
|
bool Create();
|
||||||
|
void Close();
|
||||||
bool Connect();
|
bool Connect();
|
||||||
bool WaitForConnection();
|
bool WaitForConnection();
|
||||||
bool IsPipeOpened();
|
bool IsPipeOpened();
|
||||||
|
@ -10,9 +10,9 @@
|
|||||||
namespace cheat
|
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::RenderEvent += MY_METHOD_HANDLER(CheatManagerBase::OnRender);
|
||||||
events::KeyUpEvent += MY_METHOD_HANDLER(CheatManagerBase::OnKeyUp);
|
events::KeyUpEvent += MY_METHOD_HANDLER(CheatManagerBase::OnKeyUp);
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#include <cheat-base/cheat/Feature.h>
|
#include <cheat-base/cheat/Feature.h>
|
||||||
#include <cheat-base/config/Config.h>
|
#include <cheat-base/config/Config.h>
|
||||||
#include <cheat-base/events/event.hpp>
|
#include <cheat-base/events/event.hpp>
|
||||||
|
#include <cheat-base/render/renderer.h>
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <map>
|
#include <map>
|
||||||
@ -30,7 +31,7 @@ namespace cheat
|
|||||||
void OnWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, bool& cancelled);
|
void OnWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, bool& cancelled);
|
||||||
void OnRender();
|
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 void CursorSetVisibility(bool visibility) = 0;
|
||||||
virtual bool CursorGetVisibility() = 0;
|
virtual bool CursorGetVisibility() = 0;
|
||||||
|
@ -6,7 +6,11 @@
|
|||||||
#include "fields/Toggle.h"
|
#include "fields/Toggle.h"
|
||||||
#include "fields/Enum.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 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)
|
#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;
|
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)
|
FieldBase<T>& operator=(std::shared_ptr<FieldSerialize<T>>& other)
|
||||||
{
|
{
|
||||||
p_Container->ChangedEvent -= MY_METHOD_HANDLER(FieldBase<T>::OnFieldChanged);
|
p_Container->ChangedEvent -= MY_METHOD_HANDLER(FieldBase<T>::OnFieldChanged);
|
||||||
|
@ -5,6 +5,18 @@
|
|||||||
|
|
||||||
namespace config::internal
|
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>
|
template<typename T>
|
||||||
class FieldSerialize : public FieldEntry
|
class FieldSerialize : public FieldEntry
|
||||||
{
|
{
|
||||||
@ -14,8 +26,12 @@ namespace config::internal
|
|||||||
|
|
||||||
nlohmann::json ToJson() override
|
nlohmann::json ToJson() override
|
||||||
{
|
{
|
||||||
if (m_Value == m_DefaultValue)
|
if constexpr (CHECK::EqualExists<T>::value)
|
||||||
return {};
|
{
|
||||||
|
if (m_Value == m_DefaultValue)
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
return converters::ToJson(m_Value);
|
return converters::ToJson(m_Value);
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,6 @@
|
|||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
|
|
||||||
#include <cheat-base/HookManager.h>
|
#include <cheat-base/HookManager.h>
|
||||||
|
|
||||||
#pragma comment(lib, "D3dcompiler.lib")
|
#pragma comment(lib, "D3dcompiler.lib")
|
||||||
#pragma comment(lib, "d3d11.lib")
|
#pragma comment(lib, "d3d11.lib")
|
||||||
#pragma comment(lib, "winmm.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 IDXGISwapChainPresent fnIDXGISwapChainPresent;
|
||||||
static ID3D11Device* pDevice = nullptr;
|
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;
|
static BOOL g_bInitialised = false;
|
||||||
|
|
||||||
// Main D3D11 Objects
|
// Main D3D11 Objects
|
||||||
static ID3D11DeviceContext* pContext = nullptr;
|
static ID3D11DeviceContext* pContext = nullptr;
|
||||||
|
|
||||||
if (!g_bInitialised) {
|
|
||||||
pChain->GetDevice(__uuidof(pDevice), reinterpret_cast<void**>(&pDevice));
|
if (!g_bInitialised)
|
||||||
pDevice->GetImmediateContext(&pContext);
|
{
|
||||||
|
auto result = (HRESULT)pChain->GetDevice(__uuidof(pDevice), reinterpret_cast<void**>(&pDevice));
|
||||||
|
|
||||||
DXGI_SWAP_CHAIN_DESC sd;
|
if (SUCCEEDED(result))
|
||||||
pChain->GetDesc(&sd);
|
{
|
||||||
|
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
|
// 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()
|
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;
|
IDXGISwapChain* pSwapChain;
|
||||||
|
|
||||||
constexpr D3D_FEATURE_LEVEL featureLevel = D3D_FEATURE_LEVEL_11_0;
|
D3D_FEATURE_LEVEL featureLevel;
|
||||||
DXGI_SWAP_CHAIN_DESC swapChainDesc;
|
DXGI_SWAP_CHAIN_DESC swapChainDesc;
|
||||||
ZeroMemory(&swapChainDesc, sizeof(swapChainDesc));
|
ZeroMemory(&swapChainDesc, sizeof(swapChainDesc));
|
||||||
swapChainDesc.BufferCount = 1;
|
swapChainDesc.BufferCount = 1;
|
||||||
@ -64,11 +81,15 @@ static IDXGISwapChainPresent findDirect11Present()
|
|||||||
// Main D3D11 Objects
|
// Main D3D11 Objects
|
||||||
ID3D11DeviceContext* pContext = nullptr;
|
ID3D11DeviceContext* pContext = nullptr;
|
||||||
ID3D11Device* pDevice = nullptr;
|
ID3D11Device* pDevice = nullptr;
|
||||||
if (FAILED(D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_WARP, NULL, NULL, &featureLevel, 1,
|
|
||||||
D3D11_SDK_VERSION, &swapChainDesc, &pSwapChain, &pDevice, NULL, &pContext)) &&
|
if (/*FAILED(D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_WARP, NULL, NULL, &featureLevel, 1,
|
||||||
FAILED(D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, NULL, &featureLevel, 1,
|
D3D11_SDK_VERSION, &swapChainDesc, &pSwapChain, &pDevice, NULL, &pContext)) &&*/
|
||||||
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;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -78,9 +99,12 @@ static IDXGISwapChainPresent findDirect11Present()
|
|||||||
auto swapChainPresent = reinterpret_cast<IDXGISwapChainPresent>(pSwapChainVtable[8]);
|
auto swapChainPresent = reinterpret_cast<IDXGISwapChainPresent>(pSwapChainVtable[8]);
|
||||||
|
|
||||||
pDevice->Release();
|
pDevice->Release();
|
||||||
pContext->Release();
|
//pContext->Release();
|
||||||
pSwapChain->Release();
|
pSwapChain->Release();
|
||||||
|
|
||||||
|
DestroyWindow(swapChainDesc.OutputWindow);
|
||||||
|
UnregisterClass(wc.lpszClassName, GetModuleHandle(nullptr));
|
||||||
|
|
||||||
return swapChainPresent;
|
return swapChainPresent;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -95,7 +119,7 @@ void backend::InitializeDX11Hooks()
|
|||||||
}
|
}
|
||||||
LOG_DEBUG("SwapChain Present: %p", fnIDXGISwapChainPresent);
|
LOG_DEBUG("SwapChain Present: %p", fnIDXGISwapChainPresent);
|
||||||
|
|
||||||
HookManager::install(fnIDXGISwapChainPresent, Present);
|
HookManager::install(fnIDXGISwapChainPresent, Present_Hook);
|
||||||
LOG_DEBUG("Initializing D3D11 hook: done.");
|
LOG_DEBUG("Initializing D3D11 hook: done.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,6 +2,8 @@
|
|||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
|
|
||||||
#include <d3d11.h>
|
#include <d3d11.h>
|
||||||
|
#include <d3d12.h>
|
||||||
|
|
||||||
#include <d3dcompiler.h>
|
#include <d3dcompiler.h>
|
||||||
|
|
||||||
#include <cheat-base/events/event.hpp>
|
#include <cheat-base/events/event.hpp>
|
||||||
@ -18,5 +20,6 @@ namespace backend
|
|||||||
public:
|
public:
|
||||||
inline static TEvent<ID3D11DeviceContext*> RenderEvent{};
|
inline static TEvent<ID3D11DeviceContext*> RenderEvent{};
|
||||||
inline static TEvent<HWND, ID3D11Device*, ID3D11DeviceContext*, IDXGISwapChain*> InitializeEvent{};
|
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 "renderer.h"
|
||||||
|
|
||||||
#include <backends/imgui_impl_dx11.h>
|
#include <backends/imgui_impl_dx11.h>
|
||||||
|
#pragma comment(lib, "dxgi")
|
||||||
|
#include <backends/imgui_impl_dx12.h>
|
||||||
|
|
||||||
#include <backends/imgui_impl_win32.h>
|
#include <backends/imgui_impl_win32.h>
|
||||||
|
|
||||||
#include <cheat-base/util.h>
|
#include <cheat-base/util.h>
|
||||||
#include <cheat-base/render/backend/dx11-hook.h>
|
#include <cheat-base/render/backend/dx11-hook.h>
|
||||||
|
#include <cheat-base/render/backend/dx12-hook.h>
|
||||||
|
|
||||||
#include <cheat-base/ResourceLoader.h>
|
#include <cheat-base/ResourceLoader.h>
|
||||||
|
|
||||||
extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
|
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 WNDPROC OriginalWndProcHandler;
|
||||||
static ID3D11RenderTargetView* mainRenderTargetView;
|
static ID3D11RenderTargetView* mainRenderTargetView;
|
||||||
|
|
||||||
static void OnRender(ID3D11DeviceContext* pContext);
|
static void OnRenderDX11(ID3D11DeviceContext* pContext);
|
||||||
static void OnDX11Initialize(HWND window, ID3D11Device* pDevice, ID3D11DeviceContext* pContext, IDXGISwapChain* pChain);
|
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 };
|
_customFontData = { fontData, fontDataSize };
|
||||||
|
|
||||||
LOG_DEBUG("Initialize IMGui...");
|
LOG_DEBUG("Initialize IMGui...");
|
||||||
|
|
||||||
backend::DX11Events::RenderEvent += FUNCTION_HANDLER(OnRender);
|
switch (version)
|
||||||
backend::DX11Events::InitializeEvent += FUNCTION_HANDLER(OnDX11Initialize);
|
{
|
||||||
|
case renderer::DXVersion::D3D11:
|
||||||
backend::InitializeDX11Hooks();
|
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)
|
void SetInputLock(void* id, bool value)
|
||||||
@ -134,7 +159,53 @@ namespace renderer
|
|||||||
static void SetupImGuiStyle();
|
static void SetupImGuiStyle();
|
||||||
static LRESULT CALLBACK hWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
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.");
|
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
|
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_ImplDX11_NewFrame();
|
||||||
ImGui_ImplWin32_NewFrame();
|
ImGui_ImplWin32_NewFrame();
|
||||||
|
@ -5,7 +5,15 @@
|
|||||||
|
|
||||||
namespace renderer
|
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
|
// Font sizing
|
||||||
ImFont* GetFontBySize(float fontSize);
|
ImFont* GetFontBySize(float fontSize);
|
||||||
|
@ -272,6 +272,18 @@ namespace util
|
|||||||
return static_cast<int64_t>(timezoneInfo.Bias) * 60;
|
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)
|
void OpenURL(const char* url)
|
||||||
{
|
{
|
||||||
ShellExecute(nullptr, nullptr, url, nullptr, nullptr, SW_SHOW);
|
ShellExecute(nullptr, nullptr, url, nullptr, nullptr, SW_SHOW);
|
||||||
|
@ -45,6 +45,7 @@ namespace util
|
|||||||
|
|
||||||
int64_t GetTimezoneBias();
|
int64_t GetTimezoneBias();
|
||||||
|
|
||||||
|
void OpenConsole();
|
||||||
|
|
||||||
template<typename ... Args>
|
template<typename ... Args>
|
||||||
std::string string_format(const std::string& format, Args ... args)
|
std::string string_format(const std::string& format, Args ... args)
|
||||||
|
@ -15,6 +15,11 @@
|
|||||||
</ProjectConfiguration>
|
</ProjectConfiguration>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<ClInclude Include="src\user\cheat\misc\sniffer\pipe\messages\PipeMessage.h" />
|
||||||
|
<ClInclude Include="src\user\cheat\misc\sniffer\pipe\messages\PipeModifyData.h" />
|
||||||
|
<ClInclude Include="src\user\cheat\misc\sniffer\pipe\messages\PipePacketData.h" />
|
||||||
|
<ClInclude Include="src\user\cheat\misc\sniffer\pipe\PipeClient.h" />
|
||||||
|
<ClInclude Include="src\user\cheat\misc\sniffer\pipe\PipeIO.h" />
|
||||||
<ClInclude Include="src\user\cheat\visuals\TextureChanger.h" />
|
<ClInclude Include="src\user\cheat\visuals\TextureChanger.h" />
|
||||||
<ClInclude Include="src\user\cheat\world\FakeTime.h" />
|
<ClInclude Include="src\user\cheat\world\FakeTime.h" />
|
||||||
<ClInclude Include="src\user\cheat\debugger.h">
|
<ClInclude Include="src\user\cheat\debugger.h">
|
||||||
@ -22,26 +27,6 @@
|
|||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</ExcludedFromBuild>
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</ExcludedFromBuild>
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">false</ExcludedFromBuild>
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">false</ExcludedFromBuild>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="src\user\cheat\misc\sniffer\MessageManager.h">
|
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</ExcludedFromBuild>
|
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release_WS|x64'">true</ExcludedFromBuild>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="src\user\cheat\misc\sniffer\messages\MessageBase.h">
|
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</ExcludedFromBuild>
|
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release_WS|x64'">true</ExcludedFromBuild>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="src\user\cheat\misc\sniffer\messages\MessageHeader.h">
|
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</ExcludedFromBuild>
|
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release_WS|x64'">true</ExcludedFromBuild>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="src\user\cheat\misc\sniffer\messages\ModifyData.h">
|
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</ExcludedFromBuild>
|
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release_WS|x64'">true</ExcludedFromBuild>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="src\user\cheat\misc\sniffer\messages\PacketData.h">
|
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</ExcludedFromBuild>
|
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release_WS|x64'">true</ExcludedFromBuild>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="src\user\cheat\GenshinCM.h" />
|
<ClInclude Include="src\user\cheat\GenshinCM.h" />
|
||||||
<ClInclude Include="src\user\cheat\teleport\CustomTeleports.h" />
|
<ClInclude Include="src\user\cheat\teleport\CustomTeleports.h" />
|
||||||
<ClInclude Include="src\user\cheat\visuals\Browser.h" />
|
<ClInclude Include="src\user\cheat\visuals\Browser.h" />
|
||||||
@ -117,6 +102,11 @@
|
|||||||
<Font Include="res\Ruda-ExtraBold.ttf" />
|
<Font Include="res\Ruda-ExtraBold.ttf" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<ClCompile Include="src\user\cheat\misc\sniffer\pipe\messages\PipeMessage.cpp" />
|
||||||
|
<ClCompile Include="src\user\cheat\misc\sniffer\pipe\messages\PipeModifyData.cpp" />
|
||||||
|
<ClCompile Include="src\user\cheat\misc\sniffer\pipe\messages\PipePacketData.cpp" />
|
||||||
|
<ClCompile Include="src\user\cheat\misc\sniffer\pipe\PipeClient.cpp" />
|
||||||
|
<ClCompile Include="src\user\cheat\misc\sniffer\pipe\PipeIO.cpp" />
|
||||||
<ClCompile Include="src\user\cheat\visuals\TextureChanger.cpp" />
|
<ClCompile Include="src\user\cheat\visuals\TextureChanger.cpp" />
|
||||||
<ClCompile Include="src\user\cheat\world\FakeTime.cpp" />
|
<ClCompile Include="src\user\cheat\world\FakeTime.cpp" />
|
||||||
<ClCompile Include="src\user\cheat\debugger.cpp">
|
<ClCompile Include="src\user\cheat\debugger.cpp">
|
||||||
@ -124,26 +114,6 @@
|
|||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release_WS|x64'">false</ExcludedFromBuild>
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release_WS|x64'">false</ExcludedFromBuild>
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">false</ExcludedFromBuild>
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">false</ExcludedFromBuild>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="src\user\cheat\misc\sniffer\MessageManager.cpp">
|
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</ExcludedFromBuild>
|
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release_WS|x64'">true</ExcludedFromBuild>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\user\cheat\misc\sniffer\messages\MessageBase.cpp">
|
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</ExcludedFromBuild>
|
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release_WS|x64'">true</ExcludedFromBuild>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\user\cheat\misc\sniffer\messages\MessageHeader.cpp">
|
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</ExcludedFromBuild>
|
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release_WS|x64'">true</ExcludedFromBuild>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\user\cheat\misc\sniffer\messages\ModifyData.cpp">
|
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</ExcludedFromBuild>
|
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release_WS|x64'">true</ExcludedFromBuild>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\user\cheat\misc\sniffer\messages\PacketData.cpp">
|
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</ExcludedFromBuild>
|
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release_WS|x64'">true</ExcludedFromBuild>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\user\cheat\teleport\CustomTeleports.cpp" />
|
<ClCompile Include="src\user\cheat\teleport\CustomTeleports.cpp" />
|
||||||
<ClCompile Include="src\user\cheat\GenshinCM.cpp" />
|
<ClCompile Include="src\user\cheat\GenshinCM.cpp" />
|
||||||
<ClCompile Include="src\user\cheat\visuals\Browser.cpp" />
|
<ClCompile Include="src\user\cheat\visuals\Browser.cpp" />
|
||||||
@ -849,9 +819,11 @@
|
|||||||
<TargetName>CLibrary</TargetName>
|
<TargetName>CLibrary</TargetName>
|
||||||
<OutDir>$(SolutionDir)bin\$(Configuration)-$(PlatformShortName)\</OutDir>
|
<OutDir>$(SolutionDir)bin\$(Configuration)-$(PlatformShortName)\</OutDir>
|
||||||
<IntDir>$(SolutionDir)bin\$(Configuration)-$(PlatformShortName)\obj\$(ProjectName)\</IntDir>
|
<IntDir>$(SolutionDir)bin\$(Configuration)-$(PlatformShortName)\obj\$(ProjectName)\</IntDir>
|
||||||
<CustomBuildBeforeTargets>Run</CustomBuildBeforeTargets>
|
<CustomBuildBeforeTargets>
|
||||||
|
</CustomBuildBeforeTargets>
|
||||||
<PostBuildEventUseInBuild>false</PostBuildEventUseInBuild>
|
<PostBuildEventUseInBuild>false</PostBuildEventUseInBuild>
|
||||||
<CustomBuildAfterTargets>FinalizeBuildStatus</CustomBuildAfterTargets>
|
<CustomBuildAfterTargets>
|
||||||
|
</CustomBuildAfterTargets>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
<LinkIncremental>false</LinkIncremental>
|
<LinkIncremental>false</LinkIncremental>
|
||||||
|
@ -189,21 +189,6 @@
|
|||||||
<ClInclude Include="src\user\cheat\visuals\CameraZoom.h">
|
<ClInclude Include="src\user\cheat\visuals\CameraZoom.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="src\user\cheat\misc\sniffer\messages\MessageBase.h">
|
|
||||||
<Filter>Header Files</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="src\user\cheat\misc\sniffer\messages\MessageHeader.h">
|
|
||||||
<Filter>Header Files</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="src\user\cheat\misc\sniffer\messages\ModifyData.h">
|
|
||||||
<Filter>Header Files</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="src\user\cheat\misc\sniffer\messages\PacketData.h">
|
|
||||||
<Filter>Header Files</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="src\user\cheat\misc\sniffer\MessageManager.h">
|
|
||||||
<Filter>Header Files</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="src\user\cheat\debugger.h">
|
<ClInclude Include="src\user\cheat\debugger.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
@ -237,6 +222,21 @@
|
|||||||
<ClInclude Include="src\user\cheat\visuals\TextureChanger.h">
|
<ClInclude Include="src\user\cheat\visuals\TextureChanger.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\user\cheat\misc\sniffer\pipe\messages\PipeMessage.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\user\cheat\misc\sniffer\pipe\messages\PipeModifyData.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\user\cheat\misc\sniffer\pipe\messages\PipePacketData.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\user\cheat\misc\sniffer\pipe\PipeClient.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\user\cheat\misc\sniffer\pipe\PipeIO.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Font Include="res\Ruda-Bold.ttf" />
|
<Font Include="res\Ruda-Bold.ttf" />
|
||||||
@ -384,21 +384,6 @@
|
|||||||
<ClCompile Include="src\user\cheat\visuals\CameraZoom.cpp">
|
<ClCompile Include="src\user\cheat\visuals\CameraZoom.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="src\user\cheat\misc\sniffer\messages\MessageBase.cpp">
|
|
||||||
<Filter>Source Files</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\user\cheat\misc\sniffer\messages\MessageHeader.cpp">
|
|
||||||
<Filter>Source Files</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\user\cheat\misc\sniffer\messages\ModifyData.cpp">
|
|
||||||
<Filter>Source Files</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\user\cheat\misc\sniffer\messages\PacketData.cpp">
|
|
||||||
<Filter>Source Files</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\user\cheat\misc\sniffer\MessageManager.cpp">
|
|
||||||
<Filter>Source Files</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\user\cheat\visuals\ShowChestIndicator.cpp">
|
<ClCompile Include="src\user\cheat\visuals\ShowChestIndicator.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
@ -432,6 +417,21 @@
|
|||||||
<ClCompile Include="src\user\cheat\visuals\TextureChanger.cpp">
|
<ClCompile Include="src\user\cheat\visuals\TextureChanger.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\user\cheat\misc\sniffer\pipe\messages\PipeMessage.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\user\cheat\misc\sniffer\pipe\messages\PipeModifyData.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\user\cheat\misc\sniffer\pipe\messages\PipePacketData.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\user\cheat\misc\sniffer\pipe\PipeClient.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\user\cheat\misc\sniffer\pipe\PipeIO.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ResourceCompile Include="res\res.rc">
|
<ResourceCompile Include="res\res.rc">
|
||||||
|
@ -111,7 +111,7 @@ namespace cheat
|
|||||||
FEAT_INST(HideUI),
|
FEAT_INST(HideUI),
|
||||||
FEAT_INST(Browser),
|
FEAT_INST(Browser),
|
||||||
FEAT_INST(EnablePeaking),
|
FEAT_INST(EnablePeaking),
|
||||||
FEAT_INST(TextureChanger),
|
FEAT_INST(TextureChanger)
|
||||||
|
|
||||||
});
|
});
|
||||||
#undef FEAT_INST
|
#undef FEAT_INST
|
||||||
|
@ -1,85 +0,0 @@
|
|||||||
#include "pch-il2cpp.h"
|
|
||||||
#include "MessageManager.h"
|
|
||||||
|
|
||||||
namespace sniffer
|
|
||||||
{
|
|
||||||
|
|
||||||
void MessageManager::Send(MessageBase& data)
|
|
||||||
{
|
|
||||||
if (!IsConnected())
|
|
||||||
return;
|
|
||||||
|
|
||||||
s_Pipe->WriteObject(data.header());
|
|
||||||
s_Pipe->WriteObject(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
MessageBase* MessageManager::ReceiveMessage()
|
|
||||||
{
|
|
||||||
if (!IsConnected())
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
MessageHeader header;
|
|
||||||
s_Pipe->ReadObject(header);
|
|
||||||
|
|
||||||
MessageIDs messageID = static_cast<MessageIDs>(header.messageID());
|
|
||||||
|
|
||||||
#define MESSAGE_CASE(mid, type)\
|
|
||||||
case mid: \
|
|
||||||
{ \
|
|
||||||
auto data = new type(header); \
|
|
||||||
s_Pipe->ReadObject(*data); \
|
|
||||||
CallHandlers(*data); \
|
|
||||||
return reinterpret_cast<MessageBase*>(data);\
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (messageID)
|
|
||||||
{
|
|
||||||
MESSAGE_CASE(MessageIDs::PACKET_DATA, PacketData);
|
|
||||||
MESSAGE_CASE(MessageIDs::MODIFY_DATA, ModifyData);
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MessageManager::ProcessMessage()
|
|
||||||
{
|
|
||||||
delete ReceiveMessage();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MessageManager::IsConnected()
|
|
||||||
{
|
|
||||||
if (s_Pipe == nullptr)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return s_Pipe->IsPipeOpened() || TryConnectToPipe();
|
|
||||||
}
|
|
||||||
|
|
||||||
void MessageManager::SetConnectionDelay(uint32_t delay)
|
|
||||||
{
|
|
||||||
s_ConnectionDelay = delay;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t MessageManager::GetConnectionDelay()
|
|
||||||
{
|
|
||||||
return s_ConnectionDelay;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MessageManager::Connect(const std::string& pipeName)
|
|
||||||
{
|
|
||||||
if (s_Pipe != nullptr)
|
|
||||||
delete s_Pipe;
|
|
||||||
|
|
||||||
s_Pipe = new PipeTransfer(pipeName);
|
|
||||||
TryConnectToPipe();
|
|
||||||
}
|
|
||||||
|
|
||||||
void MessageManager::Disconnect()
|
|
||||||
{
|
|
||||||
if (s_Pipe == nullptr)
|
|
||||||
return;
|
|
||||||
|
|
||||||
delete s_Pipe;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,119 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include "messages/MessageHeader.h"
|
|
||||||
#include "messages/ModifyData.h"
|
|
||||||
#include "messages/PacketData.h"
|
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
namespace sniffer
|
|
||||||
{
|
|
||||||
enum MessageIDs : uint32_t
|
|
||||||
{
|
|
||||||
NONE = 0,
|
|
||||||
PACKET_DATA = 1,
|
|
||||||
MODIFY_DATA = 2
|
|
||||||
};
|
|
||||||
|
|
||||||
class MessageManager
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
template<class T>
|
|
||||||
using CallbackFunction = void(*)(const T& packetData);
|
|
||||||
|
|
||||||
template<class T>
|
|
||||||
inline static void AddHandler(CallbackFunction<T> callback)
|
|
||||||
{
|
|
||||||
s_Handlers.push_back(callback);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class TMessage>
|
|
||||||
inline static TMessage CreateMessage(uint32_t reqID = 0)
|
|
||||||
{
|
|
||||||
static_assert(std::is_base_of<MessageBase, TMessage>::value, "Should be derived of MessageBase.");
|
|
||||||
|
|
||||||
return TMessage(MessageHeader{ GetMessageIDByType<TMessage>(), reqID });
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class TMessage>
|
|
||||||
inline static std::optional<TMessage> WaitFor()
|
|
||||||
{
|
|
||||||
static_assert(std::is_base_of<MessageBase, TMessage>::value, "Should be derived of MessageBase.");
|
|
||||||
|
|
||||||
if (!IsConnected())
|
|
||||||
return {};
|
|
||||||
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
auto messagePtr = ReceiveMessage();
|
|
||||||
if (messagePtr == nullptr)
|
|
||||||
return {};
|
|
||||||
|
|
||||||
if (GetMessageIDByType<TMessage>() != messagePtr->messageID())
|
|
||||||
{
|
|
||||||
delete messagePtr;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Copying message
|
|
||||||
TMessage message = *reinterpret_cast<TMessage*>(messagePtr);
|
|
||||||
delete messagePtr;
|
|
||||||
|
|
||||||
return message;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void Send(MessageBase& data);
|
|
||||||
|
|
||||||
static MessageBase* ReceiveMessage();
|
|
||||||
|
|
||||||
static void ProcessMessage();
|
|
||||||
|
|
||||||
static void SetConnectionDelay(uint32_t delay);
|
|
||||||
|
|
||||||
static uint32_t GetConnectionDelay();
|
|
||||||
|
|
||||||
static bool IsConnected();
|
|
||||||
|
|
||||||
static void Connect(const std::string& pipeName);
|
|
||||||
|
|
||||||
static void Disconnect();
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
inline static PipeTransfer* s_Pipe = nullptr;
|
|
||||||
|
|
||||||
inline static uint32_t s_ConnectionDelay = 5;
|
|
||||||
inline static std::time_t s_NextTimeToConnect = 0;
|
|
||||||
|
|
||||||
template<class T>
|
|
||||||
static std::vector<CallbackFunction<T>> s_Handlers;
|
|
||||||
|
|
||||||
static bool TryConnectToPipe()
|
|
||||||
{
|
|
||||||
if (s_Pipe == nullptr)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
std::time_t currTime = std::time(0);
|
|
||||||
if (s_NextTimeToConnect > currTime)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
bool result = s_Pipe->Connect();
|
|
||||||
if (result)
|
|
||||||
LOG_INFO("Connected to pipe successfully.");
|
|
||||||
else
|
|
||||||
s_NextTimeToConnect = currTime + 5; // delay in 5 sec
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class TMessage> static uint32_t GetMessageIDByType();
|
|
||||||
template<> static uint32_t GetMessageIDByType<PacketData>() { return MessageIDs::PACKET_DATA; }
|
|
||||||
template<> static uint32_t GetMessageIDByType<ModifyData>() { return MessageIDs::MODIFY_DATA; }
|
|
||||||
|
|
||||||
template<class T>
|
|
||||||
static void CallHandlers(const T& message)
|
|
||||||
{
|
|
||||||
for (auto& handler : s_Handlers<T>)
|
|
||||||
handler(message);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
@ -16,7 +16,7 @@ namespace cheat::feature
|
|||||||
NF(f_PipeName, "Pipe name", "PacketSniffer", "genshin_packet_pipe")
|
NF(f_PipeName, "Pipe name", "PacketSniffer", "genshin_packet_pipe")
|
||||||
|
|
||||||
{
|
{
|
||||||
sniffer::MessageManager::Connect(f_PipeName.value());
|
client.Connect(f_PipeName.value());
|
||||||
|
|
||||||
HookManager::install(app::Kcp_KcpNative_kcp_client_send_packet, KcpNative_kcp_client_send_packet_Hook);
|
HookManager::install(app::Kcp_KcpNative_kcp_client_send_packet, KcpNative_kcp_client_send_packet_Hook);
|
||||||
HookManager::install(app::MoleMole_KcpClient_TryDequeueEvent, KcpClient_TryDequeueEvent_Hook);
|
HookManager::install(app::MoleMole_KcpClient_TryDequeueEvent, KcpClient_TryDequeueEvent_Hook);
|
||||||
@ -42,36 +42,36 @@ namespace cheat::feature
|
|||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PacketSniffer::ProcessModifiedData(app::KcpPacket_1* packet)
|
bool PacketSniffer::ProcessModifiedData(app::KcpPacket_1*& packet)
|
||||||
{
|
{
|
||||||
auto modify_data = sniffer::MessageManager::WaitFor<ModifyData>();
|
auto modify_data = client.WaitFor<PipeModifyData>();
|
||||||
if (!modify_data)
|
if (!modify_data)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
switch (modify_data->modify_type)
|
switch (modify_data->modifyType)
|
||||||
{
|
{
|
||||||
case PacketModifyType::Blocked:
|
case ModifyType::Blocked:
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
case PacketModifyType::Modified:
|
case ModifyType::Modified:
|
||||||
{
|
{
|
||||||
auto data_size = modify_data->modified_head.size() + modify_data->modified_message.size() + 12;
|
auto data_size = modify_data->head.size() + modify_data->content.size() + 12;
|
||||||
char* data = new char[data_size];
|
char* data = new char[data_size];
|
||||||
|
|
||||||
auto head_size = static_cast<uint16_t>(modify_data->modified_head.size());
|
auto head_size = static_cast<uint16_t>(modify_data->head.size());
|
||||||
auto message_size = static_cast<uint32_t>(modify_data->modified_message.size());
|
auto message_size = static_cast<uint32_t>(modify_data->content.size());
|
||||||
|
|
||||||
util::WriteMapped(data, 0, static_cast<uint16_t>(0x4567)); // Magic number
|
util::WriteMapped(data, 0, static_cast<uint16_t>(0x4567)); // Magic number
|
||||||
util::WriteMapped(data, 2, modify_data->message_id); // Message id
|
util::WriteMapped(data, 2, modify_data->messageID); // Message id
|
||||||
util::WriteMapped(data, 4, head_size); // Head size
|
util::WriteMapped(data, 4, head_size); // Head size
|
||||||
util::WriteMapped(data, 6, message_size); // Message size
|
util::WriteMapped(data, 6, message_size); // Message size
|
||||||
|
|
||||||
// Fill content
|
// Fill content
|
||||||
char* ptr_head_content = data + 10;
|
char* ptr_head_content = data + 10;
|
||||||
memcpy_s(ptr_head_content, head_size, modify_data->modified_head.data(), head_size);
|
memcpy_s(ptr_head_content, head_size, modify_data->head.data(), head_size);
|
||||||
|
|
||||||
char* ptr_message_content = ptr_head_content + modify_data->modified_head.size();
|
char* ptr_message_content = ptr_head_content + modify_data->head.size();
|
||||||
memcpy_s(ptr_message_content, message_size, modify_data->modified_message.data(), message_size);
|
memcpy_s(ptr_message_content, message_size, modify_data->content.data(), message_size);
|
||||||
|
|
||||||
util::WriteMapped(ptr_message_content, message_size, static_cast<uint16_t>(0x89AB));
|
util::WriteMapped(ptr_message_content, message_size, static_cast<uint16_t>(0x89AB));
|
||||||
|
|
||||||
@ -86,28 +86,29 @@ namespace cheat::feature
|
|||||||
packet = new_packet;
|
packet = new_packet;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case PacketModifyType::Unchanged:
|
case ModifyType::Unchanged:
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PacketSniffer::OnPacketIO(app::KcpPacket_1* packet, PacketIOType type)
|
bool PacketSniffer::OnPacketIO(app::KcpPacket_1*& packet, NetIODirection direction)
|
||||||
{
|
{
|
||||||
if (!sniffer::MessageManager::IsConnected())
|
if (!client.IsConnected())
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (!f_CaptureEnabled)
|
if (!f_CaptureEnabled)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
PacketData packetData = ParseRawPacketData((char*)packet->data, packet->dataLen);
|
auto pipeData = client.CreateMessage<PipePacketData>();
|
||||||
if (!packetData.valid)
|
bool parsed = ParseRawPacketData((char*)packet->data, packet->dataLen, pipeData);
|
||||||
|
if (!parsed)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
packetData.ioType = type;
|
pipeData.direction = direction;
|
||||||
packetData.blockModeEnabled = f_ManipulationEnabled;
|
pipeData.manipulationEnabled = f_ManipulationEnabled;
|
||||||
sniffer::MessageManager::Send(packetData);
|
client.Send(pipeData);
|
||||||
|
|
||||||
bool canceled = f_ManipulationEnabled && ProcessModifiedData(packet);
|
bool canceled = f_ManipulationEnabled && ProcessModifiedData(packet);
|
||||||
|
|
||||||
@ -126,7 +127,7 @@ namespace cheat::feature
|
|||||||
delete[] byteArray;
|
delete[] byteArray;
|
||||||
}
|
}
|
||||||
|
|
||||||
PacketData PacketSniffer::ParseRawPacketData(char* encryptedData, uint32_t length)
|
bool PacketSniffer::ParseRawPacketData(char* encryptedData, uint32_t length, PipePacketData& dataOut)
|
||||||
{
|
{
|
||||||
// Packet structure
|
// Packet structure
|
||||||
// * Magic word (0x4567) [2 bytes]
|
// * Magic word (0x4567) [2 bytes]
|
||||||
@ -139,7 +140,6 @@ namespace cheat::feature
|
|||||||
|
|
||||||
// Header size - 12 bytes
|
// Header size - 12 bytes
|
||||||
|
|
||||||
PacketData packetData = sniffer::MessageManager::CreateMessage<PacketData>();
|
|
||||||
// Decrypting packetData
|
// Decrypting packetData
|
||||||
auto data = new char[length];
|
auto data = new char[length];
|
||||||
memcpy_s(data, length, encryptedData, length);
|
memcpy_s(data, length, encryptedData, length);
|
||||||
@ -150,14 +150,14 @@ namespace cheat::feature
|
|||||||
if (magicHead != 0x4567)
|
if (magicHead != 0x4567)
|
||||||
{
|
{
|
||||||
LOG_ERROR("Head magic value for packet is not valid.");
|
LOG_ERROR("Head magic value for packet is not valid.");
|
||||||
return packetData;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t magicEnd = util::ReadMapped<uint16_t>(data, length - 2);
|
uint16_t magicEnd = util::ReadMapped<uint16_t>(data, length - 2);
|
||||||
if (magicEnd != 0x89AB)
|
if (magicEnd != 0x89AB)
|
||||||
{
|
{
|
||||||
LOG_ERROR("End magic value for packet is not valid.");
|
LOG_ERROR("End magic value for packet is not valid.");
|
||||||
return packetData;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t messageId = util::ReadMapped<uint16_t>(data, 2);
|
uint16_t messageId = util::ReadMapped<uint16_t>(data, 2);
|
||||||
@ -167,21 +167,20 @@ namespace cheat::feature
|
|||||||
if (length < headSize + contenSize + 12)
|
if (length < headSize + contenSize + 12)
|
||||||
{
|
{
|
||||||
LOG_ERROR("Packet size is not valid.");
|
LOG_ERROR("Packet size is not valid.");
|
||||||
return packetData;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
packetData.valid = true;
|
dataOut.messageID = messageId;
|
||||||
packetData.messageID = messageId;
|
|
||||||
|
|
||||||
packetData.headRawData = std::vector<byte>((size_t)headSize, 0);
|
dataOut.head = std::vector<byte>((size_t)headSize, 0);
|
||||||
memcpy_s(packetData.headRawData.data(), headSize, data + 10, headSize);
|
memcpy_s(dataOut.head.data(), headSize, data + 10, headSize);
|
||||||
|
|
||||||
packetData.messageRawData = std::vector<byte>((size_t)contenSize, 0);
|
dataOut.content = std::vector<byte>((size_t)contenSize, 0);
|
||||||
memcpy_s(packetData.messageRawData.data(), contenSize, data + 10 + headSize, contenSize);
|
memcpy_s(dataOut.content.data(), contenSize, data + 10 + headSize, contenSize);
|
||||||
|
|
||||||
delete[] data;
|
delete[] data;
|
||||||
|
|
||||||
return packetData;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PacketSniffer::KcpClient_TryDequeueEvent_Hook(void* __this, app::ClientKcpEvent* evt, MethodInfo* method)
|
bool PacketSniffer::KcpClient_TryDequeueEvent_Hook(void* __this, app::ClientKcpEvent* evt, MethodInfo* method)
|
||||||
@ -193,13 +192,13 @@ namespace cheat::feature
|
|||||||
return result;
|
return result;
|
||||||
|
|
||||||
auto& sniffer = GetInstance();
|
auto& sniffer = GetInstance();
|
||||||
return sniffer.OnPacketIO(evt->_evt.packet, PacketIOType::Receive);
|
return sniffer.OnPacketIO(evt->_evt.packet, NetIODirection::Receive);
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t PacketSniffer::KcpNative_kcp_client_send_packet_Hook(void* kcp_client, app::KcpPacket_1* packet, MethodInfo* method)
|
int32_t PacketSniffer::KcpNative_kcp_client_send_packet_Hook(void* kcp_client, app::KcpPacket_1* packet, MethodInfo* method)
|
||||||
{
|
{
|
||||||
auto& sniffer = GetInstance();
|
auto& sniffer = GetInstance();
|
||||||
if (!sniffer.OnPacketIO(packet, PacketIOType::Send))
|
if (!sniffer.OnPacketIO(packet, NetIODirection::Send))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return CALL_ORIGIN(KcpNative_kcp_client_send_packet_Hook, kcp_client, packet, method);
|
return CALL_ORIGIN(KcpNative_kcp_client_send_packet_Hook, kcp_client, packet, method);
|
||||||
|
@ -7,10 +7,9 @@
|
|||||||
#include <cheat-base/config/config.h>
|
#include <cheat-base/config/config.h>
|
||||||
|
|
||||||
#include <cheat-base/PipeTransfer.h>
|
#include <cheat-base/PipeTransfer.h>
|
||||||
#include "messages/PacketData.h"
|
#include "pipe/messages/PipeModifyData.h"
|
||||||
#include "messages/ModifyData.h"
|
#include "pipe/messages/PipePacketData.h"
|
||||||
|
#include "pipe/PipeClient.h"
|
||||||
#include "MessageManager.h"
|
|
||||||
|
|
||||||
namespace cheat::feature
|
namespace cheat::feature
|
||||||
{
|
{
|
||||||
@ -22,6 +21,8 @@ namespace cheat::feature
|
|||||||
config::Field<bool> f_ManipulationEnabled;
|
config::Field<bool> f_ManipulationEnabled;
|
||||||
config::Field<std::string> f_PipeName;
|
config::Field<std::string> f_PipeName;
|
||||||
|
|
||||||
|
PipeClient client;
|
||||||
|
|
||||||
static PacketSniffer& GetInstance();
|
static PacketSniffer& GetInstance();
|
||||||
|
|
||||||
const FeatureGUIInfo& GetGUIInfo() const override;
|
const FeatureGUIInfo& GetGUIInfo() const override;
|
||||||
@ -30,13 +31,13 @@ namespace cheat::feature
|
|||||||
private:
|
private:
|
||||||
PacketSniffer();
|
PacketSniffer();
|
||||||
|
|
||||||
bool ProcessModifiedData(app::KcpPacket_1* packet);
|
bool ProcessModifiedData(app::KcpPacket_1*& packet);
|
||||||
PacketData ParseRawPacketData(char* encryptedData, uint32_t length);
|
bool ParseRawPacketData(char* encryptedData, uint32_t length, PipePacketData& dataOut);
|
||||||
static void EncryptXor(void* content, uint32_t length);
|
static void EncryptXor(void* content, uint32_t length);
|
||||||
static bool KcpClient_TryDequeueEvent_Hook(void* __this, app::ClientKcpEvent* evt, MethodInfo* method);
|
static bool KcpClient_TryDequeueEvent_Hook(void* __this, app::ClientKcpEvent* evt, MethodInfo* method);
|
||||||
static int32_t KcpNative_kcp_client_send_packet_Hook(void* kcp_client, app::KcpPacket_1* packet, MethodInfo* method);
|
static int32_t KcpNative_kcp_client_send_packet_Hook(void* kcp_client, app::KcpPacket_1* packet, MethodInfo* method);
|
||||||
|
|
||||||
bool OnPacketIO(app::KcpPacket_1* packet, PacketIOType type);
|
bool OnPacketIO(app::KcpPacket_1*& packet, NetIODirection direction);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,32 +0,0 @@
|
|||||||
#include "pch-il2cpp.h"
|
|
||||||
#include "MessageBase.h"
|
|
||||||
|
|
||||||
MessageBase::MessageBase(const MessageHeader& header) : m_Header(header)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t MessageBase::requestID() const
|
|
||||||
{
|
|
||||||
return m_Header.requestID();
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t MessageBase::messageID() const
|
|
||||||
{
|
|
||||||
return m_Header.messageID();
|
|
||||||
}
|
|
||||||
|
|
||||||
int64_t MessageBase::timestamp() const
|
|
||||||
{
|
|
||||||
return m_Header.timestamp();
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t MessageBase::sequenceID() const
|
|
||||||
{
|
|
||||||
return m_Header.sequenceID();
|
|
||||||
}
|
|
||||||
|
|
||||||
MessageHeader& MessageBase::header()
|
|
||||||
{
|
|
||||||
return m_Header;
|
|
||||||
}
|
|
@ -1,17 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include "MessageHeader.h"
|
|
||||||
class MessageBase : public PipeSerializedObject
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
explicit MessageBase(const MessageHeader& header);
|
|
||||||
|
|
||||||
uint32_t requestID() const;
|
|
||||||
uint32_t messageID() const;
|
|
||||||
int64_t timestamp() const;
|
|
||||||
uint64_t sequenceID() const;
|
|
||||||
|
|
||||||
MessageHeader& header();
|
|
||||||
private:
|
|
||||||
MessageHeader m_Header;
|
|
||||||
};
|
|
||||||
|
|
@ -1,53 +0,0 @@
|
|||||||
#include <pch-il2cpp.h>
|
|
||||||
#include "MessageHeader.h"
|
|
||||||
|
|
||||||
|
|
||||||
MessageHeader::MessageHeader(uint32_t messageId, uint32_t requestID /*= 0*/) :
|
|
||||||
m_MessageID(messageId), m_RequestID(requestID),
|
|
||||||
m_SequenceID(GenerateSequenceID()), m_Timestamp(util::GetCurrentTimeMillisec())
|
|
||||||
{ }
|
|
||||||
|
|
||||||
MessageHeader::MessageHeader() : m_MessageID(0), m_RequestID(0), m_SequenceID(0), m_Timestamp(0)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
uint32_t MessageHeader::requestID() const
|
|
||||||
{
|
|
||||||
return m_RequestID;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t MessageHeader::messageID() const
|
|
||||||
{
|
|
||||||
return m_MessageID;
|
|
||||||
}
|
|
||||||
|
|
||||||
int64_t MessageHeader::timestamp() const
|
|
||||||
{
|
|
||||||
return m_Timestamp;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t MessageHeader::sequenceID() const
|
|
||||||
{
|
|
||||||
return m_SequenceID;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MessageHeader::Write(PipeTransfer* transfer)
|
|
||||||
{
|
|
||||||
transfer->Write(m_MessageID);
|
|
||||||
transfer->Write(m_RequestID);
|
|
||||||
transfer->Write(util::GetCurrentTimeMillisec());
|
|
||||||
transfer->Write(m_SequenceID);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MessageHeader::Read(PipeTransfer* transfer)
|
|
||||||
{
|
|
||||||
transfer->Read(m_MessageID);
|
|
||||||
transfer->Read(m_RequestID);
|
|
||||||
transfer->Read(m_Timestamp);
|
|
||||||
transfer->Read(m_SequenceID);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t MessageHeader::GenerateSequenceID()
|
|
||||||
{
|
|
||||||
s_SequenceGlobalID += 1;
|
|
||||||
return s_SequenceGlobalID;
|
|
||||||
}
|
|
@ -1,25 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include <cheat-base/PipeTransfer.h>
|
|
||||||
|
|
||||||
class MessageHeader : public PipeSerializedObject
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
MessageHeader();
|
|
||||||
MessageHeader(uint32_t messageId, uint32_t requestID = 0);
|
|
||||||
uint32_t requestID() const;
|
|
||||||
uint32_t messageID() const;
|
|
||||||
int64_t timestamp() const;
|
|
||||||
uint64_t sequenceID() const;
|
|
||||||
|
|
||||||
void Write(PipeTransfer* transfer) final;
|
|
||||||
void Read(PipeTransfer* transfer) final;
|
|
||||||
|
|
||||||
private:
|
|
||||||
inline static std::atomic<uint64_t> s_SequenceGlobalID {};
|
|
||||||
static uint64_t GenerateSequenceID();
|
|
||||||
|
|
||||||
uint32_t m_MessageID;
|
|
||||||
uint32_t m_RequestID;
|
|
||||||
int64_t m_Timestamp;
|
|
||||||
int64_t m_SequenceID;
|
|
||||||
};
|
|
@ -1,28 +0,0 @@
|
|||||||
#include <pch-il2cpp.h>
|
|
||||||
#include "ModifyData.h"
|
|
||||||
|
|
||||||
ModifyData::ModifyData(const MessageHeader& header) : MessageBase(header),
|
|
||||||
modify_type(PacketModifyType::Unchanged)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
void ModifyData::Write(PipeTransfer* transfer)
|
|
||||||
{
|
|
||||||
transfer->Write<PacketModifyType>(modify_type);
|
|
||||||
if (modify_type == PacketModifyType::Modified)
|
|
||||||
{
|
|
||||||
transfer->Write(message_id);
|
|
||||||
transfer->Write(modified_head);
|
|
||||||
transfer->Write(modified_message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ModifyData::Read(PipeTransfer* transfer)
|
|
||||||
{
|
|
||||||
transfer->Read<PacketModifyType>(modify_type);
|
|
||||||
if (modify_type == PacketModifyType::Modified)
|
|
||||||
{
|
|
||||||
transfer->Read(message_id);
|
|
||||||
transfer->Read(modified_head);
|
|
||||||
transfer->Read(modified_message);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,28 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include <cheat-base/PipeTransfer.h>
|
|
||||||
#include "MessageBase.h"
|
|
||||||
|
|
||||||
enum class PacketModifyType
|
|
||||||
{
|
|
||||||
Unchanged,
|
|
||||||
Modified,
|
|
||||||
Blocked
|
|
||||||
};
|
|
||||||
|
|
||||||
class ModifyData : public MessageBase
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
PacketModifyType modify_type;
|
|
||||||
|
|
||||||
uint16_t message_id;
|
|
||||||
std::string modified_head;
|
|
||||||
std::string modified_message;
|
|
||||||
|
|
||||||
ModifyData(const MessageHeader& header);
|
|
||||||
~ModifyData() {}
|
|
||||||
|
|
||||||
// Inherited via PipeSerializedObject
|
|
||||||
void Write(PipeTransfer* transfer) override;
|
|
||||||
void Read(PipeTransfer* transfer) override;
|
|
||||||
};
|
|
||||||
|
|
@ -1,20 +0,0 @@
|
|||||||
#include <pch-il2cpp.h>
|
|
||||||
#include "PacketData.h"
|
|
||||||
|
|
||||||
void PacketData::Write(PipeTransfer* transfer)
|
|
||||||
{
|
|
||||||
transfer->Write(blockModeEnabled);
|
|
||||||
transfer->Write(ioType);
|
|
||||||
transfer->Write(messageID);
|
|
||||||
transfer->Write(headRawData);
|
|
||||||
transfer->Write(messageRawData);
|
|
||||||
}
|
|
||||||
|
|
||||||
void PacketData::Read(PipeTransfer* transfer)
|
|
||||||
{
|
|
||||||
transfer->Read(blockModeEnabled);
|
|
||||||
transfer->Read(ioType);
|
|
||||||
transfer->Read(messageID);
|
|
||||||
transfer->Read(headRawData);
|
|
||||||
transfer->Read(messageRawData);
|
|
||||||
}
|
|
@ -1,42 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include <cheat-base/PipeTransfer.h>
|
|
||||||
#include "MessageBase.h"
|
|
||||||
|
|
||||||
enum class PacketIOType
|
|
||||||
{
|
|
||||||
Receive,
|
|
||||||
Send
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class PacketDataType
|
|
||||||
{
|
|
||||||
Raw,
|
|
||||||
Parsed
|
|
||||||
};
|
|
||||||
|
|
||||||
class PacketData : public MessageBase
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
using MessageBase::MessageBase;
|
|
||||||
|
|
||||||
bool blockModeEnabled;
|
|
||||||
|
|
||||||
PacketIOType ioType;
|
|
||||||
PacketDataType dataType;
|
|
||||||
|
|
||||||
bool valid;
|
|
||||||
|
|
||||||
uint64_t parentPacketID;
|
|
||||||
|
|
||||||
int16_t messageID;
|
|
||||||
std::vector<byte> headRawData;
|
|
||||||
std::vector<byte> messageRawData;
|
|
||||||
|
|
||||||
std::string name;
|
|
||||||
std::string headJson;
|
|
||||||
std::string messageJson;
|
|
||||||
|
|
||||||
// Inherited via PipeSerializedObject
|
|
||||||
virtual void Write(PipeTransfer* transfer) override;
|
|
||||||
virtual void Read(PipeTransfer* transfer) override;
|
|
||||||
};
|
|
@ -0,0 +1,54 @@
|
|||||||
|
#include "pch-il2cpp.h"
|
||||||
|
#include "PipeClient.h"
|
||||||
|
|
||||||
|
bool PipeClient::IsConnected()
|
||||||
|
{
|
||||||
|
if (m_Pipe == nullptr)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return m_Pipe->IsPipeOpened() || TryConnectToPipe();
|
||||||
|
}
|
||||||
|
|
||||||
|
void PipeClient::SetConnectionDelay(uint32_t delay)
|
||||||
|
{
|
||||||
|
m_ConnectionDelay = delay;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t PipeClient::GetConnectionDelay()
|
||||||
|
{
|
||||||
|
return m_ConnectionDelay;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PipeClient::Connect(const std::string& pipeName)
|
||||||
|
{
|
||||||
|
if (m_Pipe != nullptr)
|
||||||
|
delete m_Pipe;
|
||||||
|
|
||||||
|
m_Pipe = new PipeTransfer(pipeName);
|
||||||
|
TryConnectToPipe();
|
||||||
|
}
|
||||||
|
|
||||||
|
void PipeClient::Disconnect()
|
||||||
|
{
|
||||||
|
if (m_Pipe == nullptr)
|
||||||
|
return;
|
||||||
|
|
||||||
|
delete m_Pipe;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PipeClient::TryConnectToPipe()
|
||||||
|
{
|
||||||
|
if (m_Pipe == nullptr)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
std::time_t currTime = std::time(0);
|
||||||
|
if (m_NextTimeToConnect > currTime)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
bool result = m_Pipe->Connect();
|
||||||
|
if (result)
|
||||||
|
LOG_INFO("Connected to pipe successfully.");
|
||||||
|
else
|
||||||
|
m_NextTimeToConnect = currTime + 5; // delay in 5 sec
|
||||||
|
return result;
|
||||||
|
}
|
23
cheat-library/src/user/cheat/misc/sniffer/pipe/PipeClient.h
Normal file
23
cheat-library/src/user/cheat/misc/sniffer/pipe/PipeClient.h
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "PipeIO.h"
|
||||||
|
|
||||||
|
class PipeClient : public PipeIO
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PipeClient() : PipeIO(), m_ConnectionDelay(5), m_NextTimeToConnect(0) {}
|
||||||
|
|
||||||
|
void SetConnectionDelay(uint32_t delay);
|
||||||
|
uint32_t GetConnectionDelay();
|
||||||
|
|
||||||
|
bool IsConnected() final;
|
||||||
|
void Connect(const std::string& pipeName);
|
||||||
|
void Disconnect();
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint32_t m_ConnectionDelay;
|
||||||
|
std::time_t m_NextTimeToConnect;
|
||||||
|
|
||||||
|
bool TryConnectToPipe();
|
||||||
|
};
|
46
cheat-library/src/user/cheat/misc/sniffer/pipe/PipeIO.cpp
Normal file
46
cheat-library/src/user/cheat/misc/sniffer/pipe/PipeIO.cpp
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
#include "pch-il2cpp.h"
|
||||||
|
#include "PipeIO.h"
|
||||||
|
|
||||||
|
void PipeIO::Send(PipeMessage& data)
|
||||||
|
{
|
||||||
|
if (!IsConnected())
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_Pipe->WriteObject(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
PipeMessage* PipeIO::ReceiveMessage()
|
||||||
|
{
|
||||||
|
if (!IsConnected())
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
PipeMessage header;
|
||||||
|
m_Pipe->ReadObject(header);
|
||||||
|
|
||||||
|
MessageIDs messageID = static_cast<MessageIDs>(header.packetID());
|
||||||
|
|
||||||
|
#define MESSAGE_CASE(mid, type)\
|
||||||
|
case mid: \
|
||||||
|
{ \
|
||||||
|
auto data = new type(); \
|
||||||
|
m_Pipe->ReadObject(*data); \
|
||||||
|
data->SetMessage(header); \
|
||||||
|
CallHandlers(*data); \
|
||||||
|
return reinterpret_cast<PipeMessage*>(data); \
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (messageID)
|
||||||
|
{
|
||||||
|
MESSAGE_CASE(MessageIDs::PACKET_DATA, PipePacketData);
|
||||||
|
MESSAGE_CASE(MessageIDs::MODIFY_DATA, PipeModifyData);
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PipeIO::ProcessMessage()
|
||||||
|
{
|
||||||
|
auto message = ReceiveMessage();
|
||||||
|
delete message;
|
||||||
|
}
|
110
cheat-library/src/user/cheat/misc/sniffer/pipe/PipeIO.h
Normal file
110
cheat-library/src/user/cheat/misc/sniffer/pipe/PipeIO.h
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "messages/PipeMessage.h"
|
||||||
|
#include "messages/PipeModifyData.h"
|
||||||
|
#include "messages/PipePacketData.h"
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
|
|
||||||
|
enum class MessageIDs : uint32_t
|
||||||
|
{
|
||||||
|
NONE = 0,
|
||||||
|
PACKET_DATA = 1,
|
||||||
|
MODIFY_DATA = 2
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace internal
|
||||||
|
{
|
||||||
|
template<class TMessage> struct message_to_id;
|
||||||
|
template<> struct message_to_id<PipePacketData> : std::integral_constant<uint32_t, static_cast<uint32_t>(MessageIDs::PACKET_DATA)> {};
|
||||||
|
template<> struct message_to_id<PipeModifyData> : std::integral_constant<uint32_t, static_cast<uint32_t>(MessageIDs::MODIFY_DATA)> {};
|
||||||
|
}
|
||||||
|
|
||||||
|
class PipeIO
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
template<class T>
|
||||||
|
using CallbackFunction = void(*)(const T& packetData);
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
void AddHandler(CallbackFunction<T> callback)
|
||||||
|
{
|
||||||
|
static_assert(std::is_base_of<PipeMessage, T>::value, "Should be derived of MessageBase.");
|
||||||
|
|
||||||
|
constexpr auto messageID = internal::message_to_id<T>::value;
|
||||||
|
|
||||||
|
m_Handlers.push_back({
|
||||||
|
messageID,
|
||||||
|
reinterpret_cast<UniqueCallbackFunction>(callback)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class TMessage>
|
||||||
|
TMessage CreateMessage(uint32_t reqID = 0, uint32_t seqID = 0)
|
||||||
|
{
|
||||||
|
static_assert(std::is_base_of<PipeMessage, TMessage>::value, "Should be derived of MessageBase.");
|
||||||
|
|
||||||
|
return TMessage(internal::message_to_id<TMessage>::value);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class TMessage>
|
||||||
|
std::optional<TMessage> WaitFor()
|
||||||
|
{
|
||||||
|
static_assert(std::is_base_of<PipeMessage, TMessage>::value, "Should be derived of MessageBase.");
|
||||||
|
|
||||||
|
if (!IsConnected())
|
||||||
|
return {};
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
auto messagePtr = ReceiveMessage();
|
||||||
|
if (messagePtr == nullptr)
|
||||||
|
return {};
|
||||||
|
|
||||||
|
if (internal::message_to_id<TMessage>::value != messagePtr->packetID())
|
||||||
|
{
|
||||||
|
delete messagePtr;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copying message
|
||||||
|
TMessage message = *reinterpret_cast<TMessage*>(messagePtr);
|
||||||
|
delete messagePtr;
|
||||||
|
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Send(PipeMessage& data);
|
||||||
|
|
||||||
|
PipeMessage* ReceiveMessage();
|
||||||
|
|
||||||
|
void ProcessMessage();
|
||||||
|
|
||||||
|
virtual bool IsConnected() = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
PipeIO() : m_Pipe(nullptr) {};
|
||||||
|
PipeTransfer* m_Pipe;
|
||||||
|
|
||||||
|
private:
|
||||||
|
using UniqueCallbackFunction = void(*)(const PipeMessage& pipeMessage);
|
||||||
|
std::vector<std::pair<uint32_t, UniqueCallbackFunction>> m_Handlers;
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
void CallHandlers(const T& message)
|
||||||
|
{
|
||||||
|
for (auto& [id, handler] : m_Handlers)
|
||||||
|
{
|
||||||
|
if (id == internal::message_to_id<T>::value)
|
||||||
|
handler(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
PipeIO(PipeIO& other) = delete;
|
||||||
|
PipeIO(PipeIO&& other) = delete;
|
||||||
|
PipeIO& operator=(PipeIO& other) = delete;
|
||||||
|
PipeIO& operator=(PipeIO&& other) = delete;
|
||||||
|
};
|
@ -0,0 +1,37 @@
|
|||||||
|
#include "pch-il2cpp.h"
|
||||||
|
#include "PipeMessage.h"
|
||||||
|
|
||||||
|
PipeMessage::PipeMessage(uint32_t packetID) :
|
||||||
|
m_PipePacketID(packetID), m_Timestamp(util::GetCurrentTimeMillisec())
|
||||||
|
{ }
|
||||||
|
|
||||||
|
PipeMessage::PipeMessage() : m_PipePacketID(0), m_Timestamp(0)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
uint32_t PipeMessage::packetID() const
|
||||||
|
{
|
||||||
|
return m_PipePacketID;
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t PipeMessage::timestamp() const
|
||||||
|
{
|
||||||
|
return m_Timestamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PipeMessage::Write(PipeTransfer* transfer)
|
||||||
|
{
|
||||||
|
transfer->Write(m_PipePacketID);
|
||||||
|
transfer->Write(util::GetCurrentTimeMillisec());
|
||||||
|
}
|
||||||
|
|
||||||
|
void PipeMessage::Read(PipeTransfer* transfer)
|
||||||
|
{
|
||||||
|
transfer->Read(m_PipePacketID);
|
||||||
|
transfer->Read(m_Timestamp);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PipeMessage::SetMessage(const PipeMessage& other)
|
||||||
|
{
|
||||||
|
m_PipePacketID = other.m_PipePacketID;
|
||||||
|
m_Timestamp = other.m_Timestamp;
|
||||||
|
}
|
@ -0,0 +1,21 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <atomic>
|
||||||
|
#include <cheat-base/PipeTransfer.h>
|
||||||
|
|
||||||
|
class PipeMessage : public PipeSerializedObject
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PipeMessage();
|
||||||
|
PipeMessage(uint32_t packetID);
|
||||||
|
uint32_t packetID() const;
|
||||||
|
int64_t timestamp() const;
|
||||||
|
|
||||||
|
void SetMessage(const PipeMessage& other);
|
||||||
|
void Write(PipeTransfer* transfer) override;
|
||||||
|
void Read(PipeTransfer* transfer) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
uint32_t m_PipePacketID;
|
||||||
|
int64_t m_Timestamp;
|
||||||
|
};
|
@ -0,0 +1,32 @@
|
|||||||
|
#include "pch-il2cpp.h"
|
||||||
|
#include "PipeModifyData.h"
|
||||||
|
|
||||||
|
PipeModifyData::PipeModifyData() :
|
||||||
|
modifyType(ModifyType::Unchanged), head({}), content({}), messageID(0)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
void PipeModifyData::Write(PipeTransfer* transfer)
|
||||||
|
{
|
||||||
|
PipeMessage::Write(transfer);
|
||||||
|
|
||||||
|
transfer->Write(modifyType);
|
||||||
|
if (modifyType == ModifyType::Modified)
|
||||||
|
{
|
||||||
|
|
||||||
|
transfer->Write(messageID);
|
||||||
|
transfer->Write(content);
|
||||||
|
transfer->Write(head);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PipeModifyData::Read(PipeTransfer* transfer)
|
||||||
|
{
|
||||||
|
transfer->Read(modifyType);
|
||||||
|
if (modifyType == ModifyType::Modified)
|
||||||
|
{
|
||||||
|
|
||||||
|
transfer->Read(messageID);
|
||||||
|
transfer->Read(content);
|
||||||
|
transfer->Read(head);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,26 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <cheat-base/PipeTransfer.h>
|
||||||
|
#include "PipeMessage.h"
|
||||||
|
|
||||||
|
enum class ModifyType
|
||||||
|
{
|
||||||
|
Unchanged, Blocked, Modified
|
||||||
|
};
|
||||||
|
|
||||||
|
class PipeModifyData : public PipeMessage
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using PipeMessage::PipeMessage;
|
||||||
|
|
||||||
|
ModifyType modifyType;
|
||||||
|
uint32_t messageID;
|
||||||
|
std::vector<uint8_t> head;
|
||||||
|
std::vector<uint8_t> content;
|
||||||
|
|
||||||
|
PipeModifyData();
|
||||||
|
~PipeModifyData() {}
|
||||||
|
|
||||||
|
// Inherited via PipeSerializedObject
|
||||||
|
virtual void Write(PipeTransfer* transfer) final;
|
||||||
|
virtual void Read(PipeTransfer* transfer) final;
|
||||||
|
};
|
@ -0,0 +1,22 @@
|
|||||||
|
#include "pch-il2cpp.h"
|
||||||
|
#include "PipePacketData.h"
|
||||||
|
|
||||||
|
void PipePacketData::Write(PipeTransfer* transfer)
|
||||||
|
{
|
||||||
|
PipeMessage::Write(transfer);
|
||||||
|
|
||||||
|
transfer->Write(manipulationEnabled);
|
||||||
|
transfer->Write(direction);
|
||||||
|
transfer->Write(messageID);
|
||||||
|
transfer->Write(head);
|
||||||
|
transfer->Write(content);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PipePacketData::Read(PipeTransfer* transfer)
|
||||||
|
{
|
||||||
|
transfer->Read(manipulationEnabled);
|
||||||
|
transfer->Read(direction);
|
||||||
|
transfer->Read(messageID);
|
||||||
|
transfer->Read(head);
|
||||||
|
transfer->Read(content);
|
||||||
|
}
|
@ -0,0 +1,24 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "PipeMessage.h"
|
||||||
|
|
||||||
|
enum class NetIODirection
|
||||||
|
{
|
||||||
|
Send, Receive
|
||||||
|
};
|
||||||
|
|
||||||
|
class PipePacketData : public PipeMessage
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using PipeMessage::PipeMessage;
|
||||||
|
|
||||||
|
bool manipulationEnabled;
|
||||||
|
|
||||||
|
NetIODirection direction;
|
||||||
|
int16_t messageID;
|
||||||
|
std::vector<byte> head;
|
||||||
|
std::vector<byte> content;
|
||||||
|
|
||||||
|
// Inherited via PipeSerializedObject
|
||||||
|
void Write(PipeTransfer* transfer) final;
|
||||||
|
void Read(PipeTransfer* transfer) final;
|
||||||
|
};
|
Loading…
Reference in New Issue
Block a user