Compare commits

...

59 Commits

Author SHA1 Message Date
Alibek Omarov
5d9bc950ce wscript: do not load msvc manually, it will be loaded by compiler_{c,cxx} 2024-05-25 22:40:25 +03:00
Alibek Omarov
714da79395 mainui: update 2024-05-25 22:25:33 +03:00
Alibek Omarov
823fe9ebbd waf: upgrade to waf 2.1.1/waifu 1.3.0. Try to fix most optparse->argparse migration issues 2024-05-25 04:58:28 +03:00
Alibek Omarov
4bf72b5383 engine: forbid accessing cvars starting with con_ and scr_ through stufftext
Some stupid servers might mess up with console cvars values.
2024-05-25 02:26:42 +03:00
Alibek Omarov
51945f002b engine: server: check for invoker entity when filtering out host client during entities thinking 2024-05-23 02:06:54 +03:00
Alibek Omarov
bcca9387de engine: server: sv_pmove: always set FEV_NOTHOST for events coming from PMove (like GoldSrc) 2024-05-23 01:51:42 +03:00
Alibek Omarov
b8417fa46d ref: soft: search parent in both entity lists when drawing MOVETYPE_FOLLOW entities
Fixes the issue in Brutal Half-Life beta 2 with invisible scientist skin.

Fixes: 6862b14e59 ("ref: soft: only draw MOVETYPE_FOLLOW studio model if it's parent is visible")
2024-05-19 06:31:46 +03:00
Alibek Omarov
85b0699288 ref: gl: search parent in both entity lists when drawing MOVETYPE_FOLLOW entities
Fixes the issue in Brutal Half-Life beta 2 with invisible scientist skin.

Fixes: dc1d65f621 ("ref: gl: only draw MOVETYPE_FOLLOW studio model if it's parent is visible")
2024-05-19 06:29:22 +03:00
Alibek Omarov
6c03fb0226 engine: client: first attempt to use utflib to replace Con_UtfProcessCharForce calls 2024-05-15 05:25:53 +03:00
Alibek Omarov
a084dea07c public: add functions to convert from Unicode codepoints into CP1251 or CP1252 2024-05-15 05:07:18 +03:00
Alibek Omarov
2e0fc3e4c1 engine: client: do not repeatedly check cl_charset value, use generic Con_UtfProcessChar 2024-05-15 05:06:57 +03:00
Alibek Omarov
24f4d410ce filesystem: take FS_Read improvements from DarkPlaces and proper fix for buffer overflow 2024-05-15 03:43:02 +03:00
Alibek Omarov
052e0445ab engine: client: console: cleanup input buffer from line feed characters before pushing it to the console history 2024-05-15 03:08:22 +03:00
Alibek Omarov
758c908d5a public: add buffer size parameter to COM_RemoveLineFeed 2024-05-15 03:06:57 +03:00
Alibek Omarov
3917c2589d filesystem: fix buffer overflow in FS_Read when we pass single byte buffer to it with one character sitting in ungetc 2024-05-15 02:45:01 +03:00
Alibek Omarov
f4a77308ec engine: soundlib: fix possible buffer overflow in Sound_ConvertUpsample 2024-05-06 15:45:49 +03:00
Alibek Omarov
103b9724f9 scripts: waifulib: compiler_optimizations: fix linking OpenMP 2024-05-06 15:36:26 +03:00
Alibek Omarov
75a315ecf0 engine: client: add optional (compile time for now) setting to reconfigure engine to use 48kHz sounds 2024-05-06 15:10:34 +03:00
Alibek Omarov
63b3b9ef6d engine: client: fix missing upsampling for >32kHz sounds 2024-05-06 15:09:52 +03:00
Alibek Omarov
a6c2cfe89b engine: avoid constants in Q_strncpy third argument, where possible 2024-05-06 14:27:26 +03:00
Alibek Omarov
5120657386 engine: fix possible buffer overflow in S_StreamGetCurrentState 2024-05-06 06:53:22 +03:00
Alibek Omarov
e754de46d1 engine: client: fix buffer overflow in S_FindName 2024-05-06 06:42:47 +03:00
Alibek Omarov
5d718aa0d6 scripts: waifulib: compiler_optimizations: add flag for building with OpenMP (not used anywhere in the engine but let's keep it) 2024-05-06 06:42:15 +03:00
Alibek Omarov
55fcbc8880 engine: soundlib: implement linear interpolation in Sound_ResampleInternal
* split resampling into three functions
* added resampling using SDL_AudioCVT, it's slow, so isn't enabled by default
2024-05-06 06:41:23 +03:00
Alibek Omarov
e19aa001b2 engine: client: ref_common: slight refactoring, reorder ref_state_t 2024-05-06 01:59:50 +03:00
Alibek Omarov
b447ea9c18 engine: client: remove unused fields in client_static_t 2024-05-06 01:59:14 +03:00
Alibek Omarov
13274655d4 engine: client: sound: slight refactoring, removed unused s_listener.velocity 2024-05-06 01:30:06 +03:00
Alibek Omarov
3723ac60ef engine: client: s_mix: _inline -> static 2024-05-06 00:51:32 +03:00
Alibek Omarov
da578f47f1 engine: client: fix sounds being paused in menu and then blasted all at the same time in multiplayer 2024-05-06 00:41:38 +03:00
Alibek Omarov
433e7de686 engine: clean up unused soundlib flags, set SOUND_LOOPED flag on looped sounds 2024-05-05 06:16:57 +03:00
Alibek Omarov
e18e9ae2ea engine: platform: sdl: ignore keyboard events if text mode is active 2024-05-04 11:05:17 +03:00
Alibek Omarov
27d5123a61 mainui: update 2024-05-03 16:55:17 +03:00
Alibek Omarov
89b9f9ffe2 github: update SDL to 2.30.3 2024-05-03 16:04:13 +03:00
Alibek Omarov
a17b8aaa13 public: fix parameter name omitted error for older compilers 2024-05-03 16:01:24 +03:00
Alibek Omarov
e210969612 scripts: gha: build_linux: spew config.log on build failure 2024-05-03 15:57:26 +03:00
Alibek Omarov
1208356b92 ref: gl: gl2_shim: remove unused ALLOCA_H include 2024-05-03 15:53:57 +03:00
Alibek Omarov
d7cd74fe2f wscript: no need to pass PACKAGING into env 2024-05-03 15:45:20 +03:00
Alibek Omarov
31b63e9939 wscript: exclude executing large file test for PSVita 2024-05-03 15:44:35 +03:00
Alibek Omarov
b99c2c2df1 wscript: do not execute test for test for large files 2024-05-03 15:38:35 +03:00
Alibek Omarov
94d3eff9ce engine: host: fix build with Q_strchrnul returning const char * 2024-05-03 15:31:20 +03:00
Alibek Omarov
b78e9961c6 public: fix build on Windows
stristr doesn't exist actually
2024-05-03 15:30:42 +03:00
Alibek Omarov
b0704ca5d6 mainui: update 2024-05-03 06:38:21 +03:00
Alibek Omarov
31c0934108 engine: fix parsing -bugcomp flags, assume bugcomp flags only starts with alphabetic character 2024-05-03 06:28:48 +03:00
Alibek Omarov
37083c8aef ref: soft: mark sw_drawflat and sw_draworder as cheats 2024-05-01 00:52:45 +03:00
Alibek Omarov
af23b0c67b public: crtlib: refactoring with new macros, use system strlcpy/strlcat if possible 2024-04-30 02:20:14 +03:00
Alibek Omarov
a9e83fb9cf wscript: move std defining macros into libpublic's sdk_includes target, so we don't accidentally feed submodules our macros 2024-04-29 05:29:53 +03:00
Alibek Omarov
51126e1691 mainui: update 2024-04-29 05:28:41 +03:00
Alibek Omarov
dd410a2de5 engine: implement small Message Rewrite Facitility that allows to run mods that directly write internal GoldSrc messages 2024-04-28 06:59:18 +03:00
Alibek Omarov
7ccb0b5c02 public: make simple ctype functions inlined 2024-04-28 06:59:18 +03:00
Alibek Omarov
7f3e62e456 public: remove unneeded copy in Q_atov 2024-04-28 06:59:18 +03:00
Alibek Omarov
fcfc29d7ea public: fix variables types in COM_HashKey, they are all supposed to be unsigned integers 2024-04-28 06:59:18 +03:00
Alibek Omarov
2f3429a144 engine: common: base_cmd: use flexible array to store basecmd name 2024-04-28 06:59:18 +03:00
Alibek Omarov
20782693f4 engine: server: rename symbols for svs, sv and SV_DropClient to avoid AMXModX trying to acquire their pointers 2024-04-28 06:59:18 +03:00
Alibek Omarov
0cfb354374 common: add RENAME_SYMBOL macro that renames symbol for compatibility with nasty mods (also reformat this portion, while we're at it) 2024-04-28 06:59:18 +03:00
Alibek Omarov
9be5b7c6c9 engine: physint: empty-define ALLOC_CHECK if not defined by SDK, so this header can be freely moved to another SDK 2024-04-28 06:59:18 +03:00
Alibek Omarov
e7653d2ea6 engine: soundlib: fix searching for a RIFF/WAVE chunks in streams 2024-04-27 10:51:56 +03:00
Alibek Omarov
1494887e29 engine: soundlib: snd_wav: replace strncmp by IsFourCC helper function 2024-04-26 06:29:38 +03:00
Alibek Omarov
42dab2b1a5 engine: soundlib: snd_wav: attempt to fix misleading warning about truncated file 2024-04-26 06:25:18 +03:00
Alibek Omarov
36a0c1fb17 ref: if the entity is opaque, check the renderfx too, it might become translucent 2024-04-26 04:15:21 +03:00
68 changed files with 1319 additions and 852 deletions

View File

@@ -44,7 +44,7 @@ jobs:
targetos: win32
targetarch: i386
env:
SDL_VERSION: 2.28.5
SDL_VERSION: 2.30.3
GH_CPU_ARCH: ${{ matrix.targetarch }}
steps:
- name: Checkout

View File

@@ -13,3 +13,4 @@ When `-bugcomp` is specified with argument, it interpreted as flags separated wi
| Flag | Description | Games that require this flag |
| ------- | ----------- | ---------------------------- |
| `peoei` | Reverts `pfnPEntityOfEntIndex` behavior to GoldSrc, where it returns NULL for last player due to incorrect player index comparison | * Counter-Strike: Condition Zero - Deleted Scenes |
| `gsmrf` | Rewrites message at the moment when Game DLL attempts to write an internal engine message, usually specific to GoldSrc protocol. Right now only supports `svc_spawnstaticsound`, more messages added by request. | * MetaMod/AMXModX based mods |

View File

@@ -70,48 +70,48 @@ typedef uint64_t longtime_t;
#define IsColorString( p ) ( p && *( p ) == '^' && *(( p ) + 1) && *(( p ) + 1) >= '0' && *(( p ) + 1 ) <= '9' )
#define ColorIndex( c ) ((( c ) - '0' ) & 7 )
#if defined(__GNUC__)
#ifdef __i386__
#define EXPORT __attribute__ ((visibility ("default"),force_align_arg_pointer))
#define GAME_EXPORT __attribute((force_align_arg_pointer))
#if defined( __GNUC__ )
#if defined( __i386__ )
#define EXPORT __attribute__(( visibility( "default" ), force_align_arg_pointer ))
#define GAME_EXPORT __attribute(( force_align_arg_pointer ))
#else
#define EXPORT __attribute__ ((visibility ("default")))
#define EXPORT __attribute__(( visibility ( "default" )))
#define GAME_EXPORT
#endif
#define _format(x) __attribute__((format(printf, x, x+1)))
#define NORETURN __attribute__((noreturn))
#define NONNULL __attribute__((nonnull))
#define ALLOC_CHECK(x) __attribute__((alloc_size(x)))
#elif defined(_MSC_VER)
#define EXPORT __declspec( dllexport )
#define GAME_EXPORT
#define _format(x)
#define NORETURN
#define NONNULL
#define ALLOC_CHECK(x)
#define NORETURN __attribute__(( noreturn ))
#define NONNULL __attribute__(( nonnull ))
#define _format( x ) __attribute__(( format( printf, x, x + 1 )))
#define ALLOC_CHECK( x ) __attribute__(( alloc_size( x )))
#define RENAME_SYMBOL( x ) asm( x )
#else
#define EXPORT
#if defined( _MSC_VER )
#define EXPORT __declspec( dllexport )
#else
#define EXPORT
#endif
#define GAME_EXPORT
#define _format(x)
#define NORETURN
#define NONNULL
#define ALLOC_CHECK(x)
#define _format( x )
#define ALLOC_CHECK( x )
#define RENAME_SYMBOL( x )
#endif
#if ( __GNUC__ >= 3 )
#define unlikely(x) __builtin_expect(x, 0)
#define likely(x) __builtin_expect(x, 1)
#define unlikely( x ) __builtin_expect( x, 0 )
#define likely( x ) __builtin_expect( x, 1 )
#elif defined( __has_builtin )
#if __has_builtin( __builtin_expect )
#define unlikely(x) __builtin_expect(x, 0)
#define likely(x) __builtin_expect(x, 1)
#define unlikely( x ) __builtin_expect( x, 0 )
#define likely( x ) __builtin_expect( x, 1 )
#else
#define unlikely(x) (x)
#define likely(x) (x)
#define unlikely( x ) ( x )
#define likely( x ) ( x )
#endif
#else
#define unlikely(x) (x)
#define likely(x) (x)
#define unlikely( x ) ( x )
#define likely( x ) ( x )
#endif
#if __STDC_VERSION__ >= 202311L || __cplusplus >= 201103L // C23 or C++ static_assert is a keyword

View File

@@ -192,7 +192,7 @@ void CL_RegisterEvent( int lastnum, const char *szEvName, pfnEventHook func )
ev = clgame.events[lastnum];
// NOTE: ev->index will be set later
Q_strncpy( ev->name, szEvName, MAX_QPATH );
Q_strncpy( ev->name, szEvName, sizeof( ev->name ));
ev->func = func;
}

View File

@@ -1877,8 +1877,12 @@ void CL_ParseHLTV( sizebuf_t *msg )
break;
case HLTV_LISTEN:
cls.signon = SIGNONS;
#if 1
MSG_ReadString( msg );
#else
NET_StringToAdr( MSG_ReadString( msg ), &cls.hltv_listen_address );
// NET_JoinGroup( cls.netchan.sock, cls.hltv_listen_address );
NET_JoinGroup( cls.netchan.sock, cls.hltv_listen_address );
#endif
SCR_EndLoadingPlaque();
break;
default:

View File

@@ -194,7 +194,7 @@ static void CL_LegacyPrecacheModel( sizebuf_t *msg )
if( modelIndex < 0 || modelIndex >= MAX_MODELS )
Host_Error( "CL_PrecacheModel: bad modelindex %i\n", modelIndex );
Q_strncpy( model, MSG_ReadString( msg ), MAX_STRING );
Q_strncpy( model, MSG_ReadString( msg ), sizeof( model ));
//Q_strncpy( cl.model_precache[modelIndex], BF_ReadString( msg ), sizeof( cl.model_precache[0] ));
// when we loading map all resources is precached sequentially
@@ -261,7 +261,7 @@ static void CL_LegacyParseResourceList( sizebuf_t *msg )
for( i = 0; i < reslist.rescount; i++ )
{
reslist.restype[i] = MSG_ReadWord( msg );
Q_strncpy( reslist.resnames[i], MSG_ReadString( msg ), MAX_QPATH );
Q_strncpy( reslist.resnames[i], MSG_ReadString( msg ), sizeof( reslist.resnames[i] ));
}
if( CL_IsPlaybackDemo() )

View File

@@ -853,7 +853,7 @@ static void CL_SetupPMove( playermove_t *pmove, const local_state_t *from, const
VectorCopy( cd->vuser4, pmove->vuser4 );
pmove->cmd = *ucmd; // copy current cmds
Q_strncpy( pmove->physinfo, cls.physinfo, MAX_INFO_STRING );
Q_strncpy( pmove->physinfo, cls.physinfo, sizeof( pmove->physinfo ));
}
static const void CL_FinishPMove( const playermove_t *pmove, local_state_t *to )

View File

@@ -211,7 +211,7 @@ static void CL_ParseQuakeServerInfo( sizebuf_t *msg )
clgame.maxEntities = GI->max_edicts;
clgame.maxEntities = bound( 600, clgame.maxEntities, MAX_EDICTS );
clgame.maxModels = MAX_MODELS;
Q_strncpy( clgame.maptitle, MSG_ReadString( msg ), MAX_STRING );
Q_strncpy( clgame.maptitle, MSG_ReadString( msg ), sizeof( clgame.maptitle ));
// Re-init hud video, especially if we changed game directories
clgame.dllFuncs.pfnVidInit();

View File

@@ -539,12 +539,8 @@ typedef struct
poolhandle_t mempool; // client premamnent pool: edicts etc
netadr_t hltv_listen_address;
int signon; // 0 to SIGNONS, for the signon sequence.
int quakePort; // a 16 bit value that allows quake servers
// to work around address translating routers
// g-cont. this port allow many copies of engine in multiplayer game
// connection information
char servername[MAX_QPATH]; // name of server from original connect
double connect_time; // for connection retransmits

View File

@@ -21,6 +21,7 @@ GNU General Public License for more details.
#include "qfont.h"
#include "wadfile.h"
#include "input.h"
#include "utflib.h"
static CVAR_DEFINE_AUTO( scr_conspeed, "600", FCVAR_ARCHIVE, "console moving speed" );
static CVAR_DEFINE_AUTO( con_notifytime, "3", FCVAR_ARCHIVE, "notify time to live" );
@@ -610,19 +611,6 @@ static void Con_LoadConchars( void )
con.curFont = &con.chars[fontSize];
}
// CP1251 table
int table_cp1251[64] = {
0x0402, 0x0403, 0x201A, 0x0453, 0x201E, 0x2026, 0x2020, 0x2021,
0x20AC, 0x2030, 0x0409, 0x2039, 0x040A, 0x040C, 0x040B, 0x040F,
0x0452, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
0x007F, 0x2122, 0x0459, 0x203A, 0x045A, 0x045C, 0x045B, 0x045F,
0x00A0, 0x040E, 0x045E, 0x0408, 0x00A4, 0x0490, 0x00A6, 0x00A7,
0x0401, 0x00A9, 0x0404, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x0407,
0x00B0, 0x00B1, 0x0406, 0x0456, 0x0491, 0x00B5, 0x00B6, 0x00B7,
0x0451, 0x2116, 0x0454, 0x00BB, 0x0458, 0x0405, 0x0455, 0x0457
};
/*
============================
Con_UtfProcessChar
@@ -632,83 +620,24 @@ Convert utf char to current font's single-byte encoding
*/
int Con_UtfProcessCharForce( int in )
{
static int m = -1, k = 0; //multibyte state
static int uc = 0; //unicode char
// TODO: get rid of global state where possible
static utfstate_t state = { 0 };
if( !in )
{
m = -1;
k = 0;
uc = 0;
return 0;
}
int ch = Q_DecodeUTF8( &state, in );
// Get character length
if(m == -1)
{
uc = 0;
if( in >= 0xF8 )
return 0;
else if( in >= 0xF0 )
uc = in & 0x07, m = 3;
else if( in >= 0xE0 )
uc = in & 0x0F, m = 2;
else if( in >= 0xC0 )
uc = in & 0x1F, m = 1;
else if( in <= 0x7F)
return in; //ascii
// return 0 if we need more chars to decode one
k=0;
return 0;
}
// get more chars
else if( k <= m )
{
uc <<= 6;
uc += in & 0x3F;
k++;
}
if( in > 0xBF || m < 0 )
{
m = -1;
return 0;
}
if( k == m )
{
k = m = -1;
if( g_codepage == 1251 )
{
// cp1251 now
if( uc >= 0x0410 && uc <= 0x042F )
return uc - 0x410 + 0xC0;
if( uc >= 0x0430 && uc <= 0x044F )
return uc - 0x430 + 0xE0;
else
{
int i;
for( i = 0; i < 64; i++ )
if( table_cp1251[i] == uc )
return i + 0x80;
}
}
else if( g_codepage == 1252 )
{
if( uc < 255 )
return uc;
}
if( g_codepage == 1251 )
return Q_UnicodeToCP1251( ch );
if( g_codepage == 1252 )
return Q_UnicodeToCP1252( ch );
// not implemented yet
return '?';
}
return 0;
return '?'; // not implemented yet
}
int GAME_EXPORT Con_UtfProcessChar( int in )
{
if( !g_utf8 )
return in;
else
return Con_UtfProcessCharForce( in );
return Con_UtfProcessCharForce( in );
}
/*
=================
@@ -719,16 +648,22 @@ get position of previous printful char
*/
int Con_UtfMoveLeft( char *str, int pos )
{
int i, k = 0;
// int j;
utfstate_t state = { 0 };
int k = 0;
int i;
if( !g_utf8 )
return pos - 1;
Con_UtfProcessChar( 0 );
if(pos == 1) return 0;
for( i = 0; i < pos-1; i++ )
if( Con_UtfProcessChar( (unsigned char)str[i] ) )
k = i+1;
Con_UtfProcessChar( 0 );
if( pos == 1 )
return 0;
for( i = 0; i < pos - 1; i++ )
{
if( Q_DecodeUTF8( &state, (byte)str[i] ))
k = i + 1;
}
return k;
}
@@ -741,17 +676,19 @@ get next of previous printful char
*/
int Con_UtfMoveRight( char *str, int pos, int length )
{
utfstate_t state = { 0 };
int i;
if( !g_utf8 )
return pos + 1;
Con_UtfProcessChar( 0 );
for( i = pos; i <= length; i++ )
{
if( Con_UtfProcessChar( (unsigned char)str[i] ) )
return i+1;
if( Q_DecodeUTF8( &state, (byte)str[i] ))
return i + 1;
}
Con_UtfProcessChar( 0 );
return pos+1;
return pos + 1;
}
static void Con_DrawCharToConback( int num, const byte *conchars, byte *dest )
@@ -1138,7 +1075,7 @@ Field_Set
static void Field_Set( field_t *f, const char *string )
{
f->scroll = 0;
f->cursor = Q_strncpy( f->buffer, string, MAX_STRING );
f->cursor = Q_strncpy( f->buffer, string, sizeof( f->buffer ));
}
/*
@@ -1549,6 +1486,9 @@ void Key_Console( int key )
Con_Printf( ">%s\n", con.input.buffer );
// copy line to history buffer
// just in case, remove all CR and LF characters pushing it to the history
// not sure how they get even added in the first place
COM_RemoveLineFeed( con.input.buffer, sizeof( con.input.buffer ));
Con_HistoryAppend( &con.history, &con.input );
Con_ClearField( &con.input );

View File

@@ -1055,10 +1055,7 @@ static qboolean OSK_KeyEvent( int key, int down )
break;
}
if( !Q_stricmp( cl_charset.string, "utf-8" ) )
ch = (unsigned char)osk.curbutton.val;
else
ch = Con_UtfProcessCharForce( (unsigned char)osk.curbutton.val );
ch = Con_UtfProcessChar((byte)osk.curbutton.val );
if( !ch )
break;

View File

@@ -18,19 +18,18 @@ GNU General Public License for more details.
#include "ref_api.h"
#define RP_LOCALCLIENT( e ) ((e) != NULL && (e)->index == ( cl.playernum + 1 ) && e->player )
#define RP_LOCALCLIENT( e ) ((e) != NULL && (e)->index == ( cl.playernum + 1 ) && e->player )
struct ref_state_s
{
qboolean initialized;
HINSTANCE hInstance;
HINSTANCE hInstance;
qboolean initialized;
int numRenderers;
ref_interface_t dllFuncs;
// depends on build configuration
int numRenderers;
const char **shortNames;
const char **readableNames;
const char **shortNames;
const char **readableNames;
};
extern struct ref_state_s ref;
@@ -46,8 +45,8 @@ void R_GetTextureParms( int *w, int *h, int texnum );
void GL_RenderFrame( const struct ref_viewpass_s *rvp );
// common engine and renderer cvars
extern convar_t r_decals;
extern convar_t r_adjust_fov;
extern convar_t r_decals;
extern convar_t r_adjust_fov;
extern convar_t gl_clear;
qboolean R_Init( void );

View File

@@ -52,8 +52,11 @@ void S_SoundList_f( void )
{
totalSize += sc->size;
if( sc->loopStart >= 0 ) Con_Printf( "L" );
else Con_Printf( " " );
if( FBitSet( sc->flags, SOUND_LOOPED ))
Con_Printf( "L" );
else
Con_Printf( " " );
if( sfx->name[0] == '*' || !Q_strncmp( sfx->name, DEFAULT_SOUNDPATH, sizeof( DEFAULT_SOUNDPATH ) - 1 ))
Con_Printf( " (%2db) %s : %s\n", sc->width * 8, Q_memprint( sc->size ), sfx->name );
else Con_Printf( " (%2db) %s : " DEFAULT_SOUNDPATH "%s\n", sc->width * 8, Q_memprint( sc->size ), sfx->name );
@@ -110,7 +113,7 @@ static wavdata_t *S_CreateDefaultSound( void )
sc->width = 2;
sc->channels = 1;
sc->loopStart = -1;
sc->loopStart = 0;
sc->rate = SOUND_DMA_SPEED;
sc->samples = SOUND_DMA_SPEED;
sc->size = sc->samples * sc->width * sc->channels;
@@ -155,7 +158,7 @@ wavdata_t *S_LoadSound( sfx_t *sfx )
Sound_Process( &sc, SOUND_11k, sc->width, SOUND_RESAMPLE );
else if( sc->rate > SOUND_11k && sc->rate < SOUND_22k ) // some bad sounds
Sound_Process( &sc, SOUND_22k, sc->width, SOUND_RESAMPLE );
else if( sc->rate > SOUND_22k && sc->rate <= SOUND_32k ) // some bad sounds
else if( sc->rate > SOUND_22k && sc->rate < SOUND_44k ) // some bad sounds
Sound_Process( &sc, SOUND_44k, sc->width, SOUND_RESAMPLE );
sfx->cache = sc;
@@ -218,7 +221,7 @@ sfx_t *S_FindName( const char *pname, int *pfInCache )
sfx = &s_knownSfx[i];
memset( sfx, 0, sizeof( *sfx ));
if( pfInCache ) *pfInCache = false;
Q_strncpy( sfx->name, name, MAX_STRING );
Q_strncpy( sfx->name, name, sizeof( sfx->name ));
sfx->servercount = cl.servercount;
sfx->hashValue = COM_HashKey( sfx->name, MAX_SFX_HASH );
@@ -377,7 +380,7 @@ S_InitSounds
void S_InitSounds( void )
{
// create unused 0-entry
Q_strncpy( s_knownSfx->name, "*default", MAX_QPATH );
Q_strncpy( s_knownSfx->name, "*default", sizeof( s_knownSfx->name ));
s_knownSfx->hashValue = COM_HashKey( s_knownSfx->name, MAX_SFX_HASH );
s_knownSfx->hashNext = s_sfxHashList[s_knownSfx->hashValue];
s_sfxHashList[s_knownSfx->hashValue] = s_knownSfx;

View File

@@ -70,6 +70,12 @@ float S_GetMasterVolume( void )
return 0.0f;
}
if( s_listener.inmenu && !ui_renderworld.value && !Host_IsLocalGame( ))
{
// mute sounds in menu when it's not transparent and we're in multiplayer
return 0.0f;
}
if( !s_listener.inmenu && soundfade.percent != 0 )
{
scale = bound( 0.0f, soundfade.percent / 100.0f, 1.0f );
@@ -328,7 +334,7 @@ channel_t *SND_PickDynamicChannel( int entnum, int channel, sfx_t *sfx, qboolean
// don't restart looping sounds for the same entity
wavdata_t *sc = channels[first_to_die].sfx->cache;
if( sc && sc->loopStart != -1 )
if( sc && FBitSet( sc->flags, SOUND_LOOPED ))
{
channel_t *ch = &channels[first_to_die];
@@ -503,7 +509,7 @@ static void SND_Spatialize( channel_t *ch )
pSource = ch->sfx->cache;
if( ch->use_loop && pSource && pSource->loopStart != -1 )
if( ch->use_loop && pSource && FBitSet( pSource->flags, SOUND_LOOPED ))
looping = true;
if( !ch->staticsound )
@@ -641,7 +647,7 @@ void S_StartSound( const vec3_t pos, int ent, int chan, sound_t handle, float fv
if( !target_chan->leftvol && !target_chan->rightvol )
{
// looping sounds don't use this optimization because they should stick around until they're killed.
if( !sfx->cache || sfx->cache->loopStart == -1 )
if( !sfx->cache || !FBitSet( sfx->cache->flags, SOUND_LOOPED ))
{
// if this is a streaming sound, play the whole thing.
if( chan != CHAN_STREAM )
@@ -893,7 +899,7 @@ int S_GetCurrentStaticSounds( soundlist_t *pout, int size )
VectorCopy( channels[i].origin, pout->origin );
pout->volume = (float)channels[i].master_vol / 255.0f;
pout->attenuation = channels[i].dist_mult * SND_CLIP_DISTANCE;
pout->looping = ( channels[i].use_loop && channels[i].sfx->cache->loopStart != -1 );
pout->looping = ( channels[i].use_loop && FBitSet( channels[i].sfx->cache->flags, SOUND_LOOPED ));
pout->pitch = channels[i].basePitch;
pout->channel = channels[i].entchannel;
pout->wordIndex = channels[i].wordIndex;
@@ -928,7 +934,7 @@ int S_GetCurrentDynamicSounds( soundlist_t *pout, int size )
if( !channels[i].sfx || !channels[i].sfx->name[0] || !Q_stricmp( channels[i].sfx->name, "*default" ))
continue; // don't serialize default sounds
looped = ( channels[i].use_loop && channels[i].sfx->cache->loopStart != -1 );
looped = ( channels[i].use_loop && FBitSet( channels[i].sfx->cache->flags, SOUND_LOOPED ));
if( channels[i].entchannel == CHAN_STATIC && looped && !Host_IsQuakeCompatible())
continue; // never serialize static looped sounds. It will be restoring in game code
@@ -1599,7 +1605,6 @@ void SND_UpdateSound( void )
// release raw-channels that no longer used more than 10 secs
S_FreeIdleRawChannels();
VectorCopy( cl.simvel, s_listener.velocity );
s_listener.frametime = (cl.time - cl.oldtime);
s_listener.waterlevel = cl.local.waterlevel;
s_listener.active = CL_IsInGame();

View File

@@ -17,30 +17,56 @@ GNU General Public License for more details.
#include "sound.h"
#include "client.h"
#define IPAINTBUFFER 0
#define IROOMBUFFER 1
#define ISTREAMBUFFER 2
enum
{
IPAINTBUFFER = 0,
IROOMBUFFER,
ISTREAMBUFFER,
CPAINTBUFFERS,
};
#define FILTERTYPE_NONE 0
#define FILTERTYPE_LINEAR 1
#define FILTERTYPE_CUBIC 2
enum
{
FILTERTYPE_NONE = 0,
FILTERTYPE_LINEAR,
FILTERTYPE_CUBIC,
};
#define CCHANVOLUMES 2
#define SND_SCALE_BITS 7
#define SND_SCALE_SHIFT (8 - SND_SCALE_BITS)
#define SND_SCALE_LEVELS (1 << SND_SCALE_BITS)
#define SND_SCALE_BITS 7
#define SND_SCALE_SHIFT ( 8 - SND_SCALE_BITS )
#define SND_SCALE_LEVELS ( 1 << SND_SCALE_BITS )
portable_samplepair_t *g_curpaintbuffer;
portable_samplepair_t streambuffer[(PAINTBUFFER_SIZE+1)];
portable_samplepair_t paintbuffer[(PAINTBUFFER_SIZE+1)];
portable_samplepair_t roombuffer[(PAINTBUFFER_SIZE+1)];
portable_samplepair_t facingbuffer[(PAINTBUFFER_SIZE+1)];
portable_samplepair_t temppaintbuffer[(PAINTBUFFER_SIZE+1)];
paintbuffer_t paintbuffers[CPAINTBUFFERS];
// sound mixing buffer
#define CPAINTFILTERMEM 3
#define CPAINTFILTERS 4 // maximum number of consecutive upsample passes per paintbuffer
int snd_scaletable[SND_SCALE_LEVELS][256];
// fixed point stuff for real-time resampling
#define FIX_BITS 28
#define FIX_SCALE ( 1 << FIX_BITS )
#define FIX_MASK (( 1 << FIX_BITS ) - 1 )
#define FIX_FLOAT( a ) ((int)(( a ) * FIX_SCALE ))
#define FIX( a ) (((int)( a )) << FIX_BITS )
#define FIX_INTPART( a ) (((int)( a )) >> FIX_BITS )
#define FIX_FRACPART( a ) (( a ) & FIX_MASK )
typedef struct
{
qboolean factive; // if true, mix to this paintbuffer using flags
portable_samplepair_t *pbuf; // front stereo mix buffer, for 2 or 4 channel mixing
int ifilter; // current filter memory buffer to use for upsampling pass
portable_samplepair_t fltmem[CPAINTFILTERS][CPAINTFILTERMEM];
} paintbuffer_t;
static portable_samplepair_t *g_curpaintbuffer;
static portable_samplepair_t streambuffer[(PAINTBUFFER_SIZE+1)];
static portable_samplepair_t paintbuffer[(PAINTBUFFER_SIZE+1)];
static portable_samplepair_t roombuffer[(PAINTBUFFER_SIZE+1)];
static portable_samplepair_t temppaintbuffer[(PAINTBUFFER_SIZE+1)];
static paintbuffer_t paintbuffers[CPAINTBUFFERS];
static int snd_scaletable[SND_SCALE_LEVELS][256];
void S_InitScaletable( void )
{
int i, j;
@@ -67,7 +93,7 @@ static void S_TransferPaintBuffer( int endtime )
dword *pbuf;
pbuf = (dword *)dma.buffer;
snd_p = (int *)PAINTBUFFER;
snd_p = (int *)g_curpaintbuffer;
lpaintedtime = paintedtime;
sampleMask = ((dma.samples >> 1) - 1);
@@ -111,20 +137,20 @@ static void S_TransferPaintBuffer( int endtime )
//===============================================================================
// Activate a paintbuffer. All active paintbuffers are mixed in parallel within
// MIX_MixChannelsToPaintbuffer, according to flags
_inline void MIX_ActivatePaintbuffer( int ipaintbuffer )
static void MIX_ActivatePaintbuffer( int ipaintbuffer )
{
Assert( ipaintbuffer < CPAINTBUFFERS );
paintbuffers[ipaintbuffer].factive = true;
}
_inline void MIX_SetCurrentPaintbuffer( int ipaintbuffer )
static void MIX_SetCurrentPaintbuffer( int ipaintbuffer )
{
Assert( ipaintbuffer < CPAINTBUFFERS );
g_curpaintbuffer = paintbuffers[ipaintbuffer].pbuf;
Assert( g_curpaintbuffer != NULL );
}
_inline int MIX_GetCurrentPaintbufferIndex( void )
static int MIX_GetCurrentPaintbufferIndex( void )
{
int i;
@@ -136,7 +162,7 @@ _inline int MIX_GetCurrentPaintbufferIndex( void )
return 0;
}
_inline paintbuffer_t *MIX_GetCurrentPaintbufferPtr( void )
static paintbuffer_t *MIX_GetCurrentPaintbufferPtr( void )
{
int ipaint = MIX_GetCurrentPaintbufferIndex();
@@ -145,7 +171,7 @@ _inline paintbuffer_t *MIX_GetCurrentPaintbufferPtr( void )
}
// Don't mix into any paintbuffers
_inline void MIX_DeactivateAllPaintbuffers( void )
static void MIX_DeactivateAllPaintbuffers( void )
{
int i;
@@ -154,7 +180,7 @@ _inline void MIX_DeactivateAllPaintbuffers( void )
}
// set upsampling filter indexes back to 0
_inline void MIX_ResetPaintbufferFilterCounters( void )
static void MIX_ResetPaintbufferFilterCounters( void )
{
int i;
@@ -163,13 +189,13 @@ _inline void MIX_ResetPaintbufferFilterCounters( void )
}
// return pointer to front paintbuffer pbuf, given index
_inline portable_samplepair_t *MIX_GetPFrontFromIPaint( int ipaintbuffer )
static portable_samplepair_t *MIX_GetPFrontFromIPaint( int ipaintbuffer )
{
Assert( ipaintbuffer < CPAINTBUFFERS );
return paintbuffers[ipaintbuffer].pbuf;
}
_inline paintbuffer_t *MIX_GetPPaintFromIPaint( int ipaint )
static paintbuffer_t *MIX_GetPPaintFromIPaint( int ipaint )
{
Assert( ipaint < CPAINTBUFFERS );
return &paintbuffers[ipaint];
@@ -523,6 +549,7 @@ static void MIX_MixChannelsToPaintbuffer( int endtime, int rate, int outputRate
wavdata_t *pSource;
int i, sampleCount;
qboolean bZeroVolume;
qboolean local = Host_IsLocalGame();
// mix each channel into paintbuffer
ch = channels;
@@ -549,7 +576,7 @@ static void MIX_MixChannelsToPaintbuffer( int endtime, int rate, int outputRate
{
// play, playvol
}
else if(( s_listener.inmenu || s_listener.paused ) && !ch->localsound )
else if(( s_listener.inmenu || s_listener.paused ) && !ch->localsound && local )
{
// play only local sounds, keep pause for other
continue;
@@ -567,6 +594,7 @@ static void MIX_MixChannelsToPaintbuffer( int endtime, int rate, int outputRate
// Don't mix sound data for sounds with zero volume. If it's a non-looping sound,
// just remove the sound when its volume goes to zero.
bZeroVolume = !ch->leftvol && !ch->rightvol;
if( !bZeroVolume )
@@ -576,7 +604,7 @@ static void MIX_MixChannelsToPaintbuffer( int endtime, int rate, int outputRate
bZeroVolume = true;
}
if( !pSource || ( bZeroVolume && pSource->loopStart == -1 ))
if( !pSource || ( bZeroVolume && !FBitSet( pSource->flags, SOUND_LOOPED )))
{
if( !pSource )
{
@@ -629,7 +657,7 @@ static void MIX_MixChannelsToPaintbuffer( int endtime, int rate, int outputRate
}
// pass in index -1...count+2, return pointer to source sample in either paintbuffer or delay buffer
_inline portable_samplepair_t *S_GetNextpFilter( int i, portable_samplepair_t *pbuffer, portable_samplepair_t *pfiltermem )
static portable_samplepair_t *S_GetNextpFilter( int i, portable_samplepair_t *pbuffer, portable_samplepair_t *pfiltermem )
{
// The delay buffer is assumed to precede the paintbuffer by 6 duplicated samples
if( i == -1 ) return (&(pfiltermem[0]));
@@ -838,6 +866,14 @@ static void MIX_MixPaintbuffers( int ibuf1, int ibuf2, int ibuf3, int count, flo
pbuf2 = paintbuffers[ibuf2].pbuf;
pbuf3 = paintbuffers[ibuf3].pbuf;
if( !gain )
{
// do not mix buf2 into buf3, just copy
if( pbuf1 != pbuf3 )
memcpy( pbuf3, pbuf1, sizeof( *pbuf1 ) * count );
return;
}
// destination buffer stereo - average n chans down to stereo
// destination 2ch:

View File

@@ -142,7 +142,7 @@ S_StreamGetCurrentState
save\restore code
=================
*/
qboolean S_StreamGetCurrentState( char *currentTrack, char *loopTrack, int *position )
qboolean S_StreamGetCurrentState( char *currentTrack, size_t currentTrackSize, char *loopTrack, size_t loopTrackSize, int *position )
{
if( !s_bgTrack.stream )
return false; // not active
@@ -150,15 +150,15 @@ qboolean S_StreamGetCurrentState( char *currentTrack, char *loopTrack, int *posi
if( currentTrack )
{
if( s_bgTrack.current[0] )
Q_strncpy( currentTrack, s_bgTrack.current, MAX_STRING );
else Q_strncpy( currentTrack, "*", MAX_STRING ); // no track
Q_strncpy( currentTrack, s_bgTrack.current, currentTrackSize );
else Q_strncpy( currentTrack, "*", currentTrackSize ); // no track
}
if( loopTrack )
{
if( s_bgTrack.loopName[0] )
Q_strncpy( loopTrack, s_bgTrack.loopName, MAX_STRING );
else Q_strncpy( loopTrack, "*", MAX_STRING ); // no track
Q_strncpy( loopTrack, s_bgTrack.loopName, loopTrackSize );
else Q_strncpy( loopTrack, "*", loopTrackSize ); // no track
}
if( position )

View File

@@ -27,7 +27,7 @@ int S_ConvertLoopedPosition( wavdata_t *pSource, int samplePosition, qboolean us
// convert to a position within the loop
// At the end of the loop, we return a short buffer, and subsequent call
// will loop back and get the rest of the buffer
if( pSource->loopStart >= 0 && samplePosition >= pSource->samples && use_loop )
if( FBitSet( pSource->flags, SOUND_LOOPED ) && samplePosition >= pSource->samples && use_loop )
{
// size of loop
int loopSize = pSource->samples - pSource->loopStart;

View File

@@ -20,206 +20,178 @@ extern poolhandle_t sndpool;
#include "xash3d_mathlib.h"
// sound engine rate defines
#define SOUND_DMA_SPEED 44100 // hardware playback rate
#define SOUND_11k 11025 // 11khz sample rate
#define SOUND_16k 16000 // 16khz sample rate
#define SOUND_22k 22050 // 22khz sample rate
#define SOUND_32k 32000 // 32khz sample rate
#define SOUND_44k 44100 // 44khz sample rate
#define DMA_MSEC_PER_SAMPLE ((float)(1000.0 / SOUND_DMA_SPEED))
#define XASH_AUDIO_CD_QUALITY 1 // some platforms might need this
// fixed point stuff for real-time resampling
#define FIX_BITS 28
#define FIX_SCALE (1 << FIX_BITS)
#define FIX_MASK ((1 << FIX_BITS)-1)
#define FIX_FLOAT(a) ((int)((a) * FIX_SCALE))
#define FIX(a) (((int)(a)) << FIX_BITS)
#define FIX_INTPART(a) (((int)(a)) >> FIX_BITS)
#define FIX_FRACTION(a,b) (FIX(a)/(b))
#define FIX_FRACPART(a) ((a) & FIX_MASK)
// sound engine rate defines
#if XASH_AUDIO_CD_QUALITY
#define SOUND_11k 11025 // 11khz sample rate
#define SOUND_22k 22050 // 22khz sample rate
#define SOUND_44k 44100 // 44khz sample rate
#else // XASH_AUDIO_CD_QUALITY
#define SOUND_11k 12000 // 11khz sample rate
#define SOUND_22k 24000 // 22khz sample rate
#define SOUND_44k 48000 // 44khz sample rate
#endif // XASH_AUDIO_CD_QUALITY
#define SOUND_DMA_SPEED SOUND_44k // hardware playback rate
// NOTE: clipped sound at 32760 to avoid overload
#define CLIP( x ) (( x ) > 32760 ? 32760 : (( x ) < -32760 ? -32760 : ( x )))
#define CLIP( x ) (( x ) > 32760 ? 32760 : (( x ) < -32760 ? -32760 : ( x )))
#define PAINTBUFFER_SIZE 1024 // 44k: was 512
#define PAINTBUFFER (g_curpaintbuffer)
#define CPAINTBUFFERS 3
#define PAINTBUFFER_SIZE 1024 // 44k: was 512
// sound mixing buffer
#define CPAINTFILTERMEM 3
#define CPAINTFILTERS 4 // maximum number of consecutive upsample passes per paintbuffer
#define S_RAW_SOUND_IDLE_SEC 10 // time interval for idling raw sound before it's freed
#define S_RAW_SOUND_BACKGROUNDTRACK -2
#define S_RAW_SOUND_SOUNDTRACK -1
#define S_RAW_SAMPLES_PRECISION_BITS 14
#define CIN_FRAMETIME (1.0f / 30.0f)
#define S_RAW_SOUND_IDLE_SEC 10 // time interval for idling raw sound before it's freed
#define S_RAW_SOUND_BACKGROUNDTRACK -2
#define S_RAW_SOUND_SOUNDTRACK -1
#define S_RAW_SAMPLES_PRECISION_BITS 14
typedef struct
{
int left;
int right;
int left;
int right;
} portable_samplepair_t;
typedef struct
{
qboolean factive; // if true, mix to this paintbuffer using flags
portable_samplepair_t *pbuf; // front stereo mix buffer, for 2 or 4 channel mixing
int ifilter; // current filter memory buffer to use for upsampling pass
portable_samplepair_t fltmem[CPAINTFILTERS][CPAINTFILTERMEM];
} paintbuffer_t;
typedef struct sfx_s
{
char name[MAX_QPATH];
wavdata_t *cache;
char name[MAX_QPATH];
wavdata_t *cache;
int servercount;
uint hashValue;
struct sfx_s *hashNext;
int servercount;
uint hashValue;
struct sfx_s *hashNext;
} sfx_t;
extern portable_samplepair_t paintbuffer[];
extern portable_samplepair_t roombuffer[];
extern portable_samplepair_t temppaintbuffer[];
extern portable_samplepair_t *g_curpaintbuffer;
extern paintbuffer_t paintbuffers[];
// structure used for fading in and out client sound volume.
typedef struct
{
float initial_percent;
float percent; // how far to adjust client's volume down by.
float starttime; // GetHostTime() when we started adjusting volume
float fadeouttime; // # of seconds to get to faded out state
float holdtime; // # of seconds to hold
float fadeintime; // # of seconds to restore
float initial_percent;
float percent; // how far to adjust client's volume down by.
float starttime; // GetHostTime() when we started adjusting volume
float fadeouttime; // # of seconds to get to faded out state
float holdtime; // # of seconds to hold
float fadeintime; // # of seconds to restore
} soundfade_t;
typedef struct
{
float percent;
float percent;
} musicfade_t;
typedef struct snd_format_s
{
unsigned int speed;
unsigned int width;
unsigned int channels;
uint speed;
byte width;
byte channels;
} snd_format_t;
typedef struct
{
snd_format_t format;
int samples; // mono samples in buffer
int samplepos; // in mono samples
byte *buffer;
qboolean initialized; // sound engine is active
const char *backendName;
snd_format_t format;
int samples; // mono samples in buffer
int samplepos; // in mono samples
qboolean initialized; // sound engine is active
byte *buffer;
const char *backendName;
} dma_t;
#include "vox.h"
typedef struct
{
double sample;
wavdata_t *pData;
double forcedEndSample;
qboolean finished;
double sample;
wavdata_t *pData;
double forcedEndSample;
qboolean finished;
} mixer_t;
typedef struct rawchan_s
{
int entnum;
int master_vol;
int leftvol; // 0-255 left volume
int rightvol; // 0-255 right volume
float dist_mult; // distance multiplier (attenuation/clipK)
vec3_t origin; // only use if fixed_origin is set
volatile uint s_rawend;
wavdata_t sound_info; // advance play position
float oldtime; // catch time jumps
size_t max_samples; // buffer length
portable_samplepair_t rawsamples[1]; // variable sized
int entnum;
int master_vol;
int leftvol; // 0-255 left volume
int rightvol; // 0-255 right volume
float dist_mult; // distance multiplier (attenuation/clipK)
vec3_t origin; // only use if fixed_origin is set
volatile uint s_rawend;
float oldtime; // catch time jumps
wavdata_t sound_info; // advance play position
size_t max_samples; // buffer length
portable_samplepair_t rawsamples[1]; // variable sized
} rawchan_t;
typedef struct channel_s
{
char name[16]; // keept sentence name
sfx_t *sfx; // sfx number
char name[16]; // keep sentence name
sfx_t *sfx; // sfx number
int leftvol; // 0-255 left volume
int rightvol; // 0-255 right volume
int leftvol; // 0-255 left volume
int rightvol; // 0-255 right volume
int entnum; // entity soundsource
int entchannel; // sound channel (CHAN_STREAM, CHAN_VOICE, etc.)
vec3_t origin; // only use if fixed_origin is set
float dist_mult; // distance multiplier (attenuation/clipK)
int master_vol; // 0-255 master volume
qboolean isSentence; // bit who indicated sentence
int basePitch; // base pitch percent (100% is normal pitch playback)
float pitch; // real-time pitch after any modulation or shift by dynamic data
qboolean use_loop; // don't loop default and local sounds
qboolean staticsound; // use origin instead of fetching entnum's origin
qboolean localsound; // it's a local menu sound (not looped, not paused)
mixer_t pMixer;
int entnum; // entity soundsource
int entchannel; // sound channel (CHAN_STREAM, CHAN_VOICE, etc.)
vec3_t origin; // only use if fixed_origin is set
float dist_mult; // distance multiplier (attenuation/clipK)
int master_vol; // 0-255 master volume
int basePitch; // base pitch percent (100% is normal pitch playback)
float pitch; // real-time pitch after any modulation or shift by dynamic data
qboolean use_loop; // don't loop default and local sounds
qboolean staticsound; // use origin instead of fetching entnum's origin
qboolean localsound; // it's a local menu sound (not looped, not paused)
mixer_t pMixer;
// sentence mixer
int wordIndex;
mixer_t *currentWord; // NULL if sentence is finished
voxword_t words[CVOXWORDMAX];
qboolean isSentence; // bit indicating sentence
int wordIndex;
mixer_t *currentWord; // NULL if sentence is finished
voxword_t words[CVOXWORDMAX];
} channel_t;
typedef struct
{
vec3_t origin; // simorg + view_ofs
vec3_t velocity;
vec3_t forward;
vec3_t right;
vec3_t up;
vec3_t origin; // simorg + view_ofs
vec3_t forward;
vec3_t right;
vec3_t up;
int entnum;
int waterlevel;
float frametime; // used for sound fade
qboolean active;
qboolean inmenu; // listener in-menu ?
qboolean paused;
qboolean streaming; // playing AVI-file
qboolean stream_paused; // pause only background track
int entnum;
int waterlevel;
float frametime; // used for sound fade
qboolean active;
qboolean inmenu; // listener in-menu ?
qboolean paused;
qboolean streaming; // playing AVI-file
qboolean stream_paused; // pause only background track
} listener_t;
typedef struct
{
string current; // a currently playing track
string loopName; // may be empty
stream_t *stream;
int source; // may be game, menu, etc
string current; // a currently playing track
string loopName; // may be empty
stream_t *stream;
int source; // may be game, menu, etc
} bg_track_t;
//====================================================================
#define MAX_DYNAMIC_CHANNELS (60 + NUM_AMBIENTS)
#define MAX_CHANNELS (256 + MAX_DYNAMIC_CHANNELS) // Scourge Of Armagon has too many static sounds on hip2m4.bsp
#define MAX_RAW_CHANNELS 48
#define MAX_RAW_SAMPLES 8192
#define MAX_DYNAMIC_CHANNELS (60 + NUM_AMBIENTS)
#define MAX_CHANNELS (256 + MAX_DYNAMIC_CHANNELS) // Scourge Of Armagon has too many static sounds on hip2m4.bsp
#define MAX_RAW_CHANNELS 48
#define MAX_RAW_SAMPLES 8192
extern sound_t ambient_sfx[NUM_AMBIENTS];
extern qboolean snd_ambient;
extern channel_t channels[MAX_CHANNELS];
extern rawchan_t *raw_channels[MAX_RAW_CHANNELS];
extern int total_channels;
extern int paintedtime;
extern int soundtime;
extern listener_t s_listener;
extern int idsp_room;
extern dma_t dma;
extern sound_t ambient_sfx[NUM_AMBIENTS];
extern qboolean snd_ambient;
extern channel_t channels[MAX_CHANNELS];
extern rawchan_t *raw_channels[MAX_RAW_CHANNELS];
extern int total_channels;
extern int paintedtime;
extern int soundtime;
extern listener_t s_listener;
extern int idsp_room;
extern dma_t dma;
extern convar_t s_musicvolume;
extern convar_t s_lerping;
extern convar_t s_test; // cvar to testify new effects
extern convar_t s_musicvolume;
extern convar_t s_lerping;
extern convar_t s_test; // cvar to test new effects
extern convar_t s_samplecount;
extern convar_t s_warn_late_precache;
@@ -292,7 +264,6 @@ void SND_ForceCloseMouth( int entnum );
//
void S_StreamSoundTrack( void );
void S_StreamBackgroundTrack( void );
qboolean S_StreamGetCurrentState( char *currentTrack, char *loopTrack, int *position );
void S_PrintBackgroundTrackState( void );
void S_FadeMusicVolume( float fadePercent );

View File

@@ -31,7 +31,7 @@ typedef struct OpusCustomMode OpusCustomMode;
#define VOICE_PCM_CHANNELS 1 // always mono
// never change these parameters when using opuscustom
#define VOICE_OPUS_CUSTOM_SAMPLERATE SOUND_44k
#define VOICE_OPUS_CUSTOM_SAMPLERATE 44100
// must follow opus custom requirements
// also be divisible with MAX_RAW_SAMPLES
#define VOICE_OPUS_CUSTOM_FRAME_SIZE 1024

View File

@@ -16,21 +16,20 @@ GNU General Public License for more details.
#ifndef VOX_H
#define VOX_H
#define CVOXWORDMAX 64
#define SENTENCE_INDEX -99999 // unique sentence index
#define CVOXWORDMAX 64
#define SENTENCE_INDEX -99999 // unique sentence index
typedef struct voxword_s
{
int volume; // increase percent, ie: 125 = 125% increase
int pitch; // pitch shift up percent
int start; // offset start of wave percent
int end; // offset end of wave percent
int cbtrim; // end of wave after being trimmed to 'end'
int fKeepCached; // 1 if this word was already in cache before sentence referenced it
int samplefrac; // if pitch shifting, this is position into wav * 256
int timecompress; // % of wave to skip during playback (causes no pitch shift)
sfx_t *sfx; // name and cache pointer
int volume; // increase percent, ie: 125 = 125% increase
int pitch; // pitch shift up percent
int start; // offset start of wave percent
int end; // offset end of wave percent
int cbtrim; // end of wave after being trimmed to 'end'
int fKeepCached; // 1 if this word was already in cache before sentence referenced it
int samplefrac; // if pitch shifting, this is position into wav * 256
int timecompress; // % of wave to skip during playback (causes no pitch shift)
sfx_t *sfx; // name and cache pointer
} voxword_t;
struct channel_s;

View File

@@ -19,13 +19,15 @@ GNU General Public License for more details.
#define HASH_SIZE 128 // 128 * 4 * 4 == 2048 bytes
typedef struct base_command_hashmap_s
typedef struct base_command_hashmap_s base_command_hashmap_t;
struct base_command_hashmap_s
{
base_command_t *basecmd; // base command: cvar, alias or command
const char *name; // key for searching
base_command_type_e type; // type for faster searching
struct base_command_hashmap_s *next;
} base_command_hashmap_t;
base_command_t *basecmd; // base command: cvar, alias or command
base_command_hashmap_t *next;
base_command_type_e type; // type for faster searching
char name[1]; // key for searching
};
static base_command_hashmap_t *hashed_cmds[HASH_SIZE];
@@ -124,11 +126,12 @@ void BaseCmd_Insert( base_command_type_e type, base_command_t *basecmd, const ch
{
base_command_hashmap_t *elem, *cur, *find;
uint hash = BaseCmd_HashKey( name );
size_t len = Q_strlen( name );
elem = Z_Malloc( sizeof( base_command_hashmap_t ) );
elem = Z_Malloc( sizeof( base_command_hashmap_t ) + len );
elem->basecmd = basecmd;
elem->type = type;
elem->name = name;
Q_strncpy( elem->name, name, len + 1 );
// link the variable in alphanumerical order
for( cur = NULL, find = hashed_cmds[hash];

View File

@@ -31,8 +31,6 @@ typedef enum base_command_type
typedef void base_command_t;
void BaseCmd_Init( void );
base_command_t *BaseCmd_Find( base_command_type_e type, const char *name );
void BaseCmd_FindAll( const char *name,

View File

@@ -949,7 +949,7 @@ static void Cmd_Else_f( void )
static qboolean Cmd_ShouldAllowCommand( cmd_t *cmd, qboolean isPrivileged )
{
const char *prefixes[] = { "cl_", "gl_", "r_", "m_", "hud_", "joy_" };
const char *prefixes[] = { "cl_", "gl_", "r_", "m_", "hud_", "joy_", "con_", "scr_" };
int i;
// always allow local commands
@@ -1015,7 +1015,7 @@ static void Cmd_ExecuteStringWithPrivilegeCheck( const char *text, qboolean isPr
*ptoken++ = *text++;
*ptoken = 0;
len += Q_strncpy( pcmd, Cvar_VariableString( token ), MAX_CMD_LINE - len );
len += Q_strncpy( pcmd, Cvar_VariableString( token ), sizeof( token ) - len );
pcmd = command + len;
if( !*text ) break;

View File

@@ -275,6 +275,10 @@ typedef enum bugcomp_e
{
// reverts fix for pfnPEntityOfEntIndex for bug compatibility with GoldSrc
BUGCOMP_PENTITYOFENTINDEX_FLAG = BIT( 0 ),
// rewrites mod's attempts to write GoldSrc-specific messages into Xash protocol
// (new wrappers are added by request)
BUGCOMP_MESSAGE_REWRITE_FACILITY_FLAG = BIT( 1 ),
} bugcomp_t;
typedef struct host_parm_s
@@ -475,14 +479,6 @@ typedef enum
WF_TOTALCOUNT, // must be last
} sndformat_t;
// soundlib global settings
typedef enum
{
SL_USE_LERPING = BIT(0), // lerping sounds during resample
SL_KEEP_8BIT = BIT(1), // don't expand 8bit sounds automatically up to 16 bit
SL_ALLOW_OVERWRITE = BIT(2), // allow to overwrite stored sounds
} slFlags_t;
// wavdata output flags
typedef enum
{
@@ -491,21 +487,20 @@ typedef enum
SOUND_STREAM = BIT( 1 ), // this is a streaminfo, not a real sound
// Sound_Process manipulation flags
SOUND_RESAMPLE = BIT(12), // resample sound to specified rate
SOUND_CONVERT16BIT = BIT(13), // change sound resolution from 8 bit to 16
SOUND_RESAMPLE = BIT( 12 ), // resample sound to specified rate
} sndFlags_t;
typedef struct
{
word rate; // num samples per second (e.g. 11025 - 11 khz)
byte width; // resolution - bum bits divided by 8 (8 bit is 1, 16 bit is 2)
byte channels; // num channels (1 - mono, 2 - stereo)
int loopStart; // offset at this point sound will be looping while playing more than only once
int samples; // total samplecount in wav
uint type; // compression type
uint flags; // misc sound flags
byte *buffer; // sound buffer
size_t size; // for bounds checking
word rate; // num samples per second (e.g. 11025 - 11 khz)
byte width; // resolution - bum bits divided by 8 (8 bit is 1, 16 bit is 2)
byte channels; // num channels (1 - mono, 2 - stereo)
uint loopStart; // offset at this point sound will be looping while playing more than only once
uint samples; // total samplecount in wav
uint type; // compression type
uint flags; // misc sound flags
byte *buffer; // sound buffer
size_t size; // for bounds checking
} wavdata_t;
//
@@ -700,7 +695,7 @@ void Log_Printf( const char *fmt, ... ) _format( 1 );
void SV_BroadcastCommand( const char *fmt, ... ) _format( 1 );
void SV_BroadcastPrintf( struct sv_client_s *ignore, const char *fmt, ... ) _format( 2 );
void CL_ClearStaticEntities( void );
qboolean S_StreamGetCurrentState( char *currentTrack, char *loopTrack, int *position );
qboolean S_StreamGetCurrentState( char *currentTrack, size_t currentTrackSize, char *loopTrack, size_t loopTrackSize, int *position );
void CL_ServerCommand( qboolean reliable, const char *fmt, ... ) _format( 2 );
void CL_HudMessage( const char *pMessage );
const char *CL_MsgInfo( int cmd );

View File

@@ -465,7 +465,7 @@ static qboolean Cmd_GetSoundList( const char *s, char *completedname, int length
t = FS_Search( va( "%s%s*.*", DEFAULT_SOUNDPATH, s ), true, false );
if( !t ) return false;
Q_strncpy( matchbuf, t->filenames[0] + sizeof( DEFAULT_SOUNDPATH ) - 1, MAX_STRING );
Q_strncpy( matchbuf, t->filenames[0] + sizeof( DEFAULT_SOUNDPATH ) - 1, sizeof( matchbuf ));
COM_StripExtension( matchbuf );
if( completedname && length )
Q_strncpy( completedname, matchbuf, length );
@@ -478,7 +478,7 @@ static qboolean Cmd_GetSoundList( const char *s, char *completedname, int length
if( Q_stricmp( ext, "wav" ) && Q_stricmp( ext, "mp3" ))
continue;
Q_strncpy( matchbuf, t->filenames[i] + sizeof( DEFAULT_SOUNDPATH ) - 1, MAX_STRING );
Q_strncpy( matchbuf, t->filenames[i] + sizeof( DEFAULT_SOUNDPATH ) - 1, sizeof( matchbuf ));
COM_StripExtension( matchbuf );
Con_Printf( "%16s\n", matchbuf );
numsounds++;
@@ -764,14 +764,14 @@ static qboolean Cmd_GetGamesList( const char *s, char *completedname, int length
}
if( !numgamedirs ) return false;
Q_strncpy( matchbuf, gamedirs[0], MAX_STRING );
Q_strncpy( matchbuf, gamedirs[0], sizeof( matchbuf ));
if( completedname && length )
Q_strncpy( completedname, matchbuf, length );
if( numgamedirs == 1 ) return true;
for( i = 0; i < numgamedirs; i++ )
{
Q_strncpy( matchbuf, gamedirs[i], MAX_STRING );
Q_strncpy( matchbuf, gamedirs[i], sizeof( matchbuf ));
Con_Printf( "%16s\n", matchbuf );
}
@@ -825,14 +825,14 @@ static qboolean Cmd_GetCDList( const char *s, char *completedname, int length )
}
if( !numcdcommands ) return false;
Q_strncpy( matchbuf, cdcommands[0], MAX_STRING );
Q_strncpy( matchbuf, cdcommands[0], sizeof( matchbuf ));
if( completedname && length )
Q_strncpy( completedname, matchbuf, length );
if( numcdcommands == 1 ) return true;
for( i = 0; i < numcdcommands; i++ )
{
Q_strncpy( matchbuf, cdcommands[i], MAX_STRING );
Q_strncpy( matchbuf, cdcommands[i], sizeof( matchbuf ));
Con_Printf( "%16s\n", matchbuf );
}
@@ -901,12 +901,10 @@ static qboolean Cmd_CheckMapsList_R( qboolean fRefresh, qboolean onlyingamedir )
if( f )
{
qboolean have_spawnpoints = false;
dheader_t *header;
dlump_t entities;
memset( buf, 0, MAX_SYSPATH );
FS_Read( f, buf, MAX_SYSPATH );
header = (dheader_t *)buf;
// check all the lumps and some other errors
if( !Mod_TestBmodelLumps( f, t->filenames[i], buf, true, &entities ))
@@ -937,7 +935,7 @@ static qboolean Cmd_CheckMapsList_R( qboolean fRefresh, qboolean onlyingamedir )
char token[MAX_TOKEN];
qboolean worldspawn = true;
Q_strncpy( message, "No Title", MAX_STRING );
Q_strncpy( message, "No Title", sizeof( message ));
pfile = ents;
while(( pfile = COM_ParseFile( pfile, token, sizeof( token ))) != NULL )

View File

@@ -955,7 +955,7 @@ static void Cvar_SetGL( const char *name, const char *value )
static qboolean Cvar_ShouldSetCvar( convar_t *v, qboolean isPrivileged )
{
const char *prefixes[] = { "cl_", "gl_", "m_", "r_", "hud_", "joy_" };
const char *prefixes[] = { "cl_", "gl_", "m_", "r_", "hud_", "joy_", "con_", "scr_" };
int i;
if( isPrivileged )

View File

@@ -75,6 +75,7 @@ typedef struct feature_message_s
static feature_message_t bugcomp_features[] =
{
{ BUGCOMP_PENTITYOFENTINDEX_FLAG, "pfnPEntityOfEntIndex bugfix revert", "peoei" },
{ BUGCOMP_MESSAGE_REWRITE_FACILITY_FLAG, "GoldSrc Message Rewrite Facility", "gsmrf" },
};
static feature_message_t engine_features[] =
@@ -864,7 +865,7 @@ void GAME_EXPORT Host_Error( const char *error, ... )
}
recursive = true;
Q_strncpy( hosterror2, hosterror1, MAX_SYSPATH );
Q_strncpy( hosterror2, hosterror1, sizeof( hosterror2 ));
host.errorframe = host.framecount; // to avoid multply calls per frame
Q_snprintf( host.finalmsg, sizeof( host.finalmsg ), "Server crashed: %s", hosterror1 );
@@ -958,15 +959,15 @@ static void Host_RunTests( int stage )
static uint32_t Host_CheckBugcomp( void )
{
const char *prev, *next;
uint32_t flags = 0;
string args, arg;
char *prev, *next;
size_t i;
if( !Sys_CheckParm( "-bugcomp" ))
return 0;
if( Sys_GetParmFromCmdLine( "-bugcomp", args ) && args[0] != '-' )
if( Sys_GetParmFromCmdLine( "-bugcomp", args ) && isalpha( args[0] ))
{
for( prev = args, next = Q_strchrnul( prev, '+' ); ; prev = next + 1, next = Q_strchrnul( prev, '+' ))
{

View File

@@ -262,7 +262,7 @@ static void NET_AddMaster( const char *addr, qboolean save )
}
master = Mem_Malloc( host.mempool, sizeof( master_t ) );
Q_strncpy( master->address, addr, MAX_STRING );
Q_strncpy( master->address, addr, sizeof( master->address ));
master->sent = false;
master->save = save;
master->next = NULL;

View File

@@ -1823,8 +1823,8 @@ static void Mod_LoadEntities( model_t *mod, dbspmodel_t *bmod )
{
char *pszWadFile;
Q_strncpy( wadstring, token, MAX_TOKEN - 2 );
wadstring[MAX_TOKEN - 2] = 0;
Q_strncpy( wadstring, token, sizeof( wadstring ) - 2 );
wadstring[sizeof( wadstring ) - 2] = 0;
if( !Q_strchr( wadstring, ';' ))
Q_strncat( wadstring, ";", sizeof( wadstring ));

View File

@@ -216,7 +216,7 @@ wavdata_t *FS_StreamInfo( stream_t *stream )
if( !stream ) return NULL;
// fill structure
info.loopStart = -1;
info.loopStart = 0;
info.rate = stream->rate;
info.width = stream->width;
info.channels = stream->channels;

View File

@@ -74,7 +74,10 @@ static uint32_t Sound_ParseSynchInteger( uint32_t v )
static void Sound_HandleCustomID3Comment( const char *key, const char *value )
{
if( !Q_strcmp( key, "LOOP_START" ) || !Q_strcmp( key, "LOOPSTART" ))
{
sound.loopstart = Q_atoi( value );
SetBits( sound.flags, SOUND_LOOPED );
}
// unknown comment is not an error
}
@@ -233,7 +236,6 @@ qboolean Sound_LoadMPG( const char *name, const byte *buffer, fs_offset_t filesi
sound.channels = sc.channels;
sound.rate = sc.rate;
sound.width = 2; // always 16-bit PCM
sound.loopstart = -1;
sound.size = ( sound.channels * sound.rate * sound.width ) * ( sc.playtime / 1000 ); // in bytes
padsize = sound.size % FRAME_SIZE;
pos += FRAME_SIZE; // evaluate pos
@@ -241,7 +243,6 @@ qboolean Sound_LoadMPG( const char *name, const byte *buffer, fs_offset_t filesi
if( !Sound_ParseID3Tag( buffer, filesize ))
{
Con_DPrintf( S_WARN "Sound_LoadMPG: (%s) failed to extract LOOP_START tag\n", name );
sound.loopstart = -1;
}
if( !sound.size )

View File

@@ -14,6 +14,9 @@ GNU General Public License for more details.
*/
#include "soundlib.h"
#if XASH_SDL
#include <SDL_audio.h>
#endif // XASH_SDL
/*
=============================================================================
@@ -130,7 +133,309 @@ uint GAME_EXPORT Sound_GetApproxWavePlayLen( const char *filepath )
return msecs;
}
#define drint( v ) (int)( v + 0.5 )
static qboolean Sound_ConvertNoResample( wavdata_t *sc, int inwidth, int outwidth, int outcount )
{
size_t i;
if( inwidth == 1 && outwidth == 2 ) // S8 to S16
{
for( i = 0; i < outcount * sc->channels; i++ )
((int16_t*)sound.tempbuffer)[i] = ((int8_t *)sc->buffer)[i] * 256;
return true;
}
if( inwidth == 2 && outwidth == 1 ) // S16 to S8
{
for( i = 0; i < outcount * sc->channels; i++ )
((int8_t*)sound.tempbuffer)[i] = ((int16_t *)sc->buffer)[i] / 256;
return true;
}
return false;
}
static qboolean Sound_ConvertDownsample( wavdata_t *sc, int inwidth, int outwidth, int outcount, double stepscale )
{
size_t i;
double j;
if( inwidth == 1 && outwidth == 1 )
{
int8_t *data = (int8_t *)sc->buffer;
if( outwidth == 1 )
{
int8_t *outdata = (int8_t *)sound.tempbuffer;
if( sc->channels == 2 )
{
for( i = 0; i < outcount; i++ )
{
j = stepscale * i;
outdata[i*2+0] = data[((int)j)*2+0];
outdata[i*2+1] = data[((int)j)*2+1];
}
}
else
{
for( i = 0; i < outcount; i++ )
{
j = stepscale * i;
outdata[i] = data[(int)j];
}
}
return true;
}
if( outwidth == 2 )
{
int16_t *outdata = (int16_t *)sound.tempbuffer;
if( sc->channels == 2 )
{
for( i = 0; i < outcount; i++ )
{
j = stepscale * i;
outdata[i*2+0] = data[((int)j)*2+0] * 256;
outdata[i*2+1] = data[((int)j)*2+1] * 256;
}
}
else
{
for( i = 0; i < outcount; i++ )
{
j = stepscale * i;
outdata[i] = data[(int)j] * 256;
}
}
return true;
}
}
if( inwidth == 2 )
{
int16_t *data = (int16_t *)sc->buffer;
if( outwidth == 1 )
{
int8_t *outdata = (int8_t *)sound.tempbuffer;
if( sc->channels == 2 )
{
for( i = 0; i < outcount; i++ )
{
j = stepscale * i;
outdata[i*2+0] = data[((int)j)*2+0] / 256;
outdata[i*2+1] = data[((int)j)*2+1] / 256;
}
}
else
{
for( i = 0; i < outcount; i++ )
{
j = stepscale * i;
outdata[i] = data[(int)j] / 256;
}
}
return true;
}
if( outwidth == 2 )
{
int16_t *outdata = (int16_t *)sound.tempbuffer;
if( sc->channels == 2 )
{
for( i = 0; i < outcount; i++ )
{
j = stepscale * i;
outdata[i*2+0] = data[((int)j)*2+0];
outdata[i*2+1] = data[((int)j)*2+1];
}
}
else
{
for( i = 0; i < outcount; i++ )
{
j = stepscale * i;
outdata[i] = data[(int)j];
}
}
return true;
}
}
return false;
}
static qboolean Sound_ConvertUpsample( wavdata_t *sc, int inwidth, int outwidth, int outcount, int incount, double stepscale )
{
size_t i;
double j;
double frac;
incount--; // to not go past last sample while interpolating
if( inwidth == 1 )
{
int8_t *data = (int8_t *)sc->buffer;
if( outwidth == 1 )
{
int8_t *outdata = (int8_t *)sound.tempbuffer;
if( sc->channels == 2 )
{
for( i = 0; i < outcount; i++ )
{
j = stepscale * i;
outdata[i*2+0] = data[((int)j)*2+0];
outdata[i*2+1] = data[((int)j)*2+1];
if( j != (int)j && j < incount )
{
frac = j - (int)j;
outdata[i*2+0] += (data[((int)j+1)*2+0] - data[((int)j)*2+0]) * frac;
outdata[i*2+1] += (data[((int)j+1)*2+1] - data[((int)j)*2+1]) * frac;
}
}
}
else
{
for( i = 0; i < outcount; i++ )
{
j = stepscale * i;
outdata[i] = data[(int)j];
if( j != (int)j && j < incount )
{
frac = j - (int)j;
outdata[i] += (data[(int)j+1] - data[(int)j]) * frac;
}
}
}
return true;
}
if( outwidth == 2 )
{
int16_t *outdata = (int16_t *)sound.tempbuffer;
if( sc->channels == 2 )
{
for( i = 0; i < outcount; i++ )
{
j = stepscale * i;
outdata[i*2+0] = data[((int)j)*2+0] * 256;
outdata[i*2+1] = data[((int)j)*2+1] * 256;
if( j != (int)j && j < incount )
{
frac = ( j - (int)j ) * 256;
outdata[i*2+0] += (data[((int)j+1)*2+0] - data[((int)j)*2+0]) * frac;
outdata[i*2+1] += (data[((int)j+1)*2+1] - data[((int)j)*2+1]) * frac;
}
}
}
else
{
for( i = 0; i < outcount; i++ )
{
j = stepscale * i;
outdata[i] = data[(int)j] * 256;
if( j != (int)j && j < incount )
{
frac = ( j - (int)j ) * 256;
outdata[i] += (data[(int)j+1] - data[(int)j]) * frac;
}
}
}
return true;
}
}
if( inwidth == 2 )
{
int16_t *data = (int16_t *)sc->buffer;
if( outwidth == 1 )
{
int8_t *outdata = (int8_t *)sound.tempbuffer;
if( sc->channels == 2 )
{
for( i = 0; i < outcount; i++ )
{
j = stepscale * i;
outdata[i*2+0] = data[((int)j)*2+0] / 256;
outdata[i*2+1] = data[((int)j)*2+1] / 256;
if( j != (int)j && j < incount )
{
frac = ( j - (int)j ) / 256;
outdata[i*2+0] += (data[((int)j+1)*2+0] - data[((int)j)*2+0]) * frac;
outdata[i*2+1] += (data[((int)j+1)*2+1] - data[((int)j)*2+1]) * frac;
}
}
}
else
{
for( i = 0; i < outcount; i++ )
{
j = stepscale * i;
outdata[i] = data[(int)j] / 256;
if( j != (int)j && j < incount )
{
frac = ( j - (int)j ) / 256;
outdata[i] += (data[(int)j+1] - data[(int)j]) * frac;
}
}
}
return true;
}
if( outwidth == 2 )
{
int16_t *outdata = (int16_t *)sound.tempbuffer;
if( sc->channels == 2 )
{
for( i = 0; i < outcount; i++ )
{
j = stepscale * i;
outdata[i*2+0] = data[((int)j)*2+0];
outdata[i*2+1] = data[((int)j)*2+1];
if( j != (int)j && j < incount )
{
frac = j - (int)j;
outdata[i*2+0] += (data[((int)j+1)*2+0] - data[((int)j)*2+0]) * frac;
outdata[i*2+1] += (data[((int)j+1)*2+1] - data[((int)j)*2+1]) * frac;
}
}
}
else
{
for( i = 0; i < outcount; i++ )
{
j = stepscale * i;
outdata[i] = data[(int)j];
if( j != (int)j && j < incount )
{
frac = j - (int)j;
outdata[i] += (data[(int)j+1] - data[(int)j]) * frac;
}
}
}
return true;
}
}
return false;
}
/*
================
@@ -141,125 +446,70 @@ We need convert sound to signed even if nothing to resample
*/
static qboolean Sound_ResampleInternal( wavdata_t *sc, int inrate, int inwidth, int outrate, int outwidth )
{
double stepscale, j;
int outcount;
int i;
const size_t oldsize = sc->size;
qboolean handled = false;
double stepscale;
double t1, t2;
int outcount, incount = sc->samples;
if( inrate == outrate && inwidth == outwidth )
return false;
t1 = Sys_DoubleTime();
stepscale = (double)inrate / outrate; // this is usually 0.5, 1, or 2
outcount = sc->samples / stepscale;
sc->size = outcount * outwidth * sc->channels;
sound.tempbuffer = (byte *)Mem_Realloc( host.soundpool, sound.tempbuffer, sc->size );
sc->samples = outcount;
if( sc->loopStart != -1 )
if( FBitSet( sc->flags, SOUND_LOOPED ))
sc->loopStart = sc->loopStart / stepscale;
if( inrate == outrate )
#if 0 && XASH_SDL // slow but somewhat accurate
{
if( inwidth == 1 && outwidth == 2 ) // S8 to S16
{
for( i = 0; i < outcount * sc->channels; i++ )
((int16_t*)sound.tempbuffer)[i] = ((int8_t *)sc->buffer)[i] * 256;
handled = true;
}
else if( inwidth == 2 && outwidth == 1 ) // S16 to S8
{
for( i = 0; i < outcount * sc->channels; i++ )
((int8_t*)sound.tempbuffer)[i] = ((int16_t *)sc->buffer)[i] / 256;
handled = true;
}
}
else // resample case
{
if( inwidth == 1 )
{
int8_t *data = (int8_t *)sc->buffer;
const SDL_AudioFormat infmt = inwidth == 1 ? AUDIO_S8 : AUDIO_S16;
const SDL_AudioFormat outfmt = outwidth == 1 ? AUDIO_S8 : AUDIO_S16;
SDL_AudioCVT cvt;
if( outwidth == 1 )
{
if( sc->channels == 2 )
{
for( i = 0, j = 0; i < outcount; i++, j += stepscale )
{
((int8_t*)sound.tempbuffer)[i*2+0] = data[((int)j)*2+0];
((int8_t*)sound.tempbuffer)[i*2+1] = data[((int)j)*2+1];
}
}
else
{
for( i = 0, j = 0; i < outcount; i++, j += stepscale )
((int8_t*)sound.tempbuffer)[i] = data[(int)j];
}
handled = true;
}
else if( outwidth == 2 )
{
if( sc->channels == 2 )
{
for( i = 0, j = 0; i < outcount; i++, j += stepscale )
{
((int16_t*)sound.tempbuffer)[i*2+0] = data[((int)j)*2+0] * 256;
((int16_t*)sound.tempbuffer)[i*2+1] = data[((int)j)*2+1] * 256;
}
}
else
{
for( i = 0, j = 0; i < outcount; i++, j += stepscale )
((int16_t*)sound.tempbuffer)[i] = data[(int)j] * 256;
}
handled = true;
}
}
else if( inwidth == 2 )
// SDL_AudioCVT does conversion in place, original buffer is used for it
if( SDL_BuildAudioCVT( &cvt, infmt, sc->channels, inrate, outfmt, sc->channels, outrate ) > 0 && cvt.needed )
{
int16_t *data = (int16_t *)sc->buffer;
sc->buffer = (byte *)Mem_Realloc( host.soundpool, sc->buffer, oldsize * cvt.len_mult );
cvt.len = oldsize;
cvt.buf = sc->buffer;
if( outwidth == 1 )
if( !SDL_ConvertAudio( &cvt ))
{
if( sc->channels == 2 )
{
for( i = 0, j = 0; i < outcount; i++, j += stepscale )
{
((int8_t*)sound.tempbuffer)[i*2+0] = data[((int)j)*2+0] / 256;
((int8_t*)sound.tempbuffer)[i*2+1] = data[((int)j)*2+1] / 256;
}
}
else
{
for( i = 0, j = 0; i < outcount; i++, j += stepscale )
((int8_t*)sound.tempbuffer)[i] = data[(int)j] / 256;
}
handled = true;
}
else if( outwidth == 2 )
{
if( sc->channels == 2 )
{
for( i = 0, j = 0; i < outcount; i++, j += stepscale )
{
((int16_t*)sound.tempbuffer)[i*2+0] = data[((int)j)*2+0];
((int16_t*)sound.tempbuffer)[i*2+1] = data[((int)j)*2+1];
}
}
else
{
for( i = 0, j = 0; i < outcount; i++, j += stepscale )
((int16_t*)sound.tempbuffer)[i] = data[(int)j];
}
handled = true;
t2 = Sys_DoubleTime();
Con_Reportf( "Sound_Resample: from [%d bit %d Hz] to [%d bit %d Hz] (took %.3fs through SDL)\n", inwidth * 8, inrate, outwidth * 8, outrate, t2 - t1 );
sc->rate = outrate;
sc->width = outwidth;
return false; // HACKHACK: return false so Sound_Process won't reallocate buffer
}
}
}
#endif
sound.tempbuffer = (byte *)Mem_Realloc( host.soundpool, sound.tempbuffer, sc->size );
if( inrate == outrate ) // no resampling, just copy data
handled = Sound_ConvertNoResample( sc, inwidth, outwidth, outcount );
else if( inrate > outrate ) // fast case, usually downsample but is also ok for upsampling
handled = Sound_ConvertDownsample( sc, inwidth, outwidth, outcount, stepscale );
else // upsample case, w/ interpolation
handled = Sound_ConvertUpsample( sc, inwidth, outwidth, outcount, incount, stepscale );
t2 = Sys_DoubleTime();
if( handled )
Con_Reportf( "Sound_Resample: from [%d bit %d Hz] to [%d bit %d Hz]\n", inwidth * 8, inrate, outwidth * 8, outrate );
{
if( t2 - t1 > 0.01f ) // critical, report to mod developer
Con_Printf( S_WARN "Sound_Resample: from [%d bit %d Hz] to [%d bit %d Hz] (took %.3fs)\n", inwidth * 8, inrate, outwidth * 8, outrate, t2 - t1 );
else
Con_Reportf( "Sound_Resample: from [%d bit %d Hz] to [%d bit %d Hz] (took %.3fs)\n", inwidth * 8, inrate, outwidth * 8, outrate, t2 - t1 );
}
else
Con_Reportf( S_ERROR "Sound_Resample: unsupported from [%d bit %d Hz] to [%d bit %d Hz]\n", inwidth * 8, inrate, outwidth * 8, outrate );
Con_Printf( S_ERROR "Sound_Resample: unsupported from [%d bit %d Hz] to [%d bit %d Hz]\n", inwidth * 8, inrate, outwidth * 8, outrate );
sc->rate = outrate;
sc->width = outwidth;
@@ -276,23 +526,20 @@ qboolean Sound_Process( wavdata_t **wav, int rate, int width, uint flags )
if( !snd || !snd->buffer )
return false;
if(( flags & SOUND_RESAMPLE ) && ( width > 0 || rate > 0 ))
if( FBitSet( flags, SOUND_RESAMPLE ) && ( width > 0 || rate > 0 ))
{
if( Sound_ResampleInternal( snd, snd->rate, snd->width, rate, width ))
result = Sound_ResampleInternal( snd, snd->rate, snd->width, rate, width );
if( result )
{
Mem_Free( snd->buffer ); // free original image buffer
snd->buffer = Sound_Copy( snd->size ); // unzone buffer (don't touch image.tempbuffer)
}
else
{
// not resampled
result = false;
snd->buffer = Sound_Copy( snd->size ); // unzone buffer (don't touch sound.tempbuffer)
}
}
*wav = snd;
return false;
return result;
}
qboolean Sound_SupportedFileFormat( const char *fileext )

View File

@@ -23,6 +23,11 @@ static const byte *iff_end;
static const byte *iff_lastChunk;
static int iff_chunkLen;
static int IsFourCC( const byte *ptr, const byte *fourcc )
{
return 0 == memcmp( ptr, fourcc, 4 );
}
/*
=================
GetLittleShort
@@ -86,7 +91,21 @@ static void FindNextChunk( const char *filename, const char *name )
if( iff_chunkLen > remaining )
{
Con_DPrintf( "%s: '%s' truncated by %i bytes\n", __func__, filename, iff_chunkLen - remaining );
// only print this warning if selected chunk is truncated
//
// otherwise this warning becomes misleading because some
// idiot programs like CoolEdit (i.e. Adobe Audition) don't always
// respect pad byte. The file isn't actually truncated, it just
// can't be reliably parsed as a whole
if( IsFourCC( iff_lastChunk, "RIFF" )
|| IsFourCC( iff_lastChunk, "fmt " )
|| IsFourCC( iff_lastChunk, "cue " )
|| IsFourCC( iff_lastChunk, "LIST" )
|| IsFourCC( iff_lastChunk, "data" ))
{
Con_DPrintf( "%s: '%s' truncated by %i bytes\n", __func__, filename, iff_chunkLen - remaining );
}
iff_chunkLen = remaining;
}
@@ -94,9 +113,9 @@ static void FindNextChunk( const char *filename, const char *name )
iff_dataPtr -= 8;
iff_lastChunk = iff_dataPtr + 8 + iff_chunkLen;
if ((iff_chunkLen&1) && remaining)
if(( iff_chunkLen & 1 ) && remaining )
iff_lastChunk++;
if (!Q_strncmp(iff_dataPtr, name, 4))
if( IsFourCC( iff_dataPtr, name ))
return;
}
}
@@ -130,15 +149,18 @@ static qboolean StreamFindNextChunk( file_t *file, const char *name, int *last_c
return false; // didn't find the chunk
FS_Seek( file, 4, SEEK_CUR );
FS_Read( file, &iff_chunk_len, sizeof( iff_chunk_len ));
if( FS_Read( file, &iff_chunk_len, sizeof( iff_chunk_len )) != sizeof( iff_chunk_len ))
return false;
if( iff_chunk_len < 0 )
return false; // didn't find the chunk
FS_Seek( file, -8, SEEK_CUR );
*last_chunk = FS_Tell( file ) + 8 + (( iff_chunk_len + 1 ) & ~1 );
FS_Read( file, chunkName, 4 );
if( FS_Read( file, chunkName, sizeof( chunkName )) != sizeof( chunkName ))
return false;
if( !Q_strncmp( chunkName, name, 4 ))
if( IsFourCC( chunkName, name ))
return true;
}
@@ -164,7 +186,7 @@ qboolean Sound_LoadWAV( const char *name, const byte *buffer, fs_offset_t filesi
// find "RIFF" chunk
FindChunk( name, "RIFF" );
if( !( iff_dataPtr && !Q_strncmp( (const char *)iff_dataPtr + 8, "WAVE", 4 )))
if( !iff_dataPtr || !IsFourCC( iff_dataPtr + 8, "WAVE" ))
{
Con_DPrintf( S_ERROR "Sound_LoadWAV: %s missing 'RIFF/WAVE' chunks\n", name );
return false;
@@ -223,11 +245,12 @@ qboolean Sound_LoadWAV( const char *name, const byte *buffer, fs_offset_t filesi
{
iff_dataPtr += 32;
sound.loopstart = GetLittleLong();
SetBits( sound.flags, SOUND_LOOPED );
FindNextChunk( name, "LIST" ); // if the next chunk is a LIST chunk, look for a cue length marker
if( iff_dataPtr )
{
if( !Q_strncmp( (const char *)iff_dataPtr + 28, "mark", 4 ))
if( IsFourCC( iff_dataPtr + 28, "mark" ))
{
// this is not a proper parse, but it works with CoolEdit...
iff_dataPtr += 24;
@@ -237,7 +260,7 @@ qboolean Sound_LoadWAV( const char *name, const byte *buffer, fs_offset_t filesi
}
else
{
sound.loopstart = -1;
sound.loopstart = 0;
sound.samples = 0;
}
@@ -342,8 +365,16 @@ stream_t *Stream_OpenWAV( const char *filename )
return NULL;
}
FS_Read( file, chunkName, 4 );
if( !Q_strncmp( chunkName, "WAVE", 4 ))
FS_Seek( file, 4, SEEK_CUR );
if( FS_Read( file, chunkName, 4 ) != 4 )
{
Con_DPrintf( S_ERROR "%s: %s missing WAVE chunk, truncated\n", filename );
FS_Close( file );
return false;
}
if( !IsFourCC( chunkName, "WAVE" ))
{
Con_DPrintf( S_ERROR "Stream_OpenWAV: %s missing WAVE chunk\n", filename );
FS_Close( file );
@@ -351,7 +382,7 @@ stream_t *Stream_OpenWAV( const char *filename )
}
// get "fmt " chunk
iff_data = FS_Tell( file ) + 4;
iff_data = FS_Tell( file );
last_chunk = iff_data;
if( !StreamFindNextChunk( file, "fmt ", &last_chunk ))
{

View File

@@ -50,7 +50,7 @@ typedef struct sndlib_s
int rate; // num samples per second (e.g. 11025 - 11 khz)
int width; // resolution - bum bits divided by 8 (8 bit is 1, 16 bit is 2)
int channels; // num channels (1 - mono, 2 - stereo)
int loopstart; // start looping from
uint loopstart; // start looping from
uint samples; // total samplecount in sound
uint flags; // additional sound flags
size_t size; // sound unpacked size (for bounds checking)

View File

@@ -50,6 +50,10 @@ GNU General Public License for more details.
#define LUMP_SAVE_NO_DATA 7
#define LUMP_SAVE_CORRUPTED 8
#ifndef ALLOC_CHECK
#define ALLOC_CHECK( x )
#endif
typedef struct areanode_s
{
int axis; // -1 = leaf node

View File

@@ -175,11 +175,13 @@ void Evdev_Autodetect_f( void )
if( evdev.devices >= MAX_EVDEV_DEVICES )
continue;
Q_snprintf( path, MAX_STRING, "/dev/input/%s", entry->d_name );
Q_snprintf( path, sizeof( path ), "/dev/input/%s", entry->d_name );
for( i = 0; i < evdev.devices; i++ )
if( !Q_strncmp( evdev.paths[i], path, MAX_STRING ) )
{
if( !Q_strncmp( evdev.paths[i], path, sizeof( evdev.paths[i] ))
goto next;
}
if( Q_strncmp( entry->d_name, "event", 5 ) )
continue;
@@ -220,7 +222,7 @@ void Evdev_Autodetect_f( void )
}
goto close;
open:
Q_strncpy( evdev.paths[evdev.devices], path, MAX_STRING );
Q_strncpy( evdev.paths[evdev.devices], path, sizeof( evdev.paths[0] ));
evdev.fds[evdev.devices++] = fd;
Con_Printf( "Opened device %s\n", path );
#if XASH_INPUT == INPUT_EVDEV
@@ -260,7 +262,7 @@ void Evdev_OpenDevice ( const char *path )
for( i = 0; i < evdev.devices; i++ )
{
if( !Q_strncmp( evdev.paths[i], path, MAX_STRING ) )
if( !Q_strncmp( evdev.paths[i], path, sizeof( evdev.paths[i] )))
{
Con_Printf( "device %s already open!\n", path );
return;
@@ -275,7 +277,7 @@ void Evdev_OpenDevice ( const char *path )
}
Con_Printf( "Input device #%d: %s opened sucessfully\n", evdev.devices, path );
evdev.fds[evdev.devices] = ret;
Q_strncpy( evdev.paths[evdev.devices++], path, MAX_STRING );
Q_strncpy( evdev.paths[evdev.devices++], path, sizeof( evdev.paths[0] ));
#if XASH_INPUT == INPUT_EVDEV
if( Sys_CheckParm( "-grab" ) )
@@ -309,7 +311,7 @@ void Evdev_CloseDevice_f ( void )
if( Q_isdigit( arg ) )
i = Q_atoi( arg );
else for( i = 0; i < evdev.devices; i++ )
if( !Q_strncmp( evdev.paths[i], arg, MAX_STRING ) )
if( !Q_strncmp( evdev.paths[i], arg, sizeof( evdev.paths[i] )))
break;
if( i >= evdev.devices )
@@ -324,7 +326,7 @@ void Evdev_CloseDevice_f ( void )
for( ; i < evdev.devices; i++ )
{
Q_strncpy( evdev.paths[i], evdev.paths[i+1], MAX_STRING );
Q_strncpy( evdev.paths[i], evdev.paths[i+1], sizeof( evdev.paths[i] ));
evdev.fds[i] = evdev.fds[i+1];
}
}

View File

@@ -148,7 +148,6 @@ static void SDLash_KeyEvent( SDL_KeyboardEvent key )
#else
int keynum = key.keysym.sym;
#endif
qboolean numLock = FBitSet( SDL_GetModState(), KMOD_NUM );
#if XASH_ANDROID
if( keynum == SDL_SCANCODE_VOLUMEUP || keynum == SDL_SCANCODE_VOLUMEDOWN )
@@ -157,32 +156,39 @@ static void SDLash_KeyEvent( SDL_KeyboardEvent key )
}
#endif
if( SDL_IsTextInputActive() && down && cls.key_dest != key_game )
if( SDL_IsTextInputActive( ))
{
if( FBitSet( SDL_GetModState(), KMOD_CTRL ))
// this is how engine understands ctrl+c, ctrl+v and other hotkeys
if( down && cls.key_dest != key_game )
{
if( keynum >= SDL_SCANCODE_A && keynum <= SDL_SCANCODE_Z )
if( FBitSet( SDL_GetModState(), KMOD_CTRL ))
{
keynum = keynum - SDL_SCANCODE_A + 1;
CL_CharEvent( keynum );
}
if( keynum >= SDL_SCANCODE_A && keynum <= SDL_SCANCODE_Z )
{
keynum = keynum - SDL_SCANCODE_A + 1;
CL_CharEvent( keynum );
}
return;
return;
}
}
#if !SDL_VERSION_ATLEAST( 2, 0, 0 )
#if SDL_VERSION_ATLEAST( 2, 0, 0 )
// ignore printable keys, they are coming through SDL_TEXTINPUT
if(( keynum >= SDL_SCANCODE_A && keynum <= SDL_SCANCODE_Z )
|| ( keynum >= SDL_SCANCODE_1 && keynum <= SDL_SCANCODE_0 )
|| ( keynum >= SDL_SCANCODE_KP_1 && keynum <= SDL_SCANCODE_KP_0 ))
return;
#else
if( keynum >= SDLK_KP0 && keynum <= SDLK_KP9 )
keynum -= SDLK_KP0 + '0';
if( isprint( keynum ) )
if( isprint( keynum ))
{
if( FBitSet( SDL_GetModState(), KMOD_SHIFT ))
{
keynum = Key_ToUpper( keynum );
}
CL_CharEvent( keynum );
return;
}
#endif
}
@@ -198,6 +204,8 @@ static void SDLash_KeyEvent( SDL_KeyboardEvent key )
else DECLARE_KEY_RANGE( SDL_SCANCODE_F1, SDL_SCANCODE_F12, K_F1 )
else
{
qboolean numLock = FBitSet( SDL_GetModState(), KMOD_NUM );
switch( keynum )
{
case SDL_SCANCODE_GRAVE: keynum = '`'; break;
@@ -355,10 +363,7 @@ static void SDLash_InputEvent( SDL_TextInputEvent input )
{
int ch;
if( !Q_stricmp( cl_charset.string, "utf-8" ) )
ch = (unsigned char)*text;
else
ch = Con_UtfProcessCharForce( (unsigned char)*text );
ch = Con_UtfProcessChar((byte)*text );
if( !ch )
continue;

View File

@@ -329,6 +329,8 @@ typedef struct
int msg_realsize; // left in bytes
int msg_index; // for debug messages
int msg_dest; // msg destination ( MSG_ONE, MSG_ALL etc )
int msg_rewrite_index;
int msg_rewrite_pos;
qboolean msg_started; // to avoid recursive included messages
edict_t *msg_ent; // user message member entity
vec3_t msg_org; // user message member origin
@@ -392,10 +394,10 @@ typedef struct
//=============================================================================
extern server_static_t svs; // persistant server info
extern server_t sv; // local server
extern svgame_static_t svgame; // persistant game info
extern areanode_t sv_areanodes[]; // AABB dynamic tree
extern server_static_t svs RENAME_SYMBOL( "svs_" ); // persistant server info
extern server_t sv RENAME_SYMBOL( "sv_" ); // local server
extern svgame_static_t svgame; // persistant game info
extern areanode_t sv_areanodes[]; // AABB dynamic tree
extern convar_t mp_logecho;
extern convar_t mp_logfile;
@@ -480,7 +482,7 @@ extern convar_t sv_aim;
//
void SV_FinalMessage( const char *message, qboolean reconnect );
void SV_KickPlayer( sv_client_t *cl, const char *fmt, ... ) _format( 2 );
void SV_DropClient( sv_client_t *cl, qboolean crash );
void SV_DropClient( sv_client_t *cl, qboolean crash ) RENAME_SYMBOL( "SV_DropClient_" );
void SV_UpdateMovevars( qboolean initialize );
int SV_ModelIndex( const char *name );
int SV_SoundIndex( const char *name );

View File

@@ -417,7 +417,7 @@ static void SV_ConnectClient( netadr_t from )
newcl->userid = g_userid++; // create unique userid
newcl->state = cs_connected;
newcl->extensions = extensions & (NET_EXT_SPLITSIZE);
Q_strncpy( newcl->useragent, protinfo, MAX_INFO_STRING );
Q_strncpy( newcl->useragent, protinfo, sizeof( newcl->useragent ));
// reset viewentities (from previous level)
memset( newcl->viewentity, 0, sizeof( newcl->viewentity ));

View File

@@ -690,7 +690,7 @@ static void SV_ConSay_f( void )
}
p = Cmd_Args();
Q_strncpy( text, *p == '"' ? p + 1 : p, MAX_SYSPATH );
Q_strncpy( text, *p == '"' ? p + 1 : p, sizeof( text ));
if( *p == '"' )
{

View File

@@ -666,7 +666,7 @@ void SV_RestartAmbientSounds( void )
#if !XASH_DEDICATED // TODO: ???
// restart soundtrack
if( S_StreamGetCurrentState( curtrack, looptrack, &position ))
if( S_StreamGetCurrentState( curtrack, sizeof( curtrack ), looptrack, sizeof( looptrack ), &position ))
{
SV_StartMusic( curtrack, looptrack, position );
}
@@ -2501,6 +2501,62 @@ int GAME_EXPORT pfnDecalIndex( const char *m )
return -1;
}
static int SV_CanRewriteMessage( int msg_num )
{
// feature is disabled
if( !FBitSet( host.bugcomp, BUGCOMP_MESSAGE_REWRITE_FACILITY_FLAG ))
return 0;
switch( msg_num )
{
case svc_goldsrc_spawnstaticsound:
return svc_sound;
}
return 0;
}
static qboolean SV_RewriteMessage( void )
{
vec3_t origin;
const char *sample = NULL;
float vol, attn;
int ent, pitch, flags, idx;
int cmd;
MSG_SeekToBit( &sv.multicast, svgame.msg_rewrite_pos, SEEK_SET );
cmd = MSG_ReadCmd( &sv.multicast, NS_SERVER );
switch( cmd )
{
case svc_goldsrc_spawnstaticsound:
MSG_ReadVec3Coord( &sv.multicast, origin );
idx = MSG_ReadShort( &sv.multicast );
vol = MSG_ReadByte( &sv.multicast );
attn = MSG_ReadByte( &sv.multicast ) / 64.0f;
ent = MSG_ReadShort( &sv.multicast );
pitch = MSG_ReadByte( &sv.multicast );
flags = MSG_ReadByte( &sv.multicast );
if( FBitSet( flags, SND_SENTENCE ))
sample = va( "!%i", idx );
else if( idx >= 0 && idx < MAX_SOUNDS )
sample = sv.sound_precache[idx];
if( !COM_CheckString( sample ))
{
Con_Printf( S_ERROR "%s: unrecognized sample in svc_spawnstaticsound, index %d, flags 0x%x\n", __func__, idx, flags );
return false;
}
MSG_SeekToBit( &sv.multicast, svgame.msg_rewrite_pos, SEEK_SET );
return SV_BuildSoundMsg( &sv.multicast, EDICT_NUM( ent ), CHAN_STATIC, sample, vol, attn, flags, pitch, origin );
}
return false;
}
/*
=============
pfnMessageBegin
@@ -2518,10 +2574,24 @@ static void GAME_EXPORT pfnMessageBegin( int msg_dest, int msg_num, const float
// check range
msg_num = bound( svc_bad, msg_num, 255 );
svgame.msg_rewrite_index = 0;
svgame.msg_rewrite_pos = 0;
if( msg_num <= svc_lastmsg )
{
svgame.msg_index = -msg_num; // this is a system message
svgame.msg_name = svc_strings[msg_num];
// check if we should rewrite this message into something else...
if( SV_CanRewriteMessage( msg_num ))
{
svgame.msg_index = -SV_CanRewriteMessage( msg_num );
svgame.msg_name = svc_goldsrc_strings[msg_num] ? svc_goldsrc_strings[msg_num] : svc_strings[msg_num];
svgame.msg_rewrite_index = msg_num;
svgame.msg_rewrite_pos = MSG_TellBit( &sv.multicast );
}
else
{
svgame.msg_index = -msg_num; // this is a system message
svgame.msg_name = svc_strings[msg_num];
}
if( msg_num == svc_temp_entity )
iSize = -1; // temp entity have variable size
@@ -2596,6 +2666,25 @@ static void GAME_EXPORT pfnMessageEnd( void )
return;
}
if( svgame.msg_rewrite_index != 0 )
{
if( SV_RewriteMessage( ))
{
if( MSG_CheckOverflow( &sv.multicast ))
{
Con_Printf( S_ERROR "MessageEnd: %s has overflow multicast buffer (post-rewrite)\n", name );
MSG_Clear( &sv.multicast );
return;
}
}
else
{
Con_Printf( S_ERROR "MessageEnd: failed to rewrite message %s\n", name );
MSG_Clear( &sv.multicast );
return;
}
}
// check for system message
if( svgame.msg_index < 0 )
{
@@ -2662,9 +2751,7 @@ static void GAME_EXPORT pfnMessageEnd( void )
// update some messages in case their was format was changed and we want to keep backward compatibility
if( svgame.msg_index < 0 )
{
int svc_msg = abs( svgame.msg_index );
if(( svc_msg == svc_finale || svc_msg == svc_cutscene ) && svgame.msg_realsize == 0 )
if(( svgame.msg_index == -svc_finale || svgame.msg_index == -svc_cutscene ) && svgame.msg_realsize == 0 )
MSG_WriteChar( &sv.multicast, 0 ); // write null string
}
@@ -4095,7 +4182,16 @@ void GAME_EXPORT SV_PlaybackEventFull( int flags, const edict_t *pInvoker, word
continue;
}
if( FBitSet( flags, FEV_NOTHOST ) && cl == sv.current_client && FBitSet( cl->flags, FCL_LOCAL_WEAPONS ))
// a1ba: GoldSrc never cleans up host_client pointer (similar to sv.current_client)
// so it's always points at some client and in singleplayer this check always succeedes
// in Xash, however, sv.current_client might be reset and set to NULL
// this is especially dangerous when weapons play events in Think functions
//
// IMHO, it doesn't make sense to me to compare it against current client when we have
// invoker edict pointer but to preserve behaviour check for them both
//
// if it breaks some mods, probably sv.current_client semantics must be reworked to match GoldSrc
if( FBitSet( flags, FEV_NOTHOST ) && ( cl == sv.current_client || cl->edict == pInvoker ) && FBitSet( cl->flags, FCL_LOCAL_WEAPONS ))
continue; // will be played on client side
if( FBitSet( flags, FEV_HOSTONLY ) && cl->edict != pInvoker )

View File

@@ -418,10 +418,8 @@ static void GAME_EXPORT pfnPlaybackEventFull( int flags, int clientindex, word e
ent = EDICT_NUM( clientindex + 1 );
if( !SV_IsValidEdict( ent )) return;
if( Host_IsDedicated() )
flags |= FEV_NOTHOST; // no local clients for dedicated server
SV_PlaybackEventFull( flags, ent, eventindex,
// GoldSrc always sets FEV_NOTHOST in PMove version of this function
SV_PlaybackEventFull( flags | FEV_NOTHOST, ent, eventindex,
delay, origin, angles,
fparam1, fparam2,
iparam1, iparam2,
@@ -590,7 +588,7 @@ static void SV_SetupPMove( playermove_t *pmove, sv_client_t *cl, usercmd_t *ucmd
pmove->cmd = *ucmd; // setup current cmds
pmove->runfuncs = true;
Q_strncpy( pmove->physinfo, physinfo, MAX_INFO_STRING );
Q_strncpy( pmove->physinfo, physinfo, sizeof( pmove->physinfo ));
// setup physents
pmove->numvisent = 0;

View File

@@ -652,7 +652,7 @@ static void DirectoryCopy( const char *pPath, file_t *pFile )
fileSize = FS_FileLength( pCopy );
memset( szName, 0, sizeof( szName )); // clearing the string to prevent garbage in output file
Q_strncpy( szName, COM_FileWithoutPath( t->filenames[i] ), MAX_OSPATH );
Q_strncpy( szName, COM_FileWithoutPath( t->filenames[i] ), sizeof( szName ));
FS_Write( pFile, szName, MAX_OSPATH );
FS_Write( pFile, &fileSize, sizeof( int ));
FS_FileCopy( pFile, pCopy, fileSize );
@@ -1202,7 +1202,7 @@ static void SaveClientState( SAVERESTOREDATA *pSaveData, const char *level, int
header.soundCount = S_GetCurrentDynamicSounds( soundInfo, MAX_CHANNELS );
#if !XASH_DEDICATED
// music not reqiured to save position: it's just continue playing on a next level
S_StreamGetCurrentState( header.introTrack, header.mainTrack, &header.trackPosition );
S_StreamGetCurrentState( header.introTrack, sizeof( header.introTrack ), header.mainTrack, sizeof( header.mainTrack ), &header.trackPosition );
#endif
}

View File

@@ -21,16 +21,16 @@ def options(opt):
help = 'enable custom swap allocator. For devices with no swap support')
grp.add_option('--enable-legacy-sdl', action = 'store_true', dest = 'SDL12', default = False,
help = 'enable using SDL1.2 instead of SDL2(not recommended) [default: %default]')
help = 'enable using SDL1.2 instead of SDL2(not recommended) [default: %(default)s]')
grp.add_option('--enable-static-binary', action = 'store_true', dest = 'STATIC', default = False,
help = 'build static binary(not recommended, --single-binary required) [default: %default]')
help = 'build static binary(not recommended, --single-binary required) [default: %(default)s]')
grp.add_option('--enable-engine-tests', action = 'store_true', dest = 'ENGINE_TESTS', default = False,
help = 'embed tests into the engine, jump into them by -runtests command line switch [default: %default]')
help = 'embed tests into the engine, jump into them by -runtests command line switch [default: %(default)s]')
grp.add_option('--enable-engine-fuzz', action = 'store_true', dest = 'ENGINE_FUZZ', default = False,
help = 'add LLVM libFuzzer [default: %default]' )
help = 'add LLVM libFuzzer [default: %(default)s]' )
opt.load('sdl2')

View File

@@ -2125,7 +2125,7 @@ fs_offset_t FS_Read( file_t *file, void *buffer, size_t buffersize )
{
fs_offset_t done;
fs_offset_t nb;
size_t count;
fs_offset_t count;
// nothing to copy
if( buffersize == 0 ) return 1;
@@ -2144,12 +2144,13 @@ fs_offset_t FS_Read( file_t *file, void *buffer, size_t buffersize )
if( file->buff_ind < file->buff_len )
{
count = file->buff_len - file->buff_ind;
count = ( buffersize > count ) ? count : (fs_offset_t)buffersize;
done += ( buffersize > count ) ? (fs_offset_t)count : (fs_offset_t)buffersize;
memcpy( buffer, &file->buff[file->buff_ind], done );
file->buff_ind += done;
done += count;
memcpy( buffer, &file->buff[file->buff_ind], count );
file->buff_ind += count;
buffersize -= done;
buffersize -= count;
if( buffersize == 0 )
return done;
}
@@ -2163,10 +2164,10 @@ fs_offset_t FS_Read( file_t *file, void *buffer, size_t buffersize )
// if we have a lot of data to get, put them directly into "buffer"
if( buffersize > sizeof( file->buff ) / 2 )
{
if( count > buffersize )
count = buffersize;
if( count > (fs_offset_t)buffersize )
count = (fs_offset_t)buffersize;
lseek( file->handle, file->offset + file->position, SEEK_SET );
nb = read( file->handle, (byte *)buffer + done, count );
nb = read( file->handle, &((byte *)buffer)[done], count );
if( nb > 0 )
{
@@ -2178,8 +2179,8 @@ fs_offset_t FS_Read( file_t *file, void *buffer, size_t buffersize )
}
else
{
if( count > sizeof( file->buff ))
count = sizeof( file->buff );
if( count > (fs_offset_t)sizeof( file->buff ))
count = (fs_offset_t)sizeof( file->buff );
lseek( file->handle, file->offset + file->position, SEEK_SET );
nb = read( file->handle, file->buff, count );

View File

@@ -12,7 +12,7 @@ def options(opt):
grp = opt.add_option_group('Game launcher options')
grp.add_option('--disable-menu-changegame', action = 'store_true', dest = 'DISABLE_MENU_CHANGEGAME', default = False,
help = 'disable changing the game from the menu [default: %default]')
help = 'disable changing the game from the menu [default: %(default)s]')
def configure(conf):
if conf.env.DEST_OS == 'win32':

View File

@@ -434,7 +434,7 @@ returns hash key for string
*/
uint COM_HashKey( const char *string, uint hashSize )
{
int hashKey = 5381;
uint hashKey = 5381;
unsigned char i;
while(( i = *string++ ))

View File

@@ -18,7 +18,6 @@ GNU General Public License for more details.
#include "const.h"
#include <math.h>
#include <stdarg.h>
#include <ctype.h>
#include <time.h>
#include "stdio.h"
#include "crtlib.h"
@@ -38,26 +37,6 @@ void Q_strnlwr( const char *in, char *out, size_t size_out )
*out = '\0';
}
qboolean Q_isdigit( const char *str )
{
if( str && *str )
{
while( isdigit( *str )) str++;
if( !*str ) return true;
}
return false;
}
qboolean Q_isspace( const char *str )
{
if( str && *str )
{
while( isspace( *str ) ) str++;
if( !*str ) return true;
}
return false;
}
size_t Q_colorstr( const char *string )
{
size_t len;
@@ -81,59 +60,6 @@ size_t Q_colorstr( const char *string )
return len;
}
char Q_toupper( const char in )
{
char out;
if( in >= 'a' && in <= 'z' )
out = in + 'A' - 'a';
else out = in;
return out;
}
char Q_tolower( const char in )
{
char out;
if( in >= 'A' && in <= 'Z' )
out = in + 'a' - 'A';
else out = in;
return out;
}
size_t Q_strncat( char *dst, const char *src, size_t size )
{
register char *d = dst;
register const char *s = src;
register size_t n = size;
size_t dlen;
if( !dst || !src || !size )
return 0;
// find the end of dst and adjust bytes left but don't go past end
while( n-- != 0 && *d != '\0' ) d++;
dlen = d - dst;
n = size - dlen;
if( n == 0 ) return( dlen + Q_strlen( s ));
while( *s != '\0' )
{
if( n != 1 )
{
*d++ = *s;
n--;
}
s++;
}
*d = '\0';
return( dlen + ( s - src )); // count does not include NULL
}
int Q_atoi( const char *str )
{
int val = 0;
@@ -253,13 +179,11 @@ float Q_atof( const char *str )
void Q_atov( float *vec, const char *str, size_t siz )
{
string buffer;
char *pstr, *pfront;
const char *pstr, *pfront;
int j;
Q_strncpy( buffer, str, sizeof( buffer ));
memset( vec, 0, sizeof( vec_t ) * siz );
pstr = pfront = buffer;
pstr = pfront = str;
for( j = 0; j < siz; j++ )
{
@@ -394,7 +318,7 @@ const char* Q_timestamp( int format )
return timestamp;
}
#if !defined( HAVE_STRCASESTR )
#if !HAVE_STRCASESTR
char *Q_stristr( const char *string, const char *string2 )
{
int c;
@@ -721,14 +645,14 @@ void COM_ReplaceExtension( char *path, const char *extension, size_t size )
COM_RemoveLineFeed
============
*/
void COM_RemoveLineFeed( char *str )
void COM_RemoveLineFeed( char *str, size_t bufsize )
{
while( *str != '\0' )
size_t i;
for( i = 0; i < bufsize && *str != '\0'; i++, str++ )
{
if( *str == '\r' || *str == '\n' )
*str = '\0';
++str;
}
}

View File

@@ -18,6 +18,7 @@ GNU General Public License for more details.
#include <string.h>
#include <stdarg.h>
#include <ctype.h>
#include "build.h"
#include "xash3d_types.h"
@@ -63,11 +64,6 @@ const char *Q_buildbranch( void );
void Q_strnlwr( const char *in, char *out, size_t size_out );
#define Q_strlen( str ) (( str ) ? strlen(( str )) : 0 )
size_t Q_colorstr( const char *string );
char Q_toupper( const char in );
char Q_tolower( const char in );
size_t Q_strncat( char *dst, const char *src, size_t siz );
qboolean Q_isdigit( const char *str );
qboolean Q_isspace( const char *str );
int Q_atoi( const char *str );
float Q_atof( const char *str );
void Q_atov( float *vec, const char *str, size_t siz );
@@ -90,7 +86,7 @@ void COM_ReplaceExtension( char *path, const char *extension, size_t size );
void COM_ExtractFilePath( const char *path, char *dest );
const char *COM_FileWithoutPath( const char *in );
void COM_StripExtension( char *path );
void COM_RemoveLineFeed( char *str );
void COM_RemoveLineFeed( char *str, size_t bufsize );
void COM_FixSlashes( char *pname );
void COM_PathSlashFix( char *path );
char COM_Hex2Char( uint8_t hex );
@@ -103,91 +99,186 @@ char *COM_ParseFileSafe( char *data, char *token, const int size, unsigned int f
int matchpattern( const char *in, const char *pattern, qboolean caseinsensitive );
int matchpattern_with_separator( const char *in, const char *pattern, qboolean caseinsensitive, const char *separators, qboolean wildcard_least_one );
// libc implementations
static inline char Q_toupper( const char in )
{
char out;
if( in >= 'a' && in <= 'z' )
out = in + 'A' - 'a';
else out = in;
return out;
}
static inline char Q_tolower( const char in )
{
char out;
if( in >= 'A' && in <= 'Z' )
out = in + 'a' - 'A';
else out = in;
return out;
}
static inline qboolean Q_isdigit( const char *str )
{
if( likely( str && *str ))
{
while( isdigit( *str )) str++;
if( !*str ) return true;
}
return false;
}
static inline qboolean Q_isspace( const char *str )
{
if( likely( str && *str ))
{
while( isspace( *str ) ) str++;
if( !*str ) return true;
}
return false;
}
static inline int Q_strcmp( const char *s1, const char *s2 )
{
return unlikely(!s1) ?
( !s2 ? 0 : -1 ) :
( unlikely(!s2) ? 1 : strcmp( s1, s2 ));
if( likely( s1 && s2 ))
return strcmp( s1, s2 );
return ( s1 ? 1 : 0 ) - ( s2 ? 1 : 0 );
}
static inline int Q_strncmp( const char *s1, const char *s2, size_t n )
{
return unlikely(!s1) ?
( !s2 ? 0 : -1 ) :
( unlikely(!s2) ? 1 : strncmp( s1, s2, n ));
if( likely( s1 && s2 ))
return strncmp( s1, s2, n );
return ( s1 ? 1 : 0 ) - ( s2 ? 1 : 0 );
}
static inline char *Q_strstr( const char *s1, const char *s2 )
{
return unlikely( !s1 || !s2 ) ? NULL : (char*)strstr( s1, s2 );
if( likely( s1 && s2 ))
return (char *)strstr( s1, s2 );
return NULL;
}
// Q_strncpy is the same as strlcpy
static inline size_t Q_strncpy( char *dst, const char *src, size_t siz )
// libc extensions, be careful what to enable or what not
static inline size_t Q_strncpy( char *dst, const char *src, size_t size )
{
#if HAVE_STRLCPY
if( unlikely( !dst || !src || !size ))
return 0;
return strlcpy( dst, src, size );
#else
size_t len;
if( unlikely( !dst || !src || !siz ))
if( unlikely( !dst || !src || !size ))
return 0;
len = strlen( src );
if( len + 1 > siz ) // check if truncate
if( len + 1 > size ) // check if truncate
{
memcpy( dst, src, siz - 1 );
dst[siz - 1] = 0;
memcpy( dst, src, size - 1 );
dst[size - 1] = 0;
}
else memcpy( dst, src, len + 1 );
return len; // count does not include NULL
#endif
}
// libc extensions, be careful
static inline size_t Q_strncat( char *dst, const char *src, size_t size )
{
#if HAVE_STRLCAT
if( unlikely( !dst || !src || !size ))
return 0;
return strlcat( dst, src, size );
#else
char *d = dst;
const char *s = src;
size_t n = size;
size_t dlen;
#if XASH_WIN32
#define strcasecmp stricmp
#define strncasecmp strnicmp
#endif // XASH_WIN32
if( unlikely( !dst || !src || !size ))
return 0;
// find the end of dst and adjust bytes left but don't go past end
while( n-- != 0 && *d != '\0' ) d++;
dlen = d - dst;
n = size - dlen;
if( n == 0 ) return( dlen + Q_strlen( s ));
while( *s != '\0' )
{
if( n != 1 )
{
*d++ = *s;
n--;
}
s++;
}
*d = '\0';
return( dlen + ( s - src )); // count does not include NULL
#endif
}
#if HAVE_STRICMP || HAVE_STRCASECMP
static inline int Q_stricmp( const char *s1, const char *s2 )
{
return unlikely(!s1) ?
( !s2 ? 0 : -1 ) :
( unlikely(!s2) ? 1 : strcasecmp( s1, s2 ));
if( likely( s1 && s2 ))
{
#if HAVE_STRICMP
return stricmp( s1, s2 );
#elif HAVE_STRCASECMP
return strcasecmp( s1, s2 );
#endif
}
return ( s1 ? 1 : 0 ) - ( s2 ? 1 : 0 );
}
#else
int Q_stricmp( const char *s1, const char *s2 );
#endif
#if HAVE_STRICMP || HAVE_STRCASECMP
static inline int Q_strnicmp( const char *s1, const char *s2, size_t n )
{
return unlikely(!s1) ?
( !s2 ? 0 : -1 ) :
( unlikely(!s2) ? 1 : strncasecmp( s1, s2, n ));
}
#if defined( HAVE_STRCASESTR )
#if XASH_WIN32
#define strcasestr stristr
if( likely( s1 && s2 ))
{
#if HAVE_STRICMP
return strnicmp( s1, s2, n );
#elif HAVE_STRCASECMP
return strncasecmp( s1, s2, n );
#endif
}
return ( s1 ? 1 : 0 ) - ( s2 ? 1 : 0 );
}
#else
int Q_strnicmp( const char *s1, const char *s2, size_t n );
#endif
#if HAVE_STRCASESTR
static inline char *Q_stristr( const char *s1, const char *s2 )
{
return unlikely( !s1 || !s2 ) ? NULL : (char *)strcasestr( s1, s2 );
if( likely( s1 && s2 ))
return (char *)strcasestr( s1, s2 );
return NULL;
}
#else // defined( HAVE_STRCASESTR )
#else // !HAVE_STRCASESTR
char *Q_stristr( const char *s1, const char *s2 );
#endif // defined( HAVE_STRCASESTR )
#endif // !HAVE_STRCASESTR
#if defined( HAVE_STRCHRNUL )
#if HAVE_STRCHRNUL
#define Q_strchrnul strchrnul
#else
#else // !HAVE_STRCHRNUL
static inline const char *Q_strchrnul( const char *s, int c )
{
const char *p = Q_strchr( s, c );
if( p )
return p;
if( p ) return p;
return s + Q_strlen( s );
}
#endif
#endif // !HAVE_STRCHRNUL
#ifdef __cplusplus
}

View File

@@ -205,3 +205,42 @@ size_t Q_UTF16ToUTF8( char *dst, size_t dstsize, const uint16_t *src, size_t src
return dsti;
}
static uint16_t table_cp1251[64] = {
0x0402, 0x0403, 0x201A, 0x0453, 0x201E, 0x2026, 0x2020, 0x2021,
0x20AC, 0x2030, 0x0409, 0x2039, 0x040A, 0x040C, 0x040B, 0x040F,
0x0452, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
0x007F, 0x2122, 0x0459, 0x203A, 0x045A, 0x045C, 0x045B, 0x045F,
0x00A0, 0x040E, 0x045E, 0x0408, 0x00A4, 0x0490, 0x00A6, 0x00A7,
0x0401, 0x00A9, 0x0404, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x0407,
0x00B0, 0x00B1, 0x0406, 0x0456, 0x0491, 0x00B5, 0x00B6, 0x00B7,
0x0451, 0x2116, 0x0454, 0x00BB, 0x0458, 0x0405, 0x0455, 0x0457
};
uint32_t Q_UnicodeToCP1251( uint32_t uc )
{
size_t i;
if( uc < 0x80 )
return uc;
if( uc >= 0x0410 && uc <= 0x042F )
return uc - 0x410 + 0xC0;
if( uc >= 0x0430 && uc <= 0x044F )
return uc - 0x430 + 0xE0;
for( i = 0; i < sizeof( table_cp1251 ) / sizeof( table_cp1251[0] ); i++ )
{
if( uc == (uint32_t)table_cp1251[i] )
return i + 0x80;
}
return '?';
}
uint32_t Q_UnicodeToCP1252( uint32_t uc )
{
// this is NOT valid way to convert Unicode codepoint back to CP1252!!!
return uc < 0xFF ? uc : '?';
}

View File

@@ -37,4 +37,8 @@ size_t Q_UTF8Length( const char *s );
// srcsize in byte pairs
size_t Q_UTF16ToUTF8( char *dst, size_t dstsize, const uint16_t *src, size_t srcsize );
// function to convert Unicode codepoints into CP1251 or CP1252
uint32_t Q_UnicodeToCP1251( uint32_t uc );
uint32_t Q_UnicodeToCP1252( uint32_t uc );
#endif // UTFLIB_H

View File

@@ -2,22 +2,110 @@
# encoding: utf-8
# mittorn, 2018
from waflib import Logs
from waflib import Logs, Configure
import os
top = '.'
TGMATH_H_TEST = '''#include <tgmath.h>
const float val = 2, val2 = 3;
int main(void){ return (int)(-asin(val) + cos(val2)); }'''
STRNCASECMP_TEST = '''#include <string.h>
int main(int argc, char **argv) { return strncasecmp(argv[1], argv[2], 10); }'''
STRCASECMP_TEST = '''#include <string.h>
int main(int argc, char **argv) { return strcasecmp(argv[1], argv[2]); }'''
STRCASESTR_TEST = '''#include <string.h>
int main(int argc, char **argv) { argv[0] = strcasestr(argv[1], argv[2]); return 0; }'''
STRCHRNUL_TEST = '''#include <string.h>
int main(int argc, char **argv) { argv[2] = strchrnul(argv[1], 'x'); return 0; }'''
STRLCPY_TEST = '''#include <string.h>
int main(int argc, char **argv) { return strlcpy(argv[1], argv[2], 10); }'''
STRLCAT_TEST = '''#include <string.h>
int main(int argc, char **argv) { return strlcat(argv[1], argv[2], 10); }'''
ALLOCA_TEST = '''#include <%s>
int main(void) { alloca(1); return 0; }'''
HEADER_TEST = '''#include <%s>
int main(void) { return 0; }
'''
def options(opt):
# stub
return
def header_frag(header_name):
return '#include <%s>' % header_name + EMPTY_PROGRAM
@Configure.conf
def export_define(conf, define, value=1):
if not value:
return
if value is True:
value = 1 # so python won't define it as string True
conf.env.EXPORT_DEFINES_LIST += ['%s=%s' % (define, value)]
@Configure.conf
def simple_check(conf, fragment, msg, mandatory=False, **kw):
return conf.check_cc(fragment=fragment, msg='Checking for %s' % msg, mandatory=mandatory, **kw)
def configure(conf):
# private to libpublic
conf.load('gitversion')
conf.define('XASH_BUILD_COMMIT', conf.env.GIT_VERSION if conf.env.GIT_VERSION else 'unknown-commit')
conf.define('XASH_BUILD_BRANCH', conf.env.GIT_BRANCH if conf.env.GIT_BRANCH else 'unknown-branch')
# need to expose it for everyone using libpublic headers
conf.env.EXPORT_DEFINES_LIST = []
conf.export_define('_CRT_SILENCE_NONCONFORMING_TGMATH_H', conf.env.COMPILER_CC == 'msvc')
conf.export_define('_GNU_SOURCE', conf.env.DEST_OS != 'win32')
# create temporary uselib that just enables extensions
conf.env.DEFINES_export = list(conf.env.EXPORT_DEFINES_LIST)
# check platform-specific header name for alloca(3)
if conf.simple_check(ALLOCA_TEST % 'alloca.h', msg='alloca in alloca.h'):
conf.export_define('ALLOCA_H', '<alloca.h>')
elif conf.simple_check(ALLOCA_TEST % 'malloc.h', msg='alloca in malloc.h'):
conf.export_define('ALLOCA_H', '<malloc.h>')
elif conf.simple_check(ALLOCA_TEST % 'stdlib.h', msg='alloca in stdlib.h'):
conf.export_define('ALLOCA_H', '<stdlib.h>')
conf.export_define('STDINT_H', '<stdint.h>' if conf.simple_check(HEADER_TEST % 'stdint.h', 'stdint.h') else '<pstdint.h>')
conf.export_define('HAVE_TGMATH_H', conf.simple_check(TGMATH_H_TEST, 'tgmath.h', use='M werror export'))
# save some time on Windows, msvc is too slow
# these calls must be available with both msvc and mingw
if conf.env.DEST_OS == 'win32':
conf.export_define('HAVE_STRNICMP')
conf.export_define('HAVE_STRICMP')
else:
# TODO: multicheck for speed
def check_libc_extension(frag, msg, define):
conf.export_define(define, conf.simple_check(frag, msg, use='werror export'))
check_libc_extension(STRNCASECMP_TEST, 'strncasecmp', 'HAVE_STRNCASECMP')
check_libc_extension(STRCASECMP_TEST, 'strcasecmp', 'HAVE_STRCASECMP')
check_libc_extension(STRCASESTR_TEST, 'strcasestr', 'HAVE_STRCASESTR')
check_libc_extension(STRCHRNUL_TEST, 'strchrnul', 'HAVE_STRCHRNUL')
check_libc_extension(STRLCPY_TEST, 'strlcpy', 'HAVE_STRLCPY')
check_libc_extension(STRLCAT_TEST, 'strlcat', 'HAVE_STRLCAT')
# kill temporary uselib
del conf.env.DEFINES_export
def build(bld):
bld(name = 'sdk_includes', export_includes = '. ../common ../pm_shared ../engine')
bld(name = 'sdk_includes',
export_includes = '. ../common ../pm_shared ../engine',
export_defines = bld.env.EXPORT_DEFINES_LIST)
bld.stlib(source = bld.path.ant_glob('*.c'),
target = 'public',
features = 'c',

View File

@@ -34,7 +34,6 @@ Limitations:
#include "gl_local.h"
#ifndef XASH_GL_STATIC
#include "gl2_shim.h"
#include ALLOCA_H
#define MAX_SHADERLEN 4096
// increase this when adding more attributes

View File

@@ -64,7 +64,16 @@ Opaque entity can be brush or studio model but sprite
qboolean R_OpaqueEntity( cl_entity_t *ent )
{
if( R_GetEntityRenderMode( ent ) == kRenderNormal )
return true;
{
switch( ent->curstate.renderfx )
{
case kRenderFxNone:
case kRenderFxDeadPlayer:
case kRenderFxLightMultiplier:
case kRenderFxExplode:
return true;
}
}
return false;
}

View File

@@ -3560,6 +3560,19 @@ static void R_StudioDrawModelInternal( cl_entity_t *e, int flags )
}
}
static cl_entity_t *R_FindParentEntity( cl_entity_t *e, cl_entity_t **entities, uint num_entities )
{
uint i;
for( i = 0; i < num_entities; i++ )
{
if( entities[i]->index == e->curstate.aiment )
return entities[i];
}
return NULL;
}
/*
=================
R_DrawStudioModel
@@ -3576,38 +3589,27 @@ void R_DrawStudioModel( cl_entity_t *e )
{
R_StudioDrawModelInternal( e, STUDIO_RENDER|STUDIO_EVENTS );
}
else if( e->curstate.movetype == MOVETYPE_FOLLOW && e->curstate.aiment > 0 )
else if( e->curstate.movetype == MOVETYPE_FOLLOW )
{
cl_entity_t *parent = CL_GetEntityByIndex( e->curstate.aiment ), **entities;
uint i, num_entities;
cl_entity_t *parent = CL_GetEntityByIndex( e->curstate.aiment );
if( !parent || !parent->model || parent->model->type != mod_studio )
return;
if( R_OpaqueEntity( parent ))
{
entities = tr.draw_list->solid_entities;
num_entities = tr.draw_list->num_solid_entities;
}
else
{
entities = tr.draw_list->trans_entities;
num_entities = tr.draw_list->num_solid_entities;
}
parent = R_FindParentEntity( e, tr.draw_list->solid_entities, tr.draw_list->num_solid_entities );
for( i = 0; i < num_entities; i++ )
{
if( (*entities)[i].index != e->curstate.aiment )
continue;
if( !parent )
parent = R_FindParentEntity( e, tr.draw_list->trans_entities, tr.draw_list->num_trans_entities );
RI.currententity = &(*entities)[i];
if( parent )
{
RI.currententity = parent;
R_StudioDrawModelInternal( RI.currententity, 0 );
VectorCopy( RI.currententity->curstate.origin, e->curstate.origin );
VectorCopy( RI.currententity->origin, e->origin );
RI.currententity = e;
R_StudioDrawModelInternal( e, STUDIO_RENDER|STUDIO_EVENTS );
break;
}
}
else

View File

@@ -11,7 +11,7 @@ def options(opt):
grp = opt.add_option_group('ref_gl options')
grp.add_option('--enable-static-gl', action='store_true', dest='GL_STATIC', default=False,
help = 'enable direct linking to opengl [default: %default]')
help = 'enable direct linking to opengl [default: %(default)s]')
# stub
return

View File

@@ -57,8 +57,8 @@ int r_screenwidth;
int r_viewcluster, r_oldviewcluster;
CVAR_DEFINE_AUTO( sw_clearcolor, "48999", 0, "screen clear color");
CVAR_DEFINE_AUTO( sw_drawflat, "0", 0, "");
CVAR_DEFINE_AUTO( sw_draworder, "0", 0, "");
CVAR_DEFINE_AUTO( sw_drawflat, "0", FCVAR_CHEAT, "");
CVAR_DEFINE_AUTO( sw_draworder, "0", FCVAR_CHEAT, "");
CVAR_DEFINE_AUTO( sw_maxedges, "32", 0, "");
static CVAR_DEFINE_AUTO( sw_maxsurfs, "0", 0, "");
CVAR_DEFINE_AUTO( sw_mipscale, "1", FCVAR_GLCONFIG, "nothing");
@@ -150,7 +150,16 @@ qboolean R_OpaqueEntity( cl_entity_t *ent )
int rendermode = R_GetEntityRenderMode( ent );
if( rendermode == kRenderNormal )
return true;
{
switch( ent->curstate.renderfx )
{
case kRenderFxNone:
case kRenderFxDeadPlayer:
case kRenderFxLightMultiplier:
case kRenderFxExplode:
return true;
}
}
if( sw_notransbrushes.value && ent->model && ent->model->type == mod_brush && rendermode == kRenderTransTexture )
return true;

View File

@@ -3326,6 +3326,19 @@ static void R_StudioDrawModelInternal( cl_entity_t *e, int flags )
}
}
static cl_entity_t *R_FindParentEntity( cl_entity_t *e, cl_entity_t **entities, uint num_entities )
{
uint i;
for( i = 0; i < num_entities; i++ )
{
if( entities[i]->index == e->curstate.aiment )
return entities[i];
}
return NULL;
}
/*
=================
R_DrawStudioModel
@@ -3342,38 +3355,27 @@ void R_DrawStudioModel( cl_entity_t *e )
{
R_StudioDrawModelInternal( e, STUDIO_RENDER|STUDIO_EVENTS );
}
else if( e->curstate.movetype == MOVETYPE_FOLLOW && e->curstate.aiment > 0 )
else if( e->curstate.movetype == MOVETYPE_FOLLOW )
{
cl_entity_t *parent = CL_GetEntityByIndex( e->curstate.aiment ), **entities;
uint i, num_entities;
cl_entity_t *parent = CL_GetEntityByIndex( e->curstate.aiment );
if( !parent || !parent->model || parent->model->type != mod_studio )
return;
if( R_OpaqueEntity( parent ))
{
entities = tr.draw_list->solid_entities;
num_entities = tr.draw_list->num_solid_entities;
}
else
{
entities = tr.draw_list->trans_entities;
num_entities = tr.draw_list->num_solid_entities;
}
parent = R_FindParentEntity( e, tr.draw_list->solid_entities, tr.draw_list->num_solid_entities );
for( i = 0; i < num_entities; i++ )
{
if( (*entities)[i].index != e->curstate.aiment )
continue;
if( !parent )
parent = R_FindParentEntity( e, tr.draw_list->trans_entities, tr.draw_list->num_trans_entities );
RI.currententity = &(*entities)[i];
if( parent )
{
RI.currententity = parent;
R_StudioDrawModelInternal( RI.currententity, 0 );
VectorCopy( RI.currententity->curstate.origin, e->curstate.origin );
VectorCopy( RI.currententity->origin, e->origin );
RI.currententity = e;
R_StudioDrawModelInternal( e, STUDIO_RENDER|STUDIO_EVENTS );
break;
}
}
else

View File

@@ -52,12 +52,12 @@ build_engine()
if [ "$1" = "dedicated" ]; then
./waf configure -T release -d $AMD64 --enable-tests --enable-lto || die_configure
elif [ "$1" = "full" ]; then
./waf configure --sdl2=SDL2_linux -T release --enable-stb $AMD64 --enable-utils --enable-tests --enable-lto || die_confgure
./waf configure --sdl2=SDL2_linux -T release --enable-stb $AMD64 --enable-utils --enable-tests --enable-lto || die_configure
else
die
fi
./waf build || die
./waf build || die_configure
}
build_appimage()

View File

@@ -137,10 +137,8 @@ def options(opt):
:param opt: Options context from the *waf* build environment.
:type opt: waflib.Options.OptionsContext
'''
opt.add_option('--cmake', dest='cmake', default=False,
action='store_true', help='select cmake for export/import actions')
opt.add_option('--clean', dest='clean', default=False,
action='store_true', help='delete exported files')
opt.add_option('--cmake', dest='cmake', default=False, action='store_true', help='select cmake for export/import actions')
opt.add_option('--cmake-clean', dest='cmake_clean', default=False, action='store_true', help='delete exported cmake files')
def configure(conf):
@@ -179,7 +177,7 @@ class CMakeContext(BuildContext):
pass
self.cmake = True
if self.options.clean:
if self.options.cmake_clean:
cleanup(self)
else:
export(self)
@@ -224,7 +222,7 @@ def cleanup(bld):
:param bld: a *waf* build instance from the top level *wscript*.
:type bld: waflib.Build.BuildContext
'''
if not bld.options.clean:
if not bld.options.cmake_clean:
return
loc = bld.path.relpath().replace('\\', '/')

View File

@@ -121,6 +121,17 @@ POLLY_CFLAGS = {
# msvc sosat :(
}
OPENMP_CFLAGS = {
'gcc': ['-fopenmp'],
'clang': ['-fopenmp'],
'msvc': ['/openmp']
}
OPENMP_LINKFLAGS = {
'gcc': ['-fopenmp'],
'clang': ['-fopenmp'],
}
PROFILE_GENERATE_CFLAGS = {
'gcc': ['-fprofile-generate=xash3d-prof'],
}
@@ -144,16 +155,19 @@ def options(opt):
help = 'build type: debug, release or none(custom flags)')
grp.add_option('--enable-lto', action = 'store_true', dest = 'LTO', default = False,
help = 'enable Link Time Optimization if possible [default: %default]')
help = 'enable Link Time Optimization if possible [default: %(default)s]')
grp.add_option('--enable-poly-opt', action = 'store_true', dest = 'POLLY', default = False,
help = 'enable polyhedral optimization if possible [default: %default]')
help = 'enable polyhedral optimization if possible [default: %(default)s]')
grp.add_option('--enable-openmp', action = 'store_true', dest = 'OPENMP', default = False,
help = 'enable OpenMP extensions [default: %(default)s]')
grp.add_option('--enable-profile', action = 'store_true', dest = 'PROFILE_GENERATE', default = False,
help = 'enable profile generating build (stored in xash3d-prof directory) [default: %default]')
help = 'enable profile generating build (stored in xash3d-prof directory) [default: %(default)s]')
grp.add_option('--use-profile', action = 'store', dest = 'PROFILE_USE', default = None,
help = 'use profile during build [default: %default]')
help = 'use profile during build [default: %(default)s]')
def configure(conf):
conf.start_msg('Build type')
@@ -171,6 +185,7 @@ def configure(conf):
conf.msg('LTO build', 'yes' if conf.options.LTO else 'no')
conf.msg('PolyOpt build', 'yes' if conf.options.POLLY else 'no')
conf.msg('OpenMP build', 'yes' if conf.options.OPENMP else 'no')
conf.msg('Generate profile', 'yes' if conf.options.PROFILE_GENERATE else 'no')
conf.msg('Use profile', conf.options.PROFILE_USE if not conf.options.PROFILE_GENERATE else 'no')
@@ -203,6 +218,10 @@ def get_optimization_flags(conf):
if conf.options.POLLY:
cflags += conf.get_flags_by_compiler(POLLY_CFLAGS, conf.env.COMPILER_CC)
if conf.options.OPENMP:
linkflags+= conf.get_flags_by_compiler(OPENMP_LINKFLAGS, conf.env.COMPILER_CC)
cflags += conf.get_flags_by_compiler(OPENMP_CFLAGS, conf.env.COMPILER_CC)
if conf.options.PROFILE_GENERATE:
linkflags+= conf.get_flags_by_compiler(PROFILE_GENERATE_LINKFLAGS, conf.env.COMPILER_CC)
cflags += conf.get_flags_by_compiler(PROFILE_GENERATE_CFLAGS, conf.env.COMPILER_CC)

View File

@@ -17,10 +17,10 @@ def options(opt):
vgui_dev_path = os.path.join(opt.path.path_from(opt.root), 'vgui-dev')
grp.add_option('--vgui', action = 'store', dest = 'VGUI_DEV', default=vgui_dev_path,
help = 'path to vgui-dev repo [default: %default]')
help = 'path to vgui-dev repo [default: %(default)s]')
grp.add_option('--skip-vgui-sanity-check', action = 'store_false', dest = 'VGUI_SANITY_CHECK', default=True,
help = 'skip checking VGUI sanity [default: %default]' )
help = 'skip checking VGUI sanity [default: %(default)s]' )
return
@conf

View File

@@ -503,13 +503,13 @@ def options(opt):
xc.add_option('--android', action='store', dest='ANDROID_OPTS', default=None,
help='enable building for android, format: --android=<arch>,<toolchain>,<api>, example: --android=armeabi-v7a-hard,4.9,9')
xc.add_option('--enable-magx', action='store_true', dest='MAGX', default=False,
help='enable building for Motorola MAGX [default: %default]')
help='enable building for Motorola MAGX [default: %(default)s]')
xc.add_option('--enable-msvc-wine', action='store_true', dest='MSVC_WINE', default=False,
help='enable building with MSVC using Wine [default: %default]')
help='enable building with MSVC using Wine [default: %(default)s]')
xc.add_option('--nswitch', action='store_true', dest='NSWITCH', default = False,
help='enable building for Nintendo Switch [default: %default]')
help='enable building for Nintendo Switch [default: %(default)s]')
xc.add_option('--psvita', action='store_true', dest='PSVITA', default = False,
help='enable building for PlayStation Vita [default: %default]')
help='enable building for PlayStation Vita [default: %(default)s]')
xc.add_option('--sailfish', action='store', dest='SAILFISH', default = None,
help='enable building for Sailfish/Aurora')

View File

@@ -79,7 +79,7 @@ qboolean LoadActivityList( const char *appname )
return false;
}
COM_RemoveLineFeed( buf );
COM_RemoveLineFeed( buf, sizeof( buf ));
activity_names[activity_count - 1] = strdup( buf );

View File

@@ -7,7 +7,7 @@ def options(opt):
grp = opt.get_option_group('Utilities options')
grp.add_option('--disable-utils-mdldec', action = 'store_true', dest = 'DISABLE_UTILS_MDLDEC', default = False,
help = 'disable studio model decompiler utility [default: %default]')
help = 'disable studio model decompiler utility [default: %(default)s]')
def configure(conf):
conf.env.DISABLE_UTILS_MDLDEC = conf.options.DISABLE_UTILS_MDLDEC

20
waf vendored

File diff suppressed because one or more lines are too long

88
wscript
View File

@@ -3,7 +3,7 @@
# a1batross, mittorn, 2018
from waflib import Build, Context, Logs
from waflib.Tools import waf_unit_test
from waflib.Tools import waf_unit_test, c_tests
import sys
import os
@@ -14,6 +14,9 @@ default_prefix = '/' # Waf uses it to set default prefix
Context.Context.line_just = 55 # should fit for everything on 80x26
c_tests.LARGE_FRAGMENT='''#include <unistd.h>
int check[sizeof(off_t) >= 8 ? 1 : -1]; int main(void) { return 0; }'''
class Subproject:
def __init__(self, name, fnFilter = None):
self.name = name
@@ -50,7 +53,7 @@ class RefDll:
kw['dest'] = self.dest
kw['default'] = self.default
kw['help'] = '%s %s renderer [default: %%default]' % (act, self.name)
kw['help'] = '%s %s renderer [default: %%(default)s]' % (act, self.name)
opt.add_option(key, **kw)
@@ -105,36 +108,36 @@ REFDLLS = [
]
def options(opt):
opt.load('reconfigure compiler_optimizations xshlib xcompile compiler_cxx compiler_c sdl2 clang_compilation_database strip_on_install waf_unit_test msdev msvs msvc subproject cmake')
opt.load('reconfigure compiler_optimizations xshlib xcompile compiler_cxx compiler_c sdl2 clang_compilation_database strip_on_install waf_unit_test msdev msvs subproject cmake')
grp = opt.add_option_group('Common options')
grp.add_option('-d', '--dedicated', action = 'store_true', dest = 'DEDICATED', default = False,
help = 'build Xash Dedicated Server [default: %default]')
help = 'build Xash Dedicated Server [default: %(default)s]')
grp.add_option('--gamedir', action = 'store', dest = 'GAMEDIR', default = 'valve',
help = 'engine default game directory [default: %default]')
help = 'engine default game directory [default: %(default)s]')
grp.add_option('-8', '--64bits', action = 'store_true', dest = 'ALLOW64', default = False,
help = 'allow targetting 64-bit engine(Linux/Windows/OSX x86 only) [default: %default]')
help = 'allow targetting 64-bit engine(Linux/Windows/OSX x86 only) [default: %(default)s]')
grp.add_option('-P', '--enable-packaging', action = 'store_true', dest = 'PACKAGING', default = False,
help = 'respect prefix option, useful for packaging for various operating systems [default: %default]')
help = 'respect prefix option, useful for packaging for various operating systems [default: %(default)s]')
grp.add_option('--enable-bundled-deps', action = 'store_true', dest = 'BUILD_BUNDLED_DEPS', default = False,
help = 'prefer to build bundled dependencies (like opus) instead of relying on system provided')
grp.add_option('--enable-bsp2', action = 'store_true', dest = 'SUPPORT_BSP2_FORMAT', default = False,
help = 'build engine and renderers with BSP2 map support(recommended for Quake, breaks compatibility!) [default: %default]')
help = 'build engine and renderers with BSP2 map support(recommended for Quake, breaks compatibility!) [default: %(default)s]')
grp.add_option('--low-memory-mode', action = 'store', dest = 'LOW_MEMORY', default = 0, type = 'int',
grp.add_option('--low-memory-mode', action = 'store', dest = 'LOW_MEMORY', default = 0, type = int,
help = 'enable low memory mode (only for devices have <128 ram)')
grp.add_option('--disable-werror', action = 'store_true', dest = 'DISABLE_WERROR', default = False,
help = 'disable compilation abort on warning')
grp.add_option('--enable-tests', action = 'store_true', dest = 'TESTS', default = False,
help = 'enable building standalone tests (does not enable engine tests!) [default: %default]')
help = 'enable building standalone tests (does not enable engine tests!) [default: %(default)s]')
# a1ba: special option for me
grp.add_option('--debug-all-servers', action='store_true', dest='ALL_SERVERS', default=False, help='')
@@ -142,7 +145,7 @@ def options(opt):
grp = opt.add_option_group('Renderers options')
grp.add_option('--enable-all-renderers', action='store_true', dest='ALL_RENDERERS', default=False,
help = 'enable all renderers supported by Xash3D FWGS [default: %default]')
help = 'enable all renderers supported by Xash3D FWGS [default: %(default)s]')
for dll in REFDLLS:
dll.register_option(grp)
@@ -150,10 +153,10 @@ def options(opt):
grp = opt.add_option_group('Utilities options')
grp.add_option('--enable-utils', action = 'store_true', dest = 'ENABLE_UTILS', default = False,
help = 'enable building various development utilities [default: %default]')
help = 'enable building various development utilities [default: %(default)s]')
grp.add_option('--enable-fuzzer', action = 'store_true', dest = 'ENABLE_FUZZER', default = False,
help = 'enable building libFuzzer runner [default: %default]' )
help = 'enable building libFuzzer runner [default: %(default)s]' )
for i in SUBDIRS:
if not i.is_exists(opt):
@@ -379,18 +382,6 @@ def configure(conf):
conf.define('XASH_GAMEDIR', conf.options.GAMEDIR)
conf.define_cond('XASH_ALL_SERVERS', conf.options.ALL_SERVERS)
# check if we can use C99 stdint
conf.define('STDINT_H', 'stdint.h' if conf.check_cc(header_name='stdint.h', mandatory=False) else 'pstdint.h')
# check if we can use alloca.h or malloc.h
if conf.check_cc(header_name='alloca.h', mandatory=False):
conf.define('ALLOCA_H', 'alloca.h')
elif conf.check_cc(header_name='malloc.h', mandatory=False):
conf.define('ALLOCA_H', 'malloc.h')
elif conf.check_cc(fragment = '''#include <stdlib.h>
int main(void) { alloca(1); }''', msg = 'Checking for alloca in stdlib.h'):
conf.define('ALLOCA_H', 'stdlib.h')
if conf.env.DEST_OS == 'nswitch':
conf.check_cfg(package='solder', args='--cflags --libs', uselib_store='SOLDER')
if conf.env.HAVE_SOLDER and conf.env.LIB_SOLDER and conf.options.BUILD_TYPE == 'debug':
@@ -422,53 +413,12 @@ def configure(conf):
conf.check_cc(lib='m')
# check if we can use C99 tgmath
if conf.check_cc(header_name='tgmath.h', mandatory=False):
if conf.env.COMPILER_CC == 'msvc':
conf.define('_CRT_SILENCE_NONCONFORMING_TGMATH_H', 1)
tgmath_usable = conf.check_cc(fragment='''#include<tgmath.h>
const float val = 2, val2 = 3;
int main(void){ return (int)(-asin(val) + cos(val2)); }''',
msg='Checking if tgmath.h is usable', mandatory=False, use='M werror')
conf.define_cond('HAVE_TGMATH_H', tgmath_usable)
else:
conf.undefine('HAVE_TGMATH_H')
# set _FILE_OFFSET_BITS=64 for filesystems with 64-bit inodes
if conf.env.DEST_OS != 'win32' and conf.env.DEST_SIZEOF_VOID_P == 4:
# check was borrowed from libarchive source code
file_offset_bits_usable = conf.check_cc(fragment='''
#define _FILE_OFFSET_BITS 64
#include <sys/types.h>
#define KB ((off_t)1024)
#define MB ((off_t)1024 * KB)
#define GB ((off_t)1024 * MB)
#define TB ((off_t)1024 * GB)
int t2[(((64 * GB -1) % 671088649) == 268434537)
&& (((TB - (64 * GB -1) + 255) % 1792151290) == 305159546)? 1: -1];
int main(void) { return 0; }''',
msg='Checking if _FILE_OFFSET_BITS can be defined to 64', mandatory=False, use='werror')
if file_offset_bits_usable:
conf.define('_FILE_OFFSET_BITS', 64)
else: conf.undefine('_FILE_OFFSET_BITS')
if conf.env.DEST_OS != 'win32':
strcasestr_frag = '''#include <string.h>
int main(int argc, char **argv) { strcasestr(argv[1], argv[2]); return 0; }'''
strchrnul_frag = '''#include <string.h>
int main(int argc, char **argv) { strchrnul(argv[1], 'x'); return 0; }'''
def check_gnu_function(frag, msg, define):
if conf.check_cc(msg=msg, mandatory=False, fragment=frag, use='werror'):
conf.define(define, 1)
elif conf.check_cc(msg='... with _GNU_SOURCE?', mandatory=False, fragment=frag, defines='_GNU_SOURCE=1', use='werror'):
conf.define(define, 1)
conf.define('_GNU_SOURCE', 1)
check_gnu_function(strcasestr_frag, 'Checking for strcasestr', 'HAVE_STRCASESTR')
check_gnu_function(strchrnul_frag, 'Checking for strchrnul', 'HAVE_STRCHRNUL')
# must be set globally as it changes ABI
if conf.env.DEST_OS not in ['psvita']:
conf.check_large_file(compiler = 'c', execute = False)
# indicate if we are packaging for Linux/BSD
conf.env.PACKAGING = conf.options.PACKAGING
if conf.options.PACKAGING:
conf.env.PREFIX = conf.options.prefix
if conf.env.SAILFISH == "aurora":