Compare commits
16 Commits
continuous
...
continuous
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
004af02e99 | ||
|
|
8ad56eb085 | ||
|
|
32def35408 | ||
|
|
952ccb1247 | ||
|
|
6f0fb594e7 | ||
|
|
8b4b0479c8 | ||
|
|
c8bf7e5630 | ||
|
|
4987080e1e | ||
|
|
1d78e400ff | ||
|
|
2d1a885954 | ||
|
|
43ba2e747b | ||
|
|
eefb823ee2 | ||
|
|
a3c33e0fa9 | ||
|
|
16fe6b1b1a | ||
|
|
4275829bd5 | ||
|
|
1884f0a3ce |
10
.cirrus.yml
@@ -4,10 +4,11 @@ task:
|
||||
image_family: freebsd-14-2
|
||||
setup_script:
|
||||
- pkg update
|
||||
- pkg install -y pkgconf git sdl2 python fontconfig libvorbis opusfile bzip2 libbacktrace
|
||||
- pkg install -y pkgconf git sdl2 python fontconfig libvorbis opusfile bzip2
|
||||
- git submodule update --init --recursive
|
||||
test_script:
|
||||
- ./scripts/cirrus/build_freebsd.sh
|
||||
- ./scripts/cirrus/build_freebsd.sh dedicated
|
||||
- ./scripts/cirrus/build_freebsd.sh full
|
||||
|
||||
task:
|
||||
name: freebsd-15-amd64
|
||||
@@ -15,7 +16,8 @@ task:
|
||||
image_family: freebsd-15-0-snap
|
||||
setup_script:
|
||||
- pkg update
|
||||
- pkg install -y pkgconf git sdl2 python fontconfig libvorbis opusfile bzip2 libbacktrace
|
||||
- pkg install -y pkgconf git sdl2 python fontconfig libvorbis opusfile bzip2
|
||||
- git submodule update --init --recursive
|
||||
test_script:
|
||||
- ./scripts/cirrus/build_freebsd.sh
|
||||
- ./scripts/cirrus/build_freebsd.sh dedicated
|
||||
- ./scripts/cirrus/build_freebsd.sh full
|
||||
|
||||
30
.github/workflows/c-cpp.yml
vendored
@@ -15,39 +15,35 @@ jobs:
|
||||
include:
|
||||
# Linux build specifically want oldest Ubuntu as possible
|
||||
# to be crossdistribution compatible, otherwise use ubuntu-latest
|
||||
- os: ubuntu-22.04
|
||||
- os: ubuntu-20.04
|
||||
targetos: linux
|
||||
targetarch: amd64
|
||||
- os: ubuntu-22.04
|
||||
- os: ubuntu-20.04
|
||||
targetos: linux
|
||||
targetarch: i386
|
||||
- os: ubuntu-22.04
|
||||
- os: ubuntu-20.04
|
||||
targetos: linux
|
||||
targetarch: arm64
|
||||
cross: true
|
||||
- os: ubuntu-22.04
|
||||
- os: ubuntu-20.04
|
||||
targetos: linux
|
||||
targetarch: armhf
|
||||
cross: true
|
||||
- os: ubuntu-24.04 # riscv64 would benefit from having latest compilers
|
||||
- os: ubuntu-20.04
|
||||
targetos: linux
|
||||
targetarch: riscv64
|
||||
cross: true
|
||||
- os: ubuntu-22.04
|
||||
- os: ubuntu-20.04
|
||||
targetos: linux
|
||||
targetarch: ppc64el
|
||||
cross: true
|
||||
# - os: ubuntu-aarch64-22.04
|
||||
# - os: ubuntu-aarch64-20.04
|
||||
# targetos: linux
|
||||
# targetarch: aarch64
|
||||
- os: ubuntu-latest
|
||||
targetos: linux
|
||||
targetarch: e2k-8c
|
||||
cross: true
|
||||
- os: ubuntu-latest
|
||||
- os: ubuntu-20.04
|
||||
targetos: android
|
||||
targetarch: multiarch
|
||||
# - os: ubuntu-22.04
|
||||
# - os: ubuntu-20.04
|
||||
# targetos: motomagx
|
||||
# targetarch: armv6
|
||||
|
||||
@@ -70,8 +66,10 @@ jobs:
|
||||
targetos: apple
|
||||
targetarch: amd64
|
||||
env:
|
||||
SDL_VERSION: 2.32.0
|
||||
SDL_VERSION: 2.30.11
|
||||
FFMPEG_VERSION: 7.1
|
||||
GH_CPU_ARCH: ${{ matrix.targetarch }}
|
||||
GH_CPU_OS: ${{ matrix.targetos }}
|
||||
GH_CROSSCOMPILING: ${{ matrix.cross }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
@@ -91,7 +89,6 @@ jobs:
|
||||
path: artifacts/*
|
||||
flatpak:
|
||||
runs-on: ubuntu-latest
|
||||
continue-on-error: true
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
@@ -105,7 +102,7 @@ jobs:
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: Build flatpak (Compat.i386)
|
||||
uses: FWGS/flatpak-github-actions/flatpak-builder@v6.3-fix
|
||||
uses: FWGS/flatpak-github-actions/flatpak-builder@v6.3
|
||||
with:
|
||||
bundle: ${{ matrix.app }}.flatpak
|
||||
manifest-path: scripts/flatpak/${{ matrix.app }}.yml
|
||||
@@ -124,6 +121,7 @@ jobs:
|
||||
--yes \
|
||||
--cleanup-tag \
|
||||
--repo "$GITHUB_REPOSITORY" || true
|
||||
sleep 20s
|
||||
gh run download "$GITHUB_RUN_ID" \
|
||||
--dir artifacts/ \
|
||||
--repo "$GITHUB_REPOSITORY"
|
||||
|
||||
12
.gitmodules
vendored
@@ -27,16 +27,10 @@
|
||||
url = https://github.com/FWGS/MultiEmulator
|
||||
[submodule "3rdparty/libogg/libogg"]
|
||||
path = 3rdparty/libogg/libogg
|
||||
url = https://github.com/xiph/ogg.git
|
||||
url = https://gitlab.xiph.org/xiph/ogg.git
|
||||
[submodule "3rdparty/vorbis/vorbis-src"]
|
||||
path = 3rdparty/vorbis/vorbis-src
|
||||
url = https://github.com/xiph/vorbis.git
|
||||
url = https://gitlab.xiph.org/xiph/vorbis.git
|
||||
[submodule "3rdparty/opusfile/opusfile"]
|
||||
path = 3rdparty/opusfile/opusfile
|
||||
url = https://github.com/xiph/opusfile.git
|
||||
[submodule "3rdparty/libbacktrace/libbacktrace"]
|
||||
path = 3rdparty/libbacktrace/libbacktrace
|
||||
url = https://github.com/ianlancetaylor/libbacktrace
|
||||
[submodule "3rdparty/maintui"]
|
||||
path = 3rdparty/maintui
|
||||
url = https://github.com/numas13/xash3d-maintui.git
|
||||
url = https://gitlab.xiph.org/xiph/opusfile.git
|
||||
|
||||
2
3rdparty/MultiEmulator
vendored
2
3rdparty/extras/xash-extras
vendored
2
3rdparty/gl4es/gl4es
vendored
1
3rdparty/libbacktrace/libbacktrace
vendored
183
3rdparty/libbacktrace/wscript
vendored
@@ -1,183 +0,0 @@
|
||||
#! /usr/bin/env python
|
||||
# encoding: utf-8
|
||||
|
||||
from waflib import TaskGen
|
||||
from waflib.Tools.c_config import DEFKEYS
|
||||
|
||||
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
|
||||
|
||||
conf.define('BACKTRACE_ELF_SIZE', 64 if conf.env.DEST_SIZEOF_VOID_P == 8 else 32)
|
||||
conf.define('BACKTRACE_XCOFF_SIZE', 64 if conf.env.DEST_SIZEOF_VOID_P == 8 else 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.env[DEFKEYS].sort()
|
||||
|
||||
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/'
|
||||
)
|
||||
|
||||
1
3rdparty/maintui
vendored
2
3rdparty/mainui
vendored
2
3rdparty/vgui_support
vendored
@@ -45,8 +45,3 @@
|
||||
Tags can be any: subsystem, simple feature name or even just a filename, without extension.
|
||||
Just keep them always same, it helps keep history clean and commit messages short.
|
||||
|
||||
## LLM-based tools usage.
|
||||
|
||||
While we wouldn't recommend using any LLM-based (also misleadingly called AI) tools, we understand that they are here to stay.
|
||||
|
||||
Whether you're reporting bug or contributing the code, you take complete authorship and responsibility over provided content and the same rules will apply to you as for everybody else, so validate the bug report or the patch before sending it.
|
||||
|
||||
@@ -2,27 +2,23 @@
|
||||
|
||||
On this page you can find links where you can support each developer individually, who has provided public sponsorship information.
|
||||
|
||||
## [a1batross](https://github.com/a1batross)
|
||||
### [a1batross](https://github.com/a1batross)
|
||||
|
||||
Initial Xash3D SDL2/Linux port author, Xash3D FWGS engine maintainer, creator of non-commercial Flying With Gauss organization.
|
||||
* Initial Xash3D SDL2/Linux port author, Xash3D FWGS engine maintainer, creator of non-commercial Flying With Gauss organization.
|
||||
* Boosty page: https://boosty.to/a1ba
|
||||
|
||||
* [Boosty page](https://boosty.to/a1ba)
|
||||
### [nekonomicon](https://github.com/nekonomicon)
|
||||
|
||||
## [nekonomicon](https://github.com/nekonomicon)
|
||||
* [hlsdk-portable](https://github.com/FWGS/hlsdk-portable), [mdldec](../utils/mdldec), [opensource-mods.md](opensource-mods.md) maintainer and Xash3D FWGS [contributor](https://github.com/FWGS/xash3d-fwgs/commits?author=nekonomicon) (*BSD/clang port, PNG support, etc).
|
||||
* Boosty page: https://boosty.to/nekonomicon
|
||||
|
||||
[hlsdk-portable](https://github.com/FWGS/hlsdk-portable), [mdldec](../utils/mdldec), [opensource-mods.md](opensource-mods.md) maintainer and Xash3D FWGS [contributor](https://github.com/FWGS/xash3d-fwgs/commits?author=nekonomicon) (*BSD/clang port, PNG support, etc).
|
||||
### [Velaron](https://github.com/Velaron)
|
||||
* [cs16-client](https://github.com/Velaron/cs16-client) & [tf15-client](https://github.com/Velaron/tf15-client) maintainer and Xash3D FWGS [contributor](https://github.com/FWGS/xash3d-fwgs/commits?author=Velaron) (Android port, voice chat, etc).
|
||||
* BuyMeACoffee page: https://www.buymeacoffee.com/velaron
|
||||
|
||||
* [Boosty page](https://boosty.to/nekonomicon)
|
||||
|
||||
## [Velaron](https://github.com/Velaron)
|
||||
|
||||
[cs16-client](https://github.com/Velaron/cs16-client) & [tf15-client](https://github.com/Velaron/tf15-client) maintainer and Xash3D FWGS [contributor](https://github.com/FWGS/xash3d-fwgs/commits?author=Velaron) (Android port, voice chat, etc).
|
||||
|
||||
* [BuyMeACoffee page](https://www.buymeacoffee.com/velaron)
|
||||
|
||||
## [SNMetamorph](https://github.com/SNMetamorph)
|
||||
|
||||
[PrimeXT](https://github.com/SNMetamorph/PrimeXT) & [GoldSrc Monitor](https://github.com/SNMetamorph/goldsrc-monitor) maintainer and Xash3D FWGS [contributor](https://github.com/FWGS/xash3d-fwgs/commits?author=SNMetamorph) (Windows port, voice chat, etc).
|
||||
|
||||
* [Boosty page](https://boosty.to/snmetamorph)
|
||||
* [Other donation methods](https://snmetamorph.github.io/donate)
|
||||
### [SNMetamorph](https://github.com/SNMetamorph)
|
||||
* [PrimeXT](https://github.com/SNMetamorph/PrimeXT) & [GoldSrc Monitor](https://github.com/SNMetamorph/goldsrc-monitor) maintainer and Xash3D FWGS [contributor](https://github.com/FWGS/xash3d-fwgs/commits?author=SNMetamorph) (Windows port, voice chat, etc).
|
||||
* BTC: `16GAzK3qei5AwBW7sggXp3yNcFHBtdpxXj`
|
||||
* ETH (ERC20): `0xb580eeca9756e3881f9d6d026e28db28eb72a383`
|
||||
* USDT (ERC20): `0xb580eeca9756e3881f9d6d026e28db28eb72a383`
|
||||
* USDC (ERC20): `0xb580eeca9756e3881f9d6d026e28db28eb72a383`
|
||||
|
||||
@@ -6,7 +6,7 @@ For connecting to GoldSrc-based servers, use this command:
|
||||
connect ip:port gs
|
||||
```
|
||||
|
||||
But keep in mind, there are requirement for server to be able to accept connections from Xash3D-based clients: it should use Reunion.
|
||||
But keep in mind, there are requirement for server to be able to accept connections from Xash3D-based clients: it should use Reunion or Dproto.
|
||||
Without this requirement, you will just get "Steam validation rejected" error on connecting.
|
||||
|
||||
That is because proper authorization with Steam API is not implemented in engine yet (but we have plans on it).
|
||||
|
||||
|
Before Width: | Height: | Size: 1.4 MiB |
|
Before Width: | Height: | Size: 82 KiB |
|
Before Width: | Height: | Size: 212 KiB |
|
Before Width: | Height: | Size: 400 KiB |
|
Before Width: | Height: | Size: 1.2 MiB |
|
Before Width: | Height: | Size: 1.4 MiB |
|
Before Width: | Height: | Size: 1.2 MiB |
|
Before Width: | Height: | Size: 1.1 MiB |
@@ -2,19 +2,10 @@
|
||||
|
||||
|Name |Version |Why not working |What was made for that
|
||||
|---- |------- |--------------- |----------------------
|
||||
|Area 51 |Update 1 |Uses outdated BSP31 map format and custom HLFX SDK libraries. |You can try [this tool](https://hlfx.ru/forum/showthread.php?threadid=5250) to convert maps but there no warranty if it works.
|
||||
|Arrange Mod: Rebirth |v150 |No idea yet. |
|
||||
|Blue Shift |The latest steam release |Uses vgui2 library which xash3d does not support. |Recreated source code here: https://github.com/FWGS/hlsdk-xash3d/tree/bshift.
|
||||
|Counter Strike |Beta 6.5- |Uses an old WON HL 1.0.0.16- interface. |
|
||||
| |1.4 |Has encrypted blob instead of normal client.dll. |You can try [this tool](https://aluigi.altervista.org/papers/hldlldec.zip) to decrypt client.dll but there no warranty if it works.
|
||||
| |1.5 |Has encrypted blob instead of normal client.dll. |Decrypted blob here: https://csm.dev/threads/cs-1-5-client-dll-decrypted-patched-for-usage.38845.
|
||||
| |1.6(The latest steam release) |Uses vgui2 library which xash3d does not support. |Some work on vgui2 support was made here: https://github.com/FWGS/xash3d/tree/vinterface. Recreated Client Source Code here: https://github.com/Velaron/cs16-client.
|
||||
|Counter Strike: Condition Zero |The latest steam release |Uses vgui2 library which xash3d does not support. |Some work on vgui2 support was made here: https://github.com/FWGS/xash3d/tree/vinterface. Recreated Client Source Code here: https://github.com/Velaron/cs16-client.
|
||||
|Counter Strike: Condition Zero - Deleted scenes |The latest steam release |Uses vgui2 library which xash3d does not support. Uses new sequences code on engine-side that was never used in any other mods before. |Some work on vgui2 support was made here: https://github.com/FWGS/xash3d/tree/vinterface.
|
||||
|Day of Defeat |The latest steam release |Uses vgui2 library which xash3d does not support. |Some work on vgui2 support was made here: https://github.com/FWGS/xash3d/tree/vinterface.
|
||||
|Half-Life: Extended |Day One demo |Uses many hooks to GoldSource engine and version check. |Just wait new version or use more old version.
|
||||
|Icon of Hell |Beta 0.99 |Uses outdated BSP31 map format and paranoia 2 libraries. |You can try [this tool](https://hlfx.ru/forum/showthread.php?threadid=5250) to convert maps and use Paranoia 2: The Savior 1.51 libraries but there no warranty if it works.
|
||||
|Paranoia 2: The Savior |All builds older 1.51 |Uses an old renderer interface and engine features. |
|
||||
|Rebellion |1.0 |Uses an old WON HL 1.0.0.16- interface. |Recreated source code here: https://github.com/FWGS/hlsdk-xash3d/tree/rebellion.
|
||||
|Sven-Coop |5.0+ |Uses custom GoldSrc engine. |
|
||||
|Time Shadows |Beta 0.1 |Uses Direct3D renderer. |
|
||||
|Blue Shift |The latest steam release |Uses vgui2 library which xash3d does not support |Recreated source code here: https://github.com/FWGS/hlsdk-xash3d/tree/bshift
|
||||
|Counter Strike |1.6(The latest steam release) |Uses vgui2 library which xash3d does not support |Some work on vgui2 support was made here: https://github.com/FWGS/xash3d/tree/vinterface
|
||||
|Counter Strike: Condition Zero |The latest steam release |Uses vgui2 library which xash3d does not support |Some work on vgui2 support was made here: https://github.com/FWGS/xash3d/tree/vinterface
|
||||
|Counter Strike: Condition Zero - Deleted scenes |The latest steam release |Uses vgui2 library which xash3d does not support |Some work on vgui2 support was made here: https://github.com/FWGS/xash3d/tree/vinterface
|
||||
|Day of Defeat |The latest steam release |Uses vgui2 library which xash3d does not support |Some work on vgui2 support was made here: https://github.com/FWGS/xash3d/tree/vinterface
|
||||
|Sven-Coop |5.0+ |Uses custom GoldSrc engine |
|
||||
|
||||
|
||||
@@ -32,18 +32,12 @@ Version 1.9 mirrored on github - https://github.com/solidi/hl-mods/tree/master/c
|
||||
## Cold Ice Ressurection
|
||||
Mirrored on github - https://github.com/solidi/hl-mods/tree/master/cir
|
||||
|
||||
## Counter-Life
|
||||
Available on ModDB - https://www.moddb.com/mods/counter-life/downloads/cl-version-1-source-code
|
||||
|
||||
## Cthulhu
|
||||
Uploaded to github by Oleg Cherkasky - https://github.com/gunrunners-paradise/Cthulhu-HLmod-SDK
|
||||
|
||||
## 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
|
||||
|
||||
|
||||
@@ -2,14 +2,11 @@
|
||||
|
||||
### Prerequisites
|
||||
1. Make sure your PSVita is [set up to run homebrew applications](https://vita.hacks.guide/).
|
||||
2. Install [kubridge](https://github.com/TheOfficialFloW/kubridge/releases/). It is recommended to use kubridge version `0.1`, because other versions aren't tested, we don't know are they suitable or not.
|
||||
|
||||
Worth to notice, we got reports that automatic plugins management app EasyPlugin have issues with installing kubridge plugin, so it's better to install it manually: by copying `kubridge.suprx` to your taiHEN plugins folder (usually `ux0:/tai`, but could be `ur0:/tai`) and add it to your `config.txt`, for example:
|
||||
2. Install [kubridge](https://github.com/TheOfficialFloW/kubridge/releases/) by copying `kubridge.suprx` to your taiHEN plugins folder (usually `ux0:/tai`) and add it to your `config.txt`, for example:
|
||||
```
|
||||
*KERNEL
|
||||
ux0:tai/kubridge.skprx
|
||||
```
|
||||
|
||||
3. Install `libshacccg.suprx` by following [this guide](https://cimmerian.gitbook.io/vita-troubleshooting-guide/shader-compiler/extract-libshacccg.suprx).
|
||||
|
||||
### Installation
|
||||
|
||||
@@ -1,149 +0,0 @@
|
||||
# Touch controls configuring
|
||||
|
||||
## Introduction
|
||||
|
||||
Thanks to mittorn, we have the ability to fully customize the controls in Xash3D. The new config allows you to not only add and change control buttons, but also create custom menus. There is also a built-in visual editor available, which simplifies the customization process without the need for manual file editing.
|
||||
|
||||
## Editor mode usage
|
||||
|
||||
1. Launch Xash3D and start the game.
|
||||
2. To enter the edit mode, click on the gear icon (command `touch_enableedit`).
|
||||
3. In the edit mode, the grid is displayed. The number of cells can be changed with the command `touch_grid_count` (default is 50). The grid can be disabled with the command `touch_grid_enable 0`.
|
||||
|
||||
*Touch controls layout editor*
|
||||

|
||||
|
||||
*Touch profiles window*
|
||||

|
||||
|
||||
*Touch buttons parameters window*
|
||||

|
||||
|
||||
## Layout editor features
|
||||
|
||||
* **Moving buttons**: click on a button, drag it to the desired location, and release.
|
||||
* **Resizing buttons**: place your first finger on the top left corner of the button, and use your second finger to resize it.
|
||||
* **Hiding/showing buttons**: select the button (it will turn red), then use the menu:
|
||||
* **Close**: closes the editing mode (`touch_disableedit`).
|
||||
* **Reset**: resets the button to its default values.
|
||||
* **Hide/Show**: hides or shows the button (`touch_hide <name>` / `touch_show <name>`).
|
||||
|
||||
## Working with configuration files / console
|
||||
|
||||
All changes made in the visual editor are automatically saved to the touch profile file. The files are located in the `touch_profiles` folder inside game directory. The file name depends on the selected profile.
|
||||
|
||||
### Common commands in configuration files
|
||||
|
||||
```
|
||||
// Comment: lines starting with // are ignored.
|
||||
|
||||
// Swipe zones for movement. Specify how far you need to swipe to speed up.
|
||||
// The default values are set to be optimal for a small swipe to immediately walk quickly.
|
||||
touch_forwardzone "0.060000" ; touch_sidezone "0.060000"
|
||||
|
||||
// Sensitivity settings (pitch - horizontal, yaw - vertical).
|
||||
touch_pitch ; touch_yaw
|
||||
|
||||
// Grid settings (see above).
|
||||
touch_grid_count ; touch_grid_enable
|
||||
|
||||
// Draws a border around the button.
|
||||
touch_set_stroke <thickness> <c> <v> <e> <t>
|
||||
(<r> - red; <g> - green; <b> - blue; <a> - alpha/transparency)
|
||||
|
||||
// Show (1) or hide (0) client buttons.
|
||||
touch_setclientonly
|
||||
|
||||
// Removes all buttons from the screen.
|
||||
touch_removeall
|
||||
|
||||
// Shows all available buttons in the configuration file.
|
||||
touch_list
|
||||
|
||||
// Saves the config after editing. You can specify a new file name.
|
||||
touch_config_file command.cfg
|
||||
```
|
||||
|
||||
*The full list of buttons in the standard `touch.cfg` file, displayed in the console when using `touch_list`.*
|
||||

|
||||
|
||||
|
||||
## Adding new buttons
|
||||
|
||||
To add a new button, use the console command:
|
||||
|
||||
```
|
||||
touch_addbutton "digits" "touch/key_1.png" "toggle_digits" 0.340000 0.782222 0.400000 0.888889 255 255 255 100 0
|
||||
```
|
||||
|
||||
### Parameters of `touch_addbutton` command
|
||||
|
||||
| Parameter | Description |
|
||||
| --- | --- |
|
||||
| `"digits"` | Unique name of the button. |
|
||||
| `"touch/key_1.png"` | Path to the icon file (`.png` format). If the icon is not needed, leave `""`. |
|
||||
| `"toggle_digits"` | Command to execute after clicking (for example, `"buy"` for purchase). |
|
||||
| `0.340000` | X coordinate of the upper-left corner of the button. |
|
||||
| `0.782222` | Y coordinate of the upper-left corner of the button. |
|
||||
| `0.400000` | X coordinate of the lower-right corner of the button. |
|
||||
| `0.888889` | Y coordinate of the lower-right corner of the button. |
|
||||
| `255 255 255` | Button color in RGB format. |
|
||||
| `100` | Button transparency (0 - fully transparent, 255 - fully opaque). |
|
||||
| `0` | Flags (see next section). |
|
||||
|
||||
## List of flags
|
||||
|
||||
Flags define the behavior of the button. Their values are powers of two:
|
||||
|
||||
| Flag | Value | Description |
|
||||
| --- | --- | --- |
|
||||
| `TOUCH_FL_HIDE` | 1 | Hides the button (not displayed in the game, but visible in the editor). |
|
||||
| `TOUCH_FL_NOEDIT` | 2 | Disables editing of the button in the editor. |
|
||||
| `TOUCH_FL_CLIENT` | 4 | The button is client-side (not saved in the main control file). |
|
||||
| `TOUCH_FL_MP` | 8 | The button is displayed only in multiplayer. |
|
||||
| `TOUCH_FL_SP` | 16 | The button is displayed only in singleplayer. |
|
||||
| `TOUCH_FL_DEF_SHOW` | 32 | The button is always displayed on startup. |
|
||||
| `TOUCH_FL_DEF_HIDE` | 64 | The button is always hidden on startup. |
|
||||
| `TOUCH_FL_DRAW_ADDITIVE` | 128 | The button colors are added together in blend mode. |
|
||||
| `TOUCH_FL_STROKE` | 256 | Enables outline stroke around the button. |
|
||||
|
||||
Flags can be combined by adding their values together. For example, `5 = 1 + 4` is the combination of `TOUCH_FL_HIDE` and `TOUCH_FL_CLIENT` flags, which is a hidden client button.
|
||||
|
||||
*In the image below, the `spray`, `scores`, `messagemode` buttons are displayed simultaneously with the flag 8 and `loadquick`, `savequick` with the flag 16, and each is displayed in the corresponding game mode.*
|
||||

|
||||
|
||||
## Useful commands
|
||||
|
||||
* `touch_hide <pattern>`: hides buttons by pattern.
|
||||
* `touch_setcommand`: changes the command bound to a button.
|
||||
* `touch_settexture`: quickly changes the button image.
|
||||
* `touch_setcolor`: sets the button color.
|
||||
* `touch_exportconfig`: exports the current configuration, including aspect ratio.
|
||||
|
||||
## Usage examples
|
||||
|
||||
* `touch_hide menu*` hides all buttons with names starting with `menu`.
|
||||
* `touch_setcolor "attack" 255 160 0 128` changes the color of the primary fire button from opaque white to translucent orange, similar to the color of the HUD in Half-Life.
|
||||
|
||||
*Result of executing this command*
|
||||

|
||||
|
||||
* Example of adding a new button with a custom icon (the `lastinv` command is used - quick change between weapons)
|
||||

|
||||
|
||||
*View of this button in layout editor*
|
||||

|
||||
|
||||
## Tips
|
||||
|
||||
* To prevent the `look` and `move` buttons from interfering with editing other elements, place them before the others in the configuration file.
|
||||
* And vice versa, to make a button appear on top of others, place it at the end of the configuration file.
|
||||
* You can assign commands to buttons that change other buttons, see the previous section "Usage examples".
|
||||
* After editing each parameter of each individual button in the Touch Buttons section, do not forget to press Save, otherwise the applied parameters will not be saved.
|
||||
* To create your own icon for the button, you can use any graphics editor (for Android, Photo Editor by iudesk is suitable). Saving conditions:
|
||||
* Image format - `.png` with transparency (e.g. alpha channel)
|
||||
* Aspect ratio / size - 1:1 / 256x256
|
||||
* Path to the icons location - `touch/gfx` inside game directory.
|
||||
|
||||
### Additional links
|
||||
* [Handy palette for selecting color in RGB format](https://www.rapidtables.com/web/color/RGB_Color.html)
|
||||
15
README.md
@@ -1,7 +1,6 @@
|
||||
# Xash3D FWGS Engine <img align="right" width="128" height="128" src="https://github.com/FWGS/xash3d-fwgs/raw/master/game_launch/icon-xash-material.png" alt="Xash3D FWGS icon" />
|
||||
[](https://github.com/FWGS/xash3d-fwgs/actions/workflows/c-cpp.yml) [](https://cirrus-ci.com/github/FWGS/xash3d-fwgs) \
|
||||
[](http://fwgsdiscord.mentality.rip/) [](https://t.me/flyingwithgauss) \
|
||||
[](https://github.com/FWGS/xash3d-fwgs/releases/tag/continuous)
|
||||
[](https://builds.sr.ht/~a1batross/xash3d-fwgs?) [](https://github.com/FWGS/xash3d-fwgs/actions/workflows/c-cpp.yml) [](https://cirrus-ci.com/github/FWGS/xash3d-fwgs) [](http://fwgsdiscord.mentality.rip/) \
|
||||
[](https://github.com/FWGS/xash3d-fwgs/releases/latest) [](https://github.com/FWGS/xash3d-fwgs/releases/tag/continuous)
|
||||
|
||||
Xash3D ([pronounced](https://ipa-reader.com/?text=ks%C9%91%CA%82) `[ksɑʂ]`) FWGS is a game engine, aimed to provide compatibility with Half-Life Engine and extend it, as well as to give game developers well known workflow.
|
||||
|
||||
@@ -44,7 +43,7 @@ For additional info, run Xash3D with `-help` command line key.
|
||||
## Build instructions
|
||||
We are using Waf build system. If you have some Waf-related questions, I recommend you to read [Waf Book](https://waf.io/book/).
|
||||
|
||||
**NOTE: NEVER USE GitHub's ZIP ARCHIVES. GitHub doesn't include external dependencies we're using!**
|
||||
NOTE: NEVER USE GitHub's ZIP ARCHIVES. GitHub doesn't include external dependencies we're using!
|
||||
|
||||
### Prerequisites
|
||||
If your CPU is x86 compatible and you're on Windows or Linux, we are building 32-bit code by default. This was done to maintain compatibility with Steam releases of Half-Life and based on it's engine games.
|
||||
@@ -66,21 +65,21 @@ This repository contains our fork of HLSDK and restored source code for Half-Lif
|
||||
* Only for 32-bit engine on 64-bit x86 operating system:
|
||||
* Enable i386 on your system: `$ sudo dpkg --add-architecture i386`.
|
||||
* Install `aptitude` ([why?](https://github.com/FWGS/xash3d-fwgs/issues/1828#issuecomment-2415131759)): `$ sudo apt update && sudo apt upgrade && sudo apt install aptitude`
|
||||
* Install development tools: `$ sudo aptitude --without-recommends install git build-essential gcc-multilib g++-multilib libsdl2-dev:i386 libfreetype-dev:i386 libopus-dev:i386 libbz2-dev:i386 libvorbis-dev:i386 libopusfile-dev:i386 libogg-dev:i386`.
|
||||
* Install development tools: `$ sudo aptitude --without-recommends install git build-essential gcc-multilib g++-multilib libsdl2-dev:i386 libfontconfig-dev:i386 libfreetype-dev:i386 libopus-dev:i386 libbz2-dev:i386`.
|
||||
* Set PKG_CONFIG_PATH environment variable to point at 32-bit libraries: `$ export PKG_CONFIG_PATH=/usr/lib/i386-linux-gnu/pkgconfig`.
|
||||
|
||||
* For 64-bit engine on 64-bit x86 and other non-x86 systems:
|
||||
* Install development tools: `$ sudo apt install git build-essential python libsdl2-dev libfreetype6-dev libopus-dev libbz2-dev libvorbis-dev libopusfile-dev libogg-dev`.
|
||||
* Install development tools: `$ sudo apt install git build-essential python libsdl2-dev libfontconfig-dev libfreetype6-dev libopus-dev libbz2-dev`.
|
||||
|
||||
* Clone this repostory: `$ git clone --recursive https://github.com/FWGS/xash3d-fwgs`.
|
||||
|
||||
##### RedHat/Fedora
|
||||
* Only for 32-bit engine on 64-bit x86 operating system:
|
||||
* Install development tools: `$ sudo dnf install git gcc gcc-c++ glibc-devel.i686 SDL2-devel.i686 opus-devel.i686 freetype-devel.i686 bzip2-devel.i686 libvorbis-devel.i686 opusfile-devel.i686 libogg-devel.i686`.
|
||||
* Install development tools: `$ sudo dnf install git gcc gcc-c++ glibc-devel.i686 SDL2-devel.i686 opus-devel.i686 fontconfig-devel.i686 freetype-devel.i686 bzip2-devel.i686`.
|
||||
* Set PKG_CONFIG_PATH environment variable to point at 32-bit libraries: `$ export PKG_CONFIG_PATH=/usr/lib/pkgconfig`.
|
||||
|
||||
* For 64-bit engine on 64-bit x86 and other non-x86 systems:
|
||||
* Install development tools: `$ sudo dnf install git gcc gcc-c++ SDL2-devel opus-devel freetype-devel bzip2-devel libvorbis-devel opusfile-devel libogg-devel`.
|
||||
* Install development tools: `$ sudo dnf install git gcc gcc-c++ SDL2-devel opus-devel fontconfig-devel freetype-devel bzip2-devel`.
|
||||
|
||||
* Clone this repostory: `$ git clone --recursive https://github.com/FWGS/xash3d-fwgs`.
|
||||
|
||||
|
||||
@@ -1,39 +1,49 @@
|
||||
cmake_minimum_required(VERSION 3.22)
|
||||
cmake_minimum_required(VERSION 3.6)
|
||||
|
||||
# Only used to build Android project
|
||||
|
||||
project(XASH_ANDROID)
|
||||
|
||||
# armeabi-v7a requires cpufeatures library
|
||||
if(ANDROID)
|
||||
include_directories(${ANDROID_NDK}/sources/android/cpufeatures)
|
||||
add_library(cpufeatures ${ANDROID_NDK}/sources/android/cpufeatures/cpu-features.c)
|
||||
target_link_libraries(cpufeatures dl)
|
||||
endif()
|
||||
include(AndroidNdkModules)
|
||||
android_ndk_import_module_cpufeatures()
|
||||
|
||||
include(FindPython)
|
||||
find_package(PythonInterp 2.7 REQUIRED)
|
||||
|
||||
get_filename_component(C_COMPILER_ID ${CMAKE_C_COMPILER} NAME_WE)
|
||||
get_filename_component(CXX_COMPILER_ID ${CMAKE_CXX_COMPILER} NAME_WE)
|
||||
|
||||
if("${CMAKE_BUILD_TYPE}" STREQUAL "Debug")
|
||||
set(BUILD_TYPE "debug")
|
||||
else()
|
||||
set(BUILD_TYPE "release")
|
||||
list(APPEND WAF_EXTRA_ARGS --enable-poly-opt --enable-lto --enable-limited-debuginfo)
|
||||
list(APPEND WAF_EXTRA_ARGS --enable-poly-opt --enable-lto)
|
||||
endif()
|
||||
|
||||
if(ANDROID_ABI STREQUAL "x86")
|
||||
# HACKHACK: I don't know why but engine gets built as 64-bit binary here
|
||||
list(APPEND WAF_EXTRA_ARGS -4)
|
||||
if(CMAKE_SIZEOF_VOID_P MATCHES "8")
|
||||
set(64BIT ON CACHE BOOL "" FORCE)
|
||||
list(APPEND WAF_EXTRA_ARGS -8) # only required for x86 when testing this cmakelist under linux
|
||||
endif()
|
||||
|
||||
set(CMAKE_VERBOSE_MAKEFILE ON)
|
||||
|
||||
set(WAF_CC "${CMAKE_C_COMPILER} --target=${CMAKE_C_COMPILER_TARGET}")
|
||||
set(WAF_CXX "${CMAKE_CXX_COMPILER} --target=${CMAKE_CXX_COMPILER_TARGET}")
|
||||
|
||||
# not cleanest way to get upper directory
|
||||
set(ENGINE_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../")
|
||||
|
||||
set(WAF_CC "${CMAKE_C_COMPILER} --target=${CMAKE_C_COMPILER_TARGET}")
|
||||
set(WAF_CXX "${CMAKE_CXX_COMPILER} --target=${CMAKE_CXX_COMPILER_TARGET}")
|
||||
set(WAF ${Python_EXECUTABLE} ${ENGINE_SOURCE_DIR}waf -t ${ENGINE_SOURCE_DIR} -o ${CMAKE_CURRENT_BINARY_DIR}/xash3d-fwgs)
|
||||
execute_process(
|
||||
COMMAND ${CMAKE_COMMAND} -E env
|
||||
CC=${WAF_CC} CXX=${WAF_CXX}
|
||||
AR=${CMAKE_AR} STRIP=${CMAKE_STRIP}
|
||||
${PYTHON_EXECUTABLE} waf configure -T ${BUILD_TYPE} ${WAF_EXTRA_ARGS} cmake
|
||||
--check-c-compiler=${C_COMPILER_ID} --check-cxx-compiler=${CXX_COMPILER_ID}
|
||||
-s "${ENGINE_SOURCE_DIR}/SDL" --skip-sdl2-sanity-check --enable-bundled-deps
|
||||
WORKING_DIRECTORY "${ENGINE_SOURCE_DIR}"
|
||||
)
|
||||
|
||||
add_subdirectory("${ENGINE_SOURCE_DIR}/3rdparty/hlsdk-portable" hlsdk-portable)
|
||||
|
||||
# try to build minimal SDL. Enable features as we're gonna use them
|
||||
set(SDL_RENDER OFF)
|
||||
@@ -46,50 +56,5 @@ set(SDL_VULKAN OFF)
|
||||
set(SDL_OFFSCREEN OFF)
|
||||
set(SDL_STATIC OFF)
|
||||
add_subdirectory("${ENGINE_SOURCE_DIR}/3rdparty/SDL" SDL)
|
||||
|
||||
include(ExternalProject)
|
||||
|
||||
# gradle passes backslashes to cmake, how does this even work for everybody else?
|
||||
string(REPLACE "\\" "/" CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_LIBRARY_OUTPUT_DIRECTORY})
|
||||
|
||||
ExternalProject_Add(
|
||||
Xash3DFWGS
|
||||
SOURCE_DIR ${ENGINE_SOURCE_DIR}
|
||||
INSTALL_DIR ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}
|
||||
BUILD_IN_SOURCE TRUE
|
||||
DEPENDS SDL2
|
||||
BUILD_ALWAYS TRUE
|
||||
LOG_CONFIGURE TRUE
|
||||
LOG_BUILD TRUE
|
||||
LOG_INSTALL TRUE
|
||||
LOG_OUTPUT_ON_FAILURE TRUE
|
||||
LOG_MERGED_STDOUTERR TRUE
|
||||
|
||||
# USES_TERMINAL_CONFIGURE TRUE
|
||||
# USES_TERMINAL_BUILD TRUE
|
||||
# USES_TERMINAL_INSTALL TRUE
|
||||
|
||||
# NOTE: setting up WAFLOCK is important to avoid possible race conditions
|
||||
CONFIGURE_COMMAND ${CMAKE_COMMAND} -E env
|
||||
ANDROID_NDK=${ANDROID_NDK}
|
||||
BUILD_CMAKE_LIBRARY_OUTPUT_DIRECTORY=${CMAKE_LIBRARY_OUTPUT_DIRECTORY}
|
||||
WAFLOCK=.lock-waf_android_${ANDROID_ABI}_build
|
||||
${WAF} configure -T ${BUILD_TYPE} --android=${ANDROID_ABI},,${CMAKE_SYSTEM_VERSION}
|
||||
-s "${ENGINE_SOURCE_DIR}/3rdparty/SDL" --enable-bundled-deps ${WAF_EXTRA_ARGS}
|
||||
|
||||
BUILD_COMMAND ${CMAKE_COMMAND} -E env
|
||||
WAFLOCK=.lock-waf_android_${ANDROID_ABI}_build
|
||||
${WAF} build -v
|
||||
|
||||
INSTALL_COMMAND ${CMAKE_COMMAND} -E env
|
||||
WAFLOCK=.lock-waf_android_${ANDROID_ABI}_build
|
||||
${WAF} install --destdir=${CMAKE_LIBRARY_OUTPUT_DIRECTORY}
|
||||
)
|
||||
|
||||
add_subdirectory("${ENGINE_SOURCE_DIR}/3rdparty/hlsdk-portable" hlsdk-portable)
|
||||
|
||||
# a1ba: without this, xash3d target will be ignored as nothing depends on it
|
||||
add_dependencies(client Xash3DFWGS)
|
||||
add_dependencies(server Xash3DFWGS)
|
||||
|
||||
|
||||
add_subdirectory("${ENGINE_SOURCE_DIR}/" xash3d-fwgs)
|
||||
add_subdirectory("${ENGINE_SOURCE_DIR}/3rdparty/mainui" mainui)
|
||||
|
||||
@@ -9,7 +9,7 @@ plugins {
|
||||
|
||||
android {
|
||||
namespace = "su.xash.engine"
|
||||
ndkVersion = "28.0.13004108"
|
||||
ndkVersion = "27.2.12479018"
|
||||
|
||||
defaultConfig {
|
||||
applicationId = "su.xash"
|
||||
@@ -96,7 +96,6 @@ android {
|
||||
packaging {
|
||||
jniLibs {
|
||||
useLegacyPackaging = true
|
||||
keepDebugSymbols.add("**/*.so")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -113,7 +112,7 @@ dependencies {
|
||||
implementation("androidx.preference:preference-ktx:1.2.1")
|
||||
implementation("androidx.swiperefreshlayout:swiperefreshlayout:1.1.0")
|
||||
implementation("androidx.work:work-runtime-ktx:2.9.0")
|
||||
// implementation "androidx.legacy:legacy-support-v4:1.0.0"
|
||||
// implementation "androidx.legacy:legacy-support-v4:1.0.0"
|
||||
|
||||
implementation("com.madgag.spongycastle:prov:1.58.0.0")
|
||||
implementation("in.dragonbra:javasteam:1.2.0")
|
||||
|
||||
@@ -2,7 +2,6 @@ package su.xash.engine.ui.library
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Intent
|
||||
import android.content.ActivityNotFoundException
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import android.view.LayoutInflater
|
||||
@@ -11,7 +10,6 @@ import android.view.MenuInflater
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.Toast
|
||||
import androidx.core.view.MenuProvider
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.activityViewModels
|
||||
@@ -75,16 +73,11 @@ class LibraryFragment : Fragment(), MenuProvider {
|
||||
override fun onMenuItemSelected(menuItem: MenuItem): Boolean {
|
||||
when (menuItem.itemId) {
|
||||
R.id.action_browse -> {
|
||||
try {
|
||||
startActivity(
|
||||
Intent(Intent.ACTION_VIEW).setDataAndType(
|
||||
null, "vnd.android.document/directory"
|
||||
)
|
||||
startActivity(
|
||||
Intent(Intent.ACTION_VIEW).setDataAndType(
|
||||
null, "vnd.android.document/directory"
|
||||
)
|
||||
}
|
||||
catch(e: ActivityNotFoundException) {
|
||||
Toast.makeText(getActivity(), R.string.library_fragment_no_file_manager, Toast.LENGTH_LONG).show()
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
R.id.action_install -> {
|
||||
@@ -98,4 +91,4 @@ class LibraryFragment : Fragment(), MenuProvider {
|
||||
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -33,5 +33,4 @@
|
||||
<string name="preferences_client_package">Client package</string>
|
||||
<string name="preferences_server_package">Server package</string>
|
||||
<string name="preferences_use_icons">Use icons instead of backgrounds</string>
|
||||
<string name="library_fragment_no_file_manager">File manager is missing</string>
|
||||
</resources>
|
||||
</resources>
|
||||
@@ -20,7 +20,4 @@ kotlin.code.style=official
|
||||
# Enables namespacing of each library's R class so that its R class includes only the
|
||||
# resources declared in the library itself and none from the library's dependencies,
|
||||
# thereby reducing the size of the R class for that library
|
||||
android.nonTransitiveRClass=true
|
||||
|
||||
# Enable verbose output for CMake
|
||||
android.native.buildOutput=verbose
|
||||
android.nonTransitiveRClass=true
|
||||
@@ -50,4 +50,8 @@ GNU General Public License for more details.
|
||||
#define LIB_WIN32 2
|
||||
#define LIB_STATIC 3
|
||||
|
||||
// movies (XASH_AVI)
|
||||
#define AVI_NULL 0
|
||||
#define AVI_FFMPEG 1
|
||||
|
||||
#endif /* BACKENDS_H */
|
||||
|
||||
@@ -78,7 +78,6 @@ SETUP BACKENDS DEFINITIONS
|
||||
// usually only 10-20 fds availiable
|
||||
#define XASH_REDUCE_FD
|
||||
#endif
|
||||
|
||||
#endif // XASH_DEDICATED
|
||||
|
||||
//
|
||||
@@ -105,6 +104,17 @@ SETUP BACKENDS DEFINITIONS
|
||||
#endif // !XASH_WIN32
|
||||
#endif
|
||||
|
||||
//
|
||||
// determine movie playback backend
|
||||
//
|
||||
#ifndef XASH_AVI
|
||||
#if HAVE_FFMPEG
|
||||
#define XASH_AVI AVI_FFMPEG
|
||||
#else
|
||||
#define XASH_AVI AVI_NULL
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef XASH_STATIC_LIBS
|
||||
#define XASH_LIB LIB_STATIC
|
||||
#define XASH_INTERNAL_GAMELIBS
|
||||
@@ -140,13 +150,13 @@ Default build-depended cvar and constant values
|
||||
|
||||
// Platform overrides
|
||||
#if XASH_NSWITCH
|
||||
#define DEFAULT_TOUCH_ENABLE "1"
|
||||
#define DEFAULT_TOUCH_ENABLE "0"
|
||||
#define DEFAULT_M_IGNORE "1"
|
||||
#define DEFAULT_MODE_WIDTH 1280
|
||||
#define DEFAULT_MODE_HEIGHT 720
|
||||
#define DEFAULT_ALLOWCONSOLE 1
|
||||
#elif XASH_PSVITA
|
||||
#define DEFAULT_TOUCH_ENABLE "1"
|
||||
#define DEFAULT_TOUCH_ENABLE "0"
|
||||
#define DEFAULT_M_IGNORE "1"
|
||||
#define DEFAULT_MODE_WIDTH 960
|
||||
#define DEFAULT_MODE_HEIGHT 544
|
||||
@@ -158,7 +168,7 @@ Default build-depended cvar and constant values
|
||||
#define DEFAULT_M_IGNORE "1"
|
||||
#endif // !XASH_MOBILE_PLATFORM && !XASH_NSWITCH
|
||||
|
||||
#if (XASH_ANDROID && !XASH_TERMUX) || XASH_IOS || XASH_EMSCRIPTEN
|
||||
#if XASH_ANDROID || XASH_IOS || XASH_EMSCRIPTEN
|
||||
// this means that libraries are provided with engine, but not in game data
|
||||
// You need add library loading code to library.c when adding new platform
|
||||
#define XASH_INTERNAL_GAMELIBS
|
||||
|
||||
@@ -28,17 +28,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#define PORT_ANY -1
|
||||
|
||||
typedef enum netadrtype_e
|
||||
{
|
||||
NA_UNDEFINED = 0,
|
||||
NA_LOOPBACK,
|
||||
NA_BROADCAST,
|
||||
NA_IP,
|
||||
NA_IPX,
|
||||
NA_BROADCAST_IPX,
|
||||
NA_IP6,
|
||||
NA_MULTICAST_IP6
|
||||
} netadrtype_t;
|
||||
typedef enum {NA_LOOPBACK = 1, NA_BROADCAST, NA_IP, NA_IPX, NA_BROADCAST_IPX, NA_IP6, NA_MULTICAST_IP6} netadrtype_t;
|
||||
|
||||
/*
|
||||
Original Quake-2 structure:
|
||||
@@ -56,60 +46,29 @@ typedef struct
|
||||
#pragma pack( push, 1 )
|
||||
typedef struct netadr_s
|
||||
{
|
||||
// the reason we do this evil thing, is that when this struct contains IPv6
|
||||
// address the `type` is 2-byte wide, but when it doesn't `type` must 4-byte
|
||||
// wide _and_ ip6_0 must be zeroed, to keep it binary compatible.
|
||||
#if XASH_LITTLE_ENDIAN
|
||||
uint16_t type;
|
||||
uint8_t ip6_0[2];
|
||||
#elif XASH_BIG_ENDIAN
|
||||
uint8_t ip6_0[2];
|
||||
uint16_t type;
|
||||
#else
|
||||
#error
|
||||
#endif
|
||||
|
||||
union
|
||||
{
|
||||
// IPv6 struct
|
||||
uint8_t ip6_1[14];
|
||||
struct
|
||||
{
|
||||
uint16_t type6;
|
||||
uint8_t ip6[16];
|
||||
};
|
||||
struct
|
||||
{
|
||||
uint32_t type; // must be netadrtype_t but will break with short enums
|
||||
union
|
||||
{
|
||||
uint8_t ip[4];
|
||||
uint32_t ip4; // for easier conversions
|
||||
uint8_t ip[4];
|
||||
uint32_t ip4; // for easier conversions
|
||||
};
|
||||
uint8_t ipx[10];
|
||||
};
|
||||
};
|
||||
uint16_t port;
|
||||
uint16_t port;
|
||||
} netadr_t;
|
||||
#pragma pack( pop )
|
||||
|
||||
static inline netadrtype_t NET_NetadrType( const netadr_t *a )
|
||||
{
|
||||
if( a->type == NA_IP6 || a->type == NA_MULTICAST_IP6 )
|
||||
return (netadrtype_t)a->type;
|
||||
|
||||
if( a->ip6_0[0] || a->ip6_0[1] )
|
||||
return NA_UNDEFINED;
|
||||
|
||||
return (netadrtype_t)a->type;
|
||||
}
|
||||
|
||||
static inline void NET_NetadrSetType( netadr_t *a, netadrtype_t type )
|
||||
{
|
||||
if( type == NA_IP6 || type == NA_MULTICAST_IP6 )
|
||||
{
|
||||
a->type = type;
|
||||
return;
|
||||
}
|
||||
|
||||
a->ip6_0[0] = a->ip6_0[1] = 0;
|
||||
a->type = type;
|
||||
}
|
||||
|
||||
STATIC_CHECK_SIZEOF( netadr_t, 20, 20 );
|
||||
|
||||
#endif // NET_ADR_H
|
||||
|
||||
@@ -86,4 +86,8 @@ GNU General Public License for more details.
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
|
||||
#if defined XASH_SDL && !defined REF_DLL
|
||||
#include <SDL.h>
|
||||
#endif
|
||||
|
||||
#endif // PORT_H
|
||||
|
||||
@@ -157,6 +157,23 @@ typedef struct decallist_s
|
||||
modelstate_t studio_state; // studio decals only
|
||||
} decallist_t;
|
||||
|
||||
enum movie_parms_e
|
||||
{
|
||||
AVI_PARM_LAST = 0, // marker for SetParm to end parse parsing arguments
|
||||
AVI_RENDER_TEXNUM, // (int) sets texture to draw into, if 0 will draw to screen
|
||||
AVI_RENDER_X, // (int) when set to screen, sets position where to draw
|
||||
AVI_RENDER_Y,
|
||||
AVI_RENDER_W, // (int) sets texture or screen width
|
||||
AVI_RENDER_H, // set to -1 to draw full screen
|
||||
AVI_REWIND, // no argument, rewind playback to the beginning
|
||||
AVI_ENTNUM, // (int) entity number, -1 for no spatialization
|
||||
AVI_VOLUME, // (int) volume from 0 to 255
|
||||
AVI_ATTN, // (float) attenuation value
|
||||
AVI_PAUSE, // no argument, pauses playback
|
||||
AVI_RESUME, // no argument, resumes playback
|
||||
};
|
||||
|
||||
struct movie_state_s;
|
||||
struct ref_viewpass_s;
|
||||
|
||||
typedef struct render_api_s
|
||||
@@ -193,16 +210,16 @@ typedef struct render_api_s
|
||||
void (*R_EntityRemoveDecals)( struct model_s *mod ); // remove all the decals from specified entity (BSP only)
|
||||
|
||||
// AVIkit support
|
||||
void *(*AVI_LoadVideo)( const char *filename, qboolean load_audio );
|
||||
int (*AVI_GetVideoInfo)( void *Avi, int *xres, int *yres, float *duration ); // a1ba: changed longs to int
|
||||
int (*AVI_GetVideoFrameNumber)( void *Avi, float time );
|
||||
byte *(*AVI_GetVideoFrame)( void *Avi, int frame );
|
||||
struct movie_state_s *(*AVI_LoadVideo)( const char *filename, qboolean load_audio );
|
||||
qboolean (*AVI_GetVideoInfo)( struct movie_state_s *Avi, int *xres, int *yres, float *duration ); // a1ba: changed longs to int
|
||||
int (*AVI_GetVideoFrameNumber)( struct movie_state_s *Avi, float time );
|
||||
byte *(*AVI_GetVideoFrame)( struct movie_state_s *Avi, int frame );
|
||||
void (*AVI_UploadRawFrame)( int texture, int cols, int rows, int width, int height, const byte *data );
|
||||
void (*AVI_FreeVideo)( void *Avi );
|
||||
int (*AVI_IsActive)( void *Avi );
|
||||
void (*AVI_StreamSound)( void *Avi, int entnum, float fvol, float attn, float synctime );
|
||||
void (*AVI_Reserved0)( void ); // for potential interface expansion without broken compatibility
|
||||
void (*AVI_Reserved1)( void );
|
||||
void (*AVI_FreeVideo)( struct movie_state_s *Avi );
|
||||
qboolean (*AVI_IsActive)( struct movie_state_s *Avi );
|
||||
void (*AVI_StreamSound)( struct movie_state_s *Avi, int entnum, float fvol, float attn, float synctime );
|
||||
qboolean (*AVI_Think)( struct movie_state_s *Avi );
|
||||
qboolean (*AVI_SetParm)( struct movie_state_s *Avi, enum movie_parms_e parm, ... );
|
||||
|
||||
// glState related calls (must use this instead of normal gl-calls to prevent de-synchornize local states between engine and the client)
|
||||
void (*GL_Bind)( int tmu, unsigned int texnum );
|
||||
|
||||
@@ -13,19 +13,13 @@
|
||||
#endif // _WIN32
|
||||
|
||||
#include <sys/types.h> // off_t
|
||||
#ifdef STDINT_H
|
||||
#include STDINT_H
|
||||
#else // !STDINT_H
|
||||
#include <stdint.h>
|
||||
#endif // !STDINT_H
|
||||
#include <assert.h>
|
||||
|
||||
typedef uint8_t byte;
|
||||
typedef float vec_t;
|
||||
typedef vec_t vec2_t[2];
|
||||
#ifndef vec3_t // SDK renames it to Vector
|
||||
typedef vec_t vec3_t[3];
|
||||
#endif
|
||||
typedef vec_t vec4_t[4];
|
||||
typedef vec_t quat_t[4];
|
||||
typedef byte rgba_t[4]; // unsigned byte colorpack
|
||||
@@ -37,11 +31,11 @@ typedef uint32_t poolhandle_t;
|
||||
#undef true
|
||||
#undef false
|
||||
|
||||
// true and false are keywords in C++ and C23
|
||||
#if !__cplusplus && __STDC_VERSION__ < 202311L
|
||||
enum { false, true };
|
||||
#endif
|
||||
#ifndef __cplusplus
|
||||
typedef enum { false, true } qboolean;
|
||||
#else
|
||||
typedef int qboolean;
|
||||
#endif
|
||||
|
||||
#define MAX_STRING 256 // generic string
|
||||
#define MAX_VA_STRING 1024 // compatibility macro
|
||||
@@ -50,7 +44,6 @@ typedef int qboolean;
|
||||
|
||||
#define BIT( n ) ( 1U << ( n ))
|
||||
#define BIT64( n ) ( 1ULL << ( n ))
|
||||
|
||||
#define SetBits( iBitVector, bits ) ((iBitVector) = (iBitVector) | (bits))
|
||||
#define ClearBits( iBitVector, bits ) ((iBitVector) = (iBitVector) & ~(bits))
|
||||
#define FBitSet( iBitVector, bit ) ((iBitVector) & (bit))
|
||||
@@ -67,8 +60,6 @@ typedef int qboolean;
|
||||
#define IsColorString( p ) ( p && *( p ) == '^' && *(( p ) + 1) && *(( p ) + 1) >= '0' && *(( p ) + 1 ) <= '9' )
|
||||
#define ColorIndex( c ) ((( c ) - '0' ) & 7 )
|
||||
|
||||
#undef EXPORT
|
||||
|
||||
#if defined( __GNUC__ )
|
||||
#if defined( __i386__ )
|
||||
#define EXPORT __attribute__(( visibility( "default" ), force_align_arg_pointer ))
|
||||
@@ -91,10 +82,8 @@ typedef int qboolean;
|
||||
#define NORETURN __attribute__(( noreturn ))
|
||||
#define NONNULL __attribute__(( nonnull ))
|
||||
#define RETURNS_NONNULL __attribute__(( returns_nonnull ))
|
||||
#if __clang__ || __MCST__
|
||||
// clang has bugged returns_nonnull for functions pointers, it's ignored and generates a warning about objective-c? O_o
|
||||
// lcc doesn't support it at all
|
||||
#define PFN_RETURNS_NONNULL
|
||||
#if __clang__
|
||||
#define PFN_RETURNS_NONNULL // clang has bugged returns_nonnull for functions pointers, it's ignored and generates a warning about objective-c? O_o
|
||||
#else
|
||||
#define PFN_RETURNS_NONNULL RETURNS_NONNULL
|
||||
#endif
|
||||
|
||||
@@ -18,12 +18,11 @@ GNU General Public License for more details.
|
||||
//
|
||||
// avikit.c
|
||||
//
|
||||
typedef struct movie_state_s movie_state_t;
|
||||
typedef struct movie_state_s movie_state_t;
|
||||
int AVI_GetVideoFrameNumber( movie_state_t *Avi, float time );
|
||||
byte *AVI_GetVideoFrame( movie_state_t *Avi, int frame );
|
||||
qboolean AVI_GetVideoInfo( movie_state_t *Avi, int *xres, int *yres, float *duration );
|
||||
qboolean AVI_GetAudioInfo( movie_state_t *Avi, wavdata_t *snd_info );
|
||||
int AVI_GetAudioChunk( movie_state_t *Avi, char *audiodata, int offset, int length );
|
||||
qboolean AVI_HaveAudioTrack( const movie_state_t *Avi );
|
||||
void AVI_OpenVideo( movie_state_t *Avi, const char *filename, qboolean load_audio, int quiet );
|
||||
movie_state_t *AVI_LoadVideo( const char *filename, qboolean load_audio );
|
||||
int AVI_TimeToSoundPosition( movie_state_t *Avi, int time );
|
||||
@@ -34,4 +33,7 @@ movie_state_t *AVI_GetState( int num );
|
||||
qboolean AVI_Initailize( void );
|
||||
void AVI_Shutdown( void );
|
||||
|
||||
qboolean AVI_SetParm( movie_state_t *Avi, enum movie_parms_e parm, ... );
|
||||
qboolean AVI_Think( movie_state_t *Avi );
|
||||
|
||||
#endif // AVI_H
|
||||
|
||||
761
engine/client/avi/avi_ffmpeg.c
Normal file
@@ -0,0 +1,761 @@
|
||||
/*
|
||||
avi_ffmpreg.c - playing AVI files (ffmpeg backend)
|
||||
Copyright (C) FTEQW developers (for plugins/avplug/avdecode.c)
|
||||
Copyright (C) Sam Lantinga (for tests/testffmpeg.c)
|
||||
Copyright (C) 2023-2024 Alibek Omarov
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include "defaults.h"
|
||||
#include "common.h"
|
||||
#include "client.h"
|
||||
|
||||
static qboolean avi_initialized;
|
||||
static poolhandle_t avi_mempool;
|
||||
|
||||
#if XASH_AVI == AVI_FFMPEG
|
||||
#include <libavformat/avformat.h>
|
||||
#include <libavcodec/avcodec.h>
|
||||
#include <libavutil/imgutils.h>
|
||||
#include <libswscale/swscale.h>
|
||||
#include <libswresample/swresample.h>
|
||||
|
||||
struct movie_state_s
|
||||
{
|
||||
// ffmpeg contexts
|
||||
AVFormatContext *fmt_ctx;
|
||||
AVCodecContext *video_ctx;
|
||||
AVCodecContext *audio_ctx;
|
||||
struct SwsContext *sws_ctx;
|
||||
struct SwrContext *swr_ctx;
|
||||
|
||||
AVPacket *pkt;
|
||||
AVFrame *aframe;
|
||||
AVFrame *vframe;
|
||||
AVFrame *vframe_copy;
|
||||
|
||||
int64_t first_time;
|
||||
int64_t last_time;
|
||||
|
||||
// video stream
|
||||
byte *dst;
|
||||
double duration;
|
||||
int video_stream;
|
||||
int xres;
|
||||
int yres;
|
||||
int dst_linesize;
|
||||
enum AVPixelFormat pix_fmt;
|
||||
|
||||
// rendering video parameters
|
||||
int x, y, w, h; // passed to R_DrawStretchRaw
|
||||
int texture; // passed to R_UploadStretchRaw
|
||||
|
||||
// audio stream
|
||||
int audio_stream;
|
||||
int channels;
|
||||
int rate;
|
||||
enum AVSampleFormat s_fmt;
|
||||
|
||||
byte *cached_audio;
|
||||
size_t cached_audio_buf_len; // absolute size of cached_audio array
|
||||
size_t cached_audio_len; // how many data in bytes we have in cached_audio array
|
||||
size_t cached_audio_pos; // how far we've read into cached_audio array
|
||||
|
||||
// rendering audio parameters
|
||||
float attn;
|
||||
int16_t entnum; // MAX_ENTITY_BITS is 13
|
||||
byte volume;
|
||||
byte active : 1;
|
||||
byte quiet : 1;
|
||||
byte paused : 1;
|
||||
};
|
||||
|
||||
qboolean AVI_SetParm( movie_state_t *Avi, enum movie_parms_e parm, ... )
|
||||
{
|
||||
qboolean ret = true;
|
||||
va_list va;
|
||||
va_start( va, parm );
|
||||
|
||||
while( parm != AVI_PARM_LAST )
|
||||
{
|
||||
float fval;
|
||||
int val;
|
||||
|
||||
switch( parm )
|
||||
{
|
||||
case AVI_RENDER_TEXNUM:
|
||||
Avi->texture = va_arg( va, int );
|
||||
break;
|
||||
case AVI_RENDER_X:
|
||||
Avi->x = va_arg( va, int );
|
||||
break;
|
||||
case AVI_RENDER_Y:
|
||||
Avi->y = va_arg( va, int );
|
||||
break;
|
||||
case AVI_RENDER_W:
|
||||
Avi->w = va_arg( va, int );
|
||||
break;
|
||||
case AVI_RENDER_H:
|
||||
Avi->h = va_arg( va, int );
|
||||
break;
|
||||
case AVI_REWIND:
|
||||
if( Avi->audio_ctx )
|
||||
avcodec_flush_buffers( Avi->audio_ctx );
|
||||
avcodec_flush_buffers( Avi->video_ctx );
|
||||
Avi->cached_audio_len = Avi->cached_audio_pos = 0;
|
||||
Avi->last_time = -1;
|
||||
Avi->first_time = 0;
|
||||
av_seek_frame( Avi->fmt_ctx, -1, 0, AVSEEK_FLAG_FRAME | AVSEEK_FLAG_BACKWARD );
|
||||
break;
|
||||
case AVI_ENTNUM:
|
||||
val = va_arg( va, int );
|
||||
Avi->entnum = bound( 0, val, MAX_EDICTS );
|
||||
break;
|
||||
case AVI_VOLUME:
|
||||
val = va_arg( va, int );
|
||||
Avi->volume = bound( 0, val, 255 );
|
||||
break;
|
||||
case AVI_ATTN:
|
||||
fval = va_arg( va, double );
|
||||
Avi->attn = Q_max( 0.0f, fval );
|
||||
break;
|
||||
case AVI_PAUSE:
|
||||
Avi->paused = true;
|
||||
break;
|
||||
case AVI_RESUME:
|
||||
Avi->paused = false;
|
||||
break;
|
||||
default:
|
||||
ret = false;
|
||||
}
|
||||
|
||||
parm = va_arg( va, enum movie_parms_e );
|
||||
}
|
||||
|
||||
va_end( va );
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void AVI_SpewError( qboolean quiet, const char *fmt, ... ) FORMAT_CHECK( 2 );
|
||||
static void AVI_SpewError( qboolean quiet, const char *fmt, ... )
|
||||
{
|
||||
char buf[MAX_VA_STRING];
|
||||
va_list va;
|
||||
|
||||
if( quiet )
|
||||
return;
|
||||
|
||||
va_start( va, fmt );
|
||||
Q_vsnprintf( buf, sizeof( buf ), fmt, va );
|
||||
va_end( va );
|
||||
|
||||
Con_Printf( S_ERROR "%s", buf );
|
||||
}
|
||||
|
||||
static void AVI_SpewAvError( qboolean quiet, const char *func, int numerr )
|
||||
{
|
||||
if( !quiet )
|
||||
Con_Printf( S_ERROR "%s: %s (%d)\n", func, av_err2str( numerr ), numerr );
|
||||
}
|
||||
|
||||
static int AVI_OpenCodecContext( AVCodecContext **dst_dec_ctx, AVFormatContext *fmt_ctx, enum AVMediaType type, qboolean quiet )
|
||||
{
|
||||
const AVCodec *dec;
|
||||
AVCodecContext *dec_ctx;
|
||||
AVStream *st;
|
||||
int idx, ret;
|
||||
|
||||
if(( ret = av_find_best_stream( fmt_ctx, type, -1, -1, NULL, 0 )) < 0 )
|
||||
{
|
||||
AVI_SpewAvError( quiet, "av_find_best_stream", ret );
|
||||
return ret;
|
||||
}
|
||||
|
||||
idx = ret;
|
||||
st = fmt_ctx->streams[idx];
|
||||
|
||||
if( !( dec = avcodec_find_decoder( st->codecpar->codec_id )))
|
||||
{
|
||||
AVI_SpewError( quiet, S_ERROR "Failed to find %s codec\n", av_get_media_type_string( type ));
|
||||
return AVERROR( EINVAL );
|
||||
}
|
||||
|
||||
if( !( dec_ctx = avcodec_alloc_context3( dec )))
|
||||
{
|
||||
AVI_SpewError( quiet, S_ERROR "Failed to allocate %s codec context", dec->name );
|
||||
return AVERROR( ENOMEM );
|
||||
}
|
||||
|
||||
if(( ret = avcodec_parameters_to_context( dec_ctx, st->codecpar )) < 0 )
|
||||
{
|
||||
AVI_SpewAvError( quiet, "avcodec_parameters_to_context", ret );
|
||||
avcodec_free_context( &dec_ctx );
|
||||
return ret;
|
||||
}
|
||||
|
||||
dec_ctx->pkt_timebase = st->time_base;
|
||||
|
||||
if(( ret = avcodec_open2( dec_ctx, dec, NULL )) < 0 )
|
||||
{
|
||||
AVI_SpewAvError( quiet, "avcodec_open2", ret );
|
||||
|
||||
avcodec_free_context( &dec_ctx );
|
||||
return ret;
|
||||
}
|
||||
|
||||
*dst_dec_ctx = dec_ctx;
|
||||
return idx; // always positive
|
||||
}
|
||||
|
||||
int AVI_GetVideoFrameNumber( movie_state_t *Avi, float time )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int AVI_TimeToSoundPosition( movie_state_t *Avi, int time )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
qboolean AVI_GetVideoInfo( movie_state_t *Avi, int *xres, int *yres, float *duration )
|
||||
{
|
||||
if( !Avi->active )
|
||||
return false;
|
||||
|
||||
if( xres )
|
||||
*xres = Avi->xres;
|
||||
|
||||
if( yres )
|
||||
*yres = Avi->yres;
|
||||
|
||||
if( duration )
|
||||
*duration = Avi->duration;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
qboolean AVI_HaveAudioTrack( const movie_state_t *Avi )
|
||||
{
|
||||
return Avi ? Avi->active && Avi->audio_ctx : false;
|
||||
}
|
||||
|
||||
// just let it compile, bruh!
|
||||
byte *AVI_GetVideoFrame( movie_state_t *Avi, int target )
|
||||
{
|
||||
return Avi->dst;
|
||||
}
|
||||
|
||||
static void AVI_StreamAudio( movie_state_t *Avi )
|
||||
{
|
||||
int buffer_samples, file_samples, file_bytes;
|
||||
rawchan_t *ch = NULL;
|
||||
|
||||
// keep the same semantics, when S_RAW_SOUND_SOUNDTRACK doesn't play if S_StartStreaming wasn't enabled
|
||||
qboolean disable_stream = Avi->entnum == S_RAW_SOUND_SOUNDTRACK ? !s_listener.streaming : false;
|
||||
|
||||
if( !dma.initialized || disable_stream || s_listener.paused || !Avi->cached_audio )
|
||||
return;
|
||||
|
||||
ch = S_FindRawChannel( Avi->entnum, true );
|
||||
|
||||
if( !ch )
|
||||
return;
|
||||
|
||||
ch->master_vol = Avi->volume;
|
||||
ch->dist_mult = (Avi->attn / SND_CLIP_DISTANCE);
|
||||
|
||||
if( ch->s_rawend < soundtime )
|
||||
ch->s_rawend = soundtime;
|
||||
|
||||
while( ch->s_rawend < soundtime + ch->max_samples )
|
||||
{
|
||||
size_t copy;
|
||||
|
||||
buffer_samples = ch->max_samples - (ch->s_rawend - soundtime);
|
||||
|
||||
file_samples = buffer_samples * ((float)Avi->rate / SOUND_DMA_SPEED);
|
||||
if( file_samples <= 1 ) return; // no more samples need
|
||||
|
||||
file_bytes = file_samples * av_get_bytes_per_sample( Avi->s_fmt ) * Avi->channels;
|
||||
|
||||
if( file_bytes > ch->max_samples )
|
||||
{
|
||||
file_bytes = ch->max_samples;
|
||||
file_samples = file_bytes / ( av_get_bytes_per_sample( Avi->s_fmt ) * Avi->channels );
|
||||
}
|
||||
|
||||
copy = Q_min( file_bytes, Q_max( Avi->cached_audio_len - Avi->cached_audio_pos, 0 ));
|
||||
|
||||
if( !copy )
|
||||
break;
|
||||
|
||||
if( file_bytes > copy )
|
||||
{
|
||||
file_bytes = copy;
|
||||
file_samples = file_bytes / ( av_get_bytes_per_sample( Avi->s_fmt ) * Avi->channels );
|
||||
}
|
||||
|
||||
ch->s_rawend = S_RawSamplesStereo( ch->rawsamples, ch->s_rawend, ch->max_samples, file_samples, Avi->rate, av_get_bytes_per_sample( Avi->s_fmt ), Avi->channels, Avi->cached_audio + Avi->cached_audio_pos );
|
||||
Avi->cached_audio_pos += copy;
|
||||
}
|
||||
}
|
||||
|
||||
static void AVI_HandleAudio( movie_state_t *Avi, const AVFrame *frame )
|
||||
{
|
||||
int samples = frame->nb_samples;
|
||||
size_t len = samples * av_get_bytes_per_sample( Avi->s_fmt ) * Avi->channels;
|
||||
int outsamples;
|
||||
uint8_t *ptr;
|
||||
|
||||
// allocate data
|
||||
if( !Avi->cached_audio )
|
||||
{
|
||||
Avi->cached_audio_buf_len = len;
|
||||
Avi->cached_audio_pos = 0;
|
||||
Avi->cached_audio_len = 0;
|
||||
Avi->cached_audio = Mem_Malloc( avi_mempool, len );
|
||||
}
|
||||
else
|
||||
{
|
||||
if( Avi->cached_audio_pos )
|
||||
{
|
||||
// Con_Printf( "%s: erasing old data of size %d\n", __func__, Avi->cached_audio_pos );
|
||||
Avi->cached_audio_len -= Avi->cached_audio_pos;
|
||||
memmove( Avi->cached_audio, Avi->cached_audio + Avi->cached_audio_pos, Avi->cached_audio_len );
|
||||
Avi->cached_audio_pos = 0;
|
||||
}
|
||||
|
||||
if( len + Avi->cached_audio_len > Avi->cached_audio_buf_len )
|
||||
{
|
||||
// Con_Printf( "%s: resizing old buffer of size %d to size %d\n", __func__, Avi->cached_audio_buf_len, len + Avi->cached_audio_buf_len );
|
||||
Avi->cached_audio_buf_len = len + Avi->cached_audio_len;
|
||||
Avi->cached_audio = Mem_Realloc( avi_mempool, Avi->cached_audio, Avi->cached_audio_buf_len );
|
||||
}
|
||||
}
|
||||
|
||||
ptr = Avi->cached_audio + Avi->cached_audio_len;
|
||||
outsamples = swr_convert( Avi->swr_ctx, &ptr, samples, (void *)frame->data, samples );
|
||||
Avi->cached_audio_len += outsamples * av_get_bytes_per_sample( Avi->s_fmt ) * Avi->channels;
|
||||
|
||||
// Con_Printf( "%s: got audio chunk of size %d samples\n", __func__, outsamples );
|
||||
}
|
||||
|
||||
qboolean AVI_Think( movie_state_t *Avi )
|
||||
{
|
||||
qboolean decoded = false;
|
||||
qboolean flushing = false;
|
||||
qboolean redraw = false;
|
||||
const double timebase = (double)Avi->video_ctx->pkt_timebase.den / Avi->video_ctx->pkt_timebase.num;
|
||||
int64_t curtime = round( Platform_DoubleTime() * timebase );
|
||||
|
||||
if( !Avi->first_time ) // always remember at which timestamp we started playing
|
||||
Avi->first_time = curtime;
|
||||
|
||||
if( Avi->paused )
|
||||
{
|
||||
// FIXME: there might be a better way to do this
|
||||
Avi->last_time = curtime;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Con_NPrintf( 1, "cached_audio_buf_len = %zu", Avi->cached_audio_buf_len );
|
||||
|
||||
while( 1 ) // try to get multiple decoded frames to keep up when we're running at low fps
|
||||
{
|
||||
int res;
|
||||
|
||||
AVI_StreamAudio( Avi ); // always flush audio buffers
|
||||
|
||||
// recalc time so we always play last possible frame
|
||||
curtime = round( Platform_DoubleTime() * timebase );
|
||||
|
||||
if( Avi->last_time > curtime )
|
||||
break;
|
||||
|
||||
if(( res = av_read_frame( Avi->fmt_ctx, Avi->pkt )) >= 0 )
|
||||
{
|
||||
if( Avi->pkt->stream_index == Avi->audio_stream )
|
||||
{
|
||||
res = avcodec_send_packet( Avi->audio_ctx, Avi->pkt );
|
||||
if( res < 0 )
|
||||
AVI_SpewAvError( Avi->quiet, "avcodec_send_packet (audio)", res );
|
||||
}
|
||||
else if( Avi->pkt->stream_index == Avi->video_stream )
|
||||
{
|
||||
res = avcodec_send_packet( Avi->video_ctx, Avi->pkt );
|
||||
if( res < 0 )
|
||||
AVI_SpewAvError( Avi->quiet, "avcodec_send_packet (video)", res );
|
||||
}
|
||||
av_packet_unref( Avi->pkt );
|
||||
}
|
||||
else
|
||||
{
|
||||
if( res != AVERROR_EOF )
|
||||
AVI_SpewAvError( Avi->quiet, "av_read_frame", res );
|
||||
|
||||
if( Avi->audio_ctx )
|
||||
avcodec_flush_buffers( Avi->audio_ctx );
|
||||
|
||||
avcodec_flush_buffers( Avi->video_ctx );
|
||||
flushing = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if( Avi->audio_ctx )
|
||||
{
|
||||
while( avcodec_receive_frame( Avi->audio_ctx, Avi->aframe ) == 0 )
|
||||
{
|
||||
AVI_HandleAudio( Avi, Avi->aframe );
|
||||
decoded = true;
|
||||
}
|
||||
}
|
||||
|
||||
while( avcodec_receive_frame( Avi->video_ctx, Avi->vframe ) == 0 )
|
||||
{
|
||||
Avi->last_time = Avi->first_time + Avi->vframe->best_effort_timestamp;
|
||||
decoded = true;
|
||||
|
||||
if( FBitSet( Avi->vframe->flags, AV_FRAME_FLAG_CORRUPT|AV_FRAME_FLAG_DISCARD ))
|
||||
continue;
|
||||
|
||||
if( Avi->vframe->decode_error_flags != 0 )
|
||||
continue;
|
||||
|
||||
av_frame_unref( Avi->vframe_copy );
|
||||
if( av_frame_ref( Avi->vframe_copy, Avi->vframe ) == 0 )
|
||||
redraw = true;
|
||||
}
|
||||
}
|
||||
|
||||
if( redraw )
|
||||
{
|
||||
sws_scale( Avi->sws_ctx, (void*)Avi->vframe_copy->data, Avi->vframe_copy->linesize, 0, Avi->video_ctx->height,
|
||||
&Avi->dst, &Avi->dst_linesize );
|
||||
av_frame_unref( Avi->vframe_copy );
|
||||
}
|
||||
|
||||
if( Avi->texture == 0 )
|
||||
{
|
||||
int w = Avi->w >= 0 ? Avi->w : refState.width;
|
||||
int h = Avi->h >= 0 ? Avi->h : refState.height;
|
||||
|
||||
ref.dllFuncs.R_DrawStretchRaw( Avi->x, Avi->y, w, h, Avi->xres, Avi->yres, Avi->dst, redraw );
|
||||
}
|
||||
else if( redraw && Avi->texture > 0 )
|
||||
ref.dllFuncs.AVI_UploadRawFrame( Avi->texture, Avi->xres, Avi->yres, Avi->w, Avi->h, Avi->dst );
|
||||
|
||||
if( flushing && !decoded )
|
||||
return false; // probably hit an EOF
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void AVI_OpenVideo( movie_state_t *Avi, const char *filename, qboolean load_audio, int quiet )
|
||||
{
|
||||
byte *dst[4];
|
||||
int dst_linesize[4];
|
||||
int ret;
|
||||
|
||||
if( Avi->active )
|
||||
AVI_CloseVideo( Avi );
|
||||
|
||||
if( !filename || !avi_initialized )
|
||||
return;
|
||||
|
||||
Avi->active = false;
|
||||
Avi->quiet = quiet;
|
||||
Avi->video_ctx = Avi->audio_ctx = NULL;
|
||||
Avi->fmt_ctx = NULL;
|
||||
|
||||
if(( ret = avformat_open_input( &Avi->fmt_ctx, filename, NULL, NULL )) < 0 )
|
||||
{
|
||||
AVI_SpewAvError( quiet, "avformat_open_input", ret );
|
||||
return;
|
||||
}
|
||||
|
||||
if(( ret = avformat_find_stream_info( Avi->fmt_ctx, NULL )) < 0 )
|
||||
{
|
||||
AVI_SpewAvError( quiet, "avformat_find_stream_info", ret );
|
||||
return;
|
||||
}
|
||||
|
||||
if( !( Avi->pkt = av_packet_alloc( )))
|
||||
{
|
||||
AVI_SpewAvError( quiet, "av_packet_alloc", 0 );
|
||||
return;
|
||||
}
|
||||
|
||||
if( !( Avi->vframe = av_frame_alloc( )))
|
||||
{
|
||||
AVI_SpewAvError( quiet, "av_frame_alloc (video)", 0 );
|
||||
return;
|
||||
}
|
||||
|
||||
if( !( Avi->vframe_copy = av_frame_alloc( )))
|
||||
{
|
||||
AVI_SpewAvError( quiet, "av_frame_alloc (video)", 0 );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
Avi->video_stream = AVI_OpenCodecContext( &Avi->video_ctx, Avi->fmt_ctx, AVMEDIA_TYPE_VIDEO, quiet );
|
||||
|
||||
if( Avi->video_stream < 0 )
|
||||
return;
|
||||
|
||||
Avi->xres = Avi->video_ctx->width;
|
||||
Avi->yres = Avi->video_ctx->height;
|
||||
Avi->pix_fmt = Avi->video_ctx->pix_fmt;
|
||||
Avi->duration = Avi->fmt_ctx->duration / (double)AV_TIME_BASE;
|
||||
Avi->entnum = S_RAW_SOUND_SOUNDTRACK;
|
||||
Avi->attn = ATTN_NONE;
|
||||
Avi->volume = 255;
|
||||
|
||||
if( !( Avi->sws_ctx = sws_getContext( Avi->xres, Avi->yres, Avi->pix_fmt,
|
||||
Avi->xres, Avi->yres, AV_PIX_FMT_BGR0, SWS_POINT, NULL, NULL, NULL )))
|
||||
{
|
||||
AVI_SpewAvError( quiet, "sws_getContext", 0 );
|
||||
return;
|
||||
}
|
||||
|
||||
if(( ret = av_image_alloc( dst, dst_linesize, Avi->xres, Avi->yres, AV_PIX_FMT_BGR0, 1 )) < 0 )
|
||||
{
|
||||
AVI_SpewAvError( quiet, "av_image_alloc", ret );
|
||||
return;
|
||||
}
|
||||
|
||||
Avi->dst = dst[0];
|
||||
Avi->dst_linesize = dst_linesize[0];
|
||||
|
||||
if( load_audio )
|
||||
{
|
||||
if( !( Avi->aframe = av_frame_alloc( )))
|
||||
{
|
||||
AVI_SpewAvError( quiet, "av_frame_alloc (audio)", 0 );
|
||||
return;
|
||||
}
|
||||
|
||||
Avi->audio_stream = AVI_OpenCodecContext( &Avi->audio_ctx, Avi->fmt_ctx, AVMEDIA_TYPE_AUDIO, quiet );
|
||||
|
||||
// audio stream was requested but it wasn't found
|
||||
if( Avi->audio_stream < 0 )
|
||||
return;
|
||||
|
||||
Avi->channels = Q_min( Avi->audio_ctx->ch_layout.nb_channels, 2 );
|
||||
if( Avi->audio_ctx->sample_fmt == AV_SAMPLE_FMT_U8 || Avi->audio_ctx->sample_fmt == AV_SAMPLE_FMT_U8P )
|
||||
Avi->s_fmt = AV_SAMPLE_FMT_U8;
|
||||
else Avi->s_fmt = AV_SAMPLE_FMT_S16;
|
||||
Avi->rate = Avi->audio_ctx->sample_rate;
|
||||
|
||||
if(( ret = swr_alloc_set_opts2( &Avi->swr_ctx, &Avi->audio_ctx->ch_layout, Avi->s_fmt, Avi->rate,
|
||||
&Avi->audio_ctx->ch_layout, Avi->audio_ctx->sample_fmt, Avi->audio_ctx->sample_rate, 0, 0 )) < 0 )
|
||||
{
|
||||
AVI_SpewAvError( quiet, "swr_alloc_set_opts2", ret );
|
||||
return;
|
||||
}
|
||||
|
||||
if(( ret = swr_init( Avi->swr_ctx )) < 0 )
|
||||
{
|
||||
AVI_SpewAvError( quiet, "swr_init", ret );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Avi->active = true;
|
||||
}
|
||||
|
||||
void AVI_CloseVideo( movie_state_t *Avi )
|
||||
{
|
||||
if( Avi->active )
|
||||
{
|
||||
if( Avi->cached_audio )
|
||||
Mem_Free( Avi->cached_audio );
|
||||
|
||||
swr_free( &Avi->swr_ctx );
|
||||
avcodec_free_context( &Avi->audio_ctx );
|
||||
av_frame_free( &Avi->aframe );
|
||||
|
||||
av_free( Avi->dst );
|
||||
sws_freeContext( Avi->sws_ctx );
|
||||
avcodec_free_context( &Avi->video_ctx );
|
||||
av_frame_free( &Avi->vframe );
|
||||
av_frame_free( &Avi->vframe_copy );
|
||||
|
||||
av_packet_free( &Avi->pkt );
|
||||
|
||||
avformat_close_input( &Avi->fmt_ctx );
|
||||
}
|
||||
|
||||
memset( Avi, 0, sizeof( *Avi ));
|
||||
}
|
||||
|
||||
static void AVI_PrintFFmpegVersion( void )
|
||||
{
|
||||
uint ver;
|
||||
|
||||
// print version we're compiled with and which version we're running with
|
||||
ver = avutil_version();
|
||||
Con_Reportf( "AVI: %s (runtime %d.%d.%d)\n", LIBAVUTIL_IDENT, AV_VERSION_MAJOR( ver ), AV_VERSION_MINOR( ver ), AV_VERSION_MICRO( ver ));
|
||||
|
||||
ver = avformat_version();
|
||||
Con_Reportf( "AVI: %s (runtime %d.%d.%d)\n", LIBAVFORMAT_IDENT, AV_VERSION_MAJOR( ver ), AV_VERSION_MINOR( ver ), AV_VERSION_MICRO( ver ));
|
||||
|
||||
ver = avformat_version();
|
||||
Con_Reportf( "AVI: %s (runtime %d.%d.%d)\n", LIBAVCODEC_IDENT, AV_VERSION_MAJOR( ver ), AV_VERSION_MINOR( ver ), AV_VERSION_MICRO( ver ));
|
||||
|
||||
ver = swscale_version();
|
||||
Con_Reportf( "AVI: %s (runtime %d.%d.%d)\n", LIBSWSCALE_IDENT, AV_VERSION_MAJOR( ver ), AV_VERSION_MINOR( ver ), AV_VERSION_MICRO( ver ));
|
||||
|
||||
ver = swresample_version();
|
||||
Con_Reportf( "AVI: %s (runtime %d.%d.%d)\n", LIBSWRESAMPLE_IDENT, AV_VERSION_MAJOR( ver ), AV_VERSION_MINOR( ver ), AV_VERSION_MICRO( ver ));
|
||||
}
|
||||
#else
|
||||
struct movie_state_s
|
||||
{
|
||||
qboolean active;
|
||||
};
|
||||
|
||||
int AVI_GetVideoFrameNumber( movie_state_t *Avi, float time )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
byte *AVI_GetVideoFrame( movie_state_t *Avi, int frame )
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
qboolean AVI_GetVideoInfo( movie_state_t *Avi, int *xres, int *yres, float *duration )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
qboolean AVI_HaveAudioTrack( const movie_state_t *Avi )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void AVI_OpenVideo( movie_state_t *Avi, const char *filename, qboolean load_audio, int quiet )
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
int AVI_TimeToSoundPosition( movie_state_t *Avi, int time )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void AVI_CloseVideo( movie_state_t *Avi )
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
qboolean AVI_Think( movie_state_t *Avi )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
qboolean AVI_SetParm( movie_state_t *Avi, enum movie_parms_e parm, ... )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
static void AVI_PrintFFmpegVersion( void )
|
||||
{
|
||||
|
||||
}
|
||||
#endif // XASH_AVI == AVI_NULL
|
||||
|
||||
static movie_state_t avi[2];
|
||||
movie_state_t *AVI_GetState( int num )
|
||||
{
|
||||
return &avi[num];
|
||||
}
|
||||
|
||||
qboolean AVI_IsActive( movie_state_t *Avi )
|
||||
{
|
||||
return Avi ? Avi->active : false;
|
||||
}
|
||||
|
||||
qboolean AVI_Initailize( void )
|
||||
{
|
||||
if( XASH_AVI == AVI_NULL )
|
||||
{
|
||||
Con_Printf( "AVI: Not supported\n" );
|
||||
return false;
|
||||
}
|
||||
|
||||
if( Sys_CheckParm( "-noavi" ))
|
||||
{
|
||||
Con_Printf( "AVI: Disabled\n" );
|
||||
return false;
|
||||
}
|
||||
|
||||
AVI_PrintFFmpegVersion();
|
||||
|
||||
avi_initialized = true;
|
||||
avi_mempool = Mem_AllocPool( "AVI Zone" );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void AVI_Shutdown( void )
|
||||
{
|
||||
Mem_FreePool( &avi_mempool );
|
||||
avi_initialized = XASH_AVI != AVI_NULL;
|
||||
}
|
||||
|
||||
movie_state_t *AVI_LoadVideo( const char *filename, qboolean load_audio )
|
||||
{
|
||||
movie_state_t *Avi;
|
||||
string path;
|
||||
const char *fullpath;
|
||||
|
||||
// fast reject
|
||||
if( !avi_initialized )
|
||||
return NULL;
|
||||
|
||||
// open cinematic
|
||||
Q_snprintf( path, sizeof( path ), "media/%s", filename );
|
||||
COM_DefaultExtension( path, ".avi", sizeof( path ));
|
||||
fullpath = FS_GetDiskPath( path, false );
|
||||
|
||||
if( FS_FileExists( path, false ) && !fullpath )
|
||||
{
|
||||
Con_Printf( "Couldn't load %s from packfile. Please extract it\n", path );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Avi = Mem_Calloc( avi_mempool, sizeof( movie_state_t ));
|
||||
AVI_OpenVideo( Avi, fullpath, load_audio, false );
|
||||
|
||||
if( !AVI_IsActive( Avi ))
|
||||
{
|
||||
AVI_FreeVideo( Avi ); // something bad happens
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// all done
|
||||
return Avi;
|
||||
}
|
||||
|
||||
void AVI_FreeVideo( movie_state_t *Avi )
|
||||
{
|
||||
if( !Avi )
|
||||
return;
|
||||
|
||||
AVI_CloseVideo( Avi );
|
||||
|
||||
if( Mem_IsAllocatedExt( avi_mempool, Avi ))
|
||||
Mem_Free( Avi );
|
||||
}
|
||||
@@ -1,90 +0,0 @@
|
||||
/*
|
||||
avi_stub.c - playing AVI files (stub)
|
||||
Copyright (C) 2018 a1batross
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include "build.h"
|
||||
#if !XASH_WIN32
|
||||
#include "common.h"
|
||||
|
||||
int AVI_GetVideoFrameNumber( movie_state_t *Avi, float time )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
byte *AVI_GetVideoFrame( movie_state_t *Avi, int frame )
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
qboolean AVI_GetVideoInfo( movie_state_t *Avi, int *xres, int *yres, float *duration )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
qboolean AVI_GetAudioInfo( movie_state_t *Avi, wavdata_t *snd_info )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
int AVI_GetAudioChunk( movie_state_t *Avi, char *audiodata, int offset, int length )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void AVI_OpenVideo( movie_state_t *Avi, const char *filename, qboolean load_audio, int quiet )
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
movie_state_t *AVI_LoadVideo( const char *filename, qboolean load_audio )
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int AVI_TimeToSoundPosition( movie_state_t *Avi, int time )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void AVI_CloseVideo( movie_state_t *Avi )
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
qboolean AVI_IsActive( movie_state_t *Avi )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void AVI_FreeVideo( movie_state_t *Avi )
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
movie_state_t *AVI_GetState( int num )
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
qboolean AVI_Initailize( void )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void AVI_Shutdown( void )
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
#endif // WIN32
|
||||
@@ -1,732 +0,0 @@
|
||||
/*
|
||||
avi_win.c - playing AVI files (based on original AVIKit code, Win32 version)
|
||||
Copyright (c) 2003-2004, Ruari O'Sullivan
|
||||
Copyright (C) 2010 Uncle Mike
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include "build.h"
|
||||
#if XASH_WIN32
|
||||
#include "common.h"
|
||||
#include "client.h"
|
||||
#include <vfw.h> // video for windows
|
||||
|
||||
// msvfw32.dll exports
|
||||
static HDRAWDIB (_stdcall *pDrawDibOpen)( void );
|
||||
static BOOL (_stdcall *pDrawDibClose)( HDRAWDIB hdd );
|
||||
static BOOL (_stdcall *pDrawDibDraw)( HDRAWDIB, HDC, int, int, int, int, LPBITMAPINFOHEADER, void*, int, int, int, int, uint );
|
||||
|
||||
static dllfunc_t msvfw_funcs[] =
|
||||
{
|
||||
{ "DrawDibOpen", (void **) &pDrawDibOpen },
|
||||
{ "DrawDibDraw", (void **) &pDrawDibDraw },
|
||||
{ "DrawDibClose", (void **) &pDrawDibClose },
|
||||
};
|
||||
|
||||
dll_info_t msvfw_dll = { "msvfw32.dll", msvfw_funcs, ARRAYSIZE( msvfw_funcs ), false };
|
||||
|
||||
// msacm32.dll exports
|
||||
static MMRESULT (_stdcall *pacmStreamOpen)( LPHACMSTREAM, HACMDRIVER, LPWAVEFORMATEX, LPWAVEFORMATEX, LPWAVEFILTER, DWORD, DWORD, DWORD );
|
||||
static MMRESULT (_stdcall *pacmStreamPrepareHeader)( HACMSTREAM, LPACMSTREAMHEADER, DWORD );
|
||||
static MMRESULT (_stdcall *pacmStreamUnprepareHeader)( HACMSTREAM, LPACMSTREAMHEADER, DWORD );
|
||||
static MMRESULT (_stdcall *pacmStreamConvert)( HACMSTREAM, LPACMSTREAMHEADER, DWORD );
|
||||
static MMRESULT (_stdcall *pacmStreamSize)( HACMSTREAM, DWORD, LPDWORD, DWORD );
|
||||
static MMRESULT (_stdcall *pacmStreamClose)( HACMSTREAM, DWORD );
|
||||
|
||||
static dllfunc_t msacm_funcs[] =
|
||||
{
|
||||
{ "acmStreamOpen", (void **) &pacmStreamOpen },
|
||||
{ "acmStreamPrepareHeader", (void **) &pacmStreamPrepareHeader },
|
||||
{ "acmStreamUnprepareHeader", (void **) &pacmStreamUnprepareHeader },
|
||||
{ "acmStreamConvert", (void **) &pacmStreamConvert },
|
||||
{ "acmStreamSize", (void **) &pacmStreamSize },
|
||||
{ "acmStreamClose", (void **) &pacmStreamClose },
|
||||
};
|
||||
|
||||
dll_info_t msacm_dll = { "msacm32.dll", msacm_funcs, ARRAYSIZE( msacm_funcs ), false };
|
||||
|
||||
// avifil32.dll exports
|
||||
static int (_stdcall *pAVIStreamInfo)( PAVISTREAM pavi, AVISTREAMINFO *psi, LONG lSize );
|
||||
static int (_stdcall *pAVIStreamRead)( PAVISTREAM pavi, LONG lStart, LONG lSamples, void *lpBuffer, LONG cbBuffer, LONG *plBytes, LONG *plSamples );
|
||||
static PGETFRAME (_stdcall *pAVIStreamGetFrameOpen)( PAVISTREAM pavi, LPBITMAPINFOHEADER lpbiWanted );
|
||||
static int (_stdcall *pAVIStreamTimeToSample)( PAVISTREAM pavi, LONG lTime );
|
||||
static void* (_stdcall *pAVIStreamGetFrame)( PGETFRAME pg, LONG lPos );
|
||||
static int (_stdcall *pAVIStreamGetFrameClose)( PGETFRAME pg );
|
||||
static dword (_stdcall *pAVIStreamRelease)( PAVISTREAM pavi );
|
||||
static int (_stdcall *pAVIFileOpenW)( PAVIFILE *ppfile, LPCWSTR szFile, UINT uMode, LPCLSID lpHandler );
|
||||
static int (_stdcall *pAVIFileGetStream)( PAVIFILE pfile, PAVISTREAM *ppavi, DWORD fccType, LONG lParam );
|
||||
static int (_stdcall *pAVIStreamReadFormat)( PAVISTREAM pavi, LONG lPos,LPVOID lpFormat, LONG *lpcbFormat );
|
||||
static int (_stdcall *pAVIStreamStart)( PAVISTREAM pavi );
|
||||
static dword (_stdcall *pAVIFileRelease)( PAVIFILE pfile );
|
||||
static void (_stdcall *pAVIFileInit)( void );
|
||||
static void (_stdcall *pAVIFileExit)( void );
|
||||
|
||||
static dllfunc_t avifile_funcs[] =
|
||||
{
|
||||
{ "AVIFileExit", (void **) &pAVIFileExit },
|
||||
{ "AVIFileGetStream", (void **) &pAVIFileGetStream },
|
||||
{ "AVIFileInit", (void **) &pAVIFileInit },
|
||||
{ "AVIFileOpenW", (void **) &pAVIFileOpenW },
|
||||
{ "AVIFileRelease", (void **) &pAVIFileRelease },
|
||||
{ "AVIStreamGetFrame", (void **) &pAVIStreamGetFrame },
|
||||
{ "AVIStreamGetFrameClose", (void **) &pAVIStreamGetFrameClose },
|
||||
{ "AVIStreamGetFrameOpen", (void **) &pAVIStreamGetFrameOpen },
|
||||
{ "AVIStreamInfoA", (void **) &pAVIStreamInfo },
|
||||
{ "AVIStreamRead", (void **) &pAVIStreamRead },
|
||||
{ "AVIStreamReadFormat", (void **) &pAVIStreamReadFormat },
|
||||
{ "AVIStreamRelease", (void **) &pAVIStreamRelease },
|
||||
{ "AVIStreamStart", (void **) &pAVIStreamStart },
|
||||
{ "AVIStreamTimeToSample", (void **) &pAVIStreamTimeToSample },
|
||||
};
|
||||
|
||||
dll_info_t avifile_dll = { "avifil32.dll", avifile_funcs, ARRAYSIZE( avifile_funcs ), false };
|
||||
|
||||
typedef struct movie_state_s
|
||||
{
|
||||
qboolean active;
|
||||
qboolean quiet; // ignore error messages
|
||||
|
||||
PAVIFILE pfile; // avi file pointer
|
||||
PAVISTREAM video_stream; // video stream pointer
|
||||
PGETFRAME video_getframe; // pointer to getframe object for video stream
|
||||
int video_frames; // total frames
|
||||
int video_xres; // video stream resolution
|
||||
int video_yres;
|
||||
float video_fps; // video stream fps
|
||||
|
||||
PAVISTREAM audio_stream; // audio stream pointer
|
||||
WAVEFORMAT *audio_header; // audio stream header
|
||||
int audio_header_size; // WAVEFORMAT is returned for PCM data; WAVEFORMATEX for others
|
||||
int audio_codec; // WAVE_FORMAT_PCM is oldstyle: anything else needs conversion
|
||||
int audio_length; // in converted samples
|
||||
int audio_bytes_per_sample; // guess.
|
||||
|
||||
// compressed audio specific data
|
||||
dword cpa_blockalign; // block size to read
|
||||
HACMSTREAM cpa_conversion_stream;
|
||||
ACMSTREAMHEADER cpa_conversion_header;
|
||||
byte *cpa_srcbuffer; // maintained buffer for raw data
|
||||
byte *cpa_dstbuffer;
|
||||
|
||||
dword cpa_blocknum; // current block
|
||||
dword cpa_blockpos; // read position in current block
|
||||
dword cpa_blockoffset; // corresponding offset in bytes in the output stream
|
||||
|
||||
// for additional unpack Ms-RLE codecs etc
|
||||
HDC hDC; // compatible DC
|
||||
HDRAWDIB hDD; // DrawDib handler
|
||||
HBITMAP hBitmap; // for DIB conversions
|
||||
byte *pframe_data; // converted framedata
|
||||
} movie_state_t;
|
||||
|
||||
static qboolean avi_initialized = false;
|
||||
static movie_state_t avi[2];
|
||||
|
||||
// Converts a compressed audio stream into uncompressed PCM.
|
||||
qboolean AVI_ACMConvertAudio( movie_state_t *Avi )
|
||||
{
|
||||
WAVEFORMATEX dest_header, *sh, *dh;
|
||||
AVISTREAMINFO stream_info;
|
||||
dword dest_length;
|
||||
short bits;
|
||||
|
||||
// WMA codecs, both versions - they simply don't work.
|
||||
if( Avi->audio_header->wFormatTag == 0x160 || Avi->audio_header->wFormatTag == 0x161 )
|
||||
{
|
||||
if( !Avi->quiet )
|
||||
Con_Reportf( S_ERROR "ACM does not support this audio codec.\n" );
|
||||
return false;
|
||||
}
|
||||
|
||||
// get audio stream info to work with
|
||||
pAVIStreamInfo( Avi->audio_stream, &stream_info, sizeof( stream_info ));
|
||||
|
||||
if( Avi->audio_header_size < sizeof( WAVEFORMATEX ))
|
||||
{
|
||||
if( !Avi->quiet )
|
||||
Con_Reportf( S_ERROR "ACM failed to open conversion stream.\n" );
|
||||
return false;
|
||||
}
|
||||
|
||||
sh = (WAVEFORMATEX *)Avi->audio_header;
|
||||
bits = 16; // predict state
|
||||
|
||||
// how much of this is actually required?
|
||||
dest_header.wFormatTag = WAVE_FORMAT_PCM; // yay
|
||||
dest_header.wBitsPerSample = bits; // 16bit
|
||||
dest_header.nChannels = sh->nChannels;
|
||||
dest_header.nSamplesPerSec = sh->nSamplesPerSec; // take straight from the source stream
|
||||
dest_header.nAvgBytesPerSec = (bits >> 3) * sh->nChannels * sh->nSamplesPerSec;
|
||||
dest_header.nBlockAlign = (bits >> 3) * sh->nChannels;
|
||||
dest_header.cbSize = 0; // no more data.
|
||||
|
||||
dh = &dest_header;
|
||||
|
||||
// open the stream
|
||||
if( pacmStreamOpen( &Avi->cpa_conversion_stream, NULL, sh, dh, NULL, 0, 0, 0 ) != MMSYSERR_NOERROR )
|
||||
{
|
||||
// try with 8 bit destination instead
|
||||
bits = 8;
|
||||
|
||||
dest_header.wBitsPerSample = bits; // 8bit
|
||||
dest_header.nAvgBytesPerSec = ( bits >> 3 ) * sh->nChannels * sh->nSamplesPerSec;
|
||||
dest_header.nBlockAlign = ( bits >> 3 ) * sh->nChannels; // 1 sample at a time
|
||||
|
||||
if( pacmStreamOpen( &Avi->cpa_conversion_stream, NULL, sh, dh, NULL, 0, 0, 0 ) != MMSYSERR_NOERROR )
|
||||
{
|
||||
if( !Avi->quiet )
|
||||
Con_Reportf( S_ERROR "ACM failed to open conversion stream.\n" );
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Avi->cpa_blockalign = sh->nBlockAlign;
|
||||
dest_length = 0;
|
||||
|
||||
// mp3 specific fix
|
||||
if( sh->wFormatTag == 0x55 )
|
||||
{
|
||||
LPMPEGLAYER3WAVEFORMAT k;
|
||||
|
||||
k = (LPMPEGLAYER3WAVEFORMAT)sh;
|
||||
Avi->cpa_blockalign = k->nBlockSize;
|
||||
}
|
||||
|
||||
// get the size of the output buffer for streaming the compressed audio
|
||||
if( pacmStreamSize( Avi->cpa_conversion_stream, Avi->cpa_blockalign, &dest_length, ACM_STREAMSIZEF_SOURCE ) != MMSYSERR_NOERROR )
|
||||
{
|
||||
if( !Avi->quiet )
|
||||
Con_Reportf( S_ERROR "Couldn't get ACM conversion stream size.\n" );
|
||||
pacmStreamClose( Avi->cpa_conversion_stream, 0 );
|
||||
return false;
|
||||
}
|
||||
|
||||
Avi->cpa_srcbuffer = (byte *)Mem_Malloc( cls.mempool, Avi->cpa_blockalign );
|
||||
Avi->cpa_dstbuffer = (byte *)Mem_Malloc( cls.mempool, dest_length ); // maintained buffer for raw data
|
||||
|
||||
// prep the headers!
|
||||
Avi->cpa_conversion_header.cbStruct = sizeof( ACMSTREAMHEADER );
|
||||
Avi->cpa_conversion_header.fdwStatus = 0;
|
||||
Avi->cpa_conversion_header.dwUser = 0; // no user data
|
||||
Avi->cpa_conversion_header.pbSrc = Avi->cpa_srcbuffer; // source buffer
|
||||
Avi->cpa_conversion_header.cbSrcLength = Avi->cpa_blockalign; // source buffer size
|
||||
Avi->cpa_conversion_header.cbSrcLengthUsed = 0;
|
||||
Avi->cpa_conversion_header.dwSrcUser = 0; // no user data
|
||||
Avi->cpa_conversion_header.pbDst = Avi->cpa_dstbuffer; // dest buffer
|
||||
Avi->cpa_conversion_header.cbDstLength = dest_length; // dest buffer size
|
||||
Avi->cpa_conversion_header.cbDstLengthUsed = 0;
|
||||
Avi->cpa_conversion_header.dwDstUser = 0; // no user data
|
||||
|
||||
if( pacmStreamPrepareHeader( Avi->cpa_conversion_stream, &Avi->cpa_conversion_header, 0 ) != MMSYSERR_NOERROR )
|
||||
{
|
||||
if( !Avi->quiet )
|
||||
Con_Reportf( S_ERROR "couldn't prepare stream headers.\n" );
|
||||
pacmStreamClose( Avi->cpa_conversion_stream, 0 );
|
||||
return false;
|
||||
}
|
||||
|
||||
Avi->cpa_blocknum = 0; // start at 0.
|
||||
Avi->cpa_blockpos = 0;
|
||||
Avi->cpa_blockoffset = 0;
|
||||
|
||||
pAVIStreamRead( Avi->audio_stream, Avi->cpa_blocknum * Avi->cpa_blockalign, Avi->cpa_blockalign, Avi->cpa_srcbuffer, Avi->cpa_blockalign, NULL, NULL );
|
||||
pacmStreamConvert( Avi->cpa_conversion_stream, &Avi->cpa_conversion_header, ACM_STREAMCONVERTF_BLOCKALIGN|ACM_STREAMCONVERTF_START );
|
||||
|
||||
// convert first chunk twice. it often fails the first time. BLACK MAGIC.
|
||||
pAVIStreamRead( Avi->audio_stream, Avi->cpa_blocknum * Avi->cpa_blockalign, Avi->cpa_blockalign, Avi->cpa_srcbuffer, Avi->cpa_blockalign, NULL, NULL );
|
||||
pacmStreamConvert( Avi->cpa_conversion_stream, &Avi->cpa_conversion_header, ACM_STREAMCONVERTF_BLOCKALIGN );
|
||||
|
||||
Avi->audio_bytes_per_sample = (bits >> 3 ) * Avi->audio_header->nChannels;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
qboolean AVI_GetVideoInfo( movie_state_t *Avi, int *xres, int *yres, float *duration )
|
||||
{
|
||||
if( !Avi->active )
|
||||
return false;
|
||||
|
||||
if( xres != NULL )
|
||||
*xres = Avi->video_xres;
|
||||
|
||||
if( yres != NULL )
|
||||
*yres = Avi->video_yres;
|
||||
|
||||
if( duration != NULL )
|
||||
*duration = (float)Avi->video_frames / Avi->video_fps;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// returns a unique frame identifier
|
||||
int AVI_GetVideoFrameNumber( movie_state_t *Avi, float time )
|
||||
{
|
||||
if( !Avi->active )
|
||||
return 0;
|
||||
|
||||
return (time * Avi->video_fps);
|
||||
}
|
||||
|
||||
int AVI_TimeToSoundPosition( movie_state_t *Avi, int time )
|
||||
{
|
||||
if( !Avi->active || !Avi->audio_stream )
|
||||
return 0;
|
||||
|
||||
// UNDONE: what about compressed audio?
|
||||
return pAVIStreamTimeToSample( Avi->audio_stream, time ) * Avi->audio_bytes_per_sample;
|
||||
}
|
||||
|
||||
// gets the raw frame data
|
||||
byte *AVI_GetVideoFrame( movie_state_t *Avi, int frame )
|
||||
{
|
||||
LPBITMAPINFOHEADER frame_info;
|
||||
byte *frame_raw;
|
||||
|
||||
if( !Avi->active ) return NULL;
|
||||
|
||||
if( frame >= Avi->video_frames )
|
||||
frame = Avi->video_frames - 1;
|
||||
|
||||
frame_info = (LPBITMAPINFOHEADER)pAVIStreamGetFrame( Avi->video_getframe, frame );
|
||||
frame_raw = (byte *)frame_info + frame_info->biSize + frame_info->biClrUsed * sizeof( RGBQUAD );
|
||||
pDrawDibDraw( Avi->hDD, Avi->hDC, 0, 0, Avi->video_xres, Avi->video_yres, frame_info, frame_raw, 0, 0, Avi->video_xres, Avi->video_yres, 0 );
|
||||
|
||||
return Avi->pframe_data;
|
||||
}
|
||||
|
||||
qboolean AVI_GetAudioInfo( movie_state_t *Avi, wavdata_t *snd_info )
|
||||
{
|
||||
if( !Avi->active || Avi->audio_stream == NULL || snd_info == NULL )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
snd_info->rate = Avi->audio_header->nSamplesPerSec;
|
||||
snd_info->channels = Avi->audio_header->nChannels;
|
||||
|
||||
if( Avi->audio_codec == WAVE_FORMAT_PCM ) // uncompressed audio!
|
||||
snd_info->width = ( Avi->audio_bytes_per_sample > Avi->audio_header->nChannels ) ? 2 : 1;
|
||||
else snd_info->width = 2; // assume compressed audio is always 16 bit
|
||||
|
||||
snd_info->size = snd_info->rate * snd_info->width * snd_info->channels;
|
||||
snd_info->loopStart = 0; // using loopStart as streampos
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// sync the current audio read to a specific offset
|
||||
qboolean AVI_SeekPosition( movie_state_t *Avi, dword offset )
|
||||
{
|
||||
int breaker;
|
||||
|
||||
if( offset < Avi->cpa_blockoffset ) // well, shit. we can't seek backwards... restart
|
||||
{
|
||||
if( Avi->cpa_blockoffset - offset < 500000 )
|
||||
return false; // don't bother if it's gonna catch up soon
|
||||
|
||||
Avi->cpa_blocknum = 0; // start at 0, eh.
|
||||
Avi->cpa_blockpos = 0;
|
||||
Avi->cpa_blockoffset = 0;
|
||||
|
||||
pAVIStreamRead( Avi->audio_stream, Avi->cpa_blocknum * Avi->cpa_blockalign, Avi->cpa_blockalign, Avi->cpa_srcbuffer, Avi->cpa_blockalign, NULL, NULL );
|
||||
pacmStreamConvert( Avi->cpa_conversion_stream, &Avi->cpa_conversion_header, ACM_STREAMCONVERTF_BLOCKALIGN|ACM_STREAMCONVERTF_START );
|
||||
|
||||
// convert first chunk twice. it often fails the first time. BLACK MAGIC.
|
||||
pAVIStreamRead( Avi->audio_stream, Avi->cpa_blocknum * Avi->cpa_blockalign, Avi->cpa_blockalign, Avi->cpa_srcbuffer, Avi->cpa_blockalign, NULL, NULL );
|
||||
pacmStreamConvert( Avi->cpa_conversion_stream, &Avi->cpa_conversion_header, ACM_STREAMCONVERTF_BLOCKALIGN );
|
||||
}
|
||||
|
||||
// now then: seek forwards to the required block
|
||||
breaker = 30; // maximum zero blocks: anti-freeze protection
|
||||
|
||||
while( Avi->cpa_blockoffset + Avi->cpa_conversion_header.cbDstLengthUsed < offset )
|
||||
{
|
||||
Avi->cpa_blocknum++;
|
||||
Avi->cpa_blockoffset += Avi->cpa_conversion_header.cbDstLengthUsed;
|
||||
|
||||
pAVIStreamRead( Avi->audio_stream, Avi->cpa_blocknum * Avi->cpa_blockalign, Avi->cpa_blockalign, Avi->cpa_srcbuffer, Avi->cpa_blockalign, NULL, NULL );
|
||||
pacmStreamConvert( Avi->cpa_conversion_stream, &Avi->cpa_conversion_header, ACM_STREAMCONVERTF_BLOCKALIGN );
|
||||
|
||||
if( Avi->cpa_conversion_header.cbDstLengthUsed == 0 )
|
||||
breaker--;
|
||||
else breaker = 30;
|
||||
|
||||
if( breaker <= 0 )
|
||||
return false;
|
||||
|
||||
Avi->cpa_blockpos = 0;
|
||||
}
|
||||
|
||||
// seek to the right position inside the block
|
||||
Avi->cpa_blockpos = offset - Avi->cpa_blockoffset;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// get a chunk of audio from the stream (in bytes)
|
||||
int AVI_GetAudioChunk( movie_state_t *Avi, char *audiodata, int offset, int length )
|
||||
{
|
||||
int result = 0;
|
||||
int i;
|
||||
|
||||
// zero data past the end of the file
|
||||
if( offset + length > Avi->audio_length )
|
||||
{
|
||||
if( offset <= Avi->audio_length )
|
||||
{
|
||||
int remaining_length = Avi->audio_length - offset;
|
||||
|
||||
AVI_GetAudioChunk( Avi, audiodata, offset, remaining_length );
|
||||
|
||||
for( i = remaining_length; i < length; i++ )
|
||||
audiodata[i] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// we out of soundtrack, just zeroing buffer
|
||||
for( i = 0; i < length; i++ )
|
||||
audiodata[i] = 0;
|
||||
|
||||
// return length;
|
||||
}
|
||||
}
|
||||
|
||||
// uncompressed audio!
|
||||
if( Avi->audio_codec == WAVE_FORMAT_PCM )
|
||||
{
|
||||
// very simple - read straight out
|
||||
pAVIStreamRead( Avi->audio_stream, offset / Avi->audio_bytes_per_sample, length / Avi->audio_bytes_per_sample, audiodata, length, &result, NULL );
|
||||
return result;
|
||||
}
|
||||
else
|
||||
{
|
||||
// compressed audio!
|
||||
result = 0;
|
||||
|
||||
// seek to correct chunk and all that stuff
|
||||
if( !AVI_SeekPosition( Avi, offset ))
|
||||
return 0; // don't continue if we're waiting for the play pointer to catch up
|
||||
|
||||
while( length > 0 )
|
||||
{
|
||||
int blockread = Avi->cpa_conversion_header.cbDstLengthUsed - Avi->cpa_blockpos;
|
||||
|
||||
if( blockread <= 0 ) // read next
|
||||
{
|
||||
Avi->cpa_blocknum++;
|
||||
Avi->cpa_blockoffset += Avi->cpa_conversion_header.cbDstLengthUsed;
|
||||
|
||||
pAVIStreamRead( Avi->audio_stream, Avi->cpa_blocknum * Avi->cpa_blockalign, Avi->cpa_blockalign, Avi->cpa_srcbuffer, Avi->cpa_blockalign, NULL, NULL );
|
||||
pacmStreamConvert( Avi->cpa_conversion_stream, &Avi->cpa_conversion_header, ACM_STREAMCONVERTF_BLOCKALIGN );
|
||||
|
||||
Avi->cpa_blockpos = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
if( blockread > length )
|
||||
blockread = length;
|
||||
|
||||
// copy the data
|
||||
memcpy( audiodata + result, (void *)( Avi->cpa_dstbuffer + Avi->cpa_blockpos ), blockread );
|
||||
|
||||
Avi->cpa_blockpos += blockread;
|
||||
result += blockread;
|
||||
length -= blockread;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
void AVI_CloseVideo( movie_state_t *Avi )
|
||||
{
|
||||
if( Avi->active )
|
||||
{
|
||||
pAVIStreamGetFrameClose( Avi->video_getframe );
|
||||
|
||||
if( Avi->audio_stream != NULL )
|
||||
{
|
||||
pAVIStreamRelease( Avi->audio_stream );
|
||||
Mem_Free( Avi->audio_header );
|
||||
|
||||
if( Avi->audio_codec != WAVE_FORMAT_PCM )
|
||||
{
|
||||
pacmStreamUnprepareHeader( Avi->cpa_conversion_stream, &Avi->cpa_conversion_header, 0 );
|
||||
pacmStreamClose( Avi->cpa_conversion_stream, 0 );
|
||||
Mem_Free( Avi->cpa_srcbuffer );
|
||||
Mem_Free( Avi->cpa_dstbuffer );
|
||||
}
|
||||
}
|
||||
|
||||
pAVIStreamRelease( Avi->video_stream );
|
||||
|
||||
DeleteObject( Avi->hBitmap );
|
||||
pDrawDibClose( Avi->hDD );
|
||||
DeleteDC( Avi->hDC );
|
||||
}
|
||||
|
||||
memset( Avi, 0, sizeof( movie_state_t ));
|
||||
}
|
||||
|
||||
void AVI_OpenVideo( movie_state_t *Avi, const char *filename, qboolean load_audio, int quiet )
|
||||
{
|
||||
BITMAPINFOHEADER bmih;
|
||||
AVISTREAMINFO stream_info;
|
||||
int opened_streams = 0;
|
||||
LONG hr;
|
||||
wchar_t pathBuffer[MAX_PATH];
|
||||
|
||||
// default state: non-working.
|
||||
Avi->active = false;
|
||||
Avi->quiet = quiet;
|
||||
|
||||
// can't load Video For Windows :-(
|
||||
if( !avi_initialized ) return;
|
||||
|
||||
// convert to wide char
|
||||
if( MultiByteToWideChar( CP_UTF8, 0, filename, -1, pathBuffer, ARRAYSIZE( pathBuffer )) <= 0 )
|
||||
{
|
||||
Con_DPrintf( S_ERROR "filename buffer limit exceeded\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
// load the AVI
|
||||
hr = pAVIFileOpenW( &Avi->pfile, pathBuffer, OF_SHARE_DENY_WRITE, 0L );
|
||||
|
||||
if( hr != 0 ) // error opening AVI:
|
||||
{
|
||||
switch( hr )
|
||||
{
|
||||
case AVIERR_BADFORMAT:
|
||||
if( !Avi->quiet )
|
||||
Con_DPrintf( S_ERROR "corrupt file or unknown format.\n" );
|
||||
break;
|
||||
case AVIERR_MEMORY:
|
||||
if( !Avi->quiet )
|
||||
Con_DPrintf( S_ERROR "insufficient memory to open file.\n" );
|
||||
break;
|
||||
case AVIERR_FILEREAD:
|
||||
if( !Avi->quiet )
|
||||
Con_DPrintf( S_ERROR "disk error reading file.\n" );
|
||||
break;
|
||||
case AVIERR_FILEOPEN:
|
||||
if( !Avi->quiet )
|
||||
Con_DPrintf( S_ERROR "disk error opening file.\n" );
|
||||
break;
|
||||
case REGDB_E_CLASSNOTREG:
|
||||
default:
|
||||
if( !Avi->quiet )
|
||||
Con_DPrintf( S_ERROR "no handler found (or file not found).\n" );
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
Avi->video_stream = Avi->audio_stream = NULL;
|
||||
|
||||
// open the streams until a stream is not available.
|
||||
while( 1 )
|
||||
{
|
||||
PAVISTREAM stream = NULL;
|
||||
|
||||
if( pAVIFileGetStream( Avi->pfile, &stream, 0L, opened_streams++ ) != AVIERR_OK )
|
||||
break;
|
||||
|
||||
if( stream == NULL )
|
||||
break;
|
||||
|
||||
pAVIStreamInfo( stream, &stream_info, sizeof( stream_info ));
|
||||
|
||||
if( stream_info.fccType == streamtypeVIDEO && Avi->video_stream == NULL )
|
||||
{
|
||||
Avi->video_stream = stream;
|
||||
Avi->video_frames = stream_info.dwLength;
|
||||
Avi->video_xres = stream_info.rcFrame.right - stream_info.rcFrame.left;
|
||||
Avi->video_yres = stream_info.rcFrame.bottom - stream_info.rcFrame.top;
|
||||
Avi->video_fps = (float)stream_info.dwRate / (float)stream_info.dwScale;
|
||||
}
|
||||
else if( stream_info.fccType == streamtypeAUDIO && Avi->audio_stream == NULL && load_audio )
|
||||
{
|
||||
int size;
|
||||
|
||||
Avi->audio_stream = stream;
|
||||
|
||||
// read the audio header
|
||||
pAVIStreamReadFormat( Avi->audio_stream, pAVIStreamStart( Avi->audio_stream ), 0, &size );
|
||||
|
||||
Avi->audio_header = (WAVEFORMAT *)Mem_Malloc( cls.mempool, size );
|
||||
pAVIStreamReadFormat( Avi->audio_stream, pAVIStreamStart( Avi->audio_stream ), Avi->audio_header, &size );
|
||||
Avi->audio_header_size = size;
|
||||
Avi->audio_codec = Avi->audio_header->wFormatTag;
|
||||
|
||||
// length of converted audio in samples
|
||||
Avi->audio_length = (int)((float)stream_info.dwLength / Avi->audio_header->nAvgBytesPerSec );
|
||||
Avi->audio_length *= Avi->audio_header->nSamplesPerSec;
|
||||
|
||||
if( Avi->audio_codec != WAVE_FORMAT_PCM )
|
||||
{
|
||||
if( !AVI_ACMConvertAudio( Avi ))
|
||||
{
|
||||
Mem_Free( Avi->audio_header );
|
||||
Avi->audio_stream = NULL;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else Avi->audio_bytes_per_sample = Avi->audio_header->nBlockAlign;
|
||||
Avi->audio_length *= Avi->audio_bytes_per_sample;
|
||||
}
|
||||
else
|
||||
{
|
||||
pAVIStreamRelease( stream );
|
||||
}
|
||||
}
|
||||
|
||||
// display error message-stream not found.
|
||||
if( Avi->video_stream == NULL )
|
||||
{
|
||||
if( Avi->pfile ) // if file is open, close it
|
||||
pAVIFileRelease( Avi->pfile );
|
||||
if( !Avi->quiet )
|
||||
Con_DPrintf( S_ERROR "couldn't find a valid video stream.\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
pAVIFileRelease( Avi->pfile ); // release the file
|
||||
Avi->video_getframe = pAVIStreamGetFrameOpen( Avi->video_stream, NULL ); // open the frame getter
|
||||
|
||||
if( Avi->video_getframe == NULL )
|
||||
{
|
||||
if( !Avi->quiet )
|
||||
Con_DPrintf( S_ERROR "error attempting to read video frames.\n" );
|
||||
return; // couldn't open frame getter.
|
||||
}
|
||||
|
||||
bmih.biSize = sizeof( BITMAPINFOHEADER );
|
||||
bmih.biPlanes = 1;
|
||||
bmih.biBitCount = 32;
|
||||
bmih.biCompression = BI_RGB;
|
||||
bmih.biWidth = Avi->video_xres;
|
||||
bmih.biHeight = -Avi->video_yres; // invert height to flip image upside down
|
||||
|
||||
Avi->hDC = CreateCompatibleDC( 0 );
|
||||
Avi->hDD = pDrawDibOpen();
|
||||
Avi->hBitmap = CreateDIBSection( Avi->hDC, (BITMAPINFO*)(&bmih), DIB_RGB_COLORS, (void**)(&Avi->pframe_data), NULL, 0 );
|
||||
SelectObject( Avi->hDC, Avi->hBitmap );
|
||||
|
||||
Avi->active = true; // done
|
||||
}
|
||||
|
||||
qboolean AVI_IsActive( movie_state_t *Avi )
|
||||
{
|
||||
if( Avi != NULL )
|
||||
return Avi->active;
|
||||
return false;
|
||||
}
|
||||
|
||||
movie_state_t *AVI_GetState( int num )
|
||||
{
|
||||
return &avi[num];
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
AVIKit user interface
|
||||
|
||||
=============
|
||||
*/
|
||||
movie_state_t *AVI_LoadVideo( const char *filename, qboolean load_audio )
|
||||
{
|
||||
movie_state_t *Avi;
|
||||
string path;
|
||||
const char *fullpath;
|
||||
|
||||
// fast reject
|
||||
if( !avi_initialized )
|
||||
return NULL;
|
||||
|
||||
// open cinematic
|
||||
Q_snprintf( path, sizeof( path ), "media/%s", filename );
|
||||
COM_DefaultExtension( path, ".avi", sizeof( path ));
|
||||
fullpath = FS_GetDiskPath( path, false );
|
||||
|
||||
if( FS_FileExists( path, false ) && !fullpath )
|
||||
{
|
||||
Con_Printf( "Couldn't load %s from packfile. Please extract it\n", path );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Avi = Mem_Malloc( cls.mempool, sizeof( movie_state_t ));
|
||||
AVI_OpenVideo( Avi, fullpath, load_audio, false );
|
||||
|
||||
if( !AVI_IsActive( Avi ))
|
||||
{
|
||||
AVI_FreeVideo( Avi ); // something bad happens
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// all done
|
||||
return Avi;
|
||||
}
|
||||
|
||||
void AVI_FreeVideo( movie_state_t *state )
|
||||
{
|
||||
if( !state ) return;
|
||||
|
||||
if( Mem_IsAllocatedExt( cls.mempool, state ))
|
||||
{
|
||||
AVI_CloseVideo( state );
|
||||
Mem_Free( state );
|
||||
}
|
||||
}
|
||||
|
||||
qboolean AVI_Initailize( void )
|
||||
{
|
||||
if( Sys_CheckParm( "-noavi" ))
|
||||
{
|
||||
Con_Printf( "AVI: Disabled\n" );
|
||||
return false;
|
||||
}
|
||||
|
||||
if( !Sys_LoadLibrary( &avifile_dll ))
|
||||
return false;
|
||||
|
||||
if( !Sys_LoadLibrary( &msvfw_dll ))
|
||||
{
|
||||
Sys_FreeLibrary( &avifile_dll );
|
||||
return false;
|
||||
}
|
||||
|
||||
if( !Sys_LoadLibrary( &msacm_dll ))
|
||||
{
|
||||
Sys_FreeLibrary( &avifile_dll );
|
||||
Sys_FreeLibrary( &msvfw_dll );
|
||||
return false;
|
||||
}
|
||||
|
||||
avi_initialized = true;
|
||||
pAVIFileInit();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void AVI_Shutdown( void )
|
||||
{
|
||||
if( !avi_initialized ) return;
|
||||
|
||||
pAVIFileExit();
|
||||
|
||||
Sys_FreeLibrary( &avifile_dll );
|
||||
Sys_FreeLibrary( &msvfw_dll );
|
||||
Sys_FreeLibrary( &msacm_dll );
|
||||
avi_initialized = false;
|
||||
}
|
||||
#endif // _WIN32
|
||||
@@ -42,7 +42,8 @@ void CL_PlayVideo_f( void )
|
||||
switch( Cmd_Argc( ))
|
||||
{
|
||||
case 2: // simple user version
|
||||
Q_snprintf( path, sizeof( path ), "media/%s.avi", Cmd_Argv( 1 ));
|
||||
Q_snprintf( path, sizeof( path ), "media/%s", Cmd_Argv( 1 ));
|
||||
COM_DefaultExtension( path, ".avi", sizeof( path ));
|
||||
SCR_PlayCinematic( path );
|
||||
break;
|
||||
case 3: // sequenced cinematics used this
|
||||
@@ -152,6 +153,19 @@ void CL_PlayCDTrack_f( void )
|
||||
else Con_Printf( "%s: unknown command %s\n", Cmd_Argv( 0 ), command );
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
CL_ScreenshotGetName
|
||||
==================
|
||||
*/
|
||||
static qboolean CL_ScreenshotGetName( const char *fmt, int lastnum, char *filename, size_t size )
|
||||
{
|
||||
if( lastnum < 0 || lastnum > 9999 )
|
||||
return false;
|
||||
|
||||
return Q_snprintf( filename, size, fmt, clgame.mapname, lastnum ) > 0;
|
||||
}
|
||||
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
@@ -257,6 +271,7 @@ void CL_GenericShot_f( void )
|
||||
case scrshot_normal:
|
||||
case scrshot_snapshot:
|
||||
{
|
||||
const char *fmt;
|
||||
string checkname;
|
||||
int i;
|
||||
|
||||
@@ -268,18 +283,15 @@ void CL_GenericShot_f( void )
|
||||
}
|
||||
|
||||
if( type == scrshot_snapshot )
|
||||
{
|
||||
fmt = "../%s_%04d.png";
|
||||
FS_AllowDirectPaths( true );
|
||||
}
|
||||
else fmt = "scrshots/%s_shot%04d.png";
|
||||
|
||||
for( i = 0; i < 9999; i++ )
|
||||
{
|
||||
int ret;
|
||||
|
||||
if( type == scrshot_snapshot )
|
||||
ret = Q_snprintf( checkname, sizeof( checkname ), "../%s_%04d.png", clgame.mapname, i );
|
||||
else
|
||||
ret = Q_snprintf( checkname, sizeof( checkname ), "scrshots/%s_shot%04d.png", clgame.mapname, i );
|
||||
|
||||
if( ret <= 0 )
|
||||
if( !CL_ScreenshotGetName( fmt, i, checkname, sizeof( checkname )))
|
||||
{
|
||||
Con_Printf( S_ERROR "unable to write %s\n", argv0 );
|
||||
FS_AllowDirectPaths( false );
|
||||
|
||||
@@ -198,44 +198,3 @@ void CL_WriteMessageHistory( void )
|
||||
CL_WriteErrorMessage( old->starting_offset, msg );
|
||||
cls_message_debug.parsing = false;
|
||||
}
|
||||
|
||||
void CL_ReplayBufferDat_f( void )
|
||||
{
|
||||
file_t *f = FS_Open( Cmd_Argv( 1 ), "rb", true );
|
||||
sizebuf_t msg;
|
||||
char buffer[NET_MAX_MESSAGE];
|
||||
int starting_count, current_count, protocol;
|
||||
fs_offset_t len;
|
||||
|
||||
if( !f )
|
||||
return;
|
||||
|
||||
FS_Read( f, &starting_count, sizeof( starting_count ));
|
||||
FS_Read( f, ¤t_count, sizeof( current_count ));
|
||||
FS_Read( f, &protocol, sizeof( protocol ));
|
||||
|
||||
cls.legacymode = protocol;
|
||||
|
||||
len = FS_Read( f, buffer, sizeof( buffer ));
|
||||
FS_Close( f );
|
||||
|
||||
MSG_Init( &msg, __func__, buffer, len );
|
||||
|
||||
Delta_Shutdown();
|
||||
Delta_Init();
|
||||
|
||||
clgame.maxEntities = MAX_EDICTS;
|
||||
clgame.entities = Mem_Calloc( clgame.mempool, sizeof( *clgame.entities ) * clgame.maxEntities );
|
||||
|
||||
// ad-hoc implement
|
||||
#if 0
|
||||
{
|
||||
const int message_pos = 12; // put real number here
|
||||
MSG_SeekToBit( &msg, ( message_pos - 12 + 1 ) << 3, SEEK_SET );
|
||||
|
||||
CL_ParseYourMom( &msg, protocol );
|
||||
}
|
||||
#endif
|
||||
|
||||
Sys_Quit( __func__ );
|
||||
}
|
||||
|
||||
@@ -642,7 +642,9 @@ static void CL_ReadDemoUserCmd( qboolean discard )
|
||||
pcmd->sendsize = 1;
|
||||
|
||||
// always delta'ing from null
|
||||
MSG_ReadDeltaUsercmd( &buf, &nullcmd, &pcmd->cmd );
|
||||
cl.cmd = &pcmd->cmd;
|
||||
|
||||
MSG_ReadDeltaUsercmd( &buf, &nullcmd, cl.cmd );
|
||||
|
||||
// make sure what interp info contain angles from different frames
|
||||
// or lerping will stop working
|
||||
@@ -654,16 +656,13 @@ static void CL_ReadDemoUserCmd( qboolean discard )
|
||||
|
||||
// record update
|
||||
a->starttime = demo.timestamp;
|
||||
VectorCopy( pcmd->cmd.viewangles, a->viewangles );
|
||||
VectorCopy( cl.cmd->viewangles, a->viewangles );
|
||||
demo.lasttime = demo.timestamp;
|
||||
}
|
||||
|
||||
// NOTE: we need to have the current outgoing sequence correct
|
||||
// so we can do prediction correctly during playback
|
||||
cls.netchan.outgoing_sequence = outgoing_sequence;
|
||||
|
||||
// save last usercmd
|
||||
cl.cmd = pcmd->cmd;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1146,7 +1145,8 @@ void CL_DemoInterpolateAngles( void )
|
||||
QuaternionSlerp( q2, q1, frac, q );
|
||||
QuaternionAngle( q, cl.viewangles );
|
||||
}
|
||||
else VectorCopy( cl.cmd.viewangles, cl.viewangles );
|
||||
else if( cl.cmd != NULL )
|
||||
VectorCopy( cl.cmd->viewangles, cl.viewangles );
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -405,11 +405,7 @@ void CL_ParseReliableEvent( sizebuf_t *msg, connprotocol_t proto )
|
||||
}
|
||||
|
||||
if( args.entindex > 0 && args.entindex <= cl.maxclients )
|
||||
{
|
||||
args.angles[PITCH] *= 3.0f;
|
||||
if( !FBitSet( host.features, ENGINE_COMPENSATE_QUAKE_BUG ))
|
||||
args.angles[PITCH] = -args.angles[PITCH];
|
||||
}
|
||||
args.angles[PITCH] *= -3.0f;
|
||||
|
||||
CL_QueueEvent( FEV_RELIABLE|FEV_SERVER, event_index, delay, &args );
|
||||
}
|
||||
@@ -481,9 +477,7 @@ void CL_ParseEvent( sizebuf_t *msg, connprotocol_t proto )
|
||||
|
||||
if( state->number > 0 && state->number <= cl.maxclients )
|
||||
{
|
||||
args.angles[PITCH] *= 3.0f;
|
||||
if( !FBitSet( host.features, ENGINE_COMPENSATE_QUAKE_BUG ))
|
||||
args.angles[PITCH] = -args.angles[PITCH];
|
||||
args.angles[PITCH] *= -3.0f;
|
||||
CL_CalcPlayerVelocity( state->number, args.velocity );
|
||||
args.ducking = ( state->usehull == 1 );
|
||||
}
|
||||
@@ -493,11 +487,7 @@ void CL_ParseEvent( sizebuf_t *msg, connprotocol_t proto )
|
||||
if( args.entindex != 0 )
|
||||
{
|
||||
if( args.entindex > 0 && args.entindex <= cl.maxclients )
|
||||
{
|
||||
args.angles[PITCH] /= 3.0f;
|
||||
if( !FBitSet( host.features, ENGINE_COMPENSATE_QUAKE_BUG ))
|
||||
args.angles[PITCH] = -args.angles[PITCH];
|
||||
}
|
||||
args.angles[PITCH] /= -3.0f;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -173,7 +173,7 @@ static int CL_CalcTabStop( const cl_font_t *font, int x )
|
||||
return stop;
|
||||
}
|
||||
|
||||
int CL_DrawCharacter( float x, float y, int number, const rgba_t color, cl_font_t *font, int flags )
|
||||
int CL_DrawCharacter( float x, float y, int number, rgba_t color, cl_font_t *font, int flags )
|
||||
{
|
||||
wrect_t *rc;
|
||||
float w, h;
|
||||
@@ -231,7 +231,7 @@ int CL_DrawCharacter( float x, float y, int number, const rgba_t color, cl_font_
|
||||
return font->charWidths[number];
|
||||
}
|
||||
|
||||
int CL_DrawString( float x, float y, const char *s, const rgba_t color, cl_font_t *font, int flags )
|
||||
int CL_DrawString( float x, float y, const char *s, rgba_t color, cl_font_t *font, int flags )
|
||||
{
|
||||
rgba_t current_color;
|
||||
int draw_len = 0;
|
||||
@@ -287,7 +287,7 @@ int CL_DrawString( float x, float y, const char *s, const rgba_t color, cl_font_
|
||||
return draw_len;
|
||||
}
|
||||
|
||||
int CL_DrawStringf( cl_font_t *font, float x, float y, const rgba_t color, int flags, const char *fmt, ... )
|
||||
int CL_DrawStringf( cl_font_t *font, float x, float y, rgba_t color, int flags, const char *fmt, ... )
|
||||
{
|
||||
va_list va;
|
||||
char buf[MAX_VA_STRING];
|
||||
|
||||
@@ -13,12 +13,6 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#if XASH_SDL == 2
|
||||
#include <SDL.h> // SDL_GetWindowPosition
|
||||
#elif XASH_SDL == 3
|
||||
#include <SDL3/SDL.h> // SDL_GetWindowPosition
|
||||
#endif // XASH_SDL
|
||||
|
||||
#include "common.h"
|
||||
#include "client.h"
|
||||
#include "const.h"
|
||||
@@ -312,22 +306,21 @@ void SPR_AdjustSize( float *x, float *y, float *w, float *h )
|
||||
|
||||
static void SPR_AdjustTexCoords( int texnum, float width, float height, float *s1, float *t1, float *s2, float *t2 )
|
||||
{
|
||||
const qboolean filtering = REF_GET_PARM( PARM_TEX_FILTERING, texnum );
|
||||
const int xremainder = refState.width % clgame.scrInfo.iWidth;
|
||||
const int yremainder = refState.height % clgame.scrInfo.iHeight;
|
||||
|
||||
if(( filtering || xremainder ) && refState.width != clgame.scrInfo.iWidth )
|
||||
if( REF_GET_PARM( PARM_TEX_FILTERING, texnum ))
|
||||
{
|
||||
// align to texel if scaling
|
||||
*s1 += 0.5f;
|
||||
*s2 -= 0.5f;
|
||||
}
|
||||
if( refState.width != clgame.scrInfo.iWidth )
|
||||
{
|
||||
// align to texel if scaling
|
||||
*s1 += 0.5f;
|
||||
*s2 -= 0.5f;
|
||||
}
|
||||
|
||||
if(( filtering || yremainder ) && refState.height != clgame.scrInfo.iHeight )
|
||||
{
|
||||
// align to texel if scaling
|
||||
*t1 += 0.5f;
|
||||
*t2 -= 0.5f;
|
||||
if( refState.height != clgame.scrInfo.iHeight )
|
||||
{
|
||||
// align to texel if scaling
|
||||
*t1 += 0.5f;
|
||||
*t2 -= 0.5f;
|
||||
}
|
||||
}
|
||||
|
||||
*s1 /= width;
|
||||
@@ -1690,7 +1683,7 @@ get actual screen info
|
||||
*/
|
||||
int GAME_EXPORT CL_GetScreenInfo( SCREENINFO *pscrinfo )
|
||||
{
|
||||
qboolean apply_scale_factor = false; // we don't want floating point inaccuracies
|
||||
qboolean apply_scale_factor = false;
|
||||
float scale_factor = hud_scale.value;
|
||||
|
||||
if( FBitSet( hud_fontscale.flags, FCVAR_CHANGED ))
|
||||
@@ -1705,12 +1698,7 @@ int GAME_EXPORT CL_GetScreenInfo( SCREENINFO *pscrinfo )
|
||||
clgame.scrInfo.iSize = sizeof( clgame.scrInfo );
|
||||
clgame.scrInfo.iFlags = SCRINFO_SCREENFLASH;
|
||||
|
||||
if( hud_scale.value >= 320.0f && hud_scale.value >= hud_scale_minimal_width.value )
|
||||
{
|
||||
scale_factor = refState.width / hud_scale.value;
|
||||
apply_scale_factor = scale_factor > 1.0f;
|
||||
}
|
||||
else if( scale_factor && scale_factor != 1.0f )
|
||||
if( scale_factor && scale_factor != 1.0f )
|
||||
{
|
||||
float scaled_width = (float)refState.width / scale_factor;
|
||||
if( scaled_width >= hud_scale_minimal_width.value )
|
||||
@@ -2085,7 +2073,6 @@ GetWindowCenterX
|
||||
static int GAME_EXPORT pfnGetWindowCenterX( void )
|
||||
{
|
||||
int x = 0;
|
||||
|
||||
#if XASH_WIN32
|
||||
if( m_ignore.value )
|
||||
{
|
||||
@@ -2095,7 +2082,7 @@ static int GAME_EXPORT pfnGetWindowCenterX( void )
|
||||
}
|
||||
#endif
|
||||
|
||||
#if XASH_SDL >= 2
|
||||
#if XASH_SDL == 2
|
||||
SDL_GetWindowPosition( host.hWnd, &x, NULL );
|
||||
#endif
|
||||
|
||||
@@ -2111,7 +2098,6 @@ GetWindowCenterY
|
||||
static int GAME_EXPORT pfnGetWindowCenterY( void )
|
||||
{
|
||||
int y = 0;
|
||||
|
||||
#if XASH_WIN32
|
||||
if( m_ignore.value )
|
||||
{
|
||||
@@ -2121,7 +2107,7 @@ static int GAME_EXPORT pfnGetWindowCenterY( void )
|
||||
}
|
||||
#endif
|
||||
|
||||
#if XASH_SDL >= 2
|
||||
#if XASH_SDL == 2
|
||||
SDL_GetWindowPosition( host.hWnd, NULL, &y );
|
||||
#endif
|
||||
|
||||
@@ -3414,7 +3400,7 @@ static void GAME_EXPORT NetAPI_Status( net_status_t *status )
|
||||
status->latency = (connected) ? cl.frames[cl.parsecountmod].latency : 0.0;
|
||||
status->remote_address = cls.netchan.remote_address;
|
||||
status->packet_loss = packet_loss;
|
||||
NET_GetLocalAddress( &status->local_address, NULL ); // NetAPI doesn't know about IPv6
|
||||
status->local_address = net_local;
|
||||
status->rate = rate.value;
|
||||
}
|
||||
|
||||
@@ -3435,7 +3421,7 @@ static void GAME_EXPORT NetAPI_SendRequest( int context, int request, int flags,
|
||||
return;
|
||||
}
|
||||
|
||||
if( NET_NetadrType( remote_address ) == NA_IPX || NET_NetadrType( remote_address ) == NA_BROADCAST_IPX )
|
||||
if( remote_address->type == NA_IPX || remote_address->type == NA_BROADCAST_IPX )
|
||||
return; // IPX no longer support
|
||||
|
||||
if( request == NETAPI_REQUEST_SERVERLIST )
|
||||
|
||||
@@ -302,14 +302,11 @@ void UI_ConnectionProgress_ParseServerInfo( const char *server )
|
||||
|
||||
static void GAME_EXPORT UI_DrawLogo( const char *filename, float x, float y, float width, float height )
|
||||
{
|
||||
static float cin_time;
|
||||
static int last_frame = -1;
|
||||
byte *cin_data = NULL;
|
||||
movie_state_t *cin_state;
|
||||
int cin_frame;
|
||||
qboolean redraw = false;
|
||||
|
||||
if( !gameui.drawLogo ) return;
|
||||
if( !gameui.drawLogo )
|
||||
return;
|
||||
|
||||
cin_state = AVI_GetState( CIN_LOGO );
|
||||
|
||||
if( !AVI_IsActive( cin_state ))
|
||||
@@ -336,37 +333,25 @@ static void GAME_EXPORT UI_DrawLogo( const char *filename, float x, float y, flo
|
||||
gameui.drawLogo = false;
|
||||
return;
|
||||
}
|
||||
|
||||
cin_time = 0.0f;
|
||||
last_frame = -1;
|
||||
}
|
||||
|
||||
if( width <= 0 || height <= 0 )
|
||||
{
|
||||
// precache call, don't draw
|
||||
cin_time = 0.0f;
|
||||
last_frame = -1;
|
||||
return;
|
||||
}
|
||||
|
||||
// advances cinematic time (ignores maxfps and host_framerate settings)
|
||||
cin_time += host.realframetime;
|
||||
|
||||
// restarts the cinematic
|
||||
if( cin_time > gameui.logo_length )
|
||||
cin_time = 0.0f;
|
||||
AVI_SetParm( cin_state,
|
||||
AVI_RENDER_TEXNUM, 0,
|
||||
AVI_RENDER_X, (int)x,
|
||||
AVI_RENDER_Y, (int)y,
|
||||
AVI_RENDER_W, (int)width,
|
||||
AVI_RENDER_H, (int)height,
|
||||
AVI_PARM_LAST );
|
||||
|
||||
// read the next frame
|
||||
cin_frame = AVI_GetVideoFrameNumber( cin_state, cin_time );
|
||||
|
||||
if( cin_frame != last_frame )
|
||||
{
|
||||
cin_data = AVI_GetVideoFrame( cin_state, cin_frame );
|
||||
last_frame = cin_frame;
|
||||
redraw = true;
|
||||
}
|
||||
|
||||
ref.dllFuncs.R_DrawStretchRaw( x, y, width, height, gameui.logo_xres, gameui.logo_yres, cin_data, redraw );
|
||||
if( !AVI_Think( cin_state ))
|
||||
AVI_SetParm( cin_state, AVI_REWIND, AVI_PARM_LAST );
|
||||
}
|
||||
|
||||
static int GAME_EXPORT UI_GetLogoWidth( void )
|
||||
@@ -1273,16 +1258,16 @@ static void pfnEnableTextInput( int enable )
|
||||
Key_EnableTextInput( enable, false );
|
||||
}
|
||||
|
||||
static int pfnGetRenderers( unsigned int num, char *short_name, size_t size1, char *long_name, size_t size2 )
|
||||
static int pfnGetRenderers( unsigned int num, char *shortName, size_t size1, char *readableName, size_t size2 )
|
||||
{
|
||||
if( num >= ref.num_renderers )
|
||||
if( num >= ref.numRenderers )
|
||||
return 0;
|
||||
|
||||
if( short_name && size1 )
|
||||
Q_strncpy( short_name, ref.short_names[num], size1 );
|
||||
if( shortName && size1 )
|
||||
Q_strncpy( shortName, ref.shortNames[num], size1 );
|
||||
|
||||
if( long_name && size2 )
|
||||
Q_strncpy( long_name, ref.long_names[num], size2 );
|
||||
if( readableName && size2 )
|
||||
Q_strncpy( readableName, ref.readableNames[num], size2 );
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -68,11 +68,11 @@ CVAR_DEFINE_AUTO( hud_scale_minimal_width, "640", FCVAR_ARCHIVE|FCVAR_LATCH, "if
|
||||
CVAR_DEFINE_AUTO( cl_solid_players, "1", 0, "Make all players not solid (can't traceline them)" );
|
||||
CVAR_DEFINE_AUTO( cl_updaterate, "20", FCVAR_USERINFO|FCVAR_ARCHIVE, "refresh rate of server messages" );
|
||||
CVAR_DEFINE_AUTO( cl_showevents, "0", FCVAR_ARCHIVE, "show events playback" );
|
||||
CVAR_DEFINE_AUTO( cl_cmdrate, "30", FCVAR_ARCHIVE, "Max number of command packets sent to server per second" );
|
||||
CVAR_DEFINE_AUTO( cl_cmdrate, "60", FCVAR_ARCHIVE, "Max number of command packets sent to server per second" );
|
||||
CVAR_DEFINE( cl_interp, "ex_interp", "0.1", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "Interpolate object positions starting this many seconds in past" );
|
||||
CVAR_DEFINE_AUTO( cl_nointerp, "0", 0, "disable interpolation of entities and players" );
|
||||
static CVAR_DEFINE_AUTO( cl_dlmax, "0", FCVAR_USERINFO|FCVAR_ARCHIVE, "max allowed outcoming fragment size" );
|
||||
static CVAR_DEFINE_AUTO( cl_upmax, "508", FCVAR_ARCHIVE, "max allowed incoming fragment size" );
|
||||
static CVAR_DEFINE_AUTO( cl_upmax, "1200", FCVAR_ARCHIVE, "max allowed incoming fragment size" );
|
||||
|
||||
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)" );
|
||||
@@ -94,10 +94,11 @@ static CVAR_DEFINE_AUTO( name, username, FCVAR_USERINFO|FCVAR_ARCHIVE|FCVAR_PRIN
|
||||
static CVAR_DEFINE_AUTO( model, "", FCVAR_USERINFO|FCVAR_ARCHIVE|FCVAR_FILTERABLE, "player model ('player' is a singleplayer model)" );
|
||||
static CVAR_DEFINE_AUTO( topcolor, "0", FCVAR_USERINFO|FCVAR_ARCHIVE|FCVAR_FILTERABLE, "player top color" );
|
||||
static CVAR_DEFINE_AUTO( bottomcolor, "0", FCVAR_USERINFO|FCVAR_ARCHIVE|FCVAR_FILTERABLE, "player bottom color" );
|
||||
CVAR_DEFINE_AUTO( rate, "25000", FCVAR_USERINFO|FCVAR_ARCHIVE|FCVAR_FILTERABLE, "player network rate" );
|
||||
CVAR_DEFINE_AUTO( rate, "3500", FCVAR_USERINFO|FCVAR_ARCHIVE|FCVAR_FILTERABLE, "player network rate" );
|
||||
|
||||
static CVAR_DEFINE_AUTO( cl_ticket_generator, "revemu2013", FCVAR_ARCHIVE, "you wouldn't steal a car" );
|
||||
|
||||
|
||||
client_t cl;
|
||||
client_static_t cls;
|
||||
clgame_static_t clgame;
|
||||
@@ -673,7 +674,7 @@ static void CL_CreateCmd( void )
|
||||
}
|
||||
|
||||
// demo always have commands so don't overwrite them
|
||||
if( !cls.demoplayback ) cl.cmd = pcmd->cmd;
|
||||
if( !cls.demoplayback ) cl.cmd = &pcmd->cmd;
|
||||
|
||||
// predict all unacknowledged movements
|
||||
CL_PredictMovement( false );
|
||||
@@ -1008,7 +1009,7 @@ static void CL_WriteSteamTicket( sizebuf_t *send )
|
||||
const char *s;
|
||||
uint32_t crc;
|
||||
char buf[768] = { 0 }; // setti and steamemu return 768
|
||||
int i = sizeof( buf );
|
||||
size_t i = sizeof( buf );
|
||||
|
||||
if( !Q_strcmp( cl_ticket_generator.string, "null" ))
|
||||
{
|
||||
@@ -1027,7 +1028,24 @@ static void CL_WriteSteamTicket( sizebuf_t *send )
|
||||
CRC32_Init( &crc );
|
||||
CRC32_ProcessBuffer( &crc, s, Q_strlen( s ));
|
||||
crc = CRC32_Final( crc );
|
||||
i = GenerateRevEmu2013( buf, s, crc );
|
||||
|
||||
if( !Q_stricmp( cl_ticket_generator.string, "revemu2013" ))
|
||||
i = GenerateRevEmu2013( buf, crc );
|
||||
else if( !Q_stricmp( cl_ticket_generator.string, "sc2009" ))
|
||||
i = GenerateSC2009( buf, crc );
|
||||
else if( !Q_stricmp( cl_ticket_generator.string, "oldrevemu" ))
|
||||
i = GenerateOldRevEmu( buf, crc );
|
||||
else if( !Q_stricmp( cl_ticket_generator.string, "steamemu" ))
|
||||
i = GenerateSteamEmu( buf, crc );
|
||||
else if( !Q_stricmp( cl_ticket_generator.string, "revemu" ))
|
||||
i = GenerateRevEmu( buf, crc );
|
||||
else if( !Q_stricmp( cl_ticket_generator.string, "setti" ))
|
||||
i = GenerateSetti( buf );
|
||||
else if( !Q_stricmp( cl_ticket_generator.string, "avsmp" ))
|
||||
i = GenerateAVSMP( buf, crc, true );
|
||||
else
|
||||
Con_Printf( "%s: unknown generator %s, supported are: null, revemu2003, sc2009, oldrevemu, steamemu, revemu, setti, avsmp\n", __func__, cl_ticket_generator.string );
|
||||
|
||||
MSG_WriteBytes( send, buf, i );
|
||||
}
|
||||
|
||||
@@ -1045,7 +1063,6 @@ static void CL_SendConnectPacket( connprotocol_t proto, int challenge )
|
||||
const char *key = ID_GetMD5();
|
||||
netadr_t adr = { 0 };
|
||||
int input_devices;
|
||||
netadrtype_t adrtype;
|
||||
|
||||
protinfo[0] = 0;
|
||||
|
||||
@@ -1056,16 +1073,14 @@ static void CL_SendConnectPacket( connprotocol_t proto, int challenge )
|
||||
return;
|
||||
}
|
||||
|
||||
adrtype = NET_NetadrType( &adr );
|
||||
|
||||
if( adr.port == 0 ) adr.port = MSG_BigShort( PORT_SERVER );
|
||||
|
||||
input_devices = IN_CollectInputDevices();
|
||||
IN_LockInputDevices( adrtype != NA_LOOPBACK ? true : false );
|
||||
IN_LockInputDevices( adr.type != NA_LOOPBACK ? true : false );
|
||||
|
||||
// GoldSrc doesn't need sv_cheats set to 0, it's handled by svc_goldsrc_sendextrainfo
|
||||
// it also doesn't need useragent string
|
||||
if( adrtype != NA_LOOPBACK && proto != PROTO_GOLDSRC )
|
||||
if( adr.type != NA_LOOPBACK && proto != PROTO_GOLDSRC )
|
||||
{
|
||||
Cvar_SetCheatState();
|
||||
Cvar_FullSet( "sv_cheats", "0", FCVAR_READ_ONLY | FCVAR_SERVER );
|
||||
@@ -1165,11 +1180,7 @@ Returns bandwidth test fragment size
|
||||
*/
|
||||
static int CL_GetTestFragmentSize( void )
|
||||
{
|
||||
// const int fragmentSizes[CL_TEST_RETRIES] = { 64000, 32000, 10666, 5200, 1400 };
|
||||
|
||||
// it turns out, even if we pass the bandwidth test, it doesn't mean we can use such large fragments
|
||||
// as a temporary solution, use smaller fragment sizes
|
||||
const int fragmentSizes[CL_TEST_RETRIES] = { 1400, 1200, 1000, 800, 508 };
|
||||
const int fragmentSizes[CL_TEST_RETRIES] = { 64000, 32000, 10666, 5200, 1400 };
|
||||
if( cls.connect_retry >= 0 && cls.connect_retry < CL_TEST_RETRIES )
|
||||
return bound( FRAGMENT_MIN_SIZE, fragmentSizes[cls.connect_retry], FRAGMENT_MAX_SIZE );
|
||||
else
|
||||
@@ -1207,7 +1218,7 @@ static void CL_CheckForResend( void )
|
||||
cls.signon = 0;
|
||||
cls.state = ca_connecting;
|
||||
Q_strncpy( cls.servername, "localhost", sizeof( cls.servername ));
|
||||
NET_NetadrSetType( &cls.serveradr, NA_LOOPBACK );
|
||||
cls.serveradr.type = NA_LOOPBACK;
|
||||
cls.legacymode = PROTO_CURRENT;
|
||||
|
||||
// we don't need a challenge on the localhost
|
||||
@@ -1543,8 +1554,8 @@ static void CL_SendDisconnectMessage( connprotocol_t proto )
|
||||
MSG_WriteString( &buf, "dropclient\n" );
|
||||
else MSG_WriteString( &buf, "disconnect" );
|
||||
|
||||
if( NET_NetadrType( &cls.netchan.remote_address ) == NA_UNDEFINED )
|
||||
NET_NetadrSetType( &cls.netchan.remote_address, NA_LOOPBACK );
|
||||
if( !cls.netchan.remote_address.type )
|
||||
cls.netchan.remote_address.type = NA_LOOPBACK;
|
||||
|
||||
// make sure message will be delivered
|
||||
Netchan_TransmitBits( &cls.netchan, MSG_GetNumBitsWritten( &buf ), MSG_GetData( &buf ));
|
||||
@@ -1713,17 +1724,19 @@ CL_LocalServers_f
|
||||
*/
|
||||
static void CL_LocalServers_f( void )
|
||||
{
|
||||
netadr_t adr = { 0 };
|
||||
netadr_t adr;
|
||||
|
||||
memset( &adr, 0, sizeof( adr ));
|
||||
|
||||
Con_Printf( "Scanning for servers on the local network area...\n" );
|
||||
NET_Config( true, true ); // allow remote
|
||||
|
||||
// send a broadcast packet
|
||||
NET_NetadrSetType( &adr, NA_BROADCAST );
|
||||
adr.type = NA_BROADCAST;
|
||||
adr.port = MSG_BigShort( PORT_SERVER );
|
||||
Netchan_OutOfBandPrint( NS_CLIENT, adr, A2A_INFO" %i", PROTOCOL_VERSION );
|
||||
|
||||
NET_NetadrSetType( &adr, NA_MULTICAST_IP6 );
|
||||
adr.type = NA_MULTICAST_IP6;
|
||||
Netchan_OutOfBandPrint( NS_CLIENT, adr, A2A_INFO" %i", PROTOCOL_VERSION );
|
||||
}
|
||||
|
||||
@@ -2467,18 +2480,18 @@ static void CL_ServerList( netadr_t from, sizebuf_t *msg )
|
||||
while( MSG_GetNumBitsLeft( msg ) > 8 )
|
||||
{
|
||||
uint8_t addr[16];
|
||||
netadr_t servadr = { 0 };
|
||||
netadr_t servadr;
|
||||
|
||||
if( NET_NetadrType( &from ) == NA_IP6 ) // IPv6 master server only sends IPv6 addresses
|
||||
if( from.type6 == NA_IP6 ) // IPv6 master server only sends IPv6 addresses
|
||||
{
|
||||
MSG_ReadBytes( msg, addr, sizeof( addr ));
|
||||
NET_IP6BytesToNetadr( &servadr, addr );
|
||||
NET_NetadrSetType( &servadr, NA_IP6 );
|
||||
servadr.type6 = NA_IP6;
|
||||
}
|
||||
else
|
||||
{
|
||||
MSG_ReadBytes( msg, servadr.ip, sizeof( servadr.ip )); // 4 bytes for IP
|
||||
NET_NetadrSetType( &servadr, NA_IP );
|
||||
servadr.type = NA_IP;
|
||||
}
|
||||
servadr.port = MSG_ReadShort( msg ); // 2 bytes for Port
|
||||
|
||||
@@ -3126,9 +3139,6 @@ static qboolean CL_ShouldRescanFilesystem( void )
|
||||
}
|
||||
}
|
||||
|
||||
if( FBitSet( fs_mount_lv.flags|fs_mount_hd.flags|fs_mount_addon.flags|fs_mount_l10n.flags|ui_language.flags, FCVAR_CHANGED ))
|
||||
retval = true;
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
@@ -3138,7 +3148,7 @@ qboolean CL_PrecacheResources( void )
|
||||
|
||||
// if we downloaded new WAD files or any other archives they must be added to searchpath
|
||||
if( CL_ShouldRescanFilesystem( ))
|
||||
FS_Rescan_f();
|
||||
g_fsapi.Rescan();
|
||||
|
||||
// NOTE: world need to be loaded as first model
|
||||
for( pRes = cl.resourcesonhand.pNext; pRes && pRes != &cl.resourcesonhand; pRes = pRes->pNext )
|
||||
@@ -3462,10 +3472,10 @@ static void CL_InitLocal( void )
|
||||
Cmd_AddRestrictedCommand ("userinfo", CL_SetInfo_f, "examine or change the userinfo string (alias of setinfo)" );
|
||||
Cmd_AddCommand ("physinfo", CL_Physinfo_f, "print current client physinfo" );
|
||||
Cmd_AddCommand ("disconnect", CL_Disconnect_f, "disconnect from server" );
|
||||
Cmd_AddRestrictedCommand( "record", CL_Record_f, "record a demo" );
|
||||
Cmd_AddCommand ("record", CL_Record_f, "record a demo" );
|
||||
Cmd_AddCommand ("playdemo", CL_PlayDemo_f, "play a demo" );
|
||||
Cmd_AddCommand ("timedemo", CL_TimeDemo_f, "demo benchmark" );
|
||||
Cmd_AddRestrictedCommand( "killdemo", CL_DeleteDemo_f, "delete a specified demo file" );
|
||||
Cmd_AddCommand ("killdemo", CL_DeleteDemo_f, "delete a specified demo file" );
|
||||
Cmd_AddCommand ("startdemos", CL_StartDemos_f, "start playing back the selected demos sequentially" );
|
||||
Cmd_AddCommand ("demos", CL_Demos_f, "restart looping demos defined by the last startdemos command" );
|
||||
Cmd_AddCommand ("movie", CL_PlayVideo_f, "play a movie" );
|
||||
@@ -3479,8 +3489,6 @@ static void CL_InitLocal( void )
|
||||
Cmd_AddCommand ("fullserverinfo", CL_FullServerinfo_f, "sent by server when serverinfo changes" );
|
||||
Cmd_AddCommand ("upload", CL_BeginUpload_f, "uploading file to the server" );
|
||||
|
||||
Cmd_AddRestrictedCommand( "replaybufferdat", CL_ReplayBufferDat_f, "development and debugging tool" );
|
||||
|
||||
Cmd_AddRestrictedCommand ("quit", CL_Quit_f, "quit from game" );
|
||||
Cmd_AddRestrictedCommand ("exit", CL_Quit_f, "quit from game" );
|
||||
|
||||
@@ -3677,7 +3685,7 @@ void CL_Shutdown( void )
|
||||
{
|
||||
Con_Printf( "%s()\n", __func__ );
|
||||
|
||||
if( host.status != HOST_CRASHED && cls.initialized )
|
||||
if( !host.crashed && cls.initialized )
|
||||
{
|
||||
Host_WriteOpenGLConfig ();
|
||||
Host_WriteVideoConfig ();
|
||||
|
||||
@@ -92,11 +92,6 @@ static char *pfnParseFileSafe( char *data, char *buf, const int size, unsigned i
|
||||
return COM_ParseFileSafe( data, buf, size, flags, len, NULL );
|
||||
}
|
||||
|
||||
static void GAME_EXPORT pfnSetCustomClientID( const char *id )
|
||||
{
|
||||
// deprecated
|
||||
}
|
||||
|
||||
static const mobile_engfuncs_t gMobileEngfuncs =
|
||||
{
|
||||
MOBILITY_API_VERSION,
|
||||
@@ -111,7 +106,7 @@ static const mobile_engfuncs_t gMobileEngfuncs =
|
||||
pfnDrawScaledCharacter,
|
||||
Sys_Warn,
|
||||
Sys_GetNativeObject,
|
||||
pfnSetCustomClientID,
|
||||
ID_SetCustomClientID,
|
||||
pfnParseFileSafe
|
||||
};
|
||||
|
||||
|
||||
@@ -83,10 +83,7 @@ static void CL_ParseNewMovevars( sizebuf_t *msg )
|
||||
R_SetupSky( clgame.movevars.skyName );
|
||||
|
||||
clgame.oldmovevars = clgame.movevars;
|
||||
|
||||
// FIXME: set world wave height when entities will be allocated
|
||||
if( clgame.entities )
|
||||
clgame.entities->curstate.scale = clgame.movevars.waveHeight;
|
||||
clgame.entities->curstate.scale = clgame.movevars.waveHeight;
|
||||
|
||||
// keep features an actual!
|
||||
clgame.oldmovevars.features = clgame.movevars.features = host.features;
|
||||
|
||||
@@ -973,7 +973,7 @@ void CL_MoveSpectatorCamera( void )
|
||||
|
||||
CL_SetUpPlayerPrediction( false, true );
|
||||
CL_SetSolidPlayers( cl.playernum );
|
||||
CL_RunUsercmd( &cls.spectator_state, &cls.spectator_state, &cl.cmd, true, &time, (uint)( time * 100.0 ));
|
||||
CL_RunUsercmd( &cls.spectator_state, &cls.spectator_state, cl.cmd, true, &time, (uint)( time * 100.0 ));
|
||||
|
||||
VectorCopy( cls.spectator_state.client.velocity, cl.simvel );
|
||||
VectorCopy( cls.spectator_state.client.origin, cl.simorg );
|
||||
|
||||
@@ -233,7 +233,7 @@ 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 )
|
||||
static void pfnAVI_StreamSound( movie_state_t *avi, int entnum, float fvol, float attn, float synctime )
|
||||
{
|
||||
return; // stub, use AVI_SetParm and AVI_Think to stream AVI sound
|
||||
}
|
||||
@@ -263,16 +263,16 @@ static render_api_t gRenderAPI =
|
||||
NULL, // DrawSingleDecal,
|
||||
NULL, // R_DecalSetupVerts,
|
||||
NULL, // R_EntityRemoveDecals,
|
||||
(void*)AVI_LoadVideo,
|
||||
(void*)AVI_GetVideoInfo,
|
||||
(void*)AVI_GetVideoFrameNumber,
|
||||
(void*)AVI_GetVideoFrame,
|
||||
AVI_LoadVideo,
|
||||
AVI_GetVideoInfo,
|
||||
AVI_GetVideoFrameNumber,
|
||||
AVI_GetVideoFrame,
|
||||
NULL, // R_UploadStretchRaw,
|
||||
(void*)AVI_FreeVideo,
|
||||
(void*)AVI_IsActive,
|
||||
(void*)pfnAVI_StreamSound,
|
||||
NULL,
|
||||
NULL,
|
||||
AVI_FreeVideo,
|
||||
AVI_IsActive,
|
||||
pfnAVI_StreamSound,
|
||||
AVI_Think,
|
||||
AVI_SetParm,
|
||||
NULL, // GL_Bind,
|
||||
NULL, // GL_SelectTexture,
|
||||
NULL, // GL_LoadTexMatrixExt,
|
||||
|
||||
@@ -955,6 +955,7 @@ void GAME_EXPORT R_BloodSprite( const vec3_t org, int colorIndex, int modelIndex
|
||||
if( pTemp->entity.curstate.frame > 8.0f )
|
||||
pTemp->entity.curstate.frame = pTemp->frameMax;
|
||||
|
||||
pTemp->entity.baseline.origin[2] += COM_RandomFloat( 4.0f, 16.0f ) * size;
|
||||
pTemp->entity.angles[2] = COM_RandomFloat( 0.0f, 360.0f );
|
||||
pTemp->bounceFactor = 0.0f;
|
||||
}
|
||||
@@ -2428,7 +2429,7 @@ void CL_SetLightstyle( int style, const char *s, float f )
|
||||
|
||||
if( unlikely( style < 0 || style >= MAX_LIGHTSTYLES ))
|
||||
{
|
||||
Con_Printf( S_WARN "%s: ignored invalid lightstyle id %d\n", __func__, style );
|
||||
Con_Printf( S_WARN "%s: ignored invalid lightstyle id %d\n", style );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -24,11 +24,6 @@ AVI PLAYING
|
||||
=================================================================
|
||||
*/
|
||||
|
||||
static int xres, yres;
|
||||
static float video_duration;
|
||||
static float cin_time;
|
||||
static int cin_frame;
|
||||
static wavdata_t cin_audio;
|
||||
static movie_state_t *cin_state;
|
||||
|
||||
/*
|
||||
@@ -88,7 +83,17 @@ void SCR_CheckStartupVids( void )
|
||||
char *pfile;
|
||||
string token;
|
||||
|
||||
if( Sys_CheckParm( "-nointro" ) || host_developer.value || cls.demonum != -1 || GameState->nextstate != STATE_RUNFRAME )
|
||||
#if 0
|
||||
if( host_developer.value )
|
||||
{
|
||||
// don't run movies where we in developer-mode
|
||||
cls.movienum = -1;
|
||||
CL_CheckStartupDemos();
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
if( Sys_CheckParm( "-nointro" ) || cls.demonum != -1 || GameState->nextstate != STATE_RUNFRAME )
|
||||
{
|
||||
// don't run movies where we in developer-mode
|
||||
cls.movienum = -1;
|
||||
@@ -147,23 +152,9 @@ void SCR_RunCinematic( void )
|
||||
Key_SetKeyDest( key_menu );
|
||||
S_StopStreaming();
|
||||
cls.movienum = -1;
|
||||
cin_time = 0.0f;
|
||||
cls.signon = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
// advances cinematic time (ignores maxfps and host_framerate settings)
|
||||
cin_time += host.realframetime;
|
||||
|
||||
// stop the video after it finishes
|
||||
if( cin_time > video_duration + 0.1f )
|
||||
{
|
||||
SCR_NextMovie( );
|
||||
return;
|
||||
}
|
||||
|
||||
// read the next frame
|
||||
cin_frame = AVI_GetVideoFrameNumber( cin_state, cin_time );
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -176,21 +167,11 @@ should be skipped
|
||||
*/
|
||||
qboolean SCR_DrawCinematic( void )
|
||||
{
|
||||
static int last_frame = -1;
|
||||
qboolean redraw = false;
|
||||
byte *frame = NULL;
|
||||
|
||||
if( !ref.initialized || cin_time <= 0.0f )
|
||||
if( !ref.initialized )
|
||||
return false;
|
||||
|
||||
if( cin_frame != last_frame )
|
||||
{
|
||||
frame = AVI_GetVideoFrame( cin_state, cin_frame );
|
||||
last_frame = cin_frame;
|
||||
redraw = true;
|
||||
}
|
||||
|
||||
ref.dllFuncs.R_DrawStretchRaw( 0, 0, refState.width, refState.height, xres, yres, frame, redraw );
|
||||
if( !AVI_Think( cin_state ))
|
||||
return SCR_NextMovie();
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -219,45 +200,28 @@ qboolean SCR_PlayCinematic( const char *arg )
|
||||
return false;
|
||||
}
|
||||
|
||||
if( !( AVI_GetVideoInfo( cin_state, &xres, &yres, &video_duration ))) // couldn't open this at all.
|
||||
{
|
||||
AVI_CloseVideo( cin_state );
|
||||
return false;
|
||||
}
|
||||
|
||||
if( AVI_GetAudioInfo( cin_state, &cin_audio ))
|
||||
if( AVI_HaveAudioTrack( cin_state ))
|
||||
{
|
||||
// begin streaming
|
||||
S_StopAllSounds( true );
|
||||
S_StartStreaming();
|
||||
}
|
||||
|
||||
AVI_SetParm( cin_state,
|
||||
AVI_RENDER_X, 0,
|
||||
AVI_RENDER_Y, 0,
|
||||
AVI_RENDER_W, -1,
|
||||
AVI_RENDER_H, -1,
|
||||
AVI_PARM_LAST );
|
||||
|
||||
UI_SetActiveMenu( false );
|
||||
cls.state = ca_cinematic;
|
||||
Con_FastClose();
|
||||
cin_time = 0.0f;
|
||||
cls.signon = 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int SCR_GetAudioChunk( char *rawdata, int length )
|
||||
{
|
||||
int r;
|
||||
|
||||
r = AVI_GetAudioChunk( cin_state, rawdata, cin_audio.loopStart, length );
|
||||
cin_audio.loopStart += r; // advance play position
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
wavdata_t *SCR_GetMovieInfo( void )
|
||||
{
|
||||
if( AVI_IsActive( cin_state ))
|
||||
return &cin_audio;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
SCR_StopCinematic
|
||||
@@ -270,7 +234,6 @@ void SCR_StopCinematic( void )
|
||||
|
||||
AVI_CloseVideo( cin_state );
|
||||
S_StopStreaming();
|
||||
cin_time = 0.0f;
|
||||
|
||||
cls.state = ca_disconnected;
|
||||
cls.signon = 0;
|
||||
|
||||
@@ -165,7 +165,7 @@ static void V_SetRefParams( ref_params_t *fd )
|
||||
|
||||
// get pointers to movement vars and user cmd
|
||||
fd->movevars = &clgame.movevars;
|
||||
fd->cmd = &cl.cmd;
|
||||
fd->cmd = cl.cmd;
|
||||
|
||||
// setup viewport
|
||||
fd->viewport[0] = clgame.viewport[0];
|
||||
|
||||
@@ -234,7 +234,7 @@ typedef struct
|
||||
cl_local_data_t local;
|
||||
|
||||
// player final info
|
||||
usercmd_t cmd; // cl.commands[outgoing_sequence].cmd
|
||||
usercmd_t *cmd; // cl.commands[outgoing_sequence].cmd
|
||||
vec3_t viewangles;
|
||||
vec3_t viewheight;
|
||||
vec3_t punchangle;
|
||||
@@ -737,7 +737,6 @@ void CL_ClearResourceLists( void );
|
||||
//
|
||||
// cl_debug.c
|
||||
//
|
||||
void CL_ReplayBufferDat_f( void );
|
||||
void CL_Parse_Debug( qboolean enable );
|
||||
void CL_Parse_RecordCommand( int cmd, int startoffset );
|
||||
void CL_ResetFrame( frame_t *frame );
|
||||
@@ -807,11 +806,11 @@ qboolean Con_LoadFixedWidthFont( const char *fontname, cl_font_t *font, float sc
|
||||
qboolean Con_LoadVariableWidthFont( const char *fontname, cl_font_t *font, float scale, convar_t *rendermode, uint texFlags );
|
||||
void CL_FreeFont( cl_font_t *font );
|
||||
void CL_SetFontRendermode( cl_font_t *font );
|
||||
int CL_DrawCharacter( float x, float y, int number, const rgba_t color, cl_font_t *font, int flags );
|
||||
int CL_DrawString( float x, float y, const char *s, const rgba_t color, cl_font_t *font, int flags );
|
||||
int CL_DrawCharacter( float x, float y, int number, rgba_t color, cl_font_t *font, int flags );
|
||||
int CL_DrawString( float x, float y, const char *s, rgba_t color, cl_font_t *font, int flags );
|
||||
void CL_DrawCharacterLen( cl_font_t *font, int number, int *width, int *height );
|
||||
void CL_DrawStringLen( cl_font_t *font, const char *s, int *width, int *height, int flags );
|
||||
int CL_DrawStringf( cl_font_t *font, float x, float y, const rgba_t color, int flags, const char *fmt, ... ) FORMAT_CHECK( 6 );
|
||||
int CL_DrawStringf( cl_font_t *font, float x, float y, rgba_t color, int flags, const char *fmt, ... ) FORMAT_CHECK( 6 );
|
||||
|
||||
|
||||
//
|
||||
@@ -844,21 +843,19 @@ void CL_EnableScissor( scissor_state_t *scissor, int x, int y, int width, int he
|
||||
void CL_DisableScissor( scissor_state_t *scissor );
|
||||
qboolean CL_Scissor( const scissor_state_t *scissor, float *x, float *y, float *width, float *height, float *u0, float *v0, float *u1, float *v1 );
|
||||
|
||||
static inline cl_entity_t *CL_EDICT_NUM( int index )
|
||||
static inline cl_entity_t *CL_EDICT_NUM( int n )
|
||||
{
|
||||
if( !clgame.entities ) // not in game yet
|
||||
if( !clgame.entities )
|
||||
{
|
||||
Host_Error( "%s: clgame.entities is NULL\n", __func__ );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if( index < 0 || index >= clgame.maxEntities )
|
||||
{
|
||||
Host_Error( "%s: bad number %i\n", __func__, index );
|
||||
return NULL;
|
||||
}
|
||||
if(( n >= 0 ) && ( n < clgame.maxEntities ))
|
||||
return clgame.entities + n;
|
||||
|
||||
return clgame.entities + index;
|
||||
Host_Error( "%s: bad number %i\n", __func__, n );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline cl_entity_t *CL_GetEntityByIndex( int index )
|
||||
@@ -869,7 +866,10 @@ static inline cl_entity_t *CL_GetEntityByIndex( int index )
|
||||
if( index < 0 || index >= clgame.maxEntities )
|
||||
return NULL;
|
||||
|
||||
return clgame.entities + index;
|
||||
if( index == 0 )
|
||||
return clgame.entities;
|
||||
|
||||
return CL_EDICT_NUM( index );
|
||||
}
|
||||
|
||||
static inline model_t *CL_ModelHandle( int modelindex )
|
||||
@@ -879,7 +879,7 @@ static inline model_t *CL_ModelHandle( int modelindex )
|
||||
|
||||
static inline qboolean CL_IsThirdPerson( void )
|
||||
{
|
||||
return clgame.dllFuncs.CL_IsThirdPerson();
|
||||
return clgame.dllFuncs.CL_IsThirdPerson() ? true : false;
|
||||
}
|
||||
|
||||
static inline cl_entity_t *CL_GetLocalPlayer( void )
|
||||
@@ -1107,7 +1107,7 @@ int Con_UtfMoveRight( char *str, int pos, int length );
|
||||
void Con_DefaultColor( int r, int g, int b, qboolean gameui );
|
||||
cl_font_t *Con_GetCurFont( void );
|
||||
cl_font_t *Con_GetFont( int num );
|
||||
int Con_DrawString( int x, int y, const char *string, const rgba_t setColor ); // legacy, use cl_font.c
|
||||
int Con_DrawString( int x, int y, const char *string, rgba_t setColor ); // legacy, use cl_font.c
|
||||
void GAME_EXPORT Con_DrawStringLen( const char *pText, int *length, int *height ); // legacy, use cl_font.c
|
||||
void Con_CharEvent( int key );
|
||||
void Key_Console( int key );
|
||||
@@ -1214,6 +1214,7 @@ void OSK_Draw( void );
|
||||
//
|
||||
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;
|
||||
|
||||
@@ -622,7 +622,7 @@ int Con_UtfProcessCharForce( int in )
|
||||
// TODO: get rid of global state where possible
|
||||
static utfstate_t state = { 0 };
|
||||
|
||||
uint32_t ch = Q_DecodeUTF8( &state, in );
|
||||
int ch = Q_DecodeUTF8( &state, in );
|
||||
|
||||
if( g_codepage == 1251 )
|
||||
return Q_UnicodeToCP1251( ch );
|
||||
@@ -759,7 +759,7 @@ Con_DrawString
|
||||
client version of routine
|
||||
====================
|
||||
*/
|
||||
int Con_DrawString( int x, int y, const char *string, const rgba_t setColor )
|
||||
int Con_DrawString( int x, int y, const char *string, rgba_t setColor )
|
||||
{
|
||||
return CL_DrawString( x, y, string, setColor, con.curFont, FONT_DRAW_UTF8 );
|
||||
}
|
||||
@@ -843,14 +843,11 @@ If no console is visible, the notify window will pop up.
|
||||
*/
|
||||
void Con_Print( const char *txt )
|
||||
{
|
||||
static qboolean cr_pending = false;
|
||||
static qboolean colorstring = false;
|
||||
static char buf[MAX_PRINT_MSG];
|
||||
static int lastlength = 0;
|
||||
static int bufpos = 0;
|
||||
static int charpos = 0;
|
||||
|
||||
qboolean norefresh = false;
|
||||
static int cr_pending = 0;
|
||||
static char buf[MAX_PRINT_MSG];
|
||||
qboolean norefresh = false;
|
||||
static int lastlength = 0;
|
||||
static int bufpos = 0;
|
||||
int c, mask = 0;
|
||||
|
||||
// client not running
|
||||
@@ -876,7 +873,7 @@ void Con_Print( const char *txt )
|
||||
if( cr_pending )
|
||||
{
|
||||
Con_DeleteLastLine();
|
||||
cr_pending = false;
|
||||
cr_pending = 0;
|
||||
}
|
||||
c = *txt;
|
||||
|
||||
@@ -889,42 +886,23 @@ void Con_Print( const char *txt )
|
||||
{
|
||||
Con_AddLine( buf, bufpos, true );
|
||||
lastlength = CON_LINES_LAST().length;
|
||||
cr_pending = true;
|
||||
cr_pending = 1;
|
||||
bufpos = 0;
|
||||
charpos = 0;
|
||||
}
|
||||
break;
|
||||
case '\n':
|
||||
Con_AddLine( buf, bufpos, true );
|
||||
lastlength = CON_LINES_LAST().length;
|
||||
bufpos = 0;
|
||||
charpos = 0;
|
||||
break;
|
||||
default:
|
||||
|
||||
buf[bufpos++] = c | mask;
|
||||
|
||||
if( IsColorString( txt ))
|
||||
{
|
||||
// first color string character
|
||||
colorstring = true;
|
||||
}
|
||||
else if( colorstring )
|
||||
{
|
||||
// second color string character
|
||||
colorstring = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// not a color string, move char counter
|
||||
charpos++;
|
||||
}
|
||||
|
||||
if(( bufpos >= sizeof( buf ) - 1 ) || charpos >= ( con.linewidth - 1 ))
|
||||
if(( bufpos >= sizeof( buf ) - 1 ) || bufpos >= ( con.linewidth - 1 ))
|
||||
{
|
||||
Con_AddLine( buf, bufpos, true );
|
||||
lastlength = CON_LINES_LAST().length;
|
||||
bufpos = 0;
|
||||
charpos = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -940,7 +918,6 @@ void Con_Print( const char *txt )
|
||||
Con_AddLine( buf, bufpos, lastlength != 0 );
|
||||
lastlength = 0;
|
||||
bufpos = 0;
|
||||
charpos = 0;
|
||||
}
|
||||
|
||||
// pump messages to avoid window hanging
|
||||
@@ -1267,16 +1244,45 @@ static void Field_CharEvent( field_t *edit, int ch )
|
||||
Field_DrawInputLine
|
||||
==================
|
||||
*/
|
||||
static void Field_DrawInputLine( int x, int y, const field_t *edit )
|
||||
static void Field_DrawInputLine( int x, int y, field_t *edit )
|
||||
{
|
||||
int curPos;
|
||||
char str[MAX_SYSPATH];
|
||||
const byte *colorDefault = g_color_table[ColorIndex( COLOR_DEFAULT )];
|
||||
const int prestep = bound( 0, edit->scroll, sizeof( edit->buffer ) - 1 );
|
||||
const int drawLen = bound( 0, edit->widthInChars, sizeof( str ));
|
||||
const int cursorCharPos = bound( 0, edit->cursor - prestep, sizeof( str ));
|
||||
int len, cursorChar;
|
||||
int drawLen;
|
||||
int prestep, curPos;
|
||||
char str[MAX_SYSPATH];
|
||||
byte *colorDefault;
|
||||
|
||||
Q_strncpy( str, edit->buffer + prestep, drawLen );
|
||||
drawLen = edit->widthInChars;
|
||||
len = Q_strlen( edit->buffer ) + 1;
|
||||
colorDefault = g_color_table[ColorIndex( COLOR_DEFAULT )];
|
||||
|
||||
// guarantee that cursor will be visible
|
||||
if( len <= drawLen )
|
||||
{
|
||||
prestep = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( edit->scroll + drawLen > len )
|
||||
{
|
||||
edit->scroll = len - drawLen;
|
||||
if( edit->scroll < 0 ) edit->scroll = 0;
|
||||
}
|
||||
|
||||
prestep = edit->scroll;
|
||||
}
|
||||
|
||||
if( prestep + drawLen > len )
|
||||
drawLen = len - prestep;
|
||||
|
||||
// extract <drawLen> characters from the field at <prestep>
|
||||
drawLen = Q_min( drawLen, MAX_SYSPATH - 1 );
|
||||
|
||||
memcpy( str, edit->buffer + prestep, drawLen );
|
||||
str[drawLen] = 0;
|
||||
|
||||
// save char for overstrike
|
||||
cursorChar = str[edit->cursor - prestep];
|
||||
|
||||
// draw it
|
||||
CL_DrawString( x, y, str, colorDefault, con.curFont, FONT_DRAW_UTF8 );
|
||||
@@ -1285,7 +1291,7 @@ static void Field_DrawInputLine( int x, int y, const field_t *edit )
|
||||
if((int)( host.realtime * 4 ) & 1 ) return; // off blink
|
||||
|
||||
// calc cursor position
|
||||
str[cursorCharPos] = 0;
|
||||
str[edit->cursor - prestep] = 0;
|
||||
CL_DrawStringLen( con.curFont, str, &curPos, NULL, FONT_DRAW_UTF8 );
|
||||
|
||||
if( host.key_overstrike )
|
||||
@@ -1461,16 +1467,6 @@ Handles history and console scrollback
|
||||
*/
|
||||
void Key_Console( int key )
|
||||
{
|
||||
// exit the console by pressing MINUS on NSwitch
|
||||
// or both Back(Select)/Start buttons for everyone else
|
||||
if( key == K_BACK_BUTTON || key == K_START_BUTTON || key == K_ESCAPE )
|
||||
{
|
||||
if( cls.state == ca_active && !cl.background )
|
||||
Key_SetKeyDest( key_game );
|
||||
else UI_SetActiveMenu( true );
|
||||
return;
|
||||
}
|
||||
|
||||
// ctrl-L clears screen
|
||||
if( key == 'l' && Key_IsDown( K_CTRL ))
|
||||
{
|
||||
@@ -1579,6 +1575,16 @@ void Key_Console( int key )
|
||||
return;
|
||||
}
|
||||
|
||||
// exit the console by pressing MINUS on NSwitch
|
||||
// or both Back(Select)/Start buttons for everyone else
|
||||
if( key == K_BACK_BUTTON || key == K_START_BUTTON )
|
||||
{
|
||||
if( cls.state == ca_active && !cl.background )
|
||||
Key_SetKeyDest( key_game );
|
||||
else UI_SetActiveMenu( true );
|
||||
return;
|
||||
}
|
||||
|
||||
// pass to the normal editline routine
|
||||
Field_KeyDownEvent( &con.input, key );
|
||||
}
|
||||
@@ -2002,7 +2008,7 @@ void Con_DrawVersion( void )
|
||||
int start, height = refState.height;
|
||||
string curbuild;
|
||||
|
||||
if( !scr_drawversion.value )
|
||||
if( !scr_drawversion.value || CL_IsDevOverviewMode() == 2 || net_graph.value )
|
||||
return;
|
||||
|
||||
if( cls.key_dest == key_menu )
|
||||
@@ -2014,9 +2020,6 @@ void Con_DrawVersion( void )
|
||||
{
|
||||
qboolean draw_version;
|
||||
|
||||
if( CL_IsDevOverviewMode() == 2 || net_graph.value )
|
||||
return;
|
||||
|
||||
draw_version = cls.scrshot_action == scrshot_normal
|
||||
|| cls.scrshot_action == scrshot_snapshot
|
||||
|| host.force_draw_version_time > host.realtime;
|
||||
@@ -2089,7 +2092,10 @@ void Con_RunConsole( void )
|
||||
}
|
||||
else
|
||||
{
|
||||
g_codepage = 0;
|
||||
Con_Printf( S_WARN "Unknown charset %s, defaulting to cp1252", con_charset.string );
|
||||
|
||||
Cvar_DirectSet( &con_charset, "cp1252" );
|
||||
g_codepage = 1252;
|
||||
}
|
||||
|
||||
cls.accept_utf8 = !Q_stricmp( cl_charset.string, "utf-8" );
|
||||
@@ -2132,31 +2138,20 @@ void Con_CharEvent( int key )
|
||||
|
||||
static int Con_LoadSimpleConback( const char *name, int flags )
|
||||
{
|
||||
int i;
|
||||
const char *paths[] = {
|
||||
"gfx/shell/%s.dds",
|
||||
"gfx/shell/%s.bmp",
|
||||
"gfx/shell/%s.tga",
|
||||
"cached/%s640",
|
||||
"cached/%s",
|
||||
};
|
||||
size_t i;
|
||||
|
||||
for( i = 0; i < 5; i++ )
|
||||
for( i = 0; i < ARRAYSIZE( paths ); i++ )
|
||||
{
|
||||
string path;
|
||||
|
||||
switch( i )
|
||||
{
|
||||
case 0:
|
||||
Q_snprintf( path, sizeof( path ), "gfx/shell/%s.dds", name );
|
||||
break;
|
||||
case 1:
|
||||
Q_snprintf( path, sizeof( path ), "gfx/shell/%s.bmp", name );
|
||||
break;
|
||||
case 2:
|
||||
Q_snprintf( path, sizeof( path ), "gfx/shell/%s.tga", name );
|
||||
break;
|
||||
case 3:
|
||||
Q_snprintf( path, sizeof( path ), "cached/%s640", name );
|
||||
break;
|
||||
case 4:
|
||||
Q_snprintf( path, sizeof( path ), "cached/%s", name );
|
||||
break;
|
||||
}
|
||||
|
||||
Q_snprintf( path, sizeof( path ), paths[i], name );
|
||||
if( g_fsapi.FileExists( path, false ))
|
||||
{
|
||||
int gl_texturenum = ref.dllFuncs.GL_LoadTexture( path, NULL, 0, flags );
|
||||
|
||||
@@ -19,8 +19,8 @@ GNU General Public License for more details.
|
||||
#if !XASH_WIN32
|
||||
#include <dirent.h>
|
||||
#endif
|
||||
|
||||
static char id_md5[33];
|
||||
static char id_customid[MAX_STRING];
|
||||
|
||||
/*
|
||||
==========================================================
|
||||
@@ -365,10 +365,10 @@ static int ID_GetKeyData( HKEY hRootKey, char *subKey, char *value, LPBYTE data,
|
||||
{
|
||||
HKEY hKey;
|
||||
|
||||
if( RegOpenKeyExA( hRootKey, subKey, 0, KEY_QUERY_VALUE, &hKey ) != ERROR_SUCCESS )
|
||||
if( RegOpenKeyEx( hRootKey, subKey, 0, KEY_QUERY_VALUE, &hKey ) != ERROR_SUCCESS )
|
||||
return 0;
|
||||
|
||||
if( RegQueryValueExA( hKey, value, NULL, NULL, data, &cbData ) != ERROR_SUCCESS )
|
||||
if( RegQueryValueEx( hKey, value, NULL, NULL, data, &cbData ) != ERROR_SUCCESS )
|
||||
{
|
||||
RegCloseKey( hKey );
|
||||
return 0;
|
||||
@@ -377,14 +377,13 @@ static int ID_GetKeyData( HKEY hRootKey, char *subKey, char *value, LPBYTE data,
|
||||
RegCloseKey( hKey );
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int ID_SetKeyData( HKEY hRootKey, char *subKey, DWORD dwType, char *value, LPBYTE data, DWORD cbData )
|
||||
static int ID_SetKeyData( HKEY hRootKey, char *subKey, DWORD dwType, char *value, LPBYTE data, DWORD cbData)
|
||||
{
|
||||
HKEY hKey;
|
||||
if( RegCreateKeyA( hRootKey, subKey, &hKey ) != ERROR_SUCCESS )
|
||||
if( RegCreateKey( hRootKey, subKey, &hKey ) != ERROR_SUCCESS )
|
||||
return 0;
|
||||
|
||||
if( RegSetValueExA( hKey, value, 0, dwType, data, cbData ) != ERROR_SUCCESS )
|
||||
if( RegSetValueEx( hKey, value, 0, dwType, data, cbData ) != ERROR_SUCCESS )
|
||||
{
|
||||
RegCloseKey( hKey );
|
||||
return 0;
|
||||
@@ -396,7 +395,7 @@ static int ID_SetKeyData( HKEY hRootKey, char *subKey, DWORD dwType, char *value
|
||||
|
||||
#define BUFSIZE 4096
|
||||
|
||||
static int ID_RunWMIC( char *buffer, const wchar_t *cmdline )
|
||||
static int ID_RunWMIC(char *buffer, const char *cmdline)
|
||||
{
|
||||
HANDLE g_IN_Rd = NULL;
|
||||
HANDLE g_IN_Wr = NULL;
|
||||
@@ -404,92 +403,75 @@ static int ID_RunWMIC( char *buffer, const wchar_t *cmdline )
|
||||
HANDLE g_OUT_Wr = NULL;
|
||||
DWORD dwRead;
|
||||
BOOL bSuccess = FALSE;
|
||||
wchar_t *cmdline_copy;
|
||||
SECURITY_ATTRIBUTES saAttr;
|
||||
|
||||
PROCESS_INFORMATION pi = { 0 };
|
||||
SECURITY_ATTRIBUTES saAttr =
|
||||
{
|
||||
.nLength = sizeof( SECURITY_ATTRIBUTES ),
|
||||
.bInheritHandle = TRUE,
|
||||
.lpSecurityDescriptor = NULL,
|
||||
};
|
||||
STARTUPINFO si = {0};
|
||||
|
||||
PROCESS_INFORMATION pi = {0};
|
||||
saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
|
||||
saAttr.bInheritHandle = TRUE;
|
||||
saAttr.lpSecurityDescriptor = NULL;
|
||||
|
||||
CreatePipe( &g_IN_Rd, &g_IN_Wr, &saAttr, 0 );
|
||||
CreatePipe( &g_OUT_Rd, &g_OUT_Wr, &saAttr, 0 );
|
||||
SetHandleInformation( g_IN_Wr, HANDLE_FLAG_INHERIT, 0 );
|
||||
|
||||
STARTUPINFO si =
|
||||
{
|
||||
.cb = sizeof( STARTUPINFO ),
|
||||
.dwFlags = STARTF_USESTDHANDLES,
|
||||
.hStdInput = g_IN_Rd,
|
||||
.hStdOutput = g_OUT_Wr,
|
||||
.hStdError = g_OUT_Wr,
|
||||
.wShowWindow = SW_HIDE,
|
||||
.dwFlags = STARTF_USESTDHANDLES,
|
||||
};
|
||||
si.cb = sizeof(STARTUPINFO);
|
||||
si.dwFlags = STARTF_USESTDHANDLES;
|
||||
si.hStdInput = g_IN_Rd;
|
||||
si.hStdOutput = g_OUT_Wr;
|
||||
si.hStdError = g_OUT_Wr;
|
||||
si.wShowWindow = SW_HIDE;
|
||||
si.dwFlags |= STARTF_USESTDHANDLES;
|
||||
|
||||
cmdline_copy = malloc( wcslen( cmdline ) * sizeof( *cmdline_copy ));
|
||||
CreateProcess( NULL, (char*)cmdline, NULL, NULL, true, CREATE_NO_WINDOW , NULL, NULL, &si, &pi );
|
||||
|
||||
if( !CreateProcessW( NULL, cmdline_copy, NULL, NULL, true, CREATE_NO_WINDOW, NULL, NULL, &si, &pi ))
|
||||
goto err;
|
||||
CloseHandle( g_OUT_Wr );
|
||||
CloseHandle( g_IN_Wr );
|
||||
|
||||
WaitForSingleObject( pi.hProcess, 500 );
|
||||
|
||||
bSuccess = ReadFile( g_OUT_Rd, buffer, BUFSIZE, &dwRead, NULL );
|
||||
buffer[BUFSIZE-1] = 0;
|
||||
|
||||
TerminateProcess( pi.hProcess, 0 );
|
||||
|
||||
CloseHandle( pi.hProcess );
|
||||
CloseHandle( pi.hThread );
|
||||
|
||||
err:
|
||||
CloseHandle( g_IN_Wr );
|
||||
CloseHandle( g_OUT_Wr );
|
||||
CloseHandle( g_IN_Rd );
|
||||
CloseHandle( g_OUT_Rd );
|
||||
|
||||
free( cmdline_copy );
|
||||
|
||||
return bSuccess;
|
||||
}
|
||||
|
||||
static int ID_ProcessWMIC( bloomfilter_t *value, const wchar_t *cmdline )
|
||||
static int ID_ProcessWMIC( bloomfilter_t *value, const char *cmdline )
|
||||
{
|
||||
char buffer[BUFSIZE], token[BUFSIZE], *pbuf;
|
||||
int count = 0;
|
||||
|
||||
if( !ID_RunWMIC( buffer, cmdline ))
|
||||
if( !ID_RunWMIC( buffer, cmdline ) )
|
||||
return 0;
|
||||
|
||||
pbuf = COM_ParseFile( buffer, token, sizeof( token )); // Header
|
||||
while( pbuf = COM_ParseFile( pbuf, token, sizeof( token )))
|
||||
while( pbuf = COM_ParseFile( pbuf, token, sizeof( token ) ) )
|
||||
{
|
||||
if( !ID_VerifyHEX( token ))
|
||||
if( !ID_VerifyHEX( token ) )
|
||||
continue;
|
||||
|
||||
*value |= BloomFilter_ProcessStr( token );
|
||||
count++;
|
||||
count ++;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static int ID_CheckWMIC( bloomfilter_t value, const wchar_t *cmdline )
|
||||
static int ID_CheckWMIC( bloomfilter_t value, const char *cmdline )
|
||||
{
|
||||
char buffer[BUFSIZE], token[BUFSIZE], *pbuf;
|
||||
int count = 0;
|
||||
|
||||
if( !ID_RunWMIC( buffer, cmdline ))
|
||||
if( !ID_RunWMIC( buffer, cmdline ) )
|
||||
return 0;
|
||||
|
||||
pbuf = COM_ParseFile( buffer, token, sizeof( token )); // Header
|
||||
while( pbuf = COM_ParseFile( pbuf, token, sizeof( token )))
|
||||
while( pbuf = COM_ParseFile( pbuf, token, sizeof( token ) ) )
|
||||
{
|
||||
bloomfilter_t filter;
|
||||
|
||||
if( !ID_VerifyHEX( token ))
|
||||
if( !ID_VerifyHEX( token ) )
|
||||
continue;
|
||||
|
||||
filter = BloomFilter_ProcessStr( token );
|
||||
@@ -505,10 +487,6 @@ static int ID_CheckWMIC( bloomfilter_t value, const wchar_t *cmdline )
|
||||
char *IOS_GetUDID( void );
|
||||
#endif
|
||||
|
||||
#if XASH_PSVITA
|
||||
int PSVita_GetPSID( char *buf, const size_t buflen );
|
||||
#endif
|
||||
|
||||
static bloomfilter_t ID_GenerateRawId( void )
|
||||
{
|
||||
bloomfilter_t value = 0;
|
||||
@@ -530,22 +508,14 @@ static bloomfilter_t ID_GenerateRawId( void )
|
||||
count += ID_ProcessNetDevices( &value );
|
||||
#endif
|
||||
#if XASH_WIN32
|
||||
count += ID_ProcessWMIC( &value, L"wmic path win32_physicalmedia get SerialNumber " );
|
||||
count += ID_ProcessWMIC( &value, L"wmic bios get serialnumber " );
|
||||
count += ID_ProcessWMIC( &value, "wmic path win32_physicalmedia get SerialNumber " );
|
||||
count += ID_ProcessWMIC( &value, "wmic bios get serialnumber " );
|
||||
#endif
|
||||
#if XASH_IOS
|
||||
{
|
||||
value |= BloomFilter_ProcessStr(IOS_GetUDID());
|
||||
count ++;
|
||||
}
|
||||
#endif
|
||||
#if XASH_PSVITA
|
||||
{
|
||||
char data[16];
|
||||
PSVita_GetPSID( data, sizeof( data ));
|
||||
value |= BloomFilter_Process( data, sizeof( data ));
|
||||
count ++;
|
||||
}
|
||||
#endif
|
||||
return value;
|
||||
}
|
||||
@@ -574,8 +544,8 @@ static uint ID_CheckRawId( bloomfilter_t filter )
|
||||
#endif
|
||||
|
||||
#if XASH_WIN32
|
||||
count += ID_CheckWMIC( filter, L"wmic path win32_physicalmedia get SerialNumber" );
|
||||
count += ID_CheckWMIC( filter, L"wmic bios get serialnumber" );
|
||||
count += ID_CheckWMIC( filter, "wmic path win32_physicalmedia get SerialNumber" );
|
||||
count += ID_CheckWMIC( filter, "wmic bios get serialnumber" );
|
||||
#endif
|
||||
|
||||
#if XASH_IOS
|
||||
@@ -585,15 +555,6 @@ static uint ID_CheckRawId( bloomfilter_t filter )
|
||||
value = 0;
|
||||
}
|
||||
#endif
|
||||
#if XASH_PSVITA
|
||||
{
|
||||
char data[16];
|
||||
PSVita_GetPSID( data, sizeof( data ));
|
||||
value = BloomFilter_Process( data, sizeof( data ));
|
||||
count += (filter & value) == value;
|
||||
value = 0;
|
||||
}
|
||||
#endif
|
||||
#if 0
|
||||
Msg( "%s: %d\n", __func__, count );
|
||||
#endif
|
||||
@@ -629,9 +590,25 @@ static void ID_Check( void )
|
||||
|
||||
const char *ID_GetMD5( void )
|
||||
{
|
||||
if( id_customid[0] )
|
||||
return id_customid;
|
||||
return id_md5;
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
ID_SetCustomClientID
|
||||
|
||||
===============
|
||||
*/
|
||||
void GAME_EXPORT ID_SetCustomClientID( const char *id )
|
||||
{
|
||||
if( !id )
|
||||
return;
|
||||
|
||||
Q_strncpy( id_customid, id, sizeof( id_customid ) );
|
||||
}
|
||||
|
||||
void ID_Init( void )
|
||||
{
|
||||
MD5Context_t hash = { 0 };
|
||||
|
||||
@@ -43,6 +43,7 @@ static struct joy_axis_s
|
||||
short val;
|
||||
short prevval;
|
||||
} joyaxis[MAX_AXES] = { 0 };
|
||||
static byte currentbinding; // add posibility to remap keys, to place it in joykeys[]
|
||||
static qboolean joy_initialized;
|
||||
|
||||
static CVAR_DEFINE_AUTO( joy_pitch, "100.0", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "joystick pitch sensitivity" );
|
||||
@@ -59,9 +60,9 @@ static CVAR_DEFINE_AUTO( joy_pitch_deadzone, DEFAULT_JOY_DEADZONE, FCVAR_ARCHIVE
|
||||
static CVAR_DEFINE_AUTO( joy_yaw_deadzone, DEFAULT_JOY_DEADZONE, FCVAR_ARCHIVE | FCVAR_FILTERABLE, "yaw axis deadzone. Value from 0 to 32767" );
|
||||
static CVAR_DEFINE_AUTO( joy_axis_binding, "sfpyrl", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "axis hardware id to engine inner axis binding, "
|
||||
"s - side, f - forward, y - yaw, p - pitch, r - left trigger, l - right trigger" );
|
||||
static CVAR_DEFINE_AUTO( joy_found, "0", FCVAR_READ_ONLY, "is joystick is connected" );
|
||||
static CVAR_DEFINE_AUTO( joy_index, "0", FCVAR_READ_ONLY, "current active joystick" );
|
||||
CVAR_DEFINE_AUTO( joy_enable, "1", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "enable joystick" );
|
||||
static CVAR_DEFINE_AUTO( joy_have_gyro, "0", FCVAR_READ_ONLY, "tells whether current active gamepad has gyroscope or not" );
|
||||
static CVAR_DEFINE_AUTO( joy_calibrated, "0", FCVAR_READ_ONLY, "tells whether current active gamepad gyroscope has been calibrated or not" );
|
||||
|
||||
/*
|
||||
============
|
||||
@@ -70,30 +71,7 @@ Joy_IsActive
|
||||
*/
|
||||
qboolean Joy_IsActive( void )
|
||||
{
|
||||
return joy_enable.value;
|
||||
}
|
||||
|
||||
/*
|
||||
===========
|
||||
Joy_SetCapabilities
|
||||
===========
|
||||
*/
|
||||
void Joy_SetCapabilities( qboolean have_gyro )
|
||||
{
|
||||
Cvar_FullSet( joy_have_gyro.name, have_gyro ? "1" : "0", joy_have_gyro.flags );
|
||||
}
|
||||
|
||||
/*
|
||||
===========
|
||||
Joy_SetCalibrationState
|
||||
===========
|
||||
*/
|
||||
void Joy_SetCalibrationState( joy_calibration_state_t state )
|
||||
{
|
||||
if( (int)joy_calibrated.value == state )
|
||||
return;
|
||||
|
||||
Cvar_FullSet( joy_calibrated.name, va( "%d", state ), joy_calibrated.flags );
|
||||
return joy_found.value && joy_enable.value;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -103,7 +81,7 @@ Joy_HatMotionEvent
|
||||
DPad events
|
||||
============
|
||||
*/
|
||||
static void Joy_HatMotionEvent( int value )
|
||||
void Joy_HatMotionEvent( byte hat, byte value )
|
||||
{
|
||||
struct
|
||||
{
|
||||
@@ -118,6 +96,9 @@ static void Joy_HatMotionEvent( int value )
|
||||
};
|
||||
int i;
|
||||
|
||||
if( !joy_found.value )
|
||||
return;
|
||||
|
||||
for( i = 0; i < ARRAYSIZE( keys ); i++ )
|
||||
{
|
||||
if( value & keys[i].mask )
|
||||
@@ -244,7 +225,7 @@ static void Joy_ProcessStick( const engineAxis_t engineAxis, short value )
|
||||
val |= Joy_GetHatValueForAxis( JOY_AXIS_SIDE );
|
||||
val |= Joy_GetHatValueForAxis( JOY_AXIS_FWD );
|
||||
|
||||
Joy_HatMotionEvent( val );
|
||||
Joy_HatMotionEvent( 0, val );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -255,9 +236,23 @@ Joy_AxisMotionEvent
|
||||
Axis events
|
||||
=============
|
||||
*/
|
||||
void Joy_AxisMotionEvent( engineAxis_t engineAxis, short value )
|
||||
void Joy_AxisMotionEvent( byte axis, short value )
|
||||
{
|
||||
if( engineAxis >= JOY_AXIS_NULL )
|
||||
if( !joy_found.value )
|
||||
return;
|
||||
|
||||
if( axis >= MAX_AXES )
|
||||
{
|
||||
Con_Reportf( "Only 6 axes is supported\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
Joy_KnownAxisMotionEvent( joyaxesmap[axis], value );
|
||||
}
|
||||
|
||||
void Joy_KnownAxisMotionEvent( engineAxis_t engineAxis, short value )
|
||||
{
|
||||
if( engineAxis == JOY_AXIS_NULL )
|
||||
return;
|
||||
|
||||
if( value == joyaxis[engineAxis].val )
|
||||
@@ -271,14 +266,66 @@ void Joy_AxisMotionEvent( engineAxis_t engineAxis, short value )
|
||||
|
||||
/*
|
||||
=============
|
||||
Joy_GyroEvent
|
||||
Joy_BallMotionEvent
|
||||
|
||||
Gyroscope events
|
||||
Trackball events. UNDONE
|
||||
=============
|
||||
*/
|
||||
void Joy_GyroEvent( vec3_t data )
|
||||
void Joy_BallMotionEvent( byte ball, short xrel, short yrel )
|
||||
{
|
||||
//if( !joy_found.value )
|
||||
// return;
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
Joy_ButtonEvent
|
||||
|
||||
Button events
|
||||
=============
|
||||
*/
|
||||
void Joy_ButtonEvent( byte button, byte down )
|
||||
{
|
||||
if( !joy_found.value )
|
||||
return;
|
||||
|
||||
// generic game button code.
|
||||
if( button > 32 )
|
||||
{
|
||||
int origbutton = button;
|
||||
button = ( button & 31 ) + K_AUX1;
|
||||
|
||||
Con_Reportf( "Only 32 joybuttons is supported, converting %i button ID to %s\n", origbutton, Key_KeynumToString( button ) );
|
||||
}
|
||||
else button += K_AUX1;
|
||||
|
||||
Key_Event( button, down );
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
Joy_RemoveEvent
|
||||
|
||||
Called when joystick is removed. For future expansion
|
||||
=============
|
||||
*/
|
||||
void Joy_RemoveEvent( void )
|
||||
{
|
||||
if( joy_found.value )
|
||||
Cvar_FullSet( "joy_found", "0", FCVAR_READ_ONLY );
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
Joy_RemoveEvent
|
||||
|
||||
Called when joystick is removed. For future expansion
|
||||
=============
|
||||
*/
|
||||
void Joy_AddEvent( void )
|
||||
{
|
||||
if( joy_enable.value && !joy_found.value )
|
||||
Cvar_FullSet( "joy_found", "1", FCVAR_READ_ONLY );
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -317,19 +364,14 @@ void Joy_FinalizeMove( float *fw, float *side, float *dpitch, float *dyaw )
|
||||
|
||||
*fw -= joy_forward.value * (float)joyaxis[JOY_AXIS_FWD ].val/(float)SHRT_MAX; // must be form -1.0 to 1.0
|
||||
*side += joy_side.value * (float)joyaxis[JOY_AXIS_SIDE].val/(float)SHRT_MAX;
|
||||
#if !defined(XASH_SDL)
|
||||
*dpitch += joy_pitch.value * (float)joyaxis[JOY_AXIS_PITCH].val/(float)SHRT_MAX * host.realframetime; // abs axis rotate is frametime related
|
||||
*dyaw -= joy_yaw.value * (float)joyaxis[JOY_AXIS_YAW ].val/(float)SHRT_MAX * host.realframetime;
|
||||
#else
|
||||
// HACKHACK: SDL have inverted look axis.
|
||||
*dpitch -= joy_pitch.value * (float)joyaxis[JOY_AXIS_PITCH].val/(float)SHRT_MAX * host.realframetime;
|
||||
*dyaw += joy_yaw.value * (float)joyaxis[JOY_AXIS_YAW ].val/(float)SHRT_MAX * host.realframetime;
|
||||
}
|
||||
|
||||
static void Joy_CalibrateGyro_f( void )
|
||||
{
|
||||
if( !joy_have_gyro.value )
|
||||
{
|
||||
Con_Printf( "Current active gamepad doesn't have gyroscope\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
Platform_CalibrateGamepadGyro();
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -341,8 +383,6 @@ Main init procedure
|
||||
*/
|
||||
void Joy_Init( void )
|
||||
{
|
||||
Cmd_AddRestrictedCommand( "joy_calibrate_gyro", Joy_CalibrateGyro_f, "calibrate gamepad gyroscope. You must to put gamepad on stationary surface" );
|
||||
|
||||
Cvar_RegisterVariable( &joy_pitch );
|
||||
Cvar_RegisterVariable( &joy_yaw );
|
||||
Cvar_RegisterVariable( &joy_side );
|
||||
@@ -362,9 +402,11 @@ void Joy_Init( void )
|
||||
Cvar_RegisterVariable( &joy_yaw_deadzone );
|
||||
|
||||
Cvar_RegisterVariable( &joy_axis_binding );
|
||||
Cvar_RegisterVariable( &joy_found );
|
||||
// we doesn't loaded config.cfg yet, so this cvar is not archive.
|
||||
// change by +set joy_index in cmdline
|
||||
Cvar_RegisterVariable( &joy_index );
|
||||
|
||||
Cvar_RegisterVariable( &joy_have_gyro );
|
||||
Cvar_RegisterVariable( &joy_calibrated );
|
||||
Cvar_RegisterVariable( &joy_enable );
|
||||
|
||||
// renamed from -nojoy to -noenginejoy to not conflict with
|
||||
@@ -375,7 +417,7 @@ void Joy_Init( void )
|
||||
return;
|
||||
}
|
||||
|
||||
Platform_JoyInit();
|
||||
Cvar_FullSet( "joy_found", va( "%d", Platform_JoyInit( joy_index.value )), FCVAR_READ_ONLY );
|
||||
|
||||
joy_initialized = true;
|
||||
}
|
||||
@@ -389,5 +431,8 @@ Shutdown joystick code
|
||||
*/
|
||||
void Joy_Shutdown( void )
|
||||
{
|
||||
Platform_JoyShutdown();
|
||||
if( joy_initialized )
|
||||
{
|
||||
Cvar_FullSet( "joy_found", 0, FCVAR_READ_ONLY );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,17 +13,16 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#if XASH_SDL == 2
|
||||
#include <SDL.h>
|
||||
#elif XASH_SDL == 3
|
||||
#include <SDL3/SDL.h>
|
||||
#endif
|
||||
|
||||
#include "common.h"
|
||||
#include "input.h"
|
||||
#include "client.h"
|
||||
#include "vgui_draw.h"
|
||||
#include "cursor_type.h"
|
||||
|
||||
#if XASH_SDL
|
||||
#include <SDL.h>
|
||||
#endif
|
||||
|
||||
#include "platform/platform.h"
|
||||
|
||||
void* in_mousecursor;
|
||||
@@ -206,58 +205,50 @@ void IN_ToggleClientMouse( int newstate, int oldstate )
|
||||
}
|
||||
}
|
||||
|
||||
void IN_SetRelativeMouseMode( qboolean set )
|
||||
static void IN_SetRelativeMouseMode( qboolean set, qboolean verbose )
|
||||
{
|
||||
static qboolean s_bRawInput;
|
||||
qboolean verbose = m_grab_debug.value ? true : false;
|
||||
|
||||
if( set && !s_bRawInput )
|
||||
{
|
||||
#if XASH_SDL >= 2
|
||||
SDL_GetRelativeMouseState( NULL, NULL );
|
||||
#if XASH_SDL == 2
|
||||
SDL_GetRelativeMouseState( NULL, NULL );
|
||||
SDL_SetRelativeMouseMode( SDL_TRUE );
|
||||
#else // XASH_SDL != 2
|
||||
SDL_SetWindowRelativeMouseMode( host.hWnd, true );
|
||||
#endif // XASH_SDL != 2
|
||||
#endif // XASH_SDL >= 2
|
||||
#endif
|
||||
s_bRawInput = true;
|
||||
if( verbose )
|
||||
Con_Printf( "%s: true\n", __func__ );
|
||||
}
|
||||
else if( !set && s_bRawInput )
|
||||
{
|
||||
#if XASH_SDL >= 2
|
||||
SDL_GetRelativeMouseState( NULL, NULL );
|
||||
#if XASH_SDL == 2
|
||||
SDL_GetRelativeMouseState( NULL, NULL );
|
||||
SDL_SetRelativeMouseMode( SDL_FALSE );
|
||||
#else // XASH_SDL != 2
|
||||
SDL_SetWindowRelativeMouseMode( host.hWnd, false );
|
||||
#endif // XASH_SDL != 2
|
||||
#endif // XASH_SDL >= 2
|
||||
|
||||
#endif
|
||||
s_bRawInput = false;
|
||||
if( verbose )
|
||||
Con_Printf( "%s: false\n", __func__ );
|
||||
}
|
||||
}
|
||||
|
||||
void IN_SetMouseGrab( qboolean set )
|
||||
static void IN_SetMouseGrab( qboolean set, qboolean verbose )
|
||||
{
|
||||
static qboolean s_bMouseGrab;
|
||||
qboolean verbose = m_grab_debug.value ? true : false;
|
||||
|
||||
if( set && !s_bMouseGrab )
|
||||
{
|
||||
Platform_SetMouseGrab( true );
|
||||
|
||||
#if XASH_SDL
|
||||
SDL_SetWindowGrab( host.hWnd, SDL_TRUE );
|
||||
#endif
|
||||
s_bMouseGrab = true;
|
||||
if( verbose )
|
||||
Con_Printf( "%s: true\n", __func__ );
|
||||
}
|
||||
else if( !set && s_bMouseGrab )
|
||||
{
|
||||
Platform_SetMouseGrab( false );
|
||||
#if XASH_SDL
|
||||
SDL_SetWindowGrab( host.hWnd, SDL_FALSE );
|
||||
#endif
|
||||
|
||||
s_bMouseGrab = false;
|
||||
if( verbose )
|
||||
@@ -267,7 +258,7 @@ void IN_SetMouseGrab( qboolean set )
|
||||
|
||||
static void IN_CheckMouseState( qboolean active )
|
||||
{
|
||||
qboolean use_raw_input;
|
||||
qboolean use_raw_input, verbose;
|
||||
|
||||
#if XASH_WIN32
|
||||
use_raw_input = ( m_rawinput.value && clgame.client_dll_uses_sdl ) || clgame.dllFuncs.pfnLookEvent != NULL;
|
||||
@@ -275,18 +266,20 @@ static void IN_CheckMouseState( qboolean active )
|
||||
use_raw_input = true; // always use SDL code
|
||||
#endif
|
||||
|
||||
verbose = m_grab_debug.value ? true : false;
|
||||
|
||||
if( m_ignore.value )
|
||||
active = false;
|
||||
|
||||
if( active && use_raw_input && !host.mouse_visible && cls.state == ca_active )
|
||||
IN_SetRelativeMouseMode( true );
|
||||
IN_SetRelativeMouseMode( true, verbose );
|
||||
else
|
||||
IN_SetRelativeMouseMode( false );
|
||||
IN_SetRelativeMouseMode( false, verbose );
|
||||
|
||||
if( active && !host.mouse_visible && cls.state == ca_active )
|
||||
IN_SetMouseGrab( true );
|
||||
IN_SetMouseGrab( true, verbose );
|
||||
else
|
||||
IN_SetMouseGrab( false );
|
||||
IN_SetMouseGrab( false, verbose );
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -339,7 +332,7 @@ static void IN_MouseMove( void )
|
||||
if( !in_mouseinitialized )
|
||||
return;
|
||||
|
||||
if( Touch_WantVisibleCursor( ))
|
||||
if( Touch_Emulated( ))
|
||||
{
|
||||
// touch emulation overrides all input
|
||||
Touch_KeyEvent( 0, 0 );
|
||||
@@ -370,7 +363,7 @@ void IN_MouseEvent( int key, int down )
|
||||
else ClearBits( in_mstate, BIT( key ));
|
||||
|
||||
// touch emulation overrides all input
|
||||
if( Touch_WantVisibleCursor( ))
|
||||
if( Touch_Emulated( ))
|
||||
{
|
||||
Touch_KeyEvent( K_MOUSE1 + key, down );
|
||||
}
|
||||
|
||||
@@ -46,9 +46,6 @@ uint IN_CollectInputDevices( void );
|
||||
void IN_LockInputDevices( qboolean lock );
|
||||
void IN_EngineAppendMove( float frametime, usercmd_t *cmd, qboolean active );
|
||||
|
||||
void IN_SetRelativeMouseMode( qboolean set );
|
||||
void IN_SetMouseGrab( qboolean set );
|
||||
|
||||
extern convar_t m_yaw;
|
||||
extern convar_t m_pitch;
|
||||
//
|
||||
@@ -77,6 +74,7 @@ void Touch_ResetDefaultButtons( void );
|
||||
int IN_TouchEvent( touchEventType type, int fingerID, float x, float y, float dx, float dy );
|
||||
void Touch_KeyEvent( int key, int down );
|
||||
qboolean Touch_WantVisibleCursor( void );
|
||||
qboolean Touch_Emulated( void );
|
||||
void Touch_NotifyResize( void );
|
||||
|
||||
//
|
||||
@@ -106,21 +104,18 @@ typedef enum engineAxis_e
|
||||
JOY_AXIS_NULL
|
||||
} engineAxis_t;
|
||||
|
||||
typedef enum joy_calibration_state_s
|
||||
{
|
||||
JOY_NOT_CALIBRATED = 0,
|
||||
JOY_CALIBRATING,
|
||||
JOY_FAILED_TO_CALIBRATE,
|
||||
JOY_CALIBRATED
|
||||
} joy_calibration_state_t;
|
||||
|
||||
qboolean Joy_IsActive( void );
|
||||
void Joy_SetCapabilities( qboolean have_gyro );
|
||||
void Joy_SetCalibrationState( joy_calibration_state_t state );
|
||||
void Joy_AxisMotionEvent( engineAxis_t engineAxis, short value );
|
||||
void Joy_GyroEvent( vec3_t data );
|
||||
void Joy_HatMotionEvent( byte hat, byte value );
|
||||
void Joy_AxisMotionEvent( byte axis, short value );
|
||||
void Joy_KnownAxisMotionEvent( engineAxis_t engineAxis, short value );
|
||||
void Joy_BallMotionEvent( byte ball, short xrel, short yrel );
|
||||
void Joy_ButtonEvent( byte button, byte down );
|
||||
void Joy_AddEvent( void );
|
||||
void Joy_RemoveEvent( void );
|
||||
void Joy_FinalizeMove( float *fw, float *side, float *dpitch, float *dyaw );
|
||||
void Joy_Init( void );
|
||||
void Joy_Shutdown( void );
|
||||
void Joy_EnableTextInput(qboolean enable, qboolean force);
|
||||
|
||||
|
||||
#endif//INPUT_H
|
||||
|
||||
@@ -726,8 +726,18 @@ void GAME_EXPORT Key_Event( int key, int down )
|
||||
return; // handled in client.dll
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
case key_message:
|
||||
Key_Message( key );
|
||||
return;
|
||||
case key_console:
|
||||
if( cls.state == ca_active && !cl.background )
|
||||
Key_SetKeyDest( key_game );
|
||||
else UI_SetActiveMenu( true );
|
||||
return;
|
||||
case key_menu:
|
||||
UI_KeyEvent( key, true );
|
||||
return;
|
||||
default: return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1097,7 +1107,7 @@ static qboolean OSK_KeyEvent( int key, int down )
|
||||
|
||||
/*
|
||||
=============
|
||||
OSK_EnableTextInput
|
||||
Joy_EnableTextInput
|
||||
|
||||
Enables built-in IME
|
||||
=============
|
||||
|
||||
@@ -433,8 +433,6 @@ static const ref_api_t gEngfuncs =
|
||||
&clgame.drawFuncs,
|
||||
|
||||
&g_fsapi,
|
||||
|
||||
R_GetWindowHandle,
|
||||
};
|
||||
|
||||
static void R_UnloadProgs( void )
|
||||
@@ -574,7 +572,7 @@ static void R_GetRendererName( char *dest, size_t size, const char *opt )
|
||||
}
|
||||
}
|
||||
|
||||
static qboolean R_LoadRenderer( const char *refopt, qboolean quiet )
|
||||
static qboolean R_LoadRenderer( const char *refopt )
|
||||
{
|
||||
string refdll;
|
||||
|
||||
@@ -585,8 +583,7 @@ static qboolean R_LoadRenderer( const char *refopt, qboolean quiet )
|
||||
if( !R_LoadProgs( refdll ))
|
||||
{
|
||||
R_Shutdown();
|
||||
if( !quiet )
|
||||
Sys_Warn( S_ERROR "Can't initialize %s renderer!\n", refdll );
|
||||
Sys_Warn( S_ERROR "Can't initialize %s renderer!\n", refdll );
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -625,7 +622,7 @@ static void SetFullscreenModeFromCommandLine( void )
|
||||
static void R_CollectRendererNames( void )
|
||||
{
|
||||
// ordering is important!
|
||||
static const char *short_names[] =
|
||||
static const char *shortNames[] =
|
||||
{
|
||||
#if XASH_REF_GL_ENABLED
|
||||
"gl",
|
||||
@@ -648,7 +645,7 @@ static void R_CollectRendererNames( void )
|
||||
};
|
||||
|
||||
// ordering is important here too!
|
||||
static const char *long_names[ARRAYSIZE( short_names )] =
|
||||
static const char *readableNames[ARRAYSIZE( shortNames )] =
|
||||
{
|
||||
#if XASH_REF_GL_ENABLED
|
||||
"OpenGL",
|
||||
@@ -670,9 +667,9 @@ static void R_CollectRendererNames( void )
|
||||
#endif
|
||||
};
|
||||
|
||||
ref.num_renderers = ARRAYSIZE( short_names );
|
||||
ref.short_names = short_names;
|
||||
ref.long_names = long_names;
|
||||
ref.numRenderers = ARRAYSIZE( shortNames );
|
||||
ref.shortNames = shortNames;
|
||||
ref.readableNames = readableNames;
|
||||
}
|
||||
|
||||
qboolean R_Init( void )
|
||||
@@ -733,44 +730,28 @@ qboolean R_Init( void )
|
||||
requested_cvar[0] = 0;
|
||||
|
||||
if( Sys_GetParmFromCmdLine( "-ref", requested_cmdline ))
|
||||
success = R_LoadRenderer( requested_cmdline, false );
|
||||
success = R_LoadRenderer( requested_cmdline );
|
||||
|
||||
if( !success && COM_CheckString( r_refdll.string ) && Q_stricmp( requested_cmdline, r_refdll.string ))
|
||||
{
|
||||
Q_strncpy( requested_cvar, r_refdll.string, sizeof( requested_cvar ));
|
||||
|
||||
// do not show scary messages to user if renderer set in config cannot be loaded
|
||||
// as game data could be copied from one platform to another, where this renderer
|
||||
// might not be supported (ref_gl on Android for example)
|
||||
success = R_LoadRenderer( requested_cvar, !host_developer.value );
|
||||
success = R_LoadRenderer( requested_cvar );
|
||||
}
|
||||
|
||||
if( !success )
|
||||
{
|
||||
int i;
|
||||
|
||||
for( i = 0; i < ref.num_renderers; i++ )
|
||||
for( i = 0; i < ref.numRenderers && !success; i++ )
|
||||
{
|
||||
// skip renderer that was requested but failed to load
|
||||
if( !Q_strcmp( requested_cmdline, ref.short_names[i] ))
|
||||
if( !Q_strcmp( requested_cmdline, ref.shortNames[i] ))
|
||||
continue;
|
||||
|
||||
if( !Q_strcmp( requested_cvar, ref.short_names[i] ))
|
||||
if( !Q_strcmp( requested_cvar, ref.shortNames[i] ))
|
||||
continue;
|
||||
|
||||
// do not show bruteforcing attempts, however, warn user about falling back
|
||||
// to software mode
|
||||
if( !Q_strcmp( "soft", ref.short_names[i] ) && !host_developer.value )
|
||||
Sys_Warn( "Can't initialize any hardware accelerated renderer. Falling back to software rendering...\n" );
|
||||
|
||||
success = R_LoadRenderer( ref.short_names[i], !host_developer.value );
|
||||
|
||||
if( success )
|
||||
{
|
||||
// remember last valid renderer
|
||||
Cvar_DirectSet( &r_refdll, ref.short_names[i] );
|
||||
break;
|
||||
}
|
||||
success = R_LoadRenderer( ref.shortNames[i] );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -24,12 +24,12 @@ struct ref_state_s
|
||||
{
|
||||
HINSTANCE hInstance;
|
||||
qboolean initialized;
|
||||
int num_renderers;
|
||||
int numRenderers;
|
||||
ref_interface_t dllFuncs;
|
||||
|
||||
// depends on build configuration
|
||||
const char **short_names;
|
||||
const char **long_names;
|
||||
const char **shortNames;
|
||||
const char **readableNames;
|
||||
};
|
||||
|
||||
extern struct ref_state_s ref;
|
||||
|
||||
@@ -20,8 +20,6 @@ GNU General Public License for more details.
|
||||
#include "pm_local.h"
|
||||
#include "platform/platform.h"
|
||||
|
||||
#define SND_CLIP_DISTANCE 1000.0f
|
||||
|
||||
dma_t dma;
|
||||
poolhandle_t sndpool;
|
||||
static soundfade_t soundfade;
|
||||
@@ -1111,7 +1109,7 @@ rawchan_t *S_FindRawChannel( int entnum, qboolean create )
|
||||
S_RawSamplesStereo
|
||||
===================
|
||||
*/
|
||||
static uint S_RawSamplesStereo( portable_samplepair_t *rawsamples, uint rawend, uint max_samples, uint samples, uint rate, word width, word channels, const byte *data )
|
||||
uint S_RawSamplesStereo( portable_samplepair_t *rawsamples, uint rawend, uint max_samples, uint samples, uint rate, word width, word channels, const byte *data )
|
||||
{
|
||||
uint fracstep, samplefrac;
|
||||
uint src, dst;
|
||||
@@ -1193,20 +1191,6 @@ void S_RawEntSamples( int entnum, uint samples, uint rate, word width, word chan
|
||||
ch->leftvol = ch->rightvol = snd_vol;
|
||||
}
|
||||
|
||||
/*
|
||||
===================
|
||||
S_RawSamples
|
||||
===================
|
||||
*/
|
||||
void S_RawSamples( uint samples, uint rate, word width, word channels, const byte *data, int entnum )
|
||||
{
|
||||
int snd_vol = 128;
|
||||
|
||||
if( entnum < 0 ) snd_vol = 256; // bg track or movie track
|
||||
|
||||
S_RawEntSamples( entnum, samples, rate, width, channels, data, snd_vol );
|
||||
}
|
||||
|
||||
/*
|
||||
===================
|
||||
S_FreeIdleRawChannels
|
||||
@@ -1610,7 +1594,6 @@ void SND_UpdateSound( void )
|
||||
}
|
||||
|
||||
S_StreamBackgroundTrack ();
|
||||
S_StreamSoundTrack ();
|
||||
|
||||
// mix some sound
|
||||
S_UpdateChannels ();
|
||||
|
||||
@@ -242,7 +242,7 @@ void S_StreamBackgroundTrack( void )
|
||||
if( r > 0 )
|
||||
{
|
||||
// add to raw buffer
|
||||
S_RawSamples( fileSamples, info->rate, info->width, info->channels, raw, S_RAW_SOUND_BACKGROUNDTRACK );
|
||||
S_RawEntSamples( S_RAW_SOUND_BACKGROUNDTRACK, fileSamples, info->rate, info->width, info->channels, raw, 255 );
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -287,66 +287,3 @@ void S_StopStreaming( void )
|
||||
if( !dma.initialized ) return;
|
||||
s_listener.streaming = false;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
S_StreamSoundTrack
|
||||
=================
|
||||
*/
|
||||
void S_StreamSoundTrack( void )
|
||||
{
|
||||
int bufferSamples;
|
||||
int fileSamples;
|
||||
byte raw[MAX_RAW_SAMPLES];
|
||||
int r, fileBytes;
|
||||
rawchan_t *ch = NULL;
|
||||
|
||||
if( !dma.initialized || !s_listener.streaming || s_listener.paused )
|
||||
return;
|
||||
|
||||
ch = S_FindRawChannel( S_RAW_SOUND_SOUNDTRACK, true );
|
||||
|
||||
Assert( ch != NULL );
|
||||
|
||||
// see how many samples should be copied into the raw buffer
|
||||
if( ch->s_rawend < soundtime )
|
||||
ch->s_rawend = soundtime;
|
||||
|
||||
while( ch->s_rawend < soundtime + ch->max_samples )
|
||||
{
|
||||
wavdata_t *info = SCR_GetMovieInfo();
|
||||
|
||||
if( !info ) break; // bad soundtrack?
|
||||
|
||||
bufferSamples = ch->max_samples - (ch->s_rawend - soundtime);
|
||||
|
||||
// decide how much data needs to be read from the file
|
||||
fileSamples = bufferSamples * ((float)info->rate / SOUND_DMA_SPEED );
|
||||
if( fileSamples <= 1 ) return; // no more samples need
|
||||
|
||||
// our max buffer size
|
||||
fileBytes = fileSamples * ( info->width * info->channels );
|
||||
|
||||
if( fileBytes > sizeof( raw ))
|
||||
{
|
||||
fileBytes = sizeof( raw );
|
||||
fileSamples = fileBytes / ( info->width * info->channels );
|
||||
}
|
||||
|
||||
// read audio stream
|
||||
r = SCR_GetAudioChunk( raw, fileBytes );
|
||||
|
||||
if( r < fileBytes )
|
||||
{
|
||||
fileBytes = r;
|
||||
fileSamples = r / ( info->width * info->channels );
|
||||
}
|
||||
|
||||
if( r > 0 )
|
||||
{
|
||||
// add to raw buffer
|
||||
S_RawSamples( fileSamples, info->rate, info->width, info->channels, raw, S_RAW_SOUND_SOUNDTRACK );
|
||||
}
|
||||
else break; // no more samples for this frame
|
||||
}
|
||||
}
|
||||
|
||||
@@ -177,7 +177,8 @@ typedef int sound_t;
|
||||
#define MAX_DYNAMIC_CHANNELS (60 + NUM_AMBIENTS)
|
||||
#define MAX_CHANNELS (256 + MAX_DYNAMIC_CHANNELS) // Scourge Of Armagon has too many static sounds on hip2m4.bsp
|
||||
#define MAX_RAW_CHANNELS 48
|
||||
#define MAX_RAW_SAMPLES 8192
|
||||
#define MAX_RAW_SAMPLES 16384
|
||||
#define SND_CLIP_DISTANCE 1000.0f
|
||||
|
||||
extern sound_t ambient_sfx[NUM_AMBIENTS];
|
||||
extern qboolean snd_ambient;
|
||||
@@ -243,8 +244,8 @@ int S_GetCurrentStaticSounds( soundlist_t *pout, int size );
|
||||
int S_GetCurrentDynamicSounds( soundlist_t *pout, int size );
|
||||
sfx_t *S_GetSfxByHandle( sound_t handle );
|
||||
rawchan_t *S_FindRawChannel( int entnum, qboolean create );
|
||||
uint S_RawSamplesStereo( portable_samplepair_t *rawsamples, uint rawend, uint max_samples, uint samples, uint rate, word width, word channels, const byte *data );
|
||||
void S_RawEntSamples( int entnum, uint samples, uint rate, word width, word channels, const byte *data, int snd_vol );
|
||||
void S_RawSamples( uint samples, uint rate, word width, word channels, const byte *data, int entnum );
|
||||
void S_StopSound( int entnum, int channel, const char *soundname );
|
||||
void S_UpdateFrame( struct ref_viewpass_s *rvp );
|
||||
void S_StopAllSounds( qboolean ambient );
|
||||
@@ -264,7 +265,6 @@ void SND_ForceCloseMouth( int entnum );
|
||||
//
|
||||
// s_stream.c
|
||||
//
|
||||
void S_StreamSoundTrack( void );
|
||||
void S_StreamBackgroundTrack( void );
|
||||
void S_PrintBackgroundTrackState( void );
|
||||
void S_FadeMusicVolume( float fadePercent );
|
||||
|
||||
@@ -56,10 +56,12 @@ loading and unpack to wav any known sound
|
||||
*/
|
||||
wavdata_t *FS_LoadSound( const char *filename, const byte *buffer, size_t size )
|
||||
{
|
||||
const char *ext = COM_FileExtension( filename );
|
||||
string loadname;
|
||||
qboolean anyformat = true;
|
||||
const loadwavfmt_t *format;
|
||||
const char *ext = COM_FileExtension( filename );
|
||||
string path, loadname;
|
||||
qboolean anyformat = true;
|
||||
fs_offset_t filesize = 0;
|
||||
const loadwavfmt_t *format;
|
||||
byte *f;
|
||||
|
||||
Sound_Reset(); // clear old sounddata
|
||||
Q_strncpy( loadname, filename, sizeof( loadname ));
|
||||
@@ -68,7 +70,7 @@ wavdata_t *FS_LoadSound( const char *filename, const byte *buffer, size_t size )
|
||||
{
|
||||
// we needs to compare file extension with list of supported formats
|
||||
// and be sure what is real extension, not a filename with dot
|
||||
for( format = sound.loadformats; format && format->ext; format++ )
|
||||
for( format = sound.loadformats; format && format->formatstring; format++ )
|
||||
{
|
||||
if( !Q_stricmp( format->ext, ext ))
|
||||
{
|
||||
@@ -84,42 +86,28 @@ wavdata_t *FS_LoadSound( const char *filename, const byte *buffer, size_t size )
|
||||
goto load_internal;
|
||||
|
||||
// now try all the formats in the selected list
|
||||
for( format = sound.loadformats; format && format->ext; format++)
|
||||
for( format = sound.loadformats; format && format->formatstring; format++)
|
||||
{
|
||||
if( anyformat || !Q_stricmp( ext, format->ext ))
|
||||
{
|
||||
qboolean success = false;
|
||||
fs_offset_t filesize = 0;
|
||||
byte *f;
|
||||
string path;
|
||||
|
||||
Q_snprintf( path, sizeof( path ), DEFAULT_SOUNDPATH "%s.%s", loadname, format->ext );
|
||||
Q_snprintf( path, sizeof( path ),
|
||||
format->formatstring, loadname, "", format->ext );
|
||||
|
||||
f = FS_LoadFile( path, &filesize, false );
|
||||
if( f && filesize > 0 )
|
||||
{
|
||||
success = format->loadfunc( path, f, filesize );
|
||||
Mem_Free( f ); // release buffer
|
||||
if( format->loadfunc( path, f, filesize ))
|
||||
{
|
||||
Mem_Free(f); // release buffer
|
||||
return SoundPack(); // loaded
|
||||
}
|
||||
else Mem_Free(f); // release buffer
|
||||
}
|
||||
|
||||
if( success )
|
||||
return SoundPack(); // loaded
|
||||
|
||||
Q_snprintf( path, sizeof( path ), "%s.%s", loadname, format->ext );
|
||||
f = FS_LoadFile( path, &filesize, false );
|
||||
if( f && filesize > 0 )
|
||||
{
|
||||
success = format->loadfunc( path, f, filesize );
|
||||
Mem_Free( f ); // release buffer
|
||||
}
|
||||
|
||||
if( success )
|
||||
return SoundPack();
|
||||
}
|
||||
}
|
||||
|
||||
load_internal:
|
||||
for( format = sound.loadformats; format && format->ext; format++ )
|
||||
for( format = sound.loadformats; format && format->formatstring; format++ )
|
||||
{
|
||||
if( anyformat || !Q_stricmp( ext, format->ext ))
|
||||
{
|
||||
@@ -160,7 +148,7 @@ open and reading basic info from sound stream
|
||||
stream_t *FS_OpenStream( const char *filename )
|
||||
{
|
||||
const char *ext = COM_FileExtension( filename );
|
||||
string loadname;
|
||||
string path, loadname;
|
||||
qboolean anyformat = true;
|
||||
const streamfmt_t *format;
|
||||
stream_t *stream = NULL;
|
||||
@@ -172,7 +160,7 @@ stream_t *FS_OpenStream( const char *filename )
|
||||
{
|
||||
// we needs to compare file extension with list of supported formats
|
||||
// and be sure what is real extension, not a filename with dot
|
||||
for( format = sound.streamformat; format && format->ext; format++ )
|
||||
for( format = sound.streamformat; format && format->formatstring; format++ )
|
||||
{
|
||||
if( !Q_stricmp( format->ext, ext ))
|
||||
{
|
||||
@@ -184,13 +172,12 @@ stream_t *FS_OpenStream( const char *filename )
|
||||
}
|
||||
|
||||
// now try all the formats in the selected list
|
||||
for( format = sound.streamformat; format && format->ext; format++)
|
||||
for( format = sound.streamformat; format && format->formatstring; format++)
|
||||
{
|
||||
if( anyformat || !Q_stricmp( ext, format->ext ))
|
||||
{
|
||||
string path;
|
||||
|
||||
Q_snprintf( path, sizeof( path ), "%s.%s", loadname, format->ext );
|
||||
Q_snprintf( path, sizeof( path ),
|
||||
format->formatstring, loadname, "", format->ext );
|
||||
|
||||
if(( stream = format->openfunc( path )) != NULL )
|
||||
{
|
||||
|
||||
@@ -102,14 +102,12 @@ BaseCmd_Find
|
||||
Find every type of base command and write into arguments
|
||||
============
|
||||
*/
|
||||
void BaseCmd_FindAll( const char *name, cmd_t **cmd, cmdalias_t **alias, convar_t **cvar )
|
||||
void BaseCmd_FindAll( const char *name, base_command_t **cmd, base_command_t **alias, base_command_t **cvar )
|
||||
{
|
||||
base_command_hashmap_t *base = BaseCmd_GetBucket( name );
|
||||
base_command_hashmap_t *i = base;
|
||||
|
||||
*cmd = NULL;
|
||||
*alias = NULL;
|
||||
*cvar = NULL;
|
||||
*cmd = *alias = *cvar = NULL;
|
||||
|
||||
for( ; i; i = i->next )
|
||||
{
|
||||
@@ -124,13 +122,13 @@ void BaseCmd_FindAll( const char *name, cmd_t **cmd, cmdalias_t **alias, convar_
|
||||
switch( i->type )
|
||||
{
|
||||
case HM_CMD:
|
||||
*cmd = (cmd_t *)i->basecmd;
|
||||
*cmd = i->basecmd;
|
||||
break;
|
||||
case HM_CMDALIAS:
|
||||
*alias = (cmdalias_t *)i->basecmd;
|
||||
*alias = i->basecmd;
|
||||
break;
|
||||
case HM_CVAR:
|
||||
*cvar = (convar_t *)i->basecmd;
|
||||
*cvar = i->basecmd;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
||||
@@ -21,9 +21,6 @@ GNU General Public License for more details.
|
||||
|
||||
#ifdef XASH_HASHED_VARS
|
||||
|
||||
#include "common.h"
|
||||
#include "cdll_int.h"
|
||||
|
||||
typedef enum base_command_type
|
||||
{
|
||||
HM_DONTCARE = 0,
|
||||
@@ -37,7 +34,8 @@ 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, cmd_t **cmd, cmdalias_t **alias, convar_t **cvar );
|
||||
void BaseCmd_FindAll( const char *name,
|
||||
base_command_t **cmd, base_command_t **alias, base_command_t **cvar );
|
||||
void BaseCmd_Insert ( base_command_type_e type, base_command_t *basecmd, const char *name );
|
||||
void BaseCmd_Remove ( base_command_type_e type, const char *name );
|
||||
void BaseCmd_Stats_f( void ); // to be registered later
|
||||
|
||||
@@ -526,17 +526,51 @@ static void Cmd_UnAlias_f ( void )
|
||||
*/
|
||||
struct cmd_s
|
||||
{
|
||||
cmd_t *next;
|
||||
char *name;
|
||||
xcommand_t function;
|
||||
int flags;
|
||||
char desc[];
|
||||
struct cmd_s *next;
|
||||
char *name;
|
||||
xcommand_t function;
|
||||
int flags;
|
||||
char desc[];
|
||||
};
|
||||
|
||||
int cmd_argc;
|
||||
const char *cmd_args = NULL;
|
||||
char *cmd_argv[MAX_CMD_TOKENS];
|
||||
static cmd_t *cmd_functions; // possible commands to execute
|
||||
static int cmd_argc;
|
||||
static const char *cmd_args = NULL;
|
||||
static char *cmd_argv[MAX_CMD_TOKENS];
|
||||
static cmd_t *cmd_functions; // possible commands to execute
|
||||
|
||||
/*
|
||||
============
|
||||
Cmd_Argc
|
||||
============
|
||||
*/
|
||||
int GAME_EXPORT Cmd_Argc( void )
|
||||
{
|
||||
return cmd_argc;
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
Cmd_Argv
|
||||
============
|
||||
*/
|
||||
const char *GAME_EXPORT Cmd_Argv( int arg )
|
||||
{
|
||||
if((uint)arg >= cmd_argc )
|
||||
return "";
|
||||
return cmd_argv[arg];
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
Cmd_Args
|
||||
============
|
||||
*/
|
||||
const char *GAME_EXPORT Cmd_Args( void )
|
||||
{
|
||||
return cmd_args;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===========================
|
||||
|
||||
@@ -544,6 +578,8 @@ Client exports
|
||||
|
||||
===========================
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
============
|
||||
Cmd_AliasGetList
|
||||
@@ -958,20 +994,24 @@ static void Cmd_ExecuteStringWithPrivilegeCheck( const char *text, qboolean isPr
|
||||
|
||||
if( !Cmd_Argc( )) return; // no tokens
|
||||
|
||||
#if defined( XASH_HASHED_VARS )
|
||||
BaseCmd_FindAll( cmd_argv[0], &cmd, &a, &cvar );
|
||||
#if defined(XASH_HASHED_VARS)
|
||||
BaseCmd_FindAll( cmd_argv[0],
|
||||
(base_command_t**)&cmd,
|
||||
(base_command_t**)&a,
|
||||
(base_command_t**)&cvar );
|
||||
#endif
|
||||
|
||||
if( !host.apply_game_config )
|
||||
{
|
||||
#if !defined( XASH_HASHED_VARS )
|
||||
// check aliases
|
||||
for( a = cmd_alias; a; a = a->next )
|
||||
if( !a ) // if not found in basecmd
|
||||
{
|
||||
if( !Q_stricmp( cmd_argv[0], a->name ))
|
||||
break;
|
||||
for( a = cmd_alias; a; a = a->next )
|
||||
{
|
||||
if( !Q_stricmp( cmd_argv[0], a->name ))
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if( a )
|
||||
{
|
||||
@@ -986,13 +1026,14 @@ static void Cmd_ExecuteStringWithPrivilegeCheck( const char *text, qboolean isPr
|
||||
// special mode for restore game.dll archived cvars
|
||||
if( !host.apply_game_config || !Q_strcmp( cmd_argv[0], "exec" ))
|
||||
{
|
||||
#if !defined( XASH_HASHED_VARS )
|
||||
for( cmd = cmd_functions; cmd; cmd = cmd->next )
|
||||
if( !cmd || !cmd->function ) // if not found in basecmd
|
||||
{
|
||||
if( !Q_stricmp( cmd_argv[0], cmd->name ) && cmd->function )
|
||||
break;
|
||||
for( cmd = cmd_functions; cmd; cmd = cmd->next )
|
||||
{
|
||||
if( !Q_stricmp( cmd_argv[0], cmd->name ) && cmd->function )
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// check functions
|
||||
if( cmd && cmd->function )
|
||||
@@ -1257,50 +1298,6 @@ void Cmd_Null_f( void )
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
Cmd_MakePrivileged_f
|
||||
=============
|
||||
*/
|
||||
static void Cmd_MakePrivileged_f( void )
|
||||
{
|
||||
const char *s = Cmd_Argv( 1 );
|
||||
convar_t *cv;
|
||||
cmd_t *cmd;
|
||||
cmdalias_t *alias;
|
||||
|
||||
if( Cmd_Argc( ) != 2 )
|
||||
{
|
||||
Con_Printf( S_USAGE "make_privileged <cvar or command>\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
#if defined( XASH_HASHED_VARS )
|
||||
BaseCmd_FindAll( s, &cmd, &alias, &cv );
|
||||
#else
|
||||
cmd = Cmd_Exists( s );
|
||||
cv = Cvar_FindVar( s );
|
||||
#endif
|
||||
|
||||
if( !cv && !cmd )
|
||||
{
|
||||
Con_Printf( "Nothing was found.\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
if( cv )
|
||||
{
|
||||
SetBits( cv->flags, FCVAR_PRIVILEGED );
|
||||
Con_Printf( "Cvar %s set to be privileged\n", cv->name );
|
||||
}
|
||||
|
||||
if( cmd )
|
||||
{
|
||||
SetBits( cmd->flags, CMD_PRIVILEGED );
|
||||
Con_Printf( "Command %s set to be privileged\n", cmd->name );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
==========
|
||||
Cmd_Escape
|
||||
@@ -1363,8 +1360,6 @@ void Cmd_Init( void )
|
||||
Cmd_AddRestrictedCommand( "if", Cmd_If_f, "compare and set condition bits" );
|
||||
Cmd_AddRestrictedCommand( "else", Cmd_Else_f, "invert condition bit" );
|
||||
|
||||
Cmd_AddRestrictedCommand( "make_privileged", Cmd_MakePrivileged_f, "makes command or variable privileged (protected from access attempts from server)" );
|
||||
|
||||
#if defined(XASH_HASHED_VARS)
|
||||
Cmd_AddCommand( "basecmd_stats", BaseCmd_Stats_f, "print info about basecmd usage" );
|
||||
Cmd_AddCommand( "basecmd_test", BaseCmd_Test_f, "test basecmd" );
|
||||
|
||||
@@ -251,7 +251,7 @@ static void LZSS_BuildHash( lzss_state_t *state, const byte *source )
|
||||
{
|
||||
lzss_list_t *list;
|
||||
lzss_node_t *node;
|
||||
unsigned int targetindex = (uintptr_t)source & ( state->window_size - 1 );
|
||||
unsigned int targetindex = (uint)source & ( state->window_size - 1 );
|
||||
|
||||
node = &state->hash_node[targetindex];
|
||||
|
||||
@@ -900,7 +900,7 @@ float GAME_EXPORT pfnTime( void )
|
||||
qboolean COM_IsSafeFileToDownload( const char *filename )
|
||||
{
|
||||
char lwrfilename[4096];
|
||||
const char *last;
|
||||
const char *first, *last;
|
||||
const char *ext;
|
||||
size_t len;
|
||||
int i;
|
||||
@@ -934,27 +934,25 @@ qboolean COM_IsSafeFileToDownload( const char *filename )
|
||||
return true;
|
||||
}
|
||||
|
||||
for( i = 0; i < len; i++ )
|
||||
{
|
||||
if( !isprint( filename[i] ))
|
||||
return false;
|
||||
}
|
||||
|
||||
Q_strnlwr( filename, lwrfilename, sizeof( lwrfilename ));
|
||||
ext = COM_FileExtension( lwrfilename );
|
||||
|
||||
if( Q_strpbrk( lwrfilename, "\\:~" ) || Q_strstr( lwrfilename, ".." ))
|
||||
if( Q_strpbrk( lwrfilename, "\\:~" ) || Q_strstr( lwrfilename, ".." ) )
|
||||
return false;
|
||||
|
||||
if( lwrfilename[0] == '/' )
|
||||
return false;
|
||||
|
||||
first = Q_strchr( lwrfilename, '.' );
|
||||
last = Q_strrchr( lwrfilename, '.' );
|
||||
|
||||
if( last == NULL )
|
||||
if( first == NULL || last == NULL )
|
||||
return false;
|
||||
|
||||
if( Q_strlen( last ) != 4 )
|
||||
if( first != last )
|
||||
return false;
|
||||
|
||||
if( Q_strlen( first ) != 4 )
|
||||
return false;
|
||||
|
||||
for( i = 0; i < ARRAYSIZE( file_exts ); i++ )
|
||||
@@ -1133,7 +1131,6 @@ void Test_RunCommon( void )
|
||||
{
|
||||
Msg( "Checking COM_IsSafeFileToDownload...\n" );
|
||||
|
||||
TASSERT_EQi( COM_IsSafeFileToDownload( "models/bsg_props/[hl-lab.ru]bush.mdl" ), true );
|
||||
TASSERT_EQi( COM_IsSafeFileToDownload( "!MD5AAB5E8B307672DA86FBD10AC302BC732" ), true );
|
||||
TASSERT_EQi( COM_IsSafeFileToDownload( "!MD56f1ffd8c96bd64c9c27955309f6ecfe6" ), false );
|
||||
TASSERT_EQi( COM_IsSafeFileToDownload( "!MD5AAB5E8B307672DA86FBD10AC302B.exe" ), false );
|
||||
|
||||
@@ -76,14 +76,23 @@ XASH SPECIFIC - sort of hack that works only in Xash3D not in GoldSrc
|
||||
|
||||
#define HACKS_RELATED_HLMODS // some HL-mods works differently under Xash and can't be fixed without some hacks at least at current time
|
||||
|
||||
enum dev_level_e
|
||||
enum
|
||||
{
|
||||
DEV_NONE = 0,
|
||||
DEV_NORMAL,
|
||||
DEV_EXTENDED
|
||||
};
|
||||
|
||||
typedef enum instance_e
|
||||
enum
|
||||
{
|
||||
D_INFO = 1, // "-dev 1", shows various system messages
|
||||
D_WARN, // "-dev 2", shows not critical system warnings
|
||||
D_ERROR, // "-dev 3", shows critical warnings
|
||||
D_REPORT, // "-dev 4", special case for game reports
|
||||
D_NOTE // "-dev 5", show system notifications for engine developers
|
||||
};
|
||||
|
||||
typedef enum
|
||||
{
|
||||
HOST_NORMAL, // listen server, singleplayer
|
||||
HOST_DEDICATED,
|
||||
@@ -167,11 +176,6 @@ extern convar_t cl_filterstuffcmd;
|
||||
extern convar_t rcon_password;
|
||||
extern convar_t hpk_custom_file;
|
||||
extern convar_t con_gamemaps;
|
||||
extern convar_t fs_mount_lv;
|
||||
extern convar_t fs_mount_hd;
|
||||
extern convar_t fs_mount_addon;
|
||||
extern convar_t fs_mount_l10n;
|
||||
extern convar_t ui_language; // historically used for UI, but now controls mounted localization directory
|
||||
|
||||
#define Mod_AllowMaterials() ( host_allow_materials.value != 0.0f && !FBitSet( host.features, ENGINE_DISABLE_HDTEXTURES ))
|
||||
|
||||
@@ -190,7 +194,7 @@ GAMEINFO stuff
|
||||
internal shared gameinfo structure (readonly for engine parts)
|
||||
========================================================================
|
||||
*/
|
||||
typedef enum host_status_e
|
||||
typedef enum
|
||||
{
|
||||
HOST_INIT = 0, // initalize operations
|
||||
HOST_FRAME, // host running
|
||||
@@ -201,7 +205,7 @@ typedef enum host_status_e
|
||||
HOST_CRASHED // an exception handler called
|
||||
} host_status_t;
|
||||
|
||||
typedef enum host_state_e
|
||||
typedef enum
|
||||
{
|
||||
STATE_RUNFRAME = 0,
|
||||
STATE_LOAD_LEVEL,
|
||||
@@ -210,7 +214,7 @@ typedef enum host_state_e
|
||||
STATE_GAME_SHUTDOWN,
|
||||
} host_state_t;
|
||||
|
||||
typedef struct game_status_e
|
||||
typedef struct
|
||||
{
|
||||
host_state_t curstate;
|
||||
host_state_t nextstate;
|
||||
@@ -221,7 +225,7 @@ typedef struct game_status_e
|
||||
qboolean newGame; // unload the server.dll before start a new map
|
||||
} game_status_t;
|
||||
|
||||
typedef enum keydest_e
|
||||
typedef enum
|
||||
{
|
||||
key_console = 0,
|
||||
key_game,
|
||||
@@ -229,7 +233,7 @@ typedef enum keydest_e
|
||||
key_message
|
||||
} keydest_t;
|
||||
|
||||
typedef enum rdtype_e
|
||||
typedef enum
|
||||
{
|
||||
RD_NONE = 0,
|
||||
RD_CLIENT,
|
||||
@@ -239,7 +243,7 @@ typedef enum rdtype_e
|
||||
#include "net_ws.h"
|
||||
|
||||
// console field
|
||||
typedef struct field_e
|
||||
typedef struct
|
||||
{
|
||||
string buffer;
|
||||
int cursor;
|
||||
@@ -257,7 +261,7 @@ typedef struct host_redirect_s
|
||||
int lines;
|
||||
} host_redirect_t;
|
||||
|
||||
typedef struct soundlist_e
|
||||
typedef struct
|
||||
{
|
||||
char name[MAX_QPATH];
|
||||
short entnum;
|
||||
@@ -298,7 +302,7 @@ typedef struct host_parm_s
|
||||
|
||||
host_status_t status; // global host state
|
||||
game_status_t game; // game manager
|
||||
instance_t type; // running at
|
||||
uint type; // running at
|
||||
poolhandle_t mempool; // static mempool for misc allocations
|
||||
poolhandle_t imagepool; // imagelib mempool
|
||||
poolhandle_t soundpool; // soundlib mempool
|
||||
@@ -342,6 +346,7 @@ typedef struct host_parm_s
|
||||
qboolean apply_game_config; // when true apply only to game cvars and ignore all other commands
|
||||
qboolean apply_opengl_config; // when true apply only to opengl cvars and ignore all other commands
|
||||
qboolean config_executed; // a bit who indicated was config.cfg already executed e.g. from valve.rc
|
||||
qboolean crashed; // set to true if crashed
|
||||
#if XASH_DLL_LOADER
|
||||
qboolean enabledll;
|
||||
#endif
|
||||
@@ -357,7 +362,6 @@ typedef struct host_parm_s
|
||||
int window_center_y;
|
||||
string gamedll;
|
||||
string clientlib;
|
||||
string menulib;
|
||||
} host_parm_t;
|
||||
|
||||
extern host_parm_t host;
|
||||
@@ -415,37 +419,11 @@ 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
|
||||
//
|
||||
typedef struct cmd_s cmd_t;
|
||||
|
||||
static inline int GAME_EXPORT Cmd_Argc( void )
|
||||
{
|
||||
extern int cmd_argc;
|
||||
return cmd_argc;
|
||||
}
|
||||
|
||||
static inline const char *GAME_EXPORT RETURNS_NONNULL Cmd_Argv( int arg )
|
||||
{
|
||||
extern int cmd_argc;
|
||||
extern char *cmd_argv[MAX_CMD_TOKENS];
|
||||
|
||||
if((uint)arg >= cmd_argc )
|
||||
return "";
|
||||
return cmd_argv[arg];
|
||||
}
|
||||
|
||||
static inline const char *GAME_EXPORT RETURNS_NONNULL Cmd_Args( void )
|
||||
{
|
||||
extern const char *cmd_args;
|
||||
|
||||
return cmd_args;
|
||||
}
|
||||
|
||||
void Cbuf_Clear( void );
|
||||
void Cbuf_AddText( const char *text );
|
||||
void Cbuf_AddTextf( const char *text, ... ) FORMAT_CHECK( 1 );
|
||||
@@ -455,6 +433,9 @@ void Cbuf_InsertTextLen( const char *text, size_t len, size_t requested_len );
|
||||
void Cbuf_ExecStuffCmds( void );
|
||||
void Cbuf_Execute (void);
|
||||
qboolean Cmd_CurrentCommandIsPrivileged( void );
|
||||
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 );
|
||||
@@ -515,7 +496,7 @@ internal sound format
|
||||
typically expanded to wav buffer
|
||||
========================================================================
|
||||
*/
|
||||
typedef enum sndformat_e
|
||||
typedef enum
|
||||
{
|
||||
WF_UNKNOWN = 0,
|
||||
WF_PCMDATA,
|
||||
@@ -526,7 +507,7 @@ typedef enum sndformat_e
|
||||
} sndformat_t;
|
||||
|
||||
// wavdata output flags
|
||||
typedef enum sndFlags_e
|
||||
typedef enum
|
||||
{
|
||||
// wavdata->flags
|
||||
SOUND_LOOPED = BIT( 0 ), // this is looped sound (contain cue markers)
|
||||
@@ -536,7 +517,7 @@ typedef enum sndFlags_e
|
||||
SOUND_RESAMPLE = BIT( 12 ), // resample sound to specified rate
|
||||
} sndFlags_t;
|
||||
|
||||
typedef struct wavdata_s
|
||||
typedef struct
|
||||
{
|
||||
size_t size; // for bounds checking
|
||||
uint loopStart; // offset at this point sound will be looping while playing more than only once
|
||||
@@ -752,7 +733,7 @@ qboolean UI_CreditsActive( void );
|
||||
int CL_GetMaxClients( void );
|
||||
#else
|
||||
static inline qboolean CL_Initialized( void ) { return false; }
|
||||
static inline qboolean CL_IsInGame( void ) { return true; } // always true for dedicated
|
||||
static inline qboolean CL_IsInGame( void ) { return false; }
|
||||
static inline qboolean CL_IsInConsole( void ) { return false; }
|
||||
static inline qboolean CL_IsIntermission( void ) { return false; }
|
||||
static inline qboolean CL_DisableVisibility( void ) { return false; }
|
||||
@@ -803,15 +784,13 @@ void SCR_Init( void );
|
||||
void SCR_UpdateScreen( void );
|
||||
void SCR_BeginLoadingPlaque( qboolean is_background );
|
||||
void SCR_CheckStartupVids( void );
|
||||
int SCR_GetAudioChunk( char *rawdata, int length );
|
||||
wavdata_t *SCR_GetMovieInfo( void );
|
||||
void SCR_Shutdown( void );
|
||||
void Con_Print( const char *txt );
|
||||
void Con_NPrintf( int idx, const char *fmt, ... ) FORMAT_CHECK( 2 );
|
||||
void Con_NXPrintf( con_nprint_t *info, const char *fmt, ... ) FORMAT_CHECK( 2 );
|
||||
void UI_NPrintf( int idx, const char *fmt, ... ) FORMAT_CHECK( 2 );
|
||||
void UI_NXPrintf( con_nprint_t *info, const char *fmt, ... ) FORMAT_CHECK( 2 );
|
||||
const char *Info_ValueForKey( const char *s, const char *key ) RETURNS_NONNULL NONNULL;
|
||||
const char *Info_ValueForKey( const char *s, const char *key );
|
||||
void Info_RemovePrefixedKeys( char *start, char prefix );
|
||||
qboolean Info_RemoveKey( char *s, const char *key );
|
||||
qboolean Info_SetValueForKey( char *s, const char *key, const char *value, int maxsize );
|
||||
|
||||
@@ -498,6 +498,7 @@ static qboolean Cmd_GetSoundList( const char *s, char *completedname, int length
|
||||
return true;
|
||||
}
|
||||
|
||||
#if !XASH_DEDICATED
|
||||
/*
|
||||
=====================================
|
||||
Cmd_GetItemsList
|
||||
@@ -507,7 +508,6 @@ Prints or complete item classname (weapons only)
|
||||
*/
|
||||
static qboolean Cmd_GetItemsList( const char *s, char *completedname, int length )
|
||||
{
|
||||
#if !XASH_DEDICATED
|
||||
search_t *t;
|
||||
string matchbuf;
|
||||
int i, numitems;
|
||||
@@ -521,7 +521,7 @@ static qboolean Cmd_GetItemsList( const char *s, char *completedname, int length
|
||||
Q_strncpy( completedname, matchbuf, length );
|
||||
if( t->numfilenames == 1 ) return true;
|
||||
|
||||
for( i = 0, numitems = 0; i < t->numfilenames; i++ )
|
||||
for(i = 0, numitems = 0; i < t->numfilenames; i++)
|
||||
{
|
||||
if( Q_stricmp( COM_FileExtension( t->filenames[i] ), "txt" ))
|
||||
continue;
|
||||
@@ -544,8 +544,6 @@ static qboolean Cmd_GetItemsList( const char *s, char *completedname, int length
|
||||
}
|
||||
}
|
||||
return true;
|
||||
#endif // !XASH_DEDICATED
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -557,7 +555,6 @@ Autocomplete for bind command
|
||||
*/
|
||||
static qboolean Cmd_GetKeysList( const char *s, char *completedname, int length )
|
||||
{
|
||||
#if !XASH_DEDICATED
|
||||
size_t i, numkeys;
|
||||
string keys[256];
|
||||
string matchbuf;
|
||||
@@ -598,9 +595,8 @@ static qboolean Cmd_GetKeysList( const char *s, char *completedname, int length
|
||||
}
|
||||
|
||||
return true;
|
||||
#endif // !XASH_DEDICATED
|
||||
return false;
|
||||
}
|
||||
#endif // XASH_DEDICATED
|
||||
|
||||
/*
|
||||
===============
|
||||
@@ -608,20 +604,13 @@ Con_AddCommandToList
|
||||
|
||||
===============
|
||||
*/
|
||||
static void Con_AddCommandToList( const char *s, const char *value, const void *ptoggle, void *_autocompleteList )
|
||||
static void Con_AddCommandToList( const char *s, const char *unused1, const char *unused2, void *_autocompleteList )
|
||||
{
|
||||
con_autocomplete_t *list = (con_autocomplete_t*)_autocompleteList;
|
||||
qboolean toggle = ptoggle != NULL && *(qboolean *)ptoggle;
|
||||
|
||||
if( *s == '@' ) return; // never show system cvars or cmds
|
||||
if( list->matchCount >= CON_MAXCMDS ) return; // list is full
|
||||
|
||||
if( toggle )
|
||||
{
|
||||
if( Q_strcmp( value, "0" ) && Q_strcmp( value, "1" ))
|
||||
return; // exclude non-toggable cvars
|
||||
}
|
||||
|
||||
if( Q_strnicmp( s, list->completionString, Q_strlen( list->completionString ) ) )
|
||||
return; // no match
|
||||
|
||||
@@ -645,11 +634,13 @@ Cmd_GetCommandsList
|
||||
Autocomplete for bind command
|
||||
=====================================
|
||||
*/
|
||||
static qboolean Cmd_GetCommandsAndCvarsList( const char *s, char *completedname, int length, qboolean cmds, qboolean cvars, qboolean toggle )
|
||||
static qboolean Cmd_GetCommandsList( const char *s, char *completedname, int length )
|
||||
{
|
||||
size_t i;
|
||||
string matchbuf;
|
||||
con_autocomplete_t list = { 0 }; // local autocomplete list
|
||||
con_autocomplete_t list; // local autocomplete list
|
||||
|
||||
memset( &list, 0, sizeof( list ));
|
||||
|
||||
list.completionString = s;
|
||||
|
||||
@@ -661,16 +652,8 @@ static qboolean Cmd_GetCommandsAndCvarsList( const char *s, char *completedname,
|
||||
return false;
|
||||
|
||||
// find matching commands and variables
|
||||
if( cvars )
|
||||
{
|
||||
Cvar_LookupVars( 0, &toggle, &list, (setpair_t)Con_AddCommandToList );
|
||||
}
|
||||
|
||||
if( cmds )
|
||||
{
|
||||
toggle = false;
|
||||
Cmd_LookupCmds( &toggle, &list, (setpair_t)Con_AddCommandToList );
|
||||
}
|
||||
Cmd_LookupCmds( NULL, &list, (setpair_t)Con_AddCommandToList );
|
||||
Cvar_LookupVars( 0, NULL, &list, (setpair_t)Con_AddCommandToList );
|
||||
|
||||
if( !list.matchCount ) return false;
|
||||
Q_strncpy( matchbuf, list.cmds[0], sizeof( matchbuf ));
|
||||
@@ -686,7 +669,7 @@ static qboolean Cmd_GetCommandsAndCvarsList( const char *s, char *completedname,
|
||||
Con_Printf( "%16s\n", matchbuf );
|
||||
}
|
||||
|
||||
Con_Printf( "\n^3 %i %s found.\n", list.matchCount, cmds ? "commands" : "variables" );
|
||||
Con_Printf( "\n^3 %i commands found.\n", list.matchCount );
|
||||
|
||||
if( completedname && length )
|
||||
{
|
||||
@@ -708,30 +691,6 @@ static qboolean Cmd_GetCommandsAndCvarsList( const char *s, char *completedname,
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
=====================================
|
||||
Cmd_GetCommandsList
|
||||
|
||||
Autocomplete for bind command
|
||||
=====================================
|
||||
*/
|
||||
static qboolean Cmd_GetCommandsList( const char *s, char *completedname, int length )
|
||||
{
|
||||
return Cmd_GetCommandsAndCvarsList( s, completedname, length, true, true, false );
|
||||
}
|
||||
|
||||
/*
|
||||
=====================================
|
||||
Cmd_GetCvarList
|
||||
|
||||
Autocomplete for bind command
|
||||
=====================================
|
||||
*/
|
||||
static qboolean Cmd_GetCvarsList( const char *s, char *completedname, int length )
|
||||
{
|
||||
qboolean toggle = !Q_stricmp( Cmd_Argv( 0 ), "toggle" );
|
||||
return Cmd_GetCommandsAndCvarsList( s, completedname, length, false, true, toggle );
|
||||
}
|
||||
|
||||
/*
|
||||
=====================================
|
||||
@@ -1051,38 +1010,36 @@ int GAME_EXPORT Cmd_CheckMapsList( int fRefresh )
|
||||
return Cmd_CheckMapsList_R( fRefresh, true );
|
||||
}
|
||||
|
||||
// keep this sorted
|
||||
static const autocomplete_list_t cmd_list[] =
|
||||
{
|
||||
{ "bind", 1, Cmd_GetKeysList },
|
||||
{ "bind", 2, Cmd_GetCommandsList },
|
||||
{ "cd", 1, Cmd_GetCDList },
|
||||
{ "map_background", 1, Cmd_GetMapList },
|
||||
{ "changelevel2", 1, Cmd_GetMapList },
|
||||
{ "changelevel", 1, Cmd_GetMapList },
|
||||
{ "drop", 1, Cmd_GetItemsList },
|
||||
{ "entpatch", 1, Cmd_GetMapList },
|
||||
{ "exec", 1, Cmd_GetConfigList },
|
||||
{ "game", 1, Cmd_GetGamesList },
|
||||
{ "give", 1, Cmd_GetItemsList },
|
||||
{ "hpkextract", 1, Cmd_GetCustomList },
|
||||
{ "hpklist", 1, Cmd_GetCustomList },
|
||||
{ "hpkval", 1, Cmd_GetCustomList },
|
||||
{ "listdemo", 1, Cmd_GetDemoList, },
|
||||
{ "load", 1, Cmd_GetSavesList },
|
||||
{ "map", 1, Cmd_GetMapList },
|
||||
{ "map_background", 1, Cmd_GetMapList },
|
||||
{ "movie", 1, Cmd_GetMovieList },
|
||||
{ "mp3", 1, Cmd_GetCDList },
|
||||
{ "music", 1, Cmd_GetMusicList, },
|
||||
{ "play", 1, Cmd_GetSoundList },
|
||||
{ "playdemo", 1, Cmd_GetDemoList, },
|
||||
{ "timedemo", 1, Cmd_GetDemoList, },
|
||||
{ "listdemo", 1, Cmd_GetDemoList, },
|
||||
{ "playvol", 1, Cmd_GetSoundList },
|
||||
{ "reset", 1, Cmd_GetCvarsList },
|
||||
{ "save", 1, Cmd_GetSavesList },
|
||||
{ "set", 1, Cmd_GetCvarsList },
|
||||
{ "timedemo", 1, Cmd_GetDemoList },
|
||||
{ "toggle", 1, Cmd_GetCvarsList },
|
||||
{ "hpkval", 1, Cmd_GetCustomList },
|
||||
{ "hpklist", 1, Cmd_GetCustomList },
|
||||
{ "hpkextract", 1, Cmd_GetCustomList },
|
||||
{ "entpatch", 1, Cmd_GetMapList },
|
||||
{ "music", 1, Cmd_GetMusicList, },
|
||||
{ "movie", 1, Cmd_GetMovieList },
|
||||
{ "exec", 1, Cmd_GetConfigList },
|
||||
#if !XASH_DEDICATED
|
||||
{ "give", 1, Cmd_GetItemsList },
|
||||
{ "drop", 1, Cmd_GetItemsList },
|
||||
{ "bind", 1, Cmd_GetKeysList },
|
||||
{ "unbind", 1, Cmd_GetKeysList },
|
||||
{ "bind", 2, Cmd_GetCommandsList },
|
||||
#endif
|
||||
{ "game", 1, Cmd_GetGamesList },
|
||||
{ "save", 1, Cmd_GetSavesList },
|
||||
{ "load", 1, Cmd_GetSavesList },
|
||||
{ "play", 1, Cmd_GetSoundList },
|
||||
{ "map", 1, Cmd_GetMapList },
|
||||
{ "cd", 1, Cmd_GetCDList },
|
||||
{ "mp3", 1, Cmd_GetCDList },
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -1203,7 +1160,6 @@ void Con_CompleteCommand( field_t *field )
|
||||
{
|
||||
field_t temp;
|
||||
string filename;
|
||||
qboolean toggle = false;
|
||||
qboolean nextcmd;
|
||||
int i;
|
||||
|
||||
@@ -1238,8 +1194,8 @@ void Con_CompleteCommand( field_t *field )
|
||||
con.shortestMatch[0] = 0;
|
||||
|
||||
// find matching commands and variables
|
||||
Cmd_LookupCmds( &toggle, &con, (setpair_t)Con_AddCommandToList );
|
||||
Cvar_LookupVars( 0, &toggle, &con, (setpair_t)Con_AddCommandToList );
|
||||
Cmd_LookupCmds( NULL, &con, (setpair_t)Con_AddCommandToList );
|
||||
Cvar_LookupVars( 0, NULL, &con, (setpair_t)Con_AddCommandToList );
|
||||
|
||||
if( !con.matchCount ) return; // no matches
|
||||
|
||||
|
||||
@@ -153,7 +153,7 @@ static qboolean Cvar_UpdateInfo( convar_t *var, const char *value, qboolean noti
|
||||
{
|
||||
if( FBitSet( var->flags, FCVAR_USERINFO ))
|
||||
{
|
||||
if( Host_IsDedicated() )
|
||||
if ( Host_IsDedicated() )
|
||||
{
|
||||
// g-cont. this is a very strange behavior...
|
||||
char *info = SV_Serverinfo();
|
||||
@@ -432,9 +432,8 @@ convar_t *Cvar_Get( const char *name, const char *value, int flags, const char *
|
||||
if( COM_CheckStringEmpty( var->desc ))
|
||||
{
|
||||
// directly set value
|
||||
size_t len = Q_strlen( value ) + 1;
|
||||
var->string = Mem_Realloc( cvar_pool, var->string, len );
|
||||
Q_strncpy( var->string, value, len );
|
||||
freestring( var->string );
|
||||
var->string = copystringpool( cvar_pool, value );
|
||||
var->value = Q_atof( var->string );
|
||||
SetBits( var->flags, flags );
|
||||
|
||||
@@ -450,14 +449,11 @@ convar_t *Cvar_Get( const char *name, const char *value, int flags, const char *
|
||||
|
||||
if( FBitSet( var->flags, FCVAR_ALLOCATED ) && Q_strcmp( var_desc, var->desc ))
|
||||
{
|
||||
size_t len = Q_strlen( var_desc ) + 1;
|
||||
|
||||
if( !FBitSet( flags, FCVAR_GLCONFIG ))
|
||||
Con_Reportf( "%s change description from %s to %s\n", var->name, var->desc, var_desc );
|
||||
|
||||
// update description if needs
|
||||
var->desc = Mem_Realloc( cvar_pool, var->desc, len );
|
||||
Q_strncpy( var->desc, var_desc, len );
|
||||
freestring( var->desc );
|
||||
var->desc = copystringpool( cvar_pool, var_desc );
|
||||
}
|
||||
|
||||
return var;
|
||||
@@ -606,10 +602,9 @@ Cvar_Set2
|
||||
static convar_t *Cvar_Set2( const char *var_name, const char *value )
|
||||
{
|
||||
convar_t *var;
|
||||
const char *pszValue;
|
||||
qboolean dll_variable = false;
|
||||
qboolean force = false;
|
||||
const char *fixed_string;
|
||||
size_t fixed_string_len;
|
||||
|
||||
if( !Cvar_ValidateVarName( var_name, false ))
|
||||
{
|
||||
@@ -673,20 +668,19 @@ static convar_t *Cvar_Set2( const char *var_name, const char *value )
|
||||
return var;
|
||||
}
|
||||
|
||||
fixed_string = Cvar_ValidateString( var, value );
|
||||
pszValue = Cvar_ValidateString( var, value );
|
||||
|
||||
// nothing to change
|
||||
if( !Q_strcmp( fixed_string, var->string ))
|
||||
if( !Q_strcmp( pszValue, var->string ))
|
||||
return var;
|
||||
|
||||
// fill it cls.userinfo, svs.serverinfo
|
||||
if( !Cvar_UpdateInfo( var, fixed_string, true ))
|
||||
if( !Cvar_UpdateInfo( var, pszValue, true ))
|
||||
return var;
|
||||
|
||||
// and finally change the cvar itself
|
||||
fixed_string_len = Q_strlen( fixed_string ) + 1;
|
||||
var->string = Mem_Realloc( cvar_pool, var->string, fixed_string_len );
|
||||
Q_strncpy( var->string, fixed_string, fixed_string_len );
|
||||
// and finally changed the cvar itself
|
||||
freestring( var->string );
|
||||
var->string = copystringpool( cvar_pool, pszValue );
|
||||
var->value = Q_atof( var->string );
|
||||
|
||||
// tell engine about changes
|
||||
@@ -703,8 +697,7 @@ way to change value for many cvars
|
||||
*/
|
||||
void GAME_EXPORT Cvar_DirectSet( convar_t *var, const char *value )
|
||||
{
|
||||
const char *fixed_string;
|
||||
size_t fixed_string_len;
|
||||
const char *pszValue;
|
||||
|
||||
if( unlikely( !var )) return; // ???
|
||||
|
||||
@@ -734,20 +727,19 @@ void GAME_EXPORT Cvar_DirectSet( convar_t *var, const char *value )
|
||||
value = var->def_string; // reset to default value
|
||||
}
|
||||
|
||||
fixed_string = Cvar_ValidateString( var, value );
|
||||
pszValue = Cvar_ValidateString( var, value );
|
||||
|
||||
// nothing to change
|
||||
if( !Q_strcmp( fixed_string, var->string ))
|
||||
if( !Q_strcmp( pszValue, var->string ))
|
||||
return;
|
||||
|
||||
// fill it cls.userinfo, svs.serverinfo
|
||||
if( !Cvar_UpdateInfo( var, fixed_string, true ))
|
||||
if( !Cvar_UpdateInfo( var, pszValue, true ))
|
||||
return;
|
||||
|
||||
// and finally change the cvar itself
|
||||
fixed_string_len = Q_strlen( fixed_string ) + 1;
|
||||
var->string = Mem_Realloc( cvar_pool, var->string, fixed_string_len );
|
||||
Q_strncpy( var->string, fixed_string, fixed_string_len );
|
||||
// and finally changed the cvar itself
|
||||
freestring( var->string );
|
||||
var->string = copystringpool( cvar_pool, pszValue );
|
||||
var->value = Q_atof( var->string );
|
||||
|
||||
// tell engine about changes
|
||||
@@ -781,8 +773,7 @@ can set any protected cvars
|
||||
*/
|
||||
void Cvar_FullSet( const char *var_name, const char *value, int flags )
|
||||
{
|
||||
convar_t *var = Cvar_FindVar( var_name );
|
||||
size_t len = Q_strlen( value ) + 1;
|
||||
convar_t *var = Cvar_FindVar( var_name );
|
||||
|
||||
if( !var )
|
||||
{
|
||||
@@ -790,8 +781,8 @@ void Cvar_FullSet( const char *var_name, const char *value, int flags )
|
||||
return;
|
||||
}
|
||||
|
||||
var->string = Mem_Realloc( cvar_pool, var->string, len );
|
||||
Q_strncpy( var->string, value, len );
|
||||
freestring( var->string );
|
||||
var->string = copystringpool( cvar_pool, value );
|
||||
var->value = Q_atof( var->string );
|
||||
SetBits( var->flags, flags );
|
||||
|
||||
@@ -1030,11 +1021,9 @@ qboolean Cvar_CommandWithPrivilegeCheck( convar_t *v, qboolean isPrivileged )
|
||||
return true;
|
||||
}
|
||||
|
||||
#if !defined( XASH_HASHED_VARS )
|
||||
// check variables
|
||||
v = Cvar_FindVar( Cmd_Argv( 0 ));
|
||||
#endif
|
||||
|
||||
if( !v ) // already found in basecmd
|
||||
v = Cvar_FindVar( Cmd_Argv( 0 ));
|
||||
if( !v )
|
||||
return false;
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
filesystem.c - game filesystem based on DP fs
|
||||
Copyright (C) 2003-2006 Mathieu Olivier
|
||||
Copyright (C) 2000-2007 DarkPlaces contributors
|
||||
@@ -16,23 +16,11 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#if XASH_SDL == 2
|
||||
#include <SDL.h> // SDL_GetBasePath
|
||||
#elif XASH_SDL == 3
|
||||
#include <SDL3/SDL.h>
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
#include "common.h"
|
||||
#include "library.h"
|
||||
#include "platform/platform.h"
|
||||
|
||||
CVAR_DEFINE_AUTO( fs_mount_hd, "0", FCVAR_ARCHIVE|FCVAR_PRIVILEGED|FCVAR_LATCH, "mount high definition content folder" );
|
||||
CVAR_DEFINE_AUTO( fs_mount_lv, "0", FCVAR_ARCHIVE|FCVAR_PRIVILEGED|FCVAR_LATCH, "mount low violence models content folder" );
|
||||
CVAR_DEFINE_AUTO( fs_mount_addon, "0", FCVAR_ARCHIVE|FCVAR_PRIVILEGED|FCVAR_LATCH, "mount addon content folder" );
|
||||
CVAR_DEFINE_AUTO( fs_mount_l10n, "0", FCVAR_ARCHIVE|FCVAR_PRIVILEGED|FCVAR_LATCH, "mount localization content folder" );
|
||||
CVAR_DEFINE_AUTO( ui_language, "english", FCVAR_ARCHIVE|FCVAR_PRIVILEGED|FCVAR_LATCH, "selected game language" );
|
||||
|
||||
fs_api_t g_fsapi;
|
||||
fs_globals_t *FI;
|
||||
|
||||
@@ -81,23 +69,9 @@ void *FS_GetNativeObject( const char *obj )
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void FS_Rescan_f( void )
|
||||
static void FS_Rescan_f( void )
|
||||
{
|
||||
uint32_t flags = 0;
|
||||
|
||||
// FIXME: VFS shouldn't care about this, allow engine to mount gamedirs
|
||||
if( fs_mount_lv.value ) SetBits( flags, FS_MOUNT_LV );
|
||||
if( fs_mount_hd.value ) SetBits( flags, FS_MOUNT_HD );
|
||||
if( fs_mount_addon.value ) SetBits( flags, FS_MOUNT_ADDON );
|
||||
if( fs_mount_l10n.value ) SetBits( flags, FS_MOUNT_L10N );
|
||||
|
||||
g_fsapi.Rescan( flags, ui_language.string );
|
||||
|
||||
ClearBits( fs_mount_lv.flags, FCVAR_CHANGED );
|
||||
ClearBits( fs_mount_hd.flags, FCVAR_CHANGED );
|
||||
ClearBits( fs_mount_addon.flags, FCVAR_CHANGED );
|
||||
ClearBits( fs_mount_l10n.flags, FCVAR_CHANGED );
|
||||
ClearBits( ui_language.flags, FCVAR_CHANGED );
|
||||
FS_Rescan();
|
||||
}
|
||||
|
||||
static void FS_ClearPaths_f( void )
|
||||
@@ -211,7 +185,7 @@ static qboolean FS_DetermineRootDirectory( char *out, size_t size )
|
||||
return true;
|
||||
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
|
||||
#elif ( XASH_SDL == 2 ) && !XASH_NSWITCH // GetBasePath not impl'd in switch-sdl2
|
||||
path = SDL_GetBasePath();
|
||||
|
||||
#if XASH_APPLE
|
||||
@@ -262,12 +236,6 @@ static qboolean FS_DetermineReadOnlyRootDirectory( char *out, size_t size )
|
||||
return false;
|
||||
}
|
||||
|
||||
void FS_CheckConfig( void )
|
||||
{
|
||||
if( fs_mount_lv.value || fs_mount_hd.value || fs_mount_addon.value || fs_mount_l10n.value )
|
||||
FS_Rescan_f();
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
FS_Init
|
||||
@@ -320,19 +288,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;
|
||||
|
||||
if( !Sys_GetParmFromCmdLine( "-clientlib", host.clientlib ))
|
||||
host.clientlib[0] = 0;
|
||||
|
||||
if( !Sys_GetParmFromCmdLine( "-menulib", host.menulib ))
|
||||
host.menulib[0] = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -14,6 +14,9 @@ GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include "build.h"
|
||||
#ifdef XASH_SDL
|
||||
#include <SDL.h>
|
||||
#endif // XASH_SDL
|
||||
#include <stdarg.h> // va_args
|
||||
#if !XASH_WIN32
|
||||
#include <unistd.h> // fork
|
||||
@@ -74,7 +77,7 @@ static CVAR_DEFINE_AUTO( host_gameloaded, "0", FCVAR_READ_ONLY, "inidcates a loa
|
||||
static CVAR_DEFINE_AUTO( host_clientloaded, "0", FCVAR_READ_ONLY, "inidcates a loaded client.dll" );
|
||||
CVAR_DEFINE_AUTO( host_limitlocal, "0", 0, "apply cl_cmdrate and rate to loopback connection" );
|
||||
CVAR_DEFINE( host_maxfps, "fps_max", "72", FCVAR_ARCHIVE|FCVAR_FILTERABLE, "host fps upper limit" );
|
||||
CVAR_DEFINE_AUTO( fps_override, "0", FCVAR_FILTERABLE, "unlock higher framerate values, not supported" );
|
||||
CVAR_DEFINE_AUTO( fps_override, "1", FCVAR_FILTERABLE, "unlock higher framerate values, not supported" );
|
||||
static CVAR_DEFINE_AUTO( host_framerate, "0", FCVAR_FILTERABLE, "locks frame timing to this value in seconds" );
|
||||
static CVAR_DEFINE( host_sleeptime, "sleeptime", "1", FCVAR_ARCHIVE|FCVAR_FILTERABLE, "milliseconds to sleep for each frame. higher values reduce fps accuracy" );
|
||||
static CVAR_DEFINE_AUTO( host_sleeptime_debug, "0", 0, "print sleeps between frames" );
|
||||
@@ -137,8 +140,7 @@ static void Sys_PrintUsage( const char *exename )
|
||||
|
||||
"\nCommon options:\n"
|
||||
O("-dev [level] ", "set log verbosity 0-2")
|
||||
O("-log [file name] ", "write log to \"engine.log\" or [file name] if specified")
|
||||
O("-logtime ", "enable writing timestamps to the log file")
|
||||
O("-log ", "write log to \"engine.log\"")
|
||||
O("-nowriteconfig ", "disable config save")
|
||||
O("-noch ", "disable crashhandler")
|
||||
#if XASH_WIN32 // !!!!
|
||||
@@ -174,7 +176,6 @@ static void Sys_PrintUsage( const char *exename )
|
||||
O("-dll <path> ", "override server DLL path")
|
||||
#if !XASH_DEDICATED
|
||||
O("-clientlib <path> ", "override client DLL path")
|
||||
O("-menulib <path> ", "override menu DLL path")
|
||||
O("-console ", "run engine with console enabled")
|
||||
O("-toconsole ", "run engine witn console open")
|
||||
O("-oldfont ", "enable unused Quake font in Half-Life")
|
||||
@@ -200,6 +201,7 @@ static void Sys_PrintUsage( const char *exename )
|
||||
O("-daemonize ", "run engine as a daemon")
|
||||
#endif
|
||||
#if XASH_SDL == 2
|
||||
O("-sdl_joy_old_api ","use SDL legacy joystick API")
|
||||
O("-sdl_renderer <n> ","use alternative SDL_Renderer for software")
|
||||
#endif // XASH_SDL
|
||||
#if XASH_ANDROID && !XASH_SDL
|
||||
@@ -539,6 +541,13 @@ static void Host_MemStats_f( void )
|
||||
}
|
||||
}
|
||||
|
||||
static void Host_Minimize_f( void )
|
||||
{
|
||||
#ifdef XASH_SDL
|
||||
if( host.hWnd ) SDL_MinimizeWindow( host.hWnd );
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
Host_RegisterDecal
|
||||
@@ -689,17 +698,17 @@ static qboolean Host_Autosleep( double dt, double scale )
|
||||
static double timewindow; // allocate a time window for sleeps
|
||||
static int counter; // for debug
|
||||
static double realsleeptime;
|
||||
const double sleeptime = sleep * 0.000001;
|
||||
const double sleeptime = sleep * 0.001;
|
||||
|
||||
if( dt < targetframetime * scale )
|
||||
{
|
||||
// if we have allocated time window, try to sleep
|
||||
if( timewindow > realsleeptime )
|
||||
{
|
||||
// Platform_Sleep isn't guaranteed to sleep an exact amount of microseconds
|
||||
// Platform_Sleep isn't guaranteed to sleep an exact amount of milliseconds
|
||||
// so we measure the real sleep time and use it to decrease the window
|
||||
double t1 = Sys_DoubleTime(), t2;
|
||||
Platform_NanoSleep( sleep * 1000 ); // in usec!
|
||||
Platform_Sleep( sleep ); // in msec!
|
||||
t2 = Sys_DoubleTime();
|
||||
realsleeptime = t2 - t1;
|
||||
|
||||
@@ -1035,7 +1044,7 @@ static void Host_InitCommon( int argc, char **argv, const char *progname, qboole
|
||||
}
|
||||
|
||||
if( !Sys_CheckParm( "-noch" ))
|
||||
Sys_SetupCrashHandler( argv[0] );
|
||||
Sys_SetupCrashHandler();
|
||||
|
||||
#if XASH_DLL_LOADER
|
||||
host.enabledll = !Sys_CheckParm( "-nodll" );
|
||||
@@ -1227,14 +1236,6 @@ int EXPORT Host_Main( int argc, char **argv, const char *progname, int bChangeGa
|
||||
Cvar_Getf( "host_ver", FCVAR_READ_ONLY, "detailed info about this build", "%i " XASH_VERSION " %s %s %s", Q_buildnum(), Q_buildos(), Q_buildarch(), g_buildcommit);
|
||||
Cvar_Getf( "host_lowmemorymode", FCVAR_READ_ONLY, "indicates if engine compiled for low RAM consumption (0 - normal, 1 - low engine limits, 2 - low protocol limits)", "%i", XASH_LOW_MEMORY );
|
||||
|
||||
Cvar_Get( "host_hl25_extended_structs",
|
||||
#if SUPPORT_HL25_EXTENDED_STRUCTS
|
||||
"1",
|
||||
#else
|
||||
"0",
|
||||
#endif
|
||||
FCVAR_READ_ONLY, "indicates if engine was compiled with extended msurface_t struct" );
|
||||
|
||||
Mod_Init();
|
||||
NET_Init();
|
||||
NET_InitMasters();
|
||||
@@ -1269,7 +1270,7 @@ int EXPORT Host_Main( int argc, char **argv, const char *progname, int bChangeGa
|
||||
Cmd_AddRestrictedCommand( "quit", Sys_Quit_f, "quit the game" );
|
||||
Cmd_AddRestrictedCommand( "exit", Sys_Quit_f, "quit the game" );
|
||||
}
|
||||
else Cmd_AddRestrictedCommand( "minimize", Platform_Minimize_f, "minimize main window to tray" );
|
||||
else Cmd_AddRestrictedCommand( "minimize", Host_Minimize_f, "minimize main window to tray" );
|
||||
|
||||
host.errorframe = 0;
|
||||
|
||||
@@ -1310,7 +1311,6 @@ int EXPORT Host_Main( int argc, char **argv, const char *progname, int bChangeGa
|
||||
Cmd_RemoveCommand( "setgl" );
|
||||
Cbuf_ExecStuffCmds(); // execute stuffcmds (commandline)
|
||||
SCR_CheckStartupVids(); // must be last
|
||||
FS_CheckConfig();
|
||||
|
||||
if( Sys_GetParmFromCmdLine( "-timedemo", demoname ))
|
||||
Cbuf_AddTextf( "timedemo %s\n", demoname );
|
||||
@@ -1345,7 +1345,7 @@ int EXPORT Host_Main( int argc, char **argv, const char *progname, int bChangeGa
|
||||
#endif // XASH_ANDROID
|
||||
|
||||
// main window message loop
|
||||
while( host.status != HOST_CRASHED )
|
||||
while( !host.crashed )
|
||||
{
|
||||
newtime = Sys_DoubleTime ();
|
||||
COM_Frame( newtime - oldtime );
|
||||
|
||||
@@ -220,7 +220,7 @@ void HPAK_AddLump( qboolean bUseQueue, const char *name, resource_t *pResource,
|
||||
|
||||
if( pResource->nDownloadSize < HPAK_ENTRY_MIN_SIZE || pResource->nDownloadSize > HPAK_ENTRY_MAX_SIZE )
|
||||
{
|
||||
Con_Printf( S_ERROR "%s: invalid size %s\n", name, Q_memprint( pResource->nDownloadSize ));
|
||||
Con_Printf( S_ERROR "%s: invalid size %s\n", name, Q_pretifymem( pResource->nDownloadSize, 2 ));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -441,7 +441,7 @@ static qboolean HPAK_Validate( const char *filename, qboolean quiet, qboolean de
|
||||
if( dataDir[i].disksize < HPAK_ENTRY_MIN_SIZE || dataDir[i].disksize > HPAK_ENTRY_MAX_SIZE )
|
||||
{
|
||||
// odd max size
|
||||
Con_DPrintf( S_ERROR "%s: lump %i has invalid size %s\n", __func__, i, Q_memprint( dataDir[i].disksize ));
|
||||
Con_DPrintf( S_ERROR "%s: lump %i has invalid size %s\n", __func__, i, Q_pretifymem( dataDir[i].disksize, 2 ));
|
||||
Mem_Free( dataDir );
|
||||
FS_Close( f );
|
||||
if( delete ) FS_Delete( pakname );
|
||||
@@ -462,7 +462,7 @@ static qboolean HPAK_Validate( const char *filename, qboolean quiet, qboolean de
|
||||
if( !quiet )
|
||||
{
|
||||
Con_Printf( "%i: %s %s %s: ", i, COM_ResourceTypeFromIndex( pRes->type ),
|
||||
Q_memprint( pRes->nDownloadSize ), pRes->szFileName );
|
||||
Q_pretifymem( pRes->nDownloadSize, 2 ), pRes->szFileName );
|
||||
}
|
||||
|
||||
if( memcmp( md5, pRes->rgucMD5_hash, 0x10 ))
|
||||
|
||||
@@ -45,6 +45,7 @@ typedef enum
|
||||
|
||||
typedef struct loadformat_s
|
||||
{
|
||||
const char *formatstring;
|
||||
const char *ext;
|
||||
qboolean (*loadfunc)( const char *name, const byte *buffer, fs_offset_t filesize );
|
||||
image_hint_t hint;
|
||||
@@ -52,6 +53,7 @@ typedef struct loadformat_s
|
||||
|
||||
typedef struct saveformat_s
|
||||
{
|
||||
const char *formatstring;
|
||||
const char *ext;
|
||||
qboolean (*savefunc)( const char *name, rgbdata_t *pix );
|
||||
} savepixformat_t;
|
||||
|
||||
@@ -211,7 +211,7 @@ static const loadpixformat_t *Image_GetLoadFormatForExtension( const char *ext )
|
||||
if( !COM_CheckStringEmpty( ext ))
|
||||
return NULL;
|
||||
|
||||
for( format = image.loadformats; format->ext; format++ )
|
||||
for( format = image.loadformats; format->formatstring; format++ )
|
||||
{
|
||||
if( !Q_stricmp( ext, format->ext ))
|
||||
return format;
|
||||
@@ -237,7 +237,7 @@ static qboolean Image_ProbeLoadBuffer( const loadpixformat_t *fmt, const char *n
|
||||
// bruteforce all loaders
|
||||
if( !fmt )
|
||||
{
|
||||
for( fmt = image.loadformats; fmt->ext; fmt++ )
|
||||
for( fmt = image.loadformats; fmt->formatstring; fmt++ )
|
||||
{
|
||||
if( Image_ProbeLoadBuffer_( fmt, name, buf, size, override_hint ))
|
||||
return true;
|
||||
@@ -256,7 +256,7 @@ static qboolean Image_ProbeLoad_( const loadpixformat_t *fmt, const char *name,
|
||||
string path;
|
||||
byte *f;
|
||||
|
||||
Q_snprintf( path, sizeof( path ), "%s%s.%s", name, suffix, fmt->ext );
|
||||
Q_snprintf( path, sizeof( path ), fmt->formatstring, name, suffix, fmt->ext );
|
||||
f = FS_LoadFile( path, &filesize, false );
|
||||
|
||||
if( f )
|
||||
@@ -274,7 +274,7 @@ static qboolean Image_ProbeLoad( const loadpixformat_t *fmt, const char *name, c
|
||||
if( !fmt )
|
||||
{
|
||||
// bruteforce all formats to allow implicit extension
|
||||
for( fmt = image.loadformats; fmt->ext; fmt++ )
|
||||
for( fmt = image.loadformats; fmt->formatstring; fmt++ )
|
||||
{
|
||||
if( Image_ProbeLoad_( fmt, name, suffix, override_hint ))
|
||||
return true;
|
||||
@@ -417,13 +417,14 @@ qboolean FS_SaveImage( const char *filename, rgbdata_t *pix )
|
||||
picBuffer = pix->buffer;
|
||||
|
||||
// save all sides seperately
|
||||
for( format = image.saveformats; format && format->ext; format++ )
|
||||
for( format = image.saveformats; format && format->formatstring; format++ )
|
||||
{
|
||||
if( !Q_stricmp( ext, format->ext ))
|
||||
{
|
||||
for( i = 0; i < 6; i++ )
|
||||
{
|
||||
Q_snprintf( path, sizeof( path ), "%s%s.%s", savename, box[i].suf, format->ext );
|
||||
Q_snprintf( path, sizeof( path ),
|
||||
format->formatstring, savename, box[i].suf, format->ext );
|
||||
if( !format->savefunc( path, pix )) break; // there were errors
|
||||
pix->buffer += pix->size; // move pointer
|
||||
}
|
||||
@@ -441,11 +442,12 @@ qboolean FS_SaveImage( const char *filename, rgbdata_t *pix )
|
||||
}
|
||||
else
|
||||
{
|
||||
for( format = image.saveformats; format && format->ext; format++ )
|
||||
for( format = image.saveformats; format && format->formatstring; format++ )
|
||||
{
|
||||
if( !Q_stricmp( ext, format->ext ))
|
||||
{
|
||||
Q_snprintf( path, sizeof( path ), "%s.%s", savename, format->ext );
|
||||
Q_snprintf( path, sizeof( path ),
|
||||
format->formatstring, savename, "", format->ext );
|
||||
if( format->savefunc( path, pix ))
|
||||
{
|
||||
// clear any force flags
|
||||
|
||||
@@ -46,7 +46,7 @@ qboolean Image_LoadPNG( const char *name, const byte *buffer, fs_offset_t filesi
|
||||
short p, a, b, c, pa, pb, pc;
|
||||
byte *buf_p, *pixbuf, *raw, *prior, *idat_buf = NULL, *uncompressed_buffer = NULL;
|
||||
byte *pallete = NULL, *trns = NULL;
|
||||
uint chunk_len, trns_len = 0, plte_len = 0, crc32, crc32_check, oldsize = 0, newsize = 0, rowsize;
|
||||
uint chunk_len, trns_len, plte_len, crc32, crc32_check, oldsize = 0, newsize = 0, rowsize;
|
||||
uint uncompressed_size, pixel_size, pixel_count, i, y, filter_type, chunk_sign, r_alpha, g_alpha, b_alpha;
|
||||
qboolean has_iend_chunk = false;
|
||||
z_stream stream = {0};
|
||||
|
||||
@@ -90,23 +90,23 @@ static byte palette_hl[768] =
|
||||
// stub
|
||||
static const loadpixformat_t load_null[] =
|
||||
{
|
||||
{ NULL, NULL, IL_HINT_NO }
|
||||
{ NULL, NULL, NULL, IL_HINT_NO }
|
||||
};
|
||||
|
||||
static const loadpixformat_t load_game[] =
|
||||
{
|
||||
{ "dds", Image_LoadDDS, IL_HINT_NO }, // dds for world and studio models
|
||||
{ "bmp", Image_LoadBMP, IL_HINT_NO }, // WON menu images
|
||||
{ "tga", Image_LoadTGA, IL_HINT_NO }, // hl vgui menus
|
||||
{ "png", Image_LoadPNG, IL_HINT_NO }, // NightFire 007 menus
|
||||
{ "mip", Image_LoadMIP, IL_HINT_NO }, // hl textures from wad or buffer
|
||||
{ "mdl", Image_LoadMDL, IL_HINT_HL }, // hl studio model skins
|
||||
{ "spr", Image_LoadSPR, IL_HINT_HL }, // hl sprite frames
|
||||
{ "lmp", Image_LoadLMP, IL_HINT_NO }, // hl menu images (cached.wad etc)
|
||||
{ "fnt", Image_LoadFNT, IL_HINT_HL }, // hl console font (fonts.wad etc)
|
||||
{ "pal", Image_LoadPAL, IL_HINT_NO }, // install studio\sprite palette
|
||||
{ "ktx2", Image_LoadKTX2, IL_HINT_NO }, // ktx2 for world and studio models
|
||||
{ NULL, NULL, IL_HINT_NO }
|
||||
{ "%s%s.%s", "dds", Image_LoadDDS, IL_HINT_NO }, // dds for world and studio models
|
||||
{ "%s%s.%s", "bmp", Image_LoadBMP, IL_HINT_NO }, // WON menu images
|
||||
{ "%s%s.%s", "tga", Image_LoadTGA, IL_HINT_NO }, // hl vgui menus
|
||||
{ "%s%s.%s", "png", Image_LoadPNG, IL_HINT_NO }, // NightFire 007 menus
|
||||
{ "%s%s.%s", "mip", Image_LoadMIP, IL_HINT_NO }, // hl textures from wad or buffer
|
||||
{ "%s%s.%s", "mdl", Image_LoadMDL, IL_HINT_HL }, // hl studio model skins
|
||||
{ "%s%s.%s", "spr", Image_LoadSPR, IL_HINT_HL }, // hl sprite frames
|
||||
{ "%s%s.%s", "lmp", Image_LoadLMP, IL_HINT_NO }, // hl menu images (cached.wad etc)
|
||||
{ "%s%s.%s", "fnt", Image_LoadFNT, IL_HINT_HL }, // hl console font (fonts.wad etc)
|
||||
{ "%s%s.%s", "pal", Image_LoadPAL, IL_HINT_NO }, // install studio\sprite palette
|
||||
{ "%s%s.%s", "ktx2", Image_LoadKTX2, IL_HINT_NO }, // ktx2 for world and studio models
|
||||
{ NULL, NULL, NULL, IL_HINT_NO }
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -119,16 +119,16 @@ static const loadpixformat_t load_game[] =
|
||||
// stub
|
||||
static const savepixformat_t save_null[] =
|
||||
{
|
||||
{ NULL, NULL }
|
||||
{ NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
// Xash3D normal instance
|
||||
static const savepixformat_t save_game[] =
|
||||
{
|
||||
{ "tga", Image_SaveTGA }, // tga screenshots
|
||||
{ "bmp", Image_SaveBMP }, // bmp levelshots or screenshots
|
||||
{ "png", Image_SavePNG }, // png screenshots
|
||||
{ NULL, NULL }
|
||||
{ "%s%s.%s", "tga", Image_SaveTGA }, // tga screenshots
|
||||
{ "%s%s.%s", "bmp", Image_SaveBMP }, // bmp levelshots or screenshots
|
||||
{ "%s%s.%s", "png", Image_SavePNG }, // png screenshots
|
||||
{ NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
void Image_Setup( void )
|
||||
|
||||
@@ -32,7 +32,7 @@ qboolean Image_LoadPAL( const char *name, const byte *buffer, fs_offset_t filesi
|
||||
|
||||
if( filesize > sizeof( pal ))
|
||||
{
|
||||
Con_DPrintf( S_ERROR "%s: (%s) have invalid size (%li should be less or equal than %zu)\n", __func__, name, (long)filesize, sizeof( pal ));
|
||||
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 )
|
||||
@@ -52,8 +52,6 @@ qboolean Image_LoadPAL( const char *name, const byte *buffer, fs_offset_t filesi
|
||||
rendermode = LUMP_MASKED;
|
||||
else if( Q_stristr( name, "gradient" ))
|
||||
rendermode = LUMP_GRADIENT;
|
||||
else if( Q_stristr( name, "texgamma" ))
|
||||
rendermode = LUMP_TEXGAMMA;
|
||||
else if( Q_stristr( name, "valve" ))
|
||||
{
|
||||
rendermode = LUMP_HALFLIFE;
|
||||
@@ -189,7 +187,7 @@ qboolean Image_LoadMDL( const char *name, const byte *buffer, fs_offset_t filesi
|
||||
Image_GetPaletteLMP( pal, LUMP_MASKED );
|
||||
image.flags |= IMAGE_HAS_ALPHA|IMAGE_ONEBIT_ALPHA;
|
||||
}
|
||||
else Image_GetPaletteLMP( fin + pixels, LUMP_TEXGAMMA );
|
||||
else Image_GetPaletteLMP( fin + pixels, LUMP_NORMAL );
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -228,7 +226,7 @@ qboolean Image_LoadSPR( const char *name, const byte *buffer, fs_offset_t filesi
|
||||
return false;
|
||||
}
|
||||
|
||||
memcpy( &pin, buffer, sizeof( dspriteframe_t ));
|
||||
memcpy( &pin, buffer, sizeof(dspriteframe_t) );
|
||||
image.width = pin.width;
|
||||
image.height = pin.height;
|
||||
|
||||
|
||||
@@ -128,9 +128,9 @@ dll_user_t *FS_FindLibrary( const char *dllname, qboolean directpath )
|
||||
|
||||
static void COM_GenerateCommonLibraryName( const char *name, const char *ext, char *out, size_t size )
|
||||
{
|
||||
#if ( XASH_WIN32 || ( XASH_LINUX && !XASH_ANDROID ) || XASH_APPLE ) && XASH_X86
|
||||
#if ( XASH_WIN32 || XASH_LINUX || XASH_APPLE ) && XASH_X86
|
||||
Q_snprintf( out, size, "%s.%s", name, ext );
|
||||
#elif XASH_WIN32 || ( XASH_LINUX && !XASH_ANDROID ) || XASH_APPLE
|
||||
#elif ( XASH_WIN32 || XASH_LINUX || XASH_APPLE )
|
||||
Q_snprintf( out, size, "%s_%s.%s", name, Q_buildarch(), ext );
|
||||
#else
|
||||
Q_snprintf( out, size, "%s_%s_%s.%s", name, Q_buildos(), Q_buildarch(), ext );
|
||||
@@ -185,12 +185,16 @@ static void COM_GenerateServerLibraryPath( char *out, size_t size )
|
||||
{
|
||||
#ifdef XASH_INTERNAL_GAMELIBS // assuming library loader knows where to get libraries
|
||||
Q_strncpy( out, "server", size );
|
||||
#elif XASH_X86 && XASH_WIN32
|
||||
#elif ( XASH_WIN32 || XASH_LINUX || XASH_APPLE ) && XASH_X86
|
||||
|
||||
#if XASH_WIN32
|
||||
Q_strncpy( out, GI->game_dll, size );
|
||||
#elif XASH_X86 && XASH_APPLE
|
||||
#elif XASH_APPLE
|
||||
Q_strncpy( out, GI->game_dll_osx, size );
|
||||
#elif XASH_X86 && XASH_LINUX && !XASH_ANDROID
|
||||
#else // XASH_LINUX
|
||||
Q_strncpy( out, GI->game_dll_linux, size );
|
||||
#endif
|
||||
|
||||
#else
|
||||
string dllpath;
|
||||
const char *ext;
|
||||
@@ -199,7 +203,7 @@ static void COM_GenerateServerLibraryPath( char *out, size_t size )
|
||||
Q_strncpy( dllpath, GI->game_dll, sizeof( dllpath ) );
|
||||
#elif XASH_APPLE
|
||||
Q_strncpy( dllpath, GI->game_dll_osx, sizeof( dllpath ) );
|
||||
#else
|
||||
#else // XASH_APPLE
|
||||
Q_strncpy( dllpath, GI->game_dll_linux, sizeof( dllpath ) );
|
||||
#endif
|
||||
|
||||
@@ -224,14 +228,7 @@ void COM_GetCommonLibraryPath( ECommonLibraryType eLibType, char *out, size_t si
|
||||
switch( eLibType )
|
||||
{
|
||||
case LIBRARY_GAMEUI:
|
||||
if( COM_CheckStringEmpty( host.menulib ))
|
||||
{
|
||||
Q_strncpy( out, host.menulib, size );
|
||||
}
|
||||
else
|
||||
{
|
||||
COM_GenerateClientLibraryPath( "menu", out, size );
|
||||
}
|
||||
COM_GenerateClientLibraryPath( "menu", out, size );
|
||||
break;
|
||||
case LIBRARY_CLIENT:
|
||||
if( COM_CheckStringEmpty( host.clientlib ))
|
||||
|
||||
@@ -419,21 +419,14 @@ void NET_InitMasters( void )
|
||||
|
||||
Cvar_RegisterVariable( &sv_verbose_heartbeats );
|
||||
|
||||
{ // IPv4-only
|
||||
NET_AddMaster( "mentality.rip:27010", false, false );
|
||||
NET_AddMaster( "ms2.mentality.rip:27010", false, false );
|
||||
NET_AddMaster( "ms3.mentality.rip:27010", false, false );
|
||||
}
|
||||
// keep main master always there
|
||||
NET_AddMaster( MASTERSERVER_ADR, false, false );
|
||||
NET_AddMaster( "mentality.rip:27011", false, false ); // testing server, might be offline
|
||||
NET_AddMaster( "ms2.mentality.rip:27010", false, false ); // secondary master
|
||||
|
||||
{ // IPv6-only
|
||||
NET_AddMaster( "aaaa.mentality.rip:27010", false, true );
|
||||
NET_AddMaster( "aaaa.ms2.mentality.rip:27010", false, true );
|
||||
}
|
||||
|
||||
{ // testing servers, might be offline
|
||||
NET_AddMaster( "mentality.rip:27011", false, false );
|
||||
NET_AddMaster( "aaaa.mentality.rip:27011", false, true );
|
||||
}
|
||||
NET_AddMaster( "aaaa.mentality.rip:27010", false, true ); // IPv6-only
|
||||
NET_AddMaster( "aaaa.mentality.rip:27011", false, true ); // IPv6-only, testing server, might be offline
|
||||
NET_AddMaster( "aaaa.ms2.mentality.rip:27010", false, false ); // secondary IPv6-only master
|
||||
|
||||
NET_LoadMasters( );
|
||||
}
|
||||
|
||||
@@ -129,10 +129,10 @@ typedef struct
|
||||
dclipnode32_t *clipnodes_out; // temporary 32-bit array to hold clipnodes
|
||||
|
||||
// misc stuff
|
||||
int lightmap_samples; // samples per lightmap (1 or 3)
|
||||
int version; // model version
|
||||
qboolean isworld;
|
||||
qboolean isbsp30ext;
|
||||
int lightmap_samples; // samples per lightmap (1 or 3)
|
||||
int version; // model version
|
||||
qboolean isworld;
|
||||
qboolean isbsp30ext;
|
||||
} dbspmodel_t;
|
||||
|
||||
typedef struct
|
||||
@@ -1579,8 +1579,8 @@ static void CountClipNodes16_r( mclipnode16_t *src, hull_t *hull, int nodenum )
|
||||
// leaf?
|
||||
if( nodenum < 0 ) return;
|
||||
|
||||
if( hull->lastclipnode == MAX_MAP_CLIPNODES_HLBSP )
|
||||
Host_Error( "%s: MAX_MAP_CLIPNODES_HLBSP limit exceeded\n", __func__ );
|
||||
if( hull->lastclipnode == MAX_MAP_CLIPNODES )
|
||||
Host_Error( "MAX_MAP_CLIPNODES limit exceeded\n" );
|
||||
hull->lastclipnode++;
|
||||
|
||||
CountClipNodes16_r( src, hull, src[nodenum].children[0] );
|
||||
@@ -1592,25 +1592,25 @@ static void CountClipNodes32_r( mclipnode32_t *src, hull_t *hull, int nodenum )
|
||||
// leaf?
|
||||
if( nodenum < 0 ) return;
|
||||
|
||||
if( hull->lastclipnode == MAX_MAP_CLIPNODES_BSP2 )
|
||||
Host_Error( "%s: MAX_MAP_CLIPNODES_BSP2 limit exceeded\n", __func__ );
|
||||
if( hull->lastclipnode == MAX_MAP_CLIPNODES )
|
||||
Host_Error( "MAX_MAP_CLIPNODES limit exceeded\n" );
|
||||
hull->lastclipnode++;
|
||||
|
||||
CountClipNodes32_r( src, hull, src[nodenum].children[0] );
|
||||
CountClipNodes32_r( src, hull, src[nodenum].children[1] );
|
||||
}
|
||||
|
||||
static void CountDClipNodes_r( dclipnode32_t *src, hull_t *hull, int nodenum, const int max_clipnodes )
|
||||
static void CountDClipNodes_r( dclipnode32_t *src, hull_t *hull, int nodenum )
|
||||
{
|
||||
// leaf?
|
||||
if( nodenum < 0 ) return;
|
||||
|
||||
if( hull->lastclipnode == max_clipnodes )
|
||||
Host_Error( "%s: MAX_MAP_CLIPNODES (%d) limit exceeded\n", __func__, max_clipnodes );
|
||||
if( hull->lastclipnode == MAX_MAP_CLIPNODES )
|
||||
Host_Error( "MAX_MAP_CLIPNODES limit exceeded\n" );
|
||||
hull->lastclipnode++;
|
||||
|
||||
CountDClipNodes_r( src, hull, src[nodenum].children[0], max_clipnodes );
|
||||
CountDClipNodes_r( src, hull, src[nodenum].children[1], max_clipnodes );
|
||||
CountDClipNodes_r( src, hull, src[nodenum].children[0] );
|
||||
CountDClipNodes_r( src, hull, src[nodenum].children[1] );
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1628,17 +1628,8 @@ static int RemapClipNodes_r( dbspmodel_t *bmod, dclipnode32_t *srcnodes, hull_t
|
||||
return nodenum;
|
||||
|
||||
// emit a clipnode
|
||||
if( bmod->version == QBSP2_VERSION )
|
||||
{
|
||||
if( hull->lastclipnode == MAX_MAP_CLIPNODES_BSP2 )
|
||||
Host_Error( "%s: MAX_MAP_CLIPNODES_BSP2 limit exceeded\n", __func__ );
|
||||
}
|
||||
else
|
||||
{
|
||||
if( hull->lastclipnode == MAX_MAP_CLIPNODES_HLBSP )
|
||||
Host_Error( "%s: MAX_MAP_CLIPNODES_HLBSP limit exceeded\n", __func__ );
|
||||
}
|
||||
|
||||
if( hull->lastclipnode == MAX_MAP_CLIPNODES )
|
||||
Host_Error( "MAX_MAP_CLIPNODES limit exceeded\n" );
|
||||
src = srcnodes + nodenum;
|
||||
|
||||
c = hull->lastclipnode;
|
||||
@@ -1770,17 +1761,13 @@ 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
|
||||
|
||||
CountDClipNodes_r( bmod->clipnodes_out, hull, headnode );
|
||||
|
||||
// fit array to real count
|
||||
if( bmod->version == QBSP2_VERSION )
|
||||
{
|
||||
CountDClipNodes_r( bmod->clipnodes_out, hull, headnode, MAX_MAP_CLIPNODES_BSP2 );
|
||||
hull->clipnodes32 = Mem_Malloc( mempool, sizeof( *hull->clipnodes32 ) * hull->lastclipnode );
|
||||
}
|
||||
else
|
||||
{
|
||||
CountDClipNodes_r( bmod->clipnodes_out, hull, headnode, MAX_MAP_CLIPNODES_HLBSP );
|
||||
hull->clipnodes16 = Mem_Malloc( mempool, sizeof( *hull->clipnodes16 ) * hull->lastclipnode );
|
||||
}
|
||||
|
||||
hull->planes = mod->planes; // share planes
|
||||
hull->lastclipnode = 0; // restart counting
|
||||
@@ -3467,7 +3454,7 @@ static void Mod_LoadClipnodes( model_t *mod, dbspmodel_t *bmod )
|
||||
out->children[0] = (unsigned short)in->children[0];
|
||||
out->children[1] = (unsigned short)in->children[1];
|
||||
|
||||
// aguirRe QBSP 'broken' clipnodes
|
||||
// Arguire QBSP 'broken' clipnodes
|
||||
if( out->children[0] >= bmod->numclipnodes )
|
||||
out->children[0] -= 65536;
|
||||
if( out->children[1] >= bmod->numclipnodes )
|
||||
|
||||
@@ -169,7 +169,7 @@ 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 );
|
||||
int Mod_FatPVS( const vec3_t org, float radius, byte *visbuffer, int visbytes, qboolean merge, qboolean fullvis, qboolean phs );
|
||||
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 );
|
||||
|
||||
@@ -382,7 +382,8 @@ static void Mod_StudioCalcRotations( int boneused[], int numbones, const byte *p
|
||||
for( j = numbones - 1; j >= 0; j-- )
|
||||
{
|
||||
i = boneused[j];
|
||||
R_StudioCalcBones( frame, s, &pbone[i], &panim[i], adj, pos[i], q[i] );
|
||||
R_StudioCalcBoneQuaternion( frame, s, &pbone[i], &panim[i], adj, q[i] );
|
||||
R_StudioCalcBonePosition( frame, s, &pbone[i], &panim[i], adj, pos[i] );
|
||||
}
|
||||
|
||||
if( pseqdesc->motiontype & STUDIO_X ) pos[pseqdesc->motionbone][0] = 0.0f;
|
||||
@@ -723,7 +724,7 @@ void Mod_StudioComputeBounds( void *buffer, vec3_t mins, vec3_t maxs, qboolean i
|
||||
{
|
||||
for( k = 0; k < pseqdesc->numframes; k++ )
|
||||
{
|
||||
R_StudioCalcBones( k, 0, &pbones[j], panim, NULL, pos, NULL );
|
||||
R_StudioCalcBonePosition( k, 0, &pbones[j], panim, NULL, pos );
|
||||
Mod_StudioBoundVertex( vert_mins, vert_maxs, &bone_count, pos );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -618,7 +618,7 @@ qboolean MSG_ReadBits( sizebuf_t *sb, void *pOutData, int nBits )
|
||||
int nBitsLeft = nBits;
|
||||
|
||||
// get output dword-aligned.
|
||||
while((( uintptr_t )pOut & 3) != 0 && nBitsLeft >= 8 )
|
||||
while((( uint32_t )pOut & 3) != 0 && nBitsLeft >= 8 )
|
||||
{
|
||||
*pOut = (byte)MSG_ReadUBitLong( sb, 8 );
|
||||
++pOut;
|
||||
@@ -873,7 +873,7 @@ static void Test_Buffer_Write( void )
|
||||
MSG_Init( &sb, __func__, testdata, sizeof( testdata ));
|
||||
TASSERT_EQi( sb.iCurBit, 0 );
|
||||
TASSERT_EQi( sb.nDataBits, sizeof( testdata ) << 3 );
|
||||
TASSERT_EQp( sb.pData, (void *)testdata );
|
||||
TASSERT_EQi( sb.pData, testdata );
|
||||
TASSERT_EQi( sb.bOverflow, false );
|
||||
|
||||
MSG_WriteBytes( &sb, "asdf", 4 );
|
||||
@@ -929,7 +929,7 @@ static void Test_Buffer_Read( void )
|
||||
MSG_StartReading( &sb, (void *)g_testbuf, -1, 0, g_testbuf_bits );
|
||||
TASSERT_EQi( sb.iCurBit, 0 );
|
||||
TASSERT_EQi( sb.nDataBits, g_testbuf_bits );
|
||||
TASSERT_EQp( sb.pData, (void *)g_testbuf );
|
||||
TASSERT_EQi( sb.pData, g_testbuf );
|
||||
TASSERT_EQi( sb.bOverflow, false );
|
||||
|
||||
MSG_ReadBytes( &sb, buf, 4 );
|
||||
|
||||
@@ -198,7 +198,7 @@ static int HTTP_FileQueue( httpfile_t *file )
|
||||
|
||||
if( !( file->file = FS_Open( name, "wb+", true )))
|
||||
{
|
||||
Con_Printf( S_ERROR "HTTP: cannot open %s!\n", name );
|
||||
Con_Printf( S_ERROR "HTTP: cannot open %s!", name );
|
||||
HTTP_FreeFile( file, true );
|
||||
return 0;
|
||||
}
|
||||
@@ -844,16 +844,7 @@ static int HTTP_FileProcessStream( httpfile_t *curfile )
|
||||
|
||||
if( curfile->downloaded >= curfile->size )
|
||||
{
|
||||
// chunked files are finalized in FileSaveReceivedData
|
||||
if( curfile->compressed && !curfile->chunked )
|
||||
{
|
||||
curfile->pfn_process = HTTP_FileDecompress;
|
||||
curfile->success = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
HTTP_FreeFile( curfile, false ); // success
|
||||
}
|
||||
HTTP_FreeFile( curfile, false ); // success
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -121,7 +121,7 @@ static CVAR_DEFINE_AUTO( net_resolve_debug, "0", FCVAR_PRIVILEGED, "print resolv
|
||||
CVAR_DEFINE( net_clockwindow, "clockwindow", "0.5", FCVAR_PRIVILEGED, "timewindow to execute client moves" );
|
||||
|
||||
netadr_t net_local;
|
||||
static netadr_t net6_local;
|
||||
netadr_t net6_local;
|
||||
|
||||
// cvars equivalents for IPv6
|
||||
static CVAR_DEFINE( net_ip6name, "ip6", "localhost", FCVAR_PRIVILEGED, "network ip6 address" );
|
||||
@@ -151,24 +151,17 @@ static inline qboolean NET_IsSocketValid( int socket )
|
||||
|
||||
void NET_NetadrToIP6Bytes( uint8_t *ip6, const netadr_t *adr )
|
||||
{
|
||||
memcpy( &ip6[0], adr->ip6_0, 2 );
|
||||
memcpy( &ip6[2], adr->ip6_1, 14 );
|
||||
memcpy( ip6, adr->ip6, sizeof( adr->ip6 ));
|
||||
}
|
||||
|
||||
void NET_IP6BytesToNetadr( netadr_t *adr, const uint8_t *ip6 )
|
||||
{
|
||||
memcpy( adr->ip6_0, &ip6[0], 2 );
|
||||
memcpy( adr->ip6_1, &ip6[2], 14 );
|
||||
memcpy( adr->ip6, ip6, sizeof( adr->ip6 ));
|
||||
}
|
||||
|
||||
static int NET_NetadrIP6Compare( const netadr_t *a, const netadr_t *b )
|
||||
{
|
||||
uint8_t ip6_a[16], ip6_b[16];
|
||||
|
||||
NET_NetadrToIP6Bytes( ip6_a, a );
|
||||
NET_NetadrToIP6Bytes( ip6_b, b );
|
||||
|
||||
return memcmp( ip6_a, ip6_b, sizeof( ip6_a ));
|
||||
return memcmp( a->ip6, b->ip6, sizeof( a->ip6 ));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -178,29 +171,27 @@ NET_NetadrToSockadr
|
||||
*/
|
||||
static void NET_NetadrToSockadr( netadr_t *a, struct sockaddr_storage *s )
|
||||
{
|
||||
netadrtype_t type = NET_NetadrType( a );
|
||||
|
||||
memset( s, 0, sizeof( *s ));
|
||||
|
||||
if( type == NA_BROADCAST )
|
||||
if( a->type == NA_BROADCAST )
|
||||
{
|
||||
s->ss_family = AF_INET;
|
||||
((struct sockaddr_in *)s)->sin_port = a->port;
|
||||
((struct sockaddr_in *)s)->sin_addr.s_addr = INADDR_BROADCAST;
|
||||
}
|
||||
else if( type == NA_IP )
|
||||
else if( a->type == NA_IP )
|
||||
{
|
||||
s->ss_family = AF_INET;
|
||||
((struct sockaddr_in *)s)->sin_port = a->port;
|
||||
((struct sockaddr_in *)s)->sin_addr.s_addr = a->ip4;
|
||||
}
|
||||
else if( type == NA_IP6 )
|
||||
else if( a->type6 == NA_IP6 )
|
||||
{
|
||||
s->ss_family = AF_INET6;
|
||||
((struct sockaddr_in6 *)s)->sin6_port = a->port;
|
||||
NET_NetadrToIP6Bytes(((struct sockaddr_in6 *)s)->sin6_addr.s6_addr, a );
|
||||
}
|
||||
else if( type == NA_MULTICAST_IP6 )
|
||||
else if( a->type6 == NA_MULTICAST_IP6 )
|
||||
{
|
||||
s->ss_family = AF_INET6;
|
||||
((struct sockaddr_in6 *)s)->sin6_port = a->port;
|
||||
@@ -217,13 +208,13 @@ static void NET_SockadrToNetadr( const struct sockaddr_storage *s, netadr_t *a )
|
||||
{
|
||||
if( s->ss_family == AF_INET )
|
||||
{
|
||||
NET_NetadrSetType( a, NA_IP );
|
||||
a->type = NA_IP;
|
||||
a->ip4 = ((struct sockaddr_in *)s)->sin_addr.s_addr;
|
||||
a->port = ((struct sockaddr_in *)s)->sin_port;
|
||||
}
|
||||
else if( s->ss_family == AF_INET6 )
|
||||
{
|
||||
NET_NetadrSetType( a, NA_IP6 );
|
||||
a->type6 = NA_IP6;
|
||||
NET_IP6BytesToNetadr( a, ((struct sockaddr_in6 *)s)->sin6_addr.s6_addr );
|
||||
a->port = ((struct sockaddr_in6 *)s)->sin6_port;
|
||||
}
|
||||
@@ -558,8 +549,8 @@ qboolean NET_StringToFilterAdr( const char *s, netadr_t *adr, uint *prefixlen )
|
||||
// try to parse as IPv6 first
|
||||
if( ParseIPv6Addr( copy, ip6, NULL, NULL ))
|
||||
{
|
||||
NET_NetadrSetType( adr, NA_IP6 );
|
||||
NET_IP6BytesToNetadr( adr, ip6 );
|
||||
adr->type6 = NA_IP6;
|
||||
|
||||
if( !hasCIDR )
|
||||
*prefixlen = 128;
|
||||
@@ -629,7 +620,7 @@ qboolean NET_StringToFilterAdr( const char *s, netadr_t *adr, uint *prefixlen )
|
||||
adr->ip4 = ntohl( mask );
|
||||
}
|
||||
|
||||
NET_NetadrSetType( adr, NA_IP );
|
||||
adr->type = NA_IP;
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -643,11 +634,10 @@ NET_AdrToString
|
||||
const char *NET_AdrToString( const netadr_t a )
|
||||
{
|
||||
static char s[64];
|
||||
netadrtype_t type = NET_NetadrType( &a );
|
||||
|
||||
if( type == NA_LOOPBACK )
|
||||
if( a.type == NA_LOOPBACK )
|
||||
return "loopback";
|
||||
if( type == NA_IP6 || type == NA_MULTICAST_IP6 )
|
||||
if( a.type6 == NA_IP6 || a.type6 == NA_MULTICAST_IP6 )
|
||||
{
|
||||
uint8_t ip6[16];
|
||||
|
||||
@@ -671,11 +661,10 @@ NET_BaseAdrToString
|
||||
const char *NET_BaseAdrToString( const netadr_t a )
|
||||
{
|
||||
static char s[64];
|
||||
netadrtype_t type = NET_NetadrType( &a );
|
||||
|
||||
if( type == NA_LOOPBACK )
|
||||
if( a.type == NA_LOOPBACK )
|
||||
return "loopback";
|
||||
if( type == NA_IP6 || type == NA_MULTICAST_IP6 )
|
||||
if( a.type6 == NA_IP6 || a.type6 == NA_MULTICAST_IP6 )
|
||||
{
|
||||
uint8_t ip6[16];
|
||||
|
||||
@@ -700,19 +689,16 @@ Compares without the port
|
||||
*/
|
||||
qboolean NET_CompareBaseAdr( const netadr_t a, const netadr_t b )
|
||||
{
|
||||
netadrtype_t type_a = NET_NetadrType( &a );
|
||||
netadrtype_t type_b = NET_NetadrType( &b );
|
||||
|
||||
if( type_a != type_b )
|
||||
if( a.type6 != b.type6 )
|
||||
return false;
|
||||
|
||||
if( type_a == NA_LOOPBACK )
|
||||
if( a.type == NA_LOOPBACK )
|
||||
return true;
|
||||
|
||||
if( type_a == NA_IP )
|
||||
if( a.type == NA_IP )
|
||||
return a.ip4 == b.ip4;
|
||||
|
||||
if( type_a == NA_IP6 )
|
||||
if( a.type6 == NA_IP6 )
|
||||
{
|
||||
if( !NET_NetadrIP6Compare( &a, &b ))
|
||||
return true;
|
||||
@@ -721,6 +707,36 @@ qboolean NET_CompareBaseAdr( const netadr_t a, const netadr_t b )
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
NET_CompareClassBAdr
|
||||
|
||||
Compare local masks
|
||||
====================
|
||||
*/
|
||||
qboolean NET_CompareClassBAdr( const netadr_t a, const netadr_t b )
|
||||
{
|
||||
if( a.type6 != b.type6 )
|
||||
return false;
|
||||
|
||||
if( a.type == NA_LOOPBACK )
|
||||
return true;
|
||||
|
||||
if( a.type == NA_IP )
|
||||
{
|
||||
if( a.ip[0] == b.ip[0] && a.ip[1] == b.ip[1] )
|
||||
return true;
|
||||
}
|
||||
|
||||
// NOTE: we don't check for IPv6 here
|
||||
// this check is very dumb and only used for LAN restriction
|
||||
// Actual check is in IsReservedAdr
|
||||
|
||||
// for real mask compare use NET_CompareAdrByMask
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
NET_CompareAdrByMask
|
||||
@@ -730,13 +746,10 @@ Checks if adr is a part of subnet
|
||||
*/
|
||||
qboolean NET_CompareAdrByMask( const netadr_t a, const netadr_t b, uint prefixlen )
|
||||
{
|
||||
netadrtype_t type_a = NET_NetadrType( &a );
|
||||
netadrtype_t type_b = NET_NetadrType( &b );
|
||||
|
||||
if( type_a != type_b || type_a == NA_LOOPBACK )
|
||||
if( a.type6 != b.type6 || a.type == NA_LOOPBACK )
|
||||
return false;
|
||||
|
||||
if( type_a == NA_IP )
|
||||
if( a.type == NA_IP )
|
||||
{
|
||||
uint32_t ipa = htonl( a.ip4 );
|
||||
uint32_t ipb = htonl( b.ip4 );
|
||||
@@ -744,7 +757,7 @@ qboolean NET_CompareAdrByMask( const netadr_t a, const netadr_t b, uint prefixle
|
||||
if(( ipa & (( 0xFFFFFFFFU ) << ( 32 - prefixlen ))) == ipb )
|
||||
return true;
|
||||
}
|
||||
else if( type_a == NA_IP6 )
|
||||
else if( a.type6 == NA_IP6 )
|
||||
{
|
||||
uint16_t a_[8], b_[8];
|
||||
size_t check = prefixlen / 16;
|
||||
@@ -785,13 +798,11 @@ Check for reserved ip's
|
||||
*/
|
||||
qboolean NET_IsReservedAdr( netadr_t a )
|
||||
{
|
||||
netadrtype_t type_a = NET_NetadrType( &a );
|
||||
|
||||
if( type_a == NA_LOOPBACK )
|
||||
if( a.type == NA_LOOPBACK )
|
||||
return true;
|
||||
|
||||
// Following checks was imported from GameNetworkingSockets library
|
||||
if( type_a == NA_IP )
|
||||
if( a.type == NA_IP )
|
||||
{
|
||||
if(( a.ip[0] == 10 ) || // 10.x.x.x is reserved
|
||||
( a.ip[0] == 127 ) || // 127.x.x.x
|
||||
@@ -803,7 +814,7 @@ qboolean NET_IsReservedAdr( netadr_t a )
|
||||
}
|
||||
}
|
||||
|
||||
if( type_a == NA_IP6 )
|
||||
if( a.type6 == NA_IP6 )
|
||||
{
|
||||
uint8_t ip6[16];
|
||||
|
||||
@@ -836,23 +847,20 @@ Compare full address
|
||||
*/
|
||||
qboolean NET_CompareAdr( const netadr_t a, const netadr_t b )
|
||||
{
|
||||
netadrtype_t type_a = NET_NetadrType( &a );
|
||||
netadrtype_t type_b = NET_NetadrType( &b );
|
||||
|
||||
if( type_a != type_b )
|
||||
if( a.type6 != b.type6 )
|
||||
return false;
|
||||
|
||||
if( type_a == NA_LOOPBACK )
|
||||
if( a.type == NA_LOOPBACK )
|
||||
return true;
|
||||
|
||||
if( type_a == NA_IP )
|
||||
if( a.type == NA_IP )
|
||||
{
|
||||
if( a.ip4 == b.ip4 && a.port == b.port )
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
if( type_a == NA_IP6 )
|
||||
if( a.type6 == NA_IP6 )
|
||||
{
|
||||
if( a.port == b.port && !NET_NetadrIP6Compare( &a, &b ))
|
||||
return true;
|
||||
@@ -875,13 +883,9 @@ int NET_CompareAdrSort( const void *_a, const void *_b )
|
||||
{
|
||||
const netadr_t *a = _a, *b = _b;
|
||||
int porta, portb, portdiff, addrdiff;
|
||||
netadrtype_t type_a, type_b;
|
||||
|
||||
type_a = NET_NetadrType( a );
|
||||
type_b = NET_NetadrType( b );
|
||||
|
||||
if( type_a != type_b )
|
||||
return bound( -1, (int)type_a - (int)type_b, 1 );
|
||||
if( a->type6 != b->type6 )
|
||||
return bound( -1, (int)a->type6 - (int)b->type6, 1 );
|
||||
|
||||
porta = ntohs( a->port );
|
||||
portb = ntohs( b->port );
|
||||
@@ -892,7 +896,7 @@ int NET_CompareAdrSort( const void *_a, const void *_b )
|
||||
else
|
||||
portdiff = 0;
|
||||
|
||||
switch( type_a )
|
||||
switch( a->type6 )
|
||||
{
|
||||
case NA_IP6:
|
||||
if(( addrdiff = NET_NetadrIP6Compare( a, b )))
|
||||
@@ -900,7 +904,14 @@ int NET_CompareAdrSort( const void *_a, const void *_b )
|
||||
// fallthrough
|
||||
case NA_MULTICAST_IP6:
|
||||
return portdiff;
|
||||
}
|
||||
|
||||
// don't check for full type earlier, as it's value depends on v6 address
|
||||
if( a->type != b->type )
|
||||
return bound( -1, (int)a->type - (int)b->type, 1 );
|
||||
|
||||
switch( a->type )
|
||||
{
|
||||
case NA_IP:
|
||||
if(( addrdiff = memcmp( a->ip, b->ip, sizeof( a->ipx ))))
|
||||
return addrdiff;
|
||||
@@ -935,7 +946,7 @@ static qboolean NET_StringToAdrEx( const char *string, netadr_t *adr, int family
|
||||
|
||||
if( !Q_stricmp( string, "localhost" ) || !Q_stricmp( string, "loopback" ))
|
||||
{
|
||||
NET_NetadrSetType( adr, NA_LOOPBACK );
|
||||
adr->type = NA_LOOPBACK;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -960,7 +971,7 @@ net_gai_state_t NET_StringToAdrNB( const char *string, netadr_t *adr, qboolean v
|
||||
|
||||
if( !Q_stricmp( string, "localhost" ) || !Q_stricmp( string, "loopback" ))
|
||||
{
|
||||
NET_NetadrSetType( adr, NA_LOOPBACK );
|
||||
adr->type = NA_LOOPBACK;
|
||||
return NET_EAI_OK;
|
||||
}
|
||||
|
||||
@@ -1006,7 +1017,7 @@ static qboolean NET_GetLoopPacket( netsrc_t sock, netadr_t *from, byte *data, si
|
||||
*length = loop->msgs[i].datalen;
|
||||
|
||||
memset( from, 0, sizeof( *from ));
|
||||
NET_NetadrSetType( from, NA_LOOPBACK );
|
||||
from->type = NA_LOOPBACK;
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -1512,7 +1523,7 @@ static int NET_SendLong( netsrc_t sock, int net_socket, const char *buf, size_t
|
||||
total_sent += size;
|
||||
len -= size;
|
||||
packet_number++;
|
||||
Platform_NanoSleep( 100 * 1000 );
|
||||
Platform_Sleep( 1 );
|
||||
}
|
||||
|
||||
return total_sent;
|
||||
@@ -1535,20 +1546,19 @@ void NET_SendPacketEx( netsrc_t sock, size_t length, const void *data, netadr_t
|
||||
int ret;
|
||||
struct sockaddr_storage addr = { 0 };
|
||||
SOCKET net_socket = 0;
|
||||
netadrtype_t type = NET_NetadrType( &to );
|
||||
|
||||
if( !net.initialized || type == NA_LOOPBACK )
|
||||
if( !net.initialized || to.type == NA_LOOPBACK )
|
||||
{
|
||||
NET_SendLoopPacket( sock, length, data, to );
|
||||
return;
|
||||
}
|
||||
else if( type == NA_BROADCAST || type == NA_IP )
|
||||
else if( to.type == NA_BROADCAST || to.type == NA_IP )
|
||||
{
|
||||
net_socket = net.ip_sockets[sock];
|
||||
if( !NET_IsSocketValid( net_socket ))
|
||||
return;
|
||||
}
|
||||
else if( type == NA_MULTICAST_IP6 || type == NA_IP6 )
|
||||
else if( to.type6 == NA_MULTICAST_IP6 || to.type6 == NA_IP6 )
|
||||
{
|
||||
net_socket = net.ip6_sockets[sock];
|
||||
if( !NET_IsSocketValid( net_socket ))
|
||||
@@ -1556,7 +1566,7 @@ void NET_SendPacketEx( netsrc_t sock, size_t length, const void *data, netadr_t
|
||||
}
|
||||
else
|
||||
{
|
||||
Host_Error( "%s: bad address type %i (%i, %i)\n", __func__, to.type, to.ip6_0[0], to.ip6_0[1] );
|
||||
Host_Error( "%s: bad address type %i (%i)\n", __func__, to.type, to.type6 );
|
||||
}
|
||||
|
||||
NET_NetadrToSockadr( &to, &addr );
|
||||
@@ -1572,7 +1582,7 @@ void NET_SendPacketEx( netsrc_t sock, size_t length, const void *data, netadr_t
|
||||
return;
|
||||
|
||||
// some PPP links don't allow broadcasts
|
||||
if( err == WSAEADDRNOTAVAIL && ( type == NA_BROADCAST || type == NA_MULTICAST_IP6 ))
|
||||
if( err == WSAEADDRNOTAVAIL && ( to.type == NA_BROADCAST || to.type6 == NA_MULTICAST_IP6 ))
|
||||
return;
|
||||
|
||||
if( Host_IsDedicated( ))
|
||||
@@ -1791,12 +1801,12 @@ static void NET_OpenIP( qboolean change_port, int *sockets, const char *net_ifac
|
||||
|
||||
/*
|
||||
================
|
||||
NET_DetermineLocalAddress
|
||||
NET_GetLocalAddress
|
||||
|
||||
Returns the servers' ip address as a string.
|
||||
================
|
||||
*/
|
||||
static void NET_DetermineLocalAddress( void )
|
||||
static void NET_GetLocalAddress( void )
|
||||
{
|
||||
char hostname[512];
|
||||
char buff[512];
|
||||
@@ -1910,7 +1920,7 @@ void NET_Config( qboolean multiplayer, qboolean changeport )
|
||||
// get our local address, if possible
|
||||
if( bFirst )
|
||||
{
|
||||
NET_DetermineLocalAddress();
|
||||
NET_GetLocalAddress();
|
||||
bFirst = false;
|
||||
}
|
||||
}
|
||||
@@ -2006,32 +2016,6 @@ static void NET_ClearLagData( qboolean bClient, qboolean bServer )
|
||||
if( bServer ) NET_ClearLaggedList( &net.lagdata[NS_SERVER] );
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
NET_GetLocalAddress
|
||||
|
||||
get local server addresses
|
||||
====================
|
||||
*/
|
||||
void NET_GetLocalAddress( netadr_t *ip4, netadr_t *ip6 )
|
||||
{
|
||||
if( ip4 )
|
||||
{
|
||||
if( net.allow_ip )
|
||||
*ip4 = net_local;
|
||||
else
|
||||
memset( ip4, 0, sizeof( *ip4 ));
|
||||
}
|
||||
|
||||
if( ip6 )
|
||||
{
|
||||
if( net.allow_ip6 )
|
||||
*ip6 = net6_local;
|
||||
else
|
||||
memset( ip6, 0, sizeof( *ip6 ));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
NET_Init
|
||||
@@ -2053,7 +2037,6 @@ void NET_Init( void )
|
||||
Cvar_RegisterVariable( &net_fakelag );
|
||||
Cvar_RegisterVariable( &net_fakeloss );
|
||||
Cvar_RegisterVariable( &net_resolve_debug );
|
||||
Cvar_RegisterVariable( &net_clockwindow );
|
||||
|
||||
Q_snprintf( cmd, sizeof( cmd ), "%i", PORT_SERVER );
|
||||
Cvar_FullSet( "hostport", cmd, FCVAR_READ_ONLY );
|
||||
|
||||
@@ -64,6 +64,7 @@ void NET_Config( qboolean net_enable, qboolean changeport );
|
||||
const char *NET_AdrToString( const netadr_t a ) RETURNS_NONNULL;
|
||||
const char *NET_BaseAdrToString( const netadr_t a ) RETURNS_NONNULL;
|
||||
qboolean NET_IsReservedAdr( netadr_t a );
|
||||
qboolean NET_CompareClassBAdr( const netadr_t a, const netadr_t b );
|
||||
qboolean NET_StringToAdr( const char *string, netadr_t *adr );
|
||||
qboolean NET_StringToFilterAdr( const char *s, netadr_t *adr, uint *prefixlen );
|
||||
net_gai_state_t NET_StringToAdrNB( const char *string, netadr_t *adr, qboolean v6only );
|
||||
@@ -79,11 +80,9 @@ void NET_NetadrToIP6Bytes( uint8_t *ip6, const netadr_t *adr );
|
||||
|
||||
static inline qboolean NET_IsLocalAddress( netadr_t adr )
|
||||
{
|
||||
return NET_NetadrType( &adr ) == NA_LOOPBACK;
|
||||
return adr.type == NA_LOOPBACK ? true : false;
|
||||
}
|
||||
|
||||
void NET_GetLocalAddress( netadr_t *ip4, netadr_t *ip6 );
|
||||
|
||||
#if !XASH_DEDICATED
|
||||
int CL_GetSplitSize( void );
|
||||
#endif
|
||||
|
||||
@@ -69,6 +69,7 @@ GNU General Public License for more details.
|
||||
// bytes will be stripped by the networking channel layer
|
||||
#define NET_MAX_MESSAGE PAD_NUMBER(( NET_MAX_PAYLOAD + HEADER_BYTES ), 16 )
|
||||
|
||||
#define MASTERSERVER_ADR "mentality.rip:27010"
|
||||
#define MS_SCAN_REQUEST "1\xFF" "0.0.0.0:0\0"
|
||||
|
||||
#define PORT_MASTER 27010
|
||||
@@ -290,6 +291,8 @@ typedef struct netchan_s
|
||||
} netchan_t;
|
||||
|
||||
extern netadr_t net_from;
|
||||
extern netadr_t net_local;
|
||||
extern netadr_t net6_local;
|
||||
extern sizebuf_t net_message;
|
||||
extern byte net_message_buffer[NET_MAX_MESSAGE];
|
||||
extern convar_t sv_lan;
|
||||
|
||||
@@ -14,6 +14,9 @@ GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include "soundlib.h"
|
||||
#if XASH_SDL
|
||||
#include <SDL_audio.h>
|
||||
#endif // XASH_SDL
|
||||
|
||||
// global sound variables
|
||||
sndlib_t sound;
|
||||
@@ -28,15 +31,19 @@ sndlib_t sound;
|
||||
static const loadwavfmt_t load_game[] =
|
||||
{
|
||||
#ifndef XASH_DEDICATED
|
||||
{ "wav", Sound_LoadWAV },
|
||||
{ "mp3", Sound_LoadMPG },
|
||||
{ "ogg", Sound_LoadOggVorbis },
|
||||
{ "opus", Sound_LoadOggOpus },
|
||||
{ DEFAULT_SOUNDPATH "%s%s.%s", "wav", Sound_LoadWAV },
|
||||
{ "%s%s.%s", "wav", Sound_LoadWAV },
|
||||
{ DEFAULT_SOUNDPATH "%s%s.%s", "mp3", Sound_LoadMPG },
|
||||
{ "%s%s.%s", "mp3", Sound_LoadMPG },
|
||||
{ DEFAULT_SOUNDPATH "%s%s.%s", "ogg", Sound_LoadOggVorbis },
|
||||
{ "%s%s.%s", "ogg", Sound_LoadOggVorbis },
|
||||
{ DEFAULT_SOUNDPATH "%s%s.%s", "opus", Sound_LoadOggOpus },
|
||||
{ "%s%s.%s", "opus", Sound_LoadOggOpus },
|
||||
#else // we only need extensions
|
||||
{ "wav" },
|
||||
{ "mp3" },
|
||||
{ "ogg" },
|
||||
{ "opus" },
|
||||
{ NULL, "wav" },
|
||||
{ NULL, "mp3" },
|
||||
{ NULL, "ogg" },
|
||||
{ NULL, "opus" },
|
||||
#endif
|
||||
{ NULL },
|
||||
};
|
||||
@@ -51,15 +58,15 @@ static const loadwavfmt_t load_game[] =
|
||||
static const streamfmt_t stream_game[] =
|
||||
{
|
||||
#ifndef XASH_DEDICATED
|
||||
{ "mp3", Stream_OpenMPG, Stream_ReadMPG, Stream_SetPosMPG, Stream_GetPosMPG, Stream_FreeMPG },
|
||||
{ "wav", Stream_OpenWAV, Stream_ReadWAV, Stream_SetPosWAV, Stream_GetPosWAV, Stream_FreeWAV },
|
||||
{ "ogg", Stream_OpenOggVorbis, Stream_ReadOggVorbis, Stream_SetPosOggVorbis, Stream_GetPosOggVorbis, Stream_FreeOggVorbis },
|
||||
{ "opus", Stream_OpenOggOpus, Stream_ReadOggOpus, Stream_SetPosOggOpus, Stream_GetPosOggOpus, Stream_FreeOggOpus },
|
||||
{ "%s%s.%s", "mp3", Stream_OpenMPG, Stream_ReadMPG, Stream_SetPosMPG, Stream_GetPosMPG, Stream_FreeMPG },
|
||||
{ "%s%s.%s", "wav", Stream_OpenWAV, Stream_ReadWAV, Stream_SetPosWAV, Stream_GetPosWAV, Stream_FreeWAV },
|
||||
{ "%s%s.%s", "ogg", Stream_OpenOggVorbis, Stream_ReadOggVorbis, Stream_SetPosOggVorbis, Stream_GetPosOggVorbis, Stream_FreeOggVorbis },
|
||||
{ "%s%s.%s", "opus", Stream_OpenOggOpus, Stream_ReadOggOpus, Stream_SetPosOggOpus, Stream_GetPosOggOpus, Stream_FreeOggOpus },
|
||||
#else // we only need extensions
|
||||
{ "mp3" },
|
||||
{ "wav" },
|
||||
{ "ogg" },
|
||||
{ "opus" },
|
||||
{ NULL, "mp3" },
|
||||
{ NULL, "wav" },
|
||||
{ NULL, "ogg" },
|
||||
{ NULL, "opus" },
|
||||
#endif
|
||||
{ NULL },
|
||||
};
|
||||
@@ -381,6 +388,31 @@ static qboolean Sound_ResampleInternal( wavdata_t *sc, int outrate, int outwidth
|
||||
if( FBitSet( sc->flags, SOUND_LOOPED ))
|
||||
sc->loopStart = sc->loopStart / stepscale;
|
||||
|
||||
#if 0 && XASH_SDL // slow but somewhat accurate (wasn't updated to channel manipulation!!!)
|
||||
{
|
||||
const SDL_AudioFormat infmt = inwidth == 1 ? AUDIO_S8 : AUDIO_S16;
|
||||
const SDL_AudioFormat outfmt = outwidth == 1 ? AUDIO_S8 : AUDIO_S16;
|
||||
SDL_AudioCVT cvt;
|
||||
|
||||
// SDL_AudioCVT does conversion in place, original buffer is used for it
|
||||
if( SDL_BuildAudioCVT( &cvt, infmt, inchannels, inrate, outfmt, outchannels, outrate ) > 0 && cvt.needed )
|
||||
{
|
||||
sc->buffer = (byte *)Mem_Realloc( host.soundpool, sc->buffer, oldsize * cvt.len_mult );
|
||||
cvt.len = oldsize;
|
||||
cvt.buf = sc->buffer;
|
||||
|
||||
if( !SDL_ConvertAudio( &cvt ))
|
||||
{
|
||||
t2 = Sys_DoubleTime();
|
||||
Con_Reportf( "Sound_Resample: from [%d bit %d Hz] to [%d bit %d Hz] (took %.3fs through SDL)\n", inwidth * 8, inrate, outwidth * 8, outrate, t2 - t1 );
|
||||
sc->rate = outrate;
|
||||
sc->width = outwidth;
|
||||
return false; // HACKHACK: return false so Sound_Process won't reallocate buffer
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
sound.tempbuffer = (byte *)Mem_Realloc( host.soundpool, sound.tempbuffer, sc->size );
|
||||
|
||||
if( inrate == outrate ) // no resampling, just copy data
|
||||
@@ -449,7 +481,7 @@ qboolean Sound_SupportedFileFormat( const char *fileext )
|
||||
const loadwavfmt_t *format;
|
||||
if( COM_CheckStringEmpty( fileext ))
|
||||
{
|
||||
for( format = sound.loadformats; format && format->ext; format++ )
|
||||
for( format = sound.loadformats; format && format->formatstring; format++ )
|
||||
{
|
||||
if( !Q_stricmp( format->ext, fileext ))
|
||||
return true;
|
||||
|
||||
@@ -23,12 +23,14 @@ GNU General Public License for more details.
|
||||
|
||||
typedef struct loadwavfmt_s
|
||||
{
|
||||
const char *formatstring;
|
||||
const char *ext;
|
||||
qboolean (*loadfunc)( const char *name, const byte *buffer, fs_offset_t filesize );
|
||||
} loadwavfmt_t;
|
||||
|
||||
typedef struct streamfmt_s
|
||||
{
|
||||
const char *formatstring;
|
||||
const char *ext;
|
||||
|
||||
stream_t *(*openfunc)( const char *filename );
|
||||
|
||||
@@ -31,14 +31,15 @@ GNU General Public License for more details.
|
||||
#define XASH_COLORIZE_CONSOLE 0
|
||||
#endif
|
||||
|
||||
static struct logdata_s {
|
||||
char title[64];
|
||||
qboolean log_active;
|
||||
qboolean log_time;
|
||||
char log_path[MAX_SYSPATH];
|
||||
FILE *logfile;
|
||||
int logfileno;
|
||||
} s_ld;
|
||||
typedef struct {
|
||||
char title[64];
|
||||
qboolean log_active;
|
||||
char log_path[MAX_SYSPATH];
|
||||
FILE *logfile;
|
||||
int logfileno;
|
||||
} LogData;
|
||||
|
||||
static LogData s_ld;
|
||||
|
||||
void Sys_DestroyConsole( void )
|
||||
{
|
||||
@@ -77,19 +78,14 @@ static void Sys_FlushLogfile( void )
|
||||
|
||||
void Sys_InitLog( void )
|
||||
{
|
||||
const char *mode;
|
||||
const char *mode;
|
||||
|
||||
if( Sys_CheckParm( "-log" ))
|
||||
if( Sys_CheckParm( "-log" ) && host.allow_console != 0 )
|
||||
{
|
||||
if( !Sys_GetParmFromCmdLine( "-log", s_ld.log_path ) || !isalnum( s_ld.log_path[0] ))
|
||||
Q_strncpy( s_ld.log_path, "engine.log", sizeof( s_ld.log_path ));
|
||||
|
||||
COM_DefaultExtension( s_ld.log_path, ".log", sizeof( s_ld.log_path ));
|
||||
s_ld.log_active = true;
|
||||
Q_strncpy( s_ld.log_path, "engine.log", sizeof( s_ld.log_path ));
|
||||
}
|
||||
|
||||
s_ld.log_time = Sys_CheckParm( "-logtime" );
|
||||
|
||||
if( host.change_game && host.type != HOST_DEDICATED )
|
||||
mode = "a";
|
||||
else mode = "w";
|
||||
@@ -105,7 +101,7 @@ void Sys_InitLog( void )
|
||||
|
||||
if ( !s_ld.logfile )
|
||||
{
|
||||
Con_Reportf( S_ERROR "%s: can't create log file %s: %s\n", __func__, s_ld.log_path, strerror( errno ));
|
||||
Con_Reportf( S_ERROR "Sys_InitLog: can't create log file %s: %s\n", s_ld.log_path, strerror( errno ));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -271,7 +267,7 @@ void Sys_PrintLog( const char *pMsg )
|
||||
const struct tm *crt_tm;
|
||||
char logtime[32] = "";
|
||||
static char lastchar;
|
||||
qboolean print_time = false;
|
||||
qboolean print_time = true;
|
||||
size_t len, logtime_len = 0;
|
||||
|
||||
if( !lastchar || lastchar == '\n' )
|
||||
@@ -279,9 +275,11 @@ void Sys_PrintLog( const char *pMsg )
|
||||
if( time( &crt_time ) >= 0 )
|
||||
{
|
||||
crt_tm = localtime( &crt_time );
|
||||
print_time = crt_tm != NULL;
|
||||
if( crt_tm == NULL )
|
||||
print_time = false;
|
||||
}
|
||||
}
|
||||
else print_time = false;
|
||||
|
||||
if( print_time )
|
||||
{
|
||||
@@ -297,23 +295,17 @@ void Sys_PrintLog( const char *pMsg )
|
||||
// save last char to detect when line was not ended
|
||||
lastchar = len > 0 ? pMsg[len - 1] : 0;
|
||||
|
||||
// spew to engine.log
|
||||
if( s_ld.logfile )
|
||||
{
|
||||
if( s_ld.log_time && print_time )
|
||||
{
|
||||
logtime_len = strftime( logtime, sizeof( logtime ), "[%Y:%m:%d|%H:%M:%S] ", crt_tm ); //full time
|
||||
logtime_len = Q_min( logtime_len, sizeof( logtime ) - 1 ); // just in case
|
||||
}
|
||||
else
|
||||
{
|
||||
logtime[0] = '\0';
|
||||
logtime_len = 0;
|
||||
}
|
||||
if( !s_ld.logfile )
|
||||
return;
|
||||
|
||||
Sys_PrintLogfile( s_ld.logfileno, logtime, logtime_len, pMsg, false );
|
||||
Sys_FlushLogfile();
|
||||
if( print_time )
|
||||
{
|
||||
logtime_len = strftime( logtime, sizeof( logtime ), "[%Y:%m:%d|%H:%M:%S] ", crt_tm ); //full time
|
||||
logtime_len = Q_min( logtime_len, sizeof( logtime ) - 1 ); // just in case
|
||||
}
|
||||
|
||||
Sys_PrintLogfile( s_ld.logfileno, logtime, logtime_len, pMsg, false );
|
||||
Sys_FlushLogfile();
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||