├── .gitignore ├── .gitmodules ├── LICENSE ├── README.md ├── Source.def ├── dep ├── gw2al_api.h └── gw2al_lib_imgui.h ├── gw2addon.sln ├── gw2addon.vcxproj ├── gw2addon.vcxproj.filters └── src ├── Gui.cpp ├── Gui.h ├── Main.cpp ├── Main.h ├── addon.cpp ├── addon.h ├── build_version.h ├── stdafx.cpp ├── stdafx.h └── targetver.h /.gitignore: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | *.d 3 | 4 | # Compiled Object files 5 | *.slo 6 | *.lo 7 | *.o 8 | *.obj 9 | 10 | # Precompiled Headers 11 | *.gch 12 | *.pch 13 | 14 | # Compiled Dynamic libraries 15 | *.so 16 | *.dylib 17 | *.dll 18 | 19 | # Fortran module files 20 | *.mod 21 | *.smod 22 | 23 | # Compiled Static libraries 24 | *.lai 25 | *.la 26 | *.a 27 | *.lib 28 | 29 | # Executables 30 | *.exe 31 | *.out 32 | *.app 33 | 34 | .vs/* 35 | bin/* 36 | x64/* 37 | *.vcxproj.user 38 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "dep/imgui"] 2 | path = dep/imgui 3 | url = https://github.com/gw2-addon-loader/imgui 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 gw2-addon-loader 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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SelectRenderer 2 | 3 | Ingame UI based render selection for GW2 4 | Allows selection of various render paths like DXVK, d912pxy and said paths with reshade. 5 | 6 | Menu to select render shows up at game start and allows to change render or will hide itself. 7 | 8 | # Render variants 9 | 10 | Release package does not contain DXVK, d912pxy or reshade. 11 | 12 | To be able to select them, install to said paths 13 | 14 | [DXVK](https://github.com/doitsujin/dxvk/): \/addons/dxvk/d3d9.dll 15 | 16 | [DXVK-async](https://github.com/Sporif/dxvk-async): \/addons/dxvk-async/d3d9.dll 17 | 18 | [d912pxy](https://github.com/megai2/d912pxy): \/addons/d912pxy (via addon manager) 19 | 20 | reshade dx9: \/addons/reshade/d3d9.dll 21 | 22 | reshade dx12: \/addons/reshade/dxgi.dll 23 | 24 | gw2enhanced: \/addons/gw2enhanced 25 | 26 | gw2hook: \/addons/gw2hook/d3d9.dll 27 | 28 | -------------------------------------------------------------------------------- /Source.def: -------------------------------------------------------------------------------- 1 | LIBRARY gw2addon_SelectRender.dll 2 | EXPORTS 3 | gw2addon_get_description 4 | gw2addon_load 5 | gw2addon_unload -------------------------------------------------------------------------------- /dep/gw2al_api.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define GW2AL_API_VER_MAJOR 1 4 | #define GW2AL_API_VER_MINOR 0 5 | 6 | #define GW2AL_CORE_DEP_ENTRY { L"loader_core", L"core gw2 al API", GW2AL_API_VER_MAJOR, GW2AL_API_VER_MINOR, 1, 0 } 7 | 8 | #define gw2al_hashed_name unsigned long long 9 | #define gw2al_event_id unsigned long 10 | 11 | 12 | typedef struct gw2al_addon_dsc { 13 | const wchar_t* name; 14 | const wchar_t* description; 15 | unsigned char majorVer; 16 | unsigned char minorVer; 17 | unsigned int revision; 18 | 19 | gw2al_addon_dsc* dependList; 20 | } gw2al_addon_dsc; 21 | 22 | //api return codes 23 | 24 | typedef enum gw2al_api_ret { 25 | GW2AL_OK, 26 | GW2AL_FAIL, 27 | GW2AL_IN_USE, 28 | GW2AL_NOT_FOUND, 29 | GW2AL_BAD_DLL, 30 | GW2AL_DEP_NOT_LOADED, 31 | GW2AL_DEP_OUTDATED, 32 | GW2AL_DEP_STILL_LOADED, 33 | GW2AL_STATIC_LIMIT_HIT 34 | } gw2al_api_ret; 35 | 36 | //used to handle events 37 | typedef void(*gw2al_api_event_handler)(void* data); 38 | 39 | #define GW2AL_CORE_FUNN_HASH_NAME 1 40 | #define GW2AL_CORE_FUNN_REG_FUN 2 41 | #define GW2AL_CORE_FUNN_UNREG_FUN 3 42 | #define GW2AL_CORE_FUNN_QUERY_FUN 4 43 | #define GW2AL_CORE_FUNN_FILL_VTBL 5 44 | #define GW2AL_CORE_FUNN_UNLOAD_ADDON 6 45 | #define GW2AL_CORE_FUNN_LOAD_ADDON 7 46 | #define GW2AL_CORE_FUNN_QUERY_ADDON 8 47 | #define GW2AL_CORE_FUNN_WATCH_EVENT 9 48 | #define GW2AL_CORE_FUNN_UNWATCH_EVENT 10 49 | #define GW2AL_CORE_FUNN_QUERY_EVENT 11 50 | #define GW2AL_CORE_FUNN_TRIGGER_EVENT 12 51 | #define GW2AL_CORE_FUNN_CLIENT_UNLOAD 13 52 | #define GW2AL_CORE_FUNN_LOG_TEXT_SYNC 14 53 | #define GW2AL_CORE_FUNN_LOG_TEXT 15 54 | #define GW2AL_CORE_FUNN_D3DCREATE_HOOK 16 55 | #define GW2AL_CORE_FUNN_D3D11CREATE_HOOK 17 56 | #define GW2AL_CORE_FUNN_DXGICREATE_HOOK 18 57 | 58 | typedef enum gw2al_log_level { 59 | LL_INFO = 0, 60 | LL_ERR, 61 | LL_WARN, 62 | LL_DEBUG 63 | } gw2al_log_level; 64 | 65 | typedef struct gw2al_core_vtable { 66 | //converts string to hash for usage in other functions 67 | gw2al_hashed_name(*hash_name)(const wchar_t* name); 68 | 69 | //register/unregister user functions to be called by other addons 70 | gw2al_api_ret(*register_function)(void* function, gw2al_hashed_name name); 71 | void (*unregister_function)(gw2al_hashed_name name); 72 | 73 | //query function pointer from registered list 74 | void* (*query_function)(gw2al_hashed_name name); 75 | 76 | //fills table of functions using query_function 77 | void (*fill_vtable)(const gw2al_hashed_name* nameList, void** vtable); 78 | 79 | //functions to unload/load addons 80 | gw2al_api_ret(*unload_addon)(gw2al_hashed_name name); 81 | gw2al_api_ret(*load_addon)(const wchar_t* name); 82 | 83 | //function to get currently loaded addon description 84 | gw2al_addon_dsc* (*query_addon)(gw2al_hashed_name name); 85 | 86 | //simple event api 87 | //watch event can add a number of handlers on event name with priority 88 | //query event will get internal event id to speedup trigger_event calls 89 | 90 | gw2al_api_ret(*watch_event)(gw2al_event_id id, gw2al_hashed_name subscriber, gw2al_api_event_handler handler, unsigned int priority); 91 | void (*unwatch_event)(gw2al_event_id id, gw2al_hashed_name subscriber); 92 | gw2al_event_id(*query_event)(gw2al_hashed_name name); 93 | unsigned int (*trigger_event)(gw2al_event_id id, void* data); 94 | 95 | //unload function to delete properly unload things on client exit 96 | 97 | void (*client_unload)(); 98 | 99 | //simple logging function 100 | 101 | void (*log_text_sync)(gw2al_log_level level, const wchar_t* source, const wchar_t* text); 102 | void (*log_text)(gw2al_log_level level, const wchar_t* source, const wchar_t* text); 103 | 104 | } gw2al_core_vtable; 105 | 106 | //addon must export this functions as 107 | //gw2addon_get_description 108 | //gw2addon_load 109 | //gw2addon_unload 110 | 111 | typedef gw2al_addon_dsc* (*gw2al_addon_get_dsc_proc)(); 112 | typedef gw2al_api_ret(*gw2al_addon_load_proc)(gw2al_core_vtable* core_api); 113 | typedef gw2al_api_ret(*gw2al_addon_unload_proc)(int gameExiting); 114 | -------------------------------------------------------------------------------- /dep/gw2al_lib_imgui.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #define LIB_IMGUI_DEP_ENTRY { L"lib_imgui", L" ", 2, 0, 1, 0 } 7 | 8 | template 9 | class lib_imgui 10 | { 11 | const wchar_t* getContextExportName = L"lib_imgui_get_context"; 12 | const wchar_t* guiDrawEventName = L"lib_imgui_draw_event"; 13 | 14 | gw2al_hashed_name getContextExportNameHash = 0; 15 | gw2al_hashed_name guiDrawEventNameHash = 0; 16 | gw2al_event_id guiDrawEventId = 0; 17 | 18 | static lib_imgui& instance(); 19 | 20 | typedef void* (*procType)(); 21 | void* (*getImguiContextProc)(); 22 | static void drawEventHandler(void* imguiContext) 23 | { 24 | ImGui::SetCurrentContext((ImGuiContext*)imguiContext); 25 | instance().handler.draw(); 26 | } 27 | 28 | gw2al_core_vtable* gAPI = nullptr; 29 | gw2al_hashed_name subscriber = 0; 30 | 31 | UserHandler handler; 32 | 33 | void initInternal(gw2al_core_vtable* in_api, gw2al_hashed_name addonNameHash, unsigned int priorityOverride) 34 | { 35 | gAPI = in_api; 36 | 37 | getContextExportNameHash = gAPI->hash_name((wchar_t*)getContextExportName); 38 | guiDrawEventNameHash = gAPI->hash_name((wchar_t*)guiDrawEventName); 39 | guiDrawEventId = gAPI->query_event(guiDrawEventNameHash); 40 | 41 | getImguiContextProc = (procType)gAPI->query_function(getContextExportNameHash); 42 | subscriber = addonNameHash; 43 | gAPI->watch_event(guiDrawEventId, addonNameHash, &drawEventHandler, priorityOverride); 44 | 45 | ImGui::SetCurrentContext((ImGuiContext*)getImguiContextProc()); 46 | handler.init(); 47 | } 48 | 49 | public: 50 | void init(gw2al_core_vtable* in_api, const wchar_t* addonName, unsigned int priorityOverride = 0) 51 | { 52 | initInternal(in_api, in_api->hash_name((wchar_t*)addonName), priorityOverride); 53 | } 54 | 55 | void init(gw2al_core_vtable* in_api, gw2al_hashed_name addonNameHash, unsigned int priorityOverride = 0) 56 | { 57 | initInternal(in_api, addonNameHash, priorityOverride); 58 | } 59 | 60 | void deinit() 61 | { 62 | gAPI->unwatch_event(guiDrawEventId, subscriber); 63 | handler.deinit(); 64 | } 65 | 66 | UserHandler* operator->() 67 | { 68 | return &handler; 69 | } 70 | 71 | ImGuiContext* getImguiContext() 72 | { 73 | return (ImGuiContext*)getImguiContextProc(); 74 | } 75 | }; 76 | 77 | /* 78 | class UserInterface 79 | { 80 | UserInterface() = default; 81 | 82 | void init() 83 | { 84 | //called after lib_imgui init with setted up imgui context 85 | } 86 | 87 | void draw() 88 | { 89 | //called every frame to draw interface if not hidden 90 | } 91 | 92 | void deinit() 93 | { 94 | //called at deinit 95 | } 96 | } 97 | 98 | //somewhere in addon instance 99 | 100 | lib_imgui ui; 101 | 102 | template<> 103 | inline lib_imgui& lib_imgui::instance() 104 | { 105 | return ui; 106 | } 107 | 108 | */ -------------------------------------------------------------------------------- /gw2addon.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.29728.190 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gw2addon", "gw2addon.vcxproj", "{BDCB35C3-8ED9-4A6E-A346-D16F17D4600C}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Release|x64 = Release|x64 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {BDCB35C3-8ED9-4A6E-A346-D16F17D4600C}.Debug|x64.ActiveCfg = Debug|x64 15 | {BDCB35C3-8ED9-4A6E-A346-D16F17D4600C}.Debug|x64.Build.0 = Debug|x64 16 | {BDCB35C3-8ED9-4A6E-A346-D16F17D4600C}.Release|x64.ActiveCfg = Release|x64 17 | {BDCB35C3-8ED9-4A6E-A346-D16F17D4600C}.Release|x64.Build.0 = Release|x64 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {B4AB9663-402C-42D7-94ED-864553319B48} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /gw2addon.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | x64 7 | 8 | 9 | Release 10 | x64 11 | 12 | 13 | 14 | 16.0 15 | {AE0B7438-0B6E-497E-BE0C-117FE82D2770} 16 | gw2addon 17 | 10.0 18 | SelectRender 19 | 20 | 21 | 22 | DynamicLibrary 23 | true 24 | v142 25 | Unicode 26 | 27 | 28 | DynamicLibrary 29 | false 30 | v142 31 | true 32 | Unicode 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | true 48 | gw2addon_$(ProjectName) 49 | $(SolutionDir)bin\$(Platform)\$(Configuration)\addons\$(ProjectName)\ 50 | $(ProjectDir)\dep\imgui;$(ProjectDir)\src;$(IncludePath);$(ProjectDir)\dep 51 | 52 | 53 | false 54 | gw2addon_$(ProjectName) 55 | $(SolutionDir)bin\$(Platform)\$(Configuration)\addons\$(ProjectName)\ 56 | $(ProjectDir)\dep\imgui;$(ProjectDir)\src;$(IncludePath);$(ProjectDir)\dep 57 | 58 | 59 | 60 | Use 61 | Level3 62 | Disabled 63 | true 64 | _DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) 65 | true 66 | stdafx.h 67 | 68 | 69 | Windows 70 | true 71 | Source.def 72 | 73 | 74 | 75 | 76 | Use 77 | Level3 78 | MaxSpeed 79 | true 80 | true 81 | true 82 | NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) 83 | true 84 | stdafx.h 85 | 86 | 87 | Windows 88 | true 89 | true 90 | true 91 | Source.def 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | Create 110 | Create 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | -------------------------------------------------------------------------------- /gw2addon.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 6 | h;hh;hpp;hxx;hm;inl;inc;ipp;xsd 7 | 8 | 9 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 10 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 11 | 12 | 13 | {e515062e-ccf6-4265-a455-dad31ae6d3b3} 14 | 15 | 16 | 17 | 18 | headers 19 | 20 | 21 | headers 22 | 23 | 24 | headers 25 | 26 | 27 | headers 28 | 29 | 30 | headers 31 | 32 | 33 | imgui 34 | 35 | 36 | imgui 37 | 38 | 39 | imgui 40 | 41 | 42 | sources 43 | 44 | 45 | 46 | 47 | sources 48 | 49 | 50 | sources 51 | 52 | 53 | sources 54 | 55 | 56 | imgui 57 | 58 | 59 | imgui 60 | 61 | 62 | sources 63 | 64 | 65 | 66 | 67 | sources 68 | 69 | 70 | -------------------------------------------------------------------------------- /src/Gui.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | 3 | void Gui::drawActiveSelection() 4 | { 5 | ImGui::Text("Current DX9:"); 6 | ImGui::SameLine(); 7 | 8 | switch (activeRenderIndex) 9 | { 10 | case (int)RenderType::D3D9: 11 | ImGui::Text("stock direct3d 9 renderer"); 12 | break; 13 | case (int)RenderType::D3D9_X_RESHADE: 14 | ImGui::Text("stock direct3d 9 renderer with ReShade"); 15 | break; 16 | case (int)RenderType::D3D9_X_GW2HOOK: 17 | ImGui::Text("stock direct3d 9 renderer with GW2Hook"); 18 | break; 19 | case (int)RenderType::D912PXY: 20 | ImGui::Text("direct3d 12 renderer via d912pxy proxy"); 21 | break; 22 | case (int)RenderType::D912PXY_X_RESHADE: 23 | ImGui::Text("direct3d 12 renderer via d912pxy proxy with ReShade"); 24 | break; 25 | case (int)RenderType::D912PXY_X_GW2ENHANCED: 26 | ImGui::Text("direct3d 12 renderer via d912pxy proxy with Gw2Enhanced"); 27 | break; 28 | case (int)RenderType::DXVK: 29 | ImGui::Text("vulkan renderer via DXVK"); 30 | break; 31 | case (int)RenderType::DXVK_X_RESHADE: 32 | ImGui::Text("vulkan renderer via DXVK with ReShade"); 33 | break; 34 | case (int)RenderType::DXVK_ASYNC: 35 | ImGui::Text("vulkan renderer via DXVK (async)"); 36 | break; 37 | case (int)RenderType::DXVK_ASYNC_X_RESHADE: 38 | ImGui::Text("vulkan renderer via DXVK (async) with ReShade"); 39 | break; 40 | default: 41 | ImGui::Text("current render selection is broken..."); 42 | break; 43 | } 44 | 45 | ImGui::Text("Current DX11:"); 46 | ImGui::SameLine(); 47 | 48 | switch (activeRenderIndexDX11) 49 | { 50 | case (int)RenderType::DXVK11: 51 | ImGui::Text("vulkan renderer via DXVK D3D11"); 52 | break; 53 | case (int)RenderType::DXVK11_X_RESHADE: 54 | ImGui::Text("vulkan renderer via DXVK D3D11 with ReShade"); 55 | break; 56 | case (int)RenderType::DXVK11_ASYNC: 57 | ImGui::Text("vulkan renderer via DXVK D3D11 (async) with ReShade"); 58 | break; 59 | case (int)RenderType::DXVK11_ASYNC_X_RESHADE: 60 | ImGui::Text("vulkan renderer via DXVK D3D11 (async) with ReShade"); 61 | break; 62 | case (int)RenderType::D3D11: 63 | ImGui::Text("stock direct3d 11 renderer"); 64 | break; 65 | case (int)RenderType::D3D11_X_RESHADE: 66 | ImGui::Text("stock direct3d 11 renderer with ReShade"); 67 | break; 68 | default: 69 | ImGui::Text("current render selection is broken..."); 70 | break; 71 | } 72 | } 73 | 74 | void Gui::init() 75 | { 76 | hideTimeout = gAddon().main.getHideTimeoutPtr(); 77 | updateActualActiveRender(); 78 | } 79 | 80 | void Gui::updateActualActiveRender() 81 | { 82 | activeRenderIndex = (int)gAddon().main.getActiveRenderer(); 83 | activeRenderIndexDX11 = (int)gAddon().main.getActiveDX11Renderer(); 84 | renderIndex = activeRenderIndex; 85 | renderIndexDX11 = activeRenderIndexDX11; 86 | } 87 | 88 | void Gui::draw() 89 | { 90 | if (!showUI) 91 | return; 92 | 93 | //should be separated from gui draw, but who cares 94 | gAddon().main.update(); 95 | 96 | ImGui::Begin("SelectRender"); 97 | 98 | if (!showList) 99 | drawActiveSelection(); 100 | 101 | if (!gAddon().main.isExtraDllsLoaded()) 102 | { 103 | ImGui::Text("Some extra dlls are not loaded!"); 104 | ImGui::Text("Check integrity of selected renderer installation"); 105 | } 106 | 107 | if (showList) 108 | { 109 | ImGui::Text("Select render that you want to use from list below"); 110 | ImGui::Text("DX9 will be used when DX11 is disabled in game options and vice versa"); 111 | 112 | ImGui::NewLine(); 113 | ImGui::Text("DX9:"); 114 | drawSeletionOption("stock", &renderIndex, RenderType::D3D9); 115 | drawSeletionOption("ReShade", &renderIndex, RenderType::D3D9_X_RESHADE); 116 | drawSeletionOption("GW2Hook", &renderIndex, RenderType::D3D9_X_GW2HOOK); 117 | drawSeletionOption("d912pxy", &renderIndex, RenderType::D912PXY); 118 | drawSeletionOption("d912pxy + ReShade", &renderIndex, RenderType::D912PXY_X_RESHADE); 119 | drawSeletionOption("d912pxy + Gw2Enhanced", &renderIndex, RenderType::D912PXY_X_GW2ENHANCED); 120 | drawSeletionOption("DXVK", &renderIndex, RenderType::DXVK); 121 | drawSeletionOption("DXVK + ReShade", &renderIndex, RenderType::DXVK_X_RESHADE); 122 | drawSeletionOption("DXVK (async)", &renderIndex, RenderType::DXVK_ASYNC); 123 | drawSeletionOption("DXVK (async) + ReShade", &renderIndex, RenderType::DXVK_ASYNC_X_RESHADE); 124 | ImGui::NewLine(); 125 | ImGui::Text("DX11:"); 126 | drawSeletionOption("DXVK", &renderIndexDX11, RenderType::DXVK11); 127 | drawSeletionOption("DXVK + ReShade", &renderIndexDX11, RenderType::DXVK11_X_RESHADE); 128 | drawSeletionOption("DXVK (async)", &renderIndexDX11, RenderType::DXVK11_ASYNC); 129 | drawSeletionOption("DXVK + ReShade (async)", &renderIndexDX11, RenderType::DXVK11_ASYNC_X_RESHADE); 130 | drawSeletionOption("stock", &renderIndexDX11, RenderType::D3D11); 131 | drawSeletionOption("ReShade", &renderIndexDX11, RenderType::D3D11_X_RESHADE); 132 | ImGui::NewLine(); 133 | if (ImGui::Button("Apply")) 134 | { 135 | showRestartNotify = gAddon().main.setRenderer((RenderType)renderIndex, false); 136 | showRestartNotify &= gAddon().main.setRenderer((RenderType)renderIndexDX11, true); 137 | showErrorSaveNotify = !showRestartNotify; 138 | } 139 | 140 | if (showRestartNotify) 141 | ImGui::Text("Changes will be applied after game restart"); 142 | 143 | if (showErrorSaveNotify) 144 | ImGui::Text("Failed to write binary data to addons/SelectRender directory, changes are not applied"); 145 | } 146 | else 147 | { 148 | if (ImGui::Button("Change")) 149 | { 150 | gAddon().main.stopAutoHide(); 151 | showList = true; 152 | } 153 | } 154 | 155 | if (*hideTimeout) 156 | { 157 | ImGui::NewLine(); 158 | ImGui::Text("Will auto hide in %u seconds", (*hideTimeout)/1000); 159 | } 160 | if (ImGui::Button("Hide")) 161 | toggleUI(false); 162 | ImGui::End(); 163 | } 164 | 165 | void Gui::deinit() 166 | { 167 | //CHANGE ME 168 | } 169 | 170 | void Gui::drawSeletionOption(const char* txt, int* v, RenderType v_button) 171 | { 172 | char buf[256]; 173 | sprintf_s(buf, "%s##radio_selector_%u", txt, v_button); 174 | if (gAddon().main.checkAvailability(v_button)) 175 | ImGui::RadioButton(buf, v, (int)v_button); 176 | else 177 | ImGui::Text(" %s (N/A)", txt); 178 | } 179 | -------------------------------------------------------------------------------- /src/Gui.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "stdafx.h" 3 | 4 | class Gui 5 | { 6 | bool showUI = true; 7 | int renderIndex = (int)RenderType::D3D9; 8 | int renderIndexDX11 = (int)RenderType::D3D9; 9 | int activeRenderIndex = (int)RenderType::D3D9; 10 | int activeRenderIndexDX11 = (int)RenderType::D3D9; 11 | int* hideTimeout = nullptr; 12 | bool showList = false; 13 | bool showRestartNotify = false; 14 | bool showErrorSaveNotify = false; 15 | 16 | void drawActiveSelection(); 17 | 18 | public: 19 | void toggleUI(bool v) { showUI = v; } 20 | 21 | void init(); 22 | void updateActualActiveRender(); 23 | void draw(); 24 | void deinit(); 25 | void drawSeletionOption(const char* txt, int* v, RenderType v_button); 26 | }; 27 | 28 | -------------------------------------------------------------------------------- /src/Main.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "Main.h" 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | static const char* currentRenderFn = "./addons/SelectRender/active_render.bin"; 9 | static const char* currentRenderDX11Fn = "./addons/SelectRender/active_render_dx11.bin"; 10 | 11 | static const wchar_t* render_gw2hook_d3d9_dll = L"./addons/gw2hook/d3d9.dll"; 12 | static const wchar_t* render_d912pxy_d3d9_dll = L"./addons/d912pxy/dll/release/d3d9.dll"; 13 | static const wchar_t* render_dxvk_d3d9_dll = L"./addons/dxvk/d3d9.dll"; 14 | static const wchar_t* render_dxvk_d3d11_dll = L"./addons/dxvk/d3d11.dll"; 15 | static const wchar_t* render_dxvk_dxgi_dll = L"./addons/dxvk/dxgi.dll"; 16 | static const wchar_t* render_dxvk_async_d3d9_dll = L"./addons/dxvk-async/d3d9.dll"; 17 | static const wchar_t* render_dxvk_async_d3d11_dll = L"./addons/dxvk-async/d3d11.dll"; 18 | static const wchar_t* render_dxvk_async_dxgi_dll = L"./addons/dxvk-async/dxgi.dll"; 19 | 20 | static const wchar_t* render_reshade_d3d9_dll = L"./addons/reshade/d3d9.dll"; 21 | static const wchar_t* render_reshade_dxgi_dll = L"./addons/reshade/dxgi.dll"; 22 | static const wchar_t* render_reshade_d3d11_dll = L"./addons/reshade/d3d11.dll"; 23 | static const wchar_t* render_reshade_d3d12_dll = L"./addons/reshade/d3d12.dll"; 24 | 25 | static const wchar_t* render_gw2enhanced_dxgi_dll = L"./addons/gw2enhanced/dxgi.dll"; 26 | static const wchar_t* render_gw2enhanced_d3d12_dll = L"./addons/gw2enhanced/d3d12.dll"; 27 | 28 | 29 | wchar_t* GetD3D9CustomLib() 30 | { 31 | wchar_t* ret = gAddon().main.selectRenderD3D9(); 32 | gAddon().api->log_text(LL_INFO, (wchar_t*)L"SelectRender", ret); 33 | return ret; 34 | } 35 | 36 | wchar_t* GetD3D11CustomLib() 37 | { 38 | wchar_t* ret = (wchar_t*)gAddon().main.selectRenderD3D11(); 39 | gAddon().api->log_text(LL_INFO, (wchar_t*)L"SelectRender", ret); 40 | return ret; 41 | } 42 | 43 | wchar_t* GetDXGICustomLib() 44 | { 45 | wchar_t* ret = (wchar_t*)gAddon().main.selectRenderDXGI(); 46 | gAddon().api->log_text(LL_INFO, (wchar_t*)L"SelectRender", ret); 47 | return ret; 48 | } 49 | 50 | 51 | void ExternalShowMenu() 52 | { 53 | gAddon().main.stopAutoHide(); 54 | gAddon().gui->toggleUI(true); 55 | } 56 | 57 | void Main::init() 58 | { 59 | FILE* f = nullptr; 60 | fopen_s(&f, currentRenderFn, "r"); 61 | if (f) 62 | { 63 | fread(&activeRenderer, sizeof(activeRenderer), 1, f); 64 | if ((int)activeRenderer >= (int)RenderType::COUNT) 65 | { 66 | gAddon().api->log_text(LL_ERR, (wchar_t*)L"SelectRender", (wchar_t*)L"Garbadge in active_render.bin file, using stock d3d9"); 67 | activeRenderer = RenderType::D3D9; 68 | } 69 | fclose(f); 70 | } 71 | 72 | fopen_s(&f, currentRenderDX11Fn, "r"); 73 | if (f) 74 | { 75 | fread(&activeRendererDX11, sizeof(activeRendererDX11), 1, f); 76 | if ((int)activeRendererDX11 >= (int)RenderType::COUNT) 77 | { 78 | gAddon().api->log_text(LL_ERR, (wchar_t*)L"SelectRender", (wchar_t*)L"Garbadge in active_render_dx11.bin file, using stock d3d11"); 79 | activeRendererDX11 = RenderType::D3D11; 80 | } 81 | fclose(f); 82 | } 83 | 84 | auto nha = gAddon().api->hash_name(L"D3D_wrapper_custom_d3d9_lib_query"); 85 | if (gAddon().api->register_function(&GetD3D9CustomLib, nha) != GW2AL_OK) 86 | gAddon().api->log_text(LL_ERR, (wchar_t*)L"SelectRender", (wchar_t*)L"someone already defined custom d3d9 lib query"); 87 | 88 | nha = gAddon().api->hash_name(L"D3D_wrapper_custom_d3d11_lib_query"); 89 | if (gAddon().api->register_function(&GetD3D11CustomLib, nha) != GW2AL_OK) 90 | gAddon().api->log_text(LL_ERR, (wchar_t*)L"SelectRender", (wchar_t*)L"someone already defined custom d3d11 lib query"); 91 | 92 | nha = gAddon().api->hash_name(L"D3D_wrapper_custom_dxgi_lib_query"); 93 | if (gAddon().api->register_function(&GetDXGICustomLib, nha) != GW2AL_OK) 94 | gAddon().api->log_text(LL_ERR, (wchar_t*)L"SelectRender", (wchar_t*)L"someone already defined custom dxgi lib query"); 95 | 96 | nha = gAddon().api->hash_name((wchar_t*)L"SelectRender_ExternalShowMenu"); 97 | if (gAddon().api->register_function(&ExternalShowMenu, nha) != GW2AL_OK) 98 | gAddon().api->log_text(LL_ERR, (wchar_t*)L"SelectRender", (wchar_t*)L"external show menu proc is not registered"); 99 | 100 | GetSystemDirectory(sysD3D9, 4096); 101 | lstrcatW(sysD3D9, L"\\d3d9.dll"); 102 | GetSystemDirectory(sysD3D11, 4096); 103 | lstrcatW(sysD3D11, L"\\d3d11.dll"); 104 | GetSystemDirectory(sysDXGI, 4096); 105 | lstrcatW(sysDXGI, L"\\dxgi.dll"); 106 | } 107 | 108 | void Main::update() 109 | { 110 | if (!needAutoHide) 111 | return; 112 | int cuTime = GetTickCount(); 113 | int dlt = max(cuTime - lastUpd, 0); 114 | if (!lastUpd) 115 | dlt = 0; 116 | lastUpd = cuTime; 117 | hideTimeout -= dlt; 118 | if (hideTimeout < 0) 119 | { 120 | gAddon().gui->toggleUI(false); 121 | gAddon().api->log_text(LL_INFO, (wchar_t*)L"SelectRender", (wchar_t*)L"UI hidden due to timeout"); 122 | hideTimeout = 0; 123 | } 124 | } 125 | 126 | bool Main::setRenderer(RenderType v, bool dx11_mode) 127 | { 128 | bool ret = false; 129 | FILE* f = nullptr; 130 | fopen_s(&f, dx11_mode ? currentRenderDX11Fn : currentRenderFn, "w"); 131 | 132 | if (f) 133 | { 134 | int typeddt = (int)v; 135 | if (fwrite(&typeddt, sizeof(typeddt), 1, f) != 1) 136 | gAddon().api->log_text(LL_ERR, (wchar_t*)L"SelectRender", (wchar_t*)L"Can't write active render file, stock will still be used on restart"); 137 | else 138 | ret = true; 139 | fclose(f); 140 | } else 141 | gAddon().api->log_text(LL_ERR, (wchar_t*)L"SelectRender", (wchar_t*)L"Can't create active render file, stock will still be used on restart"); 142 | 143 | 144 | return ret; 145 | } 146 | 147 | const wchar_t* Main::selectRenderD3D11() 148 | { 149 | gAddon().api->log_text(LL_INFO, (wchar_t*)L"SelectRender", (wchar_t*)L"Loading d3d11"); 150 | switch (activeRendererDX11) 151 | { 152 | case RenderType::D3D11: 153 | default: 154 | activeRendererDX11 = RenderType::D3D11; 155 | gAddon().gui->updateActualActiveRender(); 156 | return sysD3D11; 157 | case RenderType::DXVK11: 158 | return render_dxvk_d3d11_dll; 159 | case RenderType::DXVK11_X_RESHADE: 160 | //TODO: load reshade somehow 161 | return render_dxvk_d3d11_dll; 162 | case RenderType::DXVK11_ASYNC: 163 | return render_dxvk_async_d3d11_dll; 164 | case RenderType::DXVK11_ASYNC_X_RESHADE: 165 | //TODO: load reshade somehow 166 | return render_dxvk_async_d3d11_dll; 167 | case RenderType::D3D11_X_RESHADE: 168 | return sysD3D11; 169 | } 170 | } 171 | 172 | const wchar_t* Main::selectRenderDXGI() 173 | { 174 | gAddon().api->log_text(LL_INFO, (wchar_t*)L"SelectRender", (wchar_t*)L"Loading dxgi"); 175 | switch (activeRendererDX11) 176 | { 177 | case RenderType::D3D11: 178 | default: 179 | activeRendererDX11 = RenderType::D3D11; 180 | gAddon().gui->updateActualActiveRender(); 181 | return sysDXGI; 182 | case RenderType::DXVK11: 183 | return render_dxvk_dxgi_dll; 184 | case RenderType::DXVK11_X_RESHADE: 185 | //TODO: load reshade somehow 186 | return render_dxvk_dxgi_dll; 187 | case RenderType::DXVK11_ASYNC: 188 | _putenv_s("DXVK_ASYNC", "1"); 189 | return render_dxvk_async_dxgi_dll; 190 | case RenderType::DXVK11_ASYNC_X_RESHADE: 191 | //TODO: load reshade somehow 192 | _putenv_s("DXVK_ASYNC", "1"); 193 | return render_dxvk_async_dxgi_dll; 194 | case RenderType::D3D11_X_RESHADE: 195 | return render_reshade_dxgi_dll; 196 | } 197 | } 198 | 199 | 200 | wchar_t* Main::selectRenderD3D9() 201 | { 202 | gAddon().api->log_text(LL_INFO, (wchar_t*)L"SelectRender", (wchar_t*)L"Loading d3d9"); 203 | switch (activeRenderer) 204 | { 205 | case RenderType::D3D9: 206 | default: 207 | activeRenderer = RenderType::D3D9; 208 | gAddon().gui->updateActualActiveRender(); 209 | return sysD3D9; 210 | case RenderType::D3D9_X_RESHADE: 211 | return (wchar_t*)render_reshade_d3d9_dll; 212 | case RenderType::D3D9_X_GW2HOOK: 213 | return (wchar_t*)render_gw2hook_d3d9_dll; 214 | case RenderType::D912PXY: 215 | return (wchar_t*)render_d912pxy_d3d9_dll; 216 | case RenderType::D912PXY_X_RESHADE: 217 | extraDllsLoaded &= 218 | (LoadLibraryW(render_reshade_dxgi_dll) != NULL) || 219 | (LoadLibraryW(render_reshade_d3d12_dll) != NULL); 220 | return (wchar_t*)render_d912pxy_d3d9_dll; 221 | case RenderType::D912PXY_X_GW2ENHANCED: 222 | extraDllsLoaded &= 223 | (LoadLibraryW(render_gw2enhanced_dxgi_dll) != NULL) || 224 | (LoadLibraryW(render_gw2enhanced_d3d12_dll) != NULL);; 225 | return (wchar_t*)render_d912pxy_d3d9_dll; 226 | case RenderType::DXVK: 227 | return (wchar_t*)render_dxvk_d3d9_dll; 228 | case RenderType::DXVK_X_RESHADE: 229 | //TODO: see how to load reshade with dxvk from code (or maybe it is not needed at all) 230 | return (wchar_t*)render_dxvk_d3d9_dll; 231 | case RenderType::DXVK_ASYNC: 232 | _putenv_s("DXVK_ASYNC", "1"); 233 | return (wchar_t*)render_dxvk_async_d3d9_dll; 234 | case RenderType::DXVK_ASYNC_X_RESHADE: 235 | _putenv_s("DXVK_ASYNC", "1"); 236 | return (wchar_t*)render_dxvk_async_d3d9_dll; 237 | } 238 | } 239 | 240 | void Main::checkAvailabilityUncached() 241 | { 242 | //FIXME: optimize, can check files once and compose on result after 243 | renderOptionAvailability[(int)RenderType::D3D9] = true; 244 | renderOptionAvailability[(int)RenderType::D3D9_X_RESHADE] = fileExists(render_reshade_d3d9_dll); 245 | renderOptionAvailability[(int)RenderType::D3D9_X_GW2HOOK] = fileExists(render_gw2hook_d3d9_dll); 246 | renderOptionAvailability[(int)RenderType::D912PXY] = fileExists(render_d912pxy_d3d9_dll); 247 | renderOptionAvailability[(int)RenderType::D912PXY_X_RESHADE] = fileExists(render_d912pxy_d3d9_dll) 248 | && (fileExists(render_reshade_dxgi_dll) || fileExists(render_reshade_d3d12_dll)); 249 | renderOptionAvailability[(int)RenderType::D912PXY_X_GW2ENHANCED] = fileExists(render_d912pxy_d3d9_dll) 250 | && (fileExists(render_gw2enhanced_dxgi_dll) || fileExists(render_gw2enhanced_d3d12_dll)); 251 | renderOptionAvailability[(int)RenderType::DXVK] = fileExists(render_dxvk_d3d9_dll); 252 | renderOptionAvailability[(int)RenderType::DXVK_X_RESHADE] = fileExists(render_dxvk_d3d9_dll); 253 | renderOptionAvailability[(int)RenderType::DXVK_ASYNC] = fileExists(render_dxvk_async_d3d9_dll); 254 | renderOptionAvailability[(int)RenderType::DXVK_ASYNC_X_RESHADE] = fileExists(render_dxvk_async_d3d9_dll); 255 | renderOptionAvailability[(int)RenderType::DXVK11] = fileExists(render_dxvk_d3d11_dll) && fileExists(render_dxvk_dxgi_dll); 256 | renderOptionAvailability[(int)RenderType::DXVK11_X_RESHADE] = fileExists(render_dxvk_d3d11_dll) && fileExists(render_dxvk_dxgi_dll) && fileExists(render_reshade_dxgi_dll); 257 | renderOptionAvailability[(int)RenderType::DXVK11_ASYNC] = fileExists(render_dxvk_async_d3d11_dll) && fileExists(render_dxvk_async_dxgi_dll); 258 | renderOptionAvailability[(int)RenderType::DXVK11_ASYNC_X_RESHADE] = fileExists(render_dxvk_d3d11_dll) && fileExists(render_dxvk_dxgi_dll) && fileExists(render_reshade_dxgi_dll); 259 | renderOptionAvailability[(int)RenderType::D3D11] = true; 260 | renderOptionAvailability[(int)RenderType::D3D11_X_RESHADE] = fileExists(render_reshade_dxgi_dll); 261 | } 262 | 263 | bool Main::checkAvailability(RenderType index) 264 | { 265 | if (!renderAvailabilityCached) 266 | checkAvailabilityUncached(); 267 | 268 | if (index >= RenderType::COUNT) 269 | return false; 270 | 271 | return renderOptionAvailability[(int)index]; 272 | } 273 | 274 | bool Main::fileExists(const wchar_t* fn) 275 | { 276 | FILE* f = nullptr; 277 | _wfopen_s(&f, fn, L"rb"); 278 | if (!f) 279 | return false; 280 | 281 | fclose(f); 282 | return true; 283 | } 284 | -------------------------------------------------------------------------------- /src/Main.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "stdafx.h" 3 | 4 | enum class RenderType 5 | { 6 | D3D9, 7 | D3D9_X_RESHADE, 8 | D3D9_X_GW2HOOK, 9 | D912PXY, 10 | D912PXY_X_RESHADE, 11 | D912PXY_X_GW2ENHANCED, 12 | DXVK, 13 | DXVK_X_RESHADE, 14 | DXVK_ASYNC, 15 | DXVK_ASYNC_X_RESHADE, 16 | DXVK11, 17 | DXVK11_X_RESHADE, 18 | DXVK11_ASYNC, 19 | DXVK11_ASYNC_X_RESHADE, 20 | D3D11, 21 | D3D11_X_RESHADE, 22 | COUNT 23 | }; 24 | 25 | class Main 26 | { 27 | int hideTimeout = 15000; 28 | int lastUpd = 0; 29 | bool needAutoHide = true; 30 | bool extraDllsLoaded = true; 31 | RenderType activeRenderer = RenderType::D3D9; 32 | RenderType activeRendererDX11 = RenderType::D3D11; 33 | 34 | wchar_t sysD3D9[4096]; 35 | wchar_t sysD3D11[4096]; 36 | wchar_t sysDXGI[4096]; 37 | 38 | bool renderOptionAvailability[(int)RenderType::COUNT] = { 0 }; 39 | bool renderAvailabilityCached = false; 40 | 41 | public: 42 | int* getHideTimeoutPtr() { return &hideTimeout; } 43 | void stopAutoHide() { needAutoHide = false; hideTimeout = 0; } 44 | void init(); 45 | void update(); 46 | bool setRenderer(RenderType v, bool dx11_mode); 47 | RenderType getActiveRenderer() { return activeRenderer; } 48 | RenderType getActiveDX11Renderer() { return activeRendererDX11; } 49 | void deinit() { } 50 | 51 | bool isExtraDllsLoaded() { return extraDllsLoaded; } 52 | 53 | wchar_t* selectRenderD3D9(); 54 | const wchar_t* selectRenderD3D11(); 55 | const wchar_t* selectRenderDXGI(); 56 | void checkAvailabilityUncached(); 57 | bool checkAvailability(RenderType index); 58 | 59 | bool fileExists(const wchar_t* fn); 60 | }; 61 | 62 | -------------------------------------------------------------------------------- /src/addon.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "build_version.h" 3 | 4 | gw2al_addon_dsc gAddonDeps[] = { 5 | GW2AL_CORE_DEP_ENTRY, 6 | LIB_IMGUI_DEP_ENTRY, 7 | { 0,0,0,0,0,0 } 8 | }; 9 | 10 | gw2al_addon_dsc gAddonDsc = { 11 | L"SelectRender", 12 | L"Ingame UI based render selection for GW2", 13 | 1, 14 | 4, 15 | BUILD_VERSION_REV, 16 | gAddonDeps 17 | }; 18 | 19 | addon_instance gInst; 20 | 21 | addon_instance& gAddon() 22 | { 23 | return gInst; 24 | } 25 | 26 | template<> 27 | inline lib_imgui& lib_imgui::instance() 28 | { 29 | return gInst.gui; 30 | } 31 | 32 | 33 | gw2al_addon_dsc* gw2addon_get_description() 34 | { 35 | return &gAddonDsc; 36 | } 37 | 38 | gw2al_api_ret gw2addon_load(gw2al_core_vtable* core_api) 39 | { 40 | gInst.api = core_api; 41 | 42 | gInst.main.init(); 43 | gInst.gui.init(core_api, gAddonDsc.name); 44 | 45 | return GW2AL_OK; 46 | } 47 | 48 | gw2al_api_ret gw2addon_unload(int gameExiting) 49 | { 50 | gInst.gui.deinit(); 51 | gInst.main.deinit(); 52 | 53 | return GW2AL_OK; 54 | } 55 | 56 | BOOL APIENTRY DllMain(HMODULE hModule, 57 | DWORD ul_reason_for_call, 58 | LPVOID lpReserved 59 | ) 60 | { 61 | return TRUE; 62 | } 63 | -------------------------------------------------------------------------------- /src/addon.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "stdafx.h" 3 | 4 | struct addon_instance 5 | { 6 | gw2al_core_vtable* api; 7 | Main main; 8 | lib_imgui gui; 9 | }; 10 | 11 | addon_instance& gAddon(); 12 | -------------------------------------------------------------------------------- /src/build_version.h: -------------------------------------------------------------------------------- 1 | #define BUILD_VERSION_NAME "version: unknown" 2 | #define BUILD_VERSION_REV 1 -------------------------------------------------------------------------------- /src/stdafx.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | -------------------------------------------------------------------------------- /src/stdafx.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "targetver.h" 4 | 5 | #define WIN32_LEAN_AND_MEAN 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include "Main.h" 12 | #include "Gui.h" 13 | #include "addon.h" 14 | -------------------------------------------------------------------------------- /src/targetver.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | --------------------------------------------------------------------------------