mirror of https://github.com/FWGS/xash3d-fwgs
Compare commits
101 Commits
continuous
...
master
Author | SHA1 | Date |
---|---|---|
Alibek Omarov | 870e47ed03 | |
Alibek Omarov | 32d4bdb80f | |
Alibek Omarov | 929dfd2c71 | |
Alibek Omarov | f437af6451 | |
Alibek Omarov | 413a0fb2e5 | |
Alibek Omarov | 793adadb06 | |
Alibek Omarov | 999b43b89f | |
Alibek Omarov | bd60c88c7d | |
Alibek Omarov | 23b9a2eddf | |
Alibek Omarov | 0b57d97c8c | |
Alibek Omarov | 6255293dd4 | |
Alibek Omarov | 04136d95a3 | |
Alibek Omarov | 40aa29e42a | |
Alibek Omarov | a709f30da9 | |
Alibek Omarov | 0796c14e79 | |
Alibek Omarov | a9c0a4be23 | |
Alibek Omarov | 3e1209d3a4 | |
Alibek Omarov | caf14c1b7c | |
Alibek Omarov | 27f7d2c8d2 | |
Alibek Omarov | 8ee430eda2 | |
Alibek Omarov | 484e4cb225 | |
Alibek Omarov | b080ad9954 | |
Alibek Omarov | f6625d9188 | |
Alibek Omarov | 1eb2816bc4 | |
Alibek Omarov | 077be5aaf3 | |
Alibek Omarov | d59875f114 | |
Alibek Omarov | e89191ed39 | |
Alibek Omarov | ea21438637 | |
Alibek Omarov | 0d2e8333e8 | |
Alibek Omarov | 338399e622 | |
Alibek Omarov | 27cab8aad5 | |
Alibek Omarov | 1545a49b4c | |
Alibek Omarov | 3ca15250e8 | |
Alibek Omarov | 6cbac51731 | |
Alibek Omarov | e310c666b1 | |
Alibek Omarov | 677b0170aa | |
Alibek Omarov | 9150b770e4 | |
Alibek Omarov | 2ad6511c31 | |
Alibek Omarov | 0848f28d83 | |
Alibek Omarov | 5d9bc950ce | |
Alibek Omarov | 714da79395 | |
Alibek Omarov | 823fe9ebbd | |
Alibek Omarov | 4bf72b5383 | |
Alibek Omarov | 51945f002b | |
Alibek Omarov | bcca9387de | |
Alibek Omarov | b8417fa46d | |
Alibek Omarov | 85b0699288 | |
Alibek Omarov | 6c03fb0226 | |
Alibek Omarov | a084dea07c | |
Alibek Omarov | 2e0fc3e4c1 | |
Alibek Omarov | 24f4d410ce | |
Alibek Omarov | 052e0445ab | |
Alibek Omarov | 758c908d5a | |
Alibek Omarov | 3917c2589d | |
Alibek Omarov | f4a77308ec | |
Alibek Omarov | 103b9724f9 | |
Alibek Omarov | 75a315ecf0 | |
Alibek Omarov | 63b3b9ef6d | |
Alibek Omarov | a6c2cfe89b | |
Alibek Omarov | 5120657386 | |
Alibek Omarov | e754de46d1 | |
Alibek Omarov | 5d718aa0d6 | |
Alibek Omarov | 55fcbc8880 | |
Alibek Omarov | e19aa001b2 | |
Alibek Omarov | b447ea9c18 | |
Alibek Omarov | 13274655d4 | |
Alibek Omarov | 3723ac60ef | |
Alibek Omarov | da578f47f1 | |
Alibek Omarov | 433e7de686 | |
Alibek Omarov | e18e9ae2ea | |
Alibek Omarov | 27d5123a61 | |
Alibek Omarov | 89b9f9ffe2 | |
Alibek Omarov | a17b8aaa13 | |
Alibek Omarov | e210969612 | |
Alibek Omarov | 1208356b92 | |
Alibek Omarov | d7cd74fe2f | |
Alibek Omarov | 31b63e9939 | |
Alibek Omarov | b99c2c2df1 | |
Alibek Omarov | 94d3eff9ce | |
Alibek Omarov | b78e9961c6 | |
Alibek Omarov | b0704ca5d6 | |
Alibek Omarov | 31c0934108 | |
Alibek Omarov | 37083c8aef | |
Alibek Omarov | af23b0c67b | |
Alibek Omarov | a9e83fb9cf | |
Alibek Omarov | 51126e1691 | |
Alibek Omarov | dd410a2de5 | |
Alibek Omarov | 7ccb0b5c02 | |
Alibek Omarov | 7f3e62e456 | |
Alibek Omarov | fcfc29d7ea | |
Alibek Omarov | 2f3429a144 | |
Alibek Omarov | 20782693f4 | |
Alibek Omarov | 0cfb354374 | |
Alibek Omarov | 9be5b7c6c9 | |
Alibek Omarov | e7653d2ea6 | |
Alibek Omarov | 1494887e29 | |
Alibek Omarov | 42dab2b1a5 | |
Alibek Omarov | 36a0c1fb17 | |
Alibek Omarov | 60c6767337 | |
Alibek Omarov | 75451cc7fa | |
Alibek Omarov | db10035d9d |
12
.cirrus.yml
12
.cirrus.yml
|
@ -1,15 +1,3 @@
|
|||
task:
|
||||
name: freebsd-13-amd64
|
||||
freebsd_instance:
|
||||
image_family: freebsd-13-2
|
||||
setup_script:
|
||||
- pkg update
|
||||
- pkg install -y pkgconf git sdl2 python fontconfig opus
|
||||
- git submodule update --init --recursive
|
||||
test_script:
|
||||
- ./scripts/cirrus/build_freebsd.sh dedicated
|
||||
- ./scripts/cirrus/build_freebsd.sh full
|
||||
|
||||
task:
|
||||
name: freebsd-14-amd64
|
||||
freebsd_instance:
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit f5497ceb04ed60dfaa114d52aa7d558409a59321
|
||||
Subproject commit 757ace3d4e7c318faaf90ea0510a327f762f3f4a
|
|
@ -1 +1 @@
|
|||
Subproject commit a2a7b9073f89aeb479911f4c25bb03ebeb25bf63
|
||||
Subproject commit 7276993f3f4103af3f19f8313ebb2f69416f7cac
|
|
@ -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 |
|
||||
|
|
|
@ -1,25 +0,0 @@
|
|||
/*
|
||||
boneinfo.h - structure that send delta-compressed bones across network
|
||||
Copyright (C) 2018 Uncle Mike
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef BONEINFO_H
|
||||
#define BONEINFO_H
|
||||
|
||||
typedef struct
|
||||
{
|
||||
vec3_t angles;
|
||||
vec3_t origin;
|
||||
} boneinfo_t;
|
||||
|
||||
#endif//BONEINFO_H
|
|
@ -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
|
||||
|
@ -128,6 +128,14 @@ typedef uint64_t longtime_t;
|
|||
#define STATIC_ASSERT( x, y ) STATIC_ASSERT_2( __LINE__, x, y )
|
||||
#endif
|
||||
|
||||
#if !defined( __cplusplus ) && __STDC_VERSION__ >= 199101L // not C++ and C99 or newer
|
||||
#define XASH_RESTRICT restrict
|
||||
#elif _MSC_VER || __GNUC__ || __clang__ // compiler-specific extensions
|
||||
#define XASH_RESTRICT __restrict
|
||||
#else
|
||||
#define XASH_RESTRICT // nothing
|
||||
#endif
|
||||
|
||||
#ifdef XASH_BIG_ENDIAN
|
||||
#define LittleLong(x) (((int)(((x)&255)<<24)) + ((int)((((x)>>8)&255)<<16)) + ((int)(((x)>>16)&255)<<8) + (((x) >> 24)&255))
|
||||
#define LittleLongSW(x) (x = LittleLong(x) )
|
||||
|
|
|
@ -70,16 +70,17 @@ qboolean CL_CheckFile( sizebuf_t *msg, resource_t *pResource )
|
|||
return true;
|
||||
}
|
||||
|
||||
if( cl.downloadUrl[0] )
|
||||
host.downloadcount++;
|
||||
|
||||
if( cl.http_download )
|
||||
{
|
||||
HTTP_AddDownload( filepath, pResource->nDownloadSize, true );
|
||||
host.downloadcount++;
|
||||
return false;
|
||||
}
|
||||
|
||||
MSG_BeginClientCmd( msg, clc_stringcmd );
|
||||
MSG_WriteStringf( msg, "dlfile %s", filepath );
|
||||
host.downloadcount++;
|
||||
else
|
||||
{
|
||||
MSG_BeginClientCmd( msg, clc_stringcmd );
|
||||
MSG_WriteStringf( msg, "dlfile %s", filepath );
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -50,7 +50,15 @@ const char *CL_MsgInfo( int cmd )
|
|||
if( cmd >= 0 && cmd <= svc_lastmsg )
|
||||
{
|
||||
// get engine message name
|
||||
Q_strncpy( sz, svc_strings[cmd], sizeof( sz ));
|
||||
const char *svc_string = NULL;
|
||||
|
||||
if( cls.legacymode )
|
||||
svc_string = svc_legacy_strings[cmd];
|
||||
|
||||
if( !svc_string )
|
||||
svc_string = svc_strings[cmd];
|
||||
|
||||
Q_strncpy( sz, svc_string, sizeof( sz ));
|
||||
}
|
||||
else if( cmd > svc_lastmsg && cmd <= ( svc_lastmsg + MAX_USER_MESSAGES ))
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -1097,6 +1097,20 @@ static void GAME_EXPORT pfnCon_DefaultColor( int r, int g, int b )
|
|||
Con_DefaultColor( r, g, b, true );
|
||||
}
|
||||
|
||||
static void GAME_EXPORT pfnSetCursor( void *hCursor )
|
||||
{
|
||||
uintptr_t cursor;
|
||||
|
||||
if( !gameui.use_extended_api )
|
||||
return; // ignore original Xash menus
|
||||
|
||||
cursor = (uintptr_t)hCursor;
|
||||
if( cursor < dc_user || cursor > dc_last )
|
||||
return;
|
||||
|
||||
Platform_SetCursorType( cursor );
|
||||
}
|
||||
|
||||
// engine callbacks
|
||||
static ui_enginefuncs_t gEngfuncs =
|
||||
{
|
||||
|
@ -1176,7 +1190,7 @@ static ui_enginefuncs_t gEngfuncs =
|
|||
pfnHostEndGame,
|
||||
COM_RandomFloat,
|
||||
COM_RandomLong,
|
||||
IN_SetCursor,
|
||||
pfnSetCursor,
|
||||
pfnIsMapValid,
|
||||
GL_ProcessTexture,
|
||||
COM_CompareFileTime,
|
||||
|
@ -1286,7 +1300,7 @@ qboolean UI_LoadProgs( void )
|
|||
}
|
||||
|
||||
|
||||
gameui.use_text_api = false;
|
||||
gameui.use_extended_api = false;
|
||||
|
||||
// make local copy of engfuncs to prevent overwrite it with user dll
|
||||
memcpy( &gpEngfuncs, &gEngfuncs, sizeof( gpEngfuncs ));
|
||||
|
@ -1313,7 +1327,7 @@ qboolean UI_LoadProgs( void )
|
|||
if( GetExtAPI( MENU_EXTENDED_API_VERSION, &gameui.dllFuncs2, &gpExtendedfuncs ) )
|
||||
{
|
||||
Con_Reportf( "UI_LoadProgs: extended Menu API initialized\n" );
|
||||
gameui.use_text_api = true;
|
||||
gameui.use_extended_api = true;
|
||||
}
|
||||
}
|
||||
else // otherwise, fallback to old and deprecated extensions
|
||||
|
@ -1325,7 +1339,7 @@ qboolean UI_LoadProgs( void )
|
|||
if( GiveTextApi( &gpExtendedfuncs ) ) // they are binary compatible, so we can just pass extended funcs API to menu
|
||||
{
|
||||
Con_Reportf( "UI_LoadProgs: extended text API initialized\n" );
|
||||
gameui.use_text_api = true;
|
||||
gameui.use_extended_api = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -587,21 +587,38 @@ CL_CreateCmd
|
|||
*/
|
||||
static void CL_CreateCmd( void )
|
||||
{
|
||||
usercmd_t nullcmd, *cmd;
|
||||
runcmd_t *pcmd;
|
||||
vec3_t angles;
|
||||
qboolean active;
|
||||
int input_override;
|
||||
int i, ms;
|
||||
usercmd_t nullcmd, *cmd;
|
||||
runcmd_t *pcmd;
|
||||
qboolean active;
|
||||
double accurate_ms;
|
||||
vec3_t angles;
|
||||
int input_override;
|
||||
int i, ms;
|
||||
|
||||
if( cls.state < ca_connected || cls.state == ca_cinematic )
|
||||
return;
|
||||
|
||||
// store viewangles in case it's will be freeze
|
||||
VectorCopy( cl.viewangles, angles );
|
||||
ms = bound( 1, host.frametime * 1000, 255 );
|
||||
input_override = 0;
|
||||
|
||||
// fix rounding error and framerate depending player move
|
||||
accurate_ms = host.frametime * 1000;
|
||||
ms = (int)accurate_ms;
|
||||
cl.frametime_remainder += accurate_ms - ms; // accumulate rounding error each frame
|
||||
|
||||
// add a ms if error accumulates enough
|
||||
if( cl.frametime_remainder >= 1.0 )
|
||||
{
|
||||
int ms2 = (int)cl.frametime_remainder;
|
||||
|
||||
ms += ms2;
|
||||
cl.frametime_remainder -= ms2;
|
||||
}
|
||||
|
||||
// ms can't be negative, rely on error accumulation only if FPS > 1000
|
||||
ms = Q_min( ms, 255 );
|
||||
|
||||
CL_SetSolidEntities();
|
||||
CL_PushPMStates();
|
||||
CL_SetSolidPlayers( cl.playernum );
|
||||
|
@ -2510,11 +2527,6 @@ void CL_ProcessFile( qboolean successfully_received, const char *filename )
|
|||
return;
|
||||
}
|
||||
|
||||
pfilename = filename;
|
||||
|
||||
if( !Q_strnicmp( filename, DEFAULT_SOUNDPATH, sound_len ))
|
||||
pfilename += sound_len;
|
||||
|
||||
for( p = cl.resourcesneeded.pNext; p != &cl.resourcesneeded; p = p->pNext )
|
||||
{
|
||||
if( !Q_strnicmp( filename, "!MD5", 4 ))
|
||||
|
@ -2524,18 +2536,20 @@ void CL_ProcessFile( qboolean successfully_received, const char *filename )
|
|||
if( !memcmp( p->rgucMD5_hash, rgucMD5_hash, 16 ))
|
||||
break;
|
||||
}
|
||||
else if( p->type == t_sound )
|
||||
{
|
||||
const char *pfilename = filename;
|
||||
|
||||
if( !Q_strnicmp( filename, DEFAULT_SOUNDPATH, sound_len ))
|
||||
pfilename += sound_len;
|
||||
|
||||
if( !Q_stricmp( p->szFileName, pfilename ))
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( p->type == t_generic )
|
||||
{
|
||||
if( !Q_stricmp( p->szFileName, filename ))
|
||||
if( !Q_stricmp( p->szFileName, filename ))
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( !Q_stricmp( p->szFileName, pfilename ))
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2600,7 +2614,7 @@ void CL_ProcessFile( qboolean successfully_received, const char *filename )
|
|||
|
||||
if( cls.netchan.tempbuffer )
|
||||
{
|
||||
Con_Printf( "Received a decal %s, but didn't find it in resources needed list!\n", pfilename );
|
||||
Con_Printf( "Received a decal %s, but didn't find it in resources needed list!\n", filename );
|
||||
Mem_Free( cls.netchan.tempbuffer );
|
||||
}
|
||||
|
||||
|
@ -2693,10 +2707,32 @@ static void CL_Physinfo_f( void )
|
|||
Con_Printf( "Total %i symbols\n", Q_strlen( cls.physinfo ));
|
||||
}
|
||||
|
||||
static qboolean CL_ShouldRescanFilesystem( void )
|
||||
{
|
||||
resource_t *res;
|
||||
|
||||
for( res = cl.resourcesonhand.pNext; res && res != &cl.resourcesonhand; res = res->pNext )
|
||||
{
|
||||
if( res->type == t_generic )
|
||||
{
|
||||
const char *ext = COM_FileExtension( res->szFileName );
|
||||
// TODO: query supported archives format from fs_stdio
|
||||
// TODO: query if was already opened
|
||||
if( !Q_stricmp( ext, "wad" ) || !Q_stricmp( ext, "pk3" ) || !Q_stricmp( ext, "pak" ))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
qboolean CL_PrecacheResources( void )
|
||||
{
|
||||
resource_t *pRes;
|
||||
|
||||
// if we downloaded new WAD files or any other archives they must be added to searchpath
|
||||
if( CL_ShouldRescanFilesystem( ))
|
||||
g_fsapi.Rescan();
|
||||
|
||||
// NOTE: world need to be loaded as first model
|
||||
for( pRes = cl.resourcesonhand.pNext; pRes && pRes != &cl.resourcesonhand; pRes = pRes->pNext )
|
||||
{
|
||||
|
|
|
@ -458,6 +458,7 @@ void CL_BatchResourceRequest( qboolean initialize )
|
|||
byte data[MAX_INIT_MSG];
|
||||
resource_t *p, *n;
|
||||
sizebuf_t msg;
|
||||
qboolean done_downloading = true;
|
||||
|
||||
MSG_Init( &msg, "Resource Batch", data, sizeof( data ));
|
||||
|
||||
|
@ -487,7 +488,10 @@ void CL_BatchResourceRequest( qboolean initialize )
|
|||
case t_model:
|
||||
case t_eventscript:
|
||||
if( !CL_CheckFile( &msg, p ))
|
||||
{
|
||||
done_downloading = false;
|
||||
break;
|
||||
}
|
||||
CL_MoveToOnHandList( p );
|
||||
break;
|
||||
case t_skin:
|
||||
|
@ -501,6 +505,7 @@ void CL_BatchResourceRequest( qboolean initialize )
|
|||
MSG_BeginClientCmd( &msg, clc_stringcmd );
|
||||
MSG_WriteStringf( &msg, "dlfile !MD5%s", MD5_Print( p->rgucMD5_hash ));;
|
||||
SetBits( p->ucFlags, RES_REQUESTED );
|
||||
done_downloading = false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -525,11 +530,7 @@ void CL_BatchResourceRequest( qboolean initialize )
|
|||
|
||||
if( cls.state != ca_disconnected )
|
||||
{
|
||||
if( !cl.downloadUrl[0] && !MSG_GetNumBytesWritten( &msg ) && CL_PrecacheResources( ))
|
||||
{
|
||||
CL_RegisterResources( &msg );
|
||||
}
|
||||
if( cl.downloadUrl[0] && host.downloadcount == 0 && CL_PrecacheResources( ) )
|
||||
if( done_downloading && CL_PrecacheResources( ))
|
||||
{
|
||||
CL_RegisterResources( &msg );
|
||||
}
|
||||
|
@ -1840,13 +1841,10 @@ void CL_ParseResLocation( sizebuf_t *msg )
|
|||
return;
|
||||
}
|
||||
|
||||
while( ( data = COM_ParseFile( data, token, sizeof( token ) ) ) )
|
||||
while(( data = COM_ParseFile( data, token, sizeof( token ))))
|
||||
{
|
||||
Con_Reportf( "Adding %s as download location\n", token );
|
||||
|
||||
if( !cl.downloadUrl[0] )
|
||||
Q_strncpy( cl.downloadUrl, token, sizeof( token ) );
|
||||
|
||||
cl.http_download = true;
|
||||
HTTP_AddCustomServer( token );
|
||||
}
|
||||
}
|
||||
|
@ -1877,8 +1875,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:
|
||||
|
|
|
@ -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() )
|
||||
|
|
|
@ -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 )
|
||||
|
|
|
@ -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();
|
||||
|
@ -844,7 +844,7 @@ static void CL_QuakeExecStuff( void )
|
|||
while( 1 )
|
||||
{
|
||||
// skip whitespace up to a /n
|
||||
while( *text && ((byte)*text) <= ' ' && *text != '\r' && *text != '\n' )
|
||||
while( *text && ((byte)*text ) <= ' ' && *text != '\r' && *text != '\n' )
|
||||
text++;
|
||||
|
||||
if( *text == '\n' || *text == '\r' )
|
||||
|
|
|
@ -20,7 +20,7 @@ GNU General Public License for more details.
|
|||
|
||||
int R_FatPVS( const vec3_t org, float radius, byte *visbuffer, qboolean merge, qboolean fullvis )
|
||||
{
|
||||
return Mod_FatPVS( org, radius, visbuffer, world.visbytes, merge, fullvis );
|
||||
return Mod_FatPVS( org, radius, visbuffer, world.visbytes, merge, fullvis, false );
|
||||
}
|
||||
|
||||
lightstyle_t *CL_GetLightStyle( int number )
|
||||
|
|
|
@ -229,7 +229,7 @@ typedef struct
|
|||
char serverinfo[MAX_SERVERINFO_STRING];
|
||||
player_info_t players[MAX_CLIENTS]; // collected info about all other players include himself
|
||||
double lastresourcecheck;
|
||||
string downloadUrl;
|
||||
qboolean http_download;
|
||||
event_state_t events;
|
||||
|
||||
// predicting stuff but not only...
|
||||
|
@ -276,6 +276,8 @@ typedef struct
|
|||
model_t *worldmodel; // pointer to world
|
||||
|
||||
int lostpackets; // count lost packets and show dialog in menu
|
||||
|
||||
double frametime_remainder;
|
||||
} client_t;
|
||||
|
||||
/*
|
||||
|
@ -518,7 +520,7 @@ typedef struct
|
|||
int logo_yres;
|
||||
float logo_length;
|
||||
|
||||
qboolean use_text_api;
|
||||
qboolean use_extended_api;
|
||||
} gameui_static_t;
|
||||
|
||||
typedef struct
|
||||
|
@ -539,12 +541,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
|
||||
|
@ -634,6 +632,9 @@ typedef struct
|
|||
int extensions;
|
||||
|
||||
netadr_t serveradr;
|
||||
|
||||
// do we accept utf8 as input
|
||||
qboolean accept_utf8;
|
||||
} client_static_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
@ -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" );
|
||||
|
@ -34,7 +35,6 @@ static CVAR_DEFINE_AUTO( scr_drawversion, "1", FCVAR_ARCHIVE, "draw version in m
|
|||
static CVAR_DEFINE_AUTO( con_oldfont, "0", 0, "use legacy font from gfx.wad, might be missing or broken" );
|
||||
|
||||
static int g_codepage = 0;
|
||||
static qboolean g_utf8 = false;
|
||||
|
||||
static qboolean g_messagemode_privileged = true;
|
||||
|
||||
|
@ -610,19 +610,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,84 +619,28 @@ 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 )
|
||||
if( !cls.accept_utf8 ) // incoming character is not a UTF-8 sequence
|
||||
return in;
|
||||
else
|
||||
return Con_UtfProcessCharForce( in );
|
||||
|
||||
// otherwise, decode it and convert to selected codepage
|
||||
return Con_UtfProcessCharForce( in );
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
Con_UtfMoveLeft
|
||||
|
@ -719,16 +650,22 @@ get position of previous printful char
|
|||
*/
|
||||
int Con_UtfMoveLeft( char *str, int pos )
|
||||
{
|
||||
int i, k = 0;
|
||||
// int j;
|
||||
if( !g_utf8 )
|
||||
utfstate_t state = { 0 };
|
||||
int k = 0;
|
||||
int i;
|
||||
|
||||
if( !cls.accept_utf8 ) // incoming character is not a UTF-8 sequence
|
||||
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 +678,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 )
|
||||
|
||||
if( !cls.accept_utf8 ) // incoming character is not a UTF-8 sequence
|
||||
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 +1077,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 +1488,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 );
|
||||
|
@ -2157,7 +2099,7 @@ void Con_RunConsole( void )
|
|||
g_codepage = 1252;
|
||||
}
|
||||
|
||||
g_utf8 = !Q_stricmp( cl_charset.string, "utf-8" );
|
||||
cls.accept_utf8 = !Q_stricmp( cl_charset.string, "utf-8" );
|
||||
Con_InvalidateFonts();
|
||||
Con_LoadConchars();
|
||||
ClearBits( con_charset.flags, FCVAR_CHANGED );
|
||||
|
|
|
@ -17,6 +17,7 @@ GNU General Public License for more details.
|
|||
#include "input.h"
|
||||
#include "client.h"
|
||||
#include "vgui_draw.h"
|
||||
#include "cursor_type.h"
|
||||
|
||||
#if XASH_SDL
|
||||
#include <SDL.h>
|
||||
|
@ -123,11 +124,6 @@ static void IN_StartupMouse( void )
|
|||
in_mouseinitialized = true;
|
||||
}
|
||||
|
||||
void GAME_EXPORT IN_SetCursor( void *hCursor )
|
||||
{
|
||||
// stub
|
||||
}
|
||||
|
||||
/*
|
||||
===========
|
||||
IN_MouseSavePos
|
||||
|
|
|
@ -40,7 +40,6 @@ void IN_DeactivateMouse( void );
|
|||
void IN_MouseSavePos( void );
|
||||
void IN_MouseRestorePos( void );
|
||||
void IN_ToggleClientMouse( int newstate, int oldstate );
|
||||
void IN_SetCursor( void *hCursor );
|
||||
|
||||
uint IN_CollectInputDevices( void );
|
||||
void IN_LockInputDevices( qboolean lock );
|
||||
|
|
|
@ -553,7 +553,7 @@ static void Key_AddKeyCommands( int key, const char *kb, qboolean down )
|
|||
}
|
||||
|
||||
buttonPtr = button;
|
||||
while(( kb[i] <= ' ' || kb[i] == ';' ) && kb[i] != 0 )
|
||||
while((((byte)kb[i]) <= ' ' || kb[i] == ';' ) && kb[i] != 0 )
|
||||
i++;
|
||||
}
|
||||
|
||||
|
@ -749,10 +749,10 @@ void GAME_EXPORT Key_Event( int key, int down )
|
|||
if( cls.key_dest == key_menu )
|
||||
{
|
||||
// only non printable keys passed
|
||||
if( !gameui.use_text_api )
|
||||
if( !gameui.use_extended_api )
|
||||
Key_EnableTextInput( true, false );
|
||||
//pass printable chars for old menus
|
||||
if( !gameui.use_text_api && !host.textmode && down && ( key >= 32 ) && ( key <= 'z' ) )
|
||||
if( !gameui.use_extended_api && !host.textmode && down && ( key >= 32 ) && ( key <= 'z' ) )
|
||||
{
|
||||
if( Key_IsDown( K_SHIFT ) )
|
||||
{
|
||||
|
@ -1055,18 +1055,16 @@ 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 = (byte)osk.curbutton.val;
|
||||
|
||||
// do not pass UTF-8 sequence into the engine, convert it here
|
||||
if( !cls.accept_utf8 )
|
||||
ch = Con_UtfProcessCharForce( ch );
|
||||
|
||||
if( !ch )
|
||||
break;
|
||||
|
||||
Con_CharEvent( ch );
|
||||
if( cls.key_dest == key_menu )
|
||||
UI_CharEvent ( ch );
|
||||
|
||||
CL_CharEvent( ch );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1121,7 +1119,6 @@ static void OSK_EnableTextInput( qboolean enable, qboolean force )
|
|||
{
|
||||
osk.curlayout = 0;
|
||||
osk.curbutton.val = osk_keylayout[osk.curlayout][osk.curbutton.y][osk.curbutton.x];
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -685,6 +685,9 @@ void Mod_CreatePolygonsForHull( int hullnum )
|
|||
if( hullnum < 1 || hullnum > 3 )
|
||||
return;
|
||||
|
||||
if( !world.num_hull_models )
|
||||
Mod_InitDebugHulls( mod ); // FIXME: build hulls for separate bmodels (shells, medkits etc)
|
||||
|
||||
Con_Printf( "generating polygons for hull %u...\n", hullnum );
|
||||
start = Sys_DoubleTime();
|
||||
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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 )
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 );
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -640,7 +640,7 @@ void Cmd_TokenizeString( const char *text )
|
|||
while( 1 )
|
||||
{
|
||||
// skip whitespace up to a /n
|
||||
while( *text && *text <= ' ' && *text != '\r' && *text != '\n' )
|
||||
while( *text && ((byte)*text ) <= ' ' && *text != '\r' && *text != '\n' )
|
||||
text++;
|
||||
|
||||
if( *text == '\n' || *text == '\r' )
|
||||
|
@ -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;
|
||||
|
|
|
@ -25,16 +25,19 @@ GNU General Public License for more details.
|
|||
|
||||
static const char *file_exts[] =
|
||||
{
|
||||
"cfg",
|
||||
"lst",
|
||||
"exe",
|
||||
"vbs",
|
||||
"com",
|
||||
"bat",
|
||||
"dll",
|
||||
"ini",
|
||||
"log",
|
||||
"sys",
|
||||
// ban text files that don't make sense as resource
|
||||
"cfg", "lst", "ini", "log",
|
||||
|
||||
// ban Windows code
|
||||
"exe", "vbs", "com", "bat",
|
||||
"dll", "sys", "ps1",
|
||||
|
||||
// ban common unix code
|
||||
// NOTE: in unix anything can be executed as long it has access flag
|
||||
"so", "sh", "dylib",
|
||||
|
||||
// ban mobile archives
|
||||
"apk", "ipa",
|
||||
};
|
||||
|
||||
#ifdef _DEBUG
|
||||
|
@ -900,7 +903,10 @@ qboolean COM_IsSafeFileToDownload( const char *filename )
|
|||
if( !COM_CheckString( filename ))
|
||||
return false;
|
||||
|
||||
if( !Q_strncmp( filename, "!MD5", 4 ))
|
||||
ext = COM_FileExtension( lwrfilename );
|
||||
|
||||
// only allow extensionless files that start with !MD5
|
||||
if( !Q_strncmp( filename, "!MD5", 4 ) && ext[0] == 0 )
|
||||
return true;
|
||||
|
||||
Q_strnlwr( filename, lwrfilename, sizeof( lwrfilename ));
|
||||
|
@ -923,8 +929,6 @@ qboolean COM_IsSafeFileToDownload( const char *filename )
|
|||
if( Q_strlen( first ) != 4 )
|
||||
return false;
|
||||
|
||||
ext = COM_FileExtension( lwrfilename );
|
||||
|
||||
for( i = 0; i < ARRAYSIZE( file_exts ); i++ )
|
||||
{
|
||||
if( !Q_stricmp( ext, file_exts[i] ))
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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 )
|
||||
|
|
|
@ -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 )
|
||||
|
|
|
@ -89,32 +89,32 @@ qboolean FS_LoadProgs( void )
|
|||
|
||||
if( !fs_hInstance )
|
||||
{
|
||||
Host_Error( "FS_LoadProgs: can't load filesystem library %s: %s\n", name, COM_GetLibraryError() );
|
||||
Host_Error( "%s: can't load filesystem library %s: %s\n", __func__, name, COM_GetLibraryError() );
|
||||
return false;
|
||||
}
|
||||
|
||||
if( !( GetFSAPI = (FSAPI)COM_GetProcAddress( fs_hInstance, GET_FS_API )))
|
||||
{
|
||||
FS_UnloadProgs();
|
||||
Host_Error( "FS_LoadProgs: can't find GetFSAPI entry point in %s\n", name );
|
||||
Host_Error( "%s: can't find GetFSAPI entry point in %s\n", __func__, name );
|
||||
return false;
|
||||
}
|
||||
|
||||
if( !GetFSAPI( FS_API_VERSION, &g_fsapi, &FI, &fs_memfuncs ))
|
||||
if( GetFSAPI( FS_API_VERSION, &g_fsapi, &FI, &fs_memfuncs ) != FS_API_VERSION )
|
||||
{
|
||||
FS_UnloadProgs();
|
||||
Host_Error( "FS_LoadProgs: can't initialize filesystem API: wrong version\n" );
|
||||
Host_Error( "%s: can't initialize filesystem API: wrong version\n", __func__ );
|
||||
return false;
|
||||
}
|
||||
|
||||
if( !( fs_pfnCreateInterface = (pfnCreateInterface_t)COM_GetProcAddress( fs_hInstance, "CreateInterface" )))
|
||||
{
|
||||
FS_UnloadProgs();
|
||||
Host_Error( "FS_LoadProgs: can't find CreateInterface entry point in %s\n", name );
|
||||
Host_Error( "%s: can't find CreateInterface entry point in %s\n", __func__, name );
|
||||
return false;
|
||||
}
|
||||
|
||||
Con_DPrintf( "FS_LoadProgs: filesystem_stdio successfully loaded\n" );
|
||||
Con_DPrintf( "%s: filesystem_stdio successfully loaded\n", __func__ );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -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, '+' ))
|
||||
{
|
||||
|
|
|
@ -24,7 +24,8 @@ typedef struct dll_user_s
|
|||
qboolean custom_loader; // a bit who indicated loader type
|
||||
qboolean encrypted; // dll is crypted (some client.dll in HL, CS etc)
|
||||
char dllName[32]; // for debug messages
|
||||
string fullPath, shortPath; // actual dll paths
|
||||
char fullPath[2048];
|
||||
string shortPath; // actual dll paths
|
||||
|
||||
// ordinals stuff, valid only on Win32
|
||||
word *ordinals;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -24,6 +24,9 @@ GNU General Public License for more details.
|
|||
#include "client.h"
|
||||
#include "server.h" // LUMP_ error codes
|
||||
#include "ref_common.h"
|
||||
#if defined( HAVE_OPENMP )
|
||||
#include <omp.h>
|
||||
#endif // HAVE_OPENMP
|
||||
|
||||
#define MIPTEX_CUSTOM_PALETTE_SIZE_BYTES ( sizeof( int16_t ) + 768 )
|
||||
|
||||
|
@ -578,6 +581,42 @@ void Mod_PrintWorldStats_f( void )
|
|||
|
||||
===============================================================================
|
||||
*/
|
||||
/*
|
||||
===================
|
||||
Mod_DecompressPVS
|
||||
|
||||
TODO: replace all Mod_DecompressPVS calls by this
|
||||
===================
|
||||
*/
|
||||
static void Mod_DecompressPVSTo( byte *const out, const byte *in, size_t visbytes )
|
||||
{
|
||||
byte *dst = out;
|
||||
|
||||
if( !in ) // no visinfo, make all visible
|
||||
{
|
||||
memset( out, 0xFF, visbytes );
|
||||
return;
|
||||
}
|
||||
|
||||
while( dst < out + visbytes )
|
||||
{
|
||||
if( *in ) // uncompressed
|
||||
{
|
||||
*dst++ = *in++;
|
||||
}
|
||||
else // zero repeated `c` times
|
||||
{
|
||||
size_t c = in[1];
|
||||
if( c > out + visbytes - dst )
|
||||
c = out + visbytes - dst;
|
||||
|
||||
memset( dst, 0, c );
|
||||
in += 2;
|
||||
dst += c;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
===================
|
||||
Mod_DecompressPVS
|
||||
|
@ -585,41 +624,36 @@ Mod_DecompressPVS
|
|||
*/
|
||||
static byte *Mod_DecompressPVS( const byte *in, int visbytes )
|
||||
{
|
||||
byte *out;
|
||||
int c;
|
||||
Mod_DecompressPVSTo( g_visdata, in, visbytes );
|
||||
return g_visdata;
|
||||
}
|
||||
|
||||
out = g_visdata;
|
||||
static size_t Mod_CompressPVS( byte *const out, const byte *in, size_t inbytes )
|
||||
{
|
||||
size_t i;
|
||||
byte *dst = out;
|
||||
|
||||
if( !in )
|
||||
for( i = 0; i < inbytes; i++ )
|
||||
{
|
||||
// no vis info, so make all visible
|
||||
while( visbytes )
|
||||
size_t j = i + 1, rep = 1;
|
||||
|
||||
*dst++ = in[i];
|
||||
|
||||
// only compress zeros
|
||||
if( in[i] )
|
||||
continue;
|
||||
|
||||
for( ; j < inbytes && rep != 255; j++, rep++ )
|
||||
{
|
||||
*out++ = 0xff;
|
||||
visbytes--;
|
||||
if( in[j] )
|
||||
break;
|
||||
}
|
||||
return g_visdata;
|
||||
|
||||
*dst++ = rep;
|
||||
i = j - 1;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
if( *in )
|
||||
{
|
||||
*out++ = *in++;
|
||||
continue;
|
||||
}
|
||||
|
||||
c = in[1];
|
||||
in += 2;
|
||||
|
||||
while( c )
|
||||
{
|
||||
*out++ = 0;
|
||||
c--;
|
||||
}
|
||||
} while( out - g_visdata < visbytes );
|
||||
|
||||
return g_visdata;
|
||||
return dst - out;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -653,22 +687,11 @@ NOTE: can return NULL
|
|||
*/
|
||||
byte *Mod_GetPVSForPoint( const vec3_t p )
|
||||
{
|
||||
mnode_t *node;
|
||||
mleaf_t *leaf = NULL;
|
||||
mleaf_t *leaf;
|
||||
|
||||
ASSERT( worldmodel != NULL );
|
||||
|
||||
node = worldmodel->nodes;
|
||||
|
||||
while( 1 )
|
||||
{
|
||||
if( node->contents < 0 )
|
||||
{
|
||||
leaf = (mleaf_t *)node;
|
||||
break; // we found a leaf
|
||||
}
|
||||
node = node->children[PlaneDiff( p, node->plane ) <= 0];
|
||||
}
|
||||
leaf = Mod_PointInLeaf( p, worldmodel->nodes );
|
||||
|
||||
if( leaf && leaf->cluster >= 0 )
|
||||
return Mod_DecompressPVS( leaf->compressed_vis, world.visbytes );
|
||||
|
@ -681,7 +704,7 @@ Mod_FatPVS_RecursiveBSPNode
|
|||
|
||||
==================
|
||||
*/
|
||||
static void Mod_FatPVS_RecursiveBSPNode( const vec3_t org, float radius, byte *visbuffer, int visbytes, mnode_t *node )
|
||||
static void Mod_FatPVS_RecursiveBSPNode( const vec3_t org, float radius, byte *visbuffer, int visbytes, mnode_t *node, qboolean phs )
|
||||
{
|
||||
int i;
|
||||
|
||||
|
@ -696,7 +719,7 @@ static void Mod_FatPVS_RecursiveBSPNode( const vec3_t org, float radius, byte *v
|
|||
else
|
||||
{
|
||||
// go down both sides
|
||||
Mod_FatPVS_RecursiveBSPNode( org, radius, visbuffer, visbytes, node->children[0] );
|
||||
Mod_FatPVS_RecursiveBSPNode( org, radius, visbuffer, visbytes, node->children[0], phs );
|
||||
node = node->children[1];
|
||||
}
|
||||
}
|
||||
|
@ -704,10 +727,19 @@ static void Mod_FatPVS_RecursiveBSPNode( const vec3_t org, float radius, byte *v
|
|||
// if this leaf is in a cluster, accumulate the vis bits
|
||||
if(((mleaf_t *)node)->cluster >= 0 )
|
||||
{
|
||||
byte *vis = Mod_DecompressPVS( ((mleaf_t *)node)->compressed_vis, world.visbytes );
|
||||
byte *vis;
|
||||
|
||||
for( i = 0; i < visbytes; i++ )
|
||||
visbuffer[i] |= vis[i];
|
||||
if( phs )
|
||||
{
|
||||
int i = ((mleaf_t *)node)->cluster + 1;
|
||||
vis = Mod_DecompressPVS( &world.compressed_phs[world.phsofs[i]], world.visbytes );
|
||||
}
|
||||
else
|
||||
{
|
||||
vis = Mod_DecompressPVS( ((mleaf_t *)node)->compressed_vis, world.visbytes );
|
||||
}
|
||||
|
||||
Q_memor( visbuffer, vis, visbytes );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -719,7 +751,7 @@ Calculates a PVS that is the inclusive or of all leafs
|
|||
within radius pixels of the given point.
|
||||
==================
|
||||
*/
|
||||
int Mod_FatPVS( const vec3_t org, float radius, byte *visbuffer, int visbytes, qboolean merge, qboolean fullvis )
|
||||
int Mod_FatPVS( const vec3_t org, float radius, byte *visbuffer, int visbytes, qboolean merge, qboolean fullvis, qboolean phs )
|
||||
{
|
||||
int bytes = world.visbytes;
|
||||
mleaf_t *leaf = NULL;
|
||||
|
@ -736,9 +768,17 @@ int Mod_FatPVS( const vec3_t org, float radius, byte *visbuffer, int visbytes, q
|
|||
return bytes;
|
||||
}
|
||||
|
||||
// requested PHS but we don't have PHS for some reason
|
||||
// enable full visibility
|
||||
if( phs && !( world.compressed_phs && world.phsofs ))
|
||||
{
|
||||
memset( visbuffer, 0xFF, bytes );
|
||||
return bytes;
|
||||
}
|
||||
|
||||
if( !merge ) memset( visbuffer, 0x00, bytes );
|
||||
|
||||
Mod_FatPVS_RecursiveBSPNode( org, radius, visbuffer, bytes, worldmodel->nodes );
|
||||
Mod_FatPVS_RecursiveBSPNode( org, radius, visbuffer, bytes, worldmodel->nodes, phs );
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
@ -1823,8 +1863,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 ));
|
||||
|
@ -1835,7 +1875,7 @@ static void Mod_LoadEntities( model_t *mod, dbspmodel_t *bmod )
|
|||
COM_FixSlashes( pszWadFile );
|
||||
COM_FileBase( pszWadFile, token, sizeof( token ));
|
||||
|
||||
// make sure what wad is really exist
|
||||
// make sure that wad is really exist
|
||||
if( FS_FileExists( va( "%s.wad", token ), false ))
|
||||
{
|
||||
int num = bmod->wadlist.count++;
|
||||
|
@ -2028,18 +2068,16 @@ static qboolean Mod_LooksLikeWaterTexture( const char *name )
|
|||
|
||||
static void Mod_LoadTextureData( model_t *mod, dbspmodel_t *bmod, int textureIndex )
|
||||
{
|
||||
#if !XASH_DEDICATED
|
||||
texture_t *texture = NULL;
|
||||
mip_t *mipTex = NULL;
|
||||
qboolean usesCustomPalette = false;
|
||||
uint32_t txFlags = 0;
|
||||
|
||||
// Don't load texture data on dedicated server, as there is no renderer.
|
||||
// don't load texture data on dedicated server, as there is no renderer.
|
||||
// but count the wadusage for automatic precache
|
||||
//
|
||||
// FIXME: for ENGINE_IMPROVED_LINETRACE we need to load textures on server too
|
||||
// but there is no facility for this yet
|
||||
if( Host_IsDedicated( ))
|
||||
return;
|
||||
|
||||
texture = mod->textures[textureIndex];
|
||||
mipTex = Mod_GetMipTexForTexture( bmod, textureIndex );
|
||||
|
||||
|
@ -2055,10 +2093,15 @@ static void Mod_LoadTextureData( model_t *mod, dbspmodel_t *bmod, int textureInd
|
|||
// check for multi-layered sky texture (quake1 specific)
|
||||
if( bmod->isworld && Q_strncmp( mipTex->name, "sky", 3 ) == 0 && ( mipTex->width / mipTex->height ) == 2 )
|
||||
{
|
||||
ref.dllFuncs.R_InitSkyClouds( mipTex, texture, usesCustomPalette ); // load quake sky
|
||||
#if !XASH_DEDICATED
|
||||
if( !Host_IsDedicated( ))
|
||||
{
|
||||
ref.dllFuncs.R_InitSkyClouds( mipTex, texture, usesCustomPalette ); // load quake sky
|
||||
|
||||
if( R_GetBuiltinTexture( REF_SOLIDSKY_TEXTURE ) && R_GetBuiltinTexture( REF_ALPHASKY_TEXTURE ))
|
||||
SetBits( world.flags, FWORLD_SKYSPHERE );
|
||||
if( R_GetBuiltinTexture( REF_SOLIDSKY_TEXTURE ) && R_GetBuiltinTexture( REF_ALPHASKY_TEXTURE ))
|
||||
SetBits( world.flags, FWORLD_SKYSPHERE );
|
||||
}
|
||||
#endif // !XASH_DEDICATED
|
||||
|
||||
// No texture to load in this case, so just exit.
|
||||
return;
|
||||
|
@ -2076,11 +2119,18 @@ static void Mod_LoadTextureData( model_t *mod, dbspmodel_t *bmod, int textureInd
|
|||
|
||||
if( wadIndex >= 0 )
|
||||
{
|
||||
texture->gl_texturenum = ref.dllFuncs.GL_LoadTexture( texpath, NULL, 0, txFlags );
|
||||
#if !XASH_DEDICATED
|
||||
if( !Host_IsDedicated( ))
|
||||
texture->gl_texturenum = ref.dllFuncs.GL_LoadTexture( texpath, NULL, 0, txFlags );
|
||||
#endif // !XASH_DEDICATED
|
||||
bmod->wadlist.wadusage[wadIndex]++;
|
||||
}
|
||||
}
|
||||
|
||||
#if !XASH_DEDICATED
|
||||
if( Host_IsDedicated( ))
|
||||
return;
|
||||
|
||||
// WAD failed, so use internal texture (if present)
|
||||
if( mipTex->offsets[0] > 0 && texture->gl_texturenum == 0 )
|
||||
{
|
||||
|
@ -2709,6 +2759,153 @@ static void Mod_LoadLeafs( model_t *mod, dbspmodel_t *bmod )
|
|||
SetBits( world.flags, FWORLD_WATERALPHA );
|
||||
}
|
||||
|
||||
/*
|
||||
===========
|
||||
Mod_CalcPHS
|
||||
|
||||
To be called while loading world for multiplayer game server
|
||||
===========
|
||||
*/
|
||||
static void Mod_CalcPHS( model_t *mod )
|
||||
{
|
||||
const qboolean vis_stats = host_developer.value >= DEV_EXTENDED;
|
||||
const size_t rowbytes = ALIGN( world.visbytes, 4 ); // force align rows by 32-bit boundary
|
||||
const size_t count = mod->numleafs + 1; // same as mod->submodels[0].visleafs + 1
|
||||
double t1;
|
||||
double t2;
|
||||
size_t total_compressed_size = 0;
|
||||
size_t hcount = 0;
|
||||
size_t vcount = 0;
|
||||
int i;
|
||||
byte *uncompressed_pvs;
|
||||
byte *uncompressed_phs;
|
||||
|
||||
if( !mod->visdata )
|
||||
return;
|
||||
|
||||
#if defined( HAVE_OPENMP )
|
||||
Con_Reportf( "Building PHS in %d threads...\n", omp_get_max_threads( ));
|
||||
#else
|
||||
Con_Reportf( "Building PHS...\n" );
|
||||
#endif
|
||||
|
||||
uncompressed_pvs = Mem_Calloc( mod->mempool, rowbytes * count * 2 );
|
||||
uncompressed_phs = &uncompressed_pvs[rowbytes * count];
|
||||
|
||||
world.phsofs = Mem_Calloc( mod->mempool, sizeof( size_t ) * count );
|
||||
world.compressed_phs = NULL;
|
||||
|
||||
t1 = Platform_DoubleTime();
|
||||
|
||||
#pragma omp parallel
|
||||
{
|
||||
// uncompress pvs first
|
||||
#pragma omp for schedule( static, 256 ) // there might be thousands of leafs, split by 256
|
||||
for( i = 0; i < count; i++ )
|
||||
Mod_DecompressPVSTo( &uncompressed_pvs[rowbytes * i], mod->leafs[i].compressed_vis, world.visbytes );
|
||||
|
||||
// now create phs
|
||||
#pragma omp for schedule( static, 256 ) reduction( + : vcount, hcount )
|
||||
for( i = 0; i < count; i++ )
|
||||
{
|
||||
const byte *scan = &uncompressed_pvs[rowbytes * i];
|
||||
byte *dst = &uncompressed_phs[rowbytes * i]; // rowbytes, not rowwords!
|
||||
size_t j;
|
||||
|
||||
memcpy( dst, scan, rowbytes );
|
||||
|
||||
for( j = 0; j < rowbytes; j++ )
|
||||
{
|
||||
size_t k;
|
||||
uint bitbyte = scan[j];
|
||||
|
||||
if( bitbyte == 0 )
|
||||
continue;
|
||||
|
||||
for( k = 0; k < 8; k++ )
|
||||
{
|
||||
size_t index;
|
||||
|
||||
if( !FBitSet( bitbyte, BIT( k )))
|
||||
continue;
|
||||
|
||||
// OR this pvs row into the phs
|
||||
// +1 because pvs is 1 based
|
||||
index = (( j * 8 ) + k + 1 );
|
||||
if( index >= count )
|
||||
continue;
|
||||
|
||||
Q_memor( dst, &uncompressed_pvs[rowbytes * index], rowbytes );
|
||||
}
|
||||
}
|
||||
|
||||
if( vis_stats && i != 0 )
|
||||
{
|
||||
size_t j;
|
||||
|
||||
for( j = 0; j < count; j++ )
|
||||
{
|
||||
if( CHECKVISBIT( scan, j ))
|
||||
vcount++;
|
||||
|
||||
if( CHECKVISBIT( dst, j ))
|
||||
hcount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// since I can't predict at which spot compressed array
|
||||
// should be put, this loop is single threaded
|
||||
for( i = 0; i < count; i++ )
|
||||
{
|
||||
const byte *src = &uncompressed_phs[rowbytes * i];
|
||||
byte temp_compressed_row[(MAX_MAP_LEAFS+1)/4]; // compression for this row might be ineffective
|
||||
size_t compressed_size;
|
||||
|
||||
compressed_size = Mod_CompressPVS( temp_compressed_row, src, rowbytes );
|
||||
|
||||
world.compressed_phs = Mem_Realloc( mod->mempool, world.compressed_phs, total_compressed_size + compressed_size );
|
||||
memcpy( &world.compressed_phs[total_compressed_size], temp_compressed_row, compressed_size );
|
||||
world.phsofs[i] = total_compressed_size;
|
||||
|
||||
total_compressed_size += compressed_size;
|
||||
}
|
||||
|
||||
t2 = Platform_DoubleTime();
|
||||
|
||||
if( vis_stats )
|
||||
Con_Reportf( "Average leaves visible / audible / total: %i / %i / %i\n", vcount / count, hcount / count, count );
|
||||
Con_Reportf( "Uncompressed PHS size: %s\n", Q_memprint( rowbytes * count ));
|
||||
Con_Reportf( "Compressed PHS size: %s\n", Q_memprint( total_compressed_size + sizeof( *world.phsofs ) * count ));
|
||||
Con_Reportf( "PHS building time: %.2f ms\n", ( t2 - t1 ) * 1000.0f );
|
||||
|
||||
// TODO: rewrite this into a unit test
|
||||
// NOTE: how to get GoldSrc fat PHS and PVS data
|
||||
// start a multiplayer server with some op4_bootcamp (for example)
|
||||
// attach to process with GDB:
|
||||
// (gdb) p gPAS[0]
|
||||
// $0 = (byte *) ...
|
||||
// (gdb) p gPAS[gPVSRowBytes * (cl.worldmodel->numleafs + 1)]
|
||||
// $1 = (byte *) ...
|
||||
// (gdb) dump binary memory op4_bootcamp_gs.phs $0 $1
|
||||
// (gdb) p gPVS[0]
|
||||
// $2 = (byte *) ...
|
||||
// (gdb) p gPVS[gPVSRowBytes * (cl.worldmodel->numleafs + 1)]
|
||||
// $3 = (byte *) ...
|
||||
// (gdb) dump binary memory op4_bootcamp_gs.pvs $0 $1
|
||||
//
|
||||
// NOTE: as of writing, uncompressed PVS and PHS data do match! hooray!
|
||||
//
|
||||
// FS_WriteFile( "op4_bootcamp.pvs", uncompressed_pvs, rowbytes * count );
|
||||
// FS_WriteFile( "op4_bootcamp.phs", uncompressed_phs, rowbytes * count );
|
||||
|
||||
// release uncompressed data
|
||||
Mem_Free( uncompressed_pvs );
|
||||
|
||||
// TODO: cache the PHS somewhere, it might take a long time on giant maps
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
Mod_LoadClipnodes
|
||||
|
@ -2906,6 +3103,7 @@ static qboolean Mod_LoadBmodelLumps( model_t *mod, const byte *mod_base, qboolea
|
|||
char wadvalue[2048];
|
||||
size_t len = 0;
|
||||
int i, ret, flags = 0;
|
||||
qboolean wadlist_warn = false;
|
||||
|
||||
// always reset the intermediate struct
|
||||
memset( bmod, 0, sizeof( dbspmodel_t ));
|
||||
|
@ -3000,23 +3198,37 @@ static qboolean Mod_LoadBmodelLumps( model_t *mod, const byte *mod_base, qboolea
|
|||
{
|
||||
world.version = bmod->version;
|
||||
#if !XASH_DEDICATED
|
||||
Mod_InitDebugHulls( mod ); // FIXME: build hulls for separate bmodels (shells, medkits etc)
|
||||
world.deluxedata = bmod->deluxedata_out; // deluxemap data pointer
|
||||
world.shadowdata = bmod->shadowdata_out; // occlusion data pointer
|
||||
#endif // XASH_DEDICATED
|
||||
|
||||
if( SV_Active() && svs.maxclients > 1 )
|
||||
Mod_CalcPHS( mod );
|
||||
}
|
||||
|
||||
for( i = 0; i < bmod->wadlist.count; i++ )
|
||||
{
|
||||
string wadname;
|
||||
|
||||
if( !bmod->wadlist.wadusage[i] )
|
||||
continue;
|
||||
ret = Q_snprintf( &wadvalue[len], sizeof( wadvalue ), "%s.wad; ", bmod->wadlist.wadnames[i] );
|
||||
if( ret == -1 )
|
||||
|
||||
Q_snprintf( wadname, sizeof( wadname ), "%s.wad", bmod->wadlist.wadnames[i] );
|
||||
|
||||
// a1ba: automatically precache used wad files so client will download it
|
||||
if( SV_Active( ))
|
||||
SV_GenericIndex( wadname );
|
||||
|
||||
if( !wadlist_warn )
|
||||
{
|
||||
Con_DPrintf( S_WARN "Too many wad files for output!\n" );
|
||||
break;
|
||||
ret = Q_snprintf( &wadvalue[len], sizeof( wadvalue ), "%s; ", wadname );
|
||||
if( ret == -1 )
|
||||
{
|
||||
Con_DPrintf( S_WARN "Too many wad files for output!\n" );
|
||||
wadlist_warn = true;
|
||||
}
|
||||
len += ret;
|
||||
}
|
||||
len += ret;
|
||||
}
|
||||
|
||||
if( COM_CheckString( wadvalue ))
|
||||
|
|
|
@ -33,7 +33,7 @@ GNU General Public License for more details.
|
|||
|
||||
#define REFPVS_RADIUS 2.0f // radius for rendering
|
||||
#define FATPVS_RADIUS 8.0f // FatPVS use radius smaller than the FatPHS
|
||||
#define FATPHS_RADIUS 16.0f
|
||||
#define FATPHS_RADIUS 8.0f // see SV_AddToFatPAS in GoldSrc
|
||||
|
||||
#define WORLD_INDEX (1) // world index is always 1
|
||||
|
||||
|
@ -115,6 +115,10 @@ typedef struct world_static_s
|
|||
int max_recursion;
|
||||
|
||||
uint32_t version; // BSP version
|
||||
|
||||
// Potentially Hearable Set
|
||||
byte *compressed_phs;
|
||||
size_t *phsofs;
|
||||
} world_static_t;
|
||||
|
||||
#ifndef REF_DLL
|
||||
|
@ -151,7 +155,7 @@ void Mod_FreeUnused( void );
|
|||
void Mod_LoadBrushModel( model_t *mod, const void *buffer, qboolean *loaded );
|
||||
qboolean Mod_TestBmodelLumps( file_t *f, const char *name, const byte *mod_base, qboolean silent, dlump_t *entities );
|
||||
qboolean Mod_HeadnodeVisible( mnode_t *node, const byte *visbits, int *lastleaf );
|
||||
int Mod_FatPVS( const vec3_t org, float radius, byte *visbuffer, int visbytes, qboolean merge, qboolean fullvis );
|
||||
int Mod_FatPVS( const vec3_t org, float radius, byte *visbuffer, int visbytes, qboolean merge, qboolean fullvis, qboolean false );
|
||||
qboolean Mod_BoxVisible( const vec3_t mins, const vec3_t maxs, const byte *visbits );
|
||||
int Mod_CheckLump( const char *filename, const int lump, int *lumpsize );
|
||||
int Mod_ReadLump( const char *filename, const int lump, void **lumpdata, int *lumpsize );
|
||||
|
|
|
@ -114,6 +114,11 @@ void Mod_FreeModel( model_t *mod )
|
|||
world.version = 0;
|
||||
world.shadowdata = NULL;
|
||||
world.deluxedata = NULL;
|
||||
|
||||
// data already freed by Mem_FreePool above
|
||||
world.hull_models = NULL;
|
||||
world.compressed_phs = NULL;
|
||||
world.phsofs = NULL;
|
||||
}
|
||||
|
||||
memset( mod, 0, sizeof( *mod ));
|
||||
|
|
|
@ -89,6 +89,36 @@ const char *svc_strings[svc_lastmsg+1] =
|
|||
"svc_exec",
|
||||
};
|
||||
|
||||
const char *svc_legacy_strings[svc_lastmsg+1] =
|
||||
{
|
||||
[svc_legacy_changing] = "svc_legacy_changing",
|
||||
[svc_legacy_ambientsound] = "svc_legacy_ambientsound",
|
||||
[svc_legacy_soundindex] = "svc_legacy_soundindex",
|
||||
[svc_legacy_ambientsound] = "svc_legacy_ambientsound",
|
||||
[svc_legacy_modelindex] = "svc_legacy_modelindex",
|
||||
[svc_legacy_eventindex] = "svc_legacy_eventindex",
|
||||
[svc_legacy_chokecount] = "svc_legacy_chokecount",
|
||||
};
|
||||
|
||||
const char *svc_goldsrc_strings[svc_lastmsg+1] =
|
||||
{
|
||||
[svc_goldsrc_version] = "svc_goldsrc_version",
|
||||
[svc_goldsrc_serverinfo] = "svc_goldsrc_serverinfo",
|
||||
[svc_goldsrc_deltadescription] = "svc_goldsrc_deltadescription",
|
||||
[svc_goldsrc_stopsound] = "svc_goldsrc_stopsound",
|
||||
[svc_goldsrc_damage] = "svc_goldsrc_damage",
|
||||
[svc_goldsrc_killedmonster] = "svc_goldsrc_killedmonster",
|
||||
[svc_goldsrc_foundsecret] = "svc_goldsrc_foundsecret",
|
||||
[svc_goldsrc_spawnstaticsound] = "svc_goldsrc_spawnstaticsound",
|
||||
[svc_goldsrc_decalname] = "svc_goldsrc_decalname",
|
||||
[svc_goldsrc_newusermsg] = "svc_goldsrc_newusermsg",
|
||||
[svc_goldsrc_newmovevars] = "svc_goldsrc_newmovevars",
|
||||
[svc_goldsrc_sendextrainfo] = "svc_goldsrc_sendextrainfo",
|
||||
[svc_goldsrc_timescale] = "svc_goldsrc_timescale",
|
||||
[svc_goldsrc_sendcvarvalue] = "svc_goldsrc_sendcvarvalue",
|
||||
[svc_goldsrc_sendcvarvalue2] = "svc_goldsrc_sendcvarvalue2",
|
||||
};
|
||||
|
||||
void MSG_InitMasks( void )
|
||||
{
|
||||
uint startbit, endbit;
|
||||
|
|
|
@ -919,13 +919,20 @@ int Netchan_CreateFileFragments( netchan_t *chan, const char *filename )
|
|||
int remaining;
|
||||
int bufferid = 1;
|
||||
fs_offset_t filesize = 0;
|
||||
char compressedfilename[MAX_OSPATH];
|
||||
int compressedFileTime;
|
||||
int fileTime;
|
||||
qboolean firstfragment = true;
|
||||
qboolean bCompressed = false;
|
||||
fragbufwaiting_t *wait, *p;
|
||||
fragbuf_t *buf;
|
||||
char compressedfilename[sizeof( buf->filename ) + 5];
|
||||
|
||||
// shouldn't be critical, but just in case
|
||||
if( Q_strlen( filename ) > sizeof( buf->filename ) - 1 )
|
||||
{
|
||||
Con_Printf( S_WARN "Unable to transfer %s due to path length overflow\n", filename );
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(( filesize = FS_FileSize( filename, false )) <= 0 )
|
||||
{
|
||||
|
@ -937,8 +944,7 @@ int Netchan_CreateFileFragments( netchan_t *chan, const char *filename )
|
|||
chunksize = chan->pfnBlockSize( chan->client, FRAGSIZE_FRAG );
|
||||
else chunksize = FRAGMENT_MAX_SIZE; // fallback
|
||||
|
||||
Q_strncpy( compressedfilename, filename, sizeof( compressedfilename ));
|
||||
COM_ReplaceExtension( compressedfilename, ".ztmp", sizeof( compressedfilename ));
|
||||
Q_snprintf( compressedfilename, sizeof( compressedfilename ), "%s.ztmp", filename );
|
||||
compressedFileTime = FS_FileTime( compressedfilename, false );
|
||||
fileTime = FS_FileTime( filename, false );
|
||||
|
||||
|
@ -1521,10 +1527,9 @@ void Netchan_TransmitBits( netchan_t *chan, int length, byte *data )
|
|||
|
||||
if( pbuf->iscompressed )
|
||||
{
|
||||
char compressedfilename[MAX_OSPATH];
|
||||
char compressedfilename[sizeof( pbuf->filename ) + 5];
|
||||
|
||||
Q_strncpy( compressedfilename, pbuf->filename, sizeof( compressedfilename ));
|
||||
COM_ReplaceExtension( compressedfilename, ".ztmp", sizeof( compressedfilename ));
|
||||
Q_snprintf( compressedfilename, sizeof( compressedfilename ), "%s.ztmp", pbuf->filename );
|
||||
file = FS_Open( compressedfilename, "rb", false );
|
||||
}
|
||||
else file = FS_Open( pbuf->filename, "rb", false );
|
||||
|
|
|
@ -2375,7 +2375,7 @@ static qboolean HTTP_ProcessStream( httpfile_t *curfile )
|
|||
|
||||
if( curfile->header_size >= sizeof( buf ))
|
||||
{
|
||||
Con_Reportf( S_ERROR "Header too big, the size is %s\n", curfile->header_size );
|
||||
Con_Reportf( S_ERROR "Header too big, the size is %d\n", curfile->header_size );
|
||||
HTTP_FreeFile( curfile, true );
|
||||
return false;
|
||||
}
|
||||
|
@ -2395,8 +2395,6 @@ static qboolean HTTP_ProcessStream( httpfile_t *curfile )
|
|||
int cutheadersize = begin - curfile->buf + 4; // after that begin of data
|
||||
char *content_length_line;
|
||||
|
||||
Con_Reportf( "HTTP: Got response!\n" );
|
||||
|
||||
if( !Q_strstr( curfile->buf, "200 OK" ))
|
||||
{
|
||||
*begin = 0; // cut string to print out response
|
||||
|
@ -2420,10 +2418,10 @@ static qboolean HTTP_ProcessStream( httpfile_t *curfile )
|
|||
content_length_line += sizeof( "Content-Length: " ) - 1;
|
||||
size = Q_atoi( content_length_line );
|
||||
|
||||
Con_Reportf( "HTTP: File size is %d\n", size );
|
||||
Con_Reportf( "HTTP: Got 200 OK! File size is %d\n", size );
|
||||
|
||||
if( ( curfile->size != -1 ) && ( curfile->size != size )) // check size if specified, not used
|
||||
Con_Reportf( S_WARN "Server reports wrong file size!\n" );
|
||||
Con_Reportf( S_WARN "Server reports wrong file size for %s!\n", curfile->path );
|
||||
|
||||
curfile->size = size;
|
||||
curfile->header_size = 0;
|
||||
|
@ -2535,7 +2533,7 @@ void HTTP_Run( void )
|
|||
|
||||
if( !curfile->file )
|
||||
{
|
||||
Con_Printf( S_ERROR "cannot open %s!\n", name );
|
||||
Con_Printf( S_ERROR "HTTP: cannot open %s!\n", name );
|
||||
HTTP_FreeFile( curfile, true );
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -278,6 +278,8 @@ GNU General Public License for more details.
|
|||
#define SU_WEAPON (1<<14)
|
||||
|
||||
extern const char *svc_strings[svc_lastmsg+1];
|
||||
extern const char *svc_legacy_strings[svc_lastmsg+1];
|
||||
extern const char *svc_goldsrc_strings[svc_lastmsg+1];
|
||||
extern const char *clc_strings[clc_lastmsg+1];
|
||||
|
||||
// FWGS extensions
|
||||
|
@ -316,4 +318,40 @@ extern const char *clc_strings[clc_lastmsg+1];
|
|||
// Master Server protocol
|
||||
#define MS_SCAN_REQUEST "1\xFF" "0.0.0.0:0\0" // TODO: implement IP filter
|
||||
|
||||
// GoldSrc protocol definitions
|
||||
#define PROTOCOL_GOLDSRC_VERSION_REAL 48
|
||||
#define PROTOCOL_GOLDSRC_VERSION (PROTOCOL_GOLDSRC_VERSION_REAL | (BIT( 7 ))) // should be 48, only to differentiate it from PROTOCOL_LEGACY_VERSION
|
||||
|
||||
#define svc_goldsrc_version svc_changing
|
||||
#define svc_goldsrc_serverinfo svc_serverdata
|
||||
#define svc_goldsrc_deltadescription svc_deltatable
|
||||
#define svc_goldsrc_stopsound svc_resource
|
||||
#define svc_goldsrc_damage svc_restoresound
|
||||
#define svc_goldsrc_killedmonster 27
|
||||
#define svc_goldsrc_foundsecret 28
|
||||
#define svc_goldsrc_spawnstaticsound 29
|
||||
#define svc_goldsrc_decalname svc_bspdecal
|
||||
#define svc_goldsrc_newusermsg svc_usermessage
|
||||
#define svc_goldsrc_newmovevars svc_deltamovevars
|
||||
#define svc_goldsrc_sendextrainfo 54
|
||||
#define svc_goldsrc_timescale 55
|
||||
#define svc_goldsrc_sendcvarvalue svc_querycvarvalue
|
||||
#define svc_goldsrc_sendcvarvalue2 svc_querycvarvalue2
|
||||
|
||||
#define clc_goldsrc_hltv clc_requestcvarvalue // 9
|
||||
#define clc_goldsrc_requestcvarvalue clc_requestcvarvalue2 // 10
|
||||
#define clc_goldsrc_requestcvarvalue2 11
|
||||
#define clc_goldsrc_lastmsg 12
|
||||
|
||||
#define S2C_REJECT_BADPASSWORD '8'
|
||||
#define S2C_REJECT '9'
|
||||
#define S2C_CHALLENGE "A00000000"
|
||||
#define S2C_CONNECTION "B"
|
||||
|
||||
#define MAX_GOLDSRC_RESOURCE_BITS 12
|
||||
#define MAX_GOLDSRC_ENTITY_BITS 11
|
||||
// #define MAX_GOLDSRC_EDICTS BIT( MAX_ENTITY_BITS )
|
||||
#define MAX_GOLDSRC_EDICTS ( BIT( MAX_ENTITY_BITS ) + ( MAX_CLIENTS * 15 ))
|
||||
#define LAST_GOLDSRC_EDICT ( BIT( MAX_ENTITY_BITS ) - 1 )
|
||||
|
||||
#endif//NET_PROTOCOL_H
|
||||
|
|
|
@ -87,7 +87,7 @@ int open_mpeg_stream( void *mpg, void *file, pfread f_read, pfseek f_seek, wavin
|
|||
|
||||
if( !mh || !sc ) return 0;
|
||||
|
||||
ret = mpg123_replace_reader_handle( mh, (void *)f_read, (void *)f_seek, NULL );
|
||||
ret = mpg123_replace_reader_handle( mh, f_read, f_seek, NULL );
|
||||
if( ret != MPG123_OK )
|
||||
return 0;
|
||||
|
||||
|
|
|
@ -34,9 +34,15 @@ typedef struct
|
|||
int playtime; // stream size in milliseconds
|
||||
} wavinfo_t;
|
||||
|
||||
#ifdef _MSC_VER // a1ba: MSVC6 don't have ssize_t
|
||||
typedef long mpg_ssize_t;
|
||||
#else
|
||||
typedef ssize_t mpg_ssize_t;
|
||||
#endif
|
||||
|
||||
// custom stdio
|
||||
typedef long (*pfread)( void *handle, void *buf, size_t count );
|
||||
typedef long (*pfseek)( void *handle, long offset, int whence );
|
||||
typedef mpg_ssize_t (*pfread)( void *handle, void *buf, size_t count );
|
||||
typedef fs_offset_t (*pfseek)( void *handle, fs_offset_t offset, int whence );
|
||||
|
||||
extern void *create_decoder( int *error );
|
||||
extern int feed_mpeg_header( void *mpg, const byte *data, long bufsize, long streamsize, wavinfo_t *sc );
|
||||
|
|
|
@ -32,6 +32,7 @@ typedef struct mpg123_handle_s mpg123_handle_t;
|
|||
#include <stdlib.h>
|
||||
#include "fmt123.h"
|
||||
#include STDINT_H
|
||||
#include "xash3d_types.h"
|
||||
|
||||
#ifndef FALSE
|
||||
#define FALSE 0
|
||||
|
@ -50,7 +51,7 @@ typedef unsigned char byte;
|
|||
typedef unsigned short word;
|
||||
typedef unsigned long ulong;
|
||||
typedef unsigned int uint;
|
||||
typedef long mpg_off_t;
|
||||
typedef fs_offset_t mpg_off_t;
|
||||
|
||||
#ifdef _MSC_VER // a1ba: MSVC6 don't have ssize_t
|
||||
typedef long mpg_ssize_t;
|
||||
|
|
|
@ -853,11 +853,21 @@ int open_feed( mpg123_handle_t *fr )
|
|||
return 0;
|
||||
}
|
||||
|
||||
static mpg_ssize_t read_mpgtypes( int fd, void *buf, size_t count )
|
||||
{
|
||||
return read( fd, buf, count );
|
||||
}
|
||||
|
||||
static mpg_off_t lseek_mpgtypes( int fd, mpg_off_t offset, int whence )
|
||||
{
|
||||
return lseek( fd, offset, whence );
|
||||
}
|
||||
|
||||
static int default_init( mpg123_handle_t *fr )
|
||||
{
|
||||
fr->rdat.fdread = plain_read;
|
||||
fr->rdat.read = fr->rdat.r_read != NULL ? fr->rdat.r_read : read;
|
||||
fr->rdat.lseek = fr->rdat.r_lseek != NULL ? fr->rdat.r_lseek : lseek;
|
||||
fr->rdat.read = fr->rdat.r_read != NULL ? fr->rdat.r_read : read_mpgtypes;
|
||||
fr->rdat.lseek = fr->rdat.r_lseek != NULL ? fr->rdat.r_lseek : lseek_mpgtypes;
|
||||
fr->rdat.filelen = get_fileinfo( fr );
|
||||
fr->rdat.filepos = 0;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 )
|
||||
|
@ -290,14 +291,14 @@ qboolean Sound_LoadMPG( const char *name, const byte *buffer, fs_offset_t filesi
|
|||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
FS_SeekEx
|
||||
=================
|
||||
*/
|
||||
static fs_offset_t FS_SeekEx( file_t *file, fs_offset_t offset, int whence )
|
||||
static fs_offset_t FS_SeekMpg( void *file, fs_offset_t offset, int whence )
|
||||
{
|
||||
return FS_Seek( file, offset, whence ) == -1 ? -1 : FS_Tell( file );
|
||||
return g_fsapi.Seek((file_t *)file, offset, whence ) == -1 ? -1 : g_fsapi.Tell((file_t *)file );
|
||||
}
|
||||
|
||||
static mpg_ssize_t FS_ReadMpg( void *file, void *buf, size_t count )
|
||||
{
|
||||
return g_fsapi.Read((file_t *)file, buf, count );
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -333,7 +334,7 @@ stream_t *Stream_OpenMPG( const char *filename )
|
|||
if( ret ) Con_DPrintf( S_ERROR "%s\n", get_error( mpeg ));
|
||||
|
||||
// trying to open stream and read header
|
||||
if( !open_mpeg_stream( mpeg, file, (void*)FS_Read, (void*)FS_SeekEx, &sc ))
|
||||
if( !open_mpeg_stream( mpeg, file, FS_ReadMpg, FS_SeekMpg, &sc ))
|
||||
{
|
||||
Con_DPrintf( S_ERROR "Stream_OpenMPG: failed to load (%s): %s\n", filename, get_error( mpeg ));
|
||||
close_decoder( mpeg );
|
||||
|
|
|
@ -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 )
|
||||
|
|
|
@ -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 ))
|
||||
{
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -20,63 +20,6 @@ GNU General Public License for more details.
|
|||
#include "xash3d_mathlib.h"
|
||||
#include "studio.h"
|
||||
|
||||
// just for debug
|
||||
const char *et_name[] =
|
||||
{
|
||||
"normal",
|
||||
"player",
|
||||
"tempentity",
|
||||
"beam",
|
||||
"fragmented",
|
||||
};
|
||||
|
||||
/*
|
||||
===============================================================================
|
||||
|
||||
ENTITY LINKING
|
||||
|
||||
===============================================================================
|
||||
*/
|
||||
/*
|
||||
===============
|
||||
ClearLink
|
||||
|
||||
ClearLink is used for new headnodes
|
||||
===============
|
||||
*/
|
||||
void ClearLink( link_t *l )
|
||||
{
|
||||
l->prev = l->next = l;
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
RemoveLink
|
||||
|
||||
remove link from chain
|
||||
===============
|
||||
*/
|
||||
void RemoveLink( link_t *l )
|
||||
{
|
||||
l->next->prev = l->prev;
|
||||
l->prev->next = l->next;
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
InsertLinkBefore
|
||||
|
||||
kept trigger and solid entities seperate
|
||||
===============
|
||||
*/
|
||||
void InsertLinkBefore( link_t *l, link_t *before )
|
||||
{
|
||||
l->next = before;
|
||||
l->prev = before->prev;
|
||||
l->prev->next = l;
|
||||
l->next->prev = l;
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
World_MoveBounds
|
||||
|
|
|
@ -35,13 +35,6 @@ ENTITY AREA CHECKING
|
|||
|
||||
#include "lightstyle.h"
|
||||
|
||||
extern const char *et_name[];
|
||||
|
||||
// linked list
|
||||
void InsertLinkBefore( link_t *l, link_t *before );
|
||||
void RemoveLink( link_t *l );
|
||||
void ClearLink( link_t *l );
|
||||
|
||||
// trace common
|
||||
void World_MoveBounds( const vec3_t start, vec3_t mins, vec3_t maxs, const vec3_t end, vec3_t boxmins, vec3_t boxmaxs );
|
||||
void World_TransformAABB( matrix4x4 transform, const vec3_t mins, const vec3_t maxs, vec3_t outmins, vec3_t outmaxs );
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
@ -349,16 +357,17 @@ SDLash_InputEvent
|
|||
#if SDL_VERSION_ATLEAST( 2, 0, 0 )
|
||||
static void SDLash_InputEvent( SDL_TextInputEvent input )
|
||||
{
|
||||
char *text;
|
||||
const char *text;
|
||||
|
||||
VGui_ReportTextInput( input.text );
|
||||
|
||||
for( text = input.text; *text; text++ )
|
||||
{
|
||||
int ch;
|
||||
int ch = (byte)*text;
|
||||
|
||||
if( !Q_stricmp( cl_charset.string, "utf-8" ) )
|
||||
ch = (unsigned char)*text;
|
||||
else
|
||||
ch = Con_UtfProcessCharForce( (unsigned char)*text );
|
||||
// do not pass UTF-8 sequence into the engine, convert it here
|
||||
if( !cls.accept_utf8 )
|
||||
ch = Con_UtfProcessCharForce( ch );
|
||||
|
||||
if( !ch )
|
||||
continue;
|
||||
|
@ -448,7 +457,7 @@ SDLash_EventFilter
|
|||
|
||||
=============
|
||||
*/
|
||||
static void SDLash_EventFilter( SDL_Event *event )
|
||||
static void SDLash_EventHandler( SDL_Event *event )
|
||||
{
|
||||
switch ( event->type )
|
||||
{
|
||||
|
@ -679,7 +688,7 @@ void Platform_RunEvents( void )
|
|||
SDL_Event event;
|
||||
|
||||
while( !host.crashed && !host.shutdown_issued && SDL_PollEvent( &event ) )
|
||||
SDLash_EventFilter( &event );
|
||||
SDLash_EventHandler( &event );
|
||||
|
||||
#if XASH_PSVITA
|
||||
PSVita_InputUpdate();
|
||||
|
|
|
@ -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;
|
||||
|
@ -473,6 +475,7 @@ extern convar_t sv_fullupdate_penalty_time;
|
|||
extern convar_t sv_log_outofband;
|
||||
extern convar_t sv_allow_autoaim;
|
||||
extern convar_t sv_aim;
|
||||
extern convar_t sv_allow_testpacket;
|
||||
|
||||
//===========================================================
|
||||
//
|
||||
|
@ -480,7 +483,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 );
|
||||
|
@ -501,6 +504,7 @@ void SV_ActivateServer( int runPhysics );
|
|||
qboolean SV_SpawnServer( const char *server, const char *startspot, qboolean background );
|
||||
model_t *SV_ModelHandle( int modelindex );
|
||||
void SV_DeactivateServer( void );
|
||||
void SV_FreeTestPacket( void );
|
||||
|
||||
//
|
||||
// sv_phys.c
|
||||
|
|
|
@ -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 ));
|
||||
|
@ -852,7 +852,7 @@ static void SV_TestBandWidth( netadr_t from )
|
|||
}
|
||||
|
||||
// quickly reject invalid packets
|
||||
if( !svs.testpacket_buf ||
|
||||
if( !sv_allow_testpacket.value || !svs.testpacket_buf ||
|
||||
( packetsize <= FRAGMENT_MIN_SIZE ) ||
|
||||
( packetsize > FRAGMENT_MAX_SIZE ))
|
||||
{
|
||||
|
@ -2035,7 +2035,7 @@ static qboolean SV_Kill_f( sv_client_t *cl )
|
|||
{
|
||||
if( !SV_IsValidEdict( cl->edict ))
|
||||
return true;
|
||||
|
||||
|
||||
if( cl->state != cs_spawned )
|
||||
{
|
||||
SV_ClientPrintf( cl, "Can't suicide - not connected!\n" );
|
||||
|
@ -2424,7 +2424,7 @@ static qboolean SV_EntList_f( sv_client_t *cl )
|
|||
|
||||
// filter by string
|
||||
if( Cmd_Argc() > 1 )
|
||||
{
|
||||
{
|
||||
if( !Q_stricmpext( Cmd_Argv( 1 ), STRING( ent->v.classname ) ) && !Q_stricmpext( Cmd_Argv( 1 ), STRING( ent->v.targetname ) ) )
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -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 == '"' )
|
||||
{
|
||||
|
|
|
@ -30,10 +30,8 @@ GNU General Public License for more details.
|
|||
static int GAME_EXPORT pfnModelIndex( const char *m );
|
||||
|
||||
// fatpvs stuff
|
||||
static byte fatpvs[MAX_MAP_LEAFS/8];
|
||||
static byte fatphs[MAX_MAP_LEAFS/8];
|
||||
static byte clientpvs[MAX_MAP_LEAFS/8]; // for find client in PVS
|
||||
static vec3_t viewPoint[MAX_CLIENTS];
|
||||
static byte fatphs[(MAX_MAP_LEAFS+7)/8];
|
||||
static byte clientpvs[(MAX_MAP_LEAFS+7)/8]; // for find client in PVS
|
||||
|
||||
// exports
|
||||
typedef void (__cdecl *LINK_ENTITY_FUNC)( entvars_t *pev );
|
||||
|
@ -258,7 +256,7 @@ void GAME_EXPORT SV_SetModel( edict_t *ent, const char *modelname )
|
|||
return;
|
||||
}
|
||||
|
||||
if( !modelname || modelname[0] <= ' ' )
|
||||
if( !modelname || ((byte)modelname[0] ) <= ' ' )
|
||||
{
|
||||
Con_Printf( S_WARN "SV_SetModel: null name\n" );
|
||||
return;
|
||||
|
@ -339,11 +337,12 @@ static qboolean SV_CheckClientVisiblity( sv_client_t *cl, const byte *mask )
|
|||
if( !mask ) return true; // GoldSrc rules
|
||||
|
||||
clientnum = cl - svs.clients;
|
||||
VectorCopy( viewPoint[clientnum], vieworg );
|
||||
|
||||
// Invasion issues: wrong camera position received in ENGINE_SET_PVS
|
||||
if( cl->pViewEntity && !VectorCompare( vieworg, cl->pViewEntity->v.origin ))
|
||||
if( cl->pViewEntity )
|
||||
VectorCopy( cl->pViewEntity->v.origin, vieworg );
|
||||
else
|
||||
VectorCopy( cl->edict->v.origin, vieworg );
|
||||
|
||||
leaf = Mod_PointInLeaf( vieworg, sv.worldmodel->nodes );
|
||||
|
||||
|
@ -422,7 +421,7 @@ static int SV_Multicast( int dest, const vec3_t origin, const edict_t *ent, qboo
|
|||
case MSG_PAS:
|
||||
if( origin == NULL ) return false;
|
||||
// NOTE: GoldSource not using PHS for singleplayer
|
||||
Mod_FatPVS( origin, FATPHS_RADIUS, fatphs, world.fatbytes, false, ( svs.maxclients == 1 ));
|
||||
Mod_FatPVS( origin, FATPHS_RADIUS, fatphs, world.fatbytes, false, ( svs.maxclients == 1 ), true );
|
||||
mask = fatphs; // using the FatPVS like a PHS
|
||||
break;
|
||||
case MSG_PVS_R:
|
||||
|
@ -666,7 +665,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 +2500,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 +2573,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 +2665,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 +2750,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
|
||||
}
|
||||
|
||||
|
@ -4070,7 +4156,7 @@ void GAME_EXPORT SV_PlaybackEventFull( int flags, const edict_t *pInvoker, word
|
|||
// setup pvs cluster for invoker
|
||||
if( !FBitSet( flags, FEV_GLOBAL ))
|
||||
{
|
||||
Mod_FatPVS( pvspoint, FATPHS_RADIUS, fatphs, world.fatbytes, false, ( svs.maxclients == 1 ));
|
||||
Mod_FatPVS( pvspoint, FATPHS_RADIUS, fatphs, world.fatbytes, false, ( svs.maxclients == 1 ), true );
|
||||
mask = fatphs; // using the FatPVS like a PHS
|
||||
}
|
||||
|
||||
|
@ -4095,7 +4181,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 )
|
||||
|
@ -4182,43 +4277,16 @@ so we can't use a single PVS point
|
|||
*/
|
||||
static byte *GAME_EXPORT pfnSetFatPVS( const float *org )
|
||||
{
|
||||
qboolean fullvis = false;
|
||||
static byte fatpvs[(MAX_MAP_LEAFS+7)/8];
|
||||
qboolean fullvis = false, merge = false;
|
||||
|
||||
if( !sv.worldmodel->visdata || sv_novis.value || !org || CL_DisableVisibility( ))
|
||||
fullvis = true;
|
||||
|
||||
// portals can't change viewpoint!
|
||||
if( !FBitSet( sv.hostflags, SVF_MERGE_VISIBILITY ))
|
||||
{
|
||||
vec3_t viewPos, offset;
|
||||
qboolean client_active = pfnGetCurrentPlayer() != -1;
|
||||
if( FBitSet( sv.hostflags, SVF_MERGE_VISIBILITY ))
|
||||
merge = true;
|
||||
|
||||
// see code from client.cpp for understanding:
|
||||
// org = pView->v.origin + pView->v.view_ofs;
|
||||
// if ( pView->v.flags & FL_DUCKING )
|
||||
// {
|
||||
// org = org + ( VEC_HULL_MIN - VEC_DUCK_HULL_MIN );
|
||||
// }
|
||||
// so we have unneeded duck calculations who have affect when player
|
||||
// is ducked into water. Remove offset to restore right PVS position
|
||||
if( client_active && FBitSet( sv.current_client->edict->v.flags, FL_DUCKING ))
|
||||
{
|
||||
VectorSubtract( svgame.pmove->player_mins[0], svgame.pmove->player_mins[1], offset );
|
||||
VectorSubtract( org, offset, viewPos );
|
||||
}
|
||||
else VectorCopy( org, viewPos );
|
||||
|
||||
// build a new PVS frame
|
||||
Mod_FatPVS( viewPos, FATPVS_RADIUS, fatpvs, world.fatbytes, false, fullvis );
|
||||
|
||||
if( client_active )
|
||||
VectorCopy( viewPos, viewPoint[pfnGetCurrentPlayer()] );
|
||||
}
|
||||
else
|
||||
{
|
||||
// merge PVS
|
||||
Mod_FatPVS( org, FATPVS_RADIUS, fatpvs, world.fatbytes, true, fullvis );
|
||||
}
|
||||
Mod_FatPVS( org, FATPVS_RADIUS, fatpvs, world.fatbytes, merge, fullvis, false );
|
||||
|
||||
return fatpvs;
|
||||
}
|
||||
|
@ -4233,40 +4301,15 @@ so we can't use a single PHS point
|
|||
*/
|
||||
static byte *GAME_EXPORT pfnSetFatPAS( const float *org )
|
||||
{
|
||||
qboolean fullvis = false;
|
||||
qboolean fullvis = false, merge = false;
|
||||
|
||||
if( !sv.worldmodel->visdata || sv_novis.value || !org || CL_DisableVisibility( ))
|
||||
fullvis = true;
|
||||
|
||||
// portals can't change viewpoint!
|
||||
if( !FBitSet( sv.hostflags, SVF_MERGE_VISIBILITY ))
|
||||
{
|
||||
vec3_t viewPos, offset;
|
||||
qboolean client_active = pfnGetCurrentPlayer() != -1;
|
||||
if( FBitSet( sv.hostflags, SVF_MERGE_VISIBILITY ))
|
||||
merge = true;
|
||||
|
||||
// see code from client.cpp for understanding:
|
||||
// org = pView->v.origin + pView->v.view_ofs;
|
||||
// if ( pView->v.flags & FL_DUCKING )
|
||||
// {
|
||||
// org = org + ( VEC_HULL_MIN - VEC_DUCK_HULL_MIN );
|
||||
// }
|
||||
// so we have unneeded duck calculations who have affect when player
|
||||
// is ducked into water. Remove offset to restore right PVS position
|
||||
if( client_active && FBitSet( sv.current_client->edict->v.flags, FL_DUCKING ))
|
||||
{
|
||||
VectorSubtract( svgame.pmove->player_mins[0], svgame.pmove->player_mins[1], offset );
|
||||
VectorSubtract( org, offset, viewPos );
|
||||
}
|
||||
else VectorCopy( org, viewPos );
|
||||
|
||||
// build a new PHS frame
|
||||
Mod_FatPVS( viewPos, FATPHS_RADIUS, fatphs, world.fatbytes, false, fullvis );
|
||||
}
|
||||
else
|
||||
{
|
||||
// merge PHS
|
||||
Mod_FatPVS( org, FATPHS_RADIUS, fatphs, world.fatbytes, true, fullvis );
|
||||
}
|
||||
Mod_FatPVS( org, FATPHS_RADIUS, fatphs, world.fatbytes, merge, fullvis, true );
|
||||
|
||||
return fatphs;
|
||||
}
|
||||
|
|
|
@ -906,6 +906,21 @@ qboolean CRC32_MapFile( dword *crcvalue, const char *filename, qboolean multipla
|
|||
return 1;
|
||||
}
|
||||
|
||||
void SV_FreeTestPacket( void )
|
||||
{
|
||||
if( svs.testpacket_buf )
|
||||
{
|
||||
Mem_Free( svs.testpacket_buf );
|
||||
svs.testpacket_buf = NULL;
|
||||
}
|
||||
|
||||
if( svs.testpacket_crcs )
|
||||
{
|
||||
Mem_Free( svs.testpacket_crcs );
|
||||
svs.testpacket_crcs = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
SV_GenerateTestPacket
|
||||
|
@ -917,7 +932,13 @@ static void SV_GenerateTestPacket( void )
|
|||
uint32_t crc;
|
||||
file_t *file;
|
||||
byte *filepos;
|
||||
int i, filesize;
|
||||
int i;
|
||||
|
||||
if( !sv_allow_testpacket.value )
|
||||
{
|
||||
SV_FreeTestPacket();
|
||||
return;
|
||||
}
|
||||
|
||||
// testpacket already generated once, exit
|
||||
// testpacket and lookup table takes ~300k of memory
|
||||
|
|
|
@ -150,6 +150,8 @@ CVAR_DEFINE_AUTO( sv_userinfo_penalty_attempts, "4", FCVAR_ARCHIVE, "if max atte
|
|||
CVAR_DEFINE_AUTO( sv_fullupdate_penalty_time, "1", FCVAR_ARCHIVE, "allow fullupdate command only once in this timewindow (set 0 to disable)" );
|
||||
CVAR_DEFINE_AUTO( sv_log_outofband, "0", FCVAR_ARCHIVE, "log out of band messages, can be useful for server admins and for engine debugging" );
|
||||
|
||||
CVAR_DEFINE_AUTO( sv_allow_testpacket, "1", FCVAR_ARCHIVE, "allow generating and sending a big blob of data to test maximum packet size" );
|
||||
|
||||
//============================================================================
|
||||
/*
|
||||
================
|
||||
|
@ -973,6 +975,7 @@ void SV_Init( void )
|
|||
Cvar_RegisterVariable( &sv_userinfo_penalty_attempts );
|
||||
Cvar_RegisterVariable( &sv_fullupdate_penalty_time );
|
||||
Cvar_RegisterVariable( &sv_log_outofband );
|
||||
Cvar_RegisterVariable( &sv_allow_testpacket );
|
||||
|
||||
// when we in developer-mode automatically turn cheats on
|
||||
if( host_developer.value ) Cvar_SetValue( "sv_cheats", 1.0f );
|
||||
|
@ -1115,6 +1118,9 @@ void SV_Shutdown( const char *finalmsg )
|
|||
SV_FreeClients();
|
||||
svs.maxclients = 0;
|
||||
|
||||
// release test packet blob
|
||||
SV_FreeTestPacket();
|
||||
|
||||
// release all models
|
||||
Mod_FreeAll();
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -358,6 +358,53 @@ static hull_t *SV_HullForStudioModel( edict_t *ent, vec3_t mins, vec3_t maxs, ve
|
|||
return SV_HullForEntity( ent, mins, maxs, offset );
|
||||
}
|
||||
|
||||
/*
|
||||
===============================================================================
|
||||
|
||||
ENTITY LINKING
|
||||
|
||||
===============================================================================
|
||||
*/
|
||||
/*
|
||||
===============
|
||||
ClearLink
|
||||
|
||||
ClearLink is used for new headnodes
|
||||
===============
|
||||
*/
|
||||
static void ClearLink( link_t *l )
|
||||
{
|
||||
l->prev = l->next = l;
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
RemoveLink
|
||||
|
||||
remove link from chain
|
||||
===============
|
||||
*/
|
||||
static void RemoveLink( link_t *l )
|
||||
{
|
||||
l->next->prev = l->prev;
|
||||
l->prev->next = l->next;
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
InsertLinkBefore
|
||||
|
||||
kept trigger and solid entities seperate
|
||||
===============
|
||||
*/
|
||||
static void InsertLinkBefore( link_t *l, link_t *before )
|
||||
{
|
||||
l->next = before;
|
||||
l->prev = before->prev;
|
||||
l->prev->next = l;
|
||||
l->next->prev = l;
|
||||
}
|
||||
|
||||
/*
|
||||
===============================================================================
|
||||
|
||||
|
|
|
@ -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')
|
||||
|
||||
|
|
|
@ -1363,8 +1363,13 @@ static qboolean FS_FindLibrary( const char *dllname, qboolean directpath, fs_dll
|
|||
|
||||
if( index >= 0 && !dllInfo->encrypted && search )
|
||||
{
|
||||
Q_snprintf( dllInfo->fullPath, sizeof( dllInfo->fullPath ),
|
||||
"%s%s", search->filename, dllInfo->shortPath );
|
||||
// gamedll might resolve it's own path using dladdr()
|
||||
// combine it with engine returned path to gamedir
|
||||
// it might lead to double gamedir like this
|
||||
// - valve/valve/dlls/hl.so
|
||||
// instead of expected
|
||||
// - valve/dlls/hl.so
|
||||
Q_snprintf( dllInfo->fullPath, sizeof( dllInfo->fullPath ), "%s/%s%s", fs_rootdir, search->filename, dllInfo->shortPath );
|
||||
dllInfo->custom_loader = false; // we can loading from disk and use normal debugging
|
||||
}
|
||||
else
|
||||
|
@ -2120,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;
|
||||
|
@ -2139,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;
|
||||
}
|
||||
|
@ -2158,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 )
|
||||
{
|
||||
|
@ -2173,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 );
|
||||
|
||||
|
@ -2419,7 +2425,7 @@ static void *FS_CustomAlloc( size_t size )
|
|||
|
||||
static void FS_CustomFree( void *data )
|
||||
{
|
||||
return Mem_Free( data );
|
||||
Mem_Free( data );
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -31,7 +31,7 @@ extern "C"
|
|||
{
|
||||
#endif // __cplusplus
|
||||
|
||||
#define FS_API_VERSION 2 // not stable yet!
|
||||
#define FS_API_VERSION 3 // not stable yet!
|
||||
#define FS_API_CREATEINTERFACE_TAG "XashFileSystem002" // follow FS_API_VERSION!!!
|
||||
#define FILESYSTEM_INTERFACE_VERSION "VFileSystem009" // never change this!
|
||||
|
||||
|
@ -121,8 +121,8 @@ typedef enum
|
|||
|
||||
typedef struct fs_dllinfo_t
|
||||
{
|
||||
string fullPath;
|
||||
string shortPath;
|
||||
char fullPath[2048]; // absolute disk path
|
||||
string shortPath; // vfs path
|
||||
qboolean encrypted;
|
||||
qboolean custom_loader;
|
||||
} fs_dllinfo_t;
|
||||
|
|
|
@ -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':
|
||||
|
|
|
@ -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++ ))
|
||||
|
|
|
@ -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++ )
|
||||
{
|
||||
|
@ -350,6 +274,13 @@ const byte *Q_memmem( const byte *haystack, size_t haystacklen, const byte *need
|
|||
return NULL;
|
||||
}
|
||||
|
||||
void Q_memor( byte *XASH_RESTRICT dst, const byte *XASH_RESTRICT src, size_t len )
|
||||
{
|
||||
size_t i;
|
||||
for( i = 0; i < len; i++ ) // msvc likes to optimize this loop form
|
||||
dst[i] |= src[i];
|
||||
}
|
||||
|
||||
const char* Q_timestamp( int format )
|
||||
{
|
||||
static string timestamp;
|
||||
|
@ -394,7 +325,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 +652,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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
190
public/crtlib.h
190
public/crtlib.h
|
@ -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"
|
||||
|
||||
|
@ -44,6 +45,10 @@ enum
|
|||
#define PFILE_TOKEN_MAX_LENGTH 1024
|
||||
#define PFILE_FS_TOKEN_MAX_LENGTH 512
|
||||
|
||||
#ifdef __cplusplus
|
||||
#define restrict
|
||||
#endif // __cplusplus
|
||||
|
||||
//
|
||||
// build.c
|
||||
//
|
||||
|
@ -63,11 +68,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 );
|
||||
|
@ -76,6 +76,7 @@ void Q_atov( float *vec, const char *str, size_t siz );
|
|||
qboolean Q_stricmpext( const char *pattern, const char *text );
|
||||
qboolean Q_strnicmpext( const char *pattern, const char *text, size_t minimumlen );
|
||||
const byte *Q_memmem( const byte *haystack, size_t haystacklen, const byte *needle, size_t needlelen );
|
||||
void Q_memor( byte *XASH_RESTRICT dst, const byte *XASH_RESTRICT src, size_t len );
|
||||
const char *Q_timestamp( int format );
|
||||
int Q_vsnprintf( char *buffer, size_t buffersize, const char *format, va_list args );
|
||||
int Q_snprintf( char *buffer, size_t buffersize, const char *format, ... ) _format( 3 );
|
||||
|
@ -90,7 +91,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 +104,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
|
||||
}
|
||||
|
|
|
@ -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 : '?';
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -28,7 +28,7 @@ GNU General Public License for more details.
|
|||
// REFTODO: rewrite in triapi
|
||||
void R_DrawWorldHull( void )
|
||||
{
|
||||
hull_model_t *hull = &tr.world->hull_models[0];
|
||||
hull_model_t *hull;
|
||||
winding_t *poly;
|
||||
int i;
|
||||
|
||||
|
@ -42,6 +42,8 @@ void R_DrawWorldHull( void )
|
|||
if( !r_showhull->value )
|
||||
return;
|
||||
|
||||
hull = &tr.world->hull_models[0];
|
||||
|
||||
pglDisable( GL_TEXTURE_2D );
|
||||
|
||||
list_for_each_entry( poly, &hull->polys, chain )
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -66,10 +66,10 @@ Draw_StretchPicImplementation
|
|||
static void R_DrawStretchPicImplementation( int x, int y, int w, int h, int s1, int t1, int s2, int t2, image_t *pic )
|
||||
{
|
||||
pixel_t *source, *dest;
|
||||
unsigned int v, u, sv;
|
||||
unsigned int u, sv;
|
||||
unsigned int height;
|
||||
unsigned int f, fstep;
|
||||
int skip;
|
||||
int skip, v;
|
||||
qboolean transparent = false;
|
||||
pixel_t *buffer;
|
||||
|
||||
|
@ -212,9 +212,9 @@ void GAME_EXPORT R_DrawStretchPic( float x, float y, float w, float h, float s1,
|
|||
void Draw_Fill (int x, int y, int w, int h)
|
||||
{
|
||||
pixel_t *dest;
|
||||
unsigned int v, u;
|
||||
unsigned int u;
|
||||
unsigned int height;
|
||||
int skip;
|
||||
int skip, v;
|
||||
pixel_t src = vid.color;
|
||||
int alpha = vid.alpha;
|
||||
|
||||
|
|
|
@ -410,19 +410,10 @@ void R_EntityRemoveDecals( model_t *mod );
|
|||
void R_ClearDecals( void );
|
||||
void R_DecalComputeBasis( msurface_t *surf, int flags, vec3_t textureSpaceBasis[3] );
|
||||
|
||||
#if 0
|
||||
|
||||
//
|
||||
// gl_drawhulls.c
|
||||
//
|
||||
void R_DrawWorldHull( void );
|
||||
void R_DrawModelHull( void );
|
||||
#endif
|
||||
|
||||
void GL_Bind( int tmu, unsigned int texnum );
|
||||
|
||||
//
|
||||
// gl_draw.cM_PI
|
||||
// gl_draw.c
|
||||
//
|
||||
void R_Set2DMode( qboolean enable );
|
||||
void R_DrawTileClear( int texnum, int x, int y, int w, int h );
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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('\\', '/')
|
||||
|
|
|
@ -121,6 +121,17 @@ POLLY_CFLAGS = {
|
|||
# msvc sosat :(
|
||||
}
|
||||
|
||||
OPENMP_CFLAGS = {
|
||||
'gcc': ['-fopenmp', '-DHAVE_OPENMP=1'],
|
||||
'clang': ['-fopenmp', '-DHAVE_OPENMP=1'],
|
||||
'msvc': ['/openmp', '/DHAVE_OPENMP=1']
|
||||
}
|
||||
|
||||
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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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')
|
||||
|
||||
|
|
|
@ -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 );
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue