diff --git a/src/Image.cpp b/src/Image.cpp index ac5ffb7a..5d830d0b 100644 --- a/src/Image.cpp +++ b/src/Image.cpp @@ -37,6 +37,10 @@ Image::Image() spdlog::info("\tResolved to version: 1.04"); version = MakeVersion(1,4); break; + case 0x20F87F01: + spdlog::info("\tResolved to version: 1.05"); + version = MakeVersion(1, 5); + break; default: spdlog::error("\tUnknown version, please update the mod"); break; diff --git a/src/Pattern.cpp b/src/Pattern.cpp index c2ff24ef..3e9fbd84 100644 --- a/src/Pattern.cpp +++ b/src/Pattern.cpp @@ -1,6 +1,8 @@ #include "Pattern.h" #include +#include "Options.h" + bool CompareByteArray(uint8_t* Data, const std::vector& aSignature) { uint8_t* pData = Data; @@ -43,3 +45,8 @@ uint8_t* FindSignature(uint8_t* apStart, uint8_t* apEnd, std::vector aS return nullptr; } + +uint8_t* FindSignature(std::vector aSignature) noexcept +{ + return FindSignature(Options::Get().GameImage.pTextStart, Options::Get().GameImage.pTextEnd, std::move(aSignature)); +} diff --git a/src/Pattern.h b/src/Pattern.h index 23466e2d..25f1304a 100644 --- a/src/Pattern.h +++ b/src/Pattern.h @@ -3,4 +3,5 @@ #include #include -uint8_t* FindSignature(uint8_t* apStart, uint8_t* apEnd, std::vector apSignature) noexcept; \ No newline at end of file +uint8_t* FindSignature(uint8_t* apStart, uint8_t* apEnd, std::vector apSignature) noexcept; +uint8_t* FindSignature(std::vector aSignature) noexcept; \ No newline at end of file diff --git a/src/REDString.h b/src/REDString.h deleted file mode 100644 index 5a6cfb38..00000000 --- a/src/REDString.h +++ /dev/null @@ -1,26 +0,0 @@ -#pragma once - -#include - -struct REDString -{ -private: - - static constexpr uint64_t RecursiveHash(const char* acpStr, uint64_t aHash) - { - if (*acpStr) { - aHash ^= *acpStr; - aHash *= 1099511628211ull; - - return RecursiveHash(acpStr + 1, aHash); - } - - return aHash; - } - -public: - static constexpr uint64_t Hash(const char* acpStr) - { - return RecursiveHash(acpStr, 14695981039346656037ull); - } -}; \ No newline at end of file diff --git a/src/Utils.cpp b/src/Utils.cpp new file mode 100644 index 00000000..c0f3fdec --- /dev/null +++ b/src/Utils.cpp @@ -0,0 +1,21 @@ +#include "Utils.h" + +void ltrim(std::string& s) +{ + s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](unsigned char ch) { + return !std::isspace(ch); + })); +} + +void rtrim(std::string& s) +{ + s.erase(std::find_if(s.rbegin(), s.rend(), [](unsigned char ch) { + return !std::isspace(ch); + }).base(), s.end()); +} + +void trim(std::string& s) +{ + ltrim(s); + rtrim(s); +} diff --git a/src/Utils.h b/src/Utils.h new file mode 100644 index 00000000..9f621ca3 --- /dev/null +++ b/src/Utils.h @@ -0,0 +1,5 @@ +#include + +void ltrim(std::string& s); +void rtrim(std::string& s); +void trim(std::string& s); \ No newline at end of file diff --git a/src/disable_boundary_teleport.cpp b/src/disable_boundary_teleport.cpp index 8f8be354..cc3058b2 100644 --- a/src/disable_boundary_teleport.cpp +++ b/src/disable_boundary_teleport.cpp @@ -1,7 +1,6 @@ #include #include "Image.h" #include -#include "REDString.h" #include "Pattern.h" void DisableBoundaryTeleportPatch(Image* apImage) diff --git a/src/disable_intro_movies.cpp b/src/disable_intro_movies.cpp index e16f0418..8606f94a 100644 --- a/src/disable_intro_movies.cpp +++ b/src/disable_intro_movies.cpp @@ -1,9 +1,8 @@ -#include #include #include "Image.h" #include -#include "REDString.h" #include "Pattern.h" +#include "reverse/REDString.h" using TInitScriptMemberVariable = void*(void* a1, void* a2, uint64_t a3, uint64_t nameHash, void* a5, void* a6, void* a7); TInitScriptMemberVariable* RealInitScriptMemberVariable = nullptr; diff --git a/src/disable_vignette.cpp b/src/disable_vignette.cpp index 83984c43..d208ec20 100644 --- a/src/disable_vignette.cpp +++ b/src/disable_vignette.cpp @@ -1,7 +1,6 @@ #include #include "Image.h" #include -#include "REDString.h" #include "Pattern.h" void DisableVignettePatch(Image* apImage) diff --git a/src/enable_debug.cpp b/src/enable_debug.cpp index 6df4b7cc..55def308 100644 --- a/src/enable_debug.cpp +++ b/src/enable_debug.cpp @@ -1,8 +1,8 @@ #include "Image.h" #include #include -#include "REDString.h" #include "Pattern.h" +#include "reverse/REDString.h" using ScriptExecutionPointer = uint64_t; diff --git a/src/overlay/Overlay.cpp b/src/overlay/Overlay.cpp index 5afebc43..9d2f2174 100644 --- a/src/overlay/Overlay.cpp +++ b/src/overlay/Overlay.cpp @@ -2,11 +2,9 @@ #include #include -#include #include #include #include -#include #include #include #include @@ -14,6 +12,8 @@ #include "imgui_impl_dx12.h" #include "imgui_impl_win32.h" +#include "reverse/Engine.h" +#include "reverse/Scripting.h" static std::shared_ptr s_pOverlay; @@ -36,45 +36,58 @@ Overlay& Overlay::Get() return *s_pOverlay; } -void Overlay::EarlyHooks(Image* apImage) +extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); + +void Overlay::DrawImgui(IDXGISwapChain3* apSwapChain) { - uint8_t* pLocation = FindSignature(apImage->pTextStart, apImage->pTextEnd, { - 0x48, 0x89, 0x5C, 0x24, 0x08, 0x57, 0x48, 0x83, 0xEC, 0x30, 0x48, 0x8B, - 0x99, 0x68, 0x01, 0x00, 0x00, 0x48, 0x8B, 0xF9, 0xFF }); + ImGui_ImplDX12_NewFrame(); + ImGui_ImplWin32_NewFrame(); + ImGui::NewFrame(); + + ImGui::Begin("Cyber Engine Tweaks"); - if (pLocation) + if (Options::Get().GameImage.version == Image::MakeVersion(1, 4) || + Options::Get().GameImage.version == Image::MakeVersion(1, 5)) { - if (MH_CreateHook(pLocation, &ClipToCenter, (void**)&m_realClipToCenter) != MH_OK || MH_EnableHook(pLocation) != MH_OK) + ImGui::PushItemWidth(600.f); + + static char command[512] = { 0 }; + { - spdlog::error("\tCould not hook mouse clip function!"); + std::lock_guard _{ m_outputLock }; + + const auto result = ImGui::ListBoxHeader("", m_outputLines.size(), 15); + for (auto& item : m_outputLines) + ImGui::Selectable(item.c_str()); + + if (result) + ImGui::ListBoxFooter(); } - else - spdlog::info("\tHook mouse clip function!"); - } -} -BOOL CALLBACK EnumWindowsProcMy(HWND hwnd, LPARAM lParam) -{ - DWORD lpdwProcessId; - GetWindowThreadProcessId(hwnd, &lpdwProcessId); - if (lpdwProcessId == GetCurrentProcessId()) - { - char name[512] = { 0 }; - GetWindowTextA(hwnd, name, 511); - if (strcmp("Cyberpunk 2077 (C) 2020 by CD Projekt RED", name) == 0) + const auto execute = ImGui::InputText("", command, std::size(command), ImGuiInputTextFlags_EnterReturnsTrue); + if (execute) { - *reinterpret_cast(lParam) = hwnd; - return FALSE; + std::string returnMessage; + + if (!Scripting::Execute(command, returnMessage)) + { + std::lock_guard _{ m_outputLock }; + m_outputLines.push_back(std::string("Error ") + returnMessage); + } + else + { + std::lock_guard _{ m_outputLock }; + m_outputLines.push_back(std::string(command) + std::string(" - success!")); + } } } - return TRUE; -} -WNDPROC oWndProc; + ImGui::End(); -extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); + ImGui::Render(); +} -LRESULT APIENTRY WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +LRESULT APIENTRY Overlay::WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { if (ImGui_ImplWin32_WndProcHandler(hwnd, uMsg, wParam, lParam)) return true; @@ -89,278 +102,40 @@ LRESULT APIENTRY WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) break; } - if(s_pOverlay->IsEnabled() && uMsg != WM_PAINT && uMsg != WM_ACTIVATE && uMsg != WM_QUIT && uMsg != WM_CLOSE && uMsg != WM_DESTROY) + if(s_pOverlay->IsEnabled() && uMsg != WM_PAINT && uMsg != WM_ACTIVATE && uMsg != WM_QUIT && uMsg != WM_CLOSE && uMsg != WM_DESTROY) { return true; } - return CallWindowProc(oWndProc, hwnd, uMsg, wParam, lParam); -} - -void Overlay::InitializeD3D12(IDXGISwapChain3* pSwapChain) -{ - EnumWindows(EnumWindowsProcMy, reinterpret_cast(&m_hwnd)); - - oWndProc = reinterpret_cast(SetWindowLongPtr(m_hwnd, GWLP_WNDPROC, reinterpret_cast(WndProc))); - - ID3D12Device* d3d12Device = nullptr; - - if (SUCCEEDED(pSwapChain->GetDevice(__uuidof(ID3D12Device), (void**)&d3d12Device))) - { - ImGui::CreateContext(); - - unsigned char* pixels; - int width, height; - ImGuiIO& io = ImGui::GetIO(); (void)io; - ImGui::StyleColorsDark(); - io.Fonts->AddFontDefault(); - io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); - io.IniFilename = NULL; - - DXGI_SWAP_CHAIN_DESC sdesc; - pSwapChain->GetDesc(&sdesc); - - auto buffersCounts = sdesc.BufferCount; - m_frameContexts.resize(buffersCounts); - - { - D3D12_DESCRIPTOR_HEAP_DESC desc = {}; - desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV; - desc.NumDescriptors = buffersCounts; - desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE; - desc.NodeMask = 1; - if (d3d12Device->CreateDescriptorHeap(&desc, IID_PPV_ARGS(&m_pd3dRtvDescHeap)) != S_OK) - return; - - SIZE_T rtvDescriptorSize = d3d12Device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV); - D3D12_CPU_DESCRIPTOR_HANDLE rtvHandle = m_pd3dRtvDescHeap->GetCPUDescriptorHandleForHeapStart(); - for (UINT i = 0; i < buffersCounts; i++) - { - m_frameContexts[i].MainRenderTargetDescriptor = rtvHandle; - rtvHandle.ptr += rtvDescriptorSize; - } - } - - { - D3D12_DESCRIPTOR_HEAP_DESC desc = {}; - desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV; - desc.NumDescriptors = 1; - desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE; - if (d3d12Device->CreateDescriptorHeap(&desc, IID_PPV_ARGS(&m_pd3dSrvDescHeap)) != S_OK) - return; - } - - for (UINT i = 0; i < buffersCounts; i++) - if (d3d12Device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&m_frameContexts[i].CommandAllocator)) != S_OK) - return; - - if (d3d12Device->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, m_frameContexts[0].CommandAllocator, nullptr, IID_PPV_ARGS(&m_pd3dCommandList)) != S_OK || - m_pd3dCommandList->Close() != S_OK) - return; - - for (UINT i = 0; i < buffersCounts; i++) - { - pSwapChain->GetBuffer(i, IID_PPV_ARGS(&m_frameContexts[i].BackBuffer)); - d3d12Device->CreateRenderTargetView(m_frameContexts[i].BackBuffer, nullptr, m_frameContexts[i].MainRenderTargetDescriptor); - } - - ImGui_ImplWin32_Init(m_hwnd); - ImGui_ImplDX12_Init(d3d12Device, buffersCounts, - DXGI_FORMAT_R8G8B8A8_UNORM, m_pd3dSrvDescHeap, - m_pd3dSrvDescHeap->GetCPUDescriptorHandleForHeapStart(), - m_pd3dSrvDescHeap->GetGPUDescriptorHandleForHeapStart()); - } + return CallWindowProc(s_pOverlay->m_wndProc, hwnd, uMsg, wParam, lParam); } +using TScriptCall = void*(uint8_t*, uint8_t**, REDString*, void*); -struct REDString -{ - char** str; - uint8_t pad8[0x14 - 0x8]; - uint32_t someHash{ 0x40000000 }; - uint8_t pad18[0x20 - 0x18]; -}; - -using TConsoleExecute = bool(void* a1, char* apCommand, void* a3); -using TStringCtor = void(REDString*, uintptr_t); -TStringCtor* RealStringCtor = (TStringCtor*)(0x1B7830 + (uintptr_t)GetModuleHandleA(nullptr)); - -struct Result -{ - struct Unk28 - { - uintptr_t vtbl{ 0x2F2B150 + (uintptr_t)GetModuleHandleA(nullptr) }; - uintptr_t unk8{ 0 }; - }; - - Result() - { - RealStringCtor(&someStr, 0x2F2A4FD + (uintptr_t)GetModuleHandleA(nullptr)); - } - - REDString someStr; - uint32_t number{ 7 }; - Unk28 unk28; - int number2{ 0 }; - uint8_t pad[0x1000]; // we don't know -}; - -struct Console +TScriptCall** GetScriptCallArray() { - static Console* Get() - { - static Console** Singleton = (Console**)((uintptr_t)GetModuleHandleA(nullptr) + 0x406B050); - return *Singleton; - } - - virtual ~Console(); - virtual void sub_01(); - virtual void sub_02(); - virtual void sub_03(); - virtual void sub_04(); - virtual void sub_05(); - virtual void sub_06(); - virtual void sub_07(); - virtual void sub_08(); - virtual bool Execute(REDString* apCommand, Result* output); -}; - -void Overlay::Render(IDXGISwapChain3* pSwapChain) -{ - if (!IsEnabled()) - return; - - ImGui_ImplDX12_NewFrame(); - ImGui_ImplWin32_NewFrame(); - ImGui::NewFrame(); - - ImGui::Begin("Cyber Engine Tweaks"); - - if (Options::Get().GameImage.version == Image::MakeVersion(1, 4)) - { - ImGui::PushItemWidth(600.f); - - static std::vector s_consoleResult; - static char command[512] = { 0 }; - - auto execute = ImGui::InputText("Console", command, std::size(command), ImGuiInputTextFlags_EnterReturnsTrue); - if (ImGui::Button("Execute") || execute) - { - Result result; - - REDString redCommand; - redCommand.str = (char**)&command; - Console::Get()->Execute(&redCommand, &result); - - s_consoleResult.push_back(*(char**)result.unk28.vtbl); - } - - const auto result = ImGui::ListBoxHeader("List", s_consoleResult.size(), 15); - for (auto& item : s_consoleResult) - ImGui::Selectable(item.c_str()); + static uint8_t* pLocation = FindSignature({ 0x4C, 0x8D, 0x15, 0xCC, 0xCC, 0xCC, 0xCC, 0x48, 0x89, 0x42, 0x38, 0x49, 0x8B, 0xF8, 0x48, 0x8B, 0x02, 0x4C, 0x8D, 0x44, 0x24, 0x20, 0xC7 }) + 3; + static uintptr_t finalLocation = (uintptr_t)pLocation + 4 + *reinterpret_cast(pLocation); - if (result) - ImGui::ListBoxFooter(); - } - - ImGui::End(); - - ImGui::Render(); - - const auto bufferIndex = pSwapChain->GetCurrentBackBufferIndex(); - - auto& currentFrameContext = m_frameContexts[bufferIndex]; - 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.BackBuffer; - barrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES; - barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_PRESENT; - barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_RENDER_TARGET; - - m_pd3dCommandList->Reset(currentFrameContext.CommandAllocator, nullptr); - m_pd3dCommandList->ResourceBarrier(1, &barrier); - m_pd3dCommandList->OMSetRenderTargets(1, ¤tFrameContext.MainRenderTargetDescriptor, FALSE, nullptr); - m_pd3dCommandList->SetDescriptorHeaps(1, &m_pd3dSrvDescHeap); - - ImGui_ImplDX12_RenderDrawData(ImGui::GetDrawData(), m_pd3dCommandList); - - barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_RENDER_TARGET; - barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_PRESENT; - - m_pd3dCommandList->ResourceBarrier(1, &barrier); - m_pd3dCommandList->Close(); - - auto* pCommandQueue = *reinterpret_cast(reinterpret_cast(pSwapChain) + kiero::getCommandQueueOffset()); - - pCommandQueue->ExecuteCommandLists(1, reinterpret_cast(&m_pd3dCommandList)); + return reinterpret_cast(finalLocation); } -long Overlay::PresentD3D12(IDXGISwapChain3* pSwapChain, UINT SyncInterval, UINT Flags) -{ - static std::once_flag s_init; - std::call_once(s_init, [pSwapChain]() - { - s_pOverlay->InitializeD3D12(pSwapChain); - }); - s_pOverlay->Render(pSwapChain); - - return s_pOverlay->m_realPresentD3D12(pSwapChain, SyncInterval, Flags); -} - -struct SomeStruct -{ - uint8_t pad0[0x140]; - uint32_t unk140; - uint8_t pad144[0x164 - 0x144]; - uint32_t unk164; - HWND Wnd; - uint8_t pad170[0x9]; - uint8_t isClipped; -}; - -static_assert(offsetof(SomeStruct, unk140) == 0x140); -static_assert(offsetof(SomeStruct, unk164) == 0x164); -static_assert(offsetof(SomeStruct, Wnd) == 0x168); -static_assert(offsetof(SomeStruct, isClipped) == 0x179); - -BOOL Overlay::ClipToCenter(SomeStruct* apThis) +void* Overlay::Log(uintptr_t apThis, uint8_t** apStack) { - auto wnd = apThis->Wnd; - auto foreground = GetForegroundWindow(); - if(wnd == foreground && apThis->unk164 && !apThis->unk140 && !s_pOverlay->IsEnabled()) - { - RECT rect; - GetClientRect(wnd, &rect); - ClientToScreen(wnd, (POINT*)&rect.left); - ClientToScreen(wnd, (POINT*)&rect.right); - rect.left = (rect.left + rect.right) / 2; - rect.right = rect.left; - rect.bottom = (rect.bottom + rect.top) / 2; - rect.top = rect.bottom; - apThis->isClipped = true; - ShowCursor(FALSE); - return ClipCursor(&rect); - } + REDString result(""); + apStack[6] = nullptr; + apStack[7] = nullptr; + auto stack = *(*apStack)++; + GetScriptCallArray()[stack](apStack[8], apStack, &result, nullptr); + ++(*apStack); - if(apThis->isClipped) - { - apThis->isClipped = false; - return ClipCursor(nullptr); - } + std::lock_guard _{ Get().m_outputLock }; + Get().m_outputLines.emplace_back(result.ToString()); - return 1; -} + result.Destroy(); -void Overlay::Hook() -{ - if (kiero::bind(140, reinterpret_cast(&m_realPresentD3D12), PresentD3D12) != kiero::Status::Success) - spdlog::error("\tD3D12 PresentD3D12 Hook failed!"); - - spdlog::info("\tD3D12 hook complete"); + return 0; } void Overlay::Toggle() @@ -381,8 +156,7 @@ void Overlay::Toggle() break; } - Singleton* pSingleton = *(Singleton**)(0x40689D8 + (uintptr_t)GetModuleHandleA(nullptr)); - ClipToCenter(pSingleton->pSomeStruct); + ClipToCenter(CGameEngine::Get()->pSomeStruct); } bool Overlay::IsEnabled() @@ -390,7 +164,6 @@ bool Overlay::IsEnabled() return m_enabled; } - Overlay::Overlay() = default; Overlay::~Overlay() = default; diff --git a/src/overlay/Overlay.h b/src/overlay/Overlay.h index da16af39..7c58617f 100644 --- a/src/overlay/Overlay.h +++ b/src/overlay/Overlay.h @@ -1,17 +1,18 @@ #pragma once #include -#include #include +#include +#include #include #include -struct SomeStruct; - +#include "reverse/Engine.h" using TPresentD3D12 = long(IDXGISwapChain3* pSwapChain, UINT SyncInterval, UINT Flags); using TSetMousePosition = BOOL(void* apThis, HWND Wnd, long X, long Y); -using TClipToCenter = HWND(SomeStruct* apThis); +using TClipToCenter = HWND(CGameEngine::UnkC0* apThis); +using TLog = void*(uintptr_t a1, uint8_t** a2); struct Image; struct Overlay @@ -40,10 +41,13 @@ struct Overlay void InitializeD3D12(IDXGISwapChain3* pSwapChain); void Render(IDXGISwapChain3* pSwapChain); + void DrawImgui(IDXGISwapChain3* apSwapChain); static long PresentD3D12(IDXGISwapChain3* pSwapChain, UINT SyncInterval, UINT Flags); static BOOL SetMousePosition(void* apThis, HWND Wnd, long X, long Y); - static BOOL ClipToCenter(SomeStruct* apThis); + static BOOL ClipToCenter(CGameEngine::UnkC0* apThis); + static LRESULT APIENTRY WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); + static void* Log(uintptr_t apThis, uint8_t** apStack); private: @@ -55,6 +59,11 @@ struct Overlay ID3D12DescriptorHeap* m_pd3dSrvDescHeap; ID3D12GraphicsCommandList* m_pd3dCommandList; TClipToCenter* m_realClipToCenter{nullptr}; + TLog* m_realLog{nullptr}; HWND m_hwnd; + WNDPROC m_wndProc{nullptr}; bool m_enabled{ false }; + + std::recursive_mutex m_outputLock; + std::vector m_outputLines; }; diff --git a/src/overlay/Overlay_D3D12.cpp b/src/overlay/Overlay_D3D12.cpp new file mode 100644 index 00000000..91d24829 --- /dev/null +++ b/src/overlay/Overlay_D3D12.cpp @@ -0,0 +1,146 @@ +#include "Overlay.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "imgui_impl_dx12.h" +#include "imgui_impl_win32.h" + + +BOOL CALLBACK EnumWindowsProcMy(HWND hwnd, LPARAM lParam) +{ + DWORD lpdwProcessId; + GetWindowThreadProcessId(hwnd, &lpdwProcessId); + if (lpdwProcessId == GetCurrentProcessId()) + { + char name[512] = { 0 }; + GetWindowTextA(hwnd, name, 511); + if (strcmp("Cyberpunk 2077 (C) 2020 by CD Projekt RED", name) == 0) + { + *reinterpret_cast(lParam) = hwnd; + return FALSE; + } + } + return TRUE; +} + +void Overlay::InitializeD3D12(IDXGISwapChain3* pSwapChain) +{ + EnumWindows(EnumWindowsProcMy, reinterpret_cast(&m_hwnd)); + + m_wndProc = reinterpret_cast(SetWindowLongPtr(m_hwnd, GWLP_WNDPROC, reinterpret_cast(WndProc))); + + ID3D12Device* d3d12Device = nullptr; + + if (SUCCEEDED(pSwapChain->GetDevice(__uuidof(ID3D12Device), reinterpret_cast(&d3d12Device)))) + { + ImGui::CreateContext(); + + unsigned char* pixels; + int width, height; + ImGuiIO& io = ImGui::GetIO(); (void)io; + ImGui::StyleColorsDark(); + io.Fonts->AddFontDefault(); + io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); + io.IniFilename = NULL; + + DXGI_SWAP_CHAIN_DESC sdesc; + pSwapChain->GetDesc(&sdesc); + + auto buffersCounts = sdesc.BufferCount; + m_frameContexts.resize(buffersCounts); + + { + D3D12_DESCRIPTOR_HEAP_DESC desc = {}; + desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV; + desc.NumDescriptors = buffersCounts; + desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE; + desc.NodeMask = 1; + if (d3d12Device->CreateDescriptorHeap(&desc, IID_PPV_ARGS(&m_pd3dRtvDescHeap)) != S_OK) + return; + + const SIZE_T rtvDescriptorSize = d3d12Device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV); + D3D12_CPU_DESCRIPTOR_HANDLE rtvHandle = m_pd3dRtvDescHeap->GetCPUDescriptorHandleForHeapStart(); + for (UINT i = 0; i < buffersCounts; i++) + { + m_frameContexts[i].MainRenderTargetDescriptor = rtvHandle; + rtvHandle.ptr += rtvDescriptorSize; + } + } + + { + D3D12_DESCRIPTOR_HEAP_DESC desc = {}; + desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV; + desc.NumDescriptors = 1; + desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE; + if (d3d12Device->CreateDescriptorHeap(&desc, IID_PPV_ARGS(&m_pd3dSrvDescHeap)) != S_OK) + return; + } + + for (UINT i = 0; i < buffersCounts; i++) + if (d3d12Device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&m_frameContexts[i].CommandAllocator)) != S_OK) + return; + + if (d3d12Device->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, m_frameContexts[0].CommandAllocator, nullptr, IID_PPV_ARGS(&m_pd3dCommandList)) != S_OK || + m_pd3dCommandList->Close() != S_OK) + return; + + for (UINT i = 0; i < buffersCounts; i++) + { + pSwapChain->GetBuffer(i, IID_PPV_ARGS(&m_frameContexts[i].BackBuffer)); + d3d12Device->CreateRenderTargetView(m_frameContexts[i].BackBuffer, nullptr, m_frameContexts[i].MainRenderTargetDescriptor); + } + + ImGui_ImplWin32_Init(m_hwnd); + ImGui_ImplDX12_Init(d3d12Device, buffersCounts, + DXGI_FORMAT_R8G8B8A8_UNORM, m_pd3dSrvDescHeap, + m_pd3dSrvDescHeap->GetCPUDescriptorHandleForHeapStart(), + m_pd3dSrvDescHeap->GetGPUDescriptorHandleForHeapStart()); + } +} + +void Overlay::Render(IDXGISwapChain3* pSwapChain) +{ + if (!IsEnabled()) + return; + + DrawImgui(pSwapChain); + + const auto bufferIndex = pSwapChain->GetCurrentBackBufferIndex(); + + auto& currentFrameContext = m_frameContexts[bufferIndex]; + 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.BackBuffer; + barrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES; + barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_PRESENT; + barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_RENDER_TARGET; + + m_pd3dCommandList->Reset(currentFrameContext.CommandAllocator, nullptr); + m_pd3dCommandList->ResourceBarrier(1, &barrier); + m_pd3dCommandList->OMSetRenderTargets(1, ¤tFrameContext.MainRenderTargetDescriptor, FALSE, nullptr); + m_pd3dCommandList->SetDescriptorHeaps(1, &m_pd3dSrvDescHeap); + + ImGui_ImplDX12_RenderDrawData(ImGui::GetDrawData(), m_pd3dCommandList); + + barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_RENDER_TARGET; + barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_PRESENT; + + m_pd3dCommandList->ResourceBarrier(1, &barrier); + m_pd3dCommandList->Close(); + + auto* pCommandQueue = *reinterpret_cast(reinterpret_cast(pSwapChain) + kiero::getCommandQueueOffset()); + + pCommandQueue->ExecuteCommandLists(1, reinterpret_cast(&m_pd3dCommandList)); +} + diff --git a/src/overlay/Overlay_Hooks.cpp b/src/overlay/Overlay_Hooks.cpp new file mode 100644 index 00000000..ad846e4a --- /dev/null +++ b/src/overlay/Overlay_Hooks.cpp @@ -0,0 +1,94 @@ +#include "Overlay.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +void Overlay::EarlyHooks(Image* apImage) +{ + uint8_t* pLocation = FindSignature({ + 0x48, 0x89, 0x5C, 0x24, 0x08, 0x57, 0x48, 0x83, 0xEC, 0x30, 0x48, 0x8B, + 0x99, 0x68, 0x01, 0x00, 0x00, 0x48, 0x8B, 0xF9, 0xFF }); + + if (pLocation) + { + if (MH_CreateHook(pLocation, &ClipToCenter, reinterpret_cast(&m_realClipToCenter)) != MH_OK || MH_EnableHook(pLocation) != MH_OK) + { + spdlog::error("\tCould not hook mouse clip function!"); + } + else + spdlog::info("\tHook mouse clip function!"); + } + + pLocation = FindSignature({ + 0x40, 0x53, 0x48, 0x83, 0xEC, 0x40, 0x48, 0x8B, + 0xDA, 0xE8, 0xCC, 0xCC, 0xCC, 0xCC, 0x48, 0x8B, + 0xD0, 0x48, 0x8D, 0x4C, 0x24, 0x20 + }); + + if(pLocation) + { + if (MH_CreateHook(pLocation, &Log, reinterpret_cast(&m_realLog)) != MH_OK || MH_EnableHook(pLocation) != MH_OK) + { + spdlog::error("\tCould not hook Log function!"); + } + else + spdlog::info("\tLog function hook complete!"); + } +} + +long Overlay::PresentD3D12(IDXGISwapChain3* pSwapChain, UINT SyncInterval, UINT Flags) +{ + static std::once_flag s_init; + std::call_once(s_init, [pSwapChain]() + { + Get().InitializeD3D12(pSwapChain); + }); + + Get().Render(pSwapChain); + + return Get().m_realPresentD3D12(pSwapChain, SyncInterval, Flags); +} + +BOOL Overlay::ClipToCenter(CGameEngine::UnkC0* apThis) +{ + const HWND wnd = apThis->Wnd; + const HWND foreground = GetForegroundWindow(); + + if(wnd == foreground && apThis->unk164 && !apThis->unk140 && !Get().IsEnabled()) + { + RECT rect; + GetClientRect(wnd, &rect); + ClientToScreen(wnd, reinterpret_cast(&rect.left)); + ClientToScreen(wnd, reinterpret_cast(&rect.right)); + rect.left = (rect.left + rect.right) / 2; + rect.right = rect.left; + rect.bottom = (rect.bottom + rect.top) / 2; + rect.top = rect.bottom; + apThis->isClipped = true; + ShowCursor(FALSE); + return ClipCursor(&rect); + } + + if(apThis->isClipped) + { + apThis->isClipped = false; + return ClipCursor(nullptr); + } + + return 1; +} + +void Overlay::Hook() +{ + if (kiero::bind(140, reinterpret_cast(&m_realPresentD3D12), &PresentD3D12) != kiero::Status::Success) + spdlog::error("\tD3D12 PresentD3D12 Hook failed!"); + + spdlog::info("\tD3D12 hook complete"); +} + diff --git a/src/reverse/Engine.cpp b/src/reverse/Engine.cpp new file mode 100644 index 00000000..92a5b049 --- /dev/null +++ b/src/reverse/Engine.cpp @@ -0,0 +1,12 @@ +#include "Engine.h" + +#include "Pattern.h" + +CGameEngine* CGameEngine::Get() +{ + static auto* ptr = FindSignature({ 0x48, 0x89, 0x05, 0xCC, 0xCC, 0xCC, 0xCC, + 0x49, 0x8D, 0x9D, 0x88, 0x00, 0x00, 0x00, + 0x49, 0x8B, 0x07, 0x4C, 0x8B, 0xC3 }) + 3; + + return *reinterpret_cast(ptr + *reinterpret_cast(ptr) + 4); +} diff --git a/src/reverse/Engine.h b/src/reverse/Engine.h new file mode 100644 index 00000000..01a50ff5 --- /dev/null +++ b/src/reverse/Engine.h @@ -0,0 +1,58 @@ +#pragma once + +#include +#include +#include + +struct CRTTIBaseType; +struct SomeStruct; + +struct BaseGameEngine +{ + virtual void sub_0() = 0; +}; + +struct CBaseEngine : BaseGameEngine +{ +}; + +struct CGameEngine : CBaseEngine +{ + struct CGameFramework + { + struct Unk + { + virtual ~Unk() = 0; + virtual uintptr_t GetTypeInstance(CRTTIBaseType* aClass) = 0; + }; + + int8_t unk0[0x10]; + Unk* unk10; + }; + + struct UnkC0 + { + uint8_t pad0[0x140]; + uint32_t unk140; + uint8_t pad144[0x164 - 0x144]; + uint32_t unk164; + HWND Wnd; + uint8_t pad170[0x9]; + uint8_t isClipped; + }; + + static CGameEngine* Get(); + + int8_t pad8[0xC0 - 0x8]; + UnkC0* pSomeStruct; + int8_t padC8[0x260 - 0xC8]; + CGameFramework* framework; +}; + +static_assert(offsetof(CGameEngine, pSomeStruct) == 0xC0); +static_assert(offsetof(CGameEngine, framework) == 0x260); + +static_assert(offsetof(CGameEngine::UnkC0, unk140) == 0x140); +static_assert(offsetof(CGameEngine::UnkC0, unk164) == 0x164); +static_assert(offsetof(CGameEngine::UnkC0, Wnd) == 0x168); +static_assert(offsetof(CGameEngine::UnkC0, isClipped) == 0x179); \ No newline at end of file diff --git a/src/reverse/REDString.cpp b/src/reverse/REDString.cpp new file mode 100644 index 00000000..a16e4818 --- /dev/null +++ b/src/reverse/REDString.cpp @@ -0,0 +1,40 @@ +#include "REDString.h" + +#include "Pattern.h" + +REDString::REDString() +{ + using TStringCtor = void(REDString*, const char*); + static TStringCtor* RealStringCtor = reinterpret_cast(FindSignature({ + 0x40, 0x53, 0x48, 0x83, 0xEC, 0x20, 0x33, 0xC0, + 0xC6, 0x01, 0x00, 0x48, 0x89, 0x41, 0x18, 0x48, + 0x8B, 0xD9, 0x89, 0x41, 0x14, 0x48, 0x85, 0xD2, + 0x74, 0x10, 0x48, 0xC7, 0xC0, 0xFF, 0xFF, 0xFF + })); + + RealStringCtor(this, ""); +} + +REDString::REDString(const char* acpData) +{ + using TStringCtor = void(REDString*, const char*); + static TStringCtor* RealStringCtor = reinterpret_cast(FindSignature({ + 0x40, 0x53, 0x48, 0x83, 0xEC, 0x20, 0x33, 0xC0, + 0xC6, 0x01, 0x00, 0x48, 0x89, 0x41, 0x18, 0x48, + 0x8B, 0xD9, 0x89, 0x41, 0x14, 0x48, 0x85, 0xD2, + 0x74, 0x10, 0x48, 0xC7, 0xC0, 0xFF, 0xFF, 0xFF + })); + + RealStringCtor(this, acpData); +} + +void REDString::Destroy() +{ + using TStringDtor = void(REDString*); + static TStringDtor* RealStringDtor = reinterpret_cast(FindSignature({ + 0x40, 0x53, 0x48, 0x83, 0xEC, 0x20, 0x48, 0x8B, + 0xD9, 0x8B, 0x49, 0x14, 0x8B, 0xC1, 0xC1, 0xE8 + })); + + RealStringDtor(this); +} diff --git a/src/reverse/REDString.h b/src/reverse/REDString.h new file mode 100644 index 00000000..cc0a67f9 --- /dev/null +++ b/src/reverse/REDString.h @@ -0,0 +1,44 @@ +#pragma once + +#include +#include + +struct REDString +{ + REDString(); + REDString(const char* acpData); + void Destroy(); + + char* ToString() + { + if (size >= 0x40000000u) + return *(char**)str; + return reinterpret_cast(str); + } + + char str[0x14]; + uint32_t size{ 0x40000000 }; + uint8_t pad18[0x20 - 0x18]; + +private: + + static constexpr uint64_t RecursiveHash(const char* acpStr, uint64_t aHash) + { + if (*acpStr) { + aHash ^= *acpStr; + aHash *= 1099511628211ull; + + return RecursiveHash(acpStr + 1, aHash); + } + + return aHash; + } + +public: + static constexpr uint64_t Hash(const char* acpStr) + { + return RecursiveHash(acpStr, 14695981039346656037ull); + } +}; + +static_assert(offsetof(REDString, size) == 0x14); diff --git a/src/reverse/RTTI.cpp b/src/reverse/RTTI.cpp new file mode 100644 index 00000000..0f08f78d --- /dev/null +++ b/src/reverse/RTTI.cpp @@ -0,0 +1,29 @@ +#include "RTTI.h" + +#include "Pattern.h" + +using TCClass_GetFunction = CClassFunction * (CRTTIBaseType* apBase, uint64_t aHash); +using TCRTTISystem_Get = CRTTISystem*(); + +CClassFunction* CClass::GetFunction(uint64_t aName) +{ + static auto* RealCClass_GetFunction = reinterpret_cast(FindSignature( + { + 0x4C, 0x8B, 0xC9, 0x48, 0x85, 0xC9, 0x74, 0x5E, + 0x49, 0x8B, 0x41, 0x48 + })); + + if (RealCClass_GetFunction) + return RealCClass_GetFunction(this, aName); + + return nullptr; +} + +CRTTISystem* CRTTISystem::Get() +{ + static auto* RealCRTTISystem_Get = (TCRTTISystem_Get*)FindSignature({ 0x40, 0x53, 0x48, 0x83, 0xEC, 0x20, 0x65, 0x48, + 0x8B, 0x04, 0x25, 0x58, 0x00, 0x00, 0x00, 0x48, + 0x8D, 0x1D, 0xCC, 0xCC, 0xCC, 0xCC }); + + return RealCRTTISystem_Get(); +} diff --git a/src/reverse/RTTI.h b/src/reverse/RTTI.h new file mode 100644 index 00000000..7db17d6d --- /dev/null +++ b/src/reverse/RTTI.h @@ -0,0 +1,94 @@ +#pragma once + +#include + +enum class RTTIType : uint8_t +{ + Name, + Fundamental, + Class, + Array, + Simple, + Enum, + StaticArray, + NativeArray, + Pointer, + Handle, + WeakHandle, + ResourceReference, + ResourceAsyncReference, + BitField, + LegacySingleChannelCurve, + ScriptReference +}; + +struct CRTTIBaseType +{ + virtual ~CRTTIBaseType() = 0; + virtual void GetName(uint64_t* aOut) = 0; + virtual void sub_2() = 0; + virtual void sub_3() = 0; + virtual RTTIType GetType() = 0; + + int64_t unk8; +}; + +struct CClassFunction; +struct CBaseFunction; + +struct CClass : CRTTIBaseType +{ + CClassFunction* GetFunction(uint64_t aName); + + CClass* parent; +}; + +struct IRTTISystem +{ + virtual void sub_0() = 0; + virtual void sub_1() = 0; + virtual CRTTIBaseType* GetType(uint64_t aNameHash) = 0; + virtual void sub_3() = 0; + virtual void sub_4() = 0; + virtual void sub_5() = 0; + virtual CBaseFunction* GetGlobalFunction(uint64_t aNameHash) = 0; + virtual void sub_7() = 0; + virtual void sub_8() = 0; + virtual void sub_9() = 0; + virtual void sub_A() = 0; + virtual void sub_B() = 0; + virtual void sub_C() = 0; + virtual void sub_D() = 0; + virtual void sub_E() = 0; + virtual void sub_F() = 0; + virtual int64_t RegisterType(CRTTIBaseType* aType, uint32_t a2) = 0; + virtual void sub_11() = 0; + virtual void sub_12() = 0; + virtual void RegisterFunction() = 0; + virtual void sub_13() = 0; + virtual void sub_14() = 0; + virtual void sub_15() = 0; + virtual void sub_16() = 0; + virtual void sub_17() = 0; + virtual void sub_18() = 0; + virtual void sub_19() = 0; + virtual void sub_1A() = 0; + virtual void sub_1B() = 0; + virtual void sub_1C() = 0; + virtual void sub_1D() = 0; + virtual void sub_1E() = 0; + virtual void sub_1F() = 0; + + virtual ~IRTTISystem() = 0; + + template + T* GetType(uint64_t aNameHash) + { + return static_cast(GetType(aNameHash)); + } +}; + +struct CRTTISystem : IRTTISystem +{ + static CRTTISystem* Get(); +}; \ No newline at end of file diff --git a/src/reverse/Scripting.cpp b/src/reverse/Scripting.cpp new file mode 100644 index 00000000..ae3dc6d0 --- /dev/null +++ b/src/reverse/Scripting.cpp @@ -0,0 +1,128 @@ +#include "Scripting.h" + +#include +#include +#include + +#include "Engine.h" +#include "Options.h" +#include "Pattern.h" +#include "RTTI.h" +#include "Utils.h" + +using TExec = bool(void* apThis, ScriptArgs* apArgs, Result* apResult, uintptr_t apScriptable); +auto* RealExec = (TExec*)(0x25FB960 + reinterpret_cast(GetModuleHandleA(nullptr))); + +struct Unk523 +{ + int64_t unk0; + uint64_t unk8; +}; + +struct CScriptableStackFrame +{ + int64_t vtbl; + int64_t unk8; + int64_t unk10; + int64_t scriptable18; + int64_t scriptable20; + int64_t unk28; + int64_t args; + int32_t argCount; + int64_t unk40; +}; + +bool Scripting::Execute(const std::string& aCommand, std::string& aReturnMessage) +{ + const auto argsStart = aCommand.find_first_of('('); + const auto argsEnd = aCommand.find_first_of(')'); + + auto funcName = aCommand.substr(0, argsStart); + trim(funcName); + + std::string s = aCommand.substr(argsStart + 1, argsEnd - argsStart - 1); + const std::string delimiter = ","; + + std::vector redArgs; + redArgs.reserve(100); + redArgs.emplace_back(funcName.c_str()); + + size_t pos = 0; + std::string token; + while ((pos = s.find(delimiter)) != std::string::npos) { + token = s.substr(0, pos); + trim(token); + redArgs.emplace_back(token.c_str()); + s.erase(0, pos + delimiter.length()); + } + trim(s); + redArgs.emplace_back(s.c_str()); + + uintptr_t arg0Rtti = 0; + uintptr_t argiRtti = 0; + uintptr_t ctorOffset = 0; + uintptr_t execOffset = 0; + + if (Options::Get().GameImage.version == Image::MakeVersion(1, 4)) + { + arg0Rtti = 0x1442FD030 - 0x140000000; + argiRtti = 0x143C62438 - 0x140000000; + ctorOffset = 0x140270370 - 0x140000000; + execOffset = 0x1402254A0 - 0x140000000; + } + else if (Options::Get().GameImage.version == Image::MakeVersion(1, 5)) + { + arg0Rtti = 0x1442BC710 - 0x140000000; + argiRtti = 0x143C22238 - 0x140000000; + ctorOffset = 0x14026F8A0 - 0x140000000; + execOffset = 0x1402249F0 - 0x140000000; + } + + auto* const type = CRTTISystem::Get()->GetType(REDString::Hash("cpPlayerSystem")); + auto* const engine = CGameEngine::Get(); + auto* unk10 = engine->framework->unk10; + + auto func = CRTTISystem::Get()->GetGlobalFunction(REDString::Hash(funcName.c_str())); + + const auto scriptable = unk10->GetTypeInstance(type); + + uint64_t a1 = *(uintptr_t*)(scriptable + 0x40); + + Unk523 args[4]; + args[0].unk0 = *(uintptr_t*)(arg0Rtti + (uintptr_t)GetModuleHandle(nullptr)); + args[0].unk8 = (uint64_t)&a1; + + for(auto i = 1u; i < redArgs.size(); ++i) + { + args[i].unk0 = (uintptr_t)(argiRtti + (uintptr_t)GetModuleHandle(nullptr)); + args[i].unk8 = (uint64_t)&redArgs[i]; + } + + CScriptableStackFrame stack; + auto script40 = *(uintptr_t*)(scriptable + 0x40); + auto script40100 = *(uintptr_t*)(script40 + 0x100); + + using ctor_t = CScriptableStackFrame * (*)(CScriptableStackFrame* aThis, __int64 aScriptable, Unk523* aArgs, + int aArgsCount, __int64 a5, __int64* a6); + ctor_t ctor = (ctor_t)(ctorOffset + (uintptr_t)GetModuleHandle(nullptr)); + + Result result; + + ctor(&stack, scriptable, args, 3, 0, 0); + + using exec_t = bool (*)(CBaseFunction* aThis, CScriptableStackFrame* stack); + exec_t exec = (exec_t)(execOffset + (uintptr_t)GetModuleHandle(nullptr)); + + return exec(func, &stack); +} + +Result::Result() +{ + static auto* ptr = FindSignature({ + 0x48, 0x89, 0xB4, 0x24, 0xD8, 0x01, 0x00, 0x00, 0xB9, + 0x05, 0x00, 0x00, 0x00, 0x4C, 0x89, 0xA4, 0x24, 0xA0, + 0x01, 0x00, 0x00, 0x66, 0x3B, 0xC1, 0x4C, 0x89, 0xAC, + 0x24, 0x98, 0x01, 0x00, 0x00, 0x4C, 0x8D, 0x25 }) + 0x24; + + output = reinterpret_cast(ptr + *reinterpret_cast(ptr) + 4); +} diff --git a/src/reverse/Scripting.h b/src/reverse/Scripting.h new file mode 100644 index 00000000..86841e9b --- /dev/null +++ b/src/reverse/Scripting.h @@ -0,0 +1,34 @@ +#pragma once + +#include +#include +#include + +#include "REDString.h" + +struct Scripting +{ + static bool Execute(const std::string& aCommand, std::string& aReturnMessage); +}; + +struct Result +{ + Result(); + + REDString someStr; + uint64_t code{ 7 }; + REDString* output; + int number2{ 0 }; + uint8_t pad[0x1000]; // pad just in case +}; + +static_assert(offsetof(Result, code) == 0x20); +static_assert(offsetof(Result, output) == 0x28); + +struct ScriptArgs +{ + REDString* args; + uint32_t pad8; + uint32_t argCount; + uint8_t pad[0x100]; // pad just in case +}; diff --git a/src/string_initalizer_patch.cpp b/src/string_initalizer_patch.cpp index 7772d1fa..2e67b809 100644 --- a/src/string_initalizer_patch.cpp +++ b/src/string_initalizer_patch.cpp @@ -1,8 +1,4 @@ -#include - #include "Image.h" -#include -#include #include #include diff --git a/xmake.lua b/xmake.lua index b8321a65..08e5065d 100644 --- a/xmake.lua +++ b/xmake.lua @@ -14,6 +14,7 @@ target("cyber_engine_tweaks") set_kind("shared") set_filename("cyber_engine_tweaks.asi") add_files("src/**.cpp") + add_headerfiles("src/**.h") add_includedirs("src/") add_syslinks("User32", "d3d11", "D3D12") add_packages("zlib", "spdlog", "nlohmann_json", "minhook", "imgui")