diff --git a/common/boneinfo.h b/common/boneinfo.h new file mode 100644 index 00000000..d4a26060 --- /dev/null +++ b/common/boneinfo.h @@ -0,0 +1,25 @@ +/* +boneinfo.h - structure that send delta-compressed bones across network +Copyright (C) 2018 Uncle Mike + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. +*/ + +#ifndef BONEINFO_H +#define BONEINFO_H + +typedef struct +{ + vec3_t angles; + vec3_t origin; +} boneinfo_t; + +#endif//BONEINFO_H \ No newline at end of file diff --git a/common/render_api.h b/common/render_api.h index 29ea4b61..e02e9527 100644 --- a/common/render_api.h +++ b/common/render_api.h @@ -74,12 +74,13 @@ enum typedef enum { + TF_COLORMAP = 0, // just for tabulate source TF_NEAREST = (1<<0), // disable texfilter TF_KEEP_SOURCE = (1<<1), // some images keep source TF_NOFLIP_TGA = (1<<2), // Steam background completely ignore tga attribute 0x20 TF_EXPAND_SOURCE = (1<<3), // Don't keep source as 8-bit expand to RGBA - TF_TEXTURE_2D_ARRAY = (1<<4), // this is 2D texture array (multi-layers) - TF_TEXTURE_RECTANGLE= (1<<5), // this is GL_TEXTURE_RECTANGLE +// reserved + TF_RECTANGLE = (1<<5), // this is GL_TEXTURE_RECTANGLE TF_CUBEMAP = (1<<6), // it's cubemap texture TF_DEPTHMAP = (1<<7), // custom texture filter used TF_QUAKEPAL = (1<<8), // image has an quake1 palette @@ -92,7 +93,7 @@ typedef enum TF_NORMALMAP = (1<<15), // is a normalmap TF_HAS_ALPHA = (1<<16), // image has alpha (used only for GL_CreateTexture) TF_FORCE_COLOR = (1<<17), // force upload monochrome textures as RGB (detail textures) - TF_TEXTURE_1D = (1<<18), // this is GL_TEXTURE_1D +// reserved TF_BORDER = (1<<19), // zero clamp for projected textures TF_TEXTURE_3D = (1<<20), // this is GL_TEXTURE_3D TF_ATLAS_PAGE = (1<<21), // bit who indicate lightmap page or deluxemap page @@ -203,9 +204,9 @@ typedef struct render_api_s void (*GL_TextureTarget)( unsigned int target ); // change texture unit mode without bind texture void (*GL_TexCoordArrayMode)( unsigned int texmode ); void* (*GL_GetProcAddress)( const char *name ); + void (*GL_UpdateTexSize)( int texnum, int width, int height, int depth ); // recalc statistics void (*GL_Reserved0)( void ); // for potential interface expansion without broken compatibility void (*GL_Reserved1)( void ); - void (*GL_Reserved2)( void ); // Misc renderer functions void (*GL_DrawParticles)( const struct ref_viewpass_s *rvp, qboolean trans_pass, float frametime ); diff --git a/engine/client/cl_debug.c b/engine/client/cl_debug.c index 3af2e00f..35e74998 100644 --- a/engine/client/cl_debug.c +++ b/engine/client/cl_debug.c @@ -82,7 +82,7 @@ const char *svc_strings[svc_lastmsg+1] = "svc_director", "svc_voiceinit", "svc_voicedata", - "svc_unused54", + "svc_deltapacketbones", "svc_unused55", "svc_resourcelocation", "svc_querycvarvalue", diff --git a/engine/client/cl_game.c b/engine/client/cl_game.c index 4a4756ae..90de1d06 100644 --- a/engine/client/cl_game.c +++ b/engine/client/cl_game.c @@ -1059,7 +1059,7 @@ void CL_LinkUserMessage( char *pszName, const int svc_num, int iSize ) for( i = 0; i < MAX_USER_MESSAGES && clgame.msg[i].name[0]; i++ ) { // NOTE: no check for DispatchFunc, check only name - if( !Q_strcmp( clgame.msg[i].name, pszName )) + if( !Q_stricmp( clgame.msg[i].name, pszName )) { clgame.msg[i].number = svc_num; clgame.msg[i].size = iSize; @@ -1685,7 +1685,7 @@ static int pfnHookUserMsg( const char *pszName, pfnUserMsgHook pfn ) for( i = 0; i < MAX_USER_MESSAGES && clgame.msg[i].name[0]; i++ ) { // see if already hooked - if( !Q_strcmp( clgame.msg[i].name, pszName )) + if( !Q_stricmp( clgame.msg[i].name, pszName )) return 1; } @@ -1712,7 +1712,7 @@ static int pfnServerCmd( const char *szCmdString ) { string buf; - if( !szCmdString || !szCmdString[0] ) + if( !COM_CheckString( szCmdString )) return 0; // just like the client typed "cmd xxxxx" at the console @@ -1730,11 +1730,20 @@ pfnClientCmd */ static int pfnClientCmd( const char *szCmdString ) { - if( !szCmdString || !szCmdString[0] ) + if( !COM_CheckString( szCmdString )) return 0; - Cbuf_AddText( szCmdString ); - Cbuf_AddText( "\n" ); + if( cls.initialized ) + { + Cbuf_AddText( szCmdString ); + Cbuf_AddText( "\n" ); + } + else + { + // will exec later + Q_strncat( host.deferred_cmd, va( "%s\n", szCmdString ), sizeof( host.deferred_cmd )); + } + return 1; } diff --git a/engine/client/cl_gameui.c b/engine/client/cl_gameui.c index 6e3cb2c5..a1ca2bf6 100644 --- a/engine/client/cl_gameui.c +++ b/engine/client/cl_gameui.c @@ -29,6 +29,15 @@ void UI_UpdateMenu( float realtime ) { if( !gameui.hInstance ) return; + // if some deferred cmds is waiting + if( UI_IsVisible() && COM_CheckString( host.deferred_cmd )) + { + Cbuf_AddText( host.deferred_cmd ); + host.deferred_cmd[0] = '\0'; + Cbuf_Execute(); + return; + } + // menu time (not paused, not clamped) gameui.globals->time = host.realtime; gameui.globals->frametime = host.realframetime; diff --git a/engine/client/cl_main.c b/engine/client/cl_main.c index 4abc65b6..7eff7c55 100644 --- a/engine/client/cl_main.c +++ b/engine/client/cl_main.c @@ -265,7 +265,7 @@ static float CL_LerpPoint( void ) f = 0.1f; } #if 1 - frac = (cl.time - cl.mtime[1]) / f; + frac = (cl.time - cl.mtime[0]) / f; if( frac < 0.0f ) { @@ -288,7 +288,7 @@ static float CL_LerpPoint( void ) else if( f > 0.001f ) { // automatic lerp (classic mode) - frac = ( cl.time - cl.mtime[1] ) / f; + frac = ( cl.time - cl.mtime[0] ) / f; } #endif return frac; @@ -1488,8 +1488,10 @@ CL_InternetServers_f */ void CL_InternetServers_f( void ) { + char fullquery[512] = MS_SCAN_REQUEST; + char *info = fullquery + sizeof( MS_SCAN_REQUEST ) - 1; + int remaining = sizeof( fullquery ) - sizeof( MS_SCAN_REQUEST ); netadr_t adr; - char fullquery[512] = "1\xFF" "0.0.0.0:0\0" "\\gamedir\\"; Con_Printf( "Scanning for servers on the internet area...\n" ); NET_Config( true ); // allow remote @@ -1497,9 +1499,10 @@ void CL_InternetServers_f( void ) if( !NET_StringToAdr( MASTERSERVER_ADR, &adr ) ) MsgDev( D_ERROR, "Can't resolve adr: %s\n", MASTERSERVER_ADR ); - Q_strcpy( &fullquery[22], GI->gamedir ); + Info_SetValueForKey( info, "gamedir", GI->gamefolder, remaining ); + Info_SetValueForKey( info, "clver", XASH_VERSION, remaining ); // let master know about client version - NET_SendPacket( NS_CLIENT, Q_strlen( GI->gamedir ) + 23, fullquery, adr ); + NET_SendPacket( NS_CLIENT, sizeof( MS_SCAN_REQUEST ) + Q_strlen( info ), fullquery, adr ); // now we clearing the vgui request if( clgame.master_request != NULL ) diff --git a/engine/client/cl_parse.c b/engine/client/cl_parse.c index 005e6bb6..2ae56b5e 100644 --- a/engine/client/cl_parse.c +++ b/engine/client/cl_parse.c @@ -324,7 +324,7 @@ void CL_ParseStaticEntity( sizebuf_t *msg ) i = clgame.numStatics; if( i >= MAX_STATIC_ENTITIES ) { - Con_Printf( S_ERROR, "MAX_STATIC_ENTITIES limit exceeded!\n" ); + Con_Printf( S_ERROR "MAX_STATIC_ENTITIES limit exceeded!\n" ); return; } diff --git a/engine/client/cl_qparse.c b/engine/client/cl_qparse.c index f3acbd1d..ae0ec335 100644 --- a/engine/client/cl_qparse.c +++ b/engine/client/cl_qparse.c @@ -596,7 +596,7 @@ static void CL_ParseQuakeStaticEntity( sizebuf_t *msg ) i = clgame.numStatics; if( i >= MAX_STATIC_ENTITIES ) { - Con_Printf( S_ERROR, "CL_ParseStaticEntity: static entities limit exceeded!\n" ); + Con_Printf( S_ERROR "CL_ParseStaticEntity: static entities limit exceeded!\n" ); return; } diff --git a/engine/client/cl_remap.c b/engine/client/cl_remap.c index 07327373..ad49e633 100644 --- a/engine/client/cl_remap.c +++ b/engine/client/cl_remap.c @@ -99,7 +99,7 @@ Dupliacte texture with remap pixels */ void CL_DuplicateTexture( mstudiotexture_t *ptexture, int topcolor, int bottomcolor ) { - gltexture_t *glt; + gl_texture_t *glt; texture_t *tx = NULL; char texname[128]; int i, size, index; @@ -141,7 +141,7 @@ Update texture top and bottom colors */ void CL_UpdateStudioTexture( mstudiotexture_t *ptexture, int topcolor, int bottomcolor ) { - gltexture_t *glt; + gl_texture_t *glt; rgbdata_t *pic; texture_t *tx = NULL; char texname[128], name[128], mdlname[128]; @@ -183,7 +183,7 @@ void CL_UpdateStudioTexture( mstudiotexture_t *ptexture, int topcolor, int botto return; } - index = GL_LoadTextureInternal( glt->name, pic, 0, true ); + index = GL_UpdateTextureInternal( glt->name, pic, 0 ); FS_FreeImage( pic ); // restore original palette @@ -224,7 +224,7 @@ void CL_UpdateAliasTexture( unsigned short *texture, int skinnum, int topcolor, skin.buffer = (byte *)(tx + 1); skin.palette = skin.buffer + skin.size; pic = FS_CopyImage( &skin ); // because GL_LoadTextureInternal will freed a rgbdata_t at end - *texture = GL_LoadTextureInternal( texname, pic, TF_KEEP_SOURCE, false ); + *texture = GL_LoadTextureInternal( texname, pic, TF_KEEP_SOURCE ); } // and now we can remap with internal routines diff --git a/engine/client/cl_tent.c b/engine/client/cl_tent.c index 236cafe3..74ca0268 100644 --- a/engine/client/cl_tent.c +++ b/engine/client/cl_tent.c @@ -3014,7 +3014,7 @@ void CL_PlayerDecal( int playernum, int customIndex, int entityIndex, float *pos if( !pCust->nUserData1 && pCust->pInfo != NULL ) { const char *decalname = va( "player%dlogo%d", playernum, customIndex ); - pCust->nUserData1 = GL_LoadTextureInternal( decalname, pCust->pInfo, TF_DECAL, false ); + pCust->nUserData1 = GL_LoadTextureInternal( decalname, pCust->pInfo, TF_DECAL ); } textureIndex = pCust->nUserData1; } diff --git a/engine/client/cl_video.c b/engine/client/cl_video.c index ad637240..27423921 100644 --- a/engine/client/cl_video.c +++ b/engine/client/cl_video.c @@ -235,6 +235,7 @@ qboolean SCR_PlayCinematic( const char *arg ) UI_SetActiveMenu( false ); cls.state = ca_cinematic; + Con_FastClose(); cin_time = 0.0f; cls.signon = 0; diff --git a/engine/client/gl_alias.c b/engine/client/gl_alias.c index ca92e54c..fd2b9401 100644 --- a/engine/client/gl_alias.c +++ b/engine/client/gl_alias.c @@ -487,7 +487,7 @@ void *Mod_LoadSingleSkin( daliasskintype_t *pskintype, int skinnum, int size ) m_pAliasHeader->gl_texturenum[skinnum][0] = m_pAliasHeader->gl_texturenum[skinnum][1] = m_pAliasHeader->gl_texturenum[skinnum][2] = - m_pAliasHeader->gl_texturenum[skinnum][3] = GL_LoadTextureInternal( name, pic, 0, false ); + m_pAliasHeader->gl_texturenum[skinnum][3] = GL_LoadTextureInternal( name, pic, 0 ); FS_FreeImage( pic ); if( R_GetTexture( m_pAliasHeader->gl_texturenum[skinnum][0] )->flags & TF_HAS_LUMA ) @@ -496,7 +496,7 @@ void *Mod_LoadSingleSkin( daliasskintype_t *pskintype, int skinnum, int size ) m_pAliasHeader->fb_texturenum[skinnum][0] = m_pAliasHeader->fb_texturenum[skinnum][1] = m_pAliasHeader->fb_texturenum[skinnum][2] = - m_pAliasHeader->fb_texturenum[skinnum][3] = GL_LoadTextureInternal( lumaname, pic, TF_MAKELUMA, false ); + m_pAliasHeader->fb_texturenum[skinnum][3] = GL_LoadTextureInternal( lumaname, pic, TF_MAKELUMA ); FS_FreeImage( pic ); } @@ -521,14 +521,14 @@ void *Mod_LoadGroupSkin( daliasskintype_t *pskintype, int skinnum, int size ) { Q_snprintf( name, sizeof( name ), "%s_%i_%i", loadmodel->name, skinnum, i ); pic = Mod_CreateSkinData( loadmodel, (byte *)(pskintype), m_pAliasHeader->skinwidth, m_pAliasHeader->skinheight ); - m_pAliasHeader->gl_texturenum[skinnum][i & 3] = GL_LoadTextureInternal( name, pic, 0, false ); + m_pAliasHeader->gl_texturenum[skinnum][i & 3] = GL_LoadTextureInternal( name, pic, 0 ); FS_FreeImage( pic ); if( R_GetTexture( m_pAliasHeader->gl_texturenum[skinnum][i & 3] )->flags & TF_HAS_LUMA ) { Q_snprintf( lumaname, sizeof( lumaname ), "%s_%i_%i_luma", loadmodel->name, skinnum, i ); pic = Mod_CreateSkinData( NULL, (byte *)(pskintype), m_pAliasHeader->skinwidth, m_pAliasHeader->skinheight ); - m_pAliasHeader->fb_texturenum[skinnum][i & 3] = GL_LoadTextureInternal( lumaname, pic, TF_MAKELUMA, false ); + m_pAliasHeader->fb_texturenum[skinnum][i & 3] = GL_LoadTextureInternal( lumaname, pic, TF_MAKELUMA ); FS_FreeImage( pic ); } diff --git a/engine/client/gl_backend.c b/engine/client/gl_backend.c index 14b8db2f..3f13f515 100644 --- a/engine/client/gl_backend.c +++ b/engine/client/gl_backend.c @@ -249,6 +249,7 @@ GL_CleanupAllTextureUnits */ void GL_CleanupAllTextureUnits( void ) { + if( !glw_state.initialized ) return; // force to cleanup all the units GL_SelectTexture( GL_MaxTextureUnits() - 1 ); GL_CleanUpTextureUnits( 0 ); @@ -644,7 +645,7 @@ was there. This is used to test for texture thrashing. */ void R_ShowTextures( void ) { - gltexture_t *image; + gl_texture_t *image; float x, y, w, h; int total, start, end; int i, j, k, base_w, base_h; diff --git a/engine/client/gl_draw.c b/engine/client/gl_draw.c index b3e90710..55ff8fec 100644 --- a/engine/client/gl_draw.c +++ b/engine/client/gl_draw.c @@ -24,7 +24,7 @@ R_GetImageParms */ void R_GetTextureParms( int *w, int *h, int texnum ) { - gltexture_t *glt; + gl_texture_t *glt; glt = R_GetTexture( texnum ); if( w ) *w = glt->srcWidth; @@ -94,7 +94,7 @@ refresh window. void R_DrawTileClear( int x, int y, int w, int h ) { float tw, th; - gltexture_t *glt; + gl_texture_t *glt; GL_SetRenderMode( kRenderNormal ); pglColor4f( 1.0f, 1.0f, 1.0f, 1.0f ); @@ -124,7 +124,7 @@ R_DrawStretchRaw void R_DrawStretchRaw( float x, float y, float w, float h, int cols, int rows, const byte *data, qboolean dirty ) { byte *raw = NULL; - gltexture_t *tex; + gl_texture_t *tex; if( !GL_Support( GL_ARB_TEXTURE_NPOT_EXT )) { @@ -196,7 +196,7 @@ R_UploadStretchRaw void R_UploadStretchRaw( int texture, int cols, int rows, int width, int height, const byte *data ) { byte *raw = NULL; - gltexture_t *tex; + gl_texture_t *tex; if( !GL_Support( GL_ARB_TEXTURE_NPOT_EXT )) { diff --git a/engine/client/gl_export.h b/engine/client/gl_export.h index f530c977..b48834f4 100644 --- a/engine/client/gl_export.h +++ b/engine/client/gl_export.h @@ -390,6 +390,7 @@ typedef float GLmatrix[16]; #define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1 #define GL_COMPRESSED_RGBA_S3TC_DXT3_EXT 0x83F2 #define GL_COMPRESSED_RGBA_S3TC_DXT5_EXT 0x83F3 +#define GL_COMPRESSED_RED_GREEN_RGTC2_EXT 0x8DBD #define GL_COMPRESSED_ALPHA_ARB 0x84E9 #define GL_COMPRESSED_LUMINANCE_ARB 0x84EA #define GL_COMPRESSED_LUMINANCE_ALPHA_ARB 0x84EB diff --git a/engine/client/gl_image.c b/engine/client/gl_image.c index 4725def3..7618fee6 100644 --- a/engine/client/gl_image.c +++ b/engine/client/gl_image.c @@ -16,18 +16,12 @@ GNU General Public License for more details. #include "common.h" #include "client.h" #include "gl_local.h" -#include "studio.h" #define TEXTURES_HASH_SIZE (MAX_TEXTURES >> 2) -static gltexture_t r_textures[MAX_TEXTURES]; -static gltexture_t *r_texturesHashTable[TEXTURES_HASH_SIZE]; -static byte data2D[1024]; // intermediate texbuffer -static int r_numTextures; -static rgbdata_t r_image; // generic pixelbuffer used for internal textures - -// internal tables -static vec3_t r_luminanceTable[256]; // RGB to luminance +static gl_texture_t gl_textures[MAX_TEXTURES]; +static gl_texture_t* gl_texturesHashTable[TEXTURES_HASH_SIZE]; +static uint gl_numTextures; #define IsLightMap( tex ) ( FBitSet(( tex )->flags, TF_ATLAS_PAGE )) /* @@ -37,10 +31,10 @@ R_GetTexture acess to array elem ================= */ -gltexture_t *R_GetTexture( GLenum texnum ) +gl_texture_t *R_GetTexture( GLenum texnum ) { ASSERT( texnum >= 0 && texnum < MAX_TEXTURES ); - return &r_textures[texnum]; + return &gl_textures[texnum]; } /* @@ -75,18 +69,20 @@ GL_Bind */ void GL_Bind( GLint tmu, GLenum texnum ) { - gltexture_t *texture; + gl_texture_t *texture; GLuint glTarget; - // missed texture ? - if( texnum <= 0 ) texnum = tr.defaultTexture; Assert( texnum > 0 && texnum < MAX_TEXTURES ); + // missed or invalid texture? + if( texnum <= 0 || texnum >= MAX_TEXTURES ) + texnum = tr.defaultTexture; + if( tmu != GL_KEEP_UNIT ) GL_SelectTexture( tmu ); else tmu = glState.activeTMU; - texture = &r_textures[texnum]; + texture = &gl_textures[texnum]; glTarget = texture->target; if( glTarget == GL_TEXTURE_2D_ARRAY_EXT ) @@ -112,7 +108,7 @@ void GL_Bind( GLint tmu, GLenum texnum ) GL_ApplyTextureParams ================= */ -void GL_ApplyTextureParams( gltexture_t *tex ) +void GL_ApplyTextureParams( gl_texture_t *tex ) { vec4_t border = { 0.0f, 0.0f, 0.0f, 1.0f }; @@ -247,7 +243,7 @@ GL_UpdateTextureParams */ static void GL_UpdateTextureParams( int iTexture ) { - gltexture_t *tex = &r_textures[iTexture]; + gl_texture_t *tex = &gl_textures[iTexture]; Assert( tex != NULL ); @@ -322,7 +318,7 @@ void R_SetTextureParameters( void ) ClearBits( gl_lightmap_nearest->flags, FCVAR_CHANGED ); // change all the existing mipmapped texture objects - for( i = 0; i < r_numTextures; i++ ) + for( i = 0; i < gl_numTextures; i++ ) GL_UpdateTextureParams( i ); } @@ -365,6 +361,7 @@ static size_t GL_CalcImageSize( pixformat_t format, int width, int height, int d break; case PF_DXT3: case PF_DXT5: + case PF_ATI2: size = (((width + 3) >> 2) * ((height + 3) >> 2) * 16) * depth; break; } @@ -392,6 +389,7 @@ static size_t GL_CalcTextureSize( GLenum format, int width, int height, int dept break; case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: + case GL_COMPRESSED_RED_GREEN_RGTC2_EXT: size = (((width + 3) >> 2) * ((height + 3) >> 2) * 16) * depth; break; case GL_RGBA8: @@ -471,7 +469,7 @@ static size_t GL_CalcTextureSize( GLenum format, int width, int height, int dept return size; } -static int GL_CalcMipmapCount( gltexture_t *tex, qboolean haveBuffer ) +static int GL_CalcMipmapCount( gl_texture_t *tex, qboolean haveBuffer ) { int width, height; int mipcount; @@ -502,7 +500,7 @@ static int GL_CalcMipmapCount( gltexture_t *tex, qboolean haveBuffer ) GL_SetTextureDimensions ================ */ -static void GL_SetTextureDimensions( gltexture_t *tex, int width, int height, int depth ) +static void GL_SetTextureDimensions( gl_texture_t *tex, int width, int height, int depth ) { int maxTextureSize; int maxDepthSize = 1; @@ -591,7 +589,7 @@ static void GL_SetTextureDimensions( gltexture_t *tex, int width, int height, in GL_SetTextureTarget =============== */ -static void GL_SetTextureTarget( gltexture_t *tex, rgbdata_t *pic ) +static void GL_SetTextureTarget( gl_texture_t *tex, rgbdata_t *pic ) { Assert( pic != NULL ); Assert( tex != NULL ); @@ -612,7 +610,7 @@ static void GL_SetTextureTarget( gltexture_t *tex, rgbdata_t *pic ) tex->target = GL_TEXTURE_2D_ARRAY_EXT; else if( pic->width > 1 && pic->height > 1 && pic->depth > 1 ) tex->target = GL_TEXTURE_3D; - else if( FBitSet( tex->flags, TF_TEXTURE_RECTANGLE ) && pic->width == glState.width && pic->height == glState.height ) + else if( FBitSet( tex->flags, TF_RECTANGLE ) && pic->width == glState.width && pic->height == glState.height ) tex->target = GL_TEXTURE_RECTANGLE_EXT; else tex->target = GL_TEXTURE_2D; // default case @@ -636,9 +634,6 @@ static void GL_SetTextureTarget( gltexture_t *tex, rgbdata_t *pic ) // depth cubemaps only allowed when GL_EXT_gpu_shader4 is supported if( tex->target == GL_TEXTURE_CUBE_MAP_ARB && !GL_Support( GL_EXT_GPU_SHADER4 ) && FBitSet( tex->flags, TF_DEPTHMAP )) tex->target = GL_NONE; - - if( tex->target == GL_TEXTURE_CUBE_MAP_ARB ) - tex->flags |= TF_CUBEMAP; // it's cubemap! } /* @@ -646,7 +641,7 @@ static void GL_SetTextureTarget( gltexture_t *tex, rgbdata_t *pic ) GL_SetTextureFormat =============== */ -static void GL_SetTextureFormat( gltexture_t *tex, pixformat_t format, int channelMask ) +static void GL_SetTextureFormat( gl_texture_t *tex, pixformat_t format, int channelMask ) { qboolean haveColor = ( channelMask & IMAGE_HAS_COLOR ); qboolean haveAlpha = ( channelMask & IMAGE_HAS_ALPHA ); @@ -660,6 +655,7 @@ static void GL_SetTextureFormat( gltexture_t *tex, pixformat_t format, int chann case PF_DXT1: tex->format = GL_COMPRESSED_RGB_S3TC_DXT1_EXT; break; // never use DXT1 with 1-bit alpha case PF_DXT3: tex->format = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT; break; case PF_DXT5: tex->format = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; break; + case PF_ATI2: tex->format = GL_COMPRESSED_RED_GREEN_RGTC2_EXT; break; } return; } @@ -895,31 +891,6 @@ byte *GL_ApplyFilter( const byte *source, int width, int height ) return out; } -/* -================= -GL_ApplyGamma - -Assume input buffer is RGBA -================= -*/ -byte *GL_ApplyGamma( const byte *source, int pixels, qboolean isNormalMap ) -{ - byte *in = (byte *)source; - byte *out = (byte *)source; - int i; - - if( source && !isNormalMap ) - { - for( i = 0; i < pixels; i++, in += 4 ) - { - in[0] = TextureToGamma( in[0] ); - in[1] = TextureToGamma( in[1] ); - in[2] = TextureToGamma( in[2] ); - } - } - return out; -} - /* ================= GL_BuildMipMap @@ -974,7 +945,6 @@ static void GL_BuildMipMap( byte *in, int srcWidth, int srcHeight, int srcDepth, normal[2] = MAKE_SIGNED( in[row+2] ) + MAKE_SIGNED( next[row+2] ); } - if( !VectorNormalizeLength( normal )) VectorSet( normal, 0.5f, 0.5f, 1.0f ); @@ -1012,46 +982,16 @@ static void GL_BuildMipMap( byte *in, int srcWidth, int srcHeight, int srcDepth, } } -/* -================= -GL_MakeLuminance - -Converts the given image to luminance -================= -*/ -void GL_MakeLuminance( rgbdata_t *in ) -{ - byte luminance; - float r, g, b; - int x, y; - - for( y = 0; y < in->height; y++ ) - { - for( x = 0; x < in->width; x++ ) - { - r = r_luminanceTable[in->buffer[4*(y*in->width+x)+0]][0]; - g = r_luminanceTable[in->buffer[4*(y*in->width+x)+1]][1]; - b = r_luminanceTable[in->buffer[4*(y*in->width+x)+2]][2]; - - luminance = (byte)(r + g + b); - - in->buffer[4*(y*in->width+x)+0] = luminance; - in->buffer[4*(y*in->width+x)+1] = luminance; - in->buffer[4*(y*in->width+x)+2] = luminance; - } - } -} - -static void GL_TextureImageRAW( gltexture_t *tex, GLint side, GLint level, GLint width, GLint height, GLint depth, GLint type, const void *data ) +static void GL_TextureImageRAW( gl_texture_t *tex, GLint side, GLint level, GLint width, GLint height, GLint depth, GLint type, const void *data ) { GLuint cubeTarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB; - qboolean subImage = ( tex->flags & TF_IMG_UPLOADED ); + qboolean subImage = FBitSet( tex->flags, TF_IMG_UPLOADED ); GLenum inFormat = PFDesc[type].glFormat; GLint dataType = GL_UNSIGNED_BYTE; Assert( tex != NULL ); - if( tex->flags & TF_DEPTHMAP ) + if( FBitSet( tex->flags, TF_DEPTHMAP )) inFormat = GL_DEPTH_COMPONENT; if( tex->target == GL_TEXTURE_1D ) @@ -1076,10 +1016,10 @@ static void GL_TextureImageRAW( gltexture_t *tex, GLint side, GLint level, GLint } } -static void GL_TextureImageDXT( gltexture_t *tex, GLint side, GLint level, GLint width, GLint height, GLint depth, size_t size, const void *data ) +static void GL_TextureImageDXT( gl_texture_t *tex, GLint side, GLint level, GLint width, GLint height, GLint depth, size_t size, const void *data ) { GLuint cubeTarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB; - qboolean subImage = ( tex->flags & TF_IMG_UPLOADED ); + qboolean subImage = FBitSet( tex->flags, TF_IMG_UPLOADED ); Assert( tex != NULL ); @@ -1112,7 +1052,7 @@ GL_CheckTexImageError show GL-errors on load images =============== */ -static void GL_CheckTexImageError( gltexture_t *tex ) +static void GL_CheckTexImageError( gl_texture_t *tex ) { int err; @@ -1130,7 +1070,7 @@ GL_UploadTexture upload texture into video memory =============== */ -static qboolean GL_UploadTexture( gltexture_t *tex, rgbdata_t *pic ) +static qboolean GL_UploadTexture( gl_texture_t *tex, rgbdata_t *pic ) { byte *buf, *data; size_t texsize, size; @@ -1224,10 +1164,7 @@ static qboolean GL_UploadTexture( gltexture_t *tex, rgbdata_t *pic ) if(( tex->depth == 1 ) && ( pic->width != tex->width ) || ( pic->height != tex->height )) data = GL_ResampleTexture( buf, pic->width, pic->height, tex->width, tex->height, normalMap ); else data = buf; -#if 0 // g-cont. we can't apply gamma to each texture so we shouldn't do it at all - if( !ImageDXT( pic->type ) && !FBitSet( tex->flags, TF_NOMIPMAP|TF_SKYSIDE )) - data = GL_ApplyGamma( data, tex->width * tex->height * tex->depth, FBitSet( tex->flags, TF_NORMALMAP )); -#endif + if( !ImageDXT( pic->type ) && !FBitSet( tex->flags, TF_NOMIPMAP ) && FBitSet( pic->flags, IMAGE_ONEBIT_ALPHA )) data = GL_ApplyFilter( data, tex->width, tex->height ); @@ -1253,7 +1190,7 @@ static qboolean GL_UploadTexture( gltexture_t *tex, rgbdata_t *pic ) } } - tex->flags |= TF_IMG_UPLOADED; // done + SetBits( tex->flags, TF_IMG_UPLOADED ); // done tex->numMips /= numSides; return true; @@ -1266,7 +1203,7 @@ GL_ProcessImage do specified actions on pixels =============== */ -static void GL_ProcessImage( gltexture_t *tex, rgbdata_t *pic, imgfilter_t *filter ) +static void GL_ProcessImage( gl_texture_t *tex, rgbdata_t *pic, imgfilter_t *filter ) { uint img_flags = 0; @@ -1310,14 +1247,165 @@ static void GL_ProcessImage( gltexture_t *tex, rgbdata_t *pic, imgfilter_t *filt // processing image before uploading (force to rgba, make luma etc) if( pic->buffer ) Image_Process( &pic, 0, 0, img_flags, filter ); - if( tex->flags & TF_LUMINANCE ) + if( FBitSet( tex->flags, TF_LUMINANCE )) + ClearBits( pic->flags, IMAGE_HAS_COLOR ); + } +} + +/* +================ +GL_CheckTexName +================ +*/ +qboolean GL_CheckTexName( const char *name ) +{ + if( !COM_CheckString( name ) || !glw_state.initialized ) + return false; + + if( Q_strlen( name ) >= sizeof( gl_textures->name )) + { + Con_Printf( S_ERROR "LoadTexture: too long name %s (%d)\n", name, Q_strlen( name )); + return false; + } + + return true; +} + +/* +================ +GL_TextureForName +================ +*/ +static gl_texture_t *GL_TextureForName( const char *name ) +{ + gl_texture_t *tex; + uint hash; + + // find the texture in array + hash = COM_HashKey( name, TEXTURES_HASH_SIZE ); + + for( tex = gl_texturesHashTable[hash]; tex != NULL; tex = tex->nextHash ) + { + if( !Q_stricmp( tex->name, name )) + return tex; + } + + return NULL; +} + +/* +================ +GL_AllocTexture +================ +*/ +static gl_texture_t *GL_AllocTexture( const char *name, texFlags_t flags ) +{ + gl_texture_t *tex; + uint i; + + // find a free texture_t slot + for( i = 0, tex = gl_textures; i < gl_numTextures; i++, tex++ ) + if( !tex->name[0] ) break; + + if( i == gl_numTextures ) + { + if( gl_numTextures == MAX_TEXTURES ) + Host_Error( "GL_AllocTexture: MAX_TEXTURES limit exceeds\n" ); + gl_numTextures++; + } + + tex = &gl_textures[i]; + + // copy initial params + Q_strncpy( tex->name, name, sizeof( tex->name )); + if( FBitSet( flags, TF_SKYSIDE )) + tex->texnum = tr.skyboxbasenum++; + else tex->texnum = i; // texnum is used for fast acess into gl_textures array too + tex->flags = flags; + + // add to hash table + tex->hashValue = COM_HashKey( name, TEXTURES_HASH_SIZE ); + tex->nextHash = gl_texturesHashTable[tex->hashValue]; + gl_texturesHashTable[tex->hashValue] = tex; + + return tex; +} + +/* +================ +GL_DeleteTexture +================ +*/ +static void GL_DeleteTexture( gl_texture_t *tex ) +{ + gl_texture_t **prev; + gl_texture_t *cur; + + ASSERT( tex != NULL ); + + // already freed? + if( !tex->texnum ) return; + + // debug + if( !tex->name[0] ) + { + Con_Printf( S_ERROR "GL_DeleteTexture: trying to free unnamed texture with texnum %i\n", tex->texnum ); + return; + } + + // remove from hash table + prev = &gl_texturesHashTable[tex->hashValue]; + + while( 1 ) + { + cur = *prev; + if( !cur ) break; + + if( cur == tex ) { - if( !( tex->flags & TF_DEPTHMAP )) - { - GL_MakeLuminance( pic ); - tex->flags &= ~TF_LUMINANCE; - } - pic->flags &= ~IMAGE_HAS_COLOR; + *prev = cur->nextHash; + break; + } + prev = &cur->nextHash; + } + + // release source + if( tex->original ) + FS_FreeImage( tex->original ); + + pglDeleteTextures( 1, &tex->texnum ); + memset( tex, 0, sizeof( *tex )); +} + +/* +================ +GL_UpdateTexSize + +recalc image room +================ +*/ +void GL_UpdateTexSize( int texnum, int width, int height, int depth ) +{ + int i, j, texsize; + int numSides; + gl_texture_t *tex; + + if( texnum <= 0 || texnum >= MAX_TEXTURES ) + return; + + tex = &gl_textures[texnum]; + numSides = FBitSet( tex->flags, TF_CUBEMAP ) ? 6 : 1; + GL_SetTextureDimensions( tex, width, height, depth ); + tex->size = 0; // recompute now + + for( i = 0; i < numSides; i++ ) + { + for( j = 0; j < Q_max( 1, tex->numMips ); j++ ) + { + width = Q_max( 1, ( tex->width >> j )); + height = Q_max( 1, ( tex->height >> j )); + texsize = GL_CalcTextureSize( tex->format, width, height, tex->depth ); + tex->size += texsize; } } } @@ -1329,34 +1417,22 @@ GL_LoadTexture */ int GL_LoadTexture( const char *name, const byte *buf, size_t size, int flags, imgfilter_t *filter ) { - gltexture_t *tex; + gl_texture_t *tex; rgbdata_t *pic; - uint i, hash; uint picFlags = 0; - if( !COM_CheckString( name ) || !glw_state.initialized ) + if( !GL_CheckTexName( name )) return 0; - if( Q_strlen( name ) >= sizeof( r_textures->name )) - { - Con_Printf( S_ERROR "LoadTexture: too long name %s (%d)\n", name, Q_strlen( name )); - return 0; - } - // see if already loaded - hash = COM_HashKey( name, TEXTURES_HASH_SIZE ); + if(( tex = GL_TextureForName( name ))) + return (tex - gl_textures); - for( tex = r_texturesHashTable[hash]; tex != NULL; tex = tex->nextHash ) - { - if( !Q_stricmp( tex->name, name )) - return (tex - r_textures); - } - - if( flags & TF_NOFLIP_TGA ) - picFlags |= IL_DONTFLIP_TGA; + if( FBitSet( flags, TF_NOFLIP_TGA )) + SetBits( picFlags, IL_DONTFLIP_TGA ); if( FBitSet( flags, TF_KEEP_SOURCE ) && !FBitSet( flags, TF_EXPAND_SOURCE )) - picFlags |= IL_KEEP_8BIT; + SetBits( picFlags, IL_KEEP_8BIT ); // set some image flags Image_SetForceFlags( picFlags ); @@ -1364,34 +1440,13 @@ int GL_LoadTexture( const char *name, const byte *buf, size_t size, int flags, i pic = FS_LoadImage( name, buf, size ); if( !pic ) return 0; // couldn't loading image - // find a free texture slot - if( r_numTextures == MAX_TEXTURES ) - Host_Error( "GL_LoadTexture: MAX_TEXTURES limit exceeds\n" ); - - // find a free texture_t slot - for( i = 0, tex = r_textures; i < r_numTextures; i++, tex++ ) - if( !tex->name[0] ) break; - - if( i == r_numTextures ) - { - if( r_numTextures == MAX_TEXTURES ) - Host_Error( "GL_LoadTexture: MAX_TEXTURES limit exceeds\n" ); - r_numTextures++; - } - - tex = &r_textures[i]; - Q_strncpy( tex->name, name, sizeof( tex->name )); - tex->flags = flags; - - if( flags & TF_SKYSIDE ) - tex->texnum = tr.skyboxbasenum++; - else tex->texnum = i; // texnum is used for fast acess into r_textures array too - + // allocate the new one + tex = GL_AllocTexture( name, flags ); GL_ProcessImage( tex, pic, filter ); if( !GL_UploadTexture( tex, pic )) { - memset( tex, 0, sizeof( gltexture_t )); + memset( tex, 0, sizeof( gl_texture_t )); FS_FreeImage( pic ); // release source texture return 0; } @@ -1399,13 +1454,8 @@ int GL_LoadTexture( const char *name, const byte *buf, size_t size, int flags, i GL_ApplyTextureParams( tex ); // update texture filter, wrap etc FS_FreeImage( pic ); // release source texture - // add to hash table - tex->hashValue = COM_HashKey( tex->name, TEXTURES_HASH_SIZE ); - tex->nextHash = r_texturesHashTable[tex->hashValue]; - r_texturesHashTable[tex->hashValue] = tex; - // NOTE: always return texnum as index in array or engine will stop work !!! - return i; + return tex - gl_textures; } /* @@ -1415,13 +1465,13 @@ GL_LoadTextureArray */ int GL_LoadTextureArray( const char **names, int flags, imgfilter_t *filter ) { - gltexture_t *tex; rgbdata_t *pic, *src; char basename[256]; uint numLayers = 0; uint picFlags = 0; char name[256]; - uint i, j, hash; + gl_texture_t *tex; + uint i, j; if( !names || !names[0] || !glw_state.initialized ) return 0; @@ -1443,20 +1493,12 @@ int GL_LoadTextureArray( const char **names, int flags, imgfilter_t *filter ) Q_strncat( name, va( "[%i]", numLayers ), sizeof( name )); - if( Q_strlen( name ) >= sizeof( r_textures->name )) - { - Con_Printf( S_ERROR "LoadTextureArray: too long name %s (%d)\n", name, Q_strlen( name )); + if( !GL_CheckTexName( name )) return 0; - } // see if already loaded - hash = COM_HashKey( name, TEXTURES_HASH_SIZE ); - - for( tex = r_texturesHashTable[hash]; tex != NULL; tex = tex->nextHash ) - { - if( !Q_stricmp( tex->name, name )) - return (tex - r_textures); - } + if(( tex = GL_TextureForName( name ))) + return (tex - gl_textures); // load all the images and pack it into single image for( i = 0, pic = NULL; i < numLayers; i++ ) @@ -1471,20 +1513,20 @@ int GL_LoadTextureArray( const char **names, int flags, imgfilter_t *filter ) // mixed mode: DXT + RGB if( pic->type != src->type ) { - MsgDev( D_ERROR, "GL_LoadTextureArray: mismatch image format for %s and %s\n", names[0], names[i] ); + Con_Printf( S_ERROR "GL_LoadTextureArray: mismatch image format for %s and %s\n", names[0], names[i] ); break; } // different mipcount if( pic->numMips != src->numMips ) { - MsgDev( D_ERROR, "GL_LoadTextureArray: mismatch mip count for %s and %s\n", names[0], names[i] ); + Con_Printf( S_ERROR "GL_LoadTextureArray: mismatch mip count for %s and %s\n", names[0], names[i] ); break; } if( pic->encode != src->encode ) { - MsgDev( D_ERROR, "GL_LoadTextureArray: mismatch custom encoding for %s and %s\n", names[0], names[i] ); + Con_Printf( S_ERROR "GL_LoadTextureArray: mismatch custom encoding for %s and %s\n", names[0], names[i] ); break; } @@ -1494,7 +1536,7 @@ int GL_LoadTextureArray( const char **names, int flags, imgfilter_t *filter ) if( pic->size != src->size ) { - MsgDev( D_ERROR, "GL_LoadTextureArray: mismatch image size for %s and %s\n", names[0], names[i] ); + Con_Printf( S_ERROR "GL_LoadTextureArray: mismatch image size for %s and %s\n", names[0], names[i] ); break; } } @@ -1513,8 +1555,8 @@ int GL_LoadTextureArray( const char **names, int flags, imgfilter_t *filter ) for( j = 0; j < max( 1, pic->numMips ); j++ ) { - int width = max( 1, ( pic->width >> j )); - int height = max( 1, ( pic->height >> j )); + int width = Q_max( 1, ( pic->width >> j )); + int height = Q_max( 1, ( pic->height >> j )); mipsize = GL_CalcImageSize( pic->type, width, height, 1 ); memcpy( pic->buffer + dstsize + mipsize * i, src->buffer + srcsize, mipsize ); dstsize += mipsize * numLayers; @@ -1530,39 +1572,22 @@ int GL_LoadTextureArray( const char **names, int flags, imgfilter_t *filter ) // there were errors if( !pic || ( pic->depth != numLayers )) { - MsgDev( D_ERROR, "GL_LoadTextureArray: not all layers were loaded. Texture array is not created\n" ); + Con_Printf( S_ERROR "GL_LoadTextureArray: not all layers were loaded. Texture array is not created\n" ); if( pic ) FS_FreeImage( pic ); return 0; } // it's multilayer image! - pic->flags |= IMAGE_MULTILAYER; + SetBits( pic->flags, IMAGE_MULTILAYER ); pic->size *= numLayers; - // find a free texture slot - if( r_numTextures == MAX_TEXTURES ) - Host_Error( "GL_LoadTexture: MAX_TEXTURES limit exceeds\n" ); - - // find a free texture_t slot - for( i = 0, tex = r_textures; i < r_numTextures; i++, tex++ ) - if( !tex->name[0] ) break; - - if( i == r_numTextures ) - { - if( r_numTextures == MAX_TEXTURES ) - Host_Error( "GL_LoadTexture: MAX_TEXTURES limit exceeds\n" ); - r_numTextures++; - } - - tex = &r_textures[i]; - Q_strncpy( tex->name, name, sizeof( tex->name )); - tex->flags = flags; - tex->texnum = i; // texnum is used for fast acess into r_textures array too - + // allocate the new one + tex = GL_AllocTexture( name, flags ); GL_ProcessImage( tex, pic, filter ); + if( !GL_UploadTexture( tex, pic )) { - memset( tex, 0, sizeof( gltexture_t )); + memset( tex, 0, sizeof( gl_texture_t )); FS_FreeImage( pic ); // release source texture return 0; } @@ -1570,98 +1595,50 @@ int GL_LoadTextureArray( const char **names, int flags, imgfilter_t *filter ) GL_ApplyTextureParams( tex ); // update texture filter, wrap etc FS_FreeImage( pic ); // release source texture - // add to hash table - tex->hashValue = COM_HashKey( tex->name, TEXTURES_HASH_SIZE ); - tex->nextHash = r_texturesHashTable[tex->hashValue]; - r_texturesHashTable[tex->hashValue] = tex; - // NOTE: always return texnum as index in array or engine will stop work !!! - return i; + return tex - gl_textures; } /* ================ -GL_LoadTextureInternal +GL_LoadTextureFromBuffer ================ */ -int GL_LoadTextureInternal( const char *name, rgbdata_t *pic, texFlags_t flags, qboolean update ) +int GL_LoadTextureFromBuffer( const char *name, rgbdata_t *pic, texFlags_t flags, qboolean update ) { - gltexture_t *tex; - uint i, hash; + gl_texture_t *tex; - if( !COM_CheckString( name ) || !glw_state.initialized ) + if( !GL_CheckTexName( name )) return 0; - if( Q_strlen( name ) >= sizeof( r_textures->name )) - { - Con_Printf( S_ERROR "LoadTexture: too long name %s (%d)\n", name, Q_strlen( name )); - return 0; - } - // see if already loaded - hash = COM_HashKey( name, TEXTURES_HASH_SIZE ); + if(( tex = GL_TextureForName( name )) && !update ) + return (tex - gl_textures); - for( tex = r_texturesHashTable[hash]; tex != NULL; tex = tex->nextHash ) + // couldn't loading image + if( !pic ) return 0; + + if( update ) { - if( !Q_stricmp( tex->name, name )) - { - if( update ) break; - return (tex - r_textures); - } - } - - if( !pic ) return 0; // couldn't loading image - if( update && !tex ) - { - Host_Error( "Couldn't find texture %s for update\n", name ); - } - - // find a free texture slot - if( r_numTextures == MAX_TEXTURES ) - Host_Error( "GL_LoadTexture: MAX_TEXTURES limit exceeds\n" ); - - if( !update ) - { - // find a free texture_t slot - for( i = 0, tex = r_textures; i < r_numTextures; i++, tex++ ) - if( !tex->name[0] ) break; - - if( i == r_numTextures ) - { - if( r_numTextures == MAX_TEXTURES ) - Host_Error( "GL_LoadTexture: MAX_TEXTURES limit exceeds\n" ); - r_numTextures++; - } - - tex = &r_textures[i]; - hash = COM_HashKey( name, TEXTURES_HASH_SIZE ); - Q_strncpy( tex->name, name, sizeof( tex->name )); - tex->texnum = i; // texnum is used for fast acess into r_textures array too - tex->flags = flags; + if( tex == NULL ) + Host_Error( "GL_LoadTextureFromBuffer: couldn't find texture %s for update\n", name ); + SetBits( tex->flags, flags ); } else { - tex->flags |= flags; + // allocate the new one + tex = GL_AllocTexture( name, flags ); } GL_ProcessImage( tex, pic, NULL ); if( !GL_UploadTexture( tex, pic )) { - memset( tex, 0, sizeof( gltexture_t )); + memset( tex, 0, sizeof( gl_texture_t )); return 0; } GL_ApplyTextureParams( tex ); // update texture filter, wrap etc - - if( !update ) - { - // add to hash table - tex->hashValue = COM_HashKey( tex->name, TEXTURES_HASH_SIZE ); - tex->nextHash = r_texturesHashTable[tex->hashValue]; - r_texturesHashTable[tex->hashValue] = tex; - } - - return (tex - r_textures); + return (tex - gl_textures); } /* @@ -1674,42 +1651,33 @@ creates texture from buffer int GL_CreateTexture( const char *name, int width, int height, const void *buffer, texFlags_t flags ) { rgbdata_t r_empty; - int texture; memset( &r_empty, 0, sizeof( r_empty )); r_empty.width = width; r_empty.height = height; r_empty.type = PF_RGBA_32; r_empty.size = r_empty.width * r_empty.height * 4; - r_empty.flags = IMAGE_HAS_COLOR | (( flags & TF_HAS_ALPHA ) ? IMAGE_HAS_ALPHA : 0 ); r_empty.buffer = (byte *)buffer; - if( FBitSet( flags, TF_ALPHACONTRAST )) - ClearBits( r_empty.flags, IMAGE_HAS_COLOR ); + // clear invalid combinations + ClearBits( flags, TF_TEXTURE_3D ); - if( FBitSet( flags, TF_TEXTURE_1D )) + // if image not luminance and not alphacontrast it will have color + if( !FBitSet( flags, TF_LUMINANCE ) && !FBitSet( flags, TF_ALPHACONTRAST )) + SetBits( r_empty.flags, IMAGE_HAS_COLOR ); + + if( FBitSet( flags, TF_HAS_ALPHA )) + SetBits( r_empty.flags, IMAGE_HAS_ALPHA ); + + if( FBitSet( flags, TF_CUBEMAP )) { - r_empty.height = 1; - r_empty.size = r_empty.width * 4; - } - else if( FBitSet( flags, TF_TEXTURE_3D )) - { - if( !GL_Support( GL_TEXTURE_3D_EXT )) + if( !GL_Support( GL_TEXTURE_CUBEMAP_EXT )) return 0; - - r_empty.depth = r_empty.width; // assume 3D texture as cube - r_empty.size = r_empty.width * r_empty.height * r_empty.depth * 4; - } - else if( FBitSet( flags, TF_CUBEMAP )) - { SetBits( r_empty.flags, IMAGE_CUBEMAP ); - ClearBits( flags, TF_CUBEMAP ); // will be set later r_empty.size *= 6; } - texture = GL_LoadTextureInternal( name, &r_empty, flags, false ); - - return texture; + return GL_LoadTextureInternal( name, &r_empty, flags ); } /* @@ -1722,17 +1690,25 @@ creates texture array from buffer int GL_CreateTextureArray( const char *name, int width, int height, int depth, const void *buffer, texFlags_t flags ) { rgbdata_t r_empty; - int texture; memset( &r_empty, 0, sizeof( r_empty )); - r_empty.width = width; - r_empty.height = height; - r_empty.depth = depth; + r_empty.width = Q_max( width, 1 ); + r_empty.height = Q_max( height, 1 ); + r_empty.depth = Q_max( depth, 1 ); r_empty.type = PF_RGBA_32; r_empty.size = r_empty.width * r_empty.height * r_empty.depth * 4; - r_empty.flags = IMAGE_HAS_COLOR | (( flags & TF_HAS_ALPHA ) ? IMAGE_HAS_ALPHA : 0 ); r_empty.buffer = (byte *)buffer; + // clear invalid combinations + ClearBits( flags, TF_CUBEMAP|TF_SKYSIDE|TF_HAS_LUMA|TF_MAKELUMA|TF_ALPHACONTRAST ); + + // if image not luminance it will have color + if( !FBitSet( flags, TF_LUMINANCE )) + SetBits( r_empty.flags, IMAGE_HAS_COLOR ); + + if( FBitSet( flags, TF_HAS_ALPHA )) + SetBits( r_empty.flags, IMAGE_HAS_ALPHA ); + if( FBitSet( flags, TF_TEXTURE_3D )) { if( !GL_Support( GL_TEXTURE_3D_EXT )) @@ -1745,9 +1721,55 @@ int GL_CreateTextureArray( const char *name, int width, int height, int depth, c SetBits( r_empty.flags, IMAGE_MULTILAYER ); } - texture = GL_LoadTextureInternal( name, &r_empty, flags, false ); + return GL_LoadTextureInternal( name, &r_empty, flags ); +} - return texture; +/* +================ +GL_FindTexture +================ +*/ +int GL_FindTexture( const char *name ) +{ + gl_texture_t *tex; + + if( !GL_CheckTexName( name )) + return 0; + + // see if already loaded + if(( tex = GL_TextureForName( name ))) + return (tex - gl_textures); + + return 0; +} + +/* +================ +GL_FreeImage + +Frees image by name +================ +*/ +void GL_FreeImage( const char *name ) +{ + int texnum; + + if(( texnum = GL_FindTexture( name )) != 0 ) + GL_FreeTexture( texnum ); +} + +/* +================ +GL_FreeTexture +================ +*/ +void GL_FreeTexture( GLenum texnum ) +{ + // number 0 it's already freed + if( texnum <= 0 || !glw_state.initialized ) + return; + + GL_DeleteTexture( &gl_textures[texnum] ); } /* @@ -1757,13 +1779,13 @@ GL_ProcessTexture */ void GL_ProcessTexture( int texnum, float gamma, int topColor, int bottomColor ) { - gltexture_t *image; + gl_texture_t *image; rgbdata_t *pic; int flags = 0; - if( texnum <= 0 ) return; // missed image - Assert( texnum > 0 && texnum < MAX_TEXTURES ); - image = &r_textures[texnum]; + if( texnum <= 0 || texnum >= MAX_TEXTURES ) + return; // missed image + image = &gl_textures[texnum]; // select mode if( gamma != -1.0f ) @@ -1776,19 +1798,19 @@ void GL_ProcessTexture( int texnum, float gamma, int topColor, int bottomColor ) } else { - MsgDev( D_ERROR, "GL_ProcessTexture: bad operation for %s\n", image->name ); + Con_Printf( S_ERROR "GL_ProcessTexture: bad operation for %s\n", image->name ); return; } if( !image->original ) { - MsgDev( D_ERROR, "GL_ProcessTexture: no input data for %s\n", image->name ); + Con_Printf( S_ERROR "GL_ProcessTexture: no input data for %s\n", image->name ); return; } if( ImageDXT( image->original->type )) { - MsgDev( D_ERROR, "GL_ProcessTexture: can't process compressed texture %s\n", image->name ); + Con_Printf( S_ERROR "GL_ProcessTexture: can't process compressed texture %s\n", image->name ); return; } @@ -1802,129 +1824,6 @@ void GL_ProcessTexture( int texnum, float gamma, int topColor, int bottomColor ) FS_FreeImage( pic ); } -/* -================ -GL_LoadTexture -================ -*/ -int GL_FindTexture( const char *name ) -{ - gltexture_t *tex; - uint hash; - - if( !COM_CheckString( name ) || !glw_state.initialized ) - return 0; - - if( Q_strlen( name ) >= sizeof( r_textures->name )) - { - Con_Printf( S_ERROR "FindTexture: too long name %s (%d)\n", name, Q_strlen( name )); - return 0; - } - - // see if already loaded - hash = COM_HashKey( name, TEXTURES_HASH_SIZE ); - - for( tex = r_texturesHashTable[hash]; tex != NULL; tex = tex->nextHash ) - { - if( !Q_stricmp( tex->name, name )) - return (tex - r_textures); - } - - return 0; -} - -/* -================ -GL_FreeImage - -Frees image by name -================ -*/ -void GL_FreeImage( const char *name ) -{ - gltexture_t *tex; - uint hash; - - if( !COM_CheckString( name ) || !glw_state.initialized ) - return; - - if( Q_strlen( name ) >= sizeof( r_textures->name )) - { - Con_Printf( S_ERROR "FreeTexture: too long name %s (%d)\n", name, Q_strlen( name )); - return; - } - - // see if already loaded - hash = COM_HashKey( name, TEXTURES_HASH_SIZE ); - - for( tex = r_texturesHashTable[hash]; tex != NULL; tex = tex->nextHash ) - { - if( !Q_stricmp( tex->name, name )) - { - R_FreeImage( tex ); - return; - } - } -} - -/* -================ -GL_FreeTexture -================ -*/ -void GL_FreeTexture( GLenum texnum ) -{ - // number 0 it's already freed - if( texnum <= 0 || !glw_state.initialized ) - return; - - Assert( texnum > 0 && texnum < MAX_TEXTURES ); - R_FreeImage( &r_textures[texnum] ); -} - -/* -================ -R_FreeImage -================ -*/ -void R_FreeImage( gltexture_t *image ) -{ - gltexture_t *cur; - gltexture_t **prev; - - Assert( image != NULL ); - - if( !image->name[0] ) - { - if( image->texnum != 0 ) - MsgDev( D_ERROR, "trying to free unnamed texture with texnum %i\n", image->texnum ); - return; - } - - // remove from hash table - prev = &r_texturesHashTable[image->hashValue]; - - while( 1 ) - { - cur = *prev; - if( !cur ) break; - - if( cur == image ) - { - *prev = cur->nextHash; - break; - } - prev = &cur->nextHash; - } - - // release source - if( image->original ) - FS_FreeImage( image->original ); - - pglDeleteTextures( 1, &image->texnum ); - memset( image, 0, sizeof( *image )); -} - /* ============================================================================== @@ -1934,53 +1833,83 @@ INTERNAL TEXTURES */ /* ================== -R_InitDefaultTexture +GL_FakeImage ================== */ -static rgbdata_t *R_InitDefaultTexture( texFlags_t *flags ) +static rgbdata_t *GL_FakeImage( int width, int height, int depth, int flags ) { - int x, y; + static byte data2D[1024]; // 16x16x4 + static rgbdata_t r_image; // also use this for bad textures, but without alpha - r_image.width = r_image.height = 16; - r_image.buffer = data2D; - r_image.flags = IMAGE_HAS_COLOR; + r_image.width = Q_max( 1, width ); + r_image.height = Q_max( 1, height ); + r_image.depth = Q_max( 1, depth ); + r_image.flags = flags; r_image.type = PF_RGBA_32; - r_image.size = r_image.width * r_image.height * 4; + r_image.size = r_image.width * r_image.height * r_image.depth * 4; + r_image.buffer = (r_image.size > sizeof( data2D )) ? NULL : data2D; + r_image.palette = NULL; + r_image.numMips = 1; + r_image.encode = 0; - *flags = 0; + if( FBitSet( r_image.flags, IMAGE_CUBEMAP )) + r_image.size *= 6; + memset( data2D, 0xFF, sizeof( data2D )); - // emo-texture from quake1 - for( y = 0; y < 16; y++ ) - { - for( x = 0; x < 16; x++ ) - { - if(( y < 8 ) ^ ( x < 8 )) - ((uint *)&data2D)[y*16+x] = 0xFFFF00FF; - else ((uint *)&data2D)[y*16+x] = 0xFF000000; - } - } return &r_image; } /* ================== -R_InitParticleTexture +R_InitDlightTexture ================== */ -static rgbdata_t *R_InitParticleTexture( texFlags_t *flags ) +void R_InitDlightTexture( void ) { - int x, y; - int dx2, dy, d; + rgbdata_t r_image; - // particle texture - r_image.width = r_image.height = 16; - r_image.buffer = data2D; - r_image.flags = (IMAGE_HAS_COLOR|IMAGE_HAS_ALPHA); + if( tr.dlightTexture != 0 ) + return; // already initialized + + memset( &r_image, 0, sizeof( r_image )); + r_image.width = BLOCK_SIZE; + r_image.height = BLOCK_SIZE; + r_image.flags = IMAGE_HAS_COLOR; r_image.type = PF_RGBA_32; r_image.size = r_image.width * r_image.height * 4; - *flags = TF_CLAMP; + tr.dlightTexture = GL_LoadTextureInternal( "*dlight", &r_image, TF_NOMIPMAP|TF_CLAMP|TF_ATLAS_PAGE ); +} + +/* +================== +GL_CreateInternalTextures +================== +*/ +static void GL_CreateInternalTextures( void ) +{ + int dx2, dy, d; + int x, y; + rgbdata_t *pic; + + // emo-texture from quake1 + pic = GL_FakeImage( 16, 16, 1, IMAGE_HAS_COLOR ); + + for( y = 0; y < 16; y++ ) + { + for( x = 0; x < 16; x++ ) + { + if(( y < 8 ) ^ ( x < 8 )) + ((uint *)pic->buffer)[y*16+x] = 0xFFFF00FF; + else ((uint *)pic->buffer)[y*16+x] = 0xFF000000; + } + } + + tr.defaultTexture = GL_LoadTextureInternal( "*default", pic, TF_COLORMAP ); + + // particle texture from quake1 + pic = GL_FakeImage( 16, 16, 1, IMAGE_HAS_COLOR|IMAGE_HAS_ALPHA ); for( x = 0; x < 16; x++ ) { @@ -1991,139 +1920,32 @@ static rgbdata_t *R_InitParticleTexture( texFlags_t *flags ) { dy = y - 8; d = 255 - 35 * sqrt( dx2 + dy * dy ); - data2D[( y*16 + x ) * 4 + 3] = bound( 0, d, 255 ); + pic->buffer[( y*16 + x ) * 4 + 3] = bound( 0, d, 255 ); } } - return &r_image; -} -/* -================== -R_InitCinematicTexture -================== -*/ -static rgbdata_t *R_InitCinematicTexture( texFlags_t *flags ) -{ - r_image.type = PF_RGBA_32; - r_image.flags = IMAGE_HAS_COLOR; - r_image.width = 640; // same as menu head - r_image.height = 100; - r_image.size = r_image.width * r_image.height * 4; - r_image.buffer = NULL; + tr.particleTexture = GL_LoadTextureInternal( "*particle", pic, TF_CLAMP ); - *flags = TF_NOMIPMAP|TF_CLAMP; + // white texture + pic = GL_FakeImage( 4, 4, 1, IMAGE_HAS_COLOR ); + for( x = 0; x < 16; x++ ) + ((uint *)pic->buffer)[x] = 0xFFFFFFFF; + tr.whiteTexture = GL_LoadTextureInternal( "*white", pic, TF_COLORMAP ); - return &r_image; -} + // gray texture + pic = GL_FakeImage( 4, 4, 1, IMAGE_HAS_COLOR ); + for( x = 0; x < 16; x++ ) + ((uint *)pic->buffer)[x] = 0xFF7F7F7F; + tr.grayTexture = GL_LoadTextureInternal( "*gray", pic, TF_COLORMAP ); -/* -================== -R_InitSolidColorTexture -================== -*/ -static rgbdata_t *R_InitSolidColorTexture( texFlags_t *flags, int color ) -{ - // solid color texture - r_image.width = r_image.height = 1; - r_image.buffer = data2D; - r_image.flags = IMAGE_HAS_COLOR; - r_image.type = PF_RGB_24; - r_image.size = r_image.width * r_image.height * 3; + pic = GL_FakeImage( 4, 4, 1, IMAGE_HAS_COLOR ); + for( x = 0; x < 16; x++ ) + ((uint *)pic->buffer)[x] = 0xFF000000; + tr.blackTexture = GL_LoadTextureInternal( "*black", pic, TF_COLORMAP ); - *flags = 0; - - data2D[0] = data2D[1] = data2D[2] = color; - return &r_image; -} - -/* -================== -R_InitWhiteTexture -================== -*/ -static rgbdata_t *R_InitWhiteTexture( texFlags_t *flags ) -{ - return R_InitSolidColorTexture( flags, 255 ); -} - -/* -================== -R_InitGrayTexture -================== -*/ -static rgbdata_t *R_InitGrayTexture( texFlags_t *flags ) -{ - return R_InitSolidColorTexture( flags, 127 ); -} - -/* -================== -R_InitBlackTexture -================== -*/ -static rgbdata_t *R_InitBlackTexture( texFlags_t *flags ) -{ - return R_InitSolidColorTexture( flags, 0 ); -} - -/* -================== -R_InitDlightTexture -================== -*/ -void R_InitDlightTexture( void ) -{ - if( tr.dlightTexture != 0 ) - return; // already initialized - - r_image.width = BLOCK_SIZE; - r_image.height = BLOCK_SIZE; - r_image.flags = IMAGE_HAS_COLOR; - r_image.type = PF_RGBA_32; - r_image.size = r_image.width * r_image.height * 4; - r_image.buffer = NULL; - - tr.dlightTexture = GL_LoadTextureInternal( "*dlight", &r_image, TF_NOMIPMAP|TF_CLAMP|TF_ATLAS_PAGE, false ); -} - -/* -================== -R_InitBuiltinTextures -================== -*/ -static void R_InitBuiltinTextures( void ) -{ - rgbdata_t *pic; - texFlags_t flags; - - const struct - { - char *name; - int *texnum; - rgbdata_t *(*init)( texFlags_t *flags ); - } - - textures[] = - { - { "*default", &tr.defaultTexture, R_InitDefaultTexture }, - { "*particle", &tr.particleTexture, R_InitParticleTexture }, - { "*white", &tr.whiteTexture, R_InitWhiteTexture }, - { "*gray", &tr.grayTexture, R_InitGrayTexture }, - { "*black", &tr.blackTexture, R_InitBlackTexture }, // not used by engine - { "*cintexture", &tr.cinTexture, R_InitCinematicTexture }, // intermediate buffer to renderer cinematic textures - { NULL, NULL, NULL } - }; - size_t i, num_builtin_textures = ARRAYSIZE( textures ) - 1; - - for( i = 0; i < num_builtin_textures; i++ ) - { - memset( &r_image, 0, sizeof( rgbdata_t )); - memset( data2D, 0xFF, sizeof( data2D )); - - pic = textures[i].init( &flags ); - if( pic == NULL ) continue; - *textures[i].texnum = GL_LoadTextureInternal( textures[i].name, pic, flags, false ); - } + // cinematic + pic = GL_FakeImage( 640, 100, 1, IMAGE_HAS_COLOR ); + tr.cinTexture = GL_LoadTextureInternal( "*cintexture", pic, TF_NOMIPMAP|TF_CLAMP ); } /* @@ -2133,13 +1955,13 @@ R_TextureList_f */ void R_TextureList_f( void ) { - gltexture_t *image; + gl_texture_t *image; int i, texCount, bytes = 0; Con_Printf( "\n" ); Con_Printf( " -id- -w- -h- -size- -fmt- -type- -data- -encode- -wrap- -depth- -name--------\n" ); - for( i = texCount = 0, image = r_textures; i < r_numTextures; i++, image++ ) + for( i = texCount = 0, image = gl_textures; i < gl_numTextures; i++, image++ ) { if( !image->texnum ) continue; @@ -2182,6 +2004,9 @@ void R_TextureList_f( void ) case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: Con_Printf( "DXT5 " ); break; + case GL_COMPRESSED_RED_GREEN_RGTC2_EXT: + Con_Printf( "ATI2 " ); + break; case GL_RGBA: Con_Printf( "RGBA " ); break; @@ -2332,32 +2157,20 @@ R_InitImages */ void R_InitImages( void ) { - float f; - uint i; - - memset( r_textures, 0, sizeof( r_textures )); - memset( r_texturesHashTable, 0, sizeof( r_texturesHashTable )); - r_numTextures = 0; + memset( gl_textures, 0, sizeof( gl_textures )); + memset( gl_texturesHashTable, 0, sizeof( gl_texturesHashTable )); + gl_numTextures = 0; // create unused 0-entry - Q_strncpy( r_textures->name, "*unused*", sizeof( r_textures->name )); - r_textures->hashValue = COM_HashKey( r_textures->name, TEXTURES_HASH_SIZE ); - r_textures->nextHash = r_texturesHashTable[r_textures->hashValue]; - r_texturesHashTable[r_textures->hashValue] = r_textures; - r_numTextures = 1; + Q_strncpy( gl_textures->name, "*unused*", sizeof( gl_textures->name )); + gl_textures->hashValue = COM_HashKey( gl_textures->name, TEXTURES_HASH_SIZE ); + gl_textures->nextHash = gl_texturesHashTable[gl_textures->hashValue]; + gl_texturesHashTable[gl_textures->hashValue] = gl_textures; + gl_numTextures = 1; - // build luminance table - for( i = 0; i < 256; i++ ) - { - f = (float)i; - r_luminanceTable[i][0] = f * 0.299f; - r_luminanceTable[i][1] = f * 0.587f; - r_luminanceTable[i][2] = f * 0.114f; - } - - // set texture parameters + // validate cvars R_SetTextureParameters(); - R_InitBuiltinTextures(); + GL_CreateInternalTextures(); R_ParseTexFilters( "scripts/texfilter.txt" ); Cmd_AddCommand( "texturelist", R_TextureList_f, "display loaded textures list" ); @@ -2370,19 +2183,17 @@ R_ShutdownImages */ void R_ShutdownImages( void ) { - gltexture_t *image; + gl_texture_t *tex; int i; - if( !glw_state.initialized ) return; - Cmd_RemoveCommand( "texturelist" ); GL_CleanupAllTextureUnits(); - for( i = 0, image = r_textures; i < r_numTextures; i++, image++ ) - R_FreeImage( image ); + for( i = 0, tex = gl_textures; i < gl_numTextures; i++, tex++ ) + GL_DeleteTexture( tex ); memset( tr.lightmapTextures, 0, sizeof( tr.lightmapTextures )); - memset( r_texturesHashTable, 0, sizeof( r_texturesHashTable )); - memset( r_textures, 0, sizeof( r_textures )); - r_numTextures = 0; + memset( gl_texturesHashTable, 0, sizeof( gl_texturesHashTable )); + memset( gl_textures, 0, sizeof( gl_textures )); + gl_numTextures = 0; } \ No newline at end of file diff --git a/engine/client/gl_local.h b/engine/client/gl_local.h index a6a0a78f..8be880ad 100644 --- a/engine/client/gl_local.h +++ b/engine/client/gl_local.h @@ -93,7 +93,7 @@ typedef struct gltexture_s int servercount; uint hashValue; struct gltexture_s *nextHash; -} gltexture_t; +} gl_texture_t; typedef struct { @@ -306,16 +306,18 @@ void R_DrawModelHull( void ); // gl_image.c // void R_SetTextureParameters( void ); -gltexture_t *R_GetTexture( GLenum texnum ); +gl_texture_t *R_GetTexture( GLenum texnum ); +#define GL_LoadTextureInternal( name, pic, flags ) GL_LoadTextureFromBuffer( name, pic, flags, false ) +#define GL_UpdateTextureInternal( name, pic, flags ) GL_LoadTextureFromBuffer( name, pic, flags, true ) int GL_LoadTexture( const char *name, const byte *buf, size_t size, int flags, imgfilter_t *filter ); int GL_LoadTextureArray( const char **names, int flags, imgfilter_t *filter ); -int GL_LoadTextureInternal( const char *name, rgbdata_t *pic, texFlags_t flags, qboolean update ); +int GL_LoadTextureFromBuffer( const char *name, rgbdata_t *pic, texFlags_t flags, qboolean update ); byte *GL_ResampleTexture( const byte *source, int in_w, int in_h, int out_w, int out_h, qboolean isNormalMap ); int GL_CreateTexture( const char *name, int width, int height, const void *buffer, texFlags_t flags ); int GL_CreateTextureArray( const char *name, int width, int height, int depth, const void *buffer, texFlags_t flags ); void GL_ProcessTexture( int texnum, float gamma, int topColor, int bottomColor ); -void GL_ApplyTextureParams( gltexture_t *tex ); -void R_FreeImage( gltexture_t *image ); +void GL_UpdateTexSize( int texnum, int width, int height, int depth ); +void GL_ApplyTextureParams( gl_texture_t *tex ); int GL_FindTexture( const char *name ); void GL_FreeTexture( GLenum texnum ); void GL_FreeImage( const char *name ); diff --git a/engine/client/gl_rmain.c b/engine/client/gl_rmain.c index 7f63a373..8edf95be 100644 --- a/engine/client/gl_rmain.c +++ b/engine/client/gl_rmain.c @@ -579,9 +579,9 @@ using to find source waterleaf with watertexture to grab fog values from it ============= */ -static gltexture_t *R_RecursiveFindWaterTexture( const mnode_t *node, const mnode_t *ignore, qboolean down ) +static gl_texture_t *R_RecursiveFindWaterTexture( const mnode_t *node, const mnode_t *ignore, qboolean down ) { - gltexture_t *tex = NULL; + gl_texture_t *tex = NULL; // assure the initial node is not null // we could check it here, but we would rather check it @@ -654,7 +654,7 @@ from underwater leaf (idea: XaeroX) static void R_CheckFog( void ) { cl_entity_t *ent; - gltexture_t *tex; + gl_texture_t *tex; int i, cnt, count; // quake global fog @@ -1164,7 +1164,7 @@ void R_DrawCubemapView( const vec3_t origin, const vec3_t angles, int size ) static int GL_RenderGetParm( int parm, int arg ) { - gltexture_t *glt; + gl_texture_t *glt; switch( parm ) { @@ -1265,7 +1265,7 @@ static int GL_RenderGetParm( int parm, int arg ) static void R_GetDetailScaleForTexture( int texture, float *xScale, float *yScale ) { - gltexture_t *glt = R_GetTexture( texture ); + gl_texture_t *glt = R_GetTexture( texture ); if( xScale ) *xScale = glt->xscale; if( yScale ) *yScale = glt->yscale; @@ -1273,7 +1273,7 @@ static void R_GetDetailScaleForTexture( int texture, float *xScale, float *yScal static void R_GetExtraParmsForTexture( int texture, byte *red, byte *green, byte *blue, byte *density ) { - gltexture_t *glt = R_GetTexture( texture ); + gl_texture_t *glt = R_GetTexture( texture ); if( red ) *red = glt->fogParams[0]; if( green ) *green = glt->fogParams[1]; @@ -1500,7 +1500,7 @@ static render_api_t gRenderAPI = GL_TextureTarget, GL_SetTexCoordArrayMode, GL_GetProcAddress, - NULL, + GL_UpdateTexSize, NULL, NULL, CL_DrawParticlesExternal, diff --git a/engine/client/gl_rmisc.c b/engine/client/gl_rmisc.c index 99388948..f3228860 100644 --- a/engine/client/gl_rmisc.c +++ b/engine/client/gl_rmisc.c @@ -19,15 +19,6 @@ GNU General Public License for more details. #include "mod_local.h" #include "shake.h" -typedef struct -{ - const char *texname; - const char *detail; - const char material; - int lMin; - int lMax; -} dmaterial_t; - typedef struct { char texname[64]; // shortname @@ -37,188 +28,6 @@ typedef struct dfilter_t *tex_filters[MAX_TEXTURES]; int num_texfilters; -// default rules for apply detail textures. -// maybe move this to external script? -static const dmaterial_t detail_table[] = -{ -{ "crt", "dt_conc", 'C', 0, 0 }, // concrete -{ "rock", "dt_rock1", 'C', 0, 0 }, -{ "conc", "dt_conc", 'C', 0, 0 }, -{ "brick", "dt_brick", 'C', 0, 0 }, -{ "wall", "dt_brick", 'C', 0, 0 }, -{ "city", "dt_conc", 'C', 0, 0 }, -{ "crete", "dt_conc", 'C', 0, 0 }, -{ "generic", "dt_brick", 'C', 0, 0 }, -{ "floor", "dt_conc", 'C', 0, 0 }, -{ "metal", "dt_metal%i", 'M', 1, 2 }, // metal -{ "mtl", "dt_metal%i", 'M', 1, 2 }, -{ "pipe", "dt_metal%i", 'M', 1, 2 }, -{ "elev", "dt_metal%i", 'M', 1, 2 }, -{ "sign", "dt_metal%i", 'M', 1, 2 }, -{ "barrel", "dt_metal%i", 'M', 1, 2 }, -{ "bath", "dt_ssteel1", 'M', 1, 2 }, -{ "tech", "dt_ssteel1", 'M', 1, 2 }, -{ "refbridge", "dt_metal%i", 'M', 1, 2 }, -{ "panel", "dt_ssteel1", 'M', 0, 0 }, -{ "brass", "dt_ssteel1", 'M', 0, 0 }, -{ "rune", "dt_metal%i", 'M', 1, 2 }, -{ "car", "dt_metal%i", 'M', 1, 2 }, -{ "circuit", "dt_metal%i", 'M', 1, 2 }, -{ "steel", "dt_ssteel1", 'M', 0, 0 }, -{ "dirt", "dt_ground%i", 'D', 1, 5 }, // dirt -{ "drt", "dt_ground%i", 'D', 1, 5 }, -{ "out", "dt_ground%i", 'D', 1, 5 }, -{ "grass", "dt_grass1", 'D', 0, 0 }, -{ "mud", "dt_carpet1", 'D', 0, 0 }, -{ "vent", "dt_ssteel1", 'V', 1, 4 }, // vent -{ "duct", "dt_ssteel1", 'V', 1, 4 }, -{ "tile", "dt_smooth%i", 'T', 1, 2 }, -{ "labflr", "dt_smooth%i", 'T', 1, 2 }, -{ "bath", "dt_smooth%i", 'T', 1, 2 }, -{ "grate", "dt_stone%i", 'G', 1, 4 }, // vent -{ "stone", "dt_stone%i", 'G', 1, 4 }, -{ "grt", "dt_stone%i", 'G', 1, 4 }, -{ "wiz", "dt_wood%i", 'W', 1, 3 }, -{ "wood", "dt_wood%i", 'W', 1, 3 }, -{ "wizwood", "dt_wood%i", 'W', 1, 3 }, -{ "wd", "dt_wood%i", 'W', 1, 3 }, -{ "table", "dt_wood%i", 'W', 1, 3 }, -{ "board", "dt_wood%i", 'W', 1, 3 }, -{ "chair", "dt_wood%i", 'W', 1, 3 }, -{ "brd", "dt_wood%i", 'W', 1, 3 }, -{ "carp", "dt_carpet1", 'W', 1, 3 }, -{ "book", "dt_wood%i", 'W', 1, 3 }, -{ "box", "dt_wood%i", 'W', 1, 3 }, -{ "cab", "dt_wood%i", 'W', 1, 3 }, -{ "couch", "dt_wood%i", 'W', 1, 3 }, -{ "crate", "dt_wood%i", 'W', 1, 3 }, -{ "poster", "dt_plaster%i", 'W', 1, 2 }, -{ "sheet", "dt_plaster%i", 'W', 1, 2 }, -{ "stucco", "dt_plaster%i", 'W', 1, 2 }, -{ "comp", "dt_smooth1", 'P', 0, 0 }, -{ "cmp", "dt_smooth1", 'P', 0, 0 }, -{ "elec", "dt_smooth1", 'P', 0, 0 }, -{ "vend", "dt_smooth1", 'P', 0, 0 }, -{ "monitor", "dt_smooth1", 'P', 0, 0 }, -{ "phone", "dt_smooth1", 'P', 0, 0 }, -{ "glass", "dt_ssteel1", 'Y', 0, 0 }, -{ "window", "dt_ssteel1", 'Y', 0, 0 }, -{ "flesh", "dt_rough1", 'F', 0, 0 }, -{ "meat", "dt_rough1", 'F', 0, 0 }, -{ "fls", "dt_rough1", 'F', 0, 0 }, -{ "ground", "dt_ground%i", 'D', 1, 5 }, -{ "gnd", "dt_ground%i", 'D', 1, 5 }, -{ "snow", "dt_snow%i", 'O', 1, 2 }, // snow -{ "wswamp", "dt_smooth1", 'W', 0, 0 }, -{ NULL, NULL, 0, 0, 0 } -}; - -static const char *R_DetailTextureForName( const char *name ) -{ - const dmaterial_t *table; - - if( !name || !*name ) return NULL; - if( !Q_strnicmp( name, "sky", 3 )) - return NULL; // never details for sky - - // never apply details for liquids - if( !Q_strnicmp( name + 1, "!lava", 5 )) - return NULL; - if( !Q_strnicmp( name + 1, "!slime", 6 )) - return NULL; - if( !Q_strnicmp( name, "!cur_90", 7 )) - return NULL; - if( !Q_strnicmp( name, "!cur_0", 6 )) - return NULL; - if( !Q_strnicmp( name, "!cur_270", 8 )) - return NULL; - if( !Q_strnicmp( name, "!cur_180", 8 )) - return NULL; - if( !Q_strnicmp( name, "!cur_up", 7 )) - return NULL; - if( !Q_strnicmp( name, "!cur_dwn", 8 )) - return NULL; - if( name[0] == '!' ) - return NULL; - - // never apply details to the special textures - if( !Q_strnicmp( name, "origin", 6 )) - return NULL; - if( !Q_strnicmp( name, "clip", 4 )) - return NULL; - if( !Q_strnicmp( name, "hint", 4 )) - return NULL; - if( !Q_strnicmp( name, "skip", 4 )) - return NULL; - if( !Q_strnicmp( name, "translucent", 11 )) - return NULL; - if( !Q_strnicmp( name, "3dsky", 5 )) // xash-mod support :-) - return NULL; - if( !Q_strnicmp( name, "scroll", 6 )) - return NULL; - if( name[0] == '@' ) - return NULL; - - // last check ... - if( !Q_strnicmp( name, "null", 4 )) - return NULL; - - for( table = detail_table; table && table->texname; table++ ) - { - if( Q_stristr( name, table->texname )) - { - if(( table->lMin + table->lMax ) > 0 ) - return va( table->detail, COM_RandomLong( table->lMin, table->lMax )); - return table->detail; - } - } - - return NULL; -} - -void R_CreateDetailTexturesList( const char *filename ) -{ - file_t *detail_txt = NULL; - float xScale, yScale; - const char *detail_name; - texture_t *tex; - rgbdata_t *pic; - int i; - - for( i = 0; i < cl.worldmodel->numtextures; i++ ) - { - tex = cl.worldmodel->textures[i]; - detail_name = R_DetailTextureForName( tex->name ); - if( !detail_name ) continue; - - // detailtexture detected - if( detail_name ) - { - if( !detail_txt ) detail_txt = FS_Open( filename, "w", false ); - if( !detail_txt ) - { - MsgDev( D_ERROR, "Can't write %s\n", filename ); - break; - } - - pic = FS_LoadImage( va( "gfx/detail/%s", detail_name ), NULL, 0 ); - - if( pic ) - { - xScale = (pic->width / (float)tex->width) * gl_detailscale->value; - yScale = (pic->height / (float)tex->height) * gl_detailscale->value; - FS_FreeImage( pic ); - } - else xScale = yScale = 10.0f; - - // store detailtexture description - FS_Printf( detail_txt, "%s detail/%s %.2f %.2f\n", tex->name, detail_name, xScale, yScale ); - } - } - - if( detail_txt ) FS_Close( detail_txt ); -} - void R_ParseDetailTextures( const char *filename ) { char *afile, *pfile; @@ -229,12 +38,6 @@ void R_ParseDetailTextures( const char *filename ) texture_t *tex; int i; - if( r_detailtextures->value >= 2 && !FS_FileExists( filename, false )) - { - // use built-in generator for detail textures - R_CreateDetailTexturesList( filename ); - } - afile = FS_LoadFile( filename, NULL, false ); if( !afile ) return; @@ -297,7 +100,7 @@ void R_ParseDetailTextures( const char *filename ) // texture is loaded if( tex->dt_texturenum ) { - gltexture_t *glt; + gl_texture_t *glt; glt = R_GetTexture( tex->gl_texturenum ); glt->xscale = xScale; @@ -451,7 +254,7 @@ void R_NewMap( void ) R_ClearDecals(); // clear all level decals // upload detailtextures - if( r_detailtextures->value ) + if( CVAR_TO_BOOL( r_detailtextures )) { string mapname, filepath; @@ -462,7 +265,7 @@ void R_NewMap( void ) R_ParseDetailTextures( filepath ); } - if( v_dark->value ) + if( CVAR_TO_BOOL( v_dark )) { screenfade_t *sf = &clgame.fade; float fadetime = 5.0f; @@ -505,7 +308,7 @@ void R_NewMap( void ) tx = cl.worldmodel->textures[i]; - if( !Q_strncmp( tx->name, "sky", 3 ) && tx->width == 256 && tx->height == 128 ) + if( !Q_strncmp( tx->name, "sky", 3 ) && tx->width == ( tx->height * 2 )) tr.skytexturenum = i; tx->texturechain = NULL; diff --git a/engine/client/gl_rsurf.c b/engine/client/gl_rsurf.c index 4a7fb9b0..7ab32b64 100644 --- a/engine/client/gl_rsurf.c +++ b/engine/client/gl_rsurf.c @@ -275,7 +275,7 @@ void GL_BuildPolygonFromSurface( model_t *mod, msurface_t *fa ) float sample_size; int vertpage; texture_t *tex; - gltexture_t *glt; + gl_texture_t *glt; float *vec; float s, t; glpoly_t *poly; @@ -645,7 +645,7 @@ static void LM_UploadBlock( qboolean dynamic ) r_lightmap.size = r_lightmap.width * r_lightmap.height * 4; r_lightmap.flags = IMAGE_HAS_COLOR; r_lightmap.buffer = gl_lms.lightmap_buffer; - tr.lightmapTextures[i] = GL_LoadTextureInternal( lmName, &r_lightmap, TF_FONT|TF_ATLAS_PAGE, false ); + tr.lightmapTextures[i] = GL_LoadTextureInternal( lmName, &r_lightmap, TF_FONT|TF_ATLAS_PAGE ); if( ++gl_lms.current_lightmap_texture == MAX_LIGHTMAPS ) Host_Error( "AllocBlock: full\n" ); @@ -734,7 +734,7 @@ void DrawGLPoly( glpoly_t *p, float xScale, float yScale ) if( p->flags & SURF_CONVEYOR ) { - gltexture_t *texture; + gl_texture_t *texture; float flConveyorSpeed; float flRate, flAngle; @@ -1005,7 +1005,7 @@ R_RenderDetails */ void R_RenderDetails( void ) { - gltexture_t *glt; + gl_texture_t *glt; mextrasurf_t *es, *p; msurface_t *fa; int i; diff --git a/engine/client/gl_sprite.c b/engine/client/gl_sprite.c index f3b1bcc9..8121f10d 100644 --- a/engine/client/gl_sprite.c +++ b/engine/client/gl_sprite.c @@ -400,7 +400,7 @@ void Mod_LoadMapSprite( model_t *mod, const void *buffer, size_t size, qboolean pspriteframe->left = -( w >> 1 ); pspriteframe->down = ( h >> 1 ) - h; pspriteframe->right = w + -( w >> 1 ); - pspriteframe->gl_texturenum = GL_LoadTextureInternal( texname, &temp, TF_IMAGE, false ); + pspriteframe->gl_texturenum = GL_LoadTextureInternal( texname, &temp, TF_IMAGE ); xl += w; if( xl >= pix->width ) diff --git a/engine/client/gl_warp.c b/engine/client/gl_warp.c index 743c29b1..073d36b9 100644 --- a/engine/client/gl_warp.c +++ b/engine/client/gl_warp.c @@ -21,7 +21,7 @@ GNU General Public License for more details. #define SKYCLOUDS_QUALITY 12 #define MAX_CLIP_VERTS 128 // skybox clip vertices #define TURBSCALE ( 256.0f / ( M_PI2 )) -static const char* r_skyBoxSuffix[6] = { "rt", "bk", "lf", "ft", "up", "dn" }; +const char* r_skyBoxSuffix[6] = { "rt", "bk", "lf", "ft", "up", "dn" }; static const int r_skyTexOrder[6] = { 0, 2, 1, 3, 4, 5 }; static const vec3_t skyclip[6] = @@ -711,7 +711,7 @@ void R_InitSkyClouds( mip_t *mt, texture_t *tx, qboolean custom_palette ) r_temp.palette = NULL; // load it in - tr.solidskyTexture = GL_LoadTextureInternal( "solid_sky", &r_temp, TF_NOMIPMAP, false ); + tr.solidskyTexture = GL_LoadTextureInternal( "solid_sky", &r_temp, TF_NOMIPMAP ); for( i = 0; i < r_sky->width >> 1; i++ ) { @@ -734,7 +734,7 @@ void R_InitSkyClouds( mip_t *mt, texture_t *tx, qboolean custom_palette ) r_temp.flags = IMAGE_HAS_COLOR|IMAGE_HAS_ALPHA; // load it in - tr.alphaskyTexture = GL_LoadTextureInternal( "alpha_sky", &r_temp, TF_NOMIPMAP, false ); + tr.alphaskyTexture = GL_LoadTextureInternal( "alpha_sky", &r_temp, TF_NOMIPMAP ); // clean up FS_FreeImage( r_sky ); diff --git a/engine/client/vgui/vgui_draw.c b/engine/client/vgui/vgui_draw.c index a8db6252..5acbe093 100644 --- a/engine/client/vgui/vgui_draw.c +++ b/engine/client/vgui/vgui_draw.c @@ -96,7 +96,7 @@ void VGUI_UploadTexture( int id, const char *buffer, int width, int height ) r_image.flags = IMAGE_HAS_COLOR|IMAGE_HAS_ALPHA; r_image.buffer = (byte *)buffer; - g_textures[id] = GL_LoadTextureInternal( texName, &r_image, TF_IMAGE, false ); + g_textures[id] = GL_LoadTextureInternal( texName, &r_image, TF_IMAGE ); } /* diff --git a/engine/common/common.h b/engine/common/common.h index 1eb5cd20..2bab410d 100644 --- a/engine/common/common.h +++ b/engine/common/common.h @@ -123,7 +123,7 @@ typedef enum #include "crtlib.h" #include "cvar.h" -#define XASH_VERSION 0.99f // engine current version +#define XASH_VERSION "0.99" // engine current version // PERFORMANCE INFO #define MIN_FPS 20.0 // host minimum fps value for maxfps. @@ -379,6 +379,7 @@ typedef struct host_parm_s string finalmsg; // server shutdown final message string downloadfile; // filename to be downloading int downloadcount; // how many files remain to downloading + char deferred_cmd[128]; // deferred commands host_redirect_t rd; // remote console // command line parms @@ -503,7 +504,7 @@ NOTE: number at end of pixelformat name it's a total bitscount e.g. PF_RGB_24 == ======================================================================== */ #define ImageRAW( type ) (type == PF_RGBA_32 || type == PF_BGRA_32 || type == PF_RGB_24 || type == PF_BGR_24) -#define ImageDXT( type ) (type == PF_DXT1 || type == PF_DXT3 || type == PF_DXT5) +#define ImageDXT( type ) (type == PF_DXT1 || type == PF_DXT3 || type == PF_DXT5 || type == PF_ATI2) typedef enum { @@ -517,6 +518,7 @@ typedef enum PF_DXT1, // s3tc DXT1 format PF_DXT3, // s3tc DXT3 format PF_DXT5, // s3tc DXT5 format + PF_ATI2, // latc ATI2N format PF_TOTALCOUNT, // must be last } pixformat_t; diff --git a/engine/common/console.c b/engine/common/console.c index bedb2e7d..7fb2e4dc 100644 --- a/engine/common/console.c +++ b/engine/common/console.c @@ -2096,7 +2096,7 @@ void Con_DrawSolidConsole( int lines ) memcpy( color, g_color_table[7], sizeof( color )); - Q_snprintf( curbuild, MAX_STRING, "Xash3D %i/%g (hw build %i)", PROTOCOL_VERSION, XASH_VERSION, Q_buildnum( )); + Q_snprintf( curbuild, MAX_STRING, "Xash3D %i/%s (hw build %i)", PROTOCOL_VERSION, XASH_VERSION, Q_buildnum( )); Con_DrawStringLen( curbuild, &stringLen, &charH ); start = glState.width - stringLen; stringLen = Con_StringLength( curbuild ); @@ -2246,8 +2246,8 @@ void Con_DrawVersion( void ) } if( host.force_draw_version || draw_version ) - Q_snprintf( curbuild, MAX_STRING, "Xash3D v%i/%g (build %i)", PROTOCOL_VERSION, XASH_VERSION, Q_buildnum( )); - else Q_snprintf( curbuild, MAX_STRING, "v%i/%g (build %i)", PROTOCOL_VERSION, XASH_VERSION, Q_buildnum( )); + Q_snprintf( curbuild, MAX_STRING, "Xash3D v%i/%s (build %i)", PROTOCOL_VERSION, XASH_VERSION, Q_buildnum( )); + else Q_snprintf( curbuild, MAX_STRING, "v%i/%s (build %i)", PROTOCOL_VERSION, XASH_VERSION, Q_buildnum( )); Con_DrawStringLen( curbuild, &stringLen, &charH ); start = glState.width - stringLen * 1.05f; stringLen = Con_StringLength( curbuild ); @@ -2368,7 +2368,7 @@ void Con_VidInit( void ) { qboolean draw_to_console = false; int length = 0; - gltexture_t *chars; + gl_texture_t *chars; // NOTE: only these games want to draw build number into console background if( !Q_stricmp( FS_Gamedir(), "id1" )) diff --git a/engine/common/host.c b/engine/common/host.c index 1b8676c9..95b50f94 100644 --- a/engine/common/host.c +++ b/engine/common/host.c @@ -824,7 +824,7 @@ int EXPORT Host_Main( const char *progname, int bChangeGame, pfnChangeGame func host_limitlocal = Cvar_Get( "host_limitlocal", "0", 0, "apply cl_cmdrate and rate to loopback connection" ); con_gamemaps = Cvar_Get( "con_mapfilter", "1", FCVAR_ARCHIVE, "when true show only maps in game folder" ); build = Cvar_Get( "build", va( "%i", Q_buildnum()), FCVAR_READ_ONLY, "returns a current build number" ); - ver = Cvar_Get( "ver", va( "%i/%g (hw build %i)", PROTOCOL_VERSION, XASH_VERSION, Q_buildnum()), FCVAR_READ_ONLY, "shows an engine version" ); + ver = Cvar_Get( "ver", va( "%i/%s (hw build %i)", PROTOCOL_VERSION, XASH_VERSION, Q_buildnum()), FCVAR_READ_ONLY, "shows an engine version" ); Mod_Init(); NET_Init(); diff --git a/engine/common/imagelib/img_dds.c b/engine/common/imagelib/img_dds.c index 5f945b08..24f2e124 100644 --- a/engine/common/imagelib/img_dds.c +++ b/engine/common/imagelib/img_dds.c @@ -117,6 +117,9 @@ void Image_DXTGetPixelFormat( dds_t *hdr ) case TYPE_DXT5: image.type = PF_DXT5; break; + case TYPE_ATI2: + image.type = PF_ATI2; + break; default: image.type = PF_UNKNOWN; // assume error break; @@ -157,7 +160,8 @@ size_t Image_DXTGetLinearSize( int type, int width, int height, int depth ) { case PF_DXT1: return ((( width + 3 ) / 4 ) * (( height + 3 ) / 4 ) * depth * 8 ); case PF_DXT3: - case PF_DXT5: return ((( width + 3 ) / 4 ) * (( height + 3 ) / 4 ) * depth * 16 ); + case PF_DXT5: + case PF_ATI2: return ((( width + 3 ) / 4 ) * (( height + 3 ) / 4 ) * depth * 16 ); case PF_BGR_24: case PF_RGB_24: return (width * height * depth * 3); case PF_BGRA_32: @@ -214,7 +218,8 @@ uint Image_DXTCalcSize( const char *name, dds_t *hdr, size_t filesize ) if( filesize != buffsize ) // main check { MsgDev( D_WARN, "Image_LoadDDS: (%s) probably corrupted(%i should be %i)\n", name, buffsize, filesize ); - return false; + if( buffsize > filesize ) + return false; } return buffsize; @@ -274,7 +279,7 @@ qboolean Image_LoadDDS( const char *name, const byte *buffer, size_t filesize ) Image_DXTGetPixelFormat( &header ); // and image type too :) Image_DXTAdjustVolume( &header ); - if( !Image_CheckFlag( IL_DDS_HARDWARE ) && ( image.type == PF_DXT1 || image.type == PF_DXT3 || image.type == PF_DXT5 )) + if( !Image_CheckFlag( IL_DDS_HARDWARE ) && ImageDXT( image.type )) return false; // silently rejected if( image.type == PF_UNKNOWN ) @@ -324,7 +329,7 @@ qboolean Image_LoadDDS( const char *name, const byte *buffer, size_t filesize ) // dds files will be uncompressed on a render. requires minimal of info for set this image.rgba = Mem_Malloc( host.imagepool, image.size ); memcpy( image.rgba, fin, image.size ); - image.flags |= IMAGE_DDS_FORMAT; + SetBits( image.flags, IMAGE_DDS_FORMAT ); return true; } \ No newline at end of file diff --git a/engine/common/imagelib/img_main.c b/engine/common/imagelib/img_main.c index d8cc6b3c..7a80bbe9 100644 --- a/engine/common/imagelib/img_main.c +++ b/engine/common/imagelib/img_main.c @@ -93,6 +93,7 @@ const bpc_desc_t PFDesc[] = {PF_DXT1, "DXT 1", 0x83F1, 4 }, {PF_DXT3, "DXT 3", 0x83F2, 4 }, {PF_DXT5, "DXT 5", 0x83F3, 4 }, +{PF_ATI2, "ATI 2", 0x8837, 4 }, }; void Image_Reset( void ) diff --git a/engine/common/netchan.h b/engine/common/netchan.h index 0e2b7d1c..8db97a49 100644 --- a/engine/common/netchan.h +++ b/engine/common/netchan.h @@ -69,6 +69,7 @@ GNU General Public License for more details. #define NET_MAX_MESSAGE PAD_NUMBER(( NET_MAX_PAYLOAD + HEADER_BYTES ), 16 ) #define MASTERSERVER_ADR "ms.xash.su:27010" +#define MS_SCAN_REQUEST "1\xFF" "0.0.0.0:0\0" #define PORT_MASTER 27010 #define PORT_CLIENT 27005 #define PORT_SERVER 27015 diff --git a/engine/common/protocol.h b/engine/common/protocol.h index 5e8adc99..f6791b8a 100644 --- a/engine/common/protocol.h +++ b/engine/common/protocol.h @@ -73,7 +73,7 @@ GNU General Public License for more details. #define svc_director 51 // #define svc_voiceinit 52 // #define svc_voicedata 53 // [byte][short][...] -// reserved +#define svc_deltapacketbones 54 // [short][byte][...] // reserved #define svc_resourcelocation 56 // [string] #define svc_querycvarvalue 57 // [string] diff --git a/engine/common/sys_con.c b/engine/common/sys_con.c index 8ce9c7ac..1794de66 100644 --- a/engine/common/sys_con.c +++ b/engine/common/sys_con.c @@ -290,7 +290,7 @@ void Con_CreateConsole( void ) rect.top = 0; rect.bottom = 364; Q_strncpy( FontName, "Fixedsys", sizeof( FontName )); - Q_strncpy( s_wcd.title, va( "Xash3D %g", XASH_VERSION ), sizeof( s_wcd.title )); + Q_strncpy( s_wcd.title, va( "Xash3D %s", XASH_VERSION ), sizeof( s_wcd.title )); Q_strncpy( s_wcd.log_path, "engine.log", sizeof( s_wcd.log_path )); fontsize = 8; } diff --git a/engine/server/sv_game.c b/engine/server/sv_game.c index f7e43e32..65f2a753 100644 --- a/engine/server/sv_game.c +++ b/engine/server/sv_game.c @@ -1194,24 +1194,29 @@ pfnSetModel */ void pfnSetModel( edict_t *e, const char *m ) { + char name[MAX_QPATH]; model_t *mod; int i; if( !SV_IsValidEdict( e )) return; - if( COM_CheckString( m )) + if( *m == '\\' || *m == '/' ) m++; + Q_strncpy( name, m, sizeof( name )); + COM_FixSlashes( name ); + + if( COM_CheckString( name )) { // check to see if model was properly precached for( i = 1; i < MAX_MODELS && sv.model_precache[i][0]; i++ ) { - if( !Q_stricmp( sv.model_precache[i], m )) + if( !Q_stricmp( sv.model_precache[i], name )) break; } if( i == MAX_MODELS ) { - Con_Printf( S_ERROR "no precache: %s\n", m ); + Con_Printf( S_ERROR "no precache: %s\n", name ); return; } } @@ -1223,7 +1228,7 @@ void pfnSetModel( edict_t *e, const char *m ) return; } - if( COM_CheckString( m )) + if( COM_CheckString( name )) { e->v.model = MAKE_STRING( sv.model_precache[i] ); e->v.modelindex = i; @@ -1250,18 +1255,23 @@ pfnModelIndex */ int pfnModelIndex( const char *m ) { + char name[MAX_QPATH]; int i; if( !COM_CheckString( m )) return 0; + if( *m == '\\' || *m == '/' ) m++; + Q_strncpy( name, m, sizeof( name )); + COM_FixSlashes( name ); + for( i = 1; i < MAX_MODELS && sv.model_precache[i][0]; i++ ) { - if( !Q_stricmp( sv.model_precache[i], m )) + if( !Q_stricmp( sv.model_precache[i], name )) return i; } - Con_Printf( S_ERROR "no precache: %s\n", m ); + Con_Printf( S_ERROR "no precache: %s\n", name ); return 0; } diff --git a/engine/server/sv_log.c b/engine/server/sv_log.c index 4fc10e3f..75df3332 100644 --- a/engine/server/sv_log.c +++ b/engine/server/sv_log.c @@ -73,7 +73,7 @@ void Log_Open( void ) } if( fp ) svs.log.file = fp; - Log_Printf( "Log file started (file \"%s\") (game \"%s\") (version \"%i/%.2f/%d\")\n", + Log_Printf( "Log file started (file \"%s\") (game \"%s\") (version \"%i/%s/%d\")\n", szTestFile, Info_ValueForKey( SV_Serverinfo(), "*gamedir" ), PROTOCOL_VERSION, XASH_VERSION, Q_buildnum() ); } diff --git a/engine/server/sv_main.c b/engine/server/sv_main.c index bf318681..06513fbd 100644 --- a/engine/server/sv_main.c +++ b/engine/server/sv_main.c @@ -739,7 +739,7 @@ void SV_AddToMaster( netadr_t from, sizebuf_t *msg ) Info_SetValueForKey( s, "os", "w", len ); // Windows Info_SetValueForKey( s, "secure", "0", len ); // server anti-cheat Info_SetValueForKey( s, "lan", "0", len ); // LAN servers doesn't send info to master - Info_SetValueForKey( s, "version", va( "%g", XASH_VERSION ), len ); // server region. 255 -- all regions + Info_SetValueForKey( s, "version", va( "%s", XASH_VERSION ), len ); // server region. 255 -- all regions Info_SetValueForKey( s, "region", "255", len ); // server region. 255 -- all regions Info_SetValueForKey( s, "product", GI->gamefolder, len ); // product? Where is the difference with gamedir? @@ -853,7 +853,7 @@ void SV_Init( void ) MSG_Init( &net_message, "NetMessage", net_message_buffer, sizeof( net_message_buffer )); - Q_snprintf( versionString, sizeof( versionString ), "%s: %.2f,%i,%i", "Xash3D", XASH_VERSION, PROTOCOL_VERSION, Q_buildnum() ); + Q_snprintf( versionString, sizeof( versionString ), "%s: %s,%i,%i", "Xash3D", XASH_VERSION, PROTOCOL_VERSION, Q_buildnum() ); Cvar_FullSet( "sv_version", versionString, FCVAR_READ_ONLY ); SV_ClearGameState (); // delete all temporary *.hl files