diff --git a/src/common/elf_info.h b/src/common/elf_info.h index 2f2f150b2..0b2589e95 100644 --- a/src/common/elf_info.h +++ b/src/common/elf_info.h @@ -68,6 +68,7 @@ class ElfInfo { std::string app_ver{}; u32 firmware_ver = 0; u32 raw_firmware_ver = 0; + u32 sdk_ver = 0; PSFAttributes psf_attributes{}; std::filesystem::path splash_path{}; @@ -117,6 +118,11 @@ public: return raw_firmware_ver; } + [[nodiscard]] u32 CompiledSdkVer() const { + ASSERT(initialized); + return sdk_ver; + } + [[nodiscard]] const PSFAttributes& GetPSFAttributes() const { ASSERT(initialized); return psf_attributes; diff --git a/src/core/address_space.cpp b/src/core/address_space.cpp index 3f2d94cbf..3f063ea76 100644 --- a/src/core/address_space.cpp +++ b/src/core/address_space.cpp @@ -6,6 +6,7 @@ #include "common/arch.h" #include "common/assert.h" #include "common/config.h" +#include "common/elf_info.h" #include "common/error.h" #include "core/address_space.h" #include "core/libraries/kernel/memory.h" @@ -103,8 +104,8 @@ struct AddressSpace::Impl { GetSystemInfo(&sys_info); u64 alignment = sys_info.dwAllocationGranularity; - // Determine the host OS build number - // Retrieve module handle for ntdll + // Older Windows builds have a severe performance issue with VirtualAlloc2. + // We need to get the host's Windows version, then determine if it needs a workaround. auto ntdll_handle = GetModuleHandleW(L"ntdll.dll"); ASSERT_MSG(ntdll_handle, "Failed to retrieve ntdll handle"); @@ -120,12 +121,20 @@ struct AddressSpace::Impl { u64 supported_user_max = USER_MAX; // This is the build number for Windows 11 22H2 static constexpr s32 AffectedBuildNumber = 22621; - if (os_version_info.dwBuildNumber <= AffectedBuildNumber) { - // Older Windows builds have an issue with VirtualAlloc2 on higher addresses. - // To prevent regressions, limit the maximum address we reserve for this platform. - supported_user_max = 0x11000000000ULL; - LOG_WARNING(Core, "Windows 10 detected, reducing user max to {:#x} to avoid problems", - supported_user_max); + + // Higher PS4 firmware versions prevent higher address mappings too. + s32 sdk_ver = Common::ElfInfo::Instance().CompiledSdkVer(); + if (os_version_info.dwBuildNumber <= AffectedBuildNumber || + sdk_ver >= Common::ElfInfo::FW_30) { + supported_user_max = 0x10000000000ULL; + // Only log the message if we're restricting the user max due to operating system. + // Since higher compiled SDK versions also get reduced max, we don't need to log there. + if (sdk_ver < Common::ElfInfo::FW_30) { + LOG_WARNING( + Core, + "Older Windows version detected, reducing user max to {:#x} to avoid problems", + supported_user_max); + } } // Determine the free address ranges we can access. diff --git a/src/core/libraries/kernel/process.cpp b/src/core/libraries/kernel/process.cpp index 8220e55d8..02da041c3 100644 --- a/src/core/libraries/kernel/process.cpp +++ b/src/core/libraries/kernel/process.cpp @@ -36,7 +36,7 @@ s32 PS4_SYSV_ABI sceKernelGetMainSocId() { } s32 PS4_SYSV_ABI sceKernelGetCompiledSdkVersion(s32* ver) { - s32 version = Common::ElfInfo::Instance().RawFirmwareVer(); + s32 version = Common::ElfInfo::Instance().CompiledSdkVer(); *ver = version; return (version >= 0) ? ORBIS_OK : ORBIS_KERNEL_ERROR_EINVAL; } diff --git a/src/emulator.cpp b/src/emulator.cpp index 0e7485b89..ad407f9b6 100644 --- a/src/emulator.cpp +++ b/src/emulator.cpp @@ -113,6 +113,7 @@ void Emulator::Run(std::filesystem::path file, std::vector args, std::string id; std::string title; std::string app_version; + u32 sdk_version; u32 fw_version; Common::PSFAttributes psf_attributes{}; if (param_sfo_exists) { @@ -132,8 +133,48 @@ void Emulator::Run(std::filesystem::path file, std::vector args, if (const auto raw_attributes = param_sfo->GetInteger("ATTRIBUTE")) { psf_attributes.raw = *raw_attributes; } + + // Extract sdk version from pubtool info. + std::string_view pubtool_info = + param_sfo->GetString("PUBTOOLINFO").value_or("Unknown value"); + u64 sdk_ver_offset = pubtool_info.find("sdk_ver"); + + if (sdk_ver_offset == pubtool_info.npos) { + // Default to using firmware version if SDK version is not found. + sdk_version = fw_version; + } else { + // Increment offset to account for sdk_ver= part of string. + sdk_ver_offset += 8; + u64 sdk_ver_len = pubtool_info.find(",", sdk_ver_offset); + if (sdk_ver_len == pubtool_info.npos) { + // If there's no more commas, this is likely the last entry of pubtool info. + // Use string length instead. + sdk_ver_len = pubtool_info.size(); + } + sdk_ver_len -= sdk_ver_offset; + std::string sdk_ver_string = pubtool_info.substr(sdk_ver_offset, sdk_ver_len).data(); + // Number is stored in base 16. + sdk_version = std::stoi(sdk_ver_string, nullptr, 16); + } } + auto& game_info = Common::ElfInfo::Instance(); + game_info.initialized = true; + game_info.game_serial = id; + game_info.title = title; + game_info.app_ver = app_version; + game_info.firmware_ver = fw_version & 0xFFF00000; + game_info.raw_firmware_ver = fw_version; + game_info.sdk_ver = sdk_version; + game_info.psf_attributes = psf_attributes; + + const auto pic1_path = mnt->GetHostPath("/app0/sce_sys/pic1.png"); + if (std::filesystem::exists(pic1_path)) { + game_info.splash_path = pic1_path; + } + + game_info.game_folder = game_folder; + Config::load(Common::FS::GetUserPath(Common::FS::PathType::CustomConfigs) / (id + ".toml"), true); @@ -196,6 +237,7 @@ void Emulator::Run(std::filesystem::path file, std::vector args, if (param_sfo_exists) { LOG_INFO(Loader, "Game id: {} Title: {}", id, title); LOG_INFO(Loader, "Fw: {:#x} App Version: {}", fw_version, app_version); + LOG_INFO(Loader, "Compiled SDK version: {:#x}", sdk_version); LOG_INFO(Loader, "PSVR Supported: {}", (bool)psf_attributes.support_ps_vr.Value()); LOG_INFO(Loader, "PSVR Required: {}", (bool)psf_attributes.require_ps_vr.Value()); } @@ -235,22 +277,6 @@ void Emulator::Run(std::filesystem::path file, std::vector args, } } - auto& game_info = Common::ElfInfo::Instance(); - game_info.initialized = true; - game_info.game_serial = id; - game_info.title = title; - game_info.app_ver = app_version; - game_info.firmware_ver = fw_version & 0xFFF00000; - game_info.raw_firmware_ver = fw_version; - game_info.psf_attributes = psf_attributes; - - const auto pic1_path = mnt->GetHostPath("/app0/sce_sys/pic1.png"); - if (std::filesystem::exists(pic1_path)) { - game_info.splash_path = pic1_path; - } - - game_info.game_folder = game_folder; - std::string game_title = fmt::format("{} - {} <{}>", id, title, app_version); std::string window_title = ""; std::string remote_url(Common::g_scm_remote_url);