From 542a723122d84c7b2c65d1a67d3fa7edc3aa4f80 Mon Sep 17 00:00:00 2001 From: OmniBlade Date: Thu, 18 Sep 2025 10:28:01 +0100 Subject: [PATCH] refactor(leveledit): Public build + replace NvDXTLib. Replaces NvDXTLib with crunch to allow open source DXT texture compression. Builds editor as "Public" build. This disabled a bunch of VSS code that doesn't work outside of the original development environment. --- CMakeLists.txt | 14 +++-- Code/Tools/LevelEdit/CMakeLists.txt | 21 ++----- Code/Tools/LevelEdit/FileMgr.cpp | 4 +- Code/Tools/LevelEdit/TGAToDXT.cpp | 84 ++++++++------------------ Code/Tools/LevelEdit/editorbuild.h | 2 +- cmake/crunch.cmake | 94 +++++++++++++++++++++++++++++ 6 files changed, 138 insertions(+), 81 deletions(-) create mode 100644 cmake/crunch.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index 8f77e6d75..8183fb415 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,8 +12,10 @@ endif() project(commando LANGUAGES C CXX) +list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake") + # This file handles extra settings wanted/needed for different compilers. -include(cmake/compilers.cmake) +include(compilers) # Set where the build results will end up set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}" CACHE PATH "Where to output archives") @@ -49,27 +51,27 @@ endif() include(FetchContent) if(W3D_BUILD_OPTION_FFMPEG) - include(cmake/ffmpeg.cmake) + include(ffmpeg) endif() # Find/Add build dependencies and stubs. # Only 32bit Windows can make use of these APIs as the libraries shipped with the game. if(WIN32) - include(cmake/miles.cmake) + include(miles) # Do we want to build with bink for video decoding? option(W3D_BUILD_OPTION_BINK "Build with bink." ON) add_feature_info(BinkBuild W3D_BUILD_OPTION_BINK "Build Renegade with Bink") if(W3D_BUILD_OPTION_BINK) - include(cmake/bink.cmake) + include(bink) target_compile_definitions(binkstub INTERFACE W3D_HAS_BINK) endif() - include(cmake/dx9.cmake) + include(dx9) endif() -include(cmake/gamespy.cmake) +include(gamespy) # Add main build targets add_subdirectory(Code) diff --git a/Code/Tools/LevelEdit/CMakeLists.txt b/Code/Tools/LevelEdit/CMakeLists.txt index 85df1e3c4..d783ce456 100644 --- a/Code/Tools/LevelEdit/CMakeLists.txt +++ b/Code/Tools/LevelEdit/CMakeLists.txt @@ -191,7 +191,7 @@ set(LEVELEDIT_SRC VisStatsDialog.cpp VisualOptionsDialog.cpp VisWindowDialog.cpp - VSSClass.cpp + #VSSClass.cpp WaypathDefinition.cpp WaypathInfoPage.cpp WaypathNode.cpp @@ -408,7 +408,7 @@ set(LEVELEDIT_SRC VisStatsDialog.h VisualOptionsDialog.h VisWindowDialog.h - VSSClass.h + #VSSClass.h WaypathDefinition.h WaypathInfoPage.h WaypathNode.h @@ -419,8 +419,11 @@ set(LEVELEDIT_SRC ZoneEditDialog.h ZoneInfoPage.h ZoneNode.h + LevelEdit.rc ) +include(crunch) + # Targets to build. add_executable(leveledit WIN32) @@ -434,6 +437,7 @@ target_include_directories(leveledit PRIVATE ) target_link_libraries(leveledit PRIVATE + crnlib winmm wsock32 shlwapi @@ -458,17 +462,4 @@ target_link_libraries(leveledit PRIVATE combate ) -if(WIN32) - target_link_options(leveledit PRIVATE /NODEFAULTLIB:libci.lib /NODEFAULTLIB:libc.lib) - add_custom_command( - OUTPUT VSS.h VSS_i.c - COMMAND midl.exe "${CMAKE_CURRENT_SOURCE_DIR}\\VSS.IDL" /header VSS.h - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - DEPENDS "${CMAKE_CURRENT_LIST_DIR}/VSS.IDL" - VERBATIM - ) - - target_sources(leveledit PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/VSS_i.c LevelEdit.rc) -endif() - target_sources(leveledit PRIVATE ${LEVELEDIT_SRC}) diff --git a/Code/Tools/LevelEdit/FileMgr.cpp b/Code/Tools/LevelEdit/FileMgr.cpp index fa84ea0a8..3801bb832 100644 --- a/Code/Tools/LevelEdit/FileMgr.cpp +++ b/Code/Tools/LevelEdit/FileMgr.cpp @@ -56,12 +56,14 @@ #include "presetmgr.h" #include "spawnernode.h" #include "wwstring.h" -#include "vssclass.h" #include "assetdatabase.h" #include "editorbuild.h" #include "assetpackagemgr.h" #include "mixfiledatabase.h" +#ifndef PUBLIC_EDITOR_VER +#include "vssclass.h" +#endif //////////////////////////////////////////////////////////////////////// diff --git a/Code/Tools/LevelEdit/TGAToDXT.cpp b/Code/Tools/LevelEdit/TGAToDXT.cpp index 3b28b459d..d57f30164 100644 --- a/Code/Tools/LevelEdit/TGAToDXT.cpp +++ b/Code/Tools/LevelEdit/TGAToDXT.cpp @@ -35,11 +35,11 @@ * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ #include "StdAfx.h" -//#include "NvDXTLib.h" #include "Targa.h" #include "TGAToDXT.H" +#include #include -#include +#include // Singletons. TGAToDXTClass _TGAToDXTConverter; @@ -52,11 +52,10 @@ TGAToDXTClass _TGAToDXTConverter; /////////////////////////////////////////////////////////////////////////////// TGAToDXTClass::TGAToDXTClass() : WriteTimePtr (NULL), + Buffer(NULL), BufferSize (1024), BufferCount (0) { - Buffer = new unsigned char [BufferSize]; - ASSERT (Buffer != NULL); } @@ -67,8 +66,6 @@ TGAToDXTClass::TGAToDXTClass() /////////////////////////////////////////////////////////////////////////////// TGAToDXTClass::~TGAToDXTClass() { - // Clean-up. - delete [] Buffer; } @@ -102,64 +99,31 @@ bool TGAToDXTClass::Convert (const char *inputpathname, const char *outputpathna validsize = (targa.Header.Width >= 4) && (targa.Header.Height >= 4); validaspect = ((float) MAX (targa.Header.Width, targa.Header.Height)) / ((float) MIN (targa.Header.Width, targa.Header.Height)) <= 8.0f; if (validbitdepth && validsize && validaspect) { - - unsigned char *byte; - HRESULT errorcode; + crn_comp_params comp_params; + comp_params.m_width = targa.Header.Width; + comp_params.m_height = targa.Header.Height; + comp_params.set_flag(cCRNCompFlagHierarchical, false); + comp_params.m_file_type = cCRNFileTypeDDS; + comp_params.m_format = targa.Header.PixelDepth == 32 ? cCRNFmtDXT5 : cCRNFmtDXT1; targa.YFlip(); + comp_params.m_pImages[0][0] = reinterpret_cast(targa.GetImage()); - // If TGA has an alpha channel... - if (targa.Header.PixelDepth == 32) { - - // Analyse the alpha channel and ignore it if it contains redundant data (ie. is either all black or all white). - byte = (unsigned char*) targa.GetImage(); - if ((*(byte + 3) == 0x00) || (*(byte + 3) == 0xff)) { - - const unsigned char alpha = *(byte + 3); - - redundantalpha = true; - for (unsigned p = 0; p < ((unsigned) targa.Header.Width) * ((unsigned) targa.Header.Height); p++) { - redundantalpha &= (*(byte + 3) == alpha); - byte += 4; - } - } - - if (!redundantalpha) { - errorcode = E_NOTIMPL; - //errorcode = ::nvDXTcompress ((unsigned char*) targa.GetImage(), targa.Header.Width, targa.Header.Height, TF_DXT5, true, false, 4); - - } else { - - unsigned char *nonalphaimage, *nonalphabyte; - - // Remove the alpha channel and swizel the pixel data. - nonalphaimage = new unsigned char [3 * ((unsigned) targa.Header.Width) * ((unsigned) targa.Header.Height)]; - nonalphabyte = nonalphaimage; - - byte = (unsigned char*) targa.GetImage(); - for (unsigned p = 0; p < ((unsigned) targa.Header.Width) * ((unsigned) targa.Header.Height); p++) { - - *(nonalphabyte + 0) = *(byte + 0); - *(nonalphabyte + 1) = *(byte + 1); - *(nonalphabyte + 2) = *(byte + 2); - nonalphabyte += 3; - byte += 4; - } - - errorcode = E_NOTIMPL; - //errorcode = ::nvDXTcompress (nonalphaimage, targa.Header.Width, targa.Header.Height, TF_DXT1, true, false, 3); - delete [] nonalphaimage; - } - - } else { - errorcode = E_NOTIMPL; - //errorcode = ::nvDXTcompress ((unsigned char*) targa.GetImage(), targa.Header.Width, targa.Header.Height, TF_DXT1, true, false, 3); - } + crn_mipmap_params mip_params; + // mip_params.m_gamma_filtering = true; + mip_params.m_mode = cCRNMipModeGenerateMips; + mip_params.m_min_mip_size = 4; + crn_uint32 output_file_size; + void *output_file_data = crn_compress(comp_params, mip_params, output_file_size); // Was the image compressed successfully? // NOTE: Any image that does not have power of 2 dimensions will not be compressed. - if (errorcode >= 0) { + if (output_file_data) { + Buffer = static_cast(output_file_data); + BufferCount = output_file_size; Write (outputpathname); + Buffer = NULL; + crn_free_block(output_file_data); success = true; } } @@ -176,10 +140,14 @@ bool TGAToDXTClass::Convert (const char *inputpathname, const char *outputpathna /////////////////////////////////////////////////////////////////////////////// void TGAToDXTClass::Write (const char *outputpathname) { + if (!Buffer) { + return; + } + HANDLE hfile; DWORD bytecountwritten; - hfile = ::CreateFile (outputpathname, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, 0L, NULL); + hfile = ::CreateFileA (outputpathname, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, 0L, NULL); if (hfile != INVALID_HANDLE_VALUE) { LockFile (hfile, 0, 0, BufferCount, 0); WriteFile (hfile, Buffer, BufferCount, &bytecountwritten, NULL); diff --git a/Code/Tools/LevelEdit/editorbuild.h b/Code/Tools/LevelEdit/editorbuild.h index f6cc6ddd5..6626b3e0a 100644 --- a/Code/Tools/LevelEdit/editorbuild.h +++ b/Code/Tools/LevelEdit/editorbuild.h @@ -53,7 +53,7 @@ // built with the public "mod" functionality or the in-house tool // functionality. // -//#define PUBLIC_EDITOR_VER +#define PUBLIC_EDITOR_VER diff --git a/cmake/crunch.cmake b/cmake/crunch.cmake new file mode 100644 index 000000000..74ded8316 --- /dev/null +++ b/cmake/crunch.cmake @@ -0,0 +1,94 @@ +FetchContent_Populate( + crunch + GIT_REPOSITORY https://github.com/BinomialLLC/crunch.git + GIT_TAG 36479bc697be19168daafbf15f47f3c60ccec004 +) + +set(CRNLIB_SOURCES + ${crunch_SOURCE_DIR}/crnlib/crn_arealist.cpp + ${crunch_SOURCE_DIR}/crnlib/crn_assert.cpp + ${crunch_SOURCE_DIR}/crnlib/crn_checksum.cpp + ${crunch_SOURCE_DIR}/crnlib/crn_colorized_console.cpp + ${crunch_SOURCE_DIR}/crnlib/crn_command_line_params.cpp + ${crunch_SOURCE_DIR}/crnlib/crn_comp.cpp + ${crunch_SOURCE_DIR}/crnlib/crn_console.cpp + ${crunch_SOURCE_DIR}/crnlib/crn_core.cpp + ${crunch_SOURCE_DIR}/crnlib/crn_data_stream.cpp + ${crunch_SOURCE_DIR}/crnlib/crn_dds_comp.cpp + ${crunch_SOURCE_DIR}/crnlib/crn_decomp.cpp + ${crunch_SOURCE_DIR}/crnlib/crn_dxt.cpp + ${crunch_SOURCE_DIR}/crnlib/crn_dxt1.cpp + ${crunch_SOURCE_DIR}/crnlib/crn_dxt5a.cpp + ${crunch_SOURCE_DIR}/crnlib/crn_dxt_endpoint_refiner.cpp + ${crunch_SOURCE_DIR}/crnlib/crn_dxt_fast.cpp + ${crunch_SOURCE_DIR}/crnlib/crn_dxt_hc.cpp + ${crunch_SOURCE_DIR}/crnlib/crn_dxt_hc_common.cpp + ${crunch_SOURCE_DIR}/crnlib/crn_dxt_image.cpp + ${crunch_SOURCE_DIR}/crnlib/crn_dynamic_string.cpp + ${crunch_SOURCE_DIR}/crnlib/crn_etc.cpp + ${crunch_SOURCE_DIR}/crnlib/crn_file_utils.cpp + ${crunch_SOURCE_DIR}/crnlib/crn_find_files.cpp + ${crunch_SOURCE_DIR}/crnlib/crn_hash.cpp + ${crunch_SOURCE_DIR}/crnlib/crn_hash_map.cpp + ${crunch_SOURCE_DIR}/crnlib/crn_huffman_codes.cpp + ${crunch_SOURCE_DIR}/crnlib/crn_image_utils.cpp + ${crunch_SOURCE_DIR}/crnlib/crn_jpgd.cpp + ${crunch_SOURCE_DIR}/crnlib/crn_jpge.cpp + ${crunch_SOURCE_DIR}/crnlib/crn_ktx_texture.cpp + ${crunch_SOURCE_DIR}/crnlib/crn_lzma_codec.cpp + ${crunch_SOURCE_DIR}/crnlib/crn_math.cpp + ${crunch_SOURCE_DIR}/crnlib/crn_mem.cpp + ${crunch_SOURCE_DIR}/crnlib/crn_miniz.cpp + ${crunch_SOURCE_DIR}/crnlib/crn_mipmapped_texture.cpp + ${crunch_SOURCE_DIR}/crnlib/crn_pixel_format.cpp + ${crunch_SOURCE_DIR}/crnlib/crn_platform.cpp + ${crunch_SOURCE_DIR}/crnlib/crn_prefix_coding.cpp + ${crunch_SOURCE_DIR}/crnlib/crn_qdxt1.cpp + ${crunch_SOURCE_DIR}/crnlib/crn_qdxt5.cpp + ${crunch_SOURCE_DIR}/crnlib/crn_rand.cpp + ${crunch_SOURCE_DIR}/crnlib/crn_resample_filters.cpp + ${crunch_SOURCE_DIR}/crnlib/crn_resampler.cpp + ${crunch_SOURCE_DIR}/crnlib/crn_rg_etc1.cpp + ${crunch_SOURCE_DIR}/crnlib/crn_ryg_dxt.cpp + ${crunch_SOURCE_DIR}/crnlib/crn_sparse_bit_array.cpp + ${crunch_SOURCE_DIR}/crnlib/crn_stb_image.cpp + ${crunch_SOURCE_DIR}/crnlib/crn_strutils.cpp + ${crunch_SOURCE_DIR}/crnlib/crn_symbol_codec.cpp + ${crunch_SOURCE_DIR}/crnlib/crn_texture_comp.cpp + ${crunch_SOURCE_DIR}/crnlib/crn_texture_conversion.cpp + ${crunch_SOURCE_DIR}/crnlib/crn_texture_file_types.cpp + ${crunch_SOURCE_DIR}/crnlib/crn_threaded_resampler.cpp + ${crunch_SOURCE_DIR}/crnlib/crn_threading_pthreads.cpp + $<$:${crunch_SOURCE_DIR}/crnlib/crn_threading_win32.cpp> + ${crunch_SOURCE_DIR}/crnlib/crn_timer.cpp + ${crunch_SOURCE_DIR}/crnlib/crn_utils.cpp + ${crunch_SOURCE_DIR}/crnlib/crn_value.cpp + ${crunch_SOURCE_DIR}/crnlib/crn_vector.cpp + ${crunch_SOURCE_DIR}/crnlib/crn_zeng.cpp + ${crunch_SOURCE_DIR}/crnlib/crnlib.cpp + ${crunch_SOURCE_DIR}/crnlib/lzma_7zBuf.cpp + ${crunch_SOURCE_DIR}/crnlib/lzma_7zBuf2.cpp + ${crunch_SOURCE_DIR}/crnlib/lzma_7zCrc.cpp + ${crunch_SOURCE_DIR}/crnlib/lzma_7zFile.cpp + ${crunch_SOURCE_DIR}/crnlib/lzma_7zStream.cpp + ${crunch_SOURCE_DIR}/crnlib/lzma_Alloc.cpp + ${crunch_SOURCE_DIR}/crnlib/lzma_Bcj2.cpp + ${crunch_SOURCE_DIR}/crnlib/lzma_Bra.cpp + ${crunch_SOURCE_DIR}/crnlib/lzma_Bra86.cpp + ${crunch_SOURCE_DIR}/crnlib/lzma_BraIA64.cpp + ${crunch_SOURCE_DIR}/crnlib/lzma_LzFind.cpp + $<$:${crunch_SOURCE_DIR}/crnlib/lzma_LzFindMt.cpp> + ${crunch_SOURCE_DIR}/crnlib/lzma_LzmaDec.cpp + ${crunch_SOURCE_DIR}/crnlib/lzma_LzmaEnc.cpp + ${crunch_SOURCE_DIR}/crnlib/lzma_LzmaLib.cpp + $<$:${crunch_SOURCE_DIR}/crnlib/lzma_Threads.cpp> +) + +add_library(crnlib STATIC ${CRNLIB_SOURCES}) +target_include_directories(crnlib + PUBLIC + $ +)