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