Compare commits

..

4 Commits

Author SHA1 Message Date
Alibek Omarov
70a3ff531c ref_gl: fix texturelist output 2021-11-24 01:41:25 +03:00
Alibek Omarov
501ff944b9 ref_gl: add VERY basic 16-bit texture support(no mips, no rescale, no filters), as an example to ref_vk dev 2021-11-23 04:12:30 +03:00
Alibek Omarov
f16641b606 engine: imagelib: add 16-bit PNG load support 2021-11-23 04:03:07 +03:00
Alibek Omarov
f045103abb engine: imagelib: add common definitions for 16-bit images 2021-11-23 03:58:47 +03:00
267 changed files with 8429 additions and 12869 deletions

View File

@@ -1,10 +1,22 @@
task:
name: freebsd-11-amd64
freebsd_instance:
image_family: freebsd-11-4
setup_script:
- pkg update
- pkg install -y git sdl2 python
- git submodule update --init --recursive
test_script:
- ./scripts/cirrus/build_freebsd.sh dedicated
- ./scripts/cirrus/build_freebsd.sh full
task: task:
name: freebsd-12-amd64 name: freebsd-12-amd64
freebsd_instance: freebsd_instance:
image_family: freebsd-12-3 image_family: freebsd-12-2
setup_script: setup_script:
- pkg update - pkg update
- pkg install -y git sdl2 python fontconfig - pkg install -y git sdl2 python
- 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
@@ -13,22 +25,10 @@ task:
task: task:
name: freebsd-13-amd64 name: freebsd-13-amd64
freebsd_instance: freebsd_instance:
image_family: freebsd-13-1 image_family: freebsd-13-0-snap
setup_script: setup_script:
- pkg update - pkg update
- pkg install -y git sdl2 python fontconfig - pkg install -y git sdl2 python
- git submodule update --init --recursive
test_script:
- ./scripts/cirrus/build_freebsd.sh dedicated
- ./scripts/cirrus/build_freebsd.sh full
task:
name: freebsd-14-amd64
freebsd_instance:
image_family: freebsd-14-0-snap
setup_script:
- pkg update
- pkg install -y git sdl2 python fontconfig
- 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

View File

@@ -1,11 +1,6 @@
name: Build & Deploy Engine name: Build & Deploy Engine
on: [push, pull_request] on: [push, pull_request]
jobs: jobs:
# cleanup:
# runs-on: self-hosted
# steps:
# - name: Cleanup
# run: rm -rf .* || true
build: build:
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
continue-on-error: true continue-on-error: true
@@ -19,9 +14,6 @@ jobs:
- os: ubuntu-18.04 - os: ubuntu-18.04
targetos: linux targetos: linux
targetarch: i386 targetarch: i386
# - os: ubuntu-aarch64-20.04
# targetos: linux
# targetarch: aarch64
- os: ubuntu-18.04 - os: ubuntu-18.04
targetos: android targetos: android
@@ -45,6 +37,7 @@ jobs:
GH_CPU_ARCH: ${{ matrix.targetarch }} GH_CPU_ARCH: ${{ matrix.targetarch }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
ANDROID_SDK_TOOLS_VER: 4333796 ANDROID_SDK_TOOLS_VER: 4333796
ANDROID_NDK_VER: r10e
UPLOADTOOL_ISPRERELEASE: true UPLOADTOOL_ISPRERELEASE: true
steps: steps:
- name: Checkout - name: Checkout
@@ -63,10 +56,15 @@ jobs:
- name: Build engine - name: Build engine
run: bash scripts/gha/build_${{ matrix.targetos }}.sh run: bash scripts/gha/build_${{ matrix.targetos }}.sh
- name: Upload engine (prereleases) - name: Upload engine (android)
run: bash scripts/continious_upload.sh artifacts/* if: matrix.targetos == 'android'
- name: Upload engine (artifacts) run: bash scripts/continious_upload.sh xashdroid-${{ matrix.targetarch }}.apk
uses: actions/upload-artifact@v2 - name: Upload engine (motomagx)
with: if: matrix.targetos == 'motomagx'
name: artifact-${{ matrix.targetos }}-${{ matrix.targetarch }} run: bash scripts/continious_upload.sh xash3d-fwgs-magx.7z
path: artifacts/* - name: Upload engine (linux)
if: matrix.targetos == 'linux'
run: bash scripts/continious_upload.sh xash3d-fwgs-${{ matrix.targetarch }}.AppImage xashds-linux-${{ matrix.targetarch }}
- name: Upload engine (windows)
if: matrix.targetos == 'win32'
run: bash scripts/continious_upload.sh xash3d-fwgs-win32-${{ matrix.targetarch }}.7z

1
.gitignore vendored
View File

@@ -332,4 +332,3 @@ __pycache__
*.code-workspace *.code-workspace
.history/* .history/*
.cache/* .cache/*
enc_temp_folder/

17
.gitmodules vendored
View File

@@ -1,18 +1,15 @@
[submodule "mainui"] [submodule "mainui"]
path = 3rdparty/mainui path = mainui
url = https://github.com/FWGS/mainui_cpp url = https://github.com/FWGS/mainui_cpp
[submodule "ref_gl/nanogl"] [submodule "ref_gl/nanogl"]
path = 3rdparty/nanogl path = ref_gl/nanogl
url = https://github.com/FWGS/nanogl url = https://github.com/FWGS/nanogl
[submodule "ref_gl/gl-wes-v2"] [submodule "ref_gl/gl-wes-v2"]
path = 3rdparty/gl-wes-v2 path = ref_gl/gl-wes-v2
url = https://github.com/FWGS/gl-wes-v2 url = https://github.com/FWGS/gl-wes-v2
[submodule "vgui-dev"]
path = vgui-dev
url = https://github.com/FWGS/vgui-dev
[submodule "ref_gl/gl4es"] [submodule "ref_gl/gl4es"]
path = 3rdparty/gl4es/gl4es path = ref_gl/gl4es
url = https://github.com/ptitSeb/gl4es url = https://github.com/ptitSeb/gl4es
[submodule "vgui_support"]
path = 3rdparty/vgui_support
url = https://github.com/FWGS/vgui_support
[submodule "opus"]
path = 3rdparty/opus/opus
url = https://github.com/xiph/opus

35
.travis.yml Normal file
View File

@@ -0,0 +1,35 @@
language: c
compiler: gcc
sudo: false
env:
global:
- SDL_VERSION=2.0.14
git:
depth: 50
submodules: true
os: linux
arch:
- aarch64
- ppc64le
- s390x
addons:
apt:
update: true
packages:
- libx11-dev
- libxext-dev
- x11-utils
- libgl1-mesa-dev
- libasound-dev
- libstdc++6
- libfuse2
- unzip
before_script:
- sh scripts/travis/deps_common.sh
- sh scripts/travis/deps_${TRAVIS_OS_NAME}.sh
script:
- sh scripts/travis/build_${TRAVIS_OS_NAME}.sh
after_script:
- ccache --show-stats
- sh scripts/continious_upload.sh xash3d-fwgs-${ARCH}.tar.xz xashds-linux-${ARCH}

1
3rdparty/gl-wes-v2 vendored

Submodule 3rdparty/gl-wes-v2 deleted from 7f567393d4

Submodule 3rdparty/gl4es/gl4es deleted from 5c28420a38

View File

@@ -1,24 +0,0 @@
#! /usr/bin/env python
# encoding: utf-8
import os
def options(opt):
pass
def configure(conf):
if not conf.path.find_dir('gl4es') or not conf.path.find_dir('gl4es/src'):
conf.fatal('Can\'t find gl4es submodule. Run `git submodule update --init --recursive`.')
return
def build(bld):
gl4es_srcdir = bld.path.find_node('gl4es/src')
bld.stlib(source = gl4es_srcdir.ant_glob(['gl/*.c', 'gl/*/*.c', 'glx/hardext.c']),
target = 'gl4es',
features = 'c',
includes = ['gl4es/src', 'gl4es/src/gl', 'gl4es/src/glx', 'gl4es/include'],
defines = ['NOX11', 'NO_GBM', 'NO_INIT_CONSTRUCTOR', 'DEFAULT_ES=2', 'NOEGL', 'EXTERNAL_GETPROCADDRESS=GL4ES_GetProcAddress', 'NO_LOADER', 'STATICLIB'],
cflags = ['-w', '-fvisibility=hidden', '-std=gnu99'],
subsystem = bld.env.MSVC_SUBSYSTEM,
export_includes = '.')

1
3rdparty/mainui vendored

Submodule 3rdparty/mainui deleted from 14c0922af7

1
3rdparty/opus/opus vendored

Submodule 3rdparty/opus/opus deleted from 997fdf54e7

40
3rdparty/opus/wscript vendored
View File

@@ -1,40 +0,0 @@
#! /usr/bin/env python
# encoding: utf-8
import os
def options(opt):
pass
def configure(conf):
if not conf.path.find_dir('opus') or not conf.path.find_dir('opus/src'):
conf.fatal('Can\'t find opus submodule. Run `git submodule update --init --recursive`.')
return
# TODO: ARM/x86 intrinsics detection
# TODO: maybe call autotools/cmake/meson instead?
def build(bld):
sources = bld.path.ant_glob([
'opus/src/*.c',
'opus/celt/*.c',
'opus/silk/*.c',
'opus/silk/float/*.c'
], excl = [
'opus/src/repacketizer_demo.c',
'opus/src/opus_demo.c',
'opus/src/opus_compare.c',
'opus/celt/opus_custom_demo.c'
])
includes = ['opus/include/', 'opus/celt/', 'opus/silk/', 'opus/silk/float/']
defines = ['USE_ALLOCA', 'OPUS_BUILD', 'FLOAT_APPROX', 'PACKAGE_VERSION="1.3.1"', 'CUSTOM_MODES']
bld.stlib(
source = sources,
target = 'opus',
features = 'c',
includes = includes,
defines = defines,
subsystem = bld.env.MSVC_SUBSYSTEM,
export_includes = ['opus/include/']
)

Submodule 3rdparty/vgui_support deleted from 63c134f188

View File

@@ -1,17 +0,0 @@
# Bug-compatibility in Xash3D FWGS
Xash3D FWGS has special mode for games that rely on original engine bugs.
In this mode, we emulate the behaviour of selected functions that may help running mods relying on engine bugs, but enabling them by default may break majority of other games.
At this time, we only have implemented GoldSrc bug-compatibility. It can be enabled with `-bugcomp` command line switch.
## GoldSrc bug-compatibility
### Emulated bugs
* `pfnPEntityOfEntIndex` in GoldSrc returns NULL for last player due to incorrect player index comparison
### Games and mods that require this
* Counter-Strike: Condition Zero - Deleted Scenes

View File

@@ -7,5 +7,6 @@
|Counter Strike: Condition Zero |The latest steam release |Uses vgui2 library which xash3d does not support |Some work on vgui2 support was made here: https://github.com/FWGS/xash3d/tree/vinterface |Counter Strike: Condition Zero |The latest steam release |Uses vgui2 library which xash3d does not support |Some work on vgui2 support was made here: https://github.com/FWGS/xash3d/tree/vinterface
|Counter Strike: Condition Zero - Deleted scenes |The latest steam release |Uses vgui2 library which xash3d does not support |Some work on vgui2 support was made here: https://github.com/FWGS/xash3d/tree/vinterface |Counter Strike: Condition Zero - Deleted scenes |The latest steam release |Uses vgui2 library which xash3d does not support |Some work on vgui2 support was made here: https://github.com/FWGS/xash3d/tree/vinterface
|Day of Defeat |The latest steam release |Uses vgui2 library which xash3d does not support |Some work on vgui2 support was made here: https://github.com/FWGS/xash3d/tree/vinterface |Day of Defeat |The latest steam release |Uses vgui2 library which xash3d does not support |Some work on vgui2 support was made here: https://github.com/FWGS/xash3d/tree/vinterface
|Sven-Coop |5.0+ |Uses custom GoldSrc engine | |Sven-Coop |5.0+ |Uses filesystem_stdio library which xash3d does not support |filesystem_stdio replacement already was made: https://github.com/FWGS/filesystem_stdio_xash
|XDM |3.0.4.0 | |

View File

@@ -17,9 +17,7 @@ Mirrored on github - https://github.com/JoelTroch/am_src_rebirth
Mirrored on github - https://github.com/nekonomicon/BattleGrounds Mirrored on github - https://github.com/nekonomicon/BattleGrounds
## Bubblemod ## Bubblemod
Download page on official site - http://www.bubblemod.org/dl_default.php (dead link!) Download page on official site - http://www.bubblemod.org/dl_default.php
Mirrored on github - https://github.com/HLSources/BubbleMod
## Chicken Fortress ## Chicken Fortress
Official github repository - https://github.com/CKFDevPowered/CKF3Alpha Official github repository - https://github.com/CKFDevPowered/CKF3Alpha
@@ -27,11 +25,6 @@ Official github repository - https://github.com/CKFDevPowered/CKF3Alpha
## Cold Ice ## Cold Ice
Version 1.9 is available on ModDB - https://www.moddb.com/mods/cold-ice/downloads/cold-ice-sdk Version 1.9 is available on ModDB - https://www.moddb.com/mods/cold-ice/downloads/cold-ice-sdk
Version 1.9 mirrored on github - https://github.com/solidi/hl-mods/tree/master/ci
## Cold Ice Ressurection
Mirrored on github - https://github.com/solidi/hl-mods/tree/master/cir
## Cthulhu ## Cthulhu
Uploaded to github by Oleg Cherkasky - https://github.com/gunrunners-paradise/Cthulhu-HLmod-SDK Uploaded to github by Oleg Cherkasky - https://github.com/gunrunners-paradise/Cthulhu-HLmod-SDK
@@ -45,36 +38,25 @@ Official github repository - https://github.com/adslbarxatov/xash3d-for-ESHQ
Available on GamerLab - http://gamer-lab.com/eng/code_mods_goldsrc/Half-Life_2D_(Flat-Life) Available on GamerLab - http://gamer-lab.com/eng/code_mods_goldsrc/Half-Life_2D_(Flat-Life)
## Gang Wars ## Gang Wars
Mirrored on github - https://github.com/nekonomicon/gw1.45src Mirrored on github - https://github.com/hammermaps/gw1.45src
## Go-mod ## Go-mod
Versions 2.0 and 3.0, available in mod archives on ModDB - https://www.moddb.com/mods/go-mod/downloads Versions 2.0 and 3.0, available in mod archives on ModDB - https://www.moddb.com/mods/go-mod/downloads
Version 3.0, mirrored on github - https://github.com/nekonomicon/Go-mod30
## GT mod ## GT mod
Available on GamerLab - http://gamer-lab.com/eng/code_mods_goldsrc/GT_mod_(Polnie_ishodniki) Available on GamerLab - http://gamer-lab.com/eng/code_mods_goldsrc/GT_mod_(Polnie_ishodniki)
## Half-Life: Advanced Deathmatch
Mirrored on github - https://github.com/solidi/hl-mods/tree/master/hla
## Half-Life: Decay
Mirrored on github(PC Port) - https://github.com/hoaxer/Half-Life-Decay
## Half-Life: Echoes ## Half-Life: Echoes
Available on ModDB - https://www.moddb.com/mods/half-life-echoes Download link on dropbox - https://www.dropbox.com/s/s6j8gtegn10wgvj/dlls.zip?dl=1
## Half-Life: Expanded Arsenal ## Half-Life: Expanded Arsenal
Available on ModDB - https://www.moddb.com/mods/half-life-expanded-arsenal Available on ModDB - https://www.moddb.com/mods/half-life-expanded-arsenal
## Half-Life: Gravgun mod ## Half-Life: Gravgun mod
Branch **gravgun** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/gravgun Branch **gravgun** in hlsdk-xash3d - https://github.com/FWGS/hlsdk-xash3d/tree/gravgun
## Half-Life: Invasion ## Half-Life: Invasion
Official github repository - https://github.com/jlecorre/hlinvasion official github repository - https://github.com/jlecorre/hlinvasion
## Half-Life: Pong
Mirrored on github - https://github.com/solidi/hl-mods/tree/master/pong
## Half-Life: Quest Mode ## Half-Life: Quest Mode
Available on cs-mapping.com.ua - https://old.cs-mapping.com.ua/forum/showthread.php?t=38030 Available on cs-mapping.com.ua - https://old.cs-mapping.com.ua/forum/showthread.php?t=38030
@@ -110,7 +92,7 @@ Official github repository - https://github.com/desukuran/half-screwed
Version 1.3 on ModDB - https://www.moddb.com/mods/headcrab-frenzy/downloads/headcrab-frenzy-13-beta-source-code Version 1.3 on ModDB - https://www.moddb.com/mods/headcrab-frenzy/downloads/headcrab-frenzy-13-beta-source-code
## Heart of Evil ## Heart of Evil
Mirrored on github - https://github.com/nekonomicon/HeartOfEvil Available on ModDB - https://www.moddb.com/mods/heart-of-evil/downloads/heart-of-evil-dlls-source-code
## Ingram Chillin' Mod ## Ingram Chillin' Mod
Official SourceForge repository - https://sourceforge.net/projects/icm-hl/ Official SourceForge repository - https://sourceforge.net/projects/icm-hl/
@@ -173,42 +155,42 @@ Mirrored on github - https://github.com/ZXCmod/ZXCmod
# Reimplementation # Reimplementation
## Absolute Redemption ## Absolute Redemption
Branch **redempt** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/redempt Branch **redempt** in hlsdk-xash3d - https://github.com/FWGS/hlsdk-xash3d/tree/redempt
## Adrenaline Gamer ## Adrenaline Gamer
OpenAG by YaLTeR - https://github.com/YaLTeR/OpenAG OpenAG by YaLTeR - https://github.com/YaLTeR/OpenAG
## Afraid of Monsters ## Afraid of Monsters
malortie's recreation - https://github.com/malortie/hl-aom malortie's recreation - https://github.com/malortie/halflife/tree/mod-hl-aom
Branch **aom** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/aom Branch **aom** in hlsdk-xash3d - https://github.com/FWGS/hlsdk-xash3d/tree/aom
## Afraid of Monsters: Director's cut ## Afraid of Monsters: Director's cut
Reverse-engineered code, branch **aomdc** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/aomdc Reverse-engineered code, branch **aomdc** in hlsdk-xash3d - https://github.com/FWGS/hlsdk-xash3d/tree/aomdc
## Azure Sheep ## Azure Sheep
malortie's recreation - https://github.com/malortie/hl-asheep malortie's recreation - https://github.com/malortie/halflife/tree/mod-hl-asheep
Reverse-engineered code, branch **asheep** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/asheep Reverse-engineered code, branch **asheep** in hlsdk-xash3d - https://github.com/FWGS/hlsdk-xash3d/tree/asheep
## Big Lolly ## Big Lolly
malortie's recreation - https://github.com/malortie/hl-biglolly malortie's recreation - https://github.com/malortie/halflife/tree/mod-hl-biglolly
Branch **biglolly** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/biglolly Branch **biglolly** in hlsdk-xash3d - https://github.com/FWGS/hlsdk-xash3d/tree/biglolly
## Black Ops ## Black Ops
malortie's recreation - https://github.com/malortie/hl-blackops malortie's recreation - https://github.com/malortie/halflife/tree/mod-hl-blackops
Branch **blackops** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/blackops Branch **blackops** in hlsdk-xash3d - https://github.com/FWGS/hlsdk-xash3d/tree/blackops
## Bloody Pizza: Vendetta ## Bloody Pizza: Vendetta
Branch **caseclosed** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/caseclosed Branch **caseclosed** in hlsdk-xash3d - https://github.com/FWGS/hlsdk-xash3d/tree/caseclosed
## Case Closed ## Case Closed
Branch **caseclosed** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/caseclosed Branch **caseclosed** in hlsdk-xash3d - https://github.com/FWGS/hlsdk-xash3d/tree/caseclosed
## Cleaner's Adventures ## Cleaner's Adventures
Branch **CAd** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/CAd Branch **CAd** in hlsdk-xash3d - https://github.com/FWGS/hlsdk-xash3d/tree/CAd
## Counter Strike ## Counter Strike
Reverse-engineered code of client part by a1batross - https://github.com/FWGS/cs16-client/tree/v1.32 Reverse-engineered code of client part by a1batross - https://github.com/FWGS/cs16-client/tree/v1.32
@@ -224,127 +206,116 @@ CSO-like Xash3D-based mod, CSMoE - https://github.com/MoeMod/CSMoE
Recreation by lostgamer aka nillerusr - https://github.com/LostGamerHL/crack_life Recreation by lostgamer aka nillerusr - https://github.com/LostGamerHL/crack_life
## Escape from the Darkness ## Escape from the Darkness
malortie's recreation - https://github.com/malortie/hl-eftd malortie's recreation - https://github.com/malortie/halflife/tree/mod-hl-eftd
Reverse-engineered code, branch **eftd** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/eftd Reverse-engineered code, branch **eftd** in hlsdk-xash3d - https://github.com/FWGS/hlsdk-xash3d/tree/eftd
## Half-Life: Blue Shift ## Half-Life: Blue Shift
Unkle Mike's recreation - https://hlfx.ru/forum/showthread.php?s=&threadid=5253 Unkle Mike's recreation - https://hlfx.ru/forum/showthread.php?s=&threadid=5253
Reverse-engineered code, branch **bshift** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/bshift Reverse-engineered code, branch **bshift** in hlsdk-xash3d - https://github.com/FWGS/hlsdk-xash3d/tree/bshift
## Half-Life: Induction ## Half-Life: Induction
Branch **induction** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/induction Branch **induction** in hlsdk-xash3d - https://github.com/FWGS/hlsdk-xash3d/tree/induction
## Half-Life: Opposing Force ## Half-Life: Opposing Force
Recreation by lostgamer aka nillerusr - https://github.com/LostGamerHL/hlsdk-xash3d Recreation by lostgamer aka nillerusr - https://github.com/LostGamerHL/hlsdk-xash3d
Reverse-engineered code, clean branch **opfor** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/opfor Reverse-engineered code, clean branch **opfor** in hlsdk-xash3d - https://github.com/FWGS/hlsdk-xash3d/tree/opfor
Spirit of Half Life: Opposing-Force Edition - https://github.com/Hammermaps-DEV/SOHL-V1.9-Opposing-Force-Edition Spirit of Half Life: Opposing-Force Edition - https://github.com/Hammermaps-DEV/SOHL-V1.9-Opposing-Force-Edition
## Half-Life: Rebellion ## Half-Life: Rebellion
Reverse-engineered code, branch **rebellion** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/rebellion Reverse-engineered code, branch **rebellion** in hlsdk-xash3d - https://github.com/FWGS/hlsdk-xash3d/tree/rebellion
## Half-Life: Urbicide
Branch **hl_urbicide** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/hl_urbicide
## Half-Life: Visitors ## Half-Life: Visitors
malortie's recreation - https://github.com/malortie/hl-visitors malortie's recreation - https://github.com/malortie/halflife/tree/mod-hl-visitors
Reverse-engineered code, branch **visitors** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/visitors Reverse-engineered code, branch **visitors** in hlsdk-xash3d - https://github.com/FWGS/hlsdk-xash3d/tree/visitors
## Half-Secret ## Half-Secret
Branch **half-secret** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/half-secret Branch **half-secret** in hlsdk-xash3d - https://github.com/FWGS/hlsdk-xash3d/tree/half-secret
## Night at the Office ## Night at the Office
malortie's recreation - https://github.com/malortie/hl-nato malortie's recreation - https://github.com/malortie/halflife/tree/mod-hl-noffice
Branch **noffice** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/noffice Branch **noffice** in hlsdk-xash3d - https://github.com/FWGS/hlsdk-xash3d/tree/noffice
## Poke 646 ## Poke 646
malortie's recreation - https://github.com/malortie/hl-poke646 malortie's recreation - https://github.com/malortie/halflife/tree/mod-hl-poke646
Reverse-engineered code, branch **poke646** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/poke646 Reverse-engineered code, branch **poke646** in hlsdk-xash3d - https://github.com/FWGS/hlsdk-xash3d/tree/poke646
## Poke 646: Vendetta ## Poke 646: Vendetta
malortie's recreation - https://github.com/malortie/hl-poke646-vendetta malortie's recreation - https://github.com/malortie/halflife/tree/mod-hl-poke646
Reverse-engineered code, branch **poke646_vendetta** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/poke646_vendetta Reverse-engineered code, branch **poke646_vendetta** in hlsdk-xash3d - https://github.com/FWGS/hlsdk-xash3d/tree/poke646_vendetta
## Residual Life ## Residual Life
Reverse-engineered code, branch **residual_point** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/residual_point Reverse-engineered code, branch **residual_point** in hlsdk-xash3d - https://github.com/FWGS/hlsdk-xash3d/tree/residual_point
## Residual Point ## Residual Point
Reverse-engineered code, branch **residual_point** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/residual_point Reverse-engineered code, branch **residual_point** in hlsdk-xash3d - https://github.com/FWGS/hlsdk-xash3d/tree/residual_point
## Sewer Beta
Branch **sewer_beta** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/sewer_beta
## Team Fortress Classic ## Team Fortress Classic
Reverse-engineered code by Velaron - https://github.com/Velaron/tf15-client Reverse-engineered code by Velaron - https://github.com/Velaron/tf15-client
## The Gate ## The Gate
malortie's recreation - https://github.com/malortie/hl-thegate malortie's recreation - https://github.com/malortie/halflife/tree/mod-hl-TheGate
Reverse-engineered code, branch **thegate** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/thegate Reverse-engineered code, branch **thegate** in hlsdk-xash3d - https://github.com/FWGS/hlsdk-xash3d/tree/thegate
## They Hunger ## They Hunger
malortie's recreation - https://github.com/malortie/hl-theyhunger malortie's recreation - https://github.com/malortie/halflife/tree/mod-hl-Hunger
Reverse-engineered code, branch **theyhunger** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/theyhunger Reverse-engineered code, branch **theyhunger** in hlsdk-xash3d - https://github.com/FWGS/hlsdk-xash3d/tree/theyhunger
They Hunger: Tactical - https://www.moddb.com/mods/they-hunger-tactical/downloads/tht-source-code-documentation They Hunger: Tactical - https://www.moddb.com/mods/they-hunger-tactical/downloads/tht-source-code-documentation
## Times of Troubles ## Times of Troubles
malortie's recreation - https://github.com/malortie/hl-tot malortie's recreation - https://github.com/malortie/halflife/tree/mod-hl-tot
Branch **tot** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/tot Branch **tot** in hlsdk-xash3d - https://github.com/FWGS/hlsdk-xash3d/tree/tot
# Derived work # Derived work
## Adrenaline Gamer ## Adrenaline Gamer
Branch **aghl** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/aghl Branch **aghl** in hlsdk-xash3d - https://github.com/FWGS/hlsdk-xash3d/tree/aghl
## Bubblemod ## Bubblemod
Branch **bubblemod** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/bubblemod Branch **bubblemod** in hlsdk-xash3d - https://github.com/FWGS/hlsdk-xash3d/tree/bubblemod
## Deathmatch Classic ## Deathmatch Classic
Deathmatch Classic: Adrenaline Gamer Edition - https://github.com/martinwebrant/agmod/tree/master/src/dmc Deathmatch Classic: Adrenaline Gamer Edition - https://github.com/martinwebrant/agmod/tree/master/src/dmc
Deathmatch Quaked - https://www.moddb.com/games/deathmatch-classic/downloads/dmq2 Deathmatch Quaked - https://www.moddb.com/games/deathmatch-classic/downloads/dmq2
Branch **dmc** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/dmc Branch **dmc** in hlsdk-xash3d - https://github.com/FWGS/hlsdk-xash3d/tree/dmc
## Half-Life: Echoes ## Half-Life: Echoes
Branch **echoes** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/echoes Branch **echoes** in hlsdk-xash3d - https://github.com/FWGS/hlsdk-xash3d/tree/echoes
## Half-Life: Invasion ## Half-Life: Invasion
Port to HLSDK 2.4 by malortie - https://github.com/malortie/hl-invasion Port to HLSDK 2.4 by malortie - https://github.com/malortie/halflife/tree/mod-hl-invasion
Port to Linux by fmoraw - https://github.com/fmoraw/hlinvasion Port to Linux by fmoraw - https://github.com/fmoraw/hlinvasion
Branch **invasion** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/invasion
## Half-Life: Top-Down ## Half-Life: Top-Down
Branch **hltopdown** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/hltopdown Branch **hltopdown** in hlsdk-xash3d - https://github.com/FWGS/hlsdk-xash3d/tree/hltopdown
## Half-Screwed ## Half-Screwed
Branch **half-screwed** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/half-screwed Branch **half-screwed** in hlsdk-xash3d - https://github.com/FWGS/hlsdk-xash3d/tree/half-screwed
## Natural Selection ## Natural Selection
Port to Linux - https://github.com/fmoraw/NS Port to Linux - https://github.com/fmoraw/NS
## Spirit of Half-Life
Version 1.2, branch **sohl1.2** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/sohl1.2
## Swiss Cheese Halloween 2002 ## Swiss Cheese Halloween 2002
Just more playable version by malortie - https://github.com/malortie/hl-shall Just more playable version by malortie - https://github.com/malortie/halflife/tree/mod-hl-halloween
Branch **halloween** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/halloween Branch **halloween** in hlsdk-xash3d - https://github.com/FWGS/hlsdk-xash3d/tree/halloween
## Threewave CTF ## Threewave CTF
Branch **dmc** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/dmc Branch **dmc** in hlsdk-xash3d - https://github.com/FWGS/hlsdk-xash3d/tree/dmc
## Zombie-X ## Zombie-X
Branch **zombie-x** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/zombie-x Branch **zombie-x** in hlsdk-xash3d - https://github.com/FWGS/hlsdk-xash3d/tree/zombie-x

View File

@@ -15,24 +15,24 @@ Status:
Table is sorted by status. Table is sorted by status.
| Platform | Status | Maintainer | Note | Platform | Status | Maintainer | Note
| -------- | ------ | ---------- | ---- | -------- | ------ | ---------- | ----
| Windows | Supported | @a1batross, @SNMetamorph | | Windows | Supported | @a1batross |
| *BSD | Supported | @nekonomicon | | *BSD | Supported | @nekonomicon |
| GNU/Linux(x86, amd64, arm) | Supported | @a1batross, @mittorn | | GNU/Linux(x86, amd64, arm) | Supported | @a1batross, @mittorn |
| Android | Supported | @a1batross, @mittorn | | Android | Supported | @a1batross, @mittorn |
| MotoMAGX | Supported | @a1batross | | MotoMAGX | Supported | @a1batross |
| GNU/Linux(elbrus) | Supported | @a1batross, @mittorn | Rare and eventual access to e2k machine | GNU/Linux(elbrus) | Supported | @a1batross, @mittorn | Rare and eventual access to e2k machine
| Haiku | Supported | not maintained | Was added by #478 and #483 | Haiku | Supported | not maintained | Was added by #478 and #483
| DOS4GW | Supported | @mittorn | | DOS4GW | Supported | @mittorn |
| GNU/Linux(mipsel) | Supported | @mittorn | | GNU/Linux(mipsel) | Supported | @mittorn |
| Switch | In progress | @fgsfdsfgs | [GitHub Repository](https://github.com/fgsfdsfgs/xash3d-fwgs/tree/switch_new) | Switch | In progress | @fgsfdsfgs | [Github Repository](https://github.com/fgsfdsfgs/xash3d-fwgs/tree/switch_new)
| Wii | In progress | Collaborative effort | [GitHub Repository](https://github.com/saucesaft/xash3d-wii) | Wii | In progress | Collaborative effort | [Github Repository](https://github.com/saucesaft/xash3d-wii)
| PSP | In progress | @Crow_bar, @Velaron | [GitHub Repository](https://github.com/Crow-bar/xash3d-fwgs) | PSP | In progress | Collaborative effort | No sources available at this moment
| Emscripten | Old Engine | not maintained | | Emscripten | Old Engine | not maintained |
| Oculus Quest | Old Engine fork | @DrBeef | [GitHub Repository](https://github.com/DrBeef/Lambda1VR) | Oculus Quest | Old Engine fork | @DrBeef | [GitHub Repository](https://github.com/DrBeef/Lambda1VR)
| PSVita | Old Engine fork | not maintained | [GitHub Repository](https://github.com/fgsfdsfgs/vitaXash3D) | PSVita | Old Engine fork | not maintained | [GitHub Repository](https://github.com/fgsfdsfgs/vitaXash3D)
| Switch | Old Engine fork | not maintained | [GitHub Repository](https://github.com/switchports/xash3d-switch) | Switch | Old Engine fork | not maintained | [GitHub Repository](https://github.com/switchports/xash3d-switch)
| 3DS | Old Engine fork | not maintained | [GitHub Repository](https://github.com/masterfeizz/Xash3DS) | 3DS | Old Engine fork | not maintained | [GitHub Repository](https://github.com/masterfeizz/Xash3DS)
| macOS | Deprecated | not maintained | See GitHub issue #61 | macOS | Deprecated | not maintained | See GitHub issue #61
| iOS | Deprecated | not maintained | See GitHub issue #61 | iOS | Deprecated | not maintained | See GitHub issue #61

View File

@@ -46,7 +46,7 @@ For mappacks - place *.bsp files to **valve/maps** folder, *.wad files to **valv
16. [Betrayal](http://www.moddb.com/mods/betrayal) (this mod has inner bugs; set **gl_allow_mirrors** to **0** to prevent drops of game's perfomance in some areas) 16. [Betrayal](http://www.moddb.com/mods/betrayal) (this mod has inner bugs; set **gl_allow_mirrors** to **0** to prevent drops of game's perfomance in some areas)
17. [Between Two Worlds](https://www.runthinkshootlive.com/posts/between-two-worlds/) 17. [Between Two Worlds](https://www.runthinkshootlive.com/posts/between-two-worlds/)
18. [Black Mesa Energy Testing Chamber](http://twhl.info/competitions.php?results=17) 18. [Black Mesa Energy Testing Chamber](http://twhl.info/competitions.php?results=17)
19. [Black Mesa Sideline](https://www.moddb.com/mods/black-mesa-sideline) (set **gl_allow_mirrors** to **0** to prevent drops of game's perfomance in some areas) 19. [Black Mesa Sideline](http://www.isolated-design.de/half-life-mods/black-mesa-sideline/) (set **gl_allow_mirrors** to **0** to prevent drops of game's perfomance in some areas)
20. [BlackMesa 2007( Black Mesa Missions 2007 )](http://www.moddb.com/addons/blackmesa-2007) 20. [BlackMesa 2007( Black Mesa Missions 2007 )](http://www.moddb.com/addons/blackmesa-2007)
21. [Blood and Bones](https://www.runthinkshootlive.com/posts/blood-and-bones/) 21. [Blood and Bones](https://www.runthinkshootlive.com/posts/blood-and-bones/)
22. Boom (Huknenn) v1.0 & [HL Boom: Gold Edition v1.1](http://www.moddb.com/mods/boom) 22. Boom (Huknenn) v1.0 & [HL Boom: Gold Edition v1.1](http://www.moddb.com/mods/boom)
@@ -103,8 +103,8 @@ For mappacks - place *.bsp files to **valve/maps** folder, *.wad files to **valv
72. [Freeman](https://www.runthinkshootlive.com/posts/freeman/) 72. [Freeman](https://www.runthinkshootlive.com/posts/freeman/)
73. [Freeman's Escape](http://www.moddb.com/mods/freeman-escape-french) (2 maps by *JiggZ*) 73. [Freeman's Escape](http://www.moddb.com/mods/freeman-escape-french) (2 maps by *JiggZ*)
74. [Freeman's Fight](https://www.runthinkshootlive.com/posts/freemans-fight/) 74. [Freeman's Fight](https://www.runthinkshootlive.com/posts/freemans-fight/)
75. [Freeman's Return](https://www.moddb.com/games/half-life/addons/freemans-return-v12) 75. [Freeman's Return](http://jpmaps.wz.cz/epizody.htm)
76. [Freeman's Return 2](https://www.moddb.com/games/half-life/addons/freemans-return-2-v11) 76. [Freeman's Return 2](http://jpmaps.wz.cz/epizody.htm)
77. [Freeman's Revenge](https://www.runthinkshootlive.com/posts/freemans-revenge/) 77. [Freeman's Revenge](https://www.runthinkshootlive.com/posts/freemans-revenge/)
78. [Freeman's Tomb( The Crypt )](http://twhl.info/vault.php?map=3787) 78. [Freeman's Tomb( The Crypt )](http://twhl.info/vault.php?map=3787)
79. [G-Invasion v2.5](http://www.moddb.com/mods/g-man-invasion) aka G-Man Invasion (there is an inner crash bug on final titles: some text lines are too long and cannot be properly displayed) 79. [G-Invasion v2.5](http://www.moddb.com/mods/g-man-invasion) aka G-Man Invasion (there is an inner crash bug on final titles: some text lines are too long and cannot be properly displayed)
@@ -129,7 +129,7 @@ For mappacks - place *.bsp files to **valve/maps** folder, *.wad files to **valv
96. [Haunted](https://www.runthinkshootlive.com/posts/haunted/) (set **sv_validate_changelevel** to **0** to avoid a problem with level change between maps **pagan7** and **pagan8**) 96. [Haunted](https://www.runthinkshootlive.com/posts/haunted/) (set **sv_validate_changelevel** to **0** to avoid a problem with level change between maps **pagan7** and **pagan8**)
97. [Hazardous Materials: Episode 1 & 2](http://www.moddb.com/mods/half-life-hazardous-materials) 97. [Hazardous Materials: Episode 1 & 2](http://www.moddb.com/mods/half-life-hazardous-materials)
98. [Hazardous-Course 2](http://www.moddb.com/mods/hazardous-course-2) 98. [Hazardous-Course 2](http://www.moddb.com/mods/hazardous-course-2)
99. [Help Wanted](https://www.moddb.com/games/half-life/addons/help-wanted) 99. [Help Wanted](http://maps.mrsucko.org/work/)
100. [Hidden Evil v1.01](https://www.runthinkshootlive.com/posts/hidden-evil/) 100. [Hidden Evil v1.01](https://www.runthinkshootlive.com/posts/hidden-evil/)
101. [High Speed](http://www.moddb.com/games/half-life/addons/high-speed-english-version) 101. [High Speed](http://www.moddb.com/games/half-life/addons/high-speed-english-version)
102. [hlife_hotdog_compo26](http://twhl.info/vault.php?map=5181) 102. [hlife_hotdog_compo26](http://twhl.info/vault.php?map=5181)
@@ -155,7 +155,7 @@ For mappacks - place *.bsp files to **valve/maps** folder, *.wad files to **valv
122. [Mario Keys](http://www.moddb.com/mods/mario-keys) 122. [Mario Keys](http://www.moddb.com/mods/mario-keys)
123. [McBeth](https://www.runthinkshootlive.com/posts/mcbeth/) 123. [McBeth](https://www.runthinkshootlive.com/posts/mcbeth/)
124. [Medieval World](http://www.moddb.com/mods/medieval-world) 124. [Medieval World](http://www.moddb.com/mods/medieval-world)
125. [Mel Soaring 2: Star Rancor](https://www.moddb.com/addons/mel-soaring-2-star-rancor) 125. [Mel Soaring 2: Star Rancor](http://www.etherealhell.com/etherealhell/index.php/my-levels/half-life)
126. [MINIMICUS](http://twhl.info/vault.php?map=163) 126. [MINIMICUS](http://twhl.info/vault.php?map=163)
127. [Mission Failed](http://www.moddb.com/mods/mission-failed) 127. [Mission Failed](http://www.moddb.com/mods/mission-failed)
128. [Mission MC Poker](http://www.moddb.com/mods/half-life-mission-mc-poker) 128. [Mission MC Poker](http://www.moddb.com/mods/half-life-mission-mc-poker)
@@ -176,7 +176,7 @@ For mappacks - place *.bsp files to **valve/maps** folder, *.wad files to **valv
143. [Operation: Nova](http://www.moddb.com/mods/half-life-operation-nova) (there is an inner bug with an M60 machinegun on a map with Osprey: it can be activated and used if you are staying in front of it, not behind it) 143. [Operation: Nova](http://www.moddb.com/mods/half-life-operation-nova) (there is an inner bug with an M60 machinegun on a map with Osprey: it can be activated and used if you are staying in front of it, not behind it)
144. [Optimum Fear](https://www.fileplanet.com/7472/0/fileinfo/Optimum-Fear) 144. [Optimum Fear](https://www.fileplanet.com/7472/0/fileinfo/Optimum-Fear)
145. [Outrun](http://www.moddb.com/mods/outrun) 145. [Outrun](http://www.moddb.com/mods/outrun)
146. [Outwards (Day One)](https://drive.google.com/file/d/1mjQ8wUazYbwTq9Ocg0Vs0raq4avbTRne/view?usp=sharing) 146. [Outwards (Day One)](http://www.visgi.info/maps/)
147. [Overhaul Pack](http://www.moddb.com/mods/half-life-overhaul-pack) (Just HD pack for Half-Life) 147. [Overhaul Pack](http://www.moddb.com/mods/half-life-overhaul-pack) (Just HD pack for Half-Life)
148. [P.I.Z.D.E.C.](https://www.runthinkshootlive.com/posts/pizdec/) 148. [P.I.Z.D.E.C.](https://www.runthinkshootlive.com/posts/pizdec/)
149. [pagoda](http://www.moddb.com/mods/pagoda1) 149. [pagoda](http://www.moddb.com/mods/pagoda1)
@@ -184,7 +184,7 @@ For mappacks - place *.bsp files to **valve/maps** folder, *.wad files to **valv
151. [Phobos IV](http://www.moddb.com/mods/phobos-iv) 151. [Phobos IV](http://www.moddb.com/mods/phobos-iv)
152. [Pimp My Car](https://www.runthinkshootlive.com/posts/pimp-my-car/) (there is an inner issue with incorrect responses of buttons on combination locks) 152. [Pimp My Car](https://www.runthinkshootlive.com/posts/pimp-my-car/) (there is an inner issue with incorrect responses of buttons on combination locks)
153. [Point Blank Stackdeath Complex](https://www.runthinkshootlive.com/posts/half-life-point-blank-stackdeath-complex/) 153. [Point Blank Stackdeath Complex](https://www.runthinkshootlive.com/posts/half-life-point-blank-stackdeath-complex/)
154. [Prisoner Escaped](https://www.moddb.com/mods/prisoner-escaped-1-2) 154. [Prisoner Escaped](http://four0four.org/downloads/maps/)
155. [Prisoner of Event](http://wp.vondur.net/?page_id=40) 155. [Prisoner of Event](http://wp.vondur.net/?page_id=40)
156. [Prisoner of War](https://www.runthinkshootlive.com/posts/prisoner-of-war/) 156. [Prisoner of War](https://www.runthinkshootlive.com/posts/prisoner-of-war/)
157. [Project Quantum Leap](http://www.moddb.com/mods/project-quantum-leap) 157. [Project Quantum Leap](http://www.moddb.com/mods/project-quantum-leap)
@@ -282,7 +282,7 @@ For mappacks - place *.bsp files to **valve/maps** folder, *.wad files to **valv
6. [Catacombs: Part 1](https://www.runthinkshootlive.com/posts/catacombs/) 6. [Catacombs: Part 1](https://www.runthinkshootlive.com/posts/catacombs/)
7. [Cro-man's Office Mappack](http://twhl.info/vault.php?map=5547) 7. [Cro-man's Office Mappack](http://twhl.info/vault.php?map=5547)
8. [Half-Life Episode Two Demo Alpha v1.0](http://hl.loess.ru/?mod=451) 8. [Half-Life Episode Two Demo Alpha v1.0](http://hl.loess.ru/?mod=451)
9. [Hazardous-Course (first version of Hazardous-Course 2)](https://drive.google.com/file/d/16djJZSpNWKyScSxSyMqX-u_S-2i400rl/view?usp=sharing) 9. [Hazardous-Course (first version of Hazardous-Course 2)](http://www.richmans-maps.ch.vu/) (link dead!)
10. [High Tech v0.2](http://hl.loess.ru/?mod=499) 10. [High Tech v0.2](http://hl.loess.ru/?mod=499)
11. [HL Shadows, Part 1](https://www.fileplanet.com/7466/0/fileinfo/'HL-Shadows',-Part-1) 11. [HL Shadows, Part 1](https://www.fileplanet.com/7466/0/fileinfo/'HL-Shadows',-Part-1)
12. [HLNewEnd](http://twhl.info/vault.php?map=2275) 12. [HLNewEnd](http://twhl.info/vault.php?map=2275)
@@ -305,11 +305,11 @@ For mappacks - place *.bsp files to **valve/maps** folder, *.wad files to **valv
29. [Shortcut v1.0 Beta](https://www.runthinkshootlive.com/posts/shortcut/) 29. [Shortcut v1.0 Beta](https://www.runthinkshootlive.com/posts/shortcut/)
30. [Stoka](https://www.ceskemody.cz/mapy.php?lng=1&clanek=222&razeni_hra=1&pn=stoka) 30. [Stoka](https://www.ceskemody.cz/mapy.php?lng=1&clanek=222&razeni_hra=1&pn=stoka)
31. [Striker's Compo 26](http://twhl.info/vault.php?map=5190) (buggy) 31. [Striker's Compo 26](http://twhl.info/vault.php?map=5190) (buggy)
32. [Technology Test 2](https://drive.google.com/file/d/1LfldzsMIN5j07bgtNkfY5v0Xl0S9de_G/view?usp=sharing) 32. [Technology Test 2](http://www.richmans-maps.ch.vu/) (link dead!)
33. [The Gate Playable Demo](https://www.fileplanet.com/116347/110000/fileinfo/The-Gate-Playable-Demo) 33. [The Gate Playable Demo](https://www.fileplanet.com/116347/110000/fileinfo/The-Gate-Playable-Demo)
34. [They are Back](https://www.runthinkshootlive.com/posts/they-are-back/) 34. [They are Back](https://www.runthinkshootlive.com/posts/they-are-back/)
35. [Tiefseelabor( Deep Sea Laboratory )](https://www.runthinkshootlive.com/posts/deep-sea-laboratory/) 35. [Tiefseelabor( Deep Sea Laboratory )](https://www.runthinkshootlive.com/posts/deep-sea-laboratory/)
36. [Time-Shift](https://drive.google.com/file/d/1pK1s-2SIlSMQHVRPMLdC_94wTa__8_DX/view?usp=sharing) 36. [Time-Shift](http://www.richmans-maps.ch.vu/) (link dead!)
37. [Train Single Beta](https://cs-mapping.com.ua/forum/showthread.php?t=36394) (Remove **gfx.wad** from **TrainSingle** folder) 37. [Train Single Beta](https://cs-mapping.com.ua/forum/showthread.php?t=36394) (Remove **gfx.wad** from **TrainSingle** folder)
38. [WAR: The Killer Beta 0.1](http://www.moddb.com/mods/war) 38. [WAR: The Killer Beta 0.1](http://www.moddb.com/mods/war)
39. [White Force Beta( Residual Point prototype )](http://www.moddb.com/mods/hl-residual-point/downloads/white-force-beta-2002) 39. [White Force Beta( Residual Point prototype )](http://www.moddb.com/mods/hl-residual-point/downloads/white-force-beta-2002)
@@ -379,7 +379,7 @@ Mods:
5. [Half-Life Baby v1.4](http://www.moddb.com/games/half-life/addons/half-life-baby) (it's an unfinished but playable mod; after installing of the mod open **liblist.gam** or **gameinfo.txt** file in the mod's folder and correct the line **gamedll "..\hlbaby\dlls\hl.dll"** for **gamedll "dlls\hl.dll"**, otherwise you'll not be able to start a game) 5. [Half-Life Baby v1.4](http://www.moddb.com/games/half-life/addons/half-life-baby) (it's an unfinished but playable mod; after installing of the mod open **liblist.gam** or **gameinfo.txt** file in the mod's folder and correct the line **gamedll "..\hlbaby\dlls\hl.dll"** for **gamedll "dlls\hl.dll"**, otherwise you'll not be able to start a game)
6. [Half-Secret](http://www.moddb.com/mods/half-secret) (this mod has custom **weapon_snark** code) 6. [Half-Secret](http://www.moddb.com/mods/half-secret) (this mod has custom **weapon_snark** code)
7. [Induction](http://www.moddb.com/mods/half-life-induction) (this mod has new item - **item_flashlight**) 7. [Induction](http://www.moddb.com/mods/half-life-induction) (this mod has new item - **item_flashlight**)
8. [Lost in Black Mesa(first version without HLFX)](https://drive.google.com/file/d/1bEnm_AxJs-ly8hTEZIQBw_v2BsXdSiGa/view?usp=sharing) 8. [Lost in Black Mesa(first version without HLFX)](http://half-life.ru/forum/showthread.php?threadid=13959)
9. [Soldier](http://www.moddb.com/mods/half-life-soldier) 9. [Soldier](http://www.moddb.com/mods/half-life-soldier)
10. [Solo Operations](http://www.moddb.com/mods/solo-operations) 10. [Solo Operations](http://www.moddb.com/mods/solo-operations)
11. [The Blood v1.1](http://hl.loess.ru/?mods=&search=The+Blood) (there are some inner bugs in the mod, but they don't interfere with a game progress) 11. [The Blood v1.1](http://hl.loess.ru/?mods=&search=The+Blood) (there are some inner bugs in the mod, but they don't interfere with a game progress)
@@ -440,7 +440,7 @@ Mods:
51. [Data-base](https://www.runthinkshootlive.com/posts/database/) 51. [Data-base](https://www.runthinkshootlive.com/posts/database/)
52. [de_dust2_azabetfeN](https://cs-mapping.com.ua/forum/showthread.php?t=36394) (remove **cl_dlls** & **dlls** folders from inside of mod's directory before you start the game) 52. [de_dust2_azabetfeN](https://cs-mapping.com.ua/forum/showthread.php?t=36394) (remove **cl_dlls** & **dlls** folders from inside of mod's directory before you start the game)
53. [De-railed](http://twhl.info/competitions.php?results=7) 53. [De-railed](http://twhl.info/competitions.php?results=7)
54. [Dead Shift Beta](http://www.moddb.com/mods/dead-shift) - [Demo 1](https://www.gamewatcher.com/mods/half-life-mod/dead-shift-1-0-beta) & [Demo 2](https://drive.google.com/file/d/1uHvr8xONogTTNOy-8X6G4ehFV6Eawvbq/view?usp=sharing) 54. [Dead Shift Beta](http://www.moddb.com/mods/dead-shift) - [Demo 1](https://www.gamewatcher.com/mods/half-life-mod/dead-shift-1-0-beta) & [Demo 2](https://www.gamefront.com/files/13532512) (3rd link dead!)
55. [Deep](http://twhl.info/vault.php?map=1669) 55. [Deep](http://twhl.info/vault.php?map=1669)
56. [Desert Attack](http://fyzzer.narod.ru/index.html) 56. [Desert Attack](http://fyzzer.narod.ru/index.html)
57. [Desert Combat Demo](https://www.fileplanet.com/190487/190000/fileinfo/Half-Life---Desert-Combat-Mod) (despite a big file size there's only one small unfinished map) 57. [Desert Combat Demo](https://www.fileplanet.com/190487/190000/fileinfo/Half-Life---Desert-Combat-Mod) (despite a big file size there's only one small unfinished map)
@@ -469,7 +469,7 @@ Mods:
80. [Extinct Lifeform Hunt](https://www.fileplanet.com/13501/10000/fileinfo/Extinct-Lifeform-Hunt) 80. [Extinct Lifeform Hunt](https://www.fileplanet.com/13501/10000/fileinfo/Extinct-Lifeform-Hunt)
81. [Facility](http://twhl.info/vault.php?map=5482) 81. [Facility](http://twhl.info/vault.php?map=5482)
82. [Facility Escape](http://twhl.info/vault.php?map=3673) 82. [Facility Escape](http://twhl.info/vault.php?map=3673)
83. [Fallout](http://www.thewall.de/forum/thread/hl1-sp-48h-mapping-contest/64975.4.html) (map by *simb*) (link dead!) 83. [Fallout](http://www.thewall.de/forum/thread/hl1-sp-48h-mapping-contest/64975.4.html) (map by *simb*)
84. [Final Assault](http://twhl.info/vault.php?map=4500) 84. [Final Assault](http://twhl.info/vault.php?map=4500)
85. [Flat](http://hl.loess.ru/?mods=&search=Flat) 85. [Flat](http://hl.loess.ru/?mods=&search=Flat)
86. [Freeman's Allegiance](https://www.runthinkshootlive.com/posts/freemans-allegiance/) 86. [Freeman's Allegiance](https://www.runthinkshootlive.com/posts/freemans-allegiance/)
@@ -498,8 +498,8 @@ Mods:
109. [Hospital](https://gamebanana.com/maps/167446) (you need to edit **liblist.gam** file in the mod's folder - delete *gamedll & type* strings from it before you start to play) 109. [Hospital](https://gamebanana.com/maps/167446) (you need to edit **liblist.gam** file in the mod's folder - delete *gamedll & type* strings from it before you start to play)
110. [Hostage](https://www.runthinkshootlive.com/posts/hostage-2/) 110. [Hostage](https://www.runthinkshootlive.com/posts/hostage-2/)
111. [House](http://www.artpeter.net/Data/HalfLife/Hl.php) 111. [House](http://www.artpeter.net/Data/HalfLife/Hl.php)
112. [Impulse 101 Fun - The Train](https://drive.google.com/file/d/1jAuMCCmREH0mfAEAscqaG8FQGa2uNknb/view?usp=sharing) (map from *TWHL* by *Archie* aka *The Hunter*) 112. [Impulse 101 Fun - The Train](http://web.archive.org/web/20070305075816/http://www.twhl.co.za/mapvault/2817.zip) (map from *TWHL* by *Archie* aka *The Hunter*)
113. [In America](https://drive.google.com/file/d/1gOC8zfnUvBxRy8Rr8juNiUNbLYjoZpnn/view?usp=sharing) 113. [In America](http://www.lambda-force.org/load/half_life/karty/half_life_in_america/18-1-0-476)
114. [In the Kitchen](http://twhl.info/vault.php?map=4314) 114. [In the Kitchen](http://twhl.info/vault.php?map=4314)
115. [Infiltration](https://www.fileplanet.com/7467/0/fileinfo/Infiltration) 115. [Infiltration](https://www.fileplanet.com/7467/0/fileinfo/Infiltration)
116. [Interactivity & Lots of Entities](http://twhl.info/vault.php?map=5744) (link dead!) 116. [Interactivity & Lots of Entities](http://twhl.info/vault.php?map=5744) (link dead!)
@@ -668,7 +668,7 @@ Mods:
279. [X-treme Violence](http://www.moddb.com/mods/x-treme-violence) 279. [X-treme Violence](http://www.moddb.com/mods/x-treme-violence)
280. [XargoL's Entry for Vassy's Compo](http://twhl.info/vault.php?map=769) 280. [XargoL's Entry for Vassy's Compo](http://twhl.info/vault.php?map=769)
281. [Xen Again](https://www.fileplanet.com/9132/0/fileinfo/XEN-AGAIN) 281. [Xen Again](https://www.fileplanet.com/9132/0/fileinfo/XEN-AGAIN)
282. [Xen World](http://www.lambda-force.org/load/half_life/karty/half_life_xen_world/18-1-0-481) (link dead!) 282. [Xen World](http://www.lambda-force.org/load/half_life/karty/half_life_xen_world/18-1-0-481)
283. [XUnil](https://www.fileplanet.com/7883/0/fileinfo/XUNIL) 283. [XUnil](https://www.fileplanet.com/7883/0/fileinfo/XUNIL)
284. [Zeeba-G's TWHL Compo 26 Entry](http://twhl.info/competitions.php?results=26) 284. [Zeeba-G's TWHL Compo 26 Entry](http://twhl.info/competitions.php?results=26)
285. [Zombies!](https://gamebanana.com/maps/160812) 285. [Zombies!](https://gamebanana.com/maps/160812)
@@ -694,7 +694,7 @@ For Linux and OS X you must download crossbuild from [here](http://www.moddb.com
2. [Big Scientists](http://www.moddb.com/mods/big-scientists) 2. [Big Scientists](http://www.moddb.com/mods/big-scientists)
3. [Black Silla Assault DEMO v1.2](http://www.moddb.com/mods/black-silla-assault) 3. [Black Silla Assault DEMO v1.2](http://www.moddb.com/mods/black-silla-assault)
4. [Blbej Den](http://www.moddb.com/mods/blbej-den) 4. [Blbej Den](http://www.moddb.com/mods/blbej-den)
5. [Cold Experiment v1](https://www.moddb.com/games/half-life/addons/cold-experiment) (you will need some files from SoHL to play it properly; download SoHL 1.2, extract files and copy following folders into **coldexv1** folder: cl_dlls, dlls, models, sprites) 5. [Cold Experiment v1](http://jpmaps.wz.cz/epizody.htm) (you will need some files from SoHL to play it properly; download SoHL 1.2, extract files and copy following folders into **coldexv1** folder: cl_dlls, dlls, models, sprites)
6. [Dead Sector v1.0a](http://www.moddb.com/mods/dead-sector) 6. [Dead Sector v1.0a](http://www.moddb.com/mods/dead-sector)
7. [Death Is Dead](http://www.moddb.com/games/half-life/addons/death-is-dead) (there is a fog-related inner bug at the first map) 7. [Death Is Dead](http://www.moddb.com/games/half-life/addons/death-is-dead) (there is a fog-related inner bug at the first map)
8. [Escape from Black Mesa Alpha](http://www.moddb.com/mods/escape-from-black-mesa) 8. [Escape from Black Mesa Alpha](http://www.moddb.com/mods/escape-from-black-mesa)
@@ -710,9 +710,9 @@ For Linux and OS X you must download crossbuild from [here](http://www.moddb.com
18. [Santa's Revenge](http://twhl.info/vault.php?map=4332) (set **fps_max** to **60** to avoid an inner problem of the last map with final scripted sequence, otherwise the mod can not be finished properly) 18. [Santa's Revenge](http://twhl.info/vault.php?map=4332) (set **fps_max** to **60** to avoid an inner problem of the last map with final scripted sequence, otherwise the mod can not be finished properly)
19. [Sector 6](https://www.moddb.com/mods/sector-6/) 19. [Sector 6](https://www.moddb.com/mods/sector-6/)
20. [Space Prisoner v1.1](http://www.moddb.com/games/half-life/addons/space-prisoner-v11) (after installing of the mod open **liblist.gam** or **gameinfo.txt** file in the mod's folder and correct the line **gamedll "..\prison\dlls\spirit.dll"** for **gamedll "dlls\spirit.dll"**, otherwise you'll not be able to start a game; there is also a scripting error on a third map of the mod, so you'll be forced to use **noclip** to pass around bugged place) 20. [Space Prisoner v1.1](http://www.moddb.com/games/half-life/addons/space-prisoner-v11) (after installing of the mod open **liblist.gam** or **gameinfo.txt** file in the mod's folder and correct the line **gamedll "..\prison\dlls\spirit.dll"** for **gamedll "dlls\spirit.dll"**, otherwise you'll not be able to start a game; there is also a scripting error on a third map of the mod, so you'll be forced to use **noclip** to pass around bugged place)
21. [Terrorist Attack 2](https://www.moddb.com/games/half-life/addons/terrorist-attack-2) 21. [Terrorist Attack 2](http://terroristattack.wz.cz/mody.html) (link dead!)
22. [Timeline III: The Heart of Darkness](http://www.moddb.com/mods/timeline-series) 22. [Timeline III: The Heart of Darkness](http://www.moddb.com/mods/timeline-series)
23. [Underground 2 Demo](https://www.moddb.com/games/half-life/addons/underground-2-demo) 23. [Underground 2 Demo](http://www.isolated-design.de/half-life-mods/underground-2/)
## Mods which based on modified Spirit of Half-Life 1.2 or older(Partially playable with SoHL 1.2 libraries or not playable at all) ## Mods which based on modified Spirit of Half-Life 1.2 or older(Partially playable with SoHL 1.2 libraries or not playable at all)
1. [Black Death](http://www.moddb.com/mods/half-life-black-death) 1. [Black Death](http://www.moddb.com/mods/half-life-black-death)
@@ -825,10 +825,10 @@ Mods:
3. [Bomb Squad](http://www.snarkpit.net/index.php?s=maps&map=3471) 3. [Bomb Squad](http://www.snarkpit.net/index.php?s=maps&map=3471)
4. [Corruption](http://www.snarkpit.net/index.php?s=maps&map=3154) 4. [Corruption](http://www.snarkpit.net/index.php?s=maps&map=3154)
5. [Critical Mass](http://www.moddb.com/mods/half-life-critical-mass) [C3M1 Build 1 Demo](https://www.fileplanet.com/125746/120000/fileinfo/C3M1-Build-1) 5. [Critical Mass](http://www.moddb.com/mods/half-life-critical-mass) [C3M1 Build 1 Demo](https://www.fileplanet.com/125746/120000/fileinfo/C3M1-Build-1)
6. [EPRST!](https://www.runthinkshootlive.com/posts/ep-rst/) 6. [EPRST!](http://www.planetphillip.com/posts/ep-rst-opposing-force/) (link dead!)
7. [Firing Range](https://www.runthinkshootlive.com/posts/firing-range/) 7. [Firing Range](https://www.runthinkshootlive.com/posts/firing-range/)
8. [Friendly Fire](https://www.runthinkshootlive.com/posts/friendly-fire/) 8. [Friendly Fire](https://www.runthinkshootlive.com/posts/friendly-fire/)
9. [Guitar Star Pre-Alpha](http://gamer-lab.com/rus/mods_goldsrc/Guitar_Star_(Prealpha)) 9. [Guitar Star Pre-Alpha](http://hl-lab.ru/eng/mods_goldsrc/Guitar_Star_(Prealpha)) (link dead!)
10. [J2000](https://www.runthinkshootlive.com/posts/j2000/) 10. [J2000](https://www.runthinkshootlive.com/posts/j2000/)
11. [Killing House for OF](https://www.runthinkshootlive.com/posts/scientist-rescue-aka-cqb/) 11. [Killing House for OF](https://www.runthinkshootlive.com/posts/scientist-rescue-aka-cqb/)
12. [Klabautermann](https://www.runthinkshootlive.com/posts/klabautermann/) (though the map has some inner issues, it can be properly finished, just don't let the welder soldier die and don't press the fifth button until you mount a special gun in its' place) 12. [Klabautermann](https://www.runthinkshootlive.com/posts/klabautermann/) (though the map has some inner issues, it can be properly finished, just don't let the welder soldier die and don't press the fifth button until you mount a special gun in its' place)

View File

@@ -1,5 +1,5 @@
# Xash3D FWGS Engine # Xash3D FWGS Engine
[![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/) \ [![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) [![Travis CI Status](https://api.travis-ci.org/FWGS/xash3d-fwgs.svg?branch=master)](https://travis-ci.org/FWGS/xash3d-fwgs) [![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://discord.fwgs.ru/) \
[![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 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)
Xash3D FWGS is a fork of Xash3D Engine by Unkle Mike with extended features and crossplatform. Xash3D FWGS is a fork of Xash3D Engine by Unkle Mike with extended features and crossplatform.
@@ -27,13 +27,16 @@ Read more about Xash3D on ModDB: https://www.moddb.com/engines/xash3d-engine
* Vulkan renderer * Vulkan renderer
## Installation & Running ## Installation & Running
0) Get Xash3D FWGS binaries: you can use [testing](https://github.com/FWGS/xash3d-fwgs/releases/tag/continuous) build or you can compile engine from source code. 0) Get Xash3D binaries: you can use [testing](https://github.com/FWGS/xash3d-fwgs/releases/tag/continuous) build or you can compile engine from source code.
Choose proper build package depending on which platform you're using.
1) Copy engine binaries to some directory. 1) Copy engine binaries to some directory.
2) Copy `valve` directory from [Half-Life](https://store.steampowered.com/app/70/HalfLife/) to directory with engine binaries. 2) Copy `valve` directory from [Half-Life](https://store.steampowered.com/app/70/HalfLife/) to directory with engine binaries.
If your CPU is NOT x86 compatible or you're running 64-bit version of the engine, you may want to compile [Half-Life SDK](https://github.com/FWGS/hlsdk-xash3d). Also if you're using Windows: you should copy `vgui.dll` library from Half-Life directory to Xash3D directory.
This repository contains our fork of HLSDK and restored source code for some of the mods. Not all of them, of course. As alternative, you can compile [hlsdk-xash3d](https://github.com/FWGS/hlsdk-xash3d) instead of using official Valve game binaries, but you still needed to copy `valve` directory as all game resources located in there.
You still needed to copy `valve` directory as all game resources located there. 3) Download [extras.pak](https://github.com/FWGS/xash-extras/releases/tag/v0.19.2) and place it to `valve` directory.
3) Run the main executable (`xash3d.exe` or AppImage). 4) Run `xash3d.exe`/`xash3d.sh`/`xash3d` depending on which platform you're using.
Note: on Linux, you may need to create an sh file with the command `LD_LIBRARY_PATH=. ./xash3d`.
For additional info, run Xash3D with `-help` command line key. For additional info, run Xash3D with `-help` command line key.
@@ -48,13 +51,6 @@ We are using Waf build system. If you have some Waf-related questions, I recomme
NOTE: NEVER USE GitHub's ZIP ARCHIVES. GitHub doesn't include external dependencies we're using! NOTE: NEVER USE GitHub's ZIP ARCHIVES. GitHub doesn't include external dependencies we're using!
### Prerequisites ### Prerequisites
If your CPU is x86 compatible, we are building 32-bit code by default. This was dont for keeping compatibility with Steam releases of Half-Life and based on it's engine games.
Even if Xash3D FWGS does support targetting 64-bit, you can't load games without recompiling them from source code!
If your CPU is NOT x86 compatible or you decided build 64-bit version of engine, you may want to compile [Half-Life SDK](https://github.com/FWGS/hlsdk-xash3d).
This repository contains our fork of HLSDK and restored source code for some of the mods. Not all of them, of course.
#### Windows (Visual Studio) #### Windows (Visual Studio)
* Install Visual Studio. * Install Visual Studio.
* Install latest [Python](https://python.org) **OR** run `cinst python.install` if you have Chocolatey. * Install latest [Python](https://python.org) **OR** run `cinst python.install` if you have Chocolatey.
@@ -64,6 +60,10 @@ This repository contains our fork of HLSDK and restored source code for some of
* Make sure you have at least 12GB of free space to store all build-time dependencies: ~10GB for Visual Studio, 300 MB for Git, 100 MB for Python and other. * Make sure you have at least 12GB of free space to store all build-time dependencies: ~10GB for Visual Studio, 300 MB for Git, 100 MB for Python and other.
#### GNU/Linux #### GNU/Linux
NOTE FOR USERS WITH X86 COMPATIBLE CPUs:
We have forced Waf to throw an error, if you're trying to build 64-bit engine. This was done for keeping compatibility with Steam releases of Half-Life and based on it's engine games.
Even if Xash3D FWGS does support targetting 64-bit, you can't load games without recompiling them from source code!
##### Debian/Ubuntu ##### Debian/Ubuntu
* Enable i386 on your system, if you're compiling 32-bit engine on amd64. If not, skip this * Enable i386 on your system, if you're compiling 32-bit engine on amd64. If not, skip this
@@ -81,15 +81,16 @@ This repository contains our fork of HLSDK and restored source code for some of
0) Open command line 0) Open command line
1) Navigate to `xash3d-fwgs` directory. 1) Navigate to `xash3d-fwgs` directory.
2) Carefully examine which build options are available: `waf --help` 2) Carefully examine which build options are available: `waf --help`
3) Configure build: `waf configure -T release --sdl2=c:/path/to/SDL2` 3) Configure build: `waf configure -T release --sdl2=c:/path/to/SDL2 --prefix=c:/path/to/any/output/directory`
4) Compile: `waf build` 4) Compile: `waf build`
5) Install: `waf install --destdir=c:/path/to/any/output/directory` 5) Install: `waf install`
#### Linux #### Linux
If compiling 32-bit on amd64, you may need to supply `export PKG_CONFIG_PATH=/usr/lib/i386-linux-gnu/pkgconfig` prior to running configure.
0) Examine which build options are available: `./waf --help` 0) Examine which build options are available: `./waf --help`
1) Configure build: `./waf configure -T release` 1) Configure build: `./waf configure -T release --prefix=/path/to/any/output/directory`
(You need to pass `-8` to compile 64-bit engine on 64-bit x86 processor) (You need to pass `-8` to compile 64-bit engine on 64-bit x86 processor)
2) Compile: `./waf build` 2) Compile: `./waf build`
3) Install(optional): `./waf install --destdir=/path/to/any/output/directory` 3) Install(optional): `./waf install`
Note: if compiling 32-bit on amd64, you may need to supply `export PKG_CONFIG_PATH=/usr/lib/i386-linux-gnu/pkgconfig` prior to running configure.

View File

@@ -73,8 +73,7 @@ BRUSH MODELS
#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 #else
// increased to match PrimeXT compilers #define MAX_MAP_MODELS 768 // embedded models
#define MAX_MAP_MODELS 1024 // embedded models
#define MAX_MAP_ENTSTRING 0x100000 // 1 Mb should be enough #define MAX_MAP_ENTSTRING 0x100000 // 1 Mb should be enough
#define MAX_MAP_PLANES 65536 // can be increased without problems #define MAX_MAP_PLANES 65536 // can be increased without problems
#define MAX_MAP_NODES 32767 // because negative shorts are leafs #define MAX_MAP_NODES 32767 // because negative shorts are leafs

View File

@@ -9,7 +9,8 @@ NOTE: number at end of pixelformat name it's a total bitscount e.g. PF_RGB_24 ==
======================================================================== ========================================================================
*/ */
#define ImageRAW( type ) (type == PF_RGBA_32 || type == PF_BGRA_32 || type == PF_RGB_24 || type == PF_BGR_24 || type == PF_LUMINANCE) #define ImageRAW( type ) (type == PF_RGBA_32 || type == PF_BGRA_32 || type == PF_RGB_24 || type == PF_BGR_24 || type == PF_LUMINANCE)
#define ImageDXT( type ) (type == PF_DXT1 || type == PF_DXT3 || type == PF_DXT5 || type == PF_ATI2 || type == PF_BC6H_SIGNED || type == PF_BC6H_UNSIGNED || type == PF_BC7) #define ImageDXT( type ) (type == PF_DXT1 || type == PF_DXT3 || type == PF_DXT5 || type == PF_ATI2)
#define Image16( type ) (type == PF_RGBA_64 || type == PF_RGB_48)
typedef enum typedef enum
{ {
@@ -21,13 +22,12 @@ typedef enum
PF_RGB_24, // uncompressed dds or another 24-bit image PF_RGB_24, // uncompressed dds or another 24-bit image
PF_BGR_24, // big-endian RGB (MacOS) PF_BGR_24, // big-endian RGB (MacOS)
PF_LUMINANCE, PF_LUMINANCE,
PF_DXT1, // s3tc DXT1/BC1 format PF_DXT1, // s3tc DXT1 format
PF_DXT3, // s3tc DXT3/BC2 format PF_DXT3, // s3tc DXT3 format
PF_DXT5, // s3tc DXT5/BC3 format PF_DXT5, // s3tc DXT5 format
PF_ATI2, // latc ATI2N/BC5 format PF_ATI2, // latc ATI2N format
PF_BC6H_SIGNED, // bptc BC6H signed FP16 format PF_RGBA_64, // 16-bit RGBA
PF_BC6H_UNSIGNED, // bptc BC6H unsigned FP16 format PF_RGB_48, // 16-bit RGB
PF_BC7, // bptc BC7 format
PF_TOTALCOUNT, // must be last PF_TOTALCOUNT, // must be last
} pixformat_t; } pixformat_t;
@@ -85,7 +85,7 @@ typedef enum
IMAGE_ROT_90 = BIT(18), // flip from upper left corner to down right corner IMAGE_ROT_90 = BIT(18), // flip from upper left corner to down right corner
IMAGE_ROT180 = IMAGE_FLIP_X|IMAGE_FLIP_Y, IMAGE_ROT180 = IMAGE_FLIP_X|IMAGE_FLIP_Y,
IMAGE_ROT270 = IMAGE_FLIP_X|IMAGE_FLIP_Y|IMAGE_ROT_90, IMAGE_ROT270 = IMAGE_FLIP_X|IMAGE_FLIP_Y|IMAGE_ROT_90,
// reserved IMAGE_EMBOSS = BIT(19), // apply emboss mapping
IMAGE_RESAMPLE = BIT(20), // resample image to specified dims IMAGE_RESAMPLE = BIT(20), // resample image to specified dims
// reserved // reserved
// reserved // reserved

View File

@@ -530,7 +530,7 @@ typedef struct
#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 256 // SpriteTextures
#define MAX_EFRAGS 8192 // Arcane Dimensions required #define MAX_EFRAGS 8192 // Arcane Dimensions required
#define MAX_REQUESTS 64 #define MAX_REQUESTS 64

View File

@@ -725,6 +725,7 @@ typedef int string_t;
typedef unsigned short word; typedef unsigned short word;
#include "xash3d_types.h" #include "xash3d_types.h"
#define Q_isspace( ch ) (ch < 32 || ch > 255)
typedef struct typedef struct
{ {

View File

@@ -25,18 +25,14 @@
#define FCVAR_PRINTABLEONLY (1<<7) // This cvar's string cannot contain unprintable characters ( e.g., used for player name etc ). #define FCVAR_PRINTABLEONLY (1<<7) // This cvar's string cannot contain unprintable characters ( e.g., used for player name etc ).
#define FCVAR_UNLOGGED (1<<8) // If this is a FCVAR_SERVER, don't log changes to the log file / console if we are creating a log #define FCVAR_UNLOGGED (1<<8) // If this is a FCVAR_SERVER, don't log changes to the log file / console if we are creating a log
#define FCVAR_NOEXTRAWHITEPACE (1<<9) // strip trailing/leading white space from this cvar #define FCVAR_NOEXTRAWHITEPACE (1<<9) // strip trailing/leading white space from this cvar
#define FCVAR_PRIVILEGED (1<<10) // only available in privileged mode
#define FCVAR_FILTERABLE (1<<11) // filtered in unprivileged mode if cl_filterstuffcmd is 1
// Xash3D extensions #define FCVAR_MOVEVARS (1<<10) // this cvar is a part of movevars_t struct that shared between client and server
#define FCVAR_LATCH (1<<11) // notify client what this cvar will be applied only after server restart (but don't does more nothing)
#define FCVAR_GLCONFIG (1<<12) // write it into <renderer>.cfg(see RefAPI) #define FCVAR_GLCONFIG (1<<12) // write it into <renderer>.cfg(see RefAPI)
#define FCVAR_CHANGED (1<<13) // set each time the cvar is changed #define FCVAR_CHANGED (1<<13) // set each time the cvar is changed
#define FCVAR_GAMEUIDLL (1<<14) // defined by the menu DLL #define FCVAR_GAMEUIDLL (1<<14) // defined by the menu DLL
#define FCVAR_CHEAT (1<<15) // can not be changed if cheats are disabled #define FCVAR_CHEAT (1<<15) // can not be changed if cheats are disabled
// a1ba: let's reuse higher bits for flags extensions from now on
#define FCVAR_LATCH (1<<30) // notify client what this cvar will be applied only after server restart (but don't does more nothing)
typedef struct cvar_s typedef struct cvar_s
{ {
char *name; char *name;

View File

@@ -25,6 +25,5 @@ GNU General Public License for more details.
#define ENGINE_COMPENSATE_QUAKE_BUG (1<<5) // compensate stupid quake bug (inverse pitch) for mods where this bug is fixed #define ENGINE_COMPENSATE_QUAKE_BUG (1<<5) // compensate stupid quake bug (inverse pitch) for mods where this bug is fixed
#define ENGINE_IMPROVED_LINETRACE (1<<6) // new traceline that tracing through alphatextures #define ENGINE_IMPROVED_LINETRACE (1<<6) // new traceline that tracing through alphatextures
#define ENGINE_COMPUTE_STUDIO_LERP (1<<7) // enable MOVETYPE_STEP lerping back in engine #define ENGINE_COMPUTE_STUDIO_LERP (1<<7) // enable MOVETYPE_STEP lerping back in engine
#define ENGINE_LINEAR_GAMMA_SPACE (1<<8) // disable influence of gamma/brightness cvars to textures/lightmaps, for mods with custom renderer
#endif//FEATURES_H #endif//FEATURES_H

View File

@@ -18,7 +18,6 @@ GNU General Public License for more details.
#define GFL_NOMODELS (1<<0) #define GFL_NOMODELS (1<<0)
#define GFL_NOSKILLS (1<<1) #define GFL_NOSKILLS (1<<1)
#define GFL_RENDER_PICBUTTON_TEXT (1<<2)
/* /*
======================================================================== ========================================================================

View File

@@ -20,6 +20,8 @@ GNU General Public License for more details.
#include "build.h" #include "build.h"
#if !XASH_WIN32 #if !XASH_WIN32
#if XASH_APPLE #if XASH_APPLE
#include <sys/syslimits.h> #include <sys/syslimits.h>
#define OS_LIB_EXT "dylib" #define OS_LIB_EXT "dylib"
@@ -28,32 +30,67 @@ GNU General Public License for more details.
#define OS_LIB_EXT "so" #define OS_LIB_EXT "so"
#define OPEN_COMMAND "xdg-open" #define OPEN_COMMAND "xdg-open"
#endif #endif
#define OS_LIB_PREFIX "lib" #define OS_LIB_PREFIX "lib"
#if XASH_ANDROID
//#if defined(LOAD_HARDFP)
// #define POSTFIX "_hardfp"
//#else
#define POSTFIX
//#endif
#else
#endif
#define VGUI_SUPPORT_DLL "libvgui_support." OS_LIB_EXT #define VGUI_SUPPORT_DLL "libvgui_support." OS_LIB_EXT
// Windows-specific // Windows-specific
#define __cdecl #define __cdecl
#define __stdcall #define __stdcall
#define _inline static inline #define _inline static inline
#define FORCEINLINE inline __attribute__((always_inline)) #define FORCEINLINE inline __attribute__((always_inline))
#if XASH_POSIX #if XASH_POSIX
#include <unistd.h> #define PATH_SPLITTER "/"
#include <dlfcn.h> #include <unistd.h>
#include <dlfcn.h>
#define O_BINARY 0 // O_BINARY is Windows extension
#define O_TEXT 0 // O_TEXT is Windows extension
// Windows functions to posix equivalent
#define _mkdir( x ) mkdir( x, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH )
#define LoadLibrary( x ) dlopen( x, RTLD_NOW )
#define GetProcAddress( x, y ) dlsym( x, y )
#define FreeLibrary( x ) dlclose( x )
#define tell( a ) lseek(a, 0, SEEK_CUR)
#define HAVE_DUP
#endif
#define PATH_SPLITTER "/" #if XASH_DOS4GW
#define HAVE_DUP #define PATH_SPLITTER "\\"
#define LoadLibrary( x ) (0)
#define GetProcAddress( x, y ) (0)
#define FreeLibrary( x ) (0)
#endif
//#define MAKEWORD( a, b ) ((short int)(((unsigned char)(a))|(((short int)((unsigned char)(b)))<<8)))
#define max( a, b ) (((a) > (b)) ? (a) : (b))
#define min( a, b ) (((a) < (b)) ? (a) : (b))
#define O_BINARY 0 /// TODO: check if we may clean this defines, it should not appear in non-platform code!
#define O_TEXT 0 typedef unsigned char BYTE;
#define _mkdir( x ) mkdir( x, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH ) typedef short int WORD;
#elif XASH_DOS4GW typedef unsigned int DWORD;
#define PATH_SPLITTER "\\" typedef int LONG;
#endif typedef unsigned int ULONG;
typedef int WPARAM;
typedef unsigned int LPARAM;
typedef void* HANDLE; typedef void* HANDLE;
typedef void* HMODULE;
typedef void* HINSTANCE; typedef void* HINSTANCE;
typedef char* LPSTR;
typedef struct tagPOINT typedef struct tagPOINT
{ {
int x, y; int x, y;
@@ -71,6 +108,19 @@ GNU General Public License for more details.
#define read _read #define read _read
#define alloca _alloca #define alloca _alloca
// shut-up compiler warnings
#pragma warning(disable : 4244) // MIPS
#pragma warning(disable : 4018) // signed/unsigned mismatch
#pragma warning(disable : 4305) // truncation from const double to float
#pragma warning(disable : 4115) // named type definition in parentheses
#pragma warning(disable : 4100) // unreferenced formal parameter
#pragma warning(disable : 4127) // conditional expression is constant
#pragma warning(disable : 4057) // differs in indirection to slightly different base types
#pragma warning(disable : 4201) // nonstandard extension used
#pragma warning(disable : 4706) // assignment within conditional expression
#pragma warning(disable : 4054) // type cast' : from function pointer
#pragma warning(disable : 4310) // cast truncates constant value
#define HSPRITE WINAPI_HSPRITE #define HSPRITE WINAPI_HSPRITE
#define WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN
#include <winsock2.h> #include <winsock2.h>
@@ -80,9 +130,13 @@ GNU General Public License for more details.
#define OS_LIB_PREFIX "" #define OS_LIB_PREFIX ""
#define OS_LIB_EXT "dll" #define OS_LIB_EXT "dll"
#define VGUI_SUPPORT_DLL "../vgui_support." OS_LIB_EXT #define VGUI_SUPPORT_DLL "../vgui_support." OS_LIB_EXT
#ifdef XASH_64BIT
// windows NameForFunction not implemented yet
#define XASH_ALLOW_SAVERESTORE_OFFSETS
#endif
#define HAVE_DUP #define HAVE_DUP
#endif //WIN32
#endif //WIN32
#ifndef XASH_LOW_MEMORY #ifndef XASH_LOW_MEMORY
#define XASH_LOW_MEMORY 0 #define XASH_LOW_MEMORY 0
#endif #endif

View File

@@ -82,7 +82,7 @@ typedef enum
TF_KEEP_SOURCE = (1<<1), // some images keep source TF_KEEP_SOURCE = (1<<1), // some images keep source
TF_NOFLIP_TGA = (1<<2), // Steam background completely ignore tga attribute 0x20 TF_NOFLIP_TGA = (1<<2), // Steam background completely ignore tga attribute 0x20
TF_EXPAND_SOURCE = (1<<3), // Don't keep source as 8-bit expand to RGBA TF_EXPAND_SOURCE = (1<<3), // Don't keep source as 8-bit expand to RGBA
// reserved TF_ALLOW_EMBOSS = (1<<4), // Allow emboss-mapping for this image
TF_RECTANGLE = (1<<5), // this is GL_TEXTURE_RECTANGLE TF_RECTANGLE = (1<<5), // this is GL_TEXTURE_RECTANGLE
TF_CUBEMAP = (1<<6), // it's cubemap texture TF_CUBEMAP = (1<<6), // it's cubemap texture
TF_DEPTHMAP = (1<<7), // custom texture filter used TF_DEPTHMAP = (1<<7), // custom texture filter used
@@ -107,7 +107,6 @@ typedef enum
TF_ARB_FLOAT = (1<<26), // float textures TF_ARB_FLOAT = (1<<26), // float textures
TF_NOCOMPARE = (1<<27), // disable comparing for depth textures TF_NOCOMPARE = (1<<27), // disable comparing for depth textures
TF_ARB_16BIT = (1<<28), // keep image as 16-bit (not 24) TF_ARB_16BIT = (1<<28), // keep image as 16-bit (not 24)
TF_MULTISAMPLE = (1<<29) // multisampling texture
} texFlags_t; } texFlags_t;
typedef enum typedef enum

View File

@@ -2,9 +2,7 @@
#ifndef XASH_TYPES_H #ifndef XASH_TYPES_H
#define XASH_TYPES_H #define XASH_TYPES_H
#include "build.h" #ifdef _WIN32
#if XASH_WIN32
#include <wchar.h> // off_t #include <wchar.h> // off_t
#endif // _WIN32 #endif // _WIN32
@@ -66,41 +64,19 @@ typedef uint64_t longtime_t;
#define ColorIndex( c ) ((( c ) - '0' ) & 7 ) #define ColorIndex( c ) ((( c ) - '0' ) & 7 )
#if defined(__GNUC__) #if defined(__GNUC__)
#ifdef __i386__ #ifdef __i386__
#define EXPORT __attribute__ ((visibility ("default"),force_align_arg_pointer)) #define EXPORT __attribute__ ((visibility ("default"),force_align_arg_pointer))
#define GAME_EXPORT __attribute((force_align_arg_pointer)) #define GAME_EXPORT __attribute((force_align_arg_pointer))
#else
#define EXPORT __attribute__ ((visibility ("default")))
#define GAME_EXPORT
#endif
#define _format(x) __attribute__((format(printf, x, x+1)))
#define NORETURN __attribute__((noreturn))
#elif defined(_MSC_VER)
#define EXPORT __declspec( dllexport )
#define GAME_EXPORT
#define _format(x)
#define NORETURN
#else #else
#define EXPORT #define EXPORT __attribute__ ((visibility ("default")))
#define GAME_EXPORT #define GAME_EXPORT
#define _format(x)
#define NORETURN
#endif #endif
#elif defined(_MSC_VER)
#if ( __GNUC__ >= 3 ) #define EXPORT __declspec( dllexport )
#define unlikely(x) __builtin_expect(x, 0) #define GAME_EXPORT
#define likely(x) __builtin_expect(x, 1)
#elif defined( __has_builtin )
#if __has_builtin( __builtin_expect )
#define unlikely(x) __builtin_expect(x, 0)
#define likely(x) __builtin_expect(x, 1)
#else
#define unlikely(x) (x)
#define likely(x) (x)
#endif
#else #else
#define unlikely(x) (x) #define EXPORT
#define likely(x) (x) #define GAME_EXPORT
#endif #endif
@@ -138,13 +114,9 @@ typedef unsigned int dword;
typedef unsigned int uint; typedef unsigned int uint;
typedef char string[MAX_STRING]; typedef char string[MAX_STRING];
typedef struct file_s file_t; // normal file typedef struct file_s file_t; // normal file
typedef struct wfile_s wfile_t; // wad file
typedef struct stream_s stream_t; // sound stream for background music playing typedef struct stream_s stream_t; // sound stream for background music playing
typedef off_t fs_offset_t; typedef off_t fs_offset_t;
#if XASH_WIN32
typedef int fs_size_t; // return type of _read, _write funcs
#else /* !XASH_WIN32 */
typedef ssize_t fs_size_t;
#endif /* !XASH_WIN32 */
typedef struct dllfunc_s typedef struct dllfunc_s
{ {
@@ -160,7 +132,7 @@ typedef struct dll_info_s
void *link; // hinstance of loading library void *link; // hinstance of loading library
} dll_info_t; } dll_info_t;
typedef void (*setpair_t)( const char *key, const void *value, const void *buffer, void *numpairs ); typedef void (*setpair_t)( const char *key, const void *value, void *buffer, void *numpairs );
// config strings are a general means of communication from // config strings are a general means of communication from
// the server to all connected clients. // the server to all connected clients.

View File

@@ -106,7 +106,7 @@ void CL_RemoveFromResourceList( resource_t *pResource )
if( pResource->pPrev == NULL || pResource->pNext == NULL ) if( pResource->pPrev == NULL || pResource->pNext == NULL )
Host_Error( "mislinked resource in CL_RemoveFromResourceList\n" ); Host_Error( "mislinked resource in CL_RemoveFromResourceList\n" );
if( pResource->pNext == pResource || pResource->pPrev == pResource ) if ( pResource->pNext == pResource || pResource->pPrev == pResource )
Host_Error( "attempt to free last entry in list.\n" ); Host_Error( "attempt to free last entry in list.\n" );
pResource->pPrev->pNext = pResource->pNext; pResource->pPrev->pNext = pResource->pNext;

View File

@@ -888,7 +888,7 @@ qboolean CL_DemoReadMessage( byte *buffer, size_t *length )
qboolean swallowmessages = true; qboolean swallowmessages = true;
static int tdlastdemoframe = 0; static int tdlastdemoframe = 0;
byte *userbuf = NULL; byte *userbuf = NULL;
size_t size = 0; size_t size;
byte cmd; byte cmd;
if( !cls.demofile ) if( !cls.demofile )

View File

@@ -188,6 +188,8 @@ void R_StoreEfrags( efrag_t **ppefrag, int framecount )
case mod_brush: case mod_brush:
case mod_studio: case mod_studio:
case mod_sprite: case mod_sprite:
pent = pefrag->entity;
if( pent->visframe != framecount ) if( pent->visframe != framecount )
{ {
if( CL_AddVisibleEntity( pent, ET_FRAGMENTED )) if( CL_AddVisibleEntity( pent, ET_FRAGMENTED ))

View File

@@ -46,7 +46,7 @@ short GAME_EXPORT R_LookupColor( byte r, byte g, byte b )
float rf, gf, bf; float rf, gf, bf;
bestdiff = 999999; bestdiff = 999999;
best = -1; best = 65535;
for( i = 0; i < 256; i++ ) for( i = 0; i < 256; i++ )
{ {
@@ -683,46 +683,42 @@ void CL_ParseViewBeam( sizebuf_t *msg, int beamType )
switch( beamType ) switch( beamType )
{ {
case TE_BEAMPOINTS: case TE_BEAMPOINTS:
case TE_BEAMENTPOINT: start[0] = MSG_ReadCoord( msg );
case TE_BEAMENTS: start[1] = MSG_ReadCoord( msg );
if( beamType == TE_BEAMENTS ) start[2] = MSG_ReadCoord( msg );
{ end[0] = MSG_ReadCoord( msg );
startEnt = MSG_ReadShort( msg ); end[1] = MSG_ReadCoord( msg );
endEnt = MSG_ReadShort( msg ); end[2] = MSG_ReadCoord( msg );
}
else
{
if( beamType == TE_BEAMENTPOINT )
{
startEnt = MSG_ReadShort( msg );
}
else
{
start[0] = MSG_ReadCoord( msg );
start[1] = MSG_ReadCoord( msg );
start[2] = MSG_ReadCoord( msg );
}
end[0] = MSG_ReadCoord( msg );
end[1] = MSG_ReadCoord( msg );
end[2] = MSG_ReadCoord( msg );
}
modelIndex = MSG_ReadShort( msg ); modelIndex = MSG_ReadShort( msg );
startFrame = MSG_ReadByte( msg ); startFrame = MSG_ReadByte( msg );
frameRate = (float)MSG_ReadByte( msg ) * 0.1f; frameRate = (float)MSG_ReadByte( msg );
life = (float)MSG_ReadByte( msg ) * 0.1f; life = (float)(MSG_ReadByte( msg ) * 0.1f);
width = (float)MSG_ReadByte( msg ) * 0.1f; width = (float)(MSG_ReadByte( msg ) * 0.1f);
noise = (float)MSG_ReadByte( msg ) * 0.01f; noise = (float)(MSG_ReadByte( msg ) * 0.01f);
r = (float)MSG_ReadByte( msg ) / 255.0f; r = (float)MSG_ReadByte( msg ) / 255.0f;
g = (float)MSG_ReadByte( msg ) / 255.0f; g = (float)MSG_ReadByte( msg ) / 255.0f;
b = (float)MSG_ReadByte( msg ) / 255.0f; b = (float)MSG_ReadByte( msg ) / 255.0f;
a = (float)MSG_ReadByte( msg ) / 255.0f; a = (float)MSG_ReadByte( msg ) / 255.0f;
speed = (float)MSG_ReadByte( msg ) * 0.1f; speed = (float)(MSG_ReadByte( msg ) * 0.1f);
if( beamType == TE_BEAMENTS ) R_BeamPoints( start, end, modelIndex, life, width, noise, a, speed, startFrame, frameRate, r, g, b );
R_BeamEnts( startEnt, endEnt, modelIndex, life, width, noise, a, speed, startFrame, frameRate, r, g, b ); break;
else if( beamType == TE_BEAMENTPOINT ) case TE_BEAMENTPOINT:
R_BeamEntPoint( startEnt, end, modelIndex, life, width, noise, a, speed, startFrame, frameRate, r, g, b ); startEnt = MSG_ReadShort( msg );
else end[0] = MSG_ReadCoord( msg );
R_BeamPoints( start, end, modelIndex, life, width, noise, a, speed, startFrame, frameRate, r, g, b ); end[1] = MSG_ReadCoord( msg );
end[2] = MSG_ReadCoord( msg );
modelIndex = MSG_ReadShort( msg );
startFrame = MSG_ReadByte( msg );
frameRate = (float)MSG_ReadByte( msg );
life = (float)(MSG_ReadByte( msg ) * 0.1f);
width = (float)(MSG_ReadByte( msg ) * 0.1f);
noise = (float)(MSG_ReadByte( msg ) * 0.01f);
r = (float)MSG_ReadByte( msg ) / 255.0f;
g = (float)MSG_ReadByte( msg ) / 255.0f;
b = (float)MSG_ReadByte( msg ) / 255.0f;
a = (float)MSG_ReadByte( msg ) / 255.0f;
speed = (float)(MSG_ReadByte( msg ) * 0.1f);
R_BeamEntPoint( startEnt, end, modelIndex, life, width, noise, a, speed, startFrame, frameRate, r, g, b );
break; break;
case TE_LIGHTNING: case TE_LIGHTNING:
start[0] = MSG_ReadCoord( msg ); start[0] = MSG_ReadCoord( msg );
@@ -731,11 +727,27 @@ void CL_ParseViewBeam( sizebuf_t *msg, int beamType )
end[0] = MSG_ReadCoord( msg ); end[0] = MSG_ReadCoord( msg );
end[1] = MSG_ReadCoord( msg ); end[1] = MSG_ReadCoord( msg );
end[2] = MSG_ReadCoord( msg ); end[2] = MSG_ReadCoord( msg );
life = (float)MSG_ReadByte( msg ) * 0.1f; life = (float)(MSG_ReadByte( msg ) * 0.1f);
width = (float)MSG_ReadByte( msg ) * 0.1f; width = (float)(MSG_ReadByte( msg ) * 0.1f);
noise = (float)MSG_ReadByte( msg ) * 0.01f; noise = (float)(MSG_ReadByte( msg ) * 0.01f);
modelIndex = MSG_ReadShort( msg ); modelIndex = MSG_ReadShort( msg );
R_BeamLightning( start, end, modelIndex, life, width, noise, 0.6f, 3.5f ); R_BeamLightning( start, end, modelIndex, life, width, noise, 0.6F, 3.5f );
break;
case TE_BEAMENTS:
startEnt = MSG_ReadShort( msg );
endEnt = MSG_ReadShort( msg );
modelIndex = MSG_ReadShort( msg );
startFrame = MSG_ReadByte( msg );
frameRate = (float)(MSG_ReadByte( msg ) * 0.1f);
life = (float)(MSG_ReadByte( msg ) * 0.1f);
width = (float)(MSG_ReadByte( msg ) * 0.1f);
noise = (float)(MSG_ReadByte( msg ) * 0.01f);
r = (float)MSG_ReadByte( msg ) / 255.0f;
g = (float)MSG_ReadByte( msg ) / 255.0f;
b = (float)MSG_ReadByte( msg ) / 255.0f;
a = (float)MSG_ReadByte( msg ) / 255.0f;
speed = (float)(MSG_ReadByte( msg ) * 0.1f);
R_BeamEnts( startEnt, endEnt, modelIndex, life, width, noise, a, speed, startFrame, frameRate, r, g, b );
break; break;
case TE_BEAM: case TE_BEAM:
break; break;
@@ -761,21 +773,21 @@ void CL_ParseViewBeam( sizebuf_t *msg, int beamType )
end[2] = MSG_ReadCoord( msg ); end[2] = MSG_ReadCoord( msg );
modelIndex = MSG_ReadShort( msg ); modelIndex = MSG_ReadShort( msg );
startFrame = MSG_ReadByte( msg ); startFrame = MSG_ReadByte( msg );
frameRate = (float)MSG_ReadByte( msg ) * 0.1f; frameRate = (float)(MSG_ReadByte( msg ));
life = (float)MSG_ReadByte( msg ) * 0.1f; life = (float)(MSG_ReadByte( msg ) * 0.1f);
width = (float)MSG_ReadByte( msg ); width = (float)(MSG_ReadByte( msg ));
noise = (float)MSG_ReadByte( msg ) * 0.01f; noise = (float)(MSG_ReadByte( msg ) * 0.1f);
r = (float)MSG_ReadByte( msg ) / 255.0f; r = (float)MSG_ReadByte( msg ) / 255.0f;
g = (float)MSG_ReadByte( msg ) / 255.0f; g = (float)MSG_ReadByte( msg ) / 255.0f;
b = (float)MSG_ReadByte( msg ) / 255.0f; b = (float)MSG_ReadByte( msg ) / 255.0f;
a = (float)MSG_ReadByte( msg ) / 255.0f; a = (float)MSG_ReadByte( msg ) / 255.0f;
speed = (float)MSG_ReadByte( msg ) * 0.1f; speed = (float)(MSG_ReadByte( msg ) / 0.1f);
R_BeamCirclePoints( beamType, start, end, modelIndex, life, width, noise, a, speed, startFrame, frameRate, r, g, b ); R_BeamCirclePoints( beamType, start, end, modelIndex, life, width, noise, a, speed, startFrame, frameRate, r, g, b );
break; break;
case TE_BEAMFOLLOW: case TE_BEAMFOLLOW:
startEnt = MSG_ReadShort( msg ); startEnt = MSG_ReadShort( msg );
modelIndex = MSG_ReadShort( msg ); modelIndex = MSG_ReadShort( msg );
life = (float)MSG_ReadByte( msg ) * 0.1f; life = (float)(MSG_ReadByte( msg ) * 0.1f);
width = (float)MSG_ReadByte( msg ); width = (float)MSG_ReadByte( msg );
r = (float)MSG_ReadByte( msg ) / 255.0f; r = (float)MSG_ReadByte( msg ) / 255.0f;
g = (float)MSG_ReadByte( msg ) / 255.0f; g = (float)MSG_ReadByte( msg ) / 255.0f;
@@ -788,15 +800,15 @@ void CL_ParseViewBeam( sizebuf_t *msg, int beamType )
endEnt = MSG_ReadShort( msg ); endEnt = MSG_ReadShort( msg );
modelIndex = MSG_ReadShort( msg ); modelIndex = MSG_ReadShort( msg );
startFrame = MSG_ReadByte( msg ); startFrame = MSG_ReadByte( msg );
frameRate = (float)MSG_ReadByte( msg ) * 0.1f; frameRate = (float)MSG_ReadByte( msg );
life = (float)MSG_ReadByte( msg ) * 0.1f; life = (float)(MSG_ReadByte( msg ) * 0.1f);
width = (float)MSG_ReadByte( msg ) * 0.1f; width = (float)(MSG_ReadByte( msg ) * 0.1f);
noise = (float)MSG_ReadByte( msg ) * 0.01f; noise = (float)(MSG_ReadByte( msg ) * 0.01f);
r = (float)MSG_ReadByte( msg ) / 255.0f; r = (float)MSG_ReadByte( msg ) / 255.0f;
g = (float)MSG_ReadByte( msg ) / 255.0f; g = (float)MSG_ReadByte( msg ) / 255.0f;
b = (float)MSG_ReadByte( msg ) / 255.0f; b = (float)MSG_ReadByte( msg ) / 255.0f;
a = (float)MSG_ReadByte( msg ) / 255.0f; a = (float)MSG_ReadByte( msg ) / 255.0f;
speed = (float)MSG_ReadByte( msg ) * 0.1f; speed = (float)(MSG_ReadByte( msg ) * 0.1f);
R_BeamRing( startEnt, endEnt, modelIndex, life, width, noise, a, speed, startFrame, frameRate, r, g, b ); R_BeamRing( startEnt, endEnt, modelIndex, life, width, noise, a, speed, startFrame, frameRate, r, g, b );
break; break;
case TE_BEAMHOSE: case TE_BEAMHOSE:
@@ -1111,13 +1123,9 @@ R_ParticleExplosion2
void GAME_EXPORT R_ParticleExplosion2( const vec3_t org, int colorStart, int colorLength ) void GAME_EXPORT R_ParticleExplosion2( const vec3_t org, int colorStart, int colorLength )
{ {
int i, j; int i, j;
int colorMod = 0, packedColor; int colorMod = 0;
particle_t *p; particle_t *p;
if( FBitSet( host.features, ENGINE_QUAKE_COMPATIBLE ))
packedColor = 255; // use old code for blob particles
else packedColor = 0;
for( i = 0; i < 512; i++ ) for( i = 0; i < 512; i++ )
{ {
p = R_AllocParticle( NULL ); p = R_AllocParticle( NULL );
@@ -1125,7 +1133,7 @@ void GAME_EXPORT R_ParticleExplosion2( const vec3_t org, int colorStart, int col
p->die = cl.time + 0.3f; p->die = cl.time + 0.3f;
p->color = colorStart + ( colorMod % colorLength ); p->color = colorStart + ( colorMod % colorLength );
p->packedColor = packedColor; p->packedColor = 255; // use old code for blob particles
colorMod++; colorMod++;
p->type = pt_blob; p->type = pt_blob;
@@ -1147,19 +1155,15 @@ R_BlobExplosion
void GAME_EXPORT R_BlobExplosion( const vec3_t org ) void GAME_EXPORT R_BlobExplosion( const vec3_t org )
{ {
particle_t *p; particle_t *p;
int i, j, packedColor; int i, j;
if( FBitSet( host.features, ENGINE_QUAKE_COMPATIBLE ))
packedColor = 255; // use old code for blob particles
else packedColor = 0;
for( i = 0; i < 1024; i++ ) for( i = 0; i < 1024; i++ )
{ {
p = R_AllocParticle( NULL ); p = R_AllocParticle( NULL );
if( !p ) return; if( !p ) return;
p->die = cl.time + COM_RandomFloat( 1.0f, 1.4f ); p->die = cl.time + COM_RandomFloat( 2.0f, 2.4f );
p->packedColor = packedColor; p->packedColor = 255; // use old code for blob particles
if( i & 1 ) if( i & 1 )
{ {
@@ -1261,7 +1265,7 @@ void GAME_EXPORT R_BloodStream( const vec3_t org, const vec3_t dir, int pcolor,
particle_t *p; particle_t *p;
int i, j; int i, j;
float arc; float arc;
int accel = speed; // must be integer due to bug in GoldSrc float accel = speed;
for( arc = 0.05f, i = 0; i < 100; i++ ) for( arc = 0.05f, i = 0; i < 100; i++ )
{ {

View File

@@ -158,7 +158,7 @@ CL_EventIndex
*/ */
word CL_EventIndex( const char *name ) word CL_EventIndex( const char *name )
{ {
word i; int i;
if( !COM_CheckString( name )) if( !COM_CheckString( name ))
return 0; return 0;
@@ -484,7 +484,7 @@ void GAME_EXPORT CL_PlaybackEvent( int flags, const edict_t *pInvoker, word even
return; return;
// first check event for out of bounds // first check event for out of bounds
if( eventindex < 1 || eventindex >= MAX_EVENTS ) if( eventindex < 1 || eventindex > MAX_EVENTS )
{ {
Con_DPrintf( S_ERROR "CL_PlaybackEvent: invalid eventindex %i\n", eventindex ); Con_DPrintf( S_ERROR "CL_PlaybackEvent: invalid eventindex %i\n", eventindex );
return; return;

View File

@@ -58,13 +58,10 @@ void CL_UpdatePositions( cl_entity_t *ent )
ent->current_position = (ent->current_position + 1) & HISTORY_MASK; ent->current_position = (ent->current_position + 1) & HISTORY_MASK;
ph = &ent->ph[ent->current_position]; ph = &ent->ph[ent->current_position];
VectorCopy( ent->curstate.origin, ph->origin ); VectorCopy( ent->curstate.origin, ph->origin );
VectorCopy( ent->curstate.angles, ph->angles ); VectorCopy( ent->curstate.angles, ph->angles );
ph->animtime = ent->curstate.animtime; // !!!
if( ent->model && ent->model->type == mod_brush )
ph->animtime = ent->curstate.animtime;
else
ph->animtime = cl.time;
} }
/* /*
@@ -222,7 +219,7 @@ void CL_UpdateLatchedVars( cl_entity_t *ent )
if( ent->curstate.sequence != ent->prevstate.sequence ) if( ent->curstate.sequence != ent->prevstate.sequence )
{ {
memcpy( ent->latched.prevseqblending, ent->prevstate.blending, sizeof( ent->latched.prevseqblending )); memcpy( ent->prevstate.blending, ent->latched.prevseqblending, sizeof( ent->prevstate.blending ));
ent->latched.prevsequence = ent->prevstate.sequence; ent->latched.prevsequence = ent->prevstate.sequence;
ent->latched.sequencetime = ent->curstate.animtime; ent->latched.sequencetime = ent->curstate.animtime;
} }
@@ -313,7 +310,7 @@ void CL_ProcessEntityUpdate( cl_entity_t *ent )
if( FBitSet( ent->curstate.entityType, ENTITY_NORMAL )) if( FBitSet( ent->curstate.entityType, ENTITY_NORMAL ))
COM_NormalizeAngles( ent->curstate.angles ); COM_NormalizeAngles( ent->curstate.angles );
parametric = ent->curstate.starttime != 0.0f && ent->curstate.impacttime != 0.0f; parametric = CL_ParametricMove( ent );
// allow interpolation on bmodels too // allow interpolation on bmodels too
if( ent->model && ent->model->type == mod_brush ) if( ent->model && ent->model->type == mod_brush )
@@ -352,7 +349,7 @@ find two timestamps
qboolean CL_FindInterpolationUpdates( cl_entity_t *ent, float targettime, position_history_t **ph0, position_history_t **ph1 ) qboolean CL_FindInterpolationUpdates( cl_entity_t *ent, float targettime, position_history_t **ph0, position_history_t **ph1 )
{ {
qboolean extrapolate = true; qboolean extrapolate = true;
uint i, i0, i1, imod; int i, i0, i1, imod;
float at; float at;
imod = ent->current_position; imod = ent->current_position;
@@ -409,7 +406,7 @@ void CL_PureOrigin( cl_entity_t *ent, float t, vec3_t outorigin, vec3_t outangle
VectorSubtract( ph0->origin, ph1->origin, delta ); VectorSubtract( ph0->origin, ph1->origin, delta );
if( !Q_equal( t0, t1 )) if( t0 != t1 )
frac = ( t - t1 ) / ( t0 - t1 ); frac = ( t - t1 ) / ( t0 - t1 );
else frac = 1.0f; else frac = 1.0f;
@@ -489,9 +486,7 @@ int CL_InterpolateModel( cl_entity_t *e )
return 0; return 0;
} }
// HACKHACK: workaround buggy position history animtime if( t2 == t1 )
// going backward sometimes
if( Q_equal( t2, t1 ) || t2 < t1 )
{ {
VectorCopy( ph0->origin, e->origin ); VectorCopy( ph0->origin, e->origin );
VectorCopy( ph0->angles, e->angles ); VectorCopy( ph0->angles, e->angles );
@@ -534,7 +529,7 @@ void CL_ComputePlayerOrigin( cl_entity_t *ent )
vec3_t origin; vec3_t origin;
vec3_t angles; vec3_t angles;
if( !ent->player ) if( !ent->player || ent->index == ( cl.playernum + 1 ))
return; return;
if( cl_nointerp->value > 0.f ) if( cl_nointerp->value > 0.f )
@@ -983,13 +978,8 @@ qboolean CL_AddVisibleEntity( cl_entity_t *ent, int entityType )
} }
// don't add the player in firstperson mode // don't add the player in firstperson mode
if( RP_LOCALCLIENT( ent )) if( RP_LOCALCLIENT( ent ) && !CL_IsThirdPerson( ) && ( ent->index == cl.viewentity ))
{ return false;
cl.local.apply_effects = true;
if( !CL_IsThirdPerson( ) && ( ent->index == cl.viewentity ))
return false;
}
if( entityType == ET_BEAM ) if( entityType == ET_BEAM )
{ {
@@ -1003,8 +993,12 @@ qboolean CL_AddVisibleEntity( cl_entity_t *ent, int entityType )
// because pTemp->entity.curstate.effects // because pTemp->entity.curstate.effects
// is already occupied by FTENT_FLICKER // is already occupied by FTENT_FLICKER
if( entityType != ET_TEMPENTITY && !RP_LOCALCLIENT( ent ) ) if( entityType != ET_TEMPENTITY )
{ {
// no reason to do it twice
if( RP_LOCALCLIENT( ent ))
cl.local.apply_effects = false;
// apply client-side effects // apply client-side effects
CL_AddEntityEffects( ent ); CL_AddEntityEffects( ent );
@@ -1056,6 +1050,7 @@ void CL_LinkPlayers( frame_t *frame )
// apply muzzleflash to weaponmodel // apply muzzleflash to weaponmodel
if( ent && FBitSet( ent->curstate.effects, EF_MUZZLEFLASH )) if( ent && FBitSet( ent->curstate.effects, EF_MUZZLEFLASH ))
SetBits( clgame.viewent.curstate.effects, EF_MUZZLEFLASH ); SetBits( clgame.viewent.curstate.effects, EF_MUZZLEFLASH );
cl.local.apply_effects = true;
// check all the clients but add only visible // check all the clients but add only visible
for( i = 0, state = frame->playerstate; i < MAX_CLIENTS; i++, state++ ) for( i = 0, state = frame->playerstate; i < MAX_CLIENTS; i++, state++ )
@@ -1094,9 +1089,6 @@ void CL_LinkPlayers( frame_t *frame )
if ( i == cl.playernum ) if ( i == cl.playernum )
{ {
// using interpolation only for local player angles
CL_ComputePlayerOrigin( ent );
if( cls.demoplayback == DEMO_QUAKE1 ) if( cls.demoplayback == DEMO_QUAKE1 )
VectorLerp( ent->prevstate.origin, cl.lerpFrac, ent->curstate.origin, cl.simorg ); VectorLerp( ent->prevstate.origin, cl.lerpFrac, ent->curstate.origin, cl.simorg );
VectorCopy( cl.simorg, ent->origin ); VectorCopy( cl.simorg, ent->origin );

View File

@@ -147,6 +147,21 @@ qboolean CL_IsThirdPerson( void )
return false; return false;
} }
/*
====================
CL_GetPlayerInfo
get player info by render request
====================
*/
player_info_t *CL_GetPlayerInfo( int playerIndex )
{
if( playerIndex < 0 || playerIndex >= cl.maxclients )
return NULL;
return &cl.players[playerIndex];
}
/* /*
==================== ====================
CL_CreatePlaylist CL_CreatePlaylist
@@ -1220,10 +1235,6 @@ static model_t *CL_LoadSpriteModel( const char *filename, uint type, uint texFla
model_t *mod; model_t *mod;
int i; int i;
// use high indices for client sprites
// for GoldSrc bug-compatibility
const int start = type != SPR_HUDSPRITE ? MAX_CLIENT_SPRITES / 2 : 0;
if( !COM_CheckString( filename )) if( !COM_CheckString( filename ))
{ {
Con_Reportf( S_ERROR "CL_LoadSpriteModel: bad name!\n" ); Con_Reportf( S_ERROR "CL_LoadSpriteModel: bad name!\n" );
@@ -1233,7 +1244,8 @@ static model_t *CL_LoadSpriteModel( const char *filename, uint type, uint texFla
Q_strncpy( name, filename, sizeof( name )); Q_strncpy( name, filename, sizeof( name ));
COM_FixSlashes( name ); COM_FixSlashes( name );
for( i = 0, mod = clgame.sprites + start; i < MAX_CLIENT_SPRITES / 2; i++, mod++ ) // slot 0 isn't used
for( i = 1, mod = clgame.sprites; i < MAX_CLIENT_SPRITES; i++, mod++ )
{ {
if( !Q_stricmp( mod->name, name )) if( !Q_stricmp( mod->name, name ))
{ {
@@ -1250,12 +1262,12 @@ static model_t *CL_LoadSpriteModel( const char *filename, uint type, uint texFla
} }
// find a free model slot spot // find a free model slot spot
for( i = 0, mod = clgame.sprites + start; i < MAX_CLIENT_SPRITES / 2; i++, mod++ ) for( i = 1, mod = clgame.sprites; i < MAX_CLIENT_SPRITES; i++, mod++ )
if( !mod->name[0] ) break; // this is a valid spot if( !mod->name[0] ) break; // this is a valid spot
if( i == MAX_CLIENT_SPRITES / 2 ) if( i == MAX_CLIENT_SPRITES )
{ {
Con_Printf( S_ERROR "MAX_CLIENT_SPRITES limit exceeded (%d)\n", MAX_CLIENT_SPRITES / 2 ); Con_Printf( S_ERROR "MAX_CLIENT_SPRITES limit exceeded (%d)\n", MAX_CLIENT_SPRITES );
return NULL; return NULL;
} }
@@ -1296,7 +1308,7 @@ HSPRITE pfnSPR_LoadExt( const char *szPicName, uint texFlags )
if(( spr = CL_LoadSpriteModel( szPicName, SPR_CLIENT, texFlags )) == NULL ) if(( spr = CL_LoadSpriteModel( szPicName, SPR_CLIENT, texFlags )) == NULL )
return 0; return 0;
return (spr - clgame.sprites) + 1; // return index return (spr - clgame.sprites); // return index
} }
/* /*
@@ -1312,7 +1324,7 @@ HSPRITE EXPORT pfnSPR_Load( const char *szPicName )
if(( spr = CL_LoadSpriteModel( szPicName, SPR_HUDSPRITE, 0 )) == NULL ) if(( spr = CL_LoadSpriteModel( szPicName, SPR_HUDSPRITE, 0 )) == NULL )
return 0; return 0;
return (spr - clgame.sprites) + 1; // return index return (spr - clgame.sprites); // return index
} }
/* /*
@@ -1324,11 +1336,10 @@ CL_GetSpritePointer
const model_t *CL_GetSpritePointer( HSPRITE hSprite ) const model_t *CL_GetSpritePointer( HSPRITE hSprite )
{ {
model_t *mod; model_t *mod;
int index = hSprite - 1;
if( index < 0 || index >= MAX_CLIENT_SPRITES ) if( hSprite <= 0 || hSprite >= MAX_CLIENT_SPRITES )
return NULL; // bad image return NULL; // bad image
mod = &clgame.sprites[index]; mod = &clgame.sprites[hSprite];
if( mod->needload == NL_NEEDS_LOADED ) if( mod->needload == NL_NEEDS_LOADED )
{ {
@@ -1733,29 +1744,6 @@ static int GAME_EXPORT pfnClientCmd( const char *szCmdString )
return 1; return 1;
} }
/*
=============
pfnFilteredClientCmd
=============
*/
static int GAME_EXPORT pfnFilteredClientCmd( const char *szCmdString )
{
if( !COM_CheckString( szCmdString ))
return 0;
// a1ba:
// there should be stufftext validator, that checks
// hardcoded commands and disallows them before passing to
// filtered buffer, returning 0
// I've replaced it by hooking potentially exploitable
// commands and variables(motd_write, motdfile, etc) in client interfaces
Cbuf_AddFilteredText( szCmdString );
Cbuf_AddFilteredText( "\n" );
return 1;
}
/* /*
============= =============
pfnGetPlayerInfo pfnGetPlayerInfo
@@ -1936,14 +1924,7 @@ prints directly into console (can skip notify)
*/ */
static void GAME_EXPORT pfnConsolePrint( const char *string ) static void GAME_EXPORT pfnConsolePrint( const char *string )
{ {
if( !COM_CheckString( string )) Con_Printf( "%s", string );
return;
// WON GoldSrc behavior
if( string[0] != 1 )
Con_Printf( "%s", string );
else
Con_NPrintf( 0, "%s", string + 1 );
} }
/* /*
@@ -2295,9 +2276,9 @@ static void GAME_EXPORT pfnKillEvents( int entnum, const char *eventname )
int i; int i;
event_state_t *es; event_state_t *es;
event_info_t *ei; event_info_t *ei;
word eventIndex = CL_EventIndex( eventname ); int eventIndex = CL_EventIndex( eventname );
if( eventIndex >= MAX_EVENTS ) if( eventIndex < 0 || eventIndex >= MAX_EVENTS )
return; return;
if( entnum < 0 || entnum > clgame.maxEntities ) if( entnum < 0 || entnum > clgame.maxEntities )
@@ -2662,14 +2643,7 @@ pfnLoadMapSprite
*/ */
model_t *pfnLoadMapSprite( const char *filename ) model_t *pfnLoadMapSprite( const char *filename )
{ {
model_t *mod; return CL_LoadSpriteModel( filename, SPR_MAPSPRITE, 0 );
mod = Mod_FindName( filename, false );
if( CL_LoadHudSprite( filename, mod, SPR_MAPSPRITE, 0 ))
return mod;
return NULL;
} }
/* /*
@@ -2932,16 +2906,15 @@ pfnDrawString
*/ */
static int GAME_EXPORT pfnDrawString( int x, int y, const char *str, int r, int g, int b ) static int GAME_EXPORT pfnDrawString( int x, int y, const char *str, int r, int g, int b )
{ {
int iWidth = 0;
Con_UtfProcessChar(0); Con_UtfProcessChar(0);
// draw the string until we hit the null character or a newline character // draw the string until we hit the null character or a newline character
for ( ; *str != 0 && *str != '\n'; str++ ) for ( ; *str != 0 && *str != '\n'; str++ )
{ {
iWidth += pfnVGUI2DrawCharacterAdditive( x + iWidth, y, (unsigned char)*str, r, g, b, 0 ); x += pfnVGUI2DrawCharacterAdditive( x, y, (unsigned char)*str, r, g, b, 0 );
} }
return iWidth; return x;
} }
/* /*
@@ -2956,7 +2929,8 @@ static int GAME_EXPORT pfnDrawStringReverse( int x, int y, const char *str, int
char *szIt; char *szIt;
for( szIt = (char*)str; *szIt != 0; szIt++ ) for( szIt = (char*)str; *szIt != 0; szIt++ )
x -= clgame.scrInfo.charWidths[ (unsigned char) *szIt ]; x -= clgame.scrInfo.charWidths[ (unsigned char) *szIt ];
return pfnDrawString( x, y, str, r, g, b ); pfnDrawString( x, y, str, r, g, b );
return x;
} }
/* /*
@@ -3090,7 +3064,11 @@ handle colon separately
*/ */
char *pfnParseFile( char *data, char *token ) char *pfnParseFile( char *data, char *token )
{ {
return COM_ParseFileSafe( data, token, PFILE_TOKEN_MAX_LENGTH, PFILE_HANDLECOLON, NULL, NULL ); char *out;
out = _COM_ParseFileSafe( data, token, INT_MAX, PFILE_HANDLECOLON, NULL );
return out;
} }
/* /*
@@ -3177,7 +3155,16 @@ convert world coordinates (x,y,z) into screen (x, y)
*/ */
int TriWorldToScreen( const float *world, float *screen ) int TriWorldToScreen( const float *world, float *screen )
{ {
return ref.dllFuncs.WorldToScreen( world, screen ); int retval;
retval = ref.dllFuncs.WorldToScreen( world, screen );
screen[0] = 0.5f * screen[0] * (float)clgame.viewport[2];
screen[1] = -0.5f * screen[1] * (float)clgame.viewport[3];
screen[0] += 0.5f * (float)clgame.viewport[2];
screen[1] += 0.5f * (float)clgame.viewport[3];
return retval;
} }
/* /*
@@ -3311,7 +3298,7 @@ NetAPI_InitNetworking
*/ */
void GAME_EXPORT NetAPI_InitNetworking( void ) void GAME_EXPORT NetAPI_InitNetworking( void )
{ {
NET_Config( true, false ); // allow remote NET_Config( true ); // allow remote
} }
/* /*
@@ -3864,7 +3851,7 @@ static cl_enginefunc_t gEngfuncs =
(void*)Cmd_GetName, (void*)Cmd_GetName,
pfnGetClientOldTime, pfnGetClientOldTime,
pfnGetGravity, pfnGetGravity,
CL_ModelHandle, Mod_Handle,
pfnEnableTexSort, pfnEnableTexSort,
pfnSetLightmapColor, pfnSetLightmapColor,
pfnSetLightmapScale, pfnSetLightmapScale,
@@ -3891,7 +3878,10 @@ static cl_enginefunc_t gEngfuncs =
pfnGetAppID, pfnGetAppID,
Cmd_AliasGetList, Cmd_AliasGetList,
pfnVguiWrap2_GetMouseDelta, pfnVguiWrap2_GetMouseDelta,
pfnFilteredClientCmd
// HACKHACK: added it here so it wouldn't cause overflow or segfault
// TODO: itself client command filtering is not implemented yet
pfnClientCmd
}; };
void CL_UnloadProgs( void ) void CL_UnloadProgs( void )
@@ -3913,6 +3903,7 @@ void CL_UnloadProgs( void )
Cvar_FullSet( "host_clientloaded", "0", FCVAR_READ_ONLY ); Cvar_FullSet( "host_clientloaded", "0", FCVAR_READ_ONLY );
COM_FreeLibrary( clgame.hInstance ); COM_FreeLibrary( clgame.hInstance );
VGui_Shutdown();
Mem_FreePool( &cls.mempool ); Mem_FreePool( &cls.mempool );
Mem_FreePool( &clgame.mempool ); Mem_FreePool( &clgame.mempool );
memset( &clgame, 0, sizeof( clgame )); memset( &clgame, 0, sizeof( clgame ));
@@ -3956,7 +3947,7 @@ qboolean CL_LoadProgs( const char *name )
#else #else
// this doesn't mean other platforms uses SDL2 in any case // this doesn't mean other platforms uses SDL2 in any case
// it just helps input code to stay platform-independent // it just helps input code to stay platform-independent
clgame.client_dll_uses_sdl = true; clgame.client_dll_uses_sdl = false;
#endif #endif
clgame.hInstance = COM_LoadLibrary( name, false, false ); clgame.hInstance = COM_LoadLibrary( name, false, false );
@@ -3973,17 +3964,7 @@ qboolean CL_LoadProgs( const char *name )
// trying to fill interface now // trying to fill interface now
GetClientAPI( &clgame.dllFuncs ); GetClientAPI( &clgame.dllFuncs );
}
else if(( GetClientAPI = (void *)COM_GetProcAddress( clgame.hInstance, "F" )) != NULL )
{
Con_Reportf( "CL_LoadProgs: found single callback export (secured client dlls)\n" );
// trying to fill interface now
CL_GetSecuredClientAPI( GetClientAPI );
}
if ( GetClientAPI != NULL )
{
// check critical functions again // check critical functions again
for( func = cdll_exports; func && func->name; func++ ) for( func = cdll_exports; func && func->name; func++ )
{ {

View File

@@ -417,8 +417,6 @@ static void UI_ConvertGameInfo( GAMEINFO *out, gameinfo_t *in )
out->flags |= GFL_NOMODELS; out->flags |= GFL_NOMODELS;
if( in->noskills ) if( in->noskills )
out->flags |= GFL_NOSKILLS; out->flags |= GFL_NOSKILLS;
if( in->render_picbutton_text )
out->flags |= GFL_RENDER_PICBUTTON_TEXT;
} }
static qboolean PIC_Scissor( float *x, float *y, float *width, float *height, float *u0, float *v0, float *u1, float *v1 ) static qboolean PIC_Scissor( float *x, float *y, float *width, float *height, float *u0, float *v0, float *u1, float *v1 )
@@ -980,7 +978,7 @@ pfnGetGamesList
*/ */
static GAMEINFO ** GAME_EXPORT pfnGetGamesList( int *numGames ) static GAMEINFO ** GAME_EXPORT pfnGetGamesList( int *numGames )
{ {
if( numGames ) *numGames = FI->numgames; if( numGames ) *numGames = SI.numgames;
return gameui.modsInfo; return gameui.modsInfo;
} }
@@ -1060,7 +1058,10 @@ pfnChangeInstance
*/ */
static void GAME_EXPORT pfnChangeInstance( const char *newInstance, const char *szFinalMessage ) static void GAME_EXPORT pfnChangeInstance( const char *newInstance, const char *szFinalMessage )
{ {
Con_Reportf( S_ERROR "ChangeInstance menu call is deprecated!\n" ); if( !szFinalMessage ) szFinalMessage = "";
if( !newInstance || !*newInstance ) return;
Host_NewInstance( newInstance, szFinalMessage );
} }
/* /*
@@ -1117,30 +1118,6 @@ static char *pfnParseFile( char *buf, char *token )
return COM_ParseFile( buf, token, INT_MAX ); return COM_ParseFile( buf, token, INT_MAX );
} }
/*
=============
pfnFileExists
legacy wrapper
=============
*/
static int pfnFileExists( const char *path, int gamedironly )
{
return FS_FileExists( path, gamedironly );
}
/*
=============
pfnDelete
legacy wrapper
=============
*/
static int pfnDelete( const char *path )
{
return FS_Delete( path );
}
// engine callbacks // engine callbacks
static ui_enginefuncs_t gEngfuncs = static ui_enginefuncs_t gEngfuncs =
{ {
@@ -1187,7 +1164,7 @@ static ui_enginefuncs_t gEngfuncs =
pfnRenderScene, pfnRenderScene,
pfnAddEntity, pfnAddEntity,
Host_Error, Host_Error,
pfnFileExists, FS_FileExists,
pfnGetGameDir, pfnGetGameDir,
Cmd_CheckMapsList, Cmd_CheckMapsList,
CL_Active, CL_Active,
@@ -1226,7 +1203,7 @@ static ui_enginefuncs_t gEngfuncs =
COM_CompareFileTime, COM_CompareFileTime,
VID_GetModeString, VID_GetModeString,
(void*)COM_SaveFile, (void*)COM_SaveFile,
pfnDelete (void*)FS_Delete
}; };
static void pfnEnableTextInput( int enable ) static void pfnEnableTextInput( int enable )
@@ -1248,11 +1225,6 @@ static int pfnGetRenderers( unsigned int num, char *shortName, size_t size1, cha
return 1; return 1;
} }
static char *pfnParseFileSafe( char *data, char *buf, const int size, unsigned int flags, int *len )
{
return COM_ParseFileSafe( data, buf, size, flags, len, NULL );
}
static ui_extendedfuncs_t gExtendedfuncs = static ui_extendedfuncs_t gExtendedfuncs =
{ {
pfnEnableTextInput, pfnEnableTextInput,
@@ -1261,8 +1233,7 @@ static ui_extendedfuncs_t gExtendedfuncs =
Con_UtfMoveRight, Con_UtfMoveRight,
pfnGetRenderers, pfnGetRenderers,
Sys_DoubleTime, Sys_DoubleTime,
pfnParseFileSafe, _COM_ParseFileSafe
NET_AdrToString
}; };
void UI_UnloadProgs( void ) void UI_UnloadProgs( void )
@@ -1382,13 +1353,13 @@ qboolean UI_LoadProgs( void )
Cvar_FullSet( "host_gameuiloaded", "1", FCVAR_READ_ONLY ); Cvar_FullSet( "host_gameuiloaded", "1", FCVAR_READ_ONLY );
// setup gameinfo // setup gameinfo
for( i = 0; i < FI->numgames; i++ ) for( i = 0; i < SI.numgames; i++ )
{ {
gameui.modsInfo[i] = Mem_Calloc( gameui.mempool, sizeof( GAMEINFO )); gameui.modsInfo[i] = Mem_Calloc( gameui.mempool, sizeof( GAMEINFO ));
UI_ConvertGameInfo( gameui.modsInfo[i], FI->games[i] ); UI_ConvertGameInfo( gameui.modsInfo[i], SI.games[i] );
} }
UI_ConvertGameInfo( &gameui.gameInfo, FI->GameInfo ); // current gameinfo UI_ConvertGameInfo( &gameui.gameInfo, SI.GameInfo ); // current gameinfo
// setup globals // setup globals
gameui.globals->developer = host.allow_console; gameui.globals->developer = host.allow_console;

View File

@@ -70,7 +70,6 @@ convar_t *cl_upmax;
convar_t *cl_lw; convar_t *cl_lw;
convar_t *cl_charset; convar_t *cl_charset;
convar_t *cl_trace_messages; convar_t *cl_trace_messages;
convar_t *cl_nat;
convar_t *hud_utf8; convar_t *hud_utf8;
convar_t *ui_renderworld; convar_t *ui_renderworld;
@@ -196,6 +195,8 @@ void CL_CheckClientState( void )
Netchan_ReportFlow( &cls.netchan ); Netchan_ReportFlow( &cls.netchan );
Con_DPrintf( "client connected at %.2f sec\n", Sys_DoubleTime() - cls.timestart ); Con_DPrintf( "client connected at %.2f sec\n", Sys_DoubleTime() - cls.timestart );
if(( cls.demoplayback || cls.disable_servercount != cl.servercount ) && cl.video_prepped )
SCR_EndLoadingPlaque(); // get rid of loading plaque
} }
} }
@@ -233,7 +234,6 @@ void CL_SignonReply( void )
Mem_PrintStats(); Mem_PrintStats();
break; break;
case 2: case 2:
SCR_EndLoadingPlaque();
if( cl.proxy_redirect && !cls.spectator ) if( cl.proxy_redirect && !cls.spectator )
CL_Disconnect(); CL_Disconnect();
cl.proxy_redirect = false; cl.proxy_redirect = false;
@@ -243,7 +243,7 @@ void CL_SignonReply( void )
float CL_LerpInterval( void ) float CL_LerpInterval( void )
{ {
return Q_max( cl_interp->value, 1.f / cl_updaterate->value ); return max( cl_interp->value, 1.f / cl_updaterate->value );
} }
/* /*
@@ -296,7 +296,7 @@ static float CL_LerpPoint( void )
if( cl_interp->value > 0.001f ) if( cl_interp->value > 0.001f )
{ {
// manual lerp value (goldsrc mode) // manual lerp value (goldsrc mode)
float td = Q_max( 0.f, cl.time - cl.mtime[0] ); float td = max( 0.f, cl.time - cl.mtime[0] );
frac = td / CL_LerpInterval(); frac = td / CL_LerpInterval();
} }
else if( server_frametime > 0.001f ) else if( server_frametime > 0.001f )
@@ -528,7 +528,7 @@ qboolean CL_ProcessShowTexturesCmds( usercmd_t *cmd )
if( released & ( IN_RIGHT|IN_MOVERIGHT )) if( released & ( IN_RIGHT|IN_MOVERIGHT ))
Cvar_SetValue( "r_showtextures", gl_showtextures->value + 1 ); Cvar_SetValue( "r_showtextures", gl_showtextures->value + 1 );
if( released & ( IN_LEFT|IN_MOVELEFT )) if( released & ( IN_LEFT|IN_MOVELEFT ))
Cvar_SetValue( "r_showtextures", Q_max( 1, gl_showtextures->value - 1 )); Cvar_SetValue( "r_showtextures", max( 1, gl_showtextures->value - 1 ));
oldbuttons = cmd->buttons; oldbuttons = cmd->buttons;
return true; return true;
@@ -864,9 +864,6 @@ void CL_WritePacket( void )
cl.commands[cls.netchan.outgoing_sequence & CL_UPDATE_MASK].sendsize = MSG_GetNumBytesWritten( &buf ); cl.commands[cls.netchan.outgoing_sequence & CL_UPDATE_MASK].sendsize = MSG_GetNumBytesWritten( &buf );
cl.commands[cls.netchan.outgoing_sequence & CL_UPDATE_MASK].heldback = false; cl.commands[cls.netchan.outgoing_sequence & CL_UPDATE_MASK].heldback = false;
// send voice data to the server
CL_AddVoiceToDatagram();
// composite the rest of the datagram.. // composite the rest of the datagram..
if( MSG_GetNumBitsWritten( &cls.datagram ) <= MSG_GetNumBitsLeft( &buf )) if( MSG_GetNumBitsWritten( &cls.datagram ) <= MSG_GetNumBitsLeft( &buf ))
MSG_WriteBits( &buf, MSG_GetData( &cls.datagram ), MSG_GetNumBitsWritten( &cls.datagram )); MSG_WriteBits( &buf, MSG_GetData( &cls.datagram ), MSG_GetNumBitsWritten( &cls.datagram ));
@@ -1256,7 +1253,7 @@ void CL_Connect_f( void )
// if running a local server, kill it and reissue // if running a local server, kill it and reissue
if( SV_Active( )) Host_ShutdownServer(); if( SV_Active( )) Host_ShutdownServer();
NET_Config( true, !CVAR_TO_BOOL( cl_nat )); // allow remote NET_Config( true ); // allow remote
Con_Printf( "server %s\n", server ); Con_Printf( "server %s\n", server );
CL_Disconnect(); CL_Disconnect();
@@ -1287,7 +1284,6 @@ void CL_Rcon_f( void )
{ {
char message[1024]; char message[1024];
netadr_t to; netadr_t to;
string command;
int i; int i;
if( !COM_CheckString( rcon_client_password->string )) if( !COM_CheckString( rcon_client_password->string ))
@@ -1302,7 +1298,7 @@ void CL_Rcon_f( void )
message[3] = (char)255; message[3] = (char)255;
message[4] = 0; message[4] = 0;
NET_Config( true, false ); // allow remote NET_Config( true ); // allow remote
Q_strcat( message, "rcon " ); Q_strcat( message, "rcon " );
Q_strcat( message, rcon_client_password->string ); Q_strcat( message, rcon_client_password->string );
@@ -1310,8 +1306,7 @@ void CL_Rcon_f( void )
for( i = 1; i < Cmd_Argc(); i++ ) for( i = 1; i < Cmd_Argc(); i++ )
{ {
Cmd_Escape( command, Cmd_Argv( i ), sizeof( command )); Q_strcat( message, Cmd_Argv( i ));
Q_strcat( message, command );
Q_strcat( message, " " ); Q_strcat( message, " " );
} }
@@ -1503,7 +1498,6 @@ void CL_Disconnect( void )
cls.connect_time = 0; cls.connect_time = 0;
cls.changedemo = false; cls.changedemo = false;
cls.max_fragment_size = FRAGMENT_MAX_SIZE; // reset fragment size cls.max_fragment_size = FRAGMENT_MAX_SIZE; // reset fragment size
Voice_Disconnect();
CL_Stop_f(); CL_Stop_f();
// send a disconnect message to the server // send a disconnect message to the server
@@ -1566,7 +1560,8 @@ void CL_LocalServers_f( void )
netadr_t adr; netadr_t 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 ); // allow remote
cls.legacyservercount = 0;
// send a broadcast packet // send a broadcast packet
adr.type = NA_BROADCAST; adr.type = NA_BROADCAST;
@@ -1588,12 +1583,13 @@ void CL_InternetServers_f( void )
char *info = fullquery + sizeof( MS_SCAN_REQUEST ) - 1; char *info = fullquery + sizeof( MS_SCAN_REQUEST ) - 1;
const size_t remaining = sizeof( fullquery ) - sizeof( MS_SCAN_REQUEST ); const size_t remaining = sizeof( fullquery ) - sizeof( MS_SCAN_REQUEST );
NET_Config( true, true ); // allow remote NET_Config( true ); // allow remote
Con_Printf( "Scanning for servers on the internet area...\n" ); Con_Printf( "Scanning for servers on the internet area...\n" );
Info_SetValueForKey( info, "gamedir", GI->gamefolder, remaining ); Info_SetValueForKey( info, "gamedir", GI->gamefolder, remaining );
Info_SetValueForKey( info, "clver", XASH_VERSION, remaining ); // let master know about client version Info_SetValueForKey( info, "clver", XASH_VERSION, remaining ); // let master know about client version
Info_SetValueForKey( info, "nat", cl_nat->string, remaining ); // Info_SetValueForKey( info, "nat", cl_nat->string, remaining );
cls.legacyservercount = 0;
cls.internetservers_wait = NET_SendToMasters( NS_CLIENT, sizeof( MS_SCAN_REQUEST ) + Q_strlen( info ), fullquery ); cls.internetservers_wait = NET_SendToMasters( NS_CLIENT, sizeof( MS_SCAN_REQUEST ) + Q_strlen( info ), fullquery );
cls.internetservers_pending = true; cls.internetservers_pending = true;
@@ -1717,40 +1713,37 @@ void CL_ParseStatusMessage( netadr_t from, sizebuf_t *msg )
static char infostring[MAX_INFO_STRING+8]; static char infostring[MAX_INFO_STRING+8];
char *s = MSG_ReadString( msg ); char *s = MSG_ReadString( msg );
int i; int i;
const char *magic = ": wrong version\n";
size_t len = Q_strlen( s ), magiclen = Q_strlen( magic );
if( len >= magiclen && !Q_strcmp( s + len - magiclen, magic ))
{
Netchan_OutOfBandPrint( NS_CLIENT, from, "info %i", PROTOCOL_LEGACY_VERSION );
return;
}
if( !Info_IsValid( s ))
{
Con_Printf( "^1Server^7: %s, invalid infostring\n", NET_AdrToString( from ));
return;
}
CL_FixupColorStringsForInfoString( s, infostring ); CL_FixupColorStringsForInfoString( s, infostring );
if( Q_strstr( infostring, "wrong version" ) )
{
Netchan_OutOfBandPrint( NS_CLIENT, from, "info %i", PROTOCOL_LEGACY_VERSION );
Con_Printf( "^1Server^7: %s, Info: %s\n", NET_AdrToString( from ), infostring );
if( cls.legacyservercount < MAX_LEGACY_SERVERS )
cls.legacyservers[cls.legacyservercount++] = from;
return;
}
if( !COM_CheckString( Info_ValueForKey( infostring, "gamedir" ))) if( !COM_CheckString( Info_ValueForKey( infostring, "gamedir" )))
{ {
Con_Printf( "^1Server^7: %s, Info: %s\n", NET_AdrToString( from ), infostring ); Con_Printf( "^1Server^7: %s, Info: %s\n", NET_AdrToString( from ), infostring );
return; // unsupported proto return; // unsupported proto
} }
if( !COM_CheckString( Info_ValueForKey( infostring, "p" ))) for( i = 0; i < cls.legacyservercount; i++ )
{ {
Info_SetValueForKey( infostring, "legacy", "1", sizeof( infostring ) ); if( NET_CompareAdr( cls.legacyservers[i], from ) )
Con_Printf( "^3Server^7: %s, Game: %s\n", NET_AdrToString( from ), Info_ValueForKey( infostring, "gamedir" )); {
} Info_SetValueForKey( infostring, "legacy", "1", sizeof( infostring ) );
else Con_Print("Legacy: ");
{ break;
// more info about servers }
Con_Printf( "^2Server^7: %s, Game: %s\n", NET_AdrToString( from ), Info_ValueForKey( infostring, "gamedir" ));
} }
// more info about servers
Con_Printf( "^2Server^7: %s, Game: %s\n", NET_AdrToString( from ), Info_ValueForKey( infostring, "gamedir" ));
UI_AddServerToList( from, infostring ); UI_AddServerToList( from, infostring );
} }
@@ -2108,12 +2101,6 @@ void CL_ConnectionlessPacket( netadr_t from, sizebuf_t *msg )
} }
else if( !Q_strcmp( c, "f" )) else if( !Q_strcmp( c, "f" ))
{ {
if( !NET_IsMasterAdr( from ))
{
Con_Printf( S_WARN "unexpected server list packet from %s\n", NET_AdrToString( from ));
return;
}
// serverlist got from masterserver // serverlist got from masterserver
while( MSG_GetNumBitsLeft( msg ) > 8 ) while( MSG_GetNumBitsLeft( msg ) > 8 )
{ {
@@ -2172,7 +2159,7 @@ void CL_ConnectionlessPacket( netadr_t from, sizebuf_t *msg )
} }
else if( clgame.request_type == NET_REQUEST_GAMEUI ) else if( clgame.request_type == NET_REQUEST_GAMEUI )
{ {
NET_Config( true, false ); // allow remote NET_Config( true ); // allow remote
Netchan_OutOfBandPrint( NS_CLIENT, servadr, "info %i", PROTOCOL_VERSION ); Netchan_OutOfBandPrint( NS_CLIENT, servadr, "info %i", PROTOCOL_VERSION );
} }
} }
@@ -2364,10 +2351,11 @@ Replace the displayed name for some resources
*/ */
const char *CL_CleanFileName( const char *filename ) const char *CL_CleanFileName( const char *filename )
{ {
if( COM_CheckString( filename ) && filename[0] == '!' ) const char *pfilename = filename;
return "customization";
return filename; if( COM_CheckString( filename ) && filename[0] == '!' )
pfilename = "customization";
return pfilename;
} }
@@ -2827,20 +2815,18 @@ void CL_InitLocal( void )
Cvar_RegisterVariable( &cl_logocolor ); Cvar_RegisterVariable( &cl_logocolor );
Cvar_RegisterVariable( &cl_test_bandwidth ); Cvar_RegisterVariable( &cl_test_bandwidth );
Voice_RegisterCvars();
// register our variables // register our variables
cl_crosshair = Cvar_Get( "crosshair", "1", FCVAR_ARCHIVE, "show weapon chrosshair" ); cl_crosshair = Cvar_Get( "crosshair", "1", FCVAR_ARCHIVE, "show weapon chrosshair" );
cl_nodelta = Cvar_Get ("cl_nodelta", "0", 0, "disable delta-compression for server messages" ); cl_nodelta = Cvar_Get ("cl_nodelta", "0", 0, "disable delta-compression for server messages" );
cl_idealpitchscale = Cvar_Get( "cl_idealpitchscale", "0.8", 0, "how much to look up/down slopes and stairs when not using freelook" ); cl_idealpitchscale = Cvar_Get( "cl_idealpitchscale", "0.8", 0, "how much to look up/down slopes and stairs when not using freelook" );
cl_solid_players = Cvar_Get( "cl_solid_players", "1", 0, "Make all players not solid (can't traceline them)" ); cl_solid_players = Cvar_Get( "cl_solid_players", "1", 0, "Make all players not solid (can't traceline them)" );
cl_interp = Cvar_Get( "ex_interp", "0.1", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "Interpolate object positions starting this many seconds in past" ); cl_interp = Cvar_Get( "ex_interp", "0.1", FCVAR_ARCHIVE, "Interpolate object positions starting this many seconds in past" );
cl_timeout = Cvar_Get( "cl_timeout", "60", 0, "connect timeout (in-seconds)" ); cl_timeout = Cvar_Get( "cl_timeout", "60", 0, "connect timeout (in-seconds)" );
cl_charset = Cvar_Get( "cl_charset", "utf-8", FCVAR_ARCHIVE, "1-byte charset to use (iconv style)" ); cl_charset = Cvar_Get( "cl_charset", "utf-8", FCVAR_ARCHIVE, "1-byte charset to use (iconv style)" );
hud_utf8 = Cvar_Get( "hud_utf8", "0", FCVAR_ARCHIVE, "Use utf-8 encoding for hud text" ); hud_utf8 = Cvar_Get( "hud_utf8", "0", FCVAR_ARCHIVE, "Use utf-8 encoding for hud text" );
rcon_client_password = Cvar_Get( "rcon_password", "", FCVAR_PRIVILEGED, "remote control client password" ); rcon_client_password = Cvar_Get( "rcon_password", "", 0, "remote control client password" );
rcon_address = Cvar_Get( "rcon_address", "", FCVAR_PRIVILEGED, "remote control address" ); rcon_address = Cvar_Get( "rcon_address", "", 0, "remote control address" );
cl_trace_messages = Cvar_Get( "cl_trace_messages", "0", FCVAR_ARCHIVE|FCVAR_CHEAT, "enable message names tracing (good for developers)"); cl_trace_messages = Cvar_Get( "cl_trace_messages", "0", FCVAR_ARCHIVE|FCVAR_CHEAT, "enable message names tracing (good for developers)");
@@ -2851,8 +2837,7 @@ void CL_InitLocal( void )
cl_updaterate = Cvar_Get( "cl_updaterate", "20", FCVAR_USERINFO|FCVAR_ARCHIVE, "refresh rate of server messages" ); cl_updaterate = Cvar_Get( "cl_updaterate", "20", FCVAR_USERINFO|FCVAR_ARCHIVE, "refresh rate of server messages" );
cl_dlmax = Cvar_Get( "cl_dlmax", "0", FCVAR_USERINFO|FCVAR_ARCHIVE, "max allowed outcoming fragment size" ); cl_dlmax = Cvar_Get( "cl_dlmax", "0", FCVAR_USERINFO|FCVAR_ARCHIVE, "max allowed outcoming fragment size" );
cl_upmax = Cvar_Get( "cl_upmax", "1200", FCVAR_ARCHIVE, "max allowed incoming fragment size" ); cl_upmax = Cvar_Get( "cl_upmax", "1200", FCVAR_ARCHIVE, "max allowed incoming fragment size" );
cl_nat = Cvar_Get( "cl_nat", "0", 0, "show servers running under NAT" ); rate = Cvar_Get( "rate", "3500", FCVAR_USERINFO|FCVAR_ARCHIVE, "player network rate" );
rate = Cvar_Get( "rate", "3500", FCVAR_USERINFO|FCVAR_ARCHIVE|FCVAR_FILTERABLE, "player network rate" );
topcolor = Cvar_Get( "topcolor", "0", FCVAR_USERINFO|FCVAR_ARCHIVE, "player top color" ); topcolor = Cvar_Get( "topcolor", "0", FCVAR_USERINFO|FCVAR_ARCHIVE, "player top color" );
bottomcolor = Cvar_Get( "bottomcolor", "0", FCVAR_USERINFO|FCVAR_ARCHIVE, "player bottom color" ); bottomcolor = Cvar_Get( "bottomcolor", "0", FCVAR_USERINFO|FCVAR_ARCHIVE, "player bottom color" );
cl_lw = Cvar_Get( "cl_lw", "1", FCVAR_ARCHIVE|FCVAR_USERINFO, "enable client weapon predicting" ); cl_lw = Cvar_Get( "cl_lw", "1", FCVAR_ARCHIVE|FCVAR_USERINFO, "enable client weapon predicting" );
@@ -2891,9 +2876,10 @@ void CL_InitLocal( void )
Cmd_AddCommand ("give", NULL, "give specified item or weapon" ); Cmd_AddCommand ("give", NULL, "give specified item or weapon" );
Cmd_AddCommand ("drop", NULL, "drop current/specified item or weapon" ); Cmd_AddCommand ("drop", NULL, "drop current/specified item or weapon" );
Cmd_AddCommand ("gametitle", NULL, "show game logo" ); Cmd_AddCommand ("gametitle", NULL, "show game logo" );
Cmd_AddRestrictedCommand ("kill", NULL, "die instantly" ); Cmd_AddCommand( "kill", NULL, "die instantly" );
Cmd_AddCommand ("god", NULL, "enable godmode" ); Cmd_AddCommand ("god", NULL, "enable godmode" );
Cmd_AddCommand ("fov", NULL, "set client field of view" ); Cmd_AddCommand ("fov", NULL, "set client field of view" );
Cmd_AddCommand ("log", NULL, "logging server events" );
// register our commands // register our commands
Cmd_AddCommand ("pause", NULL, "pause the game (if the server allows pausing)" ); Cmd_AddCommand ("pause", NULL, "pause the game (if the server allows pausing)" );
@@ -2903,8 +2889,8 @@ void CL_InitLocal( void )
Cmd_AddCommand ("mp3", CL_PlayCDTrack_f, "Play mp3-track (based on virtual cd-player)" ); Cmd_AddCommand ("mp3", CL_PlayCDTrack_f, "Play mp3-track (based on virtual cd-player)" );
Cmd_AddCommand ("waveplaylen", CL_WavePlayLen_f, "Get approximate length of wave file"); Cmd_AddCommand ("waveplaylen", CL_WavePlayLen_f, "Get approximate length of wave file");
Cmd_AddRestrictedCommand ("setinfo", CL_SetInfo_f, "examine or change the userinfo string (alias of userinfo)" ); Cmd_AddCommand ("setinfo", CL_SetInfo_f, "examine or change the userinfo string (alias of userinfo)" );
Cmd_AddRestrictedCommand ("userinfo", CL_SetInfo_f, "examine or change the userinfo string (alias of setinfo)" ); Cmd_AddCommand ("userinfo", CL_SetInfo_f, "examine or change the userinfo string (alias of setinfo)" );
Cmd_AddCommand ("physinfo", CL_Physinfo_f, "print current client physinfo" ); Cmd_AddCommand ("physinfo", CL_Physinfo_f, "print current client physinfo" );
Cmd_AddCommand ("disconnect", CL_Disconnect_f, "disconnect from server" ); Cmd_AddCommand ("disconnect", CL_Disconnect_f, "disconnect from server" );
Cmd_AddCommand ("record", CL_Record_f, "record a demo" ); Cmd_AddCommand ("record", CL_Record_f, "record a demo" );
@@ -2923,8 +2909,8 @@ 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 ("quit", CL_Quit_f, "quit from game" ); Cmd_AddCommand ("quit", CL_Quit_f, "quit from game" );
Cmd_AddRestrictedCommand ("exit", CL_Quit_f, "quit from game" ); Cmd_AddCommand ("exit", CL_Quit_f, "quit from game" );
Cmd_AddCommand ("screenshot", CL_ScreenShot_f, "takes a screenshot of the next rendered frame" ); Cmd_AddCommand ("screenshot", CL_ScreenShot_f, "takes a screenshot of the next rendered frame" );
Cmd_AddCommand ("snapshot", CL_SnapShot_f, "takes a snapshot of the next rendered frame" ); Cmd_AddCommand ("snapshot", CL_SnapShot_f, "takes a snapshot of the next rendered frame" );
@@ -3030,8 +3016,8 @@ void Host_ClientFrame( void )
// a new portion updates from server // a new portion updates from server
CL_RedoPrediction (); CL_RedoPrediction ();
// update voice // TODO: implement
Voice_Idle( host.frametime ); // Voice_Idle( host.frametime );
// emit visible entities // emit visible entities
CL_EmitEntities (); CL_EmitEntities ();
@@ -3085,12 +3071,12 @@ void CL_Init( void )
VID_Init(); // init video VID_Init(); // init video
S_Init(); // init sound S_Init(); // init sound
Voice_Init( VOICE_DEFAULT_CODEC, 3 ); // init voice
// unreliable buffer. unsed for unreliable commands and voice stream // unreliable buffer. unsed for unreliable commands and voice stream
MSG_Init( &cls.datagram, "cls.datagram", cls.datagram_buf, sizeof( cls.datagram_buf )); MSG_Init( &cls.datagram, "cls.datagram", cls.datagram_buf, sizeof( cls.datagram_buf ));
// IN_TouchInit(); // IN_TouchInit();
Con_LoadHistory();
COM_GetCommonLibraryPath( LIBRARY_CLIENT, libpath, sizeof( libpath )); COM_GetCommonLibraryPath( LIBRARY_CLIENT, libpath, sizeof( libpath ));
@@ -3111,9 +3097,13 @@ CL_Shutdown
*/ */
void CL_Shutdown( void ) void CL_Shutdown( void )
{ {
// already freed
if( !cls.initialized ) return;
cls.initialized = false;
Con_Printf( "CL_Shutdown()\n" ); Con_Printf( "CL_Shutdown()\n" );
if( !host.crashed && cls.initialized ) if( !host.crashed )
{ {
Host_WriteOpenGLConfig (); Host_WriteOpenGLConfig ();
Host_WriteVideoConfig (); Host_WriteVideoConfig ();
@@ -3127,9 +3117,6 @@ void CL_Shutdown( void )
Mobile_Shutdown (); Mobile_Shutdown ();
SCR_Shutdown (); SCR_Shutdown ();
CL_UnloadProgs (); CL_UnloadProgs ();
cls.initialized = false;
VGui_Shutdown();
FS_Delete( "demoheader.tmp" ); // remove tmp file FS_Delete( "demoheader.tmp" ); // remove tmp file
SCR_FreeCinematic (); // release AVI's *after* client.dll because custom renderer may use them SCR_FreeCinematic (); // release AVI's *after* client.dll because custom renderer may use them
@@ -3137,5 +3124,4 @@ void CL_Shutdown( void )
R_Shutdown (); R_Shutdown ();
Con_Shutdown (); Con_Shutdown ();
} }

View File

@@ -93,20 +93,6 @@ static void *pfnGetNativeObject( const char *obj )
return Platform_GetNativeObject( obj ); return Platform_GetNativeObject( obj );
} }
static void pfnTouch_HideButtons( const char *name, byte state )
{
Touch_HideButtons( name, state, true );
}
static void pfnTouch_RemoveButton( const char *name )
{
Touch_RemoveButton( name, true );
}
static char *pfnParseFileSafe( char *data, char *buf, const int size, unsigned int flags, int *len )
{
return COM_ParseFileSafe( data, buf, size, flags, len, NULL );
}
static mobile_engfuncs_t gpMobileEngfuncs = static mobile_engfuncs_t gpMobileEngfuncs =
{ {
@@ -115,15 +101,15 @@ static mobile_engfuncs_t gpMobileEngfuncs =
pfnEnableTextInput, pfnEnableTextInput,
Touch_AddClientButton, Touch_AddClientButton,
Touch_AddDefaultButton, Touch_AddDefaultButton,
pfnTouch_HideButtons, Touch_HideButtons,
pfnTouch_RemoveButton, Touch_RemoveButton,
Touch_SetClientOnly, (void*)Touch_SetClientOnly,
Touch_ResetDefaultButtons, Touch_ResetDefaultButtons,
pfnDrawScaledCharacter, pfnDrawScaledCharacter,
Sys_Warn, Sys_Warn,
pfnGetNativeObject, pfnGetNativeObject,
ID_SetCustomClientID, ID_SetCustomClientID,
pfnParseFileSafe _COM_ParseFileSafe
}; };
qboolean Mobile_Init( void ) qboolean Mobile_Init( void )
@@ -139,8 +125,8 @@ qboolean Mobile_Init( void )
success = true; success = true;
Cmd_AddCommand( "vibrate", (xcommand_t)Vibrate_f, "Vibrate for specified time"); Cmd_AddCommand( "vibrate", (xcommand_t)Vibrate_f, "Vibrate for specified time");
vibration_length = Cvar_Get( "vibration_length", "1.0", FCVAR_ARCHIVE | FCVAR_PRIVILEGED, "Vibration length"); vibration_length = Cvar_Get( "vibration_length", "1.0", FCVAR_ARCHIVE, "Vibration length");
vibration_enable = Cvar_Get( "vibration_enable", "1", FCVAR_ARCHIVE | FCVAR_PRIVILEGED, "Enable vibration"); vibration_enable = Cvar_Get( "vibration_enable", "1", FCVAR_ARCHIVE, "Enable vibration");
return success; return success;
} }

View File

@@ -158,7 +158,6 @@ static void NetGraph_InitColors( void )
f = (float)(i - hfrac) / (float)(NETGRAPH_LERP_HEIGHT - hfrac ); f = (float)(i - hfrac) / (float)(NETGRAPH_LERP_HEIGHT - hfrac );
VectorMA( mincolor[1], f, dc[1], netcolors[NETGRAPH_NET_COLORS + i] ); VectorMA( mincolor[1], f, dc[1], netcolors[NETGRAPH_NET_COLORS + i] );
} }
netcolors[NETGRAPH_NET_COLORS + i][3] = 255;
} }
} }
@@ -260,7 +259,7 @@ static void NetGraph_DrawTimes( wrect_t rect, int x, int w )
for( a = 0; a < w; a++ ) for( a = 0; a < w; a++ )
{ {
i = ( cls.netchan.outgoing_sequence - a ) & NET_TIMINGS_MASK; i = ( cls.netchan.outgoing_sequence - a ) & NET_TIMINGS_MASK;
h = Q_min(( netstat_cmdinfo[i].cmd_lerp / 3.0f ) * NETGRAPH_LERP_HEIGHT, net_graphheight->value * 0.7f); h = ( netstat_cmdinfo[i].cmd_lerp / 3.0f ) * NETGRAPH_LERP_HEIGHT;
fill.left = x + w - a - 1; fill.left = x + w - a - 1;
fill.right = fill.bottom = 1; fill.right = fill.bottom = 1;
@@ -396,10 +395,10 @@ static void NetGraph_DrawTextFields( int x, int y, int w, wrect_t rect, int coun
if( !out ) out = lastout; if( !out ) out = lastout;
else lastout = out; else lastout = out;
Con_DrawString( x, y, va( "in : %i %.2f kb/s", netstat_graph[j].msgbytes, cls.netchan.flow[FLOW_INCOMING].avgkbytespersec ), colors ); Con_DrawString( x, y, va( "in : %i %.2f k/s", netstat_graph[j].msgbytes, cls.netchan.flow[FLOW_INCOMING].avgkbytespersec ), colors );
y += 15; y += 15;
Con_DrawString( x, y, va( "out: %i %.2f kb/s", out, cls.netchan.flow[FLOW_OUTGOING].avgkbytespersec ), colors ); Con_DrawString( x, y, va( "out: %i %.2f k/s", out, cls.netchan.flow[FLOW_OUTGOING].avgkbytespersec ), colors );
y += 15; y += 15;
if( graphtype > 2 ) if( graphtype > 2 )
@@ -616,7 +615,7 @@ static void NetGraph_GetScreenPos( wrect_t *rect, int *w, int *x, int *y )
*x = rect->left + rect->right - 5 - *w; *x = rect->left + rect->right - 5 - *w;
break; break;
case 2: // center case 2: // center
*x = ( rect->left + ( rect->right - 10 - *w )) / 2; *x = rect->left + ( rect->right - 10 - *w ) / 2;
break; break;
default: // left sided default: // left sided
*x = rect->left + 5; *x = rect->left + 5;
@@ -673,7 +672,7 @@ void SCR_DrawNetGraph( void )
if( graphtype < 3 ) if( graphtype < 3 )
{ {
ref.dllFuncs.GL_SetRenderMode( kRenderTransColor ); ref.dllFuncs.GL_SetRenderMode( kRenderTransAdd );
ref.dllFuncs.GL_Bind( XASH_TEXTURE0, R_GetBuiltinTexture( REF_WHITE_TEXTURE ) ); ref.dllFuncs.GL_Bind( XASH_TEXTURE0, R_GetBuiltinTexture( REF_WHITE_TEXTURE ) );
ref.dllFuncs.Begin( TRI_QUADS ); // draw all the fills as a long solid sequence of quads for speedup reasons ref.dllFuncs.Begin( TRI_QUADS ); // draw all the fills as a long solid sequence of quads for speedup reasons

View File

@@ -484,8 +484,6 @@ void CL_BatchResourceRequest( qboolean initialize )
switch( p->type ) switch( p->type )
{ {
case t_sound: case t_sound:
case t_model:
case t_eventscript:
if( !CL_CheckFile( &msg, p )) if( !CL_CheckFile( &msg, p ))
break; break;
CL_MoveToOnHandList( p ); CL_MoveToOnHandList( p );
@@ -493,6 +491,11 @@ void CL_BatchResourceRequest( qboolean initialize )
case t_skin: case t_skin:
CL_MoveToOnHandList( p ); CL_MoveToOnHandList( p );
break; break;
case t_model:
if( !CL_CheckFile( &msg, p ))
break;
CL_MoveToOnHandList( p );
break;
case t_decal: case t_decal:
if( !HPAK_GetDataPointer( CUSTOM_RES_PATH, p, NULL, NULL )) if( !HPAK_GetDataPointer( CUSTOM_RES_PATH, p, NULL, NULL ))
{ {
@@ -517,6 +520,11 @@ void CL_BatchResourceRequest( qboolean initialize )
break; break;
CL_MoveToOnHandList( p ); CL_MoveToOnHandList( p );
break; break;
case t_eventscript:
if( !CL_CheckFile( &msg, p ))
break;
CL_MoveToOnHandList( p );
break;
case t_world: case t_world:
ASSERT( 0 ); ASSERT( 0 );
break; break;
@@ -1314,6 +1322,30 @@ void CL_RegisterUserMessage( sizebuf_t *msg )
CL_LinkUserMessage( pszName, svc_num, size ); CL_LinkUserMessage( pszName, svc_num, size );
} }
/*
================
CL_RegisterUserMessage
register new user message or update existing
================
*/
/*
void CL_LegacyRegisterUserMessage( sizebuf_t *msg )
{
char *pszName;
int svc_num, size;
svc_num = MSG_ReadByte( msg );
size = MSG_ReadByte( msg );
pszName = MSG_ReadString( msg );
// important stuff
if( size == 0xFF ) size = -1;
svc_num = bound( 0, svc_num, 255 );
CL_LinkUserMessage( pszName, svc_num, size );
}
*/
/* /*
================ ================
CL_UpdateUserinfo CL_UpdateUserinfo
@@ -1348,12 +1380,7 @@ void CL_UpdateUserinfo( sizebuf_t *msg )
if( slot == cl.playernum ) memcpy( &gameui.playerinfo, player, sizeof( player_info_t )); if( slot == cl.playernum ) memcpy( &gameui.playerinfo, player, sizeof( player_info_t ));
} }
else else memset( player, 0, sizeof( *player ));
{
COM_ClearCustomizationList( &player->customdata, true );
memset( player, 0, sizeof( *player ));
}
} }
/* /*
@@ -1685,10 +1712,7 @@ CL_ParseVoiceInit
*/ */
void CL_ParseVoiceInit( sizebuf_t *msg ) void CL_ParseVoiceInit( sizebuf_t *msg )
{ {
char *pszCodec = MSG_ReadString( msg ); // TODO: ???
int quality = MSG_ReadByte( msg );
Voice_Init( pszCodec, quality );
} }
/* /*
@@ -1699,31 +1723,7 @@ CL_ParseVoiceData
*/ */
void CL_ParseVoiceData( sizebuf_t *msg ) void CL_ParseVoiceData( sizebuf_t *msg )
{ {
int size, idx, frames; // TODO: ???
byte received[8192];
idx = MSG_ReadByte( msg ) + 1;
frames = MSG_ReadByte( msg );
size = MSG_ReadShort( msg );
size = Q_min( size, sizeof( received ));
MSG_ReadBytes( msg, received, size );
if ( idx <= 0 || idx > cl.maxclients )
return;
// must notify through as both local player and normal client
if( idx == cl.playernum + 1 )
Voice_StatusAck( &voice.local, VOICE_LOOPBACK_INDEX );
Voice_StatusAck( &voice.players_status[idx], idx );
if ( !size )
return;
Voice_AddIncomingData( idx, received, size, frames );
} }
/* /*
@@ -1819,7 +1819,7 @@ void CL_ParseScreenShake( sizebuf_t *msg )
clgame.shake.amplitude = (float)(word)MSG_ReadShort( msg ) * (1.0f / (float)(1<<12)); clgame.shake.amplitude = (float)(word)MSG_ReadShort( msg ) * (1.0f / (float)(1<<12));
clgame.shake.duration = (float)(word)MSG_ReadShort( msg ) * (1.0f / (float)(1<<12)); clgame.shake.duration = (float)(word)MSG_ReadShort( msg ) * (1.0f / (float)(1<<12));
clgame.shake.frequency = (float)(word)MSG_ReadShort( msg ) * (1.0f / (float)(1<<8)); clgame.shake.frequency = (float)(word)MSG_ReadShort( msg ) * (1.0f / (float)(1<<8));
clgame.shake.time = cl.time + Q_max( clgame.shake.duration, 0.01f ); clgame.shake.time = cl.time + max( clgame.shake.duration, 0.01f );
clgame.shake.next_shake = 0.0f; // apply immediately clgame.shake.next_shake = 0.0f; // apply immediately
} }
@@ -1883,42 +1883,46 @@ Find the client cvar value
and sent it back to the server and sent it back to the server
============== ==============
*/ */
void CL_ParseCvarValue( sizebuf_t *msg, const qboolean ext ) void CL_ParseCvarValue( sizebuf_t *msg )
{ {
const char *cvarName, *response; const char *cvarName = MSG_ReadString( msg );
convar_t *cvar; convar_t *cvar = Cvar_FindVar( cvarName );
int requestID;
if( ext ) // build the answer
requestID = MSG_ReadLong( msg ); MSG_BeginClientCmd( &cls.netchan.message, clc_requestcvarvalue );
MSG_WriteString( &cls.netchan.message, cvar ? cvar->string : "Not Found" );
}
cvarName = MSG_ReadString( msg ); /*
cvar = Cvar_FindVar( cvarName ); ==============
CL_ParseCvarValue2
Find the client cvar value
and sent it back to the server
==============
*/
void CL_ParseCvarValue2( sizebuf_t *msg )
{
int requestID = MSG_ReadLong( msg );
const char *cvarName = MSG_ReadString( msg );
convar_t *cvar = Cvar_FindVar( cvarName );
// build the answer
MSG_BeginClientCmd( &cls.netchan.message, clc_requestcvarvalue2 );
MSG_WriteLong( &cls.netchan.message, requestID );
MSG_WriteString( &cls.netchan.message, cvarName );
if( cvar ) if( cvar )
{ {
if( cvar->flags & FCVAR_PRIVILEGED ) // cheater can change value ignoring Cvar_Set so we responce incorrect value
response = "CVAR is privileged"; if( cvar->value != Q_atof( cvar->string ))
else if( cvar->flags & FCVAR_SERVER ) MSG_WriteString( &cls.netchan.message, va( "%s (%g)", cvar->string, cvar->value ));
response = "CVAR is server-only"; else MSG_WriteString( &cls.netchan.message, cvar->string );
else if( cvar->flags & FCVAR_PROTECTED )
response = "CVAR is protected";
else
response = cvar->string;
}
else response = "Bad CVAR request";
if( ext )
{
MSG_BeginClientCmd( &cls.netchan.message, clc_requestcvarvalue2 );
MSG_WriteLong( &cls.netchan.message, requestID );
MSG_WriteString( &cls.netchan.message, cvarName );
} }
else else
{ {
MSG_BeginClientCmd( &cls.netchan.message, clc_requestcvarvalue ); MSG_WriteString( &cls.netchan.message, "Not Found" );
} }
MSG_WriteString( &cls.netchan.message, response );
} }
/* /*
@@ -2222,11 +2226,11 @@ void CL_ParseServerMessage( sizebuf_t *msg, qboolean normal_message )
case svc_stufftext: case svc_stufftext:
s = MSG_ReadString( msg ); s = MSG_ReadString( msg );
#ifdef HACKS_RELATED_HLMODS #ifdef HACKS_RELATED_HLMODS
// disable Cry Of Fear antisave protection // dsiable Cry Of Fear antisave protection
if( !Q_strnicmp( s, "disconnect", 10 ) && cls.signon != SIGNONS ) if( !Q_strnicmp( s, "disconnect", 10 ) && cls.signon != SIGNONS )
break; // too early break; // too early
#endif #endif
Cbuf_AddFilteredText( s ); Cbuf_AddText( s );
break; break;
case svc_setangle: case svc_setangle:
CL_ParseSetAngle( msg ); CL_ParseSetAngle( msg );
@@ -2367,16 +2371,15 @@ void CL_ParseServerMessage( sizebuf_t *msg, qboolean normal_message )
break; break;
case svc_voicedata: case svc_voicedata:
CL_ParseVoiceData( msg ); CL_ParseVoiceData( msg );
cl.frames[cl.parsecountmod].graphdata.voicebytes += MSG_GetNumBytesRead( msg ) - bufStart;
break; break;
case svc_resourcelocation: case svc_resourcelocation:
CL_ParseResLocation( msg ); CL_ParseResLocation( msg );
break; break;
case svc_querycvarvalue: case svc_querycvarvalue:
CL_ParseCvarValue( msg, false ); CL_ParseCvarValue( msg );
break; break;
case svc_querycvarvalue2: case svc_querycvarvalue2:
CL_ParseCvarValue( msg, true ); CL_ParseCvarValue2( msg );
break; break;
case svc_exec: case svc_exec:
CL_ParseExec( msg ); CL_ParseExec( msg );
@@ -2414,11 +2417,14 @@ CL_ParseBaseline
void CL_LegacyParseBaseline( sizebuf_t *msg ) void CL_LegacyParseBaseline( sizebuf_t *msg )
{ {
int i, newnum; int i, newnum;
entity_state_t nullstate;
qboolean player; qboolean player;
cl_entity_t *ent; cl_entity_t *ent;
Delta_InitClient (); // finalize client delta's Delta_InitClient (); // finalize client delta's
memset( &nullstate, 0, sizeof( nullstate ));
newnum = MSG_ReadWord( msg ); newnum = MSG_ReadWord( msg );
player = CL_IsPlayerIndex( newnum ); player = CL_IsPlayerIndex( newnum );
@@ -2988,13 +2994,13 @@ void CL_ParseLegacyServerMessage( sizebuf_t *msg, qboolean normal_message )
case svc_stufftext: case svc_stufftext:
s = MSG_ReadString( msg ); s = MSG_ReadString( msg );
#ifdef HACKS_RELATED_HLMODS #ifdef HACKS_RELATED_HLMODS
// disable Cry Of Fear antisave protection // dsiable Cry Of Fear antisave protection
if( !Q_strnicmp( s, "disconnect", 10 ) && cls.signon != SIGNONS ) if( !Q_strnicmp( s, "disconnect", 10 ) && cls.signon != SIGNONS )
break; // too early break; // too early
#endif #endif
Con_Reportf( "Stufftext: %s", s ); Con_Reportf( "Stufftext: %s", s );
Cbuf_AddFilteredText( s ); Cbuf_AddText( s );
break; break;
case svc_setangle: case svc_setangle:
CL_ParseSetAngle( msg ); CL_ParseSetAngle( msg );
@@ -3150,14 +3156,20 @@ void CL_ParseLegacyServerMessage( sizebuf_t *msg, qboolean normal_message )
case svc_director: case svc_director:
CL_ParseDirector( msg ); CL_ParseDirector( msg );
break; break;
case svc_voiceinit:
CL_ParseVoiceInit( msg );
break;
case svc_voicedata:
CL_ParseVoiceData( msg );
break;
case svc_resourcelocation: case svc_resourcelocation:
CL_ParseResLocation( msg ); CL_ParseResLocation( msg );
break; break;
case svc_querycvarvalue: case svc_querycvarvalue:
CL_ParseCvarValue( msg, false ); CL_ParseCvarValue( msg );
break; break;
case svc_querycvarvalue2: case svc_querycvarvalue2:
CL_ParseCvarValue( msg, true ); CL_ParseCvarValue2( msg );
break; break;
default: default:
CL_ParseUserMessage( msg, cmd ); CL_ParseUserMessage( msg, cmd );

View File

@@ -794,8 +794,6 @@ static float GAME_EXPORT pfnTraceModel( physent_t *pe, float *start, float *end,
matrix4x4 matrix; matrix4x4 matrix;
hull_t *hull; hull_t *hull;
PM_InitTrace( trace, end );
old_usehull = clgame.pmove->usehull; old_usehull = clgame.pmove->usehull;
clgame.pmove->usehull = 2; clgame.pmove->usehull = 2;
@@ -994,6 +992,7 @@ void CL_SetupPMove( playermove_t *pmove, local_state_t *from, usercmd_t *ucmd, q
pmove->flFallVelocity = ps->flFallVelocity; pmove->flFallVelocity = ps->flFallVelocity;
pmove->flSwimTime = cd->flSwimTime; pmove->flSwimTime = cd->flSwimTime;
VectorCopy( cd->punchangle, pmove->punchangle ); VectorCopy( cd->punchangle, pmove->punchangle );
pmove->flSwimTime = cd->flSwimTime;
pmove->flNextPrimaryAttack = 0.0f; // not used by PM_ code pmove->flNextPrimaryAttack = 0.0f; // not used by PM_ code
pmove->effects = ps->effects; pmove->effects = ps->effects;
pmove->flags = cd->flags; pmove->flags = cd->flags;

View File

@@ -825,9 +825,6 @@ CL_QuakeStuffText
void CL_QuakeStuffText( const char *text ) void CL_QuakeStuffText( const char *text )
{ {
Q_strncat( cmd_buf, text, sizeof( cmd_buf )); Q_strncat( cmd_buf, text, sizeof( cmd_buf ));
// a1ba: didn't filtered, anyway quake protocol
// only supported for demos, not network games
Cbuf_AddText( text ); Cbuf_AddText( text );
} }
@@ -864,7 +861,7 @@ void CL_QuakeExecStuff( void )
if( !*text ) break; if( !*text ) break;
text = COM_ParseFileSafe( text, token, sizeof( token ), PFILE_IGNOREBRACKET, NULL, NULL ); text = _COM_ParseFileSafe( text, token, sizeof( token ), PFILE_IGNOREBRACKET, NULL );
if( !text ) break; if( !text ) break;

View File

@@ -117,7 +117,7 @@ static void R_EnvShot( const float *vieworg, const char *name, qboolean skyshot,
else cls.scrshot_action = scrshot_envshot; else cls.scrshot_action = scrshot_envshot;
// catch negative values // catch negative values
cls.envshot_viewsize = Q_max( 0, shotsize ); cls.envshot_viewsize = max( 0, shotsize );
} }
/* /*

View File

@@ -418,6 +418,7 @@ void SCR_BeginLoadingPlaque( qboolean is_background )
cls.draw_changelevel = !is_background; cls.draw_changelevel = !is_background;
SCR_UpdateScreen(); SCR_UpdateScreen();
cls.disable_screen = host.realtime; cls.disable_screen = host.realtime;
cls.disable_servercount = cl.servercount;
cl.background = is_background; // set right state before svc_serverdata is came cl.background = is_background; // set right state before svc_serverdata is came
if( !Host_IsDedicated() ) if( !Host_IsDedicated() )
@@ -780,7 +781,6 @@ SCR_VidInit
*/ */
void SCR_VidInit( void ) void SCR_VidInit( void )
{ {
string libpath;
if( !ref.initialized ) // don't call VidInit too soon if( !ref.initialized ) // don't call VidInit too soon
return; return;
@@ -795,8 +795,7 @@ void SCR_VidInit( void )
gameui.globals->scrHeight = refState.height; gameui.globals->scrHeight = refState.height;
} }
COM_GetCommonLibraryPath( LIBRARY_CLIENT, libpath, sizeof( libpath )); VGui_Startup( NULL, refState.width, refState.height ); // initialized already, so pass NULL
VGui_Startup( libpath, refState.width, refState.height );
CL_ClearSpriteTextures(); // now all hud sprites are invalid CL_ClearSpriteTextures(); // now all hud sprites are invalid

View File

@@ -1,460 +0,0 @@
/*
cl_securedstub.c - secured client dll stub
Copyright (C) 2022 FWGS
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
*/
#include "common.h"
#include "client.h"
typedef struct cldll_func_src_s
{
int (*pfnInitialize)( cl_enginefunc_t *pEnginefuncs, int iVersion );
void (*pfnInit)( void );
int (*pfnVidInit)( void );
int (*pfnRedraw)( float flTime, int intermission );
int (*pfnUpdateClientData)( client_data_t *cdata, float flTime );
void (*pfnReset)( void );
void (*pfnPlayerMove)( struct playermove_s *ppmove, int server );
void (*pfnPlayerMoveInit)( struct playermove_s *ppmove );
char (*pfnPlayerMoveTexture)( char *name );
void (*IN_ActivateMouse)( void );
void (*IN_DeactivateMouse)( void );
void (*IN_MouseEvent)( int mstate );
void (*IN_ClearStates)( void );
void (*IN_Accumulate)( void );
void (*CL_CreateMove)( float frametime, struct usercmd_s *cmd, int active );
int (*CL_IsThirdPerson)( void );
void (*CL_CameraOffset)( float *ofs ); // unused
void *(*KB_Find)( const char *name );
void (*CAM_Think)( void ); // camera stuff
void (*pfnCalcRefdef)( ref_params_t *pparams );
int (*pfnAddEntity)( int type, cl_entity_t *ent, const char *modelname );
void (*pfnCreateEntities)( void );
void (*pfnDrawNormalTriangles)( void );
void (*pfnDrawTransparentTriangles)( void );
void (*pfnStudioEvent)( const struct mstudioevent_s *event, const cl_entity_t *entity );
void (*pfnPostRunCmd)( struct local_state_s *from, struct local_state_s *to, usercmd_t *cmd, int runfuncs, double time, unsigned int random_seed );
void (*pfnShutdown)( void );
void (*pfnTxferLocalOverrides)( entity_state_t *state, const clientdata_t *client );
void (*pfnProcessPlayerState)( entity_state_t *dst, const entity_state_t *src );
void (*pfnTxferPredictionData)( entity_state_t *ps, const entity_state_t *pps, clientdata_t *pcd, const clientdata_t *ppcd, weapon_data_t *wd, const weapon_data_t *pwd );
void (*pfnDemo_ReadBuffer)( int size, byte *buffer );
int (*pfnConnectionlessPacket)( const struct netadr_s *net_from, const char *args, char *buffer, int *size );
int (*pfnGetHullBounds)( int hullnumber, float *mins, float *maxs );
void (*pfnFrame)( double time );
int (*pfnKey_Event)( int eventcode, int keynum, const char *pszCurrentBinding );
void (*pfnTempEntUpdate)( double frametime, double client_time, double cl_gravity, struct tempent_s **ppTempEntFree, struct tempent_s **ppTempEntActive, int ( *Callback_AddVisibleEntity )( cl_entity_t *pEntity ), void ( *Callback_TempEntPlaySound )( struct tempent_s *pTemp, float damp ));
cl_entity_t *(*pfnGetUserEntity)( int index );
void (*pfnVoiceStatus)( int entindex, qboolean bTalking );
void (*pfnDirectorMessage)( int iSize, void *pbuf );
int (*pfnGetStudioModelInterface)( int version, struct r_studio_interface_s **ppinterface, struct engine_studio_api_s *pstudio );
void (*pfnChatInputPosition)( int *x, int *y );
int (*pfnGetPlayerTeam)( int iPlayer );
void *(*pfnClientFactory)( void );
} cldll_func_src_t;
typedef struct cldll_func_dst_s
{
void (*pfnInitialize)( cl_enginefunc_t **pEnginefuncs, int *iVersion );
void (*pfnInit)( void );
void (*pfnVidInit)( void );
void (*pfnRedraw)( float *flTime, int *intermission );
void (*pfnUpdateClientData)( client_data_t **cdata, float *flTime );
void (*pfnReset)( void );
void (*pfnPlayerMove)( struct playermove_s **ppmove, int *server );
void (*pfnPlayerMoveInit)( struct playermove_s **ppmove );
void (*pfnPlayerMoveTexture)( char **name );
void (*IN_ActivateMouse)( void );
void (*IN_DeactivateMouse)( void );
void (*IN_MouseEvent)( int *mstate );
void (*IN_ClearStates)( void );
void (*IN_Accumulate)( void );
void (*CL_CreateMove)( float *frametime, struct usercmd_s **cmd, int *active );
void (*CL_IsThirdPerson)( void );
void (*CL_CameraOffset)( float **ofs );
void (*KB_Find)( const char **name );
void (*CAM_Think)( void );
void (*pfnCalcRefdef)( ref_params_t **pparams );
void (*pfnAddEntity)( int *type, cl_entity_t **ent, const char **modelname );
void (*pfnCreateEntities)( void );
void (*pfnDrawNormalTriangles)( void );
void (*pfnDrawTransparentTriangles)( void );
void (*pfnStudioEvent)( const struct mstudioevent_s **event, const cl_entity_t **entity );
void (*pfnPostRunCmd)( struct local_state_s **from, struct local_state_s **to, usercmd_t **cmd, int *runfuncs, double *time, unsigned int *random_seed );
void (*pfnShutdown)( void );
void (*pfnTxferLocalOverrides)( entity_state_t **state, const clientdata_t **client );
void (*pfnProcessPlayerState)( entity_state_t **dst, const entity_state_t **src );
void (*pfnTxferPredictionData)( entity_state_t **ps, const entity_state_t **pps, clientdata_t **pcd, const clientdata_t **ppcd, weapon_data_t **wd, const weapon_data_t **pwd );
void (*pfnDemo_ReadBuffer)( int *size, byte **buffer );
void (*pfnConnectionlessPacket)( const struct netadr_s **net_from, const char **args, char **buffer, int **size );
void (*pfnGetHullBounds)( int *hullnumber, float **mins, float **maxs );
void (*pfnFrame)( double *time );
void (*pfnKey_Event)( int *eventcode, int *keynum, const char **pszCurrentBinding );
void (*pfnTempEntUpdate)( double *frametime, double *client_time, double *cl_gravity, struct tempent_s ***ppTempEntFree, struct tempent_s ***ppTempEntActive, int ( **Callback_AddVisibleEntity )( cl_entity_t *pEntity ), void ( **Callback_TempEntPlaySound )( struct tempent_s *pTemp, float damp ));
void (*pfnGetUserEntity)( int *index );
void (*pfnVoiceStatus)( int *entindex, qboolean *bTalking );
void (*pfnDirectorMessage)( int *iSize, void **pbuf );
void (*pfnGetStudioModelInterface)( int *version, struct r_studio_interface_s ***ppinterface, struct engine_studio_api_s **pstudio );
void (*pfnChatInputPosition)( int **x, int **y );
void (*pfnGetPlayerTeam)( int *iPlayer );
} cldll_func_dst_t;
struct cl_enginefunc_dst_s;
struct modshelpers_s;
struct modchelpers_s;
struct engdata_s;
typedef struct modfuncs_s
{
void (*m_pfnLoadMod)( char *pchModule );
void (*m_pfnCloseMod)( void );
int (*m_pfnNCall)( int ijump, int cnArg, ... );
void (*m_pfnGetClDstAddrs)( cldll_func_dst_t *pcldstAddrs );
void (*m_pfnGetEngDstAddrs)( struct cl_enginefunc_dst_s *pengdstAddrs );
void (*m_pfnModuleLoaded)( void );
void (*m_pfnProcessOutgoingNet)( struct netchan_s *pchan, struct sizebuf_s *psizebuf );
qboolean (*m_pfnProcessIncomingNet)( struct netchan_s *pchan, struct sizebuf_s *psizebuf );
void (*m_pfnTextureLoad)( char *pszName, int dxWidth, int dyHeight, char *pbData );
void (*m_pfnModelLoad)( struct model_s *pmodel, void *pvBuf );
void (*m_pfnFrameBegin)( void );
void (*m_pfnFrameRender1)( void );
void (*m_pfnFrameRender2)( void );
void (*m_pfnSetModSHelpers)( struct modshelpers_s *pmodshelpers );
void (*m_pfnSetModCHelpers)( struct modchelpers_s *pmodchelpers );
void (*m_pfnSetEngData)( struct engdata_s *pengdata );
int m_nVersion;
void (*m_pfnConnectClient)( int iPlayer );
void (*m_pfnRecordIP)( unsigned int pnIP );
void (*m_pfnPlayerStatus)( unsigned char *pbData, int cbData );
void (*m_pfnSetEngineVersion)( int nVersion );
int m_nVoid2;
int m_nVoid3;
int m_nVoid4;
int m_nVoid5;
int m_nVoid6;
int m_nVoid7;
int m_nVoid8;
int m_nVoid9;
} modfuncs_t;
static void DstInitialize( cl_enginefunc_t **pEnginefuncs, int *iVersion )
{
// stub
}
static void DstInit( void )
{
// stub
}
static void DstVidInit( void )
{
// stub
}
static void DstRedraw( float *flTime, int *intermission )
{
// stub
}
static void DstUpdateClientData( client_data_t **cdata, float *flTime )
{
// stub
}
static void DstReset( void )
{
// stub
}
static void DstPlayerMove( struct playermove_s **ppmove, int *server )
{
// stub
}
static void DstPlayerMoveInit( struct playermove_s **ppmove )
{
// stub
}
static void DstPlayerMoveTexture( char **name )
{
// stub
}
static void DstIN_ActivateMouse( void )
{
// stub
}
static void DstIN_DeactivateMouse( void )
{
// stub
}
static void DstIN_MouseEvent( int *mstate )
{
// stub
}
static void DstIN_ClearStates( void )
{
// stub
}
static void DstIN_Accumulate( void )
{
// stub
}
static void DstCL_CreateMove( float *frametime, struct usercmd_s **cmd, int *active )
{
// stub
}
static void DstCL_IsThirdPerson( void )
{
// stub
}
static void DstCL_CameraOffset( float **ofs )
{
// stub
}
static void DstKB_Find( const char **name )
{
// stub
}
static void DstCAM_Think( void )
{
// stub
}
static void DstCalcRefdef( ref_params_t **pparams )
{
// stub
}
static void DstAddEntity( int *type, cl_entity_t **ent, const char **modelname )
{
// stub
}
static void DstCreateEntities( void )
{
// stub
}
static void DstDrawNormalTriangles( void )
{
// stub
}
static void DstDrawTransparentTriangles( void )
{
// stub
}
static void DstStudioEvent( const struct mstudioevent_s **event, const cl_entity_t **entity )
{
// stub
}
static void DstPostRunCmd( struct local_state_s **from, struct local_state_s **to, usercmd_t **cmd, int *runfuncs, double *time, unsigned int *random_seed )
{
// stub
}
static void DstShutdown( void )
{
// stub
}
static void DstTxferLocalOverrides( entity_state_t **state, const clientdata_t **client )
{
// stub
}
static void DstProcessPlayerState( entity_state_t **dst, const entity_state_t **src )
{
// stub
}
static void DstTxferPredictionData( entity_state_t **ps, const entity_state_t **pps, clientdata_t **pcd, const clientdata_t **ppcd, weapon_data_t **wd, const weapon_data_t **pwd )
{
// stub
}
static void DstDemo_ReadBuffer( int *size, byte **buffer )
{
// stub
}
static void DstConnectionlessPacket( const struct netadr_s **net_from, const char **args, char **buffer, int **size )
{
// stub
}
static void DstGetHullBounds( int *hullnumber, float **mins, float **maxs )
{
// stub
}
static void DstFrame( double *time )
{
// stub
}
static void DstKey_Event( int *eventcode, int *keynum, const char **pszCurrentBinding )
{
// stub
}
static void DstTempEntUpdate( double *frametime, double *client_time, double *cl_gravity, struct tempent_s ***ppTempEntFree, struct tempent_s ***ppTempEntActive, int ( **Callback_AddVisibleEntity )( cl_entity_t *pEntity ), void ( **Callback_TempEntPlaySound )( struct tempent_s *pTemp, float damp ) )
{
// stub
}
static void DstGetUserEntity( int *index )
{
// stub
}
static void DstVoiceStatus( int *entindex, qboolean *bTalking )
{
// stub
}
static void DstDirectorMessage( int *iSize, void **pbuf )
{
// stub
}
static void DstGetStudioModelInterface( int *version, struct r_studio_interface_s ***ppinterface, struct engine_studio_api_s **pstudio )
{
// stub
}
static void DstChatInputPosition( int **x, int **y )
{
// stub
}
static void DstGetPlayerTeam( int *iPlayer )
{
// stub
}
static cldll_func_dst_t cldllFuncDst =
{
DstInitialize,
DstInit,
DstVidInit,
DstRedraw,
DstUpdateClientData,
DstReset,
DstPlayerMove,
DstPlayerMoveInit,
DstPlayerMoveTexture,
DstIN_ActivateMouse,
DstIN_DeactivateMouse,
DstIN_MouseEvent,
DstIN_ClearStates,
DstIN_Accumulate,
DstCL_CreateMove,
DstCL_IsThirdPerson,
DstCL_CameraOffset,
DstKB_Find,
DstCAM_Think,
DstCalcRefdef,
DstAddEntity,
DstCreateEntities,
DstDrawNormalTriangles,
DstDrawTransparentTriangles,
DstStudioEvent,
DstPostRunCmd,
DstShutdown,
DstTxferLocalOverrides,
DstProcessPlayerState,
DstTxferPredictionData,
DstDemo_ReadBuffer,
DstConnectionlessPacket,
DstGetHullBounds,
DstFrame,
DstKey_Event,
DstTempEntUpdate,
DstGetUserEntity,
DstVoiceStatus,
DstDirectorMessage,
DstGetStudioModelInterface,
DstChatInputPosition,
DstGetPlayerTeam,
};
void CL_GetSecuredClientAPI( CL_EXPORT_FUNCS F )
{
cldll_func_src_t cldllFuncSrc = { 0 };
modfuncs_t modFuncs = { 0 };
// secured client dlls need these
*(cldll_func_dst_t **)&cldllFuncSrc.pfnVidInit = &cldllFuncDst;
*(modfuncs_t **)&cldllFuncSrc.pfnInitialize = &modFuncs;
// trying to fill interface now
F( &cldllFuncSrc );
// map exports to xash's cldll_func_t
clgame.dllFuncs.pfnInitialize = cldllFuncSrc.pfnInitialize;
clgame.dllFuncs.pfnInit = cldllFuncSrc.pfnInit;
clgame.dllFuncs.pfnVidInit = cldllFuncSrc.pfnVidInit;
clgame.dllFuncs.pfnRedraw = cldllFuncSrc.pfnRedraw;
clgame.dllFuncs.pfnUpdateClientData = cldllFuncSrc.pfnUpdateClientData;
clgame.dllFuncs.pfnReset = cldllFuncSrc.pfnReset;
clgame.dllFuncs.pfnPlayerMove = cldllFuncSrc.pfnPlayerMove;
clgame.dllFuncs.pfnPlayerMoveInit = cldllFuncSrc.pfnPlayerMoveInit;
clgame.dllFuncs.pfnPlayerMoveTexture = cldllFuncSrc.pfnPlayerMoveTexture;
clgame.dllFuncs.IN_ActivateMouse = cldllFuncSrc.IN_ActivateMouse;
clgame.dllFuncs.IN_DeactivateMouse = cldllFuncSrc.IN_DeactivateMouse;
clgame.dllFuncs.IN_MouseEvent = cldllFuncSrc.IN_MouseEvent;
clgame.dllFuncs.IN_ClearStates = cldllFuncSrc.IN_ClearStates;
clgame.dllFuncs.IN_Accumulate = cldllFuncSrc.IN_Accumulate;
clgame.dllFuncs.CL_CreateMove = cldllFuncSrc.CL_CreateMove;
clgame.dllFuncs.CL_IsThirdPerson = cldllFuncSrc.CL_IsThirdPerson;
clgame.dllFuncs.CL_CameraOffset = cldllFuncSrc.CL_CameraOffset;
clgame.dllFuncs.KB_Find = cldllFuncSrc.KB_Find;
clgame.dllFuncs.CAM_Think = cldllFuncSrc.CAM_Think;
clgame.dllFuncs.pfnCalcRefdef = cldllFuncSrc.pfnCalcRefdef;
clgame.dllFuncs.pfnAddEntity = cldllFuncSrc.pfnAddEntity;
clgame.dllFuncs.pfnCreateEntities = cldllFuncSrc.pfnCreateEntities;
clgame.dllFuncs.pfnDrawNormalTriangles = cldllFuncSrc.pfnDrawNormalTriangles;
clgame.dllFuncs.pfnDrawTransparentTriangles = cldllFuncSrc.pfnDrawTransparentTriangles;
clgame.dllFuncs.pfnStudioEvent = cldllFuncSrc.pfnStudioEvent;
clgame.dllFuncs.pfnPostRunCmd = cldllFuncSrc.pfnPostRunCmd;
clgame.dllFuncs.pfnShutdown = cldllFuncSrc.pfnShutdown;
clgame.dllFuncs.pfnTxferLocalOverrides = cldllFuncSrc.pfnTxferLocalOverrides;
clgame.dllFuncs.pfnProcessPlayerState = cldllFuncSrc.pfnProcessPlayerState;
clgame.dllFuncs.pfnTxferPredictionData = cldllFuncSrc.pfnTxferPredictionData;
clgame.dllFuncs.pfnDemo_ReadBuffer = cldllFuncSrc.pfnDemo_ReadBuffer;
clgame.dllFuncs.pfnConnectionlessPacket = cldllFuncSrc.pfnConnectionlessPacket;
clgame.dllFuncs.pfnGetHullBounds = cldllFuncSrc.pfnGetHullBounds;
clgame.dllFuncs.pfnFrame = cldllFuncSrc.pfnFrame;
clgame.dllFuncs.pfnKey_Event = cldllFuncSrc.pfnKey_Event;
clgame.dllFuncs.pfnTempEntUpdate = cldllFuncSrc.pfnTempEntUpdate;
clgame.dllFuncs.pfnGetUserEntity = cldllFuncSrc.pfnGetUserEntity;
clgame.dllFuncs.pfnVoiceStatus = cldllFuncSrc.pfnVoiceStatus;
clgame.dllFuncs.pfnDirectorMessage = cldllFuncSrc.pfnDirectorMessage;
clgame.dllFuncs.pfnGetStudioModelInterface = cldllFuncSrc.pfnGetStudioModelInterface;
clgame.dllFuncs.pfnChatInputPosition = cldllFuncSrc.pfnChatInputPosition;
}

View File

@@ -361,8 +361,8 @@ void CL_TempEntPlaySound( TEMPENTITY *pTemp, float damp )
sound_t handle; sound_t handle;
if( isshellcasing ) if( isshellcasing )
fvol *= Q_min( 1.0f, ((float)zvel) / 350.0f ); fvol *= min ( 1.0f, ((float)zvel) / 350.0f );
else fvol *= Q_min( 1.0f, ((float)zvel) / 450.0f ); else fvol *= min ( 1.0f, ((float)zvel) / 450.0f );
if( !COM_RandomLong( 0, 3 ) && !isshellcasing ) if( !COM_RandomLong( 0, 3 ) && !isshellcasing )
pitch = COM_RandomLong( 95, 105 ); pitch = COM_RandomLong( 95, 105 );
@@ -1482,6 +1482,7 @@ void GAME_EXPORT R_FunnelSprite( const vec3_t org, int modelIndex, int reverse )
pTemp->entity.baseline.angles[2] = COM_RandomFloat( -100.0f, 100.0f ); pTemp->entity.baseline.angles[2] = COM_RandomFloat( -100.0f, 100.0f );
pTemp->entity.curstate.framerate = COM_RandomFloat( 0.1f, 0.4f ); pTemp->entity.curstate.framerate = COM_RandomFloat( 0.1f, 0.4f );
pTemp->flags = FTENT_ROTATE|FTENT_FADEOUT; pTemp->flags = FTENT_ROTATE|FTENT_FADEOUT;
pTemp->entity.curstate.framerate = 10;
vel = dest[2] / 8.0f; vel = dest[2] / 8.0f;
if( vel < 64.0f ) vel = 64.0f; if( vel < 64.0f ) vel = 64.0f;
@@ -1514,18 +1515,17 @@ R_RicochetSound
Make a random ricochet sound Make a random ricochet sound
============== ==============
*/ */
static void R_RicochetSound_( const vec3_t pos, int sound )
{
sound_t handle;
handle = S_RegisterSound( cl_ricochet_sounds[sound] );
S_StartSound( pos, 0, CHAN_AUTO, handle, VOL_NORM, 1.0, 100, 0 );
}
void GAME_EXPORT R_RicochetSound( const vec3_t pos ) void GAME_EXPORT R_RicochetSound( const vec3_t pos )
{ {
R_RicochetSound_( pos, COM_RandomLong( 0, 4 )); int iPitch = COM_RandomLong( 90, 105 );
float fvol = COM_RandomFloat( 0.7f, 0.9f );
char soundpath[32];
sound_t handle;
Q_strncpy( soundpath, cl_ricochet_sounds[COM_RandomLong( 0, 4 )], sizeof( soundpath ) );
handle = S_RegisterSound( soundpath );
S_StartSound( pos, 0, CHAN_AUTO, handle, fvol, ATTN_NORM, iPitch, 0 );
} }
/* /*
@@ -1656,7 +1656,7 @@ void GAME_EXPORT R_Explosion( vec3_t pos, int model, float scale, float framerat
dl->color.g = 250; dl->color.g = 250;
dl->color.b = 150; dl->color.b = 150;
dl->die = cl.time + 0.01f; dl->die = cl.time + 0.01f;
dl->decay = 800; dl->decay = 80;
// red glow // red glow
dl = CL_AllocDlight( 0 ); dl = CL_AllocDlight( 0 );
@@ -1904,7 +1904,7 @@ handle temp-entity messages
void CL_ParseTempEntity( sizebuf_t *msg ) void CL_ParseTempEntity( sizebuf_t *msg )
{ {
sizebuf_t buf; sizebuf_t buf;
byte pbuf[2048]; byte pbuf[256];
int iSize; int iSize;
int type, color, count, flags; int type, color, count, flags;
int decalIndex, modelIndex, entityIndex; int decalIndex, modelIndex, entityIndex;
@@ -1915,7 +1915,6 @@ void CL_ParseTempEntity( sizebuf_t *msg )
TEMPENTITY *pTemp; TEMPENTITY *pTemp;
cl_entity_t *pEnt; cl_entity_t *pEnt;
dlight_t *dl; dlight_t *dl;
sound_t hSound;
if( cls.legacymode ) if( cls.legacymode )
iSize = MSG_ReadByte( msg ); iSize = MSG_ReadByte( msg );
@@ -1923,10 +1922,6 @@ void CL_ParseTempEntity( sizebuf_t *msg )
decalIndex = modelIndex = entityIndex = 0; decalIndex = modelIndex = entityIndex = 0;
// this will probably be fatal anyway
if( iSize > sizeof( pbuf ))
Con_Printf( S_ERROR "%s: Temp buffer overflow!\n", __FUNCTION__ );
// parse user message into buffer // parse user message into buffer
MSG_ReadBytes( msg, pbuf, iSize ); MSG_ReadBytes( msg, pbuf, iSize );
@@ -1974,9 +1969,6 @@ void CL_ParseTempEntity( sizebuf_t *msg )
pos[1] = MSG_ReadCoord( &buf ); pos[1] = MSG_ReadCoord( &buf );
pos[2] = MSG_ReadCoord( &buf ); pos[2] = MSG_ReadCoord( &buf );
R_BlobExplosion( pos ); R_BlobExplosion( pos );
hSound = S_RegisterSound( cl_explode_sounds[0] );
S_StartSound( pos, -1, CHAN_AUTO, hSound, VOL_NORM, 1.0f, PITCH_NORM, 0 );
break; break;
case TE_SMOKE: case TE_SMOKE:
pos[0] = MSG_ReadCoord( &buf ); pos[0] = MSG_ReadCoord( &buf );
@@ -2022,46 +2014,15 @@ void CL_ParseTempEntity( sizebuf_t *msg )
color = MSG_ReadByte( &buf ); color = MSG_ReadByte( &buf );
count = MSG_ReadByte( &buf ); count = MSG_ReadByte( &buf );
R_ParticleExplosion2( pos, color, count ); R_ParticleExplosion2( pos, color, count );
dl = CL_AllocDlight( 0 );
VectorCopy( pos, dl->origin );
dl->radius = 350;
dl->die = cl.time + 0.5;
dl->decay = 300;
hSound = S_RegisterSound( cl_explode_sounds[0] );
S_StartSound( pos, -1, CHAN_AUTO, hSound, VOL_NORM, 0.6f, PITCH_NORM, 0 );
break; break;
case TE_BSPDECAL: case TE_BSPDECAL:
case TE_DECAL:
case TE_WORLDDECAL:
case TE_WORLDDECALHIGH:
case TE_DECALHIGH:
pos[0] = MSG_ReadCoord( &buf ); pos[0] = MSG_ReadCoord( &buf );
pos[1] = MSG_ReadCoord( &buf ); pos[1] = MSG_ReadCoord( &buf );
pos[2] = MSG_ReadCoord( &buf ); pos[2] = MSG_ReadCoord( &buf );
if( type == TE_BSPDECAL ) decalIndex = MSG_ReadShort( &buf );
{ entityIndex = MSG_ReadShort( &buf );
decalIndex = MSG_ReadShort( &buf ); if( entityIndex ) modelIndex = MSG_ReadShort( &buf );
entityIndex = MSG_ReadShort( &buf ); CL_DecalShoot( CL_DecalIndex( decalIndex ), entityIndex, modelIndex, pos, FDECAL_PERMANENT );
if( entityIndex )
modelIndex = MSG_ReadShort( &buf );
else modelIndex = 0;
}
else
{
decalIndex = MSG_ReadByte( &buf );
if( type == TE_DECALHIGH || type == TE_WORLDDECALHIGH )
decalIndex += 256;
if( type == TE_DECALHIGH || type == TE_DECAL )
entityIndex = MSG_ReadShort( &buf );
else entityIndex = 0;
pEnt = CL_GetEntityByIndex( entityIndex );
modelIndex = pEnt->curstate.modelindex;
}
CL_DecalShoot( CL_DecalIndex( decalIndex ), entityIndex, modelIndex, pos, type == TE_BSPDECAL ? FDECAL_PERMANENT : 0 );
break; break;
case TE_IMPLOSION: case TE_IMPLOSION:
pos[0] = MSG_ReadCoord( &buf ); pos[0] = MSG_ReadCoord( &buf );
@@ -2081,12 +2042,10 @@ void CL_ParseTempEntity( sizebuf_t *msg )
pos2[2] = MSG_ReadCoord( &buf ); pos2[2] = MSG_ReadCoord( &buf );
modelIndex = MSG_ReadShort( &buf ); modelIndex = MSG_ReadShort( &buf );
count = MSG_ReadByte( &buf ); count = MSG_ReadByte( &buf );
life = (float)MSG_ReadByte( &buf ) * 0.1f; life = (float)(MSG_ReadByte( &buf ) * 0.1f);
scale = (float)MSG_ReadByte( &buf ); scale = (float)(MSG_ReadByte( &buf ) * 0.1f);
if( !scale ) scale = 1.0f; vel = (float)MSG_ReadByte( &buf );
else scale *= 0.1f; random = (float)MSG_ReadByte( &buf );
vel = (float)MSG_ReadByte( &buf ) * 10;
random = (float)MSG_ReadByte( &buf ) * 10;
R_Sprite_Trail( type, pos, pos2, modelIndex, count, life, scale, random, 255, vel ); R_Sprite_Trail( type, pos, pos2, modelIndex, count, life, scale, random, 255, vel );
break; break;
case TE_SPRITE: case TE_SPRITE:
@@ -2094,23 +2053,36 @@ void CL_ParseTempEntity( sizebuf_t *msg )
pos[1] = MSG_ReadCoord( &buf ); pos[1] = MSG_ReadCoord( &buf );
pos[2] = MSG_ReadCoord( &buf ); pos[2] = MSG_ReadCoord( &buf );
modelIndex = MSG_ReadShort( &buf ); modelIndex = MSG_ReadShort( &buf );
scale = (float)MSG_ReadByte( &buf ) * 0.1f; scale = (float)(MSG_ReadByte( &buf ) * 0.1f);
brightness = (float)MSG_ReadByte( &buf ) / 255.0f; brightness = (float)MSG_ReadByte( &buf );
R_TempSprite( pos, vec3_origin, scale, modelIndex, if(( pTemp = R_DefaultSprite( pos, modelIndex, 0 )) != NULL )
kRenderTransAdd, kRenderFxNone, brightness, 0.0, FTENT_SPRANIMATE ); {
pTemp->entity.curstate.scale = scale;
pTemp->entity.baseline.renderamt = brightness;
pTemp->entity.curstate.renderamt = brightness;
pTemp->entity.curstate.rendermode = kRenderTransAdd;
}
break; break;
case TE_GLOWSPRITE: case TE_GLOWSPRITE:
pos[0] = MSG_ReadCoord( &buf ); pos[0] = MSG_ReadCoord( &buf );
pos[1] = MSG_ReadCoord( &buf ); pos[1] = MSG_ReadCoord( &buf );
pos[2] = MSG_ReadCoord( &buf ); pos[2] = MSG_ReadCoord( &buf );
modelIndex = MSG_ReadShort( &buf ); modelIndex = MSG_ReadShort( &buf );
life = (float)MSG_ReadByte( &buf ) * 0.1f; life = (float)(MSG_ReadByte( &buf ) * 0.1f);
scale = (float)MSG_ReadByte( &buf ) * 0.1f; scale = (float)(MSG_ReadByte( &buf ) * 0.1f);
brightness = (float)MSG_ReadByte( &buf ) / 255.0f; brightness = (float)MSG_ReadByte( &buf );
R_TempSprite( pos, vec3_origin, scale, modelIndex, if(( pTemp = R_DefaultSprite( pos, modelIndex, 0 )) != NULL )
kRenderGlow, kRenderFxNoDissipation, brightness, life, FTENT_FADEOUT ); {
pTemp->entity.curstate.scale = scale;
pTemp->entity.curstate.rendermode = kRenderGlow;
pTemp->entity.curstate.renderfx = kRenderFxNoDissipation;
pTemp->entity.baseline.renderamt = brightness;
pTemp->entity.curstate.renderamt = brightness;
pTemp->flags = FTENT_FADEOUT;
pTemp->die = cl.time + life;
}
break; break;
case TE_STREAK_SPLASH: case TE_STREAK_SPLASH:
pos[0] = MSG_ReadCoord( &buf ); pos[0] = MSG_ReadCoord( &buf );
@@ -2200,6 +2172,23 @@ void CL_ParseTempEntity( sizebuf_t *msg )
pos2[2] = MSG_ReadCoord( &buf ); pos2[2] = MSG_ReadCoord( &buf );
R_ShowLine( pos, pos2 ); R_ShowLine( pos, pos2 );
break; break;
case TE_DECAL:
case TE_DECALHIGH:
case TE_WORLDDECAL:
case TE_WORLDDECALHIGH:
pos[0] = MSG_ReadCoord( &buf );
pos[1] = MSG_ReadCoord( &buf );
pos[2] = MSG_ReadCoord( &buf );
decalIndex = MSG_ReadByte( &buf );
if( type == TE_DECAL || type == TE_DECALHIGH )
entityIndex = MSG_ReadShort( &buf );
else entityIndex = 0;
if( type == TE_DECALHIGH || type == TE_WORLDDECALHIGH )
decalIndex += 256;
pEnt = CL_GetEntityByIndex( entityIndex );
if( pEnt ) modelIndex = pEnt->curstate.modelindex;
CL_DecalShoot( CL_DecalIndex( decalIndex ), entityIndex, modelIndex, pos, 0 );
break;
case TE_FIZZ: case TE_FIZZ:
entityIndex = MSG_ReadShort( &buf ); entityIndex = MSG_ReadShort( &buf );
modelIndex = MSG_ReadShort( &buf ); modelIndex = MSG_ReadShort( &buf );
@@ -2255,11 +2244,10 @@ void CL_ParseTempEntity( sizebuf_t *msg )
pos[2] = MSG_ReadCoord( &buf ); pos[2] = MSG_ReadCoord( &buf );
entityIndex = MSG_ReadShort( &buf ); entityIndex = MSG_ReadShort( &buf );
decalIndex = MSG_ReadByte( &buf ); decalIndex = MSG_ReadByte( &buf );
pEnt = CL_GetEntityByIndex( entityIndex );
CL_DecalShoot( CL_DecalIndex( decalIndex ), entityIndex, 0, pos, 0 ); CL_DecalShoot( CL_DecalIndex( decalIndex ), entityIndex, 0, pos, 0 );
R_BulletImpactParticles( pos ); R_BulletImpactParticles( pos );
flags = COM_RandomLong( 0, 0x7fff ); R_RicochetSound( pos );
if( flags < 0x3fff )
R_RicochetSound_( pos, flags % 5 );
break; break;
case TE_SPRAY: case TE_SPRAY:
case TE_SPRITE_SPRAY: case TE_SPRITE_SPRAY:
@@ -2405,7 +2393,7 @@ void CL_ParseTempEntity( sizebuf_t *msg )
// throw warning // throw warning
if( MSG_CheckOverflow( &buf )) if( MSG_CheckOverflow( &buf ))
Con_DPrintf( S_WARN "ParseTempEntity: overflow TE message %i\n", type ); Con_DPrintf( S_WARN "ParseTempEntity: overflow TE message\n" );
} }
@@ -2705,7 +2693,7 @@ apply various effects to entity origin or attachment
void CL_AddEntityEffects( cl_entity_t *ent ) void CL_AddEntityEffects( cl_entity_t *ent )
{ {
// yellow flies effect 'monster stuck in the wall' // yellow flies effect 'monster stuck in the wall'
if( FBitSet( ent->curstate.effects, EF_BRIGHTFIELD ) && !RP_LOCALCLIENT( ent )) if( FBitSet( ent->curstate.effects, EF_BRIGHTFIELD ))
R_EntityParticles( ent ); R_EntityParticles( ent );
if( FBitSet( ent->curstate.effects, EF_DIMLIGHT )) if( FBitSet( ent->curstate.effects, EF_DIMLIGHT ))
@@ -2926,7 +2914,7 @@ void CL_PlayerDecal( int playernum, int customIndex, int entityIndex, float *pos
{ {
if( FBitSet( pCust->resource.ucFlags, RES_CUSTOM ) && pCust->resource.type == t_decal && pCust->bTranslated ) if( FBitSet( pCust->resource.ucFlags, RES_CUSTOM ) && pCust->resource.type == t_decal && pCust->bTranslated )
{ {
if( !pCust->nUserData1 ) if( !pCust->nUserData1 && pCust->pInfo != NULL )
{ {
const char *decalname = va( "player%dlogo%d", playernum, customIndex ); const char *decalname = va( "player%dlogo%d", playernum, customIndex );
pCust->nUserData1 = GL_LoadTextureInternal( decalname, pCust->pInfo, TF_DECAL ); pCust->nUserData1 = GL_LoadTextureInternal( decalname, pCust->pInfo, TF_DECAL );

View File

@@ -35,39 +35,30 @@ void V_CalcViewRect( void )
int sb_lines; int sb_lines;
float size; float size;
if( FBitSet( host.features, ENGINE_QUAKE_COMPATIBLE )) // intermission is always full screen
{ if( cl.intermission ) size = 120.0f;
// intermission is always full screen else size = scr_viewsize->value;
if( cl.intermission ) size = 120.0f;
else size = scr_viewsize->value;
if( size >= 120.0f ) if( size >= 120.0f )
sb_lines = 0; // no status bar at all sb_lines = 0; // no status bar at all
else if( size >= 110.0f ) else if( size >= 110.0f )
sb_lines = 24; // no inventory sb_lines = 24; // no inventory
else sb_lines = 48; else sb_lines = 48;
if( scr_viewsize->value >= 100.0f ) if( scr_viewsize->value >= 100.0f )
{
full = true;
size = 100.0f;
}
else size = scr_viewsize->value;
if( cl.intermission )
{
size = 100.0f;
sb_lines = 0;
full = true;
}
size /= 100.0f;
}
else
{ {
full = true; full = true;
sb_lines = 0; size = 100.0f;
size = 1.0f;
} }
else size = scr_viewsize->value;
if( cl.intermission )
{
size = 100.0f;
sb_lines = 0;
full = true;
}
size /= 100.0f;
clgame.viewport[2] = refState.width * size; clgame.viewport[2] = refState.width * size;
clgame.viewport[3] = refState.height * size; clgame.viewport[3] = refState.height * size;
@@ -286,6 +277,9 @@ qboolean V_PreRender( void )
if( !ref.initialized ) if( !ref.initialized )
return false; return false;
if( host.status == HOST_NOFOCUS )
return false;
if( host.status == HOST_SLEEP ) if( host.status == HOST_SLEEP )
return false; return false;

View File

@@ -33,7 +33,6 @@ GNU General Public License for more details.
#include "net_api.h" #include "net_api.h"
#include "world.h" #include "world.h"
#include "ref_common.h" #include "ref_common.h"
#include "voice.h"
// client sprite types // client sprite types
#define SPR_CLIENT 0 // client sprite for temp-entities or user-textures #define SPR_CLIENT 0 // client sprite for temp-entities or user-textures
@@ -466,7 +465,7 @@ typedef struct
string cdtracks[MAX_CDTRACKS]; // 32 cd-tracks read from cdaudio.txt string cdtracks[MAX_CDTRACKS]; // 32 cd-tracks read from cdaudio.txt
model_t sprites[MAX_CLIENT_SPRITES]; // hud&client spritetexturesz model_t sprites[MAX_CLIENT_SPRITES]; // client spritetextures
int viewport[4]; // viewport sizes int viewport[4]; // viewport sizes
client_draw_t ds; // draw2d stuff (hud, weaponmenu etc) client_draw_t ds; // draw2d stuff (hud, weaponmenu etc)
@@ -528,6 +527,9 @@ typedef struct
float disable_screen; // showing loading plaque between levels float disable_screen; // showing loading plaque between levels
// or changing rendering dlls // or changing rendering dlls
// if time gets > 30 seconds ahead, break it // if time gets > 30 seconds ahead, break it
int disable_servercount; // when we receive a frame and cl.servercount
// > cls.disable_servercount, clear disable_screen
qboolean draw_changelevel; // draw changelevel image 'Loading...' qboolean draw_changelevel; // draw changelevel image 'Loading...'
keydest_t key_dest; keydest_t key_dest;
@@ -623,6 +625,8 @@ typedef struct
// legacy mode support // legacy mode support
qboolean legacymode; // one-way 48 protocol compatibility qboolean legacymode; // one-way 48 protocol compatibility
netadr_t legacyserver; netadr_t legacyserver;
netadr_t legacyservers[MAX_LEGACY_SERVERS];
int legacyservercount;
int extensions; int extensions;
netadr_t serveradr; netadr_t serveradr;
@@ -675,6 +679,7 @@ extern convar_t *cl_fixtimerate;
extern convar_t *hud_scale; extern convar_t *hud_scale;
extern convar_t *gl_showtextures; extern convar_t *gl_showtextures;
extern convar_t *cl_bmodelinterp; extern convar_t *cl_bmodelinterp;
extern convar_t *cl_righthand;
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_messages; extern convar_t *cl_trace_messages;
@@ -703,7 +708,7 @@ dlight_t *CL_GetEntityLight( int number );
// //
// cl_cmds.c // cl_cmds.c
// //
void CL_Quit_f( void ); void CL_Quit_f( void ) NORETURN;
void CL_ScreenShot_f( void ); void CL_ScreenShot_f( void );
void CL_SnapShot_f( void ); void CL_SnapShot_f( void );
void CL_PlayCDTrack_f( void ); void CL_PlayCDTrack_f( void );
@@ -1044,6 +1049,7 @@ void Con_Bottom( void );
void Con_Top( void ); void Con_Top( void );
void Con_PageDown( int lines ); void Con_PageDown( int lines );
void Con_PageUp( int lines ); void Con_PageUp( int lines );
void Con_LoadHistory( void );
// //
// s_main.c // s_main.c
@@ -1107,11 +1113,6 @@ void pfnPIC_DrawAdditive( int x, int y, int width, int height, const wrect_t *pr
qboolean Mobile_Init( void ); qboolean Mobile_Init( void );
void Mobile_Shutdown( void ); void Mobile_Shutdown( void );
//
// cl_securedstub.c
//
void CL_GetSecuredClientAPI( CL_EXPORT_FUNCS F );
// //
// cl_video.c // cl_video.c
// //

View File

@@ -33,8 +33,6 @@ convar_t *con_color;
static int g_codepage = 0; static int g_codepage = 0;
static qboolean g_utf8 = false; static qboolean g_utf8 = false;
static qboolean g_messagemode_privileged = true;
#define CON_TIMES 4 // notify lines #define CON_TIMES 4 // notify lines
#define CON_MAX_TIMES 64 // notify max lines #define CON_MAX_TIMES 64 // notify max lines
#define COLOR_DEFAULT '7' #define COLOR_DEFAULT '7'
@@ -81,14 +79,6 @@ typedef struct con_lineinfo_s
double addtime; // notify stuff double addtime; // notify stuff
} con_lineinfo_t; } con_lineinfo_t;
typedef struct con_history_s
{
field_t lines[CON_HISTORY];
field_t backup;
int line; // the line being displayed from history buffer will be <= nextHistoryLine
int next; // the last line in the history buffer, not masked
} con_history_t;
typedef struct typedef struct
{ {
qboolean initialized; qboolean initialized;
@@ -126,8 +116,10 @@ typedef struct
string chat_cmd; // can be overrieded by user string chat_cmd; // can be overrieded by user
// console history // console history
con_history_t history; field_t historyLines[CON_HISTORY];
qboolean historyLoaded; int historyLine; // the line being displayed from history buffer will be <= nextHistoryLine
int nextHistoryLine; // the last line in the history buffer, not masked
field_t backup;
notify_t notify[MAX_DBG_NOTIFY]; // for Con_NXPrintf notify_t notify[MAX_DBG_NOTIFY]; // for Con_NXPrintf
qboolean draw_notify; // true if we have NXPrint message qboolean draw_notify; // true if we have NXPrint message
@@ -141,9 +133,6 @@ static console_t con;
void Con_ClearField( field_t *edit ); void Con_ClearField( field_t *edit );
void Field_CharEvent( field_t *edit, int ch ); void Field_CharEvent( field_t *edit, int ch );
static void Con_LoadHistory( con_history_t *self );
static void Con_SaveHistory( con_history_t *self );
/* /*
================ ================
Con_Clear_f Con_Clear_f
@@ -207,6 +196,8 @@ Con_ClearTyping
*/ */
void Con_ClearTyping( void ) void Con_ClearTyping( void )
{ {
int i;
Con_ClearField( &con.input ); Con_ClearField( &con.input );
con.input.widthInChars = con.linewidth; con.input.widthInChars = con.linewidth;
@@ -251,8 +242,6 @@ Con_MessageMode_f
*/ */
void Con_MessageMode_f( void ) void Con_MessageMode_f( void )
{ {
g_messagemode_privileged = Cmd_CurrentCommandIsPrivileged();
if( Cmd_Argc() == 2 ) if( Cmd_Argc() == 2 )
Q_strncpy( con.chat_cmd, Cmd_Argv( 1 ), sizeof( con.chat_cmd )); Q_strncpy( con.chat_cmd, Cmd_Argv( 1 ), sizeof( con.chat_cmd ));
else Q_strncpy( con.chat_cmd, "say", sizeof( con.chat_cmd )); else Q_strncpy( con.chat_cmd, "say", sizeof( con.chat_cmd ));
@@ -267,8 +256,6 @@ Con_MessageMode2_f
*/ */
void Con_MessageMode2_f( void ) void Con_MessageMode2_f( void )
{ {
g_messagemode_privileged = Cmd_CurrentCommandIsPrivileged();
Q_strncpy( con.chat_cmd, "say_team", sizeof( con.chat_cmd )); Q_strncpy( con.chat_cmd, "say_team", sizeof( con.chat_cmd ));
Key_SetKeyDest( key_message ); Key_SetKeyDest( key_message );
} }
@@ -283,8 +270,6 @@ void Con_ToggleConsole_f( void )
if( !host.allow_console || UI_CreditsActive( )) if( !host.allow_console || UI_CreditsActive( ))
return; // disabled return; // disabled
SCR_EndLoadingPlaque();
// show console only in game or by special call from menu // show console only in game or by special call from menu
if( cls.state != ca_active || cls.key_dest == key_menu ) if( cls.state != ca_active || cls.key_dest == key_menu )
return; return;
@@ -495,7 +480,7 @@ void Con_CheckResize( void )
con.input.widthInChars = con.linewidth; con.input.widthInChars = con.linewidth;
for( i = 0; i < CON_HISTORY; i++ ) for( i = 0; i < CON_HISTORY; i++ )
con.history.lines[i].widthInChars = con.linewidth; con.historyLines[i].widthInChars = con.linewidth;
} }
/* /*
@@ -914,7 +899,7 @@ static int Con_DrawGenericChar( int x, int y, int number, rgba_t color )
if( !con.curFont || !con.curFont->valid ) if( !con.curFont || !con.curFont->valid )
return 0; return 0;
number = Con_UtfProcessChar( number ); number = Con_UtfProcessChar(number);
if( !number ) if( !number )
return 0; return 0;
@@ -1071,7 +1056,7 @@ int Con_DrawGenericString( int x, int y, const char *string, rgba_t setColor, qb
Con_UtfProcessChar( 0 ); Con_UtfProcessChar( 0 );
// draw the colored text // draw the colored text
memcpy( color, setColor, sizeof( color )); *(uint *)color = *(uint *)setColor;
s = string; s = string;
while( *s ) while( *s )
@@ -1122,6 +1107,61 @@ int Con_DrawString( int x, int y, const char *string, rgba_t setColor )
return Con_DrawGenericString( x, y, string, setColor, false, -1 ); return Con_DrawGenericString( x, y, string, setColor, false, -1 );
} }
void Con_LoadHistory( void )
{
const byte *aFile = FS_LoadFile( "console_history.txt", NULL, true );
const char *pLine = (char *)aFile, *pFile = (char *)aFile;
int i;
if( !aFile )
return;
while( true )
{
if( !*pFile )
break;
if( *pFile == '\n')
{
int len = pFile - pLine + 1;
field_t *f;
if( len > 255 ) len = 255;
Con_ClearField( &con.historyLines[con.nextHistoryLine] );
f = &con.historyLines[con.nextHistoryLine % CON_HISTORY];
f->widthInChars = con.linewidth;
f->cursor = len - 1;
Q_strncpy( f->buffer, pLine, len);
con.nextHistoryLine++;
pLine = pFile + 1;
}
pFile++;
}
for( i = con.nextHistoryLine; i < CON_HISTORY; i++ )
{
Con_ClearField( &con.historyLines[i] );
con.historyLines[i].widthInChars = con.linewidth;
}
con.historyLine = con.nextHistoryLine;
}
void Con_SaveHistory( void )
{
int historyStart = con.nextHistoryLine - CON_HISTORY;
int i;
file_t *f;
if( historyStart < 0 )
historyStart = 0;
f = FS_Open("console_history.txt", "w", true );
for( i = historyStart; i < con.nextHistoryLine; i++ )
FS_Printf( f, "%s\n", con.historyLines[i % CON_HISTORY].buffer );
FS_Close(f);
}
/* /*
================ ================
@@ -1161,7 +1201,7 @@ void Con_Init( void )
con.chat.widthInChars = con.linewidth; con.chat.widthInChars = con.linewidth;
Cmd_AddCommand( "toggleconsole", Con_ToggleConsole_f, "opens or closes the console" ); Cmd_AddCommand( "toggleconsole", Con_ToggleConsole_f, "opens or closes the console" );
Cmd_AddRestrictedCommand( "clear", Con_Clear_f, "clear console history" ); Cmd_AddCommand( "clear", Con_Clear_f, "clear console history" );
Cmd_AddCommand( "messagemode", Con_MessageMode_f, "enable message mode \"say\"" ); Cmd_AddCommand( "messagemode", Con_MessageMode_f, "enable message mode \"say\"" );
Cmd_AddCommand( "messagemode2", Con_MessageMode2_f, "enable message mode \"say_team\"" ); Cmd_AddCommand( "messagemode2", Con_MessageMode2_f, "enable message mode \"say_team\"" );
Cmd_AddCommand( "contimes", Con_SetTimes_f, "change number of console overlay lines (4-64)" ); Cmd_AddCommand( "contimes", Con_SetTimes_f, "change number of console overlay lines (4-64)" );
@@ -1187,7 +1227,7 @@ void Con_Shutdown( void )
con.buffer = NULL; con.buffer = NULL;
con.lines = NULL; con.lines = NULL;
Con_SaveHistory( &con.history ); Con_SaveHistory();
} }
/* /*
@@ -1422,22 +1462,11 @@ Con_ClearField
*/ */
void Con_ClearField( field_t *edit ) void Con_ClearField( field_t *edit )
{ {
memset( edit->buffer, 0, MAX_STRING ); memset(edit->buffer, 0, MAX_STRING);
edit->cursor = 0; edit->cursor = 0;
edit->scroll = 0; edit->scroll = 0;
} }
/*
================
Field_Set
================
*/
static void Field_Set( field_t *f, const char *string )
{
f->scroll = 0;
f->cursor = Q_strncpy( f->buffer, string, MAX_STRING );
}
/* /*
================ ================
Field_Paste Field_Paste
@@ -1457,18 +1486,6 @@ void Field_Paste( field_t *edit )
Field_CharEvent( edit, cbd[i] ); Field_CharEvent( edit, cbd[i] );
} }
/*
=================
Field_GoTo
=================
*/
static void Field_GoTo( field_t *edit, int pos )
{
edit->cursor = pos;
edit->scroll = Q_max( 0, edit->cursor - edit->widthInChars );
}
/* /*
================= =================
Field_KeyDownEvent Field_KeyDownEvent
@@ -1521,20 +1538,20 @@ void Field_KeyDownEvent( field_t *edit, int key )
if( key == K_LEFTARROW ) if( key == K_LEFTARROW )
{ {
if( edit->cursor > 0 ) edit->cursor = Con_UtfMoveLeft( edit->buffer, edit->cursor ); if( edit->cursor > 0 ) edit->cursor= Con_UtfMoveLeft( edit->buffer, edit->cursor );
if( edit->cursor < edit->scroll ) edit->scroll--; if( edit->cursor < edit->scroll ) edit->scroll--;
return; return;
} }
if( key == K_HOME || ( Q_tolower(key) == 'a' && Key_IsDown( K_CTRL ))) if( key == K_HOME || ( Q_tolower(key) == 'a' && Key_IsDown( K_CTRL )))
{ {
Field_GoTo( edit, 0 ); edit->cursor = 0;
return; return;
} }
if( key == K_END || ( Q_tolower(key) == 'e' && Key_IsDown( K_CTRL ))) if( key == K_END || ( Q_tolower(key) == 'e' && Key_IsDown( K_CTRL )))
{ {
Field_GoTo( edit, len ); edit->cursor = len;
return; return;
} }
@@ -1573,14 +1590,16 @@ void Field_CharEvent( field_t *edit, int ch )
if( ch == 'a' - 'a' + 1 ) if( ch == 'a' - 'a' + 1 )
{ {
// ctrl-a is home // ctrl-a is home
Field_GoTo( edit, 0 ); edit->cursor = 0;
edit->scroll = 0;
return; return;
} }
if( ch == 'e' - 'a' + 1 ) if( ch == 'e' - 'a' + 1 )
{ {
// ctrl-e is end // ctrl-e is end
Field_GoTo( edit, len ); edit->cursor = len;
edit->scroll = edit->cursor - edit->widthInChars;
return; return;
} }
@@ -1683,134 +1702,12 @@ void Field_DrawInputLine( int x, int y, field_t *edit )
} }
} }
/*
=============================================================================
CONSOLE HISTORY HANDLING
=============================================================================
*/
/*
===================
Con_HistoryUp
===================
*/
static void Con_HistoryUp( con_history_t *self, field_t *in )
{
if( self->line == self->next )
self->backup = *in;
if(( self->next - self->line ) < CON_HISTORY )
self->line = Q_max( 0, self->line - 1 );
*in = self->lines[self->line % CON_HISTORY];
}
/*
===================
Con_HistoryDown
===================
*/
static void Con_HistoryDown( con_history_t *self, field_t *in )
{
self->line = Q_min( self->next, self->line + 1 );
if( self->line == self->next )
*in = self->backup;
else *in = self->lines[self->line % CON_HISTORY];
}
/*
===================
Con_HistoryAppend
===================
*/
static void Con_HistoryAppend( con_history_t *self, field_t *from )
{
int prevLine = Q_max( 0, self->line - 1 );
const char *buf = from->buffer;
// skip backslashes
if( from->buffer[0] == '\\' || from->buffer[1] == '/' )
buf++;
// only if non-empty
if( !from->buffer[0] )
return;
// skip empty commands
if( Q_isspace( buf ))
return;
// if not copy (don't ignore backslashes)
if( !Q_strcmp( from->buffer, self->lines[prevLine % CON_HISTORY].buffer ))
return;
self->lines[self->next % CON_HISTORY] = *from;
self->line = ++self->next;
}
static void Con_LoadHistory( con_history_t *self )
{
const byte *aFile = FS_LoadFile( "console_history.txt", NULL, true );
const char *pLine, *pFile;
int i, len;
field_t *f;
if( !aFile )
return;
for( pFile = pLine = (char *)aFile; *pFile; pFile++ )
{
if( *pFile != '\n' )
continue;
Con_ClearField( &self->lines[self->next] );
len = Q_min( pFile - pLine + 1, sizeof( f->buffer ));
f = &self->lines[self->next % CON_HISTORY];
f->widthInChars = con.linewidth;
f->cursor = len - 1;
Q_strncpy( f->buffer, pLine, len);
self->next++;
pLine = pFile + 1;
}
for( i = self->next; i < CON_HISTORY; i++ )
{
Con_ClearField( &self->lines[i] );
self->lines[i].widthInChars = con.linewidth;
}
self->line = self->next;
}
static void Con_SaveHistory( con_history_t *self )
{
int historyStart = self->next - CON_HISTORY, i;
file_t *f;
if( historyStart < 0 )
historyStart = 0;
f = FS_Open( "console_history.txt", "w", true );
for( i = historyStart; i < self->next; i++ )
FS_Printf( f, "%s\n", self->lines[i % CON_HISTORY].buffer );
FS_Close( f );
}
/* /*
============================================================================= =============================================================================
CONSOLE LINE EDITING CONSOLE LINE EDITING
============================================================================= ==============================================================================
*/ */
/* /*
==================== ====================
@@ -1831,6 +1728,16 @@ void Key_Console( int key )
// enter finishes the line // enter finishes the line
if( key == K_ENTER || key == K_KP_ENTER ) if( key == K_ENTER || key == K_KP_ENTER )
{ {
// if not in the game explicitly prepent a slash if needed
if( cls.state != ca_active && con.input.buffer[0] != '\\' && con.input.buffer[0] != '/' )
{
char temp[MAX_SYSPATH];
Q_strncpy( temp, con.input.buffer, sizeof( temp ));
Q_sprintf( con.input.buffer, "\\%s", temp );
con.input.cursor++;
}
// backslash text are commands, else chat // backslash text are commands, else chat
if( con.input.buffer[0] == '\\' || con.input.buffer[0] == '/' ) if( con.input.buffer[0] == '\\' || con.input.buffer[0] == '/' )
Cbuf_AddText( con.input.buffer + 1 ); // skip backslash Cbuf_AddText( con.input.buffer + 1 ); // skip backslash
@@ -1841,7 +1748,9 @@ void Key_Console( int key )
Con_Printf( ">%s\n", con.input.buffer ); Con_Printf( ">%s\n", con.input.buffer );
// copy line to history buffer // copy line to history buffer
Con_HistoryAppend( &con.history, &con.input ); con.historyLines[con.nextHistoryLine % CON_HISTORY] = con.input;
con.nextHistoryLine++;
con.historyLine = con.nextHistoryLine;
Con_ClearField( &con.input ); Con_ClearField( &con.input );
con.input.widthInChars = con.linewidth; con.input.widthInChars = con.linewidth;
@@ -1866,13 +1775,23 @@ void Key_Console( int key )
// command history (ctrl-p ctrl-n for unix style) // command history (ctrl-p ctrl-n for unix style)
if(( key == K_MWHEELUP && Key_IsDown( K_SHIFT )) || ( key == K_UPARROW ) || (( Q_tolower(key) == 'p' ) && Key_IsDown( K_CTRL ))) if(( key == K_MWHEELUP && Key_IsDown( K_SHIFT )) || ( key == K_UPARROW ) || (( Q_tolower(key) == 'p' ) && Key_IsDown( K_CTRL )))
{ {
Con_HistoryUp( &con.history, &con.input ); if( con.historyLine == con.nextHistoryLine )
con.backup = con.input;
if( con.nextHistoryLine - con.historyLine < CON_HISTORY && con.historyLine > 0 )
con.historyLine--;
con.input = con.historyLines[con.historyLine % CON_HISTORY];
return; return;
} }
if(( key == K_MWHEELDOWN && Key_IsDown( K_SHIFT )) || ( key == K_DOWNARROW ) || (( Q_tolower(key) == 'n' ) && Key_IsDown( K_CTRL ))) if(( key == K_MWHEELDOWN && Key_IsDown( K_SHIFT )) || ( key == K_DOWNARROW ) || (( Q_tolower(key) == 'n' ) && Key_IsDown( K_CTRL )))
{ {
Con_HistoryDown( &con.history, &con.input ); if( con.historyLine >= con.nextHistoryLine - 1 )
con.input = con.backup;
else
{
con.historyLine++;
con.input = con.historyLines[con.historyLine % CON_HISTORY];
}
return; return;
} }
@@ -1946,10 +1865,7 @@ void Key_Message( int key )
if( con.chat.buffer[0] && cls.state == ca_active ) if( con.chat.buffer[0] && cls.state == ca_active )
{ {
Q_snprintf( buffer, sizeof( buffer ), "%s \"%s\"\n", con.chat_cmd, con.chat.buffer ); Q_snprintf( buffer, sizeof( buffer ), "%s \"%s\"\n", con.chat_cmd, con.chat.buffer );
Cbuf_AddText( buffer );
if( g_messagemode_privileged )
Cbuf_AddText( buffer );
else Cbuf_AddFilteredText( buffer );
} }
Key_SetKeyDest( key_game ); Key_SetKeyDest( key_game );
@@ -2041,7 +1957,7 @@ void Con_DrawDebug( void )
if( scr_download->value != -1.0f ) if( scr_download->value != -1.0f )
{ {
Q_snprintf( dlstring, sizeof( dlstring ), "Downloading [%d remaining]: ^2%s^7 %5.1f%% time %.f secs", Q_snprintf( dlstring, sizeof( dlstring ), "Downloading [%d remaining]: ^2%s^7 %5.1f%% time %.f secs",
host.downloadcount, host.downloadfile, scr_download->value, Sys_DoubleTime() - timeStart ); host.downloadcount, host.downloadfile, scr_download->value, Sys_DoubleTime() - timeStart );
x = refState.width - 500; x = refState.width - 500;
y = con.curFont->charHeight * 1.05f; y = con.curFont->charHeight * 1.05f;
Con_DrawString( x, y, dlstring, g_color_table[7] ); Con_DrawString( x, y, dlstring, g_color_table[7] );
@@ -2051,7 +1967,7 @@ void Con_DrawDebug( void )
timeStart = Sys_DoubleTime(); timeStart = Sys_DoubleTime();
} }
if( !host.allow_console || Cvar_VariableInteger( "cl_background" ) || Cvar_VariableInteger( "sv_background" )) if( !host_developer.value || Cvar_VariableInteger( "cl_background" ) || Cvar_VariableInteger( "sv_background" ))
return; return;
if( con.draw_notify && !Con_Visible( )) if( con.draw_notify && !Con_Visible( ))
@@ -2077,7 +1993,7 @@ void Con_DrawNotify( void )
x = con.curFont->charWidths[' ']; // offset one space at left screen side x = con.curFont->charWidths[' ']; // offset one space at left screen side
if( host.allow_console && ( !Cvar_VariableInteger( "cl_background" ) && !Cvar_VariableInteger( "sv_background" ))) if( host_developer.value && ( !Cvar_VariableInteger( "cl_background" ) && !Cvar_VariableInteger( "sv_background" )))
{ {
for( i = CON_LINES_COUNT - con.num_times; i < CON_LINES_COUNT; i++ ) for( i = CON_LINES_COUNT - con.num_times; i < CON_LINES_COUNT; i++ )
{ {
@@ -2176,9 +2092,6 @@ void Con_DrawSolidConsole( int lines )
int i, x, y; int i, x, y;
float fraction; float fraction;
int start; int start;
int stringLen, width = 0, charH;
string curbuild;
byte color[4];
if( lines <= 0 ) return; if( lines <= 0 ) return;
@@ -2192,20 +2105,28 @@ void Con_DrawSolidConsole( int lines )
if( !con.curFont || !host.allow_console ) if( !con.curFont || !host.allow_console )
return; // nothing to draw return; // nothing to draw
// draw current version if( host.allow_console )
memcpy( color, g_color_table[7], sizeof( color )); {
// draw current version
int stringLen, width = 0, charH;
string curbuild;
byte color[4];
Q_snprintf( curbuild, MAX_STRING, "%s %i/%s (%s-%s build %i)", XASH_ENGINE_NAME, PROTOCOL_VERSION, XASH_VERSION, Q_buildos(), Q_buildarch(), Q_buildnum( )); memcpy( color, g_color_table[7], sizeof( color ));
Con_DrawStringLen( curbuild, &stringLen, &charH );
start = refState.width - stringLen;
stringLen = Con_StringLength( curbuild );
fraction = lines / (float)refState.height; Q_snprintf( curbuild, MAX_STRING, "%s %i/%s (%s-%s build %i)", XASH_ENGINE_NAME, PROTOCOL_VERSION, XASH_VERSION, Q_buildos(), Q_buildarch(), Q_buildnum( ));
color[3] = Q_min( fraction * 2.0f, 1.0f ) * 255; // fadeout version number
for( i = 0; i < stringLen; i++ ) Con_DrawStringLen( curbuild, &stringLen, &charH );
width += Con_DrawCharacter( start + width, 0, curbuild[i], color ); start = refState.width - stringLen;
stringLen = Con_StringLength( curbuild );
fraction = lines / (float)refState.height;
color[3] = Q_min( fraction * 2.0f, 1.0f ) * 255; // fadeout version number
for( i = 0; i < stringLen; i++ )
width += Con_DrawCharacter( start + width, 0, curbuild[i], color );
}
// draw the text // draw the text
if( CON_LINES_COUNT > 0 ) if( CON_LINES_COUNT > 0 )
@@ -2242,7 +2163,7 @@ void Con_DrawSolidConsole( int lines )
Con_DrawInput( lines ); Con_DrawInput( lines );
y = lines - ( con.curFont->charHeight * 1.2f ); y = lines - ( con.curFont->charHeight * 1.2f );
SCR_DrawFPS( Q_max( y, 4 )); // to avoid to hide fps counter SCR_DrawFPS( max( y, 4 )); // to avoid to hide fps counter
ref.dllFuncs.Color4ub( 255, 255, 255, 255 ); ref.dllFuncs.Color4ub( 255, 255, 255, 255 );
} }
@@ -2403,21 +2324,11 @@ void Con_RunConsole( void )
FBitSet( cl_charset->flags, FCVAR_CHANGED ) ) FBitSet( cl_charset->flags, FCVAR_CHANGED ) )
{ {
// update codepage parameters // update codepage parameters
if( !Q_stricmp( con_charset->string, "cp1251" )) g_codepage = 0;
{ if( !Q_stricmp( con_charset->string, "cp1251" ) )
g_codepage = 1251; g_codepage = 1251;
} else if( !Q_stricmp( con_charset->string, "cp1252" ) )
else if( !Q_stricmp( con_charset->string, "cp1252" ))
{
g_codepage = 1252; g_codepage = 1252;
}
else
{
Con_Printf( S_WARN "Unknown charset %s, defaulting to cp1252", con_charset->string );
Cvar_DirectSet( con_charset, "cp1252" );
g_codepage = 1252;
}
g_utf8 = !Q_stricmp( cl_charset->string, "utf-8" ); g_utf8 = !Q_stricmp( cl_charset->string, "utf-8" );
Con_InvalidateFonts(); Con_InvalidateFonts();
@@ -2468,12 +2379,6 @@ INTERNAL RESOURCE
*/ */
void Con_VidInit( void ) void Con_VidInit( void )
{ {
if( !con.historyLoaded )
{
Con_LoadHistory( &con.history );
con.historyLoaded = true;
}
Con_LoadConchars(); Con_LoadConchars();
Con_CheckResize(); Con_CheckResize();
#if XASH_LOW_MEMORY #if XASH_LOW_MEMORY
@@ -2509,6 +2414,7 @@ void Con_VidInit( void )
} }
} }
if( !con.background ) // last chance - quake conback image if( !con.background ) // last chance - quake conback image
{ {
qboolean draw_to_console = false; qboolean draw_to_console = false;
@@ -2596,48 +2502,3 @@ void GAME_EXPORT Con_DefaultColor( int r, int g, int b )
b = bound( 0, b, 255 ); b = bound( 0, b, 255 );
MakeRGBA( g_color_table[7], r, g, b, 255 ); MakeRGBA( g_color_table[7], r, g, b, 255 );
} }
#if XASH_ENGINE_TESTS
#include "tests.h"
static void Test_RunConHistory( void )
{
con_history_t hist = { 0 };
field_t input = { 0 };
const char *strs1[] = { "map t0a0", "quit", "wtf", "wtf", "", "nyan" };
const char *strs2[] = { "nyan", "wtf", "quit", "map t0a0" };
const char *testbackup = "unfinished_edit";
int i;
for( i = 0; i < ARRAYSIZE( strs1 ); i++ )
{
Field_Set( &input, strs1[i] );
Con_HistoryAppend( &hist, &input );
}
Field_Set( &input, testbackup );
for( i = 0; i < ARRAYSIZE( strs2 ); i++ )
{
Con_HistoryUp( &hist, &input );
TASSERT_STR( input.buffer, strs2[i] );
}
// check for overrun
Con_HistoryUp( &hist, &input );
for( i = ARRAYSIZE( strs2 ) - 1; i >= 0; i-- )
{
TASSERT_STR( input.buffer, strs2[i] );
Con_HistoryDown( &hist, &input );
}
TASSERT_STR( input.buffer, testbackup );
}
void Test_RunCon( void )
{
TRUN( Test_RunConHistory() );
}
#endif /* XASH_ENGINE_TESTS */

View File

@@ -380,32 +380,32 @@ Main init procedure
*/ */
void Joy_Init( void ) void Joy_Init( void )
{ {
joy_pitch = Cvar_Get( "joy_pitch", "100.0", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "joystick pitch sensitivity" ); joy_pitch = Cvar_Get( "joy_pitch", "100.0", FCVAR_ARCHIVE, "joystick pitch sensitivity" );
joy_yaw = Cvar_Get( "joy_yaw", "100.0", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "joystick yaw sensitivity" ); joy_yaw = Cvar_Get( "joy_yaw", "100.0", FCVAR_ARCHIVE, "joystick yaw sensitivity" );
joy_side = Cvar_Get( "joy_side", "1.0", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "joystick side sensitivity. Values from -1.0 to 1.0" ); joy_side = Cvar_Get( "joy_side", "1.0", FCVAR_ARCHIVE, "joystick side sensitivity. Values from -1.0 to 1.0" );
joy_forward = Cvar_Get( "joy_forward", "1.0", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "joystick forward sensitivity. Values from -1.0 to 1.0" ); joy_forward = Cvar_Get( "joy_forward", "1.0", FCVAR_ARCHIVE, "joystick forward sensitivity. Values from -1.0 to 1.0" );
joy_lt_threshold = Cvar_Get( "joy_lt_threshold", "16384", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "left trigger threshold. Value from 0 to 32767"); joy_lt_threshold = Cvar_Get( "joy_lt_threshold", "16384", FCVAR_ARCHIVE, "left trigger threshold. Value from 0 to 32767");
joy_rt_threshold = Cvar_Get( "joy_rt_threshold", "16384", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "right trigger threshold. Value from 0 to 32767" ); joy_rt_threshold = Cvar_Get( "joy_rt_threshold", "16384", FCVAR_ARCHIVE, "right trigger threshold. Value from 0 to 32767" );
// emit a key event at 75% axis move // emit a key event at 75% axis move
joy_side_key_threshold = Cvar_Get( "joy_side_key_threshold", "24576", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "side axis key event emit threshold. Value from 0 to 32767" ); joy_side_key_threshold = Cvar_Get( "joy_side_key_threshold", "24576", FCVAR_ARCHIVE, "side axis key event emit threshold. Value from 0 to 32767" );
joy_forward_key_threshold = Cvar_Get( "joy_forward_key_threshold", "24576", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "forward axis key event emit threshold. Value from 0 to 32767"); joy_forward_key_threshold = Cvar_Get( "joy_forward_key_threshold", "24576", FCVAR_ARCHIVE, "forward axis key event emit threshold. Value from 0 to 32767");
// by default, we rely on deadzone detection come from system, but some glitchy devices report false deadzones // by default, we rely on deadzone detection come from system, but some glitchy devices report false deadzones
joy_side_deadzone = Cvar_Get( "joy_side_deadzone", "0", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "side axis deadzone. Value from 0 to 32767" ); joy_side_deadzone = Cvar_Get( "joy_side_deadzone", "0", FCVAR_ARCHIVE, "side axis deadzone. Value from 0 to 32767" );
joy_forward_deadzone = Cvar_Get( "joy_forward_deadzone", "0", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "forward axis deadzone. Value from 0 to 32767"); joy_forward_deadzone = Cvar_Get( "joy_forward_deadzone", "0", FCVAR_ARCHIVE, "forward axis deadzone. Value from 0 to 32767");
joy_pitch_deadzone = Cvar_Get( "joy_pitch_deadzone", "0", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "pitch axis deadzone. Value from 0 to 32767"); joy_pitch_deadzone = Cvar_Get( "joy_pitch_deadzone", "0", FCVAR_ARCHIVE, "pitch axis deadzone. Value from 0 to 32767");
joy_yaw_deadzone = Cvar_Get( "joy_yaw_deadzone", "0", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "yaw axis deadzone. Value from 0 to 32767" ); joy_yaw_deadzone = Cvar_Get( "joy_yaw_deadzone", "0", FCVAR_ARCHIVE, "yaw axis deadzone. Value from 0 to 32767" );
joy_axis_binding = Cvar_Get( "joy_axis_binding", "sfpyrl", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "axis hardware id to engine inner axis binding, " joy_axis_binding = Cvar_Get( "joy_axis_binding", "sfpyrl", FCVAR_ARCHIVE, "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" );
joy_found = Cvar_Get( "joy_found", "0", FCVAR_READ_ONLY, "is joystick is connected" ); joy_found = Cvar_Get( "joy_found", "0", FCVAR_READ_ONLY, "is joystick is connected" );
// we doesn't loaded config.cfg yet, so this cvar is not archive. // we doesn't loaded config.cfg yet, so this cvar is not archive.
// change by +set joy_index in cmdline // change by +set joy_index in cmdline
joy_index = Cvar_Get( "joy_index", "0", FCVAR_READ_ONLY, "current active joystick" ); joy_index = Cvar_Get( "joy_index", "0", FCVAR_READ_ONLY, "current active joystick" );
joy_enable = Cvar_Get( "joy_enable", "1", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "enable joystick" ); joy_enable = Cvar_Get( "joy_enable", "1", FCVAR_ARCHIVE, "enable joystick" );
if( Sys_CheckParm( "-nojoy" )) if( Sys_CheckParm( "-nojoy" ))
{ {

View File

@@ -134,9 +134,6 @@ struct touch_s
qboolean configchanged; qboolean configchanged;
} touch; } touch;
// private to the engine flags
#define TOUCH_FL_UNPRIVILEGED BIT( 10 )
touchdefaultbutton_t g_DefaultButtons[256]; touchdefaultbutton_t g_DefaultButtons[256];
int g_LastDefaultButton; int g_LastDefaultButton;
@@ -197,8 +194,6 @@ static inline int Touch_ExportButtonToConfig( file_t *f, touch_button_t *button,
if( FBitSet( flags, TOUCH_FL_DEF_HIDE )) if( FBitSet( flags, TOUCH_FL_DEF_HIDE ))
SetBits( flags, TOUCH_FL_HIDE ); SetBits( flags, TOUCH_FL_HIDE );
Cmd_Escape( newCommand, B( command ), sizeof( newCommand ));
FS_Printf( f, "touch_addbutton \"%s\" \"%s\" \"%s\" %f %f %f %f %d %d %d %d %d", FS_Printf( f, "touch_addbutton \"%s\" \"%s\" \"%s\" %f %f %f %f %d %d %d %d %d",
B(name), B(texturefile), newCommand, B(name), B(texturefile), newCommand,
B(x1), B(y1), B(x2), B(y2), B(x1), B(y1), B(x2), B(y2),
@@ -460,42 +455,28 @@ static void Touch_Stroke_f( void )
MakeRGBA( touch.scolor, Q_atoi( Cmd_Argv( 2 ) ), Q_atoi( Cmd_Argv( 3 ) ), Q_atoi( Cmd_Argv( 4 ) ), Q_atoi( Cmd_Argv( 5 ) ) ); MakeRGBA( touch.scolor, Q_atoi( Cmd_Argv( 2 ) ), Q_atoi( Cmd_Argv( 3 ) ), Q_atoi( Cmd_Argv( 4 ) ), Q_atoi( Cmd_Argv( 5 ) ) );
} }
static touch_button_t *Touch_FindButton( touchbuttonlist_t *list, const char *name, qboolean privileged ) static touch_button_t *Touch_FindButton( touchbuttonlist_t *list, const char *name )
{ {
touch_button_t *button; touch_button_t *button;
for( button = list->first; button; button = button->next ) for( button = list->first; button; button = button->next )
{ if( !Q_strncmp( button->name, name, sizeof( button->name )))
if( !privileged && !FBitSet( button->flags, TOUCH_FL_UNPRIVILEGED ))
continue;
if( Q_strncmp( button->name, name, sizeof( button->name )))
continue;
return button;
}
return NULL;
}
static touch_button_t *Touch_FindFirst( touchbuttonlist_t *list, const char *name, qboolean privileged )
{
touch_button_t *button;
for( button = list->first; button; button = button->next )
{
if( !privileged && !FBitSet( button->flags, TOUCH_FL_UNPRIVILEGED ))
continue;
if(( Q_strchr( name, '*' ) && Q_stricmpext( name, button->name )) || !Q_strncmp( name, button->name, sizeof( button->name )))
{
return button; return button;
}
}
return NULL; return NULL;
} }
void Touch_SetClientOnly( byte state ) static touch_button_t *Touch_FindFirst( touchbuttonlist_t *list, const char *name )
{
touch_button_t *button;
for( button = list->first; button; button = button->next )
if(( Q_strchr( name, '*' ) && Q_stricmpext( name, button->name )) || !Q_strncmp( name, button->name, sizeof( button->name )))
return button;
return NULL;
}
void Touch_SetClientOnly( qboolean state )
{ {
touch.clientonly = state; touch.clientonly = state;
host.mouse_visible = state; host.mouse_visible = state;
@@ -503,14 +484,20 @@ void Touch_SetClientOnly( byte state )
touch.move_finger = touch.look_finger = -1; touch.move_finger = touch.look_finger = -1;
touch.forward = touch.side = 0; touch.forward = touch.side = 0;
/// TODO: touch sdl platform
#if 0
if( state ) if( state )
{ {
SDL_SetRelativeMouseMode( SDL_FALSE );
SDL_ShowCursor( true );
IN_DeactivateMouse(); IN_DeactivateMouse();
} }
else else
{ {
IN_ActivateMouse(); SDL_ShowCursor( false );
SDL_GetRelativeMouseState( 0, 0 );
} }
#endif
} }
static void Touch_SetClientOnly_f( void ) static void Touch_SetClientOnly_f( void )
@@ -524,13 +511,13 @@ static void Touch_SetClientOnly_f( void )
Touch_SetClientOnly( Q_atoi( Cmd_Argv( 1 ))); Touch_SetClientOnly( Q_atoi( Cmd_Argv( 1 )));
} }
static void Touch_RemoveButtonFromList( touchbuttonlist_t *list, const char *name, qboolean privileged ) static void Touch_RemoveButtonFromList( touchbuttonlist_t *list, const char *name )
{ {
touch_button_t *button; touch_button_t *button;
IN_TouchEditClear(); IN_TouchEditClear();
while(( button = Touch_FindFirst( &touch.list_user, name, privileged ))) while(( button = Touch_FindFirst( &touch.list_user, name )))
{ {
if( button->prev ) if( button->prev )
button->prev->next = button->next; button->prev->next = button->next;
@@ -547,9 +534,9 @@ static void Touch_RemoveButtonFromList( touchbuttonlist_t *list, const char *nam
} }
void Touch_RemoveButton( const char *name, qboolean privileged ) void Touch_RemoveButton( const char *name )
{ {
Touch_RemoveButtonFromList( &touch.list_user, name, privileged ); Touch_RemoveButtonFromList( &touch.list_user, name );
} }
static void IN_TouchRemoveButton_f( void ) static void IN_TouchRemoveButton_f( void )
@@ -560,7 +547,7 @@ static void IN_TouchRemoveButton_f( void )
return; return;
} }
Touch_RemoveButton( Cmd_Argv( 1 ), Cmd_CurrentCommandIsPrivileged()); Touch_RemoveButton( Cmd_Argv( 1 ));
} }
static void Touch_ClearList( touchbuttonlist_t *list ) static void Touch_ClearList( touchbuttonlist_t *list )
@@ -591,9 +578,9 @@ static void Touch_SetColor( touchbuttonlist_t *list, const char *name, byte *col
} }
} }
static void Touch_SetTexture( touchbuttonlist_t *list, const char *name, const char *texture, qboolean privileged ) static void Touch_SetTexture( touchbuttonlist_t *list, const char *name, const char *texture )
{ {
touch_button_t *button = Touch_FindButton( list, name, privileged ); touch_button_t *button = Touch_FindButton( list, name );
if( !button ) if( !button )
return; return;
@@ -618,15 +605,12 @@ static void Touch_SetCommand( touch_button_t *button, const char *command )
button->type = touch_wheel; button->type = touch_wheel;
} }
void Touch_HideButtons( const char *name, byte hide, qboolean privileged ) void Touch_HideButtons( const char *name, byte hide )
{ {
touch_button_t *button; touch_button_t *button;
for( button = touch.list_user.first; button; button = button->next) for( button = touch.list_user.first; button; button = button->next)
{ {
if( !privileged && !FBitSet( button->flags, TOUCH_FL_UNPRIVILEGED ))
continue;
if(( Q_strchr( name, '*' ) && Q_stricmpext( name, button->name )) || !Q_strncmp( name, button->name, sizeof( button->name ))) if(( Q_strchr( name, '*' ) && Q_stricmpext( name, button->name )) || !Q_strncmp( name, button->name, sizeof( button->name )))
{ {
if( hide ) if( hide )
@@ -651,7 +635,7 @@ static void Touch_Hide_f( void )
return; return;
} }
Touch_HideButtons( Cmd_Argv( 1 ), true, Cmd_CurrentCommandIsPrivileged() ); Touch_HideButtons( Cmd_Argv( 1 ), true );
} }
static void Touch_Show_f( void ) static void Touch_Show_f( void )
@@ -662,17 +646,14 @@ static void Touch_Show_f( void )
return; return;
} }
Touch_HideButtons( Cmd_Argv( 1 ), false, Cmd_CurrentCommandIsPrivileged() ); Touch_HideButtons( Cmd_Argv( 1 ), false );
} }
static void Touch_FadeButtons( touchbuttonlist_t *list, const char *name, float speed, float end, float start, qboolean privileged ) static void Touch_FadeButtons( touchbuttonlist_t *list, const char *name, float speed, float end, float start )
{ {
touch_button_t *button; touch_button_t *button;
for( button = list->first; button; button = button->next) for( button = list->first; button; button = button->next)
{ {
if( !privileged && !FBitSet( button->flags, TOUCH_FL_UNPRIVILEGED ))
continue;
if(( Q_strchr( name, '*' ) && Q_stricmpext( name, button->name )) || !Q_strncmp( name, button->name, sizeof( button->name ))) if(( Q_strchr( name, '*' ) && Q_stricmpext( name, button->name )) || !Q_strncmp( name, button->name, sizeof( button->name )))
{ {
if( start >= 0 ) if( start >= 0 )
@@ -697,8 +678,7 @@ static void Touch_Fade_f( void )
return; return;
} }
Touch_FadeButtons( &touch.list_user,Cmd_Argv( 1 ), Q_atof( Cmd_Argv( 2 )), Q_atof( Cmd_Argv( 3 )), Touch_FadeButtons( &touch.list_user, Cmd_Argv( 1 ), Q_atof( Cmd_Argv( 2 )), Q_atof( Cmd_Argv( 3 )), start );
start, Cmd_CurrentCommandIsPrivileged() );
} }
static void Touch_SetColor_f( void ) static void Touch_SetColor_f( void )
@@ -706,7 +686,7 @@ static void Touch_SetColor_f( void )
rgba_t color; rgba_t color;
if( Cmd_Argc() == 6 ) if( Cmd_Argc() == 6 )
{ {
MakeRGBA( color, Q_atoi( Cmd_Argv(2) ), Q_atoi( Cmd_Argv(3) ), Q_atoi( Cmd_Argv(4) ), Q_atoi( Cmd_Argv(5) ) ); MakeRGBA( color, Q_atoi( Cmd_Argv(2) ), Q_atoi( Cmd_Argv(3) ), Q_atoi( Cmd_Argv(4) ), Q_atoi( Cmd_Argv(5) ) );
Touch_SetColor( &touch.list_user, Cmd_Argv(1), color ); Touch_SetColor( &touch.list_user, Cmd_Argv(1), color );
return; return;
} }
@@ -717,7 +697,7 @@ static void Touch_SetTexture_f( void )
{ {
if( Cmd_Argc() == 3 ) if( Cmd_Argc() == 3 )
{ {
Touch_SetTexture( &touch.list_user, Cmd_Argv( 1 ), Cmd_Argv( 2 ), Cmd_CurrentCommandIsPrivileged() ); Touch_SetTexture( &touch.list_user, Cmd_Argv( 1 ), Cmd_Argv( 2 ) );
return; return;
} }
Con_Printf( S_USAGE "touch_settexture <name> <file>\n" ); Con_Printf( S_USAGE "touch_settexture <name> <file>\n" );
@@ -727,13 +707,9 @@ static void Touch_SetFlags_f( void )
{ {
if( Cmd_Argc() == 3 ) if( Cmd_Argc() == 3 )
{ {
qboolean privileged = Cmd_CurrentCommandIsPrivileged(); touch_button_t *button = Touch_FindButton( &touch.list_user, Cmd_Argv( 1 ) );
touch_button_t *button = Touch_FindButton( &touch.list_user, Cmd_Argv( 1 ), privileged );
if( button ) if( button )
{ button->flags = Q_atoi( Cmd_Argv( 2 ) );
button->flags = ( privileged ? 0 : TOUCH_FL_UNPRIVILEGED | TOUCH_FL_CLIENT ) | Q_atoi( Cmd_Argv( 2 ));
}
return; return;
} }
Con_Printf( S_USAGE "touch_setflags <name> <file>\n" ); Con_Printf( S_USAGE "touch_setflags <name> <file>\n" );
@@ -743,7 +719,7 @@ static void Touch_SetCommand_f( void )
{ {
if( Cmd_Argc() == 3 ) if( Cmd_Argc() == 3 )
{ {
touch_button_t *button = Touch_FindButton( &touch.list_user, Cmd_Argv(1), Cmd_CurrentCommandIsPrivileged() ); touch_button_t *button = Touch_FindButton( &touch.list_user, Cmd_Argv(1) );
if( !button ) if( !button )
Con_Printf( S_ERROR "no such button" ); Con_Printf( S_ERROR "no such button" );
@@ -768,24 +744,21 @@ static void Touch_ReloadConfig_f( void )
Cbuf_AddText( va("exec %s\n", touch_config_file->string ) ); Cbuf_AddText( va("exec %s\n", touch_config_file->string ) );
} }
static touch_button_t *Touch_AddButton( touchbuttonlist_t *list, static touch_button_t *Touch_AddButton( touchbuttonlist_t *list, const char *name, const char *texture, const char *command, float x1, float y1, float x2, float y2, byte *color )
const char *name, const char *texture, const char *command,
float x1, float y1, float x2, float y2, byte *color,
qboolean privileged )
{ {
touch_button_t *button = Mem_Calloc( touch.mempool, sizeof( touch_button_t ) ); touch_button_t *button = Mem_Calloc( touch.mempool, sizeof( touch_button_t ) );
button->texture = -1; button->texture = -1;
Q_strncpy( button->texturefile, texture, sizeof( B( texturefile ))); Q_strncpy( button->texturefile, texture, sizeof( B( texturefile )));
Q_strncpy( button->name, name, sizeof( B( name ))); Q_strncpy( button->name, name, sizeof( B( name )));
Touch_RemoveButtonFromList( list, name, privileged ); //replace if exist Touch_RemoveButtonFromList( list, name ); //replace if exist
button->x1 = x1; button->x1 = x1;
button->y1 = y1; button->y1 = y1;
button->x2 = x2; button->x2 = x2;
button->y2 = y2; button->y2 = y2;
button->flags = privileged ? 0 : TOUCH_FL_UNPRIVILEGED | TOUCH_FL_CLIENT;
MakeRGBA( button->color, color[0], color[1], color[2], color[3] ); MakeRGBA( button->color, color[0], color[1], color[2], color[3] );
button->command[0] = 0; button->command[0] = 0;
button->flags = 0;
button->fade = 1; button->fade = 1;
Touch_SetCommand( button, command ); Touch_SetCommand( button, command );
@@ -815,7 +788,7 @@ void Touch_AddClientButton( const char *name, const char *texture, const char *c
{ {
y2 = y1 + ( x2 - x1 ) * (SCR_W/SCR_H) * aspect; y2 = y1 + ( x2 - x1 ) * (SCR_W/SCR_H) * aspect;
} }
button = Touch_AddButton( &touch.list_user, name, texture, command, x1, y1, x2, y2, color, true ); button = Touch_AddButton( &touch.list_user, name, texture, command, x1, y1, x2, y2, color );
button->flags |= flags | TOUCH_FL_CLIENT | TOUCH_FL_NOEDIT; button->flags |= flags | TOUCH_FL_CLIENT | TOUCH_FL_NOEDIT;
button->aspect = aspect; button->aspect = aspect;
} }
@@ -842,7 +815,7 @@ static void Touch_LoadDefaults_f( void )
} }
IN_TouchCheckCoords( &x1, &y1, &x2, &y2 ); IN_TouchCheckCoords( &x1, &y1, &x2, &y2 );
button = Touch_AddButton( &touch.list_user, g_DefaultButtons[i].name, g_DefaultButtons[i].texturefile, g_DefaultButtons[i].command, x1, y1, x2, y2, g_DefaultButtons[i].color, true ); button = Touch_AddButton( &touch.list_user, g_DefaultButtons[i].name, g_DefaultButtons[i].texturefile, g_DefaultButtons[i].command, x1, y1, x2, y2, g_DefaultButtons[i].color );
button->flags |= g_DefaultButtons[i].flags; button->flags |= g_DefaultButtons[i].flags;
button->aspect = g_DefaultButtons[i].aspect; button->aspect = g_DefaultButtons[i].aspect;
} }
@@ -882,66 +855,51 @@ static void Touch_AddButton_f( void )
{ {
rgba_t color; rgba_t color;
int argc = Cmd_Argc( ); int argc = Cmd_Argc( );
touch_button_t *button = NULL;
const char *name, *texture, *command;
float x1, y1, x2, y2;
qboolean privileged = Cmd_CurrentCommandIsPrivileged();
if( argc < 4 ) if( argc >= 12 )
{ {
Con_Printf( S_USAGE "touch_addbutton <name> <texture> <command> [<x1> <y1> <x2> <y2> [ r g b a ] ]\n" ); touch_button_t *button;
MakeRGBA( color, Q_atoi( Cmd_Argv(8) ), Q_atoi( Cmd_Argv(9) ),
Q_atoi( Cmd_Argv(10) ), Q_atoi( Cmd_Argv(11) ) );
button = Touch_AddButton( &touch.list_user, Cmd_Argv(1), Cmd_Argv(2), Cmd_Argv(3),
Q_atof( Cmd_Argv(4) ), Q_atof( Cmd_Argv(5) ),
Q_atof( Cmd_Argv(6) ), Q_atof( Cmd_Argv(7) ) ,
color );
if( argc >= 13 )
{
button->flags = Q_atoi( Cmd_Argv(12) );
}
if( argc >= 14 )
{
// Recalculate button coordinates aspect ratio
// This is feature for distributed configs
float aspect = Q_atof( Cmd_Argv(13) );
if( aspect )
{
if( B(texturefile)[0] != '#' )
B(y2) = B(y1) + ( B(x2) - B(x1) ) * (SCR_W/SCR_H) * aspect;
B(aspect) = aspect;
}
}
return; return;
} }
if( argc == 8 )
name = Cmd_Argv( 1 );
texture = Cmd_Argv( 2 );
command = Cmd_Argv( 3 );
if( argc < 8 )
{
x1 = y1 = 0.4f;
x2 = y2 = 0.6f;
}
else
{
x1 = Q_atof( Cmd_Argv( 4 ));
y1 = Q_atof( Cmd_Argv( 5 ));
x2 = Q_atof( Cmd_Argv( 6 ));
y2 = Q_atof( Cmd_Argv( 7 ));
}
if( argc < 12 )
{ {
MakeRGBA( color, 255, 255, 255, 255 ); MakeRGBA( color, 255, 255, 255, 255 );
Touch_AddButton( &touch.list_user, Cmd_Argv(1), Cmd_Argv(2), Cmd_Argv(3),
Q_atof( Cmd_Argv(4) ), Q_atof( Cmd_Argv(5) ),
Q_atof( Cmd_Argv(6) ), Q_atof( Cmd_Argv(7) ),
color );
return;
} }
else if( argc == 4 )
{ {
MakeRGBA( color, MakeRGBA( color, 255, 255, 255, 255 );
Q_atoi( Cmd_Argv( 8 )), Touch_AddButton( &touch.list_user, Cmd_Argv(1), Cmd_Argv(2), Cmd_Argv(3), 0.4, 0.4, 0.6, 0.6, color );
Q_atoi( Cmd_Argv( 9 )), return;
Q_atoi( Cmd_Argv( 10 )),
Q_atoi( Cmd_Argv( 11 )));
}
button = Touch_AddButton( &touch.list_user, name, texture, command, x1, y1, x2, y2, color, privileged );
if( argc >= 13 )
{
SetBits( button->flags, Q_atoi( Cmd_Argv( 12 )));
}
if( argc >= 14 )
{
// Recalculate button coordinates aspect ratio
// This is feature for distributed configs
float aspect = Q_atof( Cmd_Argv( 13 ));
if( aspect )
{
if( B( texturefile )[0] != '#' )
B( y2 ) = B( y1 ) + ( B( x2 ) - B( x1 )) * ( SCR_W / SCR_H ) * aspect;
B( aspect ) = aspect;
}
} }
Con_Printf( S_USAGE "touch_addbutton <name> <texture> <command> [<x1> <y1> <x2> <y2> [ r g b a ] ]\n" );
} }
static void Touch_EnableEdit_f( void ) static void Touch_EnableEdit_f( void )
@@ -967,7 +925,7 @@ static void Touch_DisableEdit_f( void )
{ {
Cvar_Set( "touch_in_menu", "0" ); Cvar_Set( "touch_in_menu", "0" );
} }
else if( cls.key_dest == key_game ) else if( cls.key_dest == key_game )
Touch_WriteConfig(); Touch_WriteConfig();
} }
@@ -988,29 +946,26 @@ static void Touch_InitEditor( void )
float x = 0.1f * (SCR_H/SCR_W); float x = 0.1f * (SCR_H/SCR_W);
float y = 0.05f; float y = 0.05f;
touch_button_t *temp; touch_button_t *temp;
rgba_t color;
MakeRGBA( color, 255, 255, 255, 255 );
Touch_ClearList( &touch.list_edit ); Touch_ClearList( &touch.list_edit );
temp = Touch_AddButton( &touch.list_edit, "close", "touch_default/edit_close", "touch_disableedit", 0, y, x, y + 0.1f, color, true ); temp = Touch_AddButton( &touch.list_edit, "close", "touch_default/edit_close.tga", "touch_disableedit", 0, y, x, y + 0.1f, (byte*)"\xff\xff\xff\xff" );
SetBits( temp->flags, TOUCH_FL_NOEDIT ); SetBits( temp->flags, TOUCH_FL_NOEDIT );
temp = Touch_AddButton( &touch.list_edit, "close", "#Close and save", "", x, y, x + 0.2f, y + 0.1f, color, true ); temp = Touch_AddButton( &touch.list_edit, "close", "#Close and save", "", x, y, x + 0.2f, y + 0.1f, (byte*)"\xff\xff\xff\xff" );
SetBits( temp->flags, TOUCH_FL_NOEDIT ); SetBits( temp->flags, TOUCH_FL_NOEDIT );
y += 0.2f; y += 0.2f;
temp = Touch_AddButton( &touch.list_edit, "cancel", "touch_default/edit_reset", "touch_reloadconfig", 0, y, x, y + 0.1f, color, true ); temp = Touch_AddButton( &touch.list_edit, "cancel", "touch_default/edit_reset.tga", "touch_reloadconfig", 0, y, x, y + 0.1f, (byte*)"\xff\xff\xff\xff" );
SetBits( temp->flags, TOUCH_FL_NOEDIT ); SetBits( temp->flags, TOUCH_FL_NOEDIT );
temp = Touch_AddButton( &touch.list_edit, "close", "#Cancel and reset", "", x, y, x + 0.2f, y + 0.1f, color, true ); temp = Touch_AddButton( &touch.list_edit, "close", "#Cancel and reset", "", x, y, x + 0.2f, y + 0.1f, (byte*)"\xff\xff\xff\xff" );
SetBits( temp->flags, TOUCH_FL_NOEDIT ); SetBits( temp->flags, TOUCH_FL_NOEDIT );
y += 0.2f; y += 0.2f;
touch.hidebutton = Touch_AddButton( &touch.list_edit, "showhide", "touch_default/edit_hide", "touch_toggleselection", 0, y, x, y + 0.1f, color, true ); touch.hidebutton = Touch_AddButton( &touch.list_edit, "showhide", "touch_default/edit_hide.tga", "touch_toggleselection", 0, y, x, y + 0.1f, (byte*)"\xff\xff\xff\xff" );
SetBits( touch.hidebutton->flags, TOUCH_FL_HIDE | TOUCH_FL_NOEDIT ); SetBits( touch.hidebutton->flags, TOUCH_FL_HIDE | TOUCH_FL_NOEDIT );
} }
@@ -1038,79 +993,79 @@ void Touch_Init( void )
MakeRGBA( color, 255, 255, 255, 255 ); MakeRGBA( color, 255, 255, 255, 255 );
Touch_AddDefaultButton( "look", "", "_look", 0.500000, 0.000000, 1.000000, 1, color, 0, 0, 0 ); Touch_AddDefaultButton( "look", "", "_look", 0.500000, 0.000000, 1.000000, 1, color, 0, 0, 0 );
Touch_AddDefaultButton( "move", "", "_move", 0.000000, 0.000000, 0.500000, 1, color, 0, 0, 0 ); Touch_AddDefaultButton( "move", "", "_move", 0.000000, 0.000000, 0.500000, 1, color, 0, 0, 0 );
Touch_AddDefaultButton( "invnext", "touch_default/next_weap", "invnext", 0.000000, 0.530200, 0.120000, 0.757428, color, 2, 1, 0 ); Touch_AddDefaultButton( "invnext", "touch_default/next_weap.tga", "invnext", 0.000000, 0.530200, 0.120000, 0.757428, color, 2, 1, 0 );
Touch_AddDefaultButton( "invprev", "touch_default/prev_weap", "invprev", 0.000000, 0.075743, 0.120000, 0.302971, color, 2, 1, 0 ); Touch_AddDefaultButton( "invprev", "touch_default/prev_weap.tga", "invprev", 0.000000, 0.075743, 0.120000, 0.302971, color, 2, 1, 0 );
Touch_AddDefaultButton( "use", "touch_default/use", "+use", 0.880000, 0.454457, 1.000000, 0.681685, color, 2, 1, 0 ); Touch_AddDefaultButton( "use", "touch_default/use.tga", "+use", 0.880000, 0.454457, 1.000000, 0.681685, color, 2, 1, 0 );
Touch_AddDefaultButton( "jump", "touch_default/jump", "+jump", 0.880000, 0.227228, 1.000000, 0.454457, color, 2, 1, 0 ); Touch_AddDefaultButton( "jump", "touch_default/jump.tga", "+jump", 0.880000, 0.227228, 1.000000, 0.454457, color, 2, 1, 0 );
Touch_AddDefaultButton( "attack", "touch_default/shoot", "+attack", 0.760000, 0.530200, 0.880000, 0.757428, color, 2, 1, 0 ); Touch_AddDefaultButton( "attack", "touch_default/shoot.tga", "+attack", 0.760000, 0.530200, 0.880000, 0.757428, color, 2, 1, 0 );
Touch_AddDefaultButton( "attack2", "touch_default/shoot_alt", "+attack2", 0.760000, 0.302971, 0.880000, 0.530200, color, 2, 1, 0 ); Touch_AddDefaultButton( "attack2", "touch_default/shoot_alt.tga", "+attack2", 0.760000, 0.302971, 0.880000, 0.530200, color, 2, 1, 0 );
Touch_AddDefaultButton( "loadquick", "touch_default/load", "loadquick", 0.760000, 0.000000, 0.840000, 0.151486, color, 2, 1, 16 ); Touch_AddDefaultButton( "loadquick", "touch_default/load.tga", "loadquick", 0.760000, 0.000000, 0.840000, 0.151486, color, 2, 1, 16 );
Touch_AddDefaultButton( "savequick", "touch_default/save", "savequick", 0.840000, 0.000000, 0.920000, 0.151486, color, 2, 1, 16 ); Touch_AddDefaultButton( "savequick", "touch_default/save.tga", "savequick", 0.840000, 0.000000, 0.920000, 0.151486, color, 2, 1, 16 );
Touch_AddDefaultButton( "messagemode", "touch_default/keyboard", "messagemode", 0.840000, 0.000000, 0.920000, 0.151486, color, 2, 1, 8 ); Touch_AddDefaultButton( "messagemode", "touch_default/keyboard.tga", "messagemode", 0.840000, 0.000000, 0.920000, 0.151486, color, 2, 1, 8 );
Touch_AddDefaultButton( "reload", "touch_default/reload", "+reload", 0.000000, 0.302971, 0.120000, 0.530200, color, 2, 1, 0 ); Touch_AddDefaultButton( "reload", "touch_default/reload.tga", "+reload", 0.000000, 0.302971, 0.120000, 0.530200, color, 2, 1, 0 );
Touch_AddDefaultButton( "flashlight", "touch_default/flash_light_filled", "impulse 100", 0.920000, 0.000000, 1.000000, 0.151486, color, 2, 1, 0 ); Touch_AddDefaultButton( "flashlight", "touch_default/flash_light_filled.tga", "impulse 100", 0.920000, 0.000000, 1.000000, 0.151486, color, 2, 1, 0 );
Touch_AddDefaultButton( "scores", "touch_default/map", "+showscores", 0.760000, 0.000000, 0.840000, 0.151486, color, 2, 1, 8 ); Touch_AddDefaultButton( "scores", "touch_default/map.tga", "+showscores", 0.760000, 0.000000, 0.840000, 0.151486, color, 2, 1, 8 );
Touch_AddDefaultButton( "show_numbers", "touch_default/show_weapons", "exec touch_default/numbers.cfg", 0.440000, 0.833171, 0.520000, 0.984656, color, 2, 1, 0 ); Touch_AddDefaultButton( "show_numbers", "touch_default/show_weapons.tga", "exec touch_default/numbers.cfg", 0.440000, 0.833171, 0.520000, 0.984656, color, 2, 1, 0 );
Touch_AddDefaultButton( "duck", "touch_default/crouch", "+duck", 0.880000, 0.757428, 1.000000, 0.984656, color, 2, 1, 0 ); Touch_AddDefaultButton( "duck", "touch_default/crouch.tga", "+duck", 0.880000, 0.757428, 1.000000, 0.984656, color, 2, 1, 0 );
Touch_AddDefaultButton( "tduck", "touch_default/tduck", ";+duck", 0.560000, 0.833171, 0.620000, 0.946785, color, 2, 1, 0 ); Touch_AddDefaultButton( "tduck", "touch_default/tduck.tga", ";+duck", 0.560000, 0.833171, 0.620000, 0.946785, color, 2, 1, 0 );
Touch_AddDefaultButton( "edit", "touch_default/settings", "touch_enableedit", 0.420000, 0.000000, 0.500000, 0.151486, color, 2, 1, 32 ); Touch_AddDefaultButton( "edit", "touch_default/settings.tga", "touch_enableedit", 0.420000, 0.000000, 0.500000, 0.151486, color, 2, 1, 32 );
Touch_AddDefaultButton( "menu", "touch_default/menu", "escape", 0.000000, 0.833171, 0.080000, 0.984656, color, 2, 1, 0 ); Touch_AddDefaultButton( "menu", "touch_default/menu.tga", "escape", 0.000000, 0.833171, 0.080000, 0.984656, color, 2, 1, 0 );
Cmd_AddCommand( "touch_addbutton", Touch_AddButton_f, "add native touch button" ); Cmd_AddCommand( "touch_addbutton", Touch_AddButton_f, "add native touch button" );
Cmd_AddCommand( "touch_removebutton", IN_TouchRemoveButton_f, "remove native touch button" ); Cmd_AddCommand( "touch_removebutton", IN_TouchRemoveButton_f, "remove native touch button" );
Cmd_AddRestrictedCommand( "touch_enableedit", Touch_EnableEdit_f, "enable button editing mode" ); Cmd_AddCommand( "touch_enableedit", Touch_EnableEdit_f, "enable button editing mode" );
Cmd_AddRestrictedCommand( "touch_disableedit", Touch_DisableEdit_f, "disable button editing mode" ); Cmd_AddCommand( "touch_disableedit", Touch_DisableEdit_f, "disable button editing mode" );
Cmd_AddCommand( "touch_settexture", Touch_SetTexture_f, "change button texture" ); Cmd_AddCommand( "touch_settexture", Touch_SetTexture_f, "change button texture" );
Cmd_AddCommand( "touch_setcolor", Touch_SetColor_f, "change button color" ); Cmd_AddCommand( "touch_setcolor", Touch_SetColor_f, "change button color" );
Cmd_AddCommand( "touch_setcommand", Touch_SetCommand_f, "change button command" ); Cmd_AddCommand( "touch_setcommand", Touch_SetCommand_f, "change button command" );
Cmd_AddCommand( "touch_setflags", Touch_SetFlags_f, "change button flags (be careful)" ); Cmd_AddCommand( "touch_setflags", Touch_SetFlags_f, "change button flags (be careful)" );
Cmd_AddCommand( "touch_show", Touch_Show_f, "show button" ); Cmd_AddCommand( "touch_show", Touch_Show_f, "show button" );
Cmd_AddCommand( "touch_hide", Touch_Hide_f, "hide button" ); Cmd_AddCommand( "touch_hide", Touch_Hide_f, "hide button" );
Cmd_AddRestrictedCommand( "touch_list", Touch_ListButtons_f, "list buttons" ); Cmd_AddCommand( "touch_list", Touch_ListButtons_f, "list buttons" );
Cmd_AddRestrictedCommand( "touch_removeall", Touch_RemoveAll_f, "remove all buttons" ); Cmd_AddCommand( "touch_removeall", Touch_RemoveAll_f, "remove all buttons" );
Cmd_AddRestrictedCommand( "touch_loaddefaults", Touch_LoadDefaults_f, "generate config from defaults" ); Cmd_AddCommand( "touch_loaddefaults", Touch_LoadDefaults_f, "generate config from defaults" );
Cmd_AddRestrictedCommand( "touch_roundall", Touch_RoundAll_f, "round all buttons coordinates to grid" ); Cmd_AddCommand( "touch_roundall", Touch_RoundAll_f, "round all buttons coordinates to grid" );
Cmd_AddRestrictedCommand( "touch_exportconfig", Touch_ExportConfig_f, "export config keeping aspect ratio" ); Cmd_AddCommand( "touch_exportconfig", Touch_ExportConfig_f, "export config keeping aspect ratio" );
Cmd_AddCommand( "touch_set_stroke", Touch_Stroke_f, "set global stroke width and color" ); Cmd_AddCommand( "touch_set_stroke", Touch_Stroke_f, "set global stroke width and color" );
Cmd_AddCommand( "touch_setclientonly", Touch_SetClientOnly_f, "when 1, only client buttons are shown" ); Cmd_AddCommand( "touch_setclientonly", Touch_SetClientOnly_f, "when 1, only client buttons are shown" );
Cmd_AddRestrictedCommand( "touch_reloadconfig", Touch_ReloadConfig_f, "load config, not saving changes" ); Cmd_AddCommand( "touch_reloadconfig", Touch_ReloadConfig_f, "load config, not saving changes" );
Cmd_AddRestrictedCommand( "touch_writeconfig", Touch_WriteConfig, "save current config" ); Cmd_AddCommand( "touch_writeconfig", Touch_WriteConfig, "save current config" );
Cmd_AddRestrictedCommand( "touch_deleteprofile", Touch_DeleteProfile_f, "delete profile by name" ); Cmd_AddCommand( "touch_deleteprofile", Touch_DeleteProfile_f, "delete profile by name" );
Cmd_AddRestrictedCommand( "touch_generate_code", Touch_GenerateCode_f, "create code sample for mobility API" ); Cmd_AddCommand( "touch_generate_code", Touch_GenerateCode_f, "create code sample for mobility API" );
Cmd_AddCommand( "touch_fade", Touch_Fade_f, "start fade animation for selected buttons" ); Cmd_AddCommand( "touch_fade", Touch_Fade_f, "start fade animation for selected buttons" );
Cmd_AddRestrictedCommand( "touch_toggleselection", Touch_ToggleSelection_f, "toggle vidibility on selected button in editor" ); Cmd_AddCommand( "touch_toggleselection", Touch_ToggleSelection_f, "toggle vidibility on selected button in editor" );
// not saved, just runtime state for scripting // not saved, just runtime state for scripting
touch_in_menu = Cvar_Get( "touch_in_menu", "0", FCVAR_FILTERABLE, "draw touch in menu (for internal use only)" ); touch_in_menu = Cvar_Get( "touch_in_menu", "0", 0, "draw touch in menu (for internal use only)" );
// sensitivity configuration // sensitivity configuration
touch_forwardzone = Cvar_Get( "touch_forwardzone", "0.06", FCVAR_FILTERABLE, "forward touch zone" ); touch_forwardzone = Cvar_Get( "touch_forwardzone", "0.06", 0, "forward touch zone" );
touch_sidezone = Cvar_Get( "touch_sidezone", "0.06", FCVAR_FILTERABLE, "side touch zone" ); touch_sidezone = Cvar_Get( "touch_sidezone", "0.06", 0, "side touch zone" );
touch_pitch = Cvar_Get( "touch_pitch", "90", FCVAR_FILTERABLE, "touch pitch sensitivity" ); touch_pitch = Cvar_Get( "touch_pitch", "90", 0, "touch pitch sensitivity" );
touch_yaw = Cvar_Get( "touch_yaw", "120", FCVAR_FILTERABLE, "touch yaw sensitivity" ); touch_yaw = Cvar_Get( "touch_yaw", "120", 0, "touch yaw sensitivity" );
touch_nonlinear_look = Cvar_Get( "touch_nonlinear_look", "0", FCVAR_FILTERABLE, "enable nonlinear touch look" ); touch_nonlinear_look = Cvar_Get( "touch_nonlinear_look", "0", 0, "enable nonlinear touch look" );
touch_pow_factor = Cvar_Get( "touch_pow_factor", "1.3", FCVAR_FILTERABLE, "set > 1 to enable" ); touch_pow_factor = Cvar_Get( "touch_pow_factor", "1.3", 0, "set > 1 to enable" );
touch_pow_mult = Cvar_Get( "touch_pow_mult", "400.0", FCVAR_FILTERABLE, "power multiplier, usually 200-1000" ); touch_pow_mult = Cvar_Get( "touch_pow_mult", "400.0", 0, "power multiplier, usually 200-1000" );
touch_exp_mult = Cvar_Get( "touch_exp_mult", "0", FCVAR_FILTERABLE, "exponent multiplier, usually 20-200, 0 to disable" ); touch_exp_mult = Cvar_Get( "touch_exp_mult", "0", 0, "exponent multiplier, usually 20-200, 0 to disable" );
// touch.cfg // touch.cfg
touch_grid_count = Cvar_Get( "touch_grid_count", "50", FCVAR_FILTERABLE, "touch grid count" ); touch_grid_count = Cvar_Get( "touch_grid_count", "50", 0, "touch grid count" );
touch_grid_enable = Cvar_Get( "touch_grid_enable", "1", FCVAR_FILTERABLE, "enable touch grid" ); touch_grid_enable = Cvar_Get( "touch_grid_enable", "1", 0, "enable touch grid" );
touch_config_file = Cvar_Get( "touch_config_file", "touch.cfg", FCVAR_ARCHIVE | FCVAR_PRIVILEGED, "current touch profile file" ); touch_config_file = Cvar_Get( "touch_config_file", "touch.cfg", FCVAR_ARCHIVE, "current touch profile file" );
touch_precise_amount = Cvar_Get( "touch_precise_amount", "0.5", FCVAR_FILTERABLE, "sensitivity multiplier for precise-look" ); touch_precise_amount = Cvar_Get( "touch_precise_amount", "0.5", 0, "sensitivity multiplier for precise-look" );
touch_highlight_r = Cvar_Get( "touch_highlight_r", "1.0", 0, "highlight r color" ); touch_highlight_r = Cvar_Get( "touch_highlight_r", "1.0", 0, "highlight r color" );
touch_highlight_g = Cvar_Get( "touch_highlight_g", "1.0", 0, "highlight g color" ); touch_highlight_g = Cvar_Get( "touch_highlight_g", "1.0", 0, "highlight g color" );
touch_highlight_b = Cvar_Get( "touch_highlight_b", "1.0", 0, "highlight b color" ); touch_highlight_b = Cvar_Get( "touch_highlight_b", "1.0", 0, "highlight b color" );
touch_highlight_a = Cvar_Get( "touch_highlight_a", "1.0", 0, "highlight alpha" ); touch_highlight_a = Cvar_Get( "touch_highlight_a", "1.0", 0, "highlight alpha" );
touch_dpad_radius = Cvar_Get( "touch_dpad_radius", "1.0", FCVAR_FILTERABLE, "dpad radius multiplier" ); touch_dpad_radius = Cvar_Get( "touch_dpad_radius", "1.0", 0, "dpad radius multiplier" );
touch_joy_radius = Cvar_Get( "touch_joy_radius", "1.0", FCVAR_FILTERABLE, "joy radius multiplier" ); touch_joy_radius = Cvar_Get( "touch_joy_radius", "1.0", 0, "joy radius multiplier" );
touch_move_indicator = Cvar_Get( "touch_move_indicator", "0.0", FCVAR_FILTERABLE, "indicate move events (0 to disable)" ); touch_move_indicator = Cvar_Get( "touch_move_indicator", "0.0", 0, "indicate move events (0 to disable)" );
touch_joy_texture = Cvar_Get( "touch_joy_texture", "touch_default/joy", FCVAR_FILTERABLE, "texture for move indicator"); touch_joy_texture = Cvar_Get( "touch_joy_texture", "touch_default/joy.tga", 0, "texture for move indicator");
// input devices cvar // input devices cvar
touch_enable = Cvar_Get( "touch_enable", DEFAULT_TOUCH_ENABLE, FCVAR_ARCHIVE | FCVAR_FILTERABLE, "enable touch controls" ); touch_enable = Cvar_Get( "touch_enable", DEFAULT_TOUCH_ENABLE, FCVAR_ARCHIVE, "enable touch controls" );
touch_emulate = Cvar_Get( "touch_emulate", "0", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "emulate touch with mouse" ); touch_emulate = Cvar_Get( "touch_emulate", "0", FCVAR_ARCHIVE, "emulate touch with mouse" );
/// TODO: touch sdl platform /// TODO: touch sdl platform
// SDL_SetHint( SDL_HINT_ANDROID_SEPARATE_MOUSE_AND_TOUCH, "1" ); // SDL_SetHint( SDL_HINT_ANDROID_SEPARATE_MOUSE_AND_TOUCH, "1" );
@@ -1515,9 +1470,9 @@ static void Touch_EditMove( touchEventType type, int fingerID, float x, float y,
touch.hidebutton->flags &= ~TOUCH_FL_HIDE; touch.hidebutton->flags &= ~TOUCH_FL_HIDE;
if( FBitSet( button->flags, TOUCH_FL_HIDE )) if( FBitSet( button->flags, TOUCH_FL_HIDE ))
Q_strcpy( touch.hidebutton->texturefile, "touch_default/edit_show" ); Q_strcpy( touch.hidebutton->texturefile, "touch_default/edit_show.tga" );
else else
Q_strcpy( touch.hidebutton->texturefile, "touch_default/edit_hide" ); Q_strcpy( touch.hidebutton->texturefile, "touch_default/edit_hide.tga" );
} }
} }
if( type == event_motion ) // shutdown button move if( type == event_motion ) // shutdown button move
@@ -1675,9 +1630,7 @@ static qboolean Touch_ButtonPress( touchbuttonlist_t *list, touchEventType type,
// command down: just execute command // command down: just execute command
Q_snprintf( command, sizeof( command ), "%s\n", button->command ); Q_snprintf( command, sizeof( command ), "%s\n", button->command );
if( FBitSet( B( flags ), TOUCH_FL_UNPRIVILEGED )) Cbuf_AddText( command );
Cbuf_AddFilteredText( command );
else Cbuf_AddText( command );
// increase precision // increase precision
if( FBitSet( B(flags), TOUCH_FL_PRECISION )) if( FBitSet( B(flags), TOUCH_FL_PRECISION ))
@@ -1701,9 +1654,7 @@ static qboolean Touch_ButtonPress( touchbuttonlist_t *list, touchEventType type,
Q_snprintf( touch.wheel_end, sizeof( touch.wheel_end ), "%s\n", Cmd_Argv( 3 ) ); Q_snprintf( touch.wheel_end, sizeof( touch.wheel_end ), "%s\n", Cmd_Argv( 3 ) );
if( Q_snprintf( command, sizeof( command ), "%s\n", Cmd_Argv( 4 ) ) > 1) if( Q_snprintf( command, sizeof( command ), "%s\n", Cmd_Argv( 4 ) ) > 1)
{ {
if( FBitSet( B( flags ), TOUCH_FL_UNPRIVILEGED )) Cbuf_AddText( command );
Cbuf_AddFilteredText( command );
else Cbuf_AddText( command );
touch.wheel_count++; touch.wheel_count++;
} }
@@ -1825,12 +1776,8 @@ static qboolean Touch_ButtonPress( touchbuttonlist_t *list, touchEventType type,
char command[256]; char command[256];
Q_snprintf( command, sizeof( command ), "%s\n", button->command ); Q_snprintf( command, sizeof( command ), "%s\n", button->command );
command[0] = '-'; command[0] = '-';
Cbuf_AddText( command );
if( FBitSet( B( flags ), TOUCH_FL_UNPRIVILEGED ))
Cbuf_AddFilteredText( command );
else Cbuf_AddText( command );
} }
// disable precision mode // disable precision mode
@@ -1844,11 +1791,7 @@ static qboolean Touch_ButtonPress( touchbuttonlist_t *list, touchEventType type,
if( button->type == touch_wheel ) if( button->type == touch_wheel )
{ {
if( touch.wheel_count ) if( touch.wheel_count )
{ Cbuf_AddText( touch.wheel_end );
if( FBitSet( B( flags ), TOUCH_FL_UNPRIVILEGED ))
Cbuf_AddFilteredText( touch.wheel_end );
else Cbuf_AddText( touch.wheel_end );
}
// disable precision mode // disable precision mode
if( B(flags) & TOUCH_FL_PRECISION ) if( B(flags) & TOUCH_FL_PRECISION )

View File

@@ -18,7 +18,7 @@ GNU General Public License for more details.
#include "client.h" #include "client.h"
#include "vgui_draw.h" #include "vgui_draw.h"
#if XASH_SDL #ifdef XASH_SDL
#include <SDL.h> #include <SDL.h>
#endif #endif
@@ -30,16 +30,17 @@ qboolean in_mouseinitialized;
qboolean in_mouse_suspended; qboolean in_mouse_suspended;
POINT in_lastvalidpos; POINT in_lastvalidpos;
qboolean in_mouse_savedpos; qboolean in_mouse_savedpos;
static int in_mstate = 0;
static struct inputstate_s static struct inputstate_s
{ {
float lastpitch, lastyaw; float lastpitch, lastyaw;
} inputstate; } inputstate;
extern convar_t *vid_fullscreen; extern convar_t *vid_fullscreen;
convar_t *m_enginemouse;
convar_t *m_pitch; convar_t *m_pitch;
convar_t *m_yaw; convar_t *m_yaw;
convar_t *m_enginesens;
convar_t *m_ignore; convar_t *m_ignore;
convar_t *cl_forwardspeed; convar_t *cl_forwardspeed;
convar_t *cl_sidespeed; convar_t *cl_sidespeed;
@@ -47,8 +48,6 @@ convar_t *cl_backspeed;
convar_t *look_filter; convar_t *look_filter;
convar_t *m_rawinput; convar_t *m_rawinput;
static qboolean s_bRawInput, s_bMouseGrab;
/* /*
================ ================
IN_CollectInputDevices IN_CollectInputDevices
@@ -112,12 +111,14 @@ IN_StartupMouse
*/ */
void IN_StartupMouse( void ) void IN_StartupMouse( void )
{ {
m_ignore = Cvar_Get( "m_ignore", DEFAULT_M_IGNORE, FCVAR_ARCHIVE | FCVAR_FILTERABLE, "ignore mouse events" ); m_ignore = Cvar_Get( "m_ignore", DEFAULT_M_IGNORE, FCVAR_ARCHIVE , "ignore mouse events" );
m_pitch = Cvar_Get( "m_pitch", "0.022", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "mouse pitch value" ); m_enginemouse = Cvar_Get( "m_enginemouse", "0", FCVAR_ARCHIVE, "read mouse events in engine instead of client" );
m_yaw = Cvar_Get( "m_yaw", "0.022", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "mouse yaw value" ); m_enginesens = Cvar_Get( "m_enginesens", "0.3", FCVAR_ARCHIVE, "mouse sensitivity, when m_enginemouse enabled" );
look_filter = Cvar_Get( "look_filter", "0", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "filter look events making it smoother" ); m_pitch = Cvar_Get( "m_pitch", "0.022", FCVAR_ARCHIVE, "mouse pitch value" );
m_rawinput = Cvar_Get( "m_rawinput", "1", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "enable mouse raw input" ); m_yaw = Cvar_Get( "m_yaw", "0.022", FCVAR_ARCHIVE, "mouse yaw value" );
look_filter = Cvar_Get( "look_filter", "0", FCVAR_ARCHIVE, "filter look events making it smoother" );
m_rawinput = Cvar_Get( "m_rawinput", "1", FCVAR_ARCHIVE, "enable mouse raw input" );
// You can use -nomouse argument to prevent using mouse from client // You can use -nomouse argument to prevent using mouse from client
// -noenginemouse will disable all mouse input // -noenginemouse will disable all mouse input
@@ -126,9 +127,21 @@ void IN_StartupMouse( void )
in_mouseinitialized = true; in_mouseinitialized = true;
} }
static void IN_ActivateCursor( void )
{
if( cls.key_dest == key_menu )
{
#ifdef XASH_SDL
SDL_SetCursor( in_mousecursor );
#endif
}
}
void GAME_EXPORT IN_SetCursor( void *hCursor ) void GAME_EXPORT IN_SetCursor( void *hCursor )
{ {
// stub in_mousecursor = hCursor;
IN_ActivateCursor();
} }
/* /*
@@ -177,15 +190,47 @@ void IN_ToggleClientMouse( int newstate, int oldstate )
if( oldstate == key_game ) if( oldstate == key_game )
{ {
IN_DeactivateMouse(); if( cls.initialized )
clgame.dllFuncs.IN_DeactivateMouse();
} }
else if( newstate == key_game ) else if( newstate == key_game )
{ {
IN_ActivateMouse(); // reset mouse pos, so cancel effect in game
#if SDL_VERSION_ATLEAST( 2, 0, 0 )
if( CVAR_TO_BOOL( touch_enable ) )
{
SDL_SetRelativeMouseMode( SDL_FALSE );
SDL_SetWindowGrab( host.hWnd, SDL_FALSE );
}
else
#endif
{
Platform_SetMousePos( host.window_center_x, host.window_center_y );
#if XASH_SDL
SDL_SetWindowGrab( host.hWnd, SDL_TRUE );
#if SDL_VERSION_ATLEAST( 2, 0, 0 )
if ( clgame.dllFuncs.pfnLookEvent || ( clgame.client_dll_uses_sdl && CVAR_TO_BOOL( m_rawinput ) ) )
{
SDL_SetRelativeMouseMode( SDL_TRUE );
}
#endif
#endif // XASH_SDL
}
if( cls.initialized )
clgame.dllFuncs.IN_ActivateMouse();
} }
if( ( newstate == key_menu || newstate == key_console || newstate == key_message ) && ( !CL_IsBackgroundMap() || CL_IsBackgroundDemo( ))) if( ( newstate == key_menu || newstate == key_console || newstate == key_message ) && ( !CL_IsBackgroundMap() || CL_IsBackgroundDemo( )))
{ {
#ifdef XASH_SDL
SDL_SetWindowGrab(host.hWnd, SDL_FALSE);
#if SDL_VERSION_ATLEAST( 2, 0, 0 )
if ( clgame.dllFuncs.pfnLookEvent || ( clgame.client_dll_uses_sdl && CVAR_TO_BOOL( m_rawinput ) ) )
{
SDL_SetRelativeMouseMode( SDL_FALSE );
}
#endif
#endif // XASH_SDL
#if XASH_ANDROID #if XASH_ANDROID
Android_ShowMouse( true ); Android_ShowMouse( true );
#endif #endif
@@ -204,65 +249,6 @@ void IN_ToggleClientMouse( int newstate, int oldstate )
} }
} }
void IN_CheckMouseState( qboolean active )
{
#if XASH_WIN32
qboolean useRawInput = CVAR_TO_BOOL( m_rawinput ) && clgame.client_dll_uses_sdl || clgame.dllFuncs.pfnLookEvent;
#else
qboolean useRawInput = true; // always use SDL code
#endif
if( active && useRawInput && !host.mouse_visible && cls.state == ca_active )
{
if( !s_bRawInput )
{
#if XASH_SDL == 2
SDL_GetRelativeMouseState( NULL, NULL );
SDL_SetRelativeMouseMode( SDL_TRUE );
#endif
// Con_Printf( "Enable relative mode\n" );
s_bRawInput = true;
}
}
else
{
if( s_bRawInput )
{
#if XASH_SDL == 2
SDL_GetRelativeMouseState( NULL, NULL );
SDL_SetRelativeMouseMode( SDL_FALSE );
#endif
// Con_Printf( "Disable relative mode\n" );
s_bRawInput = false;
}
}
if( active && !host.mouse_visible && cls.state == ca_active )
{
if( !s_bMouseGrab )
{
#if XASH_SDL
SDL_SetWindowGrab( host.hWnd, SDL_TRUE );
#endif
// Con_Printf( "Enable grab\n" );
s_bMouseGrab = true;
}
}
else
{
if( s_bMouseGrab )
{
#if XASH_SDL
SDL_SetWindowGrab( host.hWnd, SDL_FALSE );
#endif
// Con_Printf( "Disable grab\n" );
s_bMouseGrab = false;
}
}
}
/* /*
=========== ===========
IN_ActivateMouse IN_ActivateMouse
@@ -270,15 +256,58 @@ IN_ActivateMouse
Called when the window gains focus or changes in some way Called when the window gains focus or changes in some way
=========== ===========
*/ */
void IN_ActivateMouse( void ) void IN_ActivateMouse( qboolean force )
{ {
int width, height;
static int oldstate;
if( !in_mouseinitialized ) if( !in_mouseinitialized )
return; return;
IN_CheckMouseState( true ); if( CL_Active() && host.mouse_visible && !force )
if( clgame.dllFuncs.IN_ActivateMouse ) return; // VGUI controls
clgame.dllFuncs.IN_ActivateMouse();
if( cls.key_dest == key_menu && !Cvar_VariableInteger( "fullscreen" ))
{
// check for mouse leave-entering
if( !in_mouse_suspended && !UI_MouseInRect( ))
in_mouse_suspended = true;
if( oldstate != in_mouse_suspended )
{
if( in_mouse_suspended )
{
#ifdef XASH_SDL
/// TODO: Platform_ShowCursor
if( !touch_emulate )
SDL_ShowCursor( SDL_FALSE );
#endif
UI_ShowCursor( false );
}
}
oldstate = in_mouse_suspended;
if( in_mouse_suspended )
{
in_mouse_suspended = false;
in_mouseactive = false; // re-initialize mouse
UI_ShowCursor( true );
}
}
if( in_mouseactive ) return;
in_mouseactive = true; in_mouseactive = true;
if( UI_IsVisible( )) return;
if( cls.key_dest == key_game )
{
clgame.dllFuncs.IN_ActivateMouse();
#ifdef XASH_SDL
SDL_GetRelativeMouseState( 0, 0 ); // Reset mouse position
#endif
}
} }
/* /*
@@ -290,17 +319,20 @@ Called when the window loses focus
*/ */
void IN_DeactivateMouse( void ) void IN_DeactivateMouse( void )
{ {
if( !in_mouseinitialized ) if( !in_mouseinitialized || !in_mouseactive )
return; return;
IN_CheckMouseState( false ); if( cls.key_dest == key_game )
if( clgame.dllFuncs.IN_DeactivateMouse ) {
clgame.dllFuncs.IN_DeactivateMouse(); clgame.dllFuncs.IN_DeactivateMouse();
}
in_mouseactive = false; in_mouseactive = false;
#ifdef XASH_SDL
SDL_SetWindowGrab( host.hWnd, SDL_FALSE );
#endif // XASH_SDL
} }
/* /*
================ ================
IN_MouseMove IN_MouseMove
@@ -310,7 +342,7 @@ void IN_MouseMove( void )
{ {
POINT current_pos; POINT current_pos;
if( !in_mouseinitialized ) if( !in_mouseinitialized || !in_mouseactive || !UI_IsVisible( ))
return; return;
// find mouse movement // find mouse movement
@@ -320,13 +352,15 @@ void IN_MouseMove( void )
// HACKHACK: show cursor in UI, as mainui doesn't call // HACKHACK: show cursor in UI, as mainui doesn't call
// platform-dependent SetCursor anymore // platform-dependent SetCursor anymore
#if XASH_SDL #ifdef XASH_SDL
if( UI_IsVisible() ) if( UI_IsVisible() )
SDL_ShowCursor( SDL_TRUE ); SDL_ShowCursor( SDL_TRUE );
#endif #endif
// if the menu is visible, move the menu cursor // if the menu is visible, move the menu cursor
UI_MouseMove( current_pos.x, current_pos.y ); UI_MouseMove( current_pos.x, current_pos.y );
IN_ActivateCursor();
} }
/* /*
@@ -334,32 +368,73 @@ void IN_MouseMove( void )
IN_MouseEvent IN_MouseEvent
=========== ===========
*/ */
void IN_MouseEvent( int key, int down ) void IN_MouseEvent( void )
{ {
int i; int i;
if( !in_mouseinitialized ) // touch emu: handle motion
if( CVAR_TO_BOOL( touch_emulate ))
{
if( Key_IsDown( K_SHIFT ) )
Touch_KeyEvent( K_MOUSE2, 2 );
else
Touch_KeyEvent( K_MOUSE1, 2 );
}
if( !in_mouseinitialized || !in_mouseactive )
return; return;
if( down )
SetBits( in_mstate, BIT( key )); if( m_ignore->value )
else ClearBits( in_mstate, BIT( key )); return;
if( cls.key_dest == key_game ) if( cls.key_dest == key_game )
{ {
// perform button actions #if defined( XASH_SDL )
VGui_KeyEvent( K_MOUSE1 + key, down ); static qboolean ignore; // igonre mouse warp event
int x, y;
Platform_GetMousePos(&x, &y);
if( host.mouse_visible )
SDL_ShowCursor( SDL_TRUE );
else if( !CVAR_TO_BOOL( touch_emulate ) )
SDL_ShowCursor( SDL_FALSE );
// don't do Key_Event here if( x < host.window_center_x / 2 ||
// client may override IN_MouseEvent y < host.window_center_y / 2 ||
// but by default it calls back to Key_Event anyway x > host.window_center_x + host.window_center_x / 2 ||
if( in_mouseactive ) y > host.window_center_y + host.window_center_y / 2 )
clgame.dllFuncs.IN_MouseEvent( in_mstate ); {
Platform_SetMousePos( host.window_center_x, host.window_center_y );
ignore = 1; // next mouse event will be mouse warp
return;
}
if ( !ignore )
{
if( !m_enginemouse->value )
{
// a1ba: mouse keys are now separated
// so pass 0 here
clgame.dllFuncs.IN_MouseEvent( 0 );
}
}
else
{
SDL_GetRelativeMouseState( 0, 0 ); // reset relative state
ignore = 0;
}
#endif
return;
} }
else else
{ {
// perform button actions #if XASH_SDL && !XASH_WIN32
Key_Event( K_MOUSE1 + key, down ); #if SDL_VERSION_ATLEAST( 2, 0, 0 )
SDL_SetRelativeMouseMode( SDL_FALSE );
#endif // SDL_VERSION_ATLEAST( 2, 0, 0 )
SDL_ShowCursor( SDL_TRUE );
#endif // XASH_SDL && !XASH_WIN32
IN_MouseMove();
} }
} }
@@ -387,9 +462,9 @@ IN_Init
*/ */
void IN_Init( void ) void IN_Init( void )
{ {
cl_forwardspeed = Cvar_Get( "cl_forwardspeed", "400", FCVAR_ARCHIVE | FCVAR_CLIENTDLL | FCVAR_FILTERABLE, "Default forward move speed" ); cl_forwardspeed = Cvar_Get( "cl_forwardspeed", "400", FCVAR_ARCHIVE | FCVAR_CLIENTDLL, "Default forward move speed" );
cl_backspeed = Cvar_Get( "cl_backspeed", "400", FCVAR_ARCHIVE | FCVAR_CLIENTDLL | FCVAR_FILTERABLE, "Default back move speed" ); cl_backspeed = Cvar_Get( "cl_backspeed", "400", FCVAR_ARCHIVE | FCVAR_CLIENTDLL, "Default back move speed" );
cl_sidespeed = Cvar_Get( "cl_sidespeed", "400", FCVAR_ARCHIVE | FCVAR_CLIENTDLL | FCVAR_FILTERABLE, "Default side move speed" ); cl_sidespeed = Cvar_Get( "cl_sidespeed", "400", FCVAR_ARCHIVE | FCVAR_CLIENTDLL, "Default side move speed" );
if( !Host_IsDedicated() ) if( !Host_IsDedicated() )
{ {
@@ -496,9 +571,13 @@ static void IN_JoyAppendMove( usercmd_t *cmd, float forwardmove, float sidemove
} }
} }
static void IN_CollectInput( float *forward, float *side, float *pitch, float *yaw, qboolean includeMouse ) void IN_CollectInput( float *forward, float *side, float *pitch, float *yaw, qboolean includeMouse, qboolean includeSdlMouse )
{ {
if( includeMouse ) if( includeMouse
#if XASH_SDL
&& includeSdlMouse
#endif
)
{ {
float x, y; float x, y;
Platform_MouseMove( &x, &y ); Platform_MouseMove( &x, &y );
@@ -547,7 +626,7 @@ void IN_EngineAppendMove( float frametime, void *cmd1, qboolean active )
{ {
float sensitivity = 1;//( (float)cl.local.scr_fov / (float)90.0f ); float sensitivity = 1;//( (float)cl.local.scr_fov / (float)90.0f );
IN_CollectInput( &forward, &side, &pitch, &yaw, false ); IN_CollectInput( &forward, &side, &pitch, &yaw, in_mouseinitialized && !CVAR_TO_BOOL( m_ignore ), m_enginemouse->value );
IN_JoyAppendMove( cmd, forward, side ); IN_JoyAppendMove( cmd, forward, side );
@@ -556,36 +635,11 @@ void IN_EngineAppendMove( float frametime, void *cmd1, qboolean active )
cmd->viewangles[YAW] += yaw * sensitivity; cmd->viewangles[YAW] += yaw * sensitivity;
cmd->viewangles[PITCH] += pitch * sensitivity; cmd->viewangles[PITCH] += pitch * sensitivity;
cmd->viewangles[PITCH] = bound( -90, cmd->viewangles[PITCH], 90 ); cmd->viewangles[PITCH] = bound( -90, cmd->viewangles[PITCH], 90 );
VectorCopy( cmd->viewangles, cl.viewangles ); VectorCopy(cmd->viewangles, cl.viewangles);
} }
} }
} }
void IN_Commands( void )
{
#ifdef XASH_USE_EVDEV
IN_EvdevFrame();
#endif
if( clgame.dllFuncs.pfnLookEvent )
{
float forward = 0, side = 0, pitch = 0, yaw = 0;
IN_CollectInput( &forward, &side, &pitch, &yaw, in_mouseinitialized && !CVAR_TO_BOOL( m_ignore ) );
if( cls.key_dest == key_game )
{
clgame.dllFuncs.pfnLookEvent( yaw, pitch );
clgame.dllFuncs.pfnMoveEvent( forward, side );
}
}
if( !in_mouseinitialized )
return;
IN_CheckMouseState( in_mouseactive );
}
/* /*
================== ==================
Host_InputFrame Host_InputFrame
@@ -595,9 +649,45 @@ Called every frame, even if not generating commands
*/ */
void Host_InputFrame( void ) void Host_InputFrame( void )
{ {
qboolean shutdownMouse = false;
float forward = 0, side = 0, pitch = 0, yaw = 0;
Sys_SendKeyEvents (); Sys_SendKeyEvents ();
IN_Commands(); #ifdef XASH_USE_EVDEV
IN_EvdevFrame();
#endif
if( clgame.dllFuncs.pfnLookEvent )
{
IN_CollectInput( &forward, &side, &pitch, &yaw, in_mouseinitialized && !CVAR_TO_BOOL( m_ignore ), true );
if( cls.key_dest == key_game )
{
clgame.dllFuncs.pfnLookEvent( yaw, pitch );
clgame.dllFuncs.pfnMoveEvent( forward, side );
}
}
if( !in_mouseinitialized )
return;
if( host.status != HOST_FRAME )
{
IN_DeactivateMouse();
return;
}
// release mouse during pause or console typeing
if( cl.paused && cls.key_dest == key_game )
shutdownMouse = true;
if( shutdownMouse && !Cvar_VariableInteger( "fullscreen" ))
{
IN_DeactivateMouse();
return;
}
IN_ActivateMouse( false );
IN_MouseMove(); IN_MouseMove();
} }

View File

@@ -33,8 +33,8 @@ extern qboolean in_mouseinitialized;
void IN_Init( void ); void IN_Init( void );
void Host_InputFrame( void ); void Host_InputFrame( void );
void IN_Shutdown( void ); void IN_Shutdown( void );
void IN_MouseEvent( int key, int down ); void IN_MouseEvent( void );
void IN_ActivateMouse( void ); void IN_ActivateMouse( qboolean force );
void IN_DeactivateMouse( void ); void IN_DeactivateMouse( void );
void IN_MouseSavePos( void ); void IN_MouseSavePos( void );
void IN_MouseRestorePos( void ); void IN_MouseRestorePos( void );
@@ -61,9 +61,12 @@ extern convar_t *touch_enable;
extern convar_t *touch_emulate; extern convar_t *touch_emulate;
void Touch_Draw( void ); void Touch_Draw( void );
void Touch_SetClientOnly( byte state ); void Touch_SetClientOnly( qboolean state );
void Touch_RemoveButton( const char *name, qboolean privileged ); void Touch_RemoveButton( const char *name );
void Touch_HideButtons( const char *name, unsigned char hide, qboolean privileged ); void Touch_HideButtons( const char *name, unsigned char hide );
//void IN_TouchSetCommand( const char *name, const char *command );
//void IN_TouchSetTexture( const char *name, const char *texture );
//void IN_TouchSetColor( const char *name, byte *color );
void Touch_AddClientButton( const char *name, const char *texture, const char *command, float x1, float y1, float x2, float y2, byte *color, int round, float aspect, int flags ); void Touch_AddClientButton( const char *name, const char *texture, const char *command, float x1, float y1, float x2, float y2, byte *color, int round, float aspect, int flags );
void Touch_AddDefaultButton( const char *name, const char *texturefile, const char *command, float x1, float y1, float x2, float y2, byte *color, int round, float aspect, int flags ); void Touch_AddDefaultButton( const char *name, const char *texturefile, const char *command, float x1, float y1, float x2, float y2, byte *color, int round, float aspect, int flags );
void Touch_WriteConfig( void ); void Touch_WriteConfig( void );

View File

@@ -462,7 +462,6 @@ Writes lines containing "bind key value"
void Key_WriteBindings( file_t *f ) void Key_WriteBindings( file_t *f )
{ {
int i; int i;
string newCommand;
if( !f ) return; if( !f ) return;
@@ -473,8 +472,7 @@ void Key_WriteBindings( file_t *f )
if( !COM_CheckString( keys[i].binding )) if( !COM_CheckString( keys[i].binding ))
continue; continue;
Cmd_Escape( newCommand, keys[i].binding, sizeof( newCommand )); FS_Printf( f, "bind %s \"%s\"\n", Key_KeynumToString( i ), keys[i].binding );
FS_Printf( f, "bind %s \"%s\"\n", Key_KeynumToString( i ), newCommand );
} }
} }
@@ -514,18 +512,18 @@ void Key_Init( void )
keyname_t *kn; 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_AddCommand( "bind", Key_Bind_f, "binds a command to the specified key in bindmap" );
Cmd_AddRestrictedCommand( "unbind", Key_Unbind_f, "removes a command on the specified key in bindmap" ); Cmd_AddCommand( "unbind", Key_Unbind_f, "removes a command on the specified key in bindmap" );
Cmd_AddRestrictedCommand( "unbindall", Key_Unbindall_f, "removes all commands from all keys in bindmap" ); Cmd_AddCommand( "unbindall", Key_Unbindall_f, "removes all commands from all keys in bindmap" );
Cmd_AddRestrictedCommand( "resetkeys", Key_Reset_f, "reset all keys to their default values" ); Cmd_AddCommand( "resetkeys", Key_Reset_f, "reset all keys to their default values" );
Cmd_AddCommand( "bindlist", Key_Bindlist_f, "display current key bindings" ); Cmd_AddCommand( "bindlist", Key_Bindlist_f, "display current key bindings" );
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( kn = keynames; kn->name; kn++ ) Key_SetBinding( kn->keynum, kn->binding ); for( kn = keynames; kn->name; kn++ ) Key_SetBinding( kn->keynum, kn->binding );
osk_enable = Cvar_Get( "osk_enable", "0", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "enable built-in on-screen keyboard" ); osk_enable = Cvar_Get( "osk_enable", "0", FCVAR_ARCHIVE, "enable built-in on-screen keyboard" );
key_rotate = Cvar_Get( "key_rotate", "0", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "rotate arrow keys (0-3)" ); key_rotate = Cvar_Get( "key_rotate", "0", FCVAR_ARCHIVE, "rotate arrow keys (0-3)" );
} }
@@ -814,9 +812,9 @@ void Key_EnableTextInput( qboolean enable, qboolean force )
OSK_EnableTextInput( enable, force ); OSK_EnableTextInput( enable, force );
return; return;
} }
if( enable && ( !host.textmode || force )) if( enable && ( !host.textmode || force ) )
Platform_EnableTextInput( true ); Platform_EnableTextInput( true );
else if( !enable && ( host.textmode || force )) else if( !enable )
Platform_EnableTextInput( false ); Platform_EnableTextInput( false );
host.textmode = enable; host.textmode = enable;
@@ -1044,7 +1042,7 @@ static qboolean OSK_KeyEvent( int key, int down )
else else
osk.curlayout++; osk.curlayout++;
osk.shift = true; osk.shift = osk.curbutton.val == OSK_SHIFT;
osk.curbutton.val = osk_keylayout[osk.curlayout][osk.curbutton.y][osk.curbutton.x]; osk.curbutton.val = osk_keylayout[osk.curlayout][osk.curbutton.y][osk.curbutton.x];
break; break;
case OSK_BACKSPACE: case OSK_BACKSPACE:

View File

@@ -13,7 +13,7 @@ convar_t *gl_showtextures;
convar_t *r_decals; convar_t *r_decals;
convar_t *r_adjust_fov; convar_t *r_adjust_fov;
convar_t *r_showtree; convar_t *r_showtree;
convar_t *gl_msaa_samples; convar_t *gl_wgl_msaa_samples;
convar_t *gl_clear; convar_t *gl_clear;
convar_t *r_refdll; convar_t *r_refdll;
@@ -151,7 +151,7 @@ static player_info_t *pfnPlayerInfo( int index )
if( index == -1 ) // special index for menu if( index == -1 ) // special index for menu
return &gameui.playerinfo; return &gameui.playerinfo;
if( index < 0 || index >= cl.maxclients ) if( index < 0 || index > cl.maxclients )
return NULL; return NULL;
return &cl.players[index]; return &cl.players[index];
@@ -334,6 +334,10 @@ static ref_api_t gEngfuncs =
COM_FreeLibrary, COM_FreeLibrary,
COM_GetProcAddress, COM_GetProcAddress,
FS_LoadFile,
FS_FileExists,
FS_AllowDirectPaths,
R_Init_Video_, R_Init_Video_,
R_Free_Video, R_Free_Video,
@@ -379,9 +383,7 @@ static ref_api_t gEngfuncs =
pfnDrawNormalTriangles, pfnDrawNormalTriangles,
pfnDrawTransparentTriangles, pfnDrawTransparentTriangles,
&clgame.drawFuncs, &clgame.drawFuncs
&g_fsapi,
}; };
static void R_UnloadProgs( void ) static void R_UnloadProgs( void )
@@ -640,28 +642,11 @@ qboolean R_Init( void )
gl_showtextures = Cvar_Get( "r_showtextures", "0", FCVAR_CHEAT, "show all uploaded textures" ); gl_showtextures = Cvar_Get( "r_showtextures", "0", FCVAR_CHEAT, "show all uploaded textures" );
r_adjust_fov = Cvar_Get( "r_adjust_fov", "1", FCVAR_ARCHIVE, "making FOV adjustment for wide-screens" ); r_adjust_fov = Cvar_Get( "r_adjust_fov", "1", FCVAR_ARCHIVE, "making FOV adjustment for wide-screens" );
r_decals = Cvar_Get( "r_decals", "4096", FCVAR_ARCHIVE, "sets the maximum number of decals" ); r_decals = Cvar_Get( "r_decals", "4096", FCVAR_ARCHIVE, "sets the maximum number of decals" );
gl_msaa_samples = Cvar_Get( "gl_msaa_samples", "0", FCVAR_GLCONFIG, "samples number for multisample anti-aliasing" ); gl_wgl_msaa_samples = Cvar_Get( "gl_wgl_msaa_samples", "0", FCVAR_GLCONFIG, "samples number for multisample anti-aliasing" );
gl_clear = Cvar_Get( "gl_clear", "0", FCVAR_ARCHIVE, "clearing screen after each frame" ); gl_clear = Cvar_Get( "gl_clear", "0", FCVAR_ARCHIVE, "clearing screen after each frame" );
r_showtree = Cvar_Get( "r_showtree", "0", FCVAR_ARCHIVE, "build the graph of visible BSP tree" ); r_showtree = Cvar_Get( "r_showtree", "0", FCVAR_ARCHIVE, "build the graph of visible BSP tree" );
r_refdll = Cvar_Get( "r_refdll", "", FCVAR_RENDERINFO|FCVAR_VIDRESTART, "choose renderer implementation, if supported" ); r_refdll = Cvar_Get( "r_refdll", "", FCVAR_RENDERINFO|FCVAR_VIDRESTART, "choose renderer implementation, if supported" );
// cvars that are expected to exist
Cvar_Get( "r_speeds", "0", FCVAR_ARCHIVE, "shows renderer speeds" );
Cvar_Get( "r_fullbright", "0", FCVAR_CHEAT, "disable lightmaps, get fullbright for entities" );
Cvar_Get( "r_norefresh", "0", 0, "disable 3D rendering (use with caution)" );
Cvar_Get( "r_dynamic", "1", FCVAR_ARCHIVE, "allow dynamic lighting (dlights, lightstyles)" );
Cvar_Get( "r_lightmap", "0", FCVAR_CHEAT, "lightmap debugging tool" );
Cvar_Get( "tracerred", "0.8", 0, "tracer red component weight ( 0 - 1.0 )" );
Cvar_Get( "tracergreen", "0.8", 0, "tracer green component weight ( 0 - 1.0 )" );
Cvar_Get( "tracerblue", "0.4", 0, "tracer blue component weight ( 0 - 1.0 )" );
Cvar_Get( "traceralpha", "0.5", 0, "tracer alpha amount ( 0 - 1.0 )" );
Cvar_Get( "r_sprite_lerping", "1", FCVAR_ARCHIVE, "enables sprite animation lerping" );
Cvar_Get( "r_sprite_lighting", "1", FCVAR_ARCHIVE, "enables sprite lighting (blood etc)" );
Cvar_Get( "r_drawviewmodel", "1", 0, "draw firstperson weapon model" );
Cvar_Get( "r_glowshellfreq", "2.2", 0, "glowing shell frequency update" );
// cvars that are expected to exist by client.dll // cvars that are expected to exist by client.dll
// refdll should just get pointer to them // refdll should just get pointer to them
Cvar_Get( "r_drawentities", "1", FCVAR_CHEAT, "render entities" ); Cvar_Get( "r_drawentities", "1", FCVAR_CHEAT, "render entities" );

View File

@@ -33,6 +33,7 @@ GNU General Public License for more details.
#define MAXDLY (STEREODLY + 1) #define MAXDLY (STEREODLY + 1)
#define MAXLP 10 #define MAXLP 10
#define MAXPRESETS 29
typedef struct sx_preset_s typedef struct sx_preset_s
{ {
@@ -78,7 +79,7 @@ typedef struct dly_s
int *lpdelayline; int *lpdelayline;
} dly_t; } dly_t;
const sx_preset_t rgsxpre[] = const sx_preset_t rgsxpre[MAXPRESETS] =
{ {
// -------reverb-------- -------delay-------- // -------reverb-------- -------delay--------
// lp mod size refl rvblp delay feedback dlylp left // lp mod size refl rvblp delay feedback dlylp left
@@ -115,7 +116,7 @@ const sx_preset_t rgsxpre[] =
// 0x0045dca8 enginegl.exe // 0x0045dca8 enginegl.exe
// SHA256: 42383d32cd712e59ee2c1bd78b7ba48814e680e7026c4223e730111f34a60d66 // SHA256: 42383d32cd712e59ee2c1bd78b7ba48814e680e7026c4223e730111f34a60d66
const sx_preset_t rgsxpre_hlalpha052[] = const sx_preset_t rgsxpre_hlalpha052[MAXPRESETS] =
{ {
// -------reverb-------- -------delay-------- // -------reverb-------- -------delay--------
// lp mod size refl rvblp delay feedback dlylp left // lp mod size refl rvblp delay feedback dlylp left
@@ -481,7 +482,7 @@ void DLY_CheckNewDelayVal( void )
} }
else else
{ {
delay = Q_min( delay, MAX_MONO_DELAY ); delay = min( delay, MAX_MONO_DELAY );
dly->delaysamples = (int)(delay * idsp_dma_speed) << sxhires; dly->delaysamples = (int)(delay * idsp_dma_speed) << sxhires;
// init dly // init dly
@@ -881,7 +882,7 @@ void CheckNewDspPresets( void )
else idsp_room = room_type->value; else idsp_room = room_type->value;
// don't pass invalid presets // don't pass invalid presets
idsp_room = bound( 0, idsp_room, MAX_ROOM_TYPES ); idsp_room = bound( 0, idsp_room, MAXPRESETS - 1 );
if( FBitSet( hisound->flags, FCVAR_CHANGED )) if( FBitSet( hisound->flags, FCVAR_CHANGED ))
{ {
@@ -892,6 +893,9 @@ void CheckNewDspPresets( void )
if( idsp_room == room_typeprev && idsp_room == 0 ) if( idsp_room == room_typeprev && idsp_room == 0 )
return; return;
if( idsp_room > MAX_ROOM_TYPES )
return;
if( idsp_room != room_typeprev ) if( idsp_room != room_typeprev )
{ {
const sx_preset_t *cur; const sx_preset_t *cur;

View File

@@ -35,18 +35,18 @@ int total_channels;
int soundtime; // sample PAIRS int soundtime; // sample PAIRS
int paintedtime; // sample PAIRS int paintedtime; // sample PAIRS
static CVAR_DEFINE( s_volume, "volume", "0.7", FCVAR_ARCHIVE|FCVAR_FILTERABLE, "sound volume" ); static CVAR_DEFINE( s_volume, "volume", "0.7", FCVAR_ARCHIVE, "sound volume" );
CVAR_DEFINE( s_musicvolume, "MP3Volume", "1.0", FCVAR_ARCHIVE|FCVAR_FILTERABLE, "background music volume" ); CVAR_DEFINE( s_musicvolume, "MP3Volume", "1.0", FCVAR_ARCHIVE, "background music volume" );
static CVAR_DEFINE( s_mixahead, "_snd_mixahead", "0.12", FCVAR_FILTERABLE, "how much sound to mix ahead of time" ); static CVAR_DEFINE( s_mixahead, "_snd_mixahead", "0.12", 0, "how much sound to mix ahead of time" );
static CVAR_DEFINE_AUTO( s_show, "0", FCVAR_ARCHIVE|FCVAR_FILTERABLE, "show playing sounds" ); static CVAR_DEFINE_AUTO( s_show, "0", FCVAR_ARCHIVE, "show playing sounds" );
CVAR_DEFINE_AUTO( s_lerping, "0", FCVAR_ARCHIVE|FCVAR_FILTERABLE, "apply interpolation to sound output" ); CVAR_DEFINE_AUTO( s_lerping, "0", FCVAR_ARCHIVE, "apply interpolation to sound output" );
static CVAR_DEFINE( s_ambient_level, "ambient_level", "0.3", FCVAR_ARCHIVE|FCVAR_FILTERABLE, "volume of environment noises (water and wind)" ); static CVAR_DEFINE( s_ambient_level, "ambient_level", "0.3", FCVAR_ARCHIVE, "volume of environment noises (water and wind)" );
static CVAR_DEFINE( s_ambient_fade, "ambient_fade", "1000", FCVAR_ARCHIVE|FCVAR_FILTERABLE, "rate of volume fading when client is moving" ); static CVAR_DEFINE( s_ambient_fade, "ambient_fade", "1000", FCVAR_ARCHIVE, "rate of volume fading when client is moving" );
static CVAR_DEFINE_AUTO( s_combine_sounds, "0", FCVAR_ARCHIVE|FCVAR_FILTERABLE, "combine channels with same sounds" ); static CVAR_DEFINE_AUTO( s_combine_sounds, "0", FCVAR_ARCHIVE, "combine channels with same sounds" );
CVAR_DEFINE_AUTO( snd_mute_losefocus, "1", FCVAR_ARCHIVE|FCVAR_FILTERABLE, "silence the audio when game window loses focus" ); CVAR_DEFINE_AUTO( snd_mute_losefocus, "1", FCVAR_ARCHIVE, "silence the audio when game window loses focus" );
CVAR_DEFINE_AUTO( s_test, "0", 0, "engine developer cvar for quick testing new features" ); CVAR_DEFINE_AUTO( s_test, "0", 0, "engine developer cvar for quick testing new features" );
CVAR_DEFINE_AUTO( s_samplecount, "0", FCVAR_ARCHIVE|FCVAR_FILTERABLE, "sample count (0 for default value)" ); CVAR_DEFINE_AUTO( s_samplecount, "0", FCVAR_ARCHIVE, "sample count (0 for default value)" );
CVAR_DEFINE_AUTO( s_warn_late_precache, "0", FCVAR_ARCHIVE|FCVAR_FILTERABLE, "warn about late precached sounds on client-side" ); CVAR_DEFINE_AUTO( s_warn_late_precache, "0", FCVAR_ARCHIVE, "warn about late precached sounds on client-side" );
/* /*
============================================================================= =============================================================================
@@ -788,8 +788,6 @@ void S_AmbientSound( const vec3_t pos, int ent, sound_t handle, float fvol, floa
return; return;
} }
pitch *= (sys_timescale.value + 1) / 2;
// never update positions if source entity is 0 // never update positions if source entity is 0
ch->staticsound = ( ent == 0 ) ? true : false; ch->staticsound = ( ent == 0 ) ? true : false;
ch->use_loop = (flags & SND_STOP_LOOPING) ? false : true; ch->use_loop = (flags & SND_STOP_LOOPING) ? false : true;
@@ -1127,7 +1125,7 @@ static uint S_RawSamplesStereo( portable_samplepair_t *rawsamples, uint rawend,
S_RawEntSamples S_RawEntSamples
=================== ===================
*/ */
void S_RawEntSamples( int entnum, uint samples, uint rate, word width, word channels, const byte *data, int snd_vol ) static void S_RawEntSamples( int entnum, uint samples, uint rate, word width, word channels, const byte *data, int snd_vol )
{ {
rawchan_t *ch; rawchan_t *ch;
@@ -1153,6 +1151,7 @@ void S_RawSamples( uint samples, uint rate, word width, word channels, const byt
int snd_vol = 128; int snd_vol = 128;
if( entnum < 0 ) snd_vol = 256; // bg track or movie track if( entnum < 0 ) snd_vol = 256; // bg track or movie track
if( snd_vol < 0 ) snd_vol = 0; // fixup negative values
S_RawEntSamples( entnum, samples, rate, width, channels, data, snd_vol ); S_RawEntSamples( entnum, samples, rate, width, channels, data, snd_vol );
} }
@@ -1287,9 +1286,6 @@ static void S_FreeIdleRawChannels( void )
if( ch->s_rawend >= paintedtime ) if( ch->s_rawend >= paintedtime )
continue; continue;
if ( ch->entnum > 0 )
SND_ForceCloseMouth( ch->entnum );
if(( paintedtime - ch->s_rawend ) / SOUND_DMA_SPEED >= S_RAW_SOUND_IDLE_SEC ) if(( paintedtime - ch->s_rawend ) / SOUND_DMA_SPEED >= S_RAW_SOUND_IDLE_SEC )
{ {
raw_channels[i] = NULL; raw_channels[i] = NULL;
@@ -1851,7 +1847,7 @@ S_SoundInfo_f
*/ */
void S_SoundInfo_f( void ) void S_SoundInfo_f( void )
{ {
Con_Printf( "Audio backend: %s\n", dma.backendName ); Con_Printf( "Audio: DirectSound\n" );
Con_Printf( "%5d channel(s)\n", 2 ); Con_Printf( "%5d channel(s)\n", 2 );
Con_Printf( "%5d samples\n", dma.samples ); Con_Printf( "%5d samples\n", dma.samples );
Con_Printf( "%5d bits/sample\n", 16 ); Con_Printf( "%5d bits/sample\n", 16 );
@@ -1861,33 +1857,6 @@ void S_SoundInfo_f( void )
S_PrintBackgroundTrackState (); S_PrintBackgroundTrackState ();
} }
/*
=================
S_VoiceRecordStart_f
=================
*/
void S_VoiceRecordStart_f( void )
{
if( cls.state != ca_active || cls.legacymode )
return;
Voice_RecordStart();
}
/*
=================
S_VoiceRecordStop_f
=================
*/
void S_VoiceRecordStop_f( void )
{
if( cls.state != ca_active || !Voice_IsRecording() )
return;
CL_AddVoiceToDatagram();
Voice_RecordStop();
}
/* /*
================ ================
S_Init S_Init
@@ -1922,12 +1891,11 @@ qboolean S_Init( void )
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" );
Cmd_AddCommand( "+voicerecord", S_VoiceRecordStart_f, "start voice recording" ); Cmd_AddCommand( "+voicerecord", Cmd_Null_f, "start voice recording (non-implemented)" );
Cmd_AddCommand( "-voicerecord", S_VoiceRecordStop_f, "stop voice recording" ); Cmd_AddCommand( "-voicerecord", Cmd_Null_f, "stop voice recording (non-implemented)" );
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" );
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" );

View File

@@ -619,8 +619,6 @@ void MIX_MixChannelsToPaintbuffer( int endtime, int rate, int outputRate )
ch->pitch = VOX_ModifyPitch( ch, ch->basePitch * 0.01f ); ch->pitch = VOX_ModifyPitch( ch, ch->basePitch * 0.01f );
else ch->pitch = ch->basePitch * 0.01f; else ch->pitch = ch->basePitch * 0.01f;
ch->pitch *= ( sys_timescale.value + 1 ) / 2;
if( CL_GetEntityByIndex( ch->entnum ) && ( ch->entchannel == CHAN_VOICE )) if( CL_GetEntityByIndex( ch->entnum ) && ( ch->entchannel == CHAN_VOICE ))
{ {
if( pSource->width == 1 ) if( pSource->width == 1 )
@@ -811,7 +809,7 @@ void S_MixBufferUpsample2x( int count, portable_samplepair_t *pbuffer, portable_
// zero out all paintbuffers // zero out all paintbuffers
void MIX_ClearAllPaintBuffers( int SampleCount, qboolean clearFilters ) void MIX_ClearAllPaintBuffers( int SampleCount, qboolean clearFilters )
{ {
int count = Q_min( SampleCount, PAINTBUFFER_SIZE ); int count = min( SampleCount, PAINTBUFFER_SIZE );
int i; int i;
// zero out all paintbuffer data (ignore sampleCount) // zero out all paintbuffer data (ignore sampleCount)
@@ -958,9 +956,6 @@ void MIX_MixRawSamplesBuffer( int end )
pbuf[j-paintedtime].left += ( ch->rawsamples[j & ( ch->max_samples - 1 )].left * ch->leftvol ) >> 8; pbuf[j-paintedtime].left += ( ch->rawsamples[j & ( ch->max_samples - 1 )].left * ch->leftvol ) >> 8;
pbuf[j-paintedtime].right += ( ch->rawsamples[j & ( ch->max_samples - 1 )].right * ch->rightvol ) >> 8; pbuf[j-paintedtime].right += ( ch->rawsamples[j & ( ch->max_samples - 1 )].right * ch->rightvol ) >> 8;
} }
if ( ch->entnum > 0 )
SND_MoveMouthRaw( ch, &ch->rawsamples[paintedtime & ( ch->max_samples - 1 )], stop - paintedtime );
} }
} }

View File

@@ -150,68 +150,3 @@ void SND_MoveMouth16( channel_t *ch, wavdata_t *pSource, int count )
pMouth->sndcount = 0; pMouth->sndcount = 0;
} }
} }
void SND_ForceInitMouth( int entnum )
{
cl_entity_t *clientEntity;
clientEntity = CL_GetEntityByIndex( entnum );
if ( clientEntity )
{
clientEntity->mouth.mouthopen = 0;
clientEntity->mouth.sndavg = 0;
clientEntity->mouth.sndcount = 0;
}
}
void SND_ForceCloseMouth( int entnum )
{
cl_entity_t *clientEntity;
clientEntity = CL_GetEntityByIndex( entnum );
if ( clientEntity )
clientEntity->mouth.mouthopen = 0;
}
void SND_MoveMouthRaw( rawchan_t *ch, portable_samplepair_t *pData, int count )
{
cl_entity_t *clientEntity;
mouth_t *pMouth = NULL;
int savg, data;
int scount = 0;
uint i;
clientEntity = CL_GetEntityByIndex( ch->entnum );
if( !clientEntity ) return;
pMouth = &clientEntity->mouth;
if( pData == NULL )
return;
i = 0;
scount = pMouth->sndcount;
savg = 0;
while ( i < count && scount < CAVGSAMPLES )
{
data = pData[i].left; // mono sound anyway
data = ( bound( -32767, data, 0x7ffe ) >> 8 );
savg += abs( data );
i += 80 + ( (byte)data & 0x1F );
scount++;
}
pMouth->sndavg += savg;
pMouth->sndcount = (byte)scount;
if ( pMouth->sndcount >= CAVGSAMPLES )
{
pMouth->mouthopen = pMouth->sndavg / CAVGSAMPLES;
pMouth->sndavg = 0;
pMouth->sndcount = 0;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -113,11 +113,10 @@ typedef struct snd_format_s
typedef struct typedef struct
{ {
snd_format_t format; snd_format_t format;
int samples; // mono samples in buffer int samples; // mono samples in buffer
int samplepos; // in mono samples int samplepos; // in mono samples
byte *buffer; byte *buffer;
qboolean initialized; // sound engine is active qboolean initialized; // sound engine is active
const char *backendName;
} dma_t; } dma_t;
#include "vox.h" #include "vox.h"
@@ -203,7 +202,7 @@ typedef struct
#define MAX_DYNAMIC_CHANNELS (60 + NUM_AMBIENTS) #define MAX_DYNAMIC_CHANNELS (60 + NUM_AMBIENTS)
#define MAX_CHANNELS (256 + MAX_DYNAMIC_CHANNELS) // Scourge Of Armagon has too many static sounds on hip2m4.bsp #define MAX_CHANNELS (256 + MAX_DYNAMIC_CHANNELS) // Scourge Of Armagon has too many static sounds on hip2m4.bsp
#define MAX_RAW_CHANNELS 48 #define MAX_RAW_CHANNELS 16
#define MAX_RAW_SAMPLES 8192 #define MAX_RAW_SAMPLES 8192
extern sound_t ambient_sfx[NUM_AMBIENTS]; extern sound_t ambient_sfx[NUM_AMBIENTS];
@@ -272,7 +271,6 @@ int S_GetCurrentStaticSounds( soundlist_t *pout, int size );
int S_GetCurrentDynamicSounds( soundlist_t *pout, int size ); int S_GetCurrentDynamicSounds( soundlist_t *pout, int size );
sfx_t *S_GetSfxByHandle( sound_t handle ); sfx_t *S_GetSfxByHandle( sound_t handle );
rawchan_t *S_FindRawChannel( int entnum, qboolean create ); rawchan_t *S_FindRawChannel( int entnum, qboolean create );
void S_RawEntSamples( int entnum, uint samples, uint rate, word width, word channels, const byte *data, int snd_vol );
void S_RawSamples( uint samples, uint rate, word width, word channels, const byte *data, int entnum ); void S_RawSamples( uint samples, uint rate, word width, word channels, const byte *data, int entnum );
void S_StopSound( int entnum, int channel, const char *soundname ); void S_StopSound( int entnum, int channel, const char *soundname );
void S_UpdateFrame( struct ref_viewpass_s *rvp ); void S_UpdateFrame( struct ref_viewpass_s *rvp );
@@ -285,12 +283,9 @@ void S_FreeSounds( void );
// s_mouth.c // s_mouth.c
// //
void SND_InitMouth( int entnum, int entchannel ); void SND_InitMouth( int entnum, int entchannel );
void SND_ForceInitMouth( int entnum );
void SND_MoveMouth8( channel_t *ch, wavdata_t *pSource, int count ); void SND_MoveMouth8( channel_t *ch, wavdata_t *pSource, int count );
void SND_MoveMouth16( channel_t *ch, wavdata_t *pSource, int count ); void SND_MoveMouth16( channel_t *ch, wavdata_t *pSource, int count );
void SND_MoveMouthRaw( rawchan_t *ch, portable_samplepair_t *pData, int count );
void SND_CloseMouth( channel_t *ch ); void SND_CloseMouth( channel_t *ch );
void SND_ForceCloseMouth( int entnum );
// //
// s_stream.c // s_stream.c

View File

@@ -21,13 +21,31 @@ GNU General Public License for more details.
#include "keydefs.h" #include "keydefs.h"
#include "ref_common.h" #include "ref_common.h"
#include "input.h" #include "input.h"
#ifdef XASH_SDL
#include <SDL.h>
static SDL_Cursor* s_pDefaultCursor[20];
#endif
#include "platform/platform.h" #include "platform/platform.h"
static enum VGUI_KeyCode s_pVirtualKeyTrans[256]; static enum VGUI_KeyCode s_pVirtualKeyTrans[256];
static VGUI_DefaultCursor s_currentCursor; static enum VGUI_DefaultCursor s_currentCursor;
static HINSTANCE s_pVGuiSupport; // vgui_support library static HINSTANCE s_pVGuiSupport; // vgui_support library
static convar_t *vgui_utf8 = NULL; static convar_t *vgui_utf8 = NULL;
// Helper functions for vgui backend
/*void VGUI_HideCursor( void )
{
host.mouse_visible = false;
SDL_HideCursor();
}
void VGUI_ShowCursor( void )
{
host.mouse_visible = true;
SDL_ShowCursor();
}*/
void GAME_EXPORT *VGUI_EngineMalloc(size_t size) void GAME_EXPORT *VGUI_EngineMalloc(size_t size)
{ {
return Z_Malloc( size ); return Z_Malloc( size );
@@ -48,10 +66,70 @@ void GAME_EXPORT VGUI_GetMousePos( int *_x, int *_y )
*_x = x / xscale, *_y = y / yscale; *_x = x / xscale, *_y = y / yscale;
} }
void GAME_EXPORT VGUI_CursorSelect( VGUI_DefaultCursor cursor ) void VGUI_InitCursors( void )
{ {
Platform_SetCursorType( cursor ); // load up all default cursors
#if SDL_VERSION_ATLEAST( 2, 0, 0 )
s_pDefaultCursor[dc_none] = NULL;
s_pDefaultCursor[dc_arrow] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_ARROW);
s_pDefaultCursor[dc_ibeam] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_IBEAM);
s_pDefaultCursor[dc_hourglass]= SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_WAIT);
s_pDefaultCursor[dc_crosshair]= SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_CROSSHAIR);
s_pDefaultCursor[dc_up] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_ARROW);
s_pDefaultCursor[dc_sizenwse] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENWSE);
s_pDefaultCursor[dc_sizenesw] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENESW);
s_pDefaultCursor[dc_sizewe] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZEWE);
s_pDefaultCursor[dc_sizens] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENS);
s_pDefaultCursor[dc_sizeall] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZEALL);
s_pDefaultCursor[dc_no] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_NO);
s_pDefaultCursor[dc_hand] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_HAND);
//host.mouse_visible = true;
SDL_SetCursor( s_pDefaultCursor[dc_arrow] );
#endif
}
void GAME_EXPORT VGUI_CursorSelect(enum VGUI_DefaultCursor cursor )
{
qboolean visible;
if( cls.key_dest != key_game || cl.paused )
return;
switch( cursor )
{
case dc_user:
case dc_none:
visible = false;
break;
default:
visible = true;
break;
}
#if SDL_VERSION_ATLEAST( 2, 0, 0 )
/// TODO: platform cursors
if( CVAR_TO_BOOL( touch_emulate ) )
return;
if( host.mouse_visible )
{
SDL_SetRelativeMouseMode( SDL_FALSE );
SDL_SetCursor( s_pDefaultCursor[cursor] );
SDL_ShowCursor( true );
}
else
{
SDL_ShowCursor( false );
if( host.mouse_visible )
SDL_GetRelativeMouseState( NULL, NULL );
Key_EnableTextInput( false, true );
}
//SDL_SetRelativeMouseMode(false);
#endif
if( s_currentCursor == cursor )
return;
s_currentCursor = cursor; s_currentCursor = cursor;
host.mouse_visible = visible;
} }
byte GAME_EXPORT VGUI_GetColor( int i, int j) byte GAME_EXPORT VGUI_GetColor( int i, int j)
@@ -60,9 +138,21 @@ byte GAME_EXPORT VGUI_GetColor( int i, int j)
} }
// Define and initialize vgui API // Define and initialize vgui API
void GAME_EXPORT VGUI_SetVisible( qboolean state )
{
host.mouse_visible=state;
#ifdef XASH_SDL
SDL_ShowCursor( state );
if( !state )
SDL_GetRelativeMouseState( NULL, NULL );
#endif
Key_EnableTextInput( false, true );
}
int GAME_EXPORT VGUI_UtfProcessChar( int in ) int GAME_EXPORT VGUI_UtfProcessChar( int in )
{ {
if( CVAR_TO_BOOL( vgui_utf8 )) if( CVAR_TO_BOOL( vgui_utf8 ) )
return Con_UtfProcessCharForce( in ); return Con_UtfProcessCharForce( in );
else else
return in; return in;
@@ -85,15 +175,14 @@ vguiapi_t vgui =
NULL, // VGUI_GetTextureSizes, NULL, // VGUI_GetTextureSizes,
NULL, // VGUI_GenerateTexture, NULL, // VGUI_GenerateTexture,
VGUI_EngineMalloc, VGUI_EngineMalloc,
/* VGUI_ShowCursor,
VGUI_HideCursor,*/
VGUI_CursorSelect, VGUI_CursorSelect,
VGUI_GetColor, VGUI_GetColor,
VGUI_IsInGame, VGUI_IsInGame,
NULL, VGUI_SetVisible,
VGUI_GetMousePos, VGUI_GetMousePos,
VGUI_UtfProcessChar, VGUI_UtfProcessChar,
Platform_GetClipboardText,
Platform_SetClipboardText,
Platform_GetKeyModifiers,
NULL, NULL,
NULL, NULL,
NULL, NULL,
@@ -101,7 +190,6 @@ vguiapi_t vgui =
NULL, NULL,
NULL, NULL,
NULL, NULL,
NULL
}; };
qboolean VGui_IsActive( void ) qboolean VGui_IsActive( void )
@@ -152,6 +240,7 @@ void VGui_Startup( const char *clientlib, int width, int height )
VGui_FillAPIFromRef( &vgui, &ref.dllFuncs ); VGui_FillAPIFromRef( &vgui, &ref.dllFuncs );
#ifdef XASH_INTERNAL_GAMELIBS
s_pVGuiSupport = COM_LoadLibrary( clientlib, false, false ); s_pVGuiSupport = COM_LoadLibrary( clientlib, false, false );
if( s_pVGuiSupport ) if( s_pVGuiSupport )
@@ -161,70 +250,58 @@ void VGui_Startup( const char *clientlib, int width, int height )
{ {
F( &vgui ); F( &vgui );
vgui.initialized = true; vgui.initialized = true;
Con_Reportf( "vgui_support: found internal client support\n" ); VGUI_InitCursors();
} Con_Reportf( "vgui_support: found interal client support\n" );
else
{
COM_FreeLibrary( s_pVGuiSupport );
} }
} }
#endif // XASH_INTERNAL_GAMELIBS
if( !vgui.initialized ) // HACKHACK: load vgui with correct path first if specified.
// it will be reused while resolving vgui support and client deps
if( Sys_GetParmFromCmdLine( "-vguilib", vguilib ) )
{ {
// HACKHACK: load vgui with correct path first if specified. if( Q_strstr( vguilib, ".dll") )
// it will be reused while resolving vgui support and client deps
if( Sys_GetParmFromCmdLine( "-vguilib", vguilib ))
{
if( Q_strstr( vguilib, ".dll" ))
Q_strncpy( vguiloader, "vgui_support.dll", 256 );
else
Q_strncpy( vguiloader, VGUI_SUPPORT_DLL, 256 );
if( !COM_LoadLibrary( vguilib, false, false ))
Con_Reportf( S_WARN "VGUI preloading failed. Default library will be used! Reason: %s\n", COM_GetLibraryError() );
}
if( Q_strstr( clientlib, ".dll" ))
Q_strncpy( vguiloader, "vgui_support.dll", 256 ); Q_strncpy( vguiloader, "vgui_support.dll", 256 );
else
if( !vguiloader[0] && !Sys_GetParmFromCmdLine( "-vguiloader", vguiloader ))
Q_strncpy( vguiloader, VGUI_SUPPORT_DLL, 256 ); Q_strncpy( vguiloader, VGUI_SUPPORT_DLL, 256 );
s_pVGuiSupport = COM_LoadLibrary( vguiloader, false, false ); if( !COM_LoadLibrary( vguilib, false, false ) )
Con_Reportf( S_WARN "VGUI preloading failed. Default library will be used! Reason: %s\n", COM_GetLibraryError());
}
if( !s_pVGuiSupport ) if( Q_strstr( clientlib, ".dll" ) )
{ Q_strncpy( vguiloader, "vgui_support.dll", 256 );
s_pVGuiSupport = COM_LoadLibrary( va( "../%s", vguiloader ), false, false );
}
if( !s_pVGuiSupport ) if( !vguiloader[0] && !Sys_GetParmFromCmdLine( "-vguiloader", vguiloader ) )
Q_strncpy( vguiloader, VGUI_SUPPORT_DLL, 256 );
s_pVGuiSupport = COM_LoadLibrary( vguiloader, false, false );
if( !s_pVGuiSupport )
{
s_pVGuiSupport = COM_LoadLibrary( va( "../%s", vguiloader ), false, false );
}
if( !s_pVGuiSupport )
{
if( FS_FileExists( vguiloader, false ) )
Con_Reportf( S_ERROR "Failed to load vgui_support library: %s\n", COM_GetLibraryError() );
else
Con_Reportf( "vgui_support: not found\n" );
}
else
{
F = COM_GetProcAddress( s_pVGuiSupport, "InitAPI" );
if( F )
{ {
if( FS_FileExists( vguiloader, false )) F( &vgui );
{ vgui.initialized = true;
Con_Reportf( S_ERROR "Failed to load vgui_support library: %s\n", COM_GetLibraryError() ); VGUI_InitCursors();
}
else
{
Con_Reportf( "vgui_support: not found\n" );
}
failed = true;
} }
else else
{ Con_Reportf( S_ERROR "Failed to find vgui_support library entry point!\n" );
F = COM_GetProcAddress( s_pVGuiSupport, "InitAPI" );
if( F )
{
F( &vgui );
vgui.initialized = true;
}
else
{
Con_Reportf( S_ERROR "Failed to find vgui_support library entry point!\n" );
failed = true;
COM_FreeLibrary( s_pVGuiSupport );
}
}
} }
} }
if( height < 480 ) if( height < 480 )
@@ -421,9 +498,8 @@ void VGui_KeyEvent( int key, int down )
switch( key ) switch( key )
{ {
case K_MOUSE1: case K_MOUSE1:
if( down && host.mouse_visible ) { if( down && host.mouse_visible )
Key_EnableTextInput(true, false); Key_EnableTextInput( true, false );
}
vgui.Mouse( down ? MA_PRESSED : MA_RELEASED, MOUSE_LEFT ); vgui.Mouse( down ? MA_PRESSED : MA_RELEASED, MOUSE_LEFT );
return; return;
case K_MOUSE2: case K_MOUSE2:
@@ -459,7 +535,7 @@ void VGui_MouseMove( int x, int y )
void VGui_Paint( void ) void VGui_Paint( void )
{ {
if( vgui.initialized ) if(vgui.initialized)
vgui.Paint(); vgui.Paint();
} }
@@ -475,9 +551,3 @@ void *GAME_EXPORT VGui_GetPanel( void )
return vgui.GetPanel(); return vgui.GetPanel();
return NULL; return NULL;
} }
void VGui_ReportTextInput( const char *text )
{
if ( vgui.initialized )
vgui.TextInput( text );
}

View File

@@ -33,7 +33,6 @@ void VGui_KeyEvent( int key, int down );
void VGui_MouseMove( int x, int y ); void VGui_MouseMove( int x, int y );
qboolean VGui_IsActive( void ); qboolean VGui_IsActive( void );
void *VGui_GetPanel( void ); void *VGui_GetPanel( void );
void VGui_ReportTextInput( const char *text );
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@@ -190,7 +190,7 @@ void VID_Init( void )
// a1ba: planned to be named vid_mode for compability // a1ba: planned to be named vid_mode for compability
// but supported mode list is filled by backends, so numbers are not portable any more // but supported mode list is filled by backends, so numbers are not portable any more
Cmd_AddRestrictedCommand( "vid_setmode", VID_Mode_f, "display video mode" ); Cmd_AddCommand( "vid_setmode", VID_Mode_f, "display video mode" );
R_Init(); // init renderer R_Init(); // init renderer
} }

View File

@@ -36,7 +36,7 @@ extern convar_t *vid_highdpi;
extern convar_t *vid_rotate; extern convar_t *vid_rotate;
extern convar_t *vid_scale; extern convar_t *vid_scale;
extern convar_t *gl_msaa_samples; extern convar_t *gl_wgl_msaa_samples;
void R_SaveVideoMode( int w, int h, int render_w, int render_h ); void R_SaveVideoMode( int w, int h, int render_w, int render_h );
void VID_CheckChanges( void ); void VID_CheckChanges( void );
const char *VID_GetModeString( int vid_mode ); const char *VID_GetModeString( int vid_mode );

View File

@@ -1,631 +0,0 @@
/*
voice.c - voice chat implementation
Copyright (C) 2022 Velaron
Copyright (C) 2022 SNMetamorph
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.
*/
#define CUSTOM_MODES 1 // required to correctly link with Opus Custom
#include <opus_custom.h>
#include "common.h"
#include "client.h"
#include "voice.h"
voice_state_t voice = { 0 };
CVAR_DEFINE_AUTO( voice_enable, "1", FCVAR_PRIVILEGED|FCVAR_ARCHIVE, "enable voice chat" );
CVAR_DEFINE_AUTO( voice_loopback, "0", FCVAR_PRIVILEGED, "loopback voice back to the speaker" );
CVAR_DEFINE_AUTO( voice_scale, "1.0", FCVAR_PRIVILEGED|FCVAR_ARCHIVE, "incoming voice volume scale" );
CVAR_DEFINE_AUTO( voice_avggain, "0.5", FCVAR_PRIVILEGED|FCVAR_ARCHIVE, "automatic voice gain control (average)" );
CVAR_DEFINE_AUTO( voice_maxgain, "5.0", FCVAR_PRIVILEGED|FCVAR_ARCHIVE, "automatic voice gain control (maximum)" );
CVAR_DEFINE_AUTO( voice_inputfromfile, "0", FCVAR_PRIVILEGED, "input voice from voice_input.wav" );
static void Voice_ApplyGainAdjust( int16_t *samples, int count );
/*
===============================================================================
OPUS INTEGRATION
===============================================================================
*/
/*
=========================
Voice_InitOpusDecoder
=========================
*/
static qboolean Voice_InitOpusDecoder( void )
{
int err;
voice.width = sizeof( opus_int16 );
voice.samplerate = VOICE_OPUS_CUSTOM_SAMPLERATE;
voice.frame_size = VOICE_OPUS_CUSTOM_FRAME_SIZE;
voice.custom_mode = opus_custom_mode_create( SOUND_44k, voice.frame_size, &err );
if( !voice.custom_mode )
{
Con_Printf( S_ERROR "Can't create Opus Custom mode: %s\n", opus_strerror( err ));
return false;
}
voice.decoder = opus_custom_decoder_create( voice.custom_mode, VOICE_PCM_CHANNELS, &err );
if( !voice.decoder )
{
Con_Printf( S_ERROR "Can't create Opus encoder: %s\n", opus_strerror( err ));
return false;
}
return true;
}
/*
=========================
Voice_InitOpusEncoder
=========================
*/
static qboolean Voice_InitOpusEncoder( int quality )
{
int err;
voice.encoder = opus_custom_encoder_create( voice.custom_mode, VOICE_PCM_CHANNELS, &err );
if( !voice.encoder )
{
Con_Printf( S_ERROR "Can't create Opus encoder: %s\n", opus_strerror( err ));
return false;
}
switch( quality )
{
case 1: // 6 kbps
opus_custom_encoder_ctl( voice.encoder, OPUS_SET_BITRATE( 6000 ));
break;
case 2: // 12 kbps
opus_custom_encoder_ctl( voice.encoder, OPUS_SET_BITRATE( 12000 ));
break;
case 4: // 64 kbps
opus_custom_encoder_ctl( voice.encoder, OPUS_SET_BITRATE( 64000 ));
break;
case 5: // 96 kbps
opus_custom_encoder_ctl( voice.encoder, OPUS_SET_BITRATE( 96000 ));
break;
default: // 36 kbps
opus_custom_encoder_ctl( voice.encoder, OPUS_SET_BITRATE( 36000 ));
break;
}
return true;
}
/*
=========================
Voice_ShutdownOpusDecoder
=========================
*/
static void Voice_ShutdownOpusDecoder( void )
{
if( voice.decoder )
{
opus_custom_decoder_destroy( voice.decoder );
voice.decoder = NULL;
}
}
/*
=========================
Voice_ShutdownOpusEncoder
=========================
*/
static void Voice_ShutdownOpusEncoder( void )
{
if( voice.encoder )
{
opus_custom_encoder_destroy( voice.encoder );
voice.encoder = NULL;
}
if( voice.custom_mode )
{
opus_custom_mode_destroy( voice.custom_mode );
voice.custom_mode = NULL;
}
}
/*
=========================
Voice_GetOpusCompressedData
=========================
*/
static uint Voice_GetOpusCompressedData( byte *out, uint maxsize, uint *frames )
{
uint ofs = 0, size = 0;
uint frame_size_bytes = voice.frame_size * voice.width;
if( voice.input_file )
{
uint numbytes;
double updateInterval;
updateInterval = cl.mtime[0] - cl.mtime[1];
numbytes = updateInterval * voice.samplerate * voice.width * VOICE_PCM_CHANNELS;
numbytes = Q_min( numbytes, voice.input_file->size - voice.input_file_pos );
numbytes = Q_min( numbytes, sizeof( voice.input_buffer ) - voice.input_buffer_pos );
memcpy( voice.input_buffer + voice.input_buffer_pos, voice.input_file->buffer + voice.input_file_pos, numbytes );
voice.input_buffer_pos += numbytes;
voice.input_file_pos += numbytes;
}
if( !voice.input_file )
VoiceCapture_Lock( true );
for( ofs = 0; voice.input_buffer_pos - ofs >= frame_size_bytes && ofs <= voice.input_buffer_pos; ofs += frame_size_bytes )
{
int bytes;
#if 1
if( !voice.input_file )
{
// adjust gain before encoding, but only for input from voice
Voice_ApplyGainAdjust((opus_int16*)(voice.input_buffer + ofs), voice.frame_size);
}
#endif
bytes = opus_custom_encode( voice.encoder, (const opus_int16 *)( voice.input_buffer + ofs ),
voice.frame_size, out + size + sizeof( uint16_t ), maxsize );
if( bytes > 0 )
{
// write compressed frame size
*((uint16_t *)&out[size]) = bytes;
size += bytes + sizeof( uint16_t );
maxsize -= bytes + sizeof( uint16_t );
(*frames)++;
}
else
{
Con_Printf( S_ERROR "%s: failed to encode frame: %s\n", __func__, opus_strerror( bytes ));
}
}
// did we compress anything? update counters
if( ofs )
{
fs_offset_t remaining = voice.input_buffer_pos - ofs;
// move remaining samples to the beginning of buffer
memmove( voice.input_buffer, voice.input_buffer + ofs, remaining );
voice.input_buffer_pos = remaining;
}
if( !voice.input_file )
VoiceCapture_Lock( false );
return size;
}
/*
===============================================================================
VOICE CHAT INTEGRATION
===============================================================================
*/
/*
=========================
Voice_ApplyGainAdjust
=========================
*/
static void Voice_ApplyGainAdjust( int16_t *samples, int count )
{
float gain, modifiedMax;
int average, adjustedSample, blockOffset = 0;
for( ;; )
{
int i, localMax = 0, localSum = 0;
int blockSize = Q_min( count - ( blockOffset + voice.autogain.block_size ), voice.autogain.block_size );
if( blockSize < 1 )
break;
for( i = 0; i < blockSize; ++i )
{
int sample = samples[blockOffset + i];
int absSample = abs( sample );
if( absSample > localMax )
localMax = absSample;
localSum += absSample;
gain = voice.autogain.current_gain + i * voice.autogain.gain_multiplier;
adjustedSample = Q_min( SHRT_MAX, Q_max(( int )( sample * gain ), SHRT_MIN ));
samples[blockOffset + i] = adjustedSample;
}
if( blockOffset % voice.autogain.block_size == 0 )
{
average = localSum / blockSize;
modifiedMax = average + ( localMax - average ) * voice_avggain.value;
voice.autogain.current_gain = voice.autogain.next_gain * voice_scale.value;
voice.autogain.next_gain = Q_min( (float)SHRT_MAX / modifiedMax, voice_maxgain.value ) * voice_scale.value;
voice.autogain.gain_multiplier = ( voice.autogain.next_gain - voice.autogain.current_gain ) / ( voice.autogain.block_size - 1 );
}
blockOffset += blockSize;
}
}
/*
=========================
Voice_Status
Notify user dll aboit voice transmission
=========================
*/
static void Voice_Status( int entindex, qboolean bTalking )
{
if( cls.state == ca_active && clgame.dllFuncs.pfnVoiceStatus )
clgame.dllFuncs.pfnVoiceStatus( entindex, bTalking );
}
/*
=========================
Voice_StatusTimeout
Waits few milliseconds and if there was no
voice transmission, sends notification
=========================
*/
static void Voice_StatusTimeout( voice_status_t *status, int entindex, double frametime )
{
if( status->talking_ack )
{
status->talking_timeout += frametime;
if( status->talking_timeout > 0.2 )
{
status->talking_ack = false;
Voice_Status( entindex, false );
}
}
}
/*
=========================
Voice_StatusAck
Sends notification to user dll and
zeroes timeouts for this client
=========================
*/
void Voice_StatusAck( voice_status_t *status, int playerIndex )
{
if( !status->talking_ack )
Voice_Status( playerIndex, true );
status->talking_ack = true;
status->talking_timeout = 0.0;
}
/*
=========================
Voice_IsRecording
=========================
*/
qboolean Voice_IsRecording( void )
{
return voice.is_recording;
}
/*
=========================
Voice_RecordStop
=========================
*/
void Voice_RecordStop( void )
{
if( voice.input_file )
{
FS_FreeSound( voice.input_file );
voice.input_file = NULL;
}
VoiceCapture_Activate( false );
voice.is_recording = false;
Voice_Status( VOICE_LOCALCLIENT_INDEX, false );
voice.input_buffer_pos = 0;
memset( voice.input_buffer, 0, sizeof( voice.input_buffer ));
}
/*
=========================
Voice_RecordStart
=========================
*/
void Voice_RecordStart( void )
{
Voice_RecordStop();
if( voice_inputfromfile.value )
{
voice.input_file = FS_LoadSound( "voice_input.wav", NULL, 0 );
if( voice.input_file )
{
Sound_Process( &voice.input_file, voice.samplerate, voice.width, SOUND_RESAMPLE );
voice.input_file_pos = 0;
voice.start_time = Sys_DoubleTime();
voice.is_recording = true;
}
else
{
FS_FreeSound( voice.input_file );
voice.input_file = NULL;
}
}
if( !Voice_IsRecording() )
voice.is_recording = VoiceCapture_Activate( true );
if( Voice_IsRecording() )
Voice_Status( VOICE_LOCALCLIENT_INDEX, true );
}
/*
=========================
Voice_Disconnect
We're disconnected from server
stop recording and notify user dlls
=========================
*/
void Voice_Disconnect( void )
{
int i;
Voice_RecordStop();
if( voice.local.talking_ack )
{
Voice_Status( VOICE_LOOPBACK_INDEX, false );
voice.local.talking_ack = false;
}
for( i = 0; i < MAX_CLIENTS; i++ )
{
if( voice.players_status[i].talking_ack )
{
Voice_Status( i, false );
voice.players_status[i].talking_ack = false;
}
}
}
/*
=========================
Voice_StartChannel
Feed the decoded data to engine sound subsystem
=========================
*/
static void Voice_StartChannel( uint samples, byte *data, int entnum )
{
SND_ForceInitMouth( entnum );
S_RawEntSamples( entnum, samples, voice.samplerate, voice.width, VOICE_PCM_CHANNELS, data, 255 );
}
/*
=========================
Voice_AddIncomingData
Received encoded voice data, decode it
=========================
*/
void Voice_AddIncomingData( int ent, const byte *data, uint size, uint frames )
{
int samples = 0;
int ofs = 0;
if( !voice.decoder )
return;
// decode frame by frame
for( ;; )
{
int frame_samples;
uint16_t compressed_size;
// no compressed size mark
if( ofs + sizeof( uint16_t ) > size )
break;
compressed_size = *(const uint16_t *)(data + ofs);
ofs += sizeof( uint16_t );
// no frame data
if( ofs + compressed_size > size )
break;
frame_samples = opus_custom_decode( voice.decoder, data + ofs, compressed_size,
(opus_int16*)voice.decompress_buffer + samples, voice.frame_size );
ofs += compressed_size;
samples += frame_samples;
}
if( samples > 0 )
Voice_StartChannel( samples, voice.decompress_buffer, ent );
}
/*
=========================
CL_AddVoiceToDatagram
Encode our voice data and send it to server
=========================
*/
void CL_AddVoiceToDatagram( void )
{
uint size, frames = 0;
if( cls.state != ca_active || !Voice_IsRecording() || !voice.encoder )
return;
size = Voice_GetOpusCompressedData( voice.output_buffer, sizeof( voice.output_buffer ), &frames );
if( size > 0 && MSG_GetNumBytesLeft( &cls.datagram ) >= size + 32 )
{
MSG_BeginClientCmd( &cls.datagram, clc_voicedata );
MSG_WriteByte( &cls.datagram, voice_loopback.value != 0 );
MSG_WriteByte( &cls.datagram, frames );
MSG_WriteShort( &cls.datagram, size );
MSG_WriteBytes( &cls.datagram, voice.output_buffer, size );
}
}
/*
=========================
Voice_RegisterCvars
Register voice related cvars and commands
=========================
*/
void Voice_RegisterCvars( void )
{
Cvar_RegisterVariable( &voice_enable );
Cvar_RegisterVariable( &voice_loopback );
Cvar_RegisterVariable( &voice_scale );
Cvar_RegisterVariable( &voice_avggain );
Cvar_RegisterVariable( &voice_maxgain );
Cvar_RegisterVariable( &voice_inputfromfile );
}
/*
=========================
Voice_Shutdown
Completely shutdown the voice subsystem
=========================
*/
static void Voice_Shutdown( void )
{
int i;
Voice_RecordStop();
Voice_ShutdownOpusEncoder();
Voice_ShutdownOpusDecoder();
VoiceCapture_Shutdown();
if( voice.local.talking_ack )
Voice_Status( VOICE_LOOPBACK_INDEX, false );
for( i = 0; i < MAX_CLIENTS; i++ )
{
if( voice.players_status[i].talking_ack )
Voice_Status( i, false );
}
memset( &voice, 0, sizeof( voice ));
}
/*
=========================
Voice_Idle
Run timeout for all clients
=========================
*/
void Voice_Idle( double frametime )
{
int i;
if( FBitSet( voice_enable.flags, FCVAR_CHANGED ) && !voice_enable.value )
{
Voice_Shutdown();
return;
}
// update local player status first
Voice_StatusTimeout( &voice.local, VOICE_LOOPBACK_INDEX, frametime );
for( i = 0; i < MAX_CLIENTS; i++ )
Voice_StatusTimeout( &voice.players_status[i], i, frametime );
}
/*
=========================
Voice_Init
Initialize the voice subsystem
=========================
*/
qboolean Voice_Init( const char *pszCodecName, int quality )
{
if( !voice_enable.value )
return false;
if( Q_strcmp( pszCodecName, VOICE_OPUS_CUSTOM_CODEC ))
{
Con_Printf( S_ERROR "Server requested unsupported codec: %s\n", pszCodecName );
return false;
}
// reinitialize only if codec parameters are different
if( Q_strcmp( voice.codec, pszCodecName ) && voice.quality != quality )
Voice_Shutdown();
voice.autogain.block_size = 128;
if( !Voice_InitOpusDecoder( ))
{
// no reason to init encoder and open audio device
// if we can't hear other players
Con_Printf( S_ERROR "Voice chat disabled.\n" );
Voice_Shutdown();
return false;
}
// we can hear others players, so it's fine to fail now
voice.initialized = true;
Q_strncpy( voice.codec, pszCodecName, sizeof( voice.codec ));
if( !Voice_InitOpusEncoder( quality ))
{
Con_Printf( S_WARN "Other players will not be able to hear you.\n" );
return false;
}
voice.quality = quality;
if( !VoiceCapture_Init( ))
Con_Printf( S_WARN "No microphone is available.\n" );
return true;
}

View File

@@ -1,104 +0,0 @@
/*
voice.h - voice chat implementation
Copyright (C) 2022 Velaron
Copyright (C) 2022 SNMetamorph
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 VOICE_H
#define VOICE_H
#include "common.h"
#include "protocol.h" // MAX_CLIENTS
#include "sound.h"
typedef struct OpusCustomEncoder OpusCustomEncoder;
typedef struct OpusCustomDecoder OpusCustomDecoder;
typedef struct OpusCustomMode OpusCustomMode;
#define VOICE_LOOPBACK_INDEX (-2)
#define VOICE_LOCALCLIENT_INDEX (-1)
#define VOICE_PCM_CHANNELS 1 // always mono
// never change these parameters when using opuscustom
#define VOICE_OPUS_CUSTOM_SAMPLERATE SOUND_44k
// must follow opus custom requirements
// also be divisible with MAX_RAW_SAMPLES
#define VOICE_OPUS_CUSTOM_FRAME_SIZE 1024
#define VOICE_OPUS_CUSTOM_CODEC "opus_custom_44k_512"
// a1ba: do not change, we don't have any re-encoding support now
#define VOICE_DEFAULT_CODEC VOICE_OPUS_CUSTOM_CODEC
typedef struct voice_status_s
{
qboolean talking_ack;
double talking_timeout;
} voice_status_t;
typedef struct voice_state_s
{
string codec;
int quality;
qboolean initialized;
qboolean is_recording;
double start_time;
voice_status_t local;
voice_status_t players_status[MAX_CLIENTS];
// opus stuff
OpusCustomMode *custom_mode;
OpusCustomEncoder *encoder;
OpusCustomDecoder *decoder;
// audio info
uint width;
uint samplerate;
uint frame_size; // in samples
// buffers
byte input_buffer[MAX_RAW_SAMPLES];
byte output_buffer[MAX_RAW_SAMPLES];
byte decompress_buffer[MAX_RAW_SAMPLES];
fs_offset_t input_buffer_pos; // in bytes
// input from file
wavdata_t *input_file;
fs_offset_t input_file_pos; // in bytes
// automatic gain control
struct {
int block_size;
float current_gain;
float next_gain;
float gain_multiplier;
} autogain;
} voice_state_t;
extern voice_state_t voice;
void CL_AddVoiceToDatagram( void );
void Voice_RegisterCvars( void );
qboolean Voice_Init( const char *pszCodecName, int quality );
void Voice_Idle( double frametime );
qboolean Voice_IsRecording( void );
void Voice_RecordStop( void );
void Voice_RecordStart( void );
void Voice_Disconnect( void );
void Voice_AddIncomingData( int ent, const byte *data, uint size, uint frames );
void Voice_StatusAck( voice_status_t *status, int playerIndex );
#endif // VOICE_H

View File

@@ -16,9 +16,9 @@ GNU General Public License for more details.
#ifndef VOX_H #ifndef VOX_H
#define VOX_H #define VOX_H
#define CVOXWORDMAX 64 #define CVOXWORDMAX 64
#define CVOXFILESENTENCEMAX 4096 #define CVOXZEROSCANMAX 255 // scan up to this many samples for next zero crossing
#define MAX_SENTENCES 4096
#define SENTENCE_INDEX -99999 // unique sentence index #define SENTENCE_INDEX -99999 // unique sentence index
typedef struct voxword_s typedef struct voxword_s
@@ -34,6 +34,13 @@ typedef struct voxword_s
sfx_t *sfx; // name and cache pointer sfx_t *sfx; // name and cache pointer
} voxword_t; } voxword_t;
typedef struct
{
char *pName;
float length;
} sentence_t;
struct channel_s; struct channel_s;
void VOX_LoadWord( struct channel_s *pchan ); void VOX_LoadWord( struct channel_s *pchan );
void VOX_FreeWord( struct channel_s *pchan ); void VOX_FreeWord( struct channel_s *pchan );

View File

@@ -229,7 +229,7 @@ void BaseCmd_Stats_f( void )
Con_Printf( "Empty buckets: %d\n", empty ); Con_Printf( "Empty buckets: %d\n", empty );
} }
static void BaseCmd_CheckCvars( const char *key, const char *value, const void *unused, void *ptr ) static void BaseCmd_CheckCvars( const char *key, const char *value, void *buffer, void *ptr )
{ {
base_command_t *v = BaseCmd_Find( HM_CVAR, key ); base_command_t *v = BaseCmd_Find( HM_CVAR, key );
qboolean *invalid = ptr; qboolean *invalid = ptr;

View File

@@ -13,7 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
*/ */
#include "crtlib.h" #include "common.h"
static const char *date = __DATE__ ; static const char *date = __DATE__ ;
static const char *mon[12] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; static const char *mon[12] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
@@ -95,8 +95,6 @@ const char *Q_buildos( void )
osname = "DOS4GW"; osname = "DOS4GW";
#elif XASH_HAIKU #elif XASH_HAIKU
osname = "haiku"; osname = "haiku";
#elif XASH_SERENITY
osname = "serenityos";
#else #else
#error "Place your operating system name here! If this is a mistake, try to fix conditions above and report a bug" #error "Place your operating system name here! If this is a mistake, try to fix conditions above and report a bug"
#endif #endif

View File

@@ -30,15 +30,11 @@ typedef struct
} cmdbuf_t; } cmdbuf_t;
qboolean cmd_wait; qboolean cmd_wait;
cmdbuf_t cmd_text, filteredcmd_text; cmdbuf_t cmd_text;
byte cmd_text_buf[MAX_CMD_BUFFER]; byte cmd_text_buf[MAX_CMD_BUFFER];
byte filteredcmd_text_buf[MAX_CMD_BUFFER];
cmdalias_t *cmd_alias; cmdalias_t *cmd_alias;
uint cmd_condition; uint cmd_condition;
int cmd_condlevel; int cmd_condlevel;
static qboolean cmd_currentCommandIsPrivileged;
static void Cmd_ExecuteStringWithPrivilegeCheck( const char *text, qboolean isPrivileged );
/* /*
============================================================================= =============================================================================
@@ -56,10 +52,8 @@ Cbuf_Init
void Cbuf_Init( void ) void Cbuf_Init( void )
{ {
cmd_text.data = cmd_text_buf; cmd_text.data = cmd_text_buf;
filteredcmd_text.data = filteredcmd_text_buf; cmd_text.maxsize = MAX_CMD_BUFFER;
cmd_text.cursize = 0;
filteredcmd_text.maxsize = cmd_text.maxsize = MAX_CMD_BUFFER;
filteredcmd_text.cursize = cmd_text.cursize = 0;
} }
/* /*
@@ -69,9 +63,8 @@ Cbuf_Clear
*/ */
void Cbuf_Clear( void ) void Cbuf_Clear( void )
{ {
memset( cmd_text.data, 0, cmd_text.maxsize ); memset( cmd_text.data, 0, sizeof( cmd_text_buf ));
memset( filteredcmd_text.data, 0, filteredcmd_text.maxsize ); cmd_text.cursize = 0;
cmd_text.cursize = filteredcmd_text.cursize = 0;
} }
/* /*
@@ -95,19 +88,6 @@ void *Cbuf_GetSpace( cmdbuf_t *buf, int length )
return data; return data;
} }
static void Cbuf_AddTextToBuffer( cmdbuf_t *buf, const char *text )
{
int l = Q_strlen( text );
if(( buf->cursize + l ) >= buf->maxsize )
{
Con_Reportf( S_WARN "%s: overflow\n", __func__ );
return;
}
memcpy( Cbuf_GetSpace( buf, l ), text, l );
}
/* /*
============ ============
Cbuf_AddText Cbuf_AddText
@@ -117,17 +97,16 @@ Adds command text at the end of the buffer
*/ */
void Cbuf_AddText( const char *text ) void Cbuf_AddText( const char *text )
{ {
Cbuf_AddTextToBuffer( &cmd_text, text ); int l = Q_strlen( text );
}
/* if(( cmd_text.cursize + l ) >= cmd_text.maxsize )
============ {
Cbuf_AddFilteredText Con_Reportf( S_WARN "Cbuf_AddText: overflow\n" );
============ }
*/ else
void Cbuf_AddFilteredText( const char *text ) {
{ memcpy( Cbuf_GetSpace( &cmd_text, l ), text, l );
Cbuf_AddTextToBuffer( &filteredcmd_text, text ); }
} }
/* /*
@@ -138,55 +117,43 @@ Adds command text immediately after the current command
Adds a \n to the text Adds a \n to the text
============ ============
*/ */
static void Cbuf_InsertTextToBuffer( cmdbuf_t *buf, const char *text ) void Cbuf_InsertText( const char *text )
{ {
int l = Q_strlen( text ); int l = Q_strlen( text );
if(( buf->cursize + l ) >= buf->maxsize ) if(( cmd_text.cursize + l ) >= cmd_text.maxsize )
{ {
Con_Reportf( S_WARN "Cbuf_InsertText: overflow\n" ); Con_Reportf( S_WARN "Cbuf_InsertText: overflow\n" );
} }
else else
{ {
memmove( buf->data + l, buf->data, buf->cursize ); memmove( cmd_text.data + l, cmd_text.data, cmd_text.cursize );
memcpy( buf->data, text, l ); memcpy( cmd_text.data, text, l );
buf->cursize += l; cmd_text.cursize += l;
} }
} }
void Cbuf_InsertText( const char *text )
{
Cbuf_InsertTextToBuffer( &cmd_text, text );
}
/* /*
============ ============
Cbuf_Execute Cbuf_Execute
============ ============
*/ */
void Cbuf_ExecuteCommandsFromBuffer( cmdbuf_t *buf, qboolean isPrivileged, int cmdsToExecute ) void Cbuf_Execute( void )
{ {
char *text; char *text;
char line[MAX_CMD_LINE]; char line[MAX_CMD_LINE];
int i, quotes; int i, quotes;
char *comment; char *comment;
while( buf->cursize ) while( cmd_text.cursize )
{ {
// limit amount of commands that can be issued
if( cmdsToExecute >= 0 )
{
if( !cmdsToExecute-- )
break;
}
// find a \n or ; line break // find a \n or ; line break
text = (char *)buf->data; text = (char *)cmd_text.data;
quotes = false; quotes = false;
comment = NULL; comment = NULL;
for( i = 0; i < buf->cursize; i++ ) for( i = 0; i < cmd_text.cursize; i++ )
{ {
if( !comment ) if( !comment )
{ {
@@ -195,7 +162,7 @@ void Cbuf_ExecuteCommandsFromBuffer( cmdbuf_t *buf, qboolean isPrivileged, int c
if( quotes ) if( quotes )
{ {
// make sure i doesn't get > cursize which causes a negative size in memmove, which is fatal --blub // make sure i doesn't get > cursize which causes a negative size in memmove, which is fatal --blub
if( i < ( buf->cursize - 1 ) && ( text[i+0] == '\\' && (text[i+1] == '"' || text[i+1] == '\\'))) if( i < ( cmd_text.cursize - 1 ) && ( text[i+0] == '\\' && (text[i+1] == '"' || text[i+1] == '\\')))
i++; i++;
} }
else else
@@ -224,19 +191,19 @@ void Cbuf_ExecuteCommandsFromBuffer( cmdbuf_t *buf, qboolean isPrivileged, int c
// delete the text from the command buffer and move remaining commands down // delete the text from the command buffer and move remaining commands down
// this is necessary because commands (exec) can insert data at the // this is necessary because commands (exec) can insert data at the
// beginning of the text buffer // beginning of the text buffer
if( i == buf->cursize ) if( i == cmd_text.cursize )
{ {
buf->cursize = 0; cmd_text.cursize = 0;
} }
else else
{ {
i++; i++;
buf->cursize -= i; cmd_text.cursize -= i;
memmove( buf->data, text + i, buf->cursize ); memmove( cmd_text.data, text + i, cmd_text.cursize );
} }
// execute the command line // execute the command line
Cmd_ExecuteStringWithPrivilegeCheck( line, isPrivileged ); Cmd_ExecuteString( line );
if( cmd_wait ) if( cmd_wait )
{ {
@@ -248,20 +215,6 @@ void Cbuf_ExecuteCommandsFromBuffer( cmdbuf_t *buf, qboolean isPrivileged, int c
} }
} }
/*
============
Cbuf_Execute
============
*/
void Cbuf_Execute( void )
{
Cbuf_ExecuteCommandsFromBuffer( &cmd_text, true, -1 );
// a1ba: unlimited commands for filtered buffer per frame
// I don't see any sense in restricting that at this moment
// but in future we may limit this
Cbuf_ExecuteCommandsFromBuffer( &filteredcmd_text, false, -1 );
}
/* /*
=============== ===============
Cbuf_ExecStuffCmds Cbuf_ExecStuffCmds
@@ -329,11 +282,6 @@ void Cbuf_ExecStuffCmds( void )
============================================================================== ==============================================================================
*/ */
qboolean Cmd_CurrentCommandIsPrivileged( void )
{
return cmd_currentCommandIsPrivileged;
}
/* /*
=============== ===============
Cmd_StuffCmds_f Cmd_StuffCmds_f
@@ -510,8 +458,8 @@ typedef struct cmd_s
struct cmd_s *next; struct cmd_s *next;
char *name; char *name;
xcommand_t function; xcommand_t function;
int flags;
char *desc; char *desc;
int flags;
} cmd_t; } cmd_t;
static int cmd_argc; static int cmd_argc;
@@ -647,7 +595,7 @@ void Cmd_TokenizeString( const char *text )
if( cmd_argc == 1 ) if( cmd_argc == 1 )
cmd_args = text; cmd_args = text;
text = COM_ParseFileSafe( (char*)text, cmd_token, sizeof( cmd_token ), PFILE_IGNOREBRACKET, NULL, NULL ); text = _COM_ParseFileSafe( (char*)text, cmd_token, sizeof( cmd_token ), PFILE_IGNOREBRACKET, NULL );
if( !text ) return; if( !text ) return;
@@ -671,21 +619,21 @@ static int Cmd_AddCommandEx( const char *funcname, const char *cmd_name, xcomman
if( !COM_CheckString( cmd_name )) if( !COM_CheckString( cmd_name ))
{ {
Con_Reportf( S_ERROR "%s: NULL name\n", funcname ); Con_Reportf( S_ERROR "Cmd_AddCommand: NULL name\n" );
return 0; return 0;
} }
// fail if the command is a variable name // fail if the command is a variable name
if( Cvar_FindVar( cmd_name )) if( Cvar_FindVar( cmd_name ))
{ {
Con_DPrintf( S_ERROR "%s: %s already defined as a var\n", funcname, cmd_name ); Con_DPrintf( S_ERROR "Cmd_AddServerCommand: %s already defined as a var\n", cmd_name );
return 0; return 0;
} }
// fail if the command already exists // fail if the command already exists
if( Cmd_Exists( cmd_name )) if( Cmd_Exists( cmd_name ))
{ {
Con_DPrintf( S_ERROR "%s: %s already defined\n", funcname, cmd_name ); Con_DPrintf( S_ERROR "Cmd_AddServerCommand: %s already defined\n", cmd_name );
return 0; return 0;
} }
@@ -728,7 +676,7 @@ Cmd_AddRestrictedCommand
*/ */
void Cmd_AddRestrictedCommand( 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 )
{ {
Cmd_AddCommandEx( __FUNCTION__, cmd_name, function, cmd_desc, CMD_PRIVILEGED ); Cmd_AddCommandEx( __FUNCTION__, cmd_name, function, cmd_desc, CMD_LOCALONLY );
} }
/* /*
@@ -748,15 +696,7 @@ Cmd_AddClientCommand
*/ */
int GAME_EXPORT Cmd_AddClientCommand( const char *cmd_name, xcommand_t function ) int GAME_EXPORT Cmd_AddClientCommand( const char *cmd_name, xcommand_t function )
{ {
int flags = CMD_CLIENTDLL; return Cmd_AddCommandEx( __FUNCTION__, cmd_name, function, "client command", CMD_CLIENTDLL );
// a1ba: try to mitigate outdated client.dll vulnerabilities
if( !Q_stricmp( cmd_name, "motd_write" ))
{
flags |= CMD_PRIVILEGED;
}
return Cmd_AddCommandEx( __FUNCTION__, cmd_name, function, "client command", flags );
} }
/* /*
@@ -936,35 +876,6 @@ void Cmd_Else_f( void )
cmd_condition ^= BIT( cmd_condlevel ); cmd_condition ^= BIT( cmd_condlevel );
} }
static qboolean Cmd_ShouldAllowCommand( cmd_t *cmd, qboolean isPrivileged )
{
const char *prefixes[] = { "cl_", "gl_", "r_", "m_", "hud_" };
int i;
// always allow local commands
if( isPrivileged )
return true;
// never allow local only commands from remote
if( FBitSet( cmd->flags, CMD_PRIVILEGED ))
return false;
// allow engine commands if user don't mind
if( cl_filterstuffcmd.value <= 0.0f )
return true;
if( FBitSet( cmd->flags, CMD_FILTERABLE ))
return false;
for( i = 0; i < ARRAYSIZE( prefixes ); i++ )
{
if( !Q_strnicmp( cmd->name, prefixes[i], Q_strlen( prefixes[i] )))
return false;
}
return true;
}
/* /*
============ ============
Cmd_ExecuteString Cmd_ExecuteString
@@ -972,7 +883,7 @@ Cmd_ExecuteString
A complete command line has been parsed, so try to execute it A complete command line has been parsed, so try to execute it
============ ============
*/ */
static void Cmd_ExecuteStringWithPrivilegeCheck( const char *text, qboolean isPrivileged ) void Cmd_ExecuteString( const char *text )
{ {
cmd_t *cmd = NULL; cmd_t *cmd = NULL;
cmdalias_t *a = NULL; cmdalias_t *a = NULL;
@@ -984,7 +895,7 @@ static void Cmd_ExecuteStringWithPrivilegeCheck( const char *text, qboolean isPr
cmd_condlevel = 0; cmd_condlevel = 0;
// cvar value substitution // cvar value substitution
if( CVAR_TO_BOOL( cmd_scripting )) if( cmd_scripting && cmd_scripting->value )
{ {
while( *text ) while( *text )
{ {
@@ -1041,59 +952,47 @@ static void Cmd_ExecuteStringWithPrivilegeCheck( const char *text, qboolean isPr
if( !host.apply_game_config ) if( !host.apply_game_config )
{ {
// check aliases // check aliases
if( !a ) // if not found in basecmd if( a ) // already found in basecmd
{ {
for( a = cmd_alias; a; a = a->next ) Cbuf_InsertText( a->value );
{ return;
if( !Q_stricmp( cmd_argv[0], a->name ))
break;
}
} }
if( a ) for( a = cmd_alias; a; a = a->next )
{ {
Cbuf_InsertTextToBuffer( if( !Q_stricmp( cmd_argv[0], a->name ))
isPrivileged ? &cmd_text : &filteredcmd_text, {
a->value ); Cbuf_InsertText( a->value );
return; return;
}
} }
} }
// special mode for restore game.dll archived cvars // special mode for restore game.dll archived cvars
if( !host.apply_game_config || !Q_strcmp( cmd_argv[0], "exec" )) if( !host.apply_game_config || !Q_strcmp( cmd_argv[0], "exec" ))
{ {
if( !cmd || !cmd->function ) // if not found in basecmd // check functions
if( cmd && cmd->function ) // already found in basecmd
{ {
for( cmd = cmd_functions; cmd; cmd = cmd->next ) cmd->function();
{ return;
if( !Q_stricmp( cmd_argv[0], cmd->name ) && cmd->function )
break;
}
} }
// check functions for( cmd = cmd_functions; cmd; cmd = cmd->next )
if( cmd && cmd->function )
{ {
if( Cmd_ShouldAllowCommand( cmd, isPrivileged )) if( !Q_stricmp( cmd_argv[0], cmd->name ) && cmd->function )
{ {
cmd_currentCommandIsPrivileged = isPrivileged;
cmd->function(); cmd->function();
cmd_currentCommandIsPrivileged = true; return;
} }
else
{
Con_Printf( S_WARN "Could not execute privileged command %s\n", cmd->name );
}
return;
} }
} }
// check cvars // check cvars
if( Cvar_CommandWithPrivilegeCheck( cvar, isPrivileged )) return; if( Cvar_Command( cvar )) return;
if( host.apply_game_config ) if( host.apply_game_config )
return; // don't send nothing to server: we are a server! return; // don't send nothing to server: we is a server!
// forward the command line to the server, so the entity DLL can parse it // forward the command line to the server, so the entity DLL can parse it
if( host.type == HOST_NORMAL ) if( host.type == HOST_NORMAL )
@@ -1107,16 +1006,11 @@ static void Cmd_ExecuteStringWithPrivilegeCheck( const char *text, qboolean isPr
#endif // XASH_DEDICATED #endif // XASH_DEDICATED
if( Cvar_VariableInteger( "host_gameloaded" )) if( Cvar_VariableInteger( "host_gameloaded" ))
{ {
Con_Printf( S_WARN "Unknown command \"%s\"\n", Cmd_Argv( 0 ) ); Con_Printf( S_WARN "Unknown command \"%s\"\n", text );
} }
} }
} }
void Cmd_ExecuteString( const char *text )
{
Cmd_ExecuteStringWithPrivilegeCheck( text, true );
}
/* /*
=================== ===================
Cmd_ForwardToServer Cmd_ForwardToServer
@@ -1171,21 +1065,17 @@ void Cmd_List_f( void )
{ {
cmd_t *cmd; cmd_t *cmd;
int i = 0; int i = 0;
size_t matchlen = 0; const char *match;
const char *match = NULL;
if( Cmd_Argc() > 1 ) if( Cmd_Argc() > 1 ) match = Cmd_Argv( 1 );
{ else match = NULL;
match = Cmd_Argv( 1 );
matchlen = Q_strlen( match );
}
for( cmd = cmd_functions; cmd; cmd = cmd->next ) for( cmd = cmd_functions; cmd; cmd = cmd->next )
{ {
if( cmd->name[0] == '@' ) if( cmd->name[0] == '@' )
continue; // never show system cmds continue; // never show system cmds
if( match && !Q_strnicmpext( match, cmd->name, matchlen )) if( match && !Q_stricmpext( match, cmd->name ))
continue; continue;
Con_Printf( " %-*s ^3%s^7\n", 32, cmd->name, cmd->desc ); Con_Printf( " %-*s ^3%s^7\n", 32, cmd->name, cmd->desc );
@@ -1335,43 +1225,9 @@ void Cmd_Null_f( void )
{ {
} }
/*
==========
Cmd_Escape
inserts escape sequences
==========
*/
void Cmd_Escape( char *newCommand, const char *oldCommand, int len )
{
int c;
int scripting = CVAR_TO_BOOL( cmd_scripting );
while( (c = *oldCommand++) && len > 1 )
{
if( c == '"' )
{
*newCommand++ = '\\';
len--;
}
if( scripting && c == '$')
{
*newCommand++ = '$';
len--;
}
*newCommand++ = c; len--;
}
*newCommand++ = 0;
}
/* /*
============ ============
Cmd_Init Cmd_Init
============ ============
*/ */
void Cmd_Init( void ) void Cmd_Init( void )
@@ -1388,13 +1244,13 @@ void Cmd_Init( void )
Cmd_AddCommand( "echo", Cmd_Echo_f, "print a message to the console (useful in scripts)" ); Cmd_AddCommand( "echo", Cmd_Echo_f, "print a message to the console (useful in scripts)" );
Cmd_AddCommand( "wait", Cmd_Wait_f, "make script execution wait for some rendered frames" ); Cmd_AddCommand( "wait", Cmd_Wait_f, "make script execution wait for some rendered frames" );
Cmd_AddCommand( "cmdlist", Cmd_List_f, "display all console commands beginning with the specified prefix" ); Cmd_AddCommand( "cmdlist", Cmd_List_f, "display all console commands beginning with the specified prefix" );
Cmd_AddRestrictedCommand( "stuffcmds", Cmd_StuffCmds_f, "execute commandline parameters (must be present in .rc script)" ); Cmd_AddCommand( "stuffcmds", Cmd_StuffCmds_f, "execute commandline parameters (must be present in .rc script)" );
Cmd_AddCommand( "apropos", Cmd_Apropos_f, "lists all console variables/commands/aliases containing the specified string in the name or description" ); Cmd_AddCommand( "apropos", Cmd_Apropos_f, "lists all console variables/commands/aliases containing the specified string in the name or description" );
#if !XASH_DEDICATED #if !XASH_DEDICATED
Cmd_AddCommand( "cmd", Cmd_ForwardToServer, "send a console commandline to the server" ); Cmd_AddCommand( "cmd", Cmd_ForwardToServer, "send a console commandline to the server" );
#endif // XASH_DEDICATED #endif // XASH_DEDICATED
Cmd_AddRestrictedCommand( "alias", Cmd_Alias_f, "create a script function. Without arguments show the list of all alias" ); Cmd_AddCommand( "alias", Cmd_Alias_f, "create a script function. Without arguments show the list of all alias" );
Cmd_AddRestrictedCommand( "unalias", Cmd_UnAlias_f, "remove a script function" ); Cmd_AddCommand( "unalias", Cmd_UnAlias_f, "remove a script function" );
Cmd_AddCommand( "if", Cmd_If_f, "compare and set condition bits" ); Cmd_AddCommand( "if", Cmd_If_f, "compare and set condition bits" );
Cmd_AddCommand( "else", Cmd_Else_f, "invert condition bit" ); Cmd_AddCommand( "else", Cmd_Else_f, "invert condition bit" );
@@ -1403,64 +1259,3 @@ void Cmd_Init( void )
Cmd_AddCommand( "basecmd_test", BaseCmd_Test_f, "test basecmd" ); Cmd_AddCommand( "basecmd_test", BaseCmd_Test_f, "test basecmd" );
#endif #endif
} }
#if XASH_ENGINE_TESTS
#include "tests.h"
enum
{
NO_CALL = 0,
PRIV = 1,
UNPRIV = 2
};
static int test_flags[3] = { NO_CALL, NO_CALL, NO_CALL };
static void Test_PrivilegedCommand_f( void )
{
test_flags[0] = Cmd_CurrentCommandIsPrivileged() ? PRIV : UNPRIV;
}
static void Test_UnprivilegedCommand_f( void )
{
test_flags[1] = Cmd_CurrentCommandIsPrivileged() ? PRIV : UNPRIV;
}
static void Test_FilteredCommand_f( void )
{
test_flags[2] = Cmd_CurrentCommandIsPrivileged() ? PRIV : UNPRIV;
}
void Test_RunCmd( void )
{
Cmd_AddCommand( "test_privileged", Test_PrivilegedCommand_f, "bark bark" );
Cmd_AddRestrictedCommand( "test_unprivileged", Test_UnprivilegedCommand_f, "meow meow" );
Cmd_AddCommand( "hud_filtered", Test_FilteredCommand_f, "dummy description" );
Cbuf_AddText( "test_privileged; test_unprivileged; hud_filtered\n" );
Cbuf_Execute();
TASSERT( test_flags[0] == PRIV );
TASSERT( test_flags[1] == PRIV );
TASSERT( test_flags[2] == PRIV );
VectorSet( test_flags, NO_CALL, NO_CALL, NO_CALL );
Cvar_DirectSet( &cl_filterstuffcmd, "0" );
Cbuf_AddFilteredText( "test_privileged; test_unprivileged; hud_filtered\n" );
Cbuf_Execute();
TASSERT( test_flags[0] == UNPRIV );
TASSERT( test_flags[1] == NO_CALL );
TASSERT( test_flags[2] == UNPRIV );
VectorSet( test_flags, NO_CALL, NO_CALL, NO_CALL );
Cvar_DirectSet( &cl_filterstuffcmd, "1" );
Cbuf_AddFilteredText( "test_privileged; test_unprivileged; hud_filtered\n" );
Cbuf_Execute();
TASSERT( test_flags[0] == UNPRIV );
TASSERT( test_flags[1] == NO_CALL );
TASSERT( test_flags[2] == NO_CALL );
Cmd_RemoveCommand( "hud_filtered" );
Cmd_RemoveCommand( "test_unprivileged" );
Cmd_RemoveCommand( "test_privileged" );
}
#endif

View File

@@ -64,8 +64,6 @@ GNU General Public License for more details.
#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"
#define XASH_VERSION "0.20" // engine current version
#define XASH_COMPAT_VERSION "0.99" // version we are based on
// renderers order is important, software is always a last chance fallback // renderers order is important, software is always a last chance fallback
#define DEFAULT_RENDERERS { "gl", "gles1", "gles2", "gl4es", "soft" } #define DEFAULT_RENDERERS { "gl", "gles1", "gles2", "gl4es", "soft" }

View File

@@ -13,9 +13,6 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
*/ */
#if defined( ALLOCA_H )
#include ALLOCA_H
#endif
#include "common.h" #include "common.h"
#include "studio.h" #include "studio.h"
#include "xash3d_mathlib.h" #include "xash3d_mathlib.h"
@@ -585,6 +582,23 @@ void COM_TrimSpace( const char *source, char *dest )
dest[length] = 0; dest[length] = 0;
} }
/*
============
COM_FixSlashes
Changes all '/' characters into '\' characters, in place.
============
*/
void COM_FixSlashes( char *pname )
{
while( *pname )
{
if( *pname == '\\' )
*pname = '/';
pname++;
}
}
/* /*
================== ==================
COM_Nibble COM_Nibble
@@ -872,10 +886,6 @@ pfnCvar_RegisterVariable
*/ */
cvar_t *pfnCvar_RegisterClientVariable( const char *szName, const char *szValue, int flags ) cvar_t *pfnCvar_RegisterClientVariable( const char *szName, const char *szValue, int flags )
{ {
// a1ba: try to mitigate outdated client.dll vulnerabilities
if( !Q_stricmp( szName, "motdfile" ))
flags |= FCVAR_PRIVILEGED;
if( FBitSet( flags, FCVAR_GLCONFIG )) if( FBitSet( flags, FCVAR_GLCONFIG ))
return (cvar_t *)Cvar_Get( szName, szValue, flags, va( CVAR_GLCONFIG_DESCRIPTION, szName )); return (cvar_t *)Cvar_Get( szName, szValue, flags, va( CVAR_GLCONFIG_DESCRIPTION, szName ));
return (cvar_t *)Cvar_Get( szName, szValue, flags|FCVAR_CLIENTDLL, Cvar_BuildAutoDescription( flags|FCVAR_CLIENTDLL )); return (cvar_t *)Cvar_Get( szName, szValue, flags|FCVAR_CLIENTDLL, Cvar_BuildAutoDescription( flags|FCVAR_CLIENTDLL ));
@@ -1165,22 +1175,22 @@ void Test_RunCommon( void )
Msg( "Checking COM_ParseFile...\n" ); Msg( "Checking COM_ParseFile...\n" );
file = COM_ParseFileSafe( file, buf, sizeof( buf ), 0, &len, NULL ); file = _COM_ParseFileSafe( file, buf, sizeof( buf ), 0, &len );
TASSERT( !Q_strcmp( buf, "q" ) && len == 1); TASSERT( !Q_strcmp( buf, "q" ) && len == 1);
file = COM_ParseFileSafe( file, buf, sizeof( buf ), 0, &len, NULL ); file = _COM_ParseFileSafe( file, buf, sizeof( buf ), 0, &len );
TASSERT( !Q_strcmp( buf, "asdf" ) && len == 4); TASSERT( !Q_strcmp( buf, "asdf" ) && len == 4);
file = COM_ParseFileSafe( file, buf, sizeof( buf ), 0, &len, NULL ); file = _COM_ParseFileSafe( file, buf, sizeof( buf ), 0, &len );
TASSERT( !Q_strcmp( buf, "qwer" ) && len == -1); TASSERT( !Q_strcmp( buf, "qwer" ) && len == -1);
file = COM_ParseFileSafe( file, buf, sizeof( buf ), 0, &len, NULL ); file = _COM_ParseFileSafe( file, buf, sizeof( buf ), 0, &len );
TASSERT( !Q_strcmp( buf, "f \"f" ) && len == 4); TASSERT( !Q_strcmp( buf, "f \"f" ) && len == 4);
file = COM_ParseFileSafe( file, buf, sizeof( buf ), 0, &len, NULL ); file = _COM_ParseFileSafe( file, buf, sizeof( buf ), 0, &len );
TASSERT( !Q_strcmp( buf, "meow" ) && len == -1); TASSERT( !Q_strcmp( buf, "meow" ) && len == -1);
file = COM_ParseFileSafe( file, buf, sizeof( buf ), 0, &len, NULL ); file = _COM_ParseFileSafe( file, buf, sizeof( buf ), 0, &len );
TASSERT( !Q_strcmp( buf, "bark" ) && len == 4); TASSERT( !Q_strcmp( buf, "bark" ) && len == 4);
} }
#endif #endif

View File

@@ -76,6 +76,13 @@ 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
typedef struct
{
int numfilenames;
char **filenames;
char *filenamesbuffer;
} search_t;
enum enum
{ {
DEV_NONE = 0, DEV_NONE = 0,
@@ -111,8 +118,9 @@ typedef enum
#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 "fscallback.h" #define XASH_VERSION "0.20" // engine current version
#define XASH_COMPAT_VERSION "0.99" // version we are based on
// 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.
@@ -142,6 +150,18 @@ typedef enum
#define MAX_STATIC_ENTITIES 32 // static entities that moved on the client when level is spawn #define MAX_STATIC_ENTITIES 32 // static entities that moved on the client when level is spawn
#endif #endif
// filesystem flags
#define FS_STATIC_PATH ( 1U << 0 ) // FS_ClearSearchPath will be ignore this path
#define FS_NOWRITE_PATH ( 1U << 1 ) // default behavior - last added gamedir set as writedir. This flag disables it
#define FS_GAMEDIR_PATH ( 1U << 2 ) // just a marker for gamedir path
#define FS_CUSTOM_PATH ( 1U << 3 ) // custom directory
#define FS_GAMERODIR_PATH ( 1U << 4 ) // caseinsensitive
#define FS_GAMEDIRONLY_SEARCH_FLAGS ( FS_GAMEDIR_PATH | FS_CUSTOM_PATH | FS_GAMERODIR_PATH )
#define GI SI.GameInfo
#define FS_Gamedir() SI.GameInfo->gamefolder
#define FS_Title() SI.GameInfo->title
#define GameState (&host.game) #define GameState (&host.game)
#define FORCE_DRAW_VERSION_TIME 5.0f // draw version for 5 seconds #define FORCE_DRAW_VERSION_TIME 5.0f // draw version for 5 seconds
@@ -164,8 +184,6 @@ extern convar_t host_developer;
extern convar_t *host_limitlocal; extern convar_t *host_limitlocal;
extern convar_t *host_framerate; extern convar_t *host_framerate;
extern convar_t *host_maxfps; extern convar_t *host_maxfps;
extern convar_t sys_timescale;
extern convar_t cl_filterstuffcmd;
/* /*
============================================================== ==============================================================
@@ -182,6 +200,60 @@ GAMEINFO stuff
internal shared gameinfo structure (readonly for engine parts) internal shared gameinfo structure (readonly for engine parts)
======================================================================== ========================================================================
*/ */
typedef struct gameinfo_s
{
// filesystem info
char gamefolder[MAX_QPATH]; // used for change game '-game x'
char basedir[MAX_QPATH]; // base game directory (like 'id1' for Quake or 'valve' for Half-Life)
char falldir[MAX_QPATH]; // used as second basedir
char startmap[MAX_QPATH];// map to start singleplayer game
char trainmap[MAX_QPATH];// map to start hazard course (if specified)
char title[64]; // Game Main Title
float version; // game version (optional)
// .dll pathes
char dll_path[MAX_QPATH]; // e.g. "bin" or "cl_dlls"
char game_dll[MAX_QPATH]; // custom path for game.dll
// .ico path
char iconpath[MAX_QPATH]; // "game.ico" by default
// about mod info
string game_url; // link to a developer's site
string update_url; // link to updates page
char type[MAX_QPATH]; // single, toolkit, multiplayer etc
char date[MAX_QPATH];
size_t size;
int gamemode;
qboolean secure; // prevent to console acess
qboolean nomodels; // don't let player to choose model (use player.mdl always)
qboolean noskills; // disable skill menu selection
char sp_entity[32]; // e.g. info_player_start
char mp_entity[32]; // e.g. info_player_deathmatch
char mp_filter[32]; // filtering multiplayer-maps
char ambientsound[NUM_AMBIENTS][MAX_QPATH]; // quake ambient sounds
int max_edicts; // min edicts is 600, max edicts is 8196
int max_tents; // min temp ents is 300, max is 2048
int max_beams; // min beams is 64, max beams is 512
int max_particles; // min particles is 4096, max particles is 32768
char game_dll_linux[64]; // custom path for game.dll
char game_dll_osx[64]; // custom path for game.dll
qboolean added;
} gameinfo_t;
typedef enum
{
GAME_NORMAL,
GAME_SINGLEPLAYER_ONLY,
GAME_MULTIPLAYER_ONLY
} gametype_t;
typedef struct sysinfo_s typedef struct sysinfo_s
{ {
string exeName; // exe.filename string exeName; // exe.filename
@@ -189,6 +261,9 @@ typedef struct sysinfo_s
string basedirName; // name of base directory string basedirName; // name of base directory
string gamedll; string gamedll;
string clientlib; string clientlib;
gameinfo_t *GameInfo; // current GameInfo
gameinfo_t *games[MAX_MODS]; // environment games (founded at each engine start)
int numgames;
} sysinfo_t; } sysinfo_t;
typedef enum typedef enum
@@ -307,16 +382,6 @@ typedef struct
float scale; // curstate.scale float scale; // curstate.scale
} tentlist_t; } tentlist_t;
typedef enum bugcomp_e
{
// default mode, we assume that user dlls are not relying on engine bugs
BUGCOMP_OFF,
// GoldSrc mode, user dlls are relying on GoldSrc specific bugs
// but fixing them may break regular Xash games
BUGCOMP_GOLDSRC,
} bugcomp_t;
typedef struct host_parm_s typedef struct host_parm_s
{ {
HINSTANCE hInst; HINSTANCE hInst;
@@ -391,9 +456,6 @@ typedef struct host_parm_s
struct decallist_s *decalList; // used for keep decals, when renderer is restarted or changed struct decallist_s *decalList; // used for keep decals, when renderer is restarted or changed
int numdecals; int numdecals;
// bug compatibility level, for very "special" games
bugcomp_t bugcomp;
} host_parm_t; } host_parm_t;
extern host_parm_t host; extern host_parm_t host;
@@ -402,30 +464,20 @@ extern sysinfo_t SI;
#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_LOCALONLY BIT( 3 ) // restricted from server commands
#define CMD_FILTERABLE BIT( 4 ) // filtered in unprivileged mode if cl_filterstuffcmd is 1 #define CMD_REFDLL BIT( 4 ) // added by ref.dll
#define CMD_REFDLL BIT( 5 ) // added by ref.dll
typedef void (*xcommand_t)( void ); typedef void (*xcommand_t)( void );
//
// filesystem_engine.c
//
qboolean FS_LoadProgs( void );
void FS_Init( void );
void FS_Shutdown( void );
// //
// cmd.c // cmd.c
// //
void Cbuf_Init( void ); void Cbuf_Init( void );
void Cbuf_Clear( void ); void Cbuf_Clear( void );
void Cbuf_AddText( const char *text ); void Cbuf_AddText( const char *text );
void Cbuf_AddFilteredText( const char *text );
void Cbuf_InsertText( const char *text ); void Cbuf_InsertText( const char *text );
void Cbuf_ExecStuffCmds( void ); void Cbuf_ExecStuffCmds( void );
void Cbuf_Execute (void); void Cbuf_Execute (void);
qboolean Cmd_CurrentCommandIsPrivileged( void );
int Cmd_Argc( void ); int Cmd_Argc( void );
const char *Cmd_Args( void ); const char *Cmd_Args( void );
const char *Cmd_Argv( int arg ); const char *Cmd_Argv( int arg );
@@ -447,7 +499,6 @@ qboolean Cmd_GetMovieList( const char *s, char *completedname, int length );
void Cmd_TokenizeString( const char *text ); void Cmd_TokenizeString( const char *text );
void Cmd_ExecuteString( const char *text ); void Cmd_ExecuteString( const char *text );
void Cmd_ForwardToServer( void ); void Cmd_ForwardToServer( void );
void Cmd_Escape( char *newCommand, const char *oldCommand, int len );
// //
// zone.c // zone.c
@@ -474,6 +525,56 @@ void Mem_PrintStats( void );
#define Mem_IsAllocated( mem ) Mem_IsAllocatedExt( NULL, mem ) #define Mem_IsAllocated( mem ) Mem_IsAllocatedExt( NULL, mem )
#define Mem_Check() _Mem_Check( __FILE__, __LINE__ ) #define Mem_Check() _Mem_Check( __FILE__, __LINE__ )
//
// filesystem.c
//
void FS_Init( void );
void FS_Path( void );
void FS_Rescan( void );
void FS_Shutdown( void );
void FS_ClearSearchPath( void );
void FS_AllowDirectPaths( qboolean enable );
void FS_AddGameDirectory( const char *dir, uint flags );
void FS_AddGameHierarchy( const char *dir, uint flags );
void FS_LoadGameInfo( const char *rootfolder );
const char *FS_GetDiskPath( const char *name, qboolean gamedironly );
byte *W_LoadLump( wfile_t *wad, const char *lumpname, size_t *lumpsizeptr, const char type );
void W_Close( wfile_t *wad );
byte *FS_LoadFile( const char *path, fs_offset_t *filesizeptr, qboolean gamedironly );
qboolean CRC32_File( dword *crcvalue, const char *filename );
qboolean MD5_HashFile( byte digest[16], const char *pszFileName, uint seed[4] );
byte *FS_LoadDirectFile( const char *path, fs_offset_t *filesizeptr );
qboolean FS_WriteFile( const char *filename, const void *data, fs_offset_t len );
qboolean COM_ParseVector( char **pfile, float *v, size_t size );
void COM_NormalizeAngles( vec3_t angles );
int COM_FileSize( const char *filename );
void COM_FixSlashes( char *pname );
void COM_FreeFile( void *buffer );
int COM_CompareFileTime( const char *filename1, const char *filename2, int *iCompare );
search_t *FS_Search( const char *pattern, int caseinsensitive, int gamedironly );
file_t *FS_Open( const char *filepath, const char *mode, qboolean gamedironly );
fs_offset_t FS_Write( file_t *file, const void *data, size_t datasize );
fs_offset_t FS_Read( file_t *file, void *buffer, size_t buffersize );
int FS_VPrintf( file_t *file, const char *format, va_list ap );
int FS_Seek( file_t *file, fs_offset_t offset, int whence );
int FS_Gets( file_t *file, byte *string, size_t bufsize );
int FS_Printf( file_t *file, const char *format, ... ) _format( 2 );
fs_offset_t FS_FileSize( const char *filename, qboolean gamedironly );
int FS_FileTime( const char *filename, qboolean gamedironly );
int FS_Print( file_t *file, const char *msg );
qboolean FS_Rename( const char *oldname, const char *newname );
int FS_FileExists( const char *filename, int gamedironly );
int FS_SetCurrentDirectory( const char *path );
qboolean FS_SysFileExists( const char *path, qboolean casesensitive );
qboolean FS_FileCopy( file_t *pOutput, file_t *pInput, int fileSize );
qboolean FS_Delete( const char *path );
int FS_UnGetc( file_t *file, byte c );
fs_offset_t FS_Tell( file_t *file );
qboolean FS_Eof( file_t *file );
int FS_Close( file_t *file );
int FS_Getc( file_t *file );
fs_offset_t FS_FileLength( file_t *f );
// //
// imagelib // imagelib
// //
@@ -488,7 +589,7 @@ qboolean FS_SaveImage( const char *filename, rgbdata_t *pix );
rgbdata_t *FS_CopyImage( rgbdata_t *in ); rgbdata_t *FS_CopyImage( rgbdata_t *in );
void FS_FreeImage( rgbdata_t *pack ); void FS_FreeImage( rgbdata_t *pack );
extern const bpc_desc_t PFDesc[]; // image get pixelformat extern const bpc_desc_t PFDesc[]; // image get pixelformat
qboolean Image_Process( rgbdata_t **pix, int width, int height, uint flags, float reserved ); qboolean Image_Process( rgbdata_t **pix, int width, int height, uint flags, float bumpscale );
void Image_PaletteHueReplace( byte *palSrc, int newHue, int start, int end, int pal_size ); void Image_PaletteHueReplace( byte *palSrc, int newHue, int start, int end, int pal_size );
void Image_PaletteTranslate( byte *palSrc, int top, int bottom, int pal_size ); void Image_PaletteTranslate( byte *palSrc, int top, int bottom, int pal_size );
void Image_SetForceFlags( uint flags ); // set image force flags on loading void Image_SetForceFlags( uint flags ); // set image force flags on loading
@@ -562,6 +663,16 @@ void FS_FreeStream( stream_t *stream );
qboolean Sound_Process( wavdata_t **wav, int rate, int width, uint flags ); qboolean Sound_Process( wavdata_t **wav, int rate, int width, uint flags );
uint Sound_GetApproxWavePlayLen( const char *filepath ); uint Sound_GetApproxWavePlayLen( const char *filepath );
//
// build.c
//
int Q_buildnum( void );
int Q_buildnum_compat( void );
const char *Q_buildos( void );
const char *Q_buildarch( void );
const char *Q_buildcommit( void );
// //
// host.c // host.c
// //
@@ -573,7 +684,7 @@ int EXPORT Host_Main( int argc, char **argv, const char *progname, int bChangeGa
int Host_CompareFileTime( int ft1, int ft2 ); int Host_CompareFileTime( int ft1, int ft2 );
void Host_NewInstance( const char *name, const char *finalmsg ); void Host_NewInstance( const char *name, const char *finalmsg );
void Host_EndGame( qboolean abort, const char *message, ... ) _format( 2 ); void Host_EndGame( qboolean abort, const char *message, ... ) _format( 2 );
void Host_AbortCurrentFrame( void ) NORETURN; void Host_AbortCurrentFrame( void );
void Host_WriteServerConfig( const char *name ); void Host_WriteServerConfig( const char *name );
void Host_WriteOpenGLConfig( void ); void Host_WriteOpenGLConfig( void );
void Host_WriteVideoConfig( void ); void Host_WriteVideoConfig( void );
@@ -638,6 +749,7 @@ void pfnDrawSetTextColor( float r, float g, float b );
void pfnDrawConsoleStringLen( const char *pText, int *length, int *height ); void pfnDrawConsoleStringLen( const char *pText, int *length, int *height );
void *Cache_Check( poolhandle_t mempool, struct cache_user_s *c ); void *Cache_Check( poolhandle_t mempool, struct cache_user_s *c );
void COM_TrimSpace( const char *source, char *dest ); void COM_TrimSpace( const char *source, char *dest );
edict_t* pfnPEntityOfEntIndex( int iEntIndex );
void pfnGetModelBounds( model_t *mod, float *mins, float *maxs ); void pfnGetModelBounds( model_t *mod, float *mins, float *maxs );
void pfnCVarDirectSet( cvar_t *var, const char *szValue ); void pfnCVarDirectSet( cvar_t *var, const char *szValue );
int COM_CheckParm( char *parm, char **ppnext ); int COM_CheckParm( char *parm, char **ppnext );
@@ -761,6 +873,7 @@ void R_ClearAllDecals( void );
void CL_ClearStaticEntities( void ); void CL_ClearStaticEntities( void );
qboolean S_StreamGetCurrentState( char *currentTrack, char *loopTrack, int *position ); qboolean S_StreamGetCurrentState( char *currentTrack, char *loopTrack, int *position );
struct cl_entity_s *CL_GetEntityByIndex( int index ); struct cl_entity_s *CL_GetEntityByIndex( int index );
struct player_info_s *CL_GetPlayerInfo( int playerIndex );
void CL_ServerCommand( qboolean reliable, const char *fmt, ... ) _format( 2 ); void CL_ServerCommand( qboolean reliable, const char *fmt, ... ) _format( 2 );
void CL_HudMessage( const char *pMessage ); void CL_HudMessage( const char *pMessage );
const char *CL_MsgInfo( int cmd ); const char *CL_MsgInfo( int cmd );
@@ -836,11 +949,6 @@ void UI_SetActiveMenu( qboolean fActive );
void UI_ShowConnectionWarning( void ); void UI_ShowConnectionWarning( void );
void Cmd_Null_f( void ); void Cmd_Null_f( void );
void Rcon_Print( const char *pMsg ); void Rcon_Print( const char *pMsg );
qboolean COM_ParseVector( char **pfile, float *v, size_t size );
void COM_NormalizeAngles( vec3_t angles );
int COM_FileSize( const char *filename );
void COM_FreeFile( void *buffer );
int COM_CompareFileTime( const char *filename1, const char *filename2, int *iCompare );
// soundlib shared exports // soundlib shared exports
qboolean S_Init( void ); qboolean S_Init( void );
@@ -868,7 +976,6 @@ void GAME_EXPORT ID_SetCustomClientID( const char *id );
void NET_InitMasters( void ); void NET_InitMasters( void );
void NET_SaveMasters( void ); void NET_SaveMasters( void );
qboolean NET_SendToMasters( netsrc_t sock, size_t len, const void *data ); qboolean NET_SendToMasters( netsrc_t sock, size_t len, const void *data );
qboolean NET_IsMasterAdr( netadr_t adr );
#ifdef REF_DLL #ifdef REF_DLL
#error "common.h in ref_dll" #error "common.h in ref_dll"

View File

@@ -761,10 +761,10 @@ qboolean Cmd_GetGamesList( const char *s, char *completedname, int length )
// compare gamelist with current keyword // compare gamelist with current keyword
len = Q_strlen( s ); len = Q_strlen( s );
for( i = 0, numgamedirs = 0; i < FI->numgames; i++ ) for( i = 0, numgamedirs = 0; i < SI.numgames; i++ )
{ {
if(( *s == '*' ) || !Q_strnicmp( FI->games[i]->gamefolder, s, len)) if(( *s == '*' ) || !Q_strnicmp( SI.games[i]->gamefolder, s, len))
Q_strcpy( gamedirs[numgamedirs++], FI->games[i]->gamefolder ); Q_strcpy( gamedirs[numgamedirs++], SI.games[i]->gamefolder );
} }
if( !numgamedirs ) return false; if( !numgamedirs ) return false;
@@ -1216,7 +1216,7 @@ void Con_CompleteCommand( field_t *field )
if( con.matchCount == 1 ) if( con.matchCount == 1 )
{ {
Q_strncpy( con.completionField->buffer, con.cmds[0], sizeof( con.completionField->buffer )); Q_sprintf( con.completionField->buffer, "\\%s", con.cmds[0] );
if( Cmd_Argc() == 1 ) Q_strncat( con.completionField->buffer, " ", sizeof( con.completionField->buffer ) ); if( Cmd_Argc() == 1 ) Q_strncat( con.completionField->buffer, " ", sizeof( con.completionField->buffer ) );
else Con_ConcatRemaining( temp.buffer, con.completionString ); else Con_ConcatRemaining( temp.buffer, con.completionString );
con.completionField->cursor = Q_strlen( con.completionField->buffer ); con.completionField->cursor = Q_strlen( con.completionField->buffer );
@@ -1244,7 +1244,7 @@ void Con_CompleteCommand( field_t *field )
con.shortestMatch[len] = 0; con.shortestMatch[len] = 0;
// multiple matches, complete to shortest // multiple matches, complete to shortest
Q_strncpy( con.completionField->buffer, con.shortestMatch, sizeof( con.completionField->buffer )); Q_sprintf( con.completionField->buffer, "\\%s", con.shortestMatch );
con.completionField->cursor = Q_strlen( con.completionField->buffer ); con.completionField->cursor = Q_strlen( con.completionField->buffer );
Con_ConcatRemaining( temp.buffer, con.completionString ); Con_ConcatRemaining( temp.buffer, con.completionString );

View File

@@ -24,11 +24,9 @@ Crash handler, called from system
================ ================
*/ */
#if XASH_CRASHHANDLER == CRASHHANDLER_DBGHELP || XASH_CRASHHANDLER == CRASHHANDLER_WIN32 #if XASH_CRASHHANDLER == CRASHHANDLER_DBGHELP || XASH_CRASHHANDLER == CRASHHANDLER_WIN32
#if XASH_CRASHHANDLER == CRASHHANDLER_DBGHELP #if XASH_CRASHHANDLER == CRASHHANDLER_DBGHELP
#pragma comment( lib, "dbghelp" ) #pragma comment( lib, "dbghelp" )
#pragma comment( lib, "psapi" )
#include <winnt.h> #include <winnt.h>
#include <dbghelp.h> #include <dbghelp.h>
#include <psapi.h> #include <psapi.h>
@@ -37,7 +35,7 @@ Crash handler, called from system
typedef ULONG_PTR DWORD_PTR, *PDWORD_PTR; typedef ULONG_PTR DWORD_PTR, *PDWORD_PTR;
#endif #endif
static int Sys_ModuleName( HANDLE process, char *name, void *address, int len ) int ModuleName( HANDLE process, char *name, void *address, int len )
{ {
DWORD_PTR baseAddress = 0; DWORD_PTR baseAddress = 0;
static HMODULE *moduleArray; static HMODULE *moduleArray;
@@ -46,24 +44,27 @@ static int Sys_ModuleName( HANDLE process, char *name, void *address, int len )
DWORD bytesRequired; DWORD bytesRequired;
int i; int i;
if( len < 3 ) if(len < 3)
return 0; return 0;
if( !moduleArray && EnumProcessModules( process, NULL, 0, &bytesRequired ) ) if ( !moduleArray && EnumProcessModules( process, NULL, 0, &bytesRequired ) )
{ {
if ( bytesRequired ) if ( bytesRequired )
{ {
moduleArrayBytes = (LPBYTE)LocalAlloc( LPTR, bytesRequired ); moduleArrayBytes = (LPBYTE)LocalAlloc( LPTR, bytesRequired );
if( moduleArrayBytes && EnumProcessModules( process, (HMODULE *)moduleArrayBytes, bytesRequired, &bytesRequired ) ) if ( moduleArrayBytes )
{ {
moduleCount = bytesRequired / sizeof( HMODULE ); if( EnumProcessModules( process, (HMODULE *)moduleArrayBytes, bytesRequired, &bytesRequired ) )
moduleArray = (HMODULE *)moduleArrayBytes; {
moduleCount = bytesRequired / sizeof( HMODULE );
moduleArray = (HMODULE *)moduleArrayBytes;
}
} }
} }
} }
for( i = 0; i < moduleCount; i++ ) for( i = 0; i<moduleCount; i++ )
{ {
MODULEINFO info; MODULEINFO info;
GetModuleInformation( process, moduleArray[i], &info, sizeof(MODULEINFO) ); GetModuleInformation( process, moduleArray[i], &info, sizeof(MODULEINFO) );
@@ -72,10 +73,9 @@ static int Sys_ModuleName( HANDLE process, char *name, void *address, int len )
( (DWORD64)address < (DWORD64)info.lpBaseOfDll + (DWORD64)info.SizeOfImage ) ) ( (DWORD64)address < (DWORD64)info.lpBaseOfDll + (DWORD64)info.SizeOfImage ) )
return GetModuleBaseName( process, moduleArray[i], name, len ); return GetModuleBaseName( process, moduleArray[i], name, len );
} }
return Q_snprintf( name, len, "???" ); return Q_snprintf(name, len, "???");
} }
static void stack_trace( PEXCEPTION_POINTERS pInfo )
static void Sys_StackTrace( PEXCEPTION_POINTERS pInfo )
{ {
char message[1024]; char message[1024];
int len = 0; int len = 0;
@@ -89,8 +89,7 @@ static void Sys_StackTrace( PEXCEPTION_POINTERS pInfo )
STACKFRAME64 stackframe; STACKFRAME64 stackframe;
DWORD image; DWORD image;
memcpy( &context, pInfo->ContextRecord, sizeof( CONTEXT )); memcpy( &context, pInfo->ContextRecord, sizeof(CONTEXT) );
options = SymGetOptions(); options = SymGetOptions();
options |= SYMOPT_DEBUG; options |= SYMOPT_DEBUG;
options |= SYMOPT_LOAD_LINES; options |= SYMOPT_LOAD_LINES;
@@ -98,7 +97,9 @@ static void Sys_StackTrace( PEXCEPTION_POINTERS pInfo )
SymInitialize( process, NULL, TRUE ); SymInitialize( process, NULL, TRUE );
ZeroMemory( &stackframe, sizeof( STACKFRAME64 ));
ZeroMemory( &stackframe, sizeof(STACKFRAME64) );
#ifdef _M_IX86 #ifdef _M_IX86
image = IMAGE_FILE_MACHINE_I386; image = IMAGE_FILE_MACHINE_I386;
@@ -126,25 +127,19 @@ static void Sys_StackTrace( PEXCEPTION_POINTERS pInfo )
stackframe.AddrBStore.Mode = AddrModeFlat; stackframe.AddrBStore.Mode = AddrModeFlat;
stackframe.AddrStack.Offset = context.IntSp; stackframe.AddrStack.Offset = context.IntSp;
stackframe.AddrStack.Mode = AddrModeFlat; stackframe.AddrStack.Mode = AddrModeFlat;
#elif
#error
#endif #endif
len += Q_snprintf( message + len, 1024 - len, "Sys_Crash: address %p, code %p\n", len += Q_snprintf( message + len, 1024 - len, "Sys_Crash: address %p, code %p\n", pInfo->ExceptionRecord->ExceptionAddress, (void*)pInfo->ExceptionRecord->ExceptionCode );
pInfo->ExceptionRecord->ExceptionAddress, (void*)pInfo->ExceptionRecord->ExceptionCode );
if( SymGetLineFromAddr64( process, (DWORD64)pInfo->ExceptionRecord->ExceptionAddress, &dline, &line ) ) if( SymGetLineFromAddr64( process, (DWORD64)pInfo->ExceptionRecord->ExceptionAddress, &dline, &line ) )
{ {
len += Q_snprintf(message + len, 1024 - len, "Exception: %s:%d:%d\n", len += Q_snprintf(message + len, 1024 - len,"Exception: %s:%d:%d\n", (char*)line.FileName, (int)line.LineNumber, (int)dline);
(char*)line.FileName, (int)line.LineNumber, (int)dline);
} }
if( SymGetLineFromAddr64( process, stackframe.AddrPC.Offset, &dline, &line ) ) if( SymGetLineFromAddr64( process, stackframe.AddrPC.Offset, &dline, &line ) )
{ {
len += Q_snprintf(message + len, 1024 - len,"PC: %s:%d:%d\n", len += Q_snprintf(message + len, 1024 - len,"PC: %s:%d:%d\n", (char*)line.FileName, (int)line.LineNumber, (int)dline);
(char*)line.FileName, (int)line.LineNumber, (int)dline);
} }
if( SymGetLineFromAddr64( process, stackframe.AddrFrame.Offset, &dline, &line ) ) if( SymGetLineFromAddr64( process, stackframe.AddrFrame.Offset, &dline, &line ) )
{ {
len += Q_snprintf(message + len, 1024 - len,"Frame: %s:%d:%d\n", len += Q_snprintf(message + len, 1024 - len,"Frame: %s:%d:%d\n", (char*)line.FileName, (int)line.LineNumber, (int)dline);
(char*)line.FileName, (int)line.LineNumber, (int)dline);
} }
for( i = 0; i < 25; i++ ) for( i = 0; i < 25; i++ )
{ {
@@ -154,43 +149,39 @@ static void Sys_StackTrace( PEXCEPTION_POINTERS pInfo )
image, process, thread, image, process, thread,
&stackframe, &context, NULL, &stackframe, &context, NULL,
SymFunctionTableAccess64, SymGetModuleBase64, NULL); SymFunctionTableAccess64, SymGetModuleBase64, NULL);
DWORD64 displacement = 0;
DWORD64 displacement = 0;
if( !result ) if( !result )
break; break;
symbol->SizeOfStruct = sizeof(SYMBOL_INFO); symbol->SizeOfStruct = sizeof(SYMBOL_INFO);
symbol->MaxNameLen = MAX_SYM_NAME; symbol->MaxNameLen = MAX_SYM_NAME;
len += Q_snprintf( message + len, 1024 - len, "% 2d %p", len += Q_snprintf( message + len, 1024 - len, "% 2d %p", i, (void*)stackframe.AddrPC.Offset );
i, (void*)stackframe.AddrPC.Offset );
if( SymFromAddr( process, stackframe.AddrPC.Offset, &displacement, symbol ) ) if( SymFromAddr( process, stackframe.AddrPC.Offset, &displacement, symbol ) )
{ {
len += Q_snprintf( message + len, 1024 - len, " %s ", symbol->Name ); len += Q_snprintf( message + len, 1024 - len, " %s ", symbol->Name );
} }
if( SymGetLineFromAddr64( process, stackframe.AddrPC.Offset, &dline, &line ) ) if( SymGetLineFromAddr64( process, stackframe.AddrPC.Offset, &dline, &line ) )
{ {
len += Q_snprintf(message + len, 1024 - len,"(%s:%d:%d) ", len += Q_snprintf(message + len, 1024 - len,"(%s:%d:%d) ", (char*)line.FileName, (int)line.LineNumber, (int)dline);
(char*)line.FileName, (int)line.LineNumber, (int)dline);
} }
len += Q_snprintf( message + len, 1024 - len, "("); len += Q_snprintf( message + len, 1024 - len, "(");
len += Sys_ModuleName( process, message + len, (void*)stackframe.AddrPC.Offset, 1024 - len ); len += ModuleName( process, message + len, (void*)stackframe.AddrPC.Offset, 1024 - len );
len += Q_snprintf( message + len, 1024 - len, ")\n"); len += Q_snprintf( message + len, 1024 - len, ")\n");
} }
#ifdef XASH_SDL
#if XASH_SDL == 2
if( host.type != HOST_DEDICATED ) // let system to restart server automaticly if( host.type != HOST_DEDICATED ) // let system to restart server automaticly
SDL_ShowSimpleMessageBox( SDL_MESSAGEBOX_ERROR, "Sys_Crash", message, host.hWnd ); SDL_ShowSimpleMessageBox( SDL_MESSAGEBOX_ERROR,"Sys_Crash", message, host.hWnd );
#endif #endif
Sys_PrintLog(message);
Sys_PrintLog( message ); SymCleanup(process);
SymCleanup( process );
} }
#endif /* XASH_CRASHHANDLER == CRASHHANDLER_DBGHELP */ #endif //DBGHELP
LPTOP_LEVEL_EXCEPTION_FILTER oldFilter; LPTOP_LEVEL_EXCEPTION_FILTER oldFilter;
static long _stdcall Sys_Crash( PEXCEPTION_POINTERS pInfo ) long _stdcall Sys_Crash( PEXCEPTION_POINTERS pInfo )
{ {
// save config // save config
if( host.status != HOST_CRASHED ) if( host.status != HOST_CRASHED )
@@ -199,7 +190,7 @@ static long _stdcall Sys_Crash( PEXCEPTION_POINTERS pInfo )
host.crashed = true; host.crashed = true;
#if XASH_CRASHHANDLER == CRASHHANDLER_DBGHELP #if XASH_CRASHHANDLER == CRASHHANDLER_DBGHELP
Sys_StackTrace( pInfo ); stack_trace( pInfo );
#else #else
Sys_Warn( "Sys_Crash: call %p at address %p", pInfo->ExceptionRecord->ExceptionAddress, pInfo->ExceptionRecord->ExceptionCode ); Sys_Warn( "Sys_Crash: call %p at address %p", pInfo->ExceptionRecord->ExceptionAddress, pInfo->ExceptionRecord->ExceptionCode );
#endif #endif
@@ -242,14 +233,13 @@ void Sys_RestoreCrashHandler( void )
#include "library.h" #include "library.h"
#if XASH_FREEBSD || XASH_NETBSD || XASH_OPENBSD || XASH_ANDROID || XASH_LINUX #if XASH_FREEBSD || XASH_NETBSD || XASH_ANDROID || XASH_LINUX
#define HAVE_UCONTEXT_H 1 #define HAVE_UCONTEXT_H 1
#endif #endif
#ifdef HAVE_UCONTEXT_H #ifdef HAVE_UCONTEXT_H
#include <ucontext.h> #include <ucontext.h>
#endif #endif
#include <signal.h> #include <signal.h>
#include <sys/mman.h> #include <sys/mman.h>
@@ -271,7 +261,7 @@ static int d_dladdr( void *sym, Dl_info *info )
#define dladdr d_dladdr #define dladdr d_dladdr
#endif #endif
static int Sys_PrintFrame( char *buf, int len, int i, void *addr ) int printframe( char *buf, int len, int i, void *addr )
{ {
Dl_info dlinfo; Dl_info dlinfo;
if( len <= 0 ) if( len <= 0 )
@@ -281,7 +271,7 @@ static int Sys_PrintFrame( char *buf, int len, int i, void *addr )
{ {
if( dlinfo.dli_sname ) if( dlinfo.dli_sname )
return Q_snprintf( buf, len, "%2d: %p <%s+%lu> (%s)\n", i, addr, 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 (unsigned long)addr - (unsigned long)dlinfo.dli_saddr, dlinfo.dli_fname ); // print symbol, module and address
else else
return Q_snprintf( buf, len, "%2d: %p (%s)\n", i, addr, dlinfo.dli_fname ); // print module and address return Q_snprintf( buf, len, "%2d: %p (%s)\n", i, addr, dlinfo.dli_fname ); // print module and address
} }
@@ -291,11 +281,10 @@ static int Sys_PrintFrame( char *buf, int len, int i, void *addr )
struct sigaction oldFilter; struct sigaction oldFilter;
#define STACK_BACKTRACE_STR "Stack backtrace:\n" #define STACK_BACKTRACE_STR_LEN 17
#define STACK_DUMP_STR "Stack dump:\n" #define STACK_BACKTRACE_STR "Stack backtrace:\n"
#define STACK_DUMP_STR_LEN 12
#define STACK_BACKTRACE_STR_LEN (sizeof( STACK_BACKTRACE_STR ) - 1) #define STACK_DUMP_STR "Stack dump:\n"
#define STACK_DUMP_STR_LEN (sizeof( STACK_DUMP_STR ) - 1)
#define ALIGN( x, y ) (((uintptr_t) (x) + ((y)-1)) & ~((y)-1)) #define ALIGN( x, y ) (((uintptr_t) (x) + ((y)-1)) & ~((y)-1))
static void Sys_Crash( int signal, siginfo_t *si, void *context) static void Sys_Crash( int signal, siginfo_t *si, void *context)
@@ -367,7 +356,7 @@ static void Sys_Crash( int signal, siginfo_t *si, void *context)
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 ); 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 #endif
write( STDERR_FILENO, message, len ); write( 2, message, len );
// flush buffers before writing directly to descriptors // flush buffers before writing directly to descriptors
fflush( stdout ); fflush( stdout );
@@ -381,9 +370,9 @@ static void Sys_Crash( int signal, siginfo_t *si, void *context)
{ {
size_t pagesize = sysconf( _SC_PAGESIZE ); size_t pagesize = sysconf( _SC_PAGESIZE );
// try to print backtrace // try to print backtrace
write( STDERR_FILENO, STACK_BACKTRACE_STR, STACK_BACKTRACE_STR_LEN ); write( 2, STACK_BACKTRACE_STR, STACK_BACKTRACE_STR_LEN );
write( logfd, 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 ); strncpy( message + len, STACK_BACKTRACE_STR, sizeof( message ) - len );
len += STACK_BACKTRACE_STR_LEN; len += STACK_BACKTRACE_STR_LEN;
// false on success, true on failure // false on success, true on failure
@@ -395,8 +384,8 @@ static void Sys_Crash( int signal, siginfo_t *si, void *context)
do do
{ {
int line = Sys_PrintFrame( message + len, sizeof( message ) - len, ++i, pc); int line = printframe( message + len, sizeof( message ) - len, ++i, pc);
write( STDERR_FILENO, message + len, line ); write( 2, message + len, line );
write( logfd, message + len, line ); write( logfd, message + len, line );
len += line; len += line;
//if( !dladdr(bp,0) ) break; // only when bp is in module //if( !dladdr(bp,0) ) break; // only when bp is in module
@@ -410,17 +399,17 @@ static void Sys_Crash( int signal, siginfo_t *si, void *context)
while( bp && i < 128 ); while( bp && i < 128 );
// try to print stack // try to print stack
write( STDERR_FILENO, STACK_DUMP_STR, STACK_DUMP_STR_LEN ); write( 2, STACK_DUMP_STR, STACK_DUMP_STR_LEN );
write( logfd, 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 ); strncpy( message + len, STACK_DUMP_STR, sizeof( message ) - len );
len += STACK_DUMP_STR_LEN; len += STACK_DUMP_STR_LEN;
if( !try_allow_read( sp, pagesize ) ) if( !try_allow_read( sp, pagesize ) )
{ {
for( i = 0; i < 32; i++ ) for( i = 0; i < 32; i++ )
{ {
int line = Sys_PrintFrame( message + len, sizeof( message ) - len, i, sp[i] ); int line = printframe( message + len, sizeof( message ) - len, i, sp[i] );
write( STDERR_FILENO, message + len, line ); write( 2, message + len, line );
write( logfd, message + len, line ); write( logfd, message + len, line );
len += line; len += line;
} }

View File

@@ -16,13 +16,10 @@ GNU General Public License for more details.
#include <math.h> // fabs... #include <math.h> // fabs...
#include "common.h" #include "common.h"
#include "base_cmd.h" #include "base_cmd.h"
#include "eiface.h" // ARRAYSIZE
convar_t *cvar_vars = NULL; // head of list convar_t *cvar_vars = NULL; // head of list
convar_t *cmd_scripting; convar_t *cmd_scripting;
CVAR_DEFINE_AUTO( cl_filterstuffcmd, "0", FCVAR_ARCHIVE | FCVAR_PRIVILEGED, "filter commands coming from server" );
/* /*
============ ============
Cvar_GetList Cvar_GetList
@@ -74,7 +71,7 @@ build cvar auto description that based on the setup flags
*/ */
const char *Cvar_BuildAutoDescription( int flags ) const char *Cvar_BuildAutoDescription( int flags )
{ {
static char desc[256]; static char desc[128];
desc[0] = '\0'; desc[0] = '\0';
@@ -94,12 +91,6 @@ const char *Cvar_BuildAutoDescription( int flags )
if( FBitSet( flags, FCVAR_ARCHIVE )) if( FBitSet( flags, FCVAR_ARCHIVE ))
Q_strncat( desc, "archived ", sizeof( desc )); Q_strncat( desc, "archived ", sizeof( desc ));
if( FBitSet( flags, FCVAR_PROTECTED ))
Q_strncat( desc, "protected ", sizeof( desc ));
if( FBitSet( flags, FCVAR_PRIVILEGED ))
Q_strncat( desc, "privileged ", sizeof( desc ));
Q_strncat( desc, "cvar", sizeof( desc )); Q_strncat( desc, "cvar", sizeof( desc ));
return desc; return desc;
@@ -519,7 +510,7 @@ void Cvar_DirectSet( convar_t *var, const char *value )
if( var != Cvar_FindVar( var->name )) if( var != Cvar_FindVar( var->name ))
return; // how this possible? return; // how this possible?
if( FBitSet( var->flags, FCVAR_READ_ONLY )) if( FBitSet( var->flags, FCVAR_READ_ONLY|FCVAR_GLCONFIG ))
{ {
Con_Printf( "%s is read-only.\n", var->name ); Con_Printf( "%s is read-only.\n", var->name );
return; return;
@@ -763,32 +754,6 @@ static void Cvar_SetGL( const char *name, const char *value )
Cvar_FullSet( name, value, FCVAR_GLCONFIG ); Cvar_FullSet( name, value, FCVAR_GLCONFIG );
} }
static qboolean Cvar_ShouldSetCvar( convar_t *v, qboolean isPrivileged )
{
const char *prefixes[] = { "cl_", "gl_", "m_", "r_", "hud_" };
int i;
if( isPrivileged )
return true;
if( FBitSet( v->flags, FCVAR_PRIVILEGED ))
return false;
if( cl_filterstuffcmd.value <= 0.0f )
return true;
if( FBitSet( v->flags, FCVAR_FILTERABLE ))
return false;
for( i = 0; i < ARRAYSIZE( prefixes ); i++ )
{
if( !Q_strnicmp( v->name, prefixes[i], Q_strlen( prefixes[i] )))
return false;
}
return true;
}
/* /*
============ ============
Cvar_Command Cvar_Command
@@ -796,7 +761,7 @@ Cvar_Command
Handles variable inspection and changing from the console Handles variable inspection and changing from the console
============ ============
*/ */
qboolean Cvar_CommandWithPrivilegeCheck( convar_t *v, qboolean isPrivileged ) qboolean Cvar_Command( convar_t *v )
{ {
// special case for setup opengl configuration // special case for setup opengl configuration
if( host.apply_opengl_config ) if( host.apply_opengl_config )
@@ -808,8 +773,7 @@ qboolean Cvar_CommandWithPrivilegeCheck( convar_t *v, qboolean isPrivileged )
// check variables // check variables
if( !v ) // already found in basecmd if( !v ) // already found in basecmd
v = Cvar_FindVar( Cmd_Argv( 0 )); v = Cvar_FindVar( Cmd_Argv( 0 ));
if( !v ) if( !v ) return false;
return false;
// perform a variable print or set // perform a variable print or set
if( Cmd_Argc() == 1 ) if( Cmd_Argc() == 1 )
@@ -832,11 +796,6 @@ qboolean Cvar_CommandWithPrivilegeCheck( convar_t *v, qboolean isPrivileged )
Con_Printf( "can't set \"%s\" in multiplayer\n", v->name ); Con_Printf( "can't set \"%s\" in multiplayer\n", v->name );
return false; return false;
} }
else if( !Cvar_ShouldSetCvar( v, isPrivileged ))
{
Con_Printf( "%s is a privileged variable\n", v->name );
return true;
}
else else
{ {
Cvar_DirectSet( v, Cmd_Argv( 1 )); Cvar_DirectSet( v, Cmd_Argv( 1 ));
@@ -934,20 +893,16 @@ void Cvar_List_f( void )
const char *match = NULL; const char *match = NULL;
char *value; char *value;
int count = 0; int count = 0;
size_t matchlen = 0;
if( Cmd_Argc() > 1 ) if( Cmd_Argc() > 1 )
{
match = Cmd_Argv( 1 ); match = Cmd_Argv( 1 );
matchlen = Q_strlen( match );
}
for( var = cvar_vars; var; var = var->next ) for( var = cvar_vars; var; var = var->next )
{ {
if( var->name[0] == '@' ) if( var->name[0] == '@' )
continue; // never shows system cvars continue; // never shows system cvars
if( match && !Q_strnicmpext( match, var->name, matchlen )) if( match && !Q_stricmpext( match, var->name ))
continue; continue;
if( Q_colorstr( var->string )) if( Q_colorstr( var->string ))
@@ -998,59 +953,11 @@ Reads in all archived cvars
void Cvar_Init( void ) void Cvar_Init( void )
{ {
cvar_vars = NULL; cvar_vars = NULL;
cmd_scripting = Cvar_Get( "cmd_scripting", "0", FCVAR_ARCHIVE|FCVAR_PRIVILEGED, "enable simple condition checking and variable operations" ); cmd_scripting = Cvar_Get( "cmd_scripting", "0", FCVAR_ARCHIVE, "enable simple condition checking and variable operations" );
Cvar_RegisterVariable (&host_developer); // early registering for dev Cvar_RegisterVariable (&host_developer); // early registering for dev
Cvar_RegisterVariable( &cl_filterstuffcmd );
Cmd_AddRestrictedCommand( "setgl", Cvar_SetGL_f, "change the value of a opengl variable" ); // OBSOLETE Cmd_AddCommand( "setgl", Cvar_SetGL_f, "change the value of a opengl variable" ); // OBSOLETE
Cmd_AddRestrictedCommand( "toggle", Cvar_Toggle_f, "toggles a console variable's values (use for more info)" ); Cmd_AddCommand( "toggle", Cvar_Toggle_f, "toggles a console variable's values (use for more info)" );
Cmd_AddRestrictedCommand( "reset", Cvar_Reset_f, "reset any type variable to initial value" ); Cmd_AddCommand( "reset", Cvar_Reset_f, "reset any type variable to initial value" );
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" );
} }
#if XASH_ENGINE_TESTS
#include "tests.h"
void Test_RunCvar( void )
{
convar_t *test_privileged = Cvar_Get( "test_privileged", "0", FCVAR_PRIVILEGED, "bark bark" );
convar_t *test_unprivileged = Cvar_Get( "test_unprivileged", "0", 0, "meow meow" );
convar_t *hud_filtered = Cvar_Get( "hud_filtered", "0", 0, "dummy description" );
convar_t *filtered2 = Cvar_Get( "filtered2", "0", FCVAR_FILTERABLE, "filtered2" );
Cbuf_AddText( "test_privileged 1; test_unprivileged 1; hud_filtered 1; filtered2 1\n" );
Cbuf_Execute();
TASSERT( test_privileged->value != 0.0f );
TASSERT( test_unprivileged->value != 0.0f );
TASSERT( hud_filtered->value != 0.0f );
TASSERT( filtered2->value != 0.0f );
Cvar_DirectSet( test_privileged, "0" );
Cvar_DirectSet( test_unprivileged, "0" );
Cvar_DirectSet( hud_filtered, "0" );
Cvar_DirectSet( filtered2, "0" );
Cvar_DirectSet( &cl_filterstuffcmd, "0" );
Cbuf_AddFilteredText( "test_privileged 1; test_unprivileged 1; hud_filtered 1; filtered2 1\n" );
Cbuf_Execute();
Cbuf_Execute();
Cbuf_Execute();
TASSERT( test_privileged->value == 0.0f );
TASSERT( test_unprivileged->value != 0.0f );
TASSERT( hud_filtered->value != 0.0f );
TASSERT( filtered2->value != 0.0f );
Cvar_DirectSet( test_privileged, "0" );
Cvar_DirectSet( test_unprivileged, "0" );
Cvar_DirectSet( hud_filtered, "0" );
Cvar_DirectSet( filtered2, "0" );
Cvar_DirectSet( &cl_filterstuffcmd, "1" );
Cbuf_AddFilteredText( "test_privileged 1; test_unprivileged 1; hud_filtered 1; filtered2 1\n" );
Cbuf_Execute();
Cbuf_Execute();
Cbuf_Execute();
TASSERT( test_privileged->value == 0.0f );
TASSERT( test_unprivileged->value != 0.0f );
TASSERT( hud_filtered->value == 0.0f );
TASSERT( filtered2->value == 0.0f );
}
#endif

View File

@@ -47,7 +47,7 @@ typedef struct convar_s
#define FCVAR_ALLOCATED (1<<19) // this convar_t is fully dynamic allocated (include description) #define FCVAR_ALLOCATED (1<<19) // this convar_t is fully dynamic allocated (include description)
#define FCVAR_VIDRESTART (1<<20) // recreate the window is cvar with this flag was changed #define FCVAR_VIDRESTART (1<<20) // recreate the window is cvar with this flag was changed
#define FCVAR_TEMPORARY (1<<21) // these cvars holds their values and can be unlink in any time #define FCVAR_TEMPORARY (1<<21) // these cvars holds their values and can be unlink in any time
#define FCVAR_MOVEVARS (1<<22) // this cvar is a part of movevars_t struct that shared between client and server #define FCVAR_LOCALONLY (1<<22) // can be set only from local buffers
#define CVAR_DEFINE( cv, cvname, cvstr, cvflags, cvdesc ) \ #define CVAR_DEFINE( cv, cvname, cvstr, cvflags, cvdesc ) \
convar_t cv = { (char*)cvname, (char*)cvstr, cvflags, 0.0f, (void *)CVAR_SENTINEL, (char*)cvdesc, NULL } convar_t cv = { (char*)cvname, (char*)cvstr, cvflags, 0.0f, (void *)CVAR_SENTINEL, (char*)cvdesc, NULL }
@@ -75,7 +75,7 @@ void Cvar_WriteVariables( file_t *f, int group );
qboolean Cvar_Exists( const char *var_name ); qboolean Cvar_Exists( const char *var_name );
void Cvar_Reset( const char *var_name ); 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_Command( convar_t *v );
void Cvar_Init( void ); void Cvar_Init( void );
void Cvar_Unlink( int group ); void Cvar_Unlink( int group );

View File

@@ -306,6 +306,11 @@ void SCR_CheckStartupVids( void )
} }
void Sys_SetClipboardData( const char *text, size_t size )
{
}
void CL_StopPlayback( void ) void CL_StopPlayback( void )
{ {

File diff suppressed because it is too large Load Diff

200
engine/common/filesystem.h Normal file
View File

@@ -0,0 +1,200 @@
/*
filesystem.h - engine FS
Copyright (C) 2007 Uncle Mike
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
*/
#ifndef FILESYSTEM_H
#define FILESYSTEM_H
/*
========================================================================
PAK FILES
The .pak files are just a linear collapse of a directory tree
========================================================================
*/
// header
#define IDPACKV1HEADER (('K'<<24)+('C'<<16)+('A'<<8)+'P') // little-endian "PACK"
#define MAX_FILES_IN_PACK 65536 // pak
typedef struct
{
int ident;
int dirofs;
int dirlen;
} dpackheader_t;
typedef struct
{
char name[56]; // total 64 bytes
int filepos;
int filelen;
} dpackfile_t;
/*
========================================================================
.WAD archive format (WhereAllData - WAD)
List of compressed files, that can be identify only by TYPE_*
<format>
header: dwadinfo_t[dwadinfo_t]
file_1: byte[dwadinfo_t[num]->disksize]
file_2: byte[dwadinfo_t[num]->disksize]
file_3: byte[dwadinfo_t[num]->disksize]
...
file_n: byte[dwadinfo_t[num]->disksize]
infotable dlumpinfo_t[dwadinfo_t->numlumps]
========================================================================
*/
#define WAD3_NAMELEN 16
#define HINT_NAMELEN 5 // e.g. _mask, _norm
#define MAX_FILES_IN_WAD 65535 // real limit as above <2Gb size not a lumpcount
#include "const.h"
typedef struct
{
int ident; // should be WAD3
int numlumps; // num files
int infotableofs; // LUT offset
} dwadinfo_t;
typedef struct
{
int filepos; // file offset in WAD
int disksize; // compressed or uncompressed
int size; // uncompressed
signed char type; // TYP_*
signed char attribs; // file attribs
signed char pad0;
signed char pad1;
char name[WAD3_NAMELEN]; // must be null terminated
} dlumpinfo_t;
#include "custom.h"
/*
========================================================================
.HPK archive format (Hash PAK - HPK)
List of compressed files, that can be identify only by TYPE_*
<format>
header: dwadinfo_t[dwadinfo_t]
file_1: byte[dwadinfo_t[num]->disksize]
file_2: byte[dwadinfo_t[num]->disksize]
file_3: byte[dwadinfo_t[num]->disksize]
...
file_n: byte[dwadinfo_t[num]->disksize]
infotable dlumpinfo_t[dwadinfo_t->numlumps]
========================================================================
*/
#define IDHPAKHEADER (('K'<<24)+('A'<<16)+('P'<<8)+'H') // little-endian "HPAK"
#define IDHPAK_VERSION 1
typedef struct
{
int ident; // should be equal HPAK
int version;
int infotableofs;
} hpak_header_t;
typedef struct
{
resource_t resource;
int filepos;
int disksize;
} hpak_lump_t;
typedef struct
{
int count;
hpak_lump_t *entries; // variable sized.
} hpak_info_t;
#define ZIP_HEADER_LF (('K'<<8)+('P')+(0x03<<16)+(0x04<<24))
#define ZIP_HEADER_SPANNED ((0x08<<24)+(0x07<<16)+('K'<<8)+'P')
#define ZIP_HEADER_CDF ((0x02<<24)+(0x01<<16)+('K'<<8)+'P')
#define ZIP_HEADER_EOCD ((0x06<<24)+(0x05<<16)+('K'<<8)+'P')
#define ZIP_COMPRESSION_NO_COMPRESSION 0
#define ZIP_COMPRESSION_DEFLATED 8
#define ZIP_ZIP64 0xffffffff
#pragma pack( push, 1 )
typedef struct zip_header_s
{
unsigned int signature; // little endian ZIP_HEADER
unsigned short version; // version of pkzip need to unpack
unsigned short flags; // flags (16 bits == 16 flags)
unsigned short compression_flags; // compression flags (bits)
unsigned int dos_date; // file modification time and file modification date
unsigned int crc32; //crc32
unsigned int compressed_size;
unsigned int uncompressed_size;
unsigned short filename_len;
unsigned short extrafield_len;
} zip_header_t;
/*
in zip64 comp and uncompr size == 0xffffffff remeber this
compressed and uncompress filesize stored in extra field
*/
typedef struct zip_header_extra_s
{
unsigned int signature; // ZIP_HEADER_SPANNED
unsigned int crc32;
unsigned int compressed_size;
unsigned int uncompressed_size;
} zip_header_extra_t;
typedef struct zip_cdf_header_s
{
unsigned int signature;
unsigned short version;
unsigned short version_need;
unsigned short generalPurposeBitFlag;
unsigned short flags;
unsigned short modification_time;
unsigned short modification_date;
unsigned int crc32;
unsigned int compressed_size;
unsigned int uncompressed_size;
unsigned short filename_len;
unsigned short extrafield_len;
unsigned short file_commentary_len;
unsigned short disk_start;
unsigned short internal_attr;
unsigned int external_attr;
unsigned int local_header_offset;
} zip_cdf_header_t;
typedef struct zip_header_eocd_s
{
unsigned short disk_number;
unsigned short start_disk_number;
unsigned short number_central_directory_record;
unsigned short total_central_directory_record;
unsigned int size_of_central_directory;
unsigned int central_directory_offset;
unsigned short commentary_len;
} zip_header_eocd_t;
#pragma pack( pop )
#endif//FILESYSTEM_H

View File

@@ -1,153 +0,0 @@
/*
filesystem.c - game filesystem based on DP fs
Copyright (C) 2007 Uncle Mike
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
*/
#include "common.h"
#include "library.h"
fs_api_t g_fsapi;
fs_globals_t *FI;
static HINSTANCE fs_hInstance;
static void FS_Rescan_f( void )
{
FS_Rescan();
}
static void FS_ClearPaths_f( void )
{
FS_ClearSearchPath();
}
static void FS_Path_f_( void )
{
FS_Path_f();
}
static fs_interface_t fs_memfuncs =
{
Con_Printf,
Con_DPrintf,
Con_Reportf,
Sys_Error,
_Mem_AllocPool,
_Mem_FreePool,
_Mem_Alloc,
_Mem_Realloc,
_Mem_Free,
};
static void FS_UnloadProgs( void )
{
COM_FreeLibrary( fs_hInstance );
fs_hInstance = 0;
}
#ifdef XASH_INTERNAL_GAMELIBS
#define FILESYSTEM_STDIO_DLL "filesystem_stdio"
#else
#define FILESYSTEM_STDIO_DLL "filesystem_stdio." OS_LIB_EXT
#endif
qboolean FS_LoadProgs( void )
{
const char *name = FILESYSTEM_STDIO_DLL;
FSAPI GetFSAPI;
fs_hInstance = COM_LoadLibrary( name, false, true );
if( !fs_hInstance )
{
Host_Error( "FS_LoadProgs: can't load filesystem library %s: %s\n", name, COM_GetLibraryError() );
return false;
}
if( !( GetFSAPI = (FSAPI)COM_GetProcAddress( fs_hInstance, GET_FS_API )))
{
FS_UnloadProgs();
Host_Error( "FS_LoadProgs: can't find GetFSAPI entry point in %s\n", name );
return false;
}
if( !GetFSAPI( FS_API_VERSION, &g_fsapi, &FI, &fs_memfuncs ))
{
FS_UnloadProgs();
Host_Error( "FS_LoadProgs: can't initialize filesystem API: wrong version\n" );
return false;
}
Con_DPrintf( "FS_LoadProgs: filesystem_stdio successfully loaded\n" );
return true;
}
/*
================
FS_Init
================
*/
void FS_Init( void )
{
qboolean hasBaseDir = false;
qboolean hasGameDir = false;
qboolean caseinsensitive = true;
int i;
string gamedir;
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_clearpaths", FS_ClearPaths_f, "clear filesystem search pathes" );
#if !XASH_WIN32
if( Sys_CheckParm( "-casesensitive" ) )
caseinsensitive = false;
#endif
if( !Sys_GetParmFromCmdLine( "-game", gamedir ))
Q_strncpy( gamedir, SI.basedirName, sizeof( gamedir )); // gamedir == basedir
if( !FS_InitStdio( caseinsensitive, host.rootdir, SI.basedirName, gamedir, host.rodir ))
{
Host_Error( "Can't init filesystem_stdio!\n" );
return;
}
if( !Sys_GetParmFromCmdLine( "-dll", SI.gamedll ))
SI.gamedll[0] = 0;
if( !Sys_GetParmFromCmdLine( "-clientlib", SI.clientlib ))
SI.clientlib[0] = 0;
}
/*
================
FS_Shutdown
================
*/
void FS_Shutdown( void )
{
int i;
FS_ShutdownStdio();
memset( &SI, 0, sizeof( sysinfo_t ));
FS_UnloadProgs();
}

View File

@@ -15,7 +15,6 @@ GNU General Public License for more details.
#include "common.h" #include "common.h"
#include "xash3d_mathlib.h" #include "xash3d_mathlib.h"
#include "enginefeatures.h"
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Gamma conversion support // Gamma conversion support
@@ -79,16 +78,10 @@ void BuildGammaTable( float lightgamma, float brightness )
byte LightToTexGamma( byte b ) byte LightToTexGamma( byte b )
{ {
if( FBitSet( host.features, ENGINE_LINEAR_GAMMA_SPACE )) return lightgammatable[b];
return b;
else
return lightgammatable[b];
} }
byte TextureToGamma( byte b ) byte TextureToGamma( byte b )
{ {
if( FBitSet( host.features, ENGINE_LINEAR_GAMMA_SPACE )) return texgammatable[b];
return b;
else
return texgammatable[b];
} }

View File

@@ -50,8 +50,7 @@ sysinfo_t SI;
struct tests_stats_s tests_stats; struct tests_stats_s tests_stats;
#endif #endif
CVAR_DEFINE( host_developer, "developer", "0", FCVAR_FILTERABLE, "engine is in development-mode" ); CVAR_DEFINE( host_developer, "developer", "0", 0, "engine is in development-mode" );
CVAR_DEFINE_AUTO( sys_timescale, "1.0", FCVAR_CHEAT|FCVAR_FILTERABLE, "scale frame time" );
CVAR_DEFINE_AUTO( sys_ticrate, "100", 0, "framerate in dedicated mode" ); CVAR_DEFINE_AUTO( sys_ticrate, "100", 0, "framerate in dedicated mode" );
convar_t *host_serverstate; convar_t *host_serverstate;
@@ -86,11 +85,9 @@ void Sys_PrintUsage( void )
O("-dev [level] ","set log verbosity 0-2") O("-dev [level] ","set log verbosity 0-2")
O("-log ","write log to \"engine.log\"") O("-log ","write log to \"engine.log\"")
O("-nowriteconfig ","disable config save") O("-nowriteconfig ","disable config save")
#if !XASH_WIN32 #if !XASH_WIN32
O("-casesensitive ","disable case-insensitive FS emulation") O("-casesensitive ","disable case-insensitive FS emulation")
#endif // !XASH_WIN32 #endif // !XASH_WIN32
#if !XASH_MOBILE_PLATFORM #if !XASH_MOBILE_PLATFORM
O("-daemonize ","run engine in background, dedicated only") O("-daemonize ","run engine in background, dedicated only")
#endif // !XASH_MOBILE_PLATFORM #endif // !XASH_MOBILE_PLATFORM
@@ -101,58 +98,56 @@ void Sys_PrintUsage( void )
O("-height <n> ","set window height") O("-height <n> ","set window height")
O("-oldfont ","enable unused Quake font in Half-Life") O("-oldfont ","enable unused Quake font in Half-Life")
#if !XASH_MOBILE_PLATFORM #if !XASH_MOBILE_PLATFORM
O("-fullscreen ","run engine in fullscreen mode") O("-fullscreen ","run engine in fullscreen mode")
O("-windowed ","run engine in windowed mode") O("-windowed ","run engine in windowed mode")
O("-dedicated ","run engine in dedicated server mode") O("-dedicated ","run engine in dedicated server mode")
#endif // XASH_MOBILE_PLATFORM #endif // XASH_MOBILE_PLATFORM
#if XASH_ANDROID #if XASH_ANDROID
O("-nativeegl ","use native egl implementation. Use if screen does not update or black") O("-nativeegl ","use native egl implementation. Use if screen does not update or black")
#endif // XASH_ANDROID #endif // XASH_ANDROID
#if XASH_WIN32 #if XASH_WIN32
O("-noavi ","disable AVI support") O("-noavi ","disable AVI support")
O("-nointro ","disable intro video") O("-nointro ","disable intro video")
#endif // XASH_WIN32 #endif // XASH_WIN32
#if XASH_DOS #if XASH_DOS
O("-novesa ","disable vesa") O("-novesa ","disable vesa")
#endif // XASH_DOS #endif // XASH_DOS
#if XASH_VIDEO == VIDEO_FBDEV #if XASH_VIDEO == VIDEO_FBDEV
O("-fbdev <path> ","open selected framebuffer") O("-fbdev <path> ","open selected framebuffer")
O("-ttygfx ","set graphics mode in tty") O("-ttygfx ","set graphics mode in tty")
O("-doublebuffer ","enable doublebuffering") O("-doublebuffer ","enable doublebuffering")
#endif // XASH_VIDEO == VIDEO_FBDEV #endif // XASH_VIDEO == VIDEO_FBDEV
#if XASH_SOUND == SOUND_ALSA #if XASH_SOUND == SOUND_ALSA
O("-alsadev <dev> ","open selected ALSA device") O("-alsadev <dev> ","open selected ALSA device")
#endif // XASH_SOUND == SOUND_ALSA #endif // XASH_SOUND == SOUND_ALSA
O("-nojoy ","disable joystick support") O("-nojoy ","disable joystick support")
#ifdef XASH_SDL
#ifdef XASH_SDL
O("-sdl_joy_old_api ","use SDL legacy joystick API") 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
O("-nosound ","disable sound") O("-nosound ","disable sound")
O("-noenginemouse ","disable mouse completely") O("-noenginemouse ","disable mouse completely")
O("-ref <name> ","use selected renderer dll") O("-ref <name> ","use selected renderer dll")
O("-gldebug ","enable OpenGL debug log") O("-gldebug ","enable OpenGL debug log")
#endif // XASH_DEDICATED #endif // XASH_DEDICATED
O("-noip ","disable TCP/IP") O("-noip ","disable TCP/IP")
O("-noch ","disable crashhandler") O("-noch ","disable crashhandler")
O("-disablehelp ","disable this message") O("-disablehelp ","disable this message")
O("-dll <path> ","override server DLL path") O("-dll <path> ","override server DLL path")
#if !XASH_DEDICATED #ifndef XASH_DEDICATED
O("-clientlib <path>","override client DLL path") O("-clientlib <path>","override client DLL path")
#endif #endif
O("-rodir <path> ","set read-only base directory, experimental") O("-rodir <path> ","set read-only base directory, experimental")
O("-bugcomp ","enable precise bug compatibility. Will break games that don't require it")
O(" ","Refer to engine documentation for more info")
O("-ip <ip> ","set custom ip") O("-ip <ip> ","set custom ip")
O("-port <port> ","set custom host port") O("-port <port> ","set custom host port")
@@ -307,9 +302,7 @@ void Host_NewInstance( const char *name, const char *finalmsg )
host.change_game = true; host.change_game = true;
Q_strncpy( host.finalmsg, finalmsg, sizeof( host.finalmsg )); Q_strncpy( host.finalmsg, finalmsg, sizeof( host.finalmsg ));
pChangeGame( name ); // call from hl.exe
if( !Sys_NewInstance( name ))
pChangeGame( name ); // call from hl.exe
} }
/* /*
@@ -330,13 +323,13 @@ void Host_ChangeGame_f( void )
} }
// validate gamedir // validate gamedir
for( i = 0; i < FI->numgames; i++ ) for( i = 0; i < SI.numgames; i++ )
{ {
if( !Q_stricmp( FI->games[i]->gamefolder, Cmd_Argv( 1 ))) if( !Q_stricmp( SI.games[i]->gamefolder, Cmd_Argv( 1 )))
break; break;
} }
if( i == FI->numgames ) if( i == SI.numgames )
{ {
Con_Printf( "%s not exist\n", Cmd_Argv( 1 )); Con_Printf( "%s not exist\n", Cmd_Argv( 1 ));
} }
@@ -347,7 +340,7 @@ void Host_ChangeGame_f( void )
else else
{ {
const char *arg1 = va( "%s%s", (host.type == HOST_NORMAL) ? "" : "#", Cmd_Argv( 1 )); const char *arg1 = va( "%s%s", (host.type == HOST_NORMAL) ? "" : "#", Cmd_Argv( 1 ));
const char *arg2 = va( "change game to '%s'", FI->games[i]->title ); const char *arg2 = va( "change game to '%s'", SI.games[i]->title );
Host_NewInstance( arg1, arg2 ); Host_NewInstance( arg1, arg2 );
} }
@@ -360,11 +353,10 @@ Host_Exec_f
*/ */
void Host_Exec_f( void ) void Host_Exec_f( void )
{ {
string cfgpath; string cfgpath;
byte *f; byte *f;
char *txt; char *txt;
fs_offset_t len; fs_offset_t len;
const char *arg;
if( Cmd_Argc() != 2 ) if( Cmd_Argc() != 2 )
{ {
@@ -372,47 +364,14 @@ void Host_Exec_f( void )
return; return;
} }
arg = Cmd_Argv( 1 ); if( !Q_stricmp( "game.cfg", Cmd_Argv( 1 )))
#ifndef XASH_DEDICATED
if( !Cmd_CurrentCommandIsPrivileged() )
{
const char *unprivilegedWhitelist[] =
{
NULL, "mapdefault.cfg", "scout.cfg", "sniper.cfg",
"soldier.cfg", "demoman.cfg", "medic.cfg", "hwguy.cfg",
"pyro.cfg", "spy.cfg", "engineer.cfg", "civilian.cfg"
};
int i;
qboolean allow = false;
unprivilegedWhitelist[0] = va( "%s.cfg", clgame.mapname );
for( i = 0; i < ARRAYSIZE( unprivilegedWhitelist ); i++ )
{
if( !Q_strcmp( arg, unprivilegedWhitelist[i] ))
{
allow = true;
break;
}
}
if( !allow )
{
Con_Printf( "exec %s: not privileged or in whitelist\n", arg );
return;
}
}
#endif // XASH_DEDICATED
if( !Q_stricmp( "game.cfg", arg ))
{ {
// don't execute game.cfg in singleplayer // don't execute game.cfg in singleplayer
if( SV_GetMaxClients() == 1 ) if( SV_GetMaxClients() == 1 )
return; return;
} }
Q_strncpy( cfgpath, arg, sizeof( cfgpath )); Q_strncpy( cfgpath, Cmd_Argv( 1 ), sizeof( cfgpath ));
COM_DefaultExtension( cfgpath, ".cfg" ); // append as default COM_DefaultExtension( cfgpath, ".cfg" ); // append as default
f = FS_LoadFile( cfgpath, &len, false ); f = FS_LoadFile( cfgpath, &len, false );
@@ -422,7 +381,7 @@ void Host_Exec_f( void )
return; return;
} }
if( !Q_stricmp( "config.cfg", arg )) if( !Q_stricmp( "config.cfg", Cmd_Argv( 1 )))
host.config_executed = true; host.config_executed = true;
// adds \n\0 at end of the file // adds \n\0 at end of the file
@@ -432,7 +391,7 @@ void Host_Exec_f( void )
Mem_Free( f ); Mem_Free( f );
if( !host.apply_game_config ) if( !host.apply_game_config )
Con_Printf( "execing %s\n", arg ); Con_Printf( "execing %s\n", Cmd_Argv( 1 ));
Cbuf_InsertText( txt ); Cbuf_InsertText( txt );
Mem_Free( txt ); Mem_Free( txt );
} }
@@ -633,9 +592,8 @@ qboolean Host_FilterTime( float time )
{ {
static double oldtime; static double oldtime;
double fps; double fps;
double scale = sys_timescale.value;
host.realtime += time * scale; host.realtime += time;
fps = Host_CalcFPS( ); fps = Host_CalcFPS( );
// clamp the fps in multiplayer games // clamp the fps in multiplayer games
@@ -646,12 +604,12 @@ qboolean Host_FilterTime( float time )
if( Host_IsDedicated() ) if( Host_IsDedicated() )
{ {
if(( host.realtime - oldtime ) < ( 1.0 / ( fps + 1.0 )) * scale) if(( host.realtime - oldtime ) < ( 1.0 / ( fps + 1.0 )))
return false; return false;
} }
else else
{ {
if(( host.realtime - oldtime ) < ( 1.0 / fps ) * scale ) if(( host.realtime - oldtime ) < ( 1.0 / fps ))
return false; return false;
} }
} }
@@ -662,7 +620,7 @@ qboolean Host_FilterTime( float time )
// NOTE: allow only in singleplayer while demos are not active // NOTE: allow only in singleplayer while demos are not active
if( host_framerate->value > 0.0f && Host_IsLocalGame() && !CL_IsPlaybackDemo() && !CL_IsRecordDemo( )) if( host_framerate->value > 0.0f && Host_IsLocalGame() && !CL_IsPlaybackDemo() && !CL_IsRecordDemo( ))
host.frametime = bound( MIN_FRAMETIME, host_framerate->value * scale, MAX_FRAMETIME ); host.frametime = bound( MIN_FRAMETIME, host_framerate->value, MAX_FRAMETIME );
else host.frametime = bound( MIN_FRAMETIME, host.frametime, MAX_FRAMETIME ); else host.frametime = bound( MIN_FRAMETIME, host.frametime, MAX_FRAMETIME );
return true; return true;
@@ -725,6 +683,7 @@ void GAME_EXPORT Host_Error( const char *error, ... )
else if( host.framecount == host.errorframe ) else if( host.framecount == host.errorframe )
{ {
Sys_Error( "Host_MultiError: %s", hosterror2 ); Sys_Error( "Host_MultiError: %s", hosterror2 );
return;
} }
else else
{ {
@@ -744,6 +703,7 @@ void GAME_EXPORT Host_Error( const char *error, ... )
{ {
Con_Printf( "Host_RecursiveError: %s", hosterror2 ); Con_Printf( "Host_RecursiveError: %s", hosterror2 );
Sys_Error( "%s", hosterror1 ); Sys_Error( "%s", hosterror1 );
return; // don't multiple executes
} }
recursive = true; recursive = true;
@@ -824,17 +784,9 @@ static void Host_RunTests( int stage )
memset( &tests_stats, 0, sizeof( tests_stats )); memset( &tests_stats, 0, sizeof( tests_stats ));
Test_RunLibCommon(); Test_RunLibCommon();
Test_RunCommon(); Test_RunCommon();
Test_RunCmd();
Test_RunCvar();
#if !XASH_DEDICATED
Test_RunCon();
#endif /* XASH_DEDICATED */
break; break;
case 1: // after FS load case 1: // after FS load
Test_RunImagelib(); Test_RunImagelib();
#if !XASH_DEDICATED
Test_RunVOX();
#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 );
Sys_Quit(); Sys_Quit();
} }
@@ -861,10 +813,10 @@ void Host_InitCommon( int argc, char **argv, const char *progname, qboolean bCha
if( !Sys_CheckParm( "-disablehelp" ) ) if( !Sys_CheckParm( "-disablehelp" ) )
{ {
if( Sys_CheckParm( "-help" ) || Sys_CheckParm( "-h" ) || Sys_CheckParm( "--help" ) ) if( Sys_CheckParm( "-help" ) || Sys_CheckParm( "-h" ) || Sys_CheckParm( "--help" ) )
{ {
Sys_PrintUsage(); Sys_PrintUsage();
} }
} }
if( !Sys_CheckParm( "-noch" ) ) if( !Sys_CheckParm( "-noch" ) )
@@ -872,7 +824,7 @@ void Host_InitCommon( int argc, char **argv, const char *progname, qboolean bCha
host.enabledll = !Sys_CheckParm( "-nodll" ); host.enabledll = !Sys_CheckParm( "-nodll" );
host.change_game = bChangeGame || Sys_CheckParm( "-changegame" ); host.change_game = bChangeGame;
host.config_executed = false; host.config_executed = false;
host.status = HOST_INIT; // initialzation started host.status = HOST_INIT; // initialzation started
@@ -943,13 +895,6 @@ void Host_InitCommon( int argc, char **argv, const char *progname, qboolean bCha
// member console allowing // member console allowing
host.allow_console_init = host.allow_console; host.allow_console_init = host.allow_console;
if( Sys_CheckParm( "-bugcomp" ))
{
// add argument check here when we add other levels
// of bugcompatibility
host.bugcomp = BUGCOMP_GOLDSRC;
}
// timeBeginPeriod( 1 ); // a1ba: Do we need this? // timeBeginPeriod( 1 ); // a1ba: Do we need this?
// NOTE: this message couldn't be passed into game console but it doesn't matter // NOTE: this message couldn't be passed into game console but it doesn't matter
@@ -1017,7 +962,7 @@ void Host_InitCommon( int argc, char **argv, const char *progname, qboolean bCha
len = Q_strlen( host.rootdir ); len = Q_strlen( host.rootdir );
if( len && host.rootdir[len - 1] == '/' ) if( host.rootdir[len - 1] == '/' )
host.rootdir[len - 1] = 0; host.rootdir[len - 1] = 0;
// get readonly root. The order is: check for arg, then env. // get readonly root. The order is: check for arg, then env.
@@ -1036,33 +981,18 @@ void Host_InitCommon( int argc, char **argv, const char *progname, qboolean bCha
if( len && host.rodir[len - 1] == '/' ) if( len && host.rodir[len - 1] == '/' )
host.rodir[len - 1] = 0; host.rodir[len - 1] = 0;
if( !COM_CheckStringEmpty( host.rootdir )) if( !COM_CheckStringEmpty( host.rootdir ) || FS_SetCurrentDirectory( host.rootdir ) != 0 )
{
Sys_Error( "Changing working directory failed (empty working directory)\n" );
return;
}
FS_LoadProgs();
if( FS_SetCurrentDirectory( host.rootdir ) != 0 )
Con_Reportf( "%s is working directory now\n", host.rootdir ); Con_Reportf( "%s is working directory now\n", host.rootdir );
else else
Sys_Error( "Changing working directory to %s failed.\n", host.rootdir ); Sys_Error( "Changing working directory to %s failed.\n", host.rootdir );
FS_Init();
Sys_InitLog(); Sys_InitLog();
// print bugcompatibility level here, after log was initialized
if( host.bugcomp == BUGCOMP_GOLDSRC )
{
Con_Printf( "^3BUGCOMP^7: GoldSrc bug-compatibility enabled\n" );
}
Cmd_AddCommand( "exec", Host_Exec_f, "execute a script file" ); Cmd_AddCommand( "exec", Host_Exec_f, "execute a script file" );
Cmd_AddCommand( "memlist", Host_MemStats_f, "prints memory pool information" ); Cmd_AddCommand( "memlist", Host_MemStats_f, "prints memory pool information" );
Cmd_AddRestrictedCommand( "userconfigd", Host_Userconfigd_f, "execute all scripts from userconfig.d" ); Cmd_AddCommand( "userconfigd", Host_Userconfigd_f, "execute all scripts from userconfig.d" );
FS_Init();
Image_Init(); Image_Init();
Sound_Init(); Sound_Init();
@@ -1072,16 +1002,8 @@ void Host_InitCommon( int argc, char **argv, const char *progname, qboolean bCha
#endif #endif
FS_LoadGameInfo( NULL ); FS_LoadGameInfo( NULL );
if( FS_FileExists( va( "%s.rc", SI.basedirName ), false ))
Q_strncpy( SI.rcName, SI.basedirName, sizeof( SI.rcName )); // e.g. valve.rc
else Q_strncpy( SI.rcName, SI.exeName, sizeof( SI.rcName )); // e.g. quake.rc
Q_strncpy( host.gamefolder, GI->gamefolder, sizeof( host.gamefolder )); Q_strncpy( host.gamefolder, GI->gamefolder, sizeof( host.gamefolder ));
Image_CheckPaletteQ1 ();
Host_InitDecals (); // reload decals
// DEPRECATED: by FWGS fork // DEPRECATED: by FWGS fork
#if 0 #if 0
if( GI->secure ) if( GI->secure )
@@ -1124,25 +1046,23 @@ int EXPORT Host_Main( int argc, char **argv, const char *progname, int bChangeGa
// init commands and vars // init commands and vars
if( host_developer.value >= DEV_EXTENDED ) if( host_developer.value >= DEV_EXTENDED )
{ {
Cmd_AddRestrictedCommand ( "sys_error", Sys_Error_f, "just throw a fatal error to test shutdown procedures"); Cmd_AddCommand ( "sys_error", Sys_Error_f, "just throw a fatal error to test shutdown procedures");
Cmd_AddRestrictedCommand ( "host_error", Host_Error_f, "just throw a host error to test shutdown procedures"); Cmd_AddCommand ( "host_error", Host_Error_f, "just throw a host error to test shutdown procedures");
Cmd_AddRestrictedCommand ( "crash", Host_Crash_f, "a way to force a bus error for development reasons"); Cmd_AddCommand ( "crash", Host_Crash_f, "a way to force a bus error for development reasons");
} }
host_serverstate = Cvar_Get( "host_serverstate", "0", FCVAR_READ_ONLY, "displays current server state" ); host_serverstate = Cvar_Get( "host_serverstate", "0", FCVAR_READ_ONLY, "displays current server state" );
host_maxfps = Cvar_Get( "fps_max", "72", FCVAR_ARCHIVE|FCVAR_FILTERABLE, "host fps upper limit" ); host_maxfps = Cvar_Get( "fps_max", "72", FCVAR_ARCHIVE, "host fps upper limit" );
host_framerate = Cvar_Get( "host_framerate", "0", FCVAR_FILTERABLE, "locks frame timing to this value in seconds" ); host_framerate = Cvar_Get( "host_framerate", "0", 0, "locks frame timing to this value in seconds" );
host_sleeptime = Cvar_Get( "sleeptime", "1", FCVAR_ARCHIVE|FCVAR_FILTERABLE, "milliseconds to sleep for each frame. higher values reduce fps accuracy" ); host_sleeptime = Cvar_Get( "sleeptime", "1", FCVAR_ARCHIVE, "milliseconds to sleep for each frame. higher values reduce fps accuracy" );
host_gameloaded = Cvar_Get( "host_gameloaded", "0", FCVAR_READ_ONLY, "inidcates a loaded game.dll" ); host_gameloaded = Cvar_Get( "host_gameloaded", "0", FCVAR_READ_ONLY, "inidcates a loaded game.dll" );
host_clientloaded = Cvar_Get( "host_clientloaded", "0", FCVAR_READ_ONLY, "inidcates a loaded client.dll" ); host_clientloaded = Cvar_Get( "host_clientloaded", "0", FCVAR_READ_ONLY, "inidcates a loaded client.dll" );
host_limitlocal = Cvar_Get( "host_limitlocal", "0", 0, "apply cl_cmdrate and rate to loopback connection" ); host_limitlocal = Cvar_Get( "host_limitlocal", "0", 0, "apply cl_cmdrate and rate to loopback connection" );
con_gamemaps = Cvar_Get( "con_mapfilter", "1", FCVAR_ARCHIVE, "when true show only maps in game folder" ); con_gamemaps = Cvar_Get( "con_mapfilter", "1", FCVAR_ARCHIVE, "when true show only maps in game folder" );
Cvar_RegisterVariable( &sys_timescale );
build = Cvar_Get( "buildnum", va( "%i", Q_buildnum_compat()), FCVAR_READ_ONLY, "returns a current build number" ); build = Cvar_Get( "buildnum", va( "%i", Q_buildnum_compat()), FCVAR_READ_ONLY, "returns a current build number" );
ver = Cvar_Get( "ver", va( "%i/%s (hw build %i)", PROTOCOL_VERSION, XASH_COMPAT_VERSION, Q_buildnum_compat()), FCVAR_READ_ONLY, "shows an engine version" ); ver = Cvar_Get( "ver", va( "%i/%s (hw build %i)", PROTOCOL_VERSION, XASH_COMPAT_VERSION, Q_buildnum_compat()), FCVAR_READ_ONLY, "shows an engine version" );
Cvar_Get( "host_ver", va( "%i %s %s %s %s", Q_buildnum(), XASH_VERSION, Q_buildos(), Q_buildarch(), Q_buildcommit() ), FCVAR_READ_ONLY, "detailed info about this build" ); Cvar_Get( "host_ver", va( "%i %s %s %s %s", Q_buildnum(), XASH_VERSION, Q_buildos(), Q_buildarch(), Q_buildcommit() ), FCVAR_READ_ONLY, "detailed info about this build" );
Cvar_Get( "host_lowmemorymode", va( "%i", XASH_LOW_MEMORY ), FCVAR_READ_ONLY, "indicates if engine compiled for low RAM consumption (0 - normal, 1 - low engine limits, 2 - low protocol limits)" );
Mod_Init(); Mod_Init();
NET_Init(); NET_Init();
@@ -1152,7 +1072,7 @@ int EXPORT Host_Main( int argc, char **argv, const char *progname, int bChangeGa
// allow to change game from the console // allow to change game from the console
if( pChangeGame != NULL ) if( pChangeGame != NULL )
{ {
Cmd_AddRestrictedCommand( "game", Host_ChangeGame_f, "change game" ); Cmd_AddCommand( "game", Host_ChangeGame_f, "change game" );
Cvar_Get( "host_allow_changegame", "1", FCVAR_READ_ONLY, "allows to change games" ); Cvar_Get( "host_allow_changegame", "1", FCVAR_READ_ONLY, "allows to change games" );
} }
else else
@@ -1172,10 +1092,10 @@ int EXPORT Host_Main( int argc, char **argv, const char *progname, int bChangeGa
Wcon_InitConsoleCommands (); Wcon_InitConsoleCommands ();
#endif #endif
Cmd_AddRestrictedCommand( "quit", Sys_Quit, "quit the game" ); Cmd_AddCommand( "quit", Sys_Quit, "quit the game" );
Cmd_AddRestrictedCommand( "exit", Sys_Quit, "quit the game" ); Cmd_AddCommand( "exit", Sys_Quit, "quit the game" );
} }
else Cmd_AddRestrictedCommand( "minimize", Host_Minimize_f, "minimize main window to tray" ); else Cmd_AddCommand( "minimize", Host_Minimize_f, "minimize main window to tray" );
host.errorframe = 0; host.errorframe = 0;

View File

@@ -14,7 +14,7 @@ GNU General Public License for more details.
*/ */
#include "common.h" #include "common.h"
#include "hpak.h" #include "filesystem.h"
#define HPAK_MAX_ENTRIES 0x8000 #define HPAK_MAX_ENTRIES 0x8000
#define HPAK_MIN_SIZE (1 * 1024) #define HPAK_MIN_SIZE (1 * 1024)
@@ -402,7 +402,7 @@ static qboolean HPAK_Validate( const char *filename, qboolean quiet )
FS_Seek( f, hdr.infotableofs, SEEK_SET ); FS_Seek( f, hdr.infotableofs, SEEK_SET );
FS_Read( f, &num_lumps, sizeof( num_lumps )); FS_Read( f, &num_lumps, sizeof( num_lumps ));
if( num_lumps < 1 || num_lumps > HPAK_MAX_ENTRIES ) if( num_lumps < 1 || num_lumps > MAX_FILES_IN_WAD )
{ {
Con_DPrintf( S_ERROR "HPAK_ValidatePak: %s has too many lumps %u.\n", pakname, num_lumps ); Con_DPrintf( S_ERROR "HPAK_ValidatePak: %s has too many lumps %u.\n", pakname, num_lumps );
FS_Close( f ); FS_Close( f );
@@ -1077,10 +1077,10 @@ void HPAK_Validate_f( void )
void HPAK_Init( void ) void HPAK_Init( void )
{ {
Cmd_AddRestrictedCommand( "hpklist", HPAK_List_f, "list all files in specified HPK-file" ); Cmd_AddCommand( "hpklist", HPAK_List_f, "list all files in specified HPK-file" );
Cmd_AddRestrictedCommand( "hpkremove", HPAK_Remove_f, "remove specified file from HPK-file" ); Cmd_AddCommand( "hpkremove", HPAK_Remove_f, "remove specified file from HPK-file" );
Cmd_AddRestrictedCommand( "hpkval", HPAK_Validate_f, "validate specified HPK-file" ); Cmd_AddCommand( "hpkval", HPAK_Validate_f, "validate specified HPK-file" );
Cmd_AddRestrictedCommand( "hpkextract", HPAK_Extract_f, "extract all lumps from specified HPK-file" ); Cmd_AddCommand( "hpkextract", HPAK_Extract_f, "extract all lumps from specified HPK-file" );
hpk_maxsize = Cvar_Get( "hpk_maxsize", "0", FCVAR_ARCHIVE, "set limit by size for all HPK-files ( 0 - unlimited )" ); hpk_maxsize = Cvar_Get( "hpk_maxsize", "0", FCVAR_ARCHIVE, "set limit by size for all HPK-files ( 0 - unlimited )" );
gp_hpak_queue = NULL; gp_hpak_queue = NULL;

View File

@@ -1,60 +0,0 @@
/*
hpak.c - custom user package to send other clients
Copyright (C) 2010 Uncle Mike
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
*/
#ifndef HPAK_H
#define HPAK_H
#include "custom.h"
/*
========================================================================
.HPK archive format (Hash PAK - HPK)
List of compressed files, that can be identify only by TYPE_*
<format>
header: dwadinfo_t[dwadinfo_t]
file_1: byte[dwadinfo_t[num]->disksize]
file_2: byte[dwadinfo_t[num]->disksize]
file_3: byte[dwadinfo_t[num]->disksize]
...
file_n: byte[dwadinfo_t[num]->disksize]
infotable dlumpinfo_t[dwadinfo_t->numlumps]
========================================================================
*/
#define IDHPAKHEADER (('K'<<24)+('A'<<16)+('P'<<8)+'H') // little-endian "HPAK"
#define IDHPAK_VERSION 1
typedef struct
{
int ident; // should be equal HPAK
int version;
int infotableofs;
} hpak_header_t;
typedef struct
{
resource_t resource;
int filepos;
int disksize;
} hpak_lump_t;
typedef struct
{
int count;
hpak_lump_t *entries; // variable sized.
} hpak_info_t;
#endif // HPAK_H

View File

@@ -614,10 +614,10 @@ void ID_Init( void )
byte md5[16]; byte md5[16];
int i; int i;
Cmd_AddRestrictedCommand( "bloomfilter", ID_BloomFilter_f, "print bloomfilter raw value of arguments set"); Cmd_AddCommand( "bloomfilter", ID_BloomFilter_f, "print bloomfilter raw value of arguments set");
Cmd_AddRestrictedCommand( "verifyhex", ID_VerifyHEX_f, "check if id source seems to be fake" ); Cmd_AddCommand( "verifyhex", ID_VerifyHEX_f, "check if id source seems to be fake" );
#if XASH_LINUX #if XASH_LINUX
Cmd_AddRestrictedCommand( "testcpuinfo", ID_TestCPUInfo_f, "try read cpu serial" ); Cmd_AddCommand( "testcpuinfo", ID_TestCPUInfo_f, "try read cpu serial" );
#endif #endif
#if XASH_ANDROID && !XASH_DEDICATED #if XASH_ANDROID && !XASH_DEDICATED

View File

@@ -41,7 +41,7 @@ qboolean Image_LoadBMP( const char *name, const byte *buffer, fs_offset_t filesi
buf_p = (byte *)buffer; buf_p = (byte *)buffer;
memcpy( &bhdr, buf_p, sizeof( bmp_t )); memcpy( &bhdr, buf_p, sizeof( bmp_t ));
buf_p += BI_FILE_HEADER_SIZE + bhdr.bitmapHeaderSize; buf_p += sizeof( bmp_t );
// bogus file header check // bogus file header check
if( bhdr.reserved0 != 0 ) return false; if( bhdr.reserved0 != 0 ) return false;
@@ -53,9 +53,9 @@ qboolean Image_LoadBMP( const char *name, const byte *buffer, fs_offset_t filesi
return false; return false;
} }
if(!( bhdr.bitmapHeaderSize == 40 || bhdr.bitmapHeaderSize == 108 || bhdr.bitmapHeaderSize == 124 )) if( bhdr.bitmapHeaderSize != 0x28 )
{ {
Con_DPrintf( S_ERROR "Image_LoadBMP: %s have non-standard header size %i\n", name, bhdr.bitmapHeaderSize ); Con_DPrintf( S_ERROR "Image_LoadBMP: invalid header size %i\n", bhdr.bitmapHeaderSize );
return false; return false;
} }
@@ -187,7 +187,6 @@ qboolean Image_LoadBMP( const char *name, const byte *buffer, fs_offset_t filesi
return false; return false;
} }
image.depth = 1;
image.size = image.width * image.height * bpp; image.size = image.width * image.height * bpp;
image.rgba = Mem_Malloc( host.imagepool, image.size ); image.rgba = Mem_Malloc( host.imagepool, image.size );
@@ -314,8 +313,8 @@ qboolean Image_LoadBMP( const char *name, const byte *buffer, fs_offset_t filesi
} }
VectorDivide( reflectivity, ( image.width * image.height ), image.fogParams ); VectorDivide( reflectivity, ( image.width * image.height ), image.fogParams );
if( image.palette ) if( image.palette ) Image_GetPaletteBMP( image.palette );
Image_GetPaletteBMP( image.palette ); image.depth = 1;
return true; return true;
} }

View File

@@ -22,7 +22,6 @@ GNU General Public License for more details.
======================================================================== ========================================================================
*/ */
#define BI_FILE_HEADER_SIZE 14
#define BI_SIZE 40 // size of bitmap info header. #define BI_SIZE 40 // size of bitmap info header.
#if !defined(BI_RGB) #if !defined(BI_RGB)
#define BI_RGB 0 // uncompressed RGB bitmap(defined in wingdi.h) #define BI_RGB 0 // uncompressed RGB bitmap(defined in wingdi.h)

View File

@@ -91,7 +91,7 @@ qboolean Image_CheckDXT5Alpha( dds_t *hdr, byte *fin )
return false; return false;
} }
void Image_DXTGetPixelFormat( dds_t *hdr, dds_header_dxt10_t *headerExt ) void Image_DXTGetPixelFormat( dds_t *hdr )
{ {
uint bits = hdr->dsPixelFormat.dwRGBBitCount; uint bits = hdr->dsPixelFormat.dwRGBBitCount;
@@ -100,53 +100,29 @@ void Image_DXTGetPixelFormat( dds_t *hdr, dds_header_dxt10_t *headerExt )
if( FBitSet( hdr->dsPixelFormat.dwFlags, DDS_FOURCC )) if( FBitSet( hdr->dsPixelFormat.dwFlags, DDS_FOURCC ))
{ {
if( hdr->dsPixelFormat.dwFourCC == TYPE_DX10 ) switch( hdr->dsPixelFormat.dwFourCC )
{ {
switch( headerExt->dxgiFormat ) case TYPE_DXT1:
{ image.type = PF_DXT1;
case DXGI_FORMAT_BC6H_SF16: break;
image.type = PF_BC6H_SIGNED; case TYPE_DXT2:
break; image.flags &= ~IMAGE_HAS_ALPHA; // alpha is already premultiplied by color
case DXGI_FORMAT_BC6H_UF16: // intentionally fallthrough
case DXGI_FORMAT_BC6H_TYPELESS: case TYPE_DXT3:
image.type = PF_BC6H_UNSIGNED; image.type = PF_DXT3;
break; break;
case DXGI_FORMAT_BC7_UNORM: case TYPE_DXT4:
case DXGI_FORMAT_BC7_UNORM_SRGB: image.flags &= ~IMAGE_HAS_ALPHA; // alpha is already premultiplied by color
case DXGI_FORMAT_BC7_TYPELESS: // intentionally fallthrough
image.type = PF_BC7; case TYPE_DXT5:
break; image.type = PF_DXT5;
default: break;
image.type = PF_UNKNOWN; case TYPE_ATI2:
break; image.type = PF_ATI2;
} break;
} default:
else image.type = PF_UNKNOWN; // assume error
{ break;
switch( hdr->dsPixelFormat.dwFourCC )
{
case TYPE_DXT1:
image.type = PF_DXT1;
break;
case TYPE_DXT2:
image.flags &= ~IMAGE_HAS_ALPHA; // alpha is already premultiplied by color
// intentionally fallthrough
case TYPE_DXT3:
image.type = PF_DXT3;
break;
case TYPE_DXT4:
image.flags &= ~IMAGE_HAS_ALPHA; // alpha is already premultiplied by color
// intentionally fallthrough
case TYPE_DXT5:
image.type = PF_DXT5;
break;
case TYPE_ATI2:
image.type = PF_ATI2;
break;
default:
image.type = PF_UNKNOWN; // assume error
break;
}
} }
} }
else else
@@ -195,9 +171,6 @@ size_t Image_DXTGetLinearSize( int type, int width, int height, int depth )
case PF_DXT1: return ((( width + 3 ) / 4 ) * (( height + 3 ) / 4 ) * depth * 8 ); case PF_DXT1: return ((( width + 3 ) / 4 ) * (( height + 3 ) / 4 ) * depth * 8 );
case PF_DXT3: case PF_DXT3:
case PF_DXT5: case PF_DXT5:
case PF_BC6H_SIGNED:
case PF_BC6H_UNSIGNED:
case PF_BC7:
case PF_ATI2: return ((( width + 3 ) / 4 ) * (( height + 3 ) / 4 ) * depth * 16 ); case PF_ATI2: return ((( width + 3 ) / 4 ) * (( height + 3 ) / 4 ) * depth * 16 );
case PF_LUMINANCE: return (width * height * depth); case PF_LUMINANCE: return (width * height * depth);
case PF_BGR_24: case PF_BGR_24:
@@ -281,18 +254,16 @@ qboolean Image_LoadDDS( const char *name, const byte *buffer, fs_offset_t filesi
{ {
dds_t header; dds_t header;
byte *fin; byte *fin;
int headersOffset;
dds_header_dxt10_t header2;
if( filesize < sizeof( header )) if( filesize < sizeof( dds_t ))
return false; return false;
memcpy( &header, buffer, sizeof( header )); memcpy( &header, buffer, sizeof( dds_t ));
if( header.dwIdent != DDSHEADER ) if( header.dwIdent != DDSHEADER )
return false; // it's not a dds file, just skip it return false; // it's not a dds file, just skip it
if( header.dwSize != sizeof( header ) - sizeof( uint )) // size of the structure (minus MagicNum) if( header.dwSize != sizeof( dds_t ) - sizeof( uint )) // size of the structure (minus MagicNum)
{ {
Con_DPrintf( S_ERROR "Image_LoadDDS: (%s) have corrupted header\n", name ); Con_DPrintf( S_ERROR "Image_LoadDDS: (%s) have corrupted header\n", name );
return false; return false;
@@ -304,13 +275,6 @@ qboolean Image_LoadDDS( const char *name, const byte *buffer, fs_offset_t filesi
return false; return false;
} }
headersOffset = sizeof( header );
if( header.dsPixelFormat.dwFourCC == TYPE_DX10 )
{
memcpy( &header2, buffer + sizeof( header ), sizeof( header2 ));
headersOffset += sizeof( header2 );
}
image.width = header.dwWidth; image.width = header.dwWidth;
image.height = header.dwHeight; image.height = header.dwHeight;
@@ -320,7 +284,7 @@ qboolean Image_LoadDDS( const char *name, const byte *buffer, fs_offset_t filesi
if( !Image_ValidSize( name )) return false; if( !Image_ValidSize( name )) return false;
Image_DXTGetPixelFormat( &header, &header2 ); // and image type too :) Image_DXTGetPixelFormat( &header ); // and image type too :)
Image_DXTAdjustVolume( &header ); Image_DXTAdjustVolume( &header );
if( !Image_CheckFlag( IL_DDS_HARDWARE ) && ImageDXT( image.type )) if( !Image_CheckFlag( IL_DDS_HARDWARE ) && ImageDXT( image.type ))
@@ -332,9 +296,9 @@ qboolean Image_LoadDDS( const char *name, const byte *buffer, fs_offset_t filesi
return false; return false;
} }
image.size = Image_DXTCalcSize( name, &header, filesize - headersOffset ); image.size = Image_DXTCalcSize( name, &header, filesize - 128 );
if( image.size == 0 ) return false; // just in case if( image.size == 0 ) return false; // just in case
fin = (byte *)( buffer + headersOffset ); fin = (byte *)(buffer + sizeof( dds_t ));
// copy an encode method // copy an encode method
image.encode = (word)header.dwReserved1[0]; image.encode = (word)header.dwReserved1[0];
@@ -356,8 +320,6 @@ qboolean Image_LoadDDS( const char *name, const byte *buffer, fs_offset_t filesi
SetBits( image.flags, IMAGE_HAS_ALPHA ); SetBits( image.flags, IMAGE_HAS_ALPHA );
else if( image.type == PF_DXT5 && Image_CheckDXT5Alpha( &header, fin )) else if( image.type == PF_DXT5 && Image_CheckDXT5Alpha( &header, fin ))
SetBits( image.flags, IMAGE_HAS_ALPHA ); SetBits( image.flags, IMAGE_HAS_ALPHA );
else if ( image.type == PF_BC7 )
SetBits(image.flags, IMAGE_HAS_ALPHA);
if( !FBitSet( header.dsPixelFormat.dwFlags, DDS_LUMINANCE )) if( !FBitSet( header.dsPixelFormat.dwFlags, DDS_LUMINANCE ))
SetBits( image.flags, IMAGE_HAS_COLOR ); SetBits( image.flags, IMAGE_HAS_COLOR );
break; break;

View File

@@ -29,7 +29,6 @@ GNU General Public License for more details.
#define TYPE_DXT3 (('3'<<24)+('T'<<16)+('X'<<8)+'D') // little-endian "DXT3" #define TYPE_DXT3 (('3'<<24)+('T'<<16)+('X'<<8)+'D') // little-endian "DXT3"
#define TYPE_DXT4 (('4'<<24)+('T'<<16)+('X'<<8)+'D') // little-endian "DXT4" #define TYPE_DXT4 (('4'<<24)+('T'<<16)+('X'<<8)+'D') // little-endian "DXT4"
#define TYPE_DXT5 (('5'<<24)+('T'<<16)+('X'<<8)+'D') // little-endian "DXT5" #define TYPE_DXT5 (('5'<<24)+('T'<<16)+('X'<<8)+'D') // little-endian "DXT5"
#define TYPE_DX10 (('0'<<24)+('1'<<16)+('X'<<8)+'D') // little-endian "DX10"
#define TYPE_ATI1 (('1'<<24)+('I'<<16)+('T'<<8)+'A') // little-endian "ATI1" #define TYPE_ATI1 (('1'<<24)+('I'<<16)+('T'<<8)+'A') // little-endian "ATI1"
#define TYPE_ATI2 (('2'<<24)+('I'<<16)+('T'<<8)+'A') // little-endian "ATI2" #define TYPE_ATI2 (('2'<<24)+('I'<<16)+('T'<<8)+'A') // little-endian "ATI2"
#define TYPE_RXGB (('B'<<24)+('G'<<16)+('X'<<8)+'R') // little-endian "RXGB" doom3 normalmaps #define TYPE_RXGB (('B'<<24)+('G'<<16)+('X'<<8)+'R') // little-endian "RXGB" doom3 normalmaps
@@ -76,141 +75,6 @@ GNU General Public License for more details.
#define DDS_CUBEMAP_ALL_SIDES 0x0000FC00L #define DDS_CUBEMAP_ALL_SIDES 0x0000FC00L
#define DDS_VOLUME 0x00200000L #define DDS_VOLUME 0x00200000L
typedef enum
{
DXGI_FORMAT_UNKNOWN = 0,
DXGI_FORMAT_R32G32B32A32_TYPELESS = 1,
DXGI_FORMAT_R32G32B32A32_FLOAT = 2,
DXGI_FORMAT_R32G32B32A32_UINT = 3,
DXGI_FORMAT_R32G32B32A32_SINT = 4,
DXGI_FORMAT_R32G32B32_TYPELESS = 5,
DXGI_FORMAT_R32G32B32_FLOAT = 6,
DXGI_FORMAT_R32G32B32_UINT = 7,
DXGI_FORMAT_R32G32B32_SINT = 8,
DXGI_FORMAT_R16G16B16A16_TYPELESS = 9,
DXGI_FORMAT_R16G16B16A16_FLOAT = 10,
DXGI_FORMAT_R16G16B16A16_UNORM = 11,
DXGI_FORMAT_R16G16B16A16_UINT = 12,
DXGI_FORMAT_R16G16B16A16_SNORM = 13,
DXGI_FORMAT_R16G16B16A16_SINT = 14,
DXGI_FORMAT_R32G32_TYPELESS = 15,
DXGI_FORMAT_R32G32_FLOAT = 16,
DXGI_FORMAT_R32G32_UINT = 17,
DXGI_FORMAT_R32G32_SINT = 18,
DXGI_FORMAT_R32G8X24_TYPELESS = 19,
DXGI_FORMAT_D32_FLOAT_S8X24_UINT = 20,
DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS = 21,
DXGI_FORMAT_X32_TYPELESS_G8X24_UINT = 22,
DXGI_FORMAT_R10G10B10A2_TYPELESS = 23,
DXGI_FORMAT_R10G10B10A2_UNORM = 24,
DXGI_FORMAT_R10G10B10A2_UINT = 25,
DXGI_FORMAT_R11G11B10_FLOAT = 26,
DXGI_FORMAT_R8G8B8A8_TYPELESS = 27,
DXGI_FORMAT_R8G8B8A8_UNORM = 28,
DXGI_FORMAT_R8G8B8A8_UNORM_SRGB = 29,
DXGI_FORMAT_R8G8B8A8_UINT = 30,
DXGI_FORMAT_R8G8B8A8_SNORM = 31,
DXGI_FORMAT_R8G8B8A8_SINT = 32,
DXGI_FORMAT_R16G16_TYPELESS = 33,
DXGI_FORMAT_R16G16_FLOAT = 34,
DXGI_FORMAT_R16G16_UNORM = 35,
DXGI_FORMAT_R16G16_UINT = 36,
DXGI_FORMAT_R16G16_SNORM = 37,
DXGI_FORMAT_R16G16_SINT = 38,
DXGI_FORMAT_R32_TYPELESS = 39,
DXGI_FORMAT_D32_FLOAT = 40,
DXGI_FORMAT_R32_FLOAT = 41,
DXGI_FORMAT_R32_UINT = 42,
DXGI_FORMAT_R32_SINT = 43,
DXGI_FORMAT_R24G8_TYPELESS = 44,
DXGI_FORMAT_D24_UNORM_S8_UINT = 45,
DXGI_FORMAT_R24_UNORM_X8_TYPELESS = 46,
DXGI_FORMAT_X24_TYPELESS_G8_UINT = 47,
DXGI_FORMAT_R8G8_TYPELESS = 48,
DXGI_FORMAT_R8G8_UNORM = 49,
DXGI_FORMAT_R8G8_UINT = 50,
DXGI_FORMAT_R8G8_SNORM = 51,
DXGI_FORMAT_R8G8_SINT = 52,
DXGI_FORMAT_R16_TYPELESS = 53,
DXGI_FORMAT_R16_FLOAT = 54,
DXGI_FORMAT_D16_UNORM = 55,
DXGI_FORMAT_R16_UNORM = 56,
DXGI_FORMAT_R16_UINT = 57,
DXGI_FORMAT_R16_SNORM = 58,
DXGI_FORMAT_R16_SINT = 59,
DXGI_FORMAT_R8_TYPELESS = 60,
DXGI_FORMAT_R8_UNORM = 61,
DXGI_FORMAT_R8_UINT = 62,
DXGI_FORMAT_R8_SNORM = 63,
DXGI_FORMAT_R8_SINT = 64,
DXGI_FORMAT_A8_UNORM = 65,
DXGI_FORMAT_R1_UNORM = 66,
DXGI_FORMAT_R9G9B9E5_SHAREDEXP = 67,
DXGI_FORMAT_R8G8_B8G8_UNORM = 68,
DXGI_FORMAT_G8R8_G8B8_UNORM = 69,
DXGI_FORMAT_BC1_TYPELESS = 70,
DXGI_FORMAT_BC1_UNORM = 71,
DXGI_FORMAT_BC1_UNORM_SRGB = 72,
DXGI_FORMAT_BC2_TYPELESS = 73,
DXGI_FORMAT_BC2_UNORM = 74,
DXGI_FORMAT_BC2_UNORM_SRGB = 75,
DXGI_FORMAT_BC3_TYPELESS = 76,
DXGI_FORMAT_BC3_UNORM = 77,
DXGI_FORMAT_BC3_UNORM_SRGB = 78,
DXGI_FORMAT_BC4_TYPELESS = 79,
DXGI_FORMAT_BC4_UNORM = 80,
DXGI_FORMAT_BC4_SNORM = 81,
DXGI_FORMAT_BC5_TYPELESS = 82,
DXGI_FORMAT_BC5_UNORM = 83,
DXGI_FORMAT_BC5_SNORM = 84,
DXGI_FORMAT_B5G6R5_UNORM = 85,
DXGI_FORMAT_B5G5R5A1_UNORM = 86,
DXGI_FORMAT_B8G8R8A8_UNORM = 87,
DXGI_FORMAT_B8G8R8X8_UNORM = 88,
DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM = 89,
DXGI_FORMAT_B8G8R8A8_TYPELESS = 90,
DXGI_FORMAT_B8G8R8A8_UNORM_SRGB = 91,
DXGI_FORMAT_B8G8R8X8_TYPELESS = 92,
DXGI_FORMAT_B8G8R8X8_UNORM_SRGB = 93,
DXGI_FORMAT_BC6H_TYPELESS = 94,
DXGI_FORMAT_BC6H_UF16 = 95,
DXGI_FORMAT_BC6H_SF16 = 96,
DXGI_FORMAT_BC7_TYPELESS = 97,
DXGI_FORMAT_BC7_UNORM = 98,
DXGI_FORMAT_BC7_UNORM_SRGB = 99,
DXGI_FORMAT_AYUV = 100,
DXGI_FORMAT_Y410 = 101,
DXGI_FORMAT_Y416 = 102,
DXGI_FORMAT_NV12 = 103,
DXGI_FORMAT_P010 = 104,
DXGI_FORMAT_P016 = 105,
DXGI_FORMAT_420_OPAQUE = 106,
DXGI_FORMAT_YUY2 = 107,
DXGI_FORMAT_Y210 = 108,
DXGI_FORMAT_Y216 = 109,
DXGI_FORMAT_NV11 = 110,
DXGI_FORMAT_AI44 = 111,
DXGI_FORMAT_IA44 = 112,
DXGI_FORMAT_P8 = 113,
DXGI_FORMAT_A8P8 = 114,
DXGI_FORMAT_B4G4R4A4_UNORM = 115,
DXGI_FORMAT_P208 = 130,
DXGI_FORMAT_V208 = 131,
DXGI_FORMAT_V408 = 132,
DXGI_FORMAT_SAMPLER_FEEDBACK_MIN_MIP_OPAQUE,
DXGI_FORMAT_SAMPLER_FEEDBACK_MIP_REGION_USED_OPAQUE,
DXGI_FORMAT_FORCE_UINT = 0xffffffff
} dxgi_format_t;
typedef enum
{
D3D10_RESOURCE_DIMENSION_UNKNOWN = 0,
D3D10_RESOURCE_DIMENSION_BUFFER = 1,
D3D10_RESOURCE_DIMENSION_TEXTURE1D = 2,
D3D10_RESOURCE_DIMENSION_TEXTURE2D = 3,
D3D10_RESOURCE_DIMENSION_TEXTURE3D = 4
} dds_resource_dimension_t;
typedef struct dds_pf_s typedef struct dds_pf_s
{ {
uint32_t dwSize; uint32_t dwSize;
@@ -232,15 +96,6 @@ typedef struct dds_caps_s
uint32_t dwCaps4; // currently unused uint32_t dwCaps4; // currently unused
} dds_caps_t; } dds_caps_t;
typedef struct dds_header_dxt10_s
{
dxgi_format_t dxgiFormat;
dds_resource_dimension_t resourceDimension;
uint32_t miscFlag;
uint32_t arraySize;
uint32_t miscFlags2;
} dds_header_dxt10_t;
typedef struct dds_s typedef struct dds_s
{ {
uint32_t dwIdent; // must matched with DDSHEADER uint32_t dwIdent; // must matched with DDSHEADER

View File

@@ -71,7 +71,7 @@ static const cubepack_t load_cubemap[] =
}; };
// soul of ImageLib - table of image format constants // soul of ImageLib - table of image format constants
const bpc_desc_t PFDesc[] = const bpc_desc_t PFDesc[PF_TOTALCOUNT] =
{ {
{ PF_UNKNOWN, "raw", 0x1908, 0 }, { PF_UNKNOWN, "raw", 0x1908, 0 },
{ PF_INDEXED_24, "pal 24", 0x1908, 1 }, { PF_INDEXED_24, "pal 24", 0x1908, 1 },
@@ -85,6 +85,8 @@ const bpc_desc_t PFDesc[] =
{ PF_DXT3, "DXT 3", 0x83F2, 4 }, { PF_DXT3, "DXT 3", 0x83F2, 4 },
{ PF_DXT5, "DXT 5", 0x83F3, 4 }, { PF_DXT5, "DXT 5", 0x83F3, 4 },
{ PF_ATI2, "ATI 2", 0x8837, 4 }, { PF_ATI2, "ATI 2", 0x8837, 4 },
{ PF_RGBA_64, "RGBA 64", 0x1908, 8 },
{ PF_RGB_48, "RGB 48", 0x1908, 6 },
}; };
void Image_Reset( void ) void Image_Reset( void )
@@ -566,25 +568,4 @@ void Test_RunImagelib( void )
Z_Free( rgb.buffer ); Z_Free( rgb.buffer );
} }
#define IMPLEMENT_IMAGELIB_FUZZ_TARGET( export, target ) \
int EXPORT export( const uint8_t *Data, size_t Size ) \
{ \
rgbdata_t *rgb; \
host.type = HOST_NORMAL; \
Memory_Init(); \
Image_Init(); \
if( target( "#internal", Data, Size )) \
{ \
rgb = ImagePack(); \
FS_FreeImage( rgb ); \
} \
Image_Shutdown(); \
return 0; \
} \
IMPLEMENT_IMAGELIB_FUZZ_TARGET( Fuzz_Image_LoadBMP, Image_LoadBMP )
IMPLEMENT_IMAGELIB_FUZZ_TARGET( Fuzz_Image_LoadPNG, Image_LoadPNG )
IMPLEMENT_IMAGELIB_FUZZ_TARGET( Fuzz_Image_LoadDDS, Image_LoadDDS )
IMPLEMENT_IMAGELIB_FUZZ_TARGET( Fuzz_Image_LoadTGA, Image_LoadTGA )
#endif /* XASH_ENGINE_TESTS */ #endif /* XASH_ENGINE_TESTS */

View File

@@ -13,6 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
*/ */
#define MINIZ_HEADER_FILE_ONLY
#include "miniz.h" #include "miniz.h"
#include "imagelib.h" #include "imagelib.h"
#include "xash3d_mathlib.h" #include "xash3d_mathlib.h"
@@ -26,8 +27,6 @@ GNU General Public License for more details.
static const char png_sign[] = {0x89, 'P', 'N', 'G', '\r', '\n', 0x1a, '\n'}; static const char png_sign[] = {0x89, 'P', 'N', 'G', '\r', '\n', 0x1a, '\n'};
static const char ihdr_sign[] = {'I', 'H', 'D', 'R'}; static const char ihdr_sign[] = {'I', 'H', 'D', 'R'};
static const char trns_sign[] = {'t', 'R', 'N', 'S'};
static const char plte_sign[] = {'P', 'L', 'T', 'E'};
static const char idat_sign[] = {'I', 'D', 'A', 'T'}; static const char idat_sign[] = {'I', 'D', 'A', 'T'};
static const char iend_sign[] = {'I', 'E', 'N', 'D'}; static const char iend_sign[] = {'I', 'E', 'N', 'D'};
static const int iend_crc32 = 0xAE426082; static const int iend_crc32 = 0xAE426082;
@@ -41,10 +40,9 @@ qboolean Image_LoadPNG( const char *name, const byte *buffer, fs_offset_t filesi
{ {
int ret; int ret;
short p, a, b, c, pa, pb, pc; short p, a, b, c, pa, pb, pc;
byte *buf_p, *pixbuf, *raw, *prior, *idat_buf = NULL, *uncompressed_buffer = NULL, *rowend; byte *buf_p, *pixbuf, *raw, *prior, *idat_buf = NULL, *uncompressed_buffer = NULL;
byte *pallete = NULL, *trns = NULL; uint chunk_len, crc32, crc32_check, oldsize = 0, newsize = 0, rowsize;
uint chunk_len, trns_len, crc32, crc32_check, oldsize = 0, newsize = 0, rowsize; uint uncompressed_size, pixel_size, i, y, filter_type, chunk_sign, channel_size;
uint uncompressed_size, pixel_size, i, y, filter_type, chunk_sign, r_alpha, g_alpha, b_alpha;
qboolean has_iend_chunk = false; qboolean has_iend_chunk = false;
z_stream stream = {0}; z_stream stream = {0};
png_t png_hdr; png_t png_hdr;
@@ -70,7 +68,7 @@ qboolean Image_LoadPNG( const char *name, const byte *buffer, fs_offset_t filesi
// check IHDR chunk length (valid value - 13) // check IHDR chunk length (valid value - 13)
if( png_hdr.ihdr_len != sizeof( png_ihdr_t ) ) if( png_hdr.ihdr_len != sizeof( png_ihdr_t ) )
{ {
Con_DPrintf( S_ERROR "Image_LoadPNG: Invalid IHDR chunk size %u (%s)\n", png_hdr.ihdr_len, name ); Con_DPrintf( S_ERROR "Image_LoadPNG: Invalid IHDR chunk size (%s)\n", name );
return false; return false;
} }
@@ -87,35 +85,31 @@ qboolean Image_LoadPNG( const char *name, const byte *buffer, fs_offset_t filesi
if( png_hdr.ihdr_chunk.height == 0 || png_hdr.ihdr_chunk.width == 0 ) if( png_hdr.ihdr_chunk.height == 0 || png_hdr.ihdr_chunk.width == 0 )
{ {
Con_DPrintf( S_ERROR "Image_LoadPNG: Invalid image size %ux%u (%s)\n", png_hdr.ihdr_chunk.width, png_hdr.ihdr_chunk.height, name ); Con_DPrintf( S_ERROR "Image_LoadPNG: Invalid image size %dx%d (%s)\n", png_hdr.ihdr_chunk.width, png_hdr.ihdr_chunk.height, name );
return false; return false;
} }
if( png_hdr.ihdr_chunk.bitdepth != 8 ) if( png_hdr.ihdr_chunk.bitdepth != 8 && png_hdr.ihdr_chunk.bitdepth != 16 )
{ {
Con_DPrintf( S_WARN "Image_LoadPNG: Only 8-bit images is supported (%s)\n", name ); Con_DPrintf( S_WARN "Image_LoadPNG: Only 8-bit or 16-bit images is supported (%s)\n", name );
return false; return false;
} }
if( !( png_hdr.ihdr_chunk.colortype == PNG_CT_RGB if( png_hdr.ihdr_chunk.colortype != PNG_CT_RGB && png_hdr.ihdr_chunk.colortype != PNG_CT_RGBA )
|| png_hdr.ihdr_chunk.colortype == PNG_CT_RGBA
|| png_hdr.ihdr_chunk.colortype == PNG_CT_GREY
|| png_hdr.ihdr_chunk.colortype == PNG_CT_ALPHA
|| png_hdr.ihdr_chunk.colortype == PNG_CT_PALLETE ) )
{ {
Con_DPrintf( S_WARN "Image_LoadPNG: Unknown color type %u (%s)\n", png_hdr.ihdr_chunk.colortype, name ); Con_DPrintf( S_WARN "Image_LoadPNG: Only 8-bit RGB and RGBA images is supported (%s)\n", name );
return false; return false;
} }
if( png_hdr.ihdr_chunk.compression > 0 ) if( png_hdr.ihdr_chunk.compression > 0 )
{ {
Con_DPrintf( S_ERROR "Image_LoadPNG: Unknown compression method %u (%s)\n", png_hdr.ihdr_chunk.compression, name ); Con_DPrintf( S_ERROR "Image_LoadPNG: Unknown compression method (%s)\n", name );
return false; return false;
} }
if( png_hdr.ihdr_chunk.filter > 0 ) if( png_hdr.ihdr_chunk.filter > 0 )
{ {
Con_DPrintf( S_ERROR "Image_LoadPNG: Unknown filter type %u (%s)\n", png_hdr.ihdr_chunk.filter, name ); Con_DPrintf( S_ERROR "Image_LoadPNG: Unknown filter type (%s)\n", name );
return false; return false;
} }
@@ -127,7 +121,7 @@ qboolean Image_LoadPNG( const char *name, const byte *buffer, fs_offset_t filesi
if( png_hdr.ihdr_chunk.interlace > 0 ) if( png_hdr.ihdr_chunk.interlace > 0 )
{ {
Con_DPrintf( S_ERROR "Image_LoadPNG: Unknown interlacing type %u (%s)\n", png_hdr.ihdr_chunk.interlace, name ); Con_DPrintf( S_ERROR "Image_LoadPNG: Unknown interlacing type (%s)\n", name );
return false; return false;
} }
@@ -165,19 +159,8 @@ qboolean Image_LoadPNG( const char *name, const byte *buffer, fs_offset_t filesi
// move pointer // move pointer
buf_p += sizeof( chunk_sign ); buf_p += sizeof( chunk_sign );
// find transparency
if( !memcmp( buf_p, trns_sign, sizeof( trns_sign ) ) )
{
trns = buf_p + sizeof( trns_sign );
trns_len = chunk_len;
}
// find pallete for indexed image
else if( !memcmp( buf_p, plte_sign, sizeof( plte_sign ) ) )
{
pallete = buf_p + sizeof( plte_sign );
}
// get all IDAT chunks data // get all IDAT chunks data
else if( !memcmp( buf_p, idat_sign, sizeof( idat_sign ) ) ) if( !memcmp( buf_p, idat_sign, sizeof( idat_sign ) ) )
{ {
newsize = oldsize + chunk_len; newsize = oldsize + chunk_len;
idat_buf = (byte *)Mem_Realloc( host.imagepool, idat_buf, newsize ); idat_buf = (byte *)Mem_Realloc( host.imagepool, idat_buf, newsize );
@@ -211,13 +194,6 @@ qboolean Image_LoadPNG( const char *name, const byte *buffer, fs_offset_t filesi
buf_p += sizeof( crc32 ); buf_p += sizeof( crc32 );
} }
if( png_hdr.ihdr_chunk.colortype == PNG_CT_PALLETE && !pallete )
{
Con_DPrintf( S_ERROR "Image_LoadPNG: PLTE chunk not found (%s)\n", name );
Mem_Free( idat_buf );
return false;
}
if( !has_iend_chunk ) if( !has_iend_chunk )
{ {
Con_DPrintf( S_ERROR "Image_LoadPNG: IEND chunk not found (%s)\n", name ); Con_DPrintf( S_ERROR "Image_LoadPNG: IEND chunk not found (%s)\n", name );
@@ -227,7 +203,7 @@ qboolean Image_LoadPNG( const char *name, const byte *buffer, fs_offset_t filesi
if( chunk_len != 0 ) if( chunk_len != 0 )
{ {
Con_DPrintf( S_ERROR "Image_LoadPNG: IEND chunk has wrong size %u (%s)\n", chunk_len, name ); Con_DPrintf( S_ERROR "Image_LoadPNG: IEND chunk has wrong size (%s)\n", name );
Mem_Free( idat_buf ); Mem_Free( idat_buf );
return false; return false;
} }
@@ -240,13 +216,6 @@ qboolean Image_LoadPNG( const char *name, const byte *buffer, fs_offset_t filesi
switch( png_hdr.ihdr_chunk.colortype ) switch( png_hdr.ihdr_chunk.colortype )
{ {
case PNG_CT_GREY:
case PNG_CT_PALLETE:
pixel_size = 1;
break;
case PNG_CT_ALPHA:
pixel_size = 2;
break;
case PNG_CT_RGB: case PNG_CT_RGB:
pixel_size = 3; pixel_size = 3;
break; break;
@@ -259,22 +228,29 @@ qboolean Image_LoadPNG( const char *name, const byte *buffer, fs_offset_t filesi
break; break;
} }
image.type = PF_RGBA_32; // always exctracted to 32-bit buffer if( png_hdr.ihdr_chunk.bitdepth == 8 )
{
image.type = PF_RGBA_32; // always exctracted to 32-bit buffer
channel_size = 1;
}
else // if( png_hdr.ihdr_chunk.bitdepth == 16 )
{
image.type = PF_RGBA_64;
channel_size = 2;
}
image.width = png_hdr.ihdr_chunk.width; image.width = png_hdr.ihdr_chunk.width;
image.height = png_hdr.ihdr_chunk.height; image.height = png_hdr.ihdr_chunk.height;
image.size = image.height * image.width * 4; image.size = image.height * image.width * channel_size * 4;
image.flags |= IMAGE_HAS_COLOR;
if( png_hdr.ihdr_chunk.colortype & PNG_CT_RGB ) if( png_hdr.ihdr_chunk.colortype == PNG_CT_RGBA )
image.flags |= IMAGE_HAS_COLOR;
if( trns || ( png_hdr.ihdr_chunk.colortype & PNG_CT_ALPHA ) )
image.flags |= IMAGE_HAS_ALPHA; image.flags |= IMAGE_HAS_ALPHA;
image.depth = 1; image.depth = 1;
rowsize = pixel_size * image.width; rowsize = pixel_size * image.width;
uncompressed_size = image.height * ( rowsize + 1 ); // +1 for filter uncompressed_size = image.height * ( rowsize * channel_size + 1 ); // +1 for filter
uncompressed_buffer = Mem_Malloc( host.imagepool, uncompressed_size ); uncompressed_buffer = Mem_Malloc( host.imagepool, uncompressed_size );
stream.next_in = idat_buf; stream.next_in = idat_buf;
@@ -309,9 +285,12 @@ qboolean Image_LoadPNG( const char *name, const byte *buffer, fs_offset_t filesi
raw = uncompressed_buffer; raw = uncompressed_buffer;
if( png_hdr.ihdr_chunk.colortype != PNG_CT_RGBA ) if( png_hdr.ihdr_chunk.colortype == PNG_CT_RGB )
prior = pixbuf = raw; prior = pixbuf = raw;
rowsize *= channel_size;
pixel_size *= channel_size;
filter_type = *raw++; filter_type = *raw++;
// decode adaptive filter // decode adaptive filter
@@ -411,91 +390,44 @@ qboolean Image_LoadPNG( const char *name, const byte *buffer, fs_offset_t filesi
prior = pixbuf; prior = pixbuf;
} }
pixbuf = image.rgba; // convert RGB-to-RGBA
raw = uncompressed_buffer; if( png_hdr.ihdr_chunk.colortype == PNG_CT_RGB )
switch( png_hdr.ihdr_chunk.colortype )
{ {
case PNG_CT_RGB: pixbuf = image.rgba;
if( trns ) raw = uncompressed_buffer;
{
r_alpha = trns[0] << 8 | trns[1];
g_alpha = trns[2] << 8 | trns[3];
b_alpha = trns[4] << 8 | trns[5];
}
for( y = 0; y < image.height; y++ ) for( y = 0; y < image.height * image.width; y++, raw += pixel_size )
{ {
rowend = raw + rowsize; *pixbuf++ = raw[0];
for( ; raw < rowend; raw += pixel_size ) *pixbuf++ = raw[1];
*pixbuf++ = raw[2];
if( channel_size == 1 )
{ {
*pixbuf++ = raw[0]; *pixbuf++ = 0xFF;
*pixbuf++ = raw[1]; }
*pixbuf++ = raw[2]; else
{
if( trns && r_alpha == raw[0] *pixbuf++ = raw[3];
&& g_alpha == raw[1] *pixbuf++ = raw[4];
&& b_alpha == raw[2] ) *pixbuf++ = raw[5];
*pixbuf++ = 0; *pixbuf++ = 0xFF;
else *pixbuf++ = 0xFF;
*pixbuf++ = 0xFF;
} }
} }
break;
case PNG_CT_GREY:
if( trns )
r_alpha = trns[0] << 8 | trns[1];
for( y = 0; y < image.height; y++ )
{
rowend = raw + rowsize;
for( ; raw < rowend; raw += pixel_size )
{
*pixbuf++ = raw[0];
*pixbuf++ = raw[0];
*pixbuf++ = raw[0];
if( trns && r_alpha == raw[0] )
*pixbuf++ = 0;
else
*pixbuf++ = 0xFF;
}
}
break;
case PNG_CT_ALPHA:
for( y = 0; y < image.height; y++ )
{
rowend = raw + rowsize;
for( ; raw < rowend; raw += pixel_size )
{
*pixbuf++ = raw[0];
*pixbuf++ = raw[0];
*pixbuf++ = raw[0];
*pixbuf++ = raw[1];
}
}
break;
case PNG_CT_PALLETE:
for( y = 0; y < image.height; y++ )
{
rowend = raw + rowsize;
for( ; raw < rowend; raw += pixel_size )
{
*pixbuf++ = pallete[raw[0] + 2];
*pixbuf++ = pallete[raw[0] + 1];
*pixbuf++ = pallete[raw[0] + 0];
if( trns && raw[0] < trns_len )
*pixbuf++ = trns[raw[0]];
else
*pixbuf++ = 0xFF;
}
}
break;
default:
break;
} }
#if XASH_LITTLE_ENDIAN
if( channel_size == 2 )
{
pixbuf = image.rgba;
for( y = 0; y < image.height * image.width * 4; y++, pixbuf += 2 )
{
uint16_t val = *(uint16_t*)pixbuf;
*(uint16_t*)pixbuf = ntohs( val );
}
}
#endif /* XASH_LITTLE_ENDIAN */
Mem_Free( uncompressed_buffer ); Mem_Free( uncompressed_buffer );
return true; return true;

View File

@@ -25,8 +25,8 @@ GNU General Public License for more details.
enum png_colortype enum png_colortype
{ {
PNG_CT_GREY, PNG_CT_GREY,
PNG_CT_PALLETE = BIT(0),
PNG_CT_RGB = BIT(1), PNG_CT_RGB = BIT(1),
PNG_CT_PALLETE = (PNG_CT_RGB|BIT(0)),
PNG_CT_ALPHA = BIT(2), PNG_CT_ALPHA = BIT(2),
PNG_CT_RGBA = (PNG_CT_RGB|PNG_CT_ALPHA) PNG_CT_RGBA = (PNG_CT_RGB|PNG_CT_ALPHA)
}; };

View File

@@ -80,6 +80,15 @@ static byte palette_hl[768] =
147,255,247,199,255,255,255,159,91,83 147,255,247,199,255,255,255,159,91,83
}; };
static float img_emboss[FILTER_SIZE][FILTER_SIZE] =
{
{-0.7f, -0.7f, -0.7f, -0.7f, 0.0f },
{-0.7f, -0.7f, -0.7f, 0.0f, 0.7f },
{-0.7f, -0.7f, 0.0f, 0.7f, 0.7f },
{-0.7f, 0.0f, 0.7f, 0.7f, 0.7f },
{ 0.0f, 0.7f, 0.7f, 0.7f, 0.7f },
};
/* /*
============================================================================= =============================================================================
@@ -96,8 +105,8 @@ static const loadpixformat_t load_null[] =
static const loadpixformat_t load_game[] = static const loadpixformat_t load_game[] =
{ {
{ "%s%s.%s", "dds", Image_LoadDDS, IL_HINT_NO }, // dds for world and studio models { "%s%s.%s", "dds", Image_LoadDDS, IL_HINT_NO }, // dds for world and studio models
{ "%s%s.%s", "bmp", Image_LoadBMP, IL_HINT_NO }, // WON menu images
{ "%s%s.%s", "tga", Image_LoadTGA, IL_HINT_NO }, // hl vgui menus { "%s%s.%s", "tga", Image_LoadTGA, IL_HINT_NO }, // hl vgui menus
{ "%s%s.%s", "bmp", Image_LoadBMP, IL_HINT_NO }, // WON menu images
{ "%s%s.%s", "png", Image_LoadPNG, IL_HINT_NO }, // NightFire 007 menus { "%s%s.%s", "png", Image_LoadPNG, IL_HINT_NO }, // NightFire 007 menus
{ "%s%s.%s", "mip", Image_LoadMIP, IL_HINT_NO }, // hl textures from wad or buffer { "%s%s.%s", "mip", Image_LoadMIP, IL_HINT_NO }, // hl textures from wad or buffer
{ "%s%s.%s", "mdl", Image_LoadMDL, IL_HINT_HL }, // hl studio model skins { "%s%s.%s", "mdl", Image_LoadMDL, IL_HINT_HL }, // hl studio model skins
@@ -456,8 +465,8 @@ void Image_PaletteHueReplace( byte *palSrc, int newHue, int start, int end, int
g = palSrc[i*pal_size+1]; g = palSrc[i*pal_size+1];
b = palSrc[i*pal_size+2]; b = palSrc[i*pal_size+2];
maxcol = Q_max( Q_max( r, g ), b ) / 255.0f; maxcol = max( max( r, g ), b ) / 255.0f;
mincol = Q_min( Q_min( r, g ), b ) / 255.0f; mincol = min( min( r, g ), b ) / 255.0f;
if( maxcol == 0 ) continue; if( maxcol == 0 ) continue;
@@ -1359,7 +1368,107 @@ qboolean Image_RemapInternal( rgbdata_t *pic, int topColor, int bottomColor )
return true; return true;
} }
qboolean Image_Process(rgbdata_t **pix, int width, int height, uint flags, float reserved ) /*
==================
Image_ApplyFilter
Applies a 5 x 5 filtering matrix to the texture, then runs it through a simulated OpenGL texture environment
blend with the original data to derive a new texture. Freaky, funky, and *f--king* *fantastic*. You can do
reasonable enough "fake bumpmapping" with this baby...
Filtering algorithm from http://www.student.kuleuven.ac.be/~m0216922/CG/filtering.html
All credit due
==================
*/
static void Image_ApplyFilter( rgbdata_t *pic, float factor )
{
int i, x, y;
uint *fin, *fout;
size_t size;
// don't waste time
if( factor <= 0.0f ) return;
// first expand the image into 32-bit buffer
pic = Image_DecompressInternal( pic );
factor = bound( 0.0f, factor, 1.0f );
size = image.width * image.height * 4;
image.tempbuffer = Mem_Realloc( host.imagepool, image.tempbuffer, size );
fout = (uint *)image.tempbuffer;
fin = (uint *)pic->buffer;
for( x = 0; x < image.width; x++ )
{
for( y = 0; y < image.height; y++ )
{
vec3_t vout = { 0.0f, 0.0f, 0.0f };
int pos_x, pos_y;
float avg;
for( pos_x = 0; pos_x < FILTER_SIZE; pos_x++ )
{
for( pos_y = 0; pos_y < FILTER_SIZE; pos_y++ )
{
int img_x = (x - (FILTER_SIZE / 2) + pos_x + image.width) % image.width;
int img_y = (y - (FILTER_SIZE / 2) + pos_y + image.height) % image.height;
// casting's a unary operation anyway, so the othermost set of brackets in the left part
// of the rvalue should not be necessary... but i'm paranoid when it comes to C...
vout[0] += ((float)((byte *)&fin[img_y * image.width + img_x])[0]) * img_emboss[pos_x][pos_y];
vout[1] += ((float)((byte *)&fin[img_y * image.width + img_x])[1]) * img_emboss[pos_x][pos_y];
vout[2] += ((float)((byte *)&fin[img_y * image.width + img_x])[2]) * img_emboss[pos_x][pos_y];
}
}
// multiply by factor, add bias, and clamp
for( i = 0; i < 3; i++ )
{
vout[i] *= factor;
vout[i] += 128.0f; // base
vout[i] = bound( 0.0f, vout[i], 255.0f );
}
// NTSC greyscale conversion standard
avg = (vout[0] * 30.0f + vout[1] * 59.0f + vout[2] * 11.0f) / 100.0f;
// divide by 255 so GL operations work as expected
vout[0] = avg / 255.0f;
vout[1] = avg / 255.0f;
vout[2] = avg / 255.0f;
// write to temp - first, write data in (to get the alpha channel quickly and
// easily, which will be left well alone by this particular operation...!)
fout[y * image.width + x] = fin[y * image.width + x];
// now write in each element, applying the blend operator. blend
// operators are based on standard OpenGL TexEnv modes, and the
// formulas are derived from the OpenGL specs (http://www.opengl.org).
for( i = 0; i < 3; i++ )
{
// divide by 255 so GL operations work as expected
float src = ((float)((byte *)&fin[y * image.width + x])[i]) / 255.0f;
float tmp;
// default is GL_BLEND here
// CsS + CdD works out as Src * Dst * 2
tmp = vout[i] * src * 2.0f;
// multiply back by 255 to get the proper byte scale
tmp *= 255.0f;
// bound the temp target again now, cos the operation may have thrown it out
tmp = bound( 0.0f, tmp, 255.0f );
// and copy it in
((byte *)&fout[y * image.width + x])[i] = (byte)tmp;
}
}
}
// copy result back
memcpy( fin, fout, size );
}
qboolean Image_Process( rgbdata_t **pix, int width, int height, uint flags, float bumpscale )
{ {
rgbdata_t *pic = *pix; rgbdata_t *pic = *pix;
qboolean result = true; qboolean result = true;
@@ -1400,6 +1509,9 @@ qboolean Image_Process(rgbdata_t **pix, int width, int height, uint flags, float
if( FBitSet( flags, IMAGE_LIGHTGAMMA )) if( FBitSet( flags, IMAGE_LIGHTGAMMA ))
pic = Image_LightGamma( pic ); pic = Image_LightGamma( pic );
if( FBitSet( flags, IMAGE_EMBOSS ))
Image_ApplyFilter( pic, bumpscale );
out = Image_FlipInternal( pic->buffer, &pic->width, &pic->height, pic->type, flags ); out = Image_FlipInternal( pic->buffer, &pic->width, &pic->height, pic->type, flags );
if( pic->buffer != out ) memcpy( pic->buffer, image.tempbuffer, pic->size ); if( pic->buffer != out ) memcpy( pic->buffer, image.tempbuffer, pic->size );

View File

@@ -15,6 +15,8 @@ GNU General Public License for more details.
#ifdef SINGLE_BINARY #ifdef SINGLE_BINARY
#include <stdlib.h>
#include <string.h>
#include "build.h" #include "build.h"
#include "common.h" #include "common.h"
#ifdef XASH_SDLMAIN #ifdef XASH_SDLMAIN
@@ -23,42 +25,66 @@ GNU General Public License for more details.
#if XASH_EMSCRIPTEN #if XASH_EMSCRIPTEN
#include <emscripten.h> #include <emscripten.h>
#elif XASH_WIN32
extern "C"
{
// Enable NVIDIA High Performance Graphics while using Integrated Graphics.
__declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001;
// Enable AMD High Performance Graphics while using Integrated Graphics.
__declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 1;
}
#endif #endif
#define E_GAME "XASH3D_GAME" // default env dir to start from #if XASH_WIN32
#define GAME_PATH "valve" // default dir to start from #define XASH_NOCONHOST 1
#endif
static char szGameDir[128]; // safe place to keep gamedir static char szGameDir[128]; // safe place to keep gamedir
static int szArgc; static int g_iArgc;
static char **szArgv; static char **g_pszArgv;
static void Sys_ChangeGame( const char *progname ) void Launcher_ChangeGame( const char *progname )
{ {
// a1ba: may never be called within engine strncpy( szGameDir, progname, sizeof( szGameDir ) - 1 );
// if platform supports execv() function
Q_strncpy( szGameDir, progname, sizeof( szGameDir ) - 1 );
Host_Shutdown( ); Host_Shutdown( );
exit( Host_Main( szArgc, szArgv, szGameDir, 1, &Sys_ChangeGame ) ); exit( Host_Main( g_iArgc, g_pszArgv, szGameDir, 1, &Launcher_ChangeGame ) );
} }
_inline int Sys_Start( void ) #if XASH_NOCONHOST
#include <windows.h>
#include <shellapi.h> // CommandLineToArgvW
int __stdcall WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR cmdLine, int nShow)
{ {
int ret; int szArgc;
const char *game = getenv( E_GAME ); char **szArgv;
LPWSTR* lpArgv = CommandLineToArgvW(GetCommandLineW(), &szArgc);
int i = 0;
if( !game ) szArgv = (char**)malloc(szArgc*sizeof(char*));
game = GAME_PATH; for (; i < szArgc; ++i)
{
size_t size = wcslen(lpArgv[i]) + 1;
szArgv[i] = (char*)malloc(size);
wcstombs(szArgv[i], lpArgv[i], size);
}
szArgv[i] = NULL;
LocalFree(lpArgv);
main( szArgc, szArgv );
for( i = 0; i < szArgc; ++i )
free( szArgv[i] );
free( szArgv );
}
#endif
int main( int argc, char** argv )
{
char gamedir_buf[32] = "";
const char *gamedir = getenv( "XASH3D_GAMEDIR" );
if( !COM_CheckString( gamedir ) )
{
gamedir = "valve";
}
else
{
strncpy( gamedir_buf, gamedir, 32 );
gamedir = gamedir_buf;
}
Q_strncpy( szGameDir, game, sizeof( szGameDir ));
#if XASH_EMSCRIPTEN #if XASH_EMSCRIPTEN
#ifdef EMSCRIPTEN_LIB_FS #ifdef EMSCRIPTEN_LIB_FS
// For some unknown reason emscripten refusing to load libraries later // For some unknown reason emscripten refusing to load libraries later
@@ -74,56 +100,17 @@ _inline int Sys_Start( void )
FS.chdir('/xash'); FS.chdir('/xash');
}catch(e){};); }catch(e){};);
#endif #endif
#elif XASH_IOS #endif
g_iArgc = argc;
g_pszArgv = argv;
#if XASH_IOS
{ {
void IOS_LaunchDialog( void ); void IOS_LaunchDialog( void );
IOS_LaunchDialog(); IOS_LaunchDialog();
} }
#endif #endif
return Host_Main( g_iArgc, g_pszArgv, gamedir, 0, &Launcher_ChangeGame );
ret = Host_Main( szArgc, szArgv, game, 0, Sys_ChangeGame );
return ret;
} }
#if !XASH_WIN32
int main( int argc, char **argv )
{
szArgc = argc;
szArgv = argv;
return Sys_Start();
}
#else
int __stdcall WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR cmdLine, int nShow)
{
LPWSTR* lpArgv;
int ret, i;
lpArgv = CommandLineToArgvW( GetCommandLineW(), &szArgc );
szArgv = ( char** )malloc( (szArgc + 1) * sizeof( char* ));
for( i = 0; i < szArgc; ++i )
{
size_t size = wcslen(lpArgv[i]) + 1;
// just in case, allocate some more memory
szArgv[i] = ( char * )malloc( size * sizeof( wchar_t ));
wcstombs( szArgv[i], lpArgv[i], size );
}
szArgv[szArgc] = 0;
LocalFree( lpArgv );
ret = Sys_Start();
for( ; i < szArgc; ++i )
free( szArgv[i] );
free( szArgv );
return ret;
}
#endif // XASH_WIN32
#endif #endif

View File

@@ -86,38 +86,6 @@ const char *COM_OffsetNameForFunction( void *function )
return sname; return sname;
} }
dll_user_t *FS_FindLibrary( const char *dllname, qboolean directpath )
{
dll_user_t *p;
fs_dllinfo_t dllInfo;
// no fs loaded yet, but let engine find fs
if( !g_fsapi.FindLibrary )
{
p = Mem_Calloc( host.mempool, sizeof( dll_user_t ));
Q_strncpy( p->shortPath, dllname, sizeof( p->shortPath ));
Q_strncpy( p->fullPath, dllname, sizeof( p->fullPath ));
Q_strncpy( p->dllName, dllname, sizeof( p->dllName ));
return p;
}
// fs can't find library
if( !g_fsapi.FindLibrary( dllname, directpath, &dllInfo ))
return NULL;
// NOTE: for libraries we not fail even if search is NULL
// let the OS find library himself
p = Mem_Calloc( host.mempool, sizeof( dll_user_t ));
Q_strncpy( p->shortPath, dllInfo.shortPath, sizeof( p->shortPath ));
Q_strncpy( p->fullPath, dllInfo.fullPath, sizeof( p->fullPath ));
Q_strncpy( p->dllName, dllname, sizeof( p->dllName ));
p->custom_loader = dllInfo.custom_loader;
p->encrypted = dllInfo.encrypted;
return p;
}
/* /*
============================================================================= =============================================================================
@@ -323,12 +291,12 @@ static char *COM_GetItaniumName( const char * const in_name )
len = len * 10 + ( *f - '0' ); len = len * 10 + ( *f - '0' );
// sane value // sane value
len = Q_min( remaining, len ); len = min( remaining, len );
if( len == 0 ) if( len == 0 )
goto invalid_format; goto invalid_format;
Q_strncpy( symbols[i], f, Q_min( len + 1, sizeof( out_name ))); Q_strncpy( symbols[i], f, min( len + 1, sizeof( out_name )));
f += len; f += len;
remaining -= len; remaining -= len;
@@ -393,7 +361,7 @@ char **COM_ConvertToLocalPlatform( EFunctionMangleType to, const char *from, siz
if( at ) len = (uint)( at - prev ); if( at ) len = (uint)( at - prev );
else len = (uint)Q_strlen( prev ); else len = (uint)Q_strlen( prev );
Q_strncpy( symbols[i], prev, Q_min( len + 1, sizeof( symbols[i] ))); Q_strncpy( symbols[i], prev, min( len + 1, sizeof( symbols[i] )));
prev = at + 1; prev = at + 1;
if( !at ) if( !at )

View File

@@ -21,7 +21,6 @@ typedef struct master_s
qboolean sent; qboolean sent;
qboolean save; qboolean save;
string address; string address;
netadr_t adr; // temporary, rewritten after each send
} master_t; } master_t;
struct masterlist_s struct masterlist_s
@@ -45,32 +44,31 @@ qboolean NET_SendToMasters( netsrc_t sock, size_t len, const void *data )
for( list = ml.list; list; list = list->next ) for( list = ml.list; list; list = list->next )
{ {
netadr_t adr;
int res; int res;
if( list->sent ) if( list->sent )
continue; continue;
res = NET_StringToAdrNB( list->address, &list->adr ); res = NET_StringToAdrNB( list->address, &adr );
if( !res ) if( !res )
{ {
Con_Reportf( "Can't resolve adr: %s\n", list->address ); Con_Reportf( "Can't resolve adr: %s\n", list->address );
list->sent = true; list->sent = true;
list->adr.type = NA_UNUSED;
continue; continue;
} }
if( res == 2 ) if( res == 2 )
{ {
list->sent = false; list->sent = false;
list->adr.type = NA_UNUSED;
wait = true; wait = true;
continue; continue;
} }
list->sent = true; list->sent = true;
NET_SendPacket( sock, len, data, list->adr ); NET_SendPacket( sock, len, data, adr );
} }
if( !wait ) if( !wait )
@@ -87,25 +85,6 @@ qboolean NET_SendToMasters( netsrc_t sock, size_t len, const void *data )
return wait; return wait;
} }
/*
========================
NET_IsMasterAdr
========================
*/
qboolean NET_IsMasterAdr( netadr_t adr )
{
master_t *master;
for( master = ml.list; master; master = master->next )
{
if( NET_CompareAdr( adr, master->adr ))
return true;
}
return false;
}
/* /*
======================== ========================
NET_AddMaster NET_AddMaster
@@ -128,7 +107,6 @@ static void NET_AddMaster( const char *addr, qboolean save )
master->sent = false; master->sent = false;
master->save = save; master->save = save;
master->next = NULL; master->next = NULL;
master->adr.type = NA_UNUSED;
// link in // link in
if( last ) if( last )
@@ -183,10 +161,7 @@ static void NET_ListMasters_f( void )
for( i = 1, list = ml.list; list; i++, list = list->next ) for( i = 1, list = ml.list; list; i++, list = list->next )
{ {
Msg( "%d\t%s", i, list->address ); Msg( "%d\t%s\n", i, list->address );
if( list->adr.type != NA_UNUSED )
Msg( "\t%s\n", NET_AdrToString( list->adr ));
else Msg( "\n" );
} }
} }
@@ -279,5 +254,6 @@ void NET_InitMasters( void )
// keep main master always there // keep main master always there
NET_AddMaster( MASTERSERVER_ADR, false ); NET_AddMaster( MASTERSERVER_ADR, false );
NET_AddMaster( MASTERSERVER_ADR2, false );
NET_LoadMasters( ); NET_LoadMasters( );
} }

View File

@@ -1020,8 +1020,6 @@ Fills in surf->texturemins[] and surf->extents[]
*/ */
static void Mod_CalcSurfaceExtents( msurface_t *surf ) static void Mod_CalcSurfaceExtents( msurface_t *surf )
{ {
// this place is VERY critical to precision
// keep it as float, don't use double, because it causes issues with lightmap
float mins[2], maxs[2], val; float mins[2], maxs[2], val;
float lmmins[2], lmmaxs[2]; float lmmins[2], lmmaxs[2];
int bmins[2], bmaxs[2]; int bmins[2], bmaxs[2];
@@ -1051,14 +1049,14 @@ static void Mod_CalcSurfaceExtents( msurface_t *surf )
for( j = 0; j < 2; j++ ) for( j = 0; j < 2; j++ )
{ {
val = DotProductPrecise( v->position, surf->texinfo->vecs[j] ) + surf->texinfo->vecs[j][3]; val = DotProduct( v->position, surf->texinfo->vecs[j] ) + surf->texinfo->vecs[j][3];
mins[j] = Q_min( val, mins[j] ); mins[j] = Q_min( val, mins[j] );
maxs[j] = Q_max( val, maxs[j] ); maxs[j] = Q_max( val, maxs[j] );
} }
for( j = 0; j < 2; j++ ) for( j = 0; j < 2; j++ )
{ {
val = DotProductPrecise( v->position, info->lmvecs[j] ) + info->lmvecs[j][3]; val = DotProduct( v->position, info->lmvecs[j] ) + info->lmvecs[j][3];
lmmins[j] = Q_min( val, lmmins[j] ); lmmins[j] = Q_min( val, lmmins[j] );
lmmaxs[j] = Q_max( val, lmmaxs[j] ); lmmaxs[j] = Q_max( val, lmmaxs[j] );
} }
@@ -2025,7 +2023,7 @@ static void Mod_LoadTextures( dbspmodel_t *bmod )
if( FS_FileExists( texpath, false )) if( FS_FileExists( texpath, false ))
{ {
tx->gl_texturenum = ref.dllFuncs.GL_LoadTexture( texpath, NULL, 0, txFlags ); tx->gl_texturenum = ref.dllFuncs.GL_LoadTexture( texpath, NULL, 0, TF_ALLOW_EMBOSS|txFlags );
bmod->wadlist.wadusage[j]++; // this wad are really used bmod->wadlist.wadusage[j]++; // this wad are really used
break; break;
} }
@@ -2041,7 +2039,7 @@ static void Mod_LoadTextures( dbspmodel_t *bmod )
if( custom_palette ) size += sizeof( short ) + 768; if( custom_palette ) size += sizeof( short ) + 768;
Q_snprintf( texname, sizeof( texname ), "#%s:%s.mip", loadstat.name, mt->name ); Q_snprintf( texname, sizeof( texname ), "#%s:%s.mip", loadstat.name, mt->name );
tx->gl_texturenum = ref.dllFuncs.GL_LoadTexture( texname, (byte *)mt, size, txFlags ); tx->gl_texturenum = ref.dllFuncs.GL_LoadTexture( texname, (byte *)mt, size, TF_ALLOW_EMBOSS|txFlags );
} }
// if texture is completely missed // if texture is completely missed
@@ -2736,37 +2734,6 @@ static void Mod_LoadLighting( dbspmodel_t *bmod )
} }
} }
/*
=================
Mod_LumpLooksLikePlanes
=================
*/
static qboolean Mod_LumpLooksLikePlanes( const byte *in, dlump_t *lump, qboolean fast )
{
int numplanes, i;
const dplane_t *planes;
if( lump->filelen < sizeof( dplane_t ) &&
lump->filelen % sizeof( dplane_t ) != 0 )
return false;
if( fast )
return true;
numplanes = lump->filelen / sizeof( dplane_t );
planes = (const dplane_t*)(in + lump->fileofs);
for( i = 0; i < numplanes; i++ )
{
// planes can only be from 0 to 5: PLANE_X, Y, Z and PLANE_ANYX, Y and Z
if( planes[i].type < 0 || planes[i].type > 5 )
return false;
}
return true;
}
/* /*
================= =================
Mod_LoadBmodelLumps Mod_LoadBmodelLumps
@@ -2813,28 +2780,13 @@ qboolean Mod_LoadBmodelLumps( const byte *mod_base, qboolean isworld )
if( isworld ) world.flags = 0; // clear world settings if( isworld ) world.flags = 0; // clear world settings
bmod->isworld = isworld; bmod->isworld = isworld;
if( header->version == HLBSP_VERSION ) if( header->version == HLBSP_VERSION &&
header->lumps[LUMP_ENTITIES].fileofs <= 1024 &&
(header->lumps[LUMP_ENTITIES].filelen % sizeof( dplane_t )) == 0 )
{ {
// only relevant for half-life maps // blue-shift swapped lumps
if( !Mod_LumpLooksLikePlanes( mod_base, &header->lumps[LUMP_PLANES], false ) && srclumps[0].lumpnumber = LUMP_PLANES;
Mod_LumpLooksLikePlanes( mod_base, &header->lumps[LUMP_ENTITIES], false )) srclumps[1].lumpnumber = LUMP_ENTITIES;
{
// blue-shift swapped lumps
srclumps[0].lumpnumber = LUMP_PLANES;
srclumps[1].lumpnumber = LUMP_ENTITIES;
}
else
{
// everything else
srclumps[0].lumpnumber = LUMP_ENTITIES;
srclumps[1].lumpnumber = LUMP_PLANES;
}
}
else
{
// everything else
srclumps[0].lumpnumber = LUMP_ENTITIES;
srclumps[1].lumpnumber = LUMP_PLANES;
} }
// loading base lumps // loading base lumps
@@ -2941,28 +2893,13 @@ qboolean Mod_TestBmodelLumps( const char *name, const byte *mod_base, qboolean s
break; break;
} }
if( header->version == HLBSP_VERSION ) if( header->version == HLBSP_VERSION &&
header->lumps[LUMP_ENTITIES].fileofs <= 1024 &&
(header->lumps[LUMP_ENTITIES].filelen % sizeof( dplane_t )) == 0 )
{ {
// only relevant for half-life maps // blue-shift swapped lumps
if( Mod_LumpLooksLikePlanes( mod_base, &header->lumps[LUMP_ENTITIES], true ) && srclumps[0].lumpnumber = LUMP_PLANES;
!Mod_LumpLooksLikePlanes( mod_base, &header->lumps[LUMP_PLANES], true )) srclumps[1].lumpnumber = LUMP_ENTITIES;
{
// blue-shift swapped lumps
srclumps[0].lumpnumber = LUMP_PLANES;
srclumps[1].lumpnumber = LUMP_ENTITIES;
}
else
{
// everything else
srclumps[0].lumpnumber = LUMP_ENTITIES;
srclumps[1].lumpnumber = LUMP_PLANES;
}
}
else
{
// everything else
srclumps[0].lumpnumber = LUMP_ENTITIES;
srclumps[1].lumpnumber = LUMP_PLANES;
} }
// loading base lumps // loading base lumps

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