mirror of
https://github.com/FWGS/xash3d-fwgs.git
synced 2026-08-05 11:35:05 +08:00
Compare commits
71 Commits
continuous
...
ffmpeg-8.1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bb734456f6 | ||
|
|
a219ca7371 | ||
|
|
c3b5e43a7a | ||
|
|
e7597d2e84 | ||
|
|
386ca1b9bb | ||
|
|
da3960c4f0 | ||
|
|
cd85762b09 | ||
|
|
d92b3a730c | ||
|
|
ffa53f14e5 | ||
|
|
b8bd906832 | ||
|
|
1c73d8d6f4 | ||
|
|
2c3fdb5eee | ||
|
|
4bbe52e3b4 | ||
|
|
2d241ed96b | ||
|
|
ba4bce06b1 | ||
|
|
f7e933aea1 | ||
|
|
dbcf77c9a9 | ||
|
|
8a9aa2da6c | ||
|
|
0e8143aefc | ||
|
|
4345e9e6a6 | ||
|
|
e7fa45d5ca | ||
|
|
abda0a07c2 | ||
|
|
9d22827395 | ||
|
|
7b665b3763 | ||
|
|
58692f397a | ||
|
|
2253fcc955 | ||
|
|
cbbae0c9bf | ||
|
|
ef513f27ac | ||
|
|
e8ae48fd3d | ||
|
|
434e508186 | ||
|
|
4a2b3e89b4 | ||
|
|
6c3f8c7ec5 | ||
|
|
3fffe061d5 | ||
|
|
729c985eaf | ||
|
|
75fb6c5f34 | ||
|
|
8bc9b1865a | ||
|
|
d6993c47d6 | ||
|
|
b8792e4084 | ||
|
|
2234dd48bc | ||
|
|
c8693e1e89 | ||
|
|
3ace4a61d2 | ||
|
|
bd3f865cf7 | ||
|
|
b68e71abfd | ||
|
|
6179bef160 | ||
|
|
983427ebb3 | ||
|
|
1b2ab34745 | ||
|
|
2713f03ec2 | ||
|
|
238083c174 | ||
|
|
78de3ee6d9 | ||
|
|
695081e079 | ||
|
|
2c5e2e1ded | ||
|
|
d151c48d1f | ||
|
|
35998bce81 | ||
|
|
a10520ca9e | ||
|
|
cb4a03ded2 | ||
|
|
31a0d17de5 | ||
|
|
5f765a35b9 | ||
|
|
5606346cc1 | ||
|
|
6faee8fd89 | ||
|
|
255c9bcaed | ||
|
|
25a3fdbcec | ||
|
|
8e450d869b | ||
|
|
e8ef7ad60c | ||
|
|
216eedcdcd | ||
|
|
fd55716633 | ||
|
|
0b920be381 | ||
|
|
e6dfccb6ba | ||
|
|
3129081050 | ||
|
|
00dac928c9 | ||
|
|
3726256514 | ||
|
|
5eb43505cb |
2
.github/workflows/c-cpp.yml
vendored
2
.github/workflows/c-cpp.yml
vendored
@@ -69,7 +69,7 @@ jobs:
|
||||
targetarch: amd64
|
||||
env:
|
||||
SDL_VERSION: 2.32.10
|
||||
FFMPEG_VERSION: 7.1
|
||||
FFMPEG_VERSION: 8.1
|
||||
GH_CPU_ARCH: ${{ matrix.targetarch }}
|
||||
GH_CPU_OS: ${{ matrix.targetos }}
|
||||
GH_CROSSCOMPILING: ${{ matrix.cross }}
|
||||
|
||||
2
3rdparty/library_suffix
vendored
2
3rdparty/library_suffix
vendored
Submodule 3rdparty/library_suffix updated: 5b670f638b...6e14ae31e8
2
3rdparty/mainui
vendored
2
3rdparty/mainui
vendored
Submodule 3rdparty/mainui updated: e198199f6c...af2b5abdde
@@ -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
|
||||
}
|
||||
|
||||
|
||||
185
common/sound_api.h
Normal file
185
common/sound_api.h
Normal file
@@ -0,0 +1,185 @@
|
||||
/*
|
||||
sound_api.h - Xash3D extension for client sound interface
|
||||
Copyright (C) 2026 Xash3D FWGS Developers
|
||||
|
||||
This is free and unencumbered software released into the public domain.
|
||||
|
||||
Anyone is free to copy, modify, publish, use, compile, sell, or
|
||||
distribute this software, either in source code form or as a compiled
|
||||
binary, for any purpose, commercial or non-commercial, and by any
|
||||
means.
|
||||
|
||||
In jurisdictions that recognize copyright laws, the author or authors
|
||||
of this software dedicate any and all copyright interest in the
|
||||
software to the public domain. We make this dedication for the benefit
|
||||
of the public at large and to the detriment of our heirs and
|
||||
successors. We intend this dedication to be an overt act of
|
||||
relinquishment in perpetuity of all present and future rights to this
|
||||
software under copyright law.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
For more information, please refer to <http://unlicense.org/>
|
||||
*/
|
||||
|
||||
#ifndef SOUND_API_H
|
||||
#define SOUND_API_H
|
||||
|
||||
#include "xash3d_types.h"
|
||||
|
||||
// Experimental implementation, backward compatibility is not guaranteed.
|
||||
#define CL_SOUND_INTERFACE_VERSION 1
|
||||
|
||||
#define FL_VOXWORD_IN_CACHE BIT( 0 ) // if set, it was loaded prior and shouldn't be freed
|
||||
|
||||
#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 int sound_t;
|
||||
|
||||
typedef struct portable_samplepair_s
|
||||
{
|
||||
int left;
|
||||
int right;
|
||||
} portable_samplepair_t;
|
||||
|
||||
typedef struct sfx_s
|
||||
{
|
||||
char name[MAX_QPATH];
|
||||
wavdata_t *cache;
|
||||
|
||||
int servercount;
|
||||
uint hashValue;
|
||||
struct sfx_s *hashNext;
|
||||
} sfx_t;
|
||||
|
||||
typedef struct voxword_s
|
||||
{
|
||||
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 channel_s
|
||||
{
|
||||
char name[16]; // keep sentence name
|
||||
sfx_t *sfx; // sfx number
|
||||
|
||||
vec3_t origin; // only use if fixed_origin is set
|
||||
float dist_mult; // distance multiplier (attenuation/clipK)
|
||||
|
||||
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 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
|
||||
float inauduble_free_time;
|
||||
|
||||
double sample;
|
||||
double forced_end;
|
||||
wavdata_t *data;
|
||||
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 rawchan_s
|
||||
{
|
||||
short entnum;
|
||||
short master_vol;
|
||||
short leftvol; // 0-255 left volume
|
||||
short rightvol; // 0-255 right volume
|
||||
float dist_mult; // distance multiplier (attenuation/clipK)
|
||||
vec3_t origin; // only use if fixed_origin is set
|
||||
volatile uint s_rawend;
|
||||
float oldtime; // catch time jumps
|
||||
|
||||
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;
|
||||
|
||||
typedef struct snd_format_s
|
||||
{
|
||||
uint speed;
|
||||
byte width;
|
||||
byte channels;
|
||||
} snd_format_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;
|
||||
|
||||
// API from engine to client (client calls these)
|
||||
typedef struct sound_api_s
|
||||
{
|
||||
qboolean (*CL_GetEntitySpatialization)( channel_t *ch );
|
||||
sfx_t* (*S_GetSfxByHandle)( sound_t handle );
|
||||
} sound_api_t;
|
||||
|
||||
// Callbacks from client to engine (engine calls these when custom sound is active)
|
||||
typedef struct sound_interface_s
|
||||
{
|
||||
int version;
|
||||
|
||||
qboolean (*pfnS_Init)( snd_globals_t *globals );
|
||||
void (*pfnS_Shutdown)( void );
|
||||
void (*pfnS_UpdateSound)( void );
|
||||
/* Full paint: endtime (sample pairs), dma buffer, paintedtime in/out. Client does mix + transfer to dma.buffer. */
|
||||
void (*pfnS_PaintChannels)( int endtime );
|
||||
void (*pfnS_UpdateChannel)( int ch_idx, const channel_t *ch, sound_t handle ); // ch=NULL -> channel freed
|
||||
void (*pfnS_UpdateRawChannel)( int raw_idx, rawchan_t *ch ); // ch=NULL -> channel freed
|
||||
void (*pfnS_Spatialize)( channel_t *ch );
|
||||
void (*pfnS_FreeSound)( sfx_t *sfx, sound_t handle );
|
||||
} sound_interface_t;
|
||||
|
||||
#endif // SOUND_API_H
|
||||
@@ -23,6 +23,12 @@ struct mstudioevent_s;
|
||||
struct engine_studio_api_s;
|
||||
struct r_studio_interface_s;
|
||||
|
||||
struct sound_api_s;
|
||||
struct sound_interface_s;
|
||||
|
||||
typedef struct sound_api_s sound_api_t;
|
||||
typedef struct sound_interface_s sound_interface_t;
|
||||
|
||||
// NOTE: ordering is important!
|
||||
typedef struct cldll_func_s
|
||||
{
|
||||
@@ -74,6 +80,8 @@ typedef struct cldll_func_s
|
||||
int (*pfnTouchEvent)( int type, int fingerID, float x, float y, float dx, float dy );
|
||||
void (*pfnMoveEvent)( float forwardmove, float sidemove );
|
||||
void (*pfnLookEvent)( float relyaw, float relpitch );
|
||||
// Sound API
|
||||
int (*pfnGetSoundInterface)( int version, const sound_api_t *api, sound_interface_t *callback );
|
||||
} cldll_func_t;
|
||||
|
||||
#endif//CDLL_EXP_H
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -26,16 +26,82 @@ GNU General Public License for more details.
|
||||
|
||||
#if XASH_FFMPEG_DLOPEN
|
||||
|
||||
// using typeof gives more resilience to function declaration changes
|
||||
// but it's only available in GCC and standardized in C23
|
||||
#if defined(__GNUC__) || __STDC_VERSION__ >= 202311L
|
||||
|
||||
#define SUPPORTED_AVU_VERSION_MAJOR LIBAVUTIL_VERSION_MAJOR
|
||||
#define SUPPORTED_AVF_VERSION_MAJOR LIBAVFORMAT_VERSION_MAJOR
|
||||
#define SUPPORTED_AVC_VERSION_MAJOR LIBAVCODEC_VERSION_MAJOR
|
||||
#define SUPPORTED_SWR_VERSION_MAJOR LIBSWRESAMPLE_VERSION_MAJOR
|
||||
#define SUPPORTED_SWS_VERSION_MAJOR LIBSWSCALE_VERSION_MAJOR
|
||||
|
||||
#define F( func ) \
|
||||
typedef typeof( func ) func##_t; \
|
||||
func##_t *p##func
|
||||
|
||||
// libavutil
|
||||
F( avutil_version );
|
||||
F( av_frame_alloc );
|
||||
F( av_frame_free );
|
||||
F( av_frame_ref );
|
||||
F( av_frame_unref );
|
||||
F( av_strerror );
|
||||
F( av_free );
|
||||
F( av_get_bytes_per_sample );
|
||||
F( av_get_media_type_string );
|
||||
F( av_image_alloc );
|
||||
|
||||
// libavformat
|
||||
F( avformat_version );
|
||||
F( av_find_best_stream );
|
||||
F( av_read_frame );
|
||||
F( av_seek_frame );
|
||||
F( avformat_close_input );
|
||||
F( avformat_find_stream_info );
|
||||
F( avformat_open_input );
|
||||
|
||||
// libavcodec
|
||||
F( avcodec_version );
|
||||
F( av_packet_alloc );
|
||||
F( av_packet_free );
|
||||
F( av_packet_unref );
|
||||
F( avcodec_alloc_context3 );
|
||||
F( avcodec_find_decoder );
|
||||
F( avcodec_flush_buffers );
|
||||
F( avcodec_free_context );
|
||||
F( avcodec_open2 );
|
||||
F( avcodec_parameters_to_context );
|
||||
F( avcodec_receive_frame );
|
||||
F( avcodec_send_packet );
|
||||
|
||||
// libswresample
|
||||
F( swresample_version );
|
||||
F( swr_alloc_set_opts2 );
|
||||
F( swr_convert );
|
||||
F( swr_free );
|
||||
F( swr_init );
|
||||
|
||||
// libswscale
|
||||
F( swscale_version );
|
||||
F( sws_freeContext );
|
||||
F( sws_getContext );
|
||||
F( sws_scale );
|
||||
|
||||
#undef F
|
||||
|
||||
#else // !defined(__GNUC__) && __STDC_VERSION__ < 202311L
|
||||
|
||||
// the following symbols were taken from ffmpeg public headers
|
||||
// on each major ffmpeg uprgade, they must be validated
|
||||
// ffmpeg guarantees API and ABI compatibility between major versions
|
||||
// so complain if this gets compiled against unsupported yet version
|
||||
// the same check will be done in runtime to ensure compatibility
|
||||
#define SUPPORTED_AVU_VERSION_MAJOR 59
|
||||
#define SUPPORTED_AVF_VERSION_MAJOR 61
|
||||
#define SUPPORTED_AVC_VERSION_MAJOR 61
|
||||
#define SUPPORTED_SWR_VERSION_MAJOR 5
|
||||
#define SUPPORTED_SWS_VERSION_MAJOR 8
|
||||
#define SUPPORTED_AVU_VERSION_MAJOR 60
|
||||
#define SUPPORTED_AVF_VERSION_MAJOR 62
|
||||
#define SUPPORTED_AVC_VERSION_MAJOR 62
|
||||
#define SUPPORTED_SWR_VERSION_MAJOR 6
|
||||
#define SUPPORTED_SWS_VERSION_MAJOR 9
|
||||
|
||||
#if SUPPORTED_AVU_VERSION_MAJOR != LIBAVUTIL_VERSION_MAJOR
|
||||
#error "unsupported libavutil version"
|
||||
@@ -105,6 +171,8 @@ void (*psws_freeContext)( struct SwsContext *swsContext );
|
||||
struct SwsContext *(*psws_getContext)( int srcW, int srcH, enum AVPixelFormat srcFormat, int dstW, int dstH, enum AVPixelFormat dstFormat, int flags, SwsFilter *srcFilter, SwsFilter *dstFilter, const double *param );
|
||||
int (*psws_scale)( struct SwsContext *c, const uint8_t *const srcSlice[], const int srcStride[], int srcSliceY, int srcSliceH, uint8_t *const dst[], const int dstStride[] );
|
||||
|
||||
#endif // defined(__GNUC__) || __STDC_VERSION__ >= 202311L
|
||||
|
||||
#else // !XASH_FFMPEG_DLOPEN
|
||||
|
||||
#define SUPPORTED_AVU_VERSION_MAJOR LIBAVUTIL_VERSION_MAJOR
|
||||
|
||||
@@ -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 )
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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[] =
|
||||
{
|
||||
@@ -96,6 +105,7 @@ static const dllfunc_t cdll_new_exports[] = // allowed only in SDK 2.3 and high
|
||||
{ "IN_ClientTouchEvent", (void **)&clgame.dllFuncs.pfnTouchEvent}, // Xash3D FWGS ext
|
||||
{ "IN_ClientMoveEvent", (void **)&clgame.dllFuncs.pfnMoveEvent}, // Xash3D FWGS ext
|
||||
{ "IN_ClientLookEvent", (void **)&clgame.dllFuncs.pfnLookEvent}, // Xash3D FWGS ext
|
||||
{ "HUD_GetSoundInterface", (void **)&clgame.dllFuncs.pfnGetSoundInterface }, // Xash3D ext
|
||||
};
|
||||
|
||||
static void pfnSPR_DrawHoles( int frame, int x, int y, const wrect_t *prc );
|
||||
@@ -179,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] ),
|
||||
@@ -560,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 );
|
||||
}
|
||||
|
||||
@@ -653,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
|
||||
@@ -1974,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;
|
||||
}
|
||||
|
||||
@@ -4095,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
|
||||
|
||||
@@ -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 ));
|
||||
@@ -3678,8 +3678,6 @@ void CL_Init( void )
|
||||
CL_InitLocal();
|
||||
|
||||
VID_Init(); // init video
|
||||
S_Init(); // init sound
|
||||
Voice_Init( VOICE_DEFAULT_CODEC, 3, true ); // init voice (do not open the device)
|
||||
|
||||
// unreliable buffer. unsed for unreliable commands and voice stream
|
||||
MSG_Init( &cls.datagram, "cls.datagram", cls.datagram_buf, sizeof( cls.datagram_buf ));
|
||||
@@ -3689,6 +3687,9 @@ void CL_Init( void )
|
||||
if( !CL_LoadProgs( libpath ))
|
||||
Host_Error( "can't initialize %s: %s\n", libpath, COM_GetLibraryError( ));
|
||||
|
||||
S_Init(); // init sound
|
||||
Voice_Init( VOICE_DEFAULT_CODEC, 3, true ); // init voice (do not open the device)
|
||||
|
||||
ID_Init();
|
||||
SteamBroker_Init();
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -213,6 +213,7 @@ static void CL_ParseQuakeServerInfo( sizebuf_t *msg )
|
||||
clgame.maxEntities = bound( 600, clgame.maxEntities, MAX_EDICTS );
|
||||
clgame.maxModels = MAX_MODELS;
|
||||
Q_strncpy( clgame.maptitle, MSG_ReadString( msg ), sizeof( clgame.maptitle ));
|
||||
Host_ValidateEngineFeatures( ENGINE_FEATURES_MASK, ENGINE_QUAKE_COMPATIBLE );
|
||||
|
||||
// Re-init hud video, especially if we changed game directories
|
||||
clgame.dllFuncs.pfnVidInit();
|
||||
@@ -929,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;
|
||||
@@ -946,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;
|
||||
@@ -973,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 ));
|
||||
@@ -1028,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
|
||||
@@ -1040,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
|
||||
@@ -1058,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;
|
||||
|
||||
@@ -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 )
|
||||
|
||||
@@ -535,6 +535,7 @@ void V_PostRender( void )
|
||||
SCR_DrawEnts();
|
||||
SCR_DrawNetGraph();
|
||||
SCR_DrawUserCmd();
|
||||
Joy_DrawDebug();
|
||||
SV_DrawOrthoTriangles();
|
||||
CL_DrawDemoRecording();
|
||||
CL_DrawHUD( CL_CHANGELEVEL );
|
||||
|
||||
@@ -26,6 +26,7 @@ GNU General Public License for more details.
|
||||
#include "pm_defs.h"
|
||||
#include "ref_params.h"
|
||||
#include "render_api.h"
|
||||
#include "sound_api.h"
|
||||
#include "cdll_exp.h"
|
||||
#include "screenfade.h"
|
||||
#include "protocol.h"
|
||||
@@ -36,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
|
||||
{
|
||||
@@ -111,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.
|
||||
|
||||
@@ -310,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];
|
||||
@@ -449,6 +455,7 @@ typedef struct
|
||||
void *hInstance; // pointer to client.dll
|
||||
cldll_func_t dllFuncs; // dll exported funcs
|
||||
render_interface_t drawFuncs; // custom renderer support
|
||||
sound_interface_t soundFuncs; // custom sound support
|
||||
poolhandle_t mempool; // client edicts pool
|
||||
string mapname; // map name
|
||||
string maptitle; // display map title
|
||||
@@ -731,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];
|
||||
|
||||
//=================================================
|
||||
|
||||
@@ -853,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 );
|
||||
@@ -923,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 );
|
||||
|
||||
@@ -1083,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 );
|
||||
|
||||
@@ -1573,7 +1573,7 @@ void Key_Console( int key )
|
||||
}
|
||||
|
||||
// command completion
|
||||
if( key == K_TAB || key == K_L2_BUTTON )
|
||||
if( key == K_TAB || key == K_L2_BUTTON || key == K_LTRIGGER )
|
||||
{
|
||||
Con_CompleteCommand( &con.input, true );
|
||||
Con_Bottom();
|
||||
|
||||
@@ -24,8 +24,6 @@ GNU General Public License for more details.
|
||||
#define SHRT_MAX 0x7FFF
|
||||
#endif
|
||||
|
||||
#define MAX_AXES JOY_AXIS_NULL
|
||||
|
||||
// index - axis num come from event
|
||||
// value - inner axis
|
||||
static engineAxis_t joyaxesmap[MAX_AXES] =
|
||||
@@ -42,7 +40,9 @@ static struct joy_axis_s
|
||||
{
|
||||
short val;
|
||||
short prevval;
|
||||
short rawval; // value before deadzone zeroing, for debug display
|
||||
} joyaxis[MAX_AXES] = { 0 };
|
||||
|
||||
static qboolean joy_initialized;
|
||||
|
||||
static CVAR_DEFINE_AUTO( joy_pitch, "100.0", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "joystick pitch sensitivity" );
|
||||
@@ -62,6 +62,15 @@ static CVAR_DEFINE_AUTO( joy_axis_binding, "sfpyrl", FCVAR_ARCHIVE | FCVAR_FILTE
|
||||
CVAR_DEFINE_AUTO( joy_enable, "1", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "enable joystick" );
|
||||
static CVAR_DEFINE_AUTO( joy_have_gyro, "0", FCVAR_READ_ONLY, "tells whether current active gamepad has gyroscope or not" );
|
||||
static CVAR_DEFINE_AUTO( joy_calibrated, "0", FCVAR_READ_ONLY, "tells whether current active gamepad gyroscope has been calibrated or not" );
|
||||
static CVAR_DEFINE_AUTO( joy_gyro_pitch, "1.0", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "gyroscope sensitivity for looking up and down" );
|
||||
static CVAR_DEFINE_AUTO( joy_gyro_yaw, "1.0", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "gyroscope sensitivity for turning left and right" );
|
||||
static CVAR_DEFINE_AUTO( joy_gyro_roll, "0.0", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "gyroscope sensitivity when tilting the device sideways" );
|
||||
static CVAR_DEFINE_AUTO( joy_debug, "0", 0, "visualize gamepad axes and buttons" );
|
||||
|
||||
// stores the latest instantaneous gyroscope rotation rates (in rad/s) from platform input
|
||||
static vec3_t joy_gyro_speed;
|
||||
// last non-zero gyro speed, retained for debug display after joy_gyro_speed is cleared
|
||||
static vec3_t joy_gyro_speed_display;
|
||||
|
||||
/*
|
||||
============
|
||||
@@ -228,6 +237,8 @@ static void Joy_ProcessStick( const engineAxis_t engineAxis, short value )
|
||||
break;
|
||||
}
|
||||
|
||||
joyaxis[engineAxis].rawval = value;
|
||||
|
||||
if( value < deadzone && value > -deadzone )
|
||||
value = 0; // caught new event in deadzone, fill it with zero(no motion)
|
||||
|
||||
@@ -257,7 +268,12 @@ Axis events
|
||||
*/
|
||||
void Joy_AxisMotionEvent( engineAxis_t engineAxis, short value )
|
||||
{
|
||||
if( engineAxis >= JOY_AXIS_NULL )
|
||||
if( engineAxis >= MAX_AXES )
|
||||
return;
|
||||
|
||||
engineAxis = joyaxesmap[engineAxis];
|
||||
|
||||
if( engineAxis >= MAX_AXES )
|
||||
return;
|
||||
|
||||
if( value == joyaxis[engineAxis].val )
|
||||
@@ -278,7 +294,8 @@ Gyroscope events
|
||||
*/
|
||||
void Joy_GyroEvent( vec3_t data )
|
||||
{
|
||||
|
||||
VectorCopy( data, joy_gyro_speed );
|
||||
VectorCopy( data, joy_gyro_speed_display );
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -290,7 +307,7 @@ Append movement from axis. Called everyframe
|
||||
*/
|
||||
void Joy_FinalizeMove( float *fw, float *side, float *dpitch, float *dyaw )
|
||||
{
|
||||
if( !Joy_IsActive() )
|
||||
if( !Joy_IsActive( ))
|
||||
return;
|
||||
|
||||
if( FBitSet( joy_axis_binding.flags, FCVAR_CHANGED ) )
|
||||
@@ -308,7 +325,7 @@ void Joy_FinalizeMove( float *fw, float *side, float *dpitch, float *dyaw )
|
||||
case 'p': joyaxesmap[i] = JOY_AXIS_PITCH; break;
|
||||
case 'r': joyaxesmap[i] = JOY_AXIS_RT; break;
|
||||
case 'l': joyaxesmap[i] = JOY_AXIS_LT; break;
|
||||
default : joyaxesmap[i] = JOY_AXIS_NULL; break;
|
||||
default : joyaxesmap[i] = MAX_AXES; break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -317,8 +334,193 @@ void Joy_FinalizeMove( float *fw, float *side, float *dpitch, float *dyaw )
|
||||
|
||||
*fw -= joy_forward.value * (float)joyaxis[JOY_AXIS_FWD ].val/(float)SHRT_MAX; // must be form -1.0 to 1.0
|
||||
*side += joy_side.value * (float)joyaxis[JOY_AXIS_SIDE].val/(float)SHRT_MAX;
|
||||
*dpitch -= joy_pitch.value * (float)joyaxis[JOY_AXIS_PITCH].val/(float)SHRT_MAX * host.realframetime;
|
||||
*dyaw += joy_yaw.value * (float)joyaxis[JOY_AXIS_YAW ].val/(float)SHRT_MAX * host.realframetime;
|
||||
*dpitch += joy_pitch.value * (float)joyaxis[JOY_AXIS_PITCH].val/(float)SHRT_MAX * host.realframetime;
|
||||
*dyaw -= joy_yaw.value * (float)joyaxis[JOY_AXIS_YAW ].val/(float)SHRT_MAX * host.realframetime;
|
||||
|
||||
if( joy_have_gyro.value && (int)joy_calibrated.value == JOY_CALIBRATED )
|
||||
{
|
||||
float pitch_speed = joy_gyro_speed[0] * ( 180.0f / M_PI );
|
||||
float yaw_speed = joy_gyro_speed[1] * ( 180.0f / M_PI );
|
||||
float roll_speed = joy_gyro_speed[2] * ( 180.0f / M_PI );
|
||||
|
||||
*dpitch -= joy_gyro_pitch.value * pitch_speed * host.realframetime;
|
||||
*dyaw += joy_gyro_yaw.value * yaw_speed * host.realframetime;
|
||||
*dyaw += joy_gyro_roll.value * roll_speed * host.realframetime;
|
||||
}
|
||||
|
||||
VectorClear( joy_gyro_speed );
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
Joy_DrawDebug
|
||||
|
||||
Draw gamepad axes and buttons for debugging (joy_debug 1)
|
||||
=============
|
||||
*/
|
||||
void Joy_DrawDebug( void )
|
||||
{
|
||||
static const int buttons[] =
|
||||
{
|
||||
K_A_BUTTON, K_B_BUTTON, K_X_BUTTON, K_Y_BUTTON, 0,
|
||||
K_L1_BUTTON, K_R1_BUTTON, 0,
|
||||
K_L2_BUTTON, K_R2_BUTTON, 0,
|
||||
K_BACK_BUTTON, K_MODE_BUTTON, K_START_BUTTON, 0,
|
||||
K_LSTICK, K_RSTICK, 0,
|
||||
|
||||
// simulated buttons
|
||||
K_DPAD_UP, K_DPAD_DOWN, K_DPAD_LEFT, K_DPAD_RIGHT, 0,
|
||||
K_LTRIGGER, K_RTRIGGER, 0,
|
||||
|
||||
// additional buttons
|
||||
K_C_BUTTON, K_Z_BUTTON, K_MISC_BUTTON, 0,
|
||||
K_PADDLE1_BUTTON, K_PADDLE2_BUTTON, K_PADDLE3_BUTTON, K_PADDLE4_BUTTON, 0
|
||||
};
|
||||
static const char *const axisnames[MAX_AXES] = { "SIDE", "FWD", "PITCH", "YAW", "RT", "LT" };
|
||||
|
||||
// deadzone for sticks, threshold for triggers
|
||||
static const convar_t *const axis_threshold[MAX_AXES] =
|
||||
{
|
||||
&joy_side_deadzone,
|
||||
&joy_forward_deadzone,
|
||||
&joy_pitch_deadzone,
|
||||
&joy_yaw_deadzone,
|
||||
&joy_rt_threshold,
|
||||
&joy_lt_threshold,
|
||||
};
|
||||
|
||||
cl_font_t *font = Con_GetCurFont();
|
||||
|
||||
if( !joy_debug.value || !Joy_IsActive( ))
|
||||
return;
|
||||
|
||||
float x = 8;
|
||||
float y = 100;
|
||||
const float bar_w = 100;
|
||||
const float halfbar_w = bar_w * 0.5f;
|
||||
const float bar_h = font->charHeight - 2;
|
||||
const float center = x + halfbar_w;
|
||||
|
||||
const rgba_t bar_backcolor = { 40, 40, 40, 180 };
|
||||
const rgba_t bar_fillcolor = { 100, 200, 100, 200 };
|
||||
|
||||
// draw axes as labeled bars
|
||||
for( int i = 0; i < MAX_AXES; i++ )
|
||||
{
|
||||
|
||||
qboolean is_trigger = ( i >= JOY_AXIS_RT );
|
||||
float fval = (float)joyaxis[i].val / SHRT_MAX;
|
||||
float fprev = (float)joyaxis[i].prevval / SHRT_MAX;
|
||||
float fthreshold = axis_threshold[i]->value / SHRT_MAX;
|
||||
|
||||
CL_DrawString( x, y, axisnames[i], g_color_table[7], font, 0 );
|
||||
y += font->charHeight;
|
||||
|
||||
// background
|
||||
ref.dllFuncs.FillRGBA( kRenderTransTexture, x, y, bar_w, bar_h, bar_backcolor[0], bar_backcolor[1], bar_backcolor[2], bar_backcolor[3] );
|
||||
|
||||
if( is_trigger )
|
||||
{
|
||||
// fill bar from the left for triggers
|
||||
float filled = fval * bar_w;
|
||||
|
||||
if( filled > 0 )
|
||||
ref.dllFuncs.FillRGBA( kRenderTransTexture, x, y, filled, bar_h, bar_fillcolor[0], bar_fillcolor[1], bar_fillcolor[2], bar_fillcolor[3] );
|
||||
|
||||
// fill threshold with red, and yellow edge marker
|
||||
float thresh_x = x + fthreshold * bar_w;
|
||||
ref.dllFuncs.FillRGBA( kRenderTransTexture, x, y, thresh_x - x, bar_h, 180, 40, 40, 120 );
|
||||
ref.dllFuncs.FillRGBA( kRenderTransTexture, thresh_x, y, 1, bar_h, 255, 200, 0, 220 );
|
||||
|
||||
// prevval marker
|
||||
float prev_x = x + fprev * bar_w;
|
||||
ref.dllFuncs.FillRGBA( kRenderTransTexture, prev_x, y, 1, bar_h, 200, 200, 200, 180 );
|
||||
}
|
||||
else
|
||||
{
|
||||
// for sticks bar is filled from the center
|
||||
float filled = fval * halfbar_w;
|
||||
ref.dllFuncs.FillRGBA( kRenderTransTexture, center + Q_min( 0, filled ), y, fabs( filled ), bar_h, bar_fillcolor[0], bar_fillcolor[1], bar_fillcolor[2], bar_fillcolor[3] );
|
||||
|
||||
// fill deadzone with red, and yellow edge marker
|
||||
float thresh_x = fthreshold * halfbar_w;
|
||||
ref.dllFuncs.FillRGBA( kRenderTransTexture, center - thresh_x, y, thresh_x * 2, bar_h, 180, 40, 40, 120 );
|
||||
ref.dllFuncs.FillRGBA( kRenderTransTexture, center + thresh_x, y, 1, bar_h, 255, 200, 0, 220 );
|
||||
ref.dllFuncs.FillRGBA( kRenderTransTexture, center - thresh_x, y, 1, bar_h, 255, 200, 0, 220 );
|
||||
|
||||
// mark the center
|
||||
ref.dllFuncs.FillRGBA( kRenderTransTexture, center, y, 1, bar_h, 180, 180, 180, 220 );
|
||||
|
||||
// now draw the actual value
|
||||
float raw_x = center + ((float)joyaxis[i].rawval / SHRT_MAX * halfbar_w );
|
||||
ref.dllFuncs.FillRGBA( kRenderTransTexture, raw_x, y, 1, bar_h, 255, 255, 100, 200 );
|
||||
|
||||
// prevval marker
|
||||
float prev_x = center + fprev * halfbar_w;
|
||||
ref.dllFuncs.FillRGBA( kRenderTransTexture, prev_x, y, 1, bar_h, 200, 200, 200, 180 );
|
||||
}
|
||||
|
||||
y += bar_h + 2;
|
||||
}
|
||||
|
||||
// draw gyro if available
|
||||
if( joy_have_gyro.value )
|
||||
{
|
||||
static const char *gyronames[3] = { "GYRO P", "GYRO Y", "GYRO R" };
|
||||
|
||||
for( int i = 0; i < 3; i++ )
|
||||
{
|
||||
// clamp to +-5 rad/s for display
|
||||
float fval = joy_gyro_speed_display[i] / 5.0f;
|
||||
|
||||
fval = bound( -1.0f, fval, 1.0f );
|
||||
|
||||
CL_DrawString( x, y, gyronames[i], g_color_table[7], font, 0 );
|
||||
y += font->charHeight;
|
||||
|
||||
// background
|
||||
ref.dllFuncs.FillRGBA( kRenderTransTexture, x, y, bar_w, bar_h, bar_backcolor[0], bar_backcolor[1], bar_backcolor[2], bar_backcolor[3] );
|
||||
|
||||
// for gyro bar is filled from the center
|
||||
float filled = fval * halfbar_w;
|
||||
ref.dllFuncs.FillRGBA( kRenderTransTexture, center + Q_min( 0, filled ), y, fabs( filled ), bar_h, bar_fillcolor[0], bar_fillcolor[1], bar_fillcolor[2], bar_fillcolor[3] );
|
||||
|
||||
// mark the center
|
||||
ref.dllFuncs.FillRGBA( kRenderTransTexture, center, y, 1, bar_h, 180, 180, 180, 220 );
|
||||
|
||||
// gyro doesn't have deadzones or prevval like axes
|
||||
y += bar_h + 2;
|
||||
}
|
||||
}
|
||||
|
||||
// draw buttons in a row
|
||||
y += 4;
|
||||
x = 8;
|
||||
for( int i = 0; i < ARRAYSIZE( buttons ); i++ )
|
||||
{
|
||||
if( !buttons[i] )
|
||||
{
|
||||
x = 8;
|
||||
y += font->charHeight;
|
||||
continue;
|
||||
}
|
||||
|
||||
qboolean pressed = Key_IsDown( buttons[i] );
|
||||
int btn_w = 0;
|
||||
rgba_t color;
|
||||
string name;
|
||||
|
||||
Q_strncpy( name, Key_KeynumToString( buttons[i] ), sizeof( name ));
|
||||
|
||||
char *p = Q_strstr( name, "_BUTTON" );
|
||||
if( p )
|
||||
*p = 0;
|
||||
|
||||
MakeRGBA( color, pressed ? 0 : 255, pressed ? 255 : 0, 0, 255 );
|
||||
CL_DrawString( x, y, name, color, font, 0 );
|
||||
CL_DrawStringLen( font, name, &btn_w, NULL, 0 );
|
||||
x += btn_w + 6;
|
||||
}
|
||||
}
|
||||
|
||||
static void Joy_CalibrateGyro_f( void )
|
||||
@@ -367,6 +569,11 @@ void Joy_Init( void )
|
||||
Cvar_RegisterVariable( &joy_calibrated );
|
||||
Cvar_RegisterVariable( &joy_enable );
|
||||
|
||||
Cvar_RegisterVariable( &joy_gyro_pitch );
|
||||
Cvar_RegisterVariable( &joy_gyro_yaw );
|
||||
Cvar_RegisterVariable( &joy_gyro_roll );
|
||||
Cvar_RegisterVariable( &joy_debug );
|
||||
|
||||
// renamed from -nojoy to -noenginejoy to not conflict with
|
||||
// client.dll's joystick support
|
||||
if( Sys_CheckParm( "-noenginejoy" ))
|
||||
|
||||
@@ -2189,12 +2189,12 @@ int IN_TouchEvent( touchEventType type, int fingerID, float x, float y, float dx
|
||||
return Touch_ControlsEvent( type, fingerID, x, y, dx, dy );
|
||||
}
|
||||
|
||||
void Touch_GetMove( float *forward, float *side, float *yaw, float *pitch )
|
||||
void Touch_GetMove( float *forward, float *side, float *pitch, float *yaw )
|
||||
{
|
||||
*forward += touch.forward;
|
||||
*side += touch.side;
|
||||
*yaw += touch.yaw;
|
||||
*pitch += touch.pitch;
|
||||
*yaw += touch.yaw;
|
||||
touch.yaw = touch.pitch = 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -560,8 +560,8 @@ static void IN_CollectInput( float *forward, float *side, float *pitch, float *y
|
||||
#endif
|
||||
}
|
||||
|
||||
Joy_FinalizeMove( forward, side, yaw, pitch );
|
||||
Touch_GetMove( forward, side, yaw, pitch );
|
||||
Joy_FinalizeMove( forward, side, pitch, yaw );
|
||||
Touch_GetMove( forward, side, pitch, yaw );
|
||||
|
||||
if( look_filter.value )
|
||||
{
|
||||
|
||||
@@ -71,7 +71,7 @@ static inline void Touch_AddDefaultButton( const char *name, const char *texture
|
||||
static inline void Touch_WriteConfig( void ) { }
|
||||
static inline void Touch_Init( void ) { }
|
||||
static inline void Touch_Shutdown( void ) { }
|
||||
static inline void Touch_GetMove( float * forward, float *side, float *yaw, float *pitch ) { }
|
||||
static inline void Touch_GetMove( float * forward, float *side, float *pitch, float *yaw ) { }
|
||||
static inline void Touch_ResetDefaultButtons( void ) { }
|
||||
static inline int IN_TouchEvent( touchEventType type, int fingerID, float x, float y, float dx, float dy ) { return 0; }
|
||||
static inline void Touch_KeyEvent( int key, int down ) { }
|
||||
@@ -87,7 +87,7 @@ void Touch_AddDefaultButton( const char *name, const char *texturefile, const ch
|
||||
void Touch_WriteConfig( void );
|
||||
void Touch_Init( void );
|
||||
void Touch_Shutdown( void );
|
||||
void Touch_GetMove( float * forward, float *side, float *yaw, float *pitch );
|
||||
void Touch_GetMove( float * forward, float *side, float *pitch, float *yaw );
|
||||
void Touch_ResetDefaultButtons( void );
|
||||
int IN_TouchEvent( touchEventType type, int fingerID, float x, float y, float dx, float dy );
|
||||
void Touch_KeyEvent( int key, int down );
|
||||
@@ -119,7 +119,7 @@ typedef enum engineAxis_e
|
||||
JOY_AXIS_YAW,
|
||||
JOY_AXIS_RT,
|
||||
JOY_AXIS_LT,
|
||||
JOY_AXIS_NULL
|
||||
MAX_AXES,
|
||||
} engineAxis_t;
|
||||
|
||||
typedef enum joy_calibration_state_s
|
||||
@@ -136,6 +136,7 @@ void Joy_SetCalibrationState( joy_calibration_state_t state );
|
||||
void Joy_AxisMotionEvent( engineAxis_t engineAxis, short value );
|
||||
void Joy_GyroEvent( vec3_t data );
|
||||
void Joy_FinalizeMove( float *fw, float *side, float *dpitch, float *dyaw );
|
||||
void Joy_DrawDebug( void );
|
||||
void Joy_Init( void );
|
||||
void Joy_Shutdown( void );
|
||||
|
||||
|
||||
@@ -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 ))
|
||||
@@ -232,6 +232,12 @@ void S_FreeSound( sfx_t *sfx )
|
||||
prev = &hashSfx->hashNext;
|
||||
}
|
||||
|
||||
if( clgame.soundFuncs.pfnS_FreeSound )
|
||||
{
|
||||
clgame.soundFuncs.pfnS_FreeSound( sfx, sfx - s_knownSfx );
|
||||
return;
|
||||
}
|
||||
|
||||
if( sfx->cache )
|
||||
FS_FreeSound( sfx->cache );
|
||||
memset( sfx, 0, sizeof( *sfx ));
|
||||
@@ -247,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++ )
|
||||
@@ -255,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;
|
||||
@@ -273,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
|
||||
@@ -306,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, '!' ))
|
||||
@@ -330,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
|
||||
@@ -369,7 +376,7 @@ void S_FreeSounds( void )
|
||||
sfx_t *sfx;
|
||||
int i;
|
||||
|
||||
if( !dma.initialized )
|
||||
if( !snd.initialized )
|
||||
return;
|
||||
|
||||
// stop all sounds
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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;
|
||||
@@ -284,13 +284,20 @@ static int S_MixNormalChannels( portable_samplepair_t *dst, int end, int rate )
|
||||
// if the sound is unaudible, skip it
|
||||
// if it's also not looping, free it
|
||||
if( ch->leftvol < 8 && ch->rightvol < 8 )
|
||||
{
|
||||
if( !FBitSet( sc->flags, SOUND_LOOPED ) || !ch->use_loop )
|
||||
S_FreeChannel( ch );
|
||||
{
|
||||
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;
|
||||
else if( ch->inauduble_free_time > host.realtime )
|
||||
S_FreeChannel( ch );
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
ch->inauduble_free_time = 0.0f;
|
||||
|
||||
if( rate != sc->rate )
|
||||
continue;
|
||||
|
||||
@@ -301,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 ));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -311,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 );
|
||||
}
|
||||
}
|
||||
@@ -368,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 ));
|
||||
@@ -376,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 ));
|
||||
@@ -395,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;
|
||||
@@ -427,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;
|
||||
@@ -436,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 );
|
||||
@@ -479,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 ();
|
||||
|
||||
@@ -489,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;
|
||||
|
||||
@@ -519,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 );
|
||||
|
||||
@@ -543,6 +550,6 @@ void S_PaintChannels( int endtime )
|
||||
|
||||
// transfer out according to DMA format
|
||||
S_TransferPaintBuffer( paintbuffer, end );
|
||||
paintedtime = end;
|
||||
snd.paintedtime = end;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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 );
|
||||
}
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ GNU General Public License for more details.
|
||||
extern poolhandle_t sndpool;
|
||||
|
||||
#include "xash3d_mathlib.h"
|
||||
#include "sound_api.h"
|
||||
|
||||
// sound engine rate defines
|
||||
#define SOUND_11k 11025 // 11khz sample rate
|
||||
@@ -38,105 +39,6 @@ extern poolhandle_t sndpool;
|
||||
|
||||
#define CLIP16( x ) bound( SHRT_MIN + 8, x, SHRT_MAX - 8 )
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int left;
|
||||
int right;
|
||||
} portable_samplepair_t;
|
||||
|
||||
typedef struct sfx_s
|
||||
{
|
||||
char name[MAX_QPATH];
|
||||
wavdata_t *cache;
|
||||
|
||||
int servercount;
|
||||
uint hashValue;
|
||||
struct sfx_s *hashNext;
|
||||
} sfx_t;
|
||||
|
||||
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
|
||||
} voxword_t;
|
||||
|
||||
typedef struct snd_format_s
|
||||
{
|
||||
uint speed;
|
||||
byte width;
|
||||
byte channels;
|
||||
} snd_format_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
snd_format_t format;
|
||||
int samples; // mono samples in buffer
|
||||
int samplepos; // in mono samples
|
||||
qboolean initialized; // sound engine is active
|
||||
byte *buffer;
|
||||
const char *backendName;
|
||||
} dma_t;
|
||||
|
||||
typedef struct rawchan_s
|
||||
{
|
||||
int entnum;
|
||||
int master_vol;
|
||||
int leftvol; // 0-255 left volume
|
||||
int rightvol; // 0-255 right volume
|
||||
float dist_mult; // distance multiplier (attenuation/clipK)
|
||||
vec3_t origin; // only use if fixed_origin is set
|
||||
volatile uint s_rawend;
|
||||
float oldtime; // catch time jumps
|
||||
size_t max_samples; // buffer length
|
||||
portable_samplepair_t rawsamples[]; // variable sized
|
||||
} rawchan_t;
|
||||
|
||||
typedef struct channel_s
|
||||
{
|
||||
char name[16]; // keep sentence name
|
||||
sfx_t *sfx; // sfx number
|
||||
|
||||
int leftvol; // 0-255 left volume
|
||||
int rightvol; // 0-255 right volume
|
||||
|
||||
int entnum; // entity soundsource
|
||||
int entchannel; // sound channel (CHAN_STREAM, CHAN_VOICE, etc.)
|
||||
vec3_t origin; // only use if fixed_origin is set
|
||||
float dist_mult; // distance multiplier (attenuation/clipK)
|
||||
int master_vol; // 0-255 master volume
|
||||
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;
|
||||
short basePitch; // base pitch percent (100% is normal pitch playback)
|
||||
voxword_t words[CVOXWORDMAX];
|
||||
double sample;
|
||||
double forced_end;
|
||||
wavdata_t *data;
|
||||
} channel_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
vec3_t origin; // simorg + view_ofs
|
||||
vec3_t forward;
|
||||
vec3_t right;
|
||||
vec3_t up;
|
||||
|
||||
int entnum;
|
||||
qboolean streaming; // playing AVI-file
|
||||
qboolean stream_paused; // pause only background track
|
||||
} listener_t;
|
||||
|
||||
typedef int sound_t;
|
||||
|
||||
//====================================================================
|
||||
|
||||
#define MAX_DYNAMIC_CHANNELS (60 + NUM_AMBIENTS)
|
||||
@@ -145,16 +47,8 @@ typedef int sound_t;
|
||||
#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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -28,7 +28,7 @@ typedef struct
|
||||
int cursize;
|
||||
} cmdbuf_t;
|
||||
|
||||
static qboolean cmd_wait;
|
||||
static int cmd_wait;
|
||||
static cmdbuf_t cmd_text;
|
||||
static cmdbuf_t filteredcmd_text;
|
||||
static cmdalias_t *cmd_alias;
|
||||
@@ -56,6 +56,7 @@ void Cbuf_Clear( void )
|
||||
{
|
||||
memset( &cmd_text, 0, sizeof( cmd_text ));
|
||||
memset( &filteredcmd_text, 0, sizeof( filteredcmd_text ));
|
||||
cmd_wait = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -174,6 +175,12 @@ static void Cbuf_ExecuteCommandsFromBuffer( cmdbuf_t *buf, qboolean isPrivileged
|
||||
|
||||
while( buf->cursize )
|
||||
{
|
||||
if( cmd_wait > 0 )
|
||||
{
|
||||
cmd_wait--;
|
||||
break;
|
||||
}
|
||||
|
||||
// limit amount of commands that can be issued
|
||||
if( cmdsToExecute >= 0 )
|
||||
{
|
||||
@@ -238,14 +245,6 @@ static void Cbuf_ExecuteCommandsFromBuffer( cmdbuf_t *buf, qboolean isPrivileged
|
||||
|
||||
// execute the command line
|
||||
Cmd_ExecuteStringWithPrivilegeCheck( line, isPrivileged );
|
||||
|
||||
if( cmd_wait )
|
||||
{
|
||||
// skip out while text still remains in buffer,
|
||||
// leaving it for next frame
|
||||
cmd_wait = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -367,7 +366,13 @@ bind g "cmd use rocket ; +attack ; wait ; -attack ; cmd use blaster"
|
||||
*/
|
||||
static void Cmd_Wait_f( void )
|
||||
{
|
||||
cmd_wait = true;
|
||||
int frame = 1;
|
||||
if( Cmd_Argc() > 1 )
|
||||
{
|
||||
frame = Q_atoi( Cmd_Argv( 1 ) );
|
||||
frame = Q_max( 1, frame );
|
||||
}
|
||||
cmd_wait = frame;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1234,26 +1239,60 @@ static void Cmd_MakePrivileged_f( void )
|
||||
|
||||
/*
|
||||
===============
|
||||
Cmd_Exec_f
|
||||
Cmd_ExecScript
|
||||
===============
|
||||
*/
|
||||
static void Cmd_Exec_f( void )
|
||||
static void Cmd_ExecScript( const char *filename )
|
||||
{
|
||||
string cfgpath;
|
||||
byte *f;
|
||||
fs_offset_t len;
|
||||
|
||||
if( Cmd_Argc() != 2 )
|
||||
f = FS_LoadFile( filename, &len, false );
|
||||
if( !f )
|
||||
{
|
||||
Con_Printf( S_USAGE "exec <filename>\n" );
|
||||
Con_Reportf( "couldn't exec %s\n", filename );
|
||||
return;
|
||||
}
|
||||
|
||||
Q_strncpy( cfgpath, Cmd_Argv( 1 ), sizeof( cfgpath ));
|
||||
COM_DefaultExtension( cfgpath, ".cfg", sizeof( cfgpath )); // append as default
|
||||
// len is fs_offset_t, which can be larger than size_t
|
||||
if( len >= SIZE_MAX )
|
||||
{
|
||||
Con_Reportf( "%s: %s is too long\n", __func__, filename );
|
||||
Mem_Free( f );
|
||||
return;
|
||||
}
|
||||
|
||||
#ifndef XASH_DEDICATED
|
||||
if( !Cmd_CurrentCommandIsPrivileged() && !Q_stricmp( GI->gamefolder, "tfc" ))
|
||||
if( f[len - 1] != '\n' )
|
||||
{
|
||||
Cbuf_InsertTextLen( f, len, len + 1 );
|
||||
Cbuf_InsertTextLen( "\n", 1, 1 );
|
||||
}
|
||||
else Cbuf_InsertTextLen( f, len, len );
|
||||
|
||||
Mem_Free( f );
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
Cmd_UnprivilegedExec_f
|
||||
===============
|
||||
*/
|
||||
static void Cmd_UnprivilegedExec_f( void )
|
||||
{
|
||||
string cfgpath;
|
||||
qboolean allow = false;
|
||||
|
||||
if( Cmd_Argc() != 2 )
|
||||
return;
|
||||
|
||||
Q_strncpy( cfgpath, Cmd_Argv( 1 ), sizeof( cfgpath ));
|
||||
COM_DefaultExtension( cfgpath, ".cfg", sizeof( cfgpath ));
|
||||
|
||||
if( SV_GetMaxClients() == 1 )
|
||||
allow = true;
|
||||
|
||||
#if !XASH_DEDICATED
|
||||
if( !allow && !Q_stricmp( GI->gamefolder, "tfc" ))
|
||||
{
|
||||
const char *const unprivileged_whitelist[] =
|
||||
{
|
||||
@@ -1278,48 +1317,75 @@ static void Cmd_Exec_f( void )
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if( !allow )
|
||||
if( allow )
|
||||
Cmd_ExecScript( cfgpath );
|
||||
else
|
||||
Con_Printf( "exec %s: not privileged or in whitelist\n", cfgpath );
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
Cmd_Exec_f
|
||||
===============
|
||||
*/
|
||||
static void Cmd_Exec_f( void )
|
||||
{
|
||||
string cfgpath;
|
||||
|
||||
// early exit for stuffcmd
|
||||
if( !Cmd_CurrentCommandIsPrivileged())
|
||||
{
|
||||
Cmd_UnprivilegedExec_f();
|
||||
return;
|
||||
}
|
||||
|
||||
if( Cmd_Argc() != 2 )
|
||||
{
|
||||
Con_Printf( S_USAGE "exec <PATTERN>\n"
|
||||
"PATTERN single file or wildcard pattern to match\n"
|
||||
"Wildcards: * matches any characters, ? matches single character\n"
|
||||
"Example: file.cfg - single file.cfg\n"
|
||||
"\tdirectory/* - all .cfg files in directory\n"
|
||||
"\tdirectory/???.cfg - all .cfg files in directory with 3 character names\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
Q_strncpy( cfgpath, Cmd_Argv( 1 ), sizeof( cfgpath ));
|
||||
COM_DefaultExtension( cfgpath, ".cfg", sizeof( cfgpath ));
|
||||
|
||||
if( Q_strpbrk( cfgpath, "*?" ))
|
||||
{
|
||||
search_t *search = FS_Search( cfgpath, true, false );
|
||||
if( !search || !search->numfilenames )
|
||||
{
|
||||
Con_Printf( "exec %s: not privileged or in whitelist\n", cfgpath );
|
||||
Con_Printf( "couldn't exec %s\n", Cmd_Argv( 1 ));
|
||||
if( search ) Mem_Free( search );
|
||||
return;
|
||||
}
|
||||
|
||||
Con_Printf( "execing %d file%s from " S_GREEN "%s" S_DEFAULT "\n",
|
||||
search->numfilenames, search->numfilenames > 1 ? "s" : "", Cmd_Argv( 1 ));
|
||||
|
||||
for( int i = 0; i < search->numfilenames; i++ )
|
||||
Cmd_ExecScript( search->filenames[i] );
|
||||
|
||||
Mem_Free( search );
|
||||
return;
|
||||
}
|
||||
#endif // XASH_DEDICATED
|
||||
|
||||
// don't execute game.cfg in singleplayer
|
||||
if( SV_GetMaxClients() == 1 && !Q_stricmp( "game.cfg", cfgpath ))
|
||||
return;
|
||||
|
||||
f = FS_LoadFile( cfgpath, &len, false );
|
||||
if( !f )
|
||||
{
|
||||
Con_Reportf( "couldn't exec %s\n", Cmd_Argv( 1 ));
|
||||
return;
|
||||
}
|
||||
|
||||
// len is fs_offset_t, which can be larger than size_t
|
||||
if( len >= SIZE_MAX )
|
||||
{
|
||||
Con_Reportf( "%s: %s is too long\n", __func__, Cmd_Argv( 1 ));
|
||||
return;
|
||||
}
|
||||
|
||||
if( !Q_stricmp( "config.cfg", cfgpath ))
|
||||
host.config_executed = true;
|
||||
|
||||
Con_Printf( "execing " S_GREEN "%s" S_DEFAULT "\n", Cmd_Argv( 1 ));
|
||||
|
||||
// adds \n at end of the file
|
||||
// FS_LoadFile always null terminates
|
||||
if( f[len - 1] != '\n' )
|
||||
{
|
||||
Cbuf_InsertTextLen( f, len, len + 1 );
|
||||
Cbuf_InsertTextLen( "\n", 1, 1 );
|
||||
}
|
||||
else Cbuf_InsertTextLen( f, len, len );
|
||||
|
||||
Mem_Free( f );
|
||||
Cmd_ExecScript( cfgpath );
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1388,13 +1454,14 @@ void Cmd_Init( void )
|
||||
cmd_pool = Mem_AllocPool( "Console Commands" );
|
||||
cmd_functions = NULL;
|
||||
cmd_condition = 0;
|
||||
cmd_wait = 0;
|
||||
cmd_alias = NULL;
|
||||
cmd_args = NULL;
|
||||
cmd_argc = 0;
|
||||
|
||||
// register our commands
|
||||
Cmd_AddCommand( "echo", Cmd_Echo_f, "print a message to the console (useful in scripts)" );
|
||||
Cmd_AddCommand( "wait", Cmd_Wait_f, "make script execution wait for some rendered frames" );
|
||||
Cmd_AddRestrictedCommand( "wait", Cmd_Wait_f, "make script execution wait for some rendered frames" );
|
||||
Cmd_AddRestrictedCommand( "cmdlist", Cmd_List_f, "display all console commands beginning with the specified prefix" );
|
||||
Cmd_AddRestrictedCommand( "stuffcmds", Cmd_StuffCmds_f, "execute commandline parameters (must be present in .rc script)" );
|
||||
Cmd_AddRestrictedCommand( "apropos", Cmd_Apropos_f, "lists all console variables/commands/aliases containing the specified string in the name or description" );
|
||||
|
||||
@@ -961,7 +961,7 @@ static void Test_LZSS( void )
|
||||
};
|
||||
const char decompressed[] = "Do you like what you see?";
|
||||
|
||||
#ifdef USING_ASAN
|
||||
#ifdef USE_ASAN
|
||||
ASAN_POISON_MEMORY_REGION( poison1, sizeof( poison1 ));
|
||||
ASAN_POISON_MEMORY_REGION( poison2, sizeof( poison2 ));
|
||||
ASAN_POISON_MEMORY_REGION( poison3, sizeof( poison3 ));
|
||||
|
||||
@@ -16,42 +16,48 @@ GNU General Public License for more details.
|
||||
#ifndef COMMON_H
|
||||
#define COMMON_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
===================================================================================================================================
|
||||
Legend:
|
||||
|
||||
INTERNAL RESOURCE - function contain hardcoded path to resource that engine required (optional in most cases)
|
||||
OBSOLETE, UNUSED - this function no longer used and leaved here for keep binary compatibility
|
||||
TODO - some functionality not impemented but planned
|
||||
FIXME - code doesn't working properly in some rare cases
|
||||
HACKHACK - unexpected behavior on some input params (or something like)
|
||||
BUGBUG - code doesn't working properly in most cases!
|
||||
TESTTEST - this code may be unstable and needs to be more tested
|
||||
g-cont: - notes from engine author
|
||||
XASH SPECIFIC - sort of hack that works only in Xash3D not in GoldSrc
|
||||
===================================================================================================================================
|
||||
*/
|
||||
|
||||
#include "port.h"
|
||||
|
||||
#include "backends.h"
|
||||
#include "defaults.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h> // rand, adbs
|
||||
#include <stdarg.h> // va
|
||||
|
||||
#include "build.h"
|
||||
|
||||
#if !XASH_WIN32
|
||||
#include <stddef.h> // size_t
|
||||
#else
|
||||
#include <sys/types.h> // off_t
|
||||
#endif
|
||||
|
||||
#include "port.h"
|
||||
#include "backends.h"
|
||||
#include "defaults.h"
|
||||
#include "library_suffix.h"
|
||||
#include "enginefeatures.h"
|
||||
#include "system.h"
|
||||
#include "com_model.h"
|
||||
#include "com_strings.h"
|
||||
#include "crtlib.h"
|
||||
#include "cvar.h"
|
||||
#include "con_nprint.h"
|
||||
#include "crclib.h"
|
||||
#include "ref_api.h"
|
||||
#include "com_image.h"
|
||||
|
||||
/*
|
||||
===================================================================================================================================
|
||||
Legend:
|
||||
|
||||
INTERNAL RESOURCE - function contain hardcoded path to resource that engine required (optional in most cases)
|
||||
OBSOLETE, UNUSED - this function no longer used and leaved here for keep binary compatibility
|
||||
TODO - some functionality not impemented but planned
|
||||
FIXME - code doesn't working properly in some rare cases
|
||||
HACKHACK - unexpected behavior on some input params (or something like)
|
||||
BUGBUG - code doesn't working properly in most cases!
|
||||
TESTTEST - this code may be unstable and needs to be more tested
|
||||
g-cont: - notes from engine author
|
||||
XASH SPECIFIC - sort of hack that works only in Xash3D not in GoldSrc
|
||||
===================================================================================================================================
|
||||
*/
|
||||
|
||||
// configuration
|
||||
|
||||
@@ -60,21 +66,19 @@ XASH SPECIFIC - sort of hack that works only in Xash3D not in GoldSrc
|
||||
//
|
||||
#if XASH_TIMER == TIMER_NULL
|
||||
#error "Please select timer backend"
|
||||
#endif
|
||||
#endif // XASH_TIMER == TIMER_NULL
|
||||
|
||||
#if !XASH_DEDICATED
|
||||
#if XASH_VIDEO == VIDEO_NULL
|
||||
#error "Please select video backend"
|
||||
#endif
|
||||
#endif
|
||||
#endif // XASH_VIDEO == VIDEO_NULL
|
||||
#endif // !XASH_DEDICATED
|
||||
|
||||
#ifndef XASH_SDL
|
||||
|
||||
#if XASH_TIMER == TIMER_SDL || XASH_VIDEO == VIDEO_SDL || XASH_SOUND == SOUND_SDL || XASH_INPUT == INPUT_SDL
|
||||
#error "SDL backends without XASH_SDL not allowed"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
#if XASH_TIMER == TIMER_SDL || XASH_VIDEO == VIDEO_SDL || XASH_SOUND == SOUND_SDL || XASH_INPUT == INPUT_SDL
|
||||
#error "SDL backends without XASH_SDL not allowed"
|
||||
#endif // XASH_TIMER == TIMER_SDL || XASH_VIDEO == VIDEO_SDL || XASH_SOUND == SOUND_SDL || XASH_INPUT == INPUT_SDL
|
||||
#endif // XASH_SDL
|
||||
|
||||
#define HACKS_RELATED_HLMODS // some HL-mods works differently under Xash and can't be fixed without some hacks at least at current time
|
||||
|
||||
@@ -97,19 +101,6 @@ typedef enum instance_e
|
||||
#define Host_IsDedicated() ( host.type == HOST_DEDICATED )
|
||||
#endif
|
||||
|
||||
#include "system.h"
|
||||
#include "com_model.h"
|
||||
#include "com_strings.h"
|
||||
#include "crtlib.h"
|
||||
#define FSCALLBACK_OVERRIDE_OPEN
|
||||
#define FSCALLBACK_OVERRIDE_LOADFILE
|
||||
#define FSCALLBACK_OVERRIDE_MALLOC_LIKE
|
||||
#include "fscallback.h"
|
||||
#include "cvar.h"
|
||||
#include "con_nprint.h"
|
||||
#include "crclib.h"
|
||||
#include "ref_api.h"
|
||||
|
||||
// PERFORMANCE INFO
|
||||
#define MIN_FPS 20.0f // host minimum fps value for maxfps.
|
||||
#define MAX_FPS_SOFT 200.0f // soft limit for maxfps.
|
||||
@@ -351,6 +342,9 @@ typedef struct host_parm_s
|
||||
string gamedll;
|
||||
string clientlib;
|
||||
string menulib;
|
||||
|
||||
// default game directory, passed to us from game launcher
|
||||
string default_gamedir;
|
||||
} host_parm_t;
|
||||
|
||||
extern host_parm_t host;
|
||||
@@ -387,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__ )
|
||||
@@ -396,7 +394,7 @@ void Mem_Stats_f( void );
|
||||
//
|
||||
// filesystem_engine.c
|
||||
//
|
||||
void FS_Init( const char *basedir );
|
||||
void FS_Init( void );
|
||||
void FS_Shutdown( void );
|
||||
void *FS_GetNativeObject( const char *obj );
|
||||
int FS_Close( file_t *file );
|
||||
@@ -480,7 +478,6 @@ void Cmd_Escape( char *newCommand, const char *oldCommand, int len );
|
||||
//
|
||||
// imagelib
|
||||
//
|
||||
#include "com_image.h"
|
||||
|
||||
void Image_Setup( void );
|
||||
void Image_Init( void );
|
||||
@@ -564,7 +561,11 @@ qboolean Sound_SupportedFileFormat( const char *fileext );
|
||||
//
|
||||
typedef void( *pfnChangeGame )( const char *progname );
|
||||
|
||||
qboolean Host_IsQuakeCompatible( void );
|
||||
static inline qboolean Host_IsQuakeCompatible( void )
|
||||
{
|
||||
return FBitSet( host.features, ENGINE_QUAKE_COMPATIBLE ) ? true : false;
|
||||
}
|
||||
|
||||
void Host_ShutdownWithReason( const char *reason );
|
||||
int EXPORT Host_Main( int argc, char **argv, const char *progname, int bChangeGame, pfnChangeGame func );
|
||||
void Host_EndGame( qboolean abort, const char *message, ... ) FORMAT_CHECK( 2 );
|
||||
@@ -934,7 +935,4 @@ void SoundList_Shutdown( void );
|
||||
#error "common.h in ref_dll"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif//COMMON_H
|
||||
|
||||
@@ -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 );
|
||||
|
||||
|
||||
@@ -328,7 +328,7 @@ static qboolean FS_DetermineReadOnlyRootDirectory( char *out, size_t size )
|
||||
FS_Init
|
||||
================
|
||||
*/
|
||||
void FS_Init( const char *basedir )
|
||||
void FS_Init( void )
|
||||
{
|
||||
string gamedir;
|
||||
char rodir[MAX_OSPATH], rootdir[MAX_OSPATH];
|
||||
@@ -352,7 +352,7 @@ void FS_Init( const char *basedir )
|
||||
if( env )
|
||||
Q_strncpy( gamedir, env, sizeof( gamedir ));
|
||||
else
|
||||
Q_strncpy( gamedir, basedir, sizeof( gamedir )); // gamedir == basedir
|
||||
Q_strncpy( gamedir, host.default_gamedir, sizeof( gamedir )); // gamedir == basedir
|
||||
}
|
||||
|
||||
FS_LoadProgs();
|
||||
@@ -364,7 +364,7 @@ void FS_Init( const char *basedir )
|
||||
// and this better be reworked at some point
|
||||
g_fsapi.SetCurrentDirectory( rootdir );
|
||||
|
||||
if( !g_fsapi.InitStdio( true, rootdir, basedir, gamedir, rodir ))
|
||||
if( !g_fsapi.InitStdio( true, rootdir, host.default_gamedir, gamedir, rodir ))
|
||||
{
|
||||
Sys_Error( "Can't init filesystem_stdio!\n" );
|
||||
return;
|
||||
|
||||
@@ -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;
|
||||
@@ -296,27 +298,6 @@ void Host_ValidateEngineFeatures( uint32_t mask, uint32_t features )
|
||||
host.features = features;
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
Host_IsQuakeCompatible
|
||||
|
||||
==============
|
||||
*/
|
||||
qboolean Host_IsQuakeCompatible( void )
|
||||
{
|
||||
// feature set
|
||||
if( FBitSet( host.features, ENGINE_QUAKE_COMPATIBLE ))
|
||||
return true;
|
||||
|
||||
#if !XASH_DEDICATED
|
||||
// quake demo playing
|
||||
if( cls.demoplayback == DEMO_QUAKE1 )
|
||||
return true;
|
||||
#endif // XASH_DEDICATED
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
Host_EndGame
|
||||
@@ -882,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
|
||||
@@ -913,6 +1006,7 @@ static void Host_InitCommon( int argc, char **argv, const char *progname, qboole
|
||||
host.config_executed = false;
|
||||
host.status = HOST_INIT; // initialzation started
|
||||
host.type = HOST_DEDICATED; // predict state
|
||||
Q_strncpy( host.default_gamedir, basedir, sizeof( host.default_gamedir ));
|
||||
|
||||
#ifndef XASH_DEDICATED
|
||||
if( !Sys_CheckParm( "-dedicated" ))
|
||||
@@ -985,8 +1079,8 @@ static void Host_InitCommon( int argc, char **argv, const char *progname, qboole
|
||||
#if XASH_DEDICATED
|
||||
Platform_SetupSigtermHandling();
|
||||
#endif
|
||||
Platform_Init( Host_IsDedicated( ) || developer >= DEV_EXTENDED, basedir );
|
||||
FS_Init( basedir );
|
||||
Platform_Init( Host_IsDedicated( ) || developer >= DEV_EXTENDED );
|
||||
FS_Init();
|
||||
|
||||
// print current developer level to simplify processing users feedback
|
||||
if( developer > 0 )
|
||||
@@ -1018,6 +1112,7 @@ static void Host_InitCommon( int argc, char **argv, const char *progname, qboole
|
||||
#endif
|
||||
|
||||
FS_LoadGameInfo();
|
||||
Host_CheckGameLibraries();
|
||||
Cvar_PostFSInit();
|
||||
|
||||
Image_CheckPaletteQ1 ();
|
||||
|
||||
@@ -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?
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 )
|
||||
|
||||
@@ -84,6 +84,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
#define K_JOY3 205
|
||||
#define K_JOY4 206
|
||||
|
||||
#define K_LTRIGGER K_JOY1
|
||||
#define K_RTRIGGER K_JOY2
|
||||
|
||||
//
|
||||
// aux keys are for multi-buttoned joysticks to generate so they can use
|
||||
// the normal binding process
|
||||
|
||||
@@ -222,7 +222,7 @@ typedef struct ui_extendedfuncs_s {
|
||||
|
||||
// new mods info
|
||||
gameinfo2_t *(*pfnGetGameInfo)( int gi_version ); // might return NULL if gi_version is unsupported
|
||||
gameinfo2_t *(*pfnGetModInfo)( int gi_version, int mod_index ); // continiously call it until it returns null
|
||||
gameinfo2_t *(*pfnGetModInfo)( int gi_version, int mod_index ); // continuously call it until it returns null
|
||||
|
||||
// returns 1 if cvar has read-only flag
|
||||
// or -1 if cvar not found
|
||||
|
||||
@@ -21,9 +21,6 @@
|
||||
#include <sys/stat.h>
|
||||
#include "dlfcn.h"
|
||||
|
||||
#ifndef XASH_GAMEDIR
|
||||
#define XASH_GAMEDIR "valve" // !!! Replace with your default (base) game directory !!!
|
||||
#endif
|
||||
#define XASHLIB "@rpath/libxash.dylib"
|
||||
|
||||
|
||||
@@ -331,4 +328,4 @@ int IOS_GetArgs( char ***out )
|
||||
{
|
||||
*out = szArgv;
|
||||
return szArgc;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 "fscallback.h"
|
||||
#include "library.h"
|
||||
#include "platform/ios/lib_ios.h"
|
||||
#include <dlfcn.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(), "valve" ) )
|
||||
{
|
||||
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 );
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -66,10 +66,15 @@ qboolean Platform_DebuggerPresent( void )
|
||||
tracer_pid = (const byte*)Q_strstr( buf, TracerPid );
|
||||
if( !tracer_pid )
|
||||
return false;
|
||||
|
||||
//printf( "%s\n", tracer_pid );
|
||||
while( *tracer_pid < '0' || *tracer_pid > '9' )
|
||||
|
||||
while(( *tracer_pid < '0' ) || ( *tracer_pid > '9' ))
|
||||
{
|
||||
if( *tracer_pid++ == '\n' )
|
||||
return false;
|
||||
}
|
||||
|
||||
//printf( "%s\n", tracer_pid );
|
||||
return !!Q_atoi( (const char*)tracer_pid );
|
||||
}
|
||||
|
||||
@@ -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
|
||||
@@ -58,7 +61,7 @@ char *Posix_Input( void );
|
||||
#endif
|
||||
|
||||
#if XASH_SDL
|
||||
void SDLash_Init( const char *basedir );
|
||||
void SDLash_Init( void );
|
||||
void SDLash_Shutdown( void );
|
||||
void SDLash_NanoSleep( int nsec );
|
||||
#endif
|
||||
@@ -111,7 +114,7 @@ void Linux_SetTimer( float time );
|
||||
int Linux_GetProcessID( void );
|
||||
#endif
|
||||
|
||||
static inline void Platform_Init( qboolean con_showalways, const char *basedir )
|
||||
static inline void Platform_Init( qboolean con_showalways )
|
||||
{
|
||||
#if XASH_POSIX
|
||||
// daemonize as early as possible, because we need to close our file descriptors
|
||||
@@ -119,7 +122,7 @@ static inline void Platform_Init( qboolean con_showalways, const char *basedir )
|
||||
#endif
|
||||
|
||||
#if XASH_SDL
|
||||
SDLash_Init( basedir );
|
||||
SDLash_Init( );
|
||||
#endif
|
||||
|
||||
#if XASH_ANDROID
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
==============================================================================
|
||||
@@ -389,14 +404,16 @@ qboolean VoiceCapture_Lock( qboolean lock );
|
||||
pid_t raise_tid = Linux_GetProcessID(); \
|
||||
int raise_sig = (x); \
|
||||
__asm__ volatile ( \
|
||||
"push {r7}\n\t" \
|
||||
"mov r7,#268\n\t" \
|
||||
"mov r0,%0\n\t" \
|
||||
"mov r1,%1\n\t" \
|
||||
"mov r2,%2\n\t" \
|
||||
"svc 0\n\t" \
|
||||
"pop {r7}\n\t" \
|
||||
: \
|
||||
: "r"(raise_pid), "r"(raise_tid), "r"(raise_sig) \
|
||||
: "r0", "r1", "r2", "r7", "memory" \
|
||||
: "r0", "r1", "r2", "memory" \
|
||||
); \
|
||||
} while( 0 )
|
||||
#define INLINE_NANOSLEEP1() do \
|
||||
@@ -404,13 +421,15 @@ qboolean VoiceCapture_Lock( qboolean lock );
|
||||
struct timespec ns_t1 = {1, 0}; \
|
||||
struct timespec ns_t2 = {0, 0}; \
|
||||
__asm__ volatile ( \
|
||||
"push {r7}\n\t" \
|
||||
"mov r7,#162\n\t" \
|
||||
"mov r0,%0\n\t" \
|
||||
"mov r1,%1\n\t" \
|
||||
"svc 0\n\t" \
|
||||
"pop {r7}\n\t" \
|
||||
: \
|
||||
: "r"(&ns_t1), "r"(&ns_t2) \
|
||||
: "r0", "r1", "r7", "memory" \
|
||||
: "r0", "r1", "memory" \
|
||||
); \
|
||||
} while( 0 )
|
||||
#elif XASH_LINUX && XASH_ARM && XASH_64BIT
|
||||
|
||||
@@ -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 );
|
||||
|
||||
@@ -41,8 +41,8 @@ static const engineAxis_t g_axis_mapping[] =
|
||||
{
|
||||
JOY_AXIS_SIDE, // SDL_CONTROLLER_AXIS_LEFTX,
|
||||
JOY_AXIS_FWD, // SDL_CONTROLLER_AXIS_LEFTY,
|
||||
JOY_AXIS_PITCH, // SDL_CONTROLLER_AXIS_RIGHTX,
|
||||
JOY_AXIS_YAW, // SDL_CONTROLLER_AXIS_RIGHTY,
|
||||
JOY_AXIS_YAW, // SDL_CONTROLLER_AXIS_RIGHTX,
|
||||
JOY_AXIS_PITCH, // SDL_CONTROLLER_AXIS_RIGHTY,
|
||||
JOY_AXIS_LT, // SDL_CONTROLLER_AXIS_TRIGGERLEFT,
|
||||
JOY_AXIS_RT, // SDL_CONTROLLER_AXIS_TRIGGERRIGHT,
|
||||
};
|
||||
@@ -52,14 +52,16 @@ static SDL_GameController *g_current_gamepad;
|
||||
static SDL_GameController **g_gamepads;
|
||||
static size_t g_num_gamepads;
|
||||
|
||||
#define CALIBRATION_TIME 10.0f
|
||||
#define CALIBRATION_TIME 5.0f
|
||||
|
||||
static struct
|
||||
{
|
||||
float time;
|
||||
vec3_t data;
|
||||
vec3_t calibrated_values;
|
||||
int samples;
|
||||
float time;
|
||||
vec3_t data;
|
||||
vec3_t calibrated_values;
|
||||
float data_rate;
|
||||
int samples;
|
||||
qboolean continuous; // true after first successful calibration
|
||||
} gyrocal;
|
||||
|
||||
static void SDLash_RestartCalibration( void )
|
||||
@@ -70,35 +72,69 @@ static void SDLash_RestartCalibration( void )
|
||||
|
||||
gyrocal.time = host.realtime + CALIBRATION_TIME;
|
||||
|
||||
Con_Printf( "Starting gyroscope calibration...\n" );
|
||||
#if SDL_VERSION_ATLEAST( 2, 0, 16 )
|
||||
gyrocal.data_rate = SDL_GameControllerGetSensorDataRate( g_current_gamepad, SDL_SENSOR_GYRO );
|
||||
#endif
|
||||
if( !gyrocal.data_rate )
|
||||
gyrocal.data_rate = 10.0f;
|
||||
|
||||
Con_Printf( S_NOTE "Starting gyroscope calibration at %g data rate for %g seconds...\n", gyrocal.data_rate, CALIBRATION_TIME );
|
||||
}
|
||||
|
||||
static void SDLash_FinalizeCalibration( void )
|
||||
{
|
||||
float data_rate = 10.0f; // let's say we're polling at 10Hz?
|
||||
int min_samples;
|
||||
|
||||
#if SDL_VERSION_ATLEAST( 2, 0, 16 )
|
||||
data_rate = SDL_GameControllerGetSensorDataRate( g_current_gamepad, SDL_SENSOR_GYRO );
|
||||
if( !data_rate )
|
||||
data_rate = 10.0f;
|
||||
#endif
|
||||
|
||||
min_samples = Q_rint( CALIBRATION_TIME * data_rate * 0.75f );
|
||||
int min_samples = Q_rint( CALIBRATION_TIME * gyrocal.data_rate * 0.5f );
|
||||
|
||||
// we waited for few seconds and got too few samples
|
||||
if( gyrocal.samples <= min_samples )
|
||||
{
|
||||
Joy_SetCalibrationState( JOY_FAILED_TO_CALIBRATE );
|
||||
return;
|
||||
if( !gyrocal.continuous )
|
||||
{
|
||||
Joy_SetCalibrationState( JOY_FAILED_TO_CALIBRATE );
|
||||
Con_Printf( S_ERROR "Calibration failed, got samples %d < %d\n", gyrocal.samples, min_samples );
|
||||
gyrocal.time = 0.0f;
|
||||
return;
|
||||
}
|
||||
// Con_Reportf( S_WARN "Continuous calibration: too few samples (%d < %d), retrying\n", gyrocal.samples, min_samples );
|
||||
}
|
||||
else
|
||||
{
|
||||
VectorScale( gyrocal.data, 1.0f / gyrocal.samples, gyrocal.calibrated_values );
|
||||
Joy_SetCalibrationState( JOY_CALIBRATED );
|
||||
if( !gyrocal.continuous )
|
||||
Con_Printf( "Calibration done. Result: %f %f %f at %d samples\n", gyrocal.calibrated_values[0], gyrocal.calibrated_values[1], gyrocal.calibrated_values[2], gyrocal.samples );
|
||||
// else
|
||||
// Con_Reportf( "Continuous calibration done. Result: %f %f %f at %d samples\n", gyrocal.calibrated_values[0], gyrocal.calibrated_values[1], gyrocal.calibrated_values[2], gyrocal.samples );
|
||||
gyrocal.continuous = true;
|
||||
}
|
||||
|
||||
VectorScale( gyrocal.data, 1.0f / gyrocal.samples, gyrocal.calibrated_values );
|
||||
Joy_SetCalibrationState( JOY_CALIBRATED );
|
||||
// schedule next calibration window
|
||||
VectorClear( gyrocal.data );
|
||||
gyrocal.samples = 0;
|
||||
gyrocal.time = host.realtime + CALIBRATION_TIME;
|
||||
}
|
||||
|
||||
Con_Printf( "Calibration done. Result: %f %f %f\n", gyrocal.calibrated_values[0], gyrocal.calibrated_values[1], gyrocal.calibrated_values[2] );
|
||||
static void SDLash_AccumulateCalibrationData( vec3_t data )
|
||||
{
|
||||
// for continuous background calibration only listen for noise
|
||||
// by comparing it with calibrated values
|
||||
//
|
||||
// for first calibration this might be hurtful as device might
|
||||
// output offset data
|
||||
if( gyrocal.continuous )
|
||||
{
|
||||
vec3_t calibrated;
|
||||
VectorSubtract( data, gyrocal.calibrated_values, calibrated );
|
||||
|
||||
gyrocal.time = 0.0f;
|
||||
if( VectorLength( calibrated ) > 0.1f )
|
||||
return;
|
||||
}
|
||||
|
||||
VectorAdd( gyrocal.data, data, gyrocal.data );
|
||||
gyrocal.samples++;
|
||||
|
||||
if( !gyrocal.continuous )
|
||||
Joy_SetCalibrationState( JOY_CALIBRATING );
|
||||
}
|
||||
|
||||
static void SDLash_GameControllerAddMappings( const char *name )
|
||||
@@ -125,7 +161,8 @@ static void SDLash_SetActiveGameController( SDL_JoystickID id )
|
||||
|
||||
#if SDL_VERSION_ATLEAST( 2, 0, 14 )
|
||||
// going to change active controller, disable gyro events in old
|
||||
SDL_GameControllerSetSensorEnabled( g_current_gamepad, SDL_SENSOR_GYRO, SDL_FALSE );
|
||||
if( g_current_gamepad )
|
||||
SDL_GameControllerSetSensorEnabled( g_current_gamepad, SDL_SENSOR_GYRO, SDL_FALSE );
|
||||
#endif // SDL_VERSION_ATLEAST( 2, 0, 14 )
|
||||
|
||||
g_current_gamepad_id = id;
|
||||
@@ -243,12 +280,12 @@ static void SDLash_GameControllerSensorUpdate( SDL_ControllerSensorEvent sensor
|
||||
{
|
||||
if( host.realtime > gyrocal.time )
|
||||
SDLash_FinalizeCalibration();
|
||||
else
|
||||
SDLash_AccumulateCalibrationData( sensor.data );
|
||||
|
||||
VectorAdd( gyrocal.data, sensor.data, gyrocal.data );
|
||||
gyrocal.samples++;
|
||||
|
||||
Joy_SetCalibrationState( JOY_CALIBRATING );
|
||||
return;
|
||||
// block gyro events only during initial calibration
|
||||
if( !gyrocal.continuous )
|
||||
return;
|
||||
}
|
||||
|
||||
VectorSubtract( sensor.data, gyrocal.calibrated_values, data );
|
||||
@@ -335,6 +372,9 @@ int Platform_JoyInit( void )
|
||||
{
|
||||
int count, numJoysticks, i;
|
||||
|
||||
SDL_SetHint( SDL_HINT_JOYSTICK_HIDAPI_PS4_RUMBLE, "1" );
|
||||
SDL_SetHint( SDL_HINT_JOYSTICK_HIDAPI_PS5_RUMBLE, "1" );
|
||||
|
||||
Con_Reportf( "Joystick: SDL GameController API\n" );
|
||||
if( SDL_WasInit( SDL_INIT_GAMECONTROLLER ) != SDL_INIT_GAMECONTROLLER &&
|
||||
SDL_InitSubSystem( SDL_INIT_GAMECONTROLLER ))
|
||||
|
||||
@@ -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 );
|
||||
|
||||
@@ -79,20 +79,23 @@ static void SDLCALL SDLash_LogOutputFunction( void *userdata, int category, SDL_
|
||||
case SDL_LOG_PRIORITY_INFO:
|
||||
str = S_NOTE;
|
||||
break;
|
||||
default:
|
||||
str = "";
|
||||
break;
|
||||
}
|
||||
|
||||
Con_Reportf( "%s" S_BLUE "SDL" S_DEFAULT ": [%s] %s\n", str, SDLash_CategoryToString( category ), message );
|
||||
}
|
||||
|
||||
void SDLash_Init( const char *basedir )
|
||||
void SDLash_Init( void )
|
||||
{
|
||||
#if XASH_APPLE
|
||||
#if XASH_IOS
|
||||
char *path = SDL_GetBasePath();
|
||||
if( path != NULL )
|
||||
{
|
||||
char buf[MAX_VA_STRING];
|
||||
|
||||
Q_snprintf( buf, sizeof( buf ), "%s%s/extras.pk3", path, basedir );
|
||||
Q_snprintf( buf, sizeof( buf ), "%s%s/extras.pk3", path, host.default_gamedir );
|
||||
setenv( "XASH3D_EXTRAS_PAK1", buf, true );
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -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 )
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1284,6 +1284,12 @@ static int GAME_EXPORT pfnPrecacheModel( const char *s )
|
||||
qboolean optional = false;
|
||||
int i;
|
||||
|
||||
if( COM_StringEmptyOrNULL( s ))
|
||||
{
|
||||
Host_Error( "%s: NULL pointer or empty string as model name\n", __func__ );
|
||||
return 0;
|
||||
}
|
||||
|
||||
if( *s == '!' )
|
||||
{
|
||||
optional = true;
|
||||
|
||||
@@ -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 );
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -27,9 +27,6 @@ extern fs_globals_t *FI;
|
||||
#define FS_Gamedir() GI->gamefolder
|
||||
#define FS_Title() GI->title
|
||||
|
||||
#define FS_InitStdio (*g_fsapi.InitStdio)
|
||||
#define FS_ShutdownStdio (*g_fsapi.ShutdownStdio)
|
||||
|
||||
// search path utils
|
||||
#define FS_Rescan (*g_fsapi.Rescan)
|
||||
#define FS_ClearSearchPath (*g_fsapi.ClearSearchPath)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -86,7 +86,7 @@ static qboolean Mod_LooksLikeWaterTexture( const char *name )
|
||||
if(( name[0] == '*' && Q_stricmp( name, REF_DEFAULT_TEXTURE )) || name[0] == '!' )
|
||||
return true;
|
||||
|
||||
if( !ENGINE_GET_PARM( PARM_QUAKE_COMPATIBLE ))
|
||||
if( !FBitSet( gp_host->features, ENGINE_QUAKE_COMPATIBLE ))
|
||||
{
|
||||
if( !Q_strncmp( name, "water", 5 ) || !Q_strnicmp( name, "laser", 5 ))
|
||||
return true;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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 )
|
||||
{
|
||||
|
||||
@@ -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];
|
||||
}
|
||||
|
||||
@@ -837,7 +842,7 @@ static byte *GL_ApplyFilter( const byte *source, int width, int height )
|
||||
byte *out = (byte *)source;
|
||||
int i;
|
||||
|
||||
if( ENGINE_GET_PARM( PARM_QUAKE_COMPATIBLE ) || glConfig.max_multisamples > 1 )
|
||||
if( FBitSet( gp_host->features, ENGINE_QUAKE_COMPATIBLE ) || glConfig.max_multisamples > 1 )
|
||||
return in;
|
||||
|
||||
for( i = 0; source && i < width * height; i++, in += 4 )
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 );
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -345,7 +345,7 @@ void R_SetupFrustum( void )
|
||||
{
|
||||
const ref_overview_t *ov = gEngfuncs.GetOverviewParms();
|
||||
|
||||
if( RP_NORMALPASS() && ( ENGINE_GET_PARM( PARM_WATER_LEVEL ) >= 3 ) && ENGINE_GET_PARM( PARM_QUAKE_COMPATIBLE ))
|
||||
if( RP_NORMALPASS() && FBitSet( gp_host->features, ENGINE_QUAKE_COMPATIBLE ) && ( ENGINE_GET_PARM( PARM_WATER_LEVEL ) >= 3 ))
|
||||
{
|
||||
RI.fov_x = atan( tan( DEG2RAD( RI.fov_x ) / 2 ) * ( 0.97f + sin( gp_cl->time * 1.5f ) * 0.03f )) * 2 / (M_PI_F / 180.0f);
|
||||
RI.fov_y = atan( tan( DEG2RAD( RI.fov_y ) / 2 ) * ( 1.03f - sin( gp_cl->time * 1.5f ) * 0.03f )) * 2 / (M_PI_F / 180.0f);
|
||||
@@ -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
|
||||
@@ -696,7 +697,7 @@ static void R_CheckFog( void )
|
||||
int i, cnt, count;
|
||||
|
||||
// quake global fog
|
||||
if( ENGINE_GET_PARM( PARM_QUAKE_COMPATIBLE ))
|
||||
if( FBitSet( gp_host->features, ENGINE_QUAKE_COMPATIBLE ))
|
||||
{
|
||||
if( !tr.movevars->fog_settings )
|
||||
{
|
||||
@@ -824,9 +825,7 @@ void R_DrawFog( void )
|
||||
return;
|
||||
|
||||
pglEnable( GL_FOG );
|
||||
if( ENGINE_GET_PARM( PARM_QUAKE_COMPATIBLE ))
|
||||
pglFogi( GL_FOG_MODE, GL_EXP2 );
|
||||
else pglFogi( GL_FOG_MODE, GL_EXP );
|
||||
pglFogi( GL_FOG_MODE, FBitSet( gp_host->features, ENGINE_QUAKE_COMPATIBLE ) ? GL_EXP2 : GL_EXP );
|
||||
pglFogf( GL_FOG_DENSITY, RI.fogDensity );
|
||||
pglFogfv( GL_FOG_COLOR, RI.fogColor );
|
||||
pglHint( GL_FOG_HINT, GL_NICEST );
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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 )
|
||||
@@ -888,7 +893,7 @@ static void DrawGLPoly( glpoly2_t *p, float xScale, float yScale )
|
||||
float flRate, flAngle, sy, cy;
|
||||
gl_texture_t *texture;
|
||||
|
||||
if( e == CL_GetEntityByIndex( 0 ) && ENGINE_GET_PARM( PARM_QUAKE_COMPATIBLE ))
|
||||
if( e == CL_GetEntityByIndex( 0 ) && FBitSet( gp_host->features, ENGINE_QUAKE_COMPATIBLE ))
|
||||
{
|
||||
// same as doom speed
|
||||
flConveyorSpeed = -35.0f;
|
||||
@@ -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 )
|
||||
@@ -1461,7 +1455,7 @@ static void R_DrawTextureChains( void )
|
||||
continue; // draw translucent water later
|
||||
}
|
||||
|
||||
if( ENGINE_GET_PARM( PARM_QUAKE_COMPATIBLE ) && FBitSet( s->flags, SURF_TRANSPARENT ))
|
||||
if( FBitSet( gp_host->features, ENGINE_QUAKE_COMPATIBLE ) && FBitSet( s->flags, SURF_TRANSPARENT ))
|
||||
{
|
||||
R_AddToSeparatePass( &draw_alpha_surfaces, i );
|
||||
continue; // draw transparent surfaces later
|
||||
@@ -1642,7 +1636,7 @@ static void R_SetRenderMode( cl_entity_t *e )
|
||||
case kRenderTransAlpha:
|
||||
pglEnable( GL_ALPHA_TEST );
|
||||
pglTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
|
||||
if( ENGINE_GET_PARM( PARM_QUAKE_COMPATIBLE ))
|
||||
if( FBitSet( gp_host->features, ENGINE_QUAKE_COMPATIBLE ))
|
||||
{
|
||||
pglBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
|
||||
pglColor4f( 1.0f, 1.0f, 1.0f, tr.blend );
|
||||
@@ -1667,7 +1661,7 @@ static void R_SetRenderMode( cl_entity_t *e )
|
||||
|
||||
static int R_SortBrushModelSurfaces( cl_entity_t *e, model_t *clmodel, vec3_t mins )
|
||||
{
|
||||
qboolean quake_compatible = ENGINE_GET_PARM( PARM_QUAKE_COMPATIBLE );
|
||||
qboolean quake_compatible = FBitSet( gp_host->features, ENGINE_QUAKE_COMPATIBLE ) ? true : false;
|
||||
int num_sorted = 0;
|
||||
|
||||
for( int i = 0; i < clmodel->nummodelsurfaces; i++ )
|
||||
@@ -1766,7 +1760,7 @@ void R_DrawBrushModel( cl_entity_t *e )
|
||||
VectorSubtract( RI.cullorigin, e->origin, tr.modelorg );
|
||||
}
|
||||
|
||||
if( ENGINE_GET_PARM( PARM_QUAKE_COMPATIBLE ) && FBitSet( clmodel->flags, MODEL_TRANSPARENT ))
|
||||
if( FBitSet( gp_host->features, ENGINE_QUAKE_COMPATIBLE ) && FBitSet( clmodel->flags, MODEL_TRANSPARENT ))
|
||||
e->curstate.rendermode = kRenderTransAlpha;
|
||||
|
||||
e->visframe = tr.realframecount; // visible
|
||||
@@ -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 );
|
||||
}
|
||||
|
||||
@@ -3728,15 +3705,11 @@ void R_MarkLeaves( void )
|
||||
{
|
||||
// merge two leafs that can be a crossed-line contents
|
||||
if( RI.viewleaf->contents == CONTENTS_EMPTY )
|
||||
{
|
||||
VectorSet( test, RI.pvsorigin[0], RI.pvsorigin[1], RI.pvsorigin[2] - 16.0f );
|
||||
leaf = gEngfuncs.Mod_PointInLeaf( test, WORLDMODEL->nodes );
|
||||
}
|
||||
else
|
||||
{
|
||||
VectorSet( test, RI.pvsorigin[0], RI.pvsorigin[1], RI.pvsorigin[2] + 16.0f );
|
||||
leaf = gEngfuncs.Mod_PointInLeaf( test, WORLDMODEL->nodes );
|
||||
}
|
||||
|
||||
leaf = gEngfuncs.Mod_PointInLeaf( test, WORLDMODEL->nodes );
|
||||
|
||||
if(( leaf->contents != CONTENTS_SOLID ) && ( RI.viewleaf != leaf ))
|
||||
force = true;
|
||||
|
||||
@@ -2340,15 +2340,24 @@ static void R_StudioDrawPoints( void )
|
||||
pstudionorms = (vec3_t *)((byte *)m_pStudioHeader + m_pSubModel->normindex);
|
||||
|
||||
// backface culling for left-handed weapons
|
||||
if( R_AllowFlipViewModel( RI.currententity ))
|
||||
//
|
||||
// there is a bug in GoldSrc that sets backface culling to GL_FRONT
|
||||
// but doesn't enable OpenGL GL_CULL_FACE. This allows mod developers to disable
|
||||
// backface culling through TriAPI call
|
||||
//
|
||||
// see https://github.com/FWGS/xash3d-fwgs/issues/2517
|
||||
if( glState.faceCull != GL_NONE )
|
||||
{
|
||||
tr.fFlipViewModel = true;
|
||||
GL_Cull( GL_NONE );
|
||||
}
|
||||
else
|
||||
{
|
||||
tr.fFlipViewModel = false;
|
||||
GL_Cull( GL_FRONT );
|
||||
if( R_AllowFlipViewModel( RI.currententity ))
|
||||
{
|
||||
tr.fFlipViewModel = true;
|
||||
GL_Cull( GL_NONE );
|
||||
}
|
||||
else
|
||||
{
|
||||
tr.fFlipViewModel = false;
|
||||
GL_Cull( GL_FRONT );
|
||||
}
|
||||
}
|
||||
|
||||
for( j = 0; j < m_pSubModel->nummesh; j++ )
|
||||
|
||||
@@ -359,7 +359,7 @@ void R_DrawSolidClippedSubmodelPolygons( model_t *pmodel, mnode_t *topnode )
|
||||
|
||||
for( i = 0; i < numsurfaces; i++, psurf++ )
|
||||
{
|
||||
if( FBitSet( psurf->flags, SURF_DRAWTURB ) && !ENGINE_GET_PARM( PARM_QUAKE_COMPATIBLE ))
|
||||
if( FBitSet( psurf->flags, SURF_DRAWTURB ) && !FBitSet( gp_host->features, ENGINE_QUAKE_COMPATIBLE ))
|
||||
{
|
||||
if( psurf->plane->type != PLANE_Z && !FBitSet( RI.currententity->curstate.effects, EF_WATERSIDES ))
|
||||
continue;
|
||||
@@ -441,7 +441,7 @@ void R_DrawSubmodelPolygons( model_t *pmodel, int clipflags, mnode_t *topnode )
|
||||
|
||||
for( i = 0; i < numsurfaces; i++, psurf++ )
|
||||
{
|
||||
if( FBitSet( psurf->flags, SURF_DRAWTURB ) && !ENGINE_GET_PARM( PARM_QUAKE_COMPATIBLE ))
|
||||
if( FBitSet( psurf->flags, SURF_DRAWTURB ) && !FBitSet( gp_host->features, ENGINE_QUAKE_COMPATIBLE ))
|
||||
{
|
||||
if( psurf->plane->type != PLANE_Z && !FBitSet( RI.currententity->curstate.effects, EF_WATERSIDES ))
|
||||
continue;
|
||||
@@ -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 );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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 );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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 );
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user