diff --git a/CMakeLists.txt b/CMakeLists.txt index b5d256c21095..50cd7b535643 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1590,6 +1590,8 @@ add_library(${CoreLibName} ${CoreLinkType} Core/HLE/sceKernelAlarm.h Core/HLE/sceKernelEventFlag.cpp Core/HLE/sceKernelEventFlag.h + Core/HLE/sceKernelHeap.cpp + Core/HLE/sceKernelHeap.h Core/HLE/sceKernelInterrupt.cpp Core/HLE/sceKernelInterrupt.h Core/HLE/sceKernelMbx.cpp diff --git a/Core/Core.vcxproj b/Core/Core.vcxproj index 1c422c1593ef..5b675bd729d9 100644 --- a/Core/Core.vcxproj +++ b/Core/Core.vcxproj @@ -371,6 +371,7 @@ + @@ -899,6 +900,7 @@ + diff --git a/Core/Core.vcxproj.filters b/Core/Core.vcxproj.filters index 19698164c259..c95b6aa41fd4 100644 --- a/Core/Core.vcxproj.filters +++ b/Core/Core.vcxproj.filters @@ -740,6 +740,9 @@ HW + + HLE\Kernel + @@ -1373,10 +1376,13 @@ HW + + HLE\Kernel + - \ No newline at end of file + diff --git a/Core/HLE/FunctionWrappers.h b/Core/HLE/FunctionWrappers.h index 39599d408fde..01124ea15735 100644 --- a/Core/HLE/FunctionWrappers.h +++ b/Core/HLE/FunctionWrappers.h @@ -134,6 +134,11 @@ template void WrapI_CIIIII RETURN(retval); } +template void WrapI_IIIC() { + u32 retval = func(PARAM(0), PARAM(1), PARAM(2), Memory::GetCharPointer(PARAM(3))); + RETURN(retval); +} + // Hm, do so many params get passed in registers? template void WrapI_IIIIIIU() { u32 retval = func(PARAM(0), PARAM(1), PARAM(2), PARAM(3), PARAM(4), PARAM(5), PARAM(6)); diff --git a/Core/HLE/HLETables.cpp b/Core/HLE/HLETables.cpp index c62a564b7fa9..b4f0636f7709 100644 --- a/Core/HLE/HLETables.cpp +++ b/Core/HLE/HLETables.cpp @@ -40,6 +40,7 @@ #include "sceJpeg.h" #include "sceKernel.h" #include "sceKernelEventFlag.h" +#include "sceKernelHeap.h" #include "sceKernelMemory.h" #include "sceKernelInterrupt.h" #include "sceKernelModule.h" diff --git a/Core/HLE/sceKernel.cpp b/Core/HLE/sceKernel.cpp index ad571355ef15..520295f2d929 100644 --- a/Core/HLE/sceKernel.cpp +++ b/Core/HLE/sceKernel.cpp @@ -50,6 +50,7 @@ #include "sceJpeg.h" #include "sceKernel.h" #include "sceKernelAlarm.h" +#include "sceKernelHeap.h" #include "sceKernelInterrupt.h" #include "sceKernelThread.h" #include "sceKernelMemory.h" diff --git a/Core/HLE/sceKernel.h b/Core/HLE/sceKernel.h index fa5928584bba..96e94cb76002 100644 --- a/Core/HLE/sceKernel.h +++ b/Core/HLE/sceKernel.h @@ -340,6 +340,7 @@ enum TMIDPurpose PPSSPP_KERNEL_TMID_PMB = 0x100002, PPSSPP_KERNEL_TMID_File = 0x100003, PPSSPP_KERNEL_TMID_DirList = 0x100004, + PPSSPP_KERNEL_TMID_Heap = 0x100005, }; typedef int SceUID; diff --git a/Core/HLE/sceKernelHeap.cpp b/Core/HLE/sceKernelHeap.cpp new file mode 100644 index 000000000000..7b99eca18479 --- /dev/null +++ b/Core/HLE/sceKernelHeap.cpp @@ -0,0 +1,94 @@ +#include + +#include "Common/ChunkFile.h" +#include "Core/HLE/HLE.h" +#include "Core/HLE/FunctionWrappers.h" +#include "Core/HLE/sceKernel.h" +#include "Core/HLE/sceKernelHeap.h" +#include "Core/HLE/sceKernelMemory.h" +#include "Core/Util/BlockAllocator.h" + +static const u32 HEAP_BLOCK_HEADER_SIZE = 8; +static const bool g_fromBottom = false; + +struct Heap : public KernelObject { + int uid = 0; + int partitionId = 0; + u32 size = 0; + int flags = 0; + u32 address = 0; + std::string name; + BlockAllocator alloc; + + static u32 GetMissingErrorCode() { return SCE_KERNEL_ERROR_UNKNOWN_UID; } + static int GetStaticIDType() { return PPSSPP_KERNEL_TMID_Heap; } + int GetIDType() const override { return PPSSPP_KERNEL_TMID_Heap; } + + void DoState(PointerWrap &p) override { + p.Do(uid); + p.Do(partitionId); + p.Do(size); + p.Do(flags); + p.Do(address); + p.Do(name); + p.Do(alloc); + } +}; + +static int sceKernelCreateHeap(int partitionId, int size, int flags, const char *Name) { + u32 allocSize = (size + 3) & ~3; + + // TODO: partitionId should probably decide if we allocate from userMemory or kernel or whatever... + u32 addr = userMemory.Alloc(allocSize, g_fromBottom, "SysMemForKernel-Heap"); + if (addr == (u32)-1) { + ERROR_LOG(HLE, "sceKernelCreateHeap(partitionId=%d): Failed to allocate %d bytes memory", partitionId, size); + return SCE_KERNEL_ERROR_NO_MEMORY; // Blind guess + } + + Heap *heap = new Heap(); + SceUID uid = kernelObjects.Create(heap); + + heap->partitionId = partitionId; + heap->flags = flags; + heap->name = Name ? Name : ""; // Not sure if this needs validation. + heap->size = allocSize; + heap->address = addr; + heap->alloc.Init(heap->address + 128, heap->size - 128); + heap->uid = uid; + return hleLogSuccessInfoX(SCEKERNEL, uid); +} + +static int sceKernelAllocHeapMemory(int heapId, int size) { + u32 error; + Heap *heap = kernelObjects.Get(heapId, error); + if (heap) { + // There's 8 bytes at the end of every block, reserved. + u32 memSize = HEAP_BLOCK_HEADER_SIZE + size; + u32 addr = heap->alloc.Alloc(memSize, true); + return hleLogSuccessInfoX(SCEKERNEL, addr); + } else { + return hleLogError(SCEKERNEL, error, "sceKernelAllocHeapMemory(%d): invalid heapId", heapId); + } +} + +static int sceKernelDeleteHeap(int heapId) { + u32 error; + Heap *heap = kernelObjects.Get(heapId, error); + if (heap) { + userMemory.Free(heap->address); + kernelObjects.Destroy(heap->uid); + return hleLogSuccessInfoX(SCEKERNEL, 0); + } else { + return hleLogError(SCEKERNEL, error, "sceKernelDeleteHeap(%d): invalid heapId", heapId); + } +} + +const HLEFunction SysMemForKernel[] = { + { 0X636C953B, &WrapI_II, "sceKernelAllocHeapMemory", 'x', "ii" }, + { 0XC9805775, &WrapI_I, "sceKernelDeleteHeap", 'i', "i" }, + { 0X1C1FBFE7, &WrapI_IIIC, "sceKernelCreateHeap", 'i', "iixs" }, +}; + +void Register_SysMemForKernel() { + RegisterModule("SysMemForKernel", ARRAY_SIZE(SysMemForKernel), SysMemForKernel); +} diff --git a/Core/HLE/sceKernelHeap.h b/Core/HLE/sceKernelHeap.h new file mode 100644 index 000000000000..1279c7496232 --- /dev/null +++ b/Core/HLE/sceKernelHeap.h @@ -0,0 +1,3 @@ +#pragma once + +void Register_SysMemForKernel(); diff --git a/Core/HLE/sceKernelMemory.cpp b/Core/HLE/sceKernelMemory.cpp index 46e53753979c..40cccaa03d9b 100644 --- a/Core/HLE/sceKernelMemory.cpp +++ b/Core/HLE/sceKernelMemory.cpp @@ -2287,16 +2287,6 @@ const HLEFunction SysMemUserForUser[] = { {0XD8DE5C1E, &WrapU_V, "SysMemUserForUser_D8DE5C1E", 'x', "" }, }; -const HLEFunction SysMemForKernel[] = { - {0x636C953B, nullptr, "SysMemForKernel_636c953b", '?', "" }, - {0xC9805775, nullptr, "SysMemForKernel_c9805775", '?', "" }, - {0x1C1FBFE7, nullptr, "SysMemForKernel_1c1fbfe7", '?', "" }, -}; - -void Register_SysMemForKernel() { - RegisterModule("SysMemForKernel", ARRAY_SIZE(SysMemForKernel), SysMemForKernel); -} - void Register_SysMemUserForUser() { RegisterModule("SysMemUserForUser", ARRAY_SIZE(SysMemUserForUser), SysMemUserForUser); } diff --git a/Core/HLE/sceKernelMemory.h b/Core/HLE/sceKernelMemory.h index 2396792436e9..dce6df77e04a 100644 --- a/Core/HLE/sceKernelMemory.h +++ b/Core/HLE/sceKernelMemory.h @@ -66,5 +66,4 @@ int sceKernelGetTlsAddr(SceUID uid); int sceKernelFreeTlspl(SceUID uid); int sceKernelReferTlsplStatus(SceUID uid, u32 infoPtr); -void Register_SysMemForKernel(); void Register_SysMemUserForUser(); diff --git a/UWP/CoreUWP/CoreUWP.vcxproj b/UWP/CoreUWP/CoreUWP.vcxproj index 814930607bfc..0bbac0c46e94 100644 --- a/UWP/CoreUWP/CoreUWP.vcxproj +++ b/UWP/CoreUWP/CoreUWP.vcxproj @@ -466,6 +466,7 @@ + @@ -678,6 +679,7 @@ + diff --git a/UWP/CoreUWP/CoreUWP.vcxproj.filters b/UWP/CoreUWP/CoreUWP.vcxproj.filters index 07d1e0937168..7afcc97e719d 100644 --- a/UWP/CoreUWP/CoreUWP.vcxproj.filters +++ b/UWP/CoreUWP/CoreUWP.vcxproj.filters @@ -368,6 +368,9 @@ HLE + + HLE + HLE @@ -968,6 +971,9 @@ HLE + + HLE + HLE @@ -1298,4 +1304,4 @@ HW - \ No newline at end of file + diff --git a/android/jni/Android.mk b/android/jni/Android.mk index d334324cf82d..6f23ada75f0f 100644 --- a/android/jni/Android.mk +++ b/android/jni/Android.mk @@ -360,6 +360,7 @@ EXEC_AND_LIB_FILES := \ $(SRC)/Core/HLE/sceKernel.cpp \ $(SRC)/Core/HLE/sceKernelAlarm.cpp \ $(SRC)/Core/HLE/sceKernelEventFlag.cpp \ + $(SRC)/Core/HLE/sceKernelHeap.cpp \ $(SRC)/Core/HLE/sceKernelInterrupt.cpp \ $(SRC)/Core/HLE/sceKernelMemory.cpp \ $(SRC)/Core/HLE/sceKernelModule.cpp \ diff --git a/libretro/Makefile.common b/libretro/Makefile.common index d909df3ada36..b1fd51bdb670 100644 --- a/libretro/Makefile.common +++ b/libretro/Makefile.common @@ -389,6 +389,7 @@ SOURCES_CXX += $(NATIVEDIR)/math/dataconv.cpp \ $(COREDIR)/HLE/sceKernel.cpp \ $(COREDIR)/HLE/sceKernelAlarm.cpp \ $(COREDIR)/HLE/sceKernelEventFlag.cpp \ + $(COREDIR)/HLE/sceKernelHeap.cpp \ $(COREDIR)/HLE/sceKernelInterrupt.cpp \ $(COREDIR)/HLE/sceKernelMbx.cpp \ $(COREDIR)/HLE/sceKernelMemory.cpp \