From ef69611435c3a6d749af45612f3f31beeb8826f7 Mon Sep 17 00:00:00 2001
From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com>
Date: Mon, 26 Jun 2023 22:34:24 +0200
Subject: [PATCH] Replace memalloc calls throughout entire SDK

Global 'direct' usage of 'MemAllocSingleton()' has been jettisoned. Where possible, smart pointers were used instead. During the refactor, the following bugs were addressed and fixed:
- The virtual destructor of 'CCVarIteratorInternal' was NOT called on destruction.
- Class function 'KeyValues::MakeCopy' did NOT calculate the buffer size of the wide string correctly, the original calculation was 'len+1*sizeof(wchar_t)', but should've been '(len+1)*sizeof(wchar_t)'.

Some other code changes include:
- Tier0 include 'memstd.h' has been moved above all thirdparty includes, to make sure the memalloc functions get shadowed with ours in third party libraries as well.
- RPak file paths string literals are now defines.
- 'DestroyOverlay' has been refactored to match the assembly of the game.
---
 r5dev/common/callback.cpp               | 71 +++++++++++-----------
 r5dev/core/stdafx.h                     | 16 +++--
 r5dev/engine/client/client.cpp          |  2 +-
 r5dev/engine/debugoverlay.cpp           | 55 +++++++----------
 r5dev/engine/modelloader.cpp            |  2 +-
 r5dev/game/server/ai_networkmanager.cpp | 19 +++---
 r5dev/game/server/ai_utility.cpp        |  6 +-
 r5dev/networksystem/bansystem.cpp       | 10 ++--
 r5dev/public/icvar.h                    |  2 +
 r5dev/public/tier0/platform.h           | 11 ----
 r5dev/public/tier1/cvar.h               | 10 ++--
 r5dev/rtech/rtech_game.h                |  7 ++-
 r5dev/tier0/memstd.cpp                  | 19 ++++--
 r5dev/tier0/memstd.h                    | 45 +++++---------
 r5dev/tier1/cmd.cpp                     |  2 +-
 r5dev/tier1/cvar.cpp                    | 20 +++----
 r5dev/tier1/utlstring.cpp               |  6 +-
 r5dev/vpc/keyvalues.cpp                 | 80 ++++++++++---------------
 r5dev/vpc/rson.cpp                      |  8 +--
 r5dev/vpklib/packedstore.cpp            | 64 ++++++++++----------
 20 files changed, 207 insertions(+), 248 deletions(-)

diff --git a/r5dev/common/callback.cpp b/r5dev/common/callback.cpp
index 62b90557..5ec7ada3 100644
--- a/r5dev/common/callback.cpp
+++ b/r5dev/common/callback.cpp
@@ -474,32 +474,36 @@ void RTech_Decompress_f(const CCommand& args)
 		return;
 	}
 
-	static const string svModDir = "paks\\Win32\\";
-	static const string svBaseDir = "paks\\Win64\\";
+	CUtlString inPakFile;
+	CUtlString outPakFile;
 
-	const string svPakNameOut = svModDir + args.Arg(1);
-	const string svPakNameIn = svBaseDir + args.Arg(1);
+	inPakFile.Format(PLATFORM_PAK_PATH "%s", args.Arg(1));
+	outPakFile.Format(PLATFORM_PAK_OVERRIDE_PATH "%s", args.Arg(1));
 
 	DevMsg(eDLL_T::RTECH, "______________________________________________________________\n");
 	DevMsg(eDLL_T::RTECH, "-+ RTech decompress ------------------------------------------\n");
 
-	if (!FileSystem()->FileExists(svPakNameIn.c_str(), "GAME"))
+	if (!FileSystem()->FileExists(inPakFile.String(), "GAME"))
 	{
-		Error(eDLL_T::RTECH, NO_ERROR, "%s - pak file '%s' does not exist!\n", __FUNCTION__, svPakNameIn.c_str());
+		Error(eDLL_T::RTECH, NO_ERROR, "%s - pak file '%s' does not exist!\n",
+			__FUNCTION__, inPakFile.String());
 		return;
 	}
 
-	DevMsg(eDLL_T::RTECH, " |-+ Processing: '%s'\n", svPakNameIn.c_str());
-	FileHandle_t hPakFile = FileSystem()->Open(svPakNameIn.c_str(), "rb", "GAME");
+	DevMsg(eDLL_T::RTECH, " |-+ Processing: '%s'\n", inPakFile.String());
+	FileHandle_t hPakFile = FileSystem()->Open(inPakFile.String(), "rb", "GAME");
 
 	if (!hPakFile)
 	{
-		Error(eDLL_T::RTECH, NO_ERROR, "%s - Unable to open '%s' (insufficient rights?)\n", __FUNCTION__, svPakNameIn.c_str());
+		Error(eDLL_T::RTECH, NO_ERROR, "%s - Unable to open '%s' (insufficient rights?)\n",
+			__FUNCTION__, inPakFile.String());
 		return;
 	}
 
 	uint32_t nPakLen = FileSystem()->Size(hPakFile);
-	uint8_t* pPakBuf = MemAllocSingleton()->Alloc<uint8_t>(nPakLen);
+
+	std::unique_ptr<uint8_t[]> pPakBufContainer(new uint8_t[nPakLen]);
+	uint8_t* pPakBuf = pPakBufContainer.get();
 
 	FileSystem()->Read(pPakBuf, nPakLen, hPakFile);
 	FileSystem()->Close(hPakFile);
@@ -514,7 +518,9 @@ void RTech_Decompress_f(const CCommand& args)
 	DevMsg(eDLL_T::RTECH, " |   |-- Magic    : '0x%08X'\n", pHeader->m_nMagic);
 	DevMsg(eDLL_T::RTECH, " |   |-- Version  : '%hu'\n", pHeader->m_nVersion);
 	DevMsg(eDLL_T::RTECH, " |   |-- Flags    : '0x%04hX'\n", flags);
-	DevMsg(eDLL_T::RTECH, " |   |-- Time     : '%hu-%hu-%hu/%hu %hu:%hu:%hu.%hu'\n",systemTime.wYear,systemTime.wMonth,systemTime.wDay, systemTime.wDayOfWeek, systemTime.wHour, systemTime.wMinute, systemTime.wSecond, systemTime.wMilliseconds);
+	DevMsg(eDLL_T::RTECH, " |   |-- Time     : '%hu-%hu-%hu/%hu %hu:%hu:%hu.%hu'\n",
+		systemTime.wYear,systemTime.wMonth,systemTime.wDay, systemTime.wDayOfWeek,
+		systemTime.wHour, systemTime.wMinute, systemTime.wSecond, systemTime.wMilliseconds);
 	DevMsg(eDLL_T::RTECH, " |   |-- Hash     : '0x%08llX'\n", pHeader->m_nHash);
 	DevMsg(eDLL_T::RTECH, " |   |-- Entries  : '%u'\n", pHeader->m_nAssetEntryCount);
 	DevMsg(eDLL_T::RTECH, " |   |-+ Compression -----------------------------------------\n");
@@ -523,22 +529,22 @@ void RTech_Decompress_f(const CCommand& args)
 
 	if (pHeader->m_nMagic != RPAK_MAGIC)
 	{
-		Error(eDLL_T::RTECH, NO_ERROR, "%s - pak file '%s' has invalid magic!\n", __FUNCTION__, svPakNameIn.c_str());
-		MemAllocSingleton()->Free(pPakBuf);
+		Error(eDLL_T::RTECH, NO_ERROR, "%s - pak file '%s' has invalid magic!\n",
+			__FUNCTION__, inPakFile.String());
 
 		return;
 	}
 	if ((pHeader->m_nFlags[1] & 1) != 1)
 	{
-		Error(eDLL_T::RTECH, NO_ERROR, "%s - pak file '%s' already decompressed!\n", __FUNCTION__, svPakNameIn.c_str());
-		MemAllocSingleton()->Free(pPakBuf);
+		Error(eDLL_T::RTECH, NO_ERROR, "%s - pak file '%s' already decompressed!\n",
+			__FUNCTION__, inPakFile.String());
 
 		return;
 	}
 	if (pHeader->m_nSizeDisk != nPakLen)
 	{
-		Error(eDLL_T::RTECH, NO_ERROR, "%s - pak file '%s' decompressed size '%llu' doesn't match expected size '%llu'!\n", __FUNCTION__, svPakNameIn.c_str(), nPakLen, pHeader->m_nSizeMemory);
-		MemAllocSingleton()->Free(pPakBuf);
+		Error(eDLL_T::RTECH, NO_ERROR, "%s - pak file '%s' decompressed size '%llu' doesn't match expected size '%llu'!\n",
+			__FUNCTION__, inPakFile.String(), nPakLen, pHeader->m_nSizeMemory);
 
 		return;
 	}
@@ -548,8 +554,8 @@ void RTech_Decompress_f(const CCommand& args)
 
 	if (nDecompSize == pHeader->m_nSizeDisk)
 	{
-		Error(eDLL_T::RTECH, NO_ERROR, "%s - calculated size: '%llu' expected: '%llu'!\n", __FUNCTION__, nDecompSize, pHeader->m_nSizeMemory);
-		MemAllocSingleton()->Free(pPakBuf);
+		Error(eDLL_T::RTECH, NO_ERROR, "%s - calculated size: '%llu' expected: '%llu'!\n",
+			__FUNCTION__, nDecompSize, pHeader->m_nSizeMemory);
 
 		return;
 	}
@@ -559,7 +565,10 @@ void RTech_Decompress_f(const CCommand& args)
 	}
 
 	DevMsg(eDLL_T::RTECH, " |     |-- Ratio    : '%.02f'\n", (pHeader->m_nSizeDisk * 100.f) / pHeader->m_nSizeMemory);
-	uint8_t* pDecompBuf = MemAllocSingleton()->Alloc<uint8_t>(pHeader->m_nSizeMemory);
+
+
+	std::unique_ptr<uint8_t[]> pDecompBufContainer(new uint8_t[nPakLen]);
+	uint8_t* pDecompBuf = pDecompBufContainer.get();
 
 	decompState.m_nOutMask = UINT64_MAX;
 	decompState.m_nOut = uint64_t(pDecompBuf);
@@ -567,25 +576,20 @@ void RTech_Decompress_f(const CCommand& args)
 	uint8_t nDecompResult = g_pRTech->DecompressPakFile(&decompState, nPakLen, pHeader->m_nSizeMemory);
 	if (nDecompResult != 1)
 	{
-		Error(eDLL_T::RTECH, NO_ERROR, "%s - decompression failed for '%s' return value: '%hu'!\n", __FUNCTION__, svPakNameIn.c_str(), nDecompResult);
-		MemAllocSingleton()->Free(pPakBuf);
-		MemAllocSingleton()->Free(pDecompBuf);
-
-		return;
+		Error(eDLL_T::RTECH, NO_ERROR, "%s - decompression failed for '%s' return value: '%hu'!\n",
+			__FUNCTION__, inPakFile.String(), nDecompResult);
 	}
 
 	pHeader->m_nFlags[1] = 0x0; // Set compressed flag to false for the decompressed pak file.
 	pHeader->m_nSizeDisk = pHeader->m_nSizeMemory; // Equal compressed size with decompressed.
 
-	FileSystem()->CreateDirHierarchy(svModDir.c_str(), "GAME");
-	FileHandle_t hDecompFile = FileSystem()->Open(svPakNameOut.c_str(), "wb", "GAME");
+	FileSystem()->CreateDirHierarchy(PLATFORM_PAK_OVERRIDE_PATH, "GAME");
+	FileHandle_t hDecompFile = FileSystem()->Open(outPakFile.String(), "wb", "GAME");
 
 	if (!hDecompFile)
 	{
-		Error(eDLL_T::RTECH, NO_ERROR, "%s - Unable to write to '%s' (read-only?)\n", __FUNCTION__, svPakNameOut.c_str());
-
-		MemAllocSingleton()->Free(pPakBuf);
-		MemAllocSingleton()->Free(pDecompBuf);
+		Error(eDLL_T::RTECH, NO_ERROR, "%s - Unable to write to '%s' (read-only?)\n",
+			__FUNCTION__, outPakFile.String());
 
 		return;
 	}
@@ -609,12 +613,9 @@ void RTech_Decompress_f(const CCommand& args)
 	FileSystem()->Write(pDecompBuf, int(decompState.m_nDecompSize), hDecompFile);
 
 	DevMsg(eDLL_T::RTECH, " |-- Checksum : '0x%08X'\n", crc32::update(NULL, pDecompBuf, decompState.m_nDecompSize));
-	DevMsg(eDLL_T::RTECH, "-+ Decompressed pak file to: '%s'\n", svPakNameOut.c_str());
+	DevMsg(eDLL_T::RTECH, "-+ Decompressed pak file to: '%s'\n", outPakFile.String());
 	DevMsg(eDLL_T::RTECH, "--------------------------------------------------------------\n");
 
-	MemAllocSingleton()->Free(pPakBuf);
-	MemAllocSingleton()->Free(pDecompBuf);
-
 	FileSystem()->Close(hDecompFile);
 }
 
diff --git a/r5dev/core/stdafx.h b/r5dev/core/stdafx.h
index 01dc4030..bcb3b0c8 100644
--- a/r5dev/core/stdafx.h
+++ b/r5dev/core/stdafx.h
@@ -1,8 +1,14 @@
 #pragma once
 #include "shared_pch.h"
-#if !defined(DEDICATED) && !defined (NETCONSOLE) && !defined(PLUGINSDK)
+#if !defined(DEDICATED) && !defined(PLUGINSDK)
 #include <d3d11.h>
-#endif // !DEDICATED && !NETCONSOLE && !PLUGINSDK
+#endif // !DEDICATED && !PLUGINSDK
+
+// Must be included before any third party lib!
+// this header replaces the standard new/delete
+// operators with our own, along with the standard
+// malloc/free functions.
+#include "tier0/memstd.h"
 
 // Thirdparty includes.
 #include "thirdparty/detours/include/detours.h"
@@ -15,7 +21,7 @@
 #include "thirdparty/curl/include/curl/curl.h"
 #include "thirdparty/nlohmann/json.hpp"
 
-#if !defined(DEDICATED) && !defined (NETCONSOLE) && !defined(PLUGINSDK)
+#if !defined(DEDICATED) && !defined(PLUGINSDK)
 #include "thirdparty/imgui/imgui.h"
 #include "thirdparty/imgui/imgui_internal.h"
 #include "thirdparty/imgui/misc/imgui_logger.h"
@@ -24,7 +30,7 @@
 #include "thirdparty/imgui/misc/cpp/imgui_stdlib.h"
 #include "thirdparty/imgui/backends/imgui_impl_dx11.h"
 #include "thirdparty/imgui/backends/imgui_impl_win32.h"
-#endif // !DEDICATED && !NETCONSOLE && !PLUGINSDK
+#endif // !DEDICATED && !PLUGINSDK
 
 
 #pragma warning(push)
@@ -40,8 +46,8 @@
 #pragma warning(pop)
 
 // Tier0 includes.
-#include "tier0/utility.h"
 #include "tier0/memaddr.h"
+#include "tier0/utility.h"
 #include "tier0/module.h"
 #include "tier0/basetypes.h"
 #include "tier0/platform.h"
diff --git a/r5dev/engine/client/client.cpp b/r5dev/engine/client/client.cpp
index 42306162..038f23a9 100644
--- a/r5dev/engine/client/client.cpp
+++ b/r5dev/engine/client/client.cpp
@@ -298,7 +298,7 @@ void CClient::Disconnect(const Reputation_t nRepLvl, const char* szReason, ...)
 	{
 		char szBuf[1024];
 		{/////////////////////////////
-			va_list vArgs{};
+			va_list vArgs;
 			va_start(vArgs, szReason);
 
 			vsnprintf(szBuf, sizeof(szBuf), szReason, vArgs);
diff --git a/r5dev/engine/debugoverlay.cpp b/r5dev/engine/debugoverlay.cpp
index 1be55801..4bfa3b78 100644
--- a/r5dev/engine/debugoverlay.cpp
+++ b/r5dev/engine/debugoverlay.cpp
@@ -66,45 +66,30 @@ bool OverlayBase_t::IsDead() const
 //------------------------------------------------------------------------------
 void DestroyOverlay(OverlayBase_t* pOverlay)
 {
-    size_t pOverlaySize;
-
-    EnterCriticalSection(&*s_OverlayMutex);
+    EnterCriticalSection(s_OverlayMutex);
     switch (pOverlay->m_Type)
     {
     case OverlayType_t::OVERLAY_BOX:
-        pOverlaySize = sizeof(OverlayBox_t);
-        goto LABEL_MALLOC;
     case OverlayType_t::OVERLAY_SPHERE:
-        pOverlaySize = sizeof(OverlaySphere_t);
-        goto LABEL_MALLOC;
     case OverlayType_t::OVERLAY_LINE:
-        pOverlaySize = sizeof(OverlayLine_t);
-        goto LABEL_MALLOC;
     case OverlayType_t::OVERLAY_TRIANGLE:
-        pOverlaySize = 6200i64;
-        goto LABEL_MALLOC;
-    case OverlayType_t::OVERLAY_LASER_LINE:
-        pOverlay->m_Type = OverlayType_t::OVERLAY_UNK1;
-        LeaveCriticalSection(&*s_OverlayMutex);
-        return;
     case OverlayType_t::OVERLAY_BOX2:
-        pOverlaySize = 88i64;
-        goto LABEL_MALLOC;
     case OverlayType_t::OVERLAY_CAPSULE:
-        pOverlaySize = sizeof(OverlayCapsule_t);
-        break;
     case OverlayType_t::OVERLAY_UNK0:
-        pOverlaySize = 88i64;
-        goto LABEL_MALLOC;
-    LABEL_MALLOC:
-        pOverlay->m_Type = OverlayType_t::OVERLAY_UNK1;
-        MemAllocSingleton()->Free(pOverlay);
+        delete pOverlay;
+        break;
+        // The laser line overlay, used for the smart pistol's guidance
+        // line, appears to be not deleted in this particular function.
+        // Its unclear whether or not something else takes care of this,
+        // research needed!!!
+    case OverlayType_t::OVERLAY_LASER_LINE:
         break;
     default:
+        Assert(0); // Code bug; invalid overlay type.
         break;
     }
 
-    LeaveCriticalSection(&*s_OverlayMutex);
+    LeaveCriticalSection(s_OverlayMutex);
 }
 
 //------------------------------------------------------------------------------
@@ -113,7 +98,7 @@ void DestroyOverlay(OverlayBase_t* pOverlay)
 //------------------------------------------------------------------------------
 void DrawOverlay(OverlayBase_t* pOverlay)
 {
-    EnterCriticalSection(&*s_OverlayMutex);
+    EnterCriticalSection(s_OverlayMutex);
 
     switch (pOverlay->m_Type)
     {
@@ -128,7 +113,7 @@ void DrawOverlay(OverlayBase_t* pOverlay)
             }
             else
             {
-                LeaveCriticalSection(&*s_OverlayMutex);
+                LeaveCriticalSection(s_OverlayMutex);
                 return;
             }
         }
@@ -147,7 +132,7 @@ void DrawOverlay(OverlayBase_t* pOverlay)
             }
             else
             {
-                LeaveCriticalSection(&*s_OverlayMutex);
+                LeaveCriticalSection(s_OverlayMutex);
                 return;
             }
         }
@@ -174,7 +159,7 @@ void DrawOverlay(OverlayBase_t* pOverlay)
             }
             else
             {
-                LeaveCriticalSection(&*s_OverlayMutex);
+                LeaveCriticalSection(s_OverlayMutex);
                 return;
             }
         }
@@ -209,7 +194,7 @@ void DrawOverlay(OverlayBase_t* pOverlay)
             }
             else
             {
-                LeaveCriticalSection(&*s_OverlayMutex);
+                LeaveCriticalSection(s_OverlayMutex);
                 return;
             }
         }
@@ -235,7 +220,7 @@ void DrawOverlay(OverlayBase_t* pOverlay)
     }
     }
 
-    LeaveCriticalSection(&*s_OverlayMutex);
+    LeaveCriticalSection(s_OverlayMutex);
 }
 
 //------------------------------------------------------------------------------
@@ -244,7 +229,7 @@ void DrawOverlay(OverlayBase_t* pOverlay)
 //------------------------------------------------------------------------------
 void DrawAllOverlays(bool bRender)
 {
-    EnterCriticalSection(&*s_OverlayMutex);
+    EnterCriticalSection(s_OverlayMutex);
 
     const bool bOverlayEnabled = (bRender && enable_debug_overlays->GetBool());
     OverlayBase_t* pCurrOverlay = *s_pOverlays; // rdi
@@ -272,7 +257,8 @@ void DrawAllOverlays(bool bRender)
         }
         else
         {
-            bool bShouldDraw{ };
+            bool bShouldDraw = false;
+
             if (pCurrOverlay->m_nCreationTick == -1)
             {
                 if (pCurrOverlay->m_nOverlayTick == *g_nOverlayTickCount)
@@ -297,6 +283,7 @@ void DrawAllOverlays(bool bRender)
                     DrawOverlay(pCurrOverlay);
                 }
             }
+
             pPrevOverlay = pCurrOverlay;
             pCurrOverlay = pCurrOverlay->m_pNextOverlay;
         }
@@ -318,7 +305,7 @@ void DrawAllOverlays(bool bRender)
     }
 #endif // !CLIENT_DLL
 
-    LeaveCriticalSection(&*s_OverlayMutex);
+    LeaveCriticalSection(s_OverlayMutex);
 }
 
 ///////////////////////////////////////////////////////////////////////////////
diff --git a/r5dev/engine/modelloader.cpp b/r5dev/engine/modelloader.cpp
index 22661bad..b80e22b4 100644
--- a/r5dev/engine/modelloader.cpp
+++ b/r5dev/engine/modelloader.cpp
@@ -274,7 +274,7 @@ void CMapLoadHelper::Constructor(CMapLoadHelper* loader, int lumpToLoad)
 		}
 		else
 		{
-			loader->m_pRawData = MemAllocSingleton()->Alloc<byte>(lumpSize);
+			loader->m_pRawData = new byte[lumpSize];
 			loader->m_pData = loader->m_pRawData;
 
 			FileHandle_t hLumpFile = FileSystem()->Open(lumpPathBuf, "rb");
diff --git a/r5dev/game/server/ai_networkmanager.cpp b/r5dev/game/server/ai_networkmanager.cpp
index ca51deff..3591d0a2 100644
--- a/r5dev/game/server/ai_networkmanager.cpp
+++ b/r5dev/game/server/ai_networkmanager.cpp
@@ -73,13 +73,12 @@ void CAI_NetworkBuilder::SaveNetworkGraph(CAI_Network* pNetwork)
 	else
 	{
 		uint32_t nLen = FileSystem()->Size(pNavMesh);
-		uint8_t* pBuf = MemAllocSingleton()->Alloc<uint8_t>(nLen);
+		std::unique_ptr<uint8_t[]> pBuf(new uint8_t[nLen]);
 
-		FileSystem()->Read(pBuf, nLen, pNavMesh);
+		FileSystem()->Read(pBuf.get(), nLen, pNavMesh);
 		FileSystem()->Close(pNavMesh);
 
-		nNavMeshHash = crc32::update(NULL, pBuf, nLen);
-		MemAllocSingleton()->Free(pBuf);
+		nNavMeshHash = crc32::update(NULL, pBuf.get(), nLen);
 	}
 
 	// Large NavMesh CRC.
@@ -183,11 +182,10 @@ void CAI_NetworkBuilder::SaveNetworkGraph(CAI_Network* pNetwork)
 
 	if (pNetwork->m_iNumNodes > 0)
 	{
-		uint32_t* unkNodeBlock = MemAllocSingleton()->Alloc<uint32_t>(pNetwork->m_iNumNodes * sizeof(uint32_t));
+		std::unique_ptr<uint32[]> unkNodeBlock(new uint32_t[pNetwork->m_iNumNodes * sizeof(uint32_t)]);
 		memset(&unkNodeBlock, '\0', pNetwork->m_iNumNodes * sizeof(uint32_t));
 
-		FileSystem()->Write(&*unkNodeBlock, pNetwork->m_iNumNodes * sizeof(uint32_t), pAIGraph);
-		MemAllocSingleton()->Free(unkNodeBlock);
+		FileSystem()->Write(unkNodeBlock.get(), pNetwork->m_iNumNodes * sizeof(uint32_t), pAIGraph);
 	}
 
 	// TODO: This is traverse nodes i think? these aren't used in r2 ains so we can get away with just writing count=0 and skipping
@@ -328,13 +326,12 @@ void CAI_NetworkManager::LoadNetworkGraph(CAI_NetworkManager* pAINetworkManager,
 	else
 	{
 		uint32_t nLen = FileSystem()->Size(pNavMesh);
-		uint8_t* pBuf = MemAllocSingleton()->Alloc<uint8_t>(nLen);
+		std::unique_ptr<uint8_t[]> pBuf(new uint8_t[nLen]);
 
-		FileSystem()->Read(pBuf, nLen, pNavMesh);
+		FileSystem()->Read(pBuf.get(), nLen, pNavMesh);
 		FileSystem()->Close(pNavMesh);
 
-		nNavMeshHash = crc32::update(NULL, pBuf, nLen);
-		MemAllocSingleton()->Free(pBuf);
+		nNavMeshHash = crc32::update(NULL, pBuf.get(), nLen);
 	}
 
 	FileHandle_t pAIGraph = FileSystem()->Open(szGraphPath, "rb", "GAME");
diff --git a/r5dev/game/server/ai_utility.cpp b/r5dev/game/server/ai_utility.cpp
index 5909e7fb..e85bb44b 100644
--- a/r5dev/game/server/ai_utility.cpp
+++ b/r5dev/game/server/ai_utility.cpp
@@ -39,8 +39,10 @@ void ClearNavMeshForHull(int hullSize)
 
     if (nav) // Only free if NavMesh for hull is loaded.
     {
-        v_Detour_FreeNavMesh(nav);      // Frees tiles, polys, tris, etc.
-        MemAllocSingleton()->Free(nav); // Frees the main navmesh memory.
+        // Frees tiles, polys, tris, anything dynamically
+        // allocated for this navmesh, and the navmesh itself.
+        v_Detour_FreeNavMesh(nav);
+        delete nav;
 
         g_pNavMesh[hullSize] = nullptr;
     }
diff --git a/r5dev/networksystem/bansystem.cpp b/r5dev/networksystem/bansystem.cpp
index 95632fa2..31359749 100644
--- a/r5dev/networksystem/bansystem.cpp
+++ b/r5dev/networksystem/bansystem.cpp
@@ -24,16 +24,16 @@ void CBanSystem::Load(void)
 		return;
 
 	uint32_t nLen = FileSystem()->Size(pFile);
-	char* pBuf = MemAllocSingleton()->Alloc<char>(nLen + 1);
+	std::unique_ptr<char[]> pBuf(new char[nLen + 1]);
 
-	int nRead = FileSystem()->Read(pBuf, nLen, pFile);
+	int nRead = FileSystem()->Read(pBuf.get(), nLen, pFile);
 	FileSystem()->Close(pFile);
 
-	pBuf[nRead] = '\0'; // Null terminate the string buffer containing our banned list.
+	pBuf.get()[nRead] = '\0'; // Null terminate the string buffer containing our banned list.
 
 	try
 	{
-		nlohmann::json jsIn = nlohmann::json::parse(pBuf);
+		nlohmann::json jsIn = nlohmann::json::parse(pBuf.get());
 
 		size_t nTotalBans = 0;
 		if (!jsIn.is_null())
@@ -58,8 +58,6 @@ void CBanSystem::Load(void)
 	{
 		Warning(eDLL_T::SERVER, "%s: Exception while parsing banned list:\n%s\n", __FUNCTION__, ex.what());
 	}
-
-	MemAllocSingleton()->Free(pBuf);
 }
 
 //-----------------------------------------------------------------------------
diff --git a/r5dev/public/icvar.h b/r5dev/public/icvar.h
index d422f79b..6855c897 100644
--- a/r5dev/public/icvar.h
+++ b/r5dev/public/icvar.h
@@ -112,6 +112,8 @@ protected:
 	class ICVarIteratorInternal
 	{
 	public:
+		virtual ~ICVarIteratorInternal(void) { }
+
 		virtual void            SetFirst(void) = 0;
 		virtual void            Next(void) = 0;
 		virtual bool            IsValid(void) = 0;
diff --git a/r5dev/public/tier0/platform.h b/r5dev/public/tier0/platform.h
index af4aaeb9..3608e5da 100644
--- a/r5dev/public/tier0/platform.h
+++ b/r5dev/public/tier0/platform.h
@@ -429,20 +429,9 @@ inline int64 CastPtrToInt64(const void* p)
 // Stack-based allocation related helpers
 //-----------------------------------------------------------------------------
 #if defined( COMPILER_GCC ) || defined( COMPILER_SNC )
-
 #define stackalloc( _size )		alloca( ALIGN_VALUE( _size, 16 ) )
-
-#ifdef PLATFORM_OSX
-#define mallocsize( _p )	( malloc_size( _p ) )
-#else
-#define mallocsize( _p )	( malloc_usable_size( _p ) )
-#endif
-
 #elif defined ( COMPILER_MSVC )
-
 #define stackalloc( _size )		_alloca( ALIGN_VALUE( _size, 16 ) )
-#define mallocsize( _p )		( _msize( _p ) )
-
 #endif
 
 #define stackalloc_aligned( _size, _align )		(void*)( ( ((uintp)alloca( ALIGN_VALUE( ( _size ) + (_align ),  ( _align ) ) )) + ( _align ) ) & ~_align )
diff --git a/r5dev/public/tier1/cvar.h b/r5dev/public/tier1/cvar.h
index 0a064c48..10adc300 100644
--- a/r5dev/public/tier1/cvar.h
+++ b/r5dev/public/tier1/cvar.h
@@ -88,10 +88,12 @@ protected:
 	class CCVarIteratorInternal : public ICVarIteratorInternal
 	{
 	public:
-		virtual void            SetFirst(void) = 0; //0
-		virtual void            Next(void) = 0; //1
-		virtual	bool            IsValid(void) = 0; //2
-		virtual ConCommandBase* Get(void) = 0; //3
+		virtual ~CCVarIteratorInternal() { }
+
+		virtual void            SetFirst(void) = 0;
+		virtual void            Next(void) = 0;
+		virtual	bool            IsValid(void) = 0;
+		virtual ConCommandBase* Get(void) = 0;
 
 		CCvar* const m_pOuter = nullptr;
 		CConCommandHash* const m_pHash = nullptr;
diff --git a/r5dev/rtech/rtech_game.h b/r5dev/rtech/rtech_game.h
index ecb3b7f8..2613093e 100644
--- a/r5dev/rtech/rtech_game.h
+++ b/r5dev/rtech/rtech_game.h
@@ -1,9 +1,12 @@
 #pragma once
 #include "tier0/tslist.h"
 
-typedef int RPakHandle_t;
-constexpr int INVALID_PAK_HANDLE = -1;
+#define PLATFORM_PAK_PATH "paks\\Win64\\"
+#define PLATFORM_PAK_OVERRIDE_PATH "paks\\Win32\\"
 
+#define INVALID_PAK_HANDLE -1
+
+typedef int RPakHandle_t;
 enum class ePakStatus : int
 {
 	PAK_STATUS_FREED = 0,
diff --git a/r5dev/tier0/memstd.cpp b/r5dev/tier0/memstd.cpp
index 7d4361b4..0092331a 100644
--- a/r5dev/tier0/memstd.cpp
+++ b/r5dev/tier0/memstd.cpp
@@ -33,7 +33,7 @@ extern "C" void* R_malloc(size_t nSize)
 {
     Assert(nSize);
     InitAllocator();
-    return MemAllocSingleton()->Alloc<void>(nSize);
+    return MemAllocSingleton()->Alloc(nSize);
 }
 
 extern "C" void R_free(void* pBlock)
@@ -50,10 +50,10 @@ extern "C" void* R_realloc(void* pBlock, size_t nSize)
     InitAllocator();
 
     if (nSize)
-        return MemAllocSingleton()->Realloc<void>(pBlock, nSize);
+        return MemAllocSingleton()->Realloc(pBlock, nSize);
     else
     {
-        MemAllocSingleton()->FreeDbg(pBlock, "tier0_static128", 0);
+        MemAllocSingleton()->InternalFree(pBlock, "tier0_static128", 0);
         return nullptr;
     }
 }
@@ -65,7 +65,7 @@ extern "C" char* R_strdup(const char* pString)
     InitAllocator();
 
     const size_t nLen = strlen(pString) + 1;
-    void* pNew = MemAllocSingleton()->Alloc<char>(nLen);
+    void* pNew = MemAllocSingleton()->Alloc(nLen);
 
     if (!pNew)
         return nullptr;
@@ -80,12 +80,21 @@ extern "C" void* R_calloc(size_t nCount, size_t nSize)
     InitAllocator();
 
     const size_t nTotal = nCount * nSize;
-    void* pNew = MemAllocSingleton()->Alloc<void>(nTotal);
+    void* pNew = MemAllocSingleton()->Alloc(nTotal);
 
     memset(pNew, NULL, nTotal);
     return pNew;
 }
 
+
+extern "C" size_t R_mallocsize(void* pBlock)
+{
+    InitAllocator();
+    size_t nSize = MemAllocSingleton()->GetSize(pBlock);
+    return nSize;
+}
+
+
 // !TODO: other 'new' operators introduced in C++17.
 void* operator new(std::size_t n) noexcept(false)
 {
diff --git a/r5dev/tier0/memstd.h b/r5dev/tier0/memstd.h
index e8a824be..3c9c56db 100644
--- a/r5dev/tier0/memstd.h
+++ b/r5dev/tier0/memstd.h
@@ -6,6 +6,7 @@ extern "C" void  R_free(void* pBlock);
 extern "C" void* R_realloc(void* pBlock, size_t nSize);
 extern "C" char* R_strdup(const char* pString);
 extern "C" void* R_calloc(size_t nCount, size_t nSize);
+extern "C" size_t R_mallocsize(void* pBlock);
 
 // Shadow standard implementation with ours.
 #define malloc(nSize) R_malloc(nSize)
@@ -13,40 +14,24 @@ extern "C" void* R_calloc(size_t nCount, size_t nSize);
 #define realloc(pBlock, nSize) R_realloc(pBlock, nSize)
 #define strdup(pString) R_strdup(pString)
 #define calloc(nCount, nSize) R_calloc(nCount, nSize)
+#define mallocsize(pBlock) R_mallocsize(pBlock)
 
 class IMemAlloc
 {
 public:
-	template<typename T>
-	inline T* Alloc(size_t nSize)
-	{
-		const static int index = 1;
-		return CallVFunc<T*>(index, this, nSize);
-	}
-	template<typename T>
-	inline T* Realloc(T* pMem, size_t nSize)
-	{
-		const static int index = 3;
-		return CallVFunc<T*>(index, this, pMem, nSize);
-	}
-	template<typename T>
-	inline void FreeDbg(T* pMem, const char* pFileName, int nLine)
-	{
-		const static int index = 4; // Same as free, but takes debug parameters.
-		CallVFunc<void>(index, this, pMem, pFileName, nLine);
-	}
-	template<typename T>
-	inline void Free(T* pMem)
-	{
-		const static int index = 5;
-		CallVFunc<void>(index, this, pMem);
-	}
-	template<typename T>
-	inline size_t GetSize(T* pMem)
-	{
-		const static int index = 6;
-		return CallVFunc<size_t>(index, this, pMem);
-	}
+	// Same functions internally.
+	virtual void* InternalAlloc(size_t nSize/*, const char* pFileName, int nLine*/) = 0;
+	virtual void* Alloc(size_t nSize) = 0;
+
+	// Same functions internally.
+	virtual void* InternalRealloc(void* pMem, size_t nSize/*, const char* pFileName, int nLine*/) = 0;
+	virtual void* Realloc(void* pMem, size_t nSize) = 0;
+
+	// Same as Free, but takes debug parameters.
+	virtual void  InternalFree(void* pMem, const char* pFileName, int nLine) = 0;
+	virtual void  Free(void* pMem) = 0;
+
+	virtual size_t GetSize(void* pMem) = 0;
 };
 
 //-----------------------------------------------------------------------------
diff --git a/r5dev/tier1/cmd.cpp b/r5dev/tier1/cmd.cpp
index ba7b7664..099287b2 100644
--- a/r5dev/tier1/cmd.cpp
+++ b/r5dev/tier1/cmd.cpp
@@ -274,7 +274,7 @@ void CCommand::Reset()
 ConCommand* ConCommand::StaticCreate(const char* pszName, const char* pszHelpString, const char* pszUsageString,
 	int nFlags, FnCommandCallback_t pCallback, FnCommandCompletionCallback pCompletionFunc)
 {
-	ConCommand* pCommand = MemAllocSingleton()->Alloc<ConCommand>(sizeof(ConCommand));
+	ConCommand* pCommand = (ConCommand*)malloc(sizeof(ConCommand));
 	*(ConCommandBase**)pCommand = g_pConCommandVFTable;
 
 	pCommand->m_pNext = nullptr;
diff --git a/r5dev/tier1/cvar.cpp b/r5dev/tier1/cvar.cpp
index fbcdd0b7..e1dd5cce 100644
--- a/r5dev/tier1/cvar.cpp
+++ b/r5dev/tier1/cvar.cpp
@@ -13,7 +13,7 @@ ConVar* ConVar::StaticCreate(const char* pszName, const char* pszDefaultValue,
 	int nFlags, const char* pszHelpString, bool bMin, float fMin, bool bMax,
 	float fMax, FnChangeCallback_t pCallback, const char* pszUsageString)
 {
-	ConVar* pNewConVar = MemAllocSingleton()->Alloc<ConVar>(sizeof(ConVar));
+	ConVar* pNewConVar = (ConVar*)malloc(sizeof(ConVar));
 
 	pNewConVar->m_bRegistered = false;
 	*(ConVar**)pNewConVar = g_pConVarVBTable;
@@ -66,7 +66,7 @@ ConVar::ConVar(void)
 //{
 //	if (m_Value.m_pszString)
 //	{
-//		MemAllocSingleton()->Free(m_Value.m_pszString);
+//		delete[] m_Value.m_pszString);
 //		m_Value.m_pszString = NULL;
 //	}
 //}
@@ -329,10 +329,10 @@ void ConVar::ChangeStringValue(const char* pszTempVal)
 	{
 		if (m_Value.m_pszString)
 		{
-			MemAllocSingleton()->Free(m_Value.m_pszString);
+			delete[] m_Value.m_pszString;
 		}
 
-		m_Value.m_pszString = MemAllocSingleton()->Alloc<char>(len);
+		m_Value.m_pszString = new char[len];
 		m_Value.m_iStringLength = len;
 	}
 
@@ -737,7 +737,7 @@ int CCvarUtilities::CountVariablesWithFlags(int flags)
 		}
 	}
 
-	MemAllocSingleton()->Free(itint);
+	delete itint;
 	return i;
 }
 
@@ -756,7 +756,7 @@ void CCvarUtilities::EnableDevCvars()
 		pCommandBase->RemoveFlags(FCVAR_DEVELOPMENTONLY);
 	}
 
-	MemAllocSingleton()->Free(itint);
+	delete itint;
 }
 
 //-----------------------------------------------------------------------------
@@ -844,7 +844,7 @@ void CCvarUtilities::CvarList(const CCommand& args)
 		}
 	}
 
-	MemAllocSingleton()->Free(itint);
+	delete itint;
 
 	if (bLogging)
 	{
@@ -940,7 +940,7 @@ void CCvarUtilities::CvarDifferences(const CCommand& args)
 		}
 	}
 
-	MemAllocSingleton()->Free(itint);
+	delete itint;
 	DevMsg(eDLL_T::ENGINE, "--------------\n%3i changed convars\n", i);
 }
 
@@ -987,7 +987,7 @@ void CCvarUtilities::CvarFindFlags_f(const CCommand& args)
 		}
 	}
 
-	MemAllocSingleton()->Free(itint);
+	delete itint;
 }
 
 //-----------------------------------------------------------------------------
@@ -1049,7 +1049,7 @@ unordered_map<string, ConCommandBase*> CCvar::DumpToMap(void)
 		allConVars[pszCommandName] = pCommand;
 	}
 
-	MemAllocSingleton()->Free(itint);
+	delete itint;
 
 	return allConVars;
 }
diff --git a/r5dev/tier1/utlstring.cpp b/r5dev/tier1/utlstring.cpp
index 14b9fc5c..e1c8c68d 100644
--- a/r5dev/tier1/utlstring.cpp
+++ b/r5dev/tier1/utlstring.cpp
@@ -868,7 +868,7 @@ char *CUtlStringBuilder::InternalPrepareBuffer(size_t nChars, bool bCopyOld, siz
 			if (bCopyOld)
 				memcpy(pszString, pszOldString, nChars); // null will be added at end of func.
 
-			MemAllocSingleton()->Free(pszOldString);
+			free(pszOldString);
 		}
 	}
 
@@ -950,7 +950,7 @@ size_t CUtlStringBuilder::ReplaceInternal(const char *pstrTarget, const char *ps
 				char *pstrNew;
 				if (nNewLength > Capacity())
 				{
-					pstrNew = MemAllocSingleton()->Alloc<char>(nNewLength + 1);
+					pstrNew = (char*)malloc(nNewLength + 1);
 					if (!pstrNew)
 					{
 						SetError();
@@ -1203,7 +1203,7 @@ bool CUtlStringBuilder::Data::MoveToHeap()
 	{
 		// try to recover the string at the point of failure, to help with debugging
 		size_t nLen = Length();
-		char *pszHeapString = MemAllocSingleton()->Alloc<char>(nLen + 1);
+		char* pszHeapString = (char*)malloc(nLen + 1);
 		if (pszHeapString)
 		{
 			// get the string copy before corrupting the stack union
diff --git a/r5dev/vpc/keyvalues.cpp b/r5dev/vpc/keyvalues.cpp
index 11553720..6bcec04e 100644
--- a/r5dev/vpc/keyvalues.cpp
+++ b/r5dev/vpc/keyvalues.cpp
@@ -146,7 +146,7 @@ void KeyValues::Init(void)
 //-----------------------------------------------------------------------------
 void KeyValues::Clear(void)
 {
-	MemAllocSingleton()->Free(m_pSub);
+	delete m_pSub;
 	m_pSub = nullptr;
 	m_iDataType = TYPE_NONE;
 }
@@ -157,8 +157,7 @@ void KeyValues::Clear(void)
 //-----------------------------------------------------------------------------
 void KeyValues::DeleteThis(void)
 {
-	this->~KeyValues();
-	MemAllocSingleton()->Free(this);
+	delete this;
 }
 
 //-----------------------------------------------------------------------------
@@ -172,19 +171,19 @@ void KeyValues::RemoveEverything(void)
 	{
 		datNext = dat->m_pPeer;
 		dat->m_pPeer = nullptr;
-		MemAllocSingleton()->Free(dat);
+		delete dat;
 	}
 
 	for (dat = m_pPeer; dat && dat != this; dat = datNext)
 	{
 		datNext = dat->m_pPeer;
 		dat->m_pPeer = nullptr;
-		MemAllocSingleton()->Free(dat);
+		delete dat;
 	}
 
-	MemAllocSingleton()->Free(m_sValue);
+	delete[] m_sValue;
 	m_sValue = nullptr;
-	MemAllocSingleton()->Free(m_wsValue);
+	delete[] m_wsValue;
 	m_wsValue = nullptr;
 }
 
@@ -387,7 +386,7 @@ void KeyValues::ElideSubKey(KeyValues* pSubKey)
 			{
 				// No children, simply remove the key
 				*ppPointerToFix = pSubKey->m_pPeer;
-				MemAllocSingleton()->Free(pSubKey);
+				delete pSubKey;
 			}
 			else
 			{
@@ -403,7 +402,7 @@ void KeyValues::ElideSubKey(KeyValues* pSubKey)
 				// Detach the node to be elided
 				pSubKey->m_pSub = nullptr;
 				pSubKey->m_pPeer = nullptr;
-				MemAllocSingleton()->Free(pSubKey);
+				delete pSubKey;
 			}
 			return;
 		}
@@ -753,18 +752,18 @@ const wchar_t* KeyValues::GetWString(const char* pszKeyName, const wchar_t* pwsz
 		case TYPE_STRING:
 		{
 			size_t bufSize = strlen(pKey->m_sValue) + 1;
-			wchar_t* pWBuf = MemAllocSingleton()->Alloc<wchar_t>(bufSize);
-			int result = V_UTF8ToUnicode(pKey->m_sValue, pWBuf, static_cast<int>(bufSize * sizeof(wchar_t)));
+			wchar_t* pWBuf = new wchar_t[bufSize];
+			int result = V_UTF8ToUnicode(pKey->m_sValue, pWBuf, int(bufSize * sizeof(wchar_t)));
 			if (result >= 0) // may be a zero length string
 			{
 				SetWString(pszKeyName, pWBuf);
 			}
 			else
 			{
-				MemAllocSingleton()->Free(pWBuf);
+				delete[] pWBuf;
 				return pwszDefaultValue;
 			}
-			MemAllocSingleton()->Free(pWBuf);
+			delete[] pWBuf;
 			break;
 		}
 		default:
@@ -863,12 +862,12 @@ void KeyValues::SetUint64(const char* pszKeyName, uint64_t nValue)
 	if (pKey)
 	{
 		// delete the old value
-		MemAllocSingleton()->Free(pKey->m_sValue);
+		delete[] pKey->m_sValue;
 		// make sure we're not storing the WSTRING  - as we're converting over to STRING
-		MemAllocSingleton()->Free(pKey->m_wsValue);
+		delete[] pKey->m_wsValue;
 		pKey->m_wsValue = nullptr;
 
-		pKey->m_sValue = MemAllocSingleton()->Alloc<char>(sizeof(uint64_t));
+		pKey->m_sValue = new char[sizeof(uint64)];
 		*(reinterpret_cast<uint64_t*>(pKey->m_sValue)) = nValue;
 		pKey->m_iDataType = TYPE_UINT64;
 	}
@@ -925,9 +924,9 @@ void KeyValues::SetPtr(const char* pszKeyName, void* pValue)
 void KeyValues::SetStringValue(char const* pszValue)
 {
 	// delete the old value
-	MemAllocSingleton()->Free(m_sValue);
+	delete[] m_sValue;
 	// make sure we're not storing the WSTRING  - as we're converting over to STRING
-	MemAllocSingleton()->Free(m_wsValue);
+	delete[] m_wsValue;
 	m_wsValue = nullptr;
 
 	if (!pszValue)
@@ -938,7 +937,7 @@ void KeyValues::SetStringValue(char const* pszValue)
 
 	// allocate memory for the new value and copy it in
 	size_t len = strlen(pszValue);
-	m_sValue = MemAllocSingleton()->Alloc<char>(len + 1);
+	m_sValue = new char[len + 1];
 	memcpy(m_sValue, pszValue, len + 1);
 
 	m_iDataType = TYPE_STRING;
@@ -977,9 +976,9 @@ void KeyValues::SetWString(const char* pszKeyName, const wchar_t* pwszValue)
 	if (pKey)
 	{
 		// delete the old value
-		MemAllocSingleton()->Free(pKey->m_wsValue);
+		delete[] pKey->m_wsValue;
 		// make sure we're not storing the STRING  - as we're converting over to WSTRING
-		MemAllocSingleton()->Free(pKey->m_sValue);
+		delete[] pKey->m_sValue;
 		pKey->m_sValue = nullptr;
 
 		if (!pwszValue)
@@ -990,7 +989,7 @@ void KeyValues::SetWString(const char* pszKeyName, const wchar_t* pwszValue)
 
 		// allocate memory for the new value and copy it in
 		size_t len = wcslen(pwszValue);
-		pKey->m_wsValue = MemAllocSingleton()->Alloc<wchar_t>(len + 1);
+		pKey->m_wsValue = new wchar_t[len + 1];
 		memcpy(pKey->m_wsValue, pwszValue, (len + 1) * sizeof(wchar_t));
 
 		pKey->m_iDataType = TYPE_WSTRING;
@@ -1048,7 +1047,7 @@ void KeyValues::RecursiveCopyKeyValues(KeyValues& src)
 			if (src.m_sValue)
 			{
 				size_t len = strlen(src.m_sValue) + 1;
-				m_sValue = MemAllocSingleton()->Alloc<char>(len);
+				m_sValue = new char[len];
 				strncpy(m_sValue, src.m_sValue, len);
 			}
 			break;
@@ -1057,7 +1056,7 @@ void KeyValues::RecursiveCopyKeyValues(KeyValues& src)
 			m_iValue = src.m_iValue;
 			snprintf(buf, sizeof(buf), "%d", m_iValue);
 			size_t len = strlen(buf) + 1;
-			m_sValue = MemAllocSingleton()->Alloc<char>(len);
+			m_sValue = new char[len];
 			strncpy(m_sValue, buf, len);
 		}
 		break;
@@ -1066,7 +1065,7 @@ void KeyValues::RecursiveCopyKeyValues(KeyValues& src)
 			m_flValue = src.m_flValue;
 			snprintf(buf, sizeof(buf), "%f", m_flValue);
 			size_t len = strlen(buf) + 1;
-			m_sValue = MemAllocSingleton()->Alloc<char>(len);
+			m_sValue = new char[len];
 			strncpy(m_sValue, buf, len);
 		}
 		break;
@@ -1077,7 +1076,7 @@ void KeyValues::RecursiveCopyKeyValues(KeyValues& src)
 		break;
 		case TYPE_UINT64:
 		{
-			m_sValue = MemAllocSingleton()->Alloc<char>(sizeof(uint64_t));
+			m_sValue = new char[sizeof(uint64)];
 			memcpy(m_sValue, src.m_sValue, sizeof(uint64_t));
 		}
 		break;
@@ -1103,24 +1102,14 @@ void KeyValues::RecursiveCopyKeyValues(KeyValues& src)
 	// Handle the immediate child
 	if (src.m_pSub)
 	{
-		m_pSub = MemAllocSingleton()->Alloc<KeyValues>(sizeof(KeyValues));
-		TRACK_KV_ADD(m_pSub, nullptr);
-
-		m_pSub->Init();
-		m_pSub->SetName(nullptr);
-
+		m_pSub = new KeyValues(NULL);
 		m_pSub->RecursiveCopyKeyValues(*src.m_pSub);
 	}
 
 	// Handle the immediate peer
 	if (src.m_pPeer)
 	{
-		m_pPeer = MemAllocSingleton()->Alloc<KeyValues>(sizeof(KeyValues));
-		TRACK_KV_ADD(m_pPeer, nullptr);
-
-		m_pPeer->Init();
-		m_pPeer->SetName(nullptr);
-
+		m_pPeer = new KeyValues(NULL);
 		m_pPeer->RecursiveCopyKeyValues(*src.m_pPeer);
 	}
 }
@@ -1187,12 +1176,7 @@ void KeyValues::CopySubkeys(KeyValues* pParent) const
 //-----------------------------------------------------------------------------
 KeyValues* KeyValues::MakeCopy(void) const
 {
-	KeyValues* pNewKeyValue = MemAllocSingleton()->Alloc<KeyValues>(sizeof(KeyValues));
-
-	TRACK_KV_ADD(pNewKeyValue, GetName());
-
-	pNewKeyValue->Init();
-	pNewKeyValue->SetName(GetName());
+	KeyValues* pNewKeyValue = new KeyValues(GetName());
 
 	// copy data
 	pNewKeyValue->m_iDataType = m_iDataType;
@@ -1204,7 +1188,7 @@ KeyValues* KeyValues::MakeCopy(void) const
 		{
 			size_t len = strlen(m_sValue);
 			Assert(!pNewKeyValue->m_sValue);
-			pNewKeyValue->m_sValue = MemAllocSingleton()->Alloc<char>(len + 1);
+			pNewKeyValue->m_sValue = new char[len + 1];
 			memcpy(pNewKeyValue->m_sValue, m_sValue, len + 1);
 		}
 	}
@@ -1214,8 +1198,8 @@ KeyValues* KeyValues::MakeCopy(void) const
 		if (m_wsValue)
 		{
 			size_t len = wcslen(m_wsValue);
-			pNewKeyValue->m_wsValue = MemAllocSingleton()->Alloc<wchar_t>(len + 1);
-			memcpy(pNewKeyValue->m_wsValue, m_wsValue, len + 1 * sizeof(wchar_t));
+			pNewKeyValue->m_wsValue = new wchar_t[len + 1];
+			memcpy(pNewKeyValue->m_wsValue, m_wsValue, (len+1)*sizeof(wchar_t));
 		}
 	}
 	break;
@@ -1240,7 +1224,7 @@ KeyValues* KeyValues::MakeCopy(void) const
 		break;
 
 	case TYPE_UINT64:
-		pNewKeyValue->m_sValue = MemAllocSingleton()->Alloc<char>(sizeof(uint64_t));
+		pNewKeyValue->m_sValue = new char[sizeof(uint64)];
 		memcpy(pNewKeyValue->m_sValue, m_sValue, sizeof(uint64_t));
 		break;
 	};
diff --git a/r5dev/vpc/rson.cpp b/r5dev/vpc/rson.cpp
index 1257de35..0efe046f 100644
--- a/r5dev/vpc/rson.cpp
+++ b/r5dev/vpc/rson.cpp
@@ -20,16 +20,14 @@ RSON::Node_t* RSON::LoadFromFile(const char* pszFilePath)
 
 		uint32_t nFileSize = FileSystem()->Size(file);
 
-		char* fileBuf = MemAllocSingleton()->Alloc<char>(nFileSize + 1);
+		std::unique_ptr<char[]> fileBuf(new char[nFileSize + 1]);
 
-		int nRead = FileSystem()->Read(fileBuf, nFileSize, file);
+		int nRead = FileSystem()->Read(fileBuf.get(), nFileSize, file);
 		FileSystem()->Close(file);
 
 		fileBuf[nRead] = '\0';
 
-		RSON::Node_t* node = RSON::LoadFromBuffer(pszFilePath, fileBuf, eFieldType::RSON_OBJECT);
-
-		MemAllocSingleton()->Free(fileBuf);
+		RSON::Node_t* node = RSON::LoadFromBuffer(pszFilePath, fileBuf.get(), eFieldType::RSON_OBJECT);
 
 		if (node)
 			return node;
diff --git a/r5dev/vpklib/packedstore.cpp b/r5dev/vpklib/packedstore.cpp
index 97a1fcab..deda0045 100644
--- a/r5dev/vpklib/packedstore.cpp
+++ b/r5dev/vpklib/packedstore.cpp
@@ -24,7 +24,7 @@
 // data is still getting read from the old pack file.
 // 
 /////////////////////////////////////////////////////////////////////////////////
-//#include "core/stdafx.h"
+
 #include "tier1/cvar.h"
 #include "tier2/fileutils.h"
 #include "mathlib/adler32.h"
@@ -324,14 +324,12 @@ void CPackedStore::ValidateCRC32PostDecomp(const CUtlString& assetPath, const ui
 	}
 
 	uint32_t nLen = FileSystem()->Size(hAsset);
-	uint8_t* pBuf = MemAllocSingleton()->Alloc<uint8_t>(nLen);
+	std::unique_ptr<uint8_t[]> pBuf(new uint8_t[nLen]);
 
-	FileSystem()->Read(pBuf, nLen, hAsset);
+	FileSystem()->Read(pBuf.get(), nLen, hAsset);
 	FileSystem()->Close(hAsset);
 
-	uint32_t nCrc32 = crc32::update(NULL, pBuf, nLen);
-	MemAllocSingleton()->Free(pBuf);
-
+	uint32_t nCrc32 = crc32::update(NULL, pBuf.get(), nLen);
 	if (nCrc32 != nFileCRC)
 	{
 		Warning(eDLL_T::FS, "Computed checksum '0x%lX' doesn't match expected checksum '0x%lX'. File may be corrupt!\n", nCrc32, nFileCRC);
@@ -376,7 +374,7 @@ bool CPackedStore::ShouldPrune(const CUtlString& filePath, CUtlVector<CUtlString
 		return true;
 	}
 
-	for (int j = 0; j < ignoreList.Count(); j++)
+	FOR_EACH_VEC(ignoreList, j)
 	{
 		CUtlString& ignoreEntry = ignoreList[j];
 
@@ -436,7 +434,8 @@ void CPackedStore::PackWorkspace(const VPKPair_t& vpkPair, const char* workspace
 		return;
 	}
 
-	uint8_t* pEntryBuffer = MemAllocSingleton()->Alloc<uint8_t>(ENTRY_MAX_LEN);
+	std::unique_ptr<uint8_t[]> pEntryBuffer(new uint8_t[ENTRY_MAX_LEN]);
+
 	if (!pEntryBuffer)
 	{
 		Error(eDLL_T::FS, NO_ERROR, "%s - Unable to allocate memory for entry buffer!\n", __FUNCTION__);
@@ -456,7 +455,7 @@ void CPackedStore::PackWorkspace(const VPKPair_t& vpkPair, const char* workspace
 	uint64_t nSharedTotal = NULL;
 	uint32_t nSharedCount = NULL;
 
-	for (int i = 0, ps = entryValues.Count(); i < ps; i++)
+	FOR_EACH_VEC(entryValues, i)
 	{
 		const VPKKeyValues_t& entryValue = entryValues[i];
 		FileHandle_t hAsset = FileSystem()->Open(entryValue.m_EntryPath.Get(), "rb", "PLATFORM");
@@ -473,14 +472,14 @@ void CPackedStore::PackWorkspace(const VPKPair_t& vpkPair, const char* workspace
 		}
 
 		uint32_t nLen = FileSystem()->Size(hAsset);
-		uint8_t* pBuf = MemAllocSingleton()->Alloc<uint8_t>(nLen);
+		std::unique_ptr<uint8_t[]> pBuf(new uint8_t[nLen]);
 
-		FileSystem()->Read(pBuf, nLen, hAsset);
+		FileSystem()->Read(pBuf.get(), nLen, hAsset);
 		FileSystem()->Seek(hAsset, 0, FileSystemSeek_t::FILESYSTEM_SEEK_HEAD);
 
 		DevMsg(eDLL_T::FS, "Packing entry '%i' ('%s')\n", i, szDestPath);
 		entryBlocks.AddToTail(VPKEntryBlock_t(
-			pBuf,
+			pBuf.get(),
 			nLen,
 			FileSystem()->Tell(hPackFile),
 			entryValue.m_iPreloadSize,
@@ -490,14 +489,15 @@ void CPackedStore::PackWorkspace(const VPKPair_t& vpkPair, const char* workspace
 			CUtlString(szDestPath)));
 
 		VPKEntryBlock_t& entryBlock = entryBlocks[i];
-		for (int j = 0, es = entryBlock.m_Fragments.Count(); j < es; j++)
+
+		FOR_EACH_VEC(entryBlock.m_Fragments, j)
 		{
 			VPKChunkDescriptor_t& descriptor = entryBlock.m_Fragments[j];
 
-			FileSystem()->Read(pEntryBuffer, int(descriptor.m_nCompressedSize), hAsset);
+			FileSystem()->Read(pEntryBuffer.get(), int(descriptor.m_nCompressedSize), hAsset);
 			descriptor.m_nPackFileOffset = FileSystem()->Tell(hPackFile);
 
-			if (entryValue.m_bDeduplicate && Deduplicate(pEntryBuffer, descriptor, j))
+			if (entryValue.m_bDeduplicate && Deduplicate(pEntryBuffer.get(), descriptor, j))
 			{
 				nSharedTotal += descriptor.m_nCompressedSize;
 				nSharedCount++;
@@ -508,7 +508,7 @@ void CPackedStore::PackWorkspace(const VPKPair_t& vpkPair, const char* workspace
 
 			if (entryValue.m_bUseCompression)
 			{
-				lzham_compress_status_t lzCompStatus = lzham_compress_memory(&m_lzCompParams, pEntryBuffer, &descriptor.m_nCompressedSize, pEntryBuffer,
+				lzham_compress_status_t lzCompStatus = lzham_compress_memory(&m_lzCompParams, pEntryBuffer.get(), &descriptor.m_nCompressedSize, pEntryBuffer.get(),
 					descriptor.m_nUncompressedSize, nullptr);
 
 				if (lzCompStatus != lzham_compress_status_t::LZHAM_COMP_STATUS_SUCCESS)
@@ -524,10 +524,9 @@ void CPackedStore::PackWorkspace(const VPKPair_t& vpkPair, const char* workspace
 				descriptor.m_nCompressedSize = descriptor.m_nUncompressedSize;
 			}
 
-			FileSystem()->Write(pEntryBuffer, int(descriptor.m_nCompressedSize), hPackFile);
+			FileSystem()->Write(pEntryBuffer.get(), int(descriptor.m_nCompressedSize), hPackFile);
 		}
 
-		MemAllocSingleton()->Free(pBuf);
 		FileSystem()->Close(hAsset);
 	}
 
@@ -535,7 +534,6 @@ void CPackedStore::PackWorkspace(const VPKPair_t& vpkPair, const char* workspace
 	FileSystem()->Close(hPackFile);
 
 	m_ChunkHashMap.clear();
-	MemAllocSingleton()->Free(pEntryBuffer);
 
 	VPKDir_t vDirectory;
 	vDirectory.BuildDirectoryFile(dirFilePath, entryBlocks);
@@ -560,8 +558,8 @@ void CPackedStore::UnpackWorkspace(const VPKDir_t& vpkDir, const char* workspace
 		return;
 	}
 
-	uint8_t* pDestBuffer = MemAllocSingleton()->Alloc<uint8_t>(ENTRY_MAX_LEN);
-	uint8_t* pSourceBuffer = MemAllocSingleton()->Alloc<uint8_t>(ENTRY_MAX_LEN);
+	std::unique_ptr<uint8_t[]> pDestBuffer(new uint8_t[ENTRY_MAX_LEN]);
+	std::unique_ptr<uint8_t[]> pSourceBuffer(new uint8_t[ENTRY_MAX_LEN]);
 
 	if (!pDestBuffer || !pSourceBuffer)
 	{
@@ -572,7 +570,7 @@ void CPackedStore::UnpackWorkspace(const VPKDir_t& vpkDir, const char* workspace
 	BuildManifest(vpkDir.m_EntryBlocks, workspacePath, GetLevelName(vpkDir.m_DirFilePath));
 	const CUtlString basePath = vpkDir.m_DirFilePath.StripFilename(false);
 
-	for (int i = 0, fs = vpkDir.m_PackFiles.Count(); i < fs; i++)
+	FOR_EACH_VEC(vpkDir.m_PackFiles, i)
 	{
 		const CUtlString packFile = basePath + vpkDir.m_PackFiles[i];
 
@@ -584,7 +582,7 @@ void CPackedStore::UnpackWorkspace(const VPKDir_t& vpkDir, const char* workspace
 			continue;
 		}
 
-		for (int j = 0, es = vpkDir.m_EntryBlocks.Count(); j < es; j++)
+		FOR_EACH_VEC(vpkDir.m_EntryBlocks, j)
 		{
 			const VPKEntryBlock_t& entryBlock = vpkDir.m_EntryBlocks[j];
 			if (entryBlock.m_iPackFileIndex != uint16_t(i))
@@ -606,16 +604,17 @@ void CPackedStore::UnpackWorkspace(const VPKDir_t& vpkDir, const char* workspace
 			}
 
 			DevMsg(eDLL_T::FS, "Unpacking entry '%i' from block '%i' ('%s')\n", j, i, entryBlock.m_EntryPath.Get());
-			for (int k = 0, cs = entryBlock.m_Fragments.Count(); k < cs; k++)
+
+			FOR_EACH_VEC(entryBlock.m_Fragments, k)
 			{
 				const VPKChunkDescriptor_t& fragment = entryBlock.m_Fragments[k];
 
 				FileSystem()->Seek(hPackFile, int(fragment.m_nPackFileOffset), FileSystemSeek_t::FILESYSTEM_SEEK_HEAD);
-				FileSystem()->Read(pSourceBuffer, int(fragment.m_nCompressedSize), hPackFile);
+				FileSystem()->Read(pSourceBuffer.get(), int(fragment.m_nCompressedSize), hPackFile);
 
 				if (fragment.m_nCompressedSize == fragment.m_nUncompressedSize) // Data is not compressed.
 				{
-					FileSystem()->Write(pSourceBuffer, int(fragment.m_nUncompressedSize), hAsset);
+					FileSystem()->Write(pSourceBuffer.get(), int(fragment.m_nUncompressedSize), hAsset);
 					continue;
 				}
 
@@ -625,8 +624,8 @@ void CPackedStore::UnpackWorkspace(const VPKDir_t& vpkDir, const char* workspace
 				if (fragment.m_nCompressedSize > nDstLen)
 					break; // Corrupt or invalid chunk descriptor.
 
-				lzham_decompress_status_t lzDecompStatus = lzham_decompress_memory(&m_lzDecompParams, pDestBuffer,
-					&nDstLen, pSourceBuffer, fragment.m_nCompressedSize, nullptr);
+				lzham_decompress_status_t lzDecompStatus = lzham_decompress_memory(&m_lzDecompParams, pDestBuffer.get(),
+					&nDstLen, pSourceBuffer.get(), fragment.m_nCompressedSize, nullptr);
 
 				if (lzDecompStatus != lzham_decompress_status_t::LZHAM_DECOMP_STATUS_SUCCESS)
 				{
@@ -635,7 +634,7 @@ void CPackedStore::UnpackWorkspace(const VPKDir_t& vpkDir, const char* workspace
 				}
 				else // If successfully decompressed, write to file.
 				{
-					FileSystem()->Write(pDestBuffer, int(nDstLen), hAsset);
+					FileSystem()->Write(pDestBuffer.get(), int(nDstLen), hAsset);
 				}
 			}
 
@@ -644,9 +643,6 @@ void CPackedStore::UnpackWorkspace(const VPKDir_t& vpkDir, const char* workspace
 		}
 		FileSystem()->Close(hPackFile);
 	}
-
-	MemAllocSingleton()->Free(pDestBuffer);
-	MemAllocSingleton()->Free(pSourceBuffer);
 }
 
 //-----------------------------------------------------------------------------
@@ -1000,7 +996,7 @@ uint64_t VPKDir_t::WriteDescriptor(FileHandle_t hDirectoryFile,
 				FileSystem()->Write(&vEntry.m_iPreloadSize, sizeof(uint16_t), hDirectoryFile);
 				FileSystem()->Write(&vEntry.m_iPackFileIndex, sizeof(uint16_t), hDirectoryFile);
 
-				for (int i = 0, nc = vEntry.m_Fragments.Count(); i < nc; i++)
+				FOR_EACH_VEC(vEntry.m_Fragments, i)
 				{
 					/*Write chunk descriptor*/
 					const VPKChunkDescriptor_t* pDescriptor = &vEntry.m_Fragments[i];
@@ -1011,7 +1007,7 @@ uint64_t VPKDir_t::WriteDescriptor(FileHandle_t hDirectoryFile,
 					FileSystem()->Write(&pDescriptor->m_nCompressedSize, sizeof(uint64_t), hDirectoryFile);
 					FileSystem()->Write(&pDescriptor->m_nUncompressedSize, sizeof(uint64_t), hDirectoryFile);
 
-					if (i != (nc - 1))
+					if (i != (vEntry.m_Fragments.Count() - 1))
 					{
 						FileSystem()->Write(&PACKFILEINDEX_SEP, sizeof(uint16_t), hDirectoryFile);
 					}