Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion Generals/Code/GameEngine/Include/Common/CRCDebug.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,11 @@
void dumpReal(Real r, AsciiString name, AsciiString fname, Int line);

void outputCRCDebugLines( void );
void CRCDebugStartNewGame( void );
void outputCRCDumpLines( void );

void addCRCDebugLine(const char *fmt, ...);
void addCRCDebugLineNoCounter(const char *fmt, ...);
void addCRCDumpLine(const char *fmt, ...);
void addCRCGenLine(const char *fmt, ...);
#define CRCDEBUG_LOG(x) addCRCDebugLine x
Expand All @@ -97,7 +99,9 @@
extern Bool g_crcModuleDataFromLogic;

extern Bool g_keepCRCSaves;

extern Bool g_saveDebugCRCPerFrame;
extern AsciiString g_saveDebugCRCPerFrameDir;

extern Bool g_logObjectCRCs;

#else // DEBUG_CRC
Expand Down
8 changes: 8 additions & 0 deletions Generals/Code/GameEngine/Include/Common/Xfer.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,14 @@
// Desc: The Xfer system is capable of setting up operations to work with blocks of data
// from other subsystems. It can work things such as file reading, file writing,
// CRC computations etc
//
// TheSuperHackers @info helmutbuhler 04/09/2025
// The baseclass Xfer has 3 implementations:
// - XferLoad: Load gamestate
// - XferSave: Save gamestate
// - XferCRC: Calculate gamestate CRC
// - XferDeepCRC: This derives from XferCRC and also writes the gamestate data relevant
// to crc calculation to a file (only used in developer builds)
///////////////////////////////////////////////////////////////////////////////////////////////////

#pragma once
Expand Down
166 changes: 109 additions & 57 deletions Generals/Code/GameEngine/Source/Common/CRCDebug.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include "Common/CRCDebug.h"
#include "Common/Debug.h"
#include "Common/PerfTimer.h"
#include "Common/LocalFileSystem.h"
#include "GameClient/InGameUI.h"
#include "GameNetwork/IPEnumeration.h"
#include <cstdarg>
Expand All @@ -41,11 +42,12 @@
#ifdef DEBUG_CRC

static const Int MaxStrings = 64000;
static const Int MaxStringLen = 1024;

static char DebugStrings[MaxStrings][1024];
static char DebugStrings[MaxStrings][MaxStringLen];
static Int nextDebugString = 0;
static Int numDebugStrings = 0;
//static char DumpStrings[MaxStrings][1024];
//static char DumpStrings[MaxStrings][MaxStringLen];
//static Int nextDumpString = 0;
//static Int numDumpStrings = 0;

Expand Down Expand Up @@ -91,12 +93,8 @@ CRCVerification::~CRCVerification()
#endif
}

static Bool dumped = FALSE;
void outputCRCDebugLines( void )
{
if (dumped)
return;
dumped = TRUE;
IPEnumeration ips;
AsciiString fname;
fname.format("crcDebug%s.txt", ips.getMachineName().str());
Expand All @@ -116,6 +114,60 @@ void outputCRCDebugLines( void )
if (fp) fclose(fp);
}

Int lastCRCDebugFrame = 0;
Int lastCRCDebugIndex = 0;
extern Bool inCRCGen;

void CRCDebugStartNewGame()
{
if (g_saveDebugCRCPerFrame)
{
// Create folder for frame data, if it doesn't exist yet.
CreateDirectory(g_saveDebugCRCPerFrameDir.str(), NULL);

// Delete existing files
FilenameList files;
AsciiString dir = g_saveDebugCRCPerFrameDir;
dir.concat("/");
TheLocalFileSystem->getFileListInDirectory(dir.str(), "", "DebugFrame_*.txt", files, FALSE);
FilenameList::iterator it;
for (it = files.begin(); it != files.end(); ++it)
{
DeleteFile(it->str());
}
}
nextDebugString = 0;
numDebugStrings = 0;
lastCRCDebugFrame = 0;
lastCRCDebugIndex = 0;
}

static void outputCRCDebugLinesPerFrame()
{
if (!g_saveDebugCRCPerFrame || numDebugStrings == 0)
return;
AsciiString fname;
fname.format("%s/DebugFrame_%06d.txt", g_saveDebugCRCPerFrameDir.str(), lastCRCDebugFrame);
FILE *fp = fopen(fname.str(), "wt");
int start = 0;
int end = nextDebugString;
if (numDebugStrings >= MaxStrings)
start = nextDebugString - MaxStrings;
nextDebugString = 0;
numDebugStrings = 0;
if (!fp)
return;

for (Int i=start; i<end; ++i)
{
const char *line = DebugStrings[ (i + MaxStrings) % MaxStrings ];
//DEBUG_LOG(("%s\n", line));
fprintf(fp, "%s\n", line);
}

fclose(fp);
}

void outputCRCDumpLines( void )
{
/*
Expand All @@ -137,64 +189,76 @@ static AsciiString getFname(AsciiString path)
return path.reverseFind('\\') + 1;
}

Int lastCRCDebugFrame = 0;
Int lastCRCDebugIndex = 0;
extern Bool inCRCGen;
void addCRCDebugLine(const char *fmt, ...)
static void addCRCDebugLineInternal(bool count, const char *fmt, va_list args)
{
if (dumped)// || inCRCGen /*|| !TheGameLogic->isInGameLogicUpdate()*/)
if (TheGameLogic == NULL || !(IS_FRAME_OK_TO_LOG))
return;

if (IS_FRAME_OK_TO_LOG)
if (lastCRCDebugFrame != TheGameLogic->getFrame())
{
outputCRCDebugLinesPerFrame();
lastCRCDebugFrame = TheGameLogic->getFrame();
lastCRCDebugIndex = 0;
}

if (lastCRCDebugFrame != TheGameLogic->getFrame())
{
lastCRCDebugFrame = TheGameLogic->getFrame();
lastCRCDebugIndex = 0;
}

sprintf(DebugStrings[nextDebugString], "%d:%d ", TheGameLogic->getFrame(), lastCRCDebugIndex++);
//DebugStrings[nextDebugString][0] = 0;
Int len = strlen(DebugStrings[nextDebugString]);
if (count)
sprintf(DebugStrings[nextDebugString], "%d:%05d ", TheGameLogic->getFrame(), lastCRCDebugIndex++);
else
DebugStrings[nextDebugString][0] = 0;
Int len = strlen(DebugStrings[nextDebugString]);

va_list va;
va_start( va, fmt );
_vsnprintf(DebugStrings[nextDebugString]+len, 1024-len, fmt, va );
DebugStrings[nextDebugString][1023] = 0;
va_end( va );
_vsnprintf(DebugStrings[nextDebugString]+len, MaxStringLen-len, fmt, args);
DebugStrings[nextDebugString][MaxStringLen-1] = 0;

char *tmp = DebugStrings[nextDebugString];
while (tmp && *tmp)
char *tmp = DebugStrings[nextDebugString];
while (tmp && *tmp)
{
if (*tmp == '\r' || *tmp == '\n')
{
if (*tmp == '\r' || *tmp == '\n')
{
*tmp = ' ';
}
++tmp;
*tmp = ' ';
}
++tmp;
}

//DEBUG_LOG(("%s\n", DebugStrings[nextDebugString]));
//DEBUG_LOG(("%s\n", DebugStrings[nextDebugString]));

++nextDebugString;
++numDebugStrings;
if (nextDebugString == MaxStrings)
nextDebugString = 0;
++nextDebugString;
++numDebugStrings;
if (nextDebugString == MaxStrings)
nextDebugString = 0;
}

}
void addCRCDebugLine(const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
addCRCDebugLineInternal(true, fmt, args);
va_end(args);
}

void addCRCDebugLineNoCounter(const char *fmt, ...)
{
// TheSuperHackers @feature helmutbuhler 04/09/2025
// This version doesn't increase the lastCRCDebugIndex counter
// and can be used for logging lines that don't necessarily match up on all peers.
// (Otherwise the numbers would no longer match up and the diff would be very difficult to read)
va_list args;
va_start(args, fmt);
addCRCDebugLineInternal(false, fmt, args);
va_end(args);
}

void addCRCGenLine(const char *fmt, ...)
{
if (dumped || !(IS_FRAME_OK_TO_LOG))
if (!(IS_FRAME_OK_TO_LOG))
return;

static char buf[1024];
static char buf[MaxStringLen];
va_list va;
va_start( va, fmt );
_vsnprintf(buf, 1024, fmt, va );
_vsnprintf(buf, MaxStringLen, fmt, va );
va_end( va );
buf[1023] = 0;
buf[MaxStringLen-1] = 0;
addCRCDebugLine("%s", buf);

//DEBUG_LOG(("%s", buf));
Expand All @@ -205,8 +269,8 @@ void addCRCDumpLine(const char *fmt, ...)
/*
va_list va;
va_start( va, fmt );
_vsnprintf(DumpStrings[nextDumpString], 1024, fmt, va );
DumpStrings[nextDumpString][1023] = 0;
_vsnprintf(DumpStrings[nextDumpString], MaxStringLen, fmt, va );
DumpStrings[nextDumpString][MaxStringLen-1] = 0;
va_end( va );

++nextDumpString;
Expand All @@ -218,9 +282,6 @@ void addCRCDumpLine(const char *fmt, ...)

void dumpVector3(const Vector3 *v, AsciiString name, AsciiString fname, Int line)
{
if (dumped)
return;

if (!(IS_FRAME_OK_TO_LOG)) return;
fname.toLower();
fname = getFname(fname);
Expand All @@ -231,9 +292,6 @@ void dumpVector3(const Vector3 *v, AsciiString name, AsciiString fname, Int line

void dumpCoord3D(const Coord3D *c, AsciiString name, AsciiString fname, Int line)
{
if (dumped)
return;

if (!(IS_FRAME_OK_TO_LOG)) return;
fname.toLower();
fname = getFname(fname);
Expand All @@ -244,9 +302,6 @@ void dumpCoord3D(const Coord3D *c, AsciiString name, AsciiString fname, Int line

void dumpMatrix3D(const Matrix3D *m, AsciiString name, AsciiString fname, Int line)
{
if (dumped)
return;

if (!(IS_FRAME_OK_TO_LOG)) return;
fname.toLower();
fname = getFname(fname);
Expand All @@ -260,9 +315,6 @@ void dumpMatrix3D(const Matrix3D *m, AsciiString name, AsciiString fname, Int li

void dumpReal(Real r, AsciiString name, AsciiString fname, Int line)
{
if (dumped)
return;

if (!(IS_FRAME_OK_TO_LOG)) return;
fname.toLower();
fname = getFname(fname);
Expand Down
Loading