Compare commits

..

2 Commits

Author SHA1 Message Date
Alibek Omarov
9cd456e414 ci: add wafcache to all targets that use Waf, except Android which uses generated CMakeLists instead 2025-01-13 20:24:45 +03:00
Alibek Omarov
4a7a5f0b8c wscript: add option to use wafcache 2025-01-13 20:02:59 +03:00
110 changed files with 2717 additions and 2909 deletions

View File

@@ -1,10 +1,10 @@
task: task:
name: freebsd-14-amd64 name: freebsd-14-amd64
freebsd_instance: freebsd_instance:
image_family: freebsd-14-2 image_family: freebsd-14-0
setup_script: setup_script:
- pkg update - pkg update
- pkg install -y pkgconf git sdl2 python fontconfig libvorbis opusfile bzip2 - pkg install -y pkgconf git sdl2 python fontconfig opus
- git submodule update --init --recursive - git submodule update --init --recursive
test_script: test_script:
- ./scripts/cirrus/build_freebsd.sh dedicated - ./scripts/cirrus/build_freebsd.sh dedicated
@@ -16,7 +16,7 @@ task:
image_family: freebsd-15-0-snap image_family: freebsd-15-0-snap
setup_script: setup_script:
- pkg update - pkg update
- pkg install -y pkgconf git sdl2 python fontconfig libvorbis opusfile bzip2 - pkg install -y pkgconf git sdl2 python fontconfig opus
- git submodule update --init --recursive - git submodule update --init --recursive
test_script: test_script:
- ./scripts/cirrus/build_freebsd.sh dedicated - ./scripts/cirrus/build_freebsd.sh dedicated

View File

@@ -6,8 +6,21 @@ jobs:
# steps: # steps:
# - name: Cleanup # - name: Cleanup
# run: rm -rf .* || true # run: rm -rf .* || true
get_prev_runid:
runs-on: ubuntu-latest
outputs:
value: ${{ steps.do.outputs.value }}
steps:
- id: do
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
value=$(gh run -R ${{ github.repository }} list -b${{ github.ref_name }} -ssuccess -L1 --json databaseId -q'.[0].databaseId')
echo "Last run ID is $value"
echo "value=$value" >> "$GITHUB_OUTPUT"
build: build:
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
needs: get_prev_runid
continue-on-error: true continue-on-error: true
strategy: strategy:
fail-fast: false fail-fast: false
@@ -67,15 +80,21 @@ jobs:
targetarch: amd64 targetarch: amd64
env: env:
SDL_VERSION: 2.30.11 SDL_VERSION: 2.30.11
FFMPEG_VERSION: 7.1
GH_CPU_ARCH: ${{ matrix.targetarch }} GH_CPU_ARCH: ${{ matrix.targetarch }}
GH_CPU_OS: ${{ matrix.targetos }}
GH_CROSSCOMPILING: ${{ matrix.cross }} GH_CROSSCOMPILING: ${{ matrix.cross }}
WAFCACHE: ${{ github.workspace }}/wafcache/
WAFCACHE_EVICT_MAX_BYTES: 1000000 # github only gives 10gb for the whole repository
WAFCACHE_STATS: 1 # enable statistics in build log
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v4 uses: actions/checkout@v4
with: with:
submodules: recursive submodules: recursive
- name: Restore cache
uses: actions/cache/restore@v4
with:
key: ${{ runner.os }}-${{ matrix.targetos }}-${{ matrix.targetarch }}-${{ needs.get_prev_runid.outputs.value }}
path: ${{ github.workspace }}/wafcache/
- name: Install dependencies - name: Install dependencies
run: bash scripts/gha/deps_${{ matrix.targetos }}.sh run: bash scripts/gha/deps_${{ matrix.targetos }}.sh
- name: Build engine - name: Build engine
@@ -87,6 +106,12 @@ jobs:
with: with:
name: artifact-${{ matrix.targetos }}-${{ matrix.targetarch }} name: artifact-${{ matrix.targetos }}-${{ matrix.targetarch }}
path: artifacts/* path: artifacts/*
- name: Save cache
uses: actions/cache/save@v4
with:
path: ${{ github.workspace }}/wafcache/
key: ${{ runner.os }}-${{ matrix.targetos }}-${{ matrix.targetarch }}-${{ github.run_id }}
flatpak: flatpak:
runs-on: ubuntu-latest runs-on: ubuntu-latest
strategy: strategy:

View File

@@ -25,4 +25,5 @@ def build(bld):
name = 'extras.pk3', name = 'extras.pk3',
files = srcdir.ant_glob('**/*'), files = srcdir.ant_glob('**/*'),
relative_to = srcdir, relative_to = srcdir,
compresslevel = 0,
install_path = install_path) install_path = install_path)

File diff suppressed because it is too large Load Diff

View File

@@ -50,8 +50,4 @@ GNU General Public License for more details.
#define LIB_WIN32 2 #define LIB_WIN32 2
#define LIB_STATIC 3 #define LIB_STATIC 3
// movies (XASH_AVI)
#define AVI_NULL 0
#define AVI_FFMPEG 1
#endif /* BACKENDS_H */ #endif /* BACKENDS_H */

View File

@@ -78,6 +78,7 @@ SETUP BACKENDS DEFINITIONS
// usually only 10-20 fds availiable // usually only 10-20 fds availiable
#define XASH_REDUCE_FD #define XASH_REDUCE_FD
#endif #endif
#endif // XASH_DEDICATED #endif // XASH_DEDICATED
// //
@@ -104,17 +105,6 @@ SETUP BACKENDS DEFINITIONS
#endif // !XASH_WIN32 #endif // !XASH_WIN32
#endif #endif
//
// determine movie playback backend
//
#ifndef XASH_AVI
#if HAVE_FFMPEG
#define XASH_AVI AVI_FFMPEG
#else
#define XASH_AVI AVI_NULL
#endif
#endif
#ifdef XASH_STATIC_LIBS #ifdef XASH_STATIC_LIBS
#define XASH_LIB LIB_STATIC #define XASH_LIB LIB_STATIC
#define XASH_INTERNAL_GAMELIBS #define XASH_INTERNAL_GAMELIBS

View File

@@ -157,23 +157,6 @@ typedef struct decallist_s
modelstate_t studio_state; // studio decals only modelstate_t studio_state; // studio decals only
} decallist_t; } decallist_t;
enum movie_parms_e
{
AVI_PARM_LAST = 0, // marker for SetParm to end parse parsing arguments
AVI_RENDER_TEXNUM, // (int) sets texture to draw into, if 0 will draw to screen
AVI_RENDER_X, // (int) when set to screen, sets position where to draw
AVI_RENDER_Y,
AVI_RENDER_W, // (int) sets texture or screen width
AVI_RENDER_H, // set to -1 to draw full screen
AVI_REWIND, // no argument, rewind playback to the beginning
AVI_ENTNUM, // (int) entity number, -1 for no spatialization
AVI_VOLUME, // (int) volume from 0 to 255
AVI_ATTN, // (float) attenuation value
AVI_PAUSE, // no argument, pauses playback
AVI_RESUME, // no argument, resumes playback
};
struct movie_state_s;
struct ref_viewpass_s; struct ref_viewpass_s;
typedef struct render_api_s typedef struct render_api_s
@@ -210,16 +193,16 @@ typedef struct render_api_s
void (*R_EntityRemoveDecals)( struct model_s *mod ); // remove all the decals from specified entity (BSP only) void (*R_EntityRemoveDecals)( struct model_s *mod ); // remove all the decals from specified entity (BSP only)
// AVIkit support // AVIkit support
struct movie_state_s *(*AVI_LoadVideo)( const char *filename, qboolean load_audio ); void *(*AVI_LoadVideo)( const char *filename, qboolean load_audio );
qboolean (*AVI_GetVideoInfo)( struct movie_state_s *Avi, int *xres, int *yres, float *duration ); // a1ba: changed longs to int int (*AVI_GetVideoInfo)( void *Avi, int *xres, int *yres, float *duration ); // a1ba: changed longs to int
int (*AVI_GetVideoFrameNumber)( struct movie_state_s *Avi, float time ); int (*AVI_GetVideoFrameNumber)( void *Avi, float time );
byte *(*AVI_GetVideoFrame)( struct movie_state_s *Avi, int frame ); byte *(*AVI_GetVideoFrame)( void *Avi, int frame );
void (*AVI_UploadRawFrame)( int texture, int cols, int rows, int width, int height, const byte *data ); void (*AVI_UploadRawFrame)( int texture, int cols, int rows, int width, int height, const byte *data );
void (*AVI_FreeVideo)( struct movie_state_s *Avi ); void (*AVI_FreeVideo)( void *Avi );
qboolean (*AVI_IsActive)( struct movie_state_s *Avi ); int (*AVI_IsActive)( void *Avi );
void (*AVI_StreamSound)( struct movie_state_s *Avi, int entnum, float fvol, float attn, float synctime ); void (*AVI_StreamSound)( void *Avi, int entnum, float fvol, float attn, float synctime );
qboolean (*AVI_Think)( struct movie_state_s *Avi ); void (*AVI_Reserved0)( void ); // for potential interface expansion without broken compatibility
qboolean (*AVI_SetParm)( struct movie_state_s *Avi, enum movie_parms_e parm, ... ); void (*AVI_Reserved1)( void );
// 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 (must use this instead of normal gl-calls to prevent de-synchornize local states between engine and the client)
void (*GL_Bind)( int tmu, unsigned int texnum ); void (*GL_Bind)( int tmu, unsigned int texnum );

View File

@@ -16,17 +16,19 @@
#include STDINT_H #include STDINT_H
#include <assert.h> #include <assert.h>
typedef uint8_t byte; typedef unsigned char byte;
typedef float vec_t; typedef int sound_t;
typedef vec_t vec2_t[2]; typedef float vec_t;
typedef vec_t vec3_t[3]; typedef vec_t vec2_t[2];
typedef vec_t vec4_t[4]; typedef vec_t vec3_t[3];
typedef vec_t quat_t[4]; typedef vec_t vec4_t[4];
typedef byte rgba_t[4]; // unsigned byte colorpack typedef vec_t quat_t[4];
typedef byte rgb_t[3]; // unsigned byte colorpack typedef byte rgba_t[4]; // unsigned byte colorpack
typedef vec_t matrix3x4[3][4]; typedef byte rgb_t[3]; // unsigned byte colorpack
typedef vec_t matrix4x4[4][4]; typedef vec_t matrix3x4[3][4];
typedef uint32_t poolhandle_t; typedef vec_t matrix4x4[4][4];
typedef uint32_t poolhandle_t;
#undef true #undef true
#undef false #undef false
@@ -37,10 +39,18 @@ typedef enum { false, true } qboolean;
typedef int qboolean; typedef int qboolean;
#endif #endif
#define MAX_STRING 256 // generic string typedef uint64_t longtime_t;
#define MAX_VA_STRING 1024 // compatibility macro
#define MAX_SYSPATH 1024 // system filepath #define MAX_STRING 256 // generic string
#define MAX_MODS 512 // environment games that engine can keep visible #define MAX_INFO_STRING 256 // infostrings are transmitted across network
#define MAX_SERVERINFO_STRING 512 // server handles too many settings. expand to 1024?
#define MAX_LOCALINFO_STRING 32768 // localinfo used on server and not sended to the clients
#define MAX_SYSPATH 1024 // system filepath
#define MAX_VA_STRING 1024 // string length returned by va()
#define MAX_PRINT_MSG 8192 // how many symbols can handle single call of Con_Printf or Con_DPrintf
#define MAX_TOKEN 2048 // parse token length
#define MAX_MODS 512 // environment games that engine can keep visible
#define MAX_USERMSG_LENGTH 2048 // don't modify it's relies on a client-side definitions
#define BIT( n ) ( 1U << ( n )) #define BIT( n ) ( 1U << ( n ))
#define BIT64( n ) ( 1ULL << ( n )) #define BIT64( n ) ( 1ULL << ( n ))
@@ -199,16 +209,35 @@ _inline float LittleFloat( float f )
#endif #endif
typedef unsigned int dword; typedef unsigned int dword;
typedef unsigned int uint; typedef unsigned int uint;
typedef char string[MAX_STRING]; typedef unsigned long ulong;
typedef off_t fs_offset_t; typedef char string[MAX_STRING];
typedef struct file_s file_t; // normal file
typedef struct stream_s stream_t; // sound stream for background music playing
typedef off_t fs_offset_t;
#if XASH_WIN32 #if XASH_WIN32
typedef int fs_size_t; // return type of _read, _write funcs typedef int fs_size_t; // return type of _read, _write funcs
#else /* !XASH_WIN32 */ #else /* !XASH_WIN32 */
typedef ssize_t fs_size_t; typedef ssize_t fs_size_t;
#endif /* !XASH_WIN32 */ #endif /* !XASH_WIN32 */
typedef struct dllfunc_s
{
const char *name;
void **func;
} dllfunc_t;
typedef struct dll_info_s
{
const char *name; // name of library
const dllfunc_t *fcts; // list of dll exports
const size_t num_fcts;
qboolean crash; // crash if dll not found
void *link; // hinstance of loading library
} dll_info_t;
typedef void (*setpair_t)( const char *key, const void *value, const void *buffer, void *numpairs );
typedef void *(*pfnCreateInterface_t)( const char *, int * ); typedef void *(*pfnCreateInterface_t)( const char *, int * );
// config strings are a general means of communication from // config strings are a general means of communication from

View File

@@ -18,11 +18,12 @@ GNU General Public License for more details.
// //
// avikit.c // avikit.c
// //
typedef struct movie_state_s movie_state_t; typedef struct movie_state_s movie_state_t;
int AVI_GetVideoFrameNumber( movie_state_t *Avi, float time ); int AVI_GetVideoFrameNumber( movie_state_t *Avi, float time );
byte *AVI_GetVideoFrame( movie_state_t *Avi, int frame ); byte *AVI_GetVideoFrame( movie_state_t *Avi, int frame );
qboolean AVI_GetVideoInfo( movie_state_t *Avi, int *xres, int *yres, float *duration ); qboolean AVI_GetVideoInfo( movie_state_t *Avi, int *xres, int *yres, float *duration );
qboolean AVI_HaveAudioTrack( const movie_state_t *Avi ); qboolean AVI_GetAudioInfo( movie_state_t *Avi, wavdata_t *snd_info );
int AVI_GetAudioChunk( movie_state_t *Avi, char *audiodata, int offset, int length );
void AVI_OpenVideo( movie_state_t *Avi, const char *filename, qboolean load_audio, int quiet ); void AVI_OpenVideo( movie_state_t *Avi, const char *filename, qboolean load_audio, int quiet );
movie_state_t *AVI_LoadVideo( const char *filename, qboolean load_audio ); movie_state_t *AVI_LoadVideo( const char *filename, qboolean load_audio );
int AVI_TimeToSoundPosition( movie_state_t *Avi, int time ); int AVI_TimeToSoundPosition( movie_state_t *Avi, int time );
@@ -33,7 +34,4 @@ movie_state_t *AVI_GetState( int num );
qboolean AVI_Initailize( void ); qboolean AVI_Initailize( void );
void AVI_Shutdown( void ); void AVI_Shutdown( void );
qboolean AVI_SetParm( movie_state_t *Avi, enum movie_parms_e parm, ... );
qboolean AVI_Think( movie_state_t *Avi );
#endif // AVI_H #endif // AVI_H

View File

@@ -1,761 +0,0 @@
/*
avi_ffmpreg.c - playing AVI files (ffmpeg backend)
Copyright (C) FTEQW developers (for plugins/avplug/avdecode.c)
Copyright (C) Sam Lantinga (for tests/testffmpeg.c)
Copyright (C) 2023-2024 Alibek Omarov
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 "defaults.h"
#include "common.h"
#include "client.h"
static qboolean avi_initialized;
static poolhandle_t avi_mempool;
#if XASH_AVI == AVI_FFMPEG
#include <libavformat/avformat.h>
#include <libavcodec/avcodec.h>
#include <libavutil/imgutils.h>
#include <libswscale/swscale.h>
#include <libswresample/swresample.h>
struct movie_state_s
{
// ffmpeg contexts
AVFormatContext *fmt_ctx;
AVCodecContext *video_ctx;
AVCodecContext *audio_ctx;
struct SwsContext *sws_ctx;
struct SwrContext *swr_ctx;
AVPacket *pkt;
AVFrame *aframe;
AVFrame *vframe;
AVFrame *vframe_copy;
int64_t first_time;
int64_t last_time;
// video stream
byte *dst;
double duration;
int video_stream;
int xres;
int yres;
int dst_linesize;
enum AVPixelFormat pix_fmt;
// rendering video parameters
int x, y, w, h; // passed to R_DrawStretchRaw
int texture; // passed to R_UploadStretchRaw
// audio stream
int audio_stream;
int channels;
int rate;
enum AVSampleFormat s_fmt;
byte *cached_audio;
size_t cached_audio_buf_len; // absolute size of cached_audio array
size_t cached_audio_len; // how many data in bytes we have in cached_audio array
size_t cached_audio_pos; // how far we've read into cached_audio array
// rendering audio parameters
float attn;
int16_t entnum; // MAX_ENTITY_BITS is 13
byte volume;
byte active : 1;
byte quiet : 1;
byte paused : 1;
};
qboolean AVI_SetParm( movie_state_t *Avi, enum movie_parms_e parm, ... )
{
qboolean ret = true;
va_list va;
va_start( va, parm );
while( parm != AVI_PARM_LAST )
{
float fval;
int val;
switch( parm )
{
case AVI_RENDER_TEXNUM:
Avi->texture = va_arg( va, int );
break;
case AVI_RENDER_X:
Avi->x = va_arg( va, int );
break;
case AVI_RENDER_Y:
Avi->y = va_arg( va, int );
break;
case AVI_RENDER_W:
Avi->w = va_arg( va, int );
break;
case AVI_RENDER_H:
Avi->h = va_arg( va, int );
break;
case AVI_REWIND:
if( Avi->audio_ctx )
avcodec_flush_buffers( Avi->audio_ctx );
avcodec_flush_buffers( Avi->video_ctx );
Avi->cached_audio_len = Avi->cached_audio_pos = 0;
Avi->last_time = -1;
Avi->first_time = 0;
av_seek_frame( Avi->fmt_ctx, -1, 0, AVSEEK_FLAG_FRAME | AVSEEK_FLAG_BACKWARD );
break;
case AVI_ENTNUM:
val = va_arg( va, int );
Avi->entnum = bound( 0, val, MAX_EDICTS );
break;
case AVI_VOLUME:
val = va_arg( va, int );
Avi->volume = bound( 0, val, 255 );
break;
case AVI_ATTN:
fval = va_arg( va, double );
Avi->attn = Q_max( 0.0f, fval );
break;
case AVI_PAUSE:
Avi->paused = true;
break;
case AVI_RESUME:
Avi->paused = false;
break;
default:
ret = false;
}
parm = va_arg( va, enum movie_parms_e );
}
va_end( va );
return ret;
}
static void AVI_SpewError( qboolean quiet, const char *fmt, ... ) FORMAT_CHECK( 2 );
static void AVI_SpewError( qboolean quiet, const char *fmt, ... )
{
char buf[MAX_VA_STRING];
va_list va;
if( quiet )
return;
va_start( va, fmt );
Q_vsnprintf( buf, sizeof( buf ), fmt, va );
va_end( va );
Con_Printf( S_ERROR "%s", buf );
}
static void AVI_SpewAvError( qboolean quiet, const char *func, int numerr )
{
if( !quiet )
Con_Printf( S_ERROR "%s: %s (%d)\n", func, av_err2str( numerr ), numerr );
}
static int AVI_OpenCodecContext( AVCodecContext **dst_dec_ctx, AVFormatContext *fmt_ctx, enum AVMediaType type, qboolean quiet )
{
const AVCodec *dec;
AVCodecContext *dec_ctx;
AVStream *st;
int idx, ret;
if(( ret = av_find_best_stream( fmt_ctx, type, -1, -1, NULL, 0 )) < 0 )
{
AVI_SpewAvError( quiet, "av_find_best_stream", ret );
return ret;
}
idx = ret;
st = fmt_ctx->streams[idx];
if( !( dec = avcodec_find_decoder( st->codecpar->codec_id )))
{
AVI_SpewError( quiet, S_ERROR "Failed to find %s codec\n", av_get_media_type_string( type ));
return AVERROR( EINVAL );
}
if( !( dec_ctx = avcodec_alloc_context3( dec )))
{
AVI_SpewError( quiet, S_ERROR "Failed to allocate %s codec context", dec->name );
return AVERROR( ENOMEM );
}
if(( ret = avcodec_parameters_to_context( dec_ctx, st->codecpar )) < 0 )
{
AVI_SpewAvError( quiet, "avcodec_parameters_to_context", ret );
avcodec_free_context( &dec_ctx );
return ret;
}
dec_ctx->pkt_timebase = st->time_base;
if(( ret = avcodec_open2( dec_ctx, dec, NULL )) < 0 )
{
AVI_SpewAvError( quiet, "avcodec_open2", ret );
avcodec_free_context( &dec_ctx );
return ret;
}
*dst_dec_ctx = dec_ctx;
return idx; // always positive
}
int AVI_GetVideoFrameNumber( movie_state_t *Avi, float time )
{
return 0;
}
int AVI_TimeToSoundPosition( movie_state_t *Avi, int time )
{
return 0;
}
qboolean AVI_GetVideoInfo( movie_state_t *Avi, int *xres, int *yres, float *duration )
{
if( !Avi->active )
return false;
if( xres )
*xres = Avi->xres;
if( yres )
*yres = Avi->yres;
if( duration )
*duration = Avi->duration;
return true;
}
qboolean AVI_HaveAudioTrack( const movie_state_t *Avi )
{
return Avi ? Avi->active && Avi->audio_ctx : false;
}
// just let it compile, bruh!
byte *AVI_GetVideoFrame( movie_state_t *Avi, int target )
{
return Avi->dst;
}
static void AVI_StreamAudio( movie_state_t *Avi )
{
int buffer_samples, file_samples, file_bytes;
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;
if( !dma.initialized || disable_stream || s_listener.paused || !Avi->cached_audio )
return;
ch = S_FindRawChannel( Avi->entnum, true );
if( !ch )
return;
ch->master_vol = Avi->volume;
ch->dist_mult = (Avi->attn / SND_CLIP_DISTANCE);
if( ch->s_rawend < soundtime )
ch->s_rawend = soundtime;
while( ch->s_rawend < soundtime + ch->max_samples )
{
size_t copy;
buffer_samples = ch->max_samples - (ch->s_rawend - soundtime);
file_samples = buffer_samples * ((float)Avi->rate / SOUND_DMA_SPEED);
if( file_samples <= 1 ) return; // no more samples need
file_bytes = file_samples * av_get_bytes_per_sample( Avi->s_fmt ) * Avi->channels;
if( file_bytes > ch->max_samples )
{
file_bytes = ch->max_samples;
file_samples = file_bytes / ( av_get_bytes_per_sample( Avi->s_fmt ) * Avi->channels );
}
copy = Q_min( file_bytes, Q_max( Avi->cached_audio_len - Avi->cached_audio_pos, 0 ));
if( !copy )
break;
if( file_bytes > copy )
{
file_bytes = copy;
file_samples = file_bytes / ( av_get_bytes_per_sample( Avi->s_fmt ) * Avi->channels );
}
ch->s_rawend = S_RawSamplesStereo( ch->rawsamples, ch->s_rawend, ch->max_samples, file_samples, Avi->rate, av_get_bytes_per_sample( Avi->s_fmt ), Avi->channels, Avi->cached_audio + Avi->cached_audio_pos );
Avi->cached_audio_pos += copy;
}
}
static void AVI_HandleAudio( movie_state_t *Avi, const AVFrame *frame )
{
int samples = frame->nb_samples;
size_t len = samples * av_get_bytes_per_sample( Avi->s_fmt ) * Avi->channels;
int outsamples;
uint8_t *ptr;
// allocate data
if( !Avi->cached_audio )
{
Avi->cached_audio_buf_len = len;
Avi->cached_audio_pos = 0;
Avi->cached_audio_len = 0;
Avi->cached_audio = Mem_Malloc( avi_mempool, len );
}
else
{
if( Avi->cached_audio_pos )
{
// Con_Printf( "%s: erasing old data of size %d\n", __func__, Avi->cached_audio_pos );
Avi->cached_audio_len -= Avi->cached_audio_pos;
memmove( Avi->cached_audio, Avi->cached_audio + Avi->cached_audio_pos, Avi->cached_audio_len );
Avi->cached_audio_pos = 0;
}
if( len + Avi->cached_audio_len > Avi->cached_audio_buf_len )
{
// Con_Printf( "%s: resizing old buffer of size %d to size %d\n", __func__, Avi->cached_audio_buf_len, len + Avi->cached_audio_buf_len );
Avi->cached_audio_buf_len = len + Avi->cached_audio_len;
Avi->cached_audio = Mem_Realloc( avi_mempool, Avi->cached_audio, Avi->cached_audio_buf_len );
}
}
ptr = Avi->cached_audio + Avi->cached_audio_len;
outsamples = swr_convert( Avi->swr_ctx, &ptr, samples, (void *)frame->data, samples );
Avi->cached_audio_len += outsamples * av_get_bytes_per_sample( Avi->s_fmt ) * Avi->channels;
// Con_Printf( "%s: got audio chunk of size %d samples\n", __func__, outsamples );
}
qboolean AVI_Think( movie_state_t *Avi )
{
qboolean decoded = false;
qboolean flushing = false;
qboolean redraw = false;
const double timebase = (double)Avi->video_ctx->pkt_timebase.den / Avi->video_ctx->pkt_timebase.num;
int64_t curtime = round( Platform_DoubleTime() * timebase );
if( !Avi->first_time ) // always remember at which timestamp we started playing
Avi->first_time = curtime;
if( Avi->paused )
{
// FIXME: there might be a better way to do this
Avi->last_time = curtime;
return true;
}
// Con_NPrintf( 1, "cached_audio_buf_len = %zu", Avi->cached_audio_buf_len );
while( 1 ) // try to get multiple decoded frames to keep up when we're running at low fps
{
int res;
AVI_StreamAudio( Avi ); // always flush audio buffers
// recalc time so we always play last possible frame
curtime = round( Platform_DoubleTime() * timebase );
if( Avi->last_time > curtime )
break;
if(( res = av_read_frame( Avi->fmt_ctx, Avi->pkt )) >= 0 )
{
if( Avi->pkt->stream_index == Avi->audio_stream )
{
res = avcodec_send_packet( Avi->audio_ctx, Avi->pkt );
if( res < 0 )
AVI_SpewAvError( Avi->quiet, "avcodec_send_packet (audio)", res );
}
else if( Avi->pkt->stream_index == Avi->video_stream )
{
res = avcodec_send_packet( Avi->video_ctx, Avi->pkt );
if( res < 0 )
AVI_SpewAvError( Avi->quiet, "avcodec_send_packet (video)", res );
}
av_packet_unref( Avi->pkt );
}
else
{
if( res != AVERROR_EOF )
AVI_SpewAvError( Avi->quiet, "av_read_frame", res );
if( Avi->audio_ctx )
avcodec_flush_buffers( Avi->audio_ctx );
avcodec_flush_buffers( Avi->video_ctx );
flushing = true;
break;
}
if( Avi->audio_ctx )
{
while( avcodec_receive_frame( Avi->audio_ctx, Avi->aframe ) == 0 )
{
AVI_HandleAudio( Avi, Avi->aframe );
decoded = true;
}
}
while( avcodec_receive_frame( Avi->video_ctx, Avi->vframe ) == 0 )
{
Avi->last_time = Avi->first_time + Avi->vframe->best_effort_timestamp;
decoded = true;
if( FBitSet( Avi->vframe->flags, AV_FRAME_FLAG_CORRUPT|AV_FRAME_FLAG_DISCARD ))
continue;
if( Avi->vframe->decode_error_flags != 0 )
continue;
av_frame_unref( Avi->vframe_copy );
if( av_frame_ref( Avi->vframe_copy, Avi->vframe ) == 0 )
redraw = true;
}
}
if( redraw )
{
sws_scale( Avi->sws_ctx, (void*)Avi->vframe_copy->data, Avi->vframe_copy->linesize, 0, Avi->video_ctx->height,
&Avi->dst, &Avi->dst_linesize );
av_frame_unref( Avi->vframe_copy );
}
if( Avi->texture == 0 )
{
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 );
}
else if( redraw && Avi->texture > 0 )
ref.dllFuncs.AVI_UploadRawFrame( Avi->texture, Avi->xres, Avi->yres, Avi->w, Avi->h, Avi->dst );
if( flushing && !decoded )
return false; // probably hit an EOF
return true;
}
void AVI_OpenVideo( movie_state_t *Avi, const char *filename, qboolean load_audio, int quiet )
{
byte *dst[4];
int dst_linesize[4];
int ret;
if( Avi->active )
AVI_CloseVideo( Avi );
if( !filename || !avi_initialized )
return;
Avi->active = false;
Avi->quiet = quiet;
Avi->video_ctx = Avi->audio_ctx = NULL;
Avi->fmt_ctx = NULL;
if(( ret = avformat_open_input( &Avi->fmt_ctx, filename, NULL, NULL )) < 0 )
{
AVI_SpewAvError( quiet, "avformat_open_input", ret );
return;
}
if(( ret = avformat_find_stream_info( Avi->fmt_ctx, NULL )) < 0 )
{
AVI_SpewAvError( quiet, "avformat_find_stream_info", ret );
return;
}
if( !( Avi->pkt = av_packet_alloc( )))
{
AVI_SpewAvError( quiet, "av_packet_alloc", 0 );
return;
}
if( !( Avi->vframe = av_frame_alloc( )))
{
AVI_SpewAvError( quiet, "av_frame_alloc (video)", 0 );
return;
}
if( !( Avi->vframe_copy = av_frame_alloc( )))
{
AVI_SpewAvError( quiet, "av_frame_alloc (video)", 0 );
return;
}
Avi->video_stream = AVI_OpenCodecContext( &Avi->video_ctx, Avi->fmt_ctx, AVMEDIA_TYPE_VIDEO, quiet );
if( Avi->video_stream < 0 )
return;
Avi->xres = Avi->video_ctx->width;
Avi->yres = Avi->video_ctx->height;
Avi->pix_fmt = Avi->video_ctx->pix_fmt;
Avi->duration = Avi->fmt_ctx->duration / (double)AV_TIME_BASE;
Avi->entnum = S_RAW_SOUND_SOUNDTRACK;
Avi->attn = ATTN_NONE;
Avi->volume = 255;
if( !( Avi->sws_ctx = sws_getContext( Avi->xres, Avi->yres, Avi->pix_fmt,
Avi->xres, Avi->yres, AV_PIX_FMT_BGR0, SWS_POINT, NULL, NULL, NULL )))
{
AVI_SpewAvError( quiet, "sws_getContext", 0 );
return;
}
if(( ret = av_image_alloc( dst, dst_linesize, Avi->xres, Avi->yres, AV_PIX_FMT_BGR0, 1 )) < 0 )
{
AVI_SpewAvError( quiet, "av_image_alloc", ret );
return;
}
Avi->dst = dst[0];
Avi->dst_linesize = dst_linesize[0];
if( load_audio )
{
if( !( Avi->aframe = av_frame_alloc( )))
{
AVI_SpewAvError( quiet, "av_frame_alloc (audio)", 0 );
return;
}
Avi->audio_stream = AVI_OpenCodecContext( &Avi->audio_ctx, Avi->fmt_ctx, AVMEDIA_TYPE_AUDIO, quiet );
// audio stream was requested but it wasn't found
if( Avi->audio_stream < 0 )
return;
Avi->channels = Q_min( Avi->audio_ctx->ch_layout.nb_channels, 2 );
if( Avi->audio_ctx->sample_fmt == AV_SAMPLE_FMT_U8 || Avi->audio_ctx->sample_fmt == AV_SAMPLE_FMT_U8P )
Avi->s_fmt = AV_SAMPLE_FMT_U8;
else Avi->s_fmt = AV_SAMPLE_FMT_S16;
Avi->rate = Avi->audio_ctx->sample_rate;
if(( ret = swr_alloc_set_opts2( &Avi->swr_ctx, &Avi->audio_ctx->ch_layout, Avi->s_fmt, Avi->rate,
&Avi->audio_ctx->ch_layout, Avi->audio_ctx->sample_fmt, Avi->audio_ctx->sample_rate, 0, 0 )) < 0 )
{
AVI_SpewAvError( quiet, "swr_alloc_set_opts2", ret );
return;
}
if(( ret = swr_init( Avi->swr_ctx )) < 0 )
{
AVI_SpewAvError( quiet, "swr_init", ret );
return;
}
}
Avi->active = true;
}
void AVI_CloseVideo( movie_state_t *Avi )
{
if( Avi->active )
{
if( Avi->cached_audio )
Mem_Free( Avi->cached_audio );
swr_free( &Avi->swr_ctx );
avcodec_free_context( &Avi->audio_ctx );
av_frame_free( &Avi->aframe );
av_free( Avi->dst );
sws_freeContext( Avi->sws_ctx );
avcodec_free_context( &Avi->video_ctx );
av_frame_free( &Avi->vframe );
av_frame_free( &Avi->vframe_copy );
av_packet_free( &Avi->pkt );
avformat_close_input( &Avi->fmt_ctx );
}
memset( Avi, 0, sizeof( *Avi ));
}
static void AVI_PrintFFmpegVersion( void )
{
uint ver;
// print version we're compiled with and which version we're running with
ver = avutil_version();
Con_Reportf( "AVI: %s (runtime %d.%d.%d)\n", LIBAVUTIL_IDENT, AV_VERSION_MAJOR( ver ), AV_VERSION_MINOR( ver ), AV_VERSION_MICRO( ver ));
ver = avformat_version();
Con_Reportf( "AVI: %s (runtime %d.%d.%d)\n", LIBAVFORMAT_IDENT, AV_VERSION_MAJOR( ver ), AV_VERSION_MINOR( ver ), AV_VERSION_MICRO( ver ));
ver = avformat_version();
Con_Reportf( "AVI: %s (runtime %d.%d.%d)\n", LIBAVCODEC_IDENT, AV_VERSION_MAJOR( ver ), AV_VERSION_MINOR( ver ), AV_VERSION_MICRO( ver ));
ver = swscale_version();
Con_Reportf( "AVI: %s (runtime %d.%d.%d)\n", LIBSWSCALE_IDENT, AV_VERSION_MAJOR( ver ), AV_VERSION_MINOR( ver ), AV_VERSION_MICRO( ver ));
ver = swresample_version();
Con_Reportf( "AVI: %s (runtime %d.%d.%d)\n", LIBSWRESAMPLE_IDENT, AV_VERSION_MAJOR( ver ), AV_VERSION_MINOR( ver ), AV_VERSION_MICRO( ver ));
}
#else
struct movie_state_s
{
qboolean active;
};
int AVI_GetVideoFrameNumber( movie_state_t *Avi, float time )
{
return 0;
}
byte *AVI_GetVideoFrame( movie_state_t *Avi, int frame )
{
return NULL;
}
qboolean AVI_GetVideoInfo( movie_state_t *Avi, int *xres, int *yres, float *duration )
{
return false;
}
qboolean AVI_HaveAudioTrack( const movie_state_t *Avi )
{
return false;
}
void AVI_OpenVideo( movie_state_t *Avi, const char *filename, qboolean load_audio, int quiet )
{
;
}
int AVI_TimeToSoundPosition( movie_state_t *Avi, int time )
{
return 0;
}
void AVI_CloseVideo( movie_state_t *Avi )
{
;
}
qboolean AVI_Think( movie_state_t *Avi )
{
return false;
}
qboolean AVI_SetParm( movie_state_t *Avi, enum movie_parms_e parm, ... )
{
return false;
}
static void AVI_PrintFFmpegVersion( void )
{
}
#endif // XASH_AVI == AVI_NULL
static movie_state_t avi[2];
movie_state_t *AVI_GetState( int num )
{
return &avi[num];
}
qboolean AVI_IsActive( movie_state_t *Avi )
{
return Avi ? Avi->active : false;
}
qboolean AVI_Initailize( void )
{
if( XASH_AVI == AVI_NULL )
{
Con_Printf( "AVI: Not supported\n" );
return false;
}
if( Sys_CheckParm( "-noavi" ))
{
Con_Printf( "AVI: Disabled\n" );
return false;
}
AVI_PrintFFmpegVersion();
avi_initialized = true;
avi_mempool = Mem_AllocPool( "AVI Zone" );
return false;
}
void AVI_Shutdown( void )
{
Mem_FreePool( &avi_mempool );
avi_initialized = XASH_AVI != AVI_NULL;
}
movie_state_t *AVI_LoadVideo( const char *filename, qboolean load_audio )
{
movie_state_t *Avi;
string path;
const char *fullpath;
// fast reject
if( !avi_initialized )
return NULL;
// open cinematic
Q_snprintf( path, sizeof( path ), "media/%s", filename );
COM_DefaultExtension( path, ".avi", sizeof( path ));
fullpath = FS_GetDiskPath( path, false );
if( FS_FileExists( path, false ) && !fullpath )
{
Con_Printf( "Couldn't load %s from packfile. Please extract it\n", path );
return NULL;
}
Avi = Mem_Calloc( avi_mempool, sizeof( movie_state_t ));
AVI_OpenVideo( Avi, fullpath, load_audio, false );
if( !AVI_IsActive( Avi ))
{
AVI_FreeVideo( Avi ); // something bad happens
return NULL;
}
// all done
return Avi;
}
void AVI_FreeVideo( movie_state_t *Avi )
{
if( !Avi )
return;
AVI_CloseVideo( Avi );
if( Mem_IsAllocatedExt( avi_mempool, Avi ))
Mem_Free( Avi );
}

View File

@@ -0,0 +1,90 @@
/*
avi_stub.c - playing AVI files (stub)
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 "build.h"
#if !XASH_WIN32
#include "common.h"
int AVI_GetVideoFrameNumber( movie_state_t *Avi, float time )
{
return 0;
}
byte *AVI_GetVideoFrame( movie_state_t *Avi, int frame )
{
return NULL;
}
qboolean AVI_GetVideoInfo( movie_state_t *Avi, int *xres, int *yres, float *duration )
{
return false;
}
qboolean AVI_GetAudioInfo( movie_state_t *Avi, wavdata_t *snd_info )
{
return false;
}
int AVI_GetAudioChunk( movie_state_t *Avi, char *audiodata, int offset, int length )
{
return 0;
}
void AVI_OpenVideo( movie_state_t *Avi, const char *filename, qboolean load_audio, int quiet )
{
;
}
movie_state_t *AVI_LoadVideo( const char *filename, qboolean load_audio )
{
return NULL;
}
int AVI_TimeToSoundPosition( movie_state_t *Avi, int time )
{
return 0;
}
void AVI_CloseVideo( movie_state_t *Avi )
{
;
}
qboolean AVI_IsActive( movie_state_t *Avi )
{
return false;
}
void AVI_FreeVideo( movie_state_t *Avi )
{
;
}
movie_state_t *AVI_GetState( int num )
{
return NULL;
}
qboolean AVI_Initailize( void )
{
return false;
}
void AVI_Shutdown( void )
{
;
}
#endif // WIN32

732
engine/client/avi/avi_win.c Normal file
View File

@@ -0,0 +1,732 @@
/*
avi_win.c - playing AVI files (based on original AVIKit code, Win32 version)
Copyright (c) 2003-2004, Ruari O'Sullivan
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 "build.h"
#if XASH_WIN32
#include "common.h"
#include "client.h"
#include <vfw.h> // video for windows
// msvfw32.dll exports
static HDRAWDIB (_stdcall *pDrawDibOpen)( void );
static BOOL (_stdcall *pDrawDibClose)( HDRAWDIB hdd );
static BOOL (_stdcall *pDrawDibDraw)( HDRAWDIB, HDC, int, int, int, int, LPBITMAPINFOHEADER, void*, int, int, int, int, uint );
static dllfunc_t msvfw_funcs[] =
{
{ "DrawDibOpen", (void **) &pDrawDibOpen },
{ "DrawDibDraw", (void **) &pDrawDibDraw },
{ "DrawDibClose", (void **) &pDrawDibClose },
};
dll_info_t msvfw_dll = { "msvfw32.dll", msvfw_funcs, ARRAYSIZE( msvfw_funcs ), false };
// msacm32.dll exports
static MMRESULT (_stdcall *pacmStreamOpen)( LPHACMSTREAM, HACMDRIVER, LPWAVEFORMATEX, LPWAVEFORMATEX, LPWAVEFILTER, DWORD, DWORD, DWORD );
static MMRESULT (_stdcall *pacmStreamPrepareHeader)( HACMSTREAM, LPACMSTREAMHEADER, DWORD );
static MMRESULT (_stdcall *pacmStreamUnprepareHeader)( HACMSTREAM, LPACMSTREAMHEADER, DWORD );
static MMRESULT (_stdcall *pacmStreamConvert)( HACMSTREAM, LPACMSTREAMHEADER, DWORD );
static MMRESULT (_stdcall *pacmStreamSize)( HACMSTREAM, DWORD, LPDWORD, DWORD );
static MMRESULT (_stdcall *pacmStreamClose)( HACMSTREAM, DWORD );
static dllfunc_t msacm_funcs[] =
{
{ "acmStreamOpen", (void **) &pacmStreamOpen },
{ "acmStreamPrepareHeader", (void **) &pacmStreamPrepareHeader },
{ "acmStreamUnprepareHeader", (void **) &pacmStreamUnprepareHeader },
{ "acmStreamConvert", (void **) &pacmStreamConvert },
{ "acmStreamSize", (void **) &pacmStreamSize },
{ "acmStreamClose", (void **) &pacmStreamClose },
};
dll_info_t msacm_dll = { "msacm32.dll", msacm_funcs, ARRAYSIZE( msacm_funcs ), false };
// avifil32.dll exports
static int (_stdcall *pAVIStreamInfo)( PAVISTREAM pavi, AVISTREAMINFO *psi, LONG lSize );
static int (_stdcall *pAVIStreamRead)( PAVISTREAM pavi, LONG lStart, LONG lSamples, void *lpBuffer, LONG cbBuffer, LONG *plBytes, LONG *plSamples );
static PGETFRAME (_stdcall *pAVIStreamGetFrameOpen)( PAVISTREAM pavi, LPBITMAPINFOHEADER lpbiWanted );
static int (_stdcall *pAVIStreamTimeToSample)( PAVISTREAM pavi, LONG lTime );
static void* (_stdcall *pAVIStreamGetFrame)( PGETFRAME pg, LONG lPos );
static int (_stdcall *pAVIStreamGetFrameClose)( PGETFRAME pg );
static dword (_stdcall *pAVIStreamRelease)( PAVISTREAM pavi );
static int (_stdcall *pAVIFileOpenW)( PAVIFILE *ppfile, LPCWSTR szFile, UINT uMode, LPCLSID lpHandler );
static int (_stdcall *pAVIFileGetStream)( PAVIFILE pfile, PAVISTREAM *ppavi, DWORD fccType, LONG lParam );
static int (_stdcall *pAVIStreamReadFormat)( PAVISTREAM pavi, LONG lPos,LPVOID lpFormat, LONG *lpcbFormat );
static int (_stdcall *pAVIStreamStart)( PAVISTREAM pavi );
static dword (_stdcall *pAVIFileRelease)( PAVIFILE pfile );
static void (_stdcall *pAVIFileInit)( void );
static void (_stdcall *pAVIFileExit)( void );
static dllfunc_t avifile_funcs[] =
{
{ "AVIFileExit", (void **) &pAVIFileExit },
{ "AVIFileGetStream", (void **) &pAVIFileGetStream },
{ "AVIFileInit", (void **) &pAVIFileInit },
{ "AVIFileOpenW", (void **) &pAVIFileOpenW },
{ "AVIFileRelease", (void **) &pAVIFileRelease },
{ "AVIStreamGetFrame", (void **) &pAVIStreamGetFrame },
{ "AVIStreamGetFrameClose", (void **) &pAVIStreamGetFrameClose },
{ "AVIStreamGetFrameOpen", (void **) &pAVIStreamGetFrameOpen },
{ "AVIStreamInfoA", (void **) &pAVIStreamInfo },
{ "AVIStreamRead", (void **) &pAVIStreamRead },
{ "AVIStreamReadFormat", (void **) &pAVIStreamReadFormat },
{ "AVIStreamRelease", (void **) &pAVIStreamRelease },
{ "AVIStreamStart", (void **) &pAVIStreamStart },
{ "AVIStreamTimeToSample", (void **) &pAVIStreamTimeToSample },
};
dll_info_t avifile_dll = { "avifil32.dll", avifile_funcs, ARRAYSIZE( avifile_funcs ), false };
typedef struct movie_state_s
{
qboolean active;
qboolean quiet; // ignore error messages
PAVIFILE pfile; // avi file pointer
PAVISTREAM video_stream; // video stream pointer
PGETFRAME video_getframe; // pointer to getframe object for video stream
int video_frames; // total frames
int video_xres; // video stream resolution
int video_yres;
float video_fps; // video stream fps
PAVISTREAM audio_stream; // audio stream pointer
WAVEFORMAT *audio_header; // audio stream header
int audio_header_size; // WAVEFORMAT is returned for PCM data; WAVEFORMATEX for others
int audio_codec; // WAVE_FORMAT_PCM is oldstyle: anything else needs conversion
int audio_length; // in converted samples
int audio_bytes_per_sample; // guess.
// compressed audio specific data
dword cpa_blockalign; // block size to read
HACMSTREAM cpa_conversion_stream;
ACMSTREAMHEADER cpa_conversion_header;
byte *cpa_srcbuffer; // maintained buffer for raw data
byte *cpa_dstbuffer;
dword cpa_blocknum; // current block
dword cpa_blockpos; // read position in current block
dword cpa_blockoffset; // corresponding offset in bytes in the output stream
// for additional unpack Ms-RLE codecs etc
HDC hDC; // compatible DC
HDRAWDIB hDD; // DrawDib handler
HBITMAP hBitmap; // for DIB conversions
byte *pframe_data; // converted framedata
} movie_state_t;
static qboolean avi_initialized = false;
static movie_state_t avi[2];
// Converts a compressed audio stream into uncompressed PCM.
qboolean AVI_ACMConvertAudio( movie_state_t *Avi )
{
WAVEFORMATEX dest_header, *sh, *dh;
AVISTREAMINFO stream_info;
dword dest_length;
short bits;
// WMA codecs, both versions - they simply don't work.
if( Avi->audio_header->wFormatTag == 0x160 || Avi->audio_header->wFormatTag == 0x161 )
{
if( !Avi->quiet )
Con_Reportf( S_ERROR "ACM does not support this audio codec.\n" );
return false;
}
// get audio stream info to work with
pAVIStreamInfo( Avi->audio_stream, &stream_info, sizeof( stream_info ));
if( Avi->audio_header_size < sizeof( WAVEFORMATEX ))
{
if( !Avi->quiet )
Con_Reportf( S_ERROR "ACM failed to open conversion stream.\n" );
return false;
}
sh = (WAVEFORMATEX *)Avi->audio_header;
bits = 16; // predict state
// how much of this is actually required?
dest_header.wFormatTag = WAVE_FORMAT_PCM; // yay
dest_header.wBitsPerSample = bits; // 16bit
dest_header.nChannels = sh->nChannels;
dest_header.nSamplesPerSec = sh->nSamplesPerSec; // take straight from the source stream
dest_header.nAvgBytesPerSec = (bits >> 3) * sh->nChannels * sh->nSamplesPerSec;
dest_header.nBlockAlign = (bits >> 3) * sh->nChannels;
dest_header.cbSize = 0; // no more data.
dh = &dest_header;
// open the stream
if( pacmStreamOpen( &Avi->cpa_conversion_stream, NULL, sh, dh, NULL, 0, 0, 0 ) != MMSYSERR_NOERROR )
{
// try with 8 bit destination instead
bits = 8;
dest_header.wBitsPerSample = bits; // 8bit
dest_header.nAvgBytesPerSec = ( bits >> 3 ) * sh->nChannels * sh->nSamplesPerSec;
dest_header.nBlockAlign = ( bits >> 3 ) * sh->nChannels; // 1 sample at a time
if( pacmStreamOpen( &Avi->cpa_conversion_stream, NULL, sh, dh, NULL, 0, 0, 0 ) != MMSYSERR_NOERROR )
{
if( !Avi->quiet )
Con_Reportf( S_ERROR "ACM failed to open conversion stream.\n" );
return false;
}
}
Avi->cpa_blockalign = sh->nBlockAlign;
dest_length = 0;
// mp3 specific fix
if( sh->wFormatTag == 0x55 )
{
LPMPEGLAYER3WAVEFORMAT k;
k = (LPMPEGLAYER3WAVEFORMAT)sh;
Avi->cpa_blockalign = k->nBlockSize;
}
// get the size of the output buffer for streaming the compressed audio
if( pacmStreamSize( Avi->cpa_conversion_stream, Avi->cpa_blockalign, &dest_length, ACM_STREAMSIZEF_SOURCE ) != MMSYSERR_NOERROR )
{
if( !Avi->quiet )
Con_Reportf( S_ERROR "Couldn't get ACM conversion stream size.\n" );
pacmStreamClose( Avi->cpa_conversion_stream, 0 );
return false;
}
Avi->cpa_srcbuffer = (byte *)Mem_Malloc( cls.mempool, Avi->cpa_blockalign );
Avi->cpa_dstbuffer = (byte *)Mem_Malloc( cls.mempool, dest_length ); // maintained buffer for raw data
// prep the headers!
Avi->cpa_conversion_header.cbStruct = sizeof( ACMSTREAMHEADER );
Avi->cpa_conversion_header.fdwStatus = 0;
Avi->cpa_conversion_header.dwUser = 0; // no user data
Avi->cpa_conversion_header.pbSrc = Avi->cpa_srcbuffer; // source buffer
Avi->cpa_conversion_header.cbSrcLength = Avi->cpa_blockalign; // source buffer size
Avi->cpa_conversion_header.cbSrcLengthUsed = 0;
Avi->cpa_conversion_header.dwSrcUser = 0; // no user data
Avi->cpa_conversion_header.pbDst = Avi->cpa_dstbuffer; // dest buffer
Avi->cpa_conversion_header.cbDstLength = dest_length; // dest buffer size
Avi->cpa_conversion_header.cbDstLengthUsed = 0;
Avi->cpa_conversion_header.dwDstUser = 0; // no user data
if( pacmStreamPrepareHeader( Avi->cpa_conversion_stream, &Avi->cpa_conversion_header, 0 ) != MMSYSERR_NOERROR )
{
if( !Avi->quiet )
Con_Reportf( S_ERROR "couldn't prepare stream headers.\n" );
pacmStreamClose( Avi->cpa_conversion_stream, 0 );
return false;
}
Avi->cpa_blocknum = 0; // start at 0.
Avi->cpa_blockpos = 0;
Avi->cpa_blockoffset = 0;
pAVIStreamRead( Avi->audio_stream, Avi->cpa_blocknum * Avi->cpa_blockalign, Avi->cpa_blockalign, Avi->cpa_srcbuffer, Avi->cpa_blockalign, NULL, NULL );
pacmStreamConvert( Avi->cpa_conversion_stream, &Avi->cpa_conversion_header, ACM_STREAMCONVERTF_BLOCKALIGN|ACM_STREAMCONVERTF_START );
// convert first chunk twice. it often fails the first time. BLACK MAGIC.
pAVIStreamRead( Avi->audio_stream, Avi->cpa_blocknum * Avi->cpa_blockalign, Avi->cpa_blockalign, Avi->cpa_srcbuffer, Avi->cpa_blockalign, NULL, NULL );
pacmStreamConvert( Avi->cpa_conversion_stream, &Avi->cpa_conversion_header, ACM_STREAMCONVERTF_BLOCKALIGN );
Avi->audio_bytes_per_sample = (bits >> 3 ) * Avi->audio_header->nChannels;
return true;
}
qboolean AVI_GetVideoInfo( movie_state_t *Avi, int *xres, int *yres, float *duration )
{
if( !Avi->active )
return false;
if( xres != NULL )
*xres = Avi->video_xres;
if( yres != NULL )
*yres = Avi->video_yres;
if( duration != NULL )
*duration = (float)Avi->video_frames / Avi->video_fps;
return true;
}
// returns a unique frame identifier
int AVI_GetVideoFrameNumber( movie_state_t *Avi, float time )
{
if( !Avi->active )
return 0;
return (time * Avi->video_fps);
}
int AVI_TimeToSoundPosition( movie_state_t *Avi, int time )
{
if( !Avi->active || !Avi->audio_stream )
return 0;
// UNDONE: what about compressed audio?
return pAVIStreamTimeToSample( Avi->audio_stream, time ) * Avi->audio_bytes_per_sample;
}
// gets the raw frame data
byte *AVI_GetVideoFrame( movie_state_t *Avi, int frame )
{
LPBITMAPINFOHEADER frame_info;
byte *frame_raw;
if( !Avi->active ) return NULL;
if( frame >= Avi->video_frames )
frame = Avi->video_frames - 1;
frame_info = (LPBITMAPINFOHEADER)pAVIStreamGetFrame( Avi->video_getframe, frame );
frame_raw = (byte *)frame_info + frame_info->biSize + frame_info->biClrUsed * sizeof( RGBQUAD );
pDrawDibDraw( Avi->hDD, Avi->hDC, 0, 0, Avi->video_xres, Avi->video_yres, frame_info, frame_raw, 0, 0, Avi->video_xres, Avi->video_yres, 0 );
return Avi->pframe_data;
}
qboolean AVI_GetAudioInfo( movie_state_t *Avi, wavdata_t *snd_info )
{
if( !Avi->active || Avi->audio_stream == NULL || snd_info == NULL )
{
return false;
}
snd_info->rate = Avi->audio_header->nSamplesPerSec;
snd_info->channels = Avi->audio_header->nChannels;
if( Avi->audio_codec == WAVE_FORMAT_PCM ) // uncompressed audio!
snd_info->width = ( Avi->audio_bytes_per_sample > Avi->audio_header->nChannels ) ? 2 : 1;
else snd_info->width = 2; // assume compressed audio is always 16 bit
snd_info->size = snd_info->rate * snd_info->width * snd_info->channels;
snd_info->loopStart = 0; // using loopStart as streampos
return true;
}
// sync the current audio read to a specific offset
qboolean AVI_SeekPosition( movie_state_t *Avi, dword offset )
{
int breaker;
if( offset < Avi->cpa_blockoffset ) // well, shit. we can't seek backwards... restart
{
if( Avi->cpa_blockoffset - offset < 500000 )
return false; // don't bother if it's gonna catch up soon
Avi->cpa_blocknum = 0; // start at 0, eh.
Avi->cpa_blockpos = 0;
Avi->cpa_blockoffset = 0;
pAVIStreamRead( Avi->audio_stream, Avi->cpa_blocknum * Avi->cpa_blockalign, Avi->cpa_blockalign, Avi->cpa_srcbuffer, Avi->cpa_blockalign, NULL, NULL );
pacmStreamConvert( Avi->cpa_conversion_stream, &Avi->cpa_conversion_header, ACM_STREAMCONVERTF_BLOCKALIGN|ACM_STREAMCONVERTF_START );
// convert first chunk twice. it often fails the first time. BLACK MAGIC.
pAVIStreamRead( Avi->audio_stream, Avi->cpa_blocknum * Avi->cpa_blockalign, Avi->cpa_blockalign, Avi->cpa_srcbuffer, Avi->cpa_blockalign, NULL, NULL );
pacmStreamConvert( Avi->cpa_conversion_stream, &Avi->cpa_conversion_header, ACM_STREAMCONVERTF_BLOCKALIGN );
}
// now then: seek forwards to the required block
breaker = 30; // maximum zero blocks: anti-freeze protection
while( Avi->cpa_blockoffset + Avi->cpa_conversion_header.cbDstLengthUsed < offset )
{
Avi->cpa_blocknum++;
Avi->cpa_blockoffset += Avi->cpa_conversion_header.cbDstLengthUsed;
pAVIStreamRead( Avi->audio_stream, Avi->cpa_blocknum * Avi->cpa_blockalign, Avi->cpa_blockalign, Avi->cpa_srcbuffer, Avi->cpa_blockalign, NULL, NULL );
pacmStreamConvert( Avi->cpa_conversion_stream, &Avi->cpa_conversion_header, ACM_STREAMCONVERTF_BLOCKALIGN );
if( Avi->cpa_conversion_header.cbDstLengthUsed == 0 )
breaker--;
else breaker = 30;
if( breaker <= 0 )
return false;
Avi->cpa_blockpos = 0;
}
// seek to the right position inside the block
Avi->cpa_blockpos = offset - Avi->cpa_blockoffset;
return true;
}
// get a chunk of audio from the stream (in bytes)
int AVI_GetAudioChunk( movie_state_t *Avi, char *audiodata, int offset, int length )
{
int result = 0;
int i;
// zero data past the end of the file
if( offset + length > Avi->audio_length )
{
if( offset <= Avi->audio_length )
{
int remaining_length = Avi->audio_length - offset;
AVI_GetAudioChunk( Avi, audiodata, offset, remaining_length );
for( i = remaining_length; i < length; i++ )
audiodata[i] = 0;
}
else
{
// we out of soundtrack, just zeroing buffer
for( i = 0; i < length; i++ )
audiodata[i] = 0;
// return length;
}
}
// uncompressed audio!
if( Avi->audio_codec == WAVE_FORMAT_PCM )
{
// very simple - read straight out
pAVIStreamRead( Avi->audio_stream, offset / Avi->audio_bytes_per_sample, length / Avi->audio_bytes_per_sample, audiodata, length, &result, NULL );
return result;
}
else
{
// compressed audio!
result = 0;
// seek to correct chunk and all that stuff
if( !AVI_SeekPosition( Avi, offset ))
return 0; // don't continue if we're waiting for the play pointer to catch up
while( length > 0 )
{
int blockread = Avi->cpa_conversion_header.cbDstLengthUsed - Avi->cpa_blockpos;
if( blockread <= 0 ) // read next
{
Avi->cpa_blocknum++;
Avi->cpa_blockoffset += Avi->cpa_conversion_header.cbDstLengthUsed;
pAVIStreamRead( Avi->audio_stream, Avi->cpa_blocknum * Avi->cpa_blockalign, Avi->cpa_blockalign, Avi->cpa_srcbuffer, Avi->cpa_blockalign, NULL, NULL );
pacmStreamConvert( Avi->cpa_conversion_stream, &Avi->cpa_conversion_header, ACM_STREAMCONVERTF_BLOCKALIGN );
Avi->cpa_blockpos = 0;
continue;
}
if( blockread > length )
blockread = length;
// copy the data
memcpy( audiodata + result, (void *)( Avi->cpa_dstbuffer + Avi->cpa_blockpos ), blockread );
Avi->cpa_blockpos += blockread;
result += blockread;
length -= blockread;
}
return result;
}
}
void AVI_CloseVideo( movie_state_t *Avi )
{
if( Avi->active )
{
pAVIStreamGetFrameClose( Avi->video_getframe );
if( Avi->audio_stream != NULL )
{
pAVIStreamRelease( Avi->audio_stream );
Mem_Free( Avi->audio_header );
if( Avi->audio_codec != WAVE_FORMAT_PCM )
{
pacmStreamUnprepareHeader( Avi->cpa_conversion_stream, &Avi->cpa_conversion_header, 0 );
pacmStreamClose( Avi->cpa_conversion_stream, 0 );
Mem_Free( Avi->cpa_srcbuffer );
Mem_Free( Avi->cpa_dstbuffer );
}
}
pAVIStreamRelease( Avi->video_stream );
DeleteObject( Avi->hBitmap );
pDrawDibClose( Avi->hDD );
DeleteDC( Avi->hDC );
}
memset( Avi, 0, sizeof( movie_state_t ));
}
void AVI_OpenVideo( movie_state_t *Avi, const char *filename, qboolean load_audio, int quiet )
{
BITMAPINFOHEADER bmih;
AVISTREAMINFO stream_info;
int opened_streams = 0;
LONG hr;
wchar_t pathBuffer[MAX_PATH];
// default state: non-working.
Avi->active = false;
Avi->quiet = quiet;
// can't load Video For Windows :-(
if( !avi_initialized ) return;
// convert to wide char
if( MultiByteToWideChar( CP_UTF8, 0, filename, -1, pathBuffer, ARRAYSIZE( pathBuffer )) <= 0 )
{
Con_DPrintf( S_ERROR "filename buffer limit exceeded\n" );
return;
}
// load the AVI
hr = pAVIFileOpenW( &Avi->pfile, pathBuffer, OF_SHARE_DENY_WRITE, 0L );
if( hr != 0 ) // error opening AVI:
{
switch( hr )
{
case AVIERR_BADFORMAT:
if( !Avi->quiet )
Con_DPrintf( S_ERROR "corrupt file or unknown format.\n" );
break;
case AVIERR_MEMORY:
if( !Avi->quiet )
Con_DPrintf( S_ERROR "insufficient memory to open file.\n" );
break;
case AVIERR_FILEREAD:
if( !Avi->quiet )
Con_DPrintf( S_ERROR "disk error reading file.\n" );
break;
case AVIERR_FILEOPEN:
if( !Avi->quiet )
Con_DPrintf( S_ERROR "disk error opening file.\n" );
break;
case REGDB_E_CLASSNOTREG:
default:
if( !Avi->quiet )
Con_DPrintf( S_ERROR "no handler found (or file not found).\n" );
break;
}
return;
}
Avi->video_stream = Avi->audio_stream = NULL;
// open the streams until a stream is not available.
while( 1 )
{
PAVISTREAM stream = NULL;
if( pAVIFileGetStream( Avi->pfile, &stream, 0L, opened_streams++ ) != AVIERR_OK )
break;
if( stream == NULL )
break;
pAVIStreamInfo( stream, &stream_info, sizeof( stream_info ));
if( stream_info.fccType == streamtypeVIDEO && Avi->video_stream == NULL )
{
Avi->video_stream = stream;
Avi->video_frames = stream_info.dwLength;
Avi->video_xres = stream_info.rcFrame.right - stream_info.rcFrame.left;
Avi->video_yres = stream_info.rcFrame.bottom - stream_info.rcFrame.top;
Avi->video_fps = (float)stream_info.dwRate / (float)stream_info.dwScale;
}
else if( stream_info.fccType == streamtypeAUDIO && Avi->audio_stream == NULL && load_audio )
{
int size;
Avi->audio_stream = stream;
// read the audio header
pAVIStreamReadFormat( Avi->audio_stream, pAVIStreamStart( Avi->audio_stream ), 0, &size );
Avi->audio_header = (WAVEFORMAT *)Mem_Malloc( cls.mempool, size );
pAVIStreamReadFormat( Avi->audio_stream, pAVIStreamStart( Avi->audio_stream ), Avi->audio_header, &size );
Avi->audio_header_size = size;
Avi->audio_codec = Avi->audio_header->wFormatTag;
// length of converted audio in samples
Avi->audio_length = (int)((float)stream_info.dwLength / Avi->audio_header->nAvgBytesPerSec );
Avi->audio_length *= Avi->audio_header->nSamplesPerSec;
if( Avi->audio_codec != WAVE_FORMAT_PCM )
{
if( !AVI_ACMConvertAudio( Avi ))
{
Mem_Free( Avi->audio_header );
Avi->audio_stream = NULL;
continue;
}
}
else Avi->audio_bytes_per_sample = Avi->audio_header->nBlockAlign;
Avi->audio_length *= Avi->audio_bytes_per_sample;
}
else
{
pAVIStreamRelease( stream );
}
}
// display error message-stream not found.
if( Avi->video_stream == NULL )
{
if( Avi->pfile ) // if file is open, close it
pAVIFileRelease( Avi->pfile );
if( !Avi->quiet )
Con_DPrintf( S_ERROR "couldn't find a valid video stream.\n" );
return;
}
pAVIFileRelease( Avi->pfile ); // release the file
Avi->video_getframe = pAVIStreamGetFrameOpen( Avi->video_stream, NULL ); // open the frame getter
if( Avi->video_getframe == NULL )
{
if( !Avi->quiet )
Con_DPrintf( S_ERROR "error attempting to read video frames.\n" );
return; // couldn't open frame getter.
}
bmih.biSize = sizeof( BITMAPINFOHEADER );
bmih.biPlanes = 1;
bmih.biBitCount = 32;
bmih.biCompression = BI_RGB;
bmih.biWidth = Avi->video_xres;
bmih.biHeight = -Avi->video_yres; // invert height to flip image upside down
Avi->hDC = CreateCompatibleDC( 0 );
Avi->hDD = pDrawDibOpen();
Avi->hBitmap = CreateDIBSection( Avi->hDC, (BITMAPINFO*)(&bmih), DIB_RGB_COLORS, (void**)(&Avi->pframe_data), NULL, 0 );
SelectObject( Avi->hDC, Avi->hBitmap );
Avi->active = true; // done
}
qboolean AVI_IsActive( movie_state_t *Avi )
{
if( Avi != NULL )
return Avi->active;
return false;
}
movie_state_t *AVI_GetState( int num )
{
return &avi[num];
}
/*
=============
AVIKit user interface
=============
*/
movie_state_t *AVI_LoadVideo( const char *filename, qboolean load_audio )
{
movie_state_t *Avi;
string path;
const char *fullpath;
// fast reject
if( !avi_initialized )
return NULL;
// open cinematic
Q_snprintf( path, sizeof( path ), "media/%s", filename );
COM_DefaultExtension( path, ".avi", sizeof( path ));
fullpath = FS_GetDiskPath( path, false );
if( FS_FileExists( path, false ) && !fullpath )
{
Con_Printf( "Couldn't load %s from packfile. Please extract it\n", path );
return NULL;
}
Avi = Mem_Malloc( cls.mempool, sizeof( movie_state_t ));
AVI_OpenVideo( Avi, fullpath, load_audio, false );
if( !AVI_IsActive( Avi ))
{
AVI_FreeVideo( Avi ); // something bad happens
return NULL;
}
// all done
return Avi;
}
void AVI_FreeVideo( movie_state_t *state )
{
if( !state ) return;
if( Mem_IsAllocatedExt( cls.mempool, state ))
{
AVI_CloseVideo( state );
Mem_Free( state );
}
}
qboolean AVI_Initailize( void )
{
if( Sys_CheckParm( "-noavi" ))
{
Con_Printf( "AVI: Disabled\n" );
return false;
}
if( !Sys_LoadLibrary( &avifile_dll ))
return false;
if( !Sys_LoadLibrary( &msvfw_dll ))
{
Sys_FreeLibrary( &avifile_dll );
return false;
}
if( !Sys_LoadLibrary( &msacm_dll ))
{
Sys_FreeLibrary( &avifile_dll );
Sys_FreeLibrary( &msvfw_dll );
return false;
}
avi_initialized = true;
pAVIFileInit();
return true;
}
void AVI_Shutdown( void )
{
if( !avi_initialized ) return;
pAVIFileExit();
Sys_FreeLibrary( &avifile_dll );
Sys_FreeLibrary( &msvfw_dll );
Sys_FreeLibrary( &msacm_dll );
avi_initialized = false;
}
#endif // _WIN32

View File

@@ -42,8 +42,7 @@ void CL_PlayVideo_f( void )
switch( Cmd_Argc( )) switch( Cmd_Argc( ))
{ {
case 2: // simple user version case 2: // simple user version
Q_snprintf( path, sizeof( path ), "media/%s", Cmd_Argv( 1 )); Q_snprintf( path, sizeof( path ), "media/%s.avi", Cmd_Argv( 1 ));
COM_DefaultExtension( path, ".avi", sizeof( path ));
SCR_PlayCinematic( path ); SCR_PlayCinematic( path );
break; break;
case 3: // sequenced cinematics used this case 3: // sequenced cinematics used this

View File

@@ -153,7 +153,6 @@ static void CL_WriteErrorMessage( int current_count, sizebuf_t *msg )
FS_Write( fp, &cls.starting_count, sizeof( int )); FS_Write( fp, &cls.starting_count, sizeof( int ));
FS_Write( fp, &current_count, sizeof( int )); FS_Write( fp, &current_count, sizeof( int ));
FS_Write( fp, &cls.legacymode, sizeof( cls.legacymode ));
FS_Write( fp, MSG_GetData( msg ), MSG_GetMaxBytes( msg )); FS_Write( fp, MSG_GetData( msg ), MSG_GetMaxBytes( msg ));
FS_Close( fp ); FS_Close( fp );
@@ -169,7 +168,7 @@ list last 32 messages for debugging net troubleshooting
*/ */
void CL_WriteMessageHistory( void ) void CL_WriteMessageHistory( void )
{ {
oldcmd_t *old; oldcmd_t *old, *failcommand;
sizebuf_t *msg = &net_message; sizebuf_t *msg = &net_message;
int i, thecmd; int i, thecmd;
@@ -193,8 +192,9 @@ void CL_WriteMessageHistory( void )
thecmd++; thecmd++;
} }
old = &cls_message_debug.oldcmd[thecmd]; failcommand = &cls_message_debug.oldcmd[thecmd];
Con_Printf( S_RED "BAD: " S_DEFAULT "%i %04i %s\n", old->frame_number, old->starting_offset, CL_MsgInfo( old->command )); Con_Printf( "BAD: %3i:%s\n", MSG_GetNumBytesRead( msg ) - 1, CL_MsgInfo( failcommand->command ));
CL_WriteErrorMessage( old->starting_offset, msg ); if( host_developer.value >= DEV_EXTENDED )
CL_WriteErrorMessage( MSG_GetNumBytesRead( msg ) - 1, msg );
cls_message_debug.parsing = false; cls_message_debug.parsing = false;
} }

View File

@@ -373,7 +373,7 @@ CL_WriteDemoUserMessage
Dumps the user message (demoaction) Dumps the user message (demoaction)
==================== ====================
*/ */
void GAME_EXPORT CL_WriteDemoUserMessage( int size, byte *buffer ) void CL_WriteDemoUserMessage( const byte *buffer, size_t size )
{ {
if( !cls.demorecording || cls.demowaiting ) if( !cls.demorecording || cls.demowaiting )
return; return;
@@ -624,10 +624,11 @@ static void CL_ReadDemoUserCmd( qboolean discard )
if( !discard ) if( !discard )
{ {
const usercmd_t nullcmd = { 0 }; usercmd_t nullcmd;
sizebuf_t buf; sizebuf_t buf;
demoangle_t *a; demoangle_t *a;
memset( &nullcmd, 0, sizeof( nullcmd ));
MSG_Init( &buf, "UserCmd", data, sizeof( data )); MSG_Init( &buf, "UserCmd", data, sizeof( data ));
// a1ba: I have no proper explanation why // a1ba: I have no proper explanation why

View File

@@ -2229,3 +2229,4 @@ void CL_ThinkParticle( double frametime, particle_t *p )
break; break;
} }
} }

View File

@@ -556,7 +556,7 @@ static void CL_InitTitles( const char *filename )
Q_snprintf( name, sizeof( name ), TEXT_MSGNAME, i ); Q_snprintf( name, sizeof( name ), TEXT_MSGNAME, i );
cl_textmessage[i].pName = copystringpool( clgame.mempool, name ); cl_textmessage[i].pName = _copystring( clgame.mempool, name, __FILE__, __LINE__ );
cl_textmessage[i].pMessage = cl_textbuffer[i]; cl_textmessage[i].pMessage = cl_textbuffer[i];
} }
@@ -3348,6 +3348,28 @@ DemoApi implementation
================= =================
*/ */
/*
=================
Demo_IsRecording
=================
*/
static int GAME_EXPORT Demo_IsRecording( void )
{
return cls.demorecording;
}
/*
=================
Demo_IsPlayingback
=================
*/
static int GAME_EXPORT Demo_IsPlayingback( void )
{
return cls.demoplayback;
}
/* /*
================= =================
Demo_IsTimeDemo Demo_IsTimeDemo
@@ -3359,6 +3381,17 @@ static int GAME_EXPORT Demo_IsTimeDemo( void )
return cls.timedemo; return cls.timedemo;
} }
/*
=================
Demo_WriteBuffer
=================
*/
static void GAME_EXPORT Demo_WriteBuffer( int size, byte *buffer )
{
CL_WriteDemoUserMessage( buffer, size );
}
/* /*
================= =================
NetworkApi implementation NetworkApi implementation
@@ -3544,6 +3577,28 @@ static int GAME_EXPORT NetAPI_CompareAdr( netadr_t *a, netadr_t *b )
return NET_CompareAdr( *a, *b ); return NET_CompareAdr( *a, *b );
} }
/*
=================
NetAPI_StringToAdr
=================
*/
static int GAME_EXPORT NetAPI_StringToAdr( char *s, netadr_t *a )
{
return NET_StringToAdr( s, a );
}
/*
=================
NetAPI_ValueForKey
=================
*/
static const char * GAME_EXPORT NetAPI_ValueForKey( const char *s, const char *key )
{
return Info_ValueForKey( s, key );
}
/* /*
================= =================
NetAPI_RemoveKey NetAPI_RemoveKey
@@ -3740,10 +3795,10 @@ static event_api_t gEventApi =
static demo_api_t gDemoApi = static demo_api_t gDemoApi =
{ {
(void *)CL_IsRecordDemo, Demo_IsRecording,
(void *)CL_IsPlaybackDemo, Demo_IsPlayingback,
Demo_IsTimeDemo, Demo_IsTimeDemo,
CL_WriteDemoUserMessage, Demo_WriteBuffer,
}; };
net_api_t gNetApi = net_api_t gNetApi =
@@ -3755,8 +3810,8 @@ net_api_t gNetApi =
NetAPI_CancelAllRequests, NetAPI_CancelAllRequests,
NetAPI_AdrToString, NetAPI_AdrToString,
NetAPI_CompareAdr, NetAPI_CompareAdr,
(void *)NET_StringToAdr, NetAPI_StringToAdr,
Info_ValueForKey, NetAPI_ValueForKey,
NetAPI_RemoveKey, NetAPI_RemoveKey,
NetAPI_SetValueForKey, NetAPI_SetValueForKey,
}; };

View File

@@ -302,11 +302,14 @@ void UI_ConnectionProgress_ParseServerInfo( const char *server )
static void GAME_EXPORT UI_DrawLogo( const char *filename, float x, float y, float width, float height ) static void GAME_EXPORT UI_DrawLogo( const char *filename, float x, float y, float width, float height )
{ {
static float cin_time;
static int last_frame = -1;
byte *cin_data = NULL;
movie_state_t *cin_state; movie_state_t *cin_state;
int cin_frame;
qboolean redraw = false;
if( !gameui.drawLogo ) if( !gameui.drawLogo ) return;
return;
cin_state = AVI_GetState( CIN_LOGO ); cin_state = AVI_GetState( CIN_LOGO );
if( !AVI_IsActive( cin_state )) if( !AVI_IsActive( cin_state ))
@@ -333,25 +336,37 @@ static void GAME_EXPORT UI_DrawLogo( const char *filename, float x, float y, flo
gameui.drawLogo = false; gameui.drawLogo = false;
return; return;
} }
cin_time = 0.0f;
last_frame = -1;
} }
if( width <= 0 || height <= 0 ) if( width <= 0 || height <= 0 )
{ {
// precache call, don't draw // precache call, don't draw
cin_time = 0.0f;
last_frame = -1;
return; return;
} }
AVI_SetParm( cin_state, // advances cinematic time (ignores maxfps and host_framerate settings)
AVI_RENDER_TEXNUM, 0, cin_time += host.realframetime;
AVI_RENDER_X, (int)x,
AVI_RENDER_Y, (int)y, // restarts the cinematic
AVI_RENDER_W, (int)width, if( cin_time > gameui.logo_length )
AVI_RENDER_H, (int)height, cin_time = 0.0f;
AVI_PARM_LAST );
// read the next frame // read the next frame
if( !AVI_Think( cin_state )) cin_frame = AVI_GetVideoFrameNumber( cin_state, cin_time );
AVI_SetParm( cin_state, AVI_REWIND, AVI_PARM_LAST );
if( cin_frame != last_frame )
{
cin_data = AVI_GetVideoFrame( cin_state, cin_frame );
last_frame = cin_frame;
redraw = true;
}
ref.dllFuncs.R_DrawStretchRaw( x, y, width, height, gameui.logo_xres, gameui.logo_yres, cin_data, redraw );
} }
static int GAME_EXPORT UI_GetLogoWidth( void ) static int GAME_EXPORT UI_GetLogoWidth( void )

View File

@@ -76,7 +76,6 @@ static CVAR_DEFINE_AUTO( cl_upmax, "1200", FCVAR_ARCHIVE, "max allowed incoming
CVAR_DEFINE_AUTO( cl_lw, "1", FCVAR_ARCHIVE|FCVAR_USERINFO, "enable client weapon predicting" ); CVAR_DEFINE_AUTO( cl_lw, "1", FCVAR_ARCHIVE|FCVAR_USERINFO, "enable client weapon predicting" );
CVAR_DEFINE_AUTO( cl_charset, "utf-8", FCVAR_ARCHIVE, "1-byte charset to use (iconv style)" ); CVAR_DEFINE_AUTO( cl_charset, "utf-8", FCVAR_ARCHIVE, "1-byte charset to use (iconv style)" );
CVAR_DEFINE_AUTO( cl_trace_consistency, "0", FCVAR_ARCHIVE, "enable consistency info tracing (good for developers)" );
CVAR_DEFINE_AUTO( cl_trace_stufftext, "0", FCVAR_ARCHIVE, "enable stufftext (server-to-client console commands) tracing (good for developers)" ); CVAR_DEFINE_AUTO( cl_trace_stufftext, "0", FCVAR_ARCHIVE, "enable stufftext (server-to-client console commands) tracing (good for developers)" );
CVAR_DEFINE_AUTO( cl_trace_messages, "0", FCVAR_ARCHIVE|FCVAR_CHEAT, "enable message names tracing (good for developers)" ); CVAR_DEFINE_AUTO( cl_trace_messages, "0", FCVAR_ARCHIVE|FCVAR_CHEAT, "enable message names tracing (good for developers)" );
CVAR_DEFINE_AUTO( cl_trace_events, "0", FCVAR_ARCHIVE|FCVAR_CHEAT, "enable events tracing (good for developers)" ); CVAR_DEFINE_AUTO( cl_trace_events, "0", FCVAR_ARCHIVE|FCVAR_CHEAT, "enable events tracing (good for developers)" );
@@ -148,6 +147,11 @@ qboolean CL_IsRecordDemo( void )
return cls.demorecording; return cls.demorecording;
} }
qboolean CL_IsTimeDemo( void )
{
return cls.timedemo;
}
qboolean CL_DisableVisibility( void ) qboolean CL_DisableVisibility( void )
{ {
return cls.envshot_disable_vis; return cls.envshot_disable_vis;
@@ -594,7 +598,7 @@ CL_CreateCmd
*/ */
static void CL_CreateCmd( void ) static void CL_CreateCmd( void )
{ {
usercmd_t nullcmd = { 0 }, *cmd; usercmd_t nullcmd, *cmd;
runcmd_t *pcmd; runcmd_t *pcmd;
qboolean active; qboolean active;
double accurate_ms; double accurate_ms;
@@ -646,6 +650,7 @@ static void CL_CreateCmd( void )
} }
else else
{ {
memset( &nullcmd, 0, sizeof( nullcmd ));
cmd = &nullcmd; cmd = &nullcmd;
} }
@@ -718,20 +723,11 @@ static void CL_WritePacket( void )
int numbackup, maxbackup, maxcmds; int numbackup, maxbackup, maxcmds;
const connprotocol_t proto = cls.legacymode; const connprotocol_t proto = cls.legacymode;
// FIXME: on Xash protocol we don't send move commands until ca_active
// to prevent outgoing_command outrun incoming_acknowledged
// which is fatal for some buggy mods like TFC
//
// ... but GoldSrc don't have (real) ca_validate state, so we consider
// ca_validate the same as ca_active, otherwise we don't pass validation
// of server-side mods like ReAuthCheck
const connstate_t min_state = proto == PROTO_GOLDSRC ? ca_validate : ca_active;
// don't send anything if playing back a demo // don't send anything if playing back a demo
if( cls.demoplayback || cls.state < ca_connected || cls.state == ca_cinematic ) if( cls.demoplayback || cls.state < ca_connected || cls.state == ca_cinematic )
return; return;
if( cls.state < min_state ) if( cls.state <= ca_connected )
{ {
Netchan_TransmitBits( &cls.netchan, 0, "" ); Netchan_TransmitBits( &cls.netchan, 0, "" );
return; return;
@@ -829,7 +825,7 @@ static void CL_WritePacket( void )
buf.pData[key] = CRC32_BlockSequence( &buf.pData[key + 1], size, cls.netchan.outgoing_sequence ); buf.pData[key] = CRC32_BlockSequence( &buf.pData[key + 1], size, cls.netchan.outgoing_sequence );
COM_Munge( &buf.pData[key + 1], Q_min( size, 255 ), cls.netchan.outgoing_sequence ); COM_Munge( &buf.pData[key + 1], Q_min( size, 255 ), cls.netchan.outgoing_sequence );
} }
else if( !Host_IsLocalClient( )) else
{ {
int size = MSG_GetRealBytesWritten( &buf ) - key - 1; int size = MSG_GetRealBytesWritten( &buf ) - key - 1;
buf.pData[key] = CRC32_BlockSequence( &buf.pData[key + 1], size, cls.netchan.outgoing_sequence ); buf.pData[key] = CRC32_BlockSequence( &buf.pData[key + 1], size, cls.netchan.outgoing_sequence );
@@ -1598,9 +1594,6 @@ void CL_SetupNetchanForProtocol( connprotocol_t proto )
} }
break; break;
default: default:
if( !Host_IsLocalClient( ))
SetBits( flags, NETCHAN_USE_LZSS );
cls.extensions = Q_atoi( Info_ValueForKey( Cmd_Argv( 1 ), "ext" )); cls.extensions = Q_atoi( Info_ValueForKey( Cmd_Argv( 1 ), "ext" ));
if( FBitSet( cls.extensions, NET_EXT_SPLITSIZE )) if( FBitSet( cls.extensions, NET_EXT_SPLITSIZE ))
@@ -3394,7 +3387,6 @@ static void CL_InitLocal( void )
Cvar_RegisterVariable( &rcon_address ); Cvar_RegisterVariable( &rcon_address );
Cvar_RegisterVariable( &cl_trace_consistency );
Cvar_RegisterVariable( &cl_trace_stufftext ); Cvar_RegisterVariable( &cl_trace_stufftext );
Cvar_RegisterVariable( &cl_trace_messages ); Cvar_RegisterVariable( &cl_trace_messages );
Cvar_RegisterVariable( &cl_trace_events ); Cvar_RegisterVariable( &cl_trace_events );
@@ -3666,8 +3658,6 @@ void CL_Init( void )
if( !CL_LoadProgs( libpath )) if( !CL_LoadProgs( libpath ))
Host_Error( "can't initialize %s: %s\n", libpath, COM_GetLibraryError( )); Host_Error( "can't initialize %s: %s\n", libpath, COM_GetLibraryError( ));
ID_Init();
cls.build_num = 0; cls.build_num = 0;
cls.initialized = true; cls.initialized = true;
cl.maxclients = 1; // allow to drawing player in menu cl.maxclients = 1; // allow to drawing player in menu

View File

@@ -1614,23 +1614,6 @@ void CL_UpdateUserPings( sizebuf_t *msg )
} }
} }
static const char *CL_CheckTypeToString( int check_type )
{
// renamed so they have same width and look better in console output
switch( check_type )
{
case force_exactfile:
return "exactfile";
case force_model_samebounds:
return "samebounds";
case force_model_specifybounds:
return "specbounds";
case force_model_specifybounds_if_avail:
return "specbounds2";
}
return "unknown";
}
static void CL_SendConsistencyInfo( sizebuf_t *msg, connprotocol_t proto ) static void CL_SendConsistencyInfo( sizebuf_t *msg, connprotocol_t proto )
{ {
qboolean user_changed_diskfile; qboolean user_changed_diskfile;
@@ -1896,9 +1879,6 @@ static void CL_ParseConsistencyInfo( sizebuf_t *msg, connprotocol_t proto )
return; return;
} }
if( cl_trace_consistency.value )
Con_Printf( "Server wants consistency of the following resources:\n" );
skip_crc_change = NULL; skip_crc_change = NULL;
lastcheck = 0; lastcheck = 0;
@@ -1930,7 +1910,7 @@ static void CL_ParseConsistencyInfo( sizebuf_t *msg, connprotocol_t proto )
pc = &cl.consistency_list[cl.num_consistency]; pc = &cl.consistency_list[cl.num_consistency];
cl.num_consistency++; cl.num_consistency++;
memset( pc, 0, sizeof( *pc )); memset( pc, 0, sizeof( consistency_t ));
pc->filename = pResource->szFileName; pc->filename = pResource->szFileName;
pc->issound = (pResource->type == t_sound); pc->issound = (pResource->type == t_sound);
pc->orig_index = delta; pc->orig_index = delta;
@@ -1943,9 +1923,6 @@ static void CL_ParseConsistencyInfo( sizebuf_t *msg, connprotocol_t proto )
pc->check_type = pResource->rguc_reserved[0]; pc->check_type = pResource->rguc_reserved[0];
} }
if( cl_trace_consistency.value )
Con_Printf( "%s\t%s\t%s\n", COM_ResourceTypeFromIndex( pResource->type ), CL_CheckTypeToString( pc->check_type ), pc->filename );
skip_crc_change = pResource; skip_crc_change = pResource;
lastcheck = delta; lastcheck = delta;
} }

View File

@@ -91,11 +91,11 @@ static void CL_ParseNewMovevars( sizebuf_t *msg )
typedef struct delta_header_t typedef struct delta_header_t
{ {
qboolean remove; qboolean remove : 1;
qboolean custom; qboolean custom : 1;
qboolean instanced; qboolean instanced : 1;
uint16_t instanced_baseline_index; uint instanced_baseline_index : 6;
uint16_t offset; uint offset : 6;
} delta_header_t; } delta_header_t;
static int CL_ParseDeltaHeader( sizebuf_t *msg, qboolean delta, int oldnum, struct delta_header_t *hdr ) static int CL_ParseDeltaHeader( sizebuf_t *msg, qboolean delta, int oldnum, struct delta_header_t *hdr )
@@ -160,47 +160,33 @@ static int CL_GetEntityDelta( const struct delta_header_t *hdr, int entnum )
return DT_ENTITY_STATE_T; return DT_ENTITY_STATE_T;
} }
static int CL_FlushEntityPacketGS( frame_t *frame, sizebuf_t *msg ) static void CL_FlushEntityPacketGS( frame_t *frame, sizebuf_t *msg )
{ {
int playerbytes = 0, numbase = 0;
frame->valid = false; frame->valid = false;
cl.validsequence = 0; // can't render a frame cl.validsequence = 0; // can't render a frame
// read it all but ignore it // read it all but ignore it
while( 1 ) while( 1 )
{ {
int newnum, bufstart; int num = 0;
entity_state_t from = { 0 }, to; entity_state_t from = { 0 }, to;
delta_header_t hdr; delta_header_t hdr;
qboolean player;
if( MSG_ReadWord( msg ) != 0 ) if( MSG_ReadWord( msg ) != 0 )
{ {
MSG_SeekToBit( msg, -16, SEEK_CUR ); MSG_SeekToBit( msg, -16, SEEK_CUR );
numbase = newnum = CL_ParseDeltaHeader( msg, true, numbase, &hdr ); num = CL_ParseDeltaHeader( msg, false, num, &hdr );
} }
else break; else break;
if( MSG_CheckOverflow( msg )) if( MSG_CheckOverflow( msg ))
Host_Error( "%s: overflow\n", __func__ ); Host_Error( "%s: overflow\n", __func__ );
player = CL_IsPlayerIndex( newnum );
bufstart = MSG_GetNumBytesRead( msg );
if( hdr.remove ) if( hdr.remove )
continue; continue;
Delta_ReadGSFields( msg, CL_GetEntityDelta( &hdr, newnum ), &from, &to, cl.mtime[0] ); Delta_ReadGSFields( msg, CL_GetEntityDelta( &hdr, num ), &from, &to, cl.mtime[0] );
if( player )
playerbytes += MSG_GetNumBytesRead( msg ) - bufstart;
} }
if( MSG_CheckOverflow( msg ))
Host_Error( "%s: overflow\n", __func__ );
return playerbytes;
} }
static void CL_DeltaEntityGS( const delta_header_t *hdr, sizebuf_t *msg, frame_t *frame, int newnum, const entity_state_t *from ) static void CL_DeltaEntityGS( const delta_header_t *hdr, sizebuf_t *msg, frame_t *frame, int newnum, const entity_state_t *from )
@@ -217,7 +203,7 @@ static void CL_DeltaEntityGS( const delta_header_t *hdr, sizebuf_t *msg, frame_t
if(( newnum < 0 ) || ( newnum >= clgame.maxEntities )) if(( newnum < 0 ) || ( newnum >= clgame.maxEntities ))
{ {
Con_DPrintf( S_ERROR "CL_DeltaEntity: invalid newnum: %d\n", newnum ); Con_DPrintf( S_ERROR "CL_DeltaEntity: invalid newnum: %d\n", newnum );
Host_Error( "%s: bad delta entity number: %i\n", __func__, newnum ); Host_Error( "%s: bad delta entity number: %i", __func__, newnum );
return; return;
} }
@@ -281,7 +267,7 @@ static void CL_CopyPacketEntity( frame_t *frame, int num, const entity_state_t *
static int CL_ParsePacketEntitiesGS( sizebuf_t *msg, qboolean delta ) static int CL_ParsePacketEntitiesGS( sizebuf_t *msg, qboolean delta )
{ {
frame_t *frame, *oldframe; frame_t *frame, *oldframe;
int oldindex, oldnum, numbase = 0; int oldindex, newnum, oldnum, numbase = 0;
entity_state_t *oldent; entity_state_t *oldent;
int count; int count;
int playerbytes = 0; int playerbytes = 0;
@@ -328,7 +314,7 @@ static int CL_ParsePacketEntitiesGS( sizebuf_t *msg, qboolean delta )
// read it all but ignore it // read it all but ignore it
while( 1 ) while( 1 )
{ {
int bufstart, newnum; int bufstart;
qboolean player; qboolean player;
delta_header_t hdr; delta_header_t hdr;
int val = MSG_ReadWord( msg ); int val = MSG_ReadWord( msg );
@@ -548,7 +534,7 @@ void CL_ParseGoldSrcServerMessage( sizebuf_t *msg )
{ {
if( MSG_CheckOverflow( msg )) if( MSG_CheckOverflow( msg ))
{ {
Host_Error( "%s: overflow!\n", __func__ ); Host_Error( "CL_ParseServerMessage: overflow!\n" );
return; return;
} }

View File

@@ -233,11 +233,6 @@ static intptr_t pfnRenderGetParm( int parm, int arg )
return CL_RenderGetParm( parm, arg, true ); return CL_RenderGetParm( parm, arg, true );
} }
static void pfnAVI_StreamSound( movie_state_t *avi, int entnum, float fvol, float attn, float synctime )
{
return; // stub, use AVI_SetParm and AVI_Think to stream AVI sound
}
static render_api_t gRenderAPI = static render_api_t gRenderAPI =
{ {
pfnRenderGetParm, // GL_RenderGetParm, pfnRenderGetParm, // GL_RenderGetParm,
@@ -263,16 +258,16 @@ static render_api_t gRenderAPI =
NULL, // DrawSingleDecal, NULL, // DrawSingleDecal,
NULL, // R_DecalSetupVerts, NULL, // R_DecalSetupVerts,
NULL, // R_EntityRemoveDecals, NULL, // R_EntityRemoveDecals,
AVI_LoadVideo, (void*)AVI_LoadVideo,
AVI_GetVideoInfo, (void*)AVI_GetVideoInfo,
AVI_GetVideoFrameNumber, (void*)AVI_GetVideoFrameNumber,
AVI_GetVideoFrame, (void*)AVI_GetVideoFrame,
NULL, // R_UploadStretchRaw, NULL, // R_UploadStretchRaw,
AVI_FreeVideo, (void*)AVI_FreeVideo,
AVI_IsActive, (void*)AVI_IsActive,
pfnAVI_StreamSound, S_StreamAviSamples,
AVI_Think, NULL,
AVI_SetParm, NULL,
NULL, // GL_Bind, NULL, // GL_Bind,
NULL, // GL_SelectTexture, NULL, // GL_SelectTexture,
NULL, // GL_LoadTexMatrixExt, NULL, // GL_LoadTexMatrixExt,

View File

@@ -24,6 +24,11 @@ AVI PLAYING
================================================================= =================================================================
*/ */
static int xres, yres;
static float video_duration;
static float cin_time;
static int cin_frame;
static wavdata_t cin_audio;
static movie_state_t *cin_state; static movie_state_t *cin_state;
/* /*
@@ -83,17 +88,7 @@ void SCR_CheckStartupVids( void )
char *pfile; char *pfile;
string token; string token;
#if 0 if( Sys_CheckParm( "-nointro" ) || host_developer.value || cls.demonum != -1 || GameState->nextstate != STATE_RUNFRAME )
if( host_developer.value )
{
// don't run movies where we in developer-mode
cls.movienum = -1;
CL_CheckStartupDemos();
return;
}
#endif
if( Sys_CheckParm( "-nointro" ) || cls.demonum != -1 || GameState->nextstate != STATE_RUNFRAME )
{ {
// don't run movies where we in developer-mode // don't run movies where we in developer-mode
cls.movienum = -1; cls.movienum = -1;
@@ -152,9 +147,23 @@ void SCR_RunCinematic( void )
Key_SetKeyDest( key_menu ); Key_SetKeyDest( key_menu );
S_StopStreaming(); S_StopStreaming();
cls.movienum = -1; cls.movienum = -1;
cin_time = 0.0f;
cls.signon = 0; cls.signon = 0;
return; return;
} }
// advances cinematic time (ignores maxfps and host_framerate settings)
cin_time += host.realframetime;
// stop the video after it finishes
if( cin_time > video_duration + 0.1f )
{
SCR_NextMovie( );
return;
}
// read the next frame
cin_frame = AVI_GetVideoFrameNumber( cin_state, cin_time );
} }
/* /*
@@ -167,11 +176,21 @@ should be skipped
*/ */
qboolean SCR_DrawCinematic( void ) qboolean SCR_DrawCinematic( void )
{ {
if( !ref.initialized ) static int last_frame = -1;
qboolean redraw = false;
byte *frame = NULL;
if( !ref.initialized || cin_time <= 0.0f )
return false; return false;
if( !AVI_Think( cin_state )) if( cin_frame != last_frame )
return SCR_NextMovie(); {
frame = AVI_GetVideoFrame( cin_state, cin_frame );
last_frame = cin_frame;
redraw = true;
}
ref.dllFuncs.R_DrawStretchRaw( 0, 0, refState.width, refState.height, xres, yres, frame, redraw );
return true; return true;
} }
@@ -200,28 +219,45 @@ qboolean SCR_PlayCinematic( const char *arg )
return false; return false;
} }
if( AVI_HaveAudioTrack( cin_state )) if( !( AVI_GetVideoInfo( cin_state, &xres, &yres, &video_duration ))) // couldn't open this at all.
{
AVI_CloseVideo( cin_state );
return false;
}
if( AVI_GetAudioInfo( cin_state, &cin_audio ))
{ {
// begin streaming // begin streaming
S_StopAllSounds( true ); S_StopAllSounds( true );
S_StartStreaming(); S_StartStreaming();
} }
AVI_SetParm( cin_state,
AVI_RENDER_X, 0,
AVI_RENDER_Y, 0,
AVI_RENDER_W, -1,
AVI_RENDER_H, -1,
AVI_PARM_LAST );
UI_SetActiveMenu( false ); UI_SetActiveMenu( false );
cls.state = ca_cinematic; cls.state = ca_cinematic;
Con_FastClose(); Con_FastClose();
cin_time = 0.0f;
cls.signon = 0; cls.signon = 0;
return true; return true;
} }
int SCR_GetAudioChunk( char *rawdata, int length )
{
int r;
r = AVI_GetAudioChunk( cin_state, rawdata, cin_audio.loopStart, length );
cin_audio.loopStart += r; // advance play position
return r;
}
wavdata_t *SCR_GetMovieInfo( void )
{
if( AVI_IsActive( cin_state ))
return &cin_audio;
return NULL;
}
/* /*
================== ==================
SCR_StopCinematic SCR_StopCinematic
@@ -234,6 +270,7 @@ void SCR_StopCinematic( void )
AVI_CloseVideo( cin_state ); AVI_CloseVideo( cin_state );
S_StopStreaming(); S_StopStreaming();
cin_time = 0.0f;
cls.state = ca_disconnected; cls.state = ca_disconnected;
cls.signon = 0; cls.signon = 0;

View File

@@ -688,7 +688,6 @@ extern convar_t r_showtextures;
extern convar_t cl_bmodelinterp; extern convar_t cl_bmodelinterp;
extern convar_t cl_lw; // local weapons extern convar_t cl_lw; // local weapons
extern convar_t cl_charset; extern convar_t cl_charset;
extern convar_t cl_trace_consistency;
extern convar_t cl_trace_stufftext; extern convar_t cl_trace_stufftext;
extern convar_t cl_trace_messages; extern convar_t cl_trace_messages;
extern convar_t cl_trace_events; extern convar_t cl_trace_events;
@@ -768,7 +767,7 @@ void CL_StartupDemoHeader( void );
void CL_DrawDemoRecording( void ); void CL_DrawDemoRecording( void );
void CL_WriteDemoUserCmd( int cmdnumber ); void CL_WriteDemoUserCmd( int cmdnumber );
void CL_WriteDemoMessage( qboolean startup, int start, sizebuf_t *msg ); void CL_WriteDemoMessage( qboolean startup, int start, sizebuf_t *msg );
void CL_WriteDemoUserMessage( int size, byte *buffer ); void CL_WriteDemoUserMessage( const byte *buffer, size_t size );
qboolean CL_DemoReadMessage( byte *buffer, size_t *length ); qboolean CL_DemoReadMessage( byte *buffer, size_t *length );
void CL_DemoInterpolateAngles( void ); void CL_DemoInterpolateAngles( void );
void CL_CheckStartupDemos( void ); void CL_CheckStartupDemos( void );
@@ -1120,7 +1119,7 @@ void Con_PageUp( int lines );
// //
// s_main.c // s_main.c
// //
typedef int sound_t; void S_StreamAviSamples( void *Avi, int entnum, float fvol, float attn, float synctime );
void S_StartBackgroundTrack( const char *intro, const char *loop, int position, qboolean fullpath ); void S_StartBackgroundTrack( const char *intro, const char *loop, int position, qboolean fullpath );
void S_StopBackgroundTrack( void ); void S_StopBackgroundTrack( void );
void S_StreamSetPause( int pause ); void S_StreamSetPause( int pause );
@@ -1209,13 +1208,6 @@ void Key_EnableTextInput( qboolean enable, qboolean force );
int Key_ToUpper( int key ); int Key_ToUpper( int key );
void OSK_Draw( void ); void OSK_Draw( void );
//
// identification.c
//
void ID_Init( void );
const char *ID_GetMD5( void );
void GAME_EXPORT ID_SetCustomClientID( const char *id );
extern rgba_t g_color_table[8]; extern rgba_t g_color_table[8];
extern triangleapi_t gTriApi; extern triangleapi_t gTriApi;
extern net_api_t gNetApi; extern net_api_t gNetApi;

View File

@@ -902,10 +902,9 @@ static void Touch_AddButton_f( void )
rgba_t color; rgba_t color;
int argc = Cmd_Argc( ); int argc = Cmd_Argc( );
touch_button_t *button = NULL; touch_button_t *button = NULL;
const char *name, *command; const char *name, *texture, *command;
float x1, y1, x2, y2; float x1, y1, x2, y2;
qboolean privileged = Cmd_CurrentCommandIsPrivileged(); qboolean privileged = Cmd_CurrentCommandIsPrivileged();
string texture;
if( argc < 4 ) if( argc < 4 )
{ {
@@ -914,18 +913,9 @@ static void Touch_AddButton_f( void )
} }
name = Cmd_Argv( 1 ); name = Cmd_Argv( 1 );
Q_strncpy( texture, Cmd_Argv( 2 ), sizeof( texture )); texture = Cmd_Argv( 2 );
command = Cmd_Argv( 3 ); command = Cmd_Argv( 3 );
// HACKHACK: old engine specifically used .tga for touch buttons
// and because new engine extras.pk3 don't have .tga textures
// (which instead were converted to .png) strip extension to let
// to let imagelib choose better format
//
// Remove this when old engine migration would be done
if( Q_stricmp( COM_FileExtension( texture ), "tga" ))
COM_StripExtension( texture );
if( argc < 8 ) if( argc < 8 )
{ {
x1 = y1 = 0.4f; x1 = y1 = 0.4f;

View File

@@ -51,7 +51,7 @@ static const keyname_t keynames[] =
{"CTRL", K_CTRL, "+attack" }, {"CTRL", K_CTRL, "+attack" },
{"SHIFT", K_SHIFT, "+speed" }, {"SHIFT", K_SHIFT, "+speed" },
{"CAPSLOCK", K_CAPSLOCK, "" }, {"CAPSLOCK", K_CAPSLOCK, "" },
{"SCROLLOCK", K_SCROLLLOCK, "" }, {"SCROLLOCK", K_SCROLLOCK, "" },
{"F1", K_F1, "cmd help" }, {"F1", K_F1, "cmd help" },
{"F2", K_F2, "menu_savegame" }, {"F2", K_F2, "menu_savegame" },
{"F3", K_F3, "menu_loadgame" }, {"F3", K_F3, "menu_loadgame" },
@@ -215,7 +215,7 @@ const char *Key_KeynumToString( int keynum )
return "<OUT OF RANGE>"; return "<OUT OF RANGE>";
// check for printable ascii (don't use quote) // check for printable ascii (don't use quote)
if( keynum > 32 && keynum < 127 && keynum != '"' && keynum != ';' && keynum != K_SCROLLLOCK ) if( keynum > 32 && keynum < 127 && keynum != '"' && keynum != ';' && keynum != K_SCROLLOCK )
{ {
tinystr[0] = keynum; tinystr[0] = keynum;
tinystr[1] = 0; tinystr[1] = 0;
@@ -861,9 +861,7 @@ void GAME_EXPORT Key_ClearStates( void )
for( i = 0; i < 256; i++ ) for( i = 0; i < 256; i++ )
{ {
if( i >= K_MOUSE1 && i <= K_MOUSE5 ) if( keys[i].down && i < K_MOUSE1 && i > K_MOUSE5 )
IN_MouseEvent( i - K_MOUSE1, false );
else
Key_Event( i, false ); Key_Event( i, false );
keys[i].down = 0; keys[i].down = 0;
@@ -871,6 +869,9 @@ void GAME_EXPORT Key_ClearStates( void )
keys[i].gamedown = 0; keys[i].gamedown = 0;
} }
for( i = K_MOUSE1; i < K_MOUSE5; i++ ) // from K_MOUSE1 to K_MOUSE5
IN_MouseEvent( i - K_MOUSE1, false );
if( clgame.hInstance ) if( clgame.hInstance )
clgame.dllFuncs.IN_ClearStates(); clgame.dllFuncs.IN_ClearStates();
} }

View File

@@ -312,7 +312,7 @@ static int DLY_Init( int idelay, float delay )
cur = &rgsxdly[idelay]; cur = &rgsxdly[idelay];
cur->cdelaysamplesmax = ((int)(delay * idsp_dma_speed) << sxhires) + 1; cur->cdelaysamplesmax = ((int)(delay * idsp_dma_speed) << sxhires) + 1;
cur->lpdelayline = (int *)Mem_Calloc( sndpool, cur->cdelaysamplesmax * sizeof( int )); cur->lpdelayline = (int *)Z_Calloc( cur->cdelaysamplesmax * sizeof( int ));
cur->xfade = 0; cur->xfade = 0;
// init modulation // init modulation

View File

@@ -107,18 +107,17 @@ S_CreateDefaultSound
*/ */
static wavdata_t *S_CreateDefaultSound( void ) static wavdata_t *S_CreateDefaultSound( void )
{ {
wavdata_t *sc; wavdata_t *sc;
uint samples = SOUND_DMA_SPEED;
uint channels = 1;
uint width = 2;
size_t size = samples * width * channels;
sc = Mem_Calloc( sndpool, sizeof( wavdata_t ) + size ); sc = Mem_Calloc( sndpool, sizeof( wavdata_t ));
sc->width = width;
sc->channels = channels; sc->width = 2;
sc->channels = 1;
sc->loopStart = 0;
sc->rate = SOUND_DMA_SPEED; sc->rate = SOUND_DMA_SPEED;
sc->samples = samples; sc->samples = SOUND_DMA_SPEED;
sc->size = size; sc->size = sc->samples * sc->width * sc->channels;
sc->buffer = Mem_Calloc( sndpool, sc->size );
return sc; return sc;
} }

View File

@@ -20,6 +20,8 @@ GNU General Public License for more details.
#include "pm_local.h" #include "pm_local.h"
#include "platform/platform.h" #include "platform/platform.h"
#define SND_CLIP_DISTANCE 1000.0f
dma_t dma; dma_t dma;
poolhandle_t sndpool; poolhandle_t sndpool;
static soundfade_t soundfade; static soundfade_t soundfade;
@@ -1109,7 +1111,7 @@ rawchan_t *S_FindRawChannel( int entnum, qboolean create )
S_RawSamplesStereo S_RawSamplesStereo
=================== ===================
*/ */
uint S_RawSamplesStereo( portable_samplepair_t *rawsamples, uint rawend, uint max_samples, uint samples, uint rate, word width, word channels, const byte *data ) static uint S_RawSamplesStereo( portable_samplepair_t *rawsamples, uint rawend, uint max_samples, uint samples, uint rate, word width, word channels, const byte *data )
{ {
uint fracstep, samplefrac; uint fracstep, samplefrac;
uint src, dst; uint src, dst;
@@ -1191,6 +1193,100 @@ void S_RawEntSamples( int entnum, uint samples, uint rate, word width, word chan
ch->leftvol = ch->rightvol = snd_vol; ch->leftvol = ch->rightvol = snd_vol;
} }
/*
===================
S_RawSamples
===================
*/
void S_RawSamples( uint samples, uint rate, word width, word channels, const byte *data, int entnum )
{
int snd_vol = 128;
if( entnum < 0 ) snd_vol = 256; // bg track or movie track
S_RawEntSamples( entnum, samples, rate, width, channels, data, snd_vol );
}
/*
===================
S_PositionedRawSamples
===================
*/
void S_StreamAviSamples( void *Avi, int entnum, float fvol, float attn, float synctime )
{
int bufferSamples;
int fileSamples;
byte raw[MAX_RAW_SAMPLES];
float duration = 0.0f;
int r, fileBytes;
rawchan_t *ch = NULL;
if( !dma.initialized || s_listener.paused || !CL_IsInGame( ))
return;
if( entnum < 0 || entnum >= GI->max_edicts )
return;
if( !( ch = S_FindRawChannel( entnum, true )))
return;
if( ch->sound_info.rate == 0 )
{
if( !AVI_GetAudioInfo( Avi, &ch->sound_info ))
return; // no audiotrack
}
ch->master_vol = bound( 0, fvol * 255, 255 );
ch->dist_mult = (attn / SND_CLIP_DISTANCE);
// see how many samples should be copied into the raw buffer
if( ch->s_rawend < soundtime )
ch->s_rawend = soundtime;
// position is changed, synchronization is lost etc
if( fabs( ch->oldtime - synctime ) > s_mixahead.value )
ch->sound_info.loopStart = AVI_TimeToSoundPosition( Avi, synctime * 1000 );
ch->oldtime = synctime; // keep actual time
while( ch->s_rawend < soundtime + ch->max_samples )
{
wavdata_t *info = &ch->sound_info;
bufferSamples = ch->max_samples - (ch->s_rawend - soundtime);
// decide how much data needs to be read from the file
fileSamples = bufferSamples * ((float)info->rate / SOUND_DMA_SPEED );
if( fileSamples <= 1 ) return; // no more samples need
// our max buffer size
fileBytes = fileSamples * ( info->width * info->channels );
if( fileBytes > sizeof( raw ))
{
fileBytes = sizeof( raw );
fileSamples = fileBytes / ( info->width * info->channels );
}
// read audio stream
r = AVI_GetAudioChunk( Avi, raw, info->loopStart, fileBytes );
info->loopStart += r; // advance play position
if( r < fileBytes )
{
fileBytes = r;
fileSamples = r / ( info->width * info->channels );
}
if( r > 0 )
{
// add to raw buffer
ch->s_rawend = S_RawSamplesStereo( ch->rawsamples, ch->s_rawend, ch->max_samples,
fileSamples, info->rate, info->width, info->channels, raw );
}
else break; // no more samples for this frame
}
}
/* /*
=================== ===================
S_FreeIdleRawChannels S_FreeIdleRawChannels
@@ -1594,6 +1690,7 @@ void SND_UpdateSound( void )
} }
S_StreamBackgroundTrack (); S_StreamBackgroundTrack ();
S_StreamSoundTrack ();
// mix some sound // mix some sound
S_UpdateChannels (); S_UpdateChannels ();
@@ -1857,15 +1954,14 @@ qboolean S_Init( void )
Cmd_AddCommand( "spk", S_SayReliable_f, "reliable play a specified sententce" ); Cmd_AddCommand( "spk", S_SayReliable_f, "reliable play a specified sententce" );
Cmd_AddCommand( "speak", S_Say_f, "playing a specified sententce" ); Cmd_AddCommand( "speak", S_Say_f, "playing a specified sententce" );
sndpool = Mem_AllocPool( "Sound Zone" );
dma.backendName = "None"; dma.backendName = "None";
if( !SNDDMA_Init( )) if( !SNDDMA_Init( ) )
{ {
Con_Printf( "Audio: sound system can't be initialized\n" ); Con_Printf( "Audio: sound system can't be initialized\n" );
Mem_FreePool( &sndpool );
return false; return false;
} }
sndpool = Mem_AllocPool( "Sound Zone" );
soundtime = 0; soundtime = 0;
paintedtime = 0; paintedtime = 0;

View File

@@ -16,7 +16,6 @@ GNU General Public License for more details.
#include "common.h" #include "common.h"
#include "sound.h" #include "sound.h"
#include "client.h" #include "client.h"
#include "soundlib.h"
static bg_track_t s_bgTrack; static bg_track_t s_bgTrack;
static musicfade_t musicfade; // controlled by game dlls static musicfade_t musicfade; // controlled by game dlls
@@ -213,7 +212,7 @@ void S_StreamBackgroundTrack( void )
while( ch->s_rawend < soundtime + ch->max_samples ) while( ch->s_rawend < soundtime + ch->max_samples )
{ {
const stream_t *info = s_bgTrack.stream; wavdata_t *info = FS_StreamInfo( s_bgTrack.stream );
bufferSamples = ch->max_samples - (ch->s_rawend - soundtime); bufferSamples = ch->max_samples - (ch->s_rawend - soundtime);
@@ -242,7 +241,7 @@ void S_StreamBackgroundTrack( void )
if( r > 0 ) if( r > 0 )
{ {
// add to raw buffer // add to raw buffer
S_RawEntSamples( S_RAW_SOUND_BACKGROUNDTRACK, fileSamples, info->rate, info->width, info->channels, raw, 255 ); S_RawSamples( fileSamples, info->rate, info->width, info->channels, raw, S_RAW_SOUND_BACKGROUNDTRACK );
} }
else else
{ {
@@ -287,3 +286,66 @@ void S_StopStreaming( void )
if( !dma.initialized ) return; if( !dma.initialized ) return;
s_listener.streaming = false; s_listener.streaming = false;
} }
/*
=================
S_StreamSoundTrack
=================
*/
void S_StreamSoundTrack( void )
{
int bufferSamples;
int fileSamples;
byte raw[MAX_RAW_SAMPLES];
int r, fileBytes;
rawchan_t *ch = NULL;
if( !dma.initialized || !s_listener.streaming || s_listener.paused )
return;
ch = S_FindRawChannel( S_RAW_SOUND_SOUNDTRACK, true );
Assert( ch != NULL );
// see how many samples should be copied into the raw buffer
if( ch->s_rawend < soundtime )
ch->s_rawend = soundtime;
while( ch->s_rawend < soundtime + ch->max_samples )
{
wavdata_t *info = SCR_GetMovieInfo();
if( !info ) break; // bad soundtrack?
bufferSamples = ch->max_samples - (ch->s_rawend - soundtime);
// decide how much data needs to be read from the file
fileSamples = bufferSamples * ((float)info->rate / SOUND_DMA_SPEED );
if( fileSamples <= 1 ) return; // no more samples need
// our max buffer size
fileBytes = fileSamples * ( info->width * info->channels );
if( fileBytes > sizeof( raw ))
{
fileBytes = sizeof( raw );
fileSamples = fileBytes / ( info->width * info->channels );
}
// read audio stream
r = SCR_GetAudioChunk( raw, fileBytes );
if( r < fileBytes )
{
fileBytes = r;
fileSamples = r / ( info->width * info->channels );
}
if( r > 0 )
{
// add to raw buffer
S_RawSamples( fileSamples, info->rate, info->width, info->channels, raw, S_RAW_SOUND_SOUNDTRACK );
}
else break; // no more samples for this frame
}
}

View File

@@ -557,7 +557,7 @@ static void VOX_ReadSentenceFile_( byte *buf, fs_offset_t size )
int index = cszrawsentences; int index = cszrawsentences;
int size = strlen( name ) + strlen( value ) + 2; int size = strlen( name ) + strlen( value ) + 2;
rgpszrawsentence[index] = Mem_Malloc( sndpool, size ); rgpszrawsentence[index] = Mem_Malloc( host.mempool, size );
memcpy( rgpszrawsentence[index], name, size ); memcpy( rgpszrawsentence[index], name, size );
rgpszrawsentence[index][size - 1] = 0; rgpszrawsentence[index][size - 1] = 0;
cszrawsentences++; cszrawsentences++;

View File

@@ -114,6 +114,7 @@ typedef struct rawchan_s
vec3_t origin; // only use if fixed_origin is set vec3_t origin; // only use if fixed_origin is set
volatile uint s_rawend; volatile uint s_rawend;
float oldtime; // catch time jumps float oldtime; // catch time jumps
wavdata_t sound_info; // advance play position
size_t max_samples; // buffer length size_t max_samples; // buffer length
portable_samplepair_t rawsamples[]; // variable sized portable_samplepair_t rawsamples[]; // variable sized
} rawchan_t; } rawchan_t;
@@ -170,15 +171,12 @@ typedef struct
int source; // may be game, menu, etc int source; // may be game, menu, etc
} bg_track_t; } bg_track_t;
typedef int sound_t;
//==================================================================== //====================================================================
#define MAX_DYNAMIC_CHANNELS (60 + NUM_AMBIENTS) #define MAX_DYNAMIC_CHANNELS (60 + NUM_AMBIENTS)
#define MAX_CHANNELS (256 + MAX_DYNAMIC_CHANNELS) // Scourge Of Armagon has too many static sounds on hip2m4.bsp #define MAX_CHANNELS (256 + MAX_DYNAMIC_CHANNELS) // Scourge Of Armagon has too many static sounds on hip2m4.bsp
#define MAX_RAW_CHANNELS 48 #define MAX_RAW_CHANNELS 48
#define MAX_RAW_SAMPLES 16384 #define MAX_RAW_SAMPLES 8192
#define SND_CLIP_DISTANCE 1000.0f
extern sound_t ambient_sfx[NUM_AMBIENTS]; extern sound_t ambient_sfx[NUM_AMBIENTS];
extern qboolean snd_ambient; extern qboolean snd_ambient;
@@ -244,8 +242,8 @@ int S_GetCurrentStaticSounds( soundlist_t *pout, int size );
int S_GetCurrentDynamicSounds( soundlist_t *pout, int size ); int S_GetCurrentDynamicSounds( soundlist_t *pout, int size );
sfx_t *S_GetSfxByHandle( sound_t handle ); sfx_t *S_GetSfxByHandle( sound_t handle );
rawchan_t *S_FindRawChannel( int entnum, qboolean create ); 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 );
void S_RawSamples( uint samples, uint rate, word width, word channels, const byte *data, int entnum );
void S_StopSound( int entnum, int channel, const char *soundname ); void S_StopSound( int entnum, int channel, const char *soundname );
void S_UpdateFrame( struct ref_viewpass_s *rvp ); void S_UpdateFrame( struct ref_viewpass_s *rvp );
void S_StopAllSounds( qboolean ambient ); void S_StopAllSounds( qboolean ambient );
@@ -265,6 +263,7 @@ void SND_ForceCloseMouth( int entnum );
// //
// s_stream.c // s_stream.c
// //
void S_StreamSoundTrack( void );
void S_StreamBackgroundTrack( void ); void S_StreamBackgroundTrack( void );
void S_PrintBackgroundTrackState( void ); void S_PrintBackgroundTrackState( void );
void S_FadeMusicVolume( float fadePercent ); void S_FadeMusicVolume( float fadePercent );

View File

@@ -29,20 +29,17 @@ static void Sound_Reset( void )
static MALLOC_LIKE( FS_FreeSound, 1 ) wavdata_t *SoundPack( void ) static MALLOC_LIKE( FS_FreeSound, 1 ) wavdata_t *SoundPack( void )
{ {
wavdata_t *pack = Mem_Malloc( host.soundpool, sizeof( *pack ) + sound.size ); wavdata_t *pack = Mem_Calloc( host.soundpool, sizeof( wavdata_t ));
pack->buffer = sound.wav;
pack->width = sound.width;
pack->rate = sound.rate;
pack->type = sound.type;
pack->size = sound.size; pack->size = sound.size;
pack->loopStart = sound.loopstart; pack->loopStart = sound.loopstart;
pack->samples = sound.samples; pack->samples = sound.samples;
pack->type = sound.type;
pack->flags = sound.flags;
pack->rate = sound.rate;
pack->width = sound.width;
pack->channels = sound.channels; pack->channels = sound.channels;
memcpy( pack->buffer, sound.wav, sound.size ); pack->flags = sound.flags;
Mem_Free( sound.wav );
sound.wav = NULL;
return pack; return pack;
} }
@@ -135,6 +132,7 @@ free WAV buffer
void FS_FreeSound( wavdata_t *pack ) void FS_FreeSound( wavdata_t *pack )
{ {
if( !pack ) return; if( !pack ) return;
if( pack->buffer ) Mem_Free( pack->buffer );
Mem_Free( pack ); Mem_Free( pack );
} }
@@ -201,6 +199,33 @@ stream_t *FS_OpenStream( const char *filename )
return stream; return stream;
} }
/*
================
FS_StreamInfo
get basic stream info
================
*/
wavdata_t *FS_StreamInfo( stream_t *stream )
{
static wavdata_t info;
if( !stream ) return NULL;
// fill structure
info.loopStart = 0;
info.rate = stream->rate;
info.width = stream->width;
info.channels = stream->channels;
info.flags = SOUND_STREAM;
info.size = stream->size;
info.buffer = NULL;
info.samples = 0; // not actual for streams
info.type = stream->type;
return &info;
}
/* /*
================ ================
FS_ReadStream FS_ReadStream

View File

@@ -17,7 +17,7 @@ GNU General Public License for more details.
#include "base_cmd.h" #include "base_cmd.h"
#include "cdll_int.h" #include "cdll_int.h"
#define HASH_SIZE 64 // 64 * 4 * 4 == 1024 bytes #define HASH_SIZE 128 // 128 * 4 * 4 == 2048 bytes
typedef struct base_command_hashmap_s base_command_hashmap_t; typedef struct base_command_hashmap_s base_command_hashmap_t;
@@ -26,11 +26,10 @@ struct base_command_hashmap_s
base_command_t *basecmd; // base command: cvar, alias or command base_command_t *basecmd; // base command: cvar, alias or command
base_command_hashmap_t *next; base_command_hashmap_t *next;
base_command_type_e type; // type for faster searching base_command_type_e type; // type for faster searching
char name[]; // key for searching char name[1]; // key for searching
}; };
static base_command_hashmap_t *hashed_cmds[HASH_SIZE]; static base_command_hashmap_t *hashed_cmds[HASH_SIZE];
static poolhandle_t basecmd_pool;
#define BaseCmd_HashKey( x ) COM_HashKey( name, HASH_SIZE ) #define BaseCmd_HashKey( x ) COM_HashKey( name, HASH_SIZE )
@@ -43,27 +42,11 @@ Find base command in bucket
*/ */
static base_command_hashmap_t *BaseCmd_FindInBucket( base_command_hashmap_t *bucket, base_command_type_e type, const char *name ) static base_command_hashmap_t *BaseCmd_FindInBucket( base_command_hashmap_t *bucket, base_command_type_e type, const char *name )
{ {
base_command_hashmap_t *i; base_command_hashmap_t *i = bucket;
for( ; i && ( i->type != type || Q_stricmp( name, i->name ) ); // filter out
i = i->next );
for( i = bucket; i != NULL; i = i->next ) return i;
{
int cmp;
if( i->type != type )
continue;
cmp = Q_stricmp( i->name, name );
if( cmp < 0 )
continue;
if( cmp > 0 )
break;
return i;
}
return NULL;
} }
/* /*
@@ -107,31 +90,27 @@ void BaseCmd_FindAll( const char *name, base_command_t **cmd, base_command_t **a
base_command_hashmap_t *base = BaseCmd_GetBucket( name ); base_command_hashmap_t *base = BaseCmd_GetBucket( name );
base_command_hashmap_t *i = base; base_command_hashmap_t *i = base;
ASSERT( cmd && alias && cvar );
*cmd = *alias = *cvar = NULL; *cmd = *alias = *cvar = NULL;
for( ; i; i = i->next ) for( ; i; i = i->next )
{ {
int cmp = Q_stricmp( i->name, name ); if( !Q_stricmp( i->name, name ) )
if( cmp < 0 )
continue;
if( cmp > 0 )
break;
switch( i->type )
{ {
case HM_CMD: switch( i->type )
*cmd = i->basecmd; {
break; case HM_CMD:
case HM_CMDALIAS: *cmd = i->basecmd;
*alias = i->basecmd; break;
break; case HM_CMDALIAS:
case HM_CVAR: *alias = i->basecmd;
*cvar = i->basecmd; break;
break; case HM_CVAR:
default: *cvar = i->basecmd;
break; break;
default: break;
}
} }
} }
} }
@@ -149,14 +128,14 @@ void BaseCmd_Insert( base_command_type_e type, base_command_t *basecmd, const ch
uint hash = BaseCmd_HashKey( name ); uint hash = BaseCmd_HashKey( name );
size_t len = Q_strlen( name ); size_t len = Q_strlen( name );
elem = Mem_Malloc( basecmd_pool, sizeof( base_command_hashmap_t ) + len + 1 ); elem = Z_Malloc( sizeof( base_command_hashmap_t ) + len );
elem->basecmd = basecmd; elem->basecmd = basecmd;
elem->type = type; elem->type = type;
Q_strncpy( elem->name, name, len + 1 ); Q_strncpy( elem->name, name, len + 1 );
// link the variable in alphanumerical order // link the variable in alphanumerical order
for( cur = NULL, find = hashed_cmds[hash]; for( cur = NULL, find = hashed_cmds[hash];
find && Q_stricmp( find->name, elem->name ) < 0; find && Q_strcmp( find->name, elem->name ) < 0;
cur = find, find = find->next ); cur = find, find = find->next );
if( cur ) cur->next = elem; if( cur ) cur->next = elem;
@@ -177,23 +156,9 @@ void BaseCmd_Remove( base_command_type_e type, const char *name )
uint hash = BaseCmd_HashKey( name ); uint hash = BaseCmd_HashKey( name );
base_command_hashmap_t *i, *prev; base_command_hashmap_t *i, *prev;
for( prev = NULL, i = hashed_cmds[hash]; i != NULL; prev = i, i = i->next ) for( prev = NULL, i = hashed_cmds[hash]; i &&
{ ( Q_strcmp( i->name, name ) || i->type != type); // filter out
int cmp; prev = i, i = i->next );
if( i->type != type )
continue;
cmp = Q_stricmp( i->name, name );
if( cmp < 0 )
continue;
if( cmp > 0 )
i = NULL;
break;
}
if( !i ) if( !i )
{ {
@@ -218,15 +183,9 @@ initialize base command hashmap system
*/ */
void BaseCmd_Init( void ) void BaseCmd_Init( void )
{ {
basecmd_pool = Mem_AllocPool( "BaseCmd" );
memset( hashed_cmds, 0, sizeof( hashed_cmds ) ); memset( hashed_cmds, 0, sizeof( hashed_cmds ) );
} }
void BaseCmd_Shutdown( void )
{
Mem_FreePool( &basecmd_pool );
}
/* /*
============ ============
BaseCmd_Stats_f BaseCmd_Stats_f

View File

@@ -32,7 +32,6 @@ typedef enum base_command_type
typedef void base_command_t; typedef void base_command_t;
void BaseCmd_Init( void ); void BaseCmd_Init( void );
void BaseCmd_Shutdown( void );
base_command_t *BaseCmd_Find( base_command_type_e type, const char *name ); base_command_t *BaseCmd_Find( base_command_type_e type, const char *name );
void BaseCmd_FindAll( const char *name, void BaseCmd_FindAll( const char *name,
base_command_t **cmd, base_command_t **alias, base_command_t **cvar ); base_command_t **cmd, base_command_t **alias, base_command_t **cvar );

View File

@@ -46,7 +46,6 @@ static cmdalias_t *cmd_alias;
static uint cmd_condition; static uint cmd_condition;
static int cmd_condlevel; static int cmd_condlevel;
static qboolean cmd_currentCommandIsPrivileged; static qboolean cmd_currentCommandIsPrivileged;
static poolhandle_t cmd_pool;
static void Cmd_ExecuteStringWithPrivilegeCheck( const char *text, qboolean isPrivileged ); static void Cmd_ExecuteStringWithPrivilegeCheck( const char *text, qboolean isPrivileged );
@@ -433,7 +432,7 @@ static void Cmd_Alias_f( void )
{ {
if( !Q_strcmp( s, a->name )) if( !Q_strcmp( s, a->name ))
{ {
Mem_Free( a->value ); Z_Free( a->value );
break; break;
} }
} }
@@ -442,7 +441,7 @@ static void Cmd_Alias_f( void )
{ {
cmdalias_t *cur, *prev; cmdalias_t *cur, *prev;
a = Mem_Malloc( cmd_pool, sizeof( cmdalias_t )); a = Z_Malloc( sizeof( cmdalias_t ));
Q_strncpy( a->name, s, sizeof( a->name )); Q_strncpy( a->name, s, sizeof( a->name ));
@@ -470,7 +469,7 @@ static void Cmd_Alias_f( void )
} }
Q_strncat( cmd, "\n", sizeof( cmd )); Q_strncat( cmd, "\n", sizeof( cmd ));
a->value = copystringpool( cmd_pool, cmd ); a->value = copystring( cmd );
} }
/* /*
@@ -530,7 +529,7 @@ struct cmd_s
char *name; char *name;
xcommand_t function; xcommand_t function;
int flags; int flags;
char desc[]; char *desc;
}; };
static int cmd_argc; static int cmd_argc;
@@ -637,7 +636,7 @@ void Cmd_TokenizeString( const char *text )
// clear the args from the last string // clear the args from the last string
for( i = 0; i < cmd_argc; i++ ) for( i = 0; i < cmd_argc; i++ )
Mem_Free( cmd_argv[i] ); Z_Free( cmd_argv[i] );
cmd_argc = 0; // clear previous args cmd_argc = 0; // clear previous args
cmd_args = NULL; cmd_args = NULL;
@@ -671,7 +670,7 @@ void Cmd_TokenizeString( const char *text )
if( cmd_argc < MAX_CMD_TOKENS ) if( cmd_argc < MAX_CMD_TOKENS )
{ {
cmd_argv[cmd_argc] = copystringpool( cmd_pool, cmd_token ); cmd_argv[cmd_argc] = copystring( cmd_token );
cmd_argc++; cmd_argc++;
} }
} }
@@ -684,8 +683,7 @@ Cmd_AddCommandEx
*/ */
int Cmd_AddCommandEx( const char *cmd_name, xcommand_t function, const char *cmd_desc, int iFlags, const char *funcname ) int Cmd_AddCommandEx( const char *cmd_name, xcommand_t function, const char *cmd_desc, int iFlags, const char *funcname )
{ {
cmd_t *cmd, *cur, *prev; cmd_t *cmd, *cur, *prev;
size_t desc_len;
if( !COM_CheckString( cmd_name )) if( !COM_CheckString( cmd_name ))
{ {
@@ -709,8 +707,8 @@ int Cmd_AddCommandEx( const char *cmd_name, xcommand_t function, const char *cmd
// unfortunately, we lose original command this way // unfortunately, we lose original command this way
if( FBitSet( cmd->flags, CMD_OVERRIDABLE )) if( FBitSet( cmd->flags, CMD_OVERRIDABLE ))
{ {
desc_len = Q_strlen( cmd->desc ) + 1; Mem_Free( cmd->desc );
Q_strncpy( cmd->desc, cmd_desc, desc_len ); cmd->desc = copystring( cmd_desc );
cmd->function = function; cmd->function = function;
cmd->flags = iFlags; cmd->flags = iFlags;
@@ -725,10 +723,9 @@ int Cmd_AddCommandEx( const char *cmd_name, xcommand_t function, const char *cmd
} }
// use a small malloc to avoid zone fragmentation // use a small malloc to avoid zone fragmentation
desc_len = Q_strlen( cmd_desc ) + 1; cmd = Z_Malloc( sizeof( cmd_t ) );
cmd = Mem_Malloc( cmd_pool, sizeof( cmd_t ) + desc_len ); cmd->name = copystring( cmd_name );
cmd->name = copystringpool( cmd_pool, cmd_name ); cmd->desc = copystring( cmd_desc );
Q_strncpy( cmd->desc, cmd_desc, desc_len );
cmd->function = function; cmd->function = function;
cmd->flags = iFlags; cmd->flags = iFlags;
@@ -775,6 +772,9 @@ void GAME_EXPORT Cmd_RemoveCommand( const char *cmd_name )
if( cmd->name ) if( cmd->name )
Mem_Free( cmd->name ); Mem_Free( cmd->name );
if( cmd->desc )
Mem_Free( cmd->desc );
Mem_Free( cmd ); Mem_Free( cmd );
return; return;
} }
@@ -1202,6 +1202,7 @@ void Cmd_Unlink( int group )
*prev = cmd->next; *prev = cmd->next;
if( cmd->name ) Mem_Free( cmd->name ); if( cmd->name ) Mem_Free( cmd->name );
if( cmd->desc ) Mem_Free( cmd->desc );
Mem_Free( cmd ); Mem_Free( cmd );
count++; count++;
@@ -1339,7 +1340,6 @@ Cmd_Init
*/ */
void Cmd_Init( void ) void Cmd_Init( void )
{ {
cmd_pool = Mem_AllocPool( "Console Commands" );
cmd_functions = NULL; cmd_functions = NULL;
cmd_condition = 0; cmd_condition = 0;
cmd_alias = NULL; cmd_alias = NULL;
@@ -1366,11 +1366,6 @@ void Cmd_Init( void )
#endif #endif
} }
void Cmd_Shutdown( void )
{
Mem_FreePool( &cmd_pool );
}
#if XASH_ENGINE_TESTS #if XASH_ENGINE_TESTS
#include "tests.h" #include "tests.h"

View File

@@ -108,14 +108,14 @@ typedef enum
#include "com_model.h" #include "com_model.h"
#include "com_strings.h" #include "com_strings.h"
#include "crtlib.h" #include "crtlib.h"
#define FSCALLBACK_OVERRIDE_OPEN
#define FSCALLBACK_OVERRIDE_LOADFILE
#define FSCALLBACK_OVERRIDE_MALLOC_LIKE
#include "fscallback.h"
#include "cvar.h" #include "cvar.h"
#include "con_nprint.h" #include "con_nprint.h"
#include "crclib.h" #include "crclib.h"
#include "ref_api.h" #include "ref_api.h"
#define FSCALLBACK_OVERRIDE_OPEN
#define FSCALLBACK_OVERRIDE_LOADFILE
#define FSCALLBACK_OVERRIDE_MALLOC_LIKE
#include "fscallback.h"
// PERFORMANCE INFO // PERFORMANCE INFO
#define MIN_FPS 20.0f // host minimum fps value for maxfps. #define MIN_FPS 20.0f // host minimum fps value for maxfps.
@@ -146,11 +146,6 @@ typedef enum
#define MAX_STATIC_ENTITIES 32 // static entities that moved on the client when level is spawn #define MAX_STATIC_ENTITIES 32 // static entities that moved on the client when level is spawn
#endif #endif
#define MAX_SERVERINFO_STRING 512 // server handles too many settings. expand to 1024?
#define MAX_PRINT_MSG 8192 // how many symbols can handle single call of Con_Printf or Con_DPrintf
#define MAX_TOKEN 2048 // parse token length
#define MAX_USERMSG_LENGTH 2048 // don't modify it's relies on a client-side definitions
#define GameState (&host.game) #define GameState (&host.game)
#define FORCE_DRAW_VERSION_TIME 5.0 // draw version for 5 seconds #define FORCE_DRAW_VERSION_TIME 5.0 // draw version for 5 seconds
@@ -437,7 +432,6 @@ int Cmd_Argc( void );
const char *Cmd_Args( void ) RETURNS_NONNULL; const char *Cmd_Args( void ) RETURNS_NONNULL;
const char *Cmd_Argv( int arg ) RETURNS_NONNULL; const char *Cmd_Argv( int arg ) RETURNS_NONNULL;
void Cmd_Init( void ); void Cmd_Init( void );
void Cmd_Shutdown( void );
void Cmd_Unlink( int group ); void Cmd_Unlink( int group );
int Cmd_AddCommandEx( const char *cmd_name, xcommand_t function, const char *cmd_desc, int flags, const char *funcname ); int Cmd_AddCommandEx( const char *cmd_name, xcommand_t function, const char *cmd_desc, int flags, const char *funcname );
@@ -519,27 +513,27 @@ typedef enum
typedef struct typedef struct
{ {
size_t size; // for bounds checking word rate; // num samples per second (e.g. 11025 - 11 khz)
byte width; // resolution - bum bits divided by 8 (8 bit is 1, 16 bit is 2)
byte channels; // num channels (1 - mono, 2 - stereo)
uint loopStart; // offset at this point sound will be looping while playing more than only once uint loopStart; // offset at this point sound will be looping while playing more than only once
uint samples; // total samplecount in wav uint samples; // total samplecount in wav
uint type; // compression type uint type; // compression type
uint flags; // misc sound flags uint flags; // misc sound flags
word rate; // num samples per second (e.g. 11025 - 11 khz) byte *buffer; // sound buffer
byte width; // resolution - bum bits divided by 8 (8 bit is 1, 16 bit is 2) size_t size; // for bounds checking
byte channels; // num channels (1 - mono, 2 - stereo)
byte buffer[]; // sound buffer
} wavdata_t; } wavdata_t;
// //
// soundlib // soundlib
// //
typedef struct stream_s stream_t;
void Sound_Init( void ); void Sound_Init( void );
void Sound_Shutdown( void ); void Sound_Shutdown( void );
void FS_FreeSound( wavdata_t *pack ); void FS_FreeSound( wavdata_t *pack );
void FS_FreeStream( stream_t *stream ); void FS_FreeStream( stream_t *stream );
wavdata_t *FS_LoadSound( const char *filename, const byte *buffer, size_t size ) MALLOC_LIKE( FS_FreeSound, 1 ) WARN_UNUSED_RESULT; wavdata_t *FS_LoadSound( const char *filename, const byte *buffer, size_t size ) MALLOC_LIKE( FS_FreeSound, 1 ) WARN_UNUSED_RESULT;
stream_t *FS_OpenStream( const char *filename ) MALLOC_LIKE( FS_FreeStream, 1 ) WARN_UNUSED_RESULT; stream_t *FS_OpenStream( const char *filename ) MALLOC_LIKE( FS_FreeStream, 1 ) WARN_UNUSED_RESULT;
wavdata_t *FS_StreamInfo( stream_t *stream );
int FS_ReadStream( stream_t *stream, int bytes, void *buffer ); int FS_ReadStream( stream_t *stream, int bytes, void *buffer );
int FS_SetStreamPos( stream_t *stream, int newpos ); int FS_SetStreamPos( stream_t *stream, int newpos );
int FS_GetStreamPos( stream_t *stream ); int FS_GetStreamPos( stream_t *stream );
@@ -584,19 +578,11 @@ CLIENT / SERVER SYSTEMS
============================================================== ==============================================================
*/ */
#if !XASH_DEDICATED
void CL_Init( void ); void CL_Init( void );
void CL_Shutdown( void ); void CL_Shutdown( void );
void Host_ClientBegin( void ); void Host_ClientBegin( void );
void Host_ClientFrame( void ); void Host_ClientFrame( void );
int CL_Active( void ); int CL_Active( void );
#else
static inline void CL_Init( void ) { }
static inline void CL_Shutdown( void ) { }
static inline void Host_ClientBegin( void ) { Cbuf_Execute(); }
static inline void Host_ClientFrame( void ) { }
static inline int CL_Active( void ) { return 0; }
#endif
void SV_Init( void ); void SV_Init( void );
void SV_Shutdown( const char *finalmsg ); void SV_Shutdown( const char *finalmsg );
@@ -634,7 +620,6 @@ int pfnNumberOfEntities( void );
int pfnIsInGame( void ); int pfnIsInGame( void );
float pfnTime( void ); float pfnTime( void );
#define copystring( s ) _copystring( host.mempool, s, __FILE__, __LINE__ ) #define copystring( s ) _copystring( host.mempool, s, __FILE__, __LINE__ )
#define copystringpool( pool, s ) _copystring( pool, s, __FILE__, __LINE__ )
#define SV_CopyString( s ) _copystring( svgame.stringspool, s, __FILE__, __LINE__ ) #define SV_CopyString( s ) _copystring( svgame.stringspool, s, __FILE__, __LINE__ )
#define freestring( s ) if( s != NULL ) { Mem_Free( s ); s = NULL; } #define freestring( s ) if( s != NULL ) { Mem_Free( s ); s = NULL; }
char *_copystring( poolhandle_t mempool, const char *s, const char *filename, int fileline ); char *_copystring( poolhandle_t mempool, const char *s, const char *filename, int fileline );
@@ -685,7 +670,6 @@ int CSCR_WriteGameCVars( file_t *cfg, const char *scriptfilename );
// //
// hpak.c // hpak.c
// //
const char *COM_ResourceTypeFromIndex( int index );
void HPAK_Init( void ); void HPAK_Init( void );
qboolean HPAK_GetDataPointer( const char *filename, struct resource_s *pRes, byte **buffer, int *size ); qboolean HPAK_GetDataPointer( const char *filename, struct resource_s *pRes, byte **buffer, int *size );
qboolean HPAK_ResourceForHash( const char *filename, byte *hash, struct resource_s *pRes ); qboolean HPAK_ResourceForHash( const char *filename, byte *hash, struct resource_s *pRes );
@@ -719,32 +703,13 @@ typedef enum connprotocol_e
struct physent_s; struct physent_s;
struct sv_client_s; struct sv_client_s;
typedef struct sizebuf_s sizebuf_t; typedef struct sizebuf_s sizebuf_t;
int SV_GetMaxClients( void );
#if !XASH_DEDICATED
qboolean CL_Initialized( void );
qboolean CL_IsInGame( void ); qboolean CL_IsInGame( void );
qboolean CL_IsInConsole( void ); qboolean CL_IsInConsole( void );
qboolean CL_IsIntermission( void ); qboolean CL_IsIntermission( void );
qboolean CL_DisableVisibility( void ); qboolean CL_Initialized( void );
qboolean CL_IsRecordDemo( void );
qboolean CL_IsPlaybackDemo( void );
qboolean UI_CreditsActive( void );
int CL_GetMaxClients( void );
#else
static inline qboolean CL_Initialized( void ) { return false; }
static inline qboolean CL_IsInGame( void ) { return false; }
static inline qboolean CL_IsInConsole( void ) { return false; }
static inline qboolean CL_IsIntermission( void ) { return false; }
static inline qboolean CL_DisableVisibility( void ) { return false; }
static inline qboolean CL_IsRecordDemo( void ) { return false; }
static inline qboolean CL_IsPlaybackDemo( void ) { return false; }
static inline qboolean UI_CreditsActive( void ) { return false; }
static inline int CL_GetMaxClients( void ) { return SV_GetMaxClients(); }
#endif
char *CL_Userinfo( void ); char *CL_Userinfo( void );
void CL_CharEvent( int key ); void CL_CharEvent( int key );
qboolean CL_DisableVisibility( void );
byte *COM_LoadFile( const char *filename, int usehunk, int *pLength ) MALLOC_LIKE( free, 1 ); byte *COM_LoadFile( const char *filename, int usehunk, int *pLength ) MALLOC_LIKE( free, 1 );
struct cmd_s *Cmd_GetFirstFunctionHandle( void ); struct cmd_s *Cmd_GetFirstFunctionHandle( void );
struct cmd_s *Cmd_GetNextFunctionHandle( struct cmd_s *cmd ); struct cmd_s *Cmd_GetNextFunctionHandle( struct cmd_s *cmd );
@@ -762,7 +727,13 @@ const char *CL_MsgInfo( int cmd );
void SV_DrawDebugTriangles( void ); void SV_DrawDebugTriangles( void );
void SV_DrawOrthoTriangles( void ); void SV_DrawOrthoTriangles( void );
double CL_GetDemoFramerate( void ); double CL_GetDemoFramerate( void );
qboolean UI_CreditsActive( void );
void CL_StopPlayback( void ); void CL_StopPlayback( void );
int CL_GetMaxClients( void );
int SV_GetMaxClients( void );
qboolean CL_IsRecordDemo( void );
qboolean CL_IsTimeDemo( void );
qboolean CL_IsPlaybackDemo( void );
qboolean SV_Initialized( void ); qboolean SV_Initialized( void );
void CL_ProcessFile( qboolean successfully_received, const char *filename ); void CL_ProcessFile( qboolean successfully_received, const char *filename );
int SV_GetSaveComment( const char *savename, char *comment ); int SV_GetSaveComment( const char *savename, char *comment );
@@ -784,6 +755,8 @@ void SCR_Init( void );
void SCR_UpdateScreen( void ); void SCR_UpdateScreen( void );
void SCR_BeginLoadingPlaque( qboolean is_background ); void SCR_BeginLoadingPlaque( qboolean is_background );
void SCR_CheckStartupVids( void ); void SCR_CheckStartupVids( void );
int SCR_GetAudioChunk( char *rawdata, int length );
wavdata_t *SCR_GetMovieInfo( void );
void SCR_Shutdown( void ); void SCR_Shutdown( void );
void Con_Print( const char *txt ); void Con_Print( const char *txt );
void Con_NPrintf( int idx, const char *fmt, ... ) FORMAT_CHECK( 2 ); void Con_NPrintf( int idx, const char *fmt, ... ) FORMAT_CHECK( 2 );
@@ -873,6 +846,13 @@ void V_CheckGamma( void );
void V_CheckGammaEnd( void ); void V_CheckGammaEnd( void );
intptr_t V_GetGammaPtr( int parm ); intptr_t V_GetGammaPtr( int parm );
//
// identification.c
//
void ID_Init( void );
const char *ID_GetMD5( void );
void GAME_EXPORT ID_SetCustomClientID( const char *id );
// //
// masterlist.c // masterlist.c
// //

View File

@@ -19,7 +19,6 @@ GNU General Public License for more details.
#include "eiface.h" // ARRAYSIZE #include "eiface.h" // ARRAYSIZE
static convar_t *cvar_vars = NULL; // head of list static convar_t *cvar_vars = NULL; // head of list
static poolhandle_t cvar_pool;
CVAR_DEFINE_AUTO( cmd_scripting, "0", FCVAR_ARCHIVE|FCVAR_PRIVILEGED, "enable simple condition checking and variable operations" ); CVAR_DEFINE_AUTO( cmd_scripting, "0", FCVAR_ARCHIVE|FCVAR_PRIVILEGED, "enable simple condition checking and variable operations" );
typedef struct cvar_filter_quirks_s typedef struct cvar_filter_quirks_s
@@ -433,7 +432,7 @@ convar_t *Cvar_Get( const char *name, const char *value, int flags, const char *
{ {
// directly set value // directly set value
freestring( var->string ); freestring( var->string );
var->string = copystringpool( cvar_pool, value ); var->string = copystring( value );
var->value = Q_atof( var->string ); var->value = Q_atof( var->string );
SetBits( var->flags, flags ); SetBits( var->flags, flags );
@@ -453,18 +452,18 @@ convar_t *Cvar_Get( const char *name, const char *value, int flags, const char *
Con_Reportf( "%s change description from %s to %s\n", var->name, var->desc, var_desc ); Con_Reportf( "%s change description from %s to %s\n", var->name, var->desc, var_desc );
// update description if needs // update description if needs
freestring( var->desc ); freestring( var->desc );
var->desc = copystringpool( cvar_pool, var_desc ); var->desc = copystring( var_desc );
} }
return var; return var;
} }
// allocate a new cvar // allocate a new cvar
var = Mem_Malloc( cvar_pool, sizeof( *var )); var = Z_Malloc( sizeof( *var ));
var->name = copystringpool( cvar_pool, name ); var->name = copystring( name );
var->string = copystringpool( cvar_pool, value ); var->string = copystring( value );
var->def_string = copystringpool( cvar_pool, value ); var->def_string = copystring( value );
var->desc = copystringpool( cvar_pool, var_desc ); var->desc = copystring( var_desc );
var->value = Q_atof( var->string ); var->value = Q_atof( var->string );
var->flags = flags|FCVAR_ALLOCATED; var->flags = flags|FCVAR_ALLOCATED;
@@ -550,7 +549,7 @@ void Cvar_RegisterVariable( convar_t *var )
if( FBitSet( var->flags, FCVAR_EXTENDED )) if( FBitSet( var->flags, FCVAR_EXTENDED ))
var->def_string = var->string; // just swap pointers var->def_string = var->string; // just swap pointers
var->string = copystringpool( cvar_pool, var->string ); var->string = copystring( var->string );
var->value = Q_atof( var->string ); var->value = Q_atof( var->string );
// find the supposed position in chain (alphanumerical order) // find the supposed position in chain (alphanumerical order)
@@ -680,7 +679,7 @@ static convar_t *Cvar_Set2( const char *var_name, const char *value )
// and finally changed the cvar itself // and finally changed the cvar itself
freestring( var->string ); freestring( var->string );
var->string = copystringpool( cvar_pool, pszValue ); var->string = copystring( pszValue );
var->value = Q_atof( var->string ); var->value = Q_atof( var->string );
// tell engine about changes // tell engine about changes
@@ -739,7 +738,7 @@ void GAME_EXPORT Cvar_DirectSet( convar_t *var, const char *value )
// and finally changed the cvar itself // and finally changed the cvar itself
freestring( var->string ); freestring( var->string );
var->string = copystringpool( cvar_pool, pszValue ); var->string = copystring( pszValue );
var->value = Q_atof( var->string ); var->value = Q_atof( var->string );
// tell engine about changes // tell engine about changes
@@ -782,7 +781,7 @@ void Cvar_FullSet( const char *var_name, const char *value, int flags )
} }
freestring( var->string ); freestring( var->string );
var->string = copystringpool( cvar_pool, value ); var->string = copystring( value );
var->value = Q_atof( var->string ); var->value = Q_atof( var->string );
SetBits( var->flags, flags ); SetBits( var->flags, flags );
@@ -1190,7 +1189,6 @@ static void Cvar_List_f( void )
for( var = cvar_vars; var; var = var->next ) for( var = cvar_vars; var; var = var->next )
{ {
char value[MAX_VA_STRING]; char value[MAX_VA_STRING];
char *p;
if( var->name[0] == '@' ) if( var->name[0] == '@' )
continue; // never shows system cvars continue; // never shows system cvars
@@ -1198,9 +1196,7 @@ static void Cvar_List_f( void )
if( match && !Q_strnicmpext( match, var->name, matchlen )) if( match && !Q_strnicmpext( match, var->name, matchlen ))
continue; continue;
p = Q_strchr( var->string, '^' ); if( Q_colorstr( var->string ))
if( IsColorString( p ))
Q_snprintf( value, sizeof( value ), "\"%s\"", var->string ); Q_snprintf( value, sizeof( value ), "\"%s\"", var->string );
else Q_snprintf( value, sizeof( value ), "\"^2%s^7\"", var->string ); else Q_snprintf( value, sizeof( value ), "\"^2%s^7\"", var->string );
@@ -1261,7 +1257,7 @@ pending_cvar_t *Cvar_PrepareToUnlink( int group )
continue; continue;
namelen = Q_strlen( cv->name ) + 1; namelen = Q_strlen( cv->name ) + 1;
p = Mem_Malloc( cvar_pool, sizeof( *list ) + namelen ); p = Mem_Malloc( host.mempool, sizeof( *list ) + namelen );
p->next = NULL; p->next = NULL;
p->cv_cur = cv; p->cv_cur = cv;
p->cv_next = cv->next; p->cv_next = cv->next;
@@ -1337,7 +1333,6 @@ Reads in all archived cvars
*/ */
void Cvar_Init( void ) void Cvar_Init( void )
{ {
cvar_pool = Mem_AllocPool( "Console Variables" );
cvar_vars = NULL; cvar_vars = NULL;
cvar_active_filter_quirks = NULL; cvar_active_filter_quirks = NULL;
Cvar_RegisterVariable( &cmd_scripting ); Cvar_RegisterVariable( &cmd_scripting );
@@ -1350,11 +1345,6 @@ void Cvar_Init( void )
Cmd_AddCommand( "cvarlist", Cvar_List_f, "display all console variables beginning with the specified prefix" ); Cmd_AddCommand( "cvarlist", Cvar_List_f, "display all console variables beginning with the specified prefix" );
} }
void Cvar_Shutdown( void )
{
Mem_FreePool( &cvar_pool );
}
/* /*
============ ============
Cvar_PostFSInit Cvar_PostFSInit

View File

@@ -30,8 +30,6 @@ typedef struct pending_cvar_s
char cv_name[]; char cv_name[];
} pending_cvar_t; } pending_cvar_t;
typedef void (*setpair_t)( const char *key, const void *value, const void *buffer, void *numpairs );
cvar_t *Cvar_GetList( void ); cvar_t *Cvar_GetList( void );
#define Cvar_FindVar( name ) Cvar_FindVarExt( name, 0 ) #define Cvar_FindVar( name ) Cvar_FindVarExt( name, 0 )
convar_t *Cvar_FindVarExt( const char *var_name, int ignore_group ); convar_t *Cvar_FindVarExt( const char *var_name, int ignore_group );
@@ -54,7 +52,6 @@ void Cvar_Reset( const char *var_name );
void Cvar_SetCheatState( void ); void Cvar_SetCheatState( void );
qboolean Cvar_CommandWithPrivilegeCheck( convar_t *v, qboolean isPrivileged ); qboolean Cvar_CommandWithPrivilegeCheck( convar_t *v, qboolean isPrivileged );
void Cvar_Init( void ); void Cvar_Init( void );
void Cvar_Shutdown( void );
void Cvar_PostFSInit( void ); void Cvar_PostFSInit( void );
void Cvar_Unlink( int group ); void Cvar_Unlink( int group );

View File

@@ -49,6 +49,52 @@ const char *CL_MsgInfo( int cmd )
return sz; return sz;
} }
int GAME_EXPORT CL_Active( void )
{
return false;
}
qboolean CL_Initialized( void )
{
return false;
}
qboolean CL_IsInGame( void )
{
return true; // always active for dedicated servers
}
qboolean CL_IsInConsole( void )
{
return false;
}
qboolean CL_IsIntermission( void )
{
return false;
}
qboolean CL_IsPlaybackDemo( void )
{
return false;
}
qboolean CL_IsRecordDemo( void )
{
return false;
}
qboolean CL_DisableVisibility( void )
{
return false;
}
void CL_Init( void )
{
}
void Key_Init( void ) void Key_Init( void )
{ {
@@ -84,6 +130,16 @@ void CL_WriteMessageHistory( void )
} }
void Host_ClientBegin( void )
{
Cbuf_Execute();
}
void Host_ClientFrame( void )
{
}
void Host_InputFrame( void ) void Host_InputFrame( void )
{ {
} }
@@ -103,6 +159,11 @@ void GAME_EXPORT S_StopSound(int entnum, int channel, const char *soundname)
} }
int GAME_EXPORT CL_GetMaxClients( void )
{
return 0;
}
void IN_TouchInitConfig( void ) void IN_TouchInitConfig( void )
{ {
@@ -113,6 +174,11 @@ void CL_Disconnect( void )
} }
void CL_Shutdown( void )
{
}
void R_ClearStaticEntities( void ) void R_ClearStaticEntities( void )
{ {
@@ -123,6 +189,11 @@ void Host_Credits( void )
} }
qboolean UI_CreditsActive( void )
{
return false;
}
void S_StopBackgroundTrack( void ) void S_StopBackgroundTrack( void )
{ {
@@ -133,6 +204,11 @@ void SCR_BeginLoadingPlaque( qboolean is_background )
} }
int S_GetCurrentDynamicSounds( soundlist_t *pout, int size )
{
return 0;
}
void S_StopAllSounds( qboolean ambient ) void S_StopAllSounds( qboolean ambient )
{ {

View File

@@ -183,23 +183,14 @@ static qboolean FS_DetermineRootDirectory( char *out, size_t size )
#elif XASH_PSVITA #elif XASH_PSVITA
if( PSVita_GetBasePath( out, size )) if( PSVita_GetBasePath( out, size ))
return true; return true;
Sys_Error( "couldn't find %s data directory", XASH_ENGINE_NAME ); Sys_Error( "couldn't find Xash3D data directory" );
return false; return false;
#elif ( XASH_SDL == 2 ) && !XASH_NSWITCH // GetBasePath not impl'd in switch-sdl2 #elif ( XASH_SDL == 2 ) && !XASH_NSWITCH // GetBasePath not impl'd in switch-sdl2
path = SDL_GetBasePath(); path = SDL_GetBasePath();
#if XASH_APPLE
if( path != NULL && Q_stristr( path, ".app" ))
{
SDL_free((void *)path );
path = SDL_GetPrefPath( NULL, XASH_ENGINE_NAME );
}
#endif
if( path != NULL ) if( path != NULL )
{ {
Q_strncpy( out, path, size ); Q_strncpy( out, path, size );
SDL_free((void *)path ); SDL_free(( void *)path );
return true; return true;
} }

View File

@@ -1131,7 +1131,7 @@ static void Host_InitCommon( int argc, char **argv, const char *progname, qboole
#if XASH_DEDICATED #if XASH_DEDICATED
Platform_SetupSigtermHandling(); Platform_SetupSigtermHandling();
#endif #endif
Platform_Init( Host_IsDedicated( ) || developer >= DEV_EXTENDED, basedir ); Platform_Init( Host_IsDedicated( ) || developer >= DEV_EXTENDED );
FS_Init( basedir ); FS_Init( basedir );
Sys_InitLog(); Sys_InitLog();
@@ -1256,6 +1256,7 @@ int EXPORT Host_Main( int argc, char **argv, const char *progname, int bChangeGa
CL_Init(); CL_Init();
HTTP_Init(); HTTP_Init();
ID_Init();
SoundList_Init(); SoundList_Init();
if( Host_IsDedicated( )) if( Host_IsDedicated( ))
@@ -1399,10 +1400,6 @@ void Host_ShutdownWithReason( const char *reason )
Host_FreeCommon(); Host_FreeCommon();
Platform_Shutdown(); Platform_Shutdown();
BaseCmd_Shutdown();
Cmd_Shutdown();
Cvar_Shutdown();
// must be last, console uses this // must be last, console uses this
Mem_FreePool( &host.mempool ); Mem_FreePool( &host.mempool );

View File

@@ -38,7 +38,7 @@ static void HPAK_MaxSize_f( void )
Con_Printf( S_ERROR "hpk_maxsize is deprecated, use hpk_max_size\n" ); Con_Printf( S_ERROR "hpk_maxsize is deprecated, use hpk_max_size\n" );
} }
const char *COM_ResourceTypeFromIndex( int type ) static const char *HPAK_TypeFromIndex( int type )
{ {
switch( type ) switch( type )
{ {
@@ -104,7 +104,7 @@ static void HPAK_CreatePak( const char *filename, resource_t *pResource, byte *p
string pakname; string pakname;
byte md5[16]; byte md5[16];
file_t *fout; file_t *fout;
MD5Context_t ctx = { 0 }; MD5Context_t ctx;
if( !COM_CheckString( filename )) if( !COM_CheckString( filename ))
return; return;
@@ -125,6 +125,7 @@ static void HPAK_CreatePak( const char *filename, resource_t *pResource, byte *p
} }
// let's hash it. // let's hash it.
memset( &ctx, 0, sizeof( MD5Context_t ));
MD5Init( &ctx ); MD5Init( &ctx );
if( pData == NULL ) if( pData == NULL )
@@ -213,7 +214,7 @@ void HPAK_AddLump( qboolean bUseQueue, const char *name, resource_t *pResource,
file_t *file_src; file_t *file_src;
file_t *file_dst; file_t *file_dst;
byte md5[16]; byte md5[16];
MD5Context_t ctx = { 0 }; MD5Context_t ctx;
if( pData == NULL && pFile == NULL ) if( pData == NULL && pFile == NULL )
return; return;
@@ -225,6 +226,7 @@ void HPAK_AddLump( qboolean bUseQueue, const char *name, resource_t *pResource,
} }
// hash it // hash it
memset( &ctx, 0, sizeof( MD5Context_t ));
MD5Init( &ctx ); MD5Init( &ctx );
if( !pData ) if( !pData )
@@ -461,7 +463,7 @@ static qboolean HPAK_Validate( const char *filename, qboolean quiet, qboolean de
if( !quiet ) if( !quiet )
{ {
Con_Printf( "%i: %s %s %s: ", i, COM_ResourceTypeFromIndex( pRes->type ), Con_Printf( "%i: %s %s %s: ", i, HPAK_TypeFromIndex( pRes->type ),
Q_pretifymem( pRes->nDownloadSize, 2 ), pRes->szFileName ); Q_pretifymem( pRes->nDownloadSize, 2 ), pRes->szFileName );
} }
@@ -942,7 +944,7 @@ static void HPAK_List_f( void )
{ {
entry = &directory.entries[nCurrent]; entry = &directory.entries[nCurrent];
COM_FileBase( entry->resource.szFileName, lumpname, sizeof( lumpname )); COM_FileBase( entry->resource.szFileName, lumpname, sizeof( lumpname ));
type = COM_ResourceTypeFromIndex( entry->resource.type ); type = HPAK_TypeFromIndex( entry->resource.type );
size = Q_memprint( entry->resource.nDownloadSize ); size = Q_memprint( entry->resource.nDownloadSize );
Con_Printf( "%i: %10s %s %s\n : %s\n", nCurrent + 1, type, size, lumpname, MD5_Print( entry->resource.rgucMD5_hash )); Con_Printf( "%i: %10s %s %s\n : %s\n", nCurrent + 1, type, size, lumpname, MD5_Print( entry->resource.rgucMD5_hash ));
@@ -1037,7 +1039,7 @@ static void HPAK_Extract_f( void )
continue; continue;
COM_FileBase( entry->resource.szFileName, lumpname, sizeof( lumpname ) ); COM_FileBase( entry->resource.szFileName, lumpname, sizeof( lumpname ) );
type = COM_ResourceTypeFromIndex( entry->resource.type ); type = HPAK_TypeFromIndex( entry->resource.type );
size = Q_memprint( entry->resource.nDownloadSize ); size = Q_memprint( entry->resource.nDownloadSize );
Con_Printf( "Extracting %i: %10s %s %s\n", nCurrent + 1, type, size, lumpname ); Con_Printf( "Extracting %i: %10s %s %s\n", nCurrent + 1, type, size, lumpname );

View File

@@ -611,7 +611,7 @@ void GAME_EXPORT ID_SetCustomClientID( const char *id )
void ID_Init( void ) void ID_Init( void )
{ {
MD5Context_t hash = { 0 }; MD5Context_t hash = {0};
byte md5[16]; byte md5[16];
int i; int i;
@@ -632,7 +632,7 @@ void ID_Init( void )
#elif XASH_WIN32 #elif XASH_WIN32
{ {
CHAR szBuf[MAX_PATH]; CHAR szBuf[MAX_PATH];
ID_GetKeyData( HKEY_CURRENT_USER, "Software\\"XASH_ENGINE_NAME"\\", "xash_id", szBuf, MAX_PATH ); ID_GetKeyData( HKEY_CURRENT_USER, "Software\\Xash3D\\", "xash_id", szBuf, MAX_PATH );
sscanf(szBuf, "%016"PRIX64, &id); sscanf(szBuf, "%016"PRIX64, &id);
id ^= SYSTEM_XOR_MASK; id ^= SYSTEM_XOR_MASK;
@@ -686,7 +686,7 @@ void ID_Init( void )
{ {
CHAR Buf[MAX_PATH]; CHAR Buf[MAX_PATH];
sprintf( Buf, "%016"PRIX64, id^SYSTEM_XOR_MASK ); sprintf( Buf, "%016"PRIX64, id^SYSTEM_XOR_MASK );
ID_SetKeyData( HKEY_CURRENT_USER, "Software\\"XASH_ENGINE_NAME"\\", REG_SZ, "xash_id", Buf, Q_strlen(Buf) ); ID_SetKeyData( HKEY_CURRENT_USER, "Software\\Xash3D\\", REG_SZ, "xash_id", Buf, Q_strlen(Buf) );
} }
#else #else
{ {

View File

@@ -28,20 +28,12 @@ Image_LoadPAL
qboolean Image_LoadPAL( const char *name, const byte *buffer, fs_offset_t filesize ) qboolean Image_LoadPAL( const char *name, const byte *buffer, fs_offset_t filesize )
{ {
int rendermode = LUMP_NORMAL; int rendermode = LUMP_NORMAL;
byte pal[768];
if( filesize > sizeof( pal )) if( filesize != 768 )
{ {
Con_DPrintf( S_ERROR "%s: (%s) have invalid size (%li should be less or equal than %d)\n", __func__, name, (long)filesize, sizeof( pal )); Con_DPrintf( S_ERROR "%s: (%s) have invalid size (%li should be %d)\n", __func__, name, (long)filesize, 768 );
return false; return false;
} }
else if( filesize < sizeof( pal ) && buffer != NULL )
{
// palette might be truncated, fill it with zeros
memset( pal, 0, sizeof( pal ));
memcpy( pal, buffer, filesize );
buffer = pal;
}
if( name[0] == '#' ) if( name[0] == '#' )
{ {

View File

@@ -482,7 +482,7 @@ static int Mod_LoadTextureFromWadList( wadlist_t *list, const char *name, rgbdat
return -1; return -1;
} }
static fs_offset_t Mod_CalculateMipTexSize( const mip_t *mt, qboolean palette ) static fs_offset_t Mod_CalculateMipTexSize( mip_t *mt, qboolean palette )
{ {
if( !mt ) if( !mt )
return 0; return 0;
@@ -2359,7 +2359,7 @@ static qboolean Mod_SearchForTextureReplacement( char *out, size_t size, const c
return false; return false;
} }
static void Mod_InitSkyClouds( model_t *mod, const mip_t *mt, texture_t *tx, qboolean custom_palette ) static void Mod_InitSkyClouds( model_t *mod, mip_t *mt, texture_t *tx, qboolean custom_palette )
{ {
#if !XASH_DEDICATED #if !XASH_DEDICATED
rgbdata_t r_temp, *r_sky; rgbdata_t r_temp, *r_sky;
@@ -2516,6 +2516,9 @@ done:
static void Mod_LoadTextureData( model_t *mod, dbspmodel_t *bmod, int textureIndex ) static void Mod_LoadTextureData( model_t *mod, dbspmodel_t *bmod, int textureIndex )
{ {
texture_t *texture = NULL;
mip_t *mipTex = NULL;
qboolean usesCustomPalette = false;
uint32_t txFlags = 0; uint32_t txFlags = 0;
char texpath[MAX_VA_STRING]; char texpath[MAX_VA_STRING];
char safemtname[16]; // only for external textures char safemtname[16]; // only for external textures
@@ -2523,10 +2526,12 @@ static void Mod_LoadTextureData( model_t *mod, dbspmodel_t *bmod, int textureInd
// don't load texture data on dedicated server, as there is no renderer. // don't load texture data on dedicated server, as there is no renderer.
// but count the wadusage for automatic precache // but count the wadusage for automatic precache
texture_t *texture = mod->textures[textureIndex]; //
const mip_t *mipTex = Mod_GetMipTexForTexture( bmod, textureIndex ); // FIXME: for ENGINE_IMPROVED_LINETRACE we need to load textures on server too
const qboolean usesCustomPalette = Mod_CalcMipTexUsesCustomPalette( mod, bmod, textureIndex ); // but there is no facility for this yet
const qboolean iswater = Mod_LooksLikeWaterTexture( mipTex->name ); texture = mod->textures[textureIndex];
mipTex = Mod_GetMipTexForTexture( bmod, textureIndex );
usesCustomPalette = Mod_CalcMipTexUsesCustomPalette( mod, bmod, textureIndex );
// check for multi-layered sky texture (quake1 specific) // check for multi-layered sky texture (quake1 specific)
if( bmod->isworld && Q_strncmp( mipTex->name, "sky", 3 ) == 0 && ( mipTex->width / mipTex->height ) == 2 ) if( bmod->isworld && Q_strncmp( mipTex->name, "sky", 3 ) == 0 && ( mipTex->width / mipTex->height ) == 2 )
@@ -2535,13 +2540,11 @@ static void Mod_LoadTextureData( model_t *mod, dbspmodel_t *bmod, int textureInd
return; return;
} }
// FIXME: for ENGINE_IMPROVED_LINETRACE we need to load textures on server too
// but there is no facility for this yet
if( FBitSet( host.features, ENGINE_IMPROVED_LINETRACE ) && mipTex->name[0] == '{' ) if( FBitSet( host.features, ENGINE_IMPROVED_LINETRACE ) && mipTex->name[0] == '{' )
SetBits( txFlags, TF_KEEP_SOURCE ); // Paranoia2 texture alpha-tracing SetBits( txFlags, TF_KEEP_SOURCE ); // Paranoia2 texture alpha-tracing
// check if this is water to keep the source texture and expand it to RGBA (so ripple effect works) // check if this is water to keep the source texture and expand it to RGBA (so ripple effect works)
if( iswater ) if( Mod_LooksLikeWaterTexture( mipTex->name ))
SetBits( txFlags, TF_KEEP_SOURCE | TF_EXPAND_SOURCE ); SetBits( txFlags, TF_KEEP_SOURCE | TF_EXPAND_SOURCE );
// Texture loading order: // Texture loading order:
@@ -2606,13 +2609,8 @@ static void Mod_LoadTextureData( model_t *mod, dbspmodel_t *bmod, int textureInd
texture->gl_texturenum = R_GetBuiltinTexture( REF_DEFAULT_TEXTURE ); texture->gl_texturenum = R_GetBuiltinTexture( REF_DEFAULT_TEXTURE );
} }
texture->fb_texturenum = 0;
// Check for luma texture // Check for luma texture
// a1ba: ignore for water because fb_texturenum will be used to store ripple texture texture->fb_texturenum = 0;
if( iswater )
return;
if( load_external ) // external textures will not have TF_HAS_LUMA flag because it set only from WAD images loader if( load_external ) // external textures will not have TF_HAS_LUMA flag because it set only from WAD images loader
{ {
if( Mod_SearchForTextureReplacement( texpath, sizeof( texpath ), mod->name, safemtname, "_luma" )) if( Mod_SearchForTextureReplacement( texpath, sizeof( texpath ), mod->name, safemtname, "_luma" ))

View File

@@ -868,7 +868,7 @@ void Mod_LoadStudioModel( model_t *mod, const void *buffer, qboolean *loaded )
mod->type = mod_studio; mod->type = mod_studio;
phdr = R_StudioLoadHeader( mod, buffer ); phdr = R_StudioLoadHeader( mod, buffer );
if( !phdr || phdr->length < sizeof( studiohdr_t )) // garbage value in length if( !phdr )
return; // bad model return; // bad model
#if !XASH_DEDICATED #if !XASH_DEDICATED

View File

@@ -258,7 +258,7 @@ model_t *Mod_LoadModel( model_t *mod, qboolean crash )
{ {
char tempname[MAX_QPATH]; char tempname[MAX_QPATH];
fs_offset_t length = 0; fs_offset_t length = 0;
qboolean loaded, loaded2 = false; qboolean loaded;
byte *buf; byte *buf;
model_info_t *p; model_info_t *p;
@@ -279,7 +279,7 @@ model_t *Mod_LoadModel( model_t *mod, qboolean crash )
buf = FS_LoadFile( tempname, &length, false ); buf = FS_LoadFile( tempname, &length, false );
if( !buf || length < sizeof( uint )) if( !buf )
{ {
memset( mod, 0, sizeof( model_t )); memset( mod, 0, sizeof( model_t ));
@@ -329,12 +329,11 @@ model_t *Mod_LoadModel( model_t *mod, qboolean crash )
// let the server.dll load custom data // let the server.dll load custom data
svgame.physFuncs.Mod_ProcessUserData( mod, true, buf ); svgame.physFuncs.Mod_ProcessUserData( mod, true, buf );
} }
loaded2 = true;
} }
#if !XASH_DEDICATED #if !XASH_DEDICATED
else else
{ {
loaded2 = ref.dllFuncs.Mod_ProcessRenderData( mod, true, buf ); loaded = ref.dllFuncs.Mod_ProcessRenderData( mod, true, buf );
} }
#endif #endif
} }
@@ -346,7 +345,7 @@ model_t *Mod_LoadModel( model_t *mod, qboolean crash )
hdr->pposeverts = NULL; hdr->pposeverts = NULL;
} }
if( !loaded || !loaded2 ) if( !loaded )
{ {
Mod_FreeModel( mod ); Mod_FreeModel( mod );
Mem_Free( buf ); Mem_Free( buf );
@@ -611,41 +610,3 @@ void Mod_NeedCRC( const char *name, qboolean needCRC )
if( needCRC ) SetBits( p->flags, FCRC_SHOULD_CHECKSUM ); if( needCRC ) SetBits( p->flags, FCRC_SHOULD_CHECKSUM );
else ClearBits( p->flags, FCRC_SHOULD_CHECKSUM ); else ClearBits( p->flags, FCRC_SHOULD_CHECKSUM );
} }
#if XASH_ENGINE_TESTS
static const uint8_t *fuzz_data;
static size_t fuzz_size;
static byte *Fuzz_LoadFile( const char *path, fs_offset_t *filesizeptr, qboolean gamedironly )
{
byte *buf = Mem_Malloc( host.mempool, fuzz_size );
memcpy( buf, fuzz_data, fuzz_size );
*filesizeptr = fuzz_size;
return buf;
}
int EXPORT Fuzz_Mod_LoadModel( const uint8_t *Data, size_t Size );
int EXPORT Fuzz_Mod_LoadModel( const uint8_t *Data, size_t Size )
{
model_t mod = { .name = "test", .needload = NL_NEEDS_LOADED };
Memory_Init();
host.type = HOST_DEDICATED;
host.mempool = Mem_AllocPool( "fuzzing pool" );
fuzz_data = Data;
fuzz_size = Size;
refState.draw_surfaces = NULL;
g_fsapi.LoadFile = Fuzz_LoadFile;
if( Mod_LoadModel( &mod, false ) && mod.mempool )
Mem_FreePool( &mod.mempool );
Mem_FreePool( &host.mempool );
return 0;
}
#endif // XASH_ENGINE_TESTS

View File

@@ -18,177 +18,11 @@ GNU General Public License for more details.
#include "net_buffer.h" #include "net_buffer.h"
#include "xash3d_mathlib.h" #include "xash3d_mathlib.h"
static const uint32_t BitWriteMasks[32][32] = // precalculated bit masks for WriteUBitLong.
{ { // Using these tables instead of doing the calculations
0xfffffffe, 0xfffffffc, 0xfffffff8, 0xfffffff0, 0xffffffe0, 0xffffffc0, 0xffffff80, 0xffffff00, // gives a 33% speedup in WriteUBitLong.
0xfffffe00, 0xfffffc00, 0xfffff800, 0xfffff000, 0xffffe000, 0xffffc000, 0xffff8000, 0xffff0000, static uint32_t BitWriteMasks[32][33];
0xfffe0000, 0xfffc0000, 0xfff80000, 0xfff00000, 0xffe00000, 0xffc00000, 0xff800000, 0xff000000, static uint32_t ExtraMasks[32];
0xfe000000, 0xfc000000, 0xf8000000, 0xf0000000, 0xe0000000, 0xc0000000, 0x80000000, 0x00000000,
}, {
0xfffffffd, 0xfffffff9, 0xfffffff1, 0xffffffe1, 0xffffffc1, 0xffffff81, 0xffffff01, 0xfffffe01,
0xfffffc01, 0xfffff801, 0xfffff001, 0xffffe001, 0xffffc001, 0xffff8001, 0xffff0001, 0xfffe0001,
0xfffc0001, 0xfff80001, 0xfff00001, 0xffe00001, 0xffc00001, 0xff800001, 0xff000001, 0xfe000001,
0xfc000001, 0xf8000001, 0xf0000001, 0xe0000001, 0xc0000001, 0x80000001, 0x00000001, 0x00000001,
}, {
0xfffffffb, 0xfffffff3, 0xffffffe3, 0xffffffc3, 0xffffff83, 0xffffff03, 0xfffffe03, 0xfffffc03,
0xfffff803, 0xfffff003, 0xffffe003, 0xffffc003, 0xffff8003, 0xffff0003, 0xfffe0003, 0xfffc0003,
0xfff80003, 0xfff00003, 0xffe00003, 0xffc00003, 0xff800003, 0xff000003, 0xfe000003, 0xfc000003,
0xf8000003, 0xf0000003, 0xe0000003, 0xc0000003, 0x80000003, 0x00000003, 0x00000003, 0x00000003,
}, {
0xfffffff7, 0xffffffe7, 0xffffffc7, 0xffffff87, 0xffffff07, 0xfffffe07, 0xfffffc07, 0xfffff807,
0xfffff007, 0xffffe007, 0xffffc007, 0xffff8007, 0xffff0007, 0xfffe0007, 0xfffc0007, 0xfff80007,
0xfff00007, 0xffe00007, 0xffc00007, 0xff800007, 0xff000007, 0xfe000007, 0xfc000007, 0xf8000007,
0xf0000007, 0xe0000007, 0xc0000007, 0x80000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007,
}, {
0xffffffef, 0xffffffcf, 0xffffff8f, 0xffffff0f, 0xfffffe0f, 0xfffffc0f, 0xfffff80f, 0xfffff00f,
0xffffe00f, 0xffffc00f, 0xffff800f, 0xffff000f, 0xfffe000f, 0xfffc000f, 0xfff8000f, 0xfff0000f,
0xffe0000f, 0xffc0000f, 0xff80000f, 0xff00000f, 0xfe00000f, 0xfc00000f, 0xf800000f, 0xf000000f,
0xe000000f, 0xc000000f, 0x8000000f, 0x0000000f, 0x0000000f, 0x0000000f, 0x0000000f, 0x0000000f,
}, {
0xffffffdf, 0xffffff9f, 0xffffff1f, 0xfffffe1f, 0xfffffc1f, 0xfffff81f, 0xfffff01f, 0xffffe01f,
0xffffc01f, 0xffff801f, 0xffff001f, 0xfffe001f, 0xfffc001f, 0xfff8001f, 0xfff0001f, 0xffe0001f,
0xffc0001f, 0xff80001f, 0xff00001f, 0xfe00001f, 0xfc00001f, 0xf800001f, 0xf000001f, 0xe000001f,
0xc000001f, 0x8000001f, 0x0000001f, 0x0000001f, 0x0000001f, 0x0000001f, 0x0000001f, 0x0000001f,
}, {
0xffffffbf, 0xffffff3f, 0xfffffe3f, 0xfffffc3f, 0xfffff83f, 0xfffff03f, 0xffffe03f, 0xffffc03f,
0xffff803f, 0xffff003f, 0xfffe003f, 0xfffc003f, 0xfff8003f, 0xfff0003f, 0xffe0003f, 0xffc0003f,
0xff80003f, 0xff00003f, 0xfe00003f, 0xfc00003f, 0xf800003f, 0xf000003f, 0xe000003f, 0xc000003f,
0x8000003f, 0x0000003f, 0x0000003f, 0x0000003f, 0x0000003f, 0x0000003f, 0x0000003f, 0x0000003f,
}, {
0xffffff7f, 0xfffffe7f, 0xfffffc7f, 0xfffff87f, 0xfffff07f, 0xffffe07f, 0xffffc07f, 0xffff807f,
0xffff007f, 0xfffe007f, 0xfffc007f, 0xfff8007f, 0xfff0007f, 0xffe0007f, 0xffc0007f, 0xff80007f,
0xff00007f, 0xfe00007f, 0xfc00007f, 0xf800007f, 0xf000007f, 0xe000007f, 0xc000007f, 0x8000007f,
0x0000007f, 0x0000007f, 0x0000007f, 0x0000007f, 0x0000007f, 0x0000007f, 0x0000007f, 0x0000007f,
}, {
0xfffffeff, 0xfffffcff, 0xfffff8ff, 0xfffff0ff, 0xffffe0ff, 0xffffc0ff, 0xffff80ff, 0xffff00ff,
0xfffe00ff, 0xfffc00ff, 0xfff800ff, 0xfff000ff, 0xffe000ff, 0xffc000ff, 0xff8000ff, 0xff0000ff,
0xfe0000ff, 0xfc0000ff, 0xf80000ff, 0xf00000ff, 0xe00000ff, 0xc00000ff, 0x800000ff, 0x000000ff,
0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff,
}, {
0xfffffdff, 0xfffff9ff, 0xfffff1ff, 0xffffe1ff, 0xffffc1ff, 0xffff81ff, 0xffff01ff, 0xfffe01ff,
0xfffc01ff, 0xfff801ff, 0xfff001ff, 0xffe001ff, 0xffc001ff, 0xff8001ff, 0xff0001ff, 0xfe0001ff,
0xfc0001ff, 0xf80001ff, 0xf00001ff, 0xe00001ff, 0xc00001ff, 0x800001ff, 0x000001ff, 0x000001ff,
0x000001ff, 0x000001ff, 0x000001ff, 0x000001ff, 0x000001ff, 0x000001ff, 0x000001ff, 0x000001ff,
}, {
0xfffffbff, 0xfffff3ff, 0xffffe3ff, 0xffffc3ff, 0xffff83ff, 0xffff03ff, 0xfffe03ff, 0xfffc03ff,
0xfff803ff, 0xfff003ff, 0xffe003ff, 0xffc003ff, 0xff8003ff, 0xff0003ff, 0xfe0003ff, 0xfc0003ff,
0xf80003ff, 0xf00003ff, 0xe00003ff, 0xc00003ff, 0x800003ff, 0x000003ff, 0x000003ff, 0x000003ff,
0x000003ff, 0x000003ff, 0x000003ff, 0x000003ff, 0x000003ff, 0x000003ff, 0x000003ff, 0x000003ff,
}, {
0xfffff7ff, 0xffffe7ff, 0xffffc7ff, 0xffff87ff, 0xffff07ff, 0xfffe07ff, 0xfffc07ff, 0xfff807ff,
0xfff007ff, 0xffe007ff, 0xffc007ff, 0xff8007ff, 0xff0007ff, 0xfe0007ff, 0xfc0007ff, 0xf80007ff,
0xf00007ff, 0xe00007ff, 0xc00007ff, 0x800007ff, 0x000007ff, 0x000007ff, 0x000007ff, 0x000007ff,
0x000007ff, 0x000007ff, 0x000007ff, 0x000007ff, 0x000007ff, 0x000007ff, 0x000007ff, 0x000007ff,
}, {
0xffffefff, 0xffffcfff, 0xffff8fff, 0xffff0fff, 0xfffe0fff, 0xfffc0fff, 0xfff80fff, 0xfff00fff,
0xffe00fff, 0xffc00fff, 0xff800fff, 0xff000fff, 0xfe000fff, 0xfc000fff, 0xf8000fff, 0xf0000fff,
0xe0000fff, 0xc0000fff, 0x80000fff, 0x00000fff, 0x00000fff, 0x00000fff, 0x00000fff, 0x00000fff,
0x00000fff, 0x00000fff, 0x00000fff, 0x00000fff, 0x00000fff, 0x00000fff, 0x00000fff, 0x00000fff,
}, {
0xffffdfff, 0xffff9fff, 0xffff1fff, 0xfffe1fff, 0xfffc1fff, 0xfff81fff, 0xfff01fff, 0xffe01fff,
0xffc01fff, 0xff801fff, 0xff001fff, 0xfe001fff, 0xfc001fff, 0xf8001fff, 0xf0001fff, 0xe0001fff,
0xc0001fff, 0x80001fff, 0x00001fff, 0x00001fff, 0x00001fff, 0x00001fff, 0x00001fff, 0x00001fff,
0x00001fff, 0x00001fff, 0x00001fff, 0x00001fff, 0x00001fff, 0x00001fff, 0x00001fff, 0x00001fff,
}, {
0xffffbfff, 0xffff3fff, 0xfffe3fff, 0xfffc3fff, 0xfff83fff, 0xfff03fff, 0xffe03fff, 0xffc03fff,
0xff803fff, 0xff003fff, 0xfe003fff, 0xfc003fff, 0xf8003fff, 0xf0003fff, 0xe0003fff, 0xc0003fff,
0x80003fff, 0x00003fff, 0x00003fff, 0x00003fff, 0x00003fff, 0x00003fff, 0x00003fff, 0x00003fff,
0x00003fff, 0x00003fff, 0x00003fff, 0x00003fff, 0x00003fff, 0x00003fff, 0x00003fff, 0x00003fff,
}, {
0xffff7fff, 0xfffe7fff, 0xfffc7fff, 0xfff87fff, 0xfff07fff, 0xffe07fff, 0xffc07fff, 0xff807fff,
0xff007fff, 0xfe007fff, 0xfc007fff, 0xf8007fff, 0xf0007fff, 0xe0007fff, 0xc0007fff, 0x80007fff,
0x00007fff, 0x00007fff, 0x00007fff, 0x00007fff, 0x00007fff, 0x00007fff, 0x00007fff, 0x00007fff,
0x00007fff, 0x00007fff, 0x00007fff, 0x00007fff, 0x00007fff, 0x00007fff, 0x00007fff, 0x00007fff,
}, {
0xfffeffff, 0xfffcffff, 0xfff8ffff, 0xfff0ffff, 0xffe0ffff, 0xffc0ffff, 0xff80ffff, 0xff00ffff,
0xfe00ffff, 0xfc00ffff, 0xf800ffff, 0xf000ffff, 0xe000ffff, 0xc000ffff, 0x8000ffff, 0x0000ffff,
0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff,
0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff,
}, {
0xfffdffff, 0xfff9ffff, 0xfff1ffff, 0xffe1ffff, 0xffc1ffff, 0xff81ffff, 0xff01ffff, 0xfe01ffff,
0xfc01ffff, 0xf801ffff, 0xf001ffff, 0xe001ffff, 0xc001ffff, 0x8001ffff, 0x0001ffff, 0x0001ffff,
0x0001ffff, 0x0001ffff, 0x0001ffff, 0x0001ffff, 0x0001ffff, 0x0001ffff, 0x0001ffff, 0x0001ffff,
0x0001ffff, 0x0001ffff, 0x0001ffff, 0x0001ffff, 0x0001ffff, 0x0001ffff, 0x0001ffff, 0x0001ffff,
}, {
0xfffbffff, 0xfff3ffff, 0xffe3ffff, 0xffc3ffff, 0xff83ffff, 0xff03ffff, 0xfe03ffff, 0xfc03ffff,
0xf803ffff, 0xf003ffff, 0xe003ffff, 0xc003ffff, 0x8003ffff, 0x0003ffff, 0x0003ffff, 0x0003ffff,
0x0003ffff, 0x0003ffff, 0x0003ffff, 0x0003ffff, 0x0003ffff, 0x0003ffff, 0x0003ffff, 0x0003ffff,
0x0003ffff, 0x0003ffff, 0x0003ffff, 0x0003ffff, 0x0003ffff, 0x0003ffff, 0x0003ffff, 0x0003ffff,
}, {
0xfff7ffff, 0xffe7ffff, 0xffc7ffff, 0xff87ffff, 0xff07ffff, 0xfe07ffff, 0xfc07ffff, 0xf807ffff,
0xf007ffff, 0xe007ffff, 0xc007ffff, 0x8007ffff, 0x0007ffff, 0x0007ffff, 0x0007ffff, 0x0007ffff,
0x0007ffff, 0x0007ffff, 0x0007ffff, 0x0007ffff, 0x0007ffff, 0x0007ffff, 0x0007ffff, 0x0007ffff,
0x0007ffff, 0x0007ffff, 0x0007ffff, 0x0007ffff, 0x0007ffff, 0x0007ffff, 0x0007ffff, 0x0007ffff,
}, {
0xffefffff, 0xffcfffff, 0xff8fffff, 0xff0fffff, 0xfe0fffff, 0xfc0fffff, 0xf80fffff, 0xf00fffff,
0xe00fffff, 0xc00fffff, 0x800fffff, 0x000fffff, 0x000fffff, 0x000fffff, 0x000fffff, 0x000fffff,
0x000fffff, 0x000fffff, 0x000fffff, 0x000fffff, 0x000fffff, 0x000fffff, 0x000fffff, 0x000fffff,
0x000fffff, 0x000fffff, 0x000fffff, 0x000fffff, 0x000fffff, 0x000fffff, 0x000fffff, 0x000fffff,
}, {
0xffdfffff, 0xff9fffff, 0xff1fffff, 0xfe1fffff, 0xfc1fffff, 0xf81fffff, 0xf01fffff, 0xe01fffff,
0xc01fffff, 0x801fffff, 0x001fffff, 0x001fffff, 0x001fffff, 0x001fffff, 0x001fffff, 0x001fffff,
0x001fffff, 0x001fffff, 0x001fffff, 0x001fffff, 0x001fffff, 0x001fffff, 0x001fffff, 0x001fffff,
0x001fffff, 0x001fffff, 0x001fffff, 0x001fffff, 0x001fffff, 0x001fffff, 0x001fffff, 0x001fffff,
}, {
0xffbfffff, 0xff3fffff, 0xfe3fffff, 0xfc3fffff, 0xf83fffff, 0xf03fffff, 0xe03fffff, 0xc03fffff,
0x803fffff, 0x003fffff, 0x003fffff, 0x003fffff, 0x003fffff, 0x003fffff, 0x003fffff, 0x003fffff,
0x003fffff, 0x003fffff, 0x003fffff, 0x003fffff, 0x003fffff, 0x003fffff, 0x003fffff, 0x003fffff,
0x003fffff, 0x003fffff, 0x003fffff, 0x003fffff, 0x003fffff, 0x003fffff, 0x003fffff, 0x003fffff,
}, {
0xff7fffff, 0xfe7fffff, 0xfc7fffff, 0xf87fffff, 0xf07fffff, 0xe07fffff, 0xc07fffff, 0x807fffff,
0x007fffff, 0x007fffff, 0x007fffff, 0x007fffff, 0x007fffff, 0x007fffff, 0x007fffff, 0x007fffff,
0x007fffff, 0x007fffff, 0x007fffff, 0x007fffff, 0x007fffff, 0x007fffff, 0x007fffff, 0x007fffff,
0x007fffff, 0x007fffff, 0x007fffff, 0x007fffff, 0x007fffff, 0x007fffff, 0x007fffff, 0x007fffff,
}, {
0xfeffffff, 0xfcffffff, 0xf8ffffff, 0xf0ffffff, 0xe0ffffff, 0xc0ffffff, 0x80ffffff, 0x00ffffff,
0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,
0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,
0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,
}, {
0xfdffffff, 0xf9ffffff, 0xf1ffffff, 0xe1ffffff, 0xc1ffffff, 0x81ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
}, {
0xfbffffff, 0xf3ffffff, 0xe3ffffff, 0xc3ffffff, 0x83ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff,
0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff,
0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff,
0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff,
}, {
0xf7ffffff, 0xe7ffffff, 0xc7ffffff, 0x87ffffff, 0x07ffffff, 0x07ffffff, 0x07ffffff, 0x07ffffff,
0x07ffffff, 0x07ffffff, 0x07ffffff, 0x07ffffff, 0x07ffffff, 0x07ffffff, 0x07ffffff, 0x07ffffff,
0x07ffffff, 0x07ffffff, 0x07ffffff, 0x07ffffff, 0x07ffffff, 0x07ffffff, 0x07ffffff, 0x07ffffff,
0x07ffffff, 0x07ffffff, 0x07ffffff, 0x07ffffff, 0x07ffffff, 0x07ffffff, 0x07ffffff, 0x07ffffff,
}, {
0xefffffff, 0xcfffffff, 0x8fffffff, 0x0fffffff, 0x0fffffff, 0x0fffffff, 0x0fffffff, 0x0fffffff,
0x0fffffff, 0x0fffffff, 0x0fffffff, 0x0fffffff, 0x0fffffff, 0x0fffffff, 0x0fffffff, 0x0fffffff,
0x0fffffff, 0x0fffffff, 0x0fffffff, 0x0fffffff, 0x0fffffff, 0x0fffffff, 0x0fffffff, 0x0fffffff,
0x0fffffff, 0x0fffffff, 0x0fffffff, 0x0fffffff, 0x0fffffff, 0x0fffffff, 0x0fffffff, 0x0fffffff,
}, {
0xdfffffff, 0x9fffffff, 0x1fffffff, 0x1fffffff, 0x1fffffff, 0x1fffffff, 0x1fffffff, 0x1fffffff,
0x1fffffff, 0x1fffffff, 0x1fffffff, 0x1fffffff, 0x1fffffff, 0x1fffffff, 0x1fffffff, 0x1fffffff,
0x1fffffff, 0x1fffffff, 0x1fffffff, 0x1fffffff, 0x1fffffff, 0x1fffffff, 0x1fffffff, 0x1fffffff,
0x1fffffff, 0x1fffffff, 0x1fffffff, 0x1fffffff, 0x1fffffff, 0x1fffffff, 0x1fffffff, 0x1fffffff,
}, {
0xbfffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff,
0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff,
0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff,
0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff,
}, {
0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff,
0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff,
0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff,
0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff,
} };
static const uint32_t ExtraMasks[32] =
{
0x00000000, 0x00000001, 0x00000003, 0x00000007, 0x0000000f, 0x0000001f, 0x0000003f, 0x0000007f,
0x000000ff, 0x000001ff, 0x000003ff, 0x000007ff, 0x00000fff, 0x00001fff, 0x00003fff, 0x00007fff,
0x0000ffff, 0x0001ffff, 0x0003ffff, 0x0007ffff, 0x000fffff, 0x001fffff, 0x003fffff, 0x007fffff,
0x00ffffff, 0x01ffffff, 0x03ffffff, 0x07ffffff, 0x0fffffff, 0x1fffffff, 0x3fffffff, 0x7fffffff,
};
const char *const svc_strings[svc_lastmsg+1] = const char *const svc_strings[svc_lastmsg+1] =
{ {
"svc_bad", "svc_bad",
@@ -298,41 +132,65 @@ const char *const svc_quake_strings[svc_lastmsg+1] =
[svc_fog] = "svc_quake_fog", [svc_fog] = "svc_quake_fog",
}; };
void MSG_InitMasks( void )
{
uint startbit, endbit;
uint maskBit, nBitsLeft;
for( startbit = 0; startbit < 32; startbit++ )
{
for( nBitsLeft = 0; nBitsLeft < 33; nBitsLeft++ )
{
endbit = startbit + nBitsLeft;
BitWriteMasks[startbit][nBitsLeft] = (uint)BIT( startbit ) - 1;
if( endbit < 32 ) BitWriteMasks[startbit][nBitsLeft] |= ~((uint)BIT( endbit ) - 1 );
}
}
for( maskBit = 0; maskBit < 32; maskBit++ )
ExtraMasks[maskBit] = (uint)BIT( maskBit ) - 1;
}
void MSG_WriteUBitLong( sizebuf_t *sb, uint curData, int numbits ) void MSG_WriteUBitLong( sizebuf_t *sb, uint curData, int numbits )
{ {
int nBitsLeft = numbits; Assert( numbits >= 0 && numbits <= 32 );
int iCurBit = sb->iCurBit;
uint iDWord = iCurBit >> 5; // Mask in a dword.
uint32_t iCurBitMasked;
int nBitsWritten;
Assert( numbits >= 1 && numbits <= 32 );
// bounds checking.. // bounds checking..
if( MSG_Overflow( sb, numbits )) if(( sb->iCurBit + numbits ) > sb->nDataBits )
{ {
sb->bOverflow = true;
sb->iCurBit = sb->nDataBits; sb->iCurBit = sb->nDataBits;
return;
} }
else
iCurBitMasked = iCurBit & 31;
((uint32_t *)sb->pData)[iDWord] &= BitWriteMasks[iCurBitMasked][nBitsLeft-1];
((uint32_t *)sb->pData)[iDWord] |= curData << iCurBitMasked;
// did it span a dword?
nBitsWritten = 32 - iCurBitMasked;
if( nBitsWritten < nBitsLeft )
{ {
nBitsLeft -= nBitsWritten; int nBitsLeft = numbits;
iCurBit += nBitsWritten; int iCurBit = sb->iCurBit;
curData >>= nBitsWritten; uint iDWord = iCurBit >> 5; // Mask in a dword.
uint32_t iCurBitMasked;
int nBitsWritten;
Assert(( iDWord * 4 + sizeof( int )) <= (uint)MSG_GetMaxBytes( sb ));
iCurBitMasked = iCurBit & 31; iCurBitMasked = iCurBit & 31;
((uint32_t *)sb->pData)[iDWord+1] &= BitWriteMasks[iCurBitMasked][nBitsLeft-1]; ((uint32_t *)sb->pData)[iDWord] &= BitWriteMasks[iCurBitMasked][nBitsLeft];
((uint32_t *)sb->pData)[iDWord+1] |= curData << iCurBitMasked; ((uint32_t *)sb->pData)[iDWord] |= curData << iCurBitMasked;
// did it span a dword?
nBitsWritten = 32 - iCurBitMasked;
if( nBitsWritten < nBitsLeft )
{
nBitsLeft -= nBitsWritten;
iCurBit += nBitsWritten;
curData >>= nBitsWritten;
iCurBitMasked = iCurBit & 31;
((uint32_t *)sb->pData)[iDWord+1] &= BitWriteMasks[iCurBitMasked][nBitsLeft];
((uint32_t *)sb->pData)[iDWord+1] |= curData << iCurBitMasked;
}
sb->iCurBit += numbits;
} }
sb->iCurBit += numbits;
} }
/* /*
@@ -380,7 +238,7 @@ qboolean MSG_WriteBits( sizebuf_t *sb, const void *pData, int nBits )
int nBitsLeft = nBits; int nBitsLeft = nBits;
// get output dword-aligned. // get output dword-aligned.
while((( uintptr_t )pOut & 3 ) != 0 && nBitsLeft >= 8 ) while((( uint32_t )pOut & 3 ) != 0 && nBitsLeft >= 8 )
{ {
MSG_WriteUBitLong( sb, *pOut, 8 ); MSG_WriteUBitLong( sb, *pOut, 8 );
@@ -417,14 +275,16 @@ qboolean MSG_WriteBits( sizebuf_t *sb, const void *pData, int nBits )
void MSG_WriteBitAngle( sizebuf_t *sb, float fAngle, int numbits ) void MSG_WriteBitAngle( sizebuf_t *sb, float fAngle, int numbits )
{ {
const uint shift = ( 1 << numbits ); uint mask, shift;
const uint mask = shift - 1;
int d; int d;
// clamp the angle before receiving // clamp the angle before receiving
fAngle = fmod( fAngle, 360.0f ); fAngle = fmod( fAngle, 360.0f );
if( fAngle < 0 ) fAngle += 360.0f; if( fAngle < 0 ) fAngle += 360.0f;
shift = ( 1 << numbits );
mask = shift - 1;
d = (int)(( fAngle * shift ) / 360.0f ); d = (int)(( fAngle * shift ) / 360.0f );
d &= mask; d &= mask;
@@ -578,8 +438,9 @@ uint MSG_ReadUBitLong( sizebuf_t *sb, int numbits )
return 0; // end of message return 0; // end of message
} }
if( MSG_Overflow( sb, numbits )) if(( sb->iCurBit + numbits ) > sb->nDataBits )
{ {
sb->bOverflow = true;
sb->iCurBit = sb->nDataBits; sb->iCurBit = sb->nDataBits;
return 0; return 0;
} }
@@ -652,9 +513,13 @@ qboolean MSG_ReadBits( sizebuf_t *sb, void *pOutData, int nBits )
float MSG_ReadBitAngle( sizebuf_t *sb, int numbits ) float MSG_ReadBitAngle( sizebuf_t *sb, int numbits )
{ {
float shift = (float)( 1 << numbits ); float fReturn, shift;
int i = MSG_ReadUBitLong( sb, numbits ); int i;
float fReturn = (float)i * ( 360.0f / shift );
shift = (float)( 1 << numbits );
i = MSG_ReadUBitLong( sb, numbits );
fReturn = (float)i * ( 360.0f / shift );
// clamp the finale angle // clamp the finale angle
if( fReturn < -180.0f ) fReturn += 360.0f; if( fReturn < -180.0f ) fReturn += 360.0f;
@@ -666,11 +531,11 @@ float MSG_ReadBitAngle( sizebuf_t *sb, int numbits )
// Append numbits least significant bits from data to the current bit stream // Append numbits least significant bits from data to the current bit stream
int MSG_ReadSBitLong( sizebuf_t *sb, int numbits ) int MSG_ReadSBitLong( sizebuf_t *sb, int numbits )
{ {
int r; int r, sign;
if( sb->iAlternateSign ) if( sb->iAlternateSign )
{ {
int sign = MSG_ReadOneBit( sb ); sign = MSG_ReadOneBit( sb );
r = MSG_ReadUBitLong( sb, numbits - 1 ); r = MSG_ReadUBitLong( sb, numbits - 1 );
if( sign ) if( sign )
@@ -679,7 +544,9 @@ int MSG_ReadSBitLong( sizebuf_t *sb, int numbits )
else else
{ {
r = MSG_ReadUBitLong( sb, numbits - 1 ); r = MSG_ReadUBitLong( sb, numbits - 1 );
if( MSG_ReadOneBit( sb )) sign = MSG_ReadOneBit( sb );
if( sign )
r = -( BIT( numbits - 1 ) - r ); r = -( BIT( numbits - 1 ) - r );
} }
@@ -800,12 +667,12 @@ qboolean MSG_ReadBytes( sizebuf_t *sb, void *pOut, int nBytes )
static char *MSG_ReadStringExt( sizebuf_t *sb, qboolean bLine ) static char *MSG_ReadStringExt( sizebuf_t *sb, qboolean bLine )
{ {
static char string[4096]; static char string[4096];
int l = 0; int l = 0, c;
do do
{ {
// use MSG_ReadByte so -1 is out of bounds // use MSG_ReadByte so -1 is out of bounds
int c = MSG_ReadByte( sb ); c = MSG_ReadByte( sb );
if( c == 0 ) break; if( c == 0 ) break;
else if( bLine && c == '\n' ) else if( bLine && c == '\n' )
@@ -998,6 +865,8 @@ static void Test_Buffer_ExciseBits( void )
void Test_RunBuffer( void ) void Test_RunBuffer( void )
{ {
MSG_InitMasks();
TRUN( Test_Buffer_BitByte( )); TRUN( Test_Buffer_BitByte( ));
TRUN( Test_Buffer_Write( )); TRUN( Test_Buffer_Write( ));
TRUN( Test_Buffer_Read( )); TRUN( Test_Buffer_Read( ));

View File

@@ -193,6 +193,7 @@ static inline void MSG_StartBitWriting( sizebuf_t *sb )
sb->iAlternateSign++; sb->iAlternateSign++;
} }
void MSG_InitMasks( void ); // called once at startup engine
void MSG_ExciseBits( sizebuf_t *sb, int startbit, int bitstoremove ); void MSG_ExciseBits( sizebuf_t *sb, int startbit, int bitstoremove );
// Bit-write functions // Bit-write functions

View File

@@ -272,6 +272,8 @@ void Netchan_Init( void )
Cvar_FullSet( net_qport.name, buf, net_qport.flags ); Cvar_FullSet( net_qport.name, buf, net_qport.flags );
net_mempool = Mem_AllocPool( "Network Pool" ); net_mempool = Mem_AllocPool( "Network Pool" );
MSG_InitMasks(); // initialize bit-masks
} }
void Netchan_Shutdown( void ) void Netchan_Shutdown( void )
@@ -341,7 +343,6 @@ void Netchan_Setup( netsrc_t sock, netchan_t *chan, netadr_t adr, int qport, voi
chan->split = FBitSet( flags, NETCHAN_USE_LEGACY_SPLIT ) ? true : false; chan->split = FBitSet( flags, NETCHAN_USE_LEGACY_SPLIT ) ? true : false;
chan->use_munge = FBitSet( flags, NETCHAN_USE_MUNGE ) ? true : false; chan->use_munge = FBitSet( flags, NETCHAN_USE_MUNGE ) ? true : false;
chan->use_bz2 = FBitSet( flags, NETCHAN_USE_BZIP2 ) ? true : false; chan->use_bz2 = FBitSet( flags, NETCHAN_USE_BZIP2 ) ? true : false;
chan->use_lzss = FBitSet( flags, NETCHAN_USE_LZSS ) ? true : false;
chan->gs_netchan = FBitSet( flags, NETCHAN_GOLDSRC ) ? true : false; chan->gs_netchan = FBitSet( flags, NETCHAN_GOLDSRC ) ? true : false;
MSG_Init( &chan->message, "NetData", chan->message_buf, sizeof( chan->message_buf )); MSG_Init( &chan->message, "NetData", chan->message_buf, sizeof( chan->message_buf ));
@@ -767,7 +768,7 @@ static void Netchan_CreateFragments_( netchan_t *chan, sizebuf_t *msg )
Host_Error( "%s: BZ2 compression is not supported for server", __func__ ); Host_Error( "%s: BZ2 compression is not supported for server", __func__ );
#endif #endif
} }
else if( chan->use_lzss && !LZSS_IsCompressed( MSG_GetData( msg ), MSG_GetMaxBytes( msg ))) else if( !chan->use_bz2 && !LZSS_IsCompressed( MSG_GetData( msg ), MSG_GetMaxBytes( msg )))
{ {
uint uCompressedSize = 0; uint uCompressedSize = 0;
uint uSourceSize = MSG_GetNumBytesWritten( msg ); uint uSourceSize = MSG_GetNumBytesWritten( msg );
@@ -1174,7 +1175,7 @@ qboolean Netchan_CopyNormalFragments( netchan_t *chan, sizebuf_t *msg, size_t *l
p = n; p = n;
} }
if( chan->use_bz2 && !memcmp( MSG_GetData( msg ), "BZ2", 4 )) if( chan->use_bz2 && !memcmp( MSG_GetData( msg ), "BZ2", 4 ) )
{ {
#if !XASH_DEDICATED #if !XASH_DEDICATED
byte buf[0x10000]; byte buf[0x10000];
@@ -1195,7 +1196,7 @@ qboolean Netchan_CopyNormalFragments( netchan_t *chan, sizebuf_t *msg, size_t *l
Host_Error( "%s: BZ2 compression is not supported for server\n", __func__ ); Host_Error( "%s: BZ2 compression is not supported for server\n", __func__ );
#endif #endif
} }
else if( chan->use_lzss && LZSS_IsCompressed( MSG_GetData( msg ), size )) else if( !chan->use_bz2 && LZSS_IsCompressed( MSG_GetData( msg ), size ))
{ {
uint uDecompressedLen = LZSS_GetActualSize( MSG_GetData( msg ), size ); uint uDecompressedLen = LZSS_GetActualSize( MSG_GetData( msg ), size );
byte buf[NET_MAX_MESSAGE]; byte buf[NET_MAX_MESSAGE];
@@ -1346,7 +1347,7 @@ qboolean Netchan_CopyFileFragments( netchan_t *chan, sizebuf_t *msg )
Host_Error( "%s: BZ2 compression is not supported for server", __func__ ); Host_Error( "%s: BZ2 compression is not supported for server", __func__ );
#endif #endif
} }
else if( chan->use_lzss && LZSS_IsCompressed( buffer, nsize + 1 )) else if( LZSS_IsCompressed( buffer, nsize + 1 ))
{ {
byte *uncompressedBuffer; byte *uncompressedBuffer;

View File

@@ -2282,6 +2282,10 @@ void Test_RunDelta( void )
char buffer[4096] = { 0 }; char buffer[4096] = { 0 };
const double timebase = 123.123; const double timebase = 123.123;
// a1ba: netbuffer bitmasks are initialized in netchan for some reason
// initialize it ourselves just in case
MSG_InitMasks(); // initialize bit-masks
Delta_AddField( dt, "dt_string", DT_STRING, 1, 1.0f, 1.0f ); Delta_AddField( dt, "dt_string", DT_STRING, 1, 1.0f, 1.0f );
Delta_AddField( dt, "dt_timewindow_big", DT_TIMEWINDOW_BIG, 24, 1000.f, 1.0f ); Delta_AddField( dt, "dt_timewindow_big", DT_TIMEWINDOW_BIG, 24, 1000.f, 1.0f );
Delta_AddField( dt, "dt_timewindow_8", DT_TIMEWINDOW_8, 8, 1.0f, 1.0f ); Delta_AddField( dt, "dt_timewindow_8", DT_TIMEWINDOW_8, 8, 1.0f, 1.0f );

View File

@@ -505,14 +505,11 @@ static int HTTP_FileDecompress( httpfile_t *file )
if( zlib_result == Z_OK || zlib_result == Z_STREAM_END ) if( zlib_result == Z_OK || zlib_result == Z_STREAM_END )
{ {
g_fsapi.WriteFile( name, data_out, decompressed_len ); Mem_Free( data_in );
HTTP_FreeFile( file, false );
} }
else HTTP_FreeFile( file, true );
Mem_Free( data_in );
Mem_Free( data_out );
g_fsapi.WriteFile( name, data_out, decompressed_len );
HTTP_FreeFile( file, false );
return 1; return 1;
} }

View File

@@ -214,7 +214,6 @@ typedef enum netchan_flags_e
NETCHAN_USE_MUNGE = BIT( 1 ), NETCHAN_USE_MUNGE = BIT( 1 ),
NETCHAN_USE_BZIP2 = BIT( 2 ), NETCHAN_USE_BZIP2 = BIT( 2 ),
NETCHAN_GOLDSRC = BIT( 3 ), NETCHAN_GOLDSRC = BIT( 3 ),
NETCHAN_USE_LZSS = BIT( 4 ), // mutually exclusive with bzip2
} netchan_flags_t; } netchan_flags_t;
// Network Connection Channel // Network Connection Channel
@@ -286,7 +285,6 @@ typedef struct netchan_s
qboolean split; qboolean split;
qboolean use_munge; qboolean use_munge;
qboolean use_bz2; qboolean use_bz2;
qboolean use_lzss;
qboolean gs_netchan; qboolean gs_netchan;
} netchan_t; } netchan_t;

View File

@@ -89,6 +89,16 @@ void Sound_Shutdown( void )
Mem_FreePool( &host.soundpool ); Mem_FreePool( &host.soundpool );
} }
static byte *Sound_Copy( size_t size )
{
byte *out;
out = Mem_Realloc( host.soundpool, sound.tempbuffer, size );
sound.tempbuffer = NULL;
return out;
}
uint GAME_EXPORT Sound_GetApproxWavePlayLen( const char *filepath ) uint GAME_EXPORT Sound_GetApproxWavePlayLen( const char *filepath )
{ {
string name; string name;
@@ -368,7 +378,6 @@ static qboolean Sound_ResampleInternal( wavdata_t *sc, int outrate, int outwidth
const int inwidth = sc->width; const int inwidth = sc->width;
const int inchannels = sc->channels; const int inchannels = sc->channels;
const int incount = sc->samples; const int incount = sc->samples;
const int insize = sc->size;
qboolean handled = false; qboolean handled = false;
double stepscale; double stepscale;
double t1, t2; double t1, t2;
@@ -422,30 +431,22 @@ static qboolean Sound_ResampleInternal( wavdata_t *sc, int outrate, int outwidth
else // upsample case, w/ interpolation else // upsample case, w/ interpolation
handled = Sound_ConvertUpsample( sc, inwidth, inchannels, incount, outwidth, outchannels, outcount, stepscale ); handled = Sound_ConvertUpsample( sc, inwidth, inchannels, incount, outwidth, outchannels, outcount, stepscale );
if( !handled ) t2 = Sys_DoubleTime();
{
// restore previously changed data
sc->rate = inrate;
sc->width = inwidth;
sc->channels = inchannels;
sc->samples = incount;
sc->size = insize;
if( handled )
{
if( t2 - t1 > 0.01f ) // critical, report to mod developer
Con_Printf( S_WARN "%s: from [%d bit %d Hz %dch] to [%d bit %d Hz %dch] (took %.3fs)\n", __func__, inwidth * 8, inrate, inchannels, outwidth * 8, outrate, outchannels, t2 - t1 );
else
Con_Reportf( "%s: from [%d bit %d Hz %dch] to [%d bit %d Hz %dch] (took %.3fs)\n", __func__, inwidth * 8, inrate, inchannels, outwidth * 8, outrate, outchannels, t2 - t1 );
}
else
Con_Printf( S_ERROR "%s: unsupported from [%d bit %d Hz %dch] to [%d bit %d Hz %dch]\n", __func__, inwidth * 8, inrate, inchannels, outwidth * 8, outrate, outchannels ); Con_Printf( S_ERROR "%s: unsupported from [%d bit %d Hz %dch] to [%d bit %d Hz %dch]\n", __func__, inwidth * 8, inrate, inchannels, outwidth * 8, outrate, outchannels );
return false;
}
t2 = Sys_DoubleTime();
sc->rate = outrate; sc->rate = outrate;
sc->width = outwidth; sc->width = outwidth;
if( t2 - t1 > 0.01f ) // critical, report to mod developer return handled;
Con_Printf( S_WARN "%s: from [%d bit %d Hz %dch] to [%d bit %d Hz %dch] (took %.3fs)\n", __func__, inwidth * 8, inrate, inchannels, outwidth * 8, outrate, outchannels, t2 - t1 );
else
Con_Reportf( "%s: from [%d bit %d Hz %dch] to [%d bit %d Hz %dch] (took %.3fs)\n", __func__, inwidth * 8, inrate, inchannels, outwidth * 8, outrate, outchannels, t2 - t1 );
return true;
} }
qboolean Sound_Process( wavdata_t **wav, int rate, int width, int channels, uint flags ) qboolean Sound_Process( wavdata_t **wav, int rate, int width, int channels, uint flags )
@@ -463,11 +464,8 @@ qboolean Sound_Process( wavdata_t **wav, int rate, int width, int channels, uint
if( result ) if( result )
{ {
snd = Mem_Realloc( host.soundpool, snd, sizeof( *snd ) + snd->size ); Mem_Free( snd->buffer ); // free original image buffer
memcpy( snd->buffer, sound.tempbuffer, snd->size ); snd->buffer = Sound_Copy( snd->size ); // unzone buffer
Mem_Free( sound.tempbuffer );
sound.tempbuffer = NULL;
} }
} }

View File

@@ -41,15 +41,6 @@ NOTE: never change this structure because all dll descriptions in xash code
writes into struct by offsets not names writes into struct by offsets not names
======================================================================== ========================================================================
*/ */
typedef struct dll_info_s
{
const char *name; // name of library
const dllfunc_t *fcts; // list of dll exports
const size_t num_fcts;
qboolean crash; // crash if dll not found
void *link; // hinstance of loading library
} dll_info_t;
extern int error_on_exit; extern int error_on_exit;
double Sys_DoubleTime( void ); double Sys_DoubleTime( void );
char *Sys_GetClipboardData( void ); char *Sys_GetClipboardData( void );

View File

@@ -68,13 +68,7 @@ extern "C" {
#if defined(_MSC_VER) #if defined(_MSC_VER)
#pragma warning(pop) #pragma warning(pop)
#endif #endif
#if (_MSC_VER >= 1900)
#include <stdbool.h> #include <stdbool.h>
#else
#define bool int
#define false 0
#define true 1
#endif
static int WAI_PREFIX(getModulePath_)(HMODULE module, char* out, int capacity, int* dirname_length) static int WAI_PREFIX(getModulePath_)(HMODULE module, char* out, int capacity, int* dirname_length)
{ {
@@ -249,11 +243,6 @@ int WAI_PREFIX(getExecutablePath)(char* out, int capacity, int* dirname_length)
#endif #endif
#endif #endif
#if !defined(WAI_STRINGIZE)
#define WAI_STRINGIZE(s)
#define WAI_STRINGIZE_(s) #s
#endif
#if defined(__ANDROID__) || defined(ANDROID) #if defined(__ANDROID__) || defined(ANDROID)
#include <fcntl.h> #include <fcntl.h>
#include <sys/mman.h> #include <sys/mman.h>
@@ -276,20 +265,20 @@ int WAI_PREFIX(getModulePath)(char* out, int capacity, int* dirname_length)
for (;;) for (;;)
{ {
char buffer[128 + PATH_MAX]; char buffer[PATH_MAX < 1024 ? 1024 : PATH_MAX];
uintptr_t low, high; uint64_t low, high;
char perms[5]; char perms[5];
uint64_t offset; uint64_t offset;
uint32_t major, minor, inode; uint32_t major, minor;
char path[PATH_MAX + 1]; char path[PATH_MAX];
uint32_t inode;
if (!fgets(buffer, sizeof(buffer), maps)) if (!fgets(buffer, sizeof(buffer), maps))
break; break;
if (sscanf(buffer, "%" SCNxPTR "-%" SCNxPTR " %s %" SCNx64 " %x:%x %u %" WAI_STRINGIZE(PATH_MAX) "[^\n]\n", &low, &high, perms, &offset, &major, &minor, &inode, path) == 8) if (sscanf(buffer, "%" PRIx64 "-%" PRIx64 " %s %" PRIx64 " %x:%x %u %s\n", &low, &high, perms, &offset, &major, &minor, &inode, path) == 8)
{ {
void* _addr = WAI_RETURN_ADDRESS(); uint64_t addr = (uintptr_t)WAI_RETURN_ADDRESS();
uintptr_t addr = (uintptr_t)_addr;
if (low <= addr && addr <= high) if (low <= addr && addr <= high)
{ {
char* resolved; char* resolved;

View File

@@ -31,8 +31,7 @@ extern "C" {
* @param out destination buffer, optional * @param out destination buffer, optional
* @param capacity destination buffer capacity * @param capacity destination buffer capacity
* @param dirname_length optional recipient for the length of the dirname part * @param dirname_length optional recipient for the length of the dirname part
* of the path. Available only when `capacity` is large enough to retrieve the * of the path.
* path.
* *
* @return the length of the executable path on success (without a terminal NUL * @return the length of the executable path on success (without a terminal NUL
* character), otherwise `-1` * character), otherwise `-1`
@@ -53,8 +52,7 @@ int WAI_PREFIX(getExecutablePath)(char* out, int capacity, int* dirname_length);
* @param out destination buffer, optional * @param out destination buffer, optional
* @param capacity destination buffer capacity * @param capacity destination buffer capacity
* @param dirname_length optional recipient for the length of the dirname part * @param dirname_length optional recipient for the length of the dirname part
* of the path. Available only when `capacity` is large enough to retrieve the * of the path.
* path.
* *
* @return the length of the module path on success (without a terminal NUL * @return the length of the module path on success (without a terminal NUL
* character), otherwise `-1` * character), otherwise `-1`

View File

@@ -18,7 +18,7 @@ GNU General Public License for more details.
#include "common.h" #include "common.h"
#define MEMHEADER_SENTINEL1 0xA1BAU #define MEMHEADER_SENTINEL1 0xDEADF00DU
#define MEMHEADER_SENTINEL2 0xDFU #define MEMHEADER_SENTINEL2 0xDFU
#ifdef XASH_CUSTOM_SWAP #ifdef XASH_CUSTOM_SWAP
@@ -51,29 +51,31 @@ static void *Q_realloc( void *mem, size_t size )
#define Q_realloc realloc #define Q_realloc realloc
#endif #endif
// keep this structure as compact as possible while keeping it aligned
// on ILP32 it's 24 bytes, which is aligned to 8 byte boundary
// on LP64 it's 40 bytes, which is also aligned to 8 byte boundary
typedef struct memheader_s typedef struct memheader_s
{ {
struct memheader_s *next, *prev; // next and previous memheaders in chain belonging to pool struct memheader_s *next; // next and previous memheaders in chain belonging to pool
const char *filename; // file name and line where Mem_Alloc was called struct memheader_s *prev;
size_t size; // size of the memory after the header (excluding header and sentinel2) const char *filename; // file name and line where Mem_Alloc was called
poolhandle_t poolptr; // pool this memheader belongs to size_t size; // size of the memory after the header (excluding header and sentinel2)
uint16_t fileline; poolhandle_t poolptr; // pool this memheader belongs to
uint16_t sentinel1; // must be equal to MEMHEADER_SENTINEL1 int fileline;
#if !XASH_64BIT
uint32_t pad0; // doesn't have value, only to make Mem_Alloc return aligned addresses on ILP32
#endif
uint32_t sentinel1; // should always be MEMHEADER_SENTINEL1
// immediately followed by data, which is followed by a MEMHEADER_SENTINEL2 byte // immediately followed by data, which is followed by a MEMHEADER_SENTINEL2 byte
} memheader_t; } memheader_t;
typedef struct mempool_s typedef struct mempool_s
{ {
struct memheader_s *chain; // chain of individual memory allocations struct memheader_s *chain; // chain of individual memory allocations
size_t totalsize; // total memory allocated in this pool (inside memheaders) size_t totalsize; // total memory allocated in this pool (inside memheaders)
size_t realsize; // total memory allocated in this pool (actual malloc total) size_t realsize; // total memory allocated in this pool (actual malloc total)
size_t lastchecksize; // updated each time the pool is displayed by memlist size_t lastchecksize; // updated each time the pool is displayed by memlist
const char *filename; // file name and line where Mem_AllocPool was called const char *filename; // file name and line where Mem_AllocPool was called
int fileline; int fileline;
char name[64]; // name of the pool char name[64]; // name of the pool
} mempool_t; } mempool_t;
static mempool_t *poolchain = NULL; // critical stuff static mempool_t *poolchain = NULL; // critical stuff
@@ -519,5 +521,4 @@ Memory_Init
void Memory_Init( void ) void Memory_Init( void )
{ {
poolchain = NULL; // init mem chain poolchain = NULL; // init mem chain
poolcount = 0;
} }

View File

@@ -1,164 +1,186 @@
/* /***
Copyright (C) 1997-2001 Id Software, Inc. *
* Copyright (c) 1996-2002, Valve LLC. All rights reserved.
*
* This product contains software technology licensed from Id
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
* All Rights Reserved.
*
* Use, distribution, and modification of this source code and/or resulting
* object code is restricted to non-commercial enhancements to products from
* Valve LLC. All other use, distribution, or modification is prohibited
* without written permission from Valve LLC.
*
****/
This program is free software; you can redistribute it and/or #ifndef KEYDEFS_H
modify it under the terms of the GNU General Public License #define KEYDEFS_H
as published by the Free Software Foundation; either version 2
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.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// taken from Quake-2 source code and modified for GoldSrc compatibility
// //
// these are the key numbers that should be passed to Key_Event // these are the key numbers that should be passed to Key_Event
// normal keys should be passed as lowercased ascii
// //
#define K_TAB 9 #define K_TAB 9
#define K_ENTER 13 #define K_ENTER 13
#define K_ESCAPE 27 #define K_ESCAPE 27
#define K_SPACE 32 #define K_SPACE 32
#define K_SCROLLLOCK 70 #define K_SCROLLOCK 70
#define K_BACKSPACE 127
#define K_UPARROW 128
#define K_DOWNARROW 129
#define K_LEFTARROW 130
#define K_RIGHTARROW 131
#define K_ALT 132
#define K_CTRL 133
#define K_SHIFT 134
#define K_F1 135
#define K_F2 136
#define K_F3 137
#define K_F4 138
#define K_F5 139
#define K_F6 140
#define K_F7 141
#define K_F8 142
#define K_F9 143
#define K_F10 144
#define K_F11 145
#define K_F12 146
#define K_INS 147
#define K_DEL 148
#define K_PGDN 149
#define K_PGUP 150
#define K_HOME 151
#define K_END 152
#define K_KP_HOME 160 // normal keys should be passed as lowercased ascii
#define K_KP_UPARROW 161
#define K_KP_PGUP 162 #define K_BACKSPACE 127
#define K_KP_LEFTARROW 163 #define K_UPARROW 128
#define K_KP_5 164 #define K_DOWNARROW 129
#define K_LEFTARROW 130
#define K_RIGHTARROW 131
#define K_ALT 132
#define K_CTRL 133
#define K_SHIFT 134
#define K_F1 135
#define K_F2 136
#define K_F3 137
#define K_F4 138
#define K_F5 139
#define K_F6 140
#define K_F7 141
#define K_F8 142
#define K_F9 143
#define K_F10 144
#define K_F11 145
#define K_F12 146
#define K_INS 147
#define K_DEL 148
#define K_PGDN 149
#define K_PGUP 150
#define K_HOME 151
#define K_END 152
#define K_KP_HOME 160
#define K_KP_UPARROW 161
#define K_KP_PGUP 162
#define K_KP_LEFTARROW 163
#define K_KP_5 164
#define K_KP_RIGHTARROW 165 #define K_KP_RIGHTARROW 165
#define K_KP_END 166 #define K_KP_END 166
#define K_KP_DOWNARROW 167 #define K_KP_DOWNARROW 167
#define K_KP_PGDN 168 #define K_KP_PGDN 168
#define K_KP_ENTER 169 #define K_KP_ENTER 169
#define K_KP_INS 170 #define K_KP_INS 170
#define K_KP_DEL 171 #define K_KP_DEL 171
#define K_KP_SLASH 172 #define K_KP_SLASH 172
#define K_KP_MINUS 173 #define K_KP_MINUS 173
#define K_KP_PLUS 174 #define K_KP_PLUS 174
#define K_CAPSLOCK 175 #define K_CAPSLOCK 175
#define K_KP_MUL 176 #define K_KP_MUL 176
#define K_WIN 177 #define K_WIN 177
#define K_KP_NUMLOCK 178 #define K_KP_NUMLOCK 178
// //
// joystick buttons // joystick buttons
// //
#define K_JOY1 203 #define K_JOY1 203 // LTRIGGER (L2)
#define K_JOY2 204 #define K_JOY2 204 // RTRIGGER (R2)
#define K_JOY3 205 #define K_JOY3 205
#define K_JOY4 206 #define K_JOY4 206
// //
// aux keys are for multi-buttoned joysticks to generate so they can use // aux keys are for multi-buttoned joysticks to generate so they can use
// the normal binding process // the normal binding process
// //
#define K_AUX1 207 #define K_AUX1 207
#define K_AUX2 208 #define K_A_BUTTON K_AUX1
#define K_AUX3 209
#define K_AUX4 210
#define K_AUX5 211
#define K_AUX6 212
#define K_AUX7 213
#define K_AUX8 214
#define K_AUX9 215
#define K_AUX10 216
#define K_AUX11 217
#define K_AUX12 218
#define K_AUX13 219
#define K_AUX14 220
#define K_AUX15 221
#define K_AUX16 222
#define K_AUX17 223
#define K_AUX18 224
#define K_AUX19 225
#define K_AUX20 226
#define K_AUX21 227
#define K_AUX22 228
#define K_AUX23 229
#define K_AUX24 230
#define K_AUX25 231
#define K_AUX26 232
#define K_AUX27 233
#define K_AUX28 234
#define K_AUX29 235
#define K_AUX30 236
#define K_AUX31 237
#define K_AUX32 238
// #define K_AUX2 208
// button names for game pads #define K_B_BUTTON K_AUX2
//
#define K_A_BUTTON K_AUX1 #define K_AUX3 209
#define K_B_BUTTON K_AUX2 #define K_X_BUTTON K_AUX3
#define K_X_BUTTON K_AUX3
#define K_Y_BUTTON K_AUX4 #define K_AUX4 210
#define K_L1_BUTTON K_AUX5 #define K_Y_BUTTON K_AUX4
#define K_R1_BUTTON K_AUX6
#define K_BACK_BUTTON K_AUX7 #define K_AUX5 211
#define K_MODE_BUTTON K_AUX8 #define K_L1_BUTTON K_AUX5
#define K_START_BUTTON K_AUX9
#define K_LSTICK K_AUX10 #define K_AUX6 212
#define K_RSTICK K_AUX11 #define K_R1_BUTTON K_AUX6
#define K_L2_BUTTON K_AUX12
#define K_R2_BUTTON K_AUX13 #define K_AUX7 213
#define K_C_BUTTON K_AUX14 #define K_BACK_BUTTON K_AUX7
#define K_Z_BUTTON K_AUX15
#define K_DPAD_UP K_AUX16 #define K_AUX8 214
#define K_DPAD_DOWN K_AUX17 #define K_MODE_BUTTON K_AUX8
#define K_DPAD_LEFT K_AUX18
#define K_DPAD_RIGHT K_AUX19 #define K_AUX9 215
#define K_MISC_BUTTON K_AUX20 #define K_START_BUTTON K_AUX9
#define K_PADDLE1_BUTTON K_AUX21
#define K_AUX10 216
#define K_LSTICK K_AUX10
#define K_AUX11 217
#define K_RSTICK K_AUX11
#define K_AUX12 218
#define K_L2_BUTTON K_AUX12
#define K_AUX13 219
#define K_R2_BUTTON K_AUX13
#define K_AUX14 220
#define K_C_BUTTON K_AUX14
#define K_AUX15 221
#define K_Z_BUTTON K_AUX15
#define K_AUX16 222
#define K_DPAD_UP K_AUX16
#define K_AUX17 223
#define K_DPAD_DOWN K_AUX17
#define K_AUX18 224
#define K_DPAD_LEFT K_AUX18
#define K_AUX19 225
#define K_DPAD_RIGHT K_AUX19
#define K_AUX20 226
#define K_MISC_BUTTON K_AUX20 // Xbox Series X share button, PS5 microphone button, Nintendo Switch Pro capture button
#define K_AUX21 227
#define K_PADDLE1_BUTTON K_AUX21 // Xbox Elite paddle P1-P4
#define K_AUX22 228
#define K_PADDLE2_BUTTON K_AUX22 #define K_PADDLE2_BUTTON K_AUX22
#define K_AUX23 229
#define K_PADDLE3_BUTTON K_AUX23 #define K_PADDLE3_BUTTON K_AUX23
#define K_AUX24 230
#define K_PADDLE4_BUTTON K_AUX24 #define K_PADDLE4_BUTTON K_AUX24
#define K_TOUCHPAD K_AUX25
#define K_AUX25 231
#define K_TOUCHPAD K_AUX25 // PS4/PS5 touchpad button
#define K_AUX26 232
#define K_AUX27 233
#define K_AUX28 234
#define K_AUX29 235
#define K_AUX30 236
#define K_AUX31 237
#define K_AUX32 238
#define K_MWHEELDOWN 239
#define K_MWHEELUP 240
#define K_PAUSE 255
// //
// mouse buttons generate virtual keys // mouse buttons generate virtual keys
// //
#define K_MWHEELDOWN 239 #define K_MOUSE1 241
#define K_MWHEELUP 240 #define K_MOUSE2 242
#define K_MOUSE1 241 #define K_MOUSE3 243
#define K_MOUSE2 242 #define K_MOUSE4 244
#define K_MOUSE3 243 #define K_MOUSE5 245
#define K_MOUSE4 244
#define K_MOUSE5 245
#define K_PAUSE 255 #endif//KEYDEFS_H

View File

@@ -184,7 +184,7 @@ qboolean SNDDMA_Init( void )
return false; return false;
} }
dma.buffer = Mem_Malloc( sndpool, samples * 2 ); //allocate pcm frame buffer dma.buffer = Z_Malloc( samples * 2 ); //allocate pcm frame buffer
dma.samplepos = 0; dma.samplepos = 0;
dma.samples = samples; dma.samples = samples;
dma.format.width = 2; dma.format.width = 2;

View File

@@ -55,7 +55,7 @@ char *Posix_Input( void );
#endif #endif
#if XASH_SDL #if XASH_SDL
void SDLash_Init( const char *basedir ); void SDLash_Init( void );
void SDLash_Shutdown( void ); void SDLash_Shutdown( void );
#endif #endif
@@ -104,7 +104,7 @@ void Linux_SetTimer( float time );
int Linux_GetProcessID( void ); int Linux_GetProcessID( void );
#endif #endif
static inline void Platform_Init( qboolean con_showalways, const char *basedir ) static inline void Platform_Init( qboolean con_showalways )
{ {
#if XASH_POSIX #if XASH_POSIX
// daemonize as early as possible, because we need to close our file descriptors // daemonize as early as possible, because we need to close our file descriptors
@@ -112,7 +112,7 @@ static inline void Platform_Init( qboolean con_showalways, const char *basedir )
#endif #endif
#if XASH_SDL #if XASH_SDL
SDLash_Init( basedir ); SDLash_Init( );
#endif #endif
#if XASH_ANDROID #if XASH_ANDROID

View File

@@ -265,7 +265,7 @@ static void SDLash_KeyEvent( SDL_KeyboardEvent key )
break; break;
} }
case SDL_SCANCODE_PAUSE: keynum = K_PAUSE; break; case SDL_SCANCODE_PAUSE: keynum = K_PAUSE; break;
case SDL_SCANCODE_SCROLLLOCK: keynum = K_SCROLLLOCK; break; case SDL_SCANCODE_SCROLLLOCK: keynum = K_SCROLLOCK; break;
#if SDL_VERSION_ATLEAST( 2, 0, 0 ) #if SDL_VERSION_ATLEAST( 2, 0, 0 )
case SDL_SCANCODE_APPLICATION: keynum = K_WIN; break; // (compose key) ??? case SDL_SCANCODE_APPLICATION: keynum = K_WIN; break; // (compose key) ???
// don't console spam on known functional buttons, not used in engine // don't console spam on known functional buttons, not used in engine

View File

@@ -175,7 +175,7 @@ qboolean SNDDMA_Init( void )
if( !samplecount ) if( !samplecount )
samplecount = 0x8000; samplecount = 0x8000;
dma.samples = samplecount * obtained.channels; dma.samples = samplecount * obtained.channels;
dma.buffer = Mem_Malloc( sndpool, dma.samples * 2 ); dma.buffer = Z_Calloc( dma.samples * 2 );
dma.samplepos = 0; dma.samplepos = 0;
sdl_format = obtained.format; sdl_format = obtained.format;

View File

@@ -20,9 +20,9 @@ GNU General Public License for more details.
#if XASH_TIMER == TIMER_SDL #if XASH_TIMER == TIMER_SDL
double Platform_DoubleTime( void ) double Platform_DoubleTime( void )
{ {
static Uint64 g_PerformanceFrequency; static longtime_t g_PerformanceFrequency;
static Uint64 g_ClockStart; static longtime_t g_ClockStart;
Uint64 CurrentTime; longtime_t CurrentTime;
if( !g_PerformanceFrequency ) if( !g_PerformanceFrequency )
{ {
@@ -78,19 +78,8 @@ static void SDLCALL SDLash_LogOutputFunction( void *userdata, int category, SDL_
} }
} }
void SDLash_Init( const char *basedir ) void SDLash_Init( void )
{ {
#if XASH_APPLE
char *path = SDL_GetBasePath();
if( path != NULL )
{
char buf[MAX_VA_STRING];
Q_snprintf( buf, sizeof( buf ), "%s%s/extras.pk3", path, basedir );
setenv( "XASH3D_EXTRAS_PAK1", buf, true );
}
#endif
SDL_LogSetOutputFunction( SDLash_LogOutputFunction, NULL ); SDL_LogSetOutputFunction( SDLash_LogOutputFunction, NULL );
if( host_developer.value >= 2 ) if( host_developer.value >= 2 )

View File

@@ -145,7 +145,7 @@ void Wcon_ShowConsole( qboolean show )
void Wcon_DisableInput( void ) void Wcon_DisableInput( void )
{ {
if( host.type != HOST_DEDICATED || !s_wcd.hWnd ) if( host.type != HOST_DEDICATED )
return; return;
s_wcd.inputEnabled = false; s_wcd.inputEnabled = false;
@@ -469,9 +469,6 @@ print into window console
*/ */
void Wcon_WinPrint( const char *pMsg ) void Wcon_WinPrint( const char *pMsg )
{ {
if( !s_wcd.hWnd )
return;
int nLen; int nLen;
if( s_wcd.consoleTextLen ) if( s_wcd.consoleTextLen )
{ {
@@ -518,18 +515,13 @@ void Wcon_CreateConsole( qboolean con_showalways )
} }
s_wcd.attached = ( AttachConsole( ATTACH_PARENT_PROCESS ) != 0 ); s_wcd.attached = ( AttachConsole( ATTACH_PARENT_PROCESS ) != 0 );
if( s_wcd.attached ) if( s_wcd.attached ) {
{
GetConsoleTitle( &s_wcd.previousTitle, sizeof( s_wcd.previousTitle )); GetConsoleTitle( &s_wcd.previousTitle, sizeof( s_wcd.previousTitle ));
s_wcd.previousCodePage = GetConsoleCP(); s_wcd.previousCodePage = GetConsoleCP();
s_wcd.previousOutputCodePage = GetConsoleOutputCP(); s_wcd.previousOutputCodePage = GetConsoleOutputCP();
} }
else else {
{ AllocConsole();
if( host.type != HOST_DEDICATED && host_developer.value == DEV_NONE )
return; // don't initialize console in case of regular game startup, it's useless anyway
else
AllocConsole();
} }
SetConsoleTitle( s_wcd.title ); SetConsoleTitle( s_wcd.title );
@@ -578,7 +570,7 @@ register console commands (dedicated only)
*/ */
void Wcon_InitConsoleCommands( void ) void Wcon_InitConsoleCommands( void )
{ {
if( host.type != HOST_DEDICATED || !s_wcd.hWnd ) if( host.type != HOST_DEDICATED )
return; return;
Cmd_AddCommand( "clear", Wcon_Clear_f, "clear console history" ); Cmd_AddCommand( "clear", Wcon_Clear_f, "clear console history" );
@@ -631,7 +623,7 @@ char *Wcon_Input( void )
DWORD eventsCount; DWORD eventsCount;
static INPUT_RECORD events[1024]; static INPUT_RECORD events[1024];
if( !s_wcd.inputEnabled || !s_wcd.hWnd ) if( !s_wcd.inputEnabled )
return NULL; return NULL;
while( true ) while( true )
@@ -674,7 +666,7 @@ set server status string in console
*/ */
void Platform_SetStatus( const char *pStatus ) void Platform_SetStatus( const char *pStatus )
{ {
if( s_wcd.attached || !s_wcd.hWnd ) if( s_wcd.attached )
return; return;
Q_strncpy( s_wcd.statusLine, pStatus, sizeof( s_wcd.statusLine ) - 1 ); Q_strncpy( s_wcd.statusLine, pStatus, sizeof( s_wcd.statusLine ) - 1 );

View File

@@ -66,7 +66,6 @@ extern int SV_UPDATE_BACKUP;
#define MAX_PUSHED_ENTS 256 #define MAX_PUSHED_ENTS 256
#define MAX_VIEWENTS 128 #define MAX_VIEWENTS 128
#define MAX_LOCALINFO_STRING 32768 // localinfo used on server and not sended to the clients
#define MAX_ENT_LEAFS( ext ) (( ext ) ? MAX_ENT_LEAFS_32 : MAX_ENT_LEAFS_16 ) #define MAX_ENT_LEAFS( ext ) (( ext ) ? MAX_ENT_LEAFS_32 : MAX_ENT_LEAFS_16 )
@@ -499,24 +498,10 @@ qboolean SV_ProcessUserAgent( netadr_t from, const char *useragent );
qboolean SV_InitGame( void ); qboolean SV_InitGame( void );
void SV_ActivateServer( int runPhysics ); void SV_ActivateServer( int runPhysics );
qboolean SV_SpawnServer( const char *server, const char *startspot, qboolean background ); qboolean SV_SpawnServer( const char *server, const char *startspot, qboolean background );
model_t *SV_ModelHandle( int modelindex );
void SV_DeactivateServer( void ); void SV_DeactivateServer( void );
void SV_FreeTestPacket( void ); void SV_FreeTestPacket( void );
/*
================
SV_ModelHandle
get model by handle
================
*/
static inline model_t *GAME_EXPORT SV_ModelHandle( int modelindex )
{
if( modelindex < 0 || modelindex >= MAX_MODELS )
return NULL;
return sv.models[modelindex];
}
// //
// sv_phys.c // sv_phys.c
// //
@@ -688,6 +673,7 @@ void SV_ClearGameState( void );
// sv_pmove.c // sv_pmove.c
// //
void SV_InitClientMove( void ); void SV_InitClientMove( void );
qboolean SV_PlayerIsFrozen( edict_t *pClient );
void SV_RunCmd( sv_client_t *cl, usercmd_t *ucmd, int random_seed ); void SV_RunCmd( sv_client_t *cl, usercmd_t *ucmd, int random_seed );
// //

View File

@@ -305,7 +305,6 @@ static void SV_ConnectClient( netadr_t from )
int challenge; int challenge;
const char *s; const char *s;
int extensions; int extensions;
uint netchan_flags = 0;
if( Cmd_Argc() < 5 ) if( Cmd_Argc() < 5 )
{ {
@@ -432,9 +431,7 @@ static void SV_ConnectClient( netadr_t from )
newcl->listeners = -1; newcl->listeners = -1;
// initailize netchan // initailize netchan
if( !Host_IsLocalClient( )) Netchan_Setup( NS_SERVER, &newcl->netchan, from, qport, newcl, SV_GetFragmentSize, 0 );
SetBits( netchan_flags, NETCHAN_USE_LZSS );
Netchan_Setup( NS_SERVER, &newcl->netchan, from, qport, newcl, SV_GetFragmentSize, netchan_flags );
MSG_Init( &newcl->datagram, "Datagram", newcl->datagram_buf, sizeof( newcl->datagram_buf )); // datagram buf MSG_Init( &newcl->datagram, "Datagram", newcl->datagram_buf, sizeof( newcl->datagram_buf )); // datagram buf
Q_strncpy( newcl->hashedcdkey, Info_ValueForKey( protinfo, "uuid" ), 32 ); Q_strncpy( newcl->hashedcdkey, Info_ValueForKey( protinfo, "uuid" ), 32 );
@@ -453,6 +450,8 @@ static void SV_ConnectClient( netadr_t from )
newcl->delta_sequence = -1; newcl->delta_sequence = -1;
newcl->flags = 0; newcl->flags = 0;
// reset any remaining events // reset any remaining events
memset( &newcl->events, 0, sizeof( newcl->events )); memset( &newcl->events, 0, sizeof( newcl->events ));
@@ -478,7 +477,7 @@ static void SV_ConnectClient( netadr_t from )
// reset stats // reset stats
newcl->next_checkpingtime = -1.0; newcl->next_checkpingtime = -1.0;
newcl->packet_loss = 0; newcl->packet_loss = 0.0f;
// if this was the first client on the server, or the last client // if this was the first client on the server, or the last client
// the server can hold, send a heartbeat to the master. // the server can hold, send a heartbeat to the master.
@@ -1171,7 +1170,7 @@ SV_EstablishTimeBase
Finangles latency and the like. Finangles latency and the like.
=================== ===================
*/ */
static void SV_EstablishTimeBase( sv_client_t *cl, const usercmd_t *cmds, int dropped, int numbackup, int numcmds ) static void SV_EstablishTimeBase( sv_client_t *cl, usercmd_t *cmds, int dropped, int numbackup, int numcmds )
{ {
double runcmd_time = 0.0; double runcmd_time = 0.0;
int i, cmdnum = dropped; int i, cmdnum = dropped;
@@ -2870,20 +2869,14 @@ static qboolean SV_EntCreate_f( sv_client_t *cl )
// XashXT does not implement SV_CreateEntity, use saverestore export // XashXT does not implement SV_CreateEntity, use saverestore export
if( !ent && svgame.physFuncs.pfnCreateEntitiesInRestoreList ) if( !ent && svgame.physFuncs.pfnCreateEntitiesInRestoreList )
{ {
ENTITYTABLE table = { SAVERESTOREDATA data = { 0 };
.classname = classname, ENTITYTABLE table = { 0 };
.id = -1, data.tableCount = 1;
.size = 1, data.pTable = &table;
.flags = 1337, table.classname = classname;
}; table.id = -1;
table.size = 1;
SAVERESTOREDATA data = { svgame.physFuncs.pfnCreateEntitiesInRestoreList( &data, 0, false );
.tableCount = 1,
.pTable = &table
};
svgame.physFuncs.pfnCreateEntitiesInRestoreList( &data, table.flags, false );
ent = table.pent; ent = table.pent;
} }
@@ -3219,20 +3212,6 @@ void SV_ConnectionlessPacket( netadr_t from, sizebuf_t *msg )
} }
} }
static qboolean SV_PlayerIsFrozen( const edict_t *pClient )
{
if( sv_background_freeze.value && sv.background )
return true;
if( FBitSet( host.features, ENGINE_QUAKE_COMPATIBLE ))
return false;
if( FBitSet( pClient->v.flags, FL_FROZEN ))
return true;
return false;
}
/* /*
================== ==================
SV_ParseClientMove SV_ParseClientMove
@@ -3247,20 +3226,29 @@ each of the backup packets.
*/ */
static void SV_ParseClientMove( sv_client_t *cl, sizebuf_t *msg ) static void SV_ParseClientMove( sv_client_t *cl, sizebuf_t *msg )
{ {
const usercmd_t nullcmd = { 0 }, *from = &nullcmd; // first cmd are starting from null-compressed usercmd_t client_frame_t *frame;
client_frame_t *frame = &cl->frames[cl->netchan.incoming_acknowledged & SV_UPDATE_MASK]; int key, size, checksum1, checksum2;
usercmd_t cmds[CMD_BACKUP] = { 0 }, *to; int i, numbackup, totalcmds, numcmds;
edict_t *player = cl->edict; usercmd_t nullcmd, *to, *from;
model_t *model; usercmd_t cmds[CMD_BACKUP];
float packet_loss;
edict_t *player;
model_t *model;
int key = MSG_GetRealBytesRead( msg ); player = cl->edict;
int checksum1 = MSG_ReadByte( msg );
int packet_loss = MSG_ReadByte( msg );
int numbackup = MSG_ReadByte( msg );
int numcmds = MSG_ReadByte( msg );
int totalcmds = numcmds + numbackup;
int i;
frame = &cl->frames[cl->netchan.incoming_acknowledged & SV_UPDATE_MASK];
memset( &nullcmd, 0, sizeof( usercmd_t ));
memset( cmds, 0, sizeof( cmds ));
key = MSG_GetRealBytesRead( msg );
checksum1 = MSG_ReadByte( msg );
packet_loss = MSG_ReadByte( msg );
numbackup = MSG_ReadByte( msg );
numcmds = MSG_ReadByte( msg );
totalcmds = numcmds + numbackup;
net_drop -= (numcmds - 1); net_drop -= (numcmds - 1);
if( totalcmds < 0 || totalcmds >= CMD_MASK ) if( totalcmds < 0 || totalcmds >= CMD_MASK )
@@ -3270,6 +3258,8 @@ static void SV_ParseClientMove( sv_client_t *cl, sizebuf_t *msg )
return; return;
} }
from = &nullcmd; // first cmd are starting from null-compressed usercmd_t
for( i = totalcmds - 1; i >= 0; i-- ) for( i = totalcmds - 1; i >= 0; i-- )
{ {
to = &cmds[i]; to = &cmds[i];
@@ -3280,17 +3270,14 @@ static void SV_ParseClientMove( sv_client_t *cl, sizebuf_t *msg )
if( cl->state != cs_spawned ) if( cl->state != cs_spawned )
return; return;
if( !Host_IsLocalClient( )) // if the checksum fails, ignore the rest of the packet
{ size = MSG_GetRealBytesRead( msg ) - key - 1;
// if the checksum fails, ignore the rest of the packet checksum2 = CRC32_BlockSequence( msg->pData + key + 1, size, cl->netchan.incoming_sequence );
int size = MSG_GetRealBytesRead( msg ) - key - 1;
int checksum2 = CRC32_BlockSequence( msg->pData + key + 1, size, cl->netchan.incoming_sequence );
if( checksum2 != checksum1 ) if( checksum2 != checksum1 )
{ {
Con_Reportf( S_ERROR "%s: failed command checksum for %s (%d != %d)\n", __func__, cl->name, checksum2, checksum1 ); Con_Reportf( S_ERROR "%s: failed command checksum for %s (%d != %d)\n", __func__, cl->name, checksum2, checksum1 );
return; return;
}
} }
cl->packet_loss = packet_loss; cl->packet_loss = packet_loss;

View File

@@ -492,15 +492,14 @@ SV_EmitPings
*/ */
static void SV_EmitPings( sizebuf_t *msg ) static void SV_EmitPings( sizebuf_t *msg )
{ {
sv_client_t *cl; sv_client_t *cl;
int i; int packet_loss;
int i, ping;
MSG_BeginServerCmd( msg, svc_pings ); MSG_BeginServerCmd( msg, svc_pings );
for( i = 0, cl = svs.clients; i < svs.maxclients; i++, cl++ ) for( i = 0, cl = svs.clients; i < svs.maxclients; i++, cl++ )
{ {
int packet_loss, ping;
if( cl->state != cs_spawned ) if( cl->state != cs_spawned )
continue; continue;

View File

@@ -273,6 +273,20 @@ int GAME_EXPORT SV_GenericIndex( const char *filename )
return i; return i;
} }
/*
================
SV_ModelHandle
get model by handle
================
*/
model_t *GAME_EXPORT SV_ModelHandle( int modelindex )
{
if( modelindex < 0 || modelindex >= MAX_MODELS )
return NULL;
return sv.models[modelindex];
}
static resourcetype_t SV_DetermineResourceType( const char *filename ) static resourcetype_t SV_DetermineResourceType( const char *filename )
{ {
if( !Q_strncmp( filename, DEFAULT_SOUNDPATH, sizeof( DEFAULT_SOUNDPATH ) - 1 ) && Sound_SupportedFileFormat( COM_FileExtension( filename ))) if( !Q_strncmp( filename, DEFAULT_SOUNDPATH, sizeof( DEFAULT_SOUNDPATH ) - 1 ) && Sound_SupportedFileFormat( COM_FileExtension( filename )))

View File

@@ -23,6 +23,19 @@ GNU General Public License for more details.
static qboolean has_update = false; static qboolean has_update = false;
static void SV_GetTrueOrigin( sv_client_t *cl, int edictnum, vec3_t origin ); static void SV_GetTrueOrigin( sv_client_t *cl, int edictnum, vec3_t origin );
qboolean SV_PlayerIsFrozen( edict_t *pClient )
{
if( sv_background_freeze.value && sv.background )
return true;
if( FBitSet( host.features, ENGINE_QUAKE_COMPATIBLE ))
return false;
if( FBitSet( pClient->v.flags, FL_FROZEN ))
return true;
return false;
}
void SV_ClipPMoveToEntity( physent_t *pe, const vec3_t start, vec3_t mins, vec3_t maxs, const vec3_t end, pmtrace_t *tr ) void SV_ClipPMoveToEntity( physent_t *pe, const vec3_t start, vec3_t mins, vec3_t maxs, const vec3_t end, pmtrace_t *tr )
{ {
Assert( tr != NULL ); Assert( tr != NULL );

View File

@@ -2279,7 +2279,7 @@ int GAME_EXPORT SV_GetSaveComment( const char *savename, char *comment )
if( tag == 0x0065 ) if( tag == 0x0065 )
{ {
Q_strncpy( comment, "<old version "XASH_ENGINE_NAME" unsupported>", MAX_STRING ); Q_strncpy( comment, "<old version Xash3D unsupported>", MAX_STRING );
FS_Close( f ); FS_Close( f );
return 0; return 0;
} }

View File

@@ -8,23 +8,6 @@ import os
top = '.' top = '.'
FFMPEG_CHECK_FRAGMENT='''
#include <libswresample/swresample.h>
#include <libavformat/avformat.h>
#include <libavcodec/avcodec.h>
#include <libswscale/swscale.h>
#include <libavutil/avutil.h>
int main(int argc, char **argv)
{
swresample_version();
avformat_version();
avcodec_version();
swscale_version();
avutil_version();
return 0;
}
'''
def options(opt): def options(opt):
grp = opt.add_option_group('Engine options') grp = opt.add_option_group('Engine options')
@@ -52,9 +35,6 @@ def options(opt):
grp.add_option('--enable-ffmpeg', action = 'store_true', dest = 'FFMPEG', default = False, grp.add_option('--enable-ffmpeg', action = 'store_true', dest = 'FFMPEG', default = False,
help = '') # hidden option, does nothing help = '') # hidden option, does nothing
grp.add_option('--enable-ffmpeg', action = 'store_true', dest = 'FFMPEG', default = False,
help = 'enable ffmpeg based movie playback')
opt.load('sdl2') opt.load('sdl2')
def configure(conf): def configure(conf):
@@ -145,20 +125,6 @@ def configure(conf):
conf.define('ENGINE_DLL', 1) conf.define('ENGINE_DLL', 1)
if conf.options.FFMPEG:
# add ffmpeg libraries into single uselib package
conf.check_cfg(package='libswresample', uselib_store='SWRESAMPLE', args='--cflags --libs')
conf.check_cfg(package='libavformat', uselib_store='AVFORMAT', args='--cflags --libs')
conf.check_cfg(package='libavcodec', uselib_store='AVCODEC', args='--cflags --libs')
conf.check_cfg(package='libswscale', uselib_store='SWSCALE', args='--cflags --libs')
conf.check_cfg(package='libavutil', uselib_store='AVUTIL', args='--cflags --libs')
# validate ffmpeg libs installation
conf.check_cc(fragment=FFMPEG_CHECK_FRAGMENT, use='SWRESAMPLE AVCODEC AVFORMAT AVUTIL SWSCALE', msg='Checking for ffmpeg sanity')
conf.env.FFMPEG = True
conf.define('HAVE_FFMPEG', True)
conf.define_cond('XASH_ENGINE_TESTS', conf.env.ENGINE_TESTS) conf.define_cond('XASH_ENGINE_TESTS', conf.env.ENGINE_TESTS)
conf.define_cond('XASH_STATIC_LIBS', conf.env.STATIC_LINKING) conf.define_cond('XASH_STATIC_LIBS', conf.env.STATIC_LINKING)
conf.define_cond('XASH_CUSTOM_SWAP', conf.options.CUSTOM_SWAP) conf.define_cond('XASH_CUSTOM_SWAP', conf.options.CUSTOM_SWAP)
@@ -219,13 +185,6 @@ def build(bld):
libs.append('SDL3' if bld.env.HAVE_SDL3 else 'SDL2') libs.append('SDL3' if bld.env.HAVE_SDL3 else 'SDL2')
source += bld.path.ant_glob(['platform/sdl/*.c']) source += bld.path.ant_glob(['platform/sdl/*.c'])
if bld.get_define('HAVE_FFMPEG'):
libs.append('SWRESAMPLE')
libs.append('AVCODEC')
libs.append('AVFORMAT')
libs.append('AVUTIL')
libs.append('SWSCALE')
if bld.env.MAGX: if bld.env.MAGX:
libs.append('MAGX') libs.append('MAGX')
is_cxx_link = True is_cxx_link = True

View File

@@ -242,7 +242,7 @@ static byte *FS_LoadAndroidAssetsFile( searchpath_t *search, const char *path, i
if( filesize ) *filesize = 0; if( filesize ) *filesize = 0;
asset = AAssetManager_open( search->assets->asset_manager, path, AASSET_MODE_BUFFER ); asset = AAssetManager_open( search->assets->asset_manager, path, AASSET_MODE_RANDOM );
if( !asset ) if( !asset )
return NULL; return NULL;

View File

@@ -49,7 +49,6 @@ GNU General Public License for more details.
#include "common/protocol.h" #include "common/protocol.h"
#define FILE_COPY_SIZE (1024 * 1024) #define FILE_COPY_SIZE (1024 * 1024)
#define SAVE_AGED_COUNT 2 // the default count of quick and auto saves
fs_globals_t FI; fs_globals_t FI;
qboolean fs_ext_path = false; // attempt to read\write from ./ or ../ pathes qboolean fs_ext_path = false; // attempt to read\write from ./ or ../ pathes
@@ -448,7 +447,6 @@ FS_ClearSearchPath
void FS_ClearSearchPath( void ) void FS_ClearSearchPath( void )
{ {
searchpath_t *cur, **prev; searchpath_t *cur, **prev;
int i;
prev = &fs_searchpaths; prev = &fs_searchpaths;
@@ -470,12 +468,6 @@ void FS_ClearSearchPath( void )
cur->pfnClose( cur ); cur->pfnClose( cur );
Mem_Free( cur ); Mem_Free( cur );
} }
for( i = 0; i < FI.numgames; i++ )
{
if( FI.games[i] )
FI.games[i]->added = false;
}
} }
/* /*
@@ -636,11 +628,13 @@ static qboolean FS_WriteGameInfo( const char *filepath, gameinfo_t *GameInfo )
if( GameInfo->noskills ) if( GameInfo->noskills )
FS_Printf( f, "noskills\t\t\"%i\"\n", GameInfo->noskills ); FS_Printf( f, "noskills\t\t\"%i\"\n", GameInfo->noskills );
#define SAVE_AGED_COUNT 2 // the default count of quick and auto saves
if( GameInfo->quicksave_aged_count != SAVE_AGED_COUNT ) if( GameInfo->quicksave_aged_count != SAVE_AGED_COUNT )
FS_Printf( f, "quicksave_aged_count\t\t%d\n", GameInfo->quicksave_aged_count ); FS_Printf( f, "quicksave_aged_count\t\t%d\n", GameInfo->quicksave_aged_count );
if( GameInfo->autosave_aged_count != SAVE_AGED_COUNT ) if( GameInfo->autosave_aged_count != SAVE_AGED_COUNT )
FS_Printf( f, "autosave_aged_count\t\t%d\n", GameInfo->autosave_aged_count ); FS_Printf( f, "autosave_aged_count\t\t%d\n", GameInfo->autosave_aged_count );
#undef SAVE_AGED_COUNT
// HL25 compatibility // HL25 compatibility
if( GameInfo->animated_title ) if( GameInfo->animated_title )
@@ -706,9 +700,6 @@ static void FS_InitGameInfo( gameinfo_t *GameInfo, const char *gamedir, qboolean
GameInfo->max_beams = 128; GameInfo->max_beams = 128;
GameInfo->max_particles = 4096; GameInfo->max_particles = 4096;
GameInfo->version = 1.0f; GameInfo->version = 1.0f;
GameInfo->quicksave_aged_count = SAVE_AGED_COUNT;
GameInfo->autosave_aged_count = SAVE_AGED_COUNT;
} }
static void FS_ParseGenericGameInfo( gameinfo_t *GameInfo, const char *buf, const qboolean isGameInfo ) static void FS_ParseGenericGameInfo( gameinfo_t *GameInfo, const char *buf, const qboolean isGameInfo )
@@ -1129,7 +1120,7 @@ static qboolean FS_ParseGameInfo( const char *gamedir, gameinfo_t *GameInfo, qbo
if( rodir ) if( rodir )
Q_snprintf( gamedir_path, sizeof( gamedir_path ), "%s/%s", fs_rodir, gamedir ); Q_snprintf( gamedir_path, sizeof( gamedir_path ), "%s/%s", fs_rodir, gamedir );
else else
Q_snprintf( gamedir_path, sizeof( gamedir_path ), "%s", gamedir ); Q_snprintf( gamedir_path, sizeof( gamedir_path ), "%s/%s", fs_rootdir, gamedir );
if( !FS_CheckForXashGameDir( gamedir_path )) if( !FS_CheckForXashGameDir( gamedir_path ))
{ {
@@ -1199,11 +1190,11 @@ void FS_AddGameHierarchy( const char *dir, uint flags )
qboolean isGameDir = flags & FS_GAMEDIR_PATH; qboolean isGameDir = flags & FS_GAMEDIR_PATH;
char buf[MAX_VA_STRING]; char buf[MAX_VA_STRING];
GI->added = true;
if( !COM_CheckString( dir )) if( !COM_CheckString( dir ))
return; return;
Con_Printf( "%s( %s )\n", __func__, dir );
// add the common game directory // add the common game directory
// recursive gamedirs // recursive gamedirs
@@ -1214,21 +1205,12 @@ void FS_AddGameHierarchy( const char *dir, uint flags )
{ {
dir = FI.games[i]->gamefolder; // fixup directory case dir = FI.games[i]->gamefolder; // fixup directory case
if( FI.games[i]->added ) // already added, refusing
break;
// don't add our game directory as base dir to prevent cyclic dependency
if( Q_stricmp( FI.games[i]->basedir, GI->gamefolder ))
break;
// don't add directory which basedir is equal to this gamefolder to prevent
// endless loop
if( Q_stricmp( FI.games[i]->basedir, FI.games[i]->gamefolder ))
break;
Con_Reportf( "%s: adding recursive basedir %s\n", __func__, FI.games[i]->basedir ); Con_Reportf( "%s: adding recursive basedir %s\n", __func__, FI.games[i]->basedir );
FI.games[i]->added = true; if( !FI.games[i]->added && Q_stricmp( FI.games[i]->gamefolder, FI.games[i]->basedir ))
FS_AddGameHierarchy( FI.games[i]->basedir, flags & (~FS_GAMEDIR_PATH)); {
FI.games[i]->added = true;
FS_AddGameHierarchy( FI.games[i]->basedir, flags & (~FS_GAMEDIR_PATH) );
}
break; break;
} }
} }
@@ -1285,8 +1267,6 @@ void FS_Rescan( void )
FS_AddGameHierarchy( GI->basedir, 0 ); FS_AddGameHierarchy( GI->basedir, 0 );
if( Q_stricmp( GI->basedir, GI->falldir ) && Q_stricmp( GI->gamefolder, GI->falldir )) if( Q_stricmp( GI->basedir, GI->falldir ) && Q_stricmp( GI->gamefolder, GI->falldir ))
FS_AddGameHierarchy( GI->falldir, 0 ); FS_AddGameHierarchy( GI->falldir, 0 );
GI->added = true;
FS_AddGameHierarchy( GI->gamefolder, FS_GAMEDIR_PATH ); FS_AddGameHierarchy( GI->gamefolder, FS_GAMEDIR_PATH );
} }
@@ -2242,12 +2222,6 @@ int FS_Close( file_t *file )
return EOF; return EOF;
} }
if( file->ztk )
{
inflateEnd( &file->ztk->zstream );
Mem_Free( file->ztk );
}
Mem_Free( file ); Mem_Free( file );
return 0; return 0;
} }
@@ -2353,93 +2327,7 @@ fs_offset_t FS_Read( file_t *file, void *buffer, size_t buffersize )
// NOTE: at this point, the read buffer is always empty // NOTE: at this point, the read buffer is always empty
FS_EnsureOpenFile( file ); // FIXME: broken XASH_REDUCE_FD in case of compressed files! FS_EnsureOpenFile( file );
if( FBitSet( file->flags, FILE_DEFLATED ))
{
// If the file is compressed, it's more complicated...
// We cycle through a few operations until we have read enough data
while( buffersize > 0 )
{
ztoolkit_t *ztk = file->ztk;
int error;
// NOTE: at this point, the read buffer is always empty
// If "input" is also empty, we need to refill it
if( ztk->in_ind == ztk->in_len )
{
// If we are at the end of the file
if( file->position == file->real_length )
return done;
count = (fs_offset_t)( ztk->comp_length - ztk->in_position );
if( count > (fs_offset_t)sizeof( ztk->input ))
count = (fs_offset_t)sizeof( ztk->input );
lseek( file->handle, file->offset + (fs_offset_t)ztk->in_position, SEEK_SET );
if( read( file->handle, ztk->input, count ) != count )
{
Con_Printf( "%s: unexpected end of file\n", __func__ );
break;
}
ztk->in_ind = 0;
ztk->in_len = count;
ztk->in_position += count;
}
ztk->zstream.next_in = &ztk->input[ztk->in_ind];
ztk->zstream.avail_in = (unsigned int)( ztk->in_len - ztk->in_ind );
// Now that we are sure we have compressed data available, we need to determine
// if it's better to inflate it in "file->buff" or directly in "buffer"
// Inflate the data in "file->buff"
if( buffersize < sizeof( file->buff ) / 2 )
{
ztk->zstream.next_out = file->buff;
ztk->zstream.avail_out = sizeof( file->buff );
}
else
{
ztk->zstream.next_out = &((unsigned char*)buffer)[done];
ztk->zstream.avail_out = (unsigned int)buffersize;
}
error = inflate( &ztk->zstream, Z_SYNC_FLUSH );
if( error != Z_OK && error != Z_STREAM_END )
{
Con_Printf( "%s: Can't inflate file (%d)\n", __func__, error );
break;
}
ztk->in_ind = ztk->in_len - ztk->zstream.avail_in;
if( buffersize < sizeof( file->buff ) / 2 )
{
file->buff_len = (fs_offset_t)sizeof( file->buff ) - ztk->zstream.avail_out;
file->position += file->buff_len;
// Copy the requested data in "buffer" (as much as we can)
count = (fs_offset_t)buffersize > file->buff_len ? file->buff_len : (fs_offset_t)buffersize;
memcpy( &((unsigned char*)buffer)[done], file->buff, count );
file->buff_ind = count;
}
else
{
count = (fs_offset_t)( buffersize - ztk->zstream.avail_out );
file->position += count;
// Purge cached data
FS_Purge( file );
}
done += count;
buffersize -= count;
}
return done;
}
// we must take care to not read after the end of the file // we must take care to not read after the end of the file
count = file->real_length - file->position; count = file->real_length - file->position;
@@ -2655,59 +2543,11 @@ int FS_Seek( file_t *file, fs_offset_t offset, int whence )
// Purge cached data // Purge cached data
FS_Purge( file ); FS_Purge( file );
if( FBitSet( file->flags, FILE_DEFLATED ))
{
// Seeking in compressed files is more a hack than anything else,
// but we need to support it, so here we go.
ztoolkit_t *ztk = file->ztk;
unsigned char *buffer;
fs_offset_t buffersize;
// If we have to go back in the file, we need to restart from the beginning
if( offset <= file->position )
{
ztk->in_ind = 0;
ztk->in_len = 0;
ztk->in_position = 0;
file->position = 0;
if( lseek( file->handle, file->offset, SEEK_SET ) == -1 )
Con_Printf("IMPOSSIBLE: couldn't seek in already opened pk3 file.\n");
// Reset the Zlib stream
ztk->zstream.next_in = ztk->input;
ztk->zstream.avail_in = 0;
inflateReset( &ztk->zstream );
}
// We need a big buffer to force inflating into it directly
buffersize = 2 * sizeof( file->buff );
buffer = (unsigned char *)Mem_Malloc( fs_mempool, buffersize );
// Skip all data until we reach the requested offset
while( offset > ( file->position - file->buff_len + file->buff_ind ))
{
fs_offset_t diff = offset - ( file->position - file->buff_len + file->buff_ind );
fs_offset_t count;
count = ( diff > buffersize ) ? buffersize : diff;
if( FS_Read( file, buffer, count ) != count )
{
Mem_Free( buffer );
return -1;
}
}
Mem_Free( buffer );
return 0;
}
if( lseek( file->handle, file->offset + offset, SEEK_SET ) == -1 ) if( lseek( file->handle, file->offset + offset, SEEK_SET ) == -1 )
return -1; return -1;
file->position = offset; file->position = offset;
return 0; return 0;
} }
/* /*
@@ -2865,20 +2705,25 @@ qboolean CRC32_File( dword *crcvalue, const char *filename )
qboolean MD5_HashFile( byte digest[16], const char *pszFileName, uint seed[4] ) qboolean MD5_HashFile( byte digest[16], const char *pszFileName, uint seed[4] )
{ {
file_t *file; file_t *file;
MD5Context_t MD5_Hash = { 0 }; byte buffer[1024];
MD5Context_t MD5_Hash;
int bytes;
if(( file = FS_Open( pszFileName, "rb", false )) == NULL ) if(( file = FS_Open( pszFileName, "rb", false )) == NULL )
return false; return false;
memset( &MD5_Hash, 0, sizeof( MD5Context_t ));
MD5Init( &MD5_Hash ); MD5Init( &MD5_Hash );
if( seed ) if( seed )
{
MD5Update( &MD5_Hash, (const byte *)seed, 16 ); MD5Update( &MD5_Hash, (const byte *)seed, 16 );
}
while( 1 ) while( 1 )
{ {
byte buffer[1024]; bytes = FS_Read( file, buffer, sizeof( buffer ));
int bytes = FS_Read( file, buffer, sizeof( buffer ));
if( bytes > 0 ) if( bytes > 0 )
MD5Update( &MD5_Hash, buffer, bytes ); MD5Update( &MD5_Hash, buffer, bytes );

View File

@@ -143,8 +143,6 @@ typedef struct fs_globals_t
int numgames; int numgames;
} fs_globals_t; } fs_globals_t;
typedef struct file_s file_t;
typedef struct fs_api_t typedef struct fs_api_t
{ {
qboolean (*InitStdio)( qboolean unused_set_to_true, const char *rootdir, const char *basedir, const char *gamedir, const char *rodir ); qboolean (*InitStdio)( qboolean unused_set_to_true, const char *rootdir, const char *basedir, const char *gamedir, const char *rodir );

View File

@@ -22,7 +22,6 @@ GNU General Public License for more details.
#include <stdlib.h> #include <stdlib.h>
#include "xash3d_types.h" #include "xash3d_types.h"
#include "filesystem.h" #include "filesystem.h"
#include "miniz.h"
#if XASH_ANDROID #if XASH_ANDROID
#include <android/asset_manager.h> #include <android/asset_manager.h>
@@ -41,16 +40,6 @@ typedef struct wfile_s wfile_t;
typedef struct android_assets_s android_assets_t; typedef struct android_assets_s android_assets_t;
#define FILE_BUFF_SIZE (2048) #define FILE_BUFF_SIZE (2048)
#define FILE_DEFLATED BIT( 0 )
typedef struct ztoolkit_s
{
z_stream zstream;
size_t comp_length;
size_t in_ind, in_len;
size_t in_position;
byte input[FILE_BUFF_SIZE];
} ztoolkit_t;
struct file_s struct file_s
{ {
@@ -61,9 +50,7 @@ struct file_s
fs_offset_t real_length; // uncompressed file size (for files opened in "read" mode) fs_offset_t real_length; // uncompressed file size (for files opened in "read" mode)
fs_offset_t position; // current position in the file fs_offset_t position; // current position in the file
fs_offset_t offset; // offset into the package (0 if external file) fs_offset_t offset; // offset into the package (0 if external file)
uint32_t flags;
ztoolkit_t *ztk; // if not NULL, all read functions must go through decompression
// contents buffer // contents buffer
fs_offset_t buff_ind; // buffer current index fs_offset_t buff_ind; // buffer current index
fs_offset_t buff_len; // buffer current length fs_offset_t buff_len; // buffer current length

View File

@@ -92,19 +92,20 @@ struct wfile_s
typedef struct wadtype_s typedef struct wadtype_s
{ {
char ext[4]; const char *ext;
signed char type; signed char type;
} wadtype_t; } wadtype_t;
// associate extension with wad type // associate extension with wad type
static const wadtype_t wad_types[] = static const wadtype_t wad_types[7] =
{ {
{ "pal", TYP_PALETTE }, // palette { "pal", TYP_PALETTE }, // palette
{ "dds", TYP_DDSTEX }, // DDS image { "dds", TYP_DDSTEX }, // DDS image
{ "lmp", TYP_GFXPIC }, // quake1, hl pic { "lmp", TYP_GFXPIC }, // quake1, hl pic
{ "fnt", TYP_QFONT }, // hl qfonts { "fnt", TYP_QFONT }, // hl qfonts
{ "mip", TYP_MIPTEX }, // hl/q1 mip { "mip", TYP_MIPTEX }, // hl/q1 mip
{ "txt", TYP_SCRIPT }, // scripts { "txt", TYP_SCRIPT }, // scripts
{ NULL, TYP_NONE }
}; };
/* /*
@@ -116,19 +117,18 @@ Extracts file type from extension
*/ */
static signed char W_TypeFromExt( const char *lumpname ) static signed char W_TypeFromExt( const char *lumpname )
{ {
const char *ext = COM_FileExtension( lumpname ); const char *ext = COM_FileExtension( lumpname );
int i; const wadtype_t *type;
// we not known about filetype, so match only by filename // we not known about filetype, so match only by filename
if( !Q_strcmp( ext, "*" ) || !COM_CheckStringEmpty( ext )) if( !Q_strcmp( ext, "*" ) || !COM_CheckStringEmpty( ext ))
return TYP_ANY; return TYP_ANY;
for( i = 0; i < sizeof( wad_types ) / sizeof( wad_types[0] ); i++ ) for( type = wad_types; type->ext; type++ )
{ {
if( !Q_stricmp( ext, wad_types[i].ext )) if( !Q_stricmp( ext, type->ext ))
return wad_types[i].type; return type->type;
} }
return TYP_NONE; return TYP_NONE;
} }
@@ -141,18 +141,17 @@ Convert type to extension
*/ */
static const char *W_ExtFromType( signed char lumptype ) static const char *W_ExtFromType( signed char lumptype )
{ {
int i; const wadtype_t *type;
// we not known aboyt filetype, so match only by filename // we not known aboyt filetype, so match only by filename
if( lumptype == TYP_NONE || lumptype == TYP_ANY ) if( lumptype == TYP_NONE || lumptype == TYP_ANY )
return ""; return "";
for( i = 0; i < sizeof( wad_types ) / sizeof( wad_types[0] ); i++ ) for( type = wad_types; type->ext; type++ )
{ {
if( lumptype == wad_types[i].type ) if( lumptype == type->type )
return wad_types[i].ext; return type->ext;
} }
return ""; return "";
} }

View File

@@ -27,6 +27,7 @@ GNU General Public License for more details.
#include "filesystem_internal.h" #include "filesystem_internal.h"
#include "crtlib.h" #include "crtlib.h"
#include "common/com_strings.h" #include "common/com_strings.h"
#include "miniz.h"
#define ZIP_HEADER_LF (('K'<<8)+('P')+(0x03<<16)+(0x04<<24)) #define ZIP_HEADER_LF (('K'<<8)+('P')+(0x03<<16)+(0x04<<24))
#define ZIP_HEADER_SPANNED ((0x08<<24)+(0x07<<16)+('K'<<8)+'P') #define ZIP_HEADER_SPANNED ((0x08<<24)+(0x07<<16)+('K'<<8)+'P')
@@ -388,43 +389,15 @@ Open a packed file using its package file descriptor
static file_t *FS_OpenFile_ZIP( searchpath_t *search, const char *filename, const char *mode, int pack_ind ) static file_t *FS_OpenFile_ZIP( searchpath_t *search, const char *filename, const char *mode, int pack_ind )
{ {
zipfile_t *pfile = &search->zip->files[pack_ind]; zipfile_t *pfile = &search->zip->files[pack_ind];
file_t *f = FS_OpenHandle( search, search->zip->handle->handle, pfile->offset, pfile->size );
if( !f ) // compressed files handled in Zip_LoadFile
return NULL; if( pfile->flags != ZIP_COMPRESSION_NO_COMPRESSION )
if( pfile->flags == ZIP_COMPRESSION_DEFLATED )
{ {
ztoolkit_t *ztk; Con_Printf( S_ERROR "%s: can't open compressed file %s\n", __func__, pfile->name );
SetBits( f->flags, FILE_DEFLATED );
ztk = Mem_Calloc( fs_mempool, sizeof( *ztk ));
ztk->comp_length = pfile->compressed_size;
ztk->zstream.next_in = ztk->input;
ztk->zstream.avail_in = 0;
if( inflateInit2( &ztk->zstream, -MAX_WBITS ) != Z_OK )
{
Con_Printf( "%s: inflate init error (file: %s)\n", __func__, filename );
FS_Close( f );
Mem_Free( ztk );
return NULL;
}
ztk->zstream.next_out = f->buff;
ztk->zstream.avail_out = sizeof( f->buff );
f->ztk = ztk;
}
else if( pfile->flags != ZIP_COMPRESSION_NO_COMPRESSION )
{
Con_Reportf( S_ERROR "%s: %s: file compressed with unknown algorithm.\n", __func__, filename );
FS_Close( f );
return NULL; return NULL;
} }
return f; return FS_OpenHandle( search, search->zip->handle->handle, pfile->offset, pfile->size );
} }
/* /*

View File

@@ -33,6 +33,26 @@ void Q_strnlwr( const char *in, char *out, size_t size_out )
out[i] = Q_tolower( out[i] ); out[i] = Q_tolower( out[i] );
} }
size_t Q_colorstr( const char *string )
{
const char *p = string;
size_t len = 0;
if( !string )
return len;
while(( p = Q_strchr( p, '^' )))
{
if( IsColorString( p ))
{
len += 2;
p += 2;
}
}
return len;
}
int Q_atoi_hex( int sign, const char *str ) int Q_atoi_hex( int sign, const char *str )
{ {
int c, val = 0; int c, val = 0;

View File

@@ -70,6 +70,7 @@ extern const char *g_buildbranch;
// //
void Q_strnlwr( const char *in, char *out, size_t size_out ); void Q_strnlwr( const char *in, char *out, size_t size_out );
#define Q_strlen( str ) (( str ) ? strlen(( str )) : 0 ) #define Q_strlen( str ) (( str ) ? strlen(( str )) : 0 )
size_t Q_colorstr( const char *string );
int Q_atoi_hex( int sign, const char *str ); int Q_atoi_hex( int sign, const char *str );
int Q_atoi( const char *str ); int Q_atoi( const char *str );
float Q_atof( const char *str ); float Q_atof( const char *str );
@@ -107,12 +108,6 @@ int matchpattern_with_separator( const char *in, const char *pattern, qboolean c
// //
// dllhelpers.c // dllhelpers.c
// //
typedef struct dllfunc_s
{
const char *name;
void **func;
} dllfunc_t;
void ClearExports( const dllfunc_t *funcs, size_t num_funcs ); void ClearExports( const dllfunc_t *funcs, size_t num_funcs );
qboolean ValidateExports( const dllfunc_t *funcs, size_t num_funcs ); qboolean ValidateExports( const dllfunc_t *funcs, size_t num_funcs );

View File

@@ -46,6 +46,17 @@ static int Test_Strnlwr( void )
return 0; return 0;
} }
static int Test_Colorstr( void )
{
if( Q_colorstr( "^1color^2string" ) != 4 )
return 1;
if( Q_colorstr( "colorlessstring" ) != 0 )
return 2;
return 0;
}
static int Test_FixSlashes( void ) static int Test_FixSlashes( void )
{ {
string s = "path\\with\\back\\slashes"; string s = "path\\with\\back\\slashes";
@@ -82,6 +93,11 @@ int main( void )
if( ret > 0 ) if( ret > 0 )
return ret + 16; return ret + 16;
ret = Test_Colorstr();
if( ret > 0 )
return ret + 32;
ret = Test_FixSlashes(); ret = Test_FixSlashes();
if( ret > 0 ) if( ret > 0 )

View File

@@ -185,7 +185,7 @@ int BoxOnPlaneSide( const vec3_t emins, const vec3_t emaxs, const mplane_t *p );
// //
static inline void Matrix3x4_LoadIdentity( matrix3x4 m ) static inline void Matrix3x4_LoadIdentity( matrix3x4 m )
{ {
memset( m, 0, sizeof( matrix3x4 )); memset( m, 0, sizeof( *m ));
m[0][0] = m[1][1] = m[2][2] = 1.0f; m[0][0] = m[1][1] = m[2][2] = 1.0f;
} }
#define Matrix3x4_Copy( out, in ) memcpy( out, in, sizeof( matrix3x4 )) #define Matrix3x4_Copy( out, in ) memcpy( out, in, sizeof( matrix3x4 ))
@@ -201,7 +201,7 @@ void Matrix3x4_AnglesFromMatrix( const matrix3x4 in, vec3_t out );
static inline void Matrix4x4_LoadIdentity( matrix4x4 m ) static inline void Matrix4x4_LoadIdentity( matrix4x4 m )
{ {
memset( m, 0, sizeof( matrix4x4 )); memset( m, 0, sizeof( *m ));
m[0][0] = m[1][1] = m[2][2] = m[3][3] = 1.0f; m[0][0] = m[1][1] = m[2][2] = m[3][3] = 1.0f;
} }
#define Matrix4x4_Copy( out, in ) memcpy( out, in, sizeof( matrix4x4 )) #define Matrix4x4_Copy( out, in ) memcpy( out, in, sizeof( matrix4x4 ))

View File

@@ -88,13 +88,11 @@ static void Mod_BrushUnloadTextures( model_t *mod )
for( i = 0; i < mod->numtextures; i++ ) for( i = 0; i < mod->numtextures; i++ )
{ {
texture_t *tx = mod->textures[i]; texture_t *tx = mod->textures[i];
if( !tx ) if( !tx || tx->gl_texturenum == tr.defaultTexture )
continue; // free slot continue; // free slot
if( tx->gl_texturenum != tr.defaultTexture ) GL_FreeTexture( tx->gl_texturenum ); // main texture
GL_FreeTexture( tx->gl_texturenum ); // main texture GL_FreeTexture( tx->fb_texturenum ); // luma texture
GL_FreeTexture( tx->fb_texturenum ); // luma texture
GL_FreeTexture( tx->dt_texturenum ); // detail texture
} }
} }
@@ -124,35 +122,33 @@ static void Mod_UnloadTextures( model_t *mod )
static qboolean Mod_ProcessRenderData( model_t *mod, qboolean create, const byte *buf ) static qboolean Mod_ProcessRenderData( model_t *mod, qboolean create, const byte *buf )
{ {
qboolean loaded = false; qboolean loaded = true;
if( create )
{
switch( mod->type )
{
case mod_studio:
// Mod_LoadStudioModel( mod, buf, loaded );
break;
case mod_sprite:
Mod_LoadSpriteModel( mod, buf, &loaded, mod->numtexinfo );
break;
case mod_alias:
Mod_LoadAliasModel( mod, buf, &loaded );
break;
case mod_brush:
// Mod_LoadBrushModel( mod, buf, loaded );
break;
default: gEngfuncs.Host_Error( "%s: unsupported type %d\n", __func__, mod->type );
}
}
if( loaded && gEngfuncs.drawFuncs->Mod_ProcessUserData )
gEngfuncs.drawFuncs->Mod_ProcessUserData( mod, create, buf );
if( !create ) if( !create )
{
if( gEngfuncs.drawFuncs->Mod_ProcessUserData )
gEngfuncs.drawFuncs->Mod_ProcessUserData( mod, false, buf );
Mod_UnloadTextures( mod ); Mod_UnloadTextures( mod );
return true;
}
switch( mod->type )
{
case mod_studio:
case mod_brush:
loaded = true;
break;
case mod_sprite:
Mod_LoadSpriteModel( mod, buf, &loaded, mod->numtexinfo );
break;
case mod_alias:
Mod_LoadAliasModel( mod, buf, &loaded );
break;
default:
gEngfuncs.Host_Error( "%s: unsupported type %d\n", __func__, mod->type );
return false;
}
if( gEngfuncs.drawFuncs->Mod_ProcessUserData )
gEngfuncs.drawFuncs->Mod_ProcessUserData( mod, true, buf );
return loaded; return loaded;
} }

View File

@@ -16,7 +16,7 @@ GNU General Public License for more details.
#include "gl_local.h" #include "gl_local.h"
#include "xash3d_mathlib.h" #include "xash3d_mathlib.h"
static void GL_FrustumSetPlane( gl_frustum_t *out, int side, const vec3_t vecNormal, float flDist ) void GL_FrustumSetPlane( gl_frustum_t *out, int side, const vec3_t vecNormal, float flDist )
{ {
Assert( side >= 0 && side < FRUSTUM_PLANES ); Assert( side >= 0 && side < FRUSTUM_PLANES );

View File

@@ -33,6 +33,7 @@ typedef struct gl_frustum_s
void GL_FrustumInitProj( gl_frustum_t *out, float flZNear, float flZFar, float flFovX, float flFovY ); void GL_FrustumInitProj( gl_frustum_t *out, float flZNear, float flZFar, float flFovX, float flFovY );
void GL_FrustumInitOrtho( gl_frustum_t *out, float xLeft, float xRight, float yTop, float yBottom, float flZNear, float flZFar ); void GL_FrustumInitOrtho( gl_frustum_t *out, float xLeft, float xRight, float yTop, float yBottom, float flZNear, float flZFar );
void GL_FrustumSetPlane( gl_frustum_t *out, int side, const vec3_t vecNormal, float flDist );
// cull methods // cull methods
qboolean GL_FrustumCullBox( gl_frustum_t *out, const vec3_t mins, const vec3_t maxs, int userClipFlags ); qboolean GL_FrustumCullBox( gl_frustum_t *out, const vec3_t mins, const vec3_t maxs, int userClipFlags );

View File

@@ -2338,6 +2338,7 @@ void R_InitImages( void )
// validate cvars // validate cvars
R_SetTextureParameters(); R_SetTextureParameters();
GL_CreateInternalTextures(); GL_CreateInternalTextures();
R_InitRipples();
gEngfuncs.Cmd_AddCommand( "texturelist", R_TextureList_f, "display loaded textures list" ); gEngfuncs.Cmd_AddCommand( "texturelist", R_TextureList_f, "display loaded textures list" );
} }

View File

@@ -130,6 +130,7 @@ typedef struct gltexture_s
float xscale; float xscale;
float yscale; float yscale;
int servercount;
uint hashValue; uint hashValue;
struct gltexture_s *nextHash; struct gltexture_s *nextHash;
} gl_texture_t; } gl_texture_t;
@@ -437,6 +438,8 @@ void R_DrawWaterSurfaces( void );
void R_DrawBrushModel( cl_entity_t *e ); void R_DrawBrushModel( cl_entity_t *e );
void GL_SubdivideSurface( model_t *mod, msurface_t *fa ); void GL_SubdivideSurface( model_t *mod, msurface_t *fa );
void GL_BuildPolygonFromSurface( model_t *mod, msurface_t *fa ); void GL_BuildPolygonFromSurface( model_t *mod, msurface_t *fa );
void DrawGLPoly( glpoly2_t *p, float xScale, float yScale );
texture_t *R_TextureAnimation( msurface_t *s );
void GL_SetupFogColorForSurfaces( void ); void GL_SetupFogColorForSurfaces( void );
void R_DrawAlphaTextureChains( void ); void R_DrawAlphaTextureChains( void );
void GL_RebuildLightmaps( void ); void GL_RebuildLightmaps( void );
@@ -500,9 +503,10 @@ void R_DrawSkyBox( void );
void R_DrawClouds( void ); void R_DrawClouds( void );
void R_UnloadSkybox( void ); void R_UnloadSkybox( void );
void EmitWaterPolys( msurface_t *warp, qboolean reverse, qboolean ripples ); void EmitWaterPolys( msurface_t *warp, qboolean reverse, qboolean ripples );
void R_InitRipples( void );
void R_ResetRipples( void ); void R_ResetRipples( void );
void R_AnimateRipples( void ); void R_AnimateRipples( void );
qboolean R_UploadRipples( texture_t *image ); qboolean R_UploadRipples( const texture_t *image );
//#include "vid_common.h" //#include "vid_common.h"

View File

@@ -478,7 +478,7 @@ R_TextureAnimation
Returns the proper texture for a given time and surface Returns the proper texture for a given time and surface
=============== ===============
*/ */
static texture_t *R_TextureAnimation( msurface_t *s ) texture_t *R_TextureAnimation( msurface_t *s )
{ {
texture_t *base = s->texinfo->texture; texture_t *base = s->texinfo->texture;
int count, reletive; int count, reletive;
@@ -812,7 +812,7 @@ static void R_BuildLightMap( const msurface_t *surf, byte *dest, int stride, qbo
DrawGLPoly DrawGLPoly
================ ================
*/ */
static void DrawGLPoly( glpoly2_t *p, float xScale, float yScale ) void DrawGLPoly( glpoly2_t *p, float xScale, float yScale )
{ {
float *v; float *v;
float sOffset, sy; float sOffset, sy;
@@ -1855,7 +1855,7 @@ typedef struct vbodecaldata_s
// gl_decals.c // gl_decals.c
extern decal_t gDecalPool[MAX_RENDER_DECALS]; extern decal_t gDecalPool[MAX_RENDER_DECALS];
static struct vbo_static_s struct vbo_static_s
{ {
// quickly free all allocations on map change // quickly free all allocations on map change
poolhandle_t mempool; poolhandle_t mempool;
@@ -1891,7 +1891,7 @@ static struct vbo_static_s
qboolean enabled; qboolean enabled;
} vbos; } vbos;
static struct multitexturestate_s struct multitexturestate_s
{ {
int tmu_gl; // texture tmu int tmu_gl; // texture tmu
int tmu_dt; // detail tmu int tmu_dt; // detail tmu

View File

@@ -152,11 +152,11 @@ load sprite model
*/ */
void Mod_LoadSpriteModel( model_t *mod, const void *buffer, qboolean *loaded, uint texFlags ) void Mod_LoadSpriteModel( model_t *mod, const void *buffer, qboolean *loaded, uint texFlags )
{ {
const dsprite_t *pin; const dsprite_t *pin;
const short *numi = NULL; const short *numi = NULL;
const byte *pframetype; const byte *pframetype;
msprite_t *psprite; msprite_t *psprite;
int i; int i;
pin = buffer; pin = buffer;
psprite = mod->cache.data; psprite = mod->cache.data;
@@ -164,7 +164,7 @@ void Mod_LoadSpriteModel( model_t *mod, const void *buffer, qboolean *loaded, ui
if( pin->version == SPRITE_VERSION_Q1 || pin->version == SPRITE_VERSION_32 ) if( pin->version == SPRITE_VERSION_Q1 || pin->version == SPRITE_VERSION_32 )
numi = NULL; numi = NULL;
else if( pin->version == SPRITE_VERSION_HL ) else if( pin->version == SPRITE_VERSION_HL )
numi = (const short *)((const byte *)buffer + sizeof( dsprite_hl_t )); numi = (const short *)((const byte*)buffer + sizeof( dsprite_hl_t ));
r_texFlags = texFlags; r_texFlags = texFlags;
sprite_version = pin->version; sprite_version = pin->version;
@@ -179,32 +179,31 @@ void Mod_LoadSpriteModel( model_t *mod, const void *buffer, qboolean *loaded, ui
pframetype = ((const byte*)buffer + sizeof( dsprite_q1_t )); // pinq1 + 1 pframetype = ((const byte*)buffer + sizeof( dsprite_q1_t )); // pinq1 + 1
gEngfuncs.FS_FreeImage( pal ); // palette installed, no reason to keep this data gEngfuncs.FS_FreeImage( pal ); // palette installed, no reason to keep this data
} }
else if( *numi <= 256 ) else if( *numi == 256 )
{ {
const byte *src = (const byte *)(numi+1); const byte *src = (const byte *)(numi+1);
rgbdata_t *pal; rgbdata_t *pal;
size_t pal_bytes = *numi * 3;
// install palette // install palette
switch( psprite->texFormat ) switch( psprite->texFormat )
{ {
case SPR_INDEXALPHA: case SPR_INDEXALPHA:
pal = gEngfuncs.FS_LoadImage( "#gradient.pal", src, pal_bytes ); pal = gEngfuncs.FS_LoadImage( "#gradient.pal", src, 768 );
break; break;
case SPR_ALPHTEST: case SPR_ALPHTEST:
pal = gEngfuncs.FS_LoadImage( "#masked.pal", src, pal_bytes ); pal = gEngfuncs.FS_LoadImage( "#masked.pal", src, 768 );
break; break;
default: default:
pal = gEngfuncs.FS_LoadImage( "#normal.pal", src, pal_bytes ); pal = gEngfuncs.FS_LoadImage( "#normal.pal", src, 768 );
break; break;
} }
pframetype = (const byte *)(src + pal_bytes); pframetype = (const byte *)(src + 768);
gEngfuncs.FS_FreeImage( pal ); // palette installed, no reason to keep this data gEngfuncs.FS_FreeImage( pal ); // palette installed, no reason to keep this data
} }
else else
{ {
gEngfuncs.Con_DPrintf( S_ERROR "%s has wrong number of palette colors %i (should be less or equal than 256)\n", mod->name, *numi ); gEngfuncs.Con_DPrintf( S_ERROR "%s has wrong number of palette colors %i (should be 256)\n", mod->name, *numi );
return; return;
} }
@@ -250,31 +249,32 @@ release sprite model and frames
*/ */
void Mod_SpriteUnloadTextures( void *data ) void Mod_SpriteUnloadTextures( void *data )
{ {
msprite_t *psprite = data; msprite_t *psprite;
int i; mspritegroup_t *pspritegroup;
mspriteframe_t *pspriteframe;
int i, j;
if( !data ) psprite = data;
return;
// release all textures if( psprite )
for( i = 0; i < psprite->numframes; i++ )
{ {
if( !psprite->frames[i].frameptr ) // release all textures
continue; for( i = 0; i < psprite->numframes; i++ )
if( psprite->frames[i].type == SPR_SINGLE )
{ {
GL_FreeTexture( psprite->frames[i].frameptr->gl_texturenum ); if( psprite->frames[i].type == SPR_SINGLE )
}
else
{
mspritegroup_t *pspritegroup = (mspritegroup_t *)psprite->frames[i].frameptr;
int j;
for( j = 0; j < pspritegroup->numframes; j++ )
{ {
if( pspritegroup->frames[j] ) pspriteframe = psprite->frames[i].frameptr;
GL_FreeTexture( pspritegroup->frames[j]->gl_texturenum ); GL_FreeTexture( pspriteframe->gl_texturenum );
}
else
{
pspritegroup = (mspritegroup_t *)psprite->frames[i].frameptr;
for( j = 0; j < pspritegroup->numframes; j++ )
{
pspriteframe = pspritegroup->frames[i];
GL_FreeTexture( pspriteframe->gl_texturenum );
}
} }
} }
} }

View File

@@ -79,6 +79,8 @@ static struct
qboolean update; qboolean update;
uint32_t texture[RIPPLES_TEXSIZE]; uint32_t texture[RIPPLES_TEXSIZE];
int gl_texturenum;
int rippletexturenum;
} g_ripple; } g_ripple;
@@ -653,6 +655,22 @@ void R_ResetRipples( void )
memset( g_ripple.buf, 0, sizeof( g_ripple.buf )); memset( g_ripple.buf, 0, sizeof( g_ripple.buf ));
} }
void R_InitRipples( void )
{
rgbdata_t pic = { 0 };
pic.width = pic.height = RIPPLES_CACHEWIDTH;
pic.depth = 1;
pic.flags = IMAGE_HAS_COLOR;
pic.buffer = (byte *)g_ripple.texture;
pic.type = PF_RGBA_32;
pic.size = sizeof( g_ripple.texture );
pic.numMips = 1;
memset( pic.buffer, 0, pic.size );
g_ripple.rippletexturenum = GL_LoadTextureInternal( "*rippletex", &pic, TF_NOMIPMAP|TF_ALLOW_NEAREST );
}
static void R_SwapBufs( void ) static void R_SwapBufs( void )
{ {
short *tempbufp = g_ripple.curbuf; short *tempbufp = g_ripple.curbuf;
@@ -720,7 +738,7 @@ void R_AnimateRipples( void )
R_RunRipplesAnimation( g_ripple.oldbuf, g_ripple.curbuf ); R_RunRipplesAnimation( g_ripple.oldbuf, g_ripple.curbuf );
} }
qboolean R_UploadRipples( texture_t *image ) qboolean R_UploadRipples( const texture_t *image )
{ {
const gl_texture_t *glt; const gl_texture_t *glt;
const uint32_t *pixels; const uint32_t *pixels;
@@ -741,6 +759,16 @@ qboolean R_UploadRipples( texture_t *image )
return false; return false;
} }
GL_Bind( XASH_TEXTURE0, g_ripple.rippletexturenum );
// no updates this frame
if( !g_ripple.update && image->gl_texturenum == g_ripple.gl_texturenum )
return true;
g_ripple.gl_texturenum = image->gl_texturenum;
size = r_ripple.value == 1.0f ? 64 : RIPPLES_CACHEWIDTH;
// try to preserve aspect ratio // try to preserve aspect ratio
width = height = RIPPLES_CACHEWIDTH; // always render at maximum size width = height = RIPPLES_CACHEWIDTH; // always render at maximum size
if( image->width > image->height ) if( image->width > image->height )
@@ -748,32 +776,6 @@ qboolean R_UploadRipples( texture_t *image )
else if( image->width < image->height ) else if( image->width < image->height )
width = (float)image->width / image->height * height; width = (float)image->width / image->height * height;
if( !image->fb_texturenum )
{
rgbdata_t pic = { 0 };
string name;
Q_snprintf( name, sizeof( name ), "*rippletex_%s", image->name );
pic.width = width;
pic.height = height;
pic.depth = 1;
pic.flags = IMAGE_HAS_COLOR;
pic.buffer = (byte *)g_ripple.texture;
pic.type = PF_RGBA_32;
pic.size = width * height * 4;
pic.numMips = 1;
memset( pic.buffer, 0, pic.size );
image->fb_texturenum = GL_LoadTextureInternal( name, &pic, TF_NOMIPMAP | TF_ALLOW_NEAREST );
}
GL_Bind( XASH_TEXTURE0, image->fb_texturenum );
// no updates this frame
if( !g_ripple.update )
return true;
size = r_ripple.value == 1.0f ? 64 : RIPPLES_CACHEWIDTH;
pixels = (const uint32_t *)glt->original->buffer; pixels = (const uint32_t *)glt->original->buffer;
for( y = 0; y < height; y++ ) for( y = 0; y < height; y++ )

View File

@@ -66,33 +66,34 @@ void Mod_UnloadTextures( model_t *mod );
static qboolean GAME_EXPORT Mod_ProcessRenderData( model_t *mod, qboolean create, const byte *buf ) static qboolean GAME_EXPORT Mod_ProcessRenderData( model_t *mod, qboolean create, const byte *buf )
{ {
qboolean loaded = false; qboolean loaded = true;
if( create )
{
switch( mod->type )
{
case mod_studio:
// Mod_LoadStudioModel( mod, buf, loaded );
break;
case mod_sprite:
Mod_LoadSpriteModel( mod, buf, &loaded, mod->numtexinfo );
break;
case mod_alias:
// Mod_LoadAliasModel( mod, buf, &loaded );
break;
case mod_brush:
// Mod_LoadBrushModel( mod, buf, loaded );
break;
default: gEngfuncs.Host_Error( "%s: unsupported type %d\n", __func__, mod->type );
}
}
if( loaded && gEngfuncs.drawFuncs->Mod_ProcessUserData )
gEngfuncs.drawFuncs->Mod_ProcessUserData( mod, create, buf );
if( !create ) if( !create )
{
if( gEngfuncs.drawFuncs->Mod_ProcessUserData )
gEngfuncs.drawFuncs->Mod_ProcessUserData( mod, false, buf );
Mod_UnloadTextures( mod ); Mod_UnloadTextures( mod );
return true;
}
switch( mod->type )
{
case mod_studio:
case mod_brush:
case mod_alias:
loaded = true;
break;
case mod_sprite:
Mod_LoadSpriteModel( mod, buf, &loaded, mod->numtexinfo );
break;
default:
gEngfuncs.Host_Error( "%s: unsupported type %d\n", __func__, mod->type );
return false;
}
if( gEngfuncs.drawFuncs->Mod_ProcessUserData )
gEngfuncs.drawFuncs->Mod_ProcessUserData( mod, true, buf );
return loaded; return loaded;
} }

View File

@@ -363,6 +363,8 @@ typedef struct image_s
pixel_t *pixels[4]; // mip levels pixel_t *pixels[4]; // mip levels
pixel_t *alpha_pixels; // mip levels pixel_t *alpha_pixels; // mip levels
int servercount;
uint hashValue; uint hashValue;
struct image_s *nextHash; struct image_s *nextHash;
} image_t; } image_t;

View File

@@ -165,32 +165,31 @@ void Mod_LoadSpriteModel( model_t *mod, const void *buffer, qboolean *loaded, ui
pframetype = ((const byte *)buffer + sizeof( dsprite_q1_t )); // pinq1 + 1 pframetype = ((const byte *)buffer + sizeof( dsprite_q1_t )); // pinq1 + 1
gEngfuncs.FS_FreeImage( pal ); // palette installed, no reason to keep this data gEngfuncs.FS_FreeImage( pal ); // palette installed, no reason to keep this data
} }
else if( *numi <= 256 ) else if( *numi == 256 )
{ {
const byte *src = (const byte *)(numi+1); const byte *src = (const byte *)( numi + 1 );
rgbdata_t *pal; rgbdata_t *pal;
size_t pal_bytes = *numi * 3;
// install palette // install palette
switch( psprite->texFormat ) switch( psprite->texFormat )
{ {
case SPR_INDEXALPHA: case SPR_INDEXALPHA:
pal = gEngfuncs.FS_LoadImage( "#gradient.pal", src, pal_bytes ); pal = gEngfuncs.FS_LoadImage( "#gradient.pal", src, 768 );
break; break;
case SPR_ALPHTEST: case SPR_ALPHTEST:
pal = gEngfuncs.FS_LoadImage( "#masked.pal", src, pal_bytes ); pal = gEngfuncs.FS_LoadImage( "#masked.pal", src, 768 );
break; break;
default: default:
pal = gEngfuncs.FS_LoadImage( "#normal.pal", src, pal_bytes ); pal = gEngfuncs.FS_LoadImage( "#normal.pal", src, 768 );
break; break;
} }
pframetype = (const byte *)(src + pal_bytes); pframetype = (const byte *)( src + 768 );
gEngfuncs.FS_FreeImage( pal ); // palette installed, no reason to keep this data gEngfuncs.FS_FreeImage( pal ); // palette installed, no reason to keep this data
} }
else else
{ {
gEngfuncs.Con_DPrintf( S_ERROR "%s has wrong number of palette colors %i (should be less or equal than 256)\n", mod->name, *numi ); gEngfuncs.Con_DPrintf( S_ERROR "%s has wrong number of palette colors %i (should be 256)\n", mod->name, *numi );
return; return;
} }
@@ -238,31 +237,32 @@ release sprite model and frames
*/ */
void Mod_SpriteUnloadTextures( void *data ) void Mod_SpriteUnloadTextures( void *data )
{ {
msprite_t *psprite = data; msprite_t *psprite;
int i; mspritegroup_t *pspritegroup;
mspriteframe_t *pspriteframe;
int i, j;
if( !data ) psprite = data;
return;
// release all textures if( psprite )
for( i = 0; i < psprite->numframes; i++ )
{ {
if( !psprite->frames[i].frameptr ) // release all textures
continue; for( i = 0; i < psprite->numframes; i++ )
if( psprite->frames[i].type == SPR_SINGLE )
{ {
GL_FreeTexture( psprite->frames[i].frameptr->gl_texturenum ); if( psprite->frames[i].type == SPR_SINGLE )
}
else
{
mspritegroup_t *pspritegroup = (mspritegroup_t *)psprite->frames[i].frameptr;
int j;
for( j = 0; j < pspritegroup->numframes; j++ )
{ {
if( pspritegroup->frames[j] ) pspriteframe = psprite->frames[i].frameptr;
GL_FreeTexture( pspritegroup->frames[j]->gl_texturenum ); GL_FreeTexture( pspriteframe->gl_texturenum );
}
else
{
pspritegroup = (mspritegroup_t *)psprite->frames[i].frameptr;
for( j = 0; j < pspritegroup->numframes; j++ )
{
pspriteframe = pspritegroup->frames[i];
GL_FreeTexture( pspriteframe->gl_texturenum );
}
} }
} }
} }

View File

@@ -8,7 +8,7 @@ pushd hlsdk || die
./waf configure build install --destdir=../bin || die ./waf configure build install --destdir=../bin || die
popd popd
./waf configure --enable-utils --enable-tests --enable-lto build install --destdir=bin || die_configure ./waf configure --enable-utils --enable-tests --enable-lto --enable-wafcache build --zones=wafcache install --destdir=bin || die_configure
cp -vr /Library/Frameworks/SDL2.framework bin cp -vr /Library/Frameworks/SDL2.framework bin

View File

@@ -18,7 +18,7 @@ for i in arm64 armhf riscv64 ppc64el; do
CROSS_COMPILE_CC[$i]=${ARCH_TRIPLET[$i]}-gcc CROSS_COMPILE_CC[$i]=${ARCH_TRIPLET[$i]}-gcc
CROSS_COMPILE_CXX[$i]=${ARCH_TRIPLET[$i]}-g++ CROSS_COMPILE_CXX[$i]=${ARCH_TRIPLET[$i]}-g++
done done
export PKG_CONFIG_PATH=$PWD/ffmpeg/lib/pkgconfig:${ARCH_TRIPLET[$GH_CPU_ARCH]} export PKG_CONFIG_PATH=${ARCH_TRIPLET[$GH_CPU_ARCH]}
export CC=${CROSS_COMPILE_CC[$GH_CPU_ARCH]} export CC=${CROSS_COMPILE_CC[$GH_CPU_ARCH]}
export CXX=${CROSS_COMPILE_CXX[$GH_CPU_ARCH]} export CXX=${CROSS_COMPILE_CXX[$GH_CPU_ARCH]}
@@ -53,39 +53,31 @@ build_engine()
cd "$BUILDDIR" || die cd "$BUILDDIR" || die
if [ "$ARCH" = "amd64" ]; then # we need enabling 64-bit target only on Intel-compatible CPUs if [ "$ARCH" = "amd64" ]; then # we need enabling 64-bit target only on Intel-compatible CPUs
WAF_EXTRA_ARGS="-8" AMD64="-8"
fi
if [ -d "ffmpeg" ]; then
WAF_EXTRA_ARGS+=" --enable-ffmpeg"
fi fi
if [ "$GH_CROSSCOMPILING" != "true" ]; then if [ "$GH_CROSSCOMPILING" != "true" ]; then
WAF_EXTRA_ARGS+=" --enable-tests" ENABLE_TESTS="--enable-tests"
fi fi
if [ "$1" = "dedicated" ]; then if [ "$1" = "dedicated" ]; then
./waf configure $WAF_EXTRA_ARGS --enable-lto --enable-bundled-deps -d || die_configure ./waf configure $AMD64 $ENABLE_TESTS --enable-lto --enable-bundled-deps -d --enable-wafcache || die_configure
elif [ "$1" = "full" ]; then elif [ "$1" = "full" ]; then
./waf configure $WAF_EXTRA_ARGS --enable-lto --enable-bundled-deps -s SDL2_linux --enable-stb --enable-utils || die_configure ./waf configure $AMD64 $ENABLE_TESTS --enable-lto --enable-bundled-deps -s SDL2_linux --enable-stb --enable-utils --enable-wafcache || die_configure
else else
die die
fi fi
./waf build || die_configure ./waf build --zones=wafcache || die_configure
} }
deploy_engine() deploy_engine()
{ {
cd "$BUILDDIR" || die cd "$BUILDDIR" || die
./waf install --destdir="$APPDIR" || die ./waf install --destdir="$APPDIR" || die
cp -av SDL2_linux/lib/libSDL2-2.0.so.0 "$APPDIR/" cp SDL2_linux/lib/libSDL2-2.0.so.0 "$APPDIR/"
if [ "$GH_CPU_ARCH" = "i386" ]; then if [ "$GH_CPU_ARCH" = "i386" ]; then
cp -av 3rdparty/vgui_support/vgui-dev/lib/vgui.so "$APPDIR/" cp 3rdparty/vgui_support/vgui-dev/lib/vgui.so "$APPDIR/"
fi
if [ -d "ffmpeg" ]; then
cp -av ffmpeg/lib/libav* ffmpeg/lib/libsw* "$APPDIR/"
fi fi
} }

View File

@@ -12,7 +12,7 @@ pushd hlsdk || die
./waf configure -T fast --enable-magx --enable-simple-mod-hacks build install --destdir=../Xash || die ./waf configure -T fast --enable-magx --enable-simple-mod-hacks build install --destdir=../Xash || die
popd popd
./waf configure -T fast --enable-magx build install --destdir=Xash/ || die ./waf configure -T fast --enable-magx --enable-wafcache build install --destdir=Xash/ || die
cat > Xash/run.sh << 'EOF' cat > Xash/run.sh << 'EOF'
mypath=${0%/*} mypath=${0%/*}

View File

@@ -11,7 +11,7 @@ mkdir -p artifacts/ || die
echo "Running build script in Docker container..." echo "Running build script in Docker container..."
docker run --name xash-build --rm -v `pwd`:`pwd` -w `pwd` devkitpro/devkita64:latest bash ./scripts/gha/build_nswitch_docker.sh || die docker run --name xash-build --rm -v `pwd`:`pwd` -v $HOME/.cache:$HOME/.cache -w `pwd` devkitpro/devkita64:latest bash ./scripts/gha/build_nswitch_docker.sh || die
echo "Packaging artifacts..." echo "Packaging artifacts..."

View File

@@ -42,7 +42,7 @@ make -C libsolder install || die
echo "Building engine..." echo "Building engine..."
./waf configure -T release --nswitch || die_configure ./waf configure -T release --nswitch --enable-wafcache || die_configure
./waf build install --destdir=pkgtemp/xash3d -v || die ./waf build install --destdir=pkgtemp/xash3d -v || die
echo "Building HLSDK..." echo "Building HLSDK..."

Some files were not shown because too many files have changed in this diff Show More