diff --git a/CMakeLists.txt b/CMakeLists.txt index d96b6908d3..a3f4ad0fa8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -51,9 +51,11 @@ if((WIN32 OR "${CMAKE_SYSTEM}" MATCHES "Windows") AND ${CMAKE_SIZEOF_VOID_P} EQU include(cmake/dbghelp.cmake) endif() +include(cmake/config.cmake) include(cmake/gamespy.cmake) include(cmake/lzhl.cmake) include(cmake/zlib.cmake) + add_subdirectory(Dependencies/Benchmark) if (IS_VS6_BUILD) # The original max sdk does not compile against a modern compiler. @@ -64,51 +66,6 @@ add_subdirectory(Dependencies/SafeDisc) add_subdirectory(Dependencies/Utility) add_subdirectory(resources) -# Do we want to build extra SDK stuff or just the game binary? -option(GENZH_BUILD_ZEROHOUR "Build Zero Hour code." ON) -option(GENZH_BUILD_GENERALS "Build Generals code." ON) -option(GENZH_BUILD_INTERNAL "Build code with the \"Internal\" configuration." OFF) -option(GENZH_BUILD_PROFILE "Build code with the \"Profile\" configuration." OFF) -option(GENZH_BUILD_DEBUG "Build code with the \"Debug\" configuration." OFF) - -if(NOT GENZH_BUILD_ZEROHOUR AND NOT GENZH_BUILD_GENERALS) - set(GENZH_BUILD_ZEROHOUR TRUE) - message("You must select one project to build, building Zero Hour by default.") -endif() - -add_feature_info(ZeroHourStuff GENZH_BUILD_ZEROHOUR "Build Zero Hour code") -add_feature_info(GeneralsStuff GENZH_BUILD_GENERALS "Build Generals code") -add_feature_info(InternalBuild GENZH_BUILD_INTERNAL "Building as an \"Internal\" build") -add_feature_info(ProfileBuild GENZH_BUILD_PROFILE "Building as a \"Profile\" build") -add_feature_info(DebugBuild GENZH_BUILD_DEBUG "Building as a \"Debug\" build") - -add_library(gz_config INTERFACE) - -if(NOT IS_VS6_BUILD) - # Because we set CMAKE_CXX_STANDARD_REQUIRED and CMAKE_CXX_EXTENSIONS in the compilers.cmake this should be enforced. - target_compile_features(gz_config INTERFACE cxx_std_20) -endif() - -target_compile_options(gz_config INTERFACE ${GENZH_FLAGS}) - -# This disables a lot of warnings steering developers to use windows only functions/function names. -if(MSVC) - target_compile_definitions(gz_config INTERFACE _CRT_NONSTDC_NO_WARNINGS _CRT_SECURE_NO_WARNINGS $<$:_DEBUG_CRT>) -endif() - -if(GENZH_BUILD_DEBUG) - target_compile_definitions(gz_config INTERFACE _DEBUG WWDEBUG DEBUG) -else() - target_compile_definitions(gz_config INTERFACE _RELEASE) - - if(GENZH_BUILD_INTERNAL) - target_compile_definitions(gz_config INTERFACE _INTERNAL) - endif() - if(GENZH_BUILD_PROFILE) - target_compile_definitions(gz_config INTERFACE _PROFILE) - endif() -endif() - # Add main build targets if(GENZH_BUILD_ZEROHOUR) add_subdirectory(GeneralsMD) diff --git a/Generals/Code/GameEngine/Include/Common/GameMemory.h b/Generals/Code/GameEngine/Include/Common/GameMemory.h index a30fe2e8be..c007d323a4 100644 --- a/Generals/Code/GameEngine/Include/Common/GameMemory.h +++ b/Generals/Code/GameEngine/Include/Common/GameMemory.h @@ -49,7 +49,9 @@ #define _GAME_MEMORY_H_ // Turn off memory pool checkpointing for now. -#define DISABLE_MEMORYPOOL_CHECKPOINTING 1 +#ifndef DISABLE_MEMORYPOOL_CHECKPOINTING + #define DISABLE_MEMORYPOOL_CHECKPOINTING 1 +#endif #if (defined(_DEBUG) || defined(_INTERNAL)) && !defined(MEMORYPOOL_DEBUG_CUSTOM_NEW) && !defined(DISABLE_MEMORYPOOL_DEBUG_CUSTOM_NEW) #define MEMORYPOOL_DEBUG_CUSTOM_NEW @@ -79,7 +81,7 @@ #ifdef MEMORYPOOL_DEBUG // by default, enable free-block-retention for checkpointing in debug mode - #ifndef DISABLE_MEMORYPOOL_CHECKPOINTING + #if !defined(DISABLE_MEMORYPOOL_CHECKPOINTING) || DISABLE_MEMORYPOOL_CHECKPOINTING == 0 #define MEMORYPOOL_CHECKPOINTING #endif @@ -127,7 +129,7 @@ // ------------------------------------------------------ #endif // MEMORYPOOL_CHECKPOINTING -#ifdef MEMORYPOOL_STACKTRACE +#ifdef MEMORYPOOL_CHECKPOINTING /** display the stacktrace for allocation location for all blocks found. this bit may be mixed-n-matched with any other flag. */ diff --git a/Generals/Code/GameEngine/Source/Common/System/GameMemory.cpp b/Generals/Code/GameEngine/Source/Common/System/GameMemory.cpp index efb0605426..58ab76dece 100644 --- a/Generals/Code/GameEngine/Source/Common/System/GameMemory.cpp +++ b/Generals/Code/GameEngine/Source/Common/System/GameMemory.cpp @@ -181,7 +181,6 @@ DECLARE_PERF_TIMER(MemoryPoolInitFilling) Int theWastedDMA = 0; Int thePeakWastedDMA = 0; -#define NO_INTENSE_DMA_BOOKKEEPING #ifdef INTENSE_DMA_BOOKKEEPING struct UsedNPeak { @@ -2298,6 +2297,9 @@ void DynamicMemoryAllocator::freeBytes(void* pBlockPtr) MemoryPoolSingleBlock *block = MemoryPoolSingleBlock::recoverBlockFromUserData(pBlockPtr); #ifdef MEMORYPOOL_DEBUG Int waste = 0, used = 0; +#ifdef INTENSE_DMA_BOOKKEEPING + const char* tagString; +#endif { USE_PERF_TIMER(MemoryPoolDebugging) waste = 0; @@ -2306,7 +2308,7 @@ void DynamicMemoryAllocator::freeBytes(void* pBlockPtr) if (thePeakDMA < theTotalDMA) thePeakDMA = theTotalDMA; #ifdef INTENSE_DMA_BOOKKEEPING - const char* tagString = block->debugGetLiteralTagString(); + tagString = block->debugGetLiteralTagString(); #endif } #endif MEMORYPOOL_DEBUG diff --git a/GeneralsMD/Code/GameEngine/Include/Common/GameMemory.h b/GeneralsMD/Code/GameEngine/Include/Common/GameMemory.h index b25def60ce..5e394ed69d 100644 --- a/GeneralsMD/Code/GameEngine/Include/Common/GameMemory.h +++ b/GeneralsMD/Code/GameEngine/Include/Common/GameMemory.h @@ -49,7 +49,9 @@ #define _GAME_MEMORY_H_ // Turn off memory pool checkpointing for now. -#define DISABLE_MEMORYPOOL_CHECKPOINTING 1 +#ifndef DISABLE_MEMORYPOOL_CHECKPOINTING + #define DISABLE_MEMORYPOOL_CHECKPOINTING 1 +#endif #if (defined(_DEBUG) || defined(_INTERNAL)) && !defined(MEMORYPOOL_DEBUG_CUSTOM_NEW) && !defined(DISABLE_MEMORYPOOL_DEBUG_CUSTOM_NEW) #define MEMORYPOOL_DEBUG_CUSTOM_NEW @@ -79,7 +81,7 @@ #ifdef MEMORYPOOL_DEBUG // by default, enable free-block-retention for checkpointing in debug mode - #ifndef DISABLE_MEMORYPOOL_CHECKPOINTING + #if !defined(DISABLE_MEMORYPOOL_CHECKPOINTING) || DISABLE_MEMORYPOOL_CHECKPOINTING == 0 #define MEMORYPOOL_CHECKPOINTING #endif @@ -127,7 +129,7 @@ // ------------------------------------------------------ #endif // MEMORYPOOL_CHECKPOINTING -#ifdef MEMORYPOOL_STACKTRACE +#ifdef MEMORYPOOL_CHECKPOINTING /** display the stacktrace for allocation location for all blocks found. this bit may be mixed-n-matched with any other flag. */ diff --git a/GeneralsMD/Code/GameEngine/Source/Common/System/GameMemory.cpp b/GeneralsMD/Code/GameEngine/Source/Common/System/GameMemory.cpp index fd66bdf24c..25f96d478a 100644 --- a/GeneralsMD/Code/GameEngine/Source/Common/System/GameMemory.cpp +++ b/GeneralsMD/Code/GameEngine/Source/Common/System/GameMemory.cpp @@ -80,7 +80,9 @@ DECLARE_PERF_TIMER(MemoryPoolInitFilling) faster to free raw DMA blocks. @todo verify this speedup is enough to be worth the extra space */ -#define MPSB_DLINK +#ifndef DISABLE_MEMORYPOOL_MPSB_DLINK + #define MPSB_DLINK +#endif #ifdef MEMORYPOOL_DEBUG @@ -181,7 +183,6 @@ DECLARE_PERF_TIMER(MemoryPoolInitFilling) Int theWastedDMA = 0; Int thePeakWastedDMA = 0; -#define NO_INTENSE_DMA_BOOKKEEPING #ifdef INTENSE_DMA_BOOKKEEPING struct UsedNPeak { @@ -2287,6 +2288,9 @@ void DynamicMemoryAllocator::freeBytes(void* pBlockPtr) MemoryPoolSingleBlock *block = MemoryPoolSingleBlock::recoverBlockFromUserData(pBlockPtr); #ifdef MEMORYPOOL_DEBUG Int waste = 0, used = 0; +#ifdef INTENSE_DMA_BOOKKEEPING + const char* tagString; +#endif { USE_PERF_TIMER(MemoryPoolDebugging) waste = 0; @@ -2295,7 +2299,7 @@ void DynamicMemoryAllocator::freeBytes(void* pBlockPtr) if (thePeakDMA < theTotalDMA) thePeakDMA = theTotalDMA; #ifdef INTENSE_DMA_BOOKKEEPING - const char* tagString = block->debugGetLiteralTagString(); + tagString = block->debugGetLiteralTagString(); #endif } #endif MEMORYPOOL_DEBUG diff --git a/cmake/config.cmake b/cmake/config.cmake new file mode 100644 index 0000000000..1dbc33386e --- /dev/null +++ b/cmake/config.cmake @@ -0,0 +1,125 @@ +### BUILD OPTIONS ### + +# Do we want to build extra SDK stuff or just the game binary? +option(GENZH_BUILD_ZEROHOUR "Build Zero Hour code." ON) +option(GENZH_BUILD_GENERALS "Build Generals code." ON) +option(GENZH_BUILD_INTERNAL "Build code with the \"Internal\" configuration." OFF) +option(GENZH_BUILD_PROFILE "Build code with the \"Profile\" configuration." OFF) +option(GENZH_BUILD_DEBUG "Build code with the \"Debug\" configuration." OFF) + +if(NOT GENZH_BUILD_ZEROHOUR AND NOT GENZH_BUILD_GENERALS) + set(GENZH_BUILD_ZEROHOUR TRUE) + message("You must select one project to build, building Zero Hour by default.") +endif() + +add_feature_info(ZeroHourStuff GENZH_BUILD_ZEROHOUR "Build Zero Hour code") +add_feature_info(GeneralsStuff GENZH_BUILD_GENERALS "Build Generals code") +add_feature_info(InternalBuild GENZH_BUILD_INTERNAL "Building as an \"Internal\" build") +add_feature_info(ProfileBuild GENZH_BUILD_PROFILE "Building as a \"Profile\" build") +add_feature_info(DebugBuild GENZH_BUILD_DEBUG "Building as a \"Debug\" build") + + +### MEMORY POOL OPTIONS ### + +# Memory pool features +option(GENZH_MEMORYPOOL_OVERRIDE_MALLOC "Enables the Dynamic Memory Allocator for malloc calls." OFF) +option(GENZH_MEMORYPOOL_MPSB_DLINK "Adds a backlink to MemoryPoolSingleBlock. Makes it faster to free raw DMA blocks, but increases memory consumption." ON) + +# Memory pool debugs +option(GENZH_MEMORYPOOL_DEBUG "Enables Memory Pool debug." ON) +option(GENZH_MEMORYPOOL_DEBUG_CUSTOM_NEW "Enables a custom new operator for the Memory Pool." ON) +option(GENZH_MEMORYPOOL_DEBUG_CHECKPOINTING "Records checkpoint information about the history of memory allocations." OFF) +option(GENZH_MEMORYPOOL_DEBUG_BOUNDINGWALL "Enables bounding wall checks around memory chunks to find memory trampling." ON) +option(GENZH_MEMORYPOOL_DEBUG_STACKTRACE "Enables stack trace collection for allocations. Reduces runtime performance significantly." OFF) +option(GENZH_MEMORYPOOL_DEBUG_INTENSE_VERIFY "Enables intensive verifications after nearly every memory operation. OFF by default, since it slows down things a lot, but is worth turning on for really obscure memory corruption issues." OFF) +option(GENZH_MEMORYPOOL_DEBUG_CHECK_BLOCK_OWNERSHIP "Enables debug to verify that a block actually belongs to the pool it is called with. This is great for debugging, but can be realllly slow, so is OFF by default." OFF) +option(GENZH_MEMORYPOOL_DEBUG_INTENSE_DMA_BOOKKEEPING "Prints statistics for memory usage of Memory Pools." OFF) + +# Memory pool features +add_feature_info(MemoryPoolOverrideMalloc GENZH_MEMORYPOOL_OVERRIDE_MALLOC "Build with Memory Pool malloc") +add_feature_info(MemoryPoolMpsbDlink GENZH_MEMORYPOOL_MPSB_DLINK "Build with Memory Pool backlink") + +# Memory pool debugs +add_feature_info(MemoryPoolDebug GENZH_MEMORYPOOL_DEBUG "Build with Memory Pool debug") +add_feature_info(MemoryPoolDebugCustomNew GENZH_MEMORYPOOL_DEBUG_CUSTOM_NEW "Build with Memory Pool custom new") +add_feature_info(MemoryPoolDebugCheckpointing GENZH_MEMORYPOOL_DEBUG_CHECKPOINTING "Build with Memory Pool checkpointing") +add_feature_info(MemoryPoolDebugBoundingwall GENZH_MEMORYPOOL_DEBUG_BOUNDINGWALL "Build with Memory Pool Bounding Wall") +add_feature_info(MemoryPoolDebugStacktrace GENZH_MEMORYPOOL_DEBUG_STACKTRACE "Build with Memory Pool Stacktrace") +add_feature_info(MemoryPoolDebugIntenseVerify GENZH_MEMORYPOOL_DEBUG_INTENSE_VERIFY "Build with Memory Pool intense verify") +add_feature_info(MemoryPoolDebugCheckBlockOwnership GENZH_MEMORYPOOL_DEBUG_CHECK_BLOCK_OWNERSHIP "Build with Memory Pool block ownership checks") +add_feature_info(MemoryPoolDebugIntenseDmaBookkeeping GENZH_MEMORYPOOL_DEBUG_INTENSE_DMA_BOOKKEEPING "Build with Memory Pool intense DMA bookkeeping") + + +### INTERFACE LIBRARY SETUP ### + +add_library(gz_config INTERFACE) + +if(NOT IS_VS6_BUILD) + # Because we set CMAKE_CXX_STANDARD_REQUIRED and CMAKE_CXX_EXTENSIONS in the compilers.cmake this should be enforced. + target_compile_features(gz_config INTERFACE cxx_std_20) +endif() + +target_compile_options(gz_config INTERFACE ${GENZH_FLAGS}) + +# This disables a lot of warnings steering developers to use windows only functions/function names. +if(MSVC) + target_compile_definitions(gz_config INTERFACE _CRT_NONSTDC_NO_WARNINGS _CRT_SECURE_NO_WARNINGS $<$:_DEBUG_CRT>) +endif() + +if(GENZH_BUILD_DEBUG) + target_compile_definitions(gz_config INTERFACE _DEBUG WWDEBUG DEBUG) +else() + target_compile_definitions(gz_config INTERFACE _RELEASE) + + if(GENZH_BUILD_INTERNAL) + target_compile_definitions(gz_config INTERFACE _INTERNAL) + endif() + if(GENZH_BUILD_PROFILE) + target_compile_definitions(gz_config INTERFACE _PROFILE) + endif() +endif() + +# Memory pool features +if(GENZH_MEMORYPOOL_OVERRIDE_MALLOC) + target_compile_definitions(gz_config INTERFACE MEMORYPOOL_OVERRIDE_MALLOC=1) +endif() + +if(NOT GENZH_MEMORYPOOL_MPSB_DLINK) + target_compile_definitions(gz_config INTERFACE DISABLE_MEMORYPOOL_MPSB_DLINK=1) +endif() + +# Memory pool debugs +if(NOT GENZH_MEMORYPOOL_DEBUG) + target_compile_definitions(gz_config INTERFACE DISABLE_MEMORYPOOL_DEBUG=1) +else() + if(NOT GENZH_MEMORYPOOL_DEBUG_CUSTOM_NEW) + target_compile_definitions(gz_config INTERFACE DISABLE_MEMORYPOOL_DEBUG_CUSTOM_NEW=1) + endif() + + if(GENZH_MEMORYPOOL_DEBUG_CHECKPOINTING) + # Set to 0 to override the default setting in code + target_compile_definitions(gz_config INTERFACE DISABLE_MEMORYPOOL_CHECKPOINTING=0) + else() + target_compile_definitions(gz_config INTERFACE DISABLE_MEMORYPOOL_CHECKPOINTING=1) + endif() + + if(NOT GENZH_MEMORYPOOL_DEBUG_BOUNDINGWALL) + target_compile_definitions(gz_config INTERFACE DISABLE_MEMORYPOOL_BOUNDINGWALL=1) + endif() + + if(NOT GENZH_MEMORYPOOL_DEBUG_STACKTRACE) + target_compile_definitions(gz_config INTERFACE DISABLE_MEMORYPOOL_STACKTRACE=1) + endif() + + if(GENZH_MEMORYPOOL_DEBUG_INTENSE_VERIFY) + target_compile_definitions(gz_config INTERFACE MEMORYPOOL_INTENSE_VERIFY=1) + endif() + + if(GENZH_MEMORYPOOL_DEBUG_CHECK_BLOCK_OWNERSHIP) + target_compile_definitions(gz_config INTERFACE MEMORYPOOL_CHECK_BLOCK_OWNERSHIP=1) + endif() + + if(GENZH_MEMORYPOOL_DEBUG_INTENSE_DMA_BOOKKEEPING) + target_compile_definitions(gz_config INTERFACE INTENSE_DMA_BOOKKEEPING=1) + endif() +endif()