mirror of
https://github.com/FWGS/xash3d-fwgs.git
synced 2026-08-05 19:45:05 +08:00
Compare commits
229 Commits
continuous
...
continuous
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7ba2209124 | ||
|
|
af6b434b71 | ||
|
|
052ea6a8bd | ||
|
|
448dc720ed | ||
|
|
75b15696f8 | ||
|
|
7fb113f610 | ||
|
|
0497e00ad2 | ||
|
|
9c50288bbb | ||
|
|
c5d4af802c | ||
|
|
340a8b5e0c | ||
|
|
bc1b86c19c | ||
|
|
b605cf603e | ||
|
|
fdc2ed8093 | ||
|
|
a27375d1f5 | ||
|
|
0e2abf9040 | ||
|
|
89430400d9 | ||
|
|
f1a9d408bf | ||
|
|
6529692244 | ||
|
|
51d11f8e86 | ||
|
|
c5397191e5 | ||
|
|
44426709f7 | ||
|
|
2d8f747e84 | ||
|
|
0dd5a60410 | ||
|
|
eec8129be4 | ||
|
|
934c5e018d | ||
|
|
d658d8cc78 | ||
|
|
ca9a3f0491 | ||
|
|
1510cb458f | ||
|
|
30cabb8107 | ||
|
|
64ee956618 | ||
|
|
39659644bf | ||
|
|
eb09af0b08 | ||
|
|
91a4ace12c | ||
|
|
2ad2e46b30 | ||
|
|
627444279f | ||
|
|
3550bdb30d | ||
|
|
c201b895eb | ||
|
|
72f1ac3780 | ||
|
|
d7dc3192de | ||
|
|
43ea65fffc | ||
|
|
a72d921c12 | ||
|
|
99b7d71824 | ||
|
|
67c73bdcbe | ||
|
|
8b1dbcf166 | ||
|
|
5f60095dc4 | ||
|
|
c7282b488b | ||
|
|
afa829d996 | ||
|
|
c06ea8d915 | ||
|
|
bf344282ec | ||
|
|
21f62910ac | ||
|
|
54552d93ef | ||
|
|
97455e7fd4 | ||
|
|
6087d43043 | ||
|
|
c1a96d3ff1 | ||
|
|
e27d20dfa3 | ||
|
|
890e12ec76 | ||
|
|
774d2ac28a | ||
|
|
960d724828 | ||
|
|
32aa1f91bf | ||
|
|
bd3634c815 | ||
|
|
eda0ac92cc | ||
|
|
546903ea05 | ||
|
|
4975001795 | ||
|
|
a078ad1f51 | ||
|
|
8307f671d4 | ||
|
|
241fab02b1 | ||
|
|
1bfee70477 | ||
|
|
eb51d17cd2 | ||
|
|
b5cb0b9f10 | ||
|
|
a955d1e957 | ||
|
|
2b2c967e85 | ||
|
|
c48d93e3ce | ||
|
|
8f257cc331 | ||
|
|
151e7fe37b | ||
|
|
add02dc6f9 | ||
|
|
d4c34abd6e | ||
|
|
1d81e611f0 | ||
|
|
6a0038e26a | ||
|
|
1d99f65e86 | ||
|
|
5e524bca60 | ||
|
|
cf3e56e275 | ||
|
|
ade560c601 | ||
|
|
62e3ba2126 | ||
|
|
674a4e5883 | ||
|
|
f911210b81 | ||
|
|
14eb07653c | ||
|
|
54b0cf9991 | ||
|
|
3ebcb08a97 | ||
|
|
23940f8590 | ||
|
|
687fb0123f | ||
|
|
6c91fdb0cd | ||
|
|
4832232fd6 | ||
|
|
185bce0489 | ||
|
|
f460aa63b0 | ||
|
|
22f8b6f9c3 | ||
|
|
0cb034afc2 | ||
|
|
d0464ef602 | ||
|
|
c3ebb84b97 | ||
|
|
11742efbc3 | ||
|
|
95af635ab4 | ||
|
|
1abec80191 | ||
|
|
93ebddfba3 | ||
|
|
5378494199 | ||
|
|
1b44d7733e | ||
|
|
694c630b44 | ||
|
|
7df1d4b9e2 | ||
|
|
b16037eabf | ||
|
|
bff7299f9b | ||
|
|
de196b1c58 | ||
|
|
a0eec8b85d | ||
|
|
c7e8ea2ffa | ||
|
|
1c1cf3d646 | ||
|
|
9759b80b78 | ||
|
|
94b2c0b443 | ||
|
|
ff8d17a5a8 | ||
|
|
aa23196a55 | ||
|
|
83b488c37e | ||
|
|
77abf621d7 | ||
|
|
f9d4ac2771 | ||
|
|
f076d84975 | ||
|
|
faf0b32a94 | ||
|
|
feb80e5997 | ||
|
|
578a77518f | ||
|
|
2457ecf226 | ||
|
|
8cd99885f1 | ||
|
|
684e229ac8 | ||
|
|
c0f1d8c647 | ||
|
|
c3b8696957 | ||
|
|
3ca413dbab | ||
|
|
92dc04ff3c | ||
|
|
ad6db91285 | ||
|
|
90a0f74087 | ||
|
|
4f7f5288a1 | ||
|
|
c23b4bfe61 | ||
|
|
4780f70ea2 | ||
|
|
98a04c7764 | ||
|
|
7da9772143 | ||
|
|
f0b29bac1b | ||
|
|
7b5ff606bd | ||
|
|
3e22ee64ae | ||
|
|
c86c45503f | ||
|
|
ef75a4c28d | ||
|
|
bccd3f2271 | ||
|
|
7bbc3e8238 | ||
|
|
c34e0c66d9 | ||
|
|
e5d80878b8 | ||
|
|
1e075d25b7 | ||
|
|
d29e53481d | ||
|
|
d23a2fd2df | ||
|
|
f6f15cc204 | ||
|
|
4f2249ed8e | ||
|
|
9f322df498 | ||
|
|
b554d7e215 | ||
|
|
719093c10b | ||
|
|
c2da140ccc | ||
|
|
375998dffb | ||
|
|
787444f63d | ||
|
|
0c50076ff0 | ||
|
|
8ce01c38c7 | ||
|
|
cac6206984 | ||
|
|
a5c88bdda9 | ||
|
|
fc017286a6 | ||
|
|
20d4e3e719 | ||
|
|
4eaa32fc10 | ||
|
|
b7c025b167 | ||
|
|
f29c588e0f | ||
|
|
2065ef143a | ||
|
|
a5c02c85f0 | ||
|
|
9a8761f1d8 | ||
|
|
273990d292 | ||
|
|
0e27d8717c | ||
|
|
8a9b209db0 | ||
|
|
232d1f8583 | ||
|
|
6cfa5877a4 | ||
|
|
154df00f94 | ||
|
|
c5649c94d5 | ||
|
|
a1da10fe38 | ||
|
|
17a71ffc96 | ||
|
|
4609fbc0c5 | ||
|
|
d278d3bdd7 | ||
|
|
7811b60292 | ||
|
|
870fad5606 | ||
|
|
3e93aa459d | ||
|
|
626c5e44f6 | ||
|
|
c906aa0106 | ||
|
|
0a41b70e44 | ||
|
|
ea338adc46 | ||
|
|
5fa777578b | ||
|
|
5b9db5940b | ||
|
|
4b1b3aa13c | ||
|
|
2d51d23d89 | ||
|
|
b5b6dad39c | ||
|
|
a5619e9960 | ||
|
|
a75666a3cd | ||
|
|
49426721d8 | ||
|
|
04125284a3 | ||
|
|
1d4f7b2f94 | ||
|
|
38c82a3f76 | ||
|
|
785632a437 | ||
|
|
4be75af214 | ||
|
|
dcdca01e86 | ||
|
|
201d9c8f80 | ||
|
|
69341e36a3 | ||
|
|
3532a77643 | ||
|
|
35dc072b26 | ||
|
|
f92a3695b3 | ||
|
|
a7b776f3b9 | ||
|
|
f2fb668c9e | ||
|
|
90e493fa3a | ||
|
|
692bcc4073 | ||
|
|
823642b10d | ||
|
|
07189ca2f5 | ||
|
|
0d55441830 | ||
|
|
98ff33d9e2 | ||
|
|
baa8fbaaec | ||
|
|
a0b46da04b | ||
|
|
e70ba7ad64 | ||
|
|
8a41be9d47 | ||
|
|
47aff9e30b | ||
|
|
ced8744ac9 | ||
|
|
734c07ddab | ||
|
|
ceb603488a | ||
|
|
80bac157eb | ||
|
|
b45581c630 | ||
|
|
d4fe3d6f8a | ||
|
|
1907485895 | ||
|
|
cfebb3e1d6 | ||
|
|
f9a0057c28 | ||
|
|
ceb2b0c5e4 |
@@ -1,10 +1,10 @@
|
||||
task:
|
||||
name: freebsd-14-amd64
|
||||
freebsd_instance:
|
||||
image_family: freebsd-14-0
|
||||
image_family: freebsd-14-2
|
||||
setup_script:
|
||||
- pkg update
|
||||
- pkg install -y pkgconf git sdl2 python fontconfig opus
|
||||
- pkg install -y pkgconf git sdl2 python fontconfig libvorbis opusfile bzip2 libbacktrace
|
||||
- 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 opus
|
||||
- pkg install -y pkgconf git sdl2 python fontconfig libvorbis opusfile bzip2 libbacktrace
|
||||
- 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.30.10
|
||||
SDL_VERSION: 2.30.12
|
||||
GH_CPU_ARCH: ${{ matrix.targetarch }}
|
||||
GH_CROSSCOMPILING: ${{ matrix.cross }}
|
||||
steps:
|
||||
@@ -87,6 +87,7 @@ jobs:
|
||||
path: artifacts/*
|
||||
flatpak:
|
||||
runs-on: ubuntu-latest
|
||||
continue-on-error: true
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
@@ -100,7 +101,7 @@ jobs:
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: Build flatpak (Compat.i386)
|
||||
uses: FWGS/flatpak-github-actions/flatpak-builder@v6.3
|
||||
uses: FWGS/flatpak-github-actions/flatpak-builder@v6.3-fix
|
||||
with:
|
||||
bundle: ${{ matrix.app }}.flatpak
|
||||
manifest-path: scripts/flatpak/${{ matrix.app }}.yml
|
||||
@@ -119,7 +120,6 @@ jobs:
|
||||
--yes \
|
||||
--cleanup-tag \
|
||||
--repo "$GITHUB_REPOSITORY" || true
|
||||
sleep 20s
|
||||
gh run download "$GITHUB_RUN_ID" \
|
||||
--dir artifacts/ \
|
||||
--repo "$GITHUB_REPOSITORY"
|
||||
|
||||
3
.gitmodules
vendored
3
.gitmodules
vendored
@@ -34,3 +34,6 @@
|
||||
[submodule "3rdparty/opusfile/opusfile"]
|
||||
path = 3rdparty/opusfile/opusfile
|
||||
url = https://gitlab.xiph.org/xiph/opusfile.git
|
||||
[submodule "3rdparty/libbacktrace/libbacktrace"]
|
||||
path = 3rdparty/libbacktrace/libbacktrace
|
||||
url = https://github.com/ianlancetaylor/libbacktrace
|
||||
|
||||
1
3rdparty/extras/wscript
vendored
1
3rdparty/extras/wscript
vendored
@@ -25,5 +25,4 @@ 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: 1bdeab2d8f...0c83a63d00
2
3rdparty/gl4es/gl4es
vendored
2
3rdparty/gl4es/gl4es
vendored
Submodule 3rdparty/gl4es/gl4es updated: e39434a2b1...a744af14d4
1
3rdparty/libbacktrace/libbacktrace
vendored
Submodule
1
3rdparty/libbacktrace/libbacktrace
vendored
Submodule
Submodule 3rdparty/libbacktrace/libbacktrace added at 78af4ffa26
185
3rdparty/libbacktrace/wscript
vendored
Normal file
185
3rdparty/libbacktrace/wscript
vendored
Normal file
@@ -0,0 +1,185 @@
|
||||
#! /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: 734a6d1ca2...1b6929d663
@@ -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 or Dproto.
|
||||
But keep in mind, there are requirement for server to be able to accept connections from Xash3D-based clients: it should use Reunion.
|
||||
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,6 +38,9 @@ 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
15
README.md
15
README.md
@@ -1,8 +1,9 @@
|
||||
# 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://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)
|
||||
[](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)
|
||||
|
||||
Xash3D (pronounced `[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.
|
||||
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.
|
||||
|
||||
Xash3D FWGS is a heavily modified fork of an original [Xash3D Engine](https://www.moddb.com/engines/xash3d-engine) by Unkle Mike.
|
||||
|
||||
@@ -65,21 +66,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 libfontconfig-dev:i386 libfreetype-dev:i386 libopus-dev:i386 libbz2-dev:i386`.
|
||||
* 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`.
|
||||
* 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 libfontconfig-dev libfreetype6-dev libopus-dev libbz2-dev`.
|
||||
* Install development tools: `$ sudo apt install git build-essential python libsdl2-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 fontconfig-devel.i686 freetype-devel.i686 bzip2-devel.i686`.
|
||||
* 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`.
|
||||
* 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 fontconfig-devel freetype-devel bzip2-devel`.
|
||||
* Install development tools: `$ sudo dnf install git gcc gcc-c++ SDL2-devel opus-devel freetype-devel bzip2-devel`.
|
||||
|
||||
* Clone this repostory: `$ git clone --recursive https://github.com/FWGS/xash3d-fwgs`.
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ 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
|
||||
${PYTHON_EXECUTABLE} waf configure -T ${BUILD_TYPE} -o "${CMAKE_CURRENT_BINARY_DIR}/xash3d-fwgs" ${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}"
|
||||
|
||||
@@ -96,6 +96,7 @@ android {
|
||||
packaging {
|
||||
jniLibs {
|
||||
useLegacyPackaging = true
|
||||
keepDebugSymbols.add("**/*.so")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -112,7 +113,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")
|
||||
|
||||
@@ -30,6 +30,18 @@ public class XashActivity extends SDLActivity {
|
||||
AndroidBug5497Workaround.assistActivity(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy()
|
||||
{
|
||||
super.onDestroy();
|
||||
|
||||
// Now that we don't exit from native code, we need to exit here, resetting
|
||||
// application state (actually global variables that we don't cleanup on exit)
|
||||
//
|
||||
// When the issue with global variables will be resolved, remove that exit() call
|
||||
System.exit(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String[] getLibraries() {
|
||||
return new String[]{"SDL2", "xash"};
|
||||
|
||||
@@ -16,8 +16,6 @@ GNU General Public License for more details.
|
||||
#ifndef BSPFILE_H
|
||||
#define BSPFILE_H
|
||||
|
||||
//#define SUPPORT_BSP2_FORMAT // allow to loading Darkplaces BSP2 maps (with broke binary compatibility)
|
||||
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
@@ -65,7 +63,6 @@ BRUSH MODELS
|
||||
#define MAX_MAP_CLIPNODES_BSP2 524288
|
||||
|
||||
// these limis not using by modelloader but only for displaying 'mapstats' correctly
|
||||
#ifdef SUPPORT_BSP2_FORMAT
|
||||
#define MAX_MAP_MODELS 2048 // embedded models
|
||||
#define MAX_MAP_ENTSTRING 0x200000 // 2 Mb should be enough
|
||||
#define MAX_MAP_PLANES 131072 // can be increased without problems
|
||||
@@ -75,18 +72,6 @@ BRUSH MODELS
|
||||
#define MAX_MAP_VERTS 524288 // can be increased without problems
|
||||
#define MAX_MAP_FACES 262144 // can be increased without problems
|
||||
#define MAX_MAP_MARKSURFACES 524288 // can be increased without problems
|
||||
#else
|
||||
// increased to match PrimeXT compilers
|
||||
#define MAX_MAP_MODELS 1024 // embedded models
|
||||
#define MAX_MAP_ENTSTRING 0x100000 // 1 Mb should be enough
|
||||
#define MAX_MAP_PLANES 65536 // can be increased without problems
|
||||
#define MAX_MAP_NODES 32767 // because negative shorts are leafs
|
||||
#define MAX_MAP_CLIPNODES MAX_MAP_CLIPNODES_HLBSP // because negative shorts are contents
|
||||
#define MAX_MAP_LEAFS 32767 // signed short limit
|
||||
#define MAX_MAP_VERTS 65535 // unsigned short limit
|
||||
#define MAX_MAP_FACES 65535 // unsigned short limit
|
||||
#define MAX_MAP_MARKSURFACES 65535 // unsigned short limit
|
||||
#endif
|
||||
|
||||
#define MAX_MAP_ENTITIES 8192 // network limit
|
||||
#define MAX_MAP_TEXINFO MAX_MAP_FACES // in theory each face may have personal texinfo
|
||||
|
||||
@@ -60,26 +60,29 @@ typedef struct
|
||||
vec3_t position;
|
||||
} mvertex_t;
|
||||
|
||||
typedef struct
|
||||
typedef struct mclipnode32_s
|
||||
{
|
||||
int planenum;
|
||||
#ifdef SUPPORT_BSP2_FORMAT
|
||||
int children[2]; // negative numbers are contents
|
||||
#else
|
||||
short children[2]; // negative numbers are contents
|
||||
#endif
|
||||
} mclipnode_t;
|
||||
int planenum;
|
||||
int children[2]; // negative numbers are contents
|
||||
} mclipnode32_t;
|
||||
|
||||
typedef struct mclipnode16_s
|
||||
{
|
||||
int planenum;
|
||||
short children[2]; // negative numbers are contents
|
||||
} mclipnode16_t;
|
||||
|
||||
// size is matched but representation is not
|
||||
typedef struct
|
||||
typedef struct medge32_s
|
||||
{
|
||||
#ifdef SUPPORT_BSP2_FORMAT
|
||||
unsigned int v[2];
|
||||
#else
|
||||
} medge32_t;
|
||||
|
||||
typedef struct medge16_s
|
||||
{
|
||||
unsigned short v[2];
|
||||
unsigned int cachededgeoffset;
|
||||
#endif
|
||||
} medge_t;
|
||||
} medge16_t;
|
||||
|
||||
typedef struct texture_s
|
||||
{
|
||||
@@ -156,13 +159,31 @@ typedef struct mnode_s
|
||||
|
||||
// node specific
|
||||
mplane_t *plane;
|
||||
struct mnode_s *children[2];
|
||||
#ifdef SUPPORT_BSP2_FORMAT
|
||||
int firstsurface;
|
||||
int numsurfaces;
|
||||
|
||||
#if !XASH_64BIT
|
||||
union
|
||||
{
|
||||
struct mnode_s *children_[2];
|
||||
struct
|
||||
{
|
||||
// the ordering is important
|
||||
int child_0_leaf : 1;
|
||||
int child_0_off : 23;
|
||||
int firstsurface_1 : 8;
|
||||
int child_1_leaf : 1;
|
||||
int child_1_off : 23;
|
||||
int numsurfaces_1 : 8;
|
||||
};
|
||||
};
|
||||
unsigned short firstsurface_0;
|
||||
unsigned short numsurfaces_0;
|
||||
#else
|
||||
unsigned short firstsurface;
|
||||
unsigned short numsurfaces;
|
||||
// in 64-bit ABI this struct has 4 more bytes of padding, let's use it!
|
||||
struct mnode_s *children_[2];
|
||||
unsigned short firstsurface_0;
|
||||
unsigned short numsurfaces_0;
|
||||
unsigned short firstsurface_1;
|
||||
unsigned short numsurfaces_1;
|
||||
#endif
|
||||
} mnode_t;
|
||||
|
||||
@@ -203,7 +224,6 @@ typedef struct mleaf_s
|
||||
int nummarksurfaces;
|
||||
int cluster; // helper to acess to uncompressed visdata
|
||||
byte ambient_sound_level[NUM_AMBIENTS];
|
||||
|
||||
} mleaf_t;
|
||||
|
||||
// surface extradata
|
||||
@@ -291,7 +311,11 @@ struct msurface_s
|
||||
|
||||
typedef struct hull_s
|
||||
{
|
||||
mclipnode_t *clipnodes;
|
||||
union
|
||||
{
|
||||
mclipnode16_t *clipnodes16;
|
||||
mclipnode32_t *clipnodes32;
|
||||
};
|
||||
mplane_t *planes;
|
||||
int firstclipnode;
|
||||
int lastclipnode;
|
||||
@@ -341,7 +365,12 @@ typedef struct model_s
|
||||
mvertex_t *vertexes;
|
||||
|
||||
int numedges;
|
||||
medge_t *edges;
|
||||
union
|
||||
{
|
||||
medge16_t *edges16;
|
||||
medge32_t *edges32;
|
||||
};
|
||||
|
||||
|
||||
int numnodes;
|
||||
mnode_t *nodes;
|
||||
@@ -356,7 +385,11 @@ typedef struct model_s
|
||||
int *surfedges;
|
||||
|
||||
int numclipnodes;
|
||||
mclipnode_t *clipnodes;
|
||||
union
|
||||
{
|
||||
mclipnode16_t *clipnodes16;
|
||||
mclipnode32_t *clipnodes32;
|
||||
};
|
||||
|
||||
int nummarksurfaces;
|
||||
msurface_t **marksurfaces;
|
||||
@@ -550,16 +583,68 @@ typedef struct
|
||||
#define ANIM_CYCLE 2
|
||||
#define MOD_FRAMES 20
|
||||
|
||||
|
||||
|
||||
#define MAX_DEMOS 32
|
||||
#define MAX_MOVIES 8
|
||||
#define MAX_CDTRACKS 32
|
||||
#define MAX_CLIENT_SPRITES 512 // SpriteTextures (0-256 hud, 256-512 client)
|
||||
#define MAX_REQUESTS 64
|
||||
|
||||
STATIC_CHECK_SIZEOF( mnode_t, 52, 72 );
|
||||
STATIC_CHECK_SIZEOF( mextrasurf_t, 324, 496 );
|
||||
STATIC_CHECK_SIZEOF( decal_t, 60, 88 );
|
||||
STATIC_CHECK_SIZEOF( mfaceinfo_t, 176, 304 );
|
||||
|
||||
// model flags (stored in model_t->flags)
|
||||
#define MODEL_QBSP2 BIT( 28 ) // uses 32-bit types
|
||||
|
||||
// access functions
|
||||
static inline mnode_t *node_child( const mnode_t *n, int side, const model_t *mod )
|
||||
{
|
||||
#if !XASH_64BIT
|
||||
if( unlikely( mod->flags & MODEL_QBSP2 )) // MODEL_QBSP2
|
||||
{
|
||||
if( side == 0 )
|
||||
{
|
||||
if( n->child_0_leaf )
|
||||
return (mnode_t *)(mod->leafs + n->child_0_off);
|
||||
else
|
||||
return (mnode_t *)(mod->nodes + n->child_0_off);
|
||||
}
|
||||
else
|
||||
{
|
||||
if( n->child_1_leaf )
|
||||
return (mnode_t *)(mod->leafs + n->child_1_off);
|
||||
else
|
||||
return (mnode_t *)(mod->nodes + n->child_1_off);
|
||||
}
|
||||
}
|
||||
|
||||
return n->children_[side];
|
||||
#else
|
||||
return n->children_[side];
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void node_children( mnode_t *children[2], const mnode_t *n, const model_t *mod )
|
||||
{
|
||||
children[0] = node_child( n, 0, mod );
|
||||
children[1] = node_child( n, 1, mod );
|
||||
}
|
||||
|
||||
static inline int node_firstsurface( const mnode_t *n, const model_t *mod )
|
||||
{
|
||||
if( mod->flags & MODEL_QBSP2 )
|
||||
return n->firstsurface_0 + ( n->firstsurface_1 << 16 );
|
||||
else
|
||||
return n->firstsurface_0;
|
||||
}
|
||||
|
||||
static inline int node_numsurfaces( const mnode_t *n, const model_t *mod )
|
||||
{
|
||||
if( mod->flags & MODEL_QBSP2 )
|
||||
return n->numsurfaces_0 + ( n->numsurfaces_1 << 16 );
|
||||
else
|
||||
return n->numsurfaces_0;
|
||||
}
|
||||
|
||||
#endif//COM_MODEL_H
|
||||
|
||||
@@ -28,7 +28,17 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#define PORT_ANY -1
|
||||
|
||||
typedef enum {NA_LOOPBACK = 1, NA_BROADCAST, NA_IP, NA_IPX, NA_BROADCAST_IPX, NA_IP6, NA_MULTICAST_IP6} netadrtype_t;
|
||||
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;
|
||||
|
||||
/*
|
||||
Original Quake-2 structure:
|
||||
@@ -46,29 +56,60 @@ 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
|
||||
|
||||
@@ -13,47 +13,44 @@
|
||||
#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 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;
|
||||
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;
|
||||
|
||||
#undef true
|
||||
#undef false
|
||||
|
||||
#ifndef __cplusplus
|
||||
typedef enum { false, true } qboolean;
|
||||
#else
|
||||
typedef int qboolean;
|
||||
// true and false are keywords in C++ and C23
|
||||
#if !__cplusplus && __STDC_VERSION__ < 202311L
|
||||
enum { false, true };
|
||||
#endif
|
||||
typedef int qboolean;
|
||||
|
||||
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 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
|
||||
|
||||
#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))
|
||||
@@ -70,6 +67,8 @@ typedef uint64_t longtime_t;
|
||||
#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 ))
|
||||
@@ -209,35 +208,16 @@ _inline float LittleFloat( float f )
|
||||
#endif
|
||||
|
||||
|
||||
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;
|
||||
typedef unsigned int dword;
|
||||
typedef unsigned int uint;
|
||||
typedef char string[MAX_STRING];
|
||||
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
|
||||
|
||||
@@ -153,6 +153,7 @@ static void CL_WriteErrorMessage( int current_count, sizebuf_t *msg )
|
||||
|
||||
FS_Write( fp, &cls.starting_count, sizeof( int ));
|
||||
FS_Write( fp, ¤t_count, sizeof( int ));
|
||||
FS_Write( fp, &cls.legacymode, sizeof( cls.legacymode ));
|
||||
FS_Write( fp, MSG_GetData( msg ), MSG_GetMaxBytes( msg ));
|
||||
FS_Close( fp );
|
||||
|
||||
@@ -168,7 +169,7 @@ list last 32 messages for debugging net troubleshooting
|
||||
*/
|
||||
void CL_WriteMessageHistory( void )
|
||||
{
|
||||
oldcmd_t *old, *failcommand;
|
||||
oldcmd_t *old;
|
||||
sizebuf_t *msg = &net_message;
|
||||
int i, thecmd;
|
||||
|
||||
@@ -192,9 +193,49 @@ void CL_WriteMessageHistory( void )
|
||||
thecmd++;
|
||||
}
|
||||
|
||||
failcommand = &cls_message_debug.oldcmd[thecmd];
|
||||
Con_Printf( "BAD: %3i:%s\n", MSG_GetNumBytesRead( msg ) - 1, CL_MsgInfo( failcommand->command ));
|
||||
if( host_developer.value >= DEV_EXTENDED )
|
||||
CL_WriteErrorMessage( MSG_GetNumBytesRead( msg ) - 1, msg );
|
||||
old = &cls_message_debug.oldcmd[thecmd];
|
||||
Con_Printf( S_RED "BAD: " S_DEFAULT "%i %04i %s\n", old->frame_number, old->starting_offset, CL_MsgInfo( old->command ));
|
||||
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 CL_WriteDemoUserMessage( const byte *buffer, size_t size )
|
||||
void GAME_EXPORT CL_WriteDemoUserMessage( int size, byte *buffer )
|
||||
{
|
||||
if( !cls.demorecording || cls.demowaiting )
|
||||
return;
|
||||
@@ -624,11 +624,10 @@ static void CL_ReadDemoUserCmd( qboolean discard )
|
||||
|
||||
if( !discard )
|
||||
{
|
||||
usercmd_t nullcmd;
|
||||
const usercmd_t nullcmd = { 0 };
|
||||
sizebuf_t buf;
|
||||
demoangle_t *a;
|
||||
|
||||
memset( &nullcmd, 0, sizeof( nullcmd ));
|
||||
MSG_Init( &buf, "UserCmd", data, sizeof( data ));
|
||||
|
||||
// a1ba: I have no proper explanation why
|
||||
|
||||
@@ -127,8 +127,10 @@ static void R_SplitEntityOnNode( mnode_t *node )
|
||||
}
|
||||
|
||||
// recurse down the contacted sides
|
||||
if( sides & 1 ) R_SplitEntityOnNode( node->children[0] );
|
||||
if( sides & 2 ) R_SplitEntityOnNode( node->children[1] );
|
||||
if( sides & 1 )
|
||||
R_SplitEntityOnNode( node_child( node, 0, cl.worldmodel ));
|
||||
if( sides & 2 )
|
||||
R_SplitEntityOnNode( node_child( node, 1, cl.worldmodel ));
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -2229,4 +2229,3 @@ void CL_ThinkParticle( double frametime, particle_t *p )
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -306,21 +306,22 @@ 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 )
|
||||
{
|
||||
if( REF_GET_PARM( PARM_TEX_FILTERING, texnum ))
|
||||
{
|
||||
if( refState.width != clgame.scrInfo.iWidth )
|
||||
{
|
||||
// align to texel if scaling
|
||||
*s1 += 0.5f;
|
||||
*s2 -= 0.5f;
|
||||
}
|
||||
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( refState.height != clgame.scrInfo.iHeight )
|
||||
{
|
||||
// align to texel if scaling
|
||||
*t1 += 0.5f;
|
||||
*t2 -= 0.5f;
|
||||
}
|
||||
if(( filtering || xremainder ) && 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;
|
||||
}
|
||||
|
||||
*s1 /= width;
|
||||
@@ -556,7 +557,7 @@ static void CL_InitTitles( const char *filename )
|
||||
|
||||
Q_snprintf( name, sizeof( name ), TEXT_MSGNAME, i );
|
||||
|
||||
cl_textmessage[i].pName = _copystring( clgame.mempool, name, __FILE__, __LINE__ );
|
||||
cl_textmessage[i].pName = copystringpool( clgame.mempool, name );
|
||||
cl_textmessage[i].pMessage = cl_textbuffer[i];
|
||||
}
|
||||
|
||||
@@ -1698,7 +1699,12 @@ int GAME_EXPORT CL_GetScreenInfo( SCREENINFO *pscrinfo )
|
||||
clgame.scrInfo.iSize = sizeof( clgame.scrInfo );
|
||||
clgame.scrInfo.iFlags = SCRINFO_SCREENFLASH;
|
||||
|
||||
if( scale_factor && scale_factor != 1.0f )
|
||||
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 )
|
||||
{
|
||||
float scaled_width = (float)refState.width / scale_factor;
|
||||
if( scaled_width >= hud_scale_minimal_width.value )
|
||||
@@ -2408,9 +2414,8 @@ CL_FindModelIndex
|
||||
*/
|
||||
static int GAME_EXPORT CL_FindModelIndex( const char *m )
|
||||
{
|
||||
char filepath[MAX_QPATH];
|
||||
static float lasttimewarn;
|
||||
int i;
|
||||
char filepath[MAX_QPATH];
|
||||
int i;
|
||||
|
||||
if( !COM_CheckString( m ))
|
||||
return 0;
|
||||
@@ -2427,13 +2432,6 @@ static int GAME_EXPORT CL_FindModelIndex( const char *m )
|
||||
return i+1;
|
||||
}
|
||||
|
||||
if( lasttimewarn < host.realtime )
|
||||
{
|
||||
// tell user about problem (but don't spam console)
|
||||
Con_DPrintf( S_ERROR "Could not find index for model %s: not precached\n", filepath );
|
||||
lasttimewarn = host.realtime + 1.0f;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -3356,28 +3354,6 @@ DemoApi implementation
|
||||
|
||||
=================
|
||||
*/
|
||||
/*
|
||||
=================
|
||||
Demo_IsRecording
|
||||
|
||||
=================
|
||||
*/
|
||||
static int GAME_EXPORT Demo_IsRecording( void )
|
||||
{
|
||||
return cls.demorecording;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
Demo_IsPlayingback
|
||||
|
||||
=================
|
||||
*/
|
||||
static int GAME_EXPORT Demo_IsPlayingback( void )
|
||||
{
|
||||
return cls.demoplayback;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
Demo_IsTimeDemo
|
||||
@@ -3389,17 +3365,6 @@ 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
|
||||
@@ -3462,7 +3427,7 @@ static void GAME_EXPORT NetAPI_SendRequest( int context, int request, int flags,
|
||||
return;
|
||||
}
|
||||
|
||||
if( remote_address->type == NA_IPX || remote_address->type == NA_BROADCAST_IPX )
|
||||
if( NET_NetadrType( remote_address ) == NA_IPX || NET_NetadrType( remote_address ) == NA_BROADCAST_IPX )
|
||||
return; // IPX no longer support
|
||||
|
||||
if( request == NETAPI_REQUEST_SERVERLIST )
|
||||
@@ -3585,28 +3550,6 @@ 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
|
||||
@@ -3803,10 +3746,10 @@ static event_api_t gEventApi =
|
||||
|
||||
static demo_api_t gDemoApi =
|
||||
{
|
||||
Demo_IsRecording,
|
||||
Demo_IsPlayingback,
|
||||
(void *)CL_IsRecordDemo,
|
||||
(void *)CL_IsPlaybackDemo,
|
||||
Demo_IsTimeDemo,
|
||||
Demo_WriteBuffer,
|
||||
CL_WriteDemoUserMessage,
|
||||
};
|
||||
|
||||
net_api_t gNetApi =
|
||||
@@ -3818,8 +3761,8 @@ net_api_t gNetApi =
|
||||
NetAPI_CancelAllRequests,
|
||||
NetAPI_AdrToString,
|
||||
NetAPI_CompareAdr,
|
||||
NetAPI_StringToAdr,
|
||||
NetAPI_ValueForKey,
|
||||
(void *)NET_StringToAdr,
|
||||
Info_ValueForKey,
|
||||
NetAPI_RemoveKey,
|
||||
NetAPI_SetValueForKey,
|
||||
};
|
||||
|
||||
@@ -76,6 +76,7 @@ static CVAR_DEFINE_AUTO( cl_upmax, "1200", FCVAR_ARCHIVE, "max allowed incoming
|
||||
|
||||
CVAR_DEFINE_AUTO( cl_lw, "1", FCVAR_ARCHIVE|FCVAR_USERINFO, "enable client weapon predicting" );
|
||||
CVAR_DEFINE_AUTO( cl_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)" );
|
||||
@@ -147,11 +148,6 @@ qboolean CL_IsRecordDemo( void )
|
||||
return cls.demorecording;
|
||||
}
|
||||
|
||||
qboolean CL_IsTimeDemo( void )
|
||||
{
|
||||
return cls.timedemo;
|
||||
}
|
||||
|
||||
qboolean CL_DisableVisibility( void )
|
||||
{
|
||||
return cls.envshot_disable_vis;
|
||||
@@ -598,7 +594,7 @@ CL_CreateCmd
|
||||
*/
|
||||
static void CL_CreateCmd( void )
|
||||
{
|
||||
usercmd_t nullcmd, *cmd;
|
||||
usercmd_t nullcmd = { 0 }, *cmd;
|
||||
runcmd_t *pcmd;
|
||||
qboolean active;
|
||||
double accurate_ms;
|
||||
@@ -650,7 +646,6 @@ static void CL_CreateCmd( void )
|
||||
}
|
||||
else
|
||||
{
|
||||
memset( &nullcmd, 0, sizeof( nullcmd ));
|
||||
cmd = &nullcmd;
|
||||
}
|
||||
|
||||
@@ -723,11 +718,20 @@ 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 <= ca_connected )
|
||||
if( cls.state < min_state )
|
||||
{
|
||||
Netchan_TransmitBits( &cls.netchan, 0, "" );
|
||||
return;
|
||||
@@ -825,7 +829,7 @@ static void CL_WritePacket( void )
|
||||
buf.pData[key] = CRC32_BlockSequence( &buf.pData[key + 1], size, cls.netchan.outgoing_sequence );
|
||||
COM_Munge( &buf.pData[key + 1], Q_min( size, 255 ), cls.netchan.outgoing_sequence );
|
||||
}
|
||||
else
|
||||
else if( !Host_IsLocalClient( ))
|
||||
{
|
||||
int size = MSG_GetRealBytesWritten( &buf ) - key - 1;
|
||||
buf.pData[key] = CRC32_BlockSequence( &buf.pData[key + 1], size, cls.netchan.outgoing_sequence );
|
||||
@@ -1059,6 +1063,7 @@ 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;
|
||||
|
||||
@@ -1069,14 +1074,16 @@ 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( adr.type != NA_LOOPBACK ? true : false );
|
||||
IN_LockInputDevices( adrtype != 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( adr.type != NA_LOOPBACK && proto != PROTO_GOLDSRC )
|
||||
if( adrtype != NA_LOOPBACK && proto != PROTO_GOLDSRC )
|
||||
{
|
||||
Cvar_SetCheatState();
|
||||
Cvar_FullSet( "sv_cheats", "0", FCVAR_READ_ONLY | FCVAR_SERVER );
|
||||
@@ -1214,7 +1221,7 @@ static void CL_CheckForResend( void )
|
||||
cls.signon = 0;
|
||||
cls.state = ca_connecting;
|
||||
Q_strncpy( cls.servername, "localhost", sizeof( cls.servername ));
|
||||
cls.serveradr.type = NA_LOOPBACK;
|
||||
NET_NetadrSetType( &cls.serveradr, NA_LOOPBACK );
|
||||
cls.legacymode = PROTO_CURRENT;
|
||||
|
||||
// we don't need a challenge on the localhost
|
||||
@@ -1550,8 +1557,8 @@ static void CL_SendDisconnectMessage( connprotocol_t proto )
|
||||
MSG_WriteString( &buf, "dropclient\n" );
|
||||
else MSG_WriteString( &buf, "disconnect" );
|
||||
|
||||
if( !cls.netchan.remote_address.type )
|
||||
cls.netchan.remote_address.type = NA_LOOPBACK;
|
||||
if( NET_NetadrType( &cls.netchan.remote_address ) == NA_UNDEFINED )
|
||||
NET_NetadrSetType( &cls.netchan.remote_address, NA_LOOPBACK );
|
||||
|
||||
// make sure message will be delivered
|
||||
Netchan_TransmitBits( &cls.netchan, MSG_GetNumBitsWritten( &buf ), MSG_GetData( &buf ));
|
||||
@@ -1594,6 +1601,9 @@ 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 ))
|
||||
@@ -1717,19 +1727,17 @@ CL_LocalServers_f
|
||||
*/
|
||||
static void CL_LocalServers_f( void )
|
||||
{
|
||||
netadr_t adr;
|
||||
|
||||
memset( &adr, 0, sizeof( adr ));
|
||||
netadr_t adr = { 0 };
|
||||
|
||||
Con_Printf( "Scanning for servers on the local network area...\n" );
|
||||
NET_Config( true, true ); // allow remote
|
||||
|
||||
// send a broadcast packet
|
||||
adr.type = NA_BROADCAST;
|
||||
NET_NetadrSetType( &adr, NA_BROADCAST );
|
||||
adr.port = MSG_BigShort( PORT_SERVER );
|
||||
Netchan_OutOfBandPrint( NS_CLIENT, adr, A2A_INFO" %i", PROTOCOL_VERSION );
|
||||
|
||||
adr.type = NA_MULTICAST_IP6;
|
||||
NET_NetadrSetType( &adr, NA_MULTICAST_IP6 );
|
||||
Netchan_OutOfBandPrint( NS_CLIENT, adr, A2A_INFO" %i", PROTOCOL_VERSION );
|
||||
}
|
||||
|
||||
@@ -1761,8 +1769,8 @@ static size_t NONNULL CL_BuildMasterServerScanRequest( char *buf, size_t size, u
|
||||
// let master know about client version
|
||||
Info_SetValueForKey( info, "clver", XASH_VERSION, remaining );
|
||||
Info_SetValueForKey( info, "nat", nat ? "1" : "0", remaining );
|
||||
Info_SetValueForKey( info, "commit", Q_buildcommit(), remaining );
|
||||
Info_SetValueForKey( info, "branch", Q_buildbranch(), remaining );
|
||||
Info_SetValueForKey( info, "commit", g_buildcommit, remaining );
|
||||
Info_SetValueForKey( info, "branch", g_buildbranch, remaining );
|
||||
Info_SetValueForKey( info, "os", Q_buildos(), remaining );
|
||||
Info_SetValueForKey( info, "arch", Q_buildarch(), remaining );
|
||||
|
||||
@@ -2473,18 +2481,18 @@ static void CL_ServerList( netadr_t from, sizebuf_t *msg )
|
||||
while( MSG_GetNumBitsLeft( msg ) > 8 )
|
||||
{
|
||||
uint8_t addr[16];
|
||||
netadr_t servadr;
|
||||
netadr_t servadr = { 0 };
|
||||
|
||||
if( from.type6 == NA_IP6 ) // IPv6 master server only sends IPv6 addresses
|
||||
if( NET_NetadrType( &from ) == NA_IP6 ) // IPv6 master server only sends IPv6 addresses
|
||||
{
|
||||
MSG_ReadBytes( msg, addr, sizeof( addr ));
|
||||
NET_IP6BytesToNetadr( &servadr, addr );
|
||||
servadr.type6 = NA_IP6;
|
||||
NET_NetadrSetType( &servadr, NA_IP6 );
|
||||
}
|
||||
else
|
||||
{
|
||||
MSG_ReadBytes( msg, servadr.ip, sizeof( servadr.ip )); // 4 bytes for IP
|
||||
servadr.type = NA_IP;
|
||||
NET_NetadrSetType( &servadr, NA_IP );
|
||||
}
|
||||
servadr.port = MSG_ReadShort( msg ); // 2 bytes for Port
|
||||
|
||||
@@ -3132,6 +3140,9 @@ 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;
|
||||
}
|
||||
|
||||
@@ -3141,7 +3152,7 @@ qboolean CL_PrecacheResources( void )
|
||||
|
||||
// if we downloaded new WAD files or any other archives they must be added to searchpath
|
||||
if( CL_ShouldRescanFilesystem( ))
|
||||
g_fsapi.Rescan();
|
||||
FS_Rescan_f();
|
||||
|
||||
// NOTE: world need to be loaded as first model
|
||||
for( pRes = cl.resourcesonhand.pNext; pRes && pRes != &cl.resourcesonhand; pRes = pRes->pNext )
|
||||
@@ -3387,6 +3398,7 @@ 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 );
|
||||
@@ -3481,6 +3493,8 @@ 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,6 +3672,8 @@ 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
|
||||
|
||||
@@ -1614,6 +1614,23 @@ void CL_UpdateUserPings( sizebuf_t *msg )
|
||||
}
|
||||
}
|
||||
|
||||
static const char *CL_CheckTypeToString( int check_type )
|
||||
{
|
||||
// renamed so they have same width and look better in console output
|
||||
switch( check_type )
|
||||
{
|
||||
case force_exactfile:
|
||||
return "exactfile";
|
||||
case force_model_samebounds:
|
||||
return "samebounds";
|
||||
case force_model_specifybounds:
|
||||
return "specbounds";
|
||||
case force_model_specifybounds_if_avail:
|
||||
return "specbounds2";
|
||||
}
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
static void CL_SendConsistencyInfo( sizebuf_t *msg, connprotocol_t proto )
|
||||
{
|
||||
qboolean user_changed_diskfile;
|
||||
@@ -1879,6 +1896,9 @@ 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;
|
||||
|
||||
@@ -1910,7 +1930,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( consistency_t ));
|
||||
memset( pc, 0, sizeof( *pc ));
|
||||
pc->filename = pResource->szFileName;
|
||||
pc->issound = (pResource->type == t_sound);
|
||||
pc->orig_index = delta;
|
||||
@@ -1923,6 +1943,9 @@ static void CL_ParseConsistencyInfo( sizebuf_t *msg, connprotocol_t proto )
|
||||
pc->check_type = pResource->rguc_reserved[0];
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -91,11 +91,11 @@ static void CL_ParseNewMovevars( sizebuf_t *msg )
|
||||
|
||||
typedef struct delta_header_t
|
||||
{
|
||||
qboolean remove : 1;
|
||||
qboolean custom : 1;
|
||||
qboolean instanced : 1;
|
||||
uint instanced_baseline_index : 6;
|
||||
uint offset : 6;
|
||||
qboolean remove;
|
||||
qboolean custom;
|
||||
qboolean instanced;
|
||||
uint16_t instanced_baseline_index;
|
||||
uint16_t offset;
|
||||
} delta_header_t;
|
||||
|
||||
static int CL_ParseDeltaHeader( sizebuf_t *msg, qboolean delta, int oldnum, struct delta_header_t *hdr )
|
||||
@@ -160,33 +160,47 @@ static int CL_GetEntityDelta( const struct delta_header_t *hdr, int entnum )
|
||||
return DT_ENTITY_STATE_T;
|
||||
}
|
||||
|
||||
static void CL_FlushEntityPacketGS( frame_t *frame, sizebuf_t *msg )
|
||||
static int CL_FlushEntityPacketGS( frame_t *frame, sizebuf_t *msg )
|
||||
{
|
||||
int playerbytes = 0, numbase = 0;
|
||||
|
||||
frame->valid = false;
|
||||
cl.validsequence = 0; // can't render a frame
|
||||
|
||||
// read it all but ignore it
|
||||
while( 1 )
|
||||
{
|
||||
int num = 0;
|
||||
int newnum, bufstart;
|
||||
entity_state_t from = { 0 }, to;
|
||||
delta_header_t hdr;
|
||||
qboolean player;
|
||||
|
||||
if( MSG_ReadWord( msg ) != 0 )
|
||||
{
|
||||
MSG_SeekToBit( msg, -16, SEEK_CUR );
|
||||
num = CL_ParseDeltaHeader( msg, false, num, &hdr );
|
||||
numbase = newnum = CL_ParseDeltaHeader( msg, true, numbase, &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, num ), &from, &to, cl.mtime[0] );
|
||||
Delta_ReadGSFields( msg, CL_GetEntityDelta( &hdr, newnum ), &from, &to, cl.mtime[0] );
|
||||
|
||||
if( player )
|
||||
playerbytes += MSG_GetNumBytesRead( msg ) - bufstart;
|
||||
}
|
||||
|
||||
if( MSG_CheckOverflow( msg ))
|
||||
Host_Error( "%s: overflow\n", __func__ );
|
||||
|
||||
return playerbytes;
|
||||
}
|
||||
|
||||
static void CL_DeltaEntityGS( const delta_header_t *hdr, sizebuf_t *msg, frame_t *frame, int newnum, const entity_state_t *from )
|
||||
@@ -203,7 +217,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", __func__, newnum );
|
||||
Host_Error( "%s: bad delta entity number: %i\n", __func__, newnum );
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -267,7 +281,7 @@ static void CL_CopyPacketEntity( frame_t *frame, int num, const entity_state_t *
|
||||
static int CL_ParsePacketEntitiesGS( sizebuf_t *msg, qboolean delta )
|
||||
{
|
||||
frame_t *frame, *oldframe;
|
||||
int oldindex, newnum, oldnum, numbase = 0;
|
||||
int oldindex, oldnum, numbase = 0;
|
||||
entity_state_t *oldent;
|
||||
int count;
|
||||
int playerbytes = 0;
|
||||
@@ -314,7 +328,7 @@ static int CL_ParsePacketEntitiesGS( sizebuf_t *msg, qboolean delta )
|
||||
// read it all but ignore it
|
||||
while( 1 )
|
||||
{
|
||||
int bufstart;
|
||||
int bufstart, newnum;
|
||||
qboolean player;
|
||||
delta_header_t hdr;
|
||||
int val = MSG_ReadWord( msg );
|
||||
@@ -534,7 +548,7 @@ void CL_ParseGoldSrcServerMessage( sizebuf_t *msg )
|
||||
{
|
||||
if( MSG_CheckOverflow( msg ))
|
||||
{
|
||||
Host_Error( "CL_ParseServerMessage: overflow!\n" );
|
||||
Host_Error( "%s: overflow!\n", __func__ );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -138,10 +138,7 @@ intptr_t CL_RenderGetParm( const int parm, const int arg, const qboolean checkRe
|
||||
switch( parm )
|
||||
{
|
||||
case PARM_BSP2_SUPPORTED:
|
||||
#ifdef SUPPORT_BSP2_FORMAT
|
||||
return 1;
|
||||
#endif
|
||||
return 0;
|
||||
case PARAM_GAMEPAUSED:
|
||||
return cl.paused;
|
||||
case PARM_CLIENT_INGAME:
|
||||
@@ -236,6 +233,11 @@ 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,
|
||||
@@ -268,7 +270,7 @@ static render_api_t gRenderAPI =
|
||||
NULL, // R_UploadStretchRaw,
|
||||
(void*)AVI_FreeVideo,
|
||||
(void*)AVI_IsActive,
|
||||
S_StreamAviSamples,
|
||||
(void*)pfnAVI_StreamSound,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL, // GL_Bind,
|
||||
|
||||
@@ -567,57 +567,54 @@ R_FizzEffect
|
||||
Create a fizz effect
|
||||
==============
|
||||
*/
|
||||
void GAME_EXPORT R_FizzEffect( cl_entity_t *pent, int modelIndex, int density )
|
||||
void GAME_EXPORT R_FizzEffect( cl_entity_t *ent, int modelIndex, int density )
|
||||
{
|
||||
TEMPENTITY *pTemp;
|
||||
int i, width, depth;
|
||||
float angle, maxHeight, speed;
|
||||
float xspeed, yspeed, zspeed;
|
||||
vec3_t origin;
|
||||
model_t *mod;
|
||||
const float base_time = cl.time - 0.1f;
|
||||
model_t *mod = CL_ModelHandle( modelIndex );
|
||||
vec3_t volume, mins, maxs;
|
||||
vec2_t speed;
|
||||
int i;
|
||||
|
||||
if( !pent || !pent->model || !modelIndex )
|
||||
if( !ent || !ent->model || !modelIndex || !mod )
|
||||
return;
|
||||
|
||||
if(( mod = CL_ModelHandle( modelIndex )) == NULL )
|
||||
return;
|
||||
VectorCopy( ent->model->mins, mins );
|
||||
VectorCopy( ent->model->maxs, maxs );
|
||||
|
||||
maxHeight = pent->model->maxs[2] - pent->model->mins[2];
|
||||
width = pent->model->maxs[0] - pent->model->mins[0];
|
||||
depth = pent->model->maxs[1] - pent->model->mins[1];
|
||||
if( ent->angles[1] != 0.0f )
|
||||
{
|
||||
const float base_speed = ( ent->curstate.rendercolor.b ? -1.0f : 1.0f ) * ( ent->curstate.rendercolor.r * 256.0f + ent->curstate.rendercolor.g );
|
||||
SinCos( DEG2RAD( ent->angles[1] ), &speed[1], &speed[0] );
|
||||
speed[0] *= base_speed;
|
||||
speed[1] *= base_speed;
|
||||
}
|
||||
else speed[0] = speed[1] = 0.0f;
|
||||
|
||||
speed = ( pent->curstate.rendercolor.r<<8 | pent->curstate.rendercolor.g );
|
||||
if( pent->curstate.rendercolor.b )
|
||||
speed = -speed;
|
||||
|
||||
angle = DEG2RAD( pent->angles[YAW] );
|
||||
SinCos( angle, &yspeed, &xspeed );
|
||||
|
||||
xspeed *= speed;
|
||||
yspeed *= speed;
|
||||
VectorSubtract( maxs, mins, volume );
|
||||
|
||||
for( i = 0; i <= density; i++ )
|
||||
{
|
||||
origin[0] = mod->mins[0] + COM_RandomLong( 0, width - 1 );
|
||||
origin[1] = mod->mins[1] + COM_RandomLong( 0, depth - 1 );
|
||||
origin[2] = mod->mins[2];
|
||||
pTemp = CL_TempEntAlloc( origin, mod );
|
||||
TEMPENTITY *tent;
|
||||
vec3_t origin;
|
||||
|
||||
if ( !pTemp ) return;
|
||||
VectorCopy( mins, origin );
|
||||
origin[0] += COM_RandomLong( 0, (int)volume[0] - 1 );
|
||||
origin[1] += COM_RandomLong( 0, (int)volume[1] - 1 );
|
||||
|
||||
pTemp->flags |= FTENT_SINEWAVE;
|
||||
if( !( tent = CL_TempEntAlloc( origin, mod )))
|
||||
return;
|
||||
|
||||
pTemp->x = origin[0];
|
||||
pTemp->y = origin[1];
|
||||
tent->x = origin[0];
|
||||
tent->y = origin[1];
|
||||
tent->die = base_time;
|
||||
tent->flags |= FTENT_SINEWAVE;
|
||||
tent->entity.curstate.rendermode = kRenderTransAlpha;
|
||||
Vector2Copy( speed, tent->entity.baseline.origin );
|
||||
|
||||
zspeed = COM_RandomLong( 80, 140 );
|
||||
VectorSet( pTemp->entity.baseline.origin, xspeed, yspeed, zspeed );
|
||||
pTemp->die = cl.time + ( maxHeight / zspeed ) - 0.1f;
|
||||
pTemp->entity.curstate.frame = COM_RandomLong( 0, pTemp->frameMax );
|
||||
// Set sprite scale
|
||||
pTemp->entity.curstate.scale = 1.0f / COM_RandomFloat( 2.0f, 5.0f );
|
||||
pTemp->entity.curstate.rendermode = kRenderTransAlpha;
|
||||
pTemp->entity.curstate.renderamt = 255;
|
||||
tent->entity.baseline.origin[2] = COM_RandomLong( 80, 140 );
|
||||
tent->die += volume[2] / tent->entity.baseline.origin[2];
|
||||
tent->entity.curstate.frame = COM_RandomLong( 0, tent->frameMax );
|
||||
tent->entity.curstate.scale = 1.0f / COM_RandomFloat( 2.0f, 5.0f );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2432,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", style );
|
||||
Con_Printf( S_WARN "%s: ignored invalid lightstyle id %d\n", __func__, style );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -466,8 +466,8 @@ static void R_ShowTree_r( mnode_t *node, float x, float y, float scale, int show
|
||||
R_DrawNodeConnection( x, y, x + scale, y + scale );
|
||||
}
|
||||
|
||||
R_ShowTree_r( node->children[1], x - scale, y + scale, downScale, shownodes, viewleaf );
|
||||
R_ShowTree_r( node->children[0], x + scale, y + scale, downScale, shownodes, viewleaf );
|
||||
R_ShowTree_r( node_child( node, 1, cl.worldmodel ), x - scale, y + scale, downScale, shownodes, viewleaf );
|
||||
R_ShowTree_r( node_child( node, 0, cl.worldmodel ), x + scale, y + scale, downScale, shownodes, viewleaf );
|
||||
|
||||
world.recursion_level--;
|
||||
}
|
||||
@@ -482,7 +482,7 @@ static void R_ShowTree( void )
|
||||
return;
|
||||
|
||||
world.recursion_level = 0;
|
||||
viewleaf = Mod_PointInLeaf( refState.vieworg, cl.worldmodel->nodes );
|
||||
viewleaf = Mod_PointInLeaf( refState.vieworg, cl.worldmodel->nodes, cl.worldmodel );
|
||||
|
||||
ref.dllFuncs.TriRenderMode( kRenderTransTexture );
|
||||
|
||||
|
||||
@@ -688,6 +688,7 @@ 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;
|
||||
@@ -736,6 +737,7 @@ 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 );
|
||||
@@ -767,7 +769,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( const byte *buffer, size_t size );
|
||||
void CL_WriteDemoUserMessage( int size, byte *buffer );
|
||||
qboolean CL_DemoReadMessage( byte *buffer, size_t *length );
|
||||
void CL_DemoInterpolateAngles( void );
|
||||
void CL_CheckStartupDemos( void );
|
||||
@@ -1119,7 +1121,7 @@ void Con_PageUp( int lines );
|
||||
//
|
||||
// s_main.c
|
||||
//
|
||||
void S_StreamAviSamples( void *Avi, int entnum, float fvol, float attn, float synctime );
|
||||
typedef int sound_t;
|
||||
void S_StartBackgroundTrack( const char *intro, const char *loop, int position, qboolean fullpath );
|
||||
void S_StopBackgroundTrack( void );
|
||||
void S_StreamSetPause( int pause );
|
||||
@@ -1208,6 +1210,13 @@ 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 );
|
||||
void GAME_EXPORT ID_SetCustomClientID( const char *id );
|
||||
|
||||
extern rgba_t g_color_table[8];
|
||||
extern triangleapi_t gTriApi;
|
||||
extern net_api_t gNetApi;
|
||||
|
||||
@@ -622,7 +622,7 @@ int Con_UtfProcessCharForce( int in )
|
||||
// TODO: get rid of global state where possible
|
||||
static utfstate_t state = { 0 };
|
||||
|
||||
int ch = Q_DecodeUTF8( &state, in );
|
||||
uint32_t ch = Q_DecodeUTF8( &state, in );
|
||||
|
||||
if( g_codepage == 1251 )
|
||||
return Q_UnicodeToCP1251( ch );
|
||||
@@ -2092,10 +2092,7 @@ void Con_RunConsole( void )
|
||||
}
|
||||
else
|
||||
{
|
||||
Con_Printf( S_WARN "Unknown charset %s, defaulting to cp1252", con_charset.string );
|
||||
|
||||
Cvar_DirectSet( &con_charset, "cp1252" );
|
||||
g_codepage = 1252;
|
||||
g_codepage = 0;
|
||||
}
|
||||
|
||||
cls.accept_utf8 = !Q_stricmp( cl_charset.string, "utf-8" );
|
||||
|
||||
@@ -611,7 +611,7 @@ void GAME_EXPORT ID_SetCustomClientID( const char *id )
|
||||
|
||||
void ID_Init( void )
|
||||
{
|
||||
MD5Context_t hash = {0};
|
||||
MD5Context_t hash = { 0 };
|
||||
byte md5[16];
|
||||
int i;
|
||||
|
||||
@@ -632,7 +632,7 @@ void ID_Init( void )
|
||||
#elif XASH_WIN32
|
||||
{
|
||||
CHAR szBuf[MAX_PATH];
|
||||
ID_GetKeyData( HKEY_CURRENT_USER, "Software\\Xash3D\\", "xash_id", szBuf, MAX_PATH );
|
||||
ID_GetKeyData( HKEY_CURRENT_USER, "Software\\"XASH_ENGINE_NAME"\\", "xash_id", szBuf, MAX_PATH );
|
||||
|
||||
sscanf(szBuf, "%016"PRIX64, &id);
|
||||
id ^= SYSTEM_XOR_MASK;
|
||||
@@ -686,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\\Xash3D\\", REG_SZ, "xash_id", Buf, Q_strlen(Buf) );
|
||||
ID_SetKeyData( HKEY_CURRENT_USER, "Software\\"XASH_ENGINE_NAME"\\", REG_SZ, "xash_id", Buf, Q_strlen(Buf) );
|
||||
}
|
||||
#else
|
||||
{
|
||||
@@ -43,7 +43,6 @@ 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" );
|
||||
@@ -60,9 +59,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" );
|
||||
|
||||
/*
|
||||
============
|
||||
@@ -71,7 +70,30 @@ Joy_IsActive
|
||||
*/
|
||||
qboolean Joy_IsActive( void )
|
||||
{
|
||||
return joy_found.value && joy_enable.value;
|
||||
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 );
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -81,7 +103,7 @@ Joy_HatMotionEvent
|
||||
DPad events
|
||||
============
|
||||
*/
|
||||
void Joy_HatMotionEvent( byte hat, byte value )
|
||||
static void Joy_HatMotionEvent( int value )
|
||||
{
|
||||
struct
|
||||
{
|
||||
@@ -96,9 +118,6 @@ void Joy_HatMotionEvent( byte hat, byte value )
|
||||
};
|
||||
int i;
|
||||
|
||||
if( !joy_found.value )
|
||||
return;
|
||||
|
||||
for( i = 0; i < ARRAYSIZE( keys ); i++ )
|
||||
{
|
||||
if( value & keys[i].mask )
|
||||
@@ -225,7 +244,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( 0, val );
|
||||
Joy_HatMotionEvent( val );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -236,23 +255,9 @@ Joy_AxisMotionEvent
|
||||
Axis events
|
||||
=============
|
||||
*/
|
||||
void Joy_AxisMotionEvent( byte axis, short value )
|
||||
void Joy_AxisMotionEvent( engineAxis_t engineAxis, short value )
|
||||
{
|
||||
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 )
|
||||
if( engineAxis >= JOY_AXIS_NULL )
|
||||
return;
|
||||
|
||||
if( value == joyaxis[engineAxis].val )
|
||||
@@ -266,66 +271,14 @@ void Joy_KnownAxisMotionEvent( engineAxis_t engineAxis, short value )
|
||||
|
||||
/*
|
||||
=============
|
||||
Joy_BallMotionEvent
|
||||
Joy_GyroEvent
|
||||
|
||||
Trackball events. UNDONE
|
||||
Gyroscope events
|
||||
=============
|
||||
*/
|
||||
void Joy_BallMotionEvent( byte ball, short xrel, short yrel )
|
||||
void Joy_GyroEvent( vec3_t data )
|
||||
{
|
||||
//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 );
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -364,14 +317,19 @@ 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;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void Joy_CalibrateGyro_f( void )
|
||||
{
|
||||
if( !joy_have_gyro.value )
|
||||
{
|
||||
Con_Printf( "Current active gamepad doesn't have gyroscope\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
Platform_CalibrateGamepadGyro();
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -383,6 +341,8 @@ 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 );
|
||||
@@ -402,11 +362,9 @@ 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
|
||||
@@ -417,7 +375,7 @@ void Joy_Init( void )
|
||||
return;
|
||||
}
|
||||
|
||||
Cvar_FullSet( "joy_found", va( "%d", Platform_JoyInit( joy_index.value )), FCVAR_READ_ONLY );
|
||||
Platform_JoyInit();
|
||||
|
||||
joy_initialized = true;
|
||||
}
|
||||
@@ -431,8 +389,5 @@ Shutdown joystick code
|
||||
*/
|
||||
void Joy_Shutdown( void )
|
||||
{
|
||||
if( joy_initialized )
|
||||
{
|
||||
Cvar_FullSet( "joy_found", 0, FCVAR_READ_ONLY );
|
||||
}
|
||||
Platform_JoyShutdown();
|
||||
}
|
||||
|
||||
@@ -266,7 +266,7 @@ static qboolean Touch_DumpConfig( const char *name, const char *profilename )
|
||||
}
|
||||
|
||||
FS_Printf( f, "//=======================================================================\n");
|
||||
FS_Printf( f, "//\tGenerated by "XASH_ENGINE_NAME" (%i, %s, %s, %s-%s)\n", Q_buildnum(), Q_buildcommit(), Q_buildbranch(), Q_buildos(), Q_buildarch());
|
||||
FS_Printf( f, "//\tGenerated by "XASH_ENGINE_NAME" (%i, %s, %s, %s-%s)\n", Q_buildnum(), g_buildcommit, g_buildbranch, Q_buildos(), Q_buildarch());
|
||||
FS_Printf( f, "//\t\t\ttouchscreen config\n" );
|
||||
FS_Printf( f, "//=======================================================================\n" );
|
||||
FS_Printf( f, "\ntouch_config_file \"%s\"\n", profilename );
|
||||
@@ -902,9 +902,10 @@ static void Touch_AddButton_f( void )
|
||||
rgba_t color;
|
||||
int argc = Cmd_Argc( );
|
||||
touch_button_t *button = NULL;
|
||||
const char *name, *texture, *command;
|
||||
const char *name, *command;
|
||||
float x1, y1, x2, y2;
|
||||
qboolean privileged = Cmd_CurrentCommandIsPrivileged();
|
||||
string texture;
|
||||
|
||||
if( argc < 4 )
|
||||
{
|
||||
@@ -913,9 +914,18 @@ static void Touch_AddButton_f( void )
|
||||
}
|
||||
|
||||
name = Cmd_Argv( 1 );
|
||||
texture = Cmd_Argv( 2 );
|
||||
Q_strncpy( texture, Cmd_Argv( 2 ), sizeof( texture ));
|
||||
command = Cmd_Argv( 3 );
|
||||
|
||||
// HACKHACK: old engine specifically used .tga for touch buttons
|
||||
// and because new engine extras.pk3 don't have .tga textures
|
||||
// (which instead were converted to .png) strip extension to let
|
||||
// to let imagelib choose better format
|
||||
//
|
||||
// Remove this when old engine migration would be done
|
||||
if( Q_stricmp( COM_FileExtension( texture ), "tga" ))
|
||||
COM_StripExtension( texture );
|
||||
|
||||
if( argc < 8 )
|
||||
{
|
||||
x1 = y1 = 0.4f;
|
||||
@@ -1120,8 +1130,8 @@ void Touch_Init( void )
|
||||
Cmd_AddRestrictedCommand( "touch_loaddefaults", Touch_LoadDefaults_f, "generate config from defaults" );
|
||||
Cmd_AddRestrictedCommand( "touch_roundall", Touch_RoundAll_f, "round all buttons coordinates to grid" );
|
||||
Cmd_AddRestrictedCommand( "touch_exportconfig", Touch_ExportConfig_f, "export config keeping aspect ratio" );
|
||||
Cmd_AddCommand( "touch_set_stroke", Touch_Stroke_f, "set global stroke width and color" );
|
||||
Cmd_AddCommand( "touch_setclientonly", Touch_SetClientOnly_f, "when 1, only client buttons are shown" );
|
||||
Cmd_AddRestrictedCommand( "touch_set_stroke", Touch_Stroke_f, "set global stroke width and color" );
|
||||
Cmd_AddRestrictedCommand( "touch_setclientonly", Touch_SetClientOnly_f, "when 1, only client buttons are shown" );
|
||||
Cmd_AddRestrictedCommand( "touch_reloadconfig", Touch_ReloadConfig_f, "load config, not saving changes" );
|
||||
Cmd_AddRestrictedCommand( "touch_writeconfig", Touch_WriteConfig, "save current config" );
|
||||
Cmd_AddRestrictedCommand( "touch_deleteprofile", Touch_DeleteProfile_f, "delete profile by name" );
|
||||
|
||||
@@ -104,18 +104,21 @@ 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_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_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_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_SCROLLOCK, "" },
|
||||
{"SCROLLOCK", K_SCROLLLOCK, "" },
|
||||
{"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_SCROLLOCK )
|
||||
if( keynum > 32 && keynum < 127 && keynum != '"' && keynum != ';' && keynum != K_SCROLLLOCK )
|
||||
{
|
||||
tinystr[0] = keynum;
|
||||
tinystr[1] = 0;
|
||||
@@ -861,7 +861,9 @@ void GAME_EXPORT Key_ClearStates( void )
|
||||
|
||||
for( i = 0; i < 256; i++ )
|
||||
{
|
||||
if( keys[i].down && i < K_MOUSE1 && i > K_MOUSE5 )
|
||||
if( i >= K_MOUSE1 && i <= K_MOUSE5 )
|
||||
IN_MouseEvent( i - K_MOUSE1, false );
|
||||
else
|
||||
Key_Event( i, false );
|
||||
|
||||
keys[i].down = 0;
|
||||
@@ -869,9 +871,6 @@ 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();
|
||||
}
|
||||
@@ -1108,7 +1107,7 @@ static qboolean OSK_KeyEvent( int key, int down )
|
||||
|
||||
/*
|
||||
=============
|
||||
Joy_EnableTextInput
|
||||
OSK_EnableTextInput
|
||||
|
||||
Enables built-in IME
|
||||
=============
|
||||
|
||||
@@ -470,16 +470,16 @@ out_free:
|
||||
* This is a stack of the clipnodes we have traversed
|
||||
* "sides" indicates which side we went down each time
|
||||
*/
|
||||
static mclipnode_t *node_stack[MAX_CLIPNODE_DEPTH];
|
||||
static int node_stack[MAX_CLIPNODE_DEPTH];
|
||||
static int side_stack[MAX_CLIPNODE_DEPTH];
|
||||
static uint node_stack_depth;
|
||||
|
||||
static void push_node( mclipnode_t *node, int side )
|
||||
static void push_node( int nodenum, int side )
|
||||
{
|
||||
if( node_stack_depth == MAX_CLIPNODE_DEPTH )
|
||||
Host_Error( "node stack overflow\n" );
|
||||
|
||||
node_stack[node_stack_depth] = node;
|
||||
node_stack[node_stack_depth] = nodenum;
|
||||
side_stack[node_stack_depth] = side;
|
||||
node_stack_depth++;
|
||||
}
|
||||
@@ -502,22 +502,27 @@ static void free_hull_polys( hullnode_t *hull_polys )
|
||||
}
|
||||
}
|
||||
|
||||
static void hull_windings_r( hull_t *hull, mclipnode_t *node, hullnode_t *polys, hull_model_t *model );
|
||||
static void hull_windings_r( hull_t *hull, int nodenum, hullnode_t *polys, hull_model_t *model );
|
||||
|
||||
static void do_hull_recursion( hull_t *hull, mclipnode_t *node, int side, hullnode_t *polys, hull_model_t *model )
|
||||
static void do_hull_recursion( hull_t *hull, int nodenum, int side, hullnode_t *polys, hull_model_t *model )
|
||||
{
|
||||
winding_t *w, *next;
|
||||
int childnum;
|
||||
|
||||
if( node->children[side] >= 0 )
|
||||
if( world.version == QBSP2_VERSION )
|
||||
childnum = hull->clipnodes32[nodenum].children[side];
|
||||
else
|
||||
childnum = hull->clipnodes16[nodenum].children[side];
|
||||
|
||||
if( childnum >= 0 )
|
||||
{
|
||||
mclipnode_t *child = hull->clipnodes + node->children[side];
|
||||
push_node( node, side );
|
||||
hull_windings_r( hull, child, polys, model );
|
||||
push_node( nodenum, side );
|
||||
hull_windings_r( hull, childnum, polys, model );
|
||||
pop_node();
|
||||
}
|
||||
else
|
||||
{
|
||||
switch( node->children[side] )
|
||||
switch( childnum )
|
||||
{
|
||||
case CONTENTS_EMPTY:
|
||||
case CONTENTS_WATER:
|
||||
@@ -542,20 +547,25 @@ static void do_hull_recursion( hull_t *hull, mclipnode_t *node, int side, hullno
|
||||
}
|
||||
break;
|
||||
default:
|
||||
Host_Error( "bad contents: %i\n", node->children[side] );
|
||||
Host_Error( "bad contents: %i\n", childnum );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void hull_windings_r( hull_t *hull, mclipnode_t *node, hullnode_t *polys, hull_model_t *model )
|
||||
static void hull_windings_r( hull_t *hull, int nodenum, hullnode_t *polys, hull_model_t *model )
|
||||
{
|
||||
mplane_t *plane = hull->planes + node->planenum;
|
||||
mplane_t *plane;
|
||||
hullnode_t frontlist = LIST_HEAD_INIT( frontlist );
|
||||
hullnode_t backlist = LIST_HEAD_INIT( backlist );
|
||||
winding_t *w, *next, *front, *back;
|
||||
int i;
|
||||
|
||||
if( world.version == QBSP2_VERSION )
|
||||
plane = hull->planes + hull->clipnodes32[nodenum].planenum;
|
||||
else
|
||||
plane = hull->planes + hull->clipnodes16[nodenum].planenum;
|
||||
|
||||
list_for_each_entry_safe( w, next, polys, chain )
|
||||
{
|
||||
// PARANIOA - PAIR CHECK
|
||||
@@ -601,7 +611,13 @@ static void hull_windings_r( hull_t *hull, mclipnode_t *node, hullnode_t *polys,
|
||||
|
||||
for( i = 0; w && i < node_stack_depth; i++ )
|
||||
{
|
||||
mplane_t *p = hull->planes + node_stack[i]->planenum;
|
||||
mplane_t *p;
|
||||
|
||||
if( world.version == QBSP2_VERSION )
|
||||
p = hull->planes + hull->clipnodes32[node_stack[i]].planenum;
|
||||
else
|
||||
p = hull->planes + hull->clipnodes16[node_stack[i]].planenum;
|
||||
|
||||
w = winding_clip( w, p, false, side_stack[i], 0.00001 );
|
||||
}
|
||||
|
||||
@@ -625,8 +641,8 @@ static void hull_windings_r( hull_t *hull, mclipnode_t *node, hullnode_t *polys,
|
||||
Con_Printf( S_WARN "new winding was clipped away!\n" );
|
||||
}
|
||||
|
||||
do_hull_recursion( hull, node, 0, &frontlist, model );
|
||||
do_hull_recursion( hull, node, 1, &backlist, model );
|
||||
do_hull_recursion( hull, nodenum, 0, &frontlist, model );
|
||||
do_hull_recursion( hull, nodenum, 1, &backlist, model );
|
||||
}
|
||||
|
||||
static void remove_paired_polys( hull_model_t *model )
|
||||
@@ -655,7 +671,7 @@ static void make_hull_windings( hull_t *hull, hull_model_t *model )
|
||||
|
||||
if( hull->planes != NULL )
|
||||
{
|
||||
hull_windings_r( hull, hull->clipnodes + hull->firstclipnode, &head, model );
|
||||
hull_windings_r( hull, hull->firstclipnode, &head, model );
|
||||
remove_paired_polys( model );
|
||||
}
|
||||
Con_Reportf( "%i hull polys\n", model->num_polys );
|
||||
|
||||
@@ -300,6 +300,12 @@ static qboolean R_Init_Video_( const int type )
|
||||
return R_Init_Video( type );
|
||||
}
|
||||
|
||||
static mleaf_t *pfnMod_PointInLeaf( const vec3_t p, mnode_t *node )
|
||||
{
|
||||
// FIXME: get rid of this on next RefAPI update
|
||||
return Mod_PointInLeaf( p, node, cl.models[1] );
|
||||
}
|
||||
|
||||
static const ref_api_t gEngfuncs =
|
||||
{
|
||||
pfnEngineGetParm,
|
||||
@@ -340,7 +346,7 @@ static const ref_api_t gEngfuncs =
|
||||
|
||||
Mod_SampleSizeForFace,
|
||||
Mod_BoxVisible,
|
||||
Mod_PointInLeaf,
|
||||
pfnMod_PointInLeaf,
|
||||
R_DrawWorldHull,
|
||||
R_DrawModelHull,
|
||||
|
||||
|
||||
@@ -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 *)Z_Calloc( cur->cdelaysamplesmax * sizeof( int ));
|
||||
cur->lpdelayline = (int *)Mem_Calloc( sndpool, cur->cdelaysamplesmax * sizeof( int ));
|
||||
cur->xfade = 0;
|
||||
|
||||
// init modulation
|
||||
|
||||
@@ -107,17 +107,18 @@ S_CreateDefaultSound
|
||||
*/
|
||||
static wavdata_t *S_CreateDefaultSound( void )
|
||||
{
|
||||
wavdata_t *sc;
|
||||
wavdata_t *sc;
|
||||
uint samples = SOUND_DMA_SPEED;
|
||||
uint channels = 1;
|
||||
uint width = 2;
|
||||
size_t size = samples * width * channels;
|
||||
|
||||
sc = Mem_Calloc( sndpool, sizeof( wavdata_t ));
|
||||
|
||||
sc->width = 2;
|
||||
sc->channels = 1;
|
||||
sc->loopStart = 0;
|
||||
sc = Mem_Calloc( sndpool, sizeof( wavdata_t ) + size );
|
||||
sc->width = width;
|
||||
sc->channels = channels;
|
||||
sc->rate = SOUND_DMA_SPEED;
|
||||
sc->samples = SOUND_DMA_SPEED;
|
||||
sc->size = sc->samples * sc->width * sc->channels;
|
||||
sc->buffer = Mem_Calloc( sndpool, sc->size );
|
||||
sc->samples = samples;
|
||||
sc->size = size;
|
||||
|
||||
return sc;
|
||||
}
|
||||
|
||||
@@ -996,7 +996,7 @@ static void S_UpdateAmbientSounds( void )
|
||||
// calc ambient sound levels
|
||||
if( !cl.worldmodel ) return;
|
||||
|
||||
leaf = Mod_PointInLeaf( s_listener.origin, cl.worldmodel->nodes );
|
||||
leaf = Mod_PointInLeaf( s_listener.origin, cl.worldmodel->nodes, cl.worldmodel );
|
||||
|
||||
if( !leaf || !s_ambient_level.value )
|
||||
{
|
||||
@@ -1207,86 +1207,6 @@ 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
|
||||
@@ -1954,14 +1874,15 @@ 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,6 +16,7 @@ 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
|
||||
@@ -212,7 +213,7 @@ void S_StreamBackgroundTrack( void )
|
||||
|
||||
while( ch->s_rawend < soundtime + ch->max_samples )
|
||||
{
|
||||
wavdata_t *info = FS_StreamInfo( s_bgTrack.stream );
|
||||
const stream_t *info = s_bgTrack.stream;
|
||||
|
||||
bufferSamples = ch->max_samples - (ch->s_rawend - soundtime);
|
||||
|
||||
|
||||
@@ -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( host.mempool, size );
|
||||
rgpszrawsentence[index] = Mem_Malloc( sndpool, size );
|
||||
memcpy( rgpszrawsentence[index], name, size );
|
||||
rgpszrawsentence[index][size - 1] = 0;
|
||||
cszrawsentences++;
|
||||
|
||||
@@ -114,7 +114,6 @@ 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;
|
||||
@@ -171,6 +170,8 @@ typedef struct
|
||||
int source; // may be game, menu, etc
|
||||
} bg_track_t;
|
||||
|
||||
typedef int sound_t;
|
||||
|
||||
//====================================================================
|
||||
|
||||
#define MAX_DYNAMIC_CHANNELS (60 + NUM_AMBIENTS)
|
||||
|
||||
@@ -29,17 +29,20 @@ static void Sound_Reset( void )
|
||||
|
||||
static MALLOC_LIKE( FS_FreeSound, 1 ) wavdata_t *SoundPack( void )
|
||||
{
|
||||
wavdata_t *pack = Mem_Calloc( host.soundpool, sizeof( wavdata_t ));
|
||||
wavdata_t *pack = Mem_Malloc( host.soundpool, sizeof( *pack ) + sound.size );
|
||||
|
||||
pack->buffer = sound.wav;
|
||||
pack->width = sound.width;
|
||||
pack->rate = sound.rate;
|
||||
pack->type = sound.type;
|
||||
pack->size = sound.size;
|
||||
pack->loopStart = sound.loopstart;
|
||||
pack->samples = sound.samples;
|
||||
pack->channels = sound.channels;
|
||||
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;
|
||||
|
||||
return pack;
|
||||
}
|
||||
@@ -132,7 +135,6 @@ free WAV buffer
|
||||
void FS_FreeSound( wavdata_t *pack )
|
||||
{
|
||||
if( !pack ) return;
|
||||
if( pack->buffer ) Mem_Free( pack->buffer );
|
||||
Mem_Free( pack );
|
||||
}
|
||||
|
||||
@@ -199,33 +201,6 @@ 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 128 // 128 * 4 * 4 == 2048 bytes
|
||||
#define HASH_SIZE 64 // 64 * 4 * 4 == 1024 bytes
|
||||
|
||||
typedef struct base_command_hashmap_s base_command_hashmap_t;
|
||||
|
||||
@@ -26,10 +26,11 @@ 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[1]; // key for searching
|
||||
char name[]; // 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 )
|
||||
|
||||
@@ -42,11 +43,27 @@ Find base command in bucket
|
||||
*/
|
||||
static base_command_hashmap_t *BaseCmd_FindInBucket( base_command_hashmap_t *bucket, base_command_type_e type, const char *name )
|
||||
{
|
||||
base_command_hashmap_t *i = bucket;
|
||||
for( ; i && ( i->type != type || Q_stricmp( name, i->name ) ); // filter out
|
||||
i = i->next );
|
||||
base_command_hashmap_t *i;
|
||||
|
||||
return i;
|
||||
for( i = bucket; i != NULL; i = i->next )
|
||||
{
|
||||
int cmp;
|
||||
|
||||
if( i->type != type )
|
||||
continue;
|
||||
|
||||
cmp = Q_stricmp( i->name, name );
|
||||
|
||||
if( cmp < 0 )
|
||||
continue;
|
||||
|
||||
if( cmp > 0 )
|
||||
break;
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -90,27 +107,31 @@ void BaseCmd_FindAll( const char *name, base_command_t **cmd, base_command_t **a
|
||||
base_command_hashmap_t *base = BaseCmd_GetBucket( name );
|
||||
base_command_hashmap_t *i = base;
|
||||
|
||||
ASSERT( cmd && alias && cvar );
|
||||
|
||||
*cmd = *alias = *cvar = NULL;
|
||||
|
||||
for( ; i; i = i->next )
|
||||
{
|
||||
if( !Q_stricmp( i->name, name ) )
|
||||
int cmp = Q_stricmp( i->name, name );
|
||||
|
||||
if( cmp < 0 )
|
||||
continue;
|
||||
|
||||
if( cmp > 0 )
|
||||
break;
|
||||
|
||||
switch( i->type )
|
||||
{
|
||||
switch( i->type )
|
||||
{
|
||||
case HM_CMD:
|
||||
*cmd = i->basecmd;
|
||||
break;
|
||||
case HM_CMDALIAS:
|
||||
*alias = i->basecmd;
|
||||
break;
|
||||
case HM_CVAR:
|
||||
*cvar = i->basecmd;
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
case HM_CMD:
|
||||
*cmd = i->basecmd;
|
||||
break;
|
||||
case HM_CMDALIAS:
|
||||
*alias = i->basecmd;
|
||||
break;
|
||||
case HM_CVAR:
|
||||
*cvar = i->basecmd;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -128,14 +149,14 @@ void BaseCmd_Insert( base_command_type_e type, base_command_t *basecmd, const ch
|
||||
uint hash = BaseCmd_HashKey( name );
|
||||
size_t len = Q_strlen( name );
|
||||
|
||||
elem = Z_Malloc( sizeof( base_command_hashmap_t ) + len );
|
||||
elem = Mem_Malloc( basecmd_pool, sizeof( base_command_hashmap_t ) + len + 1 );
|
||||
elem->basecmd = basecmd;
|
||||
elem->type = type;
|
||||
Q_strncpy( elem->name, name, len + 1 );
|
||||
|
||||
// link the variable in alphanumerical order
|
||||
for( cur = NULL, find = hashed_cmds[hash];
|
||||
find && Q_strcmp( find->name, elem->name ) < 0;
|
||||
find && Q_stricmp( find->name, elem->name ) < 0;
|
||||
cur = find, find = find->next );
|
||||
|
||||
if( cur ) cur->next = elem;
|
||||
@@ -156,9 +177,23 @@ void BaseCmd_Remove( base_command_type_e type, const char *name )
|
||||
uint hash = BaseCmd_HashKey( name );
|
||||
base_command_hashmap_t *i, *prev;
|
||||
|
||||
for( prev = NULL, i = hashed_cmds[hash]; i &&
|
||||
( Q_strcmp( i->name, name ) || i->type != type); // filter out
|
||||
prev = i, i = i->next );
|
||||
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;
|
||||
}
|
||||
|
||||
if( !i )
|
||||
{
|
||||
@@ -183,9 +218,15 @@ 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,6 +32,7 @@ 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,6 +46,7 @@ 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 );
|
||||
|
||||
@@ -432,7 +433,7 @@ static void Cmd_Alias_f( void )
|
||||
{
|
||||
if( !Q_strcmp( s, a->name ))
|
||||
{
|
||||
Z_Free( a->value );
|
||||
Mem_Free( a->value );
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -441,7 +442,7 @@ static void Cmd_Alias_f( void )
|
||||
{
|
||||
cmdalias_t *cur, *prev;
|
||||
|
||||
a = Z_Malloc( sizeof( cmdalias_t ));
|
||||
a = Mem_Malloc( cmd_pool, sizeof( cmdalias_t ));
|
||||
|
||||
Q_strncpy( a->name, s, sizeof( a->name ));
|
||||
|
||||
@@ -469,7 +470,7 @@ static void Cmd_Alias_f( void )
|
||||
}
|
||||
|
||||
Q_strncat( cmd, "\n", sizeof( cmd ));
|
||||
a->value = copystring( cmd );
|
||||
a->value = copystringpool( cmd_pool, cmd );
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -529,7 +530,7 @@ struct cmd_s
|
||||
char *name;
|
||||
xcommand_t function;
|
||||
int flags;
|
||||
char *desc;
|
||||
char desc[];
|
||||
};
|
||||
|
||||
static int cmd_argc;
|
||||
@@ -636,7 +637,7 @@ void Cmd_TokenizeString( const char *text )
|
||||
|
||||
// clear the args from the last string
|
||||
for( i = 0; i < cmd_argc; i++ )
|
||||
Z_Free( cmd_argv[i] );
|
||||
Mem_Free( cmd_argv[i] );
|
||||
|
||||
cmd_argc = 0; // clear previous args
|
||||
cmd_args = NULL;
|
||||
@@ -670,7 +671,7 @@ void Cmd_TokenizeString( const char *text )
|
||||
|
||||
if( cmd_argc < MAX_CMD_TOKENS )
|
||||
{
|
||||
cmd_argv[cmd_argc] = copystring( cmd_token );
|
||||
cmd_argv[cmd_argc] = copystringpool( cmd_pool, cmd_token );
|
||||
cmd_argc++;
|
||||
}
|
||||
}
|
||||
@@ -683,7 +684,8 @@ Cmd_AddCommandEx
|
||||
*/
|
||||
int Cmd_AddCommandEx( const char *cmd_name, xcommand_t function, const char *cmd_desc, int iFlags, const char *funcname )
|
||||
{
|
||||
cmd_t *cmd, *cur, *prev;
|
||||
cmd_t *cmd, *cur, *prev;
|
||||
size_t desc_len;
|
||||
|
||||
if( !COM_CheckString( cmd_name ))
|
||||
{
|
||||
@@ -707,8 +709,8 @@ int Cmd_AddCommandEx( const char *cmd_name, xcommand_t function, const char *cmd
|
||||
// unfortunately, we lose original command this way
|
||||
if( FBitSet( cmd->flags, CMD_OVERRIDABLE ))
|
||||
{
|
||||
Mem_Free( cmd->desc );
|
||||
cmd->desc = copystring( cmd_desc );
|
||||
desc_len = Q_strlen( cmd->desc ) + 1;
|
||||
Q_strncpy( cmd->desc, cmd_desc, desc_len );
|
||||
cmd->function = function;
|
||||
cmd->flags = iFlags;
|
||||
|
||||
@@ -723,9 +725,10 @@ int Cmd_AddCommandEx( const char *cmd_name, xcommand_t function, const char *cmd
|
||||
}
|
||||
|
||||
// use a small malloc to avoid zone fragmentation
|
||||
cmd = Z_Malloc( sizeof( cmd_t ) );
|
||||
cmd->name = copystring( cmd_name );
|
||||
cmd->desc = copystring( cmd_desc );
|
||||
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->function = function;
|
||||
cmd->flags = iFlags;
|
||||
|
||||
@@ -772,9 +775,6 @@ 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,7 +1202,6 @@ 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++;
|
||||
@@ -1340,6 +1339,7 @@ Cmd_Init
|
||||
*/
|
||||
void Cmd_Init( void )
|
||||
{
|
||||
cmd_pool = Mem_AllocPool( "Console Commands" );
|
||||
cmd_functions = NULL;
|
||||
cmd_condition = 0;
|
||||
cmd_alias = NULL;
|
||||
@@ -1366,6 +1366,11 @@ void Cmd_Init( void )
|
||||
#endif
|
||||
}
|
||||
|
||||
void Cmd_Shutdown( void )
|
||||
{
|
||||
Mem_FreePool( &cmd_pool );
|
||||
}
|
||||
|
||||
#if XASH_ENGINE_TESTS
|
||||
#include "tests.h"
|
||||
|
||||
|
||||
@@ -72,8 +72,6 @@ GNU General Public License for more details.
|
||||
|
||||
#define CVAR_GLCONFIG_DESCRIPTION "enable or disable %s"
|
||||
|
||||
#define DEFAULT_BSP_BUILD_ERROR "%s can't be loaded in this build. Please rebuild engine with enabled SUPPORT_BSP2_FORMAT\n"
|
||||
|
||||
#define DEFAULT_UPDATE_PAGE "https://github.com/FWGS/xash3d-fwgs/releases/latest"
|
||||
|
||||
#define XASH_ENGINE_NAME "Xash3D FWGS"
|
||||
|
||||
@@ -76,23 +76,14 @@ 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
|
||||
enum dev_level_e
|
||||
{
|
||||
DEV_NONE = 0,
|
||||
DEV_NORMAL,
|
||||
DEV_EXTENDED
|
||||
};
|
||||
|
||||
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
|
||||
typedef enum instance_e
|
||||
{
|
||||
HOST_NORMAL, // listen server, singleplayer
|
||||
HOST_DEDICATED,
|
||||
@@ -108,14 +99,14 @@ typedef enum
|
||||
#include "com_model.h"
|
||||
#include "com_strings.h"
|
||||
#include "crtlib.h"
|
||||
#include "cvar.h"
|
||||
#include "con_nprint.h"
|
||||
#include "crclib.h"
|
||||
#include "ref_api.h"
|
||||
#define FSCALLBACK_OVERRIDE_OPEN
|
||||
#define FSCALLBACK_OVERRIDE_LOADFILE
|
||||
#define FSCALLBACK_OVERRIDE_MALLOC_LIKE
|
||||
#include "fscallback.h"
|
||||
#include "cvar.h"
|
||||
#include "con_nprint.h"
|
||||
#include "crclib.h"
|
||||
#include "ref_api.h"
|
||||
|
||||
// PERFORMANCE INFO
|
||||
#define MIN_FPS 20.0f // host minimum fps value for maxfps.
|
||||
@@ -146,6 +137,11 @@ typedef enum
|
||||
#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
|
||||
@@ -171,6 +167,11 @@ 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 ))
|
||||
|
||||
@@ -189,7 +190,7 @@ GAMEINFO stuff
|
||||
internal shared gameinfo structure (readonly for engine parts)
|
||||
========================================================================
|
||||
*/
|
||||
typedef enum
|
||||
typedef enum host_status_e
|
||||
{
|
||||
HOST_INIT = 0, // initalize operations
|
||||
HOST_FRAME, // host running
|
||||
@@ -200,7 +201,7 @@ typedef enum
|
||||
HOST_CRASHED // an exception handler called
|
||||
} host_status_t;
|
||||
|
||||
typedef enum
|
||||
typedef enum host_state_e
|
||||
{
|
||||
STATE_RUNFRAME = 0,
|
||||
STATE_LOAD_LEVEL,
|
||||
@@ -209,7 +210,7 @@ typedef enum
|
||||
STATE_GAME_SHUTDOWN,
|
||||
} host_state_t;
|
||||
|
||||
typedef struct
|
||||
typedef struct game_status_e
|
||||
{
|
||||
host_state_t curstate;
|
||||
host_state_t nextstate;
|
||||
@@ -220,7 +221,7 @@ typedef struct
|
||||
qboolean newGame; // unload the server.dll before start a new map
|
||||
} game_status_t;
|
||||
|
||||
typedef enum
|
||||
typedef enum keydest_e
|
||||
{
|
||||
key_console = 0,
|
||||
key_game,
|
||||
@@ -228,7 +229,7 @@ typedef enum
|
||||
key_message
|
||||
} keydest_t;
|
||||
|
||||
typedef enum
|
||||
typedef enum rdtype_e
|
||||
{
|
||||
RD_NONE = 0,
|
||||
RD_CLIENT,
|
||||
@@ -238,7 +239,7 @@ typedef enum
|
||||
#include "net_ws.h"
|
||||
|
||||
// console field
|
||||
typedef struct
|
||||
typedef struct field_e
|
||||
{
|
||||
string buffer;
|
||||
int cursor;
|
||||
@@ -256,7 +257,7 @@ typedef struct host_redirect_s
|
||||
int lines;
|
||||
} host_redirect_t;
|
||||
|
||||
typedef struct
|
||||
typedef struct soundlist_e
|
||||
{
|
||||
char name[MAX_QPATH];
|
||||
short entnum;
|
||||
@@ -297,11 +298,10 @@ typedef struct host_parm_s
|
||||
|
||||
host_status_t status; // global host state
|
||||
game_status_t game; // game manager
|
||||
uint type; // running at
|
||||
instance_t type; // running at
|
||||
poolhandle_t mempool; // static mempool for misc allocations
|
||||
poolhandle_t imagepool; // imagelib mempool
|
||||
poolhandle_t soundpool; // soundlib mempool
|
||||
string finalmsg; // server shutdown final message
|
||||
string downloadfile; // filename to be downloading
|
||||
int downloadcount; // how many files remain to downloading
|
||||
char deferred_cmd[128];// deferred commands
|
||||
@@ -415,6 +415,8 @@ 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
|
||||
@@ -433,6 +435,7 @@ 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 );
|
||||
|
||||
@@ -491,7 +494,7 @@ internal sound format
|
||||
typically expanded to wav buffer
|
||||
========================================================================
|
||||
*/
|
||||
typedef enum
|
||||
typedef enum sndformat_e
|
||||
{
|
||||
WF_UNKNOWN = 0,
|
||||
WF_PCMDATA,
|
||||
@@ -502,7 +505,7 @@ typedef enum
|
||||
} sndformat_t;
|
||||
|
||||
// wavdata output flags
|
||||
typedef enum
|
||||
typedef enum sndFlags_e
|
||||
{
|
||||
// wavdata->flags
|
||||
SOUND_LOOPED = BIT( 0 ), // this is looped sound (contain cue markers)
|
||||
@@ -512,29 +515,29 @@ typedef enum
|
||||
SOUND_RESAMPLE = BIT( 12 ), // resample sound to specified rate
|
||||
} sndFlags_t;
|
||||
|
||||
typedef struct
|
||||
typedef struct wavdata_s
|
||||
{
|
||||
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)
|
||||
size_t size; // for bounds checking
|
||||
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
|
||||
byte *buffer; // sound buffer
|
||||
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)
|
||||
byte buffer[]; // sound buffer
|
||||
} 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 );
|
||||
@@ -560,6 +563,7 @@ void Host_Error( const char *error, ... ) FORMAT_CHECK( 1 );
|
||||
void Host_ValidateEngineFeatures( uint32_t mask, uint32_t features );
|
||||
void Host_Frame( double time );
|
||||
void Host_Credits( void );
|
||||
void Host_ExitInMain( void );
|
||||
|
||||
//
|
||||
// host_state.c
|
||||
@@ -578,11 +582,19 @@ CLIENT / SERVER SYSTEMS
|
||||
|
||||
==============================================================
|
||||
*/
|
||||
#if !XASH_DEDICATED
|
||||
void CL_Init( void );
|
||||
void CL_Shutdown( void );
|
||||
void Host_ClientBegin( void );
|
||||
void Host_ClientFrame( void );
|
||||
int CL_Active( void );
|
||||
#else
|
||||
static inline void CL_Init( void ) { }
|
||||
static inline void CL_Shutdown( void ) { }
|
||||
static inline void Host_ClientBegin( void ) { Cbuf_Execute(); }
|
||||
static inline void Host_ClientFrame( void ) { }
|
||||
static inline int CL_Active( void ) { return 0; }
|
||||
#endif
|
||||
|
||||
void SV_Init( void );
|
||||
void SV_Shutdown( const char *finalmsg );
|
||||
@@ -620,6 +632,7 @@ 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 );
|
||||
@@ -670,6 +683,7 @@ 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 );
|
||||
@@ -703,13 +717,32 @@ typedef enum connprotocol_e
|
||||
struct physent_s;
|
||||
struct sv_client_s;
|
||||
typedef struct sizebuf_s sizebuf_t;
|
||||
int SV_GetMaxClients( void );
|
||||
|
||||
#if !XASH_DEDICATED
|
||||
qboolean CL_Initialized( void );
|
||||
qboolean CL_IsInGame( void );
|
||||
qboolean CL_IsInConsole( void );
|
||||
qboolean CL_IsIntermission( void );
|
||||
qboolean CL_Initialized( void );
|
||||
qboolean CL_DisableVisibility( void );
|
||||
qboolean CL_IsRecordDemo( void );
|
||||
qboolean CL_IsPlaybackDemo( void );
|
||||
qboolean UI_CreditsActive( void );
|
||||
int CL_GetMaxClients( void );
|
||||
#else
|
||||
static inline qboolean CL_Initialized( void ) { return false; }
|
||||
static inline qboolean CL_IsInGame( void ) { return true; } // always true for dedicated
|
||||
static inline qboolean CL_IsInConsole( void ) { return false; }
|
||||
static inline qboolean CL_IsIntermission( void ) { return false; }
|
||||
static inline qboolean CL_DisableVisibility( void ) { return false; }
|
||||
static inline qboolean CL_IsRecordDemo( void ) { return false; }
|
||||
static inline qboolean CL_IsPlaybackDemo( void ) { return false; }
|
||||
static inline qboolean UI_CreditsActive( void ) { return false; }
|
||||
static inline int CL_GetMaxClients( void ) { return SV_GetMaxClients(); }
|
||||
#endif
|
||||
|
||||
char *CL_Userinfo( void );
|
||||
void CL_CharEvent( int key );
|
||||
qboolean CL_DisableVisibility( void );
|
||||
byte *COM_LoadFile( const char *filename, int usehunk, int *pLength ) MALLOC_LIKE( free, 1 );
|
||||
struct cmd_s *Cmd_GetFirstFunctionHandle( void );
|
||||
struct cmd_s *Cmd_GetNextFunctionHandle( struct cmd_s *cmd );
|
||||
@@ -727,13 +760,7 @@ const char *CL_MsgInfo( int cmd );
|
||||
void SV_DrawDebugTriangles( void );
|
||||
void SV_DrawOrthoTriangles( void );
|
||||
double CL_GetDemoFramerate( void );
|
||||
qboolean UI_CreditsActive( void );
|
||||
void CL_StopPlayback( void );
|
||||
int CL_GetMaxClients( void );
|
||||
int SV_GetMaxClients( void );
|
||||
qboolean CL_IsRecordDemo( void );
|
||||
qboolean CL_IsTimeDemo( void );
|
||||
qboolean CL_IsPlaybackDemo( void );
|
||||
qboolean SV_Initialized( void );
|
||||
void CL_ProcessFile( qboolean successfully_received, const char *filename );
|
||||
int SV_GetSaveComment( const char *savename, char *comment );
|
||||
@@ -846,13 +873,6 @@ 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,7 +498,6 @@ static qboolean Cmd_GetSoundList( const char *s, char *completedname, int length
|
||||
return true;
|
||||
}
|
||||
|
||||
#if !XASH_DEDICATED
|
||||
/*
|
||||
=====================================
|
||||
Cmd_GetItemsList
|
||||
@@ -508,6 +507,7 @@ 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,6 +544,8 @@ static qboolean Cmd_GetItemsList( const char *s, char *completedname, int length
|
||||
}
|
||||
}
|
||||
return true;
|
||||
#endif // !XASH_DEDICATED
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -555,6 +557,7 @@ 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;
|
||||
@@ -595,8 +598,9 @@ static qboolean Cmd_GetKeysList( const char *s, char *completedname, int length
|
||||
}
|
||||
|
||||
return true;
|
||||
#endif // !XASH_DEDICATED
|
||||
return false;
|
||||
}
|
||||
#endif // XASH_DEDICATED
|
||||
|
||||
/*
|
||||
===============
|
||||
@@ -604,13 +608,20 @@ Con_AddCommandToList
|
||||
|
||||
===============
|
||||
*/
|
||||
static void Con_AddCommandToList( const char *s, const char *unused1, const char *unused2, void *_autocompleteList )
|
||||
static void Con_AddCommandToList( const char *s, const char *value, const void *ptoggle, 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
|
||||
|
||||
@@ -634,13 +645,11 @@ Cmd_GetCommandsList
|
||||
Autocomplete for bind command
|
||||
=====================================
|
||||
*/
|
||||
static qboolean Cmd_GetCommandsList( const char *s, char *completedname, int length )
|
||||
static qboolean Cmd_GetCommandsAndCvarsList( const char *s, char *completedname, int length, qboolean cmds, qboolean cvars, qboolean toggle )
|
||||
{
|
||||
size_t i;
|
||||
string matchbuf;
|
||||
con_autocomplete_t list; // local autocomplete list
|
||||
|
||||
memset( &list, 0, sizeof( list ));
|
||||
con_autocomplete_t list = { 0 }; // local autocomplete list
|
||||
|
||||
list.completionString = s;
|
||||
|
||||
@@ -652,8 +661,16 @@ static qboolean Cmd_GetCommandsList( const char *s, char *completedname, int len
|
||||
return false;
|
||||
|
||||
// find matching commands and variables
|
||||
Cmd_LookupCmds( NULL, &list, (setpair_t)Con_AddCommandToList );
|
||||
Cvar_LookupVars( 0, NULL, &list, (setpair_t)Con_AddCommandToList );
|
||||
if( cvars )
|
||||
{
|
||||
Cvar_LookupVars( 0, &toggle, &list, (setpair_t)Con_AddCommandToList );
|
||||
}
|
||||
|
||||
if( cmds )
|
||||
{
|
||||
toggle = false;
|
||||
Cmd_LookupCmds( &toggle, &list, (setpair_t)Con_AddCommandToList );
|
||||
}
|
||||
|
||||
if( !list.matchCount ) return false;
|
||||
Q_strncpy( matchbuf, list.cmds[0], sizeof( matchbuf ));
|
||||
@@ -669,7 +686,7 @@ static qboolean Cmd_GetCommandsList( const char *s, char *completedname, int len
|
||||
Con_Printf( "%16s\n", matchbuf );
|
||||
}
|
||||
|
||||
Con_Printf( "\n^3 %i commands found.\n", list.matchCount );
|
||||
Con_Printf( "\n^3 %i %s found.\n", list.matchCount, cmds ? "commands" : "variables" );
|
||||
|
||||
if( completedname && length )
|
||||
{
|
||||
@@ -691,6 +708,30 @@ static qboolean Cmd_GetCommandsList( const char *s, char *completedname, int len
|
||||
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 );
|
||||
}
|
||||
|
||||
/*
|
||||
=====================================
|
||||
@@ -1010,36 +1051,38 @@ int GAME_EXPORT Cmd_CheckMapsList( int fRefresh )
|
||||
return Cmd_CheckMapsList_R( fRefresh, true );
|
||||
}
|
||||
|
||||
// keep this sorted
|
||||
static const autocomplete_list_t cmd_list[] =
|
||||
{
|
||||
{ "map_background", 1, Cmd_GetMapList },
|
||||
{ "bind", 1, Cmd_GetKeysList },
|
||||
{ "bind", 2, Cmd_GetCommandsList },
|
||||
{ "cd", 1, Cmd_GetCDList },
|
||||
{ "changelevel2", 1, Cmd_GetMapList },
|
||||
{ "changelevel", 1, Cmd_GetMapList },
|
||||
{ "playdemo", 1, Cmd_GetDemoList, },
|
||||
{ "timedemo", 1, Cmd_GetDemoList, },
|
||||
{ "listdemo", 1, Cmd_GetDemoList, },
|
||||
{ "playvol", 1, Cmd_GetSoundList },
|
||||
{ "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
|
||||
{ "entpatch", 1, Cmd_GetMapList },
|
||||
{ "exec", 1, Cmd_GetConfigList },
|
||||
{ "game", 1, Cmd_GetGamesList },
|
||||
{ "save", 1, Cmd_GetSavesList },
|
||||
{ "give", 1, Cmd_GetItemsList },
|
||||
{ "hpkextract", 1, Cmd_GetCustomList },
|
||||
{ "hpklist", 1, Cmd_GetCustomList },
|
||||
{ "hpkval", 1, Cmd_GetCustomList },
|
||||
{ "listdemo", 1, Cmd_GetDemoList, },
|
||||
{ "load", 1, Cmd_GetSavesList },
|
||||
{ "play", 1, Cmd_GetSoundList },
|
||||
{ "map", 1, Cmd_GetMapList },
|
||||
{ "cd", 1, Cmd_GetCDList },
|
||||
{ "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, },
|
||||
{ "playvol", 1, Cmd_GetSoundList },
|
||||
{ "reset", 1, Cmd_GetCvarsList },
|
||||
{ "save", 1, Cmd_GetSavesList },
|
||||
{ "set", 1, Cmd_GetCvarsList },
|
||||
{ "timedemo", 1, Cmd_GetDemoList },
|
||||
{ "toggle", 1, Cmd_GetCvarsList },
|
||||
{ "unbind", 1, Cmd_GetKeysList },
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -1160,6 +1203,7 @@ void Con_CompleteCommand( field_t *field )
|
||||
{
|
||||
field_t temp;
|
||||
string filename;
|
||||
qboolean toggle = false;
|
||||
qboolean nextcmd;
|
||||
int i;
|
||||
|
||||
@@ -1194,8 +1238,8 @@ void Con_CompleteCommand( field_t *field )
|
||||
con.shortestMatch[0] = 0;
|
||||
|
||||
// find matching commands and variables
|
||||
Cmd_LookupCmds( NULL, &con, (setpair_t)Con_AddCommandToList );
|
||||
Cvar_LookupVars( 0, NULL, &con, (setpair_t)Con_AddCommandToList );
|
||||
Cmd_LookupCmds( &toggle, &con, (setpair_t)Con_AddCommandToList );
|
||||
Cvar_LookupVars( 0, &toggle, &con, (setpair_t)Con_AddCommandToList );
|
||||
|
||||
if( !con.matchCount ) return; // no matches
|
||||
|
||||
@@ -1395,7 +1439,7 @@ void Host_WriteConfig( void )
|
||||
{
|
||||
Con_Reportf( "%s()\n", __func__ );
|
||||
FS_Printf( f, "//=======================================================================\n");
|
||||
FS_Printf( f, "//\tGenerated by "XASH_ENGINE_NAME" (%i, %s, %s, %s-%s)\n", Q_buildnum(), Q_buildcommit(), Q_buildbranch(), Q_buildos(), Q_buildarch());
|
||||
FS_Printf( f, "//\tGenerated by "XASH_ENGINE_NAME" (%i, %s, %s, %s-%s)\n", Q_buildnum(), g_buildcommit, g_buildbranch, Q_buildos(), Q_buildarch());
|
||||
FS_Printf( f, "//\t\tconfig.cfg - archive of cvars\n" );
|
||||
FS_Printf( f, "//=======================================================================\n" );
|
||||
Key_WriteBindings( f );
|
||||
@@ -1443,7 +1487,7 @@ void GAME_EXPORT Host_WriteServerConfig( const char *name )
|
||||
if(( f = FS_Open( newconfigfile, "w", false )) != NULL )
|
||||
{
|
||||
FS_Printf( f, "//=======================================================================\n" );
|
||||
FS_Printf( f, "//\tGenerated by "XASH_ENGINE_NAME" (%i, %s, %s, %s-%s)\n", Q_buildnum(), Q_buildcommit(), Q_buildbranch(), Q_buildos(), Q_buildarch());
|
||||
FS_Printf( f, "//\tGenerated by "XASH_ENGINE_NAME" (%i, %s, %s, %s-%s)\n", Q_buildnum(), g_buildcommit, g_buildbranch, Q_buildos(), Q_buildarch());
|
||||
FS_Printf( f, "//\t\tgame.cfg - multiplayer server temporare config\n" );
|
||||
FS_Printf( f, "//=======================================================================\n" );
|
||||
|
||||
@@ -1478,7 +1522,7 @@ void Host_WriteOpenGLConfig( void )
|
||||
{
|
||||
Con_Reportf( "%s()\n", __func__ );
|
||||
FS_Printf( f, "//=======================================================================\n" );
|
||||
FS_Printf( f, "//\tGenerated by "XASH_ENGINE_NAME" (%i, %s, %s, %s-%s)\n", Q_buildnum(), Q_buildcommit(), Q_buildbranch(), Q_buildos(), Q_buildarch());
|
||||
FS_Printf( f, "//\tGenerated by "XASH_ENGINE_NAME" (%i, %s, %s, %s-%s)\n", Q_buildnum(), g_buildcommit, g_buildbranch, Q_buildos(), Q_buildarch());
|
||||
FS_Printf( f, "//\t\t%s - archive of renderer implementation cvars\n", name );
|
||||
FS_Printf( f, "//=======================================================================\n" );
|
||||
FS_Printf( f, "\n" );
|
||||
@@ -1508,7 +1552,7 @@ void Host_WriteVideoConfig( void )
|
||||
{
|
||||
Con_Reportf( "%s()\n", __func__ );
|
||||
FS_Printf( f, "//=======================================================================\n" );
|
||||
FS_Printf( f, "//\tGenerated by "XASH_ENGINE_NAME" (%i, %s, %s, %s-%s)\n", Q_buildnum(), Q_buildcommit(), Q_buildbranch(), Q_buildos(), Q_buildarch());
|
||||
FS_Printf( f, "//\tGenerated by "XASH_ENGINE_NAME" (%i, %s, %s, %s-%s)\n", Q_buildnum(), g_buildcommit, g_buildbranch, Q_buildos(), Q_buildarch());
|
||||
FS_Printf( f, "//\t\tvideo.cfg - archive of renderer variables\n");
|
||||
FS_Printf( f, "//=======================================================================\n" );
|
||||
Cvar_WriteVariables( f, FCVAR_RENDERINFO );
|
||||
@@ -1534,7 +1578,7 @@ void Key_EnumCmds_f( void )
|
||||
if( f )
|
||||
{
|
||||
FS_Printf( f, "//=======================================================================\n");
|
||||
FS_Printf( f, "//\tGenerated by "XASH_ENGINE_NAME" (%i, %s, %s, %s-%s)\n", Q_buildnum(), Q_buildcommit(), Q_buildbranch(), Q_buildos(), Q_buildarch());
|
||||
FS_Printf( f, "//\tGenerated by "XASH_ENGINE_NAME" (%i, %s, %s, %s-%s)\n", Q_buildnum(), g_buildcommit, g_buildbranch, Q_buildos(), Q_buildarch());
|
||||
FS_Printf( f, "//\t\thelp.txt - xash commands and console variables\n");
|
||||
FS_Printf( f, "//=======================================================================\n");
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ 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
|
||||
@@ -432,7 +433,7 @@ convar_t *Cvar_Get( const char *name, const char *value, int flags, const char *
|
||||
{
|
||||
// directly set value
|
||||
freestring( var->string );
|
||||
var->string = copystring( value );
|
||||
var->string = copystringpool( cvar_pool, value );
|
||||
var->value = Q_atof( var->string );
|
||||
SetBits( var->flags, flags );
|
||||
|
||||
@@ -452,18 +453,18 @@ convar_t *Cvar_Get( const char *name, const char *value, int flags, const char *
|
||||
Con_Reportf( "%s change description from %s to %s\n", var->name, var->desc, var_desc );
|
||||
// update description if needs
|
||||
freestring( var->desc );
|
||||
var->desc = copystring( var_desc );
|
||||
var->desc = copystringpool( cvar_pool, var_desc );
|
||||
}
|
||||
|
||||
return var;
|
||||
}
|
||||
|
||||
// allocate a new cvar
|
||||
var = Z_Malloc( sizeof( *var ));
|
||||
var->name = copystring( name );
|
||||
var->string = copystring( value );
|
||||
var->def_string = copystring( value );
|
||||
var->desc = copystring( var_desc );
|
||||
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->value = Q_atof( var->string );
|
||||
var->flags = flags|FCVAR_ALLOCATED;
|
||||
|
||||
@@ -549,7 +550,7 @@ void Cvar_RegisterVariable( convar_t *var )
|
||||
if( FBitSet( var->flags, FCVAR_EXTENDED ))
|
||||
var->def_string = var->string; // just swap pointers
|
||||
|
||||
var->string = copystring( var->string );
|
||||
var->string = copystringpool( cvar_pool, var->string );
|
||||
var->value = Q_atof( var->string );
|
||||
|
||||
// find the supposed position in chain (alphanumerical order)
|
||||
@@ -679,7 +680,7 @@ static convar_t *Cvar_Set2( const char *var_name, const char *value )
|
||||
|
||||
// and finally changed the cvar itself
|
||||
freestring( var->string );
|
||||
var->string = copystring( pszValue );
|
||||
var->string = copystringpool( cvar_pool, pszValue );
|
||||
var->value = Q_atof( var->string );
|
||||
|
||||
// tell engine about changes
|
||||
@@ -738,7 +739,7 @@ void GAME_EXPORT Cvar_DirectSet( convar_t *var, const char *value )
|
||||
|
||||
// and finally changed the cvar itself
|
||||
freestring( var->string );
|
||||
var->string = copystring( pszValue );
|
||||
var->string = copystringpool( cvar_pool, pszValue );
|
||||
var->value = Q_atof( var->string );
|
||||
|
||||
// tell engine about changes
|
||||
@@ -781,7 +782,7 @@ void Cvar_FullSet( const char *var_name, const char *value, int flags )
|
||||
}
|
||||
|
||||
freestring( var->string );
|
||||
var->string = copystring( value );
|
||||
var->string = copystringpool( cvar_pool, value );
|
||||
var->value = Q_atof( var->string );
|
||||
SetBits( var->flags, flags );
|
||||
|
||||
@@ -1189,6 +1190,7 @@ 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
|
||||
@@ -1196,7 +1198,9 @@ static void Cvar_List_f( void )
|
||||
if( match && !Q_strnicmpext( match, var->name, matchlen ))
|
||||
continue;
|
||||
|
||||
if( Q_colorstr( var->string ))
|
||||
p = Q_strchr( var->string, '^' );
|
||||
|
||||
if( IsColorString( p ))
|
||||
Q_snprintf( value, sizeof( value ), "\"%s\"", var->string );
|
||||
else Q_snprintf( value, sizeof( value ), "\"^2%s^7\"", var->string );
|
||||
|
||||
@@ -1257,7 +1261,7 @@ pending_cvar_t *Cvar_PrepareToUnlink( int group )
|
||||
continue;
|
||||
|
||||
namelen = Q_strlen( cv->name ) + 1;
|
||||
p = Mem_Malloc( host.mempool, sizeof( *list ) + namelen );
|
||||
p = Mem_Malloc( cvar_pool, sizeof( *list ) + namelen );
|
||||
p->next = NULL;
|
||||
p->cv_cur = cv;
|
||||
p->cv_next = cv->next;
|
||||
@@ -1333,6 +1337,7 @@ 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 );
|
||||
@@ -1345,6 +1350,11 @@ 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,6 +30,8 @@ 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 );
|
||||
@@ -52,6 +54,7 @@ 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 );
|
||||
|
||||
|
||||
@@ -49,52 +49,6 @@ const char *CL_MsgInfo( int cmd )
|
||||
return sz;
|
||||
}
|
||||
|
||||
int GAME_EXPORT CL_Active( void )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
qboolean CL_Initialized( void )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
qboolean CL_IsInGame( void )
|
||||
{
|
||||
return true; // always active for dedicated servers
|
||||
}
|
||||
|
||||
qboolean CL_IsInConsole( void )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
qboolean CL_IsIntermission( void )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
qboolean CL_IsPlaybackDemo( void )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
qboolean CL_IsRecordDemo( void )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
qboolean CL_DisableVisibility( void )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void CL_Init( void )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void Key_Init( void )
|
||||
{
|
||||
|
||||
@@ -130,16 +84,6 @@ void CL_WriteMessageHistory( void )
|
||||
|
||||
}
|
||||
|
||||
void Host_ClientBegin( void )
|
||||
{
|
||||
Cbuf_Execute();
|
||||
}
|
||||
|
||||
void Host_ClientFrame( void )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void Host_InputFrame( void )
|
||||
{
|
||||
}
|
||||
@@ -159,11 +103,6 @@ void GAME_EXPORT S_StopSound(int entnum, int channel, const char *soundname)
|
||||
|
||||
}
|
||||
|
||||
int GAME_EXPORT CL_GetMaxClients( void )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void IN_TouchInitConfig( void )
|
||||
{
|
||||
|
||||
@@ -174,11 +113,6 @@ void CL_Disconnect( void )
|
||||
|
||||
}
|
||||
|
||||
void CL_Shutdown( void )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void R_ClearStaticEntities( void )
|
||||
{
|
||||
|
||||
@@ -189,11 +123,6 @@ void Host_Credits( void )
|
||||
|
||||
}
|
||||
|
||||
qboolean UI_CreditsActive( void )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void S_StopBackgroundTrack( void )
|
||||
{
|
||||
|
||||
@@ -204,11 +133,6 @@ void SCR_BeginLoadingPlaque( qboolean is_background )
|
||||
|
||||
}
|
||||
|
||||
int S_GetCurrentDynamicSounds( soundlist_t *pout, int size )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void S_StopAllSounds( qboolean ambient )
|
||||
{
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
filesystem.c - game filesystem based on DP fs
|
||||
Copyright (C) 2003-2006 Mathieu Olivier
|
||||
Copyright (C) 2000-2007 DarkPlaces contributors
|
||||
@@ -21,6 +21,12 @@ GNU General Public License for more details.
|
||||
#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;
|
||||
|
||||
@@ -69,9 +75,23 @@ void *FS_GetNativeObject( const char *obj )
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void FS_Rescan_f( void )
|
||||
void FS_Rescan_f( void )
|
||||
{
|
||||
FS_Rescan();
|
||||
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 );
|
||||
}
|
||||
|
||||
static void FS_ClearPaths_f( void )
|
||||
@@ -183,14 +203,23 @@ static qboolean FS_DetermineRootDirectory( char *out, size_t size )
|
||||
#elif XASH_PSVITA
|
||||
if( PSVita_GetBasePath( out, size ))
|
||||
return true;
|
||||
Sys_Error( "couldn't find Xash3D data directory" );
|
||||
Sys_Error( "couldn't find %s data directory", XASH_ENGINE_NAME );
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -227,6 +256,12 @@ 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
|
||||
@@ -279,6 +314,11 @@ 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;
|
||||
|
||||
|
||||
@@ -43,6 +43,27 @@ GNU General Public License for more details.
|
||||
static pfnChangeGame pChangeGame = NULL;
|
||||
host_parm_t host; // host parms
|
||||
|
||||
#if XASH_ANDROID
|
||||
static jmp_buf return_from_main_buf;
|
||||
|
||||
/*
|
||||
===============
|
||||
Host_ExitInMain
|
||||
|
||||
On some platforms (e.g. Android) we can't exit with exit(3) as calling it would
|
||||
kill wrapper process (e.g. app_process) too early, before all resources would
|
||||
be freed, contexts released, files closed, etc, etc...
|
||||
|
||||
To fix this, we create jmp_buf in Host_Main function, when jumping into with
|
||||
non-zero value will immediately return from it with `error_on_exit`.
|
||||
===============
|
||||
*/
|
||||
void Host_ExitInMain( void )
|
||||
{
|
||||
longjmp( return_from_main_buf, 1 );
|
||||
}
|
||||
#endif // XASH_ANDROID
|
||||
|
||||
#ifdef XASH_ENGINE_TESTS
|
||||
struct tests_stats_s tests_stats;
|
||||
#endif
|
||||
@@ -119,7 +140,8 @@ static void Sys_PrintUsage( const char *exename )
|
||||
|
||||
"\nCommon options:\n"
|
||||
O("-dev [level] ", "set log verbosity 0-2")
|
||||
O("-log ", "write log to \"engine.log\"")
|
||||
O("-log [file name] ", "write log to \"engine.log\" or [file name] if specified")
|
||||
O("-logtime ", "enable writing timestamps to the log file")
|
||||
O("-nowriteconfig ", "disable config save")
|
||||
O("-noch ", "disable crashhandler")
|
||||
#if XASH_WIN32 // !!!!
|
||||
@@ -180,7 +202,6 @@ 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
|
||||
@@ -362,9 +383,8 @@ static void Host_NewInstance( const char *name, const char *finalmsg )
|
||||
if( !pChangeGame ) return;
|
||||
|
||||
host.change_game = true;
|
||||
Q_strncpy( host.finalmsg, finalmsg, sizeof( host.finalmsg ));
|
||||
|
||||
if( !Sys_NewInstance( name ))
|
||||
if( !Sys_NewInstance( name, finalmsg ))
|
||||
pChangeGame( name ); // call from hl.exe
|
||||
}
|
||||
|
||||
@@ -678,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.001;
|
||||
const double sleeptime = sleep * 0.000001;
|
||||
|
||||
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 milliseconds
|
||||
// Platform_Sleep isn't guaranteed to sleep an exact amount of microseconds
|
||||
// so we measure the real sleep time and use it to decrease the window
|
||||
double t1 = Sys_DoubleTime(), t2;
|
||||
Platform_Sleep( sleep ); // in msec!
|
||||
Platform_NanoSleep( sleep * 1000 ); // in usec!
|
||||
t2 = Sys_DoubleTime();
|
||||
realsleeptime = t2 - t1;
|
||||
|
||||
@@ -838,7 +858,6 @@ void GAME_EXPORT Host_Error( const char *error, ... )
|
||||
recursive = true;
|
||||
Q_strncpy( hosterror2, hosterror1, sizeof( hosterror2 ));
|
||||
host.errorframe = host.framecount; // to avoid multply calls per frame
|
||||
Q_snprintf( host.finalmsg, sizeof( host.finalmsg ), "Server crashed: %s", hosterror1 );
|
||||
|
||||
// clearing cmd buffer to prevent execute any commands
|
||||
COM_InitHostState();
|
||||
@@ -1025,7 +1044,7 @@ static void Host_InitCommon( int argc, char **argv, const char *progname, qboole
|
||||
}
|
||||
|
||||
if( !Sys_CheckParm( "-noch" ))
|
||||
Sys_SetupCrashHandler();
|
||||
Sys_SetupCrashHandler( argv[0] );
|
||||
|
||||
#if XASH_DLL_LOADER
|
||||
host.enabledll = !Sys_CheckParm( "-nodll" );
|
||||
@@ -1112,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 );
|
||||
Platform_Init( Host_IsDedicated( ) || developer >= DEV_EXTENDED, basedir );
|
||||
FS_Init( basedir );
|
||||
|
||||
Sys_InitLog();
|
||||
@@ -1214,7 +1233,7 @@ int EXPORT Host_Main( int argc, char **argv, const char *progname, int bChangeGa
|
||||
|
||||
Cvar_Getf( "buildnum", FCVAR_READ_ONLY, "returns a current build number", "%i", Q_buildnum_compat());
|
||||
Cvar_Getf( "ver", FCVAR_READ_ONLY, "shows an engine version", "%i/%s (hw build %i)", PROTOCOL_VERSION, XASH_COMPAT_VERSION, Q_buildnum_compat());
|
||||
Cvar_Getf( "host_ver", FCVAR_READ_ONLY, "detailed info about this build", "%i " XASH_VERSION " %s %s %s", Q_buildnum(), Q_buildos(), Q_buildarch(), Q_buildcommit());
|
||||
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 );
|
||||
|
||||
Mod_Init();
|
||||
@@ -1237,7 +1256,6 @@ int EXPORT Host_Main( int argc, char **argv, const char *progname, int bChangeGa
|
||||
CL_Init();
|
||||
|
||||
HTTP_Init();
|
||||
ID_Init();
|
||||
SoundList_Init();
|
||||
|
||||
if( Host_IsDedicated( ))
|
||||
@@ -1293,6 +1311,7 @@ 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 );
|
||||
@@ -1321,6 +1340,11 @@ int EXPORT Host_Main( int argc, char **argv, const char *progname, int bChangeGa
|
||||
// check after all configs were executed
|
||||
HPAK_CheckIntegrity( hpk_custom_file.string );
|
||||
|
||||
#if XASH_ANDROID
|
||||
if( setjmp( return_from_main_buf ))
|
||||
return error_on_exit;
|
||||
#endif // XASH_ANDROID
|
||||
|
||||
// main window message loop
|
||||
while( !host.crashed )
|
||||
{
|
||||
@@ -1359,9 +1383,6 @@ void Host_ShutdownWithReason( const char *reason )
|
||||
if( host.status != HOST_ERR_FATAL )
|
||||
host.status = HOST_SHUTDOWN; // prepare host to normal shutdown
|
||||
|
||||
if( !host.change_game )
|
||||
Q_strncpy( host.finalmsg, "Server shutdown", sizeof( host.finalmsg ));
|
||||
|
||||
#if !XASH_DEDICATED
|
||||
if( host.type == HOST_NORMAL && !error )
|
||||
Host_WriteConfig();
|
||||
@@ -1379,10 +1400,14 @@ 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 );
|
||||
|
||||
// restore filter
|
||||
Sys_RestoreCrashHandler();
|
||||
Sys_CloseLog();
|
||||
Sys_CloseLog( reason );
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ static void HPAK_MaxSize_f( void )
|
||||
Con_Printf( S_ERROR "hpk_maxsize is deprecated, use hpk_max_size\n" );
|
||||
}
|
||||
|
||||
static const char *HPAK_TypeFromIndex( int type )
|
||||
const char *COM_ResourceTypeFromIndex( int type )
|
||||
{
|
||||
switch( type )
|
||||
{
|
||||
@@ -104,7 +104,7 @@ static void HPAK_CreatePak( const char *filename, resource_t *pResource, byte *p
|
||||
string pakname;
|
||||
byte md5[16];
|
||||
file_t *fout;
|
||||
MD5Context_t ctx;
|
||||
MD5Context_t ctx = { 0 };
|
||||
|
||||
if( !COM_CheckString( filename ))
|
||||
return;
|
||||
@@ -125,7 +125,6 @@ static void HPAK_CreatePak( const char *filename, resource_t *pResource, byte *p
|
||||
}
|
||||
|
||||
// let's hash it.
|
||||
memset( &ctx, 0, sizeof( MD5Context_t ));
|
||||
MD5Init( &ctx );
|
||||
|
||||
if( pData == NULL )
|
||||
@@ -214,7 +213,7 @@ void HPAK_AddLump( qboolean bUseQueue, const char *name, resource_t *pResource,
|
||||
file_t *file_src;
|
||||
file_t *file_dst;
|
||||
byte md5[16];
|
||||
MD5Context_t ctx;
|
||||
MD5Context_t ctx = { 0 };
|
||||
|
||||
if( pData == NULL && pFile == NULL )
|
||||
return;
|
||||
@@ -226,7 +225,6 @@ void HPAK_AddLump( qboolean bUseQueue, const char *name, resource_t *pResource,
|
||||
}
|
||||
|
||||
// hash it
|
||||
memset( &ctx, 0, sizeof( MD5Context_t ));
|
||||
MD5Init( &ctx );
|
||||
|
||||
if( !pData )
|
||||
@@ -463,7 +461,7 @@ static qboolean HPAK_Validate( const char *filename, qboolean quiet, qboolean de
|
||||
|
||||
if( !quiet )
|
||||
{
|
||||
Con_Printf( "%i: %s %s %s: ", i, HPAK_TypeFromIndex( pRes->type ),
|
||||
Con_Printf( "%i: %s %s %s: ", i, COM_ResourceTypeFromIndex( pRes->type ),
|
||||
Q_pretifymem( pRes->nDownloadSize, 2 ), pRes->szFileName );
|
||||
}
|
||||
|
||||
@@ -944,7 +942,7 @@ static void HPAK_List_f( void )
|
||||
{
|
||||
entry = &directory.entries[nCurrent];
|
||||
COM_FileBase( entry->resource.szFileName, lumpname, sizeof( lumpname ));
|
||||
type = HPAK_TypeFromIndex( entry->resource.type );
|
||||
type = COM_ResourceTypeFromIndex( entry->resource.type );
|
||||
size = Q_memprint( entry->resource.nDownloadSize );
|
||||
|
||||
Con_Printf( "%i: %10s %s %s\n : %s\n", nCurrent + 1, type, size, lumpname, MD5_Print( entry->resource.rgucMD5_hash ));
|
||||
@@ -1039,7 +1037,7 @@ static void HPAK_Extract_f( void )
|
||||
continue;
|
||||
|
||||
COM_FileBase( entry->resource.szFileName, lumpname, sizeof( lumpname ) );
|
||||
type = HPAK_TypeFromIndex( entry->resource.type );
|
||||
type = COM_ResourceTypeFromIndex( entry->resource.type );
|
||||
size = Q_memprint( entry->resource.nDownloadSize );
|
||||
|
||||
Con_Printf( "Extracting %i: %10s %s %s\n", nCurrent + 1, type, size, lumpname );
|
||||
|
||||
@@ -28,12 +28,20 @@ Image_LoadPAL
|
||||
qboolean Image_LoadPAL( const char *name, const byte *buffer, fs_offset_t filesize )
|
||||
{
|
||||
int rendermode = LUMP_NORMAL;
|
||||
byte pal[768];
|
||||
|
||||
if( filesize != 768 )
|
||||
if( filesize > sizeof( pal ))
|
||||
{
|
||||
Con_DPrintf( S_ERROR "%s: (%s) have invalid size (%li should be %d)\n", __func__, name, (long)filesize, 768 );
|
||||
Con_DPrintf( S_ERROR "%s: (%s) have invalid size (%li should be less or equal than %d)\n", __func__, name, (long)filesize, sizeof( pal ));
|
||||
return false;
|
||||
}
|
||||
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,14 +419,21 @@ void NET_InitMasters( void )
|
||||
|
||||
Cvar_RegisterVariable( &sv_verbose_heartbeats );
|
||||
|
||||
// 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
|
||||
{ // 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 );
|
||||
}
|
||||
|
||||
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
|
||||
{ // 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_LoadMasters( );
|
||||
}
|
||||
|
||||
@@ -385,6 +385,35 @@ static const mlumpinfo_t extlumps[EXTRA_LUMPS] =
|
||||
},
|
||||
};
|
||||
|
||||
#define BOX_CLIPNODES_INITIALIZER \
|
||||
{ \
|
||||
.planenum = 0, \
|
||||
.children = { CONTENTS_EMPTY, 1 }, \
|
||||
}, \
|
||||
{ \
|
||||
.planenum = 1, \
|
||||
.children = { 2, CONTENTS_EMPTY }, \
|
||||
}, \
|
||||
{ \
|
||||
.planenum = 2, \
|
||||
.children = { CONTENTS_EMPTY, 3 }, \
|
||||
}, \
|
||||
{ \
|
||||
.planenum = 3, \
|
||||
.children = { 4, CONTENTS_EMPTY }, \
|
||||
}, \
|
||||
{ \
|
||||
.planenum = 4, \
|
||||
.children = { CONTENTS_EMPTY, 5 }, \
|
||||
}, \
|
||||
{ \
|
||||
.planenum = 5, \
|
||||
.children = { CONTENTS_SOLID, CONTENTS_EMPTY }, \
|
||||
}, \
|
||||
|
||||
const mclipnode16_t box_clipnodes16[6] = { BOX_CLIPNODES_INITIALIZER };
|
||||
const mclipnode32_t box_clipnodes32[6] = { BOX_CLIPNODES_INITIALIZER };
|
||||
|
||||
/*
|
||||
===============================================================================
|
||||
|
||||
@@ -453,7 +482,7 @@ static int Mod_LoadTextureFromWadList( wadlist_t *list, const char *name, rgbdat
|
||||
return -1;
|
||||
}
|
||||
|
||||
static fs_offset_t Mod_CalculateMipTexSize( mip_t *mt, qboolean palette )
|
||||
static fs_offset_t Mod_CalculateMipTexSize( const mip_t *mt, qboolean palette )
|
||||
{
|
||||
if( !mt )
|
||||
return 0;
|
||||
@@ -856,7 +885,7 @@ Mod_PointInLeaf
|
||||
|
||||
==================
|
||||
*/
|
||||
mleaf_t *Mod_PointInLeaf( const vec3_t p, mnode_t *node )
|
||||
mleaf_t *Mod_PointInLeaf( const vec3_t p, mnode_t *node, model_t *mod )
|
||||
{
|
||||
Assert( node != NULL );
|
||||
|
||||
@@ -864,7 +893,7 @@ mleaf_t *Mod_PointInLeaf( const vec3_t p, mnode_t *node )
|
||||
{
|
||||
if( node->contents < 0 )
|
||||
return (mleaf_t *)node;
|
||||
node = node->children[PlaneDiff( p, node->plane ) <= 0];
|
||||
node = node_child( node, PlaneDiff( p, node->plane ) <= 0, mod );
|
||||
}
|
||||
|
||||
// never reached
|
||||
@@ -885,7 +914,7 @@ byte *Mod_GetPVSForPoint( const vec3_t p )
|
||||
|
||||
ASSERT( worldmodel != NULL );
|
||||
|
||||
leaf = Mod_PointInLeaf( p, worldmodel->nodes );
|
||||
leaf = Mod_PointInLeaf( p, worldmodel->nodes, worldmodel );
|
||||
|
||||
if( leaf && leaf->cluster >= 0 )
|
||||
return Mod_DecompressPVS( leaf->compressed_vis, world.visbytes );
|
||||
@@ -905,14 +934,14 @@ static void Mod_FatPVS_RecursiveBSPNode( const vec3_t org, float radius, byte *v
|
||||
float d = PlaneDiff( org, node->plane );
|
||||
|
||||
if( d > radius )
|
||||
node = node->children[0];
|
||||
node = node_child( node, 0, worldmodel );
|
||||
else if( d < -radius )
|
||||
node = node->children[1];
|
||||
node = node_child( node, 1, worldmodel );
|
||||
else
|
||||
{
|
||||
// go down both sides
|
||||
Mod_FatPVS_RecursiveBSPNode( org, radius, visbuffer, visbytes, node->children[0], phs );
|
||||
node = node->children[1];
|
||||
Mod_FatPVS_RecursiveBSPNode( org, radius, visbuffer, visbytes, node_child( node, 0, worldmodel ), phs );
|
||||
node = node_child( node, 1, worldmodel );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -950,7 +979,7 @@ int Mod_FatPVS( const vec3_t org, float radius, byte *visbuffer, int visbytes, q
|
||||
|
||||
ASSERT( worldmodel != NULL );
|
||||
|
||||
leaf = Mod_PointInLeaf( org, worldmodel->nodes );
|
||||
leaf = Mod_PointInLeaf( org, worldmodel->nodes, worldmodel );
|
||||
bytes = Q_min( bytes, visbytes );
|
||||
|
||||
// enable full visibility for some reasons
|
||||
@@ -1009,20 +1038,16 @@ static void Mod_BoxLeafnums_r( leaflist_t *ll, mnode_t *node )
|
||||
sides = BOX_ON_PLANE_SIDE( ll->mins, ll->maxs, node->plane );
|
||||
|
||||
if( sides == 1 )
|
||||
{
|
||||
node = node->children[0];
|
||||
}
|
||||
node = node_child( node, 0, worldmodel );
|
||||
else if( sides == 2 )
|
||||
{
|
||||
node = node->children[1];
|
||||
}
|
||||
node = node_child( node, 1, worldmodel );
|
||||
else
|
||||
{
|
||||
// go down both
|
||||
if( ll->topnode == -1 )
|
||||
ll->topnode = node - worldmodel->nodes;
|
||||
Mod_BoxLeafnums_r( ll, node->children[0] );
|
||||
node = node->children[1];
|
||||
Mod_BoxLeafnums_r( ll, node_child( node, 0, worldmodel ));
|
||||
node = node_child( node, 1, worldmodel );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1079,35 +1104,6 @@ qboolean Mod_BoxVisible( const vec3_t mins, const vec3_t maxs, const byte *visbi
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
Mod_HeadnodeVisible
|
||||
=============
|
||||
*/
|
||||
qboolean Mod_HeadnodeVisible( mnode_t *node, const byte *visbits, int *lastleaf )
|
||||
{
|
||||
if( !node || node->contents == CONTENTS_SOLID )
|
||||
return false;
|
||||
|
||||
if( node->contents < 0 )
|
||||
{
|
||||
if( !CHECKVISBIT( visbits, ((mleaf_t *)node)->cluster ))
|
||||
return false;
|
||||
|
||||
if( lastleaf )
|
||||
*lastleaf = ((mleaf_t *)node)->cluster;
|
||||
return true;
|
||||
}
|
||||
|
||||
if( Mod_HeadnodeVisible( node->children[0], visbits, lastleaf ))
|
||||
return true;
|
||||
|
||||
if( Mod_HeadnodeVisible( node->children[1], visbits, lastleaf ))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
Mod_FindModelOrigin
|
||||
@@ -1264,22 +1260,35 @@ Mod_GetFaceContents
|
||||
determine face contents by name
|
||||
==================
|
||||
*/
|
||||
static mvertex_t *Mod_GetVertexByNumber( model_t *mod, int surfedge )
|
||||
static mvertex_t *Mod_GetVertexByNumber( model_t *mod, int surfedge, const dbspmodel_t *bmod )
|
||||
{
|
||||
int lindex;
|
||||
medge_t *edge;
|
||||
int lindex = mod->surfedges[surfedge];
|
||||
|
||||
lindex = mod->surfedges[surfedge];
|
||||
|
||||
if( lindex > 0 )
|
||||
if( bmod->version == QBSP2_VERSION )
|
||||
{
|
||||
edge = &mod->edges[lindex];
|
||||
return &mod->vertexes[edge->v[0]];
|
||||
if( lindex > 0 )
|
||||
{
|
||||
medge32_t *edge = &mod->edges32[lindex];
|
||||
return &mod->vertexes[edge->v[0]];
|
||||
}
|
||||
else
|
||||
{
|
||||
medge32_t *edge = &mod->edges32[-lindex];
|
||||
return &mod->vertexes[edge->v[1]];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
edge = &mod->edges[-lindex];
|
||||
return &mod->vertexes[edge->v[1]];
|
||||
if( lindex > 0 )
|
||||
{
|
||||
medge16_t *edge = &mod->edges16[lindex];
|
||||
return &mod->vertexes[edge->v[0]];
|
||||
}
|
||||
else
|
||||
{
|
||||
medge16_t *edge = &mod->edges16[-lindex];
|
||||
return &mod->vertexes[edge->v[1]];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1364,7 +1373,7 @@ Mod_CalcSurfaceExtents
|
||||
Fills in surf->texturemins[] and surf->extents[]
|
||||
=================
|
||||
*/
|
||||
static void Mod_CalcSurfaceExtents( model_t *mod, msurface_t *surf )
|
||||
static void Mod_CalcSurfaceExtents( model_t *mod, msurface_t *surf, const dbspmodel_t *bmod )
|
||||
{
|
||||
// this place is VERY critical to precision
|
||||
// keep it as float, don't use double, because it causes issues with lightmap
|
||||
@@ -1391,8 +1400,16 @@ static void Mod_CalcSurfaceExtents( model_t *mod, msurface_t *surf )
|
||||
if( e >= mod->numedges || e <= -mod->numedges )
|
||||
Host_Error( "%s: bad edge\n", __func__ );
|
||||
|
||||
if( e >= 0 ) v = &mod->vertexes[mod->edges[e].v[0]];
|
||||
else v = &mod->vertexes[mod->edges[-e].v[1]];
|
||||
if( bmod->version == QBSP2_VERSION )
|
||||
{
|
||||
if( e >= 0 ) v = &mod->vertexes[mod->edges32[e].v[0]];
|
||||
else v = &mod->vertexes[mod->edges32[-e].v[1]];
|
||||
}
|
||||
else
|
||||
{
|
||||
if( e >= 0 ) v = &mod->vertexes[mod->edges16[e].v[0]];
|
||||
else v = &mod->vertexes[mod->edges16[-e].v[1]];
|
||||
}
|
||||
|
||||
for( j = 0; j < 2; j++ )
|
||||
{
|
||||
@@ -1446,7 +1463,7 @@ Mod_CalcSurfaceBounds
|
||||
fills in surf->mins and surf->maxs
|
||||
=================
|
||||
*/
|
||||
static void Mod_CalcSurfaceBounds( model_t *mod, msurface_t *surf )
|
||||
static void Mod_CalcSurfaceBounds( model_t *mod, msurface_t *surf, const dbspmodel_t *bmod )
|
||||
{
|
||||
int i, e;
|
||||
mvertex_t *v;
|
||||
@@ -1460,8 +1477,16 @@ static void Mod_CalcSurfaceBounds( model_t *mod, msurface_t *surf )
|
||||
if( e >= mod->numedges || e <= -mod->numedges )
|
||||
Host_Error( "%s: bad edge\n", __func__ );
|
||||
|
||||
if( e >= 0 ) v = &mod->vertexes[mod->edges[e].v[0]];
|
||||
else v = &mod->vertexes[mod->edges[-e].v[1]];
|
||||
if( bmod->version == QBSP2_VERSION )
|
||||
{
|
||||
if( e >= 0 ) v = &mod->vertexes[mod->edges32[e].v[0]];
|
||||
else v = &mod->vertexes[mod->edges32[-e].v[1]];
|
||||
}
|
||||
else
|
||||
{
|
||||
if( e >= 0 ) v = &mod->vertexes[mod->edges16[e].v[0]];
|
||||
else v = &mod->vertexes[mod->edges16[-e].v[1]];
|
||||
}
|
||||
AddPointToBounds( v->position, surf->info->mins, surf->info->maxs );
|
||||
}
|
||||
|
||||
@@ -1473,7 +1498,7 @@ static void Mod_CalcSurfaceBounds( model_t *mod, msurface_t *surf )
|
||||
Mod_CreateFaceBevels
|
||||
=================
|
||||
*/
|
||||
static void Mod_CreateFaceBevels( model_t *mod, msurface_t *surf )
|
||||
static void Mod_CreateFaceBevels( model_t *mod, msurface_t *surf, const dbspmodel_t *bmod )
|
||||
{
|
||||
vec3_t delta, edgevec;
|
||||
byte *facebevel;
|
||||
@@ -1506,8 +1531,8 @@ static void Mod_CreateFaceBevels( model_t *mod, msurface_t *surf )
|
||||
{
|
||||
mplane_t *dest = &fb->edges[i];
|
||||
|
||||
v0 = Mod_GetVertexByNumber( mod, surf->firstedge + i );
|
||||
v1 = Mod_GetVertexByNumber( mod, surf->firstedge + (i + 1) % surf->numedges );
|
||||
v0 = Mod_GetVertexByNumber( mod, surf->firstedge + i, bmod );
|
||||
v1 = Mod_GetVertexByNumber( mod, surf->firstedge + (i + 1) % surf->numedges, bmod );
|
||||
VectorSubtract( v1->position, v0->position, edgevec );
|
||||
CrossProduct( faceNormal, edgevec, dest->normal );
|
||||
VectorNormalize( dest->normal );
|
||||
@@ -1521,7 +1546,7 @@ static void Mod_CreateFaceBevels( model_t *mod, msurface_t *surf )
|
||||
// compute face radius
|
||||
for( i = 0; i < surf->numedges; i++ )
|
||||
{
|
||||
v0 = Mod_GetVertexByNumber( mod, surf->firstedge + i );
|
||||
v0 = Mod_GetVertexByNumber( mod, surf->firstedge + i, bmod );
|
||||
VectorSubtract( v0->position, fb->origin, delta );
|
||||
radius = DotProduct( delta, delta );
|
||||
fb->radius = Q_max( radius, fb->radius );
|
||||
@@ -1533,13 +1558,15 @@ static void Mod_CreateFaceBevels( model_t *mod, msurface_t *surf )
|
||||
Mod_SetParent
|
||||
=================
|
||||
*/
|
||||
static void Mod_SetParent( mnode_t *node, mnode_t *parent )
|
||||
static void Mod_SetParent( model_t *mod, mnode_t *node, mnode_t *parent )
|
||||
{
|
||||
node->parent = parent;
|
||||
|
||||
if( node->contents < 0 ) return; // it's leaf
|
||||
Mod_SetParent( node->children[0], node );
|
||||
Mod_SetParent( node->children[1], node );
|
||||
if( node->contents < 0 )
|
||||
return; // it's leaf
|
||||
|
||||
Mod_SetParent( mod, node_child( node, 0, mod ), node );
|
||||
Mod_SetParent( mod, node_child( node, 1, mod ), node );
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1547,7 +1574,7 @@ static void Mod_SetParent( mnode_t *node, mnode_t *parent )
|
||||
CountClipNodes_r
|
||||
==================
|
||||
*/
|
||||
static void CountClipNodes_r( mclipnode_t *src, hull_t *hull, int nodenum )
|
||||
static void CountClipNodes16_r( mclipnode16_t *src, hull_t *hull, int nodenum )
|
||||
{
|
||||
// leaf?
|
||||
if( nodenum < 0 ) return;
|
||||
@@ -1556,16 +1583,11 @@ static void CountClipNodes_r( mclipnode_t *src, hull_t *hull, int nodenum )
|
||||
Host_Error( "MAX_MAP_CLIPNODES limit exceeded\n" );
|
||||
hull->lastclipnode++;
|
||||
|
||||
CountClipNodes_r( src, hull, src[nodenum].children[0] );
|
||||
CountClipNodes_r( src, hull, src[nodenum].children[1] );
|
||||
CountClipNodes16_r( src, hull, src[nodenum].children[0] );
|
||||
CountClipNodes16_r( src, hull, src[nodenum].children[1] );
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
CountClipNodes32_r
|
||||
==================
|
||||
*/
|
||||
static void CountClipNodes32_r( dclipnode32_t *src, hull_t *hull, int nodenum )
|
||||
static void CountClipNodes32_r( mclipnode32_t *src, hull_t *hull, int nodenum )
|
||||
{
|
||||
// leaf?
|
||||
if( nodenum < 0 ) return;
|
||||
@@ -1578,15 +1600,27 @@ static void CountClipNodes32_r( dclipnode32_t *src, hull_t *hull, int nodenum )
|
||||
CountClipNodes32_r( src, hull, src[nodenum].children[1] );
|
||||
}
|
||||
|
||||
static void CountDClipNodes_r( dclipnode32_t *src, hull_t *hull, int nodenum )
|
||||
{
|
||||
// leaf?
|
||||
if( nodenum < 0 ) return;
|
||||
|
||||
if( hull->lastclipnode == MAX_MAP_CLIPNODES )
|
||||
Host_Error( "MAX_MAP_CLIPNODES limit exceeded\n" );
|
||||
hull->lastclipnode++;
|
||||
|
||||
CountDClipNodes_r( src, hull, src[nodenum].children[0] );
|
||||
CountDClipNodes_r( src, hull, src[nodenum].children[1] );
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
RemapClipNodes_r
|
||||
==================
|
||||
*/
|
||||
static int RemapClipNodes_r( dclipnode32_t *srcnodes, hull_t *hull, int nodenum )
|
||||
static int RemapClipNodes_r( dbspmodel_t *bmod, dclipnode32_t *srcnodes, hull_t *hull, int nodenum )
|
||||
{
|
||||
dclipnode32_t *src;
|
||||
mclipnode_t *out;
|
||||
dclipnode32_t *src;
|
||||
int i, c;
|
||||
|
||||
// leaf?
|
||||
@@ -1599,13 +1633,22 @@ static int RemapClipNodes_r( dclipnode32_t *srcnodes, hull_t *hull, int nodenum
|
||||
src = srcnodes + nodenum;
|
||||
|
||||
c = hull->lastclipnode;
|
||||
out = &hull->clipnodes[c];
|
||||
hull->lastclipnode++;
|
||||
|
||||
out->planenum = src->planenum;
|
||||
|
||||
for( i = 0; i < 2; i++ )
|
||||
out->children[i] = RemapClipNodes_r( srcnodes, hull, src->children[i] );
|
||||
if( bmod->version == QBSP2_VERSION )
|
||||
{
|
||||
mclipnode32_t *out = &hull->clipnodes32[c];
|
||||
out->planenum = src->planenum;
|
||||
for( i = 0; i < 2; i++ )
|
||||
out->children[i] = RemapClipNodes_r( bmod, srcnodes, hull, src->children[i] );
|
||||
}
|
||||
else
|
||||
{
|
||||
mclipnode16_t *out = &hull->clipnodes16[c];
|
||||
out->planenum = src->planenum;
|
||||
for( i = 0; i < 2; i++ )
|
||||
out->children[i] = RemapClipNodes_r( bmod, srcnodes, hull, src->children[i] );
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
@@ -1617,34 +1660,64 @@ Mod_MakeHull0
|
||||
Duplicate the drawing hull structure as a clipping hull
|
||||
=================
|
||||
*/
|
||||
static void Mod_MakeHull0( model_t *mod )
|
||||
static void Mod_MakeHull0( model_t *mod, const dbspmodel_t *bmod )
|
||||
{
|
||||
mnode_t *in, *child;
|
||||
mclipnode_t *out;
|
||||
hull_t *hull;
|
||||
int i, j;
|
||||
|
||||
hull = &mod->hulls[0];
|
||||
hull->clipnodes = out = Mem_Malloc( mod->mempool, mod->numnodes * sizeof( *out ));
|
||||
in = mod->nodes;
|
||||
hull_t *hull = &mod->hulls[0];
|
||||
int i;
|
||||
|
||||
hull->firstclipnode = 0;
|
||||
hull->lastclipnode = mod->numnodes - 1;
|
||||
hull->planes = mod->planes;
|
||||
|
||||
for( i = 0; i < mod->numnodes; i++, out++, in++ )
|
||||
if( bmod->version == QBSP2_VERSION )
|
||||
{
|
||||
out->planenum = in->plane - mod->planes;
|
||||
mclipnode32_t *out;
|
||||
mnode_t *in = mod->nodes;
|
||||
|
||||
for( j = 0; j < 2; j++ )
|
||||
hull->clipnodes32 = out = Mem_Malloc( mod->mempool, mod->numnodes * sizeof( *hull->clipnodes32 ));
|
||||
|
||||
for( i = 0; i < mod->numnodes; i++, out++, in++ )
|
||||
{
|
||||
child = in->children[j];
|
||||
int j;
|
||||
|
||||
if( child->contents < 0 )
|
||||
out->children[j] = child->contents;
|
||||
else out->children[j] = child - mod->nodes;
|
||||
out->planenum = in->plane - mod->planes;
|
||||
|
||||
for( j = 0; j < 2; j++ )
|
||||
{
|
||||
mnode_t *child = node_child( in, j, mod );
|
||||
|
||||
if( child->contents < 0 )
|
||||
out->children[j] = child->contents;
|
||||
else
|
||||
out->children[j] = child - mod->nodes;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mclipnode16_t *out;
|
||||
mnode_t *in = mod->nodes;
|
||||
|
||||
hull->clipnodes16 = out = Mem_Malloc( mod->mempool, mod->numnodes * sizeof( *hull->clipnodes16 ));
|
||||
|
||||
for( i = 0; i < mod->numnodes; i++, out++, in++ )
|
||||
{
|
||||
int j;
|
||||
|
||||
out->planenum = in->plane - mod->planes;
|
||||
|
||||
for( j = 0; j < 2; j++ )
|
||||
{
|
||||
mnode_t *child = node_child( in, j, mod );
|
||||
|
||||
if( child->contents < 0 )
|
||||
out->children[j] = child->contents;
|
||||
else
|
||||
out->children[j] = child - mod->nodes;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1688,15 +1761,18 @@ static void Mod_SetupHull( dbspmodel_t *bmod, model_t *mod, poolhandle_t mempool
|
||||
if( VectorIsNull( hull->clip_mins ) && VectorIsNull( hull->clip_maxs ))
|
||||
return; // no hull specified
|
||||
|
||||
CountClipNodes32_r( bmod->clipnodes_out, hull, headnode );
|
||||
CountDClipNodes_r( bmod->clipnodes_out, hull, headnode );
|
||||
|
||||
// fit array to real count
|
||||
hull->clipnodes = (mclipnode_t *)Mem_Malloc( mempool, sizeof( mclipnode_t ) * hull->lastclipnode );
|
||||
if( bmod->version == QBSP2_VERSION )
|
||||
hull->clipnodes32 = Mem_Malloc( mempool, sizeof( *hull->clipnodes32 ) * hull->lastclipnode );
|
||||
else
|
||||
hull->clipnodes16 = Mem_Malloc( mempool, sizeof( *hull->clipnodes16 ) * hull->lastclipnode );
|
||||
|
||||
hull->planes = mod->planes; // share planes
|
||||
hull->lastclipnode = 0; // restart counting
|
||||
|
||||
// remap clipnodes to 16-bit indexes
|
||||
RemapClipNodes_r( bmod->clipnodes_out, hull, headnode );
|
||||
RemapClipNodes_r( bmod, bmod->clipnodes_out, hull, headnode ); // remap clipnodes to 16-bit indexes
|
||||
}
|
||||
|
||||
static qboolean Mod_LoadLitfile( model_t *mod, const char *ext, size_t expected_size, color24 **out, size_t *outsize )
|
||||
@@ -1704,7 +1780,8 @@ static qboolean Mod_LoadLitfile( model_t *mod, const char *ext, size_t expected_
|
||||
char modelname[64], path[64];
|
||||
int iCompare;
|
||||
fs_offset_t datasize;
|
||||
byte *in;
|
||||
file_t *f;
|
||||
uint hdr[2];
|
||||
|
||||
COM_FileBase( mod->name, modelname, sizeof( modelname ));
|
||||
Q_snprintf( path, sizeof( path ), "maps/%s.%s", modelname, ext );
|
||||
@@ -1715,31 +1792,15 @@ static qboolean Mod_LoadLitfile( model_t *mod, const char *ext, size_t expected_
|
||||
if( iCompare < 0 ) // this may happens if level-designer used -onlyents key for hlcsg
|
||||
Con_Printf( S_WARN "%s probably is out of date\n", path );
|
||||
|
||||
in = FS_LoadFile( path, &datasize, false );
|
||||
f = FS_Open( path, "rb", false );
|
||||
|
||||
if( !in )
|
||||
if( !f )
|
||||
{
|
||||
Con_Printf( S_ERROR "couldn't load %s\n", path );
|
||||
return false;
|
||||
}
|
||||
|
||||
if( datasize <= 8 ) // header + version
|
||||
{
|
||||
Con_Printf( S_ERROR "%s is too short\n", path );
|
||||
goto cleanup_and_error;
|
||||
}
|
||||
|
||||
if( LittleLong( ((uint *)in)[0] ) != IDDELUXEMAPHEADER )
|
||||
{
|
||||
Con_Printf( S_ERROR "%s is corrupted\n", path );
|
||||
goto cleanup_and_error;
|
||||
}
|
||||
|
||||
if( LittleLong( ((uint *)in)[1] ) != DELUXEMAP_VERSION )
|
||||
{
|
||||
Con_Printf( S_ERROR "has %s mismatched version (%u should be %u)\n", path, LittleLong( ((uint *)in)[1] ), DELUXEMAP_VERSION );
|
||||
goto cleanup_and_error;
|
||||
}
|
||||
datasize = FS_FileLength( f );
|
||||
|
||||
// skip header bytes
|
||||
datasize -= 8;
|
||||
@@ -1750,14 +1811,33 @@ static qboolean Mod_LoadLitfile( model_t *mod, const char *ext, size_t expected_
|
||||
goto cleanup_and_error;
|
||||
}
|
||||
|
||||
if( FS_Read( f, hdr, sizeof( hdr )) != sizeof( hdr ))
|
||||
{
|
||||
Con_Printf( S_ERROR "failed reading header from %s\n", path );
|
||||
goto cleanup_and_error;
|
||||
}
|
||||
|
||||
if( LittleLong( hdr[0] ) != IDDELUXEMAPHEADER )
|
||||
{
|
||||
Con_Printf( S_ERROR "%s is corrupted\n", path );
|
||||
goto cleanup_and_error;
|
||||
}
|
||||
|
||||
if( LittleLong( hdr[1] ) != DELUXEMAP_VERSION )
|
||||
{
|
||||
Con_Printf( S_ERROR "has %s mismatched version (%u should be %u)\n", path, LittleLong( hdr[1] ), DELUXEMAP_VERSION );
|
||||
goto cleanup_and_error;
|
||||
}
|
||||
|
||||
*out = Mem_Malloc( mod->mempool, datasize );
|
||||
memcpy( *out, in + 8, datasize );
|
||||
*outsize = datasize;
|
||||
Mem_Free( in );
|
||||
|
||||
FS_Read( f, *out, datasize );
|
||||
FS_Close( f );
|
||||
return true;
|
||||
|
||||
cleanup_and_error:
|
||||
Mem_Free( in );
|
||||
FS_Close( f );
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1772,6 +1852,7 @@ for embedded submodels
|
||||
static void Mod_SetupSubmodels( model_t *mod, dbspmodel_t *bmod )
|
||||
{
|
||||
qboolean colored = false;
|
||||
qboolean qbsp2 = false;
|
||||
poolhandle_t mempool;
|
||||
char *ents;
|
||||
dmodel_t *bm;
|
||||
@@ -1783,6 +1864,9 @@ static void Mod_SetupSubmodels( model_t *mod, dbspmodel_t *bmod )
|
||||
if( FBitSet( mod->flags, MODEL_COLORED_LIGHTING ))
|
||||
colored = true;
|
||||
|
||||
if( FBitSet( mod->flags, MODEL_QBSP2 ))
|
||||
qbsp2 = true;
|
||||
|
||||
mod->numframes = 2; // regular and alternate animation
|
||||
|
||||
// set up the submodels
|
||||
@@ -1795,7 +1879,10 @@ static void Mod_SetupSubmodels( model_t *mod, dbspmodel_t *bmod )
|
||||
mod->hulls[0].lastclipnode = bm->headnode[0]; // need to be real count
|
||||
|
||||
// counting a real number of clipnodes per each submodel
|
||||
CountClipNodes_r( mod->hulls[0].clipnodes, &mod->hulls[0], bm->headnode[0] );
|
||||
if( bmod->version == QBSP2_VERSION )
|
||||
CountClipNodes32_r( mod->hulls[0].clipnodes32, &mod->hulls[0], bm->headnode[0] );
|
||||
else
|
||||
CountClipNodes16_r( mod->hulls[0].clipnodes16, &mod->hulls[0], bm->headnode[0] );
|
||||
|
||||
// but hulls1-3 is build individually for a each given submodel
|
||||
for( j = 1; j < MAX_MAP_HULLS; j++ )
|
||||
@@ -1813,6 +1900,7 @@ static void Mod_SetupSubmodels( model_t *mod, dbspmodel_t *bmod )
|
||||
|
||||
// this bit will be shared between all the submodels include worldmodel
|
||||
if( colored ) SetBits( mod->flags, MODEL_COLORED_LIGHTING );
|
||||
if( qbsp2 ) SetBits( mod->flags, MODEL_QBSP2 );
|
||||
|
||||
if( i != 0 )
|
||||
{
|
||||
@@ -2135,15 +2223,15 @@ Mod_LoadEdges
|
||||
*/
|
||||
static void Mod_LoadEdges( model_t *mod, dbspmodel_t *bmod )
|
||||
{
|
||||
medge_t *out;
|
||||
int i;
|
||||
|
||||
mod->edges = out = Mem_Malloc( mod->mempool, bmod->numedges * sizeof( medge_t ));
|
||||
mod->numedges = bmod->numedges;
|
||||
|
||||
if( bmod->version == QBSP2_VERSION )
|
||||
{
|
||||
dedge32_t *in = (dedge32_t *)bmod->edges32;
|
||||
dedge32_t *in = bmod->edges32;
|
||||
medge32_t *out;
|
||||
mod->edges32 = out = Mem_Malloc( mod->mempool, bmod->numedges * sizeof( *out ));
|
||||
|
||||
for( i = 0; i < bmod->numedges; i++, in++, out++ )
|
||||
{
|
||||
@@ -2153,7 +2241,9 @@ static void Mod_LoadEdges( model_t *mod, dbspmodel_t *bmod )
|
||||
}
|
||||
else
|
||||
{
|
||||
dedge_t *in = (dedge_t *)bmod->edges;
|
||||
dedge_t *in = bmod->edges;
|
||||
medge16_t *out;
|
||||
mod->edges16 = out = Mem_Malloc( mod->mempool, bmod->numedges * sizeof( *out ));
|
||||
|
||||
for( i = 0; i < bmod->numedges; i++, in++, out++ )
|
||||
{
|
||||
@@ -2269,7 +2359,7 @@ static qboolean Mod_SearchForTextureReplacement( char *out, size_t size, const c
|
||||
return false;
|
||||
}
|
||||
|
||||
static void Mod_InitSkyClouds( model_t *mod, mip_t *mt, texture_t *tx, qboolean custom_palette )
|
||||
static void Mod_InitSkyClouds( model_t *mod, const mip_t *mt, texture_t *tx, qboolean custom_palette )
|
||||
{
|
||||
#if !XASH_DEDICATED
|
||||
rgbdata_t r_temp, *r_sky;
|
||||
@@ -2426,9 +2516,6 @@ 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
|
||||
@@ -2436,12 +2523,10 @@ static void Mod_LoadTextureData( model_t *mod, dbspmodel_t *bmod, int textureInd
|
||||
|
||||
// don't load texture data on dedicated server, as there is no renderer.
|
||||
// but count the wadusage for automatic precache
|
||||
//
|
||||
// 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 );
|
||||
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 );
|
||||
|
||||
// check for multi-layered sky texture (quake1 specific)
|
||||
if( bmod->isworld && Q_strncmp( mipTex->name, "sky", 3 ) == 0 && ( mipTex->width / mipTex->height ) == 2 )
|
||||
@@ -2450,11 +2535,13 @@ 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( Mod_LooksLikeWaterTexture( mipTex->name ))
|
||||
if( iswater )
|
||||
SetBits( txFlags, TF_KEEP_SOURCE | TF_EXPAND_SOURCE );
|
||||
|
||||
// Texture loading order:
|
||||
@@ -2519,8 +2606,13 @@ static void Mod_LoadTextureData( model_t *mod, dbspmodel_t *bmod, int textureInd
|
||||
texture->gl_texturenum = R_GetBuiltinTexture( REF_DEFAULT_TEXTURE );
|
||||
}
|
||||
|
||||
// Check for luma 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;
|
||||
|
||||
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" ))
|
||||
@@ -2913,9 +3005,9 @@ static void Mod_LoadSurfaces( model_t *mod, dbspmodel_t *bmod )
|
||||
if( FBitSet( out->texinfo->flags, TEX_SPECIAL ))
|
||||
SetBits( out->flags, SURF_DRAWTILED );
|
||||
|
||||
Mod_CalcSurfaceBounds( mod, out );
|
||||
Mod_CalcSurfaceExtents( mod, out );
|
||||
Mod_CreateFaceBevels( mod, out );
|
||||
Mod_CalcSurfaceBounds( mod, out, bmod );
|
||||
Mod_CalcSurfaceExtents( mod, out, bmod );
|
||||
Mod_CreateFaceBevels( mod, out, bmod );
|
||||
|
||||
// grab the second sample to detect colored lighting
|
||||
if( test_lightsize > 0 && lightofs != -1 )
|
||||
@@ -2962,7 +3054,6 @@ static void Mod_LoadSurfaces( model_t *mod, dbspmodel_t *bmod )
|
||||
if( samples == 1 || samples == 3 )
|
||||
{
|
||||
bmod->lightmap_samples = (int)samples;
|
||||
Con_Reportf( "lighting: %s\n", (bmod->lightmap_samples == 1) ? "monochrome" : "colored" );
|
||||
bmod->lightmap_samples = Q_max( bmod->lightmap_samples, 1 ); // avoid division by zero
|
||||
}
|
||||
else Con_DPrintf( S_WARN "lighting invalid samplecount: %g, defaulting to %i\n", samples, bmod->lightmap_samples );
|
||||
@@ -2994,16 +3085,62 @@ static void Mod_LoadNodes( model_t *mod, dbspmodel_t *bmod )
|
||||
out->minmaxs[j+3] = in->maxs[j];
|
||||
}
|
||||
|
||||
#if !XASH_64BIT
|
||||
if( in->firstface >= BIT( 24 ))
|
||||
{
|
||||
Host_Error( "%s: face index limit exceeded on node %i\n", __func__, i );
|
||||
return;
|
||||
}
|
||||
|
||||
if( in->numfaces >= BIT( 24 ))
|
||||
{
|
||||
Host_Error( "%s: face count limit exceeded on node %i\n", __func__, i );
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
p = in->planenum;
|
||||
out->plane = mod->planes + p;
|
||||
out->firstsurface = in->firstface;
|
||||
out->numsurfaces = in->numfaces;
|
||||
out->firstsurface_0 = in->firstface & 0xFFFF;
|
||||
out->numsurfaces_0 = in->numfaces & 0xFFFF;
|
||||
|
||||
out->firstsurface_1 = in->firstface >> 16;
|
||||
out->numsurfaces_1 = in->numfaces >> 16;
|
||||
|
||||
for( j = 0; j < 2; j++ )
|
||||
{
|
||||
p = in->children[j];
|
||||
if( p >= 0 ) out->children[j] = mod->nodes + p;
|
||||
else out->children[j] = (mnode_t *)(mod->leafs + ( -1 - p ));
|
||||
#if XASH_64BIT
|
||||
if( p >= 0 ) out->children_[j] = mod->nodes + p;
|
||||
else out->children_[j] = (mnode_t *)(mod->leafs + ( -1 - p ));
|
||||
#else
|
||||
if( j == 0 )
|
||||
{
|
||||
if( p >= 0 )
|
||||
{
|
||||
out->child_0_leaf = 0;
|
||||
out->child_0_off = p;
|
||||
}
|
||||
else
|
||||
{
|
||||
out->child_0_leaf = 1;
|
||||
out->child_0_off = -1 - p;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if( p >= 0 )
|
||||
{
|
||||
out->child_1_leaf = 0;
|
||||
out->child_1_off = p;
|
||||
}
|
||||
else
|
||||
{
|
||||
out->child_1_leaf = 1;
|
||||
out->child_1_off = -1 - p;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -3018,20 +3155,20 @@ static void Mod_LoadNodes( model_t *mod, dbspmodel_t *bmod )
|
||||
|
||||
p = in->planenum;
|
||||
out->plane = mod->planes + p;
|
||||
out->firstsurface = in->firstface;
|
||||
out->numsurfaces = in->numfaces;
|
||||
out->firstsurface_0 = in->firstface;
|
||||
out->numsurfaces_0 = in->numfaces;
|
||||
|
||||
for( j = 0; j < 2; j++ )
|
||||
{
|
||||
p = in->children[j];
|
||||
if( p >= 0 ) out->children[j] = mod->nodes + p;
|
||||
else out->children[j] = (mnode_t *)(mod->leafs + ( -1 - p ));
|
||||
if( p >= 0 ) out->children_[j] = mod->nodes + p;
|
||||
else out->children_[j] = (mnode_t *)(mod->leafs + ( -1 - p ));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// sets nodes and leafs
|
||||
Mod_SetParent( mod->nodes, NULL );
|
||||
Mod_SetParent( mod, mod->nodes, NULL );
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -3413,6 +3550,8 @@ static void Mod_LoadLighting( model_t *mod, dbspmodel_t *bmod )
|
||||
break;
|
||||
}
|
||||
|
||||
Con_Reportf( "lighting: %s\n", FBitSet( mod->flags, MODEL_COLORED_LIGHTING ) ? "colored" : "monochrome" );
|
||||
|
||||
// not supposed to be load ?
|
||||
if( FBitSet( host.features, ENGINE_LOAD_DELUXEDATA ))
|
||||
{
|
||||
@@ -3491,13 +3630,6 @@ static qboolean Mod_LoadBmodelLumps( model_t *mod, const byte *mod_base, qboolea
|
||||
Q_strncpy( loadstat.name, mod->name, sizeof( loadstat.name ));
|
||||
wadvalue[0] = '\0';
|
||||
|
||||
#ifndef SUPPORT_BSP2_FORMAT
|
||||
if( header->version == QBSP2_VERSION )
|
||||
{
|
||||
Con_Printf( S_ERROR DEFAULT_BSP_BUILD_ERROR, mod->name );
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
switch( header->version )
|
||||
{
|
||||
case HLBSP_VERSION:
|
||||
@@ -3520,6 +3652,9 @@ static qboolean Mod_LoadBmodelLumps( model_t *mod, const byte *mod_base, qboolea
|
||||
// everything else
|
||||
srclumps[0].lumpnumber = LUMP_ENTITIES;
|
||||
srclumps[1].lumpnumber = LUMP_PLANES;
|
||||
|
||||
if( header->version == QBSP2_VERSION )
|
||||
SetBits( mod->flags, MODEL_QBSP2 );
|
||||
break;
|
||||
default:
|
||||
Con_Printf( S_ERROR "%s has wrong version number (%i should be %i)\n", mod->name, header->version, HLBSP_VERSION );
|
||||
@@ -3570,7 +3705,7 @@ static qboolean Mod_LoadBmodelLumps( model_t *mod, const byte *mod_base, qboolea
|
||||
Mod_LoadClipnodes( mod, bmod );
|
||||
|
||||
// preform some post-initalization
|
||||
Mod_MakeHull0( mod );
|
||||
Mod_MakeHull0( mod, bmod );
|
||||
Mod_SetupSubmodels( mod, bmod );
|
||||
|
||||
if( isworld )
|
||||
@@ -3660,15 +3795,6 @@ qboolean Mod_TestBmodelLumps( file_t *f, const char *name, const byte *mod_base,
|
||||
if( silent )
|
||||
SetBits( flags, LUMP_SILENT );
|
||||
|
||||
#ifndef SUPPORT_BSP2_FORMAT
|
||||
if( header->version == QBSP2_VERSION )
|
||||
{
|
||||
if( !FBitSet( flags, LUMP_SILENT ))
|
||||
Con_Printf( S_ERROR DEFAULT_BSP_BUILD_ERROR, name );
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
switch( header->version )
|
||||
{
|
||||
case HLBSP_VERSION:
|
||||
|
||||
@@ -135,6 +135,8 @@ extern poolhandle_t com_studiocache;
|
||||
extern convar_t mod_studiocache;
|
||||
extern convar_t r_wadtextures;
|
||||
extern convar_t r_showhull;
|
||||
extern const mclipnode16_t box_clipnodes16[6];
|
||||
extern const mclipnode32_t box_clipnodes32[6];
|
||||
|
||||
//
|
||||
// model.c
|
||||
@@ -167,13 +169,12 @@ void Mod_LoadAliasModel( model_t *mod, const void *buffer, qboolean *loaded );
|
||||
//
|
||||
void Mod_LoadBrushModel( model_t *mod, const void *buffer, qboolean *loaded );
|
||||
qboolean Mod_TestBmodelLumps( file_t *f, const char *name, const byte *mod_base, qboolean silent, dlump_t *entities );
|
||||
qboolean Mod_HeadnodeVisible( mnode_t *node, const byte *visbits, int *lastleaf );
|
||||
int Mod_FatPVS( const vec3_t org, float radius, byte *visbuffer, int visbytes, qboolean merge, qboolean fullvis, qboolean false );
|
||||
qboolean Mod_BoxVisible( const vec3_t mins, const vec3_t maxs, const byte *visbits );
|
||||
int Mod_CheckLump( const char *filename, const int lump, int *lumpsize );
|
||||
int Mod_ReadLump( const char *filename, const int lump, void **lumpdata, int *lumpsize );
|
||||
int Mod_SaveLump( const char *filename, const int lump, void *lumpdata, int lumpsize );
|
||||
mleaf_t *Mod_PointInLeaf( const vec3_t p, mnode_t *node );
|
||||
mleaf_t *Mod_PointInLeaf( const vec3_t p, mnode_t *node, model_t *mod );
|
||||
int Mod_SampleSizeForFace( const msurface_t *surf );
|
||||
byte *Mod_GetPVSForPoint( const vec3_t p );
|
||||
void Mod_UnloadBrushModel( model_t *mod );
|
||||
|
||||
@@ -50,9 +50,8 @@ static matrix3x4 studio_bones[MAXSTUDIOBONES];
|
||||
static uint studio_hull_hitgroup[MAXSTUDIOBONES];
|
||||
static uint cache_hull_hitgroup[MAXSTUDIOBONES];
|
||||
static mstudiocache_t cache_studio[STUDIO_CACHESIZE];
|
||||
static mclipnode_t studio_clipnodes[6];
|
||||
static mplane_t studio_planes[768];
|
||||
static mplane_t cache_planes[768];
|
||||
static mplane_t studio_planes[MAXSTUDIOBONES * 6];
|
||||
static mplane_t cache_planes[MAXSTUDIOBONES * 6];
|
||||
|
||||
// current cache state
|
||||
static int cache_current;
|
||||
@@ -66,25 +65,14 @@ Mod_InitStudioHull
|
||||
*/
|
||||
void Mod_InitStudioHull( void )
|
||||
{
|
||||
int i, side;
|
||||
int i;
|
||||
|
||||
if( studio_hull[0].planes != NULL )
|
||||
return; // already initailized
|
||||
|
||||
for( i = 0; i < 6; i++ )
|
||||
{
|
||||
studio_clipnodes[i].planenum = i;
|
||||
|
||||
side = i & 1;
|
||||
|
||||
studio_clipnodes[i].children[side] = CONTENTS_EMPTY;
|
||||
if( i != 5 ) studio_clipnodes[i].children[side^1] = i + 1;
|
||||
else studio_clipnodes[i].children[side^1] = CONTENTS_SOLID;
|
||||
}
|
||||
|
||||
for( i = 0; i < MAXSTUDIOBONES; i++ )
|
||||
{
|
||||
studio_hull[i].clipnodes = studio_clipnodes;
|
||||
studio_hull[i].clipnodes16 = (mclipnode16_t *)box_clipnodes16;
|
||||
studio_hull[i].planes = &studio_planes[i*6];
|
||||
studio_hull[i].firstclipnode = 0;
|
||||
studio_hull[i].lastclipnode = 5;
|
||||
@@ -270,6 +258,11 @@ hull_t *Mod_HullForStudio( model_t *model, float frame, int sequence, vec3_t ang
|
||||
|
||||
for( i = j = 0; i < mod_studiohdr->numhitboxes; i++, j += 6 )
|
||||
{
|
||||
if( world.version == QBSP2_VERSION )
|
||||
studio_hull[i].clipnodes32 = (mclipnode32_t *)box_clipnodes32;
|
||||
else
|
||||
studio_hull[i].clipnodes16 = (mclipnode16_t *)box_clipnodes16;
|
||||
|
||||
if( bSkipShield && i == 21 )
|
||||
continue; // CS stuff
|
||||
|
||||
@@ -389,8 +382,7 @@ static void Mod_StudioCalcRotations( int boneused[], int numbones, const byte *p
|
||||
for( j = numbones - 1; j >= 0; j-- )
|
||||
{
|
||||
i = boneused[j];
|
||||
R_StudioCalcBoneQuaternion( frame, s, &pbone[i], &panim[i], adj, q[i] );
|
||||
R_StudioCalcBonePosition( frame, s, &pbone[i], &panim[i], adj, pos[i] );
|
||||
R_StudioCalcBones( frame, s, &pbone[i], &panim[i], adj, pos[i], q[i] );
|
||||
}
|
||||
|
||||
if( pseqdesc->motiontype & STUDIO_X ) pos[pseqdesc->motionbone][0] = 0.0f;
|
||||
@@ -731,7 +723,7 @@ void Mod_StudioComputeBounds( void *buffer, vec3_t mins, vec3_t maxs, qboolean i
|
||||
{
|
||||
for( k = 0; k < pseqdesc->numframes; k++ )
|
||||
{
|
||||
R_StudioCalcBonePosition( k, 0, &pbones[j], panim, NULL, pos );
|
||||
R_StudioCalcBones( k, 0, &pbones[j], panim, NULL, pos, NULL );
|
||||
Mod_StudioBoundVertex( vert_mins, vert_maxs, &bone_count, pos );
|
||||
}
|
||||
}
|
||||
@@ -875,7 +867,7 @@ void Mod_LoadStudioModel( model_t *mod, const void *buffer, qboolean *loaded )
|
||||
mod->type = mod_studio;
|
||||
|
||||
phdr = R_StudioLoadHeader( mod, buffer );
|
||||
if( !phdr )
|
||||
if( !phdr || phdr->length < sizeof( studiohdr_t )) // garbage value in length
|
||||
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;
|
||||
qboolean loaded, loaded2 = false;
|
||||
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 )
|
||||
if( !buf || length < sizeof( uint ))
|
||||
{
|
||||
memset( mod, 0, sizeof( model_t ));
|
||||
|
||||
@@ -329,11 +329,12 @@ model_t *Mod_LoadModel( model_t *mod, qboolean crash )
|
||||
// let the server.dll load custom data
|
||||
svgame.physFuncs.Mod_ProcessUserData( mod, true, buf );
|
||||
}
|
||||
loaded2 = true;
|
||||
}
|
||||
#if !XASH_DEDICATED
|
||||
else
|
||||
{
|
||||
loaded = ref.dllFuncs.Mod_ProcessRenderData( mod, true, buf );
|
||||
loaded2 = ref.dllFuncs.Mod_ProcessRenderData( mod, true, buf );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -345,7 +346,7 @@ model_t *Mod_LoadModel( model_t *mod, qboolean crash )
|
||||
hdr->pposeverts = NULL;
|
||||
}
|
||||
|
||||
if( !loaded )
|
||||
if( !loaded || !loaded2 )
|
||||
{
|
||||
Mod_FreeModel( mod );
|
||||
Mem_Free( buf );
|
||||
@@ -610,3 +611,41 @@ 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,11 +18,177 @@ GNU General Public License for more details.
|
||||
#include "net_buffer.h"
|
||||
#include "xash3d_mathlib.h"
|
||||
|
||||
// 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];
|
||||
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,
|
||||
};
|
||||
|
||||
const char *const svc_strings[svc_lastmsg+1] =
|
||||
{
|
||||
"svc_bad",
|
||||
@@ -132,65 +298,41 @@ 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 )
|
||||
{
|
||||
Assert( numbits >= 0 && numbits <= 32 );
|
||||
int nBitsLeft = numbits;
|
||||
int iCurBit = sb->iCurBit;
|
||||
uint iDWord = iCurBit >> 5; // Mask in a dword.
|
||||
uint32_t iCurBitMasked;
|
||||
int nBitsWritten;
|
||||
|
||||
Assert( numbits >= 1 && numbits <= 32 );
|
||||
|
||||
// bounds checking..
|
||||
if(( sb->iCurBit + numbits ) > sb->nDataBits )
|
||||
if( MSG_Overflow( sb, numbits ))
|
||||
{
|
||||
sb->bOverflow = true;
|
||||
sb->iCurBit = sb->nDataBits;
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
int nBitsLeft = numbits;
|
||||
int iCurBit = sb->iCurBit;
|
||||
uint iDWord = iCurBit >> 5; // Mask in a dword.
|
||||
uint32_t iCurBitMasked;
|
||||
int nBitsWritten;
|
||||
|
||||
Assert(( iDWord * 4 + sizeof( int )) <= (uint)MSG_GetMaxBytes( sb ));
|
||||
iCurBitMasked = iCurBit & 31;
|
||||
((uint32_t *)sb->pData)[iDWord] &= BitWriteMasks[iCurBitMasked][nBitsLeft-1];
|
||||
((uint32_t *)sb->pData)[iDWord] |= curData << iCurBitMasked;
|
||||
|
||||
// did it span a dword?
|
||||
nBitsWritten = 32 - iCurBitMasked;
|
||||
|
||||
if( nBitsWritten < nBitsLeft )
|
||||
{
|
||||
nBitsLeft -= nBitsWritten;
|
||||
iCurBit += nBitsWritten;
|
||||
curData >>= nBitsWritten;
|
||||
|
||||
iCurBitMasked = iCurBit & 31;
|
||||
((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;
|
||||
((uint32_t *)sb->pData)[iDWord+1] &= BitWriteMasks[iCurBitMasked][nBitsLeft-1];
|
||||
((uint32_t *)sb->pData)[iDWord+1] |= curData << iCurBitMasked;
|
||||
}
|
||||
sb->iCurBit += numbits;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -238,7 +380,7 @@ qboolean MSG_WriteBits( sizebuf_t *sb, const void *pData, int nBits )
|
||||
int nBitsLeft = nBits;
|
||||
|
||||
// get output dword-aligned.
|
||||
while((( uint32_t )pOut & 3 ) != 0 && nBitsLeft >= 8 )
|
||||
while((( uintptr_t )pOut & 3 ) != 0 && nBitsLeft >= 8 )
|
||||
{
|
||||
MSG_WriteUBitLong( sb, *pOut, 8 );
|
||||
|
||||
@@ -275,16 +417,14 @@ qboolean MSG_WriteBits( sizebuf_t *sb, const void *pData, int nBits )
|
||||
|
||||
void MSG_WriteBitAngle( sizebuf_t *sb, float fAngle, int numbits )
|
||||
{
|
||||
uint mask, shift;
|
||||
const uint shift = ( 1 << numbits );
|
||||
const uint mask = shift - 1;
|
||||
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;
|
||||
|
||||
@@ -438,9 +578,8 @@ uint MSG_ReadUBitLong( sizebuf_t *sb, int numbits )
|
||||
return 0; // end of message
|
||||
}
|
||||
|
||||
if(( sb->iCurBit + numbits ) > sb->nDataBits )
|
||||
if( MSG_Overflow( sb, numbits ))
|
||||
{
|
||||
sb->bOverflow = true;
|
||||
sb->iCurBit = sb->nDataBits;
|
||||
return 0;
|
||||
}
|
||||
@@ -513,13 +652,9 @@ qboolean MSG_ReadBits( sizebuf_t *sb, void *pOutData, int nBits )
|
||||
|
||||
float MSG_ReadBitAngle( sizebuf_t *sb, int numbits )
|
||||
{
|
||||
float fReturn, shift;
|
||||
int i;
|
||||
|
||||
shift = (float)( 1 << numbits );
|
||||
|
||||
i = MSG_ReadUBitLong( sb, numbits );
|
||||
fReturn = (float)i * ( 360.0f / shift );
|
||||
float shift = (float)( 1 << numbits );
|
||||
int i = MSG_ReadUBitLong( sb, numbits );
|
||||
float fReturn = (float)i * ( 360.0f / shift );
|
||||
|
||||
// clamp the finale angle
|
||||
if( fReturn < -180.0f ) fReturn += 360.0f;
|
||||
@@ -531,11 +666,11 @@ float MSG_ReadBitAngle( sizebuf_t *sb, int numbits )
|
||||
// Append numbits least significant bits from data to the current bit stream
|
||||
int MSG_ReadSBitLong( sizebuf_t *sb, int numbits )
|
||||
{
|
||||
int r, sign;
|
||||
int r;
|
||||
|
||||
if( sb->iAlternateSign )
|
||||
{
|
||||
sign = MSG_ReadOneBit( sb );
|
||||
int sign = MSG_ReadOneBit( sb );
|
||||
r = MSG_ReadUBitLong( sb, numbits - 1 );
|
||||
|
||||
if( sign )
|
||||
@@ -544,9 +679,7 @@ int MSG_ReadSBitLong( sizebuf_t *sb, int numbits )
|
||||
else
|
||||
{
|
||||
r = MSG_ReadUBitLong( sb, numbits - 1 );
|
||||
sign = MSG_ReadOneBit( sb );
|
||||
|
||||
if( sign )
|
||||
if( MSG_ReadOneBit( sb ))
|
||||
r = -( BIT( numbits - 1 ) - r );
|
||||
}
|
||||
|
||||
@@ -667,12 +800,12 @@ qboolean MSG_ReadBytes( sizebuf_t *sb, void *pOut, int nBytes )
|
||||
static char *MSG_ReadStringExt( sizebuf_t *sb, qboolean bLine )
|
||||
{
|
||||
static char string[4096];
|
||||
int l = 0, c;
|
||||
int l = 0;
|
||||
|
||||
do
|
||||
{
|
||||
// use MSG_ReadByte so -1 is out of bounds
|
||||
c = MSG_ReadByte( sb );
|
||||
int c = MSG_ReadByte( sb );
|
||||
|
||||
if( c == 0 ) break;
|
||||
else if( bLine && c == '\n' )
|
||||
@@ -865,8 +998,6 @@ 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,7 +193,6 @@ 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,8 +272,6 @@ 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 )
|
||||
@@ -343,6 +341,7 @@ void Netchan_Setup( netsrc_t sock, netchan_t *chan, netadr_t adr, int qport, voi
|
||||
chan->split = FBitSet( flags, NETCHAN_USE_LEGACY_SPLIT ) ? true : false;
|
||||
chan->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 ));
|
||||
@@ -768,7 +767,7 @@ static void Netchan_CreateFragments_( netchan_t *chan, sizebuf_t *msg )
|
||||
Host_Error( "%s: BZ2 compression is not supported for server", __func__ );
|
||||
#endif
|
||||
}
|
||||
else if( !chan->use_bz2 && !LZSS_IsCompressed( MSG_GetData( msg ), MSG_GetMaxBytes( msg )))
|
||||
else if( chan->use_lzss && !LZSS_IsCompressed( MSG_GetData( msg ), MSG_GetMaxBytes( msg )))
|
||||
{
|
||||
uint uCompressedSize = 0;
|
||||
uint uSourceSize = MSG_GetNumBytesWritten( msg );
|
||||
@@ -1175,7 +1174,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];
|
||||
@@ -1196,7 +1195,7 @@ qboolean Netchan_CopyNormalFragments( netchan_t *chan, sizebuf_t *msg, size_t *l
|
||||
Host_Error( "%s: BZ2 compression is not supported for server\n", __func__ );
|
||||
#endif
|
||||
}
|
||||
else if( !chan->use_bz2 && LZSS_IsCompressed( MSG_GetData( msg ), size ))
|
||||
else if( chan->use_lzss && LZSS_IsCompressed( MSG_GetData( msg ), size ))
|
||||
{
|
||||
uint uDecompressedLen = LZSS_GetActualSize( MSG_GetData( msg ), size );
|
||||
byte buf[NET_MAX_MESSAGE];
|
||||
@@ -1347,7 +1346,7 @@ qboolean Netchan_CopyFileFragments( netchan_t *chan, sizebuf_t *msg )
|
||||
Host_Error( "%s: BZ2 compression is not supported for server", __func__ );
|
||||
#endif
|
||||
}
|
||||
else if( LZSS_IsCompressed( buffer, nsize + 1 ))
|
||||
else if( chan->use_lzss && LZSS_IsCompressed( buffer, nsize + 1 ))
|
||||
{
|
||||
byte *uncompressedBuffer;
|
||||
|
||||
|
||||
@@ -2282,10 +2282,6 @@ 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 );
|
||||
|
||||
@@ -326,7 +326,7 @@ static int HTTP_FileConnect( httpfile_t *file )
|
||||
if( !COM_CheckStringEmpty( http_useragent.string ) || !Q_strcmp( http_useragent.string, "xash3d" ))
|
||||
{
|
||||
Q_snprintf( useragent, sizeof( useragent ), "%s/%s (%s-%s; build %d; %s)",
|
||||
XASH_ENGINE_NAME, XASH_VERSION, Q_buildos( ), Q_buildarch( ), Q_buildnum( ), Q_buildcommit( ));
|
||||
XASH_ENGINE_NAME, XASH_VERSION, Q_buildos( ), Q_buildarch( ), Q_buildnum( ), g_buildcommit );
|
||||
}
|
||||
else Q_strncpy( useragent, http_useragent.string, sizeof( useragent ));
|
||||
|
||||
@@ -505,11 +505,14 @@ static int HTTP_FileDecompress( httpfile_t *file )
|
||||
|
||||
if( zlib_result == Z_OK || zlib_result == Z_STREAM_END )
|
||||
{
|
||||
Mem_Free( data_in );
|
||||
g_fsapi.WriteFile( name, data_out, decompressed_len );
|
||||
HTTP_FreeFile( file, false );
|
||||
}
|
||||
else HTTP_FreeFile( file, true );
|
||||
|
||||
Mem_Free( data_in );
|
||||
Mem_Free( data_out );
|
||||
|
||||
g_fsapi.WriteFile( name, data_out, decompressed_len );
|
||||
HTTP_FreeFile( file, false );
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -151,17 +151,24 @@ static inline qboolean NET_IsSocketValid( int socket )
|
||||
|
||||
void NET_NetadrToIP6Bytes( uint8_t *ip6, const netadr_t *adr )
|
||||
{
|
||||
memcpy( ip6, adr->ip6, sizeof( adr->ip6 ));
|
||||
memcpy( &ip6[0], adr->ip6_0, 2 );
|
||||
memcpy( &ip6[2], adr->ip6_1, 14 );
|
||||
}
|
||||
|
||||
void NET_IP6BytesToNetadr( netadr_t *adr, const uint8_t *ip6 )
|
||||
{
|
||||
memcpy( adr->ip6, ip6, sizeof( adr->ip6 ));
|
||||
memcpy( adr->ip6_0, &ip6[0], 2 );
|
||||
memcpy( adr->ip6_1, &ip6[2], 14 );
|
||||
}
|
||||
|
||||
static int NET_NetadrIP6Compare( const netadr_t *a, const netadr_t *b )
|
||||
{
|
||||
return memcmp( a->ip6, b->ip6, sizeof( a->ip6 ));
|
||||
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 ));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -171,27 +178,29 @@ 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( a->type == NA_BROADCAST )
|
||||
if( 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( a->type == NA_IP )
|
||||
else if( 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( a->type6 == NA_IP6 )
|
||||
else if( type == 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( a->type6 == NA_MULTICAST_IP6 )
|
||||
else if( type == NA_MULTICAST_IP6 )
|
||||
{
|
||||
s->ss_family = AF_INET6;
|
||||
((struct sockaddr_in6 *)s)->sin6_port = a->port;
|
||||
@@ -208,13 +217,13 @@ static void NET_SockadrToNetadr( const struct sockaddr_storage *s, netadr_t *a )
|
||||
{
|
||||
if( s->ss_family == AF_INET )
|
||||
{
|
||||
a->type = NA_IP;
|
||||
NET_NetadrSetType( a, 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 )
|
||||
{
|
||||
a->type6 = NA_IP6;
|
||||
NET_NetadrSetType( a, NA_IP6 );
|
||||
NET_IP6BytesToNetadr( a, ((struct sockaddr_in6 *)s)->sin6_addr.s6_addr );
|
||||
a->port = ((struct sockaddr_in6 *)s)->sin6_port;
|
||||
}
|
||||
@@ -549,8 +558,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;
|
||||
@@ -620,7 +629,7 @@ qboolean NET_StringToFilterAdr( const char *s, netadr_t *adr, uint *prefixlen )
|
||||
adr->ip4 = ntohl( mask );
|
||||
}
|
||||
|
||||
adr->type = NA_IP;
|
||||
NET_NetadrSetType( adr, NA_IP );
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -634,10 +643,11 @@ NET_AdrToString
|
||||
const char *NET_AdrToString( const netadr_t a )
|
||||
{
|
||||
static char s[64];
|
||||
netadrtype_t type = NET_NetadrType( &a );
|
||||
|
||||
if( a.type == NA_LOOPBACK )
|
||||
if( type == NA_LOOPBACK )
|
||||
return "loopback";
|
||||
if( a.type6 == NA_IP6 || a.type6 == NA_MULTICAST_IP6 )
|
||||
if( type == NA_IP6 || type == NA_MULTICAST_IP6 )
|
||||
{
|
||||
uint8_t ip6[16];
|
||||
|
||||
@@ -661,10 +671,11 @@ NET_BaseAdrToString
|
||||
const char *NET_BaseAdrToString( const netadr_t a )
|
||||
{
|
||||
static char s[64];
|
||||
netadrtype_t type = NET_NetadrType( &a );
|
||||
|
||||
if( a.type == NA_LOOPBACK )
|
||||
if( type == NA_LOOPBACK )
|
||||
return "loopback";
|
||||
if( a.type6 == NA_IP6 || a.type6 == NA_MULTICAST_IP6 )
|
||||
if( type == NA_IP6 || type == NA_MULTICAST_IP6 )
|
||||
{
|
||||
uint8_t ip6[16];
|
||||
|
||||
@@ -689,16 +700,19 @@ Compares without the port
|
||||
*/
|
||||
qboolean NET_CompareBaseAdr( const netadr_t a, const netadr_t b )
|
||||
{
|
||||
if( a.type6 != b.type6 )
|
||||
netadrtype_t type_a = NET_NetadrType( &a );
|
||||
netadrtype_t type_b = NET_NetadrType( &b );
|
||||
|
||||
if( type_a != type_b )
|
||||
return false;
|
||||
|
||||
if( a.type == NA_LOOPBACK )
|
||||
if( type_a == NA_LOOPBACK )
|
||||
return true;
|
||||
|
||||
if( a.type == NA_IP )
|
||||
if( type_a == NA_IP )
|
||||
return a.ip4 == b.ip4;
|
||||
|
||||
if( a.type6 == NA_IP6 )
|
||||
if( type_a == NA_IP6 )
|
||||
{
|
||||
if( !NET_NetadrIP6Compare( &a, &b ))
|
||||
return true;
|
||||
@@ -707,36 +721,6 @@ 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
|
||||
@@ -746,10 +730,13 @@ Checks if adr is a part of subnet
|
||||
*/
|
||||
qboolean NET_CompareAdrByMask( const netadr_t a, const netadr_t b, uint prefixlen )
|
||||
{
|
||||
if( a.type6 != b.type6 || a.type == NA_LOOPBACK )
|
||||
netadrtype_t type_a = NET_NetadrType( &a );
|
||||
netadrtype_t type_b = NET_NetadrType( &b );
|
||||
|
||||
if( type_a != type_b || type_a == NA_LOOPBACK )
|
||||
return false;
|
||||
|
||||
if( a.type == NA_IP )
|
||||
if( type_a == NA_IP )
|
||||
{
|
||||
uint32_t ipa = htonl( a.ip4 );
|
||||
uint32_t ipb = htonl( b.ip4 );
|
||||
@@ -757,7 +744,7 @@ qboolean NET_CompareAdrByMask( const netadr_t a, const netadr_t b, uint prefixle
|
||||
if(( ipa & (( 0xFFFFFFFFU ) << ( 32 - prefixlen ))) == ipb )
|
||||
return true;
|
||||
}
|
||||
else if( a.type6 == NA_IP6 )
|
||||
else if( type_a == NA_IP6 )
|
||||
{
|
||||
uint16_t a_[8], b_[8];
|
||||
size_t check = prefixlen / 16;
|
||||
@@ -798,11 +785,13 @@ Check for reserved ip's
|
||||
*/
|
||||
qboolean NET_IsReservedAdr( netadr_t a )
|
||||
{
|
||||
if( a.type == NA_LOOPBACK )
|
||||
netadrtype_t type_a = NET_NetadrType( &a );
|
||||
|
||||
if( type_a == NA_LOOPBACK )
|
||||
return true;
|
||||
|
||||
// Following checks was imported from GameNetworkingSockets library
|
||||
if( a.type == NA_IP )
|
||||
if( type_a == NA_IP )
|
||||
{
|
||||
if(( a.ip[0] == 10 ) || // 10.x.x.x is reserved
|
||||
( a.ip[0] == 127 ) || // 127.x.x.x
|
||||
@@ -814,7 +803,7 @@ qboolean NET_IsReservedAdr( netadr_t a )
|
||||
}
|
||||
}
|
||||
|
||||
if( a.type6 == NA_IP6 )
|
||||
if( type_a == NA_IP6 )
|
||||
{
|
||||
uint8_t ip6[16];
|
||||
|
||||
@@ -847,20 +836,23 @@ Compare full address
|
||||
*/
|
||||
qboolean NET_CompareAdr( const netadr_t a, const netadr_t b )
|
||||
{
|
||||
if( a.type6 != b.type6 )
|
||||
netadrtype_t type_a = NET_NetadrType( &a );
|
||||
netadrtype_t type_b = NET_NetadrType( &b );
|
||||
|
||||
if( type_a != type_b )
|
||||
return false;
|
||||
|
||||
if( a.type == NA_LOOPBACK )
|
||||
if( type_a == NA_LOOPBACK )
|
||||
return true;
|
||||
|
||||
if( a.type == NA_IP )
|
||||
if( type_a == NA_IP )
|
||||
{
|
||||
if( a.ip4 == b.ip4 && a.port == b.port )
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
if( a.type6 == NA_IP6 )
|
||||
if( type_a == NA_IP6 )
|
||||
{
|
||||
if( a.port == b.port && !NET_NetadrIP6Compare( &a, &b ))
|
||||
return true;
|
||||
@@ -883,9 +875,13 @@ 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;
|
||||
|
||||
if( a->type6 != b->type6 )
|
||||
return bound( -1, (int)a->type6 - (int)b->type6, 1 );
|
||||
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 );
|
||||
|
||||
porta = ntohs( a->port );
|
||||
portb = ntohs( b->port );
|
||||
@@ -896,7 +892,7 @@ int NET_CompareAdrSort( const void *_a, const void *_b )
|
||||
else
|
||||
portdiff = 0;
|
||||
|
||||
switch( a->type6 )
|
||||
switch( type_a )
|
||||
{
|
||||
case NA_IP6:
|
||||
if(( addrdiff = NET_NetadrIP6Compare( a, b )))
|
||||
@@ -904,14 +900,7 @@ 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;
|
||||
@@ -946,7 +935,7 @@ static qboolean NET_StringToAdrEx( const char *string, netadr_t *adr, int family
|
||||
|
||||
if( !Q_stricmp( string, "localhost" ) || !Q_stricmp( string, "loopback" ))
|
||||
{
|
||||
adr->type = NA_LOOPBACK;
|
||||
NET_NetadrSetType( adr, NA_LOOPBACK );
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -971,7 +960,7 @@ net_gai_state_t NET_StringToAdrNB( const char *string, netadr_t *adr, qboolean v
|
||||
|
||||
if( !Q_stricmp( string, "localhost" ) || !Q_stricmp( string, "loopback" ))
|
||||
{
|
||||
adr->type = NA_LOOPBACK;
|
||||
NET_NetadrSetType( adr, NA_LOOPBACK );
|
||||
return NET_EAI_OK;
|
||||
}
|
||||
|
||||
@@ -1017,7 +1006,7 @@ static qboolean NET_GetLoopPacket( netsrc_t sock, netadr_t *from, byte *data, si
|
||||
*length = loop->msgs[i].datalen;
|
||||
|
||||
memset( from, 0, sizeof( *from ));
|
||||
from->type = NA_LOOPBACK;
|
||||
NET_NetadrSetType( from, NA_LOOPBACK );
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -1523,7 +1512,7 @@ static int NET_SendLong( netsrc_t sock, int net_socket, const char *buf, size_t
|
||||
total_sent += size;
|
||||
len -= size;
|
||||
packet_number++;
|
||||
Platform_Sleep( 1 );
|
||||
Platform_NanoSleep( 100 * 1000 );
|
||||
}
|
||||
|
||||
return total_sent;
|
||||
@@ -1546,19 +1535,20 @@ 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 || to.type == NA_LOOPBACK )
|
||||
if( !net.initialized || type == NA_LOOPBACK )
|
||||
{
|
||||
NET_SendLoopPacket( sock, length, data, to );
|
||||
return;
|
||||
}
|
||||
else if( to.type == NA_BROADCAST || to.type == NA_IP )
|
||||
else if( type == NA_BROADCAST || type == NA_IP )
|
||||
{
|
||||
net_socket = net.ip_sockets[sock];
|
||||
if( !NET_IsSocketValid( net_socket ))
|
||||
return;
|
||||
}
|
||||
else if( to.type6 == NA_MULTICAST_IP6 || to.type6 == NA_IP6 )
|
||||
else if( type == NA_MULTICAST_IP6 || type == NA_IP6 )
|
||||
{
|
||||
net_socket = net.ip6_sockets[sock];
|
||||
if( !NET_IsSocketValid( net_socket ))
|
||||
@@ -1566,7 +1556,7 @@ void NET_SendPacketEx( netsrc_t sock, size_t length, const void *data, netadr_t
|
||||
}
|
||||
else
|
||||
{
|
||||
Host_Error( "%s: bad address type %i (%i)\n", __func__, to.type, to.type6 );
|
||||
Host_Error( "%s: bad address type %i (%i, %i)\n", __func__, to.type, to.ip6_0[0], to.ip6_0[1] );
|
||||
}
|
||||
|
||||
NET_NetadrToSockadr( &to, &addr );
|
||||
@@ -1582,7 +1572,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 && ( to.type == NA_BROADCAST || to.type6 == NA_MULTICAST_IP6 ))
|
||||
if( err == WSAEADDRNOTAVAIL && ( type == NA_BROADCAST || type == NA_MULTICAST_IP6 ))
|
||||
return;
|
||||
|
||||
if( Host_IsDedicated( ))
|
||||
|
||||
@@ -64,7 +64,6 @@ 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 );
|
||||
@@ -80,7 +79,7 @@ void NET_NetadrToIP6Bytes( uint8_t *ip6, const netadr_t *adr );
|
||||
|
||||
static inline qboolean NET_IsLocalAddress( netadr_t adr )
|
||||
{
|
||||
return adr.type == NA_LOOPBACK ? true : false;
|
||||
return NET_NetadrType( &adr ) == NA_LOOPBACK;
|
||||
}
|
||||
|
||||
#if !XASH_DEDICATED
|
||||
|
||||
@@ -69,7 +69,6 @@ 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
|
||||
@@ -214,6 +213,7 @@ 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,6 +285,7 @@ typedef struct netchan_s
|
||||
qboolean split;
|
||||
qboolean use_munge;
|
||||
qboolean use_bz2;
|
||||
qboolean use_lzss;
|
||||
qboolean gs_netchan;
|
||||
} netchan_t;
|
||||
|
||||
|
||||
@@ -112,6 +112,9 @@ msurface_t *PM_RecursiveSurfCheck( model_t *mod, mnode_t *node, vec3_t p1, vec3_
|
||||
int i, side;
|
||||
msurface_t *surf;
|
||||
vec3_t mid;
|
||||
mnode_t *children[2];
|
||||
int numsurfaces, firstsurface;
|
||||
|
||||
loc0:
|
||||
if( node->contents < 0 )
|
||||
return NULL;
|
||||
@@ -119,15 +122,17 @@ loc0:
|
||||
t1 = PlaneDiff( p1, node->plane );
|
||||
t2 = PlaneDiff( p2, node->plane );
|
||||
|
||||
node_children( children, node, mod );
|
||||
|
||||
if( t1 >= -FRAC_EPSILON && t2 >= -FRAC_EPSILON )
|
||||
{
|
||||
node = node->children[0];
|
||||
node = children[0];
|
||||
goto loc0;
|
||||
}
|
||||
|
||||
if( t1 < FRAC_EPSILON && t2 < FRAC_EPSILON )
|
||||
{
|
||||
node = node->children[1];
|
||||
node = children[1];
|
||||
goto loc0;
|
||||
}
|
||||
|
||||
@@ -137,13 +142,15 @@ loc0:
|
||||
|
||||
VectorLerp( p1, frac, p2, mid );
|
||||
|
||||
if(( surf = PM_RecursiveSurfCheck( mod, node->children[side], p1, mid )) != NULL )
|
||||
if(( surf = PM_RecursiveSurfCheck( mod, children[side], p1, mid )) != NULL )
|
||||
return surf;
|
||||
|
||||
// walk through real faces
|
||||
for( i = 0; i < node->numsurfaces; i++ )
|
||||
numsurfaces = node_numsurfaces( node, mod );
|
||||
firstsurface = node_firstsurface( node, mod );
|
||||
for( i = 0; i < numsurfaces; i++ )
|
||||
{
|
||||
msurface_t *surf = &mod->surfaces[node->firstsurface + i];
|
||||
msurface_t *surf = &mod->surfaces[firstsurface + i];
|
||||
mextrasurf_t *info = surf->info;
|
||||
mfacebevel_t *fb = info->bevel;
|
||||
int j, contents;
|
||||
@@ -172,7 +179,7 @@ loc0:
|
||||
return NULL; // through the fence
|
||||
}
|
||||
|
||||
return PM_RecursiveSurfCheck( mod, node->children[side^1], mid, p2 );
|
||||
return PM_RecursiveSurfCheck( mod, children[side^1], mid, p2 );
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -227,6 +234,9 @@ static int PM_TestLine_r( model_t *mod, mnode_t *node, vec_t p1f, vec_t p2f, con
|
||||
float frac, midf;
|
||||
int i, r, side;
|
||||
vec3_t mid;
|
||||
mnode_t *children[2];
|
||||
int numsurfaces, firstsurface;
|
||||
|
||||
loc0:
|
||||
if( node->contents < 0 )
|
||||
{
|
||||
@@ -242,15 +252,17 @@ loc0:
|
||||
front = PlaneDiff( start, node->plane );
|
||||
back = PlaneDiff( stop, node->plane );
|
||||
|
||||
node_children( children, node, mod );
|
||||
|
||||
if( front >= -FRAC_EPSILON && back >= -FRAC_EPSILON )
|
||||
{
|
||||
node = node->children[0];
|
||||
node = children[0];
|
||||
goto loc0;
|
||||
}
|
||||
|
||||
if( front < FRAC_EPSILON && back < FRAC_EPSILON )
|
||||
{
|
||||
node = node->children[1];
|
||||
node = children[1];
|
||||
goto loc0;
|
||||
}
|
||||
|
||||
@@ -261,7 +273,7 @@ loc0:
|
||||
VectorLerp( start, frac, stop, mid );
|
||||
midf = p1f + ( p2f - p1f ) * frac;
|
||||
|
||||
r = PM_TestLine_r( mod, node->children[side], p1f, midf, start, mid, trace );
|
||||
r = PM_TestLine_r( mod, children[side], p1f, midf, start, mid, trace );
|
||||
|
||||
if( r != CONTENTS_EMPTY )
|
||||
{
|
||||
@@ -272,9 +284,11 @@ loc0:
|
||||
}
|
||||
|
||||
// walk through real faces
|
||||
for( i = 0; i < node->numsurfaces; i++ )
|
||||
numsurfaces = node_numsurfaces( node, mod );
|
||||
firstsurface = node_firstsurface( node, mod );
|
||||
for( i = 0; i < numsurfaces; i++ )
|
||||
{
|
||||
msurface_t *surf = &mod->surfaces[node->firstsurface + i];
|
||||
msurface_t *surf = &mod->surfaces[firstsurface + i];
|
||||
mextrasurf_t *info = surf->info;
|
||||
mfacebevel_t *fb = info->bevel;
|
||||
int j, contents;
|
||||
@@ -308,7 +322,7 @@ loc0:
|
||||
return contents;
|
||||
}
|
||||
|
||||
return PM_TestLine_r( mod, node->children[!side], midf, p2f, mid, stop, trace );
|
||||
return PM_TestLine_r( mod, children[!side], midf, p2f, mid, stop, trace );
|
||||
}
|
||||
|
||||
int PM_TestLineExt( playermove_t *pmove, physent_t *ents, int numents, const vec3_t start, const vec3_t end, int flags )
|
||||
|
||||
@@ -25,8 +25,7 @@ GNU General Public License for more details.
|
||||
#define PM_AllowHitBoxTrace( model, hull ) ( model && model->type == mod_studio && ( FBitSet( model->flags, STUDIO_TRACE_HITBOX ) || hull == 2 ))
|
||||
|
||||
static mplane_t pm_boxplanes[6];
|
||||
static mclipnode_t pm_boxclipnodes[6];
|
||||
static hull_t pm_boxhull;
|
||||
static hull_t pm_boxhull;
|
||||
|
||||
// default hullmins
|
||||
static const vec3_t pm_hullmins[MAX_MAP_HULLS] =
|
||||
@@ -65,23 +64,15 @@ can just be stored out and get a proper hull_t structure.
|
||||
*/
|
||||
void PM_InitBoxHull( void )
|
||||
{
|
||||
int i, side;
|
||||
int i;
|
||||
|
||||
pm_boxhull.clipnodes = pm_boxclipnodes;
|
||||
pm_boxhull.clipnodes16 = (mclipnode16_t *)box_clipnodes16;
|
||||
pm_boxhull.planes = pm_boxplanes;
|
||||
pm_boxhull.firstclipnode = 0;
|
||||
pm_boxhull.lastclipnode = 5;
|
||||
|
||||
for( i = 0; i < 6; i++ )
|
||||
{
|
||||
pm_boxclipnodes[i].planenum = i;
|
||||
|
||||
side = i & 1;
|
||||
|
||||
pm_boxclipnodes[i].children[side] = CONTENTS_EMPTY;
|
||||
if( i != 5 ) pm_boxclipnodes[i].children[side^1] = i + 1;
|
||||
else pm_boxclipnodes[i].children[side^1] = CONTENTS_SOLID;
|
||||
|
||||
pm_boxplanes[i].type = i>>1;
|
||||
pm_boxplanes[i].normal[i>>1] = 1.0f;
|
||||
pm_boxplanes[i].signbits = 0;
|
||||
@@ -106,6 +97,11 @@ static hull_t *PM_HullForBox( const vec3_t mins, const vec3_t maxs )
|
||||
pm_boxplanes[4].dist = maxs[2];
|
||||
pm_boxplanes[5].dist = mins[2];
|
||||
|
||||
if( world.version == QBSP2_VERSION )
|
||||
pm_boxhull.clipnodes32 = (mclipnode32_t *)box_clipnodes32;
|
||||
else
|
||||
pm_boxhull.clipnodes16 = (mclipnode16_t *)box_clipnodes16;
|
||||
|
||||
return &pm_boxhull;
|
||||
}
|
||||
|
||||
@@ -122,10 +118,21 @@ int GAME_EXPORT PM_HullPointContents( hull_t *hull, int num, const vec3_t p )
|
||||
if( !hull || !hull->planes ) // fantom bmodels?
|
||||
return CONTENTS_NONE;
|
||||
|
||||
while( num >= 0 )
|
||||
if( world.version == QBSP2_VERSION )
|
||||
{
|
||||
plane = &hull->planes[hull->clipnodes[num].planenum];
|
||||
num = hull->clipnodes[num].children[PlaneDiff( p, plane ) < 0];
|
||||
while( num >= 0 )
|
||||
{
|
||||
plane = &hull->planes[hull->clipnodes32[num].planenum];
|
||||
num = hull->clipnodes32[num].children[PlaneDiff( p, plane ) < 0];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while( num >= 0 )
|
||||
{
|
||||
plane = &hull->planes[hull->clipnodes16[num].planenum];
|
||||
num = hull->clipnodes16[num].children[PlaneDiff( p, plane ) < 0];
|
||||
}
|
||||
}
|
||||
return num;
|
||||
}
|
||||
@@ -193,7 +200,7 @@ PM_RecursiveHullCheck
|
||||
*/
|
||||
qboolean PM_RecursiveHullCheck( hull_t *hull, int num, float p1f, float p2f, vec3_t p1, vec3_t p2, pmtrace_t *trace )
|
||||
{
|
||||
mclipnode_t *node;
|
||||
int children[2];
|
||||
mplane_t *plane;
|
||||
float t1, t2;
|
||||
float frac, midf;
|
||||
@@ -226,21 +233,31 @@ loc0:
|
||||
Host_Error( "%s: bad node number %i\n", __func__, num );
|
||||
|
||||
// find the point distances
|
||||
node = hull->clipnodes + num;
|
||||
plane = hull->planes + node->planenum;
|
||||
if( world.version == QBSP2_VERSION )
|
||||
{
|
||||
children[0] = hull->clipnodes32[num].children[0];
|
||||
children[1] = hull->clipnodes32[num].children[1];
|
||||
plane = hull->planes + hull->clipnodes32[num].planenum;
|
||||
}
|
||||
else
|
||||
{
|
||||
children[0] = hull->clipnodes16[num].children[0];
|
||||
children[1] = hull->clipnodes16[num].children[1];
|
||||
plane = hull->planes + hull->clipnodes16[num].planenum;
|
||||
}
|
||||
|
||||
t1 = PlaneDiff( p1, plane );
|
||||
t2 = PlaneDiff( p2, plane );
|
||||
|
||||
if( t1 >= 0.0f && t2 >= 0.0f )
|
||||
{
|
||||
num = node->children[0];
|
||||
num = children[0];
|
||||
goto loc0;
|
||||
}
|
||||
|
||||
if( t1 < 0.0f && t2 < 0.0f )
|
||||
{
|
||||
num = node->children[1];
|
||||
num = children[1];
|
||||
goto loc0;
|
||||
}
|
||||
|
||||
@@ -257,14 +274,14 @@ loc0:
|
||||
VectorLerp( p1, frac, p2, mid );
|
||||
|
||||
// move up to the node
|
||||
if( !PM_RecursiveHullCheck( hull, node->children[side], p1f, midf, p1, mid, trace ))
|
||||
if( !PM_RecursiveHullCheck( hull, children[side], p1f, midf, p1, mid, trace ))
|
||||
return false;
|
||||
|
||||
// this recursion can not be optimized because mid would need to be duplicated on a stack
|
||||
if( PM_HullPointContents( hull, node->children[side^1], mid ) != CONTENTS_SOLID )
|
||||
if( PM_HullPointContents( hull, children[side^1], mid ) != CONTENTS_SOLID )
|
||||
{
|
||||
// go past the node
|
||||
return PM_RecursiveHullCheck( hull, node->children[side^1], midf, p2f, mid, p2, trace );
|
||||
return PM_RecursiveHullCheck( hull, children[side^1], midf, p2f, mid, p2, trace );
|
||||
}
|
||||
|
||||
// never got out of the solid area
|
||||
|
||||
@@ -89,16 +89,6 @@ 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;
|
||||
@@ -378,6 +368,7 @@ 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;
|
||||
@@ -431,22 +422,30 @@ 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 );
|
||||
|
||||
t2 = Sys_DoubleTime();
|
||||
|
||||
if( handled )
|
||||
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
|
||||
// restore previously changed data
|
||||
sc->rate = inrate;
|
||||
sc->width = inwidth;
|
||||
sc->channels = inchannels;
|
||||
sc->samples = incount;
|
||||
sc->size = insize;
|
||||
|
||||
Con_Printf( S_ERROR "%s: unsupported from [%d bit %d Hz %dch] to [%d bit %d Hz %dch]\n", __func__, inwidth * 8, inrate, inchannels, outwidth * 8, outrate, outchannels );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
t2 = Sys_DoubleTime();
|
||||
sc->rate = outrate;
|
||||
sc->width = outwidth;
|
||||
|
||||
return handled;
|
||||
if( t2 - t1 > 0.01f ) // critical, report to mod developer
|
||||
Con_Printf( S_WARN "%s: from [%d bit %d Hz %dch] to [%d bit %d Hz %dch] (took %.3fs)\n", __func__, inwidth * 8, inrate, inchannels, outwidth * 8, outrate, outchannels, t2 - t1 );
|
||||
else
|
||||
Con_Reportf( "%s: from [%d bit %d Hz %dch] to [%d bit %d Hz %dch] (took %.3fs)\n", __func__, inwidth * 8, inrate, inchannels, outwidth * 8, outrate, outchannels, t2 - t1 );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
qboolean Sound_Process( wavdata_t **wav, int rate, int width, int channels, uint flags )
|
||||
@@ -464,8 +463,11 @@ qboolean Sound_Process( wavdata_t **wav, int rate, int width, int channels, uint
|
||||
|
||||
if( result )
|
||||
{
|
||||
Mem_Free( snd->buffer ); // free original image buffer
|
||||
snd->buffer = Sound_Copy( snd->size ); // unzone buffer
|
||||
snd = Mem_Realloc( host.soundpool, snd, sizeof( *snd ) + snd->size );
|
||||
memcpy( snd->buffer, sound.tempbuffer, snd->size );
|
||||
|
||||
Mem_Free( sound.tempbuffer );
|
||||
sound.tempbuffer = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -31,15 +31,14 @@ GNU General Public License for more details.
|
||||
#define XASH_COLORIZE_CONSOLE 0
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
char title[64];
|
||||
qboolean log_active;
|
||||
char log_path[MAX_SYSPATH];
|
||||
FILE *logfile;
|
||||
int logfileno;
|
||||
} LogData;
|
||||
|
||||
static LogData s_ld;
|
||||
static struct logdata_s {
|
||||
char title[64];
|
||||
qboolean log_active;
|
||||
qboolean log_time;
|
||||
char log_path[MAX_SYSPATH];
|
||||
FILE *logfile;
|
||||
int logfileno;
|
||||
} s_ld;
|
||||
|
||||
void Sys_DestroyConsole( void )
|
||||
{
|
||||
@@ -78,14 +77,19 @@ static void Sys_FlushLogfile( void )
|
||||
|
||||
void Sys_InitLog( void )
|
||||
{
|
||||
const char *mode;
|
||||
const char *mode;
|
||||
|
||||
if( Sys_CheckParm( "-log" ) && host.allow_console != 0 )
|
||||
if( Sys_CheckParm( "-log" ))
|
||||
{
|
||||
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";
|
||||
@@ -101,7 +105,7 @@ void Sys_InitLog( void )
|
||||
|
||||
if ( !s_ld.logfile )
|
||||
{
|
||||
Con_Reportf( S_ERROR "Sys_InitLog: can't create log file %s: %s\n", s_ld.log_path, strerror( errno ));
|
||||
Con_Reportf( S_ERROR "%s: can't create log file %s: %s\n", __func__, s_ld.log_path, strerror( errno ));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -109,44 +113,44 @@ void Sys_InitLog( void )
|
||||
|
||||
// fit to 80 columns for easier read on standard terminal
|
||||
fputs( "================================================================================\n", s_ld.logfile );
|
||||
fprintf( s_ld.logfile, "%s (%i, %s, %s, %s-%s)\n", s_ld.title, Q_buildnum(), Q_buildcommit(), Q_buildbranch(), Q_buildos(), Q_buildarch());
|
||||
fprintf( s_ld.logfile, "%s (%i, %s, %s, %s-%s)\n", s_ld.title, Q_buildnum(), g_buildcommit, g_buildbranch, Q_buildos(), Q_buildarch());
|
||||
fprintf( s_ld.logfile, "Game started at %s\n", Q_timestamp( TIME_FULL ));
|
||||
fputs( "================================================================================\n", s_ld.logfile );
|
||||
fflush( s_ld.logfile );
|
||||
}
|
||||
}
|
||||
|
||||
void Sys_CloseLog( void )
|
||||
void Sys_CloseLog( const char *finalmsg )
|
||||
{
|
||||
char event_name[64];
|
||||
|
||||
// continue logged
|
||||
switch( host.status )
|
||||
{
|
||||
case HOST_CRASHED:
|
||||
Q_strncpy( event_name, "crashed", sizeof( event_name ));
|
||||
break;
|
||||
case HOST_ERR_FATAL:
|
||||
Q_strncpy( event_name, "stopped with error", sizeof( event_name ));
|
||||
break;
|
||||
default:
|
||||
if( !host.change_game ) Q_strncpy( event_name, "stopped", sizeof( event_name ));
|
||||
else Q_strncpy( event_name, host.finalmsg, sizeof( event_name ));
|
||||
break;
|
||||
}
|
||||
|
||||
Sys_FlushStdout(); // flush to stdout to ensure all data was written
|
||||
|
||||
if( s_ld.logfile )
|
||||
if( !s_ld.logfile )
|
||||
return;
|
||||
|
||||
// continue logged
|
||||
if( !finalmsg )
|
||||
{
|
||||
fputc( '\n', s_ld.logfile );
|
||||
fputs( "================================================================================\n", s_ld.logfile );
|
||||
fprintf( s_ld.logfile, "%s (%i, %s, %s, %s-%s)\n", s_ld.title, Q_buildnum(), Q_buildcommit(), Q_buildbranch(), Q_buildos(), Q_buildarch());
|
||||
fprintf( s_ld.logfile, "Stopped with reason \"%s\" at %s\n", event_name, Q_timestamp( TIME_FULL ));
|
||||
fputs( "================================================================================\n", s_ld.logfile );
|
||||
fclose( s_ld.logfile );
|
||||
s_ld.logfile = NULL;
|
||||
switch( host.status )
|
||||
{
|
||||
case HOST_CRASHED:
|
||||
finalmsg = "crashed";
|
||||
break;
|
||||
case HOST_ERR_FATAL:
|
||||
finalmsg = "stopped with error";
|
||||
break;
|
||||
default:
|
||||
finalmsg = "stopped";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
fputc( '\n', s_ld.logfile );
|
||||
fputs( "================================================================================\n", s_ld.logfile );
|
||||
fprintf( s_ld.logfile, "%s (%i, %s, %s, %s-%s)\n", s_ld.title, Q_buildnum(), g_buildcommit, g_buildbranch, Q_buildos(), Q_buildarch());
|
||||
fprintf( s_ld.logfile, "Stopped with reason \"%s\" at %s\n", finalmsg, Q_timestamp( TIME_FULL ));
|
||||
fputs( "================================================================================\n", s_ld.logfile );
|
||||
fclose( s_ld.logfile );
|
||||
s_ld.logfile = NULL;
|
||||
}
|
||||
|
||||
#if XASH_COLORIZE_CONSOLE
|
||||
@@ -295,17 +299,23 @@ void Sys_PrintLog( const char *pMsg )
|
||||
// save last char to detect when line was not ended
|
||||
lastchar = len > 0 ? pMsg[len - 1] : 0;
|
||||
|
||||
if( !s_ld.logfile )
|
||||
return;
|
||||
|
||||
if( print_time )
|
||||
// spew to engine.log
|
||||
if( s_ld.logfile )
|
||||
{
|
||||
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
|
||||
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;
|
||||
}
|
||||
|
||||
Sys_PrintLogfile( s_ld.logfileno, logtime, logtime_len, pMsg, false );
|
||||
Sys_FlushLogfile();
|
||||
}
|
||||
|
||||
Sys_PrintLogfile( s_ld.logfileno, logtime, logtime_len, pMsg, false );
|
||||
Sys_FlushLogfile();
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -420,6 +420,12 @@ void Sys_Error( const char *error, ... )
|
||||
_exit->_Exit->asm._exit->_exit
|
||||
As we do not need atexit(), just throw hidden exception
|
||||
*/
|
||||
|
||||
// Hey, you, making an Emscripten port!
|
||||
// What if we're not supposed to use exit() on Emscripten and instead we should
|
||||
// exit from the main() function? Would this fix this bug? Test this case, pls.
|
||||
#error "Read the comment above"
|
||||
|
||||
#include <emscripten.h>
|
||||
#define exit my_exit
|
||||
void my_exit(int ret)
|
||||
@@ -438,7 +444,11 @@ Sys_Quit
|
||||
void Sys_Quit( const char *reason )
|
||||
{
|
||||
Host_ShutdownWithReason( reason );
|
||||
#if XASH_ANDROID
|
||||
Host_ExitInMain();
|
||||
#else
|
||||
exit( error_on_exit );
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -529,7 +539,7 @@ but since engine will be unloaded during this call
|
||||
it explicitly doesn't use internal allocation or string copy utils
|
||||
==================
|
||||
*/
|
||||
qboolean Sys_NewInstance( const char *gamedir )
|
||||
qboolean Sys_NewInstance( const char *gamedir, const char *finalmsg )
|
||||
{
|
||||
#if XASH_NSWITCH
|
||||
char newargs[4096];
|
||||
@@ -540,7 +550,7 @@ qboolean Sys_NewInstance( const char *gamedir )
|
||||
// just restart the entire thing
|
||||
printf( "envSetNextLoad exe: `%s`\n", exe );
|
||||
printf( "envSetNextLoad argv:\n`%s`\n", newargs );
|
||||
Host_ShutdownWithReason( "changing game" );
|
||||
Host_ShutdownWithReason( finalmsg );
|
||||
envSetNextLoad( exe, newargs );
|
||||
exit( 0 );
|
||||
#else
|
||||
@@ -578,7 +588,7 @@ qboolean Sys_NewInstance( const char *gamedir )
|
||||
#if XASH_PSVITA
|
||||
// under normal circumstances it's always going to be the same path
|
||||
exe = strdup( "app0:/eboot.bin" );
|
||||
Host_ShutdownWithReason( "changing game" );
|
||||
Host_ShutdownWithReason( finalmsg );
|
||||
sceAppMgrLoadExec( exe, newargs, NULL );
|
||||
#else
|
||||
exelen = wai_getExecutablePath( NULL, 0, NULL );
|
||||
@@ -586,7 +596,7 @@ qboolean Sys_NewInstance( const char *gamedir )
|
||||
wai_getExecutablePath( exe, exelen, NULL );
|
||||
exe[exelen] = 0;
|
||||
|
||||
Host_ShutdownWithReason( "changing game" );
|
||||
Host_ShutdownWithReason( finalmsg );
|
||||
|
||||
execv( exe, newargs );
|
||||
#endif
|
||||
|
||||
@@ -41,6 +41,15 @@ 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 );
|
||||
@@ -56,11 +65,8 @@ void Sys_DebugBreak( void );
|
||||
qboolean _Sys_GetParmFromCmdLine( const char *parm, char *out, size_t size );
|
||||
qboolean Sys_GetIntFromCmdLine( const char *parm, int *out );
|
||||
void Sys_Print( const char *pMsg );
|
||||
void Sys_PrintLog( const char *pMsg );
|
||||
void Sys_InitLog( void );
|
||||
void Sys_CloseLog( void );
|
||||
void Sys_Quit( const char *reason ) NORETURN;
|
||||
qboolean Sys_NewInstance( const char *gamedir );
|
||||
qboolean Sys_NewInstance( const char *gamedir, const char *finalmsg );
|
||||
void *Sys_GetNativeObject( const char *obj );
|
||||
|
||||
//
|
||||
@@ -68,7 +74,7 @@ void *Sys_GetNativeObject( const char *obj );
|
||||
//
|
||||
char *Sys_Input( void );
|
||||
void Sys_DestroyConsole( void );
|
||||
void Sys_CloseLog( void );
|
||||
void Sys_CloseLog( const char *finalmsg );
|
||||
void Sys_InitLog( void );
|
||||
void Sys_PrintLog( const char *pMsg );
|
||||
int Sys_LogFileNo( void );
|
||||
|
||||
@@ -68,7 +68,13 @@ 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)
|
||||
{
|
||||
@@ -243,6 +249,11 @@ 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>
|
||||
@@ -265,20 +276,20 @@ int WAI_PREFIX(getModulePath)(char* out, int capacity, int* dirname_length)
|
||||
|
||||
for (;;)
|
||||
{
|
||||
char buffer[PATH_MAX < 1024 ? 1024 : PATH_MAX];
|
||||
uint64_t low, high;
|
||||
char buffer[128 + PATH_MAX];
|
||||
uintptr_t low, high;
|
||||
char perms[5];
|
||||
uint64_t offset;
|
||||
uint32_t major, minor;
|
||||
char path[PATH_MAX];
|
||||
uint32_t inode;
|
||||
uint32_t major, minor, inode;
|
||||
char path[PATH_MAX + 1];
|
||||
|
||||
if (!fgets(buffer, sizeof(buffer), maps))
|
||||
break;
|
||||
|
||||
if (sscanf(buffer, "%" PRIx64 "-%" PRIx64 " %s %" PRIx64 " %x:%x %u %s\n", &low, &high, perms, &offset, &major, &minor, &inode, path) == 8)
|
||||
if (sscanf(buffer, "%" SCNxPTR "-%" SCNxPTR " %s %" SCNx64 " %x:%x %u %" WAI_STRINGIZE(PATH_MAX) "[^\n]\n", &low, &high, perms, &offset, &major, &minor, &inode, path) == 8)
|
||||
{
|
||||
uint64_t addr = (uintptr_t)WAI_RETURN_ADDRESS();
|
||||
void* _addr = WAI_RETURN_ADDRESS();
|
||||
uintptr_t addr = (uintptr_t)_addr;
|
||||
if (low <= addr && addr <= high)
|
||||
{
|
||||
char* resolved;
|
||||
|
||||
@@ -31,7 +31,8 @@ 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.
|
||||
* of the path. Available only when `capacity` is large enough to retrieve the
|
||||
* path.
|
||||
*
|
||||
* @return the length of the executable path on success (without a terminal NUL
|
||||
* character), otherwise `-1`
|
||||
@@ -52,7 +53,8 @@ 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.
|
||||
* of the path. Available only when `capacity` is large enough to retrieve the
|
||||
* path.
|
||||
*
|
||||
* @return the length of the module path on success (without a terminal NUL
|
||||
* character), otherwise `-1`
|
||||
|
||||
@@ -18,7 +18,7 @@ GNU General Public License for more details.
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#define MEMHEADER_SENTINEL1 0xDEADF00DU
|
||||
#define MEMHEADER_SENTINEL1 0xA1BAU
|
||||
#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; // 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
|
||||
|
||||
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
|
||||
// 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,10 +233,7 @@ 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 );
|
||||
}
|
||||
@@ -521,4 +518,5 @@ Memory_Init
|
||||
void Memory_Init( void )
|
||||
{
|
||||
poolchain = NULL; // init mem chain
|
||||
poolcount = 0;
|
||||
}
|
||||
|
||||
@@ -16,11 +16,8 @@
|
||||
#ifndef EDICT_H
|
||||
#define EDICT_H
|
||||
|
||||
#ifdef SUPPORT_BSP2_FORMAT
|
||||
#define MAX_ENT_LEAFS 24 // Orignally was 16
|
||||
#else
|
||||
#define MAX_ENT_LEAFS 48
|
||||
#endif
|
||||
#define MAX_ENT_LEAFS_32 24 // Orignally was 16
|
||||
#define MAX_ENT_LEAFS_16 48
|
||||
|
||||
#include "progdefs.h"
|
||||
|
||||
@@ -33,11 +30,12 @@ struct edict_s
|
||||
int headnode; // -1 to use normal leaf check
|
||||
|
||||
int num_leafs;
|
||||
#ifdef SUPPORT_BSP2_FORMAT
|
||||
int leafnums[MAX_ENT_LEAFS];
|
||||
#else
|
||||
short leafnums[MAX_ENT_LEAFS];
|
||||
#endif
|
||||
union
|
||||
{
|
||||
int leafnums32[MAX_ENT_LEAFS_32];
|
||||
short leafnums16[MAX_ENT_LEAFS_16];
|
||||
};
|
||||
|
||||
float freetime; // sv.time when the object was freed
|
||||
|
||||
void* pvPrivateData; // Alloced and freed by engine, used by DLLs
|
||||
|
||||
300
engine/keydefs.h
300
engine/keydefs.h
@@ -1,186 +1,164 @@
|
||||
/***
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
****/
|
||||
/*
|
||||
Copyright (C) 1997-2001 Id Software, Inc.
|
||||
|
||||
#ifndef KEYDEFS_H
|
||||
#define KEYDEFS_H
|
||||
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
|
||||
|
||||
//
|
||||
// these are the key numbers that should be passed to Key_Event
|
||||
//
|
||||
#define K_TAB 9
|
||||
#define K_ENTER 13
|
||||
#define K_ESCAPE 27
|
||||
#define K_SPACE 32
|
||||
#define K_SCROLLOCK 70
|
||||
|
||||
// normal keys should be passed as lowercased ascii
|
||||
//
|
||||
#define K_TAB 9
|
||||
#define K_ENTER 13
|
||||
#define K_ESCAPE 27
|
||||
#define K_SPACE 32
|
||||
#define K_SCROLLLOCK 70
|
||||
#define K_BACKSPACE 127
|
||||
#define K_UPARROW 128
|
||||
#define K_DOWNARROW 129
|
||||
#define K_LEFTARROW 130
|
||||
#define K_RIGHTARROW 131
|
||||
#define K_ALT 132
|
||||
#define K_CTRL 133
|
||||
#define K_SHIFT 134
|
||||
#define K_F1 135
|
||||
#define K_F2 136
|
||||
#define K_F3 137
|
||||
#define K_F4 138
|
||||
#define K_F5 139
|
||||
#define K_F6 140
|
||||
#define K_F7 141
|
||||
#define K_F8 142
|
||||
#define K_F9 143
|
||||
#define K_F10 144
|
||||
#define K_F11 145
|
||||
#define K_F12 146
|
||||
#define K_INS 147
|
||||
#define K_DEL 148
|
||||
#define K_PGDN 149
|
||||
#define K_PGUP 150
|
||||
#define K_HOME 151
|
||||
#define K_END 152
|
||||
|
||||
#define K_BACKSPACE 127
|
||||
#define K_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_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 // LTRIGGER (L2)
|
||||
#define K_JOY2 204 // RTRIGGER (R2)
|
||||
#define K_JOY3 205
|
||||
#define K_JOY4 206
|
||||
#define K_JOY1 203
|
||||
#define K_JOY2 204
|
||||
#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_A_BUTTON K_AUX1
|
||||
#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_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
|
||||
//
|
||||
// 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_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_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
|
||||
#define K_TOUCHPAD K_AUX25
|
||||
|
||||
//
|
||||
// mouse buttons generate virtual keys
|
||||
//
|
||||
#define K_MOUSE1 241
|
||||
#define K_MOUSE2 242
|
||||
#define K_MOUSE3 243
|
||||
#define K_MOUSE4 244
|
||||
#define K_MOUSE5 245
|
||||
#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
|
||||
|
||||
#endif//KEYDEFS_H
|
||||
#define K_PAUSE 255
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
#include <android/log.h>
|
||||
#include "linker.h"
|
||||
|
||||
static const Elf_Sym *soinfo_elf_lookup( const soinfo *si, unsigned hash, const char *name )
|
||||
static const Elf_Sym *soinfo_elf_lookup( const struct 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 soinfo *si, const char *name )
|
||||
static const Elf_Sym *dlsym_handle_lookup( const struct soinfo *si, const char *name )
|
||||
{
|
||||
return soinfo_elf_lookup( si, elfhash((const unsigned char *)name ), name );
|
||||
}
|
||||
|
||||
extern "C" void *dlsym_weak( void *handle, const char *symbol )
|
||||
void *dlsym_weak( void *handle, const char *symbol )
|
||||
{
|
||||
const soinfo *found = (soinfo *)handle;
|
||||
const struct soinfo *found = (struct soinfo *)handle;
|
||||
const Elf_Sym *sym = dlsym_handle_lookup( found, symbol );
|
||||
|
||||
if( sym != NULL )
|
||||
@@ -31,10 +31,8 @@
|
||||
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
// #include <elf.h>
|
||||
#include <stdbool.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
|
||||
@@ -69,8 +67,8 @@ struct link_map_t {
|
||||
uintptr_t l_addr;
|
||||
char *l_name;
|
||||
uintptr_t l_ld;
|
||||
link_map_t *l_next;
|
||||
link_map_t *l_prev;
|
||||
struct link_map_t *l_next;
|
||||
struct link_map_t *l_prev;
|
||||
};
|
||||
|
||||
// Values for r_debug->state
|
||||
@@ -85,7 +83,7 @@ enum {
|
||||
|
||||
#define SOINFO_NAME_LEN 128
|
||||
|
||||
typedef void (*linker_function_t)();
|
||||
typedef void (*linker_function_t)( void );
|
||||
|
||||
// Android uses REL for 32-bit but only uses RELA for 64-bit.
|
||||
#if defined( __LP64__ )
|
||||
@@ -93,7 +91,6 @@ typedef void (*linker_function_t)();
|
||||
#endif
|
||||
|
||||
struct soinfo {
|
||||
public:
|
||||
char name[SOINFO_NAME_LEN];
|
||||
const Elf_Phdr *phdr;
|
||||
size_t phnum;
|
||||
@@ -112,7 +109,7 @@ public:
|
||||
uint32_t unused3; // DO NOT USE, maintained for compatibility
|
||||
#endif
|
||||
|
||||
soinfo *next;
|
||||
struct soinfo *next;
|
||||
unsigned flags;
|
||||
|
||||
const char *strtab;
|
||||
@@ -164,8 +161,8 @@ public:
|
||||
unsigned mips_gotsym;
|
||||
#endif
|
||||
|
||||
size_t ref_count;
|
||||
link_map_t link_map;
|
||||
size_t ref_count;
|
||||
struct link_map_t link_map;
|
||||
|
||||
bool constructors_called;
|
||||
|
||||
@@ -177,14 +174,6 @@ public:
|
||||
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,11 +91,6 @@ void GAME_EXPORT Platform_SetMousePos(int x, int y)
|
||||
|
||||
}
|
||||
|
||||
int Platform_JoyInit( int numjoy )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Platform_EnableTextInput( qboolean enable )
|
||||
{
|
||||
keystate.chars = enable;
|
||||
|
||||
@@ -184,7 +184,7 @@ qboolean SNDDMA_Init( void )
|
||||
return false;
|
||||
}
|
||||
|
||||
dma.buffer = Z_Malloc( samples * 2 ); //allocate pcm frame buffer
|
||||
dma.buffer = Mem_Calloc( sndpool, samples * 2 ); //allocate pcm frame buffer
|
||||
dma.samplepos = 0;
|
||||
dma.samples = samples;
|
||||
dma.format.width = 2;
|
||||
|
||||
@@ -281,13 +281,8 @@ 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
|
||||
|
||||
@@ -55,7 +55,7 @@ char *Posix_Input( void );
|
||||
#endif
|
||||
|
||||
#if XASH_SDL
|
||||
void SDLash_Init( void );
|
||||
void SDLash_Init( const char *basedir );
|
||||
void SDLash_Shutdown( void );
|
||||
#endif
|
||||
|
||||
@@ -70,6 +70,9 @@ 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 );
|
||||
@@ -104,7 +107,7 @@ void Linux_SetTimer( float time );
|
||||
int Linux_GetProcessID( void );
|
||||
#endif
|
||||
|
||||
static inline void Platform_Init( qboolean con_showalways )
|
||||
static inline void Platform_Init( qboolean con_showalways, const char *basedir )
|
||||
{
|
||||
#if XASH_POSIX
|
||||
// daemonize as early as possible, because we need to close our file descriptors
|
||||
@@ -112,7 +115,7 @@ static inline void Platform_Init( qboolean con_showalways )
|
||||
#endif
|
||||
|
||||
#if XASH_SDL
|
||||
SDLash_Init( );
|
||||
SDLash_Init( basedir );
|
||||
#endif
|
||||
|
||||
#if XASH_ANDROID
|
||||
@@ -124,7 +127,7 @@ static inline void Platform_Init( qboolean con_showalways )
|
||||
#elif XASH_DOS
|
||||
DOS_Init( );
|
||||
#elif XASH_WIN32
|
||||
Wcon_CreateConsole( con_showalways );
|
||||
Win32_Init( con_showalways );
|
||||
#elif XASH_LINUX
|
||||
Linux_Init( );
|
||||
#endif
|
||||
@@ -139,7 +142,7 @@ static inline void Platform_Shutdown( void )
|
||||
#elif XASH_DOS
|
||||
DOS_Shutdown( );
|
||||
#elif XASH_WIN32
|
||||
Wcon_DestroyConsole( );
|
||||
Win32_Shutdown( );
|
||||
#elif XASH_LINUX
|
||||
Linux_Shutdown( );
|
||||
#endif
|
||||
@@ -178,11 +181,28 @@ static inline void Platform_Sleep( int msec )
|
||||
#endif
|
||||
}
|
||||
|
||||
#if XASH_WIN32 || XASH_FREEBSD || XASH_NETBSD || XASH_OPENBSD || XASH_ANDROID || XASH_LINUX
|
||||
void Sys_SetupCrashHandler( void );
|
||||
static inline qboolean Platform_NanoSleep( int nsec )
|
||||
{
|
||||
// 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 );
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if XASH_WIN32 || XASH_FREEBSD || XASH_NETBSD || XASH_OPENBSD || XASH_ANDROID || XASH_LINUX || XASH_APPLE
|
||||
void Sys_SetupCrashHandler( const char *argv0 );
|
||||
void Sys_RestoreCrashHandler( void );
|
||||
#else
|
||||
static inline void Sys_SetupCrashHandler( void )
|
||||
static inline void Sys_SetupCrashHandler( const char *argv0 )
|
||||
{
|
||||
}
|
||||
|
||||
@@ -199,7 +219,8 @@ static inline void Sys_RestoreCrashHandler( void )
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
void Platform_Vibrate( float life, char flags );
|
||||
void Platform_Vibrate( float life, char flags ); // left for compatibility
|
||||
void Platform_Vibrate2( float time, int low_freq, int high_freq, uint flags );
|
||||
|
||||
/*
|
||||
==============================================================================
|
||||
@@ -209,7 +230,27 @@ void Platform_Vibrate( float life, char flags );
|
||||
==============================================================================
|
||||
*/
|
||||
// Gamepad support
|
||||
int Platform_JoyInit( int numjoy ); // returns number of connected gamepads, negative if error
|
||||
#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
|
||||
|
||||
// Text input
|
||||
void Platform_EnableTextInput( qboolean enable );
|
||||
key_modifier_t Platform_GetKeyModifiers( void );
|
||||
|
||||
87
engine/platform/posix/crash_glibc.c
Normal file
87
engine/platform/posix/crash_glibc.c
Normal file
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
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 "common.h"
|
||||
#include <execinfo.h>
|
||||
#include <signal.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 );
|
||||
#ifdef XASH_SDL
|
||||
SDL_SetWindowGrab( host.hWnd, SDL_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
|
||||
186
engine/platform/posix/crash_libbacktrace.c
Normal file
186
engine/platform/posix/crash_libbacktrace.c
Normal file
@@ -0,0 +1,186 @@
|
||||
/*
|
||||
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"
|
||||
|
||||
|
||||
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 && function )
|
||||
{
|
||||
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 );
|
||||
#ifdef XASH_SDL
|
||||
SDL_SetWindowGrab( host.hWnd, SDL_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,7 +18,8 @@ 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
|
||||
#if XASH_FREEBSD || XASH_NETBSD || XASH_OPENBSD || XASH_ANDROID || XASH_LINUX
|
||||
#define _XOPEN_SOURCE 1 // required for ucontext
|
||||
#if XASH_FREEBSD || XASH_NETBSD || XASH_OPENBSD || XASH_ANDROID || XASH_LINUX || XASH_APPLE
|
||||
#ifndef XASH_OPENBSD
|
||||
#include <ucontext.h>
|
||||
#endif
|
||||
@@ -26,6 +27,13 @@ GNU General Public License for more details.
|
||||
#include <sys/mman.h>
|
||||
#include "library.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"
|
||||
|
||||
@@ -33,27 +41,25 @@ GNU General Public License for more details.
|
||||
#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
|
||||
}
|
||||
|
||||
static void Sys_Crash( int signal, siginfo_t *si, void *context)
|
||||
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];
|
||||
@@ -65,6 +71,10 @@ static 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;
|
||||
@@ -112,10 +122,10 @@ static 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)\n",
|
||||
Q_buildnum(), Q_buildcommit(), Q_buildos(), Q_buildarch() );
|
||||
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
|
||||
#if !XASH_FREEBSD && !XASH_NETBSD && !XASH_OPENBSD && !XASH_APPLE
|
||||
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 );
|
||||
@@ -123,10 +133,6 @@ static 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 );
|
||||
@@ -200,15 +206,27 @@ static void Sys_Crash( int signal, siginfo_t *si, void *context)
|
||||
Sys_Quit( "crashed" );
|
||||
}
|
||||
|
||||
void Sys_SetupCrashHandler( void )
|
||||
#endif // !HAVE_EXECINFO
|
||||
|
||||
void Sys_SetupCrashHandler( const char *argv0 )
|
||||
{
|
||||
struct sigaction act = { 0 };
|
||||
act.sa_sigaction = Sys_Crash;
|
||||
#if HAVE_LIBBACKTRACE
|
||||
if( Sys_SetupLibbacktrace( argv0 ))
|
||||
{
|
||||
act.sa_sigaction = Sys_CrashLibbacktrace;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
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 )
|
||||
|
||||
@@ -88,52 +88,8 @@ 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
|
||||
@@ -265,7 +221,7 @@ static void SDLash_KeyEvent( SDL_KeyboardEvent key )
|
||||
break;
|
||||
}
|
||||
case SDL_SCANCODE_PAUSE: keynum = K_PAUSE; break;
|
||||
case SDL_SCANCODE_SCROLLLOCK: keynum = K_SCROLLOCK; break;
|
||||
case SDL_SCANCODE_SCROLLLOCK: keynum = K_SCROLLLOCK; break;
|
||||
#if SDL_VERSION_ATLEAST( 2, 0, 0 )
|
||||
case SDL_SCANCODE_APPLICATION: keynum = K_WIN; break; // (compose key) ???
|
||||
// don't console spam on known functional buttons, not used in engine
|
||||
@@ -408,50 +364,6 @@ 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
|
||||
@@ -479,28 +391,6 @@ 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;
|
||||
@@ -568,46 +458,17 @@ 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:
|
||||
SDLash_GameController_Remove( event->cdevice.which );
|
||||
case SDL_CONTROLLERTOUCHPADDOWN:
|
||||
case SDL_CONTROLLERTOUCHPADMOTION:
|
||||
case SDL_CONTROLLERTOUCHPADUP:
|
||||
case SDL_CONTROLLERSENSORUPDATE:
|
||||
SDLash_HandleGameControllerEvent( event );
|
||||
break;
|
||||
|
||||
case SDL_WINDOWEVENT:
|
||||
@@ -620,19 +481,19 @@ static void SDLash_EventHandler( SDL_Event *event )
|
||||
switch( event->window.event )
|
||||
{
|
||||
case SDL_WINDOWEVENT_MOVED:
|
||||
if( vid_fullscreen.value == WINDOW_MODE_WINDOWED )
|
||||
{
|
||||
char val[32];
|
||||
{
|
||||
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,14 +28,16 @@ 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 @@
|
||||
/*
|
||||
vid_sdl.c - SDL input component
|
||||
Copyright (C) 2018 a1batross
|
||||
in_sdl.c - SDL input component
|
||||
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
|
||||
@@ -12,7 +12,6 @@ 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"
|
||||
@@ -24,7 +23,6 @@ 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
|
||||
@@ -126,20 +124,6 @@ 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
|
||||
|
||||
/*
|
||||
@@ -157,120 +141,6 @@ 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
|
||||
@@ -418,5 +288,3 @@ key_modifier_t Platform_GetKeyModifiers( void )
|
||||
return KeyModifier_None;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif // XASH_DEDICATED
|
||||
|
||||
391
engine/platform/sdl/joy_sdl.c
Normal file
391
engine/platform/sdl/joy_sdl.c
Normal file
@@ -0,0 +1,391 @@
|
||||
/*
|
||||
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;
|
||||
}
|
||||
|
||||
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 = Z_Calloc( dma.samples * 2 );
|
||||
dma.buffer = Mem_Calloc( sndpool, 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 longtime_t g_PerformanceFrequency;
|
||||
static longtime_t g_ClockStart;
|
||||
longtime_t CurrentTime;
|
||||
static Uint64 g_PerformanceFrequency;
|
||||
static Uint64 g_ClockStart;
|
||||
Uint64 CurrentTime;
|
||||
|
||||
if( !g_PerformanceFrequency )
|
||||
{
|
||||
@@ -41,8 +41,65 @@ void Platform_MessageBox( const char *title, const char *message, qboolean paren
|
||||
}
|
||||
#endif // XASH_MESSAGEBOX == MSGBOX_SDL
|
||||
|
||||
void SDLash_Init( void )
|
||||
static const char *SDLash_CategoryToString( int category )
|
||||
{
|
||||
switch( category )
|
||||
{
|
||||
case SDL_LOG_CATEGORY_APPLICATION: return "App";
|
||||
case SDL_LOG_CATEGORY_ERROR: return "Error";
|
||||
case SDL_LOG_CATEGORY_ASSERT: return "Assert";
|
||||
case SDL_LOG_CATEGORY_SYSTEM: return "System";
|
||||
case SDL_LOG_CATEGORY_AUDIO: return "Audio";
|
||||
case SDL_LOG_CATEGORY_VIDEO: return "Video";
|
||||
case SDL_LOG_CATEGORY_RENDER: return "Render";
|
||||
case SDL_LOG_CATEGORY_INPUT: return "Input";
|
||||
case SDL_LOG_CATEGORY_TEST: return "Test";
|
||||
default: return "Unknown";
|
||||
}
|
||||
}
|
||||
|
||||
static void SDLCALL SDLash_LogOutputFunction( void *userdata, int category, SDL_LogPriority priority, const char *message )
|
||||
{
|
||||
switch( priority )
|
||||
{
|
||||
case SDL_LOG_PRIORITY_CRITICAL:
|
||||
case SDL_LOG_PRIORITY_ERROR:
|
||||
Con_Printf( S_ERROR S_BLUE "SDL" S_DEFAULT ": [%s] %s\n", SDLash_CategoryToString( category ), message );
|
||||
break;
|
||||
case SDL_LOG_PRIORITY_WARN:
|
||||
Con_DPrintf( S_WARN S_BLUE "SDL" S_DEFAULT ": [%s] %s\n", SDLash_CategoryToString( category ), message );
|
||||
break;
|
||||
case SDL_LOG_PRIORITY_INFO:
|
||||
Con_Reportf( S_NOTE S_BLUE "SDL" S_DEFAULT ": [%s] %s\n", SDLash_CategoryToString( category ), message );
|
||||
break;
|
||||
default:
|
||||
Con_Reportf( S_BLUE "SDL" S_DEFAULT ": [%s] %s\n", SDLash_CategoryToString( category ), message );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void SDLash_Init( const char *basedir )
|
||||
{
|
||||
#if XASH_APPLE
|
||||
char *path = SDL_GetBasePath();
|
||||
if( path != NULL )
|
||||
{
|
||||
char buf[MAX_VA_STRING];
|
||||
|
||||
Q_snprintf( buf, sizeof( buf ), "%s%s/extras.pk3", path, basedir );
|
||||
setenv( "XASH3D_EXTRAS_PAK1", buf, true );
|
||||
}
|
||||
#endif
|
||||
|
||||
SDL_LogSetOutputFunction( SDLash_LogOutputFunction, NULL );
|
||||
|
||||
if( host_developer.value >= 2 )
|
||||
SDL_LogSetAllPriority( SDL_LOG_PRIORITY_VERBOSE );
|
||||
else if( host_developer.value >= 1 )
|
||||
SDL_LogSetAllPriority( SDL_LOG_PRIORITY_WARN );
|
||||
else
|
||||
SDL_LogSetAllPriority( SDL_LOG_PRIORITY_ERROR );
|
||||
|
||||
#ifndef SDL_INIT_EVENTS
|
||||
#define SDL_INIT_EVENTS 0
|
||||
#endif
|
||||
|
||||
@@ -257,7 +257,8 @@ static void R_InitVideoModes( void )
|
||||
{
|
||||
char buf[MAX_VA_STRING];
|
||||
#if SDL_VERSION_ATLEAST( 2, 0, 0 )
|
||||
int displayIndex = 0; // TODO: handle multiple displays somehow
|
||||
SDL_Point point = { window_xpos.value, window_ypos.value };
|
||||
int displayIndex = SDL_GetPointDisplayIndex( &point );
|
||||
int i, modes;
|
||||
|
||||
num_vidmodes = 0;
|
||||
@@ -735,6 +736,24 @@ 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
|
||||
@@ -747,6 +766,8 @@ 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 ));
|
||||
|
||||
@@ -757,35 +778,43 @@ qboolean VID_CreateWindow( int width, int height, window_mode_t window_mode )
|
||||
|
||||
if( window_mode == WINDOW_MODE_WINDOWED )
|
||||
{
|
||||
SDL_Rect r;
|
||||
|
||||
SDL_Rect *display_rects = ( SDL_Rect * )malloc( num_displays * sizeof( SDL_Rect ));
|
||||
|
||||
SetBits( wndFlags, SDL_WINDOW_RESIZABLE );
|
||||
if( maximized )
|
||||
SetBits( wndFlags, SDL_WINDOW_MAXIMIZED );
|
||||
|
||||
#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
|
||||
if( !display_rects )
|
||||
{
|
||||
Con_Reportf( S_ERROR "%s: SDL_GetDisplayBounds failed: %s\n", __func__, SDL_GetError( ));
|
||||
xpos = SDL_WINDOWPOS_CENTERED;
|
||||
ypos = SDL_WINDOWPOS_CENTERED;
|
||||
Con_Printf( S_ERROR "Failed to allocate memory for display rects!\n" );
|
||||
xpos = SDL_WINDOWPOS_UNDEFINED;
|
||||
ypos = SDL_WINDOWPOS_UNDEFINED;
|
||||
}
|
||||
else
|
||||
{
|
||||
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 )
|
||||
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 = 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
|
||||
{
|
||||
@@ -795,7 +824,16 @@ qboolean VID_CreateWindow( int width, int height, window_mode_t window_mode )
|
||||
else
|
||||
SetBits( wndFlags, SDL_WINDOW_FULLSCREEN_DESKTOP );
|
||||
SetBits( wndFlags, SDL_WINDOW_BORDERLESS );
|
||||
xpos = ypos = 0;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
if( !VID_CreateWindowWithSafeGL( wndname, xpos, ypos, width, height, wndFlags ))
|
||||
@@ -1018,7 +1056,8 @@ qboolean R_Init_Video( const int type )
|
||||
|
||||
#if SDL_VERSION_ATLEAST( 2, 0, 0 )
|
||||
SDL_DisplayMode displayMode;
|
||||
SDL_GetCurrentDisplayMode( 0, &displayMode );
|
||||
SDL_Point point = { window_xpos.value, window_ypos.value };
|
||||
SDL_GetCurrentDisplayMode( SDL_GetPointDisplayIndex( &point ), &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