Files
UnleashedRecomp-hedge-dev/UnleashedRecomp/kernel/heap.cpp
2024-09-30 20:57:43 +06:00

136 lines
3.5 KiB
C++

#include <stdafx.h>
#include "heap.h"
#include "memory.h"
#include "function.h"
constexpr size_t RESERVED_BEGIN = 0x7FEA0000;
constexpr size_t RESERVED_END = 0xA0000000;
void Heap::Init()
{
gMemory.Alloc(0x20000, RESERVED_BEGIN - 0x20000, MEM_COMMIT);
heap = o1heapInit(gMemory.Translate(0x20000), RESERVED_BEGIN - 0x20000);
gMemory.Alloc(RESERVED_END, 0x100000000 - RESERVED_END, MEM_COMMIT);
physicalHeap = o1heapInit(gMemory.Translate(RESERVED_END), 0x100000000 - RESERVED_END);
}
void* Heap::Alloc(size_t size)
{
std::lock_guard lock(mutex);
return o1heapAllocate(heap, std::max<size_t>(1, size));
}
void* Heap::AllocPhysical(size_t size, size_t alignment)
{
size = std::max<size_t>(1, size);
alignment = alignment == 0 ? 0x1000 : std::max<size_t>(16, alignment);
std::lock_guard lock(physicalMutex);
void* ptr = o1heapAllocate(physicalHeap, size + alignment);
size_t aligned = ((size_t)ptr + alignment) & ~(alignment - 1);
*((void**)aligned - 1) = ptr;
*((size_t*)aligned - 2) = size + O1HEAP_ALIGNMENT;
return (void*)aligned;
}
void Heap::Free(void* ptr)
{
if (ptr >= physicalHeap)
{
std::lock_guard lock(physicalMutex);
o1heapFree(physicalHeap, *((void**)ptr - 1));
}
else
{
std::lock_guard lock(mutex);
o1heapFree(heap, ptr);
}
}
size_t Heap::Size(void* ptr)
{
if (ptr)
return *((size_t*)ptr - 2) - O1HEAP_ALIGNMENT; // relies on fragment header in o1heap.c
return 0;
}
uint32_t RtlAllocateHeap(uint32_t heapHandle, uint32_t flags, uint32_t size)
{
void* ptr = gUserHeap.Alloc(size);
if ((flags & 0x8) != 0)
memset(ptr, 0, size);
assert(ptr);
return gMemory.MapVirtual(ptr);
}
uint32_t RtlReAllocateHeap(uint32_t heapHandle, uint32_t flags, uint32_t memoryPointer, uint32_t size)
{
void* ptr = gUserHeap.Alloc(size);
if ((flags & 0x8) != 0)
memset(ptr, 0, size);
if (memoryPointer != 0)
{
void* oldPtr = gMemory.Translate(memoryPointer);
memcpy(ptr, oldPtr, std::min<size_t>(size, gUserHeap.Size(oldPtr)));
gUserHeap.Free(oldPtr);
}
assert(ptr);
return gMemory.MapVirtual(ptr);
}
uint32_t RtlFreeHeap(uint32_t heapHandle, uint32_t flags, uint32_t memoryPointer)
{
if (memoryPointer != NULL)
gUserHeap.Free(gMemory.Translate(memoryPointer));
return true;
}
uint32_t RtlSizeHeap(uint32_t heapHandle, uint32_t flags, uint32_t memoryPointer)
{
if (memoryPointer != NULL)
return (uint32_t)gUserHeap.Size(gMemory.Translate(memoryPointer));
return 0;
}
SWA_API uint32_t XAlloc(uint32_t size, uint32_t flags)
{
void* ptr = (flags & 0x80000000) != 0 ?
gUserHeap.AllocPhysical(size, (1ull << ((flags >> 24) & 0xF))) :
gUserHeap.Alloc(size);
if ((flags & 0x40000000) != 0)
memset(ptr, 0, size);
assert(ptr);
return gMemory.MapVirtual(ptr);
}
SWA_API void XFree(uint32_t baseAddress, uint32_t flags)
{
if (baseAddress != NULL)
gUserHeap.Free(gMemory.Translate(baseAddress));
}
GUEST_FUNCTION_STUB(sub_82BD7788); // HeapCreate
GUEST_FUNCTION_STUB(sub_82BD9250); // HeapDestroy
GUEST_FUNCTION_HOOK(sub_82BD7D30, RtlAllocateHeap);
GUEST_FUNCTION_HOOK(sub_82BD8600, RtlFreeHeap);
GUEST_FUNCTION_HOOK(sub_82BD88F0, RtlReAllocateHeap);
GUEST_FUNCTION_HOOK(sub_82BD6FD0, RtlSizeHeap);
// Seems like these handle allocation of virtual and physical pages
GUEST_FUNCTION_HOOK(sub_831CC9C8, XAlloc);
GUEST_FUNCTION_HOOK(sub_831CCA60, XFree);