258 lines
		
	
	
		
			8.1 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			258 lines
		
	
	
		
			8.1 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
/*
 | 
						|
**	Command & Conquer Generals(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) 2001-2003 Electronic Arts Inc.																				//
 | 
						|
//																																						//
 | 
						|
////////////////////////////////////////////////////////////////////////////////
 | 
						|
 | 
						|
// FILE: Debug.h 
 | 
						|
//-----------------------------------------------------------------------------
 | 
						|
//                                                                          
 | 
						|
//                       Westwood Studios Pacific.                          
 | 
						|
//                                                                          
 | 
						|
//                       Confidential Information					         
 | 
						|
//                Copyright (C) 2001 - All Rights Reserved                  
 | 
						|
//                                                                          
 | 
						|
//-----------------------------------------------------------------------------
 | 
						|
//
 | 
						|
// Project:    RTS3
 | 
						|
//
 | 
						|
// File name:  Debug.h
 | 
						|
//
 | 
						|
// Created:    Steven Johnson, August 2001
 | 
						|
//
 | 
						|
// Desc:       Debug Utilities
 | 
						|
//
 | 
						|
//-----------------------------------------------------------------------------
 | 
						|
///////////////////////////////////////////////////////////////////////////////
 | 
						|
 | 
						|
#pragma once
 | 
						|
 | 
						|
#ifndef __DEBUG_H_
 | 
						|
#define __DEBUG_H_
 | 
						|
 | 
						|
class AsciiString;
 | 
						|
 | 
						|
#if defined(_DEBUG) && defined(_INTERNAL)
 | 
						|
	#error "Only one at a time of these should ever be defined"
 | 
						|
#endif
 | 
						|
 | 
						|
// These are stolen from the WW3D Debug file. REALLY useful. :-)
 | 
						|
#define STRING_IT(a) #a																				  
 | 
						|
#define TOKEN_IT(a) STRING_IT(,##a)
 | 
						|
#define MESSAGE(a) message (__FILE__ "(" TOKEN_IT(__LINE__) ") : " a)
 | 
						|
 | 
						|
// BGC, 3/26/03 - put this in so we can build internal worldbuilder for a patch that doesn't
 | 
						|
// have any debugging of any kind.
 | 
						|
//#define DISABLE_DEBUG_LOGGING
 | 
						|
 | 
						|
// by default, turn on ALLOW_DEBUG_UTILS if _DEBUG is turned on.
 | 
						|
#if (defined(_DEBUG) || defined(_INTERNAL)) && !defined(ALLOW_DEBUG_UTILS) && !defined(DISABLE_ALLOW_DEBUG_UTILS)
 | 
						|
	#define ALLOW_DEBUG_UTILS 1
 | 
						|
#endif
 | 
						|
 | 
						|
// these are predicated on ALLOW_DEBUG_UTILS, not _DEBUG, and allow you to selectively disable
 | 
						|
// bits of the debug stuff for special builds.
 | 
						|
#if defined(ALLOW_DEBUG_UTILS) && !defined(DEBUG_LOGGING) && !defined(DISABLE_DEBUG_LOGGING)
 | 
						|
	#define DEBUG_LOGGING 1
 | 
						|
#endif
 | 
						|
#if defined(ALLOW_DEBUG_UTILS) && !defined(DEBUG_CRASHING) && !defined(DISABLE_DEBUG_CRASHING)
 | 
						|
	#define DEBUG_CRASHING 1
 | 
						|
#endif
 | 
						|
 | 
						|
// BGC - added the DEBUG_LOGGING term...doesn't make sense to do stack debugging without a debug log to print to.
 | 
						|
#if defined(ALLOW_DEBUG_UTILS) && !defined(DEBUG_STACKTRACE) && !defined(DISABLE_DEBUG_STACKTRACE) && defined(DEBUG_LOGGING)
 | 
						|
	#define DEBUG_STACKTRACE 1
 | 
						|
#endif
 | 
						|
#if defined(ALLOW_DEBUG_UTILS) && !defined(DEBUG_PROFILE) && !defined(DISABLE_DEBUG_PROFILE)
 | 
						|
	#define DEBUG_PROFILE 1
 | 
						|
#endif
 | 
						|
 | 
						|
#ifdef __cplusplus
 | 
						|
	#define DEBUG_EXTERN_C extern "C"
 | 
						|
#else
 | 
						|
	#define DEBUG_EXTERN_C extern
 | 
						|
#endif
 | 
						|
 | 
						|
 | 
						|
// SYSTEM INCLUDES ////////////////////////////////////////////////////////////
 | 
						|
 | 
						|
// USER INCLUDES //////////////////////////////////////////////////////////////
 | 
						|
 | 
						|
// FORWARD REFERENCES /////////////////////////////////////////////////////////
 | 
						|
 | 
						|
// TYPE DEFINES ///////////////////////////////////////////////////////////////
 | 
						|
 | 
						|
// INLINING ///////////////////////////////////////////////////////////////////
 | 
						|
 | 
						|
// EXTERNALS //////////////////////////////////////////////////////////////////
 | 
						|
 | 
						|
/// @todo: the standard line-to-string trick isn't working correctly in vc6; figure out why
 | 
						|
#define DEBUG_STRING_IT(b)	#b
 | 
						|
#define DEBUG_TOKEN_IT(a)		DEBUG_STRING_IT(a)
 | 
						|
#define DEBUG_FILENLINE			__FILE__ ":" DEBUG_TOKEN_IT(__LINE__)
 | 
						|
 | 
						|
#ifdef ALLOW_DEBUG_UTILS
 | 
						|
 | 
						|
	enum 
 | 
						|
	{
 | 
						|
		DEBUG_FLAG_LOG_TO_FILE = 0x01,	
 | 
						|
		DEBUG_FLAG_LOG_TO_CONSOLE = 0x02,
 | 
						|
		DEBUG_FLAG_PREPEND_TIME = 0x04,
 | 
						|
#ifdef _INTERNAL
 | 
						|
		// by default, _INTERNAL builds log to file, but not to console, in the interest
 | 
						|
		// of speed. want console output? just change this line:
 | 
						|
		DEBUG_FLAGS_DEFAULT = (DEBUG_FLAG_LOG_TO_FILE)
 | 
						|
#else
 | 
						|
		DEBUG_FLAGS_DEFAULT = (DEBUG_FLAG_LOG_TO_FILE | DEBUG_FLAG_LOG_TO_CONSOLE)
 | 
						|
#endif
 | 
						|
	};
 | 
						|
 | 
						|
	DEBUG_EXTERN_C void DebugInit(int flags);
 | 
						|
	DEBUG_EXTERN_C void DebugShutdown();
 | 
						|
 | 
						|
	DEBUG_EXTERN_C int DebugGetFlags();
 | 
						|
	DEBUG_EXTERN_C void DebugSetFlags(int flags);
 | 
						|
 | 
						|
	#define DEBUG_INIT(f)						do { DebugInit(f); } while (0)
 | 
						|
	#define DEBUG_SHUTDOWN()				do { DebugShutdown(); } while (0)
 | 
						|
 | 
						|
#else
 | 
						|
 | 
						|
	#define DEBUG_INIT(f)						((void)0)
 | 
						|
	#define DEBUG_SHUTDOWN()				((void)0)
 | 
						|
 | 
						|
#endif
 | 
						|
 | 
						|
#ifdef DEBUG_LOGGING
 | 
						|
 | 
						|
	DEBUG_EXTERN_C void DebugLog(const char *format, ...);
 | 
						|
 | 
						|
	// This defines a bitmask of log types that we care about, to allow some flexability
 | 
						|
	// in what gets logged.  This should be extended to asserts, too, but the assert box
 | 
						|
	// is waiting to be rewritten. -MDC 3/19/2003
 | 
						|
	extern unsigned int DebugLevelMask;
 | 
						|
	enum
 | 
						|
	{
 | 
						|
		DEBUG_LEVEL_NET = 0,           // in-game network
 | 
						|
		DEBUG_LEVEL_MAX
 | 
						|
	};
 | 
						|
	extern const char *TheDebugLevels[DEBUG_LEVEL_MAX];
 | 
						|
 | 
						|
	#define DEBUG_LOG(m)						do { { DebugLog m ; } } while (0)
 | 
						|
	#define DEBUG_LOG_LEVEL(l, m)		do { if (l & DebugLevelMask) { DebugLog m ; } } while (0)
 | 
						|
	#define DEBUG_ASSERTLOG(c, m)		do { { if (!(c)) DebugLog m ; } } while (0)
 | 
						|
 | 
						|
#else
 | 
						|
 | 
						|
	#define DEBUG_LOG(m)						((void)0)
 | 
						|
	#define DEBUG_LOG_LEVEL(l, m)		((void)0)
 | 
						|
	#define DEBUG_ASSERTLOG(c, m)		((void)0)
 | 
						|
 | 
						|
#endif
 | 
						|
 | 
						|
#ifdef DEBUG_CRASHING
 | 
						|
 | 
						|
	DEBUG_EXTERN_C void DebugCrash(const char *format, ...);
 | 
						|
 | 
						|
	/*
 | 
						|
		Yeah, it's a sleazy global, since we can't reasonably add
 | 
						|
		any args to DebugCrash due to the varargs nature of it. 
 | 
						|
		We'll just let it slide in this case...
 | 
						|
	*/
 | 
						|
	DEBUG_EXTERN_C char* TheCurrentIgnoreCrashPtr;
 | 
						|
 | 
						|
	#define DEBUG_CRASH(m)	\
 | 
						|
		do { \
 | 
						|
			{ \
 | 
						|
				static char ignoreCrash = 0; \
 | 
						|
				if (!ignoreCrash) { \
 | 
						|
					TheCurrentIgnoreCrashPtr = &ignoreCrash; \
 | 
						|
					DebugCrash m ; \
 | 
						|
					TheCurrentIgnoreCrashPtr = NULL; \
 | 
						|
				} \
 | 
						|
			} \
 | 
						|
		} while (0)
 | 
						|
 | 
						|
	#define DEBUG_ASSERTCRASH(c, m)		do { { if (!(c)) DEBUG_CRASH(m); } } while (0)
 | 
						|
 | 
						|
	//Note: RELEASE_CRASH(m) is now always defined.
 | 
						|
	//#define RELEASE_CRASH(m)					DEBUG_CRASH((m))
 | 
						|
 | 
						|
#else
 | 
						|
 | 
						|
	#define DEBUG_CRASH(m)					((void)0)
 | 
						|
	#define DEBUG_ASSERTCRASH(c, m)	((void)0)
 | 
						|
 | 
						|
//	DEBUG_EXTERN_C void ReleaseCrash(const char* reason);
 | 
						|
 | 
						|
//	#define RELEASE_CRASH(m)				do { ReleaseCrash(m); } while (0)
 | 
						|
 | 
						|
#endif
 | 
						|
 | 
						|
DEBUG_EXTERN_C void ReleaseCrash(const char* reason);
 | 
						|
DEBUG_EXTERN_C void ReleaseCrashLocalized(const AsciiString& p, const AsciiString& m);
 | 
						|
 | 
						|
#define RELEASE_CRASH(m)				do { ReleaseCrash(m); } while (0)
 | 
						|
#define RELEASE_CRASHLOCALIZED(p, m)		do { ReleaseCrashLocalized(p, m); } while (0)
 | 
						|
 | 
						|
 | 
						|
#ifdef DEBUG_PROFILE
 | 
						|
 | 
						|
class SimpleProfiler
 | 
						|
{
 | 
						|
private:
 | 
						|
	__int64 m_freq;
 | 
						|
	__int64 m_startThisSession;
 | 
						|
	__int64 m_totalThisSession;
 | 
						|
	__int64 m_totalAllSessions;
 | 
						|
	int			m_numSessions;
 | 
						|
 | 
						|
public:
 | 
						|
 | 
						|
	SimpleProfiler();
 | 
						|
	void start();
 | 
						|
	void stop();
 | 
						|
	void stopAndLog(const char *msg, int howOftenToLog, int howOftenToResetAvg);
 | 
						|
	double getTime();				// of most recent session, in milliseconds
 | 
						|
	int getNumSessions();
 | 
						|
	double getTotalTime();	// total over all sessions, in milliseconds
 | 
						|
	double getAverageTime();	// averaged over all sessions, in milliseconds
 | 
						|
 | 
						|
};
 | 
						|
 | 
						|
#define BEGIN_PROFILE(uniqueid) \
 | 
						|
	static SimpleProfiler prof_##uniqueid; \
 | 
						|
	prof_##uniqueid.start();
 | 
						|
 | 
						|
#define END_PROFILE(uniqueid, msg, howoftentolog, howoftentoreset) \
 | 
						|
	prof_##uniqueid.stopAndLog(msg, howoftentolog, howoftentoreset);
 | 
						|
 | 
						|
#else
 | 
						|
	
 | 
						|
#define BEGIN_PROFILE(uniqueid)
 | 
						|
#define END_PROFILE(uniqueid, msg, howoftentolog, howoftentoreset)
 | 
						|
 | 
						|
#endif
 | 
						|
 | 
						|
// MACROS //////////////////////////////////////////////////////////////////
 | 
						|
 | 
						|
#endif // __DEBUG_H_
 |