CRCDebug.cpp 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  1. /*
  2. ** Command & Conquer Generals(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program is distributed in the hope that it will be useful,
  11. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ** GNU General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. ////////////////////////////////////////////////////////////////////////////////
  19. // //
  20. // (c) 2001-2003 Electronic Arts Inc. //
  21. // //
  22. ////////////////////////////////////////////////////////////////////////////////
  23. #include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
  24. #include "Common/CRCDebug.h"
  25. #include "Common/Debug.h"
  26. #include "Common/PerfTimer.h"
  27. #include "GameClient/InGameUI.h"
  28. #include "GameNetwork/IPEnumeration.h"
  29. #include <cstdarg>
  30. #ifdef _INTERNAL
  31. // for occasional debugging...
  32. //#pragma optimize("", off)
  33. //#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes")
  34. #endif
  35. #ifdef DEBUG_CRC
  36. static const Int MaxStrings = 64000;
  37. static char DebugStrings[MaxStrings][1024];
  38. static Int nextDebugString = 0;
  39. static Int numDebugStrings = 0;
  40. //static char DumpStrings[MaxStrings][1024];
  41. //static Int nextDumpString = 0;
  42. //static Int numDumpStrings = 0;
  43. #define IS_FRAME_OK_TO_LOG TheGameLogic->isInGame() && !TheGameLogic->isInShellGame() && !TheDebugIgnoreSyncErrors && \
  44. TheCRCFirstFrameToLog >= 0 && TheCRCFirstFrameToLog <= TheGameLogic->getFrame() \
  45. && TheGameLogic->getFrame() <= TheCRCLastFrameToLog
  46. CRCVerification::CRCVerification()
  47. {
  48. #ifdef DEBUG_LOGGING
  49. /**/
  50. if (g_verifyClientCRC && (IS_FRAME_OK_TO_LOG))
  51. {
  52. m_startCRC = TheGameLogic->getCRC(CRC_RECALC, (g_clientDeepCRC)?"clientPre.crc":"");
  53. }
  54. else
  55. {
  56. m_startCRC = 0;
  57. }
  58. /**/
  59. #endif
  60. }
  61. CRCVerification::~CRCVerification()
  62. {
  63. #ifdef DEBUG_LOGGING
  64. /**/
  65. UnsignedInt endCRC = 0;
  66. if (g_verifyClientCRC && (IS_FRAME_OK_TO_LOG))
  67. {
  68. endCRC = TheGameLogic->getCRC(CRC_RECALC, (g_clientDeepCRC)?"clientPost.crc":"");
  69. }
  70. DEBUG_ASSERTCRASH(!TheGameLogic->isInGame() || m_startCRC == endCRC, ("GameLogic changed outside of GameLogic::update() on frame %d!", TheGameLogic->getFrame()));
  71. if (TheGameLogic->isInMultiplayerGame() && m_startCRC != endCRC)
  72. {
  73. if (TheInGameUI)
  74. {
  75. TheInGameUI->message(UnicodeString(L"GameLogic changed outside of GameLogic::update() - call Matt (x36804)!"));
  76. }
  77. CRCDEBUG_LOG(("GameLogic changed outside of GameLogic::update()!!!\n"));
  78. }
  79. /**/
  80. #endif
  81. }
  82. static Bool dumped = FALSE;
  83. void outputCRCDebugLines( void )
  84. {
  85. if (dumped)
  86. return;
  87. dumped = TRUE;
  88. IPEnumeration ips;
  89. AsciiString fname;
  90. fname.format("crcDebug%s.txt", ips.getMachineName().str());
  91. FILE *fp = fopen(fname.str(), "wt");
  92. int start = 0;
  93. int end = nextDebugString;
  94. if (numDebugStrings >= MaxStrings)
  95. start = nextDebugString - MaxStrings;
  96. for (Int i=start; i<end; ++i)
  97. {
  98. const char *line = DebugStrings[ (i + MaxStrings) % MaxStrings ];
  99. DEBUG_LOG(("%s\n", line));
  100. if (fp) fprintf(fp, "%s\n", line);
  101. }
  102. if (fp) fclose(fp);
  103. }
  104. void outputCRCDumpLines( void )
  105. {
  106. /*
  107. int start = 0;
  108. int end = nextDumpString;
  109. if (numDumpStrings >= MaxStrings)
  110. start = nextDumpString - MaxStrings;
  111. for (Int i=start; i<end; ++i)
  112. {
  113. const char *line = DumpStrings[ (i + MaxStrings) % MaxStrings ];
  114. DEBUG_LOG(("%s", line));
  115. }
  116. */
  117. }
  118. static AsciiString getFname(AsciiString path)
  119. {
  120. return path.reverseFind('\\') + 1;
  121. }
  122. Int lastCRCDebugFrame = 0;
  123. Int lastCRCDebugIndex = 0;
  124. extern Bool inCRCGen;
  125. void addCRCDebugLine(const char *fmt, ...)
  126. {
  127. if (dumped)// || inCRCGen /*|| !TheGameLogic->isInGameLogicUpdate()*/)
  128. return;
  129. if (IS_FRAME_OK_TO_LOG)
  130. {
  131. if (lastCRCDebugFrame != TheGameLogic->getFrame())
  132. {
  133. lastCRCDebugFrame = TheGameLogic->getFrame();
  134. lastCRCDebugIndex = 0;
  135. }
  136. sprintf(DebugStrings[nextDebugString], "%d:%d ", TheGameLogic->getFrame(), lastCRCDebugIndex++);
  137. //DebugStrings[nextDebugString][0] = 0;
  138. Int len = strlen(DebugStrings[nextDebugString]);
  139. va_list va;
  140. va_start( va, fmt );
  141. _vsnprintf(DebugStrings[nextDebugString]+len, 1024-len, fmt, va );
  142. DebugStrings[nextDebugString][1023] = 0;
  143. va_end( va );
  144. char *tmp = DebugStrings[nextDebugString];
  145. while (tmp && *tmp)
  146. {
  147. if (*tmp == '\r' || *tmp == '\n')
  148. {
  149. *tmp = ' ';
  150. }
  151. ++tmp;
  152. }
  153. //DEBUG_LOG(("%s\n", DebugStrings[nextDebugString]));
  154. ++nextDebugString;
  155. ++numDebugStrings;
  156. if (nextDebugString == MaxStrings)
  157. nextDebugString = 0;
  158. }
  159. }
  160. void addCRCGenLine(const char *fmt, ...)
  161. {
  162. if (dumped || !(IS_FRAME_OK_TO_LOG))
  163. return;
  164. static char buf[1024];
  165. va_list va;
  166. va_start( va, fmt );
  167. _vsnprintf(buf, 1024, fmt, va );
  168. va_end( va );
  169. buf[1023] = 0;
  170. addCRCDebugLine("%s", buf);
  171. //DEBUG_LOG(("%s", buf));
  172. }
  173. void addCRCDumpLine(const char *fmt, ...)
  174. {
  175. /*
  176. va_list va;
  177. va_start( va, fmt );
  178. _vsnprintf(DumpStrings[nextDumpString], 1024, fmt, va );
  179. DumpStrings[nextDumpString][1023] = 0;
  180. va_end( va );
  181. ++nextDumpString;
  182. ++numDumpStrings;
  183. if (nextDumpString == MaxStrings)
  184. nextDumpString = 0;
  185. */
  186. }
  187. void dumpVector3(const Vector3 *v, AsciiString name, AsciiString fname, Int line)
  188. {
  189. if (dumped)
  190. return;
  191. if (!(IS_FRAME_OK_TO_LOG)) return;
  192. fname.toLower();
  193. fname = getFname(fname);
  194. addCRCDebugLine("dumpVector3() %s:%d %s %8.8X %8.8X %8.8X\n",
  195. fname.str(), line, name.str(),
  196. AS_INT(v->X), AS_INT(v->Y), AS_INT(v->Z));
  197. }
  198. void dumpCoord3D(const Coord3D *c, AsciiString name, AsciiString fname, Int line)
  199. {
  200. if (dumped)
  201. return;
  202. if (!(IS_FRAME_OK_TO_LOG)) return;
  203. fname.toLower();
  204. fname = getFname(fname);
  205. addCRCDebugLine("dumpCoord3D() %s:%d %s %8.8X %8.8X %8.8X\n",
  206. fname.str(), line, name.str(),
  207. AS_INT(c->x), AS_INT(c->y), AS_INT(c->z));
  208. }
  209. void dumpMatrix3D(const Matrix3D *m, AsciiString name, AsciiString fname, Int line)
  210. {
  211. if (dumped)
  212. return;
  213. if (!(IS_FRAME_OK_TO_LOG)) return;
  214. fname.toLower();
  215. fname = getFname(fname);
  216. const Real *matrix = (const Real *)m;
  217. addCRCDebugLine("dumpMatrix3D() %s:%d %s\n",
  218. fname.str(), line, name.str());
  219. for (Int i=0; i<3; ++i)
  220. addCRCDebugLine(" 0x%08X 0x%08X 0x%08X 0x%08X\n",
  221. AS_INT(matrix[(i<<2)+0]), AS_INT(matrix[(i<<2)+1]), AS_INT(matrix[(i<<2)+2]), AS_INT(matrix[(i<<2)+3]));
  222. }
  223. void dumpReal(Real r, AsciiString name, AsciiString fname, Int line)
  224. {
  225. if (dumped)
  226. return;
  227. if (!(IS_FRAME_OK_TO_LOG)) return;
  228. fname.toLower();
  229. fname = getFname(fname);
  230. addCRCDebugLine("dumpReal() %s:%d %s %8.8X (%f)\n",
  231. fname.str(), line, name.str(), AS_INT(r), r);
  232. }
  233. #endif // DEBUG_CRC