diff --git a/source-code/dependencies/GPUModel/GPUModel.h b/source-code/dependencies/GPUModel/GPUModel.h new file mode 100644 index 0000000..7fb6157 --- /dev/null +++ b/source-code/dependencies/GPUModel/GPUModel.h @@ -0,0 +1,58 @@ +/* +Simple header for detecting Nvidia GPU models +*/ + +namespace GPUModel +{ + #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers + #include + #include + + void*(*NvAPI_QueryInterface)(unsigned int offset) = NULL; + int(*NvAPI_Initialize)() = NULL; + int(*NvAPI_Unload)() = NULL; + int(*NvAPI_EnumPhysicalGPUs)(int64_t** handle, int* count) = NULL; + int(*NvAPI_GPU_GetShortName)(int64_t* handle, char* name) = NULL; + + std::string getGpuName() + { + NvAPI_QueryInterface = (void*(*)(unsigned int offset))GetProcAddress(LoadLibraryW(L"nvapi64.dll"), "nvapi_QueryInterface"); + + if (NvAPI_QueryInterface == nullptr) + { + return "Other"; + } + + NvAPI_Initialize = (int(*)())NvAPI_QueryInterface(0x0150E828); + NvAPI_Unload = (int(*)()) NvAPI_QueryInterface(0xD22BDD7E); + NvAPI_EnumPhysicalGPUs = (int(*)(int64_t** handle, int* count))NvAPI_QueryInterface(0xE5AC921F); + NvAPI_GPU_GetShortName = (int(*)(int64_t* handle, char* name))NvAPI_QueryInterface(0xD988F0F3); + + if (NvAPI_Initialize == nullptr || + NvAPI_Unload == nullptr || + NvAPI_EnumPhysicalGPUs == nullptr || + NvAPI_GPU_GetShortName == nullptr) + { + return "Unknown"; + } + + int64_t* hdlGpu[64] = { 0 }; + int nGpu = 0; + + NvAPI_Initialize(); + NvAPI_EnumPhysicalGPUs(hdlGpu, &nGpu); + + //printf("[ShaderPatch] nGpu: %d\n", nGpu); + if (nGpu < 1) + { + NvAPI_Unload(); + return "Unknown"; + } + + char nameBuf[64]; + NvAPI_GPU_GetShortName(hdlGpu[0], nameBuf); + NvAPI_Unload(); + + return std::string(nameBuf); + } +} \ No newline at end of file diff --git a/source-code/dependencies/PluginConfigApi/PluginConfigApi.h b/source-code/dependencies/PluginConfigApi/PluginConfigApi.h index bb39dca..7c1f0e2 100644 --- a/source-code/dependencies/PluginConfigApi/PluginConfigApi.h +++ b/source-code/dependencies/PluginConfigApi/PluginConfigApi.h @@ -1,3 +1,7 @@ +/* +PD Loader Launcher Plugin Information Structs +*/ + #pragma once #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers #include diff --git a/source-code/source/plugins/Launcher/Launcher.vcxproj b/source-code/source/plugins/Launcher/Launcher.vcxproj index fef5717..a430bf6 100644 --- a/source-code/source/plugins/Launcher/Launcher.vcxproj +++ b/source-code/source/plugins/Launcher/Launcher.vcxproj @@ -111,7 +111,7 @@ Level3 Disabled _DEBUG;%(PreprocessorDefinitions) - ..\..\..\dependencies\PluginConfigApi;..\..\..\dependencies\detours\include;..\..\..\dependencies\freeglut\include;%(AdditionalIncludeDirectories) + ..\..\..\dependencies\GPUModel;..\..\..\dependencies\PluginConfigApi;..\..\..\dependencies\detours\include;..\..\..\dependencies\freeglut\include;%(AdditionalIncludeDirectories) stdcpp17 @@ -142,7 +142,7 @@ Level3 NDEBUG;%(PreprocessorDefinitions) - ..\..\..\dependencies\PluginConfigApi;..\..\..\dependencies\detours\include;..\..\..\dependencies\freeglut\include;%(AdditionalIncludeDirectories) + ..\..\..\dependencies\GPUModel;..\..\..\dependencies\PluginConfigApi;..\..\..\dependencies\detours\include;..\..\..\dependencies\freeglut\include;%(AdditionalIncludeDirectories) stdcpp17 diff --git a/source-code/source/plugins/Launcher/ui.h b/source-code/source/plugins/Launcher/ui.h index 79ef930..58d27ce 100644 --- a/source-code/source/plugins/Launcher/ui.h +++ b/source-code/source/plugins/Launcher/ui.h @@ -7,6 +7,7 @@ #include #include "SkinnedMessageBox.h" #include "PluginConfig.h" +#include "GPUModel.h"" namespace Launcher { @@ -151,30 +152,76 @@ namespace Launcher { int window = glutCreateWindow("glut"); // a context must be created to use glGetString String^ vendor = gcnew String((char*)glGetString(GL_VENDOR)); + vendor = vendor->Replace(" Corporation", ""); // this is useless.. remove it to help ensure the GPU type line fits String^ renderer = gcnew String((char*)glGetString(GL_RENDERER)); String^ version = gcnew String((char*)glGetString(GL_VERSION)); + String^ gpuModel = gcnew String(GPUModel::getGpuName().c_str()); + glutDestroyWindow(window); // destroy the window so it doesn't remain on screen if (glutMainLoopEventDynamic != NULL) glutMainLoopEventDynamic(); // freeglut needs this - this->labelGPU->Text = "Vendor: " + vendor + "\nRenderer: " + renderer + "\nOpenGL: " + version; - if (!vendor->Contains("NVIDIA")) + this->labelGPU->Text = "GPU Info:\n"; + this->labelGPU->Text += vendor + " " + renderer + "\n"; + this->labelGPU->Text += "OpenGL: " + version + "\n"; + + int linkStart = this->labelGPU->Text->Length; + if (!vendor->Contains("NVIDIA")) // check OpenGL renderer to get actual GPU being used for vendor check (ensure not running on iGPU) { - this->labelGPU->Text += "\nIssues: NVIDIA GPU REQUIRED!"; - this->labelGPU->ForeColor = System::Drawing::Color::Red; - SkinnedMessageBox::Show(this, "Your graphics card is not supported! Only NVIDIA GPUs are currently supported.", "PD Launcher", MessageBoxButtons::OK, MessageBoxIcon::Warning); + this->labelGPU->Text += "Issues: NVIDIA GPU REQUIRED!"; + GPUIssueText = "Your graphics card is not supported! Only NVIDIA GPUs can run the game.\nPlease use a GTX 600 series or later GPU.\n\nIf you have a laptop with an NVIDIA GPU, you may need to set diva.exe to use it in NVIDIA Control Panel."; + this->labelGPU->LinkColor = System::Drawing::Color::Red; + SkinnedMessageBox::Show(this, GPUIssueText, "PD Launcher", MessageBoxButtons::OK, MessageBoxIcon::Warning); } - else if (version[0] < '4') + else if (gpuModel->StartsWith("TU")) { - this->labelGPU->Text += "\nIssues: GPU too old! 3D rendering might be broken."; - this->labelGPU->ForeColor = System::Drawing::Color::Orange; + this->labelGPU->Text += "Issues: Turing GPU detected! Possible noise.\n(Click for more information)"; + GPUIssueText = "On Turing GPUs (GTX 16xx/RTX 20xx), some important character shaders have issues resulting in lines/noise.\nPlease make sure the ShaderPatch plugin is enabled."; + this->labelGPU->LinkColor = System::Drawing::Color::Yellow; } - else if (renderer->Contains("RTX") || renderer->Contains("GTX 16")) + else if (gpuModel->StartsWith("GM") || gpuModel->StartsWith("GP") || gpuModel->StartsWith("GV")) { - this->labelGPU->Text += "\nIssues: Turing GPU detected! Possible noise."; - this->labelGPU->ForeColor = System::Drawing::Color::Yellow; + this->labelGPU->Text += "Issues: May have minor noise on some stages.\n(Click for more information)"; + GPUIssueText = "On Maxwell GPUs (~GTX 900) or newer, some minor stage shaders create noise.\nPlease make sure the ShaderPatch plugin is enabled."; + this->labelGPU->LinkColor = System::Drawing::Color::Yellow; } - else this->labelGPU->Text += "\nIssues: None."; + else if (gpuModel->StartsWith("GF") || gpuModel->StartsWith("GK")) + { + if (version[0] < '4') + { + this->labelGPU->Text += "Issues: Driver too old."; + GPUIssueText = "Your GPU should have no issues running the game, but it looks like your OpenGL version is too old.\nA driver update should fix this."; + this->labelGPU->LinkColor = System::Drawing::Color::Orange; + } + else + { + this->labelGPU->Text += "Issues: None."; + GPUIssueText = "Your GPU should have no issues running the game."; + this->labelGPU->LinkColor = System::Drawing::Color::Lime; + } + } + else if (version[0] >= '4' && gpuModel->Length > 0 && !gpuModel->StartsWith("Unk") && !gpuModel->StartsWith("Oth")) + { + this->labelGPU->Text += "Issues: GPU may be too new.\n(Click for more information)"; + GPUIssueText = "It looks like your GPU may be too new. Only up to Turing (GTX 16xx/RTX 20xx) is currently supported.\nGood news: the game should be capable of running, but shader patches (probably needed) may not support it yet.\nYou will likely see lines/noise on important character shaders and some minor stage shaders.\nPlease report any issues so that ShaderPatch can be updated."; + this->labelGPU->LinkColor = System::Drawing::Color::Orange; + } + else if (gpuModel->StartsWith("G") || gpuModel->StartsWith("NV") || gpuModel->StartsWith("NB") || gpuModel->StartsWith("N10") || gpuModel->StartsWith("MCP")) + { + this->labelGPU->Text += "Issues: GPU too old! 3D rendering might be broken.\n(Click for more information)"; + GPUIssueText = "Your GPU is very old and does not support rendering techniques used by the game.\nYou may be able to play, but graphics will likely have major issues.\nPlease upgrade to a GTX 600 series or later GPU."; + this->labelGPU->LinkColor = System::Drawing::Color::Orange; + } + else //if (gpuModel->Length == 0 || gpuModel->StartsWith("Unk") || gpuModel->StartsWith("Oth")) + { + this->labelGPU->Text += "Issues: Unable to detect GPU architecture.\n(Click for more information)"; + GPUIssueText = "It looks like you have an NVIDIA GPU, but something went wrong while trying to determine your GPU's architecture (type).\nThis may be a caused by a bug, but it probably indicates potential issues.\nPlease make sure you have a GTX 600 series or later GPU. (GTX 400 series or later should also work)"; + this->labelGPU->LinkColor = System::Drawing::Color::Orange; + } + int linkEnd = this->labelGPU->Text->Length - linkStart; + + this->labelGPU->LinkClicked += gcnew System::Windows::Forms::LinkLabelLinkClickedEventHandler(this, &ui::LinkLabelLinkClickedGPUIssueHandler); + this->labelGPU->LinkArea = System::Windows::Forms::LinkArea(linkStart, linkEnd); } protected: @@ -207,7 +254,7 @@ namespace Launcher { private: System::Windows::Forms::ToolTip^ toolTip1; private: System::Windows::Forms::Panel^ panel_ScreenRes; private: System::Windows::Forms::Panel^ panel_IntRes; - private: System::Windows::Forms::Label^ labelGPU; + private: System::Windows::Forms::LinkLabel^ labelGPU; private: System::Windows::Forms::Button^ button_Apply; @@ -246,7 +293,7 @@ namespace Launcher { this->panel_ScreenRes = (gcnew System::Windows::Forms::Panel()); this->tabControl = (gcnew System::Windows::Forms::TabControl()); this->tabPage_Resolution = (gcnew System::Windows::Forms::TabPage()); - this->labelGPU = (gcnew System::Windows::Forms::Label()); + this->labelGPU = (gcnew System::Windows::Forms::LinkLabel()); this->groupBox_InternalRes = (gcnew System::Windows::Forms::GroupBox()); this->panel_IntRes = (gcnew System::Windows::Forms::Panel()); this->tabPage_Patches = (gcnew System::Windows::Forms::TabPage()); @@ -353,8 +400,9 @@ namespace Launcher { // labelGPU // this->labelGPU->AutoSize = true; - this->labelGPU->ForeColor = System::Drawing::Color::Lime; - this->labelGPU->Location = System::Drawing::Point(12, 319); + this->labelGPU->BackColor = System::Drawing::Color::FromArgb(static_cast(static_cast(80)), static_cast(static_cast(24)), + static_cast(static_cast(24)), static_cast(static_cast(24)));; + this->labelGPU->Location = System::Drawing::Point(12, 314); this->labelGPU->MinimumSize = System::Drawing::Size(410, 20); this->labelGPU->Name = L"labelGPU"; this->labelGPU->Size = System::Drawing::Size(410, 20); @@ -728,5 +776,10 @@ private: bool AnyConfigChanged() { return false; } + +private: String^ GPUIssueText; +private: System::Void LinkLabelLinkClickedGPUIssueHandler(System::Object^ sender, System::Windows::Forms::LinkLabelLinkClickedEventArgs^ e) { + SkinnedMessageBox::Show(this, GPUIssueText, "PD Launcher", MessageBoxButtons::OK, MessageBoxIcon::Warning); +} }; } diff --git a/source-code/source/plugins/ShaderPatch/ShaderPatch.vcxproj b/source-code/source/plugins/ShaderPatch/ShaderPatch.vcxproj index b015031..442f3fe 100644 --- a/source-code/source/plugins/ShaderPatch/ShaderPatch.vcxproj +++ b/source-code/source/plugins/ShaderPatch/ShaderPatch.vcxproj @@ -86,7 +86,7 @@ Level3 Disabled true - ..\..\..\dependencies\detours\include;..\..\..\dependencies\PluginConfigApi + ..\..\..\dependencies\GPUModel;..\..\..\dependencies\detours\include;..\..\..\dependencies\PluginConfigApi ..\..\..\dependencies\detours\lib @@ -112,7 +112,7 @@ true true true - ..\..\..\dependencies\detours\include;..\..\..\dependencies\PluginConfigApi + ..\..\..\dependencies\GPUModel;..\..\..\dependencies\detours\include;..\..\..\dependencies\PluginConfigApi true diff --git a/source-code/source/plugins/ShaderPatch/src/dllmain.cpp b/source-code/source/plugins/ShaderPatch/src/dllmain.cpp index a86d1c8..ff325e6 100644 --- a/source-code/source/plugins/ShaderPatch/src/dllmain.cpp +++ b/source-code/source/plugins/ShaderPatch/src/dllmain.cpp @@ -3,6 +3,7 @@ #include "framework.h" #include "PluginConfigApi.h" +#include "GPUModel.h" #include "detours.h" #pragma comment(lib, "detours.lib") @@ -29,51 +30,7 @@ void NopBytes(void* address, unsigned int num) } -void loadGpuName() -{ - NvAPI_QueryInterface = (void*(*)(unsigned int offset))GetProcAddress(LoadLibrary("nvapi64.dll"), "nvapi_QueryInterface"); - if (NvAPI_QueryInterface == nullptr) - { - gpuName = "Other"; - return; - } - - NvAPI_Initialize = (int(*)())NvAPI_QueryInterface(0x0150E828); - NvAPI_Unload = (int(*)()) NvAPI_QueryInterface(0xD22BDD7E); - NvAPI_EnumPhysicalGPUs = (int(*)(int64_t** handle, int* count))NvAPI_QueryInterface(0xE5AC921F); - NvAPI_GPU_GetShortName = (int(*)(int64_t* handle, char* name))NvAPI_QueryInterface(0xD988F0F3); - - if (NvAPI_Initialize == nullptr || - NvAPI_Unload == nullptr || - NvAPI_EnumPhysicalGPUs == nullptr || - NvAPI_GPU_GetShortName == nullptr) - { - gpuName = "Unknown"; - return; - } - - int64_t* hdlGpu[64] = { 0 }; - int nGpu = 0; - - NvAPI_Initialize(); - NvAPI_EnumPhysicalGPUs(hdlGpu, &nGpu); - - //printf("[ShaderPatch] nGpu: %d\n", nGpu); - if (nGpu < 1) - { - gpuName = "Unknown"; - NvAPI_Unload(); - return; - } - - char nameBuf[64]; - NvAPI_GPU_GetShortName(hdlGpu[0], nameBuf); - NvAPI_Unload(); - - gpuName = nameBuf; - return; -} void LoadConfig() @@ -283,7 +240,7 @@ BOOL APIENTRY DllMain(HMODULE hModule, DetourAttach(&(PVOID&)loadFromFarcThunk, (PVOID)hookedLoadFromFarcThunk); DetourTransactionCommit(); - loadGpuName(); + gpuName = GPUModel::getGpuName(); printf("[ShaderPatch] Detected GPU: %s\n", gpuName.c_str()); //Sleep(2000); diff --git a/source-code/source/plugins/ShaderPatch/src/framework.h b/source-code/source/plugins/ShaderPatch/src/framework.h index 3f38996..379072f 100644 --- a/source-code/source/plugins/ShaderPatch/src/framework.h +++ b/source-code/source/plugins/ShaderPatch/src/framework.h @@ -54,15 +54,7 @@ struct FArchivedFile { void (__stdcall* loadFromFarcThunk)(FArchivedFile** file) = (void(__stdcall*)(FArchivedFile** file))0x1405e5991; - std::string gpuName; -void*(*NvAPI_QueryInterface)(unsigned int offset) = NULL; -int(*NvAPI_Initialize)() = NULL; -int(*NvAPI_Unload)() = NULL; -int(*NvAPI_EnumPhysicalGPUs)(int64_t** handle, int* count) = NULL; -int(*NvAPI_GPU_GetShortName)(int64_t* handle, char* name) = NULL; - - std::vector SplitString(const std::string& str, const std::string& delim) {