#include #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(1, size)); } void* Heap::AllocPhysical(size_t size, size_t alignment) { size = std::max(1, size); alignment = alignment == 0 ? 0x1000 : std::max(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, 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 XAllocMem(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 XFreeMem(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); GUEST_FUNCTION_HOOK(sub_831CC9C8, XAllocMem); GUEST_FUNCTION_HOOK(sub_831CCA60, XFreeMem);