Compare commits

..
200 changed files with 6909 additions and 8888 deletions
+3 -3
View File
@@ -1,10 +1,10 @@
task: task:
name: freebsd-14-amd64 name: freebsd-14-amd64
freebsd_instance: freebsd_instance:
image_family: freebsd-14-2 image_family: freebsd-14-0
setup_script: setup_script:
- pkg update - pkg update
- pkg install -y pkgconf git sdl2 python fontconfig libvorbis opusfile bzip2 libbacktrace - pkg install -y pkgconf git sdl2 python fontconfig opus
- git submodule update --init --recursive - git submodule update --init --recursive
test_script: test_script:
- ./scripts/cirrus/build_freebsd.sh dedicated - ./scripts/cirrus/build_freebsd.sh dedicated
@@ -16,7 +16,7 @@ task:
image_family: freebsd-15-0-snap image_family: freebsd-15-0-snap
setup_script: setup_script:
- pkg update - pkg update
- pkg install -y pkgconf git sdl2 python fontconfig libvorbis opusfile bzip2 libbacktrace - pkg install -y pkgconf git sdl2 python fontconfig opus
- git submodule update --init --recursive - git submodule update --init --recursive
test_script: test_script:
- ./scripts/cirrus/build_freebsd.sh dedicated - ./scripts/cirrus/build_freebsd.sh dedicated
+3 -3
View File
@@ -66,7 +66,7 @@ jobs:
targetos: apple targetos: apple
targetarch: amd64 targetarch: amd64
env: env:
SDL_VERSION: 2.32.0 SDL_VERSION: 2.30.9
GH_CPU_ARCH: ${{ matrix.targetarch }} GH_CPU_ARCH: ${{ matrix.targetarch }}
GH_CROSSCOMPILING: ${{ matrix.cross }} GH_CROSSCOMPILING: ${{ matrix.cross }}
steps: steps:
@@ -87,7 +87,6 @@ jobs:
path: artifacts/* path: artifacts/*
flatpak: flatpak:
runs-on: ubuntu-latest runs-on: ubuntu-latest
continue-on-error: true
strategy: strategy:
matrix: matrix:
include: include:
@@ -101,7 +100,7 @@ jobs:
with: with:
submodules: recursive submodules: recursive
- name: Build flatpak (Compat.i386) - 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: with:
bundle: ${{ matrix.app }}.flatpak bundle: ${{ matrix.app }}.flatpak
manifest-path: scripts/flatpak/${{ matrix.app }}.yml manifest-path: scripts/flatpak/${{ matrix.app }}.yml
@@ -120,6 +119,7 @@ jobs:
--yes \ --yes \
--cleanup-tag \ --cleanup-tag \
--repo "$GITHUB_REPOSITORY" || true --repo "$GITHUB_REPOSITORY" || true
sleep 20s
gh run download "$GITHUB_RUN_ID" \ gh run download "$GITHUB_RUN_ID" \
--dir artifacts/ \ --dir artifacts/ \
--repo "$GITHUB_REPOSITORY" --repo "$GITHUB_REPOSITORY"
-3
View File
@@ -34,6 +34,3 @@
[submodule "3rdparty/opusfile/opusfile"] [submodule "3rdparty/opusfile/opusfile"]
path = 3rdparty/opusfile/opusfile path = 3rdparty/opusfile/opusfile
url = https://gitlab.xiph.org/xiph/opusfile.git url = https://gitlab.xiph.org/xiph/opusfile.git
[submodule "3rdparty/libbacktrace/libbacktrace"]
path = 3rdparty/libbacktrace/libbacktrace
url = https://github.com/ianlancetaylor/libbacktrace
+1
View File
@@ -25,4 +25,5 @@ def build(bld):
name = 'extras.pk3', name = 'extras.pk3',
files = srcdir.ant_glob('**/*'), files = srcdir.ant_glob('**/*'),
relative_to = srcdir, relative_to = srcdir,
compresslevel = 0,
install_path = install_path) install_path = install_path)
-185
View File
@@ -1,185 +0,0 @@
#! /usr/bin/env python
# encoding: utf-8
from waflib import TaskGen
FRAGMENT_ATOMIC='''int i;
int main(void) {
__atomic_load_n(&i, __ATOMIC_ACQUIRE);
__atomic_store_n(&i, 1, __ATOMIC_RELEASE);
return 0;
}'''
FRAGMENT_SYNC='''int i;
int main (void) {
__sync_bool_compare_and_swap (&i, i, i);
__sync_lock_test_and_set (&i, 1);
__sync_lock_release (&i);
return 0;
}'''
FRAGMENT_GETPAGESIZE='''#include <unistd.h>
int main(void) { return getpagesize() }'''
FRAGMENT_GETEXECNAME='''#include <stdlib.h>
int main(void) { return getexecname() != 0 }'''
FRAGMENT_STRNLEN='''#include <string.h>
int main(int argc, char **argv) { return (int)strnlen(argv[0], 10); }'''
FRAGMENT_DL_ITERATE_PHDR='''#include <%s>
int main(void) { return dl_iterate_phdr(0, 0); }'''
FRAGMENT_FCNTL='''#include <fcntl.h>
int main(void) { return fcntl(0, 0, 0); }'''
FRAGMENT_GETIPINFO='''#include "unwind.h"
struct _Unwind_Context *context;
int ip_before_insn = 0;
int main(void) { return _Unwind_GetIPInfo(context, &ip_before_insn); }'''
FRAGMENT_LOADQUERY='''#include <sys/ldr.h>
#include <sys/debug.h>
int main(void) { return loadquery(0, 0, 0); }'''
FRAGMENT_KERN_PROC='''#include <sys/sysctl.h>
#if !defined(%s) || !defined(KERN_PROC_PATHNAME)
#error
#endif
int main(void) { return 0; }'''
FRAGMENT_LSTAT='''#include <sys/stat.h>
struct stat st;
int main(int argc, char **argv) { return lstat(argv[0], &st); }'''
FRAGMENT_READLINK='''#include <unistd.h>
char buf[100];
int main(int argc, char **argv) { return readlink(argv[0], buf, sizeof(buf)); }'''
def options(opt):
pass
def configure(conf):
# add unsupported platforms here
if conf.env.DEST_OS in ['nswitch', 'psvita', 'dos']:
conf.env.DISABLE_LIBBACKTRACE = True
return
# win32 has it's own dbghelp-based backtrace, that's why we ship PDBs
if conf.env.COMPILER_CC == 'msvc':
conf.env.DISABLE_LIBBACKTRACE = True
return
if not conf.path.find_dir('libbacktrace') or not conf.path.find_dir('libbacktrace/config'):
conf.fatal('Can\'t find libbacktrace submodule. Run `git submodule update --init --recursive`.')
return
if conf.env.DEST_SIZEOF_VOID_P == 8:
conf.define('BACKTRACE_ELF_SIZE', 64)
conf.define('BACKTRACE_XCOFF_SIZE', 64)
else:
conf.define('BACKTRACE_ELF_SIZE', 32)
conf.define('BACKTRACE_XCOFF_SIZE', 32)
conf.define('_ALL_SOURCE', 1)
conf.define('_GNU_SOURCE', 1)
conf.define('_POSIX_PTHREAD_SEMANTICS', 1)
conf.define('_TANDEM_SOURCE', 1)
conf.define('__EXTENSIONS__', 1)
conf.define('_DARWIN_USE_64_BIT_INODE', 1)
conf.define('_LARGE_FILES', 1)
conf.check_large_file(compiler='c', execute=False, mandatory=False) # sets _FILE_OFFSET_BITS
conf.env.CFLAGS_EXTRAFLAGS = conf.filter_cflags(['-funwind-tables', '-g'], [])
if conf.filter_cflags(['-frandom-seed=test'], []):
conf.env.HAVE_FRANDOM_SEED = True
def check_header(hdr):
return {'header_name':hdr, 'msg':'... %s header' % hdr, 'mandatory':False, 'id':hdr}
conf.multicheck(
check_header('dlfcn.h'),
check_header('inttypes.h'),
check_header('link.h'),
check_header('sys/link.h'),
check_header('mach-o/dyld.h'),
check_header('memory.h'),
check_header('stdint.h'),
check_header('stdlib.h'),
check_header('strings.h'),
check_header('string.h'),
check_header('sys/ldr.h'),
check_header('sys/mman.h'),
check_header('sys/stat.h'),
check_header('sys/types.h'),
check_header('tlhelp32.h'),
check_header('unistd.h'),
check_header('windows.h'),
{'fragment':FRAGMENT_ATOMIC, 'msg':'... __atomic extensions', 'define_name':'HAVE_ATOMIC_FUNCTIONS', 'mandatory':False},
{'fragment':FRAGMENT_SYNC, 'msg':'... __sync extensions', 'define_name':'HAVE_SYNC_FUNCTIONS', 'mandatory':False},
{'fragment':FRAGMENT_GETPAGESIZE, 'msg':'... getpagesize function', 'define_name':'HAVE_DECL_GETPAGESIZE', 'mandatory':False},
{'fragment':FRAGMENT_STRNLEN, 'msg':'... strnlen function', 'define_name':'HAVE_DECL_STRNLEN', 'mandatory':False},
{'fragment':FRAGMENT_DL_ITERATE_PHDR % 'link.h', 'msg':'... dl_iterate_phdr function in link.h', 'define_name':'HAVE_DL_ITERATE_PHDR', 'after_tests': ['link.h'], 'mandatory':False},
{'fragment':FRAGMENT_DL_ITERATE_PHDR % 'sys/link.h', 'msg':'... dl_iterate_phdr function in sys/link.h', 'define_name':'HAVE_DL_ITERATE_PHDR', 'after_tests': ['sys/link.h'], 'mandatory':False},
{'fragment':FRAGMENT_FCNTL,'msg':'... fnctl function', 'define_name':'HAVE_FCNTL', 'mandatory':False},
{'fragment':FRAGMENT_GETEXECNAME,'msg':'... getexecname function','define_name':'HAVE_GETEXECNAME', 'mandatory':False},
{'fragment':FRAGMENT_GETIPINFO, 'msg':'... _Unwind_GetIPInfo function', 'define_name':'HAVE_GETIPINFO', 'mandatory':False},
{'fragment':FRAGMENT_KERN_PROC % 'KERN_PROC', 'msg': '... KERN_PROC and KERN_PROC_PATHNAME defines', 'define_name':'HAVE_KERN_PROC', 'mandatory':False},
{'fragment':FRAGMENT_KERN_PROC % 'KERN_PROC_ARGS', 'msg': '... KERN_PROC_ARGS and KERN_PROC_PATHNAME defines', 'define_name':'HAVE_KERN_PROC_ARGS', 'mandatory':False},
{'fragment':FRAGMENT_LOADQUERY, 'msg': '... loadquery function', 'define_name':'HAVE_LOADQUERY', 'mandatory':False},
{'fragment':FRAGMENT_LSTAT, 'msg': '... lstat function', 'define_name':'HAVE_LSTAT', 'mandatory':False},
{'fragment':FRAGMENT_READLINK, 'msg': '... readlink function', 'define_name':'HAVE_READLINK', 'mandatory':False},
# {'lib':'lzma', 'define_name':'HAVE_LIBLZMA', 'uselib_store':'lzma', 'msg':'... lzma library', 'mandatory':False},
# {'lib':'z', 'define_name':'HAVE_ZLIB', 'uselib_store':'z', 'msg':'... zlib library', 'mandatory':False},
# {'lib':'zstd', 'define_name':'HAVE_ZSTD', 'uselib_store':'zstd', 'msg':'... zstd library', 'mandatory':False},
msg='Checking for in parallel'
)
conf.write_config_header()
conf.define('BACKTRACE_SUPPORTED', 1)
conf.define('BACKTRACE_USES_MALLOC', 0)
conf.define('BACKTRACE_SUPPORTS_THREADS', 1)
conf.define('BACKTRACE_SUPPORTS_DATA', conf.env.DEST_BINFMT in ['elf', 'mac-o'])
conf.write_config_header('backtrace-supported.h')
@TaskGen.feature('frandomseed')
@TaskGen.after_method('propagate_uselib_vars')
def process_frandom_seed(ctx):
tasks = getattr(ctx, 'compiled_tasks', [])
for task in tasks:
out = task.outputs[0]
task.env.CFLAGS = list(task.env.CFLAGS) # need a copy
task.env.CFLAGS += ['-frandom-seed=%s' % out.path_from(out.ctx.bldnode)]
def build(bld):
if bld.env.DISABLE_LIBBACKTRACE:
return
# we specifically only want mmap-based allocators because calling malloc is not safe from signal handlers
sources = ['atomic.c', 'dwarf.c', 'fileline.c', 'posix.c', 'print.c', 'sort.c', 'state.c', 'backtrace.c', 'simple.c', 'mmap.c', 'mmapio.c']
if bld.env.DEST_BINFMT == 'pe':
sources += ['pecoff.c']
elif bld.env.DEST_BINFMT == 'mac-o':
sources += ['macho.c']
elif bld.env.DEST_BINFMT == 'elf':
sources += ['elf.c']
else:
sources += ['unknown.c']
task = bld.stlib(
source = ['libbacktrace/' + i for i in sources],
target = 'backtrace',
features = 'frandomseed' if bld.env.HAVE_FRANDOM_SEED else '',
use = 'EXTRAFLAGS lzma z zstd',
includes = '. libbacktrace/',
export_defines = 'HAVE_LIBBACKTRACE=1',
export_includes = 'libbacktrace/'
)
@@ -5,10 +5,5 @@ This can be useful to test engine in Wine without using virtual machines or dual
0. Clone and install https://github.com/mstorsjo/msvc-wine (you can skip CMake part) 0. Clone and install https://github.com/mstorsjo/msvc-wine (you can skip CMake part)
1. Set environment variable MSVC_WINE_PATH to the path to installed MSVC toolchain 1. Set environment variable MSVC_WINE_PATH to the path to installed MSVC toolchain
2. Pre-load wine: `wineserver -k; wineserver -p; wine64 wineboot` 2. Pre-load wine: `wineserver -k; wineserver -p; wine64 wineboot`
3. Run `PKGCONFIG=/bin/false ./waf configure -T <build-type> --enable-wine-msvc --sdl2=../SDL2_VC`. Configuration step will take more time than usual. 3. Run `./waf configure -T <build-type> --enable-wine-msvc --sdl2=../SDL2_VC`. Configuration step will take more time than usual.
4. .. other typical steps to build from console ... 4. .. other typical steps to build from console ...
> [!NOTE]
> Notice the usage of PKGCONFIG=/bin/false here. We're disabling pkg-config so we don't accidentally pull
> system-wide dependencies and force building them from source. In future builds we might set custom
> directory to pull dependencies from, like ffmpeg...
-3
View File
@@ -85,9 +85,6 @@ These strings are specific to Xash3D FWGS.
As Xash3D accidentally supports GoldSrc games, it also supports parsing liblist.gam.\ As Xash3D accidentally supports GoldSrc games, it also supports parsing liblist.gam.\
Xash3D will use this file if gameinfo.txt is absent, or if its modification timestamp is older than liblist.gam. Xash3D will use this file if gameinfo.txt is absent, or if its modification timestamp is older than liblist.gam.
> [!NOTE]
> Starting from January 2025, Xash3D FWGS doesn't automatically generate gameinfo.txt from liblist.gam. The key conversion table still remains but if you wish to use gameinfo.txt instead of liblist.gam, you can execute `fs_make_gameinfo` in console.
For game creators who plan supporting only Xash3D, using this file is not recommended. For game creators who plan supporting only Xash3D, using this file is not recommended.
The table below defines conversion rules from liblist.gam to gameinfo.txt. Some keys' interpretation does differ from `gameinfo.txt`, in this case a note will be left. If `liblist.gam` key isn't present in this table, it's ignored. The table below defines conversion rules from liblist.gam to gameinfo.txt. Some keys' interpretation does differ from `gameinfo.txt`, in this case a note will be left. If `liblist.gam` key isn't present in this table, it's ignored.
+1 -1
View File
@@ -6,7 +6,7 @@ For connecting to GoldSrc-based servers, use this command:
connect ip:port gs 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. 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). That is because proper authorization with Steam API is not implemented in engine yet (but we have plans on it).
-6
View File
@@ -38,12 +38,6 @@ Uploaded to github by Oleg Cherkasky - https://github.com/gunrunners-paradise/Ct
## Deathmatch Classic ## Deathmatch Classic
Available in Valve's Half-Life repository - https://github.com/ValveSoftware/halflife/tree/master/dmc 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
## ESHQ ## ESHQ
Official github repository - https://github.com/adslbarxatov/xash3d-for-ESHQ Official github repository - https://github.com/adslbarxatov/xash3d-for-ESHQ
File diff suppressed because it is too large Load Diff
+7 -8
View File
@@ -1,9 +1,8 @@
# 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" /> # 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" />
[![GitHub Actions Status](https://github.com/FWGS/xash3d-fwgs/actions/workflows/c-cpp.yml/badge.svg)](https://github.com/FWGS/xash3d-fwgs/actions/workflows/c-cpp.yml) [![FreeBSD Build Status](https://img.shields.io/cirrus/github/FWGS/xash3d-fwgs?label=freebsd%20build)](https://cirrus-ci.com/github/FWGS/xash3d-fwgs) \ [![builds.sr.ht status](https://builds.sr.ht/~a1batross/xash3d-fwgs.svg)](https://builds.sr.ht/~a1batross/xash3d-fwgs?) [![GitHub Actions Status](https://github.com/FWGS/xash3d-fwgs/actions/workflows/c-cpp.yml/badge.svg)](https://github.com/FWGS/xash3d-fwgs/actions/workflows/c-cpp.yml) [![FreeBSD Build Status](https://img.shields.io/cirrus/github/FWGS/xash3d-fwgs?label=freebsd%20build)](https://cirrus-ci.com/github/FWGS/xash3d-fwgs) [![Discord Server](https://img.shields.io/discord/355697768582610945.svg)](http://fwgsdiscord.mentality.rip/) \
[![Discord Server](https://img.shields.io/discord/355697768582610945?logo=Discord&label=International%20Discord%20chat)](http://fwgsdiscord.mentality.rip/) [![Russian speakers Telegram Chat](https://img.shields.io/badge/Russian_speakers_Telegram_chat-gray?logo=Telegram)](https://t.me/flyingwithgauss) \ [![Download Stable](https://img.shields.io/badge/download-stable-yellow)](https://github.com/FWGS/xash3d-fwgs/releases/latest) [![Download Testing](https://img.shields.io/badge/downloads-testing-orange)](https://github.com/FWGS/xash3d-fwgs/releases/tag/continuous)
[![Download Daily Build](https://img.shields.io/badge/downloads-testing-orange)](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. Xash3D (pronounced `[ksɑʂ]`) FWGS is a game engine, aimed to provide compatibility with Half-Life Engine and extend it, as well as to give game developers well known workflow.
Xash3D FWGS is a heavily modified fork of an original [Xash3D Engine](https://www.moddb.com/engines/xash3d-engine) by Unkle Mike. Xash3D FWGS is a heavily modified fork of an original [Xash3D Engine](https://www.moddb.com/engines/xash3d-engine) by Unkle Mike.
@@ -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: * Only for 32-bit engine on 64-bit x86 operating system:
* Enable i386 on your system: `$ sudo dpkg --add-architecture i386`. * 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 `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`. * 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`. * 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: * 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`. * 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`. * Clone this repostory: `$ git clone --recursive https://github.com/FWGS/xash3d-fwgs`.
##### RedHat/Fedora ##### RedHat/Fedora
* Only for 32-bit engine on 64-bit x86 operating system: * 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`. * 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`. * 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: * 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`. * 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`. * Clone this repostory: `$ git clone --recursive https://github.com/FWGS/xash3d-fwgs`.
+24 -59
View File
@@ -5,13 +5,13 @@ cmake_minimum_required(VERSION 3.6)
project(XASH_ANDROID) project(XASH_ANDROID)
# armeabi-v7a requires cpufeatures library # armeabi-v7a requires cpufeatures library
if(ANDROID) include(AndroidNdkModules)
include_directories(${ANDROID_NDK}/sources/android/cpufeatures) android_ndk_import_module_cpufeatures()
add_library(cpufeatures ${ANDROID_NDK}/sources/android/cpufeatures/cpu-features.c)
target_link_libraries(cpufeatures dl)
endif()
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") if("${CMAKE_BUILD_TYPE}" STREQUAL "Debug")
set(BUILD_TYPE "debug") set(BUILD_TYPE "debug")
@@ -20,20 +20,30 @@ else()
list(APPEND WAF_EXTRA_ARGS --enable-poly-opt --enable-lto) list(APPEND WAF_EXTRA_ARGS --enable-poly-opt --enable-lto)
endif() endif()
if(ANDROID_ABI STREQUAL "x86") if(CMAKE_SIZEOF_VOID_P MATCHES "8")
# HACKHACK: I don't know why but engine gets built as 64-bit binary here set(64BIT ON CACHE BOOL "" FORCE)
list(APPEND WAF_EXTRA_ARGS -4) list(APPEND WAF_EXTRA_ARGS -8) # only required for x86 when testing this cmakelist under linux
endif() endif()
set(CMAKE_VERBOSE_MAKEFILE ON) 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 # not cleanest way to get upper directory
set(ENGINE_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../") set(ENGINE_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../")
set(WAF_CC "${CMAKE_C_COMPILER} --target=${CMAKE_C_COMPILER_TARGET}") execute_process(
set(WAF_CXX "${CMAKE_CXX_COMPILER} --target=${CMAKE_CXX_COMPILER_TARGET}") COMMAND ${CMAKE_COMMAND} -E env
set(WAF ${Python_EXECUTABLE} ${ENGINE_SOURCE_DIR}waf -t ${ENGINE_SOURCE_DIR} -o ${CMAKE_CURRENT_BINARY_DIR}/xash3d-fwgs) 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}/3rdparty/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 # try to build minimal SDL. Enable features as we're gonna use them
set(SDL_RENDER OFF) set(SDL_RENDER OFF)
@@ -46,50 +56,5 @@ set(SDL_VULKAN OFF)
set(SDL_OFFSCREEN OFF) set(SDL_OFFSCREEN OFF)
set(SDL_STATIC OFF) set(SDL_STATIC OFF)
add_subdirectory("${ENGINE_SOURCE_DIR}/3rdparty/SDL" SDL) add_subdirectory("${ENGINE_SOURCE_DIR}/3rdparty/SDL" SDL)
add_subdirectory("${ENGINE_SOURCE_DIR}/" xash3d-fwgs)
include(ExternalProject) add_subdirectory("${ENGINE_SOURCE_DIR}/3rdparty/mainui" mainui)
# 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
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)
+2 -3
View File
@@ -9,7 +9,7 @@ plugins {
android { android {
namespace = "su.xash.engine" namespace = "su.xash.engine"
ndkVersion = "28.0.13004108" ndkVersion = "27.2.12479018"
defaultConfig { defaultConfig {
applicationId = "su.xash" applicationId = "su.xash"
@@ -96,7 +96,6 @@ android {
packaging { packaging {
jniLibs { jniLibs {
useLegacyPackaging = true useLegacyPackaging = true
keepDebugSymbols.add("**/*.so")
} }
} }
} }
@@ -113,7 +112,7 @@ dependencies {
implementation("androidx.preference:preference-ktx:1.2.1") implementation("androidx.preference:preference-ktx:1.2.1")
implementation("androidx.swiperefreshlayout:swiperefreshlayout:1.1.0") implementation("androidx.swiperefreshlayout:swiperefreshlayout:1.1.0")
implementation("androidx.work:work-runtime-ktx:2.9.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("com.madgag.spongycastle:prov:1.58.0.0")
implementation("in.dragonbra:javasteam:1.2.0") implementation("in.dragonbra:javasteam:1.2.0")
@@ -30,18 +30,6 @@ public class XashActivity extends SDLActivity {
AndroidBug5497Workaround.assistActivity(this); AndroidBug5497Workaround.assistActivity(this);
} }
@Override
public void onDestroy()
{
super.onDestroy();
// Now that we don't exit from native code, we need to exit here, resetting
// application state (actually global variables that we don't cleanup on exit)
//
// When the issue with global variables will be resolved, remove that exit() call
System.exit(0);
}
@Override @Override
protected String[] getLibraries() { protected String[] getLibraries() {
return new String[]{"SDL2", "xash"}; return new String[]{"SDL2", "xash"};
+1 -4
View File
@@ -20,7 +20,4 @@ kotlin.code.style=official
# Enables namespacing of each library's R class so that its R class includes only the # 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, # resources declared in the library itself and none from the library's dependencies,
# thereby reducing the size of the R class for that library # thereby reducing the size of the R class for that library
android.nonTransitiveRClass=true android.nonTransitiveRClass=true
# Enable verbose output for CMake
android.native.buildOutput=verbose
+15
View File
@@ -16,6 +16,8 @@ GNU General Public License for more details.
#ifndef BSPFILE_H #ifndef BSPFILE_H
#define BSPFILE_H #define BSPFILE_H
//#define SUPPORT_BSP2_FORMAT // allow to loading Darkplaces BSP2 maps (with broke binary compatibility)
/* /*
============================================================================== ==============================================================================
@@ -63,6 +65,7 @@ BRUSH MODELS
#define MAX_MAP_CLIPNODES_BSP2 524288 #define MAX_MAP_CLIPNODES_BSP2 524288
// these limis not using by modelloader but only for displaying 'mapstats' correctly // these limis not using by modelloader but only for displaying 'mapstats' correctly
#ifdef SUPPORT_BSP2_FORMAT
#define MAX_MAP_MODELS 2048 // embedded models #define MAX_MAP_MODELS 2048 // embedded models
#define MAX_MAP_ENTSTRING 0x200000 // 2 Mb should be enough #define MAX_MAP_ENTSTRING 0x200000 // 2 Mb should be enough
#define MAX_MAP_PLANES 131072 // can be increased without problems #define MAX_MAP_PLANES 131072 // can be increased without problems
@@ -72,6 +75,18 @@ BRUSH MODELS
#define MAX_MAP_VERTS 524288 // can be increased without problems #define MAX_MAP_VERTS 524288 // can be increased without problems
#define MAX_MAP_FACES 262144 // can be increased without problems #define MAX_MAP_FACES 262144 // can be increased without problems
#define MAX_MAP_MARKSURFACES 524288 // can be increased without problems #define MAX_MAP_MARKSURFACES 524288 // can be increased without problems
#else
// increased to match PrimeXT compilers
#define MAX_MAP_MODELS 1024 // embedded models
#define MAX_MAP_ENTSTRING 0x100000 // 1 Mb should be enough
#define MAX_MAP_PLANES 65536 // can be increased without problems
#define MAX_MAP_NODES 32767 // because negative shorts are leafs
#define MAX_MAP_CLIPNODES MAX_MAP_CLIPNODES_HLBSP // because negative shorts are contents
#define MAX_MAP_LEAFS 32767 // signed short limit
#define MAX_MAP_VERTS 65535 // unsigned short limit
#define MAX_MAP_FACES 65535 // unsigned short limit
#define MAX_MAP_MARKSURFACES 65535 // unsigned short limit
#endif
#define MAX_MAP_ENTITIES 8192 // network limit #define MAX_MAP_ENTITIES 8192 // network limit
#define MAX_MAP_TEXINFO MAX_MAP_FACES // in theory each face may have personal texinfo #define MAX_MAP_TEXINFO MAX_MAP_FACES // in theory each face may have personal texinfo
+25 -110
View File
@@ -60,29 +60,26 @@ typedef struct
vec3_t position; vec3_t position;
} mvertex_t; } mvertex_t;
typedef struct mclipnode32_s typedef struct
{ {
int planenum; int planenum;
int children[2]; // negative numbers are contents #ifdef SUPPORT_BSP2_FORMAT
} mclipnode32_t; int children[2]; // negative numbers are contents
#else
typedef struct mclipnode16_s short children[2]; // negative numbers are contents
{ #endif
int planenum; } mclipnode_t;
short children[2]; // negative numbers are contents
} mclipnode16_t;
// size is matched but representation is not // size is matched but representation is not
typedef struct medge32_s typedef struct
{ {
#ifdef SUPPORT_BSP2_FORMAT
unsigned int v[2]; unsigned int v[2];
} medge32_t; #else
typedef struct medge16_s
{
unsigned short v[2]; unsigned short v[2];
unsigned int cachededgeoffset; unsigned int cachededgeoffset;
} medge16_t; #endif
} medge_t;
typedef struct texture_s typedef struct texture_s
{ {
@@ -159,31 +156,13 @@ typedef struct mnode_s
// node specific // node specific
mplane_t *plane; mplane_t *plane;
struct mnode_s *children[2];
#if !XASH_64BIT #ifdef SUPPORT_BSP2_FORMAT
union int firstsurface;
{ int numsurfaces;
struct mnode_s *children_[2];
struct
{
// the ordering is important
int child_0_leaf : 1;
int child_0_off : 23;
int firstsurface_1 : 8;
int child_1_leaf : 1;
int child_1_off : 23;
int numsurfaces_1 : 8;
};
};
unsigned short firstsurface_0;
unsigned short numsurfaces_0;
#else #else
// in 64-bit ABI this struct has 4 more bytes of padding, let's use it! unsigned short firstsurface;
struct mnode_s *children_[2]; unsigned short numsurfaces;
unsigned short firstsurface_0;
unsigned short numsurfaces_0;
unsigned short firstsurface_1;
unsigned short numsurfaces_1;
#endif #endif
} mnode_t; } mnode_t;
@@ -224,6 +203,7 @@ typedef struct mleaf_s
int nummarksurfaces; int nummarksurfaces;
int cluster; // helper to acess to uncompressed visdata int cluster; // helper to acess to uncompressed visdata
byte ambient_sound_level[NUM_AMBIENTS]; byte ambient_sound_level[NUM_AMBIENTS];
} mleaf_t; } mleaf_t;
// surface extradata // surface extradata
@@ -311,11 +291,7 @@ struct msurface_s
typedef struct hull_s typedef struct hull_s
{ {
union mclipnode_t *clipnodes;
{
mclipnode16_t *clipnodes16;
mclipnode32_t *clipnodes32;
};
mplane_t *planes; mplane_t *planes;
int firstclipnode; int firstclipnode;
int lastclipnode; int lastclipnode;
@@ -365,12 +341,7 @@ typedef struct model_s
mvertex_t *vertexes; mvertex_t *vertexes;
int numedges; int numedges;
union medge_t *edges;
{
medge16_t *edges16;
medge32_t *edges32;
};
int numnodes; int numnodes;
mnode_t *nodes; mnode_t *nodes;
@@ -385,11 +356,7 @@ typedef struct model_s
int *surfedges; int *surfedges;
int numclipnodes; int numclipnodes;
union mclipnode_t *clipnodes;
{
mclipnode16_t *clipnodes16;
mclipnode32_t *clipnodes32;
};
int nummarksurfaces; int nummarksurfaces;
msurface_t **marksurfaces; msurface_t **marksurfaces;
@@ -583,68 +550,16 @@ typedef struct
#define ANIM_CYCLE 2 #define ANIM_CYCLE 2
#define MOD_FRAMES 20 #define MOD_FRAMES 20
#define MAX_DEMOS 32 #define MAX_DEMOS 32
#define MAX_MOVIES 8 #define MAX_MOVIES 8
#define MAX_CDTRACKS 32 #define MAX_CDTRACKS 32
#define MAX_CLIENT_SPRITES 512 // SpriteTextures (0-256 hud, 256-512 client) #define MAX_CLIENT_SPRITES 512 // SpriteTextures (0-256 hud, 256-512 client)
#define MAX_REQUESTS 64 #define MAX_REQUESTS 64
STATIC_CHECK_SIZEOF( mnode_t, 52, 72 );
STATIC_CHECK_SIZEOF( mextrasurf_t, 324, 496 ); STATIC_CHECK_SIZEOF( mextrasurf_t, 324, 496 );
STATIC_CHECK_SIZEOF( decal_t, 60, 88 ); STATIC_CHECK_SIZEOF( decal_t, 60, 88 );
STATIC_CHECK_SIZEOF( mfaceinfo_t, 176, 304 ); STATIC_CHECK_SIZEOF( mfaceinfo_t, 176, 304 );
// model flags (stored in model_t->flags)
#define MODEL_QBSP2 BIT( 28 ) // uses 32-bit types
// access functions
static inline mnode_t *node_child( const mnode_t *n, int side, const model_t *mod )
{
#if !XASH_64BIT
if( unlikely( mod->flags & MODEL_QBSP2 )) // MODEL_QBSP2
{
if( side == 0 )
{
if( n->child_0_leaf )
return (mnode_t *)(mod->leafs + n->child_0_off);
else
return (mnode_t *)(mod->nodes + n->child_0_off);
}
else
{
if( n->child_1_leaf )
return (mnode_t *)(mod->leafs + n->child_1_off);
else
return (mnode_t *)(mod->nodes + n->child_1_off);
}
}
return n->children_[side];
#else
return n->children_[side];
#endif
}
static inline void node_children( mnode_t *children[2], const mnode_t *n, const model_t *mod )
{
children[0] = node_child( n, 0, mod );
children[1] = node_child( n, 1, mod );
}
static inline int node_firstsurface( const mnode_t *n, const model_t *mod )
{
if( mod->flags & MODEL_QBSP2 )
return n->firstsurface_0 + ( n->firstsurface_1 << 16 );
else
return n->firstsurface_0;
}
static inline int node_numsurfaces( const mnode_t *n, const model_t *mod )
{
if( mod->flags & MODEL_QBSP2 )
return n->numsurfaces_0 + ( n->numsurfaces_1 << 16 );
else
return n->numsurfaces_0;
}
#endif//COM_MODEL_H #endif//COM_MODEL_H
+10 -51
View File
@@ -28,17 +28,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#define PORT_ANY -1 #define PORT_ANY -1
typedef enum netadrtype_e typedef enum {NA_LOOPBACK = 1, NA_BROADCAST, NA_IP, NA_IPX, NA_BROADCAST_IPX, NA_IP6, NA_MULTICAST_IP6} netadrtype_t;
{
NA_UNDEFINED = 0,
NA_LOOPBACK,
NA_BROADCAST,
NA_IP,
NA_IPX,
NA_BROADCAST_IPX,
NA_IP6,
NA_MULTICAST_IP6
} netadrtype_t;
/* /*
Original Quake-2 structure: Original Quake-2 structure:
@@ -56,60 +46,29 @@ typedef struct
#pragma pack( push, 1 ) #pragma pack( push, 1 )
typedef struct netadr_s 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 union
{ {
// IPv6 struct // IPv6 struct
uint8_t ip6_1[14];
struct struct
{ {
uint16_t type6;
uint8_t ip6[16];
};
struct
{
uint32_t type; // must be netadrtype_t but will break with short enums
union union
{ {
uint8_t ip[4]; uint8_t ip[4];
uint32_t ip4; // for easier conversions uint32_t ip4; // for easier conversions
}; };
uint8_t ipx[10]; uint8_t ipx[10];
}; };
}; };
uint16_t port; uint16_t port;
} netadr_t; } netadr_t;
#pragma pack( pop ) #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 ); STATIC_CHECK_SIZEOF( netadr_t, 20, 20 );
#endif // NET_ADR_H #endif // NET_ADR_H
+53 -34
View File
@@ -13,44 +13,47 @@
#endif // _WIN32 #endif // _WIN32
#include <sys/types.h> // off_t #include <sys/types.h> // off_t
#ifdef STDINT_H
#include STDINT_H #include STDINT_H
#else // !STDINT_H
#include <stdint.h>
#endif // !STDINT_H
#include <assert.h> #include <assert.h>
typedef uint8_t byte; typedef unsigned char byte;
typedef float vec_t; typedef int sound_t;
typedef vec_t vec2_t[2]; typedef float vec_t;
#ifndef vec3_t // SDK renames it to Vector typedef vec_t vec2_t[2];
typedef vec_t vec3_t[3]; typedef vec_t vec3_t[3];
#endif typedef vec_t vec4_t[4];
typedef vec_t vec4_t[4]; typedef vec_t quat_t[4];
typedef vec_t quat_t[4]; typedef byte rgba_t[4]; // unsigned byte colorpack
typedef byte rgba_t[4]; // unsigned byte colorpack typedef byte rgb_t[3]; // unsigned byte colorpack
typedef byte rgb_t[3]; // unsigned byte colorpack typedef vec_t matrix3x4[3][4];
typedef vec_t matrix3x4[3][4]; typedef vec_t matrix4x4[4][4];
typedef vec_t matrix4x4[4][4];
typedef uint32_t poolhandle_t; typedef uint32_t poolhandle_t;
#undef true #undef true
#undef false #undef false
// true and false are keywords in C++ and C23 #ifndef __cplusplus
#if !__cplusplus && __STDC_VERSION__ < 202311L typedef enum { false, true } qboolean;
enum { false, true }; #else
#endif
typedef int qboolean; typedef int qboolean;
#endif
#define MAX_STRING 256 // generic string typedef uint64_t longtime_t;
#define MAX_VA_STRING 1024 // compatibility macro
#define MAX_SYSPATH 1024 // system filepath #define MAX_STRING 256 // generic string
#define MAX_MODS 512 // environment games that engine can keep visible #define MAX_INFO_STRING 256 // infostrings are transmitted across network
#define MAX_SERVERINFO_STRING 512 // server handles too many settings. expand to 1024?
#define MAX_LOCALINFO_STRING 32768 // localinfo used on server and not sended to the clients
#define MAX_SYSPATH 1024 // system filepath
#define MAX_VA_STRING 1024 // string length returned by va()
#define MAX_PRINT_MSG 8192 // how many symbols can handle single call of Con_Printf or Con_DPrintf
#define MAX_TOKEN 2048 // parse token length
#define MAX_MODS 512 // environment games that engine can keep visible
#define MAX_USERMSG_LENGTH 2048 // don't modify it's relies on a client-side definitions
#define BIT( n ) ( 1U << ( n )) #define BIT( n ) ( 1U << ( n ))
#define BIT64( n ) ( 1ULL << ( n )) #define BIT64( n ) ( 1ULL << ( n ))
#define SetBits( iBitVector, bits ) ((iBitVector) = (iBitVector) | (bits)) #define SetBits( iBitVector, bits ) ((iBitVector) = (iBitVector) | (bits))
#define ClearBits( iBitVector, bits ) ((iBitVector) = (iBitVector) & ~(bits)) #define ClearBits( iBitVector, bits ) ((iBitVector) = (iBitVector) & ~(bits))
#define FBitSet( iBitVector, bit ) ((iBitVector) & (bit)) #define FBitSet( iBitVector, bit ) ((iBitVector) & (bit))
@@ -67,8 +70,6 @@ typedef int qboolean;
#define IsColorString( p ) ( p && *( p ) == '^' && *(( p ) + 1) && *(( p ) + 1) >= '0' && *(( p ) + 1 ) <= '9' ) #define IsColorString( p ) ( p && *( p ) == '^' && *(( p ) + 1) && *(( p ) + 1) >= '0' && *(( p ) + 1 ) <= '9' )
#define ColorIndex( c ) ((( c ) - '0' ) & 7 ) #define ColorIndex( c ) ((( c ) - '0' ) & 7 )
#undef EXPORT
#if defined( __GNUC__ ) #if defined( __GNUC__ )
#if defined( __i386__ ) #if defined( __i386__ )
#define EXPORT __attribute__(( visibility( "default" ), force_align_arg_pointer )) #define EXPORT __attribute__(( visibility( "default" ), force_align_arg_pointer ))
@@ -208,16 +209,34 @@ _inline float LittleFloat( float f )
#endif #endif
typedef unsigned int dword; typedef unsigned int dword;
typedef unsigned int uint; typedef unsigned int uint;
typedef char string[MAX_STRING]; typedef unsigned long ulong;
typedef off_t fs_offset_t; typedef char string[MAX_STRING];
typedef struct file_s file_t; // normal file
typedef struct stream_s stream_t; // sound stream for background music playing
typedef off_t fs_offset_t;
#if XASH_WIN32 #if XASH_WIN32
typedef int fs_size_t; // return type of _read, _write funcs typedef int fs_size_t; // return type of _read, _write funcs
#else /* !XASH_WIN32 */ #else /* !XASH_WIN32 */
typedef ssize_t fs_size_t; typedef ssize_t fs_size_t;
#endif /* !XASH_WIN32 */ #endif /* !XASH_WIN32 */
typedef struct dllfunc_s
{
const char *name;
void **func;
} dllfunc_t;
typedef struct dll_info_s
{
const char *name; // name of library
const dllfunc_t *fcts; // list of dll exports
qboolean crash; // crash if dll not found
void *link; // hinstance of loading library
} dll_info_t;
typedef void (*setpair_t)( const char *key, const void *value, const void *buffer, void *numpairs );
typedef void *(*pfnCreateInterface_t)( const char *, int * ); typedef void *(*pfnCreateInterface_t)( const char *, int * );
// config strings are a general means of communication from // config strings are a general means of communication from
+6 -3
View File
@@ -30,9 +30,10 @@ static dllfunc_t msvfw_funcs[] =
{ "DrawDibOpen", (void **) &pDrawDibOpen }, { "DrawDibOpen", (void **) &pDrawDibOpen },
{ "DrawDibDraw", (void **) &pDrawDibDraw }, { "DrawDibDraw", (void **) &pDrawDibDraw },
{ "DrawDibClose", (void **) &pDrawDibClose }, { "DrawDibClose", (void **) &pDrawDibClose },
{ NULL, NULL }
}; };
dll_info_t msvfw_dll = { "msvfw32.dll", msvfw_funcs, ARRAYSIZE( msvfw_funcs ), false }; dll_info_t msvfw_dll = { "msvfw32.dll", msvfw_funcs, false };
// msacm32.dll exports // msacm32.dll exports
static MMRESULT (_stdcall *pacmStreamOpen)( LPHACMSTREAM, HACMDRIVER, LPWAVEFORMATEX, LPWAVEFORMATEX, LPWAVEFILTER, DWORD, DWORD, DWORD ); static MMRESULT (_stdcall *pacmStreamOpen)( LPHACMSTREAM, HACMDRIVER, LPWAVEFORMATEX, LPWAVEFORMATEX, LPWAVEFILTER, DWORD, DWORD, DWORD );
@@ -50,9 +51,10 @@ static dllfunc_t msacm_funcs[] =
{ "acmStreamConvert", (void **) &pacmStreamConvert }, { "acmStreamConvert", (void **) &pacmStreamConvert },
{ "acmStreamSize", (void **) &pacmStreamSize }, { "acmStreamSize", (void **) &pacmStreamSize },
{ "acmStreamClose", (void **) &pacmStreamClose }, { "acmStreamClose", (void **) &pacmStreamClose },
{ NULL, NULL }
}; };
dll_info_t msacm_dll = { "msacm32.dll", msacm_funcs, ARRAYSIZE( msacm_funcs ), false }; dll_info_t msacm_dll = { "msacm32.dll", msacm_funcs, false };
// avifil32.dll exports // avifil32.dll exports
static int (_stdcall *pAVIStreamInfo)( PAVISTREAM pavi, AVISTREAMINFO *psi, LONG lSize ); static int (_stdcall *pAVIStreamInfo)( PAVISTREAM pavi, AVISTREAMINFO *psi, LONG lSize );
@@ -86,9 +88,10 @@ static dllfunc_t avifile_funcs[] =
{ "AVIStreamRelease", (void **) &pAVIStreamRelease }, { "AVIStreamRelease", (void **) &pAVIStreamRelease },
{ "AVIStreamStart", (void **) &pAVIStreamStart }, { "AVIStreamStart", (void **) &pAVIStreamStart },
{ "AVIStreamTimeToSample", (void **) &pAVIStreamTimeToSample }, { "AVIStreamTimeToSample", (void **) &pAVIStreamTimeToSample },
{ NULL, NULL }
}; };
dll_info_t avifile_dll = { "avifil32.dll", avifile_funcs, ARRAYSIZE( avifile_funcs ), false }; dll_info_t avifile_dll = { "avifil32.dll", avifile_funcs, false };
typedef struct movie_state_s typedef struct movie_state_s
{ {
+5 -46
View File
@@ -153,7 +153,6 @@ static void CL_WriteErrorMessage( int current_count, sizebuf_t *msg )
FS_Write( fp, &cls.starting_count, sizeof( int )); FS_Write( fp, &cls.starting_count, sizeof( int ));
FS_Write( fp, &current_count, sizeof( int )); FS_Write( fp, &current_count, sizeof( int ));
FS_Write( fp, &cls.legacymode, sizeof( cls.legacymode ));
FS_Write( fp, MSG_GetData( msg ), MSG_GetMaxBytes( msg )); FS_Write( fp, MSG_GetData( msg ), MSG_GetMaxBytes( msg ));
FS_Close( fp ); FS_Close( fp );
@@ -169,7 +168,7 @@ list last 32 messages for debugging net troubleshooting
*/ */
void CL_WriteMessageHistory( void ) void CL_WriteMessageHistory( void )
{ {
oldcmd_t *old; oldcmd_t *old, *failcommand;
sizebuf_t *msg = &net_message; sizebuf_t *msg = &net_message;
int i, thecmd; int i, thecmd;
@@ -193,49 +192,9 @@ void CL_WriteMessageHistory( void )
thecmd++; thecmd++;
} }
old = &cls_message_debug.oldcmd[thecmd]; failcommand = &cls_message_debug.oldcmd[thecmd];
Con_Printf( S_RED "BAD: " S_DEFAULT "%i %04i %s\n", old->frame_number, old->starting_offset, CL_MsgInfo( old->command )); Con_Printf( "BAD: %3i:%s\n", MSG_GetNumBytesRead( msg ) - 1, CL_MsgInfo( failcommand->command ));
CL_WriteErrorMessage( old->starting_offset, msg ); if( host_developer.value >= DEV_EXTENDED )
CL_WriteErrorMessage( MSG_GetNumBytesRead( msg ) - 1, msg );
cls_message_debug.parsing = false; cls_message_debug.parsing = false;
} }
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, &current_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__ );
}
+5 -4
View File
@@ -157,7 +157,7 @@ void CL_StartupDemoHeader( void )
{ {
CL_CloseDemoHeader(); CL_CloseDemoHeader();
cls.demoheader = FS_Open( "demoheader.tmp", "w+bm", true ); cls.demoheader = FS_Open( "demoheader.tmp", "w+b", true );
if( !cls.demoheader ) if( !cls.demoheader )
{ {
@@ -373,7 +373,7 @@ CL_WriteDemoUserMessage
Dumps the user message (demoaction) Dumps the user message (demoaction)
==================== ====================
*/ */
void GAME_EXPORT CL_WriteDemoUserMessage( int size, byte *buffer ) void CL_WriteDemoUserMessage( const byte *buffer, size_t size )
{ {
if( !cls.demorecording || cls.demowaiting ) if( !cls.demorecording || cls.demowaiting )
return; return;
@@ -624,10 +624,11 @@ static void CL_ReadDemoUserCmd( qboolean discard )
if( !discard ) if( !discard )
{ {
const usercmd_t nullcmd = { 0 }; usercmd_t nullcmd;
sizebuf_t buf; sizebuf_t buf;
demoangle_t *a; demoangle_t *a;
memset( &nullcmd, 0, sizeof( nullcmd ));
MSG_Init( &buf, "UserCmd", data, sizeof( data )); MSG_Init( &buf, "UserCmd", data, sizeof( data ));
// a1ba: I have no proper explanation why // a1ba: I have no proper explanation why
@@ -723,7 +724,7 @@ static void CL_DemoStartPlayback( int mode )
{ {
// NOTE: at this point demo is still valid // NOTE: at this point demo is still valid
CL_Disconnect(); CL_Disconnect();
SV_Shutdown( "Server was killed due to demo playback start\n" ); Host_ShutdownServer();
Con_FastClose(); Con_FastClose();
UI_SetActiveMenu( false ); UI_SetActiveMenu( false );
+2 -4
View File
@@ -127,10 +127,8 @@ static void R_SplitEntityOnNode( mnode_t *node )
} }
// recurse down the contacted sides // recurse down the contacted sides
if( sides & 1 ) if( sides & 1 ) R_SplitEntityOnNode( node->children[0] );
R_SplitEntityOnNode( node_child( node, 0, cl.worldmodel )); if( sides & 2 ) R_SplitEntityOnNode( node->children[1] );
if( sides & 2 )
R_SplitEntityOnNode( node_child( node, 1, cl.worldmodel ));
} }
/* /*
+1
View File
@@ -2229,3 +2229,4 @@ void CL_ThinkParticle( double frametime, particle_t *p )
break; break;
} }
} }
+3 -3
View File
@@ -173,7 +173,7 @@ static int CL_CalcTabStop( const cl_font_t *font, int x )
return stop; 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; wrect_t *rc;
float w, h; 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]; 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; rgba_t current_color;
int draw_len = 0; 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; 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; va_list va;
char buf[MAX_VA_STRING]; char buf[MAX_VA_STRING];
+164 -74
View File
@@ -76,6 +76,7 @@ static const dllfunc_t cdll_exports[] =
{ "IN_ClearStates", (void **)&clgame.dllFuncs.IN_ClearStates }, { "IN_ClearStates", (void **)&clgame.dllFuncs.IN_ClearStates },
{ "V_CalcRefdef", (void **)&clgame.dllFuncs.pfnCalcRefdef }, { "V_CalcRefdef", (void **)&clgame.dllFuncs.pfnCalcRefdef },
{ "KB_Find", (void **)&clgame.dllFuncs.KB_Find }, { "KB_Find", (void **)&clgame.dllFuncs.KB_Find },
{ NULL, NULL }
}; };
// optional exports // optional exports
@@ -90,6 +91,7 @@ static const dllfunc_t cdll_new_exports[] = // allowed only in SDK 2.3 and high
{ "IN_ClientTouchEvent", (void **)&clgame.dllFuncs.pfnTouchEvent}, // Xash3D FWGS ext { "IN_ClientTouchEvent", (void **)&clgame.dllFuncs.pfnTouchEvent}, // Xash3D FWGS ext
{ "IN_ClientMoveEvent", (void **)&clgame.dllFuncs.pfnMoveEvent}, // Xash3D FWGS ext { "IN_ClientMoveEvent", (void **)&clgame.dllFuncs.pfnMoveEvent}, // Xash3D FWGS ext
{ "IN_ClientLookEvent", (void **)&clgame.dllFuncs.pfnLookEvent}, // Xash3D FWGS ext { "IN_ClientLookEvent", (void **)&clgame.dllFuncs.pfnLookEvent}, // Xash3D FWGS ext
{ NULL, NULL }
}; };
static void pfnSPR_DrawHoles( int frame, int x, int y, const wrect_t *prc ); static void pfnSPR_DrawHoles( int frame, int x, int y, const wrect_t *prc );
@@ -306,22 +308,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 ) 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 ); if( 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 )
{ {
// align to texel if scaling if( refState.width != clgame.scrInfo.iWidth )
*s1 += 0.5f; {
*s2 -= 0.5f; // align to texel if scaling
} *s1 += 0.5f;
*s2 -= 0.5f;
}
if(( filtering || yremainder ) && refState.height != clgame.scrInfo.iHeight ) if( refState.height != clgame.scrInfo.iHeight )
{ {
// align to texel if scaling // align to texel if scaling
*t1 += 0.5f; *t1 += 0.5f;
*t2 -= 0.5f; *t2 -= 0.5f;
}
} }
*s1 /= width; *s1 /= width;
@@ -557,7 +558,7 @@ static void CL_InitTitles( const char *filename )
Q_snprintf( name, sizeof( name ), TEXT_MSGNAME, i ); Q_snprintf( name, sizeof( name ), TEXT_MSGNAME, i );
cl_textmessage[i].pName = copystringpool( clgame.mempool, name ); cl_textmessage[i].pName = _copystring( clgame.mempool, name, __FILE__, __LINE__ );
cl_textmessage[i].pMessage = cl_textbuffer[i]; cl_textmessage[i].pMessage = cl_textbuffer[i];
} }
@@ -975,7 +976,7 @@ static void CL_ClearUserMessage( char *pszName, int svc_num )
int i; int i;
for( i = 0; i < MAX_USER_MESSAGES && clgame.msg[i].name[0]; i++ ) for( i = 0; i < MAX_USER_MESSAGES && clgame.msg[i].name[0]; i++ )
if( ( clgame.msg[i].number == svc_num ) && Q_stricmp( clgame.msg[i].name, pszName ) ) if( ( clgame.msg[i].number == svc_num ) && Q_strcmp( clgame.msg[i].name, pszName ) )
clgame.msg[i].number = 0; clgame.msg[i].number = 0;
} }
@@ -1045,7 +1046,7 @@ void CL_InitEdicts( int maxclients )
cls.num_client_entities = CL_UPDATE_BACKUP * NUM_PACKET_ENTITIES; cls.num_client_entities = CL_UPDATE_BACKUP * NUM_PACKET_ENTITIES;
cls.packet_entities = Mem_Realloc( clgame.mempool, cls.packet_entities, sizeof( entity_state_t ) * cls.num_client_entities ); cls.packet_entities = Mem_Realloc( clgame.mempool, cls.packet_entities, sizeof( entity_state_t ) * cls.num_client_entities );
clgame.entities = Mem_Calloc( clgame.mempool, sizeof( cl_entity_t ) * clgame.maxEntities ); clgame.entities = Mem_Calloc( clgame.mempool, sizeof( cl_entity_t ) * clgame.maxEntities );
clgame.static_entities = NULL; // will be initialized later clgame.static_entities = Mem_Calloc( clgame.mempool, sizeof( cl_entity_t ) * MAX_STATIC_ENTITIES );
clgame.numStatics = 0; clgame.numStatics = 0;
if(( clgame.maxRemapInfos - 1 ) != clgame.maxEntities ) if(( clgame.maxRemapInfos - 1 ) != clgame.maxEntities )
@@ -1699,12 +1700,7 @@ int GAME_EXPORT CL_GetScreenInfo( SCREENINFO *pscrinfo )
clgame.scrInfo.iSize = sizeof( clgame.scrInfo ); clgame.scrInfo.iSize = sizeof( clgame.scrInfo );
clgame.scrInfo.iFlags = SCRINFO_SCREENFLASH; clgame.scrInfo.iFlags = SCRINFO_SCREENFLASH;
if( hud_scale.value >= 320.0f && hud_scale.value >= hud_scale_minimal_width.value ) if( scale_factor && scale_factor != 1.0f )
{
scale_factor = refState.width / hud_scale.value;
apply_scale_factor = true;
}
else if( scale_factor && scale_factor != 1.0f )
{ {
float scaled_width = (float)refState.width / scale_factor; float scaled_width = (float)refState.width / scale_factor;
if( scaled_width >= hud_scale_minimal_width.value ) if( scaled_width >= hud_scale_minimal_width.value )
@@ -1769,17 +1765,6 @@ static cvar_t *GAME_EXPORT pfnCvar_RegisterClientVariable( const char *szName, c
return (cvar_t *)Cvar_Get( szName, szValue, flags|FCVAR_CLIENTDLL, Cvar_BuildAutoDescription( szName, flags|FCVAR_CLIENTDLL )); return (cvar_t *)Cvar_Get( szName, szValue, flags|FCVAR_CLIENTDLL, Cvar_BuildAutoDescription( szName, flags|FCVAR_CLIENTDLL ));
} }
static int GAME_EXPORT Cmd_AddClientCommand( const char *cmd_name, xcommand_t function )
{
int flags = CMD_CLIENTDLL;
// a1ba: try to mitigate outdated client.dll vulnerabilities
if( !Q_stricmp( cmd_name, "motd_write" ))
flags |= CMD_PRIVILEGED;
return Cmd_AddCommandEx( cmd_name, function, "client command", flags, __func__ );
}
/* /*
============= =============
pfnHookUserMsg pfnHookUserMsg
@@ -2414,8 +2399,9 @@ CL_FindModelIndex
*/ */
static int GAME_EXPORT CL_FindModelIndex( const char *m ) static int GAME_EXPORT CL_FindModelIndex( const char *m )
{ {
char filepath[MAX_QPATH]; char filepath[MAX_QPATH];
int i; static float lasttimewarn;
int i;
if( !COM_CheckString( m )) if( !COM_CheckString( m ))
return 0; return 0;
@@ -2432,6 +2418,13 @@ static int GAME_EXPORT CL_FindModelIndex( const char *m )
return i+1; return i+1;
} }
if( lasttimewarn < host.realtime )
{
// tell user about problem (but don't spam console)
Con_DPrintf( S_ERROR "Could not find index for model %s: not precached\n", filepath );
lasttimewarn = host.realtime + 1.0f;
}
return 0; return 0;
} }
@@ -2705,6 +2698,17 @@ static const char *pfnGetGameDirectory( void )
return szGetGameDir; return szGetGameDir;
} }
/*
=============
Key_LookupBinding
=============
*/
static const char *Key_LookupBinding( const char *pBinding )
{
return Key_KeynumToString( Key_GetKey( pBinding ));
}
/* /*
============= =============
pfnGetLevelName pfnGetLevelName
@@ -3354,6 +3358,28 @@ DemoApi implementation
================= =================
*/ */
/*
=================
Demo_IsRecording
=================
*/
static int GAME_EXPORT Demo_IsRecording( void )
{
return cls.demorecording;
}
/*
=================
Demo_IsPlayingback
=================
*/
static int GAME_EXPORT Demo_IsPlayingback( void )
{
return cls.demoplayback;
}
/* /*
================= =================
Demo_IsTimeDemo Demo_IsTimeDemo
@@ -3365,6 +3391,17 @@ static int GAME_EXPORT Demo_IsTimeDemo( void )
return cls.timedemo; return cls.timedemo;
} }
/*
=================
Demo_WriteBuffer
=================
*/
static void GAME_EXPORT Demo_WriteBuffer( int size, byte *buffer )
{
CL_WriteDemoUserMessage( buffer, size );
}
/* /*
================= =================
NetworkApi implementation NetworkApi implementation
@@ -3427,7 +3464,7 @@ static void GAME_EXPORT NetAPI_SendRequest( int context, int request, int flags,
return; 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 return; // IPX no longer support
if( request == NETAPI_REQUEST_SERVERLIST ) if( request == NETAPI_REQUEST_SERVERLIST )
@@ -3550,6 +3587,28 @@ static int GAME_EXPORT NetAPI_CompareAdr( netadr_t *a, netadr_t *b )
return NET_CompareAdr( *a, *b ); return NET_CompareAdr( *a, *b );
} }
/*
=================
NetAPI_StringToAdr
=================
*/
static int GAME_EXPORT NetAPI_StringToAdr( char *s, netadr_t *a )
{
return NET_StringToAdr( s, a );
}
/*
=================
NetAPI_ValueForKey
=================
*/
static const char * GAME_EXPORT NetAPI_ValueForKey( const char *s, const char *key )
{
return Info_ValueForKey( s, key );
}
/* /*
================= =================
NetAPI_RemoveKey NetAPI_RemoveKey
@@ -3746,10 +3805,10 @@ static event_api_t gEventApi =
static demo_api_t gDemoApi = static demo_api_t gDemoApi =
{ {
(void *)CL_IsRecordDemo, Demo_IsRecording,
(void *)CL_IsPlaybackDemo, Demo_IsPlayingback,
Demo_IsTimeDemo, Demo_IsTimeDemo,
CL_WriteDemoUserMessage, Demo_WriteBuffer,
}; };
net_api_t gNetApi = net_api_t gNetApi =
@@ -3761,8 +3820,8 @@ net_api_t gNetApi =
NetAPI_CancelAllRequests, NetAPI_CancelAllRequests,
NetAPI_AdrToString, NetAPI_AdrToString,
NetAPI_CompareAdr, NetAPI_CompareAdr,
(void *)NET_StringToAdr, NetAPI_StringToAdr,
Info_ValueForKey, NetAPI_ValueForKey,
NetAPI_RemoveKey, NetAPI_RemoveKey,
NetAPI_SetValueForKey, NetAPI_SetValueForKey,
}; };
@@ -3948,10 +4007,9 @@ void CL_UnloadProgs( void )
qboolean CL_LoadProgs( const char *name ) qboolean CL_LoadProgs( const char *name )
{ {
static playermove_t gpMove; static playermove_t gpMove;
CL_EXPORT_FUNCS GetClientAPI; // single export const dllfunc_t *func;
qboolean valid_single_export = false; CL_EXPORT_FUNCS GetClientAPI; // single export
qboolean missed_exports = false; qboolean critical_exports = true;
int i;
if( clgame.hInstance ) CL_UnloadProgs(); if( clgame.hInstance ) CL_UnloadProgs();
@@ -3962,19 +4020,36 @@ qboolean CL_LoadProgs( const char *name )
clgame.mempool = Mem_AllocPool( "Client Edicts Zone" ); clgame.mempool = Mem_AllocPool( "Client Edicts Zone" );
clgame.entities = NULL; clgame.entities = NULL;
// a1ba: we need to check if client.dll has direct dependency on SDL2 // a1ba: we need to check if client.dll has direct dependency on SDL2
// and if so, disable relative mouse mode // and if so, disable relative mouse mode
#if XASH_WIN32 && !XASH_64BIT #if XASH_WIN32 && !XASH_64BIT
clgame.client_dll_uses_sdl = COM_CheckLibraryDirectDependency( name, OS_LIB_PREFIX "SDL2." OS_LIB_EXT, false ); if( ( clgame.client_dll_uses_sdl = COM_CheckLibraryDirectDependency( name, OS_LIB_PREFIX "SDL2." OS_LIB_EXT, false ) ) )
Con_Printf( S_NOTE "%s uses %s for mouse input\n", name, clgame.client_dll_uses_sdl ? "SDL2" : "Windows API" ); {
Con_Printf( S_NOTE "%s uses SDL2 for mouse input\n", name );
}
else
{
Con_Printf( S_NOTE "%s uses Windows API for mouse input\n", name );
}
#else
// this doesn't mean other platforms uses SDL2 in any case
// it just helps input code to stay platform-independent
clgame.client_dll_uses_sdl = true;
#endif #endif
// NOTE: important stuff! // NOTE: important stuff!
// vgui must startup BEFORE loading client.dll to avoid get error ERROR_NOACESS during LoadLibrary // vgui must startup BEFORE loading client.dll to avoid get error ERROR_NOACESS
// during LoadLibrary
if( !GI->internal_vgui_support && VGui_LoadProgs( NULL )) if( !GI->internal_vgui_support && VGui_LoadProgs( NULL ))
{
VGui_Startup( refState.width, refState.height ); VGui_Startup( refState.width, refState.height );
}
else else
GI->internal_vgui_support = true; // we failed to load vgui_support, but let's probe client.dll for support anyway {
// we failed to load vgui_support, but let's probe client.dll for support anyway
GI->internal_vgui_support = true;
}
clgame.hInstance = COM_LoadLibrary( name, false, false ); clgame.hInstance = COM_LoadLibrary( name, false, false );
@@ -3983,10 +4058,13 @@ qboolean CL_LoadProgs( const char *name )
// delayed vgui initialization for internal support // delayed vgui initialization for internal support
if( GI->internal_vgui_support && VGui_LoadProgs( clgame.hInstance )) if( GI->internal_vgui_support && VGui_LoadProgs( clgame.hInstance ))
{
VGui_Startup( refState.width, refState.height ); VGui_Startup( refState.width, refState.height );
}
// clear exports // clear exports
ClearExports( cdll_exports, ARRAYSIZE( cdll_exports )); for( func = cdll_exports; func && func->name; func++ )
*func->func = NULL;
// trying to get single export // trying to get single export
if(( GetClientAPI = (void *)COM_GetProcAddress( clgame.hInstance, "GetClientAPI" )) != NULL ) if(( GetClientAPI = (void *)COM_GetProcAddress( clgame.hInstance, "GetClientAPI" )) != NULL )
@@ -4004,44 +4082,56 @@ qboolean CL_LoadProgs( const char *name )
CL_GetSecuredClientAPI( GetClientAPI ); CL_GetSecuredClientAPI( GetClientAPI );
} }
if( GetClientAPI != NULL ) // check critical functions again if ( GetClientAPI != NULL )
valid_single_export = ValidateExports( cdll_exports, ARRAYSIZE( cdll_exports ));
for( i = 0; i < ARRAYSIZE( cdll_exports ); i++ )
{ {
if( *(cdll_exports[i].func) != NULL ) // check critical functions again
continue; // already gott through 'F' or 'GetClientAPI' for( func = cdll_exports; func && func->name; func++ )
{
if( func->func == NULL )
break; // BAH critical function was missed
}
// because all the exports are loaded through function 'F"
if( !func || !func->name )
critical_exports = false;
}
for( func = cdll_exports; func && func->name != NULL; func++ )
{
if( *func->func != NULL )
continue; // already get through 'F'
// functions are cleared before all the extensions are evaluated // functions are cleared before all the extensions are evaluated
if(( *(cdll_exports[i].func) = (void *)COM_GetProcAddress( clgame.hInstance, cdll_exports[i].name )) == NULL ) if(( *func->func = (void *)COM_GetProcAddress( clgame.hInstance, func->name )) == NULL )
{ {
Con_Reportf( S_ERROR "%s: failed to get address of %s proc\n", __func__, cdll_exports[i].name ); Con_Reportf( "%s: failed to get address of %s proc\n", __func__, func->name );
// print all not found exports at once, for debug if( critical_exports )
missed_exports = true; {
COM_FreeLibrary( clgame.hInstance );
clgame.hInstance = NULL;
return false;
}
} }
} }
if( missed_exports ) // it may be loaded through 'GetClientAPI' so we don't need to clear them
if( critical_exports )
{ {
COM_FreeLibrary( clgame.hInstance ); // clear new exports
clgame.hInstance = NULL; for( func = cdll_new_exports; func && func->name; func++ )
return false; *func->func = NULL;
} }
// it may be loaded through 'GetClientAPI' so we don't need to clear them for( func = cdll_new_exports; func && func->name != NULL; func++ )
if( !valid_single_export )
ClearExports( cdll_new_exports, ARRAYSIZE( cdll_new_exports ));
for( i = 0; i < ARRAYSIZE( cdll_new_exports ); i++ )
{ {
if( *(cdll_new_exports[i].func) != NULL ) if( *func->func != NULL )
continue; // already gott through 'F' or 'GetClientAPI' continue; // already get through 'F'
// functions are cleared before all the extensions are evaluated // functions are cleared before all the extensions are evaluated
// NOTE: new exports can be missed without stop the engine // NOTE: new exports can be missed without stop the engine
if(( *(cdll_new_exports[i].func) = (void *)COM_GetProcAddress( clgame.hInstance, cdll_new_exports[i].name )) == NULL ) if(( *func->func = (void *)COM_GetProcAddress( clgame.hInstance, func->name )) == NULL )
Con_Reportf( S_WARN "%s: failed to get address of %s proc\n", __func__, cdll_new_exports[i].name ); Con_Reportf( "%s: failed to get address of %s proc\n", __func__, func->name );
} }
if( !clgame.dllFuncs.pfnInitialize( &gEngfuncs, CLDLL_INTERFACE_VERSION )) if( !clgame.dllFuncs.pfnInitialize( &gEngfuncs, CLDLL_INTERFACE_VERSION ))
+1 -6
View File
@@ -694,11 +694,6 @@ static cvar_t *GAME_EXPORT pfnCvar_RegisterGameUIVariable( const char *szName, c
return (cvar_t *)Cvar_Get( szName, szValue, flags|FCVAR_GAMEUIDLL, Cvar_BuildAutoDescription( szName, flags|FCVAR_GAMEUIDLL )); return (cvar_t *)Cvar_Get( szName, szValue, flags|FCVAR_GAMEUIDLL, Cvar_BuildAutoDescription( szName, flags|FCVAR_GAMEUIDLL ));
} }
static int GAME_EXPORT Cmd_AddGameUICommand( const char *cmd_name, xcommand_t function )
{
return Cmd_AddCommandEx( cmd_name, function, "gameui command", CMD_GAMEUIDLL, __func__ );
}
/* /*
============= =============
pfnClientCmd pfnClientCmd
@@ -1114,7 +1109,7 @@ static void GAME_EXPORT UI_ShellExecute( const char *path, const char *parms, in
Platform_ShellExecute( path, parms ); Platform_ShellExecute( path, parms );
if( shouldExit ) if( shouldExit )
Sys_Quit( __func__ ); Sys_Quit();
} }
/* /*
+28 -62
View File
@@ -76,7 +76,6 @@ static CVAR_DEFINE_AUTO( cl_upmax, "1200", FCVAR_ARCHIVE, "max allowed incoming
CVAR_DEFINE_AUTO( cl_lw, "1", FCVAR_ARCHIVE|FCVAR_USERINFO, "enable client weapon predicting" ); CVAR_DEFINE_AUTO( cl_lw, "1", FCVAR_ARCHIVE|FCVAR_USERINFO, "enable client weapon predicting" );
CVAR_DEFINE_AUTO( cl_charset, "utf-8", FCVAR_ARCHIVE, "1-byte charset to use (iconv style)" ); CVAR_DEFINE_AUTO( cl_charset, "utf-8", FCVAR_ARCHIVE, "1-byte charset to use (iconv style)" );
CVAR_DEFINE_AUTO( cl_trace_consistency, "0", FCVAR_ARCHIVE, "enable consistency info tracing (good for developers)" );
CVAR_DEFINE_AUTO( cl_trace_stufftext, "0", FCVAR_ARCHIVE, "enable stufftext (server-to-client console commands) tracing (good for developers)" ); CVAR_DEFINE_AUTO( cl_trace_stufftext, "0", FCVAR_ARCHIVE, "enable stufftext (server-to-client console commands) tracing (good for developers)" );
CVAR_DEFINE_AUTO( cl_trace_messages, "0", FCVAR_ARCHIVE|FCVAR_CHEAT, "enable message names tracing (good for developers)" ); CVAR_DEFINE_AUTO( cl_trace_messages, "0", FCVAR_ARCHIVE|FCVAR_CHEAT, "enable message names tracing (good for developers)" );
CVAR_DEFINE_AUTO( cl_trace_events, "0", FCVAR_ARCHIVE|FCVAR_CHEAT, "enable events tracing (good for developers)" ); CVAR_DEFINE_AUTO( cl_trace_events, "0", FCVAR_ARCHIVE|FCVAR_CHEAT, "enable events tracing (good for developers)" );
@@ -148,6 +147,11 @@ qboolean CL_IsRecordDemo( void )
return cls.demorecording; return cls.demorecording;
} }
qboolean CL_IsTimeDemo( void )
{
return cls.timedemo;
}
qboolean CL_DisableVisibility( void ) qboolean CL_DisableVisibility( void )
{ {
return cls.envshot_disable_vis; return cls.envshot_disable_vis;
@@ -594,7 +598,7 @@ CL_CreateCmd
*/ */
static void CL_CreateCmd( void ) static void CL_CreateCmd( void )
{ {
usercmd_t nullcmd = { 0 }, *cmd; usercmd_t nullcmd, *cmd;
runcmd_t *pcmd; runcmd_t *pcmd;
qboolean active; qboolean active;
double accurate_ms; double accurate_ms;
@@ -646,6 +650,7 @@ static void CL_CreateCmd( void )
} }
else else
{ {
memset( &nullcmd, 0, sizeof( nullcmd ));
cmd = &nullcmd; cmd = &nullcmd;
} }
@@ -718,20 +723,11 @@ static void CL_WritePacket( void )
int numbackup, maxbackup, maxcmds; int numbackup, maxbackup, maxcmds;
const connprotocol_t proto = cls.legacymode; const connprotocol_t proto = cls.legacymode;
// FIXME: on Xash protocol we don't send move commands until ca_active
// to prevent outgoing_command outrun incoming_acknowledged
// which is fatal for some buggy mods like TFC
//
// ... but GoldSrc don't have (real) ca_validate state, so we consider
// ca_validate the same as ca_active, otherwise we don't pass validation
// of server-side mods like ReAuthCheck
const connstate_t min_state = proto == PROTO_GOLDSRC ? ca_validate : ca_active;
// don't send anything if playing back a demo // don't send anything if playing back a demo
if( cls.demoplayback || cls.state < ca_connected || cls.state == ca_cinematic ) if( cls.demoplayback || cls.state < ca_connected || cls.state == ca_cinematic )
return; return;
if( cls.state < min_state ) if( cls.state <= ca_connected )
{ {
Netchan_TransmitBits( &cls.netchan, 0, "" ); Netchan_TransmitBits( &cls.netchan, 0, "" );
return; return;
@@ -829,7 +825,7 @@ static void CL_WritePacket( void )
buf.pData[key] = CRC32_BlockSequence( &buf.pData[key + 1], size, cls.netchan.outgoing_sequence ); buf.pData[key] = CRC32_BlockSequence( &buf.pData[key + 1], size, cls.netchan.outgoing_sequence );
COM_Munge( &buf.pData[key + 1], Q_min( size, 255 ), cls.netchan.outgoing_sequence ); COM_Munge( &buf.pData[key + 1], Q_min( size, 255 ), cls.netchan.outgoing_sequence );
} }
else if( !Host_IsLocalClient( )) else
{ {
int size = MSG_GetRealBytesWritten( &buf ) - key - 1; int size = MSG_GetRealBytesWritten( &buf ) - key - 1;
buf.pData[key] = CRC32_BlockSequence( &buf.pData[key + 1], size, cls.netchan.outgoing_sequence ); buf.pData[key] = CRC32_BlockSequence( &buf.pData[key + 1], size, cls.netchan.outgoing_sequence );
@@ -969,7 +965,7 @@ CL_Quit_f
void CL_Quit_f( void ) void CL_Quit_f( void )
{ {
CL_Disconnect(); CL_Disconnect();
Sys_Quit( "command" ); Sys_Quit();
} }
/* /*
@@ -1063,7 +1059,6 @@ static void CL_SendConnectPacket( connprotocol_t proto, int challenge )
const char *key = ID_GetMD5(); const char *key = ID_GetMD5();
netadr_t adr = { 0 }; netadr_t adr = { 0 };
int input_devices; int input_devices;
netadrtype_t adrtype;
protinfo[0] = 0; protinfo[0] = 0;
@@ -1074,16 +1069,14 @@ static void CL_SendConnectPacket( connprotocol_t proto, int challenge )
return; return;
} }
adrtype = NET_NetadrType( &adr );
if( adr.port == 0 ) adr.port = MSG_BigShort( PORT_SERVER ); if( adr.port == 0 ) adr.port = MSG_BigShort( PORT_SERVER );
input_devices = IN_CollectInputDevices(); 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 // GoldSrc doesn't need sv_cheats set to 0, it's handled by svc_goldsrc_sendextrainfo
// it also doesn't need useragent string // 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_SetCheatState();
Cvar_FullSet( "sv_cheats", "0", FCVAR_READ_ONLY | FCVAR_SERVER ); Cvar_FullSet( "sv_cheats", "0", FCVAR_READ_ONLY | FCVAR_SERVER );
@@ -1221,7 +1214,7 @@ static void CL_CheckForResend( void )
cls.signon = 0; cls.signon = 0;
cls.state = ca_connecting; cls.state = ca_connecting;
Q_strncpy( cls.servername, "localhost", sizeof( cls.servername )); Q_strncpy( cls.servername, "localhost", sizeof( cls.servername ));
NET_NetadrSetType( &cls.serveradr, NA_LOOPBACK ); cls.serveradr.type = NA_LOOPBACK;
cls.legacymode = PROTO_CURRENT; cls.legacymode = PROTO_CURRENT;
// we don't need a challenge on the localhost // we don't need a challenge on the localhost
@@ -1408,8 +1401,7 @@ static void CL_Connect_f( void )
Q_strncpy( server, Cmd_Argv( 1 ), sizeof( server )); Q_strncpy( server, Cmd_Argv( 1 ), sizeof( server ));
// if running a local server, kill it and reissue // if running a local server, kill it and reissue
if( SV_Active( )) if( SV_Active( )) Host_ShutdownServer();
SV_Shutdown( "Server was killed due to connection to remote server\n" );
NET_Config( true, !cl_nat.value ); // allow remote NET_Config( true, !cl_nat.value ); // allow remote
Con_Printf( "server %s\n", server ); Con_Printf( "server %s\n", server );
@@ -1557,8 +1549,8 @@ static void CL_SendDisconnectMessage( connprotocol_t proto )
MSG_WriteString( &buf, "dropclient\n" ); MSG_WriteString( &buf, "dropclient\n" );
else MSG_WriteString( &buf, "disconnect" ); else MSG_WriteString( &buf, "disconnect" );
if( NET_NetadrType( &cls.netchan.remote_address ) == NA_UNDEFINED ) if( !cls.netchan.remote_address.type )
NET_NetadrSetType( &cls.netchan.remote_address, NA_LOOPBACK ); cls.netchan.remote_address.type = NA_LOOPBACK;
// make sure message will be delivered // make sure message will be delivered
Netchan_TransmitBits( &cls.netchan, MSG_GetNumBitsWritten( &buf ), MSG_GetData( &buf )); Netchan_TransmitBits( &cls.netchan, MSG_GetNumBitsWritten( &buf ), MSG_GetData( &buf ));
@@ -1601,9 +1593,6 @@ void CL_SetupNetchanForProtocol( connprotocol_t proto )
} }
break; break;
default: default:
if( !Host_IsLocalClient( ))
SetBits( flags, NETCHAN_USE_LZSS );
cls.extensions = Q_atoi( Info_ValueForKey( Cmd_Argv( 1 ), "ext" )); cls.extensions = Q_atoi( Info_ValueForKey( Cmd_Argv( 1 ), "ext" ));
if( FBitSet( cls.extensions, NET_EXT_SPLITSIZE )) if( FBitSet( cls.extensions, NET_EXT_SPLITSIZE ))
@@ -1727,17 +1716,19 @@ CL_LocalServers_f
*/ */
static void CL_LocalServers_f( void ) 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" ); Con_Printf( "Scanning for servers on the local network area...\n" );
NET_Config( true, true ); // allow remote NET_Config( true, true ); // allow remote
// send a broadcast packet // send a broadcast packet
NET_NetadrSetType( &adr, NA_BROADCAST ); adr.type = NA_BROADCAST;
adr.port = MSG_BigShort( PORT_SERVER ); adr.port = MSG_BigShort( PORT_SERVER );
Netchan_OutOfBandPrint( NS_CLIENT, adr, A2A_INFO" %i", PROTOCOL_VERSION ); 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 ); Netchan_OutOfBandPrint( NS_CLIENT, adr, A2A_INFO" %i", PROTOCOL_VERSION );
} }
@@ -1769,8 +1760,8 @@ static size_t NONNULL CL_BuildMasterServerScanRequest( char *buf, size_t size, u
// let master know about client version // let master know about client version
Info_SetValueForKey( info, "clver", XASH_VERSION, remaining ); Info_SetValueForKey( info, "clver", XASH_VERSION, remaining );
Info_SetValueForKey( info, "nat", nat ? "1" : "0", remaining ); Info_SetValueForKey( info, "nat", nat ? "1" : "0", remaining );
Info_SetValueForKey( info, "commit", g_buildcommit, remaining ); Info_SetValueForKey( info, "commit", Q_buildcommit(), remaining );
Info_SetValueForKey( info, "branch", g_buildbranch, remaining ); Info_SetValueForKey( info, "branch", Q_buildbranch(), remaining );
Info_SetValueForKey( info, "os", Q_buildos(), remaining ); Info_SetValueForKey( info, "os", Q_buildos(), remaining );
Info_SetValueForKey( info, "arch", Q_buildarch(), remaining ); Info_SetValueForKey( info, "arch", Q_buildarch(), remaining );
@@ -2481,18 +2472,18 @@ static void CL_ServerList( netadr_t from, sizebuf_t *msg )
while( MSG_GetNumBitsLeft( msg ) > 8 ) while( MSG_GetNumBitsLeft( msg ) > 8 )
{ {
uint8_t addr[16]; 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 )); MSG_ReadBytes( msg, addr, sizeof( addr ));
NET_IP6BytesToNetadr( &servadr, addr ); NET_IP6BytesToNetadr( &servadr, addr );
NET_NetadrSetType( &servadr, NA_IP6 ); servadr.type6 = NA_IP6;
} }
else else
{ {
MSG_ReadBytes( msg, servadr.ip, sizeof( servadr.ip )); // 4 bytes for IP 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 servadr.port = MSG_ReadShort( msg ); // 2 bytes for Port
@@ -3140,9 +3131,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; return retval;
} }
@@ -3152,7 +3140,7 @@ qboolean CL_PrecacheResources( void )
// if we downloaded new WAD files or any other archives they must be added to searchpath // if we downloaded new WAD files or any other archives they must be added to searchpath
if( CL_ShouldRescanFilesystem( )) if( CL_ShouldRescanFilesystem( ))
FS_Rescan_f(); g_fsapi.Rescan();
// NOTE: world need to be loaded as first model // NOTE: world need to be loaded as first model
for( pRes = cl.resourcesonhand.pNext; pRes && pRes != &cl.resourcesonhand; pRes = pRes->pNext ) for( pRes = cl.resourcesonhand.pNext; pRes && pRes != &cl.resourcesonhand; pRes = pRes->pNext )
@@ -3338,22 +3326,6 @@ static void CL_Escape_f( void )
else UI_SetActiveMenu( true ); else UI_SetActiveMenu( true );
} }
static void CL_ListMessages_f( void )
{
int i;
Con_Printf( "num size name\n" );
for( i = 0; i < MAX_USER_MESSAGES; i++ )
{
if( !COM_CheckStringEmpty( clgame.msg[i].name ))
break;
Con_Printf( "%3d\t%3d\t%s\n", clgame.msg[i].number, clgame.msg[i].size, clgame.msg[i].name );
}
Con_Printf( "Total %i messages\n", i );
}
/* /*
================= =================
CL_InitLocal CL_InitLocal
@@ -3398,7 +3370,6 @@ static void CL_InitLocal( void )
Cvar_RegisterVariable( &rcon_address ); Cvar_RegisterVariable( &rcon_address );
Cvar_RegisterVariable( &cl_trace_consistency );
Cvar_RegisterVariable( &cl_trace_stufftext ); Cvar_RegisterVariable( &cl_trace_stufftext );
Cvar_RegisterVariable( &cl_trace_messages ); Cvar_RegisterVariable( &cl_trace_messages );
Cvar_RegisterVariable( &cl_trace_events ); Cvar_RegisterVariable( &cl_trace_events );
@@ -3493,8 +3464,6 @@ static void CL_InitLocal( void )
Cmd_AddCommand ("fullserverinfo", CL_FullServerinfo_f, "sent by server when serverinfo changes" ); Cmd_AddCommand ("fullserverinfo", CL_FullServerinfo_f, "sent by server when serverinfo changes" );
Cmd_AddCommand ("upload", CL_BeginUpload_f, "uploading file to the server" ); 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 ("quit", CL_Quit_f, "quit from game" );
Cmd_AddRestrictedCommand ("exit", CL_Quit_f, "quit from game" ); Cmd_AddRestrictedCommand ("exit", CL_Quit_f, "quit from game" );
@@ -3514,7 +3483,6 @@ static void CL_InitLocal( void )
Cmd_AddCommand( "richpresence_gamemode", Cmd_Null_f, "compatibility command, does nothing" ); Cmd_AddCommand( "richpresence_gamemode", Cmd_Null_f, "compatibility command, does nothing" );
Cmd_AddCommand( "richpresence_update", Cmd_Null_f, "compatibility command, does nothing" ); Cmd_AddCommand( "richpresence_update", Cmd_Null_f, "compatibility command, does nothing" );
Cmd_AddCommand( "cl_list_messages", CL_ListMessages_f, "list registered user messages" );
} }
//============================================================================ //============================================================================
@@ -3672,8 +3640,6 @@ void CL_Init( void )
if( !CL_LoadProgs( libpath )) if( !CL_LoadProgs( libpath ))
Host_Error( "can't initialize %s: %s\n", libpath, COM_GetLibraryError( )); Host_Error( "can't initialize %s: %s\n", libpath, COM_GetLibraryError( ));
ID_Init();
cls.build_num = 0; cls.build_num = 0;
cls.initialized = true; cls.initialized = true;
cl.maxclients = 1; // allow to drawing player in menu cl.maxclients = 1; // allow to drawing player in menu
+1 -6
View File
@@ -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 ); return COM_ParseFileSafe( data, buf, size, flags, len, NULL );
} }
static void GAME_EXPORT pfnSetCustomClientID( const char *id )
{
// deprecated
}
static const mobile_engfuncs_t gMobileEngfuncs = static const mobile_engfuncs_t gMobileEngfuncs =
{ {
MOBILITY_API_VERSION, MOBILITY_API_VERSION,
@@ -111,7 +106,7 @@ static const mobile_engfuncs_t gMobileEngfuncs =
pfnDrawScaledCharacter, pfnDrawScaledCharacter,
Sys_Warn, Sys_Warn,
Sys_GetNativeObject, Sys_GetNativeObject,
pfnSetCustomClientID, ID_SetCustomClientID,
pfnParseFileSafe pfnParseFileSafe
}; };
+24 -50
View File
@@ -311,13 +311,10 @@ static client entity
static void CL_ParseStaticEntity( sizebuf_t *msg ) static void CL_ParseStaticEntity( sizebuf_t *msg )
{ {
int i, newnum; int i, newnum;
const entity_state_t from = { 0 }; entity_state_t from, to;
entity_state_t to;
cl_entity_t *ent; cl_entity_t *ent;
if( !clgame.static_entities ) memset( &from, 0, sizeof( from ));
clgame.static_entities = Mem_Calloc( clgame.mempool, sizeof( cl_entity_t ) * MAX_STATIC_ENTITIES );
newnum = MSG_ReadUBitLong( msg, MAX_ENTITY_BITS ); newnum = MSG_ReadUBitLong( msg, MAX_ENTITY_BITS );
MSG_ReadDeltaEntity( msg, &from, &to, 0, DELTA_STATIC, cl.mtime[0] ); MSG_ReadDeltaEntity( msg, &from, &to, 0, DELTA_STATIC, cl.mtime[0] );
@@ -1325,11 +1322,11 @@ void CL_ParseLightStyle( sizebuf_t *msg, connprotocol_t proto )
{ {
int style; int style;
const char *s; const char *s;
float f = cl.mtime[0]; float f = 0.0f;
style = MSG_ReadByte( msg ); style = MSG_ReadByte( msg );
s = MSG_ReadString( msg ); s = MSG_ReadString( msg );
if( proto != PROTO_GOLDSRC && proto != PROTO_QUAKE ) if( proto != PROTO_GOLDSRC )
f = MSG_ReadFloat( msg ); f = MSG_ReadFloat( msg );
CL_SetLightstyle( style, s, f ); CL_SetLightstyle( style, s, f );
@@ -1427,31 +1424,37 @@ register new user message or update existing
void CL_RegisterUserMessage( sizebuf_t *msg, connprotocol_t proto ) void CL_RegisterUserMessage( sizebuf_t *msg, connprotocol_t proto )
{ {
char *pszName; char *pszName;
char szName[17]; int svc_num, size, bits;
int size;
int svc_num = MSG_ReadByte( msg ); svc_num = MSG_ReadByte( msg );
if( proto == PROTO_LEGACY || proto == PROTO_GOLDSRC ) if( proto == PROTO_LEGACY || proto == PROTO_GOLDSRC )
{ {
size = MSG_ReadByte( msg ); size = MSG_ReadByte( msg );
if( size == UINT8_MAX ) bits = 8;
size = -1;
} }
else else
{ {
size = MSG_ReadWord( msg ); size = MSG_ReadWord( msg );
if( size == UINT16_MAX ) bits = 16;
size = -1;
} }
if( proto == PROTO_GOLDSRC ) if( proto == PROTO_GOLDSRC )
{ {
static char szName[17];
MSG_ReadBytes( msg, szName, sizeof( szName ) - 1 ); MSG_ReadBytes( msg, szName, sizeof( szName ) - 1 );
szName[16] = 0; szName[16] = 0;
pszName = szName; pszName = szName;
} }
else pszName = MSG_ReadString( msg ); else pszName = MSG_ReadString( msg );
// important stuff
if( size == ( BIT( bits ) - 1 ) )
size = -1;
svc_num = bound( 0, svc_num, 255 );
CL_LinkUserMessage( pszName, svc_num, size ); CL_LinkUserMessage( pszName, svc_num, size );
} }
@@ -1590,23 +1593,17 @@ collect pings and packet lossage from clients
*/ */
void CL_UpdateUserPings( sizebuf_t *msg ) void CL_UpdateUserPings( sizebuf_t *msg )
{ {
// a1ba: there was a MAX_PLAYERS check but it doesn't make sense int i, slot;
// because pings message always ends by null bit player_info_t *player;
while( 1 )
{
int slot;
player_info_t *player;
if( !MSG_ReadOneBit( msg )) for( i = 0; i < MAX_CLIENTS; i++ )
break; // end of message {
if( !MSG_ReadOneBit( msg )) break; // end of message
slot = MSG_ReadUBitLong( msg, MAX_CLIENT_BITS ); slot = MSG_ReadUBitLong( msg, MAX_CLIENT_BITS );
if( unlikely( slot >= MAX_CLIENTS )) if( slot >= MAX_CLIENTS )
{
Host_Error( "%s: svc_pings > MAX_CLIENTS\n", __func__ ); Host_Error( "%s: svc_pings > MAX_CLIENTS\n", __func__ );
return;
}
player = &cl.players[slot]; player = &cl.players[slot];
player->ping = MSG_ReadUBitLong( msg, 12 ); player->ping = MSG_ReadUBitLong( msg, 12 );
@@ -1614,23 +1611,6 @@ void CL_UpdateUserPings( sizebuf_t *msg )
} }
} }
static const char *CL_CheckTypeToString( int check_type )
{
// renamed so they have same width and look better in console output
switch( check_type )
{
case force_exactfile:
return "exactfile";
case force_model_samebounds:
return "samebounds";
case force_model_specifybounds:
return "specbounds";
case force_model_specifybounds_if_avail:
return "specbounds2";
}
return "unknown";
}
static void CL_SendConsistencyInfo( sizebuf_t *msg, connprotocol_t proto ) static void CL_SendConsistencyInfo( sizebuf_t *msg, connprotocol_t proto )
{ {
qboolean user_changed_diskfile; qboolean user_changed_diskfile;
@@ -1896,9 +1876,6 @@ static void CL_ParseConsistencyInfo( sizebuf_t *msg, connprotocol_t proto )
return; return;
} }
if( cl_trace_consistency.value )
Con_Printf( "Server wants consistency of the following resources:\n" );
skip_crc_change = NULL; skip_crc_change = NULL;
lastcheck = 0; lastcheck = 0;
@@ -1930,7 +1907,7 @@ static void CL_ParseConsistencyInfo( sizebuf_t *msg, connprotocol_t proto )
pc = &cl.consistency_list[cl.num_consistency]; pc = &cl.consistency_list[cl.num_consistency];
cl.num_consistency++; cl.num_consistency++;
memset( pc, 0, sizeof( *pc )); memset( pc, 0, sizeof( consistency_t ));
pc->filename = pResource->szFileName; pc->filename = pResource->szFileName;
pc->issound = (pResource->type == t_sound); pc->issound = (pResource->type == t_sound);
pc->orig_index = delta; pc->orig_index = delta;
@@ -1943,9 +1920,6 @@ static void CL_ParseConsistencyInfo( sizebuf_t *msg, connprotocol_t proto )
pc->check_type = pResource->rguc_reserved[0]; pc->check_type = pResource->rguc_reserved[0];
} }
if( cl_trace_consistency.value )
Con_Printf( "%s\t%s\t%s\n", COM_ResourceTypeFromIndex( pResource->type ), CL_CheckTypeToString( pc->check_type ), pc->filename );
skip_crc_change = pResource; skip_crc_change = pResource;
lastcheck = delta; lastcheck = delta;
} }
+2 -4
View File
@@ -33,12 +33,10 @@ static client entity
static void CL_LegacyParseStaticEntity( sizebuf_t *msg ) static void CL_LegacyParseStaticEntity( sizebuf_t *msg )
{ {
int i; int i;
entity_state_t state = { 0 }; entity_state_t state;
cl_entity_t *ent; cl_entity_t *ent;
if( !clgame.static_entities ) memset( &state, 0, sizeof( state ));
clgame.static_entities = Mem_Calloc( clgame.mempool, sizeof( cl_entity_t ) * MAX_STATIC_ENTITIES );
state.modelindex = MSG_ReadShort( msg ); state.modelindex = MSG_ReadShort( msg );
state.sequence = MSG_ReadByte( msg ); state.sequence = MSG_ReadByte( msg );
state.frame = MSG_ReadByte( msg ); state.frame = MSG_ReadByte( msg );
+20 -37
View File
@@ -83,10 +83,7 @@ static void CL_ParseNewMovevars( sizebuf_t *msg )
R_SetupSky( clgame.movevars.skyName ); R_SetupSky( clgame.movevars.skyName );
clgame.oldmovevars = clgame.movevars; clgame.oldmovevars = clgame.movevars;
clgame.entities->curstate.scale = clgame.movevars.waveHeight;
// FIXME: set world wave height when entities will be allocated
if( clgame.entities )
clgame.entities->curstate.scale = clgame.movevars.waveHeight;
// keep features an actual! // keep features an actual!
clgame.oldmovevars.features = clgame.movevars.features = host.features; clgame.oldmovevars.features = clgame.movevars.features = host.features;
@@ -94,11 +91,11 @@ static void CL_ParseNewMovevars( sizebuf_t *msg )
typedef struct delta_header_t typedef struct delta_header_t
{ {
qboolean remove; qboolean remove : 1;
qboolean custom; qboolean custom : 1;
qboolean instanced; qboolean instanced : 1;
uint16_t instanced_baseline_index; uint instanced_baseline_index : 6;
uint16_t offset; uint offset : 6;
} delta_header_t; } delta_header_t;
static int CL_ParseDeltaHeader( sizebuf_t *msg, qboolean delta, int oldnum, struct delta_header_t *hdr ) static int CL_ParseDeltaHeader( sizebuf_t *msg, qboolean delta, int oldnum, struct delta_header_t *hdr )
@@ -163,47 +160,33 @@ static int CL_GetEntityDelta( const struct delta_header_t *hdr, int entnum )
return DT_ENTITY_STATE_T; return DT_ENTITY_STATE_T;
} }
static int CL_FlushEntityPacketGS( frame_t *frame, sizebuf_t *msg ) static void CL_FlushEntityPacketGS( frame_t *frame, sizebuf_t *msg )
{ {
int playerbytes = 0, numbase = 0;
frame->valid = false; frame->valid = false;
cl.validsequence = 0; // can't render a frame cl.validsequence = 0; // can't render a frame
// read it all but ignore it // read it all but ignore it
while( 1 ) while( 1 )
{ {
int newnum, bufstart; int num = 0;
entity_state_t from = { 0 }, to; entity_state_t from = { 0 }, to;
delta_header_t hdr; delta_header_t hdr;
qboolean player;
if( MSG_ReadWord( msg ) != 0 ) if( MSG_ReadWord( msg ) != 0 )
{ {
MSG_SeekToBit( msg, -16, SEEK_CUR ); MSG_SeekToBit( msg, -16, SEEK_CUR );
numbase = newnum = CL_ParseDeltaHeader( msg, true, numbase, &hdr ); num = CL_ParseDeltaHeader( msg, false, num, &hdr );
} }
else break; else break;
if( MSG_CheckOverflow( msg )) if( MSG_CheckOverflow( msg ))
Host_Error( "%s: overflow\n", __func__ ); Host_Error( "%s: overflow\n", __func__ );
player = CL_IsPlayerIndex( newnum );
bufstart = MSG_GetNumBytesRead( msg );
if( hdr.remove ) if( hdr.remove )
continue; continue;
Delta_ReadGSFields( msg, CL_GetEntityDelta( &hdr, newnum ), &from, &to, cl.mtime[0] ); Delta_ReadGSFields( msg, CL_GetEntityDelta( &hdr, num ), &from, &to, cl.mtime[0] );
if( player )
playerbytes += MSG_GetNumBytesRead( msg ) - bufstart;
} }
if( MSG_CheckOverflow( msg ))
Host_Error( "%s: overflow\n", __func__ );
return playerbytes;
} }
static void CL_DeltaEntityGS( const delta_header_t *hdr, sizebuf_t *msg, frame_t *frame, int newnum, const entity_state_t *from ) static void CL_DeltaEntityGS( const delta_header_t *hdr, sizebuf_t *msg, frame_t *frame, int newnum, const entity_state_t *from )
@@ -220,7 +203,7 @@ static void CL_DeltaEntityGS( const delta_header_t *hdr, sizebuf_t *msg, frame_t
if(( newnum < 0 ) || ( newnum >= clgame.maxEntities )) if(( newnum < 0 ) || ( newnum >= clgame.maxEntities ))
{ {
Con_DPrintf( S_ERROR "CL_DeltaEntity: invalid newnum: %d\n", newnum ); Con_DPrintf( S_ERROR "CL_DeltaEntity: invalid newnum: %d\n", newnum );
Host_Error( "%s: bad delta entity number: %i\n", __func__, newnum ); Host_Error( "%s: bad delta entity number: %i", __func__, newnum );
return; return;
} }
@@ -284,7 +267,7 @@ static void CL_CopyPacketEntity( frame_t *frame, int num, const entity_state_t *
static int CL_ParsePacketEntitiesGS( sizebuf_t *msg, qboolean delta ) static int CL_ParsePacketEntitiesGS( sizebuf_t *msg, qboolean delta )
{ {
frame_t *frame, *oldframe; frame_t *frame, *oldframe;
int oldindex, oldnum, numbase = 0; int oldindex, newnum, oldnum, numbase = 0;
entity_state_t *oldent; entity_state_t *oldent;
int count; int count;
int playerbytes = 0; int playerbytes = 0;
@@ -331,7 +314,7 @@ static int CL_ParsePacketEntitiesGS( sizebuf_t *msg, qboolean delta )
// read it all but ignore it // read it all but ignore it
while( 1 ) while( 1 )
{ {
int bufstart, newnum; int bufstart;
qboolean player; qboolean player;
delta_header_t hdr; delta_header_t hdr;
int val = MSG_ReadWord( msg ); int val = MSG_ReadWord( msg );
@@ -551,7 +534,7 @@ void CL_ParseGoldSrcServerMessage( sizebuf_t *msg )
{ {
if( MSG_CheckOverflow( msg )) if( MSG_CheckOverflow( msg ))
{ {
Host_Error( "%s: overflow!\n", __func__ ); Host_Error( "CL_ParseServerMessage: overflow!\n" );
return; return;
} }
@@ -632,7 +615,7 @@ void CL_ParseGoldSrcServerMessage( sizebuf_t *msg )
case svc_setangle: case svc_setangle:
CL_ParseSetAngle( msg ); CL_ParseSetAngle( msg );
break; break;
case svc_serverdata: case svc_goldsrc_serverinfo:
Cbuf_Execute(); // make sure any stuffed commands are done Cbuf_Execute(); // make sure any stuffed commands are done
CL_ParseServerData( msg, PROTO_GOLDSRC ); CL_ParseServerData( msg, PROTO_GOLDSRC );
break; break;
@@ -642,7 +625,7 @@ void CL_ParseGoldSrcServerMessage( sizebuf_t *msg )
case svc_updateuserinfo: case svc_updateuserinfo:
CL_UpdateUserinfo( msg, PROTO_GOLDSRC ); CL_UpdateUserinfo( msg, PROTO_GOLDSRC );
break; break;
case svc_deltatable: case svc_goldsrc_deltadescription:
Delta_ParseTableField_GS( msg ); Delta_ParseTableField_GS( msg );
break; break;
case svc_clientdata: case svc_clientdata:
@@ -704,7 +687,7 @@ void CL_ParseGoldSrcServerMessage( sizebuf_t *msg )
case svc_addangle: case svc_addangle:
CL_ParseAddAngle( msg ); CL_ParseAddAngle( msg );
break; break;
case svc_usermessage: case svc_goldsrc_newusermsg:
CL_RegisterUserMessage( msg, PROTO_GOLDSRC ); CL_RegisterUserMessage( msg, PROTO_GOLDSRC );
break; break;
case svc_packetentities: case svc_packetentities:
@@ -726,7 +709,7 @@ void CL_ParseGoldSrcServerMessage( sizebuf_t *msg )
CL_ParseResourceList( msg, PROTO_GOLDSRC ); CL_ParseResourceList( msg, PROTO_GOLDSRC );
MSG_EndBitWriting( msg ); MSG_EndBitWriting( msg );
break; break;
case svc_deltamovevars: case svc_goldsrc_newmovevars:
CL_ParseNewMovevars( msg ); CL_ParseNewMovevars( msg );
break; break;
case svc_resourcerequest: case svc_resourcerequest:
@@ -766,10 +749,10 @@ void CL_ParseGoldSrcServerMessage( sizebuf_t *msg )
Con_Reportf( S_ERROR "%s: svc_goldsrc_timescale: implement me!\n", __func__ ); Con_Reportf( S_ERROR "%s: svc_goldsrc_timescale: implement me!\n", __func__ );
MSG_ReadFloat( msg ); MSG_ReadFloat( msg );
break; break;
case svc_querycvarvalue: case svc_goldsrc_sendcvarvalue:
CL_ParseCvarValue( msg, false, PROTO_GOLDSRC ); CL_ParseCvarValue( msg, false, PROTO_GOLDSRC );
break; break;
case svc_querycvarvalue2: case svc_goldsrc_sendcvarvalue2:
CL_ParseCvarValue( msg, true, PROTO_GOLDSRC ); CL_ParseCvarValue( msg, true, PROTO_GOLDSRC );
break; break;
case svc_exec: case svc_exec:
+5 -4
View File
@@ -628,12 +628,11 @@ CL_ParseStaticEntity
*/ */
static void CL_ParseQuakeStaticEntity( sizebuf_t *msg ) static void CL_ParseQuakeStaticEntity( sizebuf_t *msg )
{ {
entity_state_t state = { 0 }; entity_state_t state;
cl_entity_t *ent; cl_entity_t *ent;
int i; int i;
if( !clgame.static_entities ) memset( &state, 0, sizeof( state ));
clgame.static_entities = Mem_Calloc( clgame.mempool, sizeof( cl_entity_t ) * MAX_STATIC_ENTITIES );
state.modelindex = MSG_ReadByte( msg ); state.modelindex = MSG_ReadByte( msg );
state.frame = MSG_ReadByte( msg ); state.frame = MSG_ReadByte( msg );
@@ -970,7 +969,9 @@ void CL_ParseQuakeMessage( sizebuf_t *msg )
CL_ParseQuakeServerInfo( msg ); CL_ParseQuakeServerInfo( msg );
break; break;
case svc_lightstyle: case svc_lightstyle:
CL_ParseLightStyle( msg, PROTO_QUAKE ); param1 = MSG_ReadByte( msg );
str = MSG_ReadString( msg );
CL_SetLightstyle( param1, str, cl.mtime[0] );
break; break;
case svc_updatename: case svc_updatename:
param1 = MSG_ReadByte( msg ); param1 = MSG_ReadByte( msg );
+4 -6
View File
@@ -138,7 +138,10 @@ intptr_t CL_RenderGetParm( const int parm, const int arg, const qboolean checkRe
switch( parm ) switch( parm )
{ {
case PARM_BSP2_SUPPORTED: case PARM_BSP2_SUPPORTED:
#ifdef SUPPORT_BSP2_FORMAT
return 1; return 1;
#endif
return 0;
case PARAM_GAMEPAUSED: case PARAM_GAMEPAUSED:
return cl.paused; return cl.paused;
case PARM_CLIENT_INGAME: case PARM_CLIENT_INGAME:
@@ -233,11 +236,6 @@ static intptr_t pfnRenderGetParm( int parm, int arg )
return CL_RenderGetParm( parm, arg, true ); return CL_RenderGetParm( parm, arg, true );
} }
static void pfnAVI_StreamSound( void *avi, int entnum, float fvol, float attn, float synctime )
{
return; // stub, use AVI_SetParm and AVI_Think to stream AVI sound
}
static render_api_t gRenderAPI = static render_api_t gRenderAPI =
{ {
pfnRenderGetParm, // GL_RenderGetParm, pfnRenderGetParm, // GL_RenderGetParm,
@@ -270,7 +268,7 @@ static render_api_t gRenderAPI =
NULL, // R_UploadStretchRaw, NULL, // R_UploadStretchRaw,
(void*)AVI_FreeVideo, (void*)AVI_FreeVideo,
(void*)AVI_IsActive, (void*)AVI_IsActive,
(void*)pfnAVI_StreamSound, S_StreamAviSamples,
NULL, NULL,
NULL, NULL,
NULL, // GL_Bind, NULL, // GL_Bind,
+1 -1
View File
@@ -124,7 +124,7 @@ void SCR_DrawPos( void )
if( cls.state != ca_active || !cl_showpos.value || cl.background ) if( cls.state != ca_active || !cl_showpos.value || cl.background )
return; return;
ent = CL_GetLocalPlayer(); ent = CL_EDICT_NUM( cl.playernum + 1 );
speed = VectorLength( cl.simvel ); speed = VectorLength( cl.simvel );
Q_snprintf( msg, MAX_SYSPATH, Q_snprintf( msg, MAX_SYSPATH,
+51 -48
View File
@@ -567,54 +567,57 @@ R_FizzEffect
Create a fizz effect Create a fizz effect
============== ==============
*/ */
void GAME_EXPORT R_FizzEffect( cl_entity_t *ent, int modelIndex, int density ) void GAME_EXPORT R_FizzEffect( cl_entity_t *pent, int modelIndex, int density )
{ {
const float base_time = cl.time - 0.1f; TEMPENTITY *pTemp;
model_t *mod = CL_ModelHandle( modelIndex ); int i, width, depth;
vec3_t volume, mins, maxs; float angle, maxHeight, speed;
vec2_t speed; float xspeed, yspeed, zspeed;
int i; vec3_t origin;
model_t *mod;
if( !ent || !ent->model || !modelIndex || !mod ) if( !pent || !pent->model || !modelIndex )
return; return;
VectorCopy( ent->model->mins, mins ); if(( mod = CL_ModelHandle( modelIndex )) == NULL )
VectorCopy( ent->model->maxs, maxs ); return;
if( ent->angles[1] != 0.0f ) maxHeight = pent->model->maxs[2] - pent->model->mins[2];
{ width = pent->model->maxs[0] - pent->model->mins[0];
const float base_speed = ( ent->curstate.rendercolor.b ? -1.0f : 1.0f ) * ( ent->curstate.rendercolor.r * 256.0f + ent->curstate.rendercolor.g ); depth = pent->model->maxs[1] - pent->model->mins[1];
SinCos( DEG2RAD( ent->angles[1] ), &speed[1], &speed[0] );
speed[0] *= base_speed;
speed[1] *= base_speed;
}
else speed[0] = speed[1] = 0.0f;
VectorSubtract( maxs, mins, volume ); speed = ( pent->curstate.rendercolor.r<<8 | pent->curstate.rendercolor.g );
if( pent->curstate.rendercolor.b )
speed = -speed;
angle = DEG2RAD( pent->angles[YAW] );
SinCos( angle, &yspeed, &xspeed );
xspeed *= speed;
yspeed *= speed;
for( i = 0; i <= density; i++ ) for( i = 0; i <= density; i++ )
{ {
TEMPENTITY *tent; origin[0] = mod->mins[0] + COM_RandomLong( 0, width - 1 );
vec3_t origin; origin[1] = mod->mins[1] + COM_RandomLong( 0, depth - 1 );
origin[2] = mod->mins[2];
pTemp = CL_TempEntAlloc( origin, mod );
VectorCopy( mins, origin ); if ( !pTemp ) return;
origin[0] += COM_RandomLong( 0, (int)volume[0] - 1 );
origin[1] += COM_RandomLong( 0, (int)volume[1] - 1 );
if( !( tent = CL_TempEntAlloc( origin, mod ))) pTemp->flags |= FTENT_SINEWAVE;
return;
tent->x = origin[0]; pTemp->x = origin[0];
tent->y = origin[1]; pTemp->y = origin[1];
tent->die = base_time;
tent->flags |= FTENT_SINEWAVE;
tent->entity.curstate.rendermode = kRenderTransAlpha;
Vector2Copy( speed, tent->entity.baseline.origin );
tent->entity.baseline.origin[2] = COM_RandomLong( 80, 140 ); zspeed = COM_RandomLong( 80, 140 );
tent->die += volume[2] / tent->entity.baseline.origin[2]; VectorSet( pTemp->entity.baseline.origin, xspeed, yspeed, zspeed );
tent->entity.curstate.frame = COM_RandomLong( 0, tent->frameMax ); pTemp->die = cl.time + ( maxHeight / zspeed ) - 0.1f;
tent->entity.curstate.scale = 1.0f / COM_RandomFloat( 2.0f, 5.0f ); pTemp->entity.curstate.frame = COM_RandomLong( 0, pTemp->frameMax );
// Set sprite scale
pTemp->entity.curstate.scale = 1.0f / COM_RandomFloat( 2.0f, 5.0f );
pTemp->entity.curstate.rendermode = kRenderTransAlpha;
pTemp->entity.curstate.renderamt = 255;
} }
} }
@@ -2424,18 +2427,18 @@ static void CL_ClearLightStyles( void )
void CL_SetLightstyle( int style, const char *s, float f ) void CL_SetLightstyle( int style, const char *s, float f )
{ {
int i; int i, k;
lightstyle_t *ls; lightstyle_t *ls;
float val1, val2;
if( unlikely( style < 0 || style >= MAX_LIGHTSTYLES )) Assert( s != NULL );
{ Assert( style >= 0 && style < MAX_LIGHTSTYLES );
Con_Printf( S_WARN "%s: ignored invalid lightstyle id %d\n", __func__, style );
return;
}
ls = &cl.lightstyles[style]; ls = &cl.lightstyles[style];
ls->length = Q_strncpy( ls->pattern, s, sizeof( ls->pattern )); Q_strncpy( ls->pattern, s, sizeof( ls->pattern ));
ls->length = Q_strlen( s );
ls->time = f; // set local time ls->time = f; // set local time
for( i = 0; i < ls->length; i++ ) for( i = 0; i < ls->length; i++ )
@@ -2445,10 +2448,10 @@ void CL_SetLightstyle( int style, const char *s, float f )
// check for allow interpolate // check for allow interpolate
// NOTE: fast flickering styles looks ugly when interpolation is running // NOTE: fast flickering styles looks ugly when interpolation is running
for( i = 0; i < ( ls->length - 1 ); i++ ) for( k = 0; k < (ls->length - 1); k++ )
{ {
float val1 = ls->map[( i + 0 ) % ls->length]; val1 = ls->map[(k+0) % ls->length];
float val2 = ls->map[( i + 1 ) % ls->length]; val2 = ls->map[(k+1) % ls->length];
if( fabs( val1 - val2 ) > STYLE_LERPING_THRESHOLD ) if( fabs( val1 - val2 ) > STYLE_LERPING_THRESHOLD )
{ {
@@ -2468,8 +2471,8 @@ DLIGHT MANAGEMENT
============================================================== ==============================================================
*/ */
static dlight_t cl_dlights[MAX_DLIGHTS]; dlight_t cl_dlights[MAX_DLIGHTS];
static dlight_t cl_elights[MAX_ELIGHTS]; dlight_t cl_elights[MAX_ELIGHTS];
/* /*
================ ================
+3 -3
View File
@@ -466,8 +466,8 @@ static void R_ShowTree_r( mnode_t *node, float x, float y, float scale, int show
R_DrawNodeConnection( x, y, x + scale, y + scale ); R_DrawNodeConnection( x, y, x + scale, y + scale );
} }
R_ShowTree_r( node_child( node, 1, cl.worldmodel ), x - scale, y + scale, downScale, shownodes, viewleaf ); R_ShowTree_r( node->children[1], x - scale, y + scale, downScale, shownodes, viewleaf );
R_ShowTree_r( node_child( node, 0, cl.worldmodel ), x + scale, y + scale, downScale, shownodes, viewleaf ); R_ShowTree_r( node->children[0], x + scale, y + scale, downScale, shownodes, viewleaf );
world.recursion_level--; world.recursion_level--;
} }
@@ -482,7 +482,7 @@ static void R_ShowTree( void )
return; return;
world.recursion_level = 0; world.recursion_level = 0;
viewleaf = Mod_PointInLeaf( refState.vieworg, cl.worldmodel->nodes, cl.worldmodel ); viewleaf = Mod_PointInLeaf( refState.vieworg, cl.worldmodel->nodes );
ref.dllFuncs.TriRenderMode( kRenderTransTexture ); ref.dllFuncs.TriRenderMode( kRenderTransTexture );
+22 -32
View File
@@ -495,9 +495,7 @@ typedef struct
cl_entity_t viewent; // viewmodel cl_entity_t viewent; // viewmodel
#if XASH_WIN32
qboolean client_dll_uses_sdl; qboolean client_dll_uses_sdl;
#endif
} clgame_static_t; } clgame_static_t;
typedef struct typedef struct
@@ -688,7 +686,6 @@ extern convar_t r_showtextures;
extern convar_t cl_bmodelinterp; extern convar_t cl_bmodelinterp;
extern convar_t cl_lw; // local weapons extern convar_t cl_lw; // local weapons
extern convar_t cl_charset; extern convar_t cl_charset;
extern convar_t cl_trace_consistency;
extern convar_t cl_trace_stufftext; extern convar_t cl_trace_stufftext;
extern convar_t cl_trace_messages; extern convar_t cl_trace_messages;
extern convar_t cl_trace_events; extern convar_t cl_trace_events;
@@ -737,7 +734,6 @@ void CL_ClearResourceLists( void );
// //
// cl_debug.c // cl_debug.c
// //
void CL_ReplayBufferDat_f( void );
void CL_Parse_Debug( qboolean enable ); void CL_Parse_Debug( qboolean enable );
void CL_Parse_RecordCommand( int cmd, int startoffset ); void CL_Parse_RecordCommand( int cmd, int startoffset );
void CL_ResetFrame( frame_t *frame ); void CL_ResetFrame( frame_t *frame );
@@ -769,7 +765,7 @@ void CL_StartupDemoHeader( void );
void CL_DrawDemoRecording( void ); void CL_DrawDemoRecording( void );
void CL_WriteDemoUserCmd( int cmdnumber ); void CL_WriteDemoUserCmd( int cmdnumber );
void CL_WriteDemoMessage( qboolean startup, int start, sizebuf_t *msg ); void CL_WriteDemoMessage( qboolean startup, int start, sizebuf_t *msg );
void CL_WriteDemoUserMessage( int size, byte *buffer ); void CL_WriteDemoUserMessage( const byte *buffer, size_t size );
qboolean CL_DemoReadMessage( byte *buffer, size_t *length ); qboolean CL_DemoReadMessage( byte *buffer, size_t *length );
void CL_DemoInterpolateAngles( void ); void CL_DemoInterpolateAngles( void );
void CL_CheckStartupDemos( void ); void CL_CheckStartupDemos( void );
@@ -807,11 +803,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 ); 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_FreeFont( cl_font_t *font );
void CL_SetFontRendermode( 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_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, 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 );
void CL_DrawCharacterLen( cl_font_t *font, int number, int *width, int *height ); 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 ); 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 +840,19 @@ void CL_EnableScissor( scissor_state_t *scissor, int x, int y, int width, int he
void CL_DisableScissor( scissor_state_t *scissor ); 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 ); 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__ ); Host_Error( "%s: clgame.entities is NULL\n", __func__ );
return NULL; return NULL;
} }
if( index < 0 || index >= clgame.maxEntities ) if(( n >= 0 ) && ( n < clgame.maxEntities ))
{ return clgame.entities + n;
Host_Error( "%s: bad number %i\n", __func__, index );
return NULL;
}
return clgame.entities + index; Host_Error( "%s: bad number %i\n", __func__, n );
return NULL;
} }
static inline cl_entity_t *CL_GetEntityByIndex( int index ) static inline cl_entity_t *CL_GetEntityByIndex( int index )
@@ -869,7 +863,10 @@ static inline cl_entity_t *CL_GetEntityByIndex( int index )
if( index < 0 || index >= clgame.maxEntities ) if( index < 0 || index >= clgame.maxEntities )
return NULL; 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 ) static inline model_t *CL_ModelHandle( int modelindex )
@@ -879,17 +876,15 @@ static inline model_t *CL_ModelHandle( int modelindex )
static inline qboolean CL_IsThirdPerson( void ) 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 ) static inline cl_entity_t *CL_GetLocalPlayer( void )
{ {
cl_entity_t *player = CL_GetEntityByIndex( cl.playernum + 1 ); cl_entity_t *player;
// HACKHACK: GoldSrc doesn't do this, but some mods actually check it for null pointer player = CL_EDICT_NUM( cl.playernum + 1 );
// this is a lesser evil than changing semantics of HUD_VidInit and call it after entities are allocated Assert( player != NULL );
if( !player )
Con_Printf( S_WARN "%s: client entities are not initialized yet! Returning NULL...\n", __func__ );
return player; return player;
} }
@@ -1107,7 +1102,7 @@ int Con_UtfMoveRight( char *str, int pos, int length );
void Con_DefaultColor( int r, int g, int b, qboolean gameui ); void Con_DefaultColor( int r, int g, int b, qboolean gameui );
cl_font_t *Con_GetCurFont( void ); cl_font_t *Con_GetCurFont( void );
cl_font_t *Con_GetFont( int num ); 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 GAME_EXPORT Con_DrawStringLen( const char *pText, int *length, int *height ); // legacy, use cl_font.c
void Con_CharEvent( int key ); void Con_CharEvent( int key );
void Key_Console( int key ); void Key_Console( int key );
@@ -1120,7 +1115,7 @@ void Con_PageUp( int lines );
// //
// s_main.c // s_main.c
// //
typedef int sound_t; void S_StreamAviSamples( void *Avi, int entnum, float fvol, float attn, float synctime );
void S_StartBackgroundTrack( const char *intro, const char *loop, int position, qboolean fullpath ); void S_StartBackgroundTrack( const char *intro, const char *loop, int position, qboolean fullpath );
void S_StopBackgroundTrack( void ); void S_StopBackgroundTrack( void );
void S_StreamSetPause( int pause ); void S_StreamSetPause( int pause );
@@ -1200,21 +1195,16 @@ void Key_Init( void );
void Key_WriteBindings( file_t *f ); void Key_WriteBindings( file_t *f );
const char *Key_GetBinding( int keynum ); const char *Key_GetBinding( int keynum );
void Key_SetBinding( int keynum, const char *binding ); void Key_SetBinding( int keynum, const char *binding );
const char *Key_LookupBinding( const char *pBinding );
void Key_ClearStates( void ); void Key_ClearStates( void );
const char *Key_KeynumToString( int keynum ); const char *Key_KeynumToString( int keynum );
int Key_StringToKeynum( const char *str );
int Key_GetKey( const char *binding );
void Key_EnumCmds_f( void ); void Key_EnumCmds_f( void );
void Key_SetKeyDest( int key_dest ); void Key_SetKeyDest( int key_dest );
void Key_EnableTextInput( qboolean enable, qboolean force ); void Key_EnableTextInput( qboolean enable, qboolean force );
int Key_ToUpper( int key ); int Key_ToUpper( int key );
void OSK_Draw( void ); void OSK_Draw( void );
//
// identification.c
//
void ID_Init( void );
const char *ID_GetMD5( void );
extern rgba_t g_color_table[8]; extern rgba_t g_color_table[8];
extern triangleapi_t gTriApi; extern triangleapi_t gTriApi;
extern net_api_t gNetApi; extern net_api_t gNetApi;
+25 -45
View File
@@ -622,7 +622,7 @@ int Con_UtfProcessCharForce( int in )
// TODO: get rid of global state where possible // TODO: get rid of global state where possible
static utfstate_t state = { 0 }; static utfstate_t state = { 0 };
uint32_t ch = Q_DecodeUTF8( &state, in ); int ch = Q_DecodeUTF8( &state, in );
if( g_codepage == 1251 ) if( g_codepage == 1251 )
return Q_UnicodeToCP1251( ch ); return Q_UnicodeToCP1251( ch );
@@ -759,7 +759,7 @@ Con_DrawString
client version of routine 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 ); 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 ) void Con_Print( const char *txt )
{ {
static qboolean cr_pending = false; static int cr_pending = 0;
static qboolean colorstring = false; static char buf[MAX_PRINT_MSG];
static char buf[MAX_PRINT_MSG]; qboolean norefresh = false;
static int lastlength = 0; static int lastlength = 0;
static int bufpos = 0; static int bufpos = 0;
static int charpos = 0;
qboolean norefresh = false;
int c, mask = 0; int c, mask = 0;
// client not running // client not running
@@ -876,7 +873,7 @@ void Con_Print( const char *txt )
if( cr_pending ) if( cr_pending )
{ {
Con_DeleteLastLine(); Con_DeleteLastLine();
cr_pending = false; cr_pending = 0;
} }
c = *txt; c = *txt;
@@ -889,42 +886,23 @@ void Con_Print( const char *txt )
{ {
Con_AddLine( buf, bufpos, true ); Con_AddLine( buf, bufpos, true );
lastlength = CON_LINES_LAST().length; lastlength = CON_LINES_LAST().length;
cr_pending = true; cr_pending = 1;
bufpos = 0; bufpos = 0;
charpos = 0;
} }
break; break;
case '\n': case '\n':
Con_AddLine( buf, bufpos, true ); Con_AddLine( buf, bufpos, true );
lastlength = CON_LINES_LAST().length; lastlength = CON_LINES_LAST().length;
bufpos = 0; bufpos = 0;
charpos = 0;
break; break;
default: default:
buf[bufpos++] = c | mask; buf[bufpos++] = c | mask;
if(( bufpos >= sizeof( buf ) - 1 ) || bufpos >= ( con.linewidth - 1 ))
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 ))
{ {
Con_AddLine( buf, bufpos, true ); Con_AddLine( buf, bufpos, true );
lastlength = CON_LINES_LAST().length; lastlength = CON_LINES_LAST().length;
bufpos = 0; bufpos = 0;
charpos = 0;
} }
break; break;
} }
@@ -940,7 +918,6 @@ void Con_Print( const char *txt )
Con_AddLine( buf, bufpos, lastlength != 0 ); Con_AddLine( buf, bufpos, lastlength != 0 );
lastlength = 0; lastlength = 0;
bufpos = 0; bufpos = 0;
charpos = 0;
} }
// pump messages to avoid window hanging // pump messages to avoid window hanging
@@ -1490,16 +1467,6 @@ Handles history and console scrollback
*/ */
void Key_Console( int key ) 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 // ctrl-L clears screen
if( key == 'l' && Key_IsDown( K_CTRL )) if( key == 'l' && Key_IsDown( K_CTRL ))
{ {
@@ -1608,6 +1575,16 @@ void Key_Console( int key )
return; 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 // pass to the normal editline routine
Field_KeyDownEvent( &con.input, key ); Field_KeyDownEvent( &con.input, key );
} }
@@ -2115,7 +2092,10 @@ void Con_RunConsole( void )
} }
else 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" ); cls.accept_utf8 = !Q_stricmp( cl_charset.string, "utf-8" );
+95 -50
View File
@@ -43,6 +43,7 @@ static struct joy_axis_s
short val; short val;
short prevval; short prevval;
} joyaxis[MAX_AXES] = { 0 }; } joyaxis[MAX_AXES] = { 0 };
static byte currentbinding; // add posibility to remap keys, to place it in joykeys[]
static qboolean joy_initialized; static qboolean joy_initialized;
static CVAR_DEFINE_AUTO( joy_pitch, "100.0", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "joystick pitch sensitivity" ); 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_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, " 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" ); "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" ); 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 ) qboolean Joy_IsActive( void )
{ {
return joy_enable.value; return joy_found.value && 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 );
} }
/* /*
@@ -103,7 +81,7 @@ Joy_HatMotionEvent
DPad events DPad events
============ ============
*/ */
static void Joy_HatMotionEvent( int value ) void Joy_HatMotionEvent( byte hat, byte value )
{ {
struct struct
{ {
@@ -118,6 +96,9 @@ static void Joy_HatMotionEvent( int value )
}; };
int i; int i;
if( !joy_found.value )
return;
for( i = 0; i < ARRAYSIZE( keys ); i++ ) for( i = 0; i < ARRAYSIZE( keys ); i++ )
{ {
if( value & keys[i].mask ) 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_SIDE );
val |= Joy_GetHatValueForAxis( JOY_AXIS_FWD ); val |= Joy_GetHatValueForAxis( JOY_AXIS_FWD );
Joy_HatMotionEvent( val ); Joy_HatMotionEvent( 0, val );
} }
} }
@@ -255,9 +236,23 @@ Joy_AxisMotionEvent
Axis events 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; return;
if( value == joyaxis[engineAxis].val ) 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 *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; *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; *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; *dyaw += joy_yaw.value * (float)joyaxis[JOY_AXIS_YAW ].val/(float)SHRT_MAX * host.realframetime;
} #endif
static void Joy_CalibrateGyro_f( void )
{
if( !joy_have_gyro.value )
{
Con_Printf( "Current active gamepad doesn't have gyroscope\n" );
return;
}
Platform_CalibrateGamepadGyro();
} }
/* /*
@@ -341,8 +383,6 @@ Main init procedure
*/ */
void Joy_Init( void ) 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_pitch );
Cvar_RegisterVariable( &joy_yaw ); Cvar_RegisterVariable( &joy_yaw );
Cvar_RegisterVariable( &joy_side ); Cvar_RegisterVariable( &joy_side );
@@ -362,9 +402,11 @@ void Joy_Init( void )
Cvar_RegisterVariable( &joy_yaw_deadzone ); Cvar_RegisterVariable( &joy_yaw_deadzone );
Cvar_RegisterVariable( &joy_axis_binding ); 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 ); Cvar_RegisterVariable( &joy_enable );
// renamed from -nojoy to -noenginejoy to not conflict with // renamed from -nojoy to -noenginejoy to not conflict with
@@ -375,7 +417,7 @@ void Joy_Init( void )
return; return;
} }
Platform_JoyInit(); Cvar_FullSet( "joy_found", va( "%d", Platform_JoyInit( joy_index.value )), FCVAR_READ_ONLY );
joy_initialized = true; joy_initialized = true;
} }
@@ -389,5 +431,8 @@ Shutdown joystick code
*/ */
void Joy_Shutdown( void ) void Joy_Shutdown( void )
{ {
Platform_JoyShutdown(); if( joy_initialized )
{
Cvar_FullSet( "joy_found", 0, FCVAR_READ_ONLY );
}
} }
+686 -731
View File
File diff suppressed because it is too large Load Diff
+4 -2
View File
@@ -332,7 +332,7 @@ static void IN_MouseMove( void )
if( !in_mouseinitialized ) if( !in_mouseinitialized )
return; return;
if( Touch_WantVisibleCursor( )) if( Touch_Emulated( ))
{ {
// touch emulation overrides all input // touch emulation overrides all input
Touch_KeyEvent( 0, 0 ); Touch_KeyEvent( 0, 0 );
@@ -363,7 +363,7 @@ void IN_MouseEvent( int key, int down )
else ClearBits( in_mstate, BIT( key )); else ClearBits( in_mstate, BIT( key ));
// touch emulation overrides all input // touch emulation overrides all input
if( Touch_WantVisibleCursor( )) if( Touch_Emulated( ))
{ {
Touch_KeyEvent( K_MOUSE1 + key, down ); Touch_KeyEvent( K_MOUSE1 + key, down );
} }
@@ -633,6 +633,8 @@ Called every frame, even if not generating commands
*/ */
void Host_InputFrame( void ) void Host_InputFrame( void )
{ {
Sys_SendKeyEvents ();
IN_Commands(); IN_Commands();
IN_MouseMove(); IN_MouseMove();
+10 -12
View File
@@ -74,6 +74,7 @@ void Touch_ResetDefaultButtons( void );
int IN_TouchEvent( touchEventType type, int fingerID, float x, float y, float dx, float dy ); int IN_TouchEvent( touchEventType type, int fingerID, float x, float y, float dx, float dy );
void Touch_KeyEvent( int key, int down ); void Touch_KeyEvent( int key, int down );
qboolean Touch_WantVisibleCursor( void ); qboolean Touch_WantVisibleCursor( void );
qboolean Touch_Emulated( void );
void Touch_NotifyResize( void ); void Touch_NotifyResize( void );
// //
@@ -103,21 +104,18 @@ typedef enum engineAxis_e
JOY_AXIS_NULL JOY_AXIS_NULL
} engineAxis_t; } 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 ); qboolean Joy_IsActive( void );
void Joy_SetCapabilities( qboolean have_gyro ); void Joy_HatMotionEvent( byte hat, byte value );
void Joy_SetCalibrationState( joy_calibration_state_t state ); void Joy_AxisMotionEvent( byte axis, short value );
void Joy_AxisMotionEvent( engineAxis_t engineAxis, short value ); void Joy_KnownAxisMotionEvent( engineAxis_t engineAxis, short value );
void Joy_GyroEvent( vec3_t data ); 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_FinalizeMove( float *fw, float *side, float *dpitch, float *dyaw );
void Joy_Init( void ); void Joy_Init( void );
void Joy_Shutdown( void ); void Joy_Shutdown( void );
void Joy_EnableTextInput(qboolean enable, qboolean force);
#endif//INPUT_H #endif//INPUT_H
+83 -76
View File
@@ -34,13 +34,13 @@ typedef struct keyname_s
const char *binding; // default bind const char *binding; // default bind
} keyname_t; } keyname_t;
static enginekey_t keys[256]; enginekey_t keys[256];
static const keyname_t keynames[] = keyname_t keynames[] =
{ {
{"TAB", K_TAB, "" }, {"TAB", K_TAB, "" },
{"ENTER", K_ENTER, "" }, {"ENTER", K_ENTER, "" },
{"ESCAPE", K_ESCAPE, "cancelselect" }, // hardcoded {"ESCAPE", K_ESCAPE, "escape" }, // hardcoded
{"SPACE", K_SPACE, "+jump" }, {"SPACE", K_SPACE, "+jump" },
{"BACKSPACE", K_BACKSPACE, "" }, {"BACKSPACE", K_BACKSPACE, "" },
{"UPARROW", K_UPARROW, "+forward" }, {"UPARROW", K_UPARROW, "+forward" },
@@ -51,7 +51,7 @@ static const keyname_t keynames[] =
{"CTRL", K_CTRL, "+attack" }, {"CTRL", K_CTRL, "+attack" },
{"SHIFT", K_SHIFT, "+speed" }, {"SHIFT", K_SHIFT, "+speed" },
{"CAPSLOCK", K_CAPSLOCK, "" }, {"CAPSLOCK", K_CAPSLOCK, "" },
{"SCROLLOCK", K_SCROLLLOCK, "" }, {"SCROLLOCK", K_SCROLLOCK, "" },
{"F1", K_F1, "cmd help" }, {"F1", K_F1, "cmd help" },
{"F2", K_F2, "menu_savegame" }, {"F2", K_F2, "menu_savegame" },
{"F3", K_F3, "menu_loadgame" }, {"F3", K_F3, "menu_loadgame" },
@@ -106,7 +106,7 @@ static const keyname_t keynames[] =
{"Y_BUTTON", K_Y_BUTTON, "impulse 100"}, // Flashlight {"Y_BUTTON", K_Y_BUTTON, "impulse 100"}, // Flashlight
{"BACK", K_BACK_BUTTON, "pause"}, // Menu {"BACK", K_BACK_BUTTON, "pause"}, // Menu
{"MODE", K_MODE_BUTTON, ""}, {"MODE", K_MODE_BUTTON, ""},
{"START", K_START_BUTTON, "cancelselect"}, {"START", K_START_BUTTON, "escape"},
{"STICK1", K_LSTICK, "+speed"}, {"STICK1", K_LSTICK, "+speed"},
{"STICK2", K_RSTICK, "+duck"}, {"STICK2", K_RSTICK, "+duck"},
{"L1_BUTTON", K_L1_BUTTON, "+duck"}, {"L1_BUTTON", K_L1_BUTTON, "+duck"},
@@ -139,6 +139,7 @@ static const keyname_t keynames[] =
// raw semicolon seperates commands // raw semicolon seperates commands
{"SEMICOLON", ';', "" }, {"SEMICOLON", ';', "" },
{NULL, 0, NULL },
}; };
static void OSK_EnableTextInput( qboolean enable, qboolean force ); static void OSK_EnableTextInput( qboolean enable, qboolean force );
@@ -171,25 +172,48 @@ the K_* names are matched up.
to be configured even if they don't have defined names. to be configured even if they don't have defined names.
=================== ===================
*/ */
static int Key_StringToKeynum( const char *str ) int Key_StringToKeynum( const char *str )
{ {
int i; keyname_t *kn;
if( !str || !str[0] ) if( !str || !str[0] ) return -1;
return -1; if( !str[1] ) return str[0];
if( !str[1] )
return str[0];
// check for hex code // check for hex code
if( str[0] == '0' && str[1] == 'x' && Q_strlen( str ) == 4 ) if( str[0] == '0' && str[1] == 'x' && Q_strlen( str ) == 4 )
return COM_Nibble( str[2] ) << 4 | COM_Nibble( str[3] ); {
int n1, n2;
n1 = str[2];
if( n1 >= '0' && n1 <= '9' )
{
n1 -= '0';
}
else if( n1 >= 'a' && n1 <= 'f' )
{
n1 = n1 - 'a' + 10;
}
else n1 = 0;
n2 = str[3];
if( n2 >= '0' && n2 <= '9' )
{
n2 -= '0';
}
else if( n2 >= 'a' && n2 <= 'f' )
{
n2 = n2 - 'a' + 10;
}
else n2 = 0;
return n1 * 16 + n2;
}
// scan for a text match // scan for a text match
for( i = 0; i < ARRAYSIZE( keynames ); i++ ) for( kn = keynames; kn->name; kn++ )
{ {
if( !Q_stricmp( str, keynames[i].name )) if( !Q_stricmp( str, kn->name ))
return keynames[i].keynum; return kn->keynum;
} }
return -1; return -1;
@@ -205,17 +229,15 @@ given keynum.
*/ */
const char *Key_KeynumToString( int keynum ) const char *Key_KeynumToString( int keynum )
{ {
keyname_t *kn;
static char tinystr[5]; static char tinystr[5];
int i, j; int i, j;
if( keynum == -1 ) if ( keynum == -1 ) return "<KEY NOT FOUND>";
return "<KEY NOT FOUND>"; if ( keynum < 0 || keynum > 255 ) return "<OUT OF RANGE>";
if( keynum < 0 || keynum > 255 )
return "<OUT OF RANGE>";
// check for printable ascii (don't use quote) // check for printable ascii (don't use quote)
if( keynum > 32 && keynum < 127 && keynum != '"' && keynum != ';' && keynum != K_SCROLLLOCK ) if( keynum > 32 && keynum < 127 && keynum != '"' && keynum != ';' && keynum != K_SCROLLOCK )
{ {
tinystr[0] = keynum; tinystr[0] = keynum;
tinystr[1] = 0; tinystr[1] = 0;
@@ -223,10 +245,10 @@ const char *Key_KeynumToString( int keynum )
} }
// check for a key string // check for a key string
for( i = 0; i < ARRAYSIZE( keynames ); i++ ) for( kn = keynames; kn->name; kn++ )
{ {
if( keynum == keynames[i].keynum ) if( keynum == kn->keynum )
return keynames[i].name; return kn->name;
} }
// make a hex string // make a hex string
@@ -279,7 +301,7 @@ const char *Key_GetBinding( int keynum )
Key_GetKey Key_GetKey
=================== ===================
*/ */
static int Key_GetKey( const char *pBinding ) int Key_GetKey( const char *pBinding )
{ {
int i, len; int i, len;
const char *p; const char *p;
@@ -305,17 +327,6 @@ static int Key_GetKey( const char *pBinding )
return -1; return -1;
} }
/*
=============
Key_LookupBinding
=============
*/
const char *Key_LookupBinding( const char *pBinding )
{
return Key_KeynumToString( Key_GetKey( pBinding ));
}
/* /*
=================== ===================
Key_Unbind_f Key_Unbind_f
@@ -339,12 +350,6 @@ static void Key_Unbind_f( void )
return; return;
} }
if( b == K_ESCAPE )
{
Con_Printf( "Can't unbind ESCAPE key\n" );
return;
}
Key_SetBinding( b, "" ); Key_SetBinding( b, "" );
} }
@@ -364,8 +369,8 @@ static void Key_Unbindall_f( void )
} }
// set some defaults // set some defaults
Key_SetBinding( K_ESCAPE, "cancelselect" ); Key_SetBinding( K_ESCAPE, "escape" );
Key_SetBinding( K_START_BUTTON, "cancelselect" ); Key_SetBinding( K_START_BUTTON, "escape" );
} }
/* /*
@@ -375,6 +380,7 @@ Key_Reset_f
*/ */
static void Key_Reset_f( void ) static void Key_Reset_f( void )
{ {
keyname_t *kn;
int i; int i;
// clear all keys first // clear all keys first
@@ -385,8 +391,8 @@ static void Key_Reset_f( void )
} }
// apply default values // apply default values
for( i = 0; i < ARRAYSIZE( keynames ); i++ ) for( kn = keynames; kn->name; kn++ )
Key_SetBinding( keynames[i].keynum, keynames[i].binding ); Key_SetBinding( kn->keynum, kn->binding );
} }
/* /*
@@ -494,7 +500,7 @@ Key_Init
*/ */
void Key_Init( void ) void Key_Init( void )
{ {
int i; keyname_t *kn;
// register our functions // register our functions
Cmd_AddRestrictedCommand( "bind", Key_Bind_f, "binds a command to the specified key in bindmap" ); Cmd_AddRestrictedCommand( "bind", Key_Bind_f, "binds a command to the specified key in bindmap" );
@@ -505,8 +511,7 @@ void Key_Init( void )
Cmd_AddCommand( "makehelp", Key_EnumCmds_f, "write help.txt that contains all console cvars and cmds" ); Cmd_AddCommand( "makehelp", Key_EnumCmds_f, "write help.txt that contains all console cvars and cmds" );
// setup default binding. "unbindall" from config.cfg will be reset it // setup default binding. "unbindall" from config.cfg will be reset it
for( i = 0; i < ARRAYSIZE( keynames ); i++ ) for( kn = keynames; kn->name; kn++ ) Key_SetBinding( kn->keynum, kn->binding );
Key_SetBinding( keynames[i].keynum, keynames[i].binding );
Cvar_RegisterVariable( &osk_enable ); Cvar_RegisterVariable( &osk_enable );
Cvar_RegisterVariable( &key_rotate ); Cvar_RegisterVariable( &key_rotate );
@@ -726,31 +731,35 @@ void GAME_EXPORT Key_Event( int key, int down )
return; // handled in client.dll return; // handled in client.dll
} }
break; break;
default: case key_message:
break; 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;
} }
} }
if( cls.key_dest == key_menu ) if( cls.key_dest == key_menu )
{ {
// classic Xash3D menus don't have an extension that tells engine // only non printable keys passed
// to enable text input
if( !gameui.use_extended_api ) if( !gameui.use_extended_api )
{
// we don't know if menu wants text input or not
// enable it unconditionally
Key_EnableTextInput( true, false ); Key_EnableTextInput( true, false );
//pass printable chars for old menus
// pass this key to the menu, if printable if( !gameui.use_extended_api && !host.textmode && down && ( key >= 32 ) && ( key <= 'z' ) )
if( !host.textmode && down && ( key >= 32 ) && ( key <= 'z' )) {
if( Key_IsDown( K_SHIFT ) )
{ {
if( Key_IsDown( K_SHIFT )) key += 'A' - 'a';
key += 'A' - 'a';
UI_CharEvent( key );
} }
UI_CharEvent( key );
} }
UI_KeyEvent( key, down ); UI_KeyEvent( key, down );
return; return;
} }
@@ -846,14 +855,11 @@ void GAME_EXPORT Key_ClearStates( void )
int i; int i;
// don't clear keys during changelevel // don't clear keys during changelevel
if( cls.changelevel ) if( cls.changelevel ) return;
return;
for( i = 0; i < 256; i++ ) for( i = 0; i < 256; i++ )
{ {
if( i >= K_MOUSE1 && i <= K_MOUSE5 ) if( keys[i].down )
IN_MouseEvent( i - K_MOUSE1, false );
else
Key_Event( i, false ); Key_Event( i, false );
keys[i].down = 0; keys[i].down = 0;
@@ -903,16 +909,17 @@ A helper function if platform input doesn't support text mode properly
*/ */
int Key_ToUpper( int keynum ) int Key_ToUpper( int keynum )
{ {
keynum = Q_toupper( keynum );
if( keynum == '-' ) if( keynum == '-' )
return '_'; keynum = '_';
if( keynum == '=' ) if( keynum == '=' )
return '+'; keynum = '+';
if( keynum == ';' ) if( keynum == ';' )
return ':'; keynum = ':';
if( keynum == '\'' ) if( keynum == '\'' )
return '"'; keynum = '"';
return Q_toupper( keynum ); return keynum;
} }
/* On-screen keyboard: /* On-screen keyboard:
@@ -1097,7 +1104,7 @@ static qboolean OSK_KeyEvent( int key, int down )
/* /*
============= =============
OSK_EnableTextInput Joy_EnableTextInput
Enables built-in IME Enables built-in IME
============= =============
+17 -33
View File
@@ -470,16 +470,16 @@ out_free:
* This is a stack of the clipnodes we have traversed * This is a stack of the clipnodes we have traversed
* "sides" indicates which side we went down each time * "sides" indicates which side we went down each time
*/ */
static int node_stack[MAX_CLIPNODE_DEPTH]; static mclipnode_t *node_stack[MAX_CLIPNODE_DEPTH];
static int side_stack[MAX_CLIPNODE_DEPTH]; static int side_stack[MAX_CLIPNODE_DEPTH];
static uint node_stack_depth; static uint node_stack_depth;
static void push_node( int nodenum, int side ) static void push_node( mclipnode_t *node, int side )
{ {
if( node_stack_depth == MAX_CLIPNODE_DEPTH ) if( node_stack_depth == MAX_CLIPNODE_DEPTH )
Host_Error( "node stack overflow\n" ); Host_Error( "node stack overflow\n" );
node_stack[node_stack_depth] = nodenum; node_stack[node_stack_depth] = node;
side_stack[node_stack_depth] = side; side_stack[node_stack_depth] = side;
node_stack_depth++; node_stack_depth++;
} }
@@ -502,27 +502,22 @@ static void free_hull_polys( hullnode_t *hull_polys )
} }
} }
static void hull_windings_r( hull_t *hull, int nodenum, hullnode_t *polys, hull_model_t *model ); static void hull_windings_r( hull_t *hull, mclipnode_t *node, hullnode_t *polys, hull_model_t *model );
static void do_hull_recursion( hull_t *hull, int nodenum, int side, hullnode_t *polys, hull_model_t *model ) static void do_hull_recursion( hull_t *hull, mclipnode_t *node, int side, hullnode_t *polys, hull_model_t *model )
{ {
winding_t *w, *next; winding_t *w, *next;
int childnum;
if( world.version == QBSP2_VERSION ) if( node->children[side] >= 0 )
childnum = hull->clipnodes32[nodenum].children[side];
else
childnum = hull->clipnodes16[nodenum].children[side];
if( childnum >= 0 )
{ {
push_node( nodenum, side ); mclipnode_t *child = hull->clipnodes + node->children[side];
hull_windings_r( hull, childnum, polys, model ); push_node( node, side );
hull_windings_r( hull, child, polys, model );
pop_node(); pop_node();
} }
else else
{ {
switch( childnum ) switch( node->children[side] )
{ {
case CONTENTS_EMPTY: case CONTENTS_EMPTY:
case CONTENTS_WATER: case CONTENTS_WATER:
@@ -547,25 +542,20 @@ static void do_hull_recursion( hull_t *hull, int nodenum, int side, hullnode_t *
} }
break; break;
default: default:
Host_Error( "bad contents: %i\n", childnum ); Host_Error( "bad contents: %i\n", node->children[side] );
break; break;
} }
} }
} }
static void hull_windings_r( hull_t *hull, int nodenum, hullnode_t *polys, hull_model_t *model ) static void hull_windings_r( hull_t *hull, mclipnode_t *node, hullnode_t *polys, hull_model_t *model )
{ {
mplane_t *plane; mplane_t *plane = hull->planes + node->planenum;
hullnode_t frontlist = LIST_HEAD_INIT( frontlist ); hullnode_t frontlist = LIST_HEAD_INIT( frontlist );
hullnode_t backlist = LIST_HEAD_INIT( backlist ); hullnode_t backlist = LIST_HEAD_INIT( backlist );
winding_t *w, *next, *front, *back; winding_t *w, *next, *front, *back;
int i; int i;
if( world.version == QBSP2_VERSION )
plane = hull->planes + hull->clipnodes32[nodenum].planenum;
else
plane = hull->planes + hull->clipnodes16[nodenum].planenum;
list_for_each_entry_safe( w, next, polys, chain ) list_for_each_entry_safe( w, next, polys, chain )
{ {
// PARANIOA - PAIR CHECK // PARANIOA - PAIR CHECK
@@ -611,13 +601,7 @@ static void hull_windings_r( hull_t *hull, int nodenum, hullnode_t *polys, hull_
for( i = 0; w && i < node_stack_depth; i++ ) for( i = 0; w && i < node_stack_depth; i++ )
{ {
mplane_t *p; mplane_t *p = hull->planes + node_stack[i]->planenum;
if( world.version == QBSP2_VERSION )
p = hull->planes + hull->clipnodes32[node_stack[i]].planenum;
else
p = hull->planes + hull->clipnodes16[node_stack[i]].planenum;
w = winding_clip( w, p, false, side_stack[i], 0.00001 ); w = winding_clip( w, p, false, side_stack[i], 0.00001 );
} }
@@ -641,8 +625,8 @@ static void hull_windings_r( hull_t *hull, int nodenum, hullnode_t *polys, hull_
Con_Printf( S_WARN "new winding was clipped away!\n" ); Con_Printf( S_WARN "new winding was clipped away!\n" );
} }
do_hull_recursion( hull, nodenum, 0, &frontlist, model ); do_hull_recursion( hull, node, 0, &frontlist, model );
do_hull_recursion( hull, nodenum, 1, &backlist, model ); do_hull_recursion( hull, node, 1, &backlist, model );
} }
static void remove_paired_polys( hull_model_t *model ) static void remove_paired_polys( hull_model_t *model )
@@ -671,7 +655,7 @@ static void make_hull_windings( hull_t *hull, hull_model_t *model )
if( hull->planes != NULL ) if( hull->planes != NULL )
{ {
hull_windings_r( hull, hull->firstclipnode, &head, model ); hull_windings_r( hull, hull->clipnodes + hull->firstclipnode, &head, model );
remove_paired_polys( model ); remove_paired_polys( model );
} }
Con_Reportf( "%i hull polys\n", model->num_polys ); Con_Reportf( "%i hull polys\n", model->num_polys );
+1 -12
View File
@@ -181,11 +181,6 @@ static void pfnCvar_FullSet( const char *var_name, const char *value, int flags
Cvar_FullSet( var_name, value, flags | FCVAR_REFDLL ); Cvar_FullSet( var_name, value, flags | FCVAR_REFDLL );
} }
static int Cmd_AddRefCommand( const char *cmd_name, xcommand_t function, const char *description )
{
return Cmd_AddCommandEx( cmd_name, function, description, CMD_REFDLL, __func__ );
}
static void pfnStudioEvent( const mstudioevent_t *event, const cl_entity_t *e ) static void pfnStudioEvent( const mstudioevent_t *event, const cl_entity_t *e )
{ {
clgame.dllFuncs.pfnStudioEvent( event, e ); clgame.dllFuncs.pfnStudioEvent( event, e );
@@ -300,12 +295,6 @@ static qboolean R_Init_Video_( const int type )
return R_Init_Video( type ); return R_Init_Video( type );
} }
static mleaf_t *pfnMod_PointInLeaf( const vec3_t p, mnode_t *node )
{
// FIXME: get rid of this on next RefAPI update
return Mod_PointInLeaf( p, node, cl.models[1] );
}
static const ref_api_t gEngfuncs = static const ref_api_t gEngfuncs =
{ {
pfnEngineGetParm, pfnEngineGetParm,
@@ -346,7 +335,7 @@ static const ref_api_t gEngfuncs =
Mod_SampleSizeForFace, Mod_SampleSizeForFace,
Mod_BoxVisible, Mod_BoxVisible,
pfnMod_PointInLeaf, Mod_PointInLeaf,
R_DrawWorldHull, R_DrawWorldHull,
R_DrawModelHull, R_DrawModelHull,
+1 -1
View File
@@ -312,7 +312,7 @@ static int DLY_Init( int idelay, float delay )
cur = &rgsxdly[idelay]; cur = &rgsxdly[idelay];
cur->cdelaysamplesmax = ((int)(delay * idsp_dma_speed) << sxhires) + 1; cur->cdelaysamplesmax = ((int)(delay * idsp_dma_speed) << sxhires) + 1;
cur->lpdelayline = (int *)Mem_Calloc( sndpool, cur->cdelaysamplesmax * sizeof( int )); cur->lpdelayline = (int *)Z_Calloc( cur->cdelaysamplesmax * sizeof( int ));
cur->xfade = 0; cur->xfade = 0;
// init modulation // init modulation
+9 -10
View File
@@ -107,18 +107,17 @@ S_CreateDefaultSound
*/ */
static wavdata_t *S_CreateDefaultSound( void ) static wavdata_t *S_CreateDefaultSound( void )
{ {
wavdata_t *sc; wavdata_t *sc;
uint samples = SOUND_DMA_SPEED;
uint channels = 1;
uint width = 2;
size_t size = samples * width * channels;
sc = Mem_Calloc( sndpool, sizeof( wavdata_t ) + size ); sc = Mem_Calloc( sndpool, sizeof( wavdata_t ));
sc->width = width;
sc->channels = channels; sc->width = 2;
sc->channels = 1;
sc->loopStart = 0;
sc->rate = SOUND_DMA_SPEED; sc->rate = SOUND_DMA_SPEED;
sc->samples = samples; sc->samples = SOUND_DMA_SPEED;
sc->size = size; sc->size = sc->samples * sc->width * sc->channels;
sc->buffer = Mem_Calloc( sndpool, sc->size );
return sc; return sc;
} }
+85 -8
View File
@@ -996,7 +996,7 @@ static void S_UpdateAmbientSounds( void )
// calc ambient sound levels // calc ambient sound levels
if( !cl.worldmodel ) return; if( !cl.worldmodel ) return;
leaf = Mod_PointInLeaf( s_listener.origin, cl.worldmodel->nodes, cl.worldmodel ); leaf = Mod_PointInLeaf( s_listener.origin, cl.worldmodel->nodes );
if( !leaf || !s_ambient_level.value ) if( !leaf || !s_ambient_level.value )
{ {
@@ -1207,6 +1207,86 @@ void S_RawSamples( uint samples, uint rate, word width, word channels, const byt
S_RawEntSamples( entnum, samples, rate, width, channels, data, snd_vol ); S_RawEntSamples( entnum, samples, rate, width, channels, data, snd_vol );
} }
/*
===================
S_PositionedRawSamples
===================
*/
void S_StreamAviSamples( void *Avi, int entnum, float fvol, float attn, float synctime )
{
int bufferSamples;
int fileSamples;
byte raw[MAX_RAW_SAMPLES];
float duration = 0.0f;
int r, fileBytes;
rawchan_t *ch = NULL;
if( !dma.initialized || s_listener.paused || !CL_IsInGame( ))
return;
if( entnum < 0 || entnum >= GI->max_edicts )
return;
if( !( ch = S_FindRawChannel( entnum, true )))
return;
if( ch->sound_info.rate == 0 )
{
if( !AVI_GetAudioInfo( Avi, &ch->sound_info ))
return; // no audiotrack
}
ch->master_vol = bound( 0, fvol * 255, 255 );
ch->dist_mult = (attn / SND_CLIP_DISTANCE);
// see how many samples should be copied into the raw buffer
if( ch->s_rawend < soundtime )
ch->s_rawend = soundtime;
// position is changed, synchronization is lost etc
if( fabs( ch->oldtime - synctime ) > s_mixahead.value )
ch->sound_info.loopStart = AVI_TimeToSoundPosition( Avi, synctime * 1000 );
ch->oldtime = synctime; // keep actual time
while( ch->s_rawend < soundtime + ch->max_samples )
{
wavdata_t *info = &ch->sound_info;
bufferSamples = ch->max_samples - (ch->s_rawend - soundtime);
// decide how much data needs to be read from the file
fileSamples = bufferSamples * ((float)info->rate / SOUND_DMA_SPEED );
if( fileSamples <= 1 ) return; // no more samples need
// our max buffer size
fileBytes = fileSamples * ( info->width * info->channels );
if( fileBytes > sizeof( raw ))
{
fileBytes = sizeof( raw );
fileSamples = fileBytes / ( info->width * info->channels );
}
// read audio stream
r = AVI_GetAudioChunk( Avi, raw, info->loopStart, fileBytes );
info->loopStart += r; // advance play position
if( r < fileBytes )
{
fileBytes = r;
fileSamples = r / ( info->width * info->channels );
}
if( r > 0 )
{
// add to raw buffer
ch->s_rawend = S_RawSamplesStereo( ch->rawsamples, ch->s_rawend, ch->max_samples,
fileSamples, info->rate, info->width, info->channels, raw );
}
else break; // no more samples for this frame
}
}
/* /*
=================== ===================
S_FreeIdleRawChannels S_FreeIdleRawChannels
@@ -1864,8 +1944,7 @@ qboolean S_Init( void )
Cmd_AddCommand( "play2", S_Play2_f, "playing a group of specified sound files" ); // nehahra stuff Cmd_AddCommand( "play2", S_Play2_f, "playing a group of specified sound files" ); // nehahra stuff
Cmd_AddCommand( "playvol", S_PlayVol_f, "playing a specified sound file with specified volume" ); Cmd_AddCommand( "playvol", S_PlayVol_f, "playing a specified sound file with specified volume" );
Cmd_AddCommand( "stopsound", S_StopSound_f, "stop all sounds" ); Cmd_AddCommand( "stopsound", S_StopSound_f, "stop all sounds" );
// HLU SDK have command with the same name Cmd_AddCommand( "music", S_Music_f, "starting a background track" );
Cmd_AddCommandWithFlags( "music", S_Music_f, "starting a background track", CMD_OVERRIDABLE );
Cmd_AddCommand( "soundlist", S_SoundList_f, "display loaded sounds" ); Cmd_AddCommand( "soundlist", S_SoundList_f, "display loaded sounds" );
Cmd_AddCommand( "s_info", S_SoundInfo_f, "print sound system information" ); Cmd_AddCommand( "s_info", S_SoundInfo_f, "print sound system information" );
Cmd_AddCommand( "s_fade", S_SoundFade_f, "fade all sounds then stop all" ); Cmd_AddCommand( "s_fade", S_SoundFade_f, "fade all sounds then stop all" );
@@ -1874,15 +1953,14 @@ qboolean S_Init( void )
Cmd_AddCommand( "spk", S_SayReliable_f, "reliable play a specified sententce" ); Cmd_AddCommand( "spk", S_SayReliable_f, "reliable play a specified sententce" );
Cmd_AddCommand( "speak", S_Say_f, "playing a specified sententce" ); Cmd_AddCommand( "speak", S_Say_f, "playing a specified sententce" );
sndpool = Mem_AllocPool( "Sound Zone" );
dma.backendName = "None"; dma.backendName = "None";
if( !SNDDMA_Init( )) if( !SNDDMA_Init( ) )
{ {
Con_Printf( "Audio: sound system can't be initialized\n" ); Con_Printf( "Audio: sound system can't be initialized\n" );
Mem_FreePool( &sndpool );
return false; return false;
} }
sndpool = Mem_AllocPool( "Sound Zone" );
soundtime = 0; soundtime = 0;
paintedtime = 0; paintedtime = 0;
@@ -1909,8 +1987,7 @@ void S_Shutdown( void )
Cmd_RemoveCommand( "play" ); Cmd_RemoveCommand( "play" );
Cmd_RemoveCommand( "playvol" ); Cmd_RemoveCommand( "playvol" );
Cmd_RemoveCommand( "stopsound" ); Cmd_RemoveCommand( "stopsound" );
if( Cmd_Exists( "music" )) Cmd_RemoveCommand( "music" );
Cmd_RemoveCommand( "music" );
Cmd_RemoveCommand( "soundlist" ); Cmd_RemoveCommand( "soundlist" );
Cmd_RemoveCommand( "s_info" ); Cmd_RemoveCommand( "s_info" );
Cmd_RemoveCommand( "s_fade" ); Cmd_RemoveCommand( "s_fade" );
+1 -2
View File
@@ -16,7 +16,6 @@ GNU General Public License for more details.
#include "common.h" #include "common.h"
#include "sound.h" #include "sound.h"
#include "client.h" #include "client.h"
#include "soundlib.h"
static bg_track_t s_bgTrack; static bg_track_t s_bgTrack;
static musicfade_t musicfade; // controlled by game dlls static musicfade_t musicfade; // controlled by game dlls
@@ -213,7 +212,7 @@ void S_StreamBackgroundTrack( void )
while( ch->s_rawend < soundtime + ch->max_samples ) while( ch->s_rawend < soundtime + ch->max_samples )
{ {
const stream_t *info = s_bgTrack.stream; wavdata_t *info = FS_StreamInfo( s_bgTrack.stream );
bufferSamples = ch->max_samples - (ch->s_rawend - soundtime); bufferSamples = ch->max_samples - (ch->s_rawend - soundtime);
+1 -1
View File
@@ -557,7 +557,7 @@ static void VOX_ReadSentenceFile_( byte *buf, fs_offset_t size )
int index = cszrawsentences; int index = cszrawsentences;
int size = strlen( name ) + strlen( value ) + 2; int size = strlen( name ) + strlen( value ) + 2;
rgpszrawsentence[index] = Mem_Malloc( sndpool, size ); rgpszrawsentence[index] = Mem_Malloc( host.mempool, size );
memcpy( rgpszrawsentence[index], name, size ); memcpy( rgpszrawsentence[index], name, size );
rgpszrawsentence[index][size - 1] = 0; rgpszrawsentence[index][size - 1] = 0;
cszrawsentences++; cszrawsentences++;
+1 -2
View File
@@ -114,6 +114,7 @@ typedef struct rawchan_s
vec3_t origin; // only use if fixed_origin is set vec3_t origin; // only use if fixed_origin is set
volatile uint s_rawend; volatile uint s_rawend;
float oldtime; // catch time jumps float oldtime; // catch time jumps
wavdata_t sound_info; // advance play position
size_t max_samples; // buffer length size_t max_samples; // buffer length
portable_samplepair_t rawsamples[]; // variable sized portable_samplepair_t rawsamples[]; // variable sized
} rawchan_t; } rawchan_t;
@@ -170,8 +171,6 @@ typedef struct
int source; // may be game, menu, etc int source; // may be game, menu, etc
} bg_track_t; } bg_track_t;
typedef int sound_t;
//==================================================================== //====================================================================
#define MAX_DYNAMIC_CHANNELS (60 + NUM_AMBIENTS) #define MAX_DYNAMIC_CHANNELS (60 + NUM_AMBIENTS)
+34 -9
View File
@@ -29,20 +29,17 @@ static void Sound_Reset( void )
static MALLOC_LIKE( FS_FreeSound, 1 ) wavdata_t *SoundPack( void ) static MALLOC_LIKE( FS_FreeSound, 1 ) wavdata_t *SoundPack( void )
{ {
wavdata_t *pack = Mem_Malloc( host.soundpool, sizeof( *pack ) + sound.size ); wavdata_t *pack = Mem_Calloc( host.soundpool, sizeof( wavdata_t ));
pack->buffer = sound.wav;
pack->width = sound.width;
pack->rate = sound.rate;
pack->type = sound.type;
pack->size = sound.size; pack->size = sound.size;
pack->loopStart = sound.loopstart; pack->loopStart = sound.loopstart;
pack->samples = sound.samples; pack->samples = sound.samples;
pack->type = sound.type;
pack->flags = sound.flags;
pack->rate = sound.rate;
pack->width = sound.width;
pack->channels = sound.channels; pack->channels = sound.channels;
memcpy( pack->buffer, sound.wav, sound.size ); pack->flags = sound.flags;
Mem_Free( sound.wav );
sound.wav = NULL;
return pack; return pack;
} }
@@ -135,6 +132,7 @@ free WAV buffer
void FS_FreeSound( wavdata_t *pack ) void FS_FreeSound( wavdata_t *pack )
{ {
if( !pack ) return; if( !pack ) return;
if( pack->buffer ) Mem_Free( pack->buffer );
Mem_Free( pack ); Mem_Free( pack );
} }
@@ -201,6 +199,33 @@ stream_t *FS_OpenStream( const char *filename )
return stream; return stream;
} }
/*
================
FS_StreamInfo
get basic stream info
================
*/
wavdata_t *FS_StreamInfo( stream_t *stream )
{
static wavdata_t info;
if( !stream ) return NULL;
// fill structure
info.loopStart = 0;
info.rate = stream->rate;
info.width = stream->width;
info.channels = stream->channels;
info.flags = SOUND_STREAM;
info.size = stream->size;
info.buffer = NULL;
info.samples = 0; // not actual for streams
info.type = stream->type;
return &info;
}
/* /*
================ ================
FS_ReadStream FS_ReadStream
+40 -85
View File
@@ -25,29 +25,20 @@ GNU General Public License for more details.
#define VGUI_MAX_TEXTURES 1024 #define VGUI_MAX_TEXTURES 1024
typedef struct vgui_reusable_texture_s
{
int gl_texturenum;
byte hash[16];
} vgui_reusable_texture_t;
typedef struct vgui_static_s typedef struct vgui_static_s
{ {
qboolean initialized; qboolean initialized;
VGUI_DefaultCursor cursor; VGUI_DefaultCursor cursor;
vguiapi_t dllFuncs; vguiapi_t dllFuncs;
vgui_reusable_texture_t *textures; int textures[VGUI_MAX_TEXTURES];
int texture_id; int texture_id;
int max_textures;
int bound_texture; int bound_texture;
byte color[4]; byte color[4];
qboolean enable_texture; qboolean enable_texture;
HINSTANCE hInstance; HINSTANCE hInstance;
poolhandle_t mempool;
enum VGUI_KeyCode virtualKeyTrans[256]; enum VGUI_KeyCode virtualKeyTrans[256];
} vgui_static_t; } vgui_static_t;
@@ -58,16 +49,9 @@ static CVAR_DEFINE_AUTO( vgui_utf8, "0", FCVAR_ARCHIVE, "enable utf-8 support fo
static void GAME_EXPORT VGUI_DrawInit( void ) static void GAME_EXPORT VGUI_DrawInit( void )
{ {
if( vgui.mempool ) memset( vgui.textures, 0, sizeof( vgui.textures ));
Mem_EmptyPool( vgui.mempool );
else vgui.mempool = Mem_AllocPool( "VGui Support Pool" );
vgui.textures = NULL;
memset( vgui.color, 0, sizeof( vgui.color )); memset( vgui.color, 0, sizeof( vgui.color ));
vgui.texture_id = 0; vgui.texture_id = vgui.bound_texture = 0;
vgui.bound_texture = 0;
vgui.max_textures = 0;
vgui.enable_texture = true; vgui.enable_texture = true;
} }
@@ -76,79 +60,28 @@ static void GAME_EXPORT VGUI_DrawShutdown( void )
int i; int i;
for( i = 1; i < vgui.texture_id; i++ ) for( i = 1; i < vgui.texture_id; i++ )
ref.dllFuncs.GL_FreeTexture( vgui.textures[i].gl_texturenum ); ref.dllFuncs.GL_FreeTexture( vgui.textures[i] );
Mem_FreePool( &vgui.mempool );
vgui.textures = NULL;
memset( vgui.color, 0, sizeof( vgui.color ));
vgui.texture_id = 0;
vgui.bound_texture = 0;
vgui.max_textures = 0;
} }
static int GAME_EXPORT VGUI_GenerateTexture( void ) static int GAME_EXPORT VGUI_GenerateTexture( void )
{ {
// allocate new if( ++vgui.texture_id >= VGUI_MAX_TEXTURES )
if( vgui.texture_id + 1 >= vgui.max_textures ) Host_Error( "%s: VGUI_MAX_TEXTURES limit exceeded\n", __func__ );
{
if( vgui.max_textures + VGUI_MAX_TEXTURES >= VGUI_MAX_TEXTURES * VGUI_MAX_TEXTURES )
{
// in theory it might look up texture that hasn't been bound for a while and
// reuse that but it will eventually overwrite some important textures anyway
Con_Printf( S_ERROR "%s: Refusing resizing VGUI textures array due to memory leak\n", __func__ );
return vgui.texture_id;
}
vgui.max_textures += VGUI_MAX_TEXTURES; return vgui.texture_id;
// this potentially might leak memory if VGUI is used incorrectly!
// (like in Cry of Fear)
vgui.textures = Mem_Realloc( vgui.mempool, vgui.textures, sizeof( *vgui.textures ) * vgui.max_textures );
// warn mod developer
if( vgui.max_textures >= VGUI_MAX_TEXTURES * 4 )
Con_Printf( S_ERROR "%s: Potential memory leak in VGUI code is detected!\n", __func__ );
}
return ++vgui.texture_id;
} }
static void GAME_EXPORT VGUI_UploadTexture( int id, const char *buffer, int width, int height ) static void GAME_EXPORT VGUI_UploadTexture( int id, const char *buffer, int width, int height )
{ {
rgbdata_t r_image = { 0 }; rgbdata_t r_image = { 0 };
char texName[32]; char texName[32];
MD5Context_t ctx;
byte hash[16];
if( id <= 0 || id >= vgui.max_textures || width <= 0 || height <= 0 ) if( id <= 0 || id >= VGUI_MAX_TEXTURES )
{ {
Con_DPrintf( S_ERROR "%s: bad texture %i. Ignored\n", __func__, id ); Con_DPrintf( S_ERROR "%s: bad texture %i. Ignored\n", __func__, id );
return; return;
} }
// need to do this as some mods tend to upload same texture over and over
// exhausing engine-wide limit on textures and leaking vram
MD5Init( &ctx );
MD5Update( &ctx, buffer, width * height * 4 );
MD5Final( hash, &ctx );
// it's a new texture, try to find a copy
if( vgui.textures[id].gl_texturenum == 0 )
{
int i;
for( i = 1; i < vgui.texture_id; i++ )
{
if( vgui.textures[i].gl_texturenum != 0 && !memcmp( vgui.textures[i].hash, hash, sizeof( hash )))
{
// copy data to new texture id
vgui.textures[id] = vgui.textures[i];
return;
}
}
}
Q_snprintf( texName, sizeof( texName ), "*vgui%i", id ); Q_snprintf( texName, sizeof( texName ), "*vgui%i", id );
r_image.width = width; r_image.width = width;
@@ -158,29 +91,51 @@ static void GAME_EXPORT VGUI_UploadTexture( int id, const char *buffer, int widt
r_image.flags = IMAGE_HAS_COLOR|IMAGE_HAS_ALPHA; r_image.flags = IMAGE_HAS_COLOR|IMAGE_HAS_ALPHA;
r_image.buffer = (byte*)buffer; r_image.buffer = (byte*)buffer;
vgui.textures[id].gl_texturenum = GL_LoadTextureInternal( texName, &r_image, TF_IMAGE ); vgui.textures[id] = GL_LoadTextureInternal( texName, &r_image, TF_IMAGE );
memcpy( vgui.textures[id].hash, hash, sizeof( hash ));
} }
static void GAME_EXPORT VGUI_CreateTexture( int id, int width, int height ) static void GAME_EXPORT VGUI_CreateTexture( int id, int width, int height )
{ {
// nothing uses it, it can be removed rgbdata_t r_image = { 0 };
Host_Error( "%s: deprecated\n", __func__ ); char texName[32];
if( id <= 0 || id >= VGUI_MAX_TEXTURES )
{
Con_DPrintf( S_ERROR "%s: bad texture %i. Ignored\n", __func__, id );
return;
}
Q_snprintf( texName, sizeof( texName ), "*vgui%i", id );
r_image.width = width;
r_image.height = height;
r_image.type = PF_RGBA_32;
r_image.size = width * height * 4;
r_image.flags = IMAGE_HAS_COLOR|IMAGE_HAS_ALPHA;
r_image.buffer = NULL;
vgui.textures[id] = GL_LoadTextureInternal( texName, &r_image, TF_IMAGE );
vgui.bound_texture = id;
} }
static void GAME_EXPORT VGUI_UploadTextureBlock( int id, int drawX, int drawY, const byte *rgba, int blockWidth, int blockHeight ) static void GAME_EXPORT VGUI_UploadTextureBlock( int id, int drawX, int drawY, const byte *rgba, int blockWidth, int blockHeight )
{ {
// nothing uses it, it can be removed if( id <= 0 || id >= VGUI_MAX_TEXTURES || vgui.textures[id] == 0 )
Host_Error( "%s: deprecated\n", __func__ ); {
Con_DPrintf( S_ERROR "%s: bad texture %i. Ignored\n", __func__, id );
return;
}
ref.dllFuncs.VGUI_UploadTextureBlock( drawX, drawY, rgba, blockWidth, blockHeight );
vgui.bound_texture = id;
} }
static void GAME_EXPORT VGUI_BindTexture( int id ) static void GAME_EXPORT VGUI_BindTexture( int id )
{ {
if( id <= 0 || id >= vgui.max_textures || !vgui.textures[id].gl_texturenum ) if( id <= 0 || id >= VGUI_MAX_TEXTURES || !vgui.textures[id] )
id = 1; // NOTE: same as bogus index 2700 in GoldSrc id = 1; // NOTE: same as bogus index 2700 in GoldSrc
ref.dllFuncs.GL_Bind( XASH_TEXTURE0, vgui.textures[id].gl_texturenum ); ref.dllFuncs.GL_Bind( XASH_TEXTURE0, vgui.textures[id] );
vgui.bound_texture = id; vgui.bound_texture = id;
} }
@@ -189,7 +144,7 @@ static void GAME_EXPORT VGUI_GetTextureSizes( int *w, int *h )
int texnum; int texnum;
if( vgui.bound_texture ) if( vgui.bound_texture )
texnum = vgui.textures[vgui.bound_texture].gl_texturenum; texnum = vgui.textures[vgui.bound_texture];
else else
texnum = R_GetBuiltinTexture( REF_DEFAULT_TEXTURE ); texnum = R_GetBuiltinTexture( REF_DEFAULT_TEXTURE );
@@ -232,7 +187,7 @@ static void GAME_EXPORT VGUI_DrawQuad( const vpoint_t *ul, const vpoint_t *lr )
t2 = lr->coord[1]; t2 = lr->coord[1];
ref.dllFuncs.Color4ub( vgui.color[0], vgui.color[1], vgui.color[2], vgui.color[3] ); ref.dllFuncs.Color4ub( vgui.color[0], vgui.color[1], vgui.color[2], vgui.color[3] );
ref.dllFuncs.R_DrawStretchPic( x, y, w, h, s1, t1, s2, t2, vgui.textures[vgui.bound_texture].gl_texturenum ); ref.dllFuncs.R_DrawStretchPic( x, y, w, h, s1, t1, s2, t2, vgui.textures[vgui.bound_texture] );
} }
else else
{ {
+27 -68
View File
@@ -17,7 +17,7 @@ GNU General Public License for more details.
#include "base_cmd.h" #include "base_cmd.h"
#include "cdll_int.h" #include "cdll_int.h"
#define HASH_SIZE 64 // 64 * 4 * 4 == 1024 bytes #define HASH_SIZE 128 // 128 * 4 * 4 == 2048 bytes
typedef struct base_command_hashmap_s base_command_hashmap_t; typedef struct base_command_hashmap_s base_command_hashmap_t;
@@ -26,11 +26,10 @@ struct base_command_hashmap_s
base_command_t *basecmd; // base command: cvar, alias or command base_command_t *basecmd; // base command: cvar, alias or command
base_command_hashmap_t *next; base_command_hashmap_t *next;
base_command_type_e type; // type for faster searching base_command_type_e type; // type for faster searching
char name[]; // key for searching char name[1]; // key for searching
}; };
static base_command_hashmap_t *hashed_cmds[HASH_SIZE]; static base_command_hashmap_t *hashed_cmds[HASH_SIZE];
static poolhandle_t basecmd_pool;
#define BaseCmd_HashKey( x ) COM_HashKey( name, HASH_SIZE ) #define BaseCmd_HashKey( x ) COM_HashKey( name, HASH_SIZE )
@@ -43,27 +42,11 @@ Find base command in bucket
*/ */
static base_command_hashmap_t *BaseCmd_FindInBucket( base_command_hashmap_t *bucket, base_command_type_e type, const char *name ) static base_command_hashmap_t *BaseCmd_FindInBucket( base_command_hashmap_t *bucket, base_command_type_e type, const char *name )
{ {
base_command_hashmap_t *i; base_command_hashmap_t *i = bucket;
for( ; i && ( i->type != type || Q_stricmp( name, i->name ) ); // filter out
i = i->next );
for( i = bucket; i != NULL; i = i->next ) return i;
{
int cmp;
if( i->type != type )
continue;
cmp = Q_stricmp( i->name, name );
if( cmp < 0 )
continue;
if( cmp > 0 )
break;
return i;
}
return NULL;
} }
/* /*
@@ -107,31 +90,27 @@ void BaseCmd_FindAll( const char *name, base_command_t **cmd, base_command_t **a
base_command_hashmap_t *base = BaseCmd_GetBucket( name ); base_command_hashmap_t *base = BaseCmd_GetBucket( name );
base_command_hashmap_t *i = base; base_command_hashmap_t *i = base;
ASSERT( cmd && alias && cvar );
*cmd = *alias = *cvar = NULL; *cmd = *alias = *cvar = NULL;
for( ; i; i = i->next ) for( ; i; i = i->next )
{ {
int cmp = Q_stricmp( i->name, name ); if( !Q_stricmp( i->name, name ) )
if( cmp < 0 )
continue;
if( cmp > 0 )
break;
switch( i->type )
{ {
case HM_CMD: switch( i->type )
*cmd = i->basecmd; {
break; case HM_CMD:
case HM_CMDALIAS: *cmd = i->basecmd;
*alias = i->basecmd; break;
break; case HM_CMDALIAS:
case HM_CVAR: *alias = i->basecmd;
*cvar = i->basecmd; break;
break; case HM_CVAR:
default: *cvar = i->basecmd;
break; break;
default: break;
}
} }
} }
} }
@@ -149,14 +128,14 @@ void BaseCmd_Insert( base_command_type_e type, base_command_t *basecmd, const ch
uint hash = BaseCmd_HashKey( name ); uint hash = BaseCmd_HashKey( name );
size_t len = Q_strlen( name ); size_t len = Q_strlen( name );
elem = Mem_Malloc( basecmd_pool, sizeof( base_command_hashmap_t ) + len + 1 ); elem = Z_Malloc( sizeof( base_command_hashmap_t ) + len );
elem->basecmd = basecmd; elem->basecmd = basecmd;
elem->type = type; elem->type = type;
Q_strncpy( elem->name, name, len + 1 ); Q_strncpy( elem->name, name, len + 1 );
// link the variable in alphanumerical order // link the variable in alphanumerical order
for( cur = NULL, find = hashed_cmds[hash]; for( cur = NULL, find = hashed_cmds[hash];
find && Q_stricmp( find->name, elem->name ) < 0; find && Q_strcmp( find->name, elem->name ) < 0;
cur = find, find = find->next ); cur = find, find = find->next );
if( cur ) cur->next = elem; if( cur ) cur->next = elem;
@@ -177,23 +156,9 @@ void BaseCmd_Remove( base_command_type_e type, const char *name )
uint hash = BaseCmd_HashKey( name ); uint hash = BaseCmd_HashKey( name );
base_command_hashmap_t *i, *prev; base_command_hashmap_t *i, *prev;
for( prev = NULL, i = hashed_cmds[hash]; i != NULL; prev = i, i = i->next ) for( prev = NULL, i = hashed_cmds[hash]; i &&
{ ( Q_strcmp( i->name, name ) || i->type != type); // filter out
int cmp; prev = i, i = i->next );
if( i->type != type )
continue;
cmp = Q_stricmp( i->name, name );
if( cmp < 0 )
continue;
if( cmp > 0 )
i = NULL;
break;
}
if( !i ) if( !i )
{ {
@@ -218,15 +183,9 @@ initialize base command hashmap system
*/ */
void BaseCmd_Init( void ) void BaseCmd_Init( void )
{ {
basecmd_pool = Mem_AllocPool( "BaseCmd" );
memset( hashed_cmds, 0, sizeof( hashed_cmds ) ); memset( hashed_cmds, 0, sizeof( hashed_cmds ) );
} }
void BaseCmd_Shutdown( void )
{
Mem_FreePool( &basecmd_pool );
}
/* /*
============ ============
BaseCmd_Stats_f BaseCmd_Stats_f
-1
View File
@@ -32,7 +32,6 @@ typedef enum base_command_type
typedef void base_command_t; typedef void base_command_t;
void BaseCmd_Init( void ); void BaseCmd_Init( void );
void BaseCmd_Shutdown( void );
base_command_t *BaseCmd_Find( base_command_type_e type, const char *name ); base_command_t *BaseCmd_Find( base_command_type_e type, const char *name );
void BaseCmd_FindAll( const char *name, void BaseCmd_FindAll( const char *name,
base_command_t **cmd, base_command_t **alias, base_command_t **cvar ); base_command_t **cmd, base_command_t **alias, base_command_t **cvar );
+108 -71
View File
@@ -46,7 +46,6 @@ static cmdalias_t *cmd_alias;
static uint cmd_condition; static uint cmd_condition;
static int cmd_condlevel; static int cmd_condlevel;
static qboolean cmd_currentCommandIsPrivileged; static qboolean cmd_currentCommandIsPrivileged;
static poolhandle_t cmd_pool;
static void Cmd_ExecuteStringWithPrivilegeCheck( const char *text, qboolean isPrivileged ); static void Cmd_ExecuteStringWithPrivilegeCheck( const char *text, qboolean isPrivileged );
@@ -143,33 +142,28 @@ void Cbuf_AddFilteredText( const char *text )
Cbuf_InsertText Cbuf_InsertText
Adds command text immediately after the current command Adds command text immediately after the current command
Adds a \n to the text
============ ============
*/ */
static void Cbuf_InsertTextToBuffer( cmdbuf_t *buf, const char *text, size_t len, size_t requested_len ) static void Cbuf_InsertTextToBuffer( cmdbuf_t *buf, const char *text )
{ {
if(( buf->cursize + requested_len ) >= buf->maxsize ) int l = Q_strlen( text );
if(( buf->cursize + l ) >= buf->maxsize )
{ {
Con_Reportf( S_WARN "%s: overflow\n", __func__ ); Con_Reportf( S_WARN "%s: overflow\n", __func__ );
} }
else else
{ {
memmove( buf->data + len, buf->data, buf->cursize ); memmove( buf->data + l, buf->data, buf->cursize );
memcpy( buf->data, text, len ); memcpy( buf->data, text, l );
buf->cursize += len; buf->cursize += l;
} }
} }
void Cbuf_InsertTextLen( const char *text, size_t len, size_t requested_len )
{
// sometimes we need to insert more data than we have
// but also prevent overflow
Cbuf_InsertTextToBuffer( &cmd_text, text, len, requested_len );
}
void Cbuf_InsertText( const char *text ) void Cbuf_InsertText( const char *text )
{ {
size_t l = Q_strlen( text ); Cbuf_InsertTextToBuffer( &cmd_text, text );
Cbuf_InsertTextToBuffer( &cmd_text, text, l, l );
} }
/* /*
@@ -269,16 +263,10 @@ Cbuf_Execute
void Cbuf_Execute( void ) void Cbuf_Execute( void )
{ {
Cbuf_ExecuteCommandsFromBuffer( &cmd_text, true, -1 ); Cbuf_ExecuteCommandsFromBuffer( &cmd_text, true, -1 );
// a1ba: unlimited commands for filtered buffer per frame
// a1ba: goldsrc limits unprivileged commands per frame to 1 here
// I don't see any sense in restricting that at this moment // I don't see any sense in restricting that at this moment
// but in future we may limit this // but in future we may limit this
Cbuf_ExecuteCommandsFromBuffer( &filteredcmd_text, false, -1 );
// a1ba: there is little to no sense limit privileged commands in
// local game, as client runs server code anyway
// do this for singleplayer only though, to make it easier to catch
// possible bugs during local multiplayer testing
Cbuf_ExecuteCommandsFromBuffer( &filteredcmd_text, SV_Active() && SV_GetMaxClients() == 1, -1 );
} }
/* /*
@@ -433,7 +421,7 @@ static void Cmd_Alias_f( void )
{ {
if( !Q_strcmp( s, a->name )) if( !Q_strcmp( s, a->name ))
{ {
Mem_Free( a->value ); Z_Free( a->value );
break; break;
} }
} }
@@ -442,7 +430,7 @@ static void Cmd_Alias_f( void )
{ {
cmdalias_t *cur, *prev; cmdalias_t *cur, *prev;
a = Mem_Malloc( cmd_pool, sizeof( cmdalias_t )); a = Z_Malloc( sizeof( cmdalias_t ));
Q_strncpy( a->name, s, sizeof( a->name )); Q_strncpy( a->name, s, sizeof( a->name ));
@@ -470,7 +458,7 @@ static void Cmd_Alias_f( void )
} }
Q_strncat( cmd, "\n", sizeof( cmd )); Q_strncat( cmd, "\n", sizeof( cmd ));
a->value = copystringpool( cmd_pool, cmd ); a->value = copystring( cmd );
} }
/* /*
@@ -524,14 +512,14 @@ static void Cmd_UnAlias_f ( void )
============================================================================= =============================================================================
*/ */
struct cmd_s typedef struct cmd_s
{ {
struct cmd_s *next; struct cmd_s *next;
char *name; char *name;
xcommand_t function; xcommand_t function;
int flags; int flags;
char desc[]; char *desc;
}; } cmd_t;
static int cmd_argc; static int cmd_argc;
static const char *cmd_args = NULL; static const char *cmd_args = NULL;
@@ -637,7 +625,7 @@ void Cmd_TokenizeString( const char *text )
// clear the args from the last string // clear the args from the last string
for( i = 0; i < cmd_argc; i++ ) for( i = 0; i < cmd_argc; i++ )
Mem_Free( cmd_argv[i] ); Z_Free( cmd_argv[i] );
cmd_argc = 0; // clear previous args cmd_argc = 0; // clear previous args
cmd_args = NULL; cmd_args = NULL;
@@ -671,7 +659,7 @@ void Cmd_TokenizeString( const char *text )
if( cmd_argc < MAX_CMD_TOKENS ) if( cmd_argc < MAX_CMD_TOKENS )
{ {
cmd_argv[cmd_argc] = copystringpool( cmd_pool, cmd_token ); cmd_argv[cmd_argc] = copystring( cmd_token );
cmd_argc++; cmd_argc++;
} }
} }
@@ -682,10 +670,10 @@ void Cmd_TokenizeString( const char *text )
Cmd_AddCommandEx Cmd_AddCommandEx
============ ============
*/ */
int Cmd_AddCommandEx( const char *cmd_name, xcommand_t function, const char *cmd_desc, int iFlags, const char *funcname ) static int Cmd_AddCommandEx( const char *funcname, const char *cmd_name, xcommand_t function,
const char *cmd_desc, int iFlags )
{ {
cmd_t *cmd, *cur, *prev; cmd_t *cmd, *cur, *prev;
size_t desc_len;
if( !COM_CheckString( cmd_name )) if( !COM_CheckString( cmd_name ))
{ {
@@ -700,35 +688,17 @@ int Cmd_AddCommandEx( const char *cmd_name, xcommand_t function, const char *cmd
return 0; return 0;
} }
// fail if the command already exists and cannot be overriden // fail if the command already exists
cmd = Cmd_Exists( cmd_name ); if( Cmd_Exists( cmd_name ))
if( cmd )
{ {
// some mods register commands that share the name with some engine's commands Con_DPrintf( S_ERROR "%s: %s already defined\n", funcname, cmd_name );
// when they aren't critical to keep engine running, we can let mods to override them return 0;
// unfortunately, we lose original command this way
if( FBitSet( cmd->flags, CMD_OVERRIDABLE ))
{
desc_len = Q_strlen( cmd->desc ) + 1;
Q_strncpy( cmd->desc, cmd_desc, desc_len );
cmd->function = function;
cmd->flags = iFlags;
Con_DPrintf( S_WARN "%s: %s already defined but is allowed to be overriden\n", funcname, cmd_name );
return 1;
}
else
{
Con_DPrintf( "%s%s: %s already defined\n", cmd->function == function ? S_WARN : S_ERROR, funcname, cmd_name );
return 0;
}
} }
// use a small malloc to avoid zone fragmentation // use a small malloc to avoid zone fragmentation
desc_len = Q_strlen( cmd_desc ) + 1; cmd = Z_Malloc( sizeof( cmd_t ) );
cmd = Mem_Malloc( cmd_pool, sizeof( cmd_t ) + desc_len ); cmd->name = copystring( cmd_name );
cmd->name = copystringpool( cmd_pool, cmd_name ); cmd->desc = copystring( cmd_desc );
Q_strncpy( cmd->desc, cmd_desc, desc_len );
cmd->function = function; cmd->function = function;
cmd->flags = iFlags; cmd->flags = iFlags;
@@ -746,6 +716,75 @@ int Cmd_AddCommandEx( const char *cmd_name, xcommand_t function, const char *cmd
return 1; return 1;
} }
/*
============
Cmd_AddCommand
============
*/
void Cmd_AddCommand( const char *cmd_name, xcommand_t function, const char *cmd_desc )
{
Cmd_AddCommandEx( __func__, cmd_name, function, cmd_desc, 0 );
}
/*
============
Cmd_AddRestrictedCommand
============
*/
void Cmd_AddRestrictedCommand( const char *cmd_name, xcommand_t function, const char *cmd_desc )
{
Cmd_AddCommandEx( __func__, cmd_name, function, cmd_desc, CMD_PRIVILEGED );
}
/*
============
Cmd_AddServerCommand
============
*/
void GAME_EXPORT Cmd_AddServerCommand( const char *cmd_name, xcommand_t function )
{
Cmd_AddCommandEx( __func__, cmd_name, function, "server command", CMD_SERVERDLL );
}
/*
============
Cmd_AddClientCommand
============
*/
int GAME_EXPORT Cmd_AddClientCommand( const char *cmd_name, xcommand_t function )
{
int flags = CMD_CLIENTDLL;
// a1ba: try to mitigate outdated client.dll vulnerabilities
if( !Q_stricmp( cmd_name, "motd_write" ))
{
flags |= CMD_PRIVILEGED;
}
return Cmd_AddCommandEx( __func__, cmd_name, function, "client command", flags );
}
/*
============
Cmd_AddGameUICommand
============
*/
int GAME_EXPORT Cmd_AddGameUICommand( const char *cmd_name, xcommand_t function )
{
return Cmd_AddCommandEx( __func__, cmd_name, function, "gameui command", CMD_GAMEUIDLL );
}
/*
============
Cmd_AddRefCommand
============
*/
int Cmd_AddRefCommand( const char *cmd_name, xcommand_t function, const char *description )
{
return Cmd_AddCommandEx( __func__, cmd_name, function, description, CMD_REFDLL );
}
/* /*
============ ============
Cmd_RemoveCommand Cmd_RemoveCommand
@@ -775,6 +814,9 @@ void GAME_EXPORT Cmd_RemoveCommand( const char *cmd_name )
if( cmd->name ) if( cmd->name )
Mem_Free( cmd->name ); Mem_Free( cmd->name );
if( cmd->desc )
Mem_Free( cmd->desc );
Mem_Free( cmd ); Mem_Free( cmd );
return; return;
} }
@@ -811,18 +853,19 @@ void Cmd_LookupCmds( void *buffer, void *ptr, setpair_t callback )
Cmd_Exists Cmd_Exists
============ ============
*/ */
cmd_t *Cmd_Exists( const char *cmd_name ) qboolean Cmd_Exists( const char *cmd_name )
{ {
#if defined(XASH_HASHED_VARS) #if defined(XASH_HASHED_VARS)
return BaseCmd_Find( HM_CMD, cmd_name ); return BaseCmd_Find( HM_CMD, cmd_name ) != NULL;
#else #else
cmd_t *cmd; cmd_t *cmd;
for( cmd = cmd_functions; cmd; cmd = cmd->next ) for( cmd = cmd_functions; cmd; cmd = cmd->next )
{ {
if( !Q_strcmp( cmd_name, cmd->name )) if( !Q_strcmp( cmd_name, cmd->name ))
return cmd; return true;
} }
return NULL; return false;
#endif #endif
} }
@@ -1015,10 +1058,9 @@ static void Cmd_ExecuteStringWithPrivilegeCheck( const char *text, qboolean isPr
if( a ) if( a )
{ {
size_t len = Q_strlen( a->value );
Cbuf_InsertTextToBuffer( Cbuf_InsertTextToBuffer(
isPrivileged ? &cmd_text : &filteredcmd_text, isPrivileged ? &cmd_text : &filteredcmd_text,
a->value, len, len ); a->value );
return; return;
} }
} }
@@ -1202,6 +1244,7 @@ void Cmd_Unlink( int group )
*prev = cmd->next; *prev = cmd->next;
if( cmd->name ) Mem_Free( cmd->name ); if( cmd->name ) Mem_Free( cmd->name );
if( cmd->desc ) Mem_Free( cmd->desc );
Mem_Free( cmd ); Mem_Free( cmd );
count++; count++;
@@ -1339,7 +1382,6 @@ Cmd_Init
*/ */
void Cmd_Init( void ) void Cmd_Init( void )
{ {
cmd_pool = Mem_AllocPool( "Console Commands" );
cmd_functions = NULL; cmd_functions = NULL;
cmd_condition = 0; cmd_condition = 0;
cmd_alias = NULL; cmd_alias = NULL;
@@ -1366,11 +1408,6 @@ void Cmd_Init( void )
#endif #endif
} }
void Cmd_Shutdown( void )
{
Mem_FreePool( &cmd_pool );
}
#if XASH_ENGINE_TESTS #if XASH_ENGINE_TESTS
#include "tests.h" #include "tests.h"
+2
View File
@@ -72,6 +72,8 @@ GNU General Public License for more details.
#define CVAR_GLCONFIG_DESCRIPTION "enable or disable %s" #define CVAR_GLCONFIG_DESCRIPTION "enable or disable %s"
#define DEFAULT_BSP_BUILD_ERROR "%s can't be loaded in this build. Please rebuild engine with enabled SUPPORT_BSP2_FORMAT\n"
#define DEFAULT_UPDATE_PAGE "https://github.com/FWGS/xash3d-fwgs/releases/latest" #define DEFAULT_UPDATE_PAGE "https://github.com/FWGS/xash3d-fwgs/releases/latest"
#define XASH_ENGINE_NAME "Xash3D FWGS" #define XASH_ENGINE_NAME "Xash3D FWGS"
+1 -1
View File
@@ -612,7 +612,7 @@ COM_Nibble
Returns the 4 bit nibble for a hex character Returns the 4 bit nibble for a hex character
================== ==================
*/ */
byte COM_Nibble( char c ) static byte COM_Nibble( char c )
{ {
if(( c >= '0' ) && ( c <= '9' )) if(( c >= '0' ) && ( c <= '9' ))
{ {
+63 -97
View File
@@ -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 #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_NONE = 0,
DEV_NORMAL, DEV_NORMAL,
DEV_EXTENDED 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_NORMAL, // listen server, singleplayer
HOST_DEDICATED, HOST_DEDICATED,
@@ -99,14 +108,14 @@ typedef enum instance_e
#include "com_model.h" #include "com_model.h"
#include "com_strings.h" #include "com_strings.h"
#include "crtlib.h" #include "crtlib.h"
#define FSCALLBACK_OVERRIDE_OPEN
#define FSCALLBACK_OVERRIDE_LOADFILE
#define FSCALLBACK_OVERRIDE_MALLOC_LIKE
#include "fscallback.h"
#include "cvar.h" #include "cvar.h"
#include "con_nprint.h" #include "con_nprint.h"
#include "crclib.h" #include "crclib.h"
#include "ref_api.h" #include "ref_api.h"
#define FSCALLBACK_OVERRIDE_OPEN
#define FSCALLBACK_OVERRIDE_LOADFILE
#define FSCALLBACK_OVERRIDE_MALLOC_LIKE
#include "fscallback.h"
// PERFORMANCE INFO // PERFORMANCE INFO
#define MIN_FPS 20.0f // host minimum fps value for maxfps. #define MIN_FPS 20.0f // host minimum fps value for maxfps.
@@ -137,11 +146,6 @@ typedef enum instance_e
#define MAX_STATIC_ENTITIES 32 // static entities that moved on the client when level is spawn #define MAX_STATIC_ENTITIES 32 // static entities that moved on the client when level is spawn
#endif #endif
#define MAX_SERVERINFO_STRING 512 // server handles too many settings. expand to 1024?
#define MAX_PRINT_MSG 8192 // how many symbols can handle single call of Con_Printf or Con_DPrintf
#define MAX_TOKEN 2048 // parse token length
#define MAX_USERMSG_LENGTH 2048 // don't modify it's relies on a client-side definitions
#define GameState (&host.game) #define GameState (&host.game)
#define FORCE_DRAW_VERSION_TIME 5.0 // draw version for 5 seconds #define FORCE_DRAW_VERSION_TIME 5.0 // draw version for 5 seconds
@@ -167,11 +171,6 @@ extern convar_t cl_filterstuffcmd;
extern convar_t rcon_password; extern convar_t rcon_password;
extern convar_t hpk_custom_file; extern convar_t hpk_custom_file;
extern convar_t con_gamemaps; 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 )) #define Mod_AllowMaterials() ( host_allow_materials.value != 0.0f && !FBitSet( host.features, ENGINE_DISABLE_HDTEXTURES ))
@@ -190,7 +189,7 @@ GAMEINFO stuff
internal shared gameinfo structure (readonly for engine parts) internal shared gameinfo structure (readonly for engine parts)
======================================================================== ========================================================================
*/ */
typedef enum host_status_e typedef enum
{ {
HOST_INIT = 0, // initalize operations HOST_INIT = 0, // initalize operations
HOST_FRAME, // host running HOST_FRAME, // host running
@@ -201,7 +200,7 @@ typedef enum host_status_e
HOST_CRASHED // an exception handler called HOST_CRASHED // an exception handler called
} host_status_t; } host_status_t;
typedef enum host_state_e typedef enum
{ {
STATE_RUNFRAME = 0, STATE_RUNFRAME = 0,
STATE_LOAD_LEVEL, STATE_LOAD_LEVEL,
@@ -210,7 +209,7 @@ typedef enum host_state_e
STATE_GAME_SHUTDOWN, STATE_GAME_SHUTDOWN,
} host_state_t; } host_state_t;
typedef struct game_status_e typedef struct
{ {
host_state_t curstate; host_state_t curstate;
host_state_t nextstate; host_state_t nextstate;
@@ -221,7 +220,7 @@ typedef struct game_status_e
qboolean newGame; // unload the server.dll before start a new map qboolean newGame; // unload the server.dll before start a new map
} game_status_t; } game_status_t;
typedef enum keydest_e typedef enum
{ {
key_console = 0, key_console = 0,
key_game, key_game,
@@ -229,7 +228,7 @@ typedef enum keydest_e
key_message key_message
} keydest_t; } keydest_t;
typedef enum rdtype_e typedef enum
{ {
RD_NONE = 0, RD_NONE = 0,
RD_CLIENT, RD_CLIENT,
@@ -239,7 +238,7 @@ typedef enum rdtype_e
#include "net_ws.h" #include "net_ws.h"
// console field // console field
typedef struct field_e typedef struct
{ {
string buffer; string buffer;
int cursor; int cursor;
@@ -257,7 +256,7 @@ typedef struct host_redirect_s
int lines; int lines;
} host_redirect_t; } host_redirect_t;
typedef struct soundlist_e typedef struct
{ {
char name[MAX_QPATH]; char name[MAX_QPATH];
short entnum; short entnum;
@@ -298,10 +297,11 @@ typedef struct host_parm_s
host_status_t status; // global host state host_status_t status; // global host state
game_status_t game; // game manager 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 mempool; // static mempool for misc allocations
poolhandle_t imagepool; // imagelib mempool poolhandle_t imagepool; // imagelib mempool
poolhandle_t soundpool; // soundlib mempool poolhandle_t soundpool; // soundlib mempool
string finalmsg; // server shutdown final message
string downloadfile; // filename to be downloading string downloadfile; // filename to be downloading
int downloadcount; // how many files remain to downloading int downloadcount; // how many files remain to downloading
char deferred_cmd[128];// deferred commands char deferred_cmd[128];// deferred commands
@@ -362,13 +362,12 @@ typedef struct host_parm_s
extern host_parm_t host; extern host_parm_t host;
#define CMD_SERVERDLL BIT( 0 ) // added by server.dll #define CMD_SERVERDLL BIT( 0 ) // added by server.dll
#define CMD_CLIENTDLL BIT( 1 ) // added by client.dll #define CMD_CLIENTDLL BIT( 1 ) // added by client.dll
#define CMD_GAMEUIDLL BIT( 2 ) // added by GameUI.dll #define CMD_GAMEUIDLL BIT( 2 ) // added by GameUI.dll
#define CMD_PRIVILEGED BIT( 3 ) // only available in privileged mode #define CMD_PRIVILEGED BIT( 3 ) // only available in privileged mode
#define CMD_FILTERABLE BIT( 4 ) // filtered in unprivileged mode if cl_filterstuffcmd is 1 #define CMD_FILTERABLE BIT( 4 ) // filtered in unprivileged mode if cl_filterstuffcmd is 1
#define CMD_REFDLL BIT( 5 ) // added by ref.dll #define CMD_REFDLL BIT( 5 ) // added by ref.dll
#define CMD_OVERRIDABLE BIT( 6 ) // can be removed by DLLs if name matches
typedef void (*xcommand_t)( void ); typedef void (*xcommand_t)( void );
@@ -415,19 +414,15 @@ byte *FS_LoadFile( const char *path, fs_offset_t *filesizeptr, qboolean gamediro
MALLOC_LIKE( _Mem_Free, 1 ) WARN_UNUSED_RESULT; MALLOC_LIKE( _Mem_Free, 1 ) WARN_UNUSED_RESULT;
byte *FS_LoadDirectFile( const char *path, fs_offset_t *filesizeptr ) byte *FS_LoadDirectFile( const char *path, fs_offset_t *filesizeptr )
MALLOC_LIKE( _Mem_Free, 1 ) WARN_UNUSED_RESULT; MALLOC_LIKE( _Mem_Free, 1 ) WARN_UNUSED_RESULT;
void FS_Rescan_f( void );
void FS_CheckConfig( void );
// //
// cmd.c // cmd.c
// //
typedef struct cmd_s cmd_t;
void Cbuf_Clear( void ); void Cbuf_Clear( void );
void Cbuf_AddText( const char *text ); void Cbuf_AddText( const char *text );
void Cbuf_AddTextf( const char *text, ... ) FORMAT_CHECK( 1 ); void Cbuf_AddTextf( const char *text, ... ) FORMAT_CHECK( 1 );
void Cbuf_AddFilteredText( const char *text ); void Cbuf_AddFilteredText( const char *text );
void Cbuf_InsertText( const char *text ); void Cbuf_InsertText( const char *text );
void Cbuf_InsertTextLen( const char *text, size_t len, size_t requested_len );
void Cbuf_ExecStuffCmds( void ); void Cbuf_ExecStuffCmds( void );
void Cbuf_Execute (void); void Cbuf_Execute (void);
qboolean Cmd_CurrentCommandIsPrivileged( void ); qboolean Cmd_CurrentCommandIsPrivileged( void );
@@ -435,27 +430,15 @@ int Cmd_Argc( void );
const char *Cmd_Args( void ) RETURNS_NONNULL; const char *Cmd_Args( void ) RETURNS_NONNULL;
const char *Cmd_Argv( int arg ) RETURNS_NONNULL; const char *Cmd_Argv( int arg ) RETURNS_NONNULL;
void Cmd_Init( void ); void Cmd_Init( void );
void Cmd_Shutdown( void );
void Cmd_Unlink( int group ); void Cmd_Unlink( int group );
int Cmd_AddCommandEx( const char *cmd_name, xcommand_t function, const char *cmd_desc, int flags, const char *funcname ); void Cmd_AddCommand( const char *cmd_name, xcommand_t function, const char *cmd_desc );
void Cmd_AddRestrictedCommand( const char *cmd_name, xcommand_t function, const char *cmd_desc );
static inline int Cmd_AddCommand( const char *cmd_name, xcommand_t function, const char *cmd_desc ) void Cmd_AddServerCommand( const char *cmd_name, xcommand_t function );
{ int Cmd_AddClientCommand( const char *cmd_name, xcommand_t function );
return Cmd_AddCommandEx( cmd_name, function, cmd_desc, 0, __func__ ); int Cmd_AddGameUICommand( const char *cmd_name, xcommand_t function );
} int Cmd_AddRefCommand( const char *cmd_name, xcommand_t function, const char *description );
static inline int Cmd_AddRestrictedCommand( const char *cmd_name, xcommand_t function, const char *cmd_desc )
{
return Cmd_AddCommandEx( cmd_name, function, cmd_desc, CMD_PRIVILEGED, __func__ );
}
static inline int Cmd_AddCommandWithFlags( const char *cmd_name, xcommand_t function, const char *cmd_desc, int flags )
{
return Cmd_AddCommandEx( cmd_name, function, cmd_desc, flags, __func__ );
}
void Cmd_RemoveCommand( const char *cmd_name ); void Cmd_RemoveCommand( const char *cmd_name );
cmd_t *Cmd_Exists( const char *cmd_name ); qboolean Cmd_Exists( const char *cmd_name );
void Cmd_LookupCmds( void *buffer, void *ptr, setpair_t callback ); void Cmd_LookupCmds( void *buffer, void *ptr, setpair_t callback );
int Cmd_ListMaps( search_t *t , char *lastmapname, size_t len ); int Cmd_ListMaps( search_t *t , char *lastmapname, size_t len );
void Cmd_TokenizeString( const char *text ); void Cmd_TokenizeString( const char *text );
@@ -494,7 +477,7 @@ internal sound format
typically expanded to wav buffer typically expanded to wav buffer
======================================================================== ========================================================================
*/ */
typedef enum sndformat_e typedef enum
{ {
WF_UNKNOWN = 0, WF_UNKNOWN = 0,
WF_PCMDATA, WF_PCMDATA,
@@ -505,7 +488,7 @@ typedef enum sndformat_e
} sndformat_t; } sndformat_t;
// wavdata output flags // wavdata output flags
typedef enum sndFlags_e typedef enum
{ {
// wavdata->flags // wavdata->flags
SOUND_LOOPED = BIT( 0 ), // this is looped sound (contain cue markers) SOUND_LOOPED = BIT( 0 ), // this is looped sound (contain cue markers)
@@ -515,29 +498,29 @@ typedef enum sndFlags_e
SOUND_RESAMPLE = BIT( 12 ), // resample sound to specified rate SOUND_RESAMPLE = BIT( 12 ), // resample sound to specified rate
} sndFlags_t; } sndFlags_t;
typedef struct wavdata_s typedef struct
{ {
size_t size; // for bounds checking word rate; // num samples per second (e.g. 11025 - 11 khz)
byte width; // resolution - bum bits divided by 8 (8 bit is 1, 16 bit is 2)
byte channels; // num channels (1 - mono, 2 - stereo)
uint loopStart; // offset at this point sound will be looping while playing more than only once uint loopStart; // offset at this point sound will be looping while playing more than only once
uint samples; // total samplecount in wav uint samples; // total samplecount in wav
uint type; // compression type uint type; // compression type
uint flags; // misc sound flags uint flags; // misc sound flags
word rate; // num samples per second (e.g. 11025 - 11 khz) byte *buffer; // sound buffer
byte width; // resolution - bum bits divided by 8 (8 bit is 1, 16 bit is 2) size_t size; // for bounds checking
byte channels; // num channels (1 - mono, 2 - stereo)
byte buffer[]; // sound buffer
} wavdata_t; } wavdata_t;
// //
// soundlib // soundlib
// //
typedef struct stream_s stream_t;
void Sound_Init( void ); void Sound_Init( void );
void Sound_Shutdown( void ); void Sound_Shutdown( void );
void FS_FreeSound( wavdata_t *pack ); void FS_FreeSound( wavdata_t *pack );
void FS_FreeStream( stream_t *stream ); void FS_FreeStream( stream_t *stream );
wavdata_t *FS_LoadSound( const char *filename, const byte *buffer, size_t size ) MALLOC_LIKE( FS_FreeSound, 1 ) WARN_UNUSED_RESULT; wavdata_t *FS_LoadSound( const char *filename, const byte *buffer, size_t size ) MALLOC_LIKE( FS_FreeSound, 1 ) WARN_UNUSED_RESULT;
stream_t *FS_OpenStream( const char *filename ) MALLOC_LIKE( FS_FreeStream, 1 ) WARN_UNUSED_RESULT; stream_t *FS_OpenStream( const char *filename ) MALLOC_LIKE( FS_FreeStream, 1 ) WARN_UNUSED_RESULT;
wavdata_t *FS_StreamInfo( stream_t *stream );
int FS_ReadStream( stream_t *stream, int bytes, void *buffer ); int FS_ReadStream( stream_t *stream, int bytes, void *buffer );
int FS_SetStreamPos( stream_t *stream, int newpos ); int FS_SetStreamPos( stream_t *stream, int newpos );
int FS_GetStreamPos( stream_t *stream ); int FS_GetStreamPos( stream_t *stream );
@@ -551,7 +534,7 @@ qboolean Sound_SupportedFileFormat( const char *fileext );
typedef void( *pfnChangeGame )( const char *progname ); typedef void( *pfnChangeGame )( const char *progname );
qboolean Host_IsQuakeCompatible( void ); qboolean Host_IsQuakeCompatible( void );
void Host_ShutdownWithReason( const char *reason ); void EXPORT Host_Shutdown( void );
int EXPORT Host_Main( int argc, char **argv, const char *progname, int bChangeGame, pfnChangeGame func ); int EXPORT Host_Main( int argc, char **argv, const char *progname, int bChangeGame, pfnChangeGame func );
void Host_EndGame( qboolean abort, const char *message, ... ) FORMAT_CHECK( 2 ); void Host_EndGame( qboolean abort, const char *message, ... ) FORMAT_CHECK( 2 );
void Host_AbortCurrentFrame( void ) NORETURN; void Host_AbortCurrentFrame( void ) NORETURN;
@@ -559,11 +542,11 @@ void Host_WriteServerConfig( const char *name );
void Host_WriteOpenGLConfig( void ); void Host_WriteOpenGLConfig( void );
void Host_WriteVideoConfig( void ); void Host_WriteVideoConfig( void );
void Host_WriteConfig( void ); void Host_WriteConfig( void );
void Host_ShutdownServer( void );
void Host_Error( const char *error, ... ) FORMAT_CHECK( 1 ); void Host_Error( const char *error, ... ) FORMAT_CHECK( 1 );
void Host_ValidateEngineFeatures( uint32_t mask, uint32_t features ); void Host_ValidateEngineFeatures( uint32_t mask, uint32_t features );
void Host_Frame( double time ); void Host_Frame( double time );
void Host_Credits( void ); void Host_Credits( void );
void Host_ExitInMain( void );
// //
// host_state.c // host_state.c
@@ -582,19 +565,11 @@ CLIENT / SERVER SYSTEMS
============================================================== ==============================================================
*/ */
#if !XASH_DEDICATED
void CL_Init( void ); void CL_Init( void );
void CL_Shutdown( void ); void CL_Shutdown( void );
void Host_ClientBegin( void ); void Host_ClientBegin( void );
void Host_ClientFrame( void ); void Host_ClientFrame( void );
int CL_Active( void ); int CL_Active( void );
#else
static inline void CL_Init( void ) { }
static inline void CL_Shutdown( void ) { }
static inline void Host_ClientBegin( void ) { Cbuf_Execute(); }
static inline void Host_ClientFrame( void ) { }
static inline int CL_Active( void ) { return 0; }
#endif
void SV_Init( void ); void SV_Init( void );
void SV_Shutdown( const char *finalmsg ); void SV_Shutdown( const char *finalmsg );
@@ -611,7 +586,6 @@ qboolean SV_Active( void );
*/ */
char *COM_MemFgets( byte *pMemFile, int fileSize, int *filePos, char *pBuffer, int bufferSize ); char *COM_MemFgets( byte *pMemFile, int fileSize, int *filePos, char *pBuffer, int bufferSize );
void COM_HexConvert( const char *pszInput, int nInputLength, byte *pOutput ); void COM_HexConvert( const char *pszInput, int nInputLength, byte *pOutput );
byte COM_Nibble( char c );
int COM_SaveFile( const char *filename, const void *data, int len ); int COM_SaveFile( const char *filename, const void *data, int len );
byte *COM_LoadFileForMe( const char *filename, int *pLength ) MALLOC_LIKE( free, 1 ); byte *COM_LoadFileForMe( const char *filename, int *pLength ) MALLOC_LIKE( free, 1 );
qboolean COM_IsSafeFileToDownload( const char *filename ); qboolean COM_IsSafeFileToDownload( const char *filename );
@@ -632,7 +606,6 @@ int pfnNumberOfEntities( void );
int pfnIsInGame( void ); int pfnIsInGame( void );
float pfnTime( void ); float pfnTime( void );
#define copystring( s ) _copystring( host.mempool, s, __FILE__, __LINE__ ) #define copystring( s ) _copystring( host.mempool, s, __FILE__, __LINE__ )
#define copystringpool( pool, s ) _copystring( pool, s, __FILE__, __LINE__ )
#define SV_CopyString( s ) _copystring( svgame.stringspool, s, __FILE__, __LINE__ ) #define SV_CopyString( s ) _copystring( svgame.stringspool, s, __FILE__, __LINE__ )
#define freestring( s ) if( s != NULL ) { Mem_Free( s ); s = NULL; } #define freestring( s ) if( s != NULL ) { Mem_Free( s ); s = NULL; }
char *_copystring( poolhandle_t mempool, const char *s, const char *filename, int fileline ); char *_copystring( poolhandle_t mempool, const char *s, const char *filename, int fileline );
@@ -683,7 +656,6 @@ int CSCR_WriteGameCVars( file_t *cfg, const char *scriptfilename );
// //
// hpak.c // hpak.c
// //
const char *COM_ResourceTypeFromIndex( int index );
void HPAK_Init( void ); void HPAK_Init( void );
qboolean HPAK_GetDataPointer( const char *filename, struct resource_s *pRes, byte **buffer, int *size ); qboolean HPAK_GetDataPointer( const char *filename, struct resource_s *pRes, byte **buffer, int *size );
qboolean HPAK_ResourceForHash( const char *filename, byte *hash, struct resource_s *pRes ); qboolean HPAK_ResourceForHash( const char *filename, byte *hash, struct resource_s *pRes );
@@ -717,32 +689,13 @@ typedef enum connprotocol_e
struct physent_s; struct physent_s;
struct sv_client_s; struct sv_client_s;
typedef struct sizebuf_s sizebuf_t; typedef struct sizebuf_s sizebuf_t;
int SV_GetMaxClients( void );
#if !XASH_DEDICATED
qboolean CL_Initialized( void );
qboolean CL_IsInGame( void ); qboolean CL_IsInGame( void );
qboolean CL_IsInConsole( void ); qboolean CL_IsInConsole( void );
qboolean CL_IsIntermission( void ); qboolean CL_IsIntermission( void );
qboolean CL_DisableVisibility( void ); qboolean CL_Initialized( void );
qboolean CL_IsRecordDemo( void );
qboolean CL_IsPlaybackDemo( void );
qboolean UI_CreditsActive( void );
int CL_GetMaxClients( void );
#else
static inline qboolean CL_Initialized( void ) { return false; }
static inline qboolean CL_IsInGame( void ) { return true; } // always true for dedicated
static inline qboolean CL_IsInConsole( void ) { return false; }
static inline qboolean CL_IsIntermission( void ) { return false; }
static inline qboolean CL_DisableVisibility( void ) { return false; }
static inline qboolean CL_IsRecordDemo( void ) { return false; }
static inline qboolean CL_IsPlaybackDemo( void ) { return false; }
static inline qboolean UI_CreditsActive( void ) { return false; }
static inline int CL_GetMaxClients( void ) { return SV_GetMaxClients(); }
#endif
char *CL_Userinfo( void ); char *CL_Userinfo( void );
void CL_CharEvent( int key ); void CL_CharEvent( int key );
qboolean CL_DisableVisibility( void );
byte *COM_LoadFile( const char *filename, int usehunk, int *pLength ) MALLOC_LIKE( free, 1 ); byte *COM_LoadFile( const char *filename, int usehunk, int *pLength ) MALLOC_LIKE( free, 1 );
struct cmd_s *Cmd_GetFirstFunctionHandle( void ); struct cmd_s *Cmd_GetFirstFunctionHandle( void );
struct cmd_s *Cmd_GetNextFunctionHandle( struct cmd_s *cmd ); struct cmd_s *Cmd_GetNextFunctionHandle( struct cmd_s *cmd );
@@ -760,7 +713,13 @@ const char *CL_MsgInfo( int cmd );
void SV_DrawDebugTriangles( void ); void SV_DrawDebugTriangles( void );
void SV_DrawOrthoTriangles( void ); void SV_DrawOrthoTriangles( void );
double CL_GetDemoFramerate( void ); double CL_GetDemoFramerate( void );
qboolean UI_CreditsActive( void );
void CL_StopPlayback( void ); void CL_StopPlayback( void );
int CL_GetMaxClients( void );
int SV_GetMaxClients( void );
qboolean CL_IsRecordDemo( void );
qboolean CL_IsTimeDemo( void );
qboolean CL_IsPlaybackDemo( void );
qboolean SV_Initialized( void ); qboolean SV_Initialized( void );
void CL_ProcessFile( qboolean successfully_received, const char *filename ); void CL_ProcessFile( qboolean successfully_received, const char *filename );
int SV_GetSaveComment( const char *savename, char *comment ); int SV_GetSaveComment( const char *savename, char *comment );
@@ -873,6 +832,13 @@ void V_CheckGamma( void );
void V_CheckGammaEnd( void ); void V_CheckGammaEnd( void );
intptr_t V_GetGammaPtr( int parm ); intptr_t V_GetGammaPtr( int parm );
//
// identification.c
//
void ID_Init( void );
const char *ID_GetMD5( void );
void GAME_EXPORT ID_SetCustomClientID( const char *id );
// //
// masterlist.c // masterlist.c
// //
+46 -89
View File
@@ -498,6 +498,7 @@ static qboolean Cmd_GetSoundList( const char *s, char *completedname, int length
return true; return true;
} }
#if !XASH_DEDICATED
/* /*
===================================== =====================================
Cmd_GetItemsList Cmd_GetItemsList
@@ -507,7 +508,6 @@ Prints or complete item classname (weapons only)
*/ */
static qboolean Cmd_GetItemsList( const char *s, char *completedname, int length ) static qboolean Cmd_GetItemsList( const char *s, char *completedname, int length )
{ {
#if !XASH_DEDICATED
search_t *t; search_t *t;
string matchbuf; string matchbuf;
int i, numitems; int i, numitems;
@@ -521,7 +521,7 @@ static qboolean Cmd_GetItemsList( const char *s, char *completedname, int length
Q_strncpy( completedname, matchbuf, length ); Q_strncpy( completedname, matchbuf, length );
if( t->numfilenames == 1 ) return true; 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" )) if( Q_stricmp( COM_FileExtension( t->filenames[i] ), "txt" ))
continue; continue;
@@ -544,8 +544,6 @@ static qboolean Cmd_GetItemsList( const char *s, char *completedname, int length
} }
} }
return true; 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 ) static qboolean Cmd_GetKeysList( const char *s, char *completedname, int length )
{ {
#if !XASH_DEDICATED
size_t i, numkeys; size_t i, numkeys;
string keys[256]; string keys[256];
string matchbuf; string matchbuf;
@@ -598,9 +595,8 @@ static qboolean Cmd_GetKeysList( const char *s, char *completedname, int length
} }
return true; 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; con_autocomplete_t *list = (con_autocomplete_t*)_autocompleteList;
qboolean toggle = ptoggle != NULL && *(qboolean *)ptoggle;
if( *s == '@' ) return; // never show system cvars or cmds if( *s == '@' ) return; // never show system cvars or cmds
if( list->matchCount >= CON_MAXCMDS ) return; // list is full 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 ) ) ) if( Q_strnicmp( s, list->completionString, Q_strlen( list->completionString ) ) )
return; // no match return; // no match
@@ -645,11 +634,13 @@ Cmd_GetCommandsList
Autocomplete for bind command 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; size_t i;
string matchbuf; 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; list.completionString = s;
@@ -661,16 +652,8 @@ static qboolean Cmd_GetCommandsAndCvarsList( const char *s, char *completedname,
return false; return false;
// find matching commands and variables // find matching commands and variables
if( cvars ) Cmd_LookupCmds( NULL, &list, (setpair_t)Con_AddCommandToList );
{ Cvar_LookupVars( 0, NULL, &list, (setpair_t)Con_AddCommandToList );
Cvar_LookupVars( 0, &toggle, &list, (setpair_t)Con_AddCommandToList );
}
if( cmds )
{
toggle = false;
Cmd_LookupCmds( &toggle, &list, (setpair_t)Con_AddCommandToList );
}
if( !list.matchCount ) return false; if( !list.matchCount ) return false;
Q_strncpy( matchbuf, list.cmds[0], sizeof( matchbuf )); 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( "%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 ) if( completedname && length )
{ {
@@ -708,30 +691,6 @@ static qboolean Cmd_GetCommandsAndCvarsList( const char *s, char *completedname,
return true; 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,37 @@ int GAME_EXPORT Cmd_CheckMapsList( int fRefresh )
return Cmd_CheckMapsList_R( fRefresh, true ); return Cmd_CheckMapsList_R( fRefresh, true );
} }
// keep this sorted
static const autocomplete_list_t cmd_list[] = static const autocomplete_list_t cmd_list[] =
{ {
{ "bind", 1, Cmd_GetKeysList }, { "map_background", 1, Cmd_GetMapList },
{ "bind", 2, Cmd_GetCommandsList },
{ "cd", 1, Cmd_GetCDList },
{ "changelevel2", 1, Cmd_GetMapList }, { "changelevel2", 1, Cmd_GetMapList },
{ "changelevel", 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, }, { "playdemo", 1, Cmd_GetDemoList, },
{ "timedemo", 1, Cmd_GetDemoList, },
{ "listdemo", 1, Cmd_GetDemoList, },
{ "playvol", 1, Cmd_GetSoundList }, { "playvol", 1, Cmd_GetSoundList },
{ "reset", 1, Cmd_GetCvarsList }, { "hpkval", 1, Cmd_GetCustomList },
{ "save", 1, Cmd_GetSavesList }, { "hpklist", 1, Cmd_GetCustomList },
{ "set", 1, Cmd_GetCvarsList }, { "hpkextract", 1, Cmd_GetCustomList },
{ "timedemo", 1, Cmd_GetDemoList }, { "entpatch", 1, Cmd_GetMapList },
{ "toggle", 1, Cmd_GetCvarsList }, { "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 }, { "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 },
{ NULL }, // termiantor
}; };
/* /*
@@ -1115,12 +1073,12 @@ for various cmds
*/ */
static qboolean Cmd_AutocompleteName( const char *source, int arg, char *buffer, size_t bufsize ) static qboolean Cmd_AutocompleteName( const char *source, int arg, char *buffer, size_t bufsize )
{ {
int i; const autocomplete_list_t *list;
for( i = 0; i < ARRAYSIZE( cmd_list ); i++ ) for( list = cmd_list; list->name; list++ )
{ {
if( cmd_list[i].arg == arg && Cmd_CheckName( cmd_list[i].name )) if( list->arg == arg && Cmd_CheckName( list->name ))
return cmd_list[i].func( source, buffer, bufsize ); return list->func( source, buffer, bufsize );
} }
return false; return false;
@@ -1203,7 +1161,6 @@ void Con_CompleteCommand( field_t *field )
{ {
field_t temp; field_t temp;
string filename; string filename;
qboolean toggle = false;
qboolean nextcmd; qboolean nextcmd;
int i; int i;
@@ -1238,8 +1195,8 @@ void Con_CompleteCommand( field_t *field )
con.shortestMatch[0] = 0; con.shortestMatch[0] = 0;
// find matching commands and variables // find matching commands and variables
Cmd_LookupCmds( &toggle, &con, (setpair_t)Con_AddCommandToList ); Cmd_LookupCmds( NULL, &con, (setpair_t)Con_AddCommandToList );
Cvar_LookupVars( 0, &toggle, &con, (setpair_t)Con_AddCommandToList ); Cvar_LookupVars( 0, NULL, &con, (setpair_t)Con_AddCommandToList );
if( !con.matchCount ) return; // no matches if( !con.matchCount ) return; // no matches
@@ -1439,7 +1396,7 @@ void Host_WriteConfig( void )
{ {
Con_Reportf( "%s()\n", __func__ ); Con_Reportf( "%s()\n", __func__ );
FS_Printf( f, "//=======================================================================\n"); FS_Printf( f, "//=======================================================================\n");
FS_Printf( f, "//\tGenerated by "XASH_ENGINE_NAME" (%i, %s, %s, %s-%s)\n", Q_buildnum(), g_buildcommit, g_buildbranch, Q_buildos(), Q_buildarch()); FS_Printf( f, "//\tGenerated by "XASH_ENGINE_NAME" (%i, %s, %s, %s-%s)\n", Q_buildnum(), Q_buildcommit(), Q_buildbranch(), Q_buildos(), Q_buildarch());
FS_Printf( f, "//\t\tconfig.cfg - archive of cvars\n" ); FS_Printf( f, "//\t\tconfig.cfg - archive of cvars\n" );
FS_Printf( f, "//=======================================================================\n" ); FS_Printf( f, "//=======================================================================\n" );
Key_WriteBindings( f ); Key_WriteBindings( f );
@@ -1487,7 +1444,7 @@ void GAME_EXPORT Host_WriteServerConfig( const char *name )
if(( f = FS_Open( newconfigfile, "w", false )) != NULL ) if(( f = FS_Open( newconfigfile, "w", false )) != NULL )
{ {
FS_Printf( f, "//=======================================================================\n" ); FS_Printf( f, "//=======================================================================\n" );
FS_Printf( f, "//\tGenerated by "XASH_ENGINE_NAME" (%i, %s, %s, %s-%s)\n", Q_buildnum(), g_buildcommit, g_buildbranch, Q_buildos(), Q_buildarch()); FS_Printf( f, "//\tGenerated by "XASH_ENGINE_NAME" (%i, %s, %s, %s-%s)\n", Q_buildnum(), Q_buildcommit(), Q_buildbranch(), Q_buildos(), Q_buildarch());
FS_Printf( f, "//\t\tgame.cfg - multiplayer server temporare config\n" ); FS_Printf( f, "//\t\tgame.cfg - multiplayer server temporare config\n" );
FS_Printf( f, "//=======================================================================\n" ); FS_Printf( f, "//=======================================================================\n" );
@@ -1522,7 +1479,7 @@ void Host_WriteOpenGLConfig( void )
{ {
Con_Reportf( "%s()\n", __func__ ); Con_Reportf( "%s()\n", __func__ );
FS_Printf( f, "//=======================================================================\n" ); FS_Printf( f, "//=======================================================================\n" );
FS_Printf( f, "//\tGenerated by "XASH_ENGINE_NAME" (%i, %s, %s, %s-%s)\n", Q_buildnum(), g_buildcommit, g_buildbranch, Q_buildos(), Q_buildarch()); FS_Printf( f, "//\tGenerated by "XASH_ENGINE_NAME" (%i, %s, %s, %s-%s)\n", Q_buildnum(), Q_buildcommit(), Q_buildbranch(), Q_buildos(), Q_buildarch());
FS_Printf( f, "//\t\t%s - archive of renderer implementation cvars\n", name ); FS_Printf( f, "//\t\t%s - archive of renderer implementation cvars\n", name );
FS_Printf( f, "//=======================================================================\n" ); FS_Printf( f, "//=======================================================================\n" );
FS_Printf( f, "\n" ); FS_Printf( f, "\n" );
@@ -1552,7 +1509,7 @@ void Host_WriteVideoConfig( void )
{ {
Con_Reportf( "%s()\n", __func__ ); Con_Reportf( "%s()\n", __func__ );
FS_Printf( f, "//=======================================================================\n" ); FS_Printf( f, "//=======================================================================\n" );
FS_Printf( f, "//\tGenerated by "XASH_ENGINE_NAME" (%i, %s, %s, %s-%s)\n", Q_buildnum(), g_buildcommit, g_buildbranch, Q_buildos(), Q_buildarch()); FS_Printf( f, "//\tGenerated by "XASH_ENGINE_NAME" (%i, %s, %s, %s-%s)\n", Q_buildnum(), Q_buildcommit(), Q_buildbranch(), Q_buildos(), Q_buildarch());
FS_Printf( f, "//\t\tvideo.cfg - archive of renderer variables\n"); FS_Printf( f, "//\t\tvideo.cfg - archive of renderer variables\n");
FS_Printf( f, "//=======================================================================\n" ); FS_Printf( f, "//=======================================================================\n" );
Cvar_WriteVariables( f, FCVAR_RENDERINFO ); Cvar_WriteVariables( f, FCVAR_RENDERINFO );
@@ -1578,7 +1535,7 @@ void Key_EnumCmds_f( void )
if( f ) if( f )
{ {
FS_Printf( f, "//=======================================================================\n"); FS_Printf( f, "//=======================================================================\n");
FS_Printf( f, "//\tGenerated by "XASH_ENGINE_NAME" (%i, %s, %s, %s-%s)\n", Q_buildnum(), g_buildcommit, g_buildbranch, Q_buildos(), Q_buildarch()); FS_Printf( f, "//\tGenerated by "XASH_ENGINE_NAME" (%i, %s, %s, %s-%s)\n", Q_buildnum(), Q_buildcommit(), Q_buildbranch(), Q_buildos(), Q_buildarch());
FS_Printf( f, "//\t\thelp.txt - xash commands and console variables\n"); FS_Printf( f, "//\t\thelp.txt - xash commands and console variables\n");
FS_Printf( f, "//=======================================================================\n"); FS_Printf( f, "//=======================================================================\n");
+558
View File
@@ -0,0 +1,558 @@
/*
crashhandler.c - advanced crashhandler
Copyright (C) 2016 Mittorn
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
*/
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#include "common.h"
/*
================
Sys_Crash
Crash handler, called from system
================
*/
#if XASH_WIN32
#if DBGHELP
#pragma comment( lib, "dbghelp" )
#include <winnt.h>
#include <dbghelp.h>
#include <psapi.h>
#include <time.h>
#ifndef XASH_SDL
typedef ULONG_PTR DWORD_PTR, *PDWORD_PTR;
#endif
static int Sys_ModuleName( HANDLE process, char *name, void *address, int len )
{
DWORD_PTR baseAddress = 0;
static HMODULE *moduleArray;
static unsigned int moduleCount;
LPBYTE moduleArrayBytes;
DWORD bytesRequired;
int i;
if( len < 3 )
return 0;
if( !moduleArray && EnumProcessModules( process, NULL, 0, &bytesRequired ) )
{
if ( bytesRequired )
{
moduleArrayBytes = (LPBYTE)LocalAlloc( LPTR, bytesRequired );
if( moduleArrayBytes && EnumProcessModules( process, (HMODULE *)moduleArrayBytes, bytesRequired, &bytesRequired ) )
{
moduleCount = bytesRequired / sizeof( HMODULE );
moduleArray = (HMODULE *)moduleArrayBytes;
}
}
}
for( i = 0; i < moduleCount; i++ )
{
MODULEINFO info;
GetModuleInformation( process, moduleArray[i], &info, sizeof(MODULEINFO) );
if( ( address > info.lpBaseOfDll ) &&
( (DWORD64)address < (DWORD64)info.lpBaseOfDll + (DWORD64)info.SizeOfImage ) )
return GetModuleBaseName( process, moduleArray[i], name, len );
}
return Q_snprintf( name, len, "???" );
}
static void Sys_StackTrace( PEXCEPTION_POINTERS pInfo )
{
char message[8192]; // match *nix Sys_Crash
int len = 0;
size_t i;
HANDLE process = GetCurrentProcess();
HANDLE thread = GetCurrentThread();
IMAGEHLP_LINE64 line;
DWORD dline = 0;
DWORD options;
CONTEXT context;
STACKFRAME64 stackframe;
DWORD image;
context = *pInfo->ContextRecord;
options = SymGetOptions();
options |= SYMOPT_DEBUG;
options |= SYMOPT_LOAD_LINES;
SymSetOptions( options );
SymInitialize( process, NULL, TRUE );
ZeroMemory( &stackframe, sizeof( STACKFRAME64 ));
#ifdef _M_IX86
image = IMAGE_FILE_MACHINE_I386;
stackframe.AddrPC.Offset = context.Eip;
stackframe.AddrPC.Mode = AddrModeFlat;
stackframe.AddrFrame.Offset = context.Ebp;
stackframe.AddrFrame.Mode = AddrModeFlat;
stackframe.AddrStack.Offset = context.Esp;
stackframe.AddrStack.Mode = AddrModeFlat;
#elif _M_X64
image = IMAGE_FILE_MACHINE_AMD64;
stackframe.AddrPC.Offset = context.Rip;
stackframe.AddrPC.Mode = AddrModeFlat;
stackframe.AddrFrame.Offset = context.Rsp;
stackframe.AddrFrame.Mode = AddrModeFlat;
stackframe.AddrStack.Offset = context.Rsp;
stackframe.AddrStack.Mode = AddrModeFlat;
#elif _M_IA64
image = IMAGE_FILE_MACHINE_IA64;
stackframe.AddrPC.Offset = context.StIIP;
stackframe.AddrPC.Mode = AddrModeFlat;
stackframe.AddrFrame.Offset = context.IntSp;
stackframe.AddrFrame.Mode = AddrModeFlat;
stackframe.AddrBStore.Offset = context.RsBSP;
stackframe.AddrBStore.Mode = AddrModeFlat;
stackframe.AddrStack.Offset = context.IntSp;
stackframe.AddrStack.Mode = AddrModeFlat;
#elif _M_ARM
image = IMAGE_FILE_MACHINE_ARMNT;
stackframe.AddrPC.Offset = context.Pc;
stackframe.AddrPC.Mode = AddrModeFlat;
stackframe.AddrFrame.Offset = context.R11;
stackframe.AddrFrame.Mode = AddrModeFlat;
stackframe.AddrStack.Offset = context.Sp;
stackframe.AddrStack.Mode = AddrModeFlat;
#elif _M_ARM64
image = IMAGE_FILE_MACHINE_ARM64;
stackframe.AddrPC.Offset = context.Pc;
stackframe.AddrPC.Mode = AddrModeFlat;
stackframe.AddrFrame.Offset = context.Fp;
stackframe.AddrFrame.Mode = AddrModeFlat;
stackframe.AddrStack.Offset = context.Sp;
stackframe.AddrStack.Mode = AddrModeFlat;
#elif
#error
#endif
len = Q_snprintf( message, sizeof( message ), "Ver: " XASH_ENGINE_NAME " " XASH_VERSION " (build %i-%s, %s-%s)\n",
Q_buildnum(), Q_buildcommit(), Q_buildos(), Q_buildarch() );
len += Q_snprintf( message + len, 1024 - len, "Sys_Crash: address %p, code %p\n",
pInfo->ExceptionRecord->ExceptionAddress, (void*)pInfo->ExceptionRecord->ExceptionCode );
if( SymGetLineFromAddr64( process, (DWORD64)pInfo->ExceptionRecord->ExceptionAddress, &dline, &line ) )
{
len += Q_snprintf(message + len, 1024 - len, "Exception: %s:%d:%d\n",
(char*)line.FileName, (int)line.LineNumber, (int)dline);
}
if( SymGetLineFromAddr64( process, stackframe.AddrPC.Offset, &dline, &line ) )
{
len += Q_snprintf(message + len, 1024 - len,"PC: %s:%d:%d\n",
(char*)line.FileName, (int)line.LineNumber, (int)dline);
}
if( SymGetLineFromAddr64( process, stackframe.AddrFrame.Offset, &dline, &line ) )
{
len += Q_snprintf(message + len, 1024 - len,"Frame: %s:%d:%d\n",
(char*)line.FileName, (int)line.LineNumber, (int)dline);
}
for( i = 0; i < 25; i++ )
{
char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(TCHAR)];
PSYMBOL_INFO symbol = (PSYMBOL_INFO)buffer;
BOOL result = StackWalk64(
image, process, thread,
&stackframe, &context, NULL,
SymFunctionTableAccess64, SymGetModuleBase64, NULL);
DWORD64 displacement = 0;
if( !result )
break;
symbol->SizeOfStruct = sizeof(SYMBOL_INFO);
symbol->MaxNameLen = MAX_SYM_NAME;
len += Q_snprintf( message + len, 1024 - len, "% 2d %p",
i, (void*)stackframe.AddrPC.Offset );
if( SymFromAddr( process, stackframe.AddrPC.Offset, &displacement, symbol ) )
{
len += Q_snprintf( message + len, 1024 - len, " %s ", symbol->Name );
}
if( SymGetLineFromAddr64( process, stackframe.AddrPC.Offset, &dline, &line ) )
{
len += Q_snprintf(message + len, 1024 - len,"(%s:%d:%d) ",
(char*)line.FileName, (int)line.LineNumber, (int)dline);
}
len += Q_snprintf( message + len, 1024 - len, "(");
len += Sys_ModuleName( process, message + len, (void*)stackframe.AddrPC.Offset, 1024 - len );
len += Q_snprintf( message + len, 1024 - len, ")\n");
}
#if XASH_SDL == 2
if( host.type != HOST_DEDICATED ) // let system to restart server automaticly
SDL_ShowSimpleMessageBox( SDL_MESSAGEBOX_ERROR, "Sys_Crash", message, host.hWnd );
#endif
Sys_PrintLog( message );
SymCleanup( process );
}
static void Sys_GetProcessName( char *processName, size_t bufferSize )
{
char fullpath[MAX_PATH];
GetModuleBaseName( GetCurrentProcess(), NULL, fullpath, sizeof( fullpath ) - 1 );
COM_FileBase( fullpath, processName, bufferSize );
}
static void Sys_GetMinidumpFileName( const char *processName, char *mdmpFileName, size_t bufferSize )
{
time_t currentUtcTime = time( NULL );
struct tm *currentLocalTime = localtime( &currentUtcTime );
Q_snprintf( mdmpFileName, bufferSize, "%s_%s_crash_%d%.2d%.2d_%.2d%.2d%.2d.mdmp",
processName,
Q_buildcommit(),
currentLocalTime->tm_year + 1900,
currentLocalTime->tm_mon + 1,
currentLocalTime->tm_mday,
currentLocalTime->tm_hour,
currentLocalTime->tm_min,
currentLocalTime->tm_sec);
}
static qboolean Sys_WriteMinidump(PEXCEPTION_POINTERS exceptionInfo, MINIDUMP_TYPE minidumpType)
{
HRESULT errorCode;
string processName;
string mdmpFileName;
MINIDUMP_EXCEPTION_INFORMATION minidumpInfo;
Sys_GetProcessName( processName, sizeof( processName ));
Sys_GetMinidumpFileName( processName, mdmpFileName, sizeof( mdmpFileName ));
SetLastError( NOERROR );
HANDLE fileHandle = CreateFile(
mdmpFileName, GENERIC_WRITE, FILE_SHARE_WRITE,
NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
errorCode = HRESULT_FROM_WIN32( GetLastError( ));
if( !SUCCEEDED( errorCode )) {
CloseHandle( fileHandle );
return false;
}
minidumpInfo.ThreadId = GetCurrentThreadId();
minidumpInfo.ExceptionPointers = exceptionInfo;
minidumpInfo.ClientPointers = FALSE;
qboolean status = MiniDumpWriteDump(
GetCurrentProcess(), GetCurrentProcessId(), fileHandle,
minidumpType, &minidumpInfo, NULL, NULL);
CloseHandle( fileHandle );
return status;
}
#endif /* DBGHELP */
LPTOP_LEVEL_EXCEPTION_FILTER oldFilter;
static long _stdcall Sys_Crash( PEXCEPTION_POINTERS pInfo )
{
// save config
if( host.status != HOST_CRASHED )
{
// check to avoid recursive call
host.crashed = true;
#ifdef XASH_SDL
SDL_SetWindowGrab( host.hWnd, SDL_FALSE );
#endif // XASH_SDL
#if DBGHELP
Sys_StackTrace( pInfo );
#else
Sys_Warn( "Sys_Crash: call %p at address %p", pInfo->ExceptionRecord->ExceptionAddress, pInfo->ExceptionRecord->ExceptionCode );
#endif
if( host.type == HOST_NORMAL )
CL_Crashed(); // tell client about crash
else host.status = HOST_CRASHED;
#if DBGHELP
if( Sys_CheckParm( "-minidumps" ))
{
int minidumpFlags = (
MiniDumpWithDataSegs |
MiniDumpWithCodeSegs |
MiniDumpWithHandleData |
MiniDumpWithFullMemory |
MiniDumpWithFullMemoryInfo |
MiniDumpWithIndirectlyReferencedMemory |
MiniDumpWithThreadInfo |
MiniDumpWithModuleHeaders);
if( !Sys_WriteMinidump( pInfo, (MINIDUMP_TYPE)minidumpFlags )) {
// fallback method, create minidump with minimal info in it
Sys_WriteMinidump( pInfo, MiniDumpWithDataSegs );
}
}
#endif
if( host_developer.value <= 0 )
{
// no reason to call debugger in release build - just exit
Sys_Quit();
return EXCEPTION_CONTINUE_EXECUTION;
}
// all other states keep unchanged to let debugger find bug
Sys_DestroyConsole();
}
if( oldFilter )
return oldFilter( pInfo );
return EXCEPTION_CONTINUE_EXECUTION;
}
void Sys_SetupCrashHandler( void )
{
SetErrorMode( SEM_FAILCRITICALERRORS ); // no abort/retry/fail errors
oldFilter = SetUnhandledExceptionFilter( Sys_Crash );
}
void Sys_RestoreCrashHandler( void )
{
// restore filter
if( oldFilter ) SetUnhandledExceptionFilter( oldFilter );
}
#elif XASH_FREEBSD || XASH_NETBSD || XASH_OPENBSD || XASH_ANDROID || XASH_LINUX
// Posix signal handler
#ifndef XASH_OPENBSD
#include <ucontext.h>
#endif
#include <signal.h>
#include <sys/mman.h>
#include "library.h"
#define STACK_BACKTRACE_STR "Stack backtrace:\n"
#define STACK_DUMP_STR "Stack dump:\n"
#define STACK_BACKTRACE_STR_LEN ( sizeof( STACK_BACKTRACE_STR ) - 1 )
#define STACK_DUMP_STR_LEN ( sizeof( STACK_DUMP_STR ) - 1 )
#define ALIGN( x, y ) (((uintptr_t) ( x ) + (( y ) - 1 )) & ~(( y ) - 1 ))
static struct sigaction oldFilter;
static int Sys_PrintFrame( char *buf, int len, int i, void *addr )
{
Dl_info dlinfo;
if( len <= 0 )
return 0; // overflow
if( dladdr( addr, &dlinfo ))
{
if( dlinfo.dli_sname )
return Q_snprintf( buf, len, "%2d: %p <%s+%lu> (%s)\n", i, addr, dlinfo.dli_sname,
(unsigned long)addr - (unsigned long)dlinfo.dli_saddr, dlinfo.dli_fname ); // print symbol, module and address
return Q_snprintf( buf, len, "%2d: %p (%s)\n", i, addr, dlinfo.dli_fname ); // print module and address
}
return Q_snprintf( buf, len, "%2d: %p\n", i, addr ); // print only address
}
static void Sys_Crash( int signal, siginfo_t *si, void *context)
{
void *pc = NULL, **bp = NULL, **sp = NULL; // this must be set for every OS!
char message[8192];
int len, logfd, i = 0;
#if XASH_OPENBSD
struct sigcontext *ucontext = (struct sigcontext*)context;
#else
ucontext_t *ucontext = (ucontext_t*)context;
#endif
#if XASH_AMD64
#if XASH_FREEBSD
pc = (void*)ucontext->uc_mcontext.mc_rip;
bp = (void**)ucontext->uc_mcontext.mc_rbp;
sp = (void**)ucontext->uc_mcontext.mc_rsp;
#elif XASH_NETBSD
pc = (void*)ucontext->uc_mcontext.__gregs[_REG_RIP];
bp = (void**)ucontext->uc_mcontext.__gregs[_REG_RBP];
sp = (void**)ucontext->uc_mcontext.__gregs[_REG_RSP];
#elif XASH_OPENBSD
pc = (void*)ucontext->sc_rip;
bp = (void**)ucontext->sc_rbp;
sp = (void**)ucontext->sc_rsp;
#else
pc = (void*)ucontext->uc_mcontext.gregs[REG_RIP];
bp = (void**)ucontext->uc_mcontext.gregs[REG_RBP];
sp = (void**)ucontext->uc_mcontext.gregs[REG_RSP];
#endif
#elif XASH_X86
#if XASH_FREEBSD
pc = (void*)ucontext->uc_mcontext.mc_eip;
bp = (void**)ucontext->uc_mcontext.mc_ebp;
sp = (void**)ucontext->uc_mcontext.mc_esp;
#elif XASH_NETBSD
pc = (void*)ucontext->uc_mcontext.__gregs[_REG_EIP];
bp = (void**)ucontext->uc_mcontext.__gregs[_REG_EBP];
sp = (void**)ucontext->uc_mcontext.__gregs[_REG_ESP];
#elif XASH_OPENBSD
pc = (void*)ucontext->sc_eip;
bp = (void**)ucontext->sc_ebp;
sp = (void**)ucontext->sc_esp;
#else
pc = (void*)ucontext->uc_mcontext.gregs[REG_EIP];
bp = (void**)ucontext->uc_mcontext.gregs[REG_EBP];
sp = (void**)ucontext->uc_mcontext.gregs[REG_ESP];
#endif
#elif XASH_ARM && XASH_64BIT
pc = (void*)ucontext->uc_mcontext.pc;
bp = (void*)ucontext->uc_mcontext.regs[29];
sp = (void*)ucontext->uc_mcontext.sp;
#elif XASH_ARM
pc = (void*)ucontext->uc_mcontext.arm_pc;
bp = (void*)ucontext->uc_mcontext.arm_fp;
sp = (void*)ucontext->uc_mcontext.arm_sp;
#endif
// safe actions first, stack and memory may be corrupted
len = Q_snprintf( message, sizeof( message ), "Ver: " XASH_ENGINE_NAME " " XASH_VERSION " (build %i-%s, %s-%s)\n",
Q_buildnum(), Q_buildcommit(), Q_buildos(), Q_buildarch() );
#if !XASH_FREEBSD && !XASH_NETBSD && !XASH_OPENBSD
len += Q_snprintf( message + len, sizeof( message ) - len, "Crash: signal %d errno %d with code %d at %p %p\n", signal, si->si_errno, si->si_code, si->si_addr, si->si_ptr );
#else
len += Q_snprintf( message + len, sizeof( message ) - len, "Crash: signal %d errno %d with code %d at %p\n", signal, si->si_errno, si->si_code, si->si_addr );
#endif
write( STDERR_FILENO, message, len );
// flush buffers before writing directly to descriptors
fflush( stdout );
fflush( stderr );
// now get log fd and write trace directly to log
logfd = Sys_LogFileNo();
write( logfd, message, len );
if( pc && bp && sp )
{
size_t pagesize = sysconf( _SC_PAGESIZE );
// try to print backtrace
write( STDERR_FILENO, STACK_BACKTRACE_STR, STACK_BACKTRACE_STR_LEN );
write( logfd, STACK_BACKTRACE_STR, STACK_BACKTRACE_STR_LEN );
Q_strncpy( message + len, STACK_BACKTRACE_STR, sizeof( message ) - len );
len += STACK_BACKTRACE_STR_LEN;
// false on success, true on failure
#define try_allow_read(pointer, pagesize) \
((mprotect( (char *)ALIGN( (pointer), (pagesize) ), (pagesize), PROT_READ | PROT_WRITE | PROT_EXEC ) == -1) && \
( mprotect( (char *)ALIGN( (pointer), (pagesize) ), (pagesize), PROT_READ | PROT_EXEC ) == -1) && \
( mprotect( (char *)ALIGN( (pointer), (pagesize) ), (pagesize), PROT_READ | PROT_WRITE ) == -1) && \
( mprotect( (char *)ALIGN( (pointer), (pagesize) ), (pagesize), PROT_READ ) == -1))
do
{
int line = Sys_PrintFrame( message + len, sizeof( message ) - len, ++i, pc);
write( STDERR_FILENO, message + len, line );
write( logfd, message + len, line );
len += line;
//if( !dladdr(bp,0) ) break; // only when bp is in module
if( try_allow_read( bp, pagesize ) )
break;
if( try_allow_read( bp[0], pagesize ) )
break;
pc = bp[1];
bp = (void**)bp[0];
}
while( bp && i < 128 );
// try to print stack
write( STDERR_FILENO, STACK_DUMP_STR, STACK_DUMP_STR_LEN );
write( logfd, STACK_DUMP_STR, STACK_DUMP_STR_LEN );
Q_strncpy( message + len, STACK_DUMP_STR, sizeof( message ) - len );
len += STACK_DUMP_STR_LEN;
if( !try_allow_read( sp, pagesize ) )
{
for( i = 0; i < 32; i++ )
{
int line = Sys_PrintFrame( message + len, sizeof( message ) - len, i, sp[i] );
write( STDERR_FILENO, message + len, line );
write( logfd, message + len, line );
len += line;
}
}
#undef try_allow_read
}
// put MessageBox as Sys_Error
Msg( "%s\n", message );
#ifdef XASH_SDL
SDL_SetWindowGrab( host.hWnd, SDL_FALSE );
#endif
host.crashed = true;
Platform_MessageBox( "Xash Error", message, false );
// log saved, now we can try to save configs and close log correctly, it may crash
if( host.type == HOST_NORMAL )
CL_Crashed();
host.status = HOST_CRASHED;
Sys_Quit();
}
void Sys_SetupCrashHandler( void )
{
struct sigaction act = { 0 };
act.sa_sigaction = Sys_Crash;
act.sa_flags = SA_SIGINFO | SA_ONSTACK;
sigaction( SIGSEGV, &act, &oldFilter );
sigaction( SIGABRT, &act, &oldFilter );
sigaction( SIGBUS, &act, &oldFilter );
sigaction( SIGILL, &act, &oldFilter );
}
void Sys_RestoreCrashHandler( void )
{
sigaction( SIGSEGV, &oldFilter, NULL );
sigaction( SIGABRT, &oldFilter, NULL );
sigaction( SIGBUS, &oldFilter, NULL );
sigaction( SIGILL, &oldFilter, NULL );
}
#else
void Sys_SetupCrashHandler( void )
{
// stub
}
void Sys_RestoreCrashHandler( void )
{
// stub
}
#endif
+13 -23
View File
@@ -19,7 +19,6 @@ GNU General Public License for more details.
#include "eiface.h" // ARRAYSIZE #include "eiface.h" // ARRAYSIZE
static convar_t *cvar_vars = NULL; // head of list static convar_t *cvar_vars = NULL; // head of list
static poolhandle_t cvar_pool;
CVAR_DEFINE_AUTO( cmd_scripting, "0", FCVAR_ARCHIVE|FCVAR_PRIVILEGED, "enable simple condition checking and variable operations" ); CVAR_DEFINE_AUTO( cmd_scripting, "0", FCVAR_ARCHIVE|FCVAR_PRIVILEGED, "enable simple condition checking and variable operations" );
typedef struct cvar_filter_quirks_s typedef struct cvar_filter_quirks_s
@@ -433,7 +432,7 @@ convar_t *Cvar_Get( const char *name, const char *value, int flags, const char *
{ {
// directly set value // directly set value
freestring( var->string ); freestring( var->string );
var->string = copystringpool( cvar_pool, value ); var->string = copystring( value );
var->value = Q_atof( var->string ); var->value = Q_atof( var->string );
SetBits( var->flags, flags ); SetBits( var->flags, flags );
@@ -453,18 +452,18 @@ convar_t *Cvar_Get( const char *name, const char *value, int flags, const char *
Con_Reportf( "%s change description from %s to %s\n", var->name, var->desc, var_desc ); Con_Reportf( "%s change description from %s to %s\n", var->name, var->desc, var_desc );
// update description if needs // update description if needs
freestring( var->desc ); freestring( var->desc );
var->desc = copystringpool( cvar_pool, var_desc ); var->desc = copystring( var_desc );
} }
return var; return var;
} }
// allocate a new cvar // allocate a new cvar
var = Mem_Malloc( cvar_pool, sizeof( *var )); var = Z_Malloc( sizeof( *var ));
var->name = copystringpool( cvar_pool, name ); var->name = copystring( name );
var->string = copystringpool( cvar_pool, value ); var->string = copystring( value );
var->def_string = copystringpool( cvar_pool, value ); var->def_string = copystring( value );
var->desc = copystringpool( cvar_pool, var_desc ); var->desc = copystring( var_desc );
var->value = Q_atof( var->string ); var->value = Q_atof( var->string );
var->flags = flags|FCVAR_ALLOCATED; var->flags = flags|FCVAR_ALLOCATED;
@@ -550,7 +549,7 @@ void Cvar_RegisterVariable( convar_t *var )
if( FBitSet( var->flags, FCVAR_EXTENDED )) if( FBitSet( var->flags, FCVAR_EXTENDED ))
var->def_string = var->string; // just swap pointers var->def_string = var->string; // just swap pointers
var->string = copystringpool( cvar_pool, var->string ); var->string = copystring( var->string );
var->value = Q_atof( var->string ); var->value = Q_atof( var->string );
// find the supposed position in chain (alphanumerical order) // find the supposed position in chain (alphanumerical order)
@@ -680,7 +679,7 @@ static convar_t *Cvar_Set2( const char *var_name, const char *value )
// and finally changed the cvar itself // and finally changed the cvar itself
freestring( var->string ); freestring( var->string );
var->string = copystringpool( cvar_pool, pszValue ); var->string = copystring( pszValue );
var->value = Q_atof( var->string ); var->value = Q_atof( var->string );
// tell engine about changes // tell engine about changes
@@ -739,7 +738,7 @@ void GAME_EXPORT Cvar_DirectSet( convar_t *var, const char *value )
// and finally changed the cvar itself // and finally changed the cvar itself
freestring( var->string ); freestring( var->string );
var->string = copystringpool( cvar_pool, pszValue ); var->string = copystring( pszValue );
var->value = Q_atof( var->string ); var->value = Q_atof( var->string );
// tell engine about changes // tell engine about changes
@@ -782,7 +781,7 @@ void Cvar_FullSet( const char *var_name, const char *value, int flags )
} }
freestring( var->string ); freestring( var->string );
var->string = copystringpool( cvar_pool, value ); var->string = copystring( value );
var->value = Q_atof( var->string ); var->value = Q_atof( var->string );
SetBits( var->flags, flags ); SetBits( var->flags, flags );
@@ -1190,7 +1189,6 @@ static void Cvar_List_f( void )
for( var = cvar_vars; var; var = var->next ) for( var = cvar_vars; var; var = var->next )
{ {
char value[MAX_VA_STRING]; char value[MAX_VA_STRING];
char *p;
if( var->name[0] == '@' ) if( var->name[0] == '@' )
continue; // never shows system cvars continue; // never shows system cvars
@@ -1198,9 +1196,7 @@ static void Cvar_List_f( void )
if( match && !Q_strnicmpext( match, var->name, matchlen )) if( match && !Q_strnicmpext( match, var->name, matchlen ))
continue; continue;
p = Q_strchr( var->string, '^' ); if( Q_colorstr( var->string ))
if( IsColorString( p ))
Q_snprintf( value, sizeof( value ), "\"%s\"", var->string ); Q_snprintf( value, sizeof( value ), "\"%s\"", var->string );
else Q_snprintf( value, sizeof( value ), "\"^2%s^7\"", var->string ); else Q_snprintf( value, sizeof( value ), "\"^2%s^7\"", var->string );
@@ -1261,7 +1257,7 @@ pending_cvar_t *Cvar_PrepareToUnlink( int group )
continue; continue;
namelen = Q_strlen( cv->name ) + 1; namelen = Q_strlen( cv->name ) + 1;
p = Mem_Malloc( cvar_pool, sizeof( *list ) + namelen ); p = Mem_Malloc( host.mempool, sizeof( *list ) + namelen );
p->next = NULL; p->next = NULL;
p->cv_cur = cv; p->cv_cur = cv;
p->cv_next = cv->next; p->cv_next = cv->next;
@@ -1337,7 +1333,6 @@ Reads in all archived cvars
*/ */
void Cvar_Init( void ) void Cvar_Init( void )
{ {
cvar_pool = Mem_AllocPool( "Console Variables" );
cvar_vars = NULL; cvar_vars = NULL;
cvar_active_filter_quirks = NULL; cvar_active_filter_quirks = NULL;
Cvar_RegisterVariable( &cmd_scripting ); Cvar_RegisterVariable( &cmd_scripting );
@@ -1350,11 +1345,6 @@ void Cvar_Init( void )
Cmd_AddCommand( "cvarlist", Cvar_List_f, "display all console variables beginning with the specified prefix" ); Cmd_AddCommand( "cvarlist", Cvar_List_f, "display all console variables beginning with the specified prefix" );
} }
void Cvar_Shutdown( void )
{
Mem_FreePool( &cvar_pool );
}
/* /*
============ ============
Cvar_PostFSInit Cvar_PostFSInit
-3
View File
@@ -30,8 +30,6 @@ typedef struct pending_cvar_s
char cv_name[]; char cv_name[];
} pending_cvar_t; } pending_cvar_t;
typedef void (*setpair_t)( const char *key, const void *value, const void *buffer, void *numpairs );
cvar_t *Cvar_GetList( void ); cvar_t *Cvar_GetList( void );
#define Cvar_FindVar( name ) Cvar_FindVarExt( name, 0 ) #define Cvar_FindVar( name ) Cvar_FindVarExt( name, 0 )
convar_t *Cvar_FindVarExt( const char *var_name, int ignore_group ); convar_t *Cvar_FindVarExt( const char *var_name, int ignore_group );
@@ -54,7 +52,6 @@ void Cvar_Reset( const char *var_name );
void Cvar_SetCheatState( void ); void Cvar_SetCheatState( void );
qboolean Cvar_CommandWithPrivilegeCheck( convar_t *v, qboolean isPrivileged ); qboolean Cvar_CommandWithPrivilegeCheck( convar_t *v, qboolean isPrivileged );
void Cvar_Init( void ); void Cvar_Init( void );
void Cvar_Shutdown( void );
void Cvar_PostFSInit( void ); void Cvar_PostFSInit( void );
void Cvar_Unlink( int group ); void Cvar_Unlink( int group );
+76
View File
@@ -49,6 +49,52 @@ const char *CL_MsgInfo( int cmd )
return sz; return sz;
} }
int GAME_EXPORT CL_Active( void )
{
return false;
}
qboolean CL_Initialized( void )
{
return false;
}
qboolean CL_IsInGame( void )
{
return true; // always active for dedicated servers
}
qboolean CL_IsInConsole( void )
{
return false;
}
qboolean CL_IsIntermission( void )
{
return false;
}
qboolean CL_IsPlaybackDemo( void )
{
return false;
}
qboolean CL_IsRecordDemo( void )
{
return false;
}
qboolean CL_DisableVisibility( void )
{
return false;
}
void CL_Init( void )
{
}
void Key_Init( void ) void Key_Init( void )
{ {
@@ -84,6 +130,16 @@ void CL_WriteMessageHistory( void )
} }
void Host_ClientBegin( void )
{
Cbuf_Execute();
}
void Host_ClientFrame( void )
{
}
void Host_InputFrame( void ) void Host_InputFrame( void )
{ {
} }
@@ -103,6 +159,11 @@ void GAME_EXPORT S_StopSound(int entnum, int channel, const char *soundname)
} }
int GAME_EXPORT CL_GetMaxClients( void )
{
return 0;
}
void IN_TouchInitConfig( void ) void IN_TouchInitConfig( void )
{ {
@@ -113,6 +174,11 @@ void CL_Disconnect( void )
} }
void CL_Shutdown( void )
{
}
void R_ClearStaticEntities( void ) void R_ClearStaticEntities( void )
{ {
@@ -123,6 +189,11 @@ void Host_Credits( void )
} }
qboolean UI_CreditsActive( void )
{
return false;
}
void S_StopBackgroundTrack( void ) void S_StopBackgroundTrack( void )
{ {
@@ -133,6 +204,11 @@ void SCR_BeginLoadingPlaque( qboolean is_background )
} }
int S_GetCurrentDynamicSounds( soundlist_t *pout, int size )
{
return 0;
}
void S_StopAllSounds( qboolean ambient ) void S_StopAllSounds( qboolean ambient )
{ {
+5 -51
View File
@@ -1,4 +1,4 @@
/* /*
filesystem.c - game filesystem based on DP fs filesystem.c - game filesystem based on DP fs
Copyright (C) 2003-2006 Mathieu Olivier Copyright (C) 2003-2006 Mathieu Olivier
Copyright (C) 2000-2007 DarkPlaces contributors Copyright (C) 2000-2007 DarkPlaces contributors
@@ -21,12 +21,6 @@ GNU General Public License for more details.
#include "library.h" #include "library.h"
#include "platform/platform.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_api_t g_fsapi;
fs_globals_t *FI; fs_globals_t *FI;
@@ -75,23 +69,9 @@ void *FS_GetNativeObject( const char *obj )
return NULL; return NULL;
} }
void FS_Rescan_f( void ) static void FS_Rescan_f( void )
{ {
uint32_t flags = 0; FS_Rescan();
// FIXME: VFS shouldn't care about this, allow engine to mount gamedirs
if( fs_mount_lv.value ) SetBits( flags, FS_MOUNT_LV );
if( fs_mount_hd.value ) SetBits( flags, FS_MOUNT_HD );
if( fs_mount_addon.value ) SetBits( flags, FS_MOUNT_ADDON );
if( fs_mount_l10n.value ) SetBits( flags, FS_MOUNT_L10N );
g_fsapi.Rescan( flags, ui_language.string );
ClearBits( fs_mount_lv.flags, FCVAR_CHANGED );
ClearBits( fs_mount_hd.flags, FCVAR_CHANGED );
ClearBits( fs_mount_addon.flags, FCVAR_CHANGED );
ClearBits( fs_mount_l10n.flags, FCVAR_CHANGED );
ClearBits( ui_language.flags, FCVAR_CHANGED );
} }
static void FS_ClearPaths_f( void ) static void FS_ClearPaths_f( void )
@@ -104,11 +84,6 @@ static void FS_Path_f_( void )
FS_Path_f(); FS_Path_f();
} }
static void FS_MakeGameInfo_f( void )
{
g_fsapi.MakeGameInfo();
}
static const fs_interface_t fs_memfuncs = static const fs_interface_t fs_memfuncs =
{ {
Con_Printf, Con_Printf,
@@ -203,23 +178,14 @@ static qboolean FS_DetermineRootDirectory( char *out, size_t size )
#elif XASH_PSVITA #elif XASH_PSVITA
if( PSVita_GetBasePath( out, size )) if( PSVita_GetBasePath( out, size ))
return true; return true;
Sys_Error( "couldn't find %s data directory", XASH_ENGINE_NAME ); Sys_Error( "couldn't find Xash3D data directory" );
return false; return false;
#elif ( XASH_SDL == 2 ) && !XASH_NSWITCH // GetBasePath not impl'd in switch-sdl2 #elif ( XASH_SDL == 2 ) && !XASH_NSWITCH // GetBasePath not impl'd in switch-sdl2
path = SDL_GetBasePath(); path = SDL_GetBasePath();
#if XASH_APPLE
if( path != NULL && Q_stristr( path, ".app" ))
{
SDL_free((void *)path );
path = SDL_GetPrefPath( NULL, XASH_ENGINE_NAME );
}
#endif
if( path != NULL ) if( path != NULL )
{ {
Q_strncpy( out, path, size ); Q_strncpy( out, path, size );
SDL_free((void *)path ); SDL_free(( void *)path );
return true; return true;
} }
@@ -256,12 +222,6 @@ static qboolean FS_DetermineReadOnlyRootDirectory( char *out, size_t size )
return false; 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 FS_Init
@@ -312,12 +272,6 @@ void FS_Init( const char *basedir )
Cmd_AddRestrictedCommand( "fs_rescan", FS_Rescan_f, "rescan filesystem search pathes" ); Cmd_AddRestrictedCommand( "fs_rescan", FS_Rescan_f, "rescan filesystem search pathes" );
Cmd_AddRestrictedCommand( "fs_path", FS_Path_f_, "show filesystem search pathes" ); Cmd_AddRestrictedCommand( "fs_path", FS_Path_f_, "show filesystem search pathes" );
Cmd_AddRestrictedCommand( "fs_clearpaths", FS_ClearPaths_f, "clear filesystem search pathes" ); 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 )) if( !Sys_GetParmFromCmdLine( "-dll", host.gamedll ))
host.gamedll[0] = 0; host.gamedll[0] = 0;
+41 -88
View File
@@ -43,27 +43,6 @@ GNU General Public License for more details.
static pfnChangeGame pChangeGame = NULL; static pfnChangeGame pChangeGame = NULL;
host_parm_t host; // host parms host_parm_t host; // host parms
#if XASH_ANDROID
static jmp_buf return_from_main_buf;
/*
===============
Host_ExitInMain
On some platforms (e.g. Android) we can't exit with exit(3) as calling it would
kill wrapper process (e.g. app_process) too early, before all resources would
be freed, contexts released, files closed, etc, etc...
To fix this, we create jmp_buf in Host_Main function, when jumping into with
non-zero value will immediately return from it with `error_on_exit`.
===============
*/
void Host_ExitInMain( void )
{
longjmp( return_from_main_buf, 1 );
}
#endif // XASH_ANDROID
#ifdef XASH_ENGINE_TESTS #ifdef XASH_ENGINE_TESTS
struct tests_stats_s tests_stats; struct tests_stats_s tests_stats;
#endif #endif
@@ -140,8 +119,7 @@ static void Sys_PrintUsage( const char *exename )
"\nCommon options:\n" "\nCommon options:\n"
O("-dev [level] ", "set log verbosity 0-2") O("-dev [level] ", "set log verbosity 0-2")
O("-log [file name] ", "write log to \"engine.log\" or [file name] if specified") O("-log ", "write log to \"engine.log\"")
O("-logtime ", "enable writing timestamps to the log file")
O("-nowriteconfig ", "disable config save") O("-nowriteconfig ", "disable config save")
O("-noch ", "disable crashhandler") O("-noch ", "disable crashhandler")
#if XASH_WIN32 // !!!! #if XASH_WIN32 // !!!!
@@ -202,6 +180,7 @@ static void Sys_PrintUsage( const char *exename )
O("-daemonize ", "run engine as a daemon") O("-daemonize ", "run engine as a daemon")
#endif #endif
#if XASH_SDL == 2 #if XASH_SDL == 2
O("-sdl_joy_old_api ","use SDL legacy joystick API")
O("-sdl_renderer <n> ","use alternative SDL_Renderer for software") O("-sdl_renderer <n> ","use alternative SDL_Renderer for software")
#endif // XASH_SDL #endif // XASH_SDL
#if XASH_ANDROID && !XASH_SDL #if XASH_ANDROID && !XASH_SDL
@@ -230,7 +209,7 @@ static void Sys_PrintUsage( const char *exename )
fprintf( stderr, usage_str, exename ); fprintf( stderr, usage_str, exename );
#endif #endif
Sys_Quit( NULL ); Sys_Quit();
} }
static void Sys_PrintBugcompUsage( const char *exename ) static void Sys_PrintBugcompUsage( const char *exename )
@@ -255,7 +234,12 @@ static void Sys_PrintBugcompUsage( const char *exename )
fprintf( stderr, usage_str, exename ); fprintf( stderr, usage_str, exename );
#endif #endif
Sys_Quit( NULL ); Sys_Quit();
}
void Host_ShutdownServer( void )
{
SV_Shutdown( "Server was killed\n" );
} }
/* /*
@@ -383,8 +367,9 @@ static void Host_NewInstance( const char *name, const char *finalmsg )
if( !pChangeGame ) return; if( !pChangeGame ) return;
host.change_game = true; host.change_game = true;
Q_strncpy( host.finalmsg, finalmsg, sizeof( host.finalmsg ));
if( !Sys_NewInstance( name, finalmsg )) if( !Sys_NewInstance( name ))
pChangeGame( name ); // call from hl.exe pChangeGame( name ); // call from hl.exe
} }
@@ -438,7 +423,8 @@ static void Host_Exec_f( void )
{ {
string cfgpath; string cfgpath;
byte *f; byte *f;
fs_offset_t len; char *txt;
fs_offset_t len;
if( Cmd_Argc() != 2 ) if( Cmd_Argc() != 2 )
{ {
@@ -493,29 +479,20 @@ static void Host_Exec_f( void )
return; return;
} }
// len is fs_offset_t, which can be larger than size_t
if( len >= SIZE_MAX )
{
Con_Reportf( "%s: %s is too long\n", __func__, Cmd_Argv( 1 ));
return;
}
if( !Q_stricmp( "config.cfg", cfgpath )) if( !Q_stricmp( "config.cfg", cfgpath ))
host.config_executed = true; host.config_executed = true;
// adds \n\0 at end of the file
txt = Z_Calloc( len + 2 );
memcpy( txt, f, len );
txt[len] = '\n';
txt[len + 1] = '\0';
Mem_Free( f );
if( !host.apply_game_config ) if( !host.apply_game_config )
Con_Printf( "execing %s\n", Cmd_Argv( 1 )); Con_Printf( "execing %s\n", Cmd_Argv( 1 ));
Cbuf_InsertText( txt );
// adds \n at end of the file Mem_Free( txt );
// FS_LoadFile always null terminates
if( f[len - 1] != '\n' )
{
Cbuf_InsertTextLen( f, len, len + 1 );
Cbuf_InsertTextLen( "\n", 1, 1 );
}
else Cbuf_InsertTextLen( f, len, len );
Mem_Free( f );
} }
/* /*
@@ -618,7 +595,7 @@ static void Host_GetCommands( void )
{ {
char *cmd; char *cmd;
while( ( cmd = Platform_Input() ) ) while( ( cmd = Sys_Input() ) )
{ {
Cbuf_AddText( cmd ); Cbuf_AddText( cmd );
Cbuf_Execute(); Cbuf_Execute();
@@ -698,17 +675,17 @@ static qboolean Host_Autosleep( double dt, double scale )
static double timewindow; // allocate a time window for sleeps static double timewindow; // allocate a time window for sleeps
static int counter; // for debug static int counter; // for debug
static double realsleeptime; static double realsleeptime;
const double sleeptime = sleep * 0.000001; const double sleeptime = sleep * 0.001;
if( dt < targetframetime * scale ) if( dt < targetframetime * scale )
{ {
// if we have allocated time window, try to sleep // if we have allocated time window, try to sleep
if( timewindow > realsleeptime ) 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 // so we measure the real sleep time and use it to decrease the window
double t1 = Sys_DoubleTime(), t2; double t1 = Sys_DoubleTime(), t2;
Platform_NanoSleep( sleep * 1000 ); // in usec! Platform_Sleep( sleep ); // in msec!
t2 = Sys_DoubleTime(); t2 = Sys_DoubleTime();
realsleeptime = t2 - t1; realsleeptime = t2 - t1;
@@ -837,11 +814,11 @@ void GAME_EXPORT Host_Error( const char *error, ... )
} }
else else
{ {
Con_Printf( "%s: %s", __func__, hosterror1 );
if( host.allow_console ) if( host.allow_console )
{ {
UI_SetActiveMenu( false ); UI_SetActiveMenu( false );
Key_SetKeyDest( key_console ); Key_SetKeyDest( key_console );
Con_Printf( "%s: %s", __func__, hosterror1 );
} }
else Platform_MessageBox( "Host Error", hosterror1, true ); else Platform_MessageBox( "Host Error", hosterror1, true );
} }
@@ -858,12 +835,13 @@ void GAME_EXPORT Host_Error( const char *error, ... )
recursive = true; recursive = true;
Q_strncpy( hosterror2, hosterror1, sizeof( hosterror2 )); Q_strncpy( hosterror2, hosterror1, sizeof( hosterror2 ));
host.errorframe = host.framecount; // to avoid multply calls per frame host.errorframe = host.framecount; // to avoid multply calls per frame
Q_snprintf( host.finalmsg, sizeof( host.finalmsg ), "Server crashed: %s", hosterror1 );
// clearing cmd buffer to prevent execute any commands // clearing cmd buffer to prevent execute any commands
COM_InitHostState(); COM_InitHostState();
Cbuf_Clear(); Cbuf_Clear();
SV_Shutdown( "Server was killed due to an error\n" ); Host_ShutdownServer();
CL_Drop(); // drop clients CL_Drop(); // drop clients
// recreate world if needs // recreate world if needs
@@ -942,7 +920,7 @@ static void Host_RunTests( int stage )
#endif #endif
Msg( "Done! %d passed, %d failed\n", tests_stats.passed, tests_stats.failed ); Msg( "Done! %d passed, %d failed\n", tests_stats.passed, tests_stats.failed );
error_on_exit = tests_stats.failed > 0 ? EXIT_FAILURE : EXIT_SUCCESS; error_on_exit = tests_stats.failed > 0 ? EXIT_FAILURE : EXIT_SUCCESS;
Sys_Quit( NULL ); Sys_Quit();
} }
} }
#endif #endif
@@ -1044,7 +1022,7 @@ static void Host_InitCommon( int argc, char **argv, const char *progname, qboole
} }
if( !Sys_CheckParm( "-noch" )) if( !Sys_CheckParm( "-noch" ))
Sys_SetupCrashHandler( argv[0] ); Sys_SetupCrashHandler();
#if XASH_DLL_LOADER #if XASH_DLL_LOADER
host.enabledll = !Sys_CheckParm( "-nodll" ); host.enabledll = !Sys_CheckParm( "-nodll" );
@@ -1131,7 +1109,7 @@ static void Host_InitCommon( int argc, char **argv, const char *progname, qboole
#if XASH_DEDICATED #if XASH_DEDICATED
Platform_SetupSigtermHandling(); Platform_SetupSigtermHandling();
#endif #endif
Platform_Init( Host_IsDedicated( ) || developer >= DEV_EXTENDED, basedir ); Platform_Init( Host_IsDedicated( ) || developer >= DEV_EXTENDED );
FS_Init( basedir ); FS_Init( basedir );
Sys_InitLog(); Sys_InitLog();
@@ -1189,11 +1167,6 @@ static void Host_FreeCommon( void )
FS_Shutdown(); FS_Shutdown();
} }
static void Sys_Quit_f( void )
{
Sys_Quit( "command" );
}
/* /*
================= =================
Host_Main Host_Main
@@ -1233,7 +1206,7 @@ int EXPORT Host_Main( int argc, char **argv, const char *progname, int bChangeGa
Cvar_Getf( "buildnum", FCVAR_READ_ONLY, "returns a current build number", "%i", Q_buildnum_compat()); Cvar_Getf( "buildnum", FCVAR_READ_ONLY, "returns a current build number", "%i", Q_buildnum_compat());
Cvar_Getf( "ver", FCVAR_READ_ONLY, "shows an engine version", "%i/%s (hw build %i)", PROTOCOL_VERSION, XASH_COMPAT_VERSION, Q_buildnum_compat()); Cvar_Getf( "ver", FCVAR_READ_ONLY, "shows an engine version", "%i/%s (hw build %i)", PROTOCOL_VERSION, XASH_COMPAT_VERSION, Q_buildnum_compat());
Cvar_Getf( "host_ver", FCVAR_READ_ONLY, "detailed info about this build", "%i " XASH_VERSION " %s %s %s", Q_buildnum(), Q_buildos(), Q_buildarch(), g_buildcommit); Cvar_Getf( "host_ver", FCVAR_READ_ONLY, "detailed info about this build", "%i " XASH_VERSION " %s %s %s", Q_buildnum(), Q_buildos(), Q_buildarch(), Q_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_Getf( "host_lowmemorymode", FCVAR_READ_ONLY, "indicates if engine compiled for low RAM consumption (0 - normal, 1 - low engine limits, 2 - low protocol limits)", "%i", XASH_LOW_MEMORY );
Mod_Init(); Mod_Init();
@@ -1256,6 +1229,7 @@ int EXPORT Host_Main( int argc, char **argv, const char *progname, int bChangeGa
CL_Init(); CL_Init();
HTTP_Init(); HTTP_Init();
ID_Init();
SoundList_Init(); SoundList_Init();
if( Host_IsDedicated( )) if( Host_IsDedicated( ))
@@ -1267,8 +1241,8 @@ int EXPORT Host_Main( int argc, char **argv, const char *progname, int bChangeGa
// disable texture replacements for dedicated // disable texture replacements for dedicated
Cvar_FullSet( "host_allow_materials", "0", FCVAR_READ_ONLY ); Cvar_FullSet( "host_allow_materials", "0", FCVAR_READ_ONLY );
Cmd_AddRestrictedCommand( "quit", Sys_Quit_f, "quit the game" ); Cmd_AddRestrictedCommand( "quit", Sys_Quit, "quit the game" );
Cmd_AddRestrictedCommand( "exit", Sys_Quit_f, "quit the game" ); Cmd_AddRestrictedCommand( "exit", Sys_Quit, "quit the game" );
} }
else Cmd_AddRestrictedCommand( "minimize", Host_Minimize_f, "minimize main window to tray" ); else Cmd_AddRestrictedCommand( "minimize", Host_Minimize_f, "minimize main window to tray" );
@@ -1311,7 +1285,6 @@ int EXPORT Host_Main( int argc, char **argv, const char *progname, int bChangeGa
Cmd_RemoveCommand( "setgl" ); Cmd_RemoveCommand( "setgl" );
Cbuf_ExecStuffCmds(); // execute stuffcmds (commandline) Cbuf_ExecStuffCmds(); // execute stuffcmds (commandline)
SCR_CheckStartupVids(); // must be last SCR_CheckStartupVids(); // must be last
FS_CheckConfig();
if( Sys_GetParmFromCmdLine( "-timedemo", demoname )) if( Sys_GetParmFromCmdLine( "-timedemo", demoname ))
Cbuf_AddTextf( "timedemo %s\n", demoname ); Cbuf_AddTextf( "timedemo %s\n", demoname );
@@ -1340,11 +1313,6 @@ int EXPORT Host_Main( int argc, char **argv, const char *progname, int bChangeGa
// check after all configs were executed // check after all configs were executed
HPAK_CheckIntegrity( hpk_custom_file.string ); HPAK_CheckIntegrity( hpk_custom_file.string );
#if XASH_ANDROID
if( setjmp( return_from_main_buf ))
return error_on_exit;
#endif // XASH_ANDROID
// main window message loop // main window message loop
while( !host.crashed ) while( !host.crashed )
{ {
@@ -1357,31 +1325,20 @@ int EXPORT Host_Main( int argc, char **argv, const char *progname, int bChangeGa
return 0; return 0;
} }
void EXPORT Host_Shutdown( void );
void EXPORT Host_Shutdown( void )
{
Host_ShutdownWithReason( "launcher shutdown" );
}
/* /*
================= =================
Host_Shutdown Host_Shutdown
================= =================
*/ */
void Host_ShutdownWithReason( const char *reason ) void EXPORT Host_Shutdown( void )
{ {
qboolean error = host.status == HOST_ERR_FATAL; qboolean error = host.status == HOST_ERR_FATAL;
if( host.shutdown_issued ) if( host.shutdown_issued ) return;
return;
host.shutdown_issued = true; host.shutdown_issued = true;
if( reason != NULL ) if( host.status != HOST_ERR_FATAL ) host.status = HOST_SHUTDOWN; // prepare host to normal shutdown
Con_Printf( S_NOTE "Issuing host shutdown due to reason \"%s\"\n", reason ); if( !host.change_game ) Q_strncpy( host.finalmsg, "Server shutdown", sizeof( host.finalmsg ));
if( host.status != HOST_ERR_FATAL )
host.status = HOST_SHUTDOWN; // prepare host to normal shutdown
#if !XASH_DEDICATED #if !XASH_DEDICATED
if( host.type == HOST_NORMAL && !error ) if( host.type == HOST_NORMAL && !error )
@@ -1400,14 +1357,10 @@ void Host_ShutdownWithReason( const char *reason )
Host_FreeCommon(); Host_FreeCommon();
Platform_Shutdown(); Platform_Shutdown();
BaseCmd_Shutdown();
Cmd_Shutdown();
Cvar_Shutdown();
// must be last, console uses this // must be last, console uses this
Mem_FreePool( &host.mempool ); Mem_FreePool( &host.mempool );
// restore filter // restore filter
Sys_RestoreCrashHandler(); Sys_RestoreCrashHandler();
Sys_CloseLog( reason ); Sys_CloseLog();
} }
+8 -6
View File
@@ -38,7 +38,7 @@ static void HPAK_MaxSize_f( void )
Con_Printf( S_ERROR "hpk_maxsize is deprecated, use hpk_max_size\n" ); Con_Printf( S_ERROR "hpk_maxsize is deprecated, use hpk_max_size\n" );
} }
const char *COM_ResourceTypeFromIndex( int type ) static const char *HPAK_TypeFromIndex( int type )
{ {
switch( type ) switch( type )
{ {
@@ -104,7 +104,7 @@ static void HPAK_CreatePak( const char *filename, resource_t *pResource, byte *p
string pakname; string pakname;
byte md5[16]; byte md5[16];
file_t *fout; file_t *fout;
MD5Context_t ctx = { 0 }; MD5Context_t ctx;
if( !COM_CheckString( filename )) if( !COM_CheckString( filename ))
return; return;
@@ -125,6 +125,7 @@ static void HPAK_CreatePak( const char *filename, resource_t *pResource, byte *p
} }
// let's hash it. // let's hash it.
memset( &ctx, 0, sizeof( MD5Context_t ));
MD5Init( &ctx ); MD5Init( &ctx );
if( pData == NULL ) if( pData == NULL )
@@ -213,7 +214,7 @@ void HPAK_AddLump( qboolean bUseQueue, const char *name, resource_t *pResource,
file_t *file_src; file_t *file_src;
file_t *file_dst; file_t *file_dst;
byte md5[16]; byte md5[16];
MD5Context_t ctx = { 0 }; MD5Context_t ctx;
if( pData == NULL && pFile == NULL ) if( pData == NULL && pFile == NULL )
return; return;
@@ -225,6 +226,7 @@ void HPAK_AddLump( qboolean bUseQueue, const char *name, resource_t *pResource,
} }
// hash it // hash it
memset( &ctx, 0, sizeof( MD5Context_t ));
MD5Init( &ctx ); MD5Init( &ctx );
if( !pData ) if( !pData )
@@ -461,7 +463,7 @@ static qboolean HPAK_Validate( const char *filename, qboolean quiet, qboolean de
if( !quiet ) if( !quiet )
{ {
Con_Printf( "%i: %s %s %s: ", i, COM_ResourceTypeFromIndex( pRes->type ), Con_Printf( "%i: %s %s %s: ", i, HPAK_TypeFromIndex( pRes->type ),
Q_pretifymem( pRes->nDownloadSize, 2 ), pRes->szFileName ); Q_pretifymem( pRes->nDownloadSize, 2 ), pRes->szFileName );
} }
@@ -942,7 +944,7 @@ static void HPAK_List_f( void )
{ {
entry = &directory.entries[nCurrent]; entry = &directory.entries[nCurrent];
COM_FileBase( entry->resource.szFileName, lumpname, sizeof( lumpname )); COM_FileBase( entry->resource.szFileName, lumpname, sizeof( lumpname ));
type = COM_ResourceTypeFromIndex( entry->resource.type ); type = HPAK_TypeFromIndex( entry->resource.type );
size = Q_memprint( entry->resource.nDownloadSize ); size = Q_memprint( entry->resource.nDownloadSize );
Con_Printf( "%i: %10s %s %s\n : %s\n", nCurrent + 1, type, size, lumpname, MD5_Print( entry->resource.rgucMD5_hash )); Con_Printf( "%i: %10s %s %s\n : %s\n", nCurrent + 1, type, size, lumpname, MD5_Print( entry->resource.rgucMD5_hash ));
@@ -1037,7 +1039,7 @@ static void HPAK_Extract_f( void )
continue; continue;
COM_FileBase( entry->resource.szFileName, lumpname, sizeof( lumpname ) ); COM_FileBase( entry->resource.szFileName, lumpname, sizeof( lumpname ) );
type = COM_ResourceTypeFromIndex( entry->resource.type ); type = HPAK_TypeFromIndex( entry->resource.type );
size = Q_memprint( entry->resource.nDownloadSize ); size = Q_memprint( entry->resource.nDownloadSize );
Con_Printf( "Extracting %i: %10s %s %s\n", nCurrent + 1, type, size, lumpname ); Con_Printf( "Extracting %i: %10s %s %s\n", nCurrent + 1, type, size, lumpname );
@@ -19,8 +19,8 @@ GNU General Public License for more details.
#if !XASH_WIN32 #if !XASH_WIN32
#include <dirent.h> #include <dirent.h>
#endif #endif
static char id_md5[33]; static char id_md5[33];
static char id_customid[MAX_STRING];
/* /*
========================================================== ==========================================================
@@ -590,12 +590,28 @@ static void ID_Check( void )
const char *ID_GetMD5( void ) const char *ID_GetMD5( void )
{ {
if( id_customid[0] )
return id_customid;
return id_md5; 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 ) void ID_Init( void )
{ {
MD5Context_t hash = { 0 }; MD5Context_t hash = {0};
byte md5[16]; byte md5[16];
int i; int i;
@@ -616,7 +632,7 @@ void ID_Init( void )
#elif XASH_WIN32 #elif XASH_WIN32
{ {
CHAR szBuf[MAX_PATH]; CHAR szBuf[MAX_PATH];
ID_GetKeyData( HKEY_CURRENT_USER, "Software\\"XASH_ENGINE_NAME"\\", "xash_id", szBuf, MAX_PATH ); ID_GetKeyData( HKEY_CURRENT_USER, "Software\\Xash3D\\", "xash_id", szBuf, MAX_PATH );
sscanf(szBuf, "%016"PRIX64, &id); sscanf(szBuf, "%016"PRIX64, &id);
id ^= SYSTEM_XOR_MASK; id ^= SYSTEM_XOR_MASK;
@@ -670,7 +686,7 @@ void ID_Init( void )
{ {
CHAR Buf[MAX_PATH]; CHAR Buf[MAX_PATH];
sprintf( Buf, "%016"PRIX64, id^SYSTEM_XOR_MASK ); sprintf( Buf, "%016"PRIX64, id^SYSTEM_XOR_MASK );
ID_SetKeyData( HKEY_CURRENT_USER, "Software\\"XASH_ENGINE_NAME"\\", REG_SZ, "xash_id", Buf, Q_strlen(Buf) ); ID_SetKeyData( HKEY_CURRENT_USER, "Software\\Xash3D\\", REG_SZ, "xash_id", Buf, Q_strlen(Buf) );
} }
#else #else
{ {
+4 -5
View File
@@ -15,7 +15,6 @@ GNU General Public License for more details.
#include <math.h> #include <math.h>
#include "imagelib.h" #include "imagelib.h"
#include "eiface.h" // ARRAYSIZE
// global image variables // global image variables
imglib_t image; imglib_t image;
@@ -68,6 +67,7 @@ static const cubepack_t load_cubemap[] =
{ "3Ds Sky1", skybox_qv1 }, { "3Ds Sky1", skybox_qv1 },
{ "3Ds Sky2", skybox_qv2 }, { "3Ds Sky2", skybox_qv2 },
{ "3Ds Cube", cubemap_v1 }, { "3Ds Cube", cubemap_v1 },
{ NULL, NULL },
}; };
// soul of ImageLib - table of image format constants // soul of ImageLib - table of image format constants
@@ -297,8 +297,9 @@ rgbdata_t *FS_LoadImage( const char *filename, const byte *buffer, size_t size )
{ {
const char *ext = COM_FileExtension( filename ); const char *ext = COM_FileExtension( filename );
string loadname; string loadname;
int i, j; int i;
const loadpixformat_t *extfmt; const loadpixformat_t *extfmt;
const cubepack_t *cmap;
Q_strncpy( loadname, filename, sizeof( loadname )); Q_strncpy( loadname, filename, sizeof( loadname ));
Image_Reset(); // clear old image Image_Reset(); // clear old image
@@ -316,10 +317,8 @@ rgbdata_t *FS_LoadImage( const char *filename, const byte *buffer, size_t size )
return ImagePack(); return ImagePack();
// check all cubemap sides with package suffix // check all cubemap sides with package suffix
for( j = 0; j < ARRAYSIZE( load_cubemap ); j++ ) for( cmap = load_cubemap; cmap && cmap->type; cmap++ )
{ {
const cubepack_t *cmap = &load_cubemap[j];
for( i = 0; i < 6; i++ ) for( i = 0; i < 6; i++ )
{ {
if( Image_ProbeLoad( extfmt, loadname, cmap->type[i].suf, cmap->type[i].hint )) if( Image_ProbeLoad( extfmt, loadname, cmap->type[i].suf, cmap->type[i].hint ))
+2 -10
View File
@@ -28,20 +28,12 @@ Image_LoadPAL
qboolean Image_LoadPAL( const char *name, const byte *buffer, fs_offset_t filesize ) qboolean Image_LoadPAL( const char *name, const byte *buffer, fs_offset_t filesize )
{ {
int rendermode = LUMP_NORMAL; int rendermode = LUMP_NORMAL;
byte pal[768];
if( filesize > sizeof( pal )) if( filesize != 768 )
{ {
Con_DPrintf( S_ERROR "%s: (%s) have invalid size (%li should be less or equal than %d)\n", __func__, name, (long)filesize, sizeof( pal )); Con_DPrintf( S_ERROR "%s: (%s) have invalid size (%li should be %d)\n", __func__, name, (long)filesize, 768 );
return false; return false;
} }
else if( filesize < sizeof( pal ) && buffer != NULL )
{
// palette might be truncated, fill it with zeros
memset( pal, 0, sizeof( pal ));
memcpy( pal, buffer, filesize );
buffer = pal;
}
if( name[0] == '#' ) if( name[0] == '#' )
{ {
+5 -1
View File
@@ -37,7 +37,11 @@ static char **szArgv;
static void Sys_ChangeGame( const char *progname ) static void Sys_ChangeGame( const char *progname )
{ {
// stub // a1ba: may never be called within engine
// if platform supports execv() function
Q_strncpy( szGameDir, progname, sizeof( szGameDir ));
Host_Shutdown( );
exit( Host_Main( szArgc, szArgv, szGameDir, 1, &Sys_ChangeGame ) );
} }
static int Sys_Start( void ) static int Sys_Start( void )
+10 -14
View File
@@ -385,7 +385,10 @@ void NET_SaveMasters( void )
master_t *m; master_t *m;
if( !ml.modified ) if( !ml.modified )
{
Con_Reportf( "Master server list not changed\n" );
return; return;
}
f = FS_Open( "xashcomm.lst", "w", true ); f = FS_Open( "xashcomm.lst", "w", true );
@@ -419,21 +422,14 @@ void NET_InitMasters( void )
Cvar_RegisterVariable( &sv_verbose_heartbeats ); Cvar_RegisterVariable( &sv_verbose_heartbeats );
{ // IPv4-only // keep main master always there
NET_AddMaster( "mentality.rip:27010", false, false ); NET_AddMaster( MASTERSERVER_ADR, false, false );
NET_AddMaster( "ms2.mentality.rip:27010", false, false ); NET_AddMaster( "mentality.rip:27011", false, false ); // testing server, might be offline
NET_AddMaster( "ms3.mentality.rip:27010", false, false ); NET_AddMaster( "ms2.mentality.rip:27010", false, false ); // secondary master
}
{ // IPv6-only NET_AddMaster( "aaaa.mentality.rip:27010", false, true ); // IPv6-only
NET_AddMaster( "aaaa.mentality.rip:27010", false, true ); NET_AddMaster( "aaaa.mentality.rip:27011", false, true ); // IPv6-only, testing server, might be offline
NET_AddMaster( "aaaa.ms2.mentality.rip:27010", false, true ); NET_AddMaster( "aaaa.ms2.mentality.rip:27010", false, false ); // secondary IPv6-only master
}
{ // testing servers, might be offline
NET_AddMaster( "mentality.rip:27011", false, false );
NET_AddMaster( "aaaa.mentality.rip:27011", false, true );
}
NET_LoadMasters( ); NET_LoadMasters( );
} }
+177 -303
View File
@@ -385,35 +385,6 @@ static const mlumpinfo_t extlumps[EXTRA_LUMPS] =
}, },
}; };
#define BOX_CLIPNODES_INITIALIZER \
{ \
.planenum = 0, \
.children = { CONTENTS_EMPTY, 1 }, \
}, \
{ \
.planenum = 1, \
.children = { 2, CONTENTS_EMPTY }, \
}, \
{ \
.planenum = 2, \
.children = { CONTENTS_EMPTY, 3 }, \
}, \
{ \
.planenum = 3, \
.children = { 4, CONTENTS_EMPTY }, \
}, \
{ \
.planenum = 4, \
.children = { CONTENTS_EMPTY, 5 }, \
}, \
{ \
.planenum = 5, \
.children = { CONTENTS_SOLID, CONTENTS_EMPTY }, \
}, \
const mclipnode16_t box_clipnodes16[6] = { BOX_CLIPNODES_INITIALIZER };
const mclipnode32_t box_clipnodes32[6] = { BOX_CLIPNODES_INITIALIZER };
/* /*
=============================================================================== ===============================================================================
@@ -482,7 +453,7 @@ static int Mod_LoadTextureFromWadList( wadlist_t *list, const char *name, rgbdat
return -1; return -1;
} }
static fs_offset_t Mod_CalculateMipTexSize( const mip_t *mt, qboolean palette ) static fs_offset_t Mod_CalculateMipTexSize( mip_t *mt, qboolean palette )
{ {
if( !mt ) if( !mt )
return 0; return 0;
@@ -885,7 +856,7 @@ Mod_PointInLeaf
================== ==================
*/ */
mleaf_t *Mod_PointInLeaf( const vec3_t p, mnode_t *node, model_t *mod ) mleaf_t *Mod_PointInLeaf( const vec3_t p, mnode_t *node )
{ {
Assert( node != NULL ); Assert( node != NULL );
@@ -893,7 +864,7 @@ mleaf_t *Mod_PointInLeaf( const vec3_t p, mnode_t *node, model_t *mod )
{ {
if( node->contents < 0 ) if( node->contents < 0 )
return (mleaf_t *)node; return (mleaf_t *)node;
node = node_child( node, PlaneDiff( p, node->plane ) <= 0, mod ); node = node->children[PlaneDiff( p, node->plane ) <= 0];
} }
// never reached // never reached
@@ -914,7 +885,7 @@ byte *Mod_GetPVSForPoint( const vec3_t p )
ASSERT( worldmodel != NULL ); ASSERT( worldmodel != NULL );
leaf = Mod_PointInLeaf( p, worldmodel->nodes, worldmodel ); leaf = Mod_PointInLeaf( p, worldmodel->nodes );
if( leaf && leaf->cluster >= 0 ) if( leaf && leaf->cluster >= 0 )
return Mod_DecompressPVS( leaf->compressed_vis, world.visbytes ); return Mod_DecompressPVS( leaf->compressed_vis, world.visbytes );
@@ -934,14 +905,14 @@ static void Mod_FatPVS_RecursiveBSPNode( const vec3_t org, float radius, byte *v
float d = PlaneDiff( org, node->plane ); float d = PlaneDiff( org, node->plane );
if( d > radius ) if( d > radius )
node = node_child( node, 0, worldmodel ); node = node->children[0];
else if( d < -radius ) else if( d < -radius )
node = node_child( node, 1, worldmodel ); node = node->children[1];
else else
{ {
// go down both sides // go down both sides
Mod_FatPVS_RecursiveBSPNode( org, radius, visbuffer, visbytes, node_child( node, 0, worldmodel ), phs ); Mod_FatPVS_RecursiveBSPNode( org, radius, visbuffer, visbytes, node->children[0], phs );
node = node_child( node, 1, worldmodel ); node = node->children[1];
} }
} }
@@ -979,7 +950,7 @@ int Mod_FatPVS( const vec3_t org, float radius, byte *visbuffer, int visbytes, q
ASSERT( worldmodel != NULL ); ASSERT( worldmodel != NULL );
leaf = Mod_PointInLeaf( org, worldmodel->nodes, worldmodel ); leaf = Mod_PointInLeaf( org, worldmodel->nodes );
bytes = Q_min( bytes, visbytes ); bytes = Q_min( bytes, visbytes );
// enable full visibility for some reasons // enable full visibility for some reasons
@@ -1038,16 +1009,20 @@ static void Mod_BoxLeafnums_r( leaflist_t *ll, mnode_t *node )
sides = BOX_ON_PLANE_SIDE( ll->mins, ll->maxs, node->plane ); sides = BOX_ON_PLANE_SIDE( ll->mins, ll->maxs, node->plane );
if( sides == 1 ) if( sides == 1 )
node = node_child( node, 0, worldmodel ); {
node = node->children[0];
}
else if( sides == 2 ) else if( sides == 2 )
node = node_child( node, 1, worldmodel ); {
node = node->children[1];
}
else else
{ {
// go down both // go down both
if( ll->topnode == -1 ) if( ll->topnode == -1 )
ll->topnode = node - worldmodel->nodes; ll->topnode = node - worldmodel->nodes;
Mod_BoxLeafnums_r( ll, node_child( node, 0, worldmodel )); Mod_BoxLeafnums_r( ll, node->children[0] );
node = node_child( node, 1, worldmodel ); node = node->children[1];
} }
} }
} }
@@ -1104,6 +1079,35 @@ qboolean Mod_BoxVisible( const vec3_t mins, const vec3_t maxs, const byte *visbi
return false; return false;
} }
/*
=============
Mod_HeadnodeVisible
=============
*/
qboolean Mod_HeadnodeVisible( mnode_t *node, const byte *visbits, int *lastleaf )
{
if( !node || node->contents == CONTENTS_SOLID )
return false;
if( node->contents < 0 )
{
if( !CHECKVISBIT( visbits, ((mleaf_t *)node)->cluster ))
return false;
if( lastleaf )
*lastleaf = ((mleaf_t *)node)->cluster;
return true;
}
if( Mod_HeadnodeVisible( node->children[0], visbits, lastleaf ))
return true;
if( Mod_HeadnodeVisible( node->children[1], visbits, lastleaf ))
return true;
return false;
}
/* /*
================= =================
Mod_FindModelOrigin Mod_FindModelOrigin
@@ -1260,35 +1264,22 @@ Mod_GetFaceContents
determine face contents by name determine face contents by name
================== ==================
*/ */
static mvertex_t *Mod_GetVertexByNumber( model_t *mod, int surfedge, const dbspmodel_t *bmod ) static mvertex_t *Mod_GetVertexByNumber( model_t *mod, int surfedge )
{ {
int lindex = mod->surfedges[surfedge]; int lindex;
medge_t *edge;
if( bmod->version == QBSP2_VERSION ) lindex = mod->surfedges[surfedge];
if( lindex > 0 )
{ {
if( lindex > 0 ) edge = &mod->edges[lindex];
{ return &mod->vertexes[edge->v[0]];
medge32_t *edge = &mod->edges32[lindex];
return &mod->vertexes[edge->v[0]];
}
else
{
medge32_t *edge = &mod->edges32[-lindex];
return &mod->vertexes[edge->v[1]];
}
} }
else else
{ {
if( lindex > 0 ) edge = &mod->edges[-lindex];
{ return &mod->vertexes[edge->v[1]];
medge16_t *edge = &mod->edges16[lindex];
return &mod->vertexes[edge->v[0]];
}
else
{
medge16_t *edge = &mod->edges16[-lindex];
return &mod->vertexes[edge->v[1]];
}
} }
} }
@@ -1373,7 +1364,7 @@ Mod_CalcSurfaceExtents
Fills in surf->texturemins[] and surf->extents[] Fills in surf->texturemins[] and surf->extents[]
================= =================
*/ */
static void Mod_CalcSurfaceExtents( model_t *mod, msurface_t *surf, const dbspmodel_t *bmod ) static void Mod_CalcSurfaceExtents( model_t *mod, msurface_t *surf )
{ {
// this place is VERY critical to precision // this place is VERY critical to precision
// keep it as float, don't use double, because it causes issues with lightmap // keep it as float, don't use double, because it causes issues with lightmap
@@ -1400,16 +1391,8 @@ static void Mod_CalcSurfaceExtents( model_t *mod, msurface_t *surf, const dbspmo
if( e >= mod->numedges || e <= -mod->numedges ) if( e >= mod->numedges || e <= -mod->numedges )
Host_Error( "%s: bad edge\n", __func__ ); Host_Error( "%s: bad edge\n", __func__ );
if( bmod->version == QBSP2_VERSION ) if( e >= 0 ) v = &mod->vertexes[mod->edges[e].v[0]];
{ else v = &mod->vertexes[mod->edges[-e].v[1]];
if( e >= 0 ) v = &mod->vertexes[mod->edges32[e].v[0]];
else v = &mod->vertexes[mod->edges32[-e].v[1]];
}
else
{
if( e >= 0 ) v = &mod->vertexes[mod->edges16[e].v[0]];
else v = &mod->vertexes[mod->edges16[-e].v[1]];
}
for( j = 0; j < 2; j++ ) for( j = 0; j < 2; j++ )
{ {
@@ -1463,7 +1446,7 @@ Mod_CalcSurfaceBounds
fills in surf->mins and surf->maxs fills in surf->mins and surf->maxs
================= =================
*/ */
static void Mod_CalcSurfaceBounds( model_t *mod, msurface_t *surf, const dbspmodel_t *bmod ) static void Mod_CalcSurfaceBounds( model_t *mod, msurface_t *surf )
{ {
int i, e; int i, e;
mvertex_t *v; mvertex_t *v;
@@ -1477,16 +1460,8 @@ static void Mod_CalcSurfaceBounds( model_t *mod, msurface_t *surf, const dbspmod
if( e >= mod->numedges || e <= -mod->numedges ) if( e >= mod->numedges || e <= -mod->numedges )
Host_Error( "%s: bad edge\n", __func__ ); Host_Error( "%s: bad edge\n", __func__ );
if( bmod->version == QBSP2_VERSION ) if( e >= 0 ) v = &mod->vertexes[mod->edges[e].v[0]];
{ else v = &mod->vertexes[mod->edges[-e].v[1]];
if( e >= 0 ) v = &mod->vertexes[mod->edges32[e].v[0]];
else v = &mod->vertexes[mod->edges32[-e].v[1]];
}
else
{
if( e >= 0 ) v = &mod->vertexes[mod->edges16[e].v[0]];
else v = &mod->vertexes[mod->edges16[-e].v[1]];
}
AddPointToBounds( v->position, surf->info->mins, surf->info->maxs ); AddPointToBounds( v->position, surf->info->mins, surf->info->maxs );
} }
@@ -1498,7 +1473,7 @@ static void Mod_CalcSurfaceBounds( model_t *mod, msurface_t *surf, const dbspmod
Mod_CreateFaceBevels Mod_CreateFaceBevels
================= =================
*/ */
static void Mod_CreateFaceBevels( model_t *mod, msurface_t *surf, const dbspmodel_t *bmod ) static void Mod_CreateFaceBevels( model_t *mod, msurface_t *surf )
{ {
vec3_t delta, edgevec; vec3_t delta, edgevec;
byte *facebevel; byte *facebevel;
@@ -1531,8 +1506,8 @@ static void Mod_CreateFaceBevels( model_t *mod, msurface_t *surf, const dbspmode
{ {
mplane_t *dest = &fb->edges[i]; mplane_t *dest = &fb->edges[i];
v0 = Mod_GetVertexByNumber( mod, surf->firstedge + i, bmod ); v0 = Mod_GetVertexByNumber( mod, surf->firstedge + i );
v1 = Mod_GetVertexByNumber( mod, surf->firstedge + (i + 1) % surf->numedges, bmod ); v1 = Mod_GetVertexByNumber( mod, surf->firstedge + (i + 1) % surf->numedges );
VectorSubtract( v1->position, v0->position, edgevec ); VectorSubtract( v1->position, v0->position, edgevec );
CrossProduct( faceNormal, edgevec, dest->normal ); CrossProduct( faceNormal, edgevec, dest->normal );
VectorNormalize( dest->normal ); VectorNormalize( dest->normal );
@@ -1546,7 +1521,7 @@ static void Mod_CreateFaceBevels( model_t *mod, msurface_t *surf, const dbspmode
// compute face radius // compute face radius
for( i = 0; i < surf->numedges; i++ ) for( i = 0; i < surf->numedges; i++ )
{ {
v0 = Mod_GetVertexByNumber( mod, surf->firstedge + i, bmod ); v0 = Mod_GetVertexByNumber( mod, surf->firstedge + i );
VectorSubtract( v0->position, fb->origin, delta ); VectorSubtract( v0->position, fb->origin, delta );
radius = DotProduct( delta, delta ); radius = DotProduct( delta, delta );
fb->radius = Q_max( radius, fb->radius ); fb->radius = Q_max( radius, fb->radius );
@@ -1558,15 +1533,13 @@ static void Mod_CreateFaceBevels( model_t *mod, msurface_t *surf, const dbspmode
Mod_SetParent Mod_SetParent
================= =================
*/ */
static void Mod_SetParent( model_t *mod, mnode_t *node, mnode_t *parent ) static void Mod_SetParent( mnode_t *node, mnode_t *parent )
{ {
node->parent = parent; node->parent = parent;
if( node->contents < 0 ) if( node->contents < 0 ) return; // it's leaf
return; // it's leaf Mod_SetParent( node->children[0], node );
Mod_SetParent( node->children[1], node );
Mod_SetParent( mod, node_child( node, 0, mod ), node );
Mod_SetParent( mod, node_child( node, 1, mod ), node );
} }
/* /*
@@ -1574,7 +1547,7 @@ static void Mod_SetParent( model_t *mod, mnode_t *node, mnode_t *parent )
CountClipNodes_r CountClipNodes_r
================== ==================
*/ */
static void CountClipNodes16_r( mclipnode16_t *src, hull_t *hull, int nodenum ) static void CountClipNodes_r( mclipnode_t *src, hull_t *hull, int nodenum )
{ {
// leaf? // leaf?
if( nodenum < 0 ) return; if( nodenum < 0 ) return;
@@ -1583,11 +1556,16 @@ static void CountClipNodes16_r( mclipnode16_t *src, hull_t *hull, int nodenum )
Host_Error( "MAX_MAP_CLIPNODES limit exceeded\n" ); Host_Error( "MAX_MAP_CLIPNODES limit exceeded\n" );
hull->lastclipnode++; hull->lastclipnode++;
CountClipNodes16_r( src, hull, src[nodenum].children[0] ); CountClipNodes_r( src, hull, src[nodenum].children[0] );
CountClipNodes16_r( src, hull, src[nodenum].children[1] ); CountClipNodes_r( src, hull, src[nodenum].children[1] );
} }
static void CountClipNodes32_r( mclipnode32_t *src, hull_t *hull, int nodenum ) /*
==================
CountClipNodes32_r
==================
*/
static void CountClipNodes32_r( dclipnode32_t *src, hull_t *hull, int nodenum )
{ {
// leaf? // leaf?
if( nodenum < 0 ) return; if( nodenum < 0 ) return;
@@ -1600,27 +1578,15 @@ static void CountClipNodes32_r( mclipnode32_t *src, hull_t *hull, int nodenum )
CountClipNodes32_r( src, hull, src[nodenum].children[1] ); CountClipNodes32_r( src, hull, src[nodenum].children[1] );
} }
static void CountDClipNodes_r( dclipnode32_t *src, hull_t *hull, int nodenum )
{
// leaf?
if( nodenum < 0 ) return;
if( hull->lastclipnode == MAX_MAP_CLIPNODES )
Host_Error( "MAX_MAP_CLIPNODES limit exceeded\n" );
hull->lastclipnode++;
CountDClipNodes_r( src, hull, src[nodenum].children[0] );
CountDClipNodes_r( src, hull, src[nodenum].children[1] );
}
/* /*
================== ==================
RemapClipNodes_r RemapClipNodes_r
================== ==================
*/ */
static int RemapClipNodes_r( dbspmodel_t *bmod, dclipnode32_t *srcnodes, hull_t *hull, int nodenum ) static int RemapClipNodes_r( dclipnode32_t *srcnodes, hull_t *hull, int nodenum )
{ {
dclipnode32_t *src; dclipnode32_t *src;
mclipnode_t *out;
int i, c; int i, c;
// leaf? // leaf?
@@ -1633,22 +1599,13 @@ static int RemapClipNodes_r( dbspmodel_t *bmod, dclipnode32_t *srcnodes, hull_t
src = srcnodes + nodenum; src = srcnodes + nodenum;
c = hull->lastclipnode; c = hull->lastclipnode;
out = &hull->clipnodes[c];
hull->lastclipnode++; hull->lastclipnode++;
if( bmod->version == QBSP2_VERSION ) out->planenum = src->planenum;
{
mclipnode32_t *out = &hull->clipnodes32[c]; for( i = 0; i < 2; i++ )
out->planenum = src->planenum; out->children[i] = RemapClipNodes_r( srcnodes, hull, src->children[i] );
for( i = 0; i < 2; i++ )
out->children[i] = RemapClipNodes_r( bmod, srcnodes, hull, src->children[i] );
}
else
{
mclipnode16_t *out = &hull->clipnodes16[c];
out->planenum = src->planenum;
for( i = 0; i < 2; i++ )
out->children[i] = RemapClipNodes_r( bmod, srcnodes, hull, src->children[i] );
}
return c; return c;
} }
@@ -1660,64 +1617,34 @@ Mod_MakeHull0
Duplicate the drawing hull structure as a clipping hull Duplicate the drawing hull structure as a clipping hull
================= =================
*/ */
static void Mod_MakeHull0( model_t *mod, const dbspmodel_t *bmod ) static void Mod_MakeHull0( model_t *mod )
{ {
hull_t *hull = &mod->hulls[0]; mnode_t *in, *child;
int i; mclipnode_t *out;
hull_t *hull;
int i, j;
hull = &mod->hulls[0];
hull->clipnodes = out = Mem_Malloc( mod->mempool, mod->numnodes * sizeof( *out ));
in = mod->nodes;
hull->firstclipnode = 0; hull->firstclipnode = 0;
hull->lastclipnode = mod->numnodes - 1; hull->lastclipnode = mod->numnodes - 1;
hull->planes = mod->planes; hull->planes = mod->planes;
if( bmod->version == QBSP2_VERSION ) for( i = 0; i < mod->numnodes; i++, out++, in++ )
{ {
mclipnode32_t *out; out->planenum = in->plane - mod->planes;
mnode_t *in = mod->nodes;
hull->clipnodes32 = out = Mem_Malloc( mod->mempool, mod->numnodes * sizeof( *hull->clipnodes32 )); for( j = 0; j < 2; j++ )
for( i = 0; i < mod->numnodes; i++, out++, in++ )
{ {
int j; child = in->children[j];
out->planenum = in->plane - mod->planes; if( child->contents < 0 )
out->children[j] = child->contents;
for( j = 0; j < 2; j++ ) else out->children[j] = child - mod->nodes;
{
mnode_t *child = node_child( in, j, mod );
if( child->contents < 0 )
out->children[j] = child->contents;
else
out->children[j] = child - mod->nodes;
}
} }
} }
else
{
mclipnode16_t *out;
mnode_t *in = mod->nodes;
hull->clipnodes16 = out = Mem_Malloc( mod->mempool, mod->numnodes * sizeof( *hull->clipnodes16 ));
for( i = 0; i < mod->numnodes; i++, out++, in++ )
{
int j;
out->planenum = in->plane - mod->planes;
for( j = 0; j < 2; j++ )
{
mnode_t *child = node_child( in, j, mod );
if( child->contents < 0 )
out->children[j] = child->contents;
else
out->children[j] = child - mod->nodes;
}
}
}
} }
/* /*
@@ -1761,18 +1688,15 @@ static void Mod_SetupHull( dbspmodel_t *bmod, model_t *mod, poolhandle_t mempool
if( VectorIsNull( hull->clip_mins ) && VectorIsNull( hull->clip_maxs )) if( VectorIsNull( hull->clip_mins ) && VectorIsNull( hull->clip_maxs ))
return; // no hull specified return; // no hull specified
CountDClipNodes_r( bmod->clipnodes_out, hull, headnode ); CountClipNodes32_r( bmod->clipnodes_out, hull, headnode );
// fit array to real count // fit array to real count
if( bmod->version == QBSP2_VERSION ) hull->clipnodes = (mclipnode_t *)Mem_Malloc( mempool, sizeof( mclipnode_t ) * hull->lastclipnode );
hull->clipnodes32 = Mem_Malloc( mempool, sizeof( *hull->clipnodes32 ) * hull->lastclipnode );
else
hull->clipnodes16 = Mem_Malloc( mempool, sizeof( *hull->clipnodes16 ) * hull->lastclipnode );
hull->planes = mod->planes; // share planes hull->planes = mod->planes; // share planes
hull->lastclipnode = 0; // restart counting hull->lastclipnode = 0; // restart counting
RemapClipNodes_r( bmod, bmod->clipnodes_out, hull, headnode ); // remap clipnodes to 16-bit indexes // remap clipnodes to 16-bit indexes
RemapClipNodes_r( bmod->clipnodes_out, hull, headnode );
} }
static qboolean Mod_LoadLitfile( model_t *mod, const char *ext, size_t expected_size, color24 **out, size_t *outsize ) static qboolean Mod_LoadLitfile( model_t *mod, const char *ext, size_t expected_size, color24 **out, size_t *outsize )
@@ -1780,8 +1704,7 @@ static qboolean Mod_LoadLitfile( model_t *mod, const char *ext, size_t expected_
char modelname[64], path[64]; char modelname[64], path[64];
int iCompare; int iCompare;
fs_offset_t datasize; fs_offset_t datasize;
file_t *f; byte *in;
uint hdr[2];
COM_FileBase( mod->name, modelname, sizeof( modelname )); COM_FileBase( mod->name, modelname, sizeof( modelname ));
Q_snprintf( path, sizeof( path ), "maps/%s.%s", modelname, ext ); Q_snprintf( path, sizeof( path ), "maps/%s.%s", modelname, ext );
@@ -1792,15 +1715,31 @@ static qboolean Mod_LoadLitfile( model_t *mod, const char *ext, size_t expected_
if( iCompare < 0 ) // this may happens if level-designer used -onlyents key for hlcsg if( iCompare < 0 ) // this may happens if level-designer used -onlyents key for hlcsg
Con_Printf( S_WARN "%s probably is out of date\n", path ); Con_Printf( S_WARN "%s probably is out of date\n", path );
f = FS_Open( path, "rb", false ); in = FS_LoadFile( path, &datasize, false );
if( !f ) if( !in )
{ {
Con_Printf( S_ERROR "couldn't load %s\n", path ); Con_Printf( S_ERROR "couldn't load %s\n", path );
return false; return false;
} }
datasize = FS_FileLength( f ); if( datasize <= 8 ) // header + version
{
Con_Printf( S_ERROR "%s is too short\n", path );
goto cleanup_and_error;
}
if( LittleLong( ((uint *)in)[0] ) != IDDELUXEMAPHEADER )
{
Con_Printf( S_ERROR "%s is corrupted\n", path );
goto cleanup_and_error;
}
if( LittleLong( ((uint *)in)[1] ) != DELUXEMAP_VERSION )
{
Con_Printf( S_ERROR "has %s mismatched version (%u should be %u)\n", path, LittleLong( ((uint *)in)[1] ), DELUXEMAP_VERSION );
goto cleanup_and_error;
}
// skip header bytes // skip header bytes
datasize -= 8; datasize -= 8;
@@ -1811,33 +1750,14 @@ static qboolean Mod_LoadLitfile( model_t *mod, const char *ext, size_t expected_
goto cleanup_and_error; goto cleanup_and_error;
} }
if( FS_Read( f, hdr, sizeof( hdr )) != sizeof( hdr ))
{
Con_Printf( S_ERROR "failed reading header from %s\n", path );
goto cleanup_and_error;
}
if( LittleLong( hdr[0] ) != IDDELUXEMAPHEADER )
{
Con_Printf( S_ERROR "%s is corrupted\n", path );
goto cleanup_and_error;
}
if( LittleLong( hdr[1] ) != DELUXEMAP_VERSION )
{
Con_Printf( S_ERROR "has %s mismatched version (%u should be %u)\n", path, LittleLong( hdr[1] ), DELUXEMAP_VERSION );
goto cleanup_and_error;
}
*out = Mem_Malloc( mod->mempool, datasize ); *out = Mem_Malloc( mod->mempool, datasize );
memcpy( *out, in + 8, datasize );
*outsize = datasize; *outsize = datasize;
Mem_Free( in );
FS_Read( f, *out, datasize );
FS_Close( f );
return true; return true;
cleanup_and_error: cleanup_and_error:
FS_Close( f ); Mem_Free( in );
return false; return false;
} }
@@ -1852,7 +1772,6 @@ for embedded submodels
static void Mod_SetupSubmodels( model_t *mod, dbspmodel_t *bmod ) static void Mod_SetupSubmodels( model_t *mod, dbspmodel_t *bmod )
{ {
qboolean colored = false; qboolean colored = false;
qboolean qbsp2 = false;
poolhandle_t mempool; poolhandle_t mempool;
char *ents; char *ents;
dmodel_t *bm; dmodel_t *bm;
@@ -1864,9 +1783,6 @@ static void Mod_SetupSubmodels( model_t *mod, dbspmodel_t *bmod )
if( FBitSet( mod->flags, MODEL_COLORED_LIGHTING )) if( FBitSet( mod->flags, MODEL_COLORED_LIGHTING ))
colored = true; colored = true;
if( FBitSet( mod->flags, MODEL_QBSP2 ))
qbsp2 = true;
mod->numframes = 2; // regular and alternate animation mod->numframes = 2; // regular and alternate animation
// set up the submodels // set up the submodels
@@ -1879,10 +1795,7 @@ static void Mod_SetupSubmodels( model_t *mod, dbspmodel_t *bmod )
mod->hulls[0].lastclipnode = bm->headnode[0]; // need to be real count mod->hulls[0].lastclipnode = bm->headnode[0]; // need to be real count
// counting a real number of clipnodes per each submodel // counting a real number of clipnodes per each submodel
if( bmod->version == QBSP2_VERSION ) CountClipNodes_r( mod->hulls[0].clipnodes, &mod->hulls[0], bm->headnode[0] );
CountClipNodes32_r( mod->hulls[0].clipnodes32, &mod->hulls[0], bm->headnode[0] );
else
CountClipNodes16_r( mod->hulls[0].clipnodes16, &mod->hulls[0], bm->headnode[0] );
// but hulls1-3 is build individually for a each given submodel // but hulls1-3 is build individually for a each given submodel
for( j = 1; j < MAX_MAP_HULLS; j++ ) for( j = 1; j < MAX_MAP_HULLS; j++ )
@@ -1900,7 +1813,6 @@ static void Mod_SetupSubmodels( model_t *mod, dbspmodel_t *bmod )
// this bit will be shared between all the submodels include worldmodel // this bit will be shared between all the submodels include worldmodel
if( colored ) SetBits( mod->flags, MODEL_COLORED_LIGHTING ); if( colored ) SetBits( mod->flags, MODEL_COLORED_LIGHTING );
if( qbsp2 ) SetBits( mod->flags, MODEL_QBSP2 );
if( i != 0 ) if( i != 0 )
{ {
@@ -2223,15 +2135,15 @@ Mod_LoadEdges
*/ */
static void Mod_LoadEdges( model_t *mod, dbspmodel_t *bmod ) static void Mod_LoadEdges( model_t *mod, dbspmodel_t *bmod )
{ {
medge_t *out;
int i; int i;
mod->edges = out = Mem_Malloc( mod->mempool, bmod->numedges * sizeof( medge_t ));
mod->numedges = bmod->numedges; mod->numedges = bmod->numedges;
if( bmod->version == QBSP2_VERSION ) if( bmod->version == QBSP2_VERSION )
{ {
dedge32_t *in = bmod->edges32; dedge32_t *in = (dedge32_t *)bmod->edges32;
medge32_t *out;
mod->edges32 = out = Mem_Malloc( mod->mempool, bmod->numedges * sizeof( *out ));
for( i = 0; i < bmod->numedges; i++, in++, out++ ) for( i = 0; i < bmod->numedges; i++, in++, out++ )
{ {
@@ -2241,9 +2153,7 @@ static void Mod_LoadEdges( model_t *mod, dbspmodel_t *bmod )
} }
else else
{ {
dedge_t *in = bmod->edges; dedge_t *in = (dedge_t *)bmod->edges;
medge16_t *out;
mod->edges16 = out = Mem_Malloc( mod->mempool, bmod->numedges * sizeof( *out ));
for( i = 0; i < bmod->numedges; i++, in++, out++ ) for( i = 0; i < bmod->numedges; i++, in++, out++ )
{ {
@@ -2359,7 +2269,7 @@ static qboolean Mod_SearchForTextureReplacement( char *out, size_t size, const c
return false; return false;
} }
static void Mod_InitSkyClouds( model_t *mod, const mip_t *mt, texture_t *tx, qboolean custom_palette ) static void Mod_InitSkyClouds( model_t *mod, mip_t *mt, texture_t *tx, qboolean custom_palette )
{ {
#if !XASH_DEDICATED #if !XASH_DEDICATED
rgbdata_t r_temp, *r_sky; rgbdata_t r_temp, *r_sky;
@@ -2516,6 +2426,9 @@ done:
static void Mod_LoadTextureData( model_t *mod, dbspmodel_t *bmod, int textureIndex ) static void Mod_LoadTextureData( model_t *mod, dbspmodel_t *bmod, int textureIndex )
{ {
texture_t *texture = NULL;
mip_t *mipTex = NULL;
qboolean usesCustomPalette = false;
uint32_t txFlags = 0; uint32_t txFlags = 0;
char texpath[MAX_VA_STRING]; char texpath[MAX_VA_STRING];
char safemtname[16]; // only for external textures char safemtname[16]; // only for external textures
@@ -2523,10 +2436,12 @@ static void Mod_LoadTextureData( model_t *mod, dbspmodel_t *bmod, int textureInd
// don't load texture data on dedicated server, as there is no renderer. // don't load texture data on dedicated server, as there is no renderer.
// but count the wadusage for automatic precache // but count the wadusage for automatic precache
texture_t *texture = mod->textures[textureIndex]; //
const mip_t *mipTex = Mod_GetMipTexForTexture( bmod, textureIndex ); // FIXME: for ENGINE_IMPROVED_LINETRACE we need to load textures on server too
const qboolean usesCustomPalette = Mod_CalcMipTexUsesCustomPalette( mod, bmod, textureIndex ); // but there is no facility for this yet
const qboolean iswater = Mod_LooksLikeWaterTexture( mipTex->name ); texture = mod->textures[textureIndex];
mipTex = Mod_GetMipTexForTexture( bmod, textureIndex );
usesCustomPalette = Mod_CalcMipTexUsesCustomPalette( mod, bmod, textureIndex );
// check for multi-layered sky texture (quake1 specific) // check for multi-layered sky texture (quake1 specific)
if( bmod->isworld && Q_strncmp( mipTex->name, "sky", 3 ) == 0 && ( mipTex->width / mipTex->height ) == 2 ) if( bmod->isworld && Q_strncmp( mipTex->name, "sky", 3 ) == 0 && ( mipTex->width / mipTex->height ) == 2 )
@@ -2535,13 +2450,11 @@ static void Mod_LoadTextureData( model_t *mod, dbspmodel_t *bmod, int textureInd
return; return;
} }
// FIXME: for ENGINE_IMPROVED_LINETRACE we need to load textures on server too
// but there is no facility for this yet
if( FBitSet( host.features, ENGINE_IMPROVED_LINETRACE ) && mipTex->name[0] == '{' ) if( FBitSet( host.features, ENGINE_IMPROVED_LINETRACE ) && mipTex->name[0] == '{' )
SetBits( txFlags, TF_KEEP_SOURCE ); // Paranoia2 texture alpha-tracing SetBits( txFlags, TF_KEEP_SOURCE ); // Paranoia2 texture alpha-tracing
// check if this is water to keep the source texture and expand it to RGBA (so ripple effect works) // check if this is water to keep the source texture and expand it to RGBA (so ripple effect works)
if( iswater ) if( Mod_LooksLikeWaterTexture( mipTex->name ))
SetBits( txFlags, TF_KEEP_SOURCE | TF_EXPAND_SOURCE ); SetBits( txFlags, TF_KEEP_SOURCE | TF_EXPAND_SOURCE );
// Texture loading order: // Texture loading order:
@@ -2606,13 +2519,8 @@ static void Mod_LoadTextureData( model_t *mod, dbspmodel_t *bmod, int textureInd
texture->gl_texturenum = R_GetBuiltinTexture( REF_DEFAULT_TEXTURE ); texture->gl_texturenum = R_GetBuiltinTexture( REF_DEFAULT_TEXTURE );
} }
texture->fb_texturenum = 0;
// Check for luma texture // Check for luma texture
// a1ba: ignore for water because fb_texturenum will be used to store ripple texture texture->fb_texturenum = 0;
if( iswater )
return;
if( load_external ) // external textures will not have TF_HAS_LUMA flag because it set only from WAD images loader if( load_external ) // external textures will not have TF_HAS_LUMA flag because it set only from WAD images loader
{ {
if( Mod_SearchForTextureReplacement( texpath, sizeof( texpath ), mod->name, safemtname, "_luma" )) if( Mod_SearchForTextureReplacement( texpath, sizeof( texpath ), mod->name, safemtname, "_luma" ))
@@ -3005,9 +2913,9 @@ static void Mod_LoadSurfaces( model_t *mod, dbspmodel_t *bmod )
if( FBitSet( out->texinfo->flags, TEX_SPECIAL )) if( FBitSet( out->texinfo->flags, TEX_SPECIAL ))
SetBits( out->flags, SURF_DRAWTILED ); SetBits( out->flags, SURF_DRAWTILED );
Mod_CalcSurfaceBounds( mod, out, bmod ); Mod_CalcSurfaceBounds( mod, out );
Mod_CalcSurfaceExtents( mod, out, bmod ); Mod_CalcSurfaceExtents( mod, out );
Mod_CreateFaceBevels( mod, out, bmod ); Mod_CreateFaceBevels( mod, out );
// grab the second sample to detect colored lighting // grab the second sample to detect colored lighting
if( test_lightsize > 0 && lightofs != -1 ) if( test_lightsize > 0 && lightofs != -1 )
@@ -3054,6 +2962,7 @@ static void Mod_LoadSurfaces( model_t *mod, dbspmodel_t *bmod )
if( samples == 1 || samples == 3 ) if( samples == 1 || samples == 3 )
{ {
bmod->lightmap_samples = (int)samples; bmod->lightmap_samples = (int)samples;
Con_Reportf( "lighting: %s\n", (bmod->lightmap_samples == 1) ? "monochrome" : "colored" );
bmod->lightmap_samples = Q_max( bmod->lightmap_samples, 1 ); // avoid division by zero bmod->lightmap_samples = Q_max( bmod->lightmap_samples, 1 ); // avoid division by zero
} }
else Con_DPrintf( S_WARN "lighting invalid samplecount: %g, defaulting to %i\n", samples, bmod->lightmap_samples ); else Con_DPrintf( S_WARN "lighting invalid samplecount: %g, defaulting to %i\n", samples, bmod->lightmap_samples );
@@ -3085,62 +2994,16 @@ static void Mod_LoadNodes( model_t *mod, dbspmodel_t *bmod )
out->minmaxs[j+3] = in->maxs[j]; out->minmaxs[j+3] = in->maxs[j];
} }
#if !XASH_64BIT
if( in->firstface >= BIT( 24 ))
{
Host_Error( "%s: face index limit exceeded on node %i\n", __func__, i );
return;
}
if( in->numfaces >= BIT( 24 ))
{
Host_Error( "%s: face count limit exceeded on node %i\n", __func__, i );
return;
}
#endif
p = in->planenum; p = in->planenum;
out->plane = mod->planes + p; out->plane = mod->planes + p;
out->firstsurface_0 = in->firstface & 0xFFFF; out->firstsurface = in->firstface;
out->numsurfaces_0 = in->numfaces & 0xFFFF; out->numsurfaces = in->numfaces;
out->firstsurface_1 = in->firstface >> 16;
out->numsurfaces_1 = in->numfaces >> 16;
for( j = 0; j < 2; j++ ) for( j = 0; j < 2; j++ )
{ {
p = in->children[j]; p = in->children[j];
#if XASH_64BIT if( p >= 0 ) out->children[j] = mod->nodes + p;
if( p >= 0 ) out->children_[j] = mod->nodes + p; else out->children[j] = (mnode_t *)(mod->leafs + ( -1 - p ));
else out->children_[j] = (mnode_t *)(mod->leafs + ( -1 - p ));
#else
if( j == 0 )
{
if( p >= 0 )
{
out->child_0_leaf = 0;
out->child_0_off = p;
}
else
{
out->child_0_leaf = 1;
out->child_0_off = -1 - p;
}
}
else
{
if( p >= 0 )
{
out->child_1_leaf = 0;
out->child_1_off = p;
}
else
{
out->child_1_leaf = 1;
out->child_1_off = -1 - p;
}
}
#endif
} }
} }
else else
@@ -3155,20 +3018,20 @@ static void Mod_LoadNodes( model_t *mod, dbspmodel_t *bmod )
p = in->planenum; p = in->planenum;
out->plane = mod->planes + p; out->plane = mod->planes + p;
out->firstsurface_0 = in->firstface; out->firstsurface = in->firstface;
out->numsurfaces_0 = in->numfaces; out->numsurfaces = in->numfaces;
for( j = 0; j < 2; j++ ) for( j = 0; j < 2; j++ )
{ {
p = in->children[j]; p = in->children[j];
if( p >= 0 ) out->children_[j] = mod->nodes + p; if( p >= 0 ) out->children[j] = mod->nodes + p;
else out->children_[j] = (mnode_t *)(mod->leafs + ( -1 - p )); else out->children[j] = (mnode_t *)(mod->leafs + ( -1 - p ));
} }
} }
} }
// sets nodes and leafs // sets nodes and leafs
Mod_SetParent( mod, mod->nodes, NULL ); Mod_SetParent( mod->nodes, NULL );
} }
/* /*
@@ -3550,8 +3413,6 @@ static void Mod_LoadLighting( model_t *mod, dbspmodel_t *bmod )
break; break;
} }
Con_Reportf( "lighting: %s\n", FBitSet( mod->flags, MODEL_COLORED_LIGHTING ) ? "colored" : "monochrome" );
// not supposed to be load ? // not supposed to be load ?
if( FBitSet( host.features, ENGINE_LOAD_DELUXEDATA )) if( FBitSet( host.features, ENGINE_LOAD_DELUXEDATA ))
{ {
@@ -3630,6 +3491,13 @@ static qboolean Mod_LoadBmodelLumps( model_t *mod, const byte *mod_base, qboolea
Q_strncpy( loadstat.name, mod->name, sizeof( loadstat.name )); Q_strncpy( loadstat.name, mod->name, sizeof( loadstat.name ));
wadvalue[0] = '\0'; wadvalue[0] = '\0';
#ifndef SUPPORT_BSP2_FORMAT
if( header->version == QBSP2_VERSION )
{
Con_Printf( S_ERROR DEFAULT_BSP_BUILD_ERROR, mod->name );
return false;
}
#endif
switch( header->version ) switch( header->version )
{ {
case HLBSP_VERSION: case HLBSP_VERSION:
@@ -3652,9 +3520,6 @@ static qboolean Mod_LoadBmodelLumps( model_t *mod, const byte *mod_base, qboolea
// everything else // everything else
srclumps[0].lumpnumber = LUMP_ENTITIES; srclumps[0].lumpnumber = LUMP_ENTITIES;
srclumps[1].lumpnumber = LUMP_PLANES; srclumps[1].lumpnumber = LUMP_PLANES;
if( header->version == QBSP2_VERSION )
SetBits( mod->flags, MODEL_QBSP2 );
break; break;
default: default:
Con_Printf( S_ERROR "%s has wrong version number (%i should be %i)\n", mod->name, header->version, HLBSP_VERSION ); Con_Printf( S_ERROR "%s has wrong version number (%i should be %i)\n", mod->name, header->version, HLBSP_VERSION );
@@ -3705,7 +3570,7 @@ static qboolean Mod_LoadBmodelLumps( model_t *mod, const byte *mod_base, qboolea
Mod_LoadClipnodes( mod, bmod ); Mod_LoadClipnodes( mod, bmod );
// preform some post-initalization // preform some post-initalization
Mod_MakeHull0( mod, bmod ); Mod_MakeHull0( mod );
Mod_SetupSubmodels( mod, bmod ); Mod_SetupSubmodels( mod, bmod );
if( isworld ) if( isworld )
@@ -3795,6 +3660,15 @@ qboolean Mod_TestBmodelLumps( file_t *f, const char *name, const byte *mod_base,
if( silent ) if( silent )
SetBits( flags, LUMP_SILENT ); SetBits( flags, LUMP_SILENT );
#ifndef SUPPORT_BSP2_FORMAT
if( header->version == QBSP2_VERSION )
{
if( !FBitSet( flags, LUMP_SILENT ))
Con_Printf( S_ERROR DEFAULT_BSP_BUILD_ERROR, name );
return false;
}
#endif
switch( header->version ) switch( header->version )
{ {
case HLBSP_VERSION: case HLBSP_VERSION:
+2 -3
View File
@@ -135,8 +135,6 @@ extern poolhandle_t com_studiocache;
extern convar_t mod_studiocache; extern convar_t mod_studiocache;
extern convar_t r_wadtextures; extern convar_t r_wadtextures;
extern convar_t r_showhull; extern convar_t r_showhull;
extern const mclipnode16_t box_clipnodes16[6];
extern const mclipnode32_t box_clipnodes32[6];
// //
// model.c // model.c
@@ -169,12 +167,13 @@ void Mod_LoadAliasModel( model_t *mod, const void *buffer, qboolean *loaded );
// //
void Mod_LoadBrushModel( model_t *mod, const void *buffer, qboolean *loaded ); void Mod_LoadBrushModel( model_t *mod, const void *buffer, qboolean *loaded );
qboolean Mod_TestBmodelLumps( file_t *f, const char *name, const byte *mod_base, qboolean silent, dlump_t *entities ); qboolean Mod_TestBmodelLumps( file_t *f, const char *name, const byte *mod_base, qboolean silent, dlump_t *entities );
qboolean Mod_HeadnodeVisible( mnode_t *node, const byte *visbits, int *lastleaf );
int Mod_FatPVS( const vec3_t org, float radius, byte *visbuffer, int visbytes, qboolean merge, qboolean fullvis, qboolean false ); 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 ); 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_CheckLump( const char *filename, const int lump, int *lumpsize );
int Mod_ReadLump( const char *filename, const int lump, void **lumpdata, int *lumpsize ); int Mod_ReadLump( const char *filename, const int lump, void **lumpdata, int *lumpsize );
int Mod_SaveLump( const char *filename, const int lump, void *lumpdata, int lumpsize ); int Mod_SaveLump( const char *filename, const int lump, void *lumpdata, int lumpsize );
mleaf_t *Mod_PointInLeaf( const vec3_t p, mnode_t *node, model_t *mod ); mleaf_t *Mod_PointInLeaf( const vec3_t p, mnode_t *node );
int Mod_SampleSizeForFace( const msurface_t *surf ); int Mod_SampleSizeForFace( const msurface_t *surf );
byte *Mod_GetPVSForPoint( const vec3_t p ); byte *Mod_GetPVSForPoint( const vec3_t p );
void Mod_UnloadBrushModel( model_t *mod ); void Mod_UnloadBrushModel( model_t *mod );
+20 -12
View File
@@ -50,8 +50,9 @@ static matrix3x4 studio_bones[MAXSTUDIOBONES];
static uint studio_hull_hitgroup[MAXSTUDIOBONES]; static uint studio_hull_hitgroup[MAXSTUDIOBONES];
static uint cache_hull_hitgroup[MAXSTUDIOBONES]; static uint cache_hull_hitgroup[MAXSTUDIOBONES];
static mstudiocache_t cache_studio[STUDIO_CACHESIZE]; static mstudiocache_t cache_studio[STUDIO_CACHESIZE];
static mplane_t studio_planes[MAXSTUDIOBONES * 6]; static mclipnode_t studio_clipnodes[6];
static mplane_t cache_planes[MAXSTUDIOBONES * 6]; static mplane_t studio_planes[768];
static mplane_t cache_planes[768];
// current cache state // current cache state
static int cache_current; static int cache_current;
@@ -65,14 +66,25 @@ Mod_InitStudioHull
*/ */
void Mod_InitStudioHull( void ) void Mod_InitStudioHull( void )
{ {
int i; int i, side;
if( studio_hull[0].planes != NULL ) if( studio_hull[0].planes != NULL )
return; // already initailized return; // already initailized
for( i = 0; i < 6; i++ )
{
studio_clipnodes[i].planenum = i;
side = i & 1;
studio_clipnodes[i].children[side] = CONTENTS_EMPTY;
if( i != 5 ) studio_clipnodes[i].children[side^1] = i + 1;
else studio_clipnodes[i].children[side^1] = CONTENTS_SOLID;
}
for( i = 0; i < MAXSTUDIOBONES; i++ ) for( i = 0; i < MAXSTUDIOBONES; i++ )
{ {
studio_hull[i].clipnodes16 = (mclipnode16_t *)box_clipnodes16; studio_hull[i].clipnodes = studio_clipnodes;
studio_hull[i].planes = &studio_planes[i*6]; studio_hull[i].planes = &studio_planes[i*6];
studio_hull[i].firstclipnode = 0; studio_hull[i].firstclipnode = 0;
studio_hull[i].lastclipnode = 5; studio_hull[i].lastclipnode = 5;
@@ -258,11 +270,6 @@ hull_t *Mod_HullForStudio( model_t *model, float frame, int sequence, vec3_t ang
for( i = j = 0; i < mod_studiohdr->numhitboxes; i++, j += 6 ) for( i = j = 0; i < mod_studiohdr->numhitboxes; i++, j += 6 )
{ {
if( world.version == QBSP2_VERSION )
studio_hull[i].clipnodes32 = (mclipnode32_t *)box_clipnodes32;
else
studio_hull[i].clipnodes16 = (mclipnode16_t *)box_clipnodes16;
if( bSkipShield && i == 21 ) if( bSkipShield && i == 21 )
continue; // CS stuff continue; // CS stuff
@@ -382,7 +389,8 @@ static void Mod_StudioCalcRotations( int boneused[], int numbones, const byte *p
for( j = numbones - 1; j >= 0; j-- ) for( j = numbones - 1; j >= 0; j-- )
{ {
i = boneused[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; if( pseqdesc->motiontype & STUDIO_X ) pos[pseqdesc->motionbone][0] = 0.0f;
@@ -723,7 +731,7 @@ void Mod_StudioComputeBounds( void *buffer, vec3_t mins, vec3_t maxs, qboolean i
{ {
for( k = 0; k < pseqdesc->numframes; k++ ) 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 ); Mod_StudioBoundVertex( vert_mins, vert_maxs, &bone_count, pos );
} }
} }
@@ -867,7 +875,7 @@ void Mod_LoadStudioModel( model_t *mod, const void *buffer, qboolean *loaded )
mod->type = mod_studio; mod->type = mod_studio;
phdr = R_StudioLoadHeader( mod, buffer ); phdr = R_StudioLoadHeader( mod, buffer );
if( !phdr || phdr->length < sizeof( studiohdr_t )) // garbage value in length if( !phdr )
return; // bad model return; // bad model
#if !XASH_DEDICATED #if !XASH_DEDICATED
+4 -43
View File
@@ -258,7 +258,7 @@ model_t *Mod_LoadModel( model_t *mod, qboolean crash )
{ {
char tempname[MAX_QPATH]; char tempname[MAX_QPATH];
fs_offset_t length = 0; fs_offset_t length = 0;
qboolean loaded, loaded2 = false; qboolean loaded;
byte *buf; byte *buf;
model_info_t *p; model_info_t *p;
@@ -279,7 +279,7 @@ model_t *Mod_LoadModel( model_t *mod, qboolean crash )
buf = FS_LoadFile( tempname, &length, false ); buf = FS_LoadFile( tempname, &length, false );
if( !buf || length < sizeof( uint )) if( !buf )
{ {
memset( mod, 0, sizeof( model_t )); memset( mod, 0, sizeof( model_t ));
@@ -329,12 +329,11 @@ model_t *Mod_LoadModel( model_t *mod, qboolean crash )
// let the server.dll load custom data // let the server.dll load custom data
svgame.physFuncs.Mod_ProcessUserData( mod, true, buf ); svgame.physFuncs.Mod_ProcessUserData( mod, true, buf );
} }
loaded2 = true;
} }
#if !XASH_DEDICATED #if !XASH_DEDICATED
else else
{ {
loaded2 = ref.dllFuncs.Mod_ProcessRenderData( mod, true, buf ); loaded = ref.dllFuncs.Mod_ProcessRenderData( mod, true, buf );
} }
#endif #endif
} }
@@ -346,7 +345,7 @@ model_t *Mod_LoadModel( model_t *mod, qboolean crash )
hdr->pposeverts = NULL; hdr->pposeverts = NULL;
} }
if( !loaded || !loaded2 ) if( !loaded )
{ {
Mod_FreeModel( mod ); Mod_FreeModel( mod );
Mem_Free( buf ); Mem_Free( buf );
@@ -611,41 +610,3 @@ void Mod_NeedCRC( const char *name, qboolean needCRC )
if( needCRC ) SetBits( p->flags, FCRC_SHOULD_CHECKSUM ); if( needCRC ) SetBits( p->flags, FCRC_SHOULD_CHECKSUM );
else ClearBits( p->flags, FCRC_SHOULD_CHECKSUM ); else ClearBits( p->flags, FCRC_SHOULD_CHECKSUM );
} }
#if XASH_ENGINE_TESTS
static const uint8_t *fuzz_data;
static size_t fuzz_size;
static byte *Fuzz_LoadFile( const char *path, fs_offset_t *filesizeptr, qboolean gamedironly )
{
byte *buf = Mem_Malloc( host.mempool, fuzz_size );
memcpy( buf, fuzz_data, fuzz_size );
*filesizeptr = fuzz_size;
return buf;
}
int EXPORT Fuzz_Mod_LoadModel( const uint8_t *Data, size_t Size );
int EXPORT Fuzz_Mod_LoadModel( const uint8_t *Data, size_t Size )
{
model_t mod = { .name = "test", .needload = NL_NEEDS_LOADED };
Memory_Init();
host.type = HOST_DEDICATED;
host.mempool = Mem_AllocPool( "fuzzing pool" );
fuzz_data = Data;
fuzz_size = Size;
refState.draw_surfaces = NULL;
g_fsapi.LoadFile = Fuzz_LoadFile;
if( Mod_LoadModel( &mod, false ) && mod.mempool )
Mem_FreePool( &mod.mempool );
Mem_FreePool( &host.mempool );
return 0;
}
#endif // XASH_ENGINE_TESTS
+82 -207
View File
@@ -18,177 +18,11 @@ GNU General Public License for more details.
#include "net_buffer.h" #include "net_buffer.h"
#include "xash3d_mathlib.h" #include "xash3d_mathlib.h"
static const uint32_t BitWriteMasks[32][32] = // precalculated bit masks for WriteUBitLong.
{ { // Using these tables instead of doing the calculations
0xfffffffe, 0xfffffffc, 0xfffffff8, 0xfffffff0, 0xffffffe0, 0xffffffc0, 0xffffff80, 0xffffff00, // gives a 33% speedup in WriteUBitLong.
0xfffffe00, 0xfffffc00, 0xfffff800, 0xfffff000, 0xffffe000, 0xffffc000, 0xffff8000, 0xffff0000, static uint32_t BitWriteMasks[32][33];
0xfffe0000, 0xfffc0000, 0xfff80000, 0xfff00000, 0xffe00000, 0xffc00000, 0xff800000, 0xff000000, static uint32_t ExtraMasks[32];
0xfe000000, 0xfc000000, 0xf8000000, 0xf0000000, 0xe0000000, 0xc0000000, 0x80000000, 0x00000000,
}, {
0xfffffffd, 0xfffffff9, 0xfffffff1, 0xffffffe1, 0xffffffc1, 0xffffff81, 0xffffff01, 0xfffffe01,
0xfffffc01, 0xfffff801, 0xfffff001, 0xffffe001, 0xffffc001, 0xffff8001, 0xffff0001, 0xfffe0001,
0xfffc0001, 0xfff80001, 0xfff00001, 0xffe00001, 0xffc00001, 0xff800001, 0xff000001, 0xfe000001,
0xfc000001, 0xf8000001, 0xf0000001, 0xe0000001, 0xc0000001, 0x80000001, 0x00000001, 0x00000001,
}, {
0xfffffffb, 0xfffffff3, 0xffffffe3, 0xffffffc3, 0xffffff83, 0xffffff03, 0xfffffe03, 0xfffffc03,
0xfffff803, 0xfffff003, 0xffffe003, 0xffffc003, 0xffff8003, 0xffff0003, 0xfffe0003, 0xfffc0003,
0xfff80003, 0xfff00003, 0xffe00003, 0xffc00003, 0xff800003, 0xff000003, 0xfe000003, 0xfc000003,
0xf8000003, 0xf0000003, 0xe0000003, 0xc0000003, 0x80000003, 0x00000003, 0x00000003, 0x00000003,
}, {
0xfffffff7, 0xffffffe7, 0xffffffc7, 0xffffff87, 0xffffff07, 0xfffffe07, 0xfffffc07, 0xfffff807,
0xfffff007, 0xffffe007, 0xffffc007, 0xffff8007, 0xffff0007, 0xfffe0007, 0xfffc0007, 0xfff80007,
0xfff00007, 0xffe00007, 0xffc00007, 0xff800007, 0xff000007, 0xfe000007, 0xfc000007, 0xf8000007,
0xf0000007, 0xe0000007, 0xc0000007, 0x80000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007,
}, {
0xffffffef, 0xffffffcf, 0xffffff8f, 0xffffff0f, 0xfffffe0f, 0xfffffc0f, 0xfffff80f, 0xfffff00f,
0xffffe00f, 0xffffc00f, 0xffff800f, 0xffff000f, 0xfffe000f, 0xfffc000f, 0xfff8000f, 0xfff0000f,
0xffe0000f, 0xffc0000f, 0xff80000f, 0xff00000f, 0xfe00000f, 0xfc00000f, 0xf800000f, 0xf000000f,
0xe000000f, 0xc000000f, 0x8000000f, 0x0000000f, 0x0000000f, 0x0000000f, 0x0000000f, 0x0000000f,
}, {
0xffffffdf, 0xffffff9f, 0xffffff1f, 0xfffffe1f, 0xfffffc1f, 0xfffff81f, 0xfffff01f, 0xffffe01f,
0xffffc01f, 0xffff801f, 0xffff001f, 0xfffe001f, 0xfffc001f, 0xfff8001f, 0xfff0001f, 0xffe0001f,
0xffc0001f, 0xff80001f, 0xff00001f, 0xfe00001f, 0xfc00001f, 0xf800001f, 0xf000001f, 0xe000001f,
0xc000001f, 0x8000001f, 0x0000001f, 0x0000001f, 0x0000001f, 0x0000001f, 0x0000001f, 0x0000001f,
}, {
0xffffffbf, 0xffffff3f, 0xfffffe3f, 0xfffffc3f, 0xfffff83f, 0xfffff03f, 0xffffe03f, 0xffffc03f,
0xffff803f, 0xffff003f, 0xfffe003f, 0xfffc003f, 0xfff8003f, 0xfff0003f, 0xffe0003f, 0xffc0003f,
0xff80003f, 0xff00003f, 0xfe00003f, 0xfc00003f, 0xf800003f, 0xf000003f, 0xe000003f, 0xc000003f,
0x8000003f, 0x0000003f, 0x0000003f, 0x0000003f, 0x0000003f, 0x0000003f, 0x0000003f, 0x0000003f,
}, {
0xffffff7f, 0xfffffe7f, 0xfffffc7f, 0xfffff87f, 0xfffff07f, 0xffffe07f, 0xffffc07f, 0xffff807f,
0xffff007f, 0xfffe007f, 0xfffc007f, 0xfff8007f, 0xfff0007f, 0xffe0007f, 0xffc0007f, 0xff80007f,
0xff00007f, 0xfe00007f, 0xfc00007f, 0xf800007f, 0xf000007f, 0xe000007f, 0xc000007f, 0x8000007f,
0x0000007f, 0x0000007f, 0x0000007f, 0x0000007f, 0x0000007f, 0x0000007f, 0x0000007f, 0x0000007f,
}, {
0xfffffeff, 0xfffffcff, 0xfffff8ff, 0xfffff0ff, 0xffffe0ff, 0xffffc0ff, 0xffff80ff, 0xffff00ff,
0xfffe00ff, 0xfffc00ff, 0xfff800ff, 0xfff000ff, 0xffe000ff, 0xffc000ff, 0xff8000ff, 0xff0000ff,
0xfe0000ff, 0xfc0000ff, 0xf80000ff, 0xf00000ff, 0xe00000ff, 0xc00000ff, 0x800000ff, 0x000000ff,
0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff,
}, {
0xfffffdff, 0xfffff9ff, 0xfffff1ff, 0xffffe1ff, 0xffffc1ff, 0xffff81ff, 0xffff01ff, 0xfffe01ff,
0xfffc01ff, 0xfff801ff, 0xfff001ff, 0xffe001ff, 0xffc001ff, 0xff8001ff, 0xff0001ff, 0xfe0001ff,
0xfc0001ff, 0xf80001ff, 0xf00001ff, 0xe00001ff, 0xc00001ff, 0x800001ff, 0x000001ff, 0x000001ff,
0x000001ff, 0x000001ff, 0x000001ff, 0x000001ff, 0x000001ff, 0x000001ff, 0x000001ff, 0x000001ff,
}, {
0xfffffbff, 0xfffff3ff, 0xffffe3ff, 0xffffc3ff, 0xffff83ff, 0xffff03ff, 0xfffe03ff, 0xfffc03ff,
0xfff803ff, 0xfff003ff, 0xffe003ff, 0xffc003ff, 0xff8003ff, 0xff0003ff, 0xfe0003ff, 0xfc0003ff,
0xf80003ff, 0xf00003ff, 0xe00003ff, 0xc00003ff, 0x800003ff, 0x000003ff, 0x000003ff, 0x000003ff,
0x000003ff, 0x000003ff, 0x000003ff, 0x000003ff, 0x000003ff, 0x000003ff, 0x000003ff, 0x000003ff,
}, {
0xfffff7ff, 0xffffe7ff, 0xffffc7ff, 0xffff87ff, 0xffff07ff, 0xfffe07ff, 0xfffc07ff, 0xfff807ff,
0xfff007ff, 0xffe007ff, 0xffc007ff, 0xff8007ff, 0xff0007ff, 0xfe0007ff, 0xfc0007ff, 0xf80007ff,
0xf00007ff, 0xe00007ff, 0xc00007ff, 0x800007ff, 0x000007ff, 0x000007ff, 0x000007ff, 0x000007ff,
0x000007ff, 0x000007ff, 0x000007ff, 0x000007ff, 0x000007ff, 0x000007ff, 0x000007ff, 0x000007ff,
}, {
0xffffefff, 0xffffcfff, 0xffff8fff, 0xffff0fff, 0xfffe0fff, 0xfffc0fff, 0xfff80fff, 0xfff00fff,
0xffe00fff, 0xffc00fff, 0xff800fff, 0xff000fff, 0xfe000fff, 0xfc000fff, 0xf8000fff, 0xf0000fff,
0xe0000fff, 0xc0000fff, 0x80000fff, 0x00000fff, 0x00000fff, 0x00000fff, 0x00000fff, 0x00000fff,
0x00000fff, 0x00000fff, 0x00000fff, 0x00000fff, 0x00000fff, 0x00000fff, 0x00000fff, 0x00000fff,
}, {
0xffffdfff, 0xffff9fff, 0xffff1fff, 0xfffe1fff, 0xfffc1fff, 0xfff81fff, 0xfff01fff, 0xffe01fff,
0xffc01fff, 0xff801fff, 0xff001fff, 0xfe001fff, 0xfc001fff, 0xf8001fff, 0xf0001fff, 0xe0001fff,
0xc0001fff, 0x80001fff, 0x00001fff, 0x00001fff, 0x00001fff, 0x00001fff, 0x00001fff, 0x00001fff,
0x00001fff, 0x00001fff, 0x00001fff, 0x00001fff, 0x00001fff, 0x00001fff, 0x00001fff, 0x00001fff,
}, {
0xffffbfff, 0xffff3fff, 0xfffe3fff, 0xfffc3fff, 0xfff83fff, 0xfff03fff, 0xffe03fff, 0xffc03fff,
0xff803fff, 0xff003fff, 0xfe003fff, 0xfc003fff, 0xf8003fff, 0xf0003fff, 0xe0003fff, 0xc0003fff,
0x80003fff, 0x00003fff, 0x00003fff, 0x00003fff, 0x00003fff, 0x00003fff, 0x00003fff, 0x00003fff,
0x00003fff, 0x00003fff, 0x00003fff, 0x00003fff, 0x00003fff, 0x00003fff, 0x00003fff, 0x00003fff,
}, {
0xffff7fff, 0xfffe7fff, 0xfffc7fff, 0xfff87fff, 0xfff07fff, 0xffe07fff, 0xffc07fff, 0xff807fff,
0xff007fff, 0xfe007fff, 0xfc007fff, 0xf8007fff, 0xf0007fff, 0xe0007fff, 0xc0007fff, 0x80007fff,
0x00007fff, 0x00007fff, 0x00007fff, 0x00007fff, 0x00007fff, 0x00007fff, 0x00007fff, 0x00007fff,
0x00007fff, 0x00007fff, 0x00007fff, 0x00007fff, 0x00007fff, 0x00007fff, 0x00007fff, 0x00007fff,
}, {
0xfffeffff, 0xfffcffff, 0xfff8ffff, 0xfff0ffff, 0xffe0ffff, 0xffc0ffff, 0xff80ffff, 0xff00ffff,
0xfe00ffff, 0xfc00ffff, 0xf800ffff, 0xf000ffff, 0xe000ffff, 0xc000ffff, 0x8000ffff, 0x0000ffff,
0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff,
0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff,
}, {
0xfffdffff, 0xfff9ffff, 0xfff1ffff, 0xffe1ffff, 0xffc1ffff, 0xff81ffff, 0xff01ffff, 0xfe01ffff,
0xfc01ffff, 0xf801ffff, 0xf001ffff, 0xe001ffff, 0xc001ffff, 0x8001ffff, 0x0001ffff, 0x0001ffff,
0x0001ffff, 0x0001ffff, 0x0001ffff, 0x0001ffff, 0x0001ffff, 0x0001ffff, 0x0001ffff, 0x0001ffff,
0x0001ffff, 0x0001ffff, 0x0001ffff, 0x0001ffff, 0x0001ffff, 0x0001ffff, 0x0001ffff, 0x0001ffff,
}, {
0xfffbffff, 0xfff3ffff, 0xffe3ffff, 0xffc3ffff, 0xff83ffff, 0xff03ffff, 0xfe03ffff, 0xfc03ffff,
0xf803ffff, 0xf003ffff, 0xe003ffff, 0xc003ffff, 0x8003ffff, 0x0003ffff, 0x0003ffff, 0x0003ffff,
0x0003ffff, 0x0003ffff, 0x0003ffff, 0x0003ffff, 0x0003ffff, 0x0003ffff, 0x0003ffff, 0x0003ffff,
0x0003ffff, 0x0003ffff, 0x0003ffff, 0x0003ffff, 0x0003ffff, 0x0003ffff, 0x0003ffff, 0x0003ffff,
}, {
0xfff7ffff, 0xffe7ffff, 0xffc7ffff, 0xff87ffff, 0xff07ffff, 0xfe07ffff, 0xfc07ffff, 0xf807ffff,
0xf007ffff, 0xe007ffff, 0xc007ffff, 0x8007ffff, 0x0007ffff, 0x0007ffff, 0x0007ffff, 0x0007ffff,
0x0007ffff, 0x0007ffff, 0x0007ffff, 0x0007ffff, 0x0007ffff, 0x0007ffff, 0x0007ffff, 0x0007ffff,
0x0007ffff, 0x0007ffff, 0x0007ffff, 0x0007ffff, 0x0007ffff, 0x0007ffff, 0x0007ffff, 0x0007ffff,
}, {
0xffefffff, 0xffcfffff, 0xff8fffff, 0xff0fffff, 0xfe0fffff, 0xfc0fffff, 0xf80fffff, 0xf00fffff,
0xe00fffff, 0xc00fffff, 0x800fffff, 0x000fffff, 0x000fffff, 0x000fffff, 0x000fffff, 0x000fffff,
0x000fffff, 0x000fffff, 0x000fffff, 0x000fffff, 0x000fffff, 0x000fffff, 0x000fffff, 0x000fffff,
0x000fffff, 0x000fffff, 0x000fffff, 0x000fffff, 0x000fffff, 0x000fffff, 0x000fffff, 0x000fffff,
}, {
0xffdfffff, 0xff9fffff, 0xff1fffff, 0xfe1fffff, 0xfc1fffff, 0xf81fffff, 0xf01fffff, 0xe01fffff,
0xc01fffff, 0x801fffff, 0x001fffff, 0x001fffff, 0x001fffff, 0x001fffff, 0x001fffff, 0x001fffff,
0x001fffff, 0x001fffff, 0x001fffff, 0x001fffff, 0x001fffff, 0x001fffff, 0x001fffff, 0x001fffff,
0x001fffff, 0x001fffff, 0x001fffff, 0x001fffff, 0x001fffff, 0x001fffff, 0x001fffff, 0x001fffff,
}, {
0xffbfffff, 0xff3fffff, 0xfe3fffff, 0xfc3fffff, 0xf83fffff, 0xf03fffff, 0xe03fffff, 0xc03fffff,
0x803fffff, 0x003fffff, 0x003fffff, 0x003fffff, 0x003fffff, 0x003fffff, 0x003fffff, 0x003fffff,
0x003fffff, 0x003fffff, 0x003fffff, 0x003fffff, 0x003fffff, 0x003fffff, 0x003fffff, 0x003fffff,
0x003fffff, 0x003fffff, 0x003fffff, 0x003fffff, 0x003fffff, 0x003fffff, 0x003fffff, 0x003fffff,
}, {
0xff7fffff, 0xfe7fffff, 0xfc7fffff, 0xf87fffff, 0xf07fffff, 0xe07fffff, 0xc07fffff, 0x807fffff,
0x007fffff, 0x007fffff, 0x007fffff, 0x007fffff, 0x007fffff, 0x007fffff, 0x007fffff, 0x007fffff,
0x007fffff, 0x007fffff, 0x007fffff, 0x007fffff, 0x007fffff, 0x007fffff, 0x007fffff, 0x007fffff,
0x007fffff, 0x007fffff, 0x007fffff, 0x007fffff, 0x007fffff, 0x007fffff, 0x007fffff, 0x007fffff,
}, {
0xfeffffff, 0xfcffffff, 0xf8ffffff, 0xf0ffffff, 0xe0ffffff, 0xc0ffffff, 0x80ffffff, 0x00ffffff,
0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,
0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,
0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,
}, {
0xfdffffff, 0xf9ffffff, 0xf1ffffff, 0xe1ffffff, 0xc1ffffff, 0x81ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
}, {
0xfbffffff, 0xf3ffffff, 0xe3ffffff, 0xc3ffffff, 0x83ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff,
0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff,
0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff,
0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff,
}, {
0xf7ffffff, 0xe7ffffff, 0xc7ffffff, 0x87ffffff, 0x07ffffff, 0x07ffffff, 0x07ffffff, 0x07ffffff,
0x07ffffff, 0x07ffffff, 0x07ffffff, 0x07ffffff, 0x07ffffff, 0x07ffffff, 0x07ffffff, 0x07ffffff,
0x07ffffff, 0x07ffffff, 0x07ffffff, 0x07ffffff, 0x07ffffff, 0x07ffffff, 0x07ffffff, 0x07ffffff,
0x07ffffff, 0x07ffffff, 0x07ffffff, 0x07ffffff, 0x07ffffff, 0x07ffffff, 0x07ffffff, 0x07ffffff,
}, {
0xefffffff, 0xcfffffff, 0x8fffffff, 0x0fffffff, 0x0fffffff, 0x0fffffff, 0x0fffffff, 0x0fffffff,
0x0fffffff, 0x0fffffff, 0x0fffffff, 0x0fffffff, 0x0fffffff, 0x0fffffff, 0x0fffffff, 0x0fffffff,
0x0fffffff, 0x0fffffff, 0x0fffffff, 0x0fffffff, 0x0fffffff, 0x0fffffff, 0x0fffffff, 0x0fffffff,
0x0fffffff, 0x0fffffff, 0x0fffffff, 0x0fffffff, 0x0fffffff, 0x0fffffff, 0x0fffffff, 0x0fffffff,
}, {
0xdfffffff, 0x9fffffff, 0x1fffffff, 0x1fffffff, 0x1fffffff, 0x1fffffff, 0x1fffffff, 0x1fffffff,
0x1fffffff, 0x1fffffff, 0x1fffffff, 0x1fffffff, 0x1fffffff, 0x1fffffff, 0x1fffffff, 0x1fffffff,
0x1fffffff, 0x1fffffff, 0x1fffffff, 0x1fffffff, 0x1fffffff, 0x1fffffff, 0x1fffffff, 0x1fffffff,
0x1fffffff, 0x1fffffff, 0x1fffffff, 0x1fffffff, 0x1fffffff, 0x1fffffff, 0x1fffffff, 0x1fffffff,
}, {
0xbfffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff,
0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff,
0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff,
0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff,
}, {
0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff,
0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff,
0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff,
0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff,
} };
static const uint32_t ExtraMasks[32] =
{
0x00000000, 0x00000001, 0x00000003, 0x00000007, 0x0000000f, 0x0000001f, 0x0000003f, 0x0000007f,
0x000000ff, 0x000001ff, 0x000003ff, 0x000007ff, 0x00000fff, 0x00001fff, 0x00003fff, 0x00007fff,
0x0000ffff, 0x0001ffff, 0x0003ffff, 0x0007ffff, 0x000fffff, 0x001fffff, 0x003fffff, 0x007fffff,
0x00ffffff, 0x01ffffff, 0x03ffffff, 0x07ffffff, 0x0fffffff, 0x1fffffff, 0x3fffffff, 0x7fffffff,
};
const char *const svc_strings[svc_lastmsg+1] = const char *const svc_strings[svc_lastmsg+1] =
{ {
"svc_bad", "svc_bad",
@@ -267,14 +101,20 @@ const char *const svc_legacy_strings[svc_lastmsg+1] =
const char *const svc_goldsrc_strings[svc_lastmsg+1] = const char *const svc_goldsrc_strings[svc_lastmsg+1] =
{ {
[svc_goldsrc_version] = "svc_goldsrc_version", [svc_goldsrc_version] = "svc_goldsrc_version",
[svc_goldsrc_serverinfo] = "svc_goldsrc_serverinfo",
[svc_goldsrc_deltadescription] = "svc_goldsrc_deltadescription",
[svc_goldsrc_stopsound] = "svc_goldsrc_stopsound", [svc_goldsrc_stopsound] = "svc_goldsrc_stopsound",
[svc_goldsrc_damage] = "svc_goldsrc_damage", [svc_goldsrc_damage] = "svc_goldsrc_damage",
[svc_goldsrc_killedmonster] = "svc_goldsrc_killedmonster", [svc_goldsrc_killedmonster] = "svc_goldsrc_killedmonster",
[svc_goldsrc_foundsecret] = "svc_goldsrc_foundsecret", [svc_goldsrc_foundsecret] = "svc_goldsrc_foundsecret",
[svc_goldsrc_spawnstaticsound] = "svc_goldsrc_spawnstaticsound", [svc_goldsrc_spawnstaticsound] = "svc_goldsrc_spawnstaticsound",
[svc_goldsrc_decalname] = "svc_goldsrc_decalname", [svc_goldsrc_decalname] = "svc_goldsrc_decalname",
[svc_goldsrc_newusermsg] = "svc_goldsrc_newusermsg",
[svc_goldsrc_newmovevars] = "svc_goldsrc_newmovevars",
[svc_goldsrc_sendextrainfo] = "svc_goldsrc_sendextrainfo", [svc_goldsrc_sendextrainfo] = "svc_goldsrc_sendextrainfo",
[svc_goldsrc_timescale] = "svc_goldsrc_timescale", [svc_goldsrc_timescale] = "svc_goldsrc_timescale",
[svc_goldsrc_sendcvarvalue] = "svc_goldsrc_sendcvarvalue",
[svc_goldsrc_sendcvarvalue2] = "svc_goldsrc_sendcvarvalue2",
}; };
const char *const svc_quake_strings[svc_lastmsg+1] = const char *const svc_quake_strings[svc_lastmsg+1] =
@@ -298,41 +138,65 @@ const char *const svc_quake_strings[svc_lastmsg+1] =
[svc_fog] = "svc_quake_fog", [svc_fog] = "svc_quake_fog",
}; };
void MSG_InitMasks( void )
{
uint startbit, endbit;
uint maskBit, nBitsLeft;
for( startbit = 0; startbit < 32; startbit++ )
{
for( nBitsLeft = 0; nBitsLeft < 33; nBitsLeft++ )
{
endbit = startbit + nBitsLeft;
BitWriteMasks[startbit][nBitsLeft] = (uint)BIT( startbit ) - 1;
if( endbit < 32 ) BitWriteMasks[startbit][nBitsLeft] |= ~((uint)BIT( endbit ) - 1 );
}
}
for( maskBit = 0; maskBit < 32; maskBit++ )
ExtraMasks[maskBit] = (uint)BIT( maskBit ) - 1;
}
void MSG_WriteUBitLong( sizebuf_t *sb, uint curData, int numbits ) void MSG_WriteUBitLong( sizebuf_t *sb, uint curData, int numbits )
{ {
int nBitsLeft = numbits; Assert( numbits >= 0 && numbits <= 32 );
int iCurBit = sb->iCurBit;
uint iDWord = iCurBit >> 5; // Mask in a dword.
uint32_t iCurBitMasked;
int nBitsWritten;
Assert( numbits >= 1 && numbits <= 32 );
// bounds checking.. // bounds checking..
if( MSG_Overflow( sb, numbits )) if(( sb->iCurBit + numbits ) > sb->nDataBits )
{ {
sb->bOverflow = true;
sb->iCurBit = sb->nDataBits; sb->iCurBit = sb->nDataBits;
return;
} }
else
iCurBitMasked = iCurBit & 31;
((uint32_t *)sb->pData)[iDWord] &= BitWriteMasks[iCurBitMasked][nBitsLeft-1];
((uint32_t *)sb->pData)[iDWord] |= curData << iCurBitMasked;
// did it span a dword?
nBitsWritten = 32 - iCurBitMasked;
if( nBitsWritten < nBitsLeft )
{ {
nBitsLeft -= nBitsWritten; int nBitsLeft = numbits;
iCurBit += nBitsWritten; int iCurBit = sb->iCurBit;
curData >>= nBitsWritten; uint iDWord = iCurBit >> 5; // Mask in a dword.
uint32_t iCurBitMasked;
int nBitsWritten;
Assert(( iDWord * 4 + sizeof( int )) <= (uint)MSG_GetMaxBytes( sb ));
iCurBitMasked = iCurBit & 31; iCurBitMasked = iCurBit & 31;
((uint32_t *)sb->pData)[iDWord+1] &= BitWriteMasks[iCurBitMasked][nBitsLeft-1]; ((uint32_t *)sb->pData)[iDWord] &= BitWriteMasks[iCurBitMasked][nBitsLeft];
((uint32_t *)sb->pData)[iDWord+1] |= curData << iCurBitMasked; ((uint32_t *)sb->pData)[iDWord] |= curData << iCurBitMasked;
// did it span a dword?
nBitsWritten = 32 - iCurBitMasked;
if( nBitsWritten < nBitsLeft )
{
nBitsLeft -= nBitsWritten;
iCurBit += nBitsWritten;
curData >>= nBitsWritten;
iCurBitMasked = iCurBit & 31;
((uint32_t *)sb->pData)[iDWord+1] &= BitWriteMasks[iCurBitMasked][nBitsLeft];
((uint32_t *)sb->pData)[iDWord+1] |= curData << iCurBitMasked;
}
sb->iCurBit += numbits;
} }
sb->iCurBit += numbits;
} }
/* /*
@@ -380,7 +244,7 @@ qboolean MSG_WriteBits( sizebuf_t *sb, const void *pData, int nBits )
int nBitsLeft = nBits; int nBitsLeft = nBits;
// get output dword-aligned. // get output dword-aligned.
while((( uintptr_t )pOut & 3 ) != 0 && nBitsLeft >= 8 ) while((( uint32_t )pOut & 3 ) != 0 && nBitsLeft >= 8 )
{ {
MSG_WriteUBitLong( sb, *pOut, 8 ); MSG_WriteUBitLong( sb, *pOut, 8 );
@@ -417,14 +281,16 @@ qboolean MSG_WriteBits( sizebuf_t *sb, const void *pData, int nBits )
void MSG_WriteBitAngle( sizebuf_t *sb, float fAngle, int numbits ) void MSG_WriteBitAngle( sizebuf_t *sb, float fAngle, int numbits )
{ {
const uint shift = ( 1 << numbits ); uint mask, shift;
const uint mask = shift - 1;
int d; int d;
// clamp the angle before receiving // clamp the angle before receiving
fAngle = fmod( fAngle, 360.0f ); fAngle = fmod( fAngle, 360.0f );
if( fAngle < 0 ) fAngle += 360.0f; if( fAngle < 0 ) fAngle += 360.0f;
shift = ( 1 << numbits );
mask = shift - 1;
d = (int)(( fAngle * shift ) / 360.0f ); d = (int)(( fAngle * shift ) / 360.0f );
d &= mask; d &= mask;
@@ -578,8 +444,9 @@ uint MSG_ReadUBitLong( sizebuf_t *sb, int numbits )
return 0; // end of message return 0; // end of message
} }
if( MSG_Overflow( sb, numbits )) if(( sb->iCurBit + numbits ) > sb->nDataBits )
{ {
sb->bOverflow = true;
sb->iCurBit = sb->nDataBits; sb->iCurBit = sb->nDataBits;
return 0; return 0;
} }
@@ -652,9 +519,13 @@ qboolean MSG_ReadBits( sizebuf_t *sb, void *pOutData, int nBits )
float MSG_ReadBitAngle( sizebuf_t *sb, int numbits ) float MSG_ReadBitAngle( sizebuf_t *sb, int numbits )
{ {
float shift = (float)( 1 << numbits ); float fReturn, shift;
int i = MSG_ReadUBitLong( sb, numbits ); int i;
float fReturn = (float)i * ( 360.0f / shift );
shift = (float)( 1 << numbits );
i = MSG_ReadUBitLong( sb, numbits );
fReturn = (float)i * ( 360.0f / shift );
// clamp the finale angle // clamp the finale angle
if( fReturn < -180.0f ) fReturn += 360.0f; if( fReturn < -180.0f ) fReturn += 360.0f;
@@ -666,11 +537,11 @@ float MSG_ReadBitAngle( sizebuf_t *sb, int numbits )
// Append numbits least significant bits from data to the current bit stream // Append numbits least significant bits from data to the current bit stream
int MSG_ReadSBitLong( sizebuf_t *sb, int numbits ) int MSG_ReadSBitLong( sizebuf_t *sb, int numbits )
{ {
int r; int r, sign;
if( sb->iAlternateSign ) if( sb->iAlternateSign )
{ {
int sign = MSG_ReadOneBit( sb ); sign = MSG_ReadOneBit( sb );
r = MSG_ReadUBitLong( sb, numbits - 1 ); r = MSG_ReadUBitLong( sb, numbits - 1 );
if( sign ) if( sign )
@@ -679,7 +550,9 @@ int MSG_ReadSBitLong( sizebuf_t *sb, int numbits )
else else
{ {
r = MSG_ReadUBitLong( sb, numbits - 1 ); r = MSG_ReadUBitLong( sb, numbits - 1 );
if( MSG_ReadOneBit( sb )) sign = MSG_ReadOneBit( sb );
if( sign )
r = -( BIT( numbits - 1 ) - r ); r = -( BIT( numbits - 1 ) - r );
} }
@@ -800,12 +673,12 @@ qboolean MSG_ReadBytes( sizebuf_t *sb, void *pOut, int nBytes )
static char *MSG_ReadStringExt( sizebuf_t *sb, qboolean bLine ) static char *MSG_ReadStringExt( sizebuf_t *sb, qboolean bLine )
{ {
static char string[4096]; static char string[4096];
int l = 0; int l = 0, c;
do do
{ {
// use MSG_ReadByte so -1 is out of bounds // use MSG_ReadByte so -1 is out of bounds
int c = MSG_ReadByte( sb ); c = MSG_ReadByte( sb );
if( c == 0 ) break; if( c == 0 ) break;
else if( bLine && c == '\n' ) else if( bLine && c == '\n' )
@@ -998,6 +871,8 @@ static void Test_Buffer_ExciseBits( void )
void Test_RunBuffer( void ) void Test_RunBuffer( void )
{ {
MSG_InitMasks();
TRUN( Test_Buffer_BitByte( )); TRUN( Test_Buffer_BitByte( ));
TRUN( Test_Buffer_Write( )); TRUN( Test_Buffer_Write( ));
TRUN( Test_Buffer_Read( )); TRUN( Test_Buffer_Read( ));
+1
View File
@@ -193,6 +193,7 @@ static inline void MSG_StartBitWriting( sizebuf_t *sb )
sb->iAlternateSign++; sb->iAlternateSign++;
} }
void MSG_InitMasks( void ); // called once at startup engine
void MSG_ExciseBits( sizebuf_t *sb, int startbit, int bitstoremove ); void MSG_ExciseBits( sizebuf_t *sb, int startbit, int bitstoremove );
// Bit-write functions // Bit-write functions
+6 -5
View File
@@ -272,6 +272,8 @@ void Netchan_Init( void )
Cvar_FullSet( net_qport.name, buf, net_qport.flags ); Cvar_FullSet( net_qport.name, buf, net_qport.flags );
net_mempool = Mem_AllocPool( "Network Pool" ); net_mempool = Mem_AllocPool( "Network Pool" );
MSG_InitMasks(); // initialize bit-masks
} }
void Netchan_Shutdown( void ) void Netchan_Shutdown( void )
@@ -341,7 +343,6 @@ void Netchan_Setup( netsrc_t sock, netchan_t *chan, netadr_t adr, int qport, voi
chan->split = FBitSet( flags, NETCHAN_USE_LEGACY_SPLIT ) ? true : false; chan->split = FBitSet( flags, NETCHAN_USE_LEGACY_SPLIT ) ? true : false;
chan->use_munge = FBitSet( flags, NETCHAN_USE_MUNGE ) ? true : false; chan->use_munge = FBitSet( flags, NETCHAN_USE_MUNGE ) ? true : false;
chan->use_bz2 = FBitSet( flags, NETCHAN_USE_BZIP2 ) ? true : false; chan->use_bz2 = FBitSet( flags, NETCHAN_USE_BZIP2 ) ? true : false;
chan->use_lzss = FBitSet( flags, NETCHAN_USE_LZSS ) ? true : false;
chan->gs_netchan = FBitSet( flags, NETCHAN_GOLDSRC ) ? true : false; chan->gs_netchan = FBitSet( flags, NETCHAN_GOLDSRC ) ? true : false;
MSG_Init( &chan->message, "NetData", chan->message_buf, sizeof( chan->message_buf )); MSG_Init( &chan->message, "NetData", chan->message_buf, sizeof( chan->message_buf ));
@@ -767,7 +768,7 @@ static void Netchan_CreateFragments_( netchan_t *chan, sizebuf_t *msg )
Host_Error( "%s: BZ2 compression is not supported for server", __func__ ); Host_Error( "%s: BZ2 compression is not supported for server", __func__ );
#endif #endif
} }
else if( chan->use_lzss && !LZSS_IsCompressed( MSG_GetData( msg ), MSG_GetMaxBytes( msg ))) else if( !chan->use_bz2 && !LZSS_IsCompressed( MSG_GetData( msg ), MSG_GetMaxBytes( msg )))
{ {
uint uCompressedSize = 0; uint uCompressedSize = 0;
uint uSourceSize = MSG_GetNumBytesWritten( msg ); uint uSourceSize = MSG_GetNumBytesWritten( msg );
@@ -1174,7 +1175,7 @@ qboolean Netchan_CopyNormalFragments( netchan_t *chan, sizebuf_t *msg, size_t *l
p = n; p = n;
} }
if( chan->use_bz2 && !memcmp( MSG_GetData( msg ), "BZ2", 4 )) if( chan->use_bz2 && !memcmp( MSG_GetData( msg ), "BZ2", 4 ) )
{ {
#if !XASH_DEDICATED #if !XASH_DEDICATED
byte buf[0x10000]; byte buf[0x10000];
@@ -1195,7 +1196,7 @@ qboolean Netchan_CopyNormalFragments( netchan_t *chan, sizebuf_t *msg, size_t *l
Host_Error( "%s: BZ2 compression is not supported for server\n", __func__ ); Host_Error( "%s: BZ2 compression is not supported for server\n", __func__ );
#endif #endif
} }
else if( chan->use_lzss && LZSS_IsCompressed( MSG_GetData( msg ), size )) else if( !chan->use_bz2 && LZSS_IsCompressed( MSG_GetData( msg ), size ))
{ {
uint uDecompressedLen = LZSS_GetActualSize( MSG_GetData( msg ), size ); uint uDecompressedLen = LZSS_GetActualSize( MSG_GetData( msg ), size );
byte buf[NET_MAX_MESSAGE]; byte buf[NET_MAX_MESSAGE];
@@ -1346,7 +1347,7 @@ qboolean Netchan_CopyFileFragments( netchan_t *chan, sizebuf_t *msg )
Host_Error( "%s: BZ2 compression is not supported for server", __func__ ); Host_Error( "%s: BZ2 compression is not supported for server", __func__ );
#endif #endif
} }
else if( chan->use_lzss && LZSS_IsCompressed( buffer, nsize + 1 )) else if( LZSS_IsCompressed( buffer, nsize + 1 ))
{ {
byte *uncompressedBuffer; byte *uncompressedBuffer;
+51 -37
View File
@@ -39,6 +39,8 @@ GNU General Public License for more details.
#define DT_SIGNED BIT( 8 ) // sign modificator #define DT_SIGNED BIT( 8 ) // sign modificator
#define DT_SIGNED_GS BIT( 31 ) // GoldSrc-specific sign modificator #define DT_SIGNED_GS BIT( 31 ) // GoldSrc-specific sign modificator
#define NUM_FIELDS( x ) ((sizeof( x ) / sizeof( x[0] )) - 1)
// helper macroses // helper macroses
#define ENTS_DEF( x ) #x, offsetof( entity_state_t, x ), sizeof( ((entity_state_t *)0)->x ) #define ENTS_DEF( x ) #x, offsetof( entity_state_t, x ), sizeof( ((entity_state_t *)0)->x )
#define UCMD_DEF( x ) #x, offsetof( usercmd_t, x ), sizeof( ((usercmd_t *)0)->x ) #define UCMD_DEF( x ) #x, offsetof( usercmd_t, x ), sizeof( ((usercmd_t *)0)->x )
@@ -69,6 +71,7 @@ static const delta_field_t cmd_fields[] =
{ UCMD_DEF( impact_position[0] ) }, { UCMD_DEF( impact_position[0] ) },
{ UCMD_DEF( impact_position[1] ) }, { UCMD_DEF( impact_position[1] ) },
{ UCMD_DEF( impact_position[2] ) }, { UCMD_DEF( impact_position[2] ) },
{ NULL },
}; };
static const delta_field_t pm_fields[] = static const delta_field_t pm_fields[] =
@@ -104,6 +107,7 @@ static const delta_field_t pm_fields[] =
{ PHYS_DEF( skydir_y ) }, { PHYS_DEF( skydir_y ) },
{ PHYS_DEF( skydir_z ) }, { PHYS_DEF( skydir_z ) },
{ PHYS_DEF( skyangle ) }, { PHYS_DEF( skyangle ) },
{ NULL },
}; };
static const delta_field_t ev_fields[] = static const delta_field_t ev_fields[] =
@@ -126,6 +130,7 @@ static const delta_field_t ev_fields[] =
{ EVNT_DEF( iparam2 ) }, { EVNT_DEF( iparam2 ) },
{ EVNT_DEF( bparam1 ) }, { EVNT_DEF( bparam1 ) },
{ EVNT_DEF( bparam2 ) }, { EVNT_DEF( bparam2 ) },
{ NULL },
}; };
static const delta_field_t wd_fields[] = static const delta_field_t wd_fields[] =
@@ -152,6 +157,7 @@ static const delta_field_t wd_fields[] =
{ WPDT_DEF( fuser2 ) }, { WPDT_DEF( fuser2 ) },
{ WPDT_DEF( fuser3 ) }, { WPDT_DEF( fuser3 ) },
{ WPDT_DEF( fuser4 ) }, { WPDT_DEF( fuser4 ) },
{ NULL },
}; };
static const delta_field_t cd_fields[] = static const delta_field_t cd_fields[] =
@@ -212,6 +218,7 @@ static const delta_field_t cd_fields[] =
{ CLDT_DEF( vuser4[0] ) }, { CLDT_DEF( vuser4[0] ) },
{ CLDT_DEF( vuser4[1] ) }, { CLDT_DEF( vuser4[1] ) },
{ CLDT_DEF( vuser4[2] ) }, { CLDT_DEF( vuser4[2] ) },
{ NULL },
}; };
static const delta_field_t ent_fields[] = static const delta_field_t ent_fields[] =
@@ -307,6 +314,7 @@ static const delta_field_t ent_fields[] =
{ ENTS_DEF( vuser4[0] ) }, { ENTS_DEF( vuser4[0] ) },
{ ENTS_DEF( vuser4[1] ) }, { ENTS_DEF( vuser4[1] ) },
{ ENTS_DEF( vuser4[2] ) }, { ENTS_DEF( vuser4[2] ) },
{ NULL },
}; };
static const delta_field_t meta_fields[] = static const delta_field_t meta_fields[] =
@@ -318,6 +326,7 @@ static const delta_field_t meta_fields[] =
{ DESC_DEF( significant_bits ), }, { DESC_DEF( significant_bits ), },
{ DESC_DEF( premultiply ), }, { DESC_DEF( premultiply ), },
{ DESC_DEF( postmultiply ), }, { DESC_DEF( postmultiply ), },
{ NULL },
}; };
#if XASH_ENGINE_TESTS #if XASH_ENGINE_TESTS
@@ -353,22 +362,24 @@ static const delta_field_t test_fields[] =
{ TEST_DEF( dt_short_unsigned ) }, { TEST_DEF( dt_short_unsigned ) },
{ TEST_DEF( dt_byte_signed ) }, { TEST_DEF( dt_byte_signed ) },
{ TEST_DEF( dt_byte_unsigned ) }, { TEST_DEF( dt_byte_unsigned ) },
{ NULL },
}; };
#endif #endif
static delta_info_t dt_info[] = static delta_info_t dt_info[] =
{ {
[DT_EVENT_T] = { "event_t", ev_fields, ARRAYSIZE( ev_fields ) }, [DT_EVENT_T] = { "event_t", ev_fields, NUM_FIELDS( ev_fields ) },
[DT_MOVEVARS_T] = { "movevars_t", pm_fields, ARRAYSIZE( pm_fields ) }, [DT_MOVEVARS_T] = { "movevars_t", pm_fields, NUM_FIELDS( pm_fields ) },
[DT_USERCMD_T] = { "usercmd_t", cmd_fields, ARRAYSIZE( cmd_fields ) }, [DT_USERCMD_T] = { "usercmd_t", cmd_fields, NUM_FIELDS( cmd_fields ) },
[DT_CLIENTDATA_T] = { "clientdata_t", cd_fields, ARRAYSIZE( cd_fields ) }, [DT_CLIENTDATA_T] = { "clientdata_t", cd_fields, NUM_FIELDS( cd_fields ) },
[DT_WEAPONDATA_T] = { "weapon_data_t", wd_fields, ARRAYSIZE( wd_fields ) }, [DT_WEAPONDATA_T] = { "weapon_data_t", wd_fields, NUM_FIELDS( wd_fields ) },
[DT_ENTITY_STATE_T] = { "entity_state_t", ent_fields, ARRAYSIZE( ent_fields ) }, [DT_ENTITY_STATE_T] = { "entity_state_t", ent_fields, NUM_FIELDS( ent_fields ) },
[DT_ENTITY_STATE_PLAYER_T] = { "entity_state_player_t", ent_fields, ARRAYSIZE( ent_fields ) }, [DT_ENTITY_STATE_PLAYER_T] = { "entity_state_player_t", ent_fields, NUM_FIELDS( ent_fields ) },
[DT_CUSTOM_ENTITY_STATE_T] = { "custom_entity_state_t", ent_fields, ARRAYSIZE( ent_fields ) }, [DT_CUSTOM_ENTITY_STATE_T] = { "custom_entity_state_t", ent_fields, NUM_FIELDS( ent_fields ) },
#if XASH_ENGINE_TESTS #if XASH_ENGINE_TESTS
[DT_DELTA_TEST_STRUCT_T] = { "delta_test_struct_t", test_fields, ARRAYSIZE( test_fields ) }, [DT_DELTA_TEST_STRUCT_T] = { "delta_test_struct_t", test_fields, NUM_FIELDS( test_fields ) },
#endif #endif
[DT_STRUCT_COUNT] = { NULL },
}; };
// meta description is special, it cannot be overriden // meta description is special, it cannot be overriden
@@ -376,9 +387,9 @@ static const delta_info_t dt_goldsrc_meta =
{ {
.pName = "goldsrc_delta_t", .pName = "goldsrc_delta_t",
.pInfo = meta_fields, .pInfo = meta_fields,
.maxFields = ARRAYSIZE( meta_fields ), .maxFields = NUM_FIELDS( meta_fields ),
.numFields = ARRAYSIZE( meta_fields ), .numFields = NUM_FIELDS( meta_fields ),
.pFields = (delta_t[ARRAYSIZE( meta_fields )]) .pFields = (delta_t[NUM_FIELDS( meta_fields )])
{ {
{ {
DESC_DEF( fieldType ), DESC_DEF( fieldType ),
@@ -440,7 +451,7 @@ static delta_info_t *Delta_FindStruct( const char *name )
if( !COM_CheckString( name )) if( !COM_CheckString( name ))
return NULL; return NULL;
for( i = 0; i < ARRAYSIZE( dt_info ); i++ ) for( i = 0; i < NUM_FIELDS( dt_info ); i++ )
{ {
if( !Q_stricmp( dt_info[i].pName, name )) if( !Q_stricmp( dt_info[i].pName, name ))
return &dt_info[i]; return &dt_info[i];
@@ -454,7 +465,7 @@ static delta_info_t *Delta_FindStruct( const char *name )
static int Delta_NumTables( void ) static int Delta_NumTables( void )
{ {
return ARRAYSIZE( dt_info ); return NUM_FIELDS( dt_info );
} }
static delta_info_t *Delta_FindStructByIndex( int index ) static delta_info_t *Delta_FindStructByIndex( int index )
@@ -469,7 +480,7 @@ static delta_info_t *Delta_FindStructByEncoder( const char *encoderName )
if( !COM_CheckString( encoderName ) ) if( !COM_CheckString( encoderName ) )
return NULL; return NULL;
for( i = 0; i < ARRAYSIZE( dt_info ); i++ ) for( i = 0; i < NUM_FIELDS( dt_info ); i++ )
{ {
if( !Q_stricmp( dt_info[i].funcName, encoderName )) if( !Q_stricmp( dt_info[i].funcName, encoderName ))
return &dt_info[i]; return &dt_info[i];
@@ -484,7 +495,7 @@ static delta_info_t *Delta_FindStructByDelta( const delta_t *pFields )
if( !pFields ) return NULL; if( !pFields ) return NULL;
for( i = 0; i < ARRAYSIZE( dt_info ); i++ ) for( i = 0; i < NUM_FIELDS( dt_info ); i++ )
{ {
if( dt_info[i].pFields == pFields ) if( dt_info[i].pFields == pFields )
return &dt_info[i]; return &dt_info[i];
@@ -507,32 +518,29 @@ static void Delta_CustomEncode( delta_info_t *dt, const void *from, const void *
dt->userCallback( dt->pFields, from, to ); dt->userCallback( dt->pFields, from, to );
} }
static const delta_field_t *Delta_FindFieldInfo( const delta_field_t *pInfo, const char *fieldName, int maxFields ) static delta_field_t *Delta_FindFieldInfo( const delta_field_t *pInfo, const char *fieldName )
{ {
int i;
if( !fieldName || !*fieldName ) if( !fieldName || !*fieldName )
return NULL; return NULL;
for( i = 0; i < maxFields; i++ ) for( ; pInfo->name; pInfo++ )
{ {
if( !Q_strcmp( pInfo[i].name, fieldName )) if( !Q_strcmp( pInfo->name, fieldName ))
return &pInfo[i]; return (delta_field_t *)pInfo;
} }
return NULL; return NULL;
} }
static int Delta_IndexForFieldInfo( const delta_field_t *pInfo, const char *fieldName, int maxFields ) static int Delta_IndexForFieldInfo( const delta_field_t *pInfo, const char *fieldName )
{ {
int i; int i;
if( !fieldName || !*fieldName ) if( !fieldName || !*fieldName )
return -1; return -1;
for( i = 0; i < maxFields; i++ ) for( i = 0; pInfo->name; i++, pInfo++ )
{ {
if( !Q_strcmp( pInfo[i].name, fieldName )) if( !Q_strcmp( pInfo->name, fieldName ))
return i; return i;
} }
return -1; return -1;
@@ -540,7 +548,7 @@ static int Delta_IndexForFieldInfo( const delta_field_t *pInfo, const char *fiel
static qboolean Delta_AddField( delta_info_t *dt, const char *pName, int flags, int bits, float mul, float post_mul ) static qboolean Delta_AddField( delta_info_t *dt, const char *pName, int flags, int bits, float mul, float post_mul )
{ {
const delta_field_t *pFieldInfo; delta_field_t *pFieldInfo;
delta_t *pField; delta_t *pField;
int i; int i;
@@ -559,7 +567,7 @@ static qboolean Delta_AddField( delta_info_t *dt, const char *pName, int flags,
} }
// find field description // find field description
pFieldInfo = Delta_FindFieldInfo( dt->pInfo, pName, dt->maxFields ); pFieldInfo = Delta_FindFieldInfo( dt->pInfo, pName );
if( !pFieldInfo ) if( !pFieldInfo )
{ {
Con_DPrintf( S_ERROR "%s: couldn't find description for %s->%s\n", __func__, dt->pName, pName ); Con_DPrintf( S_ERROR "%s: couldn't find description for %s->%s\n", __func__, dt->pName, pName );
@@ -602,7 +610,7 @@ static void Delta_WriteTableField( sizebuf_t *msg, int tableIndex, const delta_t
dt = Delta_FindStructByIndex( tableIndex ); dt = Delta_FindStructByIndex( tableIndex );
Assert( dt && dt->bInitialized ); Assert( dt && dt->bInitialized );
nameIndex = Delta_IndexForFieldInfo( dt->pInfo, pField->name, dt->maxFields ); nameIndex = Delta_IndexForFieldInfo( dt->pInfo, pField->name );
Assert( nameIndex >= 0 && nameIndex < dt->maxFields ); Assert( nameIndex >= 0 && nameIndex < dt->maxFields );
MSG_BeginServerCmd( msg, svc_deltatable ); MSG_BeginServerCmd( msg, svc_deltatable );
@@ -673,10 +681,10 @@ void Delta_ParseTableField( sizebuf_t *msg )
Delta_AddField( dt, pName, flags, bits, mul, post_mul ); Delta_AddField( dt, pName, flags, bits, mul, post_mul );
} }
static qboolean Delta_ParseField( char **delta_script, const delta_info_t *dt, delta_t *pField, qboolean bPost ) static qboolean Delta_ParseField( char **delta_script, const delta_field_t *pInfo, delta_t *pField, qboolean bPost )
{ {
const delta_field_t *pFieldInfo;
string token; string token;
delta_field_t *pFieldInfo;
char *oldpos; char *oldpos;
*delta_script = COM_ParseFile( *delta_script, token, sizeof( token )); *delta_script = COM_ParseFile( *delta_script, token, sizeof( token ));
@@ -693,7 +701,7 @@ static qboolean Delta_ParseField( char **delta_script, const delta_info_t *dt, d
return false; return false;
} }
pFieldInfo = Delta_FindFieldInfo( dt->pInfo, token, dt->maxFields ); pFieldInfo = Delta_FindFieldInfo( pInfo, token );
if( !pFieldInfo ) if( !pFieldInfo )
{ {
Con_DPrintf( S_ERROR "%s: unable to find field %s\n", __func__, token ); Con_DPrintf( S_ERROR "%s: unable to find field %s\n", __func__, token );
@@ -817,11 +825,13 @@ static void Delta_ParseTable( char **delta_script, delta_info_t *dt, const char
{ {
string token; string token;
delta_t *pField; delta_t *pField;
const delta_field_t *pInfo;
// allocate the delta-structures // allocate the delta-structures
if( !dt->pFields ) dt->pFields = (delta_t *)Z_Calloc( dt->maxFields * sizeof( delta_t )); if( !dt->pFields ) dt->pFields = (delta_t *)Z_Calloc( dt->maxFields * sizeof( delta_t ));
pField = dt->pFields; pField = dt->pFields;
pInfo = dt->pInfo;
dt->numFields = 0; dt->numFields = 0;
// assume we have handled '{' // assume we have handled '{'
@@ -831,12 +841,12 @@ static void Delta_ParseTable( char **delta_script, delta_info_t *dt, const char
if( !Q_strcmp( token, "DEFINE_DELTA" )) if( !Q_strcmp( token, "DEFINE_DELTA" ))
{ {
if( Delta_ParseField( delta_script, dt, &pField[dt->numFields], false )) if( Delta_ParseField( delta_script, pInfo, &pField[dt->numFields], false ))
dt->numFields++; dt->numFields++;
} }
else if( !Q_strcmp( token, "DEFINE_DELTA_POST" )) else if( !Q_strcmp( token, "DEFINE_DELTA_POST" ))
{ {
if( Delta_ParseField( delta_script, dt, &pField[dt->numFields], true )) if( Delta_ParseField( delta_script, pInfo, &pField[dt->numFields], true ))
dt->numFields++; dt->numFields++;
} }
else if( token[0] == '}' ) else if( token[0] == '}' )
@@ -953,7 +963,7 @@ void Delta_Init( void )
Delta_AddField( dt, "skyvec_z", DT_FLOAT|DT_SIGNED, 16, 32.0f, 1.0f ); Delta_AddField( dt, "skyvec_z", DT_FLOAT|DT_SIGNED, 16, 32.0f, 1.0f );
Delta_AddField( dt, "wateralpha", DT_FLOAT|DT_SIGNED, 16, 32.0f, 1.0f ); Delta_AddField( dt, "wateralpha", DT_FLOAT|DT_SIGNED, 16, 32.0f, 1.0f );
Delta_AddField( dt, "fog_settings", DT_INTEGER, 32, 1.0f, 1.0f ); Delta_AddField( dt, "fog_settings", DT_INTEGER, 32, 1.0f, 1.0f );
dt->numFields = ARRAYSIZE( pm_fields ) - 4; dt->numFields = NUM_FIELDS( pm_fields ) - 4;
// now done // now done
dt->bInitialized = true; dt->bInitialized = true;
@@ -966,7 +976,7 @@ void Delta_InitClient( void )
// already initalized // already initalized
if( delta_init ) return; if( delta_init ) return;
for( i = 0; i < ARRAYSIZE( dt_info ); i++ ) for( i = 0; i < NUM_FIELDS( dt_info ); i++ )
{ {
if( dt_info[i].numFields > 0 ) if( dt_info[i].numFields > 0 )
{ {
@@ -984,7 +994,7 @@ void Delta_Shutdown( void )
if( !delta_init ) return; if( !delta_init ) return;
for( i = 0; i < ARRAYSIZE( dt_info ); i++ ) for( i = 0; i < NUM_FIELDS( dt_info ); i++ )
{ {
dt_info[i].numFields = 0; dt_info[i].numFields = 0;
dt_info[i].customEncode = CUSTOM_NONE; dt_info[i].customEncode = CUSTOM_NONE;
@@ -2282,6 +2292,10 @@ void Test_RunDelta( void )
char buffer[4096] = { 0 }; char buffer[4096] = { 0 };
const double timebase = 123.123; const double timebase = 123.123;
// a1ba: netbuffer bitmasks are initialized in netchan for some reason
// initialize it ourselves just in case
MSG_InitMasks(); // initialize bit-masks
Delta_AddField( dt, "dt_string", DT_STRING, 1, 1.0f, 1.0f ); Delta_AddField( dt, "dt_string", DT_STRING, 1, 1.0f, 1.0f );
Delta_AddField( dt, "dt_timewindow_big", DT_TIMEWINDOW_BIG, 24, 1000.f, 1.0f ); Delta_AddField( dt, "dt_timewindow_big", DT_TIMEWINDOW_BIG, 24, 1000.f, 1.0f );
Delta_AddField( dt, "dt_timewindow_8", DT_TIMEWINDOW_8, 8, 1.0f, 1.0f ); Delta_AddField( dt, "dt_timewindow_8", DT_TIMEWINDOW_8, 8, 1.0f, 1.0f );
+1
View File
@@ -46,6 +46,7 @@ enum
#if XASH_ENGINE_TESTS #if XASH_ENGINE_TESTS
DT_DELTA_TEST_STRUCT_T, DT_DELTA_TEST_STRUCT_T,
#endif #endif
DT_STRUCT_COUNT
}; };
// struct info (filled by engine) // struct info (filled by engine)
+4 -7
View File
@@ -326,7 +326,7 @@ static int HTTP_FileConnect( httpfile_t *file )
if( !COM_CheckStringEmpty( http_useragent.string ) || !Q_strcmp( http_useragent.string, "xash3d" )) if( !COM_CheckStringEmpty( http_useragent.string ) || !Q_strcmp( http_useragent.string, "xash3d" ))
{ {
Q_snprintf( useragent, sizeof( useragent ), "%s/%s (%s-%s; build %d; %s)", Q_snprintf( useragent, sizeof( useragent ), "%s/%s (%s-%s; build %d; %s)",
XASH_ENGINE_NAME, XASH_VERSION, Q_buildos( ), Q_buildarch( ), Q_buildnum( ), g_buildcommit ); XASH_ENGINE_NAME, XASH_VERSION, Q_buildos( ), Q_buildarch( ), Q_buildnum( ), Q_buildcommit( ));
} }
else Q_strncpy( useragent, http_useragent.string, sizeof( useragent )); else Q_strncpy( useragent, http_useragent.string, sizeof( useragent ));
@@ -505,14 +505,11 @@ static int HTTP_FileDecompress( httpfile_t *file )
if( zlib_result == Z_OK || zlib_result == Z_STREAM_END ) if( zlib_result == Z_OK || zlib_result == Z_STREAM_END )
{ {
g_fsapi.WriteFile( name, data_out, decompressed_len ); Mem_Free( data_in );
HTTP_FreeFile( file, false );
} }
else HTTP_FreeFile( file, true );
Mem_Free( data_in );
Mem_Free( data_out );
g_fsapi.WriteFile( name, data_out, decompressed_len );
HTTP_FreeFile( file, false );
return 1; return 1;
} }
+78 -68
View File
@@ -151,24 +151,17 @@ static inline qboolean NET_IsSocketValid( int socket )
void NET_NetadrToIP6Bytes( uint8_t *ip6, const netadr_t *adr ) void NET_NetadrToIP6Bytes( uint8_t *ip6, const netadr_t *adr )
{ {
memcpy( &ip6[0], adr->ip6_0, 2 ); memcpy( ip6, adr->ip6, sizeof( adr->ip6 ));
memcpy( &ip6[2], adr->ip6_1, 14 );
} }
void NET_IP6BytesToNetadr( netadr_t *adr, const uint8_t *ip6 ) void NET_IP6BytesToNetadr( netadr_t *adr, const uint8_t *ip6 )
{ {
memcpy( adr->ip6_0, &ip6[0], 2 ); memcpy( adr->ip6, ip6, sizeof( adr->ip6 ));
memcpy( adr->ip6_1, &ip6[2], 14 );
} }
static int NET_NetadrIP6Compare( const netadr_t *a, const netadr_t *b ) static int NET_NetadrIP6Compare( const netadr_t *a, const netadr_t *b )
{ {
uint8_t ip6_a[16], ip6_b[16]; return memcmp( a->ip6, b->ip6, sizeof( a->ip6 ));
NET_NetadrToIP6Bytes( ip6_a, a );
NET_NetadrToIP6Bytes( ip6_b, b );
return memcmp( ip6_a, ip6_b, sizeof( ip6_a ));
} }
/* /*
@@ -178,29 +171,27 @@ NET_NetadrToSockadr
*/ */
static void NET_NetadrToSockadr( netadr_t *a, struct sockaddr_storage *s ) static void NET_NetadrToSockadr( netadr_t *a, struct sockaddr_storage *s )
{ {
netadrtype_t type = NET_NetadrType( a );
memset( s, 0, sizeof( *s )); memset( s, 0, sizeof( *s ));
if( type == NA_BROADCAST ) if( a->type == NA_BROADCAST )
{ {
s->ss_family = AF_INET; s->ss_family = AF_INET;
((struct sockaddr_in *)s)->sin_port = a->port; ((struct sockaddr_in *)s)->sin_port = a->port;
((struct sockaddr_in *)s)->sin_addr.s_addr = INADDR_BROADCAST; ((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; s->ss_family = AF_INET;
((struct sockaddr_in *)s)->sin_port = a->port; ((struct sockaddr_in *)s)->sin_port = a->port;
((struct sockaddr_in *)s)->sin_addr.s_addr = a->ip4; ((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; s->ss_family = AF_INET6;
((struct sockaddr_in6 *)s)->sin6_port = a->port; ((struct sockaddr_in6 *)s)->sin6_port = a->port;
NET_NetadrToIP6Bytes(((struct sockaddr_in6 *)s)->sin6_addr.s6_addr, a ); 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; s->ss_family = AF_INET6;
((struct sockaddr_in6 *)s)->sin6_port = a->port; ((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 ) 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->ip4 = ((struct sockaddr_in *)s)->sin_addr.s_addr;
a->port = ((struct sockaddr_in *)s)->sin_port; a->port = ((struct sockaddr_in *)s)->sin_port;
} }
else if( s->ss_family == AF_INET6 ) 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 ); NET_IP6BytesToNetadr( a, ((struct sockaddr_in6 *)s)->sin6_addr.s6_addr );
a->port = ((struct sockaddr_in6 *)s)->sin6_port; 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 // try to parse as IPv6 first
if( ParseIPv6Addr( copy, ip6, NULL, NULL )) if( ParseIPv6Addr( copy, ip6, NULL, NULL ))
{ {
NET_NetadrSetType( adr, NA_IP6 );
NET_IP6BytesToNetadr( adr, ip6 ); NET_IP6BytesToNetadr( adr, ip6 );
adr->type6 = NA_IP6;
if( !hasCIDR ) if( !hasCIDR )
*prefixlen = 128; *prefixlen = 128;
@@ -629,7 +620,7 @@ qboolean NET_StringToFilterAdr( const char *s, netadr_t *adr, uint *prefixlen )
adr->ip4 = ntohl( mask ); adr->ip4 = ntohl( mask );
} }
NET_NetadrSetType( adr, NA_IP ); adr->type = NA_IP;
} }
return true; return true;
@@ -643,11 +634,10 @@ NET_AdrToString
const char *NET_AdrToString( const netadr_t a ) const char *NET_AdrToString( const netadr_t a )
{ {
static char s[64]; static char s[64];
netadrtype_t type = NET_NetadrType( &a );
if( type == NA_LOOPBACK ) if( a.type == NA_LOOPBACK )
return "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]; uint8_t ip6[16];
@@ -671,11 +661,10 @@ NET_BaseAdrToString
const char *NET_BaseAdrToString( const netadr_t a ) const char *NET_BaseAdrToString( const netadr_t a )
{ {
static char s[64]; static char s[64];
netadrtype_t type = NET_NetadrType( &a );
if( type == NA_LOOPBACK ) if( a.type == NA_LOOPBACK )
return "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]; uint8_t ip6[16];
@@ -700,19 +689,16 @@ Compares without the port
*/ */
qboolean NET_CompareBaseAdr( const netadr_t a, const netadr_t b ) qboolean NET_CompareBaseAdr( const netadr_t a, const netadr_t b )
{ {
netadrtype_t type_a = NET_NetadrType( &a ); if( a.type6 != b.type6 )
netadrtype_t type_b = NET_NetadrType( &b );
if( type_a != type_b )
return false; return false;
if( type_a == NA_LOOPBACK ) if( a.type == NA_LOOPBACK )
return true; return true;
if( type_a == NA_IP ) if( a.type == NA_IP )
return a.ip4 == b.ip4; return a.ip4 == b.ip4;
if( type_a == NA_IP6 ) if( a.type6 == NA_IP6 )
{ {
if( !NET_NetadrIP6Compare( &a, &b )) if( !NET_NetadrIP6Compare( &a, &b ))
return true; return true;
@@ -721,6 +707,36 @@ qboolean NET_CompareBaseAdr( const netadr_t a, const netadr_t b )
return false; 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 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 ) qboolean NET_CompareAdrByMask( const netadr_t a, const netadr_t b, uint prefixlen )
{ {
netadrtype_t type_a = NET_NetadrType( &a ); if( a.type6 != b.type6 || a.type == NA_LOOPBACK )
netadrtype_t type_b = NET_NetadrType( &b );
if( type_a != type_b || type_a == NA_LOOPBACK )
return false; return false;
if( type_a == NA_IP ) if( a.type == NA_IP )
{ {
uint32_t ipa = htonl( a.ip4 ); uint32_t ipa = htonl( a.ip4 );
uint32_t ipb = htonl( b.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 ) if(( ipa & (( 0xFFFFFFFFU ) << ( 32 - prefixlen ))) == ipb )
return true; return true;
} }
else if( type_a == NA_IP6 ) else if( a.type6 == NA_IP6 )
{ {
uint16_t a_[8], b_[8]; uint16_t a_[8], b_[8];
size_t check = prefixlen / 16; size_t check = prefixlen / 16;
@@ -785,13 +798,11 @@ Check for reserved ip's
*/ */
qboolean NET_IsReservedAdr( netadr_t a ) qboolean NET_IsReservedAdr( netadr_t a )
{ {
netadrtype_t type_a = NET_NetadrType( &a ); if( a.type == NA_LOOPBACK )
if( type_a == NA_LOOPBACK )
return true; return true;
// Following checks was imported from GameNetworkingSockets library // 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 if(( a.ip[0] == 10 ) || // 10.x.x.x is reserved
( a.ip[0] == 127 ) || // 127.x.x.x ( 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]; uint8_t ip6[16];
@@ -836,23 +847,20 @@ Compare full address
*/ */
qboolean NET_CompareAdr( const netadr_t a, const netadr_t b ) qboolean NET_CompareAdr( const netadr_t a, const netadr_t b )
{ {
netadrtype_t type_a = NET_NetadrType( &a ); if( a.type6 != b.type6 )
netadrtype_t type_b = NET_NetadrType( &b );
if( type_a != type_b )
return false; return false;
if( type_a == NA_LOOPBACK ) if( a.type == NA_LOOPBACK )
return true; return true;
if( type_a == NA_IP ) if( a.type == NA_IP )
{ {
if( a.ip4 == b.ip4 && a.port == b.port ) if( a.ip4 == b.ip4 && a.port == b.port )
return true; return true;
return false; return false;
} }
if( type_a == NA_IP6 ) if( a.type6 == NA_IP6 )
{ {
if( a.port == b.port && !NET_NetadrIP6Compare( &a, &b )) if( a.port == b.port && !NET_NetadrIP6Compare( &a, &b ))
return true; return true;
@@ -875,13 +883,9 @@ int NET_CompareAdrSort( const void *_a, const void *_b )
{ {
const netadr_t *a = _a, *b = _b; const netadr_t *a = _a, *b = _b;
int porta, portb, portdiff, addrdiff; int porta, portb, portdiff, addrdiff;
netadrtype_t type_a, type_b;
type_a = NET_NetadrType( a ); if( a->type6 != b->type6 )
type_b = NET_NetadrType( b ); return bound( -1, (int)a->type6 - (int)b->type6, 1 );
if( type_a != type_b )
return bound( -1, (int)type_a - (int)type_b, 1 );
porta = ntohs( a->port ); porta = ntohs( a->port );
portb = ntohs( b->port ); portb = ntohs( b->port );
@@ -892,7 +896,7 @@ int NET_CompareAdrSort( const void *_a, const void *_b )
else else
portdiff = 0; portdiff = 0;
switch( type_a ) switch( a->type6 )
{ {
case NA_IP6: case NA_IP6:
if(( addrdiff = NET_NetadrIP6Compare( a, b ))) if(( addrdiff = NET_NetadrIP6Compare( a, b )))
@@ -900,7 +904,14 @@ int NET_CompareAdrSort( const void *_a, const void *_b )
// fallthrough // fallthrough
case NA_MULTICAST_IP6: case NA_MULTICAST_IP6:
return portdiff; 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: case NA_IP:
if(( addrdiff = memcmp( a->ip, b->ip, sizeof( a->ipx )))) if(( addrdiff = memcmp( a->ip, b->ip, sizeof( a->ipx ))))
return addrdiff; 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" )) if( !Q_stricmp( string, "localhost" ) || !Q_stricmp( string, "loopback" ))
{ {
NET_NetadrSetType( adr, NA_LOOPBACK ); adr->type = NA_LOOPBACK;
return true; 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" )) if( !Q_stricmp( string, "localhost" ) || !Q_stricmp( string, "loopback" ))
{ {
NET_NetadrSetType( adr, NA_LOOPBACK ); adr->type = NA_LOOPBACK;
return NET_EAI_OK; 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; *length = loop->msgs[i].datalen;
memset( from, 0, sizeof( *from )); memset( from, 0, sizeof( *from ));
NET_NetadrSetType( from, NA_LOOPBACK ); from->type = NA_LOOPBACK;
return true; return true;
} }
@@ -1512,7 +1523,7 @@ static int NET_SendLong( netsrc_t sock, int net_socket, const char *buf, size_t
total_sent += size; total_sent += size;
len -= size; len -= size;
packet_number++; packet_number++;
Platform_NanoSleep( 100 * 1000 ); Platform_Sleep( 1 );
} }
return total_sent; return total_sent;
@@ -1535,20 +1546,19 @@ void NET_SendPacketEx( netsrc_t sock, size_t length, const void *data, netadr_t
int ret; int ret;
struct sockaddr_storage addr = { 0 }; struct sockaddr_storage addr = { 0 };
SOCKET net_socket = 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 ); NET_SendLoopPacket( sock, length, data, to );
return; 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]; net_socket = net.ip_sockets[sock];
if( !NET_IsSocketValid( net_socket )) if( !NET_IsSocketValid( net_socket ))
return; 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]; net_socket = net.ip6_sockets[sock];
if( !NET_IsSocketValid( net_socket )) if( !NET_IsSocketValid( net_socket ))
@@ -1556,7 +1566,7 @@ void NET_SendPacketEx( netsrc_t sock, size_t length, const void *data, netadr_t
} }
else 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 ); NET_NetadrToSockadr( &to, &addr );
@@ -1572,7 +1582,7 @@ void NET_SendPacketEx( netsrc_t sock, size_t length, const void *data, netadr_t
return; return;
// some PPP links don't allow broadcasts // 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; return;
if( Host_IsDedicated( )) if( Host_IsDedicated( ))
+2 -1
View File
@@ -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_AdrToString( const netadr_t a ) RETURNS_NONNULL;
const char *NET_BaseAdrToString( const netadr_t a ) RETURNS_NONNULL; const char *NET_BaseAdrToString( const netadr_t a ) RETURNS_NONNULL;
qboolean NET_IsReservedAdr( netadr_t a ); 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_StringToAdr( const char *string, netadr_t *adr );
qboolean NET_StringToFilterAdr( const char *s, netadr_t *adr, uint *prefixlen ); 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 ); net_gai_state_t NET_StringToAdrNB( const char *string, netadr_t *adr, qboolean v6only );
@@ -79,7 +80,7 @@ void NET_NetadrToIP6Bytes( uint8_t *ip6, const netadr_t *adr );
static inline qboolean NET_IsLocalAddress( netadr_t adr ) static inline qboolean NET_IsLocalAddress( netadr_t adr )
{ {
return NET_NetadrType( &adr ) == NA_LOOPBACK; return adr.type == NA_LOOPBACK ? true : false;
} }
#if !XASH_DEDICATED #if !XASH_DEDICATED
+1 -2
View File
@@ -69,6 +69,7 @@ GNU General Public License for more details.
// bytes will be stripped by the networking channel layer // bytes will be stripped by the networking channel layer
#define NET_MAX_MESSAGE PAD_NUMBER(( NET_MAX_PAYLOAD + HEADER_BYTES ), 16 ) #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 MS_SCAN_REQUEST "1\xFF" "0.0.0.0:0\0"
#define PORT_MASTER 27010 #define PORT_MASTER 27010
@@ -213,7 +214,6 @@ typedef enum netchan_flags_e
NETCHAN_USE_MUNGE = BIT( 1 ), NETCHAN_USE_MUNGE = BIT( 1 ),
NETCHAN_USE_BZIP2 = BIT( 2 ), NETCHAN_USE_BZIP2 = BIT( 2 ),
NETCHAN_GOLDSRC = BIT( 3 ), NETCHAN_GOLDSRC = BIT( 3 ),
NETCHAN_USE_LZSS = BIT( 4 ), // mutually exclusive with bzip2
} netchan_flags_t; } netchan_flags_t;
// Network Connection Channel // Network Connection Channel
@@ -285,7 +285,6 @@ typedef struct netchan_s
qboolean split; qboolean split;
qboolean use_munge; qboolean use_munge;
qboolean use_bz2; qboolean use_bz2;
qboolean use_lzss;
qboolean gs_netchan; qboolean gs_netchan;
} netchan_t; } netchan_t;
+12 -26
View File
@@ -112,9 +112,6 @@ msurface_t *PM_RecursiveSurfCheck( model_t *mod, mnode_t *node, vec3_t p1, vec3_
int i, side; int i, side;
msurface_t *surf; msurface_t *surf;
vec3_t mid; vec3_t mid;
mnode_t *children[2];
int numsurfaces, firstsurface;
loc0: loc0:
if( node->contents < 0 ) if( node->contents < 0 )
return NULL; return NULL;
@@ -122,17 +119,15 @@ loc0:
t1 = PlaneDiff( p1, node->plane ); t1 = PlaneDiff( p1, node->plane );
t2 = PlaneDiff( p2, node->plane ); t2 = PlaneDiff( p2, node->plane );
node_children( children, node, mod );
if( t1 >= -FRAC_EPSILON && t2 >= -FRAC_EPSILON ) if( t1 >= -FRAC_EPSILON && t2 >= -FRAC_EPSILON )
{ {
node = children[0]; node = node->children[0];
goto loc0; goto loc0;
} }
if( t1 < FRAC_EPSILON && t2 < FRAC_EPSILON ) if( t1 < FRAC_EPSILON && t2 < FRAC_EPSILON )
{ {
node = children[1]; node = node->children[1];
goto loc0; goto loc0;
} }
@@ -142,15 +137,13 @@ loc0:
VectorLerp( p1, frac, p2, mid ); VectorLerp( p1, frac, p2, mid );
if(( surf = PM_RecursiveSurfCheck( mod, children[side], p1, mid )) != NULL ) if(( surf = PM_RecursiveSurfCheck( mod, node->children[side], p1, mid )) != NULL )
return surf; return surf;
// walk through real faces // walk through real faces
numsurfaces = node_numsurfaces( node, mod ); for( i = 0; i < node->numsurfaces; i++ )
firstsurface = node_firstsurface( node, mod );
for( i = 0; i < numsurfaces; i++ )
{ {
msurface_t *surf = &mod->surfaces[firstsurface + i]; msurface_t *surf = &mod->surfaces[node->firstsurface + i];
mextrasurf_t *info = surf->info; mextrasurf_t *info = surf->info;
mfacebevel_t *fb = info->bevel; mfacebevel_t *fb = info->bevel;
int j, contents; int j, contents;
@@ -179,7 +172,7 @@ loc0:
return NULL; // through the fence return NULL; // through the fence
} }
return PM_RecursiveSurfCheck( mod, children[side^1], mid, p2 ); return PM_RecursiveSurfCheck( mod, node->children[side^1], mid, p2 );
} }
/* /*
@@ -234,9 +227,6 @@ static int PM_TestLine_r( model_t *mod, mnode_t *node, vec_t p1f, vec_t p2f, con
float frac, midf; float frac, midf;
int i, r, side; int i, r, side;
vec3_t mid; vec3_t mid;
mnode_t *children[2];
int numsurfaces, firstsurface;
loc0: loc0:
if( node->contents < 0 ) if( node->contents < 0 )
{ {
@@ -252,17 +242,15 @@ loc0:
front = PlaneDiff( start, node->plane ); front = PlaneDiff( start, node->plane );
back = PlaneDiff( stop, node->plane ); back = PlaneDiff( stop, node->plane );
node_children( children, node, mod );
if( front >= -FRAC_EPSILON && back >= -FRAC_EPSILON ) if( front >= -FRAC_EPSILON && back >= -FRAC_EPSILON )
{ {
node = children[0]; node = node->children[0];
goto loc0; goto loc0;
} }
if( front < FRAC_EPSILON && back < FRAC_EPSILON ) if( front < FRAC_EPSILON && back < FRAC_EPSILON )
{ {
node = children[1]; node = node->children[1];
goto loc0; goto loc0;
} }
@@ -273,7 +261,7 @@ loc0:
VectorLerp( start, frac, stop, mid ); VectorLerp( start, frac, stop, mid );
midf = p1f + ( p2f - p1f ) * frac; midf = p1f + ( p2f - p1f ) * frac;
r = PM_TestLine_r( mod, children[side], p1f, midf, start, mid, trace ); r = PM_TestLine_r( mod, node->children[side], p1f, midf, start, mid, trace );
if( r != CONTENTS_EMPTY ) if( r != CONTENTS_EMPTY )
{ {
@@ -284,11 +272,9 @@ loc0:
} }
// walk through real faces // walk through real faces
numsurfaces = node_numsurfaces( node, mod ); for( i = 0; i < node->numsurfaces; i++ )
firstsurface = node_firstsurface( node, mod );
for( i = 0; i < numsurfaces; i++ )
{ {
msurface_t *surf = &mod->surfaces[firstsurface + i]; msurface_t *surf = &mod->surfaces[node->firstsurface + i];
mextrasurf_t *info = surf->info; mextrasurf_t *info = surf->info;
mfacebevel_t *fb = info->bevel; mfacebevel_t *fb = info->bevel;
int j, contents; int j, contents;
@@ -322,7 +308,7 @@ loc0:
return contents; return contents;
} }
return PM_TestLine_r( mod, children[!side], midf, p2f, mid, stop, trace ); return PM_TestLine_r( mod, node->children[!side], midf, p2f, mid, stop, trace );
} }
int PM_TestLineExt( playermove_t *pmove, physent_t *ents, int numents, const vec3_t start, const vec3_t end, int flags ) int PM_TestLineExt( playermove_t *pmove, physent_t *ents, int numents, const vec3_t start, const vec3_t end, int flags )
+23 -40
View File
@@ -25,7 +25,8 @@ GNU General Public License for more details.
#define PM_AllowHitBoxTrace( model, hull ) ( model && model->type == mod_studio && ( FBitSet( model->flags, STUDIO_TRACE_HITBOX ) || hull == 2 )) #define PM_AllowHitBoxTrace( model, hull ) ( model && model->type == mod_studio && ( FBitSet( model->flags, STUDIO_TRACE_HITBOX ) || hull == 2 ))
static mplane_t pm_boxplanes[6]; static mplane_t pm_boxplanes[6];
static hull_t pm_boxhull; static mclipnode_t pm_boxclipnodes[6];
static hull_t pm_boxhull;
// default hullmins // default hullmins
static const vec3_t pm_hullmins[MAX_MAP_HULLS] = static const vec3_t pm_hullmins[MAX_MAP_HULLS] =
@@ -64,15 +65,23 @@ can just be stored out and get a proper hull_t structure.
*/ */
void PM_InitBoxHull( void ) void PM_InitBoxHull( void )
{ {
int i; int i, side;
pm_boxhull.clipnodes16 = (mclipnode16_t *)box_clipnodes16; pm_boxhull.clipnodes = pm_boxclipnodes;
pm_boxhull.planes = pm_boxplanes; pm_boxhull.planes = pm_boxplanes;
pm_boxhull.firstclipnode = 0; pm_boxhull.firstclipnode = 0;
pm_boxhull.lastclipnode = 5; pm_boxhull.lastclipnode = 5;
for( i = 0; i < 6; i++ ) for( i = 0; i < 6; i++ )
{ {
pm_boxclipnodes[i].planenum = i;
side = i & 1;
pm_boxclipnodes[i].children[side] = CONTENTS_EMPTY;
if( i != 5 ) pm_boxclipnodes[i].children[side^1] = i + 1;
else pm_boxclipnodes[i].children[side^1] = CONTENTS_SOLID;
pm_boxplanes[i].type = i>>1; pm_boxplanes[i].type = i>>1;
pm_boxplanes[i].normal[i>>1] = 1.0f; pm_boxplanes[i].normal[i>>1] = 1.0f;
pm_boxplanes[i].signbits = 0; pm_boxplanes[i].signbits = 0;
@@ -97,11 +106,6 @@ static hull_t *PM_HullForBox( const vec3_t mins, const vec3_t maxs )
pm_boxplanes[4].dist = maxs[2]; pm_boxplanes[4].dist = maxs[2];
pm_boxplanes[5].dist = mins[2]; pm_boxplanes[5].dist = mins[2];
if( world.version == QBSP2_VERSION )
pm_boxhull.clipnodes32 = (mclipnode32_t *)box_clipnodes32;
else
pm_boxhull.clipnodes16 = (mclipnode16_t *)box_clipnodes16;
return &pm_boxhull; return &pm_boxhull;
} }
@@ -118,21 +122,10 @@ int GAME_EXPORT PM_HullPointContents( hull_t *hull, int num, const vec3_t p )
if( !hull || !hull->planes ) // fantom bmodels? if( !hull || !hull->planes ) // fantom bmodels?
return CONTENTS_NONE; return CONTENTS_NONE;
if( world.version == QBSP2_VERSION ) while( num >= 0 )
{ {
while( num >= 0 ) plane = &hull->planes[hull->clipnodes[num].planenum];
{ num = hull->clipnodes[num].children[PlaneDiff( p, plane ) < 0];
plane = &hull->planes[hull->clipnodes32[num].planenum];
num = hull->clipnodes32[num].children[PlaneDiff( p, plane ) < 0];
}
}
else
{
while( num >= 0 )
{
plane = &hull->planes[hull->clipnodes16[num].planenum];
num = hull->clipnodes16[num].children[PlaneDiff( p, plane ) < 0];
}
} }
return num; return num;
} }
@@ -200,7 +193,7 @@ PM_RecursiveHullCheck
*/ */
qboolean PM_RecursiveHullCheck( hull_t *hull, int num, float p1f, float p2f, vec3_t p1, vec3_t p2, pmtrace_t *trace ) qboolean PM_RecursiveHullCheck( hull_t *hull, int num, float p1f, float p2f, vec3_t p1, vec3_t p2, pmtrace_t *trace )
{ {
int children[2]; mclipnode_t *node;
mplane_t *plane; mplane_t *plane;
float t1, t2; float t1, t2;
float frac, midf; float frac, midf;
@@ -233,31 +226,21 @@ loc0:
Host_Error( "%s: bad node number %i\n", __func__, num ); Host_Error( "%s: bad node number %i\n", __func__, num );
// find the point distances // find the point distances
if( world.version == QBSP2_VERSION ) node = hull->clipnodes + num;
{ plane = hull->planes + node->planenum;
children[0] = hull->clipnodes32[num].children[0];
children[1] = hull->clipnodes32[num].children[1];
plane = hull->planes + hull->clipnodes32[num].planenum;
}
else
{
children[0] = hull->clipnodes16[num].children[0];
children[1] = hull->clipnodes16[num].children[1];
plane = hull->planes + hull->clipnodes16[num].planenum;
}
t1 = PlaneDiff( p1, plane ); t1 = PlaneDiff( p1, plane );
t2 = PlaneDiff( p2, plane ); t2 = PlaneDiff( p2, plane );
if( t1 >= 0.0f && t2 >= 0.0f ) if( t1 >= 0.0f && t2 >= 0.0f )
{ {
num = children[0]; num = node->children[0];
goto loc0; goto loc0;
} }
if( t1 < 0.0f && t2 < 0.0f ) if( t1 < 0.0f && t2 < 0.0f )
{ {
num = children[1]; num = node->children[1];
goto loc0; goto loc0;
} }
@@ -274,14 +257,14 @@ loc0:
VectorLerp( p1, frac, p2, mid ); VectorLerp( p1, frac, p2, mid );
// move up to the node // move up to the node
if( !PM_RecursiveHullCheck( hull, children[side], p1f, midf, p1, mid, trace )) if( !PM_RecursiveHullCheck( hull, node->children[side], p1f, midf, p1, mid, trace ))
return false; return false;
// this recursion can not be optimized because mid would need to be duplicated on a stack // this recursion can not be optimized because mid would need to be duplicated on a stack
if( PM_HullPointContents( hull, children[side^1], mid ) != CONTENTS_SOLID ) if( PM_HullPointContents( hull, node->children[side^1], mid ) != CONTENTS_SOLID )
{ {
// go past the node // go past the node
return PM_RecursiveHullCheck( hull, children[side^1], midf, p2f, mid, p2, trace ); return PM_RecursiveHullCheck( hull, node->children[side^1], midf, p2f, mid, p2, trace );
} }
// never got out of the solid area // never got out of the solid area
+6
View File
@@ -324,14 +324,20 @@ extern const char *const clc_strings[clc_lastmsg+1];
#define PROTOCOL_GOLDSRC_VERSION 48 #define PROTOCOL_GOLDSRC_VERSION 48
#define svc_goldsrc_version svc_changing #define svc_goldsrc_version svc_changing
#define svc_goldsrc_serverinfo svc_serverdata
#define svc_goldsrc_deltadescription svc_deltatable
#define svc_goldsrc_stopsound svc_resource #define svc_goldsrc_stopsound svc_resource
#define svc_goldsrc_damage svc_restoresound #define svc_goldsrc_damage svc_restoresound
#define svc_goldsrc_killedmonster 27 #define svc_goldsrc_killedmonster 27
#define svc_goldsrc_foundsecret 28 #define svc_goldsrc_foundsecret 28
#define svc_goldsrc_spawnstaticsound 29 #define svc_goldsrc_spawnstaticsound 29
#define svc_goldsrc_decalname svc_bspdecal #define svc_goldsrc_decalname svc_bspdecal
#define svc_goldsrc_newusermsg svc_usermessage
#define svc_goldsrc_newmovevars svc_deltamovevars
#define svc_goldsrc_sendextrainfo 54 #define svc_goldsrc_sendextrainfo 54
#define svc_goldsrc_timescale 55 #define svc_goldsrc_timescale 55
#define svc_goldsrc_sendcvarvalue svc_querycvarvalue
#define svc_goldsrc_sendcvarvalue2 svc_querycvarvalue2
#define clc_goldsrc_hltv clc_requestcvarvalue // 9 #define clc_goldsrc_hltv clc_requestcvarvalue // 9
#define clc_goldsrc_requestcvarvalue clc_requestcvarvalue2 // 10 #define clc_goldsrc_requestcvarvalue clc_requestcvarvalue2 // 10
+22 -24
View File
@@ -89,6 +89,16 @@ void Sound_Shutdown( void )
Mem_FreePool( &host.soundpool ); Mem_FreePool( &host.soundpool );
} }
static byte *Sound_Copy( size_t size )
{
byte *out;
out = Mem_Realloc( host.soundpool, sound.tempbuffer, size );
sound.tempbuffer = NULL;
return out;
}
uint GAME_EXPORT Sound_GetApproxWavePlayLen( const char *filepath ) uint GAME_EXPORT Sound_GetApproxWavePlayLen( const char *filepath )
{ {
string name; string name;
@@ -368,7 +378,6 @@ static qboolean Sound_ResampleInternal( wavdata_t *sc, int outrate, int outwidth
const int inwidth = sc->width; const int inwidth = sc->width;
const int inchannels = sc->channels; const int inchannels = sc->channels;
const int incount = sc->samples; const int incount = sc->samples;
const int insize = sc->size;
qboolean handled = false; qboolean handled = false;
double stepscale; double stepscale;
double t1, t2; double t1, t2;
@@ -422,30 +431,22 @@ static qboolean Sound_ResampleInternal( wavdata_t *sc, int outrate, int outwidth
else // upsample case, w/ interpolation else // upsample case, w/ interpolation
handled = Sound_ConvertUpsample( sc, inwidth, inchannels, incount, outwidth, outchannels, outcount, stepscale ); handled = Sound_ConvertUpsample( sc, inwidth, inchannels, incount, outwidth, outchannels, outcount, stepscale );
if( !handled ) t2 = Sys_DoubleTime();
{
// restore previously changed data
sc->rate = inrate;
sc->width = inwidth;
sc->channels = inchannels;
sc->samples = incount;
sc->size = insize;
if( handled )
{
if( t2 - t1 > 0.01f ) // critical, report to mod developer
Con_Printf( S_WARN "%s: from [%d bit %d Hz %dch] to [%d bit %d Hz %dch] (took %.3fs)\n", __func__, inwidth * 8, inrate, inchannels, outwidth * 8, outrate, outchannels, t2 - t1 );
else
Con_Reportf( "%s: from [%d bit %d Hz %dch] to [%d bit %d Hz %dch] (took %.3fs)\n", __func__, inwidth * 8, inrate, inchannels, outwidth * 8, outrate, outchannels, t2 - t1 );
}
else
Con_Printf( S_ERROR "%s: unsupported from [%d bit %d Hz %dch] to [%d bit %d Hz %dch]\n", __func__, inwidth * 8, inrate, inchannels, outwidth * 8, outrate, outchannels ); Con_Printf( S_ERROR "%s: unsupported from [%d bit %d Hz %dch] to [%d bit %d Hz %dch]\n", __func__, inwidth * 8, inrate, inchannels, outwidth * 8, outrate, outchannels );
return false;
}
t2 = Sys_DoubleTime();
sc->rate = outrate; sc->rate = outrate;
sc->width = outwidth; sc->width = outwidth;
if( t2 - t1 > 0.01f ) // critical, report to mod developer return handled;
Con_Printf( S_WARN "%s: from [%d bit %d Hz %dch] to [%d bit %d Hz %dch] (took %.3fs)\n", __func__, inwidth * 8, inrate, inchannels, outwidth * 8, outrate, outchannels, t2 - t1 );
else
Con_Reportf( "%s: from [%d bit %d Hz %dch] to [%d bit %d Hz %dch] (took %.3fs)\n", __func__, inwidth * 8, inrate, inchannels, outwidth * 8, outrate, outchannels, t2 - t1 );
return true;
} }
qboolean Sound_Process( wavdata_t **wav, int rate, int width, int channels, uint flags ) qboolean Sound_Process( wavdata_t **wav, int rate, int width, int channels, uint flags )
@@ -463,11 +464,8 @@ qboolean Sound_Process( wavdata_t **wav, int rate, int width, int channels, uint
if( result ) if( result )
{ {
snd = Mem_Realloc( host.soundpool, snd, sizeof( *snd ) + snd->size ); Mem_Free( snd->buffer ); // free original image buffer
memcpy( snd->buffer, sound.tempbuffer, snd->size ); snd->buffer = Sound_Copy( snd->size ); // unzone buffer
Mem_Free( sound.tempbuffer );
sound.tempbuffer = NULL;
} }
} }
+116 -99
View File
@@ -14,7 +14,10 @@ GNU General Public License for more details.
*/ */
#include "common.h" #include "common.h"
#if XASH_ANDROID #if XASH_WIN32
#define STDOUT_FILENO 1
#include <io.h>
#elif XASH_ANDROID
#include <android/log.h> #include <android/log.h>
#endif #endif
#include <string.h> #include <string.h>
@@ -22,23 +25,66 @@ GNU General Public License for more details.
#if XASH_IRIX #if XASH_IRIX
#include <sys/time.h> #include <sys/time.h>
#endif #endif
#include "xash3d_mathlib.h"
// do not waste precious CPU cycles on mobiles or low memory devices // do not waste precious CPU cycles on mobiles or low memory devices
#if !XASH_WIN32 && !XASH_MOBILE_PLATFORM && !XASH_LOW_MEMORY #if !XASH_WIN32 && !XASH_MOBILE_PLATFORM && !XASH_LOW_MEMORY
#define XASH_COLORIZE_CONSOLE 1 #define XASH_COLORIZE_CONSOLE true
// use with caution, running engine in Qt Creator may cause a freeze in read() call
// I have never encountered this bug anywhere else, so still enable by default
#define XASH_USE_SELECT 1
#else #else
#define XASH_COLORIZE_CONSOLE 0 #define XASH_COLORIZE_CONSOLE false
#endif #endif
static struct logdata_s { #if XASH_USE_SELECT
char title[64]; // non-blocking console input
qboolean log_active; #include <sys/select.h>
qboolean log_time; #endif
char log_path[MAX_SYSPATH];
FILE *logfile; typedef struct {
int logfileno; char title[64];
} s_ld; qboolean log_active;
char log_path[MAX_SYSPATH];
FILE *logfile;
int logfileno;
} LogData;
static LogData s_ld;
char *Sys_Input( void )
{
#if XASH_USE_SELECT
if( Host_IsDedicated( ))
{
fd_set rfds;
static char line[1024];
static int len;
struct timeval tv;
tv.tv_sec = 0;
tv.tv_usec = 0;
FD_ZERO( &rfds );
FD_SET( 0, &rfds); // stdin
while( select( 1, &rfds, NULL, NULL, &tv ) > 0 )
{
if( read( 0, &line[len], 1 ) != 1 )
break;
if( line[len] == '\n' || len > 1022 )
{
line[ ++len ] = 0;
len = 0;
return line;
}
len++;
tv.tv_sec = 0;
tv.tv_usec = 0;
}
}
#endif
#if XASH_WIN32
return Wcon_Input();
#endif
return NULL;
}
void Sys_DestroyConsole( void ) void Sys_DestroyConsole( void )
{ {
@@ -77,19 +123,14 @@ static void Sys_FlushLogfile( void )
void Sys_InitLog( 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; 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 ) if( host.change_game && host.type != HOST_DEDICATED )
mode = "a"; mode = "a";
else mode = "w"; else mode = "w";
@@ -105,7 +146,7 @@ void Sys_InitLog( void )
if ( !s_ld.logfile ) 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; return;
} }
@@ -113,48 +154,48 @@ void Sys_InitLog( void )
// fit to 80 columns for easier read on standard terminal // fit to 80 columns for easier read on standard terminal
fputs( "================================================================================\n", s_ld.logfile ); fputs( "================================================================================\n", s_ld.logfile );
fprintf( s_ld.logfile, "%s (%i, %s, %s, %s-%s)\n", s_ld.title, Q_buildnum(), g_buildcommit, g_buildbranch, Q_buildos(), Q_buildarch()); fprintf( s_ld.logfile, "%s (%i, %s, %s, %s-%s)\n", s_ld.title, Q_buildnum(), Q_buildcommit(), Q_buildbranch(), Q_buildos(), Q_buildarch());
fprintf( s_ld.logfile, "Game started at %s\n", Q_timestamp( TIME_FULL )); fprintf( s_ld.logfile, "Game started at %s\n", Q_timestamp( TIME_FULL ));
fputs( "================================================================================\n", s_ld.logfile ); fputs( "================================================================================\n", s_ld.logfile );
fflush( s_ld.logfile ); fflush( s_ld.logfile );
} }
} }
void Sys_CloseLog( const char *finalmsg ) void Sys_CloseLog( void )
{ {
Sys_FlushStdout(); // flush to stdout to ensure all data was written char event_name[64];
if( !s_ld.logfile )
return;
// continue logged // continue logged
if( !finalmsg ) switch( host.status )
{ {
switch( host.status ) case HOST_CRASHED:
{ Q_strncpy( event_name, "crashed", sizeof( event_name ));
case HOST_CRASHED: break;
finalmsg = "crashed"; case HOST_ERR_FATAL:
break; Q_strncpy( event_name, "stopped with error", sizeof( event_name ));
case HOST_ERR_FATAL: break;
finalmsg = "stopped with error"; default:
break; if( !host.change_game ) Q_strncpy( event_name, "stopped", sizeof( event_name ));
default: else Q_strncpy( event_name, host.finalmsg, sizeof( event_name ));
finalmsg = "stopped"; break;
break;
}
} }
fputc( '\n', s_ld.logfile ); Sys_FlushStdout(); // flush to stdout to ensure all data was written
fputs( "================================================================================\n", s_ld.logfile );
fprintf( s_ld.logfile, "%s (%i, %s, %s, %s-%s)\n", s_ld.title, Q_buildnum(), g_buildcommit, g_buildbranch, Q_buildos(), Q_buildarch()); if( s_ld.logfile )
fprintf( s_ld.logfile, "Stopped with reason \"%s\" at %s\n", finalmsg, Q_timestamp( TIME_FULL )); {
fputs( "================================================================================\n", s_ld.logfile ); fputc( '\n', s_ld.logfile );
fclose( s_ld.logfile ); fputs( "================================================================================\n", s_ld.logfile );
s_ld.logfile = NULL; fprintf( s_ld.logfile, "%s (%i, %s, %s, %s-%s)\n", s_ld.title, Q_buildnum(), Q_buildcommit(), Q_buildbranch(), Q_buildos(), Q_buildarch());
fprintf( s_ld.logfile, "Stopped with reason \"%s\" at %s\n", event_name, Q_timestamp( TIME_FULL ));
fputs( "================================================================================\n", s_ld.logfile );
fclose( s_ld.logfile );
s_ld.logfile = NULL;
}
} }
#if XASH_COLORIZE_CONSOLE #if XASH_COLORIZE_CONSOLE == true
static qboolean Sys_WriteEscapeSequenceForColorcode( int fd, int c ) static void Sys_WriteEscapeSequenceForColorcode( int fd, int c )
{ {
static const char *q3ToAnsi[ 8 ] = static const char *q3ToAnsi[ 8 ] =
{ {
@@ -169,26 +210,19 @@ static qboolean Sys_WriteEscapeSequenceForColorcode( int fd, int c )
}; };
const char *esc = q3ToAnsi[c]; const char *esc = q3ToAnsi[c];
return write( fd, esc, c == 7 ? 4 : 7 ) < 0 ? false : true; if( c == 7 )
write( fd, esc, 4 );
else write( fd, esc, 7 );
} }
#else #else
static qboolean Sys_WriteEscapeSequenceForColorcode( int fd, int c ) static void Sys_WriteEscapeSequenceForColorcode( int fd, int c ) {}
{
return true;
}
#endif #endif
static void Sys_PrintLogfile( const int fd, const char *logtime, size_t logtime_len, const char *msg, const int colorize ) static void Sys_PrintLogfile( const int fd, const char *logtime, const char *msg, const qboolean colorize )
{ {
const char *p = msg; const char *p = msg;
if( logtime_len != 0 ) write( fd, logtime, Q_strlen( logtime ) );
{
if( write( fd, logtime, logtime_len ) < 0 )
{
// not critical for us
}
}
while( p && *p ) while( p && *p )
{ {
@@ -228,7 +262,7 @@ static void Sys_PrintLogfile( const int fd, const char *logtime, size_t logtime_
Sys_WriteEscapeSequenceForColorcode( fd, 7 ); Sys_WriteEscapeSequenceForColorcode( fd, 7 );
} }
static void Sys_PrintStdout( const char *logtime, size_t logtime_len, const char *msg ) static void Sys_PrintStdout( const char *logtime, const char *msg )
{ {
#if XASH_MOBILE_PLATFORM #if XASH_MOBILE_PLATFORM
static char buf[MAX_PRINT_MSG]; static char buf[MAX_PRINT_MSG];
@@ -260,7 +294,7 @@ static void Sys_PrintStdout( const char *logtime, size_t logtime_len, const char
#endif #endif
#elif !XASH_WIN32 // Wcon does the job #elif !XASH_WIN32 // Wcon does the job
Sys_PrintLogfile( STDOUT_FILENO, logtime, logtime_len, msg, XASH_COLORIZE_CONSOLE ); Sys_PrintLogfile( STDOUT_FILENO, logtime, msg, XASH_COLORIZE_CONSOLE );
Sys_FlushStdout(); Sys_FlushStdout();
#endif #endif
} }
@@ -271,51 +305,34 @@ void Sys_PrintLog( const char *pMsg )
const struct tm *crt_tm; const struct tm *crt_tm;
char logtime[32] = ""; char logtime[32] = "";
static char lastchar; static char lastchar;
qboolean print_time = true; size_t len;
size_t len, logtime_len = 0;
if( !lastchar || lastchar == '\n' ) time( &crt_time );
{ crt_tm = localtime( &crt_time );
if( time( &crt_time ) >= 0 )
{
crt_tm = localtime( &crt_time );
if( crt_tm == NULL )
print_time = false;
}
}
else print_time = false;
if( print_time ) if( !lastchar || lastchar == '\n')
{ strftime( logtime, sizeof( logtime ), "[%H:%M:%S] ", crt_tm ); //short time
logtime_len = strftime( logtime, sizeof( logtime ), "[%H:%M:%S] ", crt_tm ); // short time
logtime_len = Q_min( logtime_len, sizeof( logtime ) - 1 ); // just in case
}
// spew to stdout // spew to stdout
Sys_PrintStdout( logtime, logtime_len, pMsg ); Sys_PrintStdout( logtime, pMsg );
len = Q_strlen( pMsg ); len = Q_strlen( pMsg );
if( !s_ld.logfile )
{
// save last char to detect when line was not ended
lastchar = len > 0 ? pMsg[len - 1] : 0;
return;
}
if( !lastchar || lastchar == '\n')
strftime( logtime, sizeof( logtime ), "[%Y:%m:%d|%H:%M:%S] ", crt_tm ); //full time
// save last char to detect when line was not ended // save last char to detect when line was not ended
lastchar = len > 0 ? pMsg[len - 1] : 0; lastchar = len > 0 ? pMsg[len - 1] : 0;
// spew to engine.log Sys_PrintLogfile( s_ld.logfileno, logtime, pMsg, false );
if( s_ld.logfile ) Sys_FlushLogfile();
{
if( s_ld.log_time && print_time )
{
logtime_len = strftime( logtime, sizeof( logtime ), "[%Y:%m:%d|%H:%M:%S] ", crt_tm ); //full time
logtime_len = Q_min( logtime_len, sizeof( logtime ) - 1 ); // just in case
}
else
{
logtime[0] = '\0';
logtime_len = 0;
}
Sys_PrintLogfile( s_ld.logfileno, logtime, logtime_len, pMsg, false );
Sys_FlushLogfile();
}
} }
/* /*
+41 -26
View File
@@ -234,12 +234,28 @@ qboolean Sys_GetIntFromCmdLine( const char* argName, int *out )
return true; return true;
} }
void Sys_SendKeyEvents( void )
{
#if XASH_WIN32
MSG msg;
while( PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE ))
{
if( !GetMessage( &msg, NULL, 0, 0 ))
Sys_Quit ();
TranslateMessage( &msg );
DispatchMessage( &msg );
}
#endif
}
//======================================================================= //=======================================================================
// DLL'S MANAGER SYSTEM // DLL'S MANAGER SYSTEM
//======================================================================= //=======================================================================
qboolean Sys_LoadLibrary( dll_info_t *dll ) qboolean Sys_LoadLibrary( dll_info_t *dll )
{ {
size_t i; const dllfunc_t *func;
string errorstring; string errorstring;
// check errors // check errors
@@ -251,8 +267,12 @@ qboolean Sys_LoadLibrary( dll_info_t *dll )
Con_Reportf( "%s: Loading %s", __func__, dll->name ); Con_Reportf( "%s: Loading %s", __func__, dll->name );
if( dll->fcts ) // lookup export table if( dll->fcts )
ClearExports( dll->fcts, dll->num_fcts ); {
// lookup export table
for( func = dll->fcts; func && func->name != NULL; func++ )
*func->func = NULL;
}
if( !dll->link ) if( !dll->link )
dll->link = COM_LoadLibrary( dll->name, false, true ); // environment pathes dll->link = COM_LoadLibrary( dll->name, false, true ); // environment pathes
@@ -265,10 +285,9 @@ qboolean Sys_LoadLibrary( dll_info_t *dll )
} }
// Get the function adresses // Get the function adresses
for( i = 0; i < dll->num_fcts; i++ ) for( func = dll->fcts; func && func->name != NULL; func++ )
{ {
const dllfunc_t *func = &dll->fcts[i]; if( !( *func->func = Sys_GetProcAddress( dll, func->name )))
if( !( *func->func = COM_GetProcAddress( dll->link, func->name )))
{ {
Q_snprintf( errorstring, sizeof( errorstring ), "Sys_LoadLibrary: %s missing or invalid function (%s)\n", dll->name, func->name ); Q_snprintf( errorstring, sizeof( errorstring ), "Sys_LoadLibrary: %s missing or invalid function (%s)\n", dll->name, func->name );
goto error; goto error;
@@ -281,11 +300,19 @@ error:
Con_Reportf( " - failed\n" ); Con_Reportf( " - failed\n" );
Sys_FreeLibrary( dll ); // trying to free Sys_FreeLibrary( dll ); // trying to free
if( dll->crash ) Sys_Error( "%s", errorstring ); if( dll->crash ) Sys_Error( "%s", errorstring );
else Con_Reportf( S_ERROR "%s", errorstring ); else Con_Reportf( S_ERROR "%s", errorstring );
return false; return false;
} }
void* Sys_GetProcAddress( dll_info_t *dll, const char* name )
{
if( !dll || !dll->link ) // invalid desc
return NULL;
return (void *)COM_GetProcAddress( dll->link, name );
}
qboolean Sys_FreeLibrary( dll_info_t *dll ) qboolean Sys_FreeLibrary( dll_info_t *dll )
{ {
// invalid desc or alredy freed // invalid desc or alredy freed
@@ -303,8 +330,6 @@ qboolean Sys_FreeLibrary( dll_info_t *dll )
COM_FreeLibrary( dll->link ); COM_FreeLibrary( dll->link );
dll->link = NULL; dll->link = NULL;
ClearExports( dll->fcts, dll->num_fcts );
return true; return true;
} }
@@ -412,7 +437,7 @@ void Sys_Error( const char *error, ... )
Sys_WaitForQuit(); Sys_WaitForQuit();
} }
Sys_Quit( "caught an error" ); Sys_Quit();
} }
#if XASH_EMSCRIPTEN #if XASH_EMSCRIPTEN
@@ -420,12 +445,6 @@ void Sys_Error( const char *error, ... )
_exit->_Exit->asm._exit->_exit _exit->_Exit->asm._exit->_exit
As we do not need atexit(), just throw hidden exception As we do not need atexit(), just throw hidden exception
*/ */
// Hey, you, making an Emscripten port!
// What if we're not supposed to use exit() on Emscripten and instead we should
// exit from the main() function? Would this fix this bug? Test this case, pls.
#error "Read the comment above"
#include <emscripten.h> #include <emscripten.h>
#define exit my_exit #define exit my_exit
void my_exit(int ret) void my_exit(int ret)
@@ -441,14 +460,10 @@ void my_exit(int ret)
Sys_Quit Sys_Quit
================ ================
*/ */
void Sys_Quit( const char *reason ) void Sys_Quit( void )
{ {
Host_ShutdownWithReason( reason ); Host_Shutdown();
#if XASH_ANDROID
Host_ExitInMain();
#else
exit( error_on_exit ); exit( error_on_exit );
#endif
} }
/* /*
@@ -539,7 +554,7 @@ but since engine will be unloaded during this call
it explicitly doesn't use internal allocation or string copy utils it explicitly doesn't use internal allocation or string copy utils
================== ==================
*/ */
qboolean Sys_NewInstance( const char *gamedir, const char *finalmsg ) qboolean Sys_NewInstance( const char *gamedir )
{ {
#if XASH_NSWITCH #if XASH_NSWITCH
char newargs[4096]; char newargs[4096];
@@ -550,7 +565,7 @@ qboolean Sys_NewInstance( const char *gamedir, const char *finalmsg )
// just restart the entire thing // just restart the entire thing
printf( "envSetNextLoad exe: `%s`\n", exe ); printf( "envSetNextLoad exe: `%s`\n", exe );
printf( "envSetNextLoad argv:\n`%s`\n", newargs ); printf( "envSetNextLoad argv:\n`%s`\n", newargs );
Host_ShutdownWithReason( finalmsg ); Host_Shutdown( );
envSetNextLoad( exe, newargs ); envSetNextLoad( exe, newargs );
exit( 0 ); exit( 0 );
#else #else
@@ -588,7 +603,7 @@ qboolean Sys_NewInstance( const char *gamedir, const char *finalmsg )
#if XASH_PSVITA #if XASH_PSVITA
// under normal circumstances it's always going to be the same path // under normal circumstances it's always going to be the same path
exe = strdup( "app0:/eboot.bin" ); exe = strdup( "app0:/eboot.bin" );
Host_ShutdownWithReason( finalmsg ); Host_Shutdown( );
sceAppMgrLoadExec( exe, newargs, NULL ); sceAppMgrLoadExec( exe, newargs, NULL );
#else #else
exelen = wai_getExecutablePath( NULL, 0, NULL ); exelen = wai_getExecutablePath( NULL, 0, NULL );
@@ -596,7 +611,7 @@ qboolean Sys_NewInstance( const char *gamedir, const char *finalmsg )
wai_getExecutablePath( exe, exelen, NULL ); wai_getExecutablePath( exe, exelen, NULL );
exe[exelen] = 0; exe[exelen] = 0;
Host_ShutdownWithReason( finalmsg ); Host_Shutdown();
execv( exe, newargs ); execv( exe, newargs );
#endif #endif
+10 -12
View File
@@ -41,15 +41,6 @@ NOTE: never change this structure because all dll descriptions in xash code
writes into struct by offsets not names writes into struct by offsets not names
======================================================================== ========================================================================
*/ */
typedef struct dll_info_s
{
const char *name; // name of library
const dllfunc_t *fcts; // list of dll exports
const size_t num_fcts;
qboolean crash; // crash if dll not found
void *link; // hinstance of loading library
} dll_info_t;
extern int error_on_exit; extern int error_on_exit;
double Sys_DoubleTime( void ); double Sys_DoubleTime( void );
char *Sys_GetClipboardData( void ); char *Sys_GetClipboardData( void );
@@ -58,15 +49,22 @@ int Sys_CheckParm( const char *parm );
void Sys_Warn( const char *format, ... ) FORMAT_CHECK( 1 ); void Sys_Warn( const char *format, ... ) FORMAT_CHECK( 1 );
void Sys_Error( const char *error, ... ) FORMAT_CHECK( 1 ); void Sys_Error( const char *error, ... ) FORMAT_CHECK( 1 );
qboolean Sys_LoadLibrary( dll_info_t *dll ); qboolean Sys_LoadLibrary( dll_info_t *dll );
void* Sys_GetProcAddress( dll_info_t *dll, const char* name );
qboolean Sys_FreeLibrary( dll_info_t *dll ); qboolean Sys_FreeLibrary( dll_info_t *dll );
void Sys_ParseCommandLine( int argc, char **argv ); void Sys_ParseCommandLine( int argc, char **argv );
void Sys_SetupCrashHandler( void );
void Sys_RestoreCrashHandler( void );
void Sys_DebugBreak( void ); void Sys_DebugBreak( void );
#define Sys_GetParmFromCmdLine( parm, out ) _Sys_GetParmFromCmdLine( parm, out, sizeof( out )) #define Sys_GetParmFromCmdLine( parm, out ) _Sys_GetParmFromCmdLine( parm, out, sizeof( out ))
qboolean _Sys_GetParmFromCmdLine( const char *parm, char *out, size_t size ); qboolean _Sys_GetParmFromCmdLine( const char *parm, char *out, size_t size );
qboolean Sys_GetIntFromCmdLine( const char *parm, int *out ); qboolean Sys_GetIntFromCmdLine( const char *parm, int *out );
void Sys_SendKeyEvents( void );
void Sys_Print( const char *pMsg ); void Sys_Print( const char *pMsg );
void Sys_Quit( const char *reason ) NORETURN; void Sys_PrintLog( const char *pMsg );
qboolean Sys_NewInstance( const char *gamedir, const char *finalmsg ); void Sys_InitLog( void );
void Sys_CloseLog( void );
void Sys_Quit( void ) NORETURN;
qboolean Sys_NewInstance( const char *gamedir );
void *Sys_GetNativeObject( const char *obj ); void *Sys_GetNativeObject( const char *obj );
// //
@@ -74,7 +72,7 @@ void *Sys_GetNativeObject( const char *obj );
// //
char *Sys_Input( void ); char *Sys_Input( void );
void Sys_DestroyConsole( void ); void Sys_DestroyConsole( void );
void Sys_CloseLog( const char *finalmsg ); void Sys_CloseLog( void );
void Sys_InitLog( void ); void Sys_InitLog( void );
void Sys_PrintLog( const char *pMsg ); void Sys_PrintLog( const char *pMsg );
int Sys_LogFileNo( void ); int Sys_LogFileNo( void );
+7 -18
View File
@@ -68,13 +68,7 @@ extern "C" {
#if defined(_MSC_VER) #if defined(_MSC_VER)
#pragma warning(pop) #pragma warning(pop)
#endif #endif
#if (_MSC_VER >= 1900)
#include <stdbool.h> #include <stdbool.h>
#else
#define bool int
#define false 0
#define true 1
#endif
static int WAI_PREFIX(getModulePath_)(HMODULE module, char* out, int capacity, int* dirname_length) static int WAI_PREFIX(getModulePath_)(HMODULE module, char* out, int capacity, int* dirname_length)
{ {
@@ -249,11 +243,6 @@ int WAI_PREFIX(getExecutablePath)(char* out, int capacity, int* dirname_length)
#endif #endif
#endif #endif
#if !defined(WAI_STRINGIZE)
#define WAI_STRINGIZE(s)
#define WAI_STRINGIZE_(s) #s
#endif
#if defined(__ANDROID__) || defined(ANDROID) #if defined(__ANDROID__) || defined(ANDROID)
#include <fcntl.h> #include <fcntl.h>
#include <sys/mman.h> #include <sys/mman.h>
@@ -276,20 +265,20 @@ int WAI_PREFIX(getModulePath)(char* out, int capacity, int* dirname_length)
for (;;) for (;;)
{ {
char buffer[128 + PATH_MAX]; char buffer[PATH_MAX < 1024 ? 1024 : PATH_MAX];
uintptr_t low, high; uint64_t low, high;
char perms[5]; char perms[5];
uint64_t offset; uint64_t offset;
uint32_t major, minor, inode; uint32_t major, minor;
char path[PATH_MAX + 1]; char path[PATH_MAX];
uint32_t inode;
if (!fgets(buffer, sizeof(buffer), maps)) if (!fgets(buffer, sizeof(buffer), maps))
break; break;
if (sscanf(buffer, "%" SCNxPTR "-%" SCNxPTR " %s %" SCNx64 " %x:%x %u %" WAI_STRINGIZE(PATH_MAX) "[^\n]\n", &low, &high, perms, &offset, &major, &minor, &inode, path) == 8) if (sscanf(buffer, "%" PRIx64 "-%" PRIx64 " %s %" PRIx64 " %x:%x %u %s\n", &low, &high, perms, &offset, &major, &minor, &inode, path) == 8)
{ {
void* _addr = WAI_RETURN_ADDRESS(); uint64_t addr = (uintptr_t)WAI_RETURN_ADDRESS();
uintptr_t addr = (uintptr_t)_addr;
if (low <= addr && addr <= high) if (low <= addr && addr <= high)
{ {
char* resolved; char* resolved;
+2 -4
View File
@@ -31,8 +31,7 @@ extern "C" {
* @param out destination buffer, optional * @param out destination buffer, optional
* @param capacity destination buffer capacity * @param capacity destination buffer capacity
* @param dirname_length optional recipient for the length of the dirname part * @param dirname_length optional recipient for the length of the dirname part
* of the path. Available only when `capacity` is large enough to retrieve the * of the path.
* path.
* *
* @return the length of the executable path on success (without a terminal NUL * @return the length of the executable path on success (without a terminal NUL
* character), otherwise `-1` * character), otherwise `-1`
@@ -53,8 +52,7 @@ int WAI_PREFIX(getExecutablePath)(char* out, int capacity, int* dirname_length);
* @param out destination buffer, optional * @param out destination buffer, optional
* @param capacity destination buffer capacity * @param capacity destination buffer capacity
* @param dirname_length optional recipient for the length of the dirname part * @param dirname_length optional recipient for the length of the dirname part
* of the path. Available only when `capacity` is large enough to retrieve the * of the path.
* path.
* *
* @return the length of the module path on success (without a terminal NUL * @return the length of the module path on success (without a terminal NUL
* character), otherwise `-1` * character), otherwise `-1`
+22 -20
View File
@@ -18,7 +18,7 @@ GNU General Public License for more details.
#include "common.h" #include "common.h"
#define MEMHEADER_SENTINEL1 0xA1BAU #define MEMHEADER_SENTINEL1 0xDEADF00DU
#define MEMHEADER_SENTINEL2 0xDFU #define MEMHEADER_SENTINEL2 0xDFU
#ifdef XASH_CUSTOM_SWAP #ifdef XASH_CUSTOM_SWAP
@@ -51,31 +51,31 @@ static void *Q_realloc( void *mem, size_t size )
#define Q_realloc realloc #define Q_realloc realloc
#endif #endif
// keep this structure as compact as possible while keeping it aligned
// on ILP32 it's 24 bytes, which is aligned to 8 byte boundary
// on LP64 it's 40 bytes, which is also aligned to 8 byte boundary
typedef struct memheader_s typedef struct memheader_s
{ {
struct memheader_s *next, *prev; // next and previous memheaders in chain belonging to pool struct memheader_s *next; // next and previous memheaders in chain belonging to pool
const char *filename; // file name and line where Mem_Alloc was called struct memheader_s *prev;
size_t size; // size of the memory after the header (excluding header and sentinel2) const char *filename; // file name and line where Mem_Alloc was called
poolhandle_t poolptr; // pool this memheader belongs to size_t size; // size of the memory after the header (excluding header and sentinel2)
uint16_t fileline; poolhandle_t poolptr; // pool this memheader belongs to
uint16_t sentinel1; // must be equal to MEMHEADER_SENTINEL1 int fileline;
#if !XASH_64BIT
uint32_t pad0; // doesn't have value, only to make Mem_Alloc return aligned addresses on ILP32
#endif
uint32_t sentinel1; // should always be MEMHEADER_SENTINEL1
// immediately followed by data, which is followed by a MEMHEADER_SENTINEL2 byte // immediately followed by data, which is followed by a MEMHEADER_SENTINEL2 byte
} memheader_t; } memheader_t;
STATIC_CHECK_SIZEOF( memheader_t, 24, 40 );
typedef struct mempool_s typedef struct mempool_s
{ {
struct memheader_s *chain; // chain of individual memory allocations struct memheader_s *chain; // chain of individual memory allocations
size_t totalsize; // total memory allocated in this pool (inside memheaders) size_t totalsize; // total memory allocated in this pool (inside memheaders)
size_t realsize; // total memory allocated in this pool (actual malloc total) size_t realsize; // total memory allocated in this pool (actual malloc total)
size_t lastchecksize; // updated each time the pool is displayed by memlist size_t lastchecksize; // updated each time the pool is displayed by memlist
const char *filename; // file name and line where Mem_AllocPool was called const char *filename; // file name and line where Mem_AllocPool was called
int fileline; int fileline;
char name[64]; // name of the pool char name[64]; // name of the pool
} mempool_t; } mempool_t;
static mempool_t *poolchain = NULL; // critical stuff static mempool_t *poolchain = NULL; // critical stuff
@@ -233,7 +233,10 @@ static void Mem_FreeBlock( memheader_t *mem, const char *filename, int fileline
void _Mem_Free( void *data, const char *filename, int fileline ) void _Mem_Free( void *data, const char *filename, int fileline )
{ {
if( data == NULL ) if( data == NULL )
{
Sys_Error( "%s: data == NULL (called at %s:%i)\n", __func__, filename, fileline );
return; return;
}
Mem_FreeBlock((memheader_t *)((byte *)data - sizeof( memheader_t )), filename, fileline ); Mem_FreeBlock((memheader_t *)((byte *)data - sizeof( memheader_t )), filename, fileline );
} }
@@ -518,5 +521,4 @@ Memory_Init
void Memory_Init( void ) void Memory_Init( void )
{ {
poolchain = NULL; // init mem chain poolchain = NULL; // init mem chain
poolcount = 0;
} }

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