Emulate memory behavior of libSceGnmDriver initialization (#2807)

* Emulate memory behavior of libSceGnmDriver _DT_INIT

Due to the unique way some games check for sceKernelAllocateDirectMemory failures, emulating this properly is necessary.

* Clang

* Fix address input for direct memory call

* Fix bug with DirectQueryAvailable

Missed this in my prior PR.

* DirectQueryAvailable fix

Fixes error cases to be more hardware accurate.
This commit is contained in:
Stephen Miller 2025-04-18 15:41:33 -05:00 committed by GitHub
parent 23c616c647
commit 0feb2e7211
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 16 additions and 10 deletions

View file

@ -2804,7 +2804,7 @@ void RegisterlibSceGnmDriver(Core::Loader::SymbolsResolver* sym) {
liverpool = std::make_unique<AmdGpu::Liverpool>();
presenter = std::make_unique<Vulkan::Presenter>(*g_window, liverpool.get());
const int result = sceKernelGetCompiledSdkVersion(&sdk_version);
const s32 result = sceKernelGetCompiledSdkVersion(&sdk_version);
if (result != ORBIS_OK) {
sdk_version = 0;
}

View file

@ -106,12 +106,6 @@ s32 PS4_SYSV_ABI sceKernelAvailableDirectMemorySize(u64 searchStart, u64 searchE
if (physAddrOut == nullptr || sizeOut == nullptr) {
return ORBIS_KERNEL_ERROR_EINVAL;
}
if (searchEnd > sceKernelGetDirectMemorySize()) {
return ORBIS_KERNEL_ERROR_EINVAL;
}
if (searchEnd <= searchStart) {
return ORBIS_KERNEL_ERROR_ENOMEM;
}
auto* memory = Core::Memory::Instance();

View file

@ -108,10 +108,22 @@ void Linker::Execute(const std::vector<std::string> args) {
static constexpr s64 InternalMemorySize = 0x1000000;
void* addr_out{reinterpret_cast<void*>(KernelAllocBase)};
const s32 ret = Libraries::Kernel::sceKernelMapNamedFlexibleMemory(
&addr_out, InternalMemorySize, 3, 0, "SceKernelInternalMemory");
s32 ret = Libraries::Kernel::sceKernelMapNamedFlexibleMemory(&addr_out, InternalMemorySize, 3,
0, "SceKernelInternalMemory");
ASSERT_MSG(ret == 0, "Unable to perform sceKernelInternalMemory mapping");
// Simulate libSceGnmDriver initialization, which maps a chunk of direct memory.
// Some games fail without accurately emulating this behavior.
s64 phys_addr{};
ret = Libraries::Kernel::sceKernelAllocateDirectMemory(
0, Libraries::Kernel::sceKernelGetDirectMemorySize(), 0x10000, 0x10000, 3, &phys_addr);
if (ret == 0) {
void* addr{reinterpret_cast<void*>(0xfe0000000)};
ret = Libraries::Kernel::sceKernelMapNamedDirectMemory(&addr, 0x10000, 0x13, 0, phys_addr,
0x10000, "SceGnmDriver");
}
ASSERT_MSG(ret == 0, "Unable to emulate libSceGnmDriver initialization");
main_thread.Run([this, module, args](std::stop_token) {
Common::SetCurrentThreadName("GAME_MainThread");
LoadSharedLibraries();

View file

@ -655,7 +655,7 @@ int MemoryManager::DirectQueryAvailable(PAddr search_start, PAddr search_end, si
if (dmem_area->second.GetEnd() > search_end) {
// We need to trim remaining_size to ignore addresses beyond search_end
remaining_size = remaining_size > (search_start - dmem_area->second.base)
remaining_size = remaining_size > (dmem_area->second.GetEnd() - search_end)
? remaining_size - (dmem_area->second.GetEnd() - search_end)
: 0;
}