Initial commit of Command & Conquer Generals and Command & Conquer Generals Zero Hour source code.
This commit is contained in:
parent
2e338c00cb
commit
3d0ee53a05
6072 changed files with 2283311 additions and 0 deletions
521
GeneralsMD/Code/Libraries/Source/WWVegas/WWDebug/wwdebug.cpp
Normal file
521
GeneralsMD/Code/Libraries/Source/WWVegas/WWDebug/wwdebug.cpp
Normal file
|
@ -0,0 +1,521 @@
|
|||
/*
|
||||
** Command & Conquer Generals Zero Hour(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/***********************************************************************************************
|
||||
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
|
||||
***********************************************************************************************
|
||||
* *
|
||||
* Project Name : WWDebug *
|
||||
* *
|
||||
* $Archive:: /Commando/Code/wwdebug/wwdebug.cpp $*
|
||||
* *
|
||||
* $Author:: Greg_h $*
|
||||
* *
|
||||
* $Modtime:: 1/13/02 1:46p $*
|
||||
* *
|
||||
* $Revision:: 16 $*
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* Functions: *
|
||||
* WWDebug_Install_Message_Handler -- install function for handling the debug messages *
|
||||
* WWDebug_Install_Assert_Handler -- Install a function for handling the assert messages *
|
||||
* WWDebug_Install_Trigger_Handler -- install a trigger handler function *
|
||||
* WWDebug_Printf -- Internal function for passing messages to installed handler *
|
||||
* WWDebug_Assert_Fail -- Internal function for passing assert messages to installed handler *
|
||||
* WWDebug_Assert_Fail_Print -- Internal function, passes assert message to handler *
|
||||
* WWDebug_Check_Trigger -- calls the user-installed debug trigger handler *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
|
||||
#include "wwdebug.h"
|
||||
#include <windows.h>
|
||||
//#include "win.h" can use this if allowed to see wwlib
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
#include "except.h"
|
||||
|
||||
|
||||
static PrintFunc _CurMessageHandler = NULL;
|
||||
static AssertPrintFunc _CurAssertHandler = NULL;
|
||||
static TriggerFunc _CurTriggerHandler = NULL;
|
||||
static ProfileFunc _CurProfileStartHandler = NULL;
|
||||
static ProfileFunc _CurProfileStopHandler = NULL;
|
||||
|
||||
// Convert the latest system error into a string and return a pointer to
|
||||
// a static buffer containing the error string.
|
||||
|
||||
void Convert_System_Error_To_String(int id, char* buffer, int buf_len)
|
||||
{
|
||||
#ifndef _UNIX
|
||||
FormatMessage(
|
||||
FORMAT_MESSAGE_FROM_SYSTEM,
|
||||
NULL,
|
||||
id,
|
||||
0,
|
||||
buffer,
|
||||
buf_len,
|
||||
NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
int Get_Last_System_Error()
|
||||
{
|
||||
return GetLastError();
|
||||
}
|
||||
|
||||
/***********************************************************************************************
|
||||
* WWDebug_Install_Message_Handler -- install function for handling the debug messages *
|
||||
* *
|
||||
* INPUT: *
|
||||
* *
|
||||
* OUTPUT: *
|
||||
* *
|
||||
* WARNINGS: *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 2/19/98 GTH : Created. *
|
||||
*=============================================================================================*/
|
||||
PrintFunc WWDebug_Install_Message_Handler(PrintFunc func)
|
||||
{
|
||||
PrintFunc tmp = _CurMessageHandler;
|
||||
_CurMessageHandler = func;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* WWDebug_Install_Assert_Handler -- Install a function for handling the assert messages *
|
||||
* *
|
||||
* INPUT: *
|
||||
* *
|
||||
* OUTPUT: *
|
||||
* *
|
||||
* WARNINGS: *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 2/19/98 GTH : Created. *
|
||||
*=============================================================================================*/
|
||||
AssertPrintFunc WWDebug_Install_Assert_Handler(AssertPrintFunc func)
|
||||
{
|
||||
AssertPrintFunc tmp = _CurAssertHandler;
|
||||
_CurAssertHandler = func;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* WWDebug_Install_Trigger_Handler -- install a trigger handler function *
|
||||
* *
|
||||
* INPUT: *
|
||||
* *
|
||||
* OUTPUT: *
|
||||
* *
|
||||
* WARNINGS: *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 2/24/98 GTH : Created. *
|
||||
*=============================================================================================*/
|
||||
TriggerFunc WWDebug_Install_Trigger_Handler(TriggerFunc func)
|
||||
{
|
||||
TriggerFunc tmp = _CurTriggerHandler;
|
||||
_CurTriggerHandler = func;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* WWDebug_Install_Profile_Start_Handler -- install a profile handler function *
|
||||
* *
|
||||
* INPUT: *
|
||||
* *
|
||||
* OUTPUT: *
|
||||
* *
|
||||
* WARNINGS: *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 2/24/98 GTH : Created. *
|
||||
*=============================================================================================*/
|
||||
ProfileFunc WWDebug_Install_Profile_Start_Handler(ProfileFunc func)
|
||||
{
|
||||
ProfileFunc tmp = _CurProfileStartHandler;
|
||||
_CurProfileStartHandler = func;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* WWDebug_Install_Profile_Stop_Handler -- install a profile handler function *
|
||||
* *
|
||||
* INPUT: *
|
||||
* *
|
||||
* OUTPUT: *
|
||||
* *
|
||||
* WARNINGS: *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 2/24/98 GTH : Created. *
|
||||
*=============================================================================================*/
|
||||
ProfileFunc WWDebug_Install_Profile_Stop_Handler(ProfileFunc func)
|
||||
{
|
||||
ProfileFunc tmp = _CurProfileStopHandler;
|
||||
_CurProfileStopHandler = func;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* WWDebug_Printf -- Internal function for passing messages to installed handler *
|
||||
* *
|
||||
* INPUT: *
|
||||
* *
|
||||
* OUTPUT: *
|
||||
* *
|
||||
* WARNINGS: *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 2/19/98 GTH : Created. *
|
||||
*=============================================================================================*/
|
||||
|
||||
void WWDebug_Printf(const char * format,...)
|
||||
{
|
||||
if (_CurMessageHandler != NULL) {
|
||||
|
||||
va_list va;
|
||||
char buffer[4096];
|
||||
|
||||
va_start(va, format);
|
||||
vsprintf(buffer, format, va);
|
||||
WWASSERT((strlen(buffer) < sizeof(buffer)));
|
||||
|
||||
_CurMessageHandler(WWDEBUG_TYPE_INFORMATION, buffer);
|
||||
va_end(va);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/***********************************************************************************************
|
||||
* WWDebug_Printf_Warning -- Internal function for passing messages to installed handler *
|
||||
* *
|
||||
* INPUT: *
|
||||
* *
|
||||
* OUTPUT: *
|
||||
* *
|
||||
* WARNINGS: *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 2/19/98 GTH : Created. *
|
||||
*=============================================================================================*/
|
||||
|
||||
void WWDebug_Printf_Warning(const char * format,...)
|
||||
{
|
||||
if (_CurMessageHandler != NULL) {
|
||||
|
||||
va_list va;
|
||||
char buffer[4096];
|
||||
|
||||
va_start(va, format);
|
||||
vsprintf(buffer, format, va);
|
||||
WWASSERT((strlen(buffer) < sizeof(buffer)));
|
||||
|
||||
_CurMessageHandler(WWDEBUG_TYPE_WARNING, buffer);
|
||||
va_end(va);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/***********************************************************************************************
|
||||
* WWDebug_Printf_Error -- Internal function for passing messages to installed handler *
|
||||
* *
|
||||
* INPUT: *
|
||||
* *
|
||||
* OUTPUT: *
|
||||
* *
|
||||
* WARNINGS: *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 2/19/98 GTH : Created. *
|
||||
*=============================================================================================*/
|
||||
|
||||
void WWDebug_Printf_Error(const char * format,...)
|
||||
{
|
||||
if (_CurMessageHandler != NULL) {
|
||||
|
||||
va_list va;
|
||||
char buffer[4096];
|
||||
|
||||
va_start(va, format);
|
||||
vsprintf(buffer, format, va);
|
||||
WWASSERT((strlen(buffer) < sizeof(buffer)));
|
||||
|
||||
_CurMessageHandler(WWDEBUG_TYPE_ERROR, buffer);
|
||||
va_end(va);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/***********************************************************************************************
|
||||
* WWDebug_Assert_Fail -- Internal function for passing assert messages to installed handler *
|
||||
* *
|
||||
* INPUT: *
|
||||
* *
|
||||
* OUTPUT: *
|
||||
* *
|
||||
* WARNINGS: *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 2/19/98 GTH : Created. *
|
||||
*=============================================================================================*/
|
||||
#ifdef WWDEBUG
|
||||
void WWDebug_Assert_Fail(const char * expr,const char * file, int line)
|
||||
{
|
||||
if (_CurAssertHandler != NULL) {
|
||||
|
||||
char buffer[4096];
|
||||
sprintf(buffer,"%s (%d) Assert: %s\n",file,line,expr);
|
||||
_CurAssertHandler(buffer);
|
||||
|
||||
} else {
|
||||
|
||||
/*
|
||||
// If the exception handler is try to quit the game then don't show an assert.
|
||||
*/
|
||||
if (Is_Trying_To_Exit()) {
|
||||
ExitProcess(0);
|
||||
}
|
||||
|
||||
char assertbuf[4096];
|
||||
sprintf(assertbuf, "Assert failed\n\n. File %s Line %d", file, line);
|
||||
|
||||
int code = MessageBoxA(NULL, assertbuf, "WWDebug_Assert_Fail", MB_ABORTRETRYIGNORE|MB_ICONHAND|MB_SETFOREGROUND|MB_TASKMODAL);
|
||||
|
||||
if (code == IDABORT) {
|
||||
raise(SIGABRT);
|
||||
_exit(3);
|
||||
}
|
||||
|
||||
if (code == IDRETRY) {
|
||||
_asm int 3;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* _assert -- Catch all asserts by overriding lib function *
|
||||
* *
|
||||
* *
|
||||
* *
|
||||
* INPUT: Assert stuff *
|
||||
* *
|
||||
* OUTPUT: Nothing *
|
||||
* *
|
||||
* WARNINGS: None *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 12/11/2001 3:56PM ST : Created *
|
||||
*=============================================================================================*/
|
||||
#if 0 //(gth) this is giving me link errors for some reason...
|
||||
|
||||
#ifndef W3D_MAX4
|
||||
#ifdef WWDEBUG
|
||||
void __cdecl _assert(void *expr, void *filename, unsigned lineno)
|
||||
{
|
||||
WWDebug_Assert_Fail((const char*)expr, (const char*)filename, lineno);
|
||||
}
|
||||
#endif //WWDEBUG
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* WWDebug_Assert_Fail_Print -- Internal function, passes assert message to handler *
|
||||
* *
|
||||
* INPUT: *
|
||||
* *
|
||||
* OUTPUT: *
|
||||
* *
|
||||
* WARNINGS: *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 2/19/98 GTH : Created. *
|
||||
*=============================================================================================*/
|
||||
#ifdef WWDEBUG
|
||||
void WWDebug_Assert_Fail_Print(const char * expr,const char * file, int line,const char * string)
|
||||
{
|
||||
if (_CurAssertHandler != NULL) {
|
||||
|
||||
char buffer[4096];
|
||||
sprintf(buffer,"%s (%d) Assert: %s %s\n",file,line,expr, string);
|
||||
_CurAssertHandler(buffer);
|
||||
|
||||
} else {
|
||||
|
||||
assert(0);
|
||||
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* WWDebug_Check_Trigger -- calls the user-installed debug trigger handler *
|
||||
* *
|
||||
* INPUT: *
|
||||
* *
|
||||
* OUTPUT: *
|
||||
* *
|
||||
* WARNINGS: *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 2/24/98 GTH : Created. *
|
||||
*=============================================================================================*/
|
||||
bool WWDebug_Check_Trigger(int trigger_num)
|
||||
{
|
||||
if (_CurTriggerHandler != NULL) {
|
||||
return _CurTriggerHandler(trigger_num);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* WWDebug_Profile_Start -- calls the user-installed profile start handler *
|
||||
* *
|
||||
* INPUT: *
|
||||
* *
|
||||
* OUTPUT: *
|
||||
* *
|
||||
* WARNINGS: *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 2/24/98 GTH : Created. *
|
||||
*=============================================================================================*/
|
||||
void WWDebug_Profile_Start( const char * title)
|
||||
{
|
||||
if (_CurProfileStartHandler != NULL) {
|
||||
_CurProfileStartHandler( title );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* WWDebug_Profile_Stop -- calls the user-installed profile start handler *
|
||||
* *
|
||||
* INPUT: *
|
||||
* *
|
||||
* OUTPUT: *
|
||||
* *
|
||||
* WARNINGS: *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 2/24/98 GTH : Created. *
|
||||
*=============================================================================================*/
|
||||
void WWDebug_Profile_Stop( const char * title)
|
||||
{
|
||||
if (_CurProfileStopHandler != NULL) {
|
||||
_CurProfileStopHandler( title );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
#ifdef WWDEBUG
|
||||
/***********************************************************************************************
|
||||
* WWDebug_DBWin32_Message_Handler -- *
|
||||
* *
|
||||
* INPUT: *
|
||||
* *
|
||||
* OUTPUT: *
|
||||
* *
|
||||
* WARNINGS: *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 10/30/98 BMG : Created. *
|
||||
*=============================================================================================*/
|
||||
void WWDebug_DBWin32_Message_Handler( const char * str )
|
||||
{
|
||||
|
||||
HANDLE heventDBWIN; /* DBWIN32 synchronization object */
|
||||
HANDLE heventData; /* data passing synch object */
|
||||
HANDLE hSharedFile; /* memory mapped file shared data */
|
||||
LPSTR lpszSharedMem;
|
||||
|
||||
/* make sure DBWIN is open and waiting */
|
||||
heventDBWIN = OpenEvent(EVENT_MODIFY_STATE, FALSE, "DBWIN_BUFFER_READY");
|
||||
if ( !heventDBWIN )
|
||||
{
|
||||
//MessageBox(NULL, "DBWIN_BUFFER_READY nonexistent", NULL, MB_OK);
|
||||
return;
|
||||
}
|
||||
|
||||
/* get a handle to the data synch object */
|
||||
heventData = OpenEvent(EVENT_MODIFY_STATE, FALSE, "DBWIN_DATA_READY");
|
||||
if ( !heventData )
|
||||
{
|
||||
// MessageBox(NULL, "DBWIN_DATA_READY nonexistent", NULL, MB_OK);
|
||||
CloseHandle(heventDBWIN);
|
||||
return;
|
||||
}
|
||||
|
||||
hSharedFile = CreateFileMapping((HANDLE)-1, NULL, PAGE_READWRITE, 0, 4096, "DBWIN_BUFFER");
|
||||
if (!hSharedFile)
|
||||
{
|
||||
//MessageBox(NULL, "DebugTrace: Unable to create file mapping object DBWIN_BUFFER", "Error", MB_OK);
|
||||
CloseHandle(heventDBWIN);
|
||||
CloseHandle(heventData);
|
||||
return;
|
||||
}
|
||||
|
||||
lpszSharedMem = (LPSTR)MapViewOfFile(hSharedFile, FILE_MAP_WRITE, 0, 0, 512);
|
||||
if (!lpszSharedMem)
|
||||
{
|
||||
//MessageBox(NULL, "DebugTrace: Unable to map shared memory", "Error", MB_OK);
|
||||
CloseHandle(heventDBWIN);
|
||||
CloseHandle(heventData);
|
||||
return;
|
||||
}
|
||||
|
||||
/* wait for buffer event */
|
||||
WaitForSingleObject(heventDBWIN, INFINITE);
|
||||
|
||||
/* write it to the shared memory */
|
||||
*((LPDWORD)lpszSharedMem) = 0;
|
||||
wsprintf(lpszSharedMem + sizeof(DWORD), "%s", str);
|
||||
|
||||
/* signal data ready event */
|
||||
SetEvent(heventData);
|
||||
|
||||
/* clean up handles */
|
||||
CloseHandle(hSharedFile);
|
||||
CloseHandle(heventData);
|
||||
CloseHandle(heventDBWIN);
|
||||
|
||||
return;
|
||||
}
|
||||
#endif // WWDEBUG
|
196
GeneralsMD/Code/Libraries/Source/WWVegas/WWDebug/wwdebug.dsp
Normal file
196
GeneralsMD/Code/Libraries/Source/WWVegas/WWDebug/wwdebug.dsp
Normal file
|
@ -0,0 +1,196 @@
|
|||
# Microsoft Developer Studio Project File - Name="wwdebug" - Package Owner=<4>
|
||||
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
# TARGTYPE "Win32 (x86) Static Library" 0x0104
|
||||
|
||||
CFG=wwdebug - Win32 DebugW3D
|
||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||
!MESSAGE use the Export Makefile command and run
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "wwdebug.mak".
|
||||
!MESSAGE
|
||||
!MESSAGE You can specify a configuration when running NMAKE
|
||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "wwdebug.mak" CFG="wwdebug - Win32 DebugW3D"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "wwdebug - Win32 Release" (based on "Win32 (x86) Static Library")
|
||||
!MESSAGE "wwdebug - Win32 Debug" (based on "Win32 (x86) Static Library")
|
||||
!MESSAGE "wwdebug - Win32 Profile" (based on "Win32 (x86) Static Library")
|
||||
!MESSAGE "wwdebug - Win32 Internal" (based on "Win32 (x86) Static Library")
|
||||
!MESSAGE "wwdebug - Win32 DebugW3D" (based on "Win32 (x86) Static Library")
|
||||
!MESSAGE
|
||||
|
||||
# Begin Project
|
||||
# PROP AllowPerConfigDependencies 0
|
||||
# PROP Scc_ProjName ""$/Commando/Code/wwdebug", OPNAAAAA"
|
||||
# PROP Scc_LocalPath "."
|
||||
CPP=cl.exe
|
||||
RSC=rc.exe
|
||||
|
||||
!IF "$(CFG)" == "wwdebug - Win32 Release"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "Release"
|
||||
# PROP BASE Intermediate_Dir "Release"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "Release"
|
||||
# PROP Intermediate_Dir "Release"
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
|
||||
# ADD CPP /nologo /G6 /MD /W3 /WX /Gi /GX /O2 /Ob2 /I "..\wwlib" /D WINVER=0x400 /D "_WINDOWS" /D "WIN32_LEAN_AND_MEAN" /D "NDEBUG" /D "WIN32" /D "IG_DEBUG_STACKTRACE" /YX /FD /c
|
||||
# ADD BASE RSC /l 0x409
|
||||
# ADD RSC /l 0x409
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LIB32=link.exe -lib
|
||||
# ADD BASE LIB32 /nologo
|
||||
# ADD LIB32 /nologo /out:"..\..\..\Lib\WWDebug.lib"
|
||||
|
||||
!ELSEIF "$(CFG)" == "wwdebug - Win32 Debug"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "Debug"
|
||||
# PROP BASE Intermediate_Dir "Debug"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "Debug"
|
||||
# PROP Intermediate_Dir "Debug"
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /GX /Z7 /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
|
||||
# ADD CPP /nologo /G6 /MDd /W3 /WX /Gi /Zi /Od /Ob2 /I "..\wwlib" /D "_DEBUG" /D WINVER=0x400 /D "_WINDOWS" /D "WIN32_LEAN_AND_MEAN" /D "WIN32" /D "WWDEBUG" /YX /FD /c
|
||||
# ADD BASE RSC /l 0x409
|
||||
# ADD RSC /l 0x409
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LIB32=link.exe -lib
|
||||
# ADD BASE LIB32 /nologo
|
||||
# ADD LIB32 /nologo /out:"..\..\..\Lib\WWDebugDebug.lib"
|
||||
|
||||
!ELSEIF "$(CFG)" == "wwdebug - Win32 Profile"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "wwdebug_"
|
||||
# PROP BASE Intermediate_Dir "wwdebug_"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "Profile"
|
||||
# PROP Intermediate_Dir "Profile"
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
|
||||
# ADD CPP /nologo /MD /W3 /WX /GX /Zi /O2 /Op /Ob2 /I "..\wwlib" /I "$(ProjDir)/DXSDK\INCLUDE" /I "../STLPORT" /I "../DXSDK/INCLUDE" /D "NDEBUG" /D "WWDEBUG" /D WINVER=0x400 /D "_WINDOWS" /D "WIN32_LEAN_AND_MEAN" /D "WIN32" /D "_PROFILE" /YX /FD /Gh /c
|
||||
# ADD BASE RSC /l 0x409
|
||||
# ADD RSC /l 0x409
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LIB32=link.exe -lib
|
||||
# ADD BASE LIB32 /nologo /out:"..\Libs\release\wwdebug.lib"
|
||||
# ADD LIB32 /nologo /out:"..\..\..\Lib\WWDebugProfile.lib"
|
||||
|
||||
!ELSEIF "$(CFG)" == "wwdebug - Win32 Internal"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "Internal"
|
||||
# PROP BASE Intermediate_Dir "Internal"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "Internal"
|
||||
# PROP Intermediate_Dir "Internal"
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /MD /W3 /Gi /GX /O2 /Ob2 /I "..\wwlib" /D "NDEBUG" /D WINVER=0x400 /D "_WINDOWS" /D "WIN32_LEAN_AND_MEAN" /D "WIN32" /YX /FD /c
|
||||
# SUBTRACT BASE CPP /Fr
|
||||
# ADD CPP /nologo /G6 /MD /W3 /WX /Gi /GX /Zi /O2 /I "..\wwlib" /D "NDEBUG" /D WINVER=0x400 /D "_WINDOWS" /D "WIN32_LEAN_AND_MEAN" /D "WIN32" /D "_INTERNAL" /D "WWDEBUG" /Fr /YX /FD /c
|
||||
# ADD BASE RSC /l 0x409
|
||||
# ADD RSC /l 0x409
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LIB32=link.exe -lib
|
||||
# ADD BASE LIB32 /nologo /out:"..\..\..\Lib\WWDebug.lib"
|
||||
# ADD LIB32 /nologo /out:"..\..\..\Lib\WWDebugInternal.lib"
|
||||
|
||||
!ELSEIF "$(CFG)" == "wwdebug - Win32 DebugW3D"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "Max4Release"
|
||||
# PROP BASE Intermediate_Dir "Max4Release"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "DebugW3D"
|
||||
# PROP Intermediate_Dir "DebugW3D"
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /MDd /W3 /WX /Gm /Gi /GR /GX /ZI /Od /I "..\wwlib" /D "_DEBUG" /D "WWDEBUG" /D WINVER=0x400 /D "_WINDOWS" /D "WIN32_LEAN_AND_MEAN" /D "WIN32" /Fr /YX /FD /c
|
||||
# ADD CPP /nologo /G6 /MDd /W3 /WX /Gi /GX /Zi /O2 /I "..\wwlib" /D "_DEBUG" /D WINVER=0x400 /D "_WINDOWS" /D "WIN32_LEAN_AND_MEAN" /D "WIN32" /D "WWDEBUG" /YX /FD /c
|
||||
# ADD BASE RSC /l 0x409
|
||||
# ADD RSC /l 0x409
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LIB32=link.exe -lib
|
||||
# ADD BASE LIB32 /nologo /out:"..\Libs\Max4Release\wwdebug.lib"
|
||||
# ADD LIB32 /nologo /out:"..\..\..\Lib\WWDebugDebugW3D.lib"
|
||||
|
||||
!ENDIF
|
||||
|
||||
# Begin Target
|
||||
|
||||
# Name "wwdebug - Win32 Release"
|
||||
# Name "wwdebug - Win32 Debug"
|
||||
# Name "wwdebug - Win32 Profile"
|
||||
# Name "wwdebug - Win32 Internal"
|
||||
# Name "wwdebug - Win32 DebugW3D"
|
||||
# Begin Group "Source"
|
||||
|
||||
# PROP Default_Filter "cpp;c"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\wwdebug.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\wwmemlog.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\wwprofile.cpp
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Headers"
|
||||
|
||||
# PROP Default_Filter "h"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\wwdebug.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\wwhack.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\wwmemlog.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\wwprofile.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# End Target
|
||||
# End Project
|
176
GeneralsMD/Code/Libraries/Source/WWVegas/WWDebug/wwdebug.h
Normal file
176
GeneralsMD/Code/Libraries/Source/WWVegas/WWDebug/wwdebug.h
Normal file
|
@ -0,0 +1,176 @@
|
|||
/*
|
||||
** Command & Conquer Generals Zero Hour(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/***********************************************************************************************
|
||||
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
|
||||
***********************************************************************************************
|
||||
* *
|
||||
* Project Name : WWDebug *
|
||||
* *
|
||||
* $Archive:: /Commando/Code/wwdebug/wwdebug.h $*
|
||||
* *
|
||||
* $Author:: Jani_p $*
|
||||
* *
|
||||
* $Modtime:: 5/04/01 7:43p $*
|
||||
* *
|
||||
* $Revision:: 18 $*
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* Functions: *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
#if _MSC_VER >= 1000
|
||||
#pragma once
|
||||
#endif // _MSC_VER >= 1000
|
||||
|
||||
#ifndef WWDEBUG_H
|
||||
#define WWDEBUG_H
|
||||
|
||||
// The macro MESSAGE allows user to put:
|
||||
// #pragma MESSAGE("Hello world")
|
||||
// anywhere in a source file. The message:
|
||||
// sourcefname.cpp (123) : Hello world
|
||||
// would be printed if put in sourcefname.cpp on line 123 in compile window like an error.
|
||||
// You can then use next/prev error hot keys to see where comment is. It is not an error and
|
||||
// will be printed everytime it is compiled. Very useful to put comments in code that cannot
|
||||
// be forgoten.
|
||||
#define STRING_IT(a) #a
|
||||
#define TOKEN_IT(a) STRING_IT(,##a)
|
||||
#define MESSAGE(a) message (__FILE__ "(" TOKEN_IT(__LINE__) ") : " a)
|
||||
|
||||
void Convert_System_Error_To_String(int error_id, char* buffer, int buf_len);
|
||||
int Get_Last_System_Error();
|
||||
|
||||
/*
|
||||
** If 'WWDEBUG' is turned off, all WWDEBUG_xxx macros will
|
||||
** be discarded.
|
||||
*/
|
||||
typedef enum {
|
||||
WWDEBUG_TYPE_INFORMATION,
|
||||
WWDEBUG_TYPE_WARNING,
|
||||
WWDEBUG_TYPE_ERROR,
|
||||
WWDEBUG_TYPE_USER
|
||||
} DebugType;
|
||||
|
||||
typedef void (*PrintFunc)(DebugType type, const char * message);
|
||||
typedef void (*AssertPrintFunc)(const char * message);
|
||||
typedef bool (*TriggerFunc)(int trigger_num);
|
||||
typedef void (*ProfileFunc)(const char * title);
|
||||
|
||||
PrintFunc WWDebug_Install_Message_Handler(PrintFunc func);
|
||||
AssertPrintFunc WWDebug_Install_Assert_Handler(AssertPrintFunc func);
|
||||
TriggerFunc WWDebug_Install_Trigger_Handler(TriggerFunc func);
|
||||
ProfileFunc WWDebug_Install_Profile_Start_Handler(ProfileFunc func);
|
||||
ProfileFunc WWDebug_Install_Profile_Stop_Handler(ProfileFunc func);
|
||||
|
||||
|
||||
/*
|
||||
** Users should not call the following three functions directly! Use the macros below instead...
|
||||
*/
|
||||
void WWDebug_Printf(const char * format,...);
|
||||
void WWDebug_Printf_Warning(const char * format,...);
|
||||
void WWDebug_Printf_Error(const char * format,...);
|
||||
#ifdef WWDEBUG
|
||||
void WWDebug_Assert_Fail(const char * expr,const char * file, int line);
|
||||
void WWDebug_Assert_Fail_Print(const char * expr,const char * file, int line,const char * string);
|
||||
bool WWDebug_Check_Trigger(int trigger_num);
|
||||
void WWDebug_Profile_Start( const char * title);
|
||||
void WWDebug_Profile_Stop( const char * title);
|
||||
|
||||
/*
|
||||
** A message handler to display to DBWIN32
|
||||
*/
|
||||
void WWDebug_DBWin32_Message_Handler( const char * message);
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
** Use the following #define so that all of the debugging messages
|
||||
** and strings go away when the release version is built.
|
||||
** WWDEBUG_SAY(("dir = %f\n",dir));
|
||||
*/
|
||||
|
||||
#include "..\..\..\..\gameengine\include\common\debug.h"
|
||||
|
||||
#ifdef DEBUG_LOGGING
|
||||
#define WWDEBUG_SAY(x) DEBUG_LOG(x)
|
||||
#define WWDEBUG_WARNING(x) DEBUG_LOG(x)
|
||||
#else
|
||||
#define WWDEBUG_SAY(x)
|
||||
#define WWDEBUG_WARNING(x)
|
||||
#endif
|
||||
|
||||
// WW3d is compiled at warning level 4, causes DEBUG_ASSERTCRASH to generate
|
||||
// the 4127 warning (constant conditional expression)
|
||||
#pragma warning(disable:4127)
|
||||
#define WWRELEASE_SAY(x) WWDebug_Printf x
|
||||
#define WWRELEASE_WARNING(x) WWDebug_Printf_Warning x
|
||||
#define WWRELEASE_ERROR(x) WWDebug_Printf_Error x
|
||||
/*
|
||||
** The WWASSERT and WWASSERT_PRINT macros will send messages to your
|
||||
** assert handler.
|
||||
*/
|
||||
#ifdef DEBUG_CRASHING
|
||||
#define WWASSERT(expr) DEBUG_ASSERTCRASH(expr, ("%s, %s, %d", #expr,__FILE__,__LINE__))
|
||||
#define WWASSERT_PRINT( expr, string ) DEBUG_ASSERTCRASH(expr, ("%s, %s, %d - %s", #expr,__FILE__,__LINE__,string))
|
||||
#define W3D_DIE DEBUG_CRASH(("DIE!, %s, %d", __FILE__,__LINE__))
|
||||
#define WWDEBUG_ERROR(x) DEBUG_CRASH(x)
|
||||
#else
|
||||
#define WWASSERT( expr )
|
||||
#define WWASSERT_PRINT( expr, string )
|
||||
#define W3D_DIE
|
||||
#define WWDEBUG_ERROR(x)
|
||||
#endif
|
||||
|
||||
/*
|
||||
** The WWDEBUG_BREAK macro will cause the application to break into
|
||||
** the debugger...
|
||||
*/
|
||||
#ifdef WWDEBUG
|
||||
#define WWDEBUG_BREAK _asm int 0x03
|
||||
#else
|
||||
#define WWDEBUG_BREAK _asm int 0x03
|
||||
#endif
|
||||
|
||||
/*
|
||||
** The WWDEBUG_TRIGGER macro can be used to ask the application if
|
||||
** a debug trigger is set. We define a couple of generic triggers
|
||||
** for casual use.
|
||||
*/
|
||||
#define WWDEBUG_TRIGGER_GENERIC0 0
|
||||
#define WWDEBUG_TRIGGER_GENERIC1 1
|
||||
|
||||
#ifdef WWDEBUG
|
||||
#define WWDEBUG_TRIGGER(x) WWDebug_Check_Trigger(x)
|
||||
#else
|
||||
#define WWDEBUG_TRIGGER(x) (0)
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
** The WWDEBUG_PROFILE macros can be used to time blocks of code
|
||||
*/
|
||||
#ifdef WWDEBUG
|
||||
#define WWDEBUG_PROFILE_START(x) WWDebug_Profile_Start(x)
|
||||
#define WWDEBUG_PROFILE_STOP(x) WWDebug_Profile_Stop(x)
|
||||
#else
|
||||
#define WWDEBUG_PROFILE_START(x)
|
||||
#define WWDEBUG_PROFILE_STOP(x)
|
||||
#endif
|
||||
|
||||
#endif
|
50
GeneralsMD/Code/Libraries/Source/WWVegas/WWDebug/wwhack.h
Normal file
50
GeneralsMD/Code/Libraries/Source/WWVegas/WWDebug/wwhack.h
Normal file
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
** Command & Conquer Generals Zero Hour(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/***********************************************************************************************
|
||||
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
|
||||
***********************************************************************************************
|
||||
* *
|
||||
* Project Name : WWDebug *
|
||||
* *
|
||||
* $Archive:: /Commando/Code/wwdebug/wwhack.h $*
|
||||
* *
|
||||
* $Author:: Byon_g $*
|
||||
* *
|
||||
* $Modtime:: 10/06/99 1:09p $*
|
||||
* *
|
||||
* $Revision:: 2 $*
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* Functions: *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
#if _MSC_VER >= 1000
|
||||
#pragma once
|
||||
#endif // _MSC_VER >= 1000
|
||||
|
||||
#ifndef WWHACK_H
|
||||
#define WWHACK_H
|
||||
|
||||
/*
|
||||
** FORCE_LINK is a hack to force a module in a lib to be linked into the EXE.
|
||||
*/
|
||||
#define FORCE_LINK( module ) void _Force_Link_ ## module( void ); _Force_Link_ ## module()
|
||||
#define DECLARE_FORCE_LINK( module ) void _Force_Link_ ## module( void ) {}
|
||||
|
||||
#endif
|
763
GeneralsMD/Code/Libraries/Source/WWVegas/WWDebug/wwmemlog.cpp
Normal file
763
GeneralsMD/Code/Libraries/Source/WWVegas/WWDebug/wwmemlog.cpp
Normal file
|
@ -0,0 +1,763 @@
|
|||
/*
|
||||
** Command & Conquer Generals Zero Hour(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/***********************************************************************************************
|
||||
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
|
||||
***********************************************************************************************
|
||||
* *
|
||||
* Project Name : WWDebug *
|
||||
* *
|
||||
* $Archive:: /Commando/Code/wwdebug/wwmemlog.cpp $*
|
||||
* *
|
||||
* Original Author:: Greg Hjelstrom *
|
||||
* *
|
||||
* $Author:: Jani_p $*
|
||||
* *
|
||||
* $Modtime:: 11/21/01 2:03p $*
|
||||
* *
|
||||
* $Revision:: 27 $*
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* Functions: *
|
||||
* WWMemoryLogClass::Allocate_Memory -- allocates memory *
|
||||
* WWMemoryLogClass::Release_Memory -- frees memory *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
#include "always.h"
|
||||
#include "wwmemlog.h"
|
||||
#include "wwdebug.h"
|
||||
#include "vector.h"
|
||||
#include "fastallocator.h"
|
||||
#include <windows.h>
|
||||
|
||||
#define USE_FAST_ALLOCATOR
|
||||
|
||||
#ifdef STEVES_NEW_CATCHER
|
||||
#define DISABLE_MEMLOG 1
|
||||
#else //STEVES_NEW_CATCHER
|
||||
#ifdef PARAM_EDITING_ON
|
||||
#define DISABLE_MEMLOG 1
|
||||
#else //PARAM_EDITING_ON
|
||||
#define DISABLE_MEMLOG 1
|
||||
#endif //PARAM_EDITING_ON
|
||||
#endif //STEVES_NEW_CATCHER*/
|
||||
|
||||
#ifdef USE_FAST_ALLOCATOR
|
||||
#define ALLOC_MEMORY(n) FastAllocatorGeneral::Get_Allocator()->Alloc(n)
|
||||
#define FREE_MEMORY(p) FastAllocatorGeneral::Get_Allocator()->Free(p)
|
||||
#else
|
||||
#define ALLOC_MEMORY(n) ::malloc(n)
|
||||
#define FREE_MEMORY(p) ::free(p)
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
** Enable one of the following #defines to specify which thread-sychronization
|
||||
** method to use.
|
||||
*/
|
||||
#ifndef _UNIX
|
||||
#define MEMLOG_USE_MUTEX 0
|
||||
#define MEMLOG_USE_CRITICALSECTION 1
|
||||
#define MEMLOG_USE_FASTCRITICALSECTION 0
|
||||
#else
|
||||
#undef DISABLE_MEMLOG
|
||||
#define DISABLE_MEMLOG 1
|
||||
#define MEMLOG_USE_MUTEX 0
|
||||
#define MEMLOG_USE_CRITICALSECTION 0
|
||||
#define MEMLOG_USE_FASTCRITICALSECTION 0
|
||||
#endif
|
||||
|
||||
#if (DISABLE_MEMLOG == 0)
|
||||
bool WWMemoryLogClass::IsMemoryLogEnabled=true;
|
||||
#else
|
||||
bool WWMemoryLogClass::IsMemoryLogEnabled=false;
|
||||
#endif
|
||||
|
||||
static unsigned AllocateCount;
|
||||
static unsigned FreeCount;
|
||||
|
||||
/*
|
||||
** Name for each memory category. I'm padding the array with some "undefined" strings in case
|
||||
** someone forgets to set the name when adding a new category.
|
||||
*/
|
||||
static char * _MemoryCategoryNames[] =
|
||||
{
|
||||
"UNKNOWN",
|
||||
"Geometry",
|
||||
"Animation",
|
||||
"Texture",
|
||||
"Pathfind",
|
||||
"Vis",
|
||||
"Sound",
|
||||
"CullingData",
|
||||
"Strings",
|
||||
"GameData",
|
||||
"PhysicsData",
|
||||
"W3dData",
|
||||
"StaticAllocations",
|
||||
"GameInit",
|
||||
"Renderer",
|
||||
"Network",
|
||||
"BINK",
|
||||
"<undefined>",
|
||||
"<undefined>",
|
||||
"<undefined>",
|
||||
"<undefined>",
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
** MemoryCounterClass
|
||||
** This object will store statistics for each memory category. It can provide things like
|
||||
** the current amount of allocated memory and the peak amount of allocated memory.
|
||||
*/
|
||||
class MemoryCounterClass
|
||||
{
|
||||
public:
|
||||
MemoryCounterClass(void) : CurrentAllocation(0), PeakAllocation(0) { }
|
||||
|
||||
void Memory_Allocated(int size) { CurrentAllocation+=size; PeakAllocation = max(PeakAllocation,CurrentAllocation); }
|
||||
void Memory_Released(int size) { CurrentAllocation-=size; }
|
||||
|
||||
int Get_Current_Allocated_Memory(void) { return CurrentAllocation; }
|
||||
int Get_Peak_Allocated_Memory(void) { return PeakAllocation; }
|
||||
|
||||
protected:
|
||||
int CurrentAllocation;
|
||||
int PeakAllocation;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
** ActiveCategoryStackClass
|
||||
** This object is used to keep track of the "active memory category". Whenever memory is allocated
|
||||
** it will be charged to the current active memory category. To be thread-safe, there will be
|
||||
** one ActiveCategoryStack per thread that is encountered in the program.
|
||||
*/
|
||||
const int MAX_CATEGORY_STACK_DEPTH = 1024;
|
||||
class ActiveCategoryStackClass : public VectorClass<int>
|
||||
{
|
||||
public:
|
||||
ActiveCategoryStackClass(void) :
|
||||
VectorClass<int>(MAX_CATEGORY_STACK_DEPTH),
|
||||
ThreadID(-1),
|
||||
Count(0)
|
||||
{ }
|
||||
|
||||
// If object was created but not Init'd, ThreadID will be -1 and Count == 0
|
||||
// If object was created and Init'd, ThreadID will not be -1. We expect Count to return to 1 after all Pop's
|
||||
~ActiveCategoryStackClass(void) { WWASSERT((ThreadID == -1 && Count == 0) || (ThreadID != -1 && Count == 1)); }
|
||||
|
||||
ActiveCategoryStackClass & operator = (const ActiveCategoryStackClass & that);
|
||||
|
||||
bool operator == (const ActiveCategoryStackClass &) { return false; }
|
||||
bool operator != (const ActiveCategoryStackClass &) { return true; }
|
||||
|
||||
void Init(int thread_id) { ThreadID = thread_id; Count = 0; Push(MEM_UNKNOWN); }
|
||||
void Set_Thread_ID(int id) { WWASSERT(ThreadID != -1); ThreadID = id; }
|
||||
int Get_Thread_ID(void) { return ThreadID; }
|
||||
|
||||
void Push(int active_category) { WWASSERT(ThreadID != -1); (*this)[Count] = active_category; Count++; }
|
||||
void Pop(void) { WWASSERT(ThreadID != -1) ; Count--; }
|
||||
int Current(void) { WWASSERT(ThreadID != -1); return (*this)[Count-1]; }
|
||||
|
||||
protected:
|
||||
|
||||
int ThreadID;
|
||||
int Count;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
** ActiveCategoryClass
|
||||
** This is a dynamic vector of ActiveCategoryStackClasses which adds a new stack each time
|
||||
** a new thread is encountered. It also is able to return to you the active category for
|
||||
** the currently active thread automatically.
|
||||
*/
|
||||
const int MAX_CATEGORY_STACKS = 256; // maximum number of threads we expect to encounter...
|
||||
|
||||
class ActiveCategoryClass : public VectorClass<ActiveCategoryStackClass>
|
||||
{
|
||||
public:
|
||||
|
||||
ActiveCategoryClass(void) : VectorClass<ActiveCategoryStackClass>(MAX_CATEGORY_STACKS), Count(0) { Get_Active_Stack().Push(MEM_STATICALLOCATION); }
|
||||
|
||||
void Push(int active_category) { Get_Active_Stack().Push(active_category); }
|
||||
void Pop(void) { Get_Active_Stack().Pop(); }
|
||||
int Current(void) { return Get_Active_Stack().Current(); }
|
||||
|
||||
protected:
|
||||
|
||||
ActiveCategoryStackClass & Get_Active_Stack(void);
|
||||
|
||||
int Count;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
** MemLogClass
|
||||
** This class ties all of the logging datastructures together into a single object
|
||||
** which can be created on demand when the first 'new' call is encountered.
|
||||
*/
|
||||
class MemLogClass
|
||||
{
|
||||
public:
|
||||
|
||||
int Get_Current_Allocated_Memory(int category);
|
||||
int Get_Peak_Allocated_Memory(int category);
|
||||
|
||||
/*
|
||||
** Interface for recording allocations and de-allocations
|
||||
*/
|
||||
int Register_Memory_Allocated(int size);
|
||||
void Register_Memory_Released(int category,int size);
|
||||
|
||||
void Push_Active_Category(int category);
|
||||
void Pop_Active_Category(void);
|
||||
|
||||
void Init();
|
||||
|
||||
private:
|
||||
|
||||
MemoryCounterClass _MemoryCounters[MEM_COUNT];
|
||||
ActiveCategoryClass _ActiveCategoryTracker;
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
** Static Variables
|
||||
** _TheMemLog - object which encapsulates all logging. will be allocated on first use
|
||||
** _MemLogMutex - handle to the mutex used to arbtirate access to the logging data structures
|
||||
** _MemLogLockCounter - count of the active mutex locks.
|
||||
*/
|
||||
static MemLogClass * _TheMemLog = NULL;
|
||||
static bool _MemLogAllocated = false;
|
||||
|
||||
#if MEMLOG_USE_MUTEX
|
||||
static void * _MemLogMutex = NULL;
|
||||
static int _MemLogLockCounter = 0;
|
||||
#endif
|
||||
|
||||
#if MEMLOG_USE_CRITICALSECTION
|
||||
static bool _MemLogCriticalSectionAllocated = false;
|
||||
static char _MemLogCriticalSectionHandle[sizeof(CRITICAL_SECTION)];
|
||||
#endif
|
||||
|
||||
#if MEMLOG_USE_FASTCRITICALSECTION
|
||||
volatile unsigned _MemLogSemaphore = 0;
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Use this code to get access to the mutex...
|
||||
*/
|
||||
WWINLINE void * Get_Mem_Log_Mutex(void)
|
||||
{
|
||||
#if MEMLOG_USE_MUTEX
|
||||
|
||||
if (_MemLogMutex == NULL) {
|
||||
_MemLogMutex=CreateMutex(NULL,false,NULL);
|
||||
WWASSERT(_MemLogMutex);
|
||||
}
|
||||
return _MemLogMutex;
|
||||
|
||||
#endif
|
||||
|
||||
#if MEMLOG_USE_CRITICALSECTION
|
||||
|
||||
if (_MemLogCriticalSectionAllocated == false) {
|
||||
InitializeCriticalSection((CRITICAL_SECTION*)_MemLogCriticalSectionHandle);
|
||||
_MemLogCriticalSectionAllocated = true;
|
||||
}
|
||||
return _MemLogCriticalSectionHandle;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
WWINLINE void Lock_Mem_Log_Mutex(void)
|
||||
{
|
||||
#if MEMLOG_USE_MUTEX
|
||||
|
||||
void * mutex = Get_Mem_Log_Mutex();
|
||||
#ifdef DEBUG_CRASHING
|
||||
int res =
|
||||
#endif
|
||||
WaitForSingleObject(mutex,INFINITE);
|
||||
WWASSERT(res==WAIT_OBJECT_0);
|
||||
_MemLogLockCounter++;
|
||||
#endif
|
||||
|
||||
#if MEMLOG_USE_CRITICALSECTION
|
||||
|
||||
Get_Mem_Log_Mutex();
|
||||
EnterCriticalSection((CRITICAL_SECTION*)_MemLogCriticalSectionHandle);
|
||||
|
||||
#endif
|
||||
|
||||
#if MEMLOG_USE_FASTCRITICALSECTION
|
||||
|
||||
volatile unsigned& nFlag=_MemLogSemaphore;
|
||||
|
||||
#define ts_lock _emit 0xF0
|
||||
assert(((unsigned)&nFlag % 4) == 0);
|
||||
|
||||
__asm mov ebx, [nFlag]
|
||||
__asm ts_lock
|
||||
__asm bts dword ptr [ebx], 0
|
||||
__asm jc The_Bit_Was_Previously_Set_So_Try_Again
|
||||
return;
|
||||
|
||||
The_Bit_Was_Previously_Set_So_Try_Again:
|
||||
ThreadClass::Switch_Thread();
|
||||
__asm mov ebx, [nFlag]
|
||||
__asm ts_lock
|
||||
__asm bts dword ptr [ebx], 0
|
||||
__asm jc The_Bit_Was_Previously_Set_So_Try_Again
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
WWINLINE void Unlock_Mem_Log_Mutex(void)
|
||||
{
|
||||
#if MEMLOG_USE_MUTEX
|
||||
|
||||
void * mutex = Get_Mem_Log_Mutex();
|
||||
_MemLogLockCounter--;
|
||||
#ifdef DEBUG_CRASHING
|
||||
int res=
|
||||
#endif
|
||||
ReleaseMutex(mutex);
|
||||
WWASSERT(res);
|
||||
|
||||
#endif
|
||||
#if MEMLOG_USE_CRITICALSECTION
|
||||
|
||||
Get_Mem_Log_Mutex();
|
||||
LeaveCriticalSection((CRITICAL_SECTION*)_MemLogCriticalSectionHandle);
|
||||
|
||||
#endif
|
||||
|
||||
#if MEMLOG_USE_FASTCRITICALSECTION
|
||||
_MemLogSemaphore = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
class MemLogMutexLockClass
|
||||
{
|
||||
public:
|
||||
MemLogMutexLockClass(void) { Lock_Mem_Log_Mutex(); }
|
||||
~MemLogMutexLockClass(void) { Unlock_Mem_Log_Mutex(); }
|
||||
};
|
||||
|
||||
|
||||
|
||||
/***************************************************************************************************
|
||||
**
|
||||
** ActiveCategoryStackClass Implementation
|
||||
**
|
||||
***************************************************************************************************/
|
||||
ActiveCategoryStackClass &
|
||||
ActiveCategoryStackClass::operator = (const ActiveCategoryStackClass & that)
|
||||
{
|
||||
if (this != &that) {
|
||||
VectorClass<int>::operator == (that);
|
||||
ThreadID = that.ThreadID;
|
||||
Count = that.Count;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************************************
|
||||
**
|
||||
** ActiveCategoryClass Implementation
|
||||
**
|
||||
***************************************************************************************************/
|
||||
ActiveCategoryStackClass & ActiveCategoryClass::Get_Active_Stack(void)
|
||||
{
|
||||
int current_thread = ::GetCurrentThreadId();
|
||||
|
||||
/*
|
||||
** If we already have an allocated category stack for the current thread,
|
||||
** just return its active category.
|
||||
*/
|
||||
for (int i=0; i<Count; i++) {
|
||||
ActiveCategoryStackClass & cat_stack = (*this)[i];
|
||||
if (cat_stack.Get_Thread_ID() == current_thread) {
|
||||
return cat_stack;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** If we fall through to here, we need to allocate a new category stack
|
||||
** for this thread.
|
||||
*/
|
||||
(*this)[Count].Init(current_thread);
|
||||
Count++;
|
||||
return (*this)[Count-1];
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************************************
|
||||
**
|
||||
** MemLogClass Implementation
|
||||
**
|
||||
***************************************************************************************************/
|
||||
int MemLogClass::Get_Current_Allocated_Memory(int category)
|
||||
{
|
||||
MemLogMutexLockClass lock;
|
||||
return _MemoryCounters[category].Get_Current_Allocated_Memory();
|
||||
}
|
||||
|
||||
int MemLogClass::Get_Peak_Allocated_Memory(int category)
|
||||
{
|
||||
MemLogMutexLockClass lock;
|
||||
return _MemoryCounters[category].Get_Peak_Allocated_Memory();
|
||||
}
|
||||
|
||||
void MemLogClass::Init()
|
||||
{
|
||||
{
|
||||
MemLogMutexLockClass lock;
|
||||
WWASSERT(_ActiveCategoryTracker.Current()==MEM_STATICALLOCATION);
|
||||
}
|
||||
Pop_Active_Category(); // Remove staticallocation state forever
|
||||
}
|
||||
|
||||
int MemLogClass::Register_Memory_Allocated(int size)
|
||||
{
|
||||
MemLogMutexLockClass lock;
|
||||
|
||||
int active_category = _ActiveCategoryTracker.Current();
|
||||
WWASSERT((active_category >= 0) && (active_category < MEM_COUNT));
|
||||
_MemoryCounters[active_category].Memory_Allocated(size);
|
||||
|
||||
return active_category;
|
||||
}
|
||||
|
||||
void MemLogClass::Register_Memory_Released(int category,int size)
|
||||
{
|
||||
MemLogMutexLockClass lock;
|
||||
_MemoryCounters[category].Memory_Released(size);
|
||||
}
|
||||
|
||||
void MemLogClass::Push_Active_Category(int category)
|
||||
{
|
||||
MemLogMutexLockClass lock;
|
||||
WWASSERT((category >= 0) && (category < MEM_COUNT));
|
||||
_ActiveCategoryTracker.Push(category);
|
||||
}
|
||||
|
||||
void MemLogClass::Pop_Active_Category(void)
|
||||
{
|
||||
MemLogMutexLockClass lock;
|
||||
_ActiveCategoryTracker.Pop();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/***************************************************************************************************
|
||||
**
|
||||
** WWMemoryLogClass Implementation
|
||||
**
|
||||
***************************************************************************************************/
|
||||
|
||||
int WWMemoryLogClass::Get_Category_Count(void)
|
||||
{
|
||||
return MEM_COUNT;
|
||||
}
|
||||
|
||||
const char * WWMemoryLogClass::Get_Category_Name(int category)
|
||||
{
|
||||
return _MemoryCategoryNames[category];
|
||||
}
|
||||
|
||||
int WWMemoryLogClass::Get_Current_Allocated_Memory(int category)
|
||||
{
|
||||
return Get_Log()->Get_Current_Allocated_Memory(category);
|
||||
}
|
||||
|
||||
int WWMemoryLogClass::Get_Peak_Allocated_Memory(int category)
|
||||
{
|
||||
return Get_Log()->Get_Peak_Allocated_Memory(category);
|
||||
}
|
||||
|
||||
void WWMemoryLogClass::Push_Active_Category(int category)
|
||||
{
|
||||
#if (DISABLE_MEMLOG == 0)
|
||||
Get_Log()->Push_Active_Category(category);
|
||||
#endif //(DISABLE_MEMLOG == 0)
|
||||
}
|
||||
|
||||
void WWMemoryLogClass::Pop_Active_Category(void)
|
||||
{
|
||||
#if (DISABLE_MEMLOG == 0)
|
||||
Get_Log()->Pop_Active_Category();
|
||||
#endif //(DISABLE_MEMLOG == 0)
|
||||
}
|
||||
|
||||
int WWMemoryLogClass::Register_Memory_Allocated(int size)
|
||||
{
|
||||
return Get_Log()->Register_Memory_Allocated(size);
|
||||
}
|
||||
|
||||
void WWMemoryLogClass::Register_Memory_Released(int category,int size)
|
||||
{
|
||||
Get_Log()->Register_Memory_Released(category,size);
|
||||
}
|
||||
|
||||
|
||||
static void _MemLogCleanup(void)
|
||||
{
|
||||
delete _TheMemLog;
|
||||
}
|
||||
|
||||
|
||||
MemLogClass * WWMemoryLogClass::Get_Log(void)
|
||||
{
|
||||
MemLogMutexLockClass lock;
|
||||
|
||||
if (_TheMemLog == NULL) {
|
||||
//assert(!_MemLogAllocated);
|
||||
_TheMemLog = W3DNEW MemLogClass;
|
||||
|
||||
#ifdef STEVES_NEW_CATCHER
|
||||
/*
|
||||
** This was me trying to be clever and fix the memory leak in the memlog. Unfortunately, the Get_Log member can be called
|
||||
** during the process of exiting the process (IYSWIM) and you get it trying to re-allocate the MemLogClass I just freed.
|
||||
** Solution is just to disable memlog when I'm trying to find memory leaks. ST - 6/18/2001 9:51PM
|
||||
*/
|
||||
if (!_MemLogAllocated) {
|
||||
atexit(&Release_Log);
|
||||
}
|
||||
_MemLogAllocated = true;
|
||||
#endif //STEVES_NEW_CATCHER
|
||||
}
|
||||
return _TheMemLog;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* WWMemoryLogClass::Release_Log -- Free the memory used by WWMemoryLogClass so it doesn't leak*
|
||||
* *
|
||||
* *
|
||||
* *
|
||||
* INPUT: Nothing *
|
||||
* *
|
||||
* OUTPUT: Nothing *
|
||||
* *
|
||||
* WARNINGS: Called as part of _onexit processing *
|
||||
* *
|
||||
* It's messy, but I assume there's a reason it's not statically allocated... *
|
||||
* OK, now I get it *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 6/13/2001 8:55PM ST : Created *
|
||||
*=============================================================================================*/
|
||||
void WWMemoryLogClass::Release_Log(void)
|
||||
{
|
||||
MemLogMutexLockClass lock;
|
||||
if (_TheMemLog) {
|
||||
delete _TheMemLog;
|
||||
_TheMemLog = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************************************
|
||||
**
|
||||
** Allocating and Freeing memory
|
||||
**
|
||||
** PLEASE NOTE: The user is expected to implement global new and delete functions in his own
|
||||
** code which call WWMemoryLogClass::Allocate_Memory and WWMemoryLogClass::Release_Memory.
|
||||
** This was the only solution I could come up given that some APPS have their own new and delete
|
||||
** functions or enable the CRT ones. It was also not an option to move this entire system into
|
||||
** the APP because I wanted all of our LIBs to participate in the memory usage logging...
|
||||
**
|
||||
***************************************************************************************************/
|
||||
|
||||
const int WWMEMLOG_KEY0 = (unsigned('G')<<24) | (unsigned('g')<<16) | (unsigned('0')<<8) | unsigned('l');
|
||||
const int WWMEMLOG_KEY1 = (unsigned('~')<<24) | (unsigned('_')<<16) | (unsigned('d')<<8) | unsigned('3');
|
||||
|
||||
|
||||
/**
|
||||
** MemoryLogStruct
|
||||
** This structure is added to the beginning of each memory allocation to facilitate
|
||||
** tracking which category the memory belongs to when it is freed. The size of
|
||||
** this struct is also 16 bytes so that we wont be seriously affecting the alignment
|
||||
** of allocated memory...
|
||||
*/
|
||||
struct MemoryLogStruct
|
||||
{
|
||||
MemoryLogStruct(int category,int size) :
|
||||
Key0(WWMEMLOG_KEY0),
|
||||
Key1(WWMEMLOG_KEY1),
|
||||
Category(category),
|
||||
Size(size)
|
||||
{}
|
||||
|
||||
bool Is_Valid_Memory_Log(void) { return ((Key0 == WWMEMLOG_KEY0) && (Key1 == WWMEMLOG_KEY1)); }
|
||||
|
||||
int Key0; // if this is not equal to WWMEMLOG_KEY0 then we don't have a valid log
|
||||
int Key1; // should be equal to WWMEMLOG_KEY1
|
||||
int Category; // category this memory belongs to
|
||||
int Size; // size of the allocation
|
||||
};
|
||||
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* WWMemoryLogClass::Allocate_Memory -- allocates memory *
|
||||
* *
|
||||
* This function adds a header to the memory allocated so that when the memory is freed *
|
||||
* the proper memory category size can be decremented. The application using this logging *
|
||||
* system should call this function from inside its overloaded 'new' operator. *
|
||||
* *
|
||||
* INPUT: *
|
||||
* *
|
||||
* OUTPUT: *
|
||||
* *
|
||||
* WARNINGS: *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 5/29/2001 gth : Created. *
|
||||
*=============================================================================================*/
|
||||
void * WWMemoryLogClass::Allocate_Memory(size_t size)
|
||||
{
|
||||
AllocateCount++;
|
||||
#if DISABLE_MEMLOG
|
||||
return ALLOC_MEMORY(size);
|
||||
#else
|
||||
|
||||
__declspec( thread ) static bool reentrancy_test = false;
|
||||
MemLogMutexLockClass lock;
|
||||
|
||||
if (reentrancy_test) {
|
||||
return ALLOC_MEMORY(size);
|
||||
} else {
|
||||
reentrancy_test = true;
|
||||
|
||||
/*
|
||||
** Allocate space for the requested buffer + our logging structure
|
||||
*/
|
||||
void * ptr = ALLOC_MEMORY(size + sizeof(MemoryLogStruct));
|
||||
|
||||
if (ptr != NULL) {
|
||||
/*
|
||||
** Record this allocation
|
||||
*/
|
||||
int active_category = WWMemoryLogClass::Register_Memory_Allocated(size);
|
||||
|
||||
/*
|
||||
** Write our logging structure into the beginning of the buffer. I'm using
|
||||
** placement new syntax to initialize the log structure right in the memory buffer
|
||||
*/
|
||||
new(ptr) MemoryLogStruct(active_category,size);
|
||||
|
||||
/*
|
||||
** Return the allocated memory to the user, skipping past our log structure.
|
||||
*/
|
||||
reentrancy_test = false;
|
||||
return (void*)(((char *)ptr) + sizeof(MemoryLogStruct));
|
||||
|
||||
} else {
|
||||
reentrancy_test = false;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
}
|
||||
#endif //DISABLE_MEMLOG
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* WWMemoryLogClass::Release_Memory -- frees memory *
|
||||
* *
|
||||
* This function checks for a wwmemlog header and decrements the relevant memory category. *
|
||||
* It should be called in the application's custom delete operator. *
|
||||
* *
|
||||
* INPUT: *
|
||||
* *
|
||||
* OUTPUT: *
|
||||
* *
|
||||
* WARNINGS: *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 5/29/2001 gth : Created. *
|
||||
*=============================================================================================*/
|
||||
void WWMemoryLogClass::Release_Memory(void *ptr)
|
||||
{
|
||||
FreeCount++;
|
||||
#if DISABLE_MEMLOG
|
||||
FREE_MEMORY(ptr);
|
||||
#else
|
||||
|
||||
MemLogMutexLockClass lock;
|
||||
if (ptr) {
|
||||
|
||||
/*
|
||||
** Check if this memory is preceeded by a valid MemoryLogStruct
|
||||
*/
|
||||
MemoryLogStruct * memlog = (MemoryLogStruct*)((char*)ptr - sizeof(MemoryLogStruct));
|
||||
if (memlog->Is_Valid_Memory_Log()) {
|
||||
|
||||
/*
|
||||
** Valid MemoryLogStruct found, track the de-allocation and pass on
|
||||
** to the built-in free function.
|
||||
*/
|
||||
WWMemoryLogClass::Register_Memory_Released(memlog->Category,memlog->Size);
|
||||
FREE_MEMORY((void*)memlog);
|
||||
|
||||
} else {
|
||||
|
||||
/*
|
||||
** No valid MemoryLogStruct found, just call free on the memory.
|
||||
*/
|
||||
FREE_MEMORY(ptr);
|
||||
}
|
||||
}
|
||||
|
||||
#endif //DISABLE_MEMLOG
|
||||
}
|
||||
|
||||
// Reset allocate and free counters
|
||||
|
||||
void WWMemoryLogClass::Reset_Counters()
|
||||
{
|
||||
AllocateCount=0;
|
||||
FreeCount=0;
|
||||
}
|
||||
|
||||
// Return allocate count since last reset
|
||||
int WWMemoryLogClass::Get_Allocate_Count()
|
||||
{
|
||||
return AllocateCount;
|
||||
}
|
||||
|
||||
// Return allocate count since last reset
|
||||
int WWMemoryLogClass::Get_Free_Count()
|
||||
{
|
||||
return FreeCount;
|
||||
}
|
||||
|
||||
void WWMemoryLogClass::Init()
|
||||
{
|
||||
Get_Log()->Init();
|
||||
}
|
191
GeneralsMD/Code/Libraries/Source/WWVegas/WWDebug/wwmemlog.h
Normal file
191
GeneralsMD/Code/Libraries/Source/WWVegas/WWDebug/wwmemlog.h
Normal file
|
@ -0,0 +1,191 @@
|
|||
/*
|
||||
** Command & Conquer Generals Zero Hour(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/***********************************************************************************************
|
||||
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
|
||||
***********************************************************************************************
|
||||
* *
|
||||
* Project Name : WWDebug *
|
||||
* *
|
||||
* $Archive:: /Commando/Code/wwdebug/wwmemlog.h $*
|
||||
* *
|
||||
* Original Author:: Greg Hjelstrom *
|
||||
* *
|
||||
* $Author:: Jani_p $*
|
||||
* *
|
||||
* $Modtime:: 11/09/01 6:51p $*
|
||||
* *
|
||||
* $Revision:: 8 $*
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* Functions: *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
|
||||
#if _MSC_VER >= 1000
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#ifndef WWMEMLOG_H
|
||||
#define WWMEMLOG_H
|
||||
|
||||
#define LOG_MEMORY // Comment this out to disable memlog compiling in
|
||||
|
||||
class MemLogClass;
|
||||
|
||||
/**
|
||||
** Memory Log Categories
|
||||
** You can cause memory allocations to be "counted" against any of the following categories.
|
||||
** NOTE: if you add a new category here, be sure to add its name to the array in the .cpp file...
|
||||
*/
|
||||
enum
|
||||
{
|
||||
MEM_UNKNOWN = 0,
|
||||
MEM_GEOMETRY, // memory used by geometry data
|
||||
MEM_ANIMATION, // memory used by animation data
|
||||
MEM_TEXTURE, // memory used by textures
|
||||
MEM_PATHFIND, // memory used by the pathfind system
|
||||
MEM_VIS, // memory used by the vis system
|
||||
MEM_SOUND, // memory used by the sound system
|
||||
MEM_CULLINGDATA, // culling systems
|
||||
MEM_STRINGS, // string data
|
||||
MEM_GAMEDATA, // game engine datastructures
|
||||
MEM_PHYSICSDATA, // physics engine datastructures
|
||||
MEM_W3DDATA, // w3d datastructures (not including ones more applicable to above categories)
|
||||
MEM_STATICALLOCATION,// all the allocations that happen before the memlog Init() function call are from statically allocated objects
|
||||
MEM_GAMEINIT, // game init time allocations
|
||||
MEM_RENDERER, // dx8 renderer
|
||||
MEM_NETWORK,
|
||||
MEM_BINK,
|
||||
|
||||
MEM_COUNT
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
** WWMemoryLogClass
|
||||
** This interface can provide information on how much memory has been allocated to each
|
||||
** memory category. In order to enable this logging, you will need to implement global
|
||||
** new and delete functions which call the Allocate_Memory and Release_Memory functions
|
||||
** in this class. For example:
|
||||
**
|
||||
** void * ::operator new (size_t size)
|
||||
** {
|
||||
** return WWMemoryLogClass::Allocate_Memory(size);
|
||||
** }
|
||||
**
|
||||
** void ::operator delete (void *ptr)
|
||||
** {
|
||||
** WWMemoryLogClass::Release_Memory(ptr);
|
||||
** }
|
||||
*/
|
||||
class WWMemoryLogClass
|
||||
{
|
||||
public:
|
||||
static void Enable_Memory_Log(bool enable) { IsMemoryLogEnabled=enable; }
|
||||
static bool Is_Memory_Log_Enabled() { return IsMemoryLogEnabled; }
|
||||
|
||||
/*
|
||||
** Accessors to the current memory map
|
||||
*/
|
||||
static int Get_Category_Count(void);
|
||||
static const char * Get_Category_Name(int category);
|
||||
static int Get_Current_Allocated_Memory(int category);
|
||||
static int Get_Peak_Allocated_Memory(int category);
|
||||
|
||||
/*
|
||||
** Interface for the debug version of new and delete
|
||||
*/
|
||||
static int Register_Memory_Allocated(int size);
|
||||
static void Register_Memory_Released(int category,int size);
|
||||
|
||||
/*
|
||||
** New and Delete functions. If you want to use this logging system,
|
||||
** implement global new and delete functions which call into these
|
||||
** functions.
|
||||
*/
|
||||
static void * Allocate_Memory(size_t size);
|
||||
static void Release_Memory(void * mem);
|
||||
|
||||
static void Reset_Counters(); // Reset allocate and free counters
|
||||
static int Get_Allocate_Count(); // Return allocate count since last reset
|
||||
static int Get_Free_Count(); // Return allocate count since last reset
|
||||
|
||||
static void Init();
|
||||
protected:
|
||||
|
||||
/*
|
||||
** Interface for WWMemorySampleClass to set the active category
|
||||
*/
|
||||
static void Push_Active_Category(int category);
|
||||
static void Pop_Active_Category(void);
|
||||
|
||||
static MemLogClass * Get_Log(void);
|
||||
static void Release_Log(void);
|
||||
|
||||
static bool IsMemoryLogEnabled;
|
||||
|
||||
friend class WWMemorySampleClass;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
** WWMemorySampleClass
|
||||
** This class is meant to be created and destroyed on the stack to automatically push
|
||||
** and pop the desired memory category. NOTE: this class should not be used directly,
|
||||
** instead, use the WWMEMLOG macros!
|
||||
*/
|
||||
class WWMemorySampleClass
|
||||
{
|
||||
bool category_push;
|
||||
public:
|
||||
WWMemorySampleClass(int category) : category_push(WWMemoryLogClass::Is_Memory_Log_Enabled())
|
||||
{
|
||||
if (category_push) {
|
||||
WWMemoryLogClass::Push_Active_Category(category);
|
||||
}
|
||||
}
|
||||
|
||||
~WWMemorySampleClass(void)
|
||||
{
|
||||
if (category_push) {
|
||||
WWMemoryLogClass::Pop_Active_Category();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
/*
|
||||
** Use the WWMEMLOG macro to track all memory allocations within the current scope.
|
||||
** If WWDEBUG is not enabled, memory usage logging will be disabled.
|
||||
*/
|
||||
#ifdef USE_MEMLOG
|
||||
#define WWMEMLOG( category ) WWMemorySampleClass _memsample( category )
|
||||
#else
|
||||
#define WWMEMLOG( category )
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#endif //WWMEMLOG_H
|
1138
GeneralsMD/Code/Libraries/Source/WWVegas/WWDebug/wwprofile.cpp
Normal file
1138
GeneralsMD/Code/Libraries/Source/WWVegas/WWDebug/wwprofile.cpp
Normal file
File diff suppressed because it is too large
Load diff
342
GeneralsMD/Code/Libraries/Source/WWVegas/WWDebug/wwprofile.h
Normal file
342
GeneralsMD/Code/Libraries/Source/WWVegas/WWDebug/wwprofile.h
Normal file
|
@ -0,0 +1,342 @@
|
|||
/*
|
||||
** Command & Conquer Generals Zero Hour(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/***********************************************************************************************
|
||||
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
|
||||
***********************************************************************************************
|
||||
* *
|
||||
* Project Name : WWDebug *
|
||||
* *
|
||||
* $Archive:: /Commando/Code/wwdebug/wwprofile.h $*
|
||||
* *
|
||||
* $Author:: Jani_p $*
|
||||
* *
|
||||
* $Modtime:: 3/25/02 2:05p $*
|
||||
* *
|
||||
* $Revision:: 14 $*
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* Functions: *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
#if _MSC_VER >= 1000
|
||||
#pragma once
|
||||
#endif // _MSC_VER >= 1000
|
||||
|
||||
//#define ENABLE_TIME_AND_MEMORY_LOG
|
||||
|
||||
#ifndef WWPROFILE_H
|
||||
#define WWPROFILE_H
|
||||
|
||||
#include "wwstring.h"
|
||||
|
||||
#ifdef _UNIX
|
||||
typedef signed long long __int64;
|
||||
typedef signed long long _int64;
|
||||
#endif
|
||||
|
||||
// enable profiling by default in debug mode.
|
||||
#ifdef WWDEBUG
|
||||
#define ENABLE_WWPROFILE
|
||||
#endif
|
||||
|
||||
extern unsigned WWProfile_Get_System_Time(); // timeGetTime() wrapper
|
||||
class FileClass;
|
||||
|
||||
/*
|
||||
** A node in the WWProfile Hierarchy Tree
|
||||
*/
|
||||
class WWProfileHierachyNodeClass {
|
||||
|
||||
public:
|
||||
WWProfileHierachyNodeClass( const char * name, WWProfileHierachyNodeClass * parent );
|
||||
WWProfileHierachyNodeClass( unsigned id, WWProfileHierachyNodeClass * parent );
|
||||
~WWProfileHierachyNodeClass( void );
|
||||
|
||||
WWProfileHierachyNodeClass * Get_Sub_Node( const char * name );
|
||||
|
||||
WWProfileHierachyNodeClass * Get_Parent( void ) { return Parent; }
|
||||
WWProfileHierachyNodeClass * Get_Sibling( void ) { return Sibling; }
|
||||
WWProfileHierachyNodeClass * Get_Child( void ) { return Child; }
|
||||
|
||||
void Set_Parent( WWProfileHierachyNodeClass *node ) { Parent=node; }
|
||||
void Set_Sibling( WWProfileHierachyNodeClass *node ) { Sibling=node; }
|
||||
void Set_Child( WWProfileHierachyNodeClass *node ) { Child=node; }
|
||||
|
||||
void Reset( void );
|
||||
void Call( void );
|
||||
bool Return( void );
|
||||
|
||||
const char * Get_Name( void ) { return Name; }
|
||||
int Get_Total_Calls( void ) { return TotalCalls; }
|
||||
float Get_Total_Time( void ) { return TotalTime; }
|
||||
void Set_Total_Calls(int calls) { TotalCalls=calls; }
|
||||
void Set_Total_Time(float time) { TotalTime=time; }
|
||||
|
||||
WWProfileHierachyNodeClass* Clone_Hierarchy(WWProfileHierachyNodeClass* parent);
|
||||
void Write_To_File(FileClass* file,int recursion);
|
||||
void Add_To_String_Compact(StringClass& string,int recursion);
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
const char * Name;
|
||||
int TotalCalls;
|
||||
float TotalTime;
|
||||
__int64 StartTime;
|
||||
int RecursionCounter;
|
||||
unsigned ProfileStringID;
|
||||
|
||||
WWProfileHierachyNodeClass * Parent;
|
||||
WWProfileHierachyNodeClass * Child;
|
||||
WWProfileHierachyNodeClass * Sibling;
|
||||
};
|
||||
|
||||
class WWProfileHierachyInfoClass {
|
||||
public:
|
||||
WWProfileHierachyInfoClass( const char * name, WWProfileHierachyInfoClass * parent );
|
||||
~WWProfileHierachyInfoClass( void );
|
||||
|
||||
WWProfileHierachyInfoClass * Get_Parent( void ) { return Parent; }
|
||||
WWProfileHierachyInfoClass * Get_Sibling( void ) { return Sibling; }
|
||||
WWProfileHierachyInfoClass * Get_Child( void ) { return Child; }
|
||||
|
||||
void Set_Parent( WWProfileHierachyInfoClass *node ) { Parent=node; }
|
||||
void Set_Sibling( WWProfileHierachyInfoClass *node ) { Sibling=node; }
|
||||
void Set_Child( WWProfileHierachyInfoClass *node ) { Child=node; }
|
||||
|
||||
const char * Get_Name( void ) { return Name; }
|
||||
void Set_Name( const char* name ) { Name=name; }
|
||||
int Get_Total_Calls( void ) { return TotalCalls; }
|
||||
float Get_Total_Time( void ) { return TotalTime; }
|
||||
void Set_Total_Calls(int calls) { TotalCalls=calls; }
|
||||
void Set_Total_Time(float time) { TotalTime=time; }
|
||||
|
||||
protected:
|
||||
|
||||
StringClass Name;
|
||||
int TotalCalls;
|
||||
float TotalTime;
|
||||
|
||||
WWProfileHierachyInfoClass * Parent;
|
||||
WWProfileHierachyInfoClass * Child;
|
||||
WWProfileHierachyInfoClass * Sibling;
|
||||
};
|
||||
|
||||
/*
|
||||
** An iterator to navigate through the tree
|
||||
*/
|
||||
class WWProfileIterator
|
||||
{
|
||||
public:
|
||||
// Access all the children of the current parent
|
||||
void First(void);
|
||||
void Next(void);
|
||||
bool Is_Done(void);
|
||||
|
||||
void Enter_Child( void ); // Make the current child the new parent
|
||||
void Enter_Child( int index ); // Make the given child the new parent
|
||||
void Enter_Parent( void ); // Make the current parent's parent the new parent
|
||||
|
||||
// Access the current child
|
||||
const char * Get_Current_Name( void ) { return CurrentChild->Get_Name(); }
|
||||
int Get_Current_Total_Calls( void ) { return CurrentChild->Get_Total_Calls(); }
|
||||
float Get_Current_Total_Time( void ) { return CurrentChild->Get_Total_Time(); }
|
||||
|
||||
// Access the current parent
|
||||
const char * Get_Current_Parent_Name( void ) { return CurrentParent->Get_Name(); }
|
||||
int Get_Current_Parent_Total_Calls( void ) { return CurrentParent->Get_Total_Calls(); }
|
||||
float Get_Current_Parent_Total_Time( void ) { return CurrentParent->Get_Total_Time(); }
|
||||
|
||||
protected:
|
||||
WWProfileHierachyNodeClass * CurrentParent;
|
||||
WWProfileHierachyNodeClass * CurrentChild;
|
||||
|
||||
WWProfileIterator( WWProfileHierachyNodeClass * start );
|
||||
friend class WWProfileManager;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
** An iterator to walk through the tree in depth first order
|
||||
*/
|
||||
class WWProfileInOrderIterator
|
||||
{
|
||||
public:
|
||||
void First(void);
|
||||
void Next(void);
|
||||
bool Is_Done(void);
|
||||
|
||||
// Access the current node
|
||||
const char * Get_Current_Name( void ) { return CurrentNode->Get_Name(); }
|
||||
int Get_Current_Total_Calls( void ) { return CurrentNode->Get_Total_Calls(); }
|
||||
float Get_Current_Total_Time( void ) { return CurrentNode->Get_Total_Time(); }
|
||||
|
||||
protected:
|
||||
WWProfileHierachyNodeClass * CurrentNode;
|
||||
|
||||
WWProfileInOrderIterator( void );
|
||||
friend class WWProfileManager;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
** The Manager for the WWProfile system
|
||||
*/
|
||||
class WWProfileManager {
|
||||
public:
|
||||
WWINLINE static void Enable_Profile(bool enable) { IsProfileEnabled=enable; }
|
||||
WWINLINE static bool Is_Profile_Enabled() { return IsProfileEnabled; }
|
||||
|
||||
static void Start_Profile( const char * name );
|
||||
static void Stop_Profile( void );
|
||||
|
||||
static void Start_Root_Profile( const char * name );
|
||||
static void Stop_Root_Profile( void );
|
||||
|
||||
static void Reset( void );
|
||||
static void Increment_Frame_Counter( void );
|
||||
static int Get_Frame_Count_Since_Reset( void ) { return FrameCounter; }
|
||||
static float Get_Time_Since_Reset( void );
|
||||
|
||||
static WWProfileIterator * Get_Iterator( void );
|
||||
static void Release_Iterator( WWProfileIterator * iterator );
|
||||
static WWProfileInOrderIterator * Get_In_Order_Iterator( void );
|
||||
static void Release_In_Order_Iterator( WWProfileInOrderIterator * iterator );
|
||||
|
||||
static WWProfileHierachyNodeClass * Get_Root( void ) { return &Root; }
|
||||
|
||||
static void Begin_Collecting();
|
||||
static void End_Collecting(const char* filename);
|
||||
|
||||
static void Load_Profile_Log(const char* filename, WWProfileHierachyInfoClass**& array, unsigned& count);
|
||||
|
||||
private:
|
||||
static WWProfileHierachyNodeClass Root;
|
||||
static WWProfileHierachyNodeClass * CurrentNode;
|
||||
static WWProfileHierachyNodeClass * CurrentRootNode;
|
||||
static int FrameCounter;
|
||||
static __int64 ResetTime;
|
||||
static bool IsProfileEnabled;
|
||||
|
||||
friend class WWProfileInOrderIterator;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
** WWProfileSampleClass is a simple way to profile a function's scope
|
||||
** Use the WWPROFILE macro at the start of scope to time
|
||||
*/
|
||||
class WWProfileSampleClass {
|
||||
bool IsRoot;
|
||||
bool Enabled;
|
||||
public:
|
||||
WWProfileSampleClass( const char * name, bool is_root ) : IsRoot(is_root), Enabled(WWProfileManager::Is_Profile_Enabled())
|
||||
{
|
||||
if (Enabled) {
|
||||
if (IsRoot) WWProfileManager::Start_Root_Profile( name );
|
||||
else WWProfileManager::Start_Profile( name );
|
||||
}
|
||||
}
|
||||
|
||||
~WWProfileSampleClass( void )
|
||||
{
|
||||
if (Enabled) {
|
||||
if (IsRoot) WWProfileManager::Stop_Root_Profile();
|
||||
else WWProfileManager::Stop_Profile();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#ifdef ENABLE_WWPROFILE
|
||||
#define WWPROFILE( name ) WWProfileSampleClass _wwprofile( name, false )
|
||||
#define WWROOTPROFILE( name ) WWProfileSampleClass _wwprofile( name, true )
|
||||
#else
|
||||
#define WWPROFILE( name )
|
||||
#define WWROOTPROFILE( name )
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
** WWTimeIt is like WWProfile, but it doesn't save anything, it just times one routine, regardless of thread
|
||||
*/
|
||||
class WWTimeItClass {
|
||||
public:
|
||||
WWTimeItClass( const char * name );
|
||||
~WWTimeItClass( void );
|
||||
private:
|
||||
const char * Name;
|
||||
__int64 Time;
|
||||
};
|
||||
|
||||
#ifdef ENABLE_WWPROFILE
|
||||
#define WWTIMEIT( name ) WWTimeItClass _wwtimeit( name )
|
||||
#else
|
||||
#define WWTIMEIT( name )
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/*
|
||||
** WWMeasureItClass is like WWTimeItClass, but it pokes the result into the given float,
|
||||
** and can be used in the release build.
|
||||
*/
|
||||
class WWMeasureItClass {
|
||||
public:
|
||||
WWMeasureItClass( float * p_result );
|
||||
~WWMeasureItClass( void );
|
||||
|
||||
private:
|
||||
__int64 Time;
|
||||
float * PResult;
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
//
|
||||
// Use the first macro to log time and memory usage within the stack segment.
|
||||
// Use the second macro to log intermediate values. The intermediate values are
|
||||
// calculated from the previous intermediate log, so you can log how much each
|
||||
// item takes by placing the macro after each of the
|
||||
//
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
#ifdef ENABLE_TIME_AND_MEMORY_LOG
|
||||
#define WWLOG_PREPARE_TIME_AND_MEMORY(t) WWMemoryAndTimeLog memory_and_time_log(t)
|
||||
#define WWLOG_INTERMEDIATE(t) memory_and_time_log.Log_Intermediate(t)
|
||||
#else
|
||||
#define WWLOG_PREPARE_TIME_AND_MEMORY(t)
|
||||
#define WWLOG_INTERMEDIATE(t)
|
||||
#endif
|
||||
|
||||
struct WWMemoryAndTimeLog
|
||||
{
|
||||
unsigned TimeStart;
|
||||
unsigned IntermediateTimeStart;
|
||||
int AllocCountStart;
|
||||
int IntermediateAllocCountStart;
|
||||
int AllocSizeStart;
|
||||
int IntermediateAllocSizeStart;
|
||||
StringClass Name;
|
||||
static unsigned TabCount;
|
||||
|
||||
WWMemoryAndTimeLog(const char* name);
|
||||
~WWMemoryAndTimeLog();
|
||||
void Log_Intermediate(const char* text);
|
||||
};
|
||||
|
||||
#endif // WWPROFILE_H
|
Reference in a new issue