From c4a9c874d197a42ed99a520c6b0a3834fec7c282 Mon Sep 17 00:00:00 2001 From: Hykem Date: Sat, 15 Mar 2014 19:45:43 +0000 Subject: [PATCH] Improved FRES and FRSQRTE results (tested with ppu_fpu). Implemented and improved several SC_Memory syscalls. Started working in sceNp module. --- rpcs3/Emu/Cell/PPUInterpreter.h | 60 +-- rpcs3/Emu/SysCalls/Modules/sceNp.cpp | 34 ++ rpcs3/Emu/SysCalls/Modules/sysPrxForUser.cpp | 2 + rpcs3/Emu/SysCalls/SysCalls.cpp | 29 +- rpcs3/Emu/SysCalls/SysCalls.h | 19 +- rpcs3/Emu/SysCalls/lv2/SC_Memory.cpp | 513 ++++++++++++++----- rpcs3/Emu/SysCalls/lv2/SC_Memory.h | 120 +++-- 7 files changed, 517 insertions(+), 260 deletions(-) diff --git a/rpcs3/Emu/Cell/PPUInterpreter.h b/rpcs3/Emu/Cell/PPUInterpreter.h index 5ebb8a36f4..4baa3ec1bf 100644 --- a/rpcs3/Emu/Cell/PPUInterpreter.h +++ b/rpcs3/Emu/Cell/PPUInterpreter.h @@ -3404,62 +3404,11 @@ private: } void FRES(u32 frd, u32 frb, bool rc) { - double res; - -#ifdef _MSC_VER - if(_fpclass(CPU.FPR[frb]) >= _FPCLASS_NZ) -#else - if(_fpclass(CPU.FPR[frb]) == FP_ZERO || std::signbit(CPU.FPR[frb]) == 0) -#endif - { - res = static_cast(1.0 / CPU.FPR[frb]); - if(FPRdouble::IsINF(res) && CPU.FPR[frb] != 0.0) - { - if(res > 0.0) - { - (u64&)res = 0x47EFFFFFE0000000ULL; - } - else - { - (u64&)res = 0xC7EFFFFFE0000000ULL; - } - } - } - else - { - u64 v = CPU.FPR[frb]; - - if(v == 0ULL) - { - v = 0x7FF0000000000000ULL; - } - else if(v == 0x8000000000000000ULL) - { - v = 0xFFF0000000000000ULL; - } - else if(FPRdouble::IsNaN(CPU.FPR[frb])) - { - v = 0x7FF8000000000000ULL; - } - else if(CPU.FPR[frb] < 0.0) - { - v = 0x8000000000000000ULL; - } - else - { - v = 0ULL; - } - - res = (double&)v; - } - if(CPU.FPR[frb] == 0.0) { CPU.SetFPSCRException(FPSCR_ZX); } - - CPU.FPR[frd] = res; - + CPU.FPR[frd] = static_cast(1.0 / CPU.FPR[frb]); if(rc) UNK("fres.");//CPU.UpdateCR1(CPU.FPR[frd]); } void FMULS(u32 frd, u32 fra, u32 frc, bool rc) @@ -3790,7 +3739,12 @@ private: } void FRSQRTE(u32 frd, u32 frb, bool rc) { - CPU.FPR[frd] = 1.0f / (float)sqrt(CPU.FPR[frb]); + if(CPU.FPR[frb] == 0.0) + { + CPU.SetFPSCRException(FPSCR_ZX); + } + CPU.FPR[frd] = static_cast(1.0 / sqrt(CPU.FPR[frb])); + if(rc) UNK("frsqrte.");//CPU.UpdateCR1(CPU.FPR[frd]); } void FMSUB(u32 frd, u32 fra, u32 frc, u32 frb, bool rc) { diff --git a/rpcs3/Emu/SysCalls/Modules/sceNp.cpp b/rpcs3/Emu/SysCalls/Modules/sceNp.cpp index 3732beb5f1..e024f0712e 100644 --- a/rpcs3/Emu/SysCalls/Modules/sceNp.cpp +++ b/rpcs3/Emu/SysCalls/Modules/sceNp.cpp @@ -7,6 +7,37 @@ void sceNp_init(); Module sceNp(0x0016, sceNp_init); +int sceNpInit(u32 mem_size, u32 mem_addr) +{ + sceNp.Log("sceNpInit(mem_size=0x%x, mem_addr=0x%x)", mem_size, mem_addr); + return CELL_OK; +} + +int sceNpTerm() +{ + sceNp.Log("sceNpTerm"); + return CELL_OK; +} + +int sceNpDrmIsAvailable(u32 k_licensee_addr, u32 drm_path_addr) +{ + sceNp.Warning("sceNpDrmIsAvailable(k_licensee_addr=0x%x, drm_path_addr=0x%x)", k_licensee_addr, drm_path_addr); + + wxString k_licensee_str; + wxString drm_path = Memory.ReadString(drm_path_addr); + u8 k_licensee[0x10]; + for(int i = 0; i < 0x10; i++) + { + k_licensee[i] = Memory.Read8(k_licensee_addr + i); + k_licensee_str += wxString::Format("%02x", k_licensee[i]); + } + + sceNp.Warning("sceNpDrmIsAvailable: Found DRM license file at %s", drm_path.c_str()); + sceNp.Warning("sceNpDrmIsAvailable: Using k_licensee 0x%s", k_licensee_str); + + return CELL_OK; +} + int sceNpManagerGetStatus(mem32_t status) { sceNp.Log("sceNpManagerGetStatus(status_addr=0x%x)", status.GetAddr()); @@ -22,5 +53,8 @@ int sceNpManagerGetStatus(mem32_t status) void sceNp_init() { + sceNp.AddFunc(0xbd28fdbf, sceNpInit); + sceNp.AddFunc(0x4885aa18, sceNpTerm); + sceNp.AddFunc(0xad218faf, sceNpDrmIsAvailable); sceNp.AddFunc(0xa7bff757, sceNpManagerGetStatus); } diff --git a/rpcs3/Emu/SysCalls/Modules/sysPrxForUser.cpp b/rpcs3/Emu/SysCalls/Modules/sysPrxForUser.cpp index 945e925063..ca91624905 100644 --- a/rpcs3/Emu/SysCalls/Modules/sysPrxForUser.cpp +++ b/rpcs3/Emu/SysCalls/Modules/sysPrxForUser.cpp @@ -167,7 +167,9 @@ void sysPrxForUser_init() sysPrxForUser.AddFunc(0x44265c08, _sys_heap_memalign); sysPrxForUser.AddFunc(0xb257540b, sys_mmapper_allocate_memory); + sysPrxForUser.AddFunc(0x70258515, sys_mmapper_allocate_memory_from_container); sysPrxForUser.AddFunc(0xdc578057, sys_mmapper_map_memory); + sysPrxForUser.AddFunc(0x4643ba6e, sys_mmapper_unmap_memory); sysPrxForUser.AddFunc(0x409ad939, sys_mmapper_free_memory); sysPrxForUser.AddFunc(0x1ed454ce, sys_spu_elf_get_information); diff --git a/rpcs3/Emu/SysCalls/SysCalls.cpp b/rpcs3/Emu/SysCalls/SysCalls.cpp index aad96f9329..f6903a3115 100644 --- a/rpcs3/Emu/SysCalls/SysCalls.cpp +++ b/rpcs3/Emu/SysCalls/SysCalls.cpp @@ -148,13 +148,28 @@ static func_caller* sc_table[1024] = bind_func(sys_vm_get_statistics), //312 (0x138) null_func, null_func, //314 null_func, null_func, null_func, null_func, null_func, //319 - null_func, null_func, null_func, null_func, bind_func(sys_memory_container_create), //324 - bind_func(sys_memory_container_destroy), null_func, null_func, null_func, null_func, //329 - bind_func(sys_mmapper_allocate_address), null_func, null_func, null_func, null_func, //334 - null_func, null_func, null_func, null_func, null_func, //339 - null_func, bind_func(sys_memory_container_create), bind_func(sys_memory_container_destroy), null_func, null_func, //344 - null_func, null_func, null_func, bind_func(sys_memory_allocate), bind_func(sys_memory_free), //349 - null_func, bind_func(sys_memory_get_page_attribute), bind_func(sys_memory_get_user_memory_size), null_func, null_func, //354 + null_func, null_func, null_func, null_func, //323 + bind_func(sys_memory_container_create), //324 + bind_func(sys_memory_container_destroy), //325 + bind_func(sys_mmapper_allocate_fixed_address), //326 + bind_func(sys_mmapper_enable_page_fault_notification), //327 + null_func, null_func, //329 + bind_func(sys_mmapper_allocate_address), //330 + bind_func(sys_mmapper_free_address), //331 + null_func, null_func, null_func, null_func, //335 + bind_func(sys_mmapper_change_address_access_right), //336 + bind_func(sys_mmapper_search_and_map), //337 + null_func, null_func, null_func, //340 + bind_func(sys_memory_container_create), //341 + bind_func(sys_memory_container_destroy), //342 + bind_func(sys_memory_container_get_size), //343 + null_func, null_func, null_func, null_func, //347 + bind_func(sys_memory_allocate), //348 + bind_func(sys_memory_free), //349 + bind_func(sys_memory_allocate_from_container), //350 + bind_func(sys_memory_get_page_attribute), //351 + bind_func(sys_memory_get_user_memory_size), //352 + null_func, null_func, //354 null_func, null_func, null_func, null_func, null_func, //359 null_func, null_func, null_func, null_func, null_func, //364 null_func, null_func, null_func, null_func, null_func, //369 diff --git a/rpcs3/Emu/SysCalls/SysCalls.h b/rpcs3/Emu/SysCalls/SysCalls.h index 0b06490c51..64c6646f1b 100644 --- a/rpcs3/Emu/SysCalls/SysCalls.h +++ b/rpcs3/Emu/SysCalls/SysCalls.h @@ -223,16 +223,25 @@ extern void sys_ppu_thread_once(u32 once_ctrl_addr, u32 entry); extern int sys_ppu_thread_get_id(const u32 id_addr); //memory +extern int sys_memory_allocate(u32 size, u32 flags, u32 alloc_addr_addr); +extern int sys_memory_allocate_from_container(u32 size, u32 cid, u32 flags, u32 alloc_addr_addr); +extern int sys_memory_free(u32 start_addr); +extern int sys_memory_get_page_attribute(u32 addr, mem_ptr_t attr); +extern int sys_memory_get_user_memory_size(u32 mem_info_addr); extern int sys_memory_container_create(mem32_t cid, u32 yield_size); extern int sys_memory_container_destroy(u32 cid); -extern int sys_memory_allocate(u32 size, u32 flags, u32 alloc_addr_addr); -extern int sys_memory_free(u32 start_addr); -extern int sys_memory_get_user_memory_size(u32 mem_info_addr); -extern int sys_memory_get_page_attribute(u32 addr, mem_ptr_t a); +extern int sys_memory_container_get_size(u32 mem_info_addr, u32 cid); extern int sys_mmapper_allocate_address(u32 size, u64 flags, u32 alignment, u32 alloc_addr); +extern int sys_mmapper_allocate_fixed_address(); extern int sys_mmapper_allocate_memory(u32 size, u64 flags, mem32_t mem_id); -extern int sys_mmapper_map_memory(u32 start_addr, u32 mem_id, u64 flags); +extern int sys_mmapper_allocate_memory_from_container(u32 size, u32 cid, u64 flags, mem32_t mem_id); +extern int sys_mmapper_change_address_access_right(u32 start_addr, u64 flags); +extern int sys_mmapper_free_address(u32 start_addr); extern int sys_mmapper_free_memory(u32 mem_id); +extern int sys_mmapper_map_memory(u32 start_addr, u32 mem_id, u64 flags); +extern int sys_mmapper_search_and_map(u32 start_addr, u32 mem_id, u64 flags, u32 alloc_addr); +extern int sys_mmapper_unmap_memory(u32 start_addr, u32 mem_id_addr); +extern int sys_mmapper_enable_page_fault_notification(u32 start_addr, u32 q_id); //vm extern int sys_vm_memory_map(u32 vsize, u32 psize, u32 cid, u64 flag, u64 policy, u32 addr); diff --git a/rpcs3/Emu/SysCalls/lv2/SC_Memory.cpp b/rpcs3/Emu/SysCalls/lv2/SC_Memory.cpp index 5c4f5b9761..09e297ab27 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_Memory.cpp +++ b/rpcs3/Emu/SysCalls/lv2/SC_Memory.cpp @@ -3,50 +3,13 @@ #include "SC_Memory.h" SysCallBase sc_mem("memory"); - -int sys_memory_container_create(mem32_t cid, u32 yield_size) -{ - sc_mem.Warning("sys_memory_container_create(cid_addr=0x%x, yield_size=0x%x)", cid.GetAddr(), yield_size); - - if (!cid.IsGood()) - { - return CELL_EFAULT; - } - - yield_size &= ~0xfffff; //round down to 1 MB granularity - - u64 addr = Memory.Alloc(yield_size, 0x100000); //1 MB alignment - - if(!addr) - { - return CELL_ENOMEM; - } - - cid = sc_mem.GetNewId(new MemoryContainerInfo(addr, yield_size)); - sc_mem.Warning("*** memory_container created(addr=0x%llx): id = %d", addr, cid.GetValue()); - return CELL_OK; -} - -int sys_memory_container_destroy(u32 cid) -{ - sc_mem.Warning("sys_memory_container_destroy(cid=%d)", cid); - - MemoryContainerInfo* ct; - - if(!sc_mem.CheckId(cid, ct)) - { - return CELL_ESRCH; - } - - Memory.Free(ct->addr); - Emu.GetIdManager().RemoveID(cid); - return CELL_OK; -} +std::map mmapper_info_map; int sys_memory_allocate(u32 size, u32 flags, u32 alloc_addr_addr) { - //0x30000100; sc_mem.Log("sys_memory_allocate(size=0x%x, flags=0x%x)", size, flags); + + // Check page size. u32 addr; switch(flags) { @@ -63,119 +26,64 @@ int sys_memory_allocate(u32 size, u32 flags, u32 alloc_addr_addr) default: return CELL_EINVAL; } - if(!addr) return CELL_ENOMEM; + if(!addr) + return CELL_ENOMEM; + + // Write back the start address of the allocated area. sc_mem.Log("Memory allocated! [addr: 0x%x, size: 0x%x]", addr, size); Memory.Write32(alloc_addr_addr, addr); return CELL_OK; } +int sys_memory_allocate_from_container(u32 size, u32 cid, u32 flags, u32 alloc_addr_addr) +{ + sc_mem.Log("sys_memory_allocate_from_container(size=0x%x, cid=0x%x, flags=0x%x)", size, cid, flags); + + // Check if this container ID is valid. + MemoryContainerInfo* ct; + if(!sc_mem.CheckId(cid, ct)) + return CELL_ESRCH; + + // Check page size. + switch(flags) + { + case SYS_MEMORY_PAGE_SIZE_1M: + if(size & 0xfffff) return CELL_EALIGN; + ct->addr = Memory.Alloc(size, 0x100000); + break; + + case SYS_MEMORY_PAGE_SIZE_64K: + if(size & 0xffff) return CELL_EALIGN; + ct->addr = Memory.Alloc(size, 0x10000); + break; + + default: return CELL_EINVAL; + } + + // Store the address and size in the container. + if(!ct->addr) + return CELL_ENOMEM; + ct->size = size; + + // Write back the start address of the allocated area. + sc_mem.Log("Memory allocated! [addr: 0x%x, size: 0x%x]", ct->addr, ct->size); + Memory.Write32(alloc_addr_addr, ct->addr); + + return CELL_OK; +} + int sys_memory_free(u32 start_addr) { sc_mem.Log("sys_memory_free(start_addr=0x%x)", start_addr); - if(!Memory.Free(start_addr)) return CELL_EFAULT; + // Release the allocated memory. + if(!Memory.Free(start_addr)) + return CELL_EFAULT; return CELL_OK; } -int sys_mmapper_allocate_address(u32 size, u64 flags, u32 alignment, u32 alloc_addr) -{ - sc_mem.Warning("sys_mmapper_allocate_address(size=0x%x, flags=0x%llx, alignment=0x%x, alloc_addr=0x%x)", size, flags, alignment, alloc_addr); - - if(!Memory.IsGoodAddr(alloc_addr)) return CELL_EFAULT; - - if(!alignment) - alignment = 1; - - u32 addr; - - switch(flags & (SYS_MEMORY_PAGE_SIZE_1M | SYS_MEMORY_PAGE_SIZE_64K)) - { - default: - case SYS_MEMORY_PAGE_SIZE_1M: - if(Memory.AlignAddr(size, alignment) & 0xfffff) return CELL_EALIGN; - addr = Memory.Alloc(size, 0x100000); - break; - - case SYS_MEMORY_PAGE_SIZE_64K: - if(Memory.AlignAddr(size, alignment) & 0xffff) return CELL_EALIGN; - addr = Memory.Alloc(size, 0x10000); - break; - } - - Memory.Write32(alloc_addr, addr); - - return CELL_OK; -} - -int sys_mmapper_allocate_memory(u32 size, u64 flags, mem32_t mem_id) -{ - sc_mem.Warning("sys_mmapper_allocate_memory(size=0x%x, flags=0x%llx, mem_id_addr=0x%x)", size, flags, mem_id.GetAddr()); - - if(!mem_id.IsGood()) return CELL_EFAULT; - - u32 addr; - switch(flags & (SYS_MEMORY_PAGE_SIZE_1M | SYS_MEMORY_PAGE_SIZE_64K)) - { - case SYS_MEMORY_PAGE_SIZE_1M: - if(size & 0xfffff) return CELL_EALIGN; - addr = Memory.Alloc(size, 0x100000); - break; - - case SYS_MEMORY_PAGE_SIZE_64K: - if(size & 0xffff) return CELL_EALIGN; - addr = Memory.Alloc(size, 0x10000); - break; - - default: - return CELL_EINVAL; - } - - if(!addr) - return CELL_ENOMEM; - - mem_id = sc_mem.GetNewId(new mmapper_info(addr, size, flags)); - - return CELL_OK; -} - -int sys_mmapper_map_memory(u32 start_addr, u32 mem_id, u64 flags) -{ - sc_mem.Warning("sys_mmapper_map_memory(start_addr=0x%x, mem_id=0x%x, flags=0x%llx)", start_addr, mem_id, flags); - - mmapper_info* info; - if(!sc_mem.CheckId(mem_id, info)) return CELL_ESRCH; - - if(!Memory.Map(start_addr, info->addr, info->size)) - { - sc_mem.Error("sys_mmapper_map_memory failed!"); - } - - return CELL_OK; -} - -int sys_mmapper_free_memory(u32 mem_id) -{ - sc_mem.Warning("sys_mmapper_free_memory(mem_id=0x%x)", mem_id); - - mmapper_info* info; - if(!sc_mem.CheckId(mem_id, info)) return CELL_ESRCH; - - Memory.Free(info->addr); - return CELL_OK; -} - -int sys_memory_get_user_memory_size(u32 mem_info_addr) -{ - sc_mem.Warning("sys_memory_get_user_memory_size(mem_info_addr=0x%x)", mem_info_addr); - sys_memory_info info; - info.total_user_memory = re(Memory.GetUserMemTotalSize()); - info.available_user_memory = re(Memory.GetUserMemAvailSize()); - Memory.WriteData(mem_info_addr, info); - return CELL_OK; -} - int sys_memory_get_page_attribute(u32 addr, mem_ptr_t attr) { sc_mem.Warning("sys_memory_get_page_attribute(addr=0x%x, attr_addr=0x%x)", addr, attr.GetAddr()); @@ -183,10 +91,335 @@ int sys_memory_get_page_attribute(u32 addr, mem_ptr_t attr) if (!attr.IsGood()) return CELL_EFAULT; + // TODO: Implement per thread page attribute setting. attr->attribute = 0; attr->page_size = 0; attr->access_right = 0; attr->pad = 0; return CELL_OK; -} \ No newline at end of file +} + +int sys_memory_get_user_memory_size(u32 mem_info_addr) +{ + sc_mem.Warning("sys_memory_get_user_memory_size(mem_info_addr=0x%x)", mem_info_addr); + + // Fetch the user memory available. + sys_memory_info info; + info.total_user_memory = re(Memory.GetUserMemTotalSize()); + info.available_user_memory = re(Memory.GetUserMemAvailSize()); + + Memory.WriteData(mem_info_addr, info); + + return CELL_OK; +} + +int sys_memory_container_create(mem32_t cid, u32 yield_size) +{ + sc_mem.Warning("sys_memory_container_create(cid_addr=0x%x, yield_size=0x%x)", cid.GetAddr(), yield_size); + + if (!cid.IsGood()) + return CELL_EFAULT; + + yield_size &= ~0xfffff; //round down to 1 MB granularity + u64 addr = Memory.Alloc(yield_size, 0x100000); //1 MB alignment + + if(!addr) + return CELL_ENOMEM; + + // Wrap the allocated memory in a memory container. + MemoryContainerInfo *ct = new MemoryContainerInfo(addr, yield_size); + cid = sc_mem.GetNewId(ct); + + sc_mem.Warning("*** memory_container created(addr=0x%llx): id = %d", addr, cid.GetValue()); + + return CELL_OK; +} + +int sys_memory_container_destroy(u32 cid) +{ + sc_mem.Warning("sys_memory_container_destroy(cid=%d)", cid); + + // Check if this container ID is valid. + MemoryContainerInfo* ct; + if(!sc_mem.CheckId(cid, ct)) + return CELL_ESRCH; + + // Release the allocated memory and remove the ID. + Memory.Free(ct->addr); + Emu.GetIdManager().RemoveID(cid); + + return CELL_OK; +} + +int sys_memory_container_get_size(u32 mem_info_addr, u32 cid) +{ + sc_mem.Warning("sys_memory_container_get_size(mem_info_addr=0x%x, cid=%d)", mem_info_addr, cid); + + // Check if this container ID is valid. + MemoryContainerInfo* ct; + if(!sc_mem.CheckId(cid, ct)) + return CELL_ESRCH; + + // HACK: Return all memory. + sys_memory_info info; + info.total_user_memory = re(ct->size); + info.available_user_memory = re(ct->size); + + Memory.WriteData(mem_info_addr, info); + + return CELL_OK; +} + +int sys_mmapper_allocate_address(u32 size, u64 flags, u32 alignment, u32 alloc_addr) +{ + sc_mem.Warning("sys_mmapper_allocate_address(size=0x%x, flags=0x%llx, alignment=0x%x, alloc_addr=0x%x)", + size, flags, alignment, alloc_addr); + + if(!Memory.IsGoodAddr(alloc_addr)) + return CELL_EFAULT; + + // Check for valid alignment. + if(alignment > 0x80000000) + return CELL_EALIGN; + + // Check page size. + u32 addr; + switch(flags & (SYS_MEMORY_PAGE_SIZE_1M | SYS_MEMORY_PAGE_SIZE_64K)) + { + default: + case SYS_MEMORY_PAGE_SIZE_1M: + if(Memory.AlignAddr(size, alignment) & 0xfffff) + return CELL_EALIGN; + addr = Memory.Alloc(size, 0x100000); + break; + + case SYS_MEMORY_PAGE_SIZE_64K: + if(Memory.AlignAddr(size, alignment) & 0xffff) + return CELL_EALIGN; + addr = Memory.Alloc(size, 0x10000); + break; + } + + // Write back the start address of the allocated area. + Memory.Write32(alloc_addr, addr); + + return CELL_OK; +} + +int sys_mmapper_allocate_fixed_address() +{ + sc_mem.Warning("sys_mmapper_allocate_fixed_address"); + + // Allocate a fixed size from user memory. + if (!Memory.Alloc(SYS_MMAPPER_FIXED_SIZE, 0x100000)) + return CELL_EEXIST; + + return CELL_OK; +} + +int sys_mmapper_allocate_memory(u32 size, u64 flags, mem32_t mem_id) +{ + sc_mem.Warning("sys_mmapper_allocate_memory(size=0x%x, flags=0x%llx, mem_id_addr=0x%x)", size, flags, mem_id.GetAddr()); + + if(!mem_id.IsGood()) + return CELL_EFAULT; + + // Check page granularity. + u32 addr; + switch(flags & (SYS_MEMORY_PAGE_SIZE_1M | SYS_MEMORY_PAGE_SIZE_64K)) + { + case SYS_MEMORY_PAGE_SIZE_1M: + if(size & 0xfffff) + return CELL_EALIGN; + addr = Memory.Alloc(size, 0x100000); + break; + + case SYS_MEMORY_PAGE_SIZE_64K: + if(size & 0xffff) + return CELL_EALIGN; + addr = Memory.Alloc(size, 0x10000); + break; + + default: + return CELL_EINVAL; + } + + if(!addr) + return CELL_ENOMEM; + + // Generate a new mem ID. + mem_id = sc_mem.GetNewId(new mmapper_info(addr, size, flags)); + + return CELL_OK; +} + +int sys_mmapper_allocate_memory_from_container(u32 size, u32 cid, u64 flags, mem32_t mem_id) +{ + sc_mem.Warning("sys_mmapper_allocate_memory_from_container(size=0x%x, cid=%d, flags=0x%llx, mem_id_addr=0x%x)", + size, cid, flags, mem_id.GetAddr()); + + if(!mem_id.IsGood()) + return CELL_EFAULT; + + // Check if this container ID is valid. + MemoryContainerInfo* ct; + if(!sc_mem.CheckId(cid, ct)) + return CELL_ESRCH; + + // Check page granularity. + switch(flags & (SYS_MEMORY_PAGE_SIZE_1M | SYS_MEMORY_PAGE_SIZE_64K)) + { + case SYS_MEMORY_PAGE_SIZE_1M: + if(size & 0xfffff) + return CELL_EALIGN; + ct->addr = Memory.Alloc(size, 0x100000); + break; + + case SYS_MEMORY_PAGE_SIZE_64K: + if(size & 0xffff) + return CELL_EALIGN; + ct->addr = Memory.Alloc(size, 0x10000); + break; + + default: + return CELL_EINVAL; + } + + if(!ct->addr) + return CELL_ENOMEM; + ct->size = size; + + // Generate a new mem ID. + mem_id = sc_mem.GetNewId(new mmapper_info(ct->addr, ct->size, flags)); + + return CELL_OK; +} + +int sys_mmapper_change_address_access_right(u32 start_addr, u64 flags) +{ + sc_mem.Warning("sys_mmapper_change_address_access_right(start_addr=0x%x, flags=0x%llx)", start_addr, flags); + + if (!Memory.IsGoodAddr(start_addr)) + return CELL_EINVAL; + + // TODO + + return CELL_OK; +} + +int sys_mmapper_free_address(u32 start_addr) +{ + sc_mem.Warning("sys_mmapper_free_address(start_addr=0x%x)", start_addr); + + if(!Memory.IsGoodAddr(start_addr)) + return CELL_EINVAL; + + // Free the address. + Memory.Free(start_addr); + return CELL_OK; +} + +int sys_mmapper_free_memory(u32 mem_id) +{ + sc_mem.Warning("sys_mmapper_free_memory(mem_id=0x%x)", mem_id); + + // Check if this mem ID is valid. + mmapper_info* info; + if(!sc_mem.CheckId(mem_id, info)) + return CELL_ESRCH; + + // Release the allocated memory and remove the ID. + Memory.Free(info->addr); + Emu.GetIdManager().RemoveID(mem_id); + + return CELL_OK; +} + +int sys_mmapper_map_memory(u32 start_addr, u32 mem_id, u64 flags) +{ + sc_mem.Warning("sys_mmapper_map_memory(start_addr=0x%x, mem_id=0x%x, flags=0x%llx)", start_addr, mem_id, flags); + + // Check if this mem ID is valid. + mmapper_info* info; + if(!sc_mem.CheckId(mem_id, info)) + return CELL_ESRCH; + + // Map the memory into the process address. + if(!Memory.Map(start_addr, info->addr, info->size)) + sc_mem.Error("sys_mmapper_map_memory failed!"); + + // Keep track of mapped addresses. + mmapper_info_map[mem_id] = start_addr; + + return CELL_OK; +} + +int sys_mmapper_search_and_map(u32 start_addr, u32 mem_id, u64 flags, u32 alloc_addr) +{ + sc_mem.Warning("sys_mmapper_search_and_map(start_addr=0x%x, mem_id=0x%x, flags=0x%llx, alloc_addr=0x%x)", + start_addr, mem_id, flags, alloc_addr); + + if(!Memory.IsGoodAddr(alloc_addr)) + return CELL_EFAULT; + + // Check if this mem ID is valid. + mmapper_info* info; + if(!sc_mem.CheckId(mem_id, info)) + return CELL_ESRCH; + + // Search for a mappable address. + u32 addr; + bool found; + for (int i = 0; i < SYS_MMAPPER_FIXED_SIZE; i += 0x100000) + { + addr = start_addr + i; + found = Memory.Map(addr, info->addr, info->size); + if(found) + { + sc_mem.Warning("Found and mapped address 0x%x", addr); + break; + } + } + + // Check if the address is valid. + if (!Memory.IsGoodAddr(addr) || !found) + return CELL_ENOMEM; + + // Write back the start address of the allocated area. + Memory.Write32(alloc_addr, addr); + + // Keep track of mapped addresses. + mmapper_info_map[mem_id] = addr; + + return CELL_OK; +} + +int sys_mmapper_unmap_memory(u32 start_addr, u32 mem_id_addr) +{ + sc_mem.Warning("sys_mmapper_unmap_memory(start_addr=0x%x, mem_id_addr=0x%x)", start_addr, mem_id_addr); + + if (!Memory.IsGoodAddr(start_addr)) + return CELL_EINVAL; + + if (!Memory.IsGoodAddr(mem_id_addr)) + return CELL_EFAULT; + + // Write back the mem ID of the unmapped area. + u32 mem_id = mmapper_info_map.find(start_addr)->first; + Memory.Write32(mem_id_addr, mem_id); + + return CELL_OK; +} + +int sys_mmapper_enable_page_fault_notification(u32 start_addr, u32 q_id) +{ + sc_mem.Warning("sys_mmapper_enable_page_fault_notification(start_addr=0x%x, q_id=0x%x)", start_addr, q_id); + + if (!Memory.IsGoodAddr(start_addr)) + return CELL_EINVAL; + + // TODO + + return CELL_OK; +} diff --git a/rpcs3/Emu/SysCalls/lv2/SC_Memory.h b/rpcs3/Emu/SysCalls/lv2/SC_Memory.h index 3f6b7e0dd4..5a09b05016 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_Memory.h +++ b/rpcs3/Emu/SysCalls/lv2/SC_Memory.h @@ -1,53 +1,71 @@ -#pragma once - -#define SYS_MEMORY_CONTAINER_ID_INVALID 0xFFFFFFFF +#pragma once + +#define SYS_MEMORY_CONTAINER_ID_INVALID 0xFFFFFFFF +#define SYS_MEMORY_ACCESS_RIGHT_NONE 0x00000000000000F0ULL +#define SYS_MEMORY_ACCESS_RIGHT_PPU_THREAD 0x0000000000000008ULL +#define SYS_MEMORY_ACCESS_RIGHT_HANDLER 0x0000000000000004ULL +#define SYS_MEMORY_ACCESS_RIGHT_SPU_THREAD 0x0000000000000002ULL +#define SYS_MEMORY_ACCESS_RIGHT_SPU_RAW 0x0000000000000001ULL +#define SYS_MEMORY_ATTR_READ_ONLY 0x0000000000080000ULL +#define SYS_MEMORY_ATTR_READ_WRITE 0x0000000000040000ULL +#define SYS_MMAPPER_FIXED_ADDR 0xB0000000 +#define SYS_MMAPPER_FIXED_SIZE 0x10000000 #define SYS_VM_TEST_INVALID 0x0000ULL #define SYS_VM_TEST_UNUSED 0x0001ULL #define SYS_VM_TEST_ALLOCATED 0x0002ULL -#define SYS_VM_TEST_STORED 0x0004ULL - -enum -{ - SYS_MEMORY_PAGE_SIZE_1M = 0x400, - SYS_MEMORY_PAGE_SIZE_64K = 0x200, -}; - -struct MemoryContainerInfo -{ - u64 addr; - u32 size; - - MemoryContainerInfo(u64 addr, u32 size) - : addr(addr) - , size(size) - { - } -}; - -struct mmapper_info -{ - u64 addr; - u32 size; - u32 flags; - - mmapper_info(u64 _addr, u32 _size, u32 _flags) - : addr(_addr) - , size(_size) - , flags(_flags) - { - } - - mmapper_info() - { - } -}; - -struct sys_memory_info -{ - u32 total_user_memory; - u32 available_user_memory; -}; - +#define SYS_VM_TEST_STORED 0x0004ULL + +enum +{ + SYS_MEMORY_PAGE_SIZE_1M = 0x400, + SYS_MEMORY_PAGE_SIZE_64K = 0x200, +}; + +struct sys_memory_info +{ + u32 total_user_memory; + u32 available_user_memory; +}; + + +struct sys_page_attr_t +{ + u64 attribute; + u64 access_right; + u32 page_size; + u32 pad; +}; + +struct MemoryContainerInfo +{ + u64 addr; + u32 size; + + MemoryContainerInfo(u64 addr, u32 size) + : addr(addr) + , size(size) + { + } +}; + +struct mmapper_info +{ + u64 addr; + u32 size; + u32 flags; + + mmapper_info(u64 _addr, u32 _size, u32 _flags) + : addr(_addr) + , size(_size) + , flags(_flags) + { + } + + mmapper_info() + { + } +}; + struct sys_vm_statistics { u64 vm_crash_ppu; u64 vm_crash_spu; @@ -56,12 +74,4 @@ struct sys_vm_statistics { u32 physical_mem_size; u32 physical_mem_used; u64 timestamp; -}; - -struct sys_page_attr_t -{ - u64 attribute; - u64 access_right; - u32 page_size; - u32 pad; }; \ No newline at end of file