├── Resources ├── BossBar.png ├── EntityBar.png ├── SekiroBar.png ├── BossBarBorder.png ├── EntityBarBorder.png ├── SekiroBarBorder.png └── SekiroEntityBarBorder.png ├── Source ├── Main │ ├── D3DRenderer.cpp │ ├── Logger.hpp │ ├── Logger.cpp │ ├── Hooking.cpp │ ├── D3DRenderer.hpp │ ├── Hooking.hpp │ ├── Memory.hpp │ └── PostureBarUI.hpp ├── dllmain.cpp ├── Common.cpp ├── PostureBarMod.hpp ├── Minhook │ ├── pstdint.h │ ├── buffer.h │ ├── hde32.h │ ├── hde64.h │ ├── table32.h │ ├── table64.h │ ├── trampoline.h │ ├── MinHook.h │ ├── hde32.c │ ├── hde64.c │ ├── buffer.c │ └── trampoline.c ├── ImGui │ ├── imgui_impl_dx12.h │ ├── imgui_impl_win32.h │ └── imconfig.h ├── Common.hpp └── Ini │ └── ini.h ├── LICENSE ├── PostureBarMod.sln ├── README.md ├── PostureBarMod.vcxproj.filters ├── Config ├── PostureBarModConfig.ini └── PostureBarModConfig - SekiroBar.ini ├── .gitignore └── PostureBarMod.vcxproj /Resources/BossBar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mordrog/EldenRing-PostureBarMod/HEAD/Resources/BossBar.png -------------------------------------------------------------------------------- /Resources/EntityBar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mordrog/EldenRing-PostureBarMod/HEAD/Resources/EntityBar.png -------------------------------------------------------------------------------- /Resources/SekiroBar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mordrog/EldenRing-PostureBarMod/HEAD/Resources/SekiroBar.png -------------------------------------------------------------------------------- /Resources/BossBarBorder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mordrog/EldenRing-PostureBarMod/HEAD/Resources/BossBarBorder.png -------------------------------------------------------------------------------- /Source/Main/D3DRenderer.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mordrog/EldenRing-PostureBarMod/HEAD/Source/Main/D3DRenderer.cpp -------------------------------------------------------------------------------- /Resources/EntityBarBorder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mordrog/EldenRing-PostureBarMod/HEAD/Resources/EntityBarBorder.png -------------------------------------------------------------------------------- /Resources/SekiroBarBorder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mordrog/EldenRing-PostureBarMod/HEAD/Resources/SekiroBarBorder.png -------------------------------------------------------------------------------- /Resources/SekiroEntityBarBorder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mordrog/EldenRing-PostureBarMod/HEAD/Resources/SekiroEntityBarBorder.png -------------------------------------------------------------------------------- /Source/dllmain.cpp: -------------------------------------------------------------------------------- 1 | #include "PostureBarMod.hpp" 2 | 3 | BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) 4 | { 5 | UNREFERENCED_PARAMETER(lpReserved); 6 | 7 | if (!g_Module) 8 | g_Module = hModule; 9 | 10 | switch (ul_reason_for_call) { 11 | case (DLL_PROCESS_ATTACH): DisableThreadLibraryCalls(hModule); CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)MainThread, g_Module, NULL, NULL); break; 12 | case (DLL_PROCESS_DETACH): g_KillSwitch = TRUE; g_Running = FALSE; break; 13 | } 14 | 15 | return TRUE; 16 | } -------------------------------------------------------------------------------- /Source/Common.cpp: -------------------------------------------------------------------------------- 1 | #include "Common.hpp" 2 | /// 3 | /// Clear Bytes 4 | /// 5 | /// Address 6 | /// Size 7 | void Nop(BYTE* dst, unsigned int size) 8 | { 9 | DWORD oldprotect; 10 | VirtualProtect(dst, size, PAGE_EXECUTE_READWRITE, &oldprotect); 11 | memset(dst, 0x90, size); 12 | VirtualProtect(dst, size, oldprotect, &oldprotect); 13 | } 14 | 15 | /// 16 | /// Patch Bytes 17 | /// 18 | /// Address 19 | /// Value 20 | /// Size 21 | void Patch(BYTE* dst, BYTE* src, unsigned int size) 22 | { 23 | DWORD oldprotect; 24 | VirtualProtect(dst, size, PAGE_EXECUTE_READWRITE, &oldprotect); 25 | memcpy(dst, src, size); 26 | VirtualProtect(dst, size, oldprotect, &oldprotect); 27 | } -------------------------------------------------------------------------------- /Source/Main/Logger.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "../Common.hpp" 3 | 4 | namespace ER 5 | { 6 | enum class LogLevel 7 | { 8 | Debug, 9 | Log, 10 | Warning, 11 | Error 12 | }; 13 | 14 | 15 | class Logger 16 | { 17 | public: 18 | static inline const std::string logFileName = "PostureModLog.txt"; 19 | static inline std::ofstream logFile; 20 | 21 | explicit Logger() = delete; 22 | ~Logger() noexcept = delete; 23 | Logger(Logger const&) = delete; 24 | Logger(Logger&&) = delete; 25 | Logger& operator=(Logger const&) = delete; 26 | Logger& operator=(Logger&&) = delete; 27 | 28 | static void log(const std::string_view& msg, LogLevel logLevel = LogLevel::Log, const std::source_location& location = std::source_location::current()); 29 | static void close(); 30 | 31 | static inline bool useLogger = false; 32 | static inline std::mutex loggerMutex; 33 | }; 34 | } -------------------------------------------------------------------------------- /Source/PostureBarMod.hpp: -------------------------------------------------------------------------------- 1 | #include "Common.hpp" 2 | 3 | using namespace ER; 4 | 5 | namespace ER 6 | { 7 | enum class EDebugTestState : int8_t 8 | { 9 | BossBarOffset = 0, 10 | EntityBarOffset = 1, 11 | GameScreenOffset = 2, 12 | PosFixingMultiplier = 3, 13 | }; 14 | 15 | template 16 | constexpr T cycleNumber(T cur, T min, T max) { if (cur > max) return min; else if (cur < min) return max; else return cur; }; 17 | 18 | static EDebugTestState cycleState(EDebugTestState oldState, int8_t mov) { return EDebugTestState(cycleNumber(((int8_t)oldState + mov), 0, 3)); } 19 | 20 | inline HMODULE g_Module{}; 21 | inline std::atomic_bool g_Running = TRUE; 22 | inline std::atomic_bool g_KillSwitch = FALSE; 23 | inline bool offsetTesting = FALSE; 24 | inline float offsetSpeed = 0.5f; 25 | inline EDebugTestState debugState = EDebugTestState::GameScreenOffset; 26 | 27 | inline std::string dllPath = ""; 28 | 29 | inline bool hideBarsOnMenu = true; 30 | } 31 | 32 | void MainThread(); -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Mordrog 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Source/Main/Logger.cpp: -------------------------------------------------------------------------------- 1 | #include "Logger.hpp" 2 | #include "../PostureBarMod.hpp" 3 | 4 | namespace ER 5 | { 6 | std::string_view logLevelText(LogLevel logLevel) 7 | { 8 | switch (logLevel) 9 | { 10 | using enum LogLevel; 11 | 12 | case Log: 13 | return "Log: "; 14 | case Warning: 15 | return "Warning: "; 16 | case Error: 17 | return "Error: "; 18 | case Debug: 19 | return "Debug: "; 20 | 21 | default: 22 | return ""; 23 | } 24 | } 25 | 26 | std::string locationText(const std::source_location& location) 27 | { 28 | std::string string = std::string(location.file_name()) + "(" + std::to_string(location.line()) + ":" + std::to_string(location.column()) + ") '" + location.function_name() + "'|\t"; 29 | return string; 30 | } 31 | 32 | void Logger::log(const std::string_view& msg, LogLevel logLevel, const std::source_location& location) 33 | { 34 | #ifndef DEBUGLOG 35 | if (logLevel == LogLevel::Debug) 36 | return; 37 | #endif // DEBUGLOG 38 | 39 | if (!useLogger) 40 | return; 41 | 42 | std::scoped_lock lock(loggerMutex); 43 | if (!logFile.is_open()) 44 | logFile.open(dllPath + logFileName, std::ifstream::out); 45 | 46 | if (logFile.good()) 47 | { 48 | logFile << locationText(location) << logLevelText(logLevel) << msg << "\n"; 49 | logFile.flush(); 50 | } 51 | } 52 | 53 | void Logger::close() 54 | { 55 | logFile.close(); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /Source/Minhook/pstdint.h: -------------------------------------------------------------------------------- 1 | /* 2 | * MinHook - The Minimalistic API Hooking Library for x64/x86 3 | * Copyright (C) 2009-2017 Tsuda Kageyu. All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 9 | * 1. Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * 2. Redistributions in binary form must reproduce the above copyright 12 | * notice, this list of conditions and the following disclaimer in the 13 | * documentation and/or other materials provided with the distribution. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR 16 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | 27 | #pragma once 28 | 29 | #include 30 | 31 | // Integer types for HDE. 32 | typedef INT8 int8_t; 33 | typedef INT16 int16_t; 34 | typedef INT32 int32_t; 35 | typedef INT64 int64_t; 36 | typedef UINT8 uint8_t; 37 | typedef UINT16 uint16_t; 38 | typedef UINT32 uint32_t; 39 | typedef UINT64 uint64_t; 40 | -------------------------------------------------------------------------------- /Source/Minhook/buffer.h: -------------------------------------------------------------------------------- 1 | /* 2 | * MinHook - The Minimalistic API Hooking Library for x64/x86 3 | * Copyright (C) 2009-2017 Tsuda Kageyu. 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright 11 | * notice, this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 18 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 19 | * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 20 | * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 21 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 22 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 23 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 24 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 25 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 26 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | #pragma once 30 | 31 | // Size of each memory slot. 32 | #if defined(_M_X64) || defined(__x86_64__) 33 | #define MEMORY_SLOT_SIZE 64 34 | #else 35 | #define MEMORY_SLOT_SIZE 32 36 | #endif 37 | 38 | VOID InitializeBuffer(VOID); 39 | VOID UninitializeBuffer(VOID); 40 | LPVOID AllocateBuffer(LPVOID pOrigin); 41 | VOID FreeBuffer(LPVOID pBuffer); 42 | BOOL IsExecutableAddress(LPVOID pAddress); 43 | -------------------------------------------------------------------------------- /PostureBarMod.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.5.33516.290 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PostureBarMod", "PostureBarMod.vcxproj", "{6AE54742-B82D-4A3E-9048-76868B06CB22}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Debug|x86 = Debug|x86 12 | Release Debug Logger|x64 = Release Debug Logger|x64 13 | Release Debug Logger|x86 = Release Debug Logger|x86 14 | Release|x64 = Release|x64 15 | Release|x86 = Release|x86 16 | EndGlobalSection 17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 18 | {6AE54742-B82D-4A3E-9048-76868B06CB22}.Debug|x64.ActiveCfg = Debug|x64 19 | {6AE54742-B82D-4A3E-9048-76868B06CB22}.Debug|x64.Build.0 = Debug|x64 20 | {6AE54742-B82D-4A3E-9048-76868B06CB22}.Debug|x86.ActiveCfg = Debug|Win32 21 | {6AE54742-B82D-4A3E-9048-76868B06CB22}.Debug|x86.Build.0 = Debug|Win32 22 | {6AE54742-B82D-4A3E-9048-76868B06CB22}.Release Debug Logger|x64.ActiveCfg = Release Debug Logger|x64 23 | {6AE54742-B82D-4A3E-9048-76868B06CB22}.Release Debug Logger|x64.Build.0 = Release Debug Logger|x64 24 | {6AE54742-B82D-4A3E-9048-76868B06CB22}.Release Debug Logger|x86.ActiveCfg = Release Debug Logger|Win32 25 | {6AE54742-B82D-4A3E-9048-76868B06CB22}.Release Debug Logger|x86.Build.0 = Release Debug Logger|Win32 26 | {6AE54742-B82D-4A3E-9048-76868B06CB22}.Release|x64.ActiveCfg = Release|x64 27 | {6AE54742-B82D-4A3E-9048-76868B06CB22}.Release|x64.Build.0 = Release|x64 28 | {6AE54742-B82D-4A3E-9048-76868B06CB22}.Release|x86.ActiveCfg = Release|Win32 29 | {6AE54742-B82D-4A3E-9048-76868B06CB22}.Release|x86.Build.0 = Release|Win32 30 | EndGlobalSection 31 | GlobalSection(SolutionProperties) = preSolution 32 | HideSolutionNode = FALSE 33 | EndGlobalSection 34 | GlobalSection(ExtensibilityGlobals) = postSolution 35 | SolutionGuid = {2FF4B4E7-4255-41B0-8512-280AB2D39B68} 36 | EndGlobalSection 37 | EndGlobal 38 | -------------------------------------------------------------------------------- /Source/ImGui/imgui_impl_dx12.h: -------------------------------------------------------------------------------- 1 | // dear imgui: Renderer Backend for DirectX12 2 | // This needs to be used along with a Platform Backend (e.g. Win32) 3 | 4 | // Implemented features: 5 | // [X] Renderer: User texture binding. Use 'D3D12_GPU_DESCRIPTOR_HANDLE' as ImTextureID. Read the FAQ about ImTextureID! 6 | // [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices. 7 | 8 | // Important: to compile on 32-bit systems, this backend requires code to be compiled with '#define ImTextureID ImU64'. 9 | // This is because we need ImTextureID to carry a 64-bit value and by default ImTextureID is defined as void*. 10 | // This define is set in the example .vcxproj file and need to be replicated in your app or by adding it to your imconfig.h file. 11 | 12 | // You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. 13 | // If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp. 14 | // Read online: https://github.com/ocornut/imgui/tree/master/docs 15 | 16 | #pragma once 17 | #include "imgui.h" // IMGUI_IMPL_API 18 | 19 | #ifdef _MSC_VER 20 | #pragma warning (push) 21 | #pragma warning (disable: 4471) // a forward declaration of an unscoped enumeration must have an underlying type 22 | #endif 23 | 24 | enum DXGI_FORMAT; 25 | struct ID3D12Device; 26 | struct ID3D12DescriptorHeap; 27 | struct ID3D12GraphicsCommandList; 28 | struct D3D12_CPU_DESCRIPTOR_HANDLE; 29 | struct D3D12_GPU_DESCRIPTOR_HANDLE; 30 | 31 | // cmd_list is the command list that the implementation will use to render imgui draw lists. 32 | // Before calling the render function, caller must prepare cmd_list by resetting it and setting the appropriate 33 | // render target and descriptor heap that contains font_srv_cpu_desc_handle/font_srv_gpu_desc_handle. 34 | // font_srv_cpu_desc_handle and font_srv_gpu_desc_handle are handles to a single SRV descriptor to use for the internal font texture. 35 | IMGUI_IMPL_API bool ImGui_ImplDX12_Init(ID3D12Device* device, int num_frames_in_flight, DXGI_FORMAT rtv_format, ID3D12DescriptorHeap* cbv_srv_heap, 36 | D3D12_CPU_DESCRIPTOR_HANDLE font_srv_cpu_desc_handle, D3D12_GPU_DESCRIPTOR_HANDLE font_srv_gpu_desc_handle); 37 | IMGUI_IMPL_API void ImGui_ImplDX12_Shutdown(); 38 | IMGUI_IMPL_API void ImGui_ImplDX12_NewFrame(); 39 | IMGUI_IMPL_API void ImGui_ImplDX12_RenderDrawData(ImDrawData* draw_data, ID3D12GraphicsCommandList* graphics_command_list); 40 | 41 | // Use if you want to reset your rendering device without losing Dear ImGui state. 42 | IMGUI_IMPL_API void ImGui_ImplDX12_InvalidateDeviceObjects(); 43 | IMGUI_IMPL_API bool ImGui_ImplDX12_CreateDeviceObjects(); 44 | 45 | #ifdef _MSC_VER 46 | #pragma warning (pop) 47 | #endif 48 | 49 | -------------------------------------------------------------------------------- /Source/ImGui/imgui_impl_win32.h: -------------------------------------------------------------------------------- 1 | // dear imgui: Platform Backend for Windows (standard windows API for 32 and 64 bits applications) 2 | // This needs to be used along with a Renderer (e.g. DirectX11, OpenGL3, Vulkan..) 3 | 4 | // Implemented features: 5 | // [X] Platform: Clipboard support (for Win32 this is actually part of core dear imgui) 6 | // [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'. 7 | // [X] Platform: Keyboard arrays indexed using VK_* Virtual Key Codes, e.g. ImGui::IsKeyPressed(VK_SPACE). 8 | // [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'. 9 | 10 | // You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. 11 | // If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp. 12 | // Read online: https://github.com/ocornut/imgui/tree/master/docs 13 | 14 | #pragma once 15 | #include "imgui.h" // IMGUI_IMPL_API 16 | 17 | IMGUI_IMPL_API bool ImGui_ImplWin32_Init(void* hwnd); 18 | IMGUI_IMPL_API void ImGui_ImplWin32_Shutdown(); 19 | IMGUI_IMPL_API void ImGui_ImplWin32_NewFrame(); 20 | 21 | // Win32 message handler your application need to call. 22 | // - Intentionally commented out in a '#if 0' block to avoid dragging dependencies on from this helper. 23 | // - You should COPY the line below into your .cpp code to forward declare the function and then you can call it. 24 | #if 0 25 | extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); 26 | #endif 27 | 28 | // DPI-related helpers (optional) 29 | // - Use to enable DPI awareness without having to create an application manifest. 30 | // - Your own app may already do this via a manifest or explicit calls. This is mostly useful for our examples/ apps. 31 | // - In theory we could call simple functions from Windows SDK such as SetProcessDPIAware(), SetProcessDpiAwareness(), etc. 32 | // but most of the functions provided by Microsoft require Windows 8.1/10+ SDK at compile time and Windows 8/10+ at runtime, 33 | // neither we want to require the user to have. So we dynamically select and load those functions to avoid dependencies. 34 | IMGUI_IMPL_API void ImGui_ImplWin32_EnableDpiAwareness(); 35 | IMGUI_IMPL_API float ImGui_ImplWin32_GetDpiScaleForHwnd(void* hwnd); // HWND hwnd 36 | IMGUI_IMPL_API float ImGui_ImplWin32_GetDpiScaleForMonitor(void* monitor); // HMONITOR monitor 37 | 38 | // Transparency related helpers (optional) [experimental] 39 | // - Use to enable alpha compositing transparency with the desktop. 40 | // - Use together with e.g. clearing your framebuffer with zero-alpha. 41 | IMGUI_IMPL_API void ImGui_ImplWin32_EnableAlphaCompositing(void* hwnd); // HWND hwnd 42 | -------------------------------------------------------------------------------- /Source/Minhook/hde32.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Hacker Disassembler Engine 32 3 | * Copyright (c) 2006-2009, Vyacheslav Patkov. 4 | * All rights reserved. 5 | * 6 | * hde32.h: C/C++ header file 7 | * 8 | */ 9 | 10 | #ifndef _HDE32_H_ 11 | #define _HDE32_H_ 12 | 13 | /* stdint.h - C99 standard header 14 | * http://en.wikipedia.org/wiki/stdint.h 15 | * 16 | * if your compiler doesn't contain "stdint.h" header (for 17 | * example, Microsoft Visual C++), you can download file: 18 | * http://www.azillionmonkeys.com/qed/pstdint.h 19 | * and change next line to: 20 | * #include "pstdint.h" 21 | */ 22 | #include "pstdint.h" 23 | 24 | #define F_MODRM 0x00000001 25 | #define F_SIB 0x00000002 26 | #define F_IMM8 0x00000004 27 | #define F_IMM16 0x00000008 28 | #define F_IMM32 0x00000010 29 | #define F_DISP8 0x00000020 30 | #define F_DISP16 0x00000040 31 | #define F_DISP32 0x00000080 32 | #define F_RELATIVE 0x00000100 33 | #define F_2IMM16 0x00000800 34 | #define F_ERROR 0x00001000 35 | #define F_ERROR_OPCODE 0x00002000 36 | #define F_ERROR_LENGTH 0x00004000 37 | #define F_ERROR_LOCK 0x00008000 38 | #define F_ERROR_OPERAND 0x00010000 39 | #define F_PREFIX_REPNZ 0x01000000 40 | #define F_PREFIX_REPX 0x02000000 41 | #define F_PREFIX_REP 0x03000000 42 | #define F_PREFIX_66 0x04000000 43 | #define F_PREFIX_67 0x08000000 44 | #define F_PREFIX_LOCK 0x10000000 45 | #define F_PREFIX_SEG 0x20000000 46 | #define F_PREFIX_ANY 0x3f000000 47 | 48 | #define PREFIX_SEGMENT_CS 0x2e 49 | #define PREFIX_SEGMENT_SS 0x36 50 | #define PREFIX_SEGMENT_DS 0x3e 51 | #define PREFIX_SEGMENT_ES 0x26 52 | #define PREFIX_SEGMENT_FS 0x64 53 | #define PREFIX_SEGMENT_GS 0x65 54 | #define PREFIX_LOCK 0xf0 55 | #define PREFIX_REPNZ 0xf2 56 | #define PREFIX_REPX 0xf3 57 | #define PREFIX_OPERAND_SIZE 0x66 58 | #define PREFIX_ADDRESS_SIZE 0x67 59 | 60 | #pragma pack(push,1) 61 | 62 | typedef struct { 63 | uint8_t len; 64 | uint8_t p_rep; 65 | uint8_t p_lock; 66 | uint8_t p_seg; 67 | uint8_t p_66; 68 | uint8_t p_67; 69 | uint8_t opcode; 70 | uint8_t opcode2; 71 | uint8_t modrm; 72 | uint8_t modrm_mod; 73 | uint8_t modrm_reg; 74 | uint8_t modrm_rm; 75 | uint8_t sib; 76 | uint8_t sib_scale; 77 | uint8_t sib_index; 78 | uint8_t sib_base; 79 | union { 80 | uint8_t imm8; 81 | uint16_t imm16; 82 | uint32_t imm32; 83 | } imm; 84 | union { 85 | uint8_t disp8; 86 | uint16_t disp16; 87 | uint32_t disp32; 88 | } disp; 89 | uint32_t flags; 90 | } hde32s; 91 | 92 | #pragma pack(pop) 93 | 94 | #ifdef __cplusplus 95 | extern "C" { 96 | #endif 97 | 98 | /* __cdecl */ 99 | unsigned int hde32_disasm(const void *code, hde32s *hs); 100 | 101 | #ifdef __cplusplus 102 | } 103 | #endif 104 | 105 | #endif /* _HDE32_H_ */ 106 | -------------------------------------------------------------------------------- /Source/Minhook/hde64.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Hacker Disassembler Engine 64 3 | * Copyright (c) 2008-2009, Vyacheslav Patkov. 4 | * All rights reserved. 5 | * 6 | * hde64.h: C/C++ header file 7 | * 8 | */ 9 | 10 | #ifndef _HDE64_H_ 11 | #define _HDE64_H_ 12 | 13 | /* stdint.h - C99 standard header 14 | * http://en.wikipedia.org/wiki/stdint.h 15 | * 16 | * if your compiler doesn't contain "stdint.h" header (for 17 | * example, Microsoft Visual C++), you can download file: 18 | * http://www.azillionmonkeys.com/qed/pstdint.h 19 | * and change next line to: 20 | * #include "pstdint.h" 21 | */ 22 | #include "pstdint.h" 23 | 24 | #define F_MODRM 0x00000001 25 | #define F_SIB 0x00000002 26 | #define F_IMM8 0x00000004 27 | #define F_IMM16 0x00000008 28 | #define F_IMM32 0x00000010 29 | #define F_IMM64 0x00000020 30 | #define F_DISP8 0x00000040 31 | #define F_DISP16 0x00000080 32 | #define F_DISP32 0x00000100 33 | #define F_RELATIVE 0x00000200 34 | #define F_ERROR 0x00001000 35 | #define F_ERROR_OPCODE 0x00002000 36 | #define F_ERROR_LENGTH 0x00004000 37 | #define F_ERROR_LOCK 0x00008000 38 | #define F_ERROR_OPERAND 0x00010000 39 | #define F_PREFIX_REPNZ 0x01000000 40 | #define F_PREFIX_REPX 0x02000000 41 | #define F_PREFIX_REP 0x03000000 42 | #define F_PREFIX_66 0x04000000 43 | #define F_PREFIX_67 0x08000000 44 | #define F_PREFIX_LOCK 0x10000000 45 | #define F_PREFIX_SEG 0x20000000 46 | #define F_PREFIX_REX 0x40000000 47 | #define F_PREFIX_ANY 0x7f000000 48 | 49 | #define PREFIX_SEGMENT_CS 0x2e 50 | #define PREFIX_SEGMENT_SS 0x36 51 | #define PREFIX_SEGMENT_DS 0x3e 52 | #define PREFIX_SEGMENT_ES 0x26 53 | #define PREFIX_SEGMENT_FS 0x64 54 | #define PREFIX_SEGMENT_GS 0x65 55 | #define PREFIX_LOCK 0xf0 56 | #define PREFIX_REPNZ 0xf2 57 | #define PREFIX_REPX 0xf3 58 | #define PREFIX_OPERAND_SIZE 0x66 59 | #define PREFIX_ADDRESS_SIZE 0x67 60 | 61 | #pragma pack(push,1) 62 | 63 | typedef struct { 64 | uint8_t len; 65 | uint8_t p_rep; 66 | uint8_t p_lock; 67 | uint8_t p_seg; 68 | uint8_t p_66; 69 | uint8_t p_67; 70 | uint8_t rex; 71 | uint8_t rex_w; 72 | uint8_t rex_r; 73 | uint8_t rex_x; 74 | uint8_t rex_b; 75 | uint8_t opcode; 76 | uint8_t opcode2; 77 | uint8_t modrm; 78 | uint8_t modrm_mod; 79 | uint8_t modrm_reg; 80 | uint8_t modrm_rm; 81 | uint8_t sib; 82 | uint8_t sib_scale; 83 | uint8_t sib_index; 84 | uint8_t sib_base; 85 | union { 86 | uint8_t imm8; 87 | uint16_t imm16; 88 | uint32_t imm32; 89 | uint64_t imm64; 90 | } imm; 91 | union { 92 | uint8_t disp8; 93 | uint16_t disp16; 94 | uint32_t disp32; 95 | } disp; 96 | uint32_t flags; 97 | } hde64s; 98 | 99 | #pragma pack(pop) 100 | 101 | #ifdef __cplusplus 102 | extern "C" { 103 | #endif 104 | 105 | /* __cdecl */ 106 | unsigned int hde64_disasm(const void *code, hde64s *hs); 107 | 108 | #ifdef __cplusplus 109 | } 110 | #endif 111 | 112 | #endif /* _HDE64_H_ */ 113 | -------------------------------------------------------------------------------- /Source/Minhook/table32.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Hacker Disassembler Engine 32 C 3 | * Copyright (c) 2008-2009, Vyacheslav Patkov. 4 | * All rights reserved. 5 | * 6 | */ 7 | 8 | #define C_NONE 0x00 9 | #define C_MODRM 0x01 10 | #define C_IMM8 0x02 11 | #define C_IMM16 0x04 12 | #define C_IMM_P66 0x10 13 | #define C_REL8 0x20 14 | #define C_REL32 0x40 15 | #define C_GROUP 0x80 16 | #define C_ERROR 0xff 17 | 18 | #define PRE_ANY 0x00 19 | #define PRE_NONE 0x01 20 | #define PRE_F2 0x02 21 | #define PRE_F3 0x04 22 | #define PRE_66 0x08 23 | #define PRE_67 0x10 24 | #define PRE_LOCK 0x20 25 | #define PRE_SEG 0x40 26 | #define PRE_ALL 0xff 27 | 28 | #define DELTA_OPCODES 0x4a 29 | #define DELTA_FPU_REG 0xf1 30 | #define DELTA_FPU_MODRM 0xf8 31 | #define DELTA_PREFIXES 0x130 32 | #define DELTA_OP_LOCK_OK 0x1a1 33 | #define DELTA_OP2_LOCK_OK 0x1b9 34 | #define DELTA_OP_ONLY_MEM 0x1cb 35 | #define DELTA_OP2_ONLY_MEM 0x1da 36 | 37 | unsigned char hde32_table[] = { 38 | 0xa3,0xa8,0xa3,0xa8,0xa3,0xa8,0xa3,0xa8,0xa3,0xa8,0xa3,0xa8,0xa3,0xa8,0xa3, 39 | 0xa8,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xac,0xaa,0xb2,0xaa,0x9f,0x9f, 40 | 0x9f,0x9f,0xb5,0xa3,0xa3,0xa4,0xaa,0xaa,0xba,0xaa,0x96,0xaa,0xa8,0xaa,0xc3, 41 | 0xc3,0x96,0x96,0xb7,0xae,0xd6,0xbd,0xa3,0xc5,0xa3,0xa3,0x9f,0xc3,0x9c,0xaa, 42 | 0xaa,0xac,0xaa,0xbf,0x03,0x7f,0x11,0x7f,0x01,0x7f,0x01,0x3f,0x01,0x01,0x90, 43 | 0x82,0x7d,0x97,0x59,0x59,0x59,0x59,0x59,0x7f,0x59,0x59,0x60,0x7d,0x7f,0x7f, 44 | 0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x9a,0x88,0x7d, 45 | 0x59,0x50,0x50,0x50,0x50,0x59,0x59,0x59,0x59,0x61,0x94,0x61,0x9e,0x59,0x59, 46 | 0x85,0x59,0x92,0xa3,0x60,0x60,0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59, 47 | 0x59,0x59,0x9f,0x01,0x03,0x01,0x04,0x03,0xd5,0x03,0xcc,0x01,0xbc,0x03,0xf0, 48 | 0x10,0x10,0x10,0x10,0x50,0x50,0x50,0x50,0x14,0x20,0x20,0x20,0x20,0x01,0x01, 49 | 0x01,0x01,0xc4,0x02,0x10,0x00,0x00,0x00,0x00,0x01,0x01,0xc0,0xc2,0x10,0x11, 50 | 0x02,0x03,0x11,0x03,0x03,0x04,0x00,0x00,0x14,0x00,0x02,0x00,0x00,0xc6,0xc8, 51 | 0x02,0x02,0x02,0x02,0x00,0x00,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0xff,0xca, 52 | 0x01,0x01,0x01,0x00,0x06,0x00,0x04,0x00,0xc0,0xc2,0x01,0x01,0x03,0x01,0xff, 53 | 0xff,0x01,0x00,0x03,0xc4,0xc4,0xc6,0x03,0x01,0x01,0x01,0xff,0x03,0x03,0x03, 54 | 0xc8,0x40,0x00,0x0a,0x00,0x04,0x00,0x00,0x00,0x00,0x7f,0x00,0x33,0x01,0x00, 55 | 0x00,0x00,0x00,0x00,0x00,0xff,0xbf,0xff,0xff,0x00,0x00,0x00,0x00,0x07,0x00, 56 | 0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 57 | 0x00,0xff,0xff,0x00,0x00,0x00,0xbf,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 58 | 0x7f,0x00,0x00,0xff,0x4a,0x4a,0x4a,0x4a,0x4b,0x52,0x4a,0x4a,0x4a,0x4a,0x4f, 59 | 0x4c,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x55,0x45,0x40,0x4a,0x4a,0x4a, 60 | 0x45,0x59,0x4d,0x46,0x4a,0x5d,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a, 61 | 0x4a,0x4a,0x4a,0x4a,0x4a,0x61,0x63,0x67,0x4e,0x4a,0x4a,0x6b,0x6d,0x4a,0x4a, 62 | 0x45,0x6d,0x4a,0x4a,0x44,0x45,0x4a,0x4a,0x00,0x00,0x00,0x02,0x0d,0x06,0x06, 63 | 0x06,0x06,0x0e,0x00,0x00,0x00,0x00,0x06,0x06,0x06,0x00,0x06,0x06,0x02,0x06, 64 | 0x00,0x0a,0x0a,0x07,0x07,0x06,0x02,0x05,0x05,0x02,0x02,0x00,0x00,0x04,0x04, 65 | 0x04,0x04,0x00,0x00,0x00,0x0e,0x05,0x06,0x06,0x06,0x01,0x06,0x00,0x00,0x08, 66 | 0x00,0x10,0x00,0x18,0x00,0x20,0x00,0x28,0x00,0x30,0x00,0x80,0x01,0x82,0x01, 67 | 0x86,0x00,0xf6,0xcf,0xfe,0x3f,0xab,0x00,0xb0,0x00,0xb1,0x00,0xb3,0x00,0xba, 68 | 0xf8,0xbb,0x00,0xc0,0x00,0xc1,0x00,0xc7,0xbf,0x62,0xff,0x00,0x8d,0xff,0x00, 69 | 0xc4,0xff,0x00,0xc5,0xff,0x00,0xff,0xff,0xeb,0x01,0xff,0x0e,0x12,0x08,0x00, 70 | 0x13,0x09,0x00,0x16,0x08,0x00,0x17,0x09,0x00,0x2b,0x09,0x00,0xae,0xff,0x07, 71 | 0xb2,0xff,0x00,0xb4,0xff,0x00,0xb5,0xff,0x00,0xc3,0x01,0x00,0xc7,0xff,0xbf, 72 | 0xe7,0x08,0x00,0xf0,0x02,0x00 73 | }; 74 | -------------------------------------------------------------------------------- /Source/Minhook/table64.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Hacker Disassembler Engine 64 C 3 | * Copyright (c) 2008-2009, Vyacheslav Patkov. 4 | * All rights reserved. 5 | * 6 | */ 7 | 8 | #define C_NONE 0x00 9 | #define C_MODRM 0x01 10 | #define C_IMM8 0x02 11 | #define C_IMM16 0x04 12 | #define C_IMM_P66 0x10 13 | #define C_REL8 0x20 14 | #define C_REL32 0x40 15 | #define C_GROUP 0x80 16 | #define C_ERROR 0xff 17 | 18 | #define PRE_ANY 0x00 19 | #define PRE_NONE 0x01 20 | #define PRE_F2 0x02 21 | #define PRE_F3 0x04 22 | #define PRE_66 0x08 23 | #define PRE_67 0x10 24 | #define PRE_LOCK 0x20 25 | #define PRE_SEG 0x40 26 | #define PRE_ALL 0xff 27 | 28 | #define DELTA_OPCODES 0x4a 29 | #define DELTA_FPU_REG 0xfd 30 | #define DELTA_FPU_MODRM 0x104 31 | #define DELTA_PREFIXES 0x13c 32 | #define DELTA_OP_LOCK_OK 0x1ae 33 | #define DELTA_OP2_LOCK_OK 0x1c6 34 | #define DELTA_OP_ONLY_MEM 0x1d8 35 | #define DELTA_OP2_ONLY_MEM 0x1e7 36 | 37 | unsigned char hde64_table[] = { 38 | 0xa5,0xaa,0xa5,0xb8,0xa5,0xaa,0xa5,0xaa,0xa5,0xb8,0xa5,0xb8,0xa5,0xb8,0xa5, 39 | 0xb8,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xac,0xc0,0xcc,0xc0,0xa1,0xa1, 40 | 0xa1,0xa1,0xb1,0xa5,0xa5,0xa6,0xc0,0xc0,0xd7,0xda,0xe0,0xc0,0xe4,0xc0,0xea, 41 | 0xea,0xe0,0xe0,0x98,0xc8,0xee,0xf1,0xa5,0xd3,0xa5,0xa5,0xa1,0xea,0x9e,0xc0, 42 | 0xc0,0xc2,0xc0,0xe6,0x03,0x7f,0x11,0x7f,0x01,0x7f,0x01,0x3f,0x01,0x01,0xab, 43 | 0x8b,0x90,0x64,0x5b,0x5b,0x5b,0x5b,0x5b,0x92,0x5b,0x5b,0x76,0x90,0x92,0x92, 44 | 0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x6a,0x73,0x90, 45 | 0x5b,0x52,0x52,0x52,0x52,0x5b,0x5b,0x5b,0x5b,0x77,0x7c,0x77,0x85,0x5b,0x5b, 46 | 0x70,0x5b,0x7a,0xaf,0x76,0x76,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b, 47 | 0x5b,0x5b,0x86,0x01,0x03,0x01,0x04,0x03,0xd5,0x03,0xd5,0x03,0xcc,0x01,0xbc, 48 | 0x03,0xf0,0x03,0x03,0x04,0x00,0x50,0x50,0x50,0x50,0xff,0x20,0x20,0x20,0x20, 49 | 0x01,0x01,0x01,0x01,0xc4,0x02,0x10,0xff,0xff,0xff,0x01,0x00,0x03,0x11,0xff, 50 | 0x03,0xc4,0xc6,0xc8,0x02,0x10,0x00,0xff,0xcc,0x01,0x01,0x01,0x00,0x00,0x00, 51 | 0x00,0x01,0x01,0x03,0x01,0xff,0xff,0xc0,0xc2,0x10,0x11,0x02,0x03,0x01,0x01, 52 | 0x01,0xff,0xff,0xff,0x00,0x00,0x00,0xff,0x00,0x00,0xff,0xff,0xff,0xff,0x10, 53 | 0x10,0x10,0x10,0x02,0x10,0x00,0x00,0xc6,0xc8,0x02,0x02,0x02,0x02,0x06,0x00, 54 | 0x04,0x00,0x02,0xff,0x00,0xc0,0xc2,0x01,0x01,0x03,0x03,0x03,0xca,0x40,0x00, 55 | 0x0a,0x00,0x04,0x00,0x00,0x00,0x00,0x7f,0x00,0x33,0x01,0x00,0x00,0x00,0x00, 56 | 0x00,0x00,0xff,0xbf,0xff,0xff,0x00,0x00,0x00,0x00,0x07,0x00,0x00,0xff,0x00, 57 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff, 58 | 0x00,0x00,0x00,0xbf,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7f,0x00,0x00, 59 | 0xff,0x40,0x40,0x40,0x40,0x41,0x49,0x40,0x40,0x40,0x40,0x4c,0x42,0x40,0x40, 60 | 0x40,0x40,0x40,0x40,0x40,0x40,0x4f,0x44,0x53,0x40,0x40,0x40,0x44,0x57,0x43, 61 | 0x5c,0x40,0x60,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40, 62 | 0x40,0x40,0x64,0x66,0x6e,0x6b,0x40,0x40,0x6a,0x46,0x40,0x40,0x44,0x46,0x40, 63 | 0x40,0x5b,0x44,0x40,0x40,0x00,0x00,0x00,0x00,0x06,0x06,0x06,0x06,0x01,0x06, 64 | 0x06,0x02,0x06,0x06,0x00,0x06,0x00,0x0a,0x0a,0x00,0x00,0x00,0x02,0x07,0x07, 65 | 0x06,0x02,0x0d,0x06,0x06,0x06,0x0e,0x05,0x05,0x02,0x02,0x00,0x00,0x04,0x04, 66 | 0x04,0x04,0x05,0x06,0x06,0x06,0x00,0x00,0x00,0x0e,0x00,0x00,0x08,0x00,0x10, 67 | 0x00,0x18,0x00,0x20,0x00,0x28,0x00,0x30,0x00,0x80,0x01,0x82,0x01,0x86,0x00, 68 | 0xf6,0xcf,0xfe,0x3f,0xab,0x00,0xb0,0x00,0xb1,0x00,0xb3,0x00,0xba,0xf8,0xbb, 69 | 0x00,0xc0,0x00,0xc1,0x00,0xc7,0xbf,0x62,0xff,0x00,0x8d,0xff,0x00,0xc4,0xff, 70 | 0x00,0xc5,0xff,0x00,0xff,0xff,0xeb,0x01,0xff,0x0e,0x12,0x08,0x00,0x13,0x09, 71 | 0x00,0x16,0x08,0x00,0x17,0x09,0x00,0x2b,0x09,0x00,0xae,0xff,0x07,0xb2,0xff, 72 | 0x00,0xb4,0xff,0x00,0xb5,0xff,0x00,0xc3,0x01,0x00,0xc7,0xff,0xbf,0xe7,0x08, 73 | 0x00,0xf0,0x02,0x00 74 | }; 75 | -------------------------------------------------------------------------------- /Source/Minhook/trampoline.h: -------------------------------------------------------------------------------- 1 | /* 2 | * MinHook - The Minimalistic API Hooking Library for x64/x86 3 | * Copyright (C) 2009-2017 Tsuda Kageyu. 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright 11 | * notice, this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 18 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 19 | * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 20 | * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 21 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 22 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 23 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 24 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 25 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 26 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | #pragma once 30 | 31 | #pragma pack(push, 1) 32 | 33 | // Structs for writing x86/x64 instructions. 34 | 35 | // 8-bit relative jump. 36 | typedef struct _JMP_REL_SHORT 37 | { 38 | UINT8 opcode; // EB xx: JMP +2+xx 39 | UINT8 operand; 40 | } JMP_REL_SHORT, *PJMP_REL_SHORT; 41 | 42 | // 32-bit direct relative jump/call. 43 | typedef struct _JMP_REL 44 | { 45 | UINT8 opcode; // E9/E8 xxxxxxxx: JMP/CALL +5+xxxxxxxx 46 | UINT32 operand; // Relative destination address 47 | } JMP_REL, *PJMP_REL, CALL_REL; 48 | 49 | // 64-bit indirect absolute jump. 50 | typedef struct _JMP_ABS 51 | { 52 | UINT8 opcode0; // FF25 00000000: JMP [+6] 53 | UINT8 opcode1; 54 | UINT32 dummy; 55 | UINT64 address; // Absolute destination address 56 | } JMP_ABS, *PJMP_ABS; 57 | 58 | // 64-bit indirect absolute call. 59 | typedef struct _CALL_ABS 60 | { 61 | UINT8 opcode0; // FF15 00000002: CALL [+6] 62 | UINT8 opcode1; 63 | UINT32 dummy0; 64 | UINT8 dummy1; // EB 08: JMP +10 65 | UINT8 dummy2; 66 | UINT64 address; // Absolute destination address 67 | } CALL_ABS; 68 | 69 | // 32-bit direct relative conditional jumps. 70 | typedef struct _JCC_REL 71 | { 72 | UINT8 opcode0; // 0F8* xxxxxxxx: J** +6+xxxxxxxx 73 | UINT8 opcode1; 74 | UINT32 operand; // Relative destination address 75 | } JCC_REL; 76 | 77 | // 64bit indirect absolute conditional jumps that x64 lacks. 78 | typedef struct _JCC_ABS 79 | { 80 | UINT8 opcode; // 7* 0E: J** +16 81 | UINT8 dummy0; 82 | UINT8 dummy1; // FF25 00000000: JMP [+6] 83 | UINT8 dummy2; 84 | UINT32 dummy3; 85 | UINT64 address; // Absolute destination address 86 | } JCC_ABS; 87 | 88 | #pragma pack(pop) 89 | 90 | typedef struct _TRAMPOLINE 91 | { 92 | LPVOID pTarget; // [In] Address of the target function. 93 | LPVOID pDetour; // [In] Address of the detour function. 94 | LPVOID pTrampoline; // [In] Buffer address for the trampoline and relay function. 95 | 96 | #if defined(_M_X64) || defined(__x86_64__) 97 | LPVOID pRelay; // [Out] Address of the relay function. 98 | #endif 99 | BOOL patchAbove; // [Out] Should use the hot patch area? 100 | UINT nIP; // [Out] Number of the instruction boundaries. 101 | UINT8 oldIPs[8]; // [Out] Instruction boundaries of the target function. 102 | UINT8 newIPs[8]; // [Out] Instruction boundaries of the trampoline function. 103 | } TRAMPOLINE, *PTRAMPOLINE; 104 | 105 | BOOL CreateTrampolineFunction(PTRAMPOLINE ct); 106 | -------------------------------------------------------------------------------- /Source/Common.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define _CRT_SECURE_NO_WARNINGS 4 | #define NOMINMAX 5 | #define WIN32_LEAN_AND_MEAN 6 | #define _WIN32_WINNT _WIN32_WINNT_WIN7 7 | 8 | #define BOSS_CHR_ARRAY_LEN 3 9 | #define ENTITY_CHR_ARRAY_LEN 8 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #include 19 | #include 20 | #pragma comment(lib, "d3d12.lib") 21 | 22 | #include 23 | 24 | #include 25 | #include 26 | #include 27 | 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | #include 44 | #include 45 | #include 46 | #include 47 | #include 48 | #include 49 | #include 50 | #include 51 | #include 52 | #include 53 | #include 54 | #include 55 | #include 56 | #include 57 | #include 58 | #include 59 | #include 60 | #include 61 | 62 | #include "Minhook/MinHook.h" 63 | #include "ImGui/imgui.h" 64 | #define IMGUI_DEFINE_MATH_OPERATORS 65 | #include "ImGui/imgui_internal.h" 66 | #include "ImGui/imgui_impl_dx12.h" 67 | #include "ImGui/imgui_impl_win32.h" 68 | #include 69 | 70 | using IndexType = uint32_t; 71 | 72 | extern void Nop(BYTE* dst, unsigned int size); 73 | extern void Patch(BYTE* dst, BYTE* src, unsigned int size); 74 | 75 | template 76 | constexpr auto make_array(T value) -> std::array 77 | { 78 | std::array a{}; 79 | for (auto& x : a) 80 | x = value; 81 | return a; 82 | } 83 | 84 | template 85 | std::map make_map() { 86 | std::map m; 87 | for (size_t i = 0; i < static_cast(EnumType::MAX); ++i) 88 | m[static_cast(i)] = Value(); 89 | return m; 90 | } 91 | 92 | inline std::vector splitString(const std::string& inputString, const std::string& delimiter) 93 | { 94 | std::regex re(delimiter); 95 | std::sregex_token_iterator first{ inputString.begin(), inputString.end(), re, -1 }, last;//the '-1' is what makes the regex split (-1 := what was not matched) 96 | return { first, last }; 97 | } 98 | 99 | namespace std 100 | { 101 | inline std::string to_string(const ImVec2& vec2) 102 | { 103 | return "(" + std::to_string(vec2.x) + ", " + std::to_string(vec2.y) + ")"; 104 | } 105 | 106 | inline std::string to_string(const ImVec4& vec4) 107 | { 108 | return "(" + std::to_string(vec4.x) + ", " + std::to_string(vec4.y) + ", " + std::to_string(vec4.z) + ", " + std::to_string(vec4.w) + ")"; 109 | } 110 | 111 | template 112 | inline std::string to_string(const std::pair pair) 113 | { 114 | return "{ " + std::to_string(pair.first) + ", " + std::to_string(pair.second) + " }"; 115 | } 116 | }; 117 | 118 | namespace ER { 119 | 120 | using namespace std::chrono_literals; 121 | using namespace DirectX; 122 | using namespace DirectX::PackedVector; 123 | namespace fs = std::filesystem; 124 | 125 | template inline T RPM(uint64_t lpBaseAddress) 126 | { 127 | __try 128 | { 129 | T A{}; 130 | A = *(T*)(lpBaseAddress); 131 | return A; 132 | } 133 | __except (EXCEPTION_EXECUTE_HANDLER) 134 | { 135 | return T{}; 136 | } 137 | } 138 | 139 | template inline void WPM(uint64_t lpBaseAddress, T Val) 140 | { 141 | __try 142 | { 143 | *(T*)(lpBaseAddress) = Val; 144 | return; 145 | } 146 | __except (EXCEPTION_EXECUTE_HANDLER) 147 | { 148 | } 149 | } 150 | 151 | static uint64_t dwGameBase = (uint64_t)GetModuleHandle(NULL); 152 | } -------------------------------------------------------------------------------- /Source/Main/Hooking.cpp: -------------------------------------------------------------------------------- 1 | #include "Hooking.hpp" 2 | #include "Logger.hpp" 3 | #include "D3DRenderer.hpp" 4 | #include "PostureBarUI.hpp" 5 | #include "Memory.hpp" 6 | 7 | namespace ER 8 | { 9 | Hooking::Hooking() 10 | { 11 | MH_Initialize(); 12 | } 13 | 14 | Hooking::~Hooking() 15 | { 16 | MH_RemoveHook(MH_ALL_HOOKS); 17 | } 18 | 19 | void Hooking::Hook() 20 | { 21 | #ifdef DEBUGLOG 22 | try 23 | { 24 | #endif // DEBUGLOG 25 | Logger::log("Start Hooking"); 26 | 27 | Logger::log("Hooking Elden Ring methods"); 28 | 29 | Logger::log("Looking for worldChr signature"); 30 | if (worldChrSignature = Signature("48 8B 05 ? ? ? ? 48 85 C0 74 0F 48 39 88").Scan().Add(3).Rip().As(); !worldChrSignature) 31 | Logger::log("Failed to find worldChr signature", LogLevel::Error); 32 | 33 | Logger::log("Looking for CSFeMan signature"); 34 | if (CSFeManSignature = Signature("48 8B 0D ? ? ? ? 8B DA 48 85 C9 75 ? 48 8D 0D ? ? ? ? E8 ? ? ? ? 4C 8B C8 4C 8D 05 ? ? ? ? BA B4 00 00 00 48 8D 0D ? ? ? ? E8 ? ? ? ? 48 8B 0D ? ? ? ? 8B D3 E8 ? ? ? ? 48 8B D8").Scan().Add(3).Rip().As(); !CSFeManSignature) 35 | Logger::log("Failed to find worldChr signature", LogLevel::Error); 36 | 37 | Logger::log("Looking for isLoading signature"); 38 | if (isLoading = Signature("10 75 ? ? ? ? 00 00 20 75 ? ? ? ? 00 00 00 00 00 00 00 00 00 00 E4 01 00 80 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ? ? ? 00 00 00 00 00 00 00 00 00 00 00 00 00 19 0E 19 B4 00 00 00 00 00").Scan().Add(81).As(); !isLoading) 39 | Logger::log("Failed to find isLoading signature", LogLevel::Error); 40 | 41 | Logger::log("Looking for menuState signature"); 42 | if (menuState1 = Signature("20 9E ? ? ? ? 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 40 CB ? ? ? ? 00 00 18 CB ? ? ? ? 00 00 00 00 00 00 00 00 00 00 97 01 00 80").Scan().Add(1244).As(); !menuState1) 43 | Logger::log("Failed to find menuState signature", LogLevel::Error); 44 | if (menuState2 = Signature("20 9E ? ? ? ? 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 40 CB ? ? ? ? 00 00 18 CB ? ? ? ? 00 00 00 00 00 00 00 00 00 00 97 01 00 80").Scan().Add(1248).As(); !menuState2) 45 | Logger::log("Failed to find menuState signature", LogLevel::Error); 46 | if (menuState3 = Signature("20 9E ? ? ? ? 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 40 CB ? ? ? ? 00 00 18 CB ? ? ? ? 00 00 00 00 00 00 00 00 00 00 97 01 00 80").Scan().Add(1252).As(); !menuState3) 47 | Logger::log("Failed to find menuState signature", LogLevel::Error); 48 | 49 | Logger::log("Looking for GetChrInsFromHandleFunc signature"); 50 | if (GetChrInsFromHandleFunc = (GetChrInsFromHandle)Signature("48 83 EC 28 E8 17 FF FF FF 48 85 C0 74 08 48 8B 00 48 83 C4 28 C3").Scan().As(); !GetChrInsFromHandleFunc) 51 | Logger::log("Failed to find GetChrInsFromHandleFunc signature", LogLevel::Error); 52 | 53 | Logger::log("Looking for UpdateUIBarStructsFunc signature"); 54 | if (UpdateUIBarStructsFunc = (UpdateUIBarStructs)Signature("40 55 56 57 41 54 41 55 41 56 41 57 48 83 EC 60 48 C7 44 24 30 FE FF FF FF 48 89 9C 24 B0 00 00 00 48 8B 05 ? ? ? ? 48 33 C4 48 89 44 24 58 48").Scan().As(); !UpdateUIBarStructsFunc) 55 | Logger::log("Failed to find UpdateUIBarStructsFunc signature", LogLevel::Error); 56 | 57 | Logger::log("Hooking UpdateUIBarStructsFunc"); 58 | if (MH_CreateHook(UpdateUIBarStructsFunc, &g_postureUI->updateUIBarStructs, (void**)&g_postureUI->updateUIBarStructsOriginal) != MH_STATUS::MH_OK) 59 | Logger::log("Failed to hook UpdateUIBarStructsFunc", LogLevel::Error); 60 | 61 | Logger::log("Hooking DirectX methods"); 62 | 63 | g_D3DRenderer->Hook(); 64 | 65 | MH_EnableHook(MH_ALL_HOOKS); 66 | #ifdef DEBUGLOG 67 | } 68 | catch (const std::exception& e) 69 | { 70 | Logger::useLogger = true; 71 | Logger::log(e.what(), LogLevel::Error); 72 | throw; 73 | } 74 | catch (...) 75 | { 76 | Logger::useLogger = true; 77 | Logger::log("Unknown exception during Hooking::Hook", LogLevel::Error); 78 | throw; 79 | } 80 | #endif // DEBUGLOG 81 | } 82 | 83 | void Hooking::Unhook() 84 | { 85 | g_D3DRenderer->Unhook(); 86 | MH_RemoveHook(MH_ALL_HOOKS); 87 | } 88 | } -------------------------------------------------------------------------------- /Source/Main/D3DRenderer.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "../Common.hpp" 3 | 4 | namespace ER 5 | { 6 | struct TextureFileData 7 | { 8 | unsigned char* data = nullptr; 9 | int width = 0; 10 | int height = 0; 11 | 12 | static inline std::string bossBarFile = "PostureBarResources\\BossBar.png"; 13 | static inline std::string bossBorderFile = "PostureBarResources\\BossBarBorder.png"; 14 | static inline std::string entityBarFile = "PostureBarResources\\EntityBar.png"; 15 | static inline std::string entityBorderFile = "PostureBarResources\\EntityBarBorder.png"; 16 | }; 17 | 18 | struct D3D12TextureData 19 | { 20 | D3D12_CPU_DESCRIPTOR_HANDLE cpuHandle{}; 21 | D3D12_GPU_DESCRIPTOR_HANDLE gpuHandle{}; 22 | ID3D12Resource* dx12Resource = nullptr; 23 | int width = 0; 24 | int height = 0; 25 | }; 26 | 27 | class D3DRenderer 28 | { 29 | class ProgramData 30 | { 31 | public: 32 | explicit ProgramData(); 33 | ~ProgramData() noexcept = default; 34 | ProgramData(ProgramData const&) = delete; 35 | ProgramData(ProgramData&&) = delete; 36 | ProgramData& operator=(ProgramData const&) = delete; 37 | ProgramData& operator=(ProgramData&&) = delete; 38 | 39 | // Dx & ImGui 40 | int m_GamePid{}; 41 | HANDLE m_GameHandle{}; 42 | HWND m_GameWindow{}; 43 | int m_GameWidth; 44 | int m_GameHeight; 45 | LPCSTR m_GameTitle; 46 | LPCSTR m_ClassName; 47 | LPCSTR m_GamePath; 48 | uintptr_t m_ModuleBase; // OBTAIN MODULE BASE 49 | }; 50 | 51 | typedef HRESULT(APIENTRY* Present12) (IDXGISwapChain* pSwapChain, UINT SyncInterval, UINT Flags); 52 | Present12 oPresent = NULL; 53 | 54 | typedef void(APIENTRY* ExecuteCommandLists)(ID3D12CommandQueue* queue, UINT NumCommandLists, ID3D12CommandList* ppCommandLists); 55 | ExecuteCommandLists oExecuteCommandLists = NULL; 56 | 57 | typedef HRESULT(APIENTRY* ResizeTarget)(IDXGISwapChain* _this, const DXGI_MODE_DESC* pNewTargetParameters); 58 | ResizeTarget oResizeTarget = NULL; 59 | 60 | public: 61 | explicit D3DRenderer() 62 | : programData(std::make_unique()) {}; 63 | ~D3DRenderer() noexcept; 64 | D3DRenderer(D3DRenderer const&) = delete; 65 | D3DRenderer(D3DRenderer&&) = delete; 66 | D3DRenderer& operator=(D3DRenderer const&) = delete; 67 | D3DRenderer& operator=(D3DRenderer&&) = delete; 68 | 69 | bool m_Init = false; 70 | 71 | 72 | void Overlay(IDXGISwapChain* pSwapChain); 73 | 74 | static HRESULT APIENTRY HookPresent(IDXGISwapChain* pSwapChain, UINT SyncInterval, UINT Flags); 75 | static void HookExecuteCommandLists(ID3D12CommandQueue* queue, UINT NumCommandLists, ID3D12CommandList* ppCommandLists); 76 | static HRESULT APIENTRY HookResizeTarget(IDXGISwapChain* _this, const DXGI_MODE_DESC* pNewTargetParameters); 77 | void ResetRenderState(IDXGISwapChain3* swapChain = nullptr); 78 | 79 | bool loadTextureFileData(const std::string& filename, TextureFileData* textureFileData); 80 | void loadBarTextures(); 81 | 82 | void EnableDebugLayer(); 83 | bool InitHook(); 84 | bool Hook(); 85 | void Unhook(); 86 | 87 | bool InitWindow(); 88 | bool DeleteWindow(); 89 | 90 | bool CreateHook(uint16_t Index, void** Original, void* Function); 91 | void DisableHook(uint16_t Index); 92 | void DisableAll(); 93 | 94 | static LRESULT WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); 95 | 96 | uint64_t m_OldWndProc{}; 97 | 98 | private: 99 | 100 | std::unique_ptr programData; 101 | 102 | WNDCLASSEX WindowClass{}; 103 | HWND WindowHwnd{}; 104 | 105 | IDXGISwapChain3* m_Swapchain{}; 106 | ID3D12Device* m_Device{}; 107 | 108 | TextureFileData entityBarFileData; 109 | TextureFileData entityBarBorderFileData; 110 | TextureFileData bossBarFileData; 111 | TextureFileData bossBarBorderFileData; 112 | bool textureFileDataLoaded = false; 113 | 114 | ID3D12DescriptorHeap* m_srvDescriptorHeap{}; 115 | ID3D12DescriptorHeap* m_rtvDescriptorHeap{}; 116 | ID3D12CommandAllocator** m_CommandAllocators; 117 | ID3D12GraphicsCommandList* m_CommandList{}; 118 | ID3D12CommandQueue* m_CommandQueue{}; 119 | ID3D12Resource** m_BackBuffers; 120 | std::vector m_RenderTargets; 121 | 122 | uint64_t m_BuffersCounts = -1; 123 | // 1 + number_of_textures * 2(cpu + gpu handles) 124 | static inline const int srvDescriptorsNumWithTextures = 9; 125 | }; 126 | 127 | inline std::unique_ptr g_D3DRenderer; 128 | } -------------------------------------------------------------------------------- /Source/Main/Hooking.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "../Common.hpp" 3 | 4 | namespace ER 5 | { 6 | namespace GameData 7 | { 8 | struct BossHpBar { 9 | int displayId = -1; 10 | uint32_t pad0x4 = 0; 11 | unsigned long long bossHandle = 0; 12 | int currentDisplayDamage = 0; 13 | int unk0x14 = 0; 14 | bool isHit = 0; 15 | uint8_t pad0x19[0x3] = {}; 16 | float displayTime = 0; 17 | }; 18 | 19 | static_assert(sizeof(BossHpBar) == 0x20); 20 | 21 | struct EntityHpBar { 22 | unsigned long long entityHandle = 0; 23 | float unk[2]; 24 | float screenPosX; 25 | float screenPosY; 26 | float mod; 27 | uint32_t unk3; 28 | char unkChar1; 29 | char unkChar2; 30 | uint16_t unkShort3; 31 | int currentDisplayDamage = -1; 32 | int previousHp = 0; 33 | float timeDisplayed; 34 | float totalTimeDisplayed; 35 | bool isVisible; 36 | char unk2[11]; 37 | }; 38 | 39 | static_assert(sizeof(EntityHpBar) == 0x40); 40 | 41 | struct CSFeManImp 42 | { 43 | uint8_t undefined[0x59F0]; 44 | EntityHpBar entityHpBars[ENTITY_CHR_ARRAY_LEN]; 45 | BossHpBar bossHpBars[BOSS_CHR_ARRAY_LEN]; 46 | }; 47 | 48 | struct StatModule 49 | { 50 | uint8_t undefined[0x138]; 51 | int health; 52 | int healthMax; 53 | int healthBase; 54 | int unk; 55 | int focus; 56 | int focusMax; 57 | int focusBase; 58 | int stamina; 59 | int staminaMax; 60 | int staminaBase; 61 | }; 62 | 63 | struct Module0x18 64 | { 65 | uint8_t undefined[0x20]; 66 | int currentAnimation; 67 | }; 68 | 69 | struct ResistanceModule 70 | { 71 | uint8_t undefined[0x10]; 72 | int poison; 73 | int rot; 74 | int bleed; 75 | int blight; 76 | int frost; 77 | int sleep; 78 | int madness; 79 | 80 | int poisonMax; 81 | int rotMax; 82 | int bleedMax; 83 | int blightMax; 84 | int frostMax; 85 | int sleepMax; 86 | int madnessMax; 87 | 88 | float poisonMod; 89 | float rotMod; 90 | float bleedMod; 91 | float blightMod; 92 | float frostMod; 93 | float sleepMod; 94 | float madnessMod; 95 | 96 | float poisonMul; 97 | float rotMul; 98 | float bleedMul; 99 | float blightMul; 100 | float frostMul; 101 | float sleepMul; 102 | float madnessMul; 103 | }; 104 | 105 | 106 | struct StaggerModule 107 | { 108 | //uint8_t undefined1; 109 | //bool useStagger; 110 | //uint8_t undefined2[0xE]; 111 | uint8_t undefined2[0x10]; 112 | float stagger; 113 | float staggerMax; 114 | uint8_t undefined3[0x4]; 115 | float resetTimer; 116 | }; 117 | 118 | struct PhysicsModule 119 | { 120 | char pad_0000[84]; 121 | float Azimuth; 122 | char pad_0058[24]; 123 | float worldPosX; 124 | float worldPosY; 125 | float worldPosZ; 126 | }; 127 | 128 | struct ChrModuleBag 129 | { 130 | StatModule* statModule; 131 | uint8_t undefined1[0x10]; 132 | Module0x18* animModule; 133 | ResistanceModule* resistanceModule; 134 | uint8_t undefined2[0x18]; 135 | StaggerModule* staggerModule; 136 | uint8_t undefined3[0x20]; 137 | PhysicsModule* physicsModule; 138 | }; 139 | 140 | struct ChrIns 141 | { 142 | uint8_t undefined[0x8]; 143 | unsigned long long handle; 144 | uint8_t undefined2[0x50]; 145 | int npcParam; 146 | int modelNumber; 147 | int chrType; 148 | uint8_t teamType; 149 | uint8_t undefined3[0x123]; 150 | ChrModuleBag* chrModulelBag; 151 | uint8_t undefined4[0x508]; 152 | unsigned long long targetHandle; 153 | }; 154 | 155 | struct WorldChrMan { 156 | char unk[0x10EF8]; 157 | ChrIns** playerArray[0x4]; 158 | }; 159 | } 160 | 161 | class Hooking 162 | { 163 | public: 164 | explicit Hooking(); 165 | ~Hooking() noexcept; 166 | Hooking(Hooking const&) = delete; 167 | Hooking(Hooking&&) = delete; 168 | Hooking& operator=(Hooking const&) = delete; 169 | Hooking& operator=(Hooking&&) = delete; 170 | 171 | void Hook(); 172 | void Unhook(); 173 | 174 | // Game found Signatures 175 | uintptr_t worldChrSignature{}; 176 | uintptr_t CSFeManSignature{}; 177 | uintptr_t isLoading{}; 178 | uintptr_t menuState1{}; 179 | uintptr_t menuState2{}; 180 | uintptr_t menuState3{}; 181 | 182 | // Static in game functions 183 | typedef GameData::ChrIns* (*GetChrInsFromHandle)(GameData::WorldChrMan* worldChrMan, uint64_t* chrInsHandlePtr); 184 | GetChrInsFromHandle GetChrInsFromHandleFunc{}; 185 | 186 | typedef void (*UpdateUIBarStructs)(uintptr_t, uintptr_t); 187 | UpdateUIBarStructs UpdateUIBarStructsFunc{}; 188 | }; 189 | 190 | inline std::unique_ptr g_Hooking; 191 | } 192 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # EldenRing-PostureBarMod 2 | A posture bar mode for the Elden Ring game, creates new user interface elements above the head of the enemy, which indicate how much posture damage the enemy remains. 3 | 4 | ## THIS IS EARLY VERSION - EXPECT SOME BUGS 5 | 6 | ## General 7 | The mod was created with the intention of presenting enemy posture as a UI element inside the game, as for me it increases enjoyment of the combat system when I can have such information visible and be capable of reacting more consciously to actual enemy state rather than try to blindly assume it or spend thousands of years learning by feeling the enemy's current posture damage state. As I play-tested it, I also quickly learned the value of playing aggressively and using more posture damage techniques and weapons, which I believe ultimately made me better at playing it. 8 | 9 | ### The mod does not have ambitions to change any game data; it is only used to display it, so do not request such changes. Modularity is a nice thing; if you wish to change how the game behaves in terms of stagger values, etc., you can do that in another mod and still use it just to display data. 10 | 11 | ### The mod should be mostly compatible with other mods as it does not modify data. It may only cause issues when using a mod that heavily changes HUD elements. 12 | 13 | ![posture_bar_texture](https://user-images.githubusercontent.com/23028397/236690919-6ed2b655-0eb2-41f1-aa92-8a6eb3204207.PNG) 14 | 15 | ## Instalation 16 | 17 | First you will have to remember that you cannot play on official servers using this (or in fact any) mod. 18 | To install mod you will have to follow this stes: 19 | * Download Elden Mod Loader from https://www.nexusmods.com/eldenring/mods/117, and extract it's content where game .exe is 20 | * Download this mod .zip file from [Nexus Mods](https://www.nexusmods.com/eldenring/mods/3405) or [Github](https://github.com/Mordrog/EldenRing-PostureBarMod/releases/) and extract it's contet inside "mods" folder where game .exe is, on steam path will be something like that "steamapps\common\ELDEN RING\Game\mods" 21 | * **DISABLE ANTI CHEAT** - you can for instance use https://www.nexusmods.com/eldenring/mods/90/%EF%BB%BF 22 | * Run game 23 | 24 | ## Possible issues 25 | 26 | There are some issues you might encounter after installing the mod. First, you have to remember that if the game was updated not too long ago, the last version of the mod might not have been deployed yet, and it just won't work. If for any reason the game crashes for you, especially while starting the game, you can try turning logs on inside the PostureBarModConfig.ini file and reporting the issue on the git or Nexus mod pages. 27 | 28 | Here are some common issues you might encounter: 29 | 30 | * ***Boss bar is not well aligned with health bar*** - it might happen especially when using other mods that changes those positions, like Reforged. You will have to set new value inside .ini file for first FirstBossScreen. You can also use special tool that can help you find proper offset inside game, by setting OffsetTest to true inside .ini file 31 | * ***Bars in general are not aligned*** - most likely mod auto position or / and auto scaling has failed, in that case you might have to set them yourself, to figure out how those parameters should be set you can set OffsetTest to true and start game, from there you will have some options to change offsets and save them inside .ini file. In extreme case where nothing seems to work, you should report this issue on git or nexus mod page. 32 | * ***Bars are aligned when static, but they shake a lot when moving*** - most likely it happens due to position fixing algorithm, you can turn it off inside .ini file, but then bars will always slightly drag after health bars OR you can try to adjust modifier values PositionFixingMultiplier inside .ini file or inside game by setting OffsetTest to true inside .ini file (remember to save those values). If posture bars tend to drag behind health bar then PositionFixingMultiplier should be bigger, if they tend to go ahead of health bar, then PositionFixingMultiplier should be lower 33 | * ***Mod does not work / Mod crashes on start*** - report issue on git or nexus mod page, best to include logs, you can generate those by setting Log to true inside .ini file 34 | 35 | ## Credits 36 | **[Nordgaren](https://github.com/Nordgaren)** author of [ERD-Tools](https://github.com/Nordgaren/Erd-Tools)\ 37 | **[ImAxel0](https://github.com/ImAxel0)** author of [Elden-Menu](https://github.com/ImAxel0/Elden-Menu)\ 38 | **[NightFyre](https://github.com/NightFyre)** author of [ELDENRING-INTERNAL](https://github.com/NightFyre/ELDENRING-INTERNAL) that I based a lot of my source code from\ 39 | **Ingart** for being passionate tester the best brother 40 | 41 | ## Changelog 42 | 43 | ### Beta 0.6.0 44 | * Added optional enemy status bars (thanks to [lrbender01](https://github.com/lrbender01)) 45 | * Fix for D3DRenderer not checking for D3D12_COMMAND_LIST_TYPE_DIRECT when executing command list (thanks to [mahkoh](https://github.com/mahkoh)) 46 | * Added debug logs for posture bar data 47 | 48 | ### Beta 0.5.0 49 | * Updated AOB and functionality of checking for open menus after patch 1.10.1 50 | * Fixes for logging for missing AOB (thanks to [viniciuslrangel](https://github.com/viniciuslrangel)) 51 | * Made open menus functionality disabled by default 52 | * Added new options for menu styles: Set from which alignment shall bar fill, Set if bar should be filled or emptied when enemy stagger level drops, Set if fill texture should be cliped or resized 53 | * Added Sekiro style bars (with configs setup for them) 54 | 55 | ### Beta 0.4.2 56 | * Updated AOB and functionality of checking for open menus 57 | 58 | ### Beta 0.4.0 59 | * Updated way mod is checking for open menus, also added option to disable this feature if it proofs not working for whatever reason 60 | * Changed way mod is looking for resources etc. to assume .dll relative path 61 | * Added stagger bar for player (not functional by default, usable only with mods that make use of player stagger values) 62 | 63 | ### Beta 0.3.0 64 | * Added textures for UI bars 65 | * Moved bars default offset position under HP bar to match new texture bars 66 | * Added option to change color of bars 67 | * Mostly fixed issues with bars appearing during menu 68 | * Fixed issue where bar would persist until game reset or next boss fight 69 | * Fixed issue with debug version, as it seemed to not be working at all for most people 70 | 71 | ### Beta 0.2.0 72 | * Increased amount of logging + made special debug version with even more logging 73 | * Made finding of Elden Ring window use Unicode format (to hopefuly fix treadmark symbol issue) 74 | * Added option to turn of drawing of bars for entity or bosses in configs 75 | 76 | ### Beta 0.1.0 77 | 78 | * Initial version, should display simple UI bars 79 | -------------------------------------------------------------------------------- /PostureBarMod.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 10 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 11 | 12 | 13 | {3a2ea10f-0798-4673-ab4f-776b4f3e7e24} 14 | 15 | 16 | {d261536c-7c67-4544-9143-cdd34dfa3e7d} 17 | 18 | 19 | {9119d17f-c20f-416e-adcf-f6edaa0112fb} 20 | 21 | 22 | {a1106453-cf7f-4c30-8971-5e4c020e7a7a} 23 | 24 | 25 | {83867c03-cce2-4b57-8328-3f4a226f5db8} 26 | 27 | 28 | {4abda075-d16b-4ff5-9c0b-0f1f2310e07e} 29 | 30 | 31 | 32 | 33 | Source Files 34 | 35 | 36 | Source Files 37 | 38 | 39 | Source Files 40 | 41 | 42 | Source Files\ImGui 43 | 44 | 45 | Source Files\ImGui 46 | 47 | 48 | Source Files\ImGui 49 | 50 | 51 | Source Files\ImGui 52 | 53 | 54 | Source Files\ImGui 55 | 56 | 57 | Source Files\ImGui 58 | 59 | 60 | Source Files\ImGui 61 | 62 | 63 | Source Files\MinHook 64 | 65 | 66 | Source Files\MinHook 67 | 68 | 69 | Source Files\MinHook 70 | 71 | 72 | Source Files\MinHook 73 | 74 | 75 | Source Files\MinHook 76 | 77 | 78 | Source Files\Main 79 | 80 | 81 | Source Files\Main 82 | 83 | 84 | Source Files\Main 85 | 86 | 87 | Source Files\Main 88 | 89 | 90 | 91 | 92 | Source Files 93 | 94 | 95 | Source Files 96 | 97 | 98 | Source Files\ImGui 99 | 100 | 101 | Source Files\ImGui 102 | 103 | 104 | Source Files\ImGui 105 | 106 | 107 | Source Files\ImGui 108 | 109 | 110 | Source Files\ImGui 111 | 112 | 113 | Source Files\ImGui 114 | 115 | 116 | Source Files\ImGui 117 | 118 | 119 | Source Files\ImGui 120 | 121 | 122 | Source Files\MinHook 123 | 124 | 125 | Source Files\MinHook 126 | 127 | 128 | Source Files\MinHook 129 | 130 | 131 | Source Files\MinHook 132 | 133 | 134 | Source Files\MinHook 135 | 136 | 137 | Source Files\MinHook 138 | 139 | 140 | Source Files\MinHook 141 | 142 | 143 | Source Files\MinHook 144 | 145 | 146 | Source Files\Main 147 | 148 | 149 | Source Files\Main 150 | 151 | 152 | Source Files\Main 153 | 154 | 155 | Source Files\Main 156 | 157 | 158 | Source Files\Main 159 | 160 | 161 | Source Files\Ini 162 | 163 | 164 | Source Files\Stb 165 | 166 | 167 | Source Files\DirectX 168 | 169 | 170 | -------------------------------------------------------------------------------- /Source/Minhook/MinHook.h: -------------------------------------------------------------------------------- 1 | /* 2 | * MinHook - The Minimalistic API Hooking Library for x64/x86 3 | * Copyright (C) 2009-2017 Tsuda Kageyu. 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright 11 | * notice, this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 18 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 19 | * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 20 | * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 21 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 22 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 23 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 24 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 25 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 26 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | #pragma once 30 | 31 | #if !(defined _M_IX86) && !(defined _M_X64) && !(defined __i386__) && !(defined __x86_64__) 32 | #error MinHook supports only x86 and x64 systems. 33 | #endif 34 | 35 | #include 36 | 37 | // MinHook Error Codes. 38 | typedef enum MH_STATUS 39 | { 40 | // Unknown error. Should not be returned. 41 | MH_UNKNOWN = -1, 42 | 43 | // Successful. 44 | MH_OK = 0, 45 | 46 | // MinHook is already initialized. 47 | MH_ERROR_ALREADY_INITIALIZED, 48 | 49 | // MinHook is not initialized yet, or already uninitialized. 50 | MH_ERROR_NOT_INITIALIZED, 51 | 52 | // The hook for the specified target function is already created. 53 | MH_ERROR_ALREADY_CREATED, 54 | 55 | // The hook for the specified target function is not created yet. 56 | MH_ERROR_NOT_CREATED, 57 | 58 | // The hook for the specified target function is already enabled. 59 | MH_ERROR_ENABLED, 60 | 61 | // The hook for the specified target function is not enabled yet, or already 62 | // disabled. 63 | MH_ERROR_DISABLED, 64 | 65 | // The specified pointer is invalid. It points the address of non-allocated 66 | // and/or non-executable region. 67 | MH_ERROR_NOT_EXECUTABLE, 68 | 69 | // The specified target function cannot be hooked. 70 | MH_ERROR_UNSUPPORTED_FUNCTION, 71 | 72 | // Failed to allocate memory. 73 | MH_ERROR_MEMORY_ALLOC, 74 | 75 | // Failed to change the memory protection. 76 | MH_ERROR_MEMORY_PROTECT, 77 | 78 | // The specified module is not loaded. 79 | MH_ERROR_MODULE_NOT_FOUND, 80 | 81 | // The specified function is not found. 82 | MH_ERROR_FUNCTION_NOT_FOUND 83 | } 84 | MH_STATUS; 85 | 86 | // Can be passed as a parameter to MH_EnableHook, MH_DisableHook, 87 | // MH_QueueEnableHook or MH_QueueDisableHook. 88 | #define MH_ALL_HOOKS NULL 89 | 90 | #ifdef __cplusplus 91 | extern "C" { 92 | #endif 93 | 94 | // Initialize the MinHook library. You must call this function EXACTLY ONCE 95 | // at the beginning of your program. 96 | MH_STATUS WINAPI MH_Initialize(VOID); 97 | 98 | // Uninitialize the MinHook library. You must call this function EXACTLY 99 | // ONCE at the end of your program. 100 | MH_STATUS WINAPI MH_Uninitialize(VOID); 101 | 102 | // Creates a Hook for the specified target function, in disabled state. 103 | // Parameters: 104 | // pTarget [in] A pointer to the target function, which will be 105 | // overridden by the detour function. 106 | // pDetour [in] A pointer to the detour function, which will override 107 | // the target function. 108 | // ppOriginal [out] A pointer to the trampoline function, which will be 109 | // used to call the original target function. 110 | // This parameter can be NULL. 111 | MH_STATUS WINAPI MH_CreateHook(LPVOID pTarget, LPVOID pDetour, LPVOID *ppOriginal); 112 | 113 | // Creates a Hook for the specified API function, in disabled state. 114 | // Parameters: 115 | // pszModule [in] A pointer to the loaded module name which contains the 116 | // target function. 117 | // pszTarget [in] A pointer to the target function name, which will be 118 | // overridden by the detour function. 119 | // pDetour [in] A pointer to the detour function, which will override 120 | // the target function. 121 | // ppOriginal [out] A pointer to the trampoline function, which will be 122 | // used to call the original target function. 123 | // This parameter can be NULL. 124 | MH_STATUS WINAPI MH_CreateHookApi( 125 | LPCWSTR pszModule, LPCSTR pszProcName, LPVOID pDetour, LPVOID *ppOriginal); 126 | 127 | // Creates a Hook for the specified API function, in disabled state. 128 | // Parameters: 129 | // pszModule [in] A pointer to the loaded module name which contains the 130 | // target function. 131 | // pszTarget [in] A pointer to the target function name, which will be 132 | // overridden by the detour function. 133 | // pDetour [in] A pointer to the detour function, which will override 134 | // the target function. 135 | // ppOriginal [out] A pointer to the trampoline function, which will be 136 | // used to call the original target function. 137 | // This parameter can be NULL. 138 | // ppTarget [out] A pointer to the target function, which will be used 139 | // with other functions. 140 | // This parameter can be NULL. 141 | MH_STATUS WINAPI MH_CreateHookApiEx( 142 | LPCWSTR pszModule, LPCSTR pszProcName, LPVOID pDetour, LPVOID *ppOriginal, LPVOID *ppTarget); 143 | 144 | // Removes an already created hook. 145 | // Parameters: 146 | // pTarget [in] A pointer to the target function. 147 | MH_STATUS WINAPI MH_RemoveHook(LPVOID pTarget); 148 | 149 | // Enables an already created hook. 150 | // Parameters: 151 | // pTarget [in] A pointer to the target function. 152 | // If this parameter is MH_ALL_HOOKS, all created hooks are 153 | // enabled in one go. 154 | MH_STATUS WINAPI MH_EnableHook(LPVOID pTarget); 155 | 156 | // Disables an already created hook. 157 | // Parameters: 158 | // pTarget [in] A pointer to the target function. 159 | // If this parameter is MH_ALL_HOOKS, all created hooks are 160 | // disabled in one go. 161 | MH_STATUS WINAPI MH_DisableHook(LPVOID pTarget); 162 | 163 | // Queues to enable an already created hook. 164 | // Parameters: 165 | // pTarget [in] A pointer to the target function. 166 | // If this parameter is MH_ALL_HOOKS, all created hooks are 167 | // queued to be enabled. 168 | MH_STATUS WINAPI MH_QueueEnableHook(LPVOID pTarget); 169 | 170 | // Queues to disable an already created hook. 171 | // Parameters: 172 | // pTarget [in] A pointer to the target function. 173 | // If this parameter is MH_ALL_HOOKS, all created hooks are 174 | // queued to be disabled. 175 | MH_STATUS WINAPI MH_QueueDisableHook(LPVOID pTarget); 176 | 177 | // Applies all queued changes in one go. 178 | MH_STATUS WINAPI MH_ApplyQueued(VOID); 179 | 180 | // Translates the MH_STATUS to its name as a string. 181 | const char * WINAPI MH_StatusToString(MH_STATUS status); 182 | 183 | BOOL WINAPI MH_IsHookEnabled(LPVOID pTarget); 184 | 185 | #ifdef __cplusplus 186 | } 187 | #endif 188 | 189 | -------------------------------------------------------------------------------- /Config/PostureBarModConfig.ini: -------------------------------------------------------------------------------- 1 | ; NOTICE: InGameScreenCoord are NOT your shown resolution, but a resolution that game uses internally to later scale it to actual shown viewport, you should most likely not change this 2 | ; ScreenPosition - set viewport position for generated bars, should be set to match top-left corner, AutoPositionSetup shall try to set it autamatically 3 | ; GameToScreenScaling - scaling between game to screen viewports, should be set to match scale between InGameScreenCoord and shown screen , AutoGameToScreenScaling shall try to set it autamatically 4 | ; AutoPositionSetup and AutoGameToScreenScaling - by default you want it to work by itself, if it won't work, try to activate OffsetTest to dedect values by yourself and turn off those options accordingly 5 | ; NOTICE: When AutoPositionSetup and AutoGameToScreenScaling are true, values below are ignored 6 | [General] 7 | InGameScreenCoordWidth = 1920.0 8 | InGameScreenCoordHeight = 1080.0 9 | ScreenPositionX = 0.0 10 | ScreenPositionY = 0.0 11 | GameToScreenScaling = 1.0 12 | AutoPositionSetup = true 13 | AutoGameToScreenScaling = true 14 | 15 | ; UseTextres - should mod load textures instead of using basic shapes style bars 16 | ; FillFile - texture for bar fill, one that indicate current status of stagger/stamina 17 | ; BorderFile - texture for bar border, one that serves as background for fill texture 18 | ; FillOffset - offsets for fill texture, where it should be placed relative to border texture, currently you have to figure this numbers out 19 | [Textures] 20 | UseTextures = true 21 | BossBarFillFile = PostureBarResources\\BossBar.png 22 | BossBarBorderFile = PostureBarResources\\BossBarBorder.png 23 | EntityBarFillFile = PostureBarResources\\EntityBar.png 24 | EntityBarBorderFile = PostureBarResources\\EntityBarBorder.png 25 | BossFillTopLeftOffsetX = 34.0 26 | BossFillTopLeftOffsetY = 5.0 27 | BossFillBotRightOffsetX = -6.0 28 | BossFillBotRightOffsetY = -1.0 29 | EntityFillTopLeftOffsetX = 8.0 30 | EntityFillTopLeftOffsetY = 6.5 31 | EntityFillBotRightOffsetX = -8.0 32 | EntityFillBotRightOffsetY = -6.0 33 | 34 | ; FillAlignment - from where should bar extend (0 - left, 1 - center, 2 - right) 35 | ; FillType - how should bar fill work (0 - full to empty, 1 - empty to full) 36 | ; FillResizeType - how should fill bar be resized due to stagger changes (0 - rect clip, 1 - scale) 37 | ; Color of bars (red, green, blue, alpha), from 0 to 255. If you are using textures, it will only affect Fill Textures. Max/Min indicate color gradient between low and high amount of stagger/stamina 38 | [Style] 39 | FillAlignment = 0 40 | FillType = 0 41 | FillResizeType = 0 42 | StaggerColorMax = 255, 255, 0, 255 43 | StaggerColorMin = 255, 255, 0, 255 44 | StaminaColorMax = 63, 200, 87, 255 45 | StaminaColorMin = 63, 200, 87, 255 46 | 47 | ; Status bars 48 | PoisonColorMax = 100, 250, 85, 255 49 | PoisonColorMin = 100, 250, 85, 255 50 | RotColorMax = 255, 127, 0, 255 51 | RotColorMin = 255, 127, 0, 255 52 | BleedColorMax = 255, 0, 0, 255 53 | BleedColorMin = 255, 0, 0, 255 54 | BlightColorMax = 255, 255, 0, 255 55 | BlightColorMin = 255, 255, 0, 255 56 | FrostColorMax = 40, 225, 255, 255 57 | FrostColorMin = 40, 225, 255, 255 58 | SleepColorMax = 240, 0, 200, 255 59 | SleepColorMin = 240, 0, 200, 255 60 | MadnessColorMax = 255, 255, 0, 255 61 | MadnessColorMin = 255, 255, 0, 255 62 | 63 | ; DrawBars - should boss posture bars be drawn 64 | ; UseStaminaForNPC - changes posture bar to stamina bar for all human characters, while they have stagger values, they do not use them at all 65 | ; BarWidth and BarHeight - uses in game scaling (1920x1080) 66 | ; ResetStaggerTotalTime - when enemy crosses 0 value of posture damage, they automatically restore it to full while getting posture broken, this value sets arbitrary time for animation of bar to load itself to full 67 | ; FirstBossScreen - sets coords (in game scaling) of first boss posture bar, right now it is found by setting value til you are satisfied with it's location, use OffsetTest to help you with finding that offset 68 | ; NextBossBarDiffScreenY - seets coords (in game scaling) for next boss bar Y wise (multiple boss fights) 69 | ; NOTICE: Some mods can change this offset (like reforged), which means you will have to find it by yourself. Some popular offsets: Default (x: 957.5 y: 876), Reforged (x: 957.5 y: 958) 70 | [Boss Posture Bar] 71 | DrawBars = true 72 | UseStaminaForNPC = true 73 | BarWidth = 1020.0 74 | BarHeight = 16.0 75 | ResetStaggerTotalTime = 2.0 76 | FirstBossScreenX = 957.5 77 | FirstBossScreenY = 876.0 78 | NextBossBarDiffScreenY = 55.0 79 | 80 | ; Status bars 81 | ; DrawXBar - should X status bar be drawn 82 | ; StatusBarWidth and StatsBarHeight - uses in game scaling (1920x1080) 83 | ; FirstStatusBarDiffScreenY - sets coords (in game scaling) of first status bar Y wise after posture bar 84 | ; NextStatusBarDiffScreenY - seets coords (in game scaling) for next status bar Y wise 85 | DrawPoisonBar = false 86 | DrawRotBar = false 87 | DrawBleedBar = false 88 | DrawBlightBar = false 89 | DrawFrostBar = false 90 | DrawSleepBar = false 91 | DrawMadnessBar = false 92 | StatusBarWidth = 1020.0 93 | StatusBarHeight = 16.0 94 | FirstStatusBarDiffScreenY = 16.0 95 | NextStatusBarDiffScreenY = 16.0 96 | 97 | ; DrawBars - should entity posture bars be drawn 98 | ; UseStaminaForNPC - changes posture bar to stamina bar for all human characters, while they have stagger values, they do not use them at all 99 | ; BarWidth and BarHeight - uses in game scaling (1920x1080) 100 | ; ResetStaggerTotalTime - when enemy crosses 0 value of posture damage, they automatically restore it to full while getting posture broken, this value sets arbitrary time for animation of bar to load itself to full 101 | ; OffsetScreen - sets the offset (in game scaling) from enemy health bar position, you can use OffsetTest to adjust this position by yourself 102 | ; ScreenThreshold - thresholds of where should posture bar stop in game viewport (in game scaling), most likely you should not change it 103 | [Entity Posture Bar] 104 | DrawBars = true 105 | UseStaminaForNPC = true 106 | BarWidth = 143.0 107 | BarHeight = 14.0 108 | ResetStaggerTotalTime = 2.0 109 | OffsetScreenX = -1.5 110 | OffsetScreenY = 1.5 111 | LeftScreenThreshold = 130.0 112 | RightScreenThreshold = 1790.0 113 | TopScreenThreshold = 175.0 114 | BottomScreenThreshold = 990.0 115 | 116 | ; Status bars 117 | ; DrawXBar - should X status bar be drawn 118 | ; StatusBarWidth and StatsBarHeight - uses in game scaling (1920x1080) 119 | ; FirstStatusBarDiffScreenY - sets coords (in game scaling) of first status bar Y wise after posture bar 120 | ; NextStatusBarDiffScreenY - seets coords (in game scaling) for next status bar Y wise 121 | DrawPoisonBar = false 122 | DrawRotBar = false 123 | DrawBleedBar = false 124 | DrawBlightBar = false 125 | DrawFrostBar = false 126 | DrawSleepBar = false 127 | DrawMadnessBar = false 128 | StatusBarWidth = 143.0 129 | StatusBarHeight = 14.0 130 | FirstStatusBarDiffScreenY = 14.0 131 | NextStatusBarDiffScreenY = 14.0 132 | 133 | ; ADVANCED: 134 | ; UsePositionFixing - position fixing alhorithm, looks for previous positions to allign posture bar better with health bar, by defalut they are slightly out of sync 135 | ; PositionFixingMultiplier - multiplier by which bar movement velocity is affected, if bar is dragging behind hp bar then you have to increase this value, if it is going ahead of hp bar, then you have to decrese it 136 | UsePositionFixing = true 137 | PositionFixingMultiplierX = 10.0 138 | PositionFixingMultiplierY = 10.0 139 | 140 | ; New stuff that I am not sure if they will work fine 141 | ; HideBarsOnMenu - whenever mod should check for open menus, might not work perfectly all the time, but should be good enaugh 142 | [Experimental] 143 | HideBarsOnMenu = false 144 | ; Player stagger bar - by default it will do nothing, as game does not use player stagger, use it only with mods that intends on making use of player stagger 145 | ; I have not made any attempts at making it look/position good right now, reffer to mod author that intends on using such bar 146 | DrawBar = false 147 | BarWidth = 214.5f 148 | BarHeight = 21.0f 149 | ResetStaggerTotalTime = 2.0f 150 | ScreenX = 963.0f 151 | ScreenY = 50.0f 152 | 153 | ; Log - log to file in mods/PostureModLog.txt 154 | ; OffsetTest - creats in game menu for adjusting screen and bar offsets. Use "Insert" key to save currently modified offset to .ini. Use "Page up/down" keys to change which offset you want to modify. Use "Arrows" keys to modify values. 155 | [Debug] 156 | Log = false 157 | OffsetTest = false 158 | -------------------------------------------------------------------------------- /Config/PostureBarModConfig - SekiroBar.ini: -------------------------------------------------------------------------------- 1 | ; IMPORTANT: if you want to use sekiro options, they still have to be in PostureBarModConfig.ini file, so either copy paste those options there or change this file name 2 | 3 | ; NOTICE: InGameScreenCoord are NOT resolution, but a system that game uses itself to later scale it to actual shown viewport, you should most likely not change those 4 | ; ScreenPosition - set viewport position for generated bars, should be set to match top-left corner, AutoPositionSetup shall try to set it autamatically 5 | ; GameToScreenScaling - scaling between game to screen viewports, should be set to match scale between InGameScreenCoord and shown screen , AutoGameToScreenScaling shall try to set it autamatically 6 | ; AutoPositionSetup and AutoGameToScreenScaling - by default you want it to work by itself, if it won't work, try to activate OffsetTest to dedect values by yourself and turn off those options accordingly 7 | ; NOTICE: When AutoPositionSetup and AutoGameToScreenScaling are true, values below are ignored 8 | [General] 9 | InGameScreenCoordWidth = 1920.0 10 | InGameScreenCoordHeight = 1080.0 11 | ScreenPositionX = 0.0 12 | ScreenPositionY = 0.0 13 | GameToScreenScaling = 1.0 14 | AutoPositionSetup = true 15 | AutoGameToScreenScaling = true 16 | 17 | ; UseTextres - whenever mod should load textures instead of using UI style bars 18 | ; FillFile - texture for bar fill, one that indicate current status of stagger/stamina 19 | ; BorderFile - texture for bar border, one that serves as background for fill texture 20 | ; FillOffset - offsets for fill texture, where it should be placed relative to border texture, currently you have to figure this numbers out 21 | [Textures] 22 | UseTextures = true 23 | BossBarFillFile = PostureBarResources\\SekiroBar.png 24 | BossBarBorderFile = PostureBarResources\\SekiroBarBorder.png 25 | EntityBarFillFile = PostureBarResources\\SekiroBar.png 26 | EntityBarBorderFile = PostureBarResources\\SekiroEntityBarBorder.png 27 | BossFillTopLeftOffsetX = 0.0 28 | BossFillTopLeftOffsetY = 0.0 29 | BossFillBotRightOffsetX = 0.0 30 | BossFillBotRightOffsetY = 0.0 31 | EntityFillTopLeftOffsetX = 0.0 32 | EntityFillTopLeftOffsetY = 0.0 33 | EntityFillBotRightOffsetX = 0.0 34 | EntityFillBotRightOffsetY = 0.0 35 | 36 | ; FillAlignment - from where should bar extend (0 - left, 1 - center, 2 - right) 37 | ; FillType - how should bar fill work (0 - full to empty, 1 - empty to full) 38 | ; FillResizeType - how should fill bar be resized due to stagger changes (0 - clip, 1 - scale) 39 | ; Color of bars (red, green, blue, alpha), from 0 to 255. If you are using textures, it will only affect Fill Textures. Max/Min indicate color gradient between low and high amount of stagger/stamina 40 | [Style] 41 | FillAlignment = 1 42 | FillType = 1 43 | FillResizeType = 1 44 | StaggerColorMax = 255, 0, 0, 255 45 | StaggerColorMin = 255, 255, 0, 255 46 | StaminaColorMax = 63, 200, 87, 255 47 | StaminaColorMin = 63, 200, 87, 255 48 | 49 | ; Status bars 50 | PoisonColorMax = 100, 250, 85, 255 51 | PoisonColorMin = 100, 250, 85, 255 52 | RotColorMax = 255, 127, 0, 255 53 | RotColorMin = 255, 127, 0, 255 54 | BleedColorMax = 255, 0, 0, 255 55 | BleedColorMin = 255, 0, 0, 255 56 | BlightColorMax = 255, 255, 0, 255 57 | BlightColorMin = 255, 255, 0, 255 58 | FrostColorMax = 40, 225, 255, 255 59 | FrostColorMin = 40, 225, 255, 255 60 | SleepColorMax = 240, 0, 200, 255 61 | SleepColorMin = 240, 0, 200, 255 62 | MadnessColorMax = 255, 255, 0, 255 63 | MadnessColorMin = 255, 255, 0, 255 64 | 65 | ; DrawBars - whenever boss posture bars should be even drawn 66 | ; UseStaminaForNPC - changes posture bar to stamina bar for all human characters, while they have stagger values, they do not use them at all 67 | ; BarWidth and BarHeight - uses in game scaling (1920x1080) 68 | ; ResetStaggerTotalTime - when enemy crosses 0 value of posture damage, they automatically restore it to full while getting posture broken, this value sets arbitrary time for animation of bar to load itself to full 69 | ; FirstBossScreen - sets coords (in game scaling) of first boss posture bar, right now it is found by setting value til you are satisfied with it's location, use OffsetTest to help you with finding that offset 70 | ; NextBossBarDiffScreenY - seets coords (in game scaling) for next boss bar Y wise (multiple boss fights) 71 | ; NOTICE: Some mods can change this offset (like reforged), which means you will have to find it by yourself. Some popular offsets: Default (x: 957.5 y: 876), Reforged (x: 957.5 y: 958) 72 | [Boss Posture Bar] 73 | DrawBars = true 74 | UseStaminaForNPC = true 75 | BarWidth = 1020.0 76 | BarHeight = 12.0 77 | ResetStaggerTotalTime = 2.0 78 | FirstBossScreenX = 957.5 79 | FirstBossScreenY = 962.0 80 | NextBossBarDiffScreenY = 55.0 81 | 82 | ; Status bars 83 | ; DrawXBar - should X status bar be drawn 84 | ; StatusBarWidth and StatsBarHeight - uses in game scaling (1920x1080) 85 | ; FirstStatusBarDiffScreenY - sets coords (in game scaling) of first status bar Y wise after posture bar 86 | ; NextStatusBarDiffScreenY - seets coords (in game scaling) for next status bar Y wise 87 | DrawPoisonBar = false 88 | DrawRotBar = false 89 | DrawBleedBar = false 90 | DrawBlightBar = false 91 | DrawFrostBar = false 92 | DrawSleepBar = false 93 | DrawMadnessBar = false 94 | StatusBarWidth = 1020.0 95 | StatusBarHeight = 16.0 96 | FirstStatusBarDiffScreenY = 16.0 97 | NextStatusBarDiffScreenY = 16.0 98 | 99 | ; DrawBars - whenever entity posture bars should be even drawn 100 | ; UseStaminaForNPC - changes posture bar to stamina bar for all human characters, while they have stagger values, they do not use them at all 101 | ; BarWidth and BarHeight - uses in game scaling (1920x1080) 102 | ; ResetStaggerTotalTime - when enemy crosses 0 value of posture damage, they automatically restore it to full while getting posture broken, this value sets arbitrary time for animation of bar to load itself to full 103 | ; OffsetScreen - sets the offset (in game scaling) from enemy health bar position, you can use OffsetTest to adjust this position by yourself 104 | ; ScreenThreshold - thresholds of where should posture bar stop in game viewport (in game scaling), most likely you should not change it 105 | [Entity Posture Bar] 106 | DrawBars = true 107 | UseStaminaForNPC = true 108 | BarWidth = 143.0 109 | BarHeight = 8.0 110 | ResetStaggerTotalTime = 2.0 111 | OffsetScreenX = -1.5 112 | OffsetScreenY = 5.0 113 | LeftScreenThreshold = 130.0 114 | RightScreenThreshold = 1790.0 115 | TopScreenThreshold = 175.0 116 | BottomScreenThreshold = 990.0 117 | 118 | ; Status bars 119 | ; DrawXBar - should X status bar be drawn 120 | ; StatusBarWidth and StatsBarHeight - uses in game scaling (1920x1080) 121 | ; FirstStatusBarDiffScreenY - sets coords (in game scaling) of first status bar Y wise after posture bar 122 | ; NextStatusBarDiffScreenY - seets coords (in game scaling) for next status bar Y wise 123 | DrawPoisonBar = false 124 | DrawRotBar = false 125 | DrawBleedBar = false 126 | DrawBlightBar = false 127 | DrawFrostBar = false 128 | DrawSleepBar = false 129 | DrawMadnessBar = false 130 | StatusBarWidth = 143.0 131 | StatusBarHeight = 14.0 132 | FirstStatusBarDiffScreenY = 14.0 133 | NextStatusBarDiffScreenY = 14.0 134 | 135 | ; ADVANCED: 136 | ; UsePositionFixing - position fixing alhorithm, looks for previous positions to allign posture bar better with health bar, by defalut they are slightly out of sync 137 | ; PositionFixingMultiplier - multiplier by which bar movement velocity is affected, if bar is dragging behind hp bar then you have to increase this value, if it is going ahead of hp bar, then you have to decrese it 138 | UsePositionFixing = true 139 | PositionFixingMultiplierX = 10.0 140 | PositionFixingMultiplierY = 10.0 141 | 142 | ; New stuff that I am not sure if they will work fine 143 | ; HideBarsOnMenu - whenever mod should check for open menus, might not work perfectly all the time, but should be good enaugh 144 | [Experimental] 145 | HideBarsOnMenu = false 146 | ; Player stagger bar - by default it will do nothing, as game does not use player stagger, use it only with mods that intends on making use of player stagger 147 | ; I have not made any attempts at making it look/position good right now, reffer to mod author that intends on using such bar 148 | DrawBar = false 149 | BarWidth = 214.5f 150 | BarHeight = 21.0f 151 | ResetStaggerTotalTime = 2.0f 152 | ScreenX = 963.0f 153 | ScreenY = 50.0f 154 | 155 | ; Log - log to file in mods/PostureModLog.txt 156 | ; OffsetTest - creats in game menu for adjusting screen and bar offsets. Use "Insert" key to save currently modified offset to .ini. Use "Page up/down" keys to change which offset you want to modify. Use "Arrows" keys to modify values. 157 | [Debug] 158 | Log = false 159 | OffsetTest = false 160 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | ## Ignore Visual Studio temporary files, build results, and 3 | ## files generated by popular Visual Studio add-ons. 4 | ## 5 | ## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore 6 | 7 | # User-specific files 8 | *.rsuser 9 | *.suo 10 | *.user 11 | *.userosscache 12 | *.sln.docstates 13 | 14 | # User-specific files (MonoDevelop/Xamarin Studio) 15 | *.userprefs 16 | 17 | # Mono auto generated files 18 | mono_crash.* 19 | 20 | # Build results 21 | [Dd]ebug/ 22 | [Dd]ebugPublic/ 23 | [Rr]elease/ 24 | [Rr]eleases/ 25 | x64/ 26 | x86/ 27 | [Ww][Ii][Nn]32/ 28 | [Aa][Rr][Mm]/ 29 | [Aa][Rr][Mm]64/ 30 | bld/ 31 | [Bb]in/ 32 | [Oo]bj/ 33 | [Ll]og/ 34 | [Ll]ogs/ 35 | 36 | # Visual Studio 2015/2017 cache/options directory 37 | .vs/ 38 | # Uncomment if you have tasks that create the project's static files in wwwroot 39 | #wwwroot/ 40 | 41 | # Visual Studio 2017 auto generated files 42 | Generated\ Files/ 43 | 44 | # MSTest test Results 45 | [Tt]est[Rr]esult*/ 46 | [Bb]uild[Ll]og.* 47 | 48 | # NUnit 49 | *.VisualState.xml 50 | TestResult.xml 51 | nunit-*.xml 52 | 53 | # Build Results of an ATL Project 54 | [Dd]ebugPS/ 55 | [Rr]eleasePS/ 56 | dlldata.c 57 | 58 | # Benchmark Results 59 | BenchmarkDotNet.Artifacts/ 60 | 61 | # .NET Core 62 | project.lock.json 63 | project.fragment.lock.json 64 | artifacts/ 65 | 66 | # ASP.NET Scaffolding 67 | ScaffoldingReadMe.txt 68 | 69 | # StyleCop 70 | StyleCopReport.xml 71 | 72 | # Files built by Visual Studio 73 | *_i.c 74 | *_p.c 75 | *_h.h 76 | *.ilk 77 | *.meta 78 | *.obj 79 | *.iobj 80 | *.pch 81 | *.pdb 82 | *.ipdb 83 | *.pgc 84 | *.pgd 85 | *.rsp 86 | *.sbr 87 | *.tlb 88 | *.tli 89 | *.tlh 90 | *.tmp 91 | *.tmp_proj 92 | *_wpftmp.csproj 93 | *.log 94 | *.tlog 95 | *.vspscc 96 | *.vssscc 97 | .builds 98 | *.pidb 99 | *.svclog 100 | *.scc 101 | 102 | # Chutzpah Test files 103 | _Chutzpah* 104 | 105 | # Visual C++ cache files 106 | ipch/ 107 | *.aps 108 | *.ncb 109 | *.opendb 110 | *.opensdf 111 | *.sdf 112 | *.cachefile 113 | *.VC.db 114 | *.VC.VC.opendb 115 | 116 | # Visual Studio profiler 117 | *.psess 118 | *.vsp 119 | *.vspx 120 | *.sap 121 | 122 | # Visual Studio Trace Files 123 | *.e2e 124 | 125 | # TFS 2012 Local Workspace 126 | $tf/ 127 | 128 | # Guidance Automation Toolkit 129 | *.gpState 130 | 131 | # ReSharper is a .NET coding add-in 132 | _ReSharper*/ 133 | *.[Rr]e[Ss]harper 134 | *.DotSettings.user 135 | 136 | # TeamCity is a build add-in 137 | _TeamCity* 138 | 139 | # DotCover is a Code Coverage Tool 140 | *.dotCover 141 | 142 | # AxoCover is a Code Coverage Tool 143 | .axoCover/* 144 | !.axoCover/settings.json 145 | 146 | # Coverlet is a free, cross platform Code Coverage Tool 147 | coverage*.json 148 | coverage*.xml 149 | coverage*.info 150 | 151 | # Visual Studio code coverage results 152 | *.coverage 153 | *.coveragexml 154 | 155 | # NCrunch 156 | _NCrunch_* 157 | .*crunch*.local.xml 158 | nCrunchTemp_* 159 | 160 | # MightyMoose 161 | *.mm.* 162 | AutoTest.Net/ 163 | 164 | # Web workbench (sass) 165 | .sass-cache/ 166 | 167 | # Installshield output folder 168 | [Ee]xpress/ 169 | 170 | # DocProject is a documentation generator add-in 171 | DocProject/buildhelp/ 172 | DocProject/Help/*.HxT 173 | DocProject/Help/*.HxC 174 | DocProject/Help/*.hhc 175 | DocProject/Help/*.hhk 176 | DocProject/Help/*.hhp 177 | DocProject/Help/Html2 178 | DocProject/Help/html 179 | 180 | # Click-Once directory 181 | publish/ 182 | 183 | # Publish Web Output 184 | *.[Pp]ublish.xml 185 | *.azurePubxml 186 | # Note: Comment the next line if you want to checkin your web deploy settings, 187 | # but database connection strings (with potential passwords) will be unencrypted 188 | *.pubxml 189 | *.publishproj 190 | 191 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 192 | # checkin your Azure Web App publish settings, but sensitive information contained 193 | # in these scripts will be unencrypted 194 | PublishScripts/ 195 | 196 | # NuGet Packages 197 | *.nupkg 198 | # NuGet Symbol Packages 199 | *.snupkg 200 | # The packages folder can be ignored because of Package Restore 201 | **/[Pp]ackages/* 202 | # except build/, which is used as an MSBuild target. 203 | !**/[Pp]ackages/build/ 204 | # Uncomment if necessary however generally it will be regenerated when needed 205 | #!**/[Pp]ackages/repositories.config 206 | # NuGet v3's project.json files produces more ignorable files 207 | *.nuget.props 208 | *.nuget.targets 209 | 210 | # Microsoft Azure Build Output 211 | csx/ 212 | *.build.csdef 213 | 214 | # Microsoft Azure Emulator 215 | ecf/ 216 | rcf/ 217 | 218 | # Windows Store app package directories and files 219 | AppPackages/ 220 | BundleArtifacts/ 221 | Package.StoreAssociation.xml 222 | _pkginfo.txt 223 | *.appx 224 | *.appxbundle 225 | *.appxupload 226 | 227 | # Visual Studio cache files 228 | # files ending in .cache can be ignored 229 | *.[Cc]ache 230 | # but keep track of directories ending in .cache 231 | !?*.[Cc]ache/ 232 | 233 | # Others 234 | ClientBin/ 235 | ~$* 236 | *~ 237 | *.dbmdl 238 | *.dbproj.schemaview 239 | *.jfm 240 | *.pfx 241 | *.publishsettings 242 | orleans.codegen.cs 243 | 244 | # Including strong name files can present a security risk 245 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 246 | #*.snk 247 | 248 | # Since there are multiple workflows, uncomment next line to ignore bower_components 249 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 250 | #bower_components/ 251 | 252 | # RIA/Silverlight projects 253 | Generated_Code/ 254 | 255 | # Backup & report files from converting an old project file 256 | # to a newer Visual Studio version. Backup files are not needed, 257 | # because we have git ;-) 258 | _UpgradeReport_Files/ 259 | Backup*/ 260 | UpgradeLog*.XML 261 | UpgradeLog*.htm 262 | ServiceFabricBackup/ 263 | *.rptproj.bak 264 | 265 | # SQL Server files 266 | *.mdf 267 | *.ldf 268 | *.ndf 269 | 270 | # Business Intelligence projects 271 | *.rdl.data 272 | *.bim.layout 273 | *.bim_*.settings 274 | *.rptproj.rsuser 275 | *- [Bb]ackup.rdl 276 | *- [Bb]ackup ([0-9]).rdl 277 | *- [Bb]ackup ([0-9][0-9]).rdl 278 | 279 | # Microsoft Fakes 280 | FakesAssemblies/ 281 | 282 | # GhostDoc plugin setting file 283 | *.GhostDoc.xml 284 | 285 | # Node.js Tools for Visual Studio 286 | .ntvs_analysis.dat 287 | node_modules/ 288 | 289 | # Visual Studio 6 build log 290 | *.plg 291 | 292 | # Visual Studio 6 workspace options file 293 | *.opt 294 | 295 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 296 | *.vbw 297 | 298 | # Visual Studio 6 auto-generated project file (contains which files were open etc.) 299 | *.vbp 300 | 301 | # Visual Studio 6 workspace and project file (working project files containing files to include in project) 302 | *.dsw 303 | *.dsp 304 | 305 | # Visual Studio 6 technical files 306 | *.ncb 307 | *.aps 308 | 309 | # Visual Studio LightSwitch build output 310 | **/*.HTMLClient/GeneratedArtifacts 311 | **/*.DesktopClient/GeneratedArtifacts 312 | **/*.DesktopClient/ModelManifest.xml 313 | **/*.Server/GeneratedArtifacts 314 | **/*.Server/ModelManifest.xml 315 | _Pvt_Extensions 316 | 317 | # Paket dependency manager 318 | .paket/paket.exe 319 | paket-files/ 320 | 321 | # FAKE - F# Make 322 | .fake/ 323 | 324 | # CodeRush personal settings 325 | .cr/personal 326 | 327 | # Python Tools for Visual Studio (PTVS) 328 | __pycache__/ 329 | *.pyc 330 | 331 | # Cake - Uncomment if you are using it 332 | # tools/** 333 | # !tools/packages.config 334 | 335 | # Tabs Studio 336 | *.tss 337 | 338 | # Telerik's JustMock configuration file 339 | *.jmconfig 340 | 341 | # BizTalk build output 342 | *.btp.cs 343 | *.btm.cs 344 | *.odx.cs 345 | *.xsd.cs 346 | 347 | # OpenCover UI analysis results 348 | OpenCover/ 349 | 350 | # Azure Stream Analytics local run output 351 | ASALocalRun/ 352 | 353 | # MSBuild Binary and Structured Log 354 | *.binlog 355 | 356 | # NVidia Nsight GPU debugger configuration file 357 | *.nvuser 358 | 359 | # MFractors (Xamarin productivity tool) working folder 360 | .mfractor/ 361 | 362 | # Local History for Visual Studio 363 | .localhistory/ 364 | 365 | # Visual Studio History (VSHistory) files 366 | .vshistory/ 367 | 368 | # BeatPulse healthcheck temp database 369 | healthchecksdb 370 | 371 | # Backup folder for Package Reference Convert tool in Visual Studio 2017 372 | MigrationBackup/ 373 | 374 | # Ionide (cross platform F# VS Code tools) working folder 375 | .ionide/ 376 | 377 | # Fody - auto-generated XML schema 378 | FodyWeavers.xsd 379 | 380 | # VS Code files for those working on multiple tools 381 | .vscode/* 382 | !.vscode/settings.json 383 | !.vscode/tasks.json 384 | !.vscode/launch.json 385 | !.vscode/extensions.json 386 | *.code-workspace 387 | 388 | # Local History for Visual Studio Code 389 | .history/ 390 | 391 | # Windows Installer files from build outputs 392 | *.cab 393 | *.msi 394 | *.msix 395 | *.msm 396 | *.msp 397 | 398 | # JetBrains Rider 399 | *.sln.iml -------------------------------------------------------------------------------- /Source/ImGui/imconfig.h: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // COMPILE-TIME OPTIONS FOR DEAR IMGUI 3 | // Runtime options (clipboard callbacks, enabling various features, etc.) can generally be set via the ImGuiIO structure. 4 | // You can use ImGui::SetAllocatorFunctions() before calling ImGui::CreateContext() to rewire memory allocation functions. 5 | //----------------------------------------------------------------------------- 6 | // A) You may edit imconfig.h (and not overwrite it when updating Dear ImGui, or maintain a patch/rebased branch with your modifications to it) 7 | // B) or '#define IMGUI_USER_CONFIG "my_imgui_config.h"' in your project and then add directives in your own file without touching this template. 8 | //----------------------------------------------------------------------------- 9 | // You need to make sure that configuration settings are defined consistently _everywhere_ Dear ImGui is used, which include the imgui*.cpp 10 | // files but also _any_ of your code that uses Dear ImGui. This is because some compile-time options have an affect on data structures. 11 | // Defining those options in imconfig.h will ensure every compilation unit gets to see the same data structure layouts. 12 | // Call IMGUI_CHECKVERSION() from your .cpp files to verify that the data structures your files are using are matching the ones imgui.cpp is using. 13 | //----------------------------------------------------------------------------- 14 | 15 | #pragma once 16 | 17 | //---- Define assertion handler. Defaults to calling assert(). 18 | // If your macro uses multiple statements, make sure is enclosed in a 'do { .. } while (0)' block so it can be used as a single statement. 19 | //#define IM_ASSERT(_EXPR) MyAssert(_EXPR) 20 | //#define IM_ASSERT(_EXPR) ((void)(_EXPR)) // Disable asserts 21 | 22 | //---- Define attributes of all API symbols declarations, e.g. for DLL under Windows 23 | // Using Dear ImGui via a shared library is not recommended, because of function call overhead and because we don't guarantee backward nor forward ABI compatibility. 24 | // DLL users: heaps and globals are not shared across DLL boundaries! You will need to call SetCurrentContext() + SetAllocatorFunctions() 25 | // for each static/DLL boundary you are calling from. Read "Context and Memory Allocators" section of imgui.cpp for more details. 26 | //#define IMGUI_API __declspec( dllexport ) 27 | //#define IMGUI_API __declspec( dllimport ) 28 | 29 | //---- Don't define obsolete functions/enums/behaviors. Consider enabling from time to time after updating to avoid using soon-to-be obsolete function/names. 30 | //#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS 31 | 32 | //---- Disable all of Dear ImGui or don't implement standard windows. 33 | // It is very strongly recommended to NOT disable the demo windows during development. Please read comments in imgui_demo.cpp. 34 | //#define IMGUI_DISABLE // Disable everything: all headers and source files will be empty. 35 | //#define IMGUI_DISABLE_DEMO_WINDOWS // Disable demo windows: ShowDemoWindow()/ShowStyleEditor() will be empty. Not recommended. 36 | //#define IMGUI_DISABLE_METRICS_WINDOW // Disable metrics/debugger window: ShowMetricsWindow() will be empty. 37 | 38 | //---- Don't implement some functions to reduce linkage requirements. 39 | //#define IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS // [Win32] Don't implement default clipboard handler. Won't use and link with OpenClipboard/GetClipboardData/CloseClipboard etc. (user32.lib/.a, kernel32.lib/.a) 40 | //#define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS // [Win32] Don't implement default IME handler. Won't use and link with ImmGetContext/ImmSetCompositionWindow. (imm32.lib/.a) 41 | //#define IMGUI_DISABLE_WIN32_FUNCTIONS // [Win32] Won't use and link with any Win32 function (clipboard, ime). 42 | //#define IMGUI_ENABLE_OSX_DEFAULT_CLIPBOARD_FUNCTIONS // [OSX] Implement default OSX clipboard handler (need to link with '-framework ApplicationServices', this is why this is not the default). 43 | //#define IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS // Don't implement ImFormatString/ImFormatStringV so you can implement them yourself (e.g. if you don't want to link with vsnprintf) 44 | //#define IMGUI_DISABLE_DEFAULT_MATH_FUNCTIONS // Don't implement ImFabs/ImSqrt/ImPow/ImFmod/ImCos/ImSin/ImAcos/ImAtan2 so you can implement them yourself. 45 | //#define IMGUI_DISABLE_FILE_FUNCTIONS // Don't implement ImFileOpen/ImFileClose/ImFileRead/ImFileWrite and ImFileHandle at all (replace them with dummies) 46 | //#define IMGUI_DISABLE_DEFAULT_FILE_FUNCTIONS // Don't implement ImFileOpen/ImFileClose/ImFileRead/ImFileWrite and ImFileHandle so you can implement them yourself if you don't want to link with fopen/fclose/fread/fwrite. This will also disable the LogToTTY() function. 47 | //#define IMGUI_DISABLE_DEFAULT_ALLOCATORS // Don't implement default allocators calling malloc()/free() to avoid linking with them. You will need to call ImGui::SetAllocatorFunctions(). 48 | 49 | //---- Include imgui_user.h at the end of imgui.h as a convenience 50 | //#define IMGUI_INCLUDE_IMGUI_USER_H 51 | 52 | //---- Pack colors to BGRA8 instead of RGBA8 (to avoid converting from one to another) 53 | //#define IMGUI_USE_BGRA_PACKED_COLOR 54 | 55 | //---- Use 32-bit for ImWchar (default is 16-bit) to support unicode planes 1-16. (e.g. point beyond 0xFFFF like emoticons, dingbats, symbols, shapes, ancient languages, etc...) 56 | //#define IMGUI_USE_WCHAR32 57 | 58 | //---- Avoid multiple STB libraries implementations, or redefine path/filenames to prioritize another version 59 | // By default the embedded implementations are declared static and not available outside of Dear ImGui sources files. 60 | //#define IMGUI_STB_TRUETYPE_FILENAME "my_folder/stb_truetype.h" 61 | //#define IMGUI_STB_RECT_PACK_FILENAME "my_folder/stb_rect_pack.h" 62 | //#define IMGUI_DISABLE_STB_TRUETYPE_IMPLEMENTATION 63 | //#define IMGUI_DISABLE_STB_RECT_PACK_IMPLEMENTATION 64 | 65 | //---- Use stb_printf's faster implementation of vsnprintf instead of the one from libc (unless IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS is defined) 66 | // Requires 'stb_sprintf.h' to be available in the include path. Compatibility checks of arguments and formats done by clang and GCC will be disabled in order to support the extra formats provided by STB sprintf. 67 | // #define IMGUI_USE_STB_SPRINTF 68 | 69 | //---- Use FreeType to build and rasterize the font atlas (instead of stb_truetype which is embedded by default in Dear ImGui) 70 | // Requires FreeType headers to be available in the include path. Requires program to be compiled with 'misc/freetype/imgui_freetype.cpp' (in this repository) + the FreeType library (not provided). 71 | // On Windows you may use vcpkg with 'vcpkg install freetype' + 'vcpkg integrate install'. 72 | //#define IMGUI_ENABLE_FREETYPE 73 | 74 | //---- Use stb_truetype to build and rasterize the font atlas (default) 75 | // The only purpose of this define is if you want force compilation of the stb_truetype backend ALONG with the FreeType backend. 76 | //#define IMGUI_ENABLE_STB_TRUETYPE 77 | 78 | //---- Define constructor and implicit cast operators to convert back<>forth between your math types and ImVec2/ImVec4. 79 | // This will be inlined as part of ImVec2 and ImVec4 class declarations. 80 | /* 81 | #define IM_VEC2_CLASS_EXTRA \ 82 | ImVec2(const MyVec2& f) { x = f.x; y = f.y; } \ 83 | operator MyVec2() const { return MyVec2(x,y); } 84 | 85 | #define IM_VEC4_CLASS_EXTRA \ 86 | ImVec4(const MyVec4& f) { x = f.x; y = f.y; z = f.z; w = f.w; } \ 87 | operator MyVec4() const { return MyVec4(x,y,z,w); } 88 | */ 89 | 90 | //---- Use 32-bit vertex indices (default is 16-bit) is one way to allow large meshes with more than 64K vertices. 91 | // Your renderer backend will need to support it (most example renderer backends support both 16/32-bit indices). 92 | // Another way to allow large meshes while keeping 16-bit indices is to handle ImDrawCmd::VtxOffset in your renderer. 93 | // Read about ImGuiBackendFlags_RendererHasVtxOffset for details. 94 | //#define ImDrawIdx unsigned int 95 | 96 | //---- Override ImDrawCallback signature (will need to modify renderer backends accordingly) 97 | //struct ImDrawList; 98 | //struct ImDrawCmd; 99 | //typedef void (*MyImDrawCallback)(const ImDrawList* draw_list, const ImDrawCmd* cmd, void* my_renderer_user_data); 100 | //#define ImDrawCallback MyImDrawCallback 101 | 102 | //---- Debug Tools: Macro to break in Debugger 103 | // (use 'Metrics->Tools->Item Picker' to pick widgets with the mouse and break into them for easy debugging.) 104 | //#define IM_DEBUG_BREAK IM_ASSERT(0) 105 | //#define IM_DEBUG_BREAK __debugbreak() 106 | 107 | //---- Debug Tools: Have the Item Picker break in the ItemAdd() function instead of ItemHoverable(), 108 | // (which comes earlier in the code, will catch a few extra items, allow picking items other than Hovered one.) 109 | // This adds a small runtime cost which is why it is not enabled by default. 110 | //#define IMGUI_DEBUG_TOOL_ITEM_PICKER_EX 111 | 112 | //---- Debug Tools: Enable slower asserts 113 | //#define IMGUI_DEBUG_PARANOID 114 | 115 | //---- Tip: You can add extra functions within the ImGui:: namespace, here or in your own headers files. 116 | /* 117 | namespace ImGui 118 | { 119 | void MyFunction(const char* name, const MyMatrix44& v); 120 | } 121 | */ 122 | -------------------------------------------------------------------------------- /Source/Main/Memory.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "../Common.hpp" 3 | 4 | namespace ER 5 | { 6 | class MemoryHandle 7 | { 8 | public: 9 | /** 10 | * \brief Constructs the object with a pointer 11 | * \param p The pointer to initialize the object with, optional 12 | */ 13 | constexpr MemoryHandle(void* p = nullptr) : 14 | m_Ptr(p) 15 | {} 16 | 17 | /** 18 | * \brief Constructs the object with an integral pointer 19 | * \param p The integral pointer to initialize the object with 20 | */ 21 | explicit MemoryHandle(std::uintptr_t p) : 22 | m_Ptr(reinterpret_cast(p)) 23 | {} 24 | 25 | /** 26 | * \brief Retrieves the pointer as a pointer 27 | * \return A pointer 28 | */ 29 | template 30 | constexpr std::enable_if_t, T> As() 31 | { 32 | return static_cast(m_Ptr); 33 | } 34 | 35 | /** 36 | * \brief Retrieves the pointer as a reference 37 | * \return A pointer 38 | */ 39 | template 40 | constexpr std::enable_if_t, T> As() 41 | { 42 | return *static_cast>>(m_Ptr); 43 | } 44 | 45 | /** 46 | * \brief Retrieves the pointer as an integral pointer 47 | * \return An integral pointer 48 | */ 49 | template 50 | constexpr std::enable_if_t, T> As() 51 | { 52 | return reinterpret_cast(m_Ptr); 53 | } 54 | 55 | /** 56 | * \brief Adds an offset to the pointer 57 | * \param offset The offset to be added 58 | * \return MemoryHandle 59 | */ 60 | template 61 | constexpr MemoryHandle Add(T offset) 62 | { 63 | if(!m_Ptr) 64 | { 65 | return {}; 66 | } 67 | return MemoryHandle(As() + offset); 68 | } 69 | 70 | /** 71 | * \brief Subtracted an offset to the pointer 72 | * \param offset The offset to be subtracted 73 | * \return MemoryHandle 74 | */ 75 | template 76 | constexpr MemoryHandle Sub(T offset) 77 | { 78 | if (!m_Ptr) 79 | { 80 | return {}; 81 | } 82 | return MemoryHandle(As() - offset); 83 | } 84 | 85 | /** 86 | * \brief Gets the relative displacement of the pointer 87 | * \return MemoryHandle 88 | */ 89 | constexpr MemoryHandle Rip() 90 | { 91 | if (!m_Ptr) 92 | return nullptr; 93 | return Add(As()).Add(4U); 94 | } 95 | 96 | /** 97 | * \brief Checks if the stored pointer is valid 98 | * \return bool 99 | */ 100 | constexpr explicit operator bool() noexcept 101 | { 102 | return m_Ptr; 103 | } 104 | protected: 105 | void* m_Ptr; 106 | }; 107 | 108 | class MemoryRegion 109 | { 110 | public: 111 | /** 112 | * \brief Constructs the region 113 | * \param base The base of the region 114 | * \param size The size of the region 115 | */ 116 | constexpr explicit MemoryRegion(MemoryHandle base, std::size_t size) : 117 | m_Base(base), 118 | m_Size(size) 119 | {} 120 | 121 | /** 122 | * \brief Gets the base of the region 123 | * \return MemoryHandle 124 | */ 125 | constexpr MemoryHandle Base() 126 | { 127 | return m_Base; 128 | } 129 | 130 | /** 131 | * \brief Gets the end of the region 132 | * \return MemoryHandle 133 | */ 134 | constexpr MemoryHandle End() 135 | { 136 | return m_Base.Add(m_Size); 137 | } 138 | 139 | /** 140 | * \brief Gets the size of the region 141 | * \return std::size_t 142 | */ 143 | constexpr std::size_t Size() 144 | { 145 | return m_Size; 146 | } 147 | 148 | /** 149 | * \brief Checks if p is within this region 150 | * \param p The pointer 151 | * \return bool 152 | */ 153 | constexpr bool Contains(MemoryHandle p) 154 | { 155 | if (p.As() < m_Base.As()) 156 | return false; 157 | if (p.As() > m_Base.Add(m_Size).As()) 158 | return false; 159 | 160 | return true; 161 | } 162 | protected: 163 | MemoryHandle m_Base; 164 | std::size_t m_Size; 165 | }; 166 | 167 | class Module : public MemoryRegion 168 | { 169 | public: 170 | /** 171 | * \brief Constructs the class with the main module 172 | */ 173 | explicit Module(std::nullptr_t) : 174 | Module(static_cast(nullptr)) 175 | {} 176 | 177 | /** 178 | * \brief Constructs the class with a module name 179 | * \param name The name of the module 180 | */ 181 | explicit Module(const char* name) : 182 | Module(GetModuleHandleA(name)) 183 | { 184 | } 185 | 186 | /** 187 | * \brief Constructs the class with a module base 188 | */ 189 | Module(HMODULE hmod) : 190 | MemoryRegion(hmod, 0) 191 | { 192 | auto dosHeader = m_Base.As(); 193 | auto ntHeader = m_Base.Add(dosHeader->e_lfanew).As(); 194 | m_Size = ntHeader->OptionalHeader.SizeOfImage; 195 | } 196 | 197 | /** 198 | * \brief Gets the DOS headers for the module 199 | */ 200 | IMAGE_DOS_HEADER* GetDosHeaders() 201 | { 202 | return m_Base.As(); 203 | } 204 | 205 | /** 206 | * \brief Gets the NT headers for the module 207 | */ 208 | IMAGE_NT_HEADERS64* GetNtHeaders() 209 | { 210 | return m_Base.Add(m_Base.As()->e_lfanew).As(); 211 | } 212 | private: 213 | /** 214 | * \brief Transforms a relative virtual address to a virtual address 215 | */ 216 | template 217 | TReturn GetRVA(TOffset rva) 218 | { 219 | return m_Base.Add(rva).As(); 220 | } 221 | }; 222 | 223 | class Signature 224 | { 225 | public: 226 | struct Element 227 | { 228 | std::uint8_t m_Data{}; 229 | bool m_Wildcard{}; 230 | }; 231 | 232 | /** 233 | * \brief Constructs the signature with an IDA pattern 234 | * \param pattern The IDA pattern string 235 | */ 236 | explicit Signature(const char* pattern) 237 | { 238 | auto toUpper = [](char c) -> char 239 | { 240 | return c >= 'a' && c <= 'z' ? static_cast(c + ('A' - 'a')) : static_cast(c); 241 | }; 242 | 243 | auto isHex = [&](char c) -> bool 244 | { 245 | switch (toUpper(c)) 246 | { 247 | case '0': 248 | case '1': 249 | case '2': 250 | case '3': 251 | case '4': 252 | case '5': 253 | case '6': 254 | case '7': 255 | case '8': 256 | case '9': 257 | case 'A': 258 | case 'B': 259 | case 'C': 260 | case 'D': 261 | case 'E': 262 | case 'F': 263 | return true; 264 | default: 265 | return false; 266 | } 267 | }; 268 | 269 | do 270 | { 271 | if (*pattern == ' ') 272 | continue; 273 | if (*pattern == '?') 274 | { 275 | m_Elements.push_back(Element{ {}, true }); 276 | continue; 277 | } 278 | 279 | if (*(pattern + 1) && isHex(*pattern) && isHex(*(pattern + 1))) 280 | { 281 | char str[3] = { *pattern, *(pattern + 1), '\0' }; 282 | auto data = std::strtol(str, nullptr, 16); 283 | 284 | m_Elements.push_back(Element{ static_cast(data), false }); 285 | } 286 | } while (*(pattern++)); 287 | } 288 | 289 | /** 290 | * \brief Scans for the pattern in a memory region 291 | * \param region The region to search in, default is the main module 292 | * \return MemoryHandle 293 | */ 294 | MemoryHandle Scan(MemoryRegion region = Module(nullptr)) 295 | { 296 | auto compareMemory = [](std::uint8_t* data, Element* elem, std::size_t num) -> bool 297 | { 298 | for (std::size_t i = 0; i < num; ++i) 299 | { 300 | if (!elem[i].m_Wildcard) 301 | if (data[i] != elem[i].m_Data) 302 | return false; 303 | } 304 | 305 | return true; 306 | }; 307 | 308 | for (std::uintptr_t i = region.Base().As(), end = region.End().As(); i != end; ++i) 309 | { 310 | if (compareMemory(reinterpret_cast(i), m_Elements.data(), m_Elements.size())) 311 | { 312 | return MemoryHandle(i); 313 | } 314 | } 315 | 316 | return {}; 317 | } 318 | private: 319 | std::vector m_Elements; 320 | }; 321 | } -------------------------------------------------------------------------------- /Source/Minhook/hde32.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Hacker Disassembler Engine 32 C 3 | * Copyright (c) 2008-2009, Vyacheslav Patkov. 4 | * All rights reserved. 5 | * 6 | */ 7 | 8 | #if defined(_M_IX86) || defined(__i386__) 9 | 10 | #include "hde32.h" 11 | #include "table32.h" 12 | 13 | unsigned int hde32_disasm(const void *code, hde32s *hs) 14 | { 15 | uint8_t x, c, *p = (uint8_t *)code, cflags, opcode, pref = 0; 16 | uint8_t *ht = hde32_table, m_mod, m_reg, m_rm, disp_size = 0; 17 | 18 | // Avoid using memset to reduce the footprint. 19 | #ifndef _MSC_VER 20 | memset((LPBYTE)hs, 0, sizeof(hde32s)); 21 | #else 22 | __stosb((LPBYTE)hs, 0, sizeof(hde32s)); 23 | #endif 24 | 25 | for (x = 16; x; x--) 26 | switch (c = *p++) { 27 | case 0xf3: 28 | hs->p_rep = c; 29 | pref |= PRE_F3; 30 | break; 31 | case 0xf2: 32 | hs->p_rep = c; 33 | pref |= PRE_F2; 34 | break; 35 | case 0xf0: 36 | hs->p_lock = c; 37 | pref |= PRE_LOCK; 38 | break; 39 | case 0x26: case 0x2e: case 0x36: 40 | case 0x3e: case 0x64: case 0x65: 41 | hs->p_seg = c; 42 | pref |= PRE_SEG; 43 | break; 44 | case 0x66: 45 | hs->p_66 = c; 46 | pref |= PRE_66; 47 | break; 48 | case 0x67: 49 | hs->p_67 = c; 50 | pref |= PRE_67; 51 | break; 52 | default: 53 | goto pref_done; 54 | } 55 | pref_done: 56 | 57 | hs->flags = (uint32_t)pref << 23; 58 | 59 | if (!pref) 60 | pref |= PRE_NONE; 61 | 62 | if ((hs->opcode = c) == 0x0f) { 63 | hs->opcode2 = c = *p++; 64 | ht += DELTA_OPCODES; 65 | } else if (c >= 0xa0 && c <= 0xa3) { 66 | if (pref & PRE_67) 67 | pref |= PRE_66; 68 | else 69 | pref &= ~PRE_66; 70 | } 71 | 72 | opcode = c; 73 | cflags = ht[ht[opcode / 4] + (opcode % 4)]; 74 | 75 | if (cflags == C_ERROR) { 76 | hs->flags |= F_ERROR | F_ERROR_OPCODE; 77 | cflags = 0; 78 | if ((opcode & -3) == 0x24) 79 | cflags++; 80 | } 81 | 82 | x = 0; 83 | if (cflags & C_GROUP) { 84 | uint16_t t; 85 | t = *(uint16_t *)(ht + (cflags & 0x7f)); 86 | cflags = (uint8_t)t; 87 | x = (uint8_t)(t >> 8); 88 | } 89 | 90 | if (hs->opcode2) { 91 | ht = hde32_table + DELTA_PREFIXES; 92 | if (ht[ht[opcode / 4] + (opcode % 4)] & pref) 93 | hs->flags |= F_ERROR | F_ERROR_OPCODE; 94 | } 95 | 96 | if (cflags & C_MODRM) { 97 | hs->flags |= F_MODRM; 98 | hs->modrm = c = *p++; 99 | hs->modrm_mod = m_mod = c >> 6; 100 | hs->modrm_rm = m_rm = c & 7; 101 | hs->modrm_reg = m_reg = (c & 0x3f) >> 3; 102 | 103 | if (x && ((x << m_reg) & 0x80)) 104 | hs->flags |= F_ERROR | F_ERROR_OPCODE; 105 | 106 | if (!hs->opcode2 && opcode >= 0xd9 && opcode <= 0xdf) { 107 | uint8_t t = opcode - 0xd9; 108 | if (m_mod == 3) { 109 | ht = hde32_table + DELTA_FPU_MODRM + t*8; 110 | t = ht[m_reg] << m_rm; 111 | } else { 112 | ht = hde32_table + DELTA_FPU_REG; 113 | t = ht[t] << m_reg; 114 | } 115 | if (t & 0x80) 116 | hs->flags |= F_ERROR | F_ERROR_OPCODE; 117 | } 118 | 119 | if (pref & PRE_LOCK) { 120 | if (m_mod == 3) { 121 | hs->flags |= F_ERROR | F_ERROR_LOCK; 122 | } else { 123 | uint8_t *table_end, op = opcode; 124 | if (hs->opcode2) { 125 | ht = hde32_table + DELTA_OP2_LOCK_OK; 126 | table_end = ht + DELTA_OP_ONLY_MEM - DELTA_OP2_LOCK_OK; 127 | } else { 128 | ht = hde32_table + DELTA_OP_LOCK_OK; 129 | table_end = ht + DELTA_OP2_LOCK_OK - DELTA_OP_LOCK_OK; 130 | op &= -2; 131 | } 132 | for (; ht != table_end; ht++) 133 | if (*ht++ == op) { 134 | if (!((*ht << m_reg) & 0x80)) 135 | goto no_lock_error; 136 | else 137 | break; 138 | } 139 | hs->flags |= F_ERROR | F_ERROR_LOCK; 140 | no_lock_error: 141 | ; 142 | } 143 | } 144 | 145 | if (hs->opcode2) { 146 | switch (opcode) { 147 | case 0x20: case 0x22: 148 | m_mod = 3; 149 | if (m_reg > 4 || m_reg == 1) 150 | goto error_operand; 151 | else 152 | goto no_error_operand; 153 | case 0x21: case 0x23: 154 | m_mod = 3; 155 | if (m_reg == 4 || m_reg == 5) 156 | goto error_operand; 157 | else 158 | goto no_error_operand; 159 | } 160 | } else { 161 | switch (opcode) { 162 | case 0x8c: 163 | if (m_reg > 5) 164 | goto error_operand; 165 | else 166 | goto no_error_operand; 167 | case 0x8e: 168 | if (m_reg == 1 || m_reg > 5) 169 | goto error_operand; 170 | else 171 | goto no_error_operand; 172 | } 173 | } 174 | 175 | if (m_mod == 3) { 176 | uint8_t *table_end; 177 | if (hs->opcode2) { 178 | ht = hde32_table + DELTA_OP2_ONLY_MEM; 179 | table_end = ht + sizeof(hde32_table) - DELTA_OP2_ONLY_MEM; 180 | } else { 181 | ht = hde32_table + DELTA_OP_ONLY_MEM; 182 | table_end = ht + DELTA_OP2_ONLY_MEM - DELTA_OP_ONLY_MEM; 183 | } 184 | for (; ht != table_end; ht += 2) 185 | if (*ht++ == opcode) { 186 | if (*ht++ & pref && !((*ht << m_reg) & 0x80)) 187 | goto error_operand; 188 | else 189 | break; 190 | } 191 | goto no_error_operand; 192 | } else if (hs->opcode2) { 193 | switch (opcode) { 194 | case 0x50: case 0xd7: case 0xf7: 195 | if (pref & (PRE_NONE | PRE_66)) 196 | goto error_operand; 197 | break; 198 | case 0xd6: 199 | if (pref & (PRE_F2 | PRE_F3)) 200 | goto error_operand; 201 | break; 202 | case 0xc5: 203 | goto error_operand; 204 | } 205 | goto no_error_operand; 206 | } else 207 | goto no_error_operand; 208 | 209 | error_operand: 210 | hs->flags |= F_ERROR | F_ERROR_OPERAND; 211 | no_error_operand: 212 | 213 | c = *p++; 214 | if (m_reg <= 1) { 215 | if (opcode == 0xf6) 216 | cflags |= C_IMM8; 217 | else if (opcode == 0xf7) 218 | cflags |= C_IMM_P66; 219 | } 220 | 221 | switch (m_mod) { 222 | case 0: 223 | if (pref & PRE_67) { 224 | if (m_rm == 6) 225 | disp_size = 2; 226 | } else 227 | if (m_rm == 5) 228 | disp_size = 4; 229 | break; 230 | case 1: 231 | disp_size = 1; 232 | break; 233 | case 2: 234 | disp_size = 2; 235 | if (!(pref & PRE_67)) 236 | disp_size <<= 1; 237 | } 238 | 239 | if (m_mod != 3 && m_rm == 4 && !(pref & PRE_67)) { 240 | hs->flags |= F_SIB; 241 | p++; 242 | hs->sib = c; 243 | hs->sib_scale = c >> 6; 244 | hs->sib_index = (c & 0x3f) >> 3; 245 | if ((hs->sib_base = c & 7) == 5 && !(m_mod & 1)) 246 | disp_size = 4; 247 | } 248 | 249 | p--; 250 | switch (disp_size) { 251 | case 1: 252 | hs->flags |= F_DISP8; 253 | hs->disp.disp8 = *p; 254 | break; 255 | case 2: 256 | hs->flags |= F_DISP16; 257 | hs->disp.disp16 = *(uint16_t *)p; 258 | break; 259 | case 4: 260 | hs->flags |= F_DISP32; 261 | hs->disp.disp32 = *(uint32_t *)p; 262 | } 263 | p += disp_size; 264 | } else if (pref & PRE_LOCK) 265 | hs->flags |= F_ERROR | F_ERROR_LOCK; 266 | 267 | if (cflags & C_IMM_P66) { 268 | if (cflags & C_REL32) { 269 | if (pref & PRE_66) { 270 | hs->flags |= F_IMM16 | F_RELATIVE; 271 | hs->imm.imm16 = *(uint16_t *)p; 272 | p += 2; 273 | goto disasm_done; 274 | } 275 | goto rel32_ok; 276 | } 277 | if (pref & PRE_66) { 278 | hs->flags |= F_IMM16; 279 | hs->imm.imm16 = *(uint16_t *)p; 280 | p += 2; 281 | } else { 282 | hs->flags |= F_IMM32; 283 | hs->imm.imm32 = *(uint32_t *)p; 284 | p += 4; 285 | } 286 | } 287 | 288 | if (cflags & C_IMM16) { 289 | if (hs->flags & F_IMM32) { 290 | hs->flags |= F_IMM16; 291 | hs->disp.disp16 = *(uint16_t *)p; 292 | } else if (hs->flags & F_IMM16) { 293 | hs->flags |= F_2IMM16; 294 | hs->disp.disp16 = *(uint16_t *)p; 295 | } else { 296 | hs->flags |= F_IMM16; 297 | hs->imm.imm16 = *(uint16_t *)p; 298 | } 299 | p += 2; 300 | } 301 | if (cflags & C_IMM8) { 302 | hs->flags |= F_IMM8; 303 | hs->imm.imm8 = *p++; 304 | } 305 | 306 | if (cflags & C_REL32) { 307 | rel32_ok: 308 | hs->flags |= F_IMM32 | F_RELATIVE; 309 | hs->imm.imm32 = *(uint32_t *)p; 310 | p += 4; 311 | } else if (cflags & C_REL8) { 312 | hs->flags |= F_IMM8 | F_RELATIVE; 313 | hs->imm.imm8 = *p++; 314 | } 315 | 316 | disasm_done: 317 | 318 | if ((hs->len = (uint8_t)(p-(uint8_t *)code)) > 15) { 319 | hs->flags |= F_ERROR | F_ERROR_LENGTH; 320 | hs->len = 15; 321 | } 322 | 323 | return (unsigned int)hs->len; 324 | } 325 | 326 | #endif // defined(_M_IX86) || defined(__i386__) 327 | -------------------------------------------------------------------------------- /Source/Minhook/hde64.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Hacker Disassembler Engine 64 C 3 | * Copyright (c) 2008-2009, Vyacheslav Patkov. 4 | * All rights reserved. 5 | * 6 | */ 7 | 8 | #if defined(_M_X64) || defined(__x86_64__) 9 | 10 | #include "hde64.h" 11 | #include "table64.h" 12 | 13 | unsigned int hde64_disasm(const void *code, hde64s *hs) 14 | { 15 | uint8_t x, c, *p = (uint8_t *)code, cflags, opcode, pref = 0; 16 | uint8_t *ht = hde64_table, m_mod, m_reg, m_rm, disp_size = 0; 17 | uint8_t op64 = 0; 18 | 19 | // Avoid using memset to reduce the footprint. 20 | #ifndef _MSC_VER 21 | memset((LPBYTE)hs, 0, sizeof(hde64s)); 22 | #else 23 | __stosb((LPBYTE)hs, 0, sizeof(hde64s)); 24 | #endif 25 | 26 | for (x = 16; x; x--) 27 | switch (c = *p++) { 28 | case 0xf3: 29 | hs->p_rep = c; 30 | pref |= PRE_F3; 31 | break; 32 | case 0xf2: 33 | hs->p_rep = c; 34 | pref |= PRE_F2; 35 | break; 36 | case 0xf0: 37 | hs->p_lock = c; 38 | pref |= PRE_LOCK; 39 | break; 40 | case 0x26: case 0x2e: case 0x36: 41 | case 0x3e: case 0x64: case 0x65: 42 | hs->p_seg = c; 43 | pref |= PRE_SEG; 44 | break; 45 | case 0x66: 46 | hs->p_66 = c; 47 | pref |= PRE_66; 48 | break; 49 | case 0x67: 50 | hs->p_67 = c; 51 | pref |= PRE_67; 52 | break; 53 | default: 54 | goto pref_done; 55 | } 56 | pref_done: 57 | 58 | hs->flags = (uint32_t)pref << 23; 59 | 60 | if (!pref) 61 | pref |= PRE_NONE; 62 | 63 | if ((c & 0xf0) == 0x40) { 64 | hs->flags |= F_PREFIX_REX; 65 | if ((hs->rex_w = (c & 0xf) >> 3) && (*p & 0xf8) == 0xb8) 66 | op64++; 67 | hs->rex_r = (c & 7) >> 2; 68 | hs->rex_x = (c & 3) >> 1; 69 | hs->rex_b = c & 1; 70 | if (((c = *p++) & 0xf0) == 0x40) { 71 | opcode = c; 72 | goto error_opcode; 73 | } 74 | } 75 | 76 | if ((hs->opcode = c) == 0x0f) { 77 | hs->opcode2 = c = *p++; 78 | ht += DELTA_OPCODES; 79 | } else if (c >= 0xa0 && c <= 0xa3) { 80 | op64++; 81 | if (pref & PRE_67) 82 | pref |= PRE_66; 83 | else 84 | pref &= ~PRE_66; 85 | } 86 | 87 | opcode = c; 88 | cflags = ht[ht[opcode / 4] + (opcode % 4)]; 89 | 90 | if (cflags == C_ERROR) { 91 | error_opcode: 92 | hs->flags |= F_ERROR | F_ERROR_OPCODE; 93 | cflags = 0; 94 | if ((opcode & -3) == 0x24) 95 | cflags++; 96 | } 97 | 98 | x = 0; 99 | if (cflags & C_GROUP) { 100 | uint16_t t; 101 | t = *(uint16_t *)(ht + (cflags & 0x7f)); 102 | cflags = (uint8_t)t; 103 | x = (uint8_t)(t >> 8); 104 | } 105 | 106 | if (hs->opcode2) { 107 | ht = hde64_table + DELTA_PREFIXES; 108 | if (ht[ht[opcode / 4] + (opcode % 4)] & pref) 109 | hs->flags |= F_ERROR | F_ERROR_OPCODE; 110 | } 111 | 112 | if (cflags & C_MODRM) { 113 | hs->flags |= F_MODRM; 114 | hs->modrm = c = *p++; 115 | hs->modrm_mod = m_mod = c >> 6; 116 | hs->modrm_rm = m_rm = c & 7; 117 | hs->modrm_reg = m_reg = (c & 0x3f) >> 3; 118 | 119 | if (x && ((x << m_reg) & 0x80)) 120 | hs->flags |= F_ERROR | F_ERROR_OPCODE; 121 | 122 | if (!hs->opcode2 && opcode >= 0xd9 && opcode <= 0xdf) { 123 | uint8_t t = opcode - 0xd9; 124 | if (m_mod == 3) { 125 | ht = hde64_table + DELTA_FPU_MODRM + t*8; 126 | t = ht[m_reg] << m_rm; 127 | } else { 128 | ht = hde64_table + DELTA_FPU_REG; 129 | t = ht[t] << m_reg; 130 | } 131 | if (t & 0x80) 132 | hs->flags |= F_ERROR | F_ERROR_OPCODE; 133 | } 134 | 135 | if (pref & PRE_LOCK) { 136 | if (m_mod == 3) { 137 | hs->flags |= F_ERROR | F_ERROR_LOCK; 138 | } else { 139 | uint8_t *table_end, op = opcode; 140 | if (hs->opcode2) { 141 | ht = hde64_table + DELTA_OP2_LOCK_OK; 142 | table_end = ht + DELTA_OP_ONLY_MEM - DELTA_OP2_LOCK_OK; 143 | } else { 144 | ht = hde64_table + DELTA_OP_LOCK_OK; 145 | table_end = ht + DELTA_OP2_LOCK_OK - DELTA_OP_LOCK_OK; 146 | op &= -2; 147 | } 148 | for (; ht != table_end; ht++) 149 | if (*ht++ == op) { 150 | if (!((*ht << m_reg) & 0x80)) 151 | goto no_lock_error; 152 | else 153 | break; 154 | } 155 | hs->flags |= F_ERROR | F_ERROR_LOCK; 156 | no_lock_error: 157 | ; 158 | } 159 | } 160 | 161 | if (hs->opcode2) { 162 | switch (opcode) { 163 | case 0x20: case 0x22: 164 | m_mod = 3; 165 | if (m_reg > 4 || m_reg == 1) 166 | goto error_operand; 167 | else 168 | goto no_error_operand; 169 | case 0x21: case 0x23: 170 | m_mod = 3; 171 | if (m_reg == 4 || m_reg == 5) 172 | goto error_operand; 173 | else 174 | goto no_error_operand; 175 | } 176 | } else { 177 | switch (opcode) { 178 | case 0x8c: 179 | if (m_reg > 5) 180 | goto error_operand; 181 | else 182 | goto no_error_operand; 183 | case 0x8e: 184 | if (m_reg == 1 || m_reg > 5) 185 | goto error_operand; 186 | else 187 | goto no_error_operand; 188 | } 189 | } 190 | 191 | if (m_mod == 3) { 192 | uint8_t *table_end; 193 | if (hs->opcode2) { 194 | ht = hde64_table + DELTA_OP2_ONLY_MEM; 195 | table_end = ht + sizeof(hde64_table) - DELTA_OP2_ONLY_MEM; 196 | } else { 197 | ht = hde64_table + DELTA_OP_ONLY_MEM; 198 | table_end = ht + DELTA_OP2_ONLY_MEM - DELTA_OP_ONLY_MEM; 199 | } 200 | for (; ht != table_end; ht += 2) 201 | if (*ht++ == opcode) { 202 | if (*ht++ & pref && !((*ht << m_reg) & 0x80)) 203 | goto error_operand; 204 | else 205 | break; 206 | } 207 | goto no_error_operand; 208 | } else if (hs->opcode2) { 209 | switch (opcode) { 210 | case 0x50: case 0xd7: case 0xf7: 211 | if (pref & (PRE_NONE | PRE_66)) 212 | goto error_operand; 213 | break; 214 | case 0xd6: 215 | if (pref & (PRE_F2 | PRE_F3)) 216 | goto error_operand; 217 | break; 218 | case 0xc5: 219 | goto error_operand; 220 | } 221 | goto no_error_operand; 222 | } else 223 | goto no_error_operand; 224 | 225 | error_operand: 226 | hs->flags |= F_ERROR | F_ERROR_OPERAND; 227 | no_error_operand: 228 | 229 | c = *p++; 230 | if (m_reg <= 1) { 231 | if (opcode == 0xf6) 232 | cflags |= C_IMM8; 233 | else if (opcode == 0xf7) 234 | cflags |= C_IMM_P66; 235 | } 236 | 237 | switch (m_mod) { 238 | case 0: 239 | if (pref & PRE_67) { 240 | if (m_rm == 6) 241 | disp_size = 2; 242 | } else 243 | if (m_rm == 5) 244 | disp_size = 4; 245 | break; 246 | case 1: 247 | disp_size = 1; 248 | break; 249 | case 2: 250 | disp_size = 2; 251 | if (!(pref & PRE_67)) 252 | disp_size <<= 1; 253 | } 254 | 255 | if (m_mod != 3 && m_rm == 4) { 256 | hs->flags |= F_SIB; 257 | p++; 258 | hs->sib = c; 259 | hs->sib_scale = c >> 6; 260 | hs->sib_index = (c & 0x3f) >> 3; 261 | if ((hs->sib_base = c & 7) == 5 && !(m_mod & 1)) 262 | disp_size = 4; 263 | } 264 | 265 | p--; 266 | switch (disp_size) { 267 | case 1: 268 | hs->flags |= F_DISP8; 269 | hs->disp.disp8 = *p; 270 | break; 271 | case 2: 272 | hs->flags |= F_DISP16; 273 | hs->disp.disp16 = *(uint16_t *)p; 274 | break; 275 | case 4: 276 | hs->flags |= F_DISP32; 277 | hs->disp.disp32 = *(uint32_t *)p; 278 | } 279 | p += disp_size; 280 | } else if (pref & PRE_LOCK) 281 | hs->flags |= F_ERROR | F_ERROR_LOCK; 282 | 283 | if (cflags & C_IMM_P66) { 284 | if (cflags & C_REL32) { 285 | if (pref & PRE_66) { 286 | hs->flags |= F_IMM16 | F_RELATIVE; 287 | hs->imm.imm16 = *(uint16_t *)p; 288 | p += 2; 289 | goto disasm_done; 290 | } 291 | goto rel32_ok; 292 | } 293 | if (op64) { 294 | hs->flags |= F_IMM64; 295 | hs->imm.imm64 = *(uint64_t *)p; 296 | p += 8; 297 | } else if (!(pref & PRE_66)) { 298 | hs->flags |= F_IMM32; 299 | hs->imm.imm32 = *(uint32_t *)p; 300 | p += 4; 301 | } else 302 | goto imm16_ok; 303 | } 304 | 305 | 306 | if (cflags & C_IMM16) { 307 | imm16_ok: 308 | hs->flags |= F_IMM16; 309 | hs->imm.imm16 = *(uint16_t *)p; 310 | p += 2; 311 | } 312 | if (cflags & C_IMM8) { 313 | hs->flags |= F_IMM8; 314 | hs->imm.imm8 = *p++; 315 | } 316 | 317 | if (cflags & C_REL32) { 318 | rel32_ok: 319 | hs->flags |= F_IMM32 | F_RELATIVE; 320 | hs->imm.imm32 = *(uint32_t *)p; 321 | p += 4; 322 | } else if (cflags & C_REL8) { 323 | hs->flags |= F_IMM8 | F_RELATIVE; 324 | hs->imm.imm8 = *p++; 325 | } 326 | 327 | disasm_done: 328 | 329 | if ((hs->len = (uint8_t)(p-(uint8_t *)code)) > 15) { 330 | hs->flags |= F_ERROR | F_ERROR_LENGTH; 331 | hs->len = 15; 332 | } 333 | 334 | return (unsigned int)hs->len; 335 | } 336 | 337 | #endif // defined(_M_X64) || defined(__x86_64__) 338 | -------------------------------------------------------------------------------- /Source/Minhook/buffer.c: -------------------------------------------------------------------------------- 1 | /* 2 | * MinHook - The Minimalistic API Hooking Library for x64/x86 3 | * Copyright (C) 2009-2017 Tsuda Kageyu. 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright 11 | * notice, this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 18 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 19 | * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 20 | * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 21 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 22 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 23 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 24 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 25 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 26 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | #include 30 | #include "buffer.h" 31 | 32 | // Size of each memory block. (= page size of VirtualAlloc) 33 | #define MEMORY_BLOCK_SIZE 0x1000 34 | 35 | // Max range for seeking a memory block. (= 1024MB) 36 | #define MAX_MEMORY_RANGE 0x40000000 37 | 38 | // Memory protection flags to check the executable address. 39 | #define PAGE_EXECUTE_FLAGS \ 40 | (PAGE_EXECUTE | PAGE_EXECUTE_READ | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY) 41 | 42 | // Memory slot. 43 | typedef struct _MEMORY_SLOT 44 | { 45 | union 46 | { 47 | struct _MEMORY_SLOT *pNext; 48 | UINT8 buffer[MEMORY_SLOT_SIZE]; 49 | }; 50 | } MEMORY_SLOT, *PMEMORY_SLOT; 51 | 52 | // Memory block info. Placed at the head of each block. 53 | typedef struct _MEMORY_BLOCK 54 | { 55 | struct _MEMORY_BLOCK *pNext; 56 | PMEMORY_SLOT pFree; // First element of the free slot list. 57 | UINT usedCount; 58 | } MEMORY_BLOCK, *PMEMORY_BLOCK; 59 | 60 | //------------------------------------------------------------------------- 61 | // Global Variables: 62 | //------------------------------------------------------------------------- 63 | 64 | // First element of the memory block list. 65 | PMEMORY_BLOCK g_pMemoryBlocks; 66 | 67 | //------------------------------------------------------------------------- 68 | VOID InitializeBuffer(VOID) 69 | { 70 | // Nothing to do for now. 71 | } 72 | 73 | //------------------------------------------------------------------------- 74 | VOID UninitializeBuffer(VOID) 75 | { 76 | PMEMORY_BLOCK pBlock = g_pMemoryBlocks; 77 | g_pMemoryBlocks = NULL; 78 | 79 | while (pBlock) 80 | { 81 | PMEMORY_BLOCK pNext = pBlock->pNext; 82 | VirtualFree(pBlock, 0, MEM_RELEASE); 83 | pBlock = pNext; 84 | } 85 | } 86 | 87 | //------------------------------------------------------------------------- 88 | #if defined(_M_X64) || defined(__x86_64__) 89 | static LPVOID FindPrevFreeRegion(LPVOID pAddress, LPVOID pMinAddr, DWORD dwAllocationGranularity) 90 | { 91 | ULONG_PTR tryAddr = (ULONG_PTR)pAddress; 92 | 93 | // Round down to the allocation granularity. 94 | tryAddr -= tryAddr % dwAllocationGranularity; 95 | 96 | // Start from the previous allocation granularity multiply. 97 | tryAddr -= dwAllocationGranularity; 98 | 99 | while (tryAddr >= (ULONG_PTR)pMinAddr) 100 | { 101 | MEMORY_BASIC_INFORMATION mbi; 102 | if (VirtualQuery((LPVOID)tryAddr, &mbi, sizeof(mbi)) == 0) 103 | break; 104 | 105 | if (mbi.State == MEM_FREE) 106 | return (LPVOID)tryAddr; 107 | 108 | if ((ULONG_PTR)mbi.AllocationBase < dwAllocationGranularity) 109 | break; 110 | 111 | tryAddr = (ULONG_PTR)mbi.AllocationBase - dwAllocationGranularity; 112 | } 113 | 114 | return NULL; 115 | } 116 | #endif 117 | 118 | //------------------------------------------------------------------------- 119 | #if defined(_M_X64) || defined(__x86_64__) 120 | static LPVOID FindNextFreeRegion(LPVOID pAddress, LPVOID pMaxAddr, DWORD dwAllocationGranularity) 121 | { 122 | ULONG_PTR tryAddr = (ULONG_PTR)pAddress; 123 | 124 | // Round down to the allocation granularity. 125 | tryAddr -= tryAddr % dwAllocationGranularity; 126 | 127 | // Start from the next allocation granularity multiply. 128 | tryAddr += dwAllocationGranularity; 129 | 130 | while (tryAddr <= (ULONG_PTR)pMaxAddr) 131 | { 132 | MEMORY_BASIC_INFORMATION mbi; 133 | if (VirtualQuery((LPVOID)tryAddr, &mbi, sizeof(mbi)) == 0) 134 | break; 135 | 136 | if (mbi.State == MEM_FREE) 137 | return (LPVOID)tryAddr; 138 | 139 | tryAddr = (ULONG_PTR)mbi.BaseAddress + mbi.RegionSize; 140 | 141 | // Round up to the next allocation granularity. 142 | tryAddr += dwAllocationGranularity - 1; 143 | tryAddr -= tryAddr % dwAllocationGranularity; 144 | } 145 | 146 | return NULL; 147 | } 148 | #endif 149 | 150 | //------------------------------------------------------------------------- 151 | static PMEMORY_BLOCK GetMemoryBlock(LPVOID pOrigin) 152 | { 153 | PMEMORY_BLOCK pBlock; 154 | #if defined(_M_X64) || defined(__x86_64__) 155 | ULONG_PTR minAddr; 156 | ULONG_PTR maxAddr; 157 | 158 | SYSTEM_INFO si; 159 | GetSystemInfo(&si); 160 | minAddr = (ULONG_PTR)si.lpMinimumApplicationAddress; 161 | maxAddr = (ULONG_PTR)si.lpMaximumApplicationAddress; 162 | 163 | // pOrigin ± 512MB 164 | if ((ULONG_PTR)pOrigin > MAX_MEMORY_RANGE && minAddr < (ULONG_PTR)pOrigin - MAX_MEMORY_RANGE) 165 | minAddr = (ULONG_PTR)pOrigin - MAX_MEMORY_RANGE; 166 | 167 | if (maxAddr > (ULONG_PTR)pOrigin + MAX_MEMORY_RANGE) 168 | maxAddr = (ULONG_PTR)pOrigin + MAX_MEMORY_RANGE; 169 | 170 | // Make room for MEMORY_BLOCK_SIZE bytes. 171 | maxAddr -= MEMORY_BLOCK_SIZE - 1; 172 | #endif 173 | 174 | // Look the registered blocks for a reachable one. 175 | for (pBlock = g_pMemoryBlocks; pBlock != NULL; pBlock = pBlock->pNext) 176 | { 177 | #if defined(_M_X64) || defined(__x86_64__) 178 | // Ignore the blocks too far. 179 | if ((ULONG_PTR)pBlock < minAddr || (ULONG_PTR)pBlock >= maxAddr) 180 | continue; 181 | #endif 182 | // The block has at least one unused slot. 183 | if (pBlock->pFree != NULL) 184 | return pBlock; 185 | } 186 | 187 | #if defined(_M_X64) || defined(__x86_64__) 188 | // Alloc a new block above if not found. 189 | { 190 | LPVOID pAlloc = pOrigin; 191 | while ((ULONG_PTR)pAlloc >= minAddr) 192 | { 193 | pAlloc = FindPrevFreeRegion(pAlloc, (LPVOID)minAddr, si.dwAllocationGranularity); 194 | if (pAlloc == NULL) 195 | break; 196 | 197 | pBlock = (PMEMORY_BLOCK)VirtualAlloc( 198 | pAlloc, MEMORY_BLOCK_SIZE, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); 199 | if (pBlock != NULL) 200 | break; 201 | } 202 | } 203 | 204 | // Alloc a new block below if not found. 205 | if (pBlock == NULL) 206 | { 207 | LPVOID pAlloc = pOrigin; 208 | while ((ULONG_PTR)pAlloc <= maxAddr) 209 | { 210 | pAlloc = FindNextFreeRegion(pAlloc, (LPVOID)maxAddr, si.dwAllocationGranularity); 211 | if (pAlloc == NULL) 212 | break; 213 | 214 | pBlock = (PMEMORY_BLOCK)VirtualAlloc( 215 | pAlloc, MEMORY_BLOCK_SIZE, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); 216 | if (pBlock != NULL) 217 | break; 218 | } 219 | } 220 | #else 221 | // In x86 mode, a memory block can be placed anywhere. 222 | pBlock = (PMEMORY_BLOCK)VirtualAlloc( 223 | NULL, MEMORY_BLOCK_SIZE, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); 224 | #endif 225 | 226 | if (pBlock != NULL) 227 | { 228 | // Build a linked list of all the slots. 229 | PMEMORY_SLOT pSlot = (PMEMORY_SLOT)pBlock + 1; 230 | pBlock->pFree = NULL; 231 | pBlock->usedCount = 0; 232 | do 233 | { 234 | pSlot->pNext = pBlock->pFree; 235 | pBlock->pFree = pSlot; 236 | pSlot++; 237 | } while ((ULONG_PTR)pSlot - (ULONG_PTR)pBlock <= MEMORY_BLOCK_SIZE - MEMORY_SLOT_SIZE); 238 | 239 | pBlock->pNext = g_pMemoryBlocks; 240 | g_pMemoryBlocks = pBlock; 241 | } 242 | 243 | return pBlock; 244 | } 245 | 246 | //------------------------------------------------------------------------- 247 | LPVOID AllocateBuffer(LPVOID pOrigin) 248 | { 249 | PMEMORY_SLOT pSlot; 250 | PMEMORY_BLOCK pBlock = GetMemoryBlock(pOrigin); 251 | if (pBlock == NULL) 252 | return NULL; 253 | 254 | // Remove an unused slot from the list. 255 | pSlot = pBlock->pFree; 256 | pBlock->pFree = pSlot->pNext; 257 | pBlock->usedCount++; 258 | #ifdef _DEBUG 259 | // Fill the slot with INT3 for debugging. 260 | memset(pSlot, 0xCC, sizeof(MEMORY_SLOT)); 261 | #endif 262 | return pSlot; 263 | } 264 | 265 | //------------------------------------------------------------------------- 266 | VOID FreeBuffer(LPVOID pBuffer) 267 | { 268 | PMEMORY_BLOCK pBlock = g_pMemoryBlocks; 269 | PMEMORY_BLOCK pPrev = NULL; 270 | ULONG_PTR pTargetBlock = ((ULONG_PTR)pBuffer / MEMORY_BLOCK_SIZE) * MEMORY_BLOCK_SIZE; 271 | 272 | while (pBlock != NULL) 273 | { 274 | if ((ULONG_PTR)pBlock == pTargetBlock) 275 | { 276 | PMEMORY_SLOT pSlot = (PMEMORY_SLOT)pBuffer; 277 | #ifdef _DEBUG 278 | // Clear the released slot for debugging. 279 | memset(pSlot, 0x00, sizeof(*pSlot)); 280 | #endif 281 | // Restore the released slot to the list. 282 | pSlot->pNext = pBlock->pFree; 283 | pBlock->pFree = pSlot; 284 | pBlock->usedCount--; 285 | 286 | // Free if unused. 287 | if (pBlock->usedCount == 0) 288 | { 289 | if (pPrev) 290 | pPrev->pNext = pBlock->pNext; 291 | else 292 | g_pMemoryBlocks = pBlock->pNext; 293 | 294 | VirtualFree(pBlock, 0, MEM_RELEASE); 295 | } 296 | 297 | break; 298 | } 299 | 300 | pPrev = pBlock; 301 | pBlock = pBlock->pNext; 302 | } 303 | } 304 | 305 | //------------------------------------------------------------------------- 306 | BOOL IsExecutableAddress(LPVOID pAddress) 307 | { 308 | MEMORY_BASIC_INFORMATION mi; 309 | VirtualQuery(pAddress, &mi, sizeof(mi)); 310 | 311 | return (mi.State == MEM_COMMIT && (mi.Protect & PAGE_EXECUTE_FLAGS)); 312 | } 313 | -------------------------------------------------------------------------------- /Source/Main/PostureBarUI.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "../Common.hpp" 3 | 4 | namespace ER 5 | { 6 | enum class EPostureBarType 7 | { 8 | Entity, 9 | Boss 10 | }; 11 | 12 | enum class EERDataType 13 | { 14 | Stagger, 15 | Stamina, 16 | STATUSES, 17 | Poison, 18 | Rot, 19 | Bleed, 20 | Blight, 21 | Frost, 22 | Sleep, 23 | Madness, 24 | MAX, 25 | }; 26 | 27 | inline std::string to_string(const EERDataType erDataType) 28 | { 29 | switch (erDataType) 30 | { 31 | case EERDataType::Stagger: 32 | return "Stagger"; 33 | case EERDataType::Stamina: 34 | return "Stamina"; 35 | case EERDataType::Poison: 36 | return "Poison"; 37 | case EERDataType::Rot: 38 | return "Rot"; 39 | case EERDataType::Bleed: 40 | return "Bleed"; 41 | case EERDataType::Blight: 42 | return "Blight"; 43 | case EERDataType::Frost: 44 | return "Frost"; 45 | case EERDataType::Sleep: 46 | return "Sleep"; 47 | case EERDataType::Madness: 48 | return "Madness"; 49 | default: 50 | return ""; 51 | } 52 | } 53 | 54 | struct BarData 55 | { 56 | float value = 0.0f; 57 | float maxValue = 0.0f; 58 | 59 | void SetValue(float inValue, float inMaxValue) { value = inValue, maxValue = inMaxValue; }; 60 | void SetValue(int inValue, int inMaxValue) { value = static_cast(inValue), maxValue = static_cast(inMaxValue); }; 61 | void SetInverseValue(int inValue, int inMaxValue) { maxValue = static_cast(inMaxValue); value = maxValue - static_cast(inValue); }; 62 | float GetRatio() { return value / maxValue; } 63 | bool IsValueMax() { return value == maxValue; } 64 | }; 65 | 66 | struct PlayerPostureBarData 67 | { 68 | float maxStagger = 0.0f; 69 | float stagger = 0.0f; 70 | 71 | // Stagger reset 72 | float previousStagger = 1.0f; // set to 1, as 0 would conflict with checking for posture break 73 | bool isResetStagger = false; 74 | float resetStaggerTimer = 0.0f; 75 | std::chrono::steady_clock::time_point lastTimePoint{}; 76 | 77 | static inline bool drawBar = true; 78 | static inline float barWidth = 286.0f; 79 | static inline float barHeight = 28.0f; 80 | static inline float resetStaggerTotalTime = 2.0f; 81 | static inline float screenX = 963.0f; 82 | static inline float screenY = 100.0f; 83 | 84 | #ifdef DEBUGLOG 85 | void LogDebug(); 86 | #endif 87 | }; 88 | 89 | struct BossPostureBarData 90 | { 91 | unsigned long long entityHandle = 0; 92 | int displayId = -1; 93 | bool isStamina = false; 94 | bool isVisible = false; 95 | 96 | std::map barDatas = make_map(); 97 | 98 | // Stagger reset 99 | float previousStagger = 1.0f; // set to 1, as 0 would conflict with checking for posture break 100 | bool isResetStagger = false; 101 | float resetStaggerTimer = 0.0f; 102 | std::chrono::steady_clock::time_point lastTimePoint{}; 103 | 104 | static inline bool drawBars = true; 105 | static inline bool useStaminaForNPC = true; 106 | static inline float barWidth = 998.0f; 107 | static inline float barHeight = 16.0f; 108 | static inline float resetStaggerTotalTime = 2.0f; 109 | static inline float firstBossScreenX = 963.0f; 110 | static inline float firstBossScreenY = 945.0f; 111 | static inline float nextBossBarDiffScreenY = 55.0f; 112 | 113 | // Status bars 114 | static inline bool drawStatusBars = false; 115 | static inline float statusBarWidth = 1020.0f; 116 | static inline float statusBarHeight = 16.0f; 117 | static inline float firstStatusBarDiffScreenY = 16.0f; 118 | static inline float nextStatusBarDiffScreenY = 16.0f; 119 | 120 | static inline std::map drawBar = make_map(); 121 | 122 | #ifdef DEBUGLOG 123 | void LogDebug(); 124 | #endif 125 | }; 126 | 127 | struct EntityPostureBarData 128 | { 129 | unsigned long long entityHandle = 0; 130 | bool isStamina = false; 131 | bool isVisible = false; 132 | float screenX = 0.0f; 133 | float screenY = 0.0f; 134 | float distanceModifier = 0.0f; 135 | 136 | // Position Fixing by movement velocity 137 | float previousScreenX = -1.0f; 138 | float previousScreenY = -1.0f; 139 | std::chrono::steady_clock::time_point gameUiUpdateTimePoint{}; 140 | std::chrono::steady_clock::time_point gamePreviousUiUpdateTimePoint{}; 141 | 142 | std::map barDatas = make_map(); 143 | 144 | // Stagger reset 145 | float previousStagger = 1.0f; // set to 1, as 0 would conflict with checking for posture break 146 | bool isResetStagger = false; 147 | float resetStaggerTimer = 0.0f; 148 | std::chrono::steady_clock::time_point lastTimePoint{}; 149 | 150 | static inline bool drawBars = true; 151 | static inline bool useStaminaForNPC = true; 152 | static inline float barWidth = 138.0f; 153 | static inline float barHeight = 5.0f; 154 | static inline float resetStaggerTotalTime = 2.0f; 155 | static inline float offsetScreenX = -1.0f; 156 | static inline float offsetScreenY = -10.0f; 157 | static inline float leftScreenThreshold = 130.0f; 158 | static inline float rightScreenThreshold = 1790.0f; 159 | static inline float topScreenThreshold = 175.0f; 160 | static inline float bottomScreenThreshold = 990.0f; 161 | static inline bool usePositionFixing = true; 162 | static inline double positionFixingMultiplierX = 10.0f; 163 | static inline double positionFixingMultiplierY = 10.0f; 164 | 165 | // Status bars 166 | static inline bool drawStatusBars = false; 167 | static inline float statusBarWidth = 143.0f; 168 | static inline float statusBarHeight = 14.0f; 169 | static inline float firstStatusBarDiffScreenY = 14.0f; 170 | static inline float nextStatusBarDiffScreenY = 14.0f; 171 | 172 | static inline std::map drawBar = make_map(); 173 | 174 | #ifdef DEBUGLOG 175 | void LogDebug(); 176 | #endif 177 | }; 178 | 179 | struct ScreenParams 180 | { 181 | static inline float inGameCoordSizeX = 1920.0f; 182 | static inline float inGameCoordSizeY = 1080.0f; 183 | static inline float posX = 0.0f; 184 | static inline float posY = 0.0f; 185 | static inline float gameToViewportScaling = 1.0f; 186 | static inline bool autoPositionSetup = true; 187 | static inline bool autoGameToViewportScaling = true; 188 | }; 189 | 190 | enum class EFillAlignment : uint_fast8_t 191 | { 192 | Left, 193 | Center, 194 | Right, 195 | Last 196 | }; 197 | 198 | enum class EFillType : uint_fast8_t 199 | { 200 | FullToEmpty, 201 | EmptyToFull, 202 | Last 203 | }; 204 | 205 | enum class EFillResizeType : uint_fast8_t 206 | { 207 | Clip, 208 | Scale, 209 | Last 210 | }; 211 | 212 | struct BarStyle 213 | { 214 | static inline EFillAlignment fillAlignment = EFillAlignment::Left; 215 | static inline EFillType fillType = EFillType::FullToEmpty; 216 | static inline EFillResizeType fillResizeType = EFillResizeType::Clip; 217 | static inline ImVec4 staggerMaxColor = { 255, 255, 0, 255 }; 218 | static inline ImVec4 staggerMinColor = { 255, 255, 0, 255 }; 219 | static inline ImVec4 staminaMaxColor = { 80, 200, 104, 255 }; 220 | static inline ImVec4 staminaMinColor = { 80, 200, 104, 255 }; 221 | 222 | static inline ImVec4 poisonMaxColor = { 100, 250, 85, 255 }; 223 | static inline ImVec4 poisonMinColor = { 100, 250, 85, 255 }; 224 | static inline ImVec4 rotMaxColor = { 255, 127, 0, 255 }; 225 | static inline ImVec4 rotMinColor = { 255, 127, 0, 255 }; 226 | static inline ImVec4 bleedMaxColor = { 255, 0, 0, 255 }; 227 | static inline ImVec4 bleedMinColor = { 255, 0, 0, 255 }; 228 | static inline ImVec4 blightMaxColor = { 200, 200, 0, 255 }; 229 | static inline ImVec4 blightMinColor = { 200, 200, 0, 255 }; 230 | static inline ImVec4 frostMaxColor = { 40, 225, 255, 255 }; 231 | static inline ImVec4 frostMinColor = { 40, 225, 255, 255 }; 232 | static inline ImVec4 sleepMaxColor = { 240, 0, 200, 255 }; 233 | static inline ImVec4 sleepMinColor = { 240, 0, 200, 255 }; 234 | static inline ImVec4 madnessMaxColor = { 255, 255, 0, 255 }; 235 | static inline ImVec4 madnessMinColor = { 255, 255, 0, 255 }; 236 | }; 237 | 238 | typedef std::pair FillTextureOffset; 239 | 240 | struct TextureData 241 | { 242 | ImTextureID texture = nullptr; 243 | float width = 0.0f; 244 | float height = 0.0f; 245 | 246 | static inline bool useTextures = true; 247 | static inline FillTextureOffset bossOffset = { {0.0f, 0.0f}, {0.0f, 0.0f} }; 248 | static inline FillTextureOffset entityOffset = { {0.0f, 0.0f}, {0.0f, 0.0f} }; 249 | }; 250 | 251 | typedef std::pair TextureBar; 252 | 253 | class PostureBarUI 254 | { 255 | public: 256 | PostureBarUI() noexcept = default; 257 | ~PostureBarUI() noexcept = default; 258 | PostureBarUI(PostureBarUI const&) = delete; 259 | PostureBarUI(PostureBarUI&&) = delete; 260 | PostureBarUI& operator=(PostureBarUI const&) = delete; 261 | PostureBarUI& operator=(PostureBarUI&&) = delete; 262 | 263 | // Draws UI posture bars, use after starting imgui new frame 264 | void Draw(); 265 | ImColor getBarColor(EERDataType StatusEffectType, float fillRatio); 266 | std::pair getMinMaxColor(EERDataType StatusEffectType); 267 | void drawBar(const EPostureBarType postureBarType, const EERDataType statusEffectType, const ImVec2& position, const ImVec2& size, float fillRatio); 268 | void drawBar(const TextureBar& textureBar, const ImColor& color, const ImVec2& position, const ImVec2& size, const std::pair& fillOffset, float fillRatio); 269 | void drawBar(const ImColor& color, const ImVec2& position, const ImVec2& size, float fillRatio); 270 | 271 | bool isMenuOpen(); 272 | 273 | // Hooked func on update of in game UI bars 274 | static void updateUIBarStructs(uintptr_t moveMapStep, uintptr_t time); 275 | static inline void (*updateUIBarStructsOriginal)(uintptr_t, uintptr_t); 276 | 277 | std::optional playerPostureBar = std::nullopt; 278 | std::array, ENTITY_CHR_ARRAY_LEN> entityPostureBars = make_array, ENTITY_CHR_ARRAY_LEN>(std::nullopt); 279 | std::array, BOSS_CHR_ARRAY_LEN> bossPostureBars = make_array, BOSS_CHR_ARRAY_LEN>(std::nullopt); 280 | 281 | TextureBar entityBarTexture; 282 | TextureBar bossBarTexture; 283 | bool textureBarInit = false; 284 | }; 285 | 286 | inline std::unique_ptr g_postureUI; 287 | }; -------------------------------------------------------------------------------- /Source/Minhook/trampoline.c: -------------------------------------------------------------------------------- 1 | /* 2 | * MinHook - The Minimalistic API Hooking Library for x64/x86 3 | * Copyright (C) 2009-2017 Tsuda Kageyu. 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright 11 | * notice, this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 18 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 19 | * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 20 | * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 21 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 22 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 23 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 24 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 25 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 26 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | #include 30 | 31 | #ifndef ARRAYSIZE 32 | #define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0])) 33 | #endif 34 | 35 | #if defined(_M_X64) || defined(__x86_64__) 36 | #include "hde64.h" 37 | typedef hde64s HDE; 38 | #define HDE_DISASM(code, hs) hde64_disasm(code, hs) 39 | #else 40 | #include "./hde/hde32.h" 41 | typedef hde32s HDE; 42 | #define HDE_DISASM(code, hs) hde32_disasm(code, hs) 43 | #endif 44 | 45 | #include "trampoline.h" 46 | #include "buffer.h" 47 | 48 | // Maximum size of a trampoline function. 49 | #if defined(_M_X64) || defined(__x86_64__) 50 | #define TRAMPOLINE_MAX_SIZE (MEMORY_SLOT_SIZE - sizeof(JMP_ABS)) 51 | #else 52 | #define TRAMPOLINE_MAX_SIZE MEMORY_SLOT_SIZE 53 | #endif 54 | 55 | //------------------------------------------------------------------------- 56 | static BOOL IsCodePadding(LPBYTE pInst, UINT size) 57 | { 58 | UINT i; 59 | 60 | if (pInst[0] != 0x00 && pInst[0] != 0x90 && pInst[0] != 0xCC) 61 | return FALSE; 62 | 63 | for (i = 1; i < size; ++i) 64 | { 65 | if (pInst[i] != pInst[0]) 66 | return FALSE; 67 | } 68 | return TRUE; 69 | } 70 | 71 | //------------------------------------------------------------------------- 72 | BOOL CreateTrampolineFunction(PTRAMPOLINE ct) 73 | { 74 | #if defined(_M_X64) || defined(__x86_64__) 75 | CALL_ABS call = { 76 | 0xFF, 0x15, 0x00000002, // FF15 00000002: CALL [RIP+8] 77 | 0xEB, 0x08, // EB 08: JMP +10 78 | 0x0000000000000000ULL // Absolute destination address 79 | }; 80 | JMP_ABS jmp = { 81 | 0xFF, 0x25, 0x00000000, // FF25 00000000: JMP [RIP+6] 82 | 0x0000000000000000ULL // Absolute destination address 83 | }; 84 | JCC_ABS jcc = { 85 | 0x70, 0x0E, // 7* 0E: J** +16 86 | 0xFF, 0x25, 0x00000000, // FF25 00000000: JMP [RIP+6] 87 | 0x0000000000000000ULL // Absolute destination address 88 | }; 89 | #else 90 | CALL_REL call = { 91 | 0xE8, // E8 xxxxxxxx: CALL +5+xxxxxxxx 92 | 0x00000000 // Relative destination address 93 | }; 94 | JMP_REL jmp = { 95 | 0xE9, // E9 xxxxxxxx: JMP +5+xxxxxxxx 96 | 0x00000000 // Relative destination address 97 | }; 98 | JCC_REL jcc = { 99 | 0x0F, 0x80, // 0F8* xxxxxxxx: J** +6+xxxxxxxx 100 | 0x00000000 // Relative destination address 101 | }; 102 | #endif 103 | 104 | UINT8 oldPos = 0; 105 | UINT8 newPos = 0; 106 | ULONG_PTR jmpDest = 0; // Destination address of an internal jump. 107 | BOOL finished = FALSE; // Is the function completed? 108 | #if defined(_M_X64) || defined(__x86_64__) 109 | UINT8 instBuf[16]; 110 | #endif 111 | 112 | ct->patchAbove = FALSE; 113 | ct->nIP = 0; 114 | 115 | do 116 | { 117 | HDE hs; 118 | UINT copySize; 119 | LPVOID pCopySrc; 120 | ULONG_PTR pOldInst = (ULONG_PTR)ct->pTarget + oldPos; 121 | ULONG_PTR pNewInst = (ULONG_PTR)ct->pTrampoline + newPos; 122 | 123 | copySize = HDE_DISASM((LPVOID)pOldInst, &hs); 124 | if (hs.flags & F_ERROR) 125 | return FALSE; 126 | 127 | pCopySrc = (LPVOID)pOldInst; 128 | if (oldPos >= sizeof(JMP_REL)) 129 | { 130 | // The trampoline function is long enough. 131 | // Complete the function with the jump to the target function. 132 | #if defined(_M_X64) || defined(__x86_64__) 133 | jmp.address = pOldInst; 134 | #else 135 | jmp.operand = (UINT32)(pOldInst - (pNewInst + sizeof(jmp))); 136 | #endif 137 | pCopySrc = &jmp; 138 | copySize = sizeof(jmp); 139 | 140 | finished = TRUE; 141 | } 142 | #if defined(_M_X64) || defined(__x86_64__) 143 | else if ((hs.modrm & 0xC7) == 0x05) 144 | { 145 | // Instructions using RIP relative addressing. (ModR/M = 00???101B) 146 | 147 | // Modify the RIP relative address. 148 | PUINT32 pRelAddr; 149 | 150 | // Avoid using memcpy to reduce the footprint. 151 | #ifndef _MSC_VER 152 | memcpy(instBuf, (LPBYTE)pOldInst, copySize); 153 | #else 154 | __movsb(instBuf, (LPBYTE)pOldInst, copySize); 155 | #endif 156 | pCopySrc = instBuf; 157 | 158 | // Relative address is stored at (instruction length - immediate value length - 4). 159 | pRelAddr = (PUINT32)(instBuf + hs.len - ((hs.flags & 0x3C) >> 2) - 4); 160 | *pRelAddr 161 | = (UINT32)((pOldInst + hs.len + (INT32)hs.disp.disp32) - (pNewInst + hs.len)); 162 | 163 | // Complete the function if JMP (FF /4). 164 | if (hs.opcode == 0xFF && hs.modrm_reg == 4) 165 | finished = TRUE; 166 | } 167 | #endif 168 | else if (hs.opcode == 0xE8) 169 | { 170 | // Direct relative CALL 171 | ULONG_PTR dest = pOldInst + hs.len + (INT32)hs.imm.imm32; 172 | #if defined(_M_X64) || defined(__x86_64__) 173 | call.address = dest; 174 | #else 175 | call.operand = (UINT32)(dest - (pNewInst + sizeof(call))); 176 | #endif 177 | pCopySrc = &call; 178 | copySize = sizeof(call); 179 | } 180 | else if ((hs.opcode & 0xFD) == 0xE9) 181 | { 182 | // Direct relative JMP (EB or E9) 183 | ULONG_PTR dest = pOldInst + hs.len; 184 | 185 | if (hs.opcode == 0xEB) // isShort jmp 186 | dest += (INT8)hs.imm.imm8; 187 | else 188 | dest += (INT32)hs.imm.imm32; 189 | 190 | // Simply copy an internal jump. 191 | if ((ULONG_PTR)ct->pTarget <= dest 192 | && dest < ((ULONG_PTR)ct->pTarget + sizeof(JMP_REL))) 193 | { 194 | if (jmpDest < dest) 195 | jmpDest = dest; 196 | } 197 | else 198 | { 199 | #if defined(_M_X64) || defined(__x86_64__) 200 | jmp.address = dest; 201 | #else 202 | jmp.operand = (UINT32)(dest - (pNewInst + sizeof(jmp))); 203 | #endif 204 | pCopySrc = &jmp; 205 | copySize = sizeof(jmp); 206 | 207 | // Exit the function If it is not in the branch 208 | finished = (pOldInst >= jmpDest); 209 | } 210 | } 211 | else if ((hs.opcode & 0xF0) == 0x70 212 | || (hs.opcode & 0xFC) == 0xE0 213 | || (hs.opcode2 & 0xF0) == 0x80) 214 | { 215 | // Direct relative Jcc 216 | ULONG_PTR dest = pOldInst + hs.len; 217 | 218 | if ((hs.opcode & 0xF0) == 0x70 // Jcc 219 | || (hs.opcode & 0xFC) == 0xE0) // LOOPNZ/LOOPZ/LOOP/JECXZ 220 | dest += (INT8)hs.imm.imm8; 221 | else 222 | dest += (INT32)hs.imm.imm32; 223 | 224 | // Simply copy an internal jump. 225 | if ((ULONG_PTR)ct->pTarget <= dest 226 | && dest < ((ULONG_PTR)ct->pTarget + sizeof(JMP_REL))) 227 | { 228 | if (jmpDest < dest) 229 | jmpDest = dest; 230 | } 231 | else if ((hs.opcode & 0xFC) == 0xE0) 232 | { 233 | // LOOPNZ/LOOPZ/LOOP/JCXZ/JECXZ to the outside are not supported. 234 | return FALSE; 235 | } 236 | else 237 | { 238 | UINT8 cond = ((hs.opcode != 0x0F ? hs.opcode : hs.opcode2) & 0x0F); 239 | #if defined(_M_X64) || defined(__x86_64__) 240 | // Invert the condition in x64 mode to simplify the conditional jump logic. 241 | jcc.opcode = 0x71 ^ cond; 242 | jcc.address = dest; 243 | #else 244 | jcc.opcode1 = 0x80 | cond; 245 | jcc.operand = (UINT32)(dest - (pNewInst + sizeof(jcc))); 246 | #endif 247 | pCopySrc = &jcc; 248 | copySize = sizeof(jcc); 249 | } 250 | } 251 | else if ((hs.opcode & 0xFE) == 0xC2) 252 | { 253 | // RET (C2 or C3) 254 | 255 | // Complete the function if not in a branch. 256 | finished = (pOldInst >= jmpDest); 257 | } 258 | 259 | // Can't alter the instruction length in a branch. 260 | if (pOldInst < jmpDest && copySize != hs.len) 261 | return FALSE; 262 | 263 | // Trampoline function is too large. 264 | if ((newPos + copySize) > TRAMPOLINE_MAX_SIZE) 265 | return FALSE; 266 | 267 | // Trampoline function has too many instructions. 268 | if (ct->nIP >= ARRAYSIZE(ct->oldIPs)) 269 | return FALSE; 270 | 271 | ct->oldIPs[ct->nIP] = oldPos; 272 | ct->newIPs[ct->nIP] = newPos; 273 | ct->nIP++; 274 | 275 | // Avoid using memcpy to reduce the footprint. 276 | #ifndef _MSC_VER 277 | memcpy((LPBYTE)ct->pTrampoline + newPos, pCopySrc, copySize); 278 | #else 279 | __movsb((LPBYTE)ct->pTrampoline + newPos, pCopySrc, copySize); 280 | #endif 281 | newPos += copySize; 282 | oldPos += hs.len; 283 | } 284 | while (!finished); 285 | 286 | // Is there enough place for a long jump? 287 | if (oldPos < sizeof(JMP_REL) 288 | && !IsCodePadding((LPBYTE)ct->pTarget + oldPos, sizeof(JMP_REL) - oldPos)) 289 | { 290 | // Is there enough place for a short jump? 291 | if (oldPos < sizeof(JMP_REL_SHORT) 292 | && !IsCodePadding((LPBYTE)ct->pTarget + oldPos, sizeof(JMP_REL_SHORT) - oldPos)) 293 | { 294 | return FALSE; 295 | } 296 | 297 | // Can we place the long jump above the function? 298 | if (!IsExecutableAddress((LPBYTE)ct->pTarget - sizeof(JMP_REL))) 299 | return FALSE; 300 | 301 | if (!IsCodePadding((LPBYTE)ct->pTarget - sizeof(JMP_REL), sizeof(JMP_REL))) 302 | return FALSE; 303 | 304 | ct->patchAbove = TRUE; 305 | } 306 | 307 | #if defined(_M_X64) || defined(__x86_64__) 308 | // Create a relay function. 309 | jmp.address = (ULONG_PTR)ct->pDetour; 310 | 311 | ct->pRelay = (LPBYTE)ct->pTrampoline + newPos; 312 | memcpy(ct->pRelay, &jmp, sizeof(jmp)); 313 | #endif 314 | 315 | return TRUE; 316 | } 317 | -------------------------------------------------------------------------------- /PostureBarMod.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release Debug Logger 10 | Win32 11 | 12 | 13 | Release Debug Logger 14 | x64 15 | 16 | 17 | Release 18 | Win32 19 | 20 | 21 | Debug 22 | x64 23 | 24 | 25 | Release 26 | x64 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 16.0 80 | Win32Proj 81 | {6ae54742-b82d-4a3e-9048-76868b06cb22} 82 | PostureBarMod 83 | 10.0 84 | 85 | 86 | 87 | DynamicLibrary 88 | true 89 | v143 90 | Unicode 91 | 92 | 93 | DynamicLibrary 94 | false 95 | v143 96 | true 97 | Unicode 98 | 99 | 100 | DynamicLibrary 101 | false 102 | v143 103 | true 104 | Unicode 105 | 106 | 107 | DynamicLibrary 108 | true 109 | v143 110 | MultiByte 111 | 112 | 113 | DynamicLibrary 114 | false 115 | v143 116 | false 117 | MultiByte 118 | 119 | 120 | DynamicLibrary 121 | false 122 | v143 123 | false 124 | MultiByte 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | false 152 | 153 | 154 | false 155 | 156 | 157 | false 158 | 159 | 160 | 161 | Level3 162 | true 163 | WIN32;_DEBUG;POSTUREBARMOD_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) 164 | true 165 | Use 166 | pch.h 167 | 168 | 169 | Windows 170 | true 171 | false 172 | 173 | 174 | 175 | 176 | Level3 177 | true 178 | true 179 | true 180 | WIN32;NDEBUG;POSTUREBARMOD_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) 181 | true 182 | Use 183 | pch.h 184 | 185 | 186 | Windows 187 | true 188 | true 189 | true 190 | false 191 | 192 | 193 | 194 | 195 | Level3 196 | true 197 | true 198 | true 199 | WIN32;NDEBUG;POSTUREBARMOD_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) 200 | true 201 | Use 202 | pch.h 203 | 204 | 205 | Windows 206 | true 207 | true 208 | true 209 | false 210 | 211 | 212 | 213 | 214 | Level3 215 | true 216 | _DEBUG;DEBUGLOG;POSTUREBARMOD_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) 217 | true 218 | NotUsing 219 | pch.h 220 | stdcpplatest 221 | ProgramDatabase 222 | 223 | 224 | Windows 225 | true 226 | false 227 | 228 | 229 | 230 | 231 | Level3 232 | true 233 | false 234 | true 235 | NDEBUG;POSTUREBARMOD_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) 236 | true 237 | NotUsing 238 | pch.h 239 | stdcpplatest 240 | ProgramDatabase 241 | 242 | 243 | Windows 244 | true 245 | true 246 | true 247 | false 248 | 249 | 250 | 251 | 252 | Level3 253 | true 254 | false 255 | true 256 | NDEBUG;DEBUGLOG;POSTUREBARMOD_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) 257 | true 258 | NotUsing 259 | pch.h 260 | stdcpplatest 261 | ProgramDatabase 262 | 263 | 264 | Windows 265 | true 266 | true 267 | true 268 | false 269 | 270 | 271 | 272 | 273 | 274 | -------------------------------------------------------------------------------- /Source/Ini/ini.h: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * Copyright (c) 2018 Danijel Durakovic 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | * this software and associated documentation files (the "Software"), to deal in 7 | * the Software without restriction, including without limitation the rights to 8 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 9 | * of the Software, and to permit persons to whom the Software is furnished to do 10 | * so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in all 13 | * copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | * 22 | */ 23 | 24 | /////////////////////////////////////////////////////////////////////////////// 25 | // 26 | // /mINI/ v0.9.11 27 | // An INI file reader and writer for the modern age. 28 | // 29 | /////////////////////////////////////////////////////////////////////////////// 30 | // 31 | // A tiny utility library for manipulating INI files with a straightforward 32 | // API and a minimal footprint. It conforms to the (somewhat) standard INI 33 | // format - sections and keys are case insensitive and all leading and 34 | // trailing whitespace is ignored. Comments are lines that begin with a 35 | // semicolon. Trailing comments are allowed on section lines. 36 | // 37 | // Files are read on demand, upon which data is kept in memory and the file 38 | // is closed. This utility supports lazy writing, which only writes changes 39 | // and updates to a file and preserves custom formatting and comments. A lazy 40 | // write invoked by a write() call will read the output file, find what 41 | // changes have been made and update the file accordingly. If you only need to 42 | // generate files, use generate() instead. Section and key order is preserved 43 | // on read, write and insert. 44 | // 45 | /////////////////////////////////////////////////////////////////////////////// 46 | // 47 | // /* BASIC USAGE EXAMPLE: */ 48 | // 49 | // /* read from file */ 50 | // mINI::INIFile file("myfile.ini"); 51 | // mINI::INIStructure ini; 52 | // file.read(ini); 53 | // 54 | // /* read value; gets a reference to actual value in the structure. 55 | // if key or section don't exist, a new empty value will be created */ 56 | // std::string& value = ini["section"]["key"]; 57 | // 58 | // /* read value safely; gets a copy of value in the structure. 59 | // does not alter the structure */ 60 | // std::string value = ini.get("section").get("key"); 61 | // 62 | // /* set or update values */ 63 | // ini["section"]["key"] = "value"; 64 | // 65 | // /* set multiple values */ 66 | // ini["section2"].set({ 67 | // {"key1", "value1"}, 68 | // {"key2", "value2"} 69 | // }); 70 | // 71 | // /* write updates back to file, preserving comments and formatting */ 72 | // file.write(ini); 73 | // 74 | // /* or generate a file (overwrites the original) */ 75 | // file.generate(ini); 76 | // 77 | /////////////////////////////////////////////////////////////////////////////// 78 | // 79 | // Long live the INI file!!! 80 | // 81 | /////////////////////////////////////////////////////////////////////////////// 82 | 83 | #ifndef MINI_INI_H_ 84 | #define MINI_INI_H_ 85 | 86 | #include 87 | #include 88 | #include 89 | #include 90 | #include 91 | #include 92 | #include 93 | #include 94 | #include 95 | #include 96 | 97 | namespace mINI 98 | { 99 | namespace INIStringUtil 100 | { 101 | const char* const whitespaceDelimiters = " \t\n\r\f\v"; 102 | inline void trim(std::string& str) 103 | { 104 | str.erase(str.find_last_not_of(whitespaceDelimiters) + 1); 105 | str.erase(0, str.find_first_not_of(whitespaceDelimiters)); 106 | } 107 | #ifndef MINI_CASE_SENSITIVE 108 | inline void toLower(std::string& str) 109 | { 110 | std::transform(str.begin(), str.end(), str.begin(), [](const char c) { 111 | return static_cast(std::tolower(c)); 112 | }); 113 | } 114 | #endif 115 | inline void replace(std::string& str, std::string const& a, std::string const& b) 116 | { 117 | if (!a.empty()) 118 | { 119 | std::size_t pos = 0; 120 | while ((pos = str.find(a, pos)) != std::string::npos) 121 | { 122 | str.replace(pos, a.size(), b); 123 | pos += b.size(); 124 | } 125 | } 126 | } 127 | #ifdef _WIN32 128 | const char* const endl = "\r\n"; 129 | #else 130 | const char* const endl = "\n"; 131 | #endif 132 | } 133 | 134 | template 135 | class INIMap 136 | { 137 | private: 138 | using T_DataIndexMap = std::unordered_map; 139 | using T_DataItem = std::pair; 140 | using T_DataContainer = std::vector; 141 | using T_MultiArgs = typename std::vector>; 142 | 143 | T_DataIndexMap dataIndexMap; 144 | T_DataContainer data; 145 | 146 | inline std::size_t setEmpty(std::string& key) 147 | { 148 | std::size_t index = data.size(); 149 | dataIndexMap[key] = index; 150 | data.emplace_back(key, T()); 151 | return index; 152 | } 153 | 154 | public: 155 | using const_iterator = typename T_DataContainer::const_iterator; 156 | 157 | INIMap() { } 158 | 159 | INIMap(INIMap const& other) 160 | { 161 | std::size_t data_size = other.data.size(); 162 | for (std::size_t i = 0; i < data_size; ++i) 163 | { 164 | auto const& key = other.data[i].first; 165 | auto const& obj = other.data[i].second; 166 | data.emplace_back(key, obj); 167 | } 168 | dataIndexMap = T_DataIndexMap(other.dataIndexMap); 169 | } 170 | 171 | T& operator[](std::string key) 172 | { 173 | INIStringUtil::trim(key); 174 | #ifndef MINI_CASE_SENSITIVE 175 | INIStringUtil::toLower(key); 176 | #endif 177 | auto it = dataIndexMap.find(key); 178 | bool hasIt = (it != dataIndexMap.end()); 179 | std::size_t index = (hasIt) ? it->second : setEmpty(key); 180 | return data[index].second; 181 | } 182 | T get(std::string key) const 183 | { 184 | INIStringUtil::trim(key); 185 | #ifndef MINI_CASE_SENSITIVE 186 | INIStringUtil::toLower(key); 187 | #endif 188 | auto it = dataIndexMap.find(key); 189 | if (it == dataIndexMap.end()) 190 | { 191 | return T(); 192 | } 193 | return T(data[it->second].second); 194 | } 195 | bool has(std::string key) const 196 | { 197 | INIStringUtil::trim(key); 198 | #ifndef MINI_CASE_SENSITIVE 199 | INIStringUtil::toLower(key); 200 | #endif 201 | return (dataIndexMap.count(key) == 1); 202 | } 203 | void set(std::string key, T obj) 204 | { 205 | INIStringUtil::trim(key); 206 | #ifndef MINI_CASE_SENSITIVE 207 | INIStringUtil::toLower(key); 208 | #endif 209 | auto it = dataIndexMap.find(key); 210 | if (it != dataIndexMap.end()) 211 | { 212 | data[it->second].second = obj; 213 | } 214 | else 215 | { 216 | dataIndexMap[key] = data.size(); 217 | data.emplace_back(key, obj); 218 | } 219 | } 220 | void set(T_MultiArgs const& multiArgs) 221 | { 222 | for (auto const& it : multiArgs) 223 | { 224 | auto const& key = it.first; 225 | auto const& obj = it.second; 226 | set(key, obj); 227 | } 228 | } 229 | bool remove(std::string key) 230 | { 231 | INIStringUtil::trim(key); 232 | #ifndef MINI_CASE_SENSITIVE 233 | INIStringUtil::toLower(key); 234 | #endif 235 | auto it = dataIndexMap.find(key); 236 | if (it != dataIndexMap.end()) 237 | { 238 | std::size_t index = it->second; 239 | data.erase(data.begin() + index); 240 | dataIndexMap.erase(it); 241 | for (auto& it2 : dataIndexMap) 242 | { 243 | auto& vi = it2.second; 244 | if (vi > index) 245 | { 246 | vi--; 247 | } 248 | } 249 | return true; 250 | } 251 | return false; 252 | } 253 | void clear() 254 | { 255 | data.clear(); 256 | dataIndexMap.clear(); 257 | } 258 | std::size_t size() const 259 | { 260 | return data.size(); 261 | } 262 | const_iterator begin() const { return data.begin(); } 263 | const_iterator end() const { return data.end(); } 264 | }; 265 | 266 | using INIStructure = INIMap>; 267 | 268 | namespace INIParser 269 | { 270 | using T_ParseValues = std::pair; 271 | 272 | enum class PDataType : char 273 | { 274 | PDATA_NONE, 275 | PDATA_COMMENT, 276 | PDATA_SECTION, 277 | PDATA_KEYVALUE, 278 | PDATA_UNKNOWN 279 | }; 280 | 281 | inline PDataType parseLine(std::string line, T_ParseValues& parseData) 282 | { 283 | parseData.first.clear(); 284 | parseData.second.clear(); 285 | INIStringUtil::trim(line); 286 | if (line.empty()) 287 | { 288 | return PDataType::PDATA_NONE; 289 | } 290 | char firstCharacter = line[0]; 291 | if (firstCharacter == ';') 292 | { 293 | return PDataType::PDATA_COMMENT; 294 | } 295 | if (firstCharacter == '[') 296 | { 297 | auto commentAt = line.find_first_of(';'); 298 | if (commentAt != std::string::npos) 299 | { 300 | line = line.substr(0, commentAt); 301 | } 302 | auto closingBracketAt = line.find_last_of(']'); 303 | if (closingBracketAt != std::string::npos) 304 | { 305 | auto section = line.substr(1, closingBracketAt - 1); 306 | INIStringUtil::trim(section); 307 | parseData.first = section; 308 | return PDataType::PDATA_SECTION; 309 | } 310 | } 311 | auto lineNorm = line; 312 | INIStringUtil::replace(lineNorm, "\\=", " "); 313 | auto equalsAt = lineNorm.find_first_of('='); 314 | if (equalsAt != std::string::npos) 315 | { 316 | auto key = line.substr(0, equalsAt); 317 | INIStringUtil::trim(key); 318 | INIStringUtil::replace(key, "\\=", "="); 319 | auto value = line.substr(equalsAt + 1); 320 | INIStringUtil::trim(value); 321 | parseData.first = key; 322 | parseData.second = value; 323 | return PDataType::PDATA_KEYVALUE; 324 | } 325 | return PDataType::PDATA_UNKNOWN; 326 | } 327 | } 328 | 329 | class INIReader 330 | { 331 | public: 332 | using T_LineData = std::vector; 333 | using T_LineDataPtr = std::shared_ptr; 334 | 335 | private: 336 | std::ifstream fileReadStream; 337 | T_LineDataPtr lineData; 338 | 339 | T_LineData readFile() 340 | { 341 | std::string fileContents; 342 | fileReadStream.seekg(0, std::ios::end); 343 | fileContents.resize(static_cast(fileReadStream.tellg())); 344 | fileReadStream.seekg(0, std::ios::beg); 345 | std::size_t fileSize = fileContents.size(); 346 | fileReadStream.read(&fileContents[0], fileSize); 347 | fileReadStream.close(); 348 | T_LineData output; 349 | if (fileSize == 0) 350 | { 351 | return output; 352 | } 353 | std::string buffer; 354 | buffer.reserve(50); 355 | for (std::size_t i = 0; i < fileSize; ++i) 356 | { 357 | char& c = fileContents[i]; 358 | if (c == '\n') 359 | { 360 | output.emplace_back(buffer); 361 | buffer.clear(); 362 | continue; 363 | } 364 | if (c != '\0' && c != '\r') 365 | { 366 | buffer += c; 367 | } 368 | } 369 | output.emplace_back(buffer); 370 | return output; 371 | } 372 | 373 | public: 374 | INIReader(std::string const& filename, bool keepLineData = false) 375 | { 376 | fileReadStream.open(filename, std::ios::in | std::ios::binary); 377 | if (keepLineData) 378 | { 379 | lineData = std::make_shared(); 380 | } 381 | } 382 | ~INIReader() { } 383 | 384 | bool operator>>(INIStructure& data) 385 | { 386 | if (!fileReadStream.is_open()) 387 | { 388 | return false; 389 | } 390 | T_LineData fileLines = readFile(); 391 | std::string section; 392 | bool inSection = false; 393 | INIParser::T_ParseValues parseData; 394 | for (auto const& line : fileLines) 395 | { 396 | auto parseResult = INIParser::parseLine(line, parseData); 397 | if (parseResult == INIParser::PDataType::PDATA_SECTION) 398 | { 399 | inSection = true; 400 | data[section = parseData.first]; 401 | } 402 | else if (inSection && parseResult == INIParser::PDataType::PDATA_KEYVALUE) 403 | { 404 | auto const& key = parseData.first; 405 | auto const& value = parseData.second; 406 | data[section][key] = value; 407 | } 408 | if (lineData && parseResult != INIParser::PDataType::PDATA_UNKNOWN) 409 | { 410 | if (parseResult == INIParser::PDataType::PDATA_KEYVALUE && !inSection) 411 | { 412 | continue; 413 | } 414 | lineData->emplace_back(line); 415 | } 416 | } 417 | return true; 418 | } 419 | T_LineDataPtr getLines() 420 | { 421 | return lineData; 422 | } 423 | }; 424 | 425 | class INIGenerator 426 | { 427 | private: 428 | std::ofstream fileWriteStream; 429 | 430 | public: 431 | bool prettyPrint = false; 432 | 433 | INIGenerator(std::string const& filename) 434 | { 435 | fileWriteStream.open(filename, std::ios::out | std::ios::binary); 436 | } 437 | ~INIGenerator() { } 438 | 439 | bool operator<<(INIStructure const& data) 440 | { 441 | if (!fileWriteStream.is_open()) 442 | { 443 | return false; 444 | } 445 | if (!data.size()) 446 | { 447 | return true; 448 | } 449 | auto it = data.begin(); 450 | for (;;) 451 | { 452 | auto const& section = it->first; 453 | auto const& collection = it->second; 454 | fileWriteStream 455 | << "[" 456 | << section 457 | << "]"; 458 | if (collection.size()) 459 | { 460 | fileWriteStream << INIStringUtil::endl; 461 | auto it2 = collection.begin(); 462 | for (;;) 463 | { 464 | auto key = it2->first; 465 | INIStringUtil::replace(key, "=", "\\="); 466 | auto value = it2->second; 467 | INIStringUtil::trim(value); 468 | fileWriteStream 469 | << key 470 | << ((prettyPrint) ? " = " : "=") 471 | << value; 472 | if (++it2 == collection.end()) 473 | { 474 | break; 475 | } 476 | fileWriteStream << INIStringUtil::endl; 477 | } 478 | } 479 | if (++it == data.end()) 480 | { 481 | break; 482 | } 483 | fileWriteStream << INIStringUtil::endl; 484 | if (prettyPrint) 485 | { 486 | fileWriteStream << INIStringUtil::endl; 487 | } 488 | } 489 | return true; 490 | } 491 | }; 492 | 493 | class INIWriter 494 | { 495 | private: 496 | using T_LineData = std::vector; 497 | using T_LineDataPtr = std::shared_ptr; 498 | 499 | std::string filename; 500 | 501 | T_LineData getLazyOutput(T_LineDataPtr const& lineData, INIStructure& data, INIStructure& original) 502 | { 503 | T_LineData output; 504 | INIParser::T_ParseValues parseData; 505 | std::string sectionCurrent; 506 | bool parsingSection = false; 507 | bool continueToNextSection = false; 508 | bool discardNextEmpty = false; 509 | bool writeNewKeys = false; 510 | std::size_t lastKeyLine = 0; 511 | for (auto line = lineData->begin(); line != lineData->end(); ++line) 512 | { 513 | if (!writeNewKeys) 514 | { 515 | auto parseResult = INIParser::parseLine(*line, parseData); 516 | if (parseResult == INIParser::PDataType::PDATA_SECTION) 517 | { 518 | if (parsingSection) 519 | { 520 | writeNewKeys = true; 521 | parsingSection = false; 522 | --line; 523 | continue; 524 | } 525 | sectionCurrent = parseData.first; 526 | if (data.has(sectionCurrent)) 527 | { 528 | parsingSection = true; 529 | continueToNextSection = false; 530 | discardNextEmpty = false; 531 | output.emplace_back(*line); 532 | lastKeyLine = output.size(); 533 | } 534 | else 535 | { 536 | continueToNextSection = true; 537 | discardNextEmpty = true; 538 | continue; 539 | } 540 | } 541 | else if (parseResult == INIParser::PDataType::PDATA_KEYVALUE) 542 | { 543 | if (continueToNextSection) 544 | { 545 | continue; 546 | } 547 | if (data.has(sectionCurrent)) 548 | { 549 | auto& collection = data[sectionCurrent]; 550 | auto const& key = parseData.first; 551 | auto const& value = parseData.second; 552 | if (collection.has(key)) 553 | { 554 | auto outputValue = collection[key]; 555 | if (value == outputValue) 556 | { 557 | output.emplace_back(*line); 558 | } 559 | else 560 | { 561 | INIStringUtil::trim(outputValue); 562 | auto lineNorm = *line; 563 | INIStringUtil::replace(lineNorm, "\\=", " "); 564 | auto equalsAt = lineNorm.find_first_of('='); 565 | auto valueAt = lineNorm.find_first_not_of( 566 | INIStringUtil::whitespaceDelimiters, 567 | equalsAt + 1 568 | ); 569 | std::string outputLine = line->substr(0, valueAt); 570 | if (prettyPrint && equalsAt + 1 == valueAt) 571 | { 572 | outputLine += " "; 573 | } 574 | outputLine += outputValue; 575 | output.emplace_back(outputLine); 576 | } 577 | lastKeyLine = output.size(); 578 | } 579 | } 580 | } 581 | else 582 | { 583 | if (discardNextEmpty && line->empty()) 584 | { 585 | discardNextEmpty = false; 586 | } 587 | else if (parseResult != INIParser::PDataType::PDATA_UNKNOWN) 588 | { 589 | output.emplace_back(*line); 590 | } 591 | } 592 | } 593 | if (writeNewKeys || std::next(line) == lineData->end()) 594 | { 595 | T_LineData linesToAdd; 596 | if (data.has(sectionCurrent) && original.has(sectionCurrent)) 597 | { 598 | auto const& collection = data[sectionCurrent]; 599 | auto const& collectionOriginal = original[sectionCurrent]; 600 | for (auto const& it : collection) 601 | { 602 | auto key = it.first; 603 | if (collectionOriginal.has(key)) 604 | { 605 | continue; 606 | } 607 | auto value = it.second; 608 | INIStringUtil::replace(key, "=", "\\="); 609 | INIStringUtil::trim(value); 610 | linesToAdd.emplace_back( 611 | key + ((prettyPrint) ? " = " : "=") + value 612 | ); 613 | } 614 | } 615 | if (!linesToAdd.empty()) 616 | { 617 | output.insert( 618 | output.begin() + lastKeyLine, 619 | linesToAdd.begin(), 620 | linesToAdd.end() 621 | ); 622 | } 623 | if (writeNewKeys) 624 | { 625 | writeNewKeys = false; 626 | --line; 627 | } 628 | } 629 | } 630 | for (auto const& it : data) 631 | { 632 | auto const& section = it.first; 633 | if (original.has(section)) 634 | { 635 | continue; 636 | } 637 | if (prettyPrint && output.size() > 0 && !output.back().empty()) 638 | { 639 | output.emplace_back(); 640 | } 641 | output.emplace_back("[" + section + "]"); 642 | auto const& collection = it.second; 643 | for (auto const& it2 : collection) 644 | { 645 | auto key = it2.first; 646 | auto value = it2.second; 647 | INIStringUtil::replace(key, "=", "\\="); 648 | INIStringUtil::trim(value); 649 | output.emplace_back( 650 | key + ((prettyPrint) ? " = " : "=") + value 651 | ); 652 | } 653 | } 654 | return output; 655 | } 656 | 657 | public: 658 | bool prettyPrint = false; 659 | 660 | INIWriter(std::string const& filename) 661 | : filename(filename) 662 | { 663 | } 664 | ~INIWriter() { } 665 | 666 | bool operator<<(INIStructure& data) 667 | { 668 | struct stat buf; 669 | bool fileExists = (stat(filename.c_str(), &buf) == 0); 670 | if (!fileExists) 671 | { 672 | INIGenerator generator(filename); 673 | generator.prettyPrint = prettyPrint; 674 | return generator << data; 675 | } 676 | INIStructure originalData; 677 | T_LineDataPtr lineData; 678 | bool readSuccess = false; 679 | { 680 | INIReader reader(filename, true); 681 | if ((readSuccess = reader >> originalData)) 682 | { 683 | lineData = reader.getLines(); 684 | } 685 | } 686 | if (!readSuccess) 687 | { 688 | return false; 689 | } 690 | T_LineData output = getLazyOutput(lineData, data, originalData); 691 | std::ofstream fileWriteStream(filename, std::ios::out | std::ios::binary); 692 | if (fileWriteStream.is_open()) 693 | { 694 | if (output.size()) 695 | { 696 | auto line = output.begin(); 697 | for (;;) 698 | { 699 | fileWriteStream << *line; 700 | if (++line == output.end()) 701 | { 702 | break; 703 | } 704 | fileWriteStream << INIStringUtil::endl; 705 | } 706 | } 707 | return true; 708 | } 709 | return false; 710 | } 711 | }; 712 | 713 | class INIFile 714 | { 715 | private: 716 | std::string filename; 717 | 718 | public: 719 | INIFile(std::string const& filename) 720 | : filename(filename) 721 | { } 722 | 723 | ~INIFile() { } 724 | 725 | bool read(INIStructure& data) const 726 | { 727 | if (data.size()) 728 | { 729 | data.clear(); 730 | } 731 | if (filename.empty()) 732 | { 733 | return false; 734 | } 735 | INIReader reader(filename); 736 | return reader >> data; 737 | } 738 | bool generate(INIStructure const& data, bool pretty = false) const 739 | { 740 | if (filename.empty()) 741 | { 742 | return false; 743 | } 744 | INIGenerator generator(filename); 745 | generator.prettyPrint = pretty; 746 | return generator << data; 747 | } 748 | bool write(INIStructure& data, bool pretty = false) const 749 | { 750 | if (filename.empty()) 751 | { 752 | return false; 753 | } 754 | INIWriter writer(filename); 755 | writer.prettyPrint = pretty; 756 | return writer << data; 757 | } 758 | }; 759 | } 760 | 761 | #endif // MINI_INI_H_ --------------------------------------------------------------------------------