#include "dllmain.h" #include "Util.h" #include "Logger.h" #include "resource.h" #include "FSR4Upgrade.h" #include "proxies/NVNGX_Proxy.h" #include "proxies/XeSS_Proxy.h" #include "proxies/FfxApi_Proxy.h" #include "proxies/Gdi32_Proxy.h" #include "proxies/Streamline_Proxy.h" #include "inputs/FSR2_Dx12.h" #include "inputs/FSR3_Dx12.h" #include "inputs/FfxApiExe_Dx12.h" #include "hooks/HooksDx.h" #include "hooks/HooksVk.h" #include static HMODULE mod_amdxc64 = nullptr; // Enables hooking of GetModuleHandle // which might create issues, not tested very well //#define HOOK_GET_MODULE #ifdef HOOK_GET_MODULE // Handle nvngx.dll calls on GetModule handle //#define GET_MODULE_NVNGX // Handle Opti dll calls on GetModule handle #define GET_MODULE_DLL #endif #pragma warning (disable : 4996) typedef BOOL(*PFN_FreeLibrary)(HMODULE lpLibrary); typedef HMODULE(*PFN_LoadLibraryA)(LPCSTR lpLibFileName); typedef HMODULE(*PFN_LoadLibraryW)(LPCWSTR lpLibFileName); typedef HMODULE(*PFN_LoadLibraryExA)(LPCSTR lpLibFileName, HANDLE hFile, DWORD dwFlags); typedef HMODULE(*PFN_LoadLibraryExW)(LPCWSTR lpLibFileName, HANDLE hFile, DWORD dwFlags); typedef FARPROC(*PFN_GetProcAddress)(HMODULE hModule, LPCSTR lpProcName); typedef HMODULE(*PFN_GetModuleHandleA)(LPCSTR lpModuleName); typedef HMODULE(*PFN_GetModuleHandleW)(LPCWSTR lpModuleName); typedef BOOL(*PFN_GetModuleHandleExA)(DWORD dwFlags, LPCSTR lpModuleName, HMODULE* phModule); typedef BOOL(*PFN_GetModuleHandleExW)(DWORD dwFlags, LPCWSTR lpModuleName, HMODULE* phModule); typedef const char* (CDECL* PFN_wine_get_version)(void); typedef HRESULT(__cdecl* PFN_AmdExtD3DCreateInterface)(IUnknown* pOuter, REFIID riid, void** ppvObject); typedef struct VkDummyProps { VkStructureType sType; void* pNext; } VkDummyProps; static PFN_FreeLibrary o_FreeLibrary = nullptr; static PFN_LoadLibraryA o_LoadLibraryA = nullptr; static PFN_LoadLibraryW o_LoadLibraryW = nullptr; static PFN_LoadLibraryExA o_LoadLibraryExA = nullptr; static PFN_LoadLibraryExW o_LoadLibraryExW = nullptr; static PFN_GetProcAddress o_GetProcAddress = nullptr; static PFN_GetModuleHandleA o_GetModuleHandleA = nullptr; static PFN_GetModuleHandleW o_GetModuleHandleW = nullptr; static PFN_GetModuleHandleExA o_GetModuleHandleExA = nullptr; static PFN_GetModuleHandleExW o_GetModuleHandleExW = nullptr; static PFN_LoadLibraryW o_KernelBase_LoadLibraryW = nullptr; static PFN_LoadLibraryA o_KernelBase_LoadLibraryA = nullptr; static PFN_LoadLibraryExA o_KernelBase_LoadLibraryExA = nullptr; static PFN_LoadLibraryExW o_KernelBase_LoadLibraryExW = nullptr; static PFN_GetProcAddress o_KernelBase_GetProcAddress = nullptr; static PFN_vkCreateDevice o_vkCreateDevice = nullptr; static PFN_vkCreateInstance o_vkCreateInstance = nullptr; static PFN_vkGetPhysicalDeviceProperties o_vkGetPhysicalDeviceProperties = nullptr; static PFN_vkGetPhysicalDeviceProperties2 o_vkGetPhysicalDeviceProperties2 = nullptr; static PFN_vkGetPhysicalDeviceProperties2KHR o_vkGetPhysicalDeviceProperties2KHR = nullptr; static PFN_vkGetPhysicalDeviceMemoryProperties o_vkGetPhysicalDeviceMemoryProperties = nullptr; static PFN_vkGetPhysicalDeviceMemoryProperties2 o_vkGetPhysicalDeviceMemoryProperties2 = nullptr; static PFN_vkGetPhysicalDeviceMemoryProperties2KHR o_vkGetPhysicalDeviceMemoryProperties2KHR = nullptr; static PFN_vkEnumerateDeviceExtensionProperties o_vkEnumerateDeviceExtensionProperties = nullptr; static PFN_vkEnumerateInstanceExtensionProperties o_vkEnumerateInstanceExtensionProperties = nullptr; static uint32_t vkEnumerateInstanceExtensionPropertiesCount = 0; static uint32_t vkEnumerateDeviceExtensionPropertiesCount = 0; static AmdExtFfxApi* _amdExtFfxApi = nullptr; static PFN_AmdExtD3DCreateInterface o_AmdExtD3DCreateInterface = nullptr; #define DEFINE_NAME_VECTORS(varName, libName) \ inline std::vector varName##Names = { libName ".dll", libName }; \ inline std::vector varName##NamesW = { L##libName L".dll", L##libName }; inline std::vector dllNames; inline std::vector dllNamesW; inline std::vector overlayNames = { "eosovh-win32-shipping.dll", "eosovh-win32-shipping", "eosovh-win64-shipping.dll", "eosovh-win64-shipping", "gameoverlayrenderer64", "gameoverlayrenderer64.dll", "gameoverlayrenderer", "gameoverlayrenderer.dll", }; inline std::vector overlayNamesW = { L"eosovh-win32-shipping.dll", L"eosovh-win32-shipping", L"eosovh-win64-shipping.dll", L"eosovh-win64-shipping", L"gameoverlayrenderer64", L"gameoverlayrenderer64.dll", L"gameoverlayrenderer", L"gameoverlayrenderer.dll", }; DEFINE_NAME_VECTORS(nvngx, "nvngx"); DEFINE_NAME_VECTORS(xess, "libxess"); DEFINE_NAME_VECTORS(nvngxDlss, "nvngx_dlss"); DEFINE_NAME_VECTORS(nvapi, "nvapi64"); DEFINE_NAME_VECTORS(dx11, "d3d11"); DEFINE_NAME_VECTORS(dx12, "d3d12"); DEFINE_NAME_VECTORS(dxgi, "dxgi"); DEFINE_NAME_VECTORS(vk, "vulkan-1"); DEFINE_NAME_VECTORS(streamline, "sl.interposer"); DEFINE_NAME_VECTORS(fsr2, "ffx_fsr2_api_x64"); DEFINE_NAME_VECTORS(fsr2BE, "ffx_fsr2_api_dx12_x64"); DEFINE_NAME_VECTORS(fsr3, "ffx_fsr3upscaler_x64"); DEFINE_NAME_VECTORS(fsr3BE, "ffx_backend_dx12_x64"); DEFINE_NAME_VECTORS(ffxDx12, "amd_fidelityfx_dx12"); DEFINE_NAME_VECTORS(ffxVk, "amd_fidelityfx_vk"); static int loadCount = 0; static bool skipLoadChecks = false; static bool dontCount = false; static bool isNvngxMode = false; static bool isWorkingWithEnabler = false; static bool isNvngxAvailable = false; void AttachHooks(); void DetachHooks(); HMODULE LoadNvApi(); HMODULE LoadNvngxDlss(std::wstring originalPath); void HookForDxgiSpoofing(HMODULE dxgiModule); void HookForVulkanSpoofing(HMODULE vulkanModule); void HookForVulkanExtensionSpoofing(HMODULE vulkanModule); void HookForVulkanVRAMSpoofing(HMODULE vulkanModule); inline static bool CheckDllName(std::string* dllName, std::vector* namesList) { for (size_t i = 0; i < namesList->size(); i++) { auto name = namesList->at(i); auto pos = dllName->rfind(name); if (pos != std::string::npos && pos == (dllName->size() - name.size())) return true; } return false; } inline static bool CheckDllNameW(std::wstring* dllName, std::vector* namesList) { for (size_t i = 0; i < namesList->size(); i++) { auto name = namesList->at(i); auto pos = dllName->rfind(name); if (pos != std::string::npos && pos == (dllName->size() - name.size())) return true; } return false; } inline static HMODULE LoadLibraryCheck(std::string lcaseLibName, LPCSTR lpLibFullPath) { LOG_TRACE("{}", lcaseLibName); // If Opti is not loading as nvngx.dll if (!isWorkingWithEnabler && !isNvngxMode) { // exe path auto exePath = Util::ExePath().parent_path().wstring(); for (size_t i = 0; i < exePath.size(); i++) exePath[i] = std::tolower(exePath[i]); auto pos = lcaseLibName.rfind(wstring_to_string(exePath)); if (Config::Instance()->DlssInputs.value_or_default() && CheckDllName(&lcaseLibName, &nvngxNames) && (!Config::Instance()->HookOriginalNvngxOnly.value_or_default() || pos == std::string::npos)) { LOG_INFO("nvngx call: {0}, returning this dll!", lcaseLibName); loadCount++; return dllModule; } } if (lcaseLibName.ends_with(".optidll")) { const std::string from = ".optidll"; const std::string to = ".dll"; auto realDll = lcaseLibName.replace(lcaseLibName.size() - from.size(), from.size(), to); LOG_INFO("Internal dll load call: {}", realDll); skipLoadChecks = true; auto result = o_LoadLibraryA(realDll.c_str()); skipLoadChecks = false; return result; } if (!isNvngxMode && (!State::Instance().isDxgiMode || !State::Instance().skipDxgiLoadChecks) && CheckDllName(&lcaseLibName, &dllNames)) { LOG_INFO("{0} call returning this dll!", lcaseLibName); loadCount++; return dllModule; } // NvApi64.dll if (CheckDllName(&lcaseLibName, &nvapiNames)) { if (!isWorkingWithEnabler && Config::Instance()->OverrideNvapiDll.value_or_default()) { LOG_INFO("{0} call!", lcaseLibName); skipLoadChecks = true; auto nvapi = LoadNvApi(); skipLoadChecks = false; // Nvapihooks intentionally won't load nvapi so have to make sure it's loaded if (nvapi != nullptr) { NvApiHooks::Hook(nvapi); return nvapi; } } else { auto nvapi = GetModuleHandleA(lcaseLibName.c_str()); // Try to load nvapi only from system32, like the original call would if (nvapi == nullptr) { skipLoadChecks = true; nvapi = o_LoadLibraryExA(lcaseLibName.c_str(), NULL, LOAD_LIBRARY_SEARCH_SYSTEM32); skipLoadChecks = false; } if (nvapi != nullptr) NvApiHooks::Hook(nvapi); // AMD without nvapi override should fall through } } // sl.interposer.dll if (Config::Instance()->FGType.value_or_default() == FGType::Nukems && CheckDllName(&lcaseLibName, &streamlineNames)) { skipLoadChecks = true; auto streamlineModule = o_LoadLibraryA(lpLibFullPath); skipLoadChecks = false; if (streamlineModule != nullptr) { skipLoadChecks = true; hookStreamline(streamlineModule); skipLoadChecks = false; } else { LOG_ERROR("Trying to load dll: {}", lcaseLibName); } return streamlineModule; } // nvngx_dlss if (Config::Instance()->DLSSEnabled.value_or_default() && Config::Instance()->NVNGX_DLSS_Library.has_value() && CheckDllName(&lcaseLibName, &nvngxDlssNames)) { skipLoadChecks = true; auto nvngxDlss = LoadNvngxDlss(string_to_wstring(lcaseLibName)); skipLoadChecks = false; if (nvngxDlss == nullptr) LOG_ERROR("Trying to load dll: {}", lcaseLibName); return nvngxDlss; } // NGX OTA // Try to catch something like this: c:\programdata/nvidia/ngx/models//dlss/versions/20316673/files/160_e658700.bin if (lcaseLibName.ends_with(".bin")) { skipLoadChecks = true; auto loadedBin = o_LoadLibraryA(lpLibFullPath); skipLoadChecks = false; if (loadedBin && lcaseLibName.contains("/versions/")) { if (lcaseLibName.contains("/dlss/")) { State::Instance().NGX_OTA_Dlss = lpLibFullPath; } if (lcaseLibName.contains("/dlssd/")) { State::Instance().NGX_OTA_Dlssd = lpLibFullPath; } } return loadedBin; } if (Config::Instance()->FGType.value_or_default() == FGType::OptiFG) { if (Config::Instance()->FGDisableOverlays.value_or_default() && CheckDllName(&lcaseLibName, &overlayNames)) { LOG_DEBUG("Trying to load overlay dll: {}", lcaseLibName); return (HMODULE)1; } } // Hooks if (CheckDllName(&lcaseLibName, &dx11Names) && Config::Instance()->OverlayMenu.value_or_default()) { skipLoadChecks = true; auto module = o_LoadLibraryA(lcaseLibName.c_str()); skipLoadChecks = false; if (module != nullptr) HooksDx::HookDx11(module); else LOG_ERROR("Trying to load dll: {}", lcaseLibName); return module; } if (CheckDllName(&lcaseLibName, &dx12Names) && Config::Instance()->OverlayMenu.value_or_default()) { skipLoadChecks = true; auto module = o_LoadLibraryA(lcaseLibName.c_str()); skipLoadChecks = false; if (module != nullptr) HooksDx::HookDx12(module); else LOG_ERROR("Trying to load dll: {}", lcaseLibName); return module; } if (CheckDllName(&lcaseLibName, &vkNames)) { skipLoadChecks = true; auto module = o_LoadLibraryA(lcaseLibName.c_str()); skipLoadChecks = false; if (module != nullptr) { if (!isWorkingWithEnabler) { HookForVulkanSpoofing(module); HookForVulkanExtensionSpoofing(module); HookForVulkanVRAMSpoofing(module); } if (Config::Instance()->OverlayMenu.value_or_default()) HooksVk::HookVk(module); } else { LOG_ERROR("Trying to load dll: {}", lcaseLibName); } return module; } if (!State::Instance().skipDxgiLoadChecks && CheckDllName(&lcaseLibName, &dxgiNames)) { skipLoadChecks = true; auto module = o_LoadLibraryA(lcaseLibName.c_str()); skipLoadChecks = false; if (module != nullptr) { if (!isWorkingWithEnabler) HookForDxgiSpoofing(module); if (Config::Instance()->OverlayMenu.value_or_default()) HooksDx::HookDxgi(module); } else { LOG_ERROR("Trying to load dll: {}", lcaseLibName); } return module; } if (CheckDllName(&lcaseLibName, &fsr2Names)) { skipLoadChecks = true; auto module = o_LoadLibraryA(lcaseLibName.c_str()); skipLoadChecks = false; if (module != nullptr) HookFSR2Inputs(module); else LOG_ERROR("Trying to load dll: {}", lcaseLibName); return module; } if (CheckDllName(&lcaseLibName, &fsr2BENames)) { skipLoadChecks = true; auto module = o_LoadLibraryA(lcaseLibName.c_str()); skipLoadChecks = false; if (module != nullptr) HookFSR2Dx12Inputs(module); else LOG_ERROR("Trying to load dll: {}", lcaseLibName); return module; } if (CheckDllName(&lcaseLibName, &fsr3Names)) { skipLoadChecks = true; auto module = o_LoadLibraryA(lcaseLibName.c_str()); skipLoadChecks = false; if (module != nullptr) HookFSR3Inputs(module); return module; } if (CheckDllName(&lcaseLibName, &fsr3BENames)) { skipLoadChecks = true; auto module = o_LoadLibraryA(lcaseLibName.c_str()); skipLoadChecks = false; if (module != nullptr) HookFSR3Dx12Inputs(module); else LOG_ERROR("Trying to load dll: {}", lcaseLibName); return module; } if (CheckDllName(&lcaseLibName, &xessNames)) { skipLoadChecks = true; auto module = o_LoadLibraryA(lcaseLibName.c_str()); skipLoadChecks = false; if (module != nullptr) XeSSProxy::HookXeSS(module); else LOG_ERROR("Trying to load dll: {}", lcaseLibName); return module; } if (CheckDllName(&lcaseLibName, &ffxDx12Names)) { skipLoadChecks = true; auto module = o_LoadLibraryA(lcaseLibName.c_str()); skipLoadChecks = false; if (module != nullptr) FfxApiProxy::InitFfxDx12(module); else LOG_ERROR("Trying to load dll: {}", lcaseLibName); return module; } if (CheckDllName(&lcaseLibName, &ffxVkNames)) { skipLoadChecks = true; auto module = o_LoadLibraryA(lcaseLibName.c_str()); skipLoadChecks = false; if (module != nullptr) FfxApiProxy::InitFfxVk(module); else LOG_ERROR("Trying to load dll: {}", lcaseLibName); return module; } return nullptr; } inline static HMODULE LoadLibraryCheckW(std::wstring lcaseLibName, LPCWSTR lpLibFullPath) { auto lcaseLibNameA = wstring_to_string(lcaseLibName); LOG_TRACE("{}", lcaseLibNameA); // If Opti is not loading as nvngx.dll if (!isWorkingWithEnabler && !isNvngxMode) { // exe path auto exePath = Util::ExePath().parent_path().wstring(); for (size_t i = 0; i < exePath.size(); i++) exePath[i] = std::tolower(exePath[i]); auto pos = lcaseLibName.rfind(exePath); if (Config::Instance()->DlssInputs.value_or_default() && CheckDllNameW(&lcaseLibName, &nvngxNamesW) && (!Config::Instance()->HookOriginalNvngxOnly.value_or_default() || pos == std::string::npos)) { LOG_INFO("nvngx call: {0}, returning this dll!", lcaseLibNameA); //if (!dontCount) loadCount++; return dllModule; } } if (lcaseLibName.ends_with(L".optidll")) { const std::wstring from = L".optidll"; const std::wstring to = L".dll"; auto realDll = lcaseLibName.replace(lcaseLibName.size() - from.size(), from.size(), to); LOG_INFO("Internal dll load call: {}", wstring_to_string(realDll)); skipLoadChecks = true; auto result = o_LoadLibraryW(realDll.c_str()); skipLoadChecks = false; return result; } if (!isNvngxMode && (!State::Instance().isDxgiMode || !State::Instance().skipDxgiLoadChecks) && CheckDllNameW(&lcaseLibName, &dllNamesW)) { LOG_INFO("{0} call returning this dll!", lcaseLibNameA); //if (!dontCount) loadCount++; return dllModule; } // nvngx_dlss if (Config::Instance()->DLSSEnabled.value_or_default() && Config::Instance()->NVNGX_DLSS_Library.has_value() && CheckDllNameW(&lcaseLibName, &nvngxDlssNamesW)) { skipLoadChecks = true; auto nvngxDlss = LoadNvngxDlss(lcaseLibName); skipLoadChecks = false; if (nvngxDlss != nullptr) return nvngxDlss; else LOG_ERROR("Trying to load dll: {}", lcaseLibNameA); } // NGX OTA // Try to catch something like this: c:\programdata/nvidia/ngx/models//dlss/versions/20316673/files/160_e658700.bin if (lcaseLibName.ends_with(L".bin")) { skipLoadChecks = true; auto loadedBin = o_LoadLibraryW(lpLibFullPath); skipLoadChecks = false; if (loadedBin && lcaseLibName.contains(L"/versions/")) { if (lcaseLibName.contains(L"/dlss/")) { State::Instance().NGX_OTA_Dlss = wstring_to_string(lpLibFullPath); } if (lcaseLibName.contains(L"/dlssd/")) { State::Instance().NGX_OTA_Dlssd = wstring_to_string(lpLibFullPath); } } return loadedBin; } // NvApi64.dll if (CheckDllNameW(&lcaseLibName, &nvapiNamesW)) { if (!isWorkingWithEnabler && Config::Instance()->OverrideNvapiDll.value_or_default()) { LOG_INFO("{0} call!", lcaseLibNameA); skipLoadChecks = true; auto nvapi = LoadNvApi(); skipLoadChecks = false; // Nvapihooks intentionally won't load nvapi so have to make sure it's loaded if (nvapi != nullptr) { NvApiHooks::Hook(nvapi); return nvapi; } } else { auto nvapi = GetModuleHandleW(lcaseLibName.c_str()); // Try to load nvapi only from system32, like the original call would if (nvapi == nullptr) { skipLoadChecks = true; nvapi = o_LoadLibraryExW(lcaseLibName.c_str(), NULL, LOAD_LIBRARY_SEARCH_SYSTEM32); skipLoadChecks = false; } if (nvapi != nullptr) NvApiHooks::Hook(nvapi); // AMD without nvapi override should fall through } } // sl.interposer.dll if (Config::Instance()->FGType.value_or_default() == FGType::Nukems && CheckDllNameW(&lcaseLibName, &streamlineNamesW)) { skipLoadChecks = true; auto streamlineModule = o_LoadLibraryW(lpLibFullPath); skipLoadChecks = false; if (streamlineModule != nullptr) { skipLoadChecks = true; hookStreamline(streamlineModule); skipLoadChecks = false; } else { LOG_ERROR("Trying to load dll: {}", lcaseLibNameA); } return streamlineModule; } if (Config::Instance()->FGType.value_or_default() == FGType::OptiFG) { if (Config::Instance()->FGDisableOverlays.value_or_default() && CheckDllNameW(&lcaseLibName, &overlayNamesW)) { LOG_DEBUG("Trying to load overlay dll: {}", lcaseLibNameA); return (HMODULE)1; } } // Hooks if (CheckDllNameW(&lcaseLibName, &dx11NamesW) && Config::Instance()->OverlayMenu.value_or_default()) { skipLoadChecks = true; auto module = o_LoadLibraryW(lcaseLibName.c_str()); skipLoadChecks = false; if (module != nullptr) HooksDx::HookDx11(module); return module; } if (CheckDllNameW(&lcaseLibName, &dx12NamesW) && Config::Instance()->OverlayMenu.value_or_default()) { skipLoadChecks = true; auto module = o_LoadLibraryW(lcaseLibName.c_str()); skipLoadChecks = false; if (module != nullptr) HooksDx::HookDx12(module); return module; } if (CheckDllNameW(&lcaseLibName, &vkNamesW)) { skipLoadChecks = true; auto module = o_LoadLibraryW(lcaseLibName.c_str()); skipLoadChecks = false; if (module != nullptr) { if (!isWorkingWithEnabler) { HookForVulkanSpoofing(module); HookForVulkanExtensionSpoofing(module); HookForVulkanVRAMSpoofing(module); } if (Config::Instance()->OverlayMenu.value_or_default()) HooksVk::HookVk(module); } return module; } if (!State::Instance().skipDxgiLoadChecks && CheckDllNameW(&lcaseLibName, &dxgiNamesW)) { skipLoadChecks = true; auto module = o_LoadLibraryW(lcaseLibName.c_str()); skipLoadChecks = false; if (module != nullptr) { if (!isWorkingWithEnabler) HookForDxgiSpoofing(module); if (Config::Instance()->OverlayMenu.value_or_default()/* && !State::Instance().isRunningOnLinux*/) HooksDx::HookDxgi(module); } } if (CheckDllNameW(&lcaseLibName, &fsr2NamesW)) { skipLoadChecks = true; auto module = o_LoadLibraryW(lcaseLibName.c_str()); skipLoadChecks = false; if (module != nullptr) HookFSR2Inputs(module); return module; } if (CheckDllNameW(&lcaseLibName, &fsr2BENamesW)) { skipLoadChecks = true; auto module = o_LoadLibraryW(lcaseLibName.c_str()); skipLoadChecks = false; if (module != nullptr) HookFSR2Dx12Inputs(module); return module; } if (CheckDllNameW(&lcaseLibName, &fsr3NamesW)) { skipLoadChecks = true; auto module = o_LoadLibraryW(lcaseLibName.c_str()); skipLoadChecks = false; if (module != nullptr) HookFSR3Inputs(module); return module; } if (CheckDllNameW(&lcaseLibName, &fsr3BENamesW)) { skipLoadChecks = true; auto module = o_LoadLibraryW(lcaseLibName.c_str()); skipLoadChecks = false; if (module != nullptr) HookFSR3Dx12Inputs(module); return module; } if (CheckDllNameW(&lcaseLibName, &xessNamesW)) { skipLoadChecks = true; auto module = o_LoadLibraryW(lcaseLibName.c_str()); skipLoadChecks = false; if (module != nullptr) XeSSProxy::HookXeSS(module); return module; } if (CheckDllNameW(&lcaseLibName, &ffxDx12NamesW)) { skipLoadChecks = true; auto module = o_LoadLibraryW(lcaseLibName.c_str()); skipLoadChecks = false; if (module != nullptr) FfxApiProxy::InitFfxDx12(module); return module; } if (CheckDllNameW(&lcaseLibName, &ffxVkNamesW)) { skipLoadChecks = true; auto module = o_LoadLibraryW(lcaseLibName.c_str()); skipLoadChecks = false; if (module != nullptr) FfxApiProxy::InitFfxVk(module); return module; } return nullptr; } static HMODULE LoadNvApi() { HMODULE nvapi = nullptr; if (Config::Instance()->NvapiDllPath.has_value()) { nvapi = o_LoadLibraryW(Config::Instance()->NvapiDllPath->c_str()); if (nvapi != nullptr) { LOG_INFO("nvapi64.dll loaded from {0}", wstring_to_string(Config::Instance()->NvapiDllPath.value())); return nvapi; } } if (nvapi == nullptr) { auto localPath = Util::DllPath().parent_path() / L"nvapi64.dll"; nvapi = o_LoadLibraryW(localPath.wstring().c_str()); if (nvapi != nullptr) { LOG_INFO("nvapi64.dll loaded from {0}", wstring_to_string(localPath.wstring())); return nvapi; } } if (nvapi == nullptr) { nvapi = o_LoadLibraryW(L"nvapi64.dll"); if (nvapi != nullptr) { LOG_WARN("nvapi64.dll loaded from system!"); return nvapi; } } return nullptr; } static HMODULE LoadNvngxDlss(std::wstring originalPath) { HMODULE nvngxDlss = nullptr; if (Config::Instance()->NVNGX_DLSS_Library.has_value()) { nvngxDlss = o_LoadLibraryW(Config::Instance()->NVNGX_DLSS_Library.value().c_str()); if (nvngxDlss != nullptr) { LOG_INFO("nvngx_dlss.dll loaded from {0}", wstring_to_string(Config::Instance()->NVNGX_DLSS_Library.value())); return nvngxDlss; } else { LOG_WARN("nvngx_dlss.dll can't found at {0}", wstring_to_string(Config::Instance()->NVNGX_DLSS_Library.value())); } } if (nvngxDlss == nullptr) { nvngxDlss = o_LoadLibraryW(originalPath.c_str()); if (nvngxDlss != nullptr) { LOG_INFO("nvngx_dlss.dll loaded from {0}", wstring_to_string(originalPath)); return nvngxDlss; } } return nullptr; } #pragma region Load & nvngxDlss Library hooks static void CheckForGPU() { if (Config::Instance()->Fsr4Update.has_value()) return; bool loaded = false; HMODULE dxgiModule = nullptr; if (o_LoadLibraryExW != nullptr) { dxgiModule = o_LoadLibraryExW(L"dxgi.dll", nullptr, LOAD_LIBRARY_SEARCH_SYSTEM32); loaded = dxgiModule != nullptr; } else { dxgiModule = LoadLibraryExW(L"dxgi.dll", nullptr, LOAD_LIBRARY_SEARCH_SYSTEM32); loaded = dxgiModule != nullptr; } if (dxgiModule == nullptr) return; auto createFactory = (PFN_CREATE_DXGI_FACTORY)GetProcAddress(dxgiModule, "CreateDXGIFactory"); if (createFactory == nullptr) { if (loaded) FreeLibrary(dxgiModule); return; } IDXGIFactory* factory; HRESULT result = createFactory(__uuidof(factory), &factory); if (result != S_OK) { LOG_ERROR("Can't create DXGIFactory error: {:X}", (UINT)result); if (loaded) FreeLibrary(dxgiModule); return; } UINT adapterIndex = 0; DXGI_ADAPTER_DESC adapterDesc{}; IDXGIAdapter* adapter; while (factory->EnumAdapters(adapterIndex, &adapter) == S_OK) { if (adapter == nullptr) { adapterIndex++; continue; } State::Instance().skipSpoofing = true; result = adapter->GetDesc(&adapterDesc); State::Instance().skipSpoofing = false; if (result == S_OK && adapterDesc.VendorId != 0x00001414) { std::wstring szName(adapterDesc.Description); std::string descStr = std::format("Adapter: {}, VRAM: {} MB", wstring_to_string(szName), adapterDesc.DedicatedVideoMemory / (1024 * 1024)); LOG_INFO("{}", descStr); // If GPU is AMD if (adapterDesc.VendorId == 0x1002) { // If GPU Name contains 90XX always set it to true if (szName.find(L" 90") != std::wstring::npos || szName.find(L" GFX12") != std::wstring::npos) Config::Instance()->Fsr4Update = true; } } else { LOG_DEBUG("Can't get description of adapter: {}", adapterIndex); } adapter->Release(); adapter = nullptr; adapterIndex++; } factory->Release(); factory = nullptr; if (loaded) { if (o_FreeLibrary != nullptr) o_FreeLibrary(dxgiModule); else FreeLibrary(dxgiModule); } if (!Config::Instance()->Fsr4Update.has_value()) Config::Instance()->Fsr4Update = false; LOG_INFO("Fsr4Update: {}", Config::Instance()->Fsr4Update.value_or_default()); } // For FSR4 Upgrade HRESULT STDMETHODCALLTYPE hkAmdExtD3DCreateInterface(IUnknown* pOuter, REFIID riid, void** ppvObject) { // If querying IAmdExtFfxApi if (riid == __uuidof(IAmdExtFfxApi)) { if (_amdExtFfxApi == nullptr) _amdExtFfxApi = new AmdExtFfxApi(); // Return custom one *ppvObject = _amdExtFfxApi; return S_OK; } if (o_AmdExtD3DCreateInterface != nullptr) return o_AmdExtD3DCreateInterface(pOuter, riid, ppvObject); return E_NOINTERFACE; } static UINT customD3D12SDKVersion = 615; static const char8_t* customD3D12SDKPath = u8".\\D3D12_Optiscaler\\"; //Hardcoded for now static FARPROC hkGetProcAddress(HMODULE hModule, LPCSTR lpProcName) { if (hModule == dllModule && lpProcName != nullptr) LOG_DEBUG("Trying to get process address of {0}", lpProcName); // For FSR4 Upgrade if (hModule == mod_amdxc64 && o_AmdExtD3DCreateInterface != nullptr && lpProcName != nullptr && strcmp(lpProcName, "AmdExtD3DCreateInterface") == 0) { CheckForGPU(); // Return custom method for upgrade for RDNA4 if (Config::Instance()->Fsr4Update.value_or_default()) return (FARPROC)hkAmdExtD3DCreateInterface; } // For Agility SDK Upgrade if (Config::Instance()->FsrAgilitySDKUpgrade.value_or_default()) { HMODULE mod_mainExe; GetModuleHandleEx(2u, 0i64, &mod_mainExe); if (hModule == mod_mainExe && lpProcName != nullptr) { if (strcmp(lpProcName, "D3D12SDKVersion") == 0) { LOG_INFO("D3D12SDKVersion call, returning this version!"); return (FARPROC)&customD3D12SDKVersion; } if (strcmp(lpProcName, "D3D12SDKPath") == 0) { LOG_INFO("D3D12SDKPath call, returning this path!"); return (FARPROC)&customD3D12SDKPath; } } } if (State::Instance().isRunningOnLinux && lpProcName != nullptr && hModule == GetModuleHandle(L"gdi32.dll") && lstrcmpA(lpProcName, "D3DKMTEnumAdapters2") == 0) return (FARPROC)&customD3DKMTEnumAdapters2; return o_GetProcAddress(hModule, lpProcName); } #ifdef HOOK_GET_MODULE static HMODULE hkGetModuleHandleA(LPCSTR lpModuleName) { if (!skipGetModuleHandle && lpModuleName != nullptr) { std::string libName(lpModuleName); std::string lcaseLibName(libName); for (size_t i = 0; i < lcaseLibName.size(); i++) lcaseLibName[i] = std::tolower(lcaseLibName[i]); LOG_DEBUG_ONLY("{}", lcaseLibName); int pos = 0; #ifdef GET_MODULE_NVNGX // nvngx dll pos = lcaseLibName.rfind(nvngxA); if (pos != std::string::npos && pos == (lcaseLibName.size() - nvngxA.size())) { LOG_INFO("{0} call, returning this dll!", libName); return dllModule; } // nvngx pos = lcaseLibName.rfind(nvngxExA); if (pos != std::string::npos && pos == (lcaseLibName.size() - nvngxExA.size())) { LOG_INFO("{0} call, returning this dll!", libName); return dllModule; } #endif #ifdef GET_MODULE_DLL // Opti if (CheckDllName(&lcaseLibName, &dllNames)) { LOG_INFO("{0} call, returning this dll!", libName); return dllModule; } #endif } return o_GetModuleHandleA(lpModuleName); } static HMODULE hkGetModuleHandleW(LPCWSTR lpModuleName) { if (!skipGetModuleHandle && lpModuleName != nullptr) { std::wstring libName(lpModuleName); std::wstring lcaseLibName(libName); for (size_t i = 0; i < lcaseLibName.size(); i++) lcaseLibName[i] = std::tolower(lcaseLibName[i]); auto lcaseLibNameA = wstring_to_string(lcaseLibName); LOG_DEBUG_ONLY("{}", lcaseLibNameA); int pos = 0; #ifdef GET_MODULE_NVNGX // nvngx dll pos = lcaseLibName.rfind(nvngxW); if (pos != std::string::npos && pos == (lcaseLibName.size() - nvngxW.size())) { LOG_INFO("{0} call, returning this dll!", lcaseLibNameA); return dllModule; } // nvngx pos = lcaseLibName.rfind(nvngxExW); if (pos != std::string::npos && pos == (lcaseLibName.size() - nvngxExW.size())) { LOG_INFO("{0} call, returning this dll!", lcaseLibNameA); return dllModule; } #endif #ifdef GET_MODULE_DLL // Opti if (CheckDllNameW(&lcaseLibName, &dllNamesW)) { LOG_INFO("{0} call, returning this dll!", lcaseLibNameA); return dllModule; } #endif } return o_GetModuleHandleW(lpModuleName); } static BOOL hkGetModuleHandleExA(DWORD dwFlags, LPCSTR lpModuleName, HMODULE* phModule) { if (!skipGetModuleHandle && lpModuleName != nullptr) { std::string libName(lpModuleName); std::string lcaseLibName(libName); for (size_t i = 0; i < lcaseLibName.size(); i++) lcaseLibName[i] = std::tolower(lcaseLibName[i]); LOG_DEBUG_ONLY("{}", lcaseLibName); int pos = 0; #ifdef GET_MODULE_NVNGX // nvngx dll pos = lcaseLibName.rfind(nvngxA); if (pos != std::string::npos && pos == (lcaseLibName.size() - nvngxA.size())) { LOG_INFO("{0} call, returning this dll!", libName); *phModule = dllModule; return TRUE; } // nvngx pos = lcaseLibName.rfind(nvngxExA); if (pos != std::string::npos && pos == (lcaseLibName.size() - nvngxExA.size())) { LOG_INFO("{0} call, returning this dll!", libName); *phModule = dllModule; return TRUE; } #endif #ifdef GET_MODULE_DLL // Opti if (CheckDllName(&lcaseLibName, &dllNames)) { LOG_INFO("{0} call, returning this dll!", libName); *phModule = dllModule; return TRUE; } #endif } return o_GetModuleHandleExA(dwFlags, lpModuleName, phModule); } static BOOL hkGetModuleHandleExW(DWORD dwFlags, LPCWSTR lpModuleName, HMODULE* phModule) { if (!skipGetModuleHandle && lpModuleName != nullptr) { std::wstring libName(lpModuleName); std::wstring lcaseLibName(libName); for (size_t i = 0; i < lcaseLibName.size(); i++) lcaseLibName[i] = std::tolower(lcaseLibName[i]); auto lcaseLibNameA = wstring_to_string(lcaseLibName); LOG_DEBUG_ONLY("{}", lcaseLibNameA); int pos = 0; #ifdef GET_MODULE_NVNGX // nvngx dll pos = lcaseLibName.rfind(nvngxW); if (pos != std::string::npos && pos == (lcaseLibName.size() - nvngxW.size())) { LOG_INFO("{0} call, returning this dll!", lcaseLibNameA); *phModule = dllModule; return TRUE; } // nvngx pos = lcaseLibName.rfind(nvngxExW); if (pos != std::string::npos && pos == (lcaseLibName.size() - nvngxExW.size())) { LOG_INFO("{0} call, returning this dll!", lcaseLibNameA); *phModule = dllModule; return TRUE; } #endif #ifdef GET_MODULE_DLL // Opti if (CheckDllNameW(&lcaseLibName, &dllNamesW)) { LOG_INFO("{0} call, returning this dll!", lcaseLibNameA); *phModule = dllModule; return TRUE; } #endif } return o_GetModuleHandleExW(dwFlags, lpModuleName, phModule); } #endif static BOOL hkFreeLibrary(HMODULE lpLibrary) { if (lpLibrary == nullptr) return FALSE; if (lpLibrary == dllModule) { if (loadCount > 0) loadCount--; LOG_INFO("Call for this module loadCount: {0}", loadCount); if (loadCount == 0) return o_FreeLibrary(lpLibrary); else return TRUE; } return o_FreeLibrary(lpLibrary); } static HMODULE hkLoadLibraryA(LPCSTR lpLibFileName) { if (lpLibFileName == nullptr) return NULL; if (!skipLoadChecks) { std::string libName(lpLibFileName); std::string lcaseLibName(libName); for (size_t i = 0; i < lcaseLibName.size(); i++) lcaseLibName[i] = std::tolower(lcaseLibName[i]); #ifdef _DEBUG LOG_TRACE("call: {0}", lcaseLibName); #endif // DEBUG auto moduleHandle = LoadLibraryCheck(lcaseLibName, lpLibFileName); // skip loading of dll if (moduleHandle == (HMODULE)1) { SetLastError(ERROR_ACCESS_DENIED); return NULL; } if (moduleHandle != nullptr) return moduleHandle; } dontCount = true; auto result = o_LoadLibraryA(lpLibFileName); dontCount = false; return result; } static HMODULE hkLoadLibraryW(LPCWSTR lpLibFileName) { if (lpLibFileName == nullptr) return NULL; if (!skipLoadChecks) { std::wstring libName(lpLibFileName); std::wstring lcaseLibName(libName); for (size_t i = 0; i < lcaseLibName.size(); i++) lcaseLibName[i] = std::tolower(lcaseLibName[i]); #ifdef _DEBUG LOG_TRACE("call: {0}", wstring_to_string(lcaseLibName)); #endif // DEBUG auto moduleHandle = LoadLibraryCheckW(lcaseLibName, lpLibFileName); // skip loading of dll if (moduleHandle == (HMODULE)1) { SetLastError(ERROR_ACCESS_DENIED); return NULL; } if (moduleHandle != nullptr) return moduleHandle; } dontCount = true; auto result = o_LoadLibraryW(lpLibFileName); dontCount = false; return result; } static HMODULE hkLoadLibraryExA(LPCSTR lpLibFileName, HANDLE hFile, DWORD dwFlags) { if (lpLibFileName == nullptr) return NULL; if (!skipLoadChecks) { std::string libName(lpLibFileName); std::string lcaseLibName(libName); for (size_t i = 0; i < lcaseLibName.size(); i++) lcaseLibName[i] = std::tolower(lcaseLibName[i]); #ifdef _DEBUG LOG_TRACE("call: {0}", lcaseLibName); #endif auto moduleHandle = LoadLibraryCheck(lcaseLibName, lpLibFileName); // skip loading of dll if (moduleHandle == (HMODULE)1) { SetLastError(ERROR_ACCESS_DENIED); return NULL; } if (moduleHandle != nullptr) return moduleHandle; } dontCount = true; auto result = o_LoadLibraryExA(lpLibFileName, hFile, dwFlags); dontCount = false; return result; } static HMODULE hkLoadLibraryExW(LPCWSTR lpLibFileName, HANDLE hFile, DWORD dwFlags) { if (lpLibFileName == nullptr) return NULL; if (!skipLoadChecks) { std::wstring libName(lpLibFileName); std::wstring lcaseLibName(libName); for (size_t i = 0; i < lcaseLibName.size(); i++) lcaseLibName[i] = std::tolower(lcaseLibName[i]); #ifdef _DEBUG LOG_TRACE("call: {0}", wstring_to_string(lcaseLibName)); #endif auto moduleHandle = LoadLibraryCheckW(lcaseLibName, lpLibFileName); // skip loading of dll if (moduleHandle == (HMODULE)1) { SetLastError(ERROR_ACCESS_DENIED); return NULL; } if (moduleHandle != nullptr) return moduleHandle; } dontCount = true; auto result = o_LoadLibraryExW(lpLibFileName, hFile, dwFlags); dontCount = false; return result; } static HMODULE hkKernelBase_LoadLibraryA(LPCSTR lpLibFileName) { if (lpLibFileName == nullptr) return NULL; if (!skipLoadChecks) { std::string libName(lpLibFileName); std::string lcaseLibName(libName); for (size_t i = 0; i < lcaseLibName.size(); i++) lcaseLibName[i] = std::tolower(lcaseLibName[i]); #ifdef _DEBUG LOG_TRACE("call: {0}", lcaseLibName); #endif // DEBUG auto moduleHandle = LoadLibraryCheck(lcaseLibName, lpLibFileName); // skip loading of dll if (moduleHandle == (HMODULE)1) { SetLastError(ERROR_ACCESS_DENIED); return NULL; } if (moduleHandle != nullptr) return moduleHandle; } dontCount = true; auto result = o_KernelBase_LoadLibraryA(lpLibFileName); dontCount = false; return result; } static HMODULE hkKernelBase_LoadLibraryW(LPCWSTR lpLibFileName) { if (lpLibFileName == nullptr) return NULL; if (!skipLoadChecks) { std::wstring libName(lpLibFileName); std::wstring lcaseLibName(libName); for (size_t i = 0; i < lcaseLibName.size(); i++) lcaseLibName[i] = std::tolower(lcaseLibName[i]); #ifdef _DEBUG LOG_TRACE("call: {0}", wstring_to_string(lcaseLibName)); #endif // DEBUG auto moduleHandle = LoadLibraryCheckW(lcaseLibName, lpLibFileName); // skip loading of dll if (moduleHandle == (HMODULE)1) { SetLastError(ERROR_ACCESS_DENIED); return NULL; } if (moduleHandle != nullptr) return moduleHandle; } dontCount = true; auto result = o_KernelBase_LoadLibraryW(lpLibFileName); dontCount = false; return result; } static HMODULE hkKernelBase_LoadLibraryExA(LPCSTR lpLibFileName, HANDLE hFile, DWORD dwFlags) { if (lpLibFileName == nullptr) return NULL; if (!skipLoadChecks) { std::string libName(lpLibFileName); std::string lcaseLibName(libName); for (size_t i = 0; i < lcaseLibName.size(); i++) lcaseLibName[i] = std::tolower(lcaseLibName[i]); #ifdef _DEBUG LOG_TRACE("call: {0}", lcaseLibName); #endif auto moduleHandle = LoadLibraryCheck(lcaseLibName, lpLibFileName); // skip loading of dll if (moduleHandle == (HMODULE)1) { SetLastError(ERROR_ACCESS_DENIED); return NULL; } if (moduleHandle != nullptr) return moduleHandle; } dontCount = true; auto result = o_KernelBase_LoadLibraryExA(lpLibFileName, hFile, dwFlags); dontCount = false; return result; } static HMODULE hkKernelBase_LoadLibraryExW(LPCWSTR lpLibFileName, HANDLE hFile, DWORD dwFlags) { if (lpLibFileName == nullptr) return NULL; if (!skipLoadChecks) { std::wstring libName(lpLibFileName); std::wstring lcaseLibName(libName); for (size_t i = 0; i < lcaseLibName.size(); i++) lcaseLibName[i] = std::tolower(lcaseLibName[i]); #ifdef _DEBUG LOG_TRACE("call: {0}", wstring_to_string(lcaseLibName)); #endif auto moduleHandle = LoadLibraryCheckW(lcaseLibName, lpLibFileName); // skip loading of dll if (moduleHandle == (HMODULE)1) { SetLastError(ERROR_ACCESS_DENIED); return NULL; } if (moduleHandle != nullptr) return moduleHandle; } dontCount = true; auto result = o_KernelBase_LoadLibraryExW(lpLibFileName, hFile, dwFlags); dontCount = false; return result; } #pragma endregion #pragma region Vulkan Hooks static void hkvkGetPhysicalDeviceMemoryProperties(VkPhysicalDevice physicalDevice, VkPhysicalDeviceMemoryProperties* pMemoryProperties) { o_vkGetPhysicalDeviceMemoryProperties(physicalDevice, pMemoryProperties); if (pMemoryProperties == nullptr) return; for (size_t i = 0; i < pMemoryProperties->memoryHeapCount; i++) { if (pMemoryProperties->memoryHeaps[i].flags & VK_MEMORY_HEAP_DEVICE_LOCAL_BIT) { uint64_t newMemSize = (uint64_t)Config::Instance()->VulkanVRAM.value() * 1024 * 1024 * 1024; pMemoryProperties->memoryHeaps[i].size = newMemSize; } } } static void hkvkGetPhysicalDeviceMemoryProperties2(VkPhysicalDevice physicalDevice, VkPhysicalDeviceMemoryProperties2* pMemoryProperties) { o_vkGetPhysicalDeviceMemoryProperties2(physicalDevice, pMemoryProperties); if (pMemoryProperties == nullptr || pMemoryProperties->sType != VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2) return; for (size_t i = 0; i < pMemoryProperties->memoryProperties.memoryHeapCount; i++) { if (pMemoryProperties->memoryProperties.memoryHeaps[i].flags & VK_MEMORY_HEAP_DEVICE_LOCAL_BIT) { uint64_t newMemSize = (uint64_t)Config::Instance()->VulkanVRAM.value() * 1024 * 1024 * 1024; pMemoryProperties->memoryProperties.memoryHeaps[i].size = newMemSize; } } } static void hkvkGetPhysicalDeviceMemoryProperties2KHR(VkPhysicalDevice physicalDevice, VkPhysicalDeviceMemoryProperties2* pMemoryProperties) { o_vkGetPhysicalDeviceMemoryProperties2(physicalDevice, pMemoryProperties); if (pMemoryProperties == nullptr || pMemoryProperties->sType != VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2_KHR) return; for (size_t i = 0; i < pMemoryProperties->memoryProperties.memoryHeapCount; i++) { if (pMemoryProperties->memoryProperties.memoryHeaps[i].flags & VK_MEMORY_HEAP_DEVICE_LOCAL_BIT) { uint64_t newMemSize = (uint64_t)Config::Instance()->VulkanVRAM.value() * 1024 * 1024 * 1024; pMemoryProperties->memoryProperties.memoryHeaps[i].size = newMemSize; } } } static void hkvkGetPhysicalDeviceProperties(VkPhysicalDevice physical_device, VkPhysicalDeviceProperties* properties) { o_vkGetPhysicalDeviceProperties(physical_device, properties); if (!State::Instance().skipSpoofing) { auto deviceName = wstring_to_string(Config::Instance()->SpoofedGPUName.value_or_default()); std::strcpy(properties->deviceName, deviceName.c_str()); properties->vendorID = 0x10de; properties->deviceID = 0x2684; properties->driverVersion = VK_MAKE_API_VERSION(999, 99, 0, 0); } else { LOG_DEBUG("Skipping spoofing"); } } static void hkvkGetPhysicalDeviceProperties2(VkPhysicalDevice phys_dev, VkPhysicalDeviceProperties2* properties2) { o_vkGetPhysicalDeviceProperties2(phys_dev, properties2); if (!State::Instance().skipSpoofing) { auto deviceName = wstring_to_string(Config::Instance()->SpoofedGPUName.value_or_default()); std::strcpy(properties2->properties.deviceName, deviceName.c_str()); properties2->properties.vendorID = 0x10de; properties2->properties.deviceID = 0x2684; properties2->properties.driverVersion = VK_MAKE_API_VERSION(999, 99, 0, 0); auto next = (VkDummyProps*)properties2->pNext; while (next != nullptr) { if (next->sType == VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES) { auto ddp = (VkPhysicalDeviceDriverProperties*)(void*)next; ddp->driverID = VK_DRIVER_ID_NVIDIA_PROPRIETARY; std::strcpy(ddp->driverName, "NVIDIA"); std::strcpy(ddp->driverInfo, "999.99"); } next = (VkDummyProps*)next->pNext; } } else { LOG_DEBUG("Skipping spoofing"); } } static void hkvkGetPhysicalDeviceProperties2KHR(VkPhysicalDevice phys_dev, VkPhysicalDeviceProperties2* properties2) { o_vkGetPhysicalDeviceProperties2KHR(phys_dev, properties2); if (!State::Instance().skipSpoofing) { auto deviceName = wstring_to_string(Config::Instance()->SpoofedGPUName.value_or_default()); std::strcpy(properties2->properties.deviceName, deviceName.c_str()); properties2->properties.vendorID = 0x10de; properties2->properties.deviceID = 0x2684; properties2->properties.driverVersion = VK_MAKE_API_VERSION(999, 99, 0, 0); auto next = (VkDummyProps*)properties2->pNext; while (next != nullptr) { if (next->sType == VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES) { auto ddp = (VkPhysicalDeviceDriverProperties*)(void*)next; ddp->driverID = VK_DRIVER_ID_NVIDIA_PROPRIETARY; std::strcpy(ddp->driverName, "NVIDIA"); std::strcpy(ddp->driverInfo, "999.99"); } next = (VkDummyProps*)next->pNext; } } else { LOG_DEBUG("Skipping spoofing"); } } static VkResult hkvkCreateInstance(VkInstanceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkInstance* pInstance) { if (pCreateInfo->pApplicationInfo->pApplicationName != nullptr) LOG_DEBUG("for {0}", pCreateInfo->pApplicationInfo->pApplicationName); std::vector newExtensionList; LOG_DEBUG("extensions ({0}):", pCreateInfo->enabledExtensionCount); for (size_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) { LOG_DEBUG(" {0}", pCreateInfo->ppEnabledExtensionNames[i]); newExtensionList.push_back(pCreateInfo->ppEnabledExtensionNames[i]); } if (State::Instance().isRunningOnNvidia) { LOG_INFO("Adding NVNGX Vulkan extensions"); newExtensionList.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); newExtensionList.push_back(VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME); newExtensionList.push_back(VK_KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_EXTENSION_NAME); } LOG_INFO("Adding FFX Vulkan extensions"); newExtensionList.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME); LOG_DEBUG("layers ({0}):", pCreateInfo->enabledLayerCount); for (size_t i = 0; i < pCreateInfo->enabledLayerCount; i++) LOG_DEBUG(" {0}", pCreateInfo->ppEnabledLayerNames[i]); pCreateInfo->enabledExtensionCount = static_cast(newExtensionList.size()); pCreateInfo->ppEnabledExtensionNames = newExtensionList.data(); // Skip spoofing for Intel Arc State::Instance().skipSpoofing = true; auto result = o_vkCreateInstance(pCreateInfo, pAllocator, pInstance); State::Instance().skipSpoofing = false; LOG_DEBUG("o_vkCreateInstance result: {0:X}", (INT)result); if (result == VK_SUCCESS) State::Instance().VulkanInstance = *pInstance; auto head = (VkBaseInStructure*)pCreateInfo; while (head->pNext != nullptr) { head = (VkBaseInStructure*)head->pNext; LOG_DEBUG("o_vkCreateInstance type: {0:X}", (UINT)head->sType); } return result; } static VkResult hkvkCreateDevice(VkPhysicalDevice physicalDevice, VkDeviceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDevice* pDevice) { LOG_FUNC(); std::vector newExtensionList; LOG_DEBUG("Checking extensions and removing VK_NVX_BINARY_IMPORT & VK_NVX_IMAGE_VIEW_HANDLE from list"); for (size_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) { if (Config::Instance()->VulkanExtensionSpoofing.value_or_default() && !State::Instance().isRunningOnNvidia && (std::strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_NVX_BINARY_IMPORT_EXTENSION_NAME) == 0 || std::strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_NVX_IMAGE_VIEW_HANDLE_EXTENSION_NAME) == 0 || std::strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_NVX_MULTIVIEW_PER_VIEW_ATTRIBUTES_EXTENSION_NAME) == 0)) { LOG_DEBUG("removing {0}", pCreateInfo->ppEnabledExtensionNames[i]); } else { LOG_DEBUG("adding {0}", pCreateInfo->ppEnabledExtensionNames[i]); newExtensionList.push_back(pCreateInfo->ppEnabledExtensionNames[i]); } } if (State::Instance().isRunningOnNvidia) { LOG_INFO("Adding NVNGX Vulkan extensions"); newExtensionList.push_back(VK_NVX_BINARY_IMPORT_EXTENSION_NAME); newExtensionList.push_back(VK_NVX_IMAGE_VIEW_HANDLE_EXTENSION_NAME); newExtensionList.push_back(VK_NVX_MULTIVIEW_PER_VIEW_ATTRIBUTES_EXTENSION_NAME); newExtensionList.push_back(VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME); newExtensionList.push_back(VK_EXT_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME); } LOG_INFO("Adding FFX Vulkan extensions"); newExtensionList.push_back(VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME); LOG_INFO("Adding XeSS Vulkan extensions"); newExtensionList.push_back(VK_KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME); newExtensionList.push_back(VK_KHR_SHADER_INTEGER_DOT_PRODUCT_EXTENSION_NAME); newExtensionList.push_back(VK_EXT_MUTABLE_DESCRIPTOR_TYPE_EXTENSION_NAME); pCreateInfo->enabledExtensionCount = static_cast(newExtensionList.size()); pCreateInfo->ppEnabledExtensionNames = newExtensionList.data(); LOG_DEBUG("final extension count: {0}", pCreateInfo->enabledExtensionCount); LOG_DEBUG("final extensions:"); for (size_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) LOG_DEBUG(" {0}", pCreateInfo->ppEnabledExtensionNames[i]); // Skip spoofing for Intel Arc State::Instance().skipSpoofing = true; auto result = o_vkCreateDevice(physicalDevice, pCreateInfo, pAllocator, pDevice); State::Instance().skipSpoofing = false; LOG_FUNC_RESULT(result); return result; } static VkResult hkvkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice, const char* pLayerName, uint32_t* pPropertyCount, VkExtensionProperties* pProperties) { LOG_FUNC(); auto count = *pPropertyCount; if (pProperties == nullptr) count = 0; auto result = o_vkEnumerateDeviceExtensionProperties(physicalDevice, pLayerName, pPropertyCount, pProperties); if (result != VK_SUCCESS) { LOG_ERROR("o_vkEnumerateDeviceExtensionProperties({0}, {1}) result: {2:X}", pLayerName, count, (UINT)result); return result; } if (pLayerName == nullptr && pProperties == nullptr && count == 0) { *pPropertyCount += 3; vkEnumerateDeviceExtensionPropertiesCount = *pPropertyCount; LOG_TRACE("hkvkEnumerateDeviceExtensionProperties({0}) count: {1}", pLayerName, vkEnumerateDeviceExtensionPropertiesCount); return result; } if (pLayerName == nullptr && pProperties != nullptr && *pPropertyCount > 0) { if (count == vkEnumerateDeviceExtensionPropertiesCount) *pPropertyCount = count; VkExtensionProperties bi{ VK_NVX_BINARY_IMPORT_EXTENSION_NAME, VK_NVX_BINARY_IMPORT_SPEC_VERSION }; memcpy(&pProperties[*pPropertyCount - 1], &bi, sizeof(VkExtensionProperties)); VkExtensionProperties ivh{ VK_NVX_IMAGE_VIEW_HANDLE_EXTENSION_NAME, VK_NVX_IMAGE_VIEW_HANDLE_SPEC_VERSION }; memcpy(&pProperties[*pPropertyCount - 2], &ivh, sizeof(VkExtensionProperties)); VkExtensionProperties mpva{ VK_NVX_MULTIVIEW_PER_VIEW_ATTRIBUTES_EXTENSION_NAME, VK_NVX_MULTIVIEW_PER_VIEW_ATTRIBUTES_SPEC_VERSION }; memcpy(&pProperties[*pPropertyCount - 3], &mpva, sizeof(VkExtensionProperties)); LOG_DEBUG("Extensions returned:"); for (size_t i = 0; i < *pPropertyCount; i++) { LOG_DEBUG(" {}", pProperties[i].extensionName); } } LOG_FUNC_RESULT(result); return result; } static VkResult hkvkEnumerateInstanceExtensionProperties(const char* pLayerName, uint32_t* pPropertyCount, VkExtensionProperties* pProperties) { LOG_FUNC(); auto count = *pPropertyCount; if (pProperties == nullptr) count = 0; auto result = o_vkEnumerateInstanceExtensionProperties(pLayerName, pPropertyCount, pProperties); if (result != VK_SUCCESS) { LOG_ERROR("o_vkEnumerateInstanceExtensionProperties({0}, {1}) result: {2:X}", pLayerName, count, (UINT)result); return result; } if (pLayerName == nullptr && pProperties == nullptr && count == 0) { //*pPropertyCount += 2; //vkEnumerateInstanceExtensionPropertiesCount = *pPropertyCount; LOG_TRACE("hkvkEnumerateDeviceExtensionProperties({0}) count: {1}", pLayerName, vkEnumerateDeviceExtensionPropertiesCount); return result; } //if (pLayerName == nullptr && pProperties != nullptr && *pPropertyCount > 0) //{ // if (vkEnumerateInstanceExtensionPropertiesCount == count) // *pPropertyCount = count; // VkExtensionProperties bi{ VK_NVX_BINARY_IMPORT_EXTENSION_NAME, VK_NVX_BINARY_IMPORT_SPEC_VERSION }; // memcpy(&pProperties[*pPropertyCount - 1], &bi, sizeof(VkExtensionProperties)); // VkExtensionProperties ivh{ VK_NVX_IMAGE_VIEW_HANDLE_EXTENSION_NAME, VK_NVX_IMAGE_VIEW_HANDLE_SPEC_VERSION }; // memcpy(&pProperties[*pPropertyCount - 2], &ivh, sizeof(VkExtensionProperties)); // LOG_DEBUG("Extensions returned:"); // for (size_t i = 0; i < *pPropertyCount; i++) // { // LOG_DEBUG(" {}", pProperties[i].extensionName); // } //} LOG_DEBUG("Extensions returned:"); for (size_t i = 0; i < *pPropertyCount; i++) { LOG_DEBUG(" {}", pProperties[i].extensionName); } LOG_FUNC_RESULT(result); return result; } #pragma endregion inline static void HookForDxgiSpoofing(HMODULE dxgiModule) { // hook dxgi when not working as dxgi.dll if (dxgi.CreateDxgiFactory == nullptr && !isWorkingWithEnabler && !State::Instance().isDxgiMode && Config::Instance()->DxgiSpoofing.value_or_default()) { LOG_INFO("DxgiSpoofing is enabled loading dxgi.dll"); dxgi.CreateDxgiFactory = (PFN_CREATE_DXGI_FACTORY)GetProcAddress(dxgiModule, "CreateDXGIFactory"); dxgi.CreateDxgiFactory1 = (PFN_CREATE_DXGI_FACTORY_1)GetProcAddress(dxgiModule, "CreateDXGIFactory1"); dxgi.CreateDxgiFactory2 = (PFN_CREATE_DXGI_FACTORY_2)GetProcAddress(dxgiModule, "CreateDXGIFactory2"); if (dxgi.CreateDxgiFactory != nullptr || dxgi.CreateDxgiFactory1 != nullptr || dxgi.CreateDxgiFactory2 != nullptr) { LOG_INFO("dxgi.dll found, hooking CreateDxgiFactory methods"); DetourTransactionBegin(); DetourUpdateThread(GetCurrentThread()); if (dxgi.CreateDxgiFactory != nullptr) DetourAttach(&(PVOID&)dxgi.CreateDxgiFactory, _CreateDXGIFactory); if (dxgi.CreateDxgiFactory1 != nullptr) DetourAttach(&(PVOID&)dxgi.CreateDxgiFactory1, _CreateDXGIFactory1); if (dxgi.CreateDxgiFactory2 != nullptr) DetourAttach(&(PVOID&)dxgi.CreateDxgiFactory2, _CreateDXGIFactory2); DetourTransactionCommit(); } } } inline static void HookForVulkanSpoofing(HMODULE vulkanModule) { if (!isNvngxMode && Config::Instance()->VulkanSpoofing.value_or_default() && o_vkGetPhysicalDeviceProperties == nullptr) { o_vkGetPhysicalDeviceProperties = reinterpret_cast(GetProcAddress(vulkanModule, "vkGetPhysicalDeviceProperties")); o_vkGetPhysicalDeviceProperties2 = reinterpret_cast(GetProcAddress(vulkanModule, "vkGetPhysicalDeviceProperties2")); o_vkGetPhysicalDeviceProperties2KHR = reinterpret_cast(GetProcAddress(vulkanModule, "vkGetPhysicalDeviceProperties2KHR")); if (o_vkGetPhysicalDeviceProperties != nullptr) { LOG_INFO("Attaching Vulkan device spoofing hooks"); DetourTransactionBegin(); DetourUpdateThread(GetCurrentThread()); if (o_vkGetPhysicalDeviceProperties) DetourAttach(&(PVOID&)o_vkGetPhysicalDeviceProperties, hkvkGetPhysicalDeviceProperties); if (o_vkGetPhysicalDeviceProperties2) DetourAttach(&(PVOID&)o_vkGetPhysicalDeviceProperties2, hkvkGetPhysicalDeviceProperties2); if (o_vkGetPhysicalDeviceProperties2KHR) DetourAttach(&(PVOID&)o_vkGetPhysicalDeviceProperties2KHR, hkvkGetPhysicalDeviceProperties2KHR); DetourTransactionCommit(); } } } inline static void HookForVulkanExtensionSpoofing(HMODULE vulkanModule) { if (!isNvngxMode && Config::Instance()->VulkanExtensionSpoofing.value_or_default() && o_vkEnumerateInstanceExtensionProperties == nullptr) { o_vkCreateDevice = reinterpret_cast(GetProcAddress(vulkanModule, "vkCreateDevice")); o_vkCreateInstance = reinterpret_cast(GetProcAddress(vulkanModule, "vkCreateInstance")); o_vkEnumerateInstanceExtensionProperties = reinterpret_cast(GetProcAddress(vulkanModule, "vkEnumerateInstanceExtensionProperties")); o_vkEnumerateDeviceExtensionProperties = reinterpret_cast(GetProcAddress(vulkanModule, "vkEnumerateDeviceExtensionProperties")); if (o_vkEnumerateInstanceExtensionProperties != nullptr || o_vkEnumerateDeviceExtensionProperties != nullptr) { LOG_INFO("Attaching Vulkan extensions spoofing hooks"); DetourTransactionBegin(); DetourUpdateThread(GetCurrentThread()); if (o_vkEnumerateInstanceExtensionProperties) DetourAttach(&(PVOID&)o_vkEnumerateInstanceExtensionProperties, hkvkEnumerateInstanceExtensionProperties); if (o_vkEnumerateDeviceExtensionProperties) DetourAttach(&(PVOID&)o_vkEnumerateDeviceExtensionProperties, hkvkEnumerateDeviceExtensionProperties); if (o_vkCreateDevice) DetourAttach(&(PVOID&)o_vkCreateDevice, hkvkCreateDevice); if (o_vkCreateInstance) DetourAttach(&(PVOID&)o_vkCreateInstance, hkvkCreateInstance); DetourTransactionCommit(); } } } inline static void HookForVulkanVRAMSpoofing(HMODULE vulkanModule) { if (!isNvngxMode && Config::Instance()->VulkanVRAM.has_value() && o_vkGetPhysicalDeviceMemoryProperties == nullptr) { o_vkGetPhysicalDeviceMemoryProperties = reinterpret_cast(GetProcAddress(vulkanModule, "vkGetPhysicalDeviceMemoryProperties")); o_vkGetPhysicalDeviceMemoryProperties2 = reinterpret_cast(GetProcAddress(vulkanModule, "vkGetPhysicalDeviceMemoryProperties2")); o_vkGetPhysicalDeviceMemoryProperties2KHR = reinterpret_cast(GetProcAddress(vulkanModule, "vkGetPhysicalDeviceMemoryProperties2KHR")); if (o_vkGetPhysicalDeviceMemoryProperties != nullptr || o_vkGetPhysicalDeviceMemoryProperties2 != nullptr || o_vkGetPhysicalDeviceMemoryProperties2KHR != nullptr) { LOG_INFO("Attaching Vulkan VRAM spoofing hooks"); DetourTransactionBegin(); DetourUpdateThread(GetCurrentThread()); if (o_vkGetPhysicalDeviceMemoryProperties) DetourAttach(&(PVOID&)o_vkGetPhysicalDeviceMemoryProperties, hkvkGetPhysicalDeviceMemoryProperties); if (o_vkGetPhysicalDeviceMemoryProperties2) DetourAttach(&(PVOID&)o_vkGetPhysicalDeviceMemoryProperties2, hkvkGetPhysicalDeviceMemoryProperties2); if (o_vkGetPhysicalDeviceMemoryProperties2KHR) DetourAttach(&(PVOID&)o_vkGetPhysicalDeviceMemoryProperties2KHR, hkvkGetPhysicalDeviceMemoryProperties2KHR); DetourTransactionCommit(); } } } static void DetachHooks() { if (!isNvngxMode) { HooksDx::UnHookDx(); HooksVk::UnHookVk(); } if (o_LoadLibraryA != nullptr || o_LoadLibraryW != nullptr || o_LoadLibraryExA != nullptr || o_LoadLibraryExW != nullptr) { DetourTransactionBegin(); DetourUpdateThread(GetCurrentThread()); if (o_FreeLibrary) { DetourDetach(&(PVOID&)o_FreeLibrary, hkFreeLibrary); o_FreeLibrary = nullptr; } if (o_LoadLibraryA) { DetourDetach(&(PVOID&)o_LoadLibraryA, hkLoadLibraryA); o_LoadLibraryA = nullptr; } if (o_LoadLibraryW) { DetourDetach(&(PVOID&)o_LoadLibraryW, hkLoadLibraryW); o_LoadLibraryW = nullptr; } if (o_LoadLibraryExA) { DetourDetach(&(PVOID&)o_LoadLibraryExA, hkLoadLibraryExA); o_LoadLibraryExA = nullptr; } if (o_LoadLibraryExW) { DetourDetach(&(PVOID&)o_LoadLibraryExW, hkLoadLibraryExW); o_LoadLibraryExW = nullptr; } if (o_GetProcAddress) { DetourDetach(&(PVOID&)o_GetProcAddress, hkGetProcAddress); o_GetProcAddress = nullptr; } if (o_KernelBase_GetProcAddress) { DetourDetach(&(PVOID&)o_KernelBase_GetProcAddress, hkGetProcAddress); o_KernelBase_GetProcAddress = nullptr; } if (o_vkGetPhysicalDeviceProperties) { DetourDetach(&(PVOID&)o_vkGetPhysicalDeviceProperties, hkvkGetPhysicalDeviceProperties); o_vkGetPhysicalDeviceProperties = nullptr; } if (o_vkGetPhysicalDeviceProperties2) { DetourDetach(&(PVOID&)o_vkGetPhysicalDeviceProperties2, hkvkGetPhysicalDeviceProperties2); o_vkGetPhysicalDeviceProperties2 = nullptr; } if (o_vkGetPhysicalDeviceProperties2KHR) { DetourDetach(&(PVOID&)o_vkGetPhysicalDeviceProperties2KHR, hkvkGetPhysicalDeviceProperties2KHR); o_vkGetPhysicalDeviceProperties2KHR = nullptr; } if (o_vkEnumerateInstanceExtensionProperties) { DetourDetach(&(PVOID&)o_vkEnumerateInstanceExtensionProperties, hkvkEnumerateInstanceExtensionProperties); o_vkEnumerateInstanceExtensionProperties = nullptr; } if (o_vkEnumerateDeviceExtensionProperties) { DetourDetach(&(PVOID&)o_vkEnumerateDeviceExtensionProperties, hkvkEnumerateDeviceExtensionProperties); o_vkEnumerateDeviceExtensionProperties = nullptr; } if (o_vkCreateDevice) { DetourDetach(&(PVOID&)o_vkCreateDevice, hkvkCreateDevice); o_vkCreateDevice = nullptr; } if (o_vkCreateInstance) { DetourDetach(&(PVOID&)o_vkCreateInstance, hkvkCreateInstance); o_vkCreateInstance = nullptr; } if (!State::Instance().isDxgiMode && Config::Instance()->DxgiSpoofing.value_or_default()) { if (dxgi.CreateDxgiFactory != nullptr) { DetourDetach(&(PVOID&)dxgi.CreateDxgiFactory, _CreateDXGIFactory); dxgi.CreateDxgiFactory = nullptr; } if (dxgi.CreateDxgiFactory1 != nullptr) { DetourDetach(&(PVOID&)dxgi.CreateDxgiFactory1, _CreateDXGIFactory1); dxgi.CreateDxgiFactory1 = nullptr; } if (dxgi.CreateDxgiFactory2 != nullptr) { DetourDetach(&(PVOID&)dxgi.CreateDxgiFactory2, _CreateDXGIFactory2); dxgi.CreateDxgiFactory2 = nullptr; } } DetourTransactionCommit(); FreeLibrary(shared.dll); } } static void AttachHooks() { LOG_FUNC(); if (o_LoadLibraryA == nullptr || o_LoadLibraryW == nullptr) { // Detour the functions o_FreeLibrary = reinterpret_cast(DetourFindFunction("kernel32.dll", "FreeLibrary")); o_LoadLibraryA = reinterpret_cast(DetourFindFunction("kernel32.dll", "LoadLibraryA")); o_LoadLibraryW = reinterpret_cast(DetourFindFunction("kernel32.dll", "LoadLibraryW")); o_LoadLibraryExA = reinterpret_cast(DetourFindFunction("kernel32.dll", "LoadLibraryExA")); o_LoadLibraryExW = reinterpret_cast(DetourFindFunction("kernel32.dll", "LoadLibraryExW")); #ifdef HOOK_GET_MODULE o_GetModuleHandleA = reinterpret_cast(DetourFindFunction("kernel32.dll", "GetModuleHandleA")); o_GetModuleHandleW = reinterpret_cast(DetourFindFunction("kernel32.dll", "GetModuleHandleW")); o_GetModuleHandleExA = reinterpret_cast(DetourFindFunction("kernel32.dll", "GetModuleHandleExA")); o_GetModuleHandleExW = reinterpret_cast(DetourFindFunction("kernel32.dll", "GetModuleHandleExW")); #endif o_GetProcAddress = reinterpret_cast(DetourFindFunction("kernel32.dll", "GetProcAddress")); o_KernelBase_LoadLibraryA = reinterpret_cast(DetourFindFunction("kernelbase.dll", "LoadLibraryA")); o_KernelBase_LoadLibraryW = reinterpret_cast(DetourFindFunction("kernelbase.dll", "LoadLibraryW")); o_KernelBase_LoadLibraryExA = reinterpret_cast(DetourFindFunction("kerkernelbasenel32.dll", "LoadLibraryExA")); o_KernelBase_LoadLibraryExW = reinterpret_cast(DetourFindFunction("kernelbase.dll", "LoadLibraryExW")); o_KernelBase_GetProcAddress = reinterpret_cast(DetourFindFunction("kernelbase.dll", "GetProcAddress")); if (o_LoadLibraryA != nullptr || o_LoadLibraryW != nullptr || o_LoadLibraryExA != nullptr || o_LoadLibraryExW != nullptr) { LOG_INFO("Attaching LoadLibrary hooks"); DetourTransactionBegin(); DetourUpdateThread(GetCurrentThread()); if (o_FreeLibrary) DetourAttach(&(PVOID&)o_FreeLibrary, hkFreeLibrary); if (o_LoadLibraryA) DetourAttach(&(PVOID&)o_LoadLibraryA, hkLoadLibraryA); if (o_LoadLibraryW) DetourAttach(&(PVOID&)o_LoadLibraryW, hkLoadLibraryW); if (o_LoadLibraryExA) DetourAttach(&(PVOID&)o_LoadLibraryExA, hkLoadLibraryExA); if (o_LoadLibraryExW) DetourAttach(&(PVOID&)o_LoadLibraryExW, hkLoadLibraryExW); if (o_KernelBase_LoadLibraryA) DetourAttach(&(PVOID&)o_KernelBase_LoadLibraryA, hkKernelBase_LoadLibraryA); if (o_KernelBase_LoadLibraryW) DetourAttach(&(PVOID&)o_KernelBase_LoadLibraryW, hkKernelBase_LoadLibraryW); if (o_KernelBase_LoadLibraryExA) DetourAttach(&(PVOID&)o_KernelBase_LoadLibraryExA, hkKernelBase_LoadLibraryExA); if (o_KernelBase_LoadLibraryExW) DetourAttach(&(PVOID&)o_KernelBase_LoadLibraryExW, hkKernelBase_LoadLibraryExW); #ifdef HOOK_GET_MODULE if (o_GetModuleHandleA) DetourAttach(&(PVOID&)o_GetModuleHandleA, hkGetModuleHandleA); if (o_GetModuleHandleW) DetourAttach(&(PVOID&)o_GetModuleHandleW, hkGetModuleHandleW); if (o_GetModuleHandleExA) DetourAttach(&(PVOID&)o_GetModuleHandleExA, hkGetModuleHandleExA); if (o_GetModuleHandleExW) DetourAttach(&(PVOID&)o_GetModuleHandleExW, hkGetModuleHandleExW); #endif // HOOK_GET_MODULE if (o_GetProcAddress) DetourAttach(&(PVOID&)o_GetProcAddress, hkGetProcAddress); if (o_KernelBase_GetProcAddress) DetourAttach(&(PVOID&)o_KernelBase_GetProcAddress, hkGetProcAddress); DetourTransactionCommit(); } } } static bool IsRunningOnWine() { LOG_FUNC(); HMODULE ntdll = GetModuleHandle(L"ntdll.dll"); if (!ntdll) { LOG_WARN("Not running on NT!?!"); return true; } auto pWineGetVersion = (PFN_wine_get_version)GetProcAddress(ntdll, "wine_get_version"); if (pWineGetVersion) { LOG_INFO("Running on Wine {0}!", pWineGetVersion()); return true; } LOG_WARN("Wine not detected"); return false; } static void CheckWorkingMode() { LOG_FUNC(); bool modeFound = false; std::string filename = Util::DllPath().filename().string(); std::string lCaseFilename(filename); wchar_t sysFolder[MAX_PATH]; GetSystemDirectory(sysFolder, MAX_PATH); std::filesystem::path sysPath(sysFolder); std::filesystem::path pluginPath(Config::Instance()->PluginPath.value_or_default()); for (size_t i = 0; i < lCaseFilename.size(); i++) lCaseFilename[i] = std::tolower(lCaseFilename[i]); HMODULE dll = nullptr; do { if (lCaseFilename == "nvngx.dll" || lCaseFilename == "_nvngx.dll" || lCaseFilename == "libxess.dll" || lCaseFilename == "dlss-enabler-upscaler.dll") { LOG_INFO("OptiScaler working as native upscaler: {0}", filename); dllNames.push_back("OptiScaler_DontLoad.dll"); dllNames.push_back("OptiScaler_DontLoad"); dllNamesW.push_back(L"OptiScaler_DontLoad.dll"); dllNamesW.push_back(L"OptiScaler_DontLoad"); isNvngxMode = true; isWorkingWithEnabler = lCaseFilename == "dlss-enabler-upscaler.dll"; if (isWorkingWithEnabler) Config::Instance()->LogToNGX.set_volatile_value(true); modeFound = true; break; } AttachHooks(); // version.dll if (lCaseFilename == "version.dll") { do { skipGetModuleHandle = true; auto pluginFilePath = pluginPath / L"version.dll"; dll = LoadLibrary(pluginFilePath.wstring().c_str()); if (dll != nullptr) { LOG_INFO("OptiScaler working as version.dll, original dll loaded from plugin folder"); break; } dll = LoadLibrary(L"version-original.dll"); if (dll != nullptr) { LOG_INFO("OptiScaler working as version.dll, version-original.dll loaded"); break; } auto sysFilePath = sysPath / L"version.dll"; dll = LoadLibrary(sysFilePath.wstring().c_str()); if (dll != nullptr) LOG_INFO("OptiScaler working as version.dll, system dll loaded"); skipGetModuleHandle = false; } while (false); if (dll != nullptr) { dllNames.push_back("version.dll"); dllNames.push_back("version"); dllNamesW.push_back(L"version.dll"); dllNamesW.push_back(L"version"); shared.LoadOriginalLibrary(dll); version.LoadOriginalLibrary(dll); modeFound = true; } else { spdlog::error("OptiScaler can't find original version.dll!"); } break; } // winmm.dll if (lCaseFilename == "winmm.dll") { do { skipGetModuleHandle = true; auto pluginFilePath = pluginPath / L"winmm.dll"; dll = LoadLibrary(pluginFilePath.wstring().c_str()); if (dll != nullptr) { LOG_INFO("OptiScaler working as winmm.dll, original dll loaded from plugin folder"); break; } dll = LoadLibrary(L"winmm-original.dll"); if (dll != nullptr) { LOG_INFO("OptiScaler working as winmm.dll, winmm-original.dll loaded"); break; } auto sysFilePath = sysPath / L"winmm.dll"; dll = LoadLibrary(sysFilePath.wstring().c_str()); if (dll != nullptr) LOG_INFO("OptiScaler working as winmm.dll, system dll loaded"); skipGetModuleHandle = false; } while (false); if (dll != nullptr) { dllNames.push_back("winmm.dll"); dllNames.push_back("winmm"); dllNamesW.push_back(L"winmm.dll"); dllNamesW.push_back(L"winmm"); shared.LoadOriginalLibrary(dll); winmm.LoadOriginalLibrary(dll); modeFound = true; } else { spdlog::error("OptiScaler can't find original winmm.dll!"); } break; } // wininet.dll if (lCaseFilename == "wininet.dll") { do { skipGetModuleHandle = true; auto pluginFilePath = pluginPath / L"wininet.dll"; dll = LoadLibrary(pluginFilePath.wstring().c_str()); if (dll != nullptr) { LOG_INFO("OptiScaler working as wininet.dll, original dll loaded from plugin folder"); break; } dll = LoadLibrary(L"wininet-original.dll"); if (dll != nullptr) { LOG_INFO("OptiScaler working as wininet.dll, wininet-original.dll loaded"); break; } auto sysFilePath = sysPath / L"wininet.dll"; dll = LoadLibrary(sysFilePath.wstring().c_str()); if (dll != nullptr) LOG_INFO("OptiScaler working as wininet.dll, system dll loaded"); skipGetModuleHandle = false; } while (false); if (dll != nullptr) { dllNames.push_back("wininet.dll"); dllNames.push_back("wininet"); dllNamesW.push_back(L"wininet.dll"); dllNamesW.push_back(L"wininet"); shared.LoadOriginalLibrary(dll); wininet.LoadOriginalLibrary(dll); modeFound = true; } else { spdlog::error("OptiScaler can't find original wininet.dll!"); } break; } // dbghelp.dll if (lCaseFilename == "dbghelp.dll") { do { skipGetModuleHandle = true; auto pluginFilePath = pluginPath / L"dbghelp.dll"; dll = LoadLibrary(pluginFilePath.wstring().c_str()); if (dll != nullptr) { LOG_INFO("OptiScaler working as dbghelp.dll, original dll loaded from plugin folder"); break; } dll = LoadLibrary(L"dbghelp-original.dll"); if (dll != nullptr) { LOG_INFO("OptiScaler working as dbghelp.dll, dbghelp-original.dll loaded"); break; } auto sysFilePath = sysPath / L"dbghelp.dll"; dll = LoadLibrary(sysFilePath.wstring().c_str()); if (dll != nullptr) LOG_INFO("OptiScaler working as dbghelp.dll, system dll loaded"); skipGetModuleHandle = false; } while (false); if (dll != nullptr) { dllNames.push_back("dbghelp.dll"); dllNames.push_back("dbghelp"); dllNamesW.push_back(L"dbghelp.dll"); dllNamesW.push_back(L"dbghelp"); shared.LoadOriginalLibrary(dll); dbghelp.LoadOriginalLibrary(dll); modeFound = true; } else { spdlog::error("OptiScaler can't find original dbghelp.dll!"); } break; } // optiscaler.dll if (lCaseFilename == "optiscaler.asi") { LOG_INFO("OptiScaler working as OptiScaler.asi"); // quick hack for testing dll = dllModule; dllNames.push_back("optiscaler.asi"); dllNames.push_back("optiscaler"); dllNamesW.push_back(L"optiscaler.asi"); dllNamesW.push_back(L"optiscaler"); modeFound = true; break; } // winhttp.dll if (lCaseFilename == "winhttp.dll") { do { skipGetModuleHandle = true; auto pluginFilePath = pluginPath / L"winhttp.dll"; dll = LoadLibrary(pluginFilePath.wstring().c_str()); if (dll != nullptr) { LOG_INFO("OptiScaler working as winhttp.dll, original dll loaded from plugin folder"); break; } dll = LoadLibrary(L"winhttp-original.dll"); if (dll != nullptr) { LOG_INFO("OptiScaler working as winhttp.dll, winhttp-original.dll loaded"); break; } auto sysFilePath = sysPath / L"winhttp.dll"; dll = LoadLibrary(sysFilePath.wstring().c_str()); if (dll != nullptr) LOG_INFO("OptiScaler working as winhttp.dll, system dll loaded"); skipGetModuleHandle = false; } while (false); if (dll != nullptr) { dllNames.push_back("winhttp.dll"); dllNames.push_back("winhttp"); dllNamesW.push_back(L"winhttp.dll"); dllNamesW.push_back(L"winhttp"); shared.LoadOriginalLibrary(dll); winhttp.LoadOriginalLibrary(dll); modeFound = true; } else { spdlog::error("OptiScaler can't find original winhttp.dll!"); } break; } // dxgi.dll if (lCaseFilename == "dxgi.dll") { do { skipGetModuleHandle = true; auto pluginFilePath = pluginPath / L"dxgi.optidll"; dll = LoadLibrary(pluginFilePath.wstring().c_str()); if (dll != nullptr) { LOG_INFO("OptiScaler working as dxgi.dll, original dll loaded from plugin folder"); break; } dll = LoadLibrary(L"dxgi-original.dll"); if (dll != nullptr) { LOG_INFO("OptiScaler working as dxgi.dll, dxgi-original.dll loaded"); break; } auto sysFilePath = sysPath / L"dxgi.optidll"; dll = LoadLibrary(sysFilePath.wstring().c_str()); if (dll != nullptr) LOG_INFO("OptiScaler working as dxgi.dll, system dll loaded"); skipGetModuleHandle = false; } while (false); if (dll != nullptr) { dllNames.push_back("dxgi.dll"); dllNames.push_back("dxgi"); dllNamesW.push_back(L"dxgi.dll"); dllNamesW.push_back(L"dxgi"); dxgi.LoadOriginalLibrary(dll); State::Instance().isDxgiMode = true; modeFound = true; } else { spdlog::error("OptiScaler can't find original dxgi.dll!"); } break; } // d3d12.dll if (lCaseFilename == "d3d12.dll") { do { skipGetModuleHandle = true; auto pluginFilePath = pluginPath / L"d3d12.optidll"; dll = LoadLibrary(pluginFilePath.wstring().c_str()); if (dll != nullptr) { LOG_INFO("OptiScaler working as d3d12.dll, original dll loaded from plugin folder"); break; } dll = LoadLibrary(L"d3d12-original.dll"); if (dll != nullptr) { LOG_INFO("OptiScaler working as d3d12.dll, d3d12-original.dll loaded"); break; } auto sysFilePath = sysPath / L"d3d12.optidll"; dll = LoadLibrary(sysFilePath.wstring().c_str()); if (dll != nullptr) LOG_INFO("OptiScaler working as d3d12.dll, system dll loaded"); skipGetModuleHandle = false; } while (false); if (dll != nullptr) { dllNames.push_back("d3d12.dll"); dllNames.push_back("d3d12"); dllNamesW.push_back(L"d3d12.dll"); dllNamesW.push_back(L"d3d12"); d3d12.LoadOriginalLibrary(dll); modeFound = true; } else { spdlog::error("OptiScaler can't find original d3d12.dll!"); } break; } } while (false); if (modeFound) { State::Instance().isWorkingAsNvngx = isNvngxMode && !isWorkingWithEnabler; Config::Instance()->OverlayMenu.set_volatile_value((!isNvngxMode || isWorkingWithEnabler) && Config::Instance()->OverlayMenu.value_or_default()); Config::Instance()->CheckUpscalerFiles(); if (!isNvngxMode || isWorkingWithEnabler) { AttachHooks(); // DXGI HMODULE dxgiModule = nullptr; dxgiModule = GetModuleHandle(L"dxgi.dll"); if (dxgiModule != nullptr) { LOG_DEBUG("dxgi.dll already in memory"); if (!isWorkingWithEnabler) HookForDxgiSpoofing(dxgiModule); if (Config::Instance()->OverlayMenu.value()) HooksDx::HookDxgi(dxgiModule); } // Vulkan HMODULE vulkanModule = nullptr; vulkanModule = GetModuleHandle(L"vulkan-1.dll"); if (State::Instance().isRunningOnDXVK || State::Instance().isRunningOnLinux) vulkanModule = LoadLibrary(L"vulkan-1.optidll"); if (vulkanModule != nullptr) { LOG_DEBUG("vulkan-1.dll already in memory"); if (!isWorkingWithEnabler) { HookForVulkanSpoofing(vulkanModule); HookForVulkanExtensionSpoofing(vulkanModule); HookForVulkanVRAMSpoofing(vulkanModule); } } if (Config::Instance()->OverlayMenu.value() && (vulkanModule != nullptr || State::Instance().isRunningOnLinux)) HooksVk::HookVk(vulkanModule); // NVAPI HMODULE nvapi64 = nullptr; nvapi64 = GetModuleHandle(L"nvapi64.dll"); if (nvapi64 != nullptr) { LOG_DEBUG("nvapi64.dll already in memory"); //if (!isWorkingWithEnabler) NvApiHooks::Hook(nvapi64); } hookGdi32(); // hook streamline right away if it's already loaded HMODULE slModule = nullptr; slModule = GetModuleHandle(L"sl.interposer.dll"); if (slModule != nullptr) { LOG_DEBUG("sl.interposer.dll already in memory"); skipLoadChecks = true; hookStreamline(slModule); skipLoadChecks = false; } // XeSS HMODULE xessModule = nullptr; xessModule = GetModuleHandle(L"libxess.dll"); if (xessModule != nullptr) { LOG_DEBUG("libxess.dll already in memory"); XeSSProxy::HookXeSS(xessModule); } // NVNGX HMODULE nvngxModule = nullptr; nvngxModule = GetModuleHandle(L"_nvngx.dll"); if (nvngxModule == nullptr) nvngxModule = GetModuleHandle(L"nvngx.dll"); if (nvngxModule != nullptr) { LOG_DEBUG("nvngx.dll already in memory"); NVNGXProxy::InitNVNGX(nvngxModule); } // FFX Dx12 HMODULE ffxDx12Module = nullptr; ffxDx12Module = GetModuleHandle(L"amd_fidelityfx_dx12.dll"); if (ffxDx12Module != nullptr) { LOG_DEBUG("amd_fidelityfx_dx12.dll already in memory"); FfxApiProxy::InitFfxDx12(ffxDx12Module); } // FFX Vulkan HMODULE ffxVkModule = nullptr; ffxVkModule = GetModuleHandle(L"amd_fidelityfx_vk.dll"); if (ffxVkModule != nullptr) { LOG_DEBUG("amd_fidelityfx_vk.dll already in memory"); FfxApiProxy::InitFfxVk(ffxVkModule); } // DirectX 11 HMODULE d3d11Module = nullptr; d3d11Module = GetModuleHandle(L"d3d11.dll"); if (Config::Instance()->OverlayMenu.value() && d3d11Module != nullptr) { LOG_DEBUG("d3d11.dll already in memory"); HooksDx::HookDx11(d3d11Module); } // DirectX 12 HMODULE d3d12Module = nullptr; d3d12Module = GetModuleHandle(L"d3d12.dll"); if (Config::Instance()->OverlayMenu.value() && d3d12Module != nullptr) { LOG_DEBUG("d3d12.dll already in memory"); HooksDx::HookDx12(d3d12Module); } // SpecialK if (!isWorkingWithEnabler && (Config::Instance()->FGType.value_or_default() != FGType::OptiFG || !Config::Instance()->OverlayMenu.value_or_default()) && skHandle == nullptr && Config::Instance()->LoadSpecialK.value_or_default()) { auto skFile = Util::DllPath().parent_path() / L"SpecialK64.dll"; SetEnvironmentVariableW(L"RESHADE_DISABLE_GRAPHICS_HOOK", L"1"); skHandle = LoadLibrary(skFile.c_str()); LOG_INFO("Loading SpecialK64.dll, result: {0:X}", (UINT64)skHandle); } // ReShade if (!isWorkingWithEnabler && reshadeHandle == nullptr && Config::Instance()->LoadReShade.value_or_default()) { auto rsFile = Util::DllPath().parent_path() / L"ReShade64.dll"; SetEnvironmentVariableW(L"RESHADE_DISABLE_LOADING_CHECK", L"1"); if (skHandle != nullptr) SetEnvironmentVariableW(L"RESHADE_DISABLE_GRAPHICS_HOOK", L"1"); reshadeHandle = LoadLibrary(rsFile.c_str()); LOG_INFO("Loading ReShade64.dll, result: {0:X}", (size_t)reshadeHandle); } // For FSR4 Upgrade mod_amdxc64 = GetModuleHandle(L"amdxc64.dll"); if (mod_amdxc64 == nullptr) mod_amdxc64 = LoadLibrary(L"amdxc64.dll"); if (mod_amdxc64 != nullptr) { LOG_DEBUG("Hooking amdxc64.dll"); o_AmdExtD3DCreateInterface = (PFN_AmdExtD3DCreateInterface)GetProcAddress(mod_amdxc64, "AmdExtD3DCreateInterface"); } } return; } LOG_ERROR("Unsupported dll name: {0}", filename); } static void CheckQuirks() { auto exePathFilename = Util::ExePath().filename(); LOG_INFO("Game's Exe: {0}", exePathFilename.string()); if (exePathFilename == "Cyberpunk2077.exe") { State::Instance().gameQuirk = Cyberpunk; // Disabled OptiFG for now if (Config::Instance()->FGType.value_or_default() == FGType::OptiFG) Config::Instance()->FGType.set_volatile_value(FGType::NoFG); //Config::Instance()->FGType.set_volatile_value(FGType::Nukems); LOG_INFO("Enabling a quirk for Cyberpunk (Disable FSR-FG Swapchain & enable DLSS-G fix)"); } else if (exePathFilename == "FMF2-Win64-Shipping.exe") { State::Instance().gameQuirk = FMF2; if (!Config::Instance()->Fsr3Inputs.has_value()) { Config::Instance()->Fsr3Inputs.set_volatile_value(false); LOG_INFO("Enabling a quirk for FMF2 (Disable FSR3 Hooks)"); } if (!Config::Instance()->Fsr3Pattern.has_value()) { Config::Instance()->Fsr3Pattern.set_volatile_value(false); LOG_INFO("Enabling a quirk for FMF2 (Disable FSR3 Pattern Hooks)"); } } else if (exePathFilename == "RDR.exe" || exePathFilename == "PlayRDR.exe") { State::Instance().gameQuirk = RDR1; if (Config::Instance()->FGType.value_or_default() == FGType::OptiFG) Config::Instance()->FGType.set_volatile_value(FGType::NoFG); LOG_INFO("Enabling a quirk for RDR1 (Disable FSR-FG Swapchain)"); } else if (exePathFilename == "Banishers-Win64-Shipping.exe") { State::Instance().gameQuirk = Banishers; if (!Config::Instance()->Fsr2Pattern.has_value()) { Config::Instance()->Fsr2Pattern.set_volatile_value(false); LOG_INFO("Enabling a quirk for Banishers (Disable FSR2 Inputs)"); } } else if (exePathFilename == "SplitFiction.exe") { State::Instance().gameQuirk = SplitFiction; LOG_INFO("Enabling a quirk for Split Fiction (Quick upscaler reinit)"); } } bool isNvidia() { bool nvidiaDetected = false; bool loadedHere = false; auto nvapiModule = GetModuleHandleW(L"nvapi64.dll"); // This is before attaching to LoadLibrary methods // No need to use .optidll extension if (!nvapiModule) { nvapiModule = LoadLibraryExW(L"nvapi64.dll", NULL, LOAD_LIBRARY_SEARCH_SYSTEM32); loadedHere = true; } // No nvapi, should not be nvidia if (!nvapiModule) { LOG_DEBUG("Detected: {}", nvidiaDetected); return nvidiaDetected; } if (auto o_NvAPI_QueryInterface = (PFN_NvApi_QueryInterface)GetProcAddress(nvapiModule, "nvapi_QueryInterface")) { // dxvk-nvapi calls CreateDxgiFactory which we can't do because we are inside DLL_PROCESS_ATTACH NvAPI_ShortString desc; auto* getVersion = GET_INTERFACE(NvAPI_GetInterfaceVersionString, o_NvAPI_QueryInterface); if (getVersion && getVersion(desc) == NVAPI_OK && (std::string_view(desc) == std::string_view("NVAPI Open Source Interface (DXVK-NVAPI)") || std::string_view(desc) == std::string_view("DXVK_NVAPI"))) { LOG_DEBUG("Using dxvk-nvapi"); DISPLAY_DEVICEA dd; dd.cb = sizeof(dd); int deviceIndex = 0; while (EnumDisplayDevicesA(nullptr, deviceIndex, &dd, 0)) { if (dd.StateFlags & DISPLAY_DEVICE_ACTIVE && std::string_view(dd.DeviceID).contains("VEN_10DE")) { // Having any Nvidia GPU active will take precedence nvidiaDetected = true; } deviceIndex++; } } else if (o_NvAPI_QueryInterface(GET_ID(Fake_InformFGState))) { // Check for fakenvapi in system32, assume it's not nvidia if found LOG_DEBUG("Using fakenvapi"); nvidiaDetected = false; } else { LOG_DEBUG("Using Nvidia's nvapi"); auto init = GET_INTERFACE(NvAPI_Initialize, o_NvAPI_QueryInterface); if (init && init() == NVAPI_OK) { nvidiaDetected = true; if (auto unload = GET_INTERFACE(NvAPI_Unload, o_NvAPI_QueryInterface)) unload(); } } } if (loadedHere) FreeLibrary(nvapiModule); LOG_DEBUG("Detected: {}", nvidiaDetected); return nvidiaDetected; } BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) { HMODULE handle = nullptr; switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: if (loadCount > 1) { LOG_INFO("DLL_PROCESS_ATTACH from module: {0:X}, count: {1}", (UINT64)hModule, loadCount); return TRUE; } dllModule = hModule; processId = GetCurrentProcessId(); DisableThreadLibraryCalls(hModule); if (Config::Instance()->FGType.value_or_default() == FGType::OptiFG && Config::Instance()->FGDisableOverlays.value_or_default()) SetEnvironmentVariable(L"SteamNoOverlayUIDrawing", L"1"); loadCount++; #ifdef VER_PRE_RELEASE // Enable file logging for pre builds Config::Instance()->LogToFile.set_volatile_value(true); // Set log level to debug if (Config::Instance()->LogLevel.value_or_default() > 1) Config::Instance()->LogLevel.set_volatile_value(1); #endif PrepareLogger(); spdlog::warn("{0} loaded", VER_PRODUCT_NAME); spdlog::warn("---------------------------------"); spdlog::warn("OptiScaler is freely downloadable from"); spdlog::warn("GitHub : https://github.com/cdozdil/OptiScaler/releases"); spdlog::warn("Nexus : https://www.nexusmods.com/site/mods/986"); spdlog::warn("If you paid for these files, you've been scammed!"); spdlog::warn("DO NOT USE IN MULTIPLAYER GAMES"); spdlog::warn(""); spdlog::warn("LogLevel: {0}", Config::Instance()->LogLevel.value_or_default()); // Check for Wine skipGetModuleHandle = true; spdlog::info(""); State::Instance().isRunningOnLinux = IsRunningOnWine(); State::Instance().isRunningOnDXVK = State::Instance().isRunningOnLinux; skipGetModuleHandle = false; // Temporary fix for Linux & DXVK if (State::Instance().isRunningOnDXVK || State::Instance().isRunningOnLinux) Config::Instance()->UseHQFont.set_volatile_value(false); spdlog::info(""); CheckQuirks(); // Check if real DLSS available if (Config::Instance()->DLSSEnabled.value_or_default()) { spdlog::info(""); State::Instance().isRunningOnNvidia = isNvidia(); if (State::Instance().isRunningOnNvidia) { spdlog::info("Running on Nvidia, setting DLSS as default upscaler and disabling spoofing options set to auto"); Config::Instance()->DLSSEnabled.set_volatile_value(true); if (!Config::Instance()->DxgiSpoofing.has_value()) Config::Instance()->DxgiSpoofing.set_volatile_value(false); isNvngxAvailable = true; } else { spdlog::info("Not running on Nvidia, disabling DLSS"); Config::Instance()->DLSSEnabled.set_volatile_value(false); } } if (!Config::Instance()->OverrideNvapiDll.has_value()) { spdlog::info("OverrideNvapiDll not set, setting it to: {}", !State::Instance().isRunningOnNvidia ? "true" : "false"); Config::Instance()->OverrideNvapiDll.set_volatile_value(!State::Instance().isRunningOnNvidia); } // Check for working mode and attach hooks spdlog::info(""); CheckWorkingMode(); spdlog::info(""); if (!State::Instance().nvngxExists && !Config::Instance()->DxgiSpoofing.has_value()) { LOG_WARN("No nvngx.dll found disabling spoofing!"); Config::Instance()->DxgiSpoofing.set_volatile_value(false); } spdlog::info(""); handle = GetModuleHandle(fsr2NamesW[0].c_str()); if (handle != nullptr) HookFSR2Inputs(handle); handle = GetModuleHandle(fsr2BENamesW[0].c_str()); if (handle != nullptr) HookFSR2Dx12Inputs(handle); spdlog::info(""); HookFSR2ExeInputs(); handle = GetModuleHandle(fsr3NamesW[0].c_str()); if (handle != nullptr) HookFSR3Inputs(handle); handle = GetModuleHandle(fsr3BENamesW[0].c_str()); if (handle != nullptr) HookFSR3Dx12Inputs(handle); HookFSR3ExeInputs(); //HookFfxExeInputs(); // Initial state of FSR-FG State::Instance().activeFgType = Config::Instance()->FGType.value_or_default(); for (size_t i = 0; i < 300; i++) { State::Instance().frameTimes.push_back(0.0f); State::Instance().upscaleTimes.push_back(0.0f); } spdlog::info(""); spdlog::info("Init done"); spdlog::info("---------------------------------------------"); spdlog::info(""); break; case DLL_PROCESS_DETACH: // Unhooking and cleaning stuff causing issues during shutdown. // Disabled for now to check if it cause any issues UnhookApis(); unhookStreamline(); unhookGdi32(); DetachHooks(); if (skHandle != nullptr) FreeLibrary(skHandle); if (reshadeHandle != nullptr) FreeLibrary(reshadeHandle); spdlog::info(""); spdlog::info("DLL_PROCESS_DETACH"); spdlog::info("Unloading OptiScaler"); CloseLogger(); break; case DLL_THREAD_ATTACH: LOG_DEBUG_ONLY("DLL_THREAD_ATTACH from module: {0:X}, count: {1}", (UINT64)hModule, loadCount); break; case DLL_THREAD_DETACH: LOG_DEBUG_ONLY("DLL_THREAD_DETACH from module: {0:X}, count: {1}", (UINT64)hModule, loadCount); break; default: LOG_WARN("Call reason: {0:X}", ul_reason_for_call); break; } return TRUE; }