mirror of
https://github.com/FWGS/xash3d-fwgs.git
synced 2026-08-05 11:35:05 +08:00
Compare commits
107 Commits
continuous
...
continuous
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
74869c8f5d | ||
|
|
dd712a0df9 | ||
|
|
bfdb62d31e | ||
|
|
ae7b9eb28d | ||
|
|
c63e13c8f4 | ||
|
|
d3e1407675 | ||
|
|
e2e4728c7c | ||
|
|
dd3583d11a | ||
|
|
e6924844da | ||
|
|
a49db03561 | ||
|
|
84b7b5803b | ||
|
|
c224d39ba7 | ||
|
|
9b24b08df1 | ||
|
|
a37b0e58f1 | ||
|
|
afca422e35 | ||
|
|
3440ddf443 | ||
|
|
6730ed9555 | ||
|
|
fdd3a44fa0 | ||
|
|
241c926076 | ||
|
|
148a9a5a8c | ||
|
|
513984d7fd | ||
|
|
1009795d5c | ||
|
|
e3d2da74db | ||
|
|
ff3a57ae8a | ||
|
|
271a6e2210 | ||
|
|
0d40357b93 | ||
|
|
a9dcdd034c | ||
|
|
7324ff43fc | ||
|
|
d85e7fc2b1 | ||
|
|
d91ecfa3df | ||
|
|
b7a3a02aad | ||
|
|
5aca78951c | ||
|
|
81abae65b5 | ||
|
|
f5f6d9bbe4 | ||
|
|
ef73b55413 | ||
|
|
8334695522 | ||
|
|
d7f416d659 | ||
|
|
5f6577df2e | ||
|
|
e87f307ac1 | ||
|
|
7e015a268b | ||
|
|
a679c53111 | ||
|
|
9e8d248044 | ||
|
|
055d646225 | ||
|
|
a2514b6916 | ||
|
|
0ac5e78040 | ||
|
|
a82221e3df | ||
|
|
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 |
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
@@ -134,7 +134,7 @@ To build you should clone [SDL](https://github.com/libsdl-org/SDL) from `SDL2` b
|
||||
0) (optional) Examine which build options are available: `./waf --help`.
|
||||
1) Configure build: `./waf configure --ios --enable-bundled-deps --sdl2 (path/to/SDL2.framework)`, set `--ios-simulator` instead of `--ios` if you want to build for simulator.
|
||||
2) Compile `./waf build`.
|
||||
3) Navigate to `build` and copy your compiled SDL2.framework there, then add your client dylibs to `build/ios/cl_dlls` and any other dylibs to `build/ios/dlls` (You can also run `scripts/ios/buildhlsdk.sh` instead to automatically create an ipa with hlsdk dylibs)
|
||||
3) Navigate to `build` and copy your compiled SDL2.framework there, then add your game dylibs to `build/ios/libs/(gamedir)/(dlls/cl_dlls)`(You can also run `scripts/ios/buildhlsdk.sh` instead to automatically create an ipa with hlsdk dylibs)
|
||||
4) Run `scripts/ios/createipa.sh` to create an installable ipa
|
||||
|
||||
### Running tests
|
||||
|
||||
@@ -116,6 +116,8 @@ typedef enum
|
||||
IMAGE_MULTILAYER = BIT(8), // to differentiate from 3D texture
|
||||
IMAGE_ONEBIT_ALPHA = BIT(9), // binary alpha
|
||||
IMAGE_QUAKEPAL = BIT(10), // image has quake1 palette
|
||||
IMAGE_PREMULTIPLIED = BIT(11),
|
||||
IMAGE_PLAYERDECAL = BIT(12), // loaded with IL_LOAD_PLAYER_DECAL (custom player spray)
|
||||
|
||||
// Image_Process manipulation flags
|
||||
IMAGE_FLIP_X = BIT(16), // flip the image by width
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -101,7 +101,7 @@ typedef enum
|
||||
TF_TEXTURE_3D = (1<<20), // this is GL_TEXTURE_3D
|
||||
TF_ATLAS_PAGE = (1<<21), // bit who indicate lightmap page or deluxemap page
|
||||
TF_ALPHACONTRAST = (1<<22), // special texture mode for A2C
|
||||
// reserved
|
||||
TF_PREMULTIPLIED = (1<<23), // RGBA was stored premultiplied (HL gradient / indexalpha)
|
||||
// reserved
|
||||
TF_IMG_UPLOADED = (1<<25), // this is set for first time when called glTexImage, otherwise it will be call glTexSubImage
|
||||
TF_ARB_FLOAT = (1<<26), // float textures
|
||||
|
||||
196
common/sound_api.h
Normal file
196
common/sound_api.h
Normal file
@@ -0,0 +1,196 @@
|
||||
/*
|
||||
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;
|
||||
|
||||
typedef struct voice_audio_info_s
|
||||
{
|
||||
uint width;
|
||||
uint samplerate;
|
||||
uint frame_size; // in samples
|
||||
} voice_audio_info_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 );
|
||||
// Voice extensions
|
||||
void (*pfnS_RawEntSamples)( int entnum, uint samples, uint rate, word width, word channels, const byte *data, int snd_vol, float attn );
|
||||
void (*pfnSND_ForceInitMouth)( int entnum );
|
||||
voice_audio_info_t (*pfnVoice_GetAudioInfo)( void );
|
||||
} 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,9 @@ 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 );
|
||||
int (*pfnVoice_StartChannel)( int samples, byte *data, int entnum );
|
||||
} 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
|
||||
@@ -444,13 +444,16 @@ qboolean AVI_Think( movie_state_t *Avi )
|
||||
|
||||
if( Avi->texture == 0 )
|
||||
{
|
||||
int cinTexture = SCR_GetCinematicTexture();
|
||||
int w = Avi->w >= 0 ? Avi->w : refState.width;
|
||||
int h = Avi->h >= 0 ? Avi->h : refState.height;
|
||||
|
||||
ref.dllFuncs.R_DrawStretchRaw( Avi->x, Avi->y, w, h, Avi->xres, Avi->yres, Avi->dst, redraw );
|
||||
if( redraw )
|
||||
ref.dllFuncs.GL_UpdateTexture( cinTexture, Avi->xres, Avi->yres, Avi->xres, Avi->yres, Avi->dst, PF_BGRA_32 );
|
||||
ref.dllFuncs.R_DrawStretchPic( Avi->x, Avi->y, w, h, 0, 0, 1, 1, cinTexture );
|
||||
}
|
||||
else if( redraw && Avi->texture > 0 )
|
||||
ref.dllFuncs.AVI_UploadRawFrame( Avi->texture, Avi->xres, Avi->yres, Avi->w, Avi->h, Avi->dst );
|
||||
ref.dllFuncs.GL_UpdateTexture( Avi->texture, Avi->xres, Avi->yres, Avi->w, Avi->h, Avi->dst, PF_BGRA_32 );
|
||||
|
||||
if( flushing && !decoded )
|
||||
return false; // probably hit an EOF
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -849,6 +849,31 @@ BEAM * GAME_EXPORT R_BeamEnts( int startEnt, int endEnt, int modelIndex, float l
|
||||
return pbeam;
|
||||
}
|
||||
|
||||
static qboolean R_BeamVisible( const vec3_t start, const vec3_t end )
|
||||
{
|
||||
vec3_t mins, maxs;
|
||||
|
||||
for( int i = 0; i < 3; i++ )
|
||||
{
|
||||
if( start[i] < end[i] )
|
||||
{
|
||||
mins[i] = start[i];
|
||||
maxs[i] = end[i];
|
||||
}
|
||||
else
|
||||
{
|
||||
mins[i] = end[i];
|
||||
maxs[i] = start[i];
|
||||
}
|
||||
|
||||
// don't let it be zero sized
|
||||
if( mins[i] == maxs[i] )
|
||||
maxs[i] += 1.0f;
|
||||
}
|
||||
|
||||
return Mod_BoxVisible( mins, maxs, ref.dllFuncs.Mod_GetCurrentVis( ));
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
R_BeamPoints
|
||||
@@ -861,7 +886,7 @@ BEAM * GAME_EXPORT R_BeamPoints( vec3_t start, vec3_t end, int modelIndex, float
|
||||
{
|
||||
BEAM *pbeam;
|
||||
|
||||
if( life != 0 && ref.dllFuncs.R_BeamCull( start, end, true ))
|
||||
if( life != 0 && !R_BeamVisible( start, end ))
|
||||
return NULL;
|
||||
|
||||
pbeam = R_BeamAlloc();
|
||||
|
||||
@@ -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 )
|
||||
|
||||
@@ -981,15 +981,8 @@ qboolean CL_AddVisibleEntity( cl_entity_t *ent, int entityType )
|
||||
if( !draw_player )
|
||||
return false;
|
||||
|
||||
if( entityType == ET_BEAM )
|
||||
{
|
||||
ref.dllFuncs.CL_AddCustomBeam( ent );
|
||||
return true;
|
||||
}
|
||||
else if( !ref.dllFuncs.R_AddEntity( ent, entityType ))
|
||||
{
|
||||
if( !ref.dllFuncs.R_AddEntity( ent, entityType ))
|
||||
return false;
|
||||
}
|
||||
|
||||
// because pTemp->entity.curstate.effects
|
||||
// is already occupied by FTENT_FLICKER
|
||||
@@ -1381,7 +1374,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
|
||||
}
|
||||
|
||||
|
||||
@@ -23,6 +23,8 @@ GNU General Public License for more details.
|
||||
#include "client.h"
|
||||
#include "const.h"
|
||||
#include "triangleapi.h"
|
||||
#include "r_studioint.h"
|
||||
#include "mod_local.h"
|
||||
#include "r_efx.h"
|
||||
#include "demo_api.h"
|
||||
#include "ivoicetweak.h"
|
||||
@@ -37,11 +39,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 +107,8 @@ 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 FWGS ext
|
||||
{ "Voice_StartChannel", (void **)&clgame.dllFuncs.pfnVoice_StartChannel }, // Xash3D FWGS ext
|
||||
};
|
||||
|
||||
static void pfnSPR_DrawHoles( int frame, int x, int y, const wrect_t *prc );
|
||||
@@ -179,7 +192,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] ),
|
||||
@@ -357,13 +376,13 @@ static void SPR_DrawGeneric( int frame, float x, float y, float width, float hei
|
||||
int w, h;
|
||||
|
||||
// assume we get sizes from image
|
||||
ref.dllFuncs.R_GetSpriteParms( &w, &h, NULL, frame, clgame.ds.pSprite );
|
||||
R_GetSpriteParms( &w, &h, NULL, frame, clgame.ds.pSprite );
|
||||
|
||||
width = w;
|
||||
height = h;
|
||||
}
|
||||
|
||||
texnum = ref.dllFuncs.R_GetSpriteTexture( clgame.ds.pSprite, frame );
|
||||
texnum = R_GetSpriteTexture( clgame.ds.pSprite, frame );
|
||||
|
||||
if( prc )
|
||||
{
|
||||
@@ -560,31 +579,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 +659,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
|
||||
@@ -1468,7 +1426,7 @@ int EXPORT pfnSPR_Frames( HSPRITE hPic )
|
||||
{
|
||||
int numFrames = 0;
|
||||
|
||||
ref.dllFuncs.R_GetSpriteParms( NULL, NULL, &numFrames, 0, CL_GetSpritePointer( hPic ));
|
||||
R_GetSpriteParms( NULL, NULL, &numFrames, 0, CL_GetSpritePointer( hPic ));
|
||||
|
||||
return numFrames;
|
||||
}
|
||||
@@ -1483,7 +1441,7 @@ static int GAME_EXPORT pfnSPR_Height( HSPRITE hPic, int frame )
|
||||
{
|
||||
int sprHeight = 0;
|
||||
|
||||
ref.dllFuncs.R_GetSpriteParms( NULL, &sprHeight, NULL, frame, CL_GetSpritePointer( hPic ));
|
||||
R_GetSpriteParms( NULL, &sprHeight, NULL, frame, CL_GetSpritePointer( hPic ));
|
||||
|
||||
return sprHeight;
|
||||
}
|
||||
@@ -1498,7 +1456,7 @@ static int GAME_EXPORT pfnSPR_Width( HSPRITE hPic, int frame )
|
||||
{
|
||||
int sprWidth = 0;
|
||||
|
||||
ref.dllFuncs.R_GetSpriteParms( &sprWidth, NULL, NULL, frame, CL_GetSpritePointer( hPic ));
|
||||
R_GetSpriteParms( &sprWidth, NULL, NULL, frame, CL_GetSpritePointer( hPic ));
|
||||
|
||||
return sprWidth;
|
||||
}
|
||||
@@ -1974,13 +1932,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;
|
||||
}
|
||||
|
||||
@@ -2218,7 +2175,7 @@ pfnGetViewModel
|
||||
|
||||
=============
|
||||
*/
|
||||
static cl_entity_t* GAME_EXPORT CL_GetViewModel( void )
|
||||
static cl_entity_t *GAME_EXPORT CL_GetViewModel( void )
|
||||
{
|
||||
return &clgame.viewent;
|
||||
}
|
||||
@@ -3369,7 +3326,7 @@ int TriSpriteTexture( model_t *pSpriteModel, int frame )
|
||||
{
|
||||
int gl_texturenum;
|
||||
|
||||
if(( gl_texturenum = ref.dllFuncs.R_GetSpriteTexture( pSpriteModel, frame )) <= 0 )
|
||||
if(( gl_texturenum = R_GetSpriteTexture( pSpriteModel, frame )) <= 0 )
|
||||
return 0;
|
||||
|
||||
ref.dllFuncs.GL_Bind( XASH_TEXTURE0, gl_texturenum );
|
||||
@@ -3974,6 +3931,69 @@ void CL_UnloadProgs( void )
|
||||
memset( &clgame, 0, sizeof( clgame ));
|
||||
}
|
||||
|
||||
static model_t *pfnStudio_Mod_ForName( const char *name, int crash )
|
||||
{
|
||||
return Mod_ForName( name, crash, false );
|
||||
}
|
||||
|
||||
static void *pfnStudio_Mod_Extradata( model_t *mod )
|
||||
{
|
||||
return Mod_StudioExtradata( mod );
|
||||
}
|
||||
|
||||
static void pfnStudio_GetAliasScale( float *x, float *y )
|
||||
{
|
||||
if( x ) *x = 1.0f;
|
||||
if( y ) *y = 1.0f;
|
||||
}
|
||||
|
||||
static float ***pfnStudio_GetAliasTransform( void )
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static model_t *pfnStudio_GetChromeSprite( void )
|
||||
{
|
||||
return cl_sprite_shell;
|
||||
}
|
||||
|
||||
static int pfnStudio_IsHardware( void )
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static engine_studio_api_t gStudioAPI =
|
||||
{
|
||||
.Mem_Calloc = Mod_Calloc,
|
||||
.Cache_Check = Mod_CacheCheck,
|
||||
.LoadCacheFile = Mod_LoadCacheFile,
|
||||
.Mod_ForName = pfnStudio_Mod_ForName,
|
||||
.Mod_Extradata = pfnStudio_Mod_Extradata,
|
||||
.GetModelByIndex = CL_ModelHandle,
|
||||
.GetCvar = pfnCVarGetPointer,
|
||||
.GetChromeSprite = pfnStudio_GetChromeSprite,
|
||||
.GetAliasScale = pfnStudio_GetAliasScale,
|
||||
.StudioGetAliasTransform = pfnStudio_GetAliasTransform,
|
||||
.GetViewEntity = CL_GetViewModel,
|
||||
.IsHardware = pfnStudio_IsHardware,
|
||||
};
|
||||
|
||||
static void CL_InitStudioAPI( void )
|
||||
{
|
||||
static r_studio_interface_t gDefaultStudioDraw;
|
||||
r_studio_interface_t *pStudioDraw;
|
||||
|
||||
if( !ref.dllFuncs.R_StudioFillAPI( &gStudioAPI, &gDefaultStudioDraw ))
|
||||
return;
|
||||
|
||||
pStudioDraw = &gDefaultStudioDraw;
|
||||
|
||||
if( clgame.dllFuncs.pfnGetStudioModelInterface )
|
||||
clgame.dllFuncs.pfnGetStudioModelInterface( STUDIO_INTERFACE_VERSION, &pStudioDraw, &gStudioAPI );
|
||||
|
||||
ref.dllFuncs.R_StudioSetDrawInterface( pStudioDraw );
|
||||
}
|
||||
|
||||
qboolean CL_LoadProgs( const char *name )
|
||||
{
|
||||
static playermove_t gpMove;
|
||||
@@ -4095,14 +4115,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
|
||||
@@ -4111,7 +4131,7 @@ qboolean CL_LoadProgs( const char *name )
|
||||
// initialize game
|
||||
clgame.dllFuncs.pfnInit();
|
||||
|
||||
ref.dllFuncs.CL_InitStudioAPI();
|
||||
CL_InitStudioAPI();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@ GNU General Public License for more details.
|
||||
|
||||
#include "common.h"
|
||||
#include "client.h"
|
||||
#include "mod_local.h"
|
||||
#include "net_encode.h"
|
||||
#include "cl_tent.h"
|
||||
#include "shake.h"
|
||||
@@ -42,7 +43,7 @@ CL_ParseViewEntity
|
||||
|
||||
==================
|
||||
*/
|
||||
void CL_ParseViewEntity( sizebuf_t *msg )
|
||||
static void CL_ParseViewEntity( sizebuf_t *msg )
|
||||
{
|
||||
cl.viewentity = MSG_ReadWord( msg );
|
||||
|
||||
@@ -161,7 +162,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 +210,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 +363,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 +617,7 @@ CL_ParseCustomization
|
||||
|
||||
==================
|
||||
*/
|
||||
void CL_ParseCustomization( sizebuf_t *msg )
|
||||
static void CL_ParseCustomization( sizebuf_t *msg )
|
||||
{
|
||||
customization_t *pExistingCustomization;
|
||||
customization_t *pList;
|
||||
@@ -704,7 +705,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 +777,7 @@ CL_ParseFileTransferFailed
|
||||
|
||||
==================
|
||||
*/
|
||||
void CL_ParseFileTransferFailed( sizebuf_t *msg )
|
||||
static void CL_ParseFileTransferFailed( sizebuf_t *msg )
|
||||
{
|
||||
const char *name = MSG_ReadString( msg );
|
||||
|
||||
@@ -796,7 +797,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 +1235,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 +1256,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 +1268,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 +1297,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 +1311,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 +1338,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 +1376,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;
|
||||
@@ -1738,6 +1739,8 @@ void CL_RegisterResources( sizebuf_t *msg, connprotocol_t proto )
|
||||
// tell rendering system we have a new set of models.
|
||||
ref.dllFuncs.R_NewMap ();
|
||||
|
||||
Mod_LoadDetailTextures( cl.worldmodel );
|
||||
|
||||
// check if this map must start from dark screen
|
||||
CL_StartDark ();
|
||||
|
||||
@@ -1898,7 +1901,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 +1915,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 +1965,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 +1994,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 +2028,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 +2122,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 +2184,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 +2360,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 +2512,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 +2524,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 +2593,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 +2615,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 +2671,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 +2688,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 +2705,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 +2718,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;
|
||||
|
||||
@@ -930,12 +930,12 @@ void CL_ParseQuakeMessage( sizebuf_t *msg )
|
||||
// record command for debugging spew on parse problem
|
||||
CL_Parse_RecordCommand( cmd, bufStart );
|
||||
|
||||
if( CL_ParseCommonMessage( msg, PROTO_QUAKE, cmd, bufStart ))
|
||||
continue;
|
||||
|
||||
// other commands
|
||||
switch( cmd )
|
||||
{
|
||||
case svc_nop:
|
||||
// this does nothing
|
||||
break;
|
||||
case svc_disconnect:
|
||||
CL_DemoCompleted ();
|
||||
break;
|
||||
@@ -947,9 +947,6 @@ void CL_ParseQuakeMessage( sizebuf_t *msg )
|
||||
if( param1 != PROTOCOL_VERSION_QUAKE )
|
||||
Host_Error( "Server is protocol %i instead of %i\n", param1, PROTOCOL_VERSION_QUAKE );
|
||||
break;
|
||||
case svc_setview:
|
||||
CL_ParseViewEntity( msg );
|
||||
break;
|
||||
case svc_sound:
|
||||
CL_ParseQuakeSound( msg );
|
||||
cl.frames[cl.parsecountmod].graphdata.sound += MSG_GetNumBytesRead( msg ) - bufStart;
|
||||
@@ -974,9 +971,6 @@ void CL_ParseQuakeMessage( sizebuf_t *msg )
|
||||
Cbuf_Execute(); // make sure any stuffed commands are done
|
||||
CL_ParseQuakeServerInfo( msg );
|
||||
break;
|
||||
case svc_lightstyle:
|
||||
CL_ParseLightStyle( msg, PROTO_QUAKE );
|
||||
break;
|
||||
case svc_updatename:
|
||||
param1 = MSG_ReadByte( msg );
|
||||
Q_strncpy( cl.players[param1].name, MSG_ReadString( msg ), sizeof( cl.players[0].name ));
|
||||
@@ -1029,8 +1023,7 @@ void CL_ParseQuakeMessage( sizebuf_t *msg )
|
||||
CL_ParseQuakeSignon( msg );
|
||||
break;
|
||||
case svc_centerprint:
|
||||
str = MSG_ReadString( msg );
|
||||
CL_DispatchUserMessage( "HudText", Q_strlen( str ) + 1, (void *)str );
|
||||
CL_HudMessage( MSG_ReadString( msg ));
|
||||
break;
|
||||
case svc_killedmonster:
|
||||
CL_DispatchQuakeMessage( "KillMonster" ); // just an event
|
||||
@@ -1041,12 +1034,6 @@ void CL_ParseQuakeMessage( sizebuf_t *msg )
|
||||
case svc_spawnstaticsound:
|
||||
CL_ParseQuakeStaticSound( msg );
|
||||
break;
|
||||
case svc_intermission:
|
||||
cl.intermission = 1;
|
||||
break;
|
||||
case svc_finale:
|
||||
CL_ParseFinaleCutscene( msg, 2 );
|
||||
break;
|
||||
case svc_cdtrack:
|
||||
param1 = MSG_ReadByte( msg );
|
||||
param1 = bound( 0, param1, MAX_CDTRACKS - 1 ); // tracknum
|
||||
@@ -1059,15 +1046,12 @@ void CL_ParseQuakeMessage( sizebuf_t *msg )
|
||||
case svc_sellscreen:
|
||||
Cmd_ExecuteString( "help" ); // open quake menu
|
||||
break;
|
||||
case svc_cutscene:
|
||||
CL_ParseFinaleCutscene( msg, 3 );
|
||||
case svc_showlmp:
|
||||
CL_ParseNehahraShowLMP( msg );
|
||||
break;
|
||||
case svc_hidelmp:
|
||||
CL_ParseNehahraHideLMP( msg );
|
||||
break;
|
||||
case svc_showlmp:
|
||||
CL_ParseNehahraShowLMP( msg );
|
||||
break;
|
||||
case svc_skybox:
|
||||
Q_strncpy( clgame.movevars.skyName, MSG_ReadString( msg ), sizeof( clgame.movevars.skyName ));
|
||||
break;
|
||||
|
||||
@@ -214,6 +214,11 @@ static void pfnAVI_StreamSound( movie_state_t *avi, int entnum, float fvol, floa
|
||||
return; // stub, use AVI_SetParm and AVI_Think to stream AVI sound
|
||||
}
|
||||
|
||||
static void pfnAVI_UploadRawFrame( int texture, int cols, int rows, int width, int height, const byte *data )
|
||||
{
|
||||
ref.dllFuncs.GL_UpdateTexture( texture, cols, rows, width, height, data, PF_BGRA_32 );
|
||||
}
|
||||
|
||||
static render_api_t gRenderAPI =
|
||||
{
|
||||
pfnRenderGetParm, // GL_RenderGetParm,
|
||||
@@ -243,7 +248,7 @@ static render_api_t gRenderAPI =
|
||||
AVI_GetVideoInfo,
|
||||
AVI_GetVideoFrameNumber,
|
||||
AVI_GetVideoFrame,
|
||||
NULL, // R_UploadStretchRaw,
|
||||
pfnAVI_UploadRawFrame, // AVI_UploadRawFrame
|
||||
AVI_FreeVideo,
|
||||
AVI_IsActive,
|
||||
pfnAVI_StreamSound,
|
||||
@@ -283,40 +288,6 @@ static render_api_t gRenderAPI =
|
||||
COM_SetRandomSeed,
|
||||
};
|
||||
|
||||
static void R_FillRenderAPIFromRef( render_api_t *to, const ref_interface_t *from )
|
||||
{
|
||||
to->GetDetailScaleForTexture = from->GetDetailScaleForTexture;
|
||||
to->GetExtraParmsForTexture = from->GetExtraParmsForTexture;
|
||||
to->GetFrameTime = from->GetFrameTime;
|
||||
to->R_SetCurrentEntity = from->R_SetCurrentEntity;
|
||||
to->R_SetCurrentModel = from->R_SetCurrentModel;
|
||||
to->GL_FindTexture = from->GL_FindTexture;
|
||||
to->GL_TextureName = from->GL_TextureName;
|
||||
to->GL_TextureData = from->GL_TextureData;
|
||||
to->GL_LoadTexture = from->GL_LoadTexture;
|
||||
to->GL_CreateTexture = from->GL_CreateTexture;
|
||||
to->GL_LoadTextureArray = from->GL_LoadTextureArray;
|
||||
to->GL_CreateTextureArray = from->GL_CreateTextureArray;
|
||||
to->GL_FreeTexture = from->GL_FreeTexture;
|
||||
to->DrawSingleDecal = from->DrawSingleDecal;
|
||||
to->R_DecalSetupVerts = from->R_DecalSetupVerts;
|
||||
to->R_EntityRemoveDecals = from->R_EntityRemoveDecals;
|
||||
to->AVI_UploadRawFrame = from->AVI_UploadRawFrame;
|
||||
to->GL_Bind = from->GL_Bind;
|
||||
to->GL_SelectTexture = from->GL_SelectTexture;
|
||||
to->GL_LoadTextureMatrix = from->GL_LoadTextureMatrix;
|
||||
to->GL_TexMatrixIdentity = from->GL_TexMatrixIdentity;
|
||||
to->GL_CleanUpTextureUnits = from->GL_CleanUpTextureUnits;
|
||||
to->GL_TexGen = from->GL_TexGen;
|
||||
to->GL_TextureTarget = from->GL_TextureTarget;
|
||||
to->GL_TexCoordArrayMode = from->GL_TexCoordArrayMode;
|
||||
to->GL_UpdateTexSize = from->GL_UpdateTexSize;
|
||||
to->GL_DrawParticles = from->GL_DrawParticles;
|
||||
to->LightVec = from->LightVec;
|
||||
to->StudioGetTexture = from->StudioGetTexture;
|
||||
to->GL_GetProcAddress = from->R_GetProcAddress;
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
R_InitRenderAPI
|
||||
@@ -329,8 +300,15 @@ qboolean R_InitRenderAPI( void )
|
||||
// make sure what render functions is cleared
|
||||
memset( &clgame.drawFuncs, 0, sizeof( clgame.drawFuncs ));
|
||||
|
||||
// fill missing functions from renderer
|
||||
R_FillRenderAPIFromRef( &gRenderAPI, &ref.dllFuncs );
|
||||
gRenderAPI.GetDetailScaleForTexture = ref.dllFuncs.R_GetDetailScaleForTexture;
|
||||
gRenderAPI.GL_FindTexture = ref.dllFuncs.GL_FindTexture;
|
||||
gRenderAPI.GL_TextureName = ref.dllFuncs.GL_TextureName;
|
||||
gRenderAPI.GL_TextureData = ref.dllFuncs.GL_TextureData;
|
||||
gRenderAPI.GL_LoadTexture = ref.dllFuncs.GL_LoadTexture;
|
||||
gRenderAPI.GL_FreeTexture = ref.dllFuncs.GL_FreeTexture;
|
||||
gRenderAPI.GL_Bind = ref.dllFuncs.GL_Bind;
|
||||
|
||||
ref.dllFuncs.R_FillRenderAPI( &gRenderAPI );
|
||||
|
||||
if( clgame.dllFuncs.pfnGetRenderInterface )
|
||||
{
|
||||
|
||||
@@ -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 )
|
||||
|
||||
360
engine/client/cl_sprite.c
Normal file
360
engine/client/cl_sprite.c
Normal file
@@ -0,0 +1,360 @@
|
||||
/*
|
||||
cl_sprite.c - sprite loading
|
||||
Copyright (C) 2010 Uncle Mike
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include "common.h"
|
||||
#include "client.h"
|
||||
#include "sprite.h"
|
||||
#include "ref_common.h"
|
||||
|
||||
static char sprite_name[MAX_QPATH];
|
||||
static char group_suffix[8];
|
||||
static uint r_texFlags = 0;
|
||||
static int sprite_version;
|
||||
|
||||
/*
|
||||
================
|
||||
R_GetSpriteFrame
|
||||
|
||||
assume pModel is valid
|
||||
================
|
||||
*/
|
||||
mspriteframe_t *R_GetSpriteFrame( const model_t *pModel, int frame, float yaw )
|
||||
{
|
||||
msprite_t *psprite;
|
||||
mspritegroup_t *pspritegroup;
|
||||
mspriteframe_t *pspriteframe = NULL;
|
||||
float *pintervals, fullinterval;
|
||||
int i, numframes;
|
||||
float targettime;
|
||||
|
||||
if( !pModel )
|
||||
return NULL;
|
||||
|
||||
psprite = pModel->cache.data;
|
||||
|
||||
if( frame < 0 )
|
||||
{
|
||||
frame = 0;
|
||||
}
|
||||
else if( frame >= psprite->numframes )
|
||||
{
|
||||
if( frame > psprite->numframes )
|
||||
Con_Printf( S_WARN "%s: no such frame %d (%s)\n", __func__, frame, pModel->name );
|
||||
frame = psprite->numframes - 1;
|
||||
}
|
||||
|
||||
if( psprite->frames[frame].type == SPR_SINGLE )
|
||||
{
|
||||
pspriteframe = psprite->frames[frame].frameptr;
|
||||
}
|
||||
else if( psprite->frames[frame].type == SPR_GROUP )
|
||||
{
|
||||
pspritegroup = (mspritegroup_t *)psprite->frames[frame].frameptr;
|
||||
pintervals = pspritegroup->intervals;
|
||||
numframes = pspritegroup->numframes;
|
||||
fullinterval = pintervals[numframes - 1];
|
||||
|
||||
// when loading in Mod_LoadSpriteGroup, we guaranteed all interval values
|
||||
// are positive, so we don't have to worry about division by zero
|
||||
targettime = cl.time - ((int)( cl.time / fullinterval )) * fullinterval;
|
||||
|
||||
for( i = 0; i < ( numframes - 1 ); i++ )
|
||||
{
|
||||
if( pintervals[i] > targettime )
|
||||
break;
|
||||
}
|
||||
pspriteframe = pspritegroup->frames[i];
|
||||
}
|
||||
else if( psprite->frames[frame].type == FRAME_ANGLED )
|
||||
{
|
||||
int angleframe = (int)( Q_rint(( refState.viewangles[1] - yaw + 45.0f ) / 360 * 8 ) - 4 ) & 7;
|
||||
|
||||
// e.g. doom-style sprite monsters
|
||||
pspritegroup = (mspritegroup_t *)psprite->frames[frame].frameptr;
|
||||
pspriteframe = pspritegroup->frames[angleframe];
|
||||
}
|
||||
|
||||
return pspriteframe;
|
||||
}
|
||||
|
||||
void R_GetSpriteParms( int *frameWidth, int *frameHeight, int *numFrames, int currentFrame, const model_t *pSprite )
|
||||
{
|
||||
mspriteframe_t *pFrame;
|
||||
|
||||
if( !pSprite || pSprite->type != mod_sprite )
|
||||
return;
|
||||
|
||||
pFrame = R_GetSpriteFrame( pSprite, currentFrame, 0.0f );
|
||||
|
||||
if( frameWidth )
|
||||
*frameWidth = pFrame->width;
|
||||
if( frameHeight )
|
||||
*frameHeight = pFrame->height;
|
||||
if( numFrames )
|
||||
*numFrames = pSprite->numframes;
|
||||
}
|
||||
|
||||
int R_GetSpriteTexture( const model_t *m_pSpriteModel, int frame )
|
||||
{
|
||||
if( !m_pSpriteModel || m_pSpriteModel->type != mod_sprite || !m_pSpriteModel->cache.data )
|
||||
return 0;
|
||||
|
||||
return R_GetSpriteFrame( m_pSpriteModel, frame, 0.0f )->gl_texturenum;
|
||||
}
|
||||
|
||||
static void Mod_SpriteTextureReplacementReport( const char *modelname, int gl_texturenum, const char *foundpath )
|
||||
{
|
||||
if( host_allow_materials.value != 2.0f )
|
||||
return;
|
||||
|
||||
if( gl_texturenum > 0 )
|
||||
Con_Printf( "Looking for %s tex replacement..." S_GREEN "OK (%s)\n", modelname, foundpath );
|
||||
else if( gl_texturenum < 0 )
|
||||
Con_Printf( "Looking for %s tex replacement..." S_YELLOW "MISS (%s)\n", modelname, foundpath );
|
||||
else
|
||||
Con_Printf( "Looking for %s tex replacement..." S_RED "FAIL (%s)\n", modelname, foundpath );
|
||||
}
|
||||
|
||||
static qboolean Mod_SpriteSearchForTextureReplacement( char *out, size_t size, const char *modelname, const char *fmt, ... )
|
||||
{
|
||||
va_list ap;
|
||||
int ret;
|
||||
|
||||
va_start( ap, fmt );
|
||||
ret = Q_vsnprintf( out, size, fmt, ap );
|
||||
va_end( ap );
|
||||
|
||||
if( ret < 0 )
|
||||
{
|
||||
Mod_SpriteTextureReplacementReport( modelname, -1, "overflow" );
|
||||
return false;
|
||||
}
|
||||
|
||||
if( FS_FileExists( out, false ))
|
||||
return true;
|
||||
|
||||
Mod_SpriteTextureReplacementReport( modelname, -1, out );
|
||||
return false;
|
||||
}
|
||||
|
||||
static const byte *Mod_SpriteLoadFrame( model_t *mod, const void *pin, mspriteframe_t **ppframe, int num )
|
||||
{
|
||||
dspriteframe_t pinframe;
|
||||
mspriteframe_t *pspriteframe;
|
||||
int gl_texturenum = 0;
|
||||
char texname[128];
|
||||
int bytes = 1;
|
||||
|
||||
memcpy( &pinframe, pin, sizeof( dspriteframe_t ));
|
||||
|
||||
if( sprite_version == SPRITE_VERSION_32 )
|
||||
bytes = 4;
|
||||
|
||||
// build unique frame name
|
||||
if( FBitSet( mod->flags, MODEL_CLIENT )) // it's a HUD sprite
|
||||
{
|
||||
Q_snprintf( texname, sizeof( texname ), "#HUD/%s(%s:%i%i).spr", sprite_name, group_suffix, num / 10, num % 10 );
|
||||
gl_texturenum = ref.dllFuncs.GL_LoadTexture( texname, pin, pinframe.width * pinframe.height * bytes, r_texFlags );
|
||||
}
|
||||
else
|
||||
{
|
||||
// partial HD-textures support
|
||||
if( Mod_AllowMaterials( ))
|
||||
{
|
||||
if( Mod_SpriteSearchForTextureReplacement( texname, sizeof( texname ), sprite_name, "materials/%s/%s%i%i.tga", sprite_name, group_suffix, num / 10, num % 10 ))
|
||||
{
|
||||
gl_texturenum = ref.dllFuncs.GL_LoadTexture( texname, NULL, 0, r_texFlags );
|
||||
Mod_SpriteTextureReplacementReport( sprite_name, gl_texturenum, texname );
|
||||
}
|
||||
}
|
||||
|
||||
if( gl_texturenum == 0 )
|
||||
{
|
||||
Q_snprintf( texname, sizeof( texname ), "#%s(%s:%i%i).spr", sprite_name, group_suffix, num / 10, num % 10 );
|
||||
gl_texturenum = ref.dllFuncs.GL_LoadTexture( texname, pin, pinframe.width * pinframe.height * bytes, r_texFlags );
|
||||
}
|
||||
}
|
||||
|
||||
// setup frame description
|
||||
pspriteframe = Mem_Malloc( mod->mempool, sizeof( mspriteframe_t ));
|
||||
pspriteframe->width = pinframe.width;
|
||||
pspriteframe->height = pinframe.height;
|
||||
pspriteframe->up = pinframe.origin[1];
|
||||
pspriteframe->left = pinframe.origin[0];
|
||||
pspriteframe->down = pinframe.origin[1] - pinframe.height;
|
||||
pspriteframe->right = pinframe.width + pinframe.origin[0];
|
||||
pspriteframe->gl_texturenum = gl_texturenum;
|
||||
*ppframe = pspriteframe;
|
||||
|
||||
return (const byte *)pin + sizeof( dspriteframe_t ) + pinframe.width * pinframe.height * bytes;
|
||||
}
|
||||
|
||||
static const byte *Mod_SpriteLoadGroup( model_t *mod, const void *pin, mspriteframe_t **ppframe, int framenum )
|
||||
{
|
||||
const dspritegroup_t *pingroup;
|
||||
mspritegroup_t *pspritegroup;
|
||||
const dspriteinterval_t *pin_intervals;
|
||||
float *poutintervals;
|
||||
int i, groupsize, numframes;
|
||||
const void *ptemp;
|
||||
|
||||
pingroup = (const dspritegroup_t *)pin;
|
||||
numframes = pingroup->numframes;
|
||||
|
||||
groupsize = sizeof( mspritegroup_t ) + ( numframes - 1 ) * sizeof( pspritegroup->frames[0] );
|
||||
pspritegroup = Mem_Calloc( mod->mempool, groupsize );
|
||||
pspritegroup->numframes = numframes;
|
||||
|
||||
*ppframe = (mspriteframe_t *)pspritegroup;
|
||||
pin_intervals = (const dspriteinterval_t *)( pingroup + 1 );
|
||||
poutintervals = Mem_Calloc( mod->mempool, numframes * sizeof( float ));
|
||||
pspritegroup->intervals = poutintervals;
|
||||
|
||||
for( i = 0; i < numframes; i++ )
|
||||
{
|
||||
*poutintervals = pin_intervals->interval;
|
||||
if( *poutintervals <= 0.0f )
|
||||
*poutintervals = 1.0f; // set error value
|
||||
poutintervals++;
|
||||
pin_intervals++;
|
||||
}
|
||||
|
||||
ptemp = (const void *)pin_intervals;
|
||||
for( i = 0; i < numframes; i++ )
|
||||
{
|
||||
ptemp = Mod_SpriteLoadFrame( mod, ptemp, &pspritegroup->frames[i], framenum * 10 + i );
|
||||
}
|
||||
|
||||
return ptemp;
|
||||
}
|
||||
|
||||
void Mod_SpriteLoadTextures( model_t *mod, const void *buffer )
|
||||
{
|
||||
const dsprite_t *pin = buffer;
|
||||
const short *numi = NULL;
|
||||
const byte *pframetype;
|
||||
msprite_t *psprite = mod->cache.data;
|
||||
int i;
|
||||
|
||||
if( pin->version == SPRITE_VERSION_Q1 || pin->version == SPRITE_VERSION_32 )
|
||||
numi = NULL;
|
||||
else if( pin->version == SPRITE_VERSION_HL )
|
||||
numi = (const short *)((const byte *)buffer + sizeof( dsprite_hl_t ));
|
||||
|
||||
r_texFlags = mod->numtexinfo;
|
||||
sprite_version = pin->version;
|
||||
Q_strncpy( sprite_name, mod->name, sizeof( sprite_name ));
|
||||
COM_StripExtension( sprite_name );
|
||||
|
||||
if( numi == NULL )
|
||||
{
|
||||
rgbdata_t *pal;
|
||||
|
||||
pal = FS_LoadImage( "#id.pal", (byte *)&i, 768 );
|
||||
pframetype = (const byte *)buffer + sizeof( dsprite_q1_t );
|
||||
FS_FreeImage( pal );
|
||||
}
|
||||
else if( *numi <= 256 )
|
||||
{
|
||||
const byte *src = (const byte *)( numi + 1 );
|
||||
rgbdata_t *pal;
|
||||
size_t pal_bytes = *numi * 3;
|
||||
|
||||
// install palette
|
||||
switch( psprite->texFormat )
|
||||
{
|
||||
case SPR_INDEXALPHA:
|
||||
pal = FS_LoadImage( "#gradient.pal", src, pal_bytes );
|
||||
break;
|
||||
case SPR_ALPHTEST:
|
||||
pal = FS_LoadImage( "#masked.pal", src, pal_bytes );
|
||||
break;
|
||||
default:
|
||||
pal = FS_LoadImage( "#texgamma.pal", src, pal_bytes );
|
||||
break;
|
||||
}
|
||||
|
||||
pframetype = (const byte *)( src + pal_bytes );
|
||||
FS_FreeImage( pal );
|
||||
}
|
||||
else
|
||||
{
|
||||
Con_DPrintf( S_ERROR "%s has wrong number of palette colors %i (should be less or equal than 256)\n", mod->name, *numi );
|
||||
return;
|
||||
}
|
||||
|
||||
if( mod->numframes < 1 )
|
||||
return;
|
||||
|
||||
for( i = 0; i < mod->numframes; i++ )
|
||||
{
|
||||
frametype_t frametype;
|
||||
dframetype_t dframetype;
|
||||
|
||||
memcpy( &dframetype, pframetype, sizeof( dframetype ));
|
||||
frametype = dframetype.type;
|
||||
psprite->frames[i].type = (spriteframetype_t)frametype;
|
||||
|
||||
switch( frametype )
|
||||
{
|
||||
case FRAME_SINGLE:
|
||||
Q_strncpy( group_suffix, "frame", sizeof( group_suffix ));
|
||||
pframetype = Mod_SpriteLoadFrame( mod, pframetype + sizeof( dframetype_t ), &psprite->frames[i].frameptr, i );
|
||||
break;
|
||||
case FRAME_GROUP:
|
||||
Q_strncpy( group_suffix, "group", sizeof( group_suffix ));
|
||||
pframetype = Mod_SpriteLoadGroup( mod, pframetype + sizeof( dframetype_t ), &psprite->frames[i].frameptr, i );
|
||||
break;
|
||||
case FRAME_ANGLED:
|
||||
Q_strncpy( group_suffix, "angle", sizeof( group_suffix ));
|
||||
pframetype = Mod_SpriteLoadGroup( mod, pframetype + sizeof( dframetype_t ), &psprite->frames[i].frameptr, i );
|
||||
break;
|
||||
}
|
||||
if( pframetype == NULL )
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Mod_SpriteUnloadTextures( void *data )
|
||||
{
|
||||
msprite_t *psprite = data;
|
||||
int i;
|
||||
|
||||
if( !data )
|
||||
return;
|
||||
|
||||
// release all textures
|
||||
for( i = 0; i < psprite->numframes; i++ )
|
||||
{
|
||||
if( !psprite->frames[i].frameptr )
|
||||
continue;
|
||||
|
||||
if( psprite->frames[i].type == SPR_SINGLE )
|
||||
{
|
||||
ref.dllFuncs.GL_FreeTexture( psprite->frames[i].frameptr->gl_texturenum );
|
||||
}
|
||||
else
|
||||
{
|
||||
mspritegroup_t *pspritegroup = (mspritegroup_t *)psprite->frames[i].frameptr;
|
||||
int j;
|
||||
|
||||
for( j = 0; j < pspritegroup->numframes; j++ )
|
||||
{
|
||||
if( pspritegroup->frames[j] )
|
||||
ref.dllFuncs.GL_FreeTexture( pspritegroup->frames[j]->gl_texturenum );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -25,6 +25,7 @@ AVI PLAYING
|
||||
*/
|
||||
|
||||
static movie_state_t *cin_state;
|
||||
static int cin_texture;
|
||||
|
||||
/*
|
||||
==================
|
||||
@@ -281,6 +282,12 @@ void SCR_InitCinematic( void )
|
||||
{
|
||||
AVI_Initailize ();
|
||||
cin_state = AVI_GetState( CIN_MAIN );
|
||||
cin_texture = ref.dllFuncs.GL_CreateTexture( "*cintexture", 64, 64, NULL, TF_NOMIPMAP|TF_CLAMP );
|
||||
}
|
||||
|
||||
int SCR_GetCinematicTexture( void )
|
||||
{
|
||||
return cin_texture;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -360,6 +360,29 @@ qboolean V_PreRender( void )
|
||||
|
||||
//============================================================================
|
||||
|
||||
/*
|
||||
====================
|
||||
V_ApplyRefUnderwater
|
||||
|
||||
apply underwater fov effect
|
||||
====================
|
||||
*/
|
||||
static void V_ApplyRefUnderwater( ref_viewpass_t *rvp )
|
||||
{
|
||||
if( !FBitSet( rvp->flags, RF_DRAW_CUBEMAP|RF_DRAW_OVERVIEW ))
|
||||
return;
|
||||
|
||||
if( !FBitSet( host.features, ENGINE_QUAKE_COMPATIBLE ))
|
||||
return;
|
||||
|
||||
if( cl.local.waterlevel < 3 )
|
||||
return;
|
||||
|
||||
rvp->fov_x = atan( tan( DEG2RAD( rvp->fov_x ) / 2 ) * ( 0.97f + sin( cl.time * 1.5f ) * 0.03f )) * 2 / (M_PI_F / 180.0f);
|
||||
rvp->fov_y = atan( tan( DEG2RAD( rvp->fov_y ) / 2 ) * ( 1.03f - sin( cl.time * 1.5f ) * 0.03f )) * 2 / (M_PI_F / 180.0f);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
V_RenderView
|
||||
@@ -389,6 +412,7 @@ void V_RenderView( void )
|
||||
clgame.dllFuncs.pfnCalcRefdef( &rp );
|
||||
V_GetRefParams( &rp, &rvp );
|
||||
V_RefApplyOverview( &rvp );
|
||||
V_ApplyRefUnderwater( &rvp );
|
||||
|
||||
if( viewnum == 0 && FBitSet( rvp.flags, RF_ONLY_CLIENTDRAW ))
|
||||
{
|
||||
@@ -535,6 +559,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 );
|
||||
@@ -869,7 +874,6 @@ struct msurface_s *pfnTraceSurface( int ground, float *vstart, float *vend );
|
||||
void CL_EnableScissor( scissor_state_t *scissor, int x, int y, int width, int height );
|
||||
void CL_DisableScissor( scissor_state_t *scissor );
|
||||
qboolean CL_Scissor( const scissor_state_t *scissor, float *x, float *y, float *width, float *height, float *u0, float *v0, float *u1, float *v1 );
|
||||
|
||||
static inline cl_entity_t *CL_EDICT_NUM( int index )
|
||||
{
|
||||
if( unlikely( !clgame.entities )) // not in game yet
|
||||
@@ -923,45 +927,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 );
|
||||
|
||||
@@ -989,6 +971,13 @@ void SCR_DrawPos( void );
|
||||
void SCR_DrawEnts( void );
|
||||
void SCR_DrawUserCmd( void );
|
||||
|
||||
//
|
||||
// cl_sprite.c
|
||||
//
|
||||
mspriteframe_t *R_GetSpriteFrame( const model_t *pModel, int frame, float yaw );
|
||||
void R_GetSpriteParms( int *frameWidth, int *frameHeight, int *numFrames, int currentFrame, const model_t *pSprite );
|
||||
int R_GetSpriteTexture( const model_t *m_pSpriteModel, int frame );
|
||||
|
||||
//
|
||||
// cl_netgraph.c
|
||||
//
|
||||
@@ -1083,6 +1072,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 );
|
||||
@@ -1222,6 +1215,7 @@ void SteamBroker_TerminateGameConnection( void );
|
||||
// cl_video.c
|
||||
//
|
||||
void SCR_InitCinematic( void );
|
||||
int SCR_GetCinematicTexture( void );
|
||||
void SCR_FreeCinematic( void );
|
||||
qboolean SCR_PlayCinematic( const char *name );
|
||||
qboolean SCR_DrawCinematic( 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();
|
||||
@@ -2164,8 +2164,11 @@ void Con_RunConsole( void )
|
||||
con.vislines = con.showlines;
|
||||
}
|
||||
|
||||
if( FBitSet( con_charset.flags|con_fontscale.flags|con_fontnum.flags|cl_charset.flags|con_oldfont.flags, FCVAR_CHANGED ))
|
||||
if( FBitSet( con_charset.flags|con_fontscale.flags|con_fontnum.flags|cl_charset.flags|con_oldfont.flags, FCVAR_CHANGED ))
|
||||
{
|
||||
if( con_fontscale.value < 1.0f )
|
||||
Cvar_DirectSet( &con_fontscale, "1" );
|
||||
|
||||
// update codepage parameters
|
||||
if( !Q_stricmp( con_charset.string, "cp1251" ))
|
||||
{
|
||||
|
||||
@@ -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,18 @@ 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_gyro_pitch_deadzone, "0.5", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "gyroscope pitch axis deadzone (deg/s)" );
|
||||
static CVAR_DEFINE_AUTO( joy_gyro_yaw_deadzone, "0.5", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "gyroscope yaw axis deadzone (deg/s)" );
|
||||
static CVAR_DEFINE_AUTO( joy_gyro_roll_deadzone, "0.5", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "gyroscope roll axis deadzone (deg/s)" );
|
||||
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 +240,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 +271,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 +297,8 @@ Gyroscope events
|
||||
*/
|
||||
void Joy_GyroEvent( vec3_t data )
|
||||
{
|
||||
|
||||
VectorCopy( data, joy_gyro_speed );
|
||||
VectorCopy( data, joy_gyro_speed_display );
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -290,7 +310,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 +328,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 +337,218 @@ 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 );
|
||||
|
||||
if( fabs( pitch_speed ) < joy_gyro_pitch_deadzone.value )
|
||||
pitch_speed = 0.0f;
|
||||
if( fabs( yaw_speed ) < joy_gyro_yaw_deadzone.value )
|
||||
yaw_speed = 0.0f;
|
||||
if( fabs( roll_speed ) < joy_gyro_roll_deadzone.value )
|
||||
roll_speed = 0.0f;
|
||||
|
||||
*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" };
|
||||
static const convar_t *const gyro_deadzone[3] =
|
||||
{
|
||||
&joy_gyro_pitch_deadzone,
|
||||
&joy_gyro_yaw_deadzone,
|
||||
&joy_gyro_roll_deadzone,
|
||||
};
|
||||
|
||||
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] );
|
||||
|
||||
// deadzone in deg/s; display scale is +-5 rad/s
|
||||
float fthreshold = gyro_deadzone[i]->value * ( M_PI / 180.0f ) / 5.0f;
|
||||
fthreshold = bound( 0.0f, fthreshold, 1.0f );
|
||||
|
||||
if( fthreshold > 0.0f )
|
||||
{
|
||||
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 );
|
||||
|
||||
// gyro doesn't have 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 +597,16 @@ 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_gyro_pitch_deadzone );
|
||||
Cvar_RegisterVariable( &joy_gyro_yaw_deadzone );
|
||||
Cvar_RegisterVariable( &joy_gyro_roll_deadzone );
|
||||
|
||||
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 );
|
||||
|
||||
|
||||
@@ -287,13 +287,6 @@ static entity_state_t *R_StudioGetPlayerState( int index )
|
||||
return &cl.frames[cl.parsecountmod].playerstate[index];
|
||||
}
|
||||
|
||||
static int pfnGetStudioModelInterface( int version, struct r_studio_interface_s **ppinterface, struct engine_studio_api_s *pstudio )
|
||||
{
|
||||
return clgame.dllFuncs.pfnGetStudioModelInterface ?
|
||||
clgame.dllFuncs.pfnGetStudioModelInterface( version, ppinterface, pstudio ) :
|
||||
0;
|
||||
}
|
||||
|
||||
static const bpc_desc_t *pfnImage_GetPFDesc( int idx )
|
||||
{
|
||||
return &PFDesc[idx];
|
||||
@@ -329,11 +322,6 @@ static qboolean R_Init_Video_( ref_graphic_apis_t type )
|
||||
return R_Init_Video( type );
|
||||
}
|
||||
|
||||
static mleaf_t *pfnMod_PointInLeaf( const vec3_t p, mnode_t *node )
|
||||
{
|
||||
// FIXME: get rid of this on next RefAPI update
|
||||
return Mod_PointInLeaf( p, node, cl.models[1] );
|
||||
}
|
||||
|
||||
static const ref_api_t gEngfuncs =
|
||||
{
|
||||
@@ -375,7 +363,7 @@ static const ref_api_t gEngfuncs =
|
||||
|
||||
Mod_SampleSizeForFace,
|
||||
Mod_BoxVisible,
|
||||
pfnMod_PointInLeaf,
|
||||
Mod_PointInLeaf,
|
||||
R_DrawWorldHull,
|
||||
R_DrawModelHull,
|
||||
|
||||
@@ -411,7 +399,6 @@ static const ref_api_t gEngfuncs =
|
||||
Mod_CacheCheck,
|
||||
Mod_LoadCacheFile,
|
||||
Mod_Calloc,
|
||||
pfnGetStudioModelInterface,
|
||||
|
||||
_Mem_AllocPool,
|
||||
_Mem_FreePool,
|
||||
@@ -465,6 +452,7 @@ static const ref_api_t gEngfuncs =
|
||||
&g_fsapi,
|
||||
|
||||
R_GetWindowHandle,
|
||||
R_GetSpriteFrame,
|
||||
};
|
||||
|
||||
static void R_UnloadProgs( void )
|
||||
@@ -487,28 +475,82 @@ static void R_UnloadProgs( void )
|
||||
memset( &ref.dllFuncs, 0, sizeof( ref.dllFuncs ));
|
||||
}
|
||||
|
||||
static void CL_FillTriAPIFromRef( triangleapi_t *dst, const ref_interface_t *src )
|
||||
static void CL_FillTriAPI( triangleapi_t *dst )
|
||||
{
|
||||
dst->version = TRI_API_VERSION;
|
||||
dst->Begin = src->Begin;
|
||||
dst->RenderMode = TriRenderMode;
|
||||
dst->End = src->End;
|
||||
dst->Color4f = TriColor4f;
|
||||
dst->Color4ub = TriColor4ub;
|
||||
dst->TexCoord2f = src->TexCoord2f;
|
||||
dst->Vertex3f = src->Vertex3f;
|
||||
dst->Vertex3fv = src->Vertex3fv;
|
||||
dst->Brightness = TriBrightness;
|
||||
dst->CullFace = TriCullFace;
|
||||
dst->SpriteTexture = TriSpriteTexture;
|
||||
dst->WorldToScreen = TriWorldToScreen;
|
||||
dst->Fog = src->Fog;
|
||||
dst->ScreenToWorld = src->ScreenToWorld;
|
||||
dst->GetMatrix = src->GetMatrix;
|
||||
dst->BoxInPVS = TriBoxInPVS;
|
||||
dst->LightAtPoint = TriLightAtPoint;
|
||||
dst->Color4fRendermode = TriColor4fRendermode;
|
||||
dst->FogParams = src->FogParams;
|
||||
dst->Begin = ref.dllFuncs.Begin;
|
||||
dst->End = ref.dllFuncs.End;
|
||||
dst->Vertex3f = ref.dllFuncs.Vertex3f;
|
||||
dst->Vertex3fv = ref.dllFuncs.Vertex3fv;
|
||||
|
||||
ref.dllFuncs.R_FillTriAPI( dst );
|
||||
}
|
||||
|
||||
static const byte dottexture[8][8] =
|
||||
{
|
||||
{ 0, 1, 1, 0, 0, 0, 0, 0 },
|
||||
{ 1, 1, 1, 1, 0, 0, 0, 0 },
|
||||
{ 1, 1, 1, 1, 0, 0, 0, 0 },
|
||||
{ 0, 1, 1, 0, 0, 0, 0, 0 },
|
||||
{ 0, 0, 0, 0, 0, 0, 0, 0 },
|
||||
{ 0, 0, 0, 0, 0, 0, 0, 0 },
|
||||
{ 0, 0, 0, 0, 0, 0, 0, 0 },
|
||||
{ 0, 0, 0, 0, 0, 0, 0, 0 },
|
||||
};
|
||||
|
||||
static void R_CreateBuiltinTextures( void )
|
||||
{
|
||||
uint data4x4[16];
|
||||
uint data16x16[256];
|
||||
byte particle[8 * 8 * 4];
|
||||
int x, y;
|
||||
|
||||
// default checkerboard
|
||||
for( y = 0; y < 16; y++ )
|
||||
{
|
||||
for( x = 0; x < 16; x++ )
|
||||
{
|
||||
if(( y < 8 ) ^ ( x < 8 ))
|
||||
data16x16[y * 16 + x] = 0xFFFF00FF;
|
||||
else
|
||||
data16x16[y * 16 + x] = 0xFF000000;
|
||||
}
|
||||
}
|
||||
ref.dllFuncs.GL_CreateTexture( REF_DEFAULT_TEXTURE, 16, 16, data16x16, TF_COLORMAP );
|
||||
|
||||
// particle texture
|
||||
memset( particle, 0, sizeof( particle ));
|
||||
for( x = 0; x < 8; x++ )
|
||||
{
|
||||
for( y = 0; y < 8; y++ )
|
||||
{
|
||||
if( dottexture[x][y] )
|
||||
particle[( y * 8 + x ) * 4 + 3] = 255;
|
||||
}
|
||||
}
|
||||
ref.dllFuncs.GL_CreateTexture( REF_PARTICLE_TEXTURE, 8, 8, particle, TF_CLAMP );
|
||||
|
||||
// solid colors
|
||||
memset( data4x4, 0xFF, sizeof( data4x4 ));
|
||||
ref.dllFuncs.GL_CreateTexture( REF_WHITE_TEXTURE, 4, 4, data4x4, TF_COLORMAP );
|
||||
|
||||
for( x = 0; x < 16; x++ )
|
||||
data4x4[x] = 0xFF7F7F7F;
|
||||
ref.dllFuncs.GL_CreateTexture( REF_GRAY_TEXTURE, 4, 4, data4x4, TF_COLORMAP );
|
||||
|
||||
for( x = 0; x < 16; x++ )
|
||||
data4x4[x] = 0xFF000000;
|
||||
ref.dllFuncs.GL_CreateTexture( REF_BLACK_TEXTURE, 4, 4, data4x4, TF_COLORMAP );
|
||||
}
|
||||
|
||||
static qboolean R_LoadProgs( const char *name )
|
||||
@@ -554,8 +596,8 @@ static qboolean R_LoadProgs( const char *name )
|
||||
Cvar_FullSet( "host_refloaded", "1", FCVAR_READ_ONLY );
|
||||
ref.initialized = true;
|
||||
|
||||
// initialize TriAPI callbacks
|
||||
CL_FillTriAPIFromRef( &gTriApi, &ref.dllFuncs );
|
||||
R_CreateBuiltinTextures();
|
||||
CL_FillTriAPI( &gTriApi );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
@@ -285,7 +285,7 @@ static int S_MixNormalChannels( portable_samplepair_t *dst, int end, int rate )
|
||||
// if it's also not looping, free it
|
||||
if( ch->leftvol < 8 && ch->rightvol < 8 )
|
||||
{
|
||||
if( !FBitSet( sc->flags, SOUND_LOOPED ) || !ch->use_loop )
|
||||
if( !FBitSet( sc->flags, SOUND_LOOPED ) || !FBitSet( ch->flags, FL_CHAN_USE_LOOP ))
|
||||
{
|
||||
if( ch->inauduble_free_time == 0.0f )
|
||||
ch->inauduble_free_time = host.realtime + MAX_CHANNEL_INAUDIBLE_TIME;
|
||||
@@ -308,9 +308,9 @@ static int S_MixNormalChannels( portable_samplepair_t *dst, int end, int rate )
|
||||
if( ent != NULL )
|
||||
{
|
||||
if( sc->width == 1 )
|
||||
SND_MoveMouth8( &ent->mouth, ch->sample, sc, num_samples, ch->use_loop );
|
||||
SND_MoveMouth8( &ent->mouth, ch->sample, sc, num_samples, FBitSet( ch->flags, FL_CHAN_USE_LOOP ));
|
||||
else
|
||||
SND_MoveMouth16( &ent->mouth, ch->sample, sc, num_samples, ch->use_loop );
|
||||
SND_MoveMouth16( &ent->mouth, ch->sample, sc, num_samples, FBitSet( ch->flags, FL_CHAN_USE_LOOP ));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -318,18 +318,18 @@ static int S_MixNormalChannels( portable_samplepair_t *dst, int end, int rate )
|
||||
|
||||
num_mixed_channels++;
|
||||
|
||||
if( ch->is_sentence )
|
||||
if( ch->words )
|
||||
{
|
||||
VOX_MixChannelToBuffer( dst, ch, num_samples, rate, pitch );
|
||||
|
||||
if( ch->sentence_finished )
|
||||
if( FBitSet( ch->flags, FL_CHAN_SENTENCE_FINISHED ))
|
||||
S_FreeChannel( ch );
|
||||
}
|
||||
else
|
||||
{
|
||||
S_MixChannelToBuffer( dst, ch, num_samples, rate, pitch, 0, 0 );
|
||||
|
||||
if( ch->finished )
|
||||
if( FBitSet( ch->flags, FL_CHAN_FINISHED ))
|
||||
S_FreeChannel( ch );
|
||||
}
|
||||
}
|
||||
@@ -375,7 +375,7 @@ static int S_MixNormalChannelsToRoombuffer( int end, int count )
|
||||
// until there is no real usecase, let's keep it simple
|
||||
int num_mixed_channels = S_MixNormalChannels( roombuffer, end, SOUND_11k );
|
||||
|
||||
if( dma.format.speed >= SOUND_22k )
|
||||
if( snd.format.speed >= SOUND_22k )
|
||||
{
|
||||
if( num_mixed_channels > 0 )
|
||||
S_UpsampleBuffer( roombuffer, count / ( SOUND_22k / SOUND_11k ));
|
||||
@@ -383,7 +383,7 @@ static int S_MixNormalChannelsToRoombuffer( int end, int count )
|
||||
num_mixed_channels += S_MixNormalChannels( roombuffer, end, SOUND_22k );
|
||||
}
|
||||
|
||||
if( dma.format.speed >= SOUND_44k )
|
||||
if( snd.format.speed >= SOUND_44k )
|
||||
{
|
||||
if( num_mixed_channels > 0 )
|
||||
S_UpsampleBuffer( roombuffer, count / ( SOUND_44k / SOUND_22k ));
|
||||
@@ -402,10 +402,10 @@ static int S_MixRawChannels( int end )
|
||||
return 0;
|
||||
|
||||
// paint in the raw channels
|
||||
for( size_t i = 0; i < ARRAYSIZE( raw_channels ); i++ )
|
||||
for( size_t i = 0; i < snd.max_raw_channels; i++ )
|
||||
{
|
||||
// copy from the streaming sound source
|
||||
rawchan_t *ch = raw_channels[i];
|
||||
rawchan_t *ch = snd.raw_channels[i];
|
||||
|
||||
if( !ch )
|
||||
continue;
|
||||
@@ -434,7 +434,7 @@ static int S_MixRawChannels( int end )
|
||||
uint stop = (end < ch->s_rawend) ? end : ch->s_rawend;
|
||||
const uint mask = ch->max_samples - 1;
|
||||
|
||||
for( size_t i = 0, j = paintedtime; j < stop; i++, j++ )
|
||||
for( size_t i = 0, j = snd.paintedtime; j < stop; i++, j++ )
|
||||
{
|
||||
pbuf[i].left += ( ch->rawsamples[j & mask].left * ch->leftvol ) >> 8;
|
||||
pbuf[i].right += ( ch->rawsamples[j & mask].right * ch->rightvol ) >> 8;
|
||||
@@ -443,8 +443,8 @@ static int S_MixRawChannels( int end )
|
||||
if( ch->entnum > 0 )
|
||||
{
|
||||
cl_entity_t *ent = CL_GetEntityByIndex( ch->entnum );
|
||||
int pos = paintedtime & ( ch->max_samples - 1 );
|
||||
int count = bound( 0, ch->max_samples - pos, stop - paintedtime );
|
||||
int pos = snd.paintedtime & ( ch->max_samples - 1 );
|
||||
int count = bound( 0, ch->max_samples - pos, stop - snd.paintedtime );
|
||||
|
||||
if( ent )
|
||||
SND_MoveMouthRaw( &ent->mouth, &ch->rawsamples[pos], count );
|
||||
@@ -486,8 +486,8 @@ static void S_WriteLinearBlastStereo16( short *snd_out, const int *snd_p, size_t
|
||||
static void S_TransferPaintBuffer( const portable_samplepair_t *src, int endtime )
|
||||
{
|
||||
const int *snd_p = (const int *)src;
|
||||
const int sampleMask = ((dma.samples >> 1) - 1);
|
||||
int lpaintedtime = paintedtime;
|
||||
const int sampleMask = ((snd.samples >> 1) - 1);
|
||||
int lpaintedtime = snd.paintedtime;
|
||||
|
||||
SNDDMA_BeginPainting ();
|
||||
|
||||
@@ -496,9 +496,9 @@ static void S_TransferPaintBuffer( const portable_samplepair_t *src, int endtime
|
||||
// handle recirculating buffer issues
|
||||
int lpos = lpaintedtime & sampleMask;
|
||||
|
||||
short *snd_out = (short *)dma.buffer + (lpos << 1);
|
||||
short *snd_out = (short *)snd.buffer + (lpos << 1);
|
||||
|
||||
int snd_linear_count = (dma.samples>>1) - lpos;
|
||||
int snd_linear_count = (snd.samples>>1) - lpos;
|
||||
if( lpaintedtime + snd_linear_count > endtime )
|
||||
snd_linear_count = endtime - lpaintedtime;
|
||||
|
||||
@@ -526,14 +526,14 @@ void S_PaintChannels( int endtime )
|
||||
{
|
||||
int gain = S_GetMasterVolume() * 256;
|
||||
|
||||
while( paintedtime < endtime )
|
||||
while( snd.paintedtime < endtime )
|
||||
{
|
||||
// if paintbuffer is smaller than DMA buffer
|
||||
int end = endtime;
|
||||
if( end - paintedtime > PAINTBUFFER_SIZE )
|
||||
end = paintedtime + PAINTBUFFER_SIZE;
|
||||
if( end - snd.paintedtime > PAINTBUFFER_SIZE )
|
||||
end = snd.paintedtime + PAINTBUFFER_SIZE;
|
||||
|
||||
const int num_samples = end - paintedtime;
|
||||
const int num_samples = end - snd.paintedtime;
|
||||
|
||||
S_ClearBuffers( num_samples );
|
||||
|
||||
@@ -550,6 +550,6 @@ void S_PaintChannels( int endtime )
|
||||
|
||||
// transfer out according to DMA format
|
||||
S_TransferPaintBuffer( paintbuffer, end );
|
||||
paintedtime = end;
|
||||
snd.paintedtime = end;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 );
|
||||
@@ -253,7 +253,7 @@ void S_StreamBackgroundTrack( void )
|
||||
{
|
||||
// add to raw buffer
|
||||
int music_vol = (int)(255.0f * S_GetMusicVolume());
|
||||
S_RawEntSamples( S_RAW_SOUND_BACKGROUNDTRACK, fileSamples, info->rate, info->width, info->channels, raw, music_vol );
|
||||
S_RawEntSamples( S_RAW_SOUND_BACKGROUNDTRACK, fileSamples, info->rate, info->width, info->channels, raw, music_vol, ATTN_NONE );
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -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,110 +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;
|
||||
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
|
||||
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
|
||||
|
||||
vec3_t origin; // only use if fixed_origin is set
|
||||
float dist_mult; // distance multiplier (attenuation/clipK)
|
||||
|
||||
int entnum; // entity soundsource
|
||||
int entchannel; // sound channel (CHAN_STREAM, CHAN_VOICE, etc.)
|
||||
short master_vol; // 0-255 master volume
|
||||
short leftvol; // 0-255 left volume
|
||||
short rightvol; // 0-255 right volume
|
||||
short basePitch; // base pitch percent (100% is normal pitch playback)
|
||||
byte use_loop : 1; // don't loop default and local sounds
|
||||
byte staticsound : 1; // use origin instead of fetching entnum's origin
|
||||
byte localsound : 1; // it's a local menu sound (not looped, not paused)
|
||||
byte is_sentence : 1; // bit indicating vox sentence
|
||||
byte sentence_finished : 1; // if set, finished playing sentence
|
||||
byte finished : 1; // if set, finished playing single word
|
||||
byte word_index;
|
||||
// HACKHACK: count when this channel became inaudible
|
||||
// to not free it when it could be respatialized soon
|
||||
#define MAX_CHANNEL_INAUDIBLE_TIME 0.1f
|
||||
float inauduble_free_time;
|
||||
|
||||
double sample;
|
||||
double forced_end;
|
||||
wavdata_t *data;
|
||||
voxword_t words[CVOXWORDMAX];
|
||||
} 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)
|
||||
@@ -150,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;
|
||||
@@ -222,7 +111,7 @@ int S_GetCurrentDynamicSounds( soundlist_t *pout, int size );
|
||||
sfx_t *S_GetSfxByHandle( sound_t handle );
|
||||
rawchan_t *S_FindRawChannel( int entnum, qboolean create );
|
||||
uint S_RawSamplesStereo( portable_samplepair_t *rawsamples, uint rawend, uint max_samples, uint samples, uint rate, word width, word channels, const byte *data );
|
||||
void S_RawEntSamples( int entnum, uint samples, uint rate, word width, word channels, const byte *data, int snd_vol );
|
||||
void S_RawEntSamples( int entnum, uint samples, uint rate, word width, word channels, const byte *data, int snd_vol, float attn );
|
||||
void S_StopSound( int entnum, int channel, const char *soundname );
|
||||
void S_UpdateFrame( struct ref_viewpass_s *rvp );
|
||||
void S_StopAllSounds( qboolean ambient );
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -939,8 +939,14 @@ Feed the decoded data to engine sound subsystem
|
||||
*/
|
||||
static void Voice_StartChannel( uint samples, byte *data, int entnum )
|
||||
{
|
||||
if( clgame.dllFuncs.pfnVoice_StartChannel != NULL )
|
||||
{
|
||||
if( clgame.dllFuncs.pfnVoice_StartChannel( samples, data, entnum ))
|
||||
return;
|
||||
}
|
||||
|
||||
SND_ForceInitMouth( entnum );
|
||||
S_RawEntSamples( entnum, samples, voice.samplerate, voice.width, VOICE_PCM_CHANNELS, data, bound( 0, 255 * voice_scale.value, 255 ));
|
||||
S_RawEntSamples( entnum, samples, voice.samplerate, voice.width, VOICE_PCM_CHANNELS, data, bound( 0, 255 * voice_scale.value, 255 ), ATTN_NONE );
|
||||
Voice_Status( entnum, true );
|
||||
}
|
||||
|
||||
@@ -1194,3 +1200,13 @@ qboolean Voice_Init( const char *pszCodecName, int quality, qboolean preinit )
|
||||
voice.initialized = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
voice_audio_info_t Voice_GetAudioInfo( void )
|
||||
{
|
||||
voice_audio_info_t info;
|
||||
|
||||
info.width = voice.width;
|
||||
info.samplerate = voice.samplerate;
|
||||
info.frame_size = voice.frame_size;
|
||||
return info;
|
||||
}
|
||||
|
||||
@@ -131,5 +131,6 @@ void Voice_Disconnect( void );
|
||||
void Voice_AddIncomingData( int ent, const byte *data, uint size, uint frames );
|
||||
void Voice_StopChannel( int entnum );
|
||||
void Voice_LoopbackAck( void ); // sends VOICE_LOOPBACK_INDEX to client, gets disabled on timeout
|
||||
voice_audio_info_t Voice_GetAudioInfo( void );
|
||||
|
||||
#endif // VOICE_H
|
||||
|
||||
@@ -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" );
|
||||
|
||||
@@ -381,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__ )
|
||||
|
||||
@@ -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 );
|
||||
|
||||
|
||||
@@ -320,6 +320,11 @@ static qboolean FS_DetermineReadOnlyRootDirectory( char *out, size_t size )
|
||||
return true;
|
||||
}
|
||||
|
||||
#if XASH_IOS
|
||||
Q_strncpy( out, IOS_GetExecDir(), size );
|
||||
return true;
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -173,6 +173,9 @@ static MALLOC_LIKE( FS_FreeImage, 1 ) rgbdata_t *ImagePack( const char *name )
|
||||
|
||||
Image_ReportLookupsCount( name );
|
||||
|
||||
if( Image_CheckFlag( IL_LOAD_PLAYER_DECAL ))
|
||||
SetBits( image.flags, IMAGE_PLAYERDECAL );
|
||||
|
||||
// clear any force flags
|
||||
image.force_flags = 0;
|
||||
|
||||
|
||||
@@ -250,6 +250,8 @@ qboolean Image_LoadSPR( const char *name, const byte *buffer, fs_offset_t filesi
|
||||
SetBits( image.flags, IMAGE_ONEBIT_ALPHA );
|
||||
// intentionally fallthrough
|
||||
case LUMP_GRADIENT:
|
||||
SetBits( image.flags, IMAGE_HAS_ALPHA );
|
||||
break;
|
||||
case LUMP_QUAKE1:
|
||||
SetBits( image.flags, IMAGE_HAS_ALPHA );
|
||||
break;
|
||||
|
||||
@@ -2014,7 +2014,7 @@ static void Mod_SetupSubmodels( model_t *mod, dbspmodel_t *bmod )
|
||||
SetBits( mod->flags, MODEL_HAS_ORIGIN );
|
||||
#ifdef HACKS_RELATED_HLMODS
|
||||
// c2a1 doesn't have origin brush it's just placed at center of the level
|
||||
if( !Q_stricmp( name, "maps/c2a1.bsp" ) && ( i == 11 ))
|
||||
if( i == 11 && !Q_stricmp( name, "maps/c2a1.bsp" ))
|
||||
SetBits( mod->flags, MODEL_HAS_ORIGIN );
|
||||
#endif
|
||||
}
|
||||
@@ -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 );
|
||||
@@ -2989,6 +2989,105 @@ static void Mod_LoadTextures( model_t *mod, dbspmodel_t *bmod )
|
||||
Mod_SequenceAllAnimatedTextures( mod );
|
||||
}
|
||||
|
||||
#if !XASH_DEDICATED
|
||||
static void Mod_ParseDetailTextures( model_t *mod )
|
||||
{
|
||||
byte *afile;
|
||||
char *pfile;
|
||||
string token, texname;
|
||||
string detail_texname;
|
||||
string detail_path;
|
||||
float xScale, yScale;
|
||||
texture_t *tex;
|
||||
int i;
|
||||
|
||||
string filepath;
|
||||
|
||||
Q_strncpy( filepath, mod->name, sizeof( filepath ));
|
||||
COM_StripExtension( filepath );
|
||||
Q_strncat( filepath, "_detail.txt", sizeof( filepath ));
|
||||
|
||||
afile = FS_LoadFile( filepath, NULL, false );
|
||||
if( !afile )
|
||||
return;
|
||||
|
||||
pfile = (char *)afile;
|
||||
|
||||
// format: 'texturename' 'detailtexture' 'xScale' 'yScale'
|
||||
while(( pfile = COM_ParseFile( pfile, token, sizeof( token ))) != NULL )
|
||||
{
|
||||
texname[0] = '\0';
|
||||
detail_texname[0] = '\0';
|
||||
|
||||
// read texname
|
||||
if( token[0] == '{' )
|
||||
{
|
||||
// NOTE: COM_ParseFile handled some symbols seperately
|
||||
// this code will be fix it
|
||||
pfile = COM_ParseFile( pfile, token, sizeof( token ));
|
||||
Q_snprintf( texname, sizeof( texname ), "{%s", token );
|
||||
}
|
||||
else
|
||||
Q_strncpy( texname, token, sizeof( texname ));
|
||||
|
||||
// read detailtexture name
|
||||
pfile = COM_ParseFile( pfile, token, sizeof( token ));
|
||||
Q_strncpy( detail_texname, token, sizeof( detail_texname ));
|
||||
|
||||
// trying the scales or '{'
|
||||
pfile = COM_ParseFile( pfile, token, sizeof( token ));
|
||||
|
||||
// read second part of detailtexture name
|
||||
if( token[0] == '{' )
|
||||
{
|
||||
Q_strncat( detail_texname, token, sizeof( detail_texname ));
|
||||
pfile = COM_ParseFile( pfile, token, sizeof( token )); // read scales
|
||||
Q_strncat( detail_texname, token, sizeof( detail_texname ));
|
||||
pfile = COM_ParseFile( pfile, token, sizeof( token )); // parse scales
|
||||
}
|
||||
|
||||
Q_snprintf( detail_path, sizeof( detail_path ), "gfx/%s", detail_texname );
|
||||
|
||||
// read scales
|
||||
xScale = Q_atof( token );
|
||||
|
||||
pfile = COM_ParseFile( pfile, token, sizeof( token ));
|
||||
yScale = Q_atof( token );
|
||||
|
||||
if( xScale <= 0.0f || yScale <= 0.0f )
|
||||
continue;
|
||||
|
||||
// search for existing texture and uploading detail texture
|
||||
for( i = 0; i < mod->numtextures; i++ )
|
||||
{
|
||||
tex = mod->textures[i];
|
||||
|
||||
if( Q_stricmp( tex->name, texname ))
|
||||
continue;
|
||||
|
||||
tex->dt_texturenum = ref.dllFuncs.GL_LoadTexture( detail_path, NULL, 0, TF_FORCE_COLOR|TF_NOFLIP_TGA );
|
||||
|
||||
if( tex->dt_texturenum )
|
||||
ref.dllFuncs.R_SetDetailScaleForTexture( tex->gl_texturenum, xScale, yScale );
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Mem_Free( afile );
|
||||
}
|
||||
|
||||
void Mod_LoadDetailTextures( model_t *mod )
|
||||
{
|
||||
convar_t *r_detailtextures = Cvar_FindVar( "r_detailtextures" );
|
||||
|
||||
if( !r_detailtextures || !r_detailtextures->value )
|
||||
return;
|
||||
|
||||
Mod_ParseDetailTextures( mod );
|
||||
}
|
||||
#endif // !XASH_DEDICATED
|
||||
|
||||
/*
|
||||
=================
|
||||
Mod_LoadTexInfo
|
||||
@@ -3599,6 +3698,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 +3896,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 +3981,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?
|
||||
{
|
||||
|
||||
@@ -156,6 +156,7 @@ model_t *Mod_ForName( const char *name, qboolean crash, qboolean trackCRC );
|
||||
qboolean Mod_ValidateCRC( const char *name, uint32_t crc );
|
||||
void Mod_NeedCRC( const char *name, qboolean needCRC );
|
||||
void Mod_FreeUnused( void );
|
||||
void Mod_LoadDetailTextures( model_t *mod );
|
||||
|
||||
//
|
||||
// mod_alias.c
|
||||
@@ -197,6 +198,8 @@ void Mod_ClearStudioCache( void );
|
||||
// mod_sprite.c
|
||||
//
|
||||
void Mod_LoadSpriteModel( model_t *mod, const void *buffer, size_t buffersize, qboolean *loaded );
|
||||
#endif
|
||||
void Mod_SpriteLoadTextures( model_t *mod, const void *buffer );
|
||||
void Mod_SpriteUnloadTextures( void *data );
|
||||
|
||||
#endif
|
||||
#endif//MOD_LOCAL_H
|
||||
|
||||
@@ -17,9 +17,6 @@ GNU General Public License for more details.
|
||||
#include "common.h"
|
||||
#include "sprite.h"
|
||||
#include "studio.h"
|
||||
#if !XASH_DEDICATED
|
||||
#include "ref_common.h"
|
||||
#endif // XASH_DEDICATED
|
||||
#include "mod_local.h"
|
||||
|
||||
|
||||
@@ -147,4 +144,8 @@ void Mod_LoadSpriteModel( model_t *mod, const void *buffer, size_t buffersize, q
|
||||
psprite->numframes = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
#if !XASH_DEDICATED
|
||||
Mod_SpriteLoadTextures( mod, buffer );
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -88,6 +88,22 @@ static void Mod_Modellist_f( void )
|
||||
Con_Printf( "\n" );
|
||||
}
|
||||
|
||||
static void Mod_UnloadRenderData( model_t *mod )
|
||||
{
|
||||
#if !XASH_DEDICATED
|
||||
switch( mod->type )
|
||||
{
|
||||
case mod_sprite:
|
||||
Mod_SpriteUnloadTextures( mod->cache.data );
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
ref.dllFuncs.Mod_ProcessRenderData( mod, false, NULL, 0 );
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
Mod_FreeUserData
|
||||
@@ -107,12 +123,10 @@ static void Mod_FreeUserData( model_t *mod )
|
||||
svgame.physFuncs.Mod_ProcessUserData( mod, false, NULL );
|
||||
}
|
||||
}
|
||||
#if !XASH_DEDICATED
|
||||
else
|
||||
{
|
||||
ref.dllFuncs.Mod_ProcessRenderData( mod, false, NULL, 0 );
|
||||
Mod_UnloadRenderData( mod );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -168,6 +168,8 @@ typedef struct physics_interface_s
|
||||
void *(*SV_HullForBsp)( edict_t *ent, const float *mins, const float *maxs, float *offset );
|
||||
// handle player custom think function
|
||||
int (*SV_PlayerThink)( edict_t *ent, float frametime, double time );
|
||||
// voice data
|
||||
qboolean (*pfnVoiceData)( int client, uint frames, uint size, qboolean loopback, const char *received );
|
||||
} physics_interface_t;
|
||||
|
||||
#endif//PHYSINT_H
|
||||
|
||||
@@ -1,282 +0,0 @@
|
||||
//
|
||||
// AsyncSocket.h
|
||||
//
|
||||
// This class is in the public domain.
|
||||
// Originally created by Dustin Voss on Wed Jan 29 2003.
|
||||
// Updated and maintained by Deusty Designs and the Mac development community.
|
||||
//
|
||||
// http://code.google.com/p/cocoaasyncsocket/
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@class AsyncSocket;
|
||||
@class AsyncReadPacket;
|
||||
@class AsyncWritePacket;
|
||||
|
||||
extern NSString *const AsyncSocketException;
|
||||
extern NSString *const AsyncSocketErrorDomain;
|
||||
|
||||
enum AsyncSocketError
|
||||
{
|
||||
AsyncSocketCFSocketError = kCFSocketError, // From CFSocketError enum.
|
||||
AsyncSocketNoError = 0, // Never used.
|
||||
AsyncSocketCanceledError, // onSocketWillConnect: returned NO.
|
||||
AsyncSocketReadMaxedOutError, // Reached set maxLength without completing
|
||||
AsyncSocketReadTimeoutError,
|
||||
AsyncSocketWriteTimeoutError
|
||||
};
|
||||
typedef enum AsyncSocketError AsyncSocketError;
|
||||
|
||||
@interface NSObject (AsyncSocketDelegate)
|
||||
|
||||
/**
|
||||
* In the event of an error, the socket is closed.
|
||||
* You may call "unreadData" during this call-back to get the last bit of data off the socket.
|
||||
* When connecting, this delegate method may be called
|
||||
* before"onSocket:didAcceptNewSocket:" or "onSocket:didConnectToHost:".
|
||||
**/
|
||||
- (void)onSocket:(AsyncSocket *)sock willDisconnectWithError:(NSError *)err;
|
||||
|
||||
/**
|
||||
* Called when a socket disconnects with or without error. If you want to release a socket after it disconnects,
|
||||
* do so here. It is not safe to do that during "onSocket:willDisconnectWithError:".
|
||||
**/
|
||||
- (void)onSocketDidDisconnect:(AsyncSocket *)sock;
|
||||
|
||||
/**
|
||||
* Called when a socket accepts a connection. Another socket is spawned to handle it. The new socket will have
|
||||
* the same delegate and will call "onSocket:didConnectToHost:port:".
|
||||
**/
|
||||
- (void)onSocket:(AsyncSocket *)sock didAcceptNewSocket:(AsyncSocket *)newSocket;
|
||||
|
||||
/**
|
||||
* Called when a new socket is spawned to handle a connection. This method should return the run-loop of the
|
||||
* thread on which the new socket and its delegate should operate. If omitted, [NSRunLoop currentRunLoop] is used.
|
||||
**/
|
||||
- (NSRunLoop *)onSocket:(AsyncSocket *)sock wantsRunLoopForNewSocket:(AsyncSocket *)newSocket;
|
||||
|
||||
/**
|
||||
* Called when a socket is about to connect. This method should return YES to continue, or NO to abort.
|
||||
* If aborted, will result in AsyncSocketCanceledError.
|
||||
*
|
||||
* If the connectToHost:onPort:error: method was called, the delegate will be able to access and configure the
|
||||
* CFReadStream and CFWriteStream as desired prior to connection.
|
||||
*
|
||||
* If the connectToAddress:error: method was called, the delegate will be able to access and configure the
|
||||
* CFSocket and CFSocketNativeHandle (BSD socket) as desired prior to connection. You will be able to access and
|
||||
* configure the CFReadStream and CFWriteStream in the onSocket:didConnectToHost:port: method.
|
||||
**/
|
||||
- (BOOL)onSocketWillConnect:(AsyncSocket *)sock;
|
||||
|
||||
|
||||
/**
|
||||
* Called when a read stream is closed. This method should return YES, if you
|
||||
* want to close the socket of the stream, or NO then the socket won't be closed.
|
||||
* This was added for the workaround to solve the issue of firefox and os-x finder,
|
||||
* which seem to close a read stream for ftp's list command.
|
||||
* 'iosftpserver' returns YES only when the socket is for FTP::STORE command.
|
||||
**/
|
||||
- (BOOL)onReadStreamEnded:(AsyncSocket *)sock;
|
||||
|
||||
/**
|
||||
* Called when a socket connects and is ready for reading and writing.
|
||||
* The host parameter will be an IP address, not a DNS name.
|
||||
**/
|
||||
- (void)onSocket:(AsyncSocket *)sock didConnectToHost:(NSString *)host port:(UInt16)port;
|
||||
|
||||
/**
|
||||
* Called when a socket has completed reading the requested data into memory.
|
||||
* Not called if there is an error.
|
||||
**/
|
||||
- (void)onSocket:(AsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag;
|
||||
|
||||
/**
|
||||
* Called when a socket has read in data, but has not yet completed the read.
|
||||
* This would occur if using readToData: or readToLength: methods.
|
||||
* It may be used to for things such as updating progress bars.
|
||||
**/
|
||||
- (void)onSocket:(AsyncSocket *)sock didReadPartialDataOfLength:(CFIndex)partialLength tag:(long)tag;
|
||||
|
||||
/**
|
||||
* Called when a socket has completed writing the requested data. Not called if there is an error.
|
||||
**/
|
||||
- (void)onSocket:(AsyncSocket *)sock didWriteDataWithTag:(long)tag;
|
||||
|
||||
@end
|
||||
|
||||
@interface AsyncSocket : NSObject
|
||||
{
|
||||
CFSocketRef theSocket; // IPv4 accept or connect socket
|
||||
CFSocketRef theSocket6; // IPv6 accept or connect socket
|
||||
CFReadStreamRef theReadStream;
|
||||
CFWriteStreamRef theWriteStream;
|
||||
|
||||
CFRunLoopSourceRef theSource; // For theSocket
|
||||
CFRunLoopSourceRef theSource6; // For theSocket6
|
||||
CFRunLoopRef theRunLoop;
|
||||
CFSocketContext theContext;
|
||||
|
||||
NSMutableArray *theReadQueue;
|
||||
AsyncReadPacket *theCurrentRead;
|
||||
NSTimer *theReadTimer;
|
||||
NSMutableData *partialReadBuffer;
|
||||
|
||||
NSMutableArray *theWriteQueue;
|
||||
AsyncWritePacket *theCurrentWrite;
|
||||
NSTimer *theWriteTimer;
|
||||
|
||||
id theDelegate;
|
||||
Byte theFlags;
|
||||
|
||||
long theUserData;
|
||||
}
|
||||
|
||||
- (id)init;
|
||||
- (id)initWithDelegate:(id)delegate;
|
||||
- (id)initWithDelegate:(id)delegate userData:(long)userData;
|
||||
|
||||
/* String representation is long but has no "\n". */
|
||||
- (NSString *)description;
|
||||
|
||||
/**
|
||||
* Use "canSafelySetDelegate" to see if there is any pending business (reads and writes) with the current delegate
|
||||
* before changing it. It is, of course, safe to change the delegate before connecting or accepting connections.
|
||||
**/
|
||||
- (id)delegate;
|
||||
- (BOOL)canSafelySetDelegate;
|
||||
- (void)setDelegate:(id)delegate;
|
||||
|
||||
/* User data can be a long, or an id or void * cast to a long. */
|
||||
- (long)userData;
|
||||
- (void)setUserData:(long)userData;
|
||||
|
||||
/* Don't use these to read or write. And don't close them, either! */
|
||||
- (CFSocketRef)getCFSocket;
|
||||
- (CFReadStreamRef)getCFReadStream;
|
||||
- (CFWriteStreamRef)getCFWriteStream;
|
||||
|
||||
/**
|
||||
* Once one of these methods is called, the AsyncSocket instance is locked in, and the rest can't be called without
|
||||
* disconnecting the socket first. If the attempt times out or fails, these methods either return NO or
|
||||
* call "onSocket:willDisconnectWithError:" and "onSockedDidDisconnect:".
|
||||
**/
|
||||
- (BOOL)acceptOnPort:(UInt16)port error:(NSError **)errPtr;
|
||||
- (BOOL)acceptOnAddress:(NSString *)hostaddr port:(UInt16)port error:(NSError **)errPtr;
|
||||
- (BOOL)connectToHost:(NSString *)hostname onPort:(UInt16)port error:(NSError **)errPtr;
|
||||
- (BOOL)connectToAddress:(NSData *)remoteAddr error:(NSError **)errPtr;
|
||||
|
||||
/**
|
||||
* Disconnects immediately. Any pending reads or writes are dropped.
|
||||
**/
|
||||
- (void)disconnect;
|
||||
|
||||
/**
|
||||
* Disconnects after all pending writes have completed.
|
||||
* After calling this, the read and write methods (including "readDataWithTimeout:tag:") will do nothing.
|
||||
* The socket will disconnect even if there are still pending reads.
|
||||
**/
|
||||
- (void)disconnectAfterWriting;
|
||||
|
||||
/* Returns YES if the socket and streams are open, connected, and ready for reading and writing. */
|
||||
- (BOOL)isConnected;
|
||||
|
||||
/**
|
||||
* Returns the local or remote host and port to which this socket is connected, or nil and 0 if not connected.
|
||||
* The host will be an IP address.
|
||||
**/
|
||||
- (NSString *)connectedHost;
|
||||
- (UInt16)connectedPort;
|
||||
|
||||
- (NSString *)localHost;
|
||||
- (UInt16)localPort;
|
||||
|
||||
- (BOOL)isIPv4;
|
||||
- (BOOL)isIPv6;
|
||||
|
||||
// The readData and writeData methods won't block. To not time out, use a negative time interval.
|
||||
// If they time out, "onSocket:disconnectWithError:" is called. The tag is for your convenience.
|
||||
// You can use it as an array index, step number, state id, pointer, etc., just like the socket's user data.
|
||||
|
||||
/**
|
||||
* This will read a certain number of bytes into memory, and call the delegate method when those bytes have been read.
|
||||
* If there is an error, partially read data is lost.
|
||||
* If the length is 0, this method does nothing and the delegate is not called.
|
||||
**/
|
||||
- (void)readDataToLength:(CFIndex)length withTimeout:(NSTimeInterval)timeout tag:(long)tag;
|
||||
|
||||
/**
|
||||
* This reads bytes until (and including) the passed "data" parameter, which acts as a separator.
|
||||
* The bytes and the separator are returned by the delegate method.
|
||||
*
|
||||
* If you pass nil or zero-length data as the "data" parameter,
|
||||
* the method will do nothing, and the delegate will not be called.
|
||||
*
|
||||
* To read a line from the socket, use the line separator (e.g. CRLF for HTTP, see below) as the "data" parameter.
|
||||
* Note that this method is not character-set aware, so if a separator can occur naturally as part of the encoding for
|
||||
* a character, the read will prematurely end.
|
||||
**/
|
||||
- (void)readDataToData:(NSData *)data withTimeout:(NSTimeInterval)timeout tag:(long)tag;
|
||||
|
||||
/**
|
||||
* Same as readDataToData:withTimeout:tag, with the additional restriction that the amount of data read
|
||||
* may not surpass the given maxLength (specified in bytes).
|
||||
*
|
||||
* If you pass a maxLength parameter that is less than the length of the data parameter,
|
||||
* the method will do nothing, and the delegate will not be called.
|
||||
*
|
||||
* If the max length is surpassed, it is treated the same as a timeout - the socket is closed.
|
||||
*
|
||||
* Pass -1 as maxLength if no length restriction is desired, or simply use the readDataToData:withTimeout:tag method.
|
||||
**/
|
||||
- (void)readDataToData:(NSData *)data withTimeout:(NSTimeInterval)timeout maxLength:(CFIndex)length tag:(long)tag;
|
||||
|
||||
/**
|
||||
* Reads the first available bytes that become available on the socket.
|
||||
**/
|
||||
- (void)readDataWithTimeout:(NSTimeInterval)timeout tag:(long)tag;
|
||||
|
||||
/* Writes data to the socket, and calls the delegate when finished.
|
||||
*
|
||||
* If you pass in nil or zero-length data, this method does nothing and the delegate will not be called.
|
||||
**/
|
||||
- (void)writeData:(NSData *)data withTimeout:(NSTimeInterval)timeout tag:(long)tag;
|
||||
|
||||
/**
|
||||
* Returns progress of current read or write, from 0.0 to 1.0, or NaN if no read/write (use isnan() to check).
|
||||
* "tag", "done" and "total" will be filled in if they aren't NULL.
|
||||
**/
|
||||
- (float)progressOfReadReturningTag:(long *)tag bytesDone:(CFIndex *)done total:(CFIndex *)total;
|
||||
- (float)progressOfWriteReturningTag:(long *)tag bytesDone:(CFIndex *)done total:(CFIndex *)total;
|
||||
|
||||
/**
|
||||
* For handling readDataToData requests, data is necessarily read from the socket in small increments.
|
||||
* The performance can be improved by allowing AsyncSocket to read larger chunks at a time and
|
||||
* store any overflow in a small internal buffer.
|
||||
* This is termed pre-buffering, as some data may be read for you before you ask for it.
|
||||
* If you use readDataToData a lot, enabling pre-buffering may offer a small performance improvement.
|
||||
*
|
||||
* Pre-buffering is disabled by default. You must explicitly enable it to turn it on.
|
||||
*
|
||||
* Note: If your protocol negotiates upgrades to TLS (as opposed to using TLS from the start), you should
|
||||
* consider how, if at all, pre-buffering could affect the TLS negotiation sequence.
|
||||
* This is because TLS runs atop TCP, and requires sending/receiving a TLS handshake over the TCP socket.
|
||||
* If the negotiation sequence is poorly designed, pre-buffering could potentially pre-read part of the TLS handshake,
|
||||
* thus causing TLS to fail. In almost all cases, especially when implementing a formalized protocol, this will never
|
||||
* be a hazard.
|
||||
**/
|
||||
- (void)enablePreBuffering;
|
||||
|
||||
/**
|
||||
* In the event of an error, this method may be called during onSocket:willDisconnectWithError: to read
|
||||
* any data that's left on the socket.
|
||||
**/
|
||||
- (NSData *)unreadData;
|
||||
|
||||
/* A few common line separators, for use with "readDataToData:withTimeout:tag:". */
|
||||
+ (NSData *)CRLFData; // 0x0D0A
|
||||
+ (NSData *)CRData; // 0x0D
|
||||
+ (NSData *)LFData; // 0x0A
|
||||
+ (NSData *)ZeroData; // 0x00
|
||||
|
||||
@end
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,129 +0,0 @@
|
||||
/*
|
||||
iosFtpServer
|
||||
Copyright (C) 2008 Richard Dearlove ( monsta )
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
#import "AsyncSocket.h"
|
||||
|
||||
#import "FtpDataConnection.h"
|
||||
#import "FtpDefines.h"
|
||||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
|
||||
|
||||
@class FtpServer;
|
||||
|
||||
@interface FtpConnection : NSObject {
|
||||
AsyncSocket *connectionSocket; // Socket for this particular connection
|
||||
FtpServer *server; // pointer to Server object
|
||||
|
||||
AsyncSocket *dataListeningSocket; // Socket to listen for a data connection to spawn on <-- think this is now redundant
|
||||
AsyncSocket *dataSocket; // duplicates the listening socket - remove listening socket from code when working - which seems to be the case.
|
||||
|
||||
FtpDataConnection *dataConnection; // instance handling spawned data connection socket
|
||||
|
||||
NSArray *msgComponents; // The Message rcvd broken into an array
|
||||
UInt16 dataPort;
|
||||
int transferMode;
|
||||
NSMutableArray *queuedData;
|
||||
|
||||
NSString *currentUser; // The current user for this connection
|
||||
NSString *currentDir; // The current directory for this connection
|
||||
NSString *currentFile; // File that is about to be uploaded
|
||||
NSFileHandle *currentFileHandle; // File handle of what to save
|
||||
|
||||
NSString *rnfrFilename; // rnfr
|
||||
|
||||
|
||||
}
|
||||
|
||||
-(id)initWithAsyncSocket:(AsyncSocket*)newSocket forServer:(id)myServer ;
|
||||
#pragma mark STATE
|
||||
|
||||
@property(readwrite)int transferMode;
|
||||
|
||||
@property(readwrite, retain ) NSString *currentFile;
|
||||
@property(readwrite, retain ) NSString *currentDir;
|
||||
@property(readwrite, retain ) NSString *rnfrFilename;
|
||||
|
||||
-(NSString*)connectionAddress;
|
||||
|
||||
|
||||
#pragma mark ASYNCSOCKET DATACONN
|
||||
|
||||
-(BOOL)openDataSocket:(int)portNumber;
|
||||
-(int)choosePasvDataPort;
|
||||
|
||||
|
||||
-(BOOL)onSocketWillConnect:(AsyncSocket *)sock;
|
||||
-(void)onSocket:(AsyncSocket *)sock didAcceptNewSocket:(AsyncSocket *)newSocket;
|
||||
|
||||
#pragma mark ASYNCSOCKET FTPCLIENT CONNECTION
|
||||
-(void)onSocket:(AsyncSocket*)sock didReadData:(NSData*)data withTag:(long)tag;
|
||||
-(void)onSocket:(AsyncSocket*)sock didWriteDataWithTag:(long)tag;
|
||||
-(void)sendMessage:(NSString*)ftpMessage; // calls FC writedata
|
||||
-(void)sendDataString:(NSString*)dataString; // calls FDC writedata
|
||||
-(void)sendData:(NSMutableData*)data;
|
||||
-(void)didReceiveDataWritten; // notification that FDC wrote data
|
||||
-(void)didReceiveDataRead; // notification that FDC read data ie a transfer
|
||||
-(void)didFinishReading; // Called at the closing == end of a data connection from the client we presume
|
||||
|
||||
#pragma mark PROCESS
|
||||
|
||||
-(void)processDataRead:(NSData*)data;
|
||||
-(void)processCommand;
|
||||
|
||||
#pragma mark COMMANDS
|
||||
-(void)doQuit:(id)sender arguments:(NSArray*)arguments;
|
||||
-(void)doUser:(id)sender arguments:(NSArray*)arguments;
|
||||
-(void)doPass:(id)sender arguments:(NSArray*)arguments;
|
||||
-(void)doStat:(id)sender arguments:(NSArray*)arguments;
|
||||
-(void)doFeat:(id)sender arguments:(NSArray*)arguments;
|
||||
-(void)doList:(id)sender arguments:(NSArray*)arguments;
|
||||
-(void)doPwd:(id)sender arguments:(NSArray*)arguments;
|
||||
-(void)doNoop:(id)sender arguments:(NSArray*)arguments;
|
||||
-(void)doSyst:(id)sender arguments:(NSArray*)arguments;
|
||||
-(void)doLprt:(id)sender arguments:(NSArray*)arguments;
|
||||
-(void)doPasv:(id)sender arguments:(NSArray*)arguments;
|
||||
-(void)doEpsv:(id)sender arguments:(NSArray*)arguments;
|
||||
-(void)doPort:(id)sender arguments:(NSArray*)arguments;
|
||||
-(void)doNlst:(id)sender arguments:(NSArray*)arguments;
|
||||
-(void)doStor:(id)sender arguments:(NSArray*)arguments;
|
||||
-(void)doRetr:(id)sender arguments:(NSArray*)arguments;
|
||||
-(void)doDele:(id)sender arguments:(NSArray*)arguments;
|
||||
-(void)doMlst:(id)sender arguments:(NSArray*)arguments;
|
||||
-(void)doSize:(id)sender arguments:(NSArray*)arguments;
|
||||
-(void)doMkdir:(id)sender arguments:(NSArray*)arguments;
|
||||
-(void)doCdUp:(id)sender arguments:(NSArray*)arguments;
|
||||
-(void)doRnfr:(id)sender arguments:(NSArray*)arguments;
|
||||
-(void)doRnto:(id)sender arguments:(NSArray*)arguments;
|
||||
|
||||
#pragma mark UTITILITES
|
||||
-(NSString*)makeFilePathFrom:(NSString*)filename;
|
||||
-(unsigned long long)fileSize:(NSString*)filePath;
|
||||
-(NSString*)fileNameFromArgs:(NSArray*)arguments;
|
||||
- (Boolean)changedCurrentDirectoryTo:(NSString *)newDirectory;
|
||||
-(Boolean)canChangeDirectoryTo:(NSString *)testDirectory;
|
||||
- (Boolean)accessibleFilePath:(NSString*)filePath; // check filepath exists and is in basedir ( if set )
|
||||
- (Boolean)validNewFilePath:(NSString*)filePath;
|
||||
- (NSString *)visibleCurrentDir;
|
||||
-(NSString *)rootedPath:(NSString*)path;
|
||||
|
||||
@end
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,54 +0,0 @@
|
||||
/*
|
||||
iosFtpServer
|
||||
Copyright (C) 2008 Richard Dearlove ( monsta )
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
#import "AsyncSocket.h"
|
||||
#import "FtpDefines.h"
|
||||
|
||||
@class FtpConnection;
|
||||
|
||||
@interface FtpDataConnection : NSObject {
|
||||
AsyncSocket *dataSocket;
|
||||
FtpConnection *ftpConnection; // connection which generated data socket we are tied to
|
||||
|
||||
AsyncSocket *dataListeningSocket;
|
||||
id dataConnection;
|
||||
NSMutableData *receivedData;
|
||||
int connectionState;
|
||||
|
||||
}
|
||||
-(id)initWithAsyncSocket:(AsyncSocket*)newSocket forConnection:(id)aConnection withQueuedData:(NSMutableArray*)queuedData;
|
||||
-(void)writeString:(NSString*)dataString;
|
||||
-(void)writeData:(NSMutableData*)data;
|
||||
-(void)writeQueuedData:(NSMutableArray*)queuedData;
|
||||
-(void)closeConnection;
|
||||
|
||||
#pragma mark ASYNCSOCKET DELEGATES
|
||||
-(BOOL)onSocketWillConnect:(AsyncSocket *)sock;
|
||||
-(void)onSocket:(AsyncSocket *)sock didAcceptNewSocket:(AsyncSocket *)newSocket;
|
||||
-(void)onSocket:(AsyncSocket*)sock didReadData:(NSData*)data withTag:(long)tag;
|
||||
-(void)onSocket:(AsyncSocket*)sock didWriteDataWithTag:(long)tag;
|
||||
|
||||
-(void)onSocket:(AsyncSocket *)sock willDisconnectWithError:(NSError *)err;
|
||||
|
||||
@property (readonly) NSMutableData *receivedData;
|
||||
@property (readwrite) int connectionState;
|
||||
|
||||
|
||||
@end
|
||||
@@ -1,192 +0,0 @@
|
||||
/*
|
||||
iosFtpServer
|
||||
Copyright (C) 2008 Richard Dearlove ( monsta )
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#import "FtpDataConnection.h"
|
||||
#import "FtpConnection.h"
|
||||
|
||||
|
||||
@implementation FtpDataConnection
|
||||
|
||||
@synthesize receivedData;
|
||||
@synthesize connectionState;
|
||||
|
||||
// ----------------------------------------------------------------------------------------------------------
|
||||
-(id)initWithAsyncSocket:(AsyncSocket*)newSocket forConnection:(id)aConnection withQueuedData:(NSMutableArray*)queuedData
|
||||
// ----------------------------------------------------------------------------------------------------------
|
||||
{
|
||||
self = [super init ];
|
||||
if (self)
|
||||
{
|
||||
dataSocket = [newSocket retain ]; // Hang onto the socket that was generated - the FDC is retained by FC
|
||||
ftpConnection = aConnection;
|
||||
|
||||
[ dataSocket setDelegate:self ];
|
||||
|
||||
if ( [queuedData count ] )
|
||||
{
|
||||
NSLog(@"FC:Write Queued Data");
|
||||
[self writeQueuedData:queuedData ];
|
||||
[ queuedData removeAllObjects ]; // Clear out queue
|
||||
}
|
||||
// [ dataSocket readDataToData:[AsyncSocket CRLFData] withTimeout:READ_TIMEOUT tag:FTP_CLIENT_REQUEST ];
|
||||
[ dataSocket readDataWithTimeout:READ_TIMEOUT tag:FTP_CLIENT_REQUEST ];
|
||||
dataListeningSocket = nil;
|
||||
receivedData = nil; // [[ NSMutableData alloc ] init ] 12/nov/08 - no need for this. rcd is just a pointer
|
||||
|
||||
connectionState = clientQuiet; // Nothing coming through
|
||||
}
|
||||
return self;
|
||||
}
|
||||
// ----------------------------------------------------------------------------------------------------------
|
||||
-(void)dealloc
|
||||
// ----------------------------------------------------------------------------------------------------------
|
||||
{
|
||||
|
||||
[dataSocket release];
|
||||
[dataListeningSocket release];
|
||||
[dataConnection release];
|
||||
// [receivedData release];
|
||||
|
||||
|
||||
[super dealloc];
|
||||
}
|
||||
// ----------------------------------------------------------------------------------------------------------
|
||||
-(void)writeString:(NSString*)dataString
|
||||
// ----------------------------------------------------------------------------------------------------------
|
||||
{
|
||||
NSLog(@"FDC:writeStringData");
|
||||
|
||||
NSMutableData *data = [[ dataString dataUsingEncoding:NSUTF8StringEncoding ] mutableCopy]; // Autoreleased
|
||||
[ data appendData:[AsyncSocket CRLFData] ];
|
||||
|
||||
[ dataSocket writeData:data withTimeout:READ_TIMEOUT tag:FTP_CLIENT_REQUEST ];
|
||||
[ dataSocket readDataWithTimeout:READ_TIMEOUT tag:FTP_CLIENT_REQUEST ];
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------------------------
|
||||
-(void)writeData:(NSMutableData*)data
|
||||
// ----------------------------------------------------------------------------------------------------------
|
||||
{
|
||||
NSLog(@"FDC:writeData");
|
||||
// [ data appendData:[AsyncSocket CRLFData] ]; // Add on CRLF to end of data - as Windows Explorer needs it
|
||||
|
||||
connectionState = clientReceiving; // We hope
|
||||
|
||||
[ dataSocket writeData:data withTimeout:READ_TIMEOUT tag:FTP_CLIENT_REQUEST ];
|
||||
|
||||
[ dataSocket readDataWithTimeout:READ_TIMEOUT tag:FTP_CLIENT_REQUEST ];
|
||||
}
|
||||
// ----------------------------------------------------------------------------------------------------------
|
||||
-(void)writeQueuedData:(NSMutableArray*)queuedData
|
||||
// ----------------------------------------------------------------------------------------------------------
|
||||
{
|
||||
for (NSMutableData* data in queuedData) {
|
||||
[self writeData:data ];
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------------------------
|
||||
-(void)closeConnection
|
||||
// ----------------------------------------------------------------------------------------------------------
|
||||
{
|
||||
NSLog(@"FDC:closeConnection");
|
||||
[ dataSocket disconnect ];
|
||||
|
||||
}
|
||||
#pragma mark ASYNCSOCKET DELEGATES
|
||||
// ----------------------------------------------------------------------------------------------------------
|
||||
-(BOOL)onSocketWillConnect:(AsyncSocket *)sock
|
||||
// ----------------------------------------------------------------------------------------------------------
|
||||
{
|
||||
|
||||
NSLog(@"FDC:onSocketWillConnect");
|
||||
[ dataSocket readDataWithTimeout:READ_TIMEOUT tag:0 ];
|
||||
return YES;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------------------------
|
||||
-(void)onSocket:(AsyncSocket *)sock didAcceptNewSocket:(AsyncSocket *)newSocket
|
||||
// ----------------------------------------------------------------------------------------------------------
|
||||
{
|
||||
// This shouldnt happen - we should be connected already - and havent set up a listening socket
|
||||
NSLog(@"FDC:New Connection -- shouldn't be called");
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------------------------------------
|
||||
-(void)onSocket:(AsyncSocket*)sock didReadData:(NSData*)data withTag:(long)tag
|
||||
// ----------------------------------------------------------------------------------------------------------
|
||||
{
|
||||
NSLog(@"FDC:didReadData");
|
||||
|
||||
// [ dataSocket readDataToData:[AsyncSocket CRLFData] withTimeout:READ_TIMEOUT tag:FTP_CLIENT_REQUEST ]; // continue reading
|
||||
[ dataSocket readDataWithTimeout:READ_TIMEOUT tag:FTP_CLIENT_REQUEST ];
|
||||
|
||||
NSMutableData *mutdata = [data mutableCopy];
|
||||
receivedData = [ mutdata retain]; // make autoreleased copy of data
|
||||
|
||||
// notify connection data came through, ( will write data for us )
|
||||
[ftpConnection didReceiveDataRead ]; // notify, the connection, so it knows to write the data
|
||||
[ receivedData release ]; // let go, not our business anymore
|
||||
connectionState = clientSent;
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------------------------------------
|
||||
-(void)onSocket:(AsyncSocket*)sock didWriteDataWithTag:(long)tag
|
||||
// ----------------------------------------------------------------------------------------------------------
|
||||
{
|
||||
NSLog(@"FDC:didWriteData");
|
||||
[ ftpConnection didReceiveDataWritten ]; // notify that we are finished writing
|
||||
|
||||
// [ dataSocket readDataToData:[AsyncSocket CRLFData] withTimeout:READ_TIMEOUT tag:FTP_CLIENT_REQUEST ]; // continue reading
|
||||
[ dataSocket readDataWithTimeout:READ_TIMEOUT tag:FTP_CLIENT_REQUEST ];
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------------------------------------
|
||||
-(void)onSocket:(AsyncSocket *)sock willDisconnectWithError:(NSError *)err
|
||||
// ----------------------------------------------------------------------------------------------------------
|
||||
{
|
||||
NSLog(@"FDC:willDisconnect");
|
||||
// if we were writing and there's no error, then it must be the end of file
|
||||
|
||||
if ( connectionState == clientSending )
|
||||
{
|
||||
NSLog(@"FDC::did FinishReading");
|
||||
// hopefully this is the end of the connection. not sure how we can tell
|
||||
}
|
||||
else
|
||||
{
|
||||
NSLog(@"FDC: we werent expecting this as we never set clientSending prob late coming up");
|
||||
}
|
||||
[ ftpConnection didFinishReading ]; // its over, please send the message
|
||||
}
|
||||
|
||||
- (BOOL)onReadStreamEnded:(AsyncSocket*)sock
|
||||
{
|
||||
NSLog( @"FDC: onReadStreamEnded %d(clientSending is %d)", connectionState, clientSending );
|
||||
if ( connectionState == clientSent ||
|
||||
connectionState == clientSending ) return YES;
|
||||
return NO;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -1,15 +0,0 @@
|
||||
enum {
|
||||
pasvftp=0,epsvftp,portftp,lprtftp, eprtftp
|
||||
};
|
||||
|
||||
#define DATASTR(args) [ args dataUsingEncoding:NSUTF8StringEncoding ]
|
||||
|
||||
#define SERVER_PORT 20000
|
||||
#define READ_TIMEOUT -1
|
||||
|
||||
#define FTP_CLIENT_REQUEST 0
|
||||
|
||||
enum {
|
||||
|
||||
clientSending=0, clientReceiving=1, clientQuiet=2,clientSent=3
|
||||
};
|
||||
@@ -1,72 +0,0 @@
|
||||
/*
|
||||
iosFtpServer
|
||||
Copyright (C) 2008 Richard Dearlove ( monsta )
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
|
||||
#import "AsyncSocket.h"
|
||||
#import "FtpDefines.h"
|
||||
#import "FtpConnection.h"
|
||||
#import "list.h"
|
||||
|
||||
@interface FtpServer : NSObject {
|
||||
|
||||
AsyncSocket *listenSocket;
|
||||
NSMutableArray *connectedSockets;
|
||||
id server;
|
||||
id notificationObject;
|
||||
|
||||
int portNumber;
|
||||
id delegate;
|
||||
|
||||
NSMutableArray *connections;
|
||||
|
||||
NSDictionary *commands;
|
||||
NSString *baseDir;
|
||||
Boolean changeRoot; // Change root to virtual root ( basedir )
|
||||
int clientEncoding; // FTP client encoding type
|
||||
}
|
||||
- (id)initWithPort:(unsigned)serverPort withDir:(NSString *)aDirectory notifyObject:(id)sender;
|
||||
- (void)stopFtpServer;
|
||||
|
||||
#pragma mark ASYNCSOCKET DELEGATES
|
||||
- (void)onSocket:(AsyncSocket *)sock didAcceptNewSocket:(AsyncSocket *)newSocket;
|
||||
- (void)onSocket:(AsyncSocket *)sock didConnectToHost:(NSString *)host port:(UInt16)port;
|
||||
|
||||
#pragma mark NOTIFICATIONS
|
||||
- (void)didReceiveFileListChanged;
|
||||
|
||||
#pragma mark CONNECTIONS
|
||||
- (void)closeConnection:(id)theConnection;
|
||||
- (NSString *)createList:(NSString *)directoryPath;
|
||||
|
||||
@property (readwrite, retain) AsyncSocket *listenSocket;
|
||||
@property (readwrite, retain) NSMutableArray *connectedSockets;
|
||||
@property (readwrite, retain) id server;
|
||||
@property (readwrite, retain) id notificationObject;
|
||||
@property (readwrite) int portNumber;
|
||||
@property (readwrite, retain) id delegate;
|
||||
@property (readwrite, retain) NSMutableArray *connections;
|
||||
@property (readwrite, retain) NSDictionary *commands;
|
||||
@property (readwrite, retain) NSString *baseDir;
|
||||
@property (readwrite) Boolean changeRoot;
|
||||
@property (readwrite) int clientEncoding;
|
||||
|
||||
@end
|
||||
@@ -1,198 +0,0 @@
|
||||
/*
|
||||
iosFtpServer
|
||||
Copyright (C) 2008 Richard Dearlove ( monsta )
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
|
||||
// 11/02/08 changes to made to allow stopping of the server. Also added a bit of code to show users IP address.
|
||||
// Cleaned up the code to make the retains and releases a bit more obvious... mostly programming style preferences.
|
||||
// Added a stop Ftp server method to be called from where ever it was start. See iphoneLibTestViewController.m to see how I was calling it.
|
||||
// Most users wouldn't want the server to continue to run once the transfers are done.
|
||||
|
||||
|
||||
#import "FtpServer.h"
|
||||
|
||||
@implementation FtpServer
|
||||
|
||||
@synthesize listenSocket, connectedSockets, server, notificationObject, portNumber, delegate, commands, baseDir, connections;
|
||||
|
||||
@synthesize clientEncoding;
|
||||
@synthesize changeRoot;
|
||||
|
||||
// ----------------------------------------------------------------------------------------------------------
|
||||
- (id)initWithPort:(unsigned)serverPort withDir:(NSString*)aDirectory notifyObject:(id)sender
|
||||
// ----------------------------------------------------------------------------------------------------------
|
||||
{
|
||||
if( self = [super init] ) {
|
||||
|
||||
NSError *error = nil;
|
||||
|
||||
self.notificationObject = sender;
|
||||
|
||||
// Load up commands
|
||||
NSString *plistPath = [[ NSBundle mainBundle ] pathForResource:@"ftp_commands" ofType:@"plist"];
|
||||
if ( ! [ [ NSFileManager defaultManager ] fileExistsAtPath:plistPath ] )
|
||||
{
|
||||
NSLog(@"ftp_commands.plist missing");
|
||||
}
|
||||
commands = [ [ NSDictionary alloc ] initWithContentsOfFile:plistPath];
|
||||
|
||||
// Clear out connections list
|
||||
NSMutableArray *myConnections = [[NSMutableArray alloc] init];
|
||||
self.connections = myConnections;
|
||||
[myConnections release];
|
||||
|
||||
|
||||
|
||||
// Create a socket
|
||||
self.portNumber = serverPort;
|
||||
|
||||
AsyncSocket *myListenSocket = [[AsyncSocket alloc] initWithDelegate:self];
|
||||
self.listenSocket = myListenSocket;
|
||||
[myListenSocket release];
|
||||
|
||||
NSLog(@"Listening on %u", portNumber);
|
||||
[listenSocket acceptOnPort:serverPort error:&error]; // start lisetning on this port.
|
||||
|
||||
NSMutableArray *myConnectedSockets = [[NSMutableArray alloc] initWithCapacity:1];
|
||||
self.connectedSockets = myConnectedSockets;
|
||||
[myConnectedSockets release];
|
||||
|
||||
// Set directory - have to do this because on iphone, some directories arent what they report back as, so need real path it resolves to, CHECKME - might be an easier way
|
||||
NSFileManager *fileManager = [ NSFileManager defaultManager ];
|
||||
NSString *expandedPath = [ aDirectory stringByStandardizingPath ];
|
||||
|
||||
// CHANGE TO NEW DIRECTORY & GET SYSTEM FILE PATH ( no .. etc )
|
||||
if ([ fileManager changeCurrentDirectoryPath:expandedPath ]) // try changing to directory
|
||||
{
|
||||
|
||||
self.baseDir = [[ fileManager currentDirectoryPath ] copy] ; // Gets the real path. CHECKME.
|
||||
// self.baseDir = @"/Users"; // REMOVEME - added for testing 7/6/10
|
||||
}
|
||||
else
|
||||
{
|
||||
self.baseDir = aDirectory; // shouldnt get to this line really
|
||||
}
|
||||
|
||||
self.changeRoot = false; // true if you want them to be sandboxed/chrooted into the basedir
|
||||
|
||||
// the default client encoding is UTF8
|
||||
self.clientEncoding = NSUTF8StringEncoding;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
// ----------------------------------------------------------------------------------------------------------
|
||||
-(void)stopFtpServer
|
||||
// ----------------------------------------------------------------------------------------------------------
|
||||
{
|
||||
if(listenSocket)[listenSocket disconnect];
|
||||
[connectedSockets removeAllObjects];
|
||||
|
||||
[connections removeAllObjects];
|
||||
|
||||
}
|
||||
#pragma mark ASYNCSOCKET DELEGATES
|
||||
// ----------------------------------------------------------------------------------------------------------
|
||||
- (void)onSocket:(AsyncSocket *)sock didAcceptNewSocket:(AsyncSocket *)newSocket
|
||||
// ----------------------------------------------------------------------------------------------------------
|
||||
{
|
||||
|
||||
FtpConnection *newConnection = [[[ FtpConnection alloc ] initWithAsyncSocket:newSocket forServer:self] autorelease]; // Create an ftp connection
|
||||
|
||||
|
||||
|
||||
|
||||
[ connections addObject:newConnection ]; // Add this to our list of connections
|
||||
|
||||
NSLog(@"FS:didAcceptNewSocket port:%i", [sock localPort]);
|
||||
|
||||
if ([sock localPort] == portNumber )
|
||||
{
|
||||
NSLog(@"Connection on Server Port");
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
// must be a data comms port
|
||||
// spawn a data comms port
|
||||
// look for the connection with the same port
|
||||
// and attach it
|
||||
NSLog(@"--ERROR %i, %i", [sock localPort],portNumber);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------------------------
|
||||
- (void)onSocket:(AsyncSocket *)sock didConnectToHost:(NSString *)host port:(UInt16)port
|
||||
// ----------------------------------------------------------------------------------------------------------
|
||||
{
|
||||
NSLog(@"FtpServer:didConnectToHost port:%i", [sock localPort]);
|
||||
}
|
||||
|
||||
#pragma mark NOTIFICATIONS
|
||||
// ----------------------------------------------------------------------------------------------------------
|
||||
-(void)didReceiveFileListChanged
|
||||
// ----------------------------------------------------------------------------------------------------------
|
||||
{
|
||||
if ([notificationObject respondsToSelector:@selector(didReceiveFileListChanged)])
|
||||
[notificationObject didReceiveFileListChanged ];
|
||||
}
|
||||
#pragma mark CONNECTIONS
|
||||
// ----------------------------------------------------------------------------------------------------------
|
||||
- (void)closeConnection:(id)theConnection
|
||||
// ----------------------------------------------------------------------------------------------------------
|
||||
{
|
||||
// Search through connections for this one - and delete
|
||||
// this should release it - and delloc
|
||||
|
||||
[connections removeObject:theConnection ];
|
||||
|
||||
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------------------------
|
||||
-(NSString*)createList:(NSString*)directoryPath
|
||||
// ----------------------------------------------------------------------------------------------------------
|
||||
{
|
||||
return createList(directoryPath);
|
||||
|
||||
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------------------------
|
||||
- (void)dealloc
|
||||
// ----------------------------------------------------------------------------------------------------------
|
||||
{
|
||||
|
||||
|
||||
if(listenSocket)
|
||||
{
|
||||
[listenSocket disconnect];
|
||||
[listenSocket release];
|
||||
}
|
||||
|
||||
[connectedSockets release];
|
||||
[notificationObject release];
|
||||
[connections release];
|
||||
[commands release];
|
||||
[baseDir release];
|
||||
[super dealloc];
|
||||
|
||||
}
|
||||
|
||||
|
||||
@end
|
||||
@@ -1,26 +0,0 @@
|
||||
//
|
||||
// networkController.h
|
||||
// DiddyDJ
|
||||
//
|
||||
// Created by Richard Dearlove on 21/10/2008.
|
||||
// Copyright 2008 DiddySoft. All rights reserved.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
#import <SystemConfiguration/SystemConfiguration.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netdb.h>
|
||||
#include <unistd.h>
|
||||
#include <ifaddrs.h>
|
||||
|
||||
@interface NetworkController : NSObject {
|
||||
|
||||
}
|
||||
+ (NSString *)localWifiIPAddress;
|
||||
+ (NSString *) localIPAddress;
|
||||
+ (BOOL)addressFromString:(NSString *)IPAddress address:(struct sockaddr_in *)address;
|
||||
+ (NSString *) getIPAddressForHost: (NSString *) theHost;
|
||||
+ (BOOL) hostAvailable: (NSString *) theHost;
|
||||
+ (BOOL) connectedToNetwork;
|
||||
@end
|
||||
@@ -1,184 +0,0 @@
|
||||
//
|
||||
// networkController.m
|
||||
//
|
||||
// Created by Richard Dearlove on 21/10/2008.
|
||||
// Copyright 2008 DiddySoft. All rights reserved.
|
||||
//
|
||||
|
||||
#import "NetworkController.h"
|
||||
|
||||
@implementation NetworkController
|
||||
|
||||
// Return the localized IP address
|
||||
|
||||
// ----------------------------------------------------------------------------------------------------------
|
||||
+ (NSString *)localWifiIPAddress
|
||||
// ----------------------------------------------------------------------------------------------------------
|
||||
|
||||
{
|
||||
NSString *address = @"error";
|
||||
struct ifaddrs *interfaces = NULL;
|
||||
struct ifaddrs *temp_addr = NULL;
|
||||
int success = 0;
|
||||
|
||||
// retrieve the current interfaces - returns 0 on success
|
||||
success = getifaddrs(&interfaces);
|
||||
if (success == 0)
|
||||
{
|
||||
// Loop through linked list of interfaces
|
||||
temp_addr = interfaces;
|
||||
while(temp_addr != NULL)
|
||||
{
|
||||
if(temp_addr->ifa_addr->sa_family == AF_INET)
|
||||
{
|
||||
// Check if interface is en0 which is the wifi connection on the iPhone
|
||||
if([[NSString stringWithUTF8String:temp_addr->ifa_name] isEqualToString:@"en0"])
|
||||
{
|
||||
// Get NSString from C String
|
||||
address = [NSString stringWithUTF8String:inet_ntoa(((struct sockaddr_in *)temp_addr->ifa_addr)->sin_addr)];
|
||||
}
|
||||
}
|
||||
|
||||
temp_addr = temp_addr->ifa_next;
|
||||
}
|
||||
}
|
||||
|
||||
// Free memory
|
||||
freeifaddrs(interfaces);
|
||||
|
||||
return address;
|
||||
}
|
||||
// ----------------------------------------------------------------------------------------------------------
|
||||
|
||||
// ----------------------------------------------------------------------------------------------------------
|
||||
+ (NSString *) localIPAddress
|
||||
// ----------------------------------------------------------------------------------------------------------
|
||||
{
|
||||
char baseHostName[255];
|
||||
gethostname(baseHostName, 255);
|
||||
|
||||
// Adjust for iPhone -- add .local to the host name
|
||||
char hn[255];
|
||||
sprintf(hn, "%s.local", baseHostName);
|
||||
|
||||
struct hostent *host = gethostbyname(hn);
|
||||
if (host == NULL)
|
||||
{
|
||||
herror("resolv");
|
||||
return NULL;
|
||||
}
|
||||
else {
|
||||
struct in_addr **list = (struct in_addr **)host->h_addr_list;
|
||||
return [NSString stringWithCString:inet_ntoa(*list[0])];
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------------------------
|
||||
+ (BOOL)addressFromString:(NSString *)IPAddress address:(struct sockaddr_in *)address
|
||||
// ----------------------------------------------------------------------------------------------------------
|
||||
{
|
||||
if (!IPAddress || ![IPAddress length]) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
memset((char *) address, sizeof(struct sockaddr_in), 0);
|
||||
address->sin_family = AF_INET;
|
||||
address->sin_len = sizeof(struct sockaddr_in);
|
||||
|
||||
int conversionResult = inet_aton([IPAddress UTF8String], &address->sin_addr);
|
||||
if (conversionResult == 0) {
|
||||
NSAssert1(conversionResult != 1, @"Failed to convert the IP address string into a sockaddr_in: %@", IPAddress);
|
||||
return NO;
|
||||
}
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------------------------
|
||||
+ (NSString *) getIPAddressForHost: (NSString *) theHost
|
||||
// ----------------------------------------------------------------------------------------------------------
|
||||
{
|
||||
struct hostent *host = gethostbyname([theHost UTF8String]);
|
||||
|
||||
if (host == NULL) {
|
||||
herror("resolv");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct in_addr **list = (struct in_addr **)host->h_addr_list;
|
||||
NSString *addressString = [NSString stringWithCString:inet_ntoa(*list[0])];
|
||||
return addressString;
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------------------------------------
|
||||
+ (BOOL) hostAvailable: (NSString *) theHost
|
||||
// ----------------------------------------------------------------------------------------------------------
|
||||
{
|
||||
|
||||
NSString *addressString = [self getIPAddressForHost:theHost];
|
||||
if (!addressString)
|
||||
{
|
||||
printf("Error recovering IP address from host name\n");
|
||||
return NO;
|
||||
}
|
||||
|
||||
struct sockaddr_in address;
|
||||
BOOL gotAddress = [self addressFromString:addressString address:&address];
|
||||
|
||||
if (!gotAddress)
|
||||
{
|
||||
printf("Error recovering sockaddr address from %s\n", [addressString UTF8String]);
|
||||
return NO;
|
||||
}
|
||||
|
||||
SCNetworkReachabilityRef defaultRouteReachability = SCNetworkReachabilityCreateWithAddress(NULL, (struct sockaddr *)&address);
|
||||
SCNetworkReachabilityFlags flags;
|
||||
|
||||
BOOL didRetrieveFlags = SCNetworkReachabilityGetFlags(defaultRouteReachability, &flags);
|
||||
CFRelease(defaultRouteReachability);
|
||||
|
||||
if (!didRetrieveFlags)
|
||||
{
|
||||
printf("Error. Could not recover network reachability flags\n");
|
||||
return NO;
|
||||
}
|
||||
|
||||
BOOL isReachable = flags & kSCNetworkFlagsReachable;
|
||||
return isReachable ? YES : NO;;
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------------------------------------
|
||||
+ (BOOL) connectedToNetwork
|
||||
// ----------------------------------------------------------------------------------------------------------
|
||||
{
|
||||
// Create zero addy
|
||||
struct sockaddr_in zeroAddress;
|
||||
bzero(&zeroAddress, sizeof(zeroAddress));
|
||||
zeroAddress.sin_len = sizeof(zeroAddress);
|
||||
zeroAddress.sin_family = AF_INET;
|
||||
|
||||
// Recover reachability flags
|
||||
SCNetworkReachabilityRef defaultRouteReachability = SCNetworkReachabilityCreateWithAddress(NULL, (struct sockaddr *)&zeroAddress);
|
||||
CFRelease(defaultRouteReachability);
|
||||
|
||||
SCNetworkReachabilityFlags flags;
|
||||
|
||||
BOOL didRetrieveFlags = SCNetworkReachabilityGetFlags(defaultRouteReachability, &flags);
|
||||
if (!didRetrieveFlags)
|
||||
{
|
||||
printf("Error. Could not recover network reachability flags\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
BOOL isReachable = flags & kSCNetworkFlagsReachable;
|
||||
BOOL needsConnection = flags & kSCNetworkFlagsConnectionRequired;
|
||||
// BOOL isEDGE = flags & kSCNetworkReachabilityFlagsIsWWAN;
|
||||
return (isReachable && !needsConnection) ? YES : NO;
|
||||
}
|
||||
|
||||
|
||||
@end
|
||||
@@ -1,64 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>ack</key>
|
||||
<string>doAck:</string>
|
||||
<key>cdup</key>
|
||||
<string>doCdUp:</string>
|
||||
<key>cwd</key>
|
||||
<string>doCwd:</string>
|
||||
<key>dele</key>
|
||||
<string>doDele:</string>
|
||||
<key>eprt</key>
|
||||
<string>doEprt:</string>
|
||||
<key>epsv</key>
|
||||
<string>doEpsv:</string>
|
||||
<key>feat</key>
|
||||
<string>doFeat:</string>
|
||||
<key>list</key>
|
||||
<string>doList:</string>
|
||||
<key>lprt</key>
|
||||
<string>doLprt:</string>
|
||||
<key>mkd</key>
|
||||
<string>doMkdir:</string>
|
||||
<key>mlst</key>
|
||||
<string>doMlst:</string>
|
||||
<key>nlst</key>
|
||||
<string>doList:</string>
|
||||
<key>noop</key>
|
||||
<string>doNoop:</string>
|
||||
<key>opts</key>
|
||||
<string>doOpts:</string>
|
||||
<key>pass</key>
|
||||
<string>doPass:</string>
|
||||
<key>pasv</key>
|
||||
<string>doPasv:</string>
|
||||
<key>port</key>
|
||||
<string>doPort:</string>
|
||||
<key>pwd</key>
|
||||
<string>doPwd:</string>
|
||||
<key>quit</key>
|
||||
<string>doQuit:</string>
|
||||
<key>retr</key>
|
||||
<string>doRetr:</string>
|
||||
<key>rmd</key>
|
||||
<string>doDele:</string>
|
||||
<key>rnfr</key>
|
||||
<string>doRnfr:</string>
|
||||
<key>rnto</key>
|
||||
<string>doRnto:</string>
|
||||
<key>size</key>
|
||||
<string>doSize:</string>
|
||||
<key>stat</key>
|
||||
<string>doStat:</string>
|
||||
<key>stor</key>
|
||||
<string>doStor:</string>
|
||||
<key>syst</key>
|
||||
<string>doSyst:</string>
|
||||
<key>type</key>
|
||||
<string>doType:</string>
|
||||
<key>user</key>
|
||||
<string>doUser:</string>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -17,7 +17,6 @@
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <UIKit/UIKit.h>
|
||||
#import <AVFoundation/AVFoundation.h>
|
||||
#import "FtpServer.h"
|
||||
#include <sys/stat.h>
|
||||
#include "dlfcn.h"
|
||||
|
||||
@@ -78,36 +77,22 @@ const char *IOS_GetDocsDir(void)
|
||||
}
|
||||
}
|
||||
|
||||
UIBackgroundTaskIdentifier task;
|
||||
FtpServer *server = NULL;
|
||||
|
||||
void IOS_StartBackgroundTask(void)
|
||||
const char *IOS_GetExecDir(void)
|
||||
{
|
||||
if( !server ) return;
|
||||
|
||||
if( task != UIBackgroundTaskInvalid )
|
||||
return;
|
||||
|
||||
UIApplication* app = [UIApplication sharedApplication];
|
||||
static const char *dir = NULL;
|
||||
|
||||
task = [app beginBackgroundTaskWithExpirationHandler:^{
|
||||
[app endBackgroundTask:task];
|
||||
task = UIBackgroundTaskInvalid;
|
||||
}];
|
||||
if( dir )
|
||||
return dir;
|
||||
|
||||
// Start the long-running task and return immediately.
|
||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
||||
UIBackgroundTaskIdentifier local = task;
|
||||
|
||||
// do not keep "zombie" tasks
|
||||
while( 1 )
|
||||
sleep(1);
|
||||
NSString *executableDirctory = [[NSBundle mainBundle] bundlePath];
|
||||
|
||||
[app endBackgroundTask:local];
|
||||
task = UIBackgroundTaskInvalid;
|
||||
});
|
||||
dir = [executableDirctory fileSystemRepresentation];
|
||||
NSLog(@"IOS_GetDocsDir: %s", dir);
|
||||
|
||||
return dir;
|
||||
}
|
||||
|
||||
|
||||
#define SETTINGS_MAGIC 111
|
||||
|
||||
typedef struct settings_s
|
||||
@@ -188,8 +173,6 @@ void IOS_LaunchDialog( void )
|
||||
|
||||
UIScrollView *scroll = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, 300, 200)];
|
||||
|
||||
UISwitch *ftpswitch = [[UISwitch alloc] initWithFrame:CGRectMake(210,60,80,30)];
|
||||
|
||||
UILabel *argstitle = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 300, 30)];
|
||||
[argstitle setText:@"Command-line arguments:"];
|
||||
|
||||
@@ -197,12 +180,6 @@ void IOS_LaunchDialog( void )
|
||||
[args setBackgroundColor:[[UIColor alloc] initWithRed:1 green:1 blue:1 alpha:1]];
|
||||
if(isdark) [args setBackgroundColor:[[UIColor alloc] initWithRed:0 green:0 blue:0 alpha:1]];
|
||||
|
||||
|
||||
UILabel *ftptitle = [[UILabel alloc] initWithFrame:CGRectMake(0, 60, 200, 30)];
|
||||
[ftptitle setText:@"FTP Server"];
|
||||
|
||||
|
||||
UITextField *port = [[UITextField alloc] initWithFrame:CGRectMake(110, 60, 100, 30)];
|
||||
|
||||
UITextField *suffix = [[UITextField alloc] initWithFrame:CGRectMake(140, 90, 160, 30 )];
|
||||
[suffix setBackgroundColor:[[UIColor alloc] initWithRed:1 green:1 blue:1 alpha:1]];
|
||||
@@ -214,9 +191,6 @@ void IOS_LaunchDialog( void )
|
||||
[scroll addSubview:argstitle];
|
||||
[scroll addSubview:args];
|
||||
[scroll addSubview:suffix];
|
||||
[scroll addSubview:ftpswitch];
|
||||
[scroll addSubview:ftptitle];
|
||||
[scroll addSubview:port];
|
||||
[scroll addSubview:suffixtitle];
|
||||
|
||||
settingsfile = fopen( settingspath, "rb" );
|
||||
@@ -225,14 +199,11 @@ void IOS_LaunchDialog( void )
|
||||
settings.args[1023] = 0;
|
||||
settings.suffix[31] = 0;
|
||||
[args setText:@(settings.args)];
|
||||
[port setText:[NSString stringWithFormat:@"%u", settings.port]];
|
||||
[suffix setText:@(settings.suffix)];
|
||||
ftpswitch.on = settings.ftpserver;
|
||||
}
|
||||
else
|
||||
{
|
||||
[args setText:@"-dev 2 -log"];
|
||||
[port setText:@"21135"];
|
||||
}
|
||||
|
||||
scroll.contentSize=CGSizeMake(250, 200);
|
||||
@@ -248,10 +219,8 @@ void IOS_LaunchDialog( void )
|
||||
|
||||
if( (settingsfile = fopen( settingspath, "wb" )) )
|
||||
{
|
||||
settings.ftpserver = ftpswitch.on;
|
||||
strlcpy(settings.args, [args.text UTF8String], 1024);
|
||||
strlcpy(settings.suffix, [suffix.text UTF8String], 32 );
|
||||
settings.port = [port.text intValue];
|
||||
settings.magic = 111;
|
||||
|
||||
fwrite(&settings, sizeof(settings), 1, settingsfile);
|
||||
@@ -263,25 +232,6 @@ void IOS_LaunchDialog( void )
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if( ftpswitch.on )
|
||||
{
|
||||
|
||||
button = -1;
|
||||
|
||||
[[[UIAlertView alloc] initWithTitle:@"Xash3D" message:[NSString stringWithFormat:@"Started FTP server on port %@", port.text] delegate:delegate cancelButtonTitle:@"Ok" otherButtonTitles:nil] show];
|
||||
|
||||
server = [[ FtpServer alloc ] initWithPort:[port.text integerValue] withDir:@(docsDir) notifyObject:nil ];
|
||||
|
||||
IOS_StartBackgroundTask();
|
||||
|
||||
@autoreleasepool {
|
||||
while( button == -1 ) {
|
||||
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
|
||||
IOS_StartBackgroundTask(); // keep running
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NSArray *argv = [ args.text componentsSeparatedByString:@" " ];
|
||||
|
||||
int count = [argv count];
|
||||
@@ -299,11 +249,8 @@ void IOS_LaunchDialog( void )
|
||||
|
||||
alert.delegate = nil;
|
||||
|
||||
[ftpswitch release];
|
||||
[ftptitle release];
|
||||
[args release];
|
||||
[argstitle release];
|
||||
[port release];
|
||||
[suffix release];
|
||||
[suffixtitle release];
|
||||
|
||||
|
||||
@@ -1,95 +0,0 @@
|
||||
/*
|
||||
ios_lib.c - dynamic library code for iOS
|
||||
Copyright (C) 2017-2018 mittorn
|
||||
|
||||
This program is free software: you can redistribute it and/sor modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
*/
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <SDL.h>
|
||||
#include <dlfcn.h>
|
||||
#include <sys/stat.h>
|
||||
#include "crtlib.h"
|
||||
#include "library.h"
|
||||
#include "platform/ios/lib_ios.h"
|
||||
#include "common.h"
|
||||
|
||||
const char *g_szLibrarySuffix;
|
||||
|
||||
static void *IOS_LoadLibraryInternal( const char *dllname )
|
||||
{
|
||||
void *pHandle;
|
||||
char path[MAX_SYSPATH];
|
||||
|
||||
Q_snprintf( path, sizeof( path ), "%s%s", SDL_GetBasePath(), dllname );
|
||||
pHandle = dlopen( path, RTLD_LAZY );
|
||||
|
||||
if( !pHandle )
|
||||
COM_PushLibraryError(dlerror( ));
|
||||
|
||||
return pHandle;
|
||||
}
|
||||
|
||||
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 )
|
||||
{
|
||||
// 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;
|
||||
char *pHandle;
|
||||
|
||||
IOS_PrepareGameLibraryPath( dllname, name, sizeof( name ));
|
||||
pHandle = IOS_LoadLibraryInternal( name );
|
||||
|
||||
if( !pHandle )
|
||||
pHandle = 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 );
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
/*
|
||||
ios_lib.h - dynamic library code for iOS
|
||||
Copyright (C) 2017-2018 mittorn
|
||||
|
||||
This program is free software: you can redistribute it and/sor modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
*/
|
||||
#pragma once
|
||||
#if TARGET_OS_IPHONE
|
||||
#ifndef IOS_LIB_H
|
||||
#define IOS_LIB_H
|
||||
|
||||
#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
|
||||
@@ -1,29 +0,0 @@
|
||||
/*
|
||||
iosFtpServer
|
||||
Copyright (C) 2008 Richard Dearlove ( monsta )
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#pragma mark LS replacement
|
||||
NSString* createList(NSString* directoryPath);
|
||||
|
||||
#pragma mark Supporting Functions
|
||||
int filesinDirectory(NSString* filePath );
|
||||
NSMutableString* int2BinString(int x);
|
||||
NSMutableString *byte2String(int x );
|
||||
NSMutableString *bin2perms(NSString *binaryValue);
|
||||
@@ -1,202 +0,0 @@
|
||||
/*
|
||||
iosFtpServer
|
||||
Copyright (C) 2008 Richard Dearlove ( monsta )
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
#import "list.h"
|
||||
|
||||
// ----------------------------------------------------------------------------------------------------------
|
||||
NSString* createList(NSString* directoryPath)
|
||||
// ----------------------------------------------------------------------------------------------------------
|
||||
{
|
||||
NSFileManager *fileManager = [ NSFileManager defaultManager ];
|
||||
NSDictionary *fileAttributes;
|
||||
NSError *error;
|
||||
|
||||
NSString* fileType;
|
||||
NSNumber* filePermissions;
|
||||
long fileSubdirCount;
|
||||
NSString* fileOwner;
|
||||
NSString* fileGroup;
|
||||
NSNumber* fileSize;
|
||||
NSDate* fileModified;
|
||||
NSString* fileDateFormatted;
|
||||
NSDateFormatter* dateFormatter = [[[ NSDateFormatter alloc ] init ] autorelease ];
|
||||
|
||||
BOOL fileIsDirectory;
|
||||
|
||||
|
||||
NSMutableString* returnString= [ NSMutableString new ];
|
||||
NSString* formattedString;
|
||||
|
||||
NSString* binaryString;
|
||||
|
||||
[returnString appendString:@"\r\n"];
|
||||
|
||||
NSDirectoryEnumerator *dirEnum = [fileManager enumeratorAtPath:directoryPath];
|
||||
NSString *filePath;
|
||||
|
||||
NSString* firstChar;
|
||||
NSString* fullFilePath;
|
||||
|
||||
[dateFormatter setDateFormat:@"MMM dd HH:mm"];
|
||||
NSLocale *englishLocale = [[NSLocale alloc] initWithLocaleIdentifier:@"en"];
|
||||
[dateFormatter setLocale:englishLocale];
|
||||
[englishLocale release];
|
||||
|
||||
|
||||
NSLog(@"Get LS for %@", directoryPath );
|
||||
int numberOfFiles = 0;
|
||||
while (filePath = [dirEnum nextObject]) {
|
||||
|
||||
firstChar = [ filePath substringToIndex:1 ];
|
||||
|
||||
[dirEnum skipDescendents ]; // don't go down that recursive road
|
||||
|
||||
if ( ![ firstChar isEqualToString:@"."] ) // dont show hidden files
|
||||
{
|
||||
fullFilePath = [directoryPath stringByAppendingPathComponent:filePath];
|
||||
|
||||
fileAttributes = [ fileManager attributesOfItemAtPath:fullFilePath error:&error ];
|
||||
|
||||
fileType = [ fileAttributes valueForKey:NSFileType ];
|
||||
|
||||
filePermissions = [ fileAttributes valueForKey:NSFilePosixPermissions ];
|
||||
fileSubdirCount = filesinDirectory(fullFilePath);
|
||||
fileOwner = [ fileAttributes valueForKey:NSFileOwnerAccountName ];
|
||||
fileGroup = [ fileAttributes valueForKey:NSFileGroupOwnerAccountName ];
|
||||
fileSize = [ fileAttributes valueForKey:NSFileSize ];
|
||||
fileModified = [ fileAttributes valueForKey:NSFileModificationDate ];
|
||||
fileDateFormatted = [ dateFormatter stringFromDate:fileModified ];
|
||||
|
||||
fileIsDirectory = (fileType == NSFileTypeDirectory );
|
||||
|
||||
|
||||
fileSubdirCount = fileSubdirCount <1 ? 1 : fileSubdirCount;
|
||||
|
||||
binaryString = int2BinString([filePermissions unsignedLongValue]) ;
|
||||
binaryString = [ binaryString substringFromIndex:7 ];// snip off the front
|
||||
formattedString = [ NSString stringWithFormat:@"%@%@ %5i %12@ %12@ %10qu %@ %@", fileIsDirectory ? @"d" : @"-" ,bin2perms(binaryString),fileSubdirCount, fileOwner, fileGroup, [fileSize unsignedLongLongValue], fileDateFormatted , filePath ];
|
||||
|
||||
[ returnString appendString:formattedString ];
|
||||
[ returnString appendString:@"\n" ];
|
||||
numberOfFiles++;
|
||||
}
|
||||
}
|
||||
[returnString insertString: [NSString stringWithFormat:@"total %d", numberOfFiles] atIndex:0];
|
||||
// NSLog(returnString );
|
||||
return [returnString autorelease]; // FIXME - release count
|
||||
|
||||
}
|
||||
// ----------------------------------------------------------------------------------------------------------
|
||||
int filesinDirectory(NSString* filePath )
|
||||
// ----------------------------------------------------------------------------------------------------------
|
||||
{
|
||||
int no_files =0;
|
||||
NSFileManager *fileManager = [ NSFileManager defaultManager ];
|
||||
NSDirectoryEnumerator *dirEnum = [fileManager enumeratorAtPath:filePath];
|
||||
|
||||
while (filePath = [dirEnum nextObject]) {
|
||||
[dirEnum skipDescendents ]; // don't want children
|
||||
no_files++;
|
||||
}
|
||||
|
||||
return no_files;
|
||||
}
|
||||
// ----------------------------------------------------------------------------------------------------------
|
||||
NSMutableString* int2BinString(int x)
|
||||
// ----------------------------------------------------------------------------------------------------------
|
||||
{
|
||||
NSMutableString *returnString = [[ NSMutableString alloc ] init];
|
||||
int hi, lo;
|
||||
hi=(x>>8) & 0xff;
|
||||
lo=x&0xff;
|
||||
|
||||
[ returnString appendString:byte2String(hi) ];
|
||||
[ returnString appendString:byte2String(lo) ];
|
||||
return [ returnString autorelease ];
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------------------------------------
|
||||
NSMutableString *byte2String(int x )
|
||||
// ----------------------------------------------------------------------------------------------------------
|
||||
{
|
||||
NSMutableString *returnString = [[ NSMutableString alloc ]init];
|
||||
|
||||
int n;
|
||||
|
||||
for(n=0; n<8; n++)
|
||||
{
|
||||
if((x & 0x80) !=0)
|
||||
{
|
||||
|
||||
[ returnString appendString:@"1"];
|
||||
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
[ returnString appendString:@"0"];
|
||||
}
|
||||
x = x<<1;
|
||||
}
|
||||
|
||||
return [returnString autorelease];
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------------------------
|
||||
NSMutableString *bin2perms(NSString *binaryValue)
|
||||
// ----------------------------------------------------------------------------------------------------------
|
||||
{
|
||||
NSMutableString *returnString = [[ NSMutableString alloc ] init];
|
||||
NSRange subStringRange;
|
||||
subStringRange.length = 1;
|
||||
NSString *replaceWithChar;
|
||||
|
||||
for (int n=0; n < [binaryValue length]; n++)
|
||||
{
|
||||
subStringRange.location = n;
|
||||
// take the char
|
||||
// if pos = 0, 3,6
|
||||
if ( n == 0 || n == 3 || n ==6)
|
||||
{
|
||||
replaceWithChar = @"r";
|
||||
}
|
||||
if ( n == 1 || n == 4 || n ==7)
|
||||
{
|
||||
replaceWithChar = @"w";
|
||||
}
|
||||
if ( n == 2 || n == 5 || n ==7)
|
||||
{
|
||||
replaceWithChar = @"x";
|
||||
}
|
||||
|
||||
if ( [[binaryValue substringWithRange:subStringRange ] isEqualToString:@"1" ] )
|
||||
{
|
||||
[ returnString appendString:replaceWithChar ];
|
||||
}
|
||||
else
|
||||
{
|
||||
[ returnString appendString:@"-" ];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return [ returnString autorelease ];
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -41,11 +41,11 @@ void Platform_SetStatus( const char *status );
|
||||
qboolean Platform_DebuggerPresent( void );
|
||||
|
||||
// legacy iOS port functions
|
||||
#if TARGET_OS_IOS
|
||||
#if XASH_IOS
|
||||
int IOS_GetArgs( char ***argv );
|
||||
const char *IOS_GetDocsDir( void );
|
||||
const char *IOS_GetExecDir( void );
|
||||
void IOS_LaunchDialog( void );
|
||||
#include "platform/ios/lib_ios.h"
|
||||
#endif // TARGET_OS_IOS
|
||||
|
||||
#if XASH_WIN32 || XASH_LINUX
|
||||
@@ -212,9 +212,7 @@ static inline void Sys_RestoreCrashHandler( void )
|
||||
|
||||
static inline qboolean Platform_LibraryExists( const char *name, qboolean gamedironly )
|
||||
{
|
||||
#if XASH_IOS
|
||||
return IOS_LibraryExists( name );
|
||||
#elif XASH_ANDROID
|
||||
#if XASH_ANDROID
|
||||
// sorry, unimplemented
|
||||
return false;
|
||||
#else
|
||||
|
||||
@@ -36,7 +36,6 @@ GNU General Public License for more details.
|
||||
#include "filesystem.h"
|
||||
#include "server.h"
|
||||
#include "platform/android/lib_android.h"
|
||||
#include "platform/ios/lib_ios.h"
|
||||
|
||||
#ifdef XASH_NO_LIBDL
|
||||
void *dlsym( void *handle, const char *symbol )
|
||||
|
||||
@@ -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 );
|
||||
|
||||
@@ -248,13 +248,6 @@ static void SDLash_ActiveEvent( int gain )
|
||||
}
|
||||
else
|
||||
{
|
||||
#if TARGET_OS_IPHONE
|
||||
{
|
||||
// Keep running if ftp server enabled
|
||||
void IOS_StartBackgroundTask( void );
|
||||
IOS_StartBackgroundTask();
|
||||
}
|
||||
#endif
|
||||
host.status = HOST_NOFOCUS;
|
||||
|
||||
if( cls.key_dest == key_game )
|
||||
|
||||
@@ -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 );
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
101
engine/ref_api.h
101
engine/ref_api.h
@@ -19,11 +19,11 @@ GNU General Public License for more details.
|
||||
#include <stdarg.h>
|
||||
#include "com_image.h"
|
||||
#include "vgui_api.h"
|
||||
#include "const.h"
|
||||
#include "com_model.h"
|
||||
#include "cl_entity.h"
|
||||
#include "render_api.h"
|
||||
#include "triangleapi.h"
|
||||
#include "const.h"
|
||||
#include "cl_entity.h"
|
||||
#include "com_model.h"
|
||||
#include "studio.h"
|
||||
#include "r_efx.h"
|
||||
#include "filesystem.h"
|
||||
@@ -62,7 +62,17 @@ GNU General Public License for more details.
|
||||
// 11. Added size argument to Mod_ProcessRenderData
|
||||
// 12. Added Image_CalcImageSize
|
||||
// 13. Removed ignore_flags argument from GetCvarPointer
|
||||
#define REF_API_VERSION 13
|
||||
// 14. Removed reserved functions, they are leftover from RenderAPI
|
||||
// Removed CL_AddCustomBeam, it's now handled through R_AddEntity
|
||||
// 15. Replaced CL_InitStudioAPI with R_StudioFillAPI + R_StudioSetDrawInterface
|
||||
// Engine now builds engine_studio_api_t and handles client DLL negotiation
|
||||
// Replaced R_DrawStretchRaw and AVI_UploadRawFrame with GL_UpdateTexture
|
||||
// Added GL_CreateTexture, R_GetDetailScaleForTexture, R_SetDetailScaleForTexture
|
||||
// Removed R_Flush, VGUI_UploadTextureBlock, R_BeamCull, pfnGetStudioModelInterface
|
||||
// Moved RenderAPI and TriAPI filling to renderer via R_FillRenderAPI and R_FillTriAPI
|
||||
// Moved detail textures parsing and cinematic texture management to engine
|
||||
// Moved creation of default textures to the engine
|
||||
#define REF_API_VERSION 15
|
||||
|
||||
#define TF_SKY (TF_SKYSIDE|TF_NOMIPMAP|TF_ALLOW_NEAREST)
|
||||
#define TF_FONT (TF_NOMIPMAP|TF_CLAMP|TF_ALLOW_NEAREST)
|
||||
@@ -90,10 +100,10 @@ GNU General Public License for more details.
|
||||
#define MODEL_CLIENT BIT( 30 ) // client sprite
|
||||
|
||||
// goes into world.flags
|
||||
#define FWORLD_SKYSPHERE BIT( 0 )
|
||||
#define FWORLD_CUSTOM_SKYBOX BIT( 1 )
|
||||
#define FWORLD_WATERALPHA BIT( 2 )
|
||||
#define FWORLD_HAS_DELUXEMAP BIT( 3 )
|
||||
#define FWORLD_SKYSPHERE BIT( 0 )
|
||||
#define FWORLD_CUSTOM_SKYBOX BIT( 1 )
|
||||
#define FWORLD_WATERALPHA BIT( 2 )
|
||||
#define FWORLD_HAS_DELUXEMAP BIT( 3 )
|
||||
|
||||
// special rendermode for screenfade modulate
|
||||
// (probably will be expanded at some point)
|
||||
@@ -221,7 +231,7 @@ enum ref_defaultsprite_e
|
||||
};
|
||||
|
||||
// the order of first three is important!
|
||||
// so you can use this value in IEngineStudio.StudioIsHardware
|
||||
// so you can use this value in IEngineStudio.StudioIsHardware (but shouldn't)
|
||||
typedef enum ref_graphic_apis_e
|
||||
{
|
||||
REF_SOFTWARE, // hypothetical: just make a surface to draw on, in software
|
||||
@@ -387,7 +397,7 @@ typedef struct ref_api_s
|
||||
// brushes
|
||||
int (*Mod_SampleSizeForFace)( const struct msurface_s *surf );
|
||||
qboolean (*Mod_BoxVisible)( const vec3_t mins, const vec3_t maxs, const byte *visbits );
|
||||
mleaf_t *(*Mod_PointInLeaf)( const vec3_t p, mnode_t *node );
|
||||
mleaf_t *(*Mod_PointInLeaf)( const vec3_t p, mnode_t *node, struct model_s *mod );
|
||||
void (*R_DrawWorldHull)( void );
|
||||
void (*R_DrawModelHull)( model_t *mod );
|
||||
|
||||
@@ -429,7 +439,6 @@ typedef struct ref_api_s
|
||||
void *(*Mod_CacheCheck)( struct cache_user_s *c );
|
||||
void (*Mod_LoadCacheFile)( const char *path, struct cache_user_s *cu );
|
||||
void *(*Mod_Calloc)( int number, size_t size );
|
||||
int (*pfnGetStudioModelInterface)( int version, struct r_studio_interface_s **ppinterface, struct engine_studio_api_s *pstudio );
|
||||
|
||||
// memory
|
||||
poolhandle_t (*_Mem_AllocPool)( const char *name, const char *filename, int fileline )
|
||||
@@ -499,6 +508,9 @@ typedef struct ref_api_s
|
||||
|
||||
// for abstracting the engine's rendering
|
||||
ref_window_type_t (*R_GetWindowHandle)( void **handle, ref_window_type_t type );
|
||||
|
||||
// sprites
|
||||
struct mspriteframe_s *(*R_GetSpriteFrame)( const struct model_s *pModel, int frame, float yaw );
|
||||
} ref_api_t;
|
||||
|
||||
struct mip_s;
|
||||
@@ -533,10 +545,7 @@ typedef struct ref_interface_s
|
||||
void (*GL_SetRenderMode)( int renderMode );
|
||||
|
||||
qboolean (*R_AddEntity)( struct cl_entity_s *clent, int type );
|
||||
void (*CL_AddCustomBeam)( cl_entity_t *pEnvBeam );
|
||||
void (*R_ProcessEntData)( qboolean allocate, cl_entity_t *entities, unsigned int max_entities );
|
||||
void (*R_Flush)( unsigned int flush_flags );
|
||||
|
||||
// debug
|
||||
void (*R_ShowTextures)( void );
|
||||
|
||||
@@ -548,7 +557,6 @@ typedef struct ref_interface_s
|
||||
|
||||
// 2D
|
||||
void (*R_Set2DMode)( qboolean enable );
|
||||
void (*R_DrawStretchRaw)( float x, float y, float w, float h, int cols, int rows, const byte *data, qboolean dirty );
|
||||
void (*R_DrawStretchPic)( float x, float y, float w, float h, float s1, float t1, float s2, float t2, int texnum );
|
||||
void (*FillRGBA)( int rendermode, float x, float y, float w, float h, byte r, byte g, byte b, byte a ); // in screen space
|
||||
int (*WorldToScreen)( const vec3_t world, vec3_t screen ); // Returns 1 if it's z clipped
|
||||
@@ -570,16 +578,14 @@ typedef struct ref_interface_s
|
||||
// studio interface
|
||||
float (*R_StudioEstimateFrame)( cl_entity_t *e, mstudioseqdesc_t *pseqdesc, double time );
|
||||
void (*R_StudioLerpMovement)( cl_entity_t *e, double time, vec3_t origin, vec3_t angles );
|
||||
void (*CL_InitStudioAPI)( void );
|
||||
qboolean (*R_StudioFillAPI)( struct engine_studio_api_s *api, struct r_studio_interface_s *pDefaultDraw );
|
||||
void (*R_StudioSetDrawInterface)( struct r_studio_interface_s *pDraw );
|
||||
|
||||
// bmodel
|
||||
void (*R_SetSkyCloudsTextures)( int solidskyTexture, int alphaskyTexture );
|
||||
void (*GL_SubdivideSurface)( model_t *mod, msurface_t *fa );
|
||||
void (*CL_RunLightStyles)( lightstyle_t *ls );
|
||||
|
||||
// sprites
|
||||
void (*R_GetSpriteParms)( int *frameWidth, int *frameHeight, int *numFrames, int currentFrame, const model_t *pSprite );
|
||||
int (*R_GetSpriteTexture)( const model_t *m_pSpriteModel, int frame );
|
||||
|
||||
// model management
|
||||
// flags ignored for everything except spritemodels
|
||||
@@ -590,55 +596,27 @@ typedef struct ref_interface_s
|
||||
void (*CL_DrawParticles)( double frametime, particle_t *particles, float partsize );
|
||||
void (*CL_DrawTracers)( double frametime, particle_t *tracers );
|
||||
void (*CL_DrawBeams)( int fTrans , BEAM *beams );
|
||||
qboolean (*R_BeamCull)( const vec3_t start, const vec3_t end, qboolean pvsOnly );
|
||||
|
||||
// Xash3D Render Interface
|
||||
// Get renderer info (doesn't changes engine state at all)
|
||||
int (*RefGetParm)( int parm, int arg ); // generic
|
||||
void (*GetDetailScaleForTexture)( int texture, float *xScale, float *yScale );
|
||||
void (*GetExtraParmsForTexture)( int texture, byte *red, byte *green, byte *blue, byte *alpha );
|
||||
float (*GetFrameTime)( void );
|
||||
|
||||
// Set renderer info (tell engine about changes)
|
||||
void (*R_SetCurrentEntity)( struct cl_entity_s *ent ); // tell engine about both currententity and currentmodel
|
||||
void (*R_SetCurrentModel)( struct model_s *mod ); // change currentmodel but leave currententity unchanged
|
||||
// detail texture scale
|
||||
void (*R_GetDetailScaleForTexture)( int texture, float *xScale, float *yScale );
|
||||
void (*R_SetDetailScaleForTexture)( int texture, float xScale, float yScale );
|
||||
|
||||
// Texture tools
|
||||
// Texture tools (used by engine directly)
|
||||
int (*GL_CreateTexture)( const char *name, int width, int height, const void *buffer, texFlags_t flags );
|
||||
int (*GL_FindTexture)( const char *name );
|
||||
const char* (*GL_TextureName)( unsigned int texnum );
|
||||
const byte* (*GL_TextureData)( unsigned int texnum ); // may be NULL
|
||||
int (*GL_LoadTexture)( const char *name, const byte *buf, size_t size, int flags );
|
||||
int (*GL_CreateTexture)( const char *name, int width, int height, const void *buffer, texFlags_t flags );
|
||||
int (*GL_LoadTextureArray)( const char **names, int flags );
|
||||
int (*GL_CreateTextureArray)( const char *name, int width, int height, int depth, const void *buffer, texFlags_t flags );
|
||||
void (*GL_FreeTexture)( unsigned int texnum );
|
||||
void (*R_OverrideTextureSourceSize)( unsigned int texnum, unsigned int srcWidth, unsigned int srcHeight ); // used to override decal size for texture replacement
|
||||
|
||||
// Decals manipulating (draw & remove)
|
||||
void (*DrawSingleDecal)( struct decal_s *pDecal, struct msurface_s *fa );
|
||||
float *(*R_DecalSetupVerts)( struct decal_s *pDecal, struct msurface_s *surf, int texture, int *outCount );
|
||||
void (*R_EntityRemoveDecals)( struct model_s *mod ); // remove all the decals from specified entity (BSP only)
|
||||
void (*GL_UpdateTexture)( int texnum, int cols, int rows, int width, int height, const byte *buffer, pixformat_t fmt );
|
||||
|
||||
// AVI
|
||||
void (*AVI_UploadRawFrame)( int texture, int cols, int rows, int width, int height, const byte *data );
|
||||
|
||||
// glState related calls (must use this instead of normal gl-calls to prevent de-synchornize local states between engine and the client)
|
||||
// glState related calls (used by engine directly)
|
||||
void (*GL_Bind)( int tmu, unsigned int texnum );
|
||||
void (*GL_SelectTexture)( int tmu );
|
||||
void (*GL_LoadTextureMatrix)( const float *glmatrix );
|
||||
void (*GL_TexMatrixIdentity)( void );
|
||||
void (*GL_CleanUpTextureUnits)( int last ); // pass 0 for clear all the texture units
|
||||
void (*GL_TexGen)( unsigned int coord, unsigned int mode );
|
||||
void (*GL_TextureTarget)( unsigned int target ); // change texture unit mode without bind texture
|
||||
void (*GL_TexCoordArrayMode)( unsigned int texmode );
|
||||
void (*GL_UpdateTexSize)( int texnum, int width, int height, int depth ); // recalc statistics
|
||||
void (*GL_Reserved0)( void ); // for potential interface expansion without broken compatibility
|
||||
void (*GL_Reserved1)( void );
|
||||
|
||||
// Misc renderer functions
|
||||
void (*GL_DrawParticles)( const struct ref_viewpass_s *rvp, qboolean trans_pass, float frametime );
|
||||
colorVec (*LightVec)( const float *start, const float *end, float *lightspot, float *lightvec );
|
||||
struct mstudiotex_s *( *StudioGetTexture )( struct cl_entity_s *e );
|
||||
|
||||
// passed through R_RenderFrame (0 - use engine renderer, 1 - use custom client renderer)
|
||||
void (*GL_RenderFrame)( const struct ref_viewpass_s *rvp );
|
||||
@@ -652,28 +630,23 @@ typedef struct ref_interface_s
|
||||
void (*R_NewMap)( void );
|
||||
// clear the render entities before each frame
|
||||
void (*R_ClearScene)( void );
|
||||
// GL_GetProcAddress for client renderer
|
||||
void* (*R_GetProcAddress)( const char *name );
|
||||
|
||||
// TriAPI Interface
|
||||
// NOTE: implementation isn't required to be compatible
|
||||
// TriAPI Interface (functions used by engine wrappers)
|
||||
void (*TriRenderMode)( int mode );
|
||||
void (*Begin)( int primitiveCode );
|
||||
void (*End)( void );
|
||||
void (*Color4f)( float r, float g, float b, float a ); // real glColor4f
|
||||
void (*Color4ub)( unsigned char r, unsigned char g, unsigned char b, unsigned char a ); // real glColor4ub
|
||||
void (*TexCoord2f)( float u, float v );
|
||||
void (*Vertex3fv)( const float *worldPnt );
|
||||
void (*Vertex3f)( float x, float y, float z );
|
||||
void (*Fog)( float flFogColor[3], float flStart, float flEnd, int bOn ); //Works just like GL_FOG, flFogColor is r/g/b.
|
||||
void (*ScreenToWorld)( const float *screen, float *world );
|
||||
void (*GetMatrix)( const int pname, float *matrix );
|
||||
void (*FogParams)( float flDensity, int iFogSkybox );
|
||||
void (*CullFace)( TRICULLSTYLE mode );
|
||||
|
||||
// fill render_api_t and triangleapi_t with renderer-specific functions
|
||||
void (*R_FillRenderAPI)( struct render_api_s *api );
|
||||
void (*R_FillTriAPI)( struct triangleapi_s *api );
|
||||
|
||||
// vgui drawing implementation
|
||||
void (*VGUI_SetupDrawing)( qboolean rect );
|
||||
void (*VGUI_UploadTextureBlock)( int drawX, int drawY, const byte *rgba, int blockWidth, int blockHeight );
|
||||
} ref_interface_t;
|
||||
|
||||
typedef int (*REFAPI)( int version, ref_interface_t *pFunctionTable, ref_api_t* engfuncs, ref_globals_t *pGlobals );
|
||||
|
||||
@@ -406,6 +406,7 @@ extern convar_t sv_wateralpha;
|
||||
extern convar_t sv_wateramp;
|
||||
extern convar_t sv_voiceenable;
|
||||
extern convar_t sv_voicequality;
|
||||
extern convar_t sv_voice_singleplayer;
|
||||
extern convar_t sv_maxvelocity;
|
||||
extern convar_t sv_stepsize;
|
||||
extern convar_t sv_skyname;
|
||||
|
||||
@@ -3571,7 +3571,16 @@ static void SV_ParseVoiceData( sv_client_t *cl, sizebuf_t *msg )
|
||||
|
||||
MSG_ReadBytes( msg, received, size );
|
||||
|
||||
if( !sv_voiceenable.value || svs.maxclients <= 1 || cl->state != cs_spawned )
|
||||
if( !sv_voiceenable.value || cl->state != cs_spawned )
|
||||
return;
|
||||
|
||||
if( svgame.physFuncs.pfnVoiceData != NULL )
|
||||
{
|
||||
if( svgame.physFuncs.pfnVoiceData( client, frames, size, loopback, received ))
|
||||
return;
|
||||
}
|
||||
|
||||
if( svs.maxclients <= 1 && sv_voice_singleplayer.value == 0.0f )
|
||||
return;
|
||||
|
||||
for( i = 0; i < svs.maxclients; i++ )
|
||||
|
||||
@@ -463,7 +463,7 @@ static void SV_CreateBaseline( void )
|
||||
int delta_type;
|
||||
int entnum;
|
||||
|
||||
if( svs.maxclients > 1 )
|
||||
if( svs.maxclients > 1 || sv_voice_singleplayer.value )
|
||||
SV_WriteVoiceCodec( &sv.signon );
|
||||
|
||||
if( FBitSet( host.features, ENGINE_QUAKE_COMPATIBLE ))
|
||||
|
||||
@@ -124,6 +124,7 @@ static CVAR_DEFINE_AUTO( violence_agibs, "1", 0, "show alien gib entities" );
|
||||
// voice chat
|
||||
CVAR_DEFINE_AUTO( sv_voiceenable, "1", FCVAR_ARCHIVE|FCVAR_SERVER, "enable voice support" );
|
||||
CVAR_DEFINE_AUTO( sv_voicequality, "3", FCVAR_ARCHIVE, "voice chat quality level, from 0 to 5, higher is better" );
|
||||
CVAR_DEFINE_AUTO( sv_voice_singleplayer, "0", FCVAR_ARCHIVE|FCVAR_SERVER, "enable voice subsystem in singleplayer games (maxclients == 1)" );
|
||||
|
||||
// enttools
|
||||
CVAR_DEFINE_AUTO( sv_enttools_enable, "0", FCVAR_ARCHIVE|FCVAR_PROTECTED, "enable powerful and dangerous entity tools" );
|
||||
@@ -975,6 +976,7 @@ void SV_Init( void )
|
||||
|
||||
Cvar_RegisterVariable( &sv_voiceenable );
|
||||
Cvar_RegisterVariable( &sv_voicequality );
|
||||
Cvar_RegisterVariable( &sv_voice_singleplayer );
|
||||
Cvar_RegisterVariable( &sv_trace_messages );
|
||||
Cvar_RegisterVariable( &sv_enttools_enable );
|
||||
Cvar_RegisterVariable( &sv_enttools_maxfire );
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
92
ref/common/ref_common.h
Normal file
92
ref/common/ref_common.h
Normal file
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
ref_common.h - shared renderer code
|
||||
Copyright (C) 2010 Uncle Mike
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef REF_COMMON_H
|
||||
#define REF_COMMON_H
|
||||
|
||||
#include "xash3d_mathlib.h"
|
||||
#include "ref_api.h"
|
||||
|
||||
//
|
||||
// ref_context.c
|
||||
//
|
||||
extern ref_api_t gEngfuncs;
|
||||
extern ref_globals_t *gpGlobals;
|
||||
extern ref_client_t *gp_cl;
|
||||
extern ref_host_t *gp_host;
|
||||
extern const ref_interface_t gReffuncs;
|
||||
|
||||
DECLARE_ENGINE_SHARED_CVAR_LIST()
|
||||
|
||||
#define Assert( x ) if( !( x )) gEngfuncs.Host_Error( "assert failed at %s:%i\n", __FILE__, __LINE__ )
|
||||
|
||||
#define ENGINE_GET_PARM_ (*gEngfuncs.EngineGetParm)
|
||||
#define ENGINE_GET_PARM( parm ) ENGINE_GET_PARM_( (parm), 0 )
|
||||
|
||||
extern uint16_t rtable[MOD_FRAMES][MOD_FRAMES];
|
||||
void GL_InitRandomTable( void );
|
||||
|
||||
void _Mem_Free( void *data, const char *filename, int fileline );
|
||||
void *_Mem_Alloc( poolhandle_t poolptr, size_t size, qboolean clear, const char *filename, int fileline )
|
||||
ALLOC_CHECK( 2 ) MALLOC_LIKE( _Mem_Free, 1 ) WARN_UNUSED_RESULT;
|
||||
void *_Mem_Realloc( poolhandle_t poolptr, void *memptr, size_t size, qboolean clear, const char *filename, int fileline )
|
||||
ALLOC_CHECK( 3 ) WARN_UNUSED_RESULT;
|
||||
|
||||
#define Mem_Malloc( pool, size ) _Mem_Alloc( pool, size, false, __FILE__, __LINE__ )
|
||||
#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_AllocPool( name ) gEngfuncs._Mem_AllocPool( name, __FILE__, __LINE__ )
|
||||
#define Mem_FreePool( pool ) gEngfuncs._Mem_FreePool( pool, __FILE__, __LINE__ )
|
||||
#define Mem_EmptyPool( pool ) gEngfuncs._Mem_EmptyPool( pool, __FILE__, __LINE__ )
|
||||
|
||||
extern dlight_t *gp_dlights;
|
||||
extern int g_lightstylevalue[MAX_LIGHTSTYLES];
|
||||
extern poolhandle_t r_temppool;
|
||||
|
||||
//
|
||||
// ref_common cvars
|
||||
//
|
||||
extern convar_t r_dlight_virtual_radius;
|
||||
extern convar_t r_lighting_extended;
|
||||
|
||||
//
|
||||
// ref_math.c
|
||||
//
|
||||
void Matrix4x4_Concat( matrix4x4 out, const matrix4x4 in1, const matrix4x4 in2 );
|
||||
void Matrix4x4_ConcatTranslate( matrix4x4 out, float x, float y, float z );
|
||||
void Matrix4x4_ConcatRotate( matrix4x4 out, float angle, float x, float y, float z );
|
||||
void Matrix4x4_CreateProjection( matrix4x4 out, float xMax, float xMin, float yMax, float yMin, float zNear, float zFar );
|
||||
void Matrix4x4_CreateOrtho( matrix4x4 m, float xLeft, float xRight, float yBottom, float yTop, float zNear, float zFar );
|
||||
void Matrix4x4_CreateModelview( matrix4x4 out );
|
||||
void Matrix4x4_ToArrayFloatGL( const matrix4x4 in, float out[16] );
|
||||
|
||||
//
|
||||
// ref_light.c
|
||||
//
|
||||
void CL_RunLightStyles( lightstyle_t *ls );
|
||||
void R_PushDlightsForBmodel( model_t *model, int framecount, const matrix4x4 object_matrix );
|
||||
int R_PushDlights( model_t *model, int framecount );
|
||||
colorVec R_LightVec( const vec3_t start, const vec3_t end, vec3_t lspot, vec3_t lvec );
|
||||
colorVec R_LightPoint( const vec3_t p0 );
|
||||
void R_GatherPlayerLight( cl_entity_t *view );
|
||||
void R_UpdateSurfaceCachedLight( msurface_t *surf );
|
||||
|
||||
//
|
||||
// ref_image.c
|
||||
//
|
||||
byte *GL_ResampleTexture( const byte *source, int in_w, int in_h, int out_w, int out_h, qboolean isNormalMap );
|
||||
|
||||
#endif // REF_COMMON_H
|
||||
81
ref/common/ref_context.c
Normal file
81
ref/common/ref_context.c
Normal file
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
ref_context.c - shared renderer context
|
||||
Copyright (C) 2018 a1batross
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include "ref_common.h"
|
||||
#include "com_strings.h"
|
||||
|
||||
DEFINE_ENGINE_SHARED_CVAR_LIST()
|
||||
|
||||
ref_api_t gEngfuncs;
|
||||
ref_globals_t *gpGlobals;
|
||||
ref_client_t *gp_cl;
|
||||
ref_host_t *gp_host;
|
||||
uint16_t rtable[MOD_FRAMES][MOD_FRAMES];
|
||||
dlight_t *gp_dlights;
|
||||
int g_lightstylevalue[MAX_LIGHTSTYLES];
|
||||
poolhandle_t r_temppool;
|
||||
|
||||
void _Mem_Free( void *data, const char *filename, int fileline )
|
||||
{
|
||||
gEngfuncs._Mem_Free( data, filename, fileline );
|
||||
}
|
||||
|
||||
void *_Mem_Alloc( poolhandle_t poolptr, size_t size, qboolean clear, const char *filename, int fileline )
|
||||
{
|
||||
return gEngfuncs._Mem_Alloc( poolptr, size, clear, filename, fileline );
|
||||
}
|
||||
|
||||
void *_Mem_Realloc( poolhandle_t poolptr, void *memptr, size_t size, qboolean clear, const char *filename, int fileline )
|
||||
{
|
||||
return gEngfuncs._Mem_Realloc( poolptr, memptr, size, clear, filename, fileline );
|
||||
}
|
||||
|
||||
void GL_InitRandomTable( void )
|
||||
{
|
||||
int tu, tv;
|
||||
|
||||
for( tu = 0; tu < MOD_FRAMES; tu++ )
|
||||
{
|
||||
for( tv = 0; tv < MOD_FRAMES; tv++ )
|
||||
{
|
||||
rtable[tu][tv] = gEngfuncs.COM_RandomLong( 0, 0x7FFF );
|
||||
}
|
||||
}
|
||||
|
||||
gEngfuncs.COM_SetRandomSeed( 0 );
|
||||
}
|
||||
|
||||
int EXPORT GetRefAPI( int version, ref_interface_t *funcs, ref_api_t *engfuncs, ref_globals_t *globals );
|
||||
int EXPORT GetRefAPI( int version, ref_interface_t *funcs, ref_api_t *engfuncs, ref_globals_t *globals )
|
||||
{
|
||||
if( version != REF_API_VERSION )
|
||||
return 0;
|
||||
|
||||
// fill in our callbacks
|
||||
*funcs = gReffuncs;
|
||||
gEngfuncs = *engfuncs;
|
||||
gpGlobals = globals;
|
||||
|
||||
gp_cl = (ref_client_t *)ENGINE_GET_PARM( PARM_GET_CLIENT_PTR );
|
||||
gp_host = (ref_host_t *)ENGINE_GET_PARM( PARM_GET_HOST_PTR );
|
||||
gp_dlights = (dlight_t *)ENGINE_GET_PARM( PARM_GET_DLIGHTS_PTR );
|
||||
|
||||
RETRIEVE_ENGINE_SHARED_CVAR_LIST();
|
||||
|
||||
gEngfuncs.Cvar_RegisterVariable( &r_dlight_virtual_radius );
|
||||
gEngfuncs.Cvar_RegisterVariable( &r_lighting_extended );
|
||||
|
||||
return REF_API_VERSION;
|
||||
}
|
||||
108
ref/common/ref_image.c
Normal file
108
ref/common/ref_image.c
Normal file
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
ref_image.c - shared image code
|
||||
Copyright (C) 2010 Uncle Mike
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include "ref_common.h"
|
||||
#include "xash3d_mathlib.h"
|
||||
|
||||
/*
|
||||
================
|
||||
GL_ResampleTexture
|
||||
|
||||
Assume input buffer is RGBA
|
||||
=================
|
||||
*/
|
||||
byte *GL_ResampleTexture( const byte *source, int inWidth, int inHeight, int outWidth, int outHeight, qboolean isNormalMap )
|
||||
{
|
||||
uint frac, fracStep;
|
||||
uint *in = (uint *)source;
|
||||
uint p1[0x1000], p2[0x1000];
|
||||
byte *pix1, *pix2, *pix3, *pix4;
|
||||
uint *out, *inRow1, *inRow2;
|
||||
static byte *scaledImage = NULL; // pointer to a scaled image
|
||||
vec3_t normal;
|
||||
int i, x, y;
|
||||
|
||||
if( !source ) return NULL;
|
||||
|
||||
scaledImage = Mem_Realloc( r_temppool, scaledImage, outWidth * outHeight * 4 );
|
||||
fracStep = inWidth * 0x10000 / outWidth;
|
||||
out = (uint *)scaledImage;
|
||||
|
||||
frac = fracStep >> 2;
|
||||
for( i = 0; i < outWidth; i++ )
|
||||
{
|
||||
p1[i] = 4 * (frac >> 16);
|
||||
frac += fracStep;
|
||||
}
|
||||
|
||||
frac = (fracStep >> 2) * 3;
|
||||
for( i = 0; i < outWidth; i++ )
|
||||
{
|
||||
p2[i] = 4 * (frac >> 16);
|
||||
frac += fracStep;
|
||||
}
|
||||
|
||||
if( isNormalMap )
|
||||
{
|
||||
for( y = 0; y < outHeight; y++, out += outWidth )
|
||||
{
|
||||
inRow1 = in + inWidth * (int)(((float)y + 0.25f) * inHeight / outHeight);
|
||||
inRow2 = in + inWidth * (int)(((float)y + 0.75f) * inHeight / outHeight);
|
||||
|
||||
for( x = 0; x < outWidth; x++ )
|
||||
{
|
||||
pix1 = (byte *)inRow1 + p1[x];
|
||||
pix2 = (byte *)inRow1 + p2[x];
|
||||
pix3 = (byte *)inRow2 + p1[x];
|
||||
pix4 = (byte *)inRow2 + p2[x];
|
||||
|
||||
normal[0] = MAKE_SIGNED( pix1[0] ) + MAKE_SIGNED( pix2[0] ) + MAKE_SIGNED( pix3[0] ) + MAKE_SIGNED( pix4[0] );
|
||||
normal[1] = MAKE_SIGNED( pix1[1] ) + MAKE_SIGNED( pix2[1] ) + MAKE_SIGNED( pix3[1] ) + MAKE_SIGNED( pix4[1] );
|
||||
normal[2] = MAKE_SIGNED( pix1[2] ) + MAKE_SIGNED( pix2[2] ) + MAKE_SIGNED( pix3[2] ) + MAKE_SIGNED( pix4[2] );
|
||||
|
||||
if( !VectorNormalizeLength( normal ))
|
||||
VectorSet( normal, 0.5f, 0.5f, 1.0f );
|
||||
|
||||
((byte *)(out+x))[0] = 128 + (byte)(127.0f * normal[0]);
|
||||
((byte *)(out+x))[1] = 128 + (byte)(127.0f * normal[1]);
|
||||
((byte *)(out+x))[2] = 128 + (byte)(127.0f * normal[2]);
|
||||
((byte *)(out+x))[3] = 255;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for( y = 0; y < outHeight; y++, out += outWidth )
|
||||
{
|
||||
inRow1 = in + inWidth * (int)(((float)y + 0.25f) * inHeight / outHeight);
|
||||
inRow2 = in + inWidth * (int)(((float)y + 0.75f) * inHeight / outHeight);
|
||||
|
||||
for( x = 0; x < outWidth; x++ )
|
||||
{
|
||||
pix1 = (byte *)inRow1 + p1[x];
|
||||
pix2 = (byte *)inRow1 + p2[x];
|
||||
pix3 = (byte *)inRow2 + p1[x];
|
||||
pix4 = (byte *)inRow2 + p2[x];
|
||||
|
||||
((byte *)(out+x))[0] = (pix1[0] + pix2[0] + pix3[0] + pix4[0]) >> 2;
|
||||
((byte *)(out+x))[1] = (pix1[1] + pix2[1] + pix3[1] + pix4[1]) >> 2;
|
||||
((byte *)(out+x))[2] = (pix1[2] + pix2[2] + pix3[2] + pix4[2]) >> 2;
|
||||
((byte *)(out+x))[3] = (pix1[3] + pix2[3] + pix3[3] + pix4[3]) >> 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return scaledImage;
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
gl_rlight.c - dynamic and static lights
|
||||
ref_light.c - shared light code
|
||||
Copyright (C) 2010 Uncle Mike
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
@@ -13,19 +13,13 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include "gl_local.h"
|
||||
#include "pm_local.h"
|
||||
#include "studio.h"
|
||||
#include "ref_common.h"
|
||||
#include "xash3d_mathlib.h"
|
||||
#include "ref_params.h"
|
||||
#include "pm_local.h"
|
||||
|
||||
/*
|
||||
=============================================================================
|
||||
CVAR_DEFINE_AUTO( r_dlight_virtual_radius, "3", FCVAR_GLCONFIG, "increase dlight radius virtually by this amount" );
|
||||
CVAR_DEFINE_AUTO( r_lighting_extended, "1", FCVAR_GLCONFIG, "allow to get lighting from world and bmodels" );
|
||||
|
||||
DYNAMIC LIGHTS
|
||||
|
||||
=============================================================================
|
||||
*/
|
||||
/*
|
||||
==================
|
||||
CL_RunLightStyles
|
||||
@@ -34,16 +28,17 @@ CL_RunLightStyles
|
||||
*/
|
||||
void CL_RunLightStyles( lightstyle_t *ls )
|
||||
{
|
||||
const model_t *world = gp_cl->models[1];
|
||||
int i;
|
||||
float frametime = (gp_cl->time - gp_cl->oldtime);
|
||||
float frametime = gp_cl->time - gp_cl->oldtime;
|
||||
|
||||
if( !WORLDMODEL )
|
||||
if( !world )
|
||||
return;
|
||||
|
||||
if( !WORLDMODEL->lightdata )
|
||||
if( r_fullbright->value || !world->lightdata )
|
||||
{
|
||||
for( i = 0; i < MAX_LIGHTSTYLES; i++ )
|
||||
tr.lightstylevalue[i] = 256 * 256;
|
||||
g_lightstylevalue[i] = 256 * 256;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -59,13 +54,13 @@ void CL_RunLightStyles( lightstyle_t *ls )
|
||||
|
||||
if( !ls[i].length )
|
||||
{
|
||||
tr.lightstylevalue[i] = 256;
|
||||
g_lightstylevalue[i] = 256;
|
||||
continue;
|
||||
}
|
||||
else if( ls[i].length == 1 )
|
||||
{
|
||||
// single length style so don't bother interpolating
|
||||
tr.lightstylevalue[i] = ( ls[i].map[0] ) * 22;
|
||||
g_lightstylevalue[i] = ls[i].map[0] * 22;
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -73,7 +68,7 @@ void CL_RunLightStyles( lightstyle_t *ls )
|
||||
|
||||
if( !ls[i].interp || !cl_lightstyle_lerping->value )
|
||||
{
|
||||
tr.lightstylevalue[i] = ls[i].map[flight%ls[i].length] * 22;
|
||||
g_lightstylevalue[i] = ls[i].map[flight % ls[i].length] * 22;
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -90,7 +85,7 @@ void CL_RunLightStyles( lightstyle_t *ls )
|
||||
k = ls[i].map[clight % ls[i].length];
|
||||
l += (float)( k * 22.0f ) * lerpfrac;
|
||||
|
||||
tr.lightstylevalue[i] = (int)l;
|
||||
g_lightstylevalue[i] = (int)l;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -99,45 +94,39 @@ void CL_RunLightStyles( lightstyle_t *ls )
|
||||
R_MarkLights
|
||||
=============
|
||||
*/
|
||||
void R_MarkLights( const dlight_t *light, int bit, const mnode_t *node )
|
||||
static void R_MarkLights( const dlight_t *light, int bit, const mnode_t *node, model_t *model, int dlightframecount )
|
||||
{
|
||||
const float virtual_radius = light->radius * Q_max( 1.0f, r_dlight_virtual_radius.value );
|
||||
const float maxdist = light->radius * light->radius;
|
||||
float dist;
|
||||
int i;
|
||||
mnode_t *children[2];
|
||||
int firstsurface, numsurfaces;
|
||||
|
||||
start:
|
||||
|
||||
if( !node || node->contents < 0 )
|
||||
return;
|
||||
|
||||
dist = PlaneDiff( light->origin, node->plane );
|
||||
|
||||
node_children( children, node, RI.currentmodel );
|
||||
float dist = PlaneDiff( light->origin, node->plane );
|
||||
|
||||
if( dist > virtual_radius )
|
||||
{
|
||||
node = children[0];
|
||||
node = node_child( node, 0, model );
|
||||
goto start;
|
||||
}
|
||||
|
||||
if( dist < -virtual_radius )
|
||||
{
|
||||
node = children[1];
|
||||
node = node_child( node, 1, model );
|
||||
goto start;
|
||||
}
|
||||
|
||||
// mark the polygons
|
||||
firstsurface = node_firstsurface( node, RI.currentmodel );
|
||||
numsurfaces = node_numsurfaces( node, RI.currentmodel );
|
||||
const float dist_sq = dist * dist;
|
||||
|
||||
for( i = 0; i < numsurfaces; i++ )
|
||||
// mark the polygons
|
||||
int firstsurface = node_firstsurface( node, model );
|
||||
int numsurfaces = node_numsurfaces( node, model );
|
||||
|
||||
for( int i = 0; i < numsurfaces && dist_sq < maxdist; i++ )
|
||||
{
|
||||
vec3_t impact;
|
||||
float s, t, l;
|
||||
msurface_t *surf = &RI.currentmodel->surfaces[firstsurface + i];
|
||||
msurface_t *surf = &model->surfaces[firstsurface + i];
|
||||
const mextrasurf_t *info = surf->info;
|
||||
|
||||
if( surf->plane->type < 3 )
|
||||
@@ -160,19 +149,20 @@ 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 )
|
||||
if( surf->dlightframe != dlightframecount )
|
||||
{
|
||||
surf->dlightbits = bit;
|
||||
surf->dlightframe = tr.dlightframecount;
|
||||
surf->dlightframe = dlightframecount;
|
||||
}
|
||||
else surf->dlightbits |= bit;
|
||||
}
|
||||
|
||||
R_MarkLights( light, bit, children[0] );
|
||||
R_MarkLights( light, bit, children[1] );
|
||||
R_MarkLights( light, bit, node_child( node, 0, model ), model, dlightframecount );
|
||||
node = node_child( node, 1, model );
|
||||
goto start;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -180,31 +170,40 @@ start:
|
||||
R_PushDlights
|
||||
=============
|
||||
*/
|
||||
void R_PushDlights( void )
|
||||
int R_PushDlights( model_t *model, int framecount )
|
||||
{
|
||||
int i;
|
||||
if( !model )
|
||||
return framecount;
|
||||
|
||||
tr.dlightframecount = tr.framecount;
|
||||
|
||||
RI.currententity = CL_GetEntityByIndex( 0 );
|
||||
|
||||
// no world -- no dlights
|
||||
if( !RI.currententity )
|
||||
return;
|
||||
|
||||
RI.currentmodel = RI.currententity->model;
|
||||
|
||||
for( i = 0; i < MAX_DLIGHTS; i++ )
|
||||
for( int i = 0; i < MAX_DLIGHTS; i++ )
|
||||
{
|
||||
dlight_t *l = &tr.dlights[i];
|
||||
const dlight_t *l = &gp_dlights[i];
|
||||
|
||||
if( l->die < gp_cl->time || !l->radius )
|
||||
continue;
|
||||
|
||||
if( GL_FrustumCullSphere( &RI.frustum, l->origin, l->radius, 15 ))
|
||||
R_MarkLights( l, 1 << i, model->nodes, model, framecount );
|
||||
}
|
||||
|
||||
return framecount;
|
||||
}
|
||||
|
||||
void R_PushDlightsForBmodel( model_t *model, int framecount, const matrix4x4 object_matrix )
|
||||
{
|
||||
for( int i = 0; i < MAX_DLIGHTS; i++ )
|
||||
{
|
||||
dlight_t *l = &gp_dlights[i];
|
||||
|
||||
if( l->die < gp_cl->time || !l->radius )
|
||||
continue;
|
||||
|
||||
R_MarkLights( l, 1<<i, RI.currentmodel->nodes );
|
||||
vec3_t oldorigin;
|
||||
VectorCopy( l->origin, oldorigin );
|
||||
|
||||
Matrix4x4_VectorITransform( object_matrix, oldorigin, l->origin );
|
||||
R_MarkLights( l, 1 << i, model->nodes + model->hulls[0].firstclipnode, model, framecount );
|
||||
|
||||
VectorCopy( oldorigin, l->origin );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -226,19 +225,7 @@ R_RecursiveLightPoint
|
||||
*/
|
||||
static qboolean R_RecursiveLightPoint( model_t *model, mnode_t *node, float p1f, float p2f, colorVec *cv, const vec3_t start, const vec3_t end )
|
||||
{
|
||||
float front, back, frac, midf;
|
||||
int i, map, side, size;
|
||||
float ds, dt, s, t;
|
||||
int sample_size;
|
||||
color24 *lm, *dm;
|
||||
mextrasurf_t *info;
|
||||
msurface_t *surf;
|
||||
mtexinfo_t *tex;
|
||||
matrix3x4 tbn;
|
||||
vec3_t mid;
|
||||
mnode_t *children[2];
|
||||
int firstsurface, numsurfaces;
|
||||
|
||||
start:
|
||||
// didn't hit anything
|
||||
if( !node || node->contents < 0 )
|
||||
{
|
||||
@@ -246,25 +233,26 @@ 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 );
|
||||
|
||||
// calculate mid point
|
||||
front = PlaneDiff( start, node->plane );
|
||||
back = PlaneDiff( end, node->plane );
|
||||
float front = PlaneDiff( start, node->plane );
|
||||
float back = PlaneDiff( end, node->plane );
|
||||
|
||||
side = front < 0;
|
||||
int side = front < 0;
|
||||
if(( back < 0 ) == side )
|
||||
return R_RecursiveLightPoint( model, children[side], p1f, p2f, cv, start, end );
|
||||
{
|
||||
node = node_child( node, side, model );
|
||||
goto start;
|
||||
}
|
||||
|
||||
frac = front / ( front - back );
|
||||
float frac = front / ( front - back );
|
||||
|
||||
vec3_t mid;
|
||||
VectorLerp( start, frac, end, mid );
|
||||
midf = p1f + ( p2f - p1f ) * frac;
|
||||
|
||||
float 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 )
|
||||
@@ -274,27 +262,27 @@ static qboolean R_RecursiveLightPoint( model_t *model, mnode_t *node, float p1f,
|
||||
}
|
||||
|
||||
// check for impact on this node
|
||||
surf = model->surfaces + firstsurface;
|
||||
int firstsurface = node_firstsurface( node, model );
|
||||
int numsurfaces = node_numsurfaces( node, model );
|
||||
|
||||
VectorCopy( mid, g_trace_lightspot );
|
||||
|
||||
for( i = 0; i < numsurfaces; i++, surf++ )
|
||||
for( int i = 0; i < numsurfaces; i++ )
|
||||
{
|
||||
int smax, tmax;
|
||||
|
||||
tex = surf->texinfo;
|
||||
info = surf->info;
|
||||
const msurface_t *surf = &model->surfaces[firstsurface + i];
|
||||
const mextrasurf_t *info = surf->info;
|
||||
|
||||
if( FBitSet( surf->flags, SURF_DRAWTILED ))
|
||||
continue; // no lightmaps
|
||||
|
||||
s = DotProduct( mid, info->lmvecs[0] ) + info->lmvecs[0][3];
|
||||
t = DotProduct( mid, info->lmvecs[1] ) + info->lmvecs[1][3];
|
||||
float s = DotProduct( mid, info->lmvecs[0] ) + info->lmvecs[0][3];
|
||||
float t = DotProduct( mid, info->lmvecs[1] ) + info->lmvecs[1][3];
|
||||
|
||||
if( s < info->lightmapmins[0] || t < info->lightmapmins[1] )
|
||||
continue;
|
||||
|
||||
ds = s - info->lightmapmins[0];
|
||||
dt = t - info->lightmapmins[1];
|
||||
float ds = s - info->lightmapmins[0];
|
||||
float dt = t - info->lightmapmins[1];
|
||||
|
||||
if ( ds > info->lightextents[0] || dt > info->lightextents[1] )
|
||||
continue;
|
||||
@@ -304,21 +292,25 @@ static qboolean R_RecursiveLightPoint( model_t *model, mnode_t *node, float p1f,
|
||||
if( !surf->samples )
|
||||
return true;
|
||||
|
||||
sample_size = gEngfuncs.Mod_SampleSizeForFace( surf );
|
||||
smax = (info->lightextents[0] / sample_size) + 1;
|
||||
tmax = (info->lightextents[1] / sample_size) + 1;
|
||||
int sample_size = gEngfuncs.Mod_SampleSizeForFace( surf );
|
||||
int smax = (info->lightextents[0] / sample_size) + 1;
|
||||
int tmax = (info->lightextents[1] / sample_size) + 1;
|
||||
|
||||
ds /= sample_size;
|
||||
dt /= sample_size;
|
||||
|
||||
lm = surf->samples + Q_rint( dt ) * smax + Q_rint( ds );
|
||||
g_trace_fraction = midf;
|
||||
size = smax * tmax;
|
||||
dm = NULL;
|
||||
|
||||
const color24 *lm = surf->samples + Q_rint( dt ) * smax + Q_rint( ds );
|
||||
const color24 *dm = NULL;
|
||||
matrix3x4 tbn;
|
||||
|
||||
if( surf->info->deluxemap )
|
||||
{
|
||||
vec3_t faceNormal;
|
||||
|
||||
dm = surf->info->deluxemap + Q_rint( dt ) * smax + Q_rint( ds );
|
||||
|
||||
if( FBitSet( surf->flags, SURF_PLANEBACK ))
|
||||
VectorNegate( surf->plane->normal, faceNormal );
|
||||
else VectorCopy( surf->plane->normal, faceNormal );
|
||||
@@ -336,12 +328,13 @@ static qboolean R_RecursiveLightPoint( model_t *model, mnode_t *node, float p1f,
|
||||
VectorNormalize( tbn[0] );
|
||||
VectorNormalize( tbn[1] );
|
||||
VectorNormalize( tbn[2] );
|
||||
dm = surf->info->deluxemap + Q_rint( dt ) * smax + Q_rint( ds );
|
||||
}
|
||||
|
||||
for( map = 0; map < MAXLIGHTMAPS && surf->styles[map] != 255; map++ )
|
||||
int size = smax * tmax;
|
||||
|
||||
for( int map = 0; map < MAXLIGHTMAPS && surf->styles[map] != 255; map++ )
|
||||
{
|
||||
uint scale = tr.lightstylevalue[surf->styles[map]];
|
||||
uint scale = g_lightstylevalue[surf->styles[map]];
|
||||
|
||||
cv->r += lm->r * scale;
|
||||
cv->g += lm->g * scale;
|
||||
@@ -366,88 +359,80 @@ 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 );
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
R_LightVec
|
||||
R_LightVecInternal
|
||||
|
||||
check bspmodels to get light from
|
||||
=================
|
||||
*/
|
||||
static colorVec R_LightVecInternal( const vec3_t start, const vec3_t end, vec3_t lspot, vec3_t lvec )
|
||||
{
|
||||
float last_fraction;
|
||||
int i, maxEnts = 1;
|
||||
colorVec light, cv;
|
||||
if( lspot )
|
||||
VectorClear( lspot );
|
||||
|
||||
if( lspot ) VectorClear( lspot );
|
||||
if( lvec ) VectorClear( lvec );
|
||||
if( lvec )
|
||||
VectorClear( lvec );
|
||||
|
||||
if( WORLDMODEL && WORLDMODEL->lightdata )
|
||||
if( !gp_cl->models[1] || !gp_cl->models[1]->lightdata )
|
||||
return (colorVec){ 255, 255, 255, 0 };
|
||||
|
||||
float last_fraction = 1.0f;
|
||||
int max_ents = r_lighting_extended.value ? MAX_PHYSENTS : 1; // get light from bmodels too
|
||||
colorVec light = { 0 };
|
||||
|
||||
// check all the bsp-models
|
||||
for( int i = 0; i < max_ents; i++ )
|
||||
{
|
||||
light.r = light.g = light.b = light.a = 0;
|
||||
last_fraction = 1.0f;
|
||||
const physent_t *pe = gEngfuncs.EV_GetPhysent( i );
|
||||
|
||||
// get light from bmodels too
|
||||
if( r_lighting_extended.value )
|
||||
maxEnts = MAX_PHYSENTS;
|
||||
if( !pe )
|
||||
break;
|
||||
|
||||
// check all the bsp-models
|
||||
for( i = 0; i < maxEnts; i++ )
|
||||
if( !pe->model || pe->model->type != mod_brush )
|
||||
continue; // skip non-bsp models
|
||||
|
||||
mnode_t *pnodes = &pe->model->nodes[pe->model->hulls[0].firstclipnode];
|
||||
vec3_t offset, start_l, end_l;
|
||||
|
||||
VectorSubtract( pe->model->hulls[0].clip_mins, vec3_origin, offset );
|
||||
VectorAdd( offset, pe->origin, offset );
|
||||
VectorSubtract( start, offset, start_l );
|
||||
VectorSubtract( end, offset, end_l );
|
||||
|
||||
// rotate start and end into the models frame of reference
|
||||
if( !VectorIsNull( pe->angles ))
|
||||
{
|
||||
physent_t *pe = gEngfuncs.EV_GetPhysent( i );
|
||||
vec3_t offset, start_l, end_l;
|
||||
mnode_t *pnodes;
|
||||
matrix4x4 matrix;
|
||||
|
||||
if( !pe )
|
||||
break;
|
||||
|
||||
if( !pe->model || pe->model->type != mod_brush )
|
||||
continue; // skip non-bsp models
|
||||
|
||||
pnodes = &pe->model->nodes[pe->model->hulls[0].firstclipnode];
|
||||
VectorSubtract( pe->model->hulls[0].clip_mins, vec3_origin, offset );
|
||||
VectorAdd( offset, pe->origin, offset );
|
||||
VectorSubtract( start, offset, start_l );
|
||||
VectorSubtract( end, offset, end_l );
|
||||
|
||||
// rotate start and end into the models frame of reference
|
||||
if( !VectorIsNull( pe->angles ))
|
||||
{
|
||||
Matrix4x4_CreateFromEntity( matrix, pe->angles, offset, 1.0f );
|
||||
Matrix4x4_VectorITransform( matrix, start, start_l );
|
||||
Matrix4x4_VectorITransform( matrix, end, end_l );
|
||||
}
|
||||
|
||||
VectorClear( g_trace_lightspot );
|
||||
VectorClear( g_trace_lightvec );
|
||||
g_trace_fraction = 1.0f;
|
||||
|
||||
if( !R_RecursiveLightPoint( pe->model, pnodes, 0.0f, 1.0f, &cv, start_l, end_l ))
|
||||
continue; // didn't hit anything
|
||||
|
||||
if( g_trace_fraction < last_fraction )
|
||||
{
|
||||
if( lspot ) VectorCopy( g_trace_lightspot, lspot );
|
||||
if( lvec ) VectorNormalize2( g_trace_lightvec, lvec );
|
||||
|
||||
light.r = Q_min(( cv.r >> 8 ), 255 );
|
||||
light.g = Q_min(( cv.g >> 8 ), 255 );
|
||||
light.b = Q_min(( cv.b >> 8 ), 255 );
|
||||
last_fraction = g_trace_fraction;
|
||||
|
||||
if(( light.r + light.g + light.b ) != 0 )
|
||||
break; // we get light now
|
||||
}
|
||||
matrix4x4 matrix;
|
||||
Matrix4x4_CreateFromEntity( matrix, pe->angles, offset, 1.0f );
|
||||
Matrix4x4_VectorITransform( matrix, start, start_l );
|
||||
Matrix4x4_VectorITransform( matrix, end, end_l );
|
||||
}
|
||||
|
||||
VectorClear( g_trace_lightspot );
|
||||
VectorClear( g_trace_lightvec );
|
||||
g_trace_fraction = 1.0f;
|
||||
|
||||
colorVec cv;
|
||||
if( !R_RecursiveLightPoint( pe->model, pnodes, 0.0f, 1.0f, &cv, start_l, end_l ))
|
||||
continue; // didn't hit anything
|
||||
|
||||
if( g_trace_fraction < last_fraction )
|
||||
{
|
||||
if( lspot ) VectorCopy( g_trace_lightspot, lspot );
|
||||
if( lvec ) VectorNormalize2( g_trace_lightvec, lvec );
|
||||
|
||||
light.r = Q_min(( cv.r >> 8 ), 255 );
|
||||
light.g = Q_min(( cv.g >> 8 ), 255 );
|
||||
light.b = Q_min(( cv.b >> 8 ), 255 );
|
||||
last_fraction = g_trace_fraction;
|
||||
|
||||
if(( light.r + light.g + light.b ) != 0 )
|
||||
break; // we get light now
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
light.r = light.g = light.b = 255;
|
||||
light.a = 0;
|
||||
}
|
||||
|
||||
return light;
|
||||
@@ -462,7 +447,7 @@ check bspmodels to get light from
|
||||
*/
|
||||
colorVec R_LightVec( const vec3_t start, const vec3_t end, vec3_t lspot, vec3_t lvec )
|
||||
{
|
||||
colorVec light = R_LightVecInternal( start, end, lspot, lvec );
|
||||
colorVec light = R_LightVecInternal( start, end, lspot, lvec );
|
||||
|
||||
if( r_lighting_extended.value && lspot != NULL && lvec != NULL )
|
||||
{
|
||||
@@ -483,9 +468,34 @@ light from floor
|
||||
*/
|
||||
colorVec R_LightPoint( const vec3_t p0 )
|
||||
{
|
||||
vec3_t p1;
|
||||
vec3_t p1;
|
||||
|
||||
VectorSet( p1, p0[0], p0[1], p0[2] - 2048.0f );
|
||||
|
||||
return R_LightVec( p0, p1, NULL, NULL );
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
R_GatherPlayerLight
|
||||
|
||||
get light level of an entity and set it as player's light level
|
||||
=================
|
||||
*/
|
||||
void R_GatherPlayerLight( cl_entity_t *view )
|
||||
{
|
||||
colorVec c = R_LightPoint( view->origin );
|
||||
|
||||
gEngfuncs.SetLocalLightLevel(( c.r + c.g + c.b ) / 3 );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
R_SetCacheState
|
||||
================
|
||||
*/
|
||||
void R_UpdateSurfaceCachedLight( msurface_t *surf )
|
||||
{
|
||||
for( int i = 0; i < MAXLIGHTMAPS && surf->styles[i] != 255; i++ )
|
||||
surf->cached_light[i] = g_lightstylevalue[surf->styles[i]];
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
gl_rmath.c - renderer mathlib
|
||||
ref_math.c - renderer mathlib
|
||||
Copyright (C) 2010 Uncle Mike
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
@@ -13,8 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include "r_local.h"
|
||||
#include "xash3d_mathlib.h"
|
||||
#include "ref_common.h"
|
||||
|
||||
/*
|
||||
========================================================================
|
||||
@@ -99,7 +98,27 @@ void Matrix4x4_CreateModelview( matrix4x4 out )
|
||||
out[1][2] = 1.0f;
|
||||
}
|
||||
|
||||
void Matrix4x4_CreateTranslate( matrix4x4 out, float x, float y, float z )
|
||||
void Matrix4x4_ToArrayFloatGL( const matrix4x4 in, float out[16] )
|
||||
{
|
||||
out[ 0] = in[0][0];
|
||||
out[ 1] = in[1][0];
|
||||
out[ 2] = in[2][0];
|
||||
out[ 3] = in[3][0];
|
||||
out[ 4] = in[0][1];
|
||||
out[ 5] = in[1][1];
|
||||
out[ 6] = in[2][1];
|
||||
out[ 7] = in[3][1];
|
||||
out[ 8] = in[0][2];
|
||||
out[ 9] = in[1][2];
|
||||
out[10] = in[2][2];
|
||||
out[11] = in[3][2];
|
||||
out[12] = in[0][3];
|
||||
out[13] = in[1][3];
|
||||
out[14] = in[2][3];
|
||||
out[15] = in[3][3];
|
||||
}
|
||||
|
||||
static void Matrix4x4_CreateTranslate( matrix4x4 out, float x, float y, float z )
|
||||
{
|
||||
out[0][0] = 1.0f;
|
||||
out[0][1] = 0.0f;
|
||||
@@ -119,7 +138,7 @@ void Matrix4x4_CreateTranslate( matrix4x4 out, float x, float y, float z )
|
||||
out[3][3] = 1.0f;
|
||||
}
|
||||
|
||||
void Matrix4x4_CreateRotate( matrix4x4 out, float angle, float x, float y, float z )
|
||||
static void Matrix4x4_CreateRotate( matrix4x4 out, float angle, float x, float y, float z )
|
||||
{
|
||||
float len, c, s;
|
||||
|
||||
27
ref/common/wscript
Normal file
27
ref/common/wscript
Normal file
@@ -0,0 +1,27 @@
|
||||
#! /usr/bin/env python
|
||||
# encoding: utf-8
|
||||
|
||||
def options(opt):
|
||||
pass
|
||||
|
||||
def configure(conf):
|
||||
pass
|
||||
|
||||
def build(bld):
|
||||
use = ['engine_includes', 'sdk_includes', 'werror']
|
||||
|
||||
# FIXME: figure out why psvita needs it and how can we avoid it
|
||||
if bld.env.DEST_OS == 'psvita':
|
||||
bld.env.CFLAGS_cstlib.remove('-fno-PIC')
|
||||
bld.env.CFLAGS += ['-fPIC']
|
||||
else:
|
||||
use += ['public']
|
||||
|
||||
bld.stlib(source = bld.path.ant_glob('*.c'),
|
||||
target = 'ref_common',
|
||||
includes = '.',
|
||||
export_includes = '.',
|
||||
defines = 'REF_DLL=1',
|
||||
use = use,
|
||||
subsystem = bld.env.MSVC_SUBSYSTEM
|
||||
)
|
||||
@@ -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;
|
||||
@@ -581,7 +578,7 @@ static void R_AliasDynamicLight( cl_entity_t *ent, alight_t *plight )
|
||||
if( !plight || !ent )
|
||||
return;
|
||||
|
||||
if( !RI.drawWorld || r_fullbright->value || FBitSet( ent->curstate.effects, EF_FULLBRIGHT ))
|
||||
if( !FBitSet( RI.rvp.flags, RF_DRAW_WORLD ) || r_fullbright->value || FBitSet( ent->curstate.effects, EF_FULLBRIGHT ))
|
||||
{
|
||||
plight->shadelight = 0;
|
||||
plight->ambientlight = 192;
|
||||
@@ -687,7 +684,7 @@ static void R_AliasDynamicLight( cl_entity_t *ent, alight_t *plight )
|
||||
|
||||
for( lnum = 0; lnum < MAX_DLIGHTS; lnum++ )
|
||||
{
|
||||
const dlight_t *dl = &tr.dlights[lnum];
|
||||
const dlight_t *dl = &gp_dlights[lnum];
|
||||
|
||||
if( dl->die < g_alias.time || !r_dynamic->value )
|
||||
continue;
|
||||
@@ -1129,7 +1126,7 @@ init current time for a given model
|
||||
*/
|
||||
static void R_AliasSetupTimings( void )
|
||||
{
|
||||
if( RI.drawWorld )
|
||||
if( FBitSet( RI.rvp.flags, RF_DRAW_WORLD ))
|
||||
{
|
||||
// synchronize with server time
|
||||
g_alias.time = gp_cl->time;
|
||||
|
||||
@@ -61,7 +61,7 @@ void GL_BackendEndFrame( void )
|
||||
{
|
||||
mleaf_t *curleaf;
|
||||
|
||||
if( r_speeds->value <= 0 || !RI.drawWorld )
|
||||
if( r_speeds->value <= 0 || !FBitSet( RI.rvp.flags, RF_DRAW_WORLD ))
|
||||
return;
|
||||
|
||||
if( !RI.viewleaf )
|
||||
@@ -616,7 +616,7 @@ qboolean VID_CubemapShot( const char *base, uint size, const float *vieworg, qbo
|
||||
string basename;
|
||||
int i = 1, flags, result;
|
||||
|
||||
if( !RI.drawWorld || !WORLDMODEL )
|
||||
if( !FBitSet( RI.rvp.flags, RF_DRAW_WORLD ) || !WORLDMODEL )
|
||||
return false;
|
||||
|
||||
// make sure the specified size is valid
|
||||
@@ -633,7 +633,7 @@ qboolean VID_CubemapShot( const char *base, uint size, const float *vieworg, qbo
|
||||
r_side = Mem_Calloc( r_temppool, sizeof( rgbdata_t ));
|
||||
|
||||
// use client vieworg
|
||||
if( !vieworg ) vieworg = RI.vieworg;
|
||||
if( !vieworg ) vieworg = RI.rvp.vieworigin;
|
||||
|
||||
for( i = 0; i < 6; i++ )
|
||||
{
|
||||
|
||||
@@ -98,7 +98,7 @@ static void R_BeamComputeNormal( const vec3_t vStartPos, const vec3_t vNextPos,
|
||||
VectorSubtract( vStartPos, vNextPos, vTangentY );
|
||||
|
||||
// vDirToBeam = vector from viewer origin to beam
|
||||
VectorSubtract( vStartPos, RI.vieworg, vDirToBeam );
|
||||
VectorSubtract( vStartPos, RI.rvp.vieworigin, vDirToBeam );
|
||||
|
||||
// get a vector that is perpendicular to us and perpendicular to the beam.
|
||||
// this is used to fatten the beam.
|
||||
@@ -114,7 +114,7 @@ R_BeamCull
|
||||
Cull the beam by bbox
|
||||
==============
|
||||
*/
|
||||
qboolean R_BeamCull( const vec3_t start, const vec3_t end, qboolean pvsOnly )
|
||||
static qboolean R_BeamCull( const vec3_t start, const vec3_t end, qboolean pvsOnly )
|
||||
{
|
||||
vec3_t mins, maxs;
|
||||
int i;
|
||||
@@ -151,28 +151,6 @@ qboolean R_BeamCull( const vec3_t start, const vec3_t end, qboolean pvsOnly )
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
CL_AddCustomBeam
|
||||
|
||||
Add the beam that encoded as custom entity
|
||||
================
|
||||
*/
|
||||
void CL_AddCustomBeam( cl_entity_t *pEnvBeam )
|
||||
{
|
||||
if( tr.draw_list->num_beam_entities >= MAX_VISIBLE_PACKET )
|
||||
{
|
||||
gEngfuncs.Con_Printf( S_ERROR "Too many beams %d!\n", tr.draw_list->num_beam_entities );
|
||||
return;
|
||||
}
|
||||
|
||||
if( pEnvBeam )
|
||||
{
|
||||
tr.draw_list->beam_entities[tr.draw_list->num_beam_entities] = pEnvBeam;
|
||||
tr.draw_list->num_beam_entities++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
==============================================================
|
||||
@@ -1028,7 +1006,7 @@ static void R_BeamDraw( BEAM *pbeam, float frametime )
|
||||
float flDistance;
|
||||
|
||||
// fade the beam if the player's not looking at the source
|
||||
VectorSubtract( RI.vieworg, pbeam->source, localDir );
|
||||
VectorSubtract( RI.rvp.vieworigin, pbeam->source, localDir );
|
||||
flDot = DotProduct( delta, localDir );
|
||||
VectorScale( delta, flDot, vecProjection );
|
||||
VectorSubtract( localDir, vecProjection, tmp );
|
||||
|
||||
@@ -22,20 +22,7 @@ GNU General Public License for more details.
|
||||
#include "gl4es/include/gl4esinit.h"
|
||||
#endif
|
||||
|
||||
ref_api_t gEngfuncs;
|
||||
ref_globals_t *gpGlobals;
|
||||
ref_client_t *gp_cl;
|
||||
ref_host_t *gp_host;
|
||||
|
||||
void _Mem_Free( void *data, const char *filename, int fileline )
|
||||
{
|
||||
gEngfuncs._Mem_Free( data, filename, fileline );
|
||||
}
|
||||
|
||||
void *_Mem_Alloc( poolhandle_t poolptr, size_t size, qboolean clear, const char *filename, int fileline )
|
||||
{
|
||||
return gEngfuncs._Mem_Alloc( poolptr, size, clear, filename, fileline );
|
||||
}
|
||||
|
||||
static void R_ClearScreen( void )
|
||||
{
|
||||
@@ -132,7 +119,6 @@ static void Mod_UnloadTextures( model_t *mod )
|
||||
Mod_BrushUnloadTextures( mod );
|
||||
break;
|
||||
case mod_sprite:
|
||||
Mod_SpriteUnloadTextures( mod->cache.data );
|
||||
break;
|
||||
default:
|
||||
Assert( 0 );
|
||||
@@ -159,7 +145,7 @@ static qboolean Mod_ProcessRenderData( model_t *mod, qboolean create, const byte
|
||||
loaded = true;
|
||||
break;
|
||||
case mod_sprite:
|
||||
Mod_LoadSpriteModel( mod, buf, &loaded, mod->numtexinfo );
|
||||
loaded = true;
|
||||
break;
|
||||
case mod_alias:
|
||||
Mod_LoadAliasModel( mod, buf, &loaded );
|
||||
@@ -228,7 +214,7 @@ static int GL_RefGetParm( int parm, int arg )
|
||||
return glState.activeTMU;
|
||||
case PARM_LIGHTSTYLEVALUE:
|
||||
arg = bound( 0, arg, MAX_LIGHTSTYLES - 1 );
|
||||
return tr.lightstylevalue[arg];
|
||||
return g_lightstylevalue[arg];
|
||||
case PARM_MAX_IMAGE_UNITS:
|
||||
return GL_MaxTextureUnits();
|
||||
case PARM_REBUILD_GAMMA:
|
||||
@@ -258,6 +244,14 @@ static void R_GetDetailScaleForTexture( int texture, float *xScale, float *yScal
|
||||
if( yScale ) *yScale = glt->yscale;
|
||||
}
|
||||
|
||||
static void R_SetDetailScaleForTexture( int texture, float xScale, float yScale )
|
||||
{
|
||||
gl_texture_t *glt = R_GetTexture( texture );
|
||||
|
||||
glt->xscale = xScale;
|
||||
glt->yscale = yScale;
|
||||
}
|
||||
|
||||
static void R_GetExtraParmsForTexture( int texture, byte *red, byte *green, byte *blue, byte *density )
|
||||
{
|
||||
gl_texture_t *glt = R_GetTexture( texture );
|
||||
@@ -325,11 +319,6 @@ static void R_ProcessEntData( qboolean allocate, cl_entity_t *entities, unsigned
|
||||
gEngfuncs.drawFuncs->R_ProcessEntData( allocate );
|
||||
}
|
||||
|
||||
static void GAME_EXPORT R_Flush( unsigned int flags )
|
||||
{
|
||||
// stub
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
R_SetSkyCloudsTextures
|
||||
@@ -383,11 +372,6 @@ static qboolean R_SetDisplayTransform( ref_screen_rotation_t rotate, int offset_
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void GAME_EXPORT VGUI_UploadTextureBlock( int drawX, int drawY, const byte *rgba, int blockWidth, int blockHeight )
|
||||
{
|
||||
pglTexSubImage2D( GL_TEXTURE_2D, 0, drawX, drawY, blockWidth, blockHeight, GL_RGBA, GL_UNSIGNED_BYTE, rgba );
|
||||
}
|
||||
|
||||
static void GAME_EXPORT VGUI_SetupDrawing( qboolean rect )
|
||||
{
|
||||
pglEnable( GL_BLEND );
|
||||
@@ -427,7 +411,86 @@ static const char *R_GetConfigName( void )
|
||||
return "opengl";
|
||||
}
|
||||
|
||||
static const ref_interface_t gReffuncs =
|
||||
static void R_NewMap( void )
|
||||
{
|
||||
texture_t *tx;
|
||||
int i;
|
||||
|
||||
tr.worldmodel = gp_cl->models[1];
|
||||
|
||||
R_ClearDecals(); // clear all level decals
|
||||
|
||||
R_StudioResetPlayerModels();
|
||||
|
||||
// clear out efrags in case the level hasn't been reloaded
|
||||
for( i = 0; i < WORLDMODEL->numleafs; i++ )
|
||||
WORLDMODEL->leafs[i+1].efrags = NULL;
|
||||
|
||||
glState.isFogEnabled = false;
|
||||
tr.skytexturenum = -1;
|
||||
pglDisable( GL_FOG );
|
||||
|
||||
// clearing texture chains
|
||||
for( i = 0; i < WORLDMODEL->numtextures; i++ )
|
||||
{
|
||||
if( !WORLDMODEL->textures[i] )
|
||||
continue;
|
||||
|
||||
tx = WORLDMODEL->textures[i];
|
||||
|
||||
if( !Q_strncmp( tx->name, "sky", 3 ) && tx->width == ( tx->height * 2 ))
|
||||
tr.skytexturenum = i;
|
||||
|
||||
tx->texturechain = NULL;
|
||||
}
|
||||
|
||||
GL_BuildLightmaps ();
|
||||
|
||||
R_ClearVBO();
|
||||
if( R_HasEnabledVBO( ))
|
||||
R_GenerateVBO();
|
||||
R_ResetRipples();
|
||||
|
||||
if( gEngfuncs.drawFuncs->R_NewMap != NULL )
|
||||
gEngfuncs.drawFuncs->R_NewMap();
|
||||
}
|
||||
|
||||
static void R_FillRenderAPI( render_api_t *api )
|
||||
{
|
||||
api->GetExtraParmsForTexture = R_GetExtraParmsForTexture;
|
||||
api->GetFrameTime = R_GetFrameTime;
|
||||
api->R_SetCurrentEntity = R_SetCurrentEntity;
|
||||
api->R_SetCurrentModel = R_SetCurrentModel;
|
||||
api->GL_CreateTexture = GL_CreateTexture;
|
||||
api->GL_LoadTextureArray = GL_LoadTextureArray;
|
||||
api->GL_CreateTextureArray = GL_CreateTextureArray;
|
||||
api->DrawSingleDecal = DrawSingleDecal;
|
||||
api->R_DecalSetupVerts = R_DecalSetupVerts;
|
||||
api->R_EntityRemoveDecals = R_EntityRemoveDecals;
|
||||
api->GL_SelectTexture = GL_SelectTexture;
|
||||
api->GL_LoadTextureMatrix = GL_LoadTexMatrixExt;
|
||||
api->GL_TexMatrixIdentity = GL_LoadIdentityTexMatrix;
|
||||
api->GL_CleanUpTextureUnits = GL_CleanUpTextureUnits;
|
||||
api->GL_TexGen = GL_TexGen;
|
||||
api->GL_TextureTarget = GL_TextureTarget;
|
||||
api->GL_TexCoordArrayMode = GL_SetTexCoordArrayMode;
|
||||
api->GL_UpdateTexSize = GL_UpdateTexSize;
|
||||
api->GL_DrawParticles = CL_DrawParticlesExternal;
|
||||
api->LightVec = R_LightVec;
|
||||
api->StudioGetTexture = R_StudioGetTexture;
|
||||
api->GL_GetProcAddress = R_GetProcAddress;
|
||||
}
|
||||
|
||||
static void R_FillTriAPI( triangleapi_t *api )
|
||||
{
|
||||
api->TexCoord2f = TriTexCoord2f;
|
||||
api->Fog = TriFog;
|
||||
api->ScreenToWorld = R_ScreenToWorld;
|
||||
api->GetMatrix = TriGetMatrix;
|
||||
api->FogParams = TriFogParams;
|
||||
}
|
||||
|
||||
const ref_interface_t gReffuncs =
|
||||
{
|
||||
R_Init,
|
||||
R_Shutdown,
|
||||
@@ -452,9 +515,7 @@ static const ref_interface_t gReffuncs =
|
||||
GL_SetRenderMode,
|
||||
|
||||
R_AddEntity,
|
||||
CL_AddCustomBeam,
|
||||
R_ProcessEntData,
|
||||
R_Flush,
|
||||
|
||||
R_ShowTextures,
|
||||
|
||||
@@ -464,7 +525,6 @@ static const ref_interface_t gReffuncs =
|
||||
R_SetupSky,
|
||||
|
||||
R_Set2DMode,
|
||||
R_DrawStretchRaw,
|
||||
R_DrawStretchPic,
|
||||
CL_FillRGBA,
|
||||
R_WorldToScreen,
|
||||
@@ -481,14 +541,13 @@ static const ref_interface_t gReffuncs =
|
||||
|
||||
R_StudioEstimateFrame,
|
||||
R_StudioLerpMovement,
|
||||
CL_InitStudioAPI,
|
||||
R_StudioFillAPI,
|
||||
R_StudioSetDrawInterface,
|
||||
|
||||
R_SetSkyCloudsTextures,
|
||||
GL_SubdivideSurface,
|
||||
CL_RunLightStyles,
|
||||
|
||||
R_GetSpriteParms,
|
||||
R_GetSpriteTexture,
|
||||
|
||||
Mod_ProcessRenderData,
|
||||
Mod_StudioLoadTextures,
|
||||
@@ -496,47 +555,23 @@ static const ref_interface_t gReffuncs =
|
||||
CL_DrawParticles,
|
||||
CL_DrawTracers,
|
||||
CL_DrawBeams,
|
||||
R_BeamCull,
|
||||
|
||||
GL_RefGetParm,
|
||||
|
||||
R_GetDetailScaleForTexture,
|
||||
R_GetExtraParmsForTexture,
|
||||
R_GetFrameTime,
|
||||
|
||||
R_SetCurrentEntity,
|
||||
R_SetCurrentModel,
|
||||
R_SetDetailScaleForTexture,
|
||||
|
||||
GL_CreateTexture,
|
||||
GL_FindTexture,
|
||||
GL_TextureName,
|
||||
GL_TextureData,
|
||||
GL_LoadTexture,
|
||||
GL_CreateTexture,
|
||||
GL_LoadTextureArray,
|
||||
GL_CreateTextureArray,
|
||||
GL_FreeTexture,
|
||||
R_OverrideTextureSourceSize,
|
||||
|
||||
DrawSingleDecal,
|
||||
R_DecalSetupVerts,
|
||||
R_EntityRemoveDecals,
|
||||
|
||||
R_UploadStretchRaw,
|
||||
GL_UpdateTexture,
|
||||
|
||||
GL_Bind,
|
||||
GL_SelectTexture,
|
||||
GL_LoadTexMatrixExt,
|
||||
GL_LoadIdentityTexMatrix,
|
||||
GL_CleanUpTextureUnits,
|
||||
GL_TexGen,
|
||||
GL_TextureTarget,
|
||||
GL_SetTexCoordArrayMode,
|
||||
GL_UpdateTexSize,
|
||||
NULL,
|
||||
NULL,
|
||||
|
||||
CL_DrawParticlesExternal,
|
||||
R_LightVec,
|
||||
R_StudioGetTexture,
|
||||
|
||||
R_RenderFrame,
|
||||
Mod_SetOrthoBounds,
|
||||
@@ -544,39 +579,19 @@ static const ref_interface_t gReffuncs =
|
||||
Mod_GetCurrentVis,
|
||||
R_NewMap,
|
||||
R_ClearScene,
|
||||
R_GetProcAddress,
|
||||
|
||||
TriRenderMode,
|
||||
TriBegin,
|
||||
TriEnd,
|
||||
_TriColor4f,
|
||||
_TriColor4ub,
|
||||
TriTexCoord2f,
|
||||
TriVertex3fv,
|
||||
TriVertex3f,
|
||||
TriFog,
|
||||
R_ScreenToWorld,
|
||||
TriGetMatrix,
|
||||
TriFogParams,
|
||||
TriCullFace,
|
||||
|
||||
R_FillRenderAPI,
|
||||
R_FillTriAPI,
|
||||
|
||||
VGUI_SetupDrawing,
|
||||
VGUI_UploadTextureBlock,
|
||||
};
|
||||
|
||||
int EXPORT GetRefAPI( int version, ref_interface_t *funcs, ref_api_t *engfuncs, ref_globals_t *globals );
|
||||
int EXPORT GetRefAPI( int version, ref_interface_t *funcs, ref_api_t *engfuncs, ref_globals_t *globals )
|
||||
{
|
||||
if( version != REF_API_VERSION )
|
||||
return 0;
|
||||
|
||||
// fill in our callbacks
|
||||
*funcs = gReffuncs;
|
||||
gEngfuncs = *engfuncs;
|
||||
gpGlobals = globals;
|
||||
|
||||
gp_cl = (ref_client_t *)ENGINE_GET_PARM( PARM_GET_CLIENT_PTR );
|
||||
gp_host = (ref_host_t *)ENGINE_GET_PARM( PARM_GET_HOST_PTR );
|
||||
|
||||
return REF_API_VERSION;
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ qboolean R_CullModel( const cl_entity_t *e, const vec3_t absmin, const vec3_t ab
|
||||
if( ENGINE_GET_PARM( PARM_DEV_OVERVIEW ))
|
||||
return true;
|
||||
|
||||
if( RP_NORMALPASS() && !ENGINE_GET_PARM( PARM_THIRDPERSON ) && CL_IsViewEntityLocalPlayer())
|
||||
if( !FBitSet( RI.rvp.flags, RF_DRAW_CUBEMAP ) && !ENGINE_GET_PARM( PARM_THIRDPERSON ) && CL_IsViewEntityLocalPlayer())
|
||||
return false;
|
||||
|
||||
return true;
|
||||
@@ -67,25 +67,25 @@ 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;
|
||||
|
||||
// can use normal.z for world (optimisation)
|
||||
if( RI.drawOrtho )
|
||||
if( FBitSet( RI.rvp.flags, RF_DRAW_OVERVIEW ))
|
||||
{
|
||||
vec3_t orthonormal;
|
||||
|
||||
@@ -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 );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -880,6 +868,10 @@ void DrawSingleDecal( decal_t *pDecal, msurface_t *fa )
|
||||
|
||||
GL_Bind( XASH_TEXTURE0, pDecal->texture );
|
||||
|
||||
if( FBitSet( R_GetTexture( pDecal->texture )->flags, TF_PREMULTIPLIED ))
|
||||
pglBlendFunc( GL_ONE, GL_ONE_MINUS_SRC_ALPHA );
|
||||
else pglBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
|
||||
|
||||
pglBegin( GL_POLYGON );
|
||||
|
||||
for( i = 0; i < numVerts; i++, v += VERTEXSIZE )
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user