2019-09-29 03:08:01 +00:00
# include "quakedef.h"
# include "shader.h"
# undef stderr
# define stderr stdout
2019-10-06 01:59:13 +00:00
# include <limits.h>
2020-01-10 12:23:25 +00:00
# include <ctype.h>
2019-09-29 03:08:01 +00:00
# ifdef _WIN32
# include <windows.h>
# endif
2020-03-07 09:00:40 +00:00
static qboolean verbose ;
2019-09-29 03:08:01 +00:00
void VARGS Sys_Error ( const char * fmt , . . . )
{
va_list argptr ;
va_start ( argptr , fmt ) ;
vfprintf ( stderr , fmt , argptr ) ;
va_end ( argptr ) ;
fflush ( stderr ) ;
exit ( 1 ) ;
}
void VARGS Con_Printf ( const char * fmt , . . . )
{
va_list argptr ;
va_start ( argptr , fmt ) ;
vfprintf ( stderr , fmt , argptr ) ;
va_end ( argptr ) ;
fflush ( stderr ) ;
}
void VARGS Con_DPrintf ( const char * fmt , . . . )
{
va_list argptr ;
2020-03-07 09:00:40 +00:00
if ( ! verbose )
return ;
2019-09-29 03:08:01 +00:00
va_start ( argptr , fmt ) ;
vfprintf ( stderr , fmt , argptr ) ;
va_end ( argptr ) ;
fflush ( stderr ) ;
}
void VARGS Con_ThrottlePrintf ( float * timer , int developerlevel , const char * fmt , . . . )
{
va_list argptr ;
va_start ( argptr , fmt ) ;
vfprintf ( stderr , fmt , argptr ) ;
va_end ( argptr ) ;
fflush ( stderr ) ;
}
void * ZF_Malloc ( size_t size )
{
# if defined(__linux__)
void * ret = NULL ;
if ( ! posix_memalign ( & ret , max ( sizeof ( float ) * 4 , sizeof ( void * ) ) , size ) )
memset ( ret , 0 , size ) ;
return ret ;
# else
return calloc ( size , 1 ) ;
# endif
}
void * Z_Malloc ( size_t size )
{
void * r = ZF_Malloc ( size ) ;
if ( ! r )
exit ( 1 ) ;
return r ;
}
void * BZ_Malloc ( size_t size )
{
return Z_Malloc ( size ) ;
}
void * BZF_Malloc ( size_t size )
{
return Z_Malloc ( size ) ;
}
void BZ_Free ( void * p )
{
free ( p ) ;
}
void Z_Free ( void * p )
{
free ( p ) ;
}
2020-06-13 00:05:47 +00:00
# ifdef _WIN32
// don't use these functions in MSVC8
# if (_MSC_VER < 1400)
int QDECL linuxlike_snprintf ( char * buffer , int size , const char * format , . . . )
{
# undef _vsnprintf
int ret ;
va_list argptr ;
if ( size < = 0 )
return 0 ;
size - - ;
va_start ( argptr , format ) ;
ret = _vsnprintf ( buffer , size , format , argptr ) ;
va_end ( argptr ) ;
buffer [ size ] = ' \0 ' ;
return ret ;
}
int QDECL linuxlike_vsnprintf ( char * buffer , int size , const char * format , va_list argptr )
{
# undef _vsnprintf
int ret ;
if ( size < = 0 )
return 0 ;
size - - ;
ret = _vsnprintf ( buffer , size , format , argptr ) ;
buffer [ size ] = ' \0 ' ;
return ret ;
}
# elif (_MSC_VER < 1900)
int VARGS linuxlike_snprintf_vc8 ( char * buffer , int size , const char * format , . . . )
{
int ret ;
va_list argptr ;
va_start ( argptr , format ) ;
ret = vsnprintf_s ( buffer , size , _TRUNCATE , format , argptr ) ;
va_end ( argptr ) ;
return ret ;
}
# endif
# endif
2019-09-29 03:08:01 +00:00
# include <sys/stat.h>
void FS_CreatePath ( const char * pname , enum fs_relative relativeto )
{
char * t = strdup ( pname ) , * sl = t ;
while ( ( sl = strchr ( sl , ' / ' ) ) )
{
* sl = 0 ;
# ifdef _WIN32
CreateDirectoryA ( t , NULL ) ;
# else
mkdir ( t , 0777 ) ;
# endif
* sl + + = ' / ' ;
}
free ( t ) ;
}
2019-10-06 01:59:13 +00:00
qboolean FS_Remove ( const char * path , enum fs_relative relativeto )
2019-09-29 03:08:01 +00:00
{
//remove is part of c89.
if ( remove ( path ) = = - 1 )
return false ;
return true ;
}
qboolean FS_NativePath ( const char * fname , enum fs_relative relativeto , char * out , int outlen )
{
Q_strncpyz ( out , fname , outlen ) ;
return true ;
}
2020-03-07 09:00:40 +00:00
char * COM_SkipPath ( const char * pathname )
{
const char * last ;
last = pathname ;
while ( * pathname )
{
if ( * pathname = = ' / ' | | * pathname = = ' \\ ' )
last = pathname + 1 ;
pathname + + ;
}
return ( char * ) last ;
}
2019-09-29 03:08:01 +00:00
# ifdef __unix__
# include <sys/stat.h>
# endif
qbyte * FS_LoadMallocFile ( const char * path , size_t * fsize )
{
qbyte * data = NULL ;
FILE * f ;
# ifdef __unix__
struct stat sb ;
if ( stat ( path , & sb ) < 0 )
return NULL ;
if ( ( sb . st_mode & S_IFMT ) ! = S_IFREG )
return NULL ;
# endif
f = fopen ( path , " rb " ) ;
if ( f )
{
long int sz ;
if ( fseek ( f , 0 , SEEK_END ) > = 0 )
{
sz = ftell ( f ) ;
if ( sz > = 0 )
{
* fsize = sz ;
fseek ( f , 0 , SEEK_SET ) ;
data = ZF_Malloc ( * fsize + 1 ) ;
if ( data )
{
data [ * fsize ] = 0 ;
fread ( data , 1 , * fsize , f ) ;
}
else
Con_Printf ( " Unable to allocate memory for %s \n " , path ) ;
}
}
fclose ( f ) ;
}
return data ;
}
# ifdef _WIN32
dllhandle_t * Sys_LoadLibrary ( const char * name , dllfunction_t * funcs )
{
return NULL ;
}
# else
# include <dlfcn.h>
void Sys_CloseLibrary ( dllhandle_t * lib )
{
dlclose ( ( void * ) lib ) ;
}
dllhandle_t * Sys_LoadLibrary ( const char * name , dllfunction_t * funcs )
{
int i ;
dllhandle_t * lib ;
lib = NULL ;
if ( ! lib )
lib = dlopen ( name , RTLD_LOCAL | RTLD_LAZY ) ;
// if (!lib && !strstr(name, ".so"))
// lib = dlopen (va("%s.so", name), RTLD_LOCAL|RTLD_LAZY);
if ( ! lib )
{
// Con_DPrintf("%s\n", dlerror());
return NULL ;
}
if ( funcs )
{
for ( i = 0 ; funcs [ i ] . name ; i + + )
{
* funcs [ i ] . funcptr = dlsym ( lib , funcs [ i ] . name ) ;
if ( ! * funcs [ i ] . funcptr )
break ;
}
if ( funcs [ i ] . name )
{
Con_DPrintf ( " Unable to find symbol \" %s \" in \" %s \" \n " , funcs [ i ] . name , name ) ;
Sys_CloseLibrary ( ( dllhandle_t * ) lib ) ;
lib = NULL ;
}
}
return ( dllhandle_t * ) lib ;
}
# endif
struct imgfile_s
{
vfsfile_t pub ;
FILE * f ;
} ;
static qboolean QDECL ImgFile_Close ( struct vfsfile_s * file )
{
struct imgfile_s * f = ( struct imgfile_s * ) file ;
fclose ( f - > f ) ;
free ( f ) ;
return true ;
}
static int QDECL ImgFile_WriteBytes ( struct vfsfile_s * file , const void * buffer , int bytestowrite )
{
struct imgfile_s * f = ( struct imgfile_s * ) file ;
return fwrite ( buffer , 1 , bytestowrite , f - > f ) ;
}
2019-10-14 02:36:13 +00:00
static qboolean QDECL ImgFile_Seek ( struct vfsfile_s * file , qofs_t newofs )
{
struct imgfile_s * f = ( struct imgfile_s * ) file ;
if ( fseek ( f - > f , newofs , SEEK_SET ) = = 0 )
return true ; //success
return false ;
}
static qofs_t QDECL ImgFile_Tell ( struct vfsfile_s * file )
{
struct imgfile_s * f = ( struct imgfile_s * ) file ;
return ftell ( f - > f ) ;
}
2019-09-29 03:08:01 +00:00
vfsfile_t * QDECL FS_OpenVFS ( const char * filename , const char * mode , enum fs_relative relativeto )
{
if ( ! strcmp ( mode , " wb " ) )
{
struct imgfile_s * r = malloc ( sizeof ( * r ) ) ;
r - > f = fopen ( filename , mode ) ;
r - > pub . seekstyle = SS_UNSEEKABLE ;
r - > pub . Close = ImgFile_Close ;
r - > pub . WriteBytes = ImgFile_WriteBytes ;
2019-10-14 02:36:13 +00:00
r - > pub . Seek = ImgFile_Seek ;
r - > pub . Tell = ImgFile_Tell ;
2019-09-29 03:08:01 +00:00
if ( r - > f )
return & r - > pub ;
free ( r ) ;
}
return NULL ;
}
qboolean COM_WriteFile ( const char * filename , enum fs_relative fsroot , const void * data , int len )
{
2020-03-07 09:00:40 +00:00
vfsfile_t * f = FS_OpenVFS ( filename , " wb " , fsroot ) ;
qboolean ret = false ;
if ( f )
{
ret = len = = VFS_WRITE ( f , data , len ) ;
if ( ! VFS_CLOSE ( f ) )
ret = false ;
}
return ret ;
2019-09-29 03:08:01 +00:00
}
void QDECL Q_strncpyz ( char * d , const char * s , int n )
{
int i ;
n - - ;
if ( n < 0 )
return ; //this could be an error
for ( i = 0 ; * s ; i + + )
{
if ( i = = n )
break ;
* d + + = * s + + ;
}
* d = ' \0 ' ;
}
void VARGS Q_vsnprintfz ( char * dest , size_t size , const char * fmt , va_list argptr )
{
# ifdef _WIN32
2019-12-17 19:21:29 +00:00
# undef _vsnprintf
2019-09-29 03:08:01 +00:00
_vsnprintf ( dest , size , fmt , argptr ) ;
2019-12-17 19:21:29 +00:00
# define _vsnprintf unsafe_vsnprintf
2019-09-29 03:08:01 +00:00
# else
# ifdef _DEBUG
if ( ( size_t ) vsnprintf ( dest , size , fmt , argptr ) > size - 1 )
Sys_Error ( " Q_vsnprintfz: truncation " ) ;
# else
vsnprintf ( dest , size , fmt , argptr ) ;
# endif
# endif
dest [ size - 1 ] = 0 ;
}
void VARGS Q_snprintfz ( char * dest , size_t size , const char * fmt , . . . )
{
va_list argptr ;
va_start ( argptr , fmt ) ;
Q_vsnprintfz ( dest , size , fmt , argptr ) ;
va_end ( argptr ) ;
}
2019-10-14 02:36:13 +00:00
//palette data is used in lmps, as well as written into pcxes or wads, probably some other things.
2019-09-29 03:08:01 +00:00
qbyte * host_basepal ;
unsigned int d_8to24rgbtable [ 256 ] ;
unsigned int d_8to24bgrtable [ 256 ] ;
2019-10-14 02:36:13 +00:00
static qbyte default_quakepal [ 768 ] =
{ //the quake palette was released into the public domain (or at least gpl) to ease development of tools writing quake-format data.
0 , 0 , 0 , 15 , 15 , 15 , 31 , 31 , 31 , 47 , 47 , 47 , 63 , 63 , 63 , 75 , 75 , 75 , 91 , 91 , 91 , 107 , 107 , 107 , 123 , 123 , 123 , 139 , 139 , 139 , 155 , 155 , 155 , 171 , 171 , 171 , 187 , 187 , 187 , 203 , 203 , 203 , 219 , 219 , 219 , 235 , 235 , 235 , 15 , 11 , 7 , 23 , 15 , 11 , 31 , 23 , 11 , 39 , 27 , 15 , 47 , 35 , 19 , 55 , 43 , 23 , 63 , 47 , 23 , 75 , 55 , 27 , 83 , 59 , 27 , 91 , 67 , 31 , 99 , 75 , 31 , 107 , 83 , 31 , 115 , 87 , 31 , 123 , 95 , 35 , 131 , 103 , 35 , 143 , 111 , 35 , 11 , 11 , 15 , 19 , 19 , 27 , 27 , 27 , 39 , 39 , 39 , 51 , 47 , 47 , 63 , 55 , 55 , 75 , 63 , 63 , 87 , 71 , 71 , 103 , 79 , 79 , 115 , 91 , 91 , 127 , 99 , 99 ,
139 , 107 , 107 , 151 , 115 , 115 , 163 , 123 , 123 , 175 , 131 , 131 , 187 , 139 , 139 , 203 , 0 , 0 , 0 , 7 , 7 , 0 , 11 , 11 , 0 , 19 , 19 , 0 , 27 , 27 , 0 , 35 , 35 , 0 , 43 , 43 , 7 , 47 , 47 , 7 , 55 , 55 , 7 , 63 , 63 , 7 , 71 , 71 , 7 , 75 , 75 , 11 , 83 , 83 , 11 , 91 , 91 , 11 , 99 , 99 , 11 , 107 , 107 , 15 , 7 , 0 , 0 , 15 , 0 , 0 , 23 , 0 , 0 , 31 , 0 , 0 , 39 , 0 , 0 , 47 , 0 , 0 , 55 , 0 , 0 , 63 , 0 , 0 , 71 , 0 , 0 , 79 , 0 , 0 , 87 , 0 , 0 , 95 , 0 , 0 , 103 , 0 , 0 , 111 , 0 , 0 , 119 , 0 , 0 , 127 , 0 , 0 , 19 , 19 , 0 , 27 , 27 , 0 , 35 , 35 , 0 , 47 , 43 , 0 , 55 , 47 , 0 , 67 ,
55 , 0 , 75 , 59 , 7 , 87 , 67 , 7 , 95 , 71 , 7 , 107 , 75 , 11 , 119 , 83 , 15 , 131 , 87 , 19 , 139 , 91 , 19 , 151 , 95 , 27 , 163 , 99 , 31 , 175 , 103 , 35 , 35 , 19 , 7 , 47 , 23 , 11 , 59 , 31 , 15 , 75 , 35 , 19 , 87 , 43 , 23 , 99 , 47 , 31 , 115 , 55 , 35 , 127 , 59 , 43 , 143 , 67 , 51 , 159 , 79 , 51 , 175 , 99 , 47 , 191 , 119 , 47 , 207 , 143 , 43 , 223 , 171 , 39 , 239 , 203 , 31 , 255 , 243 , 27 , 11 , 7 , 0 , 27 , 19 , 0 , 43 , 35 , 15 , 55 , 43 , 19 , 71 , 51 , 27 , 83 , 55 , 35 , 99 , 63 , 43 , 111 , 71 , 51 , 127 , 83 , 63 , 139 , 95 , 71 , 155 , 107 , 83 , 167 , 123 , 95 , 183 , 135 , 107 , 195 , 147 , 123 , 211 , 163 , 139 , 227 , 179 , 151 ,
171 , 139 , 163 , 159 , 127 , 151 , 147 , 115 , 135 , 139 , 103 , 123 , 127 , 91 , 111 , 119 , 83 , 99 , 107 , 75 , 87 , 95 , 63 , 75 , 87 , 55 , 67 , 75 , 47 , 55 , 67 , 39 , 47 , 55 , 31 , 35 , 43 , 23 , 27 , 35 , 19 , 19 , 23 , 11 , 11 , 15 , 7 , 7 , 187 , 115 , 159 , 175 , 107 , 143 , 163 , 95 , 131 , 151 , 87 , 119 , 139 , 79 , 107 , 127 , 75 , 95 , 115 , 67 , 83 , 107 , 59 , 75 , 95 , 51 , 63 , 83 , 43 , 55 , 71 , 35 , 43 , 59 , 31 , 35 , 47 , 23 , 27 , 35 , 19 , 19 , 23 , 11 , 11 , 15 , 7 , 7 , 219 , 195 , 187 , 203 , 179 , 167 , 191 , 163 , 155 , 175 , 151 , 139 , 163 , 135 , 123 , 151 , 123 , 111 , 135 , 111 , 95 , 123 , 99 , 83 , 107 , 87 , 71 , 95 , 75 , 59 , 83 , 63 ,
51 , 67 , 51 , 39 , 55 , 43 , 31 , 39 , 31 , 23 , 27 , 19 , 15 , 15 , 11 , 7 , 111 , 131 , 123 , 103 , 123 , 111 , 95 , 115 , 103 , 87 , 107 , 95 , 79 , 99 , 87 , 71 , 91 , 79 , 63 , 83 , 71 , 55 , 75 , 63 , 47 , 67 , 55 , 43 , 59 , 47 , 35 , 51 , 39 , 31 , 43 , 31 , 23 , 35 , 23 , 15 , 27 , 19 , 11 , 19 , 11 , 7 , 11 , 7 , 255 , 243 , 27 , 239 , 223 , 23 , 219 , 203 , 19 , 203 , 183 , 15 , 187 , 167 , 15 , 171 , 151 , 11 , 155 , 131 , 7 , 139 , 115 , 7 , 123 , 99 , 7 , 107 , 83 , 0 , 91 , 71 , 0 , 75 , 55 , 0 , 59 , 43 , 0 , 43 , 31 , 0 , 27 , 15 , 0 , 11 , 7 , 0 , 0 , 0 , 255 , 11 , 11 , 239 , 19 , 19 , 223 , 27 , 27 , 207 , 35 , 35 , 191 , 43 ,
43 , 175 , 47 , 47 , 159 , 47 , 47 , 143 , 47 , 47 , 127 , 47 , 47 , 111 , 47 , 47 , 95 , 43 , 43 , 79 , 35 , 35 , 63 , 27 , 27 , 47 , 19 , 19 , 31 , 11 , 11 , 15 , 43 , 0 , 0 , 59 , 0 , 0 , 75 , 7 , 0 , 95 , 7 , 0 , 111 , 15 , 0 , 127 , 23 , 7 , 147 , 31 , 7 , 163 , 39 , 11 , 183 , 51 , 15 , 195 , 75 , 27 , 207 , 99 , 43 , 219 , 127 , 59 , 227 , 151 , 79 , 231 , 171 , 95 , 239 , 191 , 119 , 247 , 211 , 139 , 167 , 123 , 59 , 183 , 155 , 55 , 199 , 195 , 55 , 231 , 227 , 87 , 127 , 191 , 255 , 171 , 231 , 255 , 215 , 255 , 255 , 103 , 0 , 0 , 139 , 0 , 0 , 179 , 0 , 0 , 215 , 0 , 0 , 255 , 0 , 0 , 255 , 243 , 147 , 255 , 247 , 199 , 255 , 255 , 255 , 159 , 91 , 83
} ;
2019-09-29 03:08:01 +00:00
qbyte GetPaletteIndexNoFB ( int red , int green , int blue )
{
2019-10-14 02:36:13 +00:00
int i ;
int best = 0 ;
int bestdist = INT_MAX ;
int dist ;
for ( i = 0 ; i < 256 - 32 ; i + + )
{
2020-03-07 09:00:40 +00:00
const int diff [ 3 ] = {
host_basepal [ i * 3 + 0 ] - red ,
host_basepal [ i * 3 + 1 ] - green ,
host_basepal [ i * 3 + 2 ] - blue } ;
dist = DotProduct ( diff , diff ) ;
2019-10-14 02:36:13 +00:00
if ( dist < bestdist )
{
bestdist = dist ;
best = i ;
}
}
return best ;
}
2020-06-13 00:05:47 +00:00
sh_config_t sh_config ;
viddef_t vid ;
void ImgTool_SetupPalette ( void )
2019-10-14 02:36:13 +00:00
{
int i ;
//we ought to try to read gfx/palette.lmp, but its probably in a pak
host_basepal = default_quakepal ;
for ( i = 0 ; i < 256 ; i + + )
{
d_8to24rgbtable [ i ] = ( host_basepal [ i * 3 + 0 ] < < 0 ) | ( host_basepal [ i * 3 + 1 ] < < 8 ) | ( host_basepal [ i * 3 + 2 ] < < 16 ) ;
d_8to24bgrtable [ i ] = ( host_basepal [ i * 3 + 0 ] < < 16 ) | ( host_basepal [ i * 3 + 1 ] < < 8 ) | ( host_basepal [ i * 3 + 2 ] < < 0 ) ;
}
2020-06-13 00:05:47 +00:00
sh_config . texture2d_maxsize = 1u < < 31 ;
sh_config . texture3d_maxsize = 1u < < 31 ;
sh_config . texture2darray_maxlayers = 1u < < 31 ;
sh_config . texturecube_maxsize = 8192 ;
sh_config . texture_non_power_of_two = true ;
sh_config . texture_non_power_of_two_pic = true ;
sh_config . texture_allow_block_padding = true ;
sh_config . npot_rounddown = true ; //shouldn't be relevant
sh_config . havecubemaps = true ; //I don't think this matters.
Image_Init ( ) ;
2019-10-14 02:36:13 +00:00
}
2020-06-13 00:05:47 +00:00
# ifdef IMGTOOL
2019-10-14 02:36:13 +00:00
static void ImgTool_FreeMips ( struct pendingtextureinfo * mips )
{
size_t i ;
2019-10-18 08:37:38 +00:00
if ( mips )
{
for ( i = 0 ; i < mips - > mipcount ; i + + )
if ( mips - > mip [ i ] . needfree )
BZ_Free ( mips - > mip [ i ] . data ) ;
if ( mips - > extrafree )
BZ_Free ( mips - > extrafree ) ;
BZ_Free ( mips ) ;
}
2019-09-29 03:08:01 +00:00
}
2020-01-10 12:23:25 +00:00
typedef struct
{
unsigned int offset ; // Position of the entry in WAD
unsigned int dsize ; // Size of the entry in WAD file
unsigned int size ; // Size of the entry in memory
char type ; // type of entry
char cmprs ; // Compression. 0 if none.
short dummy ; // Not used
char name [ 16 ] ; // we use only first 8
} wad2entry_t ;
typedef struct
{
char magic [ 4 ] ; //should be WAD2
unsigned int num ; //number of entries
unsigned int offset ; //location of directory
} wad2_t ;
static const char * imagetypename [ ] = { " 2D " , " 3D " , " Cube " , " 2DArray " , " CubemapArray " , " INVALID " , " INVALID " , " INVALID " , " INVALID " , " INVALID " } ;
2019-09-29 03:08:01 +00:00
struct opts_s
{
2019-10-18 08:37:38 +00:00
int textype ;
2020-01-10 12:23:25 +00:00
const char * defaultext ; //.dds or whatever when the output's extension is not explicitly given.
2019-09-29 03:08:01 +00:00
unsigned int flags ; //image flags to use (affects how textures get interpreted a little)
unsigned int mipnum ; //when exporting to a mipless format, this is the mip level that is actually written. default 0.
uploadfmt_t newpixelformat ; //try to convert to this pixel format on export.
2020-03-07 09:00:40 +00:00
int width , height ;
2019-09-29 03:08:01 +00:00
} ;
2020-03-07 09:00:40 +00:00
static qboolean ImgTool_MipExport ( struct opts_s * args , vfsfile_t * outfile , struct pendingtextureinfo * in , const char * mipname , int wadtype ) ;
2020-08-18 01:59:55 +00:00
static struct pendingtextureinfo * ImgTool_DecodeMiptex ( struct opts_s * args , miptex_t * mip , size_t fsize ) ;
2019-09-29 03:08:01 +00:00
void Image_GenerateMips ( struct pendingtextureinfo * mips , unsigned int flags ) ;
int Image_WritePNG ( const char * filename , enum fs_relative fsroot , int compression , void * * buffers , int numbuffers , qintptr_t bufferstride , int width , int height , enum uploadfmt fmt , qboolean writemetadata ) ;
qboolean WriteTGA ( const char * filename , enum fs_relative fsroot , const qbyte * fte_restrict rgb_buffer , qintptr_t bytestride , int width , int height , enum uploadfmt fmt ) ;
2019-10-06 01:59:13 +00:00
static enum uploadfmt ImgTool_ASTCToLDR ( uploadfmt_t fmt )
2019-09-29 03:08:01 +00:00
{
if ( fmt > = PTI_ASTC_FIRST & & fmt < = PTI_ASTC_LAST )
{
if ( fmt > = PTI_ASTC_4X4_HDR )
return ( fmt - PTI_ASTC_4X4_HDR ) + PTI_ASTC_4X4_LDR ;
if ( fmt > = PTI_ASTC_4X4_SRGB )
return ( fmt - PTI_ASTC_4X4_SRGB ) + PTI_ASTC_4X4_LDR ;
}
2019-10-06 01:59:13 +00:00
if ( fmt = = PTI_BC1_RGB )
return PTI_BC1_RGBA ;
2019-09-29 03:08:01 +00:00
return fmt ;
}
# ifdef _WIN32
static void FS_MakeTempName ( char * out , size_t outsize , char * prefix , char * suffix )
{
2020-01-10 12:23:25 +00:00
static char temp_path [ MAX_PATH ] ;
char temp_file_name [ MAX_PATH ] ;
if ( ! * temp_path & & ! GetTempPathA ( sizeof ( temp_path ) , temp_path ) )
Sys_Error ( " FS_MakeTempName failed to get temp path \n " ) ;
if ( ! GetTempFileNameA ( temp_path , prefix , 0 , temp_file_name ) )
Sys_Error ( " FS_MakeTempName failed \n " ) ;
Q_snprintfz ( out , outsize , " %s%s " , temp_file_name , suffix ) ;
2019-09-29 03:08:01 +00:00
}
# else
# include <unistd.h>
static void FS_MakeTempName ( char * out , size_t outsize , char * prefix , char * suffix )
{
snprintf ( out , outsize , " /tmp/%sXXXXXX%s " , prefix , suffix ) ;
close ( mkstemps ( out , strlen ( suffix ) ) ) ; //bsd4.3/posix1-2001
}
# endif
2020-01-10 12:23:25 +00:00
static qboolean ImgTool_HasAlpha ( struct pendingtextureinfo * mips )
{
if ( mips - > encoding = = PTI_RGBA8 | | mips - > encoding = = PTI_BGRA8 | | mips - > encoding = = PTI_LLLA8 | | mips - > encoding = = PTI_RGBA8_SRGB | | mips - > encoding = = PTI_BGRA8_SRGB )
{
size_t l = 0 , pixels , p ;
qbyte * d ;
for ( l = 0 ; l < mips - > mipcount ; l + + )
{
pixels = mips - > mip [ l ] . width * mips - > mip [ l ] . height * mips - > mip [ l ] . depth * 4 ;
d = mips - > mip [ l ] . data ;
d + = 3 ;
for ( p = 0 ; p < pixels ; p + = 4 )
if ( d [ p ] ! = 255 )
return true ; //a transparent pixel!
}
return false ;
}
else if ( mips - > encoding = = PTI_L8A8 | | mips - > encoding = = PTI_L8A8_SRGB )
{
size_t l = 0 , pixels , p ;
qbyte * d ;
for ( l = 0 ; l < mips - > mipcount ; l + + )
{
pixels = mips - > mip [ l ] . width * mips - > mip [ l ] . height * mips - > mip [ l ] . depth * 2 ;
d = mips - > mip [ l ] . data ;
d + = 1 ;
for ( p = 0 ; p < pixels ; p + = 2 )
if ( d [ p ] ! = 255 )
return true ; //a transparent pixel!
}
return false ;
}
else if ( mips - > encoding = = PTI_RGBA16 )
{
size_t l = 0 , pixels , p ;
unsigned short * d ;
for ( l = 0 ; l < mips - > mipcount ; l + + )
{
pixels = mips - > mip [ l ] . width * mips - > mip [ l ] . height * mips - > mip [ l ] . depth * 4 ;
d = mips - > mip [ l ] . data ;
d + = 3 ;
for ( p = 0 ; p < pixels ; p + = 4 )
if ( d [ p ] ! = 0xffff )
return true ; //a transparent pixel!
}
return false ;
}
else
return Image_FormatHasAlpha ( mips - > encoding ) ;
}
2020-03-07 09:00:40 +00:00
//copys all the data out and everything!
static struct pendingtextureinfo * ImgTool_DupeMipchain ( struct pendingtextureinfo * src )
{
struct pendingtextureinfo * dest ;
qbyte * data ;
size_t size = 0 ;
size_t m ;
for ( m = 0 ; m < src - > mipcount ; m + + )
size + = src - > mip [ m ] . datasize ;
dest = Z_Malloc ( sizeof ( * dest ) + size ) ;
* dest = * src ;
data = ( qbyte * ) ( dest + 1 ) ;
for ( m = 0 ; m < src - > mipcount ; m + + )
{
dest - > mip [ m ] . data = data ;
dest - > mip [ m ] . needfree = false ;
memcpy ( data , src - > mip [ m ] . data , src - > mip [ m ] . datasize ) ;
data + = src - > mip [ m ] . datasize ;
}
dest - > extrafree = NULL ; //part of the texinfo itself.
return dest ;
}
2019-10-06 01:59:13 +00:00
static qboolean ImgTool_ConvertPixelFormat ( struct opts_s * args , const char * inname , struct pendingtextureinfo * mips )
2019-09-29 03:08:01 +00:00
{
struct pendingtextureinfo tmp , * ret ;
size_t m ;
char raw [ MAX_OSPATH ] ;
char comp [ MAX_OSPATH ] ;
char command [ MAX_OSPATH * 3 ] ;
qbyte * fdata ;
size_t fsize ;
2020-04-29 10:43:22 +00:00
int bb , bw , bh , bd ;
2019-09-29 03:08:01 +00:00
qboolean canktx = false ;
uploadfmt_t targfmt = args - > newpixelformat ;
2020-01-10 12:23:25 +00:00
int d , l , layers , r ;
2019-09-29 03:08:01 +00:00
2019-10-06 01:59:13 +00:00
//force it to bc1 if bc2 or bc3 with no alpha channel.
2020-01-10 12:23:25 +00:00
if ( ( targfmt = = PTI_BC2_RGBA | | targfmt = = PTI_BC3_RGBA ) & & ! ImgTool_HasAlpha ( mips ) )
2019-10-06 01:59:13 +00:00
targfmt = PTI_BC1_RGB ;
2019-09-29 03:08:01 +00:00
if ( targfmt > = PTI_ASTC_FIRST & & targfmt < = PTI_ASTC_LAST )
{
Q_snprintfz ( command , sizeof ( command ) , " astcenc -c " ) ;
canktx = true ;
}
else if ( targfmt = = PTI_BC1_RGB )
Q_snprintfz ( command , sizeof ( command ) , " nvcompress -bc1%s " , ( args - > flags & IF_TRYBUMP ) ? " n " : " " ) ;
2020-01-10 12:23:25 +00:00
else if ( targfmt = = PTI_BC1_RGB_SRGB )
Q_snprintfz ( command , sizeof ( command ) , " nvcompress -bc1%s -srgb -dds10 " , ( args - > flags & IF_TRYBUMP ) ? " n " : " " ) ;
2019-09-29 03:08:01 +00:00
else if ( targfmt = = PTI_BC1_RGBA )
Q_snprintfz ( command , sizeof ( command ) , " nvcompress -bc1a " ) ;
2020-01-10 12:23:25 +00:00
else if ( targfmt = = PTI_BC1_RGBA_SRGB )
Q_snprintfz ( command , sizeof ( command ) , " nvcompress -bc1a -srgb -dds10 " ) ;
2019-09-29 03:08:01 +00:00
else if ( targfmt = = PTI_BC2_RGBA )
Q_snprintfz ( command , sizeof ( command ) , " nvcompress -bc2 " ) ;
2020-01-10 12:23:25 +00:00
else if ( targfmt = = PTI_BC2_RGBA_SRGB )
Q_snprintfz ( command , sizeof ( command ) , " nvcompress -bc2 -srgb -dds10 " ) ;
2019-09-29 03:08:01 +00:00
else if ( targfmt = = PTI_BC3_RGBA )
Q_snprintfz ( command , sizeof ( command ) , " nvcompress -bc3%s " , ( args - > flags & IF_TRYBUMP ) ? " n " : " " ) ;
2020-01-10 12:23:25 +00:00
else if ( targfmt = = PTI_BC3_RGBA_SRGB )
Q_snprintfz ( command , sizeof ( command ) , " nvcompress -bc3%s -srgb -dds10 " , ( args - > flags & IF_TRYBUMP ) ? " n " : " " ) ;
2020-03-07 09:00:40 +00:00
else if ( targfmt = = PTI_BC4_R )
2019-09-29 03:08:01 +00:00
Q_snprintfz ( command , sizeof ( command ) , " nvcompress -bc4 " ) ;
2020-03-07 09:00:40 +00:00
else if ( targfmt = = PTI_BC5_RG )
2019-09-29 03:08:01 +00:00
Q_snprintfz ( command , sizeof ( command ) , " nvcompress -bc5 " ) ;
2019-10-06 01:59:13 +00:00
else if ( targfmt = = PTI_BC6_RGB_SFLOAT | | targfmt = = PTI_BC6_RGB_UFLOAT )
Q_snprintfz ( command , sizeof ( command ) , " nvcompress -bc6 " ) ;
else if ( targfmt = = PTI_BC7_RGBA )
Q_snprintfz ( command , sizeof ( command ) , " nvcompress -bc7 " ) ;
2020-01-10 12:23:25 +00:00
else if ( targfmt = = PTI_BC7_RGBA_SRGB )
Q_snprintfz ( command , sizeof ( command ) , " nvcompress -bc7 -srgb " ) ;
2019-09-29 03:08:01 +00:00
else
2019-10-14 02:36:13 +00:00
{
if ( mips - > encoding ! = targfmt )
{
Too many changes, sorry.
Change revision displays, use the SVN commit date instead of using __DATE__ (when there's no local changes). This should allow reproducible builds.
Added s_al_disable cvar, to block openal and all the various problems people have had with it, without having to name an explicit fallback (which would vary by system).
Add mastervolume cvar (for ss).
Add r_shadows 2 (aka fake shadows - for ss).
Add scr_loadingscreen_aspect -1 setting, to disable levelshots entirely, also disables the progress bar (for ss).
Better support for some effectinfo hacks (for ss).
Added dpcompat_nocsqcwarnings (because of lazy+buggy mods like ss).
Rework the dpcsqc versions of project+unproject builtins for better compat (for ss).
Added dpcompat_csqcinputeventtypes to block unexpected csqc input events (for ss).
Better compat with DP's loadfont console command (for ss).
Added dpcompat_smallerfonts cvar to replicate a DP bug (for ss).
Detect dp's m_draw extension, to work around it (for ss).
Cvar dpcompat_ignoremodificationtimes added. A value of 0 favour the most recently modified file, 1 will use DP-like alphabetically sorted preferences (for ss).
loadfont builtin can now accept outline=1 in the sizes arg for slightly more readable fonts.
Fix bbox calcs for rotated entities, fix needed for r_ignorenetpvs 0.
Hackily parse emoji.json to provide :poop: etc suggestions.
Skip prediction entirely when there's no local entity info. This fixes stair-smoothing in xonotic.
screenshot_cubemap will now capture half-float images when saving to ktx or dds files.
Fix support for xcf files larger than 4gb, mostly to avoid compiler warnings.
Fixed size of gfx/loading.lmp when replacement textures are used.
Added mipmap support for rg8 and l8a8 textures.
r_hdr_framebuffer cvar updated to support format names instead of random negative numbers. Description updated to name some interesting ones.
Perform autoupdate _checks_ ONLY with explicit user confirmation (actual updating already needed user confirmation, but this extra step should reduce the chances of us getting wrongly accused of exfiltrating user data if we're run in a sandbox - we ONLY ever included the updating engine's version in the checks, though there's nothing we can do to avoid sending the user's router's IP).
Removed the 'summon satan all over your harddrive' quit message, in case paranoid security researchers are idiots and don't bother doing actual research.
Removed the triptohell.info and fte.triptohell.info certificates, they really need to stop being self-signed. The updates domain is still self-signed for autoupdates.
Video drivers are now able to report supported video resolutions, visible to menuqc. Currently only works with SDL2 builds.
Added setmousepos builtin. Should work with glx+win32 build.
VF_SKYROOM_CAMERA can now accept an extra two args, setviewprop(VF_SKYROOM_CAMERA, org, axis, degrees).
Removed v_skyroom_origin+v_skyroom_orientation cvars in favour just v_skyroom, which should make it behave more like the 'fog' command (used when csqc isn't overriding).
Added R_EndPolygonRibbon builtin to make it faster+easier to generate textured ribbon/cable/etc wide lines (for TW).
sdl: Fix up sys_sdl.c's file enumeration to support wildcards in directories.
edit command now displays end1.bin/end2.bin correctly, because we can.
Finally add support for f_modified - though ruleset_allow_larger_models and ruleset_allow_overlong_sounds generally make it redundant.
Fix threading race condition in sha1 lookups.
Updated f_ruleset to include the same extra flags reported by ezquake.
A mod's default.fmf file can now contain an eg 'mainconfig config.cfg' line (to explicitly set the main config saved with cfg_save_auto 1 etc).
fmf: basegame steam:GameName/GameDir can be used to try to load a mod directory from an installed steam game. The resulting gamedir will be read-only.
HOMEDIR CHANGE: use homedirs only if the basedir cannot be written or a homedir already exists, which should further reduce the probability of microsoft randomly uploading our data to their cloud (but mostly because its annoying to never know where your data is written).
Fixed buf_cvarlist, should work in xonotic now, and without segfaults.
Added an extra arg to URI_Get_Callback calls - the response size, also changed the tempstring to contain all bytes of the response, you need to be careful about nulls though.
Try to work around nvidia's forced-panning bug on x11 when changing video modes. This might screw with other programs.
sdl: support custom icons.
sdl: support choosing a specific display.
Added some documentation to menuqc builtins.
menusys: use outlines for slightly more readable fonts.
menusys: switch vid_width and vid_height combos into a single video mode combo to set both according to reported video modes.
git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5581 fc73d0e0-1445-4013-8a0c-d673dee63da5
2019-11-20 03:09:50 +00:00
qboolean forceformats [ PTI_MAX ] ;
2019-10-14 02:36:13 +00:00
for ( m = 0 ; m < PTI_MAX ; m + + )
Too many changes, sorry.
Change revision displays, use the SVN commit date instead of using __DATE__ (when there's no local changes). This should allow reproducible builds.
Added s_al_disable cvar, to block openal and all the various problems people have had with it, without having to name an explicit fallback (which would vary by system).
Add mastervolume cvar (for ss).
Add r_shadows 2 (aka fake shadows - for ss).
Add scr_loadingscreen_aspect -1 setting, to disable levelshots entirely, also disables the progress bar (for ss).
Better support for some effectinfo hacks (for ss).
Added dpcompat_nocsqcwarnings (because of lazy+buggy mods like ss).
Rework the dpcsqc versions of project+unproject builtins for better compat (for ss).
Added dpcompat_csqcinputeventtypes to block unexpected csqc input events (for ss).
Better compat with DP's loadfont console command (for ss).
Added dpcompat_smallerfonts cvar to replicate a DP bug (for ss).
Detect dp's m_draw extension, to work around it (for ss).
Cvar dpcompat_ignoremodificationtimes added. A value of 0 favour the most recently modified file, 1 will use DP-like alphabetically sorted preferences (for ss).
loadfont builtin can now accept outline=1 in the sizes arg for slightly more readable fonts.
Fix bbox calcs for rotated entities, fix needed for r_ignorenetpvs 0.
Hackily parse emoji.json to provide :poop: etc suggestions.
Skip prediction entirely when there's no local entity info. This fixes stair-smoothing in xonotic.
screenshot_cubemap will now capture half-float images when saving to ktx or dds files.
Fix support for xcf files larger than 4gb, mostly to avoid compiler warnings.
Fixed size of gfx/loading.lmp when replacement textures are used.
Added mipmap support for rg8 and l8a8 textures.
r_hdr_framebuffer cvar updated to support format names instead of random negative numbers. Description updated to name some interesting ones.
Perform autoupdate _checks_ ONLY with explicit user confirmation (actual updating already needed user confirmation, but this extra step should reduce the chances of us getting wrongly accused of exfiltrating user data if we're run in a sandbox - we ONLY ever included the updating engine's version in the checks, though there's nothing we can do to avoid sending the user's router's IP).
Removed the 'summon satan all over your harddrive' quit message, in case paranoid security researchers are idiots and don't bother doing actual research.
Removed the triptohell.info and fte.triptohell.info certificates, they really need to stop being self-signed. The updates domain is still self-signed for autoupdates.
Video drivers are now able to report supported video resolutions, visible to menuqc. Currently only works with SDL2 builds.
Added setmousepos builtin. Should work with glx+win32 build.
VF_SKYROOM_CAMERA can now accept an extra two args, setviewprop(VF_SKYROOM_CAMERA, org, axis, degrees).
Removed v_skyroom_origin+v_skyroom_orientation cvars in favour just v_skyroom, which should make it behave more like the 'fog' command (used when csqc isn't overriding).
Added R_EndPolygonRibbon builtin to make it faster+easier to generate textured ribbon/cable/etc wide lines (for TW).
sdl: Fix up sys_sdl.c's file enumeration to support wildcards in directories.
edit command now displays end1.bin/end2.bin correctly, because we can.
Finally add support for f_modified - though ruleset_allow_larger_models and ruleset_allow_overlong_sounds generally make it redundant.
Fix threading race condition in sha1 lookups.
Updated f_ruleset to include the same extra flags reported by ezquake.
A mod's default.fmf file can now contain an eg 'mainconfig config.cfg' line (to explicitly set the main config saved with cfg_save_auto 1 etc).
fmf: basegame steam:GameName/GameDir can be used to try to load a mod directory from an installed steam game. The resulting gamedir will be read-only.
HOMEDIR CHANGE: use homedirs only if the basedir cannot be written or a homedir already exists, which should further reduce the probability of microsoft randomly uploading our data to their cloud (but mostly because its annoying to never know where your data is written).
Fixed buf_cvarlist, should work in xonotic now, and without segfaults.
Added an extra arg to URI_Get_Callback calls - the response size, also changed the tempstring to contain all bytes of the response, you need to be careful about nulls though.
Try to work around nvidia's forced-panning bug on x11 when changing video modes. This might screw with other programs.
sdl: support custom icons.
sdl: support choosing a specific display.
Added some documentation to menuqc builtins.
menusys: use outlines for slightly more readable fonts.
menusys: switch vid_width and vid_height combos into a single video mode combo to set both according to reported video modes.
git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5581 fc73d0e0-1445-4013-8a0c-d673dee63da5
2019-11-20 03:09:50 +00:00
forceformats [ m ] = ( m = = targfmt ) ;
Image_ChangeFormat ( mips , forceformats , PTI_INVALID , inname ) ;
2019-10-14 02:36:13 +00:00
if ( mips - > encoding = = targfmt )
return true ;
//switch to common formats...
for ( m = 0 ; m < PTI_MAX ; m + + )
2020-03-07 09:00:40 +00:00
forceformats [ m ] = ( m = = targfmt ) | | ( m = = PTI_RGBA8 ) | | ( m = = PTI_RGBA32F ) ;
Too many changes, sorry.
Change revision displays, use the SVN commit date instead of using __DATE__ (when there's no local changes). This should allow reproducible builds.
Added s_al_disable cvar, to block openal and all the various problems people have had with it, without having to name an explicit fallback (which would vary by system).
Add mastervolume cvar (for ss).
Add r_shadows 2 (aka fake shadows - for ss).
Add scr_loadingscreen_aspect -1 setting, to disable levelshots entirely, also disables the progress bar (for ss).
Better support for some effectinfo hacks (for ss).
Added dpcompat_nocsqcwarnings (because of lazy+buggy mods like ss).
Rework the dpcsqc versions of project+unproject builtins for better compat (for ss).
Added dpcompat_csqcinputeventtypes to block unexpected csqc input events (for ss).
Better compat with DP's loadfont console command (for ss).
Added dpcompat_smallerfonts cvar to replicate a DP bug (for ss).
Detect dp's m_draw extension, to work around it (for ss).
Cvar dpcompat_ignoremodificationtimes added. A value of 0 favour the most recently modified file, 1 will use DP-like alphabetically sorted preferences (for ss).
loadfont builtin can now accept outline=1 in the sizes arg for slightly more readable fonts.
Fix bbox calcs for rotated entities, fix needed for r_ignorenetpvs 0.
Hackily parse emoji.json to provide :poop: etc suggestions.
Skip prediction entirely when there's no local entity info. This fixes stair-smoothing in xonotic.
screenshot_cubemap will now capture half-float images when saving to ktx or dds files.
Fix support for xcf files larger than 4gb, mostly to avoid compiler warnings.
Fixed size of gfx/loading.lmp when replacement textures are used.
Added mipmap support for rg8 and l8a8 textures.
r_hdr_framebuffer cvar updated to support format names instead of random negative numbers. Description updated to name some interesting ones.
Perform autoupdate _checks_ ONLY with explicit user confirmation (actual updating already needed user confirmation, but this extra step should reduce the chances of us getting wrongly accused of exfiltrating user data if we're run in a sandbox - we ONLY ever included the updating engine's version in the checks, though there's nothing we can do to avoid sending the user's router's IP).
Removed the 'summon satan all over your harddrive' quit message, in case paranoid security researchers are idiots and don't bother doing actual research.
Removed the triptohell.info and fte.triptohell.info certificates, they really need to stop being self-signed. The updates domain is still self-signed for autoupdates.
Video drivers are now able to report supported video resolutions, visible to menuqc. Currently only works with SDL2 builds.
Added setmousepos builtin. Should work with glx+win32 build.
VF_SKYROOM_CAMERA can now accept an extra two args, setviewprop(VF_SKYROOM_CAMERA, org, axis, degrees).
Removed v_skyroom_origin+v_skyroom_orientation cvars in favour just v_skyroom, which should make it behave more like the 'fog' command (used when csqc isn't overriding).
Added R_EndPolygonRibbon builtin to make it faster+easier to generate textured ribbon/cable/etc wide lines (for TW).
sdl: Fix up sys_sdl.c's file enumeration to support wildcards in directories.
edit command now displays end1.bin/end2.bin correctly, because we can.
Finally add support for f_modified - though ruleset_allow_larger_models and ruleset_allow_overlong_sounds generally make it redundant.
Fix threading race condition in sha1 lookups.
Updated f_ruleset to include the same extra flags reported by ezquake.
A mod's default.fmf file can now contain an eg 'mainconfig config.cfg' line (to explicitly set the main config saved with cfg_save_auto 1 etc).
fmf: basegame steam:GameName/GameDir can be used to try to load a mod directory from an installed steam game. The resulting gamedir will be read-only.
HOMEDIR CHANGE: use homedirs only if the basedir cannot be written or a homedir already exists, which should further reduce the probability of microsoft randomly uploading our data to their cloud (but mostly because its annoying to never know where your data is written).
Fixed buf_cvarlist, should work in xonotic now, and without segfaults.
Added an extra arg to URI_Get_Callback calls - the response size, also changed the tempstring to contain all bytes of the response, you need to be careful about nulls though.
Try to work around nvidia's forced-panning bug on x11 when changing video modes. This might screw with other programs.
sdl: support custom icons.
sdl: support choosing a specific display.
Added some documentation to menuqc builtins.
menusys: use outlines for slightly more readable fonts.
menusys: switch vid_width and vid_height combos into a single video mode combo to set both according to reported video modes.
git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5581 fc73d0e0-1445-4013-8a0c-d673dee63da5
2019-11-20 03:09:50 +00:00
Image_ChangeFormat ( mips , forceformats , PTI_INVALID , inname ) ;
2019-10-14 02:36:13 +00:00
//and try again...
for ( m = 0 ; m < PTI_MAX ; m + + )
Too many changes, sorry.
Change revision displays, use the SVN commit date instead of using __DATE__ (when there's no local changes). This should allow reproducible builds.
Added s_al_disable cvar, to block openal and all the various problems people have had with it, without having to name an explicit fallback (which would vary by system).
Add mastervolume cvar (for ss).
Add r_shadows 2 (aka fake shadows - for ss).
Add scr_loadingscreen_aspect -1 setting, to disable levelshots entirely, also disables the progress bar (for ss).
Better support for some effectinfo hacks (for ss).
Added dpcompat_nocsqcwarnings (because of lazy+buggy mods like ss).
Rework the dpcsqc versions of project+unproject builtins for better compat (for ss).
Added dpcompat_csqcinputeventtypes to block unexpected csqc input events (for ss).
Better compat with DP's loadfont console command (for ss).
Added dpcompat_smallerfonts cvar to replicate a DP bug (for ss).
Detect dp's m_draw extension, to work around it (for ss).
Cvar dpcompat_ignoremodificationtimes added. A value of 0 favour the most recently modified file, 1 will use DP-like alphabetically sorted preferences (for ss).
loadfont builtin can now accept outline=1 in the sizes arg for slightly more readable fonts.
Fix bbox calcs for rotated entities, fix needed for r_ignorenetpvs 0.
Hackily parse emoji.json to provide :poop: etc suggestions.
Skip prediction entirely when there's no local entity info. This fixes stair-smoothing in xonotic.
screenshot_cubemap will now capture half-float images when saving to ktx or dds files.
Fix support for xcf files larger than 4gb, mostly to avoid compiler warnings.
Fixed size of gfx/loading.lmp when replacement textures are used.
Added mipmap support for rg8 and l8a8 textures.
r_hdr_framebuffer cvar updated to support format names instead of random negative numbers. Description updated to name some interesting ones.
Perform autoupdate _checks_ ONLY with explicit user confirmation (actual updating already needed user confirmation, but this extra step should reduce the chances of us getting wrongly accused of exfiltrating user data if we're run in a sandbox - we ONLY ever included the updating engine's version in the checks, though there's nothing we can do to avoid sending the user's router's IP).
Removed the 'summon satan all over your harddrive' quit message, in case paranoid security researchers are idiots and don't bother doing actual research.
Removed the triptohell.info and fte.triptohell.info certificates, they really need to stop being self-signed. The updates domain is still self-signed for autoupdates.
Video drivers are now able to report supported video resolutions, visible to menuqc. Currently only works with SDL2 builds.
Added setmousepos builtin. Should work with glx+win32 build.
VF_SKYROOM_CAMERA can now accept an extra two args, setviewprop(VF_SKYROOM_CAMERA, org, axis, degrees).
Removed v_skyroom_origin+v_skyroom_orientation cvars in favour just v_skyroom, which should make it behave more like the 'fog' command (used when csqc isn't overriding).
Added R_EndPolygonRibbon builtin to make it faster+easier to generate textured ribbon/cable/etc wide lines (for TW).
sdl: Fix up sys_sdl.c's file enumeration to support wildcards in directories.
edit command now displays end1.bin/end2.bin correctly, because we can.
Finally add support for f_modified - though ruleset_allow_larger_models and ruleset_allow_overlong_sounds generally make it redundant.
Fix threading race condition in sha1 lookups.
Updated f_ruleset to include the same extra flags reported by ezquake.
A mod's default.fmf file can now contain an eg 'mainconfig config.cfg' line (to explicitly set the main config saved with cfg_save_auto 1 etc).
fmf: basegame steam:GameName/GameDir can be used to try to load a mod directory from an installed steam game. The resulting gamedir will be read-only.
HOMEDIR CHANGE: use homedirs only if the basedir cannot be written or a homedir already exists, which should further reduce the probability of microsoft randomly uploading our data to their cloud (but mostly because its annoying to never know where your data is written).
Fixed buf_cvarlist, should work in xonotic now, and without segfaults.
Added an extra arg to URI_Get_Callback calls - the response size, also changed the tempstring to contain all bytes of the response, you need to be careful about nulls though.
Try to work around nvidia's forced-panning bug on x11 when changing video modes. This might screw with other programs.
sdl: support custom icons.
sdl: support choosing a specific display.
Added some documentation to menuqc builtins.
menusys: use outlines for slightly more readable fonts.
menusys: switch vid_width and vid_height combos into a single video mode combo to set both according to reported video modes.
git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5581 fc73d0e0-1445-4013-8a0c-d673dee63da5
2019-11-20 03:09:50 +00:00
forceformats [ m ] = ( m = = targfmt ) ;
Image_ChangeFormat ( mips , forceformats , PTI_INVALID , inname ) ;
2019-10-14 02:36:13 +00:00
return ( mips - > encoding = = targfmt ) ;
}
2020-03-07 09:00:40 +00:00
return true ;
2019-10-14 02:36:13 +00:00
}
2019-09-29 03:08:01 +00:00
if ( canktx )
FS_MakeTempName ( raw , sizeof ( raw ) , " itr " , " .ktx " ) ;
else
FS_MakeTempName ( raw , sizeof ( raw ) , " itr " , " .png " ) ;
FS_MakeTempName ( comp , sizeof ( comp ) , " itc " , " .ktx " ) ;
tmp . type = mips - > type ;
tmp . encoding = mips - > encoding ;
tmp . extrafree = NULL ;
tmp . mipcount = 1 ;
2020-04-29 10:43:22 +00:00
Image_BlockSizeForEncoding ( targfmt , & bb , & bw , & bh , & bd ) ;
2019-09-29 03:08:01 +00:00
Q_snprintfz ( command + strlen ( command ) , sizeof ( command ) - strlen ( command ) , " \" %s \" \" %s \" " , raw , comp ) ;
if ( targfmt > = PTI_ASTC_FIRST & & targfmt < = PTI_ASTC_LAST )
2020-04-29 10:43:22 +00:00
{
if ( bd ! = 1 )
Q_snprintfz ( command + strlen ( command ) , sizeof ( command ) - strlen ( command ) , " %ix%ix%i -exhaustive " , bw , bh , bd ) ;
else
Q_snprintfz ( command + strlen ( command ) , sizeof ( command ) - strlen ( command ) , " %ix%i -exhaustive " , bw , bh ) ;
}
2019-09-29 03:08:01 +00:00
if ( targfmt > = PTI_ASTC_4X4_SRGB & & targfmt < = PTI_ASTC_12X12_SRGB )
Q_strncatz ( command , " -srgb " , sizeof ( command ) ) ;
if ( targfmt > = PTI_ASTC_4X4_HDR & & targfmt < = PTI_ASTC_12X12_HDR )
Q_strncatz ( command , " -hdr " , sizeof ( command ) ) ;
2019-10-06 01:59:13 +00:00
if ( targfmt > = PTI_BC1_RGB & & targfmt < = PTI_BC7_RGBA_SRGB & & ( strstr ( inname , " _n. " ) | | strstr ( inname , " _norm. " ) ) )
Q_strncatz ( command , " -normal " , sizeof ( command ) ) ; //looks like a normalmap... tweak metrics to favour normalised results.
2019-09-29 03:08:01 +00:00
2020-01-10 12:23:25 +00:00
# ifdef _WIN32
Q_strncatz ( command , " > NUL 2>&1 " , sizeof ( command ) ) ;
# else
Q_strncatz ( command , " >> /dev/null " , sizeof ( command ) ) ;
# endif
2019-10-14 02:36:13 +00:00
if ( ! canktx )
{
Too many changes, sorry.
Change revision displays, use the SVN commit date instead of using __DATE__ (when there's no local changes). This should allow reproducible builds.
Added s_al_disable cvar, to block openal and all the various problems people have had with it, without having to name an explicit fallback (which would vary by system).
Add mastervolume cvar (for ss).
Add r_shadows 2 (aka fake shadows - for ss).
Add scr_loadingscreen_aspect -1 setting, to disable levelshots entirely, also disables the progress bar (for ss).
Better support for some effectinfo hacks (for ss).
Added dpcompat_nocsqcwarnings (because of lazy+buggy mods like ss).
Rework the dpcsqc versions of project+unproject builtins for better compat (for ss).
Added dpcompat_csqcinputeventtypes to block unexpected csqc input events (for ss).
Better compat with DP's loadfont console command (for ss).
Added dpcompat_smallerfonts cvar to replicate a DP bug (for ss).
Detect dp's m_draw extension, to work around it (for ss).
Cvar dpcompat_ignoremodificationtimes added. A value of 0 favour the most recently modified file, 1 will use DP-like alphabetically sorted preferences (for ss).
loadfont builtin can now accept outline=1 in the sizes arg for slightly more readable fonts.
Fix bbox calcs for rotated entities, fix needed for r_ignorenetpvs 0.
Hackily parse emoji.json to provide :poop: etc suggestions.
Skip prediction entirely when there's no local entity info. This fixes stair-smoothing in xonotic.
screenshot_cubemap will now capture half-float images when saving to ktx or dds files.
Fix support for xcf files larger than 4gb, mostly to avoid compiler warnings.
Fixed size of gfx/loading.lmp when replacement textures are used.
Added mipmap support for rg8 and l8a8 textures.
r_hdr_framebuffer cvar updated to support format names instead of random negative numbers. Description updated to name some interesting ones.
Perform autoupdate _checks_ ONLY with explicit user confirmation (actual updating already needed user confirmation, but this extra step should reduce the chances of us getting wrongly accused of exfiltrating user data if we're run in a sandbox - we ONLY ever included the updating engine's version in the checks, though there's nothing we can do to avoid sending the user's router's IP).
Removed the 'summon satan all over your harddrive' quit message, in case paranoid security researchers are idiots and don't bother doing actual research.
Removed the triptohell.info and fte.triptohell.info certificates, they really need to stop being self-signed. The updates domain is still self-signed for autoupdates.
Video drivers are now able to report supported video resolutions, visible to menuqc. Currently only works with SDL2 builds.
Added setmousepos builtin. Should work with glx+win32 build.
VF_SKYROOM_CAMERA can now accept an extra two args, setviewprop(VF_SKYROOM_CAMERA, org, axis, degrees).
Removed v_skyroom_origin+v_skyroom_orientation cvars in favour just v_skyroom, which should make it behave more like the 'fog' command (used when csqc isn't overriding).
Added R_EndPolygonRibbon builtin to make it faster+easier to generate textured ribbon/cable/etc wide lines (for TW).
sdl: Fix up sys_sdl.c's file enumeration to support wildcards in directories.
edit command now displays end1.bin/end2.bin correctly, because we can.
Finally add support for f_modified - though ruleset_allow_larger_models and ruleset_allow_overlong_sounds generally make it redundant.
Fix threading race condition in sha1 lookups.
Updated f_ruleset to include the same extra flags reported by ezquake.
A mod's default.fmf file can now contain an eg 'mainconfig config.cfg' line (to explicitly set the main config saved with cfg_save_auto 1 etc).
fmf: basegame steam:GameName/GameDir can be used to try to load a mod directory from an installed steam game. The resulting gamedir will be read-only.
HOMEDIR CHANGE: use homedirs only if the basedir cannot be written or a homedir already exists, which should further reduce the probability of microsoft randomly uploading our data to their cloud (but mostly because its annoying to never know where your data is written).
Fixed buf_cvarlist, should work in xonotic now, and without segfaults.
Added an extra arg to URI_Get_Callback calls - the response size, also changed the tempstring to contain all bytes of the response, you need to be careful about nulls though.
Try to work around nvidia's forced-panning bug on x11 when changing video modes. This might screw with other programs.
sdl: support custom icons.
sdl: support choosing a specific display.
Added some documentation to menuqc builtins.
menusys: use outlines for slightly more readable fonts.
menusys: switch vid_width and vid_height combos into a single video mode combo to set both according to reported video modes.
git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5581 fc73d0e0-1445-4013-8a0c-d673dee63da5
2019-11-20 03:09:50 +00:00
qboolean allowformats [ PTI_MAX ] ;
2019-10-14 02:36:13 +00:00
//make sure the source pixel format is acceptable if we're forced to write a png
for ( m = 0 ; m < PTI_MAX ; m + + )
Too many changes, sorry.
Change revision displays, use the SVN commit date instead of using __DATE__ (when there's no local changes). This should allow reproducible builds.
Added s_al_disable cvar, to block openal and all the various problems people have had with it, without having to name an explicit fallback (which would vary by system).
Add mastervolume cvar (for ss).
Add r_shadows 2 (aka fake shadows - for ss).
Add scr_loadingscreen_aspect -1 setting, to disable levelshots entirely, also disables the progress bar (for ss).
Better support for some effectinfo hacks (for ss).
Added dpcompat_nocsqcwarnings (because of lazy+buggy mods like ss).
Rework the dpcsqc versions of project+unproject builtins for better compat (for ss).
Added dpcompat_csqcinputeventtypes to block unexpected csqc input events (for ss).
Better compat with DP's loadfont console command (for ss).
Added dpcompat_smallerfonts cvar to replicate a DP bug (for ss).
Detect dp's m_draw extension, to work around it (for ss).
Cvar dpcompat_ignoremodificationtimes added. A value of 0 favour the most recently modified file, 1 will use DP-like alphabetically sorted preferences (for ss).
loadfont builtin can now accept outline=1 in the sizes arg for slightly more readable fonts.
Fix bbox calcs for rotated entities, fix needed for r_ignorenetpvs 0.
Hackily parse emoji.json to provide :poop: etc suggestions.
Skip prediction entirely when there's no local entity info. This fixes stair-smoothing in xonotic.
screenshot_cubemap will now capture half-float images when saving to ktx or dds files.
Fix support for xcf files larger than 4gb, mostly to avoid compiler warnings.
Fixed size of gfx/loading.lmp when replacement textures are used.
Added mipmap support for rg8 and l8a8 textures.
r_hdr_framebuffer cvar updated to support format names instead of random negative numbers. Description updated to name some interesting ones.
Perform autoupdate _checks_ ONLY with explicit user confirmation (actual updating already needed user confirmation, but this extra step should reduce the chances of us getting wrongly accused of exfiltrating user data if we're run in a sandbox - we ONLY ever included the updating engine's version in the checks, though there's nothing we can do to avoid sending the user's router's IP).
Removed the 'summon satan all over your harddrive' quit message, in case paranoid security researchers are idiots and don't bother doing actual research.
Removed the triptohell.info and fte.triptohell.info certificates, they really need to stop being self-signed. The updates domain is still self-signed for autoupdates.
Video drivers are now able to report supported video resolutions, visible to menuqc. Currently only works with SDL2 builds.
Added setmousepos builtin. Should work with glx+win32 build.
VF_SKYROOM_CAMERA can now accept an extra two args, setviewprop(VF_SKYROOM_CAMERA, org, axis, degrees).
Removed v_skyroom_origin+v_skyroom_orientation cvars in favour just v_skyroom, which should make it behave more like the 'fog' command (used when csqc isn't overriding).
Added R_EndPolygonRibbon builtin to make it faster+easier to generate textured ribbon/cable/etc wide lines (for TW).
sdl: Fix up sys_sdl.c's file enumeration to support wildcards in directories.
edit command now displays end1.bin/end2.bin correctly, because we can.
Finally add support for f_modified - though ruleset_allow_larger_models and ruleset_allow_overlong_sounds generally make it redundant.
Fix threading race condition in sha1 lookups.
Updated f_ruleset to include the same extra flags reported by ezquake.
A mod's default.fmf file can now contain an eg 'mainconfig config.cfg' line (to explicitly set the main config saved with cfg_save_auto 1 etc).
fmf: basegame steam:GameName/GameDir can be used to try to load a mod directory from an installed steam game. The resulting gamedir will be read-only.
HOMEDIR CHANGE: use homedirs only if the basedir cannot be written or a homedir already exists, which should further reduce the probability of microsoft randomly uploading our data to their cloud (but mostly because its annoying to never know where your data is written).
Fixed buf_cvarlist, should work in xonotic now, and without segfaults.
Added an extra arg to URI_Get_Callback calls - the response size, also changed the tempstring to contain all bytes of the response, you need to be careful about nulls though.
Try to work around nvidia's forced-panning bug on x11 when changing video modes. This might screw with other programs.
sdl: support custom icons.
sdl: support choosing a specific display.
Added some documentation to menuqc builtins.
menusys: use outlines for slightly more readable fonts.
menusys: switch vid_width and vid_height combos into a single video mode combo to set both according to reported video modes.
git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5581 fc73d0e0-1445-4013-8a0c-d673dee63da5
2019-11-20 03:09:50 +00:00
allowformats [ m ] =
2019-10-14 02:36:13 +00:00
( m = = PTI_RGBA8 ) | | ( m = = PTI_RGBX8 ) | |
( m = = PTI_BGRA8 ) | | ( m = = PTI_BGRX8 ) | |
( m = = PTI_LLLA8 ) | | ( m = = PTI_LLLX8 ) | |
( m = = PTI_RGBA16 ) | |
( m = = PTI_L8 ) | | ( m = = PTI_L8A8 ) | |
/*(m == PTI_L16) ||*/
( m = = PTI_BGR8 ) | | ( m = = PTI_BGR8 ) | |
0 ;
Too many changes, sorry.
Change revision displays, use the SVN commit date instead of using __DATE__ (when there's no local changes). This should allow reproducible builds.
Added s_al_disable cvar, to block openal and all the various problems people have had with it, without having to name an explicit fallback (which would vary by system).
Add mastervolume cvar (for ss).
Add r_shadows 2 (aka fake shadows - for ss).
Add scr_loadingscreen_aspect -1 setting, to disable levelshots entirely, also disables the progress bar (for ss).
Better support for some effectinfo hacks (for ss).
Added dpcompat_nocsqcwarnings (because of lazy+buggy mods like ss).
Rework the dpcsqc versions of project+unproject builtins for better compat (for ss).
Added dpcompat_csqcinputeventtypes to block unexpected csqc input events (for ss).
Better compat with DP's loadfont console command (for ss).
Added dpcompat_smallerfonts cvar to replicate a DP bug (for ss).
Detect dp's m_draw extension, to work around it (for ss).
Cvar dpcompat_ignoremodificationtimes added. A value of 0 favour the most recently modified file, 1 will use DP-like alphabetically sorted preferences (for ss).
loadfont builtin can now accept outline=1 in the sizes arg for slightly more readable fonts.
Fix bbox calcs for rotated entities, fix needed for r_ignorenetpvs 0.
Hackily parse emoji.json to provide :poop: etc suggestions.
Skip prediction entirely when there's no local entity info. This fixes stair-smoothing in xonotic.
screenshot_cubemap will now capture half-float images when saving to ktx or dds files.
Fix support for xcf files larger than 4gb, mostly to avoid compiler warnings.
Fixed size of gfx/loading.lmp when replacement textures are used.
Added mipmap support for rg8 and l8a8 textures.
r_hdr_framebuffer cvar updated to support format names instead of random negative numbers. Description updated to name some interesting ones.
Perform autoupdate _checks_ ONLY with explicit user confirmation (actual updating already needed user confirmation, but this extra step should reduce the chances of us getting wrongly accused of exfiltrating user data if we're run in a sandbox - we ONLY ever included the updating engine's version in the checks, though there's nothing we can do to avoid sending the user's router's IP).
Removed the 'summon satan all over your harddrive' quit message, in case paranoid security researchers are idiots and don't bother doing actual research.
Removed the triptohell.info and fte.triptohell.info certificates, they really need to stop being self-signed. The updates domain is still self-signed for autoupdates.
Video drivers are now able to report supported video resolutions, visible to menuqc. Currently only works with SDL2 builds.
Added setmousepos builtin. Should work with glx+win32 build.
VF_SKYROOM_CAMERA can now accept an extra two args, setviewprop(VF_SKYROOM_CAMERA, org, axis, degrees).
Removed v_skyroom_origin+v_skyroom_orientation cvars in favour just v_skyroom, which should make it behave more like the 'fog' command (used when csqc isn't overriding).
Added R_EndPolygonRibbon builtin to make it faster+easier to generate textured ribbon/cable/etc wide lines (for TW).
sdl: Fix up sys_sdl.c's file enumeration to support wildcards in directories.
edit command now displays end1.bin/end2.bin correctly, because we can.
Finally add support for f_modified - though ruleset_allow_larger_models and ruleset_allow_overlong_sounds generally make it redundant.
Fix threading race condition in sha1 lookups.
Updated f_ruleset to include the same extra flags reported by ezquake.
A mod's default.fmf file can now contain an eg 'mainconfig config.cfg' line (to explicitly set the main config saved with cfg_save_auto 1 etc).
fmf: basegame steam:GameName/GameDir can be used to try to load a mod directory from an installed steam game. The resulting gamedir will be read-only.
HOMEDIR CHANGE: use homedirs only if the basedir cannot be written or a homedir already exists, which should further reduce the probability of microsoft randomly uploading our data to their cloud (but mostly because its annoying to never know where your data is written).
Fixed buf_cvarlist, should work in xonotic now, and without segfaults.
Added an extra arg to URI_Get_Callback calls - the response size, also changed the tempstring to contain all bytes of the response, you need to be careful about nulls though.
Try to work around nvidia's forced-panning bug on x11 when changing video modes. This might screw with other programs.
sdl: support custom icons.
sdl: support choosing a specific display.
Added some documentation to menuqc builtins.
menusys: use outlines for slightly more readable fonts.
menusys: switch vid_width and vid_height combos into a single video mode combo to set both according to reported video modes.
git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5581 fc73d0e0-1445-4013-8a0c-d673dee63da5
2019-11-20 03:09:50 +00:00
Image_ChangeFormat ( mips , allowformats , PTI_INVALID , inname ) ;
2019-10-14 02:36:13 +00:00
}
2020-03-07 09:00:40 +00:00
// Con_Printf("%s: Compressing %u mips\n", inname, mips->mipcount);
2020-04-29 10:43:22 +00:00
Image_BlockSizeForEncoding ( mips - > encoding , & bb , & bw , & bh , & bd ) ;
2019-09-29 03:08:01 +00:00
for ( m = 0 ; m < mips - > mipcount ; m + + )
{
2019-10-18 08:37:38 +00:00
qbyte * srcdata = mips - > mip [ m ] . data ;
size_t srcsize = mips - > mip [ m ] . datasize ;
if ( mips - > type = = PTI_3D )
2019-09-29 03:08:01 +00:00
{
2019-10-18 08:37:38 +00:00
layers = 1 ;
d = mips - > mip [ m ] . depth ;
tmp . type = PTI_2D ;
2019-09-29 03:08:01 +00:00
}
else
{
2019-10-18 08:37:38 +00:00
layers = mips - > mip [ m ] . depth ;
d = 1 ;
tmp . type = PTI_2D ;
2019-09-29 03:08:01 +00:00
}
2019-10-18 08:37:38 +00:00
for ( l = 0 ; l < layers ; l + + )
{
2020-03-07 09:00:40 +00:00
// Con_DPrintf("Compressing %s mip %u, layer %u\n", inname, (unsigned)m, l);
2019-10-18 08:37:38 +00:00
tmp . mip [ 0 ] = mips - > mip [ m ] ;
tmp . mip [ 0 ] . needfree = false ;
tmp . mip [ 0 ] . depth = d ;
tmp . mip [ 0 ] . datasize = srcsize / layers ;
tmp . mip [ 0 ] . data = srcdata + l * tmp . mip [ 0 ] . datasize ;
( void ) tmp ;
if ( canktx )
{
# ifdef IMAGEFMT_KTX
if ( ! Image_WriteKTXFile ( raw , FS_SYSTEM , & tmp ) )
# endif
break ;
}
else
{
# ifdef AVAIL_PNGLIB
if ( ! Image_WritePNG ( raw , FS_SYSTEM , 0 , & tmp . mip [ 0 ] . data , 1 , tmp . mip [ 0 ] . width * bb , tmp . mip [ 0 ] . width , tmp . mip [ 0 ] . height , tmp . encoding , false ) )
# endif
break ;
}
2019-09-29 03:08:01 +00:00
2020-01-10 12:23:25 +00:00
r = system ( command ) ;
if ( r ! = EXIT_SUCCESS )
{
Con_Printf ( " The following system command failed with code %i: %s \n " , r , command ) ;
break ;
}
2019-09-29 03:08:01 +00:00
2019-10-18 08:37:38 +00:00
fdata = FS_LoadMallocFile ( comp , & fsize ) ;
ret = Image_LoadMipsFromMemory ( IF_NOMIPMAP , comp , comp , fdata , fsize ) ;
if ( ret & & ret - > mip [ 0 ] . width = = mips - > mip [ m ] . width & &
ret - > mip [ 0 ] . height = = mips - > mip [ m ] . height & &
ret - > mip [ 0 ] . depth = = d & &
ImgTool_ASTCToLDR ( ret - > encoding ) = = ImgTool_ASTCToLDR ( targfmt ) )
{
if ( layers = = 1 ) //just copy it over. FIXME: memory leak
mips - > mip [ m ] = ret - > mip [ 0 ] ;
else
{
if ( ! l )
{
mips - > mip [ m ] . datasize = ret - > mip [ 0 ] . datasize * layers ;
mips - > mip [ m ] . data = BZ_Malloc ( mips - > mip [ m ] . datasize ) ;
mips - > mip [ m ] . needfree = true ;
}
else if ( ret - > mip [ 0 ] . datasize ! = mips - > mip [ m ] . datasize / layers )
break ; //erk..?
2019-12-10 14:50:47 +00:00
memcpy ( ( qbyte * ) mips - > mip [ m ] . data + l * ret - > mip [ 0 ] . datasize , ret - > mip [ 0 ] . data , ret - > mip [ 0 ] . datasize ) ;
2019-10-18 08:37:38 +00:00
}
continue ;
}
2020-03-07 09:00:40 +00:00
else if ( ! ret )
Con_Printf ( " Failed to read intermediate file %s \n " , comp ) ;
else
Con_Printf ( " intermediate file %s has unexpected size/depth/format %s:%i*%i*%i vs %s:%i*%i*%i \n " , comp ,
Image_FormatName ( ret - > encoding ) , ret - > mip [ 0 ] . width , ret - > mip [ 0 ] . height , ret - > mip [ 0 ] . depth ,
Image_FormatName ( targfmt ) , mips - > mip [ m ] . width , mips - > mip [ m ] . height , d ) ;
2019-10-18 08:37:38 +00:00
break ;
2019-09-29 03:08:01 +00:00
}
2019-10-18 08:37:38 +00:00
if ( l ! = layers )
break ;
2019-09-29 03:08:01 +00:00
}
mips - > encoding = targfmt ;
mips - > mipcount = m ;
if ( mips - > mipcount & & targfmt > = PTI_BC1_RGB & & targfmt < = PTI_BC7_RGBA_SRGB )
{ //d3d has some annoying limitations.
//do not warn for astc files, their block sizes are too weird.
2020-04-29 10:43:22 +00:00
Image_BlockSizeForEncoding ( targfmt , & bb , & bw , & bh , & bd ) ;
if ( mips - > mip [ 0 ] . width % bw | | mips - > mip [ 0 ] . height % bh | | mips - > mip [ 0 ] . depth % bd )
2019-10-06 01:59:13 +00:00
Con_Printf ( " %s: mip0 of %i*%i is not a multiple of %i*%i (d3d warning) \n " , inname , mips - > mip [ 0 ] . width , mips - > mip [ 0 ] . height , bw , bh ) ;
2019-09-29 03:08:01 +00:00
}
2019-10-06 01:59:13 +00:00
FS_Remove ( raw , FS_SYSTEM ) ;
FS_Remove ( comp , FS_SYSTEM ) ;
return true ;
2019-09-29 03:08:01 +00:00
}
const char * COM_GetFileExtension ( const char * in , const char * term )
{
const char * dot ;
if ( ! term )
term = in + strlen ( in ) ;
for ( dot = term - 1 ; dot > = in & & * dot ! = ' / ' & & * dot ! = ' \\ ' ; dot - - )
{
if ( * dot = = ' . ' )
return dot ;
}
2020-01-10 12:23:25 +00:00
return term + strlen ( term ) ;
2019-09-29 03:08:01 +00:00
}
2019-10-18 08:37:38 +00:00
static struct pendingtextureinfo * ImgTool_Read ( struct opts_s * args , const char * inname )
2019-09-29 03:08:01 +00:00
{
qbyte * indata ;
2019-10-18 08:37:38 +00:00
size_t fsize ;
2019-09-29 03:08:01 +00:00
struct pendingtextureinfo * in ;
2019-10-18 08:37:38 +00:00
indata = FS_LoadMallocFile ( inname , & fsize ) ;
if ( ! indata )
2020-03-07 09:00:40 +00:00
Con_Printf ( " %s: unable to read \n " , inname ) ;
2019-10-18 08:37:38 +00:00
else
{
2020-03-07 09:00:40 +00:00
const char * ex = COM_GetFileExtension ( inname , NULL ) ;
if ( ! strcasecmp ( ex , " .mip " ) )
2020-08-18 01:59:55 +00:00
in = ImgTool_DecodeMiptex ( args , ( miptex_t * ) indata , fsize ) ;
2020-03-07 09:00:40 +00:00
else
in = Image_LoadMipsFromMemory ( args - > flags | IF_NOMIPMAP , inname , inname , indata , fsize ) ;
2019-10-18 08:37:38 +00:00
if ( ! in )
{
2020-03-07 09:00:40 +00:00
Con_Printf ( " %s: unsupported format \n " , inname ) ;
2019-10-18 08:37:38 +00:00
BZ_Free ( indata ) ;
}
else
{
2020-03-07 09:00:40 +00:00
Con_DPrintf ( " %s: %s %s, %i*%i, %i mips \n " , inname , imagetypename [ in - > type ] , Image_FormatName ( in - > encoding ) , in - > mip [ 0 ] . width , in - > mip [ 0 ] . height , in - > mipcount ) ;
2019-10-18 08:37:38 +00:00
return in ;
}
}
return NULL ;
}
static struct pendingtextureinfo * ImgTool_Combine ( struct opts_s * args , const char * * namelist , unsigned int filecount )
{
struct pendingtextureinfo * r , * t ;
unsigned int i ;
unsigned int layers = 0 ;
unsigned int j = 0 ;
2019-10-06 01:59:13 +00:00
2019-10-18 08:37:38 +00:00
struct
{
const char * fname ;
struct pendingtextureinfo * in ;
} * srcs , * tmpsrcs ;
2019-09-29 03:08:01 +00:00
2019-10-18 08:37:38 +00:00
if ( args - > textype = = PTI_3D )
args - > flags | = IF_NOMIPMAP ; //generate any mipmaps after...
srcs = alloca ( sizeof ( * srcs ) * filecount ) ;
for ( i = 0 , j = 0 ; i < filecount ; i + + )
2019-09-29 03:08:01 +00:00
{
2019-10-18 08:37:38 +00:00
srcs [ j ] . in = t = ImgTool_Read ( args , namelist [ i ] ) ;
if ( srcs [ j ] . in )
2019-09-29 03:08:01 +00:00
{
2019-10-18 08:37:38 +00:00
if ( ! j )
{
//get the image loader to massage pixel formats...
memset ( sh_config . texfmt , 0 , sizeof ( sh_config . texfmt ) ) ;
sh_config . texfmt [ srcs [ j ] . in - > encoding ] = true ;
}
else if ( ! t - > mipcount | | ! t - > mip [ 0 ] . data )
{
Con_Printf ( " %s: no valid image data \n " , namelist [ i ] ) ;
ImgTool_FreeMips ( srcs [ j ] . in ) ;
continue ;
}
else if ( t - > encoding ! = srcs [ 0 ] . in - > encoding )
{
Con_Printf ( " %s: mismatched pixel format, (%s not %s) cannot combine \n " , namelist [ i ] , Image_FormatName ( t - > encoding ) , Image_FormatName ( srcs [ 0 ] . in - > encoding ) ) ;
ImgTool_FreeMips ( srcs [ j ] . in ) ;
continue ;
}
else if ( t - > type = = PTI_CUBE & & t - > mip [ 0 ] . depth ! = 6 )
{
Con_Printf ( " %s: incorrect cubemap data \n " , namelist [ i ] ) ;
ImgTool_FreeMips ( srcs [ j ] . in ) ;
continue ;
}
else if ( srcs [ 0 ] . in - > mip [ 0 ] . width ! = t - > mip [ 0 ] . width | | srcs [ 0 ] . in - > mip [ 0 ] . height ! = t - > mip [ 0 ] . height )
{
Con_Printf ( " %s: incorrect image size \n " , namelist [ i ] ) ;
ImgTool_FreeMips ( srcs [ j ] . in ) ;
continue ;
}
else if ( t - > mip [ 0 ] . depth = = 0 )
{
Con_Printf ( " %s: no layers \n " , namelist [ i ] ) ;
ImgTool_FreeMips ( srcs [ j ] . in ) ;
continue ;
}
layers + = t - > mip [ 0 ] . depth ;
srcs [ j + + ] . fname = namelist [ i ] ;
}
}
filecount = j ;
2019-09-29 03:08:01 +00:00
2019-10-18 08:37:38 +00:00
//FIXME: reorder input images to handle ft/bk/lt/rt/up/dn, and flip+rotate+etc to match quake
2019-10-14 02:36:13 +00:00
2019-10-18 08:37:38 +00:00
if ( args - > textype = = PTI_CUBE )
{
int facetype [ 6 ] ;
static const struct { qboolean flipx , flipy , flipd ; } skyboxflips [ ] = {
{ true , false , true } ,
{ false , true , true } ,
{ true , true , false } ,
{ false , false , false } ,
{ true , false , true } ,
{ true , false , true }
} ;
for ( i = 0 ; i < 6 ; i + + )
facetype [ i ] = 0 ;
for ( i = 0 ; i < filecount ; i + + )
{
const char * ex = COM_GetFileExtension ( srcs [ i ] . fname , NULL ) ;
if ( ex & & ex - srcs [ i ] . fname > 2 & & srcs [ i ] . in - > mip [ 0 ] . depth = = 1 )
2019-10-14 02:36:13 +00:00
{
2019-10-18 08:37:38 +00:00
if ( ! strncasecmp ( ex - 2 , " rt " , 2 ) )
facetype [ 0 ] = - i - 1 ;
else if ( ! strncasecmp ( ex - 2 , " lf " , 2 ) )
facetype [ 1 ] = - i - 1 ;
else if ( ! strncasecmp ( ex - 2 , " ft " , 2 ) )
facetype [ 2 ] = - i - 1 ;
else if ( ! strncasecmp ( ex - 2 , " bk " , 2 ) )
facetype [ 3 ] = - i - 1 ;
else if ( ! strncasecmp ( ex - 2 , " up " , 2 ) )
facetype [ 4 ] = - i - 1 ;
else if ( ! strncasecmp ( ex - 2 , " dn " , 2 ) )
facetype [ 5 ] = - i - 1 ;
else if ( ! strncasecmp ( ex - 2 , " px " , 2 ) )
facetype [ 0 ] = i + 1 ;
else if ( ! strncasecmp ( ex - 2 , " nx " , 2 ) )
facetype [ 1 ] = i + 1 ;
else if ( ! strncasecmp ( ex - 2 , " py " , 2 ) )
facetype [ 2 ] = i + 1 ;
else if ( ! strncasecmp ( ex - 2 , " ny " , 2 ) )
facetype [ 3 ] = i + 1 ;
else if ( ! strncasecmp ( ex - 2 , " pz " , 2 ) )
facetype [ 4 ] = i + 1 ;
else if ( ! strncasecmp ( ex - 2 , " nz " , 2 ) )
facetype [ 5 ] = i + 1 ;
2019-10-14 02:36:13 +00:00
}
2019-10-18 08:37:38 +00:00
}
if ( facetype [ 0 ] & & facetype [ 1 ] & & facetype [ 2 ] & & facetype [ 3 ] & & facetype [ 4 ] & & facetype [ 5 ] )
{
Con_Printf ( " Reordering images to match cubemap \n " ) ;
tmpsrcs = alloca ( sizeof ( * tmpsrcs ) * filecount ) ;
memcpy ( tmpsrcs , srcs , sizeof ( * tmpsrcs ) * filecount ) ;
for ( i = 0 ; i < 6 ; i + + )
2019-10-14 02:36:13 +00:00
{
2019-10-18 08:37:38 +00:00
if ( facetype [ i ] < 0 )
{ //flip to match legacy skyboxes
2020-04-29 10:43:22 +00:00
unsigned bb , bw , bh , bd ;
2019-10-18 08:37:38 +00:00
srcs [ i ] = tmpsrcs [ - facetype [ i ] - 1 ] ;
t = srcs [ i ] . in ;
2020-04-29 10:43:22 +00:00
Image_BlockSizeForEncoding ( t - > encoding , & bb , & bw , & bh , & bd ) ;
if ( bw = = 1 & & bh = = 1 & & bd = = 1 )
2019-10-18 08:37:38 +00:00
{
for ( j = 0 ; j < t - > mipcount ; j + + )
{
void * data = Image_FlipImage ( t - > mip [ j ] . data , BZ_Malloc ( t - > mip [ j ] . datasize ) , & t - > mip [ j ] . width , & t - > mip [ j ] . height , bb , skyboxflips [ i ] . flipx , skyboxflips [ i ] . flipy , skyboxflips [ i ] . flipd ) ;
if ( t - > mip [ j ] . needfree )
Z_Free ( t - > mip [ j ] . data ) ;
t - > mip [ j ] . data = data ;
t - > mip [ j ] . needfree = true ;
}
}
}
else
srcs [ i ] = tmpsrcs [ facetype [ i ] - 1 ] ;
2019-09-29 03:08:01 +00:00
}
2019-10-18 08:37:38 +00:00
}
else
Con_Printf ( " WARNING: Cubemap ordering unknown! \n " ) ;
}
2019-10-14 02:36:13 +00:00
2019-10-18 08:37:38 +00:00
if ( ! filecount )
Con_Printf ( " no valid input files \n " ) ;
else if ( ! layers )
Con_Printf ( " Images must have at least one layer \n " ) ;
else if ( args - > textype = = PTI_2D & & layers ! = 1 )
Con_Printf ( " 2D images must have one layer exactly, sorry \n " ) ;
else if ( args - > textype = = PTI_CUBE & & layers ! = 6 )
Con_Printf ( " Cubemaps must have 6 layers exactly \n " ) ;
else if ( args - > textype = = PTI_CUBE_ARRAY & & layers % 6 )
Con_Printf ( " Cubemap arrays must have a multiple of 6 layers exactly \n " ) ;
else
{
t = srcs [ 0 ] . in ;
r = Z_Malloc ( sizeof ( * t ) ) ;
r - > type = args - > textype ;
r - > extrafree = NULL ;
r - > encoding = t - > encoding ;
if ( args - > textype = = PTI_3D )
r - > mipcount = 1 ;
else
r - > mipcount = t - > mipcount ;
for ( j = 0 ; j < t - > mipcount ; j + + )
{
r - > mip [ j ] . datasize = t - > mip [ j ] . datasize * layers ;
r - > mip [ j ] . width = t - > mip [ j ] . width ;
r - > mip [ j ] . height = t - > mip [ j ] . height ;
r - > mip [ j ] . depth = 0 ;
r - > mip [ j ] . needfree = true ;
r - > mip [ j ] . data = BZ_Malloc ( r - > mip [ j ] . datasize ) ;
}
2019-09-29 03:08:01 +00:00
2019-10-18 08:37:38 +00:00
for ( i = 0 , j = 0 ; i < filecount ; i + + )
{
t = srcs [ i ] . in ;
if ( ! t )
2019-09-29 03:08:01 +00:00
{
2019-10-18 08:37:38 +00:00
ImgTool_FreeMips ( r ) ;
return NULL ;
2019-09-29 03:08:01 +00:00
}
2019-10-18 08:37:38 +00:00
for ( j = 0 ; j < r - > mipcount ; j + + )
2019-10-14 02:36:13 +00:00
{
2019-10-18 08:37:38 +00:00
if ( r - > mip [ j ] . width ! = t - > mip [ j ] . width | | r - > mip [ j ] . height ! = t - > mip [ j ] . height | | t - > mip [ j ] . depth ! = 1 )
{
Con_Printf ( " %s: mismatched mipmap sizes \n " , namelist [ i ] ) ;
continue ;
}
2019-12-10 14:50:47 +00:00
memcpy ( ( qbyte * ) r - > mip [ j ] . data + t - > mip [ j ] . datasize * r - > mip [ j ] . depth , t - > mip [ j ] . data , t - > mip [ j ] . datasize ) ;
2019-10-18 08:37:38 +00:00
r - > mip [ j ] . depth + + ;
2019-10-14 02:36:13 +00:00
}
2019-10-18 08:37:38 +00:00
}
for ( i = 0 ; i < filecount ; i + + )
ImgTool_FreeMips ( srcs [ i ] . in ) ;
printf ( " %s: %s %s, %i*%i, %i mips \n " , " combined " , imagetypename [ r - > type ] , Image_FormatName ( r - > encoding ) , r - > mip [ 0 ] . width , r - > mip [ 0 ] . height , r - > mipcount ) ;
return r ;
}
for ( i = 0 ; i < filecount ; i + + )
ImgTool_FreeMips ( srcs [ i ] . in ) ;
return NULL ;
}
static void ImgTool_Convert ( struct opts_s * args , struct pendingtextureinfo * in , const char * inname , const char * outname )
{
size_t k ;
2020-01-10 12:23:25 +00:00
const char * outext ;
2019-10-18 08:37:38 +00:00
qboolean allowcompressed = false ;
2020-01-10 12:23:25 +00:00
char newout [ MAX_OSPATH ] ;
2019-10-18 08:37:38 +00:00
2020-01-10 12:23:25 +00:00
if ( ! outname )
{
outext = COM_GetFileExtension ( inname , NULL ) ;
k = min ( MAX_OSPATH - 2 - strlen ( args - > defaultext ) , outext - inname ) ;
memcpy ( newout , inname , k ) ;
newout [ k + + ] = ' . ' ;
strcpy ( newout + k , args - > defaultext ) ;
outname = newout ;
}
2020-03-07 09:00:40 +00:00
2020-01-10 12:23:25 +00:00
outext = COM_GetFileExtension ( outname , NULL ) ;
2019-10-18 08:37:38 +00:00
if ( ! strcmp ( outext , " .dds " ) | | ! strcmp ( outext , " .ktx " ) )
allowcompressed = true ;
if ( in )
{
2020-02-11 18:06:10 +00:00
if ( ! strcmp ( outext , " .ktx " ) | | ! strcmp ( outext , " .dds " ) | | args - > mipnum > = in - > mipcount )
{
if ( ! ( args - > flags & IF_NOMIPMAP ) & & in - > mipcount = = 1 )
Image_GenerateMips ( in , args - > flags ) ;
}
2019-10-18 08:37:38 +00:00
if ( args - > mipnum > = in - > mipcount )
{
ImgTool_FreeMips ( in ) ;
Con_Printf ( " %s: Requested output mip number was out of bounds %i >= %i \n " , outname , args - > mipnum , in - > mipcount ) ;
return ;
}
for ( k = 0 ; k < args - > mipnum ; k + + )
{
if ( in - > mip [ k ] . needfree )
BZ_Free ( in - > mip [ k ] . data ) ;
}
in - > mipcount - = k ;
memmove ( in - > mip , & in - > mip [ k ] , sizeof ( in - > mip [ 0 ] ) * in - > mipcount ) ;
2020-03-07 09:00:40 +00:00
Con_Printf ( " %s(%s)-> " , inname , Image_FormatName ( in - > encoding ) ) ;
2020-02-11 18:06:10 +00:00
2019-10-18 08:37:38 +00:00
if ( args - > newpixelformat ! = PTI_INVALID & & ( args - > newpixelformat < PTI_BC1_RGB | | allowcompressed ) & & ImgTool_ConvertPixelFormat ( args , inname , in ) )
2020-03-07 09:00:40 +00:00
Con_Printf ( " (%s)-> " , Image_FormatName ( in - > encoding ) ) ;
2019-10-18 08:37:38 +00:00
if ( ! in - > mipcount )
2020-03-07 09:00:40 +00:00
Con_Printf ( " %s: no image data \n " , inname ) ;
else if ( ! strcasecmp ( outext , " .mip " ) )
{
vfsfile_t * fs = FS_OpenVFS ( outname , " wb " , FS_SYSTEM ) ;
if ( ! fs )
Con_Printf ( " %s(%s): Write failed \n " , outname , Image_FormatName ( in - > encoding ) ) ;
else
{
if ( ! ImgTool_MipExport ( args , fs , in , outname , 1 ) )
Con_Printf ( " %s: export failed \n " , outname ) ;
VFS_CLOSE ( fs ) ;
}
}
2019-10-18 08:37:38 +00:00
# ifdef IMAGEFMT_KTX
2020-03-07 09:00:40 +00:00
else if ( ! strcasecmp ( outext , " .ktx " ) )
2019-10-18 08:37:38 +00:00
{
if ( ! Image_WriteKTXFile ( outname , FS_SYSTEM , in ) )
Con_Printf ( " %s(%s): Write failed \n " , outname , Image_FormatName ( in - > encoding ) ) ;
}
2019-10-06 01:59:13 +00:00
# endif
# ifdef IMAGEFMT_DDS
2020-03-07 09:00:40 +00:00
else if ( ! strcasecmp ( outext , " .dds " ) )
2019-10-18 08:37:38 +00:00
{
if ( ! Image_WriteDDSFile ( outname , FS_SYSTEM , in ) )
Con_Printf ( " %s(%s): Write failed \n " , outname , Image_FormatName ( in - > encoding ) ) ;
}
2019-10-06 01:59:13 +00:00
# endif
2019-10-18 08:37:38 +00:00
else
{
2020-04-29 10:43:22 +00:00
int bb , bw , bh , bd ;
2019-10-14 02:36:13 +00:00
2019-10-18 08:37:38 +00:00
if ( in - > type ! = PTI_2D )
Con_Printf ( " %s: Unable to write %s file to 2d image format \n " , outname , imagetypename [ in - > type ] ) ;
2019-10-06 01:59:13 +00:00
# ifdef IMAGEFMT_PNG
2020-03-07 09:00:40 +00:00
else if ( ! strcasecmp ( outext , " .png " ) )
2019-10-18 08:37:38 +00:00
{
2019-09-29 03:08:01 +00:00
# ifdef AVAIL_PNGLIB
Too many changes, sorry.
Change revision displays, use the SVN commit date instead of using __DATE__ (when there's no local changes). This should allow reproducible builds.
Added s_al_disable cvar, to block openal and all the various problems people have had with it, without having to name an explicit fallback (which would vary by system).
Add mastervolume cvar (for ss).
Add r_shadows 2 (aka fake shadows - for ss).
Add scr_loadingscreen_aspect -1 setting, to disable levelshots entirely, also disables the progress bar (for ss).
Better support for some effectinfo hacks (for ss).
Added dpcompat_nocsqcwarnings (because of lazy+buggy mods like ss).
Rework the dpcsqc versions of project+unproject builtins for better compat (for ss).
Added dpcompat_csqcinputeventtypes to block unexpected csqc input events (for ss).
Better compat with DP's loadfont console command (for ss).
Added dpcompat_smallerfonts cvar to replicate a DP bug (for ss).
Detect dp's m_draw extension, to work around it (for ss).
Cvar dpcompat_ignoremodificationtimes added. A value of 0 favour the most recently modified file, 1 will use DP-like alphabetically sorted preferences (for ss).
loadfont builtin can now accept outline=1 in the sizes arg for slightly more readable fonts.
Fix bbox calcs for rotated entities, fix needed for r_ignorenetpvs 0.
Hackily parse emoji.json to provide :poop: etc suggestions.
Skip prediction entirely when there's no local entity info. This fixes stair-smoothing in xonotic.
screenshot_cubemap will now capture half-float images when saving to ktx or dds files.
Fix support for xcf files larger than 4gb, mostly to avoid compiler warnings.
Fixed size of gfx/loading.lmp when replacement textures are used.
Added mipmap support for rg8 and l8a8 textures.
r_hdr_framebuffer cvar updated to support format names instead of random negative numbers. Description updated to name some interesting ones.
Perform autoupdate _checks_ ONLY with explicit user confirmation (actual updating already needed user confirmation, but this extra step should reduce the chances of us getting wrongly accused of exfiltrating user data if we're run in a sandbox - we ONLY ever included the updating engine's version in the checks, though there's nothing we can do to avoid sending the user's router's IP).
Removed the 'summon satan all over your harddrive' quit message, in case paranoid security researchers are idiots and don't bother doing actual research.
Removed the triptohell.info and fte.triptohell.info certificates, they really need to stop being self-signed. The updates domain is still self-signed for autoupdates.
Video drivers are now able to report supported video resolutions, visible to menuqc. Currently only works with SDL2 builds.
Added setmousepos builtin. Should work with glx+win32 build.
VF_SKYROOM_CAMERA can now accept an extra two args, setviewprop(VF_SKYROOM_CAMERA, org, axis, degrees).
Removed v_skyroom_origin+v_skyroom_orientation cvars in favour just v_skyroom, which should make it behave more like the 'fog' command (used when csqc isn't overriding).
Added R_EndPolygonRibbon builtin to make it faster+easier to generate textured ribbon/cable/etc wide lines (for TW).
sdl: Fix up sys_sdl.c's file enumeration to support wildcards in directories.
edit command now displays end1.bin/end2.bin correctly, because we can.
Finally add support for f_modified - though ruleset_allow_larger_models and ruleset_allow_overlong_sounds generally make it redundant.
Fix threading race condition in sha1 lookups.
Updated f_ruleset to include the same extra flags reported by ezquake.
A mod's default.fmf file can now contain an eg 'mainconfig config.cfg' line (to explicitly set the main config saved with cfg_save_auto 1 etc).
fmf: basegame steam:GameName/GameDir can be used to try to load a mod directory from an installed steam game. The resulting gamedir will be read-only.
HOMEDIR CHANGE: use homedirs only if the basedir cannot be written or a homedir already exists, which should further reduce the probability of microsoft randomly uploading our data to their cloud (but mostly because its annoying to never know where your data is written).
Fixed buf_cvarlist, should work in xonotic now, and without segfaults.
Added an extra arg to URI_Get_Callback calls - the response size, also changed the tempstring to contain all bytes of the response, you need to be careful about nulls though.
Try to work around nvidia's forced-panning bug on x11 when changing video modes. This might screw with other programs.
sdl: support custom icons.
sdl: support choosing a specific display.
Added some documentation to menuqc builtins.
menusys: use outlines for slightly more readable fonts.
menusys: switch vid_width and vid_height combos into a single video mode combo to set both according to reported video modes.
git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5581 fc73d0e0-1445-4013-8a0c-d673dee63da5
2019-11-20 03:09:50 +00:00
qboolean outformats [ PTI_MAX ] ;
2019-10-18 08:37:38 +00:00
//force the format, because we can.
for ( k = 0 ; k < PTI_MAX ; k + + )
Too many changes, sorry.
Change revision displays, use the SVN commit date instead of using __DATE__ (when there's no local changes). This should allow reproducible builds.
Added s_al_disable cvar, to block openal and all the various problems people have had with it, without having to name an explicit fallback (which would vary by system).
Add mastervolume cvar (for ss).
Add r_shadows 2 (aka fake shadows - for ss).
Add scr_loadingscreen_aspect -1 setting, to disable levelshots entirely, also disables the progress bar (for ss).
Better support for some effectinfo hacks (for ss).
Added dpcompat_nocsqcwarnings (because of lazy+buggy mods like ss).
Rework the dpcsqc versions of project+unproject builtins for better compat (for ss).
Added dpcompat_csqcinputeventtypes to block unexpected csqc input events (for ss).
Better compat with DP's loadfont console command (for ss).
Added dpcompat_smallerfonts cvar to replicate a DP bug (for ss).
Detect dp's m_draw extension, to work around it (for ss).
Cvar dpcompat_ignoremodificationtimes added. A value of 0 favour the most recently modified file, 1 will use DP-like alphabetically sorted preferences (for ss).
loadfont builtin can now accept outline=1 in the sizes arg for slightly more readable fonts.
Fix bbox calcs for rotated entities, fix needed for r_ignorenetpvs 0.
Hackily parse emoji.json to provide :poop: etc suggestions.
Skip prediction entirely when there's no local entity info. This fixes stair-smoothing in xonotic.
screenshot_cubemap will now capture half-float images when saving to ktx or dds files.
Fix support for xcf files larger than 4gb, mostly to avoid compiler warnings.
Fixed size of gfx/loading.lmp when replacement textures are used.
Added mipmap support for rg8 and l8a8 textures.
r_hdr_framebuffer cvar updated to support format names instead of random negative numbers. Description updated to name some interesting ones.
Perform autoupdate _checks_ ONLY with explicit user confirmation (actual updating already needed user confirmation, but this extra step should reduce the chances of us getting wrongly accused of exfiltrating user data if we're run in a sandbox - we ONLY ever included the updating engine's version in the checks, though there's nothing we can do to avoid sending the user's router's IP).
Removed the 'summon satan all over your harddrive' quit message, in case paranoid security researchers are idiots and don't bother doing actual research.
Removed the triptohell.info and fte.triptohell.info certificates, they really need to stop being self-signed. The updates domain is still self-signed for autoupdates.
Video drivers are now able to report supported video resolutions, visible to menuqc. Currently only works with SDL2 builds.
Added setmousepos builtin. Should work with glx+win32 build.
VF_SKYROOM_CAMERA can now accept an extra two args, setviewprop(VF_SKYROOM_CAMERA, org, axis, degrees).
Removed v_skyroom_origin+v_skyroom_orientation cvars in favour just v_skyroom, which should make it behave more like the 'fog' command (used when csqc isn't overriding).
Added R_EndPolygonRibbon builtin to make it faster+easier to generate textured ribbon/cable/etc wide lines (for TW).
sdl: Fix up sys_sdl.c's file enumeration to support wildcards in directories.
edit command now displays end1.bin/end2.bin correctly, because we can.
Finally add support for f_modified - though ruleset_allow_larger_models and ruleset_allow_overlong_sounds generally make it redundant.
Fix threading race condition in sha1 lookups.
Updated f_ruleset to include the same extra flags reported by ezquake.
A mod's default.fmf file can now contain an eg 'mainconfig config.cfg' line (to explicitly set the main config saved with cfg_save_auto 1 etc).
fmf: basegame steam:GameName/GameDir can be used to try to load a mod directory from an installed steam game. The resulting gamedir will be read-only.
HOMEDIR CHANGE: use homedirs only if the basedir cannot be written or a homedir already exists, which should further reduce the probability of microsoft randomly uploading our data to their cloud (but mostly because its annoying to never know where your data is written).
Fixed buf_cvarlist, should work in xonotic now, and without segfaults.
Added an extra arg to URI_Get_Callback calls - the response size, also changed the tempstring to contain all bytes of the response, you need to be careful about nulls though.
Try to work around nvidia's forced-panning bug on x11 when changing video modes. This might screw with other programs.
sdl: support custom icons.
sdl: support choosing a specific display.
Added some documentation to menuqc builtins.
menusys: use outlines for slightly more readable fonts.
menusys: switch vid_width and vid_height combos into a single video mode combo to set both according to reported video modes.
git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5581 fc73d0e0-1445-4013-8a0c-d673dee63da5
2019-11-20 03:09:50 +00:00
outformats [ k ] =
2019-10-18 08:37:38 +00:00
( k = = PTI_RGBA8 ) | | ( k = = PTI_RGBX8 ) | |
( k = = PTI_BGRA8 ) | | ( k = = PTI_BGRX8 ) | |
( k = = PTI_LLLA8 ) | | ( k = = PTI_LLLX8 ) | |
( k = = PTI_RGBA16 ) | |
( k = = PTI_L8 ) | | ( k = = PTI_L8A8 ) | |
/*(k == PTI_L16) ||*/
( k = = PTI_BGR8 ) | | ( k = = PTI_BGR8 ) | |
0 ;
2020-01-10 12:23:25 +00:00
if ( ! outformats [ in - > encoding ] )
Too many changes, sorry.
Change revision displays, use the SVN commit date instead of using __DATE__ (when there's no local changes). This should allow reproducible builds.
Added s_al_disable cvar, to block openal and all the various problems people have had with it, without having to name an explicit fallback (which would vary by system).
Add mastervolume cvar (for ss).
Add r_shadows 2 (aka fake shadows - for ss).
Add scr_loadingscreen_aspect -1 setting, to disable levelshots entirely, also disables the progress bar (for ss).
Better support for some effectinfo hacks (for ss).
Added dpcompat_nocsqcwarnings (because of lazy+buggy mods like ss).
Rework the dpcsqc versions of project+unproject builtins for better compat (for ss).
Added dpcompat_csqcinputeventtypes to block unexpected csqc input events (for ss).
Better compat with DP's loadfont console command (for ss).
Added dpcompat_smallerfonts cvar to replicate a DP bug (for ss).
Detect dp's m_draw extension, to work around it (for ss).
Cvar dpcompat_ignoremodificationtimes added. A value of 0 favour the most recently modified file, 1 will use DP-like alphabetically sorted preferences (for ss).
loadfont builtin can now accept outline=1 in the sizes arg for slightly more readable fonts.
Fix bbox calcs for rotated entities, fix needed for r_ignorenetpvs 0.
Hackily parse emoji.json to provide :poop: etc suggestions.
Skip prediction entirely when there's no local entity info. This fixes stair-smoothing in xonotic.
screenshot_cubemap will now capture half-float images when saving to ktx or dds files.
Fix support for xcf files larger than 4gb, mostly to avoid compiler warnings.
Fixed size of gfx/loading.lmp when replacement textures are used.
Added mipmap support for rg8 and l8a8 textures.
r_hdr_framebuffer cvar updated to support format names instead of random negative numbers. Description updated to name some interesting ones.
Perform autoupdate _checks_ ONLY with explicit user confirmation (actual updating already needed user confirmation, but this extra step should reduce the chances of us getting wrongly accused of exfiltrating user data if we're run in a sandbox - we ONLY ever included the updating engine's version in the checks, though there's nothing we can do to avoid sending the user's router's IP).
Removed the 'summon satan all over your harddrive' quit message, in case paranoid security researchers are idiots and don't bother doing actual research.
Removed the triptohell.info and fte.triptohell.info certificates, they really need to stop being self-signed. The updates domain is still self-signed for autoupdates.
Video drivers are now able to report supported video resolutions, visible to menuqc. Currently only works with SDL2 builds.
Added setmousepos builtin. Should work with glx+win32 build.
VF_SKYROOM_CAMERA can now accept an extra two args, setviewprop(VF_SKYROOM_CAMERA, org, axis, degrees).
Removed v_skyroom_origin+v_skyroom_orientation cvars in favour just v_skyroom, which should make it behave more like the 'fog' command (used when csqc isn't overriding).
Added R_EndPolygonRibbon builtin to make it faster+easier to generate textured ribbon/cable/etc wide lines (for TW).
sdl: Fix up sys_sdl.c's file enumeration to support wildcards in directories.
edit command now displays end1.bin/end2.bin correctly, because we can.
Finally add support for f_modified - though ruleset_allow_larger_models and ruleset_allow_overlong_sounds generally make it redundant.
Fix threading race condition in sha1 lookups.
Updated f_ruleset to include the same extra flags reported by ezquake.
A mod's default.fmf file can now contain an eg 'mainconfig config.cfg' line (to explicitly set the main config saved with cfg_save_auto 1 etc).
fmf: basegame steam:GameName/GameDir can be used to try to load a mod directory from an installed steam game. The resulting gamedir will be read-only.
HOMEDIR CHANGE: use homedirs only if the basedir cannot be written or a homedir already exists, which should further reduce the probability of microsoft randomly uploading our data to their cloud (but mostly because its annoying to never know where your data is written).
Fixed buf_cvarlist, should work in xonotic now, and without segfaults.
Added an extra arg to URI_Get_Callback calls - the response size, also changed the tempstring to contain all bytes of the response, you need to be careful about nulls though.
Try to work around nvidia's forced-panning bug on x11 when changing video modes. This might screw with other programs.
sdl: support custom icons.
sdl: support choosing a specific display.
Added some documentation to menuqc builtins.
menusys: use outlines for slightly more readable fonts.
menusys: switch vid_width and vid_height combos into a single video mode combo to set both according to reported video modes.
git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5581 fc73d0e0-1445-4013-8a0c-d673dee63da5
2019-11-20 03:09:50 +00:00
Image_ChangeFormat ( in , outformats , PTI_INVALID , outname ) ;
2020-04-29 10:43:22 +00:00
Image_BlockSizeForEncoding ( in - > encoding , & bb , & bw , & bh , & bd ) ;
2019-10-18 08:37:38 +00:00
if ( ! Image_WritePNG ( outname , FS_SYSTEM , 0 , & in - > mip [ 0 ] . data , 1 , in - > mip [ 0 ] . width * bb , in - > mip [ 0 ] . width , in - > mip [ 0 ] . height , in - > encoding , false ) )
# endif
Con_Printf ( " %s(%s): Write failed \n " , outname , Image_FormatName ( in - > encoding ) ) ;
}
2019-10-06 01:59:13 +00:00
# endif
# ifdef IMAGEFMT_TGA
2020-06-27 19:32:21 +00:00
else if ( ! strcasecmp ( outext , " .tga " ) )
2019-10-18 08:37:38 +00:00
{
Too many changes, sorry.
Change revision displays, use the SVN commit date instead of using __DATE__ (when there's no local changes). This should allow reproducible builds.
Added s_al_disable cvar, to block openal and all the various problems people have had with it, without having to name an explicit fallback (which would vary by system).
Add mastervolume cvar (for ss).
Add r_shadows 2 (aka fake shadows - for ss).
Add scr_loadingscreen_aspect -1 setting, to disable levelshots entirely, also disables the progress bar (for ss).
Better support for some effectinfo hacks (for ss).
Added dpcompat_nocsqcwarnings (because of lazy+buggy mods like ss).
Rework the dpcsqc versions of project+unproject builtins for better compat (for ss).
Added dpcompat_csqcinputeventtypes to block unexpected csqc input events (for ss).
Better compat with DP's loadfont console command (for ss).
Added dpcompat_smallerfonts cvar to replicate a DP bug (for ss).
Detect dp's m_draw extension, to work around it (for ss).
Cvar dpcompat_ignoremodificationtimes added. A value of 0 favour the most recently modified file, 1 will use DP-like alphabetically sorted preferences (for ss).
loadfont builtin can now accept outline=1 in the sizes arg for slightly more readable fonts.
Fix bbox calcs for rotated entities, fix needed for r_ignorenetpvs 0.
Hackily parse emoji.json to provide :poop: etc suggestions.
Skip prediction entirely when there's no local entity info. This fixes stair-smoothing in xonotic.
screenshot_cubemap will now capture half-float images when saving to ktx or dds files.
Fix support for xcf files larger than 4gb, mostly to avoid compiler warnings.
Fixed size of gfx/loading.lmp when replacement textures are used.
Added mipmap support for rg8 and l8a8 textures.
r_hdr_framebuffer cvar updated to support format names instead of random negative numbers. Description updated to name some interesting ones.
Perform autoupdate _checks_ ONLY with explicit user confirmation (actual updating already needed user confirmation, but this extra step should reduce the chances of us getting wrongly accused of exfiltrating user data if we're run in a sandbox - we ONLY ever included the updating engine's version in the checks, though there's nothing we can do to avoid sending the user's router's IP).
Removed the 'summon satan all over your harddrive' quit message, in case paranoid security researchers are idiots and don't bother doing actual research.
Removed the triptohell.info and fte.triptohell.info certificates, they really need to stop being self-signed. The updates domain is still self-signed for autoupdates.
Video drivers are now able to report supported video resolutions, visible to menuqc. Currently only works with SDL2 builds.
Added setmousepos builtin. Should work with glx+win32 build.
VF_SKYROOM_CAMERA can now accept an extra two args, setviewprop(VF_SKYROOM_CAMERA, org, axis, degrees).
Removed v_skyroom_origin+v_skyroom_orientation cvars in favour just v_skyroom, which should make it behave more like the 'fog' command (used when csqc isn't overriding).
Added R_EndPolygonRibbon builtin to make it faster+easier to generate textured ribbon/cable/etc wide lines (for TW).
sdl: Fix up sys_sdl.c's file enumeration to support wildcards in directories.
edit command now displays end1.bin/end2.bin correctly, because we can.
Finally add support for f_modified - though ruleset_allow_larger_models and ruleset_allow_overlong_sounds generally make it redundant.
Fix threading race condition in sha1 lookups.
Updated f_ruleset to include the same extra flags reported by ezquake.
A mod's default.fmf file can now contain an eg 'mainconfig config.cfg' line (to explicitly set the main config saved with cfg_save_auto 1 etc).
fmf: basegame steam:GameName/GameDir can be used to try to load a mod directory from an installed steam game. The resulting gamedir will be read-only.
HOMEDIR CHANGE: use homedirs only if the basedir cannot be written or a homedir already exists, which should further reduce the probability of microsoft randomly uploading our data to their cloud (but mostly because its annoying to never know where your data is written).
Fixed buf_cvarlist, should work in xonotic now, and without segfaults.
Added an extra arg to URI_Get_Callback calls - the response size, also changed the tempstring to contain all bytes of the response, you need to be careful about nulls though.
Try to work around nvidia's forced-panning bug on x11 when changing video modes. This might screw with other programs.
sdl: support custom icons.
sdl: support choosing a specific display.
Added some documentation to menuqc builtins.
menusys: use outlines for slightly more readable fonts.
menusys: switch vid_width and vid_height combos into a single video mode combo to set both according to reported video modes.
git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5581 fc73d0e0-1445-4013-8a0c-d673dee63da5
2019-11-20 03:09:50 +00:00
qboolean outformats [ PTI_MAX ] ;
2019-10-18 08:37:38 +00:00
for ( k = 0 ; k < PTI_MAX ; k + + )
Too many changes, sorry.
Change revision displays, use the SVN commit date instead of using __DATE__ (when there's no local changes). This should allow reproducible builds.
Added s_al_disable cvar, to block openal and all the various problems people have had with it, without having to name an explicit fallback (which would vary by system).
Add mastervolume cvar (for ss).
Add r_shadows 2 (aka fake shadows - for ss).
Add scr_loadingscreen_aspect -1 setting, to disable levelshots entirely, also disables the progress bar (for ss).
Better support for some effectinfo hacks (for ss).
Added dpcompat_nocsqcwarnings (because of lazy+buggy mods like ss).
Rework the dpcsqc versions of project+unproject builtins for better compat (for ss).
Added dpcompat_csqcinputeventtypes to block unexpected csqc input events (for ss).
Better compat with DP's loadfont console command (for ss).
Added dpcompat_smallerfonts cvar to replicate a DP bug (for ss).
Detect dp's m_draw extension, to work around it (for ss).
Cvar dpcompat_ignoremodificationtimes added. A value of 0 favour the most recently modified file, 1 will use DP-like alphabetically sorted preferences (for ss).
loadfont builtin can now accept outline=1 in the sizes arg for slightly more readable fonts.
Fix bbox calcs for rotated entities, fix needed for r_ignorenetpvs 0.
Hackily parse emoji.json to provide :poop: etc suggestions.
Skip prediction entirely when there's no local entity info. This fixes stair-smoothing in xonotic.
screenshot_cubemap will now capture half-float images when saving to ktx or dds files.
Fix support for xcf files larger than 4gb, mostly to avoid compiler warnings.
Fixed size of gfx/loading.lmp when replacement textures are used.
Added mipmap support for rg8 and l8a8 textures.
r_hdr_framebuffer cvar updated to support format names instead of random negative numbers. Description updated to name some interesting ones.
Perform autoupdate _checks_ ONLY with explicit user confirmation (actual updating already needed user confirmation, but this extra step should reduce the chances of us getting wrongly accused of exfiltrating user data if we're run in a sandbox - we ONLY ever included the updating engine's version in the checks, though there's nothing we can do to avoid sending the user's router's IP).
Removed the 'summon satan all over your harddrive' quit message, in case paranoid security researchers are idiots and don't bother doing actual research.
Removed the triptohell.info and fte.triptohell.info certificates, they really need to stop being self-signed. The updates domain is still self-signed for autoupdates.
Video drivers are now able to report supported video resolutions, visible to menuqc. Currently only works with SDL2 builds.
Added setmousepos builtin. Should work with glx+win32 build.
VF_SKYROOM_CAMERA can now accept an extra two args, setviewprop(VF_SKYROOM_CAMERA, org, axis, degrees).
Removed v_skyroom_origin+v_skyroom_orientation cvars in favour just v_skyroom, which should make it behave more like the 'fog' command (used when csqc isn't overriding).
Added R_EndPolygonRibbon builtin to make it faster+easier to generate textured ribbon/cable/etc wide lines (for TW).
sdl: Fix up sys_sdl.c's file enumeration to support wildcards in directories.
edit command now displays end1.bin/end2.bin correctly, because we can.
Finally add support for f_modified - though ruleset_allow_larger_models and ruleset_allow_overlong_sounds generally make it redundant.
Fix threading race condition in sha1 lookups.
Updated f_ruleset to include the same extra flags reported by ezquake.
A mod's default.fmf file can now contain an eg 'mainconfig config.cfg' line (to explicitly set the main config saved with cfg_save_auto 1 etc).
fmf: basegame steam:GameName/GameDir can be used to try to load a mod directory from an installed steam game. The resulting gamedir will be read-only.
HOMEDIR CHANGE: use homedirs only if the basedir cannot be written or a homedir already exists, which should further reduce the probability of microsoft randomly uploading our data to their cloud (but mostly because its annoying to never know where your data is written).
Fixed buf_cvarlist, should work in xonotic now, and without segfaults.
Added an extra arg to URI_Get_Callback calls - the response size, also changed the tempstring to contain all bytes of the response, you need to be careful about nulls though.
Try to work around nvidia's forced-panning bug on x11 when changing video modes. This might screw with other programs.
sdl: support custom icons.
sdl: support choosing a specific display.
Added some documentation to menuqc builtins.
menusys: use outlines for slightly more readable fonts.
menusys: switch vid_width and vid_height combos into a single video mode combo to set both according to reported video modes.
git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5581 fc73d0e0-1445-4013-8a0c-d673dee63da5
2019-11-20 03:09:50 +00:00
outformats [ k ] =
2019-10-18 08:37:38 +00:00
( k = = PTI_RGBA8 ) | | ( k = = PTI_RGBX8 ) | |
( k = = PTI_BGRA8 ) | | ( k = = PTI_BGRX8 ) | |
( k = = PTI_LLLA8 ) | | ( k = = PTI_LLLX8 ) | |
( k = = PTI_RGBA16F ) | | ( k = = PTI_R16F ) | | //half-float tgas is a format extension, but allow it.
( k = = PTI_L8 ) | | ( k = = PTI_L8A8 ) | |
/*(k == PTI_L16) ||*/
( k = = PTI_BGR8 ) | | ( k = = PTI_BGR8 ) | |
0 ;
Too many changes, sorry.
Change revision displays, use the SVN commit date instead of using __DATE__ (when there's no local changes). This should allow reproducible builds.
Added s_al_disable cvar, to block openal and all the various problems people have had with it, without having to name an explicit fallback (which would vary by system).
Add mastervolume cvar (for ss).
Add r_shadows 2 (aka fake shadows - for ss).
Add scr_loadingscreen_aspect -1 setting, to disable levelshots entirely, also disables the progress bar (for ss).
Better support for some effectinfo hacks (for ss).
Added dpcompat_nocsqcwarnings (because of lazy+buggy mods like ss).
Rework the dpcsqc versions of project+unproject builtins for better compat (for ss).
Added dpcompat_csqcinputeventtypes to block unexpected csqc input events (for ss).
Better compat with DP's loadfont console command (for ss).
Added dpcompat_smallerfonts cvar to replicate a DP bug (for ss).
Detect dp's m_draw extension, to work around it (for ss).
Cvar dpcompat_ignoremodificationtimes added. A value of 0 favour the most recently modified file, 1 will use DP-like alphabetically sorted preferences (for ss).
loadfont builtin can now accept outline=1 in the sizes arg for slightly more readable fonts.
Fix bbox calcs for rotated entities, fix needed for r_ignorenetpvs 0.
Hackily parse emoji.json to provide :poop: etc suggestions.
Skip prediction entirely when there's no local entity info. This fixes stair-smoothing in xonotic.
screenshot_cubemap will now capture half-float images when saving to ktx or dds files.
Fix support for xcf files larger than 4gb, mostly to avoid compiler warnings.
Fixed size of gfx/loading.lmp when replacement textures are used.
Added mipmap support for rg8 and l8a8 textures.
r_hdr_framebuffer cvar updated to support format names instead of random negative numbers. Description updated to name some interesting ones.
Perform autoupdate _checks_ ONLY with explicit user confirmation (actual updating already needed user confirmation, but this extra step should reduce the chances of us getting wrongly accused of exfiltrating user data if we're run in a sandbox - we ONLY ever included the updating engine's version in the checks, though there's nothing we can do to avoid sending the user's router's IP).
Removed the 'summon satan all over your harddrive' quit message, in case paranoid security researchers are idiots and don't bother doing actual research.
Removed the triptohell.info and fte.triptohell.info certificates, they really need to stop being self-signed. The updates domain is still self-signed for autoupdates.
Video drivers are now able to report supported video resolutions, visible to menuqc. Currently only works with SDL2 builds.
Added setmousepos builtin. Should work with glx+win32 build.
VF_SKYROOM_CAMERA can now accept an extra two args, setviewprop(VF_SKYROOM_CAMERA, org, axis, degrees).
Removed v_skyroom_origin+v_skyroom_orientation cvars in favour just v_skyroom, which should make it behave more like the 'fog' command (used when csqc isn't overriding).
Added R_EndPolygonRibbon builtin to make it faster+easier to generate textured ribbon/cable/etc wide lines (for TW).
sdl: Fix up sys_sdl.c's file enumeration to support wildcards in directories.
edit command now displays end1.bin/end2.bin correctly, because we can.
Finally add support for f_modified - though ruleset_allow_larger_models and ruleset_allow_overlong_sounds generally make it redundant.
Fix threading race condition in sha1 lookups.
Updated f_ruleset to include the same extra flags reported by ezquake.
A mod's default.fmf file can now contain an eg 'mainconfig config.cfg' line (to explicitly set the main config saved with cfg_save_auto 1 etc).
fmf: basegame steam:GameName/GameDir can be used to try to load a mod directory from an installed steam game. The resulting gamedir will be read-only.
HOMEDIR CHANGE: use homedirs only if the basedir cannot be written or a homedir already exists, which should further reduce the probability of microsoft randomly uploading our data to their cloud (but mostly because its annoying to never know where your data is written).
Fixed buf_cvarlist, should work in xonotic now, and without segfaults.
Added an extra arg to URI_Get_Callback calls - the response size, also changed the tempstring to contain all bytes of the response, you need to be careful about nulls though.
Try to work around nvidia's forced-panning bug on x11 when changing video modes. This might screw with other programs.
sdl: support custom icons.
sdl: support choosing a specific display.
Added some documentation to menuqc builtins.
menusys: use outlines for slightly more readable fonts.
menusys: switch vid_width and vid_height combos into a single video mode combo to set both according to reported video modes.
git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5581 fc73d0e0-1445-4013-8a0c-d673dee63da5
2019-11-20 03:09:50 +00:00
if ( ! outformats [ in - > encoding ] )
Image_ChangeFormat ( in , outformats , PTI_INVALID , outname ) ;
2020-04-29 10:43:22 +00:00
Image_BlockSizeForEncoding ( in - > encoding , & bb , & bw , & bh , & bd ) ;
2019-10-18 08:37:38 +00:00
if ( ! WriteTGA ( outname , FS_SYSTEM , in - > mip [ 0 ] . data , in - > mip [ 0 ] . width * bb , in - > mip [ 0 ] . width , in - > mip [ 0 ] . height , in - > encoding ) )
Con_Printf ( " %s(%s): Write failed \n " , outname , Image_FormatName ( in - > encoding ) ) ;
2019-09-29 03:08:01 +00:00
}
2020-03-07 09:00:40 +00:00
# endif
# ifdef IMAGEFMT_PCX
2020-06-27 19:32:21 +00:00
else if ( ! strcasecmp ( outext , " .pcx " ) )
2020-03-07 09:00:40 +00:00
{
qboolean outformats [ PTI_MAX ] ;
for ( k = 0 ; k < PTI_MAX ; k + + )
outformats [ k ] =
( k = = PTI_P8 ) | |
( k = = TF_SOLID8 ) | |
( k = = TF_TRANS8 ) | |
( k = = TF_H2_TRANS8_0 ) | |
0 ;
if ( ! outformats [ in - > encoding ] )
Image_ChangeFormat ( in , outformats , PTI_INVALID , outname ) ;
2020-04-29 10:43:22 +00:00
Image_BlockSizeForEncoding ( in - > encoding , & bb , & bw , & bh , & bd ) ;
2020-03-07 09:00:40 +00:00
if ( ! WritePCXfile ( outname , FS_SYSTEM , in - > mip [ 0 ] . data , in - > mip [ 0 ] . width , in - > mip [ 0 ] . height , in - > mip [ 0 ] . width * bb , host_basepal , false ) )
Con_Printf ( " %s(%s): Write failed \n " , outname , Image_FormatName ( in - > encoding ) ) ;
}
2019-10-18 08:37:38 +00:00
# endif
else
Con_Printf ( " %s: Unknown output file format \n " , outname ) ;
}
2019-09-29 03:08:01 +00:00
2020-02-11 18:06:10 +00:00
if ( in - > mipcount > 1 )
{
2020-03-07 09:00:40 +00:00
Con_Printf ( " %s(%s): %s %i*%i*%i, %i mips \n " , outname , Image_FormatName ( in - > encoding ) , imagetypename [ in - > type ] , in - > mip [ 0 ] . width , in - > mip [ 0 ] . height , in - > mip [ 0 ] . depth , in - > mipcount ) ;
2020-02-11 18:06:10 +00:00
for ( k = 0 ; k < in - > mipcount ; k + + )
2020-03-07 09:00:40 +00:00
if ( in - > mip [ k ] . depth = = 1 & & in - > type = = PTI_2D )
Con_DPrintf ( " \t %u: %i*%i, %u \n " , ( unsigned ) k , in - > mip [ k ] . width , in - > mip [ k ] . height , ( unsigned ) in - > mip [ k ] . datasize ) ;
else
Con_DPrintf ( " \t %u: %i*%i*%i, %u \n " , ( unsigned ) k , in - > mip [ k ] . width , in - > mip [ k ] . height , in - > mip [ k ] . depth , ( unsigned ) in - > mip [ k ] . datasize ) ;
2020-02-11 18:06:10 +00:00
}
else
2020-03-07 09:00:40 +00:00
Con_Printf ( " %s(%s): %s %i*%i*%i, %u bytes \n " , outname , Image_FormatName ( in - > encoding ) , imagetypename [ in - > type ] , in - > mip [ 0 ] . width , in - > mip [ 0 ] . height , in - > mip [ 0 ] . depth , ( unsigned ) in - > mip [ 0 ] . datasize ) ;
2019-10-14 02:36:13 +00:00
2019-10-18 08:37:38 +00:00
ImgTool_FreeMips ( in ) ;
2019-09-29 03:08:01 +00:00
}
fflush ( stdout ) ;
}
2020-03-07 09:00:40 +00:00
2020-08-18 01:59:55 +00:00
static struct pendingtextureinfo * ImgTool_DecodeMiptex ( struct opts_s * args , miptex_t * mip , size_t size )
2020-03-07 09:00:40 +00:00
{
2020-08-18 01:59:55 +00:00
qbyte * data = ( qbyte * ) mip + ( mip - > offsets [ 3 ] ? mip - > offsets [ 3 ] + ( mip - > width > > 3 ) * ( mip - > height > > 3 ) : sizeof ( miptex_t ) ) ;
qbyte * dataend = ( qbyte * ) mip + size ;
2020-03-07 09:00:40 +00:00
struct pendingtextureinfo * out = Z_Malloc ( sizeof ( * out ) ) ;
qbyte * newdata = NULL ;
int neww = 0 , newh = 0 , sz ;
2020-04-29 10:43:22 +00:00
unsigned int bw , bh , bb , bd ;
2020-03-07 09:00:40 +00:00
out - > type = PTI_2D ;
out - > encoding = PTI_INVALID ;
2020-08-18 01:59:55 +00:00
Con_DPrintf ( " %s: width %i, height %i \n " , mip - > name , mip - > width , mip - > height ) ;
2020-03-07 09:00:40 +00:00
//header [legacymip0 legacymip1 legacymip2] [extsize extcode extdata]*n [legacymip3]
//extcode NAME: extdata-8 bytes of replacement name
//extdata pixelformats, extdata is: Width Height newmip0...N where N is 1*1 mip, using round-down logic.
//compressed and legacy data ommitted means all 4 offsets are 0.
//compressed-only data has offset[3] state the termination position, but offset[0,1,2] MUST be 0 still (extension data starts right after the header, offset3 points to the end of the miptex and has no data there.
//legacy-only data is densely packed or whatever.
//half-life palette data might be glued onto the end. we don't care to handle that.
Con_DPrintf ( " %i bytes of extended data \n " , ( unsigned ) ( dataend - data ) ) ;
Con_DPrintf ( " offset[0]: %i \n " , mip - > offsets [ 0 ] ) ;
Con_DPrintf ( " offset[1]: %i \n " , mip - > offsets [ 1 ] ) ;
Con_DPrintf ( " offset[2]: %i \n " , mip - > offsets [ 2 ] ) ;
Con_DPrintf ( " offset[3]: %i \n " , mip - > offsets [ 3 ] ) ;
2020-08-18 01:59:55 +00:00
if ( data + 4 < dataend & & data [ 0 ] = = 0x00 & & data [ 1 ] = = 0xfb & & data [ 2 ] = = 0x2b & & data [ 3 ] = = 0xaf ) //magic id to say that there's actually extensions here...
{
data + = 4 ;
for ( ; data + 4 < dataend ; data + = sz )
{ //we could recognise more,
uploadfmt_t fmt = PTI_INVALID ;
size_t csz , w , h ;
sz = ( data [ 0 ] < < 0 ) | ( data [ 1 ] < < 8 ) | ( data [ 2 ] < < 16 ) | ( data [ 3 ] < < 24 ) ;
if ( sz < 4 | | sz > dataend - data ) { Con_Printf ( " %s: Invalid miptex extension \n " , mip - > name ) ; break ; }
else if ( sz > 8 & & ! strncmp ( data + 4 , " NAME " , 4 ) ) continue ; //FIXME
else if ( sz > 16 & & ! strncmp ( data + 4 , " RGBA " , 4 ) ) fmt = PTI_RGBA8 ;
else if ( sz > 16 & & ! strncmp ( data + 4 , " RGB " , 4 ) ) fmt = PTI_RGB8 ;
else if ( sz > 16 & & ! strncmp ( data + 4 , " 565 " , 4 ) ) fmt = PTI_RGB565 ;
else if ( sz > 16 & & ! strncmp ( data + 4 , " 5551 " , 4 ) ) fmt = PTI_RGBA5551 ;
else if ( sz > 16 & & ! strncmp ( data + 4 , " 4444 " , 4 ) ) fmt = PTI_RGBA4444 ;
else if ( sz > 16 & & ! strncmp ( data + 4 , " LUM8 " , 4 ) ) fmt = PTI_L8 ; //greyscale. because why not.
else if ( sz > 16 & & ! strncmp ( data + 4 , " BC1 " , 4 ) ) fmt = PTI_BC1_RGBA ;
else if ( sz > 16 & & ! strncmp ( data + 4 , " BC2 " , 4 ) ) fmt = PTI_BC2_RGBA ;
else if ( sz > 16 & & ! strncmp ( data + 4 , " BC3 " , 4 ) ) fmt = PTI_BC3_RGBA ;
else if ( sz > 16 & & ! strncmp ( data + 4 , " BC4 " , 4 ) ) fmt = PTI_BC4_R ;
else if ( sz > 16 & & ! strncmp ( data + 4 , " BC5 " , 4 ) ) fmt = PTI_BC5_RG ;
else if ( sz > 16 & & ! strncmp ( data + 4 , " BC6 " , 4 ) ) fmt = PTI_BC6_RGB_UFLOAT ;
else if ( sz > 16 & & ! strncmp ( data + 4 , " BC7 " , 4 ) ) fmt = PTI_BC7_RGBA ;
else if ( sz > 16 & & ! strncmp ( data + 4 , " ETC1 " , 4 ) ) fmt = PTI_ETC1_RGB8 ;
else if ( sz > 16 & & ! strncmp ( data + 4 , " ETC2 " , 4 ) ) fmt = PTI_ETC2_RGB8 ;
else if ( sz > 16 & & ! strncmp ( data + 4 , " ETCP " , 4 ) ) fmt = PTI_ETC2_RGB8A1 ;
else if ( sz > 16 & & ! strncmp ( data + 4 , " ETCA " , 4 ) ) fmt = PTI_ETC2_RGB8A8 ;
else if ( sz > 16 & & ! strncmp ( data + 4 , " AST4 " , 4 ) ) fmt = PTI_ASTC_4X4_LDR ;
2021-04-14 05:21:04 +00:00
else if ( sz > 16 & & ! strncmp ( data + 4 , " AS54 " , 4 ) ) fmt = PTI_ASTC_5X4_LDR ;
2020-08-18 01:59:55 +00:00
else if ( sz > 16 & & ! strncmp ( data + 4 , " AST5 " , 4 ) ) fmt = PTI_ASTC_5X5_LDR ;
2021-04-14 05:21:04 +00:00
else if ( sz > 16 & & ! strncmp ( data + 4 , " AS65 " , 4 ) ) fmt = PTI_ASTC_6X5_LDR ;
else if ( sz > 16 & & ! strncmp ( data + 4 , " AS85 " , 4 ) ) fmt = PTI_ASTC_8X5_LDR ;
else if ( sz > 16 & & ! strncmp ( data + 4 , " AS05 " , 4 ) ) fmt = PTI_ASTC_10X5_LDR ;
2020-08-18 01:59:55 +00:00
else if ( sz > 16 & & ! strncmp ( data + 4 , " AST6 " , 4 ) ) fmt = PTI_ASTC_6X6_LDR ;
2021-04-14 05:21:04 +00:00
else if ( sz > 16 & & ! strncmp ( data + 4 , " AS86 " , 4 ) ) fmt = PTI_ASTC_8X6_LDR ;
else if ( sz > 16 & & ! strncmp ( data + 4 , " AS06 " , 4 ) ) fmt = PTI_ASTC_10X6_LDR ;
else if ( sz > 16 & & ! strncmp ( data + 4 , " AST8 " , 4 ) ) fmt = PTI_ASTC_8X8_LDR ;
else if ( sz > 16 & & ! strncmp ( data + 4 , " AS08 " , 4 ) ) fmt = PTI_ASTC_10X8_LDR ;
else if ( sz > 16 & & ! strncmp ( data + 4 , " AST0 " , 4 ) ) fmt = PTI_ASTC_10X10_LDR ;
else if ( sz > 16 & & ! strncmp ( data + 4 , " AS20 " , 4 ) ) fmt = PTI_ASTC_12X10_LDR ;
else if ( sz > 16 & & ! strncmp ( data + 4 , " AST2 " , 4 ) ) fmt = PTI_ASTC_12X12_LDR ;
2020-08-18 01:59:55 +00:00
else if ( sz > 16 & & ! strncmp ( data + 4 , " EXP5 " , 4 ) ) fmt = PTI_E5BGR9 ;
else { Con_Printf ( " %s: Unknown miptex extension %4s \n " , mip - > name , data + 4 ) ; continue ; }
if ( out - > encoding ! = PTI_INVALID ) //use the first format we support, allowing prioritisation.
continue ;
2020-03-07 09:00:40 +00:00
2020-08-18 01:59:55 +00:00
Image_BlockSizeForEncoding ( fmt , & bb , & bw , & bh , & bd ) ;
w = data [ 8 ] | ( data [ 9 ] < < 8 ) | ( data [ 10 ] < < 16 ) | ( data [ 11 ] < < 24 ) ;
h = data [ 12 ] | ( data [ 13 ] < < 8 ) | ( data [ 14 ] < < 16 ) | ( data [ 15 ] < < 24 ) ;
for ( csz = 16 ; w | | h ; w > > = 1 , h > > = 1 )
{
w = max ( 1 , w ) ;
h = max ( 1 , h ) ;
csz + = bb * ( ( w + bw - 1 ) / bw ) * ( ( h + bh - 1 ) / bh ) ;
}
if ( sz = = csz )
{ //mip chain is complete etc
out - > encoding = fmt ;
newdata = data + 16 ;
neww = data [ 8 ] | ( data [ 9 ] < < 8 ) | ( data [ 10 ] < < 16 ) | ( data [ 11 ] < < 24 ) ;
newh = data [ 12 ] | ( data [ 13 ] < < 8 ) | ( data [ 14 ] < < 16 ) | ( data [ 15 ] < < 24 ) ;
}
else
Con_Printf ( " %s: Chain size of %u doesn't match expected %u \n " , mip - > name , ( unsigned ) csz - 16 , sz - 16 ) ;
2020-03-07 09:00:40 +00:00
}
}
//only use our if there were no corrupt sections.
if ( data = = dataend & & newdata & & neww & & newh )
{
2020-04-29 10:43:22 +00:00
Image_BlockSizeForEncoding ( out - > encoding , & bb , & bw , & bh , & bd ) ;
2020-03-07 09:00:40 +00:00
for ( out - > mipcount = 0 ; out - > mipcount < countof ( out - > mip ) & & neww & & newh ; out - > mipcount + + , neww > > = 1 , newh > > = 1 )
{
neww = max ( 1 , neww ) ;
newh = max ( 1 , newh ) ;
out - > mip [ out - > mipcount ] . width = neww ;
out - > mip [ out - > mipcount ] . height = newh ;
out - > mip [ out - > mipcount ] . depth = 1 ;
out - > mip [ out - > mipcount ] . datasize = bb ;
out - > mip [ out - > mipcount ] . datasize * = ( out - > mip [ out - > mipcount ] . width + bw - 1 ) / bw ;
out - > mip [ out - > mipcount ] . datasize * = ( out - > mip [ out - > mipcount ] . height + bh - 1 ) / bh ;
2020-04-29 10:43:22 +00:00
out - > mip [ out - > mipcount ] . datasize * = ( out - > mip [ out - > mipcount ] . depth + bd - 1 ) / bd ;
2020-03-07 09:00:40 +00:00
out - > mip [ out - > mipcount ] . data = newdata ;
newdata + = out - > mip [ out - > mipcount ] . datasize ;
}
}
else
{
2021-04-14 05:21:04 +00:00
if ( ( ( ( dataend - data ) + 3 ) & ~ 3 ) = = ( ( ( 256 * 3 + 2 ) + 3 ) & ~ 3 ) & & data [ 0 ] = = 0 & & data [ 1 ] = = 1 )
{ //halflife format...
qbyte * idx , * rgb , * pal , * pi ;
size_t s ;
pal = data + 2 ;
out - > encoding = PTI_RGBX8 ;
for ( out - > mipcount = 0 ; out - > mipcount < 4 & & mip - > offsets [ out - > mipcount ] ; out - > mipcount + + )
{
out - > mip [ out - > mipcount ] . width = mip - > width > > out - > mipcount ;
out - > mip [ out - > mipcount ] . height = mip - > height > > out - > mipcount ;
out - > mip [ out - > mipcount ] . depth = 1 ;
s = out - > mip [ out - > mipcount ] . width * out - > mip [ out - > mipcount ] . height * out - > mip [ out - > mipcount ] . depth ;
out - > mip [ out - > mipcount ] . datasize = s * 4 ;
rgb = out - > mip [ out - > mipcount ] . data = BZ_Malloc ( out - > mip [ out - > mipcount ] . datasize ) ;
idx = ( char * ) mip + mip - > offsets [ out - > mipcount ] ;
while ( s - - > 0 )
{
pi = pal + 3 * * idx + + ;
* rgb + + = pi [ 0 ] ;
* rgb + + = pi [ 1 ] ;
* rgb + + = pi [ 2 ] ;
* rgb + + = 255 ;
}
}
}
2020-03-07 09:00:40 +00:00
else
{
2021-04-14 05:21:04 +00:00
if ( * mip - > name = = ' { ' )
out - > encoding = TF_TRANS8 ;
else if ( ! strncasecmp ( mip - > name , " sky " , 3 ) )
out - > encoding = TF_H2_TRANS8_0 ;
else
out - > encoding = PTI_P8 ;
for ( out - > mipcount = 0 ; out - > mipcount < 4 & & mip - > offsets [ out - > mipcount ] ; out - > mipcount + + )
{
out - > mip [ out - > mipcount ] . width = mip - > width > > out - > mipcount ;
out - > mip [ out - > mipcount ] . height = mip - > height > > out - > mipcount ;
out - > mip [ out - > mipcount ] . depth = 1 ;
out - > mip [ out - > mipcount ] . datasize = out - > mip [ out - > mipcount ] . width * out - > mip [ out - > mipcount ] . height * out - > mip [ out - > mipcount ] . depth ;
out - > mip [ out - > mipcount ] . data = ( char * ) mip + mip - > offsets [ out - > mipcount ] ;
}
2020-03-07 09:00:40 +00:00
}
}
if ( * mip - > name = = ' * ' )
* mip - > name = ' # ' ; //convert from * to #, so its a valid file name.
if ( args )
{
2020-08-18 01:59:55 +00:00
if ( args - > defaultext & & ! strcasecmp ( args - > defaultext , " mip " ) )
{
char newout [ MAX_OSPATH ] ;
size_t k = strlen ( mip - > name ) ;
vfsfile_t * fs ;
memcpy ( newout , mip - > name , k ) ;
newout [ k + + ] = ' . ' ;
strcpy ( newout + k , args - > defaultext ) ;
fs = FS_OpenVFS ( newout , " wb " , FS_SYSTEM ) ;
if ( ! fs )
Con_Printf ( " %s(%s): Write failed \n " , newout , Image_FormatName ( out - > encoding ) ) ;
else
{
VFS_WRITE ( fs , mip , size ) ;
VFS_CLOSE ( fs ) ;
}
fflush ( stdout ) ;
}
else
ImgTool_Convert ( args , out , mip - > name , NULL ) ;
2020-03-07 09:00:40 +00:00
return NULL ;
}
return out ;
}
2021-04-14 05:21:04 +00:00
static void ImgTool_PrintInfo ( const char * inname , struct pendingtextureinfo * in )
{
size_t m ;
if ( in - > mipcount = = 1 & & in - > type = = PTI_2D & & in - > mip [ 0 ] . depth = = 1 )
printf ( " %-20s(%s): %4i*%-4i \n " , inname , Image_FormatName ( in - > encoding ) , in - > mip [ 0 ] . width , in - > mip [ 0 ] . height ) ;
else if ( in - > mipcount = = 1 )
printf ( " %-20s(%s): %s, %i*%i*%i, %u bytes \n " , inname , Image_FormatName ( in - > encoding ) , imagetypename [ in - > type ] , in - > mip [ 0 ] . width , in - > mip [ 0 ] . height , in - > mip [ 0 ] . depth , ( unsigned ) in - > mip [ 0 ] . datasize ) ;
else
{
/*if (mip)
printf ( " %-20s(%s): \" %s \" %s %i*%i, %i mips \n " , inname , Image_FormatName ( in - > encoding ) , mip - > name , mip - > offsets [ 0 ] ? " " : " (stripped) " , mip - > width , mip - > height , in - > mipcount ) ;
else */
printf ( " %-20s(%s): %s, %i*%i*%i, %i mips \n " , inname , Image_FormatName ( in - > encoding ) , imagetypename [ in - > type ] , in - > mip [ 0 ] . width , in - > mip [ 0 ] . height , in - > mip [ 0 ] . depth , in - > mipcount ) ;
for ( m = 0 ; m < in - > mipcount ; m + + )
printf ( " \t %u: %i*%i*%i, %u \n " , ( unsigned ) m , in - > mip [ m ] . width , in - > mip [ m ] . height , in - > mip [ m ] . depth , ( unsigned ) in - > mip [ m ] . datasize ) ;
}
}
static void ImgTool_Enumerate ( struct opts_s * args , const char * inname , void ( * callback ) ( const char * name , struct pendingtextureinfo * mips ) )
2019-09-29 03:08:01 +00:00
{
qbyte * indata ;
size_t fsize ;
size_t m ;
struct pendingtextureinfo * in ;
indata = FS_LoadMallocFile ( inname , & fsize ) ;
if ( ! indata )
printf ( " %s: unable to read \n " , inname ) ;
2020-01-10 12:23:25 +00:00
else if ( fsize > = sizeof ( wad2_t ) & & indata [ 0 ] = = ' W ' & & indata [ 1 ] = = ' A ' & & indata [ 2 ] = = ' D ' )
{
const wad2_t * w = ( const wad2_t * ) indata ;
const wad2entry_t * e = ( const wad2entry_t * ) ( indata + w - > offset ) ;
printf ( " %s: wad%c file with %i entries \n " , inname , w - > magic [ 3 ] , w - > num ) ;
for ( m = 0 ; m < w - > num ; m + + , e + + )
{
switch ( e - > type )
{
2021-04-17 21:35:13 +00:00
case TYP_QPIC :
{
size_t sz = min ( e - > size , e - > dsize ) ;
unsigned int w = 0 ;
unsigned int h = 0 ;
in = NULL ;
if ( sz > = 8 )
{
w = ( indata [ e - > offset + 0 ] < < 0 ) | ( indata [ e - > offset + 1 ] < < 8 ) | ( indata [ e - > offset + 2 ] < < 16 ) | ( indata [ e - > offset + 3 ] < < 24 ) ;
h = ( indata [ e - > offset + 4 ] < < 0 ) | ( indata [ e - > offset + 5 ] < < 8 ) | ( indata [ e - > offset + 6 ] < < 16 ) | ( indata [ e - > offset + 7 ] < < 24 ) ;
}
if ( sz = = w * h + 8 )
{ //quake
in = Z_Malloc ( sizeof ( * in ) ) ;
in - > encoding = PTI_P8 ;
in - > mip [ 0 ] . data = indata + e - > offset + 8 ;
in - > mip [ 0 ] . datasize = w * h ;
}
else if ( ( ( sz + 3 ) & ~ 3 ) = = ( ( ( w * h + 10 + 768 + 3 ) & ~ 3 ) ) )
{ //halflife
const unsigned char * src = indata + e - > offset + 8 ;
const unsigned char * pal = indata + e - > offset + 8 + w * h + 2 , * p ;
unsigned char * dst ;
sz = w * h ;
in = Z_Malloc ( sizeof ( * in ) + w * h * 3 ) ;
in - > encoding = PTI_RGB8 ;
in - > mip [ 0 ] . data = dst = ( unsigned char * ) ( in + 1 ) ;
in - > mip [ 0 ] . datasize = sz * 3 ;
while ( sz - - > 0 )
{
p = pal + * src + + * 3 ;
* dst + + = * p + + ;
* dst + + = * p + + ;
* dst + + = * p + + ;
}
}
else
printf ( " \t %16.16s: missized qpic (%u %u, %u bytes) \n " , e - > name , w , h , ( unsigned int ) sz ) ;
if ( in )
{
printf ( " \n " ) ;
in - > type = PTI_2D ;
in - > mipcount = 1 ;
in - > mip [ 0 ] . width = w ;
in - > mip [ 0 ] . height = h ;
in - > mip [ 0 ] . depth = 1 ;
in - > mip [ 0 ] . needfree = false ;
callback ( e - > name , in ) ;
ImgTool_FreeMips ( in ) ;
}
}
break ;
2020-01-10 12:23:25 +00:00
case 67 : //hl...
case TYP_MIPTEX :
{
2020-03-07 09:00:40 +00:00
miptex_t * mip = ( miptex_t * ) ( indata + e - > offset ) ;
2021-04-14 05:21:04 +00:00
in = ImgTool_DecodeMiptex ( NULL , mip , min ( e - > size , e - > dsize ) ) ;
2020-03-07 09:00:40 +00:00
2021-04-14 05:21:04 +00:00
callback ( e - > name , in ) ;
/*
//mip name SHOULD match entry name... but gah!
2020-01-10 12:23:25 +00:00
if ( strcasecmp ( e - > name , mip - > name ) )
2020-03-07 09:00:40 +00:00
printf ( " \t %16.16s (%s): " , e - > name , mip - > name ) ;
2020-01-10 12:23:25 +00:00
else
2020-03-07 09:00:40 +00:00
printf ( " \t %16.16s: " , mip - > name ) ;
printf ( " %u*%u%s " , mip - > width , mip - > height , mip - > offsets [ 0 ] ? " " : " (omitted) " ) ;
if ( in - > encoding ! = PTI_P8 )
2021-04-14 05:21:04 +00:00
printf ( " (%s %u*%u) " , Image_FormatName ( in - > encoding ) , in - > mip [ 0 ] . width , in - > mip [ 0 ] . height ) ; */
2020-03-07 09:00:40 +00:00
printf ( " \n " ) ;
ImgTool_FreeMips ( in ) ;
2020-01-10 12:23:25 +00:00
}
break ;
case TYP_PALETTE :
printf ( " \t %16.16s: palette - %u bytes \n " , e - > name , e - > size ) ;
break ;
2021-04-17 21:35:13 +00:00
case 70 :
printf ( " \t %16.16s: Halflife Font (%u bytes) \n " , e - > name , e - > size ) ;
break ;
2020-01-10 12:23:25 +00:00
default :
printf ( " \t %16.16s: ENTRY TYPE %u (%u bytes) \n " , e - > name , e - > type , e - > size ) ;
break ;
}
}
}
2020-02-26 07:48:01 +00:00
else if ( fsize > = sizeof ( dheader_t ) & & (
( ( indata [ 0 ] ) | ( indata [ 1 ] < < 8 ) | ( indata [ 2 ] < < 16 ) | ( indata [ 3 ] < < 24 ) ) = = BSPVERSION | |
2021-05-09 13:00:14 +00:00
( ( indata [ 0 ] ) | ( indata [ 1 ] < < 8 ) | ( indata [ 2 ] < < 16 ) | ( indata [ 3 ] < < 24 ) ) = = BSPVERSIONHL | |
2020-02-26 07:48:01 +00:00
( ( indata [ 0 ] ) | ( indata [ 1 ] < < 8 ) | ( indata [ 2 ] < < 16 ) | ( indata [ 3 ] < < 24 ) ) = = BSPVERSIONPREREL | |
( ( indata [ 0 ] ) | ( indata [ 1 ] < < 8 ) | ( indata [ 2 ] < < 16 ) | ( indata [ 3 ] < < 24 ) ) = = BSPVERSION_LONG1 | |
( ( indata [ 0 ] ) | ( indata [ 1 ] < < 8 ) | ( indata [ 2 ] < < 16 ) | ( indata [ 3 ] < < 24 ) ) = = BSPVERSION_LONG2 ) )
{ //q1bsp
dheader_t * bsp = ( dheader_t * ) indata ;
dmiptexlump_t * texlump = ( dmiptexlump_t * ) ( indata + bsp - > lumps [ LUMP_TEXTURES ] . fileofs ) ;
miptex_t * miptex ;
size_t i ;
2020-08-18 01:59:55 +00:00
size_t sz = bsp - > lumps [ LUMP_TEXTURES ] . filelen ;
2020-02-26 07:48:01 +00:00
printf ( " %-20s: bsp file (%u textures) \n " , inname , texlump - > nummiptex ) ;
2020-08-18 01:59:55 +00:00
for ( i = texlump - > nummiptex ; i - - > 0 ; )
2020-02-26 07:48:01 +00:00
{
if ( texlump - > dataofs [ i ] < 0 | | texlump - > dataofs [ i ] > = bsp - > lumps [ LUMP_TEXTURES ] . filelen )
2020-08-18 01:59:55 +00:00
{
char syn [ MAX_QPATH ] ;
sprintf ( syn , " unnamed%u " , ( unsigned ) i ) ;
printf ( " \t %16.16s: <NO DATA> \n " , syn ) ;
2020-02-26 07:48:01 +00:00
continue ;
2020-08-18 01:59:55 +00:00
}
2020-02-26 07:48:01 +00:00
miptex = ( miptex_t * ) ( ( qbyte * ) texlump + texlump - > dataofs [ i ] ) ;
2020-03-07 09:00:40 +00:00
2020-08-18 01:59:55 +00:00
in = ImgTool_DecodeMiptex ( NULL , miptex , sz - texlump - > dataofs [ i ] ) ;
sz = texlump - > dataofs [ i ] ;
2021-04-14 05:21:04 +00:00
callback ( miptex - > name , in ) ;
/* if (in->encoding != PTI_P8)
2020-03-07 09:00:40 +00:00
printf ( " \t %16.16s: %u*%u%s (%s: %i*%i) \n " , miptex - > name , miptex - > width , miptex - > height , miptex - > offsets [ 0 ] ? " " : " (external data) " , Image_FormatName ( in - > encoding ) , in - > mip [ 0 ] . width , in - > mip [ 0 ] . height ) ;
else
printf ( " \t %16.16s: %u*%u%s \n " , miptex - > name , miptex - > width , miptex - > height , miptex - > offsets [ 0 ] ? " " : " (external data) " ) ;
2021-04-14 05:21:04 +00:00
*/ ImgTool_FreeMips ( in ) ;
2020-02-26 07:48:01 +00:00
}
}
2021-04-14 05:21:04 +00:00
else if ( fsize > = sizeof ( dmdl_t ) & & (
2021-04-17 21:35:13 +00:00
( ( indata [ 0 ] ) | ( indata [ 1 ] < < 8 ) | ( indata [ 2 ] < < 16 ) | ( indata [ 3 ] < < 24 ) ) = = IDPOLYHEADER & & ( ( ( dmdl_t * ) indata ) - > version = = ALIAS_VERSION | | ( ( dmdl_t * ) indata ) - > version = = 50 ) ) )
{ //quake's mdl format. also hexen2's missionpack format.
2021-04-14 05:21:04 +00:00
int i , j , numframes ;
2021-04-17 21:35:13 +00:00
char skinname [ 256 ] ;
2021-04-14 05:21:04 +00:00
dmdl_t * mdl = ( dmdl_t * ) indata ;
2021-04-17 21:35:13 +00:00
daliasskintype_t * pskintype = ( daliasskintype_t * ) ( indata + sizeof ( * mdl ) - ( ( ( ( dmdl_t * ) indata ) - > version = = 50 ) ? 0 : sizeof ( int ) ) ) ;
2021-04-14 05:21:04 +00:00
daliasskingroup_t * pskingroup ;
daliasskininterval_t * intervals ;
2021-04-17 21:35:13 +00:00
uploadfmt_t encoding ;
2021-04-14 05:21:04 +00:00
struct pendingtextureinfo * out = Z_Malloc ( sizeof ( * out ) ) ;
if ( mdl - > flags & MFH2_TRANSPARENT )
2021-04-17 21:35:13 +00:00
encoding = TF_H2_T7G1 ; //hexen2
else if ( mdl - > flags & MFH2_HOLEY )
encoding = TF_H2_TRANS8_0 ; //hexen2
2021-04-14 05:21:04 +00:00
else if ( mdl - > flags & MFH2_SPECIAL_TRANS )
2021-04-17 21:35:13 +00:00
encoding = TF_H2_T4A4 ; //hexen2
2021-04-14 05:21:04 +00:00
else
2021-04-17 21:35:13 +00:00
encoding = TF_SOLID8 ;
2021-04-14 05:21:04 +00:00
printf ( " %-20s: mdl file (%u skingroups) \n " , inname , mdl - > numskins ) ;
for ( i = 0 ; i < mdl - > numskins ; i + + )
{
switch ( LittleLong ( pskintype - > type ) )
{
case ALIAS_SKIN_SINGLE :
2021-04-17 21:35:13 +00:00
out = Z_Malloc ( sizeof ( * out ) ) ;
out - > type = PTI_2D ;
out - > encoding = encoding ;
out - > mipcount = 1 ;
out - > mip [ 0 ] . datasize = mdl - > skinwidth * mdl - > skinheight ;
out - > mip [ 0 ] . width = mdl - > skinwidth ;
out - > mip [ 0 ] . height = mdl - > skinheight ;
out - > mip [ 0 ] . depth = 1 ;
out - > mip [ 0 ] . needfree = false ;
2021-04-14 05:21:04 +00:00
out - > mip [ 0 ] . data = ( qbyte * ) ( pskintype + 1 ) ;
2021-04-17 21:35:13 +00:00
2021-04-14 05:21:04 +00:00
pskintype = ( daliasskintype_t * ) ( ( char * ) out - > mip [ 0 ] . data + out - > mip [ 0 ] . datasize ) ;
2021-04-17 21:35:13 +00:00
printf ( " \t %s_%u: %i*%i \n " , inname , i , mdl - > skinwidth , mdl - > skinheight ) ;
snprintf ( skinname , sizeof ( skinname ) , " %s_%u " , inname , i ) ;
callback ( skinname , out ) ;
ImgTool_FreeMips ( out ) ;
2021-04-14 05:21:04 +00:00
break ;
default :
pskingroup = ( daliasskingroup_t * ) ( pskintype + 1 ) ;
intervals = ( daliasskininterval_t * ) ( pskingroup + 1 ) ;
numframes = LittleLong ( pskingroup - > numskins ) ;
2021-04-17 21:35:13 +00:00
for ( j = 0 ; j < numframes ; j + + )
2021-04-14 05:21:04 +00:00
{
2021-04-17 21:35:13 +00:00
out = Z_Malloc ( sizeof ( * out ) ) ;
out - > type = PTI_2D ;
out - > encoding = encoding ;
out - > mipcount = 1 ;
out - > mip [ 0 ] . datasize = mdl - > skinwidth * mdl - > skinheight ;
out - > mip [ 0 ] . width = mdl - > skinwidth ;
out - > mip [ 0 ] . height = mdl - > skinheight ;
out - > mip [ 0 ] . depth = 1 ;
out - > mip [ 0 ] . needfree = false ;
out - > mip [ 0 ] . data = ( qbyte * ) ( intervals + numframes ) + mdl - > skinwidth * mdl - > skinheight * j ;
printf ( " \t \t %s_%u_%u: %i*%i @ %g \n " , inname , i , j , mdl - > skinwidth , mdl - > skinheight , intervals [ j ] . interval ) ;
snprintf ( skinname , sizeof ( skinname ) , " %s_%u_%u " , inname , i , j ) ;
callback ( skinname , out ) ;
ImgTool_FreeMips ( out ) ;
2021-04-14 05:21:04 +00:00
}
2021-04-17 21:35:13 +00:00
pskintype = ( daliasskintype_t * ) ( ( qbyte * ) ( intervals + numframes ) + mdl - > skinwidth * mdl - > skinheight * numframes ) ;
2021-04-14 05:21:04 +00:00
break ;
}
}
}
//else spr
2019-09-29 03:08:01 +00:00
else
{
2020-08-18 01:59:55 +00:00
const miptex_t * mip = NULL ;
2020-03-07 09:00:40 +00:00
const char * ex = COM_GetFileExtension ( inname , NULL ) ;
if ( ! strcasecmp ( ex , " .mip " ) )
2020-08-18 01:59:55 +00:00
{
in = ImgTool_DecodeMiptex ( NULL , ( miptex_t * ) indata , fsize ) ;
if ( fsize > = sizeof ( miptex_t ) )
mip = ( const miptex_t * ) indata ;
}
2020-03-07 09:00:40 +00:00
else
in = Image_LoadMipsFromMemory ( args - > flags | IF_NOMIPMAP , inname , inname , indata , fsize ) ;
2019-09-29 03:08:01 +00:00
if ( ! in )
2020-02-11 18:06:10 +00:00
printf ( " %-20s: unsupported format \n " , inname ) ;
2021-04-14 05:21:04 +00:00
else
callback ( inname , in ) ;
( void ) mip ;
ImgTool_FreeMips ( in ) ;
2019-09-29 03:08:01 +00:00
}
fflush ( stdout ) ;
}
2019-10-06 01:59:13 +00:00
struct filelist_s
{
const char * * exts ;
size_t numfiles ;
struct {
2020-01-10 12:23:25 +00:00
const char * rootpath ; //the basepath that was passed to the filelist scan.
2019-10-06 01:59:13 +00:00
char * name ;
size_t baselen ; //length up to but not including the filename extension.
} * file ;
size_t maxfiles ; //to avoid reallocs
} ;
static void FileList_Release ( struct filelist_s * list )
{
size_t i ;
for ( i = 0 ; i < list - > numfiles ; i + + )
free ( list - > file [ i ] . name ) ;
free ( list - > file ) ;
list - > numfiles = 0 ;
list - > maxfiles = 0 ;
}
2020-03-07 09:00:40 +00:00
static void FileList_Add ( struct filelist_s * list , const char * rootpath , const char * fname )
2019-10-06 01:59:13 +00:00
{
size_t i ;
size_t baselen ;
const char * ext = COM_GetFileExtension ( fname , NULL ) ;
for ( i = 0 ; ; i + + )
{
if ( ! list - > exts [ i ] )
return ; //extension wasn't in the list.
if ( ! strcmp ( list - > exts [ i ] , ext ) )
break ; //one of the accepted extensions
}
baselen = ext ? ext - fname : strlen ( fname ) ;
for ( i = 0 ; i < list - > numfiles ; i + + )
{
if ( list - > file [ i ] . baselen = = baselen & & ! strncasecmp ( list - > file [ i ] . name , fname , baselen ) )
{
Con_Printf ( " Ignoring dupe file %s (using %s) \n " , fname , list - > file [ i ] . name ) ;
return ; //file already listed, but maybe with a different extension
}
}
if ( i = = list - > maxfiles )
{
list - > maxfiles + = 64 ;
list - > file = realloc ( list - > file , sizeof ( * list - > file ) * list - > maxfiles ) ;
}
2020-01-10 12:23:25 +00:00
list - > file [ i ] . rootpath = rootpath ;
2019-10-06 01:59:13 +00:00
list - > file [ i ] . name = strdup ( fname ) ;
list - > file [ i ] . baselen = baselen ;
list - > numfiles + + ;
}
2019-09-29 03:08:01 +00:00
# ifdef _WIN32
2020-01-10 12:23:25 +00:00
static void ImgTool_TreeScan ( struct filelist_s * list , const char * rootpath , const char * subpath )
{ //FIXME: convert to utf-8.
HANDLE h ;
WIN32_FIND_DATAA fd ;
char file [ MAX_OSPATH ] ;
if ( subpath & & * subpath )
Q_snprintfz ( file , sizeof ( file ) , " %s/%s " , rootpath , subpath ) ;
else
Q_snprintfz ( file , sizeof ( file ) , " %s " , rootpath ) ;
if ( GetFileAttributesA ( file ) & FILE_ATTRIBUTE_DIRECTORY ) //if its a directory then scan it.
Q_snprintfz ( file + strlen ( file ) , sizeof ( file ) - strlen ( file ) , " /* " ) ;
h = FindFirstFileA ( file , & fd ) ;
if ( h ! = INVALID_HANDLE_VALUE )
{
do
{
if ( * fd . cFileName = = ' . ' )
continue ; //skip .. (and unix hidden files, because urgh)
if ( subpath & & * subpath )
Q_snprintfz ( file , sizeof ( file ) , " %s/%s " , subpath , fd . cFileName ) ;
else
Q_snprintfz ( file , sizeof ( file ) , " %s " , fd . cFileName ) ;
if ( fd . dwFileAttributes & FILE_ATTRIBUTE_HIDDEN )
; //don't report hidden entries.
else if ( fd . dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
ImgTool_TreeScan ( list , rootpath , file ) ;
else
FileList_Add ( list , rootpath , file ) ;
} while ( FindNextFileA ( h , & fd ) ) ;
FindClose ( h ) ;
}
2019-09-29 03:08:01 +00:00
}
# else
# include <dirent.h>
# include <fnmatch.h>
2019-10-06 01:59:13 +00:00
static void ImgTool_TreeScan ( struct filelist_s * list , const char * basepath , const char * subpath )
2019-09-29 03:08:01 +00:00
{
DIR * dir ;
char file [ MAX_OSPATH ] ;
struct dirent * ent ;
2020-03-07 09:00:40 +00:00
struct stat sb ;
2019-09-29 03:08:01 +00:00
2019-10-06 01:59:13 +00:00
if ( subpath & & * subpath )
Q_snprintfz ( file , sizeof ( file ) , " %s/%s " , basepath , subpath ) ;
else
Q_snprintfz ( file , sizeof ( file ) , " %s " , basepath ) ;
2020-03-07 09:00:40 +00:00
stat ( file , & sb ) ;
if ( ( sb . st_mode & S_IFMT ) = = S_IFDIR )
2019-09-29 03:08:01 +00:00
{
2020-03-07 09:00:40 +00:00
dir = opendir ( file ) ;
if ( ! dir )
2019-09-29 03:08:01 +00:00
{
2020-03-07 09:00:40 +00:00
Con_Printf ( " Failed to open dir %s \n " , file ) ;
return ;
2019-09-29 03:08:01 +00:00
}
2020-03-07 09:00:40 +00:00
for ( ; ; )
2019-09-29 03:08:01 +00:00
{
2020-03-07 09:00:40 +00:00
ent = readdir ( dir ) ;
if ( ! ent )
break ;
if ( * ent - > d_name = = ' . ' )
continue ;
else if ( ent - > d_type = = DT_DIR )
{
if ( ! subpath )
continue ;
if ( * subpath )
Q_snprintfz ( file , sizeof ( file ) , " %s/%s " , subpath , ent - > d_name ) ;
else
Q_snprintfz ( file , sizeof ( file ) , " %s " , ent - > d_name ) ;
ImgTool_TreeScan ( list , basepath , file ) ;
}
else if ( ent - > d_type = = DT_REG )
{
if ( subpath & & * subpath )
Q_snprintfz ( file , sizeof ( file ) , " %s/%s " , subpath , ent - > d_name ) ;
else
Q_snprintfz ( file , sizeof ( file ) , " %s " , ent - > d_name ) ;
FileList_Add ( list , basepath , file ) ;
}
2019-10-06 01:59:13 +00:00
}
2020-03-07 09:00:40 +00:00
closedir ( dir ) ;
}
else
{
if ( * file = = ' / ' )
FileList_Add ( list , " " , file ) ;
else
FileList_Add ( list , " . " , file ) ;
2019-10-06 01:59:13 +00:00
}
}
# endif
2020-01-10 12:23:25 +00:00
static void ImgTool_TreeConvert ( struct opts_s * args , const char * destpath , const char * srcpath )
2019-10-06 01:59:13 +00:00
{
size_t newfiles = 0 , skippedfiles = 0 , processedfiles = 0 ;
char file [ MAX_OSPATH ] ;
char dest [ MAX_OSPATH ] ;
2020-06-27 19:32:21 +00:00
const char * exts [ ] = { " .png " , " .bmp " , " .tga " , " .jpg " , " .exr " , " .hdr " , " .pcx " , NULL } ;
2019-10-06 01:59:13 +00:00
struct filelist_s list = { exts } ;
size_t i , destlen = strlen ( destpath ) + 1 ;
ImgTool_TreeScan ( & list , srcpath , " " ) ;
if ( ! list . numfiles )
Con_Printf ( " No suitable files found in directory: %s \n " , srcpath ) ;
for ( i = 0 ; i < list . numfiles ; i + + )
{
struct stat statsrc , statdst ;
Q_snprintfz ( file , sizeof ( file ) , " %s/%s " , srcpath , list . file [ i ] . name ) ;
Q_snprintfz ( dest , sizeof ( dest ) , " %s/%s " , destpath , list . file [ i ] . name ) ;
Q_snprintfz ( dest + destlen + list . file [ i ] . baselen , sizeof ( dest ) - destlen - list . file [ i ] . baselen , " .dds " ) ;
if ( stat ( file , & statsrc ) < 0 )
{
Con_Printf ( " stat( \" %s \" ) failed... \n " , file ) ;
continue ;
}
if ( stat ( dest , & statdst ) < 0 )
{
2019-10-27 06:59:19 +00:00
statdst . st_mtime = INT_MIN ; //make it look old
2019-10-06 01:59:13 +00:00
newfiles + + ;
}
2019-10-27 06:59:19 +00:00
if ( statdst . st_mtime < = statsrc . st_mtime )
2019-10-06 01:59:13 +00:00
{
processedfiles + + ;
// Con_Printf("Image file %s -> %s\n", file, dest);
FS_CreatePath ( dest , FS_SYSTEM ) ;
2019-10-18 08:37:38 +00:00
ImgTool_Convert ( args , ImgTool_Read ( args , file ) , file , dest ) ;
2019-10-06 01:59:13 +00:00
}
else
{
skippedfiles + + ;
// Con_Printf("Unmodified image file %s -> %s\n", file, dest);
}
}
Con_Printf ( " found: %u, processed: %u, skipped: %u, new: %u \n " , ( unsigned int ) list . numfiles , ( unsigned int ) processedfiles , ( unsigned int ) skippedfiles , ( unsigned int ) newfiles ) ;
FileList_Release ( & list ) ;
return ;
}
2020-01-10 12:23:25 +00:00
static void ImgTool_WadExtract ( struct opts_s * args , const char * wadname )
{
qbyte * indata ;
size_t fsize ;
size_t m ;
indata = FS_LoadMallocFile ( wadname , & fsize ) ;
if ( ! indata )
printf ( " %s: unable to read \n " , wadname ) ;
else if ( fsize > = sizeof ( wad2_t ) & & indata [ 0 ] = = ' W ' & & indata [ 1 ] = = ' A ' & & indata [ 2 ] = = ' D ' )
{
const wad2_t * w = ( const wad2_t * ) indata ;
const wad2entry_t * e = ( const wad2entry_t * ) ( indata + w - > offset ) ;
2020-02-11 18:06:10 +00:00
int i ;
char clean [ sizeof ( e - > name ) + 1 ] ;
2019-10-06 01:59:13 +00:00
2020-01-10 12:23:25 +00:00
for ( m = 0 ; m < w - > num ; m + + , e + + )
{
switch ( e - > type )
{
case 67 : //hl...
case TYP_MIPTEX :
{
miptex_t * mip = ( miptex_t * ) ( indata + e - > offset ) ;
2019-10-06 01:59:13 +00:00
2020-02-11 18:06:10 +00:00
if ( ! strcmp ( e - > name , " CONCHARS " ) & & e - > size = = 128 * 128 )
{ //special hack for conchars, which is listed as a miptex for some reason, with no qpic header (it not being a qpic lump)
2020-03-07 09:00:40 +00:00
struct pendingtextureinfo * out = Z_Malloc ( sizeof ( * out ) ) ;
2020-02-11 18:06:10 +00:00
out - > encoding = TF_H2_TRANS8_0 ;
out - > type = PTI_2D ;
out - > mip [ 0 ] . width = 128 ;
out - > mip [ 0 ] . height = 128 ;
out - > mip [ 0 ] . depth = 1 ;
out - > mip [ 0 ] . datasize = out - > mip [ 0 ] . width * out - > mip [ 0 ] . height * out - > mip [ 0 ] . depth ;
out - > mip [ 0 ] . data = ( char * ) mip ;
out - > mipcount = 1 ;
ImgTool_Convert ( args , out , " conchars " , NULL ) ;
break ;
}
2020-08-18 01:59:55 +00:00
ImgTool_DecodeMiptex ( args , mip , e - > dsize ) ;
2020-01-10 12:23:25 +00:00
}
break ;
2020-02-11 18:06:10 +00:00
case TYP_QPIC :
{
int * qpic = ( int * ) ( indata + e - > offset ) ;
struct pendingtextureinfo * out = Z_Malloc ( sizeof ( * out ) ) ;
size_t sz ;
qbyte * p ;
if ( e - > size < 8 | | 8 + qpic [ 0 ] * qpic [ 1 ] ! = e - > size )
{
printf ( " invalid size/header for qpic lump: %s \n " , e - > name ) ;
break ;
}
out - > type = PTI_2D ;
out - > mip [ 0 ] . width = LittleLong ( qpic [ 0 ] ) ;
out - > mip [ 0 ] . height = LittleLong ( qpic [ 1 ] ) ;
out - > mip [ 0 ] . depth = 1 ;
out - > mip [ 0 ] . datasize = out - > mip [ 0 ] . width * out - > mip [ 0 ] . height * out - > mip [ 0 ] . depth ;
out - > mip [ 0 ] . data = ( char * ) ( qpic + 2 ) ;
out - > mipcount = 1 ;
for ( sz = 0 , p = out - > mip [ 0 ] . data ; sz < out - > mip [ 0 ] . datasize ; sz + + )
if ( p [ sz ] = = 255 )
break ;
out - > encoding = sz < out - > mip [ 0 ] . datasize ? TF_TRANS8 : PTI_P8 ;
for ( i = 0 ; i < sizeof ( e - > name ) ; i + + )
{ //lowercase it.
if ( e - > name [ i ] > = ' A ' & & e - > name [ i ] < = ' Z ' )
clean [ i ] = ( e - > name [ i ] - ' A ' ) + ' a ' ;
else
clean [ i ] = e - > name [ i ] ;
}
clean [ sizeof ( e - > name ) ] = 0 ;
ImgTool_Convert ( args , out , clean , NULL ) ;
}
break ;
2020-01-10 12:23:25 +00:00
case TYP_PALETTE :
default :
printf ( " skipping %s \n " , e - > name ) ;
break ;
}
}
}
2020-02-26 07:48:01 +00:00
else if ( fsize > = sizeof ( dheader_t ) & & (
( ( indata [ 0 ] ) | ( indata [ 1 ] < < 8 ) | ( indata [ 2 ] < < 16 ) | ( indata [ 3 ] < < 24 ) ) = = BSPVERSION | |
// ((indata[0])|(indata[1]<<8)|(indata[2]<<16)|(indata[3]<<24)) == BSPVERSIONHL ||
( ( indata [ 0 ] ) | ( indata [ 1 ] < < 8 ) | ( indata [ 2 ] < < 16 ) | ( indata [ 3 ] < < 24 ) ) = = BSPVERSIONPREREL | |
( ( indata [ 0 ] ) | ( indata [ 1 ] < < 8 ) | ( indata [ 2 ] < < 16 ) | ( indata [ 3 ] < < 24 ) ) = = BSPVERSION_LONG1 | |
( ( indata [ 0 ] ) | ( indata [ 1 ] < < 8 ) | ( indata [ 2 ] < < 16 ) | ( indata [ 3 ] < < 24 ) ) = = BSPVERSION_LONG2 ) )
{ //q1bsp
dheader_t * bsp = ( dheader_t * ) indata ;
dmiptexlump_t * texlump = ( dmiptexlump_t * ) ( indata + bsp - > lumps [ LUMP_TEXTURES ] . fileofs ) ;
miptex_t * miptex ;
2020-03-07 09:00:40 +00:00
size_t i ;
2020-08-18 01:59:55 +00:00
size_t sz = bsp - > lumps [ LUMP_TEXTURES ] . filelen ;
for ( i = texlump - > nummiptex ; i - - > 0 ; )
2020-02-26 07:48:01 +00:00
{
if ( texlump - > dataofs [ i ] < 0 | | texlump - > dataofs [ i ] > = bsp - > lumps [ LUMP_TEXTURES ] . filelen )
continue ;
miptex = ( miptex_t * ) ( ( qbyte * ) texlump + texlump - > dataofs [ i ] ) ;
if ( * miptex - > name & & miptex - > width & & miptex - > height & & miptex - > offsets [ 0 ] > 0 )
2020-08-18 01:59:55 +00:00
{
ImgTool_DecodeMiptex ( args , miptex , sz - texlump - > dataofs [ i ] ) ;
sz = texlump - > dataofs [ i ] ;
}
2020-03-07 09:00:40 +00:00
}
}
2021-04-14 05:21:04 +00:00
else if ( fsize > = sizeof ( dmdl_t ) & & (
( ( indata [ 0 ] ) | ( indata [ 1 ] < < 8 ) | ( indata [ 2 ] < < 16 ) | ( indata [ 3 ] < < 24 ) ) = = IDPOLYHEADER & & ( ( dmdl_t * ) indata ) - > version = = ALIAS_VERSION ) )
{
char imgname [ 1024 ] ;
int i , j , numframes ;
dmdl_t * mdl = ( dmdl_t * ) indata ;
daliasskintype_t * pskintype = ( daliasskintype_t * ) ( indata + sizeof ( * mdl ) ) ;
daliasskingroup_t * pskingroup ;
daliasskininterval_t * intervals ;
struct pendingtextureinfo * out = Z_Malloc ( sizeof ( * out ) ) ;
out - > type = PTI_2D ;
# ifdef HEXEN2
if ( mdl - > flags & MFH2_TRANSPARENT )
out - > encoding = TF_H2_T7G1 ; //hexen2
else
# endif
if ( mdl - > flags & MFH2_HOLEY )
out - > encoding = TF_H2_TRANS8_0 ; //hexen2
# ifdef HEXEN2
else if ( mdl - > flags & MFH2_SPECIAL_TRANS )
out - > encoding = TF_H2_T4A4 ; //hexen2
# endif
else
out - > encoding = TF_SOLID8 ;
out - > mipcount = 1 ;
out - > mip [ 0 ] . datasize = mdl - > skinwidth * mdl - > skinheight ;
out - > mip [ 0 ] . width = mdl - > skinwidth ;
out - > mip [ 0 ] . height = mdl - > skinheight ;
out - > mip [ 0 ] . depth = 1 ;
for ( i = 0 ; i < mdl - > numskins ; i + + )
{
switch ( LittleLong ( pskintype - > type ) )
{
case ALIAS_SKIN_SINGLE :
out - > mip [ 0 ] . data = ( qbyte * ) ( pskintype + 1 ) ;
Q_snprintfz ( imgname , sizeof ( imgname ) , " %s_%i. " , wadname , i ) ;
ImgTool_Convert ( args , out , imgname , NULL ) ;
pskintype = ( daliasskintype_t * ) ( ( char * ) out - > mip [ 0 ] . data + out - > mip [ 0 ] . datasize ) ;
break ;
default :
pskingroup = ( daliasskingroup_t * ) ( pskintype + 1 ) ;
intervals = ( daliasskininterval_t * ) ( pskingroup + 1 ) ;
numframes = LittleLong ( pskingroup - > numskins ) ;
out - > mip [ 0 ] . data = ( qbyte * ) ( intervals + numframes ) ;
for ( j = 0 ; j < numframes ; j + + , out - > mip [ 0 ] . data = ( char * ) out - > mip [ 0 ] . data + out - > mip [ 0 ] . datasize )
{
Q_snprintfz ( imgname , sizeof ( imgname ) , " %s_%i_%i. " , wadname , i , j ) ;
ImgTool_Convert ( args , out , imgname , NULL ) ;
}
pskintype = ( daliasskintype_t * ) out - > mip [ 0 ] . data ;
break ;
}
}
}
2020-03-07 09:00:40 +00:00
else
printf ( " %s: does not appear to be a wad file \n " , wadname ) ;
}
//spits out our extended .mip format
static qboolean ImgTool_MipExport ( struct opts_s * args , vfsfile_t * outfile , struct pendingtextureinfo * in , const char * mipname , int wadtype )
{
struct pendingtextureinfo * highcolour = NULL ;
char * highcode = NULL , * ext ;
size_t u ;
unsigned int m , tsz ;
miptex_t mip ;
static qboolean mippixelformats [ PTI_MAX ] = { [ PTI_P8 ] = true } ;
if ( in )
{
if ( in - > mipcount = = 1 )
Image_GenerateMips ( in , args - > flags ) ;
if ( ! in - > mipcount )
{
Con_Printf ( " %s: unable to load any mips \n " , mipname ) ;
return false ;
}
}
if ( in - > encoding = = PTI_P8 | | args - > newpixelformat = = PTI_INVALID )
{
in = ImgTool_DupeMipchain ( in ) ;
highcode = NULL ; //no, don't store it weirdly...
}
else
{
highcolour = in ;
in = ImgTool_DupeMipchain ( in ) ;
Image_GenerateMips ( highcolour , args - > flags ) ;
for ( u = 1 ; u < countof ( sh_config . texfmt ) ; u + + )
sh_config . texfmt [ u ] = true ;
if ( ! ImgTool_ConvertPixelFormat ( args , mipname , highcolour ) )
{
Con_Printf ( " %s: Unable to convert to requested pixel format \n " , mipname ) ;
2020-08-18 01:59:55 +00:00
// ImgTool_FreeMips(highcolour);
2020-03-07 09:00:40 +00:00
highcolour = NULL ;
}
else if ( highcolour - > mip [ highcolour - > mipcount - 1 ] . width ! = 1 | | highcolour - > mip [ highcolour - > mipcount - 1 ] . height ! = 1 )
{
Con_Printf ( " %s: Mipchain truncated \n " , mipname ) ;
2020-08-18 01:59:55 +00:00
// ImgTool_FreeMips(highcolour);
2020-03-07 09:00:40 +00:00
highcolour = NULL ;
}
else for ( u = 1 ; u < highcolour - > mipcount ; u + + )
{ //mip chain must round down consistently.
if ( highcolour - > mip [ u ] . width ! = max ( 1 , highcolour - > mip [ u - 1 ] . width > > 1 ) | |
highcolour - > mip [ u ] . height ! = max ( 1 , highcolour - > mip [ u - 1 ] . height > > 1 ) )
2020-02-26 07:48:01 +00:00
{
2020-03-07 09:00:40 +00:00
Con_Printf ( " %s: Mipchain sized wrongly \n " , mipname ) ;
2020-08-18 01:59:55 +00:00
// ImgTool_FreeMips(highcolour);
2020-03-07 09:00:40 +00:00
highcolour = NULL ;
break ;
}
}
if ( highcolour ) switch ( highcolour - > encoding )
{
case PTI_BC1_RGB :
case PTI_BC1_RGBA : highcode = " BC1 " ; break ; //not in any core gl, but uniquitous on desktop, but not mobile.
case PTI_BC2_RGBA : highcode = " BC2 " ; break ;
case PTI_BC3_RGBA : highcode = " BC3 " ; break ;
case PTI_BC4_R : highcode = " BC4 " ; break ;
case PTI_BC5_RG : highcode = " BC5 " ; break ;
case PTI_BC6_RGB_UFLOAT : highcode = " BC6 " ; break ; //aka bptc, core in gl4.2 (not gles)
case PTI_BC7_RGBA : highcode = " BC7 " ; break ; //aka bptc, core in gl4.2 (not gles)
case PTI_ETC1_RGB8 : highcode = " ETC1 " ; break ; //available on most gles2 devices.
case PTI_ETC2_RGB8 : highcode = " ETC2 " ; break ; //core in gles3 (or gl4.3)
case PTI_ETC2_RGB8A1 : highcode = " ETCP " ; break ; //core in gles3 (or gl4.3)
case PTI_ETC2_RGB8A8 : highcode = " ETCA " ; break ; //core in gles3 (or gl4.3)
case PTI_ASTC_4X4_LDR : highcode = " AST4 " ; break ; //core in gles3.2
case PTI_ASTC_5X4_LDR : highcode = " AS54 " ; break ; //core in gles3.2
case PTI_ASTC_5X5_LDR : highcode = " AST5 " ; break ; //core in gles3.2
case PTI_ASTC_6X5_LDR : highcode = " AS65 " ; break ; //core in gles3.2
case PTI_ASTC_6X6_LDR : highcode = " AST6 " ; break ; //core in gles3.2
case PTI_ASTC_8X5_LDR : highcode = " AS85 " ; break ; //core in gles3.2
case PTI_ASTC_8X6_LDR : highcode = " AS86 " ; break ; //core in gles3.2
case PTI_ASTC_10X5_LDR : highcode = " AS05 " ; break ; //core in gles3.2
case PTI_ASTC_10X6_LDR : highcode = " AS06 " ; break ; //core in gles3.2
case PTI_ASTC_8X8_LDR : highcode = " AST8 " ; break ; //core in gles3.2
case PTI_ASTC_10X8_LDR : highcode = " AS08 " ; break ; //core in gles3.2
case PTI_ASTC_10X10_LDR : highcode = " AST0 " ; break ; //core in gles3.2
case PTI_ASTC_12X10_LDR : highcode = " AS20 " ; break ; //core in gles3.2
case PTI_ASTC_12X12_LDR : highcode = " AST2 " ; break ; //core in gles3.2
case PTI_RGB565 : highcode = " 565 " ; break ;
case PTI_RGBA5551 : highcode = " 5551 " ; break ;
case PTI_RGBA4444 : highcode = " 4444 " ; break ;
case PTI_RGB8 : highcode = " RGB " ; break ; //generally needs reformatting to rgbx.
case PTI_RGBA8 : highcode = " RGBA " ; break ; //bloaty
case PTI_L8 : highcode = " LUM8 " ; break ;
case PTI_E5BGR9 : highcode = " EXP5 " ; break ; //gl3+
default :
Con_Printf ( " %s: unsupported pixel format(%s) for miptex \n " , mipname , Image_FormatName ( highcolour - > encoding ) ) ;
2020-08-18 01:59:55 +00:00
// ImgTool_FreeMips(highcolour);
2020-03-07 09:00:40 +00:00
highcolour = NULL ;
break ;
}
}
2020-02-26 07:48:01 +00:00
2020-03-07 09:00:40 +00:00
if ( args - > width & & args - > height & & in - > mipcount > = 1 )
{
qbyte * newimg ;
2020-04-29 10:43:22 +00:00
unsigned int bb , bw , bh , bd ;
Image_BlockSizeForEncoding ( in - > encoding , & bb , & bw , & bh , & bd ) ;
2020-03-07 09:00:40 +00:00
newimg = Image_ResampleTexture ( in - > encoding , in - > mip [ 0 ] . data , in - > mip [ 0 ] . width , in - > mip [ 0 ] . height , NULL , args - > width , args - > height ) ;
if ( newimg )
{
in - > mipcount = 1 ; //urgh
if ( in - > mip [ 0 ] . needfree )
BZ_Free ( in - > mip [ 0 ] . data ) ;
in - > mip [ 0 ] . data = newimg ;
in - > mip [ 0 ] . needfree = true ;
in - > mip [ 0 ] . width = args - > width ;
in - > mip [ 0 ] . height = args - > height ;
2020-04-29 10:43:22 +00:00
in - > mip [ 0 ] . depth = 1 ;
in - > mip [ 0 ] . datasize = bb * ( ( in - > mip [ 0 ] . width + bw - 1 ) / bw ) * ( ( in - > mip [ 0 ] . height + bh - 1 ) / bh ) * ( ( in - > mip [ 0 ] . depth + bd - 1 ) / bd ) ;
2020-03-07 09:00:40 +00:00
Image_GenerateMips ( in , args - > flags ) ;
}
else
Con_Printf ( " %s: unable to resize %s \n " , mipname , Image_FormatName ( in - > encoding ) ) ;
}
if ( args - > mipnum > = in - > mipcount )
{
Con_Printf ( " %s: not enough mips \n " , mipname ) ;
return false ;
}
//strip out all but the 4 mip levels we care about.
for ( u = 0 ; u < in - > mipcount ; u + + )
{
if ( u > = args - > mipnum & & u < args - > mipnum + 4 )
{
if ( ! wadtype )
{ //if we're stripping out the wad data (so that the engine ends up requiring external textures) then do it now before palettizing, for efficiency.
if ( in - > mip [ u ] . needfree )
BZ_Free ( in - > mip [ u ] . data ) ;
in - > mip [ u ] . data = NULL ;
in - > mip [ u ] . datasize = 0 ;
2020-02-26 07:48:01 +00:00
}
}
2020-03-07 09:00:40 +00:00
else
{
if ( in - > mip [ u ] . needfree )
BZ_Free ( in - > mip [ u ] . data ) ;
memset ( & in - > mip [ u ] , 0 , sizeof ( in - > mip [ u ] ) ) ;
}
}
in - > mipcount - = args - > mipnum ;
if ( in - > mipcount > 4 )
in - > mipcount = 4 ;
memmove ( & in - > mip [ 0 ] , & in - > mip [ args - > mipnum ] , sizeof ( in - > mip [ 0 ] ) * in - > mipcount ) ;
memset ( & in - > mip [ in - > mipcount ] , 0 , sizeof ( in - > mip [ 0 ] ) * ( ( args - > mipnum + 4 ) - in - > mipcount ) ) ; //null it out, just in case.
if ( in - > mip [ 0 ] . data )
{
if ( in - > encoding ! = PTI_P8 )
Image_ChangeFormat ( in , mippixelformats , ( * mipname = = ' { ' ) ? TF_TRANS8 : PTI_INVALID , mipname ) ;
if ( in - > encoding ! = PTI_P8 )
{ //erk! we failed to palettize...
ImgTool_FreeMips ( in ) ;
ImgTool_FreeMips ( highcolour ) ;
Con_Printf ( " %s: paletizing error (source format %s) \n " , mipname , Image_FormatName ( in - > encoding ) ) ;
return false ;
}
}
if ( ! in - > mip [ 0 ] . width | | ( in - > mip [ 0 ] . width & 15 ) )
Con_Printf ( " %s(%i): WARNING: miptex width is not a multiple of 16 - %i*%i \n " , mipname , args - > mipnum , in - > mip [ 0 ] . width , in - > mip [ 0 ] . height ) ;
if ( ! in - > mip [ 0 ] . height | | ( in - > mip [ 0 ] . height & 15 ) )
Con_Printf ( " %s(%i): WARNING: miptex height is not a multiple of 16 - %i*%i \n " , mipname , args - > mipnum , in - > mip [ 0 ] . width , in - > mip [ 0 ] . height ) ;
memset ( mip . name , 0 , sizeof ( mip . name ) ) ;
Q_strncpyz ( mip . name , mipname , sizeof ( mip . name ) ) ;
ext = ( char * ) COM_GetFileExtension ( mip . name , NULL ) ;
while ( * ext ) * ext + + = 0 ;
if ( * mip . name = = ' # ' )
* mip . name = ' * ' ; //make it a proper turb
mip . width = in - > mip [ 0 ] . width ;
mip . height = in - > mip [ 0 ] . height ;
mip . offsets [ 0 ] = in - > mip [ 0 ] . datasize ? sizeof ( mip ) : 0 ;
mip . offsets [ 1 ] = in - > mip [ 1 ] . datasize ? mip . offsets [ 0 ] + in - > mip [ 0 ] . datasize : 0 ;
mip . offsets [ 2 ] = in - > mip [ 2 ] . datasize ? mip . offsets [ 1 ] + in - > mip [ 1 ] . datasize : 0 ;
mip . offsets [ 3 ] = in - > mip [ 3 ] . datasize ? mip . offsets [ 2 ] + in - > mip [ 2 ] . datasize : 0 ;
tsz = sizeof ( mip ) + in - > mip [ 0 ] . datasize + in - > mip [ 1 ] . datasize + in - > mip [ 2 ] . datasize + in - > mip [ 3 ] . datasize ;
VFS_WRITE ( outfile , & mip , sizeof ( mip ) ) ;
VFS_WRITE ( outfile , in - > mip [ 0 ] . data , in - > mip [ 0 ] . datasize ) ;
VFS_WRITE ( outfile , in - > mip [ 1 ] . data , in - > mip [ 1 ] . datasize ) ;
VFS_WRITE ( outfile , in - > mip [ 2 ] . data , in - > mip [ 2 ] . datasize ) ;
VFS_WRITE ( outfile , in - > mip [ 3 ] . data , in - > mip [ 3 ] . datasize ) ;
if ( wadtype = = 2 )
{
tsz + = 2 + 256 * 3 ;
VFS_WRITE ( outfile , " \x00 \x01 " , 2 ) ;
VFS_WRITE ( outfile , host_basepal , 256 * 3 ) ;
}
if ( highcolour )
{
unsigned int highsize ;
VFS_WRITE ( outfile , " \x00 \xfb \x2b \xaf " , 4 ) ; //magic id to say that there's actually extensions here...
tsz + = 4 ;
//spit out our high-colour lump here
for ( highsize = 16 , m = 0 ; m < highcolour - > mipcount ; m + + )
highsize + = highcolour - > mip [ m ] . datasize ;
VFS_WRITE ( outfile , & highsize , 4 ) ;
VFS_WRITE ( outfile , highcode , 4 ) ;
VFS_WRITE ( outfile , & highcolour - > mip [ 0 ] . width , 4 ) ;
VFS_WRITE ( outfile , & highcolour - > mip [ 0 ] . height , 4 ) ;
for ( m = 0 ; m < highcolour - > mipcount ; m + + )
VFS_WRITE ( outfile , highcolour - > mip [ m ] . data , highcolour - > mip [ m ] . datasize ) ;
tsz + = highsize ;
Con_Printf ( " %s: %ix%i (%s: %ix%i %i) \n " , mip . name , mip . width , mip . height , highcode , highcolour - > mip [ 0 ] . width , highcolour - > mip [ 0 ] . height , highcolour - > mipcount ) ;
2020-02-26 07:48:01 +00:00
}
2020-01-10 12:23:25 +00:00
else
2020-03-07 09:00:40 +00:00
Con_Printf ( " %s: %ix%i \n " , mip . name , mip . width , mip . height ) ;
//and pad it, just in case.
if ( tsz & 3 )
VFS_WRITE ( outfile , " \0 \0 \0 \0 " , 4 - ( tsz & 3 ) ) ;
ImgTool_FreeMips ( in ) ;
return true ;
2020-01-10 12:23:25 +00:00
}
static void ImgTool_WadConvert ( struct opts_s * args , const char * destpath , const char * * srcpaths , size_t numpaths , int wadtype /*x,2,3*/ )
2019-10-06 01:59:13 +00:00
{
char file [ MAX_OSPATH ] ;
2020-03-07 09:00:40 +00:00
const char * exts [ ] = { " .mip " , " .png " , " .bmp " , " .tga " , " .exr " , " .hdr " , " .dds " , " .ktx " , " .xcf " , " .pcx " , " .jpg " , NULL } ;
2019-10-06 01:59:13 +00:00
struct filelist_s list = { exts } ;
size_t i , u ;
vfsfile_t * f ;
char * inname ;
qbyte * indata ;
size_t fsize ;
wad2_t wad2 ;
wad2entry_t * wadentries = NULL , * entry ;
2019-10-14 02:36:13 +00:00
size_t maxentries = 0 ;
2020-03-07 09:00:40 +00:00
qboolean qpics ;
struct pendingtextureinfo * in ;
2020-01-10 12:23:25 +00:00
if ( ! numpaths )
ImgTool_TreeScan ( & list , " . " , NULL ) ;
else while ( numpaths - - > 0 )
ImgTool_TreeScan ( & list , * srcpaths + + , NULL ) ;
if ( ! list . numfiles )
{
printf ( " %s: No files specified \n " , destpath ) ;
return ;
}
2019-10-06 01:59:13 +00:00
2020-08-18 01:59:55 +00:00
if ( ! strcasecmp ( COM_GetFileExtension ( destpath , NULL ) , " .bsp " ) )
{
2020-01-10 12:23:25 +00:00
}
2020-08-18 01:59:55 +00:00
else
2019-10-06 01:59:13 +00:00
{
2020-08-18 01:59:55 +00:00
qpics = ! strcasecmp ( " gfx.wad " , COM_SkipPath ( destpath ) ) ;
f = FS_OpenVFS ( destpath , " wb " , FS_SYSTEM ) ;
wad2 . magic [ 0 ] = ' W ' ;
wad2 . magic [ 1 ] = ' A ' ;
wad2 . magic [ 2 ] = ' D ' ;
wad2 . magic [ 3 ] = ( wadtype = = 2 ) ? ' 3 ' : ' 2 ' ; //wad3 instead of 2, so we can include a palette for tools to validate against
wad2 . num = 0 ;
wad2 . offset = 0 ;
VFS_WRITE ( f , & wad2 , 12 ) ;
if ( wadtype = = 1 )
{ //WAD2 texture files generally have a palette lump.
if ( wad2 . num = = maxentries )
{
maxentries + = 64 ;
wadentries = realloc ( wadentries , sizeof ( * wadentries ) * maxentries ) ;
}
entry = & wadentries [ wad2 . num + + ] ;
memset ( entry , 0 , sizeof ( * entry ) ) ;
Q_strncpyz ( entry - > name , " PALETTE " , 16 ) ;
entry - > type = TYP_PALETTE ;
entry - > offset = VFS_TELL ( f ) ;
//and the lump data.
VFS_WRITE ( f , host_basepal , 256 * 3 ) ;
entry - > size = entry - > dsize = VFS_TELL ( f ) - entry - > offset ;
2020-03-07 09:00:40 +00:00
}
2019-10-14 02:36:13 +00:00
2020-08-18 01:59:55 +00:00
for ( i = 0 ; i < list . numfiles ; i + + )
2020-03-07 09:00:40 +00:00
{
2020-08-18 01:59:55 +00:00
Q_snprintfz ( file , sizeof ( file ) , " %s/%s " , list . file [ i ] . rootpath , list . file [ i ] . name ) ;
inname = list . file [ i ] . name ;
if ( list . file [ i ] . baselen > 15 )
2019-10-14 02:36:13 +00:00
{
2020-08-18 01:59:55 +00:00
Con_Printf ( " Path too long for wad - %s \n " , inname ) ;
2019-10-06 01:59:13 +00:00
continue ;
}
2020-08-18 01:59:55 +00:00
indata = FS_LoadMallocFile ( file , & fsize ) ;
if ( ! indata )
2020-01-10 12:23:25 +00:00
{
2020-08-18 01:59:55 +00:00
Con_Printf ( " Unable to open %s \n " , inname ) ;
continue ;
2020-01-10 12:23:25 +00:00
}
2019-10-06 01:59:13 +00:00
2020-08-18 01:59:55 +00:00
if ( wad2 . num = = maxentries )
2020-02-11 18:06:10 +00:00
{
2020-08-18 01:59:55 +00:00
maxentries + = 64 ;
wadentries = realloc ( wadentries , sizeof ( * wadentries ) * maxentries ) ;
}
entry = & wadentries [ wad2 . num ] ;
memset ( entry , 0 , sizeof ( * entry ) ) ;
Q_strncpyz ( entry - > name , inname , 16 ) ;
if ( list . file [ i ] . baselen < sizeof ( entry - > name ) )
entry - > name [ list . file [ i ] . baselen ] = 0 ; //kill any .tga
if ( * entry - > name = = ' # ' )
* entry - > name = ' * ' ; //* is not valid in a filename, yet needed for turbs, so by convention # is used instead. this is only relevant for the first char.
entry - > type = TYP_MIPTEX ;
entry - > offset = VFS_TELL ( f ) ;
if ( ! strcasecmp ( COM_GetFileExtension ( file , NULL ) , " .mip " ) )
{ //.mip files can just be loaded directly
//I just hope they are actually q1 format and not hl, for instance.
if ( wadtype = = 3 )
2020-02-11 18:06:10 +00:00
{
2020-08-18 01:59:55 +00:00
Con_Printf ( " refusing to inject q1 miptex into halflife wad-3 file \n " ) ;
Z_Free ( indata ) ;
continue ;
2020-02-11 18:06:10 +00:00
}
2020-08-18 01:59:55 +00:00
VFS_WRITE ( f , indata , fsize ) ;
wad2 . num + + ;
entry - > size = entry - > dsize = VFS_TELL ( f ) - entry - > offset ;
Z_Free ( indata ) ;
2020-02-11 18:06:10 +00:00
}
2020-08-18 01:59:55 +00:00
else
{
if ( wadtype = = 3 )
{
for ( u = 0 ; u < sizeof ( entry - > name ) ; u + + )
entry - > name [ u ] = toupper ( entry - > name [ u ] ) ;
entry - > type = 67 ; //halflife's mips actually use a different type from q1 ones.
}
2019-10-06 01:59:13 +00:00
2020-08-18 01:59:55 +00:00
//try to decompress everything to a nice friendly palletizable range.
for ( u = 1 ; u < countof ( sh_config . texfmt ) ; u + + )
sh_config . texfmt [ u ] = ( u = = PTI_RGBA8 ) | | ( u = = PTI_RGBX8 ) | | ( u = = PTI_P8 ) | | ( u = = args - > newpixelformat ) ;
in = Image_LoadMipsFromMemory ( args - > flags , inname , file , indata , fsize ) ;
if ( qpics )
{
if ( ! strcasecmp ( entry - > name , " CONCHARS " ) & & in - > mip [ 0 ] . width = = 128 & & in - > mip [ 0 ] . height = = 128 )
entry - > type = TYP_MIPTEX ; //yes, weird. match vanilla quake. explicitly avoid qpic to avoid corruption in the first 8 bytes (due to the engine's early endian swapping)
//FIXME: encoding should be pti_trans8_0...
else
{
entry - > type = TYP_QPIC ;
//qpics need a header
VFS_WRITE ( f , & in - > mip [ 0 ] . width , sizeof ( int ) ) ;
VFS_WRITE ( f , & in - > mip [ 0 ] . height , sizeof ( int ) ) ;
}
//and now the 8bit pixel data itself
VFS_WRITE ( f , in - > mip [ 0 ] . data , in - > mip [ 0 ] . datasize ) ;
}
else if ( ! ImgTool_MipExport ( args , f , in , entry - > name , wadtype ) )
continue ;
wad2 . num + + ;
entry - > size = entry - > dsize = VFS_TELL ( f ) - entry - > offset ;
}
2019-09-29 03:08:01 +00:00
}
2020-08-18 01:59:55 +00:00
wad2 . offset = VFS_TELL ( f ) ;
VFS_WRITE ( f , wadentries , sizeof ( * wadentries ) * wad2 . num ) ;
VFS_SEEK ( f , 0 ) ;
VFS_WRITE ( f , & wad2 , sizeof ( wad2 ) ) ;
VFS_CLOSE ( f ) ;
2019-09-29 03:08:01 +00:00
}
2019-10-06 01:59:13 +00:00
2020-03-07 09:00:40 +00:00
free ( wadentries ) ;
2019-10-06 01:59:13 +00:00
FileList_Release ( & list ) ;
2019-09-29 03:08:01 +00:00
}
2019-10-14 02:36:13 +00:00
2021-04-14 05:21:04 +00:00
# ifdef FTE_SDL
static void SDLL_Loop ( void ) ;
static void ImgTool_View ( const char * inname , struct pendingtextureinfo * in ) ;
# endif
2019-09-29 03:08:01 +00:00
int main ( int argc , const char * * argv )
{
2020-03-07 09:00:40 +00:00
static const struct
{
const char * alias ;
uploadfmt_t fmt ;
} fmtaliases [ ] = {
{ " BC1 " , PTI_BC1_RGBA } ,
{ " BC2 " , PTI_BC2_RGBA } ,
{ " BC3 " , PTI_BC3_RGBA } ,
{ " BC4 " , PTI_BC4_R } ,
{ " BC5 " , PTI_BC5_RG } ,
{ " BC6 " , PTI_BC6_RGB_UFLOAT } ,
{ " BC7 " , PTI_BC7_RGBA } ,
{ " ETC1 " , PTI_ETC1_RGB8 } ,
{ " ETC2 " , PTI_ETC2_RGB8 } ,
{ " ETCP " , PTI_ETC2_RGB8A1 } ,
{ " ETCA " , PTI_ETC2_RGB8A8 } ,
{ " ASTC4x4 " , PTI_ASTC_4X4_LDR } ,
{ " ASTC5x4 " , PTI_ASTC_5X4_LDR } ,
{ " ASTC5x5 " , PTI_ASTC_5X5_LDR } ,
{ " ASTC6x5 " , PTI_ASTC_6X5_LDR } ,
{ " ASTC6x6 " , PTI_ASTC_6X6_LDR } ,
{ " ASTC8x5 " , PTI_ASTC_8X5_LDR } ,
{ " ASTC8x6 " , PTI_ASTC_8X6_LDR } ,
{ " ASTC10x5 " , PTI_ASTC_10X5_LDR } ,
{ " ASTC10x6 " , PTI_ASTC_10X6_LDR } ,
{ " ASTC8x8 " , PTI_ASTC_8X8_LDR } ,
{ " ASTC10x8 " , PTI_ASTC_10X8_LDR } ,
{ " ASTC10x10 " , PTI_ASTC_10X10_LDR } ,
{ " ASTC12x10 " , PTI_ASTC_12X10_LDR } ,
{ " ASTC12x12 " , PTI_ASTC_12X12_LDR } ,
{ " LUM8 " , PTI_L8 } ,
{ " RGBA " , PTI_RGBA8 } ,
{ " RGB " , PTI_RGB8 } ,
} ;
2019-09-29 03:08:01 +00:00
enum
{
2020-03-07 09:00:40 +00:00
mode_unspecified ,
2019-09-29 03:08:01 +00:00
mode_info ,
2021-04-14 05:21:04 +00:00
# ifdef FTE_SDL
mode_view ,
# endif
2019-09-29 03:08:01 +00:00
mode_convert ,
2019-10-06 01:59:13 +00:00
mode_autotree ,
2019-10-14 02:36:13 +00:00
mode_genwadx ,
mode_genwad2 ,
mode_genwad3 ,
2020-01-10 12:23:25 +00:00
mode_extractwad ,
2020-03-07 09:00:40 +00:00
} mode = mode_unspecified ;
2019-09-29 03:08:01 +00:00
size_t u , f ;
2019-10-18 08:37:38 +00:00
qboolean nomoreopts = false ;
2019-09-29 03:08:01 +00:00
struct opts_s args ;
2019-10-18 08:37:38 +00:00
size_t files = 0 ;
2020-03-07 09:00:40 +00:00
const char * outname = NULL ;
2019-09-29 03:08:01 +00:00
for ( u = 1 ; u < countof ( sh_config . texfmt ) ; u + + )
sh_config . texfmt [ u ] = true ;
args . flags = 0 ;
args . newpixelformat = PTI_INVALID ;
args . mipnum = 0 ;
2020-03-07 09:00:40 +00:00
args . textype = PTI_ANY ;
2020-01-10 12:23:25 +00:00
args . defaultext = NULL ;
2020-03-07 09:00:40 +00:00
args . width = args . height = 0 ;
2019-09-29 03:08:01 +00:00
2019-10-14 02:36:13 +00:00
ImgTool_SetupPalette ( ) ;
2019-09-29 03:08:01 +00:00
if ( argc = = 1 )
goto showhelp ;
for ( u = 1 ; u < argc ; u + + )
{
2019-10-18 08:37:38 +00:00
if ( * argv [ u ] = = ' - ' & & ! nomoreopts )
2019-09-29 03:08:01 +00:00
{
2019-10-18 08:37:38 +00:00
if ( ! strcmp ( argv [ u ] , " -- " ) )
nomoreopts = true ;
else if ( ! strcmp ( argv [ u ] , " -? " ) | | ! strcmp ( argv [ u ] , " --help " ) )
2019-09-29 03:08:01 +00:00
{
showhelp :
2020-02-26 07:48:01 +00:00
Con_Printf ( DISTRIBUTION " Image Tool \n " ) ;
2020-06-27 19:32:21 +00:00
Con_Printf ( " show info : %s [-i] in.ktx [in2.ext ...] \n " , argv [ 0 ] ) ;
Con_Printf ( " compress : %s [-c] --ext ktx --astc_6x6_ldr [--nomips] in.png [in2.png ...] \n " , argv [ 0 ] ) ;
Con_Printf ( " compress : %s [-c] --ext dds --bc3 [--premul] [--nomips] in.png \n \t Convert pixel format (to bc3 aka dxt5) before writing to output file. \n " , argv [ 0 ] ) ;
Con_Printf ( " convert : %s [-c] --ext png in.exr [in2.pcx ...] \n \t Convert input file(s) to different file format, while trying to preserve pixel formats. \n " , argv [ 0 ] ) ;
2020-03-07 09:00:40 +00:00
Con_Printf ( " merge : %s -o output [--cube|--3d|--2darray|--cubearray] [--bc1] foo_*.png \n \t Convert to different file format, while trying to preserve pixel formats. \n " , argv [ 0 ] ) ;
2020-06-27 19:32:21 +00:00
Con_Printf ( " recursive : %s -r [--ext dds] --astc_6x6_ldr destdir srcdir \n \t Compresses the files to dds (writing to an optionally different directory) \n " , argv [ 0 ] ) ;
2020-01-10 12:23:25 +00:00
Con_Printf ( " decompress : %s --decompress [--exportmip 0] [--nomips] in.ktx out.png \n \t Decompresses any block-compressed pixel data. \n " , argv [ 0 ] ) ;
2020-06-27 19:32:21 +00:00
Con_Printf ( " create mips: %s [-c] --ext mip [--bc1] [--resize width height] [--exportmip 2] *.dds \n " , argv [ 0 ] ) ;
2020-03-07 09:00:40 +00:00
Con_Printf ( " create xwad: %s --genwadx [--exportmip 2] [--bc1] out.wad srcdir \n " , argv [ 0 ] ) ;
Con_Printf ( " create wad : %s -w [--exportmip 2] out.wad *.mipsrcdir \n " , argv [ 0 ] ) ;
2020-01-10 12:23:25 +00:00
Con_Printf ( " extract wad: %s -x [--ext png] src.wad \n " , argv [ 0 ] ) ;
2020-02-26 07:48:01 +00:00
Con_Printf ( " extract bsp: %s -x [--ext png] src.bsp \n " , argv [ 0 ] ) ;
2019-09-29 03:08:01 +00:00
Image_PrintInputFormatVersions ( ) ;
2019-10-14 02:36:13 +00:00
Con_Printf ( " Supported compressed/interesting pixelformats are: \n " ) ;
2019-09-29 03:08:01 +00:00
for ( f = 0 ; f < PTI_MAX ; f + + )
{
2020-04-29 10:43:22 +00:00
int bb , bw , bh , bd ;
Image_BlockSizeForEncoding ( f , & bb , & bw , & bh , & bd ) ;
2019-09-29 03:08:01 +00:00
if ( f > = PTI_ASTC_FIRST & & f < = PTI_ASTC_LAST )
2020-03-07 09:00:40 +00:00
{
if ( f > = PTI_ASTC_4X4_SRGB )
continue ;
2020-04-29 10:43:22 +00:00
Con_Printf ( " --%-16s %5.3g-bpp (requires astcenc) \n " , Image_FormatName ( f ) , 8 * ( float ) bb / ( bw * bh * bd ) ) ;
2020-03-07 09:00:40 +00:00
}
else if ( f = = PTI_BC1_RGB | | f = = PTI_BC1_RGBA | | f = = PTI_BC2_RGBA | | f = = PTI_BC3_RGBA | | f = = PTI_BC4_R | | f = = PTI_BC5_RG )
2020-04-29 10:43:22 +00:00
Con_Printf ( " --%-16s %5.3g-bpp (requires nvcompress) \n " , Image_FormatName ( f ) , 8 * ( float ) bb / ( bw * bh * bd ) ) ;
2019-10-06 01:59:13 +00:00
else if ( f = = PTI_BC6_RGB_UFLOAT | | f = = PTI_BC6_RGB_SFLOAT | | f = = PTI_BC7_RGBA )
2020-04-29 10:43:22 +00:00
Con_Printf ( " --%-16s %5.3g-bpp (requires nvcompress 2.1+) \n " , Image_FormatName ( f ) , 8 * ( float ) bb / ( bw * bh * bd ) ) ;
2019-10-14 02:36:13 +00:00
else if ( f = = PTI_RGBA16F | |
f = = PTI_RGBA32F | |
f = = PTI_E5BGR9 | |
f = = PTI_B10G11R11F | |
f = = PTI_RGB565 | |
f = = PTI_RGBA4444 | |
f = = PTI_ARGB4444 | |
f = = PTI_RGBA5551 | |
f = = PTI_ARGB1555 | |
f = = PTI_A2BGR10 | |
// f==PTI_R8 ||
// f==PTI_R16 ||
// f==PTI_R16F ||
// f==PTI_R32F ||
f = = PTI_RG8 | |
f = = PTI_L8 | |
f = = PTI_L8A8 | |
0 )
2020-04-29 10:43:22 +00:00
Con_Printf ( " --%-16s %5.3g-bpp \n " , Image_FormatName ( f ) , 8 * ( float ) bb / ( bw * bh * bd ) ) ;
2019-10-14 02:36:13 +00:00
// else
2020-04-29 10:43:22 +00:00
// Con_DPrintf(" --%-16s %5.3g-bpp (unsupported)\n", Image_FormatName(f), 8*(float)bb/(bw*bh*bd));
2019-09-29 03:08:01 +00:00
}
2019-10-18 08:37:38 +00:00
return EXIT_SUCCESS ;
2019-09-29 03:08:01 +00:00
}
2019-10-18 08:37:38 +00:00
else if ( ! files & & ( ! strcmp ( argv [ u ] , " -c " ) | | ! strcmp ( argv [ u ] , " --convert " ) ) )
2019-09-29 03:08:01 +00:00
mode = mode_convert ;
2019-10-18 08:37:38 +00:00
else if ( ! files & & ( ! strcmp ( argv [ u ] , " -d " ) | | ! strcmp ( argv [ u ] , " --decompress " ) ) )
2019-10-06 01:59:13 +00:00
{ //remove any (weird) gpu formats
2019-09-29 03:08:01 +00:00
for ( f = PTI_BC1_RGB ; f < PTI_ASTC_LAST ; f + + )
sh_config . texfmt [ f ] = false ;
mode = mode_convert ;
}
2019-10-18 08:37:38 +00:00
else if ( ! files & & ( ! strcmp ( argv [ u ] , " -r " ) | | ! strcmp ( argv [ u ] , " --auto " ) ) )
2019-09-29 03:08:01 +00:00
mode = mode_autotree ;
2019-10-18 08:37:38 +00:00
else if ( ! files & & ( ! strcmp ( argv [ u ] , " -i " ) | | ! strcmp ( argv [ u ] , " --info " ) ) )
2019-09-29 03:08:01 +00:00
mode = mode_info ;
2021-04-14 05:21:04 +00:00
# ifdef FTE_SDL
else if ( ! files & & ( ! strcmp ( argv [ u ] , " -v " ) | | ! strcmp ( argv [ u ] , " --view " ) ) )
mode = mode_view ;
# endif
2019-10-18 08:37:38 +00:00
else if ( ! files & & ( ! strcmp ( argv [ u ] , " -w " ) | | ! strcmp ( argv [ u ] , " --genwad2 " ) ) )
2019-10-14 02:36:13 +00:00
mode = mode_genwad2 ;
2020-03-07 09:00:40 +00:00
else if ( ! files & & ( ! strcmp ( argv [ u ] , " -w " ) | | ! strcmp ( argv [ u ] , " --genwad3 " ) ) )
mode = mode_genwad3 ;
2019-10-18 08:37:38 +00:00
else if ( ! files & & ( ! strcmp ( argv [ u ] , " -w " ) | | ! strcmp ( argv [ u ] , " --genwadx " ) ) )
2019-10-14 02:36:13 +00:00
mode = mode_genwadx ;
2020-01-10 12:23:25 +00:00
else if ( ! files & & ( ! strcmp ( argv [ u ] , " -x " ) | | ! strcmp ( argv [ u ] , " --extractwad " ) ) )
mode = mode_extractwad ;
2020-03-07 09:00:40 +00:00
else if ( ! files & & ( ! strcmp ( argv [ u ] , " -v " ) | | ! strcmp ( argv [ u ] , " --verbose " ) ) )
verbose = true ;
else if ( ! files & & ( ! strcmp ( argv [ u ] , " -o " ) | | ! strcmp ( argv [ u ] , " --outfile " ) ) )
{
if ( u + 1 < argc )
outname = argv [ + + u ] ;
else
{
Con_Printf ( " --outfile requires output filename \n " ) ;
return 1 ;
}
}
else if ( ! strcmp ( argv [ u ] , " --resize " ) )
{
if ( u + 2 < argc )
{
args . width = atoi ( argv [ + + u ] ) ;
args . height = atoi ( argv [ + + u ] ) ;
}
else
{
Con_Printf ( " --resize requires width+height values \n " ) ;
return 1 ;
}
}
2019-10-18 08:37:38 +00:00
else if ( ! strcmp ( argv [ u ] , " --2d " ) )
args . textype = PTI_2D ;
else if ( ! strcmp ( argv [ u ] , " --3d " ) )
args . textype = PTI_3D ;
else if ( ! strcmp ( argv [ u ] , " --cube " ) )
args . textype = PTI_CUBE ;
else if ( ! strcmp ( argv [ u ] , " --2darray " ) )
args . textype = PTI_2D_ARRAY ;
else if ( ! strcmp ( argv [ u ] , " --cubearray " ) )
args . textype = PTI_CUBE_ARRAY ;
2019-09-29 03:08:01 +00:00
else if ( ! strcmp ( argv [ u ] , " --nomips " ) )
args . flags | = IF_NOMIPMAP ;
else if ( ! strcmp ( argv [ u ] , " --mips " ) )
args . flags & = ~ IF_NOMIPMAP ;
2019-10-06 01:59:13 +00:00
else if ( ! strcmp ( argv [ u ] , " --premul " ) )
args . flags | = IF_PREMULTIPLYALPHA ;
else if ( ! strcmp ( argv [ u ] , " --nopremul " ) )
args . flags & = ~ IF_PREMULTIPLYALPHA ;
2020-01-10 12:23:25 +00:00
else if ( ! strcmp ( argv [ u ] , " --ext " ) )
{
2020-03-07 09:00:40 +00:00
if ( mode = = mode_unspecified )
mode = mode_convert ;
2020-01-10 12:23:25 +00:00
if ( u + 1 < argc )
args . defaultext = argv [ + + u ] ;
else
{
2020-03-07 09:00:40 +00:00
Con_Printf ( " --ext requires output extension \n " ) ;
2020-01-10 12:23:25 +00:00
return 1 ;
}
}
2019-09-29 03:08:01 +00:00
else if ( ! strcmp ( argv [ u ] , " --exportmip " ) )
{
char * e = " erk " ;
if ( u + 1 < argc )
args . mipnum = strtoul ( argv [ + + u ] , & e , 10 ) ;
if ( * e )
{
Con_Printf ( " --exportmip requires trailing numeric argument \n " ) ;
return 1 ;
}
}
else
{
if ( argv [ u ] [ 1 ] = = ' - ' )
{
2020-03-07 09:00:40 +00:00
//try aliases first.
for ( f = 0 ; f < countof ( fmtaliases ) ; f + + )
{
if ( ! strcasecmp ( argv [ u ] + 2 , fmtaliases [ f ] . alias ) )
{
args . newpixelformat = fmtaliases [ f ] . fmt ;
if ( mode = = mode_unspecified )
mode = mode_convert ;
break ;
}
}
if ( f < countof ( fmtaliases ) )
continue ;
//now try our formal format names
2019-09-29 03:08:01 +00:00
for ( f = 0 ; f < PTI_MAX ; f + + )
{
if ( ! strcasecmp ( argv [ u ] + 2 , Image_FormatName ( f ) ) )
{
args . newpixelformat = f ;
2020-03-07 09:00:40 +00:00
if ( mode = = mode_unspecified )
mode = mode_convert ;
2019-09-29 03:08:01 +00:00
break ;
}
}
if ( f < PTI_MAX )
continue ;
2020-03-07 09:00:40 +00:00
//nope, not a format name
2019-09-29 03:08:01 +00:00
}
Con_Printf ( " Unknown arg %s \n " , argv [ u ] ) ;
goto showhelp ;
}
2019-10-18 08:37:38 +00:00
argv [ u ] = NULL ;
2019-09-29 03:08:01 +00:00
}
else
2019-10-18 08:37:38 +00:00
argv [ files + + ] = argv [ u ] ;
2019-09-29 03:08:01 +00:00
}
2019-10-18 08:37:38 +00:00
2020-03-07 09:00:40 +00:00
if ( mode = = mode_unspecified & & args . textype ! = PTI_ANY )
mode = mode_convert ;
2020-01-10 12:23:25 +00:00
if ( ! args . defaultext )
{
2020-03-07 09:00:40 +00:00
if ( mode = = mode_unspecified )
2021-04-14 05:21:04 +00:00
{
# ifdef FTE_SDL
mode = mode_view ;
# else
2020-03-07 09:00:40 +00:00
mode = mode_info ;
2021-04-14 05:21:04 +00:00
# endif
}
2020-03-07 09:00:40 +00:00
2020-01-10 12:23:25 +00:00
if ( mode = = mode_extractwad )
args . defaultext = " png " ; //something the user expects to be able to view easily (and lossless)
2020-03-07 09:00:40 +00:00
else if ( args . newpixelformat > = PTI_BC1_RGB & & args . newpixelformat < PTI_BC4_R )
args . defaultext = " dds " ;
2020-01-10 12:23:25 +00:00
else
args . defaultext = " ktx " ;
}
2020-03-07 09:00:40 +00:00
else
{
if ( mode = = mode_unspecified )
mode = mode_convert ;
}
2020-01-10 12:23:25 +00:00
2019-10-18 08:37:38 +00:00
if ( mode = = mode_info )
{ //just print info about each listed file.
for ( u = 0 ; u < files ; u + + )
2021-04-14 05:21:04 +00:00
ImgTool_Enumerate ( & args , argv [ u ] , ImgTool_PrintInfo ) ;
2019-10-18 08:37:38 +00:00
}
2020-03-07 09:00:40 +00:00
else if ( mode = = mode_convert & & args . textype ! = PTI_ANY & & outname ) //overwrite input
2019-10-18 08:37:38 +00:00
{
2020-03-07 09:00:40 +00:00
ImgTool_Convert ( & args , ImgTool_Combine ( & args , argv , files ) , " combined " , outname ) ;
2019-10-18 08:37:38 +00:00
}
2020-03-07 09:00:40 +00:00
else if ( mode = = mode_convert & & args . textype = = PTI_ANY & & ( ! outname | | files = = 1 ) ) //list of files (output filenames will be generated according to -ext arg)
2019-10-18 08:37:38 +00:00
{
2020-03-07 09:00:40 +00:00
//-c src1 src2 src3
for ( u = 0 ; u < files ; u + + )
ImgTool_Convert ( & args , ImgTool_Read ( & args , argv [ u ] ) , argv [ u ] , NULL ) ;
2019-10-18 08:37:38 +00:00
}
else if ( mode = = mode_autotree & & files = = 2 )
ImgTool_TreeConvert ( & args , argv [ 0 ] , argv [ 1 ] ) ;
2020-01-10 12:23:25 +00:00
else if ( ( mode = = mode_genwad2 | | mode = = mode_genwad3 | | mode = = mode_genwadx ) )
ImgTool_WadConvert ( & args , argv [ 0 ] , argv + 1 , files - 1 , mode - mode_genwadx ) ;
else if ( ( mode = = mode_extractwad ) & & files = = 1 )
ImgTool_WadExtract ( & args , argv [ 0 ] ) ;
2021-04-14 05:21:04 +00:00
# ifdef FTE_SDL
else if ( mode = = mode_view )
{
for ( u = 0 ; u < files ; u + + )
ImgTool_Enumerate ( & args , argv [ u ] , ImgTool_View ) ;
SDLL_Loop ( ) ;
}
# endif
2019-10-18 08:37:38 +00:00
else
2020-01-10 12:23:25 +00:00
{
printf ( " %u files \n " , ( int ) files ) ;
printf ( " unsupported arg count for mode \n " ) ;
2019-10-18 08:37:38 +00:00
return EXIT_FAILURE ;
2020-01-10 12:23:25 +00:00
}
2019-10-18 08:37:38 +00:00
return EXIT_SUCCESS ;
2019-09-29 03:08:01 +00:00
}
2021-04-14 05:21:04 +00:00
# ifdef FTE_SDL
# include <SDL.h>
struct sdlwindow_s
{
SDL_Window * w ;
SDL_Renderer * r ;
2021-05-09 13:00:14 +00:00
int width ;
int height ;
float scale ;
2021-04-14 05:21:04 +00:00
size_t texshown ;
size_t texcount ;
struct
{
char * name ;
size_t w , h ;
SDL_Texture * t ;
} * tex ;
} ;
static struct
{
qboolean inited ;
qboolean tried ;
size_t windowcount ;
int ( SDLCALL * Init ) ( Uint32 flags ) ;
SDL_Window * ( SDLCALL * CreateWindow ) ( const char * title , int x , int y , int w , int h , Uint32 flags ) ;
void * ( SDLCALL * SetWindowData ) ( SDL_Window * window , const char * name , void * userdata ) ;
void * ( SDLCALL * GetWindowData ) ( SDL_Window * window , const char * name ) ;
void ( SDLCALL * SetWindowTitle ) ( SDL_Window * window , const char * title ) ;
void ( SDLCALL * SetWindowSize ) ( SDL_Window * window , int w , int h ) ;
2021-04-17 21:35:13 +00:00
Uint32 ( SDLCALL * GetWindowFlags ) ( SDL_Window * window ) ;
2021-04-14 05:21:04 +00:00
SDL_Renderer * ( SDLCALL * CreateRenderer ) ( SDL_Window * window , int index , Uint32 flags ) ;
int ( SDLCALL * GetRendererInfo ) ( SDL_Renderer * renderer , SDL_RendererInfo * info ) ;
SDL_Texture * ( SDLCALL * CreateTexture ) ( SDL_Renderer * renderer , Uint32 format , int access , int w , int h ) ;
int ( SDLCALL * UpdateTexture ) ( SDL_Texture * texture , const SDL_Rect * rect , const void * pixels , int pitch ) ;
int ( SDLCALL * RenderCopy ) ( SDL_Renderer * renderer , SDL_Texture * texture , const SDL_Rect * srcrect , const SDL_Rect * dstrect ) ;
void ( SDLCALL * RenderPresent ) ( SDL_Renderer * renderer ) ;
int ( SDLCALL * WaitEvent ) ( SDL_Event * event ) ;
int ( SDLCALL * PollEvent ) ( SDL_Event * event ) ;
SDL_Window * ( SDLCALL * GetWindowFromID ) ( Uint32 id ) ;
void ( SDLCALL * DestroyTexture ) ( SDL_Texture * texture ) ;
void ( SDLCALL * DestroyRenderer ) ( SDL_Renderer * renderer ) ;
void ( SDLCALL * DestroyWindow ) ( SDL_Window * window ) ;
void ( SDLCALL * Quit ) ( void ) ;
struct sdlwindow_s * texview ;
} sdl ;
static qboolean SDLL_Setup ( void )
{
static dllfunction_t funcs [ ] =
{
{ ( void * * ) & sdl . Init , " SDL_Init " } ,
{ ( void * * ) & sdl . CreateWindow , " SDL_CreateWindow " } ,
{ ( void * * ) & sdl . SetWindowData , " SDL_SetWindowData " } ,
{ ( void * * ) & sdl . GetWindowData , " SDL_GetWindowData " } ,
{ ( void * * ) & sdl . SetWindowTitle , " SDL_SetWindowTitle " } ,
{ ( void * * ) & sdl . SetWindowSize , " SDL_SetWindowSize " } ,
2021-04-17 21:35:13 +00:00
{ ( void * * ) & sdl . GetWindowFlags , " SDL_GetWindowFlags " } ,
2021-04-14 05:21:04 +00:00
{ ( void * * ) & sdl . CreateRenderer , " SDL_CreateRenderer " } ,
{ ( void * * ) & sdl . GetRendererInfo , " SDL_GetRendererInfo " } ,
{ ( void * * ) & sdl . CreateTexture , " SDL_CreateTexture " } ,
{ ( void * * ) & sdl . UpdateTexture , " SDL_UpdateTexture " } ,
{ ( void * * ) & sdl . RenderCopy , " SDL_RenderCopy " } ,
{ ( void * * ) & sdl . RenderPresent , " SDL_RenderPresent " } ,
{ ( void * * ) & sdl . WaitEvent , " SDL_WaitEvent " } ,
{ ( void * * ) & sdl . PollEvent , " SDL_PollEvent " } ,
{ ( void * * ) & sdl . GetWindowFromID , " SDL_GetWindowFromID " } ,
{ ( void * * ) & sdl . DestroyTexture , " SDL_DestroyTexture " } ,
{ ( void * * ) & sdl . DestroyRenderer , " SDL_DestroyRenderer " } ,
{ ( void * * ) & sdl . DestroyWindow , " SDL_DestroyWindow " } ,
{ ( void * * ) & sdl . Quit , " SDL_Quit " } ,
{ NULL , NULL }
} ;
if ( ! sdl . tried )
{
sdl . tried = true ;
# ifdef _WIN32
if ( ! Sys_LoadLibrary ( " SDL2.dll " , funcs ) )
# else
if ( ! Sys_LoadLibrary ( " libSDL2-2.0.so.0 " , funcs ) )
if ( ! Sys_LoadLibrary ( " libSDL2-2.0.so " , funcs ) )
if ( ! Sys_LoadLibrary ( " libSDL2-2.so " , funcs ) )
if ( ! Sys_LoadLibrary ( " libSDL2.so " , funcs ) )
if ( ! Sys_LoadLibrary ( " SDL2.so " , funcs ) )
# endif
{
printf ( " Unable to load SDL2 library \n " ) ;
return sdl . inited ;
}
sdl . Init ( SDL_INIT_VIDEO ) ;
sdl . inited = true ;
}
return sdl . inited ;
}
static void SDLL_KillWindow ( struct sdlwindow_s * wc )
{
while ( wc - > texcount - - > 0 )
{
if ( wc - > tex [ wc - > texcount ] . t )
sdl . DestroyTexture ( wc - > tex [ wc - > texcount ] . t ) ;
BZ_Free ( wc - > tex [ wc - > texcount ] . name ) ;
}
BZ_Free ( wc - > tex ) ;
if ( wc - > r )
sdl . DestroyRenderer ( wc - > r ) ;
if ( wc - > w )
sdl . DestroyWindow ( wc - > w ) ;
Z_Free ( wc ) ;
sdl . windowcount - - ;
if ( sdl . texview = = wc )
sdl . texview = NULL ;
}
static void SDLL_RepaintWindow ( struct sdlwindow_s * wc )
{
if ( wc - > texshown < wc - > texcount )
{
2021-05-09 13:00:14 +00:00
SDL_Rect dest ;
dest . x = dest . y = 0 ;
dest . w = dest . h = 1 ;
sdl . RenderCopy ( wc - > r , wc - > tex [ wc - > texshown ] . t , & dest , NULL ) ;
dest . w = wc - > tex [ wc - > texshown ] . w * wc - > scale ;
dest . h = wc - > tex [ wc - > texshown ] . h * wc - > scale ;
dest . x = ( wc - > width - dest . w ) / 2 ;
dest . y = ( wc - > height - dest . h ) / 2 ;
sdl . RenderCopy ( wc - > r , wc - > tex [ wc - > texshown ] . t , NULL , & dest ) ;
2021-04-14 05:21:04 +00:00
sdl . RenderPresent ( wc - > r ) ;
}
}
static void SDLL_Change ( struct sdlwindow_s * wc , size_t newshown )
{
if ( newshown < wc - > texcount )
{
2021-05-09 13:00:14 +00:00
int w , h ;
2021-04-17 21:35:13 +00:00
char title [ 512 ] ;
2021-04-14 05:21:04 +00:00
wc - > texshown = newshown ;
2021-04-17 21:35:13 +00:00
if ( wc - > texcount = = 1 )
snprintf ( title , sizeof ( title ) , " %s " , wc - > tex [ wc - > texshown ] . name ) ;
else
snprintf ( title , sizeof ( title ) , " [%u/%u] %s " , 1 + ( unsigned int ) newshown , ( unsigned int ) wc - > texcount , wc - > tex [ wc - > texshown ] . name ) ;
sdl . SetWindowTitle ( wc - > w , title ) ;
2021-05-09 13:00:14 +00:00
w = wc - > tex [ wc - > texshown ] . w * wc - > scale ;
h = wc - > tex [ wc - > texshown ] . h * wc - > scale ;
if ( w > 1024 )
w = 1024 ;
if ( h > 768 )
h = 768 ;
if ( wc - > width < w | | wc - > height < h )
if ( ! ( sdl . GetWindowFlags ( wc - > w ) & ( SDL_WINDOW_MAXIMIZED | SDL_WINDOW_FULLSCREEN ) ) ) //SetWindowSize seems to bug out on linux when its maximized.
{
wc - > width = w ;
wc - > height = h ;
sdl . SetWindowSize ( wc - > w , w , h ) ;
}
2021-04-14 05:21:04 +00:00
SDLL_RepaintWindow ( wc ) ;
}
}
static void SDLL_Event ( SDL_Event * ev )
{
struct sdlwindow_s * wc ;
switch ( ev - > type )
{
case SDL_KEYDOWN :
wc = sdl . GetWindowData ( sdl . GetWindowFromID ( ev - > key . windowID ) , " uptr " ) ;
if ( ! wc ) break ;
switch ( ev - > key . keysym . sym )
{
case SDLK_ESCAPE :
case SDLK_q :
SDLL_KillWindow ( wc ) ;
break ;
case SDLK_LEFT :
2021-05-09 13:00:14 +00:00
wc - > scale = 1 ;
2021-04-14 05:21:04 +00:00
SDLL_Change ( wc , wc - > texshown - 1 ) ;
break ;
case SDLK_RIGHT :
2021-05-09 13:00:14 +00:00
wc - > scale = 1 ;
2021-04-14 05:21:04 +00:00
SDLL_Change ( wc , wc - > texshown + 1 ) ;
break ;
2021-05-09 13:00:14 +00:00
case SDLK_UP :
wc - > scale / = 0.9 ;
if ( wc - > scale > 4 )
wc - > scale = 4 ;
SDLL_Change ( wc , wc - > texshown ) ;
break ;
case SDLK_DOWN :
wc - > scale * = 0.9 ;
if ( wc - > scale < 0.25 )
wc - > scale = 0.25 ;
SDLL_Change ( wc , wc - > texshown ) ;
break ;
2021-04-14 05:21:04 +00:00
}
break ;
case SDL_WINDOWEVENT :
wc = sdl . GetWindowData ( sdl . GetWindowFromID ( ev - > window . windowID ) , " uptr " ) ;
if ( ! wc ) break ;
switch ( ev - > window . event )
{
case SDL_WINDOWEVENT_CLOSE :
SDLL_KillWindow ( wc ) ;
break ;
2021-05-09 13:00:14 +00:00
case SDL_WINDOWEVENT_SIZE_CHANGED :
wc - > width = ev - > window . data1 ;
wc - > height = ev - > window . data2 ;
break ;
2021-04-14 05:21:04 +00:00
case SDL_WINDOWEVENT_EXPOSED :
SDLL_RepaintWindow ( wc ) ;
break ;
}
break ;
//don't bother with SDL_QUIT, it doesn't get sent if we kill the last window via a keypress. just count live windows instead.
default :
// printf("event type %x\n", ev->type);
break ;
}
}
static void SDLL_Loop ( void )
{
SDL_Event ev ;
if ( ! sdl . inited )
return ;
2021-04-17 21:35:13 +00:00
if ( sdl . texview )
SDLL_Change ( sdl . texview , sdl . texview - > texshown ) ;
2021-04-14 05:21:04 +00:00
while ( sdl . windowcount & & sdl . WaitEvent ( & ev ) )
SDLL_Event ( & ev ) ;
sdl . Quit ( ) ;
}
static void ImgTool_View ( const char * inname , struct pendingtextureinfo * in )
{
unsigned int sdlfmt ;
SDL_RendererInfo rinfo ;
int s ;
qboolean outformats [ PTI_MAX ] = { false } ;
struct sdlwindow_s * wc ;
SDL_Event ev ;
2021-05-09 13:00:14 +00:00
if ( in - > mipcount < 1 | | in - > mip [ 0 ] . width < = 0 | | in - > mip [ 0 ] . height < = 0 )
return ;
2021-04-14 05:21:04 +00:00
if ( ! SDLL_Setup ( ) )
{
ImgTool_PrintInfo ( inname , in ) ;
return ;
}
while ( sdl . windowcount > = 64 & & sdl . WaitEvent ( & ev ) )
SDLL_Event ( & ev ) ;
if ( sdl . texview )
wc = sdl . texview ;
else
{
sdl . texview = wc = Z_Malloc ( sizeof ( * wc ) ) ;
2021-05-09 13:00:14 +00:00
wc - > scale = 2 ;
2021-04-14 05:21:04 +00:00
s = 1 ;
while ( ( in - > mip [ 0 ] . width * s < 256 & & in - > mip [ 0 ] . height * s < 512 ) | |
( in - > mip [ 0 ] . height * s < 256 & & in - > mip [ 0 ] . width * s < 512 ) )
s < < = 1 ;
wc - > w = sdl . CreateWindow ( " textureview " , SDL_WINDOWPOS_UNDEFINED , SDL_WINDOWPOS_UNDEFINED , 64 , 64 , SDL_WINDOW_RESIZABLE ) ;
sdl . windowcount + + ;
if ( wc - > w )
{
sdl . SetWindowData ( wc - > w , " uptr " , wc ) ;
//needs a rendering context too
wc - > r = sdl . CreateRenderer ( wc - > w , - 1 , SDL_RENDERER_SOFTWARE ) ;
if ( ! wc - > r )
{
printf ( " Unable to create rendering context \n " ) ;
SDLL_KillWindow ( wc ) ;
return ;
}
}
}
if ( wc - > r )
{
//figure out which formats we can pass to sdl
sdl . GetRendererInfo ( wc - > r , & rinfo ) ;
while ( rinfo . num_texture_formats - - > 0 )
{
switch ( rinfo . texture_formats [ rinfo . num_texture_formats ] )
{
//packed formats use hex ordering in both apis.
case SDL_PIXELFORMAT_RGB565 : outformats [ PTI_RGB565 ] = true ; break ;
// case SDL_PIXELFORMAT_BGR565: outformats[PTI_BGR565] = true; break;
case SDL_PIXELFORMAT_RGBA4444 : outformats [ PTI_RGBA4444 ] = true ; break ;
case SDL_PIXELFORMAT_ABGR4444 : outformats [ PTI_ARGB4444 ] = true ; break ;
case SDL_PIXELFORMAT_RGBA5551 : outformats [ PTI_RGBA5551 ] = true ; break ;
case SDL_PIXELFORMAT_ARGB1555 : outformats [ PTI_ARGB1555 ] = true ; break ;
// case SDL_PIXELFORMAT_ARGB2101010: outformats[PTI_A2RGB10] = true; break;
// case SDL_PIXELFORMAT_ABGR2101010: outformats[PTI_A2BGR10] = true; break;
//these sdl aliases are for explicit byte orders, rather than packed.
case SDL_PIXELFORMAT_RGBA32 : outformats [ PTI_RGBA8 ] = true ; break ;
case SDL_PIXELFORMAT_BGRA32 : outformats [ PTI_BGRA8 ] = true ; break ;
case SDL_PIXELFORMAT_BGR24 : outformats [ PTI_RGB8 ] = true ; break ;
case SDL_PIXELFORMAT_RGB24 : outformats [ PTI_BGR8 ] = true ; break ;
// case SDL_PIXELFORMAT_ARGB32: outformats[PTI_ARGB8] = true; break;
// case SDL_PIXELFORMAT_ABGR32: outformats[PTI_ABGR8] = true; break;
# if SDL_BYTEORDER == SDL_BIG_ENDIAN
case SDL_PIXELFORMAT_RGBX8888 : outformats [ PTI_RGBX8 ] = true ; break ;
case SDL_PIXELFORMAT_BGRX8888 : outformats [ PTI_BGRX8 ] = true ; break ;
# else
//case SDL_PIXELFORMAT_XBGR8888: outformats[PTI_RGBX8] = true; break;
//case SDL_PIXELFORMAT_XRGB8888: outformats[PTI_BGRX8] = true; break;
# endif
}
}
//convert our image, if needed.
if ( ! outformats [ in - > encoding ] )
Image_ChangeFormat ( in , outformats , PTI_INVALID , inname ) ;
if ( ! outformats [ in - > encoding ] )
sdlfmt = SDL_PIXELFORMAT_UNKNOWN , printf ( " Unable to convert to usable pixel format \n " ) ;
else switch ( in - > encoding )
{
//packed formats
case PTI_RGB565 : sdlfmt = SDL_PIXELFORMAT_RGB565 ; break ;
// case PTI_BGR565: sdlfmt = SDL_PIXELFORMAT_BGR565; break;
case PTI_RGBA4444 : sdlfmt = SDL_PIXELFORMAT_RGBA4444 ; break ;
case PTI_ARGB4444 : sdlfmt = SDL_PIXELFORMAT_ARGB4444 ; break ;
case PTI_RGBA5551 : sdlfmt = SDL_PIXELFORMAT_RGBA5551 ; break ;
case PTI_ARGB1555 : sdlfmt = SDL_PIXELFORMAT_ARGB1555 ; break ;
// case PTI_A2RGB10: sdlfmt = SDL_PIXELFORMAT_ARGB2101010; break;
// case PTI_A2BGR10: sdlfmt = SDL_PIXELFORMAT_ABGR2101010; break;
//byte-ordered formats.
case PTI_RGBA8 : sdlfmt = SDL_PIXELFORMAT_RGBA32 ; break ;
case PTI_BGRA8 : sdlfmt = SDL_PIXELFORMAT_BGRA32 ; break ;
case PTI_RGB8 : sdlfmt = SDL_PIXELFORMAT_RGB24 ; break ;
case PTI_BGR8 : sdlfmt = SDL_PIXELFORMAT_BGR24 ; break ;
# if SDL_BYTEORDER == SDL_BIG_ENDIAN
case PTI_RGBX8 : sdlfmt = SDL_PIXELFORMAT_RGBX8888 ; break ;
case PTI_BGRX8 : sdlfmt = SDL_PIXELFORMAT_BGRX8888 ; break ;
# else
case PTI_RGBX8 : sdlfmt = SDL_PIXELFORMAT_XBGR8888 ; break ;
case PTI_BGRX8 : sdlfmt = SDL_PIXELFORMAT_XRGB8888 ; break ;
# endif
default : sdlfmt = SDL_PIXELFORMAT_UNKNOWN ; break ; //shouldn't happen.
}
wc - > tex = realloc ( wc - > tex , sizeof ( * wc - > tex ) * ( wc - > texcount + 1 ) ) ;
wc - > tex [ wc - > texcount ] . name = Z_StrDup ( inname ) ;
wc - > tex [ wc - > texcount ] . w = in - > mip [ 0 ] . width ;
wc - > tex [ wc - > texcount ] . h = in - > mip [ 0 ] . height ;
wc - > tex [ wc - > texcount ] . t = sdl . CreateTexture ( wc - > r , sdlfmt , SDL_TEXTUREACCESS_STATIC , in - > mip [ 0 ] . width , in - > mip [ 0 ] . height ) ; //which needs a texture...
if ( wc - > tex [ wc - > texcount ] . t )
{
sdl . UpdateTexture ( wc - > tex [ wc - > texcount ] . t , NULL , in - > mip [ 0 ] . data , in - > mip [ 0 ] . datasize / in - > mip [ 0 ] . height ) ; //with our image data
if ( ! wc - > texcount + + )
SDLL_Change ( wc , 0 ) ;
while ( sdl . PollEvent ( & ev ) )
SDLL_Event ( & ev ) ;
}
else
{
printf ( " Unable to create texture \n " ) ;
BZ_Free ( wc - > tex [ wc - > texcount ] . name ) ;
}
}
else
{
printf ( " Unable to create window \n " ) ;
SDLL_KillWindow ( wc ) ;
}
}
# endif
2020-06-13 00:05:47 +00:00
# endif