From d0c6998b00a7e5f07296c08be4b2d0cfe96a8b5f Mon Sep 17 00:00:00 2001 From: The412Banner Date: Sat, 26 Sep 2026 16:41:04 -0400 Subject: [PATCH] shadPS4: relocate fixed mappings beyond a 39-bit address space Need for Speed Hot Pursuit Remastered (and EA's engine generally) maps 'EAOSGlobal' fixed at 0xfbffffc000, the top of the PS4 user area. On a 39-bit Android kernel the ARM64 core's user area ends at 0x3fffffffff, so MapMemory asserted ("Attempted to access invalid address"). Place such a mapping at the top of the range the device has instead and log the move; the game receives the new address through out_addr. Experimental: it only helps if the game uses the returned address rather than a hard-coded one. --- ...relocate-out-of-range-fixed-mappings.patch | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 tools/shadps4/patches/0003-relocate-out-of-range-fixed-mappings.patch diff --git a/tools/shadps4/patches/0003-relocate-out-of-range-fixed-mappings.patch b/tools/shadps4/patches/0003-relocate-out-of-range-fixed-mappings.patch new file mode 100644 index 000000000..b0dcf453c --- /dev/null +++ b/tools/shadps4/patches/0003-relocate-out-of-range-fixed-mappings.patch @@ -0,0 +1,35 @@ +diff --git a/src/core/memory.cpp b/src/core/memory.cpp +index 7e17cdc..26cac97 100644 +--- a/src/core/memory.cpp ++++ b/src/core/memory.cpp +@@ -550,6 +550,30 @@ s32 MemoryManager::MapMemory(void** out_addr, VAddr virtual_addr, u64 size, Memo + } + } + ++ // A 39-bit Android address space ends far below the top of the PS4's user area, where some ++ // engines ask for fixed mappings (EA's 'EAOSGlobal' at 0xfbffffc000). Place such a mapping at ++ // the top of the range this device has instead of asserting; the caller gets the new address. ++ if (True(flags & MemoryMapFlags::Fixed) && !IsValidMapping(virtual_addr, size)) { ++ const VAddr requested = virtual_addr; ++ const u64 align = alignment > 16_KB ? alignment : 16_KB; ++ const VAddr top = impl.UserVirtualBase() + impl.UserVirtualSize(); ++ VAddr candidate = Common::AlignDown(top - size, align); ++ const auto it = FindVMA(candidate); ++ if (it == vma_map.end() || !it->second.IsFree() || !it->second.Contains(candidate, size)) { ++ candidate = SearchFree(DEFAULT_MAPPING_BASE, size, static_cast(align)); ++ } ++ if (candidate == static_cast(-1)) { ++ LOG_ERROR(Kernel_Vmm, "No room to relocate fixed mapping {:#x} ({:#x} bytes)", ++ requested, size); ++ return ORBIS_KERNEL_ERROR_ENOMEM; ++ } ++ LOG_WARNING(Kernel_Vmm, ++ "Fixed mapping {:#x} ({:#x} bytes, '{}') is outside this device's address " ++ "space; relocated to {:#x}", ++ requested, size, name, candidate); ++ virtual_addr = candidate; ++ } ++ + if (True(flags & MemoryMapFlags::Fixed) && True(flags & MemoryMapFlags::NoOverwrite)) { + // Perform necessary error checking for Fixed & NoOverwrite case + ASSERT_MSG(IsValidMapping(virtual_addr, size), "Attempted to access invalid address {:#x}",