2828#include " Common/CRCDebug.h"
2929#include " Common/Debug.h"
3030#include " Common/PerfTimer.h"
31+ #include " Common/LocalFileSystem.h"
3132#include " GameClient/InGameUI.h"
3233#include " GameNetwork/IPEnumeration.h"
3334#include < cstdarg>
4142#ifdef DEBUG_CRC
4243
4344static const Int MaxStrings = 64000 ;
45+ static const Int MaxStringLen = 1024 ;
4446
45- static char DebugStrings[MaxStrings][1024 ];
47+ static char DebugStrings[MaxStrings][MaxStringLen ];
4648static Int nextDebugString = 0 ;
4749static Int numDebugStrings = 0 ;
48- // static char DumpStrings[MaxStrings][1024 ];
50+ // static char DumpStrings[MaxStrings][MaxStringLen ];
4951// static Int nextDumpString = 0;
5052// static Int numDumpStrings = 0;
5153
@@ -91,12 +93,8 @@ CRCVerification::~CRCVerification()
9193#endif
9294}
9395
94- static Bool dumped = FALSE ;
9596void outputCRCDebugLines ( void )
9697{
97- if (dumped)
98- return ;
99- dumped = TRUE ;
10098 IPEnumeration ips;
10199 AsciiString fname;
102100 fname.format (" crcDebug%s.txt" , ips.getMachineName ().str ());
@@ -116,6 +114,60 @@ void outputCRCDebugLines( void )
116114 if (fp) fclose (fp);
117115}
118116
117+ Int lastCRCDebugFrame = 0 ;
118+ Int lastCRCDebugIndex = 0 ;
119+ extern Bool inCRCGen;
120+
121+ void CRCDebugStartNewGame ()
122+ {
123+ if (g_saveDebugCRCPerFrame)
124+ {
125+ // Create folder for frame data, if it doesn't exist yet.
126+ CreateDirectory (g_saveDebugCRCPerFrameDir.str (), NULL );
127+
128+ // Delete existing files
129+ FilenameList files;
130+ AsciiString dir = g_saveDebugCRCPerFrameDir;
131+ dir.concat (" /" );
132+ TheLocalFileSystem->getFileListInDirectory (dir.str (), " " , " DebugFrame_*.txt" , files, FALSE );
133+ FilenameList::iterator it;
134+ for (it = files.begin (); it != files.end (); ++it)
135+ {
136+ DeleteFile (it->str ());
137+ }
138+ }
139+ nextDebugString = 0 ;
140+ numDebugStrings = 0 ;
141+ lastCRCDebugFrame = 0 ;
142+ lastCRCDebugIndex = 0 ;
143+ }
144+
145+ static void outputCRCDebugLinesPerFrame ()
146+ {
147+ if (!g_saveDebugCRCPerFrame || numDebugStrings == 0 )
148+ return ;
149+ AsciiString fname;
150+ fname.format (" %s/DebugFrame_%06d.txt" , g_saveDebugCRCPerFrameDir.str (), lastCRCDebugFrame);
151+ FILE *fp = fopen (fname.str (), " wt" );
152+ int start = 0 ;
153+ int end = nextDebugString;
154+ if (numDebugStrings >= MaxStrings)
155+ start = nextDebugString - MaxStrings;
156+ nextDebugString = 0 ;
157+ numDebugStrings = 0 ;
158+ if (!fp)
159+ return ;
160+
161+ for (Int i=start; i<end; ++i)
162+ {
163+ const char *line = DebugStrings[ (i + MaxStrings) % MaxStrings ];
164+ // DEBUG_LOG(("%s\n", line));
165+ fprintf (fp, " %s\n " , line);
166+ }
167+
168+ fclose (fp);
169+ }
170+
119171void outputCRCDumpLines ( void )
120172{
121173 /*
@@ -137,64 +189,76 @@ static AsciiString getFname(AsciiString path)
137189 return path.reverseFind (' \\ ' ) + 1 ;
138190}
139191
140- Int lastCRCDebugFrame = 0 ;
141- Int lastCRCDebugIndex = 0 ;
142- extern Bool inCRCGen;
143- void addCRCDebugLine (const char *fmt, ...)
192+ static void addCRCDebugLineInternal (bool count, const char *fmt, va_list args)
144193{
145- if (dumped) // || inCRCGen /* || !TheGameLogic->isInGameLogicUpdate()*/ )
194+ if (TheGameLogic == NULL || !( IS_FRAME_OK_TO_LOG ) )
146195 return ;
147196
148- if (IS_FRAME_OK_TO_LOG )
197+ if (lastCRCDebugFrame != TheGameLogic-> getFrame () )
149198 {
199+ outputCRCDebugLinesPerFrame ();
200+ lastCRCDebugFrame = TheGameLogic->getFrame ();
201+ lastCRCDebugIndex = 0 ;
202+ }
150203
151- if (lastCRCDebugFrame != TheGameLogic->getFrame ())
152- {
153- lastCRCDebugFrame = TheGameLogic->getFrame ();
154- lastCRCDebugIndex = 0 ;
155- }
156-
157- sprintf (DebugStrings[nextDebugString], " %d:%d " , TheGameLogic->getFrame (), lastCRCDebugIndex++);
158- // DebugStrings[nextDebugString][0] = 0;
159- Int len = strlen (DebugStrings[nextDebugString]);
204+ if (count)
205+ sprintf (DebugStrings[nextDebugString], " %d:%05d " , TheGameLogic->getFrame (), lastCRCDebugIndex++);
206+ else
207+ DebugStrings[nextDebugString][0 ] = 0 ;
208+ Int len = strlen (DebugStrings[nextDebugString]);
160209
161- va_list va;
162- va_start ( va, fmt );
163- _vsnprintf (DebugStrings[nextDebugString]+len, 1024 -len, fmt, va );
164- DebugStrings[nextDebugString][1023 ] = 0 ;
165- va_end ( va );
210+ _vsnprintf (DebugStrings[nextDebugString]+len, MaxStringLen-len, fmt, args);
211+ DebugStrings[nextDebugString][MaxStringLen-1 ] = 0 ;
166212
167- char *tmp = DebugStrings[nextDebugString];
168- while (tmp && *tmp)
213+ char *tmp = DebugStrings[nextDebugString];
214+ while (tmp && *tmp)
215+ {
216+ if (*tmp == ' \r ' || *tmp == ' \n ' )
169217 {
170- if (*tmp == ' \r ' || *tmp == ' \n ' )
171- {
172- *tmp = ' ' ;
173- }
174- ++tmp;
218+ *tmp = ' ' ;
175219 }
220+ ++tmp;
221+ }
176222
177- // DEBUG_LOG(("%s\n", DebugStrings[nextDebugString]));
223+ // DEBUG_LOG(("%s\n", DebugStrings[nextDebugString]));
178224
179- ++nextDebugString;
180- ++numDebugStrings;
181- if (nextDebugString == MaxStrings)
182- nextDebugString = 0 ;
225+ ++nextDebugString;
226+ ++numDebugStrings;
227+ if (nextDebugString == MaxStrings)
228+ nextDebugString = 0 ;
229+ }
183230
184- }
231+ void addCRCDebugLine (const char *fmt, ...)
232+ {
233+ va_list args;
234+ va_start (args, fmt);
235+ addCRCDebugLineInternal (true , fmt, args);
236+ va_end (args);
237+ }
238+
239+ void addCRCDebugLineNoCounter (const char *fmt, ...)
240+ {
241+ // TheSuperHackers @feature helmutbuhler 04/09/2025
242+ // This version doesn't increase the lastCRCDebugIndex counter
243+ // and can be used for logging lines that don't necessarily match up on all peers.
244+ // (Otherwise the numbers would no longer match up and the diff would be very difficult to read)
245+ va_list args;
246+ va_start (args, fmt);
247+ addCRCDebugLineInternal (false , fmt, args);
248+ va_end (args);
185249}
186250
187251void addCRCGenLine (const char *fmt, ...)
188252{
189- if (dumped || !(IS_FRAME_OK_TO_LOG ))
253+ if (!(IS_FRAME_OK_TO_LOG ))
190254 return ;
191255
192- static char buf[1024 ];
256+ static char buf[MaxStringLen ];
193257 va_list va;
194258 va_start ( va, fmt );
195- _vsnprintf (buf, 1024 , fmt, va );
259+ _vsnprintf (buf, MaxStringLen , fmt, va );
196260 va_end ( va );
197- buf[1023 ] = 0 ;
261+ buf[MaxStringLen- 1 ] = 0 ;
198262 addCRCDebugLine (" %s" , buf);
199263
200264 // DEBUG_LOG(("%s", buf));
@@ -205,8 +269,8 @@ void addCRCDumpLine(const char *fmt, ...)
205269 /*
206270 va_list va;
207271 va_start( va, fmt );
208- _vsnprintf(DumpStrings[nextDumpString], 1024 , fmt, va );
209- DumpStrings[nextDumpString][1023 ] = 0;
272+ _vsnprintf(DumpStrings[nextDumpString], MaxStringLen , fmt, va );
273+ DumpStrings[nextDumpString][MaxStringLen-1 ] = 0;
210274 va_end( va );
211275
212276 ++nextDumpString;
@@ -218,9 +282,6 @@ void addCRCDumpLine(const char *fmt, ...)
218282
219283void dumpVector3 (const Vector3 *v, AsciiString name, AsciiString fname, Int line)
220284{
221- if (dumped)
222- return ;
223-
224285 if (!(IS_FRAME_OK_TO_LOG )) return ;
225286 fname.toLower ();
226287 fname = getFname (fname);
@@ -231,9 +292,6 @@ void dumpVector3(const Vector3 *v, AsciiString name, AsciiString fname, Int line
231292
232293void dumpCoord3D (const Coord3D *c, AsciiString name, AsciiString fname, Int line)
233294{
234- if (dumped)
235- return ;
236-
237295 if (!(IS_FRAME_OK_TO_LOG )) return ;
238296 fname.toLower ();
239297 fname = getFname (fname);
@@ -244,9 +302,6 @@ void dumpCoord3D(const Coord3D *c, AsciiString name, AsciiString fname, Int line
244302
245303void dumpMatrix3D (const Matrix3D *m, AsciiString name, AsciiString fname, Int line)
246304{
247- if (dumped)
248- return ;
249-
250305 if (!(IS_FRAME_OK_TO_LOG )) return ;
251306 fname.toLower ();
252307 fname = getFname (fname);
@@ -260,9 +315,6 @@ void dumpMatrix3D(const Matrix3D *m, AsciiString name, AsciiString fname, Int li
260315
261316void dumpReal (Real r, AsciiString name, AsciiString fname, Int line)
262317{
263- if (dumped)
264- return ;
265-
266318 if (!(IS_FRAME_OK_TO_LOG )) return ;
267319 fname.toLower ();
268320 fname = getFname (fname);
0 commit comments