centerprints with links now show cursors.

q2 temp entity tweaks. still more work to be done.
support sRGB (mostly)properly in gl+vk+d3d9+d3d11.
vulkan tweaks - multisample works under certain conditions. additional other changes to comply... cvars to enable some other device extensions.
removed r_viewleaf. now using clusters for q1 too.
improved compat with quakespasm's sky command.
Added vid_winthread cvar, to handle window messages on a separate thread. When set this allows the game to keep redrawing when the user is resizing the window etc.
Finally added renderers option to menusys.

git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5130 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2017-07-28 01:49:25 +00:00
parent d66db9930d
commit db2c378fa0
67 changed files with 6083 additions and 2281 deletions

View File

@ -1,417 +1,417 @@
#!/bin/bash
#sets up dependancies for debian-jessie (8.7)
#this script must be run twice. first time as root, which installs system packages
#second time as a regular user (probably not your normal one), which installs 3rd-party stuff
SVNROOT=$(cd "$(dirname "$BASH_SOURCE")" && pwd)
FTEROOT=$(realpath $SVNROOT/..)
FTEROOT=${FTEROOT:-~}
FTECONFIG=$SVNROOT/build.cfg
BUILDFOLDER=`echo ~`/htdocs
BUILDLOGFOLDER=$BUILDFOLDER/build_logs
#mac defaults
OSXCROSSROOT=$FTEROOT/osxcross
#emscripten defaults
EMSCRIPTENROOT=$FTEROOT/emsdk-portable
#nacl defaults
NACLROOT=$FTEROOT/nacl_sdk
NACLSDKVERSION=pepper_49
#android defaults
ANDROIDROOT=$FTEROOT/android
if [ ! -z "$(uname -o 2>&1 | grep Cygwin)" ]; then
ANDROID_HOSTSYSTEM=windows-x86_64
else
ANDROID_HOSTSYSTEM=linux-$(uname -m)
fi
ANDROIDBUILDTOOLS=25.0.0
ANDROID_ZIPALIGN=$ANDROIDROOT/build-tools/$ANDROIDBUILDTOOLS/zipalign #relative to ndk tools
THREADS="-j 4"
#windows is always cross compiled, so we don't have issues with non-native ffmpeg
PLUGINS_LINUXx86="ode qi ezhud xmpp irc"
PLUGINS_LINUXx64="ode qi ezhud xmpp irc"
PLUGINS_LINUXx32="qi ezhud xmpp irc"
PLUGINS_LINUXarmhf="qi ezhud xmpp irc"
if [ "$(uname -m)" != "x86_64" ]; then
PLUGINS_LINUXx86="ffmpeg ode qi ezhud xmpp irc"
fi
if [ "$(uname -m)" == "x86_64" ]; then
PLUGINS_LINUX64="ffmpeg ode qi ezhud xmpp irc"
fi
#windows doesn't cross compile, so no system dependancy issues
#skip some dependancies if we're running on cygwin, ode is buggy.
if [ "$(uname -s)" == "Linux" ]; then
PLUGINS_WINDOWS="ffmpeg ode qi ezhud xmpp irc"
else
PLUGINS_WINDOWS="qi ezhud xmpp irc"
fi
echo
echo "This is Spike's script to set up various cross compilers and dependancies."
echo "This script will check dependancies. If something isn't installed you can either rerun the script as root (which will ONLY install system packages), or manually apt-get or whatever. You can then re-run the script as a regular user to finish configuring 3rd party dependancies."
echo
echo "You can change your choices later by just re-running this script"
echo "(Your settings will be autosaved in $FTECONFIG)"
echo
echo "If you just want to compile a native build, just use the following command:"
echo "cd $SVNROOT/engine && make gl-rel"
echo "(if you're in cygwin, add FTE_TARGET=win32 to compile for native windows)"
echo "(add plugins-rel qcc-rel qccgui-rel sv-rel vk-rel etc for additional targets)"
echo "(or use -dbg if you want debug builds for whatever reason)"
echo
#always execute it if it exists, so that we preserve custom paths etc that are not prompted for here
if [ -e $FTECONFIG ]; then
. $FTECONFIG
if [ $UID -eq 0 ]; then
REUSE_CONFIG=y #root shouldn't be writing/owning the config file.
else
read -n 1 -p "Reuse previous build config? [y/N] " REUSE_CONFIG && echo
REUSE_CONFIG=${REUSE_CONFIG:-n}
fi
else
if [ $UID -eq 0 ]; then
exit #root can't create the output, as that would take ownership.
else
REUSE_CONFIG=n
fi
fi
if [ "$REUSE_CONFIG" != "y" ]; then
#linux compiles are native-only, so don't bug out on cygwin which lacks a cross compiler.
BUILD_LINUXx86=n
BUILD_LINUXx64=n
BUILD_LINUXx32=n
BUILD_LINUXarmhf=n
if [ "$(uname -s)" == "Linux" ]; then
read -n 1 -p "Build for Linux x86? [Y/n] " BUILD_LINUXx86 && echo
read -n 1 -p "Build for Linux x86_64? [Y/n] " BUILD_LINUXx64 && echo
read -n 1 -p "Build for Linux x32? [y/N] " BUILD_LINUXx32 && echo
#ubuntu's gcc-multilib-arm-foo package conflicts with gcc-multilib...
#the whole point of multilib was to avoid conflicts... someone fucked up.
#read -n 1 -p "Build for Linux armhf [y/N] " BUILD_LINUXarmhf && echo
else
echo "Skipping Linux options."
fi
BUILD_CYGWIN=n
BUILD_MSVC=n
if [ "$(uname -o)" == "Cygwin" ]; then
read -n 1 -p "Build for Cygwin? [y/N] " BUILD_CYGWIN && echo
read -n 1 -p "Build with MSVC? (requires windows7 sdk) [y/N] " BUILD_MSVC && echo
else
echo "Skipping Cygwin options."
fi
read -n 1 -p "Build for Windows? [Y/n] " BUILD_WINDOWS && echo
read -n 1 -p "Build for Dos? [y/N] " BUILD_WINDOWS && echo
read -n 1 -p "Build for SDL? [y/N] " BUILD_SDL && echo
read -n 1 -p "Build for Android? [y/N] " BUILD_ANDROID && echo
read -n 1 -p "Build for Emscripten? [y/N] " BUILD_WEB && echo
if [ 0 -ne 0 ]; then
read -n 1 -p "Build for MacOSX? [y/N] " BUILD_MAC && echo
else
echo "Skipping mac option."
fi
read -n 1 -p "Build for NaCL? [y/N] " BUILD_NACL && echo
fi
BUILD_LINUXx86=${BUILD_LINUXx86:-y}
BUILD_LINUXx64=${BUILD_LINUXx64:-y}
BUILD_LINUXx32=${BUILD_LINUXx32:-n}
BUILD_LINUXarmhf=${BUILD_LINUXarmhf:-n}
BUILD_CYGWIN=${BUILD_CYGWIN:-n}
BUILD_WINDOWS=${BUILD_WINDOWS:-y}
BUILD_DOS=${BUILD_DOS:-n}
BUILD_MSVC=${BUILD_MSVC:-n}
BUILD_SDL=${BUILD_SDL:-n}
BUILD_ANDROID=${BUILD_ANDROID:-n}
BUILD_WEB=${BUILD_WEB:-n}
BUILD_MAC=${BUILD_MAC:-n}
BUILD_NACL=${BUILD_NACL:-n}
if [ "$UID" != "0" ]; then
echo "#path config for fte build scripts" >$FTECONFIG
echo "THREADS=\"$THREADS\"" >>$FTECONFIG
echo "BUILDFOLDER=\"$BUILDFOLDER\"" >>$FTECONFIG
echo "BUILDLOGFOLDER=\"$BUILDLOGFOLDER\"" >>$FTECONFIG
echo "SVNROOT=\"$SVNROOT\"" >>$FTECONFIG
echo "ANDROIDROOT=\"$ANDROIDROOT\"" >>$FTECONFIG
echo "export ANDROID_HOSTSYSTEM=\"ANDROID_HOSTSYSTEM\"" >>$FTECONFIG
echo "export ANDROID_ZIPALIGN=\"ANDROID_ZIPALIGN\"" >>$FTECONFIG
echo "EMSCRIPTENROOT=\"$EMSCRIPTENROOT\"" >>$FTECONFIG
echo "OSXCROSSROOT=\"$OSXCROSSROOT\"" >>$FTECONFIG
echo "NACLROOT=\"$NACLROOT\"" >>$FTECONFIG
echo "NACL_SDK_ROOT=\"$NACLROOT/nacl_sdk/$NACLSDKVERSION\"" >>$FTECONFIG
echo "NACLSDKVERSION=\"$NACLSDKVERSION\"" >>$FTECONFIG
echo "BUILD_LINUXx86=\"$BUILD_LINUXx86\"" >>$FTECONFIG
echo "BUILD_LINUXx64=\"$BUILD_LINUXx64\"" >>$FTECONFIG
echo "BUILD_LINUXx32=\"$BUILD_LINUXx32\"" >>$FTECONFIG
echo "BUILD_LINUXarmhf=\"$BUILD_LINUXarmhf\"" >>$FTECONFIG
echo "BUILD_CYGWIN=\"$BUILD_CYGWIN\"" >>$FTECONFIG
echo "BUILD_WINDOWS=\"$BUILD_WINDOWS\"" >>$FTECONFIG
echo "BUILD_DOS=\"$BUILD_DOS\"" >>$FTECONFIG
echo "BUILD_MSVC=\"$BUILD_MSVC\"" >>$FTECONFIG
echo "BUILD_ANDROID=\"$BUILD_ANDROID\"" >>$FTECONFIG
echo "BUILD_SDL=\"$BUILD_SDL\"" >>$FTECONFIG
echo "BUILD_WEB=\"$BUILD_WEB\"" >>$FTECONFIG
echo "BUILD_MAC=\"$BUILD_MAC\"" >>$FTECONFIG
echo "BUILD_NACL=\"$BUILD_NACL\"" >>$FTECONFIG
echo "PLUGINS_WINDOWS=\"$PLUGINS_WINDOWS\"" >>$FTECONFIG
echo "PLUGINS_LINUXx86=\"$PLUGINS_LINUXx86\"" >>$FTECONFIG
echo "PLUGINS_LINUXx64=\"$PLUGINS_LINUXx64\"" >>$FTECONFIG
echo "PLUGINS_LINUXx32=\"$PLUGINS_LINUXx32\"" >>$FTECONFIG
echo "PLUGINS_LINUXarmhf=\"$PLUGINS_LINUXarmhf\"" >>$FTECONFIG
fi
true
true=$?
false
false=$?
if [ "$(uname -s)" == "Linux" ]; then
. /etc/os-release
fi
function debianpackages {
#make sure apt-get is installed
if [ -z `which apt-get 2>>/dev/null` ]; then
return $false
fi
local ret=$true
for i in "$@"
do
dpkg -s $i 2>&1 >> /dev/null
if [ $? -eq 1 ]; then
ret=$false
fi
done
if [ $ret == $false ]; then
if [ $UID -eq 0 ]; then
apt-get install --no-install-recommends $@
ret=$true
else
echo "Packages not installed. Run as root to easily install dependancies."
fi
fi
return $ret
}
function jessiepackages {
if [ "$PRETTY_NAME" != "Debian GNU/Linux 8 (jessie)" ]; then
return $false
fi
debianpackages $@
return $?
}
#we don't really know what system we're on. assume they have any system dependancies.
#fixme: args are programs findable with which
function otherpackages {
if [ -z "$PRETTY_NAME" ]; then
return $true
fi
return $false
}
#Note: only the native linux-sdl target can be compiled, as libSDL[2]-dev doesn't support multiarch properly, and we depend upon it instead of building from source (thus ensuring it has whatever distro stuff needed... though frankly that should be inside the .so instead of the headers).
if [ $UID -eq 0 ] && [ ! -z `which apt-get` ]; then
#because multiarch requires separate packages for some things, we'll need to set that up now (in case noone did that yet)
dpkg --add-architecture i386
apt-get update
fi
#generic crap. much of this is needed to set up and decompress dependancies and stuff.
debianpackages subversion make automake libtool p7zip-full zip || otherpackages z7 make svn || exit
if [ "$BUILD_LINUXx86" == "y" ]; then
#for building linux targets
debianpackages gcc-multilib g++-multilib mesa-common-dev libasound2-dev libvorbis-dev || otherpackages gcc || exit
jessiepackages libgnutls28-dev || debianpackages libgnutls28-dev || otherpackages gcc || exit
if [[ "$PLUGINS_LINUXx86" =~ "ffmpeg" ]]; then
debianpackages libswscale-dev libavcodec-dev || otherpackages || exit
fi
fi
if [ "$BUILD_LINUXx64" == "y" ]; then
#for building linux targets
debianpackages gcc-multilib g++-multilib mesa-common-dev libasound2-dev || otherpackages gcc || exit
jessiepackages libgnutls28-dev || debianpackages libgnutls28-dev || otherpackages gcc || exit
if [[ "$PLUGINS_LINUXx64" =~ "ffmpeg" ]]; then
debianpackages libswscale-dev libavcodec-dev || otherpackages || exit
fi
fi
if [ "$BUILD_LINUXx32" == "y" ]; then
#for building linux targets
debianpackages gcc-multilib g++-multilib mesa-common-dev libasound2-dev || otherpackages gcc || exit
jessiepackages libgnutls28-dev || debianpackages libgnutls28-dev || otherpackages gcc || exit
fi
if [ "$BUILD_LINUXarmhf" == "y" ]; then
#for building linux targets
debianpackages gcc-multilib-arm-linux-gnueabihf g++-multilib-arm-linux-gnueabihf mesa-common-dev libasound2-dev || otherpackages gcc || exit
jessiepackages libgnutls28-dev || debianpackages libgnutls28-dev || otherpackages gcc || exit
fi
if [ "$BUILD_SDL" == "y" ]; then
#for building SDL targets
debianpackages libSDL1.2-dev libSDL2-dev libspeex-dev libspeexdsp-dev || otherpackages || exit
fi
if [ "$BUILD_WINDOWS" == "y" ]; then
#for building windows targets
debianpackages mingw-w64 || otherpackages x86_64-w64-mingw32-gcc || exit
fi
if [ "$BUILD_ANDROID" == "y" ]; then
( (jessiepackages openjdk-8-jdk-headless || debianpackages openjdk-8-jdk-headless ) && debianpackages ant) || otherpackages || exit
fi
if [ "$BUILD_WEB" == "y" ]; then
( (jessiepackages cmake || debianpackages cmake) && debianpackages git build-essential) || exit
fi
if [ "$BUILD_MAC" == "y" ]; then
debianpackages git cmake libxml2-dev fuse || otherpackages || exit
fi
debianpackages subversion make build-essential || otherpackages svn make || exit
echo "System Package checks complete."
if [ "$UID" == "0" ]; then
#avoid root taking ownership of anything.
echo "Refusing to update/rebuild toolchains as root."
echo "Please continue running this script as a regular user."
exit
fi
echo
echo "(Any new toolchains will be installed to $FTEROOT)"
echo "(Say no if you're certain you already set up everything)"
read -n 1 -p "Rebuild/update any toolchains now? [y/N] " REBUILD_TOOLCHAINS && echo
REBUILD_TOOLCHAINS=${REBUILD_TOOLCHAINS:-n}
mkdir -p $FTEROOT
#dos shit
if [ "$BUILD_DOS" == "y" ] && [ $UID -ne 0 ] && [ $REBUILD_TOOLCHAINS == "y" ]; then
echo "You'll need to manually install djgpp for DOS builds."
fi
#android shit. WARNING: should come first as it spits out some EULAs that need confirming.
if [ "$BUILD_ANDROID" == "y" ] && [ $UID -ne 0 ] && [ $REBUILD_TOOLCHAINS == "y" ]; then
mkdir -p $ANDROIDROOT
cd $ANDROIDROOT
wget -N https://dl.google.com/android/repository/tools_r25.2.3-linux.zip
unzip -qn tools_r25.2.3-linux.zip
cd tools/bin
#yes, android-8 is fucking old now. newer versions won't work on older devices.
echo "downloading android build tools"
./sdkmanager "build-tools;$ANDROID_BUILDTOOLS"
echo "downloading android platform tools"
./sdkmanager "platform-tools"
echo "downloading android-9"
./sdkmanager "platforms;android-9"
echo "downloading android ndk"
./sdkmanager "ndk-bundle"
cd ~
fi
#emscripten/web shit
if [ "$BUILD_WEB" == "y" ] && [ $UID -ne 0 ] && [ $REBUILD_TOOLCHAINS == "y" ]; then
mkdir -p $EMSCRIPTENROOT
cd $EMSCRIPTENROOT/..
wget -N https://s3.amazonaws.com/mozilla-games/emscripten/releases/emsdk-portable.tar.gz
cd $EMSCRIPTENROOT
tar xzf ../emsdk-portable.tar.gz --strip-components=1
./emsdk install latest
./emsdk activate latest
cd ~
fi
#osxcross, for mac crap
if [ "$BUILD_MAC" == "y" ] && [ $UID -ne 0 ] && [ $REBUILD_TOOLCHAINS == "y" ]; then
echo "Setting up OSXCross... THIS IS TOTALLY UNTESTED"
read -p "You need to download xcode first. Where did you download the .dmg file to?" XCODE
git clone https://github.com/tpoechtrager/osxcross.git $OSXCROSSROOT
cd $OSXCROSSROOT
tools/gen_sdk_package_darling_dmg.sh $XCODE
cp *.tar.xz
SDK_VERSION=10.10 UNATTENDED=0 ./build.sh
cd ~
fi
if [ "$BUILD_NACL" == "y" ] && [ $UID -ne 0 ] && [ $REBUILD_TOOLCHAINS == "y" ]; then
echo "Setting up NaCL..."
mkdir -p $NACLROOT
cd $NACLROOT/..
wget -N https://storage.googleapis.com/nativeclient-mirror/nacl/nacl_sdk/nacl_sdk.zip
unzip -qn nacl_sdk.zip
cd $NACLROOT
./naclsdk update $NACLSDKVERSION
fi
#initial checkout of fte's svn
if [ $UID -ne 0 ] && [ $REBUILD_TOOLCHAINS == "y" ]; then
if [ ! -d $SVNROOT ]; then
svn checkout https://svn.code.sf.net/p/fteqw/code/trunk $SVNROOT
else
cd $SVNROOT
svn up
fi
#FIXME: there may be race conditions when compiling.
#so make sure we've pre-built certain targets without using -j
#linux distros vary too much with various dependancies and versions and such, so we might as well pre-build our own copies of certain libraries. this really only needs to be done once, but its safe to retry anyway.
cd $SVNROOT/engine
if [ "$BUILD_LINUXx86" == "y" ]; then
echo "Making libraries (x86)..."
make FTE_TARGET=linux32 makelibs CPUOPTIMISATIONS=-fno-finite-math-only 2>&1 >>/dev/null
fi
if [ "$BUILD_LINUXx64" == "y" ]; then
echo "Making libraries (linux x86_64)..."
make FTE_TARGET=linux64 makelibs CPUOPTIMISATIONS=-fno-finite-math-only 2>&1 >>/dev/null
fi
if [ "$BUILD_LINUXx32" == "y" ]; then
echo "Making libraries (linux x32)..."
make FTE_TARGET=linuxx32 makelibs CPUOPTIMISATIONS=-fno-finite-math-only 2>&1 >>/dev/null
fi
if [ "$BUILD_LINUXarmhf" == "y" ]; then
echo "Making libraries (linux armhf)..."
make FTE_TARGET=linuxarmhf makelibs CPUOPTIMISATIONS=-fno-finite-math-only 2>&1 >>/dev/null
fi
if [ "$BUILD_WINDOWS" == "y" ] && [[ "$PLUGINS_WINDOWS" =~ "ode" ]]; then
echo "Prebuilding ODE library (win32)..."
make FTE_TARGET=win32 plugins-rel NATIVE_PLUGINS=ode 2>&1 >>/dev/null
echo "Prebuilding ODE library (win64)..."
make FTE_TARGET=win64 plugins-rel NATIVE_PLUGINS=ode 2>&1 >>/dev/null
fi
if [ "$BUILD_LINUXx86" == "y" ] && [[ "$PLUGINS_LINUXx86" =~ "ode" ]]; then
echo "Prebuilding ODE library (linux x86)..."
make FTE_TARGET=linux32 plugins-rel NATIVE_PLUGINS=ode CPUOPTIMISATIONS=-fno-finite-math-only 2>&1 >>/dev/null
fi
if [ "$BUILD_LINUXx64" == "y" ] && [[ "$PLUGINS_LINUXx64" =~ "ode" ]]; then
echo "Prebuilding ODE library (linux x86_64)..."
make FTE_TARGET=linux64 plugins-rel NATIVE_PLUGINS=ode CPUOPTIMISATIONS=-fno-finite-math-only 2>&1 >>/dev/null
fi
if [ "$BUILD_WINDOWS" == "y" ]; then
echo "Obtaining ffmpeg library (win32)..."
make FTE_TARGET=win32 plugins-rel NATIVE_PLUGINS=ffmpeg 2>&1 >>/dev/null
echo "Obtaining ffmpeg library (win64)..."
make FTE_TARGET=win64 plugins-rel NATIVE_PLUGINS=ffmpeg 2>&1 >>/dev/null
fi
cd ~
fi
echo "Setup script complete."
echo "When you run build_wip.sh output will be written to $BUILDFOLDER/*"
#!/bin/bash
#sets up dependancies for debian-jessie (8.7)
#this script must be run twice. first time as root, which installs system packages
#second time as a regular user (probably not your normal one), which installs 3rd-party stuff
SVNROOT=$(cd "$(dirname "$BASH_SOURCE")" && pwd)
FTEROOT=$(realpath $SVNROOT/..)
FTEROOT=${FTEROOT:-~}
FTECONFIG=$SVNROOT/build.cfg
BUILDFOLDER=`echo ~`/htdocs
BUILDLOGFOLDER=$BUILDFOLDER/build_logs
#mac defaults
OSXCROSSROOT=$FTEROOT/osxcross
#emscripten defaults
EMSCRIPTENROOT=$FTEROOT/emsdk-portable
#nacl defaults
NACLROOT=$FTEROOT/nacl_sdk
NACLSDKVERSION=pepper_49
#android defaults
ANDROIDROOT=$FTEROOT/android
if [ ! -z "$(uname -o 2>&1 | grep Cygwin)" ]; then
ANDROID_HOSTSYSTEM=windows-x86_64
else
ANDROID_HOSTSYSTEM=linux-$(uname -m)
fi
ANDROIDBUILDTOOLS=25.0.0
ANDROID_ZIPALIGN=$ANDROIDROOT/build-tools/$ANDROIDBUILDTOOLS/zipalign #relative to ndk tools
THREADS="-j 4"
#windows is always cross compiled, so we don't have issues with non-native ffmpeg
PLUGINS_LINUXx86="ode qi ezhud xmpp irc"
PLUGINS_LINUXx64="ode qi ezhud xmpp irc"
PLUGINS_LINUXx32="qi ezhud xmpp irc"
PLUGINS_LINUXarmhf="qi ezhud xmpp irc"
if [ "$(uname -m)" != "x86_64" ]; then
PLUGINS_LINUXx86="ffmpeg ode qi ezhud xmpp irc"
fi
if [ "$(uname -m)" == "x86_64" ]; then
PLUGINS_LINUX64="ffmpeg ode qi ezhud xmpp irc"
fi
#windows doesn't cross compile, so no system dependancy issues
#skip some dependancies if we're running on cygwin, ode is buggy.
if [ "$(uname -s)" == "Linux" ]; then
PLUGINS_WINDOWS="ffmpeg ode qi ezhud xmpp irc"
else
PLUGINS_WINDOWS="qi ezhud xmpp irc"
fi
echo
echo "This is Spike's script to set up various cross compilers and dependancies."
echo "This script will check dependancies. If something isn't installed you can either rerun the script as root (which will ONLY install system packages), or manually apt-get or whatever. You can then re-run the script as a regular user to finish configuring 3rd party dependancies."
echo
echo "You can change your choices later by just re-running this script"
echo "(Your settings will be autosaved in $FTECONFIG)"
echo
echo "If you just want to compile a native build, just use the following command:"
echo "cd $SVNROOT/engine && make gl-rel"
echo "(if you're in cygwin, add FTE_TARGET=win32 to compile for native windows)"
echo "(add plugins-rel qcc-rel qccgui-rel sv-rel vk-rel etc for additional targets)"
echo "(or use -dbg if you want debug builds for whatever reason)"
echo
#always execute it if it exists, so that we preserve custom paths etc that are not prompted for here
if [ -e $FTECONFIG ]; then
. $FTECONFIG
if [ $UID -eq 0 ]; then
REUSE_CONFIG=y #root shouldn't be writing/owning the config file.
else
read -n 1 -p "Reuse previous build config? [y/N] " REUSE_CONFIG && echo
REUSE_CONFIG=${REUSE_CONFIG:-n}
fi
else
if [ $UID -eq 0 ]; then
exit #root can't create the output, as that would take ownership.
else
REUSE_CONFIG=n
fi
fi
if [ "$REUSE_CONFIG" != "y" ]; then
#linux compiles are native-only, so don't bug out on cygwin which lacks a cross compiler.
BUILD_LINUXx86=n
BUILD_LINUXx64=n
BUILD_LINUXx32=n
BUILD_LINUXarmhf=n
if [ "$(uname -s)" == "Linux" ]; then
read -n 1 -p "Build for Linux x86? [Y/n] " BUILD_LINUXx86 && echo
read -n 1 -p "Build for Linux x86_64? [Y/n] " BUILD_LINUXx64 && echo
read -n 1 -p "Build for Linux x32? [y/N] " BUILD_LINUXx32 && echo
#ubuntu's gcc-multilib-arm-foo package conflicts with gcc-multilib...
#the whole point of multilib was to avoid conflicts... someone fucked up.
#read -n 1 -p "Build for Linux armhf [y/N] " BUILD_LINUXarmhf && echo
else
echo "Skipping Linux options."
fi
BUILD_CYGWIN=n
BUILD_MSVC=n
if [ "$(uname -o)" == "Cygwin" ]; then
read -n 1 -p "Build for Cygwin? [y/N] " BUILD_CYGWIN && echo
read -n 1 -p "Build with MSVC? (requires windows7 sdk) [y/N] " BUILD_MSVC && echo
else
echo "Skipping Cygwin options."
fi
read -n 1 -p "Build for Windows? [Y/n] " BUILD_WINDOWS && echo
read -n 1 -p "Build for Dos? [y/N] " BUILD_WINDOWS && echo
read -n 1 -p "Build for SDL? [y/N] " BUILD_SDL && echo
read -n 1 -p "Build for Android? [y/N] " BUILD_ANDROID && echo
read -n 1 -p "Build for Emscripten? [y/N] " BUILD_WEB && echo
if [ 0 -ne 0 ]; then
read -n 1 -p "Build for MacOSX? [y/N] " BUILD_MAC && echo
else
echo "Skipping mac option."
fi
read -n 1 -p "Build for NaCL? [y/N] " BUILD_NACL && echo
fi
BUILD_LINUXx86=${BUILD_LINUXx86:-y}
BUILD_LINUXx64=${BUILD_LINUXx64:-y}
BUILD_LINUXx32=${BUILD_LINUXx32:-n}
BUILD_LINUXarmhf=${BUILD_LINUXarmhf:-n}
BUILD_CYGWIN=${BUILD_CYGWIN:-n}
BUILD_WINDOWS=${BUILD_WINDOWS:-y}
BUILD_DOS=${BUILD_DOS:-n}
BUILD_MSVC=${BUILD_MSVC:-n}
BUILD_SDL=${BUILD_SDL:-n}
BUILD_ANDROID=${BUILD_ANDROID:-n}
BUILD_WEB=${BUILD_WEB:-n}
BUILD_MAC=${BUILD_MAC:-n}
BUILD_NACL=${BUILD_NACL:-n}
if [ "$UID" != "0" ]; then
echo "#path config for fte build scripts" >$FTECONFIG
echo "THREADS=\"$THREADS\"" >>$FTECONFIG
echo "BUILDFOLDER=\"$BUILDFOLDER\"" >>$FTECONFIG
echo "BUILDLOGFOLDER=\"$BUILDLOGFOLDER\"" >>$FTECONFIG
echo "SVNROOT=\"$SVNROOT\"" >>$FTECONFIG
echo "ANDROIDROOT=\"$ANDROIDROOT\"" >>$FTECONFIG
echo "export ANDROID_HOSTSYSTEM=\"ANDROID_HOSTSYSTEM\"" >>$FTECONFIG
echo "export ANDROID_ZIPALIGN=\"ANDROID_ZIPALIGN\"" >>$FTECONFIG
echo "EMSCRIPTENROOT=\"$EMSCRIPTENROOT\"" >>$FTECONFIG
echo "OSXCROSSROOT=\"$OSXCROSSROOT\"" >>$FTECONFIG
echo "NACLROOT=\"$NACLROOT\"" >>$FTECONFIG
echo "NACL_SDK_ROOT=\"$NACLROOT/nacl_sdk/$NACLSDKVERSION\"" >>$FTECONFIG
echo "NACLSDKVERSION=\"$NACLSDKVERSION\"" >>$FTECONFIG
echo "BUILD_LINUXx86=\"$BUILD_LINUXx86\"" >>$FTECONFIG
echo "BUILD_LINUXx64=\"$BUILD_LINUXx64\"" >>$FTECONFIG
echo "BUILD_LINUXx32=\"$BUILD_LINUXx32\"" >>$FTECONFIG
echo "BUILD_LINUXarmhf=\"$BUILD_LINUXarmhf\"" >>$FTECONFIG
echo "BUILD_CYGWIN=\"$BUILD_CYGWIN\"" >>$FTECONFIG
echo "BUILD_WINDOWS=\"$BUILD_WINDOWS\"" >>$FTECONFIG
echo "BUILD_DOS=\"$BUILD_DOS\"" >>$FTECONFIG
echo "BUILD_MSVC=\"$BUILD_MSVC\"" >>$FTECONFIG
echo "BUILD_ANDROID=\"$BUILD_ANDROID\"" >>$FTECONFIG
echo "BUILD_SDL=\"$BUILD_SDL\"" >>$FTECONFIG
echo "BUILD_WEB=\"$BUILD_WEB\"" >>$FTECONFIG
echo "BUILD_MAC=\"$BUILD_MAC\"" >>$FTECONFIG
echo "BUILD_NACL=\"$BUILD_NACL\"" >>$FTECONFIG
echo "PLUGINS_WINDOWS=\"$PLUGINS_WINDOWS\"" >>$FTECONFIG
echo "PLUGINS_LINUXx86=\"$PLUGINS_LINUXx86\"" >>$FTECONFIG
echo "PLUGINS_LINUXx64=\"$PLUGINS_LINUXx64\"" >>$FTECONFIG
echo "PLUGINS_LINUXx32=\"$PLUGINS_LINUXx32\"" >>$FTECONFIG
echo "PLUGINS_LINUXarmhf=\"$PLUGINS_LINUXarmhf\"" >>$FTECONFIG
fi
true
true=$?
false
false=$?
if [ "$(uname -s)" == "Linux" ]; then
. /etc/os-release
fi
function debianpackages {
#make sure apt-get is installed
if [ -z `which apt-get 2>>/dev/null` ]; then
return $false
fi
local ret=$true
for i in "$@"
do
dpkg -s $i 2>&1 >> /dev/null
if [ $? -eq 1 ]; then
ret=$false
fi
done
if [ $ret == $false ]; then
if [ $UID -eq 0 ]; then
apt-get install --no-install-recommends $@
ret=$true
else
echo "Packages not installed. Run as root to easily install dependancies."
fi
fi
return $ret
}
function jessiepackages {
if [ "$PRETTY_NAME" != "Debian GNU/Linux 8 (jessie)" ]; then
return $false
fi
debianpackages $@
return $?
}
#we don't really know what system we're on. assume they have any system dependancies.
#fixme: args are programs findable with which
function otherpackages {
if [ -z "$PRETTY_NAME" ]; then
return $true
fi
return $false
}
#Note: only the native linux-sdl target can be compiled, as libSDL[2]-dev doesn't support multiarch properly, and we depend upon it instead of building from source (thus ensuring it has whatever distro stuff needed... though frankly that should be inside the .so instead of the headers).
if [ $UID -eq 0 ] && [ ! -z `which apt-get` ]; then
#because multiarch requires separate packages for some things, we'll need to set that up now (in case noone did that yet)
dpkg --add-architecture i386
apt-get update
fi
#generic crap. much of this is needed to set up and decompress dependancies and stuff.
debianpackages subversion make automake libtool p7zip-full zip || otherpackages z7 make svn || exit
if [ "$BUILD_LINUXx86" == "y" ]; then
#for building linux targets
debianpackages gcc-multilib g++-multilib mesa-common-dev libasound2-dev libvorbis-dev || otherpackages gcc || exit
jessiepackages libgnutls28-dev || debianpackages libgnutls28-dev || otherpackages gcc || exit
if [[ "$PLUGINS_LINUXx86" =~ "ffmpeg" ]]; then
debianpackages libswscale-dev libavcodec-dev || otherpackages || exit
fi
fi
if [ "$BUILD_LINUXx64" == "y" ]; then
#for building linux targets
debianpackages gcc-multilib g++-multilib mesa-common-dev libasound2-dev || otherpackages gcc || exit
jessiepackages libgnutls28-dev || debianpackages libgnutls28-dev || otherpackages gcc || exit
if [[ "$PLUGINS_LINUXx64" =~ "ffmpeg" ]]; then
debianpackages libswscale-dev libavcodec-dev || otherpackages || exit
fi
fi
if [ "$BUILD_LINUXx32" == "y" ]; then
#for building linux targets
debianpackages gcc-multilib g++-multilib mesa-common-dev libasound2-dev || otherpackages gcc || exit
jessiepackages libgnutls28-dev || debianpackages libgnutls28-dev || otherpackages gcc || exit
fi
if [ "$BUILD_LINUXarmhf" == "y" ]; then
#for building linux targets
debianpackages gcc-multilib-arm-linux-gnueabihf g++-multilib-arm-linux-gnueabihf mesa-common-dev libasound2-dev || otherpackages gcc || exit
jessiepackages libgnutls28-dev || debianpackages libgnutls28-dev || otherpackages gcc || exit
fi
if [ "$BUILD_SDL" == "y" ]; then
#for building SDL targets
debianpackages libSDL1.2-dev libSDL2-dev libspeex-dev libspeexdsp-dev || otherpackages || exit
fi
if [ "$BUILD_WINDOWS" == "y" ]; then
#for building windows targets
debianpackages mingw-w64 || otherpackages x86_64-w64-mingw32-gcc || exit
fi
if [ "$BUILD_ANDROID" == "y" ]; then
( (jessiepackages openjdk-8-jdk-headless || debianpackages openjdk-8-jdk-headless ) && debianpackages ant) || otherpackages || exit
fi
if [ "$BUILD_WEB" == "y" ]; then
( (jessiepackages cmake || debianpackages cmake) && debianpackages git build-essential) || exit
fi
if [ "$BUILD_MAC" == "y" ]; then
debianpackages git cmake libxml2-dev fuse || otherpackages || exit
fi
debianpackages subversion make build-essential || otherpackages svn make || exit
echo "System Package checks complete."
if [ "$UID" == "0" ]; then
#avoid root taking ownership of anything.
echo "Refusing to update/rebuild toolchains as root."
echo "Please continue running this script as a regular user."
exit
fi
echo
echo "(Any new toolchains will be installed to $FTEROOT)"
echo "(Say no if you're certain you already set up everything)"
read -n 1 -p "Rebuild/update any toolchains now? [y/N] " REBUILD_TOOLCHAINS && echo
REBUILD_TOOLCHAINS=${REBUILD_TOOLCHAINS:-n}
mkdir -p $FTEROOT
#dos shit
if [ "$BUILD_DOS" == "y" ] && [ $UID -ne 0 ] && [ $REBUILD_TOOLCHAINS == "y" ]; then
echo "You'll need to manually install djgpp for DOS builds."
fi
#android shit. WARNING: should come first as it spits out some EULAs that need confirming.
if [ "$BUILD_ANDROID" == "y" ] && [ $UID -ne 0 ] && [ $REBUILD_TOOLCHAINS == "y" ]; then
mkdir -p $ANDROIDROOT
cd $ANDROIDROOT
wget -N https://dl.google.com/android/repository/tools_r25.2.3-linux.zip
unzip -qn tools_r25.2.3-linux.zip
cd tools/bin
#yes, android-8 is fucking old now. newer versions won't work on older devices.
echo "downloading android build tools"
./sdkmanager "build-tools;$ANDROID_BUILDTOOLS"
echo "downloading android platform tools"
./sdkmanager "platform-tools"
echo "downloading android-9"
./sdkmanager "platforms;android-9"
echo "downloading android ndk"
./sdkmanager "ndk-bundle"
cd ~
fi
#emscripten/web shit
if [ "$BUILD_WEB" == "y" ] && [ $UID -ne 0 ] && [ $REBUILD_TOOLCHAINS == "y" ]; then
mkdir -p $EMSCRIPTENROOT
cd $EMSCRIPTENROOT/..
wget -N https://s3.amazonaws.com/mozilla-games/emscripten/releases/emsdk-portable.tar.gz
cd $EMSCRIPTENROOT
tar xzf ../emsdk-portable.tar.gz --strip-components=1
./emsdk install latest
./emsdk activate latest
cd ~
fi
#osxcross, for mac crap
if [ "$BUILD_MAC" == "y" ] && [ $UID -ne 0 ] && [ $REBUILD_TOOLCHAINS == "y" ]; then
echo "Setting up OSXCross... THIS IS TOTALLY UNTESTED"
read -p "You need to download xcode first. Where did you download the .dmg file to?" XCODE
git clone https://github.com/tpoechtrager/osxcross.git $OSXCROSSROOT
cd $OSXCROSSROOT
tools/gen_sdk_package_darling_dmg.sh $XCODE
cp *.tar.xz
SDK_VERSION=10.10 UNATTENDED=0 ./build.sh
cd ~
fi
if [ "$BUILD_NACL" == "y" ] && [ $UID -ne 0 ] && [ $REBUILD_TOOLCHAINS == "y" ]; then
echo "Setting up NaCL..."
mkdir -p $NACLROOT
cd $NACLROOT/..
wget -N https://storage.googleapis.com/nativeclient-mirror/nacl/nacl_sdk/nacl_sdk.zip
unzip -qn nacl_sdk.zip
cd $NACLROOT
./naclsdk update $NACLSDKVERSION
fi
#initial checkout of fte's svn
if [ $UID -ne 0 ] && [ $REBUILD_TOOLCHAINS == "y" ]; then
if [ ! -d $SVNROOT ]; then
svn checkout https://svn.code.sf.net/p/fteqw/code/trunk $SVNROOT
else
cd $SVNROOT
svn up
fi
#FIXME: there may be race conditions when compiling.
#so make sure we've pre-built certain targets without using -j
#linux distros vary too much with various dependancies and versions and such, so we might as well pre-build our own copies of certain libraries. this really only needs to be done once, but its safe to retry anyway.
cd $SVNROOT/engine
if [ "$BUILD_LINUXx86" == "y" ]; then
echo "Making libraries (x86)..."
make FTE_TARGET=linux32 makelibs CPUOPTIMISATIONS=-fno-finite-math-only 2>&1 >>/dev/null
fi
if [ "$BUILD_LINUXx64" == "y" ]; then
echo "Making libraries (linux x86_64)..."
make FTE_TARGET=linux64 makelibs CPUOPTIMISATIONS=-fno-finite-math-only 2>&1 >>/dev/null
fi
if [ "$BUILD_LINUXx32" == "y" ]; then
echo "Making libraries (linux x32)..."
make FTE_TARGET=linuxx32 makelibs CPUOPTIMISATIONS=-fno-finite-math-only 2>&1 >>/dev/null
fi
if [ "$BUILD_LINUXarmhf" == "y" ]; then
echo "Making libraries (linux armhf)..."
make FTE_TARGET=linuxarmhf makelibs CPUOPTIMISATIONS=-fno-finite-math-only 2>&1 >>/dev/null
fi
if [ "$BUILD_WINDOWS" == "y" ] && [[ "$PLUGINS_WINDOWS" =~ "ode" ]]; then
echo "Prebuilding ODE library (win32)..."
make FTE_TARGET=win32 plugins-rel NATIVE_PLUGINS=ode 2>&1 >>/dev/null
echo "Prebuilding ODE library (win64)..."
make FTE_TARGET=win64 plugins-rel NATIVE_PLUGINS=ode 2>&1 >>/dev/null
fi
if [ "$BUILD_LINUXx86" == "y" ] && [[ "$PLUGINS_LINUXx86" =~ "ode" ]]; then
echo "Prebuilding ODE library (linux x86)..."
make FTE_TARGET=linux32 plugins-rel NATIVE_PLUGINS=ode CPUOPTIMISATIONS=-fno-finite-math-only 2>&1 >>/dev/null
fi
if [ "$BUILD_LINUXx64" == "y" ] && [[ "$PLUGINS_LINUXx64" =~ "ode" ]]; then
echo "Prebuilding ODE library (linux x86_64)..."
make FTE_TARGET=linux64 plugins-rel NATIVE_PLUGINS=ode CPUOPTIMISATIONS=-fno-finite-math-only 2>&1 >>/dev/null
fi
if [ "$BUILD_WINDOWS" == "y" ]; then
echo "Obtaining ffmpeg library (win32)..."
make FTE_TARGET=win32 plugins-rel NATIVE_PLUGINS=ffmpeg 2>&1 >>/dev/null
echo "Obtaining ffmpeg library (win64)..."
make FTE_TARGET=win64 plugins-rel NATIVE_PLUGINS=ffmpeg 2>&1 >>/dev/null
fi
cd ~
fi
echo "Setup script complete."
echo "When you run build_wip.sh output will be written to $BUILDFOLDER/*"

View File

@ -1,329 +1,329 @@
#!/bin/bash
START=$(date +%s)
SVNROOT=$(cd "$(dirname "$(readlink "$BASH_SOURCE")")" && pwd)
FTECONFIG=$SVNROOT/build.cfg
HOME=`echo ~`
BASE=$SVNROOT/..
#set this if you want non-default branding, for customised builds.
#export BRANDING=wastes
#defaults, if we're not set up properly.
#should be overriden in build.cfg
BUILDFOLDER=$HOME/htdocs
BUILDLOGFOLDER=$BUILDFOLDER/build_logs
SVNROOT=$BASE/fteqw-code
BUILD_LINUXx86=y
BUILD_LINUXx64=y
BUILD_WINDOWS=y
BUILD_ANDROID=y
BUILD_WEB=y
PLUGINS_LINUXx86="qi ezhud xmpp irc"
PLUGINS_LINUXx64="qi ezhud xmpp irc"
PLUGINS_LINUXx32="qi ezhud xmpp irc"
PLUGINS_WINDOWS="avplug ode qi ezhud xmpp irc"
THREADS="-j 4"
########### NaCL stuff
NACL_SDK_ROOT=/opt/nacl_sdk/pepper_31/
if [ -e $FTECONFIG ]; then
. $FTECONFIG
else
echo "WARNING: $FTECONFIG does not exist yet."
fi
export NACL_SDK_ROOT
########### Emscripten / Web Stuff
export EMSDK=$EMSCRIPTENROOT
#export WEB_PREJS="--pre-js $HOME/prejs.js"
########### Android Stuff. so messy...
#This is some android password that you should keep private. You should keep the keystore file private too, of course. Frankly, that part is more important than this small random number.
KEYPASSFILE=$BASE/.fte_keypass
if [ ! -e $KEYPASSFILE ]; then
dd if=/dev/urandom count=9 bs=1 2>/dev/null | base64 > $KEYPASSFILE
chmod 400 $KEYPASSFILE
fi
KEYPASS=`cat $KEYPASSFILE`
export JAVA_HOME=/usr
if [ ! -z "$ANDROIDROOT" ]; then
export ANDROID_HOME=$ANDROIDROOT
fi
if [ ! -z "$ANDROIDNDKROOT" ]; then
export ANDROID_NDK_ROOT=$ANDROIDNDKROOT
else
export ANDROID_NDK_ROOT=$ANDROID_HOME/ndk-bundle
fi
export KEYTOOLARGS="-keypass $KEYPASS -storepass $KEYPASS -dname \"CN=fteqw.com, OU=ID, O=FTE, L=Unknown, S=Unknown, C=GB\""
export JARSIGNARGS="-storepass $KEYPASS"
########### Various Output etc Paths
QCCBUILDFOLDER=$BUILDFOLDER/fteqcc
SVNFOLDER=$SVNROOT/engine/release
ARCHIVEFOLDER=$BUILDFOLDER/archive
SVNDBGFOLDER=$SVNROOT/engine/debug
WARNINGLEVEL="-w"
FILELOCK=$BASE/.fte_buildlock
#./ccache-alias.sh
exec 9>$FILELOCK
if ! flock -n 9 ; then
echo "Build script is already running!";
exit 1
fi
mkdir -p $BUILDLOGFOLDER
if [ ! -d $SVNROOT ]; then
#just in case...
svn checkout https://svn.code.sf.net/p/fteqw/code/trunk $SVNROOT
fi
cd $SVNROOT/
echo "SVN Update"
svn update
cd engine
date > $BUILDLOGFOLDER/buildlog.txt
echo "Starting build" >> $BUILDLOGFOLDER/buildlog.txt
function build {
BUILDSTART=$(date +%s)
NAME=$1
DEST=$2
shift; shift
make clean >> /dev/null
echo -n "Making $NAME... "
date > $BUILDLOGFOLDER/$DEST.txt
echo make $THREADS $* >> $BUILDLOGFOLDER/$DEST.txt 2>&1
make $THREADS $* >> $BUILDLOGFOLDER/$DEST.txt 2>&1
if [ $? -eq 0 ]; then
BUILDEND=$(date +%s)
BUILDTIME=$(( $BUILDEND - $BUILDSTART ))
echo "$BUILDTIME seconds"
echo "$NAME done, took $BUILDTIME seconds" >> $BUILDLOGFOLDER/buildlog.txt
rm -rf $BUILDFOLDER/$DEST >> /dev/null 2>&1
mkdir $BUILDFOLDER/$DEST 2>> /dev/null
mkdir $BUILDFOLDER/$DEST/debug 2>> /dev/null
cp $SVNFOLDER/* $BUILDFOLDER/$DEST >> /dev/null 2>> /dev/null
cp $SVNDBGFOLDER/* $BUILDFOLDER/$DEST/debug >> /dev/null 2>> /dev/null
rm -rf $BUILDFOLDER/$DEST/*.a >> /dev/null 2>&1
rm -rf $BUILDFOLDER/$DEST/debug/*.a >> /dev/null 2>&1
rmdir $BUILDFOLDER/$DEST/debug 2>> /dev/null
else
echo "$NAME failed" >> $BUILDLOGFOLDER/buildlog.txt
echo "failed"
fi
}
function build_fteqcc {
echo "--- no code ---"
}
echo "--- Engine builds ---"
#the -fno-finite-math-only is to avoid a glibc dependancy
if [ "$BUILD_LINUXx86" != "n" ]; then
NATIVE_PLUGINS="$PLUGINS_LINUXx86" build "Linux 32-bit" linux_x86 FTE_TARGET=linux32 CPUOPTIMIZATIONS=-fno-finite-math-only qcc-rel rel dbg vk-rel plugins-rel plugins-dbg
fi
if [ "$BUILD_LINUXx64" != "n" ]; then
NATIVE_PLUGINS="$PLUGINS_LINUXx64" build "Linux 64-bit" linux_amd64 FTE_TARGET=linux64 LDFLAGS="-Llibs/64" CPUOPTIMIZATIONS=-fno-finite-math-only qcc-rel rel dbg vk-rel plugins-rel plugins-dbg
fi
if [ "$BUILD_LINUXx32" != "n" ]; then
# CFLAGS="-DNO_JPEG"
NATIVE_PLUGINS="$PLUGINS_LINUXx32" build "Linux x32" linux_x32 FTE_TARGET=linuxx32 CPUOPTIMIZATIONS=-fno-finite-math-only qcc-rel rel dbg plugins-rel plugins-dbg
fi
if [ "$BUILD_LINUXarmhf" != "n" ]; then
#debian/ubuntu's armhf targets armv7. we instead target armv6, because that means we work on rpi too (but still with hard-float). It should be compatible although we likely need more ops.
NATIVE_PLUGINS="$PLUGINS_LINUXarmhf" build "Linux ARMhf" linux_armhf FTE_TARGET=linuxarmhf CPUOPTIMIZATIONS=-fno-finite-math-only rel dbg qcc-rel plugins-rel plugins-dbg
fi
if [ "$BUILD_CYGWIN" != "n" ]; then
NATIVE_PLUGINS="qi ezhud" build "Cygwin" cygwin qcc-rel rel dbg plugins-rel plugins-dbg
fi
if [ "$BUILD_WINDOWS" != "n" ]; then
NATIVE_PLUGINS="$PLUGINS_WINDOWS" build "Windows 32-bit" win32 FTE_TARGET=win32 CFLAGS="$WARNINGLEVEL" sv-rel gl-rel vk-rel mingl-rel m-rel d3d-rel qcc-rel qccgui-scintilla qccgui-dbg gl-dbg sv-dbg plugins-dbg plugins-rel NATIVE_PLUGINS="$PLUGINS_WINDOWS"
NATIVE_PLUGINS="$PLUGINS_WINDOWS" build "Windows 64-bit" win64 FTE_TARGET=win64 CFLAGS="$WARNINGLEVEL" sv-rel gl-rel vk-rel mingl-rel m-rel d3d-rel qcc-rel qccgui-scintilla qccgui-dbg gl-dbg sv-dbg plugins-dbg plugins-rel
fi
if [ "$BUILD_MSVC" != "n" ]; then
NATIVE_PLUGINS="$PLUGINS_WINDOWS" build "Windows MSVC 32-bit" msvc FTE_TARGET=vc BITS=32 CFLAGS="$WARNINGLEVEL" sv-rel gl-rel vk-rel mingl-rel m-rel d3d-rel qcc-rel qccgui-scintilla qccgui-dbg gl-dbg sv-dbg plugins-dbg plugins-rel
NATIVE_PLUGINS="$PLUGINS_WINDOWS" build "Windows MSVC 64-bit" msvc FTE_TARGET=vc BITS=64 CFLAGS="$WARNINGLEVEL" sv-rel gl-rel vk-rel mingl-rel m-rel d3d-rel qcc-rel qccgui-scintilla qccgui-dbg gl-dbg sv-dbg plugins-dbg plugins-rel
fi
export NATIVE_PLUGINS="qi ezhud xmpp irc"
if [ "$BUILD_ANDROID" != "n" ]; then
build "Android" android droid-rel
fi
if [ "$BUILD_WINDOWS" != "n" ]; then
build "NPFTE" npfte npfte-rel
fi
if [ "$BUILD_DOS" == "y" ]; then
#no networking makes dedicated servers useless. and only a crappy sw renderer is implemented right now.
#the qcc might be useful to someone though!
build "DOS" dos m-rel qcc-rel
fi
if [ "$BUILD_WEB" != "n" ]; then
source $EMSDK/emsdk_env.sh >> /dev/null
build "Emscripten" web FTE_TARGET=web gl-rel CC=emcc
fi
if [ "$BUILD_LINUX" != "n" ] && [ "$BUILD_SDL" != "n" ] && [ "$(uname -m)" != "x86_64" ]; then
build "Linux 32-bit (SDL)" linux_x86_sdl FTE_TARGET=SDL BITS=32 LTO=1
fi
if [ "$BUILD_LINUX" != "n" ] && [ "$BUILD_SDL" != "n" ] && [ "$(uname -m)" == "x86_64" ]; then
build "Linux 64-bit (SDL)" linux_amd64_sdl FTE_TARGET=SDL BITS=64 LDFLAGS="-Llibs/64" LTO=1
fi
if [ "$BUILD_WINDOWS" != "n" ] && [ "$BUILD_SDL" != "n" ]; then
build "Windows 32-bit (SDL)" win32_sdl FTE_TARGET=win32_SDL gl-rel mingl-rel
build "Windows 64-bit (SDL)" win64_sdl FTE_TARGET=win64_SDL LDFLAGS="-L./libs/mingw64-libs/" gl-rel mingl-rel
CFLAGS="$WARNINGLEVEL -DNOLEGACY -DOMIT_QCC" build "Windows 32-bit nocompat" nocompat FTE_TARGET=win32 LTO=1 NOCOMPAT=1 BOTLIB_CFLAGS="" BOTLIB_OBJS="" gl-rel m-rel -k
fi
if [ "$BUILD_NACL" != "n" ]; then
#non-pnacl is supported ONLY in chrome's store crap, but pnacl works anywhere.
# build "Native Client 64-bit" nacl_amd64 FTE_TARGET=nacl NARCH=x86_64 gl-rel
# build "Native Client 32-bit" nacl_x86 FTE_TARGET=nacl NARCH=x86_32 gl-rel
#internal compiler error build "Native Client ARM" nacl_arm FTE_TARGET=nacl NARCH=arm gl-rel
build "Native Client Portable" nacl_portable FTE_TARGET=nacl NARCH=pnacl gl-rel
fi
####build "MorphOS" morphos CFLAGS="-I$BASE/morphos/os-include/ -I$BASE/morphos/lib/ -L$BASE/morphos/lib/ -I$BASE/zlib/zlib-1.2.5 -L$BASE/zlib/zlib-1.2.5 -I./libs $WARNINGLEVEL" gl-rel mingl-rel sv-rel qcc-rel
if [ "$BUILD_MAC" != "n" ]; then
#build "MacOSX" macosx_tiger CFLAGS="-I$BASE/mac/x86/include/ -L$BASE/mac/x86/lib -I./libs" FTE_TARGET=macosx_x86 sv-rel gl-rel mingl-rel qcc-rel
#FIXME: figure out how to do universal binaries or whatever they're called
build "MacOSX 32-bit" osx32 CC=o32-clang CXX=o32-clang++ FTE_TARGET=osx_x86 BITS=32 sv-rel gl-rel mingl-rel qcc-rel
build "MacOSX 64-bit" osx64 CC=o64-clang CXX=o64-clang++ FTE_TARGET=osx_x86_64 BITS=64 sv-rel gl-rel mingl-rel qcc-rel
fi
#third party stuff / misc crap
if [ "$BUILD_WEB" != "n" ]; then
cp $BASE/3rdparty/web/* $BUILDFOLDER/web/
fi
if [ "$BUILD_WINDOWS" != "n" ]; then
cp $BASE/3rdparty/win32/3rdparty.zip $BUILDFOLDER/win32/3rdparty.zip
cp $BASE/3rdparty/win64/3rdparty.zip $BUILDFOLDER/win64/3rdparty.zip
if [ "$BUILD_SDL" != "n" ]; then
cp $SVNROOT/engine/libs/SDL2-2.0.1/i686-w64-mingw32/bin/SDL2.dll $BUILDFOLDER/win32_sdl
cp $SVNROOT/engine/libs/SDL2-2.0.1/x86_64-w64-mingw32/bin/SDL2.dll $BUILDFOLDER/win64_sdl
fi
cp $HOME/nocompat_readme.html $BUILDFOLDER/nocompat/README.html
fi
echo "--- QC builds ---"
rm -rf $QCCBUILDFOLDER 2>&1
mkdir -p $QCCBUILDFOLDER
if [ -e "$BUILDFOLDER/linux_x86/fteqw-gl32" ]
then
echo "Making fteextensions.qc"
mkdir -p ~/.fte/fte
echo "pr_dumpplatform -o fteextensions" > ~/.fte/fte/minusargsaresilly.cfg
echo "pr_dumpplatform -o csqcsysdefs -Tcs" >> ~/.fte/fte/minusargsaresilly.cfg
echo "pr_dumpplatform -o menusysdefs -Tmenu" >> ~/.fte/fte/minusargsaresilly.cfg
$BUILDFOLDER/linux_x86/fteqw-gl32 -basedir ~/.fte -nohome -quake +set snd_device none -nosound +set vid_renderer sv +exec minusargsaresilly.cfg +quit >> /dev/null
mv ~/.fte/fte/src/fteextensions.qc $QCCBUILDFOLDER
mv ~/.fte/fte/src/csqcsysdefs.qc $QCCBUILDFOLDER
mv ~/.fte/fte/src/menusysdefs.qc $QCCBUILDFOLDER
else
echo "Skipping FTE Extensions, no Linux gl32 build located"
fi
if [ -e $BUILDFOLDER/linux_x86/fteqcc32 ]; then
echo "Making csaddon + qcmenu"
mkdir -p $BUILDFOLDER/csaddon/
cd $SVNROOT/quakec
cd csaddon/src
$BUILDFOLDER/linux_x86/fteqcc32 -srcfile csaddon.src > $BUILDLOGFOLDER/csaddon.txt
mv ../csaddon.dat $BUILDFOLDER/csaddon/
cd ../../menusys
$BUILDFOLDER/linux_x86/fteqcc32 -srcfile menu.src > $BUILDLOGFOLDER/menu.txt
rm fteqcc.log
zip -q -9 -o -r $BUILDFOLDER/csaddon/menusys_src.zip .
mv ../menu.dat $BUILDFOLDER/csaddon/
else
echo "Skiping csaddon + qcmenu, no compiler build"
fi
cd $SVNROOT/engine/
svn info > $BUILDFOLDER/version.txt
if [ "$BUILD_LINUXx86" != "n" ]; then
cp $BUILDFOLDER/linux_x86/fteqcc32 $QCCBUILDFOLDER/linux32-fteqcc
fi
if [ "$BUILD_LINUXx64" != "n" ]; then
cp $BUILDFOLDER/linux_amd64/fteqcc64 $QCCBUILDFOLDER/linux64-fteqcc
fi
if [ "$BUILD_LINUXx32" != "n" ]; then
cp $BUILDFOLDER/linux_x32/fteqccx32 $QCCBUILDFOLDER/linuxx32-fteqcc
fi
if [ "$BUILD_LINUXarmhf" != "n" ]; then
cp $BUILDFOLDER/linux_armhf/fteqccarmhf $QCCBUILDFOLDER/linuxarmhf-fteqcc
fi
if [ "$BUILD_WINDOWS" != "n" ]; then
cp $BUILDFOLDER/win32/fteqcc.exe $QCCBUILDFOLDER/win32-fteqcc.exe
cp $BUILDFOLDER/win32/fteqccgui.exe $QCCBUILDFOLDER/win32-fteqccgui.exe
cp $BUILDFOLDER/win64/fteqcc64.exe $QCCBUILDFOLDER/win64-fteqcc.exe
cp $BUILDFOLDER/win64/fteqccgui64.exe $QCCBUILDFOLDER/win64-fteqccgui.exe
fi
#cp $BUILDFOLDER/morphos/fteqcc $QCCBUILDFOLDER/morphos-fteqcc
#cp $BUILDFOLDER/macosx_tiger/fteqcc $QCCBUILDFOLDER/macosx_tiger-fteqcc
cp $BUILDFOLDER/version.txt $QCCBUILDFOLDER/version.txt
if [ "$BUILD_NACL" != "n" ]; then
mkdir -p $BUILDFOLDER/nacl
NACL=$BUILDFOLDER/nacl/fteqw.nmf
echo "{ \"program\":{" > $NACL
if [ -e "$BUILDFOLDER/nacl_amd64/fteqw-x86_64.nexe" ]; then
mv $BUILDFOLDER/nacl_amd64/fteqw-x86_64.nexe $BUILDFOLDER/nacl/fteqw-x86_64.nexe
echo " \"x86-64\":{\"url\":\"fteqw-x86_64.nexe\"}," >> $NACL
fi
if [ -e "$BUILDFOLDER/nacl_x86/fteqw-x86_32.nexe" ]; then
mv $BUILDFOLDER/nacl_x86/fteqw-x86_32.nexe $BUILDFOLDER/nacl/fteqw-x86_32.nexe
echo " \"x86-32\":{\"url\":\"fteqw-x86_32.nexe\"}," >> $NACL
fi
if [ -e "$BUILDFOLDER/nacl_arm/fteqw-arm.nexe" ]; then
mv $BUILDFOLDER/nacl_arm/fteqw-arm.nexe $BUILDFOLDER/nacl/fteqw-arm.nexe
echo " \"arm\":{\"url\":\"fteqw-arm.nexe\"}" >> $NACL
fi
$NACL_SDK_ROOT/toolchain/linux_pnacl/bin/pnacl-finalize -o $BUILDFOLDER/nacl/fteqw.pexe $BUILDFOLDER/nacl_portable/fteqw.pexe
echo " \"portable\":{\"pnacl-translate\":{\"url\":\"fteqw.pexe\"}}" >> $NACL
echo "} }" >> $NACL
rm -rf "$BUILDFOLDER/nacl_amd64"
rm -rf "$BUILDFOLDER/nacl_x86"
rm -rf "$BUILDFOLDER/nacl_arm"
rm -rf "$BUILDFOLDER/nacl_portable"
fi
if [ "$BUILD_WINDOWS" != "n" ]; then
echo Archiving output
SVNVER=$(svnversion $SVNROOT)
cd $BUILDFOLDER/
zip -q -9 $ARCHIVEFOLDER/win_fteqw_$SVNVER.zip win32/fteglqw.exe win32/fteqwsv.exe win32/fteqccgui.exe win32/debug/fteglqw.exe win64/fteqw.exe win64/debug/fteglqw.exe
cd $BUILDFOLDER/win32/
zip -q -j -9 $BUILDFOLDER/fteqw_for_windows.zip fteglqw.exe fteqwsv.exe fteqccgui.exe fteplug_qi_x86.dll fteplug_xmpp_x86.dll fteplug_irc_x86.dll fteplug_ezhud_x86.dll
cd $HOME/3rdparty_win32/
zip -q -9 $BUILDFOLDER/fteqw_for_windows.zip ogg.dll vorbis.dll vorbisfile.dll freetype6.dll zlib1.dll
mkdir -p $BASE/tmp/fte
cd $BASE/tmp/
cp $BUILDFOLDER/csaddon/menu.dat fte
zip -q -9 $BUILDFOLDER/fteqw_for_windows.zip fte/menu.dat
#~/afterquake/updatemini.sh
fi
echo "All done"
END=$(date +%s)
DIFF=$(( $END - $START ))
MINS=$(( $DIFF / 60 ))
echo "Total Compile Time: $MINS minutes" >> $BUILDLOGFOLDER/buildlog.txt
echo "Total Compile Time: $MINS minutes"
cd $HOME
#./errorlog.sh
#cd $HOME
#rm .bitchxrc
#cp ./fteqw/.bitchxrc ./
#./BitchX -a irc.quakenet.org -A -c "#fte" -n A_Gorilla
#!/bin/bash
START=$(date +%s)
SVNROOT=$(cd "$(dirname "$(readlink "$BASH_SOURCE")")" && pwd)
FTECONFIG=$SVNROOT/build.cfg
HOME=`echo ~`
BASE=$SVNROOT/..
#set this if you want non-default branding, for customised builds.
#export BRANDING=wastes
#defaults, if we're not set up properly.
#should be overriden in build.cfg
BUILDFOLDER=$HOME/htdocs
BUILDLOGFOLDER=$BUILDFOLDER/build_logs
SVNROOT=$BASE/fteqw-code
BUILD_LINUXx86=y
BUILD_LINUXx64=y
BUILD_WINDOWS=y
BUILD_ANDROID=y
BUILD_WEB=y
PLUGINS_LINUXx86="qi ezhud xmpp irc"
PLUGINS_LINUXx64="qi ezhud xmpp irc"
PLUGINS_LINUXx32="qi ezhud xmpp irc"
PLUGINS_WINDOWS="avplug ode qi ezhud xmpp irc"
THREADS="-j 4"
########### NaCL stuff
NACL_SDK_ROOT=/opt/nacl_sdk/pepper_31/
if [ -e $FTECONFIG ]; then
. $FTECONFIG
else
echo "WARNING: $FTECONFIG does not exist yet."
fi
export NACL_SDK_ROOT
########### Emscripten / Web Stuff
export EMSDK=$EMSCRIPTENROOT
#export WEB_PREJS="--pre-js $HOME/prejs.js"
########### Android Stuff. so messy...
#This is some android password that you should keep private. You should keep the keystore file private too, of course. Frankly, that part is more important than this small random number.
KEYPASSFILE=$BASE/.fte_keypass
if [ ! -e $KEYPASSFILE ]; then
dd if=/dev/urandom count=9 bs=1 2>/dev/null | base64 > $KEYPASSFILE
chmod 400 $KEYPASSFILE
fi
KEYPASS=`cat $KEYPASSFILE`
export JAVA_HOME=/usr
if [ ! -z "$ANDROIDROOT" ]; then
export ANDROID_HOME=$ANDROIDROOT
fi
if [ ! -z "$ANDROIDNDKROOT" ]; then
export ANDROID_NDK_ROOT=$ANDROIDNDKROOT
else
export ANDROID_NDK_ROOT=$ANDROID_HOME/ndk-bundle
fi
export KEYTOOLARGS="-keypass $KEYPASS -storepass $KEYPASS -dname \"CN=fteqw.com, OU=ID, O=FTE, L=Unknown, S=Unknown, C=GB\""
export JARSIGNARGS="-storepass $KEYPASS"
########### Various Output etc Paths
QCCBUILDFOLDER=$BUILDFOLDER/fteqcc
SVNFOLDER=$SVNROOT/engine/release
ARCHIVEFOLDER=$BUILDFOLDER/archive
SVNDBGFOLDER=$SVNROOT/engine/debug
WARNINGLEVEL="-w"
FILELOCK=$BASE/.fte_buildlock
#./ccache-alias.sh
exec 9>$FILELOCK
if ! flock -n 9 ; then
echo "Build script is already running!";
exit 1
fi
mkdir -p $BUILDLOGFOLDER
if [ ! -d $SVNROOT ]; then
#just in case...
svn checkout https://svn.code.sf.net/p/fteqw/code/trunk $SVNROOT
fi
cd $SVNROOT/
echo "SVN Update"
svn update
cd engine
date > $BUILDLOGFOLDER/buildlog.txt
echo "Starting build" >> $BUILDLOGFOLDER/buildlog.txt
function build {
BUILDSTART=$(date +%s)
NAME=$1
DEST=$2
shift; shift
make clean >> /dev/null
echo -n "Making $NAME... "
date > $BUILDLOGFOLDER/$DEST.txt
echo make $THREADS $* >> $BUILDLOGFOLDER/$DEST.txt 2>&1
make $THREADS $* >> $BUILDLOGFOLDER/$DEST.txt 2>&1
if [ $? -eq 0 ]; then
BUILDEND=$(date +%s)
BUILDTIME=$(( $BUILDEND - $BUILDSTART ))
echo "$BUILDTIME seconds"
echo "$NAME done, took $BUILDTIME seconds" >> $BUILDLOGFOLDER/buildlog.txt
rm -rf $BUILDFOLDER/$DEST >> /dev/null 2>&1
mkdir $BUILDFOLDER/$DEST 2>> /dev/null
mkdir $BUILDFOLDER/$DEST/debug 2>> /dev/null
cp $SVNFOLDER/* $BUILDFOLDER/$DEST >> /dev/null 2>> /dev/null
cp $SVNDBGFOLDER/* $BUILDFOLDER/$DEST/debug >> /dev/null 2>> /dev/null
rm -rf $BUILDFOLDER/$DEST/*.a >> /dev/null 2>&1
rm -rf $BUILDFOLDER/$DEST/debug/*.a >> /dev/null 2>&1
rmdir $BUILDFOLDER/$DEST/debug 2>> /dev/null
else
echo "$NAME failed" >> $BUILDLOGFOLDER/buildlog.txt
echo "failed"
fi
}
function build_fteqcc {
echo "--- no code ---"
}
echo "--- Engine builds ---"
#the -fno-finite-math-only is to avoid a glibc dependancy
if [ "$BUILD_LINUXx86" != "n" ]; then
NATIVE_PLUGINS="$PLUGINS_LINUXx86" build "Linux 32-bit" linux_x86 FTE_TARGET=linux32 CPUOPTIMIZATIONS=-fno-finite-math-only qcc-rel rel dbg vk-rel plugins-rel plugins-dbg
fi
if [ "$BUILD_LINUXx64" != "n" ]; then
NATIVE_PLUGINS="$PLUGINS_LINUXx64" build "Linux 64-bit" linux_amd64 FTE_TARGET=linux64 LDFLAGS="-Llibs/64" CPUOPTIMIZATIONS=-fno-finite-math-only qcc-rel rel dbg vk-rel plugins-rel plugins-dbg
fi
if [ "$BUILD_LINUXx32" != "n" ]; then
# CFLAGS="-DNO_JPEG"
NATIVE_PLUGINS="$PLUGINS_LINUXx32" build "Linux x32" linux_x32 FTE_TARGET=linuxx32 CPUOPTIMIZATIONS=-fno-finite-math-only qcc-rel rel dbg plugins-rel plugins-dbg
fi
if [ "$BUILD_LINUXarmhf" != "n" ]; then
#debian/ubuntu's armhf targets armv7. we instead target armv6, because that means we work on rpi too (but still with hard-float). It should be compatible although we likely need more ops.
NATIVE_PLUGINS="$PLUGINS_LINUXarmhf" build "Linux ARMhf" linux_armhf FTE_TARGET=linuxarmhf CPUOPTIMIZATIONS=-fno-finite-math-only rel dbg qcc-rel plugins-rel plugins-dbg
fi
if [ "$BUILD_CYGWIN" != "n" ]; then
NATIVE_PLUGINS="qi ezhud" build "Cygwin" cygwin qcc-rel rel dbg plugins-rel plugins-dbg
fi
if [ "$BUILD_WINDOWS" != "n" ]; then
NATIVE_PLUGINS="$PLUGINS_WINDOWS" build "Windows 32-bit" win32 FTE_TARGET=win32 CFLAGS="$WARNINGLEVEL" sv-rel gl-rel vk-rel mingl-rel m-rel d3d-rel qcc-rel qccgui-scintilla qccgui-dbg gl-dbg sv-dbg plugins-dbg plugins-rel NATIVE_PLUGINS="$PLUGINS_WINDOWS"
NATIVE_PLUGINS="$PLUGINS_WINDOWS" build "Windows 64-bit" win64 FTE_TARGET=win64 CFLAGS="$WARNINGLEVEL" sv-rel gl-rel vk-rel mingl-rel m-rel d3d-rel qcc-rel qccgui-scintilla qccgui-dbg gl-dbg sv-dbg plugins-dbg plugins-rel
fi
if [ "$BUILD_MSVC" != "n" ]; then
NATIVE_PLUGINS="$PLUGINS_WINDOWS" build "Windows MSVC 32-bit" msvc FTE_TARGET=vc BITS=32 CFLAGS="$WARNINGLEVEL" sv-rel gl-rel vk-rel mingl-rel m-rel d3d-rel qcc-rel qccgui-scintilla qccgui-dbg gl-dbg sv-dbg plugins-dbg plugins-rel
NATIVE_PLUGINS="$PLUGINS_WINDOWS" build "Windows MSVC 64-bit" msvc FTE_TARGET=vc BITS=64 CFLAGS="$WARNINGLEVEL" sv-rel gl-rel vk-rel mingl-rel m-rel d3d-rel qcc-rel qccgui-scintilla qccgui-dbg gl-dbg sv-dbg plugins-dbg plugins-rel
fi
export NATIVE_PLUGINS="qi ezhud xmpp irc"
if [ "$BUILD_ANDROID" != "n" ]; then
build "Android" android droid-rel
fi
if [ "$BUILD_WINDOWS" != "n" ]; then
build "NPFTE" npfte npfte-rel
fi
if [ "$BUILD_DOS" == "y" ]; then
#no networking makes dedicated servers useless. and only a crappy sw renderer is implemented right now.
#the qcc might be useful to someone though!
build "DOS" dos m-rel qcc-rel
fi
if [ "$BUILD_WEB" != "n" ]; then
source $EMSDK/emsdk_env.sh >> /dev/null
build "Emscripten" web FTE_TARGET=web gl-rel CC=emcc
fi
if [ "$BUILD_LINUX" != "n" ] && [ "$BUILD_SDL" != "n" ] && [ "$(uname -m)" != "x86_64" ]; then
build "Linux 32-bit (SDL)" linux_x86_sdl FTE_TARGET=SDL BITS=32 LTO=1
fi
if [ "$BUILD_LINUX" != "n" ] && [ "$BUILD_SDL" != "n" ] && [ "$(uname -m)" == "x86_64" ]; then
build "Linux 64-bit (SDL)" linux_amd64_sdl FTE_TARGET=SDL BITS=64 LDFLAGS="-Llibs/64" LTO=1
fi
if [ "$BUILD_WINDOWS" != "n" ] && [ "$BUILD_SDL" != "n" ]; then
build "Windows 32-bit (SDL)" win32_sdl FTE_TARGET=win32_SDL gl-rel mingl-rel
build "Windows 64-bit (SDL)" win64_sdl FTE_TARGET=win64_SDL LDFLAGS="-L./libs/mingw64-libs/" gl-rel mingl-rel
CFLAGS="$WARNINGLEVEL -DNOLEGACY -DOMIT_QCC" build "Windows 32-bit nocompat" nocompat FTE_TARGET=win32 LTO=1 NOCOMPAT=1 BOTLIB_CFLAGS="" BOTLIB_OBJS="" gl-rel m-rel -k
fi
if [ "$BUILD_NACL" != "n" ]; then
#non-pnacl is supported ONLY in chrome's store crap, but pnacl works anywhere.
# build "Native Client 64-bit" nacl_amd64 FTE_TARGET=nacl NARCH=x86_64 gl-rel
# build "Native Client 32-bit" nacl_x86 FTE_TARGET=nacl NARCH=x86_32 gl-rel
#internal compiler error build "Native Client ARM" nacl_arm FTE_TARGET=nacl NARCH=arm gl-rel
build "Native Client Portable" nacl_portable FTE_TARGET=nacl NARCH=pnacl gl-rel
fi
####build "MorphOS" morphos CFLAGS="-I$BASE/morphos/os-include/ -I$BASE/morphos/lib/ -L$BASE/morphos/lib/ -I$BASE/zlib/zlib-1.2.5 -L$BASE/zlib/zlib-1.2.5 -I./libs $WARNINGLEVEL" gl-rel mingl-rel sv-rel qcc-rel
if [ "$BUILD_MAC" != "n" ]; then
#build "MacOSX" macosx_tiger CFLAGS="-I$BASE/mac/x86/include/ -L$BASE/mac/x86/lib -I./libs" FTE_TARGET=macosx_x86 sv-rel gl-rel mingl-rel qcc-rel
#FIXME: figure out how to do universal binaries or whatever they're called
build "MacOSX 32-bit" osx32 CC=o32-clang CXX=o32-clang++ FTE_TARGET=osx_x86 BITS=32 sv-rel gl-rel mingl-rel qcc-rel
build "MacOSX 64-bit" osx64 CC=o64-clang CXX=o64-clang++ FTE_TARGET=osx_x86_64 BITS=64 sv-rel gl-rel mingl-rel qcc-rel
fi
#third party stuff / misc crap
if [ "$BUILD_WEB" != "n" ]; then
cp $BASE/3rdparty/web/* $BUILDFOLDER/web/
fi
if [ "$BUILD_WINDOWS" != "n" ]; then
cp $BASE/3rdparty/win32/3rdparty.zip $BUILDFOLDER/win32/3rdparty.zip
cp $BASE/3rdparty/win64/3rdparty.zip $BUILDFOLDER/win64/3rdparty.zip
if [ "$BUILD_SDL" != "n" ]; then
cp $SVNROOT/engine/libs/SDL2-2.0.1/i686-w64-mingw32/bin/SDL2.dll $BUILDFOLDER/win32_sdl
cp $SVNROOT/engine/libs/SDL2-2.0.1/x86_64-w64-mingw32/bin/SDL2.dll $BUILDFOLDER/win64_sdl
fi
cp $HOME/nocompat_readme.html $BUILDFOLDER/nocompat/README.html
fi
echo "--- QC builds ---"
rm -rf $QCCBUILDFOLDER 2>&1
mkdir -p $QCCBUILDFOLDER
if [ -e "$BUILDFOLDER/linux_x86/fteqw-gl32" ]
then
echo "Making fteextensions.qc"
mkdir -p ~/.fte/fte
echo "pr_dumpplatform -o fteextensions" > ~/.fte/fte/minusargsaresilly.cfg
echo "pr_dumpplatform -o csqcsysdefs -Tcs" >> ~/.fte/fte/minusargsaresilly.cfg
echo "pr_dumpplatform -o menusysdefs -Tmenu" >> ~/.fte/fte/minusargsaresilly.cfg
$BUILDFOLDER/linux_x86/fteqw-gl32 -basedir ~/.fte -nohome -quake +set snd_device none -nosound +set vid_renderer sv +exec minusargsaresilly.cfg +quit >> /dev/null
mv ~/.fte/fte/src/fteextensions.qc $QCCBUILDFOLDER
mv ~/.fte/fte/src/csqcsysdefs.qc $QCCBUILDFOLDER
mv ~/.fte/fte/src/menusysdefs.qc $QCCBUILDFOLDER
else
echo "Skipping FTE Extensions, no Linux gl32 build located"
fi
if [ -e $BUILDFOLDER/linux_x86/fteqcc32 ]; then
echo "Making csaddon + qcmenu"
mkdir -p $BUILDFOLDER/csaddon/
cd $SVNROOT/quakec
cd csaddon/src
$BUILDFOLDER/linux_x86/fteqcc32 -srcfile csaddon.src > $BUILDLOGFOLDER/csaddon.txt
mv ../csaddon.dat $BUILDFOLDER/csaddon/
cd ../../menusys
$BUILDFOLDER/linux_x86/fteqcc32 -srcfile menu.src > $BUILDLOGFOLDER/menu.txt
rm fteqcc.log
zip -q -9 -o -r $BUILDFOLDER/csaddon/menusys_src.zip .
mv ../menu.dat $BUILDFOLDER/csaddon/
else
echo "Skiping csaddon + qcmenu, no compiler build"
fi
cd $SVNROOT/engine/
svn info > $BUILDFOLDER/version.txt
if [ "$BUILD_LINUXx86" != "n" ]; then
cp $BUILDFOLDER/linux_x86/fteqcc32 $QCCBUILDFOLDER/linux32-fteqcc
fi
if [ "$BUILD_LINUXx64" != "n" ]; then
cp $BUILDFOLDER/linux_amd64/fteqcc64 $QCCBUILDFOLDER/linux64-fteqcc
fi
if [ "$BUILD_LINUXx32" != "n" ]; then
cp $BUILDFOLDER/linux_x32/fteqccx32 $QCCBUILDFOLDER/linuxx32-fteqcc
fi
if [ "$BUILD_LINUXarmhf" != "n" ]; then
cp $BUILDFOLDER/linux_armhf/fteqccarmhf $QCCBUILDFOLDER/linuxarmhf-fteqcc
fi
if [ "$BUILD_WINDOWS" != "n" ]; then
cp $BUILDFOLDER/win32/fteqcc.exe $QCCBUILDFOLDER/win32-fteqcc.exe
cp $BUILDFOLDER/win32/fteqccgui.exe $QCCBUILDFOLDER/win32-fteqccgui.exe
cp $BUILDFOLDER/win64/fteqcc64.exe $QCCBUILDFOLDER/win64-fteqcc.exe
cp $BUILDFOLDER/win64/fteqccgui64.exe $QCCBUILDFOLDER/win64-fteqccgui.exe
fi
#cp $BUILDFOLDER/morphos/fteqcc $QCCBUILDFOLDER/morphos-fteqcc
#cp $BUILDFOLDER/macosx_tiger/fteqcc $QCCBUILDFOLDER/macosx_tiger-fteqcc
cp $BUILDFOLDER/version.txt $QCCBUILDFOLDER/version.txt
if [ "$BUILD_NACL" != "n" ]; then
mkdir -p $BUILDFOLDER/nacl
NACL=$BUILDFOLDER/nacl/fteqw.nmf
echo "{ \"program\":{" > $NACL
if [ -e "$BUILDFOLDER/nacl_amd64/fteqw-x86_64.nexe" ]; then
mv $BUILDFOLDER/nacl_amd64/fteqw-x86_64.nexe $BUILDFOLDER/nacl/fteqw-x86_64.nexe
echo " \"x86-64\":{\"url\":\"fteqw-x86_64.nexe\"}," >> $NACL
fi
if [ -e "$BUILDFOLDER/nacl_x86/fteqw-x86_32.nexe" ]; then
mv $BUILDFOLDER/nacl_x86/fteqw-x86_32.nexe $BUILDFOLDER/nacl/fteqw-x86_32.nexe
echo " \"x86-32\":{\"url\":\"fteqw-x86_32.nexe\"}," >> $NACL
fi
if [ -e "$BUILDFOLDER/nacl_arm/fteqw-arm.nexe" ]; then
mv $BUILDFOLDER/nacl_arm/fteqw-arm.nexe $BUILDFOLDER/nacl/fteqw-arm.nexe
echo " \"arm\":{\"url\":\"fteqw-arm.nexe\"}" >> $NACL
fi
$NACL_SDK_ROOT/toolchain/linux_pnacl/bin/pnacl-finalize -o $BUILDFOLDER/nacl/fteqw.pexe $BUILDFOLDER/nacl_portable/fteqw.pexe
echo " \"portable\":{\"pnacl-translate\":{\"url\":\"fteqw.pexe\"}}" >> $NACL
echo "} }" >> $NACL
rm -rf "$BUILDFOLDER/nacl_amd64"
rm -rf "$BUILDFOLDER/nacl_x86"
rm -rf "$BUILDFOLDER/nacl_arm"
rm -rf "$BUILDFOLDER/nacl_portable"
fi
if [ "$BUILD_WINDOWS" != "n" ]; then
echo Archiving output
SVNVER=$(svnversion $SVNROOT)
cd $BUILDFOLDER/
zip -q -9 $ARCHIVEFOLDER/win_fteqw_$SVNVER.zip win32/fteglqw.exe win32/fteqwsv.exe win32/fteqccgui.exe win32/debug/fteglqw.exe win64/fteqw.exe win64/debug/fteglqw.exe
cd $BUILDFOLDER/win32/
zip -q -j -9 $BUILDFOLDER/fteqw_for_windows.zip fteglqw.exe fteqwsv.exe fteqccgui.exe fteplug_qi_x86.dll fteplug_xmpp_x86.dll fteplug_irc_x86.dll fteplug_ezhud_x86.dll
cd $HOME/3rdparty_win32/
zip -q -9 $BUILDFOLDER/fteqw_for_windows.zip ogg.dll vorbis.dll vorbisfile.dll freetype6.dll zlib1.dll
mkdir -p $BASE/tmp/fte
cd $BASE/tmp/
cp $BUILDFOLDER/csaddon/menu.dat fte
zip -q -9 $BUILDFOLDER/fteqw_for_windows.zip fte/menu.dat
#~/afterquake/updatemini.sh
fi
echo "All done"
END=$(date +%s)
DIFF=$(( $END - $START ))
MINS=$(( $DIFF / 60 ))
echo "Total Compile Time: $MINS minutes" >> $BUILDLOGFOLDER/buildlog.txt
echo "Total Compile Time: $MINS minutes"
cd $HOME
#./errorlog.sh
#cd $HOME
#rm .bitchxrc
#cp ./fteqw/.bitchxrc ./
#./BitchX -a irc.quakenet.org -A -c "#fte" -n A_Gorilla

View File

@ -4235,7 +4235,7 @@ void CL_LinkPacketEntities (void)
{
if (trailef == P_INVALID || pe->ParticleTrail (old_origin, ent->origin, trailef, ent->keynum, ent->axis, &(le->trailstate)))
if (model->traildefaultindex >= 0)
pe->ParticleTrailIndex(old_origin, ent->origin, trailidx, 0, &(le->trailstate));
pe->ParticleTrailIndex(old_origin, ent->origin, P_INVALID, trailidx, 0, &(le->trailstate));
//dlights are not so customisable.
if (r_rocketlight.value && (modelflags & MF_ROCKET) && !(state->lightpflags & (PFLAGS_FULLDYNAMIC|PFLAGS_CORONA)))

View File

@ -1540,7 +1540,7 @@ qboolean CLQ2_SendCmd (sizebuf_t *buf)
i = cls.netchan.outgoing_sequence & UPDATE_MASK;
cmd = &cl.outframes[i].cmd[seat];
*cmd = independantphysics[seat];
cmd->lightlevel = (lightlev>255)?255:lightlev;
cl.outframes[i].senttime = realtime;

View File

@ -8083,10 +8083,8 @@ void CLNQ_ParseServerMessage (void)
break;
case svcfitz_skybox:
{
extern cvar_t r_skyboxname;
Cvar_Set(&r_skyboxname, MSG_ReadString());
}
Q_strncpyz(cl.skyname, MSG_ReadString(), sizeof(cl.skyname));
R_SetSky(cl.skyname);
break;
case svcfitz_bf:
Cmd_ExecuteString("bf", RESTRICT_SERVER);

View File

@ -830,7 +830,7 @@ void CL_PredictEntityMovement(entity_state_t *estate, float age)
{
VectorClear(startstate.velocity);
startstate.onground = false;
startstate.jump_held = false;
startstate.jump_held = false;
CL_EntStateToPlayerState(&startstate, estate);
CL_EntStateToPlayerCommand(&cmd, estate, age);

View File

@ -63,7 +63,7 @@ void RSpeedShow(void)
RSpNames[RSPEED_STENCILSHADOWS] = "Stencil Shadows";
RSpNames[RSPEED_FULLBRIGHTS] = "World fullbrights";
RSpNames[RSPEED_SETUP] = "Setup";
RSpNames[RSPEED_SETUP] = "Setup/Acquire";
RSpNames[RSPEED_SUBMIT] = "submit/finish";
RSpNames[RSPEED_PRESENT] = "present";
@ -296,9 +296,10 @@ typedef struct {
unsigned int flags;
conchar_t *string;
conchar_t *cursorchar; //pointer into string
size_t stringbytes;
size_t charcount;
char titleimage[MAX_QPATH];
unsigned int charcount;
float time_start; // for slow victory printing
float time_off;
int erase_lines;
@ -379,6 +380,7 @@ for a few moments
*/
void SCR_CenterPrint (int pnum, char *str, qboolean skipgamecode)
{
size_t i;
cprint_t *p;
if (!str)
{
@ -411,6 +413,7 @@ void SCR_CenterPrint (int pnum, char *str, qboolean skipgamecode)
p = &scr_centerprint[pnum];
p->flags = 0;
p->titleimage[0] = 0;
p->cursorchar = NULL;
if (*str != '/')
{
@ -435,6 +438,8 @@ void SCR_CenterPrint (int pnum, char *str, qboolean skipgamecode)
p->flags |= CPRINT_PERSIST | CPRINT_BACKGROUND;
p->flags &= ~CPRINT_TALIGN;
}
else if (str[1] == 'C')
p->flags |= CPRINT_CURSOR; //this can be a little jarring if there's no links, so this forces consistent behaviour.
else if (str[1] == 'W') //wait between each char
p->flags ^= CPRINT_TYPEWRITER;
else if (str[1] == 'S') //Stay
@ -526,6 +531,15 @@ void SCR_CenterPrint (int pnum, char *str, qboolean skipgamecode)
}
}
if (!(p->flags & CPRINT_CURSOR))
{ //autodetect links
for (i = 0; i < p->charcount; i++)
{
if (p->string[i] == CON_LINKSTART)
p->flags |= CPRINT_CURSOR;
}
}
p->time_off = scr_centertime.value;
p->time_start = cl.time;
}
@ -565,6 +579,55 @@ void VARGS Stats_Message(char *msg, ...)
p->time_start = cl.time;
}
static char *SCR_CopyCenterPrint(cprint_t *p) //reads the link under the mouse cursor. non-links are ignored.
{
size_t maxlen, outlen;
char *result;
conchar_t *start = p->cursorchar, *end;
if (!start) //cursor isn't over anything.
return NULL;
//scan backwards to find any link enclosure
for(end = start-1; end >= p->string; end--)
{
if (*end == CON_LINKSTART)
{
//found one
start = end;
break;
}
if (*end == CON_LINKEND)
{
//some other link ended here. don't use its start.
break;
}
}
//scan forwards to find the end of the selected link
if (start < p->string+p->charcount && *start == CON_LINKSTART)
{
for(end = start; end < p->string + p->charcount; end++)
{
if (*end == CON_LINKEND)
{
end++;
break;
}
}
}
else// if (onlyiflink)
return NULL;
maxlen = 1024*1024;
result = Z_Malloc(maxlen+1);
outlen = COM_DeFunString(start, end, result, maxlen, false, false) - result;
result[outlen++] = 0;
return result;
}
#define MAX_CPRINT_LINES 512
void SCR_DrawCenterString (vrect_t *rect, cprint_t *p, struct font_s *font)
{
@ -576,12 +639,12 @@ void SCR_DrawCenterString (vrect_t *rect, cprint_t *p, struct font_s *font)
int bottom;
int remaining;
shader_t *pic;
int ch;
conchar_t *line_start[MAX_CPRINT_LINES];
conchar_t *line_end[MAX_CPRINT_LINES];
int linecount;
// the finale prints the characters one at a time
if (p->flags & CPRINT_TYPEWRITER)
remaining = scr_printspeed.value * (cl.time - p->time_start);
@ -646,24 +709,26 @@ void SCR_DrawCenterString (vrect_t *rect, cprint_t *p, struct font_s *font)
Font_BeginString(font, rect->x+rect->width, rect->y+rect->height, &right, &bottom);
linecount = Font_LineBreaks(p->string, p->string + p->charcount, right - left, MAX_CPRINT_LINES, line_start, line_end);
ch = Font_CharHeight();
if (p->flags & CPRINT_TALIGN)
y = top;
else if (p->flags & CPRINT_BALIGN)
y = bottom - Font_CharHeight()*linecount;
y = bottom - ch*linecount;
else if (p->flags & CPRINT_OBITUARTY)
//'obituary' messages appear at the bottom of the screen
y = (bottom-top - Font_CharHeight()*linecount) * 0.65 + top;
y = (bottom-top - ch*linecount) * 0.65 + top;
else
{
if (linecount <= 5)
{
//small messages appear above and away from the crosshair
y = (bottom-top - Font_CharHeight()*linecount) * 0.35 + top;
y = (bottom-top - ch*linecount) * 0.35 + top;
}
else
{
//longer messages are fully centered
y = (bottom-top - Font_CharHeight()*linecount) * 0.5 + top;
y = (bottom-top - ch*linecount) * 0.5 + top;
}
}
@ -683,7 +748,7 @@ void SCR_DrawCenterString (vrect_t *rect, cprint_t *p, struct font_s *font)
Font_BeginString(font, rect->x, y, &left, &top);
}
for (l = 0; l < linecount; l++, y += Font_CharHeight())
for (l = 0; l < linecount; l++, y += ch)
{
if (y >= bottom)
break;
@ -694,6 +759,11 @@ void SCR_DrawCenterString (vrect_t *rect, cprint_t *p, struct font_s *font)
else
x = left + (right - left - Font_LineWidth(line_start[l], line_end[l]))/2;
if (mousecursor_y >= y && mousecursor_y < y+ch)
{
p->cursorchar = Font_CharAt(mousecursor_x - x, line_start[l], line_end[l]);
}
remaining -= line_end[l]-line_start[l];
if (remaining <= 0)
{
@ -703,24 +773,102 @@ void SCR_DrawCenterString (vrect_t *rect, cprint_t *p, struct font_s *font)
}
Font_LineDraw(x, y, line_start[l], line_end[l]);
}
Font_EndString(font);
}
qboolean Key_Centerprint(int key, int unicode, unsigned int devid)
{
int pnum;
cprint_t *p;
char *link;
if (key == K_MOUSE1)
{
//figure out which player has the cursor
for (pnum = 0; pnum < cl.splitclients; pnum++)
{
p = &scr_centerprint[pnum];
if (cl.playerview[pnum].gamerectknown == cls.framecount)
{
link = SCR_CopyCenterPrint(p);
if (link)
{
if (link[0] == '^' && link[1] == '[')
{
//looks like it might be a link!
char *end = NULL;
char *info;
for (info = link + 2; *info; )
{
if (info[0] == '^' && info[1] == ']')
break; //end of tag, with no actual info, apparently
if (*info == '\\')
break;
else if (info[0] == '^' && info[1] == '^')
info+=2;
else
info++;
}
for(end = info; *end; )
{
if (end[0] == '^' && end[1] == ']')
{
//okay, its a valid link that they clicked
*end = 0;
#ifdef PLUGINS
if (!Plug_ConsoleLink(link+2, info, ""))
#endif
#ifdef CSQC_DAT
if (!CSQC_ConsoleLink(link+2, info))
#endif
Key_DefaultLinkClicked(NULL, link+2, info);
break;
}
if (end[0] == '^' && end[1] == '^')
end+=2;
else
end++;
}
}
}
}
}
return true; //handled
}
else if (key == K_MOUSE2)
{
for (pnum = 0; pnum < cl.splitclients; pnum++)
{
p = &scr_centerprint[pnum];
p->flags &= ~CPRINT_CURSOR;
}
return true;
}
return false;
}
void SCR_CheckDrawCenterString (void)
{
int pnum;
cprint_t *p;
Key_Dest_Remove(kdm_centerprint);
for (pnum = 0; pnum < cl.splitclients; pnum++)
{
p = &scr_centerprint[pnum];
p->cursorchar = NULL;
if (p->time_off <= 0 && !(p->flags & CPRINT_PERSIST))
continue; //'/P' prefix doesn't time out
p->time_off -= host_frametime;
if (Key_Dest_Has(~kdm_game)) //don't let progs guis/centerprints interfere with the game menu
if (Key_Dest_Has(~(kdm_game|kdm_centerprint))) //don't let progs guis/centerprints interfere with the game menu
continue; //should probably allow the console with a scissor region or something.
#ifdef QUAKEHUD
@ -729,7 +877,11 @@ void SCR_CheckDrawCenterString (void)
#endif
if (cl.playerview[pnum].gamerectknown == cls.framecount)
{
SCR_DrawCenterString(&cl.playerview[pnum].gamerect, p, font_default);
if (p->flags & CPRINT_CURSOR)
Key_Dest_Add(kdm_centerprint);
}
}
}

View File

@ -770,7 +770,7 @@ beam_t *CL_AddBeam (enum beamtype_e tent, int ent, vec3_t start, vec3_t end) //f
{
// TODO: add support for those finnicky colored railtrails...
if (P_ParticleTrail(start, end, rtqw_railtrail, -ent, NULL, NULL))
P_ParticleTrailIndex(start, end, 208, 8, NULL);
P_ParticleTrailIndex(start, end, P_INVALID, 208, 8, NULL);
return NULL;
}
break;
@ -1573,7 +1573,7 @@ void CL_ParseTEnt (void)
pos2[2] = MSG_ReadCoord ();
if (P_ParticleTrail(pos, pos2, rtqw_railtrail, 0, NULL, NULL))
P_ParticleTrailIndex(pos, pos2, 208, 8, NULL);
P_ParticleTrailIndex(pos, pos2, P_INVALID, 208, 8, NULL);
break;
case TEH2_STREAM_LIGHTNING_SMALL:
@ -1717,7 +1717,7 @@ void CL_ParseTEnt (void)
MSG_ReadCoord ();
if (P_ParticleTrail(pos, pos2, P_FindParticleType("te_nexbeam"), 0, NULL, NULL))
P_ParticleTrailIndex(pos, pos2, 15, 0, NULL);
P_ParticleTrailIndex(pos, pos2, P_INVALID, 15, 0, NULL);
break;
case TEDP_SMOKE:
@ -2467,11 +2467,11 @@ void CLQ2_ParseSteam(void)
signed int id = MSG_ReadShort();
/*qbyte count =*/ MSG_ReadByte();
MSG_ReadPos(pos);
MSG_ReadPos(dir);
MSG_ReadDir(dir);
/*colour =*/ MSG_ReadByte();
/*magnitude =*/ MSG_ReadShort();
if (id == -1)
if (id != -1)
/*duration =*/ MSG_ReadLong();
else
/*duration = 0;*/
@ -2500,172 +2500,14 @@ void Q2S_StartSound(vec3_t origin, int entnum, int entchannel, sfx_t *sfx, float
{
S_StartSound(entnum, entchannel, sfx, origin, NULL, fvol, attenuation, -delay, 0, 0);
}
void CLQ2_ParseTEnt (void)
{
beam_t *b;
int type;
int pt;
static qboolean CLQ2_ParseTEnt_RemoveMe(q2particleeffects_t type)
{ //FIXME: this function needs to die, once we're sure its no longer needed.
vec3_t pos, pos2, dir;
explosion_t *ex;
int cnt;
int color;
int r;
int ent;
// int magnitude;
type = MSG_ReadByte ();
if (type <= Q2TE_MAX)
{
pt = pt_q2[type];
if (pt == P_INVALID && q2efnames[type])
{
Con_Printf("Q2TE legacy code: te %i\n", type);
goto fixme;
}
}
else
pt = P_INVALID;
switch (type)
{
case Q2TE_GUNSHOT: //grey tall thing with smoke+sparks
case Q2TE_BLOOD: //red tall thing
case Q2TE_SPARKS: //orange tall thing (with not many particles)
case Q2TE_BLASTER: //regular blaster
case Q2TE_SHOTGUN: //gunshot with less particles
case Q2TE_SCREEN_SPARKS://green+grey tall
case Q2TE_SHIELD_SPARKS://blue+grey tall
case Q2TE_BULLET_SPARKS://orange+grey tall+smoke
case Q2TE_GREENBLOOD: //yellow...
case Q2TE_BLASTER2: //green version of te_blaster
case Q2TE_MOREBLOOD: //te_blood*2
case Q2TE_HEATBEAM_SPARKS://white outwards puffs
case Q2TE_HEATBEAM_STEAM://orange outwards puffs
case Q2TE_ELECTRIC_SPARKS://blue tall
case Q2TE_FLECHETTE: //grey version of te_blaster
MSG_ReadPos (pos);
MSG_ReadDir (dir);
P_RunParticleEffectType(pos, dir, 1, pt);
break;
case Q2TE_BFG_LASER:
MSG_ReadPos (pos);
MSG_ReadPos (pos2);
CL_Laser(pos, pos2, 0xd0d1d2d3);
break;
case Q2TE_RAILTRAIL: //blue spiral, grey particles
case Q2TE_BUBBLETRAIL: //grey sparse trail, slow riser
// case Q2TE_BFG_LASER: //green laser
case Q2TE_DEBUGTRAIL: //long lived blue trail
case Q2TE_BUBBLETRAIL2: //grey rising trail
case Q2TE_BLUEHYPERBLASTER: //TE_BLASTER without model+light
MSG_ReadPos (pos);
MSG_ReadPos (pos2);
P_ParticleTrail(pos, pos2, pt, 0, NULL, NULL);
break;
case Q2TE_EXPLOSION1: //column
case Q2TE_EXPLOSION2: //splits
case Q2TE_ROCKET_EXPLOSION://top blob/column
case Q2TE_GRENADE_EXPLOSION://indistinguishable from TE_EXPLOSION2
case Q2TE_ROCKET_EXPLOSION_WATER://rocket but with different sound
case Q2TE_GRENADE_EXPLOSION_WATER://different sound
case Q2TE_BFG_EXPLOSION://green light+sprite
case Q2TE_BFG_BIGEXPLOSION://green+white fast particles
case Q2TE_BOSSTPORT://splitting+merging+upwards particles.
case Q2TE_PLASMA_EXPLOSION://looks like rocket explosion to me
case Q2TE_PLAIN_EXPLOSION://looks like rocket explosion to me
case Q2TE_CHAINFIST_SMOKE://small smoke
case Q2TE_TRACKER_EXPLOSION://black light, slow particles
case Q2TE_TELEPORT_EFFECT://q1-style teleport
case Q2TE_DBALL_GOAL://q1-style teleport
case Q2TE_NUKEBLAST://dome expansion (blue/white particles)
case Q2TE_WIDOWSPLASH://dome (orange+gravity)
case Q2TE_EXPLOSION1_BIG://buggy model
case Q2TE_EXPLOSION1_NP://looks like a rocket explosion to me
MSG_ReadPos (pos);
P_RunParticleEffectType(pos, NULL, 1, pt);
break;
case Q2TE_SPLASH:
cnt = MSG_ReadByte ();
MSG_ReadPos (pos);
MSG_ReadDir (dir);
r = MSG_ReadByte () + Q2SPLASH_UNKNOWN;
if (r > Q2SPLASH_MAX)
r = Q2SPLASH_UNKNOWN;
pt = pt_q2[r];
P_RunParticleEffectType(pos, NULL, 1, pt);
break;
case Q2TE_PARASITE_ATTACK:
case Q2TE_MEDIC_CABLE_ATTACK:
CL_ParseBeam (BT_Q2PARASITE);
break;
case Q2TE_HEATBEAM:
b = CL_ParseBeam (BT_Q2HEATBEAM); //2, 7, -3
if (b)
{
b->bflags |= STREAM_ATTACHED;
VectorSet(b->offset, 2, 7, -3);
}
break;
case Q2TE_MONSTER_HEATBEAM:
b = CL_ParseBeam (BT_Q2HEATBEAM);
if (b)
b->bflags |= STREAM_ATTACHED;
break;
case Q2TE_GRAPPLE_CABLE:
CL_ParseBeamOffset (BT_Q2GRAPPLE);
break;
case Q2TE_LIGHTNING:
ent = MSGCL_ReadEntity ();
/*toent =*/ MSGCL_ReadEntity (); //ident only.
pos[0] = MSG_ReadCoord ();
pos[1] = MSG_ReadCoord ();
pos[2] = MSG_ReadCoord ();
pos2[0] = MSG_ReadCoord ();
pos2[1] = MSG_ReadCoord ();
pos2[2] = MSG_ReadCoord ();
CL_AddBeam(BT_Q2LIGHTNING, ent, pos, pos2);
break;
case Q2TE_LASER_SPARKS:
cnt = MSG_ReadByte ();
MSG_ReadPos (pos);
MSG_ReadDir (dir);
color = MSG_ReadByte ();
P_RunParticleEffectPalette("q2part.TEQ2_LASER_SPARKS", pos, dir, color, cnt);
break;
/*
case Q2TE_LASER_SPARKS:
case Q2TE_WELDING_SPARKS:
case Q2TE_TUNNEL_SPARKS:
break;
//Q2TE_RAILTRAIL2, ?
//Q2TE_FLAME, ?
case Q2TE_FLASHLIGHT:
break;
case Q2TE_FORCEWALL:
break;
case Q2TE_WIDOWBEAMOUT:
break;
*/
case Q2TE_STEAM:
CLQ2_ParseSteam();
break;
default:
// Con_Printf("CLQ2_ParseTEnt: bad/non-implemented type %i\n", type);
goto fixme;
// Host_EndGame ("CLQ2_ParseTEnt: bad/non-implemented type %i", type);
// break;
}
return;
fixme:
Con_DPrintf("Q2TE legacy code: te %i\n", type);
switch(type)
{
@ -2817,7 +2659,7 @@ fixme:
MSG_ReadPos (pos);
MSG_ReadPos (pos2);
if (P_ParticleTrail(pos, pos2, pt_q2[Q2TE_RAILTRAIL], 0, NULL, NULL))
P_ParticleTrailIndex(pos, pos2, 0x74, 8, NULL);
P_ParticleTrailIndex(pos, pos2, P_INVALID, 0x74, 8, NULL);
Q2S_StartSound (pos, 0, 0, S_PrecacheSound ("weapons/railgf1a.wav"), 1, ATTN_NORM, 0);
break;
@ -3025,7 +2867,7 @@ fixme:
MSG_ReadPos (pos);
MSG_ReadPos (pos2);
if (P_ParticleTrail(pos, pos2, pt_q2[Q2TE_BUBBLETRAIL], 0, NULL, NULL))
P_ParticleTrailIndex(pos, pos2, 4, 8, NULL);
P_ParticleTrailIndex(pos, pos2, P_INVALID, 4, 8, NULL);
break;
case Q2TE_PARASITE_ATTACK:
@ -3198,7 +3040,7 @@ fixme:
MSG_ReadPos (pos);
MSG_ReadPos (pos2);
if (P_ParticleTrail(pos, pos2, P_FindParticleType("te_debugtrail"), 0, NULL, NULL))
P_ParticleTrailIndex(pos, pos2, 116, 8, NULL);
P_ParticleTrailIndex(pos, pos2, P_INVALID, 116, 8, NULL);
break;
case Q2TE_PLAIN_EXPLOSION:
@ -3304,23 +3146,19 @@ fixme:
if (P_RunParticleEffectType(pos, dir, 4, ptqw_blood))
P_RunParticleEffect(pos, dir, 0xe8, 250);
break;
/*
case Q2TE_CHAINFIST_SMOKE:
dir[0]=0; dir[1]=0; dir[2]=1;
MSG_ReadPos(&net_message, pos);
CL_ParticleSmokeEffect (pos, dir, 0, 20, 20);
MSG_ReadPos(pos);
P_RunParticleEffectTypeString(pos, NULL, 1, "TEQ2_CHAINFIST_SMOKE");
break;
case Q2TE_ELECTRIC_SPARKS:
MSG_ReadPos (&net_message, pos);
MSG_ReadDir (&net_message, dir);
// CL_ParticleEffect (pos, dir, 109, 40);
CL_ParticleEffect (pos, dir, 0x75, 40);
//FIXME : replace or remove this sound
S_StartSound (pos, 0, 0, cl_sfx_lashit, 1, ATTN_NORM, 0);
MSG_ReadPos (pos);
MSG_ReadDir (dir);
P_RunParticleEffect(pos, dir, 0x75, 40);
Q2S_StartSound (pos, 0, 0, S_PrecacheSound ("weapons/lashit.wav"), 1, ATTN_NORM, 0);
break;
*/
case Q2TE_TRACKER_EXPLOSION:
MSG_ReadPos (pos);
@ -3429,7 +3267,7 @@ fixme:
MSG_ReadPos (pos2);
P_ParticleTrail(pos, pos2, P_FindParticleType("q2part.TR_BLASTERTRAIL2"), 0, NULL, NULL);
break;
case CRTE_STAIN:
/* case CRTE_STAIN:
Host_EndGame ("CLQ2_ParseTEnt: bad/non-implemented type %i", type);
case CRTE_FIRE:
Host_EndGame ("CLQ2_ParseTEnt: bad/non-implemented type %i", type);
@ -3437,9 +3275,178 @@ fixme:
Host_EndGame ("CLQ2_ParseTEnt: bad/non-implemented type %i", type);
case CRTE_SMOKE:
Host_EndGame ("CLQ2_ParseTEnt: bad/non-implemented type %i", type);
*/
default:
Host_EndGame ("CLQ2_ParseTEnt: bad/non-implemented type %i", type);
return false;
}
return true;
}
void CLQ2_ParseTEnt (void)
{
beam_t *b;
q2particleeffects_t type;
int pt;
vec3_t pos, pos2, dir;
int cnt;
int color;
int r;
int ent;
// int magnitude;
type = MSG_ReadByte ();
if (type <= Q2TE_MAX)
{
pt = pt_q2[type];
if (pt == P_INVALID && q2efnames[type])
{
Con_Printf("Q2TE legacy code: te %i\n", type);
if (CLQ2_ParseTEnt_RemoveMe(type))
return;
}
}
else
pt = P_INVALID;
switch (type)
{
case Q2TE_GUNSHOT: //grey tall thing with smoke+sparks
case Q2TE_BLOOD: //red tall thing
case Q2TE_SPARKS: //orange tall thing (with not many particles)
case Q2TE_BLASTER: //regular blaster
case Q2TE_SHOTGUN: //gunshot with less particles
case Q2TE_SCREEN_SPARKS://green+grey tall
case Q2TE_SHIELD_SPARKS://blue+grey tall
case Q2TE_BULLET_SPARKS://orange+grey tall+smoke
case Q2TE_GREENBLOOD: //yellow...
case Q2TE_BLASTER2: //green version of te_blaster
case Q2TE_MOREBLOOD: //te_blood*2
case Q2TE_HEATBEAM_SPARKS://white outwards puffs
case Q2TE_HEATBEAM_STEAM://orange outwards puffs
case Q2TE_ELECTRIC_SPARKS://blue tall
case Q2TE_FLECHETTE: //grey version of te_blaster
MSG_ReadPos (pos);
MSG_ReadDir (dir);
P_RunParticleEffectType(pos, dir, 1, pt);
break;
case Q2TE_BFG_LASER:
MSG_ReadPos (pos);
MSG_ReadPos (pos2);
CL_Laser(pos, pos2, 0xd0d1d2d3);
break;
case Q2TE_RAILTRAIL: //blue spiral, grey particles
case Q2TE_BUBBLETRAIL: //grey sparse trail, slow riser
// case Q2TE_BFG_LASER: //green laser
case Q2TE_DEBUGTRAIL: //long lived blue trail
case Q2TE_BUBBLETRAIL2: //grey rising trail
case Q2TE_BLUEHYPERBLASTER: //TE_BLASTER without model+light
MSG_ReadPos (pos);
MSG_ReadPos (pos2);
P_ParticleTrail(pos, pos2, pt, 0, NULL, NULL);
break;
case Q2TE_EXPLOSION1: //column
case Q2TE_EXPLOSION2: //splits
case Q2TE_ROCKET_EXPLOSION://top blob/column
case Q2TE_GRENADE_EXPLOSION://indistinguishable from TE_EXPLOSION2
case Q2TE_ROCKET_EXPLOSION_WATER://rocket but with different sound
case Q2TE_GRENADE_EXPLOSION_WATER://different sound
case Q2TE_BFG_EXPLOSION://green light+sprite
case Q2TE_BFG_BIGEXPLOSION://green+white fast particles
case Q2TE_BOSSTPORT://splitting+merging+upwards particles.
case Q2TE_PLASMA_EXPLOSION://looks like rocket explosion to me
case Q2TE_PLAIN_EXPLOSION://looks like rocket explosion to me
case Q2TE_CHAINFIST_SMOKE://small smoke
case Q2TE_TRACKER_EXPLOSION://black light, slow particles
case Q2TE_TELEPORT_EFFECT://q1-style teleport
case Q2TE_DBALL_GOAL://q1-style teleport
case Q2TE_NUKEBLAST://dome expansion (blue/white particles)
case Q2TE_WIDOWSPLASH://dome (orange+gravity)
case Q2TE_EXPLOSION1_BIG://buggy model
case Q2TE_EXPLOSION1_NP://looks like a rocket explosion to me
MSG_ReadPos (pos);
P_RunParticleEffectType(pos, NULL, 1, pt);
break;
case Q2TE_SPLASH:
cnt = MSG_ReadByte ();
MSG_ReadPos (pos);
MSG_ReadDir (dir);
r = MSG_ReadByte () + Q2SPLASH_UNKNOWN;
if (r > Q2SPLASH_MAX)
r = Q2SPLASH_UNKNOWN;
pt = pt_q2[r];
P_RunParticleEffectType(pos, NULL, 1, pt);
break;
case Q2TE_PARASITE_ATTACK:
case Q2TE_MEDIC_CABLE_ATTACK:
CL_ParseBeam (BT_Q2PARASITE);
break;
case Q2TE_HEATBEAM:
b = CL_ParseBeam (BT_Q2HEATBEAM); //2, 7, -3
if (b)
{
b->bflags |= STREAM_ATTACHED;
VectorSet(b->offset, 2, 7, -3);
}
break;
case Q2TE_MONSTER_HEATBEAM:
b = CL_ParseBeam (BT_Q2HEATBEAM);
if (b)
b->bflags |= STREAM_ATTACHED;
break;
case Q2TE_GRAPPLE_CABLE:
CL_ParseBeamOffset (BT_Q2GRAPPLE);
break;
case Q2TE_LIGHTNING:
ent = MSGCL_ReadEntity ();
/*toent =*/ MSGCL_ReadEntity (); //ident only.
pos[0] = MSG_ReadCoord ();
pos[1] = MSG_ReadCoord ();
pos[2] = MSG_ReadCoord ();
pos2[0] = MSG_ReadCoord ();
pos2[1] = MSG_ReadCoord ();
pos2[2] = MSG_ReadCoord ();
CL_AddBeam(BT_Q2LIGHTNING, ent, pos, pos2);
break;
case Q2TE_LASER_SPARKS:
case Q2TE_WELDING_SPARKS:
case Q2TE_TUNNEL_SPARKS:
cnt = MSG_ReadByte ();
MSG_ReadPos (pos);
MSG_ReadDir (dir);
color = MSG_ReadByte ();
P_RunParticleEffectPalette(va("q2part.%s", q2efnames[type]), pos, dir, color, cnt);
break;
case Q2TE_STEAM:
CLQ2_ParseSteam();
break;
case Q2TE_FORCEWALL:
MSG_ReadPos (pos);
MSG_ReadDir (pos2);
color = MSG_ReadByte ();
P_ParticleTrailIndex(pos, pos2, pt, color, 0, NULL);
break;
case Q2TE_RAILTRAIL2:
case Q2TE_FLAME:
case Q2TE_FLASHLIGHT:
case Q2TE_WIDOWBEAMOUT:
#ifdef __GNUC__
case (Q2TE_FLECHETTE+1) ... Q2PT_MAX:
// case (Q2TE_MAX+1) ... Q2PT_MAX:
// default:
#else
default:
#endif
// Con_Printf("CLQ2_ParseTEnt: bad/non-implemented type %i\n", type);
if (!CLQ2_ParseTEnt_RemoveMe(type))
Host_EndGame ("CLQ2_ParseTEnt: bad/non-implemented type %i", type);
break;
}
}
#endif

View File

@ -759,7 +759,7 @@ void CLQ2_ParseDelta (entity_state_t *from, entity_state_t *to, int number, int
to->effects = MSG_ReadShort();
if ( (bits & (Q2U_RENDERFX8|Q2U_RENDERFX16)) == (Q2U_RENDERFX8|Q2U_RENDERFX16) )
to->u.q2.renderfx = MSG_ReadLong();
to->u.q2.renderfx = MSG_ReadLong() & 0x0007ffff; //only the standard ones actually supported by vanilla q2.
else if (bits & Q2U_RENDERFX8)
to->u.q2.renderfx = MSG_ReadByte();
else if (bits & Q2U_RENDERFX16)
@ -1975,7 +1975,7 @@ static void CLQ2_AddPacketEntities (q2frame_t *frame)
if (P_ParticleTrail(cent->lerp_origin, ent.origin, pt_q2[Q2RT_ROCKET], ent.keynum, NULL, &cent->trailstate))
if (P_ParticleTrail(cent->lerp_origin, ent.origin, rt_rocket, ent.keynum, NULL, &cent->trailstate))
{
P_ParticleTrailIndex(cent->lerp_origin, ent.origin, 0xdc, 4, &cent->trailstate);
P_ParticleTrailIndex(cent->lerp_origin, ent.origin, P_INVALID, 0xdc, 4, &cent->trailstate);
V_AddLight (ent.keynum, ent.origin, 200, 0.2, 0.1, 0.05);
}
}
@ -1988,7 +1988,7 @@ static void CLQ2_AddPacketEntities (q2frame_t *frame)
{
if (P_ParticleTrail(cent->lerp_origin, ent.origin, pt_q2[Q2RT_BLASTERTRAIL2], ent.keynum, NULL, &cent->trailstate))
{
P_ParticleTrailIndex(cent->lerp_origin, ent.origin, 0xd0, 1, &cent->trailstate);
P_ParticleTrailIndex(cent->lerp_origin, ent.origin, P_INVALID, 0xd0, 1, &cent->trailstate);
V_AddLight (ent.keynum, ent.origin, 200, 0, 0.2, 0);
}
}
@ -1996,7 +1996,7 @@ static void CLQ2_AddPacketEntities (q2frame_t *frame)
{
if (P_ParticleTrail(cent->lerp_origin, ent.origin, pt_q2[Q2RT_BLASTERTRAIL], ent.keynum, NULL, &cent->trailstate))
{
P_ParticleTrailIndex(cent->lerp_origin, ent.origin, 0xe0, 1, &cent->trailstate);
P_ParticleTrailIndex(cent->lerp_origin, ent.origin, P_INVALID, 0xe0, 1, &cent->trailstate);
V_AddLight (ent.keynum, ent.origin, 200, 0.2, 0.2, 0);
}
}
@ -2013,13 +2013,13 @@ static void CLQ2_AddPacketEntities (q2frame_t *frame)
{
if (P_ParticleTrail(cent->lerp_origin, ent.origin, pt_q2[Q2RT_GIB], ent.keynum, NULL, &cent->trailstate))
if (P_ParticleTrail(cent->lerp_origin, ent.origin, rt_blood, ent.keynum, NULL, &cent->trailstate))
P_ParticleTrailIndex(cent->lerp_origin, ent.origin, 0xe8, 8, &cent->trailstate);
P_ParticleTrailIndex(cent->lerp_origin, ent.origin, P_INVALID, 0xe8, 8, &cent->trailstate);
}
else if (effects & Q2EF_GRENADE)
{
if (P_ParticleTrail(cent->lerp_origin, ent.origin, pt_q2[Q2RT_GRENADE], ent.keynum, NULL, &cent->trailstate))
if (P_ParticleTrail(cent->lerp_origin, ent.origin, rt_grenade, ent.keynum, NULL, &cent->trailstate))
P_ParticleTrailIndex(cent->lerp_origin, ent.origin, 4, 8, &cent->trailstate);
P_ParticleTrailIndex(cent->lerp_origin, ent.origin, P_INVALID, 4, 8, &cent->trailstate);
}
else if (effects & Q2EF_FLIES)
{
@ -2050,7 +2050,7 @@ static void CLQ2_AddPacketEntities (q2frame_t *frame)
{
if (P_ParticleTrail(cent->lerp_origin, ent.origin, pt_q2[Q2RT_FLAG1], ent.keynum, NULL, &cent->trailstate))
{
P_ParticleTrailIndex(cent->lerp_origin, ent.origin, 242, 1, &cent->trailstate);
P_ParticleTrailIndex(cent->lerp_origin, ent.origin, P_INVALID, 242, 1, &cent->trailstate);
V_AddLight (ent.keynum, ent.origin, 225, 0.2, 0.05, 0.05);
}
}
@ -2058,7 +2058,7 @@ static void CLQ2_AddPacketEntities (q2frame_t *frame)
{
if (P_ParticleTrail(cent->lerp_origin, ent.origin, pt_q2[Q2RT_FLAG2], ent.keynum, NULL, &cent->trailstate))
{
P_ParticleTrailIndex(cent->lerp_origin, ent.origin, 115, 1, &cent->trailstate);
P_ParticleTrailIndex(cent->lerp_origin, ent.origin, P_INVALID, 115, 1, &cent->trailstate);
V_AddLight (ent.keynum, ent.origin, 225, 0.05, 0.05, 0.2);
}
}
@ -2068,7 +2068,7 @@ static void CLQ2_AddPacketEntities (q2frame_t *frame)
{
if (P_ParticleTrail(cent->lerp_origin, ent.origin, pt_q2[Q2RT_TAGTRAIL], ent.keynum, NULL, &cent->trailstate))
{
P_ParticleTrailIndex(cent->lerp_origin, ent.origin, 220, 1, &cent->trailstate);
P_ParticleTrailIndex(cent->lerp_origin, ent.origin, P_INVALID, 220, 1, &cent->trailstate);
V_AddLight (ent.keynum, ent.origin, 225, 0.2, 0.2, 0.0);
}
}
@ -2093,7 +2093,7 @@ static void CLQ2_AddPacketEntities (q2frame_t *frame)
{
if (P_ParticleTrail(cent->lerp_origin, ent.origin, pt_q2[Q2RT_TRACKER], ent.keynum, NULL, &cent->trailstate))
{
P_ParticleTrailIndex(cent->lerp_origin, ent.origin, 0, 1, &cent->trailstate);
P_ParticleTrailIndex(cent->lerp_origin, ent.origin, P_INVALID, 0, 1, &cent->trailstate);
V_AddLight (ent.keynum, ent.origin, 200, -0.2, -0.2, -0.2);
}
}
@ -2103,14 +2103,14 @@ static void CLQ2_AddPacketEntities (q2frame_t *frame)
else if (effects & Q2EF_GREENGIB)
{
if (P_ParticleTrail(cent->lerp_origin, ent.origin, pt_q2[Q2RT_GREENGIB], ent.keynum, NULL, &cent->trailstate))
P_ParticleTrailIndex(cent->lerp_origin, ent.origin, 219, 8, &cent->trailstate);
P_ParticleTrailIndex(cent->lerp_origin, ent.origin, P_INVALID, 219, 8, &cent->trailstate);
}
// RAFAEL
else if (effects & Q2EF_IONRIPPER)
{
if (P_ParticleTrail(cent->lerp_origin, ent.origin, pt_q2[Q2RT_IONRIPPER], ent.keynum, NULL, &cent->trailstate))
{
P_ParticleTrailIndex(cent->lerp_origin, ent.origin, 228, 4, &cent->trailstate);
P_ParticleTrailIndex(cent->lerp_origin, ent.origin, P_INVALID, 228, 4, &cent->trailstate);
V_AddLight (ent.keynum, ent.origin, 100, 0.2, 0.1, 0.1);
}
}

View File

@ -4135,6 +4135,12 @@ static qboolean Image_GenMip0(struct pendingtextureinfo *mips, unsigned int flag
case PTI_BGRA8:
mips->encoding = PTI_BGRX8;
break;
case PTI_RGBA8_SRGB:
mips->encoding = PTI_RGBX8_SRGB;
break;
case PTI_BGRA8_SRGB:
mips->encoding = PTI_BGRX8_SRGB;
break;
case PTI_RGBA16F:
case PTI_RGBA32F:
case PTI_ARGB4444:
@ -4153,6 +4159,8 @@ static qboolean Image_GenMip0(struct pendingtextureinfo *mips, unsigned int flag
case PTI_RGB565:
case PTI_RGBX8:
case PTI_BGRX8:
case PTI_RGBX8_SRGB:
case PTI_BGRX8_SRGB:
case PTI_S3RGB1:
break; //already no alpha in these formats
case PTI_DEPTH16:
@ -4276,6 +4284,7 @@ static qboolean Image_LoadRawTexture(texid_t tex, unsigned int flags, void *rawd
tex->width = imgwidth;
tex->height = imgheight;
//d3d9 needs to reconfigure samplers depending on whether the data is srgb or not.
tex->flags &= ~IF_SRGB;
switch(mips->encoding)
{
@ -4285,6 +4294,8 @@ static qboolean Image_LoadRawTexture(texid_t tex, unsigned int flags, void *rawd
case PTI_BGRX8_SRGB:
tex->flags |= IF_SRGB;
break;
default:
break;
}
if (flags & IF_NOWORKER)

View File

@ -891,6 +891,18 @@ void Key_DefaultLinkClicked(console_t *con, char *text, char *info)
Cbuf_AddText(va("\ncmd %s\n", c), RESTRICT_LOCAL);
return;
}
c = Info_ValueForKey(info, "say");
if (*c && !strchr(c, ';') && !strchr(c, '\n'))
{
Cbuf_AddText(va("\nsay %s\n", c), RESTRICT_LOCAL);
return;
}
c = Info_ValueForKey(info, "echo");
if (*c)
{
Con_Printf("%s\n", c);
return;
}
c = Info_ValueForKey(info, "dir");
if (*c && !strchr(c, ';') && !strchr(c, '\n'))
{
@ -2215,8 +2227,8 @@ void Key_Init (void)
key_linepos = 0;
key_dest_mask = kdm_game;
key_dest_absolutemouse = kdm_console | kdm_editor | kdm_cwindows | kdm_emenu;
key_dest_absolutemouse = kdm_centerprint | kdm_console | kdm_editor | kdm_cwindows | kdm_emenu;
//
// init ascii characters in console mode
//
@ -2625,6 +2637,10 @@ void Key_Event (unsigned int devid, int key, unsigned int unicode, qboolean down
return;
}
if (Key_Dest_Has(kdm_centerprint))
if (Key_Centerprint(key, unicode, devid))
return;
//anything else is a key binding.
/*don't auto-repeat binds as it breaks too many scripts*/

View File

@ -252,12 +252,13 @@ K_MAX
typedef enum //highest has priority
{
kdm_game = 1u<<0, //should always be set
kdm_message = 1u<<1,
kdm_gmenu = 1u<<2, //menu.dat
kdm_emenu = 1u<<3, //engine's menus
kdm_editor = 1u<<4,
kdm_console = 1u<<5,
kdm_cwindows = 1u<<6,
kdm_centerprint = 1u<<1, //enabled when there's a centerprint menu with clickable things.
kdm_message = 1u<<2,
kdm_gmenu = 1u<<3, //menu.dat
kdm_emenu = 1u<<4, //engine's menus
kdm_editor = 1u<<5,
kdm_console = 1u<<6,
kdm_cwindows = 1u<<7,
} keydestmask_t;
//unsigned int Key_Dest_Get(void); //returns highest priority destination
@ -299,8 +300,10 @@ void IN_WriteButtons(vfsfile_t *f, qboolean all);
void Key_WriteBindings (struct vfsfile_s *f);
void Key_SetBinding (int keynum, int modifier, char *binding, int cmdlevel);
void Key_ClearStates (void);
qboolean Key_Centerprint(int key, int unicode, unsigned int devid);
void Key_Unbindall_f (void); //aka: Key_Shutdown
void Key_ConsoleReplace(const char *instext);
void Key_DefaultLinkClicked(console_t *con, char *text, char *info);
struct console_s;
qboolean Key_GetConsoleSelectionBox(struct console_s *con, int *sx, int *sy, int *ex, int *ey);

View File

@ -141,6 +141,7 @@ void R_DrawTextField(int x, int y, int w, int h, const char *text, unsigned int
#define CPRINT_OBITUARTY (1<<16) //O (show at 2/3rds from top)
#define CPRINT_PERSIST (1<<17) //P (doesn't time out)
#define CPRINT_TYPEWRITER (1<<18) // (char at a time)
#define CPRINT_CURSOR (1<<19) //C (use a mouse cursor, also enabled by the presence of a (auto) link)
#endif

View File

@ -257,7 +257,7 @@ static void PClassic_RunParticleEffect4 (vec3_t org, float radius, int color, in
}
//this function is used as a fallback in case a trail effect is unknown.
static void PClassic_ParticleTrailIndex (vec3_t start, vec3_t end, int color, int crnd, trailstate_t **tsk)
static void PClassic_ParticleTrailIndex (vec3_t start, vec3_t end, int type, int color, int crnd, trailstate_t **tsk)
{
}

View File

@ -22,7 +22,7 @@ static void PNULL_RunParticleEffect3 (vec3_t org, vec3_t box, int color, int eff
static void PNULL_RunParticleEffect4 (vec3_t org, float radius, int color, int effect, int count){}
static void PNULL_RunParticleEffectPalette (const char *nameprefix, vec3_t org, vec3_t dir, int color, int count){}
static void PNULL_ParticleTrailIndex (vec3_t start, vec3_t end, int color, int crnd, trailstate_t **tsk){}
static void PNULL_ParticleTrailIndex (vec3_t start, vec3_t end, int type, int color, int crnd, trailstate_t **tsk){}
static qboolean PNULL_InitParticles (void)
{

View File

@ -5987,13 +5987,15 @@ static int PScript_ParticleTrail (vec3_t startpos, vec3_t end, int type, int dlk
return 0;
}
static void PScript_ParticleTrailIndex (vec3_t start, vec3_t end, int color, int crnd, trailstate_t **tsk)
static void PScript_ParticleTrailIndex (vec3_t start, vec3_t end, int type, int color, int crnd, trailstate_t **tsk)
{
if (PART_VALID(pe_defaulttrail))
if (type == P_INVALID)
type = pe_defaulttrail;
if (PART_VALID(type))
{
part_type[pe_defaulttrail].colorindex = color;
part_type[pe_defaulttrail].colorrand = crnd;
P_ParticleTrail(start, end, pe_defaulttrail, 0, NULL, tsk);
part_type[type].colorindex = color;
part_type[type].colorrand = crnd;
P_ParticleTrail(start, end, type, 0, NULL, tsk);
}
}

View File

@ -4704,7 +4704,7 @@ void CSQC_EntStateToCSQC(unsigned int flags, float lerptime, entity_state_t *src
{
if (model->particletrail == P_INVALID || pe->ParticleTrail (ent->v->origin, src->origin, model->particletrail, src->number, NULL, &(le->trailstate)))
if (model->traildefaultindex >= 0)
pe->ParticleTrailIndex(ent->v->origin, src->origin, model->traildefaultindex, 0, &(le->trailstate));
pe->ParticleTrailIndex(ent->v->origin, src->origin, P_INVALID, model->traildefaultindex, 0, &(le->trailstate));
}
}

View File

@ -183,6 +183,8 @@ void R2D_Init(void)
extern cvar_t gl_specular_fallback, gl_specular_fallbackexp, gl_texturemode;
conback = NULL;
Cvar_ForceCallback(&gl_texturemode);
draw_mesh.istrifan = true;
draw_mesh.numvertexes = 4;
draw_mesh.numindexes = 6;
@ -377,7 +379,6 @@ void R2D_Init(void)
Cvar_ForceCallback(&gl_conback);
Cvar_ForceCallback(&vid_conautoscale);
Cvar_ForceCallback(&gl_font);
Cvar_ForceCallback(&gl_texturemode);
Cvar_ForceCallback(&crosshair);
Cvar_ForceCallback(&crosshaircolor);

View File

@ -3442,21 +3442,6 @@ char *particle_set_q2part =
"scalefactor 0.8\n"
"}\n"
"r_part TEQ2_LASER_SPARKS\n"
"{\n"
"texture \"classicparticle\"\n"
"tcoords 0 0 16 16 32\n"
"count 1\n"
"scale 1\n"
"alpha 1\n"
"die 0.3 0.8\n"
"randomvel 20\n"
"orgadd 0 7\n"
"spawnorg 4\n"
"gravity 40\n"
"scalefactor 0.8\n"
"}\n"
"r_part te_splashsparks\n"
"{\n"
"texture \"classicparticle\"\n"
@ -3567,7 +3552,56 @@ char *particle_set_q2part =
"colorindex 0xe8\n"
"}\n"
"r_part teq2_laser_sparks\n"
"{\n"
"texture \"classicparticle\"\n"
"tcoords 0 0 16 16 32\n"
"count 1\n"
"scale 1\n"
"alpha 1\n"
"die 0.3 0.8\n"
"randomvel 20\n"
"orgadd 0 7\n"
"spawnorg 4\n"
"gravity 40\n"
"scalefactor 0.8\n"
"}\n"
"r_part teq2_welding_sparks\n"
"{ //identical to teq2_laser_sparks, except for the +form that adds in some extra mesh+lighting effect.\n"
"texture \"classicparticle\"\n"
"tcoords 0 0 16 16 32\n"
"count 1\n"
"scale 1\n"
"alpha 1\n"
"die 0.3 0.8\n"
"randomvel 20\n"
"orgadd 0 7\n"
"spawnorg 4\n"
"gravity 40\n"
"scalefactor 0.8\n"
"}\n"
"r_part +teq2_welding_sparks\n"
"{\n"
"count 0 0 1\n"
"model \"models/objects/flash/tris.md2\" framestart=0 frameend=2 framerate=10 alpha=-1 fullbright\n"
"lightradius 100 175\n"
"lightradiusfade 400\n"
"lightrgb 1 1 0.3\n"
"}\n"
"r_part teq2_tunnel_sparks\n"
"{ //this is apparently identical to teq2_laser_sparks... either way the protocol provides a palette colour (particle system provides a customised variation)\n"
"texture \"classicparticle\"\n"
"tcoords 0 0 16 16 32\n"
"count 1\n"
"scale 1\n"
"alpha 1\n"
"die 0.3 0.8\n"
"randomvel 20\n"
"orgadd 0 7\n"
"spawnorg 4\n"
"gravity 40\n"
"scalefactor 0.8\n"
"}\n"
"r_part teq2_shield_sparks\n"
"{\n"
"texture \"classicparticle\"\n"
@ -3682,11 +3716,68 @@ char *particle_set_q2part =
"scalefactor 0.8\n"
"colorindex 232 7\n"
"}\n"
"r_part teq2_moreblood\n"
"{ //teq2_blood, but with count 250 instead of 60.\n"
"texture \"classicparticle\"\n"
"tcoords 0 0 16 16 32\n"
"count 250\n"
"scale 1\n"
"alpha 1\n"
"die 0.3 0.8\n"
"randomvel 20\n"
"orgadd 0 31\n"
"spawnorg 4\n"
"gravity 40\n"
"scalefactor 0.8\n"
"colorindex 232 7\n"
"}\n"
"r_part teq2_greenblood\n"
"{\n"
"texture \"classicparticle\"\n"
"tcoords 0 0 16 16 32\n"
"count 30\n"
"scale 1\n"
"alpha 1\n"
"die 0.3 0.8\n"
"randomvel 20\n"
"orgadd 0 31\n"
"spawnorg 4\n"
"gravity 40\n"
"scalefactor 0.8\n"
"colorindex 0xdf 7\n"
"}\n"
"r_part teq2_electric_sparks\n"
"{\n"
"texture \"classicparticle\"\n"
"tcoords 0 0 16 16 32\n"
"count 40\n"
"scale 1\n"
"alpha 1\n"
"die 0.3 0.8\n"
"randomvel 20\n"
"orgadd 0 31\n"
"spawnorg 4\n"
"gravity 40\n"
"scalefactor 0.8\n"
"colorindex 0x75 7\n"
"sound \"weapons/lashit.wav\" 1 1 0 0\n"
"}\n"
"r_part q2_blasterpuff\n"
"{\n"
"count 0 0 1\n"
"model \"models/objects/explode/tris.md2\" framestart=0 frameend=4 framerate=10 alpha=1 orient additive fullbright noshadow\n"
"model \"models/objects/explode/tris.md2\" framestart=0 frameend=4 framerate=10 alpha=1 orient additive fullbright noshadow skin=0\n"
"}\n"
"r_part q2_blaster2puff\n"
"{\n"
"count 0 0 1\n"
"model \"models/objects/explode/tris.md2\" framestart=0 frameend=4 framerate=10 alpha=1 orient additive fullbright noshadow skin=1\n"
"}\n"
"r_part q2_flechettepuff\n"
"{\n"
"count 0 0 1\n"
"model \"models/objects/explode/tris.md2\" framestart=0 frameend=4 framerate=10 alpha=1 orient additive fullbright noshadow skin=2\n"
"}\n"
"r_part teq2_blaster\n"
"{\n"
@ -3725,13 +3816,35 @@ char *particle_set_q2part =
"gravity 40\n"
"scalefactor 0.8\n"
"colorindex 0xd0 7\n"
"assoc q2_blasterpuff /*the model*/\n"
"assoc q2_blaster2puff /*the model*/\n"
"lightradius 150\n"
"lightradiusfade 400\n"
"lightrgb 0.05 1.0 0.05\n"
"lightshadows 1\n"
"sound \"weapons/lashit.wav\" 1 1 0 0\n"
"}\n"
"r_part teq2_flechette\n"
"{ //grey version.\n"
"texture \"classicparticle\"\n"
"tcoords 0 0 16 16 32\n"
"count 60\n"
"scale 1\n"
"alpha 1\n"
"die 0.3 0.8\n"
"randomvel 40\n"
"orgadd 0 15\n"
"veladd 30\n"
"spawnorg 4\n"
"gravity 40\n"
"scalefactor 0.8\n"
"colorindex 0x6f 7\n"
"assoc q2_flechettepuff /*the model*/\n"
"lightradius 150\n"
"lightradiusfade 400\n"
"lightrgb 0.19 0.41 0.75\n"
"lightshadows 1\n"
"sound \"weapons/lashit.wav\" 1 1 0 0\n"
"}\n"
"r_part TR_BLASTERTRAIL\n"
"{\n"
"texture \"classicparticle\"\n"

View File

@ -2338,20 +2338,12 @@ void Surf_SetupFrame(void)
}
else if (!cl.worldmodel || cl.worldmodel->loadstate != MLS_LOADED || cl.worldmodel->fromgame == fg_doom3 )
{
r_viewleaf = NULL;
r_viewleaf2 = NULL;
r_viewcluster = -1;
r_viewcluster2 = -1;
}
#ifdef Q2BSPS
else if (cl.worldmodel->fromgame == fg_quake2 || cl.worldmodel->fromgame == fg_quake3)
{
static mleaf_t fakeleaf;
mleaf_t *leaf;
//FIXME: do we still need this fakeleaf stuff?
r_viewleaf = &fakeleaf;
r_viewleaf->contents = Q1CONTENTS_EMPTY;
r_viewleaf2 = NULL;
leaf = Mod_PointInLeaf (cl.worldmodel, pvsorg);
viewcontents = cl.worldmodel->funcs.PointContents(cl.worldmodel, NULL, pvsorg);
r_viewcluster = r_viewcluster2 = leaf->cluster;
@ -2383,38 +2375,12 @@ void Surf_SetupFrame(void)
#endif
else
{
r_viewleaf = Mod_PointInLeaf (cl.worldmodel, pvsorg);
if (!r_viewleaf)
leaf = Mod_PointInLeaf (cl.worldmodel, pvsorg);
r_viewcluster = (leaf - cl.worldmodel->leafs)-1;
r_viewcluster2 = -1;
if (leaf)
{
}
else if (r_viewleaf->contents == Q1CONTENTS_EMPTY)
{ //look down a bit
VectorCopy (pvsorg, temp);
temp[2] -= 16;
leaf = Mod_PointInLeaf (cl.worldmodel, temp);
if (leaf->contents <= Q1CONTENTS_WATER && leaf->contents >= Q1CONTENTS_LAVA)
r_viewleaf2 = leaf;
else
r_viewleaf2 = NULL;
}
else if (r_viewleaf->contents <= Q1CONTENTS_WATER && r_viewleaf->contents >= Q1CONTENTS_LAVA)
{ //in water, look up a bit.
VectorCopy (pvsorg, temp);
temp[2] += 16;
leaf = Mod_PointInLeaf (cl.worldmodel, temp);
if (leaf->contents == Q1CONTENTS_EMPTY)
r_viewleaf2 = leaf;
else
r_viewleaf2 = NULL;
}
else
r_viewleaf2 = NULL;
if (r_viewleaf)
{
switch(r_viewleaf->contents)
switch(leaf->contents)
{
case Q1CONTENTS_WATER:
viewcontents |= FTECONTENTS_WATER;
@ -2435,6 +2401,24 @@ void Surf_SetupFrame(void)
viewcontents |= FTECONTENTS_LADDER;
break;
}
if (leaf->contents == Q1CONTENTS_EMPTY)
{ //look down a bit
VectorCopy (pvsorg, temp);
temp[2] -= 16;
leaf = Mod_PointInLeaf (cl.worldmodel, temp);
if (leaf->contents <= Q1CONTENTS_WATER && leaf->contents >= Q1CONTENTS_LAVA)
r_viewcluster2 = (leaf - cl.worldmodel->leafs)-1;
}
else if (leaf->contents <= Q1CONTENTS_WATER && leaf->contents >= Q1CONTENTS_LAVA)
{ //in water, look up a bit.
VectorCopy (pvsorg, temp);
temp[2] += 16;
leaf = Mod_PointInLeaf (cl.worldmodel, temp);
if (leaf->contents == Q1CONTENTS_EMPTY)
r_viewcluster2 = (leaf - cl.worldmodel->leafs)-1;
}
}
}
@ -2617,7 +2601,6 @@ struct webostate_s
{
char dbgid[12];
model_t *wmodel;
mleaf_t *leaf[2];
int cluster[2];
pvsbuffer_t pvs;
vboarray_t ebo;
@ -2859,30 +2842,23 @@ void R_GenWorldEBO(void *ctx, void *data, size_t a, size_t b)
es->batches[i].idxbuffer = NULL;
}
//maybe we should just use fatpvs instead, and wait for completion when outside?
if (es->cluster[1] != -1 && es->cluster[0] != es->cluster[1])
{ //view is near to a water boundary. this implies the water crosses the near clip plane. we need both leafs.
pvs = es->wmodel->funcs.ClusterPVS(es->wmodel, es->cluster[0], &es->pvs, PVM_REPLACE);
pvs = es->wmodel->funcs.ClusterPVS(es->wmodel, es->cluster[1], &es->pvs, PVM_MERGE);
}
else
pvs = es->wmodel->funcs.ClusterPVS(es->wmodel, es->cluster[0], &es->pvs, PVM_FAST);
#if defined(Q2BSPS) || defined(Q3BSPS)
if (es->wmodel->fromgame == fg_quake2 || es->wmodel->fromgame == fg_quake3)
{
if (es->cluster[1] != -1 && es->cluster[0] != es->cluster[1]) //view is near to a water boundary. this implies the water crosses the near clip plane.
{
pvs = es->wmodel->funcs.ClusterPVS(es->wmodel, es->cluster[0], &es->pvs, PVM_REPLACE);
pvs = es->wmodel->funcs.ClusterPVS(es->wmodel, es->cluster[1], &es->pvs, PVM_MERGE);
}
else
pvs = es->wmodel->funcs.ClusterPVS(es->wmodel, es->cluster[0], &es->pvs, PVM_FAST);
Surf_SimpleWorld_Q3BSP(es, pvs);
}
else
#endif
#ifdef Q1BSPS
if (es->wmodel->fromgame == fg_quake || es->wmodel->fromgame == fg_halflife)
{
//maybe we should just use fatpvs instead, and wait for completion when outside?
pvs = Q1BSP_LeafPVS (es->wmodel, es->leaf[0], &es->pvs, false);
if (es->leaf[1]) //view is near to a water boundary. this implies the water crosses the near clip plane.
pvs = Q1BSP_LeafPVS (es->wmodel, es->leaf[1], &es->pvs, true);
Surf_SimpleWorld_Q1BSP(es, pvs);
}
else
#endif
{
@ -2899,11 +2875,11 @@ R_DrawWorld
=============
*/
static pvsbuffer_t surf_frustumvis;
void Surf_DrawWorld (void)
{
//surfvis vs entvis - the key difference is that surfvis is surfaces while entvis is volume. though surfvis should be frustum culled also for lighting. entvis doesn't care.
qbyte *surfvis, *entvis;
static pvsbuffer_t frustumvis_;
RSpeedLocals();
if (r_refdef.flags & RDF_NOWORLDMODEL)
@ -2948,7 +2924,7 @@ void Surf_DrawWorld (void)
if (webostate->lightstylevalues[i] != d_lightstylevalue[i])
break;
}
if (webostate && webostate->leaf[0] == r_viewleaf && webostate->leaf[1] == r_viewleaf2 && i == MAX_LIGHTSTYLES)
if (webostate && webostate->cluster[0] == r_viewcluster && webostate->cluster[1] == r_viewcluster2 && i == MAX_LIGHTSTYLES)
{
}
else
@ -2971,8 +2947,8 @@ void Surf_DrawWorld (void)
webogeneratingstate = true;
webogenerating = BZ_Malloc(sizeof(*webogenerating) + sizeof(webogenerating->batches[0]) * (currentmodel->numbatches-1) + currentmodel->pvsbytes);
webogenerating->wmodel = currentmodel;
webogenerating->leaf[0] = r_viewleaf;
webogenerating->leaf[1] = r_viewleaf2;
webogenerating->cluster[0] = r_viewcluster;
webogenerating->cluster[1] = r_viewcluster2;
webogenerating->pvs.buffer = (qbyte*)(webogenerating+1) + sizeof(webogenerating->batches[0])*(currentmodel->numbatches-1);
webogenerating->pvs.buffersize = currentmodel->pvsbytes;
for (i = 0; i < MAX_LIGHTSTYLES; i++)
@ -3056,9 +3032,9 @@ void Surf_DrawWorld (void)
#if defined(Q2BSPS) || defined(Q3BSPS)
if (currentmodel->fromgame == fg_quake2 || currentmodel->fromgame == fg_quake3)
{
if (frustumvis_.buffersize < currentmodel->pvsbytes)
frustumvis_.buffer = BZ_Realloc(frustumvis_.buffer, frustumvis_.buffersize=currentmodel->pvsbytes);
frustumvis = frustumvis_.buffer;
if (surf_frustumvis.buffersize < currentmodel->pvsbytes)
surf_frustumvis.buffer = BZ_Realloc(surf_frustumvis.buffer, surf_frustumvis.buffersize=currentmodel->pvsbytes);
frustumvis = surf_frustumvis.buffer;
memset(frustumvis, 0, currentmodel->pvsbytes);
if (!r_refdef.areabitsknown)
@ -3121,9 +3097,9 @@ void Surf_DrawWorld (void)
if (!(r_novis.ival & 2))
VectorCopy (r_origin, modelorg);
if (frustumvis_.buffersize < currentmodel->pvsbytes)
frustumvis_.buffer = BZ_Realloc(frustumvis_.buffer, frustumvis_.buffersize=currentmodel->pvsbytes);
frustumvis = frustumvis_.buffer;
if (surf_frustumvis.buffersize < currentmodel->pvsbytes)
surf_frustumvis.buffer = BZ_Realloc(surf_frustumvis.buffer, surf_frustumvis.buffersize=currentmodel->pvsbytes);
frustumvis = surf_frustumvis.buffer;
memset(frustumvis, 0, currentmodel->pvsbytes);
if (r_refdef.useperspective)
@ -3200,6 +3176,9 @@ void Surf_DeInit(void)
if (lightmap)
BZ_Free(lightmap);
Z_Free(surf_frustumvis.buffer);
memset(&surf_frustumvis, 0, sizeof(surf_frustumvis));
lightmap=NULL;
numlightmaps=0;
@ -3655,8 +3634,6 @@ void Surf_BuildLightmaps (void)
Surf_LightmapMode();
r_oldviewleaf = NULL;
r_oldviewleaf2 = NULL;
r_oldviewcluster = -1;
r_oldviewcluster2 = -1;
@ -3700,11 +3677,10 @@ void Surf_NewMap (void)
Surf_DeInit();
r_viewleaf = NULL;
r_oldviewleaf = NULL;
r_viewcluster = -1;
r_oldviewcluster = 0;
r_viewcluster2 = -1;
r_oldviewcluster2 = 0;
if (cl.worldmodel)
{
@ -3768,10 +3744,10 @@ void Surf_PreNewMap(void)
#ifdef RTLIGHTS
r_loadbumpmapping |= r_shadow_realtime_world.ival || r_shadow_realtime_dlight.ival;
#endif
r_viewleaf = NULL;
r_oldviewleaf = NULL;
r_viewleaf2 = NULL;
r_oldviewleaf2 = NULL;
r_viewcluster = -1;
r_oldviewcluster = -1;
r_viewcluster2 = -1;
r_oldviewcluster2 = -1;
}

View File

@ -49,10 +49,25 @@ void QDECL R_SkyBox_Changed (struct cvar_s *var, char *oldvalue)
{
if (qrenderer != QR_NONE && cl.worldmodel)
{
if (*var->string)
R_SetSky(var->string);
R_SetSky(cl.skyname);
}
}
void R_ForceSky_f(void)
{
if (Cmd_Argc() < 2)
{
extern cvar_t r_skyboxname;
if (*r_skyboxname.string)
Con_Printf("Current user skybox is %s\n", cl.skyname);
else if (*cl.skyname)
Con_Printf("Current per-map skybox is %s\n", cl.skyname);
else
R_SetSky(cl.skyname);
Con_Printf("no skybox forced.\n", cl.skyname);
}
else
{
Q_strncpyz(cl.skyname, Cmd_Argv(1), sizeof(cl.skyname));
R_SetSky(cl.skyname);
}
}
@ -233,6 +248,7 @@ cvar_t vid_conwidth = CVARF ("vid_conwidth", "0",
//see R_RestartRenderer_f for the effective default 'if (newr.renderer == -1)'.
cvar_t vid_renderer = CVARFD ("vid_renderer", "",
CVAR_ARCHIVE | CVAR_RENDERERLATCH, "Specifies which backend is used. Values that might work are: sv (dedicated server), headless (null renderer), vk (vulkan), gl (opengl), egl (opengl es), d3d9 (direct3d 9), d3d11 (direct3d 11, with default hardware rendering), d3d11 warp (direct3d 11, with software rendering).");
cvar_t vid_renderer_opts = CVARFD ("_vid_renderer_opts", "", CVAR_NOSET, "The possible video renderer apis, in \"value\" \"description\" pairs, for gamecode to read.");
cvar_t vid_bpp = CVARFD ("vid_bpp", "0",
CVAR_ARCHIVE | CVAR_RENDERERLATCH, "The number of colour bits to request from the renedering context");
@ -251,12 +267,15 @@ cvar_t vid_fullscreen_alternative = CVARFD (NULL, "1",
cvar_t vid_height = CVARFD ("vid_height", "0",
CVAR_ARCHIVE | CVAR_RENDERERLATCH, "The screen height to attempt to use, in physical pixels. 0 means use desktop resolution.");
cvar_t vid_multisample = CVARFD ("vid_multisample", "0",
CVAR_ARCHIVE | CVAR_RENDERERLATCH, "Set to 4 or so for multisample antialiasing (msaa).");
CVAR_ARCHIVE, "The number of samples to use for Multisample AntiAliasing (aka: msaa). A value of 1 explicitly disables it.");
cvar_t vid_refreshrate = CVARF ("vid_displayfrequency", "0",
CVAR_ARCHIVE | CVAR_RENDERERLATCH);
cvar_t vid_srgb = CVARFD ("vid_srgb", "0",
CVAR_ARCHIVE, "0: Off. Colour blending will be wrong.\n1: Only the framebuffer should use sRGB colourspace, textures and colours will be assumed to be linear. This has the effect of brightening the screen.\n2: Use sRGB extensions/support to ensure that the sh");
cvar_t vid_wndalpha = CVARD ("vid_wndalpha", "1", "When running windowed, specifies the window's transparency level.");
#if defined(_WIN32) && defined(MULTITHREAD)
cvar_t vid_winthread = CVARFD ("vid_winthread", "", CVAR_ARCHIVE|CVAR_RENDERERLATCH, "When enabled, window messages will be handled by a separate thread. This allows the game to continue rendering when Microsoft Windows blocks while resizing etc.");
#endif
//more readable defaults to match conwidth/conheight.
cvar_t vid_width = CVARFD ("vid_width", "0",
CVAR_ARCHIVE | CVAR_RENDERERLATCH, "The screen width to attempt to use, in physical pixels. 0 means use desktop resolution.");
@ -426,11 +445,15 @@ cvar_t gl_screenangle = CVAR("gl_screenangle", "0");
#endif
#ifdef VKQUAKE
cvar_t vk_stagingbuffers = CVARD ("vk_stagingbuffers", "", "Configures which dynamic buffers are copied into gpu memory for rendering, instead of reading from shared memory. Empty for default settings.\nAccepted chars are u, e, v, 0.");
cvar_t vk_submissionthread = CVARD ("vk_submissionthread", "", "Execute submits+presents on a thread dedicated to executing them. This may be a significant speedup on certain drivers.");
cvar_t vk_debug = CVARD ("vk_debug", "0", "Register a debug handler to display driver/layer messages. 2 enables the standard validation layers.");
cvar_t vk_loadglsl = CVARD ("vk_loadglsl", "", "Enable direct loading of glsl, where supported by drivers. Do not use in combination with vk_debug 2 (vk_debug should be 1 if you want to see any glsl compile errors). Don't forget to do a vid_restart after.");
cvar_t vk_dualqueue = CVARD ("vk_dualqueue", "", "Attempt to use a separate queue for presentation. Blank for default.");
cvar_t vk_stagingbuffers = CVARD ("vk_stagingbuffers", "", "Configures which dynamic buffers are copied into gpu memory for rendering, instead of reading from shared memory. Empty for default settings.\nAccepted chars are u, e, v, 0.");
cvar_t vk_submissionthread = CVARD ("vk_submissionthread", "", "Execute submits+presents on a thread dedicated to executing them. This may be a significant speedup on certain drivers.");
cvar_t vk_debug = CVARD ("vk_debug", "0", "Register a debug handler to display driver/layer messages. 2 enables the standard validation layers.");
cvar_t vk_dualqueue = CVARD ("vk_dualqueue", "", "Attempt to use a separate queue for presentation. Blank for default.");
cvar_t vk_busywait = CVARD ("vk_busywait", "", "Force busy waiting until the GPU finishes doing its thing.");
cvar_t vk_nv_glsl_shader = CVARD ("vk_loadglsl", "", "Enable direct loading of glsl, where supported by drivers. Do not use in combination with vk_debug 2 (vk_debug should be 1 if you want to see any glsl compile errors). Don't forget to do a vid_restart after.");
cvar_t vk_nv_dedicated_allocation = CVARD ("vk_nv_dedicated_allocation", "", "Flag vulkan memory allocations as dedicated, where applicable.");
//cvar_t vk_khr_dedicated_allocation = CVARD ("vk_khr_dedicated_allocation", "", "Flag vulkan memory allocations as dedicated, where applicable.");
cvar_t vk_khr_push_descriptor = CVARD ("vk_khr_push_descriptor", "", "Enables better descriptor streaming.");
#endif
#if defined(D3DQUAKE)
@ -709,9 +732,33 @@ void Renderer_Init(void)
//but register ALL vid_ commands.
Cvar_Register (&gl_driver, GLRENDEREROPTIONS);
Cvar_Register (&vid_vsync, VIDCOMMANDGROUP);
Cvar_Register (&vid_wndalpha, VIDCOMMANDGROUP);
#if defined(_WIN32) && defined(MULTITHREAD)
Cvar_Register (&vid_winthread, VIDCOMMANDGROUP);
#endif
Cvar_Register (&_windowed_mouse, VIDCOMMANDGROUP);
Cvar_Register (&vid_renderer, VIDCOMMANDGROUP);
Cvar_Register (&vid_wndalpha, VIDCOMMANDGROUP);
vid_renderer_opts.enginevalue =
#ifdef GLQUAKE
"gl \"OpenGL\" "
#endif
#ifdef VKQUAKE
"vk \"Vulkan\" "
#endif
#ifdef D3D8QUAKE
// "d3d8 \"Direct3D 8\" "
#endif
#ifdef D3D9QUAKE
"d3d9 \"Direct3D 9\" "
#endif
#ifdef D3D11QUAKE
"d3d11 \"Direct3D 11\" "
#endif
#ifdef SWQUAKE
"sw \"Software Rendering\" "
#endif
"";
Cvar_Register (&vid_renderer_opts, VIDCOMMANDGROUP);
#ifndef NACL
if (COM_CheckParm("-plugin"))
@ -750,10 +797,12 @@ void Renderer_Init(void)
Cvar_Register (&r_norefresh, GLRENDEREROPTIONS);
Cvar_Register (&r_mirroralpha, GLRENDEREROPTIONS);
Cvar_Register (&r_skyboxname, GRAPHICALNICETIES);
Cbuf_AddText("alias sky r_skybox\n", RESTRICT_LOCAL); /*alternative name for users*/
Cvar_Register (&r_softwarebanding_cvar, GRAPHICALNICETIES);
Cvar_Register (&r_skyboxname, GRAPHICALNICETIES);
Cmd_AddCommand("sky", R_ForceSky_f); //QS compat
Cmd_AddCommand("loadsky", R_ForceSky_f);//DP compat
Cvar_Register(&r_dodgytgafiles, "Hacky bug workarounds");
Cvar_Register(&r_dodgypcxfiles, "Hacky bug workarounds");
Cvar_Register(&r_dodgymiptex, "Hacky bug workarounds");
@ -915,11 +964,16 @@ void Renderer_Init(void)
Cvar_Register (&r_forceprogramify, GLRENDEREROPTIONS);
#ifdef VKQUAKE
Cvar_Register (&vk_stagingbuffers, VKRENDEREROPTIONS);
Cvar_Register (&vk_submissionthread, VKRENDEREROPTIONS);
Cvar_Register (&vk_debug, VKRENDEREROPTIONS);
Cvar_Register (&vk_loadglsl, VKRENDEREROPTIONS);
Cvar_Register (&vk_dualqueue, VKRENDEREROPTIONS);
Cvar_Register (&vk_stagingbuffers, VKRENDEREROPTIONS);
Cvar_Register (&vk_submissionthread, VKRENDEREROPTIONS);
Cvar_Register (&vk_debug, VKRENDEREROPTIONS);
Cvar_Register (&vk_dualqueue, VKRENDEREROPTIONS);
Cvar_Register (&vk_busywait, VKRENDEREROPTIONS);
Cvar_Register (&vk_nv_glsl_shader, VKRENDEREROPTIONS);
Cvar_Register (&vk_nv_dedicated_allocation, VKRENDEREROPTIONS);
// Cvar_Register (&vk_khr_dedicated_allocation,VKRENDEREROPTIONS);
Cvar_Register (&vk_khr_push_descriptor, VKRENDEREROPTIONS);
#endif
// misc
@ -1966,9 +2020,14 @@ mspriteframe_t *R_GetSpriteFrame (entity_t *currententity)
}
else if (psprite->frames[frame].type == SPR_ANGLED)
{
float f = DotProduct(vpn,currententity->axis[0]);
float r = DotProduct(vright,currententity->axis[0]);
int dir = (atan2(r, f)+1.125*M_PI)*(4/M_PI);
pspritegroup = (mspritegroup_t *)psprite->frames[frame].frameptr;
// pspriteframe = pspritegroup->frames[(int)((r_refdef.viewangles[1]-currententity->angles[1])/360*pspritegroup->numframes + 0.5-4)%pspritegroup->numframes];
pspriteframe = pspritegroup->frames[(int)((r_refdef.viewangles[1]-currententity->angles[1])/360*8 + 0.5-4)&7];
//int dir = (int)((r_refdef.viewangles[1]-currententity->angles[1])/360*8 + 8 + 0.5-4)&7;
pspriteframe = pspritegroup->frames[dir&7];
}
else
{
@ -2125,8 +2184,8 @@ texture_t *R_TextureAnimation_Q2 (texture_t *base)
unsigned int r_viewcontents;
mleaf_t *r_viewleaf, *r_oldviewleaf;
mleaf_t *r_viewleaf2, *r_oldviewleaf2;
//mleaf_t *r_viewleaf, *r_oldviewleaf;
//mleaf_t *r_viewleaf2, *r_oldviewleaf2;
int r_viewcluster, r_viewcluster2, r_oldviewcluster, r_oldviewcluster2;
int r_visframecount;
mleaf_t *r_vischain; // linked list of visible leafs
@ -2357,23 +2416,23 @@ qbyte *R_MarkLeaves_Q1 (qboolean getvisonly)
{
vis = cvis[portal] = r_refdef.forcedvis;
r_oldviewleaf = NULL;
r_oldviewleaf2 = NULL;
r_oldviewcluster = -1;
r_oldviewcluster2 = -1;
}
else
{
if (!portal)
{
if (((r_oldviewleaf == r_viewleaf && r_oldviewleaf2 == r_viewleaf2) && !r_novis.ival) || r_novis.ival & 2)
if (((r_oldviewcluster == r_viewcluster && r_oldviewcluster2 == r_viewcluster2) && !r_novis.ival) || r_novis.ival & 2)
return cvis[portal];
r_oldviewleaf = r_viewleaf;
r_oldviewleaf2 = r_viewleaf2;
r_oldviewcluster = r_viewcluster;
r_oldviewcluster2 = r_viewcluster2;
}
else
{
r_oldviewleaf = NULL;
r_oldviewleaf2 = NULL;
r_oldviewcluster = -1;
r_oldviewcluster2 = -1;
}
if (r_novis.ival)
@ -2381,14 +2440,18 @@ qbyte *R_MarkLeaves_Q1 (qboolean getvisonly)
vis = cvis[portal] = curframevis[portal].buffer;
memset (curframevis[portal].buffer, 0xff, curframevis[portal].buffersize);
r_oldviewleaf = NULL;
r_oldviewleaf2 = NULL;
r_oldviewcluster = -1;
r_oldviewcluster2 = -1;
}
else
{
vis = cvis[portal] = Q1BSP_LeafPVS (cl.worldmodel, r_viewleaf, &curframevis[portal], false);
if (r_viewleaf2 && r_viewleaf2 != r_viewleaf)
vis = cvis[portal] = Q1BSP_LeafPVS (cl.worldmodel, r_viewleaf, &curframevis[portal], true);
if (r_viewcluster2 != -1 && r_viewcluster2 != r_viewcluster)
{
vis = cvis[portal] = cl.worldmodel->funcs.ClusterPVS(cl.worldmodel, r_viewcluster, &curframevis[portal], PVM_REPLACE);
vis = cvis[portal] = cl.worldmodel->funcs.ClusterPVS(cl.worldmodel, r_viewcluster2, &curframevis[portal], PVM_MERGE);
}
else
vis = cvis[portal] = cl.worldmodel->funcs.ClusterPVS(cl.worldmodel, r_viewcluster, &curframevis[portal], PVM_FAST);
}
}
@ -2396,7 +2459,7 @@ qbyte *R_MarkLeaves_Q1 (qboolean getvisonly)
if (getvisonly)
return vis;
else if (r_viewleaf && r_viewleaf->contents == Q1CONTENTS_SOLID)
else if (r_viewcluster == -1)
{
//to improve spectating, when the camera is in a wall, we ignore any sky leafs.
//this prevents seeing the upwards-facing sky surfaces within the sky volumes.

View File

@ -176,6 +176,7 @@ int Font_LineBreaks(conchar_t *start, conchar_t *end, int maxpixelwidth, int max
int Font_LineWidth(conchar_t *start, conchar_t *end);
float Font_LineScaleWidth(conchar_t *start, conchar_t *end);
void Font_LineDraw(int x, int y, conchar_t *start, conchar_t *end);
conchar_t *Font_CharAt(int x, conchar_t *start, conchar_t *end);
extern struct font_s *font_default;
extern struct font_s *font_console;
extern struct font_s *font_tiny;

View File

@ -316,15 +316,8 @@ typedef struct {
GUID SubFormat;
} QWAVEFORMATEX;
const static GUID QKSDATAFORMAT_SUBTYPE_PCM = {0x00000001,0x0000,0x0010,
{0x80,
0x00,
0x00,
0xaa,
0x00,
0x38,
0x9b,
0x71}};
const static GUID QKSDATAFORMAT_SUBTYPE_PCM = {0x00000001,0x0000,0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
const static GUID QKSDATAFORMAT_SUBTYPE_IEEE_FLOAT = {0x00000003,0x0000,0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
#ifdef _IKsPropertySet_
const static GUID CLSID_EAXDIRECTSOUND = {0x4ff53b81, 0x1ce0, 0x11d3,
@ -539,7 +532,7 @@ static unsigned int DSOUND_GetDMAPos(soundcardinfo_t *sc)
s = mmtime - dh->mmstarttime;
s >>= (sc->sn.samplebits/8) - 1;
s /= (sc->sn.samplebits/8);
s %= (sc->sn.samples);
@ -664,6 +657,13 @@ static int DSOUND_InitCard_Internal (soundcardinfo_t *sc, char *cardname)
sc->sn.numchannels = 1;
}
if (sc->sn.samplebits == 32)
{ //FTE does not support 32bit int audio, rather we interpret samplebits 32 as floats.
format.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
format.Format.cbSize = 22;
memcpy(&format.SubFormat, &QKSDATAFORMAT_SUBTYPE_IEEE_FLOAT, sizeof(GUID));
}
format.Format.nChannels = sc->sn.numchannels;
format.Format.wBitsPerSample = sc->sn.samplebits;
format.Format.nSamplesPerSec = sc->sn.speed;

View File

@ -2046,6 +2046,8 @@ void S_DoRestart (qboolean onlyifneeded)
void S_Restart_f (void)
{
S_EnumerateDevices();
S_DoRestart(false);
}

View File

@ -242,6 +242,11 @@ int WAV_InitCard (soundcardinfo_t *sc, int cardnum)
if (sc->sn.speed > 48000) // limit waveout to 48000 until that buffer issue gets solved
sc->sn.speed = 48000;
if (sc->sn.samplebits > 16)
sc->sn.samplebits = 16;
else
sc->sn.samplebits = 8;
memset (&format, 0, sizeof(format));
format.wFormatTag = WAVE_FORMAT_PCM;
format.nChannels = sc->sn.numchannels;

View File

@ -130,19 +130,27 @@ static qboolean QDECL XAUDIO_InitCard(soundcardinfo_t *sc, const char *cardname)
int dev = 0;
#endif
xaud_t *xa = Z_Malloc(sizeof(*xa));
WAVEFORMATEX wfmt;
WAVEFORMATEXTENSIBLE wfmt;
const static GUID QKSDATAFORMAT_SUBTYPE_IEEE_FLOAT = {0x00000003,0x0000,0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
xa->cb.lpVtbl = &cbvtbl;
sc->sn.numchannels = 2;
wfmt.wFormatTag = WAVE_FORMAT_PCM;
wfmt.nChannels = sc->sn.numchannels;
wfmt.nSamplesPerSec = sc->sn.speed;
wfmt.wBitsPerSample = sc->sn.samplebits;
wfmt.nBlockAlign = wfmt.nChannels * (wfmt.wBitsPerSample / 8);
wfmt.nAvgBytesPerSec = wfmt.nSamplesPerSec * wfmt.nBlockAlign;
wfmt.cbSize = 0;
memset(&wfmt, 0, sizeof(wfmt));
wfmt.Format.wFormatTag = WAVE_FORMAT_PCM;
wfmt.Format.nChannels = sc->sn.numchannels;
wfmt.Format.nSamplesPerSec = sc->sn.speed;
wfmt.Format.wBitsPerSample = sc->sn.samplebits;
wfmt.Format.nBlockAlign = wfmt.Format.nChannels * (wfmt.Format.wBitsPerSample / 8);
wfmt.Format.nAvgBytesPerSec = wfmt.Format.nSamplesPerSec * wfmt.Format.nBlockAlign;
wfmt.Format.cbSize = 0;
if (wfmt.Format.wBitsPerSample == 32)
{
wfmt.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
wfmt.Format.cbSize = 22;
memcpy(&wfmt.SubFormat, &QKSDATAFORMAT_SUBTYPE_IEEE_FLOAT, sizeof(wfmt.SubFormat));
}
sc->inactive_sound = true;
xa->buffercount = xa->bufferavail = 3; //submit this many straight up
@ -198,7 +206,7 @@ static qboolean QDECL XAUDIO_InitCard(soundcardinfo_t *sc, const char *cardname)
sd[0].Flags = 0;
sd[0].pOutputVoice = (IXAudio2Voice*)xa->master;
if (SUCCEEDED(IXAudio2_CreateSourceVoice(xa->ixa, &xa->source, &wfmt, 0, XAUDIO2_DEFAULT_FREQ_RATIO, &xa->cb, &vs, NULL)))
if (SUCCEEDED(IXAudio2_CreateSourceVoice(xa->ixa, &xa->source, &wfmt.Format, 0, XAUDIO2_DEFAULT_FREQ_RATIO, &xa->cb, &vs, NULL)))
{
sc->handle = xa;
sc->GetDMAPos = XAUDIO_GetDMAPos;

View File

@ -87,7 +87,7 @@ typedef struct
int samples; // mono samples in buffer (individual, non grouped)
// int submission_chunk; // don't mix less than this #
int samplepos; // in mono samples
int samplebits;
int samplebits; //FIXME: replace with a format enum (with separate framebytes field for lazyness).
int speed; // this many frames per second
unsigned char *buffer; // pointer to mixed pcm buffer (not directly used by mixer)
} dma_t;

View File

@ -1105,13 +1105,15 @@ int COM_EncodeSize(vec3_t mins, vec3_t maxs)
solid = bound(0, (int)-mins[0], 255);
solid |= bound(0, (int)-mins[2], 255)<<8;
solid |= bound(0, (int)((maxs[2]+32768)), 65535)<<16; /*up can be negative*/;
if (solid == 0x80000000)
solid = 0; //point sized stuff should just be non-solid. you'll thank me for splitscreens.
#else
solid = bound(0, (int)-mins[0]/8, 31);
solid |= bound(0, (int)-mins[2]/8, 31)<<5;
solid |= bound(0, (int)((maxs[2]+32)/8), 63)<<10; /*up can be negative*/;
#endif
if (solid == 4096)
solid = 0; //point sized stuff should just be non-solid. you'll thank me for splitscreens.
#endif
return solid;
}

View File

@ -33,6 +33,7 @@ the second part is some entropy differences that just allows zlib to work more e
I've rewritten the archive/outer part to plug it in to fte more nicely
the demo/inner part should mostly be the same as dzip, just with some minor tweaks to make it thread-safe (the 'dc' pointer stuff, in case that's ever an issue).
I have explicitly changed longs to ints, to ensure there's no issues with 64bit builds
*/
#include "quakedef.h"
@ -132,7 +133,6 @@ enum {
};
//basic types
#define long int //gah!
typedef unsigned int uInt; //gah!
typedef qbyte uchar;
@ -140,7 +140,7 @@ typedef struct {
uchar voz, pax;
uchar ang0, ang1, ang2;
uchar vel0, vel1, vel2;
long items;
int items;
uchar uk10, uk11, invbit;
uchar wpf, av, wpm;
int health;
@ -174,9 +174,9 @@ typedef struct
uchar copybaseline;
int maxent, lastent, sble;
int entlink[MAX_ENT];
long dem_gametime;
long outlen;
long cam0, cam1, cam2;
int dem_gametime;
int outlen;
int cam0, cam1, cam2;
uchar inblk[p_blocksize], outblk[p_blocksize], *inptr;
cdata_t oldcd, newcd;
ent_t base[MAX_ENT], oldent[MAX_ENT], newent[MAX_ENT];
@ -192,18 +192,18 @@ static void Outfile_Write(decodectx_t *dc, void *outblk, size_t outlen)
}
}
static copy_msg(decodectx_t *dc, size_t bytes)
static void copy_msg(decodectx_t *dc, size_t bytes)
{ //just copy the data over
memcpy(dc->outblk+dc->outlen, dc->inptr, bytes);
dc->outlen += bytes;
dc->inptr += bytes;
}
static insert_msg (decodectx_t *dc, void *data, size_t bytes)
static void insert_msg (decodectx_t *dc, void *data, size_t bytes)
{
memcpy(dc->outblk+dc->outlen, data, bytes);
dc->outlen += bytes;
}
static discard_msg (decodectx_t *dc, size_t bytes)
static void discard_msg (decodectx_t *dc, size_t bytes)
{
dc->inptr += bytes;
}
@ -236,7 +236,7 @@ static discard_msg (decodectx_t *dc, size_t bytes)
#define GUI //because it disables v1
#define getshort(x) LittleShort(*(short*)(x))
#define getlong(x) LittleLong(*(long*)(x))
#define getlong(x) LittleLong(*(int*)(x))
#define getfloat(x) LittleFloat(*(float*)(x))
#define cnvlong(x) LittleLong(x)
@ -336,7 +336,7 @@ void demx_sound(decodectx_t *dc)
void demx_longtime(decodectx_t *dc)
{
long tmp = getlong(inptr+1);
int tmp = getlong(inptr+1);
dem_gametime += tmp;
tmp = cnvlong(dem_gametime);
*inptr = DEM_time;
@ -347,7 +347,7 @@ void demx_longtime(decodectx_t *dc)
void demx_time(decodectx_t *dc)
{
uchar buf[5];
long tmp = getshort(inptr+1) & 0xffff;
int tmp = getshort(inptr+1) & 0xffff;
#ifndef GUI
if (dem_decode_type == TYPE_DEMV1) { demx_longtime(); return; }
@ -420,7 +420,7 @@ void create_clientdata_msg(decodectx_t *dc)
uchar buf[32];
uchar *ptr = buf+3;
int mask = newcd.invbit? 0 : 0x0200;
long tmp;
int tmp;
buf[0] = DEM_clientdata;
@ -645,7 +645,7 @@ void demx_updateentity(decodectx_t *dc)
int mask, i, entity;
int baseval = 0, prev;
ent_t n, o;
long tmp;
int tmp;
#ifndef GUI
if (dem_decode_type == TYPE_DEMV1) { demv1_updateentity(); return; }
@ -841,7 +841,7 @@ void dem_uncompress_init (decodectx_t *dc, int type)
uInt dem_uncompress_block(decodectx_t *dc)
{
long a1;
int a1;
uchar cfields;
#ifdef GUI
int uemask = 0x30, cdmask = 0x40;
@ -971,7 +971,6 @@ uInt dem_uncompress (decodectx_t *dc, uInt maxsize)
//pack mutex must be held for this function.
qboolean FSDZ_ExtractFile(qbyte *out, size_t outsize, dzarchive_t *pack, mdzfile_t *src)
{
qboolean dedemo = false;
switch(src->ztype)
{
case TYPE_PAK:
@ -1024,7 +1023,6 @@ qboolean FSDZ_ExtractFile(qbyte *out, size_t outsize, dzarchive_t *pack, mdzfile
unsigned char inbuffer[p_blocksize];
int ret;
size_t inremaining = src->csize;
size_t decompressed = 0;
decodectx_t *dc = NULL;
z_stream strm = {
@ -1380,7 +1378,7 @@ searchpathfuncs_t *QDECL FSDZ_LoadArchive (vfsfile_t *file, const char *desc, co
read = VFS_READ(packhandle, &header, sizeof(header));
if (read < sizeof(header) || header.id[0] != 'D' || header.id[1] != 'Z')
{
Con_Printf("%s is not a dz - %c%c\n", desc);
Con_Printf("%s is not a dz - %c%c\n", desc, header.id[0], header.id[1]);
return NULL;
}
if (header.major_ver > 2/* || (header.major_ver == 2 && header.minor_ver > 9)*/)

View File

@ -543,7 +543,7 @@ static void IPLog_Identify_f(void)
else
Con_Printf("%s: not connected, nor raw address\n", Cmd_Argv(0));
}
static qboolean IPLog_Dump(const char *fname)
static int IPLog_Dump(const char *fname)
{
size_t i;
vfsfile_t *f;
@ -551,6 +551,9 @@ static qboolean IPLog_Dump(const char *fname)
if (!*fname)
fname = "iplog.txt";
if (!iplog_num && !COM_FCheckExists(fname))
return 2; //no entries, nothing to overwrite
f = FS_OpenVFS(fname, "wb", FS_PUBBASEGAMEONLY);
if (!f)
return false;
@ -590,11 +593,18 @@ static void IPLog_Dump_f(void)
if (FS_NativePath(fname, FS_GAMEONLY, native, sizeof(native)))
Q_strncpyz(native, fname, sizeof(native));
IPLog_Merge_File(fname); //merge from the existing file, so that we're hopefully more robust if multiple processes are poking the same file.
if (!IPLog_Dump(fname))
Con_Printf("unable to write %s\n", fname);
else
switch (IPLog_Dump(fname))
{
case 0:
Con_Printf("unable to write %s\n", fname);
break;
default:
case 1:
Con_Printf("wrote %s\n", native);
break;
case 2:
Con_Printf("nothing to write\n");
break;
}
}
static void IPLog_Merge_f(void)

View File

@ -159,8 +159,9 @@ typedef enum
Q2PT_RESPAWN,
Q2PT_PLAYER_TELEPORT,
Q2PT_FOOTSTEP
Q2PT_FOOTSTEP,
Q2PT_MAX
} q2particleeffects_t;
extern int pt_q2[];
#endif
@ -255,7 +256,7 @@ typedef struct {
void (*RunParticleEffect4) (vec3_t org, float radius, int color, int effect, int count);
void (*RunParticleEffectPalette) (const char *nameprefix, vec3_t org, vec3_t dir, int color, int count);
void (*ParticleTrailIndex) (vec3_t start, vec3_t end, int color, int crnd, trailstate_t **tsk);
void (*ParticleTrailIndex) (vec3_t start, vec3_t end, int type, int color, int crnd, trailstate_t **tsk); //P_INVALID is fine for the type here, you'll get a default trail.
qboolean (*InitParticles) (void);
void (*ShutdownParticles) (void);
void (*DelinkTrailstate) (trailstate_t **tsk);

View File

@ -1147,13 +1147,14 @@ typedef struct usercmd_s
qbyte lightlevel;
//freestyle
float msec;
int buttons;
int weapon;
int servertime;
float fservertime;
float fclienttime;
float msec; //replace msec, but with more precision
int buttons; //replaces buttons, but with more bits.
int weapon; //q3 has a separate weapon field to supplement impulse.
int servertime; //q3 networks the time in order to calculate msecs
float fservertime;//used as part of nq msec calcs
float fclienttime;//not used?
//prydon cursor crap
vec2_t cursor_screen;
vec3_t cursor_start;
vec3_t cursor_impact;
@ -1161,17 +1162,17 @@ typedef struct usercmd_s
} usercmd_t;
typedef struct q2usercmd_s
{
{ //visible to gamecode so can't be changed (and the prediction code)
qbyte msec;
qbyte buttons;
short angles[3];
short forwardmove, sidemove, upmove;
qbyte impulse;
qbyte lightlevel;
qbyte lightlevel;
} q2usercmd_t;
typedef struct q1usercmd_s
{
{ //as written to qwd demos so can't be changed.
qbyte msec;
vec3_t angles;
short forwardmove, sidemove, upmove;

View File

@ -1739,6 +1739,7 @@ Rendering functions (Client only)
Server only functions
*/
#ifndef CLIENTONLY
static qbyte *Q1BSP_ClusterPVS (model_t *model, int cluster, pvsbuffer_t *buffer, pvsmerge_t merge);
//does the recursive work of Q1BSP_FatPVS
static void SV_Q1BSP_AddToFatPVS (model_t *mod, vec3_t org, mnode_t *node, pvsbuffer_t *pvsbuffer)
@ -1753,7 +1754,7 @@ static void SV_Q1BSP_AddToFatPVS (model_t *mod, vec3_t org, mnode_t *node, pvsbu
{
if (node->contents != Q1CONTENTS_SOLID)
{
Q1BSP_LeafPVS (mod, (mleaf_t *)node, pvsbuffer, true);
Q1BSP_ClusterPVS(mod, ((mleaf_t *)node - mod->leafs)-1, pvsbuffer, PVM_MERGE);
}
return;
}
@ -1935,25 +1936,12 @@ static qbyte *Q1BSP_DecompressVis (qbyte *in, model_t *model, qbyte *decompresse
static pvsbuffer_t mod_novis;
static pvsbuffer_t mod_tempvis;
qbyte *Q1BSP_LeafPVS (model_t *model, mleaf_t *leaf, pvsbuffer_t *buffer, qboolean merge)
void Q1BSP_Shutdown(void)
{
if (leaf == model->leafs)
{
if (mod_novis.buffersize < model->pvsbytes)
{
mod_novis.buffer = BZ_Realloc(mod_novis.buffer, mod_novis.buffersize=model->pvsbytes);
memset(mod_novis.buffer, 0xff, mod_novis.buffersize);
}
return mod_novis.buffer;
}
if (!buffer)
buffer = &mod_tempvis;
if (buffer->buffersize < model->pvsbytes)
buffer->buffer = BZ_Realloc(buffer->buffer, buffer->buffersize=model->pvsbytes);
return Q1BSP_DecompressVis (leaf->compressed_vis, model, buffer->buffer, buffer->buffersize, merge);
Z_Free(mod_novis.buffer);
memset(&mod_novis, 0, sizeof(mod_novis));
Z_Free(mod_tempvis.buffer);
memset(&mod_tempvis, 0, sizeof(mod_tempvis));
}
//pvs is 1-based. clusters are 0-based. otherwise, q1bsp has a 1:1 mapping.
@ -1990,20 +1978,34 @@ static qbyte *Q1BSP_ClusterPVS (model_t *model, int cluster, pvsbuffer_t *buffer
return Q1BSP_DecompressVis (model->leafs[cluster].compressed_vis, model, buffer->buffer, buffer->buffersize, merge==PVM_MERGE);
}
/*static qbyte *Q1BSP_ClusterPHS (model_t *model, int cluster, pvsbuffer_t *buffer)
/*static qbyte *Q1BSP_ClusterPHS (model_t *model, int cluster, pvsbuffer_t *buffer, pvsmerge_t merge)
{
if (cluster == -1 || !model->phs)
{ //without any phs info, this turns into a broadcast.
if (mod_novis.buffersize < model->pvsbytes)
{
if (merge == PVM_FAST)
{
mod_novis.buffer = BZ_Realloc(mod_novis.buffer, mod_novis.buffersize=model->pvsbytes);
memset(mod_novis.buffer, 0xff, mod_novis.buffersize);
if (mod_novis.buffersize < model->pvsbytes)
{
mod_novis.buffer = BZ_Realloc(mod_novis.buffer, mod_novis.buffersize=model->pvsbytes);
memset(mod_novis.buffer, 0xff, mod_novis.buffersize);
}
return mod_novis.buffer;
}
return mod_novis.buffer;
if (buffer->buffersize < model->pvsbytes)
buffer->buffer = BZ_Realloc(buffer->buffer, buffer->buffersize=model->pvsbytes);
memset(buffer->buffer, 0xff, model->pvsbytes);
return buffer->buffer;
}
cluster++;
return model->phs + cluster * model->pvsbytes;
if (merge == PVM_FAST)
return model->pvs + cluster * model->pvsbytes;
if (!buffer)
buffer = &mod_tempvis;
if (buffer->buffersize < model->pvsbytes)
buffer->buffer = BZ_Realloc(buffer->buffer, buffer->buffersize=model->pvsbytes);
memcpy(buffer->buffer, model->pvs + cluster * model->pvsbytes, model->pvsbytes);
return buffer->buffer;
}*/
//returns the leaf number, which is used as a bit index into the pvs.

View File

@ -1708,14 +1708,7 @@ void MSG_Q3_ReadDeltaUsercmd(int key, const usercmd_t *from, usercmd_t *to)
to->servertime = MSG_ReadBits(8) + from->servertime;
else
to->servertime = MSG_ReadBits(32);
if ((unsigned int)(to->servertime - from->servertime) > 255)
{
Con_DPrintf("msecs clamped\n");
to->msec = 255;
}
else
to->msec = to->servertime - from->servertime;
to->msec = 0; //first of a packet should always be an absolute value, which makes the old value awkward.
if (!MSG_ReadBits(1))
{

View File

@ -1447,8 +1447,9 @@ void GLBE_Init(void)
if (gl_config.glversion >= 3.0 && gl_config_nofixedfunc)
{
//docs say this line should be okay in gl3+. nvidia do not seem to agree. GL_STENCIL_BITS is depricated however. so for now, just assume.
//qglGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER_EXT, GL_STENCIL, GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE, &gl_stencilbits);
gl_stencilbits = 8;
qglGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER_EXT, GL_STENCIL, GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE, &gl_stencilbits);
if (qglGetError())
gl_stencilbits = 8;
}
else
qglGetIntegerv(GL_STENCIL_BITS, &gl_stencilbits);
@ -1484,9 +1485,17 @@ void GLBE_Init(void)
if (r_shadow_realtime_dlight.ival || r_shadow_realtime_world.ival)
{
if (r_shadow_shadowmapping.ival)
{
GLBE_RegisterLightShader(LSHADER_SMAP);
GLBE_RegisterLightShader(LSHADER_SMAP|LSHADER_CUBE);
GLBE_RegisterLightShader(LSHADER_SMAP|LSHADER_SPOT);
}
else
GLBE_RegisterLightShader(0);
{
GLBE_RegisterLightShader(LSHADER_STANDARD);
GLBE_RegisterLightShader(LSHADER_STANDARD|LSHADER_CUBE);
GLBE_RegisterLightShader(LSHADER_STANDARD|LSHADER_SPOT);
}
}
#endif

View File

@ -220,11 +220,11 @@ void VK_R_BloomBlend (texid_t source, int x, int y, int w, int h)
R2D_Flush();
#if 1
/*filter the screen into a downscaled image*/
VKBE_RT_Gen(&vk_rt_filter, texwidth[0], texheight[0], false);
VKBE_RT_Gen(&vk_rt_filter, texwidth[0], texheight[0], false, RT_IMAGEFLAGS);
VKBE_RT_Begin(&vk_rt_filter);
vk.sourcecolour = source;
R2D_ScalePic(0, 0, vid.width, vid.height, bloomfilter);
R2D_Flush();
VKBE_RT_End(&vk_rt_filter);
intex = &vk_rt_filter.q_colour;
#else
intex = source;
@ -251,29 +251,27 @@ void VK_R_BloomBlend (texid_t source, int x, int y, int w, int h)
r_worldentity.glowmod[1] = 0;
VKBE_RT_Gen(&vk_rt_bloom[1][i], texwidth[i], texheight[i], false);
VKBE_RT_Gen(&vk_rt_bloom[1][i], texwidth[i], texheight[i], false, RT_IMAGEFLAGS);
VKBE_RT_Begin(&vk_rt_bloom[1][i]);
vk.sourcecolour = intex;
BE_SelectEntity(&r_worldentity);
R2D_ScalePic(0, 0, vid.width, vid.height, bloomblur);
R2D_Flush();
VKBE_RT_End(&vk_rt_bloom[1][i]);
r_worldentity.glowmod[0] = 0;
r_worldentity.glowmod[1] = 1.0 / texheight[i];
VKBE_RT_Gen(&vk_rt_bloom[0][i], texwidth[i], texheight[i], false);
VKBE_RT_Gen(&vk_rt_bloom[0][i], texwidth[i], texheight[i], false, RT_IMAGEFLAGS);
VKBE_RT_Begin(&vk_rt_bloom[0][i]);
vk.sourcecolour = &vk_rt_bloom[1][i].q_colour;
BE_SelectEntity(&r_worldentity);
R2D_ScalePic(0, 0, vid.width, vid.height, bloomblur);
R2D_Flush();
VKBE_RT_End(&vk_rt_bloom[0][i]);
intex = &vk_rt_bloom[0][i].q_colour;
}
r_worldentity.glowmod[0] = 0;
r_worldentity.glowmod[1] = 0;
VKBE_RT_Begin(oldfbo);
//go back to the screen fbo
/*combine them onto the screen*/
bloomfinal->defaulttextures->base = intex;
@ -288,10 +286,10 @@ void VK_R_BloomShutdown(void)
int i;
for (i = 0; i < MAXLEVELS; i++)
{
VKBE_RT_Gen(&vk_rt_bloom[0][i], 0, 0, false);
VKBE_RT_Gen(&vk_rt_bloom[1][i], 0, 0, false);
VKBE_RT_Gen(&vk_rt_bloom[0][i], 0, 0, false, RT_IMAGEFLAGS);
VKBE_RT_Gen(&vk_rt_bloom[1][i], 0, 0, false, RT_IMAGEFLAGS);
}
VKBE_RT_Gen(&vk_rt_filter, 0, 0, false);
VKBE_RT_Gen(&vk_rt_filter, 0, 0, false, RT_IMAGEFLAGS);
R_InitBloomTextures();
}

View File

@ -66,12 +66,10 @@ void GLDraw_Init (void)
if (gl_config.gles && gl_config.glversion < 3.0)
r_softwarebanding = false;
if (!gl_config.gles)
if (gl_config.arb_framebuffer_srgb)
{
extern cvar_t vid_srgb;
GLint srgb;
qglGetIntegerv(GL_FRAMEBUFFER_SRGB_CAPABLE, &srgb);
vid.srgb = vid_srgb.ival>1 && srgb;
vid.srgb = vid_srgb.ival>1;
if (vid.srgb)
qglEnable(GL_FRAMEBUFFER_SRGB);
}

View File

@ -1816,6 +1816,22 @@ void Font_LineDraw(int x, int y, conchar_t *start, conchar_t *end)
}
}
conchar_t *Font_CharAt(int x, conchar_t *start, conchar_t *end)
{
int lx = 0, nx;
struct font_s *font = curfont;
unsigned int codeflags, codepoint;
conchar_t *nc;
for (; start < end; lx = nx, start = nc)
{
nc = Font_Decode(start, &codeflags, &codepoint);
nx = Font_CharEndCoord(font, lx, codeflags, codepoint);
if (x >= lx && x < nx)
return start;
}
return NULL;
}
/*Note: *all* strings after the current one will inherit the same colour, until one changes it explicitly
correct usage of this function thus requires calling this with 1111 before Font_EndString*/
void Font_InvalidateColour(vec4_t newcolour)

View File

@ -5847,6 +5847,7 @@ void Mod_LoadDoomSprite (model_t *mod)
mspriteframe_t frame;
size_t c;
unsigned int *colpointers;
vec3_t t;
mod->type = mod_dummy;
@ -5908,6 +5909,8 @@ void Mod_LoadDoomSprite (model_t *mod)
}
Z_Free(coldata);
ClearBounds(mod->mins, mod->maxs);
//do the actual loading.
for (ofs = 4; ofs < *(int*)files; ofs+=strlen(files+ofs)+1)
{
@ -5915,11 +5918,18 @@ void Mod_LoadDoomSprite (model_t *mod)
header = (doomimage_t *)FS_LoadMallocFile(name, &fsize);
frame.up = +header->ypos;
frame.down = -header->height + header->ypos;
//the 5 is because doom likes drawing sprites slightly downwards, in the floor.
frame.up = header->ypos + 5;
frame.down = header->ypos-header->height + 5;
frame.left = -header->xpos;
frame.right = header->width - header->xpos;
t[0] = t[1] = max(abs(frame.left),abs(frame.right));
t[2] = frame.up;
AddPointToBounds(t, mod->mins, mod->maxs);
t[0] *= -1;
t[1] *= -1;
t[2] = frame.down;
if (header->width*header->height <= sizeof(image))
{

View File

@ -539,7 +539,6 @@ void Mod_ClipDecal(struct model_s *mod, vec3_t center, vec3_t normal, vec3_t tan
void Q1BSP_MarkLights (dlight_t *light, int bit, mnode_t *node);
void GLQ1BSP_LightPointValues(struct model_s *model, vec3_t point, vec3_t res_diffuse, vec3_t res_ambient, vec3_t res_dir);
qboolean Q1BSP_RecursiveHullCheck (hull_t *hull, int num, float p1f, float p2f, vec3_t p1, vec3_t p2, struct trace_s *trace);
qbyte *Q1BSP_LeafPVS (struct model_s *model, mleaf_t *leaf, pvsbuffer_t *buffer, qboolean merge);
/*
==============================================================================

View File

@ -5810,7 +5810,7 @@ void Shader_DefaultBSPQ1(const char *shortname, shader_t *s, const void *args)
"}\n"
);
}
else if (*r_skyboxname.string)
else if (*r_skyboxname.string || *cl.skyname)
{
builtin = (
"{\n"

View File

@ -1480,7 +1480,8 @@ static struct shadowmesh_s *SHM_BuildShadowMesh(dlight_t *dl, unsigned char *lvi
{
int cluster = cl.worldmodel->funcs.ClusterForPoint(cl.worldmodel, dl->origin);
sh_shmesh->litleaves[cluster>>3] |= 1<<(cluster&7);
if (cluster >= 0)
sh_shmesh->litleaves[cluster>>3] |= 1<<(cluster&7);
}
break;
}

View File

@ -1089,6 +1089,8 @@ void GL_CheckExtensions (void *(*getglfunction) (char *name))
qglFramebufferRenderbufferEXT = (void *)getglext("glFramebufferRenderbuffer");
qglCheckFramebufferStatusEXT = (void *)getglext("glCheckFramebufferStatus");
qglGetFramebufferAttachmentParameteriv = (void *)getglext("glGetFramebufferAttachmentParameteriv");
gl_config.arb_framebuffer_srgb = GL_CheckExtension("GL_ARB_framebuffer_sRGB");
}
else if (GL_CheckExtension("GL_EXT_framebuffer_object"))
{

View File

@ -118,11 +118,12 @@ extern cvar_t vid_conwidth, vid_conautoscale;
extern cvar_t vid_width;
extern cvar_t vid_height;
extern cvar_t vid_wndalpha;
extern cvar_t vid_winthread;
static qboolean VID_SetWindowedMode (rendererstate_t *info); //-1 on bpp or hz for default.
static qboolean VID_SetFullDIBMode (rendererstate_t *info); //-1 on bpp or hz for default.
#ifdef MULTITHREADED
#ifdef MULTITHREAD
#define WTHREAD //While the user is resizing a window, the entire thread that owns said window becomes frozen. in order to cope with window resizing, its easiest to just create a separate thread to be microsoft's plaything. our main game thread can then just keep rendering. hopefully that won't bug out on the present.
#endif
#ifdef WTHREAD
@ -1341,7 +1342,7 @@ static qboolean CreateMainWindow(rendererstate_t *info, qboolean withthread)
qboolean stat;
#ifdef WTHREAD
if (withthread)
if (withthread && vid_winthread.ival)
{
void *cond = Sys_CreateConditional();
Sys_LockConditional(cond);
@ -1715,6 +1716,7 @@ static void VID_UpdateWindowStatus (HWND hWnd)
case MODE_VULKAN:
if (vid.pixelwidth != window_width || vid.pixelheight != window_height)
vk.neednewswapchain = true;
break;
#endif
default:
vid.pixelwidth = window_width;
@ -2741,9 +2743,9 @@ void MainThreadWndProc(void *ctx, void *data, size_t msg, size_t ex)
break;
#ifdef HAVE_CDPLAYER
case MM_MCINOTIFY:
CDAudio_MessageHandler (mainwindow, uMsg, ctx, data);
break;
case MM_MCINOTIFY:
CDAudio_MessageHandler (mainwindow, msg, (WPARAM)ctx, (LPARAM)data);
break;
#endif
}
}
@ -3071,7 +3073,7 @@ static LONG WINAPI GLMainWndProc (
#ifdef HAVE_CDPLAYER
case MM_MCINOTIFY:
#ifdef WTHREAD
COM_AddWork(WG_MAIN, MainThreadWndProc, wParam, lParam, uMsg, 0);
COM_AddWork(WG_MAIN, MainThreadWndProc, (void*)wParam, (void*)lParam, uMsg, 0);
lRet = 0;
#else
lRet = CDAudio_MessageHandler (hWnd, uMsg, wParam, lParam); //FIXME: thread

View File

@ -46,10 +46,18 @@ static shader_t *skygridface;
void R_SetSky(char *skyname)
{
extern cvar_t r_skyboxname;
forcedskyshader = NULL;
if (!qrenderer)
return;
if (*r_skyboxname.string) //user's setting overrides.
skyname = r_skyboxname.string;
Shader_NeedReload(false);
if (*skyname)
forcedskyshader = R_RegisterCustom(va("skybox_%s", skyname), SUF_NONE, Shader_DefaultSkybox, NULL);
else
forcedskyshader = NULL;
skyboxface = R_RegisterShader("skyboxface", SUF_NONE,
"{\n"

View File

@ -150,6 +150,12 @@ typedef struct {
unsigned short first;
} dssector_t;
typedef struct {
struct msector_s *sector;
unsigned short segcount;
unsigned short first;
} mssector_t;
typedef struct {
short x;
short y;
@ -178,7 +184,7 @@ typedef struct {
short tag;
} dsector_t;
typedef struct {
typedef struct msector_s {
int visframe;
int floortex;
int ceilingtex;
@ -224,7 +230,7 @@ typedef struct doommap_s
plane_t *nodeplane;
unsigned int numnodes;
dssector_t *ssector; //aka: leafs
mssector_t *ssector; //aka: leafs
unsigned int numssectors;
msector_t *sector;
@ -261,12 +267,11 @@ void Doom_SetModelFunc(model_t *mod);
//physics
/*walk the bsp tree*/
int Doom_SectorNearPoint(doommap_t *dm, vec3_t p)
msector_t *Doom_SectorNearPoint(doommap_t *dm, vec3_t p)
{
ddoomnode_t *node;
plane_t *plane;
int num;
int seg;
float d;
num = dm->numnodes-1;
while (1)
@ -274,11 +279,7 @@ int Doom_SectorNearPoint(doommap_t *dm, vec3_t p)
if (num & NODE_IS_SSECTOR)
{
num -= NODE_IS_SSECTOR;
for (seg = dm->ssector[num].first; seg < dm->ssector[num].first + dm->ssector[num].segcount; seg++)
if (dm->seg[seg].linedef != 0xffff)
break;
return dm->sidedef[dm->linedef[dm->seg[seg].linedef].sidedef[dm->seg[seg].direction]].sector;
return dm->ssector[num].sector;
}
node = dm->node + num;
@ -294,16 +295,16 @@ int Doom_SectorNearPoint(doommap_t *dm, vec3_t p)
num = node->node1;
}
return num;
return NULL;
}
int Doom_PointContents(model_t *model, vec3_t axis[3], vec3_t p)
{
doommap_t *dm = model->meshinfo;
int sec = Doom_SectorNearPoint(dm, p);
if (p[2] < dm->sector[sec].floorheight)
msector_t *sec = Doom_SectorNearPoint(dm, p);
if (p[2] < sec->floorheight)
return FTECONTENTS_SOLID;
if (p[2] > dm->sector[sec].ceilingheight)
if (p[2] > sec->ceilingheight)
return FTECONTENTS_SOLID;
return FTECONTENTS_EMPTY;
}
@ -315,26 +316,27 @@ use blockmap for walls
*/
qboolean Doom_Trace(model_t *model, int hulloverride, framestate_t *framestate, vec3_t axis[3], vec3_t start, vec3_t end, vec3_t mins, vec3_t maxs, qboolean iscapsule, unsigned int contentstype, trace_t *trace)
{
#if 0
doommap_t *dm = model->meshinfo;
#if 1
#define TRACESTEP 16
unsigned short *linedefs;
dlinedef_t *ld;
int bmi, obmi;
vec3_t delta;
int sec1 = Doom_SectorNearPoint(start);
msector_t *sec1 = Doom_SectorNearPoint(dm, start);
vec3_t p1, pointonplane, ofs;
float d1, d2, c1, c2, planedist;
plane_t *lp;
mdoomvertex_t *v1, *v2;
int j;
float p2f;
float p1f, p2f;
float clipfrac;
#define DIST_EPSILON (0.03125)
// Con_Printf("%i\n", sec1);
if (start[2] < dm->sector[sec1].floorheight-mins[2]) //whoops, started outside... ?
if (start[2] < sec1->floorheight-mins[2]) //whoops, started outside... ?
{
trace->fraction = 0;
trace->allsolid = trace->startsolid = true;
@ -346,11 +348,11 @@ qboolean Doom_Trace(model_t *model, int hulloverride, framestate_t *framestate,
trace->plane.normal[0] = 0;
trace->plane.normal[1] = 0;
trace->plane.normal[2] = 1;
trace->plane.dist = dm->sector[sec1].floorheight-mins[2];
trace->plane.dist = sec1->floorheight-mins[2];
return false;
}
if (start[2] > dm->sector[sec1].ceilingheight-maxs[2]) //whoops, started outside... ?
if (start[2] > sec1->ceilingheight-maxs[2]) //whoops, started outside... ?
{
trace->fraction = 0;
trace->allsolid = trace->startsolid = true;
@ -360,7 +362,7 @@ qboolean Doom_Trace(model_t *model, int hulloverride, framestate_t *framestate,
trace->plane.normal[0] = 0;
trace->plane.normal[1] = 0;
trace->plane.normal[2] = -1;
trace->plane.dist = -(dm->sector[sec1].ceilingheight-maxs[2]);
trace->plane.dist = -(sec1->ceilingheight-maxs[2]);
return false;
}
@ -375,6 +377,9 @@ qboolean Doom_Trace(model_t *model, int hulloverride, framestate_t *framestate,
trace->endpos[1] = end[1];
trace->endpos[2] = end[2];
VectorCopy(start, p1);
p1f = 0;
trace->fraction = 1;
while(1)
{
@ -383,7 +388,7 @@ qboolean Doom_Trace(model_t *model, int hulloverride, framestate_t *framestate,
if (bmi >= 0 && bmi < dm->blockmap->rows*dm->blockmap->columns)
if (bmi != obmi)
{
#if 1
#if 0
short dummy;
linedefs = &dummy;
for (dummy = 0; dummy < dm->numlinedefs; dummy++)
@ -436,29 +441,29 @@ qboolean Doom_Trace(model_t *model, int hulloverride, framestate_t *framestate,
else
c1 = (d1-DIST_EPSILON) / (d1 - d2);
c2 = 1-c1;
pointonplane[0] = start[0]*c2 + p2[0]*c1;
pointonplane[0] = start[0]*c2 + end[0]*c1;
/* if (pointonplane[0] > v1->xpos+DIST_EPSILON*2+hull->clip_maxs[0] && pointonplane[0] > v2->xpos+DIST_EPSILON*2+hull->clip_maxs[0])
continue;
if (pointonplane[0] < v1->xpos-DIST_EPSILON*2+hull->clip_mins[0] && pointonplane[0] < v2->xpos-DIST_EPSILON*2+hull->clip_mins[0])
continue;
*/ pointonplane[1] = start[1]*c2 + p2[1]*c1;
*/ pointonplane[1] = start[1]*c2 + end[1]*c1;
/* if (pointonplane[1] > v1->ypos+DIST_EPSILON*2+hull->clip_maxs[1] && pointonplane[1] > v2->ypos+DIST_EPSILON*2+hull->clip_maxs[1])
continue;
if (pointonplane[1] < v1->ypos-DIST_EPSILON*2+hull->clip_mins[1] && pointonplane[1] < v2->ypos-DIST_EPSILON*2+hull->clip_mins[1])
continue;
*/
pointonplane[2] = start[2]*c2 + p2[2]*c1;
pointonplane[2] = start[2]*c2 + end[2]*c1;
Con_Printf("Started in wall\n");
j = dm->sidedef[ld->sidedef[d1 < planedist]].sector;
//yup, we are in the thing
//prevent ourselves from entering the back-sector's floor/ceiling
if (pointonplane[2] < dm->sector[j].floorheight-hull->clip_mins[2]) //whoops, started outside... ?
//prevent ourselves from entering the back-sector's floor/ceiling at the point of impact
if (pointonplane[2] < dm->sector[j].floorheight-mins[2]) //whoops, started outside... ?
{
Con_Printf("Started in floor\n");
trace->allsolid = trace->startsolid = false;
trace->endpos[2] = dm->sector[j].floorheight-hull->clip_mins[2];
trace->fraction = fabs(trace->endpos[2] - start[2]) / fabs(p2[2] - start[2]);
trace->endpos[2] = dm->sector[j].floorheight-mins[2];
trace->fraction = fabs(trace->endpos[2] - start[2]) / fabs(end[2] - start[2]);
trace->endpos[0] = start[0]+delta[0]*trace->fraction*p2f;
trace->endpos[1] = start[1]+delta[1]*trace->fraction*p2f;
// if (IS_NAN(trace->endpos[2]))
@ -466,22 +471,22 @@ qboolean Doom_Trace(model_t *model, int hulloverride, framestate_t *framestate,
trace->plane.normal[0] = 0;
trace->plane.normal[1] = 0;
trace->plane.normal[2] = 1;
trace->plane.dist = dm->sector[j].floorheight-hull->clip_mins[2];
trace->plane.dist = dm->sector[j].floorheight-mins[2];
continue;
}
if (pointonplane[2] > dm->sector[j].ceilingheight-hull->clip_maxs[2]) //whoops, started outside... ?
if (pointonplane[2] > dm->sector[j].ceilingheight-maxs[2]) //whoops, started outside... ?
{
Con_Printf("Started in ceiling\n");
trace->allsolid = trace->startsolid = false;
trace->endpos[0] = pointonplane[0];
trace->endpos[1] = pointonplane[1];
trace->endpos[2] = dm->sector[j].ceilingheight-hull->clip_maxs[2];
trace->fraction = fabs(trace->endpos[2] - start[2]) / fabs(p2[2] - start[2]);
trace->endpos[2] = dm->sector[j].ceilingheight-maxs[2];
trace->fraction = fabs(trace->endpos[2] - start[2]) / fabs(end[2] - start[2]);
trace->plane.normal[0] = 0;
trace->plane.normal[1] = 0;
trace->plane.normal[2] = -1;
trace->plane.dist = -(dm->sector[j].ceilingheight-hull->clip_maxs[2]);
trace->plane.dist = -(dm->sector[j].ceilingheight-maxs[2]);
continue;
}
}
@ -504,17 +509,17 @@ qboolean Doom_Trace(model_t *model, int hulloverride, framestate_t *framestate,
else
c1 = (d1-DIST_EPSILON) / (d1 - d2);
c2 = 1-c1;
pointonplane[0] = start[0]*c2 + p2[0]*c1;
if (pointonplane[0] > v1->xpos+DIST_EPSILON*2+hull->clip_maxs[0] && pointonplane[0] > v2->xpos+DIST_EPSILON*2+hull->clip_maxs[0])
pointonplane[0] = start[0]*c2 + end[0]*c1;
if (pointonplane[0] > v1->xpos+DIST_EPSILON*2+maxs[0] && pointonplane[0] > v2->xpos+DIST_EPSILON*2+maxs[0])
continue;
if (pointonplane[0] < v1->xpos-DIST_EPSILON*2+hull->clip_mins[0] && pointonplane[0] < v2->xpos-DIST_EPSILON*2+hull->clip_mins[0])
if (pointonplane[0] < v1->xpos-DIST_EPSILON*2+mins[0] && pointonplane[0] < v2->xpos-DIST_EPSILON*2+mins[0])
continue;
pointonplane[1] = start[1]*c2 + p2[1]*c1;
if (pointonplane[1] > v1->ypos+DIST_EPSILON*2+hull->clip_maxs[1] && pointonplane[1] > v2->ypos+DIST_EPSILON*2+hull->clip_maxs[1])
pointonplane[1] = start[1]*c2 + end[1]*c1;
if (pointonplane[1] > v1->ypos+DIST_EPSILON*2+maxs[1] && pointonplane[1] > v2->ypos+DIST_EPSILON*2+maxs[1])
continue;
if (pointonplane[1] < v1->ypos-DIST_EPSILON*2+hull->clip_mins[1] && pointonplane[1] < v2->ypos-DIST_EPSILON*2+hull->clip_mins[1])
if (pointonplane[1] < v1->ypos-DIST_EPSILON*2+mins[1] && pointonplane[1] < v2->ypos-DIST_EPSILON*2+mins[1])
continue;
pointonplane[2] = start[2]*c2 + p2[2]*c1;
pointonplane[2] = start[2]*c2 + end[2]*c1;
if (ld->flags & LINEDEF_IMPASSABLE || ld->sidedef[1] == 0xffff) //unconditionally unpassable.
{ //unconditionally clipped.
@ -528,10 +533,10 @@ qboolean Doom_Trace(model_t *model, int hulloverride, framestate_t *framestate,
else
sec2 = &dm->sector[dm->sidedef[ld->sidedef[0]].sector];
if (pointonplane[2] < sec2->floorheight-hull->clip_mins[2])
if (pointonplane[2] < sec2->floorheight-mins[2])
{ //hit the floor first.
c1 = fabs(dm->sector[sec1].floorheight-hull->clip_mins[2] - start[2]);
c2 = fabs(p2[2] - start[2]);
c1 = fabs(sec1->floorheight-mins[2] - start[2]);
c2 = fabs(end[2] - start[2]);
if (!c2)
c1 = 1;
else
@ -541,21 +546,21 @@ qboolean Doom_Trace(model_t *model, int hulloverride, framestate_t *framestate,
// Con_Printf("Hit floor\n");
trace->fraction = c1;
trace->allsolid = trace->startsolid = true;
trace->endpos[0] = start[0] + trace->fraction*(p2[0]-start[0]);
trace->endpos[1] = start[1] + trace->fraction*(p2[1]-start[1]);
trace->endpos[2] = start[2] + trace->fraction*(p2[2]-start[2]);
trace->endpos[0] = start[0] + trace->fraction*(end[0]-start[0]);
trace->endpos[1] = start[1] + trace->fraction*(end[1]-start[1]);
trace->endpos[2] = start[2] + trace->fraction*(end[2]-start[2]);
trace->plane.normal[0] = 0;
trace->plane.normal[1] = 0;
trace->plane.normal[2] = 1;
trace->plane.dist = dm->sector[sec1].floorheight-hull->clip_mins[2];
trace->plane.dist = sec1->floorheight-mins[2];
}
continue;
}
if (pointonplane[2] > sec2->ceilingheight-hull->clip_maxs[2])
if (pointonplane[2] > sec2->ceilingheight-maxs[2])
{ //hit the floor first.
c1 = fabs((dm->sector[sec1].ceilingheight-hull->clip_maxs[2]) - start[2]);
c2 = fabs(p2[2] - start[2]);
c1 = fabs((sec1->ceilingheight-maxs[2]) - start[2]);
c2 = fabs(end[2] - start[2]);
if (!c2)
c1 = 1;
else
@ -567,13 +572,13 @@ qboolean Doom_Trace(model_t *model, int hulloverride, framestate_t *framestate,
// Con_Printf("Hit ceiling\n");
trace->fraction = c1;
trace->allsolid = trace->startsolid = true;
trace->endpos[0] = start[0] + trace->fraction*(p2[0]-start[0]);
trace->endpos[1] = start[1] + trace->fraction*(p2[1]-start[1]);
trace->endpos[2] = start[2] + trace->fraction*(p2[2]-start[2]);
trace->endpos[0] = start[0] + trace->fraction*(end[0]-start[0]);
trace->endpos[1] = start[1] + trace->fraction*(end[1]-start[1]);
trace->endpos[2] = start[2] + trace->fraction*(end[2]-start[2]);
trace->plane.normal[0] = 0;
trace->plane.normal[1] = 0;
trace->plane.normal[2] = -1;
trace->plane.dist = -(dm->sector[sec1].ceilingheight-hull->clip_maxs[2]);
trace->plane.dist = -(sec1->ceilingheight-maxs[2]);
}
continue;
}
@ -586,10 +591,10 @@ qboolean Doom_Trace(model_t *model, int hulloverride, framestate_t *framestate,
if(sec2->ceilingheight == sec2->floorheight)
sec2->ceilingheight += 64;
if (pointonplane[2] > sec2->floorheight-hull->clip_mins[2] &&
pointonplane[2] < sec2->ceilingheight-hull->clip_maxs[2])
if (pointonplane[2] > sec2->floorheight-mins[2] &&
pointonplane[2] < sec2->ceilingheight-maxs[2])
{
Con_Printf("Two sided passed\n");
// Con_Printf("Two sided passed\n");
continue;
}
@ -639,14 +644,14 @@ qboolean Doom_Trace(model_t *model, int hulloverride, framestate_t *framestate,
// VectorMA(start, p2f*trace->fraction, delta, p2);
if (p2[2] != start[2])
if (end[2] != start[2])
{
if (sec1 == Doom_SectorNearPoint(p2)) //special test.
if (sec1 == Doom_SectorNearPoint(dm, trace->endpos)) //special test.
{
if (p2[2] <= dm->sector[sec1].floorheight-hull->clip_mins[2]) //whoops, started outside... ?
if (end[2] <= sec1->floorheight-mins[2]) //whoops, started outside... ?
{
p1f = fabs(dm->sector[sec1].floorheight-hull->clip_mins[2] - start[2]);
p2f = fabs(p2[2] - start[2]);
p1f = fabs(sec1->floorheight-mins[2] - start[2]);
p2f = fabs(end[2] - start[2]);
if (!p2f)
c1 = 1;
else
@ -655,22 +660,22 @@ qboolean Doom_Trace(model_t *model, int hulloverride, framestate_t *framestate,
{
trace->fraction = c1;
trace->allsolid = trace->startsolid = false;
trace->endpos[0] = start[0] + trace->fraction*(p2[0]-start[0]);
trace->endpos[1] = start[1] + trace->fraction*(p2[1]-start[1]);
trace->endpos[2] = start[2] + trace->fraction*(p2[2]-start[2]);
trace->endpos[0] = start[0] + trace->fraction*(end[0]-start[0]);
trace->endpos[1] = start[1] + trace->fraction*(end[1]-start[1]);
trace->endpos[2] = start[2] + trace->fraction*(end[2]-start[2]);
trace->plane.normal[0] = 0;
trace->plane.normal[1] = 0;
trace->plane.normal[2] = 1;
trace->plane.dist = dm->sector[sec1].floorheight-hull->clip_mins[2];
trace->plane.dist = sec1->floorheight-mins[2];
}
// if (IS_NAN(trace->endpos[2]))
// Con_Printf("Nanny\n");
}
if (p2[2] >= dm->sector[sec1].ceilingheight-hull->clip_maxs[2]) //whoops, started outside... ?
if (end[2] >= sec1->ceilingheight-maxs[2]) //whoops, started outside... ?
{
p1f = fabs(dm->sector[sec1].ceilingheight-hull->clip_maxs[2] - start[2]);
p2f = fabs(p2[2] - start[2]);
p1f = fabs(sec1->ceilingheight-maxs[2] - start[2]);
p2f = fabs(end[2] - start[2]);
if (!p2f)
c1 = 1;
else
@ -679,13 +684,13 @@ qboolean Doom_Trace(model_t *model, int hulloverride, framestate_t *framestate,
{
trace->fraction = c1;
trace->allsolid = trace->startsolid = false;
trace->endpos[0] = start[0] + trace->fraction*(p2[0]-start[0]);
trace->endpos[1] = start[1] + trace->fraction*(p2[1]-start[1]);
trace->endpos[2] = start[2] + trace->fraction*(p2[2]-start[2]);
trace->endpos[0] = start[0] + trace->fraction*(end[0]-start[0]);
trace->endpos[1] = start[1] + trace->fraction*(end[1]-start[1]);
trace->endpos[2] = start[2] + trace->fraction*(end[2]-start[2]);
trace->plane.normal[0] = 0;
trace->plane.normal[1] = 0;
trace->plane.normal[2] = -1;
trace->plane.dist = -(dm->sector[sec1].ceilingheight-hull->clip_maxs[2]);
trace->plane.dist = -(sec1->ceilingheight-maxs[2]);
}
// if (IS_NAN(trace->endpos[2]))
@ -1438,8 +1443,6 @@ static void Triangulate_Sectors(doommap_t *dm, dsector_t *sectorl, qboolean glbs
int seg, nsec;
int i, sec=-1;
dm->sector = Z_Malloc(dm->numsectors * sizeof(*dm->sector));
if (glbspinuse)
{
for (i = 0; i < dm->numssectors; i++)
@ -1832,7 +1835,7 @@ static void CleanWalls(doommap_t *dm, dsidedef_t *sidedefsl)
void QuakifyThings(doommap_t *dm)
{
int sector;
msector_t *sector;
int spawnflags;
char *name;
int i;
@ -1850,6 +1853,7 @@ void QuakifyThings(doommap_t *dm)
for (i = 0; i < dm->numthings; i++)
{
float zbias = 24;
switch(dm->thing[i].type)
{
case THING_PLAYER: //fixme: spit out a coop spawn too.
@ -1889,6 +1893,7 @@ void QuakifyThings(doommap_t *dm)
default:
name = va2(thingname, sizeof(thingname), "thing_%i", dm->thing[i].type);
zbias = 0;
break;
}
@ -1896,7 +1901,7 @@ void QuakifyThings(doommap_t *dm)
point[1] = dm->thing[i].ypos;
point[2] = 0;
sector = Doom_SectorNearPoint(dm, point);
zpos = dm->sector[sector].floorheight + 24; //things have no z coord, so find the sector they're in
zpos = sector->floorheight + zbias; //things have no z coord, so find the sector they're in
spawnflags = SPAWNFLAG_NOT_EASY | SPAWNFLAG_NOT_MEDIUM | SPAWNFLAG_NOT_HARD | SPAWNFLAG_NOT_DEATHMATCH;
if (dm->thing[i].flags & THING_EASY)
@ -1991,16 +1996,29 @@ static void MoveWorld(doommap_t *dm)
if (min[0]>=-4096 && max[0]<=4096)
if (min[1]>=-4096 && max[1]<=4096)
return; //doesn't need adjusting, live with it.
adj[0] = adj[1] = 0; //doesn't need adjusting, live with it.
if (max[0]-min[0]>=8192 || max[1]-min[1]>=8192)
{
Con_Printf(CON_WARNING "Warning: Map is too large for the network protocol\n");
return;
adj[0] = adj[1] = 0;
}
else
{
adj[0] = (max[0]-4096)&~63; //don't harm the tiling.
adj[1] = (max[1]-4096)&~63;
}
adj[0] = (max[0]-4096)&~63; //don't harm the tiling.
adj[1] = (max[1]-4096)&~63;
dm->model->mins[0] = min[0] - adj[0];
dm->model->mins[1] = min[1] - adj[1];
dm->model->mins[2] = -32768;
dm->model->maxs[0] = max[0] - adj[0];
dm->model->maxs[1] = max[1] - adj[1];
dm->model->maxs[2] = 32767;
if (!adj[0] && !adj[1])
return;
Con_Printf("Adjusting map (%i %i)\n", -adj[0], -adj[1]);
@ -2102,13 +2120,37 @@ static void Doom_LoadVerticies(doommap_t *dm, char *name)
static void Doom_LoadSSectors(doommap_t *dm, char *name)
{
dssector_t *in;
size_t fsize;
unsigned int i;
char tmp[MAX_QPATH];
dm->ssector = (void *)FS_LoadMallocFile (va2(tmp, sizeof(tmp), "%s.gl_ssect", name), &fsize);
if (!dm->ssector)
dm->ssector = (void *)FS_LoadMallocFile (va2(tmp, sizeof(tmp), "%s.ssectors", name), &fsize);
in = (void *)FS_LoadMallocFile (va2(tmp, sizeof(tmp), "%s.gl_ssect", name), &fsize);
if (!in)
in = (void *)FS_LoadMallocFile (va2(tmp, sizeof(tmp), "%s.ssectors", name), &fsize);
//FIXME: "gNd3" means that it's glbsp version 3.
dm->numssectors = fsize/sizeof(*dm->ssector);
dm->numssectors = fsize/sizeof(*in);
dm->ssector = Z_Malloc(dm->numssectors * sizeof(*dm->ssector));
for (i = 0; i < dm->numssectors; i++)
{
dm->ssector[i].segcount = in[i].segcount;
dm->ssector[i].first = in[i].first;
}
Z_Free(in);
}
static void Doom_CalcSubsectorSectors(doommap_t *dm)
{ //kinda shitty
unsigned int num, seg;
for (num = 0; num < dm->numssectors; num++)
{
dm->ssector[num].sector = &dm->sector[dm->sidedef[dm->linedef[dm->seg[dm->ssector[num].first].linedef].sidedef[dm->seg[dm->ssector[num].first].direction]].sector];
for (seg = dm->ssector[num].first+1; seg < dm->ssector[num].first + dm->ssector[num].segcount; seg++)
if (dm->seg[seg].linedef != 0xffff)
{
dm->ssector[num].sector = &dm->sector[dm->sidedef[dm->linedef[dm->seg[seg].linedef].sidedef[dm->seg[seg].direction]].sector];
break;
}
}
}
static void Doom_LoadSSegs(doommap_t *dm, char *name)
@ -2210,6 +2252,7 @@ qboolean QDECL Mod_LoadDoomLevel(model_t *mod, void *buffer, size_t fsize)
}
sectorl = (void *)FS_LoadMallocFile (va2(tmp,sizeof(tmp),"%s.sectors", name), &fsize);
dm->numsectors = fsize/sizeof(*sectorl);
dm->sector = Z_Malloc(dm->numsectors * sizeof(*dm->sector));
#ifndef SERVERONLY
dm->numtextures=0;
@ -2229,7 +2272,7 @@ qboolean QDECL Mod_LoadDoomLevel(model_t *mod, void *buffer, size_t fsize)
sidedefsl = (void *)FS_LoadMallocFile (va2(tmp,sizeof(tmp),"%s.sidedefs", name), &fsize);
dm->numsidedefs = fsize/sizeof(*sidedefsl);
dm->blockmap = (void *)FS_LoadMallocFile (va2(tmp,sizeof(tmp),"%s.blockmap", name), &fsize);
// blockmaps = fsize;
#ifndef SERVERONLY
Doom_LoadTextureInfos();
#endif
@ -2262,9 +2305,12 @@ qboolean QDECL Mod_LoadDoomLevel(model_t *mod, void *buffer, size_t fsize)
mod->fromgame = fg_doom;
mod->type = mod_brush;
mod->nodes = (void*)0x1;
mod->numclusters = dm->numsectors;
CleanWalls(dm, sidedefsl);
Doom_CalcSubsectorSectors(dm);
Triangulate_Sectors(dm, sectorl, !!gl_nodes);
QuakifyThings(dm);
@ -2273,11 +2319,11 @@ qboolean QDECL Mod_LoadDoomLevel(model_t *mod, void *buffer, size_t fsize)
return true;
}
void Doom_LightPointValues(model_t *model, vec3_t point, vec3_t res_diffuse, vec3_t res_ambient, vec3_t res_dir)
static void Doom_LightPointValues(model_t *model, vec3_t point, vec3_t res_diffuse, vec3_t res_ambient, vec3_t res_dir)
{
doommap_t *dm = model->meshinfo;
msector_t *sec;
sec = dm->sector + Doom_SectorNearPoint(dm, point);
sec = Doom_SectorNearPoint(dm, point);
res_dir[0] = 0;
res_dir[1] = 1;
@ -2291,31 +2337,41 @@ void Doom_LightPointValues(model_t *model, vec3_t point, vec3_t res_diffuse, vec
}
//return pvs bits for point
unsigned int Doom_FatPVS(struct model_s *model, vec3_t org, pvsbuffer_t *pvsbuffer, qboolean merge)
static unsigned int Doom_FatPVS(struct model_s *model, vec3_t org, pvsbuffer_t *pvsbuffer, qboolean merge)
{
//FIXME: use REJECT lump.
return 0;
}
//check if an ent is within the given pvs
qboolean Doom_EdictInFatPVS(struct model_s *model, struct pvscache_s *edict, qbyte *pvsbuffer)
static qboolean Doom_EdictInFatPVS(struct model_s *model, struct pvscache_s *edict, qbyte *pvsbuffer)
{ //FIXME: use REJECT lump.
return true;
}
static int Doom_ClusterForPoint(struct model_s *model, vec3_t point)
{
doommap_t *dm = model->meshinfo;
return Doom_SectorNearPoint(dm, point) - dm->sector;
}
static qbyte *Doom_ClusterPVS(struct model_s *model, int cluster, pvsbuffer_t *pvsbuffer, pvsmerge_t merge)
{ //FIXME: use REJECT lump.
return NULL;
}
//generate useful info for correct functioning of Doom_EdictInFatPVS.
void Doom_FindTouchedLeafs(struct model_s *model, struct pvscache_s *ent, vec3_t cullmins, vec3_t cullmaxs)
static void Doom_FindTouchedLeafs(struct model_s *model, struct pvscache_s *ent, vec3_t cullmins, vec3_t cullmaxs)
{
//work out the sectors this ent is in for easy pvs.
}
//requires lightmaps - not supported.
void Doom_StainNode(struct mnode_s *node, float *parms)
static void Doom_StainNode(struct mnode_s *node, float *parms)
{
}
//requires lightmaps - not supported.
void Doom_MarkLights(struct dlight_s *light, int bit, struct mnode_s *node)
static void Doom_MarkLights(struct dlight_s *light, int bit, struct mnode_s *node)
{
}
@ -2327,6 +2383,8 @@ void Doom_SetModelFunc(model_t *mod)
mod->funcs.FatPVS = Doom_FatPVS;
mod->funcs.EdictInFatPVS = Doom_EdictInFatPVS;
mod->funcs.FindTouchedLeafs = Doom_FindTouchedLeafs;
mod->funcs.ClusterForPoint = Doom_ClusterForPoint;
mod->funcs.ClusterPVS = Doom_ClusterPVS;
mod->funcs.LightPointValues = Doom_LightPointValues;
mod->funcs.StainNode = Doom_StainNode;
@ -2334,8 +2392,8 @@ void Doom_SetModelFunc(model_t *mod)
// mod->funcs.LeafPVS) (struct model_s *model, int num, qbyte *buffer, unsigned int buffersize);
mod->funcs.NativeTrace = Doom_Trace;
mod->funcs.PointContents = Doom_PointContents;
mod->funcs.NativeTrace = Doom_Trace;
mod->funcs.PointContents = Doom_PointContents;
//Doom_SetCollisionFuncs(mod);
}

View File

@ -226,11 +226,12 @@ typedef struct {
qboolean geometryshaders;
qboolean ext_framebuffer_objects;
qboolean arb_framebuffer_srgb;
// qboolean arb_fragment_program;
qboolean arb_shader_objects;
qboolean arb_shadow;
qboolean arb_depth_texture;
qboolean ext_framebuffer_objects;
qboolean ext_stencil_wrap;
qboolean ext_packed_depth_stencil;
qboolean arb_depth_clamp;
@ -300,8 +301,6 @@ extern vec3_t r_origin;
//
extern refdef_t r_refdef;
extern unsigned int r_viewcontents;
extern mleaf_t *r_viewleaf, *r_oldviewleaf;
extern mleaf_t *r_viewleaf2, *r_oldviewleaf2;
extern int r_viewcluster, r_viewcluster2, r_oldviewcluster, r_oldviewcluster2; //q2
extern texture_t *r_notexture_mip;
extern int d_lightstylevalue[256]; // 8.8 fraction of base light value

View File

@ -610,7 +610,9 @@ typedef void (APIENTRYP PFNGLGETSHADERSOURCEARBPROC) (GLhandleARB obj, GLsizei
#define GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB 0x20B2
#define WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB 0x20A9
#define GL_FRAMEBUFFER_SRGB 0x8DB9
#define GL_FRAMEBUFFER_SRGB_CAPABLE 0x8DBA
#endif
#ifndef GL_FRAMEBUFFER_SRGB_CAPABLE_EXT
#define GL_FRAMEBUFFER_SRGB_CAPABLE_EXT 0x8DBA
#endif
#ifndef GL_EXT_texture_sRGB
@ -754,7 +756,9 @@ typedef void (APIENTRY * PFNGLUNLOCKARRAYSEXTPROC) (void);
#endif
#ifndef GL_ARB_framebuffer_object
#define GL_DRAW_FRAMEBUFFER_ARB 0x8CA9
#define GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE 0x8217
#define GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING_ARB 0x8210
#endif
#ifndef GL_VERSION_3_0

File diff suppressed because it is too large Load Diff

View File

@ -18,21 +18,6 @@ r_part pe_default
scalefactor 0.8
}
r_part TEQ2_LASER_SPARKS
{
texture "classicparticle"
tcoords 0 0 16 16 32
count 1
scale 1
alpha 1
die 0.3 0.8
randomvel 20
orgadd 0 7
spawnorg 4
gravity 40
scalefactor 0.8
}
r_part te_splashsparks
{
texture "classicparticle"
@ -143,7 +128,56 @@ r_part te_splashblood
colorindex 0xe8
}
r_part teq2_laser_sparks
{
texture "classicparticle"
tcoords 0 0 16 16 32
count 1
scale 1
alpha 1
die 0.3 0.8
randomvel 20
orgadd 0 7
spawnorg 4
gravity 40
scalefactor 0.8
}
r_part teq2_welding_sparks
{ //identical to teq2_laser_sparks, except for the +form that adds in some extra mesh+lighting effect.
texture "classicparticle"
tcoords 0 0 16 16 32
count 1
scale 1
alpha 1
die 0.3 0.8
randomvel 20
orgadd 0 7
spawnorg 4
gravity 40
scalefactor 0.8
}
r_part +teq2_welding_sparks
{
count 0 0 1
model "models/objects/flash/tris.md2" framestart=0 frameend=2 framerate=10 alpha=-1 fullbright
lightradius 100 175
lightradiusfade 400
lightrgb 1 1 0.3
}
r_part teq2_tunnel_sparks
{ //this is apparently identical to teq2_laser_sparks... either way the protocol provides a palette colour (particle system provides a customised variation)
texture "classicparticle"
tcoords 0 0 16 16 32
count 1
scale 1
alpha 1
die 0.3 0.8
randomvel 20
orgadd 0 7
spawnorg 4
gravity 40
scalefactor 0.8
}
r_part teq2_shield_sparks
{
texture "classicparticle"
@ -258,11 +292,68 @@ r_part teq2_blood
scalefactor 0.8
colorindex 232 7
}
r_part teq2_moreblood
{ //teq2_blood, but with count 250 instead of 60.
texture "classicparticle"
tcoords 0 0 16 16 32
count 250
scale 1
alpha 1
die 0.3 0.8
randomvel 20
orgadd 0 31
spawnorg 4
gravity 40
scalefactor 0.8
colorindex 232 7
}
r_part teq2_greenblood
{
texture "classicparticle"
tcoords 0 0 16 16 32
count 30
scale 1
alpha 1
die 0.3 0.8
randomvel 20
orgadd 0 31
spawnorg 4
gravity 40
scalefactor 0.8
colorindex 0xdf 7
}
r_part teq2_electric_sparks
{
texture "classicparticle"
tcoords 0 0 16 16 32
count 40
scale 1
alpha 1
die 0.3 0.8
randomvel 20
orgadd 0 31
spawnorg 4
gravity 40
scalefactor 0.8
colorindex 0x75 7
sound "weapons/lashit.wav" 1 1 0 0
}
r_part q2_blasterpuff
{
count 0 0 1
model "models/objects/explode/tris.md2" framestart=0 frameend=4 framerate=10 alpha=1 orient additive fullbright noshadow
model "models/objects/explode/tris.md2" framestart=0 frameend=4 framerate=10 alpha=1 orient additive fullbright noshadow skin=0
}
r_part q2_blaster2puff
{
count 0 0 1
model "models/objects/explode/tris.md2" framestart=0 frameend=4 framerate=10 alpha=1 orient additive fullbright noshadow skin=1
}
r_part q2_flechettepuff
{
count 0 0 1
model "models/objects/explode/tris.md2" framestart=0 frameend=4 framerate=10 alpha=1 orient additive fullbright noshadow skin=2
}
r_part teq2_blaster
{
@ -301,13 +392,35 @@ r_part teq2_blaster2
gravity 40
scalefactor 0.8
colorindex 0xd0 7
assoc q2_blasterpuff /*the model*/
assoc q2_blaster2puff /*the model*/
lightradius 150
lightradiusfade 400
lightrgb 0.05 1.0 0.05
lightshadows 1
sound "weapons/lashit.wav" 1 1 0 0
}
r_part teq2_flechette
{ //grey version.
texture "classicparticle"
tcoords 0 0 16 16 32
count 60
scale 1
alpha 1
die 0.3 0.8
randomvel 40
orgadd 0 15
veladd 30
spawnorg 4
gravity 40
scalefactor 0.8
colorindex 0x6f 7
assoc q2_flechettepuff /*the model*/
lightradius 150
lightradiusfade 400
lightrgb 0.19 0.41 0.75
lightshadows 1
sound "weapons/lashit.wav" 1 1 0 0
}
r_part TR_BLASTERTRAIL
{
texture "classicparticle"

View File

@ -282,7 +282,7 @@ optimisations_t optimisations[] =
{&opt_locals_overlapping, "lo", 2, FLAG_KILLSDEBUGGERS, "locals_overlapping", "Store all locals in a single section of the pr_globals. Vastly reducing it. This effectivly does the job of overlaptemps.\nHowever, locals are no longer automatically initialised to 0 (and never were in the case of recursion, but at least then its the same type).\nIf locals appear uninitialised, fteqcc will disable this optimisation for the affected functions, you can optionally get a warning about these locals using: #pragma warning enable F302"},
{&opt_vectorcalls, "vc", 4, FLAG_KILLSDEBUGGERS, "vectorcalls", "Where a function is called with just a vector, this causes the function call to store three floats instead of one vector. This can save a good number of pr_globals where those vectors contain many duplicate coordinates but do not match entirly."},
{&opt_classfields, "cf", 2, FLAG_KILLSDEBUGGERS, "class_fields", "Strip class field names. This will harm debugging and can result in 'gibberish' names appearing in saved games. Has no effect on engines other than FTEQW, which will not recognise these anyway."},
// {&opt_stripunusedfields, "uf", 4, 0, "strip_unused_fields","Strips any fields that have no references. This may result in extra warnings at load time, or disabling support for mapper-specified alpha in engines that do not provide that."},
// {&opt_stripunusedfields, "uf", 4, 0, "strip_unused_fields","FIXME: needs relocs. Strips any fields that have no references. This may result in extra warnings at load time, or disabling support for mapper-specified alpha in engines that do not provide that."},
{NULL}
};

View File

@ -11536,7 +11536,7 @@ void PR_DumpPlatform_f(void)
{"CSQC_Input_Frame", "__used void()", CS, "Called just before each time clientcommandframe is updated. You can edit the input_* globals in order to apply your own player inputs within csqc, which may allow you a convienient way to pass certain info to ssqc."},
{"CSQC_RendererRestarted", "void(string rendererdescription)", CS, "Called by the engine after the video was restarted. This serves to notify the CSQC that any render targets that it may have cached were purged, and will need to be regenerated."},
{"CSQC_ConsoleCommand", "float(string cmd)", CS, "Called if the user uses any console command registed via registercommand."},
{"CSQC_ConsoleLink", "float(string text, string info)", CS, "Called if the user clicks a ^[text\\infokey\\infovalue^] link. Use infoget to read/check each supported key. Return true if you wish the engine to not attempt to handle the link itself."},
{"CSQC_ConsoleLink", "float(string text, string info)", CS, "Called if the user clicks a ^[text\\infokey\\infovalue^] link. Use infoget to read/check each supported key. Return true if you wish the engine to not attempt to handle the link itself.\nWARNING: link text can potentially come from other players, so be careful about what you allow to be changed."},
{"CSQC_Ent_Update", "void(float isnew)", CS},
{"CSQC_Ent_Remove", "void()", CS},
{"CSQC_Event_Sound", "float(float entnum, float channel, string soundname, float vol, float attenuation, vector pos, float pitchmod, float flags"/*", float timeofs*/")", CS},

View File

@ -1343,31 +1343,42 @@ void SV_AutoSave(void)
return;
if (sv.state != ss_active)
return;
//don't bother to autosave multiplayer games.
//this may be problematic with splitscreen, but coop rules tend to apply there anyway.
if (sv.allocated_client_slots != 1)
switch(svs.gametype)
{
default: //probably broken. don't ever try.
return;
for (i = 0; i < sv.allocated_client_slots; i++)
{
if (svs.clients[i].state == cs_spawned)
#ifdef VM_LUA
case GT_LUA:
#endif
case GT_Q1QVM:
case GT_PROGS:
//don't bother to autosave multiplayer games.
//this may be problematic with splitscreen, but coop rules tend to apply there anyway.
if (sv.allocated_client_slots != 1)
return;
for (i = 0; i < sv.allocated_client_slots; i++)
{
if (svs.clients[i].edict->v->health <= 0)
return; //autosaves with a dead player are just cruel.
if (svs.clients[i].state == cs_spawned)
{
if (svs.clients[i].edict->v->health <= 0)
return; //autosaves with a dead player are just cruel.
if ((int)svs.clients[i].edict->v->flags & (FL_GODMODE | FL_NOTARGET))
return; //autosaves to highlight cheaters is also just spiteful.
if ((int)svs.clients[i].edict->v->flags & (FL_GODMODE | FL_NOTARGET))
return; //autosaves to highlight cheaters is also just spiteful.
if (svs.clients[i].edict->v->movetype != MOVETYPE_WALK)
return; //noclip|fly are cheaters, toss|bounce are bad at playing. etc.
if (svs.clients[i].edict->v->movetype != MOVETYPE_WALK)
return; //noclip|fly are cheaters, toss|bounce are bad at playing. etc.
if (!((int)svs.clients[i].edict->v->flags & FL_ONGROUND))
return; //autosaves while people are jumping are awkward.
if (!((int)svs.clients[i].edict->v->flags & FL_ONGROUND))
return; //autosaves while people are jumping are awkward.
if (svs.clients[i].edict->v->velocity[0] || svs.clients[i].edict->v->velocity[1] || svs.clients[i].edict->v->velocity[2])
return; //people running around are likely to result in poor saves
if (svs.clients[i].edict->v->velocity[0] || svs.clients[i].edict->v->velocity[1] || svs.clients[i].edict->v->velocity[2])
return; //people running around are likely to result in poor saves
}
}
break;
}
autosavename = M_ChooseAutoSave();

View File

@ -303,10 +303,10 @@ static qboolean SV_AddCSQCUpdate (client_t *client, edict_t *ent)
#ifndef PEXT_CSQC
return false;
#else
if (!(client->csqcactive))
if (!ent->xv->SendEntity)
return false;
if (!ent->xv->SendEntity)
if (!(client->csqcactive))
return false;
csqcent[csqcnuments++] = ent;
@ -3682,8 +3682,11 @@ void SV_Snapshot_BuildQ1(client_t *client, packet_entities_t *pack, pvscamera_t
}
else
{
// ignore ents without visible models
if (!ent->xv->SendEntity && (!ent->v->modelindex || !*PR_GetString(svprogfuncs, ent->v->model)) && !((int)ent->xv->pflags & PFLAGS_FULLDYNAMIC) && ent->v->skin >= 0)
// many ents are not intended to be networked.
if (!(ent->xv->SendEntity && client->csqcactive) && //if SendEntity is set then its definitely important, even if not visible.
(!ent->v->modelindex || !*PR_GetString(svprogfuncs, ent->v->model)) && // also definitely valid if it has a model
!((int)ent->xv->pflags & PFLAGS_FULLDYNAMIC) && //needs to be networked if its giving off realtime lights, even when it has no model.
ent->v->skin >= 0) //ents with negative skins are networked too. eg ladder volumes.
continue;
if (cameras) //self doesn't get a pvs test, to cover teleporters

View File

@ -75,19 +75,19 @@ cvar_t pm_walljump = CVARF("pm_walljump", "", CVAR_SERVERINFO);
#define cvargroup_serverphysics "server physics variables"
void WPhys_Init(void)
{
Cvar_Register (&sv_maxvelocity, cvargroup_serverphysics);
Cvar_Register (&sv_gravity, cvargroup_serverphysics);
Cvar_Register (&sv_stopspeed, cvargroup_serverphysics);
Cvar_Register (&sv_maxspeed, cvargroup_serverphysics);
Cvar_Register (&sv_spectatormaxspeed, cvargroup_serverphysics);
Cvar_Register (&sv_accelerate, cvargroup_serverphysics);
Cvar_Register (&sv_airaccelerate, cvargroup_serverphysics);
Cvar_Register (&sv_wateraccelerate, cvargroup_serverphysics);
Cvar_Register (&sv_friction, cvargroup_serverphysics);
Cvar_Register (&sv_waterfriction, cvargroup_serverphysics);
Cvar_Register (&sv_sound_watersplash, cvargroup_serverphysics);
Cvar_Register (&sv_sound_land, cvargroup_serverphysics);
Cvar_Register (&sv_stepheight, cvargroup_serverphysics);
Cvar_Register (&sv_maxvelocity, cvargroup_serverphysics);
Cvar_Register (&sv_gravity, cvargroup_serverphysics);
Cvar_Register (&sv_stopspeed, cvargroup_serverphysics);
Cvar_Register (&sv_maxspeed, cvargroup_serverphysics);
Cvar_Register (&sv_spectatormaxspeed, cvargroup_serverphysics);
Cvar_Register (&sv_accelerate, cvargroup_serverphysics);
Cvar_Register (&sv_airaccelerate, cvargroup_serverphysics);
Cvar_Register (&sv_wateraccelerate, cvargroup_serverphysics);
Cvar_Register (&sv_friction, cvargroup_serverphysics);
Cvar_Register (&sv_waterfriction, cvargroup_serverphysics);
Cvar_Register (&sv_sound_watersplash, cvargroup_serverphysics);
Cvar_Register (&sv_sound_land, cvargroup_serverphysics);
Cvar_Register (&sv_stepheight, cvargroup_serverphysics);
Cvar_Register (&sv_gameplayfix_noairborncorpse, cvargroup_serverphysics);
Cvar_Register (&sv_gameplayfix_multiplethinks, cvargroup_serverphysics);
@ -1365,7 +1365,7 @@ static void WPhys_Physics_Toss (world_t *w, wedict_t *ent)
#pragma warningmsg("The following line might help boost framerates a lot in rmq, not sure if they violate expected behaviour in other mods though - check that they're safe.")
VectorNegate(gravitydir, trace.plane.normal);
}
if (trace.fraction == 1)
if (trace.fraction == 1 || !trace.ent)
return;
if (ED_ISFREE(ent))
return;

View File

@ -691,6 +691,9 @@ static cvar_t *VARGS Q2Cvar_Get (const char *var_name, const char *value, int fl
//q2 gamecode knows about these flags. anything else is probably a bug, or 3rd-party extension.
flags &= (CVAR_NOSET|CVAR_SERVERINFO|CVAR_USERINFO|CVAR_ARCHIVE|CVAR_LATCH);
if (!strcmp(var_name, "gamedir"))
var_name = "fs_gamedir";
var = Cvar_Get(var_name, value, flags, "Quake2 game variables");
if (!var)
{

View File

@ -2906,7 +2906,6 @@ void SVQ3_ParseUsercmd(client_t *client, qboolean delta)
// read delta sequenced usercmds
from = &nullcmd;
from->servertime = client->lastcmd.servertime;
for(i=0, to=commands; i<cmdCount; i++, to++)
{
MSG_Q3_ReadDeltaUsercmd(key, from, to);
@ -2963,11 +2962,13 @@ void SVQ3_ParseUsercmd(client_t *client, qboolean delta)
temp.sidemove *= client->maxspeed/127.0f;
temp.forwardmove *= client->maxspeed/127.0f;
temp.upmove *= client->maxspeed/127.0f;
temp.msec = bound(0, to->servertime - temp.servertime, 255);
temp.buttons &= ~2;
if (temp.buttons & 64)
temp.buttons |= 2;
SV_RunCmd(&temp, false);
client->lastcmd.servertime = to->servertime;
}
}
if (svs.gametype != GT_QUAKE3)

View File

@ -559,7 +559,9 @@ void QDECL World_LinkEdict (world_t *w, wedict_t *ent, qboolean touch_triggers)
VectorAdd (ent->v->origin, ent->v->maxs, ent->v->absmax);
}
if (ent->v->modelindex)
if (!ent->v->solid)
ent->solidsize = ES_SOLID_BSP;
else// if (1)///*ent->v->modelindex || */ent->v->model)
{
model_t *mod = w->Get_CModel(w, ent->v->modelindex);
if (mod && mod->type == mod_brush)
@ -567,8 +569,6 @@ void QDECL World_LinkEdict (world_t *w, wedict_t *ent, qboolean touch_triggers)
else
ent->solidsize = COM_EncodeSize(ent->v->mins, ent->v->maxs);
}
else
ent->solidsize = ES_SOLID_BSP;
//
// to make items easier to pick up and allow them to be grabbed off
@ -1167,7 +1167,7 @@ static trace_t World_ClipMoveToEntity (world_t *w, wedict_t *ent, vec3_t eorg, v
}
// did we clip the move?
if (trace.fraction < 1 || trace.startsolid)
if (trace.fraction < 1 || trace.startsolid || trace.allsolid)
trace.ent = ent;
return trace;

View File

@ -24,8 +24,8 @@ makevulkanblob: makevulkanblob.c
vulkanblobs/%.fvb: vulkan/%.glsl makevulkanblob vulkan/sys/defs.h vulkan/sys/fog.h vulkan/sys/offsetmapping.h vulkan/sys/skeletal.h
./makevulkanblob $< $@
vulkanblobs/%.fvb: glsl/%.glsl makevulkanblob vulkan/sys/defs.h vulkan/sys/fog.h vulkan/sys/offsetmapping.h vulkan/sys/skeletal.h
./makevulkanblob $< $@
#vulkanblobs/%.fvb: glsl/%.glsl makevulkanblob vulkan/sys/defs.h vulkan/sys/fog.h vulkan/sys/offsetmapping.h vulkan/sys/skeletal.h
# ./makevulkanblob $< $@
all: generatebuiltinsl $(ALLNAMES)

View File

@ -1,18 +1,28 @@
!!cvarf r_glsl_turbscale=1
!!permu FOG
!!cvarb r_fog_exp2=true
!!cvarf r_glsl_turbscale_reflect=1
!!cvarf r_glsl_turbscale_refract=1
!!cvarf gl_maxdist=8192
!!cvarf gl_mindist=4
!!samps normalmap diffuse 4
!!argb reflect=0 //s_t1 is a reflection instead of diffusemap
!!argf strength=0.1 //0.1 = fairly gentle, 0.2 = big waves
!!argf fresnel=5.0 //water should be around 5
!!argf txscale=0.2 //wave strength
!!argf strength_refl=0.1 //0.1 = fairly gentle, 0.2 = big waves
!!argf strength_refr=0.1 //0.1 = fairly gentle, 0.2 = big waves
!!argf fresnel_exp=5.0 //water should be around 5
!!argf fresnel_range=1.0
!!argf fresnel_min=1.0
!!argf txscale1=0.2 //wave strength
!!argf txscale2=0.2 //wave strength
!!argb ripplemap=0 //s_t2 contains a ripplemap
!!arg3f tint=0.7 0.8 0.7 //some colour value
!!arg3f tint_refr=0.7 0.8 0.7 //some colour value
!!arg3f tint_refl=0.7 0.8 0.7 //some colour value
!!argb depth=0 //s_t3 is a depth image
!!argf alpha=0 //blend in the alpha channel
!!arg3f fogtint=0.2 0.3 0.2 //tints as it gets deeper
#include "sys/defs.h"
#include "sys/fog.h"
layout(location=0) varying vec2 tc;
layout(location=1) varying vec4 tf;
@ -49,15 +59,16 @@ void main (void)
ntc.t = tc.t + sin(tc.s+e_time)*0.125;
//generate the two wave patterns from the normalmap
n = (texture2D(s_normalmap, arg_txscale*tc + vec2(e_time*0.1, 0.0)).xyz);
n += (texture2D(s_normalmap, arg_txscale*tc - vec2(0, e_time*0.097)).xyz);
n = (texture2D(s_normalmap, arg_txscale1*tc + vec2(e_time*0.1, 0.0)).xyz);
n += (texture2D(s_normalmap, arg_txscale2*tc - vec2(0, e_time*0.097)).xyz);
n -= 1.0 - 4.0/256.0;
if (arg_ripplemap)
n += texture2D(s_ripplemap, stc).rgb*3.0;
n = normalize(n);
//the fresnel term decides how transparent the water should be
fres = pow(1.0-abs(dot(normalize(n), normalize(eye))), arg_fresnel);
fres = pow(1.0-abs(dot(n, normalize(eye))), arg_fresnel_exp) * arg_fresnel_range + arg_fresnel_min;
if (arg_depth)
{
@ -91,14 +102,14 @@ void main (void)
//refraction image (and water fog, if possible)
refr = texture2D(s_refract, stc + n.st*arg_strength*cvar_r_glsl_turbscale).rgb * arg_tint;
refr = texture2D(s_refract, stc + n.st*arg_strength_refr*cvar_r_glsl_turbscale_refract).rgb * arg_tint_refr;
if (arg_depth)
refr = mix(refr, arg_fogtint, min(depth/4096.0, 1.0));
//reflection/diffuse
if (arg_reflect)
refl = texture2D(s_reflect, stc - n.st*arg_strength*cvar_r_glsl_turbscale).rgb;
else
if (arg_reflect)
refl = texture2D(s_reflect, stc - n.st*arg_strength_refl*cvar_r_glsl_turbscale_reflect).rgb * arg_tint_refl;
else
refl = texture2D(s_diffuse, ntc).xyz;
//FIXME: add specular tints
@ -106,6 +117,13 @@ else
//interplate by fresnel
refr = mix(refr, refl, fres);
if (arg_alpha != 0)
{
vec4 ts = texture2D(s_diffuse, ntc);
vec4 surf = fog4blend(vec4(ts.rgb, arg_alpha*ts.a));
refr = mix(refr, surf.rgb, surf.a);
}
//done
gl_FragColor = vec4(refr, 1.0);
}

View File

@ -208,16 +208,9 @@ typedef struct
float curtime;
const entity_t *curentity;
const dlight_t *curdlight;
// vec3_t curdlight_colours;
shader_t *curshader;
shader_t *depthonly;
texnums_t *curtexnums;
int curvertdecl;
// unsigned int shaderbits;
// unsigned int curcull;
// float depthbias;
// float depthfactor;
// unsigned int lastpasscount;
vbo_t *batchvbo;
batch_t *curbatch;
batch_t dummybatch;
@ -252,7 +245,6 @@ typedef struct
//descriptor sets are: 0) entity+light 1) batch textures + pass textures
VkDescriptorSet descriptorsets[1];
// VkDescriptorPool texturedescpool[2];
//commandbuffer state, to avoid redundant state changes.
VkPipeline activepipeline;
@ -456,6 +448,8 @@ static void VK_FinishProg(program_t *prog, const char *name)
descSetLayoutCreateInfo.bindingCount = db-dbs;
descSetLayoutCreateInfo.pBindings = dbs;
if (vk.khr_push_descriptor)
descSetLayoutCreateInfo.flags |= VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR;
VkAssert(vkCreateDescriptorSetLayout(vk.device, &descSetLayoutCreateInfo, NULL, &desclayout));
prog->desclayout = desclayout;
}
@ -1142,10 +1136,9 @@ qboolean VK_LoadBlob(program_t *prog, void *blobdata, const char *name)
prog->pipelines = NULL; //generated as needed, depending on blend states etc.
return true;
}
void VKBE_DeleteProg(program_t *prog)
{
static void VKBE_ReallyDeleteProg(program_t *prog)
{ //nothing else is refering to this data any more, its safe to obliterate it.
struct pipeline_s *pipe;
Z_Free(prog->cvardata);
while(prog->pipelines)
{
pipe = prog->pipelines;
@ -1157,15 +1150,25 @@ void VKBE_DeleteProg(program_t *prog)
}
if (prog->layout)
vkDestroyPipelineLayout(vk.device, prog->layout, vkallocationcb);
prog->layout = VK_NULL_HANDLE;
if (prog->desclayout)
vkDestroyDescriptorSetLayout(vk.device, prog->desclayout, vkallocationcb);
prog->desclayout = VK_NULL_HANDLE;
if (prog->vert)
vkDestroyShaderModule(vk.device, prog->vert, vkallocationcb);
prog->vert = VK_NULL_HANDLE;
if (prog->frag)
vkDestroyShaderModule(vk.device, prog->frag, vkallocationcb);
}
void VKBE_DeleteProg(program_t *prog)
{
//schedule the deletes when its safe to do so.
VK_AtFrameEnd(VKBE_ReallyDeleteProg, prog, sizeof(*prog));
//clear stuff out so that the caller doesn't get confused.
Z_Free(prog->cvardata);
prog->pipelines = NULL;
prog->layout = VK_NULL_HANDLE;
prog->desclayout = VK_NULL_HANDLE;
prog->vert = VK_NULL_HANDLE;
prog->frag = VK_NULL_HANDLE;
}
@ -1217,7 +1220,6 @@ void VKBE_Init(void)
be_maxpasses = 1;
memset(&shaderstate, 0, sizeof(shaderstate));
shaderstate.inited = true;
shaderstate.curvertdecl = -1;
for (i = 0; i < MAXRLIGHTMAPS; i++)
shaderstate.dummybatch.lightmap[i] = -1;
@ -1366,66 +1368,82 @@ static VkDescriptorSet VKBE_TempDescriptorSet(VkDescriptorSetLayout layout)
}
//creates a new dynamic buffer for us to use while streaming. because spoons.
static struct dynbuffer *VKBE_AllocNewBuffer(struct dynbuffer **link, enum dynbuf_e type)
static struct dynbuffer *VKBE_AllocNewBuffer(struct dynbuffer **link, enum dynbuf_e type, VkDeviceSize minsize)
{
VkBufferUsageFlags ufl[] = {VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, VK_BUFFER_USAGE_INDEX_BUFFER_BIT, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT};
VkBufferUsageFlags ufl[] = {VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, VK_BUFFER_USAGE_INDEX_BUFFER_BIT, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_BUFFER_USAGE_TRANSFER_SRC_BIT};
VkBufferCreateInfo bufinf = {VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO};
VkMemoryRequirements mem_reqs;
VkMemoryAllocateInfo memAllocInfo = {VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO};
struct dynbuffer *n = Z_Malloc(sizeof(*n));
qboolean usestaging = (vk_usedynamicstaging & (1u<<type))!=0;
bufinf.flags = 0;
bufinf.size = n->size = (1u<<20);
bufinf.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
bufinf.queueFamilyIndexCount = 0;
bufinf.pQueueFamilyIndices = NULL;
if (vk_usedynamicstaging & (1u<<type))
while(1)
{
bufinf.usage = ufl[type]|VK_BUFFER_USAGE_TRANSFER_DST_BIT;
vkCreateBuffer(vk.device, &bufinf, vkallocationcb, &n->devicebuf);
bufinf.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
vkCreateBuffer(vk.device, &bufinf, vkallocationcb, &n->stagingbuf);
bufinf.flags = 0;
bufinf.size = n->size = (1u<<20);
bufinf.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
bufinf.queueFamilyIndexCount = 0;
bufinf.pQueueFamilyIndices = NULL;
vkGetBufferMemoryRequirements(vk.device, n->devicebuf, &mem_reqs);
while (bufinf.size < minsize)
bufinf.size *= 2;
n->size = bufinf.size;
if (type != DB_STAGING && usestaging)
{
//create two buffers, one staging/host buffer and one device buffer
bufinf.usage = ufl[type]|VK_BUFFER_USAGE_TRANSFER_DST_BIT;
vkCreateBuffer(vk.device, &bufinf, vkallocationcb, &n->devicebuf);
bufinf.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
vkCreateBuffer(vk.device, &bufinf, vkallocationcb, &n->stagingbuf);
vkGetBufferMemoryRequirements(vk.device, n->devicebuf, &mem_reqs);
n->align = mem_reqs.alignment-1;
memAllocInfo.allocationSize = mem_reqs.size;
memAllocInfo.memoryTypeIndex = vk_find_memory_require(mem_reqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
VkAssert(vkAllocateMemory(vk.device, &memAllocInfo, vkallocationcb, &n->devicememory));
VkAssert(vkBindBufferMemory(vk.device, n->devicebuf, n->devicememory, 0));
n->renderbuf = n->devicebuf;
}
else
{ //single buffer. we'll write directly to the buffer.
bufinf.usage = ufl[type];
vkCreateBuffer(vk.device, &bufinf, vkallocationcb, &n->stagingbuf);
n->renderbuf = n->stagingbuf;
}
//now allocate some host-visible memory for the buffer that we're going to map.
vkGetBufferMemoryRequirements(vk.device, n->stagingbuf, &mem_reqs);
n->align = mem_reqs.alignment-1;
memAllocInfo.allocationSize = mem_reqs.size;
memAllocInfo.memoryTypeIndex = vk_find_memory_require(mem_reqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
memAllocInfo.memoryTypeIndex = ~0;
// if (memAllocInfo.memoryTypeIndex == ~0)
// memAllocInfo.memoryTypeIndex = vk_find_memory_try(mem_reqs.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT|VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
if (memAllocInfo.memoryTypeIndex == ~0 && n->renderbuf == n->stagingbuf) //probably won't get anything, but whatever.
memAllocInfo.memoryTypeIndex = vk_find_memory_try(mem_reqs.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT|VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
if (memAllocInfo.memoryTypeIndex == ~0)
memAllocInfo.memoryTypeIndex = vk_find_memory_require(mem_reqs.memoryTypeBits, 0); //device will still be okay with this usage...
VkAssert(vkAllocateMemory(vk.device, &memAllocInfo, vkallocationcb, &n->devicememory));
VkAssert(vkBindBufferMemory(vk.device, n->devicebuf, n->devicememory, 0));
memAllocInfo.memoryTypeIndex = vk_find_memory_try(mem_reqs.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
if (memAllocInfo.memoryTypeIndex == ~0)
{ //if we can't find any usable memory, force staging instead.
vkDestroyBuffer(vk.device, n->stagingbuf, vkallocationcb);
if (usestaging)
Sys_Error("Unable to allocate buffer memory");
usestaging = true;
continue;
}
VkAssert(vkAllocateMemory(vk.device, &memAllocInfo, vkallocationcb, &n->stagingmemory));
VkAssert(vkBindBufferMemory(vk.device, n->stagingbuf, n->stagingmemory, 0));
n->renderbuf = n->devicebuf;
VkAssert(vkMapMemory(vk.device, n->stagingmemory, 0, n->size, 0, &n->ptr)); //persistent-mapped.
n->stagingcoherent = !!(vk.memory_properties.memoryTypes[memAllocInfo.memoryTypeIndex].propertyFlags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
n->next = *link;
*link = n;
return n;
}
else
{
bufinf.usage = ufl[type];
vkCreateBuffer(vk.device, &bufinf, vkallocationcb, &n->stagingbuf);
n->renderbuf = n->stagingbuf;
}
vkGetBufferMemoryRequirements(vk.device, n->stagingbuf, &mem_reqs);
n->align = mem_reqs.alignment-1;
memAllocInfo.allocationSize = mem_reqs.size;
memAllocInfo.memoryTypeIndex = vk_find_memory_try(mem_reqs.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT|VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
if (memAllocInfo.memoryTypeIndex == ~0)
memAllocInfo.memoryTypeIndex = vk_find_memory_try(mem_reqs.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT|VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
// if (memAllocInfo.memoryTypeIndex == ~0)
// memAllocInfo.memoryTypeIndex = vk_find_memory_try(mem_reqs.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT|VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
if (memAllocInfo.memoryTypeIndex == ~0)
memAllocInfo.memoryTypeIndex = vk_find_memory_require(mem_reqs.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
if (memAllocInfo.memoryTypeIndex == ~0)
Sys_Error("Unable to allocate buffer memory");
VkAssert(vkAllocateMemory(vk.device, &memAllocInfo, vkallocationcb, &n->stagingmemory));
VkAssert(vkBindBufferMemory(vk.device, n->stagingbuf, n->stagingmemory, 0));
VkAssert(vkMapMemory(vk.device, n->stagingmemory, 0, n->size, 0, &n->ptr)); //persistent-mapped.
n->next = *link;
*link = n;
return n;
}
static void *fte_restrict VKBE_AllocateBufferSpace(enum dynbuf_e type, size_t datasize, VkBuffer *buf, VkDeviceSize *offset)
{ //FIXME: ubos need alignment
@ -1434,11 +1452,14 @@ static void *fte_restrict VKBE_AllocateBufferSpace(enum dynbuf_e type, size_t da
if (b->offset + datasize > b->size)
{
//flush the old one, just in case.
VkMappedMemoryRange range = {VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE};
range.offset = b->flushed;
range.size = b->offset-b->flushed;
range.memory = b->stagingmemory;
vkFlushMappedMemoryRanges(vk.device, 1, &range);
if (!b->stagingcoherent)
{
VkMappedMemoryRange range = {VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE};
range.offset = b->flushed;
range.size = b->offset-b->flushed;
range.memory = b->stagingmemory;
vkFlushMappedMemoryRanges(vk.device, 1, &range);
}
if (b->devicebuf != VK_NULL_HANDLE)
{
@ -1452,7 +1473,7 @@ static void *fte_restrict VKBE_AllocateBufferSpace(enum dynbuf_e type, size_t da
}
if (!b->next)
VKBE_AllocNewBuffer(&b->next, type);
VKBE_AllocNewBuffer(&b->next, type, datasize);
b = vk.dynbuf[type] = b->next;
b->offset = 0;
b->flushed = 0;
@ -1462,7 +1483,7 @@ static void *fte_restrict VKBE_AllocateBufferSpace(enum dynbuf_e type, size_t da
*offset = b->offset;
ret = (qbyte*)b->ptr + b->offset;
b->offset += datasize;
b->offset += datasize; //FIXME: alignment
return ret;
}
@ -1474,18 +1495,21 @@ void VKBE_InitFramePools(struct vkframe *frame)
for (i = 0; i < DB_MAX; i++)
{
frame->dynbufs[i] = NULL;
VKBE_AllocNewBuffer(&frame->dynbufs[i], i);
VKBE_AllocNewBuffer(&frame->dynbufs[i], i, 0);
}
frame->descpools = VKBE_CreateDescriptorPool();
frame->descpools = vk.khr_push_descriptor?NULL:VKBE_CreateDescriptorPool();
{
frame->numcbufs = 0;
frame->maxcbufs = 0;
frame->cbufs = NULL;
/*{
VkCommandBufferAllocateInfo cbai = {VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO};
cbai.commandPool = vk.cmdpool;
cbai.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
cbai.commandBufferCount = 1;
VkAssert(vkAllocateCommandBuffers(vk.device, &cbai, &frame->cbuf));
}
cbai.commandBufferCount = frame->maxcbufs;
VkAssert(vkAllocateCommandBuffers(vk.device, &cbai, frame->cbufs));
}*/
{
VkFenceCreateInfo fci = {VK_STRUCTURE_TYPE_FENCE_CREATE_INFO};
@ -1509,10 +1533,13 @@ void VKBE_FlushDynamicBuffers(void)
if (d->flushed == d->offset)
continue;
range.offset = d->flushed;
range.size = d->offset - d->flushed;
range.memory = d->stagingmemory;
vkFlushMappedMemoryRanges(vk.device, 1, &range);
if (!d->stagingcoherent)
{
range.offset = d->flushed;
range.size = d->offset - d->flushed;
range.memory = d->stagingmemory;
vkFlushMappedMemoryRanges(vk.device, 1, &range);
}
if (d->devicebuf != VK_NULL_HANDLE)
{
@ -1553,8 +1580,11 @@ void VKBE_RestartFrame(void)
shaderstate.activepipeline = VK_NULL_HANDLE;
vk.descpool = vk.frame->descpools;
vkResetDescriptorPool(vk.device, vk.descpool->pool, 0);
vk.descpool->availsets = vk.descpool->totalsets;
if (vk.descpool)
{
vkResetDescriptorPool(vk.device, vk.descpool->pool, 0);
vk.descpool->availsets = vk.descpool->totalsets;
}
}
void VKBE_ShutdownFramePools(struct vkframe *frame)
@ -1712,14 +1742,14 @@ static void T_Gen_CurrentRender(void)
if (img->width != vid.fbpwidth || img->height != vid.fbpheight)
{
//FIXME: free the old image when its safe to do so.
*img = VK_CreateTexture2DArray(vid.fbpwidth, vid.fbpheight, 1, 1, PTI_BGRA8, PTI_2D);
*img = VK_CreateTexture2DArray(vid.fbpwidth, vid.fbpheight, 1, 1, PTI_BGRA8, PTI_2D, true);
if (!img->sampler)
VK_CreateSampler(shaderstate.tex_currentrender->flags, img);
}
vkCmdEndRenderPass(vk.frame->cbuf);
vkCmdEndRenderPass(vk.rendertarg->cbuf);
//submit now?
@ -1744,17 +1774,17 @@ static void T_Gen_CurrentRender(void)
region.extent.height = vid.fbpheight;
region.extent.depth = 1;
set_image_layout(vk.frame->cbuf, vk.frame->backbuf->colour.image, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_ACCESS_TRANSFER_READ_BIT);
set_image_layout(vk.frame->cbuf, img->image, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_UNDEFINED, 0, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_ACCESS_TRANSFER_WRITE_BIT);
vkCmdCopyImage(vk.frame->cbuf, vk.frame->backbuf->colour.image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, img->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &region);
set_image_layout(vk.frame->cbuf, img->image, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_ACCESS_SHADER_READ_BIT);
set_image_layout(vk.frame->cbuf, vk.frame->backbuf->colour.image, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_ACCESS_TRANSFER_READ_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT);
set_image_layout(vk.rendertarg->cbuf, vk.frame->backbuf->colour.image, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_ACCESS_TRANSFER_READ_BIT);
set_image_layout(vk.rendertarg->cbuf, img->image, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_UNDEFINED, 0, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_ACCESS_TRANSFER_WRITE_BIT);
vkCmdCopyImage(vk.rendertarg->cbuf, vk.frame->backbuf->colour.image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, img->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &region);
set_image_layout(vk.rendertarg->cbuf, img->image, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_ACCESS_SHADER_READ_BIT);
set_image_layout(vk.rendertarg->cbuf, vk.frame->backbuf->colour.image, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_ACCESS_TRANSFER_READ_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT);
}
//submit now?
//barrier?
vkCmdBeginRenderPass(vk.frame->cbuf, &vk.rendertarg->restartinfo, VK_SUBPASS_CONTENTS_INLINE);
vkCmdBeginRenderPass(vk.rendertarg->cbuf, &vk.rendertarg->restartinfo, VK_SUBPASS_CONTENTS_INLINE);
//fixme: viewport+scissor?
}
@ -2760,7 +2790,9 @@ static void BE_CreatePipeline(program_t *p, unsigned int shaderflags, unsigned i
rs.depthBiasEnable = VK_FALSE;
ms.pSampleMask = NULL;
ms.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
ms.rasterizationSamples = vk.multisamplebits;
// ms.sampleShadingEnable = VK_TRUE; //call the fragment shader multiple times, instead of just once per final pixel
// ms.minSampleShading = 0.25;
ds.depthTestEnable = (blendflags&SBITS_MISC_NODEPTHTEST)?VK_FALSE:VK_TRUE;
ds.depthWriteEnable = (blendflags&SBITS_MISC_DEPTHWRITE)?VK_TRUE:VK_FALSE;
if (blendflags & SBITS_MISC_DEPTHEQUALONLY)
@ -2964,7 +2996,7 @@ static void BE_CreatePipeline(program_t *p, unsigned int shaderflags, unsigned i
return;
}
vkCmdBindPipeline(vk.frame->cbuf, VK_PIPELINE_BIND_POINT_GRAPHICS, shaderstate.activepipeline=pipe->pipeline);
vkCmdBindPipeline(vk.rendertarg->cbuf, VK_PIPELINE_BIND_POINT_GRAPHICS, shaderstate.activepipeline=pipe->pipeline);
}
static void BE_BindPipeline(program_t *p, unsigned int shaderflags, unsigned int blendflags, unsigned int permu)
{
@ -2993,7 +3025,7 @@ static void BE_BindPipeline(program_t *p, unsigned int shaderflags, unsigned int
{
shaderstate.activepipeline = pipe->pipeline;
if (shaderstate.activepipeline)
vkCmdBindPipeline(vk.frame->cbuf, VK_PIPELINE_BIND_POINT_GRAPHICS, shaderstate.activepipeline);
vkCmdBindPipeline(vk.rendertarg->cbuf, VK_PIPELINE_BIND_POINT_GRAPHICS, shaderstate.activepipeline);
}
return;
}
@ -3062,7 +3094,7 @@ static qboolean BE_SetupMeshProgram(program_t *p, shaderpass_t *pass, unsigned i
//most gpus will have a fairly low descriptor set limit of 4 (this is the minimum required)
//that isn't enough for all our textures, so we need to make stuff up as required.
{
VkDescriptorSet set = shaderstate.descriptorsets[0] = VKBE_TempDescriptorSet(p->desclayout);
VkDescriptorSet set = shaderstate.descriptorsets[0] = vk.khr_push_descriptor?VK_NULL_HANDLE:VKBE_TempDescriptorSet(p->desclayout);
VkWriteDescriptorSet descs[MAX_TMUS], *desc = descs;
VkDescriptorImageInfo imgs[MAX_TMUS], *img = imgs;
unsigned int i;
@ -3144,9 +3176,13 @@ static qboolean BE_SetupMeshProgram(program_t *p, shaderpass_t *pass, unsigned i
for (i = 0; i < p->numsamplers; i++)
BE_SetupTextureDescriptor(SelectPassTexture(pass+i), r_blackimage, set, descs, desc++, img++);
vkUpdateDescriptorSets(vk.device, desc-descs, descs, 0, NULL);
if (!set)
vkCmdPushDescriptorSetKHR(vk.rendertarg->cbuf, VK_PIPELINE_BIND_POINT_GRAPHICS, p->layout, 0, desc-descs, descs);
else
vkUpdateDescriptorSets(vk.device, desc-descs, descs, 0, NULL);
}
vkCmdBindDescriptorSets(vk.frame->cbuf, VK_PIPELINE_BIND_POINT_GRAPHICS, p->layout, 0, countof(shaderstate.descriptorsets), shaderstate.descriptorsets, 0, NULL);
if (!vk.khr_push_descriptor)
vkCmdBindDescriptorSets(vk.rendertarg->cbuf, VK_PIPELINE_BIND_POINT_GRAPHICS, p->layout, 0, countof(shaderstate.descriptorsets), shaderstate.descriptorsets, 0, NULL);
RQuantAdd(RQUANT_PRIMITIVEINDICIES, idxcount);
RQuantAdd(RQUANT_DRAWS, 1);
@ -3239,7 +3275,7 @@ static void BE_DrawMeshChain_Internal(void)
{
m = shaderstate.meshlist[0];
vkCmdBindIndexBuffer(vk.frame->cbuf, shaderstate.batchvbo->indicies.vk.buff, shaderstate.batchvbo->indicies.vk.offs, VK_INDEX_TYPE);
vkCmdBindIndexBuffer(vk.rendertarg->cbuf, shaderstate.batchvbo->indicies.vk.buff, shaderstate.batchvbo->indicies.vk.offs, VK_INDEX_TYPE);
idxfirst = m->vbofirstelement;
vertcount = m->vbofirstvert + m->numvertexes;
@ -3251,7 +3287,7 @@ static void BE_DrawMeshChain_Internal(void)
vertcount = shaderstate.batchvbo->vertcount;
idxcount = shaderstate.batchvbo->indexcount;
vkCmdBindIndexBuffer(vk.frame->cbuf, shaderstate.batchvbo->indicies.vk.buff, shaderstate.batchvbo->indicies.vk.offs, VK_INDEX_TYPE);
vkCmdBindIndexBuffer(vk.rendertarg->cbuf, shaderstate.batchvbo->indicies.vk.buff, shaderstate.batchvbo->indicies.vk.offs, VK_INDEX_TYPE);
}
else
{
@ -3273,7 +3309,7 @@ static void BE_DrawMeshChain_Internal(void)
map[i] = m->indexes[i]+m->vbofirstvert;
map += m->numindexes;
}
vkCmdBindIndexBuffer(vk.frame->cbuf, buf, offset, VK_INDEX_TYPE);
vkCmdBindIndexBuffer(vk.rendertarg->cbuf, buf, offset, VK_INDEX_TYPE);
idxfirst = 0;
}
}
@ -3304,7 +3340,7 @@ static void BE_DrawMeshChain_Internal(void)
map += m->numindexes;
vertcount += m->numvertexes;
}
vkCmdBindIndexBuffer(vk.frame->cbuf, buf, offset, VK_INDEX_TYPE);
vkCmdBindIndexBuffer(vk.rendertarg->cbuf, buf, offset, VK_INDEX_TYPE);
idxfirst = 0;
}
@ -3522,9 +3558,9 @@ static void BE_DrawMeshChain_Internal(void)
}
}
vkCmdBindVertexBuffers(vk.frame->cbuf, 0, VK_BUFF_MAX, vertexbuffers, vertexoffsets);
vkCmdBindVertexBuffers(vk.rendertarg->cbuf, 0, VK_BUFF_MAX, vertexbuffers, vertexoffsets);
if (BE_SetupMeshProgram(altshader->prog, altshader->passes, altshader->flags, idxcount))
vkCmdDrawIndexed(vk.frame->cbuf, idxcount, 1, idxfirst, 0, 0);
vkCmdDrawIndexed(vk.rendertarg->cbuf, idxcount, 1, idxfirst, 0, 0);
}
else if (1)
{
@ -3559,9 +3595,9 @@ static void BE_DrawMeshChain_Internal(void)
vertexbuffers[VK_BUFF_TDIR] = shaderstate.staticbuf;
vertexoffsets[VK_BUFF_TDIR] = vertexoffsets[VK_BUFF_SDIR] + sizeof(vec3_t)*65536;
vkCmdBindVertexBuffers(vk.frame->cbuf, 0, VK_BUFF_MAX, vertexbuffers, vertexoffsets);
vkCmdBindVertexBuffers(vk.rendertarg->cbuf, 0, VK_BUFF_MAX, vertexbuffers, vertexoffsets);
if (BE_SetupMeshProgram(p->prog, p, altshader->flags, idxcount))
vkCmdDrawIndexed(vk.frame->cbuf, idxcount, 1, idxfirst, 0, 0);
vkCmdDrawIndexed(vk.rendertarg->cbuf, idxcount, 1, idxfirst, 0, 0);
continue;
}
@ -3609,19 +3645,19 @@ static void BE_DrawMeshChain_Internal(void)
vertexbuffers[VK_BUFF_COL] = shaderstate.staticbuf;
vertexoffsets[VK_BUFF_COL] = 0;
vkCmdBindVertexBuffers(vk.frame->cbuf, 0, VK_BUFF_MAX, vertexbuffers, vertexoffsets);
vkCmdBindVertexBuffers(vk.rendertarg->cbuf, 0, VK_BUFF_MAX, vertexbuffers, vertexoffsets);
if (BE_SetupMeshProgram(shaderstate.programfixedemu[1], p, altshader->flags, idxcount))
{
vkCmdPushConstants(vk.frame->cbuf, shaderstate.programfixedemu[1]->layout, VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(passcolour), passcolour);
vkCmdDrawIndexed(vk.frame->cbuf, idxcount, 1, idxfirst, 0, 0);
vkCmdPushConstants(vk.rendertarg->cbuf, shaderstate.programfixedemu[1]->layout, VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(passcolour), passcolour);
vkCmdDrawIndexed(vk.rendertarg->cbuf, idxcount, 1, idxfirst, 0, 0);
}
}
else
{
BE_GenerateColourMods(vertcount, p, &vertexbuffers[VK_BUFF_COL], &vertexoffsets[VK_BUFF_COL]);
vkCmdBindVertexBuffers(vk.frame->cbuf, 0, VK_BUFF_MAX, vertexbuffers, vertexoffsets);
vkCmdBindVertexBuffers(vk.rendertarg->cbuf, 0, VK_BUFF_MAX, vertexbuffers, vertexoffsets);
if (BE_SetupMeshProgram(shaderstate.programfixedemu[0], p, altshader->flags, idxcount))
vkCmdDrawIndexed(vk.frame->cbuf, idxcount, 1, idxfirst, 0, 0);
vkCmdDrawIndexed(vk.rendertarg->cbuf, idxcount, 1, idxfirst, 0, 0);
}
}
}
@ -3929,15 +3965,16 @@ void VKBE_GenBrushModelVBO(model_t *mod)
}
}
/*Wipes a vbo*/
void VKBE_ClearVBO(vbo_t *vbo)
struct vkbe_clearvbo
{
//FIXME: may still be in use by an active commandbuffer.
struct vk_frameend fe;
vbo_t *vbo;
};
static void VKBE_SafeClearVBO(void *vboptr)
{
vbo_t *vbo = *(vbo_t**)vboptr;
VkDeviceMemory *retarded;
if (vbo->indicies.vk.buff || vbo->coord.vk.buff)
vkDeviceWaitIdle(vk.device); //just in case
if (vbo->indicies.vk.buff)
{
vkDestroyBuffer(vk.device, vbo->indicies.vk.buff, vkallocationcb);
@ -3956,12 +3993,18 @@ void VKBE_ClearVBO(vbo_t *vbo)
BZ_Free(vbo);
}
/*Wipes a vbo*/
void VKBE_ClearVBO(vbo_t *vbo)
{
VK_AtFrameEnd(VKBE_SafeClearVBO, &vbo, sizeof(vbo));
}
void VK_UploadLightmap(lightmapinfo_t *lm)
{
extern cvar_t gl_lightmap_nearest;
struct pendingtextureinfo mips;
image_t *tex;
lm->modified = false;
if (!TEXVALID(lm->lightmap_texture))
{
@ -3971,28 +4014,69 @@ void VK_UploadLightmap(lightmapinfo_t *lm)
}
tex = lm->lightmap_texture;
mips.extrafree = NULL;
mips.type = PTI_2D;
mips.mip[0].data = lm->lightmaps;
mips.mip[0].needfree = false;
mips.mip[0].width = lm->width;
mips.mip[0].height = lm->height;
switch(lightmap_fmt)
{
case TF_BGRA32:
mips.encoding = PTI_BGRX8;
break;
default:
Sys_Error("Unsupported encoding\n");
break;
}
mips.mipcount = 1;
VK_LoadTextureMips(tex, &mips);
tex->status = TEX_LOADED;
tex->width = lm->width;
tex->height = lm->height;
if (0)//vk.frame && tex->vkimage)
{ //the inline streaming path.
//the double-copy sucks but at least ensures that the dma copies stuff from THIS frame and not some of the next one too.
int *data;
VkBufferImageCopy bic;
VkBuffer buf;
//size_t x = 0, w = lm->width;
size_t x = lm->rectchange.l, w = lm->rectchange.r - lm->rectchange.l;
size_t y = lm->rectchange.t, h = lm->rectchange.b - lm->rectchange.t, i;
lm->lightmap_texture = tex;
data = VKBE_AllocateBufferSpace(DB_STAGING, w * h * 4, &buf, &bic.bufferOffset);
bic.bufferRowLength = w;
bic.bufferImageHeight = h;
bic.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
bic.imageSubresource.mipLevel = 0;
bic.imageSubresource.baseArrayLayer = 0;
bic.imageSubresource.layerCount = 1;
bic.imageOffset.x = x;
bic.imageOffset.y = y;
bic.imageOffset.z = 0;
bic.imageExtent.width = w;
bic.imageExtent.height = h;
bic.imageExtent.depth = 1;
if (w == lm->width) //can just copy the lot in a single call.
memcpy(data, lm->lightmaps + 4*(y * lm->width), w*h*4);
else
{ //there's unused data on each row, oh well.
for (i = 0; i < h; i++)
memcpy(data + i * w, lm->lightmaps + 4*((y+i) * lm->width + x), w*4);
}
vkCmdCopyBufferToImage(vk.rendertarg->cbuf, buf, tex->vkimage->image, tex->vkimage->layout, 1, &bic);
}
else
{ //the slow out-of-frame generic path.
mips.extrafree = NULL;
mips.type = PTI_2D;
mips.mip[0].data = lm->lightmaps;
mips.mip[0].needfree = false;
mips.mip[0].width = lm->width;
mips.mip[0].height = lm->height;
switch(lightmap_fmt)
{
case TF_BGRA32:
mips.encoding = PTI_BGRX8;
break;
default:
Sys_Error("Unsupported encoding\n");
break;
}
mips.mipcount = 1;
VK_LoadTextureMips(tex, &mips);
tex->status = TEX_LOADED;
tex->width = lm->width;
tex->height = lm->height;
}
//invert the size so we're not always updating the entire thing.
lm->rectchange.l = lm->width;
lm->rectchange.t = lm->height;
lm->rectchange.r = 0;
lm->rectchange.b = 0;
lm->modified = false;
}
/*upload all lightmaps at the start to reduce lags*/
static void BE_UploadLightmaps(qboolean force)
@ -4364,7 +4448,7 @@ static void BE_RotateForEntity (const entity_t *e, const model_t *mod)
viewport.height = r_refdef.pxrect.height;
viewport.minDepth = 0;
viewport.maxDepth = ndr;
vkCmdSetViewport(vk.frame->cbuf, 0, 1, &viewport);
vkCmdSetViewport(vk.rendertarg->cbuf, 0, 1, &viewport);
}
}
@ -4443,7 +4527,6 @@ void VKBE_RT_Destroy(struct vk_rendertarg *targ)
struct vkbe_rtpurge
{
struct vk_fencework fw;
VkFramebuffer framebuffer;
vk_image_t colour;
vk_image_t depth;
@ -4455,7 +4538,7 @@ static void VKBE_RT_Purge(void *ptr)
VK_DestroyVkTexture(&ctx->depth);
VK_DestroyVkTexture(&ctx->colour);
}
void VKBE_RT_Gen(struct vk_rendertarg *targ, uint32_t width, uint32_t height, qboolean clear)
void VKBE_RT_Gen(struct vk_rendertarg *targ, uint32_t width, uint32_t height, qboolean clear, unsigned int flags)
{
//sooooo much work...
VkImageCreateInfo colour_imginfo = {VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO};
@ -4470,12 +4553,12 @@ void VKBE_RT_Gen(struct vk_rendertarg *targ, uint32_t width, uint32_t height, qb
targ->restartinfo.clearValueCount = 2;
targ->depthcleared = true; //will be once its activated.
if (targ->width == width && targ->height == height)
if (targ->width == width && targ->height == height && targ->q_colour.flags == flags)
return; //no work to do.
if (targ->framebuffer)
{ //schedule the old one to be destroyed at the end of the current frame. DIE OLD ONE, DIE!
purge = VK_AtFrameEnd(VKBE_RT_Purge, sizeof(*purge));
purge = VK_AtFrameEnd(VKBE_RT_Purge, NULL, sizeof(*purge));
purge->framebuffer = targ->framebuffer;
purge->colour = targ->colour;
purge->depth = targ->depth;
@ -4489,6 +4572,7 @@ void VKBE_RT_Gen(struct vk_rendertarg *targ, uint32_t width, uint32_t height, qb
targ->q_colour.status = TEX_LOADED;
targ->q_colour.width = width;
targ->q_colour.height = height;
targ->q_colour.flags = flags;
targ->width = width;
targ->height = height;
@ -4496,7 +4580,7 @@ void VKBE_RT_Gen(struct vk_rendertarg *targ, uint32_t width, uint32_t height, qb
if (width == 0 && height == 0)
return; //destroyed
colour_imginfo.format = VK_FORMAT_R8G8B8A8_UNORM;
colour_imginfo.format = vk.backbufformat;
colour_imginfo.flags = 0;
colour_imginfo.imageType = VK_IMAGE_TYPE_2D;
colour_imginfo.extent.width = width;
@ -4568,14 +4652,14 @@ void VKBE_RT_Gen(struct vk_rendertarg *targ, uint32_t width, uint32_t height, qb
{
VkSamplerCreateInfo lmsampinfo = {VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO};
lmsampinfo.minFilter = lmsampinfo.magFilter = VK_FILTER_LINEAR;
lmsampinfo.minFilter = lmsampinfo.magFilter = (flags&IF_NEAREST)?VK_FILTER_NEAREST:VK_FILTER_LINEAR;
lmsampinfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR;
lmsampinfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
lmsampinfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
lmsampinfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
lmsampinfo.mipLodBias = 0.0;
lmsampinfo.anisotropyEnable = VK_FALSE;
lmsampinfo.maxAnisotropy = 0;
lmsampinfo.maxAnisotropy = 1.0;
lmsampinfo.compareOp = VK_COMPARE_OP_LESS_OR_EQUAL;
lmsampinfo.minLod = 0;
lmsampinfo.maxLod = 0;
@ -4589,15 +4673,16 @@ void VKBE_RT_Gen(struct vk_rendertarg *targ, uint32_t width, uint32_t height, qb
VkAssert(vkCreateSampler(vk.device, &lmsampinfo, NULL, &targ->depth.sampler));
}
targ->colour.layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
targ->depth.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL;
targ->colour.layout = VK_IMAGE_LAYOUT_UNDEFINED;
targ->mscolour.layout = VK_IMAGE_LAYOUT_UNDEFINED;
targ->depth.layout = VK_IMAGE_LAYOUT_UNDEFINED;
{
VkFramebufferCreateInfo fbinfo = {VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO};
VkImageView attachments[2] = {targ->colour.view, targ->depth.view};
VkImageView attachments[3] = {targ->colour.view, targ->depth.view, targ->mscolour.view};
fbinfo.flags = 0;
fbinfo.renderPass = vk.renderpass[2];
fbinfo.attachmentCount = countof(attachments);
fbinfo.attachmentCount = (vk.multisamplebits!=VK_SAMPLE_COUNT_1_BIT)?3:2;
fbinfo.pAttachments = attachments;
fbinfo.width = width;
fbinfo.height = height;
@ -4618,7 +4703,6 @@ void VKBE_RT_Gen(struct vk_rendertarg *targ, uint32_t width, uint32_t height, qb
struct vkbe_rtpurge_cube
{
struct vk_fencework fw;
vk_image_t colour;
vk_image_t depth;
struct
@ -4663,7 +4747,7 @@ void VKBE_RT_Gen_Cube(struct vk_rendertarg_cube *targ, uint32_t size, qboolean c
if (targ->size)
{ //schedule the old one to be destroyed at the end of the current frame. DIE OLD ONE, DIE!
purge = VK_AtFrameEnd(VKBE_RT_Purge_Cube, sizeof(*purge));
purge = VK_AtFrameEnd(VKBE_RT_Purge_Cube, NULL, sizeof(*purge));
for (f = 0; f < 6; f++)
{
purge->face[f].framebuffer = targ->face[f].framebuffer;
@ -4741,7 +4825,7 @@ void VKBE_RT_Gen_Cube(struct vk_rendertarg_cube *targ, uint32_t size, qboolean c
lmsampinfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
lmsampinfo.mipLodBias = 0.0;
lmsampinfo.anisotropyEnable = VK_FALSE;
lmsampinfo.maxAnisotropy = 0;
lmsampinfo.maxAnisotropy = 1.0;
lmsampinfo.compareOp = VK_COMPARE_OP_LESS_OR_EQUAL;
lmsampinfo.minLod = 0;
lmsampinfo.maxLod = 0;
@ -4842,9 +4926,6 @@ void VKBE_RT_Begin(struct vk_rendertarg *targ)
if (vk.rendertarg == targ)
return;
if (vk.rendertarg)
vkCmdEndRenderPass(vk.frame->cbuf);
r_refdef.pxrect.x = 0;
r_refdef.pxrect.y = 0;
r_refdef.pxrect.width = targ->width;
@ -4854,7 +4935,33 @@ void VKBE_RT_Begin(struct vk_rendertarg *targ)
vid.fbpwidth = targ->width;
vid.fbpheight = targ->height;
vkCmdBeginRenderPass(vk.frame->cbuf, &targ->restartinfo, VK_SUBPASS_CONTENTS_INLINE);
#if 0
targ->cbuf = vk.rendertarg->cbuf;
if (vk.rendertarg)
vkCmdEndRenderPass(vk.rendertarg->cbuf);
#else
shaderstate.activepipeline = VK_NULL_HANDLE;
targ->cbuf = VK_AllocFrameCBuf();
{
VkCommandBufferBeginInfo begininf = {VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO};
VkCommandBufferInheritanceInfo inh = {VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO};
begininf.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
begininf.pInheritanceInfo = &inh;
inh.renderPass = VK_NULL_HANDLE; //unused
inh.subpass = 0; //unused
inh.framebuffer = VK_NULL_HANDLE; //unused
inh.occlusionQueryEnable = VK_FALSE;
inh.queryFlags = 0;
inh.pipelineStatistics = 0;
vkBeginCommandBuffer(targ->cbuf, &begininf);
}
#endif
targ->prevtarg = vk.rendertarg;
vk.rendertarg = targ;
vkCmdBeginRenderPass(vk.rendertarg->cbuf, &targ->restartinfo, VK_SUBPASS_CONTENTS_INLINE);
//future reuse shouldn't clear stuff
if (targ->restartinfo.clearValueCount)
{
@ -4862,7 +4969,6 @@ void VKBE_RT_Begin(struct vk_rendertarg *targ)
targ->restartinfo.renderPass = vk.renderpass[0];
targ->restartinfo.clearValueCount = 0;
}
vk.rendertarg = targ;
{
VkRect2D wrekt;
@ -4873,25 +4979,52 @@ void VKBE_RT_Begin(struct vk_rendertarg *targ)
viewport.height = r_refdef.pxrect.height;
viewport.minDepth = 0;
viewport.maxDepth = shaderstate.depthrange;
vkCmdSetViewport(vk.frame->cbuf, 0, 1, &viewport);
vkCmdSetViewport(vk.rendertarg->cbuf, 0, 1, &viewport);
wrekt.offset.x = viewport.x;
wrekt.offset.y = viewport.y;
wrekt.extent.width = viewport.width;
wrekt.extent.height = viewport.height;
vkCmdSetScissor(vk.frame->cbuf, 0, 1, &wrekt);
vkCmdSetScissor(vk.rendertarg->cbuf, 0, 1, &wrekt);
}
}
void VKBE_RT_End(struct vk_rendertarg *targ)
{
if (R2D_Flush)
R2D_Flush();
vk.rendertarg = vk.rendertarg->prevtarg;
vid.fbpwidth = vk.rendertarg->width;
vid.fbpheight = vk.rendertarg->height;
#if 0
#else
shaderstate.activepipeline = VK_NULL_HANDLE;
vkCmdEndRenderPass(targ->cbuf);
vkEndCommandBuffer(targ->cbuf);
VK_Submit_Work(targ->cbuf, VK_NULL_HANDLE, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_NULL_HANDLE, VK_NULL_HANDLE, NULL, NULL);
// VK_Submit_Work(VkCommandBuffer cmdbuf, VkSemaphore semwait, VkPipelineStageFlags semwaitstagemask, VkSemaphore semsignal, VkFence fencesignal, struct vkframe *presentframe, struct vk_fencework *fencedwork)
#endif
}
static qboolean BE_GenerateRefraction(batch_t *batch, shader_t *bs)
{
extern cvar_t r_refractreflect_scale;
float oldil;
int oldbem;
struct vk_rendertarg *targ;
//these flags require rendering some view as an fbo
if (r_refdef.recurse)
return false;
if (r_refdef.recurse == r_portalrecursion.ival || r_refdef.recurse == R_MAX_RECURSE)
return false;
if (shaderstate.mode != BEM_STANDARD && shaderstate.mode != BEM_DEPTHDARK)
return false;
if (vk.multisamplebits != VK_SAMPLE_COUNT_1_BIT)
return false; //multisample rendering can't deal with this.
oldbem = shaderstate.mode;
oldil = shaderstate.identitylighting;
targ = vk.rendertarg;
@ -4903,11 +5036,12 @@ static qboolean BE_GenerateRefraction(batch_t *batch, shader_t *bs)
r_refdef.vrect.x = 0;
r_refdef.vrect.y = 0;
r_refdef.vrect.width = vid.fbvwidth/2;
r_refdef.vrect.height = vid.fbvheight/2;
VKBE_RT_Gen(&shaderstate.rt_reflection, vid.fbpwidth/2, vid.fbpheight/2, false);
r_refdef.vrect.width = max(1, vid.fbvwidth*r_refractreflect_scale.value);
r_refdef.vrect.height = max(1, vid.fbvheight*r_refractreflect_scale.value);
VKBE_RT_Gen(&shaderstate.rt_reflection, r_refdef.vrect.width, r_refdef.vrect.height, false, RT_IMAGEFLAGS);
VKBE_RT_Begin(&shaderstate.rt_reflection);
R_DrawPortal(batch, cl.worldmodel->batches, NULL, 1);
VKBE_RT_End(&shaderstate.rt_reflection);
r_refdef.vrect = orect;
r_refdef.pxrect = oprect;
}
@ -4923,18 +5057,17 @@ static qboolean BE_GenerateRefraction(batch_t *batch, shader_t *bs)
r_refdef.vrect.y = 0;
r_refdef.vrect.width = vid.fbvwidth/2;
r_refdef.vrect.height = vid.fbvheight/2;
VKBE_RT_Gen(&shaderstate.rt_refraction, vid.fbpwidth/2, vid.fbpheight/2, false);
VKBE_RT_Gen(&shaderstate.rt_refraction, r_refdef.vrect.width, r_refdef.vrect.height, false, RT_IMAGEFLAGS);
VKBE_RT_Begin(&shaderstate.rt_refraction);
R_DrawPortal(batch, cl.worldmodel->batches, NULL, ((bs->flags & SHADER_HASREFRACTDEPTH)?3:2)); //fixme
VKBE_RT_End(&shaderstate.rt_refraction);
r_refdef.vrect = ovrect;
r_refdef.pxrect = oprect;
shaderstate.tex_refraction = &shaderstate.rt_refraction.q_colour;
VKBE_RT_Begin(targ);
}
else
{
VKBE_RT_Begin(targ);
R_DrawPortal(batch, cl.worldmodel->batches, NULL, 3);
T_Gen_CurrentRender();
shaderstate.tex_refraction = shaderstate.tex_currentrender;
@ -4994,7 +5127,6 @@ static qboolean BE_GenerateRefraction(batch_t *batch, shader_t *bs)
BE_RT_End();
}
*/
VKBE_RT_Begin(targ);
VKBE_SelectMode(oldbem);
shaderstate.identitylighting = oldil;
@ -5557,7 +5689,7 @@ static void BE_SubmitMeshesPortals(batch_t **worldlist, batch_t *dynamiclist)
rect.rect.extent.height = r_refdef.pxrect.height;
rect.layerCount = 1;
rect.baseArrayLayer = 0;
vkCmdClearAttachments(vk.frame->cbuf, 1, &clr, 1, &rect);
vkCmdClearAttachments(vk.rendertarg->cbuf, 1, &clr, 1, &rect);
}
VKBE_SelectMode(BEM_DEPTHONLY);
VKBE_SubmitBatch(batch);
@ -5652,15 +5784,9 @@ struct vk_shadowbuffer *VKBE_GenerateShadowBuffer(vecV_t *verts, int numverts, i
return buf;
}
}
struct vk_shadowbuffer_destroy
{
struct vk_fencework fw;
struct vk_shadowbuffer buf;
};
static void VKBE_DestroyShadowBuffer_Delayed(void *ctx)
{
struct vk_shadowbuffer_destroy *d = ctx;
struct vk_shadowbuffer *buf = &d->buf;
struct vk_shadowbuffer *buf = ctx;
vkDestroyBuffer(vk.device, buf->vbuffer, vkallocationcb);
vkDestroyBuffer(vk.device, buf->ibuffer, vkallocationcb);
vkFreeMemory(vk.device, buf->vmemory, vkallocationcb);
@ -5670,8 +5796,7 @@ void VKBE_DestroyShadowBuffer(struct vk_shadowbuffer *buf)
{
if (buf && buf->isstatic)
{
struct vk_shadowbuffer_destroy *ctx = VK_AtFrameEnd(VKBE_DestroyShadowBuffer_Delayed, sizeof(*ctx));
ctx->buf = *buf;
struct vk_shadowbuffer_destroy *ctx = VK_AtFrameEnd(VKBE_DestroyShadowBuffer_Delayed, buf, sizeof(*buf));
Z_Free(buf);
}
}
@ -5694,10 +5819,10 @@ void VKBE_RenderShadowBuffer(struct vk_shadowbuffer *buf)
"}\n"
);
vkCmdBindVertexBuffers(vk.frame->cbuf, 0, 1, &buf->vbuffer, &buf->voffset);
vkCmdBindIndexBuffer(vk.frame->cbuf, buf->ibuffer, buf->ioffset, VK_INDEX_TYPE);
if (BE_SetupMeshProgram(depthonlyshader->passes[0].prog, depthonlyshader->passes, 0, buf->numindicies))
vkCmdDrawIndexed(vk.frame->cbuf, buf->numindicies, 1, 0, 0, 0);
vkCmdBindVertexBuffers(vk.rendertarg->cbuf, 0, 1, &buf->vbuffer, &buf->voffset);
vkCmdBindIndexBuffer(vk.rendertarg->cbuf, buf->ibuffer, buf->ioffset, VK_INDEX_TYPE);
if (BE_SetupMeshProgram(depthonlyshader->prog, depthonlyshader->passes, 0, buf->numindicies))
vkCmdDrawIndexed(vk.rendertarg->cbuf, buf->numindicies, 1, 0, 0, 0);
}
@ -5740,7 +5865,7 @@ qboolean VKBE_BeginShadowmap(qboolean isspot, uint32_t width, uint32_t height)
// const qboolean altqueue = false;
// if (!altqueue)
// vkCmdEndRenderPass(vk.frame->cbuf);
vkCmdEndRenderPass(vk.rendertarg->cbuf);
if (shad->width != width || shad->height != height)
{
@ -5851,7 +5976,7 @@ qboolean VKBE_BeginShadowmap(qboolean isspot, uint32_t width, uint32_t height)
lmsampinfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
lmsampinfo.mipLodBias = 0.0;
lmsampinfo.anisotropyEnable = VK_FALSE;
lmsampinfo.maxAnisotropy = 0;
lmsampinfo.maxAnisotropy = 1.0;
lmsampinfo.compareEnable = VK_TRUE;
lmsampinfo.compareOp = VK_COMPARE_OP_LESS_OR_EQUAL;
lmsampinfo.minLod = 0;
@ -5889,7 +6014,7 @@ qboolean VKBE_BeginShadowmap(qboolean isspot, uint32_t width, uint32_t height)
imgbarrier.subresourceRange.layerCount = 1;
imgbarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
imgbarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
vkCmdPipelineBarrier(vk.frame->cbuf, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, 0, 0, NULL, 0, NULL, 1, &imgbarrier);
vkCmdPipelineBarrier(vk.rendertarg->cbuf, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, 0, 0, NULL, 0, NULL, 1, &imgbarrier);
}
{
@ -5905,7 +6030,7 @@ qboolean VKBE_BeginShadowmap(qboolean isspot, uint32_t width, uint32_t height)
rpass.renderArea.extent.height = height;
rpass.clearValueCount = 1;
rpass.pClearValues = &clearval;
vkCmdBeginRenderPass(vk.frame->cbuf, &rpass, VK_SUBPASS_CONTENTS_INLINE);
vkCmdBeginRenderPass(vk.rendertarg->cbuf, &rpass, VK_SUBPASS_CONTENTS_INLINE);
}
//viewport+scissor will be done elsewhere
@ -5922,7 +6047,7 @@ void VKBE_DoneShadows(void)
//we've rendered the shadowmap, but now we need to blit it to the screen
//so set stuff back to the main view. FIXME: do these in batches to ease the load on tilers.
vkCmdEndRenderPass(vk.frame->cbuf);
vkCmdEndRenderPass(vk.rendertarg->cbuf);
/*if (altqueue)
{
@ -5955,7 +6080,7 @@ void VKBE_DoneShadows(void)
}
*/
vkCmdBeginRenderPass(vk.frame->cbuf, &vk.rendertarg->restartinfo, VK_SUBPASS_CONTENTS_INLINE);
vkCmdBeginRenderPass(vk.rendertarg->cbuf, &vk.rendertarg->restartinfo, VK_SUBPASS_CONTENTS_INLINE);
viewport.x = r_refdef.pxrect.x;
viewport.y = r_refdef.pxrect.y;//r_refdef.pxrect.maxheight - (r_refdef.pxrect.y+r_refdef.pxrect.height); //silly GL...
@ -5963,7 +6088,7 @@ void VKBE_DoneShadows(void)
viewport.height = r_refdef.pxrect.height;
viewport.minDepth = 0;
viewport.maxDepth = shaderstate.depthrange;
vkCmdSetViewport(vk.frame->cbuf, 0, 1, &viewport);
vkCmdSetViewport(vk.rendertarg->cbuf, 0, 1, &viewport);
}
@ -6002,13 +6127,13 @@ void VKBE_BeginShadowmapFace(void)
viewport.height = r_refdef.pxrect.height;
viewport.minDepth = 0;
viewport.maxDepth = 1;
vkCmdSetViewport(vk.frame->cbuf, 0, 1, &viewport);
vkCmdSetViewport(vk.rendertarg->cbuf, 0, 1, &viewport);
wrekt.offset.x = viewport.x;
wrekt.offset.y = viewport.y;
wrekt.extent.width = viewport.width;
wrekt.extent.height = viewport.height;
vkCmdSetScissor(vk.frame->cbuf, 0, 1, &wrekt);
vkCmdSetScissor(vk.rendertarg->cbuf, 0, 1, &wrekt);
}
#endif
@ -6168,7 +6293,7 @@ void VKBE_VBO_Destroy(vboarray_t *vearray, void *mem)
if (!vearray->vk.buff)
return; //not actually allocated...
fence = VK_AtFrameEnd(VKBE_DoneBufferStaging, sizeof(*fence));
fence = VK_AtFrameEnd(VKBE_DoneBufferStaging, NULL, sizeof(*fence));
fence->buf = vearray->vk.buff;
fence->mem = *retarded;
@ -6208,7 +6333,7 @@ void VKBE_Scissor(srect_t *rect)
wrekt.extent.height = vid.fbpheight;
}
vkCmdSetScissor(vk.frame->cbuf, 0, 1, &wrekt);
vkCmdSetScissor(vk.rendertarg->cbuf, 0, 1, &wrekt);
}
#endif

File diff suppressed because it is too large Load Diff

View File

@ -54,6 +54,7 @@
VKFunc(GetPhysicalDeviceSurfaceCapabilitiesKHR) \
VKFunc(GetPhysicalDeviceMemoryProperties) \
VKFunc(GetPhysicalDeviceFormatProperties) \
VKFunc(GetPhysicalDeviceFeatures) \
VKFunc(DestroySurfaceKHR) \
VKFunc(CreateDevice) \
VKFunc(DestroyInstance) \
@ -78,6 +79,7 @@
VKFunc(CmdBindIndexBuffer) \
VKFunc(CmdBindVertexBuffers) \
VKFunc(CmdPushConstants) \
VKFunc(CmdPushDescriptorSetKHR) \
VKFunc(CmdClearAttachments) \
VKFunc(CmdClearColorImage) \
VKFunc(CmdClearDepthStencilImage) \
@ -191,30 +193,35 @@ typedef struct vk_image_s
uint32_t layers;
uint32_t mipcount;
uint32_t encoding;
uint32_t type;
uint32_t type; //PTI_2D/3D/CUBE
} vk_image_t;
enum dynbuf_e
{
DB_VBO,
DB_EBO,
DB_UBO,
DB_STAGING,
DB_MAX
};
struct vk_rendertarg
{
VkCommandBuffer cbuf; //cbuf allocated for this render target.
VkFramebuffer framebuffer;
vk_image_t colour, depth;
vk_image_t colour, depth, mscolour;
image_t q_colour, q_depth; //extra sillyness...
image_t q_colour, q_depth, q_mscolour; //extra sillyness...
uint32_t width;
uint32_t height;
qboolean multisample;
qboolean depthcleared; //starting a new gameview needs cleared depth relative to other views, but the first probably won't.
VkRenderPassBeginInfo restartinfo;
VkSemaphore presentsemaphore;
qboolean firstuse;
struct vk_rendertarg *prevtarg;
};
struct vk_rendertarg_cube
{
@ -233,9 +240,14 @@ extern struct vulkaninfo_s
{
unsigned short triplebuffer;
qboolean vsync;
qboolean headless;
qboolean allowsubmissionthread;
qboolean khr_swapchain; //aka: not headless. we're actually rendering stuff!
qboolean nv_glsl_shader; //we can load glsl shaders. probably missing lots of reflection info though, so this is probably too limited.
qboolean nv_dedicated_allocation; //nvidia-specific extension that provides hints that there's no memory aliasing going on.
qboolean khr_dedicated_allocation; //standardised version of the above where the driver decides whether a resource is worth a dedicated allocation.
qboolean khr_push_descriptor; //more efficient descriptor streaming
VkInstance instance;
VkDevice device;
VkPhysicalDevice gpu;
@ -247,6 +259,7 @@ extern struct vulkaninfo_s
VkQueue queue_alt[1];
VkPhysicalDeviceMemoryProperties memory_properties;
VkCommandPool cmdpool;
VkPhysicalDeviceLimits limits;
#define ACQUIRELIMIT 8
VkFence acquirefences[ACQUIRELIMIT];
@ -268,6 +281,7 @@ extern struct vulkaninfo_s
int filterpic[3];
int mipcap[2];
float max_anistophy;
float max_anistophy_limit;
struct descpool
{
@ -282,11 +296,12 @@ extern struct vulkaninfo_s
size_t offset; //size written by the cpu (that might not yet be flushed)
size_t size; //maximum buffer size
size_t align;
qboolean stagingcoherent;
VkBuffer stagingbuf;
VkDeviceMemory stagingmemory;
VkBuffer devicebuf;
VkDeviceMemory devicememory;
VkBuffer renderbuf; //either staging or device.
VkBuffer renderbuf; //either staging or device. this is the buffer that we tell vulkan about
void *ptr;
struct dynbuffer *next;
@ -295,27 +310,34 @@ extern struct vulkaninfo_s
struct vk_rendertarg *rendertarg;
struct vkframe {
struct vkframe *next;
VkCommandBuffer cbuf;
struct dynbuffer *dynbufs[DB_MAX];
struct descpool *descpools;
VkCommandBuffer *cbufs;
size_t numcbufs;
size_t maxcbufs;
VkFence finishedfence;
struct vk_fencework *frameendjobs;
struct vk_frameend {
struct vk_frameend *next;
void (*FrameEnded) (void*);
} *frameendjobs;
struct vk_rendertarg *backbuf;
} *frame, *unusedframes;
struct vk_fencework *frameendjobs;
struct vk_frameend *frameendjobs;
uint32_t backbuf_count;
VkRenderPass shadow_renderpass; //clears depth etc.
VkRenderPass renderpass[3]; //initial, resume
VkRenderPass renderpass[3]; //reload-both(resume prior renderpass), clear-depth-dontcare-colour(gl_clear==0), clear-both(cl_clear!=0)
VkSwapchainKHR swapchain;
uint32_t bufferidx;
VkSampleCountFlagBits multisamplebits;
VkFormat depthformat;
VkFormat backbufformat;
qboolean srgbcapable;
qboolean neednewswapchain;
qboolean neednewswapchain; //something changed that invalidates the old one.
qboolean devicelost; //we seriously fucked up somewhere. or the gpu is shite.
struct vkwork_s
{
@ -367,6 +389,9 @@ qboolean R_CanBloom(void);
struct programshared_s;
qboolean VK_LoadGLSL(struct programshared_s *prog, const char *name, unsigned int permu, int ver, const char **precompilerconstants, const char *vert, const char *tcs, const char *tes, const char *geom, const char *frag, qboolean noerrors, vfsfile_t *blobfile);
VkCommandBuffer VK_AllocFrameCBuf(void);
void VK_Submit_Work(VkCommandBuffer cmdbuf, VkSemaphore semwait, VkPipelineStageFlags semwaitstagemask, VkSemaphore semsignal, VkFence fencesignal, struct vkframe *presentframe, struct vk_fencework *fencedwork);
void VKBE_Init(void);
void VKBE_InitFramePools(struct vkframe *frame);
void VKBE_RestartFrame(void);
@ -403,8 +428,9 @@ void VKBE_BeginShadowmapFace(void);
void VKBE_DoneShadows(void);
void VKBE_RT_Gen_Cube(struct vk_rendertarg_cube *targ, uint32_t size, qboolean clear);
void VKBE_RT_Gen(struct vk_rendertarg *targ, uint32_t width, uint32_t height, qboolean clear);
void VKBE_RT_Gen(struct vk_rendertarg *targ, uint32_t width, uint32_t height, qboolean clear, unsigned int flags);
void VKBE_RT_Begin(struct vk_rendertarg *targ);
void VKBE_RT_End(struct vk_rendertarg *targ);
void VKBE_RT_Destroy(struct vk_rendertarg *targ);
@ -416,7 +442,7 @@ struct stagingbuf
size_t size;
VkBufferUsageFlags usage;
};
vk_image_t VK_CreateTexture2DArray(uint32_t width, uint32_t height, uint32_t layers, uint32_t mips, unsigned int encoding, unsigned int type);
vk_image_t VK_CreateTexture2DArray(uint32_t width, uint32_t height, uint32_t layers, uint32_t mips, unsigned int encoding, unsigned int type, qboolean rendertarget);
void set_image_layout(VkCommandBuffer cmd, VkImage image, VkImageAspectFlags aspectMask, VkImageLayout old_image_layout, VkAccessFlags srcaccess, VkImageLayout new_image_layout, VkAccessFlags dstaccess);
void VK_CreateSampler(unsigned int flags, vk_image_t *img);
void *VKBE_CreateStagingBuffer(struct stagingbuf *n, size_t size, VkBufferUsageFlags usage);
@ -424,7 +450,7 @@ VkBuffer VKBE_FinishStaging(struct stagingbuf *n, VkDeviceMemory *memptr);
void *VK_FencedBegin(void (*passed)(void *work), size_t worksize);
void VK_FencedSubmit(void *work);
void VK_FencedCheck(void);
void *VK_AtFrameEnd(void (*passed)(void *work), size_t worksize);
void *VK_AtFrameEnd(void (*passed)(void *work), void *data, size_t worksize);

View File

@ -2,7 +2,7 @@
// File: vk_platform.h
//
/*
** Copyright (c) 2014-2015 The Khronos Group Inc.
** Copyright (c) 2014-2017 The Khronos Group Inc.
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
@ -51,13 +51,13 @@ extern "C"
#define VKAPI_ATTR
#define VKAPI_CALL __stdcall
#define VKAPI_PTR VKAPI_CALL
#elif defined(__ANDROID__) && defined(__ARM_EABI__) && !defined(__ARM_ARCH_7A__)
// Android does not support Vulkan in native code using the "armeabi" ABI.
#error "Vulkan requires the 'armeabi-v7a' or 'armeabi-v7a-hard' ABI on 32-bit ARM CPUs"
#elif defined(__ANDROID__) && defined(__ARM_ARCH_7A__)
// On Android/ARMv7a, Vulkan functions use the armeabi-v7a-hard calling
// convention, even if the application's native code is compiled with the
// armeabi-v7a calling convention.
#elif defined(__ANDROID__) && defined(__ARM_ARCH) && __ARM_ARCH < 7
#error "Vulkan isn't supported for the 'armeabi' NDK ABI"
#elif defined(__ANDROID__) && defined(__ARM_ARCH) && __ARM_ARCH >= 7 && defined(__ARM_32BIT_STATE)
// On Android 32-bit ARM targets, Vulkan functions use the "hardfloat"
// calling convention, i.e. float parameters are passed in registers. This
// is true even if the rest of the application passes floats on the stack,
// as it does by default when compiling for the armeabi-v7a NDK ABI.
#define VKAPI_ATTR __attribute__((pcs("aapcs-vfp")))
#define VKAPI_CALL
#define VKAPI_PTR VKAPI_ATTR

File diff suppressed because it is too large Load Diff

View File

@ -19,6 +19,8 @@ nonstatic void(mitem_desktop desktop) M_Options_Video =
pos += 8;
fr.add(spawn(mitem_text, item_text:_("Apply / Restart"), item_command:"vid_restart", item_scale:8, item_flags:IF_RIGHTALIGN), RS_X_MIN_PARENT_MIN|RS_Y_MIN_PARENT_MIN | RS_X_MAX_PARENT_MID|RS_Y_MAX_OWN_MIN, [0, pos], [-8, 8]); pos += 8;
pos += 8;
if (cvar_type("vid_renderer")) fr.add(menuitemcombo_spawn(_("Renderer"), "vid_renderer", '280 8', cvar_string("_vid_renderer_opts")), fl, [0, pos], [0, 8]); pos += 8;
//add the options
if (!dp_workarounds)

View File

@ -420,6 +420,8 @@ float(entity to, float sendflags) MySendEntity =
if (sendflags & 128)
WriteByte(MSG_ENTITY, self.modelindex); //sending a modelindex is smaller than sending an entire string.
return TRUE; //handled. If you return FALSE here, the entity will be considered invisible to the player.
};
In your spawn function: