diff --git a/.gitignore b/.gitignore
index dc6d161e8..6aa9bce05 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,6 +2,7 @@
*.bat
*.log
*.lnk
+*.aps
**/msvc/Debug*
**/msvc/Release*
**/msvc/Tests
diff --git a/regamedll/CMakeLists.txt b/regamedll/CMakeLists.txt
index 735d54fc8..69f710b31 100644
--- a/regamedll/CMakeLists.txt
+++ b/regamedll/CMakeLists.txt
@@ -161,6 +161,9 @@ set(SHARED_SRCS
"public/FileSystem.cpp"
"public/interface.cpp"
"public/MemPool.cpp"
+ "public/MemPool.cpp"
+ "public/tier0/dbg.cpp"
+ "public/tier0/platform_posix.cpp"
)
set(GAMEDLL_SRCS
diff --git a/regamedll/dlls/client.cpp b/regamedll/dlls/client.cpp
index dca3c5690..4d42cbe34 100644
--- a/regamedll/dlls/client.cpp
+++ b/regamedll/dlls/client.cpp
@@ -673,7 +673,7 @@ void EXT_FUNC ClientPutInServer(edict_t *pEntity)
CBaseEntity *pTarget = nullptr;
pPlayer->m_pIntroCamera = UTIL_FindEntityByClassname(nullptr, "trigger_camera");
-#ifndef REGAMEDLL_FIXES
+#ifndef REGAMEDLL_FIXES
if (g_pGameRules && g_pGameRules->IsMultiplayer())
{
CSGameRules()->m_bMapHasCameras = (pPlayer->m_pIntroCamera != nullptr);
@@ -696,8 +696,8 @@ void EXT_FUNC ClientPutInServer(edict_t *pEntity)
pPlayer->pev->angles = CamAngles;
pPlayer->pev->v_angle = pPlayer->pev->angles;
- pPlayer->m_fIntroCamTime =
-#ifdef REGAMEDLL_FIXES
+ pPlayer->m_fIntroCamTime =
+#ifdef REGAMEDLL_FIXES
(CSGameRules()->m_bMapHasCameras <= 1) ? 0.0 : // no need to refresh cameras if map has only one
#endif
gpGlobals->time + 6;
diff --git a/regamedll/dlls/game.cpp b/regamedll/dlls/game.cpp
index 55c2600c1..423250ce6 100644
--- a/regamedll/dlls/game.cpp
+++ b/regamedll/dlls/game.cpp
@@ -228,8 +228,13 @@ void GameDLL_SwapTeams_f()
#endif // REGAMEDLL_ADD
+SpewRetval_t GameDLL_SpewHandler(SpewType_t spewType, int level, const char *pMsg);
+
void EXT_FUNC GameDLLInit()
{
+ // By default, direct dbg reporting...
+ SpewOutputFunc(GameDLL_SpewHandler);
+
g_pskill = CVAR_GET_POINTER("skill");
g_psv_gravity = CVAR_GET_POINTER("sv_gravity");
g_psv_aim = CVAR_GET_POINTER("sv_aim");
@@ -455,3 +460,28 @@ void EXT_FUNC GameDLLInit()
#endif
}
+
+SpewRetval_t GameDLL_SpewHandler(SpewType_t spewType, int level, const char *pMsg)
+{
+ bool bSpewPrint = (CVAR_GET_FLOAT("developer") >= level);
+ switch (spewType)
+ {
+ case SPEW_LOG:
+ case SPEW_MESSAGE:
+ if (bSpewPrint) UTIL_ServerPrint("%s", pMsg);
+ break;
+ case SPEW_WARNING:
+ if (bSpewPrint) UTIL_ServerPrint("Warning: %s", pMsg);
+ break;
+ case SPEW_ERROR:
+ Sys_Error("%s", pMsg);
+ return SPEW_ABORT; // fatal error, terminate it!
+ case SPEW_ASSERT:
+ UTIL_ServerPrint("Assert: %s", pMsg);
+ return SPEW_DEBUGGER; // assert always tries to debugger break
+ default:
+ break;
+ }
+
+ return SPEW_CONTINUE; // spew handled, continue on
+}
diff --git a/regamedll/dlls/h_export.cpp b/regamedll/dlls/h_export.cpp
index 47189b833..486a3eedf 100644
--- a/regamedll/dlls/h_export.cpp
+++ b/regamedll/dlls/h_export.cpp
@@ -16,22 +16,7 @@ C_DLLEXPORT void WINAPI GiveFnptrsToDll(enginefuncs_t *pEnginefuncsTable, global
Regamedll_Game_Init();
}
-#ifdef _WIN32
-
-// DLL entry point
-BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
-{
- if (fdwReason == DLL_PROCESS_ATTACH)
- {
- }
- else if (fdwReason == DLL_PROCESS_DETACH)
- {
- }
-
- return TRUE;
-}
-
-#else // _WIN32
+#if defined(_LINUX)
void __attribute__((constructor)) DllMainLoad()
{
@@ -41,4 +26,4 @@ void __attribute__((destructor)) DllMainUnload()
{
}
-#endif // _WIN32
+#endif // _LINUX
diff --git a/regamedll/dlls/util.cpp b/regamedll/dlls/util.cpp
index 714fe79d1..7c3c3db6c 100644
--- a/regamedll/dlls/util.cpp
+++ b/regamedll/dlls/util.cpp
@@ -1497,7 +1497,7 @@ void UTIL_RestartOther(const char *szClassname)
while ((pEntity = UTIL_FindEntityByClassname(pEntity, szClassname)))
{
pEntity->Restart();
-
+
#ifdef REGAMEDLL_ADD
FireTargets("game_entity_restart", pEntity, nullptr, USE_TOGGLE, 0.0);
#endif
@@ -1731,7 +1731,7 @@ bool UTIL_AreHostagesImprov()
#ifdef REGAMEDLL_ADD
if (g_engfuncs.pfnEngCheckParm == nullptr)
return false;
-
+
// someday in CS 1.6
int improv = ENG_CHECK_PARM("-host-improv", nullptr);
if (improv)
@@ -1819,10 +1819,11 @@ void NORETURN Sys_Error(const char *error, ...)
CONSOLE_ECHO("FATAL ERROR (shutting down): %s\n", text);
- //TerminateProcess(GetCurrentProcess(), 1);
- int *null = 0;
- *null = 0;
- exit(-1);
+#if defined(_WIN32)
+ MessageBoxA(NULL, text, "Fatal error", MB_ICONERROR | MB_OK);
+#endif
+
+ exit(EXIT_FAILURE);
}
int UTIL_CountPlayersInBrushVolume(bool bOnlyAlive, CBaseEntity *pBrushEntity, int &playersInCount, int &playersOutCount, CPlayerInVolumeAdapter *pAdapter)
diff --git a/regamedll/engine/unicode_strtools.cpp b/regamedll/engine/unicode_strtools.cpp
index e7e113ba6..6dbf19417 100644
--- a/regamedll/engine/unicode_strtools.cpp
+++ b/regamedll/engine/unicode_strtools.cpp
@@ -756,9 +756,8 @@ int Q_UnicodeConvertT(const SrcType *pIn, int nInChars, DstType *pOut, int nOutB
if (bErr)
{
-#ifdef _DEBUG
- AssertMsg(!(ePolicy & _STRINGCONVERTFLAG_ASSERT), "invalid Unicode byte sequence");
-#endif
+ DbgAssertMsg(!(ePolicy & _STRINGCONVERTFLAG_ASSERT), "invalid Unicode byte sequence");
+
if (ePolicy & _STRINGCONVERTFLAG_SKIP)
{
nOut -= EncodeDstLen(uVal);
@@ -793,9 +792,8 @@ int Q_UnicodeConvertT(const SrcType *pIn, int nInChars, DstType *pOut, int nOutB
nOut += EncodeDst(uVal, pOut + nOut);
if (bErr)
{
-#ifdef _DEBUG
- AssertMsg(!(ePolicy & _STRINGCONVERTFLAG_ASSERT), "invalid Unicode byte sequence");
-#endif
+ DbgAssertMsg(!(ePolicy & _STRINGCONVERTFLAG_ASSERT), "invalid Unicode byte sequence");
+
if (ePolicy & _STRINGCONVERTFLAG_SKIP)
{
nOut -= EncodeDstLen(uVal);
diff --git a/regamedll/msvc/ReGameDLL.vcxproj b/regamedll/msvc/ReGameDLL.vcxproj
index c31abc6e9..1c51c7fd1 100644
--- a/regamedll/msvc/ReGameDLL.vcxproj
+++ b/regamedll/msvc/ReGameDLL.vcxproj
@@ -540,6 +540,7 @@
+
@@ -548,6 +549,7 @@
true
true
+
true
true
@@ -787,6 +789,7 @@
+
@@ -810,6 +813,9 @@
false
+
+
+
{70A2B904-B7DB-4C48-8DE0-AF567360D572}
ReGameDLL
diff --git a/regamedll/msvc/ReGameDLL.vcxproj.filters b/regamedll/msvc/ReGameDLL.vcxproj.filters
index 84536f321..ef2017ae4 100644
--- a/regamedll/msvc/ReGameDLL.vcxproj.filters
+++ b/regamedll/msvc/ReGameDLL.vcxproj.filters
@@ -555,6 +555,12 @@
public
+
+ public\tier0
+
+
+ public\tier0
+
@@ -1055,5 +1061,13 @@
public
+
+ public\tier0
+
+
+
+
+ public\tier0
+
\ No newline at end of file
diff --git a/regamedll/public/tier0/assert_dialog.cpp b/regamedll/public/tier0/assert_dialog.cpp
new file mode 100644
index 000000000..11bb9442b
--- /dev/null
+++ b/regamedll/public/tier0/assert_dialog.cpp
@@ -0,0 +1,302 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//
+//===========================================================================//
+
+#include "precompiled.h"
+#include "resource.h"
+
+class CDialogInitInfo
+{
+public:
+ const char *m_pFilename;
+ int m_iLine;
+ const char *m_pExpression;
+};
+
+class CAssertDisable
+{
+public:
+ char m_Filename[MAX_OSPATH];
+
+ // If these are not -1, then this CAssertDisable only disables asserts on lines between
+ // these values (inclusive).
+ int m_LineMin;
+ int m_LineMax;
+
+ // Decremented each time we hit this assert and ignore it, until it's 0.
+ // Then the CAssertDisable is removed.
+ // If this is -1, then we always ignore this assert.
+ int m_nIgnoreTimes;
+
+ CAssertDisable *m_pNext;
+};
+
+static CDialogInitInfo g_Info{};
+static bool g_bAssertsEnabled = true;
+static CAssertDisable *g_pAssertDisables = nullptr;
+
+// Set to true if they want to break in the debugger
+static bool g_bBreak = false;
+
+// Internal functions
+static HINSTANCE g_hTier0Instance = nullptr;
+BOOL WINAPI DllMain(
+ HINSTANCE hinstDLL, // handle to the DLL module
+ DWORD fdwReason, // reason for calling function
+ LPVOID lpvReserved // reserved
+)
+{
+ g_hTier0Instance = hinstDLL;
+ return true;
+}
+
+static bool IsDebugBreakEnabled()
+{
+ static bool bResult = (Q_strstr(Plat_GetCommandLine(), "-debugbreak") != nullptr);
+ return bResult;
+}
+
+static bool AreAssertsDisabled()
+{
+ static bool bResult = (Q_strstr(Plat_GetCommandLine(), "-noassert") != nullptr);
+ return bResult;
+}
+
+static bool AreAssertsEnabledInFileLine(const char *pFilename, int iLine)
+{
+ CAssertDisable **pPrev = &g_pAssertDisables;
+ CAssertDisable *pNext = nullptr;
+
+ for (CAssertDisable *pCur = g_pAssertDisables; pCur; pCur = pNext)
+ {
+ pNext = pCur->m_pNext;
+
+ if (Q_stricmp(pFilename, pCur->m_Filename) == 0)
+ {
+ // Are asserts disabled in the whole file?
+ bool bAssertsEnabled = true;
+ if (pCur->m_LineMin == -1 && pCur->m_LineMax == -1)
+ bAssertsEnabled = false;
+
+ // Are asserts disabled on the specified line?
+ if (iLine >= pCur->m_LineMin && iLine <= pCur->m_LineMax)
+ bAssertsEnabled = false;
+
+ if (!bAssertsEnabled)
+ {
+ // If this assert is only disabled for the next N times, then countdown..
+ if (pCur->m_nIgnoreTimes > 0)
+ {
+ pCur->m_nIgnoreTimes--;
+
+ if (pCur->m_nIgnoreTimes == 0)
+ {
+ // Remove this one from the list.
+ *pPrev = pNext;
+ delete pCur;
+ continue;
+ }
+ }
+
+ return false;
+ }
+ }
+
+ pPrev = &pCur->m_pNext;
+ }
+
+ return true;
+}
+
+CAssertDisable *CreateNewAssertDisable(const char *pFilename)
+{
+ CAssertDisable *pDisable = new CAssertDisable;
+ pDisable->m_pNext = g_pAssertDisables;
+ g_pAssertDisables = pDisable;
+
+ pDisable->m_LineMin = pDisable->m_LineMax = -1;
+ pDisable->m_nIgnoreTimes = -1;
+
+ Q_strlcpy(pDisable->m_Filename, g_Info.m_pFilename);
+
+ return pDisable;
+}
+
+void IgnoreAssertsInCurrentFile()
+{
+ CreateNewAssertDisable(g_Info.m_pFilename);
+}
+
+CAssertDisable *IgnoreAssertsNearby(int nRange)
+{
+ CAssertDisable *pDisable = CreateNewAssertDisable(g_Info.m_pFilename);
+ pDisable->m_LineMin = g_Info.m_iLine - nRange;
+ pDisable->m_LineMax = g_Info.m_iLine - nRange;
+ return pDisable;
+}
+
+static int g_iLastLineRange = 5;
+static int g_nLastIgnoreNumTimes = 1;
+
+int CALLBACK AssertDialogProc(
+ HWND hDlg, // handle to dialog box
+ UINT uMsg, // message
+ WPARAM wParam, // first message parameter
+ LPARAM lParam // second message parameter
+)
+{
+ switch (uMsg)
+ {
+ case WM_INITDIALOG:
+ {
+ SetDlgItemText(hDlg, IDC_ASSERT_MSG_CTRL, g_Info.m_pExpression);
+ SetDlgItemText(hDlg, IDC_FILENAME_CONTROL, g_Info.m_pFilename);
+
+ SetDlgItemInt(hDlg, IDC_LINE_CONTROL, g_Info.m_iLine, false);
+ SetDlgItemInt(hDlg, IDC_IGNORE_NUMLINES, g_iLastLineRange, false);
+ SetDlgItemInt(hDlg, IDC_IGNORE_NUMTIMES, g_nLastIgnoreNumTimes, false);
+
+ // Center the dialog.
+ RECT rcDlg, rcDesktop;
+ GetWindowRect(hDlg, &rcDlg);
+ GetWindowRect(GetDesktopWindow(), &rcDesktop);
+ SetWindowPos(hDlg, HWND_TOP,
+ ((rcDesktop.right - rcDesktop.left) - (rcDlg.right - rcDlg.left)) / 2,
+ ((rcDesktop.bottom - rcDesktop.top) - (rcDlg.bottom - rcDlg.top)) / 2,
+ 0, 0,
+ SWP_NOSIZE
+ );
+
+ return TRUE;
+ }
+ case WM_COMMAND:
+ {
+ switch (LOWORD(wParam))
+ {
+ // Ignore this assert N times
+ case IDC_IGNORE_THIS:
+ {
+ BOOL bTranslated = false;
+ UINT value = GetDlgItemInt(hDlg, IDC_IGNORE_NUMTIMES, &bTranslated, false);
+ if (bTranslated && value > 1)
+ {
+ CAssertDisable *pDisable = IgnoreAssertsNearby(0);
+ pDisable->m_nIgnoreTimes = value - 1;
+ g_nLastIgnoreNumTimes = value;
+ }
+
+ EndDialog(hDlg, 0);
+ return TRUE;
+ }
+ case IDC_IGNORE_NEARBY:
+ {
+ BOOL bTranslated = false;
+ UINT value = GetDlgItemInt(hDlg, IDC_IGNORE_NUMLINES, &bTranslated, false);
+ if (!bTranslated || value < 1)
+ return TRUE;
+
+ IgnoreAssertsNearby(value);
+ EndDialog(hDlg, 0);
+ return TRUE;
+ }
+ case IDC_IGNORE_FILE:
+ IgnoreAssertsInCurrentFile();
+ EndDialog(hDlg, 0);
+ return TRUE;
+ // Always ignore this assert
+ case IDC_IGNORE_ALWAYS:
+ IgnoreAssertsNearby(0);
+ EndDialog(hDlg, 0);
+ return TRUE;
+ case IDC_IGNORE_ALL:
+ g_bAssertsEnabled = false;
+ EndDialog(hDlg, 0);
+ return TRUE;
+ case IDC_BREAK:
+ g_bBreak = true;
+ EndDialog(hDlg, 0);
+ return TRUE;
+ }
+ case WM_KEYDOWN:
+ {
+ // Escape?
+ if (wParam == 2)
+ {
+ // Ignore this assert
+ EndDialog(hDlg, 0);
+ return TRUE;
+ }
+
+ break;
+ }
+
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+static HWND g_hBestParentWindow = nullptr;
+
+static BOOL CALLBACK ParentWindowEnumProc(
+ HWND hWnd, // handle to parent window
+ LPARAM lParam // application-defined value
+)
+{
+ if (IsWindowVisible(hWnd))
+ {
+ DWORD procID;
+ GetWindowThreadProcessId(hWnd, &procID);
+ if (procID == (DWORD)lParam)
+ {
+ g_hBestParentWindow = hWnd;
+ return FALSE; // don't iterate any more.
+ }
+ }
+
+ return TRUE;
+}
+
+static HWND FindLikelyParentWindow()
+{
+ // Enumerate top-level windows and take the first visible one with our processID.
+ g_hBestParentWindow = nullptr;
+ EnumWindows(ParentWindowEnumProc, GetCurrentProcessId());
+ return g_hBestParentWindow;
+}
+
+bool DoNewAssertDialog(const char *pFilename, int line, const char *pExpression)
+{
+ if (AreAssertsDisabled())
+ return false;
+
+ // If they have the old mode enabled (always break immediately), then just break right into
+ // the debugger like we used to do.
+ if (IsDebugBreakEnabled())
+ return true;
+
+ // Have ALL Asserts been disabled?
+ if (!g_bAssertsEnabled)
+ return false;
+
+ // Has this specific Assert been disabled?
+ if (!AreAssertsEnabledInFileLine(pFilename, line))
+ return false;
+
+ // Now create the dialog.
+ g_Info.m_pFilename = pFilename;
+ g_Info.m_iLine = line;
+ g_Info.m_pExpression = pExpression;
+
+ g_bBreak = false;
+
+ HWND hParentWindow = FindLikelyParentWindow();
+ DialogBox(g_hTier0Instance, MAKEINTRESOURCE(IDD_ASSERT_DIALOG), hParentWindow, AssertDialogProc);
+
+ return g_bBreak;
+}
diff --git a/regamedll/public/tier0/assert_dialog.rc b/regamedll/public/tier0/assert_dialog.rc
new file mode 100644
index 000000000..513f46878
--- /dev/null
+++ b/regamedll/public/tier0/assert_dialog.rc
@@ -0,0 +1,117 @@
+//Microsoft Developer Studio generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "winres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// English (U.S.) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+#pragma code_page(1252)
+#endif //_WIN32
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "#include ""afxres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+IDD_ASSERT_DIALOG DIALOG DISCARDABLE 0, 0, 268, 158
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Assert"
+FONT 8, "MS Sans Serif"
+BEGIN
+ LTEXT "File:",IDC_NOID,7,7,23,9
+ LTEXT "c:/gsclient/src/blah.cpp",IDC_FILENAME_CONTROL,36,7,217,8
+ LTEXT "Line:",IDC_NOID,7,18,23,9
+ LTEXT "45",IDC_LINE_CONTROL,36,18,217,8
+ LTEXT "Assert:",IDC_NOID,7,29,23,9
+ CONTROL "ASSERT MESSAGE",IDC_ASSERT_MSG_CTRL,"Static",
+ SS_LEFTNOWORDWRAP | SS_NOPREFIX | WS_GROUP,36,29,217,9
+ DEFPUSHBUTTON "&Break in Debugger",IDC_BREAK,7,49,98,14
+ PUSHBUTTON "&Ignore This Assert",IDC_IGNORE_THIS,7,66,98,14
+ EDITTEXT IDC_IGNORE_NUMTIMES,110,66,24,14,ES_AUTOHSCROLL |
+ ES_NUMBER
+ LTEXT "time(s).",IDC_NOID,138,68,23,8
+ PUSHBUTTON "Always Ignore &This Assert",IDC_IGNORE_ALWAYS,7,84,98,
+ 14
+ PUSHBUTTON "Ignore &Nearby Asserts",IDC_IGNORE_NEARBY,7,102,98,14
+ LTEXT "within",IDC_NOID,109,105,19,8
+ EDITTEXT IDC_IGNORE_NUMLINES,131,102,40,14,ES_AUTOHSCROLL |
+ ES_NUMBER
+ LTEXT "lines.",IDC_NOID,175,105,17,8
+ PUSHBUTTON "Ignore Asserts in This &File",IDC_IGNORE_FILE,7,120,98,
+ 14
+ PUSHBUTTON "Ignore &All Asserts",IDC_IGNORE_ALL,7,137,98,14
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// DESIGNINFO
+//
+
+#ifdef APSTUDIO_INVOKED
+GUIDELINES DESIGNINFO DISCARDABLE
+BEGIN
+ IDD_ASSERT_DIALOG, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 261
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 151
+ END
+END
+#endif // APSTUDIO_INVOKED
+
+#endif // English (U.S.) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/regamedll/public/tier0/dbg.cpp b/regamedll/public/tier0/dbg.cpp
index ebf36c2e4..35c99fe38 100644
--- a/regamedll/public/tier0/dbg.cpp
+++ b/regamedll/public/tier0/dbg.cpp
@@ -1,50 +1,17 @@
-/*
-*
-* This program is free software; you can redistribute it and/or modify it
-* under the terms of the GNU General Public License as published by the
-* Free Software Foundation; either version 2 of the License, or (at
-* your option) any later version.
-*
-* This program is distributed in the hope that it will be useful, but
-* WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-* General Public License for more details.
-*
-* You should have received a copy of the GNU General Public License
-* along with this program; if not, write to the Free Software Foundation,
-* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*
-* In addition, as a special exception, the author gives permission to
-* link the code of this program with the Half-Life Game Engine ("HL
-* Engine") and Modified Game Libraries ("MODs") developed by Valve,
-* L.L.C ("Valve"). You must obey the GNU General Public License in all
-* respects for all of the code used other than the HL Engine and MODs
-* from Valve. If you modify this file, you may extend this exception
-* to your version of the file, but you are not obligated to do so. If
-* you do not wish to do so, delete this exception statement from your
-* version.
-*
-*/
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//
+//===========================================================================//
#include "precompiled.h"
-// Internal structures
-enum
-{
- MAX_GROUP_NAME_LENGTH = 48
-};
-
-struct SpewGroup_t
-{
- char m_GroupName[MAX_GROUP_NAME_LENGTH];
- int m_Level;
-};
-
-
// Templates to assist in validating pointers:
void _AssertValidReadPtr(void *ptr, int count)
{
-#ifdef _WIN32
+#if defined(_WIN32)
Assert(!IsBadReadPtr(ptr, count));
#else
Assert(ptr);
@@ -54,7 +21,7 @@ void _AssertValidReadPtr(void *ptr, int count)
void _AssertValidWritePtr(void *ptr, int count)
{
-#ifdef _WIN32
+#if defined(_WIN32)
Assert(!IsBadWritePtr(ptr, count));
#else
Assert(ptr);
@@ -63,26 +30,29 @@ void _AssertValidWritePtr(void *ptr, int count)
void _AssertValidReadWritePtr(void *ptr, int count)
{
-#ifdef _WIN32
+#if defined(_WIN32)
Assert(!(IsBadWritePtr(ptr, count) || IsBadReadPtr(ptr, count)));
#else
Assert(ptr);
#endif
}
+#if defined(DBGFLAG_ASSERT)
void AssertValidStringPtr(const char *ptr, int maxchar)
{
-#ifdef _WIN32
+#if defined(_WIN32)
Assert(!IsBadStringPtr(ptr, maxchar));
#else
Assert(ptr);
#endif
}
+#endif // DBGFLAG_ASSERT
// Globals
-SpewRetval_t DefaultSpewFunc(SpewType_t type, const char *pMsg)
+SpewRetval_t DefaultSpewFunc(SpewType_t type, int level, const char *pMsg)
{
printf("%s", pMsg);
+
if (type == SPEW_ASSERT)
return SPEW_DEBUGGER;
else if (type == SPEW_ERROR)
@@ -93,13 +63,10 @@ SpewRetval_t DefaultSpewFunc(SpewType_t type, const char *pMsg)
static SpewOutputFunc_t s_SpewOutputFunc = DefaultSpewFunc;
-static const char *s_pFileName;
-static int s_Line;
-static SpewType_t s_SpewType;
-
-static SpewGroup_t *s_pSpewGroups = 0;
-static int s_GroupCount = 0;
-static int s_DefaultLevel = 0;
+static const char *s_pMessage = nullptr;
+static const char *s_pFileName = nullptr;
+static int s_Line = 0;
+static SpewType_t s_SpewType = SPEW_MESSAGE;
// Spew output management.
void SpewOutputFunc(SpewOutputFunc_t func)
@@ -119,54 +86,92 @@ SpewOutputFunc_t GetSpewOutputFunc()
}
}
+void _ExitOnFatalAssert()
+{
+ Msg("Fatal assert failed: %s, file %s line %d. Application exiting.\n", s_pMessage, s_pFileName, s_Line);
+
+#if defined(WIN32)
+ TerminateProcess(GetCurrentProcess(), EXIT_FAILURE); // die, die RIGHT NOW! (don't call exit() so destructors will not get run)
+#else
+ exit(EXIT_FAILURE); // forcefully shutdown of the process without destructors running
+#endif
+}
+
// Spew functions
void _SpewInfo(SpewType_t type, const char *pFile, int line)
{
- // Only grab the file name. Ignore the path.
- const char *pSlash = strrchr(pFile, '\\');
- const char *pSlash2 = strrchr(pFile, '/');
+ // Only grab the file name. Ignore the path
+ const char *pSlash = Q_strrchr(pFile, '\\');
+ const char *pSlash2 = Q_strrchr(pFile, '/');
+
if (pSlash < pSlash2) pSlash = pSlash2;
s_pFileName = pSlash ? pSlash + 1 : pFile;
- s_Line = line;
- s_SpewType = type;
+ s_Line = line;
+ s_SpewType = type;
}
-SpewRetval_t _SpewMessage(SpewType_t spewType, const char *pMsgFormat, va_list args)
+SpewRetval_t _SpewMessageV(SpewType_t spewType, int level, const char *pMsgFormat, va_list args)
{
- char pTempBuffer[1024];
+ if (level < 0) level = DBG_DEFAULT_LEVEL;
+
+ static char szTempBuffer[4096]{};
+ szTempBuffer[0] = '\0';
+ s_pMessage = szTempBuffer;
+
+ // check that we won't artifically truncate the string
+ assert(Q_strlen(pMsgFormat) < sizeof(szTempBuffer));
// Printf the file and line for warning + assert only...
int len = 0;
- if ((spewType == SPEW_ASSERT))
+ if (spewType == SPEW_ASSERT)
+ {
+ len = Q_snprintf(szTempBuffer, sizeof(szTempBuffer), "%s (%d) : ", s_pFileName, s_Line);
+ }
+
+ if (len == -1)
{
- len = sprintf(pTempBuffer, "%s (%d) : ", s_pFileName, s_Line);
+ return SPEW_ABORT;
}
// Create the message....
- len += vsprintf(&pTempBuffer[len], pMsgFormat, args);
+ len += Q_vsnprintf(&szTempBuffer[len], sizeof(szTempBuffer) - len, pMsgFormat, args);
+
+ // Use normal assert here; to avoid recursion
+ assert(len < sizeof(szTempBuffer));
// Add \n for warning and assert
if ((spewType == SPEW_ASSERT))
{
- len += sprintf(&pTempBuffer[len], "\n");
+ len += Q_snprintf(&szTempBuffer[len], sizeof(szTempBuffer) - len, "\n");
+ Plat_OutputDebugString(szTempBuffer);
}
- assert(len < 1024); // use normal assert here; to avoid recursion.
+ // use normal assert here; to avoid recursion
+ assert((size_t)len < (sizeof(szTempBuffer) / sizeof(szTempBuffer[0]) - 1));
assert(s_SpewOutputFunc);
// direct it to the appropriate target(s)
- SpewRetval_t ret = s_SpewOutputFunc(spewType, pTempBuffer);
+ SpewRetval_t ret = s_SpewOutputFunc(spewType, level, szTempBuffer);
switch (ret)
{
// Put the break into the macro so it would occur in the right place
- //case SPEW_DEBUGGER:
- // DebuggerBreak();
- // break;
+ case SPEW_DEBUGGER:
+ {
+ if (spewType != SPEW_ASSERT)
+ DebuggerBreakIfDebugging();
+ break;
+ }
case SPEW_ABORT:
- // MessageBox(nullptr, "Error in _SpewMessage", "Error", MB_OK);
- exit(0);
+ {
+#if defined(WIN32)
+ TerminateProcess(GetCurrentProcess(), EXIT_FAILURE); // die, die RIGHT NOW! (don't call exit() so destructors will not get run)
+#else
+ exit(EXIT_FAILURE); // forcefully shutdown of the process without destructors running
+#endif
+ break;
+ }
default:
break;
}
@@ -174,81 +179,52 @@ SpewRetval_t _SpewMessage(SpewType_t spewType, const char *pMsgFormat, va_list a
return ret;
}
-SpewRetval_t _SpewMessage(const char *pMsgFormat, ...)
-{
- va_list args;
- va_start(args, pMsgFormat);
- SpewRetval_t ret = _SpewMessage(s_SpewType, pMsgFormat, args);
- va_end(args);
- return ret;
-}
-
-SpewRetval_t _DSpewMessage(const char *pGroupName, int level, const char *pMsgFormat, ...)
-{
- if (!IsSpewActive(pGroupName, level))
- return SPEW_CONTINUE;
-
- va_list args;
- va_start(args, pMsgFormat);
- SpewRetval_t ret = _SpewMessage(s_SpewType, pMsgFormat, args);
- va_end(args);
- return ret;
-}
+#if defined(_WIN32)
+// Returns true if they want to break in the debugger
+bool DoNewAssertDialog(const char *pFile, int line, const char *pExpression);
+#endif
-void Msg(const char *pMsgFormat, ...)
+bool _SpewAssertDialog()
{
- va_list args;
- va_start(args, pMsgFormat);
- _SpewMessage(SPEW_MESSAGE, pMsgFormat, args);
- va_end(args);
+#if defined(_WIN32)
+ return DoNewAssertDialog(s_pFileName, s_Line, s_pMessage);
+#else
+ return false;
+#endif
}
-void DMsg(const char *pGroupName, int level, const char *pMsgFormat, ...)
+SpewRetval_t _SpewAssert(const char *pFile, int line, int level, const char *pMsgFormat, ...)
{
- if (!IsSpewActive(pGroupName, level))
- return;
+ _SpewInfo(SPEW_ASSERT, pFile, line);
va_list args;
va_start(args, pMsgFormat);
- _SpewMessage(SPEW_MESSAGE, pMsgFormat, args);
- va_end(args);
-}
-
-void Warning(const char *pMsgFormat, ...)
-{
- va_list args;
- va_start(args, pMsgFormat);
- _SpewMessage(SPEW_WARNING, pMsgFormat, args);
+ SpewRetval_t ret = _SpewMessageV(s_SpewType, level, pMsgFormat, args);
va_end(args);
+ return ret;
}
-void DWarning(const char *pGroupName, int level, const char *pMsgFormat, ...)
+void _Msg(int level, const char *pMsgFormat, ...)
{
- if (!IsSpewActive(pGroupName, level))
- return;
-
va_list args;
va_start(args, pMsgFormat);
- _SpewMessage(SPEW_WARNING, pMsgFormat, args);
+ _SpewMessageV(SPEW_MESSAGE, level, pMsgFormat, args);
va_end(args);
}
-void Log(const char *pMsgFormat, ...)
+void _Warning(int level, const char *pMsgFormat, ...)
{
va_list args;
va_start(args, pMsgFormat);
- _SpewMessage(SPEW_LOG, pMsgFormat, args);
+ _SpewMessageV(SPEW_WARNING, level, pMsgFormat, args);
va_end(args);
}
-void DLog(const char *pGroupName, int level, const char *pMsgFormat, ...)
+void _Log(int level, const char *pMsgFormat, ...)
{
- if (!IsSpewActive(pGroupName, level))
- return;
-
va_list args;
va_start(args, pMsgFormat);
- _SpewMessage(SPEW_LOG, pMsgFormat, args);
+ _SpewMessageV(SPEW_LOG, level, pMsgFormat, args);
va_end(args);
}
@@ -256,146 +232,6 @@ void Error(const char *pMsgFormat, ...)
{
va_list args;
va_start(args, pMsgFormat);
- _SpewMessage(SPEW_ERROR, pMsgFormat, args);
+ _SpewMessageV(SPEW_ERROR, DBG_DEFAULT_LEVEL, pMsgFormat, args);
va_end(args);
}
-
-// A couple of super-common dynamic spew messages, here for convenience
-// These looked at the "developer" group, print if it's level 1 or higher
-void DevMsg(int level, char const *pMsgFormat, ...)
-{
- if (!IsSpewActive("developer", level))
- return;
-
- va_list args;
- va_start(args, pMsgFormat);
- _SpewMessage(SPEW_MESSAGE, pMsgFormat, args);
- va_end(args);
-}
-
-void DevWarning(int level, const char *pMsgFormat, ...)
-{
- if (!IsSpewActive("developer", level))
- return;
-
- va_list args;
- va_start(args, pMsgFormat);
- _SpewMessage(SPEW_WARNING, pMsgFormat, args);
- va_end(args);
-}
-
-void DevLog(int level, const char *pMsgFormat, ...)
-{
- if (!IsSpewActive("developer", level))
- return;
-
- va_list args;
- va_start(args, pMsgFormat);
- _SpewMessage(SPEW_LOG, pMsgFormat, args);
- va_end(args);
-}
-
-void DevMsg(const char *pMsgFormat, ...)
-{
- if (!IsSpewActive("developer", 1))
- return;
-
- va_list args;
- va_start(args, pMsgFormat);
- _SpewMessage(SPEW_MESSAGE, pMsgFormat, args);
- va_end(args);
-}
-
-void DevWarning(const char *pMsgFormat, ...)
-{
- va_list args;
- va_start(args, pMsgFormat);
- _SpewMessage(SPEW_WARNING, pMsgFormat, args);
- va_end(args);
-}
-
-void DevLog(const char *pMsgFormat, ...)
-{
- va_list args;
- va_start(args, pMsgFormat);
- _SpewMessage(SPEW_LOG, pMsgFormat, args);
- va_end(args);
-}
-
-// Find a group, return true if found, false if not. Return in ind the
-// index of the found group, or the index of the group right before where the
-// group should be inserted into the list to maintain sorted order.
-bool FindSpewGroup(const char *pGroupName, int *pInd)
-{
- int s = 0;
- if (s_GroupCount)
- {
- int e = (int)(s_GroupCount - 1);
- while (s <= e)
- {
- int m = (s + e) >> 1;
- int cmp = Q_stricmp(pGroupName, s_pSpewGroups[m].m_GroupName);
- if (!cmp)
- {
- *pInd = m;
- return true;
- }
-
- if (cmp < 0)
- e = m - 1;
- else
- s = m + 1;
- }
- }
-
- *pInd = s;
- return false;
-}
-
-// Sets the priority level for a spew group
-void SpewActivate(const char *pGroupName, int level)
-{
- Assert(pGroupName);
-
- // check for the default group first...
- if ((pGroupName[0] == '*') && (pGroupName[1] == '\0'))
- {
- s_DefaultLevel = level;
- return;
- }
-
- // Normal case, search in group list using binary search.
- // If not found, grow the list of groups and insert it into the
- // right place to maintain sorted order. Then set the level.
- int ind;
- if (!FindSpewGroup(pGroupName, &ind))
- {
- // not defined yet, insert an entry.
- s_GroupCount++;
- if (s_pSpewGroups)
- {
- s_pSpewGroups = (SpewGroup_t *)realloc(s_pSpewGroups, s_GroupCount * sizeof(SpewGroup_t));
-
- // shift elements down to preserve order
- int numToMove = s_GroupCount - ind - 1;
- memmove(&s_pSpewGroups[ind + 1], &s_pSpewGroups[ind], numToMove * sizeof(SpewGroup_t));
- }
- else
- s_pSpewGroups = (SpewGroup_t *)malloc(s_GroupCount * sizeof(SpewGroup_t));
-
- Assert(strlen(pGroupName) < MAX_GROUP_NAME_LENGTH);
- strcpy(s_pSpewGroups[ind].m_GroupName, pGroupName);
- }
- s_pSpewGroups[ind].m_Level = level;
-}
-
-// Tests to see if a particular spew is active
-bool IsSpewActive(const char *pGroupName, int level)
-{
- // If we don't find the spew group, use the default level.
- int ind;
- if (FindSpewGroup(pGroupName, &ind))
- return s_pSpewGroups[ind].m_Level >= level;
- else
- return s_DefaultLevel >= level;
-}
diff --git a/regamedll/public/tier0/dbg.h b/regamedll/public/tier0/dbg.h
index 38e992f67..848250414 100644
--- a/regamedll/public/tier0/dbg.h
+++ b/regamedll/public/tier0/dbg.h
@@ -1,30 +1,10 @@
-/*
-*
-* This program is free software; you can redistribute it and/or modify it
-* under the terms of the GNU General Public License as published by the
-* Free Software Foundation; either version 2 of the License, or (at
-* your option) any later version.
-*
-* This program is distributed in the hope that it will be useful, but
-* WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-* General Public License for more details.
-*
-* You should have received a copy of the GNU General Public License
-* along with this program; if not, write to the Free Software Foundation,
-* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*
-* In addition, as a special exception, the author gives permission to
-* link the code of this program with the Half-Life Game Engine ("HL
-* Engine") and Modified Game Libraries ("MODs") developed by Valve,
-* L.L.C ("Valve"). You must obey the GNU General Public License in all
-* respects for all of the code used other than the HL Engine and MODs
-* from Valve. If you modify this file, you may extend this exception
-* to your version of the file, but you are not obligated to do so. If
-* you do not wish to do so, delete this exception statement from your
-* version.
-*
-*/
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//
+//===========================================================================//
#pragma once
@@ -34,16 +14,7 @@
#include
#include
-// dll export stuff
-#ifdef TIER0_DLL_EXPORT
-#define DBG_INTERFACE DLL_EXPORT
-#define DBG_OVERLOAD DLL_GLOBAL_EXPORT
-#define DBG_CLASS DLL_CLASS_EXPORT
-#else
-#define DBG_INTERFACE DLL_IMPORT
-#define DBG_OVERLOAD DLL_GLOBAL_IMPORT
-#define DBG_CLASS DLL_CLASS_IMPORT
-#endif
+#define DBG_DEFAULT_LEVEL 0
// Usage model for the Dbg library
//
@@ -87,22 +58,6 @@
// Msg("Isn't this exciting %d?", 5);
// Error("I'm just thrilled");
//
-// Dynamic Spew messages
-//
-// It is possible to dynamically turn spew on and off. Dynamic spew is
-// identified by a spew group and priority level. To turn spew on for a
-// particular spew group, use SpewActivate("group", level). This will
-// cause all spew in that particular group with priority levels <= the
-// level specified in the SpewActivate function to be printed. Use DSpew
-// to perform the spew:
-//
-// DWarning("group", level, "Oh I feel even yummier!\n");
-//
-// Priority level 0 means that the spew will *always* be printed, and group
-// '*' is the default spew group. If a DWarning is encountered using a group
-// whose priority has not been set, it will use the priority of the default
-// group. The priority of the default group is initially set to 0.
-//
// Spew output
//
// The output of the spew system can be redirected to an externally-supplied
@@ -131,12 +86,6 @@
// }
// );
//
-// Code can be activated based on the dynamic spew groups also. Use
-//
-// DBG_DCODE("group", level,
-// { int x = 5; ++x; }
-// );
-//
// 3. Breaking into the debugger.
//
// To cause an unconditional break into the debugger in debug builds only, use DBG_BREAK
@@ -170,7 +119,7 @@ enum SpewRetval_t
};
// Type of externally defined function used to display debug spew
-typedef SpewRetval_t (*SpewOutputFunc_t)(SpewType_t spewType, const char *pMsg);
+typedef SpewRetval_t (*SpewOutputFunc_t)(SpewType_t spewType, int level, const char *pMsg);
// Used to redirect spew output
void SpewOutputFunc(SpewOutputFunc_t func);
@@ -178,134 +127,220 @@ void SpewOutputFunc(SpewOutputFunc_t func);
// Used ot get the current spew output function
SpewOutputFunc_t GetSpewOutputFunc();
-// Used to manage spew groups and subgroups
-void SpewActivate(const char *pGroupName, int level);
-bool IsSpewActive(const char *pGroupName, int level);
-
// Used to display messages, should never be called directly.
-void _SpewInfo(SpewType_t type, const char *pFile, int line);
-SpewRetval_t _SpewMessage(const char *pMsg, ...);
-SpewRetval_t _DSpewMessage(const char *pGroupName, int level, const char *pMsg, ...);
-
-// Used to define macros, never use these directly.
-#define _Assert(_exp) \
- do { \
- if (!(_exp)) \
- { \
- _SpewInfo(SPEW_ASSERT, __FILE__, __LINE__); \
- if (_SpewMessage("Assertion Failed: " #_exp) == SPEW_DEBUGGER) \
- { \
- DebuggerBreak(); \
- } \
- } \
- } while (0)
-
-#define _AssertMsg(_exp, _msg) \
- do { \
- if (!(_exp)) \
- { \
- _SpewInfo(SPEW_ASSERT, __FILE__, __LINE__); \
- if (_SpewMessage(_msg) == SPEW_DEBUGGER) \
- { \
- DebuggerBreak(); \
- } \
- } \
- } while (0)
-
-#define _AssertFunc(_exp, _f) \
- do { \
- if (!(_exp)) \
- { \
- _SpewInfo(SPEW_ASSERT, __FILE__, __LINE__); \
- SpewRetval_t ret = _SpewMessage("Assertion Failed!" #_exp); \
- _f; \
- if (ret == SPEW_DEBUGGER) \
- { \
- DebuggerBreak(); \
- } \
- } \
- } while (0)
+SpewRetval_t _SpewAssert(const char *pFile, int line, int level, const char *pMsg, ...);
+void _ExitOnFatalAssert();
+bool _SpewAssertDialog();
-#define _AssertEquals(_exp, _expectedValue) \
- do { \
- if ((_exp) != (_expectedValue)) \
- { \
- _SpewInfo(SPEW_ASSERT, __FILE__, __LINE__); \
- SpewRetval_t ret = _SpewMessage("Expected %d but got %d!", (_expectedValue), (_exp)); \
- if (ret == SPEW_DEBUGGER) \
- { \
- DebuggerBreak(); \
- } \
- } \
+inline bool ShouldUseNewAssertDialog()
+{
+#if defined(DBGFLAG_ASSERTDLG)
+ return true; // always show an assert dialog
+#else
+ return Plat_IsInDebugSession(); // only show an assert dialog if the process is being debugged
+#endif // DBGFLAG_ASSERTDLG
+}
+
+#define _AssertMsg(_exp, _msg, _executeExp, _bFatal) \
+ do { \
+ if (!(_exp)) \
+ { \
+ SpewRetval_t ret = _SpewAssert(__FILE__, __LINE__, DBG_DEFAULT_LEVEL, _msg); \
+ if (ret == SPEW_DEBUGGER) \
+ { \
+ if (!ShouldUseNewAssertDialog() || _SpewAssertDialog()) \
+ DebuggerBreakIfDebugging(); \
+ } \
+ _executeExp; \
+ if (_bFatal) \
+ _ExitOnFatalAssert(); \
+ } \
} while (0)
-#define _AssertFloatEquals(_exp, _expectedValue, _tol) \
- do { \
- if (fabs((_exp) - (_expectedValue)) > (_tol)) \
- { \
- _SpewInfo(SPEW_ASSERT, __FILE__, __LINE__); \
- SpewRetval_t ret = _SpewMessage("Expected %f but got %f!", (_expectedValue), (_exp)); \
- if (ret == SPEW_DEBUGGER) \
- { \
- DebuggerBreak(); \
- } \
- } \
+#define _AssertMsgWarn(_exp, _msg) \
+ if (!(_exp)) \
+ { \
+ Warning("%s (%d) : " _msg, __FILE__, __LINE__); \
+ } \
+
+#define _AssertMsgOnce(_exp, _msg, _bFatal) \
+ do { \
+ static bool fAsserted = false; \
+ if (!fAsserted && !(_exp)) \
+ { \
+ fAsserted = true; \
+ _AssertMsg(_exp, _msg, (fAsserted = true), _bFatal); \
+ } \
} while (0)
// Spew macros...
-#ifdef _DEBUG
-
-#define Assert(_exp) _Assert(_exp)
-#define AssertMsg(_exp, _msg) _AssertMsg(_exp, _msg)
-#define AssertFunc(_exp, _f) _AssertFunc(_exp, _f)
-#define AssertEquals(_exp, _expectedValue) _AssertEquals(_exp, _expectedValue)
-#define AssertFloatEquals(_exp, _expectedValue, _tol) _AssertFloatEquals(_exp, _expectedValue, _tol)
-#define Verify(_exp) _Assert(_exp)
-
-#define AssertMsg1(_exp, _msg, a1) _AssertMsg(_exp, CDbgFmtMsg(_msg, a1))
-#define AssertMsg2(_exp, _msg, a1, a2) _AssertMsg(_exp, CDbgFmtMsg(_msg, a1, a2))
-#define AssertMsg3(_exp, _msg, a1, a2, a3) _AssertMsg(_exp, CDbgFmtMsg(_msg, a1, a2, a3))
-#define AssertMsg4(_exp, _msg, a1, a2, a3, a4) _AssertMsg(_exp, CDbgFmtMsg(_msg, a1, a2, a3, a4))
-#define AssertMsg5(_exp, _msg, a1, a2, a3, a4, a5) _AssertMsg(_exp, CDbgFmtMsg(_msg, a1, a2, a3, a4, a5))
-#define AssertMsg6(_exp, _msg, a1, a2, a3, a4, a5, a6) _AssertMsg(_exp, CDbgFmtMsg(_msg, a1, a2, a3, a4, a5, a6))
-#define AssertMsg6(_exp, _msg, a1, a2, a3, a4, a5, a6) _AssertMsg(_exp, CDbgFmtMsg(_msg, a1, a2, a3, a4, a5, a6))
-#define AssertMsg7(_exp, _msg, a1, a2, a3, a4, a5, a6, a7) _AssertMsg(_exp, CDbgFmtMsg(_msg, a1, a2, a3, a4, a5, a6, a7))
-#define AssertMsg8(_exp, _msg, a1, a2, a3, a4, a5, a6, a7, a8) _AssertMsg(_exp, CDbgFmtMsg(_msg, a1, a2, a3, a4, a5, a6, a7, a8))
-#define AssertMsg9(_exp, _msg, a1, a2, a3, a4, a5, a6, a7, a8, a9) _AssertMsg(_exp, CDbgFmtMsg(_msg, a1, a2, a3, a4, a5, a6, a7, a8, a9))
-
-#else // _DEBUG
+// AssertFatal macros
+// AssertFatal is used to detect an unrecoverable error condition.
+// If enabled, it may display an assert dialog (if DBGFLAG_ASSERTDLG is turned on or running under the debugger),
+// and always terminates the application
+
+#if defined(DBGFLAG_ASSERTFATAL)
+
+#define AssertWarn(_exp) _AssertMsgWarn(_exp, "Assertion Failed: " #_exp)
+#define AssertFatal(_exp) _AssertMsg(_exp, "Assertion Failed: " #_exp, ((void)0), true)
+#define AssertFatalOnce(_exp) _AssertMsgOnce(_exp, "Assertion Failed: " #_exp, true)
+#define AssertFatalMsg(_exp, _msg) _AssertMsg(_exp, _msg, ((void)0), true)
+#define AssertFatalMsgOnce(_exp, _msg) _AssertMsgOnce(_exp, _msg, true)
+#define AssertFatalFunc(_exp, _f) _AssertMsg(_exp, "Assertion Failed: " #_exp, _f, true)
+#define AssertFatalEquals(_exp, _expectedValue) AssertFatalMsg2((_exp) == (_expectedValue), "Expected %d but got %d!", (_expectedValue), (_exp))
+#define AssertFatalFloatEquals(_exp, _expectedValue, _tol) AssertFatalMsg2(fabs((_exp) - (_expectedValue)) <= (_tol), "Expected %f but got %f!", (_expectedValue), (_exp))
+#define VerifyFatal(_exp) AssertFatal(_exp)
+#define VerifyEqualsFatal(_exp, _expectedValue) AssertFatalEquals(_exp, _expectedValue)
+
+#if defined(_DEBUG)
+ #define DbgVerifyFatal(_exp) AssertFatal(_exp)
+#else
+ #define DbgVerifyFatal(_exp) ((void)0)
+#endif
-#define Assert(_exp) ((void)0)
-#define AssertMsg(_exp, _msg) ((void)0)
-#define AssertFunc(_exp, _f) ((void)0)
-#define AssertEquals(_exp, _expectedValue) ((void)0)
-#define AssertFloatEquals(_exp, _expectedValue, _tol) ((void)0)
-#define Verify(_exp) (_exp)
-
-#define AssertMsg1(_exp, _msg, a1) ((void)0)
-#define AssertMsg2(_exp, _msg, a1, a2) ((void)0)
-#define AssertMsg3(_exp, _msg, a1, a2, a3) ((void)0)
-#define AssertMsg4(_exp, _msg, a1, a2, a3, a4) ((void)0)
-#define AssertMsg5(_exp, _msg, a1, a2, a3, a4, a5) ((void)0)
-#define AssertMsg6(_exp, _msg, a1, a2, a3, a4, a5, a6) ((void)0)
-#define AssertMsg6(_exp, _msg, a1, a2, a3, a4, a5, a6) ((void)0)
-#define AssertMsg7(_exp, _msg, a1, a2, a3, a4, a5, a6, a7) ((void)0)
-#define AssertMsg8(_exp, _msg, a1, a2, a3, a4, a5, a6, a7, a8) ((void)0)
-#define AssertMsg9(_exp, _msg, a1, a2, a3, a4, a5, a6, a7, a8, a9) ((void)0)
+#define AssertFatalMsg1(_exp, _msg, a1) AssertFatalMsg(_exp, CDbgFmtMsg(_msg, a1).ToString())
+#define AssertFatalMsg2(_exp, _msg, a1, a2) AssertFatalMsg(_exp, CDbgFmtMsg(_msg, a1, a2).ToString())
+#define AssertFatalMsg3(_exp, _msg, a1, a2, a3) AssertFatalMsg(_exp, CDbgFmtMsg(_msg, a1, a2, a3).ToString())
+#define AssertFatalMsg4(_exp, _msg, a1, a2, a3, a4) AssertFatalMsg(_exp, CDbgFmtMsg(_msg, a1, a2, a3, a4).ToString())
+#define AssertFatalMsg5(_exp, _msg, a1, a2, a3, a4, a5) AssertFatalMsg(_exp, CDbgFmtMsg(_msg, a1, a2, a3, a4, a5).ToString())
+#define AssertFatalMsg6(_exp, _msg, a1, a2, a3, a4, a5, a6) AssertFatalMsg(_exp, CDbgFmtMsg(_msg, a1, a2, a3, a4, a5, a6).ToString())
+#define AssertFatalMsg7(_exp, _msg, a1, a2, a3, a4, a5, a6, a7) AssertFatalMsg(_exp, CDbgFmtMsg(_msg, a1, a2, a3, a4, a5, a6, a7).ToString())
+#define AssertFatalMsg8(_exp, _msg, a1, a2, a3, a4, a5, a6, a7, a8) AssertFatalMsg(_exp, CDbgFmtMsg(_msg, a1, a2, a3, a4, a5, a6, a7, a8).ToString())
+#define AssertFatalMsg9(_exp, _msg, a1, a2, a3, a4, a5, a6, a7, a8, a9) AssertFatalMsg(_exp, CDbgFmtMsg(_msg, a1, a2, a3, a4, a5, a6, a7, a8, a9).ToString())
+
+#else // DBGFLAG_ASSERTFATAL
+
+#define AssertWarn(_exp) ((void)0)
+#define AssertFatal(_exp) ((void)0)
+#define AssertFatalOnce(_exp) ((void)0)
+#define AssertFatalMsg(_exp, _msg) ((void)0)
+#define AssertFatalMsgOnce(_exp, _msg) ((void)0)
+#define AssertFatalFunc(_exp, _f) ((void)0)
+#define AssertFatalEquals(_exp, _expectedValue) ((void)0)
+#define AssertFatalFloatEquals(_exp, _expectedValue, _tol) ((void)0)
+#define VerifyFatal(_exp) (_exp)
+#define VerifyEqualsFatal(_exp, _expectedValue) (_exp)
+
+#define DbgVerifyFatal(_exp) (_exp)
+
+#define AssertFatalMsg1(_exp, _msg, a1) ((void)0)
+#define AssertFatalMsg2(_exp, _msg, a1, a2) ((void)0)
+#define AssertFatalMsg3(_exp, _msg, a1, a2, a3) ((void)0)
+#define AssertFatalMsg4(_exp, _msg, a1, a2, a3, a4) ((void)0)
+#define AssertFatalMsg5(_exp, _msg, a1, a2, a3, a4, a5) ((void)0)
+#define AssertFatalMsg6(_exp, _msg, a1, a2, a3, a4, a5, a6) ((void)0)
+#define AssertFatalMsg7(_exp, _msg, a1, a2, a3, a4, a5, a6, a7) ((void)0)
+#define AssertFatalMsg8(_exp, _msg, a1, a2, a3, a4, a5, a6, a7, a8) ((void)0)
+#define AssertFatalMsg9(_exp, _msg, a1, a2, a3, a4, a5, a6, a7, a8, a9) ((void)0)
+
+#endif // DBGFLAG_ASSERTFATAL
+
+#if defined(DBGFLAG_ASSERT)
+
+#define Assert(_exp) _AssertMsg(_exp, "Assertion Failed: " #_exp, ((void)0), false)
+#define AssertMsg_(_exp, _msg) _AssertMsg(_exp, _msg, ((void)0), false)
+#define AssertOnce(_exp) _AssertMsgOnce(_exp, "Assertion Failed: " #_exp, false)
+#define AssertMsgOnce(_exp, _msg) _AssertMsgOnce(_exp, _msg, false)
+#define AssertFunc(_exp, _f) _AssertMsg(_exp, "Assertion Failed: " #_exp, _f, false)
+#define AssertEquals(_exp, _expectedValue) AssertMsg2((_exp) == (_expectedValue), "Expected %d but got %d!", (_expectedValue), (_exp))
+#define AssertFloatEquals(_exp, _expectedValue, _tol) AssertMsg2(fabs((_exp) - (_expectedValue)) <= (_tol), "Expected %f but got %f!", (_expectedValue), (_exp))
+#define Verify(_exp) (_exp)
+#define VerifyEquals(_exp, _expectedValue) AssertEquals(_exp, _expectedValue)
+
+#if defined(_DEBUG)
+ #define DbgVerify(_exp) (_exp)
+ #define DbgAssert(_exp) Assert(_exp)
+ #define DbgAssertMsg(_exp, _msg) AssertMsg(_exp, _msg)
+ #define DbgAssertMsg1(_exp, _msg, a1) AssertMsg1(_exp, _msg, a1)
+ #define DbgAssertMsg2(_exp, _msg, a1, a2) AssertMsg2(_exp, _msg, a1, a2)
+ #define DbgAssertMsg3(_exp, _msg, a1, a2, a3) AssertMsg3(_exp, _msg, a1, a2, a3)
+ #define DbgAssertMsg4(_exp, _msg, a1, a2, a3) AssertMsg4(_exp, _msg, a1, a2, a3, a4)
+ #define DbgAssertMsg5(_exp, _msg, a1, a2, a3) AssertMsg5(_exp, _msg, a1, a2, a3, a4, a5)
+ #define DbgAssertMsg6(_exp, _msg, a1, a2, a3) AssertMsg6(_exp, _msg, a1, a2, a3, a4, a5, a6)
+ #define DbgAssertMsg7(_exp, _msg, a1, a2, a3) AssertMsg7(_exp, _msg, a1, a2, a3, a4, a5, a6, a7)
+ #define DbgAssertMsg8(_exp, _msg, a1, a2, a3) AssertMsg8(_exp, _msg, a1, a2, a3, a4, a5, a6, a7, a8)
+ #define DbgAssertMsg9(_exp, _msg, a1, a2, a3) AssertMsg9(_exp, _msg, a1, a2, a3, a4, a5, a6, a7, a8, a9)
+#else
+ #define DbgVerify(_exp) ((void)0)
+ #define DbgAssert(_exp) ((void)0)
+ #define DbgAssertMsg(_exp, _msg) ((void)0)
+ #define DbgAssertMsg1(_exp, _msg, a1) ((void)0)
+ #define DbgAssertMsg2(_exp, _msg, a1, a2) ((void)0)
+ #define DbgAssertMsg3(_exp, _msg, a1, a2, a3) ((void)0)
+ #define DbgAssertMsg4(_exp, _msg, a1, a2, a3) ((void)0)
+ #define DbgAssertMsg5(_exp, _msg, a1, a2, a3) ((void)0)
+ #define DbgAssertMsg6(_exp, _msg, a1, a2, a3) ((void)0)
+ #define DbgAssertMsg7(_exp, _msg, a1, a2, a3) ((void)0)
+ #define DbgAssertMsg8(_exp, _msg, a1, a2, a3) ((void)0)
+ #define DbgAssertMsg9(_exp, _msg, a1, a2, a3) ((void)0)
+#endif
-#endif // _DEBUG
+#define AssertMsg(_exp, _msg) AssertMsg_(_exp, _msg)
+#define AssertMsg1(_exp, _msg, a1) AssertMsg_(_exp, CDbgFmtMsg(_msg, a1).ToString())
+#define AssertMsg2(_exp, _msg, a1, a2) AssertMsg_(_exp, CDbgFmtMsg(_msg, a1, a2).ToString())
+#define AssertMsg3(_exp, _msg, a1, a2, a3) AssertMsg_(_exp, CDbgFmtMsg(_msg, a1, a2, a3).ToString())
+#define AssertMsg4(_exp, _msg, a1, a2, a3, a4) AssertMsg_(_exp, CDbgFmtMsg(_msg, a1, a2, a3, a4).ToString())
+#define AssertMsg5(_exp, _msg, a1, a2, a3, a4, a5) AssertMsg_(_exp, CDbgFmtMsg(_msg, a1, a2, a3, a4, a5).ToString())
+#define AssertMsg6(_exp, _msg, a1, a2, a3, a4, a5, a6) AssertMsg_(_exp, CDbgFmtMsg(_msg, a1, a2, a3, a4, a5, a6).ToString())
+#define AssertMsg6(_exp, _msg, a1, a2, a3, a4, a5, a6) AssertMsg_(_exp, CDbgFmtMsg(_msg, a1, a2, a3, a4, a5, a6).ToString())
+#define AssertMsg7(_exp, _msg, a1, a2, a3, a4, a5, a6, a7) AssertMsg_(_exp, CDbgFmtMsg(_msg, a1, a2, a3, a4, a5, a6, a7).ToString())
+#define AssertMsg8(_exp, _msg, a1, a2, a3, a4, a5, a6, a7, a8) AssertMsg_(_exp, CDbgFmtMsg(_msg, a1, a2, a3, a4, a5, a6, a7, a8).ToString())
+#define AssertMsg9(_exp, _msg, a1, a2, a3, a4, a5, a6, a7, a8, a9) AssertMsg_(_exp, CDbgFmtMsg(_msg, a1, a2, a3, a4, a5, a6, a7, a8, a9).ToString())
+
+#else // DBGFLAG_ASSERT
+
+#define Assert(_exp) ((void)0)
+#define AssertMsg(_exp, _msg) ((void)0)
+#define AssertOnce(_exp) ((void)0)
+#define AssertMsgOnce(_exp, _msg) ((void)0)
+#define AssertFunc(_exp, _f) ((void)0)
+#define AssertEquals(_exp, _expectedValue) ((void)0)
+#define AssertFloatEquals(_exp, _expectedValue, _tol) ((void)0)
+
+#define Verify(_exp) ((void)0)
+#define VerifyEquals(_exp, _expectedValue) ((void)0)
+
+#define DbgVerify(_exp) ((void)0)
+#define DbgAssert(_exp) ((void)0)
+#define DbgAssertMsg(_exp, _msg) ((void)0)
+#define DbgAssertMsg1(_exp, _msg, a1) ((void)0)
+#define DbgAssertMsg2(_exp, _msg, a1, a2) ((void)0)
+#define DbgAssertMsg3(_exp, _msg, a1, a2, a3) ((void)0)
+#define DbgAssertMsg4(_exp, _msg, a1, a2, a3) ((void)0)
+#define DbgAssertMsg5(_exp, _msg, a1, a2, a3) ((void)0)
+#define DbgAssertMsg6(_exp, _msg, a1, a2, a3) ((void)0)
+#define DbgAssertMsg7(_exp, _msg, a1, a2, a3) ((void)0)
+#define DbgAssertMsg8(_exp, _msg, a1, a2, a3) ((void)0)
+#define DbgAssertMsg9(_exp, _msg, a1, a2, a3) ((void)0)
+
+#define AssertMsg1(_exp, _msg, a1) ((void)0)
+#define AssertMsg2(_exp, _msg, a1, a2) ((void)0)
+#define AssertMsg3(_exp, _msg, a1, a2, a3) ((void)0)
+#define AssertMsg4(_exp, _msg, a1, a2, a3, a4) ((void)0)
+#define AssertMsg5(_exp, _msg, a1, a2, a3, a4, a5) ((void)0)
+#define AssertMsg6(_exp, _msg, a1, a2, a3, a4, a5, a6) ((void)0)
+#define AssertMsg6(_exp, _msg, a1, a2, a3, a4, a5, a6) ((void)0)
+#define AssertMsg7(_exp, _msg, a1, a2, a3, a4, a5, a6, a7) ((void)0)
+#define AssertMsg8(_exp, _msg, a1, a2, a3, a4, a5, a6, a7, a8) ((void)0)
+#define AssertMsg9(_exp, _msg, a1, a2, a3, a4, a5, a6, a7, a8, a9) ((void)0)
+
+#endif // DBGFLAG_ASSERT
+
+// default level versions (level 0)
+#define Msg(...) _Msg (0, __VA_ARGS__)
+#define Warning(...) _Warning(0, __VA_ARGS__)
+#define Log(...) _Log (0, __VA_ARGS__)
+
+// These looked at the "developer" functions
+#define DevMsg(...) _Msg (1, __VA_ARGS__)
+#define DevWarning(...) _Warning(1, __VA_ARGS__)
+#define DevLog(...) _Log (1, __VA_ARGS__)
// These are always compiled in
-void Msg(const char *pMsg, ...);
-void DMsg(const char *pGroupName, int level, const char *pMsg, ...);
-
-void Warning(const char *pMsg, ...);
-void DWarning(const char *pGroupName, int level, const char *pMsg, ...);
-
-void Log(const char *pMsg, ...);
-void DLog(const char *pGroupName, int level, const char *pMsg, ...);
-
-void Error(const char *pMsg, ...);
+void _Msg (int level, const char *pMsg, ...);
+void _Warning(int level, const char *pMsg, ...);
+void _Log (int level, const char *pMsg, ...);
+void Error (const char *pMsg, ...);
// You can use this macro like a runtime assert macro.
// If the condition fails, then Error is called with the message. This macro is called
@@ -320,57 +355,39 @@ void Error(const char *pMsg, ...);
Error msg; \
}
-// A couple of super-common dynamic spew messages, here for convenience
-// These looked at the "developer" group
-void DevMsg(int level, char const* pMsg, ...);
-void DevWarning(int level, const char *pMsg, ...);
-void DevLog(int level, const char *pMsg, ...);
-
-// default level versions (level 1)
-void DevMsg(char const* pMsg, ...);
-void DevWarning(const char *pMsg, ...);
-void DevLog(const char *pMsg, ...);
-
// Code macros, debugger interface
-#ifdef _DEBUG
-#define DBG_CODE(_code) if (0) ; else { _code }
-#define DBG_DCODE(_g, _l, _code) if (IsSpewActive(_g, _l)) { _code } else {}
-#define DBG_BREAK() DebuggerBreak()
+#if defined(_DEBUG)
+ #define DBG_CODE(_code) if (0) ; else { _code }
+ #define DBG_DCODE(_g, _l, _code) if (IsSpewActive(_g, _l)) { _code } else {}
+ #define DBG_BREAK() DebuggerBreakIfDebugging()
#else // _DEBUG
-#define DBG_CODE(_code) ((void)0)
-#define DBG_DCODE(_g, _l, _code) ((void)0)
-#define DBG_BREAK() ((void)0)
+ #define DBG_CODE(_code) ((void)0)
+ #define DBG_DCODE(_g, _l, _code) ((void)0)
+ #define DBG_BREAK() ((void)0)
#endif // _DEBUG
-// Macro to assist in asserting constant invariants during compilation
-#define UID_PREFIX generated_id_
-#define UID_CAT1(a, c) a ## c
-#define UID_CAT2(a, c) UID_CAT1(a,c)
-#define UNIQUE_ID UID_CAT2(UID_PREFIX, __LINE__)
-
-#ifdef _DEBUG
-#define COMPILE_TIME_ASSERT(pred) switch(0){case 0:case pred:;}
-#define ASSERT_INVARIANT(pred) static void UNIQUE_ID() { COMPILE_TIME_ASSERT(pred) }
-#else
-#define COMPILE_TIME_ASSERT(pred)
-#define ASSERT_INVARIANT(pred)
-#endif
-
// Templates to assist in validating pointers:
// Have to use these stubs so we don't have to include windows.h here.
void _AssertValidReadPtr(void *ptr, int count = 1);
void _AssertValidWritePtr(void *ptr, int count = 1);
void _AssertValidReadWritePtr(void *ptr, int count = 1);
- void AssertValidStringPtr(const char *ptr, int maxchar = 0xFFFFFF);
-template inline void AssertValidReadPtr(T *ptr, int count = 1) { _AssertValidReadPtr((void *)ptr, count); }
-template inline void AssertValidWritePtr(T *ptr, int count = 1) { _AssertValidWritePtr((void *)ptr, count); }
-template inline void AssertValidReadWritePtr(T *ptr, int count = 1) { _AssertValidReadWritePtr((void *)ptr, count); }
-
-#define AssertValidThis() AssertValidReadWritePtr(this, sizeof(*this))
+#if defined(DBGFLAG_ASSERT)
+ void AssertValidStringPtr(const char *ptr, int maxchar = 0xFFFFFF);
+ template inline void AssertValidReadPtr(T *ptr, int count = 1) { _AssertValidReadPtr((void *)ptr, count); }
+ template inline void AssertValidWritePtr(T *ptr, int count = 1) { _AssertValidWritePtr((void *)ptr, count); }
+ template inline void AssertValidReadWritePtr(T *ptr, int count = 1) { _AssertValidReadWritePtr((void *)ptr, count); }
+ #define AssertValidThis() AssertValidReadWritePtr(this, sizeof(*this))
+#else
+ #define AssertValidStringPtr(...) ((void)0)
+ #define AssertValidReadPtr(...) ((void)0)
+ #define AssertValidWritePtr(...) ((void)0)
+ #define AssertValidReadWritePtr(...) ((void)0)
+ #define AssertValidThis() ((void)0)
+#endif // #if defined(DBGFLAG_ASSERT)
// Macro to protect functions that are not reentrant
-#ifdef _DEBUG
+#if defined(_DEBUG)
class CReentryGuard
{
public:
@@ -406,6 +423,7 @@ class CDbgFmtMsg
va_start(arg_ptr, pszFormat);
_vsnprintf(m_szBuf, sizeof(m_szBuf) - 1, pszFormat, arg_ptr);
va_end(arg_ptr);
+
m_szBuf[sizeof(m_szBuf) - 1] = '\0';
}
@@ -414,14 +432,11 @@ class CDbgFmtMsg
return m_szBuf;
}
+ const char *ToString() const
+ {
+ return m_szBuf;
+ }
+
private:
char m_szBuf[256];
};
-
-// Embed debug info in each file.
-//#ifdef _WIN32
-//#ifdef _DEBUG
-//#pragma comment(compiler)
-//#pragma comment(exestr,"*** DEBUG file detected, Last Compile: " __DATE__ ", " __TIME__ " ***")
-//#endif
-//#endif
diff --git a/regamedll/public/tier0/platform.h b/regamedll/public/tier0/platform.h
index c10ae8b9b..5703cf53b 100644
--- a/regamedll/public/tier0/platform.h
+++ b/regamedll/public/tier0/platform.h
@@ -41,7 +41,14 @@
#endif
// Used to step into the debugger
-#define DebuggerBreak() __asm { int 3 }
+#if defined(__GNUC__) && !defined(__clang__)
+ #define DebuggerBreak() __asm__ __volatile__("int3;")
+#else
+ #define DebuggerBreak() __asm { int 3 }
+#endif
+
+#define DebuggerBreakIfDebugging() if (Plat_IsInDebugSession()) { DebuggerBreak(); }
+#define DebuggerSegFault() { volatile int *null = 0; *null = 0; }
// C functions for external declarations that call the appropriate C++ methods
#ifndef EXPORT
@@ -105,6 +112,37 @@
#endif
#endif
+//
+// Macro to assist in asserting constant invariants during compilation
+
+#define STRINGIFY_INTERNAL(x) #x
+#define STRINGIFY(x) STRINGIFY_INTERNAL(x)
+
+// This implementation of compile time assert has zero cost (so it can safely be
+// included in release builds) and can be used at file scope or function scope.
+#define COMPILE_TIME_ASSERT(pred) static_assert(pred, "Compile time assert constraint is not true: " #pred)
+
+// ASSERT_INVARIANT used to be needed in order to allow COMPILE_TIME_ASSERTs at global
+// scope. However the new COMPILE_TIME_ASSERT macro supports that by default.
+#define ASSERT_INVARIANT(pred) COMPILE_TIME_ASSERT(pred)
+
+// Macro to assist in asserting constant invariants during compilation
+//
+// If available use static_assert instead of weird language tricks. This
+// leads to much more readable messages when compile time assert constraints
+// are violated.
+#if !defined(OSX) && (_MSC_VER > 1500 || __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5))
+ #define PLAT_COMPILE_TIME_ASSERT(pred) static_assert(pred, "Compile time assert constraint is not true: " #pred)
+#else
+ #define PLAT_COMPILE_TIME_ASSERT(pred) typedef int UNIQUE_ID[ (pred) ? 1 : -1]
+#endif
+
+bool Plat_IsInDebugSession();
+void Plat_DebugString(const char *psz);
+void Plat_OutputDebugString(const char *psz);
+void Plat_OutputDebugStringRaw(const char *psz);
+const char *Plat_GetCommandLine();
+
// Methods to invoke the constructor, copy constructor, and destructor
template
inline void Construct(T *pMemory)
diff --git a/regamedll/public/tier0/platform_posix.cpp b/regamedll/public/tier0/platform_posix.cpp
new file mode 100644
index 000000000..202040b90
--- /dev/null
+++ b/regamedll/public/tier0/platform_posix.cpp
@@ -0,0 +1,113 @@
+/*
+*
+* This program is free software; you can redistribute it and/or modify it
+* under the terms of the GNU General Public License as published by the
+* Free Software Foundation; either version 2 of the License, or (at
+* your option) any later version.
+*
+* This program is distributed in the hope that it will be useful, but
+* WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*
+* In addition, as a special exception, the author gives permission to
+* link the code of this program with the Half-Life Game Engine ("HL
+* Engine") and Modified Game Libraries ("MODs") developed by Valve,
+* L.L.C ("Valve"). You must obey the GNU General Public License in all
+* respects for all of the code used other than the HL Engine and MODs
+* from Valve. If you modify this file, you may extend this exception
+* to your version of the file, but you are not obligated to do so. If
+* you do not wish to do so, delete this exception statement from your
+* version.
+*
+*/
+
+#include "precompiled.h"
+
+bool Plat_IsInDebugSession()
+{
+#if defined(OSX)
+ int mib[4];
+ struct kinfo_proc info;
+ size_t size;
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_PROC;
+ mib[2] = KERN_PROC_PID;
+ mib[3] = getpid();
+ size = sizeof(info);
+ info.kp_proc.p_flag = 0;
+ sysctl(mib, 4, &info, &size, NULL, 0);
+ bool result = ((info.kp_proc.p_flag & P_TRACED) == P_TRACED);
+ return result;
+#elif defined(_LINUX)
+ char s[256];
+ snprintf(s, 256, "/proc/%d/cmdline", getppid());
+ FILE *fp = fopen(s, "r");
+ if (fp)
+ {
+ fread(s, 256, 1, fp);
+ fclose(fp);
+ return (0 == strncmp(s, "gdb", 3));
+ }
+ return false;
+#endif
+}
+
+void Plat_OutputDebugStringRaw(const char *psz)
+{
+ fprintf(stderr, "%s", psz);
+}
+
+void Plat_OutputDebugString(const char *psz)
+{
+ fprintf(stderr, "%s", psz);
+}
+
+void Plat_DebugString(const char *psz)
+{
+ fprintf(stderr, "%s", psz);
+}
+
+static char g_CmdLine[2048]{};
+
+const char *Plat_GetCommandLine()
+{
+#if defined(_LINUX)
+ static bool commandline_initialized = false;
+ if (!commandline_initialized)
+ {
+ commandline_initialized = true;
+
+ FILE *fp = fopen("/proc/self/cmdline", "rb");
+ if (fp)
+ {
+ size_t nCharRead = 0;
+
+ // -1 to leave room for the '\0'
+ nCharRead = fread(g_CmdLine, sizeof(g_CmdLine[0]), ARRAYSIZE(g_CmdLine) - 1, fp);
+ if (feof(fp) && !ferror(fp)) // Should have read the whole command line without error
+ {
+ Assert(nCharRead < ARRAYSIZE(g_CmdLine));
+
+ for (int i = 0; i < nCharRead; i++)
+ {
+ if (!g_CmdLine[i])
+ g_CmdLine[i] = ' ';
+ }
+
+ g_CmdLine[nCharRead] = '\0';
+ }
+
+ fclose(fp);
+ }
+
+ Assert(g_CmdLine[0]);
+ }
+#endif // LINUX
+
+ return g_CmdLine;
+}
diff --git a/regamedll/public/tier0/platform_win32.cpp b/regamedll/public/tier0/platform_win32.cpp
new file mode 100644
index 000000000..0ffbf7cf3
--- /dev/null
+++ b/regamedll/public/tier0/platform_win32.cpp
@@ -0,0 +1,57 @@
+/*
+*
+* This program is free software; you can redistribute it and/or modify it
+* under the terms of the GNU General Public License as published by the
+* Free Software Foundation; either version 2 of the License, or (at
+* your option) any later version.
+*
+* This program is distributed in the hope that it will be useful, but
+* WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*
+* In addition, as a special exception, the author gives permission to
+* link the code of this program with the Half-Life Game Engine ("HL
+* Engine") and Modified Game Libraries ("MODs") developed by Valve,
+* L.L.C ("Valve"). You must obey the GNU General Public License in all
+* respects for all of the code used other than the HL Engine and MODs
+* from Valve. If you modify this file, you may extend this exception
+* to your version of the file, but you are not obligated to do so. If
+* you do not wish to do so, delete this exception statement from your
+* version.
+*
+*/
+
+#include "precompiled.h"
+
+bool Plat_IsInDebugSession()
+{
+ return IsDebuggerPresent() != FALSE;
+}
+
+void Plat_OutputDebugStringRaw(const char *psz)
+{
+ OutputDebugString(psz);
+}
+
+void Plat_OutputDebugString(const char *psz)
+{
+ static char buf[4096];
+ int len = Q_snprintf(buf, sizeof(buf), "%s", psz);
+ Assert(len > 0);
+ OutputDebugString(buf);
+}
+
+void Plat_DebugString(const char *psz)
+{
+ Plat_OutputDebugString(psz);
+}
+
+const char *Plat_GetCommandLine()
+{
+ return GetCommandLineA();
+}
diff --git a/regamedll/public/tier0/resource.h b/regamedll/public/tier0/resource.h
new file mode 100644
index 000000000..d261901a6
--- /dev/null
+++ b/regamedll/public/tier0/resource.h
@@ -0,0 +1,44 @@
+/*
+*
+* Copyright (c) 1996-2002, Valve LLC. All rights reserved.
+*
+* This product contains software technology licensed from Id
+* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
+* All Rights Reserved.
+*
+* Use, distribution, and modification of this source code and/or resulting
+* object code is restricted to non-commercial enhancements to products from
+* Valve LLC. All other use, distribution, or modification is prohibited
+* without written permission from Valve LLC.
+*
+*/
+
+//{{NO_DEPENDENCIES}}
+// Microsoft Developer Studio generated include file.
+// Used by assert_dialog.rc
+//
+
+#define IDD_ASSERT_DIALOG 101
+#define IDC_FILENAME_CONTROL 1000
+#define IDC_LINE_CONTROL 1001
+#define IDC_IGNORE_FILE 1002
+#define IDC_IGNORE_NEARBY 1003
+#define IDC_IGNORE_NUMLINES 1004
+#define IDC_IGNORE_THIS 1005
+#define IDC_BREAK 1006
+#define IDC_IGNORE_ALL 1008
+#define IDC_IGNORE_ALWAYS 1009
+#define IDC_IGNORE_NUMTIMES 1010
+#define IDC_ASSERT_MSG_CTRL 1011
+#define IDC_NOID -1
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 103
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1005
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif