Merge remote-tracking branch 'upstream/master' into theevolk-feature-soundapi

This commit is contained in:
TheEVolk
2026-04-07 18:35:39 +03:00
51 changed files with 1178 additions and 1204 deletions

View File

@@ -612,9 +612,9 @@ static inline mnode_t *node_child( const mnode_t *n, int side, const model_t *mo
}
}
return n->children_[side];
return n->children_[side ? 1 : 0];
#else
return n->children_[side];
return n->children_[side ? 1 : 0];
#endif
}

View File

@@ -255,9 +255,9 @@ static void AVI_StreamAudio( movie_state_t *Avi )
rawchan_t *ch = NULL;
// keep the same semantics, when S_RAW_SOUND_SOUNDTRACK doesn't play if S_StartStreaming wasn't enabled
qboolean disable_stream = Avi->entnum == S_RAW_SOUND_SOUNDTRACK ? !s_listener.streaming : false;
qboolean disable_stream = Avi->entnum == S_RAW_SOUND_SOUNDTRACK ? !snd.streaming : false;
if( !dma.initialized || disable_stream || cl.paused || !Avi->cached_audio )
if( !snd.initialized || disable_stream || cl.paused || !Avi->cached_audio )
return;
ch = S_FindRawChannel( Avi->entnum, true );
@@ -268,14 +268,14 @@ static void AVI_StreamAudio( movie_state_t *Avi )
ch->master_vol = Avi->volume;
ch->dist_mult = (Avi->attn / SND_CLIP_DISTANCE);
if( ch->s_rawend < soundtime )
ch->s_rawend = soundtime;
if( ch->s_rawend < snd.soundtime )
ch->s_rawend = snd.soundtime;
while( ch->s_rawend < soundtime + ch->max_samples )
while( ch->s_rawend < snd.soundtime + ch->max_samples )
{
size_t copy;
buffer_samples = ch->max_samples - (ch->s_rawend - soundtime);
buffer_samples = ch->max_samples - (ch->s_rawend - snd.soundtime);
file_samples = buffer_samples * ((float)Avi->rate / SOUND_DMA_SPEED);
if( file_samples <= 1 ) return; // no more samples need

View File

@@ -70,11 +70,7 @@ void CL_SetFontRendermode( cl_font_t *font )
void CL_SetFontColor( cl_font_t *font, const rgba_t color )
{
// don't apply color to fixed fonts it's already colored
if( font->type != FONT_FIXED || REF_GET_PARM( PARM_TEX_GLFORMAT, font->hFontTexture ) == 0x8045 ) // GL_LUMINANCE8_ALPHA8
ref.dllFuncs.Color4ub( color[0], color[1], color[2], color[3] );
else
ref.dllFuncs.Color4ub( 255, 255, 255, color[3] );
ref.dllFuncs.Color4ub( color[0], color[1], color[2], color[3] );
}
qboolean Con_LoadFixedWidthFont( const char *fontname, cl_font_t *font, float scale, convar_t *rendermode, uint texFlags )

View File

@@ -1381,7 +1381,7 @@ qboolean CL_GetEntitySpatialization( channel_t *ch )
if( ch->entnum == 0 )
{
ch->staticsound = true;
SetBits( ch->flags, FL_CHAN_STATIC_SOUND );
return true; // static sound
}

View File

@@ -37,11 +37,20 @@ GNU General Public License for more details.
#include "platform/platform.h"
#define MAX_LINELENGTH 80
#define MAX_TEXTCHANNELS 8 // must be power of two (GoldSrc uses 4 channels)
#define TEXT_MSGNAME "TextMessage%i"
#define TEXT_MSGNAME "TextMessage"
static char cl_textbuffer[MAX_TEXTCHANNELS][2048];
static client_textmessage_t cl_textmessage[MAX_TEXTCHANNELS];
client_textmessage_t cl_textmessage[MAX_TEXTCHANNELS] =
{
{ .pName = "TextMessage0", .pMessage = cl_textbuffer[0] },
{ .pName = "TextMessage1", .pMessage = cl_textbuffer[1] },
{ .pName = "TextMessage2", .pMessage = cl_textbuffer[2] },
{ .pName = "TextMessage3", .pMessage = cl_textbuffer[3] },
{ .pName = "TextMessage4", .pMessage = cl_textbuffer[4] },
{ .pName = "TextMessage5", .pMessage = cl_textbuffer[5] },
{ .pName = "TextMessage6", .pMessage = cl_textbuffer[6] },
{ .pName = "TextMessage7", .pMessage = cl_textbuffer[7] },
};
static const dllfunc_t cdll_exports[] =
{
@@ -180,7 +189,13 @@ static void CL_InitCDAudio( const char *filename )
while(( pfile = COM_ParseFile( pfile, token, sizeof( token ))) != NULL )
{
if( !Q_stricmp( token, "blank" ))
{
clgame.cdtracks[c][0] = '\0';
}
else if( token[0] == '/' ) // allow custom path
{
Q_strncpy( clgame.cdtracks[c], &token[1], sizeof( clgame.cdtracks[c] ));
}
else
{
Q_snprintf( clgame.cdtracks[c], sizeof( clgame.cdtracks[c] ),
@@ -561,31 +576,18 @@ and hold them into permament memory pool
*/
static void CL_InitTitles( const char *filename )
{
fs_offset_t fileSize;
byte *pMemFile;
int i;
// initialize text messages (game_text)
for( i = 0; i < MAX_TEXTCHANNELS; i++ )
{
char name[MAX_VA_STRING];
Q_snprintf( name, sizeof( name ), TEXT_MSGNAME, i );
cl_textmessage[i].pName = copystringpool( clgame.mempool, name );
cl_textmessage[i].pMessage = cl_textbuffer[i];
}
// clear out any old data that's sitting around.
if( clgame.titles ) Mem_Free( clgame.titles );
Mem_Free( clgame.titles );
clgame.titles = NULL;
clgame.numTitles = 0;
pMemFile = FS_LoadFile( filename, &fileSize, false );
if( !pMemFile ) return;
fs_offset_t fileSize = 0;
char *pMemFile = (char *)FS_LoadFile( filename, &fileSize, false );
if( !pMemFile )
return;
clgame.titles = CL_TextMessageParse( clgame.mempool, (char *)pMemFile, fileSize, &clgame.numTitles );
clgame.titles = CL_TextMessageParse( clgame.mempool, pMemFile, fileSize, &clgame.numTitles );
Mem_Free( pMemFile );
}
@@ -654,54 +656,6 @@ void CL_ParseTextMessage( sizebuf_t *msg )
CL_HudMessage( text->pName );
}
/*
================
CL_ParseFinaleCutscene
show display finale or cutscene message
================
*/
void CL_ParseFinaleCutscene( sizebuf_t *msg, int level )
{
static int msgindex = 0;
client_textmessage_t *text;
int channel;
cl.intermission = level;
channel = msgindex;
msgindex = (msgindex + 1) & (MAX_TEXTCHANNELS - 1);
// grab message channel
text = &cl_textmessage[channel];
// NOTE: svc_finale and svc_cutscene has a
// predefined settings like Quake-style
text->x = -1.0f;
text->y = 0.15f;
text->effect = 2; // scan out effect
text->r1 = 245;
text->g1 = 245;
text->b1 = 245;
text->a1 = 0; // unused
text->r2 = 0;
text->g2 = 0;
text->b2 = 0;
text->a2 = 0;
text->fadein = 0.15f;
text->fadeout = 0.0f;
text->holdtime = 99999.0f;
text->fxtime = 0.0f;
// to prevent grab too long messages
Q_strncpy( (char *)text->pMessage, MSG_ReadString( msg ), 2048 );
if( *text->pMessage == '\0' )
return; // no real text
CL_HudMessage( text->pName );
}
/*
====================
CL_GetMaxlients
@@ -1975,13 +1929,12 @@ client_textmessage_t *CL_TextMessageGet( const char *pName )
int i;
// first check internal messages
for( i = 0; i < MAX_TEXTCHANNELS; i++ )
if( Q_strlen( pName ) == sizeof( TEXT_MSGNAME ) // including the digit
&& !Q_strncmp( pName, TEXT_MSGNAME, sizeof( TEXT_MSGNAME ) - 1 ))
{
char name[MAX_VA_STRING];
i = pName[sizeof( TEXT_MSGNAME ) - 1] - '0';
Q_snprintf( name, sizeof( name ), TEXT_MSGNAME, i );
if( !Q_strcmp( pName, name ))
if( i >= 0 && i < MAX_TEXTCHANNELS )
return cl_textmessage + i;
}
@@ -4096,14 +4049,14 @@ qboolean CL_LoadProgs( const char *name )
CL_InitCDAudio( "media/cdaudio.txt" );
CL_InitTitles( "titles.txt" );
CL_InitParticles ();
CL_InitViewBeams ();
CL_InitTempEnts ();
CL_InitParticles( );
CL_InitViewBeams( );
CL_InitTempEnts( );
if( !R_InitRenderAPI()) // Xash3D extension
if( !R_InitRenderAPI( )) // Xash3D extension
Con_Reportf( S_WARN "%s: couldn't get render API\n", __func__ );
if( !Mobile_Init() ) // Xash3D FWGS extension: mobile interface
if( !Mobile_Init( )) // Xash3D FWGS extension: mobile interface
Con_Reportf( S_WARN "%s: couldn't get mobility API\n", __func__ );
CL_InitEdicts( cl.maxclients ); // initailize local player and world

View File

@@ -1174,7 +1174,7 @@ static void CL_SendConnectPacket( connprotocol_t proto, int challenge )
else
{
const char *qport = Cvar_VariableString( "net_qport" );
int extensions = NET_EXT_SPLITSIZE;
int extensions = Host_IsLocalGame() ? 0 : NET_EXT_SPLITSIZE;
string key;
ID_GetMD5ForAddress( key, adr, sizeof( key ));

View File

@@ -42,7 +42,7 @@ CL_ParseViewEntity
==================
*/
void CL_ParseViewEntity( sizebuf_t *msg )
static void CL_ParseViewEntity( sizebuf_t *msg )
{
cl.viewentity = MSG_ReadWord( msg );
@@ -161,7 +161,7 @@ CL_ParseSignon
==================
*/
void CL_ParseSignon( sizebuf_t *msg, connprotocol_t proto )
static void CL_ParseSignon( sizebuf_t *msg, connprotocol_t proto )
{
int i = MSG_ReadByte( msg );
@@ -209,7 +209,7 @@ CL_ParseParticles
==================
*/
void CL_ParseParticles( sizebuf_t *msg, connprotocol_t proto )
static void CL_ParseParticles( sizebuf_t *msg, connprotocol_t proto )
{
vec3_t org, dir;
int i, count, color;
@@ -362,7 +362,7 @@ CL_ParseSoundFade
==================
*/
void CL_ParseSoundFade( sizebuf_t *msg )
static void CL_ParseSoundFade( sizebuf_t *msg )
{
int fade_percent = MSG_ReadByte( msg );
int hold_time = MSG_ReadByte( msg );
@@ -616,7 +616,7 @@ CL_ParseCustomization
==================
*/
void CL_ParseCustomization( sizebuf_t *msg )
static void CL_ParseCustomization( sizebuf_t *msg )
{
customization_t *pExistingCustomization;
customization_t *pList;
@@ -704,7 +704,7 @@ CL_ParseResourceRequest
==================
*/
void CL_ParseResourceRequest( sizebuf_t *msg )
static void CL_ParseResourceRequest( sizebuf_t *msg )
{
byte buffer[MAX_INIT_MSG];
int i, arg, nStartIndex;
@@ -776,7 +776,7 @@ CL_ParseFileTransferFailed
==================
*/
void CL_ParseFileTransferFailed( sizebuf_t *msg )
static void CL_ParseFileTransferFailed( sizebuf_t *msg )
{
const char *name = MSG_ReadString( msg );
@@ -796,7 +796,7 @@ void CL_ParseFileTransferFailed( sizebuf_t *msg )
CL_ParseServerData
==================
*/
void CL_ParseServerData( sizebuf_t *msg, connprotocol_t proto )
static void CL_ParseServerData( sizebuf_t *msg, connprotocol_t proto )
{
char gamefolder[MAX_QPATH];
string mapfile;
@@ -1234,7 +1234,7 @@ void CL_ParseBaseline( sizebuf_t *msg, connprotocol_t proto )
CL_ParseLightStyle
================
*/
void CL_ParseLightStyle( sizebuf_t *msg, connprotocol_t proto )
static void CL_ParseLightStyle( sizebuf_t *msg, connprotocol_t proto )
{
int style;
const char *s;
@@ -1255,7 +1255,7 @@ CL_ParseSetAngle
set the view angle to this absolute value
================
*/
void CL_ParseSetAngle( sizebuf_t *msg )
static void CL_ParseSetAngle( sizebuf_t *msg )
{
MSG_ReadVec3Angles( msg, cl.viewangles );
}
@@ -1267,7 +1267,7 @@ CL_ParseAddAngle
add the view angle yaw
================
*/
void CL_ParseAddAngle( sizebuf_t *msg )
static void CL_ParseAddAngle( sizebuf_t *msg )
{
pred_viewangle_t *a;
float delta_yaw;
@@ -1296,7 +1296,7 @@ CL_ParseCrosshairAngle
offset crosshair angles
================
*/
void CL_ParseCrosshairAngle( sizebuf_t *msg )
static void CL_ParseCrosshairAngle( sizebuf_t *msg )
{
cl.crosshairangle[0] = MSG_ReadChar( msg ) * 0.2f;
cl.crosshairangle[1] = MSG_ReadChar( msg ) * 0.2f;
@@ -1310,7 +1310,7 @@ CL_ParseRestore
reading decals, etc.
================
*/
void CL_ParseRestore( sizebuf_t *msg )
static void CL_ParseRestore( sizebuf_t *msg )
{
string filename;
int i, mapCount;
@@ -1337,7 +1337,7 @@ CL_RegisterUserMessage
register new user message or update existing
================
*/
void CL_RegisterUserMessage( sizebuf_t *msg, connprotocol_t proto )
static void CL_RegisterUserMessage( sizebuf_t *msg, connprotocol_t proto )
{
char *pszName;
char szName[17];
@@ -1375,7 +1375,7 @@ CL_UpdateUserinfo
collect userinfo from all players
================
*/
void CL_UpdateUserinfo( sizebuf_t *msg, connprotocol_t proto )
static void CL_UpdateUserinfo( sizebuf_t *msg, connprotocol_t proto )
{
int slot, id;
qboolean active;
@@ -1898,7 +1898,7 @@ CL_ParseVoiceInit
==================
*/
void CL_ParseVoiceInit( sizebuf_t *msg )
static void CL_ParseVoiceInit( sizebuf_t *msg )
{
char *pszCodec = MSG_ReadString( msg );
int quality = MSG_ReadByte( msg );
@@ -1912,7 +1912,7 @@ CL_ParseVoiceData
==================
*/
void CL_ParseVoiceData( sizebuf_t *msg, connprotocol_t proto )
static void CL_ParseVoiceData( sizebuf_t *msg, connprotocol_t proto )
{
int size, idx, frames = 0;
byte received[VOICE_MAX_DATA_SIZE];
@@ -1962,7 +1962,7 @@ CL_ParseResLocation
==================
*/
void CL_ParseResLocation( sizebuf_t *msg )
static void CL_ParseResLocation( sizebuf_t *msg )
{
char *data = MSG_ReadString( msg );
char token[256];
@@ -1991,7 +1991,7 @@ sended from game.dll
normal client ignores any of HLTV messages
==============
*/
void CL_ParseHLTV( sizebuf_t *msg )
static void CL_ParseHLTV( sizebuf_t *msg )
{
switch( MSG_ReadByte( msg ))
{
@@ -2025,7 +2025,7 @@ spectator message (director)
sended from game.dll
==============
*/
void CL_ParseDirector( sizebuf_t *msg )
static void CL_ParseDirector( sizebuf_t *msg )
{
int iSize = MSG_ReadByte( msg );
byte pbuf[256];
@@ -2119,7 +2119,7 @@ Find the client cvar value
and sent it back to the server
==============
*/
void CL_ParseCvarValue( sizebuf_t *msg, const qboolean ext, const connprotocol_t proto )
static void CL_ParseCvarValue( sizebuf_t *msg, const qboolean ext, const connprotocol_t proto )
{
const char *cvarName, *response = NULL;
convar_t *cvar;
@@ -2181,7 +2181,7 @@ CL_ParseExec
Exec map/class specific configs
==============
*/
void CL_ParseExec( sizebuf_t *msg )
static void CL_ParseExec( sizebuf_t *msg )
{
qboolean is_class;
int class_idx;
@@ -2357,25 +2357,150 @@ ACTION MESSAGES
*/
/*
============
CL_ParseCommonDLLMessage
================
CL_ParseFinaleCutscene
parse a message which structure is enforced by DLL compatibility
it should always be the same regardless of protocol used
show display finale or cutscene message
================
*/
static void CL_ParseFinaleCutscene( sizebuf_t *msg, int level )
{
static int msgindex = 0;
client_textmessage_t *text;
int channel;
cl.intermission = level;
channel = msgindex;
msgindex = (msgindex + 1) & (MAX_TEXTCHANNELS - 1);
// grab message channel
text = &cl_textmessage[channel];
// NOTE: svc_finale and svc_cutscene has a
// predefined settings like Quake-style
text->x = -1.0f;
text->y = 0.15f;
text->effect = 2; // scan out effect
text->r1 = 245;
text->g1 = 245;
text->b1 = 245;
text->a1 = 0; // unused
text->r2 = 0;
text->g2 = 0;
text->b2 = 0;
text->a2 = 0;
text->fadein = 0.15f;
text->fadeout = 0.0f;
text->holdtime = 99999.0f;
text->fxtime = 0.0f;
// to prevent grab too long messages
Q_strncpy( (char *)text->pMessage, MSG_ReadString( msg ), 2048 );
if( *text->pMessage == '\0' )
return; // no real text
CL_HudMessage( text->pName );
}
/*
============
CL_ParseCommonMessage
parse a message which is the same across all supported protocols
============
*/
qboolean CL_ParseCommonDLLMessage( sizebuf_t *msg, connprotocol_t proto, int svc_num, int startoffset )
qboolean CL_ParseCommonMessage( sizebuf_t *msg, connprotocol_t proto, int svc_num, int startoffset )
{
int param1, param2;
switch( svc_num )
{
case svc_nop:
break;
case svc_setview:
CL_ParseViewEntity( msg );
break;
case svc_lightstyle:
CL_ParseLightStyle( msg, proto );
break;
case svc_intermission:
cl.intermission = 1;
break;
case svc_finale:
CL_ParseFinaleCutscene( msg, 2 );
break;
case svc_cutscene:
CL_ParseFinaleCutscene( msg, 3 );
break;
default:
return false;
}
return true;
}
/*
============
CL_ParseCommonHLMessage
parse a message which structure is enforced by DLL compatibility
it should always be the same regardless of HL-based protocol used
============
*/
qboolean CL_ParseCommonHLMessage( sizebuf_t *msg, connprotocol_t proto, int svc_num, int startoffset )
{
const char *s;
int param1, param2;
switch( svc_num )
{
case svc_bad:
Host_Error( "svc_bad\n" );
break;
case svc_time:
CL_ParseServerTime( msg, proto );
break;
case svc_print:
Con_Printf( "%s", MSG_ReadString( msg ));
break;
case svc_stufftext:
s = MSG_ReadString( msg );
if( cl_trace_stufftext.value )
{
size_t len = Q_strlen( s );
Con_Printf( "Stufftext: %s%c", s, len && s[len-1] == '\n' ? '\0' : '\n' );
}
#ifdef HACKS_RELATED_HLMODS
// disable Cry Of Fear antisave protection
if( !Q_strnicmp( s, "disconnect", 10 ) && cls.signon != SIGNONS )
break; // too early
#endif
Cbuf_AddFilteredText( s );
break;
case svc_setangle:
CL_ParseSetAngle( msg );
break;
case svc_serverdata:
Cbuf_Execute(); // make sure any stuffed commands are done
CL_ParseServerData( msg, proto );
break;
case svc_updateuserinfo:
CL_UpdateUserinfo( msg, proto );
break;
case svc_particle:
CL_ParseParticles( msg, proto );
break;
case svc_temp_entity:
CL_ParseTempEntity( msg, proto ); // need protocol because message header differs
cl.frames[cl.parsecountmod].graphdata.tentities += MSG_GetNumBytesRead( msg ) - startoffset;
break;
case svc_intermission:
cl.intermission = 1;
case svc_signonnum:
CL_ParseSignon( msg, proto );
break;
case svc_centerprint:
CL_CenterPrint( MSG_ReadString( msg ), 0.25f );
break;
case svc_cdtrack:
param1 = MSG_ReadByte( msg );
@@ -2384,6 +2509,9 @@ qboolean CL_ParseCommonDLLMessage( sizebuf_t *msg, connprotocol_t proto, int svc
param2 = bound( 1, param2, MAX_CDTRACKS ); // loopnum
S_StartBackgroundTrack( clgame.cdtracks[param1-1], clgame.cdtracks[param2-1], 0, false );
break;
case svc_restore:
CL_ParseRestore( msg );
break;
case svc_weaponanim:
param1 = MSG_ReadByte( msg ); // iAnim
param2 = MSG_ReadByte( msg ); // body
@@ -2393,9 +2521,56 @@ qboolean CL_ParseCommonDLLMessage( sizebuf_t *msg, connprotocol_t proto, int svc
param1 = MSG_ReadShort( msg );
Cvar_SetValue( "room_type", param1 );
break;
case svc_addangle:
CL_ParseAddAngle( msg );
break;
case svc_usermessage:
CL_RegisterUserMessage( msg, proto );
break;
case svc_choke:
cl.frames[cls.netchan.incoming_sequence & CL_UPDATE_MASK].choked = true;
cl.frames[cls.netchan.incoming_sequence & CL_UPDATE_MASK].receivedtime = -2.0;
break;
case svc_resourcerequest:
CL_ParseResourceRequest( msg );
break;
case svc_customization:
CL_ParseCustomization( msg );
break;
case svc_crosshairangle:
CL_ParseCrosshairAngle( msg );
break;
case svc_soundfade:
CL_ParseSoundFade( msg );
break;
case svc_filetxferfailed:
CL_ParseFileTransferFailed( msg );
break;
case svc_hltv:
CL_ParseHLTV( msg );
break;
case svc_director:
CL_ParseDirector( msg );
break;
case svc_voiceinit:
CL_ParseVoiceInit( msg );
break;
case svc_voicedata:
CL_ParseVoiceData( msg, proto );
cl.frames[cl.parsecountmod].graphdata.voicebytes += MSG_GetNumBytesRead( msg ) - startoffset;
break;
case svc_resourcelocation:
CL_ParseResLocation( msg );
break;
case svc_querycvarvalue:
CL_ParseCvarValue( msg, false, proto );
break;
case svc_querycvarvalue2:
CL_ParseCvarValue( msg, true, proto );
break;
case svc_exec:
CL_ParseExec( msg );
break;
default:
return false;
}
@@ -2415,7 +2590,6 @@ void CL_ParseServerMessage( sizebuf_t *msg )
size_t bufStart, playerbytes;
int cmd;
int old_background;
const char *s;
// parse the message
while( 1 )
@@ -2438,18 +2612,15 @@ void CL_ParseServerMessage( sizebuf_t *msg )
// record command for debugging spew on parse problem
CL_Parse_RecordCommand( cmd, bufStart );
if( CL_ParseCommonDLLMessage( msg, PROTO_CURRENT, cmd, bufStart ))
if( CL_ParseCommonMessage( msg, PROTO_CURRENT, cmd, bufStart ))
continue;
if( CL_ParseCommonHLMessage( msg, PROTO_CURRENT, cmd, bufStart ))
continue;
// other commands
switch( cmd )
{
case svc_bad:
Host_Error( "svc_bad\n" );
break;
case svc_nop:
// this does nothing
break;
case svc_disconnect:
CL_Drop ();
Host_AbortCurrentFrame ();
@@ -2497,48 +2668,10 @@ void CL_ParseServerMessage( sizebuf_t *msg )
cls.connect_retry = 0;
}
break;
case svc_setview:
CL_ParseViewEntity( msg );
break;
case svc_sound:
CL_ParseSoundPacket( msg, false );
cl.frames[cl.parsecountmod].graphdata.sound += MSG_GetNumBytesRead( msg ) - bufStart;
break;
case svc_time:
CL_ParseServerTime( msg, PROTO_CURRENT );
break;
case svc_print:
Con_Printf( "%s", MSG_ReadString( msg ));
break;
case svc_stufftext:
s = MSG_ReadString( msg );
if( cl_trace_stufftext.value )
{
size_t len = Q_strlen( s );
Con_Printf( "Stufftext: %s%c", s, len && s[len-1] == '\n' ? '\0' : '\n' );
}
#ifdef HACKS_RELATED_HLMODS
// disable Cry Of Fear antisave protection
if( !Q_strnicmp( s, "disconnect", 10 ) && cls.signon != SIGNONS )
break; // too early
#endif
Cbuf_AddFilteredText( s );
break;
case svc_setangle:
CL_ParseSetAngle( msg );
break;
case svc_serverdata:
Cbuf_Execute(); // make sure any stuffed commands are done
CL_ParseServerData( msg, PROTO_CURRENT );
break;
case svc_lightstyle:
CL_ParseLightStyle( msg, PROTO_CURRENT );
break;
case svc_updateuserinfo:
CL_UpdateUserinfo( msg, PROTO_CURRENT );
break;
case svc_deltatable:
Delta_ParseTableField( msg );
break;
@@ -2552,9 +2685,6 @@ void CL_ParseServerMessage( sizebuf_t *msg )
case svc_pings:
CL_UpdateUserPings( msg );
break;
case svc_particle:
CL_ParseParticles( msg, PROTO_CURRENT );
break;
case svc_restoresound:
CL_ParseSoundPacket( msg, true );
cl.frames[cl.parsecountmod].graphdata.sound += MSG_GetNumBytesRead( msg ) - bufStart;
@@ -2572,30 +2702,9 @@ void CL_ParseServerMessage( sizebuf_t *msg )
case svc_setpause:
cl.paused = ( MSG_ReadOneBit( msg ) != 0 );
break;
case svc_signonnum:
CL_ParseSignon( msg, PROTO_CURRENT );
break;
case svc_centerprint:
CL_CenterPrint( MSG_ReadString( msg ), 0.25f );
break;
case svc_finale:
CL_ParseFinaleCutscene( msg, 2 );
break;
case svc_restore:
CL_ParseRestore( msg );
break;
case svc_cutscene:
CL_ParseFinaleCutscene( msg, 3 );
break;
case svc_bspdecal:
CL_ParseStaticDecal( msg );
break;
case svc_addangle:
CL_ParseAddAngle( msg );
break;
case svc_usermessage:
CL_RegisterUserMessage( msg, PROTO_CURRENT );
break;
case svc_packetentities:
playerbytes = CL_ParsePacketEntities( msg, false, PROTO_CURRENT );
cl.frames[cl.parsecountmod].graphdata.players += playerbytes;
@@ -2606,53 +2715,12 @@ void CL_ParseServerMessage( sizebuf_t *msg )
cl.frames[cl.parsecountmod].graphdata.players += playerbytes;
cl.frames[cl.parsecountmod].graphdata.entities += MSG_GetNumBytesRead( msg ) - bufStart - playerbytes;
break;
case svc_choke:
cl.frames[cls.netchan.incoming_sequence & CL_UPDATE_MASK].choked = true;
cl.frames[cls.netchan.incoming_sequence & CL_UPDATE_MASK].receivedtime = -2.0;
break;
case svc_resourcelist:
CL_ParseResourceList( msg, PROTO_CURRENT );
break;
case svc_deltamovevars:
CL_ParseMovevars( msg );
break;
case svc_resourcerequest:
CL_ParseResourceRequest( msg );
break;
case svc_customization:
CL_ParseCustomization( msg );
break;
case svc_crosshairangle:
CL_ParseCrosshairAngle( msg );
break;
case svc_soundfade:
CL_ParseSoundFade( msg );
break;
case svc_filetxferfailed:
CL_ParseFileTransferFailed( msg );
break;
case svc_hltv:
CL_ParseHLTV( msg );
break;
case svc_voiceinit:
CL_ParseVoiceInit( msg );
break;
case svc_voicedata:
CL_ParseVoiceData( msg, PROTO_CURRENT );
cl.frames[cl.parsecountmod].graphdata.voicebytes += MSG_GetNumBytesRead( msg ) - bufStart;
break;
case svc_resourcelocation:
CL_ParseResLocation( msg );
break;
case svc_querycvarvalue:
CL_ParseCvarValue( msg, false, PROTO_CURRENT );
break;
case svc_querycvarvalue2:
CL_ParseCvarValue( msg, true, PROTO_CURRENT );
break;
case svc_exec:
CL_ParseExec( msg );
break;
default:
CL_ParseUserMessage( msg, cmd, PROTO_CURRENT );
cl.frames[cl.parsecountmod].graphdata.usr += MSG_GetNumBytesRead( msg ) - bufStart;

View File

@@ -569,22 +569,15 @@ void CL_ParseGoldSrcServerMessage( sizebuf_t *msg )
// record command for debugging spew on parse problem
CL_Parse_RecordCommand( cmd, bufStart );
if( CL_ParseCommonDLLMessage( msg, PROTO_GOLDSRC, cmd, bufStart ))
if( CL_ParseCommonMessage( msg, PROTO_GOLDSRC, cmd, bufStart ))
continue;
if( CL_ParseCommonHLMessage( msg, PROTO_GOLDSRC, cmd, bufStart ))
continue;
// other commands
switch( cmd )
{
case svc_bad:
Host_Error( "svc_bad\n" );
break;
case svc_nop:
case svc_spawnstatic:
case svc_goldsrc_damage:
case svc_goldsrc_killedmonster:
case svc_goldsrc_foundsecret:
// this does nothing
break;
case svc_disconnect:
s = MSG_ReadString( msg );
if( !COM_StringEmpty( s ))
@@ -603,47 +596,10 @@ void CL_ParseGoldSrcServerMessage( sizebuf_t *msg )
if( param1 != PROTOCOL_GOLDSRC_VERSION )
Host_Error( "Server use invalid protocol (%i should be %i)\n", param1, PROTOCOL_GOLDSRC_VERSION );
break;
case svc_setview:
CL_ParseViewEntity( msg );
break;
case svc_sound:
CL_ParseSoundPacketGS( msg );
cl.frames[cl.parsecountmod].graphdata.sound += MSG_GetNumBytesRead( msg ) - bufStart;
break;
case svc_time:
CL_ParseServerTime( msg, PROTO_GOLDSRC );
break;
case svc_print:
Con_Printf( "%s", MSG_ReadString( msg ));
break;
case svc_stufftext:
s = MSG_ReadString( msg );
if( cl_trace_stufftext.value )
{
size_t len = Q_strlen( s );
Con_Printf( "Stufftext: %s%c", s, len && s[len-1] == '\n' ? '\0' : '\n' );
}
#ifdef HACKS_RELATED_HLMODS
// disable Cry Of Fear antisave protection
if( !Q_strnicmp( s, "disconnect", 10 ) && cls.signon != SIGNONS )
break; // too early
#endif
Cbuf_AddFilteredText( s );
break;
case svc_setangle:
CL_ParseSetAngle( msg );
break;
case svc_serverdata:
Cbuf_Execute(); // make sure any stuffed commands are done
CL_ParseServerData( msg, PROTO_GOLDSRC );
break;
case svc_lightstyle:
CL_ParseLightStyle( msg, PROTO_GOLDSRC );
break;
case svc_updateuserinfo:
CL_UpdateUserinfo( msg, PROTO_GOLDSRC );
break;
case svc_deltatable:
Delta_ParseTableField_GS( msg );
break;
@@ -663,8 +619,9 @@ void CL_ParseGoldSrcServerMessage( sizebuf_t *msg )
CL_UpdateUserPings( msg );
MSG_EndBitWriting( msg );
break;
case svc_particle:
CL_ParseParticles( msg, PROTO_GOLDSRC );
case svc_goldsrc_damage:
case svc_spawnstatic:
// this does nothing
break;
case svc_event_reliable:
MSG_StartBitWriting( msg );
@@ -680,35 +637,18 @@ void CL_ParseGoldSrcServerMessage( sizebuf_t *msg )
case svc_setpause:
cl.paused = ( MSG_ReadByte( msg ) != 0 );
break;
case svc_signonnum:
CL_ParseSignon( msg, PROTO_GOLDSRC );
break;
case svc_centerprint:
CL_CenterPrint( MSG_ReadString( msg ), 0.25f );
case svc_goldsrc_killedmonster:
case svc_goldsrc_foundsecret:
// this does nothing
break;
case svc_goldsrc_spawnstaticsound:
CL_ParseSpawnStaticSound( msg );
break;
case svc_finale:
CL_ParseFinaleCutscene( msg, 2 );
break;
case svc_restore:
CL_ParseRestore( msg );
break;
case svc_cutscene:
CL_ParseFinaleCutscene( msg, 3 );
break;
case svc_goldsrc_decalname:
param1 = MSG_ReadByte( msg );
s = MSG_ReadString( msg );
Q_strncpy( host.draw_decals[param1], s, sizeof( host.draw_decals[param1] ));
break;
case svc_addangle:
CL_ParseAddAngle( msg );
break;
case svc_usermessage:
CL_RegisterUserMessage( msg, PROTO_GOLDSRC );
break;
case svc_packetentities:
playerbytes = CL_ParsePacketEntitiesGS( msg, false );
cl.frames[cl.parsecountmod].graphdata.players += playerbytes;
@@ -719,10 +659,6 @@ void CL_ParseGoldSrcServerMessage( sizebuf_t *msg )
cl.frames[cl.parsecountmod].graphdata.players += playerbytes;
cl.frames[cl.parsecountmod].graphdata.entities += MSG_GetNumBytesRead( msg ) - bufStart - playerbytes;
break;
case svc_choke:
cl.frames[cls.netchan.incoming_sequence & CL_UPDATE_MASK].choked = true;
cl.frames[cls.netchan.incoming_sequence & CL_UPDATE_MASK].receivedtime = -2.0;
break;
case svc_resourcelist:
MSG_StartBitWriting( msg );
CL_ParseResourceList( msg, PROTO_GOLDSRC );
@@ -731,34 +667,6 @@ void CL_ParseGoldSrcServerMessage( sizebuf_t *msg )
case svc_deltamovevars:
CL_ParseNewMovevars( msg );
break;
case svc_resourcerequest:
CL_ParseResourceRequest( msg );
break;
case svc_customization:
CL_ParseCustomization( msg );
break;
case svc_crosshairangle:
CL_ParseCrosshairAngle( msg );
break;
case svc_soundfade:
CL_ParseSoundFade( msg );
break;
case svc_filetxferfailed:
CL_ParseFileTransferFailed( msg );
break;
case svc_hltv:
CL_ParseHLTV( msg );
break;
case svc_voiceinit:
CL_ParseVoiceInit( msg );
break;
case svc_voicedata:
CL_ParseVoiceData( msg, PROTO_GOLDSRC );
cl.frames[cl.parsecountmod].graphdata.voicebytes += MSG_GetNumBytesRead( msg ) - bufStart;
break;
case svc_resourcelocation:
CL_ParseResLocation( msg );
break;
case svc_goldsrc_sendextrainfo:
CL_ParseExtraInfo( msg );
break;
@@ -768,15 +676,6 @@ void CL_ParseGoldSrcServerMessage( sizebuf_t *msg )
Con_Reportf( S_ERROR "%s: svc_goldsrc_timescale: implement me!\n", __func__ );
MSG_ReadFloat( msg );
break;
case svc_querycvarvalue:
CL_ParseCvarValue( msg, false, PROTO_GOLDSRC );
break;
case svc_querycvarvalue2:
CL_ParseCvarValue( msg, true, PROTO_GOLDSRC );
break;
case svc_exec:
CL_ParseExec( msg );
break;
default:
CL_ParseUserMessage( msg, cmd, PROTO_GOLDSRC );
cl.frames[cl.parsecountmod].graphdata.usr += MSG_GetNumBytesRead( msg ) - bufStart;

View File

@@ -930,12 +930,12 @@ void CL_ParseQuakeMessage( sizebuf_t *msg )
// record command for debugging spew on parse problem
CL_Parse_RecordCommand( cmd, bufStart );
if( CL_ParseCommonMessage( msg, PROTO_QUAKE, cmd, bufStart ))
continue;
// other commands
switch( cmd )
{
case svc_nop:
// this does nothing
break;
case svc_disconnect:
CL_DemoCompleted ();
break;
@@ -947,9 +947,6 @@ void CL_ParseQuakeMessage( sizebuf_t *msg )
if( param1 != PROTOCOL_VERSION_QUAKE )
Host_Error( "Server is protocol %i instead of %i\n", param1, PROTOCOL_VERSION_QUAKE );
break;
case svc_setview:
CL_ParseViewEntity( msg );
break;
case svc_sound:
CL_ParseQuakeSound( msg );
cl.frames[cl.parsecountmod].graphdata.sound += MSG_GetNumBytesRead( msg ) - bufStart;
@@ -974,9 +971,6 @@ void CL_ParseQuakeMessage( sizebuf_t *msg )
Cbuf_Execute(); // make sure any stuffed commands are done
CL_ParseQuakeServerInfo( msg );
break;
case svc_lightstyle:
CL_ParseLightStyle( msg, PROTO_QUAKE );
break;
case svc_updatename:
param1 = MSG_ReadByte( msg );
Q_strncpy( cl.players[param1].name, MSG_ReadString( msg ), sizeof( cl.players[0].name ));
@@ -1029,8 +1023,7 @@ void CL_ParseQuakeMessage( sizebuf_t *msg )
CL_ParseQuakeSignon( msg );
break;
case svc_centerprint:
str = MSG_ReadString( msg );
CL_DispatchUserMessage( "HudText", Q_strlen( str ) + 1, (void *)str );
CL_HudMessage( MSG_ReadString( msg ));
break;
case svc_killedmonster:
CL_DispatchQuakeMessage( "KillMonster" ); // just an event
@@ -1041,12 +1034,6 @@ void CL_ParseQuakeMessage( sizebuf_t *msg )
case svc_spawnstaticsound:
CL_ParseQuakeStaticSound( msg );
break;
case svc_intermission:
cl.intermission = 1;
break;
case svc_finale:
CL_ParseFinaleCutscene( msg, 2 );
break;
case svc_cdtrack:
param1 = MSG_ReadByte( msg );
param1 = bound( 0, param1, MAX_CDTRACKS - 1 ); // tracknum
@@ -1059,15 +1046,12 @@ void CL_ParseQuakeMessage( sizebuf_t *msg )
case svc_sellscreen:
Cmd_ExecuteString( "help" ); // open quake menu
break;
case svc_cutscene:
CL_ParseFinaleCutscene( msg, 3 );
case svc_showlmp:
CL_ParseNehahraShowLMP( msg );
break;
case svc_hidelmp:
CL_ParseNehahraHideLMP( msg );
break;
case svc_showlmp:
CL_ParseNehahraShowLMP( msg );
break;
case svc_skybox:
Q_strncpy( clgame.movevars.skyName, MSG_ReadString( msg ), sizeof( clgame.movevars.skyName ));
break;

View File

@@ -744,7 +744,7 @@ void SCR_LoadCreditsFont( void )
success = Con_LoadVariableWidthFont( "gfx/creditsfont.fnt", font, scale, &hud_fontrender, TF_FONT );
if( !success )
success = Con_LoadFixedWidthFont( "gfx/conchars", font, scale, &hud_fontrender, TF_FONT );
success = Con_LoadFixedWidthFont( "gfx/conchars", font, scale, &hud_fontrender, TF_FONT|TF_NEAREST );
// copy font size for client.dll
if( success )

View File

@@ -37,11 +37,6 @@ GNU General Public License for more details.
#include "voice.h"
#include "q_client.h"
// client sprite types
#define SPR_CLIENT 0 // client sprite for temp-entities or user-textures
#define SPR_HUDSPRITE 1 // hud sprite
#define SPR_MAPSPRITE 2 // contain overview.bmp that diced into frames 128x128
//=============================================================================
typedef struct netbandwithgraph_s
{
@@ -112,6 +107,8 @@ extern int CL_UPDATE_BACKUP;
#define MAX_EX_INTERP 0.1f
#define MAX_TEXTCHANNELS 8 // must be power of two (GoldSrc uses 4 channels)
#define CL_MIN_RESEND_TIME 1.5f // mininum time gap (in seconds) before a subsequent connection request is sent.
#define CL_MAX_RESEND_TIME 20.0f // max time. The cvar cl_resend is bounded by these.
@@ -311,6 +308,14 @@ typedef enum
CL_CHANGELEVEL, // draw 'loading' during changelevel
} scrstate_t;
// client sprite types
enum
{
SPR_CLIENT = 0, // client sprite for temp-entities or user-textures
SPR_HUDSPRITE, // hud sprite
SPR_MAPSPRITE, // contain overview.bmp that diced into frames 128x128
};
typedef struct
{
char name[32];
@@ -733,10 +738,7 @@ extern convar_t cl_fixmodelinterpolationartifacts;
//=============================================================================
void CL_SetLightstyle( int style, const char* s, float f );
void CL_DecayLights( void );
dlight_t *CL_GetDynamicLight( int number );
dlight_t *CL_GetEntityLight( int number );
extern client_textmessage_t cl_textmessage[MAX_TEXTCHANNELS];
//=================================================
@@ -855,6 +857,7 @@ void CL_FreeEdicts( void );
void CL_ClearWorld( void );
void CL_DrawCenterPrint( void );
void CL_ClearSpriteTextures( void );
void CL_HudMessage( const char *pMessage );
void CL_CenterPrint( const char *text, float y );
client_textmessage_t *CL_TextMessageGet( const char *pName );
void NetAPI_CancelAllRequests( void );
@@ -925,45 +928,23 @@ static inline cl_entity_t *CL_GetLocalPlayer( void )
//
// cl_parse.c
//
void CL_ParseSetAngle( sizebuf_t *msg );
void CL_ParseServerData( sizebuf_t *msg, connprotocol_t proto );
void CL_ParseLightStyle( sizebuf_t *msg, connprotocol_t proto );
void CL_UpdateUserinfo( sizebuf_t *msg, connprotocol_t proto );
void CL_ParseResource( sizebuf_t *msg );
void CL_ParseClientData( sizebuf_t *msg, connprotocol_t proto );
void CL_UpdateUserPings( sizebuf_t *msg );
void CL_ParseParticles( sizebuf_t *msg, connprotocol_t proto );
void CL_ParseBaseline( sizebuf_t *msg, connprotocol_t proto );
void CL_ParseSignon( sizebuf_t *msg, connprotocol_t proto );
void CL_ParseRestore( sizebuf_t *msg );
void CL_ParseStaticDecal( sizebuf_t *msg );
void CL_ParseAddAngle( sizebuf_t *msg );
void CL_RegisterUserMessage( sizebuf_t *msg, connprotocol_t proto );
void CL_ParseResourceList( sizebuf_t *msg, connprotocol_t proto );
void CL_ParseMovevars( sizebuf_t *msg );
void CL_ParseResourceRequest( sizebuf_t *msg );
void CL_ParseCustomization( sizebuf_t *msg );
void CL_ParseCrosshairAngle( sizebuf_t *msg );
void CL_ParseSoundFade( sizebuf_t *msg );
void CL_ParseFileTransferFailed( sizebuf_t *msg );
void CL_ParseHLTV( sizebuf_t *msg );
void CL_ParseDirector( sizebuf_t *msg );
void CL_ParseVoiceInit( sizebuf_t *msg );
void CL_ParseVoiceData( sizebuf_t *msg, connprotocol_t proto );
void CL_ParseResLocation( sizebuf_t *msg );
void CL_ParseCvarValue( sizebuf_t *msg, const qboolean ext, const connprotocol_t proto );
void CL_ParseServerMessage( sizebuf_t *msg );
qboolean CL_ParseCommonDLLMessage( sizebuf_t *msg, connprotocol_t proto, int svc_num, int startoffset );
qboolean CL_ParseCommonMessage( sizebuf_t *msg, connprotocol_t proto, int svc_num, int startoffset );
qboolean CL_ParseCommonHLMessage( sizebuf_t *msg, connprotocol_t proto, int svc_num, int startoffset );
void CL_ParseTempEntity( sizebuf_t *msg, connprotocol_t proto );
qboolean CL_DispatchUserMessage( const char *pszName, int iSize, void *pbuf );
qboolean CL_RequestMissingResources( void );
void CL_RegisterResources( sizebuf_t *msg, connprotocol_t proto );
void CL_ParseViewEntity( sizebuf_t *msg );
void CL_ParseServerTime( sizebuf_t *msg, connprotocol_t proto );
void CL_ParseUserMessage( sizebuf_t *msg, int svc_num, connprotocol_t proto );
void CL_ParseFinaleCutscene( sizebuf_t *msg, int level );
void CL_ParseTextMessage( sizebuf_t *msg );
void CL_ParseExec( sizebuf_t *msg );
void CL_BatchResourceRequest( qboolean initialize );
int CL_EstimateNeededResources( void );
@@ -1085,6 +1066,10 @@ void R_AddEfrags( cl_entity_t *ent );
// cl_tent.c
//
struct particle_s;
void CL_SetLightstyle( int style, const char* s, float f );
void CL_DecayLights( void );
dlight_t *CL_GetDynamicLight( int number );
dlight_t *CL_GetEntityLight( int number );
void CL_WeaponAnim( int iAnim, int body );
void CL_ClearEffects( void );
void CL_ClearEfrags( void );

View File

@@ -152,7 +152,7 @@ sfx_t *S_FindName( const char *pname, qboolean *pfInCache )
uint i, hash;
string name;
if( COM_StringEmptyOrNULL( pname ) || !dma.initialized )
if( COM_StringEmptyOrNULL( pname ) || !snd.initialized )
return NULL;
if( Q_strlen( pname ) >= sizeof( sfx->name ))
@@ -253,7 +253,7 @@ void S_BeginRegistration( void )
{
int i;
snd_ambient = false;
snd.have_ambient_sfx = false;
// check for automatic ambient sounds
for( i = 0; i < NUM_AMBIENTS; i++ )
@@ -261,8 +261,9 @@ void S_BeginRegistration( void )
if( !GI->ambientsound[i][0] )
continue; // empty slot
ambient_sfx[i] = S_RegisterSound( GI->ambientsound[i] );
if( ambient_sfx[i] ) snd_ambient = true; // allow auto-ambients
snd.ambient_sfx[i] = S_RegisterSound( GI->ambientsound[i] );
if( snd.ambient_sfx[i] )
snd.have_ambient_sfx = true; // allow auto-ambients
}
s_registering = true;
@@ -279,7 +280,7 @@ void S_EndRegistration( void )
sfx_t *sfx;
int i;
if( !s_registering || !dma.initialized )
if( !s_registering || !snd.initialized )
return;
// free any sounds not from this registration sequence
@@ -312,7 +313,7 @@ sound_t S_RegisterSound( const char *name )
{
sfx_t *sfx;
if( COM_StringEmptyOrNULL( name ) || !dma.initialized )
if( COM_StringEmptyOrNULL( name ) || !snd.initialized )
return -1;
if( S_TestSoundChar( name, '!' ))
@@ -336,7 +337,7 @@ sound_t S_RegisterSound( const char *name )
sfx_t *S_GetSfxByHandle( sound_t handle )
{
if( !dma.initialized )
if( !snd.initialized )
return NULL;
// create new sfx
@@ -375,7 +376,7 @@ void S_FreeSounds( void )
sfx_t *sfx;
int i;
if( !dma.initialized )
if( !snd.initialized )
return;
// stop all sounds

View File

@@ -31,19 +31,18 @@ struct
int in_seconds;
} soundfade;
dma_t dma;
poolhandle_t sndpool;
sound_t ambient_sfx[NUM_AMBIENTS];
qboolean snd_ambient = false;
qboolean snd_fade_sequence = false;
listener_t s_listener;
channel_t channels[MAX_CHANNELS];
rawchan_t *raw_channels[MAX_RAW_CHANNELS];
int total_channels;
int soundtime; // sample PAIRS
int paintedtime; // sample PAIRS
// this confuses the shit out of qt creator parser
// and good luck if you rely on shitty old msvc
snd_globals_t snd =
{
.channels = (channel_t[MAX_CHANNELS]){},
.max_channels = MAX_CHANNELS,
.raw_channels = (rawchan_t*[MAX_RAW_CHANNELS]){},
.max_raw_channels = MAX_RAW_CHANNELS,
};
static snd_interface_state_t s_sndState;
@@ -54,7 +53,6 @@ static CVAR_DEFINE_AUTO( s_show, "0", FCVAR_ARCHIVE|FCVAR_FILTERABLE, "show play
CVAR_DEFINE_AUTO( s_lerping, "0", FCVAR_ARCHIVE|FCVAR_FILTERABLE, "apply interpolation to sound output" );
static CVAR_DEFINE( s_ambient_level, "ambient_level", "0.3", FCVAR_ARCHIVE|FCVAR_FILTERABLE, "volume of environment noises (water and wind)" );
static CVAR_DEFINE( s_ambient_fade, "ambient_fade", "1000", FCVAR_ARCHIVE|FCVAR_FILTERABLE, "rate of volume fading when client is moving" );
static CVAR_DEFINE_AUTO( s_combine_sounds, "0", FCVAR_ARCHIVE|FCVAR_FILTERABLE, "combine channels with same sounds" );
CVAR_DEFINE_AUTO( snd_mute_losefocus, "1", FCVAR_ARCHIVE|FCVAR_FILTERABLE, "silence the audio when game window loses focus" );
CVAR_DEFINE_AUTO( s_test, "0", 0, "engine developer cvar for quick testing new features" );
CVAR_DEFINE_AUTO( s_samplecount, "0", FCVAR_ARCHIVE|FCVAR_FILTERABLE, "sample count (0 for default value)" );
@@ -160,7 +158,7 @@ S_IsClient
*/
static qboolean S_IsClient( int entnum )
{
return entnum == s_listener.entnum;
return entnum == snd.entnum;
}
/*
@@ -189,13 +187,16 @@ void S_FreeChannel( channel_t *ch )
{
S_NotifyChannelUpdate( ch - channels, NULL, -1 );
// free the currently loaded word's audio cache before nuking the channel
if( ch->words )
VOX_FreeWord( ch );
ch->sfx = NULL;
ch->name[0] = '\0';
ch->use_loop = false;
ch->is_sentence = false;
ch->flags = 0;
ch->forced_end = ch->sample = 0.0;
ch->data = NULL;
ch->finished = false;
Mem_Free2( &ch->words );
SND_CloseMouth( ch );
}
@@ -269,7 +270,7 @@ static qboolean SND_FStreamIsPlaying( sfx_t *sfx )
{
for( int i = NUM_AMBIENTS; i < MAX_DYNAMIC_CHANNELS; i++ )
{
if( channels[i].sfx == sfx )
if( snd.channels[i].sfx == sfx )
return true;
}
return false;
@@ -286,14 +287,14 @@ static int SND_GetChannelTimeLeft( const channel_t *ch )
{
int remaining;
if( ch->finished || !ch->sfx || !ch->sfx->cache )
if( FBitSet( ch->flags, FL_CHAN_FINISHED ) || !ch->sfx || !ch->sfx->cache )
return 0;
if( ch->is_sentence ) // sentences are special, count all remaining words
if( ch->words ) // sentences are special, count all remaining words
{
int i;
if( ch->sentence_finished )
if( FBitSet( ch->flags, FL_CHAN_SENTENCE_FINISHED ) )
return 0;
// current word
@@ -301,7 +302,7 @@ static int SND_GetChannelTimeLeft( const channel_t *ch )
// here we count all remaining words, stopping if no sfx or sound file is available
// see VOX_LoadWord
for( i = ch->word_index + 1; i < ARRAYSIZE( ch->words ); i++ )
for( i = ch->word_index + 1; i < CVOXWORDMAX; i++ )
{
wavdata_t *sc;
int end;
@@ -323,7 +324,7 @@ static int SND_GetChannelTimeLeft( const channel_t *ch )
else
{
int samples = ch->sfx->cache->samples;
int curpos = S_AdjustLoopedSamplePosition( ch->sfx->cache, ch->sample, ch->use_loop );
int curpos = S_AdjustLoopedSamplePosition( ch->sfx->cache, ch->sample, FBitSet( ch->flags, FL_CHAN_USE_LOOP ));
remaining = bound( 0, samples - curpos, samples );
}
@@ -361,7 +362,7 @@ channel_t *SND_PickDynamicChannel( int entnum, int channel, sfx_t *sfx, qboolean
for( ch_idx = NUM_AMBIENTS; ch_idx < MAX_DYNAMIC_CHANNELS; ch_idx++ )
{
channel_t *ch = &channels[ch_idx];
channel_t *ch = &snd.channels[ch_idx];
// Never override a streaming sound that is currently playing or
// voice over IP data that is playing or any sound on CHAN_VOICE( acting )
@@ -392,14 +393,14 @@ channel_t *SND_PickDynamicChannel( int entnum, int channel, sfx_t *sfx, qboolean
if( first_to_die == -1 )
return NULL;
if( channels[first_to_die].sfx )
if( snd.channels[first_to_die].sfx )
{
// don't restart looping sounds for the same entity
wavdata_t *sc = channels[first_to_die].sfx->cache;
wavdata_t *sc = snd.channels[first_to_die].sfx->cache;
if( sc && FBitSet( sc->flags, SOUND_LOOPED ))
{
channel_t *ch = &channels[first_to_die];
channel_t *ch = &snd.channels[first_to_die];
if( ch->entnum == entnum && ch->entchannel == channel && ch->sfx == sfx )
{
@@ -410,10 +411,10 @@ channel_t *SND_PickDynamicChannel( int entnum, int channel, sfx_t *sfx, qboolean
}
// be sure and release previous channel if sentence.
S_FreeChannel( &( channels[first_to_die] ));
S_FreeChannel( &( snd.channels[first_to_die] ));
}
return &channels[first_to_die];
return &snd.channels[first_to_die];
}
/*
@@ -432,32 +433,32 @@ channel_t *SND_PickStaticChannel( const vec3_t pos, sfx_t *sfx )
int i;
// check for replacement sound, or find the best one to replace
for( i = MAX_DYNAMIC_CHANNELS; i < total_channels; i++ )
for( i = MAX_DYNAMIC_CHANNELS; i < snd.total_channels; i++ )
{
if( channels[i].sfx == NULL )
if( snd.channels[i].sfx == NULL )
break;
if( VectorCompare( pos, channels[i].origin ) && channels[i].sfx == sfx )
if( VectorCompare( pos, snd.channels[i].origin ) && snd.channels[i].sfx == sfx )
break;
}
if( i < total_channels )
if( i < snd.total_channels )
{
// reuse an empty static sound channel
ch = &channels[i];
ch = &snd.channels[i];
}
else
{
// no empty slots, alloc a new static sound channel
if( total_channels == MAX_CHANNELS )
if( snd.total_channels == snd.max_channels )
{
Con_DPrintf( S_ERROR "%s: no free channels\n", __func__ );
return NULL;
}
// get a channel for the static sound
ch = &channels[total_channels];
total_channels++;
ch = &snd.channels[snd.total_channels];
snd.total_channels++;
}
return ch;
}
@@ -473,7 +474,7 @@ static qboolean S_MaybeAlterChannel( channel_t *ch, int entnum, int entchannel,
// if no sfx passed, check if it's a sentence
if( !sfx )
{
if( !ch->is_sentence )
if( !ch->words )
return false;
}
else
@@ -514,34 +515,21 @@ returns FALSE if sound was not found (sound is not playing)
*/
static int S_AlterChannel( int entnum, int channel, const sfx_t *sfx, int vol, int pitch, int flags )
{
channel_t *ch;
int i;
// This is a sentence name.
// For sentences: assume that the entity is only playing one sentence
// at a time, so we can just shut off
// any channel that has ch->is_sentence >= 0 and matches the entnum.
qboolean is_sentence = S_TestSoundChar( sfx->name, '!' );
if( S_TestSoundChar( sfx->name, '!' ))
for( int i = NUM_AMBIENTS; i < snd.total_channels; i++ )
{
// This is a sentence name.
// For sentences: assume that the entity is only playing one sentence
// at a time, so we can just shut off
// any channel that has ch->is_sentence >= 0 and matches the entnum.
channel_t *ch = &snd.channels[i];
for( i = NUM_AMBIENTS, ch = channels + NUM_AMBIENTS; i < total_channels; i++, ch++ )
{
if( S_MaybeAlterChannel( ch, entnum, channel, flags, NULL, pitch, vol ))
return true;
}
// channel not found
return false;
}
// regular sound or streaming sound
for( i = NUM_AMBIENTS, ch = channels + NUM_AMBIENTS; i < total_channels; i++, ch++ )
{
if( S_MaybeAlterChannel( ch, entnum, channel, flags, sfx, pitch, vol ))
if( S_MaybeAlterChannel( ch, entnum, channel, flags, is_sentence ? NULL : sfx, pitch, vol ))
return true;
}
// channel not found
return false;
}
@@ -589,7 +577,7 @@ static void SND_Spatialize( channel_t *ch )
return;
}
if( !ch->staticsound )
if( !FBitSet( ch->flags, FL_CHAN_STATIC_SOUND ))
{
if( !CL_GetEntitySpatialization( ch ))
{
@@ -602,11 +590,11 @@ static void SND_Spatialize( channel_t *ch )
// source_vec is vector from listener to sound source
// player sounds come from 1' in front of player
vec3_t source_vec;
VectorSubtract( ch->origin, s_listener.origin, source_vec );
VectorSubtract( ch->origin, snd.origin, source_vec );
// normalize source_vec and get distance from listener to source
float dist = VectorNormalizeLength( source_vec );
float dot = DotProduct( s_listener.right, source_vec );
float dot = DotProduct( snd.right, source_vec );
if( !FBitSet( host.bugcomp, BUGCOMP_SPATIALIZE_SOUND_WITH_ATTN_NONE ))
{
@@ -645,7 +633,7 @@ void S_StartSound( const vec3_t pos, int ent, int chan, sound_t handle, float fv
int vol, ch_idx;
qboolean bIgnore = false;
if( !dma.initialized ) return;
if( !snd.initialized ) return;
sfx = S_GetSfxByHandle( handle );
if( !sfx ) return;
@@ -668,8 +656,10 @@ void S_StartSound( const vec3_t pos, int ent, int chan, sound_t handle, float fv
SetBits( flags, SND_STOP_LOOPING );
// pick a channel to play on
if( chan == CHAN_STATIC ) target_chan = SND_PickStaticChannel( pos, sfx );
else target_chan = SND_PickDynamicChannel( ent, chan, sfx, &bIgnore );
if( chan == CHAN_STATIC )
target_chan = SND_PickStaticChannel( pos, sfx );
else
target_chan = SND_PickDynamicChannel( ent, chan, sfx, &bIgnore );
if( !target_chan )
{
@@ -682,15 +672,21 @@ void S_StartSound( const vec3_t pos, int ent, int chan, sound_t handle, float fv
memset( target_chan, 0, sizeof( *target_chan ));
VectorCopy( pos, target_chan->origin );
target_chan->staticsound = ( ent == 0 ) ? true : false;
target_chan->use_loop = (flags & SND_STOP_LOOPING) ? false : true;
target_chan->localsound = (flags & SND_LOCALSOUND) ? true : false;
if( ent == 0 )
SetBits( target_chan->flags, FL_CHAN_STATIC_SOUND );
if( !FBitSet( flags, SND_STOP_LOOPING ))
SetBits( target_chan->flags, FL_CHAN_USE_LOOP );
if( FBitSet( flags, SND_LOCALSOUND ))
SetBits( target_chan->flags, FL_CHAN_LOCAL_SOUND );
target_chan->dist_mult = (attn / SND_CLIP_DISTANCE);
target_chan->master_vol = vol;
target_chan->entnum = ent;
target_chan->entchannel = chan;
target_chan->basePitch = pitch;
target_chan->is_sentence = false;
target_chan->sfx = sfx;
pSource = NULL;
@@ -760,7 +756,7 @@ void S_RestoreSound( const vec3_t pos, int ent, int chan, sound_t handle, float
qboolean bIgnore = false;
int vol;
if( !dma.initialized ) return;
if( !snd.initialized ) return;
sfx = S_GetSfxByHandle( handle );
if( !sfx ) return;
@@ -768,8 +764,10 @@ void S_RestoreSound( const vec3_t pos, int ent, int chan, sound_t handle, float
if( pitch <= 1 ) pitch = PITCH_NORM; // Invasion issues
// pick a channel to play on
if( chan == CHAN_STATIC ) target_chan = SND_PickStaticChannel( pos, sfx );
else target_chan = SND_PickDynamicChannel( ent, chan, sfx, &bIgnore );
if( chan == CHAN_STATIC )
target_chan = SND_PickStaticChannel( pos, sfx );
else
target_chan = SND_PickDynamicChannel( ent, chan, sfx, &bIgnore );
if( !target_chan )
{
@@ -782,15 +780,21 @@ void S_RestoreSound( const vec3_t pos, int ent, int chan, sound_t handle, float
memset( target_chan, 0, sizeof( *target_chan ));
VectorCopy( pos, target_chan->origin );
target_chan->staticsound = ( ent == 0 ) ? true : false;
target_chan->use_loop = (flags & SND_STOP_LOOPING) ? false : true;
target_chan->localsound = (flags & SND_LOCALSOUND) ? true : false;
if( ent == 0 )
SetBits( target_chan->flags, FL_CHAN_STATIC_SOUND );
if( !FBitSet( flags, SND_STOP_LOOPING ))
SetBits( target_chan->flags, FL_CHAN_USE_LOOP );
if( FBitSet( flags, SND_LOCALSOUND ))
SetBits( target_chan->flags, FL_CHAN_LOCAL_SOUND );
target_chan->dist_mult = (attn / SND_CLIP_DISTANCE);
target_chan->master_vol = vol;
target_chan->entnum = ent;
target_chan->entchannel = chan;
target_chan->basePitch = pitch;
target_chan->is_sentence = false;
target_chan->sfx = sfx;
pSource = NULL;
@@ -812,7 +816,7 @@ void S_RestoreSound( const vec3_t pos, int ent, int chan, sound_t handle, float
target_chan->word_index = wordIndex; // restore current word
VOX_LoadWord( target_chan );
if( !target_chan->sentence_finished )
if( !FBitSet( target_chan->flags, FL_CHAN_SENTENCE_FINISHED ))
{
target_chan->sfx = target_chan->words[target_chan->word_index].sfx;
sfx = target_chan->sfx;
@@ -874,7 +878,7 @@ void S_AmbientSound( const vec3_t pos, int ent, sound_t handle, float fvol, floa
sfx_t *sfx = NULL;
int vol, fvox = 0;
if( !dma.initialized ) return;
if( !snd.initialized ) return;
sfx = S_GetSfxByHandle( handle );
if( !sfx ) return;
@@ -916,7 +920,6 @@ void S_AmbientSound( const vec3_t pos, int ent, sound_t handle, float fvol, floa
// load regular or stream sound
pSource = S_LoadSound( sfx );
ch->sfx = sfx;
ch->is_sentence = false;
ch->name[0] = '\0';
}
@@ -929,9 +932,15 @@ void S_AmbientSound( const vec3_t pos, int ent, sound_t handle, float fvol, floa
pitch *= (sys_timescale.value + 1) / 2;
// never update positions if source entity is 0
ch->staticsound = ( ent == 0 ) ? true : false;
ch->use_loop = (flags & SND_STOP_LOOPING) ? false : true;
ch->localsound = (flags & SND_LOCALSOUND) ? true : false;
if( ent == 0 ) SetBits( ch->flags, FL_CHAN_STATIC_SOUND );
else ClearBits( ch->flags, FL_CHAN_STATIC_SOUND );
if( !FBitSet( flags, SND_STOP_LOOPING )) SetBits( ch->flags, FL_CHAN_USE_LOOP );
else ClearBits( ch->flags, FL_CHAN_USE_LOOP );
if( FBitSet( flags, SND_LOCALSOUND )) SetBits( ch->flags, FL_CHAN_LOCAL_SOUND );
else ClearBits( ch->flags, FL_CHAN_LOCAL_SOUND );
ch->master_vol = vol;
ch->dist_mult = (attn / SND_CLIP_DISTANCE);
ch->entchannel = CHAN_STATIC;
@@ -954,9 +963,9 @@ void S_StartLocalSound( const char *name, float volume, qboolean reliable )
if( reliable ) channel = CHAN_STATIC;
if( !dma.initialized ) return;
if( !snd.initialized ) return;
sfxHandle = S_RegisterSound( name );
S_StartSound( NULL, s_listener.entnum, channel, sfxHandle, volume, ATTN_NONE, PITCH_NORM, flags );
S_StartSound( NULL, snd.entnum, channel, sfxHandle, volume, ATTN_NONE, PITCH_NORM, flags );
}
/*
@@ -969,32 +978,35 @@ grab all static sounds playing at current channel
int S_GetCurrentStaticSounds( soundlist_t *pout, int size )
{
int sounds_left = size;
int i;
if( !dma.initialized )
if( !snd.initialized )
return 0;
for( i = MAX_DYNAMIC_CHANNELS; i < total_channels && sounds_left; i++ )
for( int i = MAX_DYNAMIC_CHANNELS; i < snd.total_channels && sounds_left; i++ )
{
if( channels[i].entchannel == CHAN_STATIC && channels[i].sfx && channels[i].sfx->name[0] )
{
if( channels[i].is_sentence && channels[i].name[0] )
Q_strncpy( pout->name, channels[i].name, sizeof( pout->name ));
else Q_strncpy( pout->name, channels[i].sfx->name, sizeof( pout->name ));
pout->entnum = channels[i].entnum;
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 && FBitSet( channels[i].sfx->cache->flags, SOUND_LOOPED ));
pout->pitch = channels[i].basePitch;
pout->channel = channels[i].entchannel;
pout->wordIndex = channels[i].word_index;
pout->samplePos = channels[i].sample;
pout->forcedEnd = channels[i].forced_end;
const channel_t *ch = &snd.channels[i];
sounds_left--;
pout++;
}
if( ch->entchannel != CHAN_STATIC || !ch->sfx || !ch->sfx->name[0] )
continue;
if( ch->words && ch->name[0] )
Q_strncpy( pout->name, ch->name, sizeof( pout->name ));
else
Q_strncpy( pout->name, ch->sfx->name, sizeof( pout->name ));
pout->entnum = ch->entnum;
VectorCopy( ch->origin, pout->origin );
pout->volume = (float)ch->master_vol / 255.0f;
pout->attenuation = ch->dist_mult * SND_CLIP_DISTANCE;
pout->looping = ( FBitSet( ch->flags, FL_CHAN_USE_LOOP ) && FBitSet( ch->sfx->cache->flags, SOUND_LOOPED ));
pout->pitch = ch->basePitch;
pout->channel = ch->entchannel;
pout->wordIndex = ch->word_index;
pout->samplePos = ch->sample;
pout->forcedEnd = ch->forced_end;
sounds_left--;
pout++;
}
return ( size - sounds_left );
@@ -1012,31 +1024,35 @@ int S_GetCurrentDynamicSounds( soundlist_t *pout, int size )
int sounds_left = size;
int i, looped;
if( !dma.initialized )
if( !snd.initialized )
return 0;
for( i = 0; i < MAX_CHANNELS && sounds_left; i++ )
for( i = 0; i < snd.max_channels && sounds_left; i++ )
{
if( !channels[i].sfx || !channels[i].sfx->name[0] || !Q_stricmp( channels[i].sfx->name, "*default" ))
const channel_t *ch = &snd.channels[i];
if( !ch->sfx || !ch->sfx->name[0] || !Q_stricmp( ch->sfx->name, "*default" ))
continue; // don't serialize default sounds
looped = ( channels[i].use_loop && FBitSet( channels[i].sfx->cache->flags, SOUND_LOOPED ));
looped = ( FBitSet( ch->flags, FL_CHAN_USE_LOOP ) && FBitSet( ch->sfx->cache->flags, SOUND_LOOPED ));
if( channels[i].entchannel == CHAN_STATIC && looped && !Host_IsQuakeCompatible())
if( ch->entchannel == CHAN_STATIC && looped && !Host_IsQuakeCompatible())
continue; // never serialize static looped sounds. It will be restoring in game code
if( channels[i].is_sentence && channels[i].name[0] )
Q_strncpy( pout->name, channels[i].name, sizeof( pout->name ));
else Q_strncpy( pout->name, channels[i].sfx->name, sizeof( pout->name ));
pout->entnum = (channels[i].entnum < 0) ? 0 : channels[i].entnum;
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->pitch = channels[i].basePitch;
pout->channel = channels[i].entchannel;
pout->wordIndex = channels[i].word_index;
pout->samplePos = channels[i].sample;
pout->forcedEnd = channels[i].forced_end;
if( ch->words && ch->name[0] )
Q_strncpy( pout->name, ch->name, sizeof( pout->name ));
else
Q_strncpy( pout->name, ch->sfx->name, sizeof( pout->name ));
pout->entnum = (ch->entnum < 0) ? 0 : ch->entnum;
VectorCopy( ch->origin, pout->origin );
pout->volume = (float)ch->master_vol / 255.0f;
pout->attenuation = ch->dist_mult * SND_CLIP_DISTANCE;
pout->pitch = ch->basePitch;
pout->channel = ch->entchannel;
pout->wordIndex = ch->word_index;
pout->samplePos = ch->sample;
pout->forcedEnd = ch->forced_end;
pout->looping = looped;
sounds_left--;
@@ -1053,18 +1069,14 @@ S_InitAmbientChannels
*/
static void S_InitAmbientChannels( void )
{
int ambient_channel;
channel_t *chan;
for( ambient_channel = 0; ambient_channel < NUM_AMBIENTS; ambient_channel++ )
for( int i = 0; i < NUM_AMBIENTS; i++ )
{
chan = &channels[ambient_channel];
channel_t *ch = &snd.channels[i];
chan->staticsound = true;
chan->use_loop = true;
chan->entchannel = CHAN_STATIC;
chan->dist_mult = (ATTN_NONE / SND_CLIP_DISTANCE);
chan->basePitch = PITCH_NORM;
SetBits( ch->flags, FL_CHAN_USE_LOOP | FL_CHAN_STATIC_SOUND );
ch->entchannel = CHAN_STATIC;
ch->dist_mult = (ATTN_NONE / SND_CLIP_DISTANCE);
ch->basePitch = PITCH_NORM;
}
}
@@ -1077,27 +1089,27 @@ static void S_UpdateAmbientSounds( void )
{
int ambient_channel;
if( !snd_ambient )
if( !snd.have_ambient_sfx )
return;
// calc ambient sound levels
if( !cl.worldmodel )
return;
mleaf_t *leaf = Mod_PointInLeaf( s_listener.origin, cl.worldmodel->nodes, cl.worldmodel );
mleaf_t *leaf = Mod_PointInLeaf( snd.origin, cl.worldmodel->nodes, cl.worldmodel );
if( !leaf || !s_ambient_level.value )
{
for( ambient_channel = 0; ambient_channel < NUM_AMBIENTS; ambient_channel++ )
channels[ambient_channel].sfx = NULL;
for( int i = 0; i < NUM_AMBIENTS; i++ )
snd.channels[i].sfx = NULL;
return;
}
for( ambient_channel = 0; ambient_channel < NUM_AMBIENTS; ambient_channel++ )
for( int i = 0; i < NUM_AMBIENTS; i++ )
{
channel_t *chan = &channels[ambient_channel];
chan->sfx = S_GetSfxByHandle( ambient_sfx[ambient_channel] );
channel_t *chan = &snd.channels[i];
chan->sfx = S_GetSfxByHandle( snd.ambient_sfx[i] );
// ambient is unused
if( !chan->sfx )
@@ -1156,9 +1168,9 @@ rawchan_t *S_FindRawChannel( int entnum, qboolean create )
int best = -1;
int free = -1;
for( int i = 0; i < MAX_RAW_CHANNELS; i++ )
for( int i = 0; i < snd.max_raw_channels; i++ )
{
ch = raw_channels[i];
ch = snd.raw_channels[i];
if( free < 0 && !ch )
{
@@ -1172,7 +1184,7 @@ rawchan_t *S_FindRawChannel( int entnum, qboolean create )
if( ch->entnum == entnum )
return ch;
time = ch->s_rawend - paintedtime;
time = ch->s_rawend - snd.paintedtime;
if( time < best_time )
{
best = i;
@@ -1190,14 +1202,14 @@ rawchan_t *S_FindRawChannel( int entnum, qboolean create )
if( best < 0 )
return NULL; // no free slots
if( !raw_channels[best] )
if( !snd.raw_channels[best] )
{
size_t raw_samples = MAX_RAW_SAMPLES;
raw_channels[best] = Mem_Calloc( sndpool, sizeof( *ch ) + sizeof( portable_samplepair_t ) * raw_samples );
raw_channels[best]->max_samples = raw_samples;
snd.raw_channels[best] = Mem_Calloc( sndpool, sizeof( *ch ) + sizeof( portable_samplepair_t ) * raw_samples );
snd.raw_channels[best]->max_samples = raw_samples;
}
ch = raw_channels[best];
ch = snd.raw_channels[best];
ch->entnum = entnum;
ch->s_rawend = 0;
@@ -1216,8 +1228,8 @@ uint S_RawSamplesStereo( portable_samplepair_t *rawsamples, uint rawend, uint ma
uint fracstep, samplefrac;
uint src, dst;
if( rawend < paintedtime )
rawend = paintedtime;
if( rawend < snd.paintedtime )
rawend = snd.paintedtime;
fracstep = ((double) rate / (double)SOUND_DMA_SPEED) * (double)(1 << S_RAW_SAMPLES_PRECISION_BITS);
samplefrac = 0;
@@ -1304,14 +1316,14 @@ static void S_FreeIdleRawChannels( void )
{
int i;
for( i = 0; i < MAX_RAW_CHANNELS; i++ )
for( i = 0; i < snd.max_raw_channels; i++ )
{
rawchan_t *ch = raw_channels[i];
rawchan_t *ch = snd.raw_channels[i];
if( !ch )
continue;
if( ch->s_rawend >= paintedtime )
if( ch->s_rawend >= snd.paintedtime )
continue;
if( ch->entnum > 0 )
@@ -1322,9 +1334,9 @@ static void S_FreeIdleRawChannels( void )
Voice_StopChannel( ch->entnum );
}
if(( paintedtime - ch->s_rawend ) / SOUND_DMA_SPEED >= S_RAW_SOUND_IDLE_SEC )
if(( snd.paintedtime - ch->s_rawend ) / SOUND_DMA_SPEED >= S_RAW_SOUND_IDLE_SEC )
{
raw_channels[i] = NULL;
snd.raw_channels[i] = NULL;
Mem_Free( ch );
}
}
@@ -1339,9 +1351,9 @@ static void S_ClearRawChannels( void )
{
int i;
for( i = 0; i < MAX_RAW_CHANNELS; i++ )
for( i = 0; i < snd.max_raw_channels; i++ )
{
rawchan_t *ch = raw_channels[i];
rawchan_t *ch = snd.raw_channels[i];
if( !ch ) continue;
ch->s_rawend = 0;
@@ -1356,14 +1368,14 @@ S_SpatializeRawChannels
*/
static void S_SpatializeRawChannels( void )
{
for( int i = 0; i < MAX_RAW_CHANNELS; i++ )
for( int i = 0; i < snd.max_raw_channels; i++ )
{
rawchan_t *ch = raw_channels[i];
rawchan_t *ch = snd.raw_channels[i];
if( !ch )
continue;
if( ch->s_rawend < paintedtime )
if( ch->s_rawend < snd.paintedtime )
{
ch->leftvol = ch->rightvol = 0;
continue;
@@ -1381,11 +1393,11 @@ static void S_SpatializeRawChannels( void )
{
vec3_t source_vec;
VectorSubtract( ch->origin, s_listener.origin, source_vec );
VectorSubtract( ch->origin, snd.origin, source_vec );
// normalize source_vec and get distance from listener to source
float dist = VectorNormalizeLength( source_vec );
float dot = DotProduct( s_listener.right, source_vec );
float dot = DotProduct( snd.right, source_vec );
// don't pan sounds with no attenuation
if( ch->dist_mult <= 0.0f ) dot = 0.0f;
@@ -1408,16 +1420,9 @@ 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 ));
for( int i = 0; i < snd.max_raw_channels; i++ )
Mem_Free2( &snd.raw_channels[i] );
}
//=============================================================================
@@ -1432,8 +1437,10 @@ static void S_ClearBuffer( void )
S_ClearRawChannels();
SNDDMA_BeginPainting ();
if( dma.buffer )
memset( dma.buffer, 0, dma.samples * 2 );
if( snd.buffer )
memset( snd.buffer, 0, snd.samples * 2 );
SNDDMA_Submit ();
S_ClearBuffers( PAINTBUFFER_SIZE );
@@ -1450,7 +1457,7 @@ void GAME_EXPORT S_StopSound( int entnum, int channel, const char *soundname )
{
sfx_t *sfx;
if( !dma.initialized ) return;
if( !snd.initialized ) return;
sfx = S_FindName( soundname, NULL );
S_AlterChannel( entnum, channel, sfx, 0, 0, SND_STOP );
}
@@ -1464,19 +1471,21 @@ void S_StopAllSounds( qboolean ambient )
{
int i;
if( !dma.initialized ) return;
total_channels = MAX_DYNAMIC_CHANNELS; // no statics
if( !snd.initialized ) return;
snd.total_channels = MAX_DYNAMIC_CHANNELS; // no statics
for( i = 0; i < MAX_CHANNELS; i++ )
for( i = 0; i < snd.max_channels; i++ )
{
if( !channels[i].sfx ) continue;
S_FreeChannel( &channels[i] );
if( !snd.channels[i].sfx )
continue;
S_FreeChannel( &snd.channels[i] );
}
SX_ClearState();
// clear all the channels
memset( channels, 0, sizeof( channels ));
memset( snd.channels, 0, sizeof( snd.channels[0] ) * snd.max_channels );
// restart the ambient sounds
if( ambient ) S_InitAmbientChannels ();
@@ -1501,22 +1510,22 @@ static int S_GetSoundtime( void )
static int buffers, oldsamplepos;
int samplepos, fullsamples;
fullsamples = dma.samples / 2;
fullsamples = snd.samples / 2;
// it is possible to miscount buffers
// if it has wrapped twice between
// calls to S_Update. Oh well.
samplepos = dma.samplepos;
samplepos = snd.samplepos;
if( samplepos < oldsamplepos )
{
buffers++; // buffer wrapped
if( paintedtime > 0x40000000 )
if( snd.paintedtime > 0x40000000 )
{
// time to chop things off to avoid 32 bit limits
buffers = 0;
paintedtime = fullsamples;
snd.paintedtime = fullsamples;
S_StopAllSounds( true );
}
}
@@ -1534,25 +1543,25 @@ static void S_UpdateChannels( void )
SNDDMA_BeginPainting();
if( !dma.buffer ) return;
if( !snd.buffer ) return;
// updates DMA time
soundtime = S_GetSoundtime();
snd.soundtime = S_GetSoundtime();
// soundtime - total samples that have been played out to hardware at dmaspeed
// paintedtime - total samples that have been mixed at speed
// endtime - target for samples in mixahead buffer at speed
endtime = soundtime + s_mixahead.value * SOUND_DMA_SPEED;
samps = dma.samples >> 1;
endtime = snd.soundtime + s_mixahead.value * SOUND_DMA_SPEED;
samps = snd.samples >> 1;
if((int)(endtime - soundtime) > samps )
endtime = soundtime + samps;
if((int)(endtime - snd.soundtime) > samps )
endtime = snd.soundtime + samps;
if(( endtime - paintedtime ) & 0x3 )
if(( endtime - snd.paintedtime ) & 0x3 )
{
// the difference between endtime and painted time should align on
// boundaries of 4 samples. this is important when upsampling from 11khz -> 44khz.
endtime -= ( endtime - paintedtime ) & 0x3;
endtime -= ( endtime - snd.paintedtime ) & 0x3;
}
s_sndState.total_channels = total_channels;
@@ -1573,7 +1582,7 @@ Don't let sound skip if going slow
*/
void S_ExtraUpdate( void )
{
if( !dma.initialized ) return;
if( !snd.initialized ) return;
S_UpdateChannels ();
}
@@ -1589,9 +1598,9 @@ void S_UpdateFrame( struct ref_viewpass_s *rvp )
if( !FBitSet( rvp->flags, RF_DRAW_WORLD ) || FBitSet( rvp->flags, RF_ONLY_CLIENTDRAW ))
return;
VectorCopy( rvp->vieworigin, s_listener.origin );
AngleVectors( rvp->viewangles, s_listener.forward, s_listener.right, s_listener.up );
s_listener.entnum = rvp->viewentity; // can be camera entity too
VectorCopy( rvp->vieworigin, snd.origin );
AngleVectors( rvp->viewangles, snd.forward, snd.right, snd.up );
snd.entnum = rvp->viewentity; // can be camera entity too
}
/*
@@ -1603,11 +1612,7 @@ Called once each time through the main loop
*/
void SND_UpdateSound( void )
{
int i, j, total;
channel_t *ch, *combine;
con_nprint_t info;
if( !dma.initialized ) return;
if( !snd.initialized ) return;
if( clgame.soundFuncs.pfnS_UpdateSound )
clgame.soundFuncs.pfnS_UpdateSound();
@@ -1624,55 +1629,15 @@ void SND_UpdateSound( void )
// update general area ambient sound sources
S_UpdateAmbientSounds();
combine = NULL;
// update spatialization for static and dynamic sounds
for( i = NUM_AMBIENTS, ch = channels + NUM_AMBIENTS; i < total_channels; i++, ch++ )
for( int i = NUM_AMBIENTS; i < snd.total_channels; i++ )
{
if( !ch->sfx ) continue;
SND_Spatialize( ch ); // respatialize channel
channel_t *ch = &snd.channels[i];
if( !ch->leftvol && !ch->rightvol )
if( !ch->sfx )
continue;
// try to combine static sounds with a previous channel of the same
// sound effect so we don't mix five torches every frame
// g-cont: perfomance option, probably kill stereo effect in most cases
if( i >= MAX_DYNAMIC_CHANNELS && s_combine_sounds.value )
{
// see if it can just use the last one
if( combine && combine->sfx == ch->sfx )
{
combine->leftvol += ch->leftvol;
combine->rightvol += ch->rightvol;
ch->leftvol = ch->rightvol = 0;
continue;
}
// search for one
combine = channels + MAX_DYNAMIC_CHANNELS;
for( j = MAX_DYNAMIC_CHANNELS; j < i; j++, combine++ )
{
if( combine->sfx == ch->sfx )
break;
}
if( j == total_channels )
{
combine = NULL;
}
else
{
if( combine != ch )
{
combine->leftvol += ch->leftvol;
combine->rightvol += ch->rightvol;
ch->leftvol = ch->rightvol = 0;
}
continue;
}
}
SND_Spatialize( ch ); // respatialize channel
}
S_SpatializeRawChannels();
@@ -1680,26 +1645,33 @@ void SND_UpdateSound( void )
// debugging output
if( s_show.value != 0.0f )
{
info.color[0] = 1.0f;
info.color[1] = 0.6f;
info.color[2] = 0.0f;
info.time_to_live = 0.5f;
for( i = 0, total = 1, ch = channels; i < MAX_CHANNELS; i++, ch++ )
con_nprint_t info =
{
if( ch->sfx && ( ch->leftvol || ch->rightvol ))
{
info.index = total;
Con_NXPrintf( &info, "chan %i, pos (%.f %.f %.f) ent %i, lv%3i rv%3i %s\n",
.color[0] = 1.0f,
.color[1] = 0.6f,
.color[2] = 0.0f,
.index = 1,
.time_to_live = 0.5f,
};
for( int i = 0; i < MAX_CHANNELS; i++ )
{
channel_t *ch = &snd.channels[i];
if( !ch->sfx || ( !ch->leftvol && !ch->rightvol ))
continue;
Con_NXPrintf( &info, "chan %i, pos (%.f %.f %.f) ent %i, lv%3i rv%3i %s\n",
i, ch->origin[0], ch->origin[1], ch->origin[2], ch->entnum, ch->leftvol, ch->rightvol, ch->sfx->name );
total++;
}
info.index++;
}
int total = info.index - 1;
VectorSet( info.color, 1.0f, 1.0f, 1.0f );
info.index = 0;
Con_NXPrintf( &info, "room_type: %i (%s) ----(%i)---- painted: %i\n", idsp_room, Cvar_VariableString( "dsp_coeff_table" ), total - 1, paintedtime );
Con_NXPrintf( &info, "room_type: %i (%s) ----(%i)---- painted: %i\n", idsp_room, Cvar_VariableString( "dsp_coeff_table" ), total, snd.paintedtime );
}
S_StreamBackgroundTrack ();
@@ -1929,12 +1901,12 @@ S_SoundInfo_f
*/
void S_SoundInfo_f( void )
{
Con_Printf( "Audio backend: %s\n", dma.backendName );
Con_Printf( "Audio backend: %s\n", snd.backend_name );
Con_Printf( "%5d channel(s)\n", 2 );
Con_Printf( "%5d samples\n", dma.samples );
Con_Printf( "%5d samples\n", snd.samples );
Con_Printf( "%5d bits/sample\n", 16 );
Con_Printf( "%5d bytes/sec\n", SOUND_DMA_SPEED );
Con_Printf( "%5d total_channels\n", total_channels );
Con_Printf( "%5d total_channels\n", snd.total_channels );
S_PrintBackgroundTrackState ();
}
@@ -2029,7 +2001,6 @@ qboolean S_Init( void )
Cvar_RegisterVariable( &s_lerping );
Cvar_RegisterVariable( &s_ambient_level );
Cvar_RegisterVariable( &s_ambient_fade );
Cvar_RegisterVariable( &s_combine_sounds );
Cvar_RegisterVariable( &snd_mute_losefocus );
Cvar_RegisterVariable( &s_test );
Cvar_RegisterVariable( &s_samplecount );
@@ -2057,7 +2028,7 @@ qboolean S_Init( void )
Cmd_AddCommand( "speak", S_Say_f, "playing a specified sententce" );
sndpool = Mem_AllocPool( "Sound Zone" );
dma.backendName = "None";
snd.backend_name = "None";
if( !SNDDMA_Init( ))
{
Con_Printf( "Audio: sound system can't be initialized\n" );
@@ -2065,11 +2036,11 @@ qboolean S_Init( void )
return false;
}
soundtime = 0;
paintedtime = 0;
snd.soundtime = 0;
snd.paintedtime = 0;
// clear ambient sounds
memset( ambient_sfx, 0, sizeof( ambient_sfx ));
memset( snd.ambient_sfx, 0, sizeof( snd.ambient_sfx ));
SX_Init ();
S_StopAllSounds ( true );
@@ -2089,7 +2060,7 @@ qboolean S_Init( void )
// =======================================================================
void S_Shutdown( void )
{
if( !dma.initialized ) return;
if( !snd.initialized ) return;
Cmd_RemoveCommand( "play" );
Cmd_RemoveCommand( "playvol" );

View File

@@ -120,7 +120,7 @@ static void S_MixAudio( portable_samplepair_t *pbuf, const int *pvol, const void
static int S_AdjustNumSamples( channel_t *chan, int num_samples, double rate, double timecompress_rate )
{
if( chan->finished )
if( FBitSet( chan->flags, FL_CHAN_FINISHED ))
return 0;
// if channel is set to end at specific sample,
@@ -132,7 +132,7 @@ static int S_AdjustNumSamples( channel_t *chan, int num_samples, double rate, do
if( end_sample >= chan->forced_end )
{
chan->finished = true;
SetBits( chan->flags, FL_CHAN_FINISHED );
return floor(( chan->forced_end - chan->sample ) / ( rate * timecompress_rate ));
}
}
@@ -153,7 +153,7 @@ static int S_MixChannelToBuffer( portable_samplepair_t *pbuf, channel_t *chan, i
// timecompress at 100% is skipping the entire sfx, so mark as finished and exit
if( timecompress >= 100 )
{
chan->finished = true;
SetBits( chan->flags, FL_CHAN_FINISHED );
return 0;
}
@@ -173,7 +173,7 @@ static int S_MixChannelToBuffer( portable_samplepair_t *pbuf, channel_t *chan, i
// get sample pointer and also amount of samples available
const void *audio = NULL;
int available = S_RetrieveAudioSamples( chan->sfx->cache, &audio, chan->sample, request_num_samples, chan->use_loop );
int available = S_RetrieveAudioSamples( chan->sfx->cache, &audio, chan->sample, request_num_samples, FBitSet( chan->flags, FL_CHAN_USE_LOOP ));
// no samples available, exit
if( !available )
@@ -196,7 +196,7 @@ static int S_MixChannelToBuffer( portable_samplepair_t *pbuf, channel_t *chan, i
// samples couldn't be retrieved, mark as finished
if( num_samples > 0 )
chan->finished = true;
SetBits( chan->flags, FL_CHAN_FINISHED );
// total amount of samples mixed
return offset - initial_offset;
@@ -206,10 +206,10 @@ static int VOX_MixChannelToBuffer( portable_samplepair_t *pbuf, channel_t *chan,
{
int offset = 0;
if( chan->sentence_finished )
if( FBitSet( chan->flags, FL_CHAN_SENTENCE_FINISHED ))
return 0;
while( num_samples > 0 && !chan->sentence_finished )
while( num_samples > 0 && !FBitSet( chan->flags, FL_CHAN_SENTENCE_FINISHED ))
{
int outputCount = S_MixChannelToBuffer( pbuf, chan, num_samples, out_rate, pitch, offset, chan->words[chan->word_index].timecompress );
@@ -217,13 +217,13 @@ static int VOX_MixChannelToBuffer( portable_samplepair_t *pbuf, channel_t *chan,
num_samples -= outputCount;
// if we finished load a next word
if( chan->finished )
if( FBitSet( chan->flags, FL_CHAN_FINISHED ))
{
VOX_FreeWord( chan );
chan->word_index++;
VOX_LoadWord( chan );
if( !chan->sentence_finished )
if( !FBitSet( chan->flags, FL_CHAN_SENTENCE_FINISHED ))
chan->sfx = chan->words[chan->word_index].sfx;
}
}
@@ -235,7 +235,7 @@ static int S_MixNormalChannels( portable_samplepair_t *dst, int end, int rate )
{
const qboolean local = Host_IsLocalGame();
const qboolean ingame = CL_IsInGame();
const int num_samples = ( end - paintedtime ) / ( SOUND_DMA_SPEED / rate );
const int num_samples = ( end - snd.paintedtime ) / ( SOUND_DMA_SPEED / rate );
// FWGS feature: make everybody sound like chipmunks when we're going fast
const float pitch_mult = ( sys_timescale.value + 1 ) / 2;
@@ -248,25 +248,25 @@ static int S_MixNormalChannels( portable_samplepair_t *dst, int end, int rate )
if( cl.background && cls.key_dest == key_console )
return num_mixed_channels; // no sounds in console with background map
for( int i = 0; i < total_channels; i++ )
for( int i = 0; i < snd.total_channels; i++ )
{
channel_t *ch = &channels[i];
channel_t *ch = &snd.channels[i];
if( !ch->sfx )
continue;
if( !cl.background )
{
if( cls.key_dest == key_console && ch->localsound )
if( cls.key_dest == key_console && FBitSet( ch->flags, FL_CHAN_LOCAL_SOUND ))
{
// play, playvol
}
else if(( cls.key_dest == key_menu || cl.paused ) && !ch->localsound && local )
else if(( cls.key_dest == key_menu || cl.paused ) && !FBitSet( ch->flags, FL_CHAN_LOCAL_SOUND ) && local )
{
// play only local sounds, keep pause for other
continue;
}
else if( cls.key_dest != key_menu && !ingame && !ch->staticsound )
else if( cls.key_dest != key_menu && !ingame && !FBitSet( ch->flags, FL_CHAN_STATIC_SOUND ))
{
// play only ambient sounds, keep pause for other
continue;
@@ -285,7 +285,7 @@ static int S_MixNormalChannels( portable_samplepair_t *dst, int end, int rate )
// if it's also not looping, free it
if( ch->leftvol < 8 && ch->rightvol < 8 )
{
if( !FBitSet( sc->flags, SOUND_LOOPED ) || !ch->use_loop )
if( !FBitSet( sc->flags, SOUND_LOOPED ) || !FBitSet( ch->flags, FL_CHAN_USE_LOOP ))
{
if( ch->inauduble_free_time == 0.0f )
ch->inauduble_free_time = host.realtime + MAX_CHANNEL_INAUDIBLE_TIME;
@@ -308,9 +308,9 @@ static int S_MixNormalChannels( portable_samplepair_t *dst, int end, int rate )
if( ent != NULL )
{
if( sc->width == 1 )
SND_MoveMouth8( &ent->mouth, ch->sample, sc, num_samples, ch->use_loop );
SND_MoveMouth8( &ent->mouth, ch->sample, sc, num_samples, FBitSet( ch->flags, FL_CHAN_USE_LOOP ));
else
SND_MoveMouth16( &ent->mouth, ch->sample, sc, num_samples, ch->use_loop );
SND_MoveMouth16( &ent->mouth, ch->sample, sc, num_samples, FBitSet( ch->flags, FL_CHAN_USE_LOOP ));
}
}
@@ -318,18 +318,18 @@ static int S_MixNormalChannels( portable_samplepair_t *dst, int end, int rate )
num_mixed_channels++;
if( ch->is_sentence )
if( ch->words )
{
VOX_MixChannelToBuffer( dst, ch, num_samples, rate, pitch );
if( ch->sentence_finished )
if( FBitSet( ch->flags, FL_CHAN_SENTENCE_FINISHED ))
S_FreeChannel( ch );
}
else
{
S_MixChannelToBuffer( dst, ch, num_samples, rate, pitch, 0, 0 );
if( ch->finished )
if( FBitSet( ch->flags, FL_CHAN_FINISHED ))
S_FreeChannel( ch );
}
}
@@ -375,7 +375,7 @@ static int S_MixNormalChannelsToRoombuffer( int end, int count )
// until there is no real usecase, let's keep it simple
int num_mixed_channels = S_MixNormalChannels( roombuffer, end, SOUND_11k );
if( dma.format.speed >= SOUND_22k )
if( snd.format.speed >= SOUND_22k )
{
if( num_mixed_channels > 0 )
S_UpsampleBuffer( roombuffer, count / ( SOUND_22k / SOUND_11k ));
@@ -383,7 +383,7 @@ static int S_MixNormalChannelsToRoombuffer( int end, int count )
num_mixed_channels += S_MixNormalChannels( roombuffer, end, SOUND_22k );
}
if( dma.format.speed >= SOUND_44k )
if( snd.format.speed >= SOUND_44k )
{
if( num_mixed_channels > 0 )
S_UpsampleBuffer( roombuffer, count / ( SOUND_44k / SOUND_22k ));
@@ -402,10 +402,10 @@ static int S_MixRawChannels( int end )
return 0;
// paint in the raw channels
for( size_t i = 0; i < ARRAYSIZE( raw_channels ); i++ )
for( size_t i = 0; i < snd.max_raw_channels; i++ )
{
// copy from the streaming sound source
rawchan_t *ch = raw_channels[i];
rawchan_t *ch = snd.raw_channels[i];
if( !ch )
continue;
@@ -434,7 +434,7 @@ static int S_MixRawChannels( int end )
uint stop = (end < ch->s_rawend) ? end : ch->s_rawend;
const uint mask = ch->max_samples - 1;
for( size_t i = 0, j = paintedtime; j < stop; i++, j++ )
for( size_t i = 0, j = snd.paintedtime; j < stop; i++, j++ )
{
pbuf[i].left += ( ch->rawsamples[j & mask].left * ch->leftvol ) >> 8;
pbuf[i].right += ( ch->rawsamples[j & mask].right * ch->rightvol ) >> 8;
@@ -443,8 +443,8 @@ static int S_MixRawChannels( int end )
if( ch->entnum > 0 )
{
cl_entity_t *ent = CL_GetEntityByIndex( ch->entnum );
int pos = paintedtime & ( ch->max_samples - 1 );
int count = bound( 0, ch->max_samples - pos, stop - paintedtime );
int pos = snd.paintedtime & ( ch->max_samples - 1 );
int count = bound( 0, ch->max_samples - pos, stop - snd.paintedtime );
if( ent )
SND_MoveMouthRaw( &ent->mouth, &ch->rawsamples[pos], count );
@@ -486,8 +486,8 @@ static void S_WriteLinearBlastStereo16( short *snd_out, const int *snd_p, size_t
static void S_TransferPaintBuffer( const portable_samplepair_t *src, int endtime )
{
const int *snd_p = (const int *)src;
const int sampleMask = ((dma.samples >> 1) - 1);
int lpaintedtime = paintedtime;
const int sampleMask = ((snd.samples >> 1) - 1);
int lpaintedtime = snd.paintedtime;
SNDDMA_BeginPainting ();
@@ -496,9 +496,9 @@ static void S_TransferPaintBuffer( const portable_samplepair_t *src, int endtime
// handle recirculating buffer issues
int lpos = lpaintedtime & sampleMask;
short *snd_out = (short *)dma.buffer + (lpos << 1);
short *snd_out = (short *)snd.buffer + (lpos << 1);
int snd_linear_count = (dma.samples>>1) - lpos;
int snd_linear_count = (snd.samples>>1) - lpos;
if( lpaintedtime + snd_linear_count > endtime )
snd_linear_count = endtime - lpaintedtime;
@@ -526,14 +526,14 @@ void S_PaintChannels( int endtime )
{
int gain = S_GetMasterVolume() * 256;
while( paintedtime < endtime )
while( snd.paintedtime < endtime )
{
// if paintbuffer is smaller than DMA buffer
int end = endtime;
if( end - paintedtime > PAINTBUFFER_SIZE )
end = paintedtime + PAINTBUFFER_SIZE;
if( end - snd.paintedtime > PAINTBUFFER_SIZE )
end = snd.paintedtime + PAINTBUFFER_SIZE;
const int num_samples = end - paintedtime;
const int num_samples = end - snd.paintedtime;
S_ClearBuffers( num_samples );
@@ -550,6 +550,6 @@ void S_PaintChannels( int endtime )
// transfer out according to DMA format
S_TransferPaintBuffer( paintbuffer, end );
paintedtime = end;
snd.paintedtime = end;
}
}

View File

@@ -92,7 +92,7 @@ void S_StartBackgroundTrack( const char *introTrack, const char *mainTrack, int
{
S_StopBackgroundTrack();
if( !dma.initialized ) return;
if( !snd.initialized ) return;
// check for special symbols
if( introTrack && *introTrack == '*' )
@@ -132,9 +132,9 @@ S_StopBackgroundTrack
*/
void S_StopBackgroundTrack( void )
{
s_listener.stream_paused = false;
snd.stream_paused = false;
if( !dma.initialized ) return;
if( !snd.initialized ) return;
if( !s_bgTrack.stream ) return;
FS_FreeStream( s_bgTrack.stream );
@@ -149,7 +149,7 @@ S_StreamSetPause
*/
void S_StreamSetPause( int pause )
{
s_listener.stream_paused = pause;
snd.stream_paused = pause;
}
/*
@@ -197,11 +197,11 @@ void S_StreamBackgroundTrack( void )
int r, fileBytes;
rawchan_t *ch = NULL;
if( !dma.initialized || !s_bgTrack.stream || s_listener.streaming )
if( !snd.initialized || !s_bgTrack.stream || snd.streaming )
return;
// don't bother playing anything if musicvolume is 0
if( !s_musicvolume.value || cl.paused || s_listener.stream_paused )
if( !s_musicvolume.value || cl.paused || snd.stream_paused )
return;
if( !cl.background )
@@ -218,14 +218,14 @@ void S_StreamBackgroundTrack( void )
Assert( ch != NULL );
// see how many samples should be copied into the raw buffer
if( ch->s_rawend < soundtime )
ch->s_rawend = soundtime;
if( ch->s_rawend < snd.soundtime )
ch->s_rawend = snd.soundtime;
while( ch->s_rawend < soundtime + ch->max_samples )
while( ch->s_rawend < snd.soundtime + ch->max_samples )
{
const stream_t *info = s_bgTrack.stream;
bufferSamples = ch->max_samples - (ch->s_rawend - soundtime);
bufferSamples = ch->max_samples - (ch->s_rawend - snd.soundtime);
// decide how much data needs to be read from the file
fileSamples = bufferSamples * ((float)info->rate / SOUND_DMA_SPEED );
@@ -283,9 +283,9 @@ S_StartStreaming
*/
void S_StartStreaming( void )
{
if( !dma.initialized ) return;
if( !snd.initialized ) return;
// begin streaming movie soundtrack
s_listener.streaming = true;
snd.streaming = true;
}
/*
@@ -295,6 +295,6 @@ S_StopStreaming
*/
void S_StopStreaming( void )
{
if( !dma.initialized ) return;
s_listener.streaming = false;
if( !snd.initialized ) return;
snd.streaming = false;
}

View File

@@ -140,7 +140,7 @@ static void S_TrimStartEndTimes( channel_t *ch, wavdata_t *wav, int start, int e
void VOX_LoadWord( channel_t *ch )
{
ch->sentence_finished = true;
SetBits( ch->flags, FL_CHAN_SENTENCE_FINISHED );
if( ch->word_index < 0 || ch->word_index >= CVOXWORDMAX )
return;
@@ -155,7 +155,7 @@ void VOX_LoadWord( channel_t *ch )
if( !data )
return;
ch->sentence_finished = false;
ClearBits( ch->flags, FL_CHAN_SENTENCE_FINISHED );
ch->data = data;
int start = word->start;
@@ -171,7 +171,7 @@ void VOX_FreeWord( channel_t *ch )
{
// TODO: don't set random fields to zero lol, was memset before
ch->sample = ch->forced_end = 0.0;
ch->finished = false;
ClearBits( ch->flags, FL_CHAN_FINISHED );
ch->data = NULL;
if( ch->word_index < 0 || ch->word_index >= CVOXWORDMAX )
@@ -179,7 +179,7 @@ void VOX_FreeWord( channel_t *ch )
voxword_t *word = &ch->words[ch->word_index];
if( !word->sfx || word->in_cache )
if( !word->sfx || FBitSet( word->flags, FL_VOXWORD_IN_CACHE ))
return;
FS_FreeSound( word->sfx->cache );
@@ -191,7 +191,7 @@ void VOX_SetChanVol( channel_t *ch )
{
voxword_t *word;
if( !ch->is_sentence || ch->sentence_finished )
if( !ch->words || FBitSet( ch->flags, FL_CHAN_SENTENCE_FINISHED ))
return;
word = &ch->words[ch->word_index];
@@ -207,7 +207,7 @@ float VOX_ModifyPitch( channel_t *ch, float pitch )
{
voxword_t *word;
if( !ch->is_sentence || ch->sentence_finished )
if( !ch->words || FBitSet( ch->flags, FL_CHAN_SENTENCE_FINISHED ))
return pitch;
word = &ch->words[ch->word_index];
@@ -356,10 +356,7 @@ static void VOX_MakeDefaultWordParams( voxword_t *voxword )
*voxword = (voxword_t) {
.volume = 100,
.pitch = 100,
.start = 0,
.end = 100,
.timecompress = 0,
.in_cache = false,
};
}
@@ -416,19 +413,24 @@ static qboolean VOX_ParseWordParams( char *psz, voxword_t *pvoxword, voxword_t *
i = Q_atoi( sznum );
switch( command )
{
case 'e': pvoxword->end = i; break;
case 'p': pvoxword->pitch = i; break;
case 's': pvoxword->start = i; break;
case 't': pvoxword->timecompress = i; break;
case 'v': pvoxword->volume = i; break;
case 'e':
pvoxword->end = bound( 0, i, 100 );
break;
case 'p':
pvoxword->pitch = bound( 0, i, UINT16_MAX );
break;
case 's':
pvoxword->start = bound( 0, i, 100 );
break;
case 't':
pvoxword->timecompress = bound( 0, i, 100 );
break;
case 'v':
pvoxword->volume = bound( 0, i, UINT16_MAX );
break;
}
}
// validate some of the parameters
pvoxword->start = bound( 0, pvoxword->start, 100 );
pvoxword->end = bound( 0, pvoxword->end, 100 );
pvoxword->timecompress = bound( 0, pvoxword->timecompress, 100 );
// no actual word but new defaults
if( Q_strlen( pszsave ) == 0 )
{
@@ -447,10 +449,18 @@ void VOX_LoadSound( channel_t *ch, const char *pszin )
int i, j;
int num_words;
voxword_t default_voxword;
voxword_t words_buf[CVOXWORDMAX + 1]; // local scratch: parsed words + null terminator
if( !pszin )
return;
// free any existing words from a previous sentence on this channel
if( ch->words )
{
VOX_FreeWord( ch );
Mem_Free2( &ch->words );
}
psz = VOX_LookupString( pszin );
if( !psz )
@@ -478,12 +488,13 @@ void VOX_LoadSound( channel_t *ch, const char *pszin )
num_words = VOX_ParseString( buffer, rgpparseword );
VOX_MakeDefaultWordParams( &default_voxword );
memset( words_buf, 0, sizeof( words_buf ));
for( i = 0, j = 0; i < num_words; i++ )
{
char pathbuffer[MAX_SYSPATH];
if( !VOX_ParseWordParams( rgpparseword[i], &ch->words[j], &default_voxword ))
if( !VOX_ParseWordParams( rgpparseword[i], &words_buf[j], &default_voxword ))
continue;
if( Q_snprintf( pathbuffer, sizeof( pathbuffer ), "%s%s", szpath, rgpparseword[i] ) < 0 )
@@ -493,17 +504,19 @@ void VOX_LoadSound( channel_t *ch, const char *pszin )
}
qboolean in_cache = false;
ch->words[j].sfx = S_FindName( pathbuffer, &in_cache );
ch->words[j].in_cache = in_cache;
words_buf[j].sfx = S_FindName( pathbuffer, &in_cache );
if( in_cache )
SetBits( words_buf[j].flags, FL_VOXWORD_IN_CACHE );
j++;
}
ch->words[j].sfx = NULL;
// words_buf[j].sfx is already NULL from the memset — null terminator
ch->words = Mem_Malloc( sndpool, ( j + 1 ) * sizeof( voxword_t ));
memcpy( ch->words, words_buf, ( j + 1 ) * sizeof( voxword_t ));
ch->sfx = ch->words[0].sfx;
ch->word_index = 0;
ch->is_sentence = true;
VOX_LoadWord( ch );
}

View File

@@ -55,15 +55,17 @@ typedef struct sfx_s
struct sfx_s *hashNext;
} sfx_t;
#define FL_VOXWORD_IN_CACHE BIT( 0 ) // if set, it was loaded prior and shouldn't be freed
typedef struct voxword_s
{
sfx_t *sfx;
uint16_t volume; // volume percent
uint16_t pitch; // pitch shift percent (keep large for extra chipmunk fun)
uint16_t timecompress; // percent of skipped data (speeds up playback without pitch shift)
uint16_t start : 7; // percent at which playback starts
uint16_t end : 7; // percent at which playback ends
uint16_t in_cache : 1; // if set to 1, it was loaded prior and shouldn't be freed
sfx_t *sfx;
uint16_t volume; // volume percent
uint16_t pitch; // pitch shift percent (keep large for extra chipmunk fun)
uint8_t timecompress; // percent of skipped data (speeds up playback without pitch shift)
uint8_t start; // percent at which playback starts
uint8_t end; // percent at which playback ends
uint8_t flags;
} voxword_t;
typedef struct snd_format_s
@@ -73,19 +75,9 @@ typedef struct snd_format_s
byte channels;
} snd_format_t;
typedef struct dma_api_s
{
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;
typedef struct rawchan_s
{
int entnum;
short entnum;
short master_vol;
short leftvol; // 0-255 left volume
short rightvol; // 0-255 right volume
@@ -93,31 +85,37 @@ typedef struct rawchan_s
vec3_t origin; // only use if fixed_origin is set
volatile uint s_rawend;
float oldtime; // catch time jumps
uintptr_t engine_reserved[8]; // only for engine developers
uintptr_t game_reserved[8]; // free space for game developers
size_t max_samples; // buffer length
portable_samplepair_t rawsamples[]; // variable sized
} rawchan_t;
#define FL_CHAN_USE_LOOP BIT( 0 ) // don't loop default and local sounds
#define FL_CHAN_STATIC_SOUND BIT( 1 ) // use origin instead of fetching entnum's origin
#define FL_CHAN_LOCAL_SOUND BIT( 2 ) // it's a local menu sound (not looped, not paused)
#define FL_CHAN_SENTENCE_FINISHED BIT( 4 ) // if set, finished playing sentence
#define FL_CHAN_FINISHED BIT( 5 ) // if set, finished playing single word
typedef struct channel_s
{
char name[16]; // keep sentence name
sfx_t *sfx; // sfx number
sfx_t *sfx; // sfx number
vec3_t origin; // only use if fixed_origin is set
float dist_mult; // distance multiplier (attenuation/clipK)
int entnum; // entity soundsource
int entchannel; // sound channel (CHAN_STREAM, CHAN_VOICE, etc.)
uint flags;
short entnum; // entity soundsource
short master_vol; // 0-255 master volume
short leftvol; // 0-255 left volume
short rightvol; // 0-255 right volume
short basePitch; // base pitch percent (100% is normal pitch playback)
byte use_loop : 1; // don't loop default and local sounds
byte staticsound : 1; // use origin instead of fetching entnum's origin
byte localsound : 1; // it's a local menu sound (not looped, not paused)
byte is_sentence : 1; // bit indicating vox sentence
byte sentence_finished : 1; // if set, finished playing sentence
byte finished : 1; // if set, finished playing single word
byte word_index;
// HACKHACK: count when this channel became inaudible
// to not free it when it could be respatialized soon
#define MAX_CHANNEL_INAUDIBLE_TIME 0.1f
@@ -126,20 +124,43 @@ typedef struct channel_s
double sample;
double forced_end;
wavdata_t *data;
voxword_t words[CVOXWORDMAX];
voxword_t *words; // dynamically allocated, (num_words + 1) entries, null sfx terminates
uintptr_t engine_reserved[8]; // only for engine developers
uintptr_t game_reserved[8]; // free space for game developers
} channel_t;
typedef struct
{
vec3_t origin; // simorg + view_ofs
vec3_t forward;
vec3_t right;
vec3_t up;
typedef int sound_t;
int entnum;
qboolean streaming; // playing AVI-file
qboolean stream_paused; // pause only background track
} listener_t;
typedef struct snd_globals_s
{
// dma
const char *backend_name;
byte *buffer;
snd_format_t format;
qboolean initialized; // sound engine is active
int samples; // mono samples in buffer
int samplepos; // in mono samples
int paintedtime; // total samples that have been mixed at speed
int soundtime; // total samples that have been played out to hardware at dma speed
// listener (client, camera, etc)
vec3_t origin;
vec3_t forward, right, up;
int entnum;
qboolean streaming; // playing AVI-file
qboolean stream_paused; // pause only background track
// SoundAPI shared pointers
channel_t *const channels;
int max_channels;
int total_channels;
rawchan_t **const raw_channels;
int max_raw_channels;
sound_t ambient_sfx[NUM_AMBIENTS];
qboolean have_ambient_sfx;
} snd_globals_t;
//====================================================================
@@ -149,16 +170,8 @@ typedef struct
#define MAX_RAW_SAMPLES 16384
#define SND_CLIP_DISTANCE 1000.0f
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 int idsp_room;
extern snd_globals_t snd;
extern convar_t s_musicvolume;
extern convar_t s_lerping;

View File

@@ -51,12 +51,12 @@ GetLittleLong
*/
static int GetLittleLong( void )
{
int val = 0;
uint val = 0;
val += (*(iff_dataPtr+0) << 0);
val += (*(iff_dataPtr+1) << 8);
val += (*(iff_dataPtr+2) <<16);
val += (*(iff_dataPtr+3) <<24);
val += ((uint)*(iff_dataPtr+0) << 0);
val += ((uint)*(iff_dataPtr+1) << 8);
val += ((uint)*(iff_dataPtr+2) <<16);
val += ((uint)*(iff_dataPtr+3) <<24);
iff_dataPtr += 4;
return val;

View File

@@ -37,8 +37,6 @@ GNU General Public License for more details.
#include "com_model.h"
#include "com_strings.h"
#include "crtlib.h"
#define FSCALLBACK_OVERRIDE_MALLOC_LIKE
#include "fscallback.h"
#include "cvar.h"
#include "con_nprint.h"
#include "crclib.h"
@@ -383,6 +381,10 @@ void Mem_Stats_f( void );
#define Mem_Calloc( pool, size ) _Mem_Alloc( pool, size, true, __FILE__, __LINE__ )
#define Mem_Realloc( pool, ptr, size ) _Mem_Realloc( pool, ptr, size, true, __FILE__, __LINE__ )
#define Mem_Free( mem ) _Mem_Free( mem, __FILE__, __LINE__ )
#define Mem_Free2( ptr ) { \
_Mem_Free( *ptr, __FILE__, __LINE__ ); \
*ptr = NULL; }
#define Mem_AllocPool( name ) _Mem_AllocPool( name, __FILE__, __LINE__ )
#define Mem_FreePool( pool ) _Mem_FreePool( pool, __FILE__, __LINE__ )
#define Mem_EmptyPool( pool ) _Mem_EmptyPool( pool, __FILE__, __LINE__ )

View File

@@ -1199,6 +1199,9 @@ void Con_CompleteCommand( field_t *field, qboolean print_suggestions )
// setup the completion field
con.completionField = field;
if( COM_StringEmpty( con.completionField->buffer ))
return;
// only look at the first token for completion purposes
Cmd_TokenizeString( con.completionField->buffer );

View File

@@ -36,6 +36,8 @@ GNU General Public License for more details.
#include "enginefeatures.h"
#include "render_api.h" // decallist_t
#include "tests.h"
#include "library.h"
#include "platform/platform.h"
host_parm_t host; // host parms
static jmp_buf return_from_main_buf;
@@ -861,6 +863,118 @@ static void Host_DetermineExecutableName( char *out, size_t size )
#endif
}
static qboolean Host_CollectX86Libraries( ECommonLibraryType lib_type,
const char *win_path, const char *lin_path, const char *osx_path,
char *found, size_t found_size )
{
string native_path;
qboolean has_any = false;
found[0] = 0;
COM_GetCommonLibraryPath( lib_type, native_path, sizeof( native_path ));
if( Platform_LibraryExists( native_path, true ))
return 0;
#if !( XASH_WIN32 && XASH_X86 )
if( !COM_StringEmpty( win_path ) && FS_FileExists( win_path, true ))
{
Q_strncat( found, "Windows (x86)", found_size );
has_any = true;
}
#endif
#if !( XASH_LINUX && !XASH_ANDROID && XASH_X86 )
if( !COM_StringEmpty( lin_path ) && FS_FileExists( lin_path, true ))
{
if( has_any )
Q_strncat( found, ", ", found_size );
Q_strncat( found, "GNU/Linux (x86)", found_size );
has_any = true;
}
#endif
#if !( XASH_APPLE && XASH_X86 )
if( !COM_StringEmpty( osx_path ) && FS_FileExists( osx_path, true ))
{
if( has_any )
Q_strncat( found, ", ", found_size );
Q_strncat( found, "macOS (x86)", found_size );
has_any = true;
}
#endif
return has_any;
}
static void Host_CheckGameLibraries( void )
{
// on Android, game libraries are loaded from APKs and are invisible to FS_FileExists,
// so the check cannot work there; iOS is handled via Platform_LibraryExists -> IOS_LibraryExists
#if !defined( XASH_INTERNAL_GAMELIBS ) && !XASH_ANDROID
struct
{
const char *name;
ECommonLibraryType type;
const char *override; // host.gamedll / host.clientlib / host.menulib
} libs[3] = {
{ "client", LIBRARY_CLIENT, host.clientlib },
{ "server", LIBRARY_SERVER, host.gamedll },
{ "menu", LIBRARY_GAMEUI, host.menulib },
};
char details[MAX_VA_STRING];
details[0] = 0;
for( int i = 0; i < ARRAYSIZE( libs ); i++ )
{
string found;
qboolean ret;
// if the user explicitly set a library path, trust them and skip the check
if( !COM_StringEmpty( libs[i].override ))
continue;
if( libs[i].type == LIBRARY_SERVER )
{
// missing server library is only critical when singleplayer is available
// mirrors silent mode in SV_InitGame
if( GI->gamemode != GAME_SINGLEPLAYER_ONLY )
continue;
ret = Host_CollectX86Libraries( libs[i].type,
GI->game_dll, GI->game_dll_linux, GI->game_dll_osx,
found, sizeof( found ));
}
else
{
string win, lin, osx;
Q_snprintf( win, sizeof( win ), "%s/%s.dll", GI->dll_path, libs[i].name );
Q_snprintf( lin, sizeof( lin ), "%s/%s.so", GI->dll_path, libs[i].name );
Q_snprintf( osx, sizeof( osx ), "%s/%s.dylib", GI->dll_path, libs[i].name );
ret = Host_CollectX86Libraries( libs[i].type,
win, lin, osx, found, sizeof( found ));
}
if( ret )
{
size_t len = Q_strlen( details );
Q_snprintf( details + len, sizeof( details ) - len, "- %s: %s\n", libs[i].name, found );
}
}
if( COM_StringEmpty( details ))
return;
Sys_Warn( "No native game libraries found for current platform (%s-%s),\n"
"but found libraries for other platforms:\n"
"%s"
"The game may fail to load or work incorrectly.\n"
"Consider using a mod version built for this platform.",
Q_buildos(), Q_buildarch(), details );
#endif // XASH_INTERNAL_GAMELIBS
}
/*
=================
Host_InitCommon
@@ -998,6 +1112,7 @@ static void Host_InitCommon( int argc, char **argv, const char *progname, qboole
#endif
FS_LoadGameInfo();
Host_CheckGameLibraries();
Cvar_PostFSInit();
Image_CheckPaletteQ1 ();

View File

@@ -2587,7 +2587,7 @@ static void Mod_InitSkyClouds( model_t *mod, const mip_t *mt, texture_t *tx, qbo
r_temp.palette = NULL;
// load it in
solidskyTexture = GL_LoadTextureInternal( "solid_sky", &r_temp, TF_NOMIPMAP );
solidskyTexture = GL_LoadTextureInternal( "solid_sky", &r_temp, TF_NOMIPMAP | TF_ALLOW_NEAREST );
for( i = 0; i < r_sky->width >> 1; i++ )
{
@@ -2610,7 +2610,7 @@ static void Mod_InitSkyClouds( model_t *mod, const mip_t *mt, texture_t *tx, qbo
r_temp.flags = IMAGE_HAS_COLOR|IMAGE_HAS_ALPHA;
// load it in
alphaskyTexture = GL_LoadTextureInternal( "alpha_sky", &r_temp, TF_NOMIPMAP );
alphaskyTexture = GL_LoadTextureInternal( "alpha_sky", &r_temp, TF_NOMIPMAP | TF_ALLOW_NEAREST );
// clean up
FS_FreeImage( r_sky );
@@ -3599,6 +3599,10 @@ Mod_LoadVisibility
*/
static void Mod_LoadVisibility( model_t *mod, dbspmodel_t *bmod )
{
// external bmodels have no visibility
if( !bmod->visdata || !bmod->visdatasize )
return;
mod->visdata = Mem_Malloc( mod->mempool, bmod->visdatasize );
memcpy( mod->visdata, bmod->visdata, bmod->visdatasize );
}
@@ -3793,7 +3797,7 @@ static fs_offset_t Mod_FindBSPX( const byte *mod_base, size_t bufferlen )
max_offset = ALIGN( max_offset, 4 ); // force 32-bit boundary
if( max_offset > bufferlen )
if( max_offset + sizeof( dbspx_hdr_t ) > bufferlen )
return -1;
bspx_header = (const dbspx_hdr_t *)( mod_base + max_offset );
@@ -3878,8 +3882,11 @@ static qboolean Mod_LoadBmodelLumps( model_t *mod, byte *mod_base, size_t buffer
Mod_LoadLump( mod_base, &extlumps[i], &worldstats[stat_index], flags, LOADLUMP_BSP30EXT, NULL );
// loading bspx lumps
for( i = 0; i < ARRAYSIZE( bspxlumps ); i++, stat_index++ )
Mod_LoadLump( mod_base, &bspxlumps[i], &worldstats[stat_index], flags, LOADLUMP_BSPX, mod_base + bspx_header_offset );
if( bspx_header_offset >= 0 )
{
for( i = 0; i < ARRAYSIZE( bspxlumps ); i++, stat_index++ )
Mod_LoadLump( mod_base, &bspxlumps[i], &worldstats[stat_index], flags, LOADLUMP_BSPX, mod_base + bspx_header_offset );
}
if( !bmod->isworld ) // a1ba: why world excluded here?
{

View File

@@ -1658,7 +1658,7 @@ void Netchan_TransmitBits( netchan_t *chan, int length, const byte *data )
MSG_Init( &send, "NetSend", send_buf, sizeof( send_buf ));
// prepare the packet header
w1 = chan->outgoing_sequence | (send_reliable << 31);
w1 = chan->outgoing_sequence | (((uint)send_reliable ) << 31);
w2 = chan->incoming_sequence | (chan->incoming_reliable_sequence << 31);
send_reliable_fragment = false;

View File

@@ -112,7 +112,6 @@ msurface_t *PM_RecursiveSurfCheck( model_t *mod, mnode_t *node, vec3_t p1, vec3_
int i, side;
msurface_t *surf;
vec3_t mid;
mnode_t *children[2];
int numsurfaces, firstsurface;
loc0:
@@ -122,17 +121,15 @@ loc0:
t1 = PlaneDiff( p1, node->plane );
t2 = PlaneDiff( p2, node->plane );
node_children( children, node, mod );
if( t1 >= -FRAC_EPSILON && t2 >= -FRAC_EPSILON )
{
node = children[0];
node = node_child( node, 0, mod );
goto loc0;
}
if( t1 < FRAC_EPSILON && t2 < FRAC_EPSILON )
{
node = children[1];
node = node_child( node, 1, mod );
goto loc0;
}
@@ -142,7 +139,7 @@ loc0:
VectorLerp( p1, frac, p2, mid );
if(( surf = PM_RecursiveSurfCheck( mod, children[side], p1, mid )) != NULL )
if(( surf = PM_RecursiveSurfCheck( mod, node_child( node, side, mod ), p1, mid )) != NULL )
return surf;
// walk through real faces
@@ -179,7 +176,7 @@ loc0:
return NULL; // through the fence
}
return PM_RecursiveSurfCheck( mod, children[side^1], mid, p2 );
return PM_RecursiveSurfCheck( mod, node_child( node, side^1, mod ), mid, p2 );
}
/*
@@ -234,7 +231,6 @@ static int PM_TestLine_r( model_t *mod, mnode_t *node, vec_t p1f, vec_t p2f, con
float frac, midf;
int i, r, side;
vec3_t mid;
mnode_t *children[2];
int numsurfaces, firstsurface;
loc0:
@@ -252,17 +248,15 @@ loc0:
front = PlaneDiff( start, node->plane );
back = PlaneDiff( stop, node->plane );
node_children( children, node, mod );
if( front >= -FRAC_EPSILON && back >= -FRAC_EPSILON )
{
node = children[0];
node = node_child( node, 0, mod );
goto loc0;
}
if( front < FRAC_EPSILON && back < FRAC_EPSILON )
{
node = children[1];
node = node_child( node, 1, mod );
goto loc0;
}
@@ -273,7 +267,7 @@ loc0:
VectorLerp( start, frac, stop, mid );
midf = p1f + ( p2f - p1f ) * frac;
r = PM_TestLine_r( mod, children[side], p1f, midf, start, mid, trace );
r = PM_TestLine_r( mod, node_child( node, side, mod ), p1f, midf, start, mid, trace );
if( r != CONTENTS_EMPTY )
{
@@ -322,7 +316,7 @@ loc0:
return contents;
}
return PM_TestLine_r( mod, children[!side], midf, p2f, mid, stop, trace );
return PM_TestLine_r( mod, node_child( node, !side, mod ), midf, p2f, mid, stop, trace );
}
int PM_TestLineExt( playermove_t *pmove, physent_t *ents, int numents, const vec3_t start, const vec3_t end, int flags )

View File

@@ -13,63 +13,83 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
*/
#include <string.h>
#include <unistd.h>
#include <SDL.h>
#include <dlfcn.h>
#include <sys/stat.h>
#include "crtlib.h"
#include "library.h"
#include "platform/ios/lib_ios.h"
#include "common.h"
#define EXT_LENGTH 5
const char *g_szLibrarySuffix;
static void *IOS_LoadLibraryInternal( const char *dllname )
{
void *pHandle;
string errorstring = "";
char path[MAX_SYSPATH];
Q_snprintf( path, MAX_SYSPATH, "%s%s", SDL_GetBasePath(), dllname );
Q_snprintf( path, sizeof( path ), "%s%s", SDL_GetBasePath(), dllname );
pHandle = dlopen( path, RTLD_LAZY );
if( !pHandle )
{
COM_PushLibraryError(errorstring);
COM_PushLibraryError(dlerror());
}
COM_PushLibraryError(dlerror( ));
return pHandle;
}
const char *g_szLibrarySuffix;
static qboolean IOS_LibraryExistsInternal( const char *name )
{
struct stat buf;
char path[MAX_SYSPATH];
Q_snprintf( path, sizeof( path ), "%s%s", SDL_GetBasePath(), name );
return stat( path, &buf ) == 0;
}
static const char *IOS_GetLibraryPostfix( void )
{
if( g_szLibrarySuffix )
return g_szLibrarySuffix;
return Q_strcmp( host.default_gamedir, FS_Gamedir( )) ? FS_Gamedir( ) : "";
}
static void IOS_PrepareGameLibraryPath( const char *dllname, char *out, size_t outsize )
{
string strippedname;
Q_strncpy( strippedname, dllname, sizeof( strippedname ));
COM_StripExtension( strippedname );
Q_snprintf( out, outsize, "%s_%s.dylib", strippedname, IOS_GetLibraryPostfix( ));
}
void *IOS_LoadLibrary( const char *dllname )
{
//Immediately load if the library is filesystem_stdio.dylib or we will crash when accessing gamedir
if ( !Q_strcmp( dllname, "filesystem_stdio.dylib" ) )
{
// filesystem_stdio is a special case, as engine won't work correctly without it
// but it's always located at known path
if( !Q_strcmp( dllname, "filesystem_stdio.dylib" ))
return IOS_LoadLibraryInternal( dllname );
}
string name;
string strippedname;
const char *postfix = g_szLibrarySuffix;
char *pHandle;
if( !postfix )
{
if ( Q_strcmp(FS_Gamedir(), host.default_gamedir ) )
{
postfix = FS_Gamedir( );
}
else postfix = "";
}
Q_strncpy( strippedname, dllname, sizeof( strippedname ) );
COM_StripExtension(strippedname);
Q_snprintf( name, MAX_STRING, "%s_%s.dylib", strippedname, postfix );
IOS_PrepareGameLibraryPath( dllname, name, sizeof( name ));
pHandle = IOS_LoadLibraryInternal( name );
if( pHandle )
return pHandle;
if( !pHandle )
pHandle = IOS_LoadLibraryInternal( dllname );
return IOS_LoadLibraryInternal( dllname );
return pHandle;
}
qboolean IOS_LibraryExists( const char *dllname )
{
string name;
IOS_PrepareGameLibraryPath( dllname, name, sizeof( name ));
return IOS_LibraryExistsInternal( name ) || IOS_LibraryExistsInternal( dllname );
}

View File

@@ -20,6 +20,7 @@ GNU General Public License for more details.
#define Platform_POSIX_LoadLibrary( x ) IOS_LoadLibrary(( x ))
void *IOS_LoadLibrary( const char *dllname );
qboolean IOS_LibraryExists( const char *name );
#endif // IOS_LIB_H
#endif // TARGET_OS_IPHONE

View File

@@ -105,8 +105,8 @@ qboolean SNDDMA_Init( void )
return false;
}
dma.format.speed = SOUND_DMA_SPEED;
r = dma.format.speed;
snd.format.speed = SOUND_DMA_SPEED;
r = snd.format.speed;
if( ( err = snd_pcm_hw_params_set_rate_near( s_alsa.pcm_handle, s_alsa.hw_params, &r, &dir ) ) < 0 )
{
@@ -121,14 +121,14 @@ qboolean SNDDMA_Init( void )
if( dir != 0 )
{
Con_Printf( "ALSA: rate %d not supported, using %d\n", SOUND_DMA_SPEED, r );
dma.format.speed = r;
snd.format.speed = r;
dir = 0;
}
}
dma.format.channels = 2;
snd.format.channels = 2;
if( ( err = snd_pcm_hw_params_set_channels(s_alsa.pcm_handle, s_alsa.hw_params, dma.format.channels ) ) < 0 )
if( ( err = snd_pcm_hw_params_set_channels(s_alsa.pcm_handle, s_alsa.hw_params, snd.format.channels ) ) < 0 )
{
Con_Printf( "ALSA: cannot set channels %d(%s)\n", 2, snd_strerror( err ) );
snd_pcm_hw_params_free( s_alsa.hw_params );
@@ -162,7 +162,7 @@ qboolean SNDDMA_Init( void )
}
else
{
// if period is NPOT it cannot be used as dma.samples in Xash3D
// if period is NPOT it cannot be used as snd.samples in Xash3D
// and need more space to send buffer partially
samples = 1;
while( samples < p * 4 )
@@ -184,15 +184,15 @@ qboolean SNDDMA_Init( void )
return false;
}
dma.buffer = Mem_Calloc( sndpool, samples * 2 ); //allocate pcm frame buffer
dma.samplepos = 0;
dma.samples = samples;
dma.format.width = 2;
dma.initialized = 1;
dma.backendName = "ALSA";
snd.buffer = Mem_Calloc( sndpool, samples * 2 ); //allocate pcm frame buffer
snd.samplepos = 0;
snd.samples = samples;
snd.format.width = 2;
snd.initialized = 1;
snd.backend_name = "ALSA";
snd_pcm_prepare( s_alsa.pcm_handle );
snd_pcm_writei( s_alsa.pcm_handle, dma.buffer, 2 * s_alsa.period_size );
snd_pcm_writei( s_alsa.pcm_handle, snd.buffer, 2 * s_alsa.period_size );
snd_pcm_start( s_alsa.pcm_handle );
return true;
@@ -208,14 +208,14 @@ Closes the ALSA pcm device and frees the dma buffer.
void SNDDMA_Shutdown(void)
{
Con_Printf( "Shutting down audio.\n" );
dma.initialized = false;
snd.initialized = false;
if( dma.buffer )
if( snd.buffer )
{
snd_pcm_drop( s_alsa.pcm_handle );
snd_pcm_close( s_alsa.pcm_handle );
Mem_Free( dma.buffer );
dma.buffer = NULL;
Mem_Free( snd.buffer );
snd.buffer = NULL;
}
}
@@ -240,38 +240,38 @@ void SNDDMA_Submit( void )
while( avail >= s_alsa.period_size )
{
int size = dma.samples << 1;
int pos = dma.samplepos << 1;
int size = snd.samples << 1;
int pos = snd.samplepos << 1;
unsigned long len = s_alsa.period_size * 4;
int wrapped = pos + len - size;
int w;
if( wrapped < 0 )
{
w = snd_pcm_writei( s_alsa.pcm_handle, dma.buffer + pos, len / 4 );
w = snd_pcm_writei( s_alsa.pcm_handle, snd.buffer + pos, len / 4 );
if( w < 0 )
{
snd_pcm_prepare(s_alsa.pcm_handle);
return;
}
dma.samplepos += len >> 1;
snd.samplepos += len >> 1;
}
else
{
int remaining = size - pos;
w = snd_pcm_writei( s_alsa.pcm_handle, dma.buffer + pos, remaining / 4 );
w = snd_pcm_writei( s_alsa.pcm_handle, snd.buffer + pos, remaining / 4 );
if( w < 0 )
{
snd_pcm_prepare(s_alsa.pcm_handle);
return;
}
w = snd_pcm_writei( s_alsa.pcm_handle, dma.buffer, wrapped / 4 );
w = snd_pcm_writei( s_alsa.pcm_handle, snd.buffer, wrapped / 4 );
if( w < 0 )
{
snd_pcm_prepare(s_alsa.pcm_handle);
return;
}
dma.samplepos = wrapped >> 1;
snd.samplepos = wrapped >> 1;
}
avail = snd_pcm_avail_update( s_alsa.pcm_handle );
@@ -282,11 +282,11 @@ void SNDDMA_Submit( void )
int s, w, frames;
void *start;
if( !dma.buffer )
if( !snd.buffer )
return;
s = dma.samplepos * 2;
start = (void *)&dma.buffer[s];
s = snd.samplepos * 2;
start = (void *)&snd.buffer[s];
frames = s_alsa.period_size / 2;
// write to card
if( ( w = snd_pcm_writei( s_alsa.pcm_handle, start, frames ) ) < 0)
@@ -296,10 +296,10 @@ void SNDDMA_Submit( void )
return;
}
dma.samplepos += w * 2; // mark progress
snd.samplepos += w * 2; // mark progress
if(dma.samplepos >= dma.samples)
dma.samplepos = 0; // wrap buffer
if(snd.samplepos >= snd.samples)
snd.samplepos = 0; // wrap buffer
}
}
@@ -324,7 +324,7 @@ between a deactivate and an activate.
*/
void SNDDMA_Activate( qboolean active )
{
if( !dma.initialized )
if( !snd.initialized )
return;
s_alsa.paused = !active;

View File

@@ -18,6 +18,8 @@ GNU General Public License for more details.
#define PLATFORM_H
#include <errno.h>
#define FSCALLBACK_OVERRIDE_MALLOC_LIKE
#include "fscallback.h"
#include "common.h"
#include "system.h"
#include "defaults.h"
@@ -43,6 +45,7 @@ qboolean Platform_DebuggerPresent( void );
int IOS_GetArgs( char ***argv );
const char *IOS_GetDocsDir( void );
void IOS_LaunchDialog( void );
#include "platform/ios/lib_ios.h"
#endif // TARGET_OS_IOS
#if XASH_WIN32 || XASH_LINUX
@@ -207,6 +210,18 @@ static inline void Sys_RestoreCrashHandler( void )
}
#endif
static inline qboolean Platform_LibraryExists( const char *name, qboolean gamedironly )
{
#if XASH_IOS
return IOS_LibraryExists( name );
#elif XASH_ANDROID
// sorry, unimplemented
return false;
#else
return g_fsapi.FileExists( name, gamedironly );
#endif
}
/*
==============================================================================

View File

@@ -46,38 +46,38 @@ static char sdl_backend_name[32];
static void SDL_SoundCallback( void *userdata, Uint8 *stream, int len )
{
const int size = dma.samples << 1;
const int size = snd.samples << 1;
int pos;
int wrapped;
if( !dma.buffer )
if( !snd.buffer )
{
memset( stream, 0, len );
return;
}
pos = dma.samplepos << 1;
pos = snd.samplepos << 1;
if( pos >= size )
pos = dma.samplepos = 0;
pos = snd.samplepos = 0;
wrapped = pos + len - size;
if( wrapped < 0 )
{
memcpy( stream, dma.buffer + pos, len );
dma.samplepos += len >> 1;
memcpy( stream, snd.buffer + pos, len );
snd.samplepos += len >> 1;
}
else
{
int remaining = size - pos;
memcpy( stream, dma.buffer + pos, remaining );
memcpy( stream + remaining, dma.buffer, wrapped );
dma.samplepos = wrapped >> 1;
memcpy( stream, snd.buffer + pos, remaining );
memcpy( stream + remaining, snd.buffer, wrapped );
snd.samplepos = wrapped >> 1;
}
if( dma.samplepos >= size )
dma.samplepos = 0;
if( snd.samplepos >= size )
snd.samplepos = 0;
}
/*
@@ -131,20 +131,20 @@ qboolean SNDDMA_Init( void )
goto fail;
}
dma.format.speed = obtained.freq;
dma.format.channels = obtained.channels;
dma.format.width = 2;
snd.format.speed = obtained.freq;
snd.format.channels = obtained.channels;
snd.format.width = 2;
samplecount = s_samplecount.value;
if( !samplecount )
samplecount = 0x8000;
dma.samples = samplecount * obtained.channels;
dma.buffer = Mem_Calloc( sndpool, dma.samples * 2 );
dma.samplepos = 0;
snd.samples = samplecount * obtained.channels;
snd.buffer = Mem_Calloc( sndpool, snd.samples * 2 );
snd.samplepos = 0;
Con_Printf( "Using SDL audio driver: %s @ %d Hz\n", SDL_GetCurrentAudioDriver( ), obtained.freq );
Q_snprintf( sdl_backend_name, sizeof( sdl_backend_name ), "SDL" );
dma.initialized = true;
dma.backendName = sdl_backend_name;
snd.initialized = true;
snd.backend_name = sdl_backend_name;
SNDDMA_Activate( true );
@@ -191,7 +191,7 @@ Reset the sound device for exiting
void SNDDMA_Shutdown( void )
{
Con_Printf( "Shutting down audio.\n" );
dma.initialized = false;
snd.initialized = false;
if( sdl_dev )
{
@@ -203,10 +203,10 @@ void SNDDMA_Shutdown( void )
if( SDL_WasInit( SDL_INIT_AUDIO ))
SDL_QuitSubSystem( SDL_INIT_AUDIO );
if( dma.buffer )
if( snd.buffer )
{
Mem_Free( dma.buffer );
dma.buffer = NULL;
Mem_Free( snd.buffer );
snd.buffer = NULL;
}
}
@@ -220,7 +220,7 @@ between a deactivate and an activate.
*/
void SNDDMA_Activate( qboolean active )
{
if( !dma.initialized )
if( !snd.initialized )
return;
SDL_PauseAudioDevice( sdl_dev, !active );

View File

@@ -39,32 +39,32 @@ static char sdl_backend_name[32];
static void SDL_SoundCallback( void *userdata, Uint8 *stream, int len )
{
const int size = dma.samples << 1;
const int size = snd.samples << 1;
int pos;
int wrapped;
pos = dma.samplepos << 1;
pos = snd.samplepos << 1;
if( pos >= size )
pos = dma.samplepos = 0;
pos = snd.samplepos = 0;
wrapped = pos + len - size;
if( wrapped < 0 )
{
memcpy( stream, dma.buffer + pos, len );
dma.samplepos += len >> 1;
memcpy( stream, snd.buffer + pos, len );
snd.samplepos += len >> 1;
}
else
{
int remaining = size - pos;
memcpy( stream, dma.buffer + pos, remaining );
memcpy( stream + remaining, dma.buffer, wrapped );
dma.samplepos = wrapped >> 1;
memcpy( stream, snd.buffer + pos, remaining );
memcpy( stream + remaining, snd.buffer, wrapped );
snd.samplepos = wrapped >> 1;
}
if( dma.samplepos >= size )
dma.samplepos = 0;
if( snd.samplepos >= size )
snd.samplepos = 0;
}
/*
@@ -148,22 +148,22 @@ qboolean SNDDMA_Init( void )
goto fail;
}
dma.format.speed = obtained.freq;
dma.format.channels = obtained.channels;
dma.format.width = 2;
snd.format.speed = obtained.freq;
snd.format.channels = obtained.channels;
snd.format.width = 2;
samplecount = s_samplecount.value;
if( !samplecount )
samplecount = 0x8000;
dma.samples = samplecount * obtained.channels;
dma.buffer = Mem_Calloc( sndpool, dma.samples * 2 );
dma.samplepos = 0;
snd.samples = samplecount * obtained.channels;
snd.buffer = Mem_Calloc( sndpool, snd.samples * 2 );
snd.samplepos = 0;
sdl_format = obtained.format;
Con_Printf( "Using SDL audio driver: %s @ %d Hz\n", SDL_GetCurrentAudioDriver( ), obtained.freq );
Q_snprintf( sdl_backend_name, sizeof( sdl_backend_name ), "SDL (%s)", SDL_GetCurrentAudioDriver( ));
dma.initialized = true;
dma.backendName = sdl_backend_name;
snd.initialized = true;
snd.backend_name = sdl_backend_name;
SNDDMA_Activate( true );
@@ -179,7 +179,7 @@ fail:
==============
SNDDMA_BeginPainting
Makes sure dma.buffer is valid
Makes sure snd.buffer is valid
===============
*/
void SNDDMA_BeginPainting( void )
@@ -210,7 +210,7 @@ Reset the sound device for exiting
void SNDDMA_Shutdown( void )
{
Con_Printf( "Shutting down audio.\n" );
dma.initialized = false;
snd.initialized = false;
if( sdl_dev )
{
@@ -221,10 +221,10 @@ void SNDDMA_Shutdown( void )
SDL_QuitSubSystem( SDL_INIT_AUDIO );
if( dma.buffer )
if( snd.buffer )
{
Mem_Free( dma.buffer );
dma.buffer = NULL;
Mem_Free( snd.buffer );
snd.buffer = NULL;
}
}
@@ -238,7 +238,7 @@ between a deactivate and an activate.
*/
void SNDDMA_Activate( qboolean active )
{
if( !dma.initialized )
if( !snd.initialized )
return;
SDL_PauseAudioDevice( sdl_dev, !active );

View File

@@ -28,35 +28,35 @@ static char sdl_backend_name[32];
static void SDLash_OutputCallback( void *userdata, SDL_AudioStream *stream, int additional_amount, int len )
{
const int size = dma.samples << 1;
const int size = snd.samples << 1;
int pos;
int wrapped;
(void)userdata;
(void)additional_amount;
pos = dma.samplepos << 1;
pos = snd.samplepos << 1;
if( pos >= size )
pos = dma.samplepos = 0;
pos = snd.samplepos = 0;
wrapped = pos + len - size;
if( wrapped < 0 )
{
SDL_PutAudioStreamData( stream, dma.buffer + pos, len );
dma.samplepos += len >> 1;
SDL_PutAudioStreamData( stream, snd.buffer + pos, len );
snd.samplepos += len >> 1;
}
else
{
int remaining = size - pos;
SDL_PutAudioStreamData( stream, dma.buffer + pos, remaining );
SDL_PutAudioStreamData( stream, dma.buffer, wrapped );
dma.samplepos = wrapped >> 1;
SDL_PutAudioStreamData( stream, snd.buffer + pos, remaining );
SDL_PutAudioStreamData( stream, snd.buffer, wrapped );
snd.samplepos = wrapped >> 1;
}
if( dma.samplepos >= size )
dma.samplepos = 0;
if( snd.samplepos >= size )
snd.samplepos = 0;
}
/*
@@ -122,18 +122,18 @@ qboolean SNDDMA_Init( void )
return false;
}
dma.format.speed = SOUND_DMA_SPEED;
dma.format.channels = 2;
dma.format.width = 2;
snd.format.speed = SOUND_DMA_SPEED;
snd.format.channels = 2;
snd.format.width = 2;
int samplecount = s_samplecount.value;
if( !samplecount )
samplecount = 0x8000;
dma.samples = samplecount * dma.format.channels;
dma.buffer = Mem_Calloc( sndpool, dma.samples * dma.format.width );
dma.samplepos = 0;
dma.initialized = true;
snd.samples = samplecount * snd.format.channels;
snd.buffer = Mem_Calloc( sndpool, snd.samples * snd.format.width );
snd.samplepos = 0;
snd.initialized = true;
Q_snprintf( sdl_backend_name, sizeof( sdl_backend_name ), "SDL3 (%s)", SDL_GetCurrentAudioDriver( ));
dma.backendName = sdl_backend_name;
snd.backend_name = sdl_backend_name;
Con_Printf( "Using audio driver: %s @ %d Hz\n", sdl_backend_name, SOUND_DMA_SPEED );
@@ -178,7 +178,7 @@ Reset the sound device for exiting
void SNDDMA_Shutdown( void )
{
Con_Printf( "Shutting down audio.\n" );
dma.initialized = false;
snd.initialized = false;
if( out_stream )
{
@@ -189,10 +189,10 @@ void SNDDMA_Shutdown( void )
SDL_QuitSubSystem( SDL_INIT_AUDIO );
if( dma.buffer )
if( snd.buffer )
{
Mem_Free( dma.buffer );
dma.buffer = NULL;
Mem_Free( snd.buffer );
snd.buffer = NULL;
}
}
@@ -206,7 +206,7 @@ between a deactivate and an activate.
*/
void SNDDMA_Activate( qboolean active )
{
if( !dma.initialized )
if( !snd.initialized )
return;
if( active )

View File

@@ -30,8 +30,6 @@ so it can unlock and free the data block after it has been played.
=======================================================================
*/
dma_t dma;
void S_Activate( qboolean active )
{
}
@@ -86,11 +84,12 @@ Reset the sound device for exiting
void SNDDMA_Shutdown( void )
{
Con_Printf("Shutting down audio.\n");
dma.initialized = false;
snd.initialized = false;
if (dma.buffer) {
Z_Free(dma.buffer);
dma.buffer = NULL;
if( snd.buffer )
{
Mem_Free( snd.buffer );
snd.buffer = NULL;
}
}

View File

@@ -1518,7 +1518,6 @@ static qboolean SV_RecursiveLightPoint( model_t *model, mnode_t *node, const vec
float front, back, frac;
int i, side;
vec3_t mid;
mnode_t *children[2];
int numsurfaces, firstsurface;
// didn't hit anything
@@ -1529,18 +1528,16 @@ static qboolean SV_RecursiveLightPoint( model_t *model, mnode_t *node, const vec
front = PlaneDiff( start, node->plane );
back = PlaneDiff( end, node->plane );
node_children( children, node, model );
side = front < 0.0f;
if(( back < 0.0f ) == side )
return SV_RecursiveLightPoint( model, children[side], start, end, point_color );
return SV_RecursiveLightPoint( model, node_child( node, side, model ), start, end, point_color );
frac = front / ( front - back );
VectorLerp( start, frac, end, mid );
// co down front side
if( SV_RecursiveLightPoint( model, children[side], start, mid, point_color ))
if( SV_RecursiveLightPoint( model, node_child( node, side, model ), start, mid, point_color ))
return true; // hit something
if(( back < 0.0f ) == side )
@@ -1602,7 +1599,7 @@ static qboolean SV_RecursiveLightPoint( model_t *model, mnode_t *node, const vec
}
// go down back side
return SV_RecursiveLightPoint( model, children[!side], mid, end, point_color );
return SV_RecursiveLightPoint( model, node_child( node, !side, model ), mid, end, point_color );
}
/*

View File

@@ -747,6 +747,7 @@ static void FS_InitGameInfo( gameinfo_t *GameInfo, const char *gamedir, qboolean
if( quake )
{
Q_strncpy( GameInfo->basedir, "id1", sizeof( GameInfo->basedir ));
Q_strncpy( GameInfo->falldir, "qwrap", sizeof( GameInfo->falldir ));
Q_strncpy( GameInfo->title, gamedir, sizeof( GameInfo->title ));
Q_strncpy( GameInfo->startmap, "start", sizeof( GameInfo->startmap ));
Q_strncpy( GameInfo->dll_path, "bin", sizeof( GameInfo->dll_path ));
@@ -1123,27 +1124,28 @@ static qboolean FS_CheckForQuakeGameDir( const char *gamedir )
{
// if directory contain quake.rc or progs.dat it's 100% quake gamedir
// quake mods probably always archived, so check pak0.pak too
const char *files[] = { "progs.dat", "quake.rc" };
char buf[MAX_SYSPATH];
const char *files[] = { "pak0.pak", "PAK0.PAK", "progs.dat", "quake.rc" };
int i;
// try to read pak0.pak first, most quake mods are archived
if( Q_snprintf( buf, sizeof( buf ), "%s/pak0.pak", gamedir ) > 0 )
{
if( FS_SysFileExists( buf ))
{
if( FS_CheckForQuakePak( buf, files, sizeof( files ) / sizeof( files[0] )))
return true;
}
}
// search it in the filesystem
for( i = 0; i < sizeof( files ) / sizeof( files[0] ); i++ )
{
char buf[MAX_SYSPATH];
if( Q_snprintf( buf, sizeof( buf ), "%s/%s", gamedir, files[i] ) > 0 )
{
if( FS_SysFileExists( buf ))
if( !FS_SysFileExists( buf ))
continue;
if( !Q_stricmp( COM_FileExtension( buf ), "pak" ))
{
if( FS_CheckForQuakePak( buf, &files[2], sizeof( files ) / sizeof( files[0] ) - 2 ))
return true;
}
else
{
return true;
}
}
}

View File

@@ -337,7 +337,6 @@ Mod_CreateSkinData
static rgbdata_t *Mod_CreateSkinData( model_t *mod, const byte *data, int width, int height )
{
static rgbdata_t skin;
char name[MAX_QPATH];
int i;
skin.width = width;
@@ -363,10 +362,8 @@ static rgbdata_t *Mod_CreateSkinData( model_t *mod, const byte *data, int width,
}
}
COM_FileBase( mod->name, name, sizeof( name ));
// for alias models only player can have remap textures
if( mod != NULL && !Q_stricmp( name, "player" ))
if( mod != NULL && !Q_stricmp( mod->name, "player" ))
{
texture_t *tx = NULL;
int i, size;

View File

@@ -67,20 +67,20 @@ int R_CullSurface( const msurface_t *surf, const gl_frustum_t *frustum, uint cli
{
cl_entity_t *e = RI.currententity;
if( !e || !surf || !surf->texinfo || !surf->texinfo->texture )
return CULL_OTHER;
if( r_nocull.value )
return CULL_VISIBLE;
// world surfaces can be culled by vis frame too
if( e == CL_GetEntityByIndex( 0 ) && surf->visframe != tr.framecount )
if( surf->visframe != tr.framecount && e == CL_GetEntityByIndex( 0 ))
return CULL_VISFRAME;
// only static ents can be culled by frustum
if( !R_StaticEntity( e )) frustum = NULL;
if( unlikely( !surf->texinfo || !surf->texinfo->texture ))
return CULL_OTHER;
if( !VectorIsNull( surf->plane->normal ))
if( unlikely( r_nocull.value ))
return CULL_VISIBLE;
// only static ents can be culled by frustum
if( !R_StaticEntity( e ))
frustum = NULL;
if( glState.faceCull != GL_NONE && !VectorIsNull( surf->plane->normal ))
{
float dist;
@@ -95,35 +95,22 @@ int R_CullSurface( const msurface_t *surf, const gl_frustum_t *frustum, uint cli
}
else dist = PlaneDiff( tr.modelorg, surf->plane );
if( FBitSet( surf->flags, SURF_PLANEBACK ))
dist = -dist;
if( glState.faceCull == GL_FRONT )
{
if( FBitSet( surf->flags, SURF_PLANEBACK ))
{
if( dist >= -BACKFACE_EPSILON )
return CULL_BACKSIDE; // wrong side
}
else
{
if( dist <= BACKFACE_EPSILON )
return CULL_BACKSIDE; // wrong side
}
if( dist <= BACKFACE_EPSILON )
return CULL_BACKSIDE;
}
else if( glState.faceCull == GL_BACK )
else // if( glState.faceCull == GL_BACK )
{
if( FBitSet( surf->flags, SURF_PLANEBACK ))
{
if( dist <= BACKFACE_EPSILON )
return CULL_BACKSIDE; // wrong side
}
else
{
if( dist >= -BACKFACE_EPSILON )
return CULL_BACKSIDE; // wrong side
}
if( dist >= -BACKFACE_EPSILON )
return CULL_BACKSIDE;
}
}
if( frustum && GL_FrustumCullBox( frustum, surf->info->mins, surf->info->maxs, clipflags ))
if( frustum && clipflags && GL_FrustumCullBox( frustum, surf->info->mins, surf->info->maxs, clipflags ))
return CULL_FRUSTUM;
return CULL_VISIBLE;

View File

@@ -697,11 +697,8 @@ static void R_DecalNodeSurfaces( model_t *model, mnode_t *node, decalinfo_t *dec
//-----------------------------------------------------------------------------
static void R_DecalNode( model_t *model, mnode_t *node, decalinfo_t *decalinfo )
{
mplane_t *splitplane;
float dist;
mnode_t *children[2];
Assert( node != NULL );
mplane_t *splitplane;
float dist;
if( node->contents < 0 )
{
@@ -711,31 +708,22 @@ static void R_DecalNode( model_t *model, mnode_t *node, decalinfo_t *decalinfo )
splitplane = node->plane;
dist = DotProduct( decalinfo->m_Position, splitplane->normal ) - splitplane->dist;
node_children( children, node, model );
// This is arbitrarily set to 10 right now. In an ideal world we'd have the
// exact surface but we don't so, this tells me which planes are "sort of
// close" to the gunshot -- the gunshot is actually 4 units in front of the
// wall (see dlls\weapons.cpp). We also need to check to see if the decal
// actually intersects the texture space of the surface, as this method tags
// parallel surfaces in the same node always.
// JAY: This still tags faces that aren't correct at edges because we don't
// have a surface normal
if( dist > decalinfo->m_Size )
{
R_DecalNode( model, children[0], decalinfo );
R_DecalNode( model, node_child( node, 0, model ), decalinfo );
}
else if( dist < -decalinfo->m_Size )
{
R_DecalNode( model, children[1], decalinfo );
R_DecalNode( model, node_child( node, 1, model ), decalinfo );
}
else
{
if( dist < DECAL_DISTANCE && dist > -DECAL_DISTANCE )
R_DecalNodeSurfaces( model, node, decalinfo );
R_DecalNode( model, children[0], decalinfo );
R_DecalNode( model, children[1], decalinfo );
R_DecalNode( model, node_child( node, 0, model ), decalinfo );
R_DecalNode( model, node_child( node, 1, model ), decalinfo );
}
}

View File

@@ -99,15 +99,14 @@ void GL_FrustumInitOrtho( gl_frustum_t *out, float xLeft, float xRight, float yT
// cull methods
qboolean GL_FrustumCullBox( const gl_frustum_t *out, const vec3_t mins, const vec3_t maxs, int userClipFlags )
{
int iClipFlags;
int iClipFlags = userClipFlags != 0 ? userClipFlags : out->clipFlags;
int i, bit;
if( r_nocull.value )
if( unlikely( r_nocull.value ))
return false;
if( userClipFlags != 0 )
iClipFlags = userClipFlags;
else iClipFlags = out->clipFlags;
if( !iClipFlags )
return false;
for( i = FRUSTUM_PLANES, bit = 1; i > 0; i--, bit <<= 1 )
{
@@ -160,15 +159,14 @@ qboolean GL_FrustumCullBox( const gl_frustum_t *out, const vec3_t mins, const ve
qboolean GL_FrustumCullSphere( const gl_frustum_t *out, const vec3_t center, float radius, int userClipFlags )
{
int iClipFlags;
int iClipFlags = userClipFlags != 0 ? userClipFlags : out->clipFlags;
int i, bit;
if( r_nocull.value )
if( unlikely( r_nocull.value ))
return false;
if( userClipFlags != 0 )
iClipFlags = userClipFlags;
else iClipFlags = out->clipFlags;
if( !iClipFlags )
return false;
for( i = FRUSTUM_PLANES, bit = 1; i > 0; i--, bit <<= 1 )
{

View File

@@ -46,7 +46,12 @@ acess to array elem
*/
gl_texture_t *R_GetTexture( unsigned int texnum )
{
Assert( texnum < MAX_TEXTURES );
if( texnum >= MAX_TEXTURES )
{
gEngfuncs.Host_Error( "%s: texnum (%d) >= MAX_TEXTURES (%d)", __func__, texnum, MAX_TEXTURES );
texnum = 0;
}
return &gl_textures[texnum];
}

View File

@@ -249,6 +249,7 @@ typedef struct
vec3_t modelorg; // relative to viewpoint
// get from engine
model_t *worldmodel;
world_static_t *world;
cl_entity_t *entities;
movevars_t *movevars;
@@ -770,7 +771,7 @@ static inline int GL_MaxTextureUnits( void )
return Q_min( glConfig.max_texture_units, MAX_TEXTURE_UNITS );
}
#define WORLDMODEL (gp_cl->models[1])
#define WORLDMODEL (tr.worldmodel)
//
// renderer cvars

View File

@@ -105,7 +105,6 @@ void R_MarkLights( const dlight_t *light, int bit, const mnode_t *node )
const float maxdist = light->radius * light->radius;
float dist;
int i;
mnode_t *children[2];
int firstsurface, numsurfaces;
start:
@@ -115,25 +114,25 @@ start:
dist = PlaneDiff( light->origin, node->plane );
node_children( children, node, RI.currentmodel );
if( dist > virtual_radius )
{
node = children[0];
node = node_child( node, 0, RI.currentmodel );
goto start;
}
if( dist < -virtual_radius )
{
node = children[1];
node = node_child( node, 1, RI.currentmodel );
goto start;
}
const float dist_sq = dist * dist;
// mark the polygons
firstsurface = node_firstsurface( node, RI.currentmodel );
numsurfaces = node_numsurfaces( node, RI.currentmodel );
for( i = 0; i < numsurfaces; i++ )
for( i = 0; i < numsurfaces && dist_sq < maxdist; i++ )
{
vec3_t impact;
float s, t, l;
@@ -160,7 +159,7 @@ start:
t = bound( 0, t, info->lightextents[1] );
t = l - t;
if( s * s + t * t + dist * dist >= maxdist )
if( s * s + t * t + dist_sq >= maxdist )
continue;
if( surf->dlightframe != tr.dlightframecount )
@@ -171,8 +170,8 @@ start:
else surf->dlightbits |= bit;
}
R_MarkLights( light, bit, children[0] );
R_MarkLights( light, bit, children[1] );
R_MarkLights( light, bit, node_child( node, 0, RI.currentmodel ));
R_MarkLights( light, bit, node_child( node, 1, RI.currentmodel ));
}
/*
@@ -236,7 +235,6 @@ static qboolean R_RecursiveLightPoint( model_t *model, mnode_t *node, float p1f,
mtexinfo_t *tex;
matrix3x4 tbn;
vec3_t mid;
mnode_t *children[2];
int firstsurface, numsurfaces;
// didn't hit anything
@@ -246,7 +244,6 @@ static qboolean R_RecursiveLightPoint( model_t *model, mnode_t *node, float p1f,
return false;
}
node_children( children, node, model );
firstsurface = node_firstsurface( node, model );
numsurfaces = node_numsurfaces( node, model );
@@ -256,7 +253,7 @@ static qboolean R_RecursiveLightPoint( model_t *model, mnode_t *node, float p1f,
side = front < 0;
if(( back < 0 ) == side )
return R_RecursiveLightPoint( model, children[side], p1f, p2f, cv, start, end );
return R_RecursiveLightPoint( model, node_child( node, side, model ), p1f, p2f, cv, start, end );
frac = front / ( front - back );
@@ -264,7 +261,7 @@ static qboolean R_RecursiveLightPoint( model_t *model, mnode_t *node, float p1f,
midf = p1f + ( p2f - p1f ) * frac;
// co down front side
if( R_RecursiveLightPoint( model, children[side], p1f, midf, cv, start, mid ))
if( R_RecursiveLightPoint( model, node_child( node, side, model ), p1f, midf, cv, start, mid ))
return true; // hit something
if(( back < 0 ) == side )
@@ -366,7 +363,7 @@ static qboolean R_RecursiveLightPoint( model_t *model, mnode_t *node, float p1f,
}
// go down back side
return R_RecursiveLightPoint( model, children[!side], midf, p2f, cv, mid, end );
return R_RecursiveLightPoint( model, node_child( node, !side, model ), midf, p2f, cv, mid, end );
}
/*

View File

@@ -617,7 +617,6 @@ watertexture to grab fog values from it
static gl_texture_t *R_RecursiveFindWaterTexture( const mnode_t *node, const mnode_t *ignore, qboolean down )
{
gl_texture_t *tex = NULL;
mnode_t *children[2];
// assure the initial node is not null
// we could check it here, but we would rather check it
@@ -655,18 +654,20 @@ static gl_texture_t *R_RecursiveFindWaterTexture( const mnode_t *node, const mno
// this is a regular node
// traverse children
node_children( children, node, WORLDMODEL );
mnode_t *child = node_child( node, 0, WORLDMODEL );
if( children[0] && ( children[0] != ignore ))
if( child && ( child != ignore ))
{
tex = R_RecursiveFindWaterTexture( children[0], node, true );
tex = R_RecursiveFindWaterTexture( child, node, true );
if( tex ) return tex;
}
if( children[1] && ( children[1] != ignore ))
child = node_child( node, 1, WORLDMODEL );
if( child && ( child != ignore ))
{
tex = R_RecursiveFindWaterTexture( children[1], node, true );
if( tex ) return tex;
tex = R_RecursiveFindWaterTexture( child, node, true );
if( tex ) return tex;
}
// for down recursion, return immediately

View File

@@ -108,6 +108,8 @@ void R_NewMap( void )
texture_t *tx;
int i;
tr.worldmodel = gp_cl->models[1];
R_ClearDecals(); // clear all level decals
R_StudioResetPlayerModels();

View File

@@ -20,6 +20,7 @@ GNU General Public License for more details.
typedef struct
{
int allocated[BLOCK_SIZE_MAX];
int max_height; // maximum height currently in use in the block
int current_lightmap_texture;
msurface_t *dynamic_surfaces;
msurface_t *lightmap_surfaces[MAX_LIGHTMAPS];
@@ -653,6 +654,7 @@ static void R_SetCacheState( msurface_t *surf )
static void LM_InitBlock( void )
{
memset( gl_lms.allocated, 0, sizeof( gl_lms.allocated ));
gl_lms.max_height = 0;
}
static int LM_AllocBlock( int w, int h, int *x, int *y )
@@ -662,7 +664,7 @@ static int LM_AllocBlock( int w, int h, int *x, int *y )
best = BLOCK_SIZE;
for( i = 0; i < BLOCK_SIZE - w; i++ )
for( i = 0; i < BLOCK_SIZE - w; )
{
best2 = 0;
@@ -679,6 +681,14 @@ static int LM_AllocBlock( int w, int h, int *x, int *y )
// this is a valid spot
*x = i;
*y = best = best2;
if( best == 0 )
break; // height 0 is optimal, can't do better
i++;
}
else
{
// allocated[i+j] was too tall — no position in [i, i+j] can work
i += j + 1;
}
}
@@ -688,20 +698,15 @@ static int LM_AllocBlock( int w, int h, int *x, int *y )
for( i = 0; i < w; i++ )
gl_lms.allocated[*x + i] = best + h;
if( best + h > gl_lms.max_height )
gl_lms.max_height = best + h;
return true;
}
static void LM_UploadDynamicBlock( void )
{
int height = 0, i;
for( i = 0; i < BLOCK_SIZE; i++ )
{
if( gl_lms.allocated[i] > height )
height = gl_lms.allocated[i];
}
pglTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, BLOCK_SIZE, height, GL_RGBA, GL_UNSIGNED_BYTE, gl_lms.lightmap_buffer );
pglTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, BLOCK_SIZE, gl_lms.max_height, GL_RGBA, GL_UNSIGNED_BYTE, gl_lms.lightmap_buffer );
}
static void LM_UploadBlock( qboolean dynamic )
@@ -1290,70 +1295,59 @@ static void R_RenderDecalsForSurface( msurface_t *fa, int cull_type )
static qboolean R_CheckLightMap( msurface_t *fa )
{
qboolean is_dynamic = false;
int maps;
// check for lightmap modification
if( unlikely( !r_dynamic->value ))
return false;
if( fa->dlightframe == tr.framecount )
return true; // dlighted surfaces are always dynamic
// check for light styles
for( maps = 0; maps < MAXLIGHTMAPS && fa->styles[maps] != 255; maps++ )
{
if( tr.lightstylevalue[fa->styles[maps]] != fa->cached_light[maps] )
goto dynamic;
}
if( tr.lightstylevalue[fa->styles[maps]] == fa->cached_light[maps] )
continue;
// dynamic this frame or dynamic previously
if( fa->dlightframe == tr.framecount )
{
dynamic:
// NOTE: at this point we have only valid textures
if( r_dynamic->value )
is_dynamic = true;
}
if( is_dynamic )
{
const int style = fa->styles[maps];
if( maps < MAXLIGHTMAPS && ( style >= 32 || style == 0 || style == 20 ) && fa->dlightframe != tr.framecount )
{
byte temp[132*132*4];
mextrasurf_t *info = fa->info;
int sample_size;
int smax, tmax;
// flickering light styles can go to dynamic chain
if( !( style >= 32 || style == 0 || style == 20 ))
return true;
sample_size = gEngfuncs.Mod_SampleSizeForFace( fa );
smax = ( info->lightextents[0] / sample_size ) + 1;
tmax = ( info->lightextents[1] / sample_size ) + 1;
byte temp[132*132*4];
mextrasurf_t *info = fa->info;
int sample_size = gEngfuncs.Mod_SampleSizeForFace( fa );
int smax = ( info->lightextents[0] / sample_size ) + 1;
int tmax = ( info->lightextents[1] / sample_size ) + 1;
if( smax < 132 && tmax < 132 )
R_BuildLightMap( fa, temp, smax * 4, true );
else
{
smax = Q_min( smax, 132 );
tmax = Q_min( tmax, 132 );
memset( temp, 255, sizeof( temp ));
//Host_MapDesignError( "%s: bad surface extents: %d %d", __func__, fa->extents[0], fa->extents[1] );
}
R_SetCacheState( fa );
#if XASH_WES
GL_Bind( XASH_TEXTURE1, tr.lightmapTextures[fa->lightmaptexturenum] );
pglTexParameteri( GL_TEXTURE_2D, GL_GENERATE_MIPMAP_SGIS, GL_TRUE );
#else
GL_Bind( XASH_TEXTURE0, tr.lightmapTextures[fa->lightmaptexturenum] );
#endif
pglTexSubImage2D( GL_TEXTURE_2D, 0, fa->light_s, fa->light_t, smax, tmax, GL_RGBA, GL_UNSIGNED_BYTE, temp );
#if XASH_WES
GL_SelectTexture( XASH_TEXTURE0 );
#endif
}
if( smax < 132 && tmax < 132 )
R_BuildLightMap( fa, temp, smax * 4, true );
else
return true; // add to dynamic chain
{
smax = Q_min( smax, 132 );
tmax = Q_min( tmax, 132 );
memset( temp, 255, sizeof( temp ));
//Host_MapDesignError( "%s: bad surface extents: %d %d", __func__, fa->extents[0], fa->extents[1] );
}
R_SetCacheState( fa );
#if XASH_WES
GL_Bind( XASH_TEXTURE1, tr.lightmapTextures[fa->lightmaptexturenum] );
pglTexParameteri( GL_TEXTURE_2D, GL_GENERATE_MIPMAP_SGIS, GL_TRUE );
#else
GL_Bind( XASH_TEXTURE0, tr.lightmapTextures[fa->lightmaptexturenum] );
#endif
pglTexSubImage2D( GL_TEXTURE_2D, 0, fa->light_s, fa->light_t, smax, tmax, GL_RGBA, GL_UNSIGNED_BYTE, temp );
#if XASH_WES
GL_SelectTexture( XASH_TEXTURE0 );
#endif
return false;
}
return false; // updated
return false; // no change
}
static void R_RenderLightmapForSurface( msurface_t *fa )
@@ -2091,7 +2085,7 @@ void R_GenerateVBO( void )
if( surf->lightmaptexturenum != k )
continue;
if( surf->flags & ( SURF_DRAWSKY | SURF_DRAWTURB | SURF_CONVEYOR | SURF_DRAWTURB_QUADS ) )
if( surf->flags & ( SURF_DRAWSKY | SURF_DRAWTURB | SURF_CONVEYOR | SURF_DRAWTURB_QUADS | SURF_TRANSPARENT ) )
continue;
if( R_TextureAnimation( surf ) != world->textures[j] )
@@ -2162,7 +2156,7 @@ void R_GenerateVBO( void )
if( surf->lightmaptexturenum != k )
continue;
if( surf->flags & ( SURF_DRAWSKY | SURF_DRAWTURB | SURF_CONVEYOR | SURF_DRAWTURB_QUADS ) )
if( surf->flags & ( SURF_DRAWSKY | SURF_DRAWTURB | SURF_CONVEYOR | SURF_DRAWTURB_QUADS | SURF_TRANSPARENT ) )
continue;
if( R_TextureAnimation( surf ) != world->textures[j] )
@@ -3403,14 +3397,6 @@ R_RecursiveWorldNode
*/
static void R_RecursiveWorldNode( mnode_t *node, uint clipflags )
{
int i, clipped;
msurface_t *surf, **mark;
mleaf_t *pleaf;
int c, side;
float dot;
mnode_t *children[2];
int numsurfaces, firstsurface;
loc0:
if( node->contents == CONTENTS_SOLID )
return; // hit a solid leaf
@@ -3420,14 +3406,14 @@ loc0:
if( clipflags && !r_nocull.value )
{
for( i = 0; i < 6; i++ )
for( int i = 0; i < 6; i++ )
{
const mplane_t *p = &RI.frustum.planes[i];
if( !FBitSet( clipflags, BIT( i )))
continue;
clipped = BOX_ON_PLANE_SIDE( node->minmaxs, node->minmaxs + 3, p );
int clipped = BOX_ON_PLANE_SIDE( node->minmaxs, node->minmaxs + 3, p );
if( clipped == 2 ) return;
if( clipped == 1 ) ClearBits( clipflags, BIT( i ));
}
@@ -3436,19 +3422,11 @@ loc0:
// if a leaf node, draw stuff
if( node->contents < 0 )
{
pleaf = (mleaf_t *)node;
mleaf_t *pleaf = (mleaf_t *)node;
msurface_t **mark = pleaf->firstmarksurface;
mark = pleaf->firstmarksurface;
c = pleaf->nummarksurfaces;
if( c )
{
do
{
(*mark)->visframe = tr.framecount;
mark++;
} while( --c );
}
for( int i = 0; i < pleaf->nummarksurfaces; i++ )
mark[i]->visframe = tr.framecount;
// deal with model fragments in this leaf
if( pleaf->efrags )
@@ -3461,19 +3439,20 @@ loc0:
// node is just a decision point, so go down the apropriate sides
// find which side of the node we are on
dot = PlaneDiff( tr.modelorg, node->plane );
side = (dot >= 0.0f) ? 0 : 1;
float dot = PlaneDiff( tr.modelorg, node->plane );
int side = (dot >= 0.0f) ? 0 : 1;
// recurse down the children, front side first
node_children( children, node, WORLDMODEL );
R_RecursiveWorldNode( children[side], clipflags );
R_RecursiveWorldNode( node_child( node, side, WORLDMODEL ), clipflags );
firstsurface = node_firstsurface( node, WORLDMODEL );
numsurfaces = node_numsurfaces( node, WORLDMODEL );
int firstsurface = node_firstsurface( node, WORLDMODEL );
int numsurfaces = node_numsurfaces( node, WORLDMODEL );
// draw stuff
for( c = numsurfaces, surf = WORLDMODEL->surfaces + firstsurface; c; c--, surf++ )
for( int i = firstsurface; i < firstsurface + numsurfaces; i++ )
{
msurface_t *surf = &WORLDMODEL->surfaces[i];
if( R_CullSurface( surf, &RI.frustum, clipflags ))
continue;
@@ -3491,7 +3470,7 @@ loc0:
}
// recurse down the back side
node = children[!side];
node = node_child( node, !side, WORLDMODEL );
goto loc0;
}
@@ -3567,7 +3546,6 @@ static void R_DrawWorldTopView( mnode_t *node, uint clipflags )
do
{
mnode_t *children[2];
int numsurfaces, firstsurface;
if( node->contents == CONTENTS_SOLID )
@@ -3625,9 +3603,8 @@ static void R_DrawWorldTopView( mnode_t *node, uint clipflags )
}
// recurse down both children, we don't care the order...
node_children( children, node, WORLDMODEL );
R_DrawWorldTopView( children[0], clipflags );
node = children[1];
R_DrawWorldTopView( node_child( node, 0, WORLDMODEL ), clipflags );
node = node_child( node, 1, WORLDMODEL );
} while( node );
}

View File

@@ -559,7 +559,6 @@ static void R_RecursiveWorldNode( mnode_t *node, int clipflags )
}
else
{
mnode_t *children[2];
int firstsurface;
// node is just a decision point, so go down the apropriate sides
@@ -589,8 +588,7 @@ static void R_RecursiveWorldNode( mnode_t *node, int clipflags )
side = 1;
// recurse down the children, front side first
node_children( children, node, WORLDMODEL );
R_RecursiveWorldNode( children[side], clipflags );
R_RecursiveWorldNode( node_child( node, side, WORLDMODEL ), clipflags );
// draw stuff
c = node_numsurfaces( node, WORLDMODEL );
@@ -634,7 +632,7 @@ static void R_RecursiveWorldNode( mnode_t *node, int clipflags )
}
// recurse down the back side
R_RecursiveWorldNode( children[!side], clipflags );
R_RecursiveWorldNode( node_child( node, !side, WORLDMODEL ), clipflags );
}
}

View File

@@ -705,10 +705,7 @@ static void R_DecalNodeSurfaces( model_t *model, mnode_t *node, decalinfo_t *dec
static void R_DecalNode( model_t *model, mnode_t *node, decalinfo_t *decalinfo )
{
mplane_t *splitplane;
float dist;
mnode_t *children[2];
Assert( node != NULL );
float dist;
if( node->contents < 0 )
{
@@ -718,31 +715,22 @@ static void R_DecalNode( model_t *model, mnode_t *node, decalinfo_t *decalinfo )
splitplane = node->plane;
dist = DotProduct( decalinfo->m_Position, splitplane->normal ) - splitplane->dist;
node_children( children, node, model );
// This is arbitrarily set to 10 right now. In an ideal world we'd have the
// exact surface but we don't so, this tells me which planes are "sort of
// close" to the gunshot -- the gunshot is actually 4 units in front of the
// wall (see dlls\weapons.cpp). We also need to check to see if the decal
// actually intersects the texture space of the surface, as this method tags
// parallel surfaces in the same node always.
// JAY: This still tags faces that aren't correct at edges because we don't
// have a surface normal
if( dist > decalinfo->m_Size )
{
R_DecalNode( model, children[0], decalinfo );
R_DecalNode( model, node_child( node, 0, model ), decalinfo );
}
else if( dist < -decalinfo->m_Size )
{
R_DecalNode( model, children[1], decalinfo );
R_DecalNode( model, node_child( node, 1, model ), decalinfo );
}
else
{
if( dist < DECAL_DISTANCE && dist > -DECAL_DISTANCE )
R_DecalNodeSurfaces( model, node, decalinfo );
R_DecalNode( model, children[0], decalinfo );
R_DecalNode( model, children[1], decalinfo );
R_DecalNode( model, node_child( node, 0, model ), decalinfo );
R_DecalNode( model, node_child( node, 1, model ), decalinfo );
}
}

View File

@@ -107,7 +107,6 @@ void R_MarkLights( dlight_t *light, int bit, mnode_t *node )
float dist;
msurface_t *surf;
int i;
mnode_t *children[2];
int firstsurface, numsurfaces;
if( !node || node->contents < 0 )
@@ -115,18 +114,17 @@ void R_MarkLights( dlight_t *light, int bit, mnode_t *node )
dist = PlaneDiff( light->origin, node->plane );
node_children( children, node, RI.currentmodel );
firstsurface = node_firstsurface( node, RI.currentmodel );
numsurfaces = node_numsurfaces( node, RI.currentmodel );
if( dist > light->radius )
{
R_MarkLights( light, bit, children[0] );
R_MarkLights( light, bit, node_child( node, 0, RI.currentmodel ));
return;
}
if( dist < -light->radius )
{
R_MarkLights( light, bit, children[1] );
R_MarkLights( light, bit, node_child( node, 1, RI.currentmodel ));
return;
}
@@ -146,8 +144,8 @@ void R_MarkLights( dlight_t *light, int bit, mnode_t *node )
surf->dlightbits |= bit;
}
R_MarkLights( light, bit, children[0] );
R_MarkLights( light, bit, children[1] );
R_MarkLights( light, bit, node_child( node, 0, RI.currentmodel ));
R_MarkLights( light, bit, node_child( node, 1, RI.currentmodel ));
}
/*
@@ -207,7 +205,6 @@ static qboolean R_RecursiveLightPoint( model_t *model, mnode_t *node, float p1f,
msurface_t *surf;
matrix3x4 tbn;
vec3_t mid;
mnode_t *children[2];
int firstsurface, numsurfaces;
// didn't hit anything
@@ -217,7 +214,6 @@ static qboolean R_RecursiveLightPoint( model_t *model, mnode_t *node, float p1f,
return false;
}
node_children( children, node, model );
firstsurface = node_firstsurface( node, model );
numsurfaces = node_numsurfaces( node, model );
@@ -227,7 +223,7 @@ static qboolean R_RecursiveLightPoint( model_t *model, mnode_t *node, float p1f,
side = front < 0;
if(( back < 0 ) == side )
return R_RecursiveLightPoint( model, children[side], p1f, p2f, cv, start, end );
return R_RecursiveLightPoint( model, node_child( node, side, model ), p1f, p2f, cv, start, end );
frac = front / ( front - back );
@@ -235,7 +231,7 @@ static qboolean R_RecursiveLightPoint( model_t *model, mnode_t *node, float p1f,
midf = p1f + ( p2f - p1f ) * frac;
// co down front side
if( R_RecursiveLightPoint( model, children[side], p1f, midf, cv, start, mid ))
if( R_RecursiveLightPoint( model, node_child( node, side, model ), p1f, midf, cv, start, mid ))
return true; // hit something
if(( back < 0 ) == side )
@@ -337,7 +333,7 @@ static qboolean R_RecursiveLightPoint( model_t *model, mnode_t *node, float p1f,
}
// go down back side
return R_RecursiveLightPoint( model, children[!side], midf, p2f, cv, mid, end );
return R_RecursiveLightPoint( model, node_child( node, !side, model ), midf, p2f, cv, mid, end );
}
/*

View File

@@ -12,7 +12,7 @@ else
git clone --recursive https://github.com/FWGS/hlsdk-portable -b "$1" "$MODPATH"
fi
mkdir ../../build/ios || exit 1
mkdir -p ../../build/ios || exit 1
IOSDIR=$(realpath ../../build/ios)
cd "$MODPATH" || exit 1

View File

@@ -20,7 +20,7 @@ import os
import sys
ANDROID_NDK_ENVVARS = ['ANDROID_NDK_HOME', 'ANDROID_NDK']
ANDROID_NDK_SUPPORTED = [10, 19, 20, 23, 25, 27, 28, 29]
ANDROID_NDK_SUPPORTED = [10, 19, 20, 23, 25, 27, 28, 29, 30]
ANDROID_NDK_HARDFP_MAX = 11 # latest version that supports hardfp
ANDROID_NDK_GCC_MAX = 17 # latest NDK that ships with GCC
ANDROID_NDK_UNIFIED_SYSROOT_MIN = 15
@@ -35,6 +35,7 @@ ANDROID_NDK_API_MIN = {
27: 19,
28: 21,
29: 21,
30: 21,
} # minimal API level ndk revision supports
ANDROID_STPCPY_API_MIN = 21 # stpcpy() introduced in SDK 21