r5sdk/r5dev/tier0/memstd.cpp
Kawe Mazidjatari 789ecbc234 Fully disable memory expansion
The game's memalloc does not support memory expansion, the base expansion function couldn't be shadowed properly without linker errors. However we want to make sure no instances of it get compiled into the module, ever. Therefore, the duplicate symbol is kept in memoverride (_expand_base), and the only usage has been removed from LZHAM's 'lzham_mem'. If a linkage is attempted to anything utilizing '_expand', a linker error will be emitted and no image will be generated.
2023-07-03 00:25:15 +02:00

292 lines
10 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"
//-----------------------------------------------------------------------------
// 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));
}
//-------------------------------------------------------------------------
// 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* pBlock, size_t nNewSize, int nBlockUse,
const char* const pFileName, int 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)
{
return _msize(pBlock);
}
//-------------------------------------------------------------------------
void* __cdecl _heap_alloc_dbg(size_t nSize, int nBlockUse, const char* szFileName, int nLine)
{
return _malloc_dbg(nSize, nBlockUse, szFileName, nLine);
}
//-------------------------------------------------------------------------
// CRT debug nolocks
//-------------------------------------------------------------------------
void __cdecl _free_nolock(void* pUserData)
{
// I don't think the second param is used in memoverride
_free_dbg(pUserData, 0);
}
void __cdecl _free_dbg_nolock(void* pUserData, int nBlockUse)
{
_free_dbg(pUserData, 0);
}
//-------------------------------------------------------------------------
// 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
}