mirror of
https://github.com/Mauler125/r5sdk.git
synced 2025-02-09 19:15:03 +01:00
477 lines
17 KiB
C++
477 lines
17 KiB
C++
//=============================================================================//
|
|
//
|
|
// Purpose: Memory allocation override functions
|
|
//-----------------------------------------------------------------------------
|
|
// The replacement functions use the game's internal memalloc system instead
|
|
// of the CRT one, this allows for sharing allocated memory directly between
|
|
// the SDK and the engine itself.
|
|
//
|
|
//=============================================================================//
|
|
#include "memstd.h"
|
|
#include "mathlib/mathlib.h"
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: initialize the global memory allocator singleton pointer
|
|
//-----------------------------------------------------------------------------
|
|
static bool s_bAllocatorInitialized = false;
|
|
static void InitAllocator()
|
|
{
|
|
if (!s_bAllocatorInitialized)
|
|
{
|
|
s_bAllocatorInitialized = true;
|
|
const QWORD imageBase = CModule::GetProcessEnvironmentBlock()->ImageBaseAddress;
|
|
|
|
CreateGlobalMemAlloc = CModule::GetExportedSymbol(imageBase,
|
|
"CreateGlobalMemAlloc").RCast<CStdMemAlloc* (*)(void)>();
|
|
|
|
g_pMemAllocSingleton = CModule::GetExportedSymbol(imageBase,
|
|
"g_pMemAllocSingleton").DerefSelf().RCast<CStdMemAlloc*>();
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: new/delete operator override
|
|
//-----------------------------------------------------------------------------
|
|
void* operator new(size_t const nSize) noexcept(false)
|
|
{
|
|
return malloc(nSize);
|
|
}
|
|
void* __cdecl operator new(size_t const nSize,
|
|
int const nBlockUse, const char* const pFileName, int const nLine)
|
|
{
|
|
NOTE_UNUSED(nBlockUse);
|
|
|
|
InitAllocator();
|
|
return MemAllocSingleton()->InternalAlloc(nSize, pFileName, nLine);
|
|
}
|
|
void operator delete(void* const pBlock) throw()
|
|
{
|
|
return free(pBlock);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
extern "C"
|
|
{
|
|
//-------------------------------------------------------------------------
|
|
// Base overrides
|
|
//-------------------------------------------------------------------------
|
|
__declspec(restrict) void* __cdecl _malloc_base(size_t const nSize)
|
|
{
|
|
InitAllocator();
|
|
return MemAllocSingleton()->Alloc(nSize);
|
|
}
|
|
//-------------------------------------------------------------------------
|
|
__declspec(restrict) void* __cdecl _calloc_base(size_t const nCount,
|
|
size_t const nSize)
|
|
{
|
|
InitAllocator();
|
|
|
|
size_t const nTotal = nCount * nSize;
|
|
void* const pNew = MemAllocSingleton()->Alloc(nTotal);
|
|
|
|
memset(pNew, NULL, nTotal);
|
|
return pNew;
|
|
}
|
|
//-------------------------------------------------------------------------
|
|
__declspec(restrict) void* __cdecl _realloc_base(void* const pBlock,
|
|
size_t const nSize)
|
|
{
|
|
InitAllocator();
|
|
|
|
if (nSize)
|
|
return MemAllocSingleton()->Realloc(pBlock, nSize);
|
|
else
|
|
{
|
|
MemAllocSingleton()->InternalFree(pBlock, "tier0_static128", 0);
|
|
return nullptr;
|
|
}
|
|
}
|
|
//-------------------------------------------------------------------------
|
|
__declspec(restrict) void* __cdecl _recalloc_base(void* const pBlock,
|
|
size_t const nCount, size_t const nSize)
|
|
{
|
|
InitAllocator();
|
|
|
|
const size_t nTotal = nCount * nSize;
|
|
void* const pMemOut = MemAllocSingleton()->Realloc(pBlock, nTotal);
|
|
|
|
if (!pBlock)
|
|
memset(pMemOut, NULL, nTotal);
|
|
|
|
return pMemOut;
|
|
}
|
|
//-------------------------------------------------------------------------
|
|
__declspec(noinline) void __cdecl _free_base(void* const pBlock)
|
|
{
|
|
InitAllocator();
|
|
#if !(defined(_DEBUG) && !defined(USE_MEM_DEBUG))
|
|
MemAllocSingleton()->Free(pBlock);
|
|
#else
|
|
MemAllocSingleton()->InternalFree(pBlock, "tier0_static128", 0);
|
|
#endif // !_DEBUG && !USE_MEM_DEBUG
|
|
}
|
|
//-------------------------------------------------------------------------
|
|
void* __cdecl _expand_base(void* const pBlock, size_t const nNewSize, int const nBlockUse)
|
|
{
|
|
// Expanding isn't supported!!!
|
|
Assert(0);
|
|
return NULL;
|
|
}
|
|
//-------------------------------------------------------------------------
|
|
__declspec(noinline) size_t __cdecl _msize(void* const pBlock)
|
|
{
|
|
InitAllocator();
|
|
return MemAllocSingleton()->GetSize(pBlock);
|
|
}
|
|
//-------------------------------------------------------------------------
|
|
char* __cdecl _strdup(const char* const pString)
|
|
{
|
|
InitAllocator();
|
|
|
|
const size_t nLen = strlen(pString) + 1;
|
|
void* const pNew = MemAllocSingleton()->Alloc(nLen);
|
|
|
|
if (!pNew)
|
|
return nullptr;
|
|
|
|
return reinterpret_cast<char*>(memcpy(pNew, pString, nLen));
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
// Align overrides
|
|
//-------------------------------------------------------------------------
|
|
ALLOC_CALL void* _aligned_malloc_base(size_t const nSize, size_t nAlign)
|
|
{
|
|
InitAllocator();
|
|
unsigned char* pAlloc, * pResult;
|
|
|
|
if (!IsPowerOfTwo(nAlign))
|
|
return nullptr;
|
|
|
|
nAlign = (nAlign > sizeof(void*) ? nAlign : sizeof(void*)) - 1;
|
|
|
|
if ((pAlloc = (unsigned char*)MemAllocSingleton()->Alloc(
|
|
sizeof(void*) + nAlign + nSize)) == (unsigned char*)nullptr)
|
|
return nullptr;
|
|
|
|
pResult = (unsigned char*)((size_t)(pAlloc + sizeof(void*) + nAlign) & ~nAlign);
|
|
((unsigned char**)(pResult))[-1] = pAlloc;
|
|
|
|
return (void*)pResult;
|
|
}
|
|
//-------------------------------------------------------------------------
|
|
ALLOC_CALL void* __cdecl _aligned_realloc_base(void* const pBlock,
|
|
size_t const nSize, size_t const nAlign)
|
|
{
|
|
InitAllocator();
|
|
|
|
if (!IsPowerOfTwo(nAlign))
|
|
return nullptr;
|
|
|
|
// Don't change alignment between allocation + reallocation.
|
|
if (((size_t)pBlock & (nAlign - 1)) != 0)
|
|
return nullptr;
|
|
|
|
if (!pBlock)
|
|
return _aligned_malloc_base(nSize, nAlign);
|
|
|
|
void* pAlloc, * pResult;
|
|
|
|
// Figure out the actual allocation point
|
|
pAlloc = pBlock;
|
|
pAlloc = (void*)(((size_t)pAlloc & ~(sizeof(void*) - 1)) - sizeof(void*));
|
|
pAlloc = *((void**)pAlloc);
|
|
|
|
// See if we have enough space
|
|
size_t nOffset = (size_t)pBlock - (size_t)pAlloc;
|
|
size_t nOldSize = MemAllocSingleton()->GetSize(pAlloc);
|
|
|
|
if (nOldSize >= nSize + nOffset)
|
|
return pBlock;
|
|
|
|
pResult = _aligned_malloc_base(nSize, nAlign);
|
|
memcpy(pResult, pBlock, nOldSize - nOffset);
|
|
|
|
MemAllocSingleton()->Free(pAlloc);
|
|
return pResult;
|
|
}
|
|
//-------------------------------------------------------------------------
|
|
ALLOC_CALL void* __cdecl _aligned_recalloc_base(void* const pBlock,
|
|
size_t const nSize, size_t const nAlign)
|
|
{
|
|
NOTE_UNUSED(pBlock);
|
|
NOTE_UNUSED(nSize);
|
|
NOTE_UNUSED(nAlign);
|
|
|
|
Assert(0); // Unsupported function.
|
|
Error(eDLL_T::COMMON, EXIT_FAILURE, "Unsupported function\n");
|
|
|
|
return NULL;
|
|
}
|
|
//-------------------------------------------------------------------------
|
|
FREE_CALL void __cdecl _aligned_free_base(void* const pBlock)
|
|
{
|
|
InitAllocator();
|
|
|
|
if (!pBlock)
|
|
return;
|
|
|
|
// pAlloc is the pointer to the start of memory block.
|
|
void* pAlloc = pBlock;
|
|
|
|
pAlloc = (void*)(((size_t)pAlloc & ~(sizeof(void*) - 1)) - sizeof(void*));
|
|
pAlloc = *((void**)pAlloc);
|
|
|
|
MemAllocSingleton()->Free(pAlloc);
|
|
}
|
|
// aligned ----------------------------------------------------------------
|
|
ALLOC_CALL void* __cdecl _aligned_malloc(size_t const nSize, size_t const nAlign)
|
|
{
|
|
return _aligned_malloc_base(nSize, nAlign);
|
|
}
|
|
ALLOC_CALL void* __cdecl _aligned_realloc(void* const pBlock,
|
|
size_t const nSize, size_t const nAlign)
|
|
{
|
|
return _aligned_realloc_base(pBlock, nSize, nAlign);
|
|
}
|
|
ALLOC_CALL void* __cdecl _aligned_recalloc(void* const pBlock,
|
|
size_t const nCount, size_t const nSize, size_t const nAlign)
|
|
{
|
|
return _aligned_recalloc_base(pBlock, nCount * nSize, nAlign);
|
|
}
|
|
FREE_CALL void __cdecl _aligned_free(void* pBlock)
|
|
{
|
|
_aligned_free_base(pBlock);
|
|
}
|
|
// aligned offset base ----------------------------------------------------
|
|
ALLOC_CALL void* __cdecl _aligned_offset_malloc_base(
|
|
size_t const nSize, size_t const nAlign, size_t const nOffset)
|
|
{
|
|
Assert(IsPC() || 0);
|
|
return NULL;
|
|
}
|
|
ALLOC_CALL void* __cdecl _aligned_offset_realloc_base(
|
|
void* const pBlock, size_t const nSize, size_t const nAlign, size_t const nOffset)
|
|
{
|
|
Assert(IsPC() || 0);
|
|
return NULL;
|
|
}
|
|
ALLOC_CALL void* __cdecl _aligned_offset_recalloc_base(
|
|
void* const pBlock, size_t const nSize, size_t const nAlign, size_t const nOffset)
|
|
{
|
|
Assert(IsPC() || 0);
|
|
return NULL;
|
|
}
|
|
// aligned offset ---------------------------------------------------------
|
|
ALLOC_CALL void* __cdecl _aligned_offset_malloc(
|
|
size_t const nSize, size_t const nAlign, size_t const nOffset)
|
|
{
|
|
return _aligned_offset_malloc_base(nSize, nAlign, nOffset);
|
|
}
|
|
ALLOC_CALL void* __cdecl _aligned_offset_realloc(
|
|
void* const pBlock, size_t const nSize, size_t const nAlign, size_t const nOffset)
|
|
{
|
|
return _aligned_offset_realloc_base(pBlock, nSize, nAlign, nOffset);
|
|
}
|
|
ALLOC_CALL void* __cdecl _aligned_offset_recalloc(
|
|
void* const pBlock, size_t const nCount, size_t const nSize, size_t const nAlign, size_t const nOffset)
|
|
{
|
|
return _aligned_offset_recalloc_base(pBlock, nCount * nSize, nAlign, nOffset);
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
// CRT overrides
|
|
//-------------------------------------------------------------------------
|
|
void* __cdecl _heap_alloc(size_t const nSize)
|
|
{
|
|
return _malloc_base(nSize);
|
|
}
|
|
void* __cdecl _malloc_crt(size_t const nSize)
|
|
{
|
|
return _malloc_base(nSize);
|
|
}
|
|
void* __cdecl _calloc_crt(size_t const nCount, size_t const nSize)
|
|
{
|
|
return _calloc_base(nCount, nSize);
|
|
}
|
|
void* __cdecl _realloc_crt(void* const pBlock, size_t const nSize)
|
|
{
|
|
return _realloc_base(pBlock, nSize);
|
|
}
|
|
void* __cdecl _recalloc_crt(void* const pBlock, size_t const nCount, size_t const nSize)
|
|
{
|
|
return _recalloc_base(pBlock, nSize, nCount);
|
|
}
|
|
|
|
#if (defined(_DEBUG) || defined(USE_MEM_DEBUG))
|
|
//-------------------------------------------------------------------------
|
|
// Debug overrides
|
|
//-------------------------------------------------------------------------
|
|
__declspec(noinline) void* __cdecl _malloc_dbg(size_t const nSize,
|
|
int const nBlockUse, const char* const pFileName, int const nLine)
|
|
{
|
|
NOTE_UNUSED(nBlockUse);
|
|
InitAllocator();
|
|
|
|
return MemAllocSingleton()->InternalAlloc(nSize, pFileName, nLine);
|
|
}
|
|
//-------------------------------------------------------------------------
|
|
__declspec(noinline) void* __cdecl _calloc_dbg(size_t const nCount,
|
|
size_t const nSize, int const nBlockUse, const char* const pFileName,
|
|
int const nLine)
|
|
{
|
|
NOTE_UNUSED(nBlockUse);
|
|
InitAllocator();
|
|
|
|
size_t const nTotal = nCount * nSize;
|
|
void* const pNew = MemAllocSingleton()->InternalAlloc(nTotal, pFileName, nLine);
|
|
|
|
memset(pNew, NULL, nTotal);
|
|
return pNew;
|
|
}
|
|
//-------------------------------------------------------------------------
|
|
__declspec(noinline) void* __cdecl _realloc_dbg(void* const pBlock,
|
|
size_t const nSize, int const nBlockUse, const char* const pFileName,
|
|
int const nLine)
|
|
{
|
|
NOTE_UNUSED(nBlockUse);
|
|
InitAllocator();
|
|
|
|
if (nSize)
|
|
return MemAllocSingleton()->Realloc(pBlock, nSize);
|
|
else
|
|
{
|
|
MemAllocSingleton()->InternalFree(pBlock, pFileName, nLine);
|
|
return nullptr;
|
|
}
|
|
}
|
|
//-------------------------------------------------------------------------
|
|
__declspec(noinline) void* __cdecl _recalloc_dbg(void* const pBlock,
|
|
size_t const nCount, size_t const nSize, int const nBlockUse,
|
|
const char* const pFileName, int const nLine)
|
|
{
|
|
NOTE_UNUSED(nBlockUse);
|
|
InitAllocator();
|
|
|
|
const size_t nTotal = nCount * nSize;
|
|
void* const pMemOut = MemAllocSingleton()->InternalRealloc(pBlock, nTotal,
|
|
pFileName, nLine);
|
|
|
|
if (!pBlock)
|
|
memset(pMemOut, NULL, nTotal);
|
|
|
|
return pMemOut;
|
|
}
|
|
//-------------------------------------------------------------------------
|
|
__declspec(noinline) void __cdecl _free_dbg(void* const pBlock,
|
|
int const nBlockUse)
|
|
{
|
|
NOTE_UNUSED(nBlockUse);
|
|
InitAllocator();
|
|
|
|
MemAllocSingleton()->InternalFree(pBlock, "tier0_static128", 0);
|
|
}
|
|
//-------------------------------------------------------------------------
|
|
void* __cdecl _expand_dbg(void* const pBlock, size_t const nNewSize, int const nBlockUse,
|
|
const char* const pFileName, int const nLine)
|
|
{
|
|
NOTE_UNUSED(pFileName);
|
|
NOTE_UNUSED(nLine);
|
|
|
|
return _expand_base(pBlock, nNewSize, nBlockUse);
|
|
}
|
|
//-------------------------------------------------------------------------
|
|
__declspec(noinline) size_t __cdecl _msize_dbg(void* const pBlock, int const nBlockUse)
|
|
{
|
|
NOTE_UNUSED(nBlockUse);
|
|
return _msize(pBlock);
|
|
}
|
|
//-------------------------------------------------------------------------
|
|
void* __cdecl _heap_alloc_dbg(size_t const nSize, int const nBlockUse,
|
|
const char* const szFileName, int const nLine)
|
|
{
|
|
return _malloc_dbg(nSize, nBlockUse, szFileName, nLine);
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
// Debug align
|
|
//-------------------------------------------------------------------------
|
|
void* __cdecl _aligned_malloc_dbg(size_t nSize, size_t nAlign,
|
|
const char* const szFileName, int nLine)
|
|
{
|
|
NOTE_UNUSED(szFileName);
|
|
NOTE_UNUSED(nLine);
|
|
|
|
return _aligned_malloc(nSize, nAlign);
|
|
}
|
|
void* __cdecl _aligned_realloc_dbg(void* pBlock, size_t nSize, size_t nAlign,
|
|
const char* const szFileName, int nLine)
|
|
{
|
|
NOTE_UNUSED(szFileName);
|
|
NOTE_UNUSED(nLine);
|
|
|
|
return _aligned_realloc(pBlock, nSize, nAlign);
|
|
}
|
|
void* __cdecl _aligned_offset_malloc_dbg(size_t const nSize, size_t const nAlign,
|
|
size_t const nOffset, const char* const szFileName, int const nLine)
|
|
{
|
|
NOTE_UNUSED(szFileName);
|
|
NOTE_UNUSED(nLine);
|
|
|
|
return _aligned_offset_malloc(nSize, nAlign, nOffset);
|
|
}
|
|
void* __cdecl _aligned_offset_realloc_dbg(void* const pBlock, size_t const nSize,
|
|
size_t const nAlign, size_t const offset, const char* const szFileName, int const nLine)
|
|
{
|
|
NOTE_UNUSED(szFileName);
|
|
NOTE_UNUSED(nLine);
|
|
|
|
return _aligned_offset_realloc(pBlock, nSize, nAlign, offset);
|
|
}
|
|
void __cdecl _aligned_free_dbg(void* const pBlock)
|
|
{
|
|
_aligned_free(pBlock);
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
// CRT debug nolocks
|
|
//-------------------------------------------------------------------------
|
|
void __cdecl _free_nolock(void* const pUserData)
|
|
{
|
|
// I don't think the second param is used in memoverride
|
|
_free_dbg(pUserData, 0);
|
|
}
|
|
void __cdecl _free_dbg_nolock(void* const pUserData, int const nBlockUse)
|
|
{
|
|
_free_dbg(pUserData, nBlockUse);
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
// CRT debug stubs
|
|
//-------------------------------------------------------------------------
|
|
_CRT_ALLOC_HOOK __cdecl _CrtGetAllocHook(void)
|
|
{
|
|
Assert(0);
|
|
return NULL;
|
|
}
|
|
int __cdecl CheckBytes(unsigned char* pb, unsigned char bCheck, size_t nSize)
|
|
{
|
|
int bOkay = TRUE;
|
|
return bOkay;
|
|
}
|
|
_CRT_DUMP_CLIENT __cdecl _CrtGetDumpClient(void)
|
|
{
|
|
Assert(0);
|
|
return NULL;
|
|
}
|
|
void __cdecl _printMemBlockData(_locale_t plocinfo, _CrtMemBlockHeader* pHead)
|
|
{
|
|
}
|
|
void __cdecl _CrtMemDumpAllObjectsSince_stat(const _CrtMemState* state, _locale_t plocinfo)
|
|
{
|
|
// Might need to be renamed to '_CrtMemDumpAllObjectsSince'
|
|
// instead of '_CrtMemDumpAllObjectsSince_stat'.
|
|
}
|
|
#endif // _DEBUG || USE_MEM_DEBUG
|
|
} // end extern "C"
|