From ee2bc97248f460670e982f7966a70c092c896676 Mon Sep 17 00:00:00 2001 From: Stephen Miller <56742918+StevenMiller123@users.noreply.github.com> Date: Mon, 10 Nov 2025 09:07:17 -0600 Subject: [PATCH 1/5] Windows: Limit address space maximum when higher addresses are not needed (#3775) * Earlier initialization of elf info. Everything used for elf info initialization comes from the param.sfo, so we can initialize this earlier to have this information accessible during memory init. * Extract compiled SDK version from pubtoolinfo string Up until now, we've been using the game's reported "firmware version" as our compiled SDK version. This behavior is inaccurate, and is something that has come up in my hardware tests before. For the actual compiled SDK version, we should use the SDK version in the PUBTOOLINFO string of the param.sfo, only falling back on the firmware version when that the sdk_ver component isn't present. * Store compiled SDK version in ElfInfo * Limit address space for compiled SDK version at or above FW 3 Sony placed a hard cap at 0xfc00000000, with a slight extension for stack mappings. For now, though stack mappings aren't implemented, there's no harm in keeping a slightly extended address space (since this cap is lower than our old user max). Limiting the max through address space is necessary for Windows due to performance issues, in the future I plan to properly implement checks in memory manager code to properly handle this behavior for all platforms. * Use compiled SDK version for sceKernelGetCompiledSdkVersion I think this is pretty self explanatory. * Log SDK version Since this value is what most internal firmware version checks are against, logging the value will help with debugging. * Update address_space.cpp * Update emulator.cpp * Backwards compatible logging Because that's apparently an issue now --- src/common/elf_info.h | 6 +++ src/core/address_space.cpp | 25 ++++++++---- src/core/libraries/kernel/process.cpp | 2 +- src/emulator.cpp | 58 +++++++++++++++++++-------- 4 files changed, 66 insertions(+), 25 deletions(-) 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); From bbd985fe4b771c2f24d8d05a9dc3b43cd5f50f00 Mon Sep 17 00:00:00 2001 From: Missake Date: Tue, 11 Nov 2025 16:56:03 +0100 Subject: [PATCH 2/5] Update building-windows.md (#3792) --- documents/building-windows.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/documents/building-windows.md b/documents/building-windows.md index aa7213abc..d1f8a6895 100644 --- a/documents/building-windows.md +++ b/documents/building-windows.md @@ -36,9 +36,8 @@ Go through the Git for Windows installation as normal 1. Open up Visual Studio, select `Open a local folder` and select the folder with the shadPS4 source code. The folder should contain `CMakeLists.txt` 2. Change Clang x64 Debug to Clang x64 Release if you want a regular, non-debug build. -3. If you want to build shadPS4 with the Qt Gui, simply select Clang x64 Release with Qt instead. -4. Change the project to build to shadps4.exe -5. Build -> Build All +3. Change the project to build to shadps4.exe +4. Build -> Build All Your shadps4.exe will be in `C:\path\to\source\Build\x64-Clang-Release\` From 25344a3b89207b5bd9f6e530654191e4cdb55aa8 Mon Sep 17 00:00:00 2001 From: Joshua de Reeper Date: Wed, 12 Nov 2025 11:40:39 +0100 Subject: [PATCH 3/5] calloc UsbDevice instead of pointer (#3790) --- src/core/libraries/usbd/usb_backend.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/libraries/usbd/usb_backend.h b/src/core/libraries/usbd/usb_backend.h index 7a5c2899a..505f825ab 100644 --- a/src/core/libraries/usbd/usb_backend.h +++ b/src/core/libraries/usbd/usb_backend.h @@ -366,7 +366,7 @@ public: const auto desc = FillDeviceDescriptor(); ASSERT(desc); - const auto fake = static_cast(calloc(1, sizeof(UsbDevice*))); + const auto fake = static_cast(calloc(1, sizeof(UsbDevice))); fake->bus_number = 0; fake->port_number = 0; fake->device_address = 0; From 93c340c6e1804ad167b4cd9f61ce5912277c8281 Mon Sep 17 00:00:00 2001 From: Stephen Miller <56742918+StevenMiller123@users.noreply.github.com> Date: Wed, 12 Nov 2025 09:26:26 -0600 Subject: [PATCH 4/5] calloc libusb_interface instead of pointer (#3793) interface->num_altsetting is oob --- src/core/libraries/usbd/usb_backend.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/libraries/usbd/usb_backend.h b/src/core/libraries/usbd/usb_backend.h index 505f825ab..e668d5509 100644 --- a/src/core/libraries/usbd/usb_backend.h +++ b/src/core/libraries/usbd/usb_backend.h @@ -312,7 +312,7 @@ public: const auto endpoint_descs = FillEndpointDescriptorPair(); const auto interface_desc = FillInterfaceDescriptor(endpoint_descs); - const auto interface = static_cast(calloc(1, sizeof(libusb_interface*))); + const auto interface = static_cast(calloc(1, sizeof(libusb_interface))); interface->altsetting = interface_desc; interface->num_altsetting = 1; From f557c6ac645337feb898b8174aff7a7e6f03c03e Mon Sep 17 00:00:00 2001 From: kalaposfos13 <153381648+kalaposfos13@users.noreply.github.com> Date: Fri, 14 Nov 2025 20:47:16 +0100 Subject: [PATCH 5/5] Update MoltenVK to the shadPS4 fork (#3797) --- .gitmodules | 2 +- externals/MoltenVK | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitmodules b/.gitmodules index 38aed89a0..43ba2a7c1 100644 --- a/.gitmodules +++ b/.gitmodules @@ -108,7 +108,7 @@ branch = dist [submodule "externals/MoltenVK"] path = externals/MoltenVK - url = https://github.com/KhronosGroup/MoltenVK.git + url = https://github.com/shadPS4-emu/ext-MoltenVK.git shallow = true [submodule "externals/json"] path = externals/json diff --git a/externals/MoltenVK b/externals/MoltenVK index b23d42534..f168dec05 160000 --- a/externals/MoltenVK +++ b/externals/MoltenVK @@ -1 +1 @@ -Subproject commit b23d42534622cd9926fe526fec1b7f8795a2853c +Subproject commit f168dec05998ab0ca09a400bab6831a95c0bdb2e