Files
source/Standard Gaming Platform/DEBUG.cpp
T
lalien 0530b53b9c bug fixes from Overhaul:
- Data type changes 
- Templates removed

git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@871 3b4a5df2-a311-0410-b5c6-a8a6f20db521
2007-05-09 13:16:37 +00:00

644 lines
15 KiB
C++

// JA2
//**************************************************************************
//
// Filename : debug.c
//
// Purpose : debug manager implementation
//
// Modification history :
//
// xxxxx96:LH - Creation
// xxnov96:HJH - made it work
//
//**************************************************************************
// Because we're in a library, define SGP_DEBUG here - the client may not always
// use the code to write text, because the header switches on the define
#define SGP_DEBUG
//#undef _DEBUG
// WDS: Note: To compile with VS2005 in release mode you might have to not define SGP_DEBUG and
// undefine _DEBUG or you get linker errors.
#ifdef JA2_PRECOMPILED_HEADERS
#include "JA2 SGP ALL.H"
#elif defined( WIZ8_PRECOMPILED_HEADERS )
#include "WIZ8 SGP ALL.H"
#else
#include "types.h"
#include <windows.h>
#include <ddeml.h>
#include <stdio.h>
#include "debug.h"
#include "WCheck.h"
#include "TopicIDs.h"
#include "TopicOps.h"
#include "WizShare.h"
//Kris addition
#ifdef JA2
#include "screenids.h"
#include "Sys Globals.h"
#include "jascreens.h"
#include "gameloop.h"
#include "input.h"
#endif
// CJC added
#ifndef _NO_DEBUG_TXT
#include "fileman.h"
#endif
#endif
#ifdef __cplusplus
extern "C" {
#endif
BOOLEAN gfRecordToFile = FALSE;
BOOLEAN gfRecordToDebugger = TRUE;
// moved from header file: 24mar98:HJH
UINT32 guiProfileStart, guiExecutions, guiProfileTime;
INT32 giProfileCount;
// Had to move these outside the ifdef SGP_DEBUG below, because
// they are required for the String() function, which is NOT a
// debug-mode only function, it's used in release-mode as well! -- DB
CHAR8 gubAssertString[128];
#define MAX_MSG_LENGTH2 512
CHAR8 gbTmpDebugString[8][MAX_MSG_LENGTH2];
UINT8 gubStringIndex = 0;
#ifdef __cplusplus
}
#endif
#ifdef SGP_DEBUG
#ifdef __cplusplus
extern "C" {
#endif
//**************************************************************************
//
// Defines
//
//**************************************************************************
#define BUFSIZE 100
#define TIMER_TIMEOUT 1000
//**************************************************************************
//
// Variables
//
//**************************************************************************
UINT16 TOPIC_MEMORY_MANAGER = INVALID_TOPIC;
UINT16 TOPIC_FILE_MANAGER = INVALID_TOPIC;
UINT16 TOPIC_DATABASE_MANAGER = INVALID_TOPIC;
UINT16 TOPIC_GAME = INVALID_TOPIC;
UINT16 TOPIC_SGP = INVALID_TOPIC;
UINT16 TOPIC_VIDEO = INVALID_TOPIC;
UINT16 TOPIC_INPUT = INVALID_TOPIC;
UINT16 TOPIC_STACK_CONTAINERS = INVALID_TOPIC;
UINT16 TOPIC_LIST_CONTAINERS = INVALID_TOPIC;
UINT16 TOPIC_QUEUE_CONTAINERS = INVALID_TOPIC;
UINT16 TOPIC_PRILIST_CONTAINERS = INVALID_TOPIC;
UINT16 TOPIC_HIMAGE = INVALID_TOPIC;
UINT16 TOPIC_ORDLIST_CONTAINERS = INVALID_TOPIC;
UINT16 TOPIC_3DENGINE = INVALID_TOPIC;
UINT16 TOPIC_VIDEOOBJECT = INVALID_TOPIC;
UINT16 TOPIC_FONT_HANDLER = INVALID_TOPIC;
UINT16 TOPIC_VIDEOSURFACE = INVALID_TOPIC;
UINT16 TOPIC_MOUSE_SYSTEM = INVALID_TOPIC;
UINT16 TOPIC_BUTTON_HANDLER = INVALID_TOPIC;
UINT16 TOPIC_MUTEX = INVALID_TOPIC;
UINT16 TOPIC_JA2 = 3;
UINT16 TOPIC_BLIT_QUEUE = INVALID_TOPIC;
UINT16 TOPIC_JA2OPPLIST = 2;
UINT16 TOPIC_JA2AI = 1;
UINT32 guiTimerID = 0;
UINT8 guiDebugLevels[NUM_TOPIC_IDS]; // don't change this, Luis!!!!
BOOLEAN gfDebugTopics[MAX_TOPICS_ALLOTED];
UINT16 *gpDbgTopicPtrs[MAX_TOPICS_ALLOTED];
// remove debug .txt file
void RemoveDebugText( void );
STRING512 gpcDebugLogFileName;
#ifdef __cplusplus
}
#endif
//**************************************************************************
//
// Functions
//
//**************************************************************************
//**************************************************************************
//
// DbgGetLogFileName
//
//
//
// Parameter List :
// Return Value :
// Modification history :
//
// xxjun98:CJC -> creation
//
//**************************************************************************
BOOLEAN DbgGetLogFileName( STRING512 pcName )
{
// use the provided buffer to get the directory name, then tack on
// "\debug.txt"
#ifndef _NO_DEBUG_TXT
if ( ! GetExecutableDirectory( pcName ) )
{
return( FALSE );
}
if ( strlen( pcName ) > (512 - strlen( "\\debug.txt" ) - 1 ) )
{
// no room!
return( FALSE );
}
strcat( pcName, "\\debug.txt" );
#endif
return( TRUE );
}
//**************************************************************************
//
// DbgInitialize
//
//
//
// Parameter List :
// Return Value :
// Modification history :
//
// xxnov96:HJH -> creation
//
//**************************************************************************
BOOLEAN DbgInitialize(void)
{
INT32 iX;
for( iX = 0; iX < MAX_TOPICS_ALLOTED; iX++ )
{
gpDbgTopicPtrs[iX] = NULL;
}
DbgClearAllTopics();
gfRecordToFile = TRUE;
gfRecordToDebugger = TRUE;
gubAssertString[0] = '\0';
#ifndef _NO_DEBUG_TXT
if (! DbgGetLogFileName( gpcDebugLogFileName ) )
{
return( FALSE );
}
// clear debug text file out
RemoveDebugText( );
#endif
return(TRUE);
}
//**************************************************************************
//
// DbgShutdown
//
//
//
// Parameter List :
// Return Value :
// Modification history :
//
// xxnov96:HJH -> creation
//
//**************************************************************************
void DbgShutdown(void)
{
DbgMessageReal( (UINT16)(-1), CLIENT_SHUTDOWN, 0, "SGP Going Down" );
}
//**************************************************************************
//
// DbgTopicRegistration
//
//
// Parameter List :
// Return Value :
// Modification history :
//
// June 97: BR -> creation
//
//**************************************************************************
void DbgTopicRegistration( UINT8 ubCmd, UINT16 *usTopicID, CHAR8 *zMessage )
{
UINT16 usIndex,usUse;
BOOLEAN fFound;
if ( usTopicID == NULL )
return;
if( ubCmd == TOPIC_REGISTER )
{
usUse = INVALID_TOPIC;
fFound = FALSE;
for( usIndex = 0; usIndex < MAX_TOPICS_ALLOTED && !fFound; usIndex++)
{
if ( !gfDebugTopics[usIndex] )
{
fFound = TRUE;
usUse = usIndex;
}
}
gfDebugTopics[ usUse ] = TRUE;
*usTopicID = usUse;
gpDbgTopicPtrs[usUse] = usTopicID;
DbgMessageReal(usUse, TOPIC_MESSAGE, DBG_LEVEL_0, zMessage );
}
else if( ubCmd == TOPIC_UNREGISTER )
{
if ( *usTopicID >= MAX_TOPICS_ALLOTED )
return;
DbgMessageReal( *usTopicID, TOPIC_MESSAGE, DBG_LEVEL_0, zMessage );
gfDebugTopics[ *usTopicID ] = FALSE;
if (gpDbgTopicPtrs[ *usTopicID ] != NULL )
{
gpDbgTopicPtrs[ *usTopicID ] = NULL;
}
*usTopicID = INVALID_TOPIC;
}
}
// *************************************************************************
// Clear the debug txt file out to prevent it from getting huge
//
//
// *************************************************************************
void RemoveDebugText( void )
{
DeleteFile( gpcDebugLogFileName );
}
//**************************************************************************
//
// DbgClearAllTopics
//
//
// Parameter List :
// Return Value :
// Modification history :
//
// June 97: BR -> creation
//
//**************************************************************************
void DbgClearAllTopics( void )
{
UINT16 usIndex;
for( usIndex = 0; usIndex < MAX_TOPICS_ALLOTED; usIndex++)
{
gfDebugTopics[ usIndex ] = FALSE;
if ( gpDbgTopicPtrs[ usIndex ] != NULL )
{
*gpDbgTopicPtrs[usIndex] = INVALID_TOPIC;
gpDbgTopicPtrs[usIndex] = NULL;
}
}
}
//**************************************************************************
//
// DbgMessageReal
//
//
//
// Parameter List :
// Return Value :
// Modification history :
//
// xxnov96:HJH -> creation
//
//**************************************************************************
void DbgMessageReal(UINT16 uiTopicId, UINT8 uiCommand, UINT8 uiDebugLevel, STR8 strMessage)
{
#ifndef _NO_DEBUG_TXT
FILE *OutFile;
#endif
// Check for a registered topic ID
if ( uiTopicId < MAX_TOPICS_ALLOTED )//&& gfDebugTopics[uiTopicId] )
{
OutputDebugString ( strMessage );
OutputDebugString ( "\n" );
//add _NO_DEBUG_TXT to your SGP preprocessor definitions to avoid this f**king huge file from
//slowly growing behind the scenes!!!!
#ifndef _NO_DEBUG_TXT
if ((OutFile = fopen(gpcDebugLogFileName, "a+t")) != NULL)
{
fprintf(OutFile, "%s\n", strMessage);
fclose(OutFile);
}
#endif
}
}
//**************************************************************************
//
// DbgSetDebugLevel
//
//
//
// Parameter List :
// Return Value :
// Modification history :
//
// 11nov96:HJH -> creation
//
//**************************************************************************
BOOLEAN DbgSetDebugLevel(UINT16 uiTopicId, UINT8 uiDebugLevel)
{
return(TRUE);
}
//**************************************************************************
//
// DbgFailedAssertion
//
//
//
// Parameter List :
// Return Value :
// Modification history :
//
// xxnov96:HJH -> creation
//
//**************************************************************************
void DbgFailedAssertion( BOOLEAN fExpression, STR8 szFile, int nLine )
{
#ifndef _NO_DEBUG_TXT
FILE *OutFile;
if ( fExpression == FALSE )
{
if ((OutFile = fopen(gpcDebugLogFileName, "a+t")) != NULL)
{
fprintf(OutFile, "Assertion Failed at:\n line %i\n %s\n", nLine, szFile);
fclose(OutFile);
}
}
#endif
}
///////////////////////////////////////////////////////////////////////////////////////////////////
void _DebugRecordToFile(BOOLEAN gfState)
{
gfRecordToFile = gfState;
}
///////////////////////////////////////////////////////////////////////////////////////////////////
void _DebugRecordToDebugger(BOOLEAN gfState)
{
gfRecordToDebugger = gfState;
}
///////////////////////////////////////////////////////////////////////////////////////////////////
// Wiz8 compatible debug messaging
void _DebugMessage(UINT8 *pString, UINT32 uiLineNum, UINT8 *pSourceFile)
{
CHAR8 ubOutputString[512];
#ifndef _NO_DEBUG_TXT
FILE *DebugFile;
#endif
//
// Build the output string
//
sprintf( ubOutputString, "{ %ld } %s [Line %d in %s]\n", GetTickCount(), pString, uiLineNum, pSourceFile );
//
// Output to debugger
//
if (gfRecordToDebugger)
{
OutputDebugString( (LPCSTR) ubOutputString );
}
//
// Record to file if required
//
#ifndef _NO_DEBUG_TXT
if (gfRecordToFile)
{
if ((DebugFile = fopen( gpcDebugLogFileName, "a+t" )) != NULL)
{
fputs( ubOutputString, DebugFile );
fclose( DebugFile );
}
}
#endif
}
//////////////////////////////////////////////////////////////////////
// This func is used by Assert()
void _Null(void)
{
}
extern HVOBJECT FontObjs[25];
#ifdef JA2 //JAGGED ALLIANCE 2 VERSION ONLY
void _FailMessage( STR8 pString, UINT32 uiLineNum, STR8 pSourceFile )
{
CHAR8 ubOutputString[512];
#ifndef _NO_DEBUG_TXT
MSG Message;
FILE *DebugFile;
#endif
BOOLEAN fDone = FALSE;
//Build the output strings
sprintf( ubOutputString, "{ %ld } Assertion Failure [Line %d in %s]\n", GetTickCount(), uiLineNum, pSourceFile );
if( pString )
sprintf( gubAssertString, pString );
else
sprintf( gubAssertString, "" );
//Output to debugger
if (gfRecordToDebugger)
OutputDebugString( ubOutputString );
//Record to file if required
#ifndef _NO_DEBUG_TXT
if (gfRecordToFile)
{
if ((DebugFile = fopen( gpcDebugLogFileName, "a+t" )) != NULL)
{
fputs( ubOutputString, DebugFile );
fclose( DebugFile );
}
}
#if 0
if( !FontObjs[0] )
{ //Font manager hasn't yet been initialized so use the windows error system
sprintf( gubErrorText, "Assertion Failure -- Line %d in %s", uiLineNum, pSourceFile );
MessageBox( NULL, gubErrorText, "Jagged Alliance 2", MB_OK );
gfProgramIsRunning = FALSE;
return;
}
#endif
//Kris:
//NASTY HACK, THE GAME IS GOING TO DIE ANYWAY, SO WHO CARES WHAT WE DO.
//This will actually bring up a screen that prints out the assert message
//until the user hits esc or alt-x.
sprintf( gubErrorText, "Assertion Failure -- Line %d in %s", uiLineNum, pSourceFile );
SetPendingNewScreen( ERROR_SCREEN );
SetCurrentScreen( ERROR_SCREEN );
while (gfProgramIsRunning)
{
if (PeekMessage(&Message, NULL, 0, 0, PM_NOREMOVE))
{ // We have a message on the WIN95 queue, let's get it
if (!GetMessage(&Message, NULL, 0, 0))
{ // It's quitting time
continue;
}
// Ok, now that we have the message, let's handle it
TranslateMessage(&Message);
DispatchMessage(&Message);
}
else
{ // Windows hasn't processed any messages, therefore we handle the rest
GameLoop();
gfSGPInputReceived = FALSE;
}
}
#endif
exit(0);
}
#else //NOT JAGGED ALLIANCE 2
void _FailMessage(STR8 pString, UINT32 uiLineNum, STR8 pSourceFile)
{
CHAR8 ubOutputString[512];
BOOLEAN fDone = FALSE;
#ifndef _NO_DEBUG_TXT
FILE *DebugFile;
#endif
// Build the output string
sprintf( ubOutputString, "{ %ld } Assertion Failure: %s [Line %d in %s]\n", GetTickCount(), pString, uiLineNum, pSourceFile );
if( pString )
sprintf( gubAssertString, pString );
// Output to debugger
if (gfRecordToDebugger)
{
OutputDebugString( ubOutputString );
if( pString )
{ //tag on the assert message
OutputDebugString( gubAssertString );
}
}
// Record to file if required
#ifndef _NO_DEBUG_TXT
if (gfRecordToFile)
{
if ((DebugFile = fopen( gpcDebugLogFileName, "a+t" )) != NULL)
{
fputs( ubOutputString, DebugFile );
if( pString )
{ //tag on the assert message
fputs( gubAssertString, DebugFile );
}
fclose( DebugFile );
}
}
#endif
exit( 0 );
}
#endif
#else
BOOLEAN DbgInitialize(void) { return true; };
void DbgShutdown(void) {};
#endif
// This is NOT a _DEBUG only function! It is also needed in
// release mode builds. -- DB
STR8 String(const STR8 String, ...)
{
va_list ArgPtr;
UINT8 usIndex;
// Record string index. This index is used since we live in a multitasking environment.
// It is still not bulletproof, but it's better than a single string
usIndex = gubStringIndex++;
if (gubStringIndex == 8)
{ // reset string pointer
gubStringIndex = 0;
}
va_start(ArgPtr, String);
vsprintf( gbTmpDebugString[usIndex], String, ArgPtr);
va_end(ArgPtr);
return gbTmpDebugString[usIndex];
}