1 /*
2 ===========================================================================
3 Copyright (C) 1999 - 2005, Id Software, Inc.
4 Copyright (C) 2000 - 2013, Raven Software, Inc.
5 Copyright (C) 2001 - 2013, Activision, Inc.
6 Copyright (C) 2005 - 2015, ioquake3 contributors
7 Copyright (C) 2013 - 2015, OpenJK contributors
8 
9 This file is part of the OpenJK source code.
10 
11 OpenJK is free software; you can redistribute it and/or modify it
12 under the terms of the GNU General Public License version 2 as
13 published by the Free Software Foundation.
14 
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 GNU General Public License for more details.
19 
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, see <http://www.gnu.org/licenses/>.
22 ===========================================================================
23 */
24 
25 #pragma once
26 
27 // for windows fastcall option
28 #define QDECL
29 #define QCALL
30 
31 // Win64
32 #if defined(WIN64) || defined(_WIN64) || defined(__WIN64__)
33 
34 	#define idx64
35 
36 	#undef QDECL
37 	#define QDECL __cdecl
38 
39 	#undef QCALL
40 	#define QCALL __stdcall
41 
42 	#if defined(_MSC_VER)
43 		#define OS_STRING "win_msvc"
44 	#elif defined(__MINGW64__)
45 		#define OS_STRING "win_mingw"
46 	#endif
47 
48 	#define QINLINE __inline
49 	#define PATH_SEP '\\'
50 
51 	#if defined(_M_ALPHA)
52 		#define ARCH_STRING "AXP"
53 	#else
54 		#define ARCH_STRING "x86_64"
55 	#endif
56 
57 	#define Q3_LITTLE_ENDIAN
58 
59 	#define DLL_EXT ".dll"
60 
61 // Win32
62 #elif defined(_WIN32) || defined(__WIN32__)
63 
64 	#undef QDECL
65 	#define	QDECL __cdecl
66 
67 	#undef QCALL
68 	#define QCALL __stdcall
69 
70 	#if defined(_MSC_VER)
71 		#define OS_STRING "win_msvc"
72 	#elif defined(__MINGW32__)
73 		#define OS_STRING "win_mingw"
74 	#endif
75 
76 	#define QINLINE __inline
77 	#define PATH_SEP '\\'
78 
79 	#if defined(_M_IX86) || defined(__i386__)
80 		#define ARCH_STRING "x86"
81 	#elif defined _M_ALPHA
82 		#define ARCH_STRING "AXP"
83 	#endif
84 
85 	#define Q3_LITTLE_ENDIAN
86 
87 	#define DLL_EXT ".dll"
88 
89 // MAC OS X
90 #elif defined(MACOS_X) || defined(__APPLE_CC__)
91 
92 	// make sure this is defined, just for sanity's sake...
93 	#ifndef MACOS_X
94 		#define MACOS_X
95 	#endif
96 
97 	#define OS_STRING "macosx"
98 	#define QINLINE inline
99 	#define	PATH_SEP '/'
100 
101 	#if defined(__ppc__)
102 		#define ARCH_STRING "ppc"
103 		#define Q3_BIG_ENDIAN
104 	#elif defined(__i386__)
105 		#define ARCH_STRING "x86"
106 		#define Q3_LITTLE_ENDIAN
107 	#elif defined(__x86_64__)
108 		#define idx64
109 		#define ARCH_STRING "x86_64"
110 		#define Q3_LITTLE_ENDIAN
111 	#endif
112 
113     #define DLL_EXT ".dylib"
114 
115 // Linux
116 #elif defined(__linux__) || defined(__FreeBSD_kernel__)
117 
118 	#include <endian.h>
119 
120 	#if defined(__linux__)
121 		#define OS_STRING "linux"
122 	#else
123 		#define OS_STRING "kFreeBSD"
124 	#endif
125 
126 	#define QINLINE inline
127 
128 	#define PATH_SEP '/'
129 
130 	#if !defined(ARCH_STRING)
131 		#error ARCH_STRING should be defined by the build system
132 	#endif
133 
134 	#if defined(__x86_64__)
135 		#define idx64
136 	#endif
137 
138 	#if __FLOAT_WORD_ORDER == __BIG_ENDIAN
139 		#define Q3_BIG_ENDIAN
140 	#else
141 		#define Q3_LITTLE_ENDIAN
142 	#endif
143 
144 	#define DLL_EXT ".so"
145 
146 // BSD
147 #elif defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__)
148 
149 	#include <sys/types.h>
150 	#include <machine/endian.h>
151 
152 	#ifndef __BSD__
153 		#define __BSD__
154 	#endif
155 
156 	#if defined(__FreeBSD__)
157 		#define OS_STRING "freebsd"
158 	#elif defined(__OpenBSD__)
159 		#define OS_STRING "openbsd"
160 	#elif defined(__NetBSD__)
161 		#define OS_STRING "netbsd"
162 	#elif defined(__DragonFly__)
163 		#define OS_STRING "dragonfly"
164 	#endif
165 
166 	#define QINLINE inline
167 	#define PATH_SEP '/'
168 
169 	#if !defined(ARCH_STRING)
170 		#error ARCH_STRING should be defined by the build system
171 	#endif
172 
173 	#if defined(__amd64__)
174 		#define idx64
175 	#endif
176 
177 	#if BYTE_ORDER == BIG_ENDIAN
178 		#define Q3_BIG_ENDIAN
179 	#else
180 		#define Q3_LITTLE_ENDIAN
181 	#endif
182 
183 	#define DLL_EXT ".so"
184 #endif
185 
186 #if (defined( _MSC_VER ) && (_MSC_VER < 1900)) || (defined(__GNUC__))
187 // VS2013, which for some reason we still support, does not support noexcept
188 // GCC GNU has the same problem: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=52869
189 #define NOEXCEPT
190 #define NOEXCEPT_IF(x)
191 #define IS_NOEXCEPT(x) false
192 #else
193 #define NOEXCEPT noexcept
194 #define NOEXCEPT_IF(x) noexcept(x)
195 #define IS_NOEXCEPT(x) noexcept(x)
196 #endif
197 
198 #if defined(__GNUC__)
199 #define NORETURN __attribute__((noreturn))
200 #define NORETURN_PTR __attribute__((noreturn))
201 #elif defined(_MSC_VER)
202 #define NORETURN __declspec(noreturn)
203 // __declspec doesn't work on function pointers
204 #define NORETURN_PTR /* nothing */
205 #else
206 #define NORETURN /* nothing */
207 #define NORETURN_PTR /* nothing */
208 #endif
209 
210 #define OVERRIDE override
211 
212 #if defined(__cplusplus)
213 	#include <cstddef>
214 
215 	// gcc versions < 4.9 did not add max_align_t to the std:: namespace, but instead
216 	// put it in the global namespace. Need this to provide uniform access to max_align_t
217 	#if defined(__GNUC__) && ((__GNUC__ < 4) || (__GNUC__ == 4 && __GNUC_MINOR__ < 9))
218 		typedef max_align_t qmax_align_t;
219 	#else
220 		typedef std::max_align_t qmax_align_t;
221 	#endif
222 #endif
223 
224 #if defined (_MSC_VER)
225 	#if _MSC_VER >= 1600
226 		#include <stdint.h>
227 	#else
228 		typedef signed __int64 int64_t;
229 		typedef signed __int32 int32_t;
230 		typedef signed __int16 int16_t;
231 		typedef signed __int8  int8_t;
232 		typedef unsigned __int64 uint64_t;
233 		typedef unsigned __int32 uint32_t;
234 		typedef unsigned __int16 uint16_t;
235 		typedef unsigned __int8  uint8_t;
236 	#endif
237 #else // not using MSVC
238 	#if !defined(__STDC_LIMIT_MACROS)
239 		#define __STDC_LIMIT_MACROS
240 	#endif
241 	#include <stdint.h>
242 #endif
243 
244 // catch missing defines in above blocks
245 #if !defined(OS_STRING)
246 	#error "Operating system not supported"
247 #endif
248 #if !defined(ARCH_STRING)
249 	#error "Architecture not supported"
250 #endif
251 #if !defined(DLL_EXT)
252 	#error "DLL_EXT not defined"
253 #endif
254 #if !defined(QINLINE)
255 	#error "QINLINE not defined"
256 #endif
257 #if !defined(PATH_SEP)
258 	#error "PATH_SEP not defined"
259 #endif
260 
261 // endianness
262 // Use compiler builtins where possible for maximum performance
263 #include <stdint.h>
264 #if !defined(__clang__) && (defined(__GNUC__) || defined(__GNUG__)) \
265             && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 403)
266 // gcc >= 4.3
267 
ShortSwap(uint16_t v)268 static inline uint16_t ShortSwap(uint16_t v)
269 {
270 #if __GNUC_MINOR__ >= 8
271     return __builtin_bswap16(v);
272 #else
273     return (v << 8) | (v >> 8);
274 #endif // gcc >= 4.8
275 }
276 
LongSwap(uint32_t v)277 static inline uint32_t LongSwap(uint32_t v)
278 {
279     return __builtin_bswap32(v);
280 }
281 #elif defined(_MSC_VER)
282 // MSVC
283 
284 // required for _byteswap_ushort/ulong
285 #include <stdlib.h>
286 
ShortSwap(uint16_t v)287 static uint16_t ShortSwap(uint16_t v)
288 {
289     return _byteswap_ushort(v);
290 }
291 
LongSwap(uint32_t v)292 static uint32_t LongSwap(uint32_t v)
293 {
294     return _byteswap_ulong(v);
295 }
296 
297 #else
298 // clang, gcc < 4.3 and others
299 
ShortSwap(uint16_t v)300 static inline uint16_t ShortSwap(uint16_t v)
301 {
302     return (v << 8) | (v >> 8);
303 }
304 
LongSwap(uint32_t v)305 static inline uint32_t LongSwap(uint32_t v)
306 {
307     return ((v & 0x000000FF) << 24) |
308            ((v & 0x0000FF00) << 8)  |
309            ((v & 0x00FF0000) >> 8)  |
310            ((v & 0xFF000000) >> 24);
311 }
312 #endif
313 
CopyShortSwap(void * dest,const void * src)314 static QINLINE void CopyShortSwap( void *dest, const void *src )
315 {
316     *(uint16_t*)dest = ShortSwap(*(uint16_t*)src);
317 }
318 
CopyLongSwap(void * dest,const void * src)319 static QINLINE void CopyLongSwap( void *dest, const void *src )
320 {
321     *(uint32_t*)dest = LongSwap(*(uint32_t*)src);
322 }
323 
FloatSwap(float f)324 static QINLINE float FloatSwap(float f)
325 {
326     float out;
327     CopyLongSwap(&out, &f);
328     return out;
329 }
330 
331 #if defined(Q3_BIG_ENDIAN) && defined(Q3_LITTLE_ENDIAN)
332 	#error "Endianness defined as both big and little"
333 #elif defined(Q3_BIG_ENDIAN)
334 	#define CopyLittleShort( dest, src )	CopyShortSwap( dest, src )
335 	#define CopyLittleLong( dest, src )		CopyLongSwap( dest, src )
336 	#define LittleShort( x )				ShortSwap( x )
337 	#define LittleLong( x )					LongSwap( x )
338 	#define LittleFloat( x )				FloatSwap( x )
339 	#define BigShort
340 	#define BigLong
341 	#define BigFloat
342 #elif defined( Q3_LITTLE_ENDIAN )
343 	#define CopyLittleShort( dest, src )	Com_Memcpy(dest, src, 2)
344 	#define CopyLittleLong( dest, src )		Com_Memcpy(dest, src, 4)
345 	#define LittleShort
346 	#define LittleLong
347 	#define LittleFloat
348 	#define BigShort( x )					ShortSwap( x )
349 	#define BigLong( x )					LongSwap( x )
350 	#define BigFloat( x )					FloatSwap( x )
351 #else
352 	#error "Endianness not defined"
353 #endif
354 
355 typedef unsigned char byte;
356 typedef unsigned short word;
357 typedef unsigned long ulong;
358 
359 typedef enum { qfalse, qtrue } qboolean;
360 
361 // 32 bit field aliasing
362 typedef union byteAlias_u {
363 	float f;
364 	int32_t i;
365 	uint32_t ui;
366 	qboolean qb;
367 	byte b[4];
368 	char c[4];
369 } byteAlias_t;
370 
371 // platform string
372 #if defined(NDEBUG)
373 	#define PLATFORM_STRING OS_STRING "-" ARCH_STRING
374 #else
375 	#define PLATFORM_STRING OS_STRING "-" ARCH_STRING "-debug"
376 #endif
377