2006-04-13 20:47:06 +00:00
// Compatibility declarations for things which might not be present in
// certain build environments. It also levels the playing field caused
// by different platforms.
2014-11-22 12:32:56 +00:00
# ifndef compat_h_
# define compat_h_
2006-04-13 20:47:06 +00:00
2017-02-25 08:15:16 +00:00
# pragma once
2020-01-25 10:56:13 +00:00
# include "xs_Float.h"
2017-02-25 08:15:16 +00:00
////////// Compiler detection //////////
2014-10-25 10:17:35 +00:00
# ifdef __GNUC__
2014-11-24 08:19:50 +00:00
# define EDUKE32_GCC_PREREQ(major, minor) (major < __GNUC__ || (major == __GNUC__ && minor <= __GNUC_MINOR__))
2014-10-25 10:17:35 +00:00
# else
# define EDUKE32_GCC_PREREQ(major, minor) 0
# endif
# ifdef __clang__
2014-11-24 08:19:50 +00:00
# define EDUKE32_CLANG_PREREQ(major, minor) (major < __clang_major__ || (major == __clang_major__ && minor <= __clang_minor__))
2014-10-25 10:17:35 +00:00
# else
# define EDUKE32_CLANG_PREREQ(major, minor) 0
# endif
# ifndef __has_builtin
# define __has_builtin(x) 0 // Compatibility with non-clang compilers.
# endif
# ifndef __has_feature
# define __has_feature(x) 0 // Compatibility with non-clang compilers.
# endif
# ifndef __has_extension
# define __has_extension __has_feature // Compatibility with pre-3.0 compilers.
# endif
2017-07-10 13:44:04 +00:00
# ifndef __has_cpp_attribute
# define __has_cpp_attribute(x) 0
# endif
2014-10-25 10:17:35 +00:00
2017-06-05 10:05:17 +00:00
# ifdef _MSC_VER
# define EDUKE32_MSVC_PREREQ(major) ((major) <= (_MSC_VER))
2017-10-09 07:37:05 +00:00
# ifdef __cplusplus
# define EDUKE32_MSVC_CXX_PREREQ(major) ((major) <= (_MSC_VER))
# else
# define EDUKE32_MSVC_CXX_PREREQ(major) 0
# endif
2017-06-05 10:05:17 +00:00
# else
# define EDUKE32_MSVC_PREREQ(major) 0
2017-10-09 07:37:05 +00:00
# define EDUKE32_MSVC_CXX_PREREQ(major) 0
2017-06-05 10:05:17 +00:00
# endif
2017-02-25 08:15:16 +00:00
2017-04-12 08:30:18 +00:00
////////// Language detection //////////
# if defined __STDC__
# if defined __STDC_VERSION__ && __STDC_VERSION__ >= 201112L
# define CSTD 2011
# elif defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L
# define CSTD 1999
# elif defined __STDC_VERSION__ && __STDC_VERSION__ >= 199409L
# define CSTD 1994
# else
# define CSTD 1989
# endif
# else
# define CSTD 0
# endif
2017-10-09 07:37:01 +00:00
# if defined __cplusplus && __cplusplus >= 201703L
# define CXXSTD 2017
# elif defined __cplusplus && __cplusplus >= 201402L
2017-04-12 08:30:18 +00:00
# define CXXSTD 2014
# elif defined __cplusplus && __cplusplus >= 201103L
# define CXXSTD 2011
# elif defined __cplusplus && __cplusplus >= 199711L
# define CXXSTD 1998
# else
# define CXXSTD 0
# endif
2017-02-25 08:15:16 +00:00
////////// Language and compiler feature polyfills //////////
# define EXTERNC
2017-02-25 08:15:13 +00:00
# ifndef UNREFERENCED_PARAMETER
# define UNREFERENCED_PARAMETER(x) (x) = (x)
2014-11-30 23:18:57 +00:00
# endif
2014-10-29 17:05:15 +00:00
2017-06-27 02:24:14 +00:00
# ifndef UNREFERENCED_CONST_PARAMETER
# ifdef _MSC_VER
2017-07-29 20:39:50 +00:00
# define UNREFERENCED_CONST_PARAMETER(x) ((void)(x))
2017-06-27 02:24:14 +00:00
# else
# define UNREFERENCED_CONST_PARAMETER(x)
# endif
# endif
2015-05-19 21:56:03 +00:00
# ifdef __GNUC__
# define UNUSED(x) UNUSED_ ## x __attribute__((unused))
# define PRINTF_FORMAT(stringindex, firstargindex) __attribute__((format (printf, stringindex, firstargindex)))
# else
# define UNUSED(x) x
# define PRINTF_FORMAT(stringindex, firstargindex)
# endif
2010-12-20 16:55:37 +00:00
# if defined __GNUC__ || defined __clang__
# define ATTRIBUTE(attrlist) __attribute__(attrlist)
# else
# define ATTRIBUTE(attrlist)
# endif
2012-12-29 15:21:16 +00:00
# if !defined __clang__ && !defined USING_LTO
# define ATTRIBUTE_OPTIMIZE(str) ATTRIBUTE((optimize(str)))
# else
# define ATTRIBUTE_OPTIMIZE(str)
# endif
2017-02-25 08:15:16 +00:00
# if EDUKE32_GCC_PREREQ(4,0)
# define WARN_UNUSED_RESULT __attribute__((warn_unused_result))
2014-10-25 10:17:35 +00:00
# else
2017-02-25 08:15:16 +00:00
# define WARN_UNUSED_RESULT
2015-03-02 08:15:28 +00:00
# endif
2017-02-25 08:15:16 +00:00
# if defined _MSC_VER && _MSC_VER < 1800
# define inline __inline
2014-11-24 08:19:50 +00:00
# endif
2018-12-23 23:23:50 +00:00
# ifndef MAY_ALIAS
# ifdef _MSC_VER
# define MAY_ALIAS
# else
# define MAY_ALIAS __attribute__((may_alias))
# endif
# endif
2017-02-25 08:15:16 +00:00
# ifndef FORCE_INLINE
2017-02-25 08:15:53 +00:00
# ifdef _MSC_VER
# define FORCE_INLINE __forceinline
2015-01-25 12:16:10 +00:00
# else
2017-02-25 08:15:16 +00:00
# ifdef __GNUC__
2017-02-25 08:15:53 +00:00
# define FORCE_INLINE inline __attribute__((always_inline))
2017-02-25 08:15:16 +00:00
# else
2017-02-25 08:15:53 +00:00
# define FORCE_INLINE inline
2014-11-24 08:19:50 +00:00
# endif
2014-10-30 04:59:23 +00:00
# endif
2008-02-16 22:27:08 +00:00
# endif
2009-06-18 05:57:10 +00:00
# ifndef _MSC_VER
Win64 support! (Meaning it works, not that we recommend it for everyday use.)
This includes a complete Windows header and library refresh, including the addition of 64-bit compiled libs:
*libogg 1.3.0
*libvorbis 1.3.3
*zlib 1.2.7
*libpng 1.5.13
*libvpx 9a3de881c0e681ba1a79a166a86308bbc84b4acd
*SDL_mixer 1.2.12 (for RENDERTYPE=SDL)
*DirectX import libraries: dsound and dxguid (now included)
To build in 64-bit, you essentially need MinGW's MSYS (but not MinGW itself) and MinGW-w64 at the top of your PATH. The target is automatically detected using `$(CC) -dumpmachine`. The EDukeWiki will get detailed instrucitons.
All compiler and linker warnings when building in 64-bit mode have been fixed.
Remaining 64-bit to-do:
- The ebacktrace dll does not build under 64-bit. It uses code specific to the format of 32-bit executables and will have to be ported to work with 64-bit executables. A future 64-bit version will be named ebacktrace1-64.dll.
- RENDERTYPE=SDL crashes in SDL_mixer's Mix_Linked_Version().
- DirectInput gives an error and does not function. This only affects joysticks, and the error never happens without any plugged in.
- Port the classic renderer ASM to 64-bit. (Just kidding, this is way out of my league.)
This commit includes a fair bit of Makefile development spanning all platforms, including simplifying the SDLCONFIG code, fixing build on Mac OS X (thanks rhoenie!), globally factoring Apple brew/port inclusion, enforcing that all -L come before all -l, and ensuring that $(shell ) is always :='d.
In addition, I have resurrected the old GCC_MAJOR and GCC_MINOR detection using `$(CC) -dumpversion`, but I have made it failsafe in case the command fails or the version is manually specified. I have applied this new fine-grained detection where applicable, including allowing LTO, and restraining -W's to versions that support them.
git-svn-id: https://svn.eduke32.com/eduke32@3278 1a8010ca-5511-0410-912e-c29ae57300e0
2012-12-13 02:37:20 +00:00
# ifndef __fastcall
# if defined(__GNUC__) && defined(__i386__)
2012-09-02 14:13:06 +00:00
# define __fastcall __attribute__((fastcall))
Win64 support! (Meaning it works, not that we recommend it for everyday use.)
This includes a complete Windows header and library refresh, including the addition of 64-bit compiled libs:
*libogg 1.3.0
*libvorbis 1.3.3
*zlib 1.2.7
*libpng 1.5.13
*libvpx 9a3de881c0e681ba1a79a166a86308bbc84b4acd
*SDL_mixer 1.2.12 (for RENDERTYPE=SDL)
*DirectX import libraries: dsound and dxguid (now included)
To build in 64-bit, you essentially need MinGW's MSYS (but not MinGW itself) and MinGW-w64 at the top of your PATH. The target is automatically detected using `$(CC) -dumpmachine`. The EDukeWiki will get detailed instrucitons.
All compiler and linker warnings when building in 64-bit mode have been fixed.
Remaining 64-bit to-do:
- The ebacktrace dll does not build under 64-bit. It uses code specific to the format of 32-bit executables and will have to be ported to work with 64-bit executables. A future 64-bit version will be named ebacktrace1-64.dll.
- RENDERTYPE=SDL crashes in SDL_mixer's Mix_Linked_Version().
- DirectInput gives an error and does not function. This only affects joysticks, and the error never happens without any plugged in.
- Port the classic renderer ASM to 64-bit. (Just kidding, this is way out of my league.)
This commit includes a fair bit of Makefile development spanning all platforms, including simplifying the SDLCONFIG code, fixing build on Mac OS X (thanks rhoenie!), globally factoring Apple brew/port inclusion, enforcing that all -L come before all -l, and ensuring that $(shell ) is always :='d.
In addition, I have resurrected the old GCC_MAJOR and GCC_MINOR detection using `$(CC) -dumpversion`, but I have made it failsafe in case the command fails or the version is manually specified. I have applied this new fine-grained detection where applicable, including allowing LTO, and restraining -W's to versions that support them.
git-svn-id: https://svn.eduke32.com/eduke32@3278 1a8010ca-5511-0410-912e-c29ae57300e0
2012-12-13 02:37:20 +00:00
# else
# define __fastcall
2012-09-02 14:13:06 +00:00
# endif
# endif
2009-06-18 05:57:10 +00:00
# endif
2017-02-25 08:15:16 +00:00
# ifndef DISABLE_INLINING
# define EXTERN_INLINE static inline
# define EXTERN_INLINE_HEADER static inline
# else
# define EXTERN_INLINE __fastcall
# define EXTERN_INLINE_HEADER extern __fastcall
2009-04-26 05:57:42 +00:00
# endif
2020-01-29 11:36:52 +00:00
#if 0 && defined(__OPTIMIZE__) && (defined __GNUC__ || __has_builtin(__builtin_expect))
2017-02-25 08:15:16 +00:00
# define EDUKE32_PREDICT_TRUE(x) __builtin_expect(!!(x),1)
# define EDUKE32_PREDICT_FALSE(x) __builtin_expect(!!(x),0)
# else
# define EDUKE32_PREDICT_TRUE(x) (x)
# define EDUKE32_PREDICT_FALSE(x) (x)
2009-04-26 05:57:42 +00:00
# endif
2017-02-25 08:15:16 +00:00
# if EDUKE32_GCC_PREREQ(4,5) || __has_builtin(__builtin_unreachable)
# define EDUKE32_UNREACHABLE_SECTION(...) __builtin_unreachable()
# elif _MSC_VER
# define EDUKE32_UNREACHABLE_SECTION(...) __assume(0)
2017-02-25 08:15:10 +00:00
# else
2017-02-25 08:15:16 +00:00
# define EDUKE32_UNREACHABLE_SECTION(...) __VA_ARGS__
2006-04-13 20:47:06 +00:00
# endif
2017-02-25 08:15:58 +00:00
# if EDUKE32_GCC_PREREQ(2,0) || defined _MSC_VER
2017-02-25 08:15:16 +00:00
# define EDUKE32_FUNCTION __FUNCTION__
2017-04-12 08:30:18 +00:00
# elif CSTD >= 1999 || CXXSTD >= 2011
2017-02-25 08:15:58 +00:00
# define EDUKE32_FUNCTION __func__
2017-02-25 08:15:16 +00:00
# else
# define EDUKE32_FUNCTION "???"
# endif
2012-03-14 22:31:19 +00:00
2017-02-25 08:15:58 +00:00
# ifdef _MSC_VER
# define EDUKE32_PRETTY_FUNCTION __FUNCSIG__
# elif EDUKE32_GCC_PREREQ(2,0)
# define EDUKE32_PRETTY_FUNCTION __PRETTY_FUNCTION__
# else
# define EDUKE32_PRETTY_FUNCTION EDUKE32_FUNCTION
# endif
2017-02-25 08:15:16 +00:00
# ifdef __COUNTER__
2017-10-09 07:37:14 +00:00
# define EDUKE32_UNIQUE_SRC_ID __COUNTER__
# else
# define EDUKE32_UNIQUE_SRC_ID __LINE__
# endif
# if CXXSTD >= 2017
# define EDUKE32_STATIC_ASSERT(cond) static_assert(cond)
# elif CXXSTD >= 2011 || CSTD >= 2011 || EDUKE32_MSVC_CXX_PREREQ(1600)
# define EDUKE32_STATIC_ASSERT(cond) static_assert(cond, "")
2017-02-25 08:15:16 +00:00
# else
2017-10-09 07:37:14 +00:00
/* C99 / C++03 static assertions based on source found in LuaJIT's src/lj_def.h. */
# define EDUKE32_ASSERT_NAME2(name, line) name ## line
# define EDUKE32_ASSERT_NAME(line) EDUKE32_ASSERT_NAME2(eduke32_assert_, line)
2017-02-25 08:15:16 +00:00
# define EDUKE32_STATIC_ASSERT(cond) \
2017-10-09 07:37:14 +00:00
extern void EDUKE32_ASSERT_NAME ( EDUKE32_UNIQUE_SRC_ID ) ( int STATIC_ASSERTION_FAILED [ ( cond ) ? 1 : - 1 ] )
2006-04-13 20:47:06 +00:00
# endif
2017-02-25 08:15:16 +00:00
# ifndef FP_OFF
# define FP_OFF(__p) ((uintptr_t)(__p))
2014-09-30 04:06:32 +00:00
# endif
2019-04-08 06:27:48 +00:00
2017-06-05 10:05:17 +00:00
# if defined __cplusplus && (__cplusplus >= 201103L || __has_feature(cxx_constexpr) || EDUKE32_MSVC_PREREQ(1900))
2017-04-12 08:30:23 +00:00
# define HAVE_CONSTEXPR
# define CONSTEXPR constexpr
# else
# define CONSTEXPR
# endif
2017-06-05 10:05:17 +00:00
# if CXXSTD >= 2011 || EDUKE32_MSVC_PREREQ(1700)
2017-04-12 08:30:29 +00:00
# define FINAL final
# else
# define FINAL
# endif
2017-04-12 08:30:23 +00:00
# if CXXSTD >= 2014
# define CONSTEXPR_CXX14 CONSTEXPR
# else
# define CONSTEXPR_CXX14
# endif
Inreased debugging level for catching oob accesses to 'main' arrays.
If enabled, this makes the following arrays be allocated statically:
spriteext, spritesmooth, sector, wall, sprite, tsprite, while
necessarily disabling the clipshape feature (because it relies on
setting sector/wall to different malloc'd block temporarily).
To compile, pass DEBUGANYWAY=1 in addition to RELEASE=0 to 'make',
and it's really only useful with CC=clang, of course.
git-svn-id: https://svn.eduke32.com/eduke32@2270 1a8010ca-5511-0410-912e-c29ae57300e0
2012-01-19 23:17:34 +00:00
2017-10-09 07:37:11 +00:00
# if CXXSTD >= 2011
2017-09-23 03:17:29 +00:00
# if __has_cpp_attribute(fallthrough)
# define fallthrough__ [[fallthrough]]
# elif __has_cpp_attribute(clang::fallthrough)
# define fallthrough__ [[clang::fallthrough]]
# elif __has_cpp_attribute(gnu::fallthrough)
# define fallthrough__ [[gnu::fallthrough]]
# endif
# endif
# ifndef fallthrough__
# if !defined __clang__ && EDUKE32_GCC_PREREQ(7,0)
# define fallthrough__ __attribute__((fallthrough))
# elif defined _MSC_VER
# define fallthrough__ __fallthrough
# else
# define fallthrough__
# endif
2017-07-10 13:44:04 +00:00
# endif
2017-02-25 08:15:16 +00:00
////////// Platform detection //////////
# if defined __FreeBSD__ || defined __NetBSD__ || defined __OpenBSD__ || defined __bsdi__ || defined __DragonFly__
# define EDUKE32_BSD
2015-01-19 00:11:25 +00:00
# endif
2017-02-25 08:15:16 +00:00
# ifdef __APPLE__
# include <TargetConditionals.h>
# if TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR
# define EDUKE32_IOS
2015-01-19 00:11:25 +00:00
# else
2017-02-25 08:15:16 +00:00
# define EDUKE32_OSX
2015-01-19 00:11:25 +00:00
# endif
2012-11-05 02:49:08 +00:00
# endif
2012-03-18 08:50:41 +00:00
2017-02-25 08:15:16 +00:00
////////// Architecture detection //////////
# if defined _LP64 || defined __LP64__ || defined __64BIT__ || _ADDR64 || defined _WIN64 || defined __arch64__ || \
__WORDSIZE = = 64 | | ( defined __sparc & & defined __sparcv9 ) | | defined __x86_64 | | defined __amd64 | | \
defined __x86_64__ | | defined __amd64__ | | defined _M_X64 | | defined _M_IA64 | | defined __ia64 | | defined __IA64__
# define BITNESS64
# endif
2011-07-20 23:04:20 +00:00
2006-04-13 20:47:06 +00:00
# if defined(__linux)
# include <endian.h>
# if __BYTE_ORDER == __LITTLE_ENDIAN
# define B_LITTLE_ENDIAN 1
# define B_BIG_ENDIAN 0
# elif __BYTE_ORDER == __BIG_ENDIAN
# define B_LITTLE_ENDIAN 0
# define B_BIG_ENDIAN 1
# endif
2012-08-19 04:01:04 +00:00
# elif defined(GEKKO) || defined(__ANDROID__)
2012-05-01 12:40:53 +00:00
# define B_LITTLE_ENDIAN 0
# define B_BIG_ENDIAN 1
2012-08-19 04:01:04 +00:00
# elif defined(__OpenBSD__)
# include <machine / endian.h>
# if _BYTE_ORDER == _LITTLE_ENDIAN
# define B_LITTLE_ENDIAN 1
# define B_BIG_ENDIAN 0
# elif _BYTE_ORDER == _BIG_ENDIAN
# define B_LITTLE_ENDIAN 0
# define B_BIG_ENDIAN 1
# endif
2015-03-02 07:54:24 +00:00
# elif defined EDUKE32_BSD
2006-04-13 20:47:06 +00:00
# include <sys / endian.h>
# if _BYTE_ORDER == _LITTLE_ENDIAN
# define B_LITTLE_ENDIAN 1
# define B_BIG_ENDIAN 0
# elif _BYTE_ORDER == _BIG_ENDIAN
# define B_LITTLE_ENDIAN 0
# define B_BIG_ENDIAN 1
# endif
# elif defined(__APPLE__)
# if defined(__LITTLE_ENDIAN__)
# define B_LITTLE_ENDIAN 1
# define B_BIG_ENDIAN 0
# elif defined(__BIG_ENDIAN__)
# define B_LITTLE_ENDIAN 0
# define B_BIG_ENDIAN 1
# endif
# include <libkern / OSByteOrder.h>
# elif defined(__BEOS__)
# include <posix / endian.h>
# if LITTLE_ENDIAN != 0
# define B_LITTLE_ENDIAN 1
# define B_BIG_ENDIAN 0
# elif BIG_ENDIAN != 0
# define B_LITTLE_ENDIAN 0
# define B_BIG_ENDIAN 1
# endif
# elif defined(__QNX__)
# if defined __LITTLEENDIAN__
# define B_LITTLE_ENDIAN 1
# define B_BIG_ENDIAN 0
# elif defined __BIGENDIAN__
# define B_LITTLE_ENDIAN 0
# define B_BIG_ENDIAN 1
# endif
# elif defined(__sun)
# if defined _LITTLE_ENDIAN
# define B_LITTLE_ENDIAN 1
# define B_BIG_ENDIAN 0
# elif defined _BIG_ENDIAN
# define B_LITTLE_ENDIAN 0
# define B_BIG_ENDIAN 1
# endif
# elif defined(_WIN32) || defined(SKYOS) || defined(__SYLLABLE__)
# define B_LITTLE_ENDIAN 1
# define B_BIG_ENDIAN 0
# endif
# if !defined(B_LITTLE_ENDIAN) || !defined(B_BIG_ENDIAN)
# error Unknown endianness
# endif
2015-01-11 04:53:16 +00:00
2017-02-25 08:15:16 +00:00
////////// Standard library headers //////////
# undef __USE_MINGW_ANSI_STDIO // Workaround for MinGW-w64.
2015-01-11 04:53:16 +00:00
2017-02-25 08:15:16 +00:00
# ifndef __STDC_FORMAT_MACROS
# define __STDC_FORMAT_MACROS
# endif
# ifndef __STDC_LIMIT_MACROS
# define __STDC_LIMIT_MACROS
2014-01-27 10:31:39 +00:00
# endif
2017-02-25 08:15:20 +00:00
2018-03-17 03:26:05 +00:00
# ifndef _USE_MATH_DEFINES
# define _USE_MATH_DEFINES
# endif
2019-04-18 17:24:22 +00:00
# include <inttypes.h>
# include <stdint.h>
2006-08-31 01:54:23 +00:00
2017-02-25 08:15:36 +00:00
# include <limits.h>
2017-02-25 08:15:16 +00:00
# include <stdarg.h>
2018-11-18 18:09:48 +00:00
# include <stddef.h>
2019-03-01 08:51:50 +00:00
# ifndef USE_PHYSFS
2017-02-25 08:15:16 +00:00
# include <stdio.h>
2019-03-01 08:51:50 +00:00
# endif
2018-11-18 18:09:48 +00:00
# include <stdlib.h>
2017-02-25 08:15:16 +00:00
# include <string.h>
2006-08-31 01:54:23 +00:00
2019-07-16 09:35:09 +00:00
# if !(defined _WIN32 && defined __clang__)
2017-02-25 08:15:36 +00:00
# include <float.h>
2019-07-16 09:35:09 +00:00
# endif
2018-11-18 18:09:48 +00:00
# include <math.h>
2006-04-13 20:47:06 +00:00
2017-02-25 08:15:16 +00:00
# include <ctype.h>
# include <errno.h>
2018-11-18 18:09:48 +00:00
# include <time.h>
2015-05-03 07:03:12 +00:00
2017-02-25 08:15:16 +00:00
# include <assert.h>
2015-05-03 07:03:48 +00:00
2017-04-12 08:30:29 +00:00
# ifdef __cplusplus
2019-07-16 09:35:09 +00:00
# include <limits>
2017-06-05 10:05:17 +00:00
# if CXXSTD >= 2011 || EDUKE32_MSVC_PREREQ(1800)
2018-10-16 06:09:54 +00:00
# include <algorithm>
# include <functional>
2017-04-12 08:30:29 +00:00
# include <type_traits>
2019-04-10 01:00:38 +00:00
// we need this because MSVC does not properly identify C++11 support
# define HAVE_CXX11_HEADERS
2017-04-12 08:30:29 +00:00
# endif
# endif
2017-02-25 08:15:16 +00:00
////////// Platform headers //////////
# if !defined __APPLE__ && (!defined EDUKE32_BSD || !__STDC__)
# include <malloc.h>
2006-04-13 20:47:06 +00:00
# endif
2019-03-01 08:51:50 +00:00
# ifndef USE_PHYSFS
2017-02-25 08:15:16 +00:00
# include <fcntl.h>
# include <sys/stat.h>
2018-11-18 18:09:48 +00:00
# include <sys/types.h>
2015-05-03 07:03:48 +00:00
2017-02-25 08:15:16 +00:00
# if defined(_WIN32)
2017-02-25 08:15:36 +00:00
# include <direct.h>
2018-11-18 18:09:48 +00:00
# include <io.h>
2015-05-03 07:03:48 +00:00
# else
2017-02-25 08:15:16 +00:00
# include <unistd.h>
2015-05-03 07:03:48 +00:00
# endif
2019-03-01 08:51:50 +00:00
# endif
2014-02-10 11:00:25 +00:00
2017-02-25 08:15:16 +00:00
////////// DEPRECATED: Standard library prefixing //////////
# ifdef _MSC_VER
2017-07-22 04:00:20 +00:00
# if defined _M_AMD64 || defined _M_ARM64 || defined _M_X64 || defined _WIN64
2019-11-08 01:02:54 +00:00
typedef int64_t ssize_t ;
2017-07-22 04:00:20 +00:00
# else
typedef int32_t ssize_t ;
# endif
2006-04-13 20:47:06 +00:00
# endif
2017-06-24 21:18:12 +00:00
2017-02-25 08:15:16 +00:00
typedef size_t bsize_t ;
typedef ssize_t bssize_t ;
# define BMAX_PATH 256
# define Bassert assert
# define Brand rand
# define Balloca alloca
# define Bmalloc malloc
# define Bcalloc calloc
# define Brealloc realloc
2019-11-08 01:02:54 +00:00
2017-02-25 08:15:16 +00:00
# define Bstrcpy strcpy
# define Bstrncpy strncpy
# define Bstrcmp strcmp
# define Bstrncmp strncmp
# define Bstrcat strcat
# define Bstrncat strncat
# define Bstrlen strlen
# define Bstrchr strchr
# define Bstrrchr strrchr
# define Bstrtol strtol
# define Bstrtoul strtoul
# define Bstrtod strtod
# define Bstrstr strstr
# define Bislower islower
# define Bisupper isupper
# define Bisdigit isdigit
# define Btoupper toupper
# define Btolower tolower
# define Bmemcpy memcpy
# define Bmemset memset
# define Bmemcmp memcmp
# define Bsprintf sprintf
////////// Standard library wrappers //////////
# if defined(_MSC_VER)
# define Bstrcasecmp _stricmp
# define Bstrncasecmp _strnicmp
# elif defined(__QNX__)
# define Bstrcasecmp stricmp
# define Bstrncasecmp strnicmp
2011-03-23 17:41:01 +00:00
# else
2017-02-25 08:15:16 +00:00
# define Bstrcasecmp strcasecmp
# define Bstrncasecmp strncasecmp
2011-03-23 17:41:01 +00:00
# endif
2013-05-16 21:54:59 +00:00
2020-01-25 09:56:30 +00:00
static inline int32_t atoi_safe ( const char * str ) { return ( int32_t ) strtoll ( str , NULL , 10 ) ; }
2019-12-07 23:50:27 +00:00
# define Batoi(x) atoi_safe(x)
2017-02-25 08:15:16 +00:00
# define Batol(str) (strtol(str, NULL, 10))
2014-04-12 08:45:08 +00:00
2020-01-25 10:56:13 +00:00
static inline int Blrintf ( const double x )
2017-02-25 08:15:16 +00:00
{
2020-01-25 10:56:13 +00:00
return xs_CRoundToInt ( x ) ;
2017-02-25 08:15:16 +00:00
}
2006-04-13 20:47:06 +00:00
2017-02-25 08:15:16 +00:00
# if defined(__arm__)
# define Bsqrtf __builtin_sqrtf
2015-03-24 00:40:33 +00:00
# else
2017-02-25 08:15:16 +00:00
# define Bsqrtf sqrtf
2015-03-24 00:40:33 +00:00
# endif
2006-04-13 20:47:06 +00:00
2019-10-26 08:30:08 +00:00
class ExitEvent : public std : : exception
{
int reason ;
public :
ExitEvent ( int a ) { reason = a ; }
int Reason ( ) const { return reason ; }
} ;
inline void Bexit ( int a )
{
throw ExitEvent ( a ) ;
}
2017-02-25 08:15:16 +00:00
////////// Standard library monkey patching //////////
# ifndef NULL
# define NULL ((void *)0)
# endif
2006-04-13 20:47:06 +00:00
2017-03-23 03:03:26 +00:00
# ifndef O_BINARY
# define O_BINARY 0
# endif
# ifndef O_TEXT
# define O_TEXT 0
# endif
# ifndef F_OK
# define F_OK 0
# endif
2014-12-27 18:36:43 +00:00
2017-04-12 08:30:29 +00:00
////////// Metaprogramming structs //////////
# ifdef __cplusplus
2019-04-10 01:00:38 +00:00
# ifdef HAVE_CXX11_HEADERS
2017-04-12 08:30:29 +00:00
using std : : is_integral ;
2018-01-13 22:15:07 +00:00
template < typename T >
struct is_signed
{
static constexpr bool value = std : : is_signed < T > : : value ;
} ;
template < typename T >
struct is_unsigned
{
static constexpr bool value = std : : is_unsigned < T > : : value ;
} ;
2017-04-12 08:30:29 +00:00
# endif
# if CXXSTD >= 2014
using std : : enable_if_t ;
using std : : conditional_t ;
2017-06-05 10:05:03 +00:00
using std : : make_signed_t ;
using std : : make_unsigned_t ;
2019-06-25 11:30:08 +00:00
using std : : remove_pointer_t ;
2019-04-10 01:00:38 +00:00
# elif defined HAVE_CXX11_HEADERS
2017-04-12 08:30:29 +00:00
template < bool B , class T = void >
using enable_if_t = typename std : : enable_if < B , T > : : type ;
template < bool B , class T , class F >
using conditional_t = typename std : : conditional < B , T , F > : : type ;
2017-06-05 10:05:03 +00:00
template < typename T >
using make_signed_t = typename std : : make_signed < T > : : type ;
template < typename T >
using make_unsigned_t = typename std : : make_unsigned < T > : : type ;
2019-09-20 12:32:28 +00:00
template < class T >
2019-06-25 11:30:08 +00:00
using remove_pointer_t = typename std : : remove_pointer < T > : : type ;
2017-04-12 08:30:29 +00:00
# endif
2019-04-10 01:00:50 +00:00
# ifdef HAVE_CXX11_HEADERS
template < typename type , typename other_type_with_sign >
using take_sign_t = conditional_t < is_signed < other_type_with_sign > : : value , make_signed_t < type > , make_unsigned_t < type > > ;
# endif
2017-04-12 08:30:32 +00:00
template < size_t size >
struct integers_of_size { } ;
template < >
struct integers_of_size < sizeof ( int8_t ) >
{
typedef int8_t i ;
typedef uint8_t u ;
} ;
template < >
struct integers_of_size < sizeof ( int16_t ) >
{
typedef int16_t i ;
typedef uint16_t u ;
} ;
template < >
struct integers_of_size < sizeof ( int32_t ) >
{
typedef int32_t i ;
typedef uint32_t u ;
} ;
template < >
struct integers_of_size < sizeof ( int64_t ) >
{
typedef int64_t i ;
typedef uint64_t u ;
} ;
2017-04-12 08:30:29 +00:00
# endif
2017-02-25 08:15:16 +00:00
////////// Typedefs //////////
2017-07-22 04:00:18 +00:00
# if defined(__x86_64__)
// for 32-bit pointers in x86_64 code, such as `gcc -mx32`
typedef uint64_t reg_t ;
typedef int64_t sreg_t ;
# else
typedef size_t reg_t ;
2017-07-27 09:13:32 +00:00
typedef ssize_t sreg_t ;
2017-07-22 04:00:18 +00:00
# endif
2019-04-10 01:00:38 +00:00
# ifdef HAVE_CXX11_HEADERS
2017-07-22 04:00:18 +00:00
using native_t = typename integers_of_size < sizeof ( reg_t ) > : : i ;
using unative_t = typename integers_of_size < sizeof ( reg_t ) > : : u ;
2017-04-12 08:30:32 +00:00
# else
2017-07-22 04:00:18 +00:00
typedef sreg_t native_t ;
typedef reg_t unative_t ;
2017-04-12 08:30:32 +00:00
# endif
EDUKE32_STATIC_ASSERT ( sizeof ( native_t ) = = sizeof ( unative_t ) ) ;
2018-12-23 23:23:50 +00:00
typedef struct MAY_ALIAS {
2014-12-27 18:36:43 +00:00
int32_t x , y ;
} vec2_t ;
2019-06-25 11:28:04 +00:00
typedef struct MAY_ALIAS {
2017-06-24 09:21:13 +00:00
int16_t x , y ;
2019-06-25 11:28:04 +00:00
} vec2_16_t ;
2015-05-27 08:48:07 +00:00
typedef struct {
uint32_t x , y ;
} vec2u_t ;
2014-12-27 18:36:43 +00:00
typedef struct {
float x , y ;
} vec2f_t ;
2019-03-02 23:21:52 +00:00
typedef struct {
double x , y ;
} vec2d_t ;
2019-06-25 11:28:04 +00:00
typedef struct MAY_ALIAS {
2019-07-24 01:38:05 +00:00
union {
struct { int32_t x , y , z ; } ;
vec2_t vec2 ;
} ;
2019-06-25 11:28:04 +00:00
} vec3_t ;
typedef struct MAY_ALIAS {
2019-07-24 01:38:05 +00:00
union {
struct { int16_t x , y , z ; } ;
vec2_16_t vec2 ;
} ;
2019-06-25 11:28:04 +00:00
} vec3_16_t ;
2014-12-27 18:36:43 +00:00
typedef struct {
2019-07-24 01:38:05 +00:00
union {
struct {
union { float x , d ; } ;
union { float y , u ; } ;
union { float z , v ; } ;
} ;
vec2f_t vec2 ;
} ;
2014-12-27 18:36:43 +00:00
} vec3f_t ;
2015-03-24 00:40:33 +00:00
EDUKE32_STATIC_ASSERT ( sizeof ( vec3f_t ) = = sizeof ( float ) * 3 ) ;
typedef struct {
union { double x ; double d ; } ;
union { double y ; double u ; } ;
union { double z ; double v ; } ;
} vec3d_t ;
EDUKE32_STATIC_ASSERT ( sizeof ( vec3d_t ) = = sizeof ( double ) * 3 ) ;
2014-12-27 18:36:43 +00:00
2018-05-08 17:32:16 +00:00
typedef struct {
float x , y , z , w ;
} vec4f_t ;
typedef struct {
float x , y , z , w ;
} vec4d_t ;
2006-04-13 20:47:06 +00:00
2017-02-25 08:16:01 +00:00
////////// Language tricks that depend on size_t //////////
2019-12-29 15:35:51 +00:00
# include "basics.h"
# define ARRAY_SIZE(arr) countof(arr)
2017-12-02 08:45:04 +00:00
# define ARRAY_SSIZE(arr) (native_t)ARRAY_SIZE(arr)
2017-02-25 08:16:01 +00:00
2017-02-25 08:15:16 +00:00
////////// Memory management //////////
2012-03-01 23:36:11 +00:00
2017-02-25 08:15:16 +00:00
# if !defined NO_ALIGNED_MALLOC
2017-02-25 08:15:53 +00:00
static FORCE_INLINE void * Baligned_alloc ( const size_t alignment , const size_t size )
2017-02-25 08:15:16 +00:00
{
# ifdef _WIN32
void * ptr = _aligned_malloc ( size , alignment ) ;
# elif defined __APPLE__ || defined EDUKE32_BSD
void * ptr = NULL ;
posix_memalign ( & ptr , alignment , size ) ;
2017-02-25 08:15:10 +00:00
# else
2017-02-25 08:15:16 +00:00
void * ptr = memalign ( alignment , size ) ;
2017-02-25 08:15:10 +00:00
# endif
2017-02-25 08:15:16 +00:00
return ptr ;
}
2017-02-25 08:15:10 +00:00
# else
2017-02-25 08:15:16 +00:00
# define Baligned_alloc(alignment, size) Bmalloc(size)
2017-02-25 08:15:10 +00:00
# endif
2017-02-25 08:15:16 +00:00
# if defined _WIN32 && !defined NO_ALIGNED_MALLOC
# define Baligned_free _aligned_free
2017-02-25 08:15:10 +00:00
# else
2020-02-03 18:12:36 +00:00
# define Baligned_free free
2017-02-25 08:15:10 +00:00
# endif
2017-02-25 08:15:16 +00:00
////////// Pointer management //////////
# define DO_FREE_AND_NULL(var) do { \
2019-06-25 11:29:08 +00:00
Xfree ( var ) ; ( var ) = NULL ; \
2017-02-25 08:15:16 +00:00
} while ( 0 )
# define ALIGNED_FREE_AND_NULL(var) do { \
2019-06-25 11:29:08 +00:00
Xaligned_free ( var ) ; ( var ) = NULL ; \
2017-02-25 08:15:16 +00:00
} while ( 0 )
////////// Data serialization //////////
2019-04-08 06:27:48 +00:00
static FORCE_INLINE CONSTEXPR uint16_t B_SWAP16_impl ( uint16_t value )
2017-02-25 08:15:16 +00:00
{
2017-04-12 08:30:26 +00:00
return
( ( value & 0xFF00u ) > > 8u ) |
( ( value & 0x00FFu ) < < 8u ) ;
2017-02-25 08:15:16 +00:00
}
2019-04-08 06:27:48 +00:00
static FORCE_INLINE CONSTEXPR uint32_t B_SWAP32_impl ( uint32_t value )
2017-02-25 08:15:16 +00:00
{
2017-04-12 08:30:26 +00:00
return
( ( value & 0xFF000000u ) > > 24u ) |
( ( value & 0x00FF0000u ) > > 8u ) |
( ( value & 0x0000FF00u ) < < 8u ) |
( ( value & 0x000000FFu ) < < 24u ) ;
2017-02-25 08:15:16 +00:00
}
2019-04-08 06:27:48 +00:00
static FORCE_INLINE CONSTEXPR uint64_t B_SWAP64_impl ( uint64_t value )
2017-02-25 08:15:16 +00:00
{
2017-04-12 08:30:26 +00:00
return
( ( value & 0xFF00000000000000ULL ) > > 56ULL ) |
( ( value & 0x00FF000000000000ULL ) > > 40ULL ) |
( ( value & 0x0000FF0000000000ULL ) > > 24ULL ) |
( ( value & 0x000000FF00000000ULL ) > > 8ULL ) |
( ( value & 0x00000000FF000000ULL ) < < 8ULL ) |
( ( value & 0x0000000000FF0000ULL ) < < 24ULL ) |
( ( value & 0x000000000000FF00ULL ) < < 40ULL ) |
( ( value & 0x00000000000000FFULL ) < < 56ULL ) ;
2017-02-25 08:15:16 +00:00
}
2019-04-08 06:27:48 +00:00
/* The purpose of B_PASS* as functions, as opposed to macros, is to prevent them from being used as lvalues. */
2019-06-25 11:29:15 +00:00
# if CXXSTD >= 2011 || EDUKE32_MSVC_PREREQ(1900)
2019-04-08 06:27:48 +00:00
template < typename T >
2019-04-10 01:00:50 +00:00
static FORCE_INLINE CONSTEXPR take_sign_t < int16_t , T > B_SWAP16 ( T x )
2019-04-08 06:27:48 +00:00
{
2019-04-10 01:00:50 +00:00
return static_cast < take_sign_t < int16_t , T > > ( B_SWAP16_impl ( static_cast < uint16_t > ( x ) ) ) ;
2019-04-08 06:27:48 +00:00
}
template < typename T >
2019-04-10 01:00:50 +00:00
static FORCE_INLINE CONSTEXPR take_sign_t < int32_t , T > B_SWAP32 ( T x )
2019-04-08 06:27:48 +00:00
{
2019-04-10 01:00:50 +00:00
return static_cast < take_sign_t < int32_t , T > > ( B_SWAP32_impl ( static_cast < uint32_t > ( x ) ) ) ;
2019-04-08 06:27:48 +00:00
}
template < typename T >
2019-04-10 01:00:50 +00:00
static FORCE_INLINE CONSTEXPR take_sign_t < int64_t , T > B_SWAP64 ( T x )
2019-04-08 06:27:48 +00:00
{
2019-04-10 01:00:50 +00:00
return static_cast < take_sign_t < int64_t , T > > ( B_SWAP64_impl ( static_cast < uint64_t > ( x ) ) ) ;
2019-04-08 06:27:48 +00:00
}
template < typename T >
2019-04-10 01:00:50 +00:00
static FORCE_INLINE CONSTEXPR take_sign_t < int16_t , T > B_PASS16 ( T x )
2019-04-08 06:27:48 +00:00
{
2019-04-10 01:00:50 +00:00
return static_cast < take_sign_t < int16_t , T > > ( x ) ;
2019-04-08 06:27:48 +00:00
}
template < typename T >
2019-04-10 01:00:50 +00:00
static FORCE_INLINE CONSTEXPR take_sign_t < int32_t , T > B_PASS32 ( T x )
2019-04-08 06:27:48 +00:00
{
2019-04-10 01:00:50 +00:00
return static_cast < take_sign_t < int32_t , T > > ( x ) ;
2019-04-08 06:27:48 +00:00
}
template < typename T >
2019-04-10 01:00:50 +00:00
static FORCE_INLINE CONSTEXPR take_sign_t < int64_t , T > B_PASS64 ( T x )
2019-04-08 06:27:48 +00:00
{
2019-04-10 01:00:50 +00:00
return static_cast < take_sign_t < int64_t , T > > ( x ) ;
2019-04-08 06:27:48 +00:00
}
# else
# define B_SWAP16(x) B_SWAP16_impl(x)
# define B_SWAP32(x) B_SWAP32_impl(x)
# define B_SWAP64(x) B_SWAP64_impl(x)
2017-04-12 08:30:26 +00:00
static FORCE_INLINE CONSTEXPR uint16_t B_PASS16 ( uint16_t const x ) { return x ; }
static FORCE_INLINE CONSTEXPR uint32_t B_PASS32 ( uint32_t const x ) { return x ; }
static FORCE_INLINE CONSTEXPR uint64_t B_PASS64 ( uint64_t const x ) { return x ; }
2019-04-08 06:27:48 +00:00
# endif
2017-02-25 08:15:16 +00:00
# if B_LITTLE_ENDIAN == 1
# define B_LITTLE64(x) B_PASS64(x)
# define B_BIG64(x) B_SWAP64(x)
# define B_LITTLE32(x) B_PASS32(x)
# define B_BIG32(x) B_SWAP32(x)
# define B_LITTLE16(x) B_PASS16(x)
# define B_BIG16(x) B_SWAP16(x)
# elif B_BIG_ENDIAN == 1
# define B_LITTLE64(x) B_SWAP64(x)
# define B_BIG64(x) B_PASS64(x)
# define B_LITTLE32(x) B_SWAP32(x)
# define B_BIG32(x) B_PASS32(x)
# define B_LITTLE16(x) B_SWAP16(x)
# define B_BIG16(x) B_PASS16(x)
# endif
2017-02-25 08:15:53 +00:00
static FORCE_INLINE void B_BUF16 ( void * const buf , uint16_t const x ) { * ( uint16_t * ) buf = x ; }
static FORCE_INLINE void B_BUF32 ( void * const buf , uint32_t const x ) { * ( uint32_t * ) buf = x ; }
static FORCE_INLINE void B_BUF64 ( void * const buf , uint64_t const x ) { * ( uint64_t * ) buf = x ; }
2017-02-25 08:15:16 +00:00
2018-10-25 23:33:52 +00:00
static FORCE_INLINE CONSTEXPR uint16_t B_UNBUF16 ( void const * const buf ) { return * ( uint16_t const * ) buf ; }
static FORCE_INLINE CONSTEXPR uint32_t B_UNBUF32 ( void const * const buf ) { return * ( uint32_t const * ) buf ; }
static FORCE_INLINE CONSTEXPR uint64_t B_UNBUF64 ( void const * const buf ) { return * ( uint64_t const * ) buf ; }
2017-02-25 08:15:16 +00:00
////////// Abstract data operations //////////
2018-10-25 23:33:52 +00:00
# define ABSTRACT_DECL static FORCE_INLINE WARN_UNUSED_RESULT CONSTEXPR
2017-06-27 02:23:46 +00:00
# ifdef __cplusplus
2018-10-16 06:09:54 +00:00
template < typename T , typename X , typename Y > ABSTRACT_DECL T clamp ( T in , X min , Y max ) { return in < = ( T ) min ? ( T ) min : ( in > = ( T ) max ? ( T ) max : in ) ; }
template < typename T , typename X , typename Y > ABSTRACT_DECL T clamp2 ( T in , X min , Y max ) { return in > = ( T ) max ? ( T ) max : ( in < = ( T ) min ? ( T ) min : in ) ; }
using std : : min ;
using std : : max ;
2017-06-27 02:23:46 +00:00
# define fclamp clamp
# define fclamp2 clamp2
# else
2017-02-25 08:15:16 +00:00
// Clamp <in> to [<min>..<max>]. The case in <= min is handled first.
2018-10-16 06:09:54 +00:00
ABSTRACT_DECL int32_t clamp ( int32_t in , int32_t min , int32_t max ) { return in < = min ? min : ( in > = max ? max : in ) ; }
ABSTRACT_DECL float fclamp ( float in , float min , float max ) { return in < = min ? min : ( in > = max ? max : in ) ; }
2017-02-25 08:15:16 +00:00
// Clamp <in> to [<min>..<max>]. The case in >= max is handled first.
2018-10-16 06:09:54 +00:00
ABSTRACT_DECL int32_t clamp2 ( int32_t in , int32_t min , int32_t max ) { return in > = max ? max : ( in < = min ? min : in ) ; }
ABSTRACT_DECL float fclamp2 ( float in , float min , float max ) { return in > = max ? max : ( in < = min ? min : in ) ; }
# ifndef min
# define min(a, b) (((a) < (b)) ? (a) : (b))
# endif
# ifndef max
# define max(a, b) (((a) > (b)) ? (a) : (b))
# endif
2017-06-27 02:23:46 +00:00
# endif
2017-02-25 08:15:16 +00:00
2017-04-12 08:30:35 +00:00
////////// Mathematical operations //////////
# ifdef __cplusplus
2019-04-10 01:00:38 +00:00
# ifdef HAVE_CXX11_HEADERS
2017-06-05 10:05:03 +00:00
template < typename T >
struct DivResult
{
T q ; // quotient
T r ; // remainder
} ;
template < typename T >
FORCE_INLINE CONSTEXPR DivResult < T > divide ( T lhs , T rhs )
{
return DivResult < T > { ( T ) ( lhs / rhs ) , ( T ) ( lhs % rhs ) } ;
}
template < native_t base , typename T >
FORCE_INLINE CONSTEXPR DivResult < T > divrhs ( T lhs )
{
return divide ( lhs , ( T ) base ) ;
}
2019-11-26 08:25:13 +00:00
template < typename T , typename T2 >
static FORCE_INLINE CONSTEXPR_CXX14 enable_if_t < is_signed < T > : : value , T > NEGATE_ON_CONDITION ( T value , T2 condition )
{
T const invert = ! ! condition ;
return ( value ^ - invert ) + invert ;
}
2017-06-05 10:05:03 +00:00
# endif
2017-04-12 08:30:35 +00:00
template < size_t base , typename T >
CONSTEXPR size_t logbase ( T n )
{
return n < static_cast < T > ( base ) ? 1 : 1 + logbase < base > ( n / static_cast < T > ( base ) ) ;
}
// hackish version to work around the impossibility of representing abs(INT*_MIN)
template < size_t base , typename T >
CONSTEXPR size_t logbasenegative ( T n )
{
return n > static_cast < T > ( - ( native_t ) base ) ? 1 : 1 + logbase < base > ( n / static_cast < T > ( - ( native_t ) base ) ) ;
}
2019-11-26 08:25:13 +00:00
# endif
2019-09-18 22:19:02 +00:00
# define isPow2OrZero(v) (((v) & ((v) - 1)) == 0)
2018-04-11 03:34:03 +00:00
# define isPow2(v) (isPow2OrZero(v) && (v))
2019-05-19 03:52:54 +00:00
////////// Bitfield manipulation //////////
2019-11-02 09:45:41 +00:00
#if 0
// Behold the probably most useless (de)optimization I ever discovered.
// Replacing a simple bit shift with a memory access through a global pointer is surely going to improve matters... >(
// Constexpr means shit here if the index is not a constant!
2019-09-10 23:35:07 +00:00
static CONSTEXPR const char pow2char [ 8 ] = { 1 , 2 , 4 , 8 , 16 , 32 , 64 , 128u } ;
2019-11-02 09:45:41 +00:00
# else
// Revert the above to a real bit shift through some C++ operator magic. That saves me from reverting all the code that uses this construct.
2019-11-13 21:40:08 +00:00
static struct
2019-11-02 09:45:41 +00:00
{
constexpr uint8_t operator [ ] ( int index ) const { return 1 < < index ; } ;
} pow2char ;
# endif
2019-08-04 02:51:50 +00:00
static FORCE_INLINE void bitmap_set ( uint8_t * const ptr , int const n ) { ptr [ n > > 3 ] | = pow2char [ n & 7 ] ; }
static FORCE_INLINE void bitmap_clear ( uint8_t * const ptr , int const n ) { ptr [ n > > 3 ] & = ~ pow2char [ n & 7 ] ; }
static FORCE_INLINE CONSTEXPR char bitmap_test ( uint8_t const * const ptr , int const n ) { return ptr [ n > > 3 ] & pow2char [ n & 7 ] ; }
2017-04-12 08:30:35 +00:00
2017-02-25 08:15:16 +00:00
////////// Utility functions //////////
2019-05-19 03:52:54 +00:00
// breadth-first search helpers
template < typename T >
void bfirst_search_init ( T * const list , uint8_t * const bitmap , T * const eltnumptr , int const maxelts , int const firstelt )
{
Bmemset ( bitmap , 0 , ( maxelts + 7 ) > > 3 ) ;
list [ 0 ] = firstelt ;
bitmap_set ( bitmap , firstelt ) ;
* eltnumptr = 1 ;
}
template < typename T >
void bfirst_search_try ( T * const list , uint8_t * const bitmap , T * const eltnumptr , int const elt )
{
if ( ! bitmap_test ( bitmap , elt ) )
{
bitmap_set ( bitmap , elt ) ;
list [ ( * eltnumptr ) + + ] = elt ;
}
}
2017-02-25 08:15:16 +00:00
# if RAND_MAX == 32767
2017-02-25 08:15:53 +00:00
static FORCE_INLINE uint16_t system_15bit_rand ( void ) { return ( uint16_t ) rand ( ) ; }
2017-02-25 08:15:16 +00:00
# else // RAND_MAX > 32767, assumed to be of the form 2^k - 1
2017-02-25 08:15:53 +00:00
static FORCE_INLINE uint16_t system_15bit_rand ( void ) { return ( ( uint16_t ) rand ( ) ) & 0x7fff ; }
2006-04-13 20:47:06 +00:00
# endif
2013-05-06 19:43:38 +00:00
// Copy min(strlen(src)+1, n) characters into dst, always terminate with a NUL.
2017-02-25 08:15:53 +00:00
static FORCE_INLINE char * Bstrncpyz ( char * dst , const char * src , bsize_t n )
2012-11-20 01:33:22 +00:00
{
Bstrncpy ( dst , src , n ) ;
dst [ n - 1 ] = 0 ;
return dst ;
}
2013-05-06 19:43:38 +00:00
// Append extension when <outbuf> contains no dot.
2013-06-13 17:10:56 +00:00
// <ext> can be like ".mhk" or like "_crash.map", no need to start with a dot.
2013-05-06 19:43:38 +00:00
// The ugly name is deliberate: we should be checking the sizes of all buffers!
static inline void append_ext_UNSAFE ( char * outbuf , const char * ext )
{
char * p = Bstrrchr ( outbuf , ' . ' ) ;
if ( ! p )
Bstrcat ( outbuf , ext ) ;
else
2013-06-13 17:10:56 +00:00
Bstrcpy ( p , ext ) ;
2013-05-06 19:43:38 +00:00
}
2017-02-25 08:15:16 +00:00
////////// Paths //////////
int32_t Bcorrectfilename ( char * filename , int32_t removefn ) ;
////////// String manipulation //////////
char * Bstrtoken ( char * s , const char * delim , char * * ptrptr , int chop ) ;
char * Bstrtolower ( char * str ) ;
////////// Miscellaneous //////////
2019-09-02 05:55:32 +00:00
int Bgetpagesize ( void ) ;
2017-02-25 08:15:16 +00:00
uint32_t Bgetsysmemsize ( void ) ;
////////// PANICKING ALLOCATION WRAPPERS //////////
2014-05-30 00:02:16 +00:00
# ifdef DEBUGGINGAIDS
extern void xalloc_set_location ( int32_t line , const char * file , const char * func ) ;
# endif
void set_memerr_handler ( void ( * handlerfunc ) ( int32_t , const char * , const char * ) ) ;
2018-10-25 23:30:22 +00:00
void * handle_memerr ( void * ) ;
2014-09-30 04:12:27 +00:00
2017-02-25 08:15:53 +00:00
static FORCE_INLINE char * xstrdup ( const char * s )
2014-09-30 04:12:27 +00:00
{
2020-01-25 09:56:30 +00:00
char * ptr = strdup ( s ) ;
2019-05-19 03:55:10 +00:00
return ( EDUKE32_PREDICT_TRUE ( ptr ! = NULL ) ) ? ptr : ( char * ) handle_memerr ( ptr ) ;
2014-09-30 04:12:27 +00:00
}
2017-02-25 08:15:53 +00:00
static FORCE_INLINE void * xmalloc ( const bsize_t size )
2014-09-30 04:12:27 +00:00
{
void * ptr = Bmalloc ( size ) ;
2019-05-19 03:55:10 +00:00
return ( EDUKE32_PREDICT_TRUE ( ptr ! = NULL ) ) ? ptr : handle_memerr ( ptr ) ;
2014-09-30 04:12:27 +00:00
}
2017-02-25 08:15:53 +00:00
static FORCE_INLINE void * xcalloc ( const bsize_t nmemb , const bsize_t size )
2014-09-30 04:12:27 +00:00
{
void * ptr = Bcalloc ( nmemb , size ) ;
2019-05-19 03:55:10 +00:00
return ( EDUKE32_PREDICT_TRUE ( ptr ! = NULL ) ) ? ptr : handle_memerr ( ptr ) ;
2014-09-30 04:12:27 +00:00
}
2017-02-25 08:15:53 +00:00
static FORCE_INLINE void * xrealloc ( void * const ptr , const bsize_t size )
2014-09-30 04:12:27 +00:00
{
void * newptr = Brealloc ( ptr , size ) ;
// According to the C Standard,
// - ptr == NULL makes realloc() behave like malloc()
// - size == 0 make it behave like free() if ptr != NULL
// Since we want to catch an out-of-mem in the first case, this leaves:
2019-05-19 03:55:10 +00:00
return ( EDUKE32_PREDICT_TRUE ( newptr ! = NULL | | size = = 0 ) ) ? newptr : handle_memerr ( ptr ) ;
2014-09-30 04:12:27 +00:00
}
2019-09-20 11:17:19 +00:00
2020-02-03 18:12:36 +00:00
static FORCE_INLINE void xfree ( void * const ptr ) { free ( ptr ) ; }
2019-06-25 11:29:08 +00:00
static FORCE_INLINE void xaligned_free ( void * const ptr ) { Baligned_free ( ptr ) ; }
2016-02-29 06:33:58 +00:00
# if !defined NO_ALIGNED_MALLOC
2017-02-25 08:15:53 +00:00
static FORCE_INLINE void * xaligned_alloc ( const bsize_t alignment , const bsize_t size )
2014-10-29 17:04:28 +00:00
{
2017-02-25 08:15:16 +00:00
void * ptr = Baligned_alloc ( alignment , size ) ;
2019-05-19 03:55:10 +00:00
return ( EDUKE32_PREDICT_TRUE ( ptr ! = NULL ) ) ? ptr : handle_memerr ( ptr ) ;
2014-10-29 17:04:28 +00:00
}
2019-12-07 23:50:16 +00:00
static FORCE_INLINE void * xaligned_calloc ( const bsize_t alignment , const bsize_t count , const bsize_t size )
{
bsize_t const blocksize = count * size ;
void * ptr = Baligned_alloc ( alignment , blocksize ) ;
if ( EDUKE32_PREDICT_TRUE ( ptr ! = NULL ) )
{
Bmemset ( ptr , 0 , blocksize ) ;
return ptr ;
}
return handle_memerr ( ptr ) ;
}
2017-02-25 08:15:16 +00:00
# else
# define xaligned_alloc(alignment, size) xmalloc(size)
2019-12-07 23:50:16 +00:00
# define xaligned_calloc(alignment, count, size) xcalloc(count, size)
2016-02-29 06:33:58 +00:00
# endif
2014-05-30 00:02:16 +00:00
# ifdef DEBUGGINGAIDS
2019-05-19 03:55:14 +00:00
# define EDUKE32_PRE_XALLOC xalloc_set_location(__LINE__, __FILE__, EDUKE32_FUNCTION),
2014-05-30 00:02:16 +00:00
# else
2019-05-19 03:55:14 +00:00
# define EDUKE32_PRE_XALLOC
2014-05-30 00:02:16 +00:00
# endif
2014-10-29 17:04:28 +00:00
2019-12-26 13:43:44 +00:00
# ifndef _DEBUG
2019-05-19 03:55:14 +00:00
# define Xstrdup(s) (EDUKE32_PRE_XALLOC xstrdup(s))
# define Xmalloc(size) (EDUKE32_PRE_XALLOC xmalloc(size))
# define Xcalloc(nmemb, size) (EDUKE32_PRE_XALLOC xcalloc(nmemb, size))
# define Xrealloc(ptr, size) (EDUKE32_PRE_XALLOC xrealloc(ptr, size))
# define Xaligned_alloc(alignment, size) (EDUKE32_PRE_XALLOC xaligned_alloc(alignment, size))
2019-12-07 23:50:16 +00:00
# define Xaligned_calloc(alignment, count, size) (EDUKE32_PRE_XALLOC xaligned_calloc(alignment, count, size))
2019-06-25 11:29:08 +00:00
# define Xfree(ptr) (EDUKE32_PRE_XALLOC xfree(ptr))
# define Xaligned_free(ptr) (EDUKE32_PRE_XALLOC xaligned_free(ptr))
2019-12-26 13:43:44 +00:00
# else
// This is for allowing the compiler's heap checker to do its job. When wrapped it only points to the wrapper for a memory leak, not to the real location where the allocation takes place.
# define Xstrdup(s) (strdup(s))
# define Xmalloc(size) (malloc(size))
# define Xcalloc(nmemb, size) (calloc(nmemb, size))
# define Xrealloc(ptr, size) (realloc(ptr, size))
# define Xaligned_alloc(alignment, size) (malloc(size))
# define Xaligned_calloc(alignment, count, size) (calloc(count, size))
# define Xfree(ptr) (free(ptr))
# define Xaligned_free(ptr) (free(ptr))
# endif
2016-05-02 18:29:38 +00:00
2017-02-25 08:15:16 +00:00
////////// More utility functions //////////
2014-10-29 17:04:28 +00:00
2015-04-12 08:07:30 +00:00
static inline void maybe_grow_buffer ( char * * const buffer , int32_t * const buffersize , int32_t const newsize )
{
if ( newsize > * buffersize )
{
* buffer = ( char * ) Xrealloc ( * buffer , newsize ) ;
* buffersize = newsize ;
}
}
2017-02-25 08:15:16 +00:00
////////// Inlined external libraries //////////
2017-06-14 06:59:50 +00:00
# ifndef LIBDIVIDE_BODY
# define LIBDIVIDE_HEADER_ONLY
# endif
# define LIBDIVIDE_C_HEADERS
# define LIBDIVIDE_NONAMESPACE
# define LIBDIVIDE_NOINLINE
2018-03-07 04:21:05 +00:00
# include "fix16.h"
2018-11-18 18:09:48 +00:00
# include "libdivide.h"
2019-08-27 13:39:54 +00:00
# include "clockticks.hpp"
2019-12-17 18:37:05 +00:00
# include "vectors.h"
inline FVector3 GetSoundPos ( const vec3_t * pos )
{
// converts a Build coordinate to a sound system coordinate
const float xmul = 1 / 16.f ;
const float ymul = - 1 / 16.f ;
const float zmul = - 1 / 256.f ;
return { pos - > x * xmul , pos - > z * zmul , pos - > y * ymul } ;
}
2017-02-25 08:15:16 +00:00
/* End dependence on compat.o object. */
////////// EDuke32-specific features //////////
# ifndef TRUE
# define TRUE 1
# endif
# ifndef FALSE
# define FALSE 0
# endif
# define WITHKPLIB
# if DEBUGGINGAIDS>=2
# define DEBUG_MAIN_ARRAYS
# endif
# if !defined DEBUG_MAIN_ARRAYS
# define HAVE_CLIPSHAPE_FEATURE
# endif
2014-05-30 00:02:16 +00:00
2014-11-22 12:32:56 +00:00
# endif // compat_h_