mirror of
https://github.com/FWGS/xash3d-fwgs.git
synced 2026-08-05 11:35:05 +08:00
Compare commits
1 Commits
continuous
...
apidocs
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
03a9d08053 |
@@ -1,10 +1,10 @@
|
||||
task:
|
||||
name: freebsd-14-amd64
|
||||
freebsd_instance:
|
||||
image_family: freebsd-14-2
|
||||
image_family: freebsd-14-0
|
||||
setup_script:
|
||||
- pkg update
|
||||
- pkg install -y pkgconf git sdl2 python fontconfig libvorbis opusfile bzip2 libbacktrace
|
||||
- pkg install -y pkgconf git sdl2 python fontconfig opus
|
||||
- git submodule update --init --recursive
|
||||
test_script:
|
||||
- ./scripts/cirrus/build_freebsd.sh dedicated
|
||||
@@ -16,7 +16,7 @@ task:
|
||||
image_family: freebsd-15-0-snap
|
||||
setup_script:
|
||||
- pkg update
|
||||
- pkg install -y pkgconf git sdl2 python fontconfig libvorbis opusfile bzip2 libbacktrace
|
||||
- pkg install -y pkgconf git sdl2 python fontconfig opus
|
||||
- git submodule update --init --recursive
|
||||
test_script:
|
||||
- ./scripts/cirrus/build_freebsd.sh dedicated
|
||||
|
||||
6
.github/workflows/c-cpp.yml
vendored
6
.github/workflows/c-cpp.yml
vendored
@@ -66,7 +66,7 @@ jobs:
|
||||
targetos: apple
|
||||
targetarch: amd64
|
||||
env:
|
||||
SDL_VERSION: 2.32.0
|
||||
SDL_VERSION: 2.30.11
|
||||
GH_CPU_ARCH: ${{ matrix.targetarch }}
|
||||
GH_CROSSCOMPILING: ${{ matrix.cross }}
|
||||
steps:
|
||||
@@ -87,7 +87,6 @@ jobs:
|
||||
path: artifacts/*
|
||||
flatpak:
|
||||
runs-on: ubuntu-latest
|
||||
continue-on-error: true
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
@@ -101,7 +100,7 @@ jobs:
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: Build flatpak (Compat.i386)
|
||||
uses: FWGS/flatpak-github-actions/flatpak-builder@v6.3-fix
|
||||
uses: FWGS/flatpak-github-actions/flatpak-builder@v6.3
|
||||
with:
|
||||
bundle: ${{ matrix.app }}.flatpak
|
||||
manifest-path: scripts/flatpak/${{ matrix.app }}.yml
|
||||
@@ -120,6 +119,7 @@ jobs:
|
||||
--yes \
|
||||
--cleanup-tag \
|
||||
--repo "$GITHUB_REPOSITORY" || true
|
||||
sleep 20s
|
||||
gh run download "$GITHUB_RUN_ID" \
|
||||
--dir artifacts/ \
|
||||
--repo "$GITHUB_REPOSITORY"
|
||||
|
||||
9
.gitmodules
vendored
9
.gitmodules
vendored
@@ -27,13 +27,10 @@
|
||||
url = https://github.com/FWGS/MultiEmulator
|
||||
[submodule "3rdparty/libogg/libogg"]
|
||||
path = 3rdparty/libogg/libogg
|
||||
url = https://github.com/xiph/ogg.git
|
||||
url = https://gitlab.xiph.org/xiph/ogg.git
|
||||
[submodule "3rdparty/vorbis/vorbis-src"]
|
||||
path = 3rdparty/vorbis/vorbis-src
|
||||
url = https://github.com/xiph/vorbis.git
|
||||
url = https://gitlab.xiph.org/xiph/vorbis.git
|
||||
[submodule "3rdparty/opusfile/opusfile"]
|
||||
path = 3rdparty/opusfile/opusfile
|
||||
url = https://github.com/xiph/opusfile.git
|
||||
[submodule "3rdparty/libbacktrace/libbacktrace"]
|
||||
path = 3rdparty/libbacktrace/libbacktrace
|
||||
url = https://github.com/ianlancetaylor/libbacktrace
|
||||
url = https://gitlab.xiph.org/xiph/opusfile.git
|
||||
|
||||
2
3rdparty/MultiEmulator
vendored
2
3rdparty/MultiEmulator
vendored
Submodule 3rdparty/MultiEmulator updated: 11ff077ca5...7e989e670e
1
3rdparty/extras/wscript
vendored
1
3rdparty/extras/wscript
vendored
@@ -25,4 +25,5 @@ def build(bld):
|
||||
name = 'extras.pk3',
|
||||
files = srcdir.ant_glob('**/*'),
|
||||
relative_to = srcdir,
|
||||
compresslevel = 0,
|
||||
install_path = install_path)
|
||||
|
||||
2
3rdparty/extras/xash-extras
vendored
2
3rdparty/extras/xash-extras
vendored
Submodule 3rdparty/extras/xash-extras updated: 0c83a63d00...1bdeab2d8f
2
3rdparty/gl4es/gl4es
vendored
2
3rdparty/gl4es/gl4es
vendored
Submodule 3rdparty/gl4es/gl4es updated: a744af14d4...e39434a2b1
1
3rdparty/libbacktrace/libbacktrace
vendored
1
3rdparty/libbacktrace/libbacktrace
vendored
Submodule 3rdparty/libbacktrace/libbacktrace deleted from 78af4ffa26
185
3rdparty/libbacktrace/wscript
vendored
185
3rdparty/libbacktrace/wscript
vendored
@@ -1,185 +0,0 @@
|
||||
#! /usr/bin/env python
|
||||
# encoding: utf-8
|
||||
|
||||
from waflib import TaskGen
|
||||
|
||||
FRAGMENT_ATOMIC='''int i;
|
||||
int main(void) {
|
||||
__atomic_load_n(&i, __ATOMIC_ACQUIRE);
|
||||
__atomic_store_n(&i, 1, __ATOMIC_RELEASE);
|
||||
return 0;
|
||||
}'''
|
||||
|
||||
FRAGMENT_SYNC='''int i;
|
||||
int main (void) {
|
||||
__sync_bool_compare_and_swap (&i, i, i);
|
||||
__sync_lock_test_and_set (&i, 1);
|
||||
__sync_lock_release (&i);
|
||||
return 0;
|
||||
}'''
|
||||
|
||||
FRAGMENT_GETPAGESIZE='''#include <unistd.h>
|
||||
int main(void) { return getpagesize() }'''
|
||||
|
||||
FRAGMENT_GETEXECNAME='''#include <stdlib.h>
|
||||
int main(void) { return getexecname() != 0 }'''
|
||||
|
||||
FRAGMENT_STRNLEN='''#include <string.h>
|
||||
int main(int argc, char **argv) { return (int)strnlen(argv[0], 10); }'''
|
||||
|
||||
FRAGMENT_DL_ITERATE_PHDR='''#include <%s>
|
||||
int main(void) { return dl_iterate_phdr(0, 0); }'''
|
||||
|
||||
FRAGMENT_FCNTL='''#include <fcntl.h>
|
||||
int main(void) { return fcntl(0, 0, 0); }'''
|
||||
|
||||
FRAGMENT_GETIPINFO='''#include "unwind.h"
|
||||
struct _Unwind_Context *context;
|
||||
int ip_before_insn = 0;
|
||||
int main(void) { return _Unwind_GetIPInfo(context, &ip_before_insn); }'''
|
||||
|
||||
FRAGMENT_LOADQUERY='''#include <sys/ldr.h>
|
||||
#include <sys/debug.h>
|
||||
int main(void) { return loadquery(0, 0, 0); }'''
|
||||
|
||||
FRAGMENT_KERN_PROC='''#include <sys/sysctl.h>
|
||||
#if !defined(%s) || !defined(KERN_PROC_PATHNAME)
|
||||
#error
|
||||
#endif
|
||||
int main(void) { return 0; }'''
|
||||
|
||||
FRAGMENT_LSTAT='''#include <sys/stat.h>
|
||||
struct stat st;
|
||||
int main(int argc, char **argv) { return lstat(argv[0], &st); }'''
|
||||
|
||||
FRAGMENT_READLINK='''#include <unistd.h>
|
||||
char buf[100];
|
||||
int main(int argc, char **argv) { return readlink(argv[0], buf, sizeof(buf)); }'''
|
||||
|
||||
def options(opt):
|
||||
pass
|
||||
|
||||
def configure(conf):
|
||||
# add unsupported platforms here
|
||||
if conf.env.DEST_OS in ['nswitch', 'psvita', 'dos']:
|
||||
conf.env.DISABLE_LIBBACKTRACE = True
|
||||
return
|
||||
|
||||
# win32 has it's own dbghelp-based backtrace, that's why we ship PDBs
|
||||
if conf.env.COMPILER_CC == 'msvc':
|
||||
conf.env.DISABLE_LIBBACKTRACE = True
|
||||
return
|
||||
|
||||
if not conf.path.find_dir('libbacktrace') or not conf.path.find_dir('libbacktrace/config'):
|
||||
conf.fatal('Can\'t find libbacktrace submodule. Run `git submodule update --init --recursive`.')
|
||||
return
|
||||
|
||||
if conf.env.DEST_SIZEOF_VOID_P == 8:
|
||||
conf.define('BACKTRACE_ELF_SIZE', 64)
|
||||
conf.define('BACKTRACE_XCOFF_SIZE', 64)
|
||||
else:
|
||||
conf.define('BACKTRACE_ELF_SIZE', 32)
|
||||
conf.define('BACKTRACE_XCOFF_SIZE', 32)
|
||||
|
||||
conf.define('_ALL_SOURCE', 1)
|
||||
conf.define('_GNU_SOURCE', 1)
|
||||
conf.define('_POSIX_PTHREAD_SEMANTICS', 1)
|
||||
conf.define('_TANDEM_SOURCE', 1)
|
||||
conf.define('__EXTENSIONS__', 1)
|
||||
conf.define('_DARWIN_USE_64_BIT_INODE', 1)
|
||||
conf.define('_LARGE_FILES', 1)
|
||||
conf.check_large_file(compiler='c', execute=False, mandatory=False) # sets _FILE_OFFSET_BITS
|
||||
|
||||
conf.env.CFLAGS_EXTRAFLAGS = conf.filter_cflags(['-funwind-tables', '-g'], [])
|
||||
|
||||
if conf.filter_cflags(['-frandom-seed=test'], []):
|
||||
conf.env.HAVE_FRANDOM_SEED = True
|
||||
|
||||
def check_header(hdr):
|
||||
return {'header_name':hdr, 'msg':'... %s header' % hdr, 'mandatory':False, 'id':hdr}
|
||||
|
||||
conf.multicheck(
|
||||
check_header('dlfcn.h'),
|
||||
check_header('inttypes.h'),
|
||||
check_header('link.h'),
|
||||
check_header('sys/link.h'),
|
||||
check_header('mach-o/dyld.h'),
|
||||
check_header('memory.h'),
|
||||
check_header('stdint.h'),
|
||||
check_header('stdlib.h'),
|
||||
check_header('strings.h'),
|
||||
check_header('string.h'),
|
||||
check_header('sys/ldr.h'),
|
||||
check_header('sys/mman.h'),
|
||||
check_header('sys/stat.h'),
|
||||
check_header('sys/types.h'),
|
||||
check_header('tlhelp32.h'),
|
||||
check_header('unistd.h'),
|
||||
check_header('windows.h'),
|
||||
|
||||
{'fragment':FRAGMENT_ATOMIC, 'msg':'... __atomic extensions', 'define_name':'HAVE_ATOMIC_FUNCTIONS', 'mandatory':False},
|
||||
{'fragment':FRAGMENT_SYNC, 'msg':'... __sync extensions', 'define_name':'HAVE_SYNC_FUNCTIONS', 'mandatory':False},
|
||||
{'fragment':FRAGMENT_GETPAGESIZE, 'msg':'... getpagesize function', 'define_name':'HAVE_DECL_GETPAGESIZE', 'mandatory':False},
|
||||
{'fragment':FRAGMENT_STRNLEN, 'msg':'... strnlen function', 'define_name':'HAVE_DECL_STRNLEN', 'mandatory':False},
|
||||
{'fragment':FRAGMENT_DL_ITERATE_PHDR % 'link.h', 'msg':'... dl_iterate_phdr function in link.h', 'define_name':'HAVE_DL_ITERATE_PHDR', 'after_tests': ['link.h'], 'mandatory':False},
|
||||
{'fragment':FRAGMENT_DL_ITERATE_PHDR % 'sys/link.h', 'msg':'... dl_iterate_phdr function in sys/link.h', 'define_name':'HAVE_DL_ITERATE_PHDR', 'after_tests': ['sys/link.h'], 'mandatory':False},
|
||||
{'fragment':FRAGMENT_FCNTL,'msg':'... fnctl function', 'define_name':'HAVE_FCNTL', 'mandatory':False},
|
||||
{'fragment':FRAGMENT_GETEXECNAME,'msg':'... getexecname function','define_name':'HAVE_GETEXECNAME', 'mandatory':False},
|
||||
{'fragment':FRAGMENT_GETIPINFO, 'msg':'... _Unwind_GetIPInfo function', 'define_name':'HAVE_GETIPINFO', 'mandatory':False},
|
||||
{'fragment':FRAGMENT_KERN_PROC % 'KERN_PROC', 'msg': '... KERN_PROC and KERN_PROC_PATHNAME defines', 'define_name':'HAVE_KERN_PROC', 'mandatory':False},
|
||||
{'fragment':FRAGMENT_KERN_PROC % 'KERN_PROC_ARGS', 'msg': '... KERN_PROC_ARGS and KERN_PROC_PATHNAME defines', 'define_name':'HAVE_KERN_PROC_ARGS', 'mandatory':False},
|
||||
{'fragment':FRAGMENT_LOADQUERY, 'msg': '... loadquery function', 'define_name':'HAVE_LOADQUERY', 'mandatory':False},
|
||||
{'fragment':FRAGMENT_LSTAT, 'msg': '... lstat function', 'define_name':'HAVE_LSTAT', 'mandatory':False},
|
||||
{'fragment':FRAGMENT_READLINK, 'msg': '... readlink function', 'define_name':'HAVE_READLINK', 'mandatory':False},
|
||||
|
||||
# {'lib':'lzma', 'define_name':'HAVE_LIBLZMA', 'uselib_store':'lzma', 'msg':'... lzma library', 'mandatory':False},
|
||||
# {'lib':'z', 'define_name':'HAVE_ZLIB', 'uselib_store':'z', 'msg':'... zlib library', 'mandatory':False},
|
||||
# {'lib':'zstd', 'define_name':'HAVE_ZSTD', 'uselib_store':'zstd', 'msg':'... zstd library', 'mandatory':False},
|
||||
msg='Checking for in parallel'
|
||||
)
|
||||
|
||||
conf.write_config_header()
|
||||
|
||||
conf.define('BACKTRACE_SUPPORTED', 1)
|
||||
conf.define('BACKTRACE_USES_MALLOC', 0)
|
||||
conf.define('BACKTRACE_SUPPORTS_THREADS', 1)
|
||||
conf.define('BACKTRACE_SUPPORTS_DATA', conf.env.DEST_BINFMT in ['elf', 'mac-o'])
|
||||
|
||||
conf.write_config_header('backtrace-supported.h')
|
||||
|
||||
@TaskGen.feature('frandomseed')
|
||||
@TaskGen.after_method('propagate_uselib_vars')
|
||||
def process_frandom_seed(ctx):
|
||||
tasks = getattr(ctx, 'compiled_tasks', [])
|
||||
|
||||
for task in tasks:
|
||||
out = task.outputs[0]
|
||||
task.env.CFLAGS = list(task.env.CFLAGS) # need a copy
|
||||
task.env.CFLAGS += ['-frandom-seed=%s' % out.path_from(out.ctx.bldnode)]
|
||||
|
||||
def build(bld):
|
||||
if bld.env.DISABLE_LIBBACKTRACE:
|
||||
return
|
||||
|
||||
# we specifically only want mmap-based allocators because calling malloc is not safe from signal handlers
|
||||
sources = ['atomic.c', 'dwarf.c', 'fileline.c', 'posix.c', 'print.c', 'sort.c', 'state.c', 'backtrace.c', 'simple.c', 'mmap.c', 'mmapio.c']
|
||||
|
||||
if bld.env.DEST_BINFMT == 'pe':
|
||||
sources += ['pecoff.c']
|
||||
elif bld.env.DEST_BINFMT == 'mac-o':
|
||||
sources += ['macho.c']
|
||||
elif bld.env.DEST_BINFMT == 'elf':
|
||||
sources += ['elf.c']
|
||||
else:
|
||||
sources += ['unknown.c']
|
||||
|
||||
task = bld.stlib(
|
||||
source = ['libbacktrace/' + i for i in sources],
|
||||
target = 'backtrace',
|
||||
features = 'frandomseed' if bld.env.HAVE_FRANDOM_SEED else '',
|
||||
use = 'EXTRAFLAGS lzma z zstd',
|
||||
includes = '. libbacktrace/',
|
||||
export_defines = 'HAVE_LIBBACKTRACE=1',
|
||||
export_includes = 'libbacktrace/'
|
||||
)
|
||||
|
||||
2
3rdparty/mainui
vendored
2
3rdparty/mainui
vendored
Submodule 3rdparty/mainui updated: cbbfe2e23c...734a6d1ca2
5
Documentation/api/README.md
Normal file
5
Documentation/api/README.md
Normal file
@@ -0,0 +1,5 @@
|
||||
# Welcome to the GoldSource API docs
|
||||
|
||||
This documentation is an attempt on explaining inner workings of Valve's Half-Life (R) engine, also known as GoldSource, from programmer's perspective. A deep knowledge of Quake (NQ, QW and Q2) engines is required.
|
||||
|
||||
Everything discussed here is it's author assumption based on studying Xash3D source code and reverse engineering Half-Life mods. Xash3D API extensions is out of scope of this document and will be explained separately.
|
||||
20
Documentation/api/client/01-init.md
Normal file
20
Documentation/api/client/01-init.md
Normal file
@@ -0,0 +1,20 @@
|
||||
# Initializing client.dll
|
||||
|
||||
`client.dll` has got multiple ways of initialization during it's life but we will go through the simplest and the most common route here.
|
||||
|
||||
Here we expect that reader has knowledge of loading dynamic shared objects on their platform. On Windows it's done through `LoadLibrary`/`GetProcAddress`/`FreeLibrary` functions, on POSIX-complaint systems it's done through `dlopen`/`dlsym`/`dlclose` functions.
|
||||
|
||||
## client.dll lifetime
|
||||
|
||||
`client.dll` is expected to be loaded during client initialization and unloaded on client shutdown. Essentially, in non-dedicated builds, it always exists during the engine lifetime. Judging by the API, it might look like `client.dll` might be safely unloaded and loaded again, for example for implementing classic `Change Game` functionality from WON versions of Half-Life, but in practice it's nearly impossible to do this clean in standard and portable manner. If you want to implement changing games, consider using `execv`-like functions.
|
||||
|
||||
## client.dll exported functions
|
||||
|
||||
The first thing you should do, is to acquire pointers to all exported functions, which you can find in the next chapter. Some of them are optional, and might not present in the `client.dll`, and will be labeled as such.
|
||||
|
||||
## client.dll initialization process
|
||||
|
||||
1. The first function you call is `Initialize` function, which lets `client.dll` to store a copy of an engine API functions.
|
||||
2. Since SDK 2.0, `client.dll` have player movement code in it, which you must initialize through `HUD_PlayerMoveInit` function. `client.dll` might want to override player hulls, which can be grabbed with `HUD_GetHullBounds` function.
|
||||
3. HUD functionality must be started up with `HUD_Init` function and can be de-initialized with `HUD_Shutdown` export function.
|
||||
4. And finally, SDK 2.1 brings studio model renderer, which has separate set of API functions, which must be initialized with `HUD_GetStudioModelInterface` function.
|
||||
286
Documentation/api/client/02-exports.md
Normal file
286
Documentation/api/client/02-exports.md
Normal file
@@ -0,0 +1,286 @@
|
||||
# List of client.dll exported functions
|
||||
|
||||
### `int Initialize( cl_enginefuncs_t *enginefuncs, int version )`
|
||||
|
||||
> [!IMPORTANT]
|
||||
> This function is only called once.
|
||||
|
||||
Called after loading DLL and exports engine API to the `client.dll`.
|
||||
* `enginefuncs` must be set to a pointer to a struct filled with engine function pointers, it will be described in next chapters.
|
||||
* `version` must be always set to `7`. (HLSDK 1.0 uses version `6`, and is binary incompatible with `7`).
|
||||
Return value: `0` on error, otherwise success.
|
||||
|
||||
### `void HUD_PlayerMoveInit( struct playermove_s *ppmove, int server )`
|
||||
|
||||
> [!IMPORTANT]
|
||||
> This function is only called once.
|
||||
|
||||
Called on player movement prediction initialization, before HUD. In GoldSrc, engine only runs prediction loop, the players physics are implemented in `client.dll`.
|
||||
* `ppmove` must be set to a pointer to a client instance of player movement structure, which also exports it's own API and will be discussed in the next chapters.
|
||||
* `server` must be always set to `0` on client side.
|
||||
This function is called only once.
|
||||
|
||||
### `void HUD_Init( void )`
|
||||
|
||||
> [!IMPORTANT]
|
||||
> This function is only called once.
|
||||
|
||||
Called to initialize the HUD. At this moment engine should be ready to register new commands, console variables and user messages. No rendering or loading graphics done at this moment.
|
||||
|
||||
### `int HUD_GetStudioModelInterface( int version, struct r_studio_interface_s **ppinterface, struct engine_studio_api_s *pstudio )`
|
||||
|
||||
> [!IMPORTANT]
|
||||
> This function is only called once.
|
||||
|
||||
This function is called after initializing HUD and exports studio model interface to the `client.dll`.
|
||||
* `version` must be always set to `1`.
|
||||
* `ppinterface` will be set by `client.dll` to a pointer to `r_studio_interface_s` structure.
|
||||
* `pstudio` must be set to a pointer to `engine_studio_api_s` structure. The studio model interface will be discussed in the next chapters.
|
||||
Return value: `0` on error, otherwise success.
|
||||
|
||||
### `void HUD_Shutdown( void )`
|
||||
|
||||
> [!IMPORTANT]
|
||||
> This function is only called once.
|
||||
|
||||
Called at client shutdown.
|
||||
|
||||
### `int HUD_GetHullBounds( int hull, vec3_t mins, vec3_t maxs )`
|
||||
|
||||
> [!IMPORTANT]
|
||||
> This function is only called once.
|
||||
|
||||
Called by the engine after `HUD_PlayerMoveInit` to let `client.dll` override hull bounds used for in player movement prediction.
|
||||
|
||||
* `hull` is the hull index (0: player standing, 1: player crouched, 2: point hull, 3: large hull).
|
||||
* `mins` will contain hull mins.
|
||||
* `maxs` will contain hull maxs.
|
||||
Return value: if 0, don't override this hull and stop reading, non-zero means hull is valid _and_ there is more.
|
||||
|
||||
> [!NOTE]
|
||||
> This function is broken in most implementations. It might return non-zero value, but don't write anything to the `mins` and `maxs` vectors, so be prepared to have some default values.
|
||||
|
||||
### `int HUD_VidInit( void )`
|
||||
|
||||
Called when client receives `svc_serverdata` message. It is called before any parsing of that message is done, thus the state is preserved from the previous connection. It lets `client.dll` to re-initialize graphics, if required. At this point, engine is expected to have video subsystem running, but no rendering is done here.
|
||||
|
||||
### `int HUD_Redraw( float flTime, int intermission )`
|
||||
|
||||
Called each frame to redraw the HUD. Only 2D is drawn here.
|
||||
* `flTime` must be set to `cl.time`, i.e. synchronized with server.
|
||||
* `intermission` must be set to `1` during intermission (set through `svc_intermission` message), otherwise it's set to `0`.
|
||||
Return value: ignored.
|
||||
|
||||
### `void HUD_Reset( void )`
|
||||
|
||||
Called on demo recording or playback start and stop.
|
||||
|
||||
### `int HUD_UpdateClientData( client_data_t *cdata, float flTime )`
|
||||
|
||||
Called each frame after taking input.
|
||||
* `cdata` contains pointer to `client_data_t` structure, populated by engine.
|
||||
* `flTime` must be set to `cl.time`, i.e. synchronized with server.
|
||||
Return value: if non-zero, will override engine viewangles and FOV value.
|
||||
|
||||
### `void HUD_PlayerMove( struct playermove_s *pmove, int server )`
|
||||
|
||||
When prediction is enabled, use this function to run player movement prediction. Note that this correlates to QW/Q2's prediction mechanism. It does not include weapon prediction.
|
||||
|
||||
* `pmove` is a pointer to playermove object
|
||||
* `server` must be always set to `0`
|
||||
|
||||
### `char HUD_PlayerMoveTexture( char *name )`
|
||||
|
||||
Not used in the engine.
|
||||
|
||||
### `int HUD_ConnectionlessPacket( const netadr_t *from, const char *args, char *response_buffer, int *response_buffer_size )`
|
||||
|
||||
Called by the engine on unknown connectionless packets. Lets `client.dll` and `server.dll` have custom query protocol.
|
||||
|
||||
* `from` is set to network address where this packet is coming from.
|
||||
* `args` raw network buffer, minus the connectionless packet header (0xFFFFFFFF).
|
||||
* `response_buffer` set by `client.dll` if there is a response.
|
||||
* `response_buffer_size` is initialized by the engine with buffer maximum size. Set by `client.dll` if there is a response.
|
||||
Return value: non-zero if handled.
|
||||
|
||||
### `void HUD_Frame( double time )`
|
||||
|
||||
Called each frame after sending command to the remote server. No rendering is normally done in this function.
|
||||
|
||||
* `time` is the local delta time between previous and this frame (i.e. `host.frametime`)
|
||||
|
||||
### `void HUD_PostRunCmd( struct local_state_s *from, struct local_state_s *to, usercmd_t *cmd, int runfuncs, double time, unsigned int random_seed )`
|
||||
|
||||
Always called after `HUD_PlayerMove`, even if movement prediction is disabled. Used for weapon prediction stuff.
|
||||
|
||||
* `from` is a pointer to `local_state_s` object of the previous predicted frame
|
||||
* `to` is a pointer to `local_state_s` object of this current frame
|
||||
* `cmd` is current user command
|
||||
* `runfuncs` is set to `1` if this frame was never predicted before, and to `0` if it is being predicted again
|
||||
* `random_seed` is set to `incoming_acknowledged` plus number of predicted frames starting with `1`. This way it's synchronized between client and server.
|
||||
|
||||
### `int HUD_Key_Event( int down, int key, const char *current_binding )`
|
||||
|
||||
Called on keyboard event.
|
||||
|
||||
* `down` is set to `1` if key is being pressed or set to `0` on being released.
|
||||
* `key` is set to the key number. The key IDs are predefined.
|
||||
* `current_binding` is set to a null-terminated string with commands bound to this key
|
||||
Return value: `0` if `client.dll` wants engine to ignore that key.
|
||||
|
||||
### `int HUD_AddEntity( int type, struct cl_entity_s *ent, const char *modelname )`
|
||||
|
||||
Called before adding entity to the rendering list.
|
||||
|
||||
* `type` is set to an entity type, see `entity_state_t::entityType`
|
||||
* `ent` is a pointer to `cl_entity_t` object.
|
||||
* `modelname` is a null-terminated string with that entity model name.
|
||||
Return value: `0` if `client.dll` wants engine to not draw this entity.
|
||||
|
||||
### `void HUD_CreateEntities( void )`
|
||||
|
||||
Called each frame after all network entities (including players) are linked to let `client.dll` spawn client-side entities.
|
||||
|
||||
### `void HUD_StudioEvent( const struct mstudioevent_s *event, const struct cl_entity_s *ent )`
|
||||
|
||||
Studio models have events tied to the frame, on which engine calls this function.
|
||||
|
||||
* `event` is a pointer to a studio event object
|
||||
* `ent` is a pointer to a client entity object
|
||||
|
||||
### `void HUD_TxferLocalOverrides( struct entity_state_s *state, const struct clientdata_s *client )`
|
||||
|
||||
When client processes entity updates, for local client it might be truncated, don't have enough precision, miss some critical info, so engine calls this function as `client.dll` might choose to use client data came from `svc_clientdata` message. Note that it is called on raw, non-interpolated networked entity state.
|
||||
|
||||
* `state` is a pointer to the local client entity state coming from the network
|
||||
* `client` is a pointer to local client data object
|
||||
|
||||
### `void HUD_ProcessPlayerState( struct entity_state_s *dst, const struct entity_state_s *src )`
|
||||
|
||||
When client processes entity updates, it calls this function for player entities as `client.dll` might want to override some data or fill the missing parts, but usually it just copies from `src` to `dst`.
|
||||
|
||||
* `src` is a target pointer to the player entity data (stored in frames, for example)
|
||||
* `dst` is a source pointer to the player entity data coming from network
|
||||
|
||||
### `void HUD_TxferPredictionData( struct entity_state_s *ps, const struct entity_state_s *pps, struct clientdata_s *pcd, const struct clientdata_s *ppcd, struct weapon_data_s *wd, const weapon_data_s *pwd )`
|
||||
|
||||
When client receives `svc_clientdata` message, this function is called before any parsing is done, so that the `client.dll` fills in data from prediction.
|
||||
|
||||
* `ps`, `pcd`, `wd` are pointers to current network frame data.
|
||||
* `pps`, `ppcd`, `pwd` are pointers to predicted frame data.
|
||||
|
||||
### `void HUD_TempEntUpdate( double frametime, double client_time, double cl_gravity, TEMPENTITY **ppTempEntFree, TEMPENTITY **ppTempEntActive, int ( *AddVisibleEntity )( cl_entity_t *pEntity ), void ( *TempEntPlaySound)( TEMPENTITY *pTemp, float damp ))`
|
||||
|
||||
Called each frame after network entities are processed and after `HUD_CreateEntities`, to let `client.dll` process temporary entities logic.
|
||||
|
||||
* `frametime` is the delta between `cl.time` and `cl.oldtime`, i.e. server time.
|
||||
* `client_time` is `cl.time`
|
||||
* `gravity` is the synchronized gravity value from the server
|
||||
* `ppTempEntFree` is a pointer to the head of linked list of free temp entities
|
||||
* `ppTempEntActive` is a pointer to the head of linked list of active temp entities
|
||||
* `AddVisibleEntity` is a pointer to function that lets `client.dll` add this entity to the rendering list.
|
||||
* `TempEntPlaySound` is a pointer to function that's called by `client.dll` when temp entity needs to play predefined hit sound. The `damp` argument of this argument only makes sound to NOT play, if it's zero or negative.
|
||||
|
||||
### `void HUD_DrawNormalTriangles( void )`
|
||||
|
||||
Called each rendering frame to let `client.dll` draw custom solid triangles through TriAPI or direct OpenGL calls.
|
||||
|
||||
### `void HUD_DrawTransparentTriangles( void )`
|
||||
|
||||
Called each rendering frame to let `client.dll` draw custom transparent triangles through TriAPI or direct OpenGL calls.
|
||||
|
||||
### `struct cl_entity_s *HUD_GetUserEntity( int index )`
|
||||
|
||||
Called by engine when beam start/end indices are negative, thus allowing attaching beams to a temporary or client-only entity.
|
||||
|
||||
* `index` is the fixed up entity index, as beam start/end indices encode real entity index in low 12 bits (i.e. `beament_start & 0xFFF`).
|
||||
|
||||
### `void Demo_ReadBuffer( int size, unsigned char *buffer )`
|
||||
|
||||
Called by engine on demo playback, if `client.dll` saved some custom data on demo recording prior.
|
||||
|
||||
* `size` is the size of buffer in bytes
|
||||
* `buffer` is the pointer to custom data stored by `client.dll` in demo
|
||||
|
||||
### `void CAM_Think( void )`
|
||||
|
||||
Called each frame before rendering starts to let `client.dll` run custom camera logic, like advanced thirdperson follow camera for example.
|
||||
|
||||
### `int CL_IsThirdPerson( void )`
|
||||
|
||||
Returns non-zero value if camera is in thirdperson mode, lets engine figure out whether add local client entity to the rendering list or not.
|
||||
|
||||
### `void CL_CameraOffset( vec3_t offset )`
|
||||
|
||||
Not used in the engine.
|
||||
|
||||
### `void CL_CreateMove( float frametime, usercmd_t *cmd, int active )`
|
||||
|
||||
Called when `usercmd_t` is being created to let `client.dll` record user commands before they are being sent over the network.
|
||||
|
||||
* `frametime` is the delta time between previous and current frames.
|
||||
* `cmd` is the pointer to `usercmd_t` object, where player's intentions and impulses are added.
|
||||
* `active` is set to `1` when client is finished signing on to the server (as movement commands are being sent even if client is not fully spawned yet).
|
||||
|
||||
### `void IN_ActivateMouse( void )`
|
||||
|
||||
Called from similarly named NQ/QW function.
|
||||
|
||||
### `void IN_DeactivateMouse( void )`
|
||||
|
||||
Called from similarly named NQ/QW function.
|
||||
|
||||
### `void IN_MouseEvent( int mstate )`
|
||||
|
||||
Called from similarly named NQ/QW function.
|
||||
|
||||
### `void IN_Accumulate( void )`
|
||||
|
||||
Called from similarly named NQ/QW function.
|
||||
|
||||
### `void IN_ClearStates( void )`
|
||||
|
||||
Called from similarly named NQ/QW function.
|
||||
|
||||
### `void V_CalcRefdef( struct ref_params_s *params )`
|
||||
|
||||
Called each frame before rendering starts. This is close to the similarly named function found in NQ/QW and lets `client.dll` to run custom view logic.
|
||||
|
||||
* `params` is the refdef parameters object. It is also used as return value and might request from the engine to not draw anything (by `onlyClientDraws` field) or to run this multiple times (by `nextview` field)
|
||||
|
||||
### `kbutton_t *KB_Find( const char *name )`
|
||||
|
||||
Called by engine to find extra keys and their state.
|
||||
|
||||
Only few are really used by the engine:
|
||||
* `in_mlook` for mouse look
|
||||
* `in_jlook` for joystick look
|
||||
* `in_graph` for net_graph toggle
|
||||
|
||||
Return value: returns pointer to `kbutton_t` if found. `kbutton_t` structure matches the same structure that can be found in NQ and QW.
|
||||
|
||||
### `void HUD_DirectorMessage( int size, void *buf )`
|
||||
|
||||
> [!IMPORTANT]
|
||||
> This function is optional.
|
||||
|
||||
Called to notify `client.dll` about an `svc_director` message. This feature is used for HLTV, though mods use it to spawn text messages or execute commands (bypassing `svc_stufftext` filter in old `client.dll`) but `svc_director` message structure isn't enforced by engine, so it in theory mods might modify it for their own needs.
|
||||
|
||||
* `size` is the size of the payload
|
||||
* `buf` raw `svc_director` payload
|
||||
|
||||
### `void HUD_VoiceStatus( int entindex, qboolean talking )`
|
||||
|
||||
> [!IMPORTANT]
|
||||
> This function is optional.
|
||||
|
||||
Called to notify `client.dll` about a client status of using voice chat.
|
||||
* `entindex` an entity index (client index plus one, because zero is always world). When set to -1, notifies `client.dll` about local client recording. When set to -2, notifies `client.dll` about a loopback (i.e. local client's voice message was sent to server and received back)
|
||||
* `talking` if true, this client is talking
|
||||
|
||||
### `void HUD_ChatInputPosition( int *x, int *y )`
|
||||
|
||||
> [!IMPORTANT]
|
||||
> This function is optional.
|
||||
|
||||
When called, returns desired X and Y positions of chat box.
|
||||
9
Documentation/api/client/README.md
Normal file
9
Documentation/api/client/README.md
Normal file
@@ -0,0 +1,9 @@
|
||||
# What is client.dll in GoldSource?
|
||||
|
||||
One of technical differences a programmer working with Quake engine might notice is the client.dll file. Historically, it appeared somewhere in between Alpha 0.52 and NetTest1 development and judging by Half-Life SDK 1.0 was meant to handle HUD rendering. The time moved forward, SDK 2.0 finalized `client.dll` API at version 7, added an in-game UI, custom input processing, player movement and weapon prediction, very basic rendering through TriAPI. SDK 2.1 added ability to re-define studio model rendering, and so on.
|
||||
|
||||
It somewhat resembles `cgame` module from Quake 3, but more crudely designed and sometimes feels like an afterthought, considering how many engine internal structures it exposes and the main point of incompatibilities with mods, which these days sometimes use `client.dll` as a way to inject custom rendering into the game.
|
||||
|
||||
In this document I will try to go through each step, letting you, dear reader, implement your own GoldSrc compatible API in your Quake fork, targetting vanilla Half-Life `client.dll` from latest update, which at the time of writing, is 25-th anniversary update.
|
||||
|
||||
Despite that we call it `client.dll`, since SDK 2.4 (unofficial naming, it's the first SDK Valve published on GitHub) it is considered portable and only has SDL2 and VGUI libraries in it's external dependences. It's only called this way to avoid possible misunderstandings with engine developers, who might interpret client as `cl_` prefixed part of Quake engine.
|
||||
120
Documentation/api/client/xx-structs.md
Normal file
120
Documentation/api/client/xx-structs.md
Normal file
@@ -0,0 +1,120 @@
|
||||
# `client.dll` shared structs and enums
|
||||
|
||||
GoldSource exposes a lot of structs to `client.dll`. Some of them are specific to `client.dll` and only used for passing data between engine and client, some of them are used in the engine everywhere, but still exposed in the public SDK. However, many mods rely on internal structs as well, and I will try to shed light on them as well.
|
||||
|
||||
When implementing them in C, consider the default to 32-bit systems alignment of 4 bytes and ILP32 data type model.
|
||||
|
||||
This file won't have API structs, for that, there should be separate chapters.
|
||||
|
||||
## Enums
|
||||
|
||||
### Entity types enum
|
||||
|
||||
This enum has no real name.
|
||||
|
||||
| Value | Description |
|
||||
|-------|-----------------|
|
||||
| `0` | Normal entities |
|
||||
| `1` | Players |
|
||||
| `2` | Temp entities |
|
||||
| `3` | Beams |
|
||||
| `4` | Fragmented entities. |
|
||||
|
||||
### edict->solid
|
||||
|
||||
It matches QuakeWorld definition.
|
||||
|
||||
## `client_data_t`
|
||||
|
||||
Used only to pass data to `client.dll` through `HUD_UpdateClientData`.
|
||||
|
||||
| Type | Name | Description |
|
||||
|----------|---------------|--------------------------------------------------------------|
|
||||
| `vec3_t` | `origin` | Local client origin. Cannot be changed by `client.dll` here. |
|
||||
| `vec3_t` | `viewangles` | Local client viewangles. This and next fields can be changed by `client.dll` |
|
||||
| `int` | `iWeaponBits` | Bit vector of weapons held by client. |
|
||||
| `float` | `fov` | Local client's field of view. |
|
||||
|
||||
## `netadr_t`
|
||||
|
||||
Matches Quake-2 structure with the similar name.
|
||||
|
||||
## `local_state_t`
|
||||
|
||||
Only consists of another structs. All of these structs are used to store prediction data, so one `local_state_t` for each predicted frame.
|
||||
|
||||
| Type | Name | Description |
|
||||
|---------------------|---------------|--------------------------------------|
|
||||
| `entity_state_t` | `playerstate` | Contains local player's entity state |
|
||||
| `clientdata_t` | `client` | Additional information about local client. _Do not get confused with `client_data_t`, note the underscore._ |
|
||||
| `weapon_data_t[64]` | `weapondata` | Array of 64 predictable weapons. |
|
||||
|
||||
## `entity_state_t`
|
||||
|
||||
This structure is similar to the one that can be found in QW, but contains much more data, though most of these fields are not used by the engine, but might be used by mods.
|
||||
|
||||
| Type | Name | Description |
|
||||
|-------------|----------------|------------------------------------------------------|
|
||||
| `int` | `entityType` | Entity type (see entity type enum above) |
|
||||
| `int` | `number` | Index of this entity on the server |
|
||||
| `float` | `msg_time` | Server time at which this entity had been updated |
|
||||
| `int` | `messagenum` | `parsecount` at which this entity had been updated |
|
||||
| `vec3_t` | `origin` | Non-interpolated entity position |
|
||||
| `vec3_t` | `angles` | Non-interpolated entity angles |
|
||||
| `int` | `modelindex` | Server model index |
|
||||
| `int` | `sequence` | Model animation sequence |
|
||||
| `int` | `frame` | Model animation frame |
|
||||
| `int` | `colormap` | Texture's top and bottom colors, like Quake |
|
||||
| `short` | `skin` | Texture number |
|
||||
| `short` | `solid` | `edict->solid` enum |
|
||||
| `int` | `effects` | Bitmask of entity effects |
|
||||
| `float` | `scale` | Entity scale value |
|
||||
| `byte` | `eflags` | |
|
||||
| `int` | `eflags` | |
|
||||
| `int` | `eflags` | |
|
||||
| `color24` | `eflags` | |
|
||||
| `int` | `eflags` | |
|
||||
| `int` | `eflags` | |
|
||||
| `float` | `eflags` | |
|
||||
| `float` | `eflags` | |
|
||||
| `int` | `eflags` | |
|
||||
| `byte[4]` | `eflags` | |
|
||||
| `byte[4]` | `eflags` | |
|
||||
| `vec3_t` | `eflags` | |
|
||||
| `vec3_t` | `eflags` | |
|
||||
| `vec3_t` | `eflags` | |
|
||||
| `vec3_t` | `maxs` | |
|
||||
| `int` | `eflags` | |
|
||||
| `int` | `eflags` | |
|
||||
| `float` | `eflags` | |
|
||||
| `float` | `eflags` | |
|
||||
| `int` | `eflags` | |
|
||||
| `int` | `eflags` | |
|
||||
| `int` | `eflags` | |
|
||||
| `qboolean` | `eflags` | |
|
||||
| `int` | `eflags` | |
|
||||
| `int` | `eflags` | |
|
||||
| `vec3_t` | `eflags` | |
|
||||
| `int` | `eflags` | |
|
||||
| `int` | `eflags` | |
|
||||
| `int` | `eflags` | |
|
||||
| `int` | `eflags` | |
|
||||
| `float` | `eflags` | |
|
||||
| `float` | `eflags` | |
|
||||
| `int` | `eflags` | |
|
||||
| `vec3_t` | `eflags` | |
|
||||
| `vec3_t` | `eflags` | |
|
||||
| `float` | `eflags` | |
|
||||
| `float` | `eflags` | |
|
||||
| `int` | `iuser1` | Few more extra fields for mods |
|
||||
| `int` | `iuser2` | |
|
||||
| `int` | `iuser3` | |
|
||||
| `int` | `iuser4` | |
|
||||
| `float` | `fuser1` | |
|
||||
| `float` | `fuser2` | |
|
||||
| `float` | `fuser3` | |
|
||||
| `float` | `fuser4` | |
|
||||
| `vec3_t` | `vuser1` | |
|
||||
| `vec3_t` | `vuser2` | |
|
||||
| `vec3_t` | `vuser3` | |
|
||||
| `vec3_t` | `vuser4` | |
|
||||
@@ -6,7 +6,7 @@ For connecting to GoldSrc-based servers, use this command:
|
||||
connect ip:port gs
|
||||
```
|
||||
|
||||
But keep in mind, there are requirement for server to be able to accept connections from Xash3D-based clients: it should use Reunion.
|
||||
But keep in mind, there are requirement for server to be able to accept connections from Xash3D-based clients: it should use Reunion or Dproto.
|
||||
Without this requirement, you will just get "Steam validation rejected" error on connecting.
|
||||
|
||||
That is because proper authorization with Steam API is not implemented in engine yet (but we have plans on it).
|
||||
|
||||
@@ -38,9 +38,6 @@ Uploaded to github by Oleg Cherkasky - https://github.com/gunrunners-paradise/Ct
|
||||
## Deathmatch Classic
|
||||
Available in Valve's Half-Life repository - https://github.com/ValveSoftware/halflife/tree/master/dmc
|
||||
|
||||
## Delta Particles
|
||||
Available on ModDB - https://www.moddb.com/mods/half-life-delta/downloads/delta-particles-full-sources-maps-and-c-code
|
||||
|
||||
## Earth Special Forces
|
||||
Alpha 2.0 - https://www.gamers-desire.de/details/2830
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
13
README.md
13
README.md
@@ -1,7 +1,6 @@
|
||||
# Xash3D FWGS Engine <img align="right" width="128" height="128" src="https://github.com/FWGS/xash3d-fwgs/raw/master/game_launch/icon-xash-material.png" alt="Xash3D FWGS icon" />
|
||||
[](https://github.com/FWGS/xash3d-fwgs/actions/workflows/c-cpp.yml) [](https://cirrus-ci.com/github/FWGS/xash3d-fwgs) \
|
||||
[](http://fwgsdiscord.mentality.rip/) [](https://t.me/flyingwithgauss) \
|
||||
[](https://github.com/FWGS/xash3d-fwgs/releases/tag/continuous)
|
||||
[](https://builds.sr.ht/~a1batross/xash3d-fwgs?) [](https://github.com/FWGS/xash3d-fwgs/actions/workflows/c-cpp.yml) [](https://cirrus-ci.com/github/FWGS/xash3d-fwgs) [](http://fwgsdiscord.mentality.rip/) \
|
||||
[](https://github.com/FWGS/xash3d-fwgs/releases/latest) [](https://github.com/FWGS/xash3d-fwgs/releases/tag/continuous)
|
||||
|
||||
Xash3D ([pronounced](https://ipa-reader.com/?text=ks%C9%91%CA%82) `[ksɑʂ]`) FWGS is a game engine, aimed to provide compatibility with Half-Life Engine and extend it, as well as to give game developers well known workflow.
|
||||
|
||||
@@ -66,21 +65,21 @@ This repository contains our fork of HLSDK and restored source code for Half-Lif
|
||||
* Only for 32-bit engine on 64-bit x86 operating system:
|
||||
* Enable i386 on your system: `$ sudo dpkg --add-architecture i386`.
|
||||
* Install `aptitude` ([why?](https://github.com/FWGS/xash3d-fwgs/issues/1828#issuecomment-2415131759)): `$ sudo apt update && sudo apt upgrade && sudo apt install aptitude`
|
||||
* Install development tools: `$ sudo aptitude --without-recommends install git build-essential gcc-multilib g++-multilib libsdl2-dev:i386 libfreetype-dev:i386 libopus-dev:i386 libbz2-dev:i386 libvorbis-dev:i386 libopusfile-dev:i386 libogg-dev:i386`.
|
||||
* Install development tools: `$ sudo aptitude --without-recommends install git build-essential gcc-multilib g++-multilib libsdl2-dev:i386 libfontconfig-dev:i386 libfreetype-dev:i386 libopus-dev:i386 libbz2-dev:i386`.
|
||||
* Set PKG_CONFIG_PATH environment variable to point at 32-bit libraries: `$ export PKG_CONFIG_PATH=/usr/lib/i386-linux-gnu/pkgconfig`.
|
||||
|
||||
* For 64-bit engine on 64-bit x86 and other non-x86 systems:
|
||||
* Install development tools: `$ sudo apt install git build-essential python libsdl2-dev libfreetype6-dev libopus-dev libbz2-dev libvorbis-dev libopusfile-dev libogg-dev`.
|
||||
* Install development tools: `$ sudo apt install git build-essential python libsdl2-dev libfontconfig-dev libfreetype6-dev libopus-dev libbz2-dev`.
|
||||
|
||||
* Clone this repostory: `$ git clone --recursive https://github.com/FWGS/xash3d-fwgs`.
|
||||
|
||||
##### RedHat/Fedora
|
||||
* Only for 32-bit engine on 64-bit x86 operating system:
|
||||
* Install development tools: `$ sudo dnf install git gcc gcc-c++ glibc-devel.i686 SDL2-devel.i686 opus-devel.i686 freetype-devel.i686 bzip2-devel.i686 libvorbis-devel.i686 opusfile-devel.i686 libogg-devel.i686`.
|
||||
* Install development tools: `$ sudo dnf install git gcc gcc-c++ glibc-devel.i686 SDL2-devel.i686 opus-devel.i686 fontconfig-devel.i686 freetype-devel.i686 bzip2-devel.i686`.
|
||||
* Set PKG_CONFIG_PATH environment variable to point at 32-bit libraries: `$ export PKG_CONFIG_PATH=/usr/lib/pkgconfig`.
|
||||
|
||||
* For 64-bit engine on 64-bit x86 and other non-x86 systems:
|
||||
* Install development tools: `$ sudo dnf install git gcc gcc-c++ SDL2-devel opus-devel freetype-devel bzip2-devel libvorbis-devel opusfile-devel libogg-devel`.
|
||||
* Install development tools: `$ sudo dnf install git gcc gcc-c++ SDL2-devel opus-devel fontconfig-devel freetype-devel bzip2-devel`.
|
||||
|
||||
* Clone this repostory: `$ git clone --recursive https://github.com/FWGS/xash3d-fwgs`.
|
||||
|
||||
|
||||
@@ -1,39 +1,49 @@
|
||||
cmake_minimum_required(VERSION 3.22)
|
||||
cmake_minimum_required(VERSION 3.6)
|
||||
|
||||
# Only used to build Android project
|
||||
|
||||
project(XASH_ANDROID)
|
||||
|
||||
# armeabi-v7a requires cpufeatures library
|
||||
if(ANDROID)
|
||||
include_directories(${ANDROID_NDK}/sources/android/cpufeatures)
|
||||
add_library(cpufeatures ${ANDROID_NDK}/sources/android/cpufeatures/cpu-features.c)
|
||||
target_link_libraries(cpufeatures dl)
|
||||
endif()
|
||||
include(AndroidNdkModules)
|
||||
android_ndk_import_module_cpufeatures()
|
||||
|
||||
include(FindPython)
|
||||
find_package(PythonInterp 2.7 REQUIRED)
|
||||
|
||||
get_filename_component(C_COMPILER_ID ${CMAKE_C_COMPILER} NAME_WE)
|
||||
get_filename_component(CXX_COMPILER_ID ${CMAKE_CXX_COMPILER} NAME_WE)
|
||||
|
||||
if("${CMAKE_BUILD_TYPE}" STREQUAL "Debug")
|
||||
set(BUILD_TYPE "debug")
|
||||
else()
|
||||
set(BUILD_TYPE "release")
|
||||
list(APPEND WAF_EXTRA_ARGS --enable-poly-opt --enable-lto --enable-limited-debuginfo)
|
||||
list(APPEND WAF_EXTRA_ARGS --enable-poly-opt --enable-lto)
|
||||
endif()
|
||||
|
||||
if(ANDROID_ABI STREQUAL "x86")
|
||||
# HACKHACK: I don't know why but engine gets built as 64-bit binary here
|
||||
list(APPEND WAF_EXTRA_ARGS -4)
|
||||
if(CMAKE_SIZEOF_VOID_P MATCHES "8")
|
||||
set(64BIT ON CACHE BOOL "" FORCE)
|
||||
list(APPEND WAF_EXTRA_ARGS -8) # only required for x86 when testing this cmakelist under linux
|
||||
endif()
|
||||
|
||||
set(CMAKE_VERBOSE_MAKEFILE ON)
|
||||
|
||||
set(WAF_CC "${CMAKE_C_COMPILER} --target=${CMAKE_C_COMPILER_TARGET}")
|
||||
set(WAF_CXX "${CMAKE_CXX_COMPILER} --target=${CMAKE_CXX_COMPILER_TARGET}")
|
||||
|
||||
# not cleanest way to get upper directory
|
||||
set(ENGINE_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../")
|
||||
|
||||
set(WAF_CC "${CMAKE_C_COMPILER} --target=${CMAKE_C_COMPILER_TARGET}")
|
||||
set(WAF_CXX "${CMAKE_CXX_COMPILER} --target=${CMAKE_CXX_COMPILER_TARGET}")
|
||||
set(WAF ${Python_EXECUTABLE} ${ENGINE_SOURCE_DIR}waf -t ${ENGINE_SOURCE_DIR} -o ${CMAKE_CURRENT_BINARY_DIR}/xash3d-fwgs)
|
||||
execute_process(
|
||||
COMMAND ${CMAKE_COMMAND} -E env
|
||||
CC=${WAF_CC} CXX=${WAF_CXX}
|
||||
AR=${CMAKE_AR} STRIP=${CMAKE_STRIP}
|
||||
${PYTHON_EXECUTABLE} waf configure -T ${BUILD_TYPE} ${WAF_EXTRA_ARGS} cmake
|
||||
--check-c-compiler=${C_COMPILER_ID} --check-cxx-compiler=${CXX_COMPILER_ID}
|
||||
-s "${ENGINE_SOURCE_DIR}/SDL" --skip-sdl2-sanity-check --enable-bundled-deps
|
||||
WORKING_DIRECTORY "${ENGINE_SOURCE_DIR}"
|
||||
)
|
||||
|
||||
add_subdirectory("${ENGINE_SOURCE_DIR}/3rdparty/hlsdk-portable" hlsdk-portable)
|
||||
|
||||
# try to build minimal SDL. Enable features as we're gonna use them
|
||||
set(SDL_RENDER OFF)
|
||||
@@ -46,50 +56,5 @@ set(SDL_VULKAN OFF)
|
||||
set(SDL_OFFSCREEN OFF)
|
||||
set(SDL_STATIC OFF)
|
||||
add_subdirectory("${ENGINE_SOURCE_DIR}/3rdparty/SDL" SDL)
|
||||
|
||||
include(ExternalProject)
|
||||
|
||||
# gradle passes backslashes to cmake, how does this even work for everybody else?
|
||||
string(REPLACE "\\" "/" CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_LIBRARY_OUTPUT_DIRECTORY})
|
||||
|
||||
ExternalProject_Add(
|
||||
Xash3DFWGS
|
||||
SOURCE_DIR ${ENGINE_SOURCE_DIR}
|
||||
INSTALL_DIR ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}
|
||||
BUILD_IN_SOURCE TRUE
|
||||
DEPENDS SDL2
|
||||
BUILD_ALWAYS TRUE
|
||||
LOG_CONFIGURE TRUE
|
||||
LOG_BUILD TRUE
|
||||
LOG_INSTALL TRUE
|
||||
LOG_OUTPUT_ON_FAILURE TRUE
|
||||
LOG_MERGED_STDOUTERR TRUE
|
||||
|
||||
# USES_TERMINAL_CONFIGURE TRUE
|
||||
# USES_TERMINAL_BUILD TRUE
|
||||
# USES_TERMINAL_INSTALL TRUE
|
||||
|
||||
# NOTE: setting up WAFLOCK is important to avoid possible race conditions
|
||||
CONFIGURE_COMMAND ${CMAKE_COMMAND} -E env
|
||||
ANDROID_NDK=${ANDROID_NDK}
|
||||
BUILD_CMAKE_LIBRARY_OUTPUT_DIRECTORY=${CMAKE_LIBRARY_OUTPUT_DIRECTORY}
|
||||
WAFLOCK=.lock-waf_android_${ANDROID_ABI}_build
|
||||
${WAF} configure -T ${BUILD_TYPE} --android=${ANDROID_ABI},,${CMAKE_SYSTEM_VERSION}
|
||||
-s "${ENGINE_SOURCE_DIR}/3rdparty/SDL" --enable-bundled-deps ${WAF_EXTRA_ARGS}
|
||||
|
||||
BUILD_COMMAND ${CMAKE_COMMAND} -E env
|
||||
WAFLOCK=.lock-waf_android_${ANDROID_ABI}_build
|
||||
${WAF} build -v
|
||||
|
||||
INSTALL_COMMAND ${CMAKE_COMMAND} -E env
|
||||
WAFLOCK=.lock-waf_android_${ANDROID_ABI}_build
|
||||
${WAF} install --destdir=${CMAKE_LIBRARY_OUTPUT_DIRECTORY}
|
||||
)
|
||||
|
||||
add_subdirectory("${ENGINE_SOURCE_DIR}/3rdparty/hlsdk-portable" hlsdk-portable)
|
||||
|
||||
# a1ba: without this, xash3d target will be ignored as nothing depends on it
|
||||
add_dependencies(client Xash3DFWGS)
|
||||
add_dependencies(server Xash3DFWGS)
|
||||
|
||||
|
||||
add_subdirectory("${ENGINE_SOURCE_DIR}/" xash3d-fwgs)
|
||||
add_subdirectory("${ENGINE_SOURCE_DIR}/3rdparty/mainui" mainui)
|
||||
|
||||
@@ -9,7 +9,7 @@ plugins {
|
||||
|
||||
android {
|
||||
namespace = "su.xash.engine"
|
||||
ndkVersion = "28.0.13004108"
|
||||
ndkVersion = "27.2.12479018"
|
||||
|
||||
defaultConfig {
|
||||
applicationId = "su.xash"
|
||||
@@ -96,7 +96,6 @@ android {
|
||||
packaging {
|
||||
jniLibs {
|
||||
useLegacyPackaging = true
|
||||
keepDebugSymbols.add("**/*.so")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -113,7 +112,7 @@ dependencies {
|
||||
implementation("androidx.preference:preference-ktx:1.2.1")
|
||||
implementation("androidx.swiperefreshlayout:swiperefreshlayout:1.1.0")
|
||||
implementation("androidx.work:work-runtime-ktx:2.9.0")
|
||||
// implementation "androidx.legacy:legacy-support-v4:1.0.0"
|
||||
// implementation "androidx.legacy:legacy-support-v4:1.0.0"
|
||||
|
||||
implementation("com.madgag.spongycastle:prov:1.58.0.0")
|
||||
implementation("in.dragonbra:javasteam:1.2.0")
|
||||
|
||||
@@ -20,7 +20,4 @@ kotlin.code.style=official
|
||||
# Enables namespacing of each library's R class so that its R class includes only the
|
||||
# resources declared in the library itself and none from the library's dependencies,
|
||||
# thereby reducing the size of the R class for that library
|
||||
android.nonTransitiveRClass=true
|
||||
|
||||
# Enable verbose output for CMake
|
||||
android.native.buildOutput=verbose
|
||||
android.nonTransitiveRClass=true
|
||||
@@ -28,17 +28,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#define PORT_ANY -1
|
||||
|
||||
typedef enum netadrtype_e
|
||||
{
|
||||
NA_UNDEFINED = 0,
|
||||
NA_LOOPBACK,
|
||||
NA_BROADCAST,
|
||||
NA_IP,
|
||||
NA_IPX,
|
||||
NA_BROADCAST_IPX,
|
||||
NA_IP6,
|
||||
NA_MULTICAST_IP6
|
||||
} netadrtype_t;
|
||||
typedef enum {NA_LOOPBACK = 1, NA_BROADCAST, NA_IP, NA_IPX, NA_BROADCAST_IPX, NA_IP6, NA_MULTICAST_IP6} netadrtype_t;
|
||||
|
||||
/*
|
||||
Original Quake-2 structure:
|
||||
@@ -56,60 +46,29 @@ typedef struct
|
||||
#pragma pack( push, 1 )
|
||||
typedef struct netadr_s
|
||||
{
|
||||
// the reason we do this evil thing, is that when this struct contains IPv6
|
||||
// address the `type` is 2-byte wide, but when it doesn't `type` must 4-byte
|
||||
// wide _and_ ip6_0 must be zeroed, to keep it binary compatible.
|
||||
#if XASH_LITTLE_ENDIAN
|
||||
uint16_t type;
|
||||
uint8_t ip6_0[2];
|
||||
#elif XASH_BIG_ENDIAN
|
||||
uint8_t ip6_0[2];
|
||||
uint16_t type;
|
||||
#else
|
||||
#error
|
||||
#endif
|
||||
|
||||
union
|
||||
{
|
||||
// IPv6 struct
|
||||
uint8_t ip6_1[14];
|
||||
struct
|
||||
{
|
||||
uint16_t type6;
|
||||
uint8_t ip6[16];
|
||||
};
|
||||
struct
|
||||
{
|
||||
uint32_t type; // must be netadrtype_t but will break with short enums
|
||||
union
|
||||
{
|
||||
uint8_t ip[4];
|
||||
uint32_t ip4; // for easier conversions
|
||||
uint8_t ip[4];
|
||||
uint32_t ip4; // for easier conversions
|
||||
};
|
||||
uint8_t ipx[10];
|
||||
};
|
||||
};
|
||||
uint16_t port;
|
||||
uint16_t port;
|
||||
} netadr_t;
|
||||
#pragma pack( pop )
|
||||
|
||||
static inline netadrtype_t NET_NetadrType( const netadr_t *a )
|
||||
{
|
||||
if( a->type == NA_IP6 || a->type == NA_MULTICAST_IP6 )
|
||||
return (netadrtype_t)a->type;
|
||||
|
||||
if( a->ip6_0[0] || a->ip6_0[1] )
|
||||
return NA_UNDEFINED;
|
||||
|
||||
return (netadrtype_t)a->type;
|
||||
}
|
||||
|
||||
static inline void NET_NetadrSetType( netadr_t *a, netadrtype_t type )
|
||||
{
|
||||
if( type == NA_IP6 || type == NA_MULTICAST_IP6 )
|
||||
{
|
||||
a->type = type;
|
||||
return;
|
||||
}
|
||||
|
||||
a->ip6_0[0] = a->ip6_0[1] = 0;
|
||||
a->type = type;
|
||||
}
|
||||
|
||||
STATIC_CHECK_SIZEOF( netadr_t, 20, 20 );
|
||||
|
||||
#endif // NET_ADR_H
|
||||
|
||||
@@ -86,4 +86,8 @@ GNU General Public License for more details.
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
|
||||
#if defined XASH_SDL && !defined REF_DLL
|
||||
#include <SDL.h>
|
||||
#endif
|
||||
|
||||
#endif // PORT_H
|
||||
|
||||
@@ -13,44 +13,47 @@
|
||||
#endif // _WIN32
|
||||
|
||||
#include <sys/types.h> // off_t
|
||||
#ifdef STDINT_H
|
||||
#include STDINT_H
|
||||
#else // !STDINT_H
|
||||
#include <stdint.h>
|
||||
#endif // !STDINT_H
|
||||
#include <assert.h>
|
||||
|
||||
typedef uint8_t byte;
|
||||
typedef float vec_t;
|
||||
typedef vec_t vec2_t[2];
|
||||
#ifndef vec3_t // SDK renames it to Vector
|
||||
typedef vec_t vec3_t[3];
|
||||
#endif
|
||||
typedef vec_t vec4_t[4];
|
||||
typedef vec_t quat_t[4];
|
||||
typedef byte rgba_t[4]; // unsigned byte colorpack
|
||||
typedef byte rgb_t[3]; // unsigned byte colorpack
|
||||
typedef vec_t matrix3x4[3][4];
|
||||
typedef vec_t matrix4x4[4][4];
|
||||
typedef uint32_t poolhandle_t;
|
||||
typedef unsigned char byte;
|
||||
typedef int sound_t;
|
||||
typedef float vec_t;
|
||||
typedef vec_t vec2_t[2];
|
||||
typedef vec_t vec3_t[3];
|
||||
typedef vec_t vec4_t[4];
|
||||
typedef vec_t quat_t[4];
|
||||
typedef byte rgba_t[4]; // unsigned byte colorpack
|
||||
typedef byte rgb_t[3]; // unsigned byte colorpack
|
||||
typedef vec_t matrix3x4[3][4];
|
||||
typedef vec_t matrix4x4[4][4];
|
||||
|
||||
typedef uint32_t poolhandle_t;
|
||||
|
||||
#undef true
|
||||
#undef false
|
||||
|
||||
// true and false are keywords in C++ and C23
|
||||
#if !__cplusplus && __STDC_VERSION__ < 202311L
|
||||
enum { false, true };
|
||||
#endif
|
||||
#ifndef __cplusplus
|
||||
typedef enum { false, true } qboolean;
|
||||
#else
|
||||
typedef int qboolean;
|
||||
#endif
|
||||
|
||||
#define MAX_STRING 256 // generic string
|
||||
#define MAX_VA_STRING 1024 // compatibility macro
|
||||
#define MAX_SYSPATH 1024 // system filepath
|
||||
#define MAX_MODS 512 // environment games that engine can keep visible
|
||||
typedef uint64_t longtime_t;
|
||||
|
||||
#define MAX_STRING 256 // generic string
|
||||
#define MAX_INFO_STRING 256 // infostrings are transmitted across network
|
||||
#define MAX_SERVERINFO_STRING 512 // server handles too many settings. expand to 1024?
|
||||
#define MAX_LOCALINFO_STRING 32768 // localinfo used on server and not sended to the clients
|
||||
#define MAX_SYSPATH 1024 // system filepath
|
||||
#define MAX_VA_STRING 1024 // string length returned by va()
|
||||
#define MAX_PRINT_MSG 8192 // how many symbols can handle single call of Con_Printf or Con_DPrintf
|
||||
#define MAX_TOKEN 2048 // parse token length
|
||||
#define MAX_MODS 512 // environment games that engine can keep visible
|
||||
#define MAX_USERMSG_LENGTH 2048 // don't modify it's relies on a client-side definitions
|
||||
|
||||
#define BIT( n ) ( 1U << ( n ))
|
||||
#define BIT64( n ) ( 1ULL << ( n ))
|
||||
|
||||
#define SetBits( iBitVector, bits ) ((iBitVector) = (iBitVector) | (bits))
|
||||
#define ClearBits( iBitVector, bits ) ((iBitVector) = (iBitVector) & ~(bits))
|
||||
#define FBitSet( iBitVector, bit ) ((iBitVector) & (bit))
|
||||
@@ -67,8 +70,6 @@ typedef int qboolean;
|
||||
#define IsColorString( p ) ( p && *( p ) == '^' && *(( p ) + 1) && *(( p ) + 1) >= '0' && *(( p ) + 1 ) <= '9' )
|
||||
#define ColorIndex( c ) ((( c ) - '0' ) & 7 )
|
||||
|
||||
#undef EXPORT
|
||||
|
||||
#if defined( __GNUC__ )
|
||||
#if defined( __i386__ )
|
||||
#define EXPORT __attribute__(( visibility( "default" ), force_align_arg_pointer ))
|
||||
@@ -208,16 +209,35 @@ _inline float LittleFloat( float f )
|
||||
#endif
|
||||
|
||||
|
||||
typedef unsigned int dword;
|
||||
typedef unsigned int uint;
|
||||
typedef char string[MAX_STRING];
|
||||
typedef off_t fs_offset_t;
|
||||
typedef unsigned int dword;
|
||||
typedef unsigned int uint;
|
||||
typedef unsigned long ulong;
|
||||
typedef char string[MAX_STRING];
|
||||
typedef struct file_s file_t; // normal file
|
||||
typedef struct stream_s stream_t; // sound stream for background music playing
|
||||
typedef off_t fs_offset_t;
|
||||
#if XASH_WIN32
|
||||
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 */
|
||||
typedef ssize_t fs_size_t;
|
||||
typedef ssize_t fs_size_t;
|
||||
#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 * );
|
||||
|
||||
// config strings are a general means of communication from
|
||||
|
||||
@@ -198,44 +198,3 @@ void CL_WriteMessageHistory( void )
|
||||
CL_WriteErrorMessage( old->starting_offset, msg );
|
||||
cls_message_debug.parsing = false;
|
||||
}
|
||||
|
||||
void CL_ReplayBufferDat_f( void )
|
||||
{
|
||||
file_t *f = FS_Open( Cmd_Argv( 1 ), "rb", true );
|
||||
sizebuf_t msg;
|
||||
char buffer[NET_MAX_MESSAGE];
|
||||
int starting_count, current_count, protocol;
|
||||
fs_offset_t len;
|
||||
|
||||
if( !f )
|
||||
return;
|
||||
|
||||
FS_Read( f, &starting_count, sizeof( starting_count ));
|
||||
FS_Read( f, ¤t_count, sizeof( current_count ));
|
||||
FS_Read( f, &protocol, sizeof( protocol ));
|
||||
|
||||
cls.legacymode = protocol;
|
||||
|
||||
len = FS_Read( f, buffer, sizeof( buffer ));
|
||||
FS_Close( f );
|
||||
|
||||
MSG_Init( &msg, __func__, buffer, len );
|
||||
|
||||
Delta_Shutdown();
|
||||
Delta_Init();
|
||||
|
||||
clgame.maxEntities = MAX_EDICTS;
|
||||
clgame.entities = Mem_Calloc( clgame.mempool, sizeof( *clgame.entities ) * clgame.maxEntities );
|
||||
|
||||
// ad-hoc implement
|
||||
#if 0
|
||||
{
|
||||
const int message_pos = 12; // put real number here
|
||||
MSG_SeekToBit( &msg, ( message_pos - 12 + 1 ) << 3, SEEK_SET );
|
||||
|
||||
CL_ParseYourMom( &msg, protocol );
|
||||
}
|
||||
#endif
|
||||
|
||||
Sys_Quit( __func__ );
|
||||
}
|
||||
|
||||
@@ -373,7 +373,7 @@ CL_WriteDemoUserMessage
|
||||
Dumps the user message (demoaction)
|
||||
====================
|
||||
*/
|
||||
void GAME_EXPORT CL_WriteDemoUserMessage( int size, byte *buffer )
|
||||
void CL_WriteDemoUserMessage( const byte *buffer, size_t size )
|
||||
{
|
||||
if( !cls.demorecording || cls.demowaiting )
|
||||
return;
|
||||
|
||||
@@ -2229,3 +2229,4 @@ void CL_ThinkParticle( double frametime, particle_t *p )
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -13,12 +13,10 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <ctype.h>
|
||||
#include "common.h"
|
||||
#include "filesystem.h"
|
||||
#include "client.h"
|
||||
#include "qfont.h"
|
||||
#include "utflib.h"
|
||||
|
||||
qboolean CL_FixedFont( cl_font_t *font )
|
||||
{
|
||||
@@ -175,27 +173,31 @@ static int CL_CalcTabStop( const cl_font_t *font, int x )
|
||||
return stop;
|
||||
}
|
||||
|
||||
static int CL_DrawBitmapCharacter( float x, float y, uint32_t uc, const rgba_t color, const cl_font_t *font, int flags )
|
||||
int CL_DrawCharacter( float x, float y, int number, rgba_t color, cl_font_t *font, int flags )
|
||||
{
|
||||
wrect_t *rc;
|
||||
float w, h;
|
||||
float s1, t1, s2, t2, half = 0.5f;
|
||||
int texw, texh;
|
||||
uint32_t number;
|
||||
|
||||
// bitmap fonts need conversion. Do this and validate the result
|
||||
if( g_codepage == 1251 )
|
||||
number = Q_UnicodeToCP1251( uc );
|
||||
else if( g_codepage == 1252 )
|
||||
number = Q_UnicodeToCP1252( uc );
|
||||
else
|
||||
number = uc;
|
||||
|
||||
if( !number || number >= ARRAYSIZE( font->charWidths ))
|
||||
if( !font || !font->valid || y < -font->charHeight )
|
||||
return 0;
|
||||
|
||||
// start rendering
|
||||
if( !font->charWidths[number] )
|
||||
// check if printable
|
||||
if( number <= 32 )
|
||||
{
|
||||
if( number == ' ' )
|
||||
return font->charWidths[' '];
|
||||
else if( number == '\t' )
|
||||
return CL_CalcTabStop( font, x );
|
||||
return 0;
|
||||
}
|
||||
|
||||
if( FBitSet( flags, FONT_DRAW_UTF8 ))
|
||||
number = Con_UtfProcessChar( number & 255 );
|
||||
else number &= 255;
|
||||
|
||||
if( !number || !font->charWidths[number])
|
||||
return 0;
|
||||
|
||||
R_GetTextureParms( &texw, &texh, font->hFontTexture );
|
||||
@@ -229,60 +231,29 @@ static int CL_DrawBitmapCharacter( float x, float y, uint32_t uc, const rgba_t c
|
||||
return font->charWidths[number];
|
||||
}
|
||||
|
||||
static int CL_DrawTrueTypeCharacter( float x, float y, uint32_t uc, const rgba_t color, cl_font_t *font, int flags )
|
||||
{
|
||||
// stub
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CL_DrawCharacter( float x, float y, uint32_t uc, const rgba_t color, const cl_font_t *font, int flags )
|
||||
{
|
||||
if( !font || !font->valid || y < -font->charHeight )
|
||||
return 0;
|
||||
|
||||
// check if printable
|
||||
if( uc <= 32 )
|
||||
{
|
||||
if( uc == ' ' )
|
||||
return font->charWidths[' '];
|
||||
else if( uc == '\t' )
|
||||
return CL_CalcTabStop( font, x );
|
||||
return 0;
|
||||
}
|
||||
|
||||
if( font->type == FONT_TRUETYPE )
|
||||
return CL_DrawTrueTypeCharacter( x, y, uc, color, font, flags );
|
||||
|
||||
return CL_DrawBitmapCharacter( x, y, uc, color, font, flags );
|
||||
}
|
||||
|
||||
int CL_DrawString( float x, float y, const char *s, const rgba_t color, const cl_font_t *font, int flags )
|
||||
int CL_DrawString( float x, float y, const char *s, rgba_t color, cl_font_t *font, int flags )
|
||||
{
|
||||
rgba_t current_color;
|
||||
int draw_len = 0;
|
||||
utfstate_t utfstate = { 0 };
|
||||
|
||||
if( !font || !font->valid )
|
||||
return 0;
|
||||
|
||||
if( FBitSet( flags, FONT_DRAW_UTF8 ))
|
||||
Con_UtfProcessChar( 0 ); // clear utf state
|
||||
|
||||
if( !FBitSet( flags, FONT_DRAW_NORENDERMODE ))
|
||||
CL_SetFontRendermode( font );
|
||||
|
||||
Vector4Copy( color, current_color );
|
||||
|
||||
for( ; *s; s++ )
|
||||
while( *s )
|
||||
{
|
||||
uint32_t uc = (byte)*s;
|
||||
|
||||
if( FBitSet( flags, FONT_DRAW_UTF8 ))
|
||||
uc = Q_DecodeUTF8( &utfstate, uc );
|
||||
|
||||
if( !uc )
|
||||
continue;
|
||||
|
||||
if( uc == '\n' )
|
||||
if( *s == '\n' )
|
||||
{
|
||||
if( !s[1] ) // ignore newline at end of string if next
|
||||
s++;
|
||||
|
||||
if( !*s )
|
||||
break;
|
||||
|
||||
// some client functions ignore newlines
|
||||
@@ -293,29 +264,30 @@ int CL_DrawString( float x, float y, const char *s, const rgba_t color, const cl
|
||||
}
|
||||
|
||||
if( FBitSet( flags, FONT_DRAW_RESETCOLORONLF ))
|
||||
Vector4Copy( color, current_color );
|
||||
|
||||
Vector4Copy( color, current_color );
|
||||
continue;
|
||||
}
|
||||
|
||||
// check for colorstrings
|
||||
if( uc == '^' && isdigit( s[1] ))
|
||||
if( IsColorString( s ))
|
||||
{
|
||||
// don't copy alpha
|
||||
if( !FBitSet( flags, FONT_DRAW_FORCECOL ))
|
||||
VectorCopy( g_color_table[ColorIndex( s[1] )], current_color );
|
||||
VectorCopy( g_color_table[ColorIndex(*( s + 1 ))], current_color );
|
||||
|
||||
s++;
|
||||
s += 2;
|
||||
continue;
|
||||
}
|
||||
|
||||
// skip setting rendermode, it was changed for this string already
|
||||
draw_len += CL_DrawCharacter( x + draw_len, y, uc, current_color, font, flags | FONT_DRAW_NORENDERMODE );
|
||||
draw_len += CL_DrawCharacter( x + draw_len, y, (byte)*s, current_color, font, flags | FONT_DRAW_NORENDERMODE );
|
||||
|
||||
s++;
|
||||
}
|
||||
|
||||
return draw_len;
|
||||
}
|
||||
|
||||
int CL_DrawStringf( const cl_font_t *font, float x, float y, const rgba_t color, int flags, const char *fmt, ... )
|
||||
int CL_DrawStringf( cl_font_t *font, float x, float y, rgba_t color, int flags, const char *fmt, ... )
|
||||
{
|
||||
va_list va;
|
||||
char buf[MAX_VA_STRING];
|
||||
@@ -327,63 +299,20 @@ int CL_DrawStringf( const cl_font_t *font, float x, float y, const rgba_t color,
|
||||
return CL_DrawString( x, y, buf, color, font, flags );
|
||||
}
|
||||
|
||||
static int CL_DrawBitmapCharacterLen( const cl_font_t *font, uint32_t uc )
|
||||
void CL_DrawCharacterLen( cl_font_t *font, int number, int *width, int *height )
|
||||
{
|
||||
int number;
|
||||
|
||||
if( g_codepage == 1251 )
|
||||
number = Q_UnicodeToCP1251( uc );
|
||||
else if( g_codepage == 1252 )
|
||||
number = Q_UnicodeToCP1252( uc );
|
||||
else
|
||||
number = uc;
|
||||
|
||||
if( !number || number >= ARRAYSIZE( font->charWidths ))
|
||||
return 0;
|
||||
|
||||
return font->charWidths[number];
|
||||
}
|
||||
|
||||
static int CL_DrawTrueTypeCharacterLen( const cl_font_t *font, uint32_t uc )
|
||||
{
|
||||
// stub
|
||||
return 0;
|
||||
}
|
||||
|
||||
void CL_DrawCharacterLen( const cl_font_t *font, uint32_t uc, int *width, int *height )
|
||||
{
|
||||
if( !font || !font->valid )
|
||||
return;
|
||||
|
||||
if( height )
|
||||
*height = font->charHeight;
|
||||
|
||||
if( !font || !font->valid ) return;
|
||||
if( width )
|
||||
{
|
||||
// basically matches logic of CL_DrawCharacter
|
||||
if( uc <= 32 )
|
||||
{
|
||||
if( uc == ' ' )
|
||||
*width = font->charWidths[' '];
|
||||
else if( uc == '\t' )
|
||||
*width = CL_CalcTabStop( font, 0 ); // at least return max tabstop
|
||||
else
|
||||
*width = 0;
|
||||
}
|
||||
else if( font->type == FONT_TRUETYPE )
|
||||
{
|
||||
*width = CL_DrawTrueTypeCharacterLen( font, uc );
|
||||
}
|
||||
else
|
||||
{
|
||||
*width = CL_DrawBitmapCharacterLen( font, uc );
|
||||
}
|
||||
if( number == '\t' )
|
||||
*width = CL_CalcTabStop( font, 0 ); // at least return max tabstop
|
||||
else *width = font->charWidths[number & 255];
|
||||
}
|
||||
if( height ) *height = font->charHeight;
|
||||
}
|
||||
|
||||
void CL_DrawStringLen( const cl_font_t *font, const char *s, int *width, int *height, int flags )
|
||||
void CL_DrawStringLen( cl_font_t *font, const char *s, int *width, int *height, int flags )
|
||||
{
|
||||
utfstate_t utfstate = { 0 };
|
||||
int draw_len = 0;
|
||||
|
||||
if( !font || !font->valid )
|
||||
@@ -398,45 +327,54 @@ void CL_DrawStringLen( const cl_font_t *font, const char *s, int *width, int *he
|
||||
if( !COM_CheckString( s ))
|
||||
return;
|
||||
|
||||
for( ; *s; s++ )
|
||||
if( FBitSet( flags, FONT_DRAW_UTF8 ))
|
||||
Con_UtfProcessChar( 0 ); // reset utf state
|
||||
|
||||
while( *s )
|
||||
{
|
||||
uint32_t uc = (byte)*s;
|
||||
int char_width = 0;
|
||||
int number;
|
||||
|
||||
if( FBitSet( flags, FONT_DRAW_UTF8 ))
|
||||
uc = Q_DecodeUTF8( &utfstate, uc );
|
||||
|
||||
if( !uc )
|
||||
continue;
|
||||
|
||||
if( uc == '\n' )
|
||||
if( *s == '\n' )
|
||||
{
|
||||
// BUG: no check for end string here
|
||||
// but high chances somebody's relying on this
|
||||
s++;
|
||||
draw_len = 0;
|
||||
|
||||
// some client functions ignore newlines
|
||||
if( !FBitSet( flags, FONT_DRAW_NOLF ))
|
||||
{
|
||||
if( height )
|
||||
*height += font->charHeight;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// check for colorstrings
|
||||
if( uc == '^' && isdigit( s[1] ))
|
||||
else if( *s == '\t' )
|
||||
{
|
||||
draw_len += CL_CalcTabStop( font, 0 ); // at least return max tabstop
|
||||
s++;
|
||||
continue;
|
||||
}
|
||||
|
||||
CL_DrawCharacterLen( font, uc, &char_width, NULL );
|
||||
draw_len += char_width;
|
||||
|
||||
if( width )
|
||||
if( IsColorString( s ))
|
||||
{
|
||||
if( *width < draw_len )
|
||||
*width = draw_len;
|
||||
s += 2;
|
||||
continue;
|
||||
}
|
||||
|
||||
if( FBitSet( flags, FONT_DRAW_UTF8 ))
|
||||
number = Con_UtfProcessChar( (byte)*s );
|
||||
else number = (byte)*s;
|
||||
|
||||
if( number )
|
||||
{
|
||||
draw_len += font->charWidths[number];
|
||||
|
||||
if( width )
|
||||
{
|
||||
if( draw_len > *width )
|
||||
*width = draw_len;
|
||||
}
|
||||
}
|
||||
|
||||
s++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,10 +13,6 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#if XASH_SDL
|
||||
#include <SDL.h> // SDL_GetWindowPosition
|
||||
#endif // XASH_SDL
|
||||
|
||||
#include "common.h"
|
||||
#include "client.h"
|
||||
#include "const.h"
|
||||
@@ -33,7 +29,6 @@ GNU General Public License for more details.
|
||||
#include "vgui_draw.h"
|
||||
#include "sound.h" // SND_STOP_LOOPING
|
||||
#include "platform/platform.h"
|
||||
#include "utflib.h"
|
||||
|
||||
#define MAX_LINELENGTH 80
|
||||
#define MAX_TEXTCHANNELS 8 // must be power of two (GoldSrc uses 4 channels)
|
||||
@@ -311,22 +306,21 @@ void SPR_AdjustSize( float *x, float *y, float *w, float *h )
|
||||
|
||||
static void SPR_AdjustTexCoords( int texnum, float width, float height, float *s1, float *t1, float *s2, float *t2 )
|
||||
{
|
||||
const qboolean filtering = REF_GET_PARM( PARM_TEX_FILTERING, texnum );
|
||||
const int xremainder = refState.width % clgame.scrInfo.iWidth;
|
||||
const int yremainder = refState.height % clgame.scrInfo.iHeight;
|
||||
|
||||
if(( filtering || xremainder ) && refState.width != clgame.scrInfo.iWidth )
|
||||
if( REF_GET_PARM( PARM_TEX_FILTERING, texnum ))
|
||||
{
|
||||
// align to texel if scaling
|
||||
*s1 += 0.5f;
|
||||
*s2 -= 0.5f;
|
||||
}
|
||||
if( refState.width != clgame.scrInfo.iWidth )
|
||||
{
|
||||
// align to texel if scaling
|
||||
*s1 += 0.5f;
|
||||
*s2 -= 0.5f;
|
||||
}
|
||||
|
||||
if(( filtering || yremainder ) && refState.height != clgame.scrInfo.iHeight )
|
||||
{
|
||||
// align to texel if scaling
|
||||
*t1 += 0.5f;
|
||||
*t2 -= 0.5f;
|
||||
if( refState.height != clgame.scrInfo.iHeight )
|
||||
{
|
||||
// align to texel if scaling
|
||||
*t1 += 0.5f;
|
||||
*t2 -= 0.5f;
|
||||
}
|
||||
}
|
||||
|
||||
*s1 /= width;
|
||||
@@ -409,10 +403,8 @@ void CL_DrawCenterPrint( void )
|
||||
char *pText;
|
||||
int i, j, x, y;
|
||||
int width, lineLength;
|
||||
byte *colorDefault;
|
||||
uint32_t line[MAX_LINELENGTH];
|
||||
byte *colorDefault, line[MAX_LINELENGTH];
|
||||
int charWidth, charHeight;
|
||||
utfstate_t utfstate = { 0 };
|
||||
|
||||
if( !clgame.centerPrint.time )
|
||||
return;
|
||||
@@ -435,19 +427,14 @@ void CL_DrawCenterPrint( void )
|
||||
lineLength = 0;
|
||||
width = 0;
|
||||
|
||||
for( ; *pText && *pText != '\n' && lineLength < MAX_LINELENGTH; pText++ )
|
||||
while( *pText && *pText != '\n' && lineLength < MAX_LINELENGTH )
|
||||
{
|
||||
byte c = *pText;
|
||||
uint32_t uc = Q_DecodeUTF8( &utfstate, c );
|
||||
|
||||
if( !uc )
|
||||
continue;
|
||||
|
||||
line[lineLength] = uc;
|
||||
CL_DrawCharacterLen( font, uc, &charWidth, NULL );
|
||||
|
||||
line[lineLength] = c;
|
||||
CL_DrawCharacterLen( font, c, &charWidth, NULL );
|
||||
width += charWidth;
|
||||
lineLength++;
|
||||
pText++;
|
||||
}
|
||||
|
||||
if( lineLength == MAX_LINELENGTH )
|
||||
@@ -461,7 +448,7 @@ void CL_DrawCenterPrint( void )
|
||||
for( j = 0; j < lineLength; j++ )
|
||||
{
|
||||
if( x >= 0 && y >= 0 && x <= refState.width )
|
||||
x += CL_DrawCharacter( x, y, line[j], colorDefault, font, FONT_DRAW_HUD | FONT_DRAW_NORENDERMODE );
|
||||
x += CL_DrawCharacter( x, y, line[j], colorDefault, font, FONT_DRAW_UTF8 | FONT_DRAW_HUD | FONT_DRAW_NORENDERMODE );
|
||||
}
|
||||
y += charHeight;
|
||||
}
|
||||
@@ -569,7 +556,7 @@ static void CL_InitTitles( const char *filename )
|
||||
|
||||
Q_snprintf( name, sizeof( name ), TEXT_MSGNAME, i );
|
||||
|
||||
cl_textmessage[i].pName = copystringpool( clgame.mempool, name );
|
||||
cl_textmessage[i].pName = _copystring( clgame.mempool, name, __FILE__, __LINE__ );
|
||||
cl_textmessage[i].pMessage = cl_textbuffer[i];
|
||||
}
|
||||
|
||||
@@ -1711,12 +1698,7 @@ int GAME_EXPORT CL_GetScreenInfo( SCREENINFO *pscrinfo )
|
||||
clgame.scrInfo.iSize = sizeof( clgame.scrInfo );
|
||||
clgame.scrInfo.iFlags = SCRINFO_SCREENFLASH;
|
||||
|
||||
if( hud_scale.value >= 320.0f && hud_scale.value >= hud_scale_minimal_width.value )
|
||||
{
|
||||
scale_factor = refState.width / hud_scale.value;
|
||||
apply_scale_factor = true;
|
||||
}
|
||||
else if( scale_factor && scale_factor != 1.0f )
|
||||
if( scale_factor && scale_factor != 1.0f )
|
||||
{
|
||||
float scaled_width = (float)refState.width / scale_factor;
|
||||
if( scaled_width >= hud_scale_minimal_width.value )
|
||||
@@ -1997,13 +1979,7 @@ static int GAME_EXPORT pfnDrawCharacter( int x, int y, int number, int r, int g,
|
||||
int flags = FONT_DRAW_HUD;
|
||||
|
||||
if( hud_utf8.value )
|
||||
{
|
||||
static utfstate_t utfstate;
|
||||
number = Q_DecodeUTF8( &utfstate, number );
|
||||
|
||||
if( !number )
|
||||
return 0;
|
||||
}
|
||||
flags |= FONT_DRAW_UTF8;
|
||||
|
||||
return CL_DrawCharacter( x, y, number, color, &cls.creditsFont, flags );
|
||||
}
|
||||
@@ -3066,8 +3042,12 @@ pfnDrawString
|
||||
*/
|
||||
static int GAME_EXPORT pfnDrawString( int x, int y, const char *str, int r, int g, int b )
|
||||
{
|
||||
const rgba_t color = { r, g, b, 255 };
|
||||
int flags = FONT_DRAW_HUD | FONT_DRAW_NOLF | FONT_DRAW_UTF8;
|
||||
rgba_t color = { r, g, b, 255 };
|
||||
int flags = FONT_DRAW_HUD | FONT_DRAW_NOLF;
|
||||
|
||||
if( hud_utf8.value )
|
||||
SetBits( flags, FONT_DRAW_UTF8 );
|
||||
|
||||
return CL_DrawString( x, y, str, color, &cls.creditsFont, flags );
|
||||
}
|
||||
|
||||
@@ -3079,10 +3059,13 @@ pfnDrawStringReverse
|
||||
*/
|
||||
static int GAME_EXPORT pfnDrawStringReverse( int x, int y, const char *str, int r, int g, int b )
|
||||
{
|
||||
const rgba_t color = { r, g, b, 255 };
|
||||
int flags = FONT_DRAW_HUD | FONT_DRAW_NOLF | FONT_DRAW_UTF8;
|
||||
rgba_t color = { r, g, b, 255 };
|
||||
int flags = FONT_DRAW_HUD | FONT_DRAW_NOLF;
|
||||
int width;
|
||||
|
||||
if( hud_utf8.value )
|
||||
SetBits( flags, FONT_DRAW_UTF8 );
|
||||
|
||||
CL_DrawStringLen( &cls.creditsFont, str, &width, NULL, flags );
|
||||
|
||||
x -= width;
|
||||
@@ -3365,6 +3348,28 @@ DemoApi implementation
|
||||
|
||||
=================
|
||||
*/
|
||||
/*
|
||||
=================
|
||||
Demo_IsRecording
|
||||
|
||||
=================
|
||||
*/
|
||||
static int GAME_EXPORT Demo_IsRecording( void )
|
||||
{
|
||||
return cls.demorecording;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
Demo_IsPlayingback
|
||||
|
||||
=================
|
||||
*/
|
||||
static int GAME_EXPORT Demo_IsPlayingback( void )
|
||||
{
|
||||
return cls.demoplayback;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
Demo_IsTimeDemo
|
||||
@@ -3376,6 +3381,17 @@ static int GAME_EXPORT Demo_IsTimeDemo( void )
|
||||
return cls.timedemo;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
Demo_WriteBuffer
|
||||
|
||||
=================
|
||||
*/
|
||||
static void GAME_EXPORT Demo_WriteBuffer( int size, byte *buffer )
|
||||
{
|
||||
CL_WriteDemoUserMessage( buffer, size );
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
NetworkApi implementation
|
||||
@@ -3438,7 +3454,7 @@ static void GAME_EXPORT NetAPI_SendRequest( int context, int request, int flags,
|
||||
return;
|
||||
}
|
||||
|
||||
if( NET_NetadrType( remote_address ) == NA_IPX || NET_NetadrType( remote_address ) == NA_BROADCAST_IPX )
|
||||
if( remote_address->type == NA_IPX || remote_address->type == NA_BROADCAST_IPX )
|
||||
return; // IPX no longer support
|
||||
|
||||
if( request == NETAPI_REQUEST_SERVERLIST )
|
||||
@@ -3561,6 +3577,28 @@ static int GAME_EXPORT NetAPI_CompareAdr( netadr_t *a, netadr_t *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
|
||||
@@ -3757,10 +3795,10 @@ static event_api_t gEventApi =
|
||||
|
||||
static demo_api_t gDemoApi =
|
||||
{
|
||||
(void *)CL_IsRecordDemo,
|
||||
(void *)CL_IsPlaybackDemo,
|
||||
Demo_IsRecording,
|
||||
Demo_IsPlayingback,
|
||||
Demo_IsTimeDemo,
|
||||
CL_WriteDemoUserMessage,
|
||||
Demo_WriteBuffer,
|
||||
};
|
||||
|
||||
net_api_t gNetApi =
|
||||
@@ -3772,8 +3810,8 @@ net_api_t gNetApi =
|
||||
NetAPI_CancelAllRequests,
|
||||
NetAPI_AdrToString,
|
||||
NetAPI_CompareAdr,
|
||||
(void *)NET_StringToAdr,
|
||||
Info_ValueForKey,
|
||||
NetAPI_StringToAdr,
|
||||
NetAPI_ValueForKey,
|
||||
NetAPI_RemoveKey,
|
||||
NetAPI_SetValueForKey,
|
||||
};
|
||||
|
||||
@@ -1324,21 +1324,10 @@ static int pfnIsCvarReadOnly( const char *name )
|
||||
return FBitSet( cv->flags, FCVAR_READ_ONLY ) ? 1 : 0;
|
||||
}
|
||||
|
||||
static int GAME_EXPORT pfnUtfProcessChar( int in )
|
||||
{
|
||||
// compatibility export, deprecated, do not use
|
||||
|
||||
if( !cls.accept_utf8 ) // incoming character is not a UTF-8 sequence
|
||||
return in;
|
||||
|
||||
// otherwise, decode it and convert to selected codepage
|
||||
return Con_UtfProcessCharForce( in );
|
||||
}
|
||||
|
||||
static ui_extendedfuncs_t gExtendedfuncs =
|
||||
{
|
||||
pfnEnableTextInput,
|
||||
pfnUtfProcessChar,
|
||||
Con_UtfProcessChar,
|
||||
Con_UtfMoveLeft,
|
||||
Con_UtfMoveRight,
|
||||
pfnGetRenderers,
|
||||
|
||||
@@ -68,7 +68,7 @@ CVAR_DEFINE_AUTO( hud_scale_minimal_width, "640", FCVAR_ARCHIVE|FCVAR_LATCH, "if
|
||||
CVAR_DEFINE_AUTO( cl_solid_players, "1", 0, "Make all players not solid (can't traceline them)" );
|
||||
CVAR_DEFINE_AUTO( cl_updaterate, "20", FCVAR_USERINFO|FCVAR_ARCHIVE, "refresh rate of server messages" );
|
||||
CVAR_DEFINE_AUTO( cl_showevents, "0", FCVAR_ARCHIVE, "show events playback" );
|
||||
CVAR_DEFINE_AUTO( cl_cmdrate, "30", FCVAR_ARCHIVE, "Max number of command packets sent to server per second" );
|
||||
CVAR_DEFINE_AUTO( cl_cmdrate, "60", FCVAR_ARCHIVE, "Max number of command packets sent to server per second" );
|
||||
CVAR_DEFINE( cl_interp, "ex_interp", "0.1", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "Interpolate object positions starting this many seconds in past" );
|
||||
CVAR_DEFINE_AUTO( cl_nointerp, "0", 0, "disable interpolation of entities and players" );
|
||||
static CVAR_DEFINE_AUTO( cl_dlmax, "0", FCVAR_USERINFO|FCVAR_ARCHIVE, "max allowed outcoming fragment size" );
|
||||
@@ -76,7 +76,6 @@ static CVAR_DEFINE_AUTO( cl_upmax, "1200", FCVAR_ARCHIVE, "max allowed incoming
|
||||
|
||||
CVAR_DEFINE_AUTO( cl_lw, "1", FCVAR_ARCHIVE|FCVAR_USERINFO, "enable client weapon predicting" );
|
||||
CVAR_DEFINE_AUTO( cl_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_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)" );
|
||||
@@ -94,10 +93,11 @@ static CVAR_DEFINE_AUTO( name, username, FCVAR_USERINFO|FCVAR_ARCHIVE|FCVAR_PRIN
|
||||
static CVAR_DEFINE_AUTO( model, "", FCVAR_USERINFO|FCVAR_ARCHIVE|FCVAR_FILTERABLE, "player model ('player' is a singleplayer model)" );
|
||||
static CVAR_DEFINE_AUTO( topcolor, "0", FCVAR_USERINFO|FCVAR_ARCHIVE|FCVAR_FILTERABLE, "player top color" );
|
||||
static CVAR_DEFINE_AUTO( bottomcolor, "0", FCVAR_USERINFO|FCVAR_ARCHIVE|FCVAR_FILTERABLE, "player bottom color" );
|
||||
CVAR_DEFINE_AUTO( rate, "25000", FCVAR_USERINFO|FCVAR_ARCHIVE|FCVAR_FILTERABLE, "player network rate" );
|
||||
CVAR_DEFINE_AUTO( rate, "3500", FCVAR_USERINFO|FCVAR_ARCHIVE|FCVAR_FILTERABLE, "player network rate" );
|
||||
|
||||
static CVAR_DEFINE_AUTO( cl_ticket_generator, "revemu2013", FCVAR_ARCHIVE, "you wouldn't steal a car" );
|
||||
|
||||
|
||||
client_t cl;
|
||||
client_static_t cls;
|
||||
clgame_static_t clgame;
|
||||
@@ -717,20 +717,11 @@ static void CL_WritePacket( void )
|
||||
int numbackup, maxbackup, maxcmds;
|
||||
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
|
||||
if( cls.demoplayback || cls.state < ca_connected || cls.state == ca_cinematic )
|
||||
return;
|
||||
|
||||
if( cls.state < min_state )
|
||||
if( cls.state <= ca_connected )
|
||||
{
|
||||
Netchan_TransmitBits( &cls.netchan, 0, "" );
|
||||
return;
|
||||
@@ -1008,7 +999,7 @@ static void CL_WriteSteamTicket( sizebuf_t *send )
|
||||
const char *s;
|
||||
uint32_t crc;
|
||||
char buf[768] = { 0 }; // setti and steamemu return 768
|
||||
int i = sizeof( buf );
|
||||
size_t i = sizeof( buf );
|
||||
|
||||
if( !Q_strcmp( cl_ticket_generator.string, "null" ))
|
||||
{
|
||||
@@ -1027,7 +1018,24 @@ static void CL_WriteSteamTicket( sizebuf_t *send )
|
||||
CRC32_Init( &crc );
|
||||
CRC32_ProcessBuffer( &crc, s, Q_strlen( s ));
|
||||
crc = CRC32_Final( crc );
|
||||
i = GenerateRevEmu2013( buf, s, crc );
|
||||
|
||||
if( !Q_stricmp( cl_ticket_generator.string, "revemu2013" ))
|
||||
i = GenerateRevEmu2013( buf, crc );
|
||||
else if( !Q_stricmp( cl_ticket_generator.string, "sc2009" ))
|
||||
i = GenerateSC2009( buf, crc );
|
||||
else if( !Q_stricmp( cl_ticket_generator.string, "oldrevemu" ))
|
||||
i = GenerateOldRevEmu( buf, crc );
|
||||
else if( !Q_stricmp( cl_ticket_generator.string, "steamemu" ))
|
||||
i = GenerateSteamEmu( buf, crc );
|
||||
else if( !Q_stricmp( cl_ticket_generator.string, "revemu" ))
|
||||
i = GenerateRevEmu( buf, crc );
|
||||
else if( !Q_stricmp( cl_ticket_generator.string, "setti" ))
|
||||
i = GenerateSetti( buf );
|
||||
else if( !Q_stricmp( cl_ticket_generator.string, "avsmp" ))
|
||||
i = GenerateAVSMP( buf, crc, true );
|
||||
else
|
||||
Con_Printf( "%s: unknown generator %s, supported are: null, revemu2003, sc2009, oldrevemu, steamemu, revemu, setti, avsmp\n", __func__, cl_ticket_generator.string );
|
||||
|
||||
MSG_WriteBytes( send, buf, i );
|
||||
}
|
||||
|
||||
@@ -1045,7 +1053,6 @@ static void CL_SendConnectPacket( connprotocol_t proto, int challenge )
|
||||
const char *key = ID_GetMD5();
|
||||
netadr_t adr = { 0 };
|
||||
int input_devices;
|
||||
netadrtype_t adrtype;
|
||||
|
||||
protinfo[0] = 0;
|
||||
|
||||
@@ -1056,16 +1063,14 @@ static void CL_SendConnectPacket( connprotocol_t proto, int challenge )
|
||||
return;
|
||||
}
|
||||
|
||||
adrtype = NET_NetadrType( &adr );
|
||||
|
||||
if( adr.port == 0 ) adr.port = MSG_BigShort( PORT_SERVER );
|
||||
|
||||
input_devices = IN_CollectInputDevices();
|
||||
IN_LockInputDevices( adrtype != NA_LOOPBACK ? true : false );
|
||||
IN_LockInputDevices( adr.type != NA_LOOPBACK ? true : false );
|
||||
|
||||
// GoldSrc doesn't need sv_cheats set to 0, it's handled by svc_goldsrc_sendextrainfo
|
||||
// it also doesn't need useragent string
|
||||
if( adrtype != NA_LOOPBACK && proto != PROTO_GOLDSRC )
|
||||
if( adr.type != NA_LOOPBACK && proto != PROTO_GOLDSRC )
|
||||
{
|
||||
Cvar_SetCheatState();
|
||||
Cvar_FullSet( "sv_cheats", "0", FCVAR_READ_ONLY | FCVAR_SERVER );
|
||||
@@ -1165,11 +1170,7 @@ Returns bandwidth test fragment size
|
||||
*/
|
||||
static int CL_GetTestFragmentSize( void )
|
||||
{
|
||||
// const int fragmentSizes[CL_TEST_RETRIES] = { 64000, 32000, 10666, 5200, 1400 };
|
||||
|
||||
// it turns out, even if we pass the bandwidth test, it doesn't mean we can use such large fragments
|
||||
// as a temporary solution, use smaller fragment sizes
|
||||
const int fragmentSizes[CL_TEST_RETRIES] = { 1400, 1200, 1000, 800, 508 };
|
||||
const int fragmentSizes[CL_TEST_RETRIES] = { 64000, 32000, 10666, 5200, 1400 };
|
||||
if( cls.connect_retry >= 0 && cls.connect_retry < CL_TEST_RETRIES )
|
||||
return bound( FRAGMENT_MIN_SIZE, fragmentSizes[cls.connect_retry], FRAGMENT_MAX_SIZE );
|
||||
else
|
||||
@@ -1207,7 +1208,7 @@ static void CL_CheckForResend( void )
|
||||
cls.signon = 0;
|
||||
cls.state = ca_connecting;
|
||||
Q_strncpy( cls.servername, "localhost", sizeof( cls.servername ));
|
||||
NET_NetadrSetType( &cls.serveradr, NA_LOOPBACK );
|
||||
cls.serveradr.type = NA_LOOPBACK;
|
||||
cls.legacymode = PROTO_CURRENT;
|
||||
|
||||
// we don't need a challenge on the localhost
|
||||
@@ -1543,8 +1544,8 @@ static void CL_SendDisconnectMessage( connprotocol_t proto )
|
||||
MSG_WriteString( &buf, "dropclient\n" );
|
||||
else MSG_WriteString( &buf, "disconnect" );
|
||||
|
||||
if( NET_NetadrType( &cls.netchan.remote_address ) == NA_UNDEFINED )
|
||||
NET_NetadrSetType( &cls.netchan.remote_address, NA_LOOPBACK );
|
||||
if( !cls.netchan.remote_address.type )
|
||||
cls.netchan.remote_address.type = NA_LOOPBACK;
|
||||
|
||||
// make sure message will be delivered
|
||||
Netchan_TransmitBits( &cls.netchan, MSG_GetNumBitsWritten( &buf ), MSG_GetData( &buf ));
|
||||
@@ -1587,9 +1588,6 @@ void CL_SetupNetchanForProtocol( connprotocol_t proto )
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if( !Host_IsLocalClient( ))
|
||||
SetBits( flags, NETCHAN_USE_LZSS );
|
||||
|
||||
cls.extensions = Q_atoi( Info_ValueForKey( Cmd_Argv( 1 ), "ext" ));
|
||||
|
||||
if( FBitSet( cls.extensions, NET_EXT_SPLITSIZE ))
|
||||
@@ -1713,17 +1711,19 @@ CL_LocalServers_f
|
||||
*/
|
||||
static void CL_LocalServers_f( void )
|
||||
{
|
||||
netadr_t adr = { 0 };
|
||||
netadr_t adr;
|
||||
|
||||
memset( &adr, 0, sizeof( adr ));
|
||||
|
||||
Con_Printf( "Scanning for servers on the local network area...\n" );
|
||||
NET_Config( true, true ); // allow remote
|
||||
|
||||
// send a broadcast packet
|
||||
NET_NetadrSetType( &adr, NA_BROADCAST );
|
||||
adr.type = NA_BROADCAST;
|
||||
adr.port = MSG_BigShort( PORT_SERVER );
|
||||
Netchan_OutOfBandPrint( NS_CLIENT, adr, A2A_INFO" %i", PROTOCOL_VERSION );
|
||||
|
||||
NET_NetadrSetType( &adr, NA_MULTICAST_IP6 );
|
||||
adr.type = NA_MULTICAST_IP6;
|
||||
Netchan_OutOfBandPrint( NS_CLIENT, adr, A2A_INFO" %i", PROTOCOL_VERSION );
|
||||
}
|
||||
|
||||
@@ -2467,18 +2467,18 @@ static void CL_ServerList( netadr_t from, sizebuf_t *msg )
|
||||
while( MSG_GetNumBitsLeft( msg ) > 8 )
|
||||
{
|
||||
uint8_t addr[16];
|
||||
netadr_t servadr = { 0 };
|
||||
netadr_t servadr;
|
||||
|
||||
if( NET_NetadrType( &from ) == NA_IP6 ) // IPv6 master server only sends IPv6 addresses
|
||||
if( from.type6 == NA_IP6 ) // IPv6 master server only sends IPv6 addresses
|
||||
{
|
||||
MSG_ReadBytes( msg, addr, sizeof( addr ));
|
||||
NET_IP6BytesToNetadr( &servadr, addr );
|
||||
NET_NetadrSetType( &servadr, NA_IP6 );
|
||||
servadr.type6 = NA_IP6;
|
||||
}
|
||||
else
|
||||
{
|
||||
MSG_ReadBytes( msg, servadr.ip, sizeof( servadr.ip )); // 4 bytes for IP
|
||||
NET_NetadrSetType( &servadr, NA_IP );
|
||||
servadr.type = NA_IP;
|
||||
}
|
||||
servadr.port = MSG_ReadShort( msg ); // 2 bytes for Port
|
||||
|
||||
@@ -3126,9 +3126,6 @@ static qboolean CL_ShouldRescanFilesystem( void )
|
||||
}
|
||||
}
|
||||
|
||||
if( FBitSet( fs_mount_lv.flags|fs_mount_hd.flags|fs_mount_addon.flags|fs_mount_l10n.flags|ui_language.flags, FCVAR_CHANGED ))
|
||||
retval = true;
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
@@ -3138,7 +3135,7 @@ qboolean CL_PrecacheResources( void )
|
||||
|
||||
// if we downloaded new WAD files or any other archives they must be added to searchpath
|
||||
if( CL_ShouldRescanFilesystem( ))
|
||||
FS_Rescan_f();
|
||||
g_fsapi.Rescan();
|
||||
|
||||
// NOTE: world need to be loaded as first model
|
||||
for( pRes = cl.resourcesonhand.pNext; pRes && pRes != &cl.resourcesonhand; pRes = pRes->pNext )
|
||||
@@ -3384,7 +3381,6 @@ static void CL_InitLocal( void )
|
||||
|
||||
Cvar_RegisterVariable( &rcon_address );
|
||||
|
||||
Cvar_RegisterVariable( &cl_trace_consistency );
|
||||
Cvar_RegisterVariable( &cl_trace_stufftext );
|
||||
Cvar_RegisterVariable( &cl_trace_messages );
|
||||
Cvar_RegisterVariable( &cl_trace_events );
|
||||
@@ -3479,8 +3475,6 @@ static void CL_InitLocal( void )
|
||||
Cmd_AddCommand ("fullserverinfo", CL_FullServerinfo_f, "sent by server when serverinfo changes" );
|
||||
Cmd_AddCommand ("upload", CL_BeginUpload_f, "uploading file to the server" );
|
||||
|
||||
Cmd_AddRestrictedCommand( "replaybufferdat", CL_ReplayBufferDat_f, "development and debugging tool" );
|
||||
|
||||
Cmd_AddRestrictedCommand ("quit", CL_Quit_f, "quit from game" );
|
||||
Cmd_AddRestrictedCommand ("exit", CL_Quit_f, "quit from game" );
|
||||
|
||||
@@ -3658,8 +3652,6 @@ void CL_Init( void )
|
||||
if( !CL_LoadProgs( libpath ))
|
||||
Host_Error( "can't initialize %s: %s\n", libpath, COM_GetLibraryError( ));
|
||||
|
||||
ID_Init();
|
||||
|
||||
cls.build_num = 0;
|
||||
cls.initialized = true;
|
||||
cl.maxclients = 1; // allow to drawing player in menu
|
||||
|
||||
@@ -19,7 +19,6 @@ GNU General Public License for more details.
|
||||
#include "library.h"
|
||||
#include "input.h"
|
||||
#include "platform/platform.h"
|
||||
#include "utflib.h"
|
||||
|
||||
static CVAR_DEFINE_AUTO( vibration_length, "1.0", FCVAR_ARCHIVE | FCVAR_PRIVILEGED, "vibration length" );
|
||||
static CVAR_DEFINE_AUTO( vibration_enable, "1", FCVAR_ARCHIVE | FCVAR_PRIVILEGED, "enable vibration" );
|
||||
@@ -59,13 +58,7 @@ static int pfnDrawScaledCharacter( int x, int y, int number, int r, int g, int b
|
||||
int flags = FONT_DRAW_HUD;
|
||||
|
||||
if( hud_utf8.value )
|
||||
{
|
||||
static utfstate_t utfstate;
|
||||
number = Q_DecodeUTF8( &utfstate, number );
|
||||
|
||||
if( !number )
|
||||
return 0;
|
||||
}
|
||||
SetBits( flags, FONT_DRAW_UTF8 );
|
||||
|
||||
if( fabs( g_font_scale - scale ) > 0.1f ||
|
||||
g_scaled_font.hFontTexture != cls.creditsFont.hFontTexture )
|
||||
@@ -99,11 +92,6 @@ static char *pfnParseFileSafe( char *data, char *buf, const int size, unsigned i
|
||||
return COM_ParseFileSafe( data, buf, size, flags, len, NULL );
|
||||
}
|
||||
|
||||
static void GAME_EXPORT pfnSetCustomClientID( const char *id )
|
||||
{
|
||||
// deprecated
|
||||
}
|
||||
|
||||
static const mobile_engfuncs_t gMobileEngfuncs =
|
||||
{
|
||||
MOBILITY_API_VERSION,
|
||||
@@ -118,7 +106,7 @@ static const mobile_engfuncs_t gMobileEngfuncs =
|
||||
pfnDrawScaledCharacter,
|
||||
Sys_Warn,
|
||||
Sys_GetNativeObject,
|
||||
pfnSetCustomClientID,
|
||||
ID_SetCustomClientID,
|
||||
pfnParseFileSafe
|
||||
};
|
||||
|
||||
|
||||
@@ -1614,23 +1614,6 @@ void CL_UpdateUserPings( sizebuf_t *msg )
|
||||
}
|
||||
}
|
||||
|
||||
static const char *CL_CheckTypeToString( int check_type )
|
||||
{
|
||||
// renamed so they have same width and look better in console output
|
||||
switch( check_type )
|
||||
{
|
||||
case force_exactfile:
|
||||
return "exactfile";
|
||||
case force_model_samebounds:
|
||||
return "samebounds";
|
||||
case force_model_specifybounds:
|
||||
return "specbounds";
|
||||
case force_model_specifybounds_if_avail:
|
||||
return "specbounds2";
|
||||
}
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
static void CL_SendConsistencyInfo( sizebuf_t *msg, connprotocol_t proto )
|
||||
{
|
||||
qboolean user_changed_diskfile;
|
||||
@@ -1896,9 +1879,6 @@ static void CL_ParseConsistencyInfo( sizebuf_t *msg, connprotocol_t proto )
|
||||
return;
|
||||
}
|
||||
|
||||
if( cl_trace_consistency.value )
|
||||
Con_Printf( "Server wants consistency of the following resources:\n" );
|
||||
|
||||
skip_crc_change = NULL;
|
||||
lastcheck = 0;
|
||||
|
||||
@@ -1930,7 +1910,7 @@ static void CL_ParseConsistencyInfo( sizebuf_t *msg, connprotocol_t proto )
|
||||
pc = &cl.consistency_list[cl.num_consistency];
|
||||
cl.num_consistency++;
|
||||
|
||||
memset( pc, 0, sizeof( *pc ));
|
||||
memset( pc, 0, sizeof( consistency_t ));
|
||||
pc->filename = pResource->szFileName;
|
||||
pc->issound = (pResource->type == t_sound);
|
||||
pc->orig_index = delta;
|
||||
@@ -1943,9 +1923,6 @@ static void CL_ParseConsistencyInfo( sizebuf_t *msg, connprotocol_t proto )
|
||||
pc->check_type = pResource->rguc_reserved[0];
|
||||
}
|
||||
|
||||
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;
|
||||
lastcheck = delta;
|
||||
}
|
||||
|
||||
@@ -83,10 +83,7 @@ static void CL_ParseNewMovevars( sizebuf_t *msg )
|
||||
R_SetupSky( clgame.movevars.skyName );
|
||||
|
||||
clgame.oldmovevars = clgame.movevars;
|
||||
|
||||
// FIXME: set world wave height when entities will be allocated
|
||||
if( clgame.entities )
|
||||
clgame.entities->curstate.scale = clgame.movevars.waveHeight;
|
||||
clgame.entities->curstate.scale = clgame.movevars.waveHeight;
|
||||
|
||||
// keep features an actual!
|
||||
clgame.oldmovevars.features = clgame.movevars.features = host.features;
|
||||
@@ -94,11 +91,11 @@ static void CL_ParseNewMovevars( sizebuf_t *msg )
|
||||
|
||||
typedef struct delta_header_t
|
||||
{
|
||||
qboolean remove;
|
||||
qboolean custom;
|
||||
qboolean instanced;
|
||||
uint16_t instanced_baseline_index;
|
||||
uint16_t offset;
|
||||
qboolean remove : 1;
|
||||
qboolean custom : 1;
|
||||
qboolean instanced : 1;
|
||||
uint instanced_baseline_index : 6;
|
||||
uint offset : 6;
|
||||
} delta_header_t;
|
||||
|
||||
static int CL_ParseDeltaHeader( sizebuf_t *msg, qboolean delta, int oldnum, struct delta_header_t *hdr )
|
||||
@@ -163,47 +160,33 @@ static int CL_GetEntityDelta( const struct delta_header_t *hdr, int entnum )
|
||||
return DT_ENTITY_STATE_T;
|
||||
}
|
||||
|
||||
static int CL_FlushEntityPacketGS( frame_t *frame, sizebuf_t *msg )
|
||||
static void CL_FlushEntityPacketGS( frame_t *frame, sizebuf_t *msg )
|
||||
{
|
||||
int playerbytes = 0, numbase = 0;
|
||||
|
||||
frame->valid = false;
|
||||
cl.validsequence = 0; // can't render a frame
|
||||
|
||||
// read it all but ignore it
|
||||
while( 1 )
|
||||
{
|
||||
int newnum, bufstart;
|
||||
int num = 0;
|
||||
entity_state_t from = { 0 }, to;
|
||||
delta_header_t hdr;
|
||||
qboolean player;
|
||||
|
||||
if( MSG_ReadWord( msg ) != 0 )
|
||||
{
|
||||
MSG_SeekToBit( msg, -16, SEEK_CUR );
|
||||
numbase = newnum = CL_ParseDeltaHeader( msg, true, numbase, &hdr );
|
||||
num = CL_ParseDeltaHeader( msg, false, num, &hdr );
|
||||
}
|
||||
else break;
|
||||
|
||||
if( MSG_CheckOverflow( msg ))
|
||||
Host_Error( "%s: overflow\n", __func__ );
|
||||
|
||||
player = CL_IsPlayerIndex( newnum );
|
||||
bufstart = MSG_GetNumBytesRead( msg );
|
||||
|
||||
if( hdr.remove )
|
||||
continue;
|
||||
|
||||
Delta_ReadGSFields( msg, CL_GetEntityDelta( &hdr, newnum ), &from, &to, cl.mtime[0] );
|
||||
|
||||
if( player )
|
||||
playerbytes += MSG_GetNumBytesRead( msg ) - bufstart;
|
||||
Delta_ReadGSFields( msg, CL_GetEntityDelta( &hdr, num ), &from, &to, cl.mtime[0] );
|
||||
}
|
||||
|
||||
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 )
|
||||
@@ -220,7 +203,7 @@ static void CL_DeltaEntityGS( const delta_header_t *hdr, sizebuf_t *msg, frame_t
|
||||
if(( newnum < 0 ) || ( newnum >= clgame.maxEntities ))
|
||||
{
|
||||
Con_DPrintf( S_ERROR "CL_DeltaEntity: invalid newnum: %d\n", newnum );
|
||||
Host_Error( "%s: bad delta entity number: %i\n", __func__, newnum );
|
||||
Host_Error( "%s: bad delta entity number: %i", __func__, newnum );
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -284,7 +267,7 @@ static void CL_CopyPacketEntity( frame_t *frame, int num, const entity_state_t *
|
||||
static int CL_ParsePacketEntitiesGS( sizebuf_t *msg, qboolean delta )
|
||||
{
|
||||
frame_t *frame, *oldframe;
|
||||
int oldindex, oldnum, numbase = 0;
|
||||
int oldindex, newnum, oldnum, numbase = 0;
|
||||
entity_state_t *oldent;
|
||||
int count;
|
||||
int playerbytes = 0;
|
||||
@@ -331,7 +314,7 @@ static int CL_ParsePacketEntitiesGS( sizebuf_t *msg, qboolean delta )
|
||||
// read it all but ignore it
|
||||
while( 1 )
|
||||
{
|
||||
int bufstart, newnum;
|
||||
int bufstart;
|
||||
qboolean player;
|
||||
delta_header_t hdr;
|
||||
int val = MSG_ReadWord( msg );
|
||||
|
||||
@@ -233,11 +233,6 @@ static intptr_t pfnRenderGetParm( int parm, int arg )
|
||||
return CL_RenderGetParm( parm, arg, true );
|
||||
}
|
||||
|
||||
static void pfnAVI_StreamSound( void *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 =
|
||||
{
|
||||
pfnRenderGetParm, // GL_RenderGetParm,
|
||||
@@ -270,7 +265,7 @@ static render_api_t gRenderAPI =
|
||||
NULL, // R_UploadStretchRaw,
|
||||
(void*)AVI_FreeVideo,
|
||||
(void*)AVI_IsActive,
|
||||
(void*)pfnAVI_StreamSound,
|
||||
S_StreamAviSamples,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL, // GL_Bind,
|
||||
|
||||
@@ -2429,7 +2429,7 @@ void CL_SetLightstyle( int style, const char *s, float f )
|
||||
|
||||
if( unlikely( style < 0 || style >= MAX_LIGHTSTYLES ))
|
||||
{
|
||||
Con_Printf( S_WARN "%s: ignored invalid lightstyle id %d\n", __func__, style );
|
||||
Con_Printf( S_WARN "%s: ignored invalid lightstyle id %d\n", style );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -326,12 +326,8 @@ typedef struct
|
||||
pfnEventHook func; // user-defined function
|
||||
} cl_user_event_t;
|
||||
|
||||
enum
|
||||
{
|
||||
FONT_FIXED,
|
||||
FONT_VARIABLE,
|
||||
FONT_TRUETYPE
|
||||
};
|
||||
#define FONT_FIXED 0
|
||||
#define FONT_VARIABLE 1
|
||||
|
||||
#define FONT_DRAW_HUD BIT( 0 ) // pass to drawing function to apply hud_scale
|
||||
#define FONT_DRAW_UTF8 BIT( 1 ) // call UtfProcessChar
|
||||
@@ -692,7 +688,6 @@ extern convar_t r_showtextures;
|
||||
extern convar_t cl_bmodelinterp;
|
||||
extern convar_t cl_lw; // local weapons
|
||||
extern convar_t cl_charset;
|
||||
extern convar_t cl_trace_consistency;
|
||||
extern convar_t cl_trace_stufftext;
|
||||
extern convar_t cl_trace_messages;
|
||||
extern convar_t cl_trace_events;
|
||||
@@ -741,7 +736,6 @@ void CL_ClearResourceLists( void );
|
||||
//
|
||||
// cl_debug.c
|
||||
//
|
||||
void CL_ReplayBufferDat_f( void );
|
||||
void CL_Parse_Debug( qboolean enable );
|
||||
void CL_Parse_RecordCommand( int cmd, int startoffset );
|
||||
void CL_ResetFrame( frame_t *frame );
|
||||
@@ -773,7 +767,7 @@ void CL_StartupDemoHeader( void );
|
||||
void CL_DrawDemoRecording( void );
|
||||
void CL_WriteDemoUserCmd( int cmdnumber );
|
||||
void CL_WriteDemoMessage( qboolean startup, int start, sizebuf_t *msg );
|
||||
void CL_WriteDemoUserMessage( int size, byte *buffer );
|
||||
void CL_WriteDemoUserMessage( const byte *buffer, size_t size );
|
||||
qboolean CL_DemoReadMessage( byte *buffer, size_t *length );
|
||||
void CL_DemoInterpolateAngles( void );
|
||||
void CL_CheckStartupDemos( void );
|
||||
@@ -811,12 +805,11 @@ qboolean Con_LoadFixedWidthFont( const char *fontname, cl_font_t *font, float sc
|
||||
qboolean Con_LoadVariableWidthFont( const char *fontname, cl_font_t *font, float scale, convar_t *rendermode, uint texFlags );
|
||||
void CL_FreeFont( cl_font_t *font );
|
||||
void CL_SetFontRendermode( cl_font_t *font );
|
||||
int CL_DrawCharacter( float x, float y, uint32_t uc, const rgba_t color, const cl_font_t *font, int flags );
|
||||
void CL_DrawCharacterLen( const cl_font_t *font, uint32_t uc, int *width, int *height );
|
||||
|
||||
int CL_DrawString( float x, float y, const char *s, const rgba_t color, const cl_font_t *font, int flags );
|
||||
int CL_DrawStringf( const cl_font_t *font, float x, float y, const rgba_t color, int flags, const char *fmt, ... ) FORMAT_CHECK( 6 );
|
||||
void CL_DrawStringLen( const cl_font_t *font, const char *s, int *width, int *height, int flags );
|
||||
int CL_DrawCharacter( float x, float y, int number, rgba_t color, cl_font_t *font, int flags );
|
||||
int CL_DrawString( float x, float y, const char *s, rgba_t color, cl_font_t *font, int flags );
|
||||
void CL_DrawCharacterLen( cl_font_t *font, int number, int *width, int *height );
|
||||
void CL_DrawStringLen( cl_font_t *font, const char *s, int *width, int *height, int flags );
|
||||
int CL_DrawStringf( cl_font_t *font, float x, float y, rgba_t color, int flags, const char *fmt, ... ) FORMAT_CHECK( 6 );
|
||||
|
||||
|
||||
//
|
||||
@@ -849,21 +842,19 @@ void CL_EnableScissor( scissor_state_t *scissor, int x, int y, int width, int he
|
||||
void CL_DisableScissor( scissor_state_t *scissor );
|
||||
qboolean CL_Scissor( const scissor_state_t *scissor, float *x, float *y, float *width, float *height, float *u0, float *v0, float *u1, float *v1 );
|
||||
|
||||
static inline cl_entity_t *CL_EDICT_NUM( int index )
|
||||
static inline cl_entity_t *CL_EDICT_NUM( int n )
|
||||
{
|
||||
if( !clgame.entities ) // not in game yet
|
||||
if( !clgame.entities )
|
||||
{
|
||||
Host_Error( "%s: clgame.entities is NULL\n", __func__ );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if( index < 0 || index >= clgame.maxEntities )
|
||||
{
|
||||
Host_Error( "%s: bad number %i\n", __func__, index );
|
||||
return NULL;
|
||||
}
|
||||
if(( n >= 0 ) && ( n < clgame.maxEntities ))
|
||||
return clgame.entities + n;
|
||||
|
||||
return clgame.entities + index;
|
||||
Host_Error( "%s: bad number %i\n", __func__, n );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline cl_entity_t *CL_GetEntityByIndex( int index )
|
||||
@@ -874,7 +865,10 @@ static inline cl_entity_t *CL_GetEntityByIndex( int index )
|
||||
if( index < 0 || index >= clgame.maxEntities )
|
||||
return NULL;
|
||||
|
||||
return clgame.entities + index;
|
||||
if( index == 0 )
|
||||
return clgame.entities;
|
||||
|
||||
return CL_EDICT_NUM( index );
|
||||
}
|
||||
|
||||
static inline model_t *CL_ModelHandle( int modelindex )
|
||||
@@ -884,7 +878,7 @@ static inline model_t *CL_ModelHandle( int modelindex )
|
||||
|
||||
static inline qboolean CL_IsThirdPerson( void )
|
||||
{
|
||||
return clgame.dllFuncs.CL_IsThirdPerson();
|
||||
return clgame.dllFuncs.CL_IsThirdPerson() ? true : false;
|
||||
}
|
||||
|
||||
static inline cl_entity_t *CL_GetLocalPlayer( void )
|
||||
@@ -1095,7 +1089,6 @@ void CL_ReadLineFile_f( void );
|
||||
// console.c
|
||||
//
|
||||
extern convar_t con_fontsize;
|
||||
extern int g_codepage;
|
||||
int Con_Visible( void );
|
||||
qboolean Con_FixedFont( void );
|
||||
void Con_VidInit( void );
|
||||
@@ -1106,13 +1099,14 @@ void Con_DrawDebug( void );
|
||||
void Con_RunConsole( void );
|
||||
void Con_DrawConsole( void );
|
||||
void Con_DrawVersion( void );
|
||||
int Con_UtfProcessChar( int in );
|
||||
int Con_UtfProcessCharForce( int in );
|
||||
int Con_UtfMoveLeft( char *str, int pos );
|
||||
int Con_UtfMoveRight( char *str, int pos, int length );
|
||||
void Con_DefaultColor( int r, int g, int b, qboolean gameui );
|
||||
cl_font_t *Con_GetCurFont( void );
|
||||
cl_font_t *Con_GetFont( int num );
|
||||
int Con_DrawString( int x, int y, const char *string, const rgba_t setColor ); // legacy, use cl_font.c
|
||||
int Con_DrawString( int x, int y, const char *string, rgba_t setColor ); // legacy, use cl_font.c
|
||||
void GAME_EXPORT Con_DrawStringLen( const char *pText, int *length, int *height ); // legacy, use cl_font.c
|
||||
void Con_CharEvent( int key );
|
||||
void Key_Console( int key );
|
||||
@@ -1125,7 +1119,7 @@ void Con_PageUp( int lines );
|
||||
//
|
||||
// s_main.c
|
||||
//
|
||||
typedef int sound_t;
|
||||
void S_StreamAviSamples( void *Avi, int entnum, float fvol, float attn, float synctime );
|
||||
void S_StartBackgroundTrack( const char *intro, const char *loop, int position, qboolean fullpath );
|
||||
void S_StopBackgroundTrack( void );
|
||||
void S_StreamSetPause( int pause );
|
||||
@@ -1214,12 +1208,6 @@ void Key_EnableTextInput( qboolean enable, qboolean force );
|
||||
int Key_ToUpper( int key );
|
||||
void OSK_Draw( void );
|
||||
|
||||
//
|
||||
// identification.c
|
||||
//
|
||||
void ID_Init( void );
|
||||
const char *ID_GetMD5( void );
|
||||
|
||||
extern rgba_t g_color_table[8];
|
||||
extern triangleapi_t gTriApi;
|
||||
extern net_api_t gNetApi;
|
||||
|
||||
@@ -34,7 +34,7 @@ static CVAR_DEFINE_AUTO( con_color, "240 180 24", FCVAR_ARCHIVE, "set a custom c
|
||||
static CVAR_DEFINE_AUTO( scr_drawversion, "1", FCVAR_ARCHIVE, "draw version in menu or screenshots, doesn't affect console" );
|
||||
static CVAR_DEFINE_AUTO( con_oldfont, "0", 0, "use legacy font from gfx.wad, might be missing or broken" );
|
||||
|
||||
int g_codepage = 0;
|
||||
static int g_codepage = 0;
|
||||
|
||||
static qboolean g_messagemode_privileged = true;
|
||||
|
||||
@@ -622,7 +622,7 @@ int Con_UtfProcessCharForce( int in )
|
||||
// TODO: get rid of global state where possible
|
||||
static utfstate_t state = { 0 };
|
||||
|
||||
uint32_t ch = Q_DecodeUTF8( &state, in );
|
||||
int ch = Q_DecodeUTF8( &state, in );
|
||||
|
||||
if( g_codepage == 1251 )
|
||||
return Q_UnicodeToCP1251( ch );
|
||||
@@ -632,6 +632,15 @@ int Con_UtfProcessCharForce( int in )
|
||||
return '?'; // not implemented yet
|
||||
}
|
||||
|
||||
int GAME_EXPORT Con_UtfProcessChar( int in )
|
||||
{
|
||||
if( !cls.accept_utf8 ) // incoming character is not a UTF-8 sequence
|
||||
return in;
|
||||
|
||||
// otherwise, decode it and convert to selected codepage
|
||||
return Con_UtfProcessCharForce( in );
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
Con_UtfMoveLeft
|
||||
@@ -750,7 +759,7 @@ Con_DrawString
|
||||
client version of routine
|
||||
====================
|
||||
*/
|
||||
int Con_DrawString( int x, int y, const char *string, const rgba_t setColor )
|
||||
int Con_DrawString( int x, int y, const char *string, rgba_t setColor )
|
||||
{
|
||||
return CL_DrawString( x, y, string, setColor, con.curFont, FONT_DRAW_UTF8 );
|
||||
}
|
||||
@@ -834,14 +843,11 @@ If no console is visible, the notify window will pop up.
|
||||
*/
|
||||
void Con_Print( const char *txt )
|
||||
{
|
||||
static qboolean cr_pending = false;
|
||||
static qboolean colorstring = false;
|
||||
static char buf[MAX_PRINT_MSG];
|
||||
static int lastlength = 0;
|
||||
static int bufpos = 0;
|
||||
static int charpos = 0;
|
||||
|
||||
qboolean norefresh = false;
|
||||
static int cr_pending = 0;
|
||||
static char buf[MAX_PRINT_MSG];
|
||||
qboolean norefresh = false;
|
||||
static int lastlength = 0;
|
||||
static int bufpos = 0;
|
||||
int c, mask = 0;
|
||||
|
||||
// client not running
|
||||
@@ -867,7 +873,7 @@ void Con_Print( const char *txt )
|
||||
if( cr_pending )
|
||||
{
|
||||
Con_DeleteLastLine();
|
||||
cr_pending = false;
|
||||
cr_pending = 0;
|
||||
}
|
||||
c = *txt;
|
||||
|
||||
@@ -880,42 +886,23 @@ void Con_Print( const char *txt )
|
||||
{
|
||||
Con_AddLine( buf, bufpos, true );
|
||||
lastlength = CON_LINES_LAST().length;
|
||||
cr_pending = true;
|
||||
cr_pending = 1;
|
||||
bufpos = 0;
|
||||
charpos = 0;
|
||||
}
|
||||
break;
|
||||
case '\n':
|
||||
Con_AddLine( buf, bufpos, true );
|
||||
lastlength = CON_LINES_LAST().length;
|
||||
bufpos = 0;
|
||||
charpos = 0;
|
||||
break;
|
||||
default:
|
||||
|
||||
buf[bufpos++] = c | mask;
|
||||
|
||||
if( IsColorString( txt ))
|
||||
{
|
||||
// first color string character
|
||||
colorstring = true;
|
||||
}
|
||||
else if( colorstring )
|
||||
{
|
||||
// second color string character
|
||||
colorstring = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// not a color string, move char counter
|
||||
charpos++;
|
||||
}
|
||||
|
||||
if(( bufpos >= sizeof( buf ) - 1 ) || charpos >= ( con.linewidth - 1 ))
|
||||
if(( bufpos >= sizeof( buf ) - 1 ) || bufpos >= ( con.linewidth - 1 ))
|
||||
{
|
||||
Con_AddLine( buf, bufpos, true );
|
||||
lastlength = CON_LINES_LAST().length;
|
||||
bufpos = 0;
|
||||
charpos = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -931,7 +918,6 @@ void Con_Print( const char *txt )
|
||||
Con_AddLine( buf, bufpos, lastlength != 0 );
|
||||
lastlength = 0;
|
||||
bufpos = 0;
|
||||
charpos = 0;
|
||||
}
|
||||
|
||||
// pump messages to avoid window hanging
|
||||
@@ -1258,16 +1244,45 @@ static void Field_CharEvent( field_t *edit, int ch )
|
||||
Field_DrawInputLine
|
||||
==================
|
||||
*/
|
||||
static void Field_DrawInputLine( int x, int y, const field_t *edit )
|
||||
static void Field_DrawInputLine( int x, int y, field_t *edit )
|
||||
{
|
||||
int curPos;
|
||||
char str[MAX_SYSPATH];
|
||||
const byte *colorDefault = g_color_table[ColorIndex( COLOR_DEFAULT )];
|
||||
const int prestep = bound( 0, edit->scroll, sizeof( edit->buffer ) - 1 );
|
||||
const int drawLen = bound( 0, edit->widthInChars, sizeof( str ));
|
||||
const int cursorCharPos = bound( 0, edit->cursor - prestep, sizeof( str ));
|
||||
int len, cursorChar;
|
||||
int drawLen;
|
||||
int prestep, curPos;
|
||||
char str[MAX_SYSPATH];
|
||||
byte *colorDefault;
|
||||
|
||||
Q_strncpy( str, edit->buffer + prestep, drawLen );
|
||||
drawLen = edit->widthInChars;
|
||||
len = Q_strlen( edit->buffer ) + 1;
|
||||
colorDefault = g_color_table[ColorIndex( COLOR_DEFAULT )];
|
||||
|
||||
// guarantee that cursor will be visible
|
||||
if( len <= drawLen )
|
||||
{
|
||||
prestep = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( edit->scroll + drawLen > len )
|
||||
{
|
||||
edit->scroll = len - drawLen;
|
||||
if( edit->scroll < 0 ) edit->scroll = 0;
|
||||
}
|
||||
|
||||
prestep = edit->scroll;
|
||||
}
|
||||
|
||||
if( prestep + drawLen > len )
|
||||
drawLen = len - prestep;
|
||||
|
||||
// extract <drawLen> characters from the field at <prestep>
|
||||
drawLen = Q_min( drawLen, MAX_SYSPATH - 1 );
|
||||
|
||||
memcpy( str, edit->buffer + prestep, drawLen );
|
||||
str[drawLen] = 0;
|
||||
|
||||
// save char for overstrike
|
||||
cursorChar = str[edit->cursor - prestep];
|
||||
|
||||
// draw it
|
||||
CL_DrawString( x, y, str, colorDefault, con.curFont, FONT_DRAW_UTF8 );
|
||||
@@ -1276,7 +1291,7 @@ static void Field_DrawInputLine( int x, int y, const field_t *edit )
|
||||
if((int)( host.realtime * 4 ) & 1 ) return; // off blink
|
||||
|
||||
// calc cursor position
|
||||
str[cursorCharPos] = 0;
|
||||
str[edit->cursor - prestep] = 0;
|
||||
CL_DrawStringLen( con.curFont, str, &curPos, NULL, FONT_DRAW_UTF8 );
|
||||
|
||||
if( host.key_overstrike )
|
||||
@@ -1452,16 +1467,6 @@ Handles history and console scrollback
|
||||
*/
|
||||
void Key_Console( int key )
|
||||
{
|
||||
// exit the console by pressing MINUS on NSwitch
|
||||
// or both Back(Select)/Start buttons for everyone else
|
||||
if( key == K_BACK_BUTTON || key == K_START_BUTTON || key == K_ESCAPE )
|
||||
{
|
||||
if( cls.state == ca_active && !cl.background )
|
||||
Key_SetKeyDest( key_game );
|
||||
else UI_SetActiveMenu( true );
|
||||
return;
|
||||
}
|
||||
|
||||
// ctrl-L clears screen
|
||||
if( key == 'l' && Key_IsDown( K_CTRL ))
|
||||
{
|
||||
@@ -1570,6 +1575,16 @@ void Key_Console( int key )
|
||||
return;
|
||||
}
|
||||
|
||||
// exit the console by pressing MINUS on NSwitch
|
||||
// or both Back(Select)/Start buttons for everyone else
|
||||
if( key == K_BACK_BUTTON || key == K_START_BUTTON )
|
||||
{
|
||||
if( cls.state == ca_active && !cl.background )
|
||||
Key_SetKeyDest( key_game );
|
||||
else UI_SetActiveMenu( true );
|
||||
return;
|
||||
}
|
||||
|
||||
// pass to the normal editline routine
|
||||
Field_KeyDownEvent( &con.input, key );
|
||||
}
|
||||
@@ -1993,7 +2008,7 @@ void Con_DrawVersion( void )
|
||||
int start, height = refState.height;
|
||||
string curbuild;
|
||||
|
||||
if( !scr_drawversion.value )
|
||||
if( !scr_drawversion.value || CL_IsDevOverviewMode() == 2 || net_graph.value )
|
||||
return;
|
||||
|
||||
if( cls.key_dest == key_menu )
|
||||
@@ -2005,9 +2020,6 @@ void Con_DrawVersion( void )
|
||||
{
|
||||
qboolean draw_version;
|
||||
|
||||
if( CL_IsDevOverviewMode() == 2 || net_graph.value )
|
||||
return;
|
||||
|
||||
draw_version = cls.scrshot_action == scrshot_normal
|
||||
|| cls.scrshot_action == scrshot_snapshot
|
||||
|| host.force_draw_version_time > host.realtime;
|
||||
@@ -2080,7 +2092,10 @@ void Con_RunConsole( void )
|
||||
}
|
||||
else
|
||||
{
|
||||
g_codepage = 0;
|
||||
Con_Printf( S_WARN "Unknown charset %s, defaulting to cp1252", con_charset.string );
|
||||
|
||||
Cvar_DirectSet( &con_charset, "cp1252" );
|
||||
g_codepage = 1252;
|
||||
}
|
||||
|
||||
cls.accept_utf8 = !Q_stricmp( cl_charset.string, "utf-8" );
|
||||
|
||||
@@ -43,6 +43,7 @@ static struct joy_axis_s
|
||||
short val;
|
||||
short prevval;
|
||||
} joyaxis[MAX_AXES] = { 0 };
|
||||
static byte currentbinding; // add posibility to remap keys, to place it in joykeys[]
|
||||
static qboolean joy_initialized;
|
||||
|
||||
static CVAR_DEFINE_AUTO( joy_pitch, "100.0", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "joystick pitch sensitivity" );
|
||||
@@ -59,9 +60,9 @@ static CVAR_DEFINE_AUTO( joy_pitch_deadzone, DEFAULT_JOY_DEADZONE, FCVAR_ARCHIVE
|
||||
static CVAR_DEFINE_AUTO( joy_yaw_deadzone, DEFAULT_JOY_DEADZONE, FCVAR_ARCHIVE | FCVAR_FILTERABLE, "yaw axis deadzone. Value from 0 to 32767" );
|
||||
static CVAR_DEFINE_AUTO( joy_axis_binding, "sfpyrl", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "axis hardware id to engine inner axis binding, "
|
||||
"s - side, f - forward, y - yaw, p - pitch, r - left trigger, l - right trigger" );
|
||||
static CVAR_DEFINE_AUTO( joy_found, "0", FCVAR_READ_ONLY, "is joystick is connected" );
|
||||
static CVAR_DEFINE_AUTO( joy_index, "0", FCVAR_READ_ONLY, "current active joystick" );
|
||||
CVAR_DEFINE_AUTO( joy_enable, "1", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "enable joystick" );
|
||||
static CVAR_DEFINE_AUTO( joy_have_gyro, "0", FCVAR_READ_ONLY, "tells whether current active gamepad has gyroscope or not" );
|
||||
static CVAR_DEFINE_AUTO( joy_calibrated, "0", FCVAR_READ_ONLY, "tells whether current active gamepad gyroscope has been calibrated or not" );
|
||||
|
||||
/*
|
||||
============
|
||||
@@ -70,30 +71,7 @@ Joy_IsActive
|
||||
*/
|
||||
qboolean Joy_IsActive( void )
|
||||
{
|
||||
return joy_enable.value;
|
||||
}
|
||||
|
||||
/*
|
||||
===========
|
||||
Joy_SetCapabilities
|
||||
===========
|
||||
*/
|
||||
void Joy_SetCapabilities( qboolean have_gyro )
|
||||
{
|
||||
Cvar_FullSet( joy_have_gyro.name, have_gyro ? "1" : "0", joy_have_gyro.flags );
|
||||
}
|
||||
|
||||
/*
|
||||
===========
|
||||
Joy_SetCalibrationState
|
||||
===========
|
||||
*/
|
||||
void Joy_SetCalibrationState( joy_calibration_state_t state )
|
||||
{
|
||||
if( (int)joy_calibrated.value == state )
|
||||
return;
|
||||
|
||||
Cvar_FullSet( joy_calibrated.name, va( "%d", state ), joy_calibrated.flags );
|
||||
return joy_found.value && joy_enable.value;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -103,7 +81,7 @@ Joy_HatMotionEvent
|
||||
DPad events
|
||||
============
|
||||
*/
|
||||
static void Joy_HatMotionEvent( int value )
|
||||
void Joy_HatMotionEvent( byte hat, byte value )
|
||||
{
|
||||
struct
|
||||
{
|
||||
@@ -118,6 +96,9 @@ static void Joy_HatMotionEvent( int value )
|
||||
};
|
||||
int i;
|
||||
|
||||
if( !joy_found.value )
|
||||
return;
|
||||
|
||||
for( i = 0; i < ARRAYSIZE( keys ); i++ )
|
||||
{
|
||||
if( value & keys[i].mask )
|
||||
@@ -244,7 +225,7 @@ static void Joy_ProcessStick( const engineAxis_t engineAxis, short value )
|
||||
val |= Joy_GetHatValueForAxis( JOY_AXIS_SIDE );
|
||||
val |= Joy_GetHatValueForAxis( JOY_AXIS_FWD );
|
||||
|
||||
Joy_HatMotionEvent( val );
|
||||
Joy_HatMotionEvent( 0, val );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -255,9 +236,23 @@ Joy_AxisMotionEvent
|
||||
Axis events
|
||||
=============
|
||||
*/
|
||||
void Joy_AxisMotionEvent( engineAxis_t engineAxis, short value )
|
||||
void Joy_AxisMotionEvent( byte axis, short value )
|
||||
{
|
||||
if( engineAxis >= JOY_AXIS_NULL )
|
||||
if( !joy_found.value )
|
||||
return;
|
||||
|
||||
if( axis >= MAX_AXES )
|
||||
{
|
||||
Con_Reportf( "Only 6 axes is supported\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
Joy_KnownAxisMotionEvent( joyaxesmap[axis], value );
|
||||
}
|
||||
|
||||
void Joy_KnownAxisMotionEvent( engineAxis_t engineAxis, short value )
|
||||
{
|
||||
if( engineAxis == JOY_AXIS_NULL )
|
||||
return;
|
||||
|
||||
if( value == joyaxis[engineAxis].val )
|
||||
@@ -271,14 +266,66 @@ void Joy_AxisMotionEvent( engineAxis_t engineAxis, short value )
|
||||
|
||||
/*
|
||||
=============
|
||||
Joy_GyroEvent
|
||||
Joy_BallMotionEvent
|
||||
|
||||
Gyroscope events
|
||||
Trackball events. UNDONE
|
||||
=============
|
||||
*/
|
||||
void Joy_GyroEvent( vec3_t data )
|
||||
void Joy_BallMotionEvent( byte ball, short xrel, short yrel )
|
||||
{
|
||||
//if( !joy_found.value )
|
||||
// return;
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
Joy_ButtonEvent
|
||||
|
||||
Button events
|
||||
=============
|
||||
*/
|
||||
void Joy_ButtonEvent( byte button, byte down )
|
||||
{
|
||||
if( !joy_found.value )
|
||||
return;
|
||||
|
||||
// generic game button code.
|
||||
if( button > 32 )
|
||||
{
|
||||
int origbutton = button;
|
||||
button = ( button & 31 ) + K_AUX1;
|
||||
|
||||
Con_Reportf( "Only 32 joybuttons is supported, converting %i button ID to %s\n", origbutton, Key_KeynumToString( button ) );
|
||||
}
|
||||
else button += K_AUX1;
|
||||
|
||||
Key_Event( button, down );
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
Joy_RemoveEvent
|
||||
|
||||
Called when joystick is removed. For future expansion
|
||||
=============
|
||||
*/
|
||||
void Joy_RemoveEvent( void )
|
||||
{
|
||||
if( joy_found.value )
|
||||
Cvar_FullSet( "joy_found", "0", FCVAR_READ_ONLY );
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
Joy_RemoveEvent
|
||||
|
||||
Called when joystick is removed. For future expansion
|
||||
=============
|
||||
*/
|
||||
void Joy_AddEvent( void )
|
||||
{
|
||||
if( joy_enable.value && !joy_found.value )
|
||||
Cvar_FullSet( "joy_found", "1", FCVAR_READ_ONLY );
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -317,19 +364,14 @@ void Joy_FinalizeMove( float *fw, float *side, float *dpitch, float *dyaw )
|
||||
|
||||
*fw -= joy_forward.value * (float)joyaxis[JOY_AXIS_FWD ].val/(float)SHRT_MAX; // must be form -1.0 to 1.0
|
||||
*side += joy_side.value * (float)joyaxis[JOY_AXIS_SIDE].val/(float)SHRT_MAX;
|
||||
#if !defined(XASH_SDL)
|
||||
*dpitch += joy_pitch.value * (float)joyaxis[JOY_AXIS_PITCH].val/(float)SHRT_MAX * host.realframetime; // abs axis rotate is frametime related
|
||||
*dyaw -= joy_yaw.value * (float)joyaxis[JOY_AXIS_YAW ].val/(float)SHRT_MAX * host.realframetime;
|
||||
#else
|
||||
// HACKHACK: SDL have inverted look axis.
|
||||
*dpitch -= joy_pitch.value * (float)joyaxis[JOY_AXIS_PITCH].val/(float)SHRT_MAX * host.realframetime;
|
||||
*dyaw += joy_yaw.value * (float)joyaxis[JOY_AXIS_YAW ].val/(float)SHRT_MAX * host.realframetime;
|
||||
}
|
||||
|
||||
static void Joy_CalibrateGyro_f( void )
|
||||
{
|
||||
if( !joy_have_gyro.value )
|
||||
{
|
||||
Con_Printf( "Current active gamepad doesn't have gyroscope\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
Platform_CalibrateGamepadGyro();
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -341,8 +383,6 @@ Main init procedure
|
||||
*/
|
||||
void Joy_Init( void )
|
||||
{
|
||||
Cmd_AddRestrictedCommand( "joy_calibrate_gyro", Joy_CalibrateGyro_f, "calibrate gamepad gyroscope. You must to put gamepad on stationary surface" );
|
||||
|
||||
Cvar_RegisterVariable( &joy_pitch );
|
||||
Cvar_RegisterVariable( &joy_yaw );
|
||||
Cvar_RegisterVariable( &joy_side );
|
||||
@@ -362,9 +402,11 @@ void Joy_Init( void )
|
||||
Cvar_RegisterVariable( &joy_yaw_deadzone );
|
||||
|
||||
Cvar_RegisterVariable( &joy_axis_binding );
|
||||
Cvar_RegisterVariable( &joy_found );
|
||||
// we doesn't loaded config.cfg yet, so this cvar is not archive.
|
||||
// change by +set joy_index in cmdline
|
||||
Cvar_RegisterVariable( &joy_index );
|
||||
|
||||
Cvar_RegisterVariable( &joy_have_gyro );
|
||||
Cvar_RegisterVariable( &joy_calibrated );
|
||||
Cvar_RegisterVariable( &joy_enable );
|
||||
|
||||
// renamed from -nojoy to -noenginejoy to not conflict with
|
||||
@@ -375,7 +417,7 @@ void Joy_Init( void )
|
||||
return;
|
||||
}
|
||||
|
||||
Platform_JoyInit();
|
||||
Cvar_FullSet( "joy_found", va( "%d", Platform_JoyInit( joy_index.value )), FCVAR_READ_ONLY );
|
||||
|
||||
joy_initialized = true;
|
||||
}
|
||||
@@ -389,5 +431,8 @@ Shutdown joystick code
|
||||
*/
|
||||
void Joy_Shutdown( void )
|
||||
{
|
||||
Platform_JoyShutdown();
|
||||
if( joy_initialized )
|
||||
{
|
||||
Cvar_FullSet( "joy_found", 0, FCVAR_READ_ONLY );
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -205,10 +205,9 @@ void IN_ToggleClientMouse( int newstate, int oldstate )
|
||||
}
|
||||
}
|
||||
|
||||
void IN_SetRelativeMouseMode( qboolean set )
|
||||
static void IN_SetRelativeMouseMode( qboolean set, qboolean verbose )
|
||||
{
|
||||
static qboolean s_bRawInput;
|
||||
qboolean verbose = m_grab_debug.value ? true : false;
|
||||
|
||||
if( set && !s_bRawInput )
|
||||
{
|
||||
@@ -232,10 +231,9 @@ void IN_SetRelativeMouseMode( qboolean set )
|
||||
}
|
||||
}
|
||||
|
||||
void IN_SetMouseGrab( qboolean set )
|
||||
static void IN_SetMouseGrab( qboolean set, qboolean verbose )
|
||||
{
|
||||
static qboolean s_bMouseGrab;
|
||||
qboolean verbose = m_grab_debug.value ? true : false;
|
||||
|
||||
if( set && !s_bMouseGrab )
|
||||
{
|
||||
@@ -260,7 +258,7 @@ void IN_SetMouseGrab( qboolean set )
|
||||
|
||||
static void IN_CheckMouseState( qboolean active )
|
||||
{
|
||||
qboolean use_raw_input;
|
||||
qboolean use_raw_input, verbose;
|
||||
|
||||
#if XASH_WIN32
|
||||
use_raw_input = ( m_rawinput.value && clgame.client_dll_uses_sdl ) || clgame.dllFuncs.pfnLookEvent != NULL;
|
||||
@@ -268,18 +266,20 @@ static void IN_CheckMouseState( qboolean active )
|
||||
use_raw_input = true; // always use SDL code
|
||||
#endif
|
||||
|
||||
verbose = m_grab_debug.value ? true : false;
|
||||
|
||||
if( m_ignore.value )
|
||||
active = false;
|
||||
|
||||
if( active && use_raw_input && !host.mouse_visible && cls.state == ca_active )
|
||||
IN_SetRelativeMouseMode( true );
|
||||
IN_SetRelativeMouseMode( true, verbose );
|
||||
else
|
||||
IN_SetRelativeMouseMode( false );
|
||||
IN_SetRelativeMouseMode( false, verbose );
|
||||
|
||||
if( active && !host.mouse_visible && cls.state == ca_active )
|
||||
IN_SetMouseGrab( true );
|
||||
IN_SetMouseGrab( true, verbose );
|
||||
else
|
||||
IN_SetMouseGrab( false );
|
||||
IN_SetMouseGrab( false, verbose );
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -332,7 +332,7 @@ static void IN_MouseMove( void )
|
||||
if( !in_mouseinitialized )
|
||||
return;
|
||||
|
||||
if( Touch_WantVisibleCursor( ))
|
||||
if( Touch_Emulated( ))
|
||||
{
|
||||
// touch emulation overrides all input
|
||||
Touch_KeyEvent( 0, 0 );
|
||||
@@ -363,7 +363,7 @@ void IN_MouseEvent( int key, int down )
|
||||
else ClearBits( in_mstate, BIT( key ));
|
||||
|
||||
// touch emulation overrides all input
|
||||
if( Touch_WantVisibleCursor( ))
|
||||
if( Touch_Emulated( ))
|
||||
{
|
||||
Touch_KeyEvent( K_MOUSE1 + key, down );
|
||||
}
|
||||
|
||||
@@ -46,9 +46,6 @@ uint IN_CollectInputDevices( void );
|
||||
void IN_LockInputDevices( qboolean lock );
|
||||
void IN_EngineAppendMove( float frametime, usercmd_t *cmd, qboolean active );
|
||||
|
||||
void IN_SetRelativeMouseMode( qboolean set );
|
||||
void IN_SetMouseGrab( qboolean set );
|
||||
|
||||
extern convar_t m_yaw;
|
||||
extern convar_t m_pitch;
|
||||
//
|
||||
@@ -77,6 +74,7 @@ void Touch_ResetDefaultButtons( void );
|
||||
int IN_TouchEvent( touchEventType type, int fingerID, float x, float y, float dx, float dy );
|
||||
void Touch_KeyEvent( int key, int down );
|
||||
qboolean Touch_WantVisibleCursor( void );
|
||||
qboolean Touch_Emulated( void );
|
||||
void Touch_NotifyResize( void );
|
||||
|
||||
//
|
||||
@@ -106,21 +104,18 @@ typedef enum engineAxis_e
|
||||
JOY_AXIS_NULL
|
||||
} engineAxis_t;
|
||||
|
||||
typedef enum joy_calibration_state_s
|
||||
{
|
||||
JOY_NOT_CALIBRATED = 0,
|
||||
JOY_CALIBRATING,
|
||||
JOY_FAILED_TO_CALIBRATE,
|
||||
JOY_CALIBRATED
|
||||
} joy_calibration_state_t;
|
||||
|
||||
qboolean Joy_IsActive( void );
|
||||
void Joy_SetCapabilities( qboolean have_gyro );
|
||||
void Joy_SetCalibrationState( joy_calibration_state_t state );
|
||||
void Joy_AxisMotionEvent( engineAxis_t engineAxis, short value );
|
||||
void Joy_GyroEvent( vec3_t data );
|
||||
void Joy_HatMotionEvent( byte hat, byte value );
|
||||
void Joy_AxisMotionEvent( byte axis, short value );
|
||||
void Joy_KnownAxisMotionEvent( engineAxis_t engineAxis, short value );
|
||||
void Joy_BallMotionEvent( byte ball, short xrel, short yrel );
|
||||
void Joy_ButtonEvent( byte button, byte down );
|
||||
void Joy_AddEvent( void );
|
||||
void Joy_RemoveEvent( void );
|
||||
void Joy_FinalizeMove( float *fw, float *side, float *dpitch, float *dyaw );
|
||||
void Joy_Init( void );
|
||||
void Joy_Shutdown( void );
|
||||
void Joy_EnableTextInput(qboolean enable, qboolean force);
|
||||
|
||||
|
||||
#endif//INPUT_H
|
||||
|
||||
@@ -51,7 +51,7 @@ static const keyname_t keynames[] =
|
||||
{"CTRL", K_CTRL, "+attack" },
|
||||
{"SHIFT", K_SHIFT, "+speed" },
|
||||
{"CAPSLOCK", K_CAPSLOCK, "" },
|
||||
{"SCROLLOCK", K_SCROLLLOCK, "" },
|
||||
{"SCROLLOCK", K_SCROLLOCK, "" },
|
||||
{"F1", K_F1, "cmd help" },
|
||||
{"F2", K_F2, "menu_savegame" },
|
||||
{"F3", K_F3, "menu_loadgame" },
|
||||
@@ -215,7 +215,7 @@ const char *Key_KeynumToString( int keynum )
|
||||
return "<OUT OF RANGE>";
|
||||
|
||||
// check for printable ascii (don't use quote)
|
||||
if( keynum > 32 && keynum < 127 && keynum != '"' && keynum != ';' && keynum != K_SCROLLLOCK )
|
||||
if( keynum > 32 && keynum < 127 && keynum != '"' && keynum != ';' && keynum != K_SCROLLOCK )
|
||||
{
|
||||
tinystr[0] = keynum;
|
||||
tinystr[1] = 0;
|
||||
@@ -726,8 +726,18 @@ void GAME_EXPORT Key_Event( int key, int down )
|
||||
return; // handled in client.dll
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
case key_message:
|
||||
Key_Message( key );
|
||||
return;
|
||||
case key_console:
|
||||
if( cls.state == ca_active && !cl.background )
|
||||
Key_SetKeyDest( key_game );
|
||||
else UI_SetActiveMenu( true );
|
||||
return;
|
||||
case key_menu:
|
||||
UI_KeyEvent( key, true );
|
||||
return;
|
||||
default: return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -851,9 +861,7 @@ void GAME_EXPORT Key_ClearStates( void )
|
||||
|
||||
for( i = 0; i < 256; i++ )
|
||||
{
|
||||
if( i >= K_MOUSE1 && i <= K_MOUSE5 )
|
||||
IN_MouseEvent( i - K_MOUSE1, false );
|
||||
else
|
||||
if( keys[i].down && i < K_MOUSE1 && i > K_MOUSE5 )
|
||||
Key_Event( i, false );
|
||||
|
||||
keys[i].down = 0;
|
||||
@@ -861,6 +869,9 @@ void GAME_EXPORT Key_ClearStates( void )
|
||||
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 )
|
||||
clgame.dllFuncs.IN_ClearStates();
|
||||
}
|
||||
@@ -957,7 +968,6 @@ enum
|
||||
OSK_ENTER,
|
||||
OSK_SPECKEY_LAST
|
||||
};
|
||||
|
||||
static const char *osk_keylayout[][4] =
|
||||
{
|
||||
{
|
||||
@@ -974,7 +984,7 @@ static const char *osk_keylayout[][4] =
|
||||
}
|
||||
};
|
||||
|
||||
static struct osk_s
|
||||
struct osk_s
|
||||
{
|
||||
qboolean enable;
|
||||
int curlayout;
|
||||
@@ -1008,6 +1018,7 @@ static qboolean OSK_KeyEvent( int key, int down )
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
switch ( key )
|
||||
{
|
||||
case K_ENTER:
|
||||
@@ -1050,6 +1061,10 @@ static qboolean OSK_KeyEvent( int key, int down )
|
||||
|
||||
ch = (byte)osk.curbutton.val;
|
||||
|
||||
// do not pass UTF-8 sequence into the engine, convert it here
|
||||
if( !cls.accept_utf8 )
|
||||
ch = Con_UtfProcessCharForce( ch );
|
||||
|
||||
if( !ch )
|
||||
break;
|
||||
|
||||
@@ -1093,7 +1108,7 @@ static qboolean OSK_KeyEvent( int key, int down )
|
||||
|
||||
/*
|
||||
=============
|
||||
OSK_EnableTextInput
|
||||
Joy_EnableTextInput
|
||||
|
||||
Enables built-in IME
|
||||
=============
|
||||
@@ -1184,15 +1199,13 @@ void OSK_Draw( void )
|
||||
X_STEP * MAX_OSK_ROWS * refState.width,
|
||||
Y_STEP * MAX_OSK_LINES * refState.height, 100, 100, 100, 100 );
|
||||
|
||||
OSK_DrawSpecialButton( "-]", X_START, Y_START + Y_STEP * 2, X_STEP, Y_STEP );
|
||||
OSK_DrawSpecialButton( "<-", X_START + X_STEP * 12, Y_START + Y_STEP * 2, X_STEP, Y_STEP );
|
||||
OSK_DrawSpecialButton( "-]", X_START, Y_START + Y_STEP * 2, X_STEP, Y_STEP );
|
||||
OSK_DrawSpecialButton( "<-", X_START + X_STEP * 12, Y_START + Y_STEP * 2, X_STEP, Y_STEP );
|
||||
|
||||
OSK_DrawSpecialButton( "sh", X_START, Y_START + Y_STEP * 3, X_STEP, Y_STEP );
|
||||
OSK_DrawSpecialButton( "en", X_START + X_STEP * 12, Y_START + Y_STEP * 3, X_STEP, Y_STEP );
|
||||
|
||||
for( y = Y_START, j = 0; j < MAX_OSK_LINES; j++, y += Y_STEP )
|
||||
{
|
||||
for( y = Y_START, j = 0; j < MAX_OSK_LINES; j++, y += Y_STEP )
|
||||
for( x = X_START, i = 0; i < MAX_OSK_ROWS; i++, x += X_STEP )
|
||||
OSK_DrawSymbolButton( curlayout[j][i], x, y, X_STEP, Y_STEP );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -312,7 +312,7 @@ static int DLY_Init( int idelay, float delay )
|
||||
|
||||
cur = &rgsxdly[idelay];
|
||||
cur->cdelaysamplesmax = ((int)(delay * idsp_dma_speed) << sxhires) + 1;
|
||||
cur->lpdelayline = (int *)Mem_Calloc( sndpool, cur->cdelaysamplesmax * sizeof( int ));
|
||||
cur->lpdelayline = (int *)Z_Calloc( cur->cdelaysamplesmax * sizeof( int ));
|
||||
cur->xfade = 0;
|
||||
|
||||
// init modulation
|
||||
|
||||
@@ -107,18 +107,17 @@ S_CreateDefaultSound
|
||||
*/
|
||||
static wavdata_t *S_CreateDefaultSound( void )
|
||||
{
|
||||
wavdata_t *sc;
|
||||
uint samples = SOUND_DMA_SPEED;
|
||||
uint channels = 1;
|
||||
uint width = 2;
|
||||
size_t size = samples * width * channels;
|
||||
wavdata_t *sc;
|
||||
|
||||
sc = Mem_Calloc( sndpool, sizeof( wavdata_t ) + size );
|
||||
sc->width = width;
|
||||
sc->channels = channels;
|
||||
sc = Mem_Calloc( sndpool, sizeof( wavdata_t ));
|
||||
|
||||
sc->width = 2;
|
||||
sc->channels = 1;
|
||||
sc->loopStart = 0;
|
||||
sc->rate = SOUND_DMA_SPEED;
|
||||
sc->samples = samples;
|
||||
sc->size = size;
|
||||
sc->samples = SOUND_DMA_SPEED;
|
||||
sc->size = sc->samples * sc->width * sc->channels;
|
||||
sc->buffer = Mem_Calloc( sndpool, sc->size );
|
||||
|
||||
return sc;
|
||||
}
|
||||
|
||||
@@ -1207,6 +1207,86 @@ void S_RawSamples( uint samples, uint rate, word width, word channels, const byt
|
||||
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
|
||||
@@ -1874,15 +1954,14 @@ qboolean S_Init( void )
|
||||
Cmd_AddCommand( "spk", S_SayReliable_f, "reliable play a specified sententce" );
|
||||
Cmd_AddCommand( "speak", S_Say_f, "playing a specified sententce" );
|
||||
|
||||
sndpool = Mem_AllocPool( "Sound Zone" );
|
||||
dma.backendName = "None";
|
||||
if( !SNDDMA_Init( ))
|
||||
if( !SNDDMA_Init( ) )
|
||||
{
|
||||
Con_Printf( "Audio: sound system can't be initialized\n" );
|
||||
Mem_FreePool( &sndpool );
|
||||
return false;
|
||||
}
|
||||
|
||||
sndpool = Mem_AllocPool( "Sound Zone" );
|
||||
soundtime = 0;
|
||||
paintedtime = 0;
|
||||
|
||||
|
||||
@@ -16,7 +16,6 @@ GNU General Public License for more details.
|
||||
#include "common.h"
|
||||
#include "sound.h"
|
||||
#include "client.h"
|
||||
#include "soundlib.h"
|
||||
|
||||
static bg_track_t s_bgTrack;
|
||||
static musicfade_t musicfade; // controlled by game dlls
|
||||
@@ -213,7 +212,7 @@ void S_StreamBackgroundTrack( void )
|
||||
|
||||
while( ch->s_rawend < soundtime + ch->max_samples )
|
||||
{
|
||||
const stream_t *info = s_bgTrack.stream;
|
||||
wavdata_t *info = FS_StreamInfo( s_bgTrack.stream );
|
||||
|
||||
bufferSamples = ch->max_samples - (ch->s_rawend - soundtime);
|
||||
|
||||
|
||||
@@ -557,7 +557,7 @@ static void VOX_ReadSentenceFile_( byte *buf, fs_offset_t size )
|
||||
int index = cszrawsentences;
|
||||
int size = strlen( name ) + strlen( value ) + 2;
|
||||
|
||||
rgpszrawsentence[index] = Mem_Malloc( sndpool, size );
|
||||
rgpszrawsentence[index] = Mem_Malloc( host.mempool, size );
|
||||
memcpy( rgpszrawsentence[index], name, size );
|
||||
rgpszrawsentence[index][size - 1] = 0;
|
||||
cszrawsentences++;
|
||||
|
||||
@@ -114,6 +114,7 @@ typedef struct rawchan_s
|
||||
vec3_t origin; // only use if fixed_origin is set
|
||||
volatile uint s_rawend;
|
||||
float oldtime; // catch time jumps
|
||||
wavdata_t sound_info; // advance play position
|
||||
size_t max_samples; // buffer length
|
||||
portable_samplepair_t rawsamples[]; // variable sized
|
||||
} rawchan_t;
|
||||
@@ -170,8 +171,6 @@ typedef struct
|
||||
int source; // may be game, menu, etc
|
||||
} bg_track_t;
|
||||
|
||||
typedef int sound_t;
|
||||
|
||||
//====================================================================
|
||||
|
||||
#define MAX_DYNAMIC_CHANNELS (60 + NUM_AMBIENTS)
|
||||
|
||||
@@ -29,20 +29,17 @@ static void Sound_Reset( void )
|
||||
|
||||
static MALLOC_LIKE( FS_FreeSound, 1 ) wavdata_t *SoundPack( void )
|
||||
{
|
||||
wavdata_t *pack = Mem_Malloc( host.soundpool, sizeof( *pack ) + sound.size );
|
||||
wavdata_t *pack = Mem_Calloc( host.soundpool, sizeof( wavdata_t ));
|
||||
|
||||
pack->buffer = sound.wav;
|
||||
pack->width = sound.width;
|
||||
pack->rate = sound.rate;
|
||||
pack->type = sound.type;
|
||||
pack->size = sound.size;
|
||||
pack->loopStart = sound.loopstart;
|
||||
pack->samples = sound.samples;
|
||||
pack->type = sound.type;
|
||||
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;
|
||||
pack->flags = sound.flags;
|
||||
|
||||
return pack;
|
||||
}
|
||||
@@ -135,6 +132,7 @@ free WAV buffer
|
||||
void FS_FreeSound( wavdata_t *pack )
|
||||
{
|
||||
if( !pack ) return;
|
||||
if( pack->buffer ) Mem_Free( pack->buffer );
|
||||
Mem_Free( pack );
|
||||
}
|
||||
|
||||
@@ -201,6 +199,33 @@ stream_t *FS_OpenStream( const char *filename )
|
||||
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
|
||||
|
||||
@@ -17,7 +17,7 @@ GNU General Public License for more details.
|
||||
#include "base_cmd.h"
|
||||
#include "cdll_int.h"
|
||||
|
||||
#define HASH_SIZE 64 // 64 * 4 * 4 == 1024 bytes
|
||||
#define HASH_SIZE 128 // 128 * 4 * 4 == 2048 bytes
|
||||
|
||||
typedef struct base_command_hashmap_s base_command_hashmap_t;
|
||||
|
||||
@@ -26,11 +26,10 @@ struct base_command_hashmap_s
|
||||
base_command_t *basecmd; // base command: cvar, alias or command
|
||||
base_command_hashmap_t *next;
|
||||
base_command_type_e type; // type for faster searching
|
||||
char name[]; // key for searching
|
||||
char name[1]; // key for searching
|
||||
};
|
||||
|
||||
static base_command_hashmap_t *hashed_cmds[HASH_SIZE];
|
||||
static poolhandle_t basecmd_pool;
|
||||
|
||||
#define BaseCmd_HashKey( x ) COM_HashKey( name, HASH_SIZE )
|
||||
|
||||
@@ -43,27 +42,11 @@ Find base command in bucket
|
||||
*/
|
||||
static base_command_hashmap_t *BaseCmd_FindInBucket( base_command_hashmap_t *bucket, base_command_type_e type, const char *name )
|
||||
{
|
||||
base_command_hashmap_t *i;
|
||||
base_command_hashmap_t *i = bucket;
|
||||
for( ; i && ( i->type != type || Q_stricmp( name, i->name ) ); // filter out
|
||||
i = i->next );
|
||||
|
||||
for( i = bucket; i != NULL; i = i->next )
|
||||
{
|
||||
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;
|
||||
return i;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -107,31 +90,27 @@ void BaseCmd_FindAll( const char *name, base_command_t **cmd, base_command_t **a
|
||||
base_command_hashmap_t *base = BaseCmd_GetBucket( name );
|
||||
base_command_hashmap_t *i = base;
|
||||
|
||||
ASSERT( cmd && alias && cvar );
|
||||
|
||||
*cmd = *alias = *cvar = NULL;
|
||||
|
||||
for( ; i; i = i->next )
|
||||
{
|
||||
int cmp = Q_stricmp( i->name, name );
|
||||
|
||||
if( cmp < 0 )
|
||||
continue;
|
||||
|
||||
if( cmp > 0 )
|
||||
break;
|
||||
|
||||
switch( i->type )
|
||||
if( !Q_stricmp( i->name, name ) )
|
||||
{
|
||||
case HM_CMD:
|
||||
*cmd = i->basecmd;
|
||||
break;
|
||||
case HM_CMDALIAS:
|
||||
*alias = i->basecmd;
|
||||
break;
|
||||
case HM_CVAR:
|
||||
*cvar = i->basecmd;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
switch( i->type )
|
||||
{
|
||||
case HM_CMD:
|
||||
*cmd = i->basecmd;
|
||||
break;
|
||||
case HM_CMDALIAS:
|
||||
*alias = i->basecmd;
|
||||
break;
|
||||
case HM_CVAR:
|
||||
*cvar = i->basecmd;
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -149,14 +128,14 @@ void BaseCmd_Insert( base_command_type_e type, base_command_t *basecmd, const ch
|
||||
uint hash = BaseCmd_HashKey( name );
|
||||
size_t len = Q_strlen( name );
|
||||
|
||||
elem = Mem_Malloc( basecmd_pool, sizeof( base_command_hashmap_t ) + len + 1 );
|
||||
elem = Z_Malloc( sizeof( base_command_hashmap_t ) + len );
|
||||
elem->basecmd = basecmd;
|
||||
elem->type = type;
|
||||
Q_strncpy( elem->name, name, len + 1 );
|
||||
|
||||
// link the variable in alphanumerical order
|
||||
for( cur = NULL, find = hashed_cmds[hash];
|
||||
find && Q_stricmp( find->name, elem->name ) < 0;
|
||||
find && Q_strcmp( find->name, elem->name ) < 0;
|
||||
cur = find, find = find->next );
|
||||
|
||||
if( cur ) cur->next = elem;
|
||||
@@ -177,23 +156,9 @@ void BaseCmd_Remove( base_command_type_e type, const char *name )
|
||||
uint hash = BaseCmd_HashKey( name );
|
||||
base_command_hashmap_t *i, *prev;
|
||||
|
||||
for( prev = NULL, i = hashed_cmds[hash]; i != NULL; 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;
|
||||
}
|
||||
for( prev = NULL, i = hashed_cmds[hash]; i &&
|
||||
( Q_strcmp( i->name, name ) || i->type != type); // filter out
|
||||
prev = i, i = i->next );
|
||||
|
||||
if( !i )
|
||||
{
|
||||
@@ -218,15 +183,9 @@ initialize base command hashmap system
|
||||
*/
|
||||
void BaseCmd_Init( void )
|
||||
{
|
||||
basecmd_pool = Mem_AllocPool( "BaseCmd" );
|
||||
memset( hashed_cmds, 0, sizeof( hashed_cmds ) );
|
||||
}
|
||||
|
||||
void BaseCmd_Shutdown( void )
|
||||
{
|
||||
Mem_FreePool( &basecmd_pool );
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
BaseCmd_Stats_f
|
||||
|
||||
@@ -32,7 +32,6 @@ typedef enum base_command_type
|
||||
typedef void base_command_t;
|
||||
|
||||
void BaseCmd_Init( void );
|
||||
void BaseCmd_Shutdown( void );
|
||||
base_command_t *BaseCmd_Find( base_command_type_e type, const char *name );
|
||||
void BaseCmd_FindAll( const char *name,
|
||||
base_command_t **cmd, base_command_t **alias, base_command_t **cvar );
|
||||
|
||||
@@ -46,7 +46,6 @@ static cmdalias_t *cmd_alias;
|
||||
static uint cmd_condition;
|
||||
static int cmd_condlevel;
|
||||
static qboolean cmd_currentCommandIsPrivileged;
|
||||
static poolhandle_t cmd_pool;
|
||||
|
||||
static void Cmd_ExecuteStringWithPrivilegeCheck( const char *text, qboolean isPrivileged );
|
||||
|
||||
@@ -433,7 +432,7 @@ static void Cmd_Alias_f( void )
|
||||
{
|
||||
if( !Q_strcmp( s, a->name ))
|
||||
{
|
||||
Mem_Free( a->value );
|
||||
Z_Free( a->value );
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -442,7 +441,7 @@ static void Cmd_Alias_f( void )
|
||||
{
|
||||
cmdalias_t *cur, *prev;
|
||||
|
||||
a = Mem_Malloc( cmd_pool, sizeof( cmdalias_t ));
|
||||
a = Z_Malloc( sizeof( cmdalias_t ));
|
||||
|
||||
Q_strncpy( a->name, s, sizeof( a->name ));
|
||||
|
||||
@@ -470,7 +469,7 @@ static void Cmd_Alias_f( void )
|
||||
}
|
||||
|
||||
Q_strncat( cmd, "\n", sizeof( cmd ));
|
||||
a->value = copystringpool( cmd_pool, cmd );
|
||||
a->value = copystring( cmd );
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -530,7 +529,7 @@ struct cmd_s
|
||||
char *name;
|
||||
xcommand_t function;
|
||||
int flags;
|
||||
char desc[];
|
||||
char *desc;
|
||||
};
|
||||
|
||||
static int cmd_argc;
|
||||
@@ -637,7 +636,7 @@ void Cmd_TokenizeString( const char *text )
|
||||
|
||||
// clear the args from the last string
|
||||
for( i = 0; i < cmd_argc; i++ )
|
||||
Mem_Free( cmd_argv[i] );
|
||||
Z_Free( cmd_argv[i] );
|
||||
|
||||
cmd_argc = 0; // clear previous args
|
||||
cmd_args = NULL;
|
||||
@@ -671,7 +670,7 @@ void Cmd_TokenizeString( const char *text )
|
||||
|
||||
if( cmd_argc < MAX_CMD_TOKENS )
|
||||
{
|
||||
cmd_argv[cmd_argc] = copystringpool( cmd_pool, cmd_token );
|
||||
cmd_argv[cmd_argc] = copystring( cmd_token );
|
||||
cmd_argc++;
|
||||
}
|
||||
}
|
||||
@@ -684,8 +683,7 @@ Cmd_AddCommandEx
|
||||
*/
|
||||
int Cmd_AddCommandEx( const char *cmd_name, xcommand_t function, const char *cmd_desc, int iFlags, const char *funcname )
|
||||
{
|
||||
cmd_t *cmd, *cur, *prev;
|
||||
size_t desc_len;
|
||||
cmd_t *cmd, *cur, *prev;
|
||||
|
||||
if( !COM_CheckString( cmd_name ))
|
||||
{
|
||||
@@ -709,8 +707,8 @@ int Cmd_AddCommandEx( const char *cmd_name, xcommand_t function, const char *cmd
|
||||
// unfortunately, we lose original command this way
|
||||
if( FBitSet( cmd->flags, CMD_OVERRIDABLE ))
|
||||
{
|
||||
desc_len = Q_strlen( cmd->desc ) + 1;
|
||||
Q_strncpy( cmd->desc, cmd_desc, desc_len );
|
||||
Mem_Free( cmd->desc );
|
||||
cmd->desc = copystring( cmd_desc );
|
||||
cmd->function = function;
|
||||
cmd->flags = iFlags;
|
||||
|
||||
@@ -725,10 +723,9 @@ int Cmd_AddCommandEx( const char *cmd_name, xcommand_t function, const char *cmd
|
||||
}
|
||||
|
||||
// use a small malloc to avoid zone fragmentation
|
||||
desc_len = Q_strlen( cmd_desc ) + 1;
|
||||
cmd = Mem_Malloc( cmd_pool, sizeof( cmd_t ) + desc_len );
|
||||
cmd->name = copystringpool( cmd_pool, cmd_name );
|
||||
Q_strncpy( cmd->desc, cmd_desc, desc_len );
|
||||
cmd = Z_Malloc( sizeof( cmd_t ) );
|
||||
cmd->name = copystring( cmd_name );
|
||||
cmd->desc = copystring( cmd_desc );
|
||||
cmd->function = function;
|
||||
cmd->flags = iFlags;
|
||||
|
||||
@@ -775,6 +772,9 @@ void GAME_EXPORT Cmd_RemoveCommand( const char *cmd_name )
|
||||
if( cmd->name )
|
||||
Mem_Free( cmd->name );
|
||||
|
||||
if( cmd->desc )
|
||||
Mem_Free( cmd->desc );
|
||||
|
||||
Mem_Free( cmd );
|
||||
return;
|
||||
}
|
||||
@@ -1202,6 +1202,7 @@ void Cmd_Unlink( int group )
|
||||
*prev = cmd->next;
|
||||
|
||||
if( cmd->name ) Mem_Free( cmd->name );
|
||||
if( cmd->desc ) Mem_Free( cmd->desc );
|
||||
|
||||
Mem_Free( cmd );
|
||||
count++;
|
||||
@@ -1339,7 +1340,6 @@ Cmd_Init
|
||||
*/
|
||||
void Cmd_Init( void )
|
||||
{
|
||||
cmd_pool = Mem_AllocPool( "Console Commands" );
|
||||
cmd_functions = NULL;
|
||||
cmd_condition = 0;
|
||||
cmd_alias = NULL;
|
||||
@@ -1366,11 +1366,6 @@ void Cmd_Init( void )
|
||||
#endif
|
||||
}
|
||||
|
||||
void Cmd_Shutdown( void )
|
||||
{
|
||||
Mem_FreePool( &cmd_pool );
|
||||
}
|
||||
|
||||
#if XASH_ENGINE_TESTS
|
||||
#include "tests.h"
|
||||
|
||||
|
||||
@@ -76,14 +76,23 @@ XASH SPECIFIC - sort of hack that works only in Xash3D not in GoldSrc
|
||||
|
||||
#define HACKS_RELATED_HLMODS // some HL-mods works differently under Xash and can't be fixed without some hacks at least at current time
|
||||
|
||||
enum dev_level_e
|
||||
enum
|
||||
{
|
||||
DEV_NONE = 0,
|
||||
DEV_NORMAL,
|
||||
DEV_EXTENDED
|
||||
};
|
||||
|
||||
typedef enum instance_e
|
||||
enum
|
||||
{
|
||||
D_INFO = 1, // "-dev 1", shows various system messages
|
||||
D_WARN, // "-dev 2", shows not critical system warnings
|
||||
D_ERROR, // "-dev 3", shows critical warnings
|
||||
D_REPORT, // "-dev 4", special case for game reports
|
||||
D_NOTE // "-dev 5", show system notifications for engine developers
|
||||
};
|
||||
|
||||
typedef enum
|
||||
{
|
||||
HOST_NORMAL, // listen server, singleplayer
|
||||
HOST_DEDICATED,
|
||||
@@ -99,14 +108,14 @@ typedef enum instance_e
|
||||
#include "com_model.h"
|
||||
#include "com_strings.h"
|
||||
#include "crtlib.h"
|
||||
#define FSCALLBACK_OVERRIDE_OPEN
|
||||
#define FSCALLBACK_OVERRIDE_LOADFILE
|
||||
#define FSCALLBACK_OVERRIDE_MALLOC_LIKE
|
||||
#include "fscallback.h"
|
||||
#include "cvar.h"
|
||||
#include "con_nprint.h"
|
||||
#include "crclib.h"
|
||||
#include "ref_api.h"
|
||||
#define FSCALLBACK_OVERRIDE_OPEN
|
||||
#define FSCALLBACK_OVERRIDE_LOADFILE
|
||||
#define FSCALLBACK_OVERRIDE_MALLOC_LIKE
|
||||
#include "fscallback.h"
|
||||
|
||||
// PERFORMANCE INFO
|
||||
#define MIN_FPS 20.0f // host minimum fps value for maxfps.
|
||||
@@ -137,11 +146,6 @@ typedef enum instance_e
|
||||
#define MAX_STATIC_ENTITIES 32 // static entities that moved on the client when level is spawn
|
||||
#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 FORCE_DRAW_VERSION_TIME 5.0 // draw version for 5 seconds
|
||||
@@ -167,11 +171,6 @@ extern convar_t cl_filterstuffcmd;
|
||||
extern convar_t rcon_password;
|
||||
extern convar_t hpk_custom_file;
|
||||
extern convar_t con_gamemaps;
|
||||
extern convar_t fs_mount_lv;
|
||||
extern convar_t fs_mount_hd;
|
||||
extern convar_t fs_mount_addon;
|
||||
extern convar_t fs_mount_l10n;
|
||||
extern convar_t ui_language; // historically used for UI, but now controls mounted localization directory
|
||||
|
||||
#define Mod_AllowMaterials() ( host_allow_materials.value != 0.0f && !FBitSet( host.features, ENGINE_DISABLE_HDTEXTURES ))
|
||||
|
||||
@@ -190,7 +189,7 @@ GAMEINFO stuff
|
||||
internal shared gameinfo structure (readonly for engine parts)
|
||||
========================================================================
|
||||
*/
|
||||
typedef enum host_status_e
|
||||
typedef enum
|
||||
{
|
||||
HOST_INIT = 0, // initalize operations
|
||||
HOST_FRAME, // host running
|
||||
@@ -201,7 +200,7 @@ typedef enum host_status_e
|
||||
HOST_CRASHED // an exception handler called
|
||||
} host_status_t;
|
||||
|
||||
typedef enum host_state_e
|
||||
typedef enum
|
||||
{
|
||||
STATE_RUNFRAME = 0,
|
||||
STATE_LOAD_LEVEL,
|
||||
@@ -210,7 +209,7 @@ typedef enum host_state_e
|
||||
STATE_GAME_SHUTDOWN,
|
||||
} host_state_t;
|
||||
|
||||
typedef struct game_status_e
|
||||
typedef struct
|
||||
{
|
||||
host_state_t curstate;
|
||||
host_state_t nextstate;
|
||||
@@ -221,7 +220,7 @@ typedef struct game_status_e
|
||||
qboolean newGame; // unload the server.dll before start a new map
|
||||
} game_status_t;
|
||||
|
||||
typedef enum keydest_e
|
||||
typedef enum
|
||||
{
|
||||
key_console = 0,
|
||||
key_game,
|
||||
@@ -229,7 +228,7 @@ typedef enum keydest_e
|
||||
key_message
|
||||
} keydest_t;
|
||||
|
||||
typedef enum rdtype_e
|
||||
typedef enum
|
||||
{
|
||||
RD_NONE = 0,
|
||||
RD_CLIENT,
|
||||
@@ -239,7 +238,7 @@ typedef enum rdtype_e
|
||||
#include "net_ws.h"
|
||||
|
||||
// console field
|
||||
typedef struct field_e
|
||||
typedef struct
|
||||
{
|
||||
string buffer;
|
||||
int cursor;
|
||||
@@ -257,7 +256,7 @@ typedef struct host_redirect_s
|
||||
int lines;
|
||||
} host_redirect_t;
|
||||
|
||||
typedef struct soundlist_e
|
||||
typedef struct
|
||||
{
|
||||
char name[MAX_QPATH];
|
||||
short entnum;
|
||||
@@ -298,7 +297,7 @@ typedef struct host_parm_s
|
||||
|
||||
host_status_t status; // global host state
|
||||
game_status_t game; // game manager
|
||||
instance_t type; // running at
|
||||
uint type; // running at
|
||||
poolhandle_t mempool; // static mempool for misc allocations
|
||||
poolhandle_t imagepool; // imagelib mempool
|
||||
poolhandle_t soundpool; // soundlib mempool
|
||||
@@ -415,8 +414,6 @@ byte *FS_LoadFile( const char *path, fs_offset_t *filesizeptr, qboolean gamediro
|
||||
MALLOC_LIKE( _Mem_Free, 1 ) WARN_UNUSED_RESULT;
|
||||
byte *FS_LoadDirectFile( const char *path, fs_offset_t *filesizeptr )
|
||||
MALLOC_LIKE( _Mem_Free, 1 ) WARN_UNUSED_RESULT;
|
||||
void FS_Rescan_f( void );
|
||||
void FS_CheckConfig( void );
|
||||
|
||||
//
|
||||
// cmd.c
|
||||
@@ -435,7 +432,6 @@ int Cmd_Argc( void );
|
||||
const char *Cmd_Args( void ) RETURNS_NONNULL;
|
||||
const char *Cmd_Argv( int arg ) RETURNS_NONNULL;
|
||||
void Cmd_Init( void );
|
||||
void Cmd_Shutdown( void );
|
||||
void Cmd_Unlink( int group );
|
||||
int Cmd_AddCommandEx( const char *cmd_name, xcommand_t function, const char *cmd_desc, int flags, const char *funcname );
|
||||
|
||||
@@ -494,7 +490,7 @@ internal sound format
|
||||
typically expanded to wav buffer
|
||||
========================================================================
|
||||
*/
|
||||
typedef enum sndformat_e
|
||||
typedef enum
|
||||
{
|
||||
WF_UNKNOWN = 0,
|
||||
WF_PCMDATA,
|
||||
@@ -505,7 +501,7 @@ typedef enum sndformat_e
|
||||
} sndformat_t;
|
||||
|
||||
// wavdata output flags
|
||||
typedef enum sndFlags_e
|
||||
typedef enum
|
||||
{
|
||||
// wavdata->flags
|
||||
SOUND_LOOPED = BIT( 0 ), // this is looped sound (contain cue markers)
|
||||
@@ -515,29 +511,29 @@ typedef enum sndFlags_e
|
||||
SOUND_RESAMPLE = BIT( 12 ), // resample sound to specified rate
|
||||
} sndFlags_t;
|
||||
|
||||
typedef struct wavdata_s
|
||||
typedef struct
|
||||
{
|
||||
size_t size; // for bounds checking
|
||||
word rate; // num samples per second (e.g. 11025 - 11 khz)
|
||||
byte width; // resolution - bum bits divided by 8 (8 bit is 1, 16 bit is 2)
|
||||
byte channels; // num channels (1 - mono, 2 - stereo)
|
||||
uint loopStart; // offset at this point sound will be looping while playing more than only once
|
||||
uint samples; // total samplecount in wav
|
||||
uint type; // compression type
|
||||
uint flags; // misc sound flags
|
||||
word rate; // num samples per second (e.g. 11025 - 11 khz)
|
||||
byte width; // resolution - bum bits divided by 8 (8 bit is 1, 16 bit is 2)
|
||||
byte channels; // num channels (1 - mono, 2 - stereo)
|
||||
byte buffer[]; // sound buffer
|
||||
byte *buffer; // sound buffer
|
||||
size_t size; // for bounds checking
|
||||
} wavdata_t;
|
||||
|
||||
//
|
||||
// soundlib
|
||||
//
|
||||
typedef struct stream_s stream_t;
|
||||
void Sound_Init( void );
|
||||
void Sound_Shutdown( void );
|
||||
void FS_FreeSound( wavdata_t *pack );
|
||||
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;
|
||||
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_SetStreamPos( stream_t *stream, int newpos );
|
||||
int FS_GetStreamPos( stream_t *stream );
|
||||
@@ -632,7 +628,6 @@ int pfnNumberOfEntities( void );
|
||||
int pfnIsInGame( void );
|
||||
float pfnTime( void );
|
||||
#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 freestring( s ) if( s != NULL ) { Mem_Free( s ); s = NULL; }
|
||||
char *_copystring( poolhandle_t mempool, const char *s, const char *filename, int fileline );
|
||||
@@ -683,7 +678,6 @@ int CSCR_WriteGameCVars( file_t *cfg, const char *scriptfilename );
|
||||
//
|
||||
// hpak.c
|
||||
//
|
||||
const char *COM_ResourceTypeFromIndex( int index );
|
||||
void HPAK_Init( void );
|
||||
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 );
|
||||
@@ -731,7 +725,7 @@ qboolean UI_CreditsActive( void );
|
||||
int CL_GetMaxClients( void );
|
||||
#else
|
||||
static inline qboolean CL_Initialized( void ) { return false; }
|
||||
static inline qboolean CL_IsInGame( void ) { return true; } // always true for dedicated
|
||||
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; }
|
||||
@@ -873,6 +867,13 @@ void V_CheckGamma( void );
|
||||
void V_CheckGammaEnd( void );
|
||||
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
|
||||
//
|
||||
|
||||
@@ -498,6 +498,7 @@ static qboolean Cmd_GetSoundList( const char *s, char *completedname, int length
|
||||
return true;
|
||||
}
|
||||
|
||||
#if !XASH_DEDICATED
|
||||
/*
|
||||
=====================================
|
||||
Cmd_GetItemsList
|
||||
@@ -507,7 +508,6 @@ Prints or complete item classname (weapons only)
|
||||
*/
|
||||
static qboolean Cmd_GetItemsList( const char *s, char *completedname, int length )
|
||||
{
|
||||
#if !XASH_DEDICATED
|
||||
search_t *t;
|
||||
string matchbuf;
|
||||
int i, numitems;
|
||||
@@ -521,7 +521,7 @@ static qboolean Cmd_GetItemsList( const char *s, char *completedname, int length
|
||||
Q_strncpy( completedname, matchbuf, length );
|
||||
if( t->numfilenames == 1 ) return true;
|
||||
|
||||
for( i = 0, numitems = 0; i < t->numfilenames; i++ )
|
||||
for(i = 0, numitems = 0; i < t->numfilenames; i++)
|
||||
{
|
||||
if( Q_stricmp( COM_FileExtension( t->filenames[i] ), "txt" ))
|
||||
continue;
|
||||
@@ -544,8 +544,6 @@ static qboolean Cmd_GetItemsList( const char *s, char *completedname, int length
|
||||
}
|
||||
}
|
||||
return true;
|
||||
#endif // !XASH_DEDICATED
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -557,7 +555,6 @@ Autocomplete for bind command
|
||||
*/
|
||||
static qboolean Cmd_GetKeysList( const char *s, char *completedname, int length )
|
||||
{
|
||||
#if !XASH_DEDICATED
|
||||
size_t i, numkeys;
|
||||
string keys[256];
|
||||
string matchbuf;
|
||||
@@ -598,9 +595,8 @@ static qboolean Cmd_GetKeysList( const char *s, char *completedname, int length
|
||||
}
|
||||
|
||||
return true;
|
||||
#endif // !XASH_DEDICATED
|
||||
return false;
|
||||
}
|
||||
#endif // XASH_DEDICATED
|
||||
|
||||
/*
|
||||
===============
|
||||
@@ -608,20 +604,13 @@ Con_AddCommandToList
|
||||
|
||||
===============
|
||||
*/
|
||||
static void Con_AddCommandToList( const char *s, const char *value, const void *ptoggle, void *_autocompleteList )
|
||||
static void Con_AddCommandToList( const char *s, const char *unused1, const char *unused2, void *_autocompleteList )
|
||||
{
|
||||
con_autocomplete_t *list = (con_autocomplete_t*)_autocompleteList;
|
||||
qboolean toggle = ptoggle != NULL && *(qboolean *)ptoggle;
|
||||
|
||||
if( *s == '@' ) return; // never show system cvars or cmds
|
||||
if( list->matchCount >= CON_MAXCMDS ) return; // list is full
|
||||
|
||||
if( toggle )
|
||||
{
|
||||
if( Q_strcmp( value, "0" ) && Q_strcmp( value, "1" ))
|
||||
return; // exclude non-toggable cvars
|
||||
}
|
||||
|
||||
if( Q_strnicmp( s, list->completionString, Q_strlen( list->completionString ) ) )
|
||||
return; // no match
|
||||
|
||||
@@ -645,11 +634,13 @@ Cmd_GetCommandsList
|
||||
Autocomplete for bind command
|
||||
=====================================
|
||||
*/
|
||||
static qboolean Cmd_GetCommandsAndCvarsList( const char *s, char *completedname, int length, qboolean cmds, qboolean cvars, qboolean toggle )
|
||||
static qboolean Cmd_GetCommandsList( const char *s, char *completedname, int length )
|
||||
{
|
||||
size_t i;
|
||||
string matchbuf;
|
||||
con_autocomplete_t list = { 0 }; // local autocomplete list
|
||||
con_autocomplete_t list; // local autocomplete list
|
||||
|
||||
memset( &list, 0, sizeof( list ));
|
||||
|
||||
list.completionString = s;
|
||||
|
||||
@@ -661,16 +652,8 @@ static qboolean Cmd_GetCommandsAndCvarsList( const char *s, char *completedname,
|
||||
return false;
|
||||
|
||||
// find matching commands and variables
|
||||
if( cvars )
|
||||
{
|
||||
Cvar_LookupVars( 0, &toggle, &list, (setpair_t)Con_AddCommandToList );
|
||||
}
|
||||
|
||||
if( cmds )
|
||||
{
|
||||
toggle = false;
|
||||
Cmd_LookupCmds( &toggle, &list, (setpair_t)Con_AddCommandToList );
|
||||
}
|
||||
Cmd_LookupCmds( NULL, &list, (setpair_t)Con_AddCommandToList );
|
||||
Cvar_LookupVars( 0, NULL, &list, (setpair_t)Con_AddCommandToList );
|
||||
|
||||
if( !list.matchCount ) return false;
|
||||
Q_strncpy( matchbuf, list.cmds[0], sizeof( matchbuf ));
|
||||
@@ -686,7 +669,7 @@ static qboolean Cmd_GetCommandsAndCvarsList( const char *s, char *completedname,
|
||||
Con_Printf( "%16s\n", matchbuf );
|
||||
}
|
||||
|
||||
Con_Printf( "\n^3 %i %s found.\n", list.matchCount, cmds ? "commands" : "variables" );
|
||||
Con_Printf( "\n^3 %i commands found.\n", list.matchCount );
|
||||
|
||||
if( completedname && length )
|
||||
{
|
||||
@@ -708,30 +691,6 @@ static qboolean Cmd_GetCommandsAndCvarsList( const char *s, char *completedname,
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
=====================================
|
||||
Cmd_GetCommandsList
|
||||
|
||||
Autocomplete for bind command
|
||||
=====================================
|
||||
*/
|
||||
static qboolean Cmd_GetCommandsList( const char *s, char *completedname, int length )
|
||||
{
|
||||
return Cmd_GetCommandsAndCvarsList( s, completedname, length, true, true, false );
|
||||
}
|
||||
|
||||
/*
|
||||
=====================================
|
||||
Cmd_GetCvarList
|
||||
|
||||
Autocomplete for bind command
|
||||
=====================================
|
||||
*/
|
||||
static qboolean Cmd_GetCvarsList( const char *s, char *completedname, int length )
|
||||
{
|
||||
qboolean toggle = !Q_stricmp( Cmd_Argv( 0 ), "toggle" );
|
||||
return Cmd_GetCommandsAndCvarsList( s, completedname, length, false, true, toggle );
|
||||
}
|
||||
|
||||
/*
|
||||
=====================================
|
||||
@@ -1051,38 +1010,36 @@ int GAME_EXPORT Cmd_CheckMapsList( int fRefresh )
|
||||
return Cmd_CheckMapsList_R( fRefresh, true );
|
||||
}
|
||||
|
||||
// keep this sorted
|
||||
static const autocomplete_list_t cmd_list[] =
|
||||
{
|
||||
{ "bind", 1, Cmd_GetKeysList },
|
||||
{ "bind", 2, Cmd_GetCommandsList },
|
||||
{ "cd", 1, Cmd_GetCDList },
|
||||
{ "map_background", 1, Cmd_GetMapList },
|
||||
{ "changelevel2", 1, Cmd_GetMapList },
|
||||
{ "changelevel", 1, Cmd_GetMapList },
|
||||
{ "drop", 1, Cmd_GetItemsList },
|
||||
{ "entpatch", 1, Cmd_GetMapList },
|
||||
{ "exec", 1, Cmd_GetConfigList },
|
||||
{ "game", 1, Cmd_GetGamesList },
|
||||
{ "give", 1, Cmd_GetItemsList },
|
||||
{ "hpkextract", 1, Cmd_GetCustomList },
|
||||
{ "hpklist", 1, Cmd_GetCustomList },
|
||||
{ "hpkval", 1, Cmd_GetCustomList },
|
||||
{ "listdemo", 1, Cmd_GetDemoList, },
|
||||
{ "load", 1, Cmd_GetSavesList },
|
||||
{ "map", 1, Cmd_GetMapList },
|
||||
{ "map_background", 1, Cmd_GetMapList },
|
||||
{ "movie", 1, Cmd_GetMovieList },
|
||||
{ "mp3", 1, Cmd_GetCDList },
|
||||
{ "music", 1, Cmd_GetMusicList, },
|
||||
{ "play", 1, Cmd_GetSoundList },
|
||||
{ "playdemo", 1, Cmd_GetDemoList, },
|
||||
{ "timedemo", 1, Cmd_GetDemoList, },
|
||||
{ "listdemo", 1, Cmd_GetDemoList, },
|
||||
{ "playvol", 1, Cmd_GetSoundList },
|
||||
{ "reset", 1, Cmd_GetCvarsList },
|
||||
{ "save", 1, Cmd_GetSavesList },
|
||||
{ "set", 1, Cmd_GetCvarsList },
|
||||
{ "timedemo", 1, Cmd_GetDemoList },
|
||||
{ "toggle", 1, Cmd_GetCvarsList },
|
||||
{ "hpkval", 1, Cmd_GetCustomList },
|
||||
{ "hpklist", 1, Cmd_GetCustomList },
|
||||
{ "hpkextract", 1, Cmd_GetCustomList },
|
||||
{ "entpatch", 1, Cmd_GetMapList },
|
||||
{ "music", 1, Cmd_GetMusicList, },
|
||||
{ "movie", 1, Cmd_GetMovieList },
|
||||
{ "exec", 1, Cmd_GetConfigList },
|
||||
#if !XASH_DEDICATED
|
||||
{ "give", 1, Cmd_GetItemsList },
|
||||
{ "drop", 1, Cmd_GetItemsList },
|
||||
{ "bind", 1, Cmd_GetKeysList },
|
||||
{ "unbind", 1, Cmd_GetKeysList },
|
||||
{ "bind", 2, Cmd_GetCommandsList },
|
||||
#endif
|
||||
{ "game", 1, Cmd_GetGamesList },
|
||||
{ "save", 1, Cmd_GetSavesList },
|
||||
{ "load", 1, Cmd_GetSavesList },
|
||||
{ "play", 1, Cmd_GetSoundList },
|
||||
{ "map", 1, Cmd_GetMapList },
|
||||
{ "cd", 1, Cmd_GetCDList },
|
||||
{ "mp3", 1, Cmd_GetCDList },
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -1203,7 +1160,6 @@ void Con_CompleteCommand( field_t *field )
|
||||
{
|
||||
field_t temp;
|
||||
string filename;
|
||||
qboolean toggle = false;
|
||||
qboolean nextcmd;
|
||||
int i;
|
||||
|
||||
@@ -1238,8 +1194,8 @@ void Con_CompleteCommand( field_t *field )
|
||||
con.shortestMatch[0] = 0;
|
||||
|
||||
// find matching commands and variables
|
||||
Cmd_LookupCmds( &toggle, &con, (setpair_t)Con_AddCommandToList );
|
||||
Cvar_LookupVars( 0, &toggle, &con, (setpair_t)Con_AddCommandToList );
|
||||
Cmd_LookupCmds( NULL, &con, (setpair_t)Con_AddCommandToList );
|
||||
Cvar_LookupVars( 0, NULL, &con, (setpair_t)Con_AddCommandToList );
|
||||
|
||||
if( !con.matchCount ) return; // no matches
|
||||
|
||||
|
||||
@@ -19,7 +19,6 @@ GNU General Public License for more details.
|
||||
#include "eiface.h" // ARRAYSIZE
|
||||
|
||||
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" );
|
||||
|
||||
typedef struct cvar_filter_quirks_s
|
||||
@@ -433,7 +432,7 @@ convar_t *Cvar_Get( const char *name, const char *value, int flags, const char *
|
||||
{
|
||||
// directly set value
|
||||
freestring( var->string );
|
||||
var->string = copystringpool( cvar_pool, value );
|
||||
var->string = copystring( value );
|
||||
var->value = Q_atof( var->string );
|
||||
SetBits( var->flags, flags );
|
||||
|
||||
@@ -453,18 +452,18 @@ convar_t *Cvar_Get( const char *name, const char *value, int flags, const char *
|
||||
Con_Reportf( "%s change description from %s to %s\n", var->name, var->desc, var_desc );
|
||||
// update description if needs
|
||||
freestring( var->desc );
|
||||
var->desc = copystringpool( cvar_pool, var_desc );
|
||||
var->desc = copystring( var_desc );
|
||||
}
|
||||
|
||||
return var;
|
||||
}
|
||||
|
||||
// allocate a new cvar
|
||||
var = Mem_Malloc( cvar_pool, sizeof( *var ));
|
||||
var->name = copystringpool( cvar_pool, name );
|
||||
var->string = copystringpool( cvar_pool, value );
|
||||
var->def_string = copystringpool( cvar_pool, value );
|
||||
var->desc = copystringpool( cvar_pool, var_desc );
|
||||
var = Z_Malloc( sizeof( *var ));
|
||||
var->name = copystring( name );
|
||||
var->string = copystring( value );
|
||||
var->def_string = copystring( value );
|
||||
var->desc = copystring( var_desc );
|
||||
var->value = Q_atof( var->string );
|
||||
var->flags = flags|FCVAR_ALLOCATED;
|
||||
|
||||
@@ -550,7 +549,7 @@ void Cvar_RegisterVariable( convar_t *var )
|
||||
if( FBitSet( var->flags, FCVAR_EXTENDED ))
|
||||
var->def_string = var->string; // just swap pointers
|
||||
|
||||
var->string = copystringpool( cvar_pool, var->string );
|
||||
var->string = copystring( var->string );
|
||||
var->value = Q_atof( var->string );
|
||||
|
||||
// find the supposed position in chain (alphanumerical order)
|
||||
@@ -680,7 +679,7 @@ static convar_t *Cvar_Set2( const char *var_name, const char *value )
|
||||
|
||||
// and finally changed the cvar itself
|
||||
freestring( var->string );
|
||||
var->string = copystringpool( cvar_pool, pszValue );
|
||||
var->string = copystring( pszValue );
|
||||
var->value = Q_atof( var->string );
|
||||
|
||||
// tell engine about changes
|
||||
@@ -739,7 +738,7 @@ void GAME_EXPORT Cvar_DirectSet( convar_t *var, const char *value )
|
||||
|
||||
// and finally changed the cvar itself
|
||||
freestring( var->string );
|
||||
var->string = copystringpool( cvar_pool, pszValue );
|
||||
var->string = copystring( pszValue );
|
||||
var->value = Q_atof( var->string );
|
||||
|
||||
// tell engine about changes
|
||||
@@ -782,7 +781,7 @@ void Cvar_FullSet( const char *var_name, const char *value, int flags )
|
||||
}
|
||||
|
||||
freestring( var->string );
|
||||
var->string = copystringpool( cvar_pool, value );
|
||||
var->string = copystring( value );
|
||||
var->value = Q_atof( var->string );
|
||||
SetBits( var->flags, flags );
|
||||
|
||||
@@ -1190,7 +1189,6 @@ static void Cvar_List_f( void )
|
||||
for( var = cvar_vars; var; var = var->next )
|
||||
{
|
||||
char value[MAX_VA_STRING];
|
||||
char *p;
|
||||
|
||||
if( var->name[0] == '@' )
|
||||
continue; // never shows system cvars
|
||||
@@ -1198,9 +1196,7 @@ static void Cvar_List_f( void )
|
||||
if( match && !Q_strnicmpext( match, var->name, matchlen ))
|
||||
continue;
|
||||
|
||||
p = Q_strchr( var->string, '^' );
|
||||
|
||||
if( IsColorString( p ))
|
||||
if( Q_colorstr( var->string ))
|
||||
Q_snprintf( value, sizeof( value ), "\"%s\"", var->string );
|
||||
else Q_snprintf( value, sizeof( value ), "\"^2%s^7\"", var->string );
|
||||
|
||||
@@ -1261,7 +1257,7 @@ pending_cvar_t *Cvar_PrepareToUnlink( int group )
|
||||
continue;
|
||||
|
||||
namelen = Q_strlen( cv->name ) + 1;
|
||||
p = Mem_Malloc( cvar_pool, sizeof( *list ) + namelen );
|
||||
p = Mem_Malloc( host.mempool, sizeof( *list ) + namelen );
|
||||
p->next = NULL;
|
||||
p->cv_cur = cv;
|
||||
p->cv_next = cv->next;
|
||||
@@ -1337,7 +1333,6 @@ Reads in all archived cvars
|
||||
*/
|
||||
void Cvar_Init( void )
|
||||
{
|
||||
cvar_pool = Mem_AllocPool( "Console Variables" );
|
||||
cvar_vars = NULL;
|
||||
cvar_active_filter_quirks = NULL;
|
||||
Cvar_RegisterVariable( &cmd_scripting );
|
||||
@@ -1350,11 +1345,6 @@ void Cvar_Init( void )
|
||||
Cmd_AddCommand( "cvarlist", Cvar_List_f, "display all console variables beginning with the specified prefix" );
|
||||
}
|
||||
|
||||
void Cvar_Shutdown( void )
|
||||
{
|
||||
Mem_FreePool( &cvar_pool );
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
Cvar_PostFSInit
|
||||
|
||||
@@ -30,8 +30,6 @@ typedef struct pending_cvar_s
|
||||
char cv_name[];
|
||||
} pending_cvar_t;
|
||||
|
||||
typedef void (*setpair_t)( const char *key, const void *value, const void *buffer, void *numpairs );
|
||||
|
||||
cvar_t *Cvar_GetList( void );
|
||||
#define Cvar_FindVar( name ) Cvar_FindVarExt( name, 0 )
|
||||
convar_t *Cvar_FindVarExt( const char *var_name, int ignore_group );
|
||||
@@ -54,7 +52,6 @@ void Cvar_Reset( const char *var_name );
|
||||
void Cvar_SetCheatState( void );
|
||||
qboolean Cvar_CommandWithPrivilegeCheck( convar_t *v, qboolean isPrivileged );
|
||||
void Cvar_Init( void );
|
||||
void Cvar_Shutdown( void );
|
||||
void Cvar_PostFSInit( void );
|
||||
void Cvar_Unlink( int group );
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
filesystem.c - game filesystem based on DP fs
|
||||
Copyright (C) 2003-2006 Mathieu Olivier
|
||||
Copyright (C) 2000-2007 DarkPlaces contributors
|
||||
@@ -16,21 +16,11 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#if XASH_SDL
|
||||
#include <SDL.h> // SDL_GetBasePath
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
#include "common.h"
|
||||
#include "library.h"
|
||||
#include "platform/platform.h"
|
||||
|
||||
CVAR_DEFINE_AUTO( fs_mount_hd, "0", FCVAR_ARCHIVE|FCVAR_PRIVILEGED|FCVAR_LATCH, "mount high definition content folder" );
|
||||
CVAR_DEFINE_AUTO( fs_mount_lv, "0", FCVAR_ARCHIVE|FCVAR_PRIVILEGED|FCVAR_LATCH, "mount low violence models content folder" );
|
||||
CVAR_DEFINE_AUTO( fs_mount_addon, "0", FCVAR_ARCHIVE|FCVAR_PRIVILEGED|FCVAR_LATCH, "mount addon content folder" );
|
||||
CVAR_DEFINE_AUTO( fs_mount_l10n, "0", FCVAR_ARCHIVE|FCVAR_PRIVILEGED|FCVAR_LATCH, "mount localization content folder" );
|
||||
CVAR_DEFINE_AUTO( ui_language, "english", FCVAR_ARCHIVE|FCVAR_PRIVILEGED|FCVAR_LATCH, "selected game language" );
|
||||
|
||||
fs_api_t g_fsapi;
|
||||
fs_globals_t *FI;
|
||||
|
||||
@@ -79,23 +69,9 @@ void *FS_GetNativeObject( const char *obj )
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void FS_Rescan_f( void )
|
||||
static void FS_Rescan_f( void )
|
||||
{
|
||||
uint32_t flags = 0;
|
||||
|
||||
// FIXME: VFS shouldn't care about this, allow engine to mount gamedirs
|
||||
if( fs_mount_lv.value ) SetBits( flags, FS_MOUNT_LV );
|
||||
if( fs_mount_hd.value ) SetBits( flags, FS_MOUNT_HD );
|
||||
if( fs_mount_addon.value ) SetBits( flags, FS_MOUNT_ADDON );
|
||||
if( fs_mount_l10n.value ) SetBits( flags, FS_MOUNT_L10N );
|
||||
|
||||
g_fsapi.Rescan( flags, ui_language.string );
|
||||
|
||||
ClearBits( fs_mount_lv.flags, FCVAR_CHANGED );
|
||||
ClearBits( fs_mount_hd.flags, FCVAR_CHANGED );
|
||||
ClearBits( fs_mount_addon.flags, FCVAR_CHANGED );
|
||||
ClearBits( fs_mount_l10n.flags, FCVAR_CHANGED );
|
||||
ClearBits( ui_language.flags, FCVAR_CHANGED );
|
||||
FS_Rescan();
|
||||
}
|
||||
|
||||
static void FS_ClearPaths_f( void )
|
||||
@@ -207,23 +183,14 @@ static qboolean FS_DetermineRootDirectory( char *out, size_t size )
|
||||
#elif XASH_PSVITA
|
||||
if( PSVita_GetBasePath( out, size ))
|
||||
return true;
|
||||
Sys_Error( "couldn't find %s data directory", XASH_ENGINE_NAME );
|
||||
Sys_Error( "couldn't find Xash3D data directory" );
|
||||
return false;
|
||||
#elif ( XASH_SDL == 2 ) && !XASH_NSWITCH // GetBasePath not impl'd in switch-sdl2
|
||||
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 )
|
||||
{
|
||||
Q_strncpy( out, path, size );
|
||||
SDL_free((void *)path );
|
||||
SDL_free(( void *)path );
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -260,12 +227,6 @@ static qboolean FS_DetermineReadOnlyRootDirectory( char *out, size_t size )
|
||||
return false;
|
||||
}
|
||||
|
||||
void FS_CheckConfig( void )
|
||||
{
|
||||
if( fs_mount_lv.value || fs_mount_hd.value || fs_mount_addon.value || fs_mount_l10n.value )
|
||||
FS_Rescan_f();
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
FS_Init
|
||||
@@ -318,11 +279,6 @@ void FS_Init( const char *basedir )
|
||||
Cmd_AddRestrictedCommand( "fs_clearpaths", FS_ClearPaths_f, "clear filesystem search pathes" );
|
||||
Cmd_AddRestrictedCommand( "fs_make_gameinfo", FS_MakeGameInfo_f, "create gameinfo.txt for current running game" );
|
||||
|
||||
Cvar_RegisterVariable( &fs_mount_hd );
|
||||
Cvar_RegisterVariable( &fs_mount_lv );
|
||||
Cvar_RegisterVariable( &fs_mount_addon );
|
||||
Cvar_RegisterVariable( &fs_mount_l10n );
|
||||
|
||||
if( !Sys_GetParmFromCmdLine( "-dll", host.gamedll ))
|
||||
host.gamedll[0] = 0;
|
||||
|
||||
|
||||
@@ -140,8 +140,7 @@ static void Sys_PrintUsage( const char *exename )
|
||||
|
||||
"\nCommon options:\n"
|
||||
O("-dev [level] ", "set log verbosity 0-2")
|
||||
O("-log [file name] ", "write log to \"engine.log\" or [file name] if specified")
|
||||
O("-logtime ", "enable writing timestamps to the log file")
|
||||
O("-log ", "write log to \"engine.log\"")
|
||||
O("-nowriteconfig ", "disable config save")
|
||||
O("-noch ", "disable crashhandler")
|
||||
#if XASH_WIN32 // !!!!
|
||||
@@ -202,6 +201,7 @@ static void Sys_PrintUsage( const char *exename )
|
||||
O("-daemonize ", "run engine as a daemon")
|
||||
#endif
|
||||
#if XASH_SDL == 2
|
||||
O("-sdl_joy_old_api ","use SDL legacy joystick API")
|
||||
O("-sdl_renderer <n> ","use alternative SDL_Renderer for software")
|
||||
#endif // XASH_SDL
|
||||
#if XASH_ANDROID && !XASH_SDL
|
||||
@@ -698,17 +698,17 @@ static qboolean Host_Autosleep( double dt, double scale )
|
||||
static double timewindow; // allocate a time window for sleeps
|
||||
static int counter; // for debug
|
||||
static double realsleeptime;
|
||||
const double sleeptime = sleep * 0.000001;
|
||||
const double sleeptime = sleep * 0.001;
|
||||
|
||||
if( dt < targetframetime * scale )
|
||||
{
|
||||
// if we have allocated time window, try to sleep
|
||||
if( timewindow > realsleeptime )
|
||||
{
|
||||
// Platform_Sleep isn't guaranteed to sleep an exact amount of microseconds
|
||||
// Platform_Sleep isn't guaranteed to sleep an exact amount of milliseconds
|
||||
// so we measure the real sleep time and use it to decrease the window
|
||||
double t1 = Sys_DoubleTime(), t2;
|
||||
Platform_NanoSleep( sleep * 1000 ); // in usec!
|
||||
Platform_Sleep( sleep ); // in msec!
|
||||
t2 = Sys_DoubleTime();
|
||||
realsleeptime = t2 - t1;
|
||||
|
||||
@@ -1044,7 +1044,7 @@ static void Host_InitCommon( int argc, char **argv, const char *progname, qboole
|
||||
}
|
||||
|
||||
if( !Sys_CheckParm( "-noch" ))
|
||||
Sys_SetupCrashHandler( argv[0] );
|
||||
Sys_SetupCrashHandler();
|
||||
|
||||
#if XASH_DLL_LOADER
|
||||
host.enabledll = !Sys_CheckParm( "-nodll" );
|
||||
@@ -1131,7 +1131,7 @@ static void Host_InitCommon( int argc, char **argv, const char *progname, qboole
|
||||
#if XASH_DEDICATED
|
||||
Platform_SetupSigtermHandling();
|
||||
#endif
|
||||
Platform_Init( Host_IsDedicated( ) || developer >= DEV_EXTENDED, basedir );
|
||||
Platform_Init( Host_IsDedicated( ) || developer >= DEV_EXTENDED );
|
||||
FS_Init( basedir );
|
||||
|
||||
Sys_InitLog();
|
||||
@@ -1236,14 +1236,6 @@ int EXPORT Host_Main( int argc, char **argv, const char *progname, int bChangeGa
|
||||
Cvar_Getf( "host_ver", FCVAR_READ_ONLY, "detailed info about this build", "%i " XASH_VERSION " %s %s %s", Q_buildnum(), Q_buildos(), Q_buildarch(), g_buildcommit);
|
||||
Cvar_Getf( "host_lowmemorymode", FCVAR_READ_ONLY, "indicates if engine compiled for low RAM consumption (0 - normal, 1 - low engine limits, 2 - low protocol limits)", "%i", XASH_LOW_MEMORY );
|
||||
|
||||
Cvar_Get( "host_hl25_extended_structs",
|
||||
#if SUPPORT_HL25_EXTENDED_STRUCTS
|
||||
"1",
|
||||
#else
|
||||
"0",
|
||||
#endif
|
||||
FCVAR_READ_ONLY, "indicates if engine was compiled with extended msurface_t struct" );
|
||||
|
||||
Mod_Init();
|
||||
NET_Init();
|
||||
NET_InitMasters();
|
||||
@@ -1264,6 +1256,7 @@ int EXPORT Host_Main( int argc, char **argv, const char *progname, int bChangeGa
|
||||
CL_Init();
|
||||
|
||||
HTTP_Init();
|
||||
ID_Init();
|
||||
SoundList_Init();
|
||||
|
||||
if( Host_IsDedicated( ))
|
||||
@@ -1319,7 +1312,6 @@ int EXPORT Host_Main( int argc, char **argv, const char *progname, int bChangeGa
|
||||
Cmd_RemoveCommand( "setgl" );
|
||||
Cbuf_ExecStuffCmds(); // execute stuffcmds (commandline)
|
||||
SCR_CheckStartupVids(); // must be last
|
||||
FS_CheckConfig();
|
||||
|
||||
if( Sys_GetParmFromCmdLine( "-timedemo", demoname ))
|
||||
Cbuf_AddTextf( "timedemo %s\n", demoname );
|
||||
@@ -1408,10 +1400,6 @@ void Host_ShutdownWithReason( const char *reason )
|
||||
Host_FreeCommon();
|
||||
Platform_Shutdown();
|
||||
|
||||
BaseCmd_Shutdown();
|
||||
Cmd_Shutdown();
|
||||
Cvar_Shutdown();
|
||||
|
||||
// must be last, console uses this
|
||||
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" );
|
||||
}
|
||||
|
||||
const char *COM_ResourceTypeFromIndex( int type )
|
||||
static const char *HPAK_TypeFromIndex( int type )
|
||||
{
|
||||
switch( type )
|
||||
{
|
||||
@@ -461,7 +461,7 @@ static qboolean HPAK_Validate( const char *filename, qboolean quiet, qboolean de
|
||||
|
||||
if( !quiet )
|
||||
{
|
||||
Con_Printf( "%i: %s %s %s: ", i, COM_ResourceTypeFromIndex( pRes->type ),
|
||||
Con_Printf( "%i: %s %s %s: ", i, HPAK_TypeFromIndex( pRes->type ),
|
||||
Q_pretifymem( pRes->nDownloadSize, 2 ), pRes->szFileName );
|
||||
}
|
||||
|
||||
@@ -942,7 +942,7 @@ static void HPAK_List_f( void )
|
||||
{
|
||||
entry = &directory.entries[nCurrent];
|
||||
COM_FileBase( entry->resource.szFileName, lumpname, sizeof( lumpname ));
|
||||
type = COM_ResourceTypeFromIndex( entry->resource.type );
|
||||
type = HPAK_TypeFromIndex( entry->resource.type );
|
||||
size = Q_memprint( entry->resource.nDownloadSize );
|
||||
|
||||
Con_Printf( "%i: %10s %s %s\n : %s\n", nCurrent + 1, type, size, lumpname, MD5_Print( entry->resource.rgucMD5_hash ));
|
||||
@@ -1037,7 +1037,7 @@ static void HPAK_Extract_f( void )
|
||||
continue;
|
||||
|
||||
COM_FileBase( entry->resource.szFileName, lumpname, sizeof( lumpname ) );
|
||||
type = COM_ResourceTypeFromIndex( entry->resource.type );
|
||||
type = HPAK_TypeFromIndex( entry->resource.type );
|
||||
size = Q_memprint( entry->resource.nDownloadSize );
|
||||
|
||||
Con_Printf( "Extracting %i: %10s %s %s\n", nCurrent + 1, type, size, lumpname );
|
||||
|
||||
@@ -19,8 +19,8 @@ GNU General Public License for more details.
|
||||
#if !XASH_WIN32
|
||||
#include <dirent.h>
|
||||
#endif
|
||||
|
||||
static char id_md5[33];
|
||||
static char id_customid[MAX_STRING];
|
||||
|
||||
/*
|
||||
==========================================================
|
||||
@@ -590,9 +590,25 @@ static void ID_Check( void )
|
||||
|
||||
const char *ID_GetMD5( void )
|
||||
{
|
||||
if( id_customid[0] )
|
||||
return id_customid;
|
||||
return id_md5;
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
ID_SetCustomClientID
|
||||
|
||||
===============
|
||||
*/
|
||||
void GAME_EXPORT ID_SetCustomClientID( const char *id )
|
||||
{
|
||||
if( !id )
|
||||
return;
|
||||
|
||||
Q_strncpy( id_customid, id, sizeof( id_customid ) );
|
||||
}
|
||||
|
||||
void ID_Init( void )
|
||||
{
|
||||
MD5Context_t hash = { 0 };
|
||||
@@ -616,7 +632,7 @@ void ID_Init( void )
|
||||
#elif XASH_WIN32
|
||||
{
|
||||
CHAR szBuf[MAX_PATH];
|
||||
ID_GetKeyData( HKEY_CURRENT_USER, "Software\\"XASH_ENGINE_NAME"\\", "xash_id", szBuf, MAX_PATH );
|
||||
ID_GetKeyData( HKEY_CURRENT_USER, "Software\\Xash3D\\", "xash_id", szBuf, MAX_PATH );
|
||||
|
||||
sscanf(szBuf, "%016"PRIX64, &id);
|
||||
id ^= SYSTEM_XOR_MASK;
|
||||
@@ -670,7 +686,7 @@ void ID_Init( void )
|
||||
{
|
||||
CHAR Buf[MAX_PATH];
|
||||
sprintf( Buf, "%016"PRIX64, id^SYSTEM_XOR_MASK );
|
||||
ID_SetKeyData( HKEY_CURRENT_USER, "Software\\"XASH_ENGINE_NAME"\\", REG_SZ, "xash_id", Buf, Q_strlen(Buf) );
|
||||
ID_SetKeyData( HKEY_CURRENT_USER, "Software\\Xash3D\\", REG_SZ, "xash_id", Buf, Q_strlen(Buf) );
|
||||
}
|
||||
#else
|
||||
{
|
||||
@@ -28,20 +28,12 @@ Image_LoadPAL
|
||||
qboolean Image_LoadPAL( const char *name, const byte *buffer, fs_offset_t filesize )
|
||||
{
|
||||
int rendermode = LUMP_NORMAL;
|
||||
byte pal[768];
|
||||
|
||||
if( filesize > sizeof( pal ))
|
||||
if( filesize != 768 )
|
||||
{
|
||||
Con_DPrintf( S_ERROR "%s: (%s) have invalid size (%li should be less or equal than %d)\n", __func__, name, (long)filesize, sizeof( pal ));
|
||||
Con_DPrintf( S_ERROR "%s: (%s) have invalid size (%li should be %d)\n", __func__, name, (long)filesize, 768 );
|
||||
return false;
|
||||
}
|
||||
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] == '#' )
|
||||
{
|
||||
|
||||
@@ -419,21 +419,14 @@ void NET_InitMasters( void )
|
||||
|
||||
Cvar_RegisterVariable( &sv_verbose_heartbeats );
|
||||
|
||||
{ // IPv4-only
|
||||
NET_AddMaster( "mentality.rip:27010", false, false );
|
||||
NET_AddMaster( "ms2.mentality.rip:27010", false, false );
|
||||
NET_AddMaster( "ms3.mentality.rip:27010", false, false );
|
||||
}
|
||||
// keep main master always there
|
||||
NET_AddMaster( MASTERSERVER_ADR, false, false );
|
||||
NET_AddMaster( "mentality.rip:27011", false, false ); // testing server, might be offline
|
||||
NET_AddMaster( "ms2.mentality.rip:27010", false, false ); // secondary master
|
||||
|
||||
{ // IPv6-only
|
||||
NET_AddMaster( "aaaa.mentality.rip:27010", false, true );
|
||||
NET_AddMaster( "aaaa.ms2.mentality.rip:27010", false, true );
|
||||
}
|
||||
|
||||
{ // testing servers, might be offline
|
||||
NET_AddMaster( "mentality.rip:27011", false, false );
|
||||
NET_AddMaster( "aaaa.mentality.rip:27011", false, true );
|
||||
}
|
||||
NET_AddMaster( "aaaa.mentality.rip:27010", false, true ); // IPv6-only
|
||||
NET_AddMaster( "aaaa.mentality.rip:27011", false, true ); // IPv6-only, testing server, might be offline
|
||||
NET_AddMaster( "aaaa.ms2.mentality.rip:27010", false, false ); // secondary IPv6-only master
|
||||
|
||||
NET_LoadMasters( );
|
||||
}
|
||||
|
||||
@@ -482,7 +482,7 @@ static int Mod_LoadTextureFromWadList( wadlist_t *list, const char *name, rgbdat
|
||||
return -1;
|
||||
}
|
||||
|
||||
static fs_offset_t Mod_CalculateMipTexSize( const mip_t *mt, qboolean palette )
|
||||
static fs_offset_t Mod_CalculateMipTexSize( mip_t *mt, qboolean palette )
|
||||
{
|
||||
if( !mt )
|
||||
return 0;
|
||||
@@ -2359,7 +2359,7 @@ static qboolean Mod_SearchForTextureReplacement( char *out, size_t size, const c
|
||||
return false;
|
||||
}
|
||||
|
||||
static void Mod_InitSkyClouds( model_t *mod, const mip_t *mt, texture_t *tx, qboolean custom_palette )
|
||||
static void Mod_InitSkyClouds( model_t *mod, mip_t *mt, texture_t *tx, qboolean custom_palette )
|
||||
{
|
||||
#if !XASH_DEDICATED
|
||||
rgbdata_t r_temp, *r_sky;
|
||||
@@ -2516,6 +2516,9 @@ done:
|
||||
|
||||
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;
|
||||
char texpath[MAX_VA_STRING];
|
||||
char safemtname[16]; // only for external textures
|
||||
@@ -2523,10 +2526,12 @@ static void Mod_LoadTextureData( model_t *mod, dbspmodel_t *bmod, int textureInd
|
||||
|
||||
// don't load texture data on dedicated server, as there is no renderer.
|
||||
// but count the wadusage for automatic precache
|
||||
texture_t *texture = mod->textures[textureIndex];
|
||||
const mip_t *mipTex = Mod_GetMipTexForTexture( bmod, textureIndex );
|
||||
const qboolean usesCustomPalette = Mod_CalcMipTexUsesCustomPalette( mod, bmod, textureIndex );
|
||||
const qboolean iswater = Mod_LooksLikeWaterTexture( mipTex->name );
|
||||
//
|
||||
// FIXME: for ENGINE_IMPROVED_LINETRACE we need to load textures on server too
|
||||
// but there is no facility for this yet
|
||||
texture = mod->textures[textureIndex];
|
||||
mipTex = Mod_GetMipTexForTexture( bmod, textureIndex );
|
||||
usesCustomPalette = Mod_CalcMipTexUsesCustomPalette( mod, bmod, textureIndex );
|
||||
|
||||
// check for multi-layered sky texture (quake1 specific)
|
||||
if( bmod->isworld && Q_strncmp( mipTex->name, "sky", 3 ) == 0 && ( mipTex->width / mipTex->height ) == 2 )
|
||||
@@ -2535,13 +2540,11 @@ static void Mod_LoadTextureData( model_t *mod, dbspmodel_t *bmod, int textureInd
|
||||
return;
|
||||
}
|
||||
|
||||
// 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] == '{' )
|
||||
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)
|
||||
if( iswater )
|
||||
if( Mod_LooksLikeWaterTexture( mipTex->name ))
|
||||
SetBits( txFlags, TF_KEEP_SOURCE | TF_EXPAND_SOURCE );
|
||||
|
||||
// Texture loading order:
|
||||
@@ -2606,13 +2609,8 @@ static void Mod_LoadTextureData( model_t *mod, dbspmodel_t *bmod, int textureInd
|
||||
texture->gl_texturenum = R_GetBuiltinTexture( REF_DEFAULT_TEXTURE );
|
||||
}
|
||||
|
||||
texture->fb_texturenum = 0;
|
||||
|
||||
// Check for luma texture
|
||||
// a1ba: ignore for water because fb_texturenum will be used to store ripple texture
|
||||
if( iswater )
|
||||
return;
|
||||
|
||||
texture->fb_texturenum = 0;
|
||||
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" ))
|
||||
|
||||
@@ -382,7 +382,8 @@ static void Mod_StudioCalcRotations( int boneused[], int numbones, const byte *p
|
||||
for( j = numbones - 1; j >= 0; j-- )
|
||||
{
|
||||
i = boneused[j];
|
||||
R_StudioCalcBones( frame, s, &pbone[i], &panim[i], adj, pos[i], q[i] );
|
||||
R_StudioCalcBoneQuaternion( frame, s, &pbone[i], &panim[i], adj, q[i] );
|
||||
R_StudioCalcBonePosition( frame, s, &pbone[i], &panim[i], adj, pos[i] );
|
||||
}
|
||||
|
||||
if( pseqdesc->motiontype & STUDIO_X ) pos[pseqdesc->motionbone][0] = 0.0f;
|
||||
@@ -723,7 +724,7 @@ void Mod_StudioComputeBounds( void *buffer, vec3_t mins, vec3_t maxs, qboolean i
|
||||
{
|
||||
for( k = 0; k < pseqdesc->numframes; k++ )
|
||||
{
|
||||
R_StudioCalcBones( k, 0, &pbones[j], panim, NULL, pos, NULL );
|
||||
R_StudioCalcBonePosition( k, 0, &pbones[j], panim, NULL, pos );
|
||||
Mod_StudioBoundVertex( vert_mins, vert_maxs, &bone_count, pos );
|
||||
}
|
||||
}
|
||||
@@ -867,7 +868,7 @@ void Mod_LoadStudioModel( model_t *mod, const void *buffer, qboolean *loaded )
|
||||
mod->type = mod_studio;
|
||||
|
||||
phdr = R_StudioLoadHeader( mod, buffer );
|
||||
if( !phdr || phdr->length < sizeof( studiohdr_t )) // garbage value in length
|
||||
if( !phdr )
|
||||
return; // bad model
|
||||
|
||||
#if !XASH_DEDICATED
|
||||
|
||||
@@ -258,7 +258,7 @@ model_t *Mod_LoadModel( model_t *mod, qboolean crash )
|
||||
{
|
||||
char tempname[MAX_QPATH];
|
||||
fs_offset_t length = 0;
|
||||
qboolean loaded, loaded2 = false;
|
||||
qboolean loaded;
|
||||
byte *buf;
|
||||
model_info_t *p;
|
||||
|
||||
@@ -279,7 +279,7 @@ model_t *Mod_LoadModel( model_t *mod, qboolean crash )
|
||||
|
||||
buf = FS_LoadFile( tempname, &length, false );
|
||||
|
||||
if( !buf || length < sizeof( uint ))
|
||||
if( !buf )
|
||||
{
|
||||
memset( mod, 0, sizeof( model_t ));
|
||||
|
||||
@@ -329,12 +329,11 @@ model_t *Mod_LoadModel( model_t *mod, qboolean crash )
|
||||
// let the server.dll load custom data
|
||||
svgame.physFuncs.Mod_ProcessUserData( mod, true, buf );
|
||||
}
|
||||
loaded2 = true;
|
||||
}
|
||||
#if !XASH_DEDICATED
|
||||
else
|
||||
{
|
||||
loaded2 = ref.dllFuncs.Mod_ProcessRenderData( mod, true, buf );
|
||||
loaded = ref.dllFuncs.Mod_ProcessRenderData( mod, true, buf );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -346,7 +345,7 @@ model_t *Mod_LoadModel( model_t *mod, qboolean crash )
|
||||
hdr->pposeverts = NULL;
|
||||
}
|
||||
|
||||
if( !loaded || !loaded2 )
|
||||
if( !loaded )
|
||||
{
|
||||
Mod_FreeModel( mod );
|
||||
Mem_Free( buf );
|
||||
@@ -611,41 +610,3 @@ void Mod_NeedCRC( const char *name, qboolean needCRC )
|
||||
if( needCRC ) SetBits( 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,177 +18,11 @@ GNU General Public License for more details.
|
||||
#include "net_buffer.h"
|
||||
#include "xash3d_mathlib.h"
|
||||
|
||||
static const uint32_t BitWriteMasks[32][32] =
|
||||
{ {
|
||||
0xfffffffe, 0xfffffffc, 0xfffffff8, 0xfffffff0, 0xffffffe0, 0xffffffc0, 0xffffff80, 0xffffff00,
|
||||
0xfffffe00, 0xfffffc00, 0xfffff800, 0xfffff000, 0xffffe000, 0xffffc000, 0xffff8000, 0xffff0000,
|
||||
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,
|
||||
};
|
||||
|
||||
// precalculated bit masks for WriteUBitLong.
|
||||
// Using these tables instead of doing the calculations
|
||||
// gives a 33% speedup in WriteUBitLong.
|
||||
static uint32_t BitWriteMasks[32][33];
|
||||
static uint32_t ExtraMasks[32];
|
||||
const char *const svc_strings[svc_lastmsg+1] =
|
||||
{
|
||||
"svc_bad",
|
||||
@@ -298,41 +132,65 @@ const char *const svc_quake_strings[svc_lastmsg+1] =
|
||||
[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 )
|
||||
{
|
||||
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 );
|
||||
Assert( numbits >= 0 && numbits <= 32 );
|
||||
|
||||
// bounds checking..
|
||||
if( MSG_Overflow( sb, numbits ))
|
||||
if(( sb->iCurBit + numbits ) > sb->nDataBits )
|
||||
{
|
||||
sb->bOverflow = true;
|
||||
sb->iCurBit = sb->nDataBits;
|
||||
return;
|
||||
}
|
||||
|
||||
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 )
|
||||
else
|
||||
{
|
||||
nBitsLeft -= nBitsWritten;
|
||||
iCurBit += nBitsWritten;
|
||||
curData >>= nBitsWritten;
|
||||
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+1] &= BitWriteMasks[iCurBitMasked][nBitsLeft-1];
|
||||
((uint32_t *)sb->pData)[iDWord+1] |= curData << iCurBitMasked;
|
||||
((uint32_t *)sb->pData)[iDWord] &= BitWriteMasks[iCurBitMasked][nBitsLeft];
|
||||
((uint32_t *)sb->pData)[iDWord] |= curData << iCurBitMasked;
|
||||
|
||||
// did it span a dword?
|
||||
nBitsWritten = 32 - iCurBitMasked;
|
||||
|
||||
if( nBitsWritten < nBitsLeft )
|
||||
{
|
||||
nBitsLeft -= nBitsWritten;
|
||||
iCurBit += nBitsWritten;
|
||||
curData >>= nBitsWritten;
|
||||
|
||||
iCurBitMasked = iCurBit & 31;
|
||||
((uint32_t *)sb->pData)[iDWord+1] &= BitWriteMasks[iCurBitMasked][nBitsLeft];
|
||||
((uint32_t *)sb->pData)[iDWord+1] |= curData << iCurBitMasked;
|
||||
}
|
||||
sb->iCurBit += numbits;
|
||||
}
|
||||
sb->iCurBit += numbits;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -380,7 +238,7 @@ qboolean MSG_WriteBits( sizebuf_t *sb, const void *pData, int nBits )
|
||||
int nBitsLeft = nBits;
|
||||
|
||||
// get output dword-aligned.
|
||||
while((( uintptr_t )pOut & 3 ) != 0 && nBitsLeft >= 8 )
|
||||
while((( uint32_t )pOut & 3 ) != 0 && nBitsLeft >= 8 )
|
||||
{
|
||||
MSG_WriteUBitLong( sb, *pOut, 8 );
|
||||
|
||||
@@ -417,14 +275,16 @@ qboolean MSG_WriteBits( sizebuf_t *sb, const void *pData, int nBits )
|
||||
|
||||
void MSG_WriteBitAngle( sizebuf_t *sb, float fAngle, int numbits )
|
||||
{
|
||||
const uint shift = ( 1 << numbits );
|
||||
const uint mask = shift - 1;
|
||||
uint mask, shift;
|
||||
int d;
|
||||
|
||||
// clamp the angle before receiving
|
||||
fAngle = fmod( fAngle, 360.0f );
|
||||
if( fAngle < 0 ) fAngle += 360.0f;
|
||||
|
||||
shift = ( 1 << numbits );
|
||||
mask = shift - 1;
|
||||
|
||||
d = (int)(( fAngle * shift ) / 360.0f );
|
||||
d &= mask;
|
||||
|
||||
@@ -578,8 +438,9 @@ uint MSG_ReadUBitLong( sizebuf_t *sb, int numbits )
|
||||
return 0; // end of message
|
||||
}
|
||||
|
||||
if( MSG_Overflow( sb, numbits ))
|
||||
if(( sb->iCurBit + numbits ) > sb->nDataBits )
|
||||
{
|
||||
sb->bOverflow = true;
|
||||
sb->iCurBit = sb->nDataBits;
|
||||
return 0;
|
||||
}
|
||||
@@ -652,9 +513,13 @@ qboolean MSG_ReadBits( sizebuf_t *sb, void *pOutData, int nBits )
|
||||
|
||||
float MSG_ReadBitAngle( sizebuf_t *sb, int numbits )
|
||||
{
|
||||
float shift = (float)( 1 << numbits );
|
||||
int i = MSG_ReadUBitLong( sb, numbits );
|
||||
float fReturn = (float)i * ( 360.0f / shift );
|
||||
float fReturn, shift;
|
||||
int i;
|
||||
|
||||
shift = (float)( 1 << numbits );
|
||||
|
||||
i = MSG_ReadUBitLong( sb, numbits );
|
||||
fReturn = (float)i * ( 360.0f / shift );
|
||||
|
||||
// clamp the finale angle
|
||||
if( fReturn < -180.0f ) fReturn += 360.0f;
|
||||
@@ -666,11 +531,11 @@ float MSG_ReadBitAngle( sizebuf_t *sb, int numbits )
|
||||
// Append numbits least significant bits from data to the current bit stream
|
||||
int MSG_ReadSBitLong( sizebuf_t *sb, int numbits )
|
||||
{
|
||||
int r;
|
||||
int r, sign;
|
||||
|
||||
if( sb->iAlternateSign )
|
||||
{
|
||||
int sign = MSG_ReadOneBit( sb );
|
||||
sign = MSG_ReadOneBit( sb );
|
||||
r = MSG_ReadUBitLong( sb, numbits - 1 );
|
||||
|
||||
if( sign )
|
||||
@@ -679,7 +544,9 @@ int MSG_ReadSBitLong( sizebuf_t *sb, int numbits )
|
||||
else
|
||||
{
|
||||
r = MSG_ReadUBitLong( sb, numbits - 1 );
|
||||
if( MSG_ReadOneBit( sb ))
|
||||
sign = MSG_ReadOneBit( sb );
|
||||
|
||||
if( sign )
|
||||
r = -( BIT( numbits - 1 ) - r );
|
||||
}
|
||||
|
||||
@@ -800,12 +667,12 @@ qboolean MSG_ReadBytes( sizebuf_t *sb, void *pOut, int nBytes )
|
||||
static char *MSG_ReadStringExt( sizebuf_t *sb, qboolean bLine )
|
||||
{
|
||||
static char string[4096];
|
||||
int l = 0;
|
||||
int l = 0, c;
|
||||
|
||||
do
|
||||
{
|
||||
// use MSG_ReadByte so -1 is out of bounds
|
||||
int c = MSG_ReadByte( sb );
|
||||
c = MSG_ReadByte( sb );
|
||||
|
||||
if( c == 0 ) break;
|
||||
else if( bLine && c == '\n' )
|
||||
@@ -998,6 +865,8 @@ static void Test_Buffer_ExciseBits( void )
|
||||
|
||||
void Test_RunBuffer( void )
|
||||
{
|
||||
MSG_InitMasks();
|
||||
|
||||
TRUN( Test_Buffer_BitByte( ));
|
||||
TRUN( Test_Buffer_Write( ));
|
||||
TRUN( Test_Buffer_Read( ));
|
||||
|
||||
@@ -193,6 +193,7 @@ static inline void MSG_StartBitWriting( sizebuf_t *sb )
|
||||
sb->iAlternateSign++;
|
||||
}
|
||||
|
||||
void MSG_InitMasks( void ); // called once at startup engine
|
||||
void MSG_ExciseBits( sizebuf_t *sb, int startbit, int bitstoremove );
|
||||
|
||||
// Bit-write functions
|
||||
|
||||
@@ -272,6 +272,8 @@ void Netchan_Init( void )
|
||||
Cvar_FullSet( net_qport.name, buf, net_qport.flags );
|
||||
|
||||
net_mempool = Mem_AllocPool( "Network Pool" );
|
||||
|
||||
MSG_InitMasks(); // initialize bit-masks
|
||||
}
|
||||
|
||||
void Netchan_Shutdown( void )
|
||||
@@ -341,7 +343,6 @@ void Netchan_Setup( netsrc_t sock, netchan_t *chan, netadr_t adr, int qport, voi
|
||||
chan->split = FBitSet( flags, NETCHAN_USE_LEGACY_SPLIT ) ? true : false;
|
||||
chan->use_munge = FBitSet( flags, NETCHAN_USE_MUNGE ) ? 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;
|
||||
|
||||
MSG_Init( &chan->message, "NetData", chan->message_buf, sizeof( chan->message_buf ));
|
||||
@@ -767,7 +768,7 @@ static void Netchan_CreateFragments_( netchan_t *chan, sizebuf_t *msg )
|
||||
Host_Error( "%s: BZ2 compression is not supported for server", __func__ );
|
||||
#endif
|
||||
}
|
||||
else if( chan->use_lzss && !LZSS_IsCompressed( MSG_GetData( msg ), MSG_GetMaxBytes( msg )))
|
||||
else if( !chan->use_bz2 && !LZSS_IsCompressed( MSG_GetData( msg ), MSG_GetMaxBytes( msg )))
|
||||
{
|
||||
uint uCompressedSize = 0;
|
||||
uint uSourceSize = MSG_GetNumBytesWritten( msg );
|
||||
@@ -1174,7 +1175,7 @@ qboolean Netchan_CopyNormalFragments( netchan_t *chan, sizebuf_t *msg, size_t *l
|
||||
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
|
||||
byte buf[0x10000];
|
||||
@@ -1195,7 +1196,7 @@ qboolean Netchan_CopyNormalFragments( netchan_t *chan, sizebuf_t *msg, size_t *l
|
||||
Host_Error( "%s: BZ2 compression is not supported for server\n", __func__ );
|
||||
#endif
|
||||
}
|
||||
else if( chan->use_lzss && LZSS_IsCompressed( MSG_GetData( msg ), size ))
|
||||
else if( !chan->use_bz2 && LZSS_IsCompressed( MSG_GetData( msg ), size ))
|
||||
{
|
||||
uint uDecompressedLen = LZSS_GetActualSize( MSG_GetData( msg ), size );
|
||||
byte buf[NET_MAX_MESSAGE];
|
||||
@@ -1346,7 +1347,7 @@ qboolean Netchan_CopyFileFragments( netchan_t *chan, sizebuf_t *msg )
|
||||
Host_Error( "%s: BZ2 compression is not supported for server", __func__ );
|
||||
#endif
|
||||
}
|
||||
else if( chan->use_lzss && LZSS_IsCompressed( buffer, nsize + 1 ))
|
||||
else if( LZSS_IsCompressed( buffer, nsize + 1 ))
|
||||
{
|
||||
byte *uncompressedBuffer;
|
||||
|
||||
|
||||
@@ -2282,6 +2282,10 @@ void Test_RunDelta( void )
|
||||
char buffer[4096] = { 0 };
|
||||
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_timewindow_big", DT_TIMEWINDOW_BIG, 24, 1000.f, 1.0f );
|
||||
Delta_AddField( dt, "dt_timewindow_8", DT_TIMEWINDOW_8, 8, 1.0f, 1.0f );
|
||||
|
||||
@@ -505,14 +505,11 @@ static int HTTP_FileDecompress( httpfile_t *file )
|
||||
|
||||
if( zlib_result == Z_OK || zlib_result == Z_STREAM_END )
|
||||
{
|
||||
g_fsapi.WriteFile( name, data_out, decompressed_len );
|
||||
HTTP_FreeFile( file, false );
|
||||
Mem_Free( data_in );
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -844,16 +841,7 @@ static int HTTP_FileProcessStream( httpfile_t *curfile )
|
||||
|
||||
if( curfile->downloaded >= curfile->size )
|
||||
{
|
||||
// chunked files are finalized in FileSaveReceivedData
|
||||
if( curfile->compressed && !curfile->chunked )
|
||||
{
|
||||
curfile->pfn_process = HTTP_FileDecompress;
|
||||
curfile->success = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
HTTP_FreeFile( curfile, false ); // success
|
||||
}
|
||||
HTTP_FreeFile( curfile, false ); // success
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -151,24 +151,17 @@ static inline qboolean NET_IsSocketValid( int socket )
|
||||
|
||||
void NET_NetadrToIP6Bytes( uint8_t *ip6, const netadr_t *adr )
|
||||
{
|
||||
memcpy( &ip6[0], adr->ip6_0, 2 );
|
||||
memcpy( &ip6[2], adr->ip6_1, 14 );
|
||||
memcpy( ip6, adr->ip6, sizeof( adr->ip6 ));
|
||||
}
|
||||
|
||||
void NET_IP6BytesToNetadr( netadr_t *adr, const uint8_t *ip6 )
|
||||
{
|
||||
memcpy( adr->ip6_0, &ip6[0], 2 );
|
||||
memcpy( adr->ip6_1, &ip6[2], 14 );
|
||||
memcpy( adr->ip6, ip6, sizeof( adr->ip6 ));
|
||||
}
|
||||
|
||||
static int NET_NetadrIP6Compare( const netadr_t *a, const netadr_t *b )
|
||||
{
|
||||
uint8_t ip6_a[16], ip6_b[16];
|
||||
|
||||
NET_NetadrToIP6Bytes( ip6_a, a );
|
||||
NET_NetadrToIP6Bytes( ip6_b, b );
|
||||
|
||||
return memcmp( ip6_a, ip6_b, sizeof( ip6_a ));
|
||||
return memcmp( a->ip6, b->ip6, sizeof( a->ip6 ));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -178,29 +171,27 @@ NET_NetadrToSockadr
|
||||
*/
|
||||
static void NET_NetadrToSockadr( netadr_t *a, struct sockaddr_storage *s )
|
||||
{
|
||||
netadrtype_t type = NET_NetadrType( a );
|
||||
|
||||
memset( s, 0, sizeof( *s ));
|
||||
|
||||
if( type == NA_BROADCAST )
|
||||
if( a->type == NA_BROADCAST )
|
||||
{
|
||||
s->ss_family = AF_INET;
|
||||
((struct sockaddr_in *)s)->sin_port = a->port;
|
||||
((struct sockaddr_in *)s)->sin_addr.s_addr = INADDR_BROADCAST;
|
||||
}
|
||||
else if( type == NA_IP )
|
||||
else if( a->type == NA_IP )
|
||||
{
|
||||
s->ss_family = AF_INET;
|
||||
((struct sockaddr_in *)s)->sin_port = a->port;
|
||||
((struct sockaddr_in *)s)->sin_addr.s_addr = a->ip4;
|
||||
}
|
||||
else if( type == NA_IP6 )
|
||||
else if( a->type6 == NA_IP6 )
|
||||
{
|
||||
s->ss_family = AF_INET6;
|
||||
((struct sockaddr_in6 *)s)->sin6_port = a->port;
|
||||
NET_NetadrToIP6Bytes(((struct sockaddr_in6 *)s)->sin6_addr.s6_addr, a );
|
||||
}
|
||||
else if( type == NA_MULTICAST_IP6 )
|
||||
else if( a->type6 == NA_MULTICAST_IP6 )
|
||||
{
|
||||
s->ss_family = AF_INET6;
|
||||
((struct sockaddr_in6 *)s)->sin6_port = a->port;
|
||||
@@ -217,13 +208,13 @@ static void NET_SockadrToNetadr( const struct sockaddr_storage *s, netadr_t *a )
|
||||
{
|
||||
if( s->ss_family == AF_INET )
|
||||
{
|
||||
NET_NetadrSetType( a, NA_IP );
|
||||
a->type = NA_IP;
|
||||
a->ip4 = ((struct sockaddr_in *)s)->sin_addr.s_addr;
|
||||
a->port = ((struct sockaddr_in *)s)->sin_port;
|
||||
}
|
||||
else if( s->ss_family == AF_INET6 )
|
||||
{
|
||||
NET_NetadrSetType( a, NA_IP6 );
|
||||
a->type6 = NA_IP6;
|
||||
NET_IP6BytesToNetadr( a, ((struct sockaddr_in6 *)s)->sin6_addr.s6_addr );
|
||||
a->port = ((struct sockaddr_in6 *)s)->sin6_port;
|
||||
}
|
||||
@@ -558,8 +549,8 @@ qboolean NET_StringToFilterAdr( const char *s, netadr_t *adr, uint *prefixlen )
|
||||
// try to parse as IPv6 first
|
||||
if( ParseIPv6Addr( copy, ip6, NULL, NULL ))
|
||||
{
|
||||
NET_NetadrSetType( adr, NA_IP6 );
|
||||
NET_IP6BytesToNetadr( adr, ip6 );
|
||||
adr->type6 = NA_IP6;
|
||||
|
||||
if( !hasCIDR )
|
||||
*prefixlen = 128;
|
||||
@@ -629,7 +620,7 @@ qboolean NET_StringToFilterAdr( const char *s, netadr_t *adr, uint *prefixlen )
|
||||
adr->ip4 = ntohl( mask );
|
||||
}
|
||||
|
||||
NET_NetadrSetType( adr, NA_IP );
|
||||
adr->type = NA_IP;
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -643,11 +634,10 @@ NET_AdrToString
|
||||
const char *NET_AdrToString( const netadr_t a )
|
||||
{
|
||||
static char s[64];
|
||||
netadrtype_t type = NET_NetadrType( &a );
|
||||
|
||||
if( type == NA_LOOPBACK )
|
||||
if( a.type == NA_LOOPBACK )
|
||||
return "loopback";
|
||||
if( type == NA_IP6 || type == NA_MULTICAST_IP6 )
|
||||
if( a.type6 == NA_IP6 || a.type6 == NA_MULTICAST_IP6 )
|
||||
{
|
||||
uint8_t ip6[16];
|
||||
|
||||
@@ -671,11 +661,10 @@ NET_BaseAdrToString
|
||||
const char *NET_BaseAdrToString( const netadr_t a )
|
||||
{
|
||||
static char s[64];
|
||||
netadrtype_t type = NET_NetadrType( &a );
|
||||
|
||||
if( type == NA_LOOPBACK )
|
||||
if( a.type == NA_LOOPBACK )
|
||||
return "loopback";
|
||||
if( type == NA_IP6 || type == NA_MULTICAST_IP6 )
|
||||
if( a.type6 == NA_IP6 || a.type6 == NA_MULTICAST_IP6 )
|
||||
{
|
||||
uint8_t ip6[16];
|
||||
|
||||
@@ -700,19 +689,16 @@ Compares without the port
|
||||
*/
|
||||
qboolean NET_CompareBaseAdr( const netadr_t a, const netadr_t b )
|
||||
{
|
||||
netadrtype_t type_a = NET_NetadrType( &a );
|
||||
netadrtype_t type_b = NET_NetadrType( &b );
|
||||
|
||||
if( type_a != type_b )
|
||||
if( a.type6 != b.type6 )
|
||||
return false;
|
||||
|
||||
if( type_a == NA_LOOPBACK )
|
||||
if( a.type == NA_LOOPBACK )
|
||||
return true;
|
||||
|
||||
if( type_a == NA_IP )
|
||||
if( a.type == NA_IP )
|
||||
return a.ip4 == b.ip4;
|
||||
|
||||
if( type_a == NA_IP6 )
|
||||
if( a.type6 == NA_IP6 )
|
||||
{
|
||||
if( !NET_NetadrIP6Compare( &a, &b ))
|
||||
return true;
|
||||
@@ -721,6 +707,36 @@ qboolean NET_CompareBaseAdr( const netadr_t a, const netadr_t b )
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
NET_CompareClassBAdr
|
||||
|
||||
Compare local masks
|
||||
====================
|
||||
*/
|
||||
qboolean NET_CompareClassBAdr( const netadr_t a, const netadr_t b )
|
||||
{
|
||||
if( a.type6 != b.type6 )
|
||||
return false;
|
||||
|
||||
if( a.type == NA_LOOPBACK )
|
||||
return true;
|
||||
|
||||
if( a.type == NA_IP )
|
||||
{
|
||||
if( a.ip[0] == b.ip[0] && a.ip[1] == b.ip[1] )
|
||||
return true;
|
||||
}
|
||||
|
||||
// NOTE: we don't check for IPv6 here
|
||||
// this check is very dumb and only used for LAN restriction
|
||||
// Actual check is in IsReservedAdr
|
||||
|
||||
// for real mask compare use NET_CompareAdrByMask
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
NET_CompareAdrByMask
|
||||
@@ -730,13 +746,10 @@ Checks if adr is a part of subnet
|
||||
*/
|
||||
qboolean NET_CompareAdrByMask( const netadr_t a, const netadr_t b, uint prefixlen )
|
||||
{
|
||||
netadrtype_t type_a = NET_NetadrType( &a );
|
||||
netadrtype_t type_b = NET_NetadrType( &b );
|
||||
|
||||
if( type_a != type_b || type_a == NA_LOOPBACK )
|
||||
if( a.type6 != b.type6 || a.type == NA_LOOPBACK )
|
||||
return false;
|
||||
|
||||
if( type_a == NA_IP )
|
||||
if( a.type == NA_IP )
|
||||
{
|
||||
uint32_t ipa = htonl( a.ip4 );
|
||||
uint32_t ipb = htonl( b.ip4 );
|
||||
@@ -744,7 +757,7 @@ qboolean NET_CompareAdrByMask( const netadr_t a, const netadr_t b, uint prefixle
|
||||
if(( ipa & (( 0xFFFFFFFFU ) << ( 32 - prefixlen ))) == ipb )
|
||||
return true;
|
||||
}
|
||||
else if( type_a == NA_IP6 )
|
||||
else if( a.type6 == NA_IP6 )
|
||||
{
|
||||
uint16_t a_[8], b_[8];
|
||||
size_t check = prefixlen / 16;
|
||||
@@ -785,13 +798,11 @@ Check for reserved ip's
|
||||
*/
|
||||
qboolean NET_IsReservedAdr( netadr_t a )
|
||||
{
|
||||
netadrtype_t type_a = NET_NetadrType( &a );
|
||||
|
||||
if( type_a == NA_LOOPBACK )
|
||||
if( a.type == NA_LOOPBACK )
|
||||
return true;
|
||||
|
||||
// Following checks was imported from GameNetworkingSockets library
|
||||
if( type_a == NA_IP )
|
||||
if( a.type == NA_IP )
|
||||
{
|
||||
if(( a.ip[0] == 10 ) || // 10.x.x.x is reserved
|
||||
( a.ip[0] == 127 ) || // 127.x.x.x
|
||||
@@ -803,7 +814,7 @@ qboolean NET_IsReservedAdr( netadr_t a )
|
||||
}
|
||||
}
|
||||
|
||||
if( type_a == NA_IP6 )
|
||||
if( a.type6 == NA_IP6 )
|
||||
{
|
||||
uint8_t ip6[16];
|
||||
|
||||
@@ -836,23 +847,20 @@ Compare full address
|
||||
*/
|
||||
qboolean NET_CompareAdr( const netadr_t a, const netadr_t b )
|
||||
{
|
||||
netadrtype_t type_a = NET_NetadrType( &a );
|
||||
netadrtype_t type_b = NET_NetadrType( &b );
|
||||
|
||||
if( type_a != type_b )
|
||||
if( a.type6 != b.type6 )
|
||||
return false;
|
||||
|
||||
if( type_a == NA_LOOPBACK )
|
||||
if( a.type == NA_LOOPBACK )
|
||||
return true;
|
||||
|
||||
if( type_a == NA_IP )
|
||||
if( a.type == NA_IP )
|
||||
{
|
||||
if( a.ip4 == b.ip4 && a.port == b.port )
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
if( type_a == NA_IP6 )
|
||||
if( a.type6 == NA_IP6 )
|
||||
{
|
||||
if( a.port == b.port && !NET_NetadrIP6Compare( &a, &b ))
|
||||
return true;
|
||||
@@ -875,13 +883,9 @@ int NET_CompareAdrSort( const void *_a, const void *_b )
|
||||
{
|
||||
const netadr_t *a = _a, *b = _b;
|
||||
int porta, portb, portdiff, addrdiff;
|
||||
netadrtype_t type_a, type_b;
|
||||
|
||||
type_a = NET_NetadrType( a );
|
||||
type_b = NET_NetadrType( b );
|
||||
|
||||
if( type_a != type_b )
|
||||
return bound( -1, (int)type_a - (int)type_b, 1 );
|
||||
if( a->type6 != b->type6 )
|
||||
return bound( -1, (int)a->type6 - (int)b->type6, 1 );
|
||||
|
||||
porta = ntohs( a->port );
|
||||
portb = ntohs( b->port );
|
||||
@@ -892,7 +896,7 @@ int NET_CompareAdrSort( const void *_a, const void *_b )
|
||||
else
|
||||
portdiff = 0;
|
||||
|
||||
switch( type_a )
|
||||
switch( a->type6 )
|
||||
{
|
||||
case NA_IP6:
|
||||
if(( addrdiff = NET_NetadrIP6Compare( a, b )))
|
||||
@@ -900,7 +904,14 @@ int NET_CompareAdrSort( const void *_a, const void *_b )
|
||||
// fallthrough
|
||||
case NA_MULTICAST_IP6:
|
||||
return portdiff;
|
||||
}
|
||||
|
||||
// don't check for full type earlier, as it's value depends on v6 address
|
||||
if( a->type != b->type )
|
||||
return bound( -1, (int)a->type - (int)b->type, 1 );
|
||||
|
||||
switch( a->type )
|
||||
{
|
||||
case NA_IP:
|
||||
if(( addrdiff = memcmp( a->ip, b->ip, sizeof( a->ipx ))))
|
||||
return addrdiff;
|
||||
@@ -935,7 +946,7 @@ static qboolean NET_StringToAdrEx( const char *string, netadr_t *adr, int family
|
||||
|
||||
if( !Q_stricmp( string, "localhost" ) || !Q_stricmp( string, "loopback" ))
|
||||
{
|
||||
NET_NetadrSetType( adr, NA_LOOPBACK );
|
||||
adr->type = NA_LOOPBACK;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -960,7 +971,7 @@ net_gai_state_t NET_StringToAdrNB( const char *string, netadr_t *adr, qboolean v
|
||||
|
||||
if( !Q_stricmp( string, "localhost" ) || !Q_stricmp( string, "loopback" ))
|
||||
{
|
||||
NET_NetadrSetType( adr, NA_LOOPBACK );
|
||||
adr->type = NA_LOOPBACK;
|
||||
return NET_EAI_OK;
|
||||
}
|
||||
|
||||
@@ -1006,7 +1017,7 @@ static qboolean NET_GetLoopPacket( netsrc_t sock, netadr_t *from, byte *data, si
|
||||
*length = loop->msgs[i].datalen;
|
||||
|
||||
memset( from, 0, sizeof( *from ));
|
||||
NET_NetadrSetType( from, NA_LOOPBACK );
|
||||
from->type = NA_LOOPBACK;
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -1512,7 +1523,7 @@ static int NET_SendLong( netsrc_t sock, int net_socket, const char *buf, size_t
|
||||
total_sent += size;
|
||||
len -= size;
|
||||
packet_number++;
|
||||
Platform_NanoSleep( 100 * 1000 );
|
||||
Platform_Sleep( 1 );
|
||||
}
|
||||
|
||||
return total_sent;
|
||||
@@ -1535,20 +1546,19 @@ void NET_SendPacketEx( netsrc_t sock, size_t length, const void *data, netadr_t
|
||||
int ret;
|
||||
struct sockaddr_storage addr = { 0 };
|
||||
SOCKET net_socket = 0;
|
||||
netadrtype_t type = NET_NetadrType( &to );
|
||||
|
||||
if( !net.initialized || type == NA_LOOPBACK )
|
||||
if( !net.initialized || to.type == NA_LOOPBACK )
|
||||
{
|
||||
NET_SendLoopPacket( sock, length, data, to );
|
||||
return;
|
||||
}
|
||||
else if( type == NA_BROADCAST || type == NA_IP )
|
||||
else if( to.type == NA_BROADCAST || to.type == NA_IP )
|
||||
{
|
||||
net_socket = net.ip_sockets[sock];
|
||||
if( !NET_IsSocketValid( net_socket ))
|
||||
return;
|
||||
}
|
||||
else if( type == NA_MULTICAST_IP6 || type == NA_IP6 )
|
||||
else if( to.type6 == NA_MULTICAST_IP6 || to.type6 == NA_IP6 )
|
||||
{
|
||||
net_socket = net.ip6_sockets[sock];
|
||||
if( !NET_IsSocketValid( net_socket ))
|
||||
@@ -1556,7 +1566,7 @@ void NET_SendPacketEx( netsrc_t sock, size_t length, const void *data, netadr_t
|
||||
}
|
||||
else
|
||||
{
|
||||
Host_Error( "%s: bad address type %i (%i, %i)\n", __func__, to.type, to.ip6_0[0], to.ip6_0[1] );
|
||||
Host_Error( "%s: bad address type %i (%i)\n", __func__, to.type, to.type6 );
|
||||
}
|
||||
|
||||
NET_NetadrToSockadr( &to, &addr );
|
||||
@@ -1572,7 +1582,7 @@ void NET_SendPacketEx( netsrc_t sock, size_t length, const void *data, netadr_t
|
||||
return;
|
||||
|
||||
// some PPP links don't allow broadcasts
|
||||
if( err == WSAEADDRNOTAVAIL && ( type == NA_BROADCAST || type == NA_MULTICAST_IP6 ))
|
||||
if( err == WSAEADDRNOTAVAIL && ( to.type == NA_BROADCAST || to.type6 == NA_MULTICAST_IP6 ))
|
||||
return;
|
||||
|
||||
if( Host_IsDedicated( ))
|
||||
@@ -2027,7 +2037,6 @@ void NET_Init( void )
|
||||
Cvar_RegisterVariable( &net_fakelag );
|
||||
Cvar_RegisterVariable( &net_fakeloss );
|
||||
Cvar_RegisterVariable( &net_resolve_debug );
|
||||
Cvar_RegisterVariable( &net_clockwindow );
|
||||
|
||||
Q_snprintf( cmd, sizeof( cmd ), "%i", PORT_SERVER );
|
||||
Cvar_FullSet( "hostport", cmd, FCVAR_READ_ONLY );
|
||||
|
||||
@@ -64,6 +64,7 @@ void NET_Config( qboolean net_enable, qboolean changeport );
|
||||
const char *NET_AdrToString( const netadr_t a ) RETURNS_NONNULL;
|
||||
const char *NET_BaseAdrToString( const netadr_t a ) RETURNS_NONNULL;
|
||||
qboolean NET_IsReservedAdr( netadr_t a );
|
||||
qboolean NET_CompareClassBAdr( const netadr_t a, const netadr_t b );
|
||||
qboolean NET_StringToAdr( const char *string, netadr_t *adr );
|
||||
qboolean NET_StringToFilterAdr( const char *s, netadr_t *adr, uint *prefixlen );
|
||||
net_gai_state_t NET_StringToAdrNB( const char *string, netadr_t *adr, qboolean v6only );
|
||||
@@ -79,7 +80,7 @@ void NET_NetadrToIP6Bytes( uint8_t *ip6, const netadr_t *adr );
|
||||
|
||||
static inline qboolean NET_IsLocalAddress( netadr_t adr )
|
||||
{
|
||||
return NET_NetadrType( &adr ) == NA_LOOPBACK;
|
||||
return adr.type == NA_LOOPBACK ? true : false;
|
||||
}
|
||||
|
||||
#if !XASH_DEDICATED
|
||||
|
||||
@@ -69,6 +69,7 @@ GNU General Public License for more details.
|
||||
// bytes will be stripped by the networking channel layer
|
||||
#define NET_MAX_MESSAGE PAD_NUMBER(( NET_MAX_PAYLOAD + HEADER_BYTES ), 16 )
|
||||
|
||||
#define MASTERSERVER_ADR "mentality.rip:27010"
|
||||
#define MS_SCAN_REQUEST "1\xFF" "0.0.0.0:0\0"
|
||||
|
||||
#define PORT_MASTER 27010
|
||||
@@ -213,7 +214,6 @@ typedef enum netchan_flags_e
|
||||
NETCHAN_USE_MUNGE = BIT( 1 ),
|
||||
NETCHAN_USE_BZIP2 = BIT( 2 ),
|
||||
NETCHAN_GOLDSRC = BIT( 3 ),
|
||||
NETCHAN_USE_LZSS = BIT( 4 ), // mutually exclusive with bzip2
|
||||
} netchan_flags_t;
|
||||
|
||||
// Network Connection Channel
|
||||
@@ -285,7 +285,6 @@ typedef struct netchan_s
|
||||
qboolean split;
|
||||
qboolean use_munge;
|
||||
qboolean use_bz2;
|
||||
qboolean use_lzss;
|
||||
qboolean gs_netchan;
|
||||
} netchan_t;
|
||||
|
||||
|
||||
@@ -89,6 +89,16 @@ void Sound_Shutdown( void )
|
||||
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 )
|
||||
{
|
||||
string name;
|
||||
@@ -368,7 +378,6 @@ static qboolean Sound_ResampleInternal( wavdata_t *sc, int outrate, int outwidth
|
||||
const int inwidth = sc->width;
|
||||
const int inchannels = sc->channels;
|
||||
const int incount = sc->samples;
|
||||
const int insize = sc->size;
|
||||
qboolean handled = false;
|
||||
double stepscale;
|
||||
double t1, t2;
|
||||
@@ -422,30 +431,22 @@ static qboolean Sound_ResampleInternal( wavdata_t *sc, int outrate, int outwidth
|
||||
else // upsample case, w/ interpolation
|
||||
handled = Sound_ConvertUpsample( sc, inwidth, inchannels, incount, outwidth, outchannels, outcount, stepscale );
|
||||
|
||||
if( !handled )
|
||||
{
|
||||
// restore previously changed data
|
||||
sc->rate = inrate;
|
||||
sc->width = inwidth;
|
||||
sc->channels = inchannels;
|
||||
sc->samples = incount;
|
||||
sc->size = insize;
|
||||
t2 = Sys_DoubleTime();
|
||||
|
||||
if( handled )
|
||||
{
|
||||
if( t2 - t1 > 0.01f ) // critical, report to mod developer
|
||||
Con_Printf( S_WARN "%s: from [%d bit %d Hz %dch] to [%d bit %d Hz %dch] (took %.3fs)\n", __func__, inwidth * 8, inrate, inchannels, outwidth * 8, outrate, outchannels, t2 - t1 );
|
||||
else
|
||||
Con_Reportf( "%s: from [%d bit %d Hz %dch] to [%d bit %d Hz %dch] (took %.3fs)\n", __func__, inwidth * 8, inrate, inchannels, outwidth * 8, outrate, outchannels, t2 - t1 );
|
||||
}
|
||||
else
|
||||
Con_Printf( S_ERROR "%s: unsupported from [%d bit %d Hz %dch] to [%d bit %d Hz %dch]\n", __func__, inwidth * 8, inrate, inchannels, outwidth * 8, outrate, outchannels );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
t2 = Sys_DoubleTime();
|
||||
sc->rate = outrate;
|
||||
sc->width = outwidth;
|
||||
|
||||
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;
|
||||
return handled;
|
||||
}
|
||||
|
||||
qboolean Sound_Process( wavdata_t **wav, int rate, int width, int channels, uint flags )
|
||||
@@ -463,11 +464,8 @@ qboolean Sound_Process( wavdata_t **wav, int rate, int width, int channels, uint
|
||||
|
||||
if( result )
|
||||
{
|
||||
snd = Mem_Realloc( host.soundpool, snd, sizeof( *snd ) + snd->size );
|
||||
memcpy( snd->buffer, sound.tempbuffer, snd->size );
|
||||
|
||||
Mem_Free( sound.tempbuffer );
|
||||
sound.tempbuffer = NULL;
|
||||
Mem_Free( snd->buffer ); // free original image buffer
|
||||
snd->buffer = Sound_Copy( snd->size ); // unzone buffer
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -31,14 +31,15 @@ GNU General Public License for more details.
|
||||
#define XASH_COLORIZE_CONSOLE 0
|
||||
#endif
|
||||
|
||||
static struct logdata_s {
|
||||
char title[64];
|
||||
qboolean log_active;
|
||||
qboolean log_time;
|
||||
char log_path[MAX_SYSPATH];
|
||||
FILE *logfile;
|
||||
int logfileno;
|
||||
} s_ld;
|
||||
typedef struct {
|
||||
char title[64];
|
||||
qboolean log_active;
|
||||
char log_path[MAX_SYSPATH];
|
||||
FILE *logfile;
|
||||
int logfileno;
|
||||
} LogData;
|
||||
|
||||
static LogData s_ld;
|
||||
|
||||
void Sys_DestroyConsole( void )
|
||||
{
|
||||
@@ -77,19 +78,14 @@ static void Sys_FlushLogfile( void )
|
||||
|
||||
void Sys_InitLog( void )
|
||||
{
|
||||
const char *mode;
|
||||
const char *mode;
|
||||
|
||||
if( Sys_CheckParm( "-log" ))
|
||||
if( Sys_CheckParm( "-log" ) && host.allow_console != 0 )
|
||||
{
|
||||
if( !Sys_GetParmFromCmdLine( "-log", s_ld.log_path ) || !isalnum( s_ld.log_path[0] ))
|
||||
Q_strncpy( s_ld.log_path, "engine.log", sizeof( s_ld.log_path ));
|
||||
|
||||
COM_DefaultExtension( s_ld.log_path, ".log", sizeof( s_ld.log_path ));
|
||||
s_ld.log_active = true;
|
||||
Q_strncpy( s_ld.log_path, "engine.log", sizeof( s_ld.log_path ));
|
||||
}
|
||||
|
||||
s_ld.log_time = Sys_CheckParm( "-logtime" );
|
||||
|
||||
if( host.change_game && host.type != HOST_DEDICATED )
|
||||
mode = "a";
|
||||
else mode = "w";
|
||||
@@ -105,7 +101,7 @@ void Sys_InitLog( void )
|
||||
|
||||
if ( !s_ld.logfile )
|
||||
{
|
||||
Con_Reportf( S_ERROR "%s: can't create log file %s: %s\n", __func__, s_ld.log_path, strerror( errno ));
|
||||
Con_Reportf( S_ERROR "Sys_InitLog: can't create log file %s: %s\n", s_ld.log_path, strerror( errno ));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -299,23 +295,17 @@ void Sys_PrintLog( const char *pMsg )
|
||||
// save last char to detect when line was not ended
|
||||
lastchar = len > 0 ? pMsg[len - 1] : 0;
|
||||
|
||||
// spew to engine.log
|
||||
if( s_ld.logfile )
|
||||
{
|
||||
if( s_ld.log_time && print_time )
|
||||
{
|
||||
logtime_len = strftime( logtime, sizeof( logtime ), "[%Y:%m:%d|%H:%M:%S] ", crt_tm ); //full time
|
||||
logtime_len = Q_min( logtime_len, sizeof( logtime ) - 1 ); // just in case
|
||||
}
|
||||
else
|
||||
{
|
||||
logtime[0] = '\0';
|
||||
logtime_len = 0;
|
||||
}
|
||||
if( !s_ld.logfile )
|
||||
return;
|
||||
|
||||
Sys_PrintLogfile( s_ld.logfileno, logtime, logtime_len, pMsg, false );
|
||||
Sys_FlushLogfile();
|
||||
if( print_time )
|
||||
{
|
||||
logtime_len = strftime( logtime, sizeof( logtime ), "[%Y:%m:%d|%H:%M:%S] ", crt_tm ); //full time
|
||||
logtime_len = Q_min( logtime_len, sizeof( logtime ) - 1 ); // just in case
|
||||
}
|
||||
|
||||
Sys_PrintLogfile( s_ld.logfileno, logtime, logtime_len, pMsg, false );
|
||||
Sys_FlushLogfile();
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -41,15 +41,6 @@ NOTE: never change this structure because all dll descriptions in xash code
|
||||
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;
|
||||
double Sys_DoubleTime( void );
|
||||
char *Sys_GetClipboardData( void );
|
||||
|
||||
@@ -68,13 +68,7 @@ extern "C" {
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
#if (_MSC_VER >= 1900)
|
||||
#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)
|
||||
{
|
||||
@@ -249,11 +243,6 @@ int WAI_PREFIX(getExecutablePath)(char* out, int capacity, int* dirname_length)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if !defined(WAI_STRINGIZE)
|
||||
#define WAI_STRINGIZE(s)
|
||||
#define WAI_STRINGIZE_(s) #s
|
||||
#endif
|
||||
|
||||
#if defined(__ANDROID__) || defined(ANDROID)
|
||||
#include <fcntl.h>
|
||||
#include <sys/mman.h>
|
||||
@@ -276,20 +265,20 @@ int WAI_PREFIX(getModulePath)(char* out, int capacity, int* dirname_length)
|
||||
|
||||
for (;;)
|
||||
{
|
||||
char buffer[128 + PATH_MAX];
|
||||
uintptr_t low, high;
|
||||
char buffer[PATH_MAX < 1024 ? 1024 : PATH_MAX];
|
||||
uint64_t low, high;
|
||||
char perms[5];
|
||||
uint64_t offset;
|
||||
uint32_t major, minor, inode;
|
||||
char path[PATH_MAX + 1];
|
||||
uint32_t major, minor;
|
||||
char path[PATH_MAX];
|
||||
uint32_t inode;
|
||||
|
||||
if (!fgets(buffer, sizeof(buffer), maps))
|
||||
break;
|
||||
|
||||
if (sscanf(buffer, "%" SCNxPTR "-%" SCNxPTR " %s %" SCNx64 " %x:%x %u %" WAI_STRINGIZE(PATH_MAX) "[^\n]\n", &low, &high, perms, &offset, &major, &minor, &inode, path) == 8)
|
||||
if (sscanf(buffer, "%" PRIx64 "-%" PRIx64 " %s %" PRIx64 " %x:%x %u %s\n", &low, &high, perms, &offset, &major, &minor, &inode, path) == 8)
|
||||
{
|
||||
void* _addr = WAI_RETURN_ADDRESS();
|
||||
uintptr_t addr = (uintptr_t)_addr;
|
||||
uint64_t addr = (uintptr_t)WAI_RETURN_ADDRESS();
|
||||
if (low <= addr && addr <= high)
|
||||
{
|
||||
char* resolved;
|
||||
|
||||
@@ -31,8 +31,7 @@ extern "C" {
|
||||
* @param out destination buffer, optional
|
||||
* @param capacity destination buffer capacity
|
||||
* @param dirname_length optional recipient for the length of the dirname part
|
||||
* of the path. Available only when `capacity` is large enough to retrieve the
|
||||
* path.
|
||||
* of the path.
|
||||
*
|
||||
* @return the length of the executable path on success (without a terminal NUL
|
||||
* character), otherwise `-1`
|
||||
@@ -53,8 +52,7 @@ int WAI_PREFIX(getExecutablePath)(char* out, int capacity, int* dirname_length);
|
||||
* @param out destination buffer, optional
|
||||
* @param capacity destination buffer capacity
|
||||
* @param dirname_length optional recipient for the length of the dirname part
|
||||
* of the path. Available only when `capacity` is large enough to retrieve the
|
||||
* path.
|
||||
* of the path.
|
||||
*
|
||||
* @return the length of the module path on success (without a terminal NUL
|
||||
* character), otherwise `-1`
|
||||
|
||||
@@ -18,7 +18,7 @@ GNU General Public License for more details.
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#define MEMHEADER_SENTINEL1 0xA1BAU
|
||||
#define MEMHEADER_SENTINEL1 0xDEADF00DU
|
||||
#define MEMHEADER_SENTINEL2 0xDFU
|
||||
|
||||
#ifdef XASH_CUSTOM_SWAP
|
||||
@@ -51,31 +51,31 @@ static void *Q_realloc( void *mem, size_t size )
|
||||
#define Q_realloc realloc
|
||||
#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
|
||||
{
|
||||
struct memheader_s *next, *prev; // next and previous memheaders in chain belonging to pool
|
||||
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)
|
||||
poolhandle_t poolptr; // pool this memheader belongs to
|
||||
uint16_t fileline;
|
||||
uint16_t sentinel1; // must be equal to MEMHEADER_SENTINEL1
|
||||
struct memheader_s *next; // 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
|
||||
size_t size; // size of the memory after the header (excluding header and sentinel2)
|
||||
poolhandle_t poolptr; // pool this memheader belongs to
|
||||
int fileline;
|
||||
#if !XASH_64BIT
|
||||
uint32_t pad0; // doesn't have value, only to make Mem_Alloc return aligned addresses on ILP32
|
||||
#endif
|
||||
uint32_t sentinel1; // should always be MEMHEADER_SENTINEL1
|
||||
|
||||
// immediately followed by data, which is followed by a MEMHEADER_SENTINEL2 byte
|
||||
} memheader_t;
|
||||
|
||||
STATIC_CHECK_SIZEOF( memheader_t, 24, 40 );
|
||||
|
||||
typedef struct mempool_s
|
||||
{
|
||||
struct memheader_s *chain; // chain of individual memory allocations
|
||||
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 lastchecksize; // updated each time the pool is displayed by memlist
|
||||
const char *filename; // file name and line where Mem_AllocPool was called
|
||||
int fileline;
|
||||
char name[64]; // name of the pool
|
||||
struct memheader_s *chain; // chain of individual memory allocations
|
||||
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 lastchecksize; // updated each time the pool is displayed by memlist
|
||||
const char *filename; // file name and line where Mem_AllocPool was called
|
||||
int fileline;
|
||||
char name[64]; // name of the pool
|
||||
} mempool_t;
|
||||
|
||||
static mempool_t *poolchain = NULL; // critical stuff
|
||||
@@ -233,7 +233,10 @@ static void Mem_FreeBlock( memheader_t *mem, const char *filename, int fileline
|
||||
void _Mem_Free( void *data, const char *filename, int fileline )
|
||||
{
|
||||
if( data == NULL )
|
||||
{
|
||||
Sys_Error( "%s: data == NULL (called at %s:%i)\n", __func__, filename, fileline );
|
||||
return;
|
||||
}
|
||||
|
||||
Mem_FreeBlock((memheader_t *)((byte *)data - sizeof( memheader_t )), filename, fileline );
|
||||
}
|
||||
@@ -518,5 +521,4 @@ Memory_Init
|
||||
void Memory_Init( void )
|
||||
{
|
||||
poolchain = NULL; // init mem chain
|
||||
poolcount = 0;
|
||||
}
|
||||
|
||||
300
engine/keydefs.h
300
engine/keydefs.h
@@ -1,164 +1,186 @@
|
||||
/*
|
||||
Copyright (C) 1997-2001 Id Software, Inc.
|
||||
/***
|
||||
*
|
||||
* Copyright (c) 1996-2002, Valve LLC. All rights reserved.
|
||||
*
|
||||
* This product contains software technology licensed from Id
|
||||
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Use, distribution, and modification of this source code and/or resulting
|
||||
* object code is restricted to non-commercial enhancements to products from
|
||||
* Valve LLC. All other use, distribution, or modification is prohibited
|
||||
* without written permission from Valve LLC.
|
||||
*
|
||||
****/
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
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
|
||||
#ifndef KEYDEFS_H
|
||||
#define KEYDEFS_H
|
||||
|
||||
//
|
||||
// these are the key numbers that should be passed to Key_Event
|
||||
// normal keys should be passed as lowercased ascii
|
||||
//
|
||||
#define K_TAB 9
|
||||
#define K_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_TAB 9
|
||||
#define K_ENTER 13
|
||||
#define K_ESCAPE 27
|
||||
#define K_SPACE 32
|
||||
#define K_SCROLLOCK 70
|
||||
|
||||
#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
|
||||
// normal keys should be passed as lowercased ascii
|
||||
|
||||
#define K_BACKSPACE 127
|
||||
#define K_UPARROW 128
|
||||
#define K_DOWNARROW 129
|
||||
#define K_LEFTARROW 130
|
||||
#define K_RIGHTARROW 131
|
||||
|
||||
#define K_ALT 132
|
||||
#define K_CTRL 133
|
||||
#define K_SHIFT 134
|
||||
#define K_F1 135
|
||||
#define K_F2 136
|
||||
#define K_F3 137
|
||||
#define K_F4 138
|
||||
#define K_F5 139
|
||||
#define K_F6 140
|
||||
#define K_F7 141
|
||||
#define K_F8 142
|
||||
#define K_F9 143
|
||||
#define K_F10 144
|
||||
#define K_F11 145
|
||||
#define K_F12 146
|
||||
#define K_INS 147
|
||||
#define K_DEL 148
|
||||
#define K_PGDN 149
|
||||
#define K_PGUP 150
|
||||
#define K_HOME 151
|
||||
#define K_END 152
|
||||
|
||||
#define K_KP_HOME 160
|
||||
#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_END 166
|
||||
#define K_KP_DOWNARROW 167
|
||||
#define K_KP_PGDN 168
|
||||
#define K_KP_ENTER 169
|
||||
#define K_KP_INS 170
|
||||
#define K_KP_DEL 171
|
||||
#define K_KP_SLASH 172
|
||||
#define K_KP_MINUS 173
|
||||
#define K_KP_PLUS 174
|
||||
#define K_CAPSLOCK 175
|
||||
#define K_KP_MUL 176
|
||||
#define K_WIN 177
|
||||
#define K_KP_NUMLOCK 178
|
||||
#define K_KP_END 166
|
||||
#define K_KP_DOWNARROW 167
|
||||
#define K_KP_PGDN 168
|
||||
#define K_KP_ENTER 169
|
||||
#define K_KP_INS 170
|
||||
#define K_KP_DEL 171
|
||||
#define K_KP_SLASH 172
|
||||
#define K_KP_MINUS 173
|
||||
#define K_KP_PLUS 174
|
||||
#define K_CAPSLOCK 175
|
||||
#define K_KP_MUL 176
|
||||
#define K_WIN 177
|
||||
#define K_KP_NUMLOCK 178
|
||||
|
||||
//
|
||||
// joystick buttons
|
||||
//
|
||||
#define K_JOY1 203
|
||||
#define K_JOY2 204
|
||||
#define K_JOY3 205
|
||||
#define K_JOY4 206
|
||||
#define K_JOY1 203 // LTRIGGER (L2)
|
||||
#define K_JOY2 204 // RTRIGGER (R2)
|
||||
#define K_JOY3 205
|
||||
#define K_JOY4 206
|
||||
|
||||
//
|
||||
// aux keys are for multi-buttoned joysticks to generate so they can use
|
||||
// the normal binding process
|
||||
//
|
||||
#define K_AUX1 207
|
||||
#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_AUX1 207
|
||||
#define K_A_BUTTON K_AUX1
|
||||
|
||||
//
|
||||
// button names for game pads
|
||||
//
|
||||
#define K_A_BUTTON K_AUX1
|
||||
#define K_B_BUTTON K_AUX2
|
||||
#define K_X_BUTTON K_AUX3
|
||||
#define K_Y_BUTTON K_AUX4
|
||||
#define K_L1_BUTTON K_AUX5
|
||||
#define K_R1_BUTTON K_AUX6
|
||||
#define K_BACK_BUTTON K_AUX7
|
||||
#define K_MODE_BUTTON K_AUX8
|
||||
#define K_START_BUTTON K_AUX9
|
||||
#define K_LSTICK K_AUX10
|
||||
#define K_RSTICK K_AUX11
|
||||
#define K_L2_BUTTON K_AUX12
|
||||
#define K_R2_BUTTON K_AUX13
|
||||
#define K_C_BUTTON K_AUX14
|
||||
#define K_Z_BUTTON K_AUX15
|
||||
#define K_DPAD_UP K_AUX16
|
||||
#define K_DPAD_DOWN K_AUX17
|
||||
#define K_DPAD_LEFT K_AUX18
|
||||
#define K_DPAD_RIGHT K_AUX19
|
||||
#define K_MISC_BUTTON K_AUX20
|
||||
#define K_PADDLE1_BUTTON K_AUX21
|
||||
#define K_AUX2 208
|
||||
#define K_B_BUTTON K_AUX2
|
||||
|
||||
#define K_AUX3 209
|
||||
#define K_X_BUTTON K_AUX3
|
||||
|
||||
#define K_AUX4 210
|
||||
#define K_Y_BUTTON K_AUX4
|
||||
|
||||
#define K_AUX5 211
|
||||
#define K_L1_BUTTON K_AUX5
|
||||
|
||||
#define K_AUX6 212
|
||||
#define K_R1_BUTTON K_AUX6
|
||||
|
||||
#define K_AUX7 213
|
||||
#define K_BACK_BUTTON K_AUX7
|
||||
|
||||
#define K_AUX8 214
|
||||
#define K_MODE_BUTTON K_AUX8
|
||||
|
||||
#define K_AUX9 215
|
||||
#define K_START_BUTTON K_AUX9
|
||||
|
||||
#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_AUX23 229
|
||||
#define K_PADDLE3_BUTTON K_AUX23
|
||||
|
||||
#define K_AUX24 230
|
||||
#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
|
||||
//
|
||||
#define K_MWHEELDOWN 239
|
||||
#define K_MWHEELUP 240
|
||||
#define K_MOUSE1 241
|
||||
#define K_MOUSE2 242
|
||||
#define K_MOUSE3 243
|
||||
#define K_MOUSE4 244
|
||||
#define K_MOUSE5 245
|
||||
#define K_MOUSE1 241
|
||||
#define K_MOUSE2 242
|
||||
#define K_MOUSE3 243
|
||||
#define K_MOUSE4 244
|
||||
#define K_MOUSE5 245
|
||||
|
||||
#define K_PAUSE 255
|
||||
#endif//KEYDEFS_H
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
#include <android/log.h>
|
||||
#include "linker.h"
|
||||
|
||||
static const Elf_Sym *soinfo_elf_lookup( const struct soinfo *si, unsigned hash, const char *name )
|
||||
static const Elf_Sym *soinfo_elf_lookup( const soinfo *si, unsigned hash, const char *name )
|
||||
{
|
||||
const Elf_Sym *symtab = si->symtab;
|
||||
const char *strtab = si->strtab;
|
||||
@@ -87,14 +87,14 @@ static unsigned elfhash( const unsigned char *name )
|
||||
Binary Interface) where in Chapter 5 it discuss resolving "Shared
|
||||
Object Dependencies" in breadth first search order.
|
||||
*/
|
||||
static const Elf_Sym *dlsym_handle_lookup( const struct soinfo *si, const char *name )
|
||||
static const Elf_Sym *dlsym_handle_lookup( const soinfo *si, const char *name )
|
||||
{
|
||||
return soinfo_elf_lookup( si, elfhash((const unsigned char *)name ), name );
|
||||
}
|
||||
|
||||
void *dlsym_weak( void *handle, const char *symbol )
|
||||
extern "C" void *dlsym_weak( void *handle, const char *symbol )
|
||||
{
|
||||
const struct soinfo *found = (struct soinfo *)handle;
|
||||
const soinfo *found = (soinfo *)handle;
|
||||
const Elf_Sym *sym = dlsym_handle_lookup( found, symbol );
|
||||
|
||||
if( sym != NULL )
|
||||
@@ -31,8 +31,10 @@
|
||||
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <stdbool.h>
|
||||
// #include <elf.h>
|
||||
#include <linux/elf.h>
|
||||
// #include <sys/exec_elf.h>
|
||||
// #include <link.h>
|
||||
|
||||
// a1ba: we don't really need custom linker on Android 64, because
|
||||
// it's only intended to workaround bug which persist on Android < 4.4
|
||||
@@ -67,8 +69,8 @@ struct link_map_t {
|
||||
uintptr_t l_addr;
|
||||
char *l_name;
|
||||
uintptr_t l_ld;
|
||||
struct link_map_t *l_next;
|
||||
struct link_map_t *l_prev;
|
||||
link_map_t *l_next;
|
||||
link_map_t *l_prev;
|
||||
};
|
||||
|
||||
// Values for r_debug->state
|
||||
@@ -83,7 +85,7 @@ enum {
|
||||
|
||||
#define SOINFO_NAME_LEN 128
|
||||
|
||||
typedef void (*linker_function_t)( void );
|
||||
typedef void (*linker_function_t)();
|
||||
|
||||
// Android uses REL for 32-bit but only uses RELA for 64-bit.
|
||||
#if defined( __LP64__ )
|
||||
@@ -91,6 +93,7 @@ typedef void (*linker_function_t)( void );
|
||||
#endif
|
||||
|
||||
struct soinfo {
|
||||
public:
|
||||
char name[SOINFO_NAME_LEN];
|
||||
const Elf_Phdr *phdr;
|
||||
size_t phnum;
|
||||
@@ -109,7 +112,7 @@ struct soinfo {
|
||||
uint32_t unused3; // DO NOT USE, maintained for compatibility
|
||||
#endif
|
||||
|
||||
struct soinfo *next;
|
||||
soinfo *next;
|
||||
unsigned flags;
|
||||
|
||||
const char *strtab;
|
||||
@@ -161,8 +164,8 @@ struct soinfo {
|
||||
unsigned mips_gotsym;
|
||||
#endif
|
||||
|
||||
size_t ref_count;
|
||||
struct link_map_t link_map;
|
||||
size_t ref_count;
|
||||
link_map_t link_map;
|
||||
|
||||
bool constructors_called;
|
||||
|
||||
@@ -174,6 +177,14 @@ struct soinfo {
|
||||
bool has_text_relocations;
|
||||
#endif
|
||||
bool has_DT_SYMBOLIC;
|
||||
|
||||
void CallConstructors();
|
||||
void CallDestructors();
|
||||
void CallPreInitConstructors();
|
||||
|
||||
private:
|
||||
void CallArray( const char *array_name, linker_function_t *functions, size_t count, bool reverse );
|
||||
void CallFunction( const char *function_name, linker_function_t function );
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -91,6 +91,11 @@ void GAME_EXPORT Platform_SetMousePos(int x, int y)
|
||||
|
||||
}
|
||||
|
||||
int Platform_JoyInit( int numjoy )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Platform_EnableTextInput( qboolean enable )
|
||||
{
|
||||
keystate.chars = enable;
|
||||
|
||||
@@ -142,10 +142,17 @@ static qboolean vsync;
|
||||
|
||||
void GL_UpdateSwapInterval( void )
|
||||
{
|
||||
if( FBitSet( gl_vsync.flags, FCVAR_CHANGED ))
|
||||
// disable VSync while level is loading
|
||||
if( cls.state < ca_active )
|
||||
{
|
||||
ClearBits( gl_vsync.flags, FCVAR_CHANGED );
|
||||
vsync = gl_vsync.value;
|
||||
// setup vsync here
|
||||
vsync = false;
|
||||
SetBits( gl_vsync->flags, FCVAR_CHANGED );
|
||||
}
|
||||
else if( FBitSet( gl_vsync->flags, FCVAR_CHANGED ))
|
||||
{
|
||||
ClearBits( gl_vsync->flags, FCVAR_CHANGED );
|
||||
vsync = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -184,7 +184,7 @@ qboolean SNDDMA_Init( void )
|
||||
return false;
|
||||
}
|
||||
|
||||
dma.buffer = Mem_Calloc( sndpool, samples * 2 ); //allocate pcm frame buffer
|
||||
dma.buffer = Z_Malloc( samples * 2 ); //allocate pcm frame buffer
|
||||
dma.samplepos = 0;
|
||||
dma.samples = samples;
|
||||
dma.format.width = 2;
|
||||
|
||||
@@ -161,10 +161,17 @@ void* GL_GetProcAddress( const char *name ) // RenderAPI requirement
|
||||
|
||||
void GL_UpdateSwapInterval( void )
|
||||
{
|
||||
if( FBitSet( gl_vsync.flags, FCVAR_CHANGED ))
|
||||
// disable VSync while level is loading
|
||||
if( cls.state < ca_active )
|
||||
{
|
||||
// setup fb vsync here
|
||||
fb.vsync = false;
|
||||
SetBits( gl_vsync.flags, FCVAR_CHANGED );
|
||||
}
|
||||
else if( FBitSet( gl_vsync.flags, FCVAR_CHANGED ))
|
||||
{
|
||||
ClearBits( gl_vsync.flags, FCVAR_CHANGED );
|
||||
fb.vsync = gl_vsync.value;
|
||||
fb.vsync = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -274,8 +281,13 @@ void GAME_EXPORT Platform_SetMousePos(int x, int y)
|
||||
|
||||
}
|
||||
|
||||
void Platform_Vibrate( float life, char flags )
|
||||
void Platform_Vibrate(float life, char flags)
|
||||
{
|
||||
|
||||
}
|
||||
int Platform_JoyInit( int numjoy )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -31,7 +31,6 @@ GNU General Public License for more details.
|
||||
==============================================================================
|
||||
*/
|
||||
double Platform_DoubleTime( void );
|
||||
void Platform_Sleep( int msec );
|
||||
void Platform_ShellExecute( const char *path, const char *parms );
|
||||
void Platform_MessageBox( const char *title, const char *message, qboolean parentMainWindow );
|
||||
void Platform_SetStatus( const char *status );
|
||||
@@ -56,7 +55,7 @@ char *Posix_Input( void );
|
||||
#endif
|
||||
|
||||
#if XASH_SDL
|
||||
void SDLash_Init( const char *basedir );
|
||||
void SDLash_Init( void );
|
||||
void SDLash_Shutdown( void );
|
||||
#endif
|
||||
|
||||
@@ -71,9 +70,6 @@ void Android_Shutdown( void );
|
||||
#endif
|
||||
|
||||
#if XASH_WIN32
|
||||
void Win32_Init( qboolean con_showalways );
|
||||
void Win32_Shutdown( void );
|
||||
qboolean Win32_NanoSleep( int nsec );
|
||||
void Wcon_CreateConsole( qboolean con_showalways );
|
||||
void Wcon_DestroyConsole( void );
|
||||
void Wcon_InitConsoleCommands( void );
|
||||
@@ -108,7 +104,7 @@ void Linux_SetTimer( float time );
|
||||
int Linux_GetProcessID( void );
|
||||
#endif
|
||||
|
||||
static inline void Platform_Init( qboolean con_showalways, const char *basedir )
|
||||
static inline void Platform_Init( qboolean con_showalways )
|
||||
{
|
||||
#if XASH_POSIX
|
||||
// daemonize as early as possible, because we need to close our file descriptors
|
||||
@@ -116,7 +112,7 @@ static inline void Platform_Init( qboolean con_showalways, const char *basedir )
|
||||
#endif
|
||||
|
||||
#if XASH_SDL
|
||||
SDLash_Init( basedir );
|
||||
SDLash_Init( );
|
||||
#endif
|
||||
|
||||
#if XASH_ANDROID
|
||||
@@ -128,7 +124,7 @@ static inline void Platform_Init( qboolean con_showalways, const char *basedir )
|
||||
#elif XASH_DOS
|
||||
DOS_Init( );
|
||||
#elif XASH_WIN32
|
||||
Win32_Init( con_showalways );
|
||||
Wcon_CreateConsole( con_showalways );
|
||||
#elif XASH_LINUX
|
||||
Linux_Init( );
|
||||
#endif
|
||||
@@ -143,7 +139,7 @@ static inline void Platform_Shutdown( void )
|
||||
#elif XASH_DOS
|
||||
DOS_Shutdown( );
|
||||
#elif XASH_WIN32
|
||||
Win32_Shutdown( );
|
||||
Wcon_DestroyConsole( );
|
||||
#elif XASH_LINUX
|
||||
Linux_Shutdown( );
|
||||
#endif
|
||||
@@ -169,28 +165,24 @@ static inline void Platform_SetupSigtermHandling( void )
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline qboolean Platform_NanoSleep( int nsec )
|
||||
static inline void Platform_Sleep( int msec )
|
||||
{
|
||||
// SDL2 doesn't have nanosleep, so use low-level functions here
|
||||
// When this code will be ported to SDL3, use SDL_DelayNS
|
||||
#if XASH_POSIX
|
||||
struct timespec ts = {
|
||||
.tv_sec = 0,
|
||||
.tv_nsec = nsec, // just don't put large numbers here
|
||||
};
|
||||
return nanosleep( &ts, NULL ) == 0;
|
||||
#elif XASH_WIN32
|
||||
return Win32_NanoSleep( nsec );
|
||||
#if XASH_TIMER == TIMER_SDL
|
||||
SDL_Delay( msec );
|
||||
#elif XASH_TIMER == TIMER_POSIX
|
||||
usleep( msec * 1000 );
|
||||
#elif XASH_TIMER == TIMER_WIN32
|
||||
Sleep( msec );
|
||||
#else
|
||||
return false;
|
||||
// stub
|
||||
#endif
|
||||
}
|
||||
|
||||
#if XASH_WIN32 || XASH_FREEBSD || XASH_NETBSD || XASH_OPENBSD || XASH_ANDROID || XASH_LINUX || XASH_APPLE
|
||||
void Sys_SetupCrashHandler( const char *argv0 );
|
||||
#if XASH_WIN32 || XASH_FREEBSD || XASH_NETBSD || XASH_OPENBSD || XASH_ANDROID || XASH_LINUX
|
||||
void Sys_SetupCrashHandler( void );
|
||||
void Sys_RestoreCrashHandler( void );
|
||||
#else
|
||||
static inline void Sys_SetupCrashHandler( const char *argv0 )
|
||||
static inline void Sys_SetupCrashHandler( void )
|
||||
{
|
||||
}
|
||||
|
||||
@@ -207,8 +199,7 @@ static inline void Sys_RestoreCrashHandler( void )
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
void Platform_Vibrate( float life, char flags ); // left for compatibility
|
||||
void Platform_Vibrate2( float time, int low_freq, int high_freq, uint flags );
|
||||
void Platform_Vibrate( float life, char flags );
|
||||
|
||||
/*
|
||||
==============================================================================
|
||||
@@ -218,27 +209,7 @@ void Platform_Vibrate2( float time, int low_freq, int high_freq, uint flags );
|
||||
==============================================================================
|
||||
*/
|
||||
// Gamepad support
|
||||
#if XASH_SDL
|
||||
int Platform_JoyInit( void ); // returns number of connected gamepads, negative if error
|
||||
void Platform_JoyShutdown( void );
|
||||
void Platform_CalibrateGamepadGyro( void );
|
||||
#else
|
||||
static inline int Platform_JoyInit( void )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void Platform_JoyShutdown( void )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
static inline void Platform_CalibrateGamepadGyro( void )
|
||||
{
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
int Platform_JoyInit( int numjoy ); // returns number of connected gamepads, negative if error
|
||||
// Text input
|
||||
void Platform_EnableTextInput( qboolean enable );
|
||||
key_modifier_t Platform_GetKeyModifiers( void );
|
||||
|
||||
@@ -1,88 +0,0 @@
|
||||
/*
|
||||
crashhandler.c - advanced crashhandler
|
||||
Copyright (C) 2016 Mittorn
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
// on Glibc (which potentially might not be only Linux) systems we
|
||||
// have backtrace() and backtrace_symbols() calls, which replace for us
|
||||
// platform-specific code
|
||||
#if HAVE_EXECINFO
|
||||
#include <execinfo.h>
|
||||
#include <signal.h>
|
||||
#include "common.h"
|
||||
#include "input.h"
|
||||
|
||||
void Sys_Crash( int signal, siginfo_t *si, void *context )
|
||||
{
|
||||
char message[8192];
|
||||
int len, logfd, i = 0;
|
||||
int size;
|
||||
void *addrs[16];
|
||||
char **syms;
|
||||
|
||||
(void)context;
|
||||
|
||||
// flush buffers before writing directly to descriptors
|
||||
fflush( stdout );
|
||||
fflush( stderr );
|
||||
|
||||
// safe actions first, stack and memory may be corrupted
|
||||
len = Q_snprintf( message, sizeof( message ), "Ver: " XASH_ENGINE_NAME " " XASH_VERSION " (build %i-%s-%s, %s-%s)\n",
|
||||
Q_buildnum(), g_buildcommit, g_buildbranch, Q_buildos(), Q_buildarch() );
|
||||
|
||||
#if !XASH_FREEBSD && !XASH_NETBSD && !XASH_OPENBSD && !XASH_APPLE // they don't have si_ptr
|
||||
len += Q_snprintf( message + len, sizeof( message ) - len, "Crash: signal %d errno %d with code %d at %p %p\n", signal, si->si_errno, si->si_code, si->si_addr, si->si_ptr );
|
||||
#else
|
||||
len += Q_snprintf( message + len, sizeof( message ) - len, "Crash: signal %d errno %d with code %d at %p\n", signal, si->si_errno, si->si_code, si->si_addr );
|
||||
#endif
|
||||
|
||||
write( STDERR_FILENO, message, len );
|
||||
|
||||
// now get log fd and write trace directly to log
|
||||
logfd = Sys_LogFileNo();
|
||||
write( logfd, message, len );
|
||||
|
||||
size = backtrace( addrs, sizeof( addrs ) / sizeof( addrs[0] ));
|
||||
syms = backtrace_symbols( addrs, size );
|
||||
|
||||
for( i = 0; i < size && syms; i++ )
|
||||
{
|
||||
size_t symlen = Q_strlen( syms[i] );
|
||||
char ch = '\n';
|
||||
|
||||
write( logfd, syms[i], symlen );
|
||||
write( logfd, &ch, 1 );
|
||||
|
||||
write( STDERR_FILENO, syms[i], symlen );
|
||||
write( STDERR_FILENO, &ch, 1 );
|
||||
|
||||
len += Q_snprintf( message + len, sizeof( message ) - len, "%2d: %s\n", i, syms[i] );
|
||||
}
|
||||
|
||||
// put MessageBox as Sys_Error
|
||||
Msg( "%s\n", message );
|
||||
#if !XASH_DEDICATED
|
||||
IN_SetMouseGrab( false );
|
||||
#endif
|
||||
host.crashed = true;
|
||||
Platform_MessageBox( "Xash Error", message, false );
|
||||
|
||||
// log saved, now we can try to save configs and close log correctly, it may crash
|
||||
if( host.type == HOST_NORMAL )
|
||||
CL_Crashed();
|
||||
host.status = HOST_CRASHED;
|
||||
|
||||
Sys_Quit( "crashed" );
|
||||
}
|
||||
|
||||
#endif // HAVE_EXECINFO
|
||||
@@ -1,188 +0,0 @@
|
||||
/*
|
||||
crashhandler.c - advanced crashhandler
|
||||
Copyright (C) 2016 Mittorn
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
#if HAVE_LIBBACKTRACE
|
||||
#include <signal.h>
|
||||
#include "common.h"
|
||||
#include "backtrace.h"
|
||||
#include "input.h"
|
||||
|
||||
static struct backtrace_state *g_bt_state;
|
||||
static qboolean enable_libbacktrace;
|
||||
|
||||
static void Sys_BacktraceError( void *data, const char *msg, int errnum )
|
||||
{
|
||||
if( errnum < 0 )
|
||||
{
|
||||
Con_Printf( S_ERROR "no symbol info, no libbacktrace\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
Con_Printf( S_ERROR "libbacktrace error: %s (%d)\n", msg, errnum );
|
||||
|
||||
enable_libbacktrace = false;
|
||||
}
|
||||
|
||||
struct print_data
|
||||
{
|
||||
char *message;
|
||||
size_t message_size;
|
||||
int len;
|
||||
int idx;
|
||||
int logfd;
|
||||
};
|
||||
|
||||
static void Sys_AppendPrint( struct print_data *pd, const char *fmt, ... )
|
||||
{
|
||||
va_list va;
|
||||
int len;
|
||||
|
||||
va_start( va, fmt );
|
||||
len = Q_vsnprintf( pd->message, pd->message_size, fmt, va );
|
||||
va_end( va );
|
||||
|
||||
if( len > 0 )
|
||||
{
|
||||
char ch = '\n';
|
||||
|
||||
write( pd->logfd, pd->message, len );
|
||||
write( pd->logfd, &ch, 1 );
|
||||
|
||||
write( STDERR_FILENO, pd->message, len );
|
||||
write( STDERR_FILENO, &ch, 1 );
|
||||
|
||||
pd->message += len;
|
||||
pd->len += len;
|
||||
pd->message_size -= len;
|
||||
}
|
||||
}
|
||||
|
||||
static void Sys_BacktracePrintError( void *data, const char *msg, int errnum )
|
||||
{
|
||||
struct print_data *pd = data;
|
||||
Sys_AppendPrint( pd, "%2d: error: %s (%d)\n", pd->idx++, msg, errnum );
|
||||
}
|
||||
|
||||
static void Sys_BacktracePrintSyminfo( void *data, uintptr_t pc, const char *symname, uintptr_t symval, uintptr_t symsize )
|
||||
{
|
||||
struct print_data *pd = data;
|
||||
Dl_info dlinfo = { 0 };
|
||||
const char *module_name;
|
||||
|
||||
if( dladdr((void *)pc, &dlinfo ))
|
||||
module_name = dlinfo.dli_fname;
|
||||
else module_name = NULL;
|
||||
|
||||
if( symname )
|
||||
{
|
||||
if( module_name )
|
||||
Sys_AppendPrint( pd, "%2d: <%s+%d> (%s)\n", pd->idx++, symname, pc - symval, module_name );
|
||||
else
|
||||
Sys_AppendPrint( pd, "%2d: <%s+%d>\n", pd->idx++, symname, pc - symval );
|
||||
}
|
||||
else
|
||||
{
|
||||
if( module_name )
|
||||
Sys_AppendPrint( pd, "%2d: %p (%s)\n", pd->idx++, pc, module_name );
|
||||
else
|
||||
Sys_AppendPrint( pd, "%2d: %p\n", pd->idx++, pc );
|
||||
}
|
||||
}
|
||||
|
||||
static int Sys_BacktracePrintFull( void *data, uintptr_t pc, const char *filename, int lineno, const char *function )
|
||||
{
|
||||
struct print_data *pd = data;
|
||||
Dl_info dlinfo = { 0 };
|
||||
const char *module_name;
|
||||
|
||||
if( dladdr((void *)pc, &dlinfo ))
|
||||
module_name = dlinfo.dli_fname;
|
||||
else module_name = NULL;
|
||||
|
||||
if( filename && lineno >= 0 && function )
|
||||
{
|
||||
filename = COM_FileWithoutPath( filename );
|
||||
|
||||
if( module_name )
|
||||
Sys_AppendPrint( pd, "%2d: %s (%s:%d) (%s)\n", pd->idx++, function, filename, lineno, module_name );
|
||||
else
|
||||
Sys_AppendPrint( pd, "%2d: %s (%s:%d)\n", pd->idx++, function, filename, lineno );
|
||||
}
|
||||
else
|
||||
{
|
||||
backtrace_syminfo( g_bt_state, pc, Sys_BacktracePrintSyminfo, Sys_BacktraceError, data );
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Sys_CrashLibbacktrace( int signal, siginfo_t *si, void *context )
|
||||
{
|
||||
char message[8192];
|
||||
int len, logfd;
|
||||
struct print_data pd = { .idx = 0 };
|
||||
|
||||
(void)context;
|
||||
|
||||
// flush buffers before writing directly to descriptors
|
||||
fflush( stdout );
|
||||
fflush( stderr );
|
||||
|
||||
// safe actions first, stack and memory may be corrupted
|
||||
len = Q_snprintf( message, sizeof( message ), "Ver: " XASH_ENGINE_NAME " " XASH_VERSION " (build %i-%s-%s, %s-%s)\n",
|
||||
Q_buildnum(), g_buildcommit, g_buildbranch, Q_buildos(), Q_buildarch() );
|
||||
|
||||
#if !XASH_FREEBSD && !XASH_NETBSD && !XASH_OPENBSD && !XASH_APPLE // they don't have si_ptr
|
||||
len += Q_snprintf( message + len, sizeof( message ) - len, "Crash: signal %d errno %d with code %d at %p %p\n", signal, si->si_errno, si->si_code, si->si_addr, si->si_ptr );
|
||||
#else
|
||||
len += Q_snprintf( message + len, sizeof( message ) - len, "Crash: signal %d errno %d with code %d at %p\n", signal, si->si_errno, si->si_code, si->si_addr );
|
||||
#endif
|
||||
|
||||
write( STDERR_FILENO, message, len );
|
||||
|
||||
// now get log fd and write trace directly to log
|
||||
pd.logfd = logfd = Sys_LogFileNo();
|
||||
write( logfd, message, len );
|
||||
|
||||
pd.message = message + len;
|
||||
pd.message_size = sizeof( message ) - len;
|
||||
pd.len = 0;
|
||||
|
||||
backtrace_full( g_bt_state, 1, Sys_BacktracePrintFull, Sys_BacktracePrintError, &pd );
|
||||
|
||||
// put MessageBox as Sys_Error
|
||||
Msg( "%s\n", message );
|
||||
#if !XASH_DEDICATED
|
||||
IN_SetMouseGrab( false );
|
||||
#endif
|
||||
host.crashed = true;
|
||||
Platform_MessageBox( "Xash Error", message, false );
|
||||
|
||||
// log saved, now we can try to save configs and close log correctly, it may crash
|
||||
if( host.type == HOST_NORMAL )
|
||||
CL_Crashed();
|
||||
host.status = HOST_CRASHED;
|
||||
|
||||
Sys_Quit( "crashed" );
|
||||
}
|
||||
|
||||
qboolean Sys_SetupLibbacktrace( const char *argv0 )
|
||||
{
|
||||
enable_libbacktrace = true;
|
||||
g_bt_state = backtrace_create_state( argv0, true, Sys_BacktraceError, NULL );
|
||||
return g_bt_state != NULL && enable_libbacktrace;
|
||||
}
|
||||
|
||||
#endif // HAVE_EXECINFO
|
||||
@@ -18,22 +18,13 @@ GNU General Public License for more details.
|
||||
// while this is mostly POSIX-compatible functions
|
||||
// the contents of ucontext_t is platform-dependent
|
||||
// before adding new OS here, check platform.h
|
||||
#define _XOPEN_SOURCE 1 // required for ucontext
|
||||
#if XASH_FREEBSD || XASH_NETBSD || XASH_OPENBSD || XASH_ANDROID || XASH_LINUX || XASH_APPLE
|
||||
#if XASH_FREEBSD || XASH_NETBSD || XASH_OPENBSD || XASH_ANDROID || XASH_LINUX
|
||||
#ifndef XASH_OPENBSD
|
||||
#include <ucontext.h>
|
||||
#endif
|
||||
#include <signal.h>
|
||||
#include <sys/mman.h>
|
||||
#include "library.h"
|
||||
#include "input.h"
|
||||
|
||||
void Sys_Crash( int signal, siginfo_t *si, void *context );
|
||||
void Sys_CrashLibbacktrace( int signal, siginfo_t *si, void *context );
|
||||
qboolean Sys_SetupLibbacktrace( const char *argv0 );
|
||||
static struct sigaction oldFilter;
|
||||
|
||||
#if !HAVE_EXECINFO
|
||||
|
||||
#define STACK_BACKTRACE_STR "Stack backtrace:\n"
|
||||
#define STACK_DUMP_STR "Stack dump:\n"
|
||||
@@ -42,25 +33,27 @@ static struct sigaction oldFilter;
|
||||
#define STACK_DUMP_STR_LEN ( sizeof( STACK_DUMP_STR ) - 1 )
|
||||
#define ALIGN( x, y ) (((uintptr_t) ( x ) + (( y ) - 1 )) & ~(( y ) - 1 ))
|
||||
|
||||
static struct sigaction oldFilter;
|
||||
|
||||
static int Sys_PrintFrame( char *buf, int len, int i, void *addr )
|
||||
{
|
||||
Dl_info dlinfo;
|
||||
if( len <= 0 )
|
||||
return 0; // overflow
|
||||
|
||||
if( dladdr( addr, &dlinfo ))
|
||||
{
|
||||
if( dlinfo.dli_sname )
|
||||
return Q_snprintf( buf, len, "%2d: %p <%s+%lu> (%s)\n", i, addr, dlinfo.dli_sname,
|
||||
(unsigned long)addr - (unsigned long)dlinfo.dli_saddr, dlinfo.dli_fname ); // print symbol, module and address
|
||||
if( dladdr( addr, &dlinfo ))
|
||||
{
|
||||
if( dlinfo.dli_sname )
|
||||
return Q_snprintf( buf, len, "%2d: %p <%s+%lu> (%s)\n", i, addr, dlinfo.dli_sname,
|
||||
(unsigned long)addr - (unsigned long)dlinfo.dli_saddr, dlinfo.dli_fname ); // print symbol, module and address
|
||||
|
||||
return Q_snprintf( buf, len, "%2d: %p (%s)\n", i, addr, dlinfo.dli_fname ); // print module and address
|
||||
}
|
||||
return Q_snprintf( buf, len, "%2d: %p (%s)\n", i, addr, dlinfo.dli_fname ); // print module and address
|
||||
}
|
||||
|
||||
return Q_snprintf( buf, len, "%2d: %p\n", i, addr ); // print only address
|
||||
return Q_snprintf( buf, len, "%2d: %p\n", i, addr ); // print only address
|
||||
}
|
||||
|
||||
void Sys_Crash( int signal, siginfo_t *si, void *context )
|
||||
static void Sys_Crash( int signal, siginfo_t *si, void *context)
|
||||
{
|
||||
void *pc = NULL, **bp = NULL, **sp = NULL; // this must be set for every OS!
|
||||
char message[8192];
|
||||
@@ -72,10 +65,6 @@ void Sys_Crash( int signal, siginfo_t *si, void *context )
|
||||
ucontext_t *ucontext = (ucontext_t*)context;
|
||||
#endif
|
||||
|
||||
// flush buffers before writing directly to descriptors
|
||||
fflush( stdout );
|
||||
fflush( stderr );
|
||||
|
||||
#if XASH_AMD64
|
||||
#if XASH_FREEBSD
|
||||
pc = (void*)ucontext->uc_mcontext.mc_rip;
|
||||
@@ -123,10 +112,10 @@ void Sys_Crash( int signal, siginfo_t *si, void *context )
|
||||
#endif
|
||||
|
||||
// safe actions first, stack and memory may be corrupted
|
||||
len = Q_snprintf( message, sizeof( message ), "Ver: " XASH_ENGINE_NAME " " XASH_VERSION " (build %i-%s-%s, %s-%s)\n",
|
||||
Q_buildnum(), g_buildcommit, g_buildbranch, Q_buildos(), Q_buildarch() );
|
||||
len = Q_snprintf( message, sizeof( message ), "Ver: " XASH_ENGINE_NAME " " XASH_VERSION " (build %i-%s, %s-%s)\n",
|
||||
Q_buildnum(), g_buildcommit, Q_buildos(), Q_buildarch() );
|
||||
|
||||
#if !XASH_FREEBSD && !XASH_NETBSD && !XASH_OPENBSD && !XASH_APPLE
|
||||
#if !XASH_FREEBSD && !XASH_NETBSD && !XASH_OPENBSD
|
||||
len += Q_snprintf( message + len, sizeof( message ) - len, "Crash: signal %d errno %d with code %d at %p %p\n", signal, si->si_errno, si->si_code, si->si_addr, si->si_ptr );
|
||||
#else
|
||||
len += Q_snprintf( message + len, sizeof( message ) - len, "Crash: signal %d errno %d with code %d at %p\n", signal, si->si_errno, si->si_code, si->si_addr );
|
||||
@@ -134,6 +123,10 @@ void Sys_Crash( int signal, siginfo_t *si, void *context )
|
||||
|
||||
write( STDERR_FILENO, message, len );
|
||||
|
||||
// flush buffers before writing directly to descriptors
|
||||
fflush( stdout );
|
||||
fflush( stderr );
|
||||
|
||||
// now get log fd and write trace directly to log
|
||||
logfd = Sys_LogFileNo();
|
||||
write( logfd, message, len );
|
||||
@@ -193,8 +186,8 @@ void Sys_Crash( int signal, siginfo_t *si, void *context )
|
||||
|
||||
// put MessageBox as Sys_Error
|
||||
Msg( "%s\n", message );
|
||||
#if !XASH_DEDICATED
|
||||
IN_SetMouseGrab( false );
|
||||
#ifdef XASH_SDL
|
||||
SDL_SetWindowGrab( host.hWnd, SDL_FALSE );
|
||||
#endif
|
||||
host.crashed = true;
|
||||
Platform_MessageBox( "Xash Error", message, false );
|
||||
@@ -207,27 +200,15 @@ void Sys_Crash( int signal, siginfo_t *si, void *context )
|
||||
Sys_Quit( "crashed" );
|
||||
}
|
||||
|
||||
#endif // !HAVE_EXECINFO
|
||||
|
||||
void Sys_SetupCrashHandler( const char *argv0 )
|
||||
void Sys_SetupCrashHandler( void )
|
||||
{
|
||||
struct sigaction act = { 0 };
|
||||
#if HAVE_LIBBACKTRACE
|
||||
if( Sys_SetupLibbacktrace( argv0 ))
|
||||
{
|
||||
act.sa_sigaction = Sys_CrashLibbacktrace;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
act.sa_sigaction = Sys_Crash;
|
||||
}
|
||||
act.sa_sigaction = Sys_Crash;
|
||||
act.sa_flags = SA_SIGINFO | SA_ONSTACK;
|
||||
sigaction( SIGSEGV, &act, &oldFilter );
|
||||
sigaction( SIGABRT, &act, &oldFilter );
|
||||
sigaction( SIGBUS, &act, &oldFilter );
|
||||
sigaction( SIGILL, &act, &oldFilter );
|
||||
|
||||
}
|
||||
|
||||
void Sys_RestoreCrashHandler( void )
|
||||
|
||||
@@ -174,10 +174,5 @@ double Platform_DoubleTime( void )
|
||||
#endif
|
||||
return (double) ts.tv_sec + (double) ts.tv_nsec/1000000000.0;
|
||||
}
|
||||
|
||||
void Platform_Sleep( int msec )
|
||||
{
|
||||
usleep( msec * 1000 );
|
||||
}
|
||||
#endif // XASH_TIMER == TIMER_POSIX
|
||||
|
||||
|
||||
@@ -88,8 +88,52 @@ GNU General Public License for more details.
|
||||
#define SDL_SCANCODE_PRINTSCREEN SDLK_PRINT
|
||||
#define SDL_SCANCODE_UNKNOWN SDLK_UNKNOWN
|
||||
#define SDL_GetScancodeName( x ) "unknown"
|
||||
#define SDL_JoystickID Uint8
|
||||
#endif
|
||||
|
||||
static int SDLash_GameControllerButtonMapping[] =
|
||||
{
|
||||
#if XASH_NSWITCH // devkitPro/SDL has inverted Nintendo layout for SDL_GameController
|
||||
K_B_BUTTON, K_A_BUTTON, K_Y_BUTTON, K_X_BUTTON,
|
||||
#else
|
||||
K_A_BUTTON, K_B_BUTTON, K_X_BUTTON, K_Y_BUTTON,
|
||||
#endif
|
||||
K_BACK_BUTTON, K_MODE_BUTTON, K_START_BUTTON,
|
||||
K_LSTICK, K_RSTICK,
|
||||
K_L1_BUTTON, K_R1_BUTTON,
|
||||
K_DPAD_UP, K_DPAD_DOWN, K_DPAD_LEFT, K_DPAD_RIGHT,
|
||||
K_MISC_BUTTON,
|
||||
K_PADDLE1_BUTTON, K_PADDLE2_BUTTON, K_PADDLE3_BUTTON, K_PADDLE4_BUTTON,
|
||||
K_TOUCHPAD,
|
||||
};
|
||||
|
||||
// Swap axis to follow default axis binding:
|
||||
// LeftX, LeftY, RightX, RightY, TriggerRight, TriggerLeft
|
||||
static int SDLash_GameControllerAxisMapping[] =
|
||||
{
|
||||
JOY_AXIS_SIDE, // SDL_CONTROLLER_AXIS_LEFTX,
|
||||
JOY_AXIS_FWD, // SDL_CONTROLLER_AXIS_LEFTY,
|
||||
JOY_AXIS_PITCH, // SDL_CONTROLLER_AXIS_RIGHTX,
|
||||
JOY_AXIS_YAW, // SDL_CONTROLLER_AXIS_RIGHTY,
|
||||
JOY_AXIS_LT, // SDL_CONTROLLER_AXIS_TRIGGERLEFT,
|
||||
JOY_AXIS_RT, // SDL_CONTROLLER_AXIS_TRIGGERRIGHT,
|
||||
};
|
||||
|
||||
static qboolean SDLash_IsInstanceIDAGameController( SDL_JoystickID joyId )
|
||||
{
|
||||
#if !SDL_VERSION_ATLEAST( 2, 0, 4 )
|
||||
// HACKHACK: if we're not initialized g_joy, then we're probably using gamecontroller api
|
||||
// so return true
|
||||
if( !g_joy )
|
||||
return true;
|
||||
return false;
|
||||
#else
|
||||
if( SDL_GameControllerFromInstanceID( joyId ) != NULL )
|
||||
return true;
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
SDLash_KeyEvent
|
||||
@@ -221,7 +265,7 @@ static void SDLash_KeyEvent( SDL_KeyboardEvent key )
|
||||
break;
|
||||
}
|
||||
case SDL_SCANCODE_PAUSE: keynum = K_PAUSE; break;
|
||||
case SDL_SCANCODE_SCROLLLOCK: keynum = K_SCROLLLOCK; break;
|
||||
case SDL_SCANCODE_SCROLLLOCK: keynum = K_SCROLLOCK; break;
|
||||
#if SDL_VERSION_ATLEAST( 2, 0, 0 )
|
||||
case SDL_SCANCODE_APPLICATION: keynum = K_WIN; break; // (compose key) ???
|
||||
// don't console spam on known functional buttons, not used in engine
|
||||
@@ -364,6 +408,50 @@ static void SDLash_ActiveEvent( int gain )
|
||||
}
|
||||
}
|
||||
|
||||
#if SDL_VERSION_ATLEAST( 2, 0, 0 )
|
||||
static size_t num_open_game_controllers = 0;
|
||||
|
||||
static void SDLash_GameController_Add( int index )
|
||||
{
|
||||
extern convar_t joy_enable; // private to input system
|
||||
SDL_GameController *controller;
|
||||
|
||||
if( !joy_enable.value )
|
||||
return;
|
||||
|
||||
controller = SDL_GameControllerOpen( index );
|
||||
if( !controller )
|
||||
{
|
||||
Con_Reportf( "Failed to open SDL GameController %d: %s\n", index, SDL_GetError( ) );
|
||||
SDL_ClearError( );
|
||||
return;
|
||||
}
|
||||
#if SDL_VERSION_ATLEAST( 2, 0, 6 )
|
||||
Con_Reportf( "Added controller: %s (%i:%i:%i)\n",
|
||||
SDL_GameControllerName( controller ),
|
||||
SDL_GameControllerGetVendor( controller ),
|
||||
SDL_GameControllerGetProduct( controller ),
|
||||
SDL_GameControllerGetProductVersion( controller ));
|
||||
#endif // SDL_VERSION_ATLEAST( 2, 0, 6 )
|
||||
|
||||
++num_open_game_controllers;
|
||||
if( num_open_game_controllers == 1 )
|
||||
Joy_AddEvent( );
|
||||
}
|
||||
|
||||
|
||||
static void SDLash_GameController_Remove( SDL_JoystickID joystick_id )
|
||||
{
|
||||
Con_Reportf( "Removed controller %i\n", joystick_id );
|
||||
|
||||
// `Joy_RemoveEvent` sets `joy_found` to `0`.
|
||||
// We only want to do this when all the game controllers have been removed.
|
||||
--num_open_game_controllers;
|
||||
if( num_open_game_controllers == 0 )
|
||||
Joy_RemoveEvent( );
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
=============
|
||||
SDLash_EventFilter
|
||||
@@ -391,6 +479,28 @@ static void SDLash_EventHandler( SDL_Event *event )
|
||||
SDLash_KeyEvent( event->key );
|
||||
break;
|
||||
|
||||
/* Joystick events */
|
||||
case SDL_JOYAXISMOTION:
|
||||
if ( !SDLash_IsInstanceIDAGameController( event->jaxis.which ))
|
||||
Joy_AxisMotionEvent( event->jaxis.axis, event->jaxis.value );
|
||||
break;
|
||||
|
||||
case SDL_JOYBALLMOTION:
|
||||
if ( !SDLash_IsInstanceIDAGameController( event->jball.which ))
|
||||
Joy_BallMotionEvent( event->jball.ball, event->jball.xrel, event->jball.yrel );
|
||||
break;
|
||||
|
||||
case SDL_JOYHATMOTION:
|
||||
if ( !SDLash_IsInstanceIDAGameController( event->jhat.which ))
|
||||
Joy_HatMotionEvent( event->jhat.hat, event->jhat.value );
|
||||
break;
|
||||
|
||||
case SDL_JOYBUTTONDOWN:
|
||||
case SDL_JOYBUTTONUP:
|
||||
if ( !SDLash_IsInstanceIDAGameController( event->jbutton.which ))
|
||||
Joy_ButtonEvent( event->jbutton.button, event->jbutton.state );
|
||||
break;
|
||||
|
||||
case SDL_QUIT:
|
||||
Sys_Quit( "caught SDL_QUIT" );
|
||||
break;
|
||||
@@ -458,17 +568,46 @@ static void SDLash_EventHandler( SDL_Event *event )
|
||||
SDLash_InputEvent( event->text );
|
||||
break;
|
||||
|
||||
case SDL_JOYDEVICEADDED:
|
||||
Joy_AddEvent();
|
||||
break;
|
||||
case SDL_JOYDEVICEREMOVED:
|
||||
Joy_RemoveEvent();
|
||||
break;
|
||||
|
||||
/* GameController API */
|
||||
case SDL_CONTROLLERAXISMOTION:
|
||||
{
|
||||
if( !Joy_IsActive( ))
|
||||
break;
|
||||
|
||||
if( event->caxis.axis >= 0 && event->caxis.axis < ARRAYSIZE( SDLash_GameControllerAxisMapping ))
|
||||
{
|
||||
Joy_KnownAxisMotionEvent( SDLash_GameControllerAxisMapping[event->caxis.axis], event->caxis.value );
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case SDL_CONTROLLERBUTTONDOWN:
|
||||
case SDL_CONTROLLERBUTTONUP:
|
||||
{
|
||||
if( !Joy_IsActive( ))
|
||||
break;
|
||||
|
||||
// TODO: Use joyinput funcs, for future multiple gamepads support
|
||||
if( event->cbutton.button >= 0 && event->cbutton.button < ARRAYSIZE( SDLash_GameControllerButtonMapping ))
|
||||
{
|
||||
Key_Event( SDLash_GameControllerButtonMapping[event->cbutton.button], event->cbutton.state );
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case SDL_CONTROLLERDEVICEADDED:
|
||||
SDLash_GameController_Add( event->cdevice.which );
|
||||
break;
|
||||
|
||||
case SDL_CONTROLLERDEVICEREMOVED:
|
||||
case SDL_CONTROLLERTOUCHPADDOWN:
|
||||
case SDL_CONTROLLERTOUCHPADMOTION:
|
||||
case SDL_CONTROLLERTOUCHPADUP:
|
||||
case SDL_CONTROLLERSENSORUPDATE:
|
||||
SDLash_HandleGameControllerEvent( event );
|
||||
SDLash_GameController_Remove( event->cdevice.which );
|
||||
break;
|
||||
|
||||
case SDL_WINDOWEVENT:
|
||||
@@ -481,19 +620,19 @@ static void SDLash_EventHandler( SDL_Event *event )
|
||||
switch( event->window.event )
|
||||
{
|
||||
case SDL_WINDOWEVENT_MOVED:
|
||||
{
|
||||
char val[32];
|
||||
if( vid_fullscreen.value == WINDOW_MODE_WINDOWED )
|
||||
{
|
||||
char val[32];
|
||||
|
||||
Q_snprintf( val, sizeof( val ), "%d", event->window.data1 );
|
||||
Cvar_DirectSet( &window_xpos, val );
|
||||
Q_snprintf( val, sizeof( val ), "%d", event->window.data1 );
|
||||
Cvar_DirectSet( &window_xpos, val );
|
||||
|
||||
Q_snprintf( val, sizeof( val ), "%d", event->window.data2 );
|
||||
Cvar_DirectSet( &window_ypos, val );
|
||||
Q_snprintf( val, sizeof( val ), "%d", event->window.data2 );
|
||||
Cvar_DirectSet( &window_ypos, val );
|
||||
|
||||
if ( vid_fullscreen.value == WINDOW_MODE_WINDOWED )
|
||||
Cvar_DirectSet( &vid_maximized, "0" );
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SDL_WINDOWEVENT_MINIMIZED:
|
||||
host.status = HOST_SLEEP;
|
||||
Cvar_DirectSet( &vid_maximized, "0" );
|
||||
|
||||
@@ -28,16 +28,14 @@ void GL_InitExtensions( void );
|
||||
qboolean GL_DeleteContext( void );
|
||||
void VID_SaveWindowSize( int width, int height, qboolean maximized );
|
||||
|
||||
// joystick events
|
||||
extern SDL_Joystick *g_joy;
|
||||
|
||||
//
|
||||
// in_sdl.c
|
||||
//
|
||||
void SDLash_InitCursors( void );
|
||||
void SDLash_FreeCursors( void );
|
||||
|
||||
//
|
||||
// joy_sdl.c
|
||||
//
|
||||
void SDLash_HandleGameControllerEvent( SDL_Event *ev );
|
||||
|
||||
#endif // XASH_SDL
|
||||
#endif // KEYWRAPPER_H
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
in_sdl.c - SDL input component
|
||||
Copyright (C) 2018-2025 a1batross
|
||||
vid_sdl.c - SDL input component
|
||||
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
|
||||
@@ -12,6 +12,7 @@ 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.
|
||||
*/
|
||||
#if !XASH_DEDICATED
|
||||
#include <SDL.h>
|
||||
|
||||
#include "common.h"
|
||||
@@ -23,6 +24,7 @@ GNU General Public License for more details.
|
||||
#include "sound.h"
|
||||
#include "vid_common.h"
|
||||
|
||||
SDL_Joystick *g_joy = NULL;
|
||||
#if !SDL_VERSION_ATLEAST( 2, 0, 0 )
|
||||
#define SDL_WarpMouseInWindow( win, x, y ) SDL_WarpMouse( ( x ), ( y ) )
|
||||
#else
|
||||
@@ -33,12 +35,6 @@ static struct
|
||||
} cursors;
|
||||
#endif
|
||||
|
||||
static struct
|
||||
{
|
||||
int x, y;
|
||||
qboolean pushed;
|
||||
} in_visible_cursor_pos;
|
||||
|
||||
/*
|
||||
=============
|
||||
Platform_GetMousePos
|
||||
@@ -130,6 +126,20 @@ void Platform_SetClipboardText( const char *buffer )
|
||||
#endif // SDL_VERSION_ATLEAST( 2, 0, 0 )
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
Platform_Vibrate
|
||||
|
||||
=============
|
||||
*/
|
||||
void Platform_Vibrate( float time, char flags )
|
||||
{
|
||||
#if SDL_VERSION_ATLEAST( 2, 0, 9 )
|
||||
if( g_joy )
|
||||
SDL_JoystickRumble( g_joy, 0xFFFF, 0xFFFF, time * 1000.0f );
|
||||
#endif // SDL_VERSION_ATLEAST( 2, 0, 9 )
|
||||
}
|
||||
|
||||
#if !XASH_PSVITA
|
||||
|
||||
/*
|
||||
@@ -147,6 +157,120 @@ void Platform_EnableTextInput( qboolean enable )
|
||||
|
||||
#endif // !XASH_PSVITA
|
||||
|
||||
/*
|
||||
=============
|
||||
SDLash_JoyInit_Old
|
||||
|
||||
=============
|
||||
*/
|
||||
static int SDLash_JoyInit_Old( int numjoy )
|
||||
{
|
||||
int num;
|
||||
int i;
|
||||
|
||||
Con_Reportf( "Joystick: SDL\n" );
|
||||
|
||||
if( SDL_WasInit( SDL_INIT_JOYSTICK ) != SDL_INIT_JOYSTICK &&
|
||||
SDL_InitSubSystem( SDL_INIT_JOYSTICK ) )
|
||||
{
|
||||
Con_Reportf( "Failed to initialize SDL Joysitck: %s\n", SDL_GetError() );
|
||||
return 0;
|
||||
}
|
||||
|
||||
if( g_joy )
|
||||
{
|
||||
SDL_JoystickClose( g_joy );
|
||||
}
|
||||
|
||||
num = SDL_NumJoysticks();
|
||||
|
||||
if( num > 0 )
|
||||
Con_Reportf( "%i joysticks found:\n", num );
|
||||
else
|
||||
{
|
||||
Con_Reportf( "No joystick found.\n" );
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if SDL_VERSION_ATLEAST( 2, 0, 0 )
|
||||
for( i = 0; i < num; i++ )
|
||||
Con_Reportf( "%i\t: %s\n", i, SDL_JoystickNameForIndex( i ) );
|
||||
#endif // SDL_VERSION_ATLEAST( 2, 0, 0 )
|
||||
|
||||
Con_Reportf( "Pass +set joy_index N to command line, where N is number, to select active joystick\n" );
|
||||
|
||||
g_joy = SDL_JoystickOpen( numjoy );
|
||||
|
||||
if( !g_joy )
|
||||
{
|
||||
Con_Reportf( "Failed to select joystick: %s\n", SDL_GetError( ) );
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if SDL_VERSION_ATLEAST( 2, 0, 0 )
|
||||
Con_Reportf( "Selected joystick: %s\n"
|
||||
"\tAxes: %i\n"
|
||||
"\tHats: %i\n"
|
||||
"\tButtons: %i\n"
|
||||
"\tBalls: %i\n",
|
||||
SDL_JoystickName( g_joy ), SDL_JoystickNumAxes( g_joy ), SDL_JoystickNumHats( g_joy ),
|
||||
SDL_JoystickNumButtons( g_joy ), SDL_JoystickNumBalls( g_joy ) );
|
||||
|
||||
SDL_GameControllerEventState( SDL_DISABLE );
|
||||
#endif // SDL_VERSION_ATLEAST( 2, 0, 0 )
|
||||
SDL_JoystickEventState( SDL_ENABLE );
|
||||
|
||||
return num;
|
||||
}
|
||||
|
||||
#if SDL_VERSION_ATLEAST( 2, 0, 0 )
|
||||
/*
|
||||
=============
|
||||
SDLash_JoyInit_New
|
||||
|
||||
=============
|
||||
*/
|
||||
static int SDLash_JoyInit_New( int numjoy )
|
||||
{
|
||||
int count, numJoysticks, i;
|
||||
|
||||
Con_Reportf( "Joystick: SDL GameController API\n" );
|
||||
if( SDL_WasInit( SDL_INIT_GAMECONTROLLER ) != SDL_INIT_GAMECONTROLLER &&
|
||||
SDL_InitSubSystem( SDL_INIT_GAMECONTROLLER ) )
|
||||
{
|
||||
Con_Reportf( "Failed to initialize SDL GameController API: %s\n", SDL_GetError() );
|
||||
return 0;
|
||||
}
|
||||
|
||||
SDL_GameControllerAddMappingsFromFile( "controllermappings.txt" );
|
||||
|
||||
count = 0;
|
||||
numJoysticks = SDL_NumJoysticks();
|
||||
for ( i = 0; i < numJoysticks; i++ )
|
||||
if( SDL_IsGameController( i ) )
|
||||
++count;
|
||||
|
||||
return count;
|
||||
}
|
||||
#endif // SDL_VERSION_ATLEAST( 2, 0, 0 )
|
||||
|
||||
/*
|
||||
=============
|
||||
Platform_JoyInit
|
||||
|
||||
=============
|
||||
*/
|
||||
int Platform_JoyInit( int numjoy )
|
||||
{
|
||||
#if SDL_VERSION_ATLEAST( 2, 0, 0 )
|
||||
// SDL_Joystick is now an old API
|
||||
// SDL_GameController is preferred
|
||||
if( !Sys_CheckParm( "-sdl_joy_old_api" ) )
|
||||
return SDLash_JoyInit_New(numjoy);
|
||||
#endif // SDL_VERSION_ATLEAST( 2, 0, 0 )
|
||||
return SDLash_JoyInit_Old(numjoy);
|
||||
}
|
||||
|
||||
/*
|
||||
========================
|
||||
SDLash_InitCursors
|
||||
@@ -209,6 +333,11 @@ void Platform_SetCursorType( VGUI_DefaultCursor type )
|
||||
{
|
||||
qboolean visible;
|
||||
|
||||
#if SDL_VERSION_ATLEAST( 2, 0, 0 )
|
||||
if( !cursors.initialized )
|
||||
return;
|
||||
#endif
|
||||
|
||||
switch( type )
|
||||
{
|
||||
case dc_user:
|
||||
@@ -221,7 +350,7 @@ void Platform_SetCursorType( VGUI_DefaultCursor type )
|
||||
}
|
||||
|
||||
// never disable cursor in touch emulation mode
|
||||
if( !visible && Touch_WantVisibleCursor( ))
|
||||
if( !visible && Touch_Emulated( ))
|
||||
return;
|
||||
|
||||
host.mouse_visible = visible;
|
||||
@@ -230,28 +359,11 @@ void Platform_SetCursorType( VGUI_DefaultCursor type )
|
||||
#if SDL_VERSION_ATLEAST( 2, 0, 0 )
|
||||
if( host.mouse_visible )
|
||||
{
|
||||
if( cursors.initialized )
|
||||
SDL_SetCursor( cursors.cursors[type] );
|
||||
|
||||
SDL_SetCursor( cursors.cursors[type] );
|
||||
SDL_ShowCursor( true );
|
||||
|
||||
// restore the last mouse position
|
||||
if( in_visible_cursor_pos.pushed )
|
||||
{
|
||||
SDL_WarpMouseInWindow( host.hWnd, in_visible_cursor_pos.x, in_visible_cursor_pos.y );
|
||||
in_visible_cursor_pos.pushed = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// save last mouse position and warp it to the center
|
||||
if( !in_visible_cursor_pos.pushed )
|
||||
{
|
||||
SDL_GetMouseState( &in_visible_cursor_pos.x, &in_visible_cursor_pos.y );
|
||||
SDL_WarpMouseInWindow( host.hWnd, host.window_center_x, host.window_center_y );
|
||||
in_visible_cursor_pos.pushed = true;
|
||||
}
|
||||
|
||||
SDL_ShowCursor( false );
|
||||
}
|
||||
#else
|
||||
@@ -306,3 +418,5 @@ key_modifier_t Platform_GetKeyModifiers( void )
|
||||
return KeyModifier_None;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif // XASH_DEDICATED
|
||||
|
||||
@@ -1,403 +0,0 @@
|
||||
/*
|
||||
joy_sdl.c - SDL gamepads
|
||||
Copyright (C) 2018-2025 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 <SDL.h>
|
||||
|
||||
#if SDL_VERSION_ATLEAST( 2, 0, 0 )
|
||||
#include "common.h"
|
||||
#include "keydefs.h"
|
||||
#include "input.h"
|
||||
#include "client.h"
|
||||
#include "events.h"
|
||||
|
||||
static const int g_button_mapping[] =
|
||||
{
|
||||
#if XASH_NSWITCH // devkitPro/SDL has inverted Nintendo layout for SDL_GameController
|
||||
K_B_BUTTON, K_A_BUTTON, K_Y_BUTTON, K_X_BUTTON,
|
||||
#else
|
||||
K_A_BUTTON, K_B_BUTTON, K_X_BUTTON, K_Y_BUTTON,
|
||||
#endif
|
||||
K_BACK_BUTTON, K_MODE_BUTTON, K_START_BUTTON,
|
||||
K_LSTICK, K_RSTICK,
|
||||
K_L1_BUTTON, K_R1_BUTTON,
|
||||
K_DPAD_UP, K_DPAD_DOWN, K_DPAD_LEFT, K_DPAD_RIGHT,
|
||||
K_MISC_BUTTON,
|
||||
K_PADDLE1_BUTTON, K_PADDLE2_BUTTON, K_PADDLE3_BUTTON, K_PADDLE4_BUTTON,
|
||||
K_TOUCHPAD,
|
||||
};
|
||||
|
||||
// Swap axis to follow default axis binding:
|
||||
static const engineAxis_t g_axis_mapping[] =
|
||||
{
|
||||
JOY_AXIS_SIDE, // SDL_CONTROLLER_AXIS_LEFTX,
|
||||
JOY_AXIS_FWD, // SDL_CONTROLLER_AXIS_LEFTY,
|
||||
JOY_AXIS_PITCH, // SDL_CONTROLLER_AXIS_RIGHTX,
|
||||
JOY_AXIS_YAW, // SDL_CONTROLLER_AXIS_RIGHTY,
|
||||
JOY_AXIS_LT, // SDL_CONTROLLER_AXIS_TRIGGERLEFT,
|
||||
JOY_AXIS_RT, // SDL_CONTROLLER_AXIS_TRIGGERRIGHT,
|
||||
};
|
||||
|
||||
static SDL_JoystickID g_current_gamepad_id = -1; // used to send rumble to
|
||||
static SDL_GameController *g_current_gamepad;
|
||||
static SDL_GameController **g_gamepads;
|
||||
static size_t g_num_gamepads;
|
||||
|
||||
#define CALIBRATION_TIME 10.0f
|
||||
|
||||
static struct
|
||||
{
|
||||
float time;
|
||||
vec3_t data;
|
||||
vec3_t calibrated_values;
|
||||
int samples;
|
||||
} gyrocal;
|
||||
|
||||
static void SDLash_RestartCalibration( void )
|
||||
{
|
||||
Joy_SetCalibrationState( JOY_NOT_CALIBRATED );
|
||||
|
||||
memset( &gyrocal, 0, sizeof( gyrocal ));
|
||||
|
||||
gyrocal.time = host.realtime + CALIBRATION_TIME;
|
||||
|
||||
Con_Printf( "Starting gyroscope calibration...\n" );
|
||||
}
|
||||
|
||||
static void SDLash_FinalizeCalibration( void )
|
||||
{
|
||||
float data_rate = 10.0f; // let's say we're polling at 10Hz?
|
||||
int min_samples;
|
||||
|
||||
#if SDL_VERSION_ATLEAST( 2, 0, 16 )
|
||||
data_rate = SDL_GameControllerGetSensorDataRate( g_current_gamepad, SDL_SENSOR_GYRO );
|
||||
if( !data_rate )
|
||||
data_rate = 10.0f;
|
||||
#endif
|
||||
|
||||
min_samples = Q_rint( CALIBRATION_TIME * data_rate * 0.75f );
|
||||
|
||||
// we waited for few seconds and got too few samples
|
||||
if( gyrocal.samples <= min_samples )
|
||||
{
|
||||
Joy_SetCalibrationState( JOY_FAILED_TO_CALIBRATE );
|
||||
return;
|
||||
}
|
||||
|
||||
VectorScale( gyrocal.data, 1.0f / gyrocal.samples, gyrocal.calibrated_values );
|
||||
Joy_SetCalibrationState( JOY_CALIBRATED );
|
||||
|
||||
Con_Printf( "Calibration done. Result: %f %f %f\n", gyrocal.calibrated_values[0], gyrocal.calibrated_values[1], gyrocal.calibrated_values[2] );
|
||||
|
||||
gyrocal.time = 0.0f;
|
||||
}
|
||||
|
||||
static void SDLash_GameControllerAddMappings( const char *name )
|
||||
{
|
||||
fs_offset_t len = 0;
|
||||
byte *p = FS_LoadFile( name, &len, false );
|
||||
|
||||
if( !p )
|
||||
return;
|
||||
|
||||
if( len > 0 && len < INT32_MAX ) // function accepts int, SDL3 fixes this
|
||||
{
|
||||
SDL_RWops *rwops = SDL_RWFromConstMem( p, (int)len );
|
||||
SDL_GameControllerAddMappingsFromRW( rwops, true );
|
||||
}
|
||||
|
||||
Mem_Free( p );
|
||||
}
|
||||
|
||||
static void SDLash_SetActiveGameController( SDL_JoystickID id )
|
||||
{
|
||||
SDL_GameController *oldgc;
|
||||
|
||||
if( g_current_gamepad_id == id )
|
||||
return;
|
||||
|
||||
g_current_gamepad_id = id;
|
||||
|
||||
oldgc = g_current_gamepad;
|
||||
#if SDL_VERSION_ATLEAST( 2, 0, 14 )
|
||||
SDL_GameControllerSetSensorEnabled( oldgc, SDL_SENSOR_GYRO, SDL_FALSE );
|
||||
#endif // SDL_VERSION_ATLEAST( 2, 0, 14 )
|
||||
|
||||
if( id < 0 )
|
||||
{
|
||||
g_current_gamepad = NULL;
|
||||
Joy_SetCapabilities( false );
|
||||
Joy_SetCalibrationState( JOY_NOT_CALIBRATED );
|
||||
}
|
||||
else
|
||||
{
|
||||
qboolean have_gyro = false;
|
||||
|
||||
g_current_gamepad = SDL_GameControllerFromInstanceID( id );
|
||||
|
||||
#if SDL_VERSION_ATLEAST( 2, 0, 14 )
|
||||
have_gyro = SDL_GameControllerHasSensor( g_current_gamepad, SDL_SENSOR_GYRO );
|
||||
|
||||
if( have_gyro )
|
||||
{
|
||||
SDL_GameControllerSetSensorEnabled( g_current_gamepad, SDL_SENSOR_GYRO, SDL_TRUE );
|
||||
SDLash_RestartCalibration();
|
||||
}
|
||||
#endif // SDL_VERSION_ATLEAST( 2, 0, 14 )
|
||||
|
||||
Joy_SetCapabilities( have_gyro );
|
||||
}
|
||||
}
|
||||
|
||||
static void SDLash_GameControllerAdded( int device_index )
|
||||
{
|
||||
SDL_GameController *gc;
|
||||
SDL_GameController **list;
|
||||
|
||||
gc = SDL_GameControllerOpen( device_index );
|
||||
if( !gc )
|
||||
{
|
||||
Con_Printf( S_ERROR "SDL_GameControllerOpen: %s\n", SDL_GetError( ));
|
||||
return;
|
||||
}
|
||||
|
||||
// this "game controller" only exists on Android within emulator and tries to map
|
||||
// keyboard events into game controller events, which as you can expect, doesn't
|
||||
// work and I don't understand the intention here. When debugging Xash in Android
|
||||
// Studio emulator, just enable hardware input passthrough.
|
||||
#if XASH_ANDROID
|
||||
if( !Q_strcmp( SDL_GameControllerName( gc ), "qwerty2" ))
|
||||
{
|
||||
SDL_GameControllerClose( gc );
|
||||
return;
|
||||
}
|
||||
#endif // XASH_ANDROID
|
||||
|
||||
list = Mem_Realloc( host.mempool, g_gamepads, sizeof( *list ) * ( g_num_gamepads + 1 ));
|
||||
list[g_num_gamepads++] = gc;
|
||||
|
||||
g_gamepads = list;
|
||||
|
||||
// set as current device if none other set
|
||||
if( g_current_gamepad_id < 0 )
|
||||
{
|
||||
SDL_Joystick *joy = SDL_GameControllerGetJoystick( gc );
|
||||
|
||||
if( joy )
|
||||
SDLash_SetActiveGameController( SDL_JoystickInstanceID( joy ));
|
||||
}
|
||||
|
||||
Con_Printf( "Detected \"%s\" game controller.\nMapping string: %s\n", SDL_GameControllerName( gc ), SDL_GameControllerMapping( gc ));
|
||||
}
|
||||
|
||||
static void SDLash_GameControllerRemoved( SDL_JoystickID id )
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if( id == g_current_gamepad_id )
|
||||
SDLash_SetActiveGameController( -1 );
|
||||
|
||||
// now close the device
|
||||
for( i = 0; i < g_num_gamepads; i++ )
|
||||
{
|
||||
SDL_GameController *gc = g_gamepads[i];
|
||||
SDL_Joystick *joy;
|
||||
|
||||
if( !gc )
|
||||
continue;
|
||||
|
||||
joy = SDL_GameControllerGetJoystick( gc );
|
||||
|
||||
if( !joy )
|
||||
continue;
|
||||
|
||||
if( SDL_JoystickInstanceID( joy ) == id )
|
||||
{
|
||||
Con_Printf( "Game controller \"%s\" was disconnected\n", SDL_GameControllerName( gc ));
|
||||
|
||||
SDL_GameControllerClose( gc );
|
||||
g_gamepads[i] = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void SDLash_GameControllerSensorUpdate( SDL_ControllerSensorEvent sensor )
|
||||
{
|
||||
vec3_t data;
|
||||
|
||||
if( sensor.which != g_current_gamepad_id )
|
||||
return;
|
||||
|
||||
if( sensor.sensor != SDL_SENSOR_GYRO )
|
||||
return;
|
||||
|
||||
if( gyrocal.time != 0.0f )
|
||||
{
|
||||
if( host.realtime > gyrocal.time )
|
||||
SDLash_FinalizeCalibration();
|
||||
|
||||
VectorAdd( gyrocal.data, sensor.data, gyrocal.data );
|
||||
gyrocal.samples++;
|
||||
|
||||
Joy_SetCalibrationState( JOY_CALIBRATING );
|
||||
return;
|
||||
}
|
||||
|
||||
VectorSubtract( sensor.data, gyrocal.calibrated_values, data );
|
||||
Joy_GyroEvent( data );
|
||||
}
|
||||
|
||||
void SDLash_HandleGameControllerEvent( SDL_Event *ev )
|
||||
{
|
||||
int x;
|
||||
|
||||
switch( ev->type )
|
||||
{
|
||||
case SDL_CONTROLLERAXISMOTION:
|
||||
SDLash_SetActiveGameController( ev->caxis.which );
|
||||
x = ev->caxis.axis;
|
||||
if( x >= 0 && x < ARRAYSIZE( g_axis_mapping ))
|
||||
Joy_AxisMotionEvent( g_axis_mapping[x], ev->caxis.value );
|
||||
break;
|
||||
case SDL_CONTROLLERBUTTONDOWN:
|
||||
case SDL_CONTROLLERBUTTONUP:
|
||||
SDLash_SetActiveGameController( ev->cbutton.which );
|
||||
x = ev->cbutton.button;
|
||||
if( x >= 0 && x < ARRAYSIZE( g_button_mapping ))
|
||||
Key_Event( g_button_mapping[x], ev->cbutton.state );
|
||||
break;
|
||||
case SDL_CONTROLLERDEVICEREMOVED:
|
||||
SDLash_GameControllerRemoved( ev->cdevice.which );
|
||||
break;
|
||||
case SDL_CONTROLLERDEVICEADDED:
|
||||
SDLash_GameControllerAdded( ev->cdevice.which );
|
||||
break;
|
||||
#if SDL_VERSION_ATLEAST( 2, 0, 14 )
|
||||
case SDL_CONTROLLERSENSORUPDATE:
|
||||
SDLash_GameControllerSensorUpdate( ev->csensor );
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void Platform_CalibrateGamepadGyro( void )
|
||||
{
|
||||
SDLash_RestartCalibration();
|
||||
}
|
||||
|
||||
void Platform_Vibrate2( float time, int val1, int val2, uint flags )
|
||||
{
|
||||
#if SDL_VERSION_ATLEAST( 2, 0, 9 )
|
||||
SDL_GameController *gc = g_current_gamepad;
|
||||
Uint32 ms;
|
||||
|
||||
if( g_current_gamepad_id < 0 || !gc )
|
||||
return;
|
||||
|
||||
if( val1 < 0 )
|
||||
val1 = COM_RandomLong( 0x7FFF, 0xFFFF );
|
||||
|
||||
if( val2 < 0 )
|
||||
val2 = COM_RandomLong( 0x7FFF, 0xFFFF );
|
||||
|
||||
ms = (Uint32)ceil( time );
|
||||
SDL_GameControllerRumble( gc, val1, val2, ms );
|
||||
#endif // SDL_VERSION_ATLEAST( 2, 0, 9 )
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
Platform_Vibrate
|
||||
|
||||
=============
|
||||
*/
|
||||
void Platform_Vibrate( float time, char flags )
|
||||
{
|
||||
Platform_Vibrate2( time, -1, -1, flags );
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
Platform_JoyInit
|
||||
|
||||
=============
|
||||
*/
|
||||
int Platform_JoyInit( void )
|
||||
{
|
||||
int count, numJoysticks, i;
|
||||
|
||||
Con_Reportf( "Joystick: SDL GameController API\n" );
|
||||
if( SDL_WasInit( SDL_INIT_GAMECONTROLLER ) != SDL_INIT_GAMECONTROLLER &&
|
||||
SDL_InitSubSystem( SDL_INIT_GAMECONTROLLER ))
|
||||
{
|
||||
Con_Reportf( "Failed to initialize SDL GameController API: %s\n", SDL_GetError( ));
|
||||
return 0;
|
||||
}
|
||||
|
||||
SDLash_GameControllerAddMappings( "gamecontrollerdb.txt" ); // shipped in extras.pk3
|
||||
SDLash_GameControllerAddMappings( "controllermappings.txt" );
|
||||
|
||||
count = 0;
|
||||
numJoysticks = SDL_NumJoysticks();
|
||||
for ( i = 0; i < numJoysticks; i++ )
|
||||
{
|
||||
if( SDL_IsGameController( i ))
|
||||
++count;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
Platform_JoyShutdown
|
||||
|
||||
=============
|
||||
*/
|
||||
void Platform_JoyShutdown( void )
|
||||
{
|
||||
size_t i;
|
||||
|
||||
SDLash_SetActiveGameController( -1 );
|
||||
|
||||
for( i = 0; i < g_num_gamepads; i++ )
|
||||
{
|
||||
if( !g_gamepads[i] )
|
||||
continue;
|
||||
|
||||
SDL_GameControllerClose( g_gamepads[i] );
|
||||
g_gamepads[i] = NULL;
|
||||
}
|
||||
|
||||
Mem_Free( g_gamepads );
|
||||
g_gamepads = NULL;
|
||||
g_num_gamepads = 0;
|
||||
|
||||
SDL_QuitSubSystem( SDL_INIT_GAMECONTROLLER );
|
||||
}
|
||||
#else // SDL_VERSION_ATLEAST( 2, 0, 0 )
|
||||
void Platform_Vibrate( float time, char flags )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
int Platform_JoyInit( void )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Platform_JoyShutdown( void )
|
||||
{
|
||||
|
||||
}
|
||||
#endif
|
||||
@@ -175,7 +175,7 @@ qboolean SNDDMA_Init( void )
|
||||
if( !samplecount )
|
||||
samplecount = 0x8000;
|
||||
dma.samples = samplecount * obtained.channels;
|
||||
dma.buffer = Mem_Calloc( sndpool, dma.samples * 2 );
|
||||
dma.buffer = Z_Calloc( dma.samples * 2 );
|
||||
dma.samplepos = 0;
|
||||
|
||||
sdl_format = obtained.format;
|
||||
|
||||
@@ -20,9 +20,9 @@ GNU General Public License for more details.
|
||||
#if XASH_TIMER == TIMER_SDL
|
||||
double Platform_DoubleTime( void )
|
||||
{
|
||||
static Uint64 g_PerformanceFrequency;
|
||||
static Uint64 g_ClockStart;
|
||||
Uint64 CurrentTime;
|
||||
static longtime_t g_PerformanceFrequency;
|
||||
static longtime_t g_ClockStart;
|
||||
longtime_t CurrentTime;
|
||||
|
||||
if( !g_PerformanceFrequency )
|
||||
{
|
||||
@@ -32,11 +32,6 @@ double Platform_DoubleTime( void )
|
||||
CurrentTime = SDL_GetPerformanceCounter();
|
||||
return (double)( CurrentTime - g_ClockStart ) / (double)( g_PerformanceFrequency );
|
||||
}
|
||||
|
||||
void Platform_Sleep( int msec )
|
||||
{
|
||||
SDL_Delay( msec );
|
||||
}
|
||||
#endif // XASH_TIMER == TIMER_SDL
|
||||
|
||||
#if XASH_MESSAGEBOX == MSGBOX_SDL
|
||||
@@ -83,19 +78,8 @@ static void SDLCALL SDLash_LogOutputFunction( void *userdata, int category, SDL_
|
||||
}
|
||||
}
|
||||
|
||||
void SDLash_Init( const char *basedir )
|
||||
void SDLash_Init( void )
|
||||
{
|
||||
#if XASH_APPLE
|
||||
char *path = SDL_GetBasePath();
|
||||
if( path != NULL )
|
||||
{
|
||||
char buf[MAX_VA_STRING];
|
||||
|
||||
Q_snprintf( buf, sizeof( buf ), "%s%s/extras.pk3", path, basedir );
|
||||
setenv( "XASH3D_EXTRAS_PAK1", buf, true );
|
||||
}
|
||||
#endif
|
||||
|
||||
SDL_LogSetOutputFunction( SDLash_LogOutputFunction, NULL );
|
||||
|
||||
if( host_developer.value >= 2 )
|
||||
@@ -114,11 +98,8 @@ void SDLash_Init( const char *basedir )
|
||||
host.type = HOST_DEDICATED;
|
||||
}
|
||||
|
||||
#if SDL_MAJOR_VERSION >= 2
|
||||
SDL_SetHint( SDL_HINT_ACCELEROMETER_AS_JOYSTICK, "0" );
|
||||
SDL_SetHint( SDL_HINT_MOUSE_TOUCH_EVENTS, "0" );
|
||||
SDL_SetHint( SDL_HINT_TOUCH_MOUSE_EVENTS, "0" );
|
||||
|
||||
#if XASH_SDL == 2
|
||||
SDL_SetHint(SDL_HINT_ACCELEROMETER_AS_JOYSTICK, "0");
|
||||
SDL_StopTextInput();
|
||||
#endif // XASH_SDL == 2
|
||||
|
||||
|
||||
@@ -257,8 +257,7 @@ static void R_InitVideoModes( void )
|
||||
{
|
||||
char buf[MAX_VA_STRING];
|
||||
#if SDL_VERSION_ATLEAST( 2, 0, 0 )
|
||||
SDL_Point point = { window_xpos.value, window_ypos.value };
|
||||
int displayIndex = SDL_GetPointDisplayIndex( &point );
|
||||
int displayIndex = 0; // TODO: handle multiple displays somehow
|
||||
int i, modes;
|
||||
|
||||
num_vidmodes = 0;
|
||||
@@ -488,7 +487,13 @@ GL_UpdateSwapInterval
|
||||
void GL_UpdateSwapInterval( void )
|
||||
{
|
||||
#if SDL_VERSION_ATLEAST( 2, 0, 0 )
|
||||
if( FBitSet( gl_vsync.flags, FCVAR_CHANGED ))
|
||||
// disable VSync while level is loading
|
||||
if( cls.state < ca_active )
|
||||
{
|
||||
SDL_GL_SetSwapInterval( 0 );
|
||||
SetBits( gl_vsync.flags, FCVAR_CHANGED );
|
||||
}
|
||||
else if( FBitSet( gl_vsync.flags, FCVAR_CHANGED ))
|
||||
{
|
||||
ClearBits( gl_vsync.flags, FCVAR_CHANGED );
|
||||
|
||||
@@ -730,24 +735,6 @@ static qboolean VID_CreateWindowWithSafeGL( const char *wndname, int xpos, int y
|
||||
return true;
|
||||
}
|
||||
|
||||
static qboolean RectFitsInDisplay( const SDL_Rect *rect, const SDL_Rect *display )
|
||||
{
|
||||
return rect->x >= display->x
|
||||
&& rect->y >= display->y
|
||||
&& rect->x + rect->w <= display->x + display->w
|
||||
&& rect->y + rect->h <= display->y + display->h;
|
||||
}
|
||||
// Function to check if the rectangle fits in any display
|
||||
static qboolean RectFitsInAnyDisplay( const SDL_Rect *rect, const SDL_Rect *display_rects, int num_displays )
|
||||
{
|
||||
for( int i = 0; i < num_displays; i++ )
|
||||
{
|
||||
if( RectFitsInDisplay( rect, &display_rects[i] ))
|
||||
return true; // Rectangle fits in this display
|
||||
}
|
||||
return false; // Rectangle does not fit in any display
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
VID_CreateWindow
|
||||
@@ -760,8 +747,6 @@ qboolean VID_CreateWindow( int width, int height, window_mode_t window_mode )
|
||||
qboolean maximized = vid_maximized.value != 0.0f;
|
||||
Uint32 wndFlags = SDL_WINDOW_SHOWN | SDL_WINDOW_MOUSE_FOCUS;
|
||||
int xpos, ypos;
|
||||
int num_displays = SDL_GetNumVideoDisplays();
|
||||
SDL_Rect rect = { window_xpos.value, window_ypos.value, width, height };
|
||||
|
||||
Q_strncpy( wndname, GI->title, sizeof( wndname ));
|
||||
|
||||
@@ -772,43 +757,35 @@ qboolean VID_CreateWindow( int width, int height, window_mode_t window_mode )
|
||||
|
||||
if( window_mode == WINDOW_MODE_WINDOWED )
|
||||
{
|
||||
SDL_Rect *display_rects = ( SDL_Rect * )malloc( num_displays * sizeof( SDL_Rect ));
|
||||
|
||||
SDL_Rect r;
|
||||
|
||||
SetBits( wndFlags, SDL_WINDOW_RESIZABLE );
|
||||
if( maximized )
|
||||
SetBits( wndFlags, SDL_WINDOW_MAXIMIZED );
|
||||
|
||||
if( !display_rects )
|
||||
#if SDL_VERSION_ATLEAST( 2, 0, 5 )
|
||||
if( SDL_GetDisplayUsableBounds( 0, &r ) < 0 &&
|
||||
SDL_GetDisplayBounds( 0, &r ) < 0 )
|
||||
#else
|
||||
if( SDL_GetDisplayBounds( 0, &r ) < 0 )
|
||||
#endif
|
||||
{
|
||||
Con_Printf( S_ERROR "Failed to allocate memory for display rects!\n" );
|
||||
xpos = SDL_WINDOWPOS_UNDEFINED;
|
||||
ypos = SDL_WINDOWPOS_UNDEFINED;
|
||||
Con_Reportf( S_ERROR "%s: SDL_GetDisplayBounds failed: %s\n", __func__, SDL_GetError( ));
|
||||
xpos = SDL_WINDOWPOS_CENTERED;
|
||||
ypos = SDL_WINDOWPOS_CENTERED;
|
||||
}
|
||||
else
|
||||
{
|
||||
for( int i = 0; i < num_displays; i++ )
|
||||
{
|
||||
if( SDL_GetDisplayBounds( i, &display_rects[i] ) != 0 )
|
||||
{
|
||||
Con_Printf( S_ERROR "Failed to get bounds for display %d! SDL_Error: %s\n", i, SDL_GetError());
|
||||
display_rects[i] = ( SDL_Rect ){ 0, 0, 0, 0 };
|
||||
}
|
||||
}
|
||||
// Check if the rectangle fits in any display
|
||||
if( !RectFitsInAnyDisplay( &rect, display_rects, num_displays ))
|
||||
{
|
||||
// Rectangle doesn't fit in any display, center it
|
||||
xpos = window_xpos.value;
|
||||
ypos = window_ypos.value;
|
||||
|
||||
// don't create window outside of usable display space
|
||||
if( xpos < r.x || xpos + width > r.x + r.w )
|
||||
xpos = SDL_WINDOWPOS_CENTERED;
|
||||
|
||||
if( ypos < r.y || ypos + height > r.y + r.h )
|
||||
ypos = SDL_WINDOWPOS_CENTERED;
|
||||
Con_Printf( S_ERROR "Rectangle does not fit in any display. Centering window.\n" );
|
||||
}
|
||||
else
|
||||
{
|
||||
xpos = rect.x;
|
||||
ypos = rect.y;
|
||||
}
|
||||
}
|
||||
free( display_rects );
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -818,16 +795,7 @@ qboolean VID_CreateWindow( int width, int height, window_mode_t window_mode )
|
||||
else
|
||||
SetBits( wndFlags, SDL_WINDOW_FULLSCREEN_DESKTOP );
|
||||
SetBits( wndFlags, SDL_WINDOW_BORDERLESS );
|
||||
if ( window_xpos.value < 0 || window_ypos.value < 0 )
|
||||
{
|
||||
xpos = SDL_WINDOWPOS_UNDEFINED;
|
||||
ypos = SDL_WINDOWPOS_UNDEFINED;
|
||||
}
|
||||
else
|
||||
{
|
||||
xpos = window_xpos.value;
|
||||
ypos = window_ypos.value;
|
||||
}
|
||||
xpos = ypos = 0;
|
||||
}
|
||||
|
||||
if( !VID_CreateWindowWithSafeGL( wndname, xpos, ypos, width, height, wndFlags ))
|
||||
@@ -1050,8 +1018,7 @@ qboolean R_Init_Video( const int type )
|
||||
|
||||
#if SDL_VERSION_ATLEAST( 2, 0, 0 )
|
||||
SDL_DisplayMode displayMode;
|
||||
SDL_Point point = { window_xpos.value, window_ypos.value };
|
||||
SDL_GetCurrentDisplayMode( SDL_GetPointDisplayIndex( &point ), &displayMode );
|
||||
SDL_GetCurrentDisplayMode( 0, &displayMode );
|
||||
refState.desktopBitsPixel = SDL_BITSPERPIXEL( displayMode.format );
|
||||
#else
|
||||
refState.desktopBitsPixel = 16;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user