/*============================================================================= DEBUG.C: Functions for debugging. Created June 1997 by Luke Moloney =============================================================================*/ #include #include #include #include #include #include "resource.h" #include "types.h" #include "utility.h" #include "debugwnd.h" #include "task.h" #include "debug.h" /*============================================================================= Data: =============================================================================*/ char dbgFatalErrorString[DBG_BufferLength]; sdword dbgInt3Enabled = TRUE; /*============================================================================= Functions: =============================================================================*/ /*----------------------------------------------------------------------------- Name : dbgMessage Description : Post a generic message Inputs : string - message to print Outputs : .. Return : .. ----------------------------------------------------------------------------*/ sdword dbgMessage(char *string) { return(dbwPrint(0, string)); } /*----------------------------------------------------------------------------- Name : dbgMessagef Description : Post a generic formatted message Inputs : format - format string ... - variable number of parameters Outputs : .. Return : Number of characters printed ----------------------------------------------------------------------------*/ sdword dbgMessagef(char *format, ...) { char buffer[DBG_BufferLength]; va_list argList; sdword nParams; va_start(argList, format); //get first arg _vsnprintf(buffer, DBG_BufferMax, format, argList); //prepare output string va_end(argList); nParams = dbgMessage(buffer); return(nParams); } /*----------------------------------------------------------------------------- Name : dbgWarning Description : Post a warning message Inputs : file - points to file name string line - line number called from string - output string Outputs : Return : ----------------------------------------------------------------------------*/ sdword dbgWarning(char *file, sdword line, char *string) { char buffer[DBG_BufferLength]; _snprintf(buffer, DBG_BufferMax, "\n%s (%d): Warning- %s", file, line, string); return(dbgMessage(buffer)); //print the message } /*----------------------------------------------------------------------------- Name : dbgWarning Description : Post a formatted warning message Inputs : file - points to file name string line - line number called from format - format string ... - variable number of parameters Outputs : Return : ----------------------------------------------------------------------------*/ sdword dbgWarningf(char *file, sdword line, char *format, ...) { char buffer[DBG_BufferLength]; char newFormat[DBG_BufferLength]; va_list argList; sdword returnValue; _snprintf(newFormat, DBG_BufferMax, "\n%s (%d): Warning- %s", file, line, format); va_start(argList, format); //get first arg _vsnprintf(buffer, DBG_BufferMax, newFormat, argList); //prepare output string va_end(argList); returnValue = dbgMessage(buffer); return(returnValue); //print the message } /*----------------------------------------------------------------------------- Name : dbgFatal Description : Print a fatal error message and exit program. Inputs : file - points to file name string line - line number called from string - output string Outputs : Return : ----------------------------------------------------------------------------*/ sdword dbgFatal(char *file, sdword line, char *string) { _snprintf(dbgFatalErrorString, DBG_BufferMax, "\n%s (%d): Fatal error - %s", file, line, string); #if DBG_STACK_CONTEXT { char *fileName = dbgStackDump(); if (fileName) { sprintf(dbgFatalErrorString + strlen(dbgFatalErrorString), "\nDumped to '%s'.", fileName); } } #endif dbgMessage(dbgFatalErrorString); //print the message if (dbgInt3Enabled) { _asm int 3 } utyFatalErrorWaitLoop(DBG_ExitCode); //exit with a MessageBox return(ERROR); } /*----------------------------------------------------------------------------- Name : dbgFatalf Description : Print a formatted fatal error message and exit program. Inputs : file - points to file name string line - line number called from format - format string ... - variable number of parameters Outputs : Return : ----------------------------------------------------------------------------*/ sdword dbgFatalf(char *file, sdword line, char *format, ...) { char newFormat[DBG_BufferLength]; va_list argList; _snprintf(newFormat, DBG_BufferMax, "\n%s (%d): Fatal Error - %s", file, line, format); va_start(argList, format); //get first arg _vsnprintf(dbgFatalErrorString, DBG_BufferMax, newFormat, argList); //prepare output string va_end(argList); #if DBG_STACK_CONTEXT { char *fileName = dbgStackDump(); if (fileName) { sprintf(dbgFatalErrorString + strlen(dbgFatalErrorString), "\nDumped to '%s'.", fileName); } } #endif dbgMessage(dbgFatalErrorString); //print the message if (dbgInt3Enabled) { _asm int 3 } utyFatalErrorWaitLoop(DBG_ExitCode); //exit with a MessageBox return(ERROR); } /*----------------------------------------------------------------------------- Name : dbgNonFatal Description : Non-fatal error handling: pops up a dialog but does not exit the game. Inputs : same as dbgFatal Outputs : Return : 0 ----------------------------------------------------------------------------*/ sdword dbgNonFatal(char *file, sdword line, char *error) { sprintf(dbgFatalErrorString, "\n%s (%d): Non-fatal error - %s", file, line, error); if (utyNonFatalErrorWaitLoop() && dbgInt3Enabled) { _asm int 3 } return(0); } /*----------------------------------------------------------------------------- Name : dbgNonFatalf Description : Non-fatal error handling: pops up a dialog but does not exit the game. Inputs : same as dbgFatalf Outputs : Return : 0 ----------------------------------------------------------------------------*/ sdword dbgNonFatalf(char *file, sdword line, char *format, ...) { va_list argList; char error[DBG_BufferLength]; va_start(argList, format); //get first arg vsprintf(error, format, argList); //prepare output string va_end(argList); dbgNonFatal(file, line, error); //print the message return(0); } /*----------------------------------------------------------------------------- Name : dbgStackDump Description : Dumps the stack to a file for debugging purposes. Inputs : void Outputs : Return : filename of file written to, or NULL on error ----------------------------------------------------------------------------*/ #if DBG_STACK_CONTEXT static char dbgStackFilename[256]; udword dbgStackBase = 0; char *dbgStackDump(void) { udword nDwords, _ESP; char *blankPtr; struct tm *newtime; time_t aclock; FILE *fp; udword referenceAddress; if (dbgStackBase == 0) { return(NULL); } //find stack pointers _asm mov eax, esp _asm mov _ESP, eax _ESP = _ESP & (~3); //round off to dword boundary dbgStackBase = dbgStackBase & (~3); nDwords = dbgStackBase - _ESP; //create a filename with the time in it time( &aclock ); //Get time in seconds newtime = localtime( &aclock ); //Convert time to struct sprintf(dbgStackFilename, "stack-%s.dump", asctime(newtime)); for (blankPtr = dbgStackFilename; *blankPtr; blankPtr++) { if (strchr(": \n\r", *blankPtr)) { *blankPtr = '-'; } } fp = fopen(dbgStackFilename, "wb"); //open the dump file if (fp == NULL) { return(NULL); } fwrite(&_ESP, sizeof(udword), 1, fp); //write the stack reference referenceAddress = (udword)&dbgFatalf; fwrite(&referenceAddress, sizeof(udword), 1, fp); //write the .text reference while (nDwords) { fwrite((udword *)_ESP, sizeof(udword), 1, fp); //write the stack block nDwords--; _ESP++; } fclose(fp); //close the file return(dbgStackFilename); } #endif //DBG_STACK_CONTEXT