diff --git a/Common/OSVersion.cpp b/Common/OSVersion.cpp index ee35ef7c4e..a69b8217c7 100644 --- a/Common/OSVersion.cpp +++ b/Common/OSVersion.cpp @@ -46,7 +46,7 @@ bool GetVersionFromKernel32(uint32_t &major, uint32_t &minor, uint32_t &build) { #endif } -bool DoesVersionMatchWindows(uint32_t major, uint32_t minor, uint32_t spMajor, uint32_t spMinor, bool greater) { +bool DoesVersionMatchWindows(uint32_t major, uint32_t minor, uint32_t spMajor, uint32_t spMinor, uint32_t build, bool greater) { #if !PPSSPP_PLATFORM(UWP) if (spMajor == 0 && spMinor == 0) { // "Applications not manifested for Windows 10 will return the Windows 8 OS version value (6.2)." @@ -55,7 +55,9 @@ bool DoesVersionMatchWindows(uint32_t major, uint32_t minor, uint32_t spMajor, u if (GetVersionFromKernel32(actualMajor, actualMinor, actualBuild)) { if (greater) return actualMajor > major || (major == actualMajor && actualMinor >= minor); - return major == actualMajor && minor == actualMinor; + + // To detect Windows 11 we must check build number + return major == actualMajor && minor == actualMinor && actualBuild >= build; } } @@ -86,59 +88,25 @@ bool DoesVersionMatchWindows(uint32_t major, uint32_t minor, uint32_t spMajor, u return VerifyVersionInfo(&osvi, typeMask, conditionMask) != FALSE; #else - if (greater) { + if (greater) return true; - } return false; #endif } -bool DoesVersionMatchWindows(WindowsReleaseInfo release) { - if (release.spMajor == 0 && release.spMinor == 0) { - // Compare Info - uint32_t major = release.major; - uint32_t minor = release.minor; - uint32_t build = release.build; - bool greater = release.greater; - - OSVERSIONINFOEX osvi; - ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX)); - osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); - GetVersionEx((LPOSVERSIONINFO)&osvi); - - // OS Info - uint32_t osMajor = osvi.dwMajorVersion; - uint32_t osMinor = osvi.dwMinorVersion; - uint32_t osBuild = osvi.dwBuildNumber; - -#if !PPSSPP_PLATFORM(UWP) - // "Applications not manifested for Windows 10 will return the Windows 8 OS version value (6.2)." - // Try to use kernel32.dll instead, for Windows 10+. - GetVersionFromKernel32(osMajor, osMinor, osBuild); -#endif - - if (major == osMajor) { - // To detect Windows 11 we must check build number - if (osMinor >= minor && osBuild >= build) { - return true; - } - } - } - else { - return DoesVersionMatchWindows(release.major, release.minor, release.spMajor, release.spMinor, release.greater); - } - - return false; -} - bool IsVistaOrHigher() { // Vista is 6.0 - return DoesVersionMatchWindows(6, 0, 0, 0, true); + return DoesVersionMatchWindows(6, 0, 0, 0, 0, true); } bool IsWin7OrHigher() { // Win7 is 6.1 - return DoesVersionMatchWindows(6, 1, 0, 0, true); + return DoesVersionMatchWindows(6, 1, 0, 0, 0, true); +} + +bool IsWin8OrHigher() { + // Win8 is 6.2 + return DoesVersionMatchWindows(6, 2, 0, 0, 0, true); } std::string GetWindowsVersion() { @@ -160,8 +128,7 @@ std::string GetWindowsVersion() { // Start from higher to lower for (auto release = rbegin(windowsReleases); release != rend(windowsReleases); ++release) { WindowsReleaseInfo releaseInfo = release->second; - bool buildMatch = DoesVersionMatchWindows(releaseInfo); - if (buildMatch) { + if (DoesVersionMatchWindows(releaseInfo.major, releaseInfo.minor, releaseInfo.spMajor, releaseInfo.spMinor, releaseInfo.build, releaseInfo.greater)) { std::string previewText = release->first; return previewText; } diff --git a/Common/OSVersion.h b/Common/OSVersion.h index 262cba05ac..c1704b85df 100644 --- a/Common/OSVersion.h +++ b/Common/OSVersion.h @@ -6,7 +6,10 @@ bool IsVistaOrHigher(); bool IsWin7OrHigher(); -bool DoesVersionMatchWindows(uint32_t major, uint32_t minor, uint32_t spMajor, uint32_t spMinor, bool acceptGreater); +bool IsWin8OrHigher(); +bool DoesVersionMatchWindows(uint32_t major, uint32_t minor, uint32_t spMajor, uint32_t spMinor, uint32_t build, bool acceptGreater); +bool GetVersionFromKernel32(uint32_t& major, uint32_t& minor, uint32_t& build); + std::string GetWindowsVersion(); std::string GetWindowsSystemArchitecture(); diff --git a/Common/System/System.h b/Common/System/System.h index b0f83d70bd..fdd7a81874 100644 --- a/Common/System/System.h +++ b/Common/System/System.h @@ -124,6 +124,7 @@ enum SystemKeyboardLayout { enum SystemProperty { SYSPROP_NAME, + SYSPROP_SYSTEMBUILD, SYSPROP_LANGREGION, SYSPROP_CPUINFO, SYSPROP_BOARDNAME, diff --git a/Core/Config.cpp b/Core/Config.cpp index 7a39fd081d..3c28b1e26e 100644 --- a/Core/Config.cpp +++ b/Core/Config.cpp @@ -423,7 +423,7 @@ static int DefaultGPUBackend() { #if PPSSPP_PLATFORM(WINDOWS) // If no Vulkan, use Direct3D 11 on Windows 8+ (most importantly 10.) - if (DoesVersionMatchWindows(6, 2, 0, 0, true)) { + if (IsWin8OrHigher()) { return (int)GPUBackend::DIRECT3D11; } #elif PPSSPP_PLATFORM(ANDROID) @@ -494,7 +494,7 @@ int Config::NextValidBackend() { } #endif #if PPSSPP_PLATFORM(WINDOWS) - if (!failed.count(GPUBackend::DIRECT3D11) && DoesVersionMatchWindows(6, 1, 0, 0, true)) { + if (!failed.count(GPUBackend::DIRECT3D11) && IsWin7OrHigher()) { return (int)GPUBackend::DIRECT3D11; } #endif @@ -541,7 +541,7 @@ bool Config::IsBackendEnabled(GPUBackend backend) { if (backend != GPUBackend::OPENGL) return false; #elif PPSSPP_PLATFORM(WINDOWS) - if (backend == GPUBackend::DIRECT3D11 && !DoesVersionMatchWindows(6, 0, 0, 0, true)) + if (backend == GPUBackend::DIRECT3D11 && !IsVistaOrHigher()) return false; #else if (backend == GPUBackend::DIRECT3D11 || backend == GPUBackend::DIRECT3D9) diff --git a/UI/DevScreens.cpp b/UI/DevScreens.cpp index 56cda92067..53300d3d74 100644 --- a/UI/DevScreens.cpp +++ b/UI/DevScreens.cpp @@ -489,6 +489,11 @@ void SystemInfoScreen::CreateTabs() { systemInfo->Add(new InfoItem(si->T("System Name", "Name"), System_GetProperty(SYSPROP_NAME))); #if PPSSPP_PLATFORM(ANDROID) systemInfo->Add(new InfoItem(si->T("System Version"), StringFromInt(System_GetPropertyInt(SYSPROP_SYSTEMVERSION)))); +#elif PPSSPP_PLATFORM(WINDOWS) + std::string sysVersion = System_GetProperty(SYSPROP_SYSTEMBUILD); + if (!sysVersion.empty()) { + systemInfo->Add(new InfoItem(si->T("OS Build"), sysVersion)); + } #endif systemInfo->Add(new InfoItem(si->T("Lang/Region"), System_GetProperty(SYSPROP_LANGREGION))); std::string board = System_GetProperty(SYSPROP_BOARDNAME); diff --git a/UWP/PPSSPP_UWPMain.cpp b/UWP/PPSSPP_UWPMain.cpp index 719d342821..140d0948fd 100644 --- a/UWP/PPSSPP_UWPMain.cpp +++ b/UWP/PPSSPP_UWPMain.cpp @@ -24,7 +24,6 @@ #include "Common/System/Display.h" #include "Common/System/NativeApp.h" #include "Common/System/Request.h" -#include "Common/OSVersion.h" #include "Core/System.h" #include "Core/Loaders.h" @@ -314,7 +313,9 @@ std::string System_GetProperty(SystemProperty prop) { static bool hasCheckedGPUDriverVersion = false; switch (prop) { case SYSPROP_NAME: - return GetWindowsVersion(); + return GetSystemName(); + case SYSPROP_SYSTEMBUILD: + return GetWindowsBuild(); case SYSPROP_LANGREGION: return GetLangRegion(); case SYSPROP_CLIPBOARD_TEXT: diff --git a/UWP/UWPHelpers/InputHelpers.cpp b/UWP/UWPHelpers/InputHelpers.cpp index 485998a044..441b731094 100644 --- a/UWP/UWPHelpers/InputHelpers.cpp +++ b/UWP/UWPHelpers/InputHelpers.cpp @@ -21,6 +21,7 @@ #include "UWPUtil.h" #include "NKCodeFromWindowsSystem.h" #include "Common/Log.h" +#include "Common/OSVersion.h" #include #include @@ -238,4 +239,40 @@ bool IsMobile() { auto deviceInfo = Windows::System::Profile::AnalyticsInfo::VersionInfo; return deviceInfo->DeviceFamily == "Windows.Mobile"; } + +void GetVersionInfo(uint32_t& major, uint32_t& minor, uint32_t& build, uint32_t& revision) { + Platform::String^ deviceFamilyVersion = Windows::System::Profile::AnalyticsInfo::VersionInfo->DeviceFamilyVersion; + uint64_t version = std::stoull(deviceFamilyVersion->Data()); + + major = static_cast((version & 0xFFFF000000000000L) >> 48); + minor = static_cast((version & 0x0000FFFF00000000L) >> 32); + build = static_cast((version & 0x00000000FFFF0000L) >> 16); + revision = static_cast(version & 0x000000000000FFFFL); +} + +std::string GetSystemName() { + std::string osName = "Microsoft Windows 10"; + + if (IsXBox()) { + osName = "Xbox OS"; + } + else { + uint32_t major = 0, minor = 0, build = 0, revision = 0; + GetVersionInfo(major, minor, build, revision); + + if (build >= 22000) { + osName = "Microsoft Windows 11"; + } + } + return osName + " " + GetWindowsSystemArchitecture(); +} + +std::string GetWindowsBuild() { + uint32_t major = 0, minor = 0, build = 0, revision = 0; + GetVersionInfo(major, minor, build, revision); + + char buffer[50]; + sprintf_s(buffer, sizeof(buffer), "%u.%u.%u (rev. %u)", major, minor, build, revision); + return std::string(buffer); +} #pragma endregion diff --git a/UWP/UWPHelpers/InputHelpers.h b/UWP/UWPHelpers/InputHelpers.h index d5656e81fc..7bcfb4931c 100644 --- a/UWP/UWPHelpers/InputHelpers.h +++ b/UWP/UWPHelpers/InputHelpers.h @@ -47,3 +47,10 @@ bool IsCtrlOnHold(); std::string GetLangRegion(); bool IsXBox(); bool IsMobile(); + +// Get major, minor, build, revision +void GetVersionInfo(uint32_t& major, uint32_t& minor, uint32_t& build, uint32_t& revision); + +// Get formatted windows info as string (for preview) +std::string GetSystemName(); +std::string GetWindowsBuild(); diff --git a/Windows/MainWindow.cpp b/Windows/MainWindow.cpp index 8921e9c985..09857e31d2 100644 --- a/Windows/MainWindow.cpp +++ b/Windows/MainWindow.cpp @@ -765,7 +765,7 @@ namespace MainWindow switch (message) { case WM_CREATE: - if (!DoesVersionMatchWindows(6, 0, 0, 0, true)) { + if (!IsVistaOrHigher()) { // Remove the D3D11 choice on versions below XP RemoveMenu(GetMenu(hWnd), ID_OPTIONS_DIRECT3D11, MF_BYCOMMAND); } diff --git a/Windows/main.cpp b/Windows/main.cpp index bd763a0908..cfd7d987e9 100644 --- a/Windows/main.cpp +++ b/Windows/main.cpp @@ -106,6 +106,7 @@ CVFPUDlg *vfpudlg = nullptr; static std::string langRegion; static std::string osName; +static std::string osVersion; static std::string gpuDriverVersion; static std::string restartArgs; @@ -203,6 +204,8 @@ std::string System_GetProperty(SystemProperty prop) { switch (prop) { case SYSPROP_NAME: return osName; + case SYSPROP_SYSTEMBUILD: + return osVersion; case SYSPROP_LANGREGION: return langRegion; case SYSPROP_CLIPBOARD_TEXT: @@ -905,6 +908,13 @@ int WINAPI WinMain(HINSTANCE _hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLin langRegion = GetDefaultLangRegion(); osName = GetWindowsVersion() + " " + GetWindowsSystemArchitecture(); + // OS Build + uint32_t outMajor = 0, outMinor = 0, outBuild = 0; + if (GetVersionFromKernel32(outMajor, outMinor, outBuild)) { + // Builds with (service pack) don't show OS Build for now + osVersion = std::to_string(outMajor) + "." + std::to_string(outMinor) + "." + std::to_string(outBuild); + } + std::string configFilename = ""; const std::wstring configOption = L"--config=";