mirror of
https://github.com/hedge-dev/UnleashedRecomp.git
synced 2025-12-31 00:10:26 -06:00
136 lines
3.5 KiB
C++
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()
|
|
{
|
|
g_memory.Alloc(0x20000, RESERVED_BEGIN - 0x20000, MEM_COMMIT);
|
|
heap = o1heapInit(g_memory.Translate(0x20000), RESERVED_BEGIN - 0x20000);
|
|
|
|
g_memory.Alloc(RESERVED_END, 0x100000000 - RESERVED_END, MEM_COMMIT);
|
|
physicalHeap = o1heapInit(g_memory.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 = g_userHeap.Alloc(size);
|
|
if ((flags & 0x8) != 0)
|
|
memset(ptr, 0, size);
|
|
|
|
assert(ptr);
|
|
return g_memory.MapVirtual(ptr);
|
|
}
|
|
|
|
uint32_t RtlReAllocateHeap(uint32_t heapHandle, uint32_t flags, uint32_t memoryPointer, uint32_t size)
|
|
{
|
|
void* ptr = g_userHeap.Alloc(size);
|
|
if ((flags & 0x8) != 0)
|
|
memset(ptr, 0, size);
|
|
|
|
if (memoryPointer != 0)
|
|
{
|
|
void* oldPtr = g_memory.Translate(memoryPointer);
|
|
memcpy(ptr, oldPtr, std::min<size_t>(size, g_userHeap.Size(oldPtr)));
|
|
g_userHeap.Free(oldPtr);
|
|
}
|
|
|
|
assert(ptr);
|
|
return g_memory.MapVirtual(ptr);
|
|
}
|
|
|
|
uint32_t RtlFreeHeap(uint32_t heapHandle, uint32_t flags, uint32_t memoryPointer)
|
|
{
|
|
if (memoryPointer != NULL)
|
|
g_userHeap.Free(g_memory.Translate(memoryPointer));
|
|
|
|
return true;
|
|
}
|
|
|
|
uint32_t RtlSizeHeap(uint32_t heapHandle, uint32_t flags, uint32_t memoryPointer)
|
|
{
|
|
if (memoryPointer != NULL)
|
|
return (uint32_t)g_userHeap.Size(g_memory.Translate(memoryPointer));
|
|
|
|
return 0;
|
|
}
|
|
|
|
SWA_API uint32_t XAlloc(uint32_t size, uint32_t flags)
|
|
{
|
|
void* ptr = (flags & 0x80000000) != 0 ?
|
|
g_userHeap.AllocPhysical(size, (1ull << ((flags >> 24) & 0xF))) :
|
|
g_userHeap.Alloc(size);
|
|
|
|
if ((flags & 0x40000000) != 0)
|
|
memset(ptr, 0, size);
|
|
|
|
assert(ptr);
|
|
return g_memory.MapVirtual(ptr);
|
|
}
|
|
|
|
SWA_API void XFree(uint32_t baseAddress, uint32_t flags)
|
|
{
|
|
if (baseAddress != NULL)
|
|
g_userHeap.Free(g_memory.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);
|