16 Nov 2016

This commit is contained in:
g-cont 2016-11-16 00:00:00 +03:00 committed by Alibek Omarov
parent 8bc12edbac
commit ad1c92a0c0
33 changed files with 1014 additions and 281 deletions

View File

@ -17,7 +17,7 @@
static int context_id;
// Default master server address in case we can't read any from woncomm.lst file
#define VALVE_MASTER_ADDRESS "half-life.east.won.net"
#define VALVE_MASTER_ADDRESS "ms.xash.su"
#define PORT_MASTER 27010
#define PORT_SERVER 27015
@ -902,7 +902,7 @@ void CHudServers::RequestList( void )
NET_API->InitNetworking();
// Kill off left overs if any
NET_API->CancelAllRequests();
CancelRequest();
// Request Server List from master
NET_API->SendRequest( context_id++, NETAPI_REQUEST_SERVERLIST, 0, 5.0, &adr, ::ListResponse );
@ -935,7 +935,7 @@ void CHudServers::RequestBroadcastList( int clearpending )
if ( clearpending )
{
// Kill off left overs if any
NET_API->CancelAllRequests();
CancelRequest();
}
adr.type = NA_BROADCAST;

View File

@ -2718,6 +2718,24 @@ void pfnSetLightmapScale( float scale )
{
}
/*
=============
pfnParseFile
handle colon separately
=============
*/
char *pfnParseFile( char *data, char *token )
{
char *out;
host.com_handlecolon = true;
out = COM_ParseFile( data, token );
host.com_handlecolon = false;
return out;
}
/*
=============
pfnSPR_DrawGeneric
@ -3128,7 +3146,7 @@ int TriSpriteTexture( model_t *pSpriteModel, int frame )
if( psprite->texFormat == SPR_ALPHTEST )
{
pglEnable( GL_ALPHA_TEST );
pglAlphaFunc( GL_GREATER, 0.0f );
pglAlphaFunc( GL_GEQUAL, 0.5f );
}
GL_Bind( GL_TEXTURE0, gl_texturenum );
@ -3349,7 +3367,7 @@ void NetAPI_Status( net_status_t *status )
status->connected = NET_IsLocalAddress( cls.netchan.remote_address ) ? false : true;
status->connection_time = host.realtime - cls.netchan.connect_time;
status->remote_address = cls.netchan.remote_address;
status->packet_loss = cls.packet_loss / 100; // percent
status->packet_loss = cls.packet_loss / 100.0; // percent
status->latency = cl.frame.latency;
status->local_address = net_local;
status->rate = cls.netchan.rate;
@ -3377,15 +3395,14 @@ void NetAPI_SendRequest( int context, int request, int flags, double timeout, ne
for( i = 0; i < MAX_REQUESTS; i++ )
{
nr = &clgame.net_requests[i];
if( !nr->pfnFunc || nr->timeout < host.realtime )
break;
if( !nr->pfnFunc ) break;
}
if( i == MAX_REQUESTS )
{
double max_timeout = 0;
// no free requests? use older
// no free requests? use oldest
for( i = 0, nr = NULL; i < MAX_REQUESTS; i++ )
{
if(( host.realtime - clgame.net_requests[i].timesend ) > max_timeout )
@ -3412,11 +3429,20 @@ void NetAPI_SendRequest( int context, int request, int flags, double timeout, ne
if( request == NETAPI_REQUEST_SERVERLIST )
{
// UNDONE: build request for master-server
char fullquery[512] = "1\xFF" "0.0.0.0:0\0" "\\gamedir\\";
// make sure what port is specified
if( !nr->resp.remote_address.port ) nr->resp.remote_address.port = MSG_BigShort( PORT_MASTER );
// grab the list from the master server
Q_strcpy( &fullquery[22], GI->gamedir );
NET_SendPacket( NS_CLIENT, Q_strlen( GI->gamedir ) + 23, fullquery, nr->resp.remote_address );
clgame.request_type = NET_REQUEST_CLIENT;
clgame.master_request = nr; // holds the master request unitl the master acking
}
else
{
// send request over the net
// local servers request
Q_snprintf( req, sizeof( req ), "netinfo %i %i %i", PROTOCOL_VERSION, context, request );
Netchan_OutOfBandPrint( NS_CLIENT, nr->resp.remote_address, req );
}
@ -3430,15 +3456,31 @@ NetAPI_CancelRequest
*/
void NetAPI_CancelRequest( int context )
{
int i;
net_request_t *nr;
int i;
// find a specified request
for( i = 0; i < MAX_REQUESTS; i++ )
{
nr = &clgame.net_requests[i];
if( clgame.net_requests[i].resp.context == context )
{
MsgDev( D_NOTE, "Request with context %i cancelled\n", context );
if( nr->pfnFunc )
{
SetBits( nr->resp.error, NET_ERROR_TIMEOUT );
nr->resp.ping = host.realtime - nr->timesend;
nr->pfnFunc( &nr->resp );
}
Q_memset( &clgame.net_requests[i], 0, sizeof( net_request_t ));
if( clgame.net_requests[i].resp.type == NETAPI_REQUEST_SERVERLIST && &clgame.net_requests[i] == clgame.master_request )
{
if( clgame.request_type == NET_REQUEST_CLIENT )
clgame.request_type = NET_REQUEST_CANCEL;
clgame.master_request = NULL;
}
break;
}
}
@ -3452,7 +3494,22 @@ NetAPI_CancelAllRequests
*/
void NetAPI_CancelAllRequests( void )
{
net_request_t *nr;
int i;
// tell the user about cancel
for( i = 0; i < MAX_REQUESTS; i++ )
{
nr = &clgame.net_requests[i];
if( !nr->pfnFunc ) continue; // not used
SetBits( nr->resp.error, NET_ERROR_TIMEOUT );
nr->resp.ping = host.realtime - nr->timesend;
nr->pfnFunc( &nr->resp );
}
Q_memset( clgame.net_requests, 0, sizeof( clgame.net_requests ));
clgame.request_type = NET_REQUEST_CANCEL;
clgame.master_request = NULL;
}
/*
@ -3836,7 +3893,7 @@ static cl_enginefunc_t gEngfuncs =
VGui_GetPanel,
VGui_ViewportPaintBackground,
COM_LoadFile,
COM_ParseFile,
pfnParseFile,
COM_FreeFile,
&gTriApi,
&gEfxApi,

View File

@ -905,6 +905,7 @@ void CL_ClearState( void )
cl.refdef.movevars = &clgame.movevars;
cl.maxclients = 1; // allow to drawing player in menu
cl.mtime[0] = cl.mtime[1] = 1.0f; // because level starts from 1.0f second
NetAPI_CancelAllRequests();
cl.scr_fov = 90.0f;
Cvar_SetFloat( "scr_download", 0.0f );
@ -1044,6 +1045,11 @@ void CL_InternetServers_f( void )
Q_strcpy( &fullquery[22], GI->gamedir );
NET_SendPacket( NS_CLIENT, Q_strlen( GI->gamedir ) + 23, fullquery, adr );
// now we clearing the vgui request
if( clgame.master_request != NULL )
Q_memset( clgame.master_request, 0, sizeof( net_request_t ));
clgame.request_type = NET_REQUEST_GAMEUI;
}
/*
@ -1164,6 +1170,70 @@ void CL_ParseStatusMessage( netadr_t from, sizebuf_t *msg )
UI_AddServerToList( from, s );
}
/*
=================
CL_FixupColorStringsForInfoString
all the keys and values must be ends with ^7
=================
*/
void CL_FixupColorStringsForInfoString( const char *in, char *out )
{
qboolean hasPrefix = false;
qboolean endOfKeyVal = false;
int color = 7;
int count = 0;
if( *in == '\\' )
{
*out++ = *in++;
count++;
}
while( *in && count < MAX_INFO_STRING )
{
if( IsColorString( in ))
color = ColorIndex( *(in+1));
// color the not reset while end of key (or value) was found!
if( *in == '\\' && color != 7 )
{
if( IsColorString( out - 2 ))
{
*(out - 1) = '7';
}
else
{
*out++ = '^';
*out++ = '7';
count += 2;
}
color = 7;
}
*out++ = *in++;
count++;
}
// check the remaining value
if( color != 7 )
{
// if the ends with another color rewrite it
if( IsColorString( out - 2 ))
{
*(out - 1) = '7';
}
else
{
*out++ = '^';
*out++ = '7';
count += 2;
}
}
*out = '\0';
}
/*
=================
CL_ParseNETInfoMessage
@ -1173,14 +1243,26 @@ Handle a reply from a netinfo
*/
void CL_ParseNETInfoMessage( netadr_t from, sizebuf_t *msg )
{
char *s;
char *s, *val;
net_request_t *nr;
static char infostring[MAX_INFO_STRING+8];
int i, context, type;
int errorBits = 0;
context = Q_atoi( Cmd_Argv( 1 ));
type = Q_atoi( Cmd_Argv( 2 ));
s = Cmd_Argv( 3 );
// check for errors
val = Info_ValueForKey( s, "neterror" );
if( !Q_stricmp( val, "protocol" ))
SetBits( errorBits, NET_ERROR_PROTO_UNSUPPORTED );
else if( !Q_stricmp( val, "undefined" ))
SetBits( errorBits, NET_ERROR_UNDEFINED );
CL_FixupColorStringsForInfoString( s, infostring );
// find a request with specified context
for( i = 0; i < MAX_REQUESTS; i++ )
{
@ -1188,27 +1270,55 @@ void CL_ParseNETInfoMessage( netadr_t from, sizebuf_t *msg )
if( nr->resp.context == context && nr->resp.type == type )
{
if( nr->timeout > host.realtime )
{
// setup the answer
nr->resp.response = s;
nr->resp.remote_address = from;
nr->resp.error = NET_SUCCESS;
nr->resp.ping = host.realtime - nr->timesend;
nr->pfnFunc( &nr->resp );
// setup the answer
nr->resp.response = infostring;
nr->resp.remote_address = from;
nr->resp.error = NET_SUCCESS;
nr->resp.ping = host.realtime - nr->timesend;
if(!( nr->flags & FNETAPI_MULTIPLE_RESPONSE ))
Q_memset( nr, 0, sizeof( *nr )); // done
}
else
{
Q_memset( nr, 0, sizeof( *nr ));
}
if( nr->timeout <= host.realtime )
SetBits( nr->resp.error, NET_ERROR_TIMEOUT );
SetBits( nr->resp.error, errorBits ); // misc error bits
nr->pfnFunc( &nr->resp );
if( !FBitSet( nr->flags, FNETAPI_MULTIPLE_RESPONSE ))
Q_memset( nr, 0, sizeof( *nr )); // done
return;
}
}
}
/*
=================
CL_ProcessNetRequests
check for timeouts
=================
*/
void CL_ProcessNetRequests( void )
{
net_request_t *nr;
int i;
// find a request with specified context
for( i = 0; i < MAX_REQUESTS; i++ )
{
nr = &clgame.net_requests[i];
if( !nr->pfnFunc ) continue; // not used
if( nr->timeout <= host.realtime )
{
// setup the answer
SetBits( nr->resp.error, NET_ERROR_TIMEOUT );
nr->resp.ping = host.realtime - nr->timesend;
nr->pfnFunc( &nr->resp );
Q_memset( nr, 0, sizeof( *nr )); // done
}
}
}
//===================================================================
/*
===============
@ -1450,18 +1560,66 @@ void CL_ConnectionlessPacket( netadr_t from, sizebuf_t *msg )
else if( !Q_strcmp( c, "f" ))
{
// serverlist got from masterserver
while( !msg->bOverflow )
while( MSG_GetNumBitsLeft( msg ) > 8 )
{
MSG_ReadBytes( msg, servadr.ip, sizeof( servadr.ip )); // 4 bytes for IP
servadr.port = MSG_ReadShort( msg ); // 2 bytes for Port
servadr.type = NA_IP;
// 4 bytes for IP
MSG_ReadBytes( msg, servadr.ip, sizeof( servadr.ip ));
// 2 bytes for Port
servadr.port = MSG_ReadShort( msg );
if( !servadr.port ) break;
// list is ends here
if( !servadr.port )
{
if( clgame.request_type == NET_REQUEST_CLIENT && clgame.master_request != NULL )
{
net_request_t *nr = clgame.master_request;
net_adrlist_t *list, **prev;
NET_Config( true ); // allow remote
Netchan_OutOfBandPrint( NS_CLIENT, servadr, "info %i", PROTOCOL_VERSION );
// setup the answer
nr->resp.remote_address = from;
nr->resp.error = NET_SUCCESS;
nr->resp.ping = host.realtime - nr->timesend;
if( nr->timeout <= host.realtime )
SetBits( nr->resp.error, NET_ERROR_TIMEOUT );
MsgDev( D_INFO, "serverlist call: %s\n", NET_AdrToString( from ));
nr->pfnFunc( &nr->resp );
// throw the list, now it will be stored in user area
prev = &((net_adrlist_t *)nr->resp.response);
while( 1 )
{
list = *prev;
if( !list ) break;
// throw out any variables the game created
*prev = list->next;
Mem_Free( list );
}
Q_memset( nr, 0, sizeof( *nr )); // done
clgame.request_type = NET_REQUEST_CANCEL;
clgame.master_request = NULL;
}
break;
}
if( clgame.request_type == NET_REQUEST_CLIENT && clgame.master_request != NULL )
{
net_request_t *nr = clgame.master_request;
net_adrlist_t *list;
// adding addresses into list
list = Z_Malloc( sizeof( *list ));
list->remote_address = servadr;
list->next = nr->resp.response;
nr->resp.response = list;
}
else if( clgame.request_type == NET_REQUEST_GAMEUI )
{
NET_Config( true ); // allow remote
Netchan_OutOfBandPrint( NS_CLIENT, servadr, "info %i", PROTOCOL_VERSION );
}
}
}
else if( clgame.dllFuncs.pfnConnectionlessPacket( &from, args, buf, &len ))
@ -1556,6 +1714,9 @@ void CL_ReadNetMessage( void )
}
Netchan_UpdateProgress( &cls.netchan );
// check requests for time-expire
CL_ProcessNetRequests();
}
void CL_ReadPackets( void )

View File

@ -37,7 +37,7 @@ GNU General Public License for more details.
#define MAX_CDTRACKS 32
#define MAX_IMAGES 256 // SpriteTextures
#define MAX_EFRAGS 4096
#define MAX_REQUESTS 32
#define MAX_REQUESTS 128
// screenshot types
#define VID_SCREENSHOT 0
@ -354,6 +354,13 @@ typedef struct
model_t *model; // for catch model changes
} remap_info_t;
typedef enum
{
NET_REQUEST_CANCEL = 0, // request was cancelled for some reasons
NET_REQUEST_GAMEUI, // called from GameUI
NET_REQUEST_CLIENT, // called from Client
} net_request_type_t;
typedef struct
{
net_response_t resp;
@ -415,7 +422,9 @@ typedef struct
client_textmessage_t *titles; // title messages, not network messages
int numTitles;
net_request_type_t request_type; // filter the requests
net_request_t net_requests[MAX_REQUESTS]; // no reason to keep more
net_request_t *master_request; // queued master request
efrag_t *free_efrags; // linked efrags
cl_entity_t viewent; // viewmodel
@ -677,6 +686,7 @@ void CL_TextMessageParse( byte *pMemFile, int fileSize );
client_textmessage_t *CL_TextMessageGet( const char *pName );
int pfnDecalIndexFromName( const char *szDecalName );
int pfnIndexFromTrace( struct pmtrace_s *pTrace );
void NetAPI_CancelAllRequests( void );
int CL_FindModelIndex( const char *m );
HSPRITE pfnSPR_Load( const char *szPicName );
HSPRITE pfnSPR_LoadExt( const char *szPicName, uint texFlags );

View File

@ -1188,7 +1188,8 @@ void R_DrawEntitiesOnList( void )
R_DrawViewModel();
CL_ExtraUpdate();
if( !FBitSet( host.features, ENGINE_FIXED_FRAMERATE ))
CL_ExtraUpdate();
}
/*
@ -1216,7 +1217,8 @@ void R_RenderScene( const ref_params_t *fd )
R_CheckFog();
R_DrawWorld();
CL_ExtraUpdate (); // don't let sound get messed up if going slow
if( !FBitSet( host.features, ENGINE_FIXED_FRAMERATE ))
CL_ExtraUpdate (); // don't let sound get messed up if going slow
R_DrawEntitiesOnList();
@ -1269,7 +1271,8 @@ void R_BeginFrame( qboolean clearScene )
// swapinterval stuff
GL_UpdateSwapInterval();
CL_ExtraUpdate ();
if( !FBitSet( host.features, ENGINE_FIXED_FRAMERATE ))
CL_ExtraUpdate ();
}
/*

View File

@ -2021,7 +2021,7 @@ static void R_StudioDrawPoints( void )
else if( g_nFaceFlags & STUDIO_NF_TRANSPARENT && R_StudioOpaque( g_iRenderMode ))
{
GL_SetRenderMode( kRenderTransAlpha );
pglAlphaFunc( GL_GREATER, 0.0f );
pglAlphaFunc( GL_GEQUAL, 0.5f );
alpha = 1.0f;
}
else if( g_nFaceFlags & STUDIO_NF_ADDITIVE )
@ -2574,7 +2574,7 @@ static void R_StudioSetupRenderer( int rendermode )
if( glState.drawTrans && g_iRenderMode != kRenderTransAdd )
pglDepthMask( GL_TRUE );
pglAlphaFunc( GL_GREATER, 0.0f );
pglAlphaFunc( GL_GEQUAL, 0.5f );
pglShadeModel( GL_SMOOTH );
if( g_iBackFaceCull )

View File

@ -1661,7 +1661,7 @@ static void GL_SetDefaults( void )
pglDisable( GL_BLEND );
pglDisable( GL_ALPHA_TEST );
pglDisable( GL_POLYGON_OFFSET_FILL );
pglAlphaFunc( GL_GREATER, 0.0f );
pglAlphaFunc( GL_GEQUAL, 0.5f );
pglEnable( GL_TEXTURE_2D );
pglShadeModel( GL_SMOOTH );

View File

@ -361,7 +361,7 @@ int SNDDMA_Init( void *hInst )
else
{
if( snd_firsttime )
MsgDev( D_ERROR, "SNDDMA_Init: can't initialize sound device\n" );
MsgDev( D_ERROR, "Audio: can't initialize sound device\n" );
return false;
}

View File

@ -68,8 +68,8 @@ void S_SoundList_f( void )
// return true if char 'c' is one of 1st 2 characters in pch
qboolean S_TestSoundChar( const char *pch, char c )
{
int i;
char *pcht = (char *)pch;
int i;
if( !pch || !*pch )
return false;
@ -141,15 +141,11 @@ wavdata_t *S_LoadSound( sfx_t *sfx )
if( sc->rate < SOUND_11k ) // some bad sounds
Sound_Process( &sc, SOUND_11k, sc->width, SOUND_RESAMPLE );
#if SOUND_DMA_SPEED > SOUND_11k
else if( sc->rate > SOUND_11k && sc->rate < SOUND_22k ) // some bad sounds
Sound_Process( &sc, SOUND_22k, sc->width, SOUND_RESAMPLE );
#endif
#if SOUND_DMA_SPEED > SOUND_32k
else if( sc->rate > SOUND_22k && sc->rate <= SOUND_32k ) // some bad sounds
Sound_Process( &sc, SOUND_44k, sc->width, SOUND_RESAMPLE );
#endif
sfx->cache = sc;
return sfx->cache;
@ -201,9 +197,7 @@ sfx_t *S_FindName( const char *pname, int *pfInCache )
// find a free sfx slot spot
for( i = 0, sfx = s_knownSfx; i < s_numSfx; i++, sfx++)
{
if( !sfx->name[0] ) break; // free spot
}
if( i == s_numSfx )
{

View File

@ -20,7 +20,6 @@ GNU General Public License for more details.
#include "ref_params.h"
#include "pm_local.h"
#define MAX_DUPLICATED_CHANNELS 4 // threshold for identical static channels (probably error)
#define SND_CLIP_DISTANCE (float)(GI->soundclip_dist)
dma_t dma;
@ -28,6 +27,7 @@ byte *sndpool;
static soundfade_t soundfade;
channel_t channels[MAX_CHANNELS];
sound_t ambient_sfx[NUM_AMBIENTS];
rawchan_t *raw_channels[MAX_RAW_CHANNELS];
qboolean snd_ambient = false;
listener_t s_listener;
int total_channels;
@ -35,6 +35,7 @@ int soundtime; // sample PAIRS
int paintedtime; // sample PAIRS
static int trace_count = 0;
static int last_trace_chan = 0;
static byte s_fatphs[MAX_MAP_LEAFS/8]; // PHS array for snd module
convar_t *s_volume;
convar_t *s_musicvolume;
@ -689,6 +690,13 @@ float SND_GetGain( channel_t *ch, qboolean fplayersound, qboolean flooping, floa
return gain;
}
/*
=================
SND_CheckPHS
using a 'fat' radius
=================
*/
qboolean SND_CheckPHS( channel_t *ch )
{
mleaf_t *leaf;
@ -1355,7 +1363,7 @@ void S_UpdateAmbientSounds( void )
if( !chan->sfx ) continue;
vol = s_ambient_level->value * leaf->ambient_sound_level[ambient_channel];
if( vol < 8 ) vol = 0;
if( vol < 0 ) vol = 0;
// don't adjust volume too fast
if( chan->master_vol < vol )
@ -1373,6 +1381,362 @@ void S_UpdateAmbientSounds( void )
}
}
/*
=============================================================================
SOUND STREAM RAW SAMPLES
=============================================================================
*/
/*
===================
S_FindRawChannel
===================
*/
rawchan_t *S_FindRawChannel( int entnum, qboolean create )
{
int i, free;
int best, best_time;
size_t raw_samples = 0;
rawchan_t *ch;
if( !entnum ) return NULL; // world is unused
// check for replacement sound, or find the best one to replace
best_time = 0x7fffffff;
best = free = -1;
for( i = 0; i < MAX_RAW_CHANNELS; i++ )
{
ch = raw_channels[i];
if( free < 0 && !ch )
{
free = i;
}
else if( ch )
{
int time;
// exact match
if( ch->entnum == entnum )
return ch;
time = ch->s_rawend - paintedtime;
if( time < best_time )
{
best = i;
best_time = time;
}
}
}
if( !create ) return NULL;
if( free >= 0 ) best = free;
if( best < 0 ) return NULL; // no free slots
if( !raw_channels[best] )
{
raw_samples = MAX_RAW_SAMPLES;
raw_channels[best] = Mem_Alloc( sndpool, sizeof( *ch ) + sizeof( portable_samplepair_t ) * ( raw_samples - 1 ));
}
ch = raw_channels[best];
ch->max_samples = raw_samples;
ch->entnum = entnum;
ch->s_rawend = 0;
return ch;
}
/*
===================
S_RawSamplesStereo
===================
*/
static uint S_RawSamplesStereo( portable_samplepair_t *rawsamples, uint rawend, uint max_samples, uint samples, uint rate, word width, word channels, const byte *data )
{
uint fracstep, samplefrac;
uint src, dst;
if( rawend < paintedtime )
rawend = paintedtime;
fracstep = ((double) rate / (double)SOUND_DMA_SPEED) * (double)(1 << S_RAW_SAMPLES_PRECISION_BITS);
samplefrac = 0;
if( width == 2 )
{
const short *in = (const short *)data;
if( channels == 2 )
{
for( src = 0; src < samples; samplefrac += fracstep, src = ( samplefrac >> S_RAW_SAMPLES_PRECISION_BITS ))
{
dst = rawend++ & ( max_samples - 1 );
rawsamples[dst].left = in[src*2+0];
rawsamples[dst].right = in[src*2+1];
}
}
else
{
for( src = 0; src < samples; samplefrac += fracstep, src = ( samplefrac >> S_RAW_SAMPLES_PRECISION_BITS ))
{
dst = rawend++ & ( max_samples - 1 );
rawsamples[dst].left = in[src];
rawsamples[dst].right = in[src];
}
}
}
else
{
if( channels == 2 )
{
const char *in = (const char *)data;
for( src = 0; src < samples; samplefrac += fracstep, src = ( samplefrac >> S_RAW_SAMPLES_PRECISION_BITS ))
{
dst = rawend++ & ( max_samples - 1 );
rawsamples[dst].left = in[src*2+0] << 8;
rawsamples[dst].right = in[src*2+1] << 8;
}
}
else
{
for( src = 0; src < samples; samplefrac += fracstep, src = ( samplefrac >> S_RAW_SAMPLES_PRECISION_BITS ))
{
dst = rawend++ & ( max_samples - 1 );
rawsamples[dst].left = ( data[src] - 128 ) << 8;
rawsamples[dst].right = ( data[src] - 128 ) << 8;
}
}
}
return rawend;
}
/*
===================
S_RawEntSamples
===================
*/
static void S_RawEntSamples( int entnum, uint samples, uint rate, word width, word channels, const byte *data, int snd_vol )
{
rawchan_t *ch;
if( snd_vol < 0 )
snd_vol = 0;
if( !( ch = S_FindRawChannel( entnum, true )))
return;
ch->master_vol = snd_vol;
ch->dist_mult = (ATTN_NONE / SND_CLIP_DISTANCE);
ch->s_rawend = S_RawSamplesStereo( ch->rawsamples, ch->s_rawend, ch->max_samples, samples, rate, width, channels, data );
ch->leftvol = ch->rightvol = snd_vol;
}
/*
===================
S_RawSamples
===================
*/
void S_RawSamples( uint samples, uint rate, word width, word channels, const byte *data, int entnum )
{
int snd_vol;
if( entnum < 0 ) snd_vol = 128; // bg track or movie track
if( snd_vol < 0 ) snd_vol = 0; // fixup negative values
S_RawEntSamples( entnum, samples, rate, width, channels, data, snd_vol );
}
/*
===================
S_PositionedRawSamples
===================
*/
static void S_PositionedRawSamples( int entnum, float fvol, float attn, uint samples, uint rate, word width, word channels, const byte *data )
{
rawchan_t *ch;
if( entnum < 0 || entnum >= GI->max_edicts )
return;
if( !( ch = S_FindRawChannel( entnum, true )))
return;
ch->master_vol = bound( 0, fvol * 255, 255 );
ch->dist_mult = (attn / SND_CLIP_DISTANCE);
ch->s_rawend = S_RawSamplesStereo( ch->rawsamples, ch->s_rawend, ch->max_samples, samples, rate, width, channels, data );
}
/*
===================
S_GetRawSamplesLength
===================
*/
uint S_GetRawSamplesLength( int entnum )
{
rawchan_t *ch;
if( !( ch = S_FindRawChannel( entnum, false )))
return 0;
return ch->s_rawend <= paintedtime ? 0 : (float)(ch->s_rawend - paintedtime) * DMA_MSEC_PER_SAMPLE;
}
/*
===================
S_ClearRawChannel
===================
*/
void S_ClearRawChannel( int entnum )
{
rawchan_t *ch;
if( !( ch = S_FindRawChannel( entnum, false )))
return;
ch->s_rawend = 0;
}
/*
===================
S_FreeIdleRawChannels
Free raw channel that have been idling for too long.
===================
*/
static void S_FreeIdleRawChannels( void )
{
int i;
for( i = 0; i < MAX_RAW_CHANNELS; i++ )
{
rawchan_t *ch = raw_channels[i];
if( !ch ) continue;
if( ch->s_rawend >= paintedtime )
continue;
if(( paintedtime - ch->s_rawend ) / SOUND_DMA_SPEED >= S_RAW_SOUND_IDLE_SEC )
{
raw_channels[i] = NULL;
Mem_Free( ch );
}
}
}
/*
===================
S_ClearRawChannels
===================
*/
static void S_ClearRawChannels( void )
{
int i;
for( i = 0; i < MAX_RAW_CHANNELS; i++ )
{
rawchan_t *ch = raw_channels[i];
if( !ch ) continue;
ch->s_rawend = 0;
}
}
/*
===================
S_SpatializeRawChannels
===================
*/
static void S_SpatializeRawChannels( void )
{
int i;
for( i = 0; i < MAX_RAW_CHANNELS; i++ )
{
rawchan_t *ch = raw_channels[i];
vec3_t source_vec;
float dist, dot;
if( !ch ) continue;
if( ch->s_rawend < paintedtime )
{
ch->leftvol = ch->rightvol = 0;
continue;
}
// spatialization
if( !S_IsClient( ch->entnum ) && ch->dist_mult && ch->entnum >= 0 && ch->entnum < GI->max_edicts )
{
if( !CL_GetEntitySpatialization( ch->entnum, ch->origin, &ch->radius ))
{
// origin is null and entity not exist on client
ch->leftvol = ch->rightvol = 0;
}
else
{
VectorSubtract( ch->origin, s_listener.origin, source_vec );
// normalize source_vec and get distance from listener to source
dist = VectorNormalizeLength( source_vec );
dot = DotProduct( s_listener.right, source_vec );
// for sounds with a radius, spatialize left/right evenly within the radius
if( ch->radius > 0 && dist < ch->radius )
{
float interval = ch->radius * 0.5f;
float blend = dist - interval;
if( blend < 0 ) blend = 0;
blend /= interval;
// blend is 0.0 - 1.0, from 50% radius -> 100% radius
// at radius * 0.5, dot is 0 (ie: sound centered left/right)
// at radius dot == dot
dot *= blend;
}
// don't pan sounds with no attenuation
if( ch->dist_mult <= 0.0f ) dot = 0.0f;
// fill out channel volumes for single location
S_SpatializeChannel( &ch->leftvol, &ch->rightvol, ch->master_vol, 1.0f, dot, dist * ch->dist_mult );
}
}
else
{
ch->leftvol = ch->rightvol = ch->master_vol;
}
}
}
/*
===================
S_FreeRawChannels
===================
*/
static void S_FreeRawChannels( void )
{
int i;
// free raw samples
for( i = 0; i < MAX_RAW_CHANNELS; i++ )
{
if( raw_channels[i] )
Mem_Free( raw_channels[i] );
}
memset( raw_channels, 0, sizeof( raw_channels ));
}
//=============================================================================
/*
==================
S_ClearBuffer
@ -1380,7 +1744,7 @@ S_ClearBuffer
*/
void S_ClearBuffer( void )
{
s_rawend = 0;
S_ClearRawChannels();
SNDDMA_BeginPainting ();
if( dma.buffer ) Q_memset( dma.buffer, 0, dma.samples * 2 );
@ -1506,6 +1870,9 @@ void S_RenderFrame( ref_params_t *fd )
// update any client side sound fade
S_UpdateSoundFade();
// release raw-channels that no longer used more than 10 secs
S_FreeIdleRawChannels();
s_listener.entnum = fd->viewentity; // can be camera entity too
s_listener.frametime = fd->frametime;
s_listener.waterlevel = fd->waterlevel;
@ -1571,6 +1938,8 @@ void S_RenderFrame( ref_params_t *fd )
}
}
S_SpatializeRawChannels();
// debugging output
if( s_show->value )
{
@ -1591,7 +1960,12 @@ void S_RenderFrame( ref_params_t *fd )
}
// to differentiate modes
if( s_cull->integer ) VectorSet( info.color, 0.0f, 1.0f, 0.0f );
if( s_cull->integer && s_phs->integer )
VectorSet( info.color, 1.0f, 1.0f, 0.0f );
else if( s_phs->integer )
VectorSet( info.color, 0.0f, 1.0f, 0.0f );
else if( s_cull->integer )
VectorSet( info.color, 1.0f, 0.0f, 0.0f );
else VectorSet( info.color, 1.0f, 1.0f, 1.0f );
info.index = 0;
@ -1759,8 +2133,8 @@ qboolean S_Init( void )
s_mixahead = Cvar_Get( "_snd_mixahead", "0.12", 0, "how much sound to mix ahead of time" );
s_show = Cvar_Get( "s_show", "0", CVAR_ARCHIVE, "show playing sounds" );
s_lerping = Cvar_Get( "s_lerping", "0", CVAR_ARCHIVE, "apply interpolation to sound output" );
s_ambient_level = Cvar_Get( "ambient_level", "0.3", 0, "volume of environment noises (water and wind)" );
s_ambient_fade = Cvar_Get( "ambient_fade", "100", 0, "rate of volume fading when client is moving" );
s_ambient_level = Cvar_Get( "ambient_level", "0.3", CVAR_ARCHIVE, "volume of environment noises (water and wind)" );
s_ambient_fade = Cvar_Get( "ambient_fade", "1000", CVAR_ARCHIVE, "rate of volume fading when client is moving" );
s_combine_sounds = Cvar_Get( "s_combine_channels", "1", CVAR_ARCHIVE, "combine channels with same sounds" );
snd_foliage_db_loss = Cvar_Get( "snd_foliage_db_loss", "4", 0, "foliage loss factor" );
snd_gain_max = Cvar_Get( "snd_gain_max", "1", 0, "gain maximal threshold" );
@ -1821,10 +2195,11 @@ void S_Shutdown( void )
Cmd_RemoveCommand( "s_info" );
Cmd_RemoveCommand( "+voicerecord" );
Cmd_RemoveCommand( "-voicerecord" );
Cmd_RemoveCommand( "spk" );
Cmd_RemoveCommand( "speak" );
Cmd_RemoveCommand( "spk" );
S_StopAllSounds ();
S_FreeRawChannels ();
S_FreeSounds ();
VOX_Shutdown ();
FreeDsps ();

View File

@ -216,8 +216,8 @@ CHANNEL MIXING
*/
void S_PaintMonoFrom8( portable_samplepair_t *pbuf, int *volume, byte *pData, int outCount )
{
int i, data;
int *lscale, *rscale;
int i, data;
lscale = snd_scaletable[volume[0] >> SND_SCALE_SHIFT];
rscale = snd_scaletable[volume[1] >> SND_SCALE_SHIFT];
@ -252,8 +252,8 @@ void S_PaintStereoFrom8( portable_samplepair_t *pbuf, int *volume, byte *pData,
void S_PaintMonoFrom16( portable_samplepair_t *pbuf, int *volume, short *pData, int outCount )
{
int i, data;
int left, right;
int i, data;
for( i = 0; i < outCount; i++ )
{
@ -473,20 +473,13 @@ int S_MixDataToDevice( channel_t *pChannel, int sampleCount, int outputRate, int
for( i = 0; i < CPAINTBUFFERS; i++ )
{
if( paintbuffers[i].factive )
{
// mix chan into all active paintbuffers
MIX_SetCurrentPaintbuffer( i );
if( !paintbuffers[i].factive )
continue;
S_MixChannel(
pChannel, // Channel.
pData, // Input buffer.
outputOffset, // Output position.
FIX_FLOAT( sampleFraction ), // Iterators.
FIX_FLOAT( rate ),
outputSampleCount
);
}
// mix chan into all active paintbuffers
MIX_SetCurrentPaintbuffer( i );
S_MixChannel( pChannel, pData, outputOffset, FIX_FLOAT( sampleFraction ), FIX_FLOAT( rate ), outputSampleCount );
}
MIX_SetCurrentPaintbuffer( j );
@ -692,7 +685,7 @@ void S_Interpolate2xCubic( portable_samplepair_t *pbuffer, portable_samplepair_t
{
// get source sample pointer
psamp0 = S_GetNextpFilter( i-1, pbuffer, pfiltermem );
psamp1 = S_GetNextpFilter( i, pbuffer, pfiltermem );
psamp1 = S_GetNextpFilter( i+0, pbuffer, pfiltermem );
psamp2 = S_GetNextpFilter( i+1, pbuffer, pfiltermem );
psamp3 = S_GetNextpFilter( i+2, pbuffer, pfiltermem );
@ -778,9 +771,9 @@ void S_Interpolate2xLinear( portable_samplepair_t *pbuffer, portable_samplepair_
// filtertype: FILTERTYPE_NONE, _LINEAR, _CUBIC etc. Must match prevfilter.
void S_MixBufferUpsample2x( int count, portable_samplepair_t *pbuffer, portable_samplepair_t *pfiltermem, int cfltmem, int filtertype )
{
int i, j;
int upCount = count<<1;
int i, j;
// reverse through buffer, duplicating contents for 'count' samples
for( i = upCount - 1, j = count - 1; j >= 0; i-=2, j-- )
{
@ -893,57 +886,16 @@ void S_MixUpsample( int sampleCount, int filtertype )
ppaint->ifilter++;
}
// mix and upsample channels to 44khz 'ipaintbuffer'
// mix channels matching 'flags' (SOUND_MIX_DRY or SOUND_MIX_WET) into specified paintbuffer
// upsamples 11khz, 22khz channels to 44khz.
// NOTE: only call this on channels that will be mixed into only 1 paintbuffer
// and that will not be mixed until the next mix pass! otherwise, MIX_MixChannelsToPaintbuffer
// will advance any internal pointers on mixed channels; subsequent calls will be at
// incorrect offset.
void MIX_MixUpsampleBuffer( int ipaintbuffer, int end, int count )
{
int ipaintcur = MIX_GetCurrentPaintbufferIndex(); // save current paintbuffer
// reset paintbuffer upsampling filter index
MIX_ResetPaintbufferFilterCounter( ipaintbuffer );
// prevent other paintbuffers from being mixed
MIX_DeactivateAllPaintbuffers();
MIX_ActivatePaintbuffer( ipaintbuffer ); // operates on MIX_MixChannelsToPaintbuffer
MIX_SetCurrentPaintbuffer( ipaintbuffer ); // operates on MixUpSample
// mix 11khz channels to buffer
MIX_MixChannelsToPaintbuffer( end, SOUND_11k, SOUND_11k );
// upsample 11khz buffer by 2x
S_MixUpsample( count / (SOUND_DMA_SPEED / SOUND_11k), FILTERTYPE_LINEAR );
// mix 22khz channels to buffer
MIX_MixChannelsToPaintbuffer( end, SOUND_22k, SOUND_22k );
// upsample 22khz buffer by 2x
#if (SOUND_DMA_SPEED > SOUND_22k)
S_MixUpsample( count / (SOUND_DMA_SPEED / SOUND_22k), FILTERTYPE_LINEAR );
#endif
// mix 44khz channels to buffer
MIX_MixChannelsToPaintbuffer( end, SOUND_44k, SOUND_DMA_SPEED );
MIX_DeactivateAllPaintbuffers();
// restore previous paintbuffer
MIX_SetCurrentPaintbuffer( ipaintcur );
}
void MIX_MixStreamBuffer( int end )
{
portable_samplepair_t *pbuf;
rawchan_t *ch;
pbuf = MIX_GetPFrontFromIPaint( ISTREAMBUFFER );
ch = S_FindRawChannel( S_RAW_SOUND_BACKGROUNDTRACK, false );
// clear the paint buffer
if( s_listener.paused || s_rawend < paintedtime )
if( s_listener.paused || !ch || ch->s_rawend < paintedtime )
{
Q_memset( pbuf, 0, (end - paintedtime) * sizeof( portable_samplepair_t ));
}
@ -952,18 +904,54 @@ void MIX_MixStreamBuffer( int end )
int i, stop;
// copy from the streaming sound source
stop = (end < s_rawend) ? end : s_rawend;
stop = (end < ch->s_rawend) ? end : ch->s_rawend;
for( i = paintedtime; i < stop; i++ )
pbuf[i - paintedtime] = s_rawsamples[i & (MAX_RAW_SAMPLES - 1)];
{
pbuf[i-paintedtime].left = ( ch->rawsamples[i & ( ch->max_samples - 1 )].left * ch->leftvol ) >> 8;
pbuf[i-paintedtime].right = ( ch->rawsamples[i & ( ch->max_samples - 1 )].right * ch->rightvol ) >> 8;
}
for( ; i < end; i++ )
pbuf[i-paintedtime].left = pbuf[i-paintedtime].right = 0;
}
}
void MIX_MixRawSamplesBuffer( int end )
{
portable_samplepair_t *pbuf;
uint i, j, stop;
pbuf = MIX_GetCurrentPaintbufferPtr()->pbuf;
if( s_listener.paused ) return;
// paint in the raw channels
for( i = 0; i < MAX_RAW_CHANNELS; i++ )
{
// copy from the streaming sound source
rawchan_t *ch = raw_channels[i];
// background track should be mixing into another buffer
if( !ch || ch->entnum == S_RAW_SOUND_BACKGROUNDTRACK )
continue;
// not audible
if( !ch->leftvol && !ch->rightvol )
continue;
stop = (end < ch->s_rawend) ? end : ch->s_rawend;
for( j = paintedtime; j < stop; j++ )
{
pbuf[j-paintedtime].left += ( ch->rawsamples[j & ( ch->max_samples - 1 )].left * ch->leftvol ) >> 8;
pbuf[j-paintedtime].right += ( ch->rawsamples[j & ( ch->max_samples - 1 )].right * ch->rightvol ) >> 8;
}
}
}
// upsample and mix sounds into final 44khz versions of:
// IROOMBUFFER, IFACINGBUFFER, IFACINGAWAY, IDRYBUFFER
// IROOMBUFFER, IFACINGBUFFER, IFACINGAWAY
// dsp fx are then applied to these buffers by the caller.
// caller also remixes all into final IPAINTBUFFER output.
void MIX_UpsampleAllPaintbuffers( int end, int count )
@ -1000,14 +988,17 @@ void MIX_UpsampleAllPaintbuffers( int end, int count )
MIX_MixChannelsToPaintbuffer( end, SOUND_22k, SOUND_22k );
// upsample all 22khz buffers by 2x
#if (SOUND_DMA_SPEED > SOUND_22k)
// only upsample roombuffer if dsp fx are on KDB: perf
MIX_SetCurrentPaintbuffer( IROOMBUFFER );
S_MixUpsample( count / ( SOUND_DMA_SPEED / SOUND_22k ), FILTERTYPE_LINEAR );
#endif
// mix all 44khz sounds to all active paintbuffers
MIX_MixChannelsToPaintbuffer( end, SOUND_44k, SOUND_DMA_SPEED );
// mix raw samples from the video streams
MIX_SetCurrentPaintbuffer( IROOMBUFFER );
MIX_MixRawSamplesBuffer( end );
MIX_DeactivateAllPaintbuffers();
MIX_SetCurrentPaintbuffer( IPAINTBUFFER );
}

View File

@ -32,8 +32,8 @@ void SND_InitMouth( int entnum, int entchannel )
if( clientEntity )
{
clientEntity->mouth.mouthopen = 0;
clientEntity->mouth.sndavg = 0;
clientEntity->mouth.sndcount = 0;
clientEntity->mouth.sndavg = 0;
}
}
}
@ -59,8 +59,8 @@ void SND_MoveMouth8( channel_t *ch, wavdata_t *pSource, int count )
cl_entity_t *clientEntity;
char *pdata = NULL;
mouth_t *pMouth = NULL;
int savg, data;
int scount, pos = 0;
int savg, data;
uint i;
clientEntity = CL_GetEntityByIndex( ch->entnum );

View File

@ -17,11 +17,14 @@ GNU General Public License for more details.
#include "sound.h"
#include "client.h"
portable_samplepair_t s_rawsamples[MAX_RAW_SAMPLES];
static bg_track_t s_bgTrack;
static musicfade_t musicfade; // controlled by game dlls
int s_rawend;
/*
=================
S_PrintBackgroundTrackState
=================
*/
void S_PrintBackgroundTrackState( void )
{
if( s_bgTrack.current[0] && s_bgTrack.loopName[0] )
@ -32,18 +35,6 @@ void S_PrintBackgroundTrackState( void )
Msg( "BackgroundTrack: %s [loop]\n", s_bgTrack.loopName );
}
void S_CheckLerpingState( void )
{
wavdata_t *info;
s_listener.lerping = false;
if( !s_bgTrack.stream ) return;
info = FS_StreamInfo( s_bgTrack.stream );
if( info && ((float)info->rate / SOUND_DMA_SPEED ) >= 1.0f )
s_listener.lerping = s_lerping->integer;
}
/*
=================
S_FadeMusicVolume
@ -68,6 +59,7 @@ float S_GetMusicVolume( void )
scale = bound( 0.0f, musicfade.percent / 100.0f, 1.0f );
scale = 1.0f - scale;
}
return s_musicvolume->value * scale;
}
@ -109,10 +101,13 @@ void S_StartBackgroundTrack( const char *introTrack, const char *mainTrack, long
// restore message, update song position
FS_SetStreamPos( s_bgTrack.stream, position );
}
S_CheckLerpingState();
}
/*
=================
S_StopBackgroundTrack
=================
*/
void S_StopBackgroundTrack( void )
{
s_listener.stream_paused = false;
@ -123,10 +118,13 @@ void S_StopBackgroundTrack( void )
FS_FreeStream( s_bgTrack.stream );
Q_memset( &s_bgTrack, 0, sizeof( bg_track_t ));
Q_memset( &musicfade, 0, sizeof( musicfade ));
s_listener.lerping = false;
s_rawend = 0;
}
/*
=================
S_StreamSetPause
=================
*/
void S_StreamSetPause( int pause )
{
s_listener.stream_paused = pause;
@ -175,10 +173,10 @@ void S_StreamBackgroundTrack( void )
int fileSamples;
byte raw[MAX_RAW_SAMPLES];
int r, fileBytes;
rawchan_t *ch = NULL;
if( !dma.initialized ) return;
if( !s_bgTrack.stream ) return;
if( s_listener.streaming ) return; // we are playing movie or somewhat
if( !dma.initialized || !s_bgTrack.stream || s_listener.streaming )
return;
// don't bother playing anything if musicvolume is 0
if( !s_musicvolume->value || s_listener.paused || s_listener.stream_paused )
@ -193,15 +191,19 @@ void S_StreamBackgroundTrack( void )
else if( cls.key_dest == key_console )
return;
// see how many samples should be copied into the raw buffer
if( s_rawend < soundtime )
s_rawend = soundtime;
ch = S_FindRawChannel( S_RAW_SOUND_BACKGROUNDTRACK, true );
while( s_rawend < soundtime + MAX_RAW_SAMPLES )
ASSERT( ch != NULL );
// see how many samples should be copied into the raw buffer
if( ch->s_rawend < soundtime )
ch->s_rawend = soundtime;
while( ch->s_rawend < soundtime + ch->max_samples )
{
wavdata_t *info = FS_StreamInfo( s_bgTrack.stream );
bufferSamples = MAX_RAW_SAMPLES - (s_rawend - soundtime);
bufferSamples = ch->max_samples - (ch->s_rawend - soundtime);
// decide how much data needs to be read from the file
fileSamples = bufferSamples * ((float)info->rate / SOUND_DMA_SPEED );
@ -228,7 +230,7 @@ void S_StreamBackgroundTrack( void )
if( r > 0 )
{
// add to raw buffer
S_StreamRawSamples( fileSamples, info->rate, info->width, info->channels, raw );
S_RawSamples( fileSamples, info->rate, info->width, info->channels, raw, S_RAW_SOUND_BACKGROUNDTRACK );
}
else
{
@ -240,7 +242,6 @@ void S_StreamBackgroundTrack( void )
Q_strncpy( s_bgTrack.current, s_bgTrack.loopName, sizeof( s_bgTrack.current ));
if( !s_bgTrack.stream ) return;
S_CheckLerpingState();
}
else
{
@ -262,7 +263,6 @@ void S_StartStreaming( void )
if( !dma.initialized ) return;
// begin streaming movie soundtrack
s_listener.streaming = true;
s_listener.lerping = false;
}
/*
@ -274,8 +274,6 @@ void S_StopStreaming( void )
{
if( !dma.initialized ) return;
s_listener.streaming = false;
s_listener.lerping = false;
s_rawend = 0;
}
/*
@ -289,19 +287,24 @@ void S_StreamSoundTrack( void )
int fileSamples;
byte raw[MAX_RAW_SAMPLES];
int r, fileBytes;
rawchan_t *ch = NULL;
if( !dma.initialized ) return;
if( !s_listener.streaming || s_listener.paused ) return;
if( !dma.initialized || !s_listener.streaming || s_listener.paused )
return;
ch = S_FindRawChannel( S_RAW_SOUND_SOUNDTRACK, true );
ASSERT( ch != NULL );
// see how many samples should be copied into the raw buffer
if( s_rawend < soundtime )
s_rawend = soundtime;
if( ch->s_rawend < soundtime )
ch->s_rawend = soundtime;
while( s_rawend < soundtime + MAX_RAW_SAMPLES )
while( ch->s_rawend < soundtime + ch->max_samples )
{
wavdata_t *info = SCR_GetMovieInfo();
bufferSamples = MAX_RAW_SAMPLES - (s_rawend - soundtime);
bufferSamples = ch->max_samples - (ch->s_rawend - soundtime);
// decide how much data needs to be read from the file
fileSamples = bufferSamples * ((float)info->rate / SOUND_DMA_SPEED );
@ -328,68 +331,8 @@ void S_StreamSoundTrack( void )
if( r > 0 )
{
// add to raw buffer
S_StreamRawSamples( fileSamples, info->rate, info->width, info->channels, raw );
S_RawSamples( fileSamples, info->rate, info->width, info->channels, raw, S_RAW_SOUND_SOUNDTRACK );
}
else break; // no more samples for this frame
}
}
/*
============
S_StreamRawSamples
Cinematic streaming and voice over network
============
*/
void S_StreamRawSamples( int samples, int rate, int width, int channels, const byte *data )
{
int i, a, b, src, dst;
int fracstep, samplefrac;
int incount, outcount;
src = 0;
samplefrac = 0;
fracstep = (((double)rate) / (double)SOUND_DMA_SPEED) * 256.0;
outcount = (double)samples * (double)SOUND_DMA_SPEED / (double)rate;
incount = samples * channels;
#define TAKE_SAMPLE( s ) (sizeof(*in) == 1 ? (a = (in[src+(s)]-128)<<8,\
b = (src < incount - channels) ? (in[src+channels+(s)]-128)<<8 : 128) : \
(a = in[src+(s)],\
b = (src < incount - channels) ? (in[src+channels+(s)]) : 0))
// NOTE: disable lerping for cinematic sountracks
#define LERP_SAMPLE s_listener.lerping ? (((((b - a) * (samplefrac & 255)) >> 8) + a)) : a
#define RESAMPLE_RAW \
if( channels == 2 ) { \
for( i = 0; i < outcount; i++, samplefrac += fracstep, src = (samplefrac >> 8) << 1 ) { \
dst = s_rawend++ & (MAX_RAW_SAMPLES - 1); \
TAKE_SAMPLE(0); \
s_rawsamples[dst].left = LERP_SAMPLE; \
TAKE_SAMPLE(1); \
s_rawsamples[dst].right = LERP_SAMPLE; \
} \
} else { \
for( i = 0; i < outcount; i++, samplefrac += fracstep, src = (samplefrac >> 8) << 0 ) { \
dst = s_rawend++ & (MAX_RAW_SAMPLES - 1); \
TAKE_SAMPLE(0); \
s_rawsamples[dst].left = LERP_SAMPLE; \
s_rawsamples[dst].right = s_rawsamples[dst].left; \
} \
}
if( s_rawend < paintedtime )
s_rawend = paintedtime;
if( width == 2 )
{
short *in = (short *)data;
RESAMPLE_RAW
}
else
{
byte *in = (unsigned char *)data;
RESAMPLE_RAW
}
}

View File

@ -35,7 +35,7 @@ float S_SimpleSpline( float value )
float valueSquared = value * value;
// nice little ease-in, ease-out spline-like curve
return (3 * valueSquared - 2 * valueSquared * value);
return (3.0f * valueSquared - 2.0f * valueSquared * value);
}
//-----------------------------------------------------------------------------

View File

@ -25,12 +25,13 @@ extern byte *sndpool;
#define SND_STOP_LOOPING (1<<10) // stop all looping sounds on the entity.
// 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 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 SND_TRACE_UPDATE_MAX 2 // max of N channels may be checked for obscured source per frame
#define SND_RADIUS_MAX 240.0f // max sound source radius
@ -50,14 +51,14 @@ extern byte *sndpool;
#define SND_GAIN_PLAYER_WEAPON_DB 2.0f // increase player weapon gain by N dB
// 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)
#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)
#define SNDLVL_TO_DIST_MULT( sndlvl ) \
( sndlvl ? ((pow( 10, s_refdb->value / 20 ) / pow( 10, (float)sndlvl / 20 )) / s_refdist->value ) : 0 )
@ -66,26 +67,30 @@ extern byte *sndpool;
(int)( dist_mult ? ( 20 * log10( pow( 10, s_refdb->value / 20 ) / (dist_mult * s_refdist->value ))) : 0 )
// NOTE: clipped sound at 32760 to avoid overload
#define CLIP( x ) (( x ) > 32760 ? 32760 : (( x ) < -32760 ? -32760 : ( x )))
#define SWAP( a, b, t ) {(t) = (a); (a) = (b); (b) = (t);}
#define AVG( a, b ) (((a) + (b)) >> 1 )
#define AVG4( a, b, c, d ) (((a) + (b) + (c) + (d)) >> 2 )
#define CLIP( x ) (( x ) > 32760 ? 32760 : (( x ) < -32760 ? -32760 : ( x )))
#define SWAP( a, b, t ) {(t) = (a); (a) = (b); (b) = (t);}
#define AVG( a, b ) (((a) + (b)) >> 1 )
#define AVG4( a, b, c, d ) (((a) + (b) + (c) + (d)) >> 2 )
#define PAINTBUFFER_SIZE 1024 // 44k: was 512
#define PAINTBUFFER (g_curpaintbuffer)
#define CPAINTBUFFERS 3
#define PAINTBUFFER_SIZE 1024 // 44k: was 512
#define PAINTBUFFER (g_curpaintbuffer)
#define CPAINTBUFFERS 3
// 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
typedef struct
{
int left;
int right;
int left;
int right;
} portable_samplepair_t;
// sound mixing buffer
#define CPAINTFILTERMEM 3
#define CPAINTFILTERS 4 // maximum number of consecutive upsample passes per paintbuffer
typedef struct
{
qboolean factive; // if true, mix to this paintbuffer using flags
@ -104,7 +109,6 @@ typedef struct sfx_s
struct sfx_s *hashNext;
} sfx_t;
extern portable_samplepair_t drybuffer[];
extern portable_samplepair_t paintbuffer[];
extern portable_samplepair_t roombuffer[];
extern portable_samplepair_t temppaintbuffer[];
@ -146,6 +150,20 @@ typedef struct
qboolean finished;
} mixer_t;
typedef struct
{
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
float radius; // radius of this sound effect
volatile uint s_rawend;
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
@ -196,7 +214,6 @@ typedef struct
qboolean inmenu; // listener in-menu ?
qboolean paused;
qboolean streaming; // playing AVI-file
qboolean lerping; // lerp stream ?
qboolean stream_paused; // pause only background track
} listener_t;
@ -226,18 +243,19 @@ void SNDDMA_Submit( void );
#define MAX_DYNAMIC_CHANNELS (28 + NUM_AMBIENTS)
#define MAX_CHANNELS (128 + MAX_DYNAMIC_CHANNELS) // Scourge Of Armagon has too many static sounds on hip2m4.bsp
#define MAX_RAW_CHANNELS 16
#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 s_rawend;
extern int soundtime;
extern dma_t dma;
extern listener_t s_listener;
extern int idsp_room;
extern dma_t dma;
extern convar_t *s_volume;
extern convar_t *s_musicvolume;
@ -245,10 +263,7 @@ extern convar_t *s_show;
extern convar_t *s_mixahead;
extern convar_t *s_lerping;
extern convar_t *dsp_off;
extern convar_t *s_test;
extern convar_t *s_phs;
extern portable_samplepair_t s_rawsamples[MAX_RAW_SAMPLES];
extern convar_t *s_test; // cvar to testify new effects
void S_InitScaletable( void );
wavdata_t *S_LoadSound( sfx_t *sfx );
@ -296,7 +311,11 @@ channel_t *SND_PickStaticChannel( int entnum, sfx_t *sfx, const vec3_t pos );
int S_GetCurrentStaticSounds( soundlist_t *pout, int size );
int S_GetCurrentDynamicSounds( soundlist_t *pout, int size );
sfx_t *S_GetSfxByHandle( sound_t handle );
rawchan_t *S_FindRawChannel( int entnum, qboolean create );
void S_RawSamples( uint samples, uint rate, word width, word channels, const byte *data, int entnum );
void S_StopSound( int entnum, int channel, const char *soundname );
uint S_GetRawSamplesLength( int entnum );
void S_ClearRawChannel( int entnum );
void S_StopAllSounds( void );
void S_FreeSounds( void );

View File

@ -127,6 +127,7 @@ public:
virtual void setTitle( const char *title ) { }
virtual void createPopup( Panel* embeddedPanel ) { }
virtual bool isWithin( int x, int y ) { return true; }
virtual void GetMousePos( int &x, int &y );
virtual bool hasFocus( void );
protected:
virtual int createNewTextureID( void );
@ -158,6 +159,7 @@ protected:
int _drawTextPos[2];
int _drawColor[4];
int _drawTextColor[4];
bool _allowSetTextPos;
friend class App;
friend class Panel;
};

View File

@ -56,6 +56,17 @@ void CEngineSurface :: setCursor( Cursor *cursor )
VGUI_CursorSelect( cursor );
}
void CEngineSurface :: GetMousePos( int &x, int &y )
{
POINT curpos;
GetCursorPos( &curpos );
ScreenToClient( host.hWnd, &curpos );
x = curpos.x;
y = curpos.y;
}
void CEngineSurface :: SetupPaintState( const paintState_t &paintState )
{
_translateX = paintState.iTranslateX;

View File

@ -20,6 +20,25 @@ GNU General Public License for more details.
#include "client.h"
#include "library.h"
/*
==============
COM_IsSingleChar
interpert this character as single
==============
*/
qboolean COM_IsSingleChar( char c )
{
if( c == '{' || c == '}' || c == ')' || c == '(' || c == '\'' || c == ',' )
return true;
if( host.com_handlecolon && c == ':' )
return true;
return false;
}
/*
==============
COM_ParseFile
@ -74,7 +93,7 @@ skipwhite:
}
// parse single characters
if( c == '{' || c == '}' || c == ')' || c == '(' || c == '\'' || c == ',' )
if( COM_IsSingleChar( c ))
{
token[len] = c;
len++;
@ -90,7 +109,7 @@ skipwhite:
len++;
c = ((byte)*data);
if( c == '{' || c == '}' || c == ')' || c == '(' || c == '\'' || c == ',' )
if( COM_IsSingleChar( c ))
break;
} while( c > 32 );

View File

@ -325,6 +325,7 @@ typedef struct host_parm_s
qboolean key_overstrike; // key overstrike mode
qboolean stuffcmdsrun; // execute stuff commands
qboolean con_showalways; // show console always (developer and dedicated)
qboolean com_handlecolon; // allow COM_ParseFile to handle colon as single char
qboolean change_game; // initialize when game is changed
qboolean mouse_visible; // vgui override cursor control
qboolean input_enabled; // vgui override mouse & keyboard input

View File

@ -693,18 +693,26 @@ void SV_BuildNetAnswer( netadr_t from )
type = Q_atoi( Cmd_Argv( 3 ));
if( version != PROTOCOL_VERSION )
return;
{
// handle the unsupported protocol
string[0] = '\0';
Info_SetValueForKey( string, "neterror", "protocol" );
// send error unsupported protocol
Q_snprintf( answer, sizeof( answer ), "netinfo %i %i %s\n", context, type, string );
Netchan_OutOfBandPrint( NS_SERVER, from, answer );
return;
}
if( type == NETAPI_REQUEST_PING )
{
Q_snprintf( answer, sizeof( answer ), "netinfo %i %i\n", context, type );
Netchan_OutOfBandPrint( NS_SERVER, from, answer ); // no info string
Q_snprintf( answer, sizeof( answer ), "netinfo %i %i %s\n", context, type, "" );
Netchan_OutOfBandPrint( NS_SERVER, from, answer );
}
else if( type == NETAPI_REQUEST_RULES )
{
// send serverinfo
Q_snprintf( answer, sizeof( answer ), "netinfo %i %i %s\n", context, type, Cvar_Serverinfo( ));
Netchan_OutOfBandPrint( NS_SERVER, from, answer ); // no info string
Netchan_OutOfBandPrint( NS_SERVER, from, answer );
}
else if( type == NETAPI_REQUEST_PLAYERS )
{
@ -723,7 +731,7 @@ void SV_BuildNetAnswer( netadr_t from )
// send playernames
Q_snprintf( answer, sizeof( answer ), "netinfo %i %i %s\n", context, type, string );
Netchan_OutOfBandPrint( NS_SERVER, from, answer ); // no info string
Netchan_OutOfBandPrint( NS_SERVER, from, answer );
}
else if( type == NETAPI_REQUEST_DETAILS )
{
@ -740,7 +748,16 @@ void SV_BuildNetAnswer( netadr_t from )
// send serverinfo
Q_snprintf( answer, sizeof( answer ), "netinfo %i %i %s\n", context, type, string );
Netchan_OutOfBandPrint( NS_SERVER, from, answer ); // no info string
Netchan_OutOfBandPrint( NS_SERVER, from, answer );
}
else
{
string[0] = '\0';
Info_SetValueForKey( string, "neterror", "undefined" );
// send error undefined request type
Q_snprintf( answer, sizeof( answer ), "netinfo %i %i %s\n", context, type, string );
Netchan_OutOfBandPrint( NS_SERVER, from, answer );
}
}

View File

@ -80,7 +80,8 @@
#ifdef _WIN32
# define VGUIAPI __declspec( dllexport )
#else
# define VGUIAPI
# define VGUIAPI __attribute__ ((visibility("default")))
#include <sys/types.h> // size_t define
#endif
#define null 0L
@ -93,7 +94,7 @@ typedef unsigned long ulong;
namespace vgui
{
VGUIAPI void vgui_setMalloc(void* (*malloc)(size_t size));
VGUIAPI void vgui_setMalloc(void *(*malloc)(size_t size) );
VGUIAPI void vgui_setFree(void (*free)(void* memblock));
VGUIAPI void vgui_strcpy(char* dst,int dstLen,const char* src);
VGUIAPI char* vgui_strdup(const char* src);

View File

@ -17,8 +17,6 @@
namespace vgui
{
enum MouseCode;
enum KeyCode;
class Panel;
class TickSignal;
class Scheme;
@ -117,7 +115,7 @@ protected:
bool _buildMode;
bool _wantedBuildMode;
Panel* _mouseArenaPanel;
Cursor* _cursor[Cursor::DefaultCursor::dc_last];
Cursor* _cursor[Cursor::dc_last];
Cursor* _cursorOveride;
private:
long _nextTickMillis;

View File

@ -10,7 +10,8 @@
#include<VGUI.h>
#include<VGUI_Dar.h>
#include <VGUI_MouseCode.h>
#include <VGUI_KeyCode.h>
namespace vgui
{

View File

@ -166,6 +166,7 @@ protected:
ELEMTYPE* _data;
};
#ifdef _WIN32
//forward referencing all the template types used so they get exported
template class VGUIAPI Dar<char>;
template class VGUIAPI Dar<char*>;
@ -185,7 +186,7 @@ template class VGUIAPI Dar<class ChangeSignal*>;
template class VGUIAPI Dar<class Panel*>;
template class VGUIAPI Dar<class Label*>;
template class VGUIAPI Dar<class RepaintSignal*>;
#endif
}

View File

@ -32,6 +32,9 @@ class VGUIAPI Font
virtual void getCharABCwide(int ch,int& a,int& b,int& c);
virtual void getTextSize(const char* text,int& wide,int& tall);
virtual int getTall();
#ifndef _WIN32
virtual int getWide();
#endif
virtual int getId();
protected:
char* _name;

View File

@ -11,6 +11,7 @@
#include<VGUI.h>
#include<VGUI_Panel.h>
#include<VGUI_Scheme.h>
#include<VGUI_Image.h>
//TODO: this should use a TextImage for the text

View File

@ -28,6 +28,10 @@ TODO:
#include<VGUI_Dar.h>
#include<VGUI_Scheme.h>
#include<VGUI_Color.h>
#include<VGUI_Cursor.h>
#include <VGUI_MouseCode.h>
#include <VGUI_KeyCode.h>
#include <VGUI_RepaintSignal.h>
namespace vgui
{

View File

@ -0,0 +1,117 @@
//========= Copyright © 1996-2001, Valve LLC, All rights reserved. ============
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================
#ifndef VGUI_Point_H
#define VGUI_Point_H
#ifdef _WIN32
#pragma once
#endif
#include <VGUI.h>
namespace vgui
{
//-----------------------------------------------------------------------------
// Purpose: Basic handler for a Points in 2 dimensions
// This class is fully inline
//-----------------------------------------------------------------------------
class Point
{
public:
// constructors
Point()
{
SetPoint(0, 0);
}
Point(int x,int y)
{
SetPoint(x,y);
}
void SetPoint(int x1, int y1)
{
x=x1;
y=y1;
}
void GetPoint(int& x1,int& y1) const
{
x1 = x;
y1 = y;
}
bool operator == (Point &rhs) const
{
return ( x == rhs.x && y==rhs.y);
}
private:
int x,y;
};
}
#endif // VGUI_Point_H
//## <b>class Point</b>
//## Point is a class to handle Points in VGUI.
//## // The default Point is (0,0,0,0)
//## Point()
//##
//## // A Point may be created with x,yvalues.
//## Point(int x,int y)
//##
//## // Set the x,y components of the Point.
//## void SetPoint(int x1, int y1)
//##
//## // Get the position of the Point
//## void GetPoint(int& x1,int& y1) const
//##
//## // Point classes can be set equal to each other.
//## bool operator == (Point &rhs) const
//##
//##
//## <hr>
//##
//##
//## <method>Point()
//## Description: Default constructor. The default Point is (0,0,0,0)
//##
//##
//## <method>Point(int x,int y)
//## Description:
//## A Point may be created with a x,y position.
//## Arguments:
//## x - x position (horizontal axis) (0-65535)
//## y - y position (vertical axis) (0-65535)
//##
//##
//## <method>void SetPoint(int x1, int x1)
//## Description:
//## Set the position of the Point.
//## Arguments:
//## x - x position (horizontal axis) (0-65535)
//## y - y position (vertical axis) (0-65535)
//##
//##
//## <method>void GetPoint(int& x1,int& y1) const
//## Description:
//## Get the x,y components of a Point
//## Arguments:
//## x - x position (horizontal axis) (0-65535)
//## y - y position (vertical axis) (0-65535)
//##
//## <method>bool operator == (Point &rhs) const
//## Description:
//## Point classes can be set equal to each other.
//##
//##

View File

@ -12,7 +12,8 @@
namespace vgui
{
class Panel;
class RepaintSignal
{
public:

View File

@ -31,6 +31,7 @@ public:
virtual void createPopup(Panel* embeddedPanel);
virtual bool hasFocus();
virtual bool isWithin(int x,int y);
virtual void GetMousePos( int &x, int &y );
protected:
virtual int createNewTextureID(void);
virtual void drawSetColor(int r,int g,int b,int a);

View File

@ -44,6 +44,7 @@ public:
virtual bool hasFocus()=0;
virtual bool isWithin(int x,int y)=0;
virtual int createNewTextureID(void)=0;
virtual void GetMousePos( int &x, int &y ) = 0;
protected:
virtual void addModeInfo(int wide,int tall,int bpp);
protected:

View File

@ -10,6 +10,7 @@
#include<VGUI_Panel.h>
#include<VGUI_Dar.h>
#include<VGUI_Button.h>
namespace vgui
{

Binary file not shown.