1 /* ScummVM - Graphic Adventure Engine
2  *
3  * ScummVM is the legal property of its developers, whose names
4  * are too numerous to list here. Please refer to the COPYRIGHT
5  * file distributed with this source distribution.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20  *
21  */
22 
23 #ifndef COMMON_SCUMMSYS_H
24 #define COMMON_SCUMMSYS_H
25 
26 #ifndef __has_feature           // Optional of course.
27 	#define __has_feature(x) 0  // Compatibility with non-clang compilers.
28 #endif
29 
30 // This is a convenience macro to test whether the compiler used is a GCC
31 // version, which is at least major.minor.
32 #ifdef __GNUC__
33 	#define GCC_ATLEAST(major, minor) (__GNUC__ > (major) || (__GNUC__ == (major) && __GNUC_MINOR__ >= (minor)))
34 #else
35 	#define GCC_ATLEAST(major, minor) 0
36 #endif
37 
38 #if defined(NONSTANDARD_PORT)
39 
40 	// Ports which need to perform #includes and #defines visible in
41 	// virtually all the source of ScummVM should do so by providing a
42 	// "portdefs.h" header file (and not by directly modifying this
43 	// header file).
44 	#include <portdefs.h>
45 #else // defined(NONSTANDARD_PORT)
46 
47 	#if defined(WIN32)
48 
49 		#if defined(_MSC_VER) && _MSC_VER <= 1800
50 
51 		// FIXME: The placement of the workaround functions for MSVC below
52 		// require us to include stdio.h and stdarg.h for MSVC here. This
53 		// is not exactly nice...
54 		// We should think of a better way of doing this.
55 		#include <stdio.h>
56 		#include <stdarg.h>
57 
58 		// MSVC's vsnprintf is either non-existent (2003) or bugged since it
59 		// does not always include a terminating NULL (2005+). To work around
60 		// that we fix up the _vsnprintf included. Note that the return value
61 		// will still not match C99's specs!
vsnprintf_msvc(char * str,size_t size,const char * format,va_list args)62 		inline int vsnprintf_msvc(char *str, size_t size, const char *format, va_list args) {
63 			// We do not pass size - 1 here, to ensure we would get the same
64 			// return value as when we would use _vsnprintf directly, since
65 			// for example Common::String::format relies on this.
66 			int retValue = _vsnprintf(str, size, format, args);
67 			str[size - 1] = 0;
68 			return retValue;
69 		}
70 
71 		#define vsnprintf vsnprintf_msvc
72 
73 		// Visual Studio does not include snprintf in its standard C library.
74 		// Instead it includes a function called _snprintf with somewhat
75 		// similar semantics. The minor difference is that the return value in
76 		// case the formatted string exceeds the buffer size is different.
77 		// A much more dangerous one is that _snprintf does not always include
78 		// a terminating null (Whoops!). Instead we map to our fixed vsnprintf.
snprintf(char * str,size_t size,const char * format,...)79 		inline int snprintf(char *str, size_t size, const char *format, ...) {
80 			va_list args;
81 			va_start(args, format);
82 			int len = vsnprintf(str, size, format, args);
83 			va_end(args);
84 			return len;
85 		}
86 		#endif
87 
88 		#define WIN32_LEAN_AND_MEAN		// Exclude rarely-used stuff from Windows headers
89 		#define NOGDICAPMASKS
90 		#define OEMRESOURCE
91 		#define NONLS
92 		#define NOICONS
93 		#define NOMCX
94 		#define NOPROFILER
95 		#define NOKANJI
96 		#define NOSERVICE
97 		#define NOMETAFILE
98 		#define NOCOMM
99 		#define NOCRYPT
100 		#define NOIME
101 		#define NOATOM
102 		#define NOCTLMGR
103 		#define NOCLIPBOARD
104 		#define NOMEMMGR
105 		#define NOSYSMETRICS
106 		#define NOMENUS
107 		#define NOOPENFILE
108 		#define NOWH
109 		#define NOSOUND
110 		#define NODRAWTEXT
111 
112 	#endif
113 
114 	#if defined(__QNXNTO__)
115 	#include <strings.h>	/* For strcasecmp */
116 	#endif
117 
118 	#include <stdio.h>
119 	#include <stdlib.h>
120 	#include <string.h>
121 	#include <stdarg.h>
122 	#include <stddef.h>
123 	#include <assert.h>
124 	#include <ctype.h>
125 	// MSVC does not define M_PI, M_SQRT2 and other math defines by default.
126 	// _USE_MATH_DEFINES must be defined in order to have these defined, thus
127 	// we enable it here. For more information, check:
128 	// http://msdn.microsoft.com/en-us/library/4hwaceh6(v=VS.100).aspx
129 	#define _USE_MATH_DEFINES
130 	#include <math.h>
131 
132 	// FIXME: We sadly can't assume standard C++ headers to be present on every
133 	// system we support, so we should get rid of this. The solution should be to
134 	// write a simple placement new on our own. It might be noteworthy we can't
135 	// easily do that for systems which do have a <new>, since it might clash with
136 	// the default definition otherwise!
137 	// Symbian does not have <new> but the new operator
138 	#if !defined(__SYMBIAN32__)
139 	#include <new>
140 	#endif
141 #endif
142 
143 #ifndef STATIC_ASSERT
144 #if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER > 1600)
145 	/**
146 	 * Generates a compile-time assertion.
147 	 *
148 	 * @param expression An expression that can be evaluated at compile time.
149 	 * @param message An underscore-delimited message to be presented at compile
150 	 * time if the expression evaluates to false.
151 	 */
152 	#define STATIC_ASSERT(expression, message) \
153 		static_assert((expression), #message)
154 #else
155 	/**
156 	 * Generates a compile-time assertion.
157 	 *
158 	 * @param expression An expression that can be evaluated at compile time.
159 	 * @param message An underscore-delimited message to be presented at compile
160 	 * time if the expression evaluates to false.
161 	 */
162 	#define STATIC_ASSERT(expression, message) \
163 		do { \
164 			extern int STATIC_ASSERT_##message[(expression) ? 1 : -1]; \
165 			(void)(STATIC_ASSERT_##message); \
166 		} while (false)
167 #endif
168 #endif
169 
170 // The following math constants are usually defined by the system math.h header, but
171 // they are not part of the ANSI C++ standards and so can NOT be relied upon to be
172 // present i.e. when -std=c++11 is passed to GCC, enabling strict ANSI compliance.
173 // As we rely on these being present, we define them if they are not set.
174 
175 #ifndef M_E
176 	#define M_E 2.7182818284590452354 /* e */
177 #endif
178 
179 #ifndef M_LOG2E
180 	#define M_LOG2E 1.4426950408889634074 /* log_2 e */
181 #endif
182 
183 #ifndef M_LOG10E
184 	#define M_LOG10E 0.43429448190325182765 /* log_10 e */
185 #endif
186 
187 #ifndef M_LN2
188 	#define M_LN2 0.69314718055994530942 /* log_e 2 */
189 #endif
190 
191 #ifndef M_LN10
192 	#define M_LN10 2.30258509299404568402 /* log_e 10 */
193 #endif
194 
195 #ifndef M_PI
196 	#define M_PI 3.14159265358979323846 /* pi */
197 #endif
198 
199 #ifndef M_PI_2
200 	#define M_PI_2 1.57079632679489661923 /* pi/2 */
201 #endif
202 
203 #ifndef M_PI_4
204 	#define M_PI_4 0.78539816339744830962 /* pi/4 */
205 #endif
206 
207 #ifndef M_1_PI
208 	#define M_1_PI 0.31830988618379067154 /* 1/pi */
209 #endif
210 
211 #ifndef M_2_PI
212 	#define M_2_PI 0.63661977236758134308 /* 2/pi */
213 #endif
214 
215 #ifndef M_2_SQRTPI
216 	#define M_2_SQRTPI 1.12837916709551257390 /* 2/sqrt(pi) */
217 #endif
218 
219 #ifndef M_SQRT2
220 	#define M_SQRT2 1.41421356237309504880 /* sqrt(2) */
221 #endif
222 
223 #ifndef M_SQRT1_2
224 	#define M_SQRT1_2 0.70710678118654752440 /* 1/sqrt(2) */
225 #endif
226 
227 // Include our C++11 compatability header for pre-C++11 compilers.
228 #if __cplusplus < 201103L
229 #include "common/c++11-compat.h"
230 #endif
231 
232 // Use config.h, generated by configure
233 #if defined(HAVE_CONFIG_H)
234 #include "config.h"
235 #endif
236 
237 
238 // In the following we configure various targets, in particular those
239 // which can't use our "configure" tool and hence don't use config.h.
240 //
241 // Some #defines that occur here frequently:
242 // SCUMM_LITTLE_ENDIAN
243 //    - Define this on a little endian target
244 // SCUMM_BIG_ENDIAN
245 //    - Define this on a big endian target
246 // SCUMM_NEED_ALIGNMENT
247 //    - Define this if your system has problems reading e.g. an int32 from an odd address
248 // SMALL_SCREEN_DEVICE
249 //    - ...
250 // ...
251 
252 
253 //
254 // By default we try to use pragma push/pop to ensure various structs we use
255 // are "packed". If your compiler doesn't support this pragma, you are in for
256 // a problem. If you are lucky, there is a compiler switch, or another pragma,
257 // doing the same thing -- in that case, try to modify common/pack-begin.h and
258 // common/pack-end.h accordingly. Or maybe your port simply *always* packs
259 // everything, in which case you could #undefine SCUMMVM_USE_PRAGMA_PACK.
260 //
261 // If neither is possible, tough luck. Try to contact the team, maybe we can
262 // come up with a solution, though I wouldn't hold my breath on it :-/.
263 //
264 #define SCUMMVM_USE_PRAGMA_PACK
265 
266 //
267 // Determine the host endianess and whether memory alignment is required.
268 //
269 #if !defined(HAVE_CONFIG_H)
270 
271 	#if defined(__DC__) || \
272 		  defined(__DS__) || \
273 		  defined(__3DS__) || \
274 		  defined(IPHONE) || \
275 		  defined(__PLAYSTATION2__) || \
276 		  defined(__PSP__) || \
277 		  defined(__SYMBIAN32__) || \
278 		  defined(__LIBRETRO__)
279 
280 #if defined(WIIU) || defined(__CELLOS_LV2__) || defined(GEKKO)
281 		#undef  SCUMM_LITTLE_ENDIAN
282 		#define SCUMM_BIG_ENDIAN
283 		#define SCUMM_NEED_ALIGNMENT
284 #else
285 		#define SCUMM_LITTLE_ENDIAN
286 		#define SCUMM_NEED_ALIGNMENT
287 #endif
288 	#elif defined(_WIN32_WCE) || defined(_MSC_VER) || defined(__MINGW32__)
289 
290 		#define SCUMM_LITTLE_ENDIAN
291 
292 	#elif defined(__amigaos4__) || defined(__N64__) || defined(__WII__)
293 
294 		#define SCUMM_BIG_ENDIAN
295 		#define SCUMM_NEED_ALIGNMENT
296 
297 	#elif defined(SDL_BACKEND)
298 		// On SDL based ports, we try to use SDL_BYTEORDER to determine the
299 		// endianess. We explicitly do this as the *last* thing we try, so that
300 		// platform specific settings have precedence.
301 		#include <SDL_endian.h>
302 
303 		#if SDL_BYTEORDER == SDL_LIL_ENDIAN
304 		#define SCUMM_LITTLE_ENDIAN
305 		#elif SDL_BYTEORDER == SDL_BIG_ENDIAN
306 		#define SCUMM_BIG_ENDIAN
307 		#else
308 		#error Neither SDL_BIG_ENDIAN nor SDL_LIL_ENDIAN is set.
309 		#endif
310 
311 	#else
312 
313 		#error No system type defined, host endianess unknown.
314 
315 	#endif
316 #endif
317 
318 //
319 // Some more system specific settings.
320 // TODO/FIXME: All of these should be moved to backend specific files (such as portdefs.h)
321 //
322 #if defined(DINGUX)
323 
324 	// Very BAD hack following, used to avoid triggering an assert in uClibc dingux library
325 	// "toupper" when pressing keyboard function keys.
326 	#undef toupper
327 	#define toupper(c) (((c & 0xFF) >= 97) && ((c & 0xFF) <= 122) ? ((c & 0xFF) - 32) : (c & 0xFF))
328 
329 #elif defined(__PSP__)
330 
331 	#include <malloc.h>
332 	#include "backends/platform/psp/memory.h"
333 
334 	/* to make an efficient, inlined memcpy implementation */
335 	#define memcpy(dst, src, size)   psp_memcpy(dst, src, size)
336 
337 #endif
338 
339 #if defined(USE_TREMOR) && !defined(USE_VORBIS)
340 #define USE_VORBIS // make sure this one is defined together with USE_TREMOR!
341 #endif
342 
343 //
344 // Fallbacks / default values for various special macros
345 //
346 #ifndef GCC_PRINTF
347 	#if defined(__GNUC__) || defined(__INTEL_COMPILER)
348 		#define GCC_PRINTF(x,y) __attribute__((__format__(__printf__, x, y)))
349 	#else
350 		#define GCC_PRINTF(x,y)
351 	#endif
352 #endif
353 
354 #ifndef PACKED_STRUCT
355 	#if defined(__GNUC__) || defined(__INTEL_COMPILER)
356 		#define PACKED_STRUCT __attribute__((__packed__))
357 	#else
358 		#define PACKED_STRUCT
359 	#endif
360 #endif
361 
362 #ifndef FORCEINLINE
363 	#if defined(_MSC_VER)
364 		#define FORCEINLINE __forceinline
365 	#elif GCC_ATLEAST(3, 1)
366 		#define FORCEINLINE inline __attribute__((__always_inline__))
367 	#else
368 		#define FORCEINLINE inline
369 	#endif
370 #endif
371 
372 #ifndef PLUGIN_EXPORT
373 	#if defined(_MSC_VER) || defined(_WIN32_WCE) || defined(__MINGW32__)
374 		#define PLUGIN_EXPORT __declspec(dllexport)
375 	#else
376 		#define PLUGIN_EXPORT
377 	#endif
378 #endif
379 
380 #ifndef NORETURN_PRE
381 	#if defined(_MSC_VER)
382 		#define NORETURN_PRE __declspec(noreturn)
383 	#else
384 		#define NORETURN_PRE
385 	#endif
386 #endif
387 
388 #ifndef NORETURN_POST
389 	#if defined(__GNUC__) || defined(__INTEL_COMPILER)
390 		#define NORETURN_POST __attribute__((__noreturn__))
391 	#else
392 		#define NORETURN_POST
393 	#endif
394 #endif
395 
396 #ifndef WARN_UNUSED_RESULT
397 	#if __cplusplus >= 201703L
398 		#define WARN_UNUSED_RESULT [[nodiscard]]
399 	#elif GCC_ATLEAST(3, 4)
400 		#define WARN_UNUSED_RESULT __attribute__((__warn_unused_result__))
401 	#elif defined(_Check_return_)
402 		#define WARN_UNUSED_RESULT _Check_return_
403 	#else
404 		#define WARN_UNUSED_RESULT
405 	#endif
406 #endif
407 
408 #ifndef STRINGBUFLEN
409 	#if defined(__N64__) || defined(__DS__) || defined(__3DS__)
410 		#define STRINGBUFLEN 256
411 	#else
412 		#define STRINGBUFLEN 1024
413 	#endif
414 #endif
415 
416 #ifndef MAXPATHLEN
417 #define MAXPATHLEN 256
418 #endif
419 
420 #ifndef scumm_va_copy
421 	#if defined(va_copy)
422 		#define scumm_va_copy va_copy
423 	#elif defined(__va_copy)
424 		#define scumm_va_copy __va_copy
425 	#elif defined(_MSC_VER) || defined(__SYMBIAN32__)
426 		#define scumm_va_copy(dst, src)       ((dst) = (src))
427 	#else
428 		#error scumm_va_copy undefined for this port
429 	#endif
430 #endif
431 
432 
433 
434 //
435 // Typedef our system types unless they have already been defined by config.h,
436 // or SCUMMVM_DONT_DEFINE_TYPES is set.
437 //
438 #if !defined(HAVE_CONFIG_H) && !defined(SCUMMVM_DONT_DEFINE_TYPES)
439 	typedef unsigned char byte;
440 	typedef unsigned char uint8;
441 	typedef signed char int8;
442 	typedef unsigned short uint16;
443 	typedef signed short int16;
444 	typedef unsigned int uint32;
445 	typedef signed int int32;
446 	typedef unsigned int uint;
447 	#ifdef __PLAYSTATION2__
448 	typedef signed long int64;
449 	typedef unsigned long uint64;
450 	#else
451 	typedef signed long long int64;
452 	typedef unsigned long long uint64;
453 	#endif
454 #endif
455 
456 //
457 // Determine 64 bitness
458 // Reference: http://nadeausoftware.com/articles/2012/02/c_c_tip_how_detect_processor_type_using_compiler_predefined_macros
459 //
460 #if !defined(HAVE_CONFIG_H)
461 
462 #if defined(__x86_64__) || \
463 		  defined(_M_X64) || \
464 		  defined(__ppc64__) || \
465 		  defined(__powerpc64__) || \
466 		  defined(__LP64__)
467 
468 typedef uint64 uintptr;
469 
470 #else
471 
472 typedef uint32 uintptr;
473 
474 #endif
475 
476 #endif
477 
478 #include "common/forbidden.h"
479 
480 #endif
481