From ccb88fd322415f51513fa07ef72ee1ec05668d87 Mon Sep 17 00:00:00 2001 From: Alexander Pavlov Date: Tue, 26 Dec 2023 13:20:57 +0300 Subject: [PATCH] Adding the TEXConv utility. The TEXConv utility converts normal textures into TGA images. --- .github/workflows/cibuild.yml | 4 +- CHANGELOG.md | 6 +- README.md | 1 + SamTFE/Sources/CMakeLists.txt | 39 ++ SamTFE/Sources/SamTFE.sln | 17 + SamTFE/Sources/TEXConv/TEXConv.cpp | 340 ++++++++++++++++++ SamTFE/Sources/TEXConv/TEXConv.vcxproj | 310 ++++++++++++++++ .../Sources/TEXConv/TEXConv.vcxproj.filters | 22 ++ SamTFE/Sources/TEXConv/TEXConv.vcxproj.user | 3 + SamTSE/Sources/CMakeLists.txt | 39 ++ SamTSE/Sources/SamTSE.sln | 17 + SamTSE/Sources/TEXConv/TEXConv.cpp | 340 ++++++++++++++++++ SamTSE/Sources/TEXConv/TEXConv.vcxproj | 310 ++++++++++++++++ .../Sources/TEXConv/TEXConv.vcxproj.filters | 22 ++ SamTSE/Sources/TEXConv/TEXConv.vcxproj.user | 3 + 15 files changed, 1470 insertions(+), 3 deletions(-) mode change 100755 => 100644 SamTFE/Sources/SamTFE.sln create mode 100644 SamTFE/Sources/TEXConv/TEXConv.cpp create mode 100644 SamTFE/Sources/TEXConv/TEXConv.vcxproj create mode 100644 SamTFE/Sources/TEXConv/TEXConv.vcxproj.filters create mode 100644 SamTFE/Sources/TEXConv/TEXConv.vcxproj.user mode change 100755 => 100644 SamTSE/Sources/SamTSE.sln create mode 100644 SamTSE/Sources/TEXConv/TEXConv.cpp create mode 100644 SamTSE/Sources/TEXConv/TEXConv.vcxproj create mode 100644 SamTSE/Sources/TEXConv/TEXConv.vcxproj.filters create mode 100644 SamTSE/Sources/TEXConv/TEXConv.vcxproj.user diff --git a/.github/workflows/cibuild.yml b/.github/workflows/cibuild.yml index be68e124..c4fb1f85 100644 --- a/.github/workflows/cibuild.yml +++ b/.github/workflows/cibuild.yml @@ -542,11 +542,11 @@ jobs: echo "*** Prepare Archive ***" cd ${{github.workspace}} cp -vfr SamTFE/Sources/build-x64/Debug/*.dylib x64/SamTFE/Bin - cp -vfr SamTFE/Sources/build-x64/{DedicatedServer,MakeFONT,SeriousSam} x64/SamTFE/Bin + cp -vfr SamTFE/Sources/build-x64/{DedicatedServer,TEXConv,MakeFONT,SeriousSam} x64/SamTFE/Bin cp -vfr SamTFE/Sources/build-x64-xplus/Debug/libEntities.dylib x64/SamTFE/Mods/XPLUS/Bin cp -vfr SamTFE/Sources/build-x64-xplus/Debug/libGame.dylib x64/SamTFE/Mods/XPLUS/Bin cp -vfr SamTSE/Sources/build-x64/Debug/*.dylib x64/SamTSE/Bin - cp -vfr SamTSE/Sources/build-x64/{DedicatedServer,MakeFONT,SeriousSam} x64/SamTSE/Bin + cp -vfr SamTSE/Sources/build-x64/{DedicatedServer,TEXConv,MakeFONT,SeriousSam} x64/SamTSE/Bin cp -vfr SamTSE/Sources/build-x64-xplus/Debug/libEntitiesMP.dylib x64/SamTSE/Mods/XPLUS/Bin cp -vfr SamTSE/Sources/build-x64-xplus/Debug/libGameMP.dylib x64/SamTSE/Mods/XPLUS/Bin cp -vfr {SamTFE/SE1_10b.gro,SamTFE/ModEXT.txt} x64/SamTFE diff --git a/CHANGELOG.md b/CHANGELOG.md index 658948f2..0355623a 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -216,5 +216,9 @@ All notable changes to this project will be documented in this file. - Added man pages for.for FreeBSD and OpenBSD. - Added searching library libvorbisfile for BSD platforms. -## 2023-12-01 - 2023-12-02 +## 2023-12-01 - 2023-12-26 - Add building portable version for x86 and amd64 without asm code. +- Fixed creation of textures from TGA images in the Modeler and Editor. +- Added man pages Man pages for Gentoo. +- Fixed broken water and fire effects for textures. They were broken when ported to Linux in 2016. +- Adding the TEXConv utility that converts normal textures into TGA images. diff --git a/README.md b/README.md index 9c810aae..5f707bcf 100644 --- a/README.md +++ b/README.md @@ -38,6 +38,7 @@ This is the source code for Serious Engine v.1.10, including the following proje * `Depend` Used to build a list of dependency files based on a list of root files * `LWSkaExporter` Exporter for use in LightWave * `MakeFONT` Used for generating *.fnt files +* `TexConv` Used for converting *.tex files to *.tga images * `Shaders` Compiled shaders * `GameAgent` The serverlist masterserver written in Python * `libogg`, `libvorbis` Third party libraries used for playing OGG-encoded ingame music (see http://www.vorbis.com/ for more information) diff --git a/SamTFE/Sources/CMakeLists.txt b/SamTFE/Sources/CMakeLists.txt index e455792d..6cb18dca 100644 --- a/SamTFE/Sources/CMakeLists.txt +++ b/SamTFE/Sources/CMakeLists.txt @@ -1562,6 +1562,15 @@ if(BUILD_MAKEFONT) set_target_properties(MakeFONT${MP} PROPERTIES ENABLE_EXPORTS ON) endif() +option(BUILD_TEXConv "Compile the TEXConv, too" TRUE) +if(BUILD_TEXConv) + add_executable(TEXConv${MP} TEXConv/TEXConv.cpp) + target_link_libraries(TEXConv${MP} ${ENGINELIB}) + add_dependencies(TEXConv${MP} ParseEntities${MP}) + # Make symbols in the main executable available to dynamic objects + set_target_properties(TEXConv${MP} PROPERTIES ENABLE_EXPORTS ON) +endif() + option(BUILD_AMP11LIB "Compile the AMP11LIB, too" TRUE) if(BUILD_AMP11LIB) add_definitions(-DFASTBITS) @@ -1634,6 +1643,14 @@ if(LINUX) target_link_libraries(MakeFONT${MP} ${SDL2_LIBRARY}) target_link_libraries(MakeFONT${MP} ${ZLIB_LIBRARIES}) endif() + if(BUILD_TEXConv) + set_target_properties(TEXConv${MP} PROPERTIES LINK_FLAGS "-Wl,${RPATH_SETTINGS}") + target_link_libraries(TEXConv${MP} "m") + target_link_libraries(TEXConv${MP} "dl") + target_link_libraries(TEXConv${MP} "pthread") + target_link_libraries(TEXConv${MP} ${SDL2_LIBRARY}) + target_link_libraries(TEXConv${MP} ${ZLIB_LIBRARIES}) + endif() endif() if(FREEBSD) @@ -1656,12 +1673,14 @@ if(LOCAL_INSTALL) set_target_properties(SeriousSam${MP} PROPERTIES OUTPUT_NAME "SeriousSam") set_target_properties(DedicatedServer${MP} PROPERTIES OUTPUT_NAME "DedicatedServer") set_target_properties(MakeFONT${MP} PROPERTIES OUTPUT_NAME "MakeFONT") + set_target_properties(TEXConv${MP} PROPERTIES OUTPUT_NAME "TEXConv") set_target_properties(amp11lib${MP} PROPERTIES OUTPUT_NAME "amp11lib${DEBUGSUFFIX}") set_target_properties(${SHADERSLIBSE} PROPERTIES OUTPUT_NAME "Shaders${DEBUGSUFFIX}") else() set_target_properties(SeriousSam${MP} PROPERTIES OUTPUT_NAME "${INTERNAL_NAME}") set_target_properties(DedicatedServer${MP} PROPERTIES OUTPUT_NAME "${INTERNAL_NAME}-ded") set_target_properties(MakeFONT${MP} PROPERTIES OUTPUT_NAME "${INTERNAL_NAME}-mkfont") + set_target_properties(TEXConv${MP} PROPERTIES OUTPUT_NAME "${INTERNAL_NAME}-texconv") set_target_properties(amp11lib${MP} PROPERTIES OUTPUT_NAME "amp11lib") set_target_properties(${SHADERSLIB} PROPERTIES OUTPUT_NAME "Shaders") endif() @@ -1687,6 +1706,11 @@ if(DEBUG) # RAKE! Will this work with TFE? RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}/Bin" PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_WRITE GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) endif() + if(BUILD_TEXConv) + install(TARGETS TEXConv${MP} + RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}/Bin" + PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_WRITE GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) + endif() if(BUILD_AMP11LIB) install(TARGETS amp11lib${MP} LIBRARY DESTINATION "${CMAKE_INSTALL_PREFIX}/Bin/Debug" @@ -1707,6 +1731,11 @@ else() RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}/Bin" PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_WRITE GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) endif() + if(BUILD_TEXConv) + install(TARGETS TEXConv${MP} + RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}/Bin" + PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_WRITE GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) + endif() if(BUILD_AMP11LIB) install(TARGETS amp11lib${MP} LIBRARY DESTINATION "${CMAKE_INSTALL_PREFIX}/Bin" @@ -1734,6 +1763,11 @@ if(DEBUG) # RAKE! Will this work with TFE? RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}/Bin" PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_WRITE GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) endif() + if(BUILD_TEXConv) + install(TARGETS TEXConv${MP} + RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}/Bin" + PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_WRITE GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) + endif() if(BUILD_AMP11LIB) install(TARGETS amp11lib${MP} LIBRARY DESTINATION "${CMAKE_INSTALL_PREFIX}/Bin/Debug" @@ -1757,6 +1791,11 @@ else() RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}/bin" PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_WRITE GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) endif() + if(BUILD_TEXConv) + install(TARGETS TEXConv${MP} + RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}/bin" + PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_WRITE GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) + endif() if(BUILD_AMP11LIB) install(TARGETS amp11lib${MP} LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}/${INTERNAL_NAME}" diff --git a/SamTFE/Sources/SamTFE.sln b/SamTFE/Sources/SamTFE.sln old mode 100755 new mode 100644 index 4a206677..18da430f --- a/SamTFE/Sources/SamTFE.sln +++ b/SamTFE/Sources/SamTFE.sln @@ -103,6 +103,11 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SeriousSam", "SeriousSam\Se EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "amp11lib", "amp11lib\amp11lib.vcxproj", "{813C514A-80C7-462F-A7FB-2ED105A0789A}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TEXConv", "TEXConv\TEXConv.vcxproj", "{8DABA89A-52A2-4620-A135-63D0830630ED}" + ProjectSection(ProjectDependencies) = postProject + {4B6F587C-7C59-4481-FBB9-CA44380D0CBF} = {4B6F587C-7C59-4481-FBB9-CA44380D0CBF} + EndProjectSection +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 @@ -365,6 +370,18 @@ Global {813C514A-80C7-462F-A7FB-2ED105A0789A}.Template|Win32.Build.0 = Release|Win32 {813C514A-80C7-462F-A7FB-2ED105A0789A}.Template|x64.ActiveCfg = Release|x64 {813C514A-80C7-462F-A7FB-2ED105A0789A}.Template|x64.Build.0 = Release|x64 + {8DABA89A-52A2-4620-A135-63D0830630ED}.Debug|Win32.ActiveCfg = Debug|Win32 + {8DABA89A-52A2-4620-A135-63D0830630ED}.Debug|Win32.Build.0 = Debug|Win32 + {8DABA89A-52A2-4620-A135-63D0830630ED}.Debug|x64.ActiveCfg = Debug|x64 + {8DABA89A-52A2-4620-A135-63D0830630ED}.Debug|x64.Build.0 = Debug|x64 + {8DABA89A-52A2-4620-A135-63D0830630ED}.Release|Win32.ActiveCfg = Release|Win32 + {8DABA89A-52A2-4620-A135-63D0830630ED}.Release|Win32.Build.0 = Release|Win32 + {8DABA89A-52A2-4620-A135-63D0830630ED}.Release|x64.ActiveCfg = Release|x64 + {8DABA89A-52A2-4620-A135-63D0830630ED}.Release|x64.Build.0 = Release|x64 + {8DABA89A-52A2-4620-A135-63D0830630ED}.Template|Win32.ActiveCfg = Template|Win32 + {8DABA89A-52A2-4620-A135-63D0830630ED}.Template|Win32.Build.0 = Template|Win32 + {8DABA89A-52A2-4620-A135-63D0830630ED}.Template|x64.ActiveCfg = Template|x64 + {8DABA89A-52A2-4620-A135-63D0830630ED}.Template|x64.Build.0 = Template|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/SamTFE/Sources/TEXConv/TEXConv.cpp b/SamTFE/Sources/TEXConv/TEXConv.cpp new file mode 100644 index 00000000..671c5d32 --- /dev/null +++ b/SamTFE/Sources/TEXConv/TEXConv.cpp @@ -0,0 +1,340 @@ +/* Copyright (c) 2023 Alexander Pavlov + +This program is free software; you can redistribute it and/or modify +it under the terms of version 2 of the GNU General Public License as published by +the Free Software Foundation + + +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, write to the Free Software Foundation, Inc., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ + + +// TEXConv - Converter normal texture to TGA format. + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +// Not used; dummy declaration only needed by +// Engine/Base/ErrorReporting.o +HWND _hwndMain = NULL; + +#ifdef PLATFORM_UNIX +// retrives memory offset of a specified mip-map or a size of all mip-maps (IN PIXELS!) +// (zero offset means first, i.e. largest mip-map) +extern PIX GetMipmapOffset(INDEX iMipLevel, PIX pixWidth, PIX pixHeight); +// adds 8-bit opaque alpha channel to 24-bit bitmap (in place supported) +extern void AddAlphaChannel(UBYTE *pubSrcBitmap, ULONG *pulDstBitmap, PIX pixSize, UBYTE *pubAlphaBitmap); +// removes 8-bit alpha channel from 32-bit bitmap (in place supported) +extern void RemoveAlphaChannel(ULONG *pulSrcBitmap, UBYTE *pubDstBitmap, PIX pixSize); +#else +// retrives memory offset of a specified mip-map or a size of all mip-maps (IN PIXELS!) +// (zero offset means first, i.e. largest mip-map) +static PIX GetMipmapOffset(INDEX iMipLevel, PIX pixWidth, PIX pixHeight) +{ + PIX pixTexSize = 0; + PIX pixMipSize = pixWidth*pixHeight; + INDEX iMips = GetNoOfMipmaps(pixWidth, pixHeight); + iMips = Min(iMips, iMipLevel); + while (iMips>0) { + pixTexSize += pixMipSize; + pixMipSize >>= 2; + iMips--; + } + return pixTexSize; +} + +// adds 8-bit opaque alpha channel to 24-bit bitmap (in place supported) +static void AddAlphaChannel(UBYTE *pubSrcBitmap, ULONG *pulDstBitmap, PIX pixSize, UBYTE *pubAlphaBitmap) +{ + UBYTE ubR, ubG, ubB, ubA = 255; + // loop backwards thru all bitmap pixels + for (INDEX iPix = (pixSize - 1); iPix >= 0; iPix--) { + ubR = pubSrcBitmap[iPix * 3 + 0]; + ubG = pubSrcBitmap[iPix * 3 + 1]; + ubB = pubSrcBitmap[iPix * 3 + 2]; + if (pubAlphaBitmap != NULL) ubA = pubAlphaBitmap[iPix]; + else ubA = 255; // for the sake of forced RGBA internal formats! + pulDstBitmap[iPix] = ByteSwap(RGBAToColor(ubR, ubG, ubB, ubA)); + } +} + +// removes 8-bit alpha channel from 32-bit bitmap (in place supported) +static void RemoveAlphaChannel(ULONG *pulSrcBitmap, UBYTE *pubDstBitmap, PIX pixSize) +{ + UBYTE ubR, ubG, ubB; + // loop thru all bitmap pixels + for (INDEX iPix = 0; iPixtd_ptegEffect != NULL) return; + + // determine dimensions + PIX pixWidth = pTD->GetPixWidth(); + PIX pixHeight = pTD->GetPixHeight(); + PIX pixMipSize = pixWidth * pixHeight; + PIX pixFrameSize = GetMipmapOffset( 15, pixWidth, pixHeight); + // allocate memory for new texture + ULONG *pulFramesNew = (ULONG*)AllocMemory( pixFrameSize*pTD->td_ctFrames *BYTES_PER_TEXEL); + UWORD *puwFramesOld = (UWORD*)pTD->td_pulFrames; + ASSERT( puwFramesOld!=NULL); + + // determine alpha channel presence + BOOL bHasAlphaChannel = pTD->td_ulFlags & TEX_ALPHACHANNEL; + + // unpack texture from 16-bit RGBA4444 or RGBA5551 format to RGBA8888 32-bit format + UBYTE r,g,b,a; + // for each frame + for( INDEX iFr=0; iFrtd_ctFrames; iFr++) + { // get addresses of current frames (new and old) + PIX pixFrameOffset = iFr * pixFrameSize; + // for each pixel + for( INDEX iPix=0; iPix>8; + g = (uwPix & 0x0F00) >>4; + b = (uwPix & 0x00F0) >>0; + a = (uwPix & 0x000F) <<4; + // adjust strength + r |= r>>4; g |= g>>4; b |= b>>4; a |= a>>4; + } else { + // without alpha channel + r = (uwPix & 0xF800) >>8; + g = (uwPix & 0x07C0) >>3; + b = (uwPix & 0x003E) <<2; + a = 0xFF; + // adjust strength + r |= r>>5; g |= g>>5; b |= b>>5; + } + + // pack it back to 32-bit + ULONG ulPix = RGBAToColor(r,g,b,a); + // store 32-bit pixel + pulFramesNew[pixFrameOffset+iPix] = ByteSwap(ulPix); + } + } + + // free old memory + FreeMemory( pTD->td_pulFrames); + // remember new texture parameters + pTD->td_pulFrames = pulFramesNew; + pTD->td_slFrameSize = pixFrameSize *BYTES_PER_TEXEL; +} + +void SubMain( int argc, char *argv[]) +{ + printf("\nTEXConv - Converter normal texture to TGA format (1.00)\n"); + printf( " (C)2023 Alexander Pavlov \n\n"); + // 2 parameters are allowed as input + if( (argc<2) || (argc>3)) + { + printf( "USAGE: TEXConv [] "); + printf( "\n"); + printf( "\n"); + printf( "texture_file: path to texture file\n"); + printf( "tga_output_file: path to create tga file\n"); + printf( "\n"); + printf( "NOTES: - out file will have the name as texture file, but \".tga\" extension\n"); + printf( "The texture file must be in the game directory. In the root or any subdirectory\n"); + exit(EXIT_FAILURE); + } + + // initialize engine +#ifdef PLATFORM_UNIX + SE_InitEngine("",""); +#else + SE_InitEngine(""); +#endif + // first input parameter is texture name + CTFileName fnTexture = CTString(argv[1]); + if(!FileExists(fnTexture)) { + printf( "Error: You specified an incorrect file name\n"); + exit(EXIT_FAILURE); + } + + // output tga file + CTFileName fnOrderFile = fnTexture.NoExt()+".tga"; + // parameter 2 specifies tga output file + if( argc>2 ) { + fnOrderFile = CTString(argv[2]); + } + + // the creation of the tga image begins + CTextureData *pTD = new CTextureData; + CTFileStream TEXFile; + SLONG slFileSize; + + // determine file size + TEXFile.Open_t( fnTexture, CTStream::OM_READ); + slFileSize = TEXFile.GetStreamSize(); + printf("Open texture file: %s (bytes:%d)\n",(const char *) TEXFile.GetDescription(),slFileSize); + + // read version + INDEX iVersion; + TEXFile.ExpectID_t( "TVER"); + TEXFile >> iVersion; + printf("Texture version: %d\n",iVersion); + + // check currently supported versions + if( iVersion!=4 && iVersion!=3) throw( TRANSV("Error: Invalid texture format version.")); + + // mark if this texture was loaded form the old format + if( iVersion==3) pTD->td_ulFlags |= TEX_WASOLD; + BOOL bAlphaChannel = FALSE; + + // loop trough file and react according to chunk ID + do + { + // obtain chunk id + CChunkID idChunk = TEXFile.GetID_t(); + if( idChunk == CChunkID(" ")) { + // we should stop reading when an invalid chunk has been encountered + break; + } + + // if this is chunk containing texture data + if( idChunk == CChunkID("TDAT")) + { + printf("CChunkID: TDAT\n"); + // read data describing texture + ULONG ulFlags=0; + INDEX ctMipLevels; + TEXFile >> ulFlags; + TEXFile >> pTD->td_mexWidth; + TEXFile >> pTD->td_mexHeight; + TEXFile >> pTD->td_ctFineMipLevels; + if( iVersion!=4) TEXFile >> ctMipLevels; + TEXFile >> pTD->td_iFirstMipLevel; + if( iVersion!=4) TEXFile >> pTD->td_slFrameSize; + TEXFile >> pTD->td_ctFrames; + // combine flags + pTD->td_ulFlags |= ulFlags; + bAlphaChannel = pTD->td_ulFlags&TEX_ALPHACHANNEL; + // determine frame size + if( iVersion==4) pTD->td_slFrameSize = GetMipmapOffset( 15, pTD->GetPixWidth(), pTD->GetPixHeight()) + * BYTES_PER_TEXEL; + } // TDAT + + // if this is chunk containing raw frames + else if( idChunk == CChunkID("FRMS")) + { + printf("CChunkID: FRMS\n"); + // calculate texture size for corresponding texture format and allocate memory + SLONG slTexSize = pTD->td_slFrameSize * pTD->td_ctFrames; + pTD->td_pulFrames = (ULONG*)AllocMemory( slTexSize); + // if older version + if( iVersion==3) { + // alloc memory block and read mip-maps + TEXFile.Read_t( pTD->td_pulFrames, slTexSize); + #if PLATFORM_BIGENDIAN + for (SLONG i = 0; i < slTexSize/4; i++) + BYTESWAP(pTD->td_pulFrames[i]); + #endif + } + // if current version + else { + PIX pixFrameSizeOnDisk = pTD->GetPixWidth()*pTD->GetPixHeight(); + for( INDEX iFr=0; iFrtd_ctFrames; iFr++) + { // loop thru frames + ULONG *pulCurrentFrame = pTD->td_pulFrames + (iFr * pTD->td_slFrameSize/BYTES_PER_TEXEL); + if( bAlphaChannel) { + // read texture with alpha channel from file + TEXFile.Read_t( pulCurrentFrame, pixFrameSizeOnDisk *4); + #if PLATFORM_BIGENDIAN + for (SLONG i = 0; i < pixFrameSizeOnDisk; i++) + BYTESWAP(pulCurrentFrame[i]); + #endif + } else { + // read texture without alpha channel from file + TEXFile.Read_t( pulCurrentFrame, pixFrameSizeOnDisk *3); + // add opaque alpha channel + AddAlphaChannel( (UBYTE*)pulCurrentFrame, pulCurrentFrame, pixFrameSizeOnDisk); + } + } + } + } // FRMS + } + // until we didn't reach end of file + while( !TEXFile.AtEOF()); + + // if texture is in old format, convert it to current format + if( iVersion==3) Convert(pTD); + printf("Width: %d Height: %d\n", pTD->GetPixHeight(), pTD->GetPixWidth()); + + // Croteam internal image format + CImageInfo ii; + // needs only first frame + INDEX iFrame = 0; + // prepare miplevel and mipmap offset + PIX pixWidth = pTD->GetPixWidth(); + PIX pixHeight = pTD->GetPixHeight(); + // export header to image info structure + ii.Clear(); + ii.ii_Width = pixWidth; + ii.ii_Height = pixHeight; + ii.ii_BitsPerPixel = (pTD->td_ulFlags&TEX_ALPHACHANNEL) ? 32 : 24; + + // prepare the texture for exporting (with or without alpha channel) + ULONG *pulFrame = (ULONG*)pTD->td_pulFrames + pTD->td_slFrameSize*iFrame/BYTES_PER_TEXEL; + PIX pixMipSize = pixWidth*pixHeight; + SLONG slMipSize = pixMipSize * ii.ii_BitsPerPixel/8; + ii.ii_Picture = (UBYTE*)AllocMemory( slMipSize); + + // export frame + if( pTD->td_ulFlags&TEX_ALPHACHANNEL) { + memcpy( ii.ii_Picture, pulFrame, slMipSize); + } else { + RemoveAlphaChannel( pulFrame, ii.ii_Picture, pixMipSize); + } + + // save tga + ii.SaveTGA_t(fnOrderFile); + ii.Clear(); + printf("Create %s image success.\n", (const char *) fnOrderFile); + exit( EXIT_SUCCESS); +} + + +// ---------------- Main ---------------- +int main( int argc, char *argv[]) +{ + CTSTREAM_BEGIN + { + SubMain(argc, argv); + } + CTSTREAM_END; + #ifdef PLATFORM_UNIX + getchar(); + #else + getch(); + #endif + return 0; +} diff --git a/SamTFE/Sources/TEXConv/TEXConv.vcxproj b/SamTFE/Sources/TEXConv/TEXConv.vcxproj new file mode 100644 index 00000000..23a1c207 --- /dev/null +++ b/SamTFE/Sources/TEXConv/TEXConv.vcxproj @@ -0,0 +1,310 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + Template + Win32 + + + Template + x64 + + + + + + + + MFCProj + {8DABA89A-52A2-4620-A135-63D0830630ED} + 10.0.14393.0 + + + + Application + v140 + Unicode + + + Application + v140 + Unicode + + + Application + Dynamic + Unicode + v140 + + + Application + Dynamic + Unicode + v140 + + + Application + false + Unicode + v140 + + + Application + false + Unicode + v140 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Release\ + Release\ + false + $(SolutionDir);$(SolutionDir)..\Tools.Win32\Libraries\DX8SDK\Include;$(IncludePath) + $(SolutionDir)..\Bin;$(SolutionDir)..\Tools.Win32\Libraries\DX8SDK\Lib;$(LibraryPath) + + + false + $(SolutionDir);$(SolutionDir)..\Tools.Win32\Libraries\DX8SDK\Include;$(IncludePath) + $(SolutionDir)..\Bin;$(SolutionDir)..\Tools.Win32\Libraries\DX8SDK\Lib;$(LibraryPath) + Release\ + Release\ + + + Debug\ + Debug\ + false + $(SolutionDir);$(SolutionDir)..\Tools.Win32\Libraries\DX8SDK\Include;$(IncludePath) + $(SolutionDir)..\Bin\Debug;$(SolutionDir)..\Tools.Win32\Libraries\DX8SDK\Lib;$(LibraryPath) + + + false + $(SolutionDir);$(SolutionDir)..\Tools.Win32\Libraries\DX8SDK\Include;$(IncludePath) + $(SolutionDir)..\Bin\Debug;$(SolutionDir)..\Tools.Win32\Libraries\DX8SDK\Lib;$(LibraryPath) + Debug\ + Debug\ + + + + MultiThreadedDLL + OnlyExplicitInline + false + MaxSpeed + true + Level3 + Speed + true + false + true + WIN32;NDEBUG;_CONSOLE;DIRECT3D_VERSION=0x0800;%(PreprocessorDefinitions) + .\Release\ + .\Release\TEXConv.pch + .\Release\ + .\Release\ + 4996;4333 + + + + + .\Release\TEXConv.tlb + + + 0x0409 + NDEBUG;%(PreprocessorDefinitions) + + + true + .\Release\TEXConv.bsc + + + true + true + Console + .\Release\TEXConv.exe + true + + + copy Release\$(TargetName).exe $(SolutionDir)..\Bin\ >nul +copy Release\$(TargetName).map $(SolutionDir)..\Bin\ >nul + Copying %(Filename) binaries to $(ENGINE_DIR)\Bin\Debug + $(SolutionDir)..\Bin\$(TargetName).exe;%(Outputs) + + + + + MultiThreadedDLL + OnlyExplicitInline + false + MaxSpeed + true + Level3 + Speed + true + false + true + WIN32;NDEBUG;_CONSOLE;DIRECT3D_VERSION=0x0800;%(PreprocessorDefinitions) + .\Release\ + .\Release\TEXConv.pch + .\Release\ + .\Release\ + 4996;4333 + + + + + .\Release\TEXConv.tlb + + + 0x0409 + NDEBUG;%(PreprocessorDefinitions) + + + true + .\Release\TEXConv.bsc + + + true + true + Console + .\Release\TEXConv.exe + true + + + copy Release\$(TargetName).exe $(SolutionDir)..\Bin\ >nul +copy Release\$(TargetName).map $(SolutionDir)..\Bin\ >nul + Copying %(Filename) binaries to $(ENGINE_DIR)\Bin\Debug + $(SolutionDir)..\Bin\$(TargetName).exe;%(Outputs) + + + + + MultiThreadedDebugDLL + Default + false + Disabled + true + Level3 + true + WIN32;_DEBUG;_CONSOLE;DIRECT3D_VERSION=0x0800;%(PreprocessorDefinitions) + Debug\ + .\Debug\TEXConv.pch + Debug\ + Debug\ + 4996;4333 + + + + + .\Debug\TEXConv.tlb + + + 0x0409 + _DEBUG;%(PreprocessorDefinitions) + + + true + .\Debug\TEXConv.bsc + + + true + true + Console + Debug\TEXConv.exe + true + + + copy Debug\$(TargetName).exe $(SolutionDir)..\Bin\Debug\ >nul +copy Debug\$(TargetName).map $(SolutionDir)..\Bin\Debug\ >nul + Copying %(Filename) binaries to $(ENGINE_DIR)\Bin\Debug + $(SolutionDir)..\Bin\Debug\$(TargetName).exe;%(Outputs) + + + + + MultiThreadedDebugDLL + Default + false + Disabled + true + Level3 + WIN32;_DEBUG;_CONSOLE;DIRECT3D_VERSION=0x0800;%(PreprocessorDefinitions) + Debug\ + .\Debug\TEXConv.pch + Debug\ + Debug\ + 4996;4333 + + + + + .\Debug\TEXConv.tlb + + + 0x0409 + _DEBUG;%(PreprocessorDefinitions) + + + true + .\Debug\TEXConv.bsc + + + true + true + Console + Debug\TEXConv.exe + true + + + copy Debug\$(TargetName).exe $(SolutionDir)..\Bin\Debug\ >nul +copy Debug\$(TargetName).map $(SolutionDir)..\Bin\Debug\ >nul + Copying %(Filename) binaries to $(ENGINE_DIR)\Bin\Debug + $(SolutionDir)..\Bin\Debug\$(TargetName).exe;%(Outputs) + + + + + + + + + \ No newline at end of file diff --git a/SamTFE/Sources/TEXConv/TEXConv.vcxproj.filters b/SamTFE/Sources/TEXConv/TEXConv.vcxproj.filters new file mode 100644 index 00000000..0e59b281 --- /dev/null +++ b/SamTFE/Sources/TEXConv/TEXConv.vcxproj.filters @@ -0,0 +1,22 @@ + + + + + {0020fbb2-e50f-49f1-b4bc-17cc8c0c186a} + cpp;c;cxx;rc;def;r;odl;hpj;bat;for;f90 + + + {24e0bef6-bc2a-407e-83b9-786e62b24e82} + h;hpp;hxx;hm;inl;fi;fd + + + {91274eac-444b-46e6-9d11-beaf0fa96d2d} + ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe + + + + + Source Files + + + diff --git a/SamTFE/Sources/TEXConv/TEXConv.vcxproj.user b/SamTFE/Sources/TEXConv/TEXConv.vcxproj.user new file mode 100644 index 00000000..695b5c78 --- /dev/null +++ b/SamTFE/Sources/TEXConv/TEXConv.vcxproj.user @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/SamTSE/Sources/CMakeLists.txt b/SamTSE/Sources/CMakeLists.txt index c003231b..a0b2ea91 100644 --- a/SamTSE/Sources/CMakeLists.txt +++ b/SamTSE/Sources/CMakeLists.txt @@ -1562,6 +1562,15 @@ if(BUILD_MAKEFONT) set_target_properties(MakeFONT${MP} PROPERTIES ENABLE_EXPORTS ON) endif() +option(BUILD_TEXConv "Compile the TEXConv, too" TRUE) +if(BUILD_TEXConv) + add_executable(TEXConv${MP} TEXConv/TEXConv.cpp) + target_link_libraries(TEXConv${MP} ${ENGINELIB}) + add_dependencies(TEXConv${MP} ParseEntities${MP}) + # Make symbols in the main executable available to dynamic objects + set_target_properties(TEXConv${MP} PROPERTIES ENABLE_EXPORTS ON) +endif() + option(BUILD_AMP11LIB "Compile the AMP11LIB, too" TRUE) if(BUILD_AMP11LIB) add_definitions(-DFASTBITS) @@ -1634,6 +1643,14 @@ if(LINUX) target_link_libraries(MakeFONT${MP} ${SDL2_LIBRARY}) target_link_libraries(MakeFONT${MP} ${ZLIB_LIBRARIES}) endif() + if(BUILD_TEXConv) + set_target_properties(TEXConv${MP} PROPERTIES LINK_FLAGS "-Wl,${RPATH_SETTINGS}") + target_link_libraries(TEXConv${MP} "m") + target_link_libraries(TEXConv${MP} "dl") + target_link_libraries(TEXConv${MP} "pthread") + target_link_libraries(TEXConv${MP} ${SDL2_LIBRARY}) + target_link_libraries(TEXConv${MP} ${ZLIB_LIBRARIES}) + endif() endif() if(FREEBSD) @@ -1656,12 +1673,14 @@ if(LOCAL_INSTALL) set_target_properties(SeriousSam${MP} PROPERTIES OUTPUT_NAME "SeriousSam") set_target_properties(DedicatedServer${MP} PROPERTIES OUTPUT_NAME "DedicatedServer") set_target_properties(MakeFONT${MP} PROPERTIES OUTPUT_NAME "MakeFONT") + set_target_properties(TEXConv${MP} PROPERTIES OUTPUT_NAME "TEXConv") set_target_properties(amp11lib${MP} PROPERTIES OUTPUT_NAME "amp11lib${DEBUGSUFFIX}") set_target_properties(${SHADERSLIBSE} PROPERTIES OUTPUT_NAME "Shaders${DEBUGSUFFIX}") else() set_target_properties(SeriousSam${MP} PROPERTIES OUTPUT_NAME "${INTERNAL_NAME}") set_target_properties(DedicatedServer${MP} PROPERTIES OUTPUT_NAME "${INTERNAL_NAME}-ded") set_target_properties(MakeFONT${MP} PROPERTIES OUTPUT_NAME "${INTERNAL_NAME}-mkfont") + set_target_properties(TEXConv${MP} PROPERTIES OUTPUT_NAME "${INTERNAL_NAME}-texconv") set_target_properties(amp11lib${MP} PROPERTIES OUTPUT_NAME "amp11lib") set_target_properties(${SHADERSLIB} PROPERTIES OUTPUT_NAME "Shaders") endif() @@ -1687,6 +1706,11 @@ if(DEBUG) # RAKE! Will this work with TFE? RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}/Bin" PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_WRITE GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) endif() + if(BUILD_TEXConv) + install(TARGETS TEXConv${MP} + RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}/Bin" + PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_WRITE GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) + endif() if(BUILD_AMP11LIB) install(TARGETS amp11lib${MP} LIBRARY DESTINATION "${CMAKE_INSTALL_PREFIX}/Bin/Debug" @@ -1707,6 +1731,11 @@ else() RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}/Bin" PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_WRITE GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) endif() + if(BUILD_TEXConv) + install(TARGETS TEXConv${MP} + RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}/Bin" + PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_WRITE GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) + endif() if(BUILD_AMP11LIB) install(TARGETS amp11lib${MP} LIBRARY DESTINATION "${CMAKE_INSTALL_PREFIX}/Bin" @@ -1734,6 +1763,11 @@ if(DEBUG) # RAKE! Will this work with TFE? RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}/Bin" PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_WRITE GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) endif() + if(BUILD_TEXConv) + install(TARGETS TEXConv${MP} + RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}/Bin" + PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_WRITE GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) + endif() if(BUILD_AMP11LIB) install(TARGETS amp11lib${MP} LIBRARY DESTINATION "${CMAKE_INSTALL_PREFIX}/Bin/Debug" @@ -1757,6 +1791,11 @@ else() RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}/bin" PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_WRITE GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) endif() + if(BUILD_TEXConv) + install(TARGETS TEXConv${MP} + RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}/bin" + PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_WRITE GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) + endif() if(BUILD_AMP11LIB) install(TARGETS amp11lib${MP} LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}/${INTERNAL_NAME}" diff --git a/SamTSE/Sources/SamTSE.sln b/SamTSE/Sources/SamTSE.sln old mode 100755 new mode 100644 index 7992bb9b..5ad62992 --- a/SamTSE/Sources/SamTSE.sln +++ b/SamTSE/Sources/SamTSE.sln @@ -106,6 +106,11 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "amp11lib", "amp11lib\amp11lib.vcxproj", "{813C514A-80C7-462F-A7FB-2ED105A0789A}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TEXConv", "TEXConv\TEXConv.vcxproj", "{8DABA89A-52A2-4620-A135-63D0830630ED}" + ProjectSection(ProjectDependencies) = postProject + {4B6F587C-7C59-4481-FBB9-CA44380D0CBF} = {4B6F587C-7C59-4481-FBB9-CA44380D0CBF} + EndProjectSection +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 @@ -368,6 +373,18 @@ Global {813C514A-80C7-462F-A7FB-2ED105A0789A}.Template|Win32.Build.0 = Release|Win32 {813C514A-80C7-462F-A7FB-2ED105A0789A}.Template|x64.ActiveCfg = Release|x64 {813C514A-80C7-462F-A7FB-2ED105A0789A}.Template|x64.Build.0 = Release|x64 + {8DABA89A-52A2-4620-A135-63D0830630ED}.Debug|Win32.ActiveCfg = Debug|Win32 + {8DABA89A-52A2-4620-A135-63D0830630ED}.Debug|Win32.Build.0 = Debug|Win32 + {8DABA89A-52A2-4620-A135-63D0830630ED}.Debug|x64.ActiveCfg = Debug|x64 + {8DABA89A-52A2-4620-A135-63D0830630ED}.Debug|x64.Build.0 = Debug|x64 + {8DABA89A-52A2-4620-A135-63D0830630ED}.Release|Win32.ActiveCfg = Release|Win32 + {8DABA89A-52A2-4620-A135-63D0830630ED}.Release|Win32.Build.0 = Release|Win32 + {8DABA89A-52A2-4620-A135-63D0830630ED}.Release|x64.ActiveCfg = Release|x64 + {8DABA89A-52A2-4620-A135-63D0830630ED}.Release|x64.Build.0 = Release|x64 + {8DABA89A-52A2-4620-A135-63D0830630ED}.Template|Win32.ActiveCfg = Template|Win32 + {8DABA89A-52A2-4620-A135-63D0830630ED}.Template|Win32.Build.0 = Template|Win32 + {8DABA89A-52A2-4620-A135-63D0830630ED}.Template|x64.ActiveCfg = Template|x64 + {8DABA89A-52A2-4620-A135-63D0830630ED}.Template|x64.Build.0 = Template|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/SamTSE/Sources/TEXConv/TEXConv.cpp b/SamTSE/Sources/TEXConv/TEXConv.cpp new file mode 100644 index 00000000..671c5d32 --- /dev/null +++ b/SamTSE/Sources/TEXConv/TEXConv.cpp @@ -0,0 +1,340 @@ +/* Copyright (c) 2023 Alexander Pavlov + +This program is free software; you can redistribute it and/or modify +it under the terms of version 2 of the GNU General Public License as published by +the Free Software Foundation + + +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, write to the Free Software Foundation, Inc., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ + + +// TEXConv - Converter normal texture to TGA format. + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +// Not used; dummy declaration only needed by +// Engine/Base/ErrorReporting.o +HWND _hwndMain = NULL; + +#ifdef PLATFORM_UNIX +// retrives memory offset of a specified mip-map or a size of all mip-maps (IN PIXELS!) +// (zero offset means first, i.e. largest mip-map) +extern PIX GetMipmapOffset(INDEX iMipLevel, PIX pixWidth, PIX pixHeight); +// adds 8-bit opaque alpha channel to 24-bit bitmap (in place supported) +extern void AddAlphaChannel(UBYTE *pubSrcBitmap, ULONG *pulDstBitmap, PIX pixSize, UBYTE *pubAlphaBitmap); +// removes 8-bit alpha channel from 32-bit bitmap (in place supported) +extern void RemoveAlphaChannel(ULONG *pulSrcBitmap, UBYTE *pubDstBitmap, PIX pixSize); +#else +// retrives memory offset of a specified mip-map or a size of all mip-maps (IN PIXELS!) +// (zero offset means first, i.e. largest mip-map) +static PIX GetMipmapOffset(INDEX iMipLevel, PIX pixWidth, PIX pixHeight) +{ + PIX pixTexSize = 0; + PIX pixMipSize = pixWidth*pixHeight; + INDEX iMips = GetNoOfMipmaps(pixWidth, pixHeight); + iMips = Min(iMips, iMipLevel); + while (iMips>0) { + pixTexSize += pixMipSize; + pixMipSize >>= 2; + iMips--; + } + return pixTexSize; +} + +// adds 8-bit opaque alpha channel to 24-bit bitmap (in place supported) +static void AddAlphaChannel(UBYTE *pubSrcBitmap, ULONG *pulDstBitmap, PIX pixSize, UBYTE *pubAlphaBitmap) +{ + UBYTE ubR, ubG, ubB, ubA = 255; + // loop backwards thru all bitmap pixels + for (INDEX iPix = (pixSize - 1); iPix >= 0; iPix--) { + ubR = pubSrcBitmap[iPix * 3 + 0]; + ubG = pubSrcBitmap[iPix * 3 + 1]; + ubB = pubSrcBitmap[iPix * 3 + 2]; + if (pubAlphaBitmap != NULL) ubA = pubAlphaBitmap[iPix]; + else ubA = 255; // for the sake of forced RGBA internal formats! + pulDstBitmap[iPix] = ByteSwap(RGBAToColor(ubR, ubG, ubB, ubA)); + } +} + +// removes 8-bit alpha channel from 32-bit bitmap (in place supported) +static void RemoveAlphaChannel(ULONG *pulSrcBitmap, UBYTE *pubDstBitmap, PIX pixSize) +{ + UBYTE ubR, ubG, ubB; + // loop thru all bitmap pixels + for (INDEX iPix = 0; iPixtd_ptegEffect != NULL) return; + + // determine dimensions + PIX pixWidth = pTD->GetPixWidth(); + PIX pixHeight = pTD->GetPixHeight(); + PIX pixMipSize = pixWidth * pixHeight; + PIX pixFrameSize = GetMipmapOffset( 15, pixWidth, pixHeight); + // allocate memory for new texture + ULONG *pulFramesNew = (ULONG*)AllocMemory( pixFrameSize*pTD->td_ctFrames *BYTES_PER_TEXEL); + UWORD *puwFramesOld = (UWORD*)pTD->td_pulFrames; + ASSERT( puwFramesOld!=NULL); + + // determine alpha channel presence + BOOL bHasAlphaChannel = pTD->td_ulFlags & TEX_ALPHACHANNEL; + + // unpack texture from 16-bit RGBA4444 or RGBA5551 format to RGBA8888 32-bit format + UBYTE r,g,b,a; + // for each frame + for( INDEX iFr=0; iFrtd_ctFrames; iFr++) + { // get addresses of current frames (new and old) + PIX pixFrameOffset = iFr * pixFrameSize; + // for each pixel + for( INDEX iPix=0; iPix>8; + g = (uwPix & 0x0F00) >>4; + b = (uwPix & 0x00F0) >>0; + a = (uwPix & 0x000F) <<4; + // adjust strength + r |= r>>4; g |= g>>4; b |= b>>4; a |= a>>4; + } else { + // without alpha channel + r = (uwPix & 0xF800) >>8; + g = (uwPix & 0x07C0) >>3; + b = (uwPix & 0x003E) <<2; + a = 0xFF; + // adjust strength + r |= r>>5; g |= g>>5; b |= b>>5; + } + + // pack it back to 32-bit + ULONG ulPix = RGBAToColor(r,g,b,a); + // store 32-bit pixel + pulFramesNew[pixFrameOffset+iPix] = ByteSwap(ulPix); + } + } + + // free old memory + FreeMemory( pTD->td_pulFrames); + // remember new texture parameters + pTD->td_pulFrames = pulFramesNew; + pTD->td_slFrameSize = pixFrameSize *BYTES_PER_TEXEL; +} + +void SubMain( int argc, char *argv[]) +{ + printf("\nTEXConv - Converter normal texture to TGA format (1.00)\n"); + printf( " (C)2023 Alexander Pavlov \n\n"); + // 2 parameters are allowed as input + if( (argc<2) || (argc>3)) + { + printf( "USAGE: TEXConv [] "); + printf( "\n"); + printf( "\n"); + printf( "texture_file: path to texture file\n"); + printf( "tga_output_file: path to create tga file\n"); + printf( "\n"); + printf( "NOTES: - out file will have the name as texture file, but \".tga\" extension\n"); + printf( "The texture file must be in the game directory. In the root or any subdirectory\n"); + exit(EXIT_FAILURE); + } + + // initialize engine +#ifdef PLATFORM_UNIX + SE_InitEngine("",""); +#else + SE_InitEngine(""); +#endif + // first input parameter is texture name + CTFileName fnTexture = CTString(argv[1]); + if(!FileExists(fnTexture)) { + printf( "Error: You specified an incorrect file name\n"); + exit(EXIT_FAILURE); + } + + // output tga file + CTFileName fnOrderFile = fnTexture.NoExt()+".tga"; + // parameter 2 specifies tga output file + if( argc>2 ) { + fnOrderFile = CTString(argv[2]); + } + + // the creation of the tga image begins + CTextureData *pTD = new CTextureData; + CTFileStream TEXFile; + SLONG slFileSize; + + // determine file size + TEXFile.Open_t( fnTexture, CTStream::OM_READ); + slFileSize = TEXFile.GetStreamSize(); + printf("Open texture file: %s (bytes:%d)\n",(const char *) TEXFile.GetDescription(),slFileSize); + + // read version + INDEX iVersion; + TEXFile.ExpectID_t( "TVER"); + TEXFile >> iVersion; + printf("Texture version: %d\n",iVersion); + + // check currently supported versions + if( iVersion!=4 && iVersion!=3) throw( TRANSV("Error: Invalid texture format version.")); + + // mark if this texture was loaded form the old format + if( iVersion==3) pTD->td_ulFlags |= TEX_WASOLD; + BOOL bAlphaChannel = FALSE; + + // loop trough file and react according to chunk ID + do + { + // obtain chunk id + CChunkID idChunk = TEXFile.GetID_t(); + if( idChunk == CChunkID(" ")) { + // we should stop reading when an invalid chunk has been encountered + break; + } + + // if this is chunk containing texture data + if( idChunk == CChunkID("TDAT")) + { + printf("CChunkID: TDAT\n"); + // read data describing texture + ULONG ulFlags=0; + INDEX ctMipLevels; + TEXFile >> ulFlags; + TEXFile >> pTD->td_mexWidth; + TEXFile >> pTD->td_mexHeight; + TEXFile >> pTD->td_ctFineMipLevels; + if( iVersion!=4) TEXFile >> ctMipLevels; + TEXFile >> pTD->td_iFirstMipLevel; + if( iVersion!=4) TEXFile >> pTD->td_slFrameSize; + TEXFile >> pTD->td_ctFrames; + // combine flags + pTD->td_ulFlags |= ulFlags; + bAlphaChannel = pTD->td_ulFlags&TEX_ALPHACHANNEL; + // determine frame size + if( iVersion==4) pTD->td_slFrameSize = GetMipmapOffset( 15, pTD->GetPixWidth(), pTD->GetPixHeight()) + * BYTES_PER_TEXEL; + } // TDAT + + // if this is chunk containing raw frames + else if( idChunk == CChunkID("FRMS")) + { + printf("CChunkID: FRMS\n"); + // calculate texture size for corresponding texture format and allocate memory + SLONG slTexSize = pTD->td_slFrameSize * pTD->td_ctFrames; + pTD->td_pulFrames = (ULONG*)AllocMemory( slTexSize); + // if older version + if( iVersion==3) { + // alloc memory block and read mip-maps + TEXFile.Read_t( pTD->td_pulFrames, slTexSize); + #if PLATFORM_BIGENDIAN + for (SLONG i = 0; i < slTexSize/4; i++) + BYTESWAP(pTD->td_pulFrames[i]); + #endif + } + // if current version + else { + PIX pixFrameSizeOnDisk = pTD->GetPixWidth()*pTD->GetPixHeight(); + for( INDEX iFr=0; iFrtd_ctFrames; iFr++) + { // loop thru frames + ULONG *pulCurrentFrame = pTD->td_pulFrames + (iFr * pTD->td_slFrameSize/BYTES_PER_TEXEL); + if( bAlphaChannel) { + // read texture with alpha channel from file + TEXFile.Read_t( pulCurrentFrame, pixFrameSizeOnDisk *4); + #if PLATFORM_BIGENDIAN + for (SLONG i = 0; i < pixFrameSizeOnDisk; i++) + BYTESWAP(pulCurrentFrame[i]); + #endif + } else { + // read texture without alpha channel from file + TEXFile.Read_t( pulCurrentFrame, pixFrameSizeOnDisk *3); + // add opaque alpha channel + AddAlphaChannel( (UBYTE*)pulCurrentFrame, pulCurrentFrame, pixFrameSizeOnDisk); + } + } + } + } // FRMS + } + // until we didn't reach end of file + while( !TEXFile.AtEOF()); + + // if texture is in old format, convert it to current format + if( iVersion==3) Convert(pTD); + printf("Width: %d Height: %d\n", pTD->GetPixHeight(), pTD->GetPixWidth()); + + // Croteam internal image format + CImageInfo ii; + // needs only first frame + INDEX iFrame = 0; + // prepare miplevel and mipmap offset + PIX pixWidth = pTD->GetPixWidth(); + PIX pixHeight = pTD->GetPixHeight(); + // export header to image info structure + ii.Clear(); + ii.ii_Width = pixWidth; + ii.ii_Height = pixHeight; + ii.ii_BitsPerPixel = (pTD->td_ulFlags&TEX_ALPHACHANNEL) ? 32 : 24; + + // prepare the texture for exporting (with or without alpha channel) + ULONG *pulFrame = (ULONG*)pTD->td_pulFrames + pTD->td_slFrameSize*iFrame/BYTES_PER_TEXEL; + PIX pixMipSize = pixWidth*pixHeight; + SLONG slMipSize = pixMipSize * ii.ii_BitsPerPixel/8; + ii.ii_Picture = (UBYTE*)AllocMemory( slMipSize); + + // export frame + if( pTD->td_ulFlags&TEX_ALPHACHANNEL) { + memcpy( ii.ii_Picture, pulFrame, slMipSize); + } else { + RemoveAlphaChannel( pulFrame, ii.ii_Picture, pixMipSize); + } + + // save tga + ii.SaveTGA_t(fnOrderFile); + ii.Clear(); + printf("Create %s image success.\n", (const char *) fnOrderFile); + exit( EXIT_SUCCESS); +} + + +// ---------------- Main ---------------- +int main( int argc, char *argv[]) +{ + CTSTREAM_BEGIN + { + SubMain(argc, argv); + } + CTSTREAM_END; + #ifdef PLATFORM_UNIX + getchar(); + #else + getch(); + #endif + return 0; +} diff --git a/SamTSE/Sources/TEXConv/TEXConv.vcxproj b/SamTSE/Sources/TEXConv/TEXConv.vcxproj new file mode 100644 index 00000000..23a1c207 --- /dev/null +++ b/SamTSE/Sources/TEXConv/TEXConv.vcxproj @@ -0,0 +1,310 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + Template + Win32 + + + Template + x64 + + + + + + + + MFCProj + {8DABA89A-52A2-4620-A135-63D0830630ED} + 10.0.14393.0 + + + + Application + v140 + Unicode + + + Application + v140 + Unicode + + + Application + Dynamic + Unicode + v140 + + + Application + Dynamic + Unicode + v140 + + + Application + false + Unicode + v140 + + + Application + false + Unicode + v140 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Release\ + Release\ + false + $(SolutionDir);$(SolutionDir)..\Tools.Win32\Libraries\DX8SDK\Include;$(IncludePath) + $(SolutionDir)..\Bin;$(SolutionDir)..\Tools.Win32\Libraries\DX8SDK\Lib;$(LibraryPath) + + + false + $(SolutionDir);$(SolutionDir)..\Tools.Win32\Libraries\DX8SDK\Include;$(IncludePath) + $(SolutionDir)..\Bin;$(SolutionDir)..\Tools.Win32\Libraries\DX8SDK\Lib;$(LibraryPath) + Release\ + Release\ + + + Debug\ + Debug\ + false + $(SolutionDir);$(SolutionDir)..\Tools.Win32\Libraries\DX8SDK\Include;$(IncludePath) + $(SolutionDir)..\Bin\Debug;$(SolutionDir)..\Tools.Win32\Libraries\DX8SDK\Lib;$(LibraryPath) + + + false + $(SolutionDir);$(SolutionDir)..\Tools.Win32\Libraries\DX8SDK\Include;$(IncludePath) + $(SolutionDir)..\Bin\Debug;$(SolutionDir)..\Tools.Win32\Libraries\DX8SDK\Lib;$(LibraryPath) + Debug\ + Debug\ + + + + MultiThreadedDLL + OnlyExplicitInline + false + MaxSpeed + true + Level3 + Speed + true + false + true + WIN32;NDEBUG;_CONSOLE;DIRECT3D_VERSION=0x0800;%(PreprocessorDefinitions) + .\Release\ + .\Release\TEXConv.pch + .\Release\ + .\Release\ + 4996;4333 + + + + + .\Release\TEXConv.tlb + + + 0x0409 + NDEBUG;%(PreprocessorDefinitions) + + + true + .\Release\TEXConv.bsc + + + true + true + Console + .\Release\TEXConv.exe + true + + + copy Release\$(TargetName).exe $(SolutionDir)..\Bin\ >nul +copy Release\$(TargetName).map $(SolutionDir)..\Bin\ >nul + Copying %(Filename) binaries to $(ENGINE_DIR)\Bin\Debug + $(SolutionDir)..\Bin\$(TargetName).exe;%(Outputs) + + + + + MultiThreadedDLL + OnlyExplicitInline + false + MaxSpeed + true + Level3 + Speed + true + false + true + WIN32;NDEBUG;_CONSOLE;DIRECT3D_VERSION=0x0800;%(PreprocessorDefinitions) + .\Release\ + .\Release\TEXConv.pch + .\Release\ + .\Release\ + 4996;4333 + + + + + .\Release\TEXConv.tlb + + + 0x0409 + NDEBUG;%(PreprocessorDefinitions) + + + true + .\Release\TEXConv.bsc + + + true + true + Console + .\Release\TEXConv.exe + true + + + copy Release\$(TargetName).exe $(SolutionDir)..\Bin\ >nul +copy Release\$(TargetName).map $(SolutionDir)..\Bin\ >nul + Copying %(Filename) binaries to $(ENGINE_DIR)\Bin\Debug + $(SolutionDir)..\Bin\$(TargetName).exe;%(Outputs) + + + + + MultiThreadedDebugDLL + Default + false + Disabled + true + Level3 + true + WIN32;_DEBUG;_CONSOLE;DIRECT3D_VERSION=0x0800;%(PreprocessorDefinitions) + Debug\ + .\Debug\TEXConv.pch + Debug\ + Debug\ + 4996;4333 + + + + + .\Debug\TEXConv.tlb + + + 0x0409 + _DEBUG;%(PreprocessorDefinitions) + + + true + .\Debug\TEXConv.bsc + + + true + true + Console + Debug\TEXConv.exe + true + + + copy Debug\$(TargetName).exe $(SolutionDir)..\Bin\Debug\ >nul +copy Debug\$(TargetName).map $(SolutionDir)..\Bin\Debug\ >nul + Copying %(Filename) binaries to $(ENGINE_DIR)\Bin\Debug + $(SolutionDir)..\Bin\Debug\$(TargetName).exe;%(Outputs) + + + + + MultiThreadedDebugDLL + Default + false + Disabled + true + Level3 + WIN32;_DEBUG;_CONSOLE;DIRECT3D_VERSION=0x0800;%(PreprocessorDefinitions) + Debug\ + .\Debug\TEXConv.pch + Debug\ + Debug\ + 4996;4333 + + + + + .\Debug\TEXConv.tlb + + + 0x0409 + _DEBUG;%(PreprocessorDefinitions) + + + true + .\Debug\TEXConv.bsc + + + true + true + Console + Debug\TEXConv.exe + true + + + copy Debug\$(TargetName).exe $(SolutionDir)..\Bin\Debug\ >nul +copy Debug\$(TargetName).map $(SolutionDir)..\Bin\Debug\ >nul + Copying %(Filename) binaries to $(ENGINE_DIR)\Bin\Debug + $(SolutionDir)..\Bin\Debug\$(TargetName).exe;%(Outputs) + + + + + + + + + \ No newline at end of file diff --git a/SamTSE/Sources/TEXConv/TEXConv.vcxproj.filters b/SamTSE/Sources/TEXConv/TEXConv.vcxproj.filters new file mode 100644 index 00000000..0e59b281 --- /dev/null +++ b/SamTSE/Sources/TEXConv/TEXConv.vcxproj.filters @@ -0,0 +1,22 @@ + + + + + {0020fbb2-e50f-49f1-b4bc-17cc8c0c186a} + cpp;c;cxx;rc;def;r;odl;hpj;bat;for;f90 + + + {24e0bef6-bc2a-407e-83b9-786e62b24e82} + h;hpp;hxx;hm;inl;fi;fd + + + {91274eac-444b-46e6-9d11-beaf0fa96d2d} + ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe + + + + + Source Files + + + diff --git a/SamTSE/Sources/TEXConv/TEXConv.vcxproj.user b/SamTSE/Sources/TEXConv/TEXConv.vcxproj.user new file mode 100644 index 00000000..695b5c78 --- /dev/null +++ b/SamTSE/Sources/TEXConv/TEXConv.vcxproj.user @@ -0,0 +1,3 @@ + + + \ No newline at end of file