diff options
| author | auth12 <[email protected]> | 2020-08-06 15:33:18 +0100 |
|---|---|---|
| committer | auth12 <[email protected]> | 2020-08-06 15:33:18 +0100 |
| commit | d120e7b489adc42a4489c63305413dfe52ed8bbf (patch) | |
| tree | 6c114e3b0e8f22aa4c0210e2006a88ec63182b95 | |
| parent | More ui improvements. (diff) | |
| download | loader-d120e7b489adc42a4489c63305413dfe52ed8bbf.tar.xz loader-d120e7b489adc42a4489c63305413dfe52ed8bbf.zip | |
Improved CPU usage drastically.
Switched to directx9.
Reduced RAM usage by only remapping modules from a blacklist.
| -rw-r--r-- | client/client.vcxproj | 8 | ||||
| -rw-r--r-- | client/client.vcxproj.filters | 12 | ||||
| -rw-r--r-- | client/src/hwid/hwid.h | 24 | ||||
| -rw-r--r-- | client/src/injection/pe.h | 2 | ||||
| -rw-r--r-- | client/src/injection/process.cpp | 6 | ||||
| -rw-r--r-- | client/src/injection/process.h | 2 | ||||
| -rw-r--r-- | client/src/main.cpp | 48 | ||||
| -rw-r--r-- | client/src/security/security.cpp | 110 | ||||
| -rw-r--r-- | client/src/security/security.h | 58 | ||||
| -rw-r--r-- | client/src/ui/imgui/imgui_impl_dx11.cpp | 551 | ||||
| -rw-r--r-- | client/src/ui/imgui/imgui_impl_dx11.h | 25 | ||||
| -rw-r--r-- | client/src/ui/imgui/imgui_impl_dx9.cpp | 284 | ||||
| -rw-r--r-- | client/src/ui/imgui/imgui_impl_dx9.h | 24 | ||||
| -rw-r--r-- | client/src/ui/ui.cpp | 78 | ||||
| -rw-r--r-- | client/src/ui/ui.h | 16 | ||||
| -rw-r--r-- | client/src/util/native.h | 113 | ||||
| -rw-r--r-- | client/src/util/util.cpp | 10 |
17 files changed, 614 insertions, 757 deletions
diff --git a/client/client.vcxproj b/client/client.vcxproj index cd28e6d..ac79152 100644 --- a/client/client.vcxproj +++ b/client/client.vcxproj @@ -131,7 +131,7 @@ <FunctionLevelLinking>true</FunctionLevelLinking> <IntrinsicFunctions>true</IntrinsicFunctions> <SDLCheck>true</SDLCheck> - <PreprocessorDefinitions>NDEBUG;_CONSOLE;NOMINMAX;WIN32_LEAN_AND_MEAN;_WINSOCK_DEPRECATED_NO_WARNINGS;FMT_HEADER_ONLY;IMGUI_DISABLE_INCLUDE_IMCONFIG_H;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <PreprocessorDefinitions>NDEBUG;_CONSOLE;NOMINMAX;WIN32_LEAN_AND_MEAN;_WINSOCK_DEPRECATED_NO_WARNINGS;FMT_HEADER_ONLY;IMGUI_DISABLE_INCLUDE_IMCONFIG_H;TRACY_ENABLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> <ConformanceMode>true</ConformanceMode> <LanguageStandard>stdcpplatest</LanguageStandard> <AdditionalIncludeDirectories>$(DXSDK_DIR)include\;$(SolutionDir);$(SolutionDir)wolfssl;$(SolutionDir)..\shared;$(SolutionDir)..\shared\spdlog\include;$(IncludePath)</AdditionalIncludeDirectories> @@ -144,7 +144,7 @@ <EnableCOMDATFolding>true</EnableCOMDATFolding> <OptimizeReferences>true</OptimizeReferences> <GenerateDebugInformation>true</GenerateDebugInformation> - <AdditionalDependencies>wolfssl.lib;ws2_32.lib;d3d11.lib;d3dcompiler.lib;%(AdditionalDependencies)</AdditionalDependencies> + <AdditionalDependencies>wolfssl.lib;ws2_32.lib;d3d9.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalLibraryDirectories>$(DXSDK_DIR)Lib\x64\;$(SolutionDir)lib\$(Platform)\$(Configuration)\</AdditionalLibraryDirectories> <UACExecutionLevel>RequireAdministrator</UACExecutionLevel> <ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers> @@ -164,7 +164,7 @@ <ClInclude Include="src\injection\process.h" /> <ClInclude Include="src\security\security.h" /> <ClInclude Include="src\ui\imgui\imgui.h" /> - <ClInclude Include="src\ui\imgui\imgui_impl_dx11.h" /> + <ClInclude Include="src\ui\imgui\imgui_impl_dx9.h" /> <ClInclude Include="src\ui\imgui\imgui_impl_win32.h" /> <ClInclude Include="src\ui\imgui\imgui_internal.h" /> <ClInclude Include="src\ui\imgui\imgui_stdlib.h" /> @@ -187,7 +187,7 @@ <ClCompile Include="src\security\security.cpp" /> <ClCompile Include="src\ui\imgui\imgui.cpp" /> <ClCompile Include="src\ui\imgui\imgui_draw.cpp" /> - <ClCompile Include="src\ui\imgui\imgui_impl_dx11.cpp" /> + <ClCompile Include="src\ui\imgui\imgui_impl_dx9.cpp" /> <ClCompile Include="src\ui\imgui\imgui_impl_win32.cpp" /> <ClCompile Include="src\ui\imgui\imgui_stdlib.cpp" /> <ClCompile Include="src\ui\imgui\imgui_widgets.cpp" /> diff --git a/client/client.vcxproj.filters b/client/client.vcxproj.filters index 9689b6f..8b22397 100644 --- a/client/client.vcxproj.filters +++ b/client/client.vcxproj.filters @@ -90,9 +90,6 @@ <ClInclude Include="src\ui\imgui\imgui.h"> <Filter>src\ui\imgui</Filter> </ClInclude> - <ClInclude Include="src\ui\imgui\imgui_impl_dx11.h"> - <Filter>src\ui\imgui</Filter> - </ClInclude> <ClInclude Include="src\ui\imgui\imgui_impl_win32.h"> <Filter>src\ui\imgui</Filter> </ClInclude> @@ -114,6 +111,9 @@ <ClInclude Include="src\ui\imgui\imgui_stdlib.h"> <Filter>src\ui\imgui</Filter> </ClInclude> + <ClInclude Include="src\ui\imgui\imgui_impl_dx9.h"> + <Filter>src\ui\imgui</Filter> + </ClInclude> </ItemGroup> <ItemGroup> <ClCompile Include="src\main.cpp"> @@ -143,9 +143,6 @@ <ClCompile Include="src\security\security.cpp"> <Filter>src\security</Filter> </ClCompile> - <ClCompile Include="src\ui\imgui\imgui_impl_dx11.cpp"> - <Filter>src\ui\imgui</Filter> - </ClCompile> <ClCompile Include="src\ui\imgui\imgui_impl_win32.cpp"> <Filter>src\ui\imgui</Filter> </ClCompile> @@ -164,5 +161,8 @@ <ClCompile Include="src\ui\imgui\imgui_stdlib.cpp"> <Filter>src\ui\imgui</Filter> </ClCompile> + <ClCompile Include="src\ui\imgui\imgui_impl_dx9.cpp"> + <Filter>src\ui\imgui</Filter> + </ClCompile> </ItemGroup> </Project>
\ No newline at end of file diff --git a/client/src/hwid/hwid.h b/client/src/hwid/hwid.h index 445635d..d4b1159 100644 --- a/client/src/hwid/hwid.h +++ b/client/src/hwid/hwid.h @@ -9,29 +9,7 @@ namespace hwid { }; __forceinline bool fetch(hwid_data_t& out) { - IDXGIDevice* dxgi_device; - if (ui::device->QueryInterface(&dxgi_device) != S_OK) { - return false; - } - - IDXGIAdapter* adapter; - if (dxgi_device->GetParent(__uuidof(IDXGIAdapter), reinterpret_cast<void**>(&adapter)) != S_OK) { - return false; - } - - DXGI_ADAPTER_DESC desc; - if (adapter->GetDesc(&desc) != S_OK) { - return false; - } - - out.uid += desc.VendorId >> 1; - out.uid += desc.DeviceId >> 1; - out.uid += desc.DedicatedVideoMemory << 5; - - out.gpu = util::wide_to_multibyte(desc.Description); - - adapter->Release(); - dxgi_device->Release(); + return true; } diff --git a/client/src/injection/pe.h b/client/src/injection/pe.h index 6d2b655..4b94a88 100644 --- a/client/src/injection/pe.h +++ b/client/src/injection/pe.h @@ -308,5 +308,5 @@ namespace pe { return img; } - void get_all_modules(std::unordered_map<std::string, virtual_image>& modules); + bool get_all_modules(std::unordered_map<std::string, virtual_image>& modules); }; // namespace pe
\ No newline at end of file diff --git a/client/src/injection/process.cpp b/client/src/injection/process.cpp index c37e131..588699f 100644 --- a/client/src/injection/process.cpp +++ b/client/src/injection/process.cpp @@ -68,7 +68,7 @@ bool util::base_process::free(const uintptr_t addr, size_t size, uint32_t type / return true; } -bool util::base_process::info(PROCESSINFOCLASS proc_info, void* data, size_t size) { +bool util::base_process::info(native::PROCESSINFOCLASS proc_info, void* data, size_t size) { static auto nt_proc_info = g_syscalls.get<native::NtQueryInformationProcess>("NtQueryInformationProcess"); auto status = nt_proc_info(m_handle, proc_info, data, size, nullptr); if (!NT_SUCCESS(status)) { @@ -179,7 +179,7 @@ uintptr_t util::process<T>::peb() { if (is64) { native::PROCESS_EXTENDED_BASIC_INFORMATION proc_info; proc_info.Size = sizeof(proc_info); - if (!info(ProcessBasicInformation, &proc_info, sizeof(proc_info))) { + if (!info(native::ProcessBasicInformation, &proc_info, sizeof(proc_info))) { return {}; } @@ -187,7 +187,7 @@ uintptr_t util::process<T>::peb() { } uintptr_t addr; - if (!info(ProcessWow64Information, &addr, sizeof(addr))) { + if (!info(native::ProcessWow64Information, &addr, sizeof(addr))) { return {}; } diff --git a/client/src/injection/process.h b/client/src/injection/process.h index 74cfccd..1b0fdb3 100644 --- a/client/src/injection/process.h +++ b/client/src/injection/process.h @@ -14,7 +14,7 @@ namespace util { bool read(const uintptr_t addr, void* data, size_t size); bool write(const uintptr_t addr, void* data, size_t size); bool free(const uintptr_t addr, size_t size, uint32_t type = MEM_RELEASE); - bool info(PROCESSINFOCLASS proc_info, void* data, size_t size); + bool info(native::PROCESSINFOCLASS proc_info, void* data, size_t size); bool thread(const uintptr_t func); bool close(); diff --git a/client/src/main.cpp b/client/src/main.cpp index 9c023e1..d7427cb 100644 --- a/client/src/main.cpp +++ b/client/src/main.cpp @@ -39,7 +39,7 @@ void add_handlers(tcp::client& client) { return; } - hwid::hwid_data_t data; + /*hwid::hwid_data_t data; if (!hwid::fetch(data)) { client.session_result = tcp::session_result::hwid_fail; @@ -47,11 +47,11 @@ void add_handlers(tcp::client& client) { client.shutdown(); return; - } + }*/ nlohmann::json json; - json["uid"] = data.uid; - json["gpu"] = data.gpu; + json["uid"] = 0; + //json["gpu"] = data.gpu; int ret = client.write(tcp::packet_t(json.dump(), tcp::packet_type::write, client.session_id, tcp::packet_id::hwid)); if (ret <= 0) { @@ -120,8 +120,10 @@ void add_handlers(tcp::client& client) { } int WinMain(HINSTANCE inst, HINSTANCE prev_inst, LPSTR cmd_args, int show_cmd) { + AllocConsole(); + FILE* fp = nullptr; - freopen_s(&fp, "log", "w", stdout); + freopen_s(&fp, "CONOUT$", "w", stdout); g_syscalls.init(); @@ -137,7 +139,7 @@ int WinMain(HINSTANCE inst, HINSTANCE prev_inst, LPSTR cmd_args, int show_cmd) { add_handlers(client); - auto hwnd = ui::create(inst, { 400, 300 }); + auto hwnd = ui::create_window(inst, { 400, 300 }); if (!ui::create_device(hwnd)) { MessageBoxA(0, "internal graphics error, please check your video drivers.", "client", MB_OK); @@ -164,7 +166,7 @@ int WinMain(HINSTANCE inst, HINSTANCE prev_inst, LPSTR cmd_args, int show_cmd) { ImGui::GetStyle().WindowRounding = 0.f; ImGui_ImplWin32_Init(hwnd); - ImGui_ImplDX11_Init(ui::device, ui::device_context); + ImGui_ImplDX9_Init(ui::device); int offset_x = 0; int offset_y = 0; @@ -181,7 +183,7 @@ int WinMain(HINSTANCE inst, HINSTANCE prev_inst, LPSTR cmd_args, int show_cmd) { if (!client) break; - ImGui_ImplDX11_NewFrame(); + ImGui_ImplDX9_NewFrame(); ImGui_ImplWin32_NewFrame(); ImGui::NewFrame(); @@ -317,7 +319,7 @@ int WinMain(HINSTANCE inst, HINSTANCE prev_inst, LPSTR cmd_args, int show_cmd) { ImGui::BeginGroup(); ImGui::BeginChild("data", ImVec2(0, -ImGui::GetFrameHeightWithSpacing())); auto game = client.games[selected]; - ImGui::Text("%s", game.name); + ImGui::Text("%s", game.name.c_str()); ImGui::Separator(); ImGui::Text("version %d", game.version); @@ -364,14 +366,32 @@ int WinMain(HINSTANCE inst, HINSTANCE prev_inst, LPSTR cmd_args, int show_cmd) { ImGui::End(); - ImGui::Render(); - ui::device_context->OMSetRenderTargets(1, &ui::main_render_target, NULL); - ImGui_ImplDX11_RenderDrawData(ImGui::GetDrawData()); + ImGui::EndFrame(); + + if (ui::device->BeginScene() == D3D_OK) { + ImGui::Render(); + ImGui_ImplDX9_RenderDrawData(ImGui::GetDrawData()); + ui::device->EndScene(); + } + + HRESULT result = ui::device->Present(0, 0, 0, 0); + + if (result == D3DERR_DEVICELOST && ui::device->TestCooperativeLevel() == D3DERR_DEVICENOTRESET) { + ImGui_ImplDX9_InvalidateDeviceObjects(); + HRESULT hr = ui::device->Reset(&ui::present_params); + if (hr == D3DERR_INVALIDCALL) { + io::log_error("reset failed."); - ui::swap_chain->Present(0, 0); + break; + } + ImGui_ImplDX9_CreateDeviceObjects(); + } } - ImGui_ImplDX11_Shutdown(); + ImGui_ImplDX9_Shutdown(); ImGui_ImplWin32_Shutdown(); ImGui::DestroyContext(); + + ui::cleanup_device(); + DestroyWindow(hwnd); } diff --git a/client/src/security/security.cpp b/client/src/security/security.cpp index f0adfe9..b1e2b93 100644 --- a/client/src/security/security.cpp +++ b/client/src/security/security.cpp @@ -6,71 +6,36 @@ #include "../util/syscalls.h" #include "security.h" -#define SEC_NO_CHANGE 0x00400000 - std::unordered_map<std::string, std::vector<char>> security::parsed_images; void security::thread(tcp::client& client) { - std::list<std::string> whitelist = { "d3dcompiler_43.dll", "xinput1_3.dll" }; - - std::unordered_map<std::string, pe::virtual_image> images; - std::unordered_map<std::string, pe::image<true>> raw_images; - pe::get_all_modules(images); - - for (auto& [name, vi] : images) { - auto it = std::find(whitelist.begin(), whitelist.end(), name); - if (it != whitelist.end()) { - continue; - } - - std::vector<char> raw; - char path[MAX_PATH]; - GetModuleFileNameA(GetModuleHandleA(name.c_str()), path, MAX_PATH); - - if (!io::read_file(path, raw)) { - io::log("failed to read {}.", name); - continue; - } - - raw_images[name] = pe::image<true>(raw); - } + if (!init()) { + io::log_error("failed to init security thread."); - for (auto& [name, image] : raw_images) { - std::vector<char> mem; + client.shutdown(); - image.copy(mem); - image.relocate(mem, uintptr_t(GetModuleHandleA(name.c_str()))); - - for (auto& [mod, funcs] : image.imports()) { - std::string mod_name{ mod }; - g_apiset.find(mod_name); - - for (auto& func : funcs) { - *reinterpret_cast<uintptr_t*>(&mem[func.rva]) = uintptr_t(GetProcAddress(GetModuleHandleA(mod_name.c_str()), func.name.c_str())); - } - } - - parsed_images[name] = mem; + return; } - raw_images.clear(); - images.clear(); - while (client) { if (client.session_id.empty()) { continue; } + bool ret = check(); + io::log("check returned {}.", ret); + std::unordered_map<std::string, pe::virtual_image> loaded_images; - pe::get_all_modules(loaded_images); + if (!pe::get_all_modules(loaded_images)) { + io::log_error("failed to get loaded modules."); + + client.shutdown(); + + break; + } std::vector<patch_t> patches; for (auto& [name, limage] : loaded_images) { - auto it = std::find(whitelist.begin(), whitelist.end(), name); - if (it != whitelist.end()) { - continue; - } - auto& parsed = parsed_images[name]; if (parsed.empty()) { continue; @@ -85,12 +50,12 @@ void security::thread(tcp::client& client) { continue; } - /*int ret = std::memcmp(&parsed[sec.va], reinterpret_cast<void*>(start + sec.va), sec.size); + int ret = std::memcmp(&parsed[sec.va], reinterpret_cast<void*>(start + sec.va), sec.size); if (ret != 0) { io::log("found patch in {}.", name); - }*/ + } - auto sec_start = reinterpret_cast<uint8_t*>(start + sec.va); + /*auto sec_start = reinterpret_cast<uint8_t*>(start + sec.va); auto sec_len = sec.size; for (size_t i = 0; i < sec_len; ++i) { @@ -107,7 +72,7 @@ void security::thread(tcp::client& client) { patches.emplace_back(patch); } - } + }*/ } } nlohmann::json j; @@ -125,4 +90,43 @@ void security::thread(tcp::client& client) { std::this_thread::sleep_for(std::chrono::seconds(5)); } +} + +__forceinline bool security::check() { + static auto peb = util::peb(); + auto being_debugged = static_cast<bool>(peb->BeingDebugged); + if (being_debugged) { + return true; + } + + io::log("being debugged {}", being_debugged); + + static auto query_info = g_syscalls.get<native::NtQueryInformationProcess>("NtQueryInformationProcess"); + + uint32_t debug_inherit = 0; + auto status = query_info(INVALID_HANDLE_VALUE, native::ProcessDebugFlags, &debug_inherit, sizeof(debug_inherit), 0); + if (!NT_SUCCESS(status)) { + io::log_error("failed to get local process debug flags, status {:#X}.", (status & 0xFFFFFFFF)); + return true; + } + + io::log("debug inherit {}", debug_inherit); + + if (debug_inherit == 0) { + return true; + } + + uint64_t remote_debug = 0; + status = query_info(INVALID_HANDLE_VALUE, native::ProcessDebugPort, &remote_debug, sizeof(remote_debug), 0); + if (!NT_SUCCESS(status)) { + io::log_error("failed to get local process debug port, status {:#X}.", (status & 0xFFFFFFFF)); + return true; + } + + io::log("remote debug {}", remote_debug); + if (remote_debug != 0) { + return true; + } + + return false; }
\ No newline at end of file diff --git a/client/src/security/security.h b/client/src/security/security.h index 009622a..fd2a5f3 100644 --- a/client/src/security/security.h +++ b/client/src/security/security.h @@ -4,6 +4,8 @@ namespace security { extern std::unordered_map<std::string, std::vector<char>> parsed_images; + + struct patch_t { uintptr_t va; uint8_t original_op; @@ -11,5 +13,59 @@ namespace security { std::string module; }; - void thread(tcp::client &client); + void thread(tcp::client& client); + + __forceinline bool check(); + + __forceinline bool init() { + std::list<std::string> blacklist = { "ntdll.dll", "kernel32.dll" }; + + std::unordered_map<std::string, pe::virtual_image> memory_modules; + std::unordered_map<std::string, pe::image<true>> disk_modules; + if (!pe::get_all_modules(memory_modules)) { + io::log_error("failed to get loaded modules."); + return false; + } + + for (auto& [name, vi] : memory_modules) { + auto it = std::find(blacklist.begin(), blacklist.end(), name); + if (it == blacklist.end()) { + continue; + } + + std::vector<char> raw; + char path[MAX_PATH]; + GetModuleFileNameA(GetModuleHandleA(name.c_str()), path, MAX_PATH); + + if (!io::read_file(path, raw)) { + io::log("failed to read {}.", name); + continue; + } + + disk_modules[name] = pe::image<true>(raw); + } + + for (auto& [name, image] : disk_modules) { + std::vector<char> mem; + + image.copy(mem); + image.relocate(mem, uintptr_t(GetModuleHandleA(name.c_str()))); + + for (auto& [mod, funcs] : image.imports()) { + std::string mod_name{ mod }; + g_apiset.find(mod_name); + + for (auto& func : funcs) { + *reinterpret_cast<uintptr_t*>(&mem[func.rva]) = uintptr_t(GetProcAddress(GetModuleHandleA(mod_name.c_str()), func.name.c_str())); + } + } + + parsed_images[name] = mem; + } + + disk_modules.clear(); + memory_modules.clear(); + + return !parsed_images.empty(); + } };
\ No newline at end of file diff --git a/client/src/ui/imgui/imgui_impl_dx11.cpp b/client/src/ui/imgui/imgui_impl_dx11.cpp deleted file mode 100644 index 0f4a861..0000000 --- a/client/src/ui/imgui/imgui_impl_dx11.cpp +++ /dev/null @@ -1,551 +0,0 @@ -// dear imgui: Renderer for DirectX11 -// This needs to be used along with a Platform Binding (e.g. Win32) - -// Implemented features: -// [X] Renderer: User texture binding. Use 'ID3D11ShaderResourceView*' as ImTextureID. Read the FAQ about ImTextureID! -// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices. - -// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. -// If you are new to dear imgui, read examples/README.txt and read the documentation at the top of imgui.cpp -// https://github.com/ocornut/imgui - -// CHANGELOG -// (minor and older changes stripped away, please see git history for details) -// 2019-08-01: DirectX11: Fixed code querying the Geometry Shader state (would generally error with Debug layer enabled). -// 2019-07-21: DirectX11: Backup, clear and restore Geometry Shader is any is bound when calling ImGui_ImplDX10_RenderDrawData. Clearing Hull/Domain/Compute shaders without backup/restore. -// 2019-05-29: DirectX11: Added support for large mesh (64K+ vertices), enable ImGuiBackendFlags_RendererHasVtxOffset flag. -// 2019-04-30: DirectX11: Added support for special ImDrawCallback_ResetRenderState callback to reset render state. -// 2018-12-03: Misc: Added #pragma comment statement to automatically link with d3dcompiler.lib when using D3DCompile(). -// 2018-11-30: Misc: Setting up io.BackendRendererName so it can be displayed in the About Window. -// 2018-08-01: DirectX11: Querying for IDXGIFactory instead of IDXGIFactory1 to increase compatibility. -// 2018-07-13: DirectX11: Fixed unreleased resources in Init and Shutdown functions. -// 2018-06-08: Misc: Extracted imgui_impl_dx11.cpp/.h away from the old combined DX11+Win32 example. -// 2018-06-08: DirectX11: Use draw_data->DisplayPos and draw_data->DisplaySize to setup projection matrix and clipping rectangle. -// 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback and exposed ImGui_ImplDX11_RenderDrawData() in the .h file so you can call it yourself. -// 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves. -// 2016-05-07: DirectX11: Disabling depth-write. - -#include "imgui.h" -#include "imgui_impl_dx11.h" - -// DirectX -#include <stdio.h> -#include <d3d11.h> -#include <d3dcompiler.h> -#ifdef _MSC_VER -#pragma comment(lib, "d3dcompiler") // Automatically link with d3dcompiler.lib as we are using D3DCompile() below. -#endif - -// DirectX data -static ID3D11Device* g_pd3dDevice = NULL; -static ID3D11DeviceContext* g_pd3dDeviceContext = NULL; -static IDXGIFactory* g_pFactory = NULL; -static ID3D11Buffer* g_pVB = NULL; -static ID3D11Buffer* g_pIB = NULL; -static ID3D11VertexShader* g_pVertexShader = NULL; -static ID3D11InputLayout* g_pInputLayout = NULL; -static ID3D11Buffer* g_pVertexConstantBuffer = NULL; -static ID3D11PixelShader* g_pPixelShader = NULL; -static ID3D11SamplerState* g_pFontSampler = NULL; -static ID3D11ShaderResourceView*g_pFontTextureView = NULL; -static ID3D11RasterizerState* g_pRasterizerState = NULL; -static ID3D11BlendState* g_pBlendState = NULL; -static ID3D11DepthStencilState* g_pDepthStencilState = NULL; -static int g_VertexBufferSize = 5000, g_IndexBufferSize = 10000; - -struct VERTEX_CONSTANT_BUFFER -{ - float mvp[4][4]; -}; - -static void ImGui_ImplDX11_SetupRenderState(ImDrawData* draw_data, ID3D11DeviceContext* ctx) -{ - // Setup viewport - D3D11_VIEWPORT vp; - memset(&vp, 0, sizeof(D3D11_VIEWPORT)); - vp.Width = draw_data->DisplaySize.x; - vp.Height = draw_data->DisplaySize.y; - vp.MinDepth = 0.0f; - vp.MaxDepth = 1.0f; - vp.TopLeftX = vp.TopLeftY = 0; - ctx->RSSetViewports(1, &vp); - - // Setup shader and vertex buffers - unsigned int stride = sizeof(ImDrawVert); - unsigned int offset = 0; - ctx->IASetInputLayout(g_pInputLayout); - ctx->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); - ctx->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); - ctx->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - ctx->VSSetShader(g_pVertexShader, NULL, 0); - ctx->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); - ctx->PSSetShader(g_pPixelShader, NULL, 0); - ctx->PSSetSamplers(0, 1, &g_pFontSampler); - ctx->GSSetShader(NULL, NULL, 0); - ctx->HSSetShader(NULL, NULL, 0); // In theory we should backup and restore this as well.. very infrequently used.. - ctx->DSSetShader(NULL, NULL, 0); // In theory we should backup and restore this as well.. very infrequently used.. - ctx->CSSetShader(NULL, NULL, 0); // In theory we should backup and restore this as well.. very infrequently used.. - - // Setup blend state - const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f }; - ctx->OMSetBlendState(g_pBlendState, blend_factor, 0xffffffff); - ctx->OMSetDepthStencilState(g_pDepthStencilState, 0); - ctx->RSSetState(g_pRasterizerState); -} - -// Render function -// (this used to be set in io.RenderDrawListsFn and called by ImGui::Render(), but you can now call this directly from your main loop) -void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data) -{ - // Avoid rendering when minimized - if (draw_data->DisplaySize.x <= 0.0f || draw_data->DisplaySize.y <= 0.0f) - return; - - ID3D11DeviceContext* ctx = g_pd3dDeviceContext; - - // Create and grow vertex/index buffers if needed - if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount) - { - if (g_pVB) { g_pVB->Release(); g_pVB = NULL; } - g_VertexBufferSize = draw_data->TotalVtxCount + 5000; - D3D11_BUFFER_DESC desc; - memset(&desc, 0, sizeof(D3D11_BUFFER_DESC)); - desc.Usage = D3D11_USAGE_DYNAMIC; - desc.ByteWidth = g_VertexBufferSize * sizeof(ImDrawVert); - desc.BindFlags = D3D11_BIND_VERTEX_BUFFER; - desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - desc.MiscFlags = 0; - if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVB) < 0) - return; - } - if (!g_pIB || g_IndexBufferSize < draw_data->TotalIdxCount) - { - if (g_pIB) { g_pIB->Release(); g_pIB = NULL; } - g_IndexBufferSize = draw_data->TotalIdxCount + 10000; - D3D11_BUFFER_DESC desc; - memset(&desc, 0, sizeof(D3D11_BUFFER_DESC)); - desc.Usage = D3D11_USAGE_DYNAMIC; - desc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); - desc.BindFlags = D3D11_BIND_INDEX_BUFFER; - desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pIB) < 0) - return; - } - - // Upload vertex/index data into a single contiguous GPU buffer - D3D11_MAPPED_SUBRESOURCE vtx_resource, idx_resource; - if (ctx->Map(g_pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vtx_resource) != S_OK) - return; - if (ctx->Map(g_pIB, 0, D3D11_MAP_WRITE_DISCARD, 0, &idx_resource) != S_OK) - return; - ImDrawVert* vtx_dst = (ImDrawVert*)vtx_resource.pData; - ImDrawIdx* idx_dst = (ImDrawIdx*)idx_resource.pData; - for (int n = 0; n < draw_data->CmdListsCount; n++) - { - const ImDrawList* cmd_list = draw_data->CmdLists[n]; - memcpy(vtx_dst, cmd_list->VtxBuffer.Data, cmd_list->VtxBuffer.Size * sizeof(ImDrawVert)); - memcpy(idx_dst, cmd_list->IdxBuffer.Data, cmd_list->IdxBuffer.Size * sizeof(ImDrawIdx)); - vtx_dst += cmd_list->VtxBuffer.Size; - idx_dst += cmd_list->IdxBuffer.Size; - } - ctx->Unmap(g_pVB, 0); - ctx->Unmap(g_pIB, 0); - - // Setup orthographic projection matrix into our constant buffer - // Our visible imgui space lies from draw_data->DisplayPos (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayPos is (0,0) for single viewport apps. - { - D3D11_MAPPED_SUBRESOURCE mapped_resource; - if (ctx->Map(g_pVertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK) - return; - VERTEX_CONSTANT_BUFFER* constant_buffer = (VERTEX_CONSTANT_BUFFER*)mapped_resource.pData; - float L = draw_data->DisplayPos.x; - float R = draw_data->DisplayPos.x + draw_data->DisplaySize.x; - float T = draw_data->DisplayPos.y; - float B = draw_data->DisplayPos.y + draw_data->DisplaySize.y; - float mvp[4][4] = - { - { 2.0f/(R-L), 0.0f, 0.0f, 0.0f }, - { 0.0f, 2.0f/(T-B), 0.0f, 0.0f }, - { 0.0f, 0.0f, 0.5f, 0.0f }, - { (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f }, - }; - memcpy(&constant_buffer->mvp, mvp, sizeof(mvp)); - ctx->Unmap(g_pVertexConstantBuffer, 0); - } - - // Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!) - struct BACKUP_DX11_STATE - { - UINT ScissorRectsCount, ViewportsCount; - D3D11_RECT ScissorRects[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; - D3D11_VIEWPORT Viewports[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; - ID3D11RasterizerState* RS; - ID3D11BlendState* BlendState; - FLOAT BlendFactor[4]; - UINT SampleMask; - UINT StencilRef; - ID3D11DepthStencilState* DepthStencilState; - ID3D11ShaderResourceView* PSShaderResource; - ID3D11SamplerState* PSSampler; - ID3D11PixelShader* PS; - ID3D11VertexShader* VS; - ID3D11GeometryShader* GS; - UINT PSInstancesCount, VSInstancesCount, GSInstancesCount; - ID3D11ClassInstance *PSInstances[256], *VSInstances[256], *GSInstances[256]; // 256 is max according to PSSetShader documentation - D3D11_PRIMITIVE_TOPOLOGY PrimitiveTopology; - ID3D11Buffer* IndexBuffer, *VertexBuffer, *VSConstantBuffer; - UINT IndexBufferOffset, VertexBufferStride, VertexBufferOffset; - DXGI_FORMAT IndexBufferFormat; - ID3D11InputLayout* InputLayout; - }; - BACKUP_DX11_STATE old; - old.ScissorRectsCount = old.ViewportsCount = D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; - ctx->RSGetScissorRects(&old.ScissorRectsCount, old.ScissorRects); - ctx->RSGetViewports(&old.ViewportsCount, old.Viewports); - ctx->RSGetState(&old.RS); - ctx->OMGetBlendState(&old.BlendState, old.BlendFactor, &old.SampleMask); - ctx->OMGetDepthStencilState(&old.DepthStencilState, &old.StencilRef); - ctx->PSGetShaderResources(0, 1, &old.PSShaderResource); - ctx->PSGetSamplers(0, 1, &old.PSSampler); - old.PSInstancesCount = old.VSInstancesCount = old.GSInstancesCount = 256; - ctx->PSGetShader(&old.PS, old.PSInstances, &old.PSInstancesCount); - ctx->VSGetShader(&old.VS, old.VSInstances, &old.VSInstancesCount); - ctx->VSGetConstantBuffers(0, 1, &old.VSConstantBuffer); - ctx->GSGetShader(&old.GS, old.GSInstances, &old.GSInstancesCount); - - ctx->IAGetPrimitiveTopology(&old.PrimitiveTopology); - ctx->IAGetIndexBuffer(&old.IndexBuffer, &old.IndexBufferFormat, &old.IndexBufferOffset); - ctx->IAGetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); - ctx->IAGetInputLayout(&old.InputLayout); - - // Setup desired DX state - ImGui_ImplDX11_SetupRenderState(draw_data, ctx); - - // Render command lists - // (Because we merged all buffers into a single one, we maintain our own offset into them) - int global_idx_offset = 0; - int global_vtx_offset = 0; - ImVec2 clip_off = draw_data->DisplayPos; - for (int n = 0; n < draw_data->CmdListsCount; n++) - { - const ImDrawList* cmd_list = draw_data->CmdLists[n]; - for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++) - { - const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i]; - if (pcmd->UserCallback != NULL) - { - // User callback, registered via ImDrawList::AddCallback() - // (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.) - if (pcmd->UserCallback == ImDrawCallback_ResetRenderState) - ImGui_ImplDX11_SetupRenderState(draw_data, ctx); - else - pcmd->UserCallback(cmd_list, pcmd); - } - else - { - // Apply scissor/clipping rectangle - const D3D11_RECT r = { (LONG)(pcmd->ClipRect.x - clip_off.x), (LONG)(pcmd->ClipRect.y - clip_off.y), (LONG)(pcmd->ClipRect.z - clip_off.x), (LONG)(pcmd->ClipRect.w - clip_off.y) }; - ctx->RSSetScissorRects(1, &r); - - // Bind texture, Draw - ID3D11ShaderResourceView* texture_srv = (ID3D11ShaderResourceView*)pcmd->TextureId; - ctx->PSSetShaderResources(0, 1, &texture_srv); - ctx->DrawIndexed(pcmd->ElemCount, pcmd->IdxOffset + global_idx_offset, pcmd->VtxOffset + global_vtx_offset); - } - } - global_idx_offset += cmd_list->IdxBuffer.Size; - global_vtx_offset += cmd_list->VtxBuffer.Size; - } - - // Restore modified DX state - ctx->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects); - ctx->RSSetViewports(old.ViewportsCount, old.Viewports); - ctx->RSSetState(old.RS); if (old.RS) old.RS->Release(); - ctx->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask); if (old.BlendState) old.BlendState->Release(); - ctx->OMSetDepthStencilState(old.DepthStencilState, old.StencilRef); if (old.DepthStencilState) old.DepthStencilState->Release(); - ctx->PSSetShaderResources(0, 1, &old.PSShaderResource); if (old.PSShaderResource) old.PSShaderResource->Release(); - ctx->PSSetSamplers(0, 1, &old.PSSampler); if (old.PSSampler) old.PSSampler->Release(); - ctx->PSSetShader(old.PS, old.PSInstances, old.PSInstancesCount); if (old.PS) old.PS->Release(); - for (UINT i = 0; i < old.PSInstancesCount; i++) if (old.PSInstances[i]) old.PSInstances[i]->Release(); - ctx->VSSetShader(old.VS, old.VSInstances, old.VSInstancesCount); if (old.VS) old.VS->Release(); - ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer); if (old.VSConstantBuffer) old.VSConstantBuffer->Release(); - ctx->GSSetShader(old.GS, old.GSInstances, old.GSInstancesCount); if (old.GS) old.GS->Release(); - for (UINT i = 0; i < old.VSInstancesCount; i++) if (old.VSInstances[i]) old.VSInstances[i]->Release(); - ctx->IASetPrimitiveTopology(old.PrimitiveTopology); - ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release(); - ctx->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); if (old.VertexBuffer) old.VertexBuffer->Release(); - ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release(); -} - -static void ImGui_ImplDX11_CreateFontsTexture() -{ - // Build texture atlas - ImGuiIO& io = ImGui::GetIO(); - unsigned char* pixels; - int width, height; - io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); - - // Upload texture to graphics system - { - D3D11_TEXTURE2D_DESC desc; - ZeroMemory(&desc, sizeof(desc)); - desc.Width = width; - desc.Height = height; - desc.MipLevels = 1; - desc.ArraySize = 1; - desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - desc.SampleDesc.Count = 1; - desc.Usage = D3D11_USAGE_DEFAULT; - desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; - desc.CPUAccessFlags = 0; - - ID3D11Texture2D* pTexture = NULL; - D3D11_SUBRESOURCE_DATA subResource; - subResource.pSysMem = pixels; - subResource.SysMemPitch = desc.Width * 4; - subResource.SysMemSlicePitch = 0; - g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture); - - // Create texture view - D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; - ZeroMemory(&srvDesc, sizeof(srvDesc)); - srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; - srvDesc.Texture2D.MipLevels = desc.MipLevels; - srvDesc.Texture2D.MostDetailedMip = 0; - g_pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, &g_pFontTextureView); - pTexture->Release(); - } - - // Store our identifier - io.Fonts->TexID = (ImTextureID)g_pFontTextureView; - - // Create texture sampler - { - D3D11_SAMPLER_DESC desc; - ZeroMemory(&desc, sizeof(desc)); - desc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; - desc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; - desc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; - desc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; - desc.MipLODBias = 0.f; - desc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; - desc.MinLOD = 0.f; - desc.MaxLOD = 0.f; - g_pd3dDevice->CreateSamplerState(&desc, &g_pFontSampler); - } -} - -bool ImGui_ImplDX11_CreateDeviceObjects() -{ - if (!g_pd3dDevice) - return false; - if (g_pFontSampler) - ImGui_ImplDX11_InvalidateDeviceObjects(); - - // By using D3DCompile() from <d3dcompiler.h> / d3dcompiler.lib, we introduce a dependency to a given version of d3dcompiler_XX.dll (see D3DCOMPILER_DLL_A) - // If you would like to use this DX11 sample code but remove this dependency you can: - // 1) compile once, save the compiled shader blobs into a file or source code and pass them to CreateVertexShader()/CreatePixelShader() [preferred solution] - // 2) use code to detect any version of the DLL and grab a pointer to D3DCompile from the DLL. - // See https://github.com/ocornut/imgui/pull/638 for sources and details. - - // Create the vertex shader - { - static const char* vertexShader = - "cbuffer vertexBuffer : register(b0) \ - {\ - float4x4 ProjectionMatrix; \ - };\ - struct VS_INPUT\ - {\ - float2 pos : POSITION;\ - float4 col : COLOR0;\ - float2 uv : TEXCOORD0;\ - };\ - \ - struct PS_INPUT\ - {\ - float4 pos : SV_POSITION;\ - float4 col : COLOR0;\ - float2 uv : TEXCOORD0;\ - };\ - \ - PS_INPUT main(VS_INPUT input)\ - {\ - PS_INPUT output;\ - output.pos = mul( ProjectionMatrix, float4(input.pos.xy, 0.f, 1.f));\ - output.col = input.col;\ - output.uv = input.uv;\ - return output;\ - }"; - - ID3DBlob* vertexShaderBlob; - if (FAILED(D3DCompile(vertexShader, strlen(vertexShader), NULL, NULL, NULL, "main", "vs_4_0", 0, 0, &vertexShaderBlob, NULL))) - return false; // NB: Pass ID3DBlob* pErrorBlob to D3DCompile() to get error showing in (const char*)pErrorBlob->GetBufferPointer(). Make sure to Release() the blob! - if (g_pd3dDevice->CreateVertexShader(vertexShaderBlob->GetBufferPointer(), vertexShaderBlob->GetBufferSize(), NULL, &g_pVertexShader) != S_OK) - { - vertexShaderBlob->Release(); - return false; - } - - // Create the input layout - D3D11_INPUT_ELEMENT_DESC local_layout[] = - { - { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (UINT)IM_OFFSETOF(ImDrawVert, pos), D3D11_INPUT_PER_VERTEX_DATA, 0 }, - { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (UINT)IM_OFFSETOF(ImDrawVert, uv), D3D11_INPUT_PER_VERTEX_DATA, 0 }, - { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (UINT)IM_OFFSETOF(ImDrawVert, col), D3D11_INPUT_PER_VERTEX_DATA, 0 }, - }; - if (g_pd3dDevice->CreateInputLayout(local_layout, 3, vertexShaderBlob->GetBufferPointer(), vertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) - { - vertexShaderBlob->Release(); - return false; - } - vertexShaderBlob->Release(); - - // Create the constant buffer - { - D3D11_BUFFER_DESC desc; - desc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); - desc.Usage = D3D11_USAGE_DYNAMIC; - desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; - desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - desc.MiscFlags = 0; - g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVertexConstantBuffer); - } - } - - // Create the pixel shader - { - static const char* pixelShader = - "struct PS_INPUT\ - {\ - float4 pos : SV_POSITION;\ - float4 col : COLOR0;\ - float2 uv : TEXCOORD0;\ - };\ - sampler sampler0;\ - Texture2D texture0;\ - \ - float4 main(PS_INPUT input) : SV_Target\ - {\ - float4 out_col = input.col * texture0.Sample(sampler0, input.uv); \ - return out_col; \ - }"; - - ID3DBlob* pixelShaderBlob; - if (FAILED(D3DCompile(pixelShader, strlen(pixelShader), NULL, NULL, NULL, "main", "ps_4_0", 0, 0, &pixelShaderBlob, NULL))) - return false; // NB: Pass ID3DBlob* pErrorBlob to D3DCompile() to get error showing in (const char*)pErrorBlob->GetBufferPointer(). Make sure to Release() the blob! - if (g_pd3dDevice->CreatePixelShader(pixelShaderBlob->GetBufferPointer(), pixelShaderBlob->GetBufferSize(), NULL, &g_pPixelShader) != S_OK) - { - pixelShaderBlob->Release(); - return false; - } - pixelShaderBlob->Release(); - } - - // Create the blending setup - { - D3D11_BLEND_DESC desc; - ZeroMemory(&desc, sizeof(desc)); - desc.AlphaToCoverageEnable = false; - desc.RenderTarget[0].BlendEnable = true; - desc.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA; - desc.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA; - desc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD; - desc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_INV_SRC_ALPHA; - desc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO; - desc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD; - desc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL; - g_pd3dDevice->CreateBlendState(&desc, &g_pBlendState); - } - - // Create the rasterizer state - { - D3D11_RASTERIZER_DESC desc; - ZeroMemory(&desc, sizeof(desc)); - desc.FillMode = D3D11_FILL_SOLID; - desc.CullMode = D3D11_CULL_NONE; - desc.ScissorEnable = true; - desc.DepthClipEnable = true; - g_pd3dDevice->CreateRasterizerState(&desc, &g_pRasterizerState); - } - - // Create depth-stencil State - { - D3D11_DEPTH_STENCIL_DESC desc; - ZeroMemory(&desc, sizeof(desc)); - desc.DepthEnable = false; - desc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL; - desc.DepthFunc = D3D11_COMPARISON_ALWAYS; - desc.StencilEnable = false; - desc.FrontFace.StencilFailOp = desc.FrontFace.StencilDepthFailOp = desc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP; - desc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS; - desc.BackFace = desc.FrontFace; - g_pd3dDevice->CreateDepthStencilState(&desc, &g_pDepthStencilState); - } - - ImGui_ImplDX11_CreateFontsTexture(); - - return true; -} - -void ImGui_ImplDX11_InvalidateDeviceObjects() -{ - if (!g_pd3dDevice) - return; - - if (g_pFontSampler) { g_pFontSampler->Release(); g_pFontSampler = NULL; } - if (g_pFontTextureView) { g_pFontTextureView->Release(); g_pFontTextureView = NULL; ImGui::GetIO().Fonts->TexID = NULL; } // We copied g_pFontTextureView to io.Fonts->TexID so let's clear that as well. - if (g_pIB) { g_pIB->Release(); g_pIB = NULL; } - if (g_pVB) { g_pVB->Release(); g_pVB = NULL; } - - if (g_pBlendState) { g_pBlendState->Release(); g_pBlendState = NULL; } - if (g_pDepthStencilState) { g_pDepthStencilState->Release(); g_pDepthStencilState = NULL; } - if (g_pRasterizerState) { g_pRasterizerState->Release(); g_pRasterizerState = NULL; } - if (g_pPixelShader) { g_pPixelShader->Release(); g_pPixelShader = NULL; } - if (g_pVertexConstantBuffer) { g_pVertexConstantBuffer->Release(); g_pVertexConstantBuffer = NULL; } - if (g_pInputLayout) { g_pInputLayout->Release(); g_pInputLayout = NULL; } - if (g_pVertexShader) { g_pVertexShader->Release(); g_pVertexShader = NULL; } -} - -bool ImGui_ImplDX11_Init(ID3D11Device* device, ID3D11DeviceContext* device_context) -{ - // Setup back-end capabilities flags - ImGuiIO& io = ImGui::GetIO(); - io.BackendRendererName = "imgui_impl_dx11"; - io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes. - - // Get factory from device - IDXGIDevice* pDXGIDevice = NULL; - IDXGIAdapter* pDXGIAdapter = NULL; - IDXGIFactory* pFactory = NULL; - - if (device->QueryInterface(IID_PPV_ARGS(&pDXGIDevice)) == S_OK) - if (pDXGIDevice->GetParent(IID_PPV_ARGS(&pDXGIAdapter)) == S_OK) - if (pDXGIAdapter->GetParent(IID_PPV_ARGS(&pFactory)) == S_OK) - { - g_pd3dDevice = device; - g_pd3dDeviceContext = device_context; - g_pFactory = pFactory; - } - if (pDXGIDevice) pDXGIDevice->Release(); - if (pDXGIAdapter) pDXGIAdapter->Release(); - g_pd3dDevice->AddRef(); - g_pd3dDeviceContext->AddRef(); - - return true; -} - -void ImGui_ImplDX11_Shutdown() -{ - ImGui_ImplDX11_InvalidateDeviceObjects(); - if (g_pFactory) { g_pFactory->Release(); g_pFactory = NULL; } - if (g_pd3dDevice) { g_pd3dDevice->Release(); g_pd3dDevice = NULL; } - if (g_pd3dDeviceContext) { g_pd3dDeviceContext->Release(); g_pd3dDeviceContext = NULL; } -} - -void ImGui_ImplDX11_NewFrame() -{ - if (!g_pFontSampler) - ImGui_ImplDX11_CreateDeviceObjects(); -} diff --git a/client/src/ui/imgui/imgui_impl_dx11.h b/client/src/ui/imgui/imgui_impl_dx11.h deleted file mode 100644 index cccadcd..0000000 --- a/client/src/ui/imgui/imgui_impl_dx11.h +++ /dev/null @@ -1,25 +0,0 @@ -// dear imgui: Renderer for DirectX11 -// This needs to be used along with a Platform Binding (e.g. Win32) - -// Implemented features: -// [X] Renderer: User texture binding. Use 'ID3D11ShaderResourceView*' as ImTextureID. Read the FAQ about ImTextureID! -// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices. - -// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. -// If you are new to dear imgui, read examples/README.txt and read the documentation at the top of imgui.cpp. -// https://github.com/ocornut/imgui - -#pragma once -#include "imgui.h" // IMGUI_IMPL_API - -struct ID3D11Device; -struct ID3D11DeviceContext; - -IMGUI_IMPL_API bool ImGui_ImplDX11_Init(ID3D11Device* device, ID3D11DeviceContext* device_context); -IMGUI_IMPL_API void ImGui_ImplDX11_Shutdown(); -IMGUI_IMPL_API void ImGui_ImplDX11_NewFrame(); -IMGUI_IMPL_API void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data); - -// Use if you want to reset your rendering device without losing Dear ImGui state. -IMGUI_IMPL_API void ImGui_ImplDX11_InvalidateDeviceObjects(); -IMGUI_IMPL_API bool ImGui_ImplDX11_CreateDeviceObjects(); diff --git a/client/src/ui/imgui/imgui_impl_dx9.cpp b/client/src/ui/imgui/imgui_impl_dx9.cpp new file mode 100644 index 0000000..b4c49cd --- /dev/null +++ b/client/src/ui/imgui/imgui_impl_dx9.cpp @@ -0,0 +1,284 @@ +// dear imgui: Renderer for DirectX9 +// This needs to be used along with a Platform Binding (e.g. Win32) + +// Implemented features: +// [X] Renderer: User texture binding. Use 'LPDIRECT3DTEXTURE9' as ImTextureID. Read the FAQ about ImTextureID! +// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices. + +// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. +// If you are new to dear imgui, read examples/README.txt and read the documentation at the top of imgui.cpp. +// https://github.com/ocornut/imgui + +// CHANGELOG +// (minor and older changes stripped away, please see git history for details) +// 2019-05-29: DirectX9: Added support for large mesh (64K+ vertices), enable ImGuiBackendFlags_RendererHasVtxOffset flag. +// 2019-04-30: DirectX9: Added support for special ImDrawCallback_ResetRenderState callback to reset render state. +// 2019-03-29: Misc: Fixed erroneous assert in ImGui_ImplDX9_InvalidateDeviceObjects(). +// 2019-01-16: Misc: Disabled fog before drawing UI's. Fixes issue #2288. +// 2018-11-30: Misc: Setting up io.BackendRendererName so it can be displayed in the About Window. +// 2018-06-08: Misc: Extracted imgui_impl_dx9.cpp/.h away from the old combined DX9+Win32 example. +// 2018-06-08: DirectX9: Use draw_data->DisplayPos and draw_data->DisplaySize to setup projection matrix and clipping rectangle. +// 2018-05-07: Render: Saving/restoring Transform because they don't seem to be included in the StateBlock. Setting shading mode to Gouraud. +// 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback and exposed ImGui_ImplDX9_RenderDrawData() in the .h file so you can call it yourself. +// 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves. + +#include "imgui.h" +#include "imgui_impl_dx9.h" + +// DirectX +#include <d3d9.h> +#define DIRECTINPUT_VERSION 0x0800 +#include <dinput.h> + +// DirectX data +static LPDIRECT3DDEVICE9 g_pd3dDevice = NULL; +static LPDIRECT3DVERTEXBUFFER9 g_pVB = NULL; +static LPDIRECT3DINDEXBUFFER9 g_pIB = NULL; +static LPDIRECT3DTEXTURE9 g_FontTexture = NULL; +static int g_VertexBufferSize = 5000, g_IndexBufferSize = 10000; + +struct CUSTOMVERTEX +{ + float pos[3]; + D3DCOLOR col; + float uv[2]; +}; +#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_TEX1) + +static void ImGui_ImplDX9_SetupRenderState(ImDrawData* draw_data) +{ + // Setup viewport + D3DVIEWPORT9 vp; + vp.X = vp.Y = 0; + vp.Width = (DWORD)draw_data->DisplaySize.x; + vp.Height = (DWORD)draw_data->DisplaySize.y; + vp.MinZ = 0.0f; + vp.MaxZ = 1.0f; + g_pd3dDevice->SetViewport(&vp); + + // Setup render state: fixed-pipeline, alpha-blending, no face culling, no depth testing, shade mode (for gradient) + g_pd3dDevice->SetPixelShader(NULL); + g_pd3dDevice->SetVertexShader(NULL); + g_pd3dDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); + g_pd3dDevice->SetRenderState(D3DRS_LIGHTING, FALSE); + g_pd3dDevice->SetRenderState(D3DRS_ZENABLE, FALSE); + g_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); + g_pd3dDevice->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE); + g_pd3dDevice->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD); + g_pd3dDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); + g_pd3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); + g_pd3dDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE); + g_pd3dDevice->SetRenderState(D3DRS_SHADEMODE, D3DSHADE_GOURAUD); + g_pd3dDevice->SetRenderState(D3DRS_FOGENABLE, FALSE); + g_pd3dDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE); + g_pd3dDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); + g_pd3dDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE); + g_pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE); + g_pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); + g_pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE); + g_pd3dDevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); + g_pd3dDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); + + // Setup orthographic projection matrix + // Our visible imgui space lies from draw_data->DisplayPos (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayPos is (0,0) for single viewport apps. + // Being agnostic of whether <d3dx9.h> or <DirectXMath.h> can be used, we aren't relying on D3DXMatrixIdentity()/D3DXMatrixOrthoOffCenterLH() or DirectX::XMMatrixIdentity()/DirectX::XMMatrixOrthographicOffCenterLH() + { + float L = draw_data->DisplayPos.x + 0.5f; + float R = draw_data->DisplayPos.x + draw_data->DisplaySize.x + 0.5f; + float T = draw_data->DisplayPos.y + 0.5f; + float B = draw_data->DisplayPos.y + draw_data->DisplaySize.y + 0.5f; + D3DMATRIX mat_identity = { { { 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f } } }; + D3DMATRIX mat_projection = + { { { + 2.0f/(R-L), 0.0f, 0.0f, 0.0f, + 0.0f, 2.0f/(T-B), 0.0f, 0.0f, + 0.0f, 0.0f, 0.5f, 0.0f, + (L+R)/(L-R), (T+B)/(B-T), 0.5f, 1.0f + } } }; + g_pd3dDevice->SetTransform(D3DTS_WORLD, &mat_identity); + g_pd3dDevice->SetTransform(D3DTS_VIEW, &mat_identity); + g_pd3dDevice->SetTransform(D3DTS_PROJECTION, &mat_projection); + } +} + +// Render function. +// (this used to be set in io.RenderDrawListsFn and called by ImGui::Render(), but you can now call this directly from your main loop) +void ImGui_ImplDX9_RenderDrawData(ImDrawData* draw_data) +{ + // Avoid rendering when minimized + if (draw_data->DisplaySize.x <= 0.0f || draw_data->DisplaySize.y <= 0.0f) + return; + + // Create and grow buffers if needed + if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount) + { + if (g_pVB) { g_pVB->Release(); g_pVB = NULL; } + g_VertexBufferSize = draw_data->TotalVtxCount + 5000; + if (g_pd3dDevice->CreateVertexBuffer(g_VertexBufferSize * sizeof(CUSTOMVERTEX), D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, D3DFVF_CUSTOMVERTEX, D3DPOOL_DEFAULT, &g_pVB, NULL) < 0) + return; + } + if (!g_pIB || g_IndexBufferSize < draw_data->TotalIdxCount) + { + if (g_pIB) { g_pIB->Release(); g_pIB = NULL; } + g_IndexBufferSize = draw_data->TotalIdxCount + 10000; + if (g_pd3dDevice->CreateIndexBuffer(g_IndexBufferSize * sizeof(ImDrawIdx), D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, sizeof(ImDrawIdx) == 2 ? D3DFMT_INDEX16 : D3DFMT_INDEX32, D3DPOOL_DEFAULT, &g_pIB, NULL) < 0) + return; + } + + // Backup the DX9 state + IDirect3DStateBlock9* d3d9_state_block = NULL; + if (g_pd3dDevice->CreateStateBlock(D3DSBT_ALL, &d3d9_state_block) < 0) + return; + + // Backup the DX9 transform (DX9 documentation suggests that it is included in the StateBlock but it doesn't appear to) + D3DMATRIX last_world, last_view, last_projection; + g_pd3dDevice->GetTransform(D3DTS_WORLD, &last_world); + g_pd3dDevice->GetTransform(D3DTS_VIEW, &last_view); + g_pd3dDevice->GetTransform(D3DTS_PROJECTION, &last_projection); + + // Copy and convert all vertices into a single contiguous buffer, convert colors to DX9 default format. + // FIXME-OPT: This is a waste of resource, the ideal is to use imconfig.h and + // 1) to avoid repacking colors: #define IMGUI_USE_BGRA_PACKED_COLOR + // 2) to avoid repacking vertices: #define IMGUI_OVERRIDE_DRAWVERT_STRUCT_LAYOUT struct ImDrawVert { ImVec2 pos; float z; ImU32 col; ImVec2 uv; } + CUSTOMVERTEX* vtx_dst; + ImDrawIdx* idx_dst; + if (g_pVB->Lock(0, (UINT)(draw_data->TotalVtxCount * sizeof(CUSTOMVERTEX)), (void**)&vtx_dst, D3DLOCK_DISCARD) < 0) + return; + if (g_pIB->Lock(0, (UINT)(draw_data->TotalIdxCount * sizeof(ImDrawIdx)), (void**)&idx_dst, D3DLOCK_DISCARD) < 0) + return; + for (int n = 0; n < draw_data->CmdListsCount; n++) + { + const ImDrawList* cmd_list = draw_data->CmdLists[n]; + const ImDrawVert* vtx_src = cmd_list->VtxBuffer.Data; + for (int i = 0; i < cmd_list->VtxBuffer.Size; i++) + { + vtx_dst->pos[0] = vtx_src->pos.x; + vtx_dst->pos[1] = vtx_src->pos.y; + vtx_dst->pos[2] = 0.0f; + vtx_dst->col = (vtx_src->col & 0xFF00FF00) | ((vtx_src->col & 0xFF0000) >> 16) | ((vtx_src->col & 0xFF) << 16); // RGBA --> ARGB for DirectX9 + vtx_dst->uv[0] = vtx_src->uv.x; + vtx_dst->uv[1] = vtx_src->uv.y; + vtx_dst++; + vtx_src++; + } + memcpy(idx_dst, cmd_list->IdxBuffer.Data, cmd_list->IdxBuffer.Size * sizeof(ImDrawIdx)); + idx_dst += cmd_list->IdxBuffer.Size; + } + g_pVB->Unlock(); + g_pIB->Unlock(); + g_pd3dDevice->SetStreamSource(0, g_pVB, 0, sizeof(CUSTOMVERTEX)); + g_pd3dDevice->SetIndices(g_pIB); + g_pd3dDevice->SetFVF(D3DFVF_CUSTOMVERTEX); + + // Setup desired DX state + ImGui_ImplDX9_SetupRenderState(draw_data); + + // Render command lists + // (Because we merged all buffers into a single one, we maintain our own offset into them) + int global_vtx_offset = 0; + int global_idx_offset = 0; + ImVec2 clip_off = draw_data->DisplayPos; + for (int n = 0; n < draw_data->CmdListsCount; n++) + { + const ImDrawList* cmd_list = draw_data->CmdLists[n]; + for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++) + { + const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i]; + if (pcmd->UserCallback != NULL) + { + // User callback, registered via ImDrawList::AddCallback() + // (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.) + if (pcmd->UserCallback == ImDrawCallback_ResetRenderState) + ImGui_ImplDX9_SetupRenderState(draw_data); + else + pcmd->UserCallback(cmd_list, pcmd); + } + else + { + const RECT r = { (LONG)(pcmd->ClipRect.x - clip_off.x), (LONG)(pcmd->ClipRect.y - clip_off.y), (LONG)(pcmd->ClipRect.z - clip_off.x), (LONG)(pcmd->ClipRect.w - clip_off.y) }; + const LPDIRECT3DTEXTURE9 texture = (LPDIRECT3DTEXTURE9)pcmd->TextureId; + g_pd3dDevice->SetTexture(0, texture); + g_pd3dDevice->SetScissorRect(&r); + g_pd3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, pcmd->VtxOffset + global_vtx_offset, 0, (UINT)cmd_list->VtxBuffer.Size, pcmd->IdxOffset + global_idx_offset, pcmd->ElemCount / 3); + } + } + global_idx_offset += cmd_list->IdxBuffer.Size; + global_vtx_offset += cmd_list->VtxBuffer.Size; + } + + // Restore the DX9 transform + g_pd3dDevice->SetTransform(D3DTS_WORLD, &last_world); + g_pd3dDevice->SetTransform(D3DTS_VIEW, &last_view); + g_pd3dDevice->SetTransform(D3DTS_PROJECTION, &last_projection); + + // Restore the DX9 state + d3d9_state_block->Apply(); + d3d9_state_block->Release(); +} + +bool ImGui_ImplDX9_Init(IDirect3DDevice9* device) +{ + // Setup back-end capabilities flags + ImGuiIO& io = ImGui::GetIO(); + io.BackendRendererName = "imgui_impl_dx9"; + io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes. + + g_pd3dDevice = device; + g_pd3dDevice->AddRef(); + return true; +} + +void ImGui_ImplDX9_Shutdown() +{ + ImGui_ImplDX9_InvalidateDeviceObjects(); + if (g_pd3dDevice) { g_pd3dDevice->Release(); g_pd3dDevice = NULL; } +} + +static bool ImGui_ImplDX9_CreateFontsTexture() +{ + // Build texture atlas + ImGuiIO& io = ImGui::GetIO(); + unsigned char* pixels; + int width, height, bytes_per_pixel; + io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height, &bytes_per_pixel); + + // Upload texture to graphics system + g_FontTexture = NULL; + if (g_pd3dDevice->CreateTexture(width, height, 1, D3DUSAGE_DYNAMIC, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &g_FontTexture, NULL) < 0) + return false; + D3DLOCKED_RECT tex_locked_rect; + if (g_FontTexture->LockRect(0, &tex_locked_rect, NULL, 0) != D3D_OK) + return false; + for (int y = 0; y < height; y++) + memcpy((unsigned char*)tex_locked_rect.pBits + tex_locked_rect.Pitch * y, pixels + (width * bytes_per_pixel) * y, (width * bytes_per_pixel)); + g_FontTexture->UnlockRect(0); + + // Store our identifier + io.Fonts->TexID = (ImTextureID)g_FontTexture; + + return true; +} + +bool ImGui_ImplDX9_CreateDeviceObjects() +{ + if (!g_pd3dDevice) + return false; + if (!ImGui_ImplDX9_CreateFontsTexture()) + return false; + return true; +} + +void ImGui_ImplDX9_InvalidateDeviceObjects() +{ + if (!g_pd3dDevice) + return; + if (g_pVB) { g_pVB->Release(); g_pVB = NULL; } + if (g_pIB) { g_pIB->Release(); g_pIB = NULL; } + if (g_FontTexture) { g_FontTexture->Release(); g_FontTexture = NULL; ImGui::GetIO().Fonts->TexID = NULL; } // We copied g_pFontTextureView to io.Fonts->TexID so let's clear that as well. +} + +void ImGui_ImplDX9_NewFrame() +{ + if (!g_FontTexture) + ImGui_ImplDX9_CreateDeviceObjects(); +} diff --git a/client/src/ui/imgui/imgui_impl_dx9.h b/client/src/ui/imgui/imgui_impl_dx9.h new file mode 100644 index 0000000..b93c89f --- /dev/null +++ b/client/src/ui/imgui/imgui_impl_dx9.h @@ -0,0 +1,24 @@ +// dear imgui: Renderer for DirectX9 +// This needs to be used along with a Platform Binding (e.g. Win32) + +// Implemented features: +// [X] Renderer: User texture binding. Use 'LPDIRECT3DTEXTURE9' as ImTextureID. Read the FAQ about ImTextureID! +// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices. + +// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. +// If you are new to dear imgui, read examples/README.txt and read the documentation at the top of imgui.cpp. +// https://github.com/ocornut/imgui + +#pragma once +#include "imgui.h" // IMGUI_IMPL_API + +struct IDirect3DDevice9; + +IMGUI_IMPL_API bool ImGui_ImplDX9_Init(IDirect3DDevice9* device); +IMGUI_IMPL_API void ImGui_ImplDX9_Shutdown(); +IMGUI_IMPL_API void ImGui_ImplDX9_NewFrame(); +IMGUI_IMPL_API void ImGui_ImplDX9_RenderDrawData(ImDrawData* draw_data); + +// Use if you want to reset your rendering device without losing Dear ImGui state. +IMGUI_IMPL_API bool ImGui_ImplDX9_CreateDeviceObjects(); +IMGUI_IMPL_API void ImGui_ImplDX9_InvalidateDeviceObjects(); diff --git a/client/src/ui/ui.cpp b/client/src/ui/ui.cpp index 242bb5c..3ef383d 100644 --- a/client/src/ui/ui.cpp +++ b/client/src/ui/ui.cpp @@ -1,10 +1,9 @@ #include "../include.h" #include "ui.h" -ID3D11Device* ui::device; -ID3D11DeviceContext* ui::device_context; -IDXGISwapChain* ui::swap_chain; -ID3D11RenderTargetView* ui::main_render_target; +IDirect3D9* ui::d3d; +IDirect3DDevice9* ui::device; +D3DPRESENT_PARAMETERS ui::present_params; extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); @@ -12,8 +11,7 @@ LRESULT ui::wnd_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) { if (ImGui_ImplWin32_WndProcHandler(hwnd, message, wparam, lparam)) return true; - switch (message) - { + switch (message) { case WM_DESTROY: PostQuitMessage(0); return 0; @@ -22,7 +20,7 @@ LRESULT ui::wnd_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) { return DefWindowProc(hwnd, message, wparam, lparam); } -HWND ui::create(HINSTANCE instance, const std::pair<int, int> size, const std::pair<int, int> pos /*= { 400, 400 }*/) { +HWND ui::create_window(HINSTANCE instance, const std::pair<int, int> size, const std::pair<int, int> pos /*= { 400, 400 }*/) { WNDCLASSEX wc; std::memset(&wc, 0, sizeof(wc)); @@ -43,61 +41,29 @@ HWND ui::create(HINSTANCE instance, const std::pair<int, int> size, const std::p } bool ui::create_device(HWND hwnd) { - DXGI_SWAP_CHAIN_DESC sd; - ZeroMemory(&sd, sizeof(sd)); - sd.BufferCount = 2; - sd.BufferDesc.Width = 0; - sd.BufferDesc.Height = 0; - sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - sd.BufferDesc.RefreshRate.Numerator = 60; - sd.BufferDesc.RefreshRate.Denominator = 1; - sd.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH; - sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; - sd.OutputWindow = hwnd; - sd.SampleDesc.Count = 1; - sd.SampleDesc.Quality = 0; - sd.Windowed = TRUE; - sd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; - - UINT createDeviceFlags = 0; - //createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG; - D3D_FEATURE_LEVEL featureLevel; - const D3D_FEATURE_LEVEL featureLevelArray[2] = { D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_10_0, }; - auto ret = D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, createDeviceFlags, featureLevelArray, 2, - D3D11_SDK_VERSION, &sd, &swap_chain, &device, &featureLevel, &device_context); - if (ret != S_OK) + d3d = Direct3DCreate9(D3D_SDK_VERSION); + if (!d3d) { return false; + } - create_target(); + std::memset(&present_params, 0, sizeof(present_params)); - return true; -} + present_params.Windowed = TRUE; + present_params.SwapEffect = D3DSWAPEFFECT_DISCARD; + present_params.BackBufferFormat = D3DFMT_UNKNOWN; + present_params.EnableAutoDepthStencil = TRUE; + present_params.AutoDepthStencilFormat = D3DFMT_D16; + present_params.PresentationInterval = D3DPRESENT_INTERVAL_ONE; -void ui::create_target() { - ID3D11Texture2D* pBackBuffer; - swap_chain->GetBuffer(0, IID_PPV_ARGS(&pBackBuffer)); - device->CreateRenderTargetView(pBackBuffer, NULL, &main_render_target); - pBackBuffer->Release(); -} - -void ui::cleanup_target() { - if (main_render_target) { - main_render_target->Release(); - main_render_target = nullptr; + auto res = d3d->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd, D3DCREATE_HARDWARE_VERTEXPROCESSING, &present_params, &device); + if (res != D3D_OK) { + return false; } + + return true; } void ui::cleanup_device() { - cleanup_target(); - if (swap_chain) { - swap_chain->Release(); - } - - if (device_context) { - device_context->Release(); - } - - if (device) { - device->Release(); - } + device->Release(); + d3d->Release(); }
\ No newline at end of file diff --git a/client/src/ui/ui.h b/client/src/ui/ui.h index 7fd3248..4ad7c76 100644 --- a/client/src/ui/ui.h +++ b/client/src/ui/ui.h @@ -2,23 +2,21 @@ #include "imgui/imgui.h" +#include "imgui/imgui_impl_dx9.h" #include "imgui/imgui_impl_win32.h" -#include "imgui/imgui_impl_dx11.h" #include "imgui/imgui_stdlib.h" -#include <d3d11.h> + +#include <d3d9.h> namespace ui { - extern ID3D11Device* device; - extern ID3D11DeviceContext* device_context; - extern IDXGISwapChain* swap_chain; - extern ID3D11RenderTargetView* main_render_target; + extern IDirect3D9* d3d; + extern IDirect3DDevice9* device; + extern D3DPRESENT_PARAMETERS present_params; LRESULT wnd_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam); - HWND create(HINSTANCE instance, const std::pair<int, int> size, const std::pair<int, int> pos = { 400, 400 }); + HWND create_window(HINSTANCE instance, const std::pair<int, int> size, const std::pair<int, int> pos = { 400, 400 }); bool create_device(HWND hwnd); - void create_target(); - void cleanup_target(); void cleanup_device(); };
\ No newline at end of file diff --git a/client/src/util/native.h b/client/src/util/native.h index aa41b65..d8b580a 100644 --- a/client/src/util/native.h +++ b/client/src/util/native.h @@ -157,11 +157,114 @@ namespace native { uint8_t Flags; }; - enum SECTION_INHERIT { - ViewShare = 1, - ViewUnmap = 2 + enum PROCESSINFOCLASS + { + ProcessBasicInformation, // q: PROCESS_BASIC_INFORMATION, PROCESS_EXTENDED_BASIC_INFORMATION + ProcessQuotaLimits, // qs: QUOTA_LIMITS, QUOTA_LIMITS_EX + ProcessIoCounters, // q: IO_COUNTERS + ProcessVmCounters, // q: VM_COUNTERS, VM_COUNTERS_EX, VM_COUNTERS_EX2 + ProcessTimes, // q: KERNEL_USER_TIMES + ProcessBasePriority, // s: KPRIORITY + ProcessRaisePriority, // s: ULONG + ProcessDebugPort, // q: HANDLE + ProcessExceptionPort, // s: PROCESS_EXCEPTION_PORT + ProcessAccessToken, // s: PROCESS_ACCESS_TOKEN + ProcessLdtInformation, // qs: PROCESS_LDT_INFORMATION // 10 + ProcessLdtSize, // s: PROCESS_LDT_SIZE + ProcessDefaultHardErrorMode, // qs: ULONG + ProcessIoPortHandlers, // (kernel-mode only) // PROCESS_IO_PORT_HANDLER_INFORMATION + ProcessPooledUsageAndLimits, // q: POOLED_USAGE_AND_LIMITS + ProcessWorkingSetWatch, // q: PROCESS_WS_WATCH_INFORMATION[]; s: void + ProcessUserModeIOPL, // qs: ULONG (requires SeTcbPrivilege) + ProcessEnableAlignmentFaultFixup, // s: BOOLEAN + ProcessPriorityClass, // qs: PROCESS_PRIORITY_CLASS + ProcessWx86Information, // qs: ULONG (requires SeTcbPrivilege) (VdmAllowed) + ProcessHandleCount, // q: ULONG, PROCESS_HANDLE_INFORMATION // 20 + ProcessAffinityMask, // s: KAFFINITY + ProcessPriorityBoost, // qs: ULONG + ProcessDeviceMap, // qs: PROCESS_DEVICEMAP_INFORMATION, PROCESS_DEVICEMAP_INFORMATION_EX + ProcessSessionInformation, // q: PROCESS_SESSION_INFORMATION + ProcessForegroundInformation, // s: PROCESS_FOREGROUND_BACKGROUND + ProcessWow64Information, // q: ULONG_PTR + ProcessImageFileName, // q: UNICODE_STRING + ProcessLUIDDeviceMapsEnabled, // q: ULONG + ProcessBreakOnTermination, // qs: ULONG + ProcessDebugObjectHandle, // q: HANDLE // 30 + ProcessDebugFlags, // qs: ULONG + ProcessHandleTracing, // q: PROCESS_HANDLE_TRACING_QUERY; s: size 0 disables, otherwise enables + ProcessIoPriority, // qs: IO_PRIORITY_HINT + ProcessExecuteFlags, // qs: ULONG + ProcessResourceManagement, // ProcessTlsInformation // PROCESS_TLS_INFORMATION + ProcessCookie, // q: ULONG + ProcessImageInformation, // q: SECTION_IMAGE_INFORMATION + ProcessCycleTime, // q: PROCESS_CYCLE_TIME_INFORMATION // since VISTA + ProcessPagePriority, // q: PAGE_PRIORITY_INFORMATION + ProcessInstrumentationCallback, // qs: PROCESS_INSTRUMENTATION_CALLBACK_INFORMATION // 40 + ProcessThreadStackAllocation, // s: PROCESS_STACK_ALLOCATION_INFORMATION, PROCESS_STACK_ALLOCATION_INFORMATION_EX + ProcessWorkingSetWatchEx, // q: PROCESS_WS_WATCH_INFORMATION_EX[] + ProcessImageFileNameWin32, // q: UNICODE_STRING + ProcessImageFileMapping, // q: HANDLE (input) + ProcessAffinityUpdateMode, // qs: PROCESS_AFFINITY_UPDATE_MODE + ProcessMemoryAllocationMode, // qs: PROCESS_MEMORY_ALLOCATION_MODE + ProcessGroupInformation, // q: USHORT[] + ProcessTokenVirtualizationEnabled, // s: ULONG + ProcessConsoleHostProcess, // q: ULONG_PTR // ProcessOwnerInformation + ProcessWindowInformation, // q: PROCESS_WINDOW_INFORMATION // 50 + ProcessHandleInformation, // q: PROCESS_HANDLE_SNAPSHOT_INFORMATION // since WIN8 + ProcessMitigationPolicy, // s: PROCESS_MITIGATION_POLICY_INFORMATION + ProcessDynamicFunctionTableInformation, + ProcessHandleCheckingMode, // qs: ULONG; s: 0 disables, otherwise enables + ProcessKeepAliveCount, // q: PROCESS_KEEPALIVE_COUNT_INFORMATION + ProcessRevokeFileHandles, // s: PROCESS_REVOKE_FILE_HANDLES_INFORMATION + ProcessWorkingSetControl, // s: PROCESS_WORKING_SET_CONTROL + ProcessHandleTable, // q: ULONG[] // since WINBLUE + ProcessCheckStackExtentsMode, + ProcessCommandLineInformation, // q: UNICODE_STRING // 60 + ProcessProtectionInformation, // q: PS_PROTECTION + ProcessMemoryExhaustion, // PROCESS_MEMORY_EXHAUSTION_INFO // since THRESHOLD + ProcessFaultInformation, // PROCESS_FAULT_INFORMATION + ProcessTelemetryIdInformation, // PROCESS_TELEMETRY_ID_INFORMATION + ProcessCommitReleaseInformation, // PROCESS_COMMIT_RELEASE_INFORMATION + ProcessDefaultCpuSetsInformation, + ProcessAllowedCpuSetsInformation, + ProcessSubsystemProcess, + ProcessJobMemoryInformation, // PROCESS_JOB_MEMORY_INFO + ProcessInPrivate, // since THRESHOLD2 // 70 + ProcessRaiseUMExceptionOnInvalidHandleClose, // qs: ULONG; s: 0 disables, otherwise enables + ProcessIumChallengeResponse, + ProcessChildProcessInformation, // PROCESS_CHILD_PROCESS_INFORMATION + ProcessHighGraphicsPriorityInformation, + ProcessSubsystemInformation, // q: SUBSYSTEM_INFORMATION_TYPE // since REDSTONE2 + ProcessEnergyValues, // PROCESS_ENERGY_VALUES, PROCESS_EXTENDED_ENERGY_VALUES + ProcessActivityThrottleState, // PROCESS_ACTIVITY_THROTTLE_STATE + ProcessActivityThrottlePolicy, // PROCESS_ACTIVITY_THROTTLE_POLICY + ProcessWin32kSyscallFilterInformation, + ProcessDisableSystemAllowedCpuSets, // 80 + ProcessWakeInformation, // PROCESS_WAKE_INFORMATION + ProcessEnergyTrackingState, // PROCESS_ENERGY_TRACKING_STATE + ProcessManageWritesToExecutableMemory, // MANAGE_WRITES_TO_EXECUTABLE_MEMORY // since REDSTONE3 + ProcessCaptureTrustletLiveDump, + ProcessTelemetryCoverage, + ProcessEnclaveInformation, + ProcessEnableReadWriteVmLogging, // PROCESS_READWRITEVM_LOGGING_INFORMATION + ProcessUptimeInformation, // PROCESS_UPTIME_INFORMATION + ProcessImageSection, // q: HANDLE + ProcessDebugAuthInformation, // since REDSTONE4 // 90 + ProcessSystemResourceManagement, // PROCESS_SYSTEM_RESOURCE_MANAGEMENT + ProcessSequenceNumber, // q: ULONGLONG + ProcessLoaderDetour, // since REDSTONE5 + ProcessSecurityDomainInformation, // PROCESS_SECURITY_DOMAIN_INFORMATION + ProcessCombineSecurityDomainsInformation, // PROCESS_COMBINE_SECURITY_DOMAINS_INFORMATION + ProcessEnableLogging, // PROCESS_LOGGING_INFORMATION + ProcessLeapSecondInformation, // PROCESS_LEAP_SECOND_INFORMATION + ProcessFiberShadowStackAllocation, // PROCESS_FIBER_SHADOW_STACK_ALLOCATION_INFORMATION // since 19H1 + ProcessFreeFiberShadowStackAllocation, // PROCESS_FREE_FIBER_SHADOW_STACK_ALLOCATION_INFORMATION + ProcessAltSystemCallInformation, // since 20H1 // 100 + ProcessDynamicEHContinuationTargets, // PROCESS_DYNAMIC_EH_CONTINUATION_TARGETS_INFORMATION + MaxProcessInfoClass }; + using NtQuerySystemInformation = NTSTATUS(__stdcall*)(SYSTEM_INFORMATION_CLASS, PVOID, SIZE_T, PULONG); using NtOpenProcess = NTSTATUS(__stdcall*)(PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES, CLIENT_ID*); using NtOpenThread = NTSTATUS(__stdcall*)(PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES, CLIENT_ID*); @@ -174,8 +277,4 @@ namespace native { using NtWaitForSingleObject = NTSTATUS(__stdcall*)(HANDLE, BOOLEAN, PLARGE_INTEGER); using NtCreateThreadEx = NTSTATUS(__stdcall*)(PHANDLE, ACCESS_MASK, PVOID, HANDLE, LPTHREAD_START_ROUTINE, PVOID, ULONG, ULONG_PTR, SIZE_T, SIZE_T, PVOID); - using NtCreateSection = NTSTATUS(__stdcall*)(PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES, PLARGE_INTEGER, ULONG, ULONG, HANDLE); - using NtMapViewOfSection = NTSTATUS(__stdcall*)(HANDLE, HANDLE, PVOID *, ULONG_PTR, SIZE_T, PLARGE_INTEGER, PSIZE_T, SECTION_INHERIT, ULONG, ULONG); - using NtUnmapViewOfSection = NTSTATUS(__stdcall*)(HANDLE, PVOID); - }; // namespace native
\ No newline at end of file diff --git a/client/src/util/util.cpp b/client/src/util/util.cpp index fab886e..7103604 100644 --- a/client/src/util/util.cpp +++ b/client/src/util/util.cpp @@ -56,11 +56,13 @@ bool util::close_handle(HANDLE handle) { } -void pe::get_all_modules(std::unordered_map<std::string, virtual_image>& modules) { +bool pe::get_all_modules(std::unordered_map<std::string, virtual_image>& modules) { + modules.clear(); + auto peb = util::peb(); - if (!peb) return; + if (!peb) return false; - if (!peb->Ldr->InMemoryOrderModuleList.Flink) return; + if (!peb->Ldr->InMemoryOrderModuleList.Flink) return false; auto* list = &peb->Ldr->InMemoryOrderModuleList; @@ -74,4 +76,6 @@ void pe::get_all_modules(std::unordered_map<std::string, virtual_image>& modules modules[name] = virtual_image(entry->DllBase); } + + return !modules.empty(); }
\ No newline at end of file |