diff --git a/rpcs3/Emu/Cell/lv2/sys_memory.cpp b/rpcs3/Emu/Cell/lv2/sys_memory.cpp index eb21fc873d..4c9e0e8c3e 100644 --- a/rpcs3/Emu/Cell/lv2/sys_memory.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_memory.cpp @@ -45,16 +45,24 @@ error_code sys_memory_allocate(u32 size, u64 flags, vm::ptr alloc_addr) return CELL_ENOMEM; } - if (!alloc_addr) + if (const auto area = vm::get(align == 0x10000 ? vm::user64k : vm::user1m, 0, ::align(size, 0x10000000))) { - dct->used -= size; - return CELL_EFAULT; + if (u32 addr = area->alloc(size, align)) + { + if (alloc_addr) + { + *alloc_addr = addr; + return CELL_OK; + } + + // Dealloc using the syscall + sys_memory_free(addr); + return CELL_EFAULT; + } } - // Allocate memory, write back the start address of the allocated area - *alloc_addr = verify(HERE, vm::alloc(size, align == 0x10000 ? vm::user64k : vm::user1m, align)); - - return CELL_OK; + dct->used -= size; + return CELL_ENOMEM; } error_code sys_memory_allocate_from_container(u32 size, u32 cid, u64 flags, vm::ptr alloc_addr) @@ -98,19 +106,28 @@ error_code sys_memory_allocate_from_container(u32 size, u32 cid, u64 flags, vm:: return ct.ret; } - if (!alloc_addr) - { - ct->used -= size; - return CELL_EFAULT; - } - // Create phantom memory object const auto mem = idm::make_ptr(size, align, flags, ct.ptr); - // Allocate memory - *alloc_addr = verify(HERE, vm::get(align == 0x10000 ? vm::user64k : vm::user1m)->alloc(size, mem->align, &mem->shm)); + if (const auto area = vm::get(align == 0x10000 ? vm::user64k : vm::user1m, 0, ::align(size, 0x10000000))) + { + if (u32 addr = area->alloc(size, mem->align, &mem->shm)) + { + if (alloc_addr) + { + *alloc_addr = addr; + return CELL_OK; + } - return CELL_OK; + // Dealloc using the syscall + sys_memory_free(addr); + return CELL_EFAULT; + } + } + + idm::remove(idm::last_id()); + ct->used -= size; + return CELL_ENOMEM; } error_code sys_memory_free(u32 addr) diff --git a/rpcs3/Emu/Memory/vm.cpp b/rpcs3/Emu/Memory/vm.cpp index 457f311f8a..8b2974915f 100644 --- a/rpcs3/Emu/Memory/vm.cpp +++ b/rpcs3/Emu/Memory/vm.cpp @@ -978,7 +978,7 @@ namespace vm return nullptr; } - std::shared_ptr get(memory_location_t location, u32 addr) + std::shared_ptr get(memory_location_t location, u32 addr, u32 area_size) { vm::reader_lock lock; @@ -989,7 +989,7 @@ namespace vm { auto& loc = g_locations[location]; - if (!loc) + if (!loc && area_size) { if (location == vm::user64k || location == vm::user1m) { @@ -998,7 +998,7 @@ namespace vm if (!loc) { // Deferred allocation - loc = _find_map(0x10000000, 0x10000000, location == vm::user64k ? 0x201 : 0x401); + loc = _find_map(area_size, 0x10000000, location == vm::user64k ? 0x201 : 0x401); } } } diff --git a/rpcs3/Emu/Memory/vm.h b/rpcs3/Emu/Memory/vm.h index 562ba25218..453a2e5d08 100644 --- a/rpcs3/Emu/Memory/vm.h +++ b/rpcs3/Emu/Memory/vm.h @@ -189,7 +189,7 @@ namespace vm std::shared_ptr unmap(u32 addr, bool must_be_empty = false); // Get memory block associated with optionally specified memory location or optionally specified address - std::shared_ptr get(memory_location_t location, u32 addr = 0); + std::shared_ptr get(memory_location_t location, u32 addr = 0, u32 area_size = 0); // Get PS3/PSV virtual memory address from the provided pointer (nullptr always converted to 0) inline vm::addr_t get_addr(const void* real_ptr)