mirror of
https://github.com/FWGS/xash3d-fwgs.git
synced 2026-08-05 19:45:05 +08:00
Compare commits
95 Commits
continuous
...
continuous
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
004af02e99 | ||
|
|
8ad56eb085 | ||
|
|
578a77518f | ||
|
|
2457ecf226 | ||
|
|
8cd99885f1 | ||
|
|
684e229ac8 | ||
|
|
c0f1d8c647 | ||
|
|
c3b8696957 | ||
|
|
3ca413dbab | ||
|
|
92dc04ff3c | ||
|
|
ad6db91285 | ||
|
|
90a0f74087 | ||
|
|
4f7f5288a1 | ||
|
|
c23b4bfe61 | ||
|
|
4780f70ea2 | ||
|
|
98a04c7764 | ||
|
|
7da9772143 | ||
|
|
32def35408 | ||
|
|
952ccb1247 | ||
|
|
6f0fb594e7 | ||
|
|
f0b29bac1b | ||
|
|
7b5ff606bd | ||
|
|
3e22ee64ae | ||
|
|
c86c45503f | ||
|
|
ef75a4c28d | ||
|
|
bccd3f2271 | ||
|
|
7bbc3e8238 | ||
|
|
c34e0c66d9 | ||
|
|
e5d80878b8 | ||
|
|
1e075d25b7 | ||
|
|
d29e53481d | ||
|
|
d23a2fd2df | ||
|
|
f6f15cc204 | ||
|
|
4f2249ed8e | ||
|
|
9f322df498 | ||
|
|
b554d7e215 | ||
|
|
719093c10b | ||
|
|
c2da140ccc | ||
|
|
375998dffb | ||
|
|
787444f63d | ||
|
|
0c50076ff0 | ||
|
|
8ce01c38c7 | ||
|
|
cac6206984 | ||
|
|
a5c88bdda9 | ||
|
|
fc017286a6 | ||
|
|
20d4e3e719 | ||
|
|
4eaa32fc10 | ||
|
|
b7c025b167 | ||
|
|
f29c588e0f | ||
|
|
2065ef143a | ||
|
|
a5c02c85f0 | ||
|
|
9a8761f1d8 | ||
|
|
273990d292 | ||
|
|
0e27d8717c | ||
|
|
8a9b209db0 | ||
|
|
232d1f8583 | ||
|
|
6cfa5877a4 | ||
|
|
154df00f94 | ||
|
|
c5649c94d5 | ||
|
|
a1da10fe38 | ||
|
|
17a71ffc96 | ||
|
|
4609fbc0c5 | ||
|
|
d278d3bdd7 | ||
|
|
7811b60292 | ||
|
|
870fad5606 | ||
|
|
3e93aa459d | ||
|
|
626c5e44f6 | ||
|
|
c906aa0106 | ||
|
|
0a41b70e44 | ||
|
|
ea338adc46 | ||
|
|
5fa777578b | ||
|
|
5b9db5940b | ||
|
|
4b1b3aa13c | ||
|
|
2d51d23d89 | ||
|
|
b5b6dad39c | ||
|
|
a5619e9960 | ||
|
|
a75666a3cd | ||
|
|
49426721d8 | ||
|
|
04125284a3 | ||
|
|
1d4f7b2f94 | ||
|
|
38c82a3f76 | ||
|
|
785632a437 | ||
|
|
4be75af214 | ||
|
|
dcdca01e86 | ||
|
|
8b4b0479c8 | ||
|
|
c8bf7e5630 | ||
|
|
4987080e1e | ||
|
|
1d78e400ff | ||
|
|
2d1a885954 | ||
|
|
43ba2e747b | ||
|
|
eefb823ee2 | ||
|
|
a3c33e0fa9 | ||
|
|
16fe6b1b1a | ||
|
|
4275829bd5 | ||
|
|
1884f0a3ce |
@@ -1,10 +1,10 @@
|
|||||||
task:
|
task:
|
||||||
name: freebsd-14-amd64
|
name: freebsd-14-amd64
|
||||||
freebsd_instance:
|
freebsd_instance:
|
||||||
image_family: freebsd-14-0
|
image_family: freebsd-14-2
|
||||||
setup_script:
|
setup_script:
|
||||||
- pkg update
|
- pkg update
|
||||||
- pkg install -y pkgconf git sdl2 python fontconfig opus
|
- pkg install -y pkgconf git sdl2 python fontconfig libvorbis opusfile bzip2
|
||||||
- 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 opus
|
- pkg install -y pkgconf git sdl2 python fontconfig libvorbis opusfile bzip2
|
||||||
- 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
|
||||||
|
|||||||
2
.github/workflows/c-cpp.yml
vendored
2
.github/workflows/c-cpp.yml
vendored
@@ -67,7 +67,9 @@ 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 }}
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
|
|||||||
1
3rdparty/extras/wscript
vendored
1
3rdparty/extras/wscript
vendored
@@ -25,5 +25,4 @@ 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)
|
||||||
|
|||||||
2
3rdparty/mainui
vendored
2
3rdparty/mainui
vendored
Submodule 3rdparty/mainui updated: 734a6d1ca2...695ea1be2e
File diff suppressed because it is too large
Load Diff
@@ -50,4 +50,8 @@ 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 */
|
||||||
|
|||||||
@@ -78,7 +78,6 @@ 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
|
||||||
|
|
||||||
//
|
//
|
||||||
@@ -105,6 +104,17 @@ 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
|
||||||
|
|||||||
@@ -157,6 +157,23 @@ 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
|
||||||
@@ -193,16 +210,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
|
||||||
void *(*AVI_LoadVideo)( const char *filename, qboolean load_audio );
|
struct movie_state_s *(*AVI_LoadVideo)( const char *filename, qboolean load_audio );
|
||||||
int (*AVI_GetVideoInfo)( void *Avi, int *xres, int *yres, float *duration ); // a1ba: changed longs to int
|
qboolean (*AVI_GetVideoInfo)( struct movie_state_s *Avi, int *xres, int *yres, float *duration ); // a1ba: changed longs to int
|
||||||
int (*AVI_GetVideoFrameNumber)( void *Avi, float time );
|
int (*AVI_GetVideoFrameNumber)( struct movie_state_s *Avi, float time );
|
||||||
byte *(*AVI_GetVideoFrame)( void *Avi, int frame );
|
byte *(*AVI_GetVideoFrame)( struct movie_state_s *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)( void *Avi );
|
void (*AVI_FreeVideo)( struct movie_state_s *Avi );
|
||||||
int (*AVI_IsActive)( void *Avi );
|
qboolean (*AVI_IsActive)( struct movie_state_s *Avi );
|
||||||
void (*AVI_StreamSound)( void *Avi, int entnum, float fvol, float attn, float synctime );
|
void (*AVI_StreamSound)( struct movie_state_s *Avi, int entnum, float fvol, float attn, float synctime );
|
||||||
void (*AVI_Reserved0)( void ); // for potential interface expansion without broken compatibility
|
qboolean (*AVI_Think)( struct movie_state_s *Avi );
|
||||||
void (*AVI_Reserved1)( void );
|
qboolean (*AVI_SetParm)( struct movie_state_s *Avi, enum movie_parms_e parm, ... );
|
||||||
|
|
||||||
// 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 );
|
||||||
|
|||||||
@@ -16,19 +16,17 @@
|
|||||||
#include STDINT_H
|
#include STDINT_H
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
typedef unsigned char byte;
|
typedef uint8_t byte;
|
||||||
typedef int sound_t;
|
typedef float vec_t;
|
||||||
typedef float vec_t;
|
typedef vec_t vec2_t[2];
|
||||||
typedef vec_t vec2_t[2];
|
typedef vec_t vec3_t[3];
|
||||||
typedef vec_t vec3_t[3];
|
typedef vec_t vec4_t[4];
|
||||||
typedef vec_t vec4_t[4];
|
typedef vec_t quat_t[4];
|
||||||
typedef vec_t quat_t[4];
|
typedef byte rgba_t[4]; // unsigned byte colorpack
|
||||||
typedef byte rgba_t[4]; // unsigned byte colorpack
|
typedef byte rgb_t[3]; // unsigned byte colorpack
|
||||||
typedef byte rgb_t[3]; // unsigned byte colorpack
|
typedef vec_t matrix3x4[3][4];
|
||||||
typedef vec_t matrix3x4[3][4];
|
typedef vec_t matrix4x4[4][4];
|
||||||
typedef vec_t matrix4x4[4][4];
|
typedef uint32_t poolhandle_t;
|
||||||
|
|
||||||
typedef uint32_t poolhandle_t;
|
|
||||||
|
|
||||||
#undef true
|
#undef true
|
||||||
#undef false
|
#undef false
|
||||||
@@ -39,18 +37,10 @@ typedef enum { false, true } qboolean;
|
|||||||
typedef int qboolean;
|
typedef int qboolean;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef uint64_t longtime_t;
|
#define MAX_STRING 256 // generic string
|
||||||
|
#define MAX_VA_STRING 1024 // compatibility macro
|
||||||
#define MAX_STRING 256 // generic string
|
#define MAX_SYSPATH 1024 // system filepath
|
||||||
#define MAX_INFO_STRING 256 // infostrings are transmitted across network
|
#define MAX_MODS 512 // environment games that engine can keep visible
|
||||||
#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 ))
|
||||||
@@ -209,35 +199,16 @@ _inline float LittleFloat( float f )
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
typedef unsigned int dword;
|
typedef unsigned int dword;
|
||||||
typedef unsigned int uint;
|
typedef unsigned int uint;
|
||||||
typedef unsigned long ulong;
|
typedef char string[MAX_STRING];
|
||||||
typedef char string[MAX_STRING];
|
typedef off_t fs_offset_t;
|
||||||
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
|
||||||
|
|||||||
@@ -18,12 +18,11 @@ 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_GetAudioInfo( movie_state_t *Avi, wavdata_t *snd_info );
|
qboolean AVI_HaveAudioTrack( const movie_state_t *Avi );
|
||||||
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 );
|
||||||
@@ -34,4 +33,7 @@ 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
|
||||||
|
|||||||
761
engine/client/avi/avi_ffmpeg.c
Normal file
761
engine/client/avi/avi_ffmpeg.c
Normal file
@@ -0,0 +1,761 @@
|
|||||||
|
/*
|
||||||
|
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 );
|
||||||
|
}
|
||||||
@@ -1,90 +0,0 @@
|
|||||||
/*
|
|
||||||
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
|
|
||||||
@@ -1,732 +0,0 @@
|
|||||||
/*
|
|
||||||
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
|
|
||||||
@@ -42,7 +42,8 @@ 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.avi", Cmd_Argv( 1 ));
|
Q_snprintf( path, sizeof( path ), "media/%s", 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
|
||||||
|
|||||||
@@ -153,6 +153,7 @@ 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, ¤t_count, sizeof( int ));
|
FS_Write( fp, ¤t_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 );
|
||||||
|
|
||||||
@@ -168,7 +169,7 @@ list last 32 messages for debugging net troubleshooting
|
|||||||
*/
|
*/
|
||||||
void CL_WriteMessageHistory( void )
|
void CL_WriteMessageHistory( void )
|
||||||
{
|
{
|
||||||
oldcmd_t *old, *failcommand;
|
oldcmd_t *old;
|
||||||
sizebuf_t *msg = &net_message;
|
sizebuf_t *msg = &net_message;
|
||||||
int i, thecmd;
|
int i, thecmd;
|
||||||
|
|
||||||
@@ -192,9 +193,8 @@ void CL_WriteMessageHistory( void )
|
|||||||
thecmd++;
|
thecmd++;
|
||||||
}
|
}
|
||||||
|
|
||||||
failcommand = &cls_message_debug.oldcmd[thecmd];
|
old = &cls_message_debug.oldcmd[thecmd];
|
||||||
Con_Printf( "BAD: %3i:%s\n", MSG_GetNumBytesRead( msg ) - 1, CL_MsgInfo( failcommand->command ));
|
Con_Printf( S_RED "BAD: " S_DEFAULT "%i %04i %s\n", old->frame_number, old->starting_offset, CL_MsgInfo( old->command ));
|
||||||
if( host_developer.value >= DEV_EXTENDED )
|
CL_WriteErrorMessage( old->starting_offset, msg );
|
||||||
CL_WriteErrorMessage( MSG_GetNumBytesRead( msg ) - 1, msg );
|
|
||||||
cls_message_debug.parsing = false;
|
cls_message_debug.parsing = false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -373,7 +373,7 @@ CL_WriteDemoUserMessage
|
|||||||
Dumps the user message (demoaction)
|
Dumps the user message (demoaction)
|
||||||
====================
|
====================
|
||||||
*/
|
*/
|
||||||
void CL_WriteDemoUserMessage( const byte *buffer, size_t size )
|
void GAME_EXPORT CL_WriteDemoUserMessage( int size, byte *buffer )
|
||||||
{
|
{
|
||||||
if( !cls.demorecording || cls.demowaiting )
|
if( !cls.demorecording || cls.demowaiting )
|
||||||
return;
|
return;
|
||||||
@@ -624,11 +624,10 @@ static void CL_ReadDemoUserCmd( qboolean discard )
|
|||||||
|
|
||||||
if( !discard )
|
if( !discard )
|
||||||
{
|
{
|
||||||
usercmd_t nullcmd;
|
const usercmd_t nullcmd = { 0 };
|
||||||
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
|
||||||
|
|||||||
@@ -2229,4 +2229,3 @@ void CL_ThinkParticle( double frametime, particle_t *p )
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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 = _copystring( clgame.mempool, name, __FILE__, __LINE__ );
|
cl_textmessage[i].pName = copystringpool( clgame.mempool, name );
|
||||||
cl_textmessage[i].pMessage = cl_textbuffer[i];
|
cl_textmessage[i].pMessage = cl_textbuffer[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3348,28 +3348,6 @@ 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
|
||||||
@@ -3381,17 +3359,6 @@ 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
|
||||||
@@ -3577,28 +3544,6 @@ 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
|
||||||
@@ -3795,10 +3740,10 @@ static event_api_t gEventApi =
|
|||||||
|
|
||||||
static demo_api_t gDemoApi =
|
static demo_api_t gDemoApi =
|
||||||
{
|
{
|
||||||
Demo_IsRecording,
|
(void *)CL_IsRecordDemo,
|
||||||
Demo_IsPlayingback,
|
(void *)CL_IsPlaybackDemo,
|
||||||
Demo_IsTimeDemo,
|
Demo_IsTimeDemo,
|
||||||
Demo_WriteBuffer,
|
CL_WriteDemoUserMessage,
|
||||||
};
|
};
|
||||||
|
|
||||||
net_api_t gNetApi =
|
net_api_t gNetApi =
|
||||||
@@ -3810,8 +3755,8 @@ net_api_t gNetApi =
|
|||||||
NetAPI_CancelAllRequests,
|
NetAPI_CancelAllRequests,
|
||||||
NetAPI_AdrToString,
|
NetAPI_AdrToString,
|
||||||
NetAPI_CompareAdr,
|
NetAPI_CompareAdr,
|
||||||
NetAPI_StringToAdr,
|
(void *)NET_StringToAdr,
|
||||||
NetAPI_ValueForKey,
|
Info_ValueForKey,
|
||||||
NetAPI_RemoveKey,
|
NetAPI_RemoveKey,
|
||||||
NetAPI_SetValueForKey,
|
NetAPI_SetValueForKey,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -302,14 +302,11 @@ 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 ) return;
|
if( !gameui.drawLogo )
|
||||||
|
return;
|
||||||
|
|
||||||
cin_state = AVI_GetState( CIN_LOGO );
|
cin_state = AVI_GetState( CIN_LOGO );
|
||||||
|
|
||||||
if( !AVI_IsActive( cin_state ))
|
if( !AVI_IsActive( cin_state ))
|
||||||
@@ -336,37 +333,25 @@ 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
// advances cinematic time (ignores maxfps and host_framerate settings)
|
AVI_SetParm( cin_state,
|
||||||
cin_time += host.realframetime;
|
AVI_RENDER_TEXNUM, 0,
|
||||||
|
AVI_RENDER_X, (int)x,
|
||||||
// restarts the cinematic
|
AVI_RENDER_Y, (int)y,
|
||||||
if( cin_time > gameui.logo_length )
|
AVI_RENDER_W, (int)width,
|
||||||
cin_time = 0.0f;
|
AVI_RENDER_H, (int)height,
|
||||||
|
AVI_PARM_LAST );
|
||||||
|
|
||||||
// read the next frame
|
// read the next frame
|
||||||
cin_frame = AVI_GetVideoFrameNumber( cin_state, cin_time );
|
if( !AVI_Think( cin_state ))
|
||||||
|
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 )
|
||||||
|
|||||||
@@ -76,6 +76,7 @@ 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)" );
|
||||||
@@ -147,11 +148,6 @@ 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;
|
||||||
@@ -598,7 +594,7 @@ CL_CreateCmd
|
|||||||
*/
|
*/
|
||||||
static void CL_CreateCmd( void )
|
static void CL_CreateCmd( void )
|
||||||
{
|
{
|
||||||
usercmd_t nullcmd, *cmd;
|
usercmd_t nullcmd = { 0 }, *cmd;
|
||||||
runcmd_t *pcmd;
|
runcmd_t *pcmd;
|
||||||
qboolean active;
|
qboolean active;
|
||||||
double accurate_ms;
|
double accurate_ms;
|
||||||
@@ -650,7 +646,6 @@ static void CL_CreateCmd( void )
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
memset( &nullcmd, 0, sizeof( nullcmd ));
|
|
||||||
cmd = &nullcmd;
|
cmd = &nullcmd;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -723,11 +718,20 @@ 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 <= ca_connected )
|
if( cls.state < min_state )
|
||||||
{
|
{
|
||||||
Netchan_TransmitBits( &cls.netchan, 0, "" );
|
Netchan_TransmitBits( &cls.netchan, 0, "" );
|
||||||
return;
|
return;
|
||||||
@@ -825,7 +829,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
|
else if( !Host_IsLocalClient( ))
|
||||||
{
|
{
|
||||||
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 );
|
||||||
@@ -1594,6 +1598,9 @@ 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 ))
|
||||||
@@ -3387,6 +3394,7 @@ 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 );
|
||||||
@@ -3658,6 +3666,8 @@ 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
|
||||||
|
|||||||
@@ -1614,6 +1614,23 @@ 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;
|
||||||
@@ -1879,6 +1896,9 @@ 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;
|
||||||
|
|
||||||
@@ -1910,7 +1930,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( consistency_t ));
|
memset( pc, 0, sizeof( *pc ));
|
||||||
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;
|
||||||
@@ -1923,6 +1943,9 @@ 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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -91,11 +91,11 @@ static void CL_ParseNewMovevars( sizebuf_t *msg )
|
|||||||
|
|
||||||
typedef struct delta_header_t
|
typedef struct delta_header_t
|
||||||
{
|
{
|
||||||
qboolean remove : 1;
|
qboolean remove;
|
||||||
qboolean custom : 1;
|
qboolean custom;
|
||||||
qboolean instanced : 1;
|
qboolean instanced;
|
||||||
uint instanced_baseline_index : 6;
|
uint16_t instanced_baseline_index;
|
||||||
uint offset : 6;
|
uint16_t offset;
|
||||||
} 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,33 +160,47 @@ static int CL_GetEntityDelta( const struct delta_header_t *hdr, int entnum )
|
|||||||
return DT_ENTITY_STATE_T;
|
return DT_ENTITY_STATE_T;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void CL_FlushEntityPacketGS( frame_t *frame, sizebuf_t *msg )
|
static int 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 num = 0;
|
int newnum, bufstart;
|
||||||
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 );
|
||||||
num = CL_ParseDeltaHeader( msg, false, num, &hdr );
|
numbase = newnum = CL_ParseDeltaHeader( msg, true, numbase, &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, num ), &from, &to, cl.mtime[0] );
|
Delta_ReadGSFields( msg, CL_GetEntityDelta( &hdr, newnum ), &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 )
|
||||||
@@ -203,7 +217,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", __func__, newnum );
|
Host_Error( "%s: bad delta entity number: %i\n", __func__, newnum );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -267,7 +281,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, newnum, oldnum, numbase = 0;
|
int oldindex, oldnum, numbase = 0;
|
||||||
entity_state_t *oldent;
|
entity_state_t *oldent;
|
||||||
int count;
|
int count;
|
||||||
int playerbytes = 0;
|
int playerbytes = 0;
|
||||||
@@ -314,7 +328,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;
|
int bufstart, newnum;
|
||||||
qboolean player;
|
qboolean player;
|
||||||
delta_header_t hdr;
|
delta_header_t hdr;
|
||||||
int val = MSG_ReadWord( msg );
|
int val = MSG_ReadWord( msg );
|
||||||
@@ -534,7 +548,7 @@ void CL_ParseGoldSrcServerMessage( sizebuf_t *msg )
|
|||||||
{
|
{
|
||||||
if( MSG_CheckOverflow( msg ))
|
if( MSG_CheckOverflow( msg ))
|
||||||
{
|
{
|
||||||
Host_Error( "CL_ParseServerMessage: overflow!\n" );
|
Host_Error( "%s: overflow!\n", __func__ );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -233,6 +233,11 @@ 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,
|
||||||
@@ -258,16 +263,16 @@ static render_api_t gRenderAPI =
|
|||||||
NULL, // DrawSingleDecal,
|
NULL, // DrawSingleDecal,
|
||||||
NULL, // R_DecalSetupVerts,
|
NULL, // R_DecalSetupVerts,
|
||||||
NULL, // R_EntityRemoveDecals,
|
NULL, // R_EntityRemoveDecals,
|
||||||
(void*)AVI_LoadVideo,
|
AVI_LoadVideo,
|
||||||
(void*)AVI_GetVideoInfo,
|
AVI_GetVideoInfo,
|
||||||
(void*)AVI_GetVideoFrameNumber,
|
AVI_GetVideoFrameNumber,
|
||||||
(void*)AVI_GetVideoFrame,
|
AVI_GetVideoFrame,
|
||||||
NULL, // R_UploadStretchRaw,
|
NULL, // R_UploadStretchRaw,
|
||||||
(void*)AVI_FreeVideo,
|
AVI_FreeVideo,
|
||||||
(void*)AVI_IsActive,
|
AVI_IsActive,
|
||||||
S_StreamAviSamples,
|
pfnAVI_StreamSound,
|
||||||
NULL,
|
AVI_Think,
|
||||||
NULL,
|
AVI_SetParm,
|
||||||
NULL, // GL_Bind,
|
NULL, // GL_Bind,
|
||||||
NULL, // GL_SelectTexture,
|
NULL, // GL_SelectTexture,
|
||||||
NULL, // GL_LoadTexMatrixExt,
|
NULL, // GL_LoadTexMatrixExt,
|
||||||
|
|||||||
@@ -24,11 +24,6 @@ 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;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -88,7 +83,17 @@ void SCR_CheckStartupVids( void )
|
|||||||
char *pfile;
|
char *pfile;
|
||||||
string token;
|
string token;
|
||||||
|
|
||||||
if( Sys_CheckParm( "-nointro" ) || host_developer.value || cls.demonum != -1 || GameState->nextstate != STATE_RUNFRAME )
|
#if 0
|
||||||
|
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;
|
||||||
@@ -147,23 +152,9 @@ 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 );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -176,21 +167,11 @@ should be skipped
|
|||||||
*/
|
*/
|
||||||
qboolean SCR_DrawCinematic( void )
|
qboolean SCR_DrawCinematic( void )
|
||||||
{
|
{
|
||||||
static int last_frame = -1;
|
if( !ref.initialized )
|
||||||
qboolean redraw = false;
|
|
||||||
byte *frame = NULL;
|
|
||||||
|
|
||||||
if( !ref.initialized || cin_time <= 0.0f )
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if( cin_frame != last_frame )
|
if( !AVI_Think( cin_state ))
|
||||||
{
|
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;
|
||||||
}
|
}
|
||||||
@@ -219,45 +200,28 @@ qboolean SCR_PlayCinematic( const char *arg )
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( !( AVI_GetVideoInfo( cin_state, &xres, &yres, &video_duration ))) // couldn't open this at all.
|
if( AVI_HaveAudioTrack( cin_state ))
|
||||||
{
|
|
||||||
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
|
||||||
@@ -270,7 +234,6 @@ 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;
|
||||||
|
|||||||
@@ -688,6 +688,7 @@ 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;
|
||||||
@@ -767,7 +768,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( const byte *buffer, size_t size );
|
void CL_WriteDemoUserMessage( int size, byte *buffer );
|
||||||
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 );
|
||||||
@@ -1119,7 +1120,7 @@ void Con_PageUp( int lines );
|
|||||||
//
|
//
|
||||||
// s_main.c
|
// s_main.c
|
||||||
//
|
//
|
||||||
void S_StreamAviSamples( void *Avi, int entnum, float fvol, float attn, float synctime );
|
typedef int sound_t;
|
||||||
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 );
|
||||||
@@ -1208,6 +1209,13 @@ 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;
|
||||||
|
|||||||
@@ -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\\Xash3D\\", "xash_id", szBuf, MAX_PATH );
|
ID_GetKeyData( HKEY_CURRENT_USER, "Software\\"XASH_ENGINE_NAME"\\", "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\\Xash3D\\", REG_SZ, "xash_id", Buf, Q_strlen(Buf) );
|
ID_SetKeyData( HKEY_CURRENT_USER, "Software\\"XASH_ENGINE_NAME"\\", REG_SZ, "xash_id", Buf, Q_strlen(Buf) );
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
{
|
{
|
||||||
@@ -902,9 +902,10 @@ 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, *texture, *command;
|
const char *name, *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 )
|
||||||
{
|
{
|
||||||
@@ -913,9 +914,18 @@ static void Touch_AddButton_f( void )
|
|||||||
}
|
}
|
||||||
|
|
||||||
name = Cmd_Argv( 1 );
|
name = Cmd_Argv( 1 );
|
||||||
texture = Cmd_Argv( 2 );
|
Q_strncpy( texture, Cmd_Argv( 2 ), sizeof( texture ));
|
||||||
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;
|
||||||
|
|||||||
@@ -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_SCROLLOCK, "" },
|
{"SCROLLOCK", K_SCROLLLOCK, "" },
|
||||||
{"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_SCROLLOCK )
|
if( keynum > 32 && keynum < 127 && keynum != '"' && keynum != ';' && keynum != K_SCROLLLOCK )
|
||||||
{
|
{
|
||||||
tinystr[0] = keynum;
|
tinystr[0] = keynum;
|
||||||
tinystr[1] = 0;
|
tinystr[1] = 0;
|
||||||
@@ -861,7 +861,9 @@ void GAME_EXPORT Key_ClearStates( void )
|
|||||||
|
|
||||||
for( i = 0; i < 256; i++ )
|
for( i = 0; i < 256; i++ )
|
||||||
{
|
{
|
||||||
if( keys[i].down && i < K_MOUSE1 && i > K_MOUSE5 )
|
if( 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;
|
||||||
@@ -869,9 +871,6 @@ 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();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 *)Z_Calloc( cur->cdelaysamplesmax * sizeof( int ));
|
cur->lpdelayline = (int *)Mem_Calloc( sndpool, cur->cdelaysamplesmax * sizeof( int ));
|
||||||
cur->xfade = 0;
|
cur->xfade = 0;
|
||||||
|
|
||||||
// init modulation
|
// init modulation
|
||||||
|
|||||||
@@ -107,17 +107,18 @@ 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 ));
|
sc = Mem_Calloc( sndpool, sizeof( wavdata_t ) + size );
|
||||||
|
sc->width = width;
|
||||||
sc->width = 2;
|
sc->channels = channels;
|
||||||
sc->channels = 1;
|
|
||||||
sc->loopStart = 0;
|
|
||||||
sc->rate = SOUND_DMA_SPEED;
|
sc->rate = SOUND_DMA_SPEED;
|
||||||
sc->samples = SOUND_DMA_SPEED;
|
sc->samples = samples;
|
||||||
sc->size = sc->samples * sc->width * sc->channels;
|
sc->size = size;
|
||||||
sc->buffer = Mem_Calloc( sndpool, sc->size );
|
|
||||||
|
|
||||||
return sc;
|
return sc;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,8 +20,6 @@ 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;
|
||||||
@@ -1111,7 +1109,7 @@ rawchan_t *S_FindRawChannel( int entnum, qboolean create )
|
|||||||
S_RawSamplesStereo
|
S_RawSamplesStereo
|
||||||
===================
|
===================
|
||||||
*/
|
*/
|
||||||
static uint S_RawSamplesStereo( portable_samplepair_t *rawsamples, uint rawend, uint max_samples, uint samples, uint rate, word width, word channels, const byte *data )
|
uint 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;
|
||||||
@@ -1193,100 +1191,6 @@ 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
|
||||||
@@ -1690,7 +1594,6 @@ void SND_UpdateSound( void )
|
|||||||
}
|
}
|
||||||
|
|
||||||
S_StreamBackgroundTrack ();
|
S_StreamBackgroundTrack ();
|
||||||
S_StreamSoundTrack ();
|
|
||||||
|
|
||||||
// mix some sound
|
// mix some sound
|
||||||
S_UpdateChannels ();
|
S_UpdateChannels ();
|
||||||
@@ -1954,14 +1857,15 @@ 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;
|
||||||
|
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ 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
|
||||||
@@ -212,7 +213,7 @@ void S_StreamBackgroundTrack( void )
|
|||||||
|
|
||||||
while( ch->s_rawend < soundtime + ch->max_samples )
|
while( ch->s_rawend < soundtime + ch->max_samples )
|
||||||
{
|
{
|
||||||
wavdata_t *info = FS_StreamInfo( s_bgTrack.stream );
|
const stream_t *info = s_bgTrack.stream;
|
||||||
|
|
||||||
bufferSamples = ch->max_samples - (ch->s_rawend - soundtime);
|
bufferSamples = ch->max_samples - (ch->s_rawend - soundtime);
|
||||||
|
|
||||||
@@ -241,7 +242,7 @@ void S_StreamBackgroundTrack( void )
|
|||||||
if( r > 0 )
|
if( r > 0 )
|
||||||
{
|
{
|
||||||
// add to raw buffer
|
// add to raw buffer
|
||||||
S_RawSamples( fileSamples, info->rate, info->width, info->channels, raw, S_RAW_SOUND_BACKGROUNDTRACK );
|
S_RawEntSamples( S_RAW_SOUND_BACKGROUNDTRACK, fileSamples, info->rate, info->width, info->channels, raw, 255 );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -286,66 +287,3 @@ 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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -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( host.mempool, size );
|
rgpszrawsentence[index] = Mem_Malloc( sndpool, size );
|
||||||
memcpy( rgpszrawsentence[index], name, size );
|
memcpy( rgpszrawsentence[index], name, size );
|
||||||
rgpszrawsentence[index][size - 1] = 0;
|
rgpszrawsentence[index][size - 1] = 0;
|
||||||
cszrawsentences++;
|
cszrawsentences++;
|
||||||
|
|||||||
@@ -114,7 +114,6 @@ 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;
|
||||||
@@ -171,12 +170,15 @@ 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 8192
|
#define MAX_RAW_SAMPLES 16384
|
||||||
|
#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;
|
||||||
@@ -242,8 +244,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 );
|
||||||
@@ -263,7 +265,6 @@ 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 );
|
||||||
|
|||||||
@@ -29,17 +29,20 @@ 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_Calloc( host.soundpool, sizeof( wavdata_t ));
|
wavdata_t *pack = Mem_Malloc( host.soundpool, sizeof( *pack ) + sound.size );
|
||||||
|
|
||||||
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->channels = sound.channels;
|
pack->type = sound.type;
|
||||||
pack->flags = sound.flags;
|
pack->flags = sound.flags;
|
||||||
|
pack->rate = sound.rate;
|
||||||
|
pack->width = sound.width;
|
||||||
|
pack->channels = sound.channels;
|
||||||
|
memcpy( pack->buffer, sound.wav, sound.size );
|
||||||
|
|
||||||
|
Mem_Free( sound.wav );
|
||||||
|
sound.wav = NULL;
|
||||||
|
|
||||||
return pack;
|
return pack;
|
||||||
}
|
}
|
||||||
@@ -132,7 +135,6 @@ 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 );
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -199,33 +201,6 @@ 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
|
||||||
|
|||||||
@@ -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 128 // 128 * 4 * 4 == 2048 bytes
|
#define HASH_SIZE 64 // 64 * 4 * 4 == 1024 bytes
|
||||||
|
|
||||||
typedef struct base_command_hashmap_s base_command_hashmap_t;
|
typedef struct base_command_hashmap_s base_command_hashmap_t;
|
||||||
|
|
||||||
@@ -26,10 +26,11 @@ 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[1]; // key for searching
|
char name[]; // 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 )
|
||||||
|
|
||||||
@@ -42,11 +43,27 @@ 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 = bucket;
|
base_command_hashmap_t *i;
|
||||||
for( ; i && ( i->type != type || Q_stricmp( name, i->name ) ); // filter out
|
|
||||||
i = i->next );
|
|
||||||
|
|
||||||
return i;
|
for( i = bucket; i != NULL; i = i->next )
|
||||||
|
{
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -90,27 +107,31 @@ 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 )
|
||||||
{
|
{
|
||||||
if( !Q_stricmp( i->name, name ) )
|
int cmp = Q_stricmp( i->name, name );
|
||||||
|
|
||||||
|
if( cmp < 0 )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if( cmp > 0 )
|
||||||
|
break;
|
||||||
|
|
||||||
|
switch( i->type )
|
||||||
{
|
{
|
||||||
switch( i->type )
|
case HM_CMD:
|
||||||
{
|
*cmd = i->basecmd;
|
||||||
case HM_CMD:
|
break;
|
||||||
*cmd = i->basecmd;
|
case HM_CMDALIAS:
|
||||||
break;
|
*alias = i->basecmd;
|
||||||
case HM_CMDALIAS:
|
break;
|
||||||
*alias = i->basecmd;
|
case HM_CVAR:
|
||||||
break;
|
*cvar = i->basecmd;
|
||||||
case HM_CVAR:
|
break;
|
||||||
*cvar = i->basecmd;
|
default:
|
||||||
break;
|
break;
|
||||||
default: break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -128,14 +149,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 = Z_Malloc( sizeof( base_command_hashmap_t ) + len );
|
elem = Mem_Malloc( basecmd_pool, sizeof( base_command_hashmap_t ) + len + 1 );
|
||||||
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_strcmp( find->name, elem->name ) < 0;
|
find && Q_stricmp( 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;
|
||||||
@@ -156,9 +177,23 @@ 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 &&
|
for( prev = NULL, i = hashed_cmds[hash]; i != NULL; prev = i, i = i->next )
|
||||||
( Q_strcmp( i->name, name ) || i->type != type); // filter out
|
{
|
||||||
prev = i, i = i->next );
|
int cmp;
|
||||||
|
|
||||||
|
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 )
|
||||||
{
|
{
|
||||||
@@ -183,9 +218,15 @@ 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
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ 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 );
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ 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 );
|
||||||
|
|
||||||
@@ -432,7 +433,7 @@ static void Cmd_Alias_f( void )
|
|||||||
{
|
{
|
||||||
if( !Q_strcmp( s, a->name ))
|
if( !Q_strcmp( s, a->name ))
|
||||||
{
|
{
|
||||||
Z_Free( a->value );
|
Mem_Free( a->value );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -441,7 +442,7 @@ static void Cmd_Alias_f( void )
|
|||||||
{
|
{
|
||||||
cmdalias_t *cur, *prev;
|
cmdalias_t *cur, *prev;
|
||||||
|
|
||||||
a = Z_Malloc( sizeof( cmdalias_t ));
|
a = Mem_Malloc( cmd_pool, sizeof( cmdalias_t ));
|
||||||
|
|
||||||
Q_strncpy( a->name, s, sizeof( a->name ));
|
Q_strncpy( a->name, s, sizeof( a->name ));
|
||||||
|
|
||||||
@@ -469,7 +470,7 @@ static void Cmd_Alias_f( void )
|
|||||||
}
|
}
|
||||||
|
|
||||||
Q_strncat( cmd, "\n", sizeof( cmd ));
|
Q_strncat( cmd, "\n", sizeof( cmd ));
|
||||||
a->value = copystring( cmd );
|
a->value = copystringpool( cmd_pool, cmd );
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -529,7 +530,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;
|
||||||
@@ -636,7 +637,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++ )
|
||||||
Z_Free( cmd_argv[i] );
|
Mem_Free( cmd_argv[i] );
|
||||||
|
|
||||||
cmd_argc = 0; // clear previous args
|
cmd_argc = 0; // clear previous args
|
||||||
cmd_args = NULL;
|
cmd_args = NULL;
|
||||||
@@ -670,7 +671,7 @@ void Cmd_TokenizeString( const char *text )
|
|||||||
|
|
||||||
if( cmd_argc < MAX_CMD_TOKENS )
|
if( cmd_argc < MAX_CMD_TOKENS )
|
||||||
{
|
{
|
||||||
cmd_argv[cmd_argc] = copystring( cmd_token );
|
cmd_argv[cmd_argc] = copystringpool( cmd_pool, cmd_token );
|
||||||
cmd_argc++;
|
cmd_argc++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -683,7 +684,8 @@ 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 ))
|
||||||
{
|
{
|
||||||
@@ -707,8 +709,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 ))
|
||||||
{
|
{
|
||||||
Mem_Free( cmd->desc );
|
desc_len = Q_strlen( cmd->desc ) + 1;
|
||||||
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;
|
||||||
|
|
||||||
@@ -723,9 +725,10 @@ 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
|
||||||
cmd = Z_Malloc( sizeof( cmd_t ) );
|
desc_len = Q_strlen( cmd_desc ) + 1;
|
||||||
cmd->name = copystring( cmd_name );
|
cmd = Mem_Malloc( cmd_pool, sizeof( cmd_t ) + desc_len );
|
||||||
cmd->desc = copystring( cmd_desc );
|
cmd->name = copystringpool( cmd_pool, cmd_name );
|
||||||
|
Q_strncpy( cmd->desc, cmd_desc, desc_len );
|
||||||
cmd->function = function;
|
cmd->function = function;
|
||||||
cmd->flags = iFlags;
|
cmd->flags = iFlags;
|
||||||
|
|
||||||
@@ -772,9 +775,6 @@ 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,7 +1202,6 @@ 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++;
|
||||||
@@ -1340,6 +1339,7 @@ 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,6 +1366,11 @@ 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"
|
||||||
|
|
||||||
|
|||||||
@@ -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"
|
||||||
#include "cvar.h"
|
|
||||||
#include "con_nprint.h"
|
|
||||||
#include "crclib.h"
|
|
||||||
#include "ref_api.h"
|
|
||||||
#define FSCALLBACK_OVERRIDE_OPEN
|
#define FSCALLBACK_OVERRIDE_OPEN
|
||||||
#define FSCALLBACK_OVERRIDE_LOADFILE
|
#define FSCALLBACK_OVERRIDE_LOADFILE
|
||||||
#define FSCALLBACK_OVERRIDE_MALLOC_LIKE
|
#define FSCALLBACK_OVERRIDE_MALLOC_LIKE
|
||||||
#include "fscallback.h"
|
#include "fscallback.h"
|
||||||
|
#include "cvar.h"
|
||||||
|
#include "con_nprint.h"
|
||||||
|
#include "crclib.h"
|
||||||
|
#include "ref_api.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,6 +146,11 @@ 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
|
||||||
@@ -432,6 +437,7 @@ 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 );
|
||||||
|
|
||||||
@@ -513,27 +519,27 @@ typedef enum
|
|||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
word rate; // num samples per second (e.g. 11025 - 11 khz)
|
size_t size; // for bounds checking
|
||||||
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
|
||||||
byte *buffer; // sound buffer
|
word rate; // num samples per second (e.g. 11025 - 11 khz)
|
||||||
size_t size; // for bounds checking
|
byte width; // resolution - bum bits divided by 8 (8 bit is 1, 16 bit is 2)
|
||||||
|
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 );
|
||||||
@@ -578,11 +584,19 @@ 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 );
|
||||||
@@ -620,6 +634,7 @@ 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 );
|
||||||
@@ -670,6 +685,7 @@ 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 );
|
||||||
@@ -703,13 +719,32 @@ 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_Initialized( void );
|
qboolean CL_DisableVisibility( 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 );
|
||||||
@@ -727,13 +762,7 @@ 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 );
|
||||||
@@ -755,8 +784,6 @@ 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 );
|
||||||
@@ -846,13 +873,6 @@ 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
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ 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
|
||||||
@@ -432,7 +433,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 = copystring( value );
|
var->string = copystringpool( cvar_pool, value );
|
||||||
var->value = Q_atof( var->string );
|
var->value = Q_atof( var->string );
|
||||||
SetBits( var->flags, flags );
|
SetBits( var->flags, flags );
|
||||||
|
|
||||||
@@ -452,18 +453,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 = copystring( var_desc );
|
var->desc = copystringpool( cvar_pool, var_desc );
|
||||||
}
|
}
|
||||||
|
|
||||||
return var;
|
return var;
|
||||||
}
|
}
|
||||||
|
|
||||||
// allocate a new cvar
|
// allocate a new cvar
|
||||||
var = Z_Malloc( sizeof( *var ));
|
var = Mem_Malloc( cvar_pool, sizeof( *var ));
|
||||||
var->name = copystring( name );
|
var->name = copystringpool( cvar_pool, name );
|
||||||
var->string = copystring( value );
|
var->string = copystringpool( cvar_pool, value );
|
||||||
var->def_string = copystring( value );
|
var->def_string = copystringpool( cvar_pool, value );
|
||||||
var->desc = copystring( var_desc );
|
var->desc = copystringpool( cvar_pool, var_desc );
|
||||||
var->value = Q_atof( var->string );
|
var->value = Q_atof( var->string );
|
||||||
var->flags = flags|FCVAR_ALLOCATED;
|
var->flags = flags|FCVAR_ALLOCATED;
|
||||||
|
|
||||||
@@ -549,7 +550,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 = copystring( var->string );
|
var->string = copystringpool( cvar_pool, 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)
|
||||||
@@ -679,7 +680,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 = copystring( pszValue );
|
var->string = copystringpool( cvar_pool, pszValue );
|
||||||
var->value = Q_atof( var->string );
|
var->value = Q_atof( var->string );
|
||||||
|
|
||||||
// tell engine about changes
|
// tell engine about changes
|
||||||
@@ -738,7 +739,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 = copystring( pszValue );
|
var->string = copystringpool( cvar_pool, pszValue );
|
||||||
var->value = Q_atof( var->string );
|
var->value = Q_atof( var->string );
|
||||||
|
|
||||||
// tell engine about changes
|
// tell engine about changes
|
||||||
@@ -781,7 +782,7 @@ void Cvar_FullSet( const char *var_name, const char *value, int flags )
|
|||||||
}
|
}
|
||||||
|
|
||||||
freestring( var->string );
|
freestring( var->string );
|
||||||
var->string = copystring( value );
|
var->string = copystringpool( cvar_pool, value );
|
||||||
var->value = Q_atof( var->string );
|
var->value = Q_atof( var->string );
|
||||||
SetBits( var->flags, flags );
|
SetBits( var->flags, flags );
|
||||||
|
|
||||||
@@ -1189,6 +1190,7 @@ 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
|
||||||
@@ -1196,7 +1198,9 @@ static void Cvar_List_f( void )
|
|||||||
if( match && !Q_strnicmpext( match, var->name, matchlen ))
|
if( match && !Q_strnicmpext( match, var->name, matchlen ))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if( Q_colorstr( var->string ))
|
p = Q_strchr( 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 );
|
||||||
|
|
||||||
@@ -1257,7 +1261,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( host.mempool, sizeof( *list ) + namelen );
|
p = Mem_Malloc( cvar_pool, 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;
|
||||||
@@ -1333,6 +1337,7 @@ 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 );
|
||||||
@@ -1345,6 +1350,11 @@ 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
|
||||||
|
|||||||
@@ -30,6 +30,8 @@ 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 );
|
||||||
@@ -52,6 +54,7 @@ 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 );
|
||||||
|
|
||||||
|
|||||||
@@ -49,52 +49,6 @@ 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 )
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -130,16 +84,6 @@ void CL_WriteMessageHistory( void )
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Host_ClientBegin( void )
|
|
||||||
{
|
|
||||||
Cbuf_Execute();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Host_ClientFrame( void )
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void Host_InputFrame( void )
|
void Host_InputFrame( void )
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -159,11 +103,6 @@ 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 )
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -174,11 +113,6 @@ void CL_Disconnect( void )
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CL_Shutdown( void )
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void R_ClearStaticEntities( void )
|
void R_ClearStaticEntities( void )
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -189,11 +123,6 @@ void Host_Credits( void )
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
qboolean UI_CreditsActive( void )
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void S_StopBackgroundTrack( void )
|
void S_StopBackgroundTrack( void )
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -204,11 +133,6 @@ 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 )
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|||||||
@@ -183,14 +183,23 @@ 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 Xash3D data directory" );
|
Sys_Error( "couldn't find %s data directory", XASH_ENGINE_NAME );
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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 );
|
Platform_Init( Host_IsDedicated( ) || developer >= DEV_EXTENDED, basedir );
|
||||||
FS_Init( basedir );
|
FS_Init( basedir );
|
||||||
|
|
||||||
Sys_InitLog();
|
Sys_InitLog();
|
||||||
@@ -1256,7 +1256,6 @@ 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( ))
|
||||||
@@ -1400,6 +1399,10 @@ 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 );
|
||||||
|
|
||||||
|
|||||||
@@ -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" );
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *HPAK_TypeFromIndex( int type )
|
const char *COM_ResourceTypeFromIndex( 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;
|
MD5Context_t ctx = { 0 };
|
||||||
|
|
||||||
if( !COM_CheckString( filename ))
|
if( !COM_CheckString( filename ))
|
||||||
return;
|
return;
|
||||||
@@ -125,7 +125,6 @@ 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 )
|
||||||
@@ -214,7 +213,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;
|
MD5Context_t ctx = { 0 };
|
||||||
|
|
||||||
if( pData == NULL && pFile == NULL )
|
if( pData == NULL && pFile == NULL )
|
||||||
return;
|
return;
|
||||||
@@ -226,7 +225,6 @@ 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 )
|
||||||
@@ -463,7 +461,7 @@ static qboolean HPAK_Validate( const char *filename, qboolean quiet, qboolean de
|
|||||||
|
|
||||||
if( !quiet )
|
if( !quiet )
|
||||||
{
|
{
|
||||||
Con_Printf( "%i: %s %s %s: ", i, HPAK_TypeFromIndex( pRes->type ),
|
Con_Printf( "%i: %s %s %s: ", i, COM_ResourceTypeFromIndex( pRes->type ),
|
||||||
Q_pretifymem( pRes->nDownloadSize, 2 ), pRes->szFileName );
|
Q_pretifymem( pRes->nDownloadSize, 2 ), pRes->szFileName );
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -944,7 +942,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 = HPAK_TypeFromIndex( entry->resource.type );
|
type = COM_ResourceTypeFromIndex( 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 ));
|
||||||
@@ -1039,7 +1037,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 = HPAK_TypeFromIndex( entry->resource.type );
|
type = COM_ResourceTypeFromIndex( 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 );
|
||||||
|
|||||||
@@ -28,12 +28,20 @@ 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 != 768 )
|
if( filesize > sizeof( pal ))
|
||||||
{
|
{
|
||||||
Con_DPrintf( S_ERROR "%s: (%s) have invalid size (%li should be %d)\n", __func__, name, (long)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 ));
|
||||||
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] == '#' )
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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( mip_t *mt, qboolean palette )
|
static fs_offset_t Mod_CalculateMipTexSize( const 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, mip_t *mt, texture_t *tx, qboolean custom_palette )
|
static void Mod_InitSkyClouds( model_t *mod, const 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,9 +2516,6 @@ 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
|
||||||
@@ -2526,12 +2523,10 @@ 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];
|
||||||
// FIXME: for ENGINE_IMPROVED_LINETRACE we need to load textures on server too
|
const mip_t *mipTex = Mod_GetMipTexForTexture( bmod, textureIndex );
|
||||||
// but there is no facility for this yet
|
const qboolean usesCustomPalette = Mod_CalcMipTexUsesCustomPalette( mod, bmod, textureIndex );
|
||||||
texture = mod->textures[textureIndex];
|
const qboolean iswater = Mod_LooksLikeWaterTexture( mipTex->name );
|
||||||
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 )
|
||||||
@@ -2540,11 +2535,13 @@ 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( Mod_LooksLikeWaterTexture( mipTex->name ))
|
if( iswater )
|
||||||
SetBits( txFlags, TF_KEEP_SOURCE | TF_EXPAND_SOURCE );
|
SetBits( txFlags, TF_KEEP_SOURCE | TF_EXPAND_SOURCE );
|
||||||
|
|
||||||
// Texture loading order:
|
// Texture loading order:
|
||||||
@@ -2609,8 +2606,13 @@ 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 );
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for luma texture
|
|
||||||
texture->fb_texturenum = 0;
|
texture->fb_texturenum = 0;
|
||||||
|
|
||||||
|
// Check for luma texture
|
||||||
|
// a1ba: ignore for water because fb_texturenum will be used to store ripple texture
|
||||||
|
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" ))
|
||||||
|
|||||||
@@ -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 )
|
if( !phdr || phdr->length < sizeof( studiohdr_t )) // garbage value in length
|
||||||
return; // bad model
|
return; // bad model
|
||||||
|
|
||||||
#if !XASH_DEDICATED
|
#if !XASH_DEDICATED
|
||||||
|
|||||||
@@ -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;
|
qboolean loaded, loaded2 = false;
|
||||||
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 )
|
if( !buf || length < sizeof( uint ))
|
||||||
{
|
{
|
||||||
memset( mod, 0, sizeof( model_t ));
|
memset( mod, 0, sizeof( model_t ));
|
||||||
|
|
||||||
@@ -329,11 +329,12 @@ 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
|
||||||
{
|
{
|
||||||
loaded = ref.dllFuncs.Mod_ProcessRenderData( mod, true, buf );
|
loaded2 = ref.dllFuncs.Mod_ProcessRenderData( mod, true, buf );
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@@ -345,7 +346,7 @@ model_t *Mod_LoadModel( model_t *mod, qboolean crash )
|
|||||||
hdr->pposeverts = NULL;
|
hdr->pposeverts = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( !loaded )
|
if( !loaded || !loaded2 )
|
||||||
{
|
{
|
||||||
Mod_FreeModel( mod );
|
Mod_FreeModel( mod );
|
||||||
Mem_Free( buf );
|
Mem_Free( buf );
|
||||||
@@ -610,3 +611,41 @@ 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
|
||||||
|
|||||||
@@ -18,11 +18,177 @@ GNU General Public License for more details.
|
|||||||
#include "net_buffer.h"
|
#include "net_buffer.h"
|
||||||
#include "xash3d_mathlib.h"
|
#include "xash3d_mathlib.h"
|
||||||
|
|
||||||
// precalculated bit masks for WriteUBitLong.
|
static const uint32_t BitWriteMasks[32][32] =
|
||||||
// Using these tables instead of doing the calculations
|
{ {
|
||||||
// gives a 33% speedup in WriteUBitLong.
|
0xfffffffe, 0xfffffffc, 0xfffffff8, 0xfffffff0, 0xffffffe0, 0xffffffc0, 0xffffff80, 0xffffff00,
|
||||||
static uint32_t BitWriteMasks[32][33];
|
0xfffffe00, 0xfffffc00, 0xfffff800, 0xfffff000, 0xffffe000, 0xffffc000, 0xffff8000, 0xffff0000,
|
||||||
static uint32_t ExtraMasks[32];
|
0xfffe0000, 0xfffc0000, 0xfff80000, 0xfff00000, 0xffe00000, 0xffc00000, 0xff800000, 0xff000000,
|
||||||
|
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",
|
||||||
@@ -132,65 +298,41 @@ 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 )
|
||||||
{
|
{
|
||||||
Assert( numbits >= 0 && numbits <= 32 );
|
int nBitsLeft = numbits;
|
||||||
|
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(( sb->iCurBit + numbits ) > sb->nDataBits )
|
if( MSG_Overflow( sb, numbits ))
|
||||||
{
|
{
|
||||||
sb->bOverflow = true;
|
|
||||||
sb->iCurBit = sb->nDataBits;
|
sb->iCurBit = sb->nDataBits;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
int nBitsLeft = numbits;
|
|
||||||
int iCurBit = sb->iCurBit;
|
|
||||||
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;
|
||||||
|
((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;
|
||||||
|
iCurBit += nBitsWritten;
|
||||||
|
curData >>= nBitsWritten;
|
||||||
|
|
||||||
iCurBitMasked = iCurBit & 31;
|
iCurBitMasked = iCurBit & 31;
|
||||||
((uint32_t *)sb->pData)[iDWord] &= BitWriteMasks[iCurBitMasked][nBitsLeft];
|
((uint32_t *)sb->pData)[iDWord+1] &= BitWriteMasks[iCurBitMasked][nBitsLeft-1];
|
||||||
((uint32_t *)sb->pData)[iDWord] |= curData << iCurBitMasked;
|
((uint32_t *)sb->pData)[iDWord+1] |= 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -238,7 +380,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((( uint32_t )pOut & 3 ) != 0 && nBitsLeft >= 8 )
|
while((( uintptr_t )pOut & 3 ) != 0 && nBitsLeft >= 8 )
|
||||||
{
|
{
|
||||||
MSG_WriteUBitLong( sb, *pOut, 8 );
|
MSG_WriteUBitLong( sb, *pOut, 8 );
|
||||||
|
|
||||||
@@ -275,16 +417,14 @@ 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 )
|
||||||
{
|
{
|
||||||
uint mask, shift;
|
const uint shift = ( 1 << numbits );
|
||||||
|
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;
|
||||||
|
|
||||||
@@ -438,9 +578,8 @@ uint MSG_ReadUBitLong( sizebuf_t *sb, int numbits )
|
|||||||
return 0; // end of message
|
return 0; // end of message
|
||||||
}
|
}
|
||||||
|
|
||||||
if(( sb->iCurBit + numbits ) > sb->nDataBits )
|
if( MSG_Overflow( sb, numbits ))
|
||||||
{
|
{
|
||||||
sb->bOverflow = true;
|
|
||||||
sb->iCurBit = sb->nDataBits;
|
sb->iCurBit = sb->nDataBits;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -513,13 +652,9 @@ 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 fReturn, shift;
|
float shift = (float)( 1 << numbits );
|
||||||
int i;
|
int i = MSG_ReadUBitLong( sb, numbits );
|
||||||
|
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;
|
||||||
@@ -531,11 +666,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, sign;
|
int r;
|
||||||
|
|
||||||
if( sb->iAlternateSign )
|
if( sb->iAlternateSign )
|
||||||
{
|
{
|
||||||
sign = MSG_ReadOneBit( sb );
|
int sign = MSG_ReadOneBit( sb );
|
||||||
r = MSG_ReadUBitLong( sb, numbits - 1 );
|
r = MSG_ReadUBitLong( sb, numbits - 1 );
|
||||||
|
|
||||||
if( sign )
|
if( sign )
|
||||||
@@ -544,9 +679,7 @@ int MSG_ReadSBitLong( sizebuf_t *sb, int numbits )
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
r = MSG_ReadUBitLong( sb, numbits - 1 );
|
r = MSG_ReadUBitLong( sb, numbits - 1 );
|
||||||
sign = MSG_ReadOneBit( sb );
|
if( MSG_ReadOneBit( sb ))
|
||||||
|
|
||||||
if( sign )
|
|
||||||
r = -( BIT( numbits - 1 ) - r );
|
r = -( BIT( numbits - 1 ) - r );
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -667,12 +800,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, c;
|
int l = 0;
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
// use MSG_ReadByte so -1 is out of bounds
|
// use MSG_ReadByte so -1 is out of bounds
|
||||||
c = MSG_ReadByte( sb );
|
int c = MSG_ReadByte( sb );
|
||||||
|
|
||||||
if( c == 0 ) break;
|
if( c == 0 ) break;
|
||||||
else if( bLine && c == '\n' )
|
else if( bLine && c == '\n' )
|
||||||
@@ -865,8 +998,6 @@ 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( ));
|
||||||
|
|||||||
@@ -193,7 +193,6 @@ 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
|
||||||
|
|||||||
@@ -272,8 +272,6 @@ 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 )
|
||||||
@@ -343,6 +341,7 @@ 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 ));
|
||||||
@@ -768,7 +767,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_bz2 && !LZSS_IsCompressed( MSG_GetData( msg ), MSG_GetMaxBytes( msg )))
|
else if( chan->use_lzss && !LZSS_IsCompressed( MSG_GetData( msg ), MSG_GetMaxBytes( msg )))
|
||||||
{
|
{
|
||||||
uint uCompressedSize = 0;
|
uint uCompressedSize = 0;
|
||||||
uint uSourceSize = MSG_GetNumBytesWritten( msg );
|
uint uSourceSize = MSG_GetNumBytesWritten( msg );
|
||||||
@@ -1175,7 +1174,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];
|
||||||
@@ -1196,7 +1195,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_bz2 && LZSS_IsCompressed( MSG_GetData( msg ), size ))
|
else if( chan->use_lzss && 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];
|
||||||
@@ -1347,7 +1346,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( LZSS_IsCompressed( buffer, nsize + 1 ))
|
else if( chan->use_lzss && LZSS_IsCompressed( buffer, nsize + 1 ))
|
||||||
{
|
{
|
||||||
byte *uncompressedBuffer;
|
byte *uncompressedBuffer;
|
||||||
|
|
||||||
|
|||||||
@@ -2282,10 +2282,6 @@ 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 );
|
||||||
|
|||||||
@@ -505,11 +505,14 @@ 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 )
|
||||||
{
|
{
|
||||||
Mem_Free( data_in );
|
g_fsapi.WriteFile( name, data_out, decompressed_len );
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -214,6 +214,7 @@ 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
|
||||||
@@ -285,6 +286,7 @@ 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;
|
||||||
|
|
||||||
|
|||||||
@@ -89,16 +89,6 @@ 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;
|
||||||
@@ -378,6 +368,7 @@ 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;
|
||||||
@@ -431,22 +422,30 @@ 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 );
|
||||||
|
|
||||||
t2 = Sys_DoubleTime();
|
if( !handled )
|
||||||
|
|
||||||
if( handled )
|
|
||||||
{
|
{
|
||||||
if( t2 - t1 > 0.01f ) // critical, report to mod developer
|
// restore previously changed data
|
||||||
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 );
|
sc->rate = inrate;
|
||||||
else
|
sc->width = inwidth;
|
||||||
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 );
|
sc->channels = inchannels;
|
||||||
}
|
sc->samples = incount;
|
||||||
else
|
sc->size = insize;
|
||||||
|
|
||||||
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;
|
||||||
|
|
||||||
return 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 );
|
||||||
|
|
||||||
|
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 )
|
||||||
@@ -464,8 +463,11 @@ qboolean Sound_Process( wavdata_t **wav, int rate, int width, int channels, uint
|
|||||||
|
|
||||||
if( result )
|
if( result )
|
||||||
{
|
{
|
||||||
Mem_Free( snd->buffer ); // free original image buffer
|
snd = Mem_Realloc( host.soundpool, snd, sizeof( *snd ) + snd->size );
|
||||||
snd->buffer = Sound_Copy( snd->size ); // unzone buffer
|
memcpy( snd->buffer, sound.tempbuffer, snd->size );
|
||||||
|
|
||||||
|
Mem_Free( sound.tempbuffer );
|
||||||
|
sound.tempbuffer = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -41,6 +41,15 @@ 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 );
|
||||||
|
|||||||
@@ -68,7 +68,13 @@ 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)
|
||||||
{
|
{
|
||||||
@@ -243,6 +249,11 @@ 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>
|
||||||
@@ -265,20 +276,20 @@ int WAI_PREFIX(getModulePath)(char* out, int capacity, int* dirname_length)
|
|||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
char buffer[PATH_MAX < 1024 ? 1024 : PATH_MAX];
|
char buffer[128 + PATH_MAX];
|
||||||
uint64_t low, high;
|
uintptr_t low, high;
|
||||||
char perms[5];
|
char perms[5];
|
||||||
uint64_t offset;
|
uint64_t offset;
|
||||||
uint32_t major, minor;
|
uint32_t major, minor, inode;
|
||||||
char path[PATH_MAX];
|
char path[PATH_MAX + 1];
|
||||||
uint32_t inode;
|
|
||||||
|
|
||||||
if (!fgets(buffer, sizeof(buffer), maps))
|
if (!fgets(buffer, sizeof(buffer), maps))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (sscanf(buffer, "%" PRIx64 "-%" PRIx64 " %s %" PRIx64 " %x:%x %u %s\n", &low, &high, perms, &offset, &major, &minor, &inode, path) == 8)
|
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)
|
||||||
{
|
{
|
||||||
uint64_t addr = (uintptr_t)WAI_RETURN_ADDRESS();
|
void* _addr = WAI_RETURN_ADDRESS();
|
||||||
|
uintptr_t addr = (uintptr_t)_addr;
|
||||||
if (low <= addr && addr <= high)
|
if (low <= addr && addr <= high)
|
||||||
{
|
{
|
||||||
char* resolved;
|
char* resolved;
|
||||||
|
|||||||
@@ -31,7 +31,8 @@ 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.
|
* of the path. Available only when `capacity` is large enough to retrieve the
|
||||||
|
* 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`
|
||||||
@@ -52,7 +53,8 @@ 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.
|
* of the path. Available only when `capacity` is large enough to retrieve the
|
||||||
|
* 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`
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ GNU General Public License for more details.
|
|||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
|
||||||
#define MEMHEADER_SENTINEL1 0xDEADF00DU
|
#define MEMHEADER_SENTINEL1 0xA1BAU
|
||||||
#define MEMHEADER_SENTINEL2 0xDFU
|
#define MEMHEADER_SENTINEL2 0xDFU
|
||||||
|
|
||||||
#ifdef XASH_CUSTOM_SWAP
|
#ifdef XASH_CUSTOM_SWAP
|
||||||
@@ -51,31 +51,29 @@ 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; // next and previous memheaders in chain belonging to pool
|
struct memheader_s *next, *prev; // next and previous memheaders in chain belonging to pool
|
||||||
struct memheader_s *prev;
|
const char *filename; // file name and line where Mem_Alloc was called
|
||||||
const char *filename; // file name and line where Mem_Alloc was called
|
size_t size; // size of the memory after the header (excluding header and sentinel2)
|
||||||
size_t size; // size of the memory after the header (excluding header and sentinel2)
|
poolhandle_t poolptr; // pool this memheader belongs to
|
||||||
poolhandle_t poolptr; // pool this memheader belongs to
|
uint16_t fileline;
|
||||||
int fileline;
|
uint16_t sentinel1; // must be equal to MEMHEADER_SENTINEL1
|
||||||
#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
|
||||||
@@ -521,4 +519,5 @@ Memory_Init
|
|||||||
void Memory_Init( void )
|
void Memory_Init( void )
|
||||||
{
|
{
|
||||||
poolchain = NULL; // init mem chain
|
poolchain = NULL; // init mem chain
|
||||||
|
poolcount = 0;
|
||||||
}
|
}
|
||||||
|
|||||||
300
engine/keydefs.h
300
engine/keydefs.h
@@ -1,186 +1,164 @@
|
|||||||
/***
|
/*
|
||||||
*
|
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.
|
|
||||||
*
|
|
||||||
****/
|
|
||||||
|
|
||||||
#ifndef KEYDEFS_H
|
This program is free software; you can redistribute it and/or
|
||||||
#define KEYDEFS_H
|
modify it under the terms of the GNU General Public License
|
||||||
|
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
|
||||||
//
|
|
||||||
#define K_TAB 9
|
|
||||||
#define K_ENTER 13
|
|
||||||
#define K_ESCAPE 27
|
|
||||||
#define K_SPACE 32
|
|
||||||
#define K_SCROLLOCK 70
|
|
||||||
|
|
||||||
// normal keys should be passed as lowercased ascii
|
// normal keys should be passed as lowercased ascii
|
||||||
|
//
|
||||||
|
#define K_TAB 9
|
||||||
|
#define K_ENTER 13
|
||||||
|
#define K_ESCAPE 27
|
||||||
|
#define K_SPACE 32
|
||||||
|
#define K_SCROLLLOCK 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_BACKSPACE 127
|
#define K_KP_HOME 160
|
||||||
#define K_UPARROW 128
|
#define K_KP_UPARROW 161
|
||||||
#define K_DOWNARROW 129
|
#define K_KP_PGUP 162
|
||||||
#define K_LEFTARROW 130
|
#define K_KP_LEFTARROW 163
|
||||||
#define K_RIGHTARROW 131
|
#define K_KP_5 164
|
||||||
|
|
||||||
#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 // LTRIGGER (L2)
|
#define K_JOY1 203
|
||||||
#define K_JOY2 204 // RTRIGGER (R2)
|
#define K_JOY2 204
|
||||||
#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_A_BUTTON K_AUX1
|
#define K_AUX2 208
|
||||||
|
#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
|
//
|
||||||
#define K_B_BUTTON K_AUX2
|
// button names for game pads
|
||||||
|
//
|
||||||
#define K_AUX3 209
|
#define K_A_BUTTON K_AUX1
|
||||||
#define K_X_BUTTON K_AUX3
|
#define K_B_BUTTON K_AUX2
|
||||||
|
#define K_X_BUTTON K_AUX3
|
||||||
#define K_AUX4 210
|
#define K_Y_BUTTON K_AUX4
|
||||||
#define K_Y_BUTTON K_AUX4
|
#define K_L1_BUTTON K_AUX5
|
||||||
|
#define K_R1_BUTTON K_AUX6
|
||||||
#define K_AUX5 211
|
#define K_BACK_BUTTON K_AUX7
|
||||||
#define K_L1_BUTTON K_AUX5
|
#define K_MODE_BUTTON K_AUX8
|
||||||
|
#define K_START_BUTTON K_AUX9
|
||||||
#define K_AUX6 212
|
#define K_LSTICK K_AUX10
|
||||||
#define K_R1_BUTTON K_AUX6
|
#define K_RSTICK K_AUX11
|
||||||
|
#define K_L2_BUTTON K_AUX12
|
||||||
#define K_AUX7 213
|
#define K_R2_BUTTON K_AUX13
|
||||||
#define K_BACK_BUTTON K_AUX7
|
#define K_C_BUTTON K_AUX14
|
||||||
|
#define K_Z_BUTTON K_AUX15
|
||||||
#define K_AUX8 214
|
#define K_DPAD_UP K_AUX16
|
||||||
#define K_MODE_BUTTON K_AUX8
|
#define K_DPAD_DOWN K_AUX17
|
||||||
|
#define K_DPAD_LEFT K_AUX18
|
||||||
#define K_AUX9 215
|
#define K_DPAD_RIGHT K_AUX19
|
||||||
#define K_START_BUTTON K_AUX9
|
#define K_MISC_BUTTON K_AUX20
|
||||||
|
#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_MOUSE1 241
|
#define K_MWHEELDOWN 239
|
||||||
#define K_MOUSE2 242
|
#define K_MWHEELUP 240
|
||||||
#define K_MOUSE3 243
|
#define K_MOUSE1 241
|
||||||
#define K_MOUSE4 244
|
#define K_MOUSE2 242
|
||||||
#define K_MOUSE5 245
|
#define K_MOUSE3 243
|
||||||
|
#define K_MOUSE4 244
|
||||||
|
#define K_MOUSE5 245
|
||||||
|
|
||||||
#endif//KEYDEFS_H
|
#define K_PAUSE 255
|
||||||
|
|||||||
@@ -184,7 +184,7 @@ qboolean SNDDMA_Init( void )
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
dma.buffer = Z_Malloc( samples * 2 ); //allocate pcm frame buffer
|
dma.buffer = Mem_Malloc( sndpool, 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;
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ char *Posix_Input( void );
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if XASH_SDL
|
#if XASH_SDL
|
||||||
void SDLash_Init( void );
|
void SDLash_Init( const char *basedir );
|
||||||
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 )
|
static inline void Platform_Init( qboolean con_showalways, const char *basedir )
|
||||||
{
|
{
|
||||||
#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 )
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if XASH_SDL
|
#if XASH_SDL
|
||||||
SDLash_Init( );
|
SDLash_Init( basedir );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if XASH_ANDROID
|
#if XASH_ANDROID
|
||||||
|
|||||||
@@ -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_SCROLLOCK; break;
|
case SDL_SCANCODE_SCROLLLOCK: keynum = K_SCROLLLOCK; 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
|
||||||
|
|||||||
@@ -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 = Z_Calloc( dma.samples * 2 );
|
dma.buffer = Mem_Malloc( sndpool, dma.samples * 2 );
|
||||||
dma.samplepos = 0;
|
dma.samplepos = 0;
|
||||||
|
|
||||||
sdl_format = obtained.format;
|
sdl_format = obtained.format;
|
||||||
|
|||||||
@@ -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 longtime_t g_PerformanceFrequency;
|
static Uint64 g_PerformanceFrequency;
|
||||||
static longtime_t g_ClockStart;
|
static Uint64 g_ClockStart;
|
||||||
longtime_t CurrentTime;
|
Uint64 CurrentTime;
|
||||||
|
|
||||||
if( !g_PerformanceFrequency )
|
if( !g_PerformanceFrequency )
|
||||||
{
|
{
|
||||||
@@ -78,8 +78,19 @@ static void SDLCALL SDLash_LogOutputFunction( void *userdata, int category, SDL_
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SDLash_Init( void )
|
void SDLash_Init( const char *basedir )
|
||||||
{
|
{
|
||||||
|
#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 )
|
||||||
|
|||||||
@@ -145,7 +145,7 @@ void Wcon_ShowConsole( qboolean show )
|
|||||||
|
|
||||||
void Wcon_DisableInput( void )
|
void Wcon_DisableInput( void )
|
||||||
{
|
{
|
||||||
if( host.type != HOST_DEDICATED )
|
if( host.type != HOST_DEDICATED || !s_wcd.hWnd )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
s_wcd.inputEnabled = false;
|
s_wcd.inputEnabled = false;
|
||||||
@@ -469,6 +469,9 @@ 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 )
|
||||||
{
|
{
|
||||||
@@ -515,13 +518,18 @@ 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 );
|
||||||
@@ -570,7 +578,7 @@ register console commands (dedicated only)
|
|||||||
*/
|
*/
|
||||||
void Wcon_InitConsoleCommands( void )
|
void Wcon_InitConsoleCommands( void )
|
||||||
{
|
{
|
||||||
if( host.type != HOST_DEDICATED )
|
if( host.type != HOST_DEDICATED || !s_wcd.hWnd )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Cmd_AddCommand( "clear", Wcon_Clear_f, "clear console history" );
|
Cmd_AddCommand( "clear", Wcon_Clear_f, "clear console history" );
|
||||||
@@ -623,7 +631,7 @@ char *Wcon_Input( void )
|
|||||||
DWORD eventsCount;
|
DWORD eventsCount;
|
||||||
static INPUT_RECORD events[1024];
|
static INPUT_RECORD events[1024];
|
||||||
|
|
||||||
if( !s_wcd.inputEnabled )
|
if( !s_wcd.inputEnabled || !s_wcd.hWnd )
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
while( true )
|
while( true )
|
||||||
@@ -666,7 +674,7 @@ set server status string in console
|
|||||||
*/
|
*/
|
||||||
void Platform_SetStatus( const char *pStatus )
|
void Platform_SetStatus( const char *pStatus )
|
||||||
{
|
{
|
||||||
if( s_wcd.attached )
|
if( s_wcd.attached || !s_wcd.hWnd )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Q_strncpy( s_wcd.statusLine, pStatus, sizeof( s_wcd.statusLine ) - 1 );
|
Q_strncpy( s_wcd.statusLine, pStatus, sizeof( s_wcd.statusLine ) - 1 );
|
||||||
|
|||||||
@@ -66,6 +66,7 @@ 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 )
|
||||||
|
|
||||||
@@ -498,10 +499,24 @@ 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
|
||||||
//
|
//
|
||||||
@@ -673,7 +688,6 @@ 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 );
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -305,6 +305,7 @@ 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 )
|
||||||
{
|
{
|
||||||
@@ -431,7 +432,9 @@ static void SV_ConnectClient( netadr_t from )
|
|||||||
newcl->listeners = -1;
|
newcl->listeners = -1;
|
||||||
|
|
||||||
// initailize netchan
|
// initailize netchan
|
||||||
Netchan_Setup( NS_SERVER, &newcl->netchan, from, qport, newcl, SV_GetFragmentSize, 0 );
|
if( !Host_IsLocalClient( ))
|
||||||
|
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 );
|
||||||
@@ -450,8 +453,6 @@ 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 ));
|
||||||
|
|
||||||
@@ -477,7 +478,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.0f;
|
newcl->packet_loss = 0;
|
||||||
|
|
||||||
// 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.
|
||||||
@@ -1170,7 +1171,7 @@ SV_EstablishTimeBase
|
|||||||
Finangles latency and the like.
|
Finangles latency and the like.
|
||||||
===================
|
===================
|
||||||
*/
|
*/
|
||||||
static void SV_EstablishTimeBase( sv_client_t *cl, usercmd_t *cmds, int dropped, int numbackup, int numcmds )
|
static void SV_EstablishTimeBase( sv_client_t *cl, const 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;
|
||||||
@@ -2869,14 +2870,20 @@ 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 )
|
||||||
{
|
{
|
||||||
SAVERESTOREDATA data = { 0 };
|
ENTITYTABLE table = {
|
||||||
ENTITYTABLE table = { 0 };
|
.classname = classname,
|
||||||
data.tableCount = 1;
|
.id = -1,
|
||||||
data.pTable = &table;
|
.size = 1,
|
||||||
table.classname = classname;
|
.flags = 1337,
|
||||||
table.id = -1;
|
};
|
||||||
table.size = 1;
|
|
||||||
svgame.physFuncs.pfnCreateEntitiesInRestoreList( &data, 0, false );
|
SAVERESTOREDATA data = {
|
||||||
|
.tableCount = 1,
|
||||||
|
.pTable = &table
|
||||||
|
};
|
||||||
|
|
||||||
|
svgame.physFuncs.pfnCreateEntitiesInRestoreList( &data, table.flags, false );
|
||||||
|
|
||||||
ent = table.pent;
|
ent = table.pent;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3212,6 +3219,20 @@ 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
|
||||||
@@ -3226,29 +3247,20 @@ 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 )
|
||||||
{
|
{
|
||||||
client_frame_t *frame;
|
const usercmd_t nullcmd = { 0 }, *from = &nullcmd; // first cmd are starting from null-compressed usercmd_t
|
||||||
int key, size, checksum1, checksum2;
|
client_frame_t *frame = &cl->frames[cl->netchan.incoming_acknowledged & SV_UPDATE_MASK];
|
||||||
int i, numbackup, totalcmds, numcmds;
|
usercmd_t cmds[CMD_BACKUP] = { 0 }, *to;
|
||||||
usercmd_t nullcmd, *to, *from;
|
edict_t *player = cl->edict;
|
||||||
usercmd_t cmds[CMD_BACKUP];
|
model_t *model;
|
||||||
float packet_loss;
|
|
||||||
edict_t *player;
|
|
||||||
model_t *model;
|
|
||||||
|
|
||||||
player = cl->edict;
|
int key = MSG_GetRealBytesRead( msg );
|
||||||
|
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 )
|
||||||
@@ -3258,8 +3270,6 @@ 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];
|
||||||
@@ -3270,14 +3280,17 @@ static void SV_ParseClientMove( sv_client_t *cl, sizebuf_t *msg )
|
|||||||
if( cl->state != cs_spawned )
|
if( cl->state != cs_spawned )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// if the checksum fails, ignore the rest of the packet
|
if( !Host_IsLocalClient( ))
|
||||||
size = MSG_GetRealBytesRead( msg ) - key - 1;
|
|
||||||
checksum2 = CRC32_BlockSequence( msg->pData + key + 1, size, cl->netchan.incoming_sequence );
|
|
||||||
|
|
||||||
if( checksum2 != checksum1 )
|
|
||||||
{
|
{
|
||||||
Con_Reportf( S_ERROR "%s: failed command checksum for %s (%d != %d)\n", __func__, cl->name, checksum2, checksum1 );
|
// if the checksum fails, ignore the rest of the packet
|
||||||
return;
|
int size = MSG_GetRealBytesRead( msg ) - key - 1;
|
||||||
|
int checksum2 = CRC32_BlockSequence( msg->pData + key + 1, size, cl->netchan.incoming_sequence );
|
||||||
|
|
||||||
|
if( checksum2 != checksum1 )
|
||||||
|
{
|
||||||
|
Con_Reportf( S_ERROR "%s: failed command checksum for %s (%d != %d)\n", __func__, cl->name, checksum2, checksum1 );
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cl->packet_loss = packet_loss;
|
cl->packet_loss = packet_loss;
|
||||||
|
|||||||
@@ -492,14 +492,15 @@ 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 packet_loss;
|
int i;
|
||||||
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;
|
||||||
|
|
||||||
|
|||||||
@@ -273,20 +273,6 @@ 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 )))
|
||||||
|
|||||||
@@ -23,19 +23,6 @@ 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 );
|
||||||
|
|||||||
@@ -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 Xash3D unsupported>", MAX_STRING );
|
Q_strncpy( comment, "<old version "XASH_ENGINE_NAME" unsupported>", MAX_STRING );
|
||||||
FS_Close( f );
|
FS_Close( f );
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,23 @@ 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')
|
||||||
|
|
||||||
@@ -35,6 +52,9 @@ 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):
|
||||||
@@ -125,6 +145,20 @@ 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)
|
||||||
@@ -185,6 +219,13 @@ 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
|
||||||
|
|||||||
@@ -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_RANDOM );
|
asset = AAssetManager_open( search->assets->asset_manager, path, AASSET_MODE_BUFFER );
|
||||||
if( !asset )
|
if( !asset )
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
|||||||
@@ -49,6 +49,7 @@ 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
|
||||||
@@ -447,6 +448,7 @@ 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;
|
||||||
|
|
||||||
@@ -468,6 +470,12 @@ 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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -628,13 +636,11 @@ 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 )
|
||||||
@@ -700,6 +706,9 @@ 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 )
|
||||||
@@ -1120,7 +1129,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/%s", fs_rootdir, gamedir );
|
Q_snprintf( gamedir_path, sizeof( gamedir_path ), "%s", gamedir );
|
||||||
|
|
||||||
if( !FS_CheckForXashGameDir( gamedir_path ))
|
if( !FS_CheckForXashGameDir( gamedir_path ))
|
||||||
{
|
{
|
||||||
@@ -1190,11 +1199,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
|
||||||
@@ -1205,12 +1214,21 @@ 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 );
|
||||||
if( !FI.games[i]->added && Q_stricmp( FI.games[i]->gamefolder, FI.games[i]->basedir ))
|
FI.games[i]->added = true;
|
||||||
{
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1267,6 +1285,8 @@ 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 );
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2222,6 +2242,12 @@ 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;
|
||||||
}
|
}
|
||||||
@@ -2327,7 +2353,93 @@ 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 );
|
FS_EnsureOpenFile( file ); // FIXME: broken XASH_REDUCE_FD in case of compressed files!
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
@@ -2543,11 +2655,59 @@ 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;
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -2705,25 +2865,20 @@ 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;
|
||||||
byte buffer[1024];
|
MD5Context_t MD5_Hash = { 0 };
|
||||||
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 )
|
||||||
{
|
{
|
||||||
bytes = FS_Read( file, buffer, sizeof( buffer ));
|
byte buffer[1024];
|
||||||
|
int bytes = FS_Read( file, buffer, sizeof( buffer ));
|
||||||
|
|
||||||
if( bytes > 0 )
|
if( bytes > 0 )
|
||||||
MD5Update( &MD5_Hash, buffer, bytes );
|
MD5Update( &MD5_Hash, buffer, bytes );
|
||||||
|
|||||||
@@ -143,6 +143,8 @@ 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 );
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ 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>
|
||||||
@@ -40,6 +41,16 @@ 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
|
||||||
{
|
{
|
||||||
@@ -50,6 +61,8 @@ 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
|
||||||
|
|||||||
@@ -92,20 +92,19 @@ struct wfile_s
|
|||||||
|
|
||||||
typedef struct wadtype_s
|
typedef struct wadtype_s
|
||||||
{
|
{
|
||||||
const char *ext;
|
char ext[4];
|
||||||
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[7] =
|
static const wadtype_t wad_types[] =
|
||||||
{
|
{
|
||||||
{ "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 }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -117,18 +116,19 @@ 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 );
|
||||||
const wadtype_t *type;
|
int i;
|
||||||
|
|
||||||
// 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( type = wad_types; type->ext; type++ )
|
for( i = 0; i < sizeof( wad_types ) / sizeof( wad_types[0] ); i++ )
|
||||||
{
|
{
|
||||||
if( !Q_stricmp( ext, type->ext ))
|
if( !Q_stricmp( ext, wad_types[i].ext ))
|
||||||
return type->type;
|
return wad_types[i].type;
|
||||||
}
|
}
|
||||||
|
|
||||||
return TYP_NONE;
|
return TYP_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -141,17 +141,18 @@ Convert type to extension
|
|||||||
*/
|
*/
|
||||||
static const char *W_ExtFromType( signed char lumptype )
|
static const char *W_ExtFromType( signed char lumptype )
|
||||||
{
|
{
|
||||||
const wadtype_t *type;
|
int i;
|
||||||
|
|
||||||
// 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( type = wad_types; type->ext; type++ )
|
for( i = 0; i < sizeof( wad_types ) / sizeof( wad_types[0] ); i++ )
|
||||||
{
|
{
|
||||||
if( lumptype == type->type )
|
if( lumptype == wad_types[i].type )
|
||||||
return type->ext;
|
return wad_types[i].ext;
|
||||||
}
|
}
|
||||||
|
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,7 +27,6 @@ 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')
|
||||||
@@ -389,15 +388,43 @@ 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 );
|
||||||
|
|
||||||
// compressed files handled in Zip_LoadFile
|
if( !f )
|
||||||
if( pfile->flags != ZIP_COMPRESSION_NO_COMPRESSION )
|
return NULL;
|
||||||
|
|
||||||
|
if( pfile->flags == ZIP_COMPRESSION_DEFLATED )
|
||||||
{
|
{
|
||||||
Con_Printf( S_ERROR "%s: can't open compressed file %s\n", __func__, pfile->name );
|
ztoolkit_t *ztk;
|
||||||
|
|
||||||
|
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 FS_OpenHandle( search, search->zip->handle->handle, pfile->offset, pfile->size );
|
return f;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -33,26 +33,6 @@ 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;
|
||||||
|
|||||||
@@ -70,7 +70,6 @@ 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 );
|
||||||
@@ -108,6 +107,12 @@ 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 );
|
||||||
|
|
||||||
|
|||||||
@@ -46,17 +46,6 @@ 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";
|
||||||
@@ -93,11 +82,6 @@ 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 )
|
||||||
|
|||||||
@@ -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( *m ));
|
memset( m, 0, sizeof( matrix3x4 ));
|
||||||
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( *m ));
|
memset( m, 0, sizeof( matrix4x4 ));
|
||||||
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 ))
|
||||||
|
|||||||
@@ -88,11 +88,13 @@ 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 || tx->gl_texturenum == tr.defaultTexture )
|
if( !tx )
|
||||||
continue; // free slot
|
continue; // free slot
|
||||||
|
|
||||||
GL_FreeTexture( tx->gl_texturenum ); // main texture
|
if( tx->gl_texturenum != tr.defaultTexture )
|
||||||
GL_FreeTexture( tx->fb_texturenum ); // luma texture
|
GL_FreeTexture( tx->gl_texturenum ); // main texture
|
||||||
|
GL_FreeTexture( tx->fb_texturenum ); // luma texture
|
||||||
|
GL_FreeTexture( tx->dt_texturenum ); // detail texture
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -122,33 +124,35 @@ 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 = true;
|
qboolean loaded = false;
|
||||||
|
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|
||||||
void GL_FrustumSetPlane( gl_frustum_t *out, int side, const vec3_t vecNormal, float flDist )
|
static 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 );
|
||||||
|
|
||||||
|
|||||||
@@ -33,7 +33,6 @@ 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 );
|
||||||
|
|||||||
@@ -2338,7 +2338,6 @@ 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" );
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -130,7 +130,6 @@ 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;
|
||||||
@@ -438,8 +437,6 @@ 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 );
|
||||||
@@ -503,10 +500,9 @@ 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( const texture_t *image );
|
qboolean R_UploadRipples( texture_t *image );
|
||||||
|
|
||||||
//#include "vid_common.h"
|
//#include "vid_common.h"
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
===============
|
===============
|
||||||
*/
|
*/
|
||||||
texture_t *R_TextureAnimation( msurface_t *s )
|
static 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
|
||||||
================
|
================
|
||||||
*/
|
*/
|
||||||
void DrawGLPoly( glpoly2_t *p, float xScale, float yScale )
|
static 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];
|
||||||
|
|
||||||
struct vbo_static_s
|
static 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 @@ struct vbo_static_s
|
|||||||
qboolean enabled;
|
qboolean enabled;
|
||||||
} vbos;
|
} vbos;
|
||||||
|
|
||||||
struct multitexturestate_s
|
static struct multitexturestate_s
|
||||||
{
|
{
|
||||||
int tmu_gl; // texture tmu
|
int tmu_gl; // texture tmu
|
||||||
int tmu_dt; // detail tmu
|
int tmu_dt; // detail tmu
|
||||||
|
|||||||
@@ -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,31 +179,32 @@ 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, 768 );
|
pal = gEngfuncs.FS_LoadImage( "#gradient.pal", src, pal_bytes );
|
||||||
break;
|
break;
|
||||||
case SPR_ALPHTEST:
|
case SPR_ALPHTEST:
|
||||||
pal = gEngfuncs.FS_LoadImage( "#masked.pal", src, 768 );
|
pal = gEngfuncs.FS_LoadImage( "#masked.pal", src, pal_bytes );
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
pal = gEngfuncs.FS_LoadImage( "#normal.pal", src, 768 );
|
pal = gEngfuncs.FS_LoadImage( "#normal.pal", src, pal_bytes );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
pframetype = (const byte *)(src + 768);
|
pframetype = (const byte *)(src + pal_bytes);
|
||||||
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 256)\n", mod->name, *numi );
|
gEngfuncs.Con_DPrintf( S_ERROR "%s has wrong number of palette colors %i (should be less or equal than 256)\n", mod->name, *numi );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -249,32 +250,31 @@ release sprite model and frames
|
|||||||
*/
|
*/
|
||||||
void Mod_SpriteUnloadTextures( void *data )
|
void Mod_SpriteUnloadTextures( void *data )
|
||||||
{
|
{
|
||||||
msprite_t *psprite;
|
msprite_t *psprite = data;
|
||||||
mspritegroup_t *pspritegroup;
|
int i;
|
||||||
mspriteframe_t *pspriteframe;
|
|
||||||
int i, j;
|
|
||||||
|
|
||||||
psprite = data;
|
if( !data )
|
||||||
|
return;
|
||||||
|
|
||||||
if( psprite )
|
// release all textures
|
||||||
|
for( i = 0; i < psprite->numframes; i++ )
|
||||||
{
|
{
|
||||||
// release all textures
|
if( !psprite->frames[i].frameptr )
|
||||||
for( i = 0; i < psprite->numframes; i++ )
|
continue;
|
||||||
{
|
|
||||||
if( psprite->frames[i].type == SPR_SINGLE )
|
|
||||||
{
|
|
||||||
pspriteframe = psprite->frames[i].frameptr;
|
|
||||||
GL_FreeTexture( pspriteframe->gl_texturenum );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
pspritegroup = (mspritegroup_t *)psprite->frames[i].frameptr;
|
|
||||||
|
|
||||||
for( j = 0; j < pspritegroup->numframes; j++ )
|
if( psprite->frames[i].type == SPR_SINGLE )
|
||||||
{
|
{
|
||||||
pspriteframe = pspritegroup->frames[i];
|
GL_FreeTexture( psprite->frames[i].frameptr->gl_texturenum );
|
||||||
GL_FreeTexture( pspriteframe->gl_texturenum );
|
}
|
||||||
}
|
else
|
||||||
|
{
|
||||||
|
mspritegroup_t *pspritegroup = (mspritegroup_t *)psprite->frames[i].frameptr;
|
||||||
|
int j;
|
||||||
|
|
||||||
|
for( j = 0; j < pspritegroup->numframes; j++ )
|
||||||
|
{
|
||||||
|
if( pspritegroup->frames[j] )
|
||||||
|
GL_FreeTexture( pspritegroup->frames[j]->gl_texturenum );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -79,8 +79,6 @@ 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;
|
||||||
|
|
||||||
|
|
||||||
@@ -655,22 +653,6 @@ 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;
|
||||||
@@ -738,7 +720,7 @@ void R_AnimateRipples( void )
|
|||||||
R_RunRipplesAnimation( g_ripple.oldbuf, g_ripple.curbuf );
|
R_RunRipplesAnimation( g_ripple.oldbuf, g_ripple.curbuf );
|
||||||
}
|
}
|
||||||
|
|
||||||
qboolean R_UploadRipples( const texture_t *image )
|
qboolean R_UploadRipples( texture_t *image )
|
||||||
{
|
{
|
||||||
const gl_texture_t *glt;
|
const gl_texture_t *glt;
|
||||||
const uint32_t *pixels;
|
const uint32_t *pixels;
|
||||||
@@ -759,16 +741,6 @@ qboolean R_UploadRipples( const 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 )
|
||||||
@@ -776,6 +748,32 @@ qboolean R_UploadRipples( const 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++ )
|
||||||
|
|||||||
@@ -66,34 +66,33 @@ 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 = true;
|
qboolean loaded = false;
|
||||||
|
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -363,8 +363,6 @@ 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;
|
||||||
|
|||||||
@@ -165,31 +165,32 @@ 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, 768 );
|
pal = gEngfuncs.FS_LoadImage( "#gradient.pal", src, pal_bytes );
|
||||||
break;
|
break;
|
||||||
case SPR_ALPHTEST:
|
case SPR_ALPHTEST:
|
||||||
pal = gEngfuncs.FS_LoadImage( "#masked.pal", src, 768 );
|
pal = gEngfuncs.FS_LoadImage( "#masked.pal", src, pal_bytes );
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
pal = gEngfuncs.FS_LoadImage( "#normal.pal", src, 768 );
|
pal = gEngfuncs.FS_LoadImage( "#normal.pal", src, pal_bytes );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
pframetype = (const byte *)( src + 768 );
|
pframetype = (const byte *)(src + pal_bytes);
|
||||||
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 256)\n", mod->name, *numi );
|
gEngfuncs.Con_DPrintf( S_ERROR "%s has wrong number of palette colors %i (should be less or equal than 256)\n", mod->name, *numi );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -237,32 +238,31 @@ release sprite model and frames
|
|||||||
*/
|
*/
|
||||||
void Mod_SpriteUnloadTextures( void *data )
|
void Mod_SpriteUnloadTextures( void *data )
|
||||||
{
|
{
|
||||||
msprite_t *psprite;
|
msprite_t *psprite = data;
|
||||||
mspritegroup_t *pspritegroup;
|
int i;
|
||||||
mspriteframe_t *pspriteframe;
|
|
||||||
int i, j;
|
|
||||||
|
|
||||||
psprite = data;
|
if( !data )
|
||||||
|
return;
|
||||||
|
|
||||||
if( psprite )
|
// release all textures
|
||||||
|
for( i = 0; i < psprite->numframes; i++ )
|
||||||
{
|
{
|
||||||
// release all textures
|
if( !psprite->frames[i].frameptr )
|
||||||
for( i = 0; i < psprite->numframes; i++ )
|
continue;
|
||||||
{
|
|
||||||
if( psprite->frames[i].type == SPR_SINGLE )
|
|
||||||
{
|
|
||||||
pspriteframe = psprite->frames[i].frameptr;
|
|
||||||
GL_FreeTexture( pspriteframe->gl_texturenum );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
pspritegroup = (mspritegroup_t *)psprite->frames[i].frameptr;
|
|
||||||
|
|
||||||
for( j = 0; j < pspritegroup->numframes; j++ )
|
if( psprite->frames[i].type == SPR_SINGLE )
|
||||||
{
|
{
|
||||||
pspriteframe = pspritegroup->frames[i];
|
GL_FreeTexture( psprite->frames[i].frameptr->gl_texturenum );
|
||||||
GL_FreeTexture( pspriteframe->gl_texturenum );
|
}
|
||||||
}
|
else
|
||||||
|
{
|
||||||
|
mspritegroup_t *pspritegroup = (mspritegroup_t *)psprite->frames[i].frameptr;
|
||||||
|
int j;
|
||||||
|
|
||||||
|
for( j = 0; j < pspritegroup->numframes; j++ )
|
||||||
|
{
|
||||||
|
if( pspritegroup->frames[j] )
|
||||||
|
GL_FreeTexture( pspritegroup->frames[j]->gl_texturenum );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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=${ARCH_TRIPLET[$GH_CPU_ARCH]}
|
export PKG_CONFIG_PATH=$PWD/ffmpeg/lib/pkgconfig:${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,17 +53,21 @@ 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
|
||||||
AMD64="-8"
|
WAF_EXTRA_ARGS="-8"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -d "ffmpeg" ]; then
|
||||||
|
WAF_EXTRA_ARGS+=" --enable-ffmpeg"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ "$GH_CROSSCOMPILING" != "true" ]; then
|
if [ "$GH_CROSSCOMPILING" != "true" ]; then
|
||||||
ENABLE_TESTS="--enable-tests"
|
WAF_EXTRA_ARGS+=" --enable-tests"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ "$1" = "dedicated" ]; then
|
if [ "$1" = "dedicated" ]; then
|
||||||
./waf configure $AMD64 $ENABLE_TESTS --enable-lto --enable-bundled-deps -d || die_configure
|
./waf configure $WAF_EXTRA_ARGS --enable-lto --enable-bundled-deps -d || die_configure
|
||||||
elif [ "$1" = "full" ]; then
|
elif [ "$1" = "full" ]; then
|
||||||
./waf configure $AMD64 $ENABLE_TESTS --enable-lto --enable-bundled-deps -s SDL2_linux --enable-stb --enable-utils || die_configure
|
./waf configure $WAF_EXTRA_ARGS --enable-lto --enable-bundled-deps -s SDL2_linux --enable-stb --enable-utils || die_configure
|
||||||
else
|
else
|
||||||
die
|
die
|
||||||
fi
|
fi
|
||||||
@@ -75,9 +79,13 @@ deploy_engine()
|
|||||||
{
|
{
|
||||||
cd "$BUILDDIR" || die
|
cd "$BUILDDIR" || die
|
||||||
./waf install --destdir="$APPDIR" || die
|
./waf install --destdir="$APPDIR" || die
|
||||||
cp SDL2_linux/lib/libSDL2-2.0.so.0 "$APPDIR/"
|
cp -av SDL2_linux/lib/libSDL2-2.0.so.0 "$APPDIR/"
|
||||||
if [ "$GH_CPU_ARCH" = "i386" ]; then
|
if [ "$GH_CPU_ARCH" = "i386" ]; then
|
||||||
cp 3rdparty/vgui_support/vgui-dev/lib/vgui.so "$APPDIR/"
|
cp -av 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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,23 +9,33 @@ if [ "$ARCH" = "amd64" ]; then # we need enabling 64-bit target only on Intel-co
|
|||||||
AMD64="-8"
|
AMD64="-8"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if [ -d "ffmpeg" ]; then
|
||||||
|
export PKGCONFIG="$PWD/pkgconf/bin/pkgconf.exe"
|
||||||
|
export PKG_CONFIG_PATH="$PWD/ffmpeg/lib/pkgconfig"
|
||||||
|
WAF_EXTRA_ARGS="--enable-ffmpeg"
|
||||||
|
fi
|
||||||
|
|
||||||
# NOTE: to build with other version use --msvc_version during configuration
|
# NOTE: to build with other version use --msvc_version during configuration
|
||||||
# NOTE: sometimes you may need to add WinSDK to %PATH%
|
# NOTE: sometimes you may need to add WinSDK to %PATH%
|
||||||
# NOTE: --enable-msvcdeps only used for CI builds, enabling it non-English versions of MSVC causes useless console spam
|
# NOTE: --enable-msvcdeps only used for CI builds, enabling it non-English versions of MSVC causes useless console spam
|
||||||
./waf.bat configure -s "SDL2_VC" -T release --enable-utils --enable-tests --enable-lto --enable-msvcdeps $AMD64 || die_configure
|
./waf.bat configure -s "SDL2_VC" -T release --enable-utils --enable-tests --enable-lto --enable-msvcdeps $AMD64 $WAF_EXTRA_ARGS || die_configure
|
||||||
./waf.bat build || die
|
./waf.bat build || die
|
||||||
./waf.bat install --destdir=. || die
|
./waf.bat install --destdir=. || die
|
||||||
|
|
||||||
if [ "$ARCH" = "i386" ]; then
|
if [ "$ARCH" = "i386" ]; then
|
||||||
cp SDL2_VC/lib/x86/SDL2.dll . # Install SDL2
|
cp -v SDL2_VC/lib/x86/SDL2.dll . # Install SDL2
|
||||||
cp SDL2_VC/lib/x86/SDL2.pdb .
|
cp -v SDL2_VC/lib/x86/SDL2.pdb .
|
||||||
elif [ "$ARCH" = "amd64" ]; then
|
elif [ "$ARCH" = "amd64" ]; then
|
||||||
cp SDL2_VC/lib/x64/SDL2.dll .
|
cp -v SDL2_VC/lib/x64/SDL2.dll .
|
||||||
cp SDL2_VC/lib/x64/SDL2.pdb .
|
cp -v SDL2_VC/lib/x64/SDL2.pdb .
|
||||||
else
|
else
|
||||||
die
|
die
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if [ -d "ffmpeg" ]; then
|
||||||
|
cp -v ffmpeg/bin/av* ffmpeg/bin/sw* .
|
||||||
|
fi
|
||||||
|
|
||||||
WINSDK_LATEST=$(ls -1 "C:/Program Files (x86)/Windows Kits/10/bin" | grep -E '^10' | sort -rV | head -n1)
|
WINSDK_LATEST=$(ls -1 "C:/Program Files (x86)/Windows Kits/10/bin" | grep -E '^10' | sort -rV | head -n1)
|
||||||
echo "Latest installed Windows SDK is $WINSDK_LATEST"
|
echo "Latest installed Windows SDK is $WINSDK_LATEST"
|
||||||
|
|
||||||
|
|||||||
@@ -70,5 +70,9 @@ if [ -n "${APPIMAGETOOL[$GH_CPU_ARCH]}" ]; then
|
|||||||
chmod +x appimagetool.AppImage
|
chmod +x appimagetool.AppImage
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
FFMPEG_ARCHIVE=$(get_ffmpeg_archive)
|
||||||
|
wget https://github.com/FWGS/FFmpeg-Builds/releases/download/latest/$FFMPEG_ARCHIVE.tar.xz -qO- | tar -xJf -
|
||||||
|
mv $FFMPEG_ARCHIVE ffmpeg
|
||||||
|
|
||||||
wget "https://github.com/libsdl-org/SDL/releases/download/release-$SDL_VERSION/SDL2-$SDL_VERSION.tar.gz" -qO- | tar -xzf -
|
wget "https://github.com/libsdl-org/SDL/releases/download/release-$SDL_VERSION/SDL2-$SDL_VERSION.tar.gz" -qO- | tar -xzf -
|
||||||
mv "SDL2-$SDL_VERSION" SDL2_src
|
mv "SDL2-$SDL_VERSION" SDL2_src
|
||||||
|
|||||||
@@ -1,5 +1,20 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
curl -L https://github.com/libsdl-org/SDL/releases/download/release-$SDL_VERSION/SDL2-devel-$SDL_VERSION-VC.zip -o SDL2.zip
|
. scripts/lib.sh
|
||||||
|
|
||||||
|
curl -L http://libsdl.org/release/SDL2-devel-$SDL_VERSION-VC.zip -o SDL2.zip
|
||||||
unzip -q SDL2.zip
|
unzip -q SDL2.zip
|
||||||
mv SDL2-$SDL_VERSION SDL2_VC
|
mv SDL2-$SDL_VERSION SDL2_VC
|
||||||
|
|
||||||
|
curl -L https://github.com/FWGS/potential-meme/releases/download/prebuilts/mingw-w64-x86_64-pkgconf-1.2.3.0-1-any.pkg.tar.zst -o pkgconf.tar.zst
|
||||||
|
7z x pkgconf.tar.zst
|
||||||
|
7z x pkgconf.tar
|
||||||
|
rm pkgconf.tar*
|
||||||
|
mv mingw64 pkgconf
|
||||||
|
|
||||||
|
FFMPEG_ARCHIVE=$(get_ffmpeg_archive)
|
||||||
|
curl -L https://github.com/FWGS/FFmpeg-Builds/releases/download/latest/$FFMPEG_ARCHIVE.zip -o ffmpeg.zip
|
||||||
|
if [ -f ffmpeg.zip ]; then
|
||||||
|
unzip -x ffmpeg.zip
|
||||||
|
mv $FFMPEG_ARCHIVE ffmpeg
|
||||||
|
fi
|
||||||
|
|||||||
@@ -9,6 +9,27 @@ die_configure()
|
|||||||
die
|
die
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get_ffmpeg_archive()
|
||||||
|
{
|
||||||
|
if [ "$GH_CPU_OS" == "win32" ]; then
|
||||||
|
A=win
|
||||||
|
else
|
||||||
|
A="$GH_CPU_OS"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$GH_CPU_ARCH" == "amd64" ]; then
|
||||||
|
B=64
|
||||||
|
elif [ "$GH_CPU_ARCH" == "i386" ]; then
|
||||||
|
B=32
|
||||||
|
else
|
||||||
|
B="$GH_CPU_ARCH"
|
||||||
|
fi
|
||||||
|
|
||||||
|
FLAVOR=lgpl-shared-minimal
|
||||||
|
|
||||||
|
echo "ffmpeg-n$FFMPEG_VERSION-latest-$A$B-$FLAVOR-$FFMPEG_VERSION"
|
||||||
|
}
|
||||||
|
|
||||||
if [ -n "$TRAVIS_BUILD_DIR" ]; then
|
if [ -n "$TRAVIS_BUILD_DIR" ]; then
|
||||||
BUILDDIR=$TRAVIS_BUILD_DIR
|
BUILDDIR=$TRAVIS_BUILD_DIR
|
||||||
elif [ -n "$GITHUB_WORKSPACE" ]; then
|
elif [ -n "$GITHUB_WORKSPACE" ]; then
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user