/* ** 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. // // // //////////////////////////////////////////////////////////////////////////////// // FILE: Compression.cpp ///////////////////////////////////////////////////// // Author: Matthew D. Campbell ////////////////////////////////////////////////////////////////////////////// #include "PreRTS.h" #include "Compression.h" #ifdef _INTERNAL // for occasional debugging... //#pragma optimize("", off) //#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes") #endif /////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////// ///// Performance Testing /////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////// //#define TEST_COMPRESSION #ifdef TEST_COMPRESSION #include "GameClient/MapUtil.h" #include "Common/FileSystem.h" #include "Common/File.h" #include "Common/PerfTimer.h" enum { NUM_TIMES = 1 }; struct CompData { public: Int origSize; Int compressedSize[COMPRESSION_MAX+1]; }; #define TEST_COMPRESSION_MIN COMPRESSION_BTREE #define TEST_COMPRESSION_MAX COMPRESSION_MAX void DoCompressTest( void ) { Int i; /* PerfGather *s_compressGathers[TEST_COMPRESSION_MAX+1]; PerfGather *s_decompressGathers[TEST_COMPRESSION_MAX+1]; for (i = TEST_COMPRESSION_MIN; i < TEST_COMPRESSION_MAX+1; ++i) { s_compressGathers[i] = new PerfGather(CompressionManager::getCompressionNameByType((CompressionType)i)); s_decompressGathers[i] = new PerfGather(CompressionManager::getDecompressionNameByType((CompressionType)i)); } */ std::map s_sizes; std::map::const_iterator it = TheMapCache->find("userdata\\maps\\_usa01\\_usa01.map"); if (it != TheMapCache->end()) { //if (it->second.m_isOfficial) //{ //++it; //continue; //} //static Int count = 0; //if (count++ > 2) //break; File *f = TheFileSystem->openFile(it->first.str()); if (f) { DEBUG_LOG(("***************************\nTesting '%s'\n\n", it->first.str())); Int origSize = f->size(); UnsignedByte *buf = (UnsignedByte *)f->readEntireAndClose(); UnsignedByte *uncompressedBuf = NEW UnsignedByte[origSize]; CompData d = s_sizes[it->first]; d.origSize = origSize; d.compressedSize[COMPRESSION_NONE] = origSize; for (i=TEST_COMPRESSION_MIN; i<=TEST_COMPRESSION_MAX; ++i) { DEBUG_LOG(("=================================================\n")); DEBUG_LOG(("Compression Test %d\n", i)); Int maxCompressedSize = CompressionManager::getMaxCompressedSize( origSize, (CompressionType)i ); DEBUG_LOG(("Orig size is %d, max compressed size is %d bytes\n", origSize, maxCompressedSize)); UnsignedByte *compressedBuf = NEW UnsignedByte[maxCompressedSize]; memset(compressedBuf, 0, maxCompressedSize); memset(uncompressedBuf, 0, origSize); Int compressedLen, decompressedLen; for (Int j=0; j < NUM_TIMES; ++j) { //s_compressGathers[i]->startTimer(); compressedLen = CompressionManager::compressData((CompressionType)i, buf, origSize, compressedBuf, maxCompressedSize); //s_compressGathers[i]->stopTimer(); //s_decompressGathers[i]->startTimer(); decompressedLen = CompressionManager::decompressData(compressedBuf, compressedLen, uncompressedBuf, origSize); //s_decompressGathers[i]->stopTimer(); } d.compressedSize[i] = compressedLen; DEBUG_LOG(("Compressed len is %d (%g%% of original size)\n", compressedLen, (double)compressedLen/(double)origSize*100.0)); DEBUG_ASSERTCRASH(compressedLen, ("Failed to compress\n")); DEBUG_LOG(("Decompressed len is %d (%g%% of original size)\n", decompressedLen, (double)decompressedLen/(double)origSize*100.0)); DEBUG_ASSERTCRASH(decompressedLen == origSize, ("orig size does not match compressed+uncompressed output\n")); if (decompressedLen == origSize) { Int ret = memcmp(buf, uncompressedBuf, origSize); if (ret != 0) { DEBUG_CRASH(("orig buffer does not match compressed+uncompressed output - ret was %d\n", ret)); } } delete compressedBuf; compressedBuf = NULL; } DEBUG_LOG(("d = %d -> %d\n", d.origSize, d.compressedSize[i])); s_sizes[it->first] = d; DEBUG_LOG(("s_sizes[%s] = %d -> %d\n", it->first.str(), s_sizes[it->first].origSize, s_sizes[it->first].compressedSize[i])); delete[] buf; buf = NULL; delete[] uncompressedBuf; uncompressedBuf = NULL; } ++it; } for (i=TEST_COMPRESSION_MIN; i<=TEST_COMPRESSION_MAX; ++i) { Real maxCompression = 1000.0f; Real minCompression = 0.0f; Int totalUncompressedBytes = 0; Int totalCompressedBytes = 0; for (std::map::iterator cd = s_sizes.begin(); cd != s_sizes.end(); ++cd) { CompData d = cd->second; Real ratio = d.compressedSize[i]/(Real)d.origSize; maxCompression = min(maxCompression, ratio); minCompression = max(minCompression, ratio); totalUncompressedBytes += d.origSize; totalCompressedBytes += d.compressedSize[i]; } DEBUG_LOG(("***************************************************\n")); DEBUG_LOG(("Compression method %s:\n", CompressionManager::getCompressionNameByType((CompressionType)i))); DEBUG_LOG(("%d bytes compressed to %d (%g%%)\n", totalUncompressedBytes, totalCompressedBytes, totalCompressedBytes/(Real)totalUncompressedBytes*100.0f)); DEBUG_LOG(("Min ratio: %g%%, Max ratio: %g%%\n", minCompression*100.0f, maxCompression*100.0f)); DEBUG_LOG(("\n")); } /* PerfGather::dumpAll(10000); PerfGather::resetAll(); CopyFile( "AAAPerfStats.csv", "AAACompressPerfStats.csv", FALSE ); for (i = TEST_COMPRESSION_MIN; i < TEST_COMPRESSION_MAX+1; ++i) { delete s_compressGathers[i]; s_compressGathers[i] = NULL; delete s_decompressGathers[i]; s_decompressGathers[i] = NULL; } */ } #endif // TEST_COMPRESSION