diff --git a/Core/HLE/sceHeap.cpp b/Core/HLE/sceHeap.cpp index 57b087b922..30556a0041 100644 --- a/Core/HLE/sceHeap.cpp +++ b/Core/HLE/sceHeap.cpp @@ -18,62 +18,117 @@ #include "Common/ChunkFile.h" #include "Core/Reporting.h" #include "Core/HLE/HLE.h" +#include "sceKernelMemory.h" #include "Core/HLE/sceHeap.h" +std::map heapList; + void __HeapDoState(PointerWrap &p) { - auto s = p.Section("sceHeap", 1); + auto s = p.Section("sceHeap", 1, 2); if (!s) return; + + if (s == 1) { + } else { + p.Do(heapList); + } } -int sceHeapReallocHeapMemory(u32 heapPtr, u32 memPtr, int memSize) { - ERROR_LOG_REPORT(HLE,"UNIMPL sceHeapReallocHeapMemory(%d %d %d)", heapPtr, memPtr, memSize); +enum SceHeapAttr +{ + PSP_HEAP_ATTR_HIGHMEM = 0x4000, + PSP_HEAP_ATTR_EXT = 0x8000, +}; + +int sceHeapReallocHeapMemory(u32 heapAddr, u32 memPtr, int memSize) { + ERROR_LOG_REPORT(HLE,"UNIMPL sceHeapReallocHeapMemory(%08x, %08x, %08x)", heapAddr, memPtr, memSize); return 0; } int sceHeapReallocHeapMemoryWithOption(u32 heapPtr, u32 memPtr, int memSize, u32 paramsPtr) { - ERROR_LOG_REPORT(HLE,"UNIMPL sceHeapReallocHeapMemoryWithOption(%d %d %d %d)", heapPtr, memPtr, memSize, paramsPtr); + ERROR_LOG_REPORT(HLE,"UNIMPL sceHeapReallocHeapMemoryWithOption(%08x, %08x, %08x, %08x)", heapPtr, memPtr, memSize, paramsPtr); return 0; } -int sceHeapFreeHeapMemory(u32 heapPtr, u32 memPtr) { - ERROR_LOG_REPORT(HLE,"UNIMPL sceHeapFreeHeapMemory(%d %d)", heapPtr, memPtr); +int sceHeapFreeHeapMemory(u32 heapAddr, u32 memAddr) { + if (!Memory::IsValidAddress(memAddr)) + return SCE_KERNEL_ERROR_ILLEGAL_ADDR; + Heap *heap = heapList[heapAddr]; + if (!heap) + return SCE_KERNEL_ERROR_INVALID_ID; + if(!heap->alloc.FreeExact(memAddr)) + return SCE_KERNEL_ERROR_INVALID_POINTER; + + DEBUG_LOG_REPORT(HLE,"sceHeapFreeHeapMemory(%08x, %08x)", heapAddr, memAddr); return 0; } -int sceHeapGetMallinfo(u32 heapPtr, u32 infoPtr) { - ERROR_LOG_REPORT(HLE,"UNIMPL sceHeapGetMallinfo(%d %d)", heapPtr, infoPtr); +int sceHeapGetMallinfo(u32 heapAddr, u32 infoPtr) { + ERROR_LOG_REPORT(HLE,"UNIMPL sceHeapGetMallinfo(%08x, %08x)", heapAddr, infoPtr); return 0; } -int sceHeapAllocHeapMemoryWithOption(u32 heapPtr, int memSize, u32 paramsPtr) { - ERROR_LOG_REPORT(HLE,"UNIMPL sceHeapAllocHeapMemoryWithOption(%08x, %08x, %08x)", heapPtr, memSize, paramsPtr); - return 0; +int sceHeapAllocHeapMemoryWithOption(u32 heapAddr, u32 memSize, u32 paramsPtr) { + Heap *heap = heapList[heapAddr]; + if (!heap) + return 0; + if (Memory::Read_U32(paramsPtr) == 8) + heap->alloc.Setgrain_(Memory::Read_U32(paramsPtr + 4)); + u32 addr = heap->alloc.Alloc(memSize, heap->fromtop); + DEBUG_LOG_REPORT(HLE,"sceHeapAllocHeapMemoryWithOption(%08x, %08x, %08x)", heapAddr, memSize, paramsPtr); + return addr; } -int sceHeapGetTotalFreeSize(u32 heapPtr) { - ERROR_LOG_REPORT(HLE,"UNIMPL sceHeapGetTotalFreeSize(%d)", heapPtr); - return 0; +int sceHeapGetTotalFreeSize(u32 heapAddr) { + Heap *heap = heapList[heapAddr]; + DEBUG_LOG_REPORT(HLE,"UNIMPL sceHeapGetTotalFreeSize(%08x)", heapAddr); + return heap->alloc.GetTotalFreeBytes(); } int sceHeapIsAllocatedHeapMemory(u32 heapPtr, u32 memPtr) { - ERROR_LOG_REPORT(HLE,"UNIMPL sceHeapIsAllocatedHeapMemory(%d %d)", heapPtr, memPtr); + ERROR_LOG_REPORT(HLE,"UNIMPL sceHeapIsAllocatedHeapMemory(%08x, %08x)", heapPtr, memPtr); return 0; } -int sceHeapDeleteHeap(u32 heapPtr) { - ERROR_LOG_REPORT(HLE,"UNIMPL sceHeapDeleteHeap(%d)", heapPtr); +int sceHeapDeleteHeap(u32 heapAddr) { + Heap *heap = heapList[heapAddr]; + if(heapList.erase(heapAddr) != 0) + delete heap; + ERROR_LOG_REPORT(HLE,"UNIMPL sceHeapDeleteHeap(%08x)", heapAddr); return 0; } -int sceHeapCreateHeap(const char* name, int len, int attr, u32 paramsPtr) { - ERROR_LOG_REPORT(HLE,"UNIMPL sceHeapCreateHeap(%s %d %d %d)", name, len, attr, paramsPtr); - return 0; +int sceHeapCreateHeap(const char* name, u32 heapSize, int attr, u32 paramsPtr) { + if (paramsPtr != 0) { + u32 size = Memory::Read_U32(paramsPtr); + WARN_LOG_REPORT(SCEKERNEL, "sceHeapCreateHeap(): unsupported options parameter, size = %d", size); + } + + int allocSize = (heapSize + 3) & ~3; + + Heap *heap = new Heap; + heap->size = allocSize; + heap->fromtop = (attr & PSP_HEAP_ATTR_HIGHMEM) != 0; + u32 addr = userMemory.Alloc(heap->size, heap->fromtop, "Heap"); + if (addr == (u32)-1) { + ERROR_LOG(SCEKERNEL, "sceHeapCreateHeap(): Failed to allocate %i bytes memory", allocSize); + delete heap; + return 0; + } + heap->address = addr; + heap->alloc.Init(heap->address,heap->size); + heapList[heap->address] = heap; + DEBUG_LOG_REPORT(HLE,"sceHeapCreateHeap(%s, %08x, %08x, %08x)", name, heapSize, attr, paramsPtr); + return heap->address; } -int sceHeapAllocHeapMemory(u32 heapAddr, int len) { - ERROR_LOG_REPORT(HLE,"UNIMPL sceHeapAllocHeapMemory(%d %d)", heapAddr, len); - return 0; +int sceHeapAllocHeapMemory(u32 heapAddr, u32 memSize) { + Heap *heap = heapList[heapAddr]; + if (!heap) + return 0; + u32 addr = heap->alloc.Alloc(memSize, heap->fromtop); + DEBUG_LOG_REPORT(HLE,"sceHeapAllocHeapMemory(%08x, %08x)", heapAddr, memSize); + return addr; } @@ -83,12 +138,12 @@ static const HLEFunction sceHeap[] = {0x1C84B58D,WrapI_UUIU,"sceHeapReallocHeapMemoryWithOption"}, {0x2ABADC63,WrapI_UU,"sceHeapFreeHeapMemory"}, {0x2A0C2009,WrapI_UU,"sceHeapGetMallinfo"}, - {0x2B7299D8,WrapI_UIU,"sceHeapAllocHeapMemoryWithOption"}, + {0x2B7299D8,WrapI_UUU,"sceHeapAllocHeapMemoryWithOption"}, {0x4929B40D,WrapI_U,"sceHeapGetTotalFreeSize"}, {0x7012BBDD,WrapI_UU,"sceHeapIsAllocatedHeapMemory"}, {0x70210B73,WrapI_U,"sceHeapDeleteHeap"}, - {0x7DE281C2,WrapI_CIIU,"sceHeapCreateHeap"}, - {0xA8E102A0,WrapI_UI,"sceHeapAllocHeapMemory"}, + {0x7DE281C2,WrapI_CUIU,"sceHeapCreateHeap"}, + {0xA8E102A0,WrapI_UU,"sceHeapAllocHeapMemory"}, }; void Register_sceHeap() diff --git a/Core/HLE/sceHeap.h b/Core/HLE/sceHeap.h index ecffd69f25..2d65df9269 100644 --- a/Core/HLE/sceHeap.h +++ b/Core/HLE/sceHeap.h @@ -16,6 +16,18 @@ // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. #pragma once +#include "../Util/BlockAllocator.h" +#include + +struct Heap +{ + Heap():alloc(4) {} + + u32 size; + u32 address; + bool fromtop; + BlockAllocator alloc; +}; void Register_sceHeap(); void __HeapDoState(PointerWrap &p); \ No newline at end of file diff --git a/Core/Util/BlockAllocator.h b/Core/Util/BlockAllocator.h index 273b636b16..6eb48efc41 100644 --- a/Core/Util/BlockAllocator.h +++ b/Core/Util/BlockAllocator.h @@ -54,6 +54,8 @@ public: u32 GetLargestFreeBlockSize() const; u32 GetTotalFreeBytes() const; + void Setgrain_(u32 value) {grain_ = value;} + void DoState(PointerWrap &p); private: