/* ** Command & Conquer Generals Zero Hour(tm) ** Copyright 2025 Electronic Arts Inc. ** ** This program is free software: you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation, either version 3 of the License, or ** (at your option) any later version. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. ** ** You should have received a copy of the GNU General Public License ** along with this program. If not, see . */ //////////////////////////////////////////////////////////////////////////////// // // // (c) 2001-2003 Electronic Arts Inc. // // // //////////////////////////////////////////////////////////////////////////////// #include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine #include "Common/CRCDebug.h" #include "Common/Debug.h" #include "Common/PerfTimer.h" #include "GameClient/InGameUI.h" #include "GameNetwork/IPEnumeration.h" #include #ifdef _INTERNAL // for occasional debugging... //#pragma optimize("", off) //#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes") #endif #ifdef DEBUG_CRC static const Int MaxStrings = 64000; static char DebugStrings[MaxStrings][1024]; static Int nextDebugString = 0; static Int numDebugStrings = 0; //static char DumpStrings[MaxStrings][1024]; //static Int nextDumpString = 0; //static Int numDumpStrings = 0; #define IS_FRAME_OK_TO_LOG TheGameLogic->isInGame() && !TheGameLogic->isInShellGame() && !TheDebugIgnoreSyncErrors && \ TheCRCFirstFrameToLog >= 0 && TheCRCFirstFrameToLog <= TheGameLogic->getFrame() \ && TheGameLogic->getFrame() <= TheCRCLastFrameToLog CRCVerification::CRCVerification() { #ifdef DEBUG_LOGGING /**/ if (g_verifyClientCRC && (IS_FRAME_OK_TO_LOG)) { m_startCRC = TheGameLogic->getCRC(CRC_RECALC, (g_clientDeepCRC)?"clientPre.crc":""); } else { m_startCRC = 0; } /**/ #endif } CRCVerification::~CRCVerification() { #ifdef DEBUG_LOGGING /**/ UnsignedInt endCRC = 0; if (g_verifyClientCRC && (IS_FRAME_OK_TO_LOG)) { endCRC = TheGameLogic->getCRC(CRC_RECALC, (g_clientDeepCRC)?"clientPost.crc":""); } DEBUG_ASSERTCRASH(!TheGameLogic->isInGame() || m_startCRC == endCRC, ("GameLogic changed outside of GameLogic::update() on frame %d!", TheGameLogic->getFrame())); if (TheGameLogic->isInMultiplayerGame() && m_startCRC != endCRC) { if (TheInGameUI) { TheInGameUI->message(UnicodeString(L"GameLogic changed outside of GameLogic::update() - call Matt (x36804)!")); } CRCDEBUG_LOG(("GameLogic changed outside of GameLogic::update()!!!\n")); } /**/ #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()); FILE *fp = fopen(fname.str(), "wt"); int start = 0; int end = nextDebugString; if (numDebugStrings >= MaxStrings) start = nextDebugString - MaxStrings; for (Int i=start; i= MaxStrings) start = nextDumpString - MaxStrings; for (Int i=start; iisInGameLogicUpdate()*/) return; if (IS_FRAME_OK_TO_LOG) { 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]); va_list va; va_start( va, fmt ); _vsnprintf(DebugStrings[nextDebugString]+len, 1024-len, fmt, va ); DebugStrings[nextDebugString][1023] = 0; va_end( va ); char *tmp = DebugStrings[nextDebugString]; while (tmp && *tmp) { if (*tmp == '\r' || *tmp == '\n') { *tmp = ' '; } ++tmp; } //DEBUG_LOG(("%s\n", DebugStrings[nextDebugString])); ++nextDebugString; ++numDebugStrings; if (nextDebugString == MaxStrings) nextDebugString = 0; } } void addCRCGenLine(const char *fmt, ...) { if (dumped || !(IS_FRAME_OK_TO_LOG)) return; static char buf[1024]; va_list va; va_start( va, fmt ); _vsnprintf(buf, 1024, fmt, va ); va_end( va ); buf[1023] = 0; addCRCDebugLine("%s", buf); //DEBUG_LOG(("%s", buf)); } void addCRCDumpLine(const char *fmt, ...) { /* va_list va; va_start( va, fmt ); _vsnprintf(DumpStrings[nextDumpString], 1024, fmt, va ); DumpStrings[nextDumpString][1023] = 0; va_end( va ); ++nextDumpString; ++numDumpStrings; if (nextDumpString == MaxStrings) nextDumpString = 0; */ } 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); addCRCDebugLine("dumpVector3() %s:%d %s %8.8X %8.8X %8.8X\n", fname.str(), line, name.str(), AS_INT(v->X), AS_INT(v->Y), AS_INT(v->Z)); } 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); addCRCDebugLine("dumpCoord3D() %s:%d %s %8.8X %8.8X %8.8X\n", fname.str(), line, name.str(), AS_INT(c->x), AS_INT(c->y), AS_INT(c->z)); } 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); const Real *matrix = (const Real *)m; addCRCDebugLine("dumpMatrix3D() %s:%d %s\n", fname.str(), line, name.str()); for (Int i=0; i<3; ++i) addCRCDebugLine(" 0x%08X 0x%08X 0x%08X 0x%08X\n", AS_INT(matrix[(i<<2)+0]), AS_INT(matrix[(i<<2)+1]), AS_INT(matrix[(i<<2)+2]), AS_INT(matrix[(i<<2)+3])); } 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); addCRCDebugLine("dumpReal() %s:%d %s %8.8X (%f)\n", fname.str(), line, name.str(), AS_INT(r), r); } #endif // DEBUG_CRC