ScummVM API documentation
scummsys.h
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 modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation, either version 3 of the License, or
10  * (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, see <http://www.gnu.org/licenses/>.
19  *
20  */
21 
22 #ifndef COMMON_SCUMMSYS_H
23 #define COMMON_SCUMMSYS_H
24 
25 #ifndef __has_feature // Optional of course.
26  #define __has_feature(x) 0 // Compatibility with non-clang compilers.
27 #endif
28 
29 // This is a convenience macro to test whether the compiler used is a GCC
30 // version, which is at least major.minor. Note that Clang will also define
31 // it and report itself as GCC 4.2.1.
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(_MSC_VER) && _MSC_VER < 1900
39  #error MSVC support requires MSVC 2015 or newer
40 #endif
41 
42 #if defined(NONSTANDARD_PORT)
43 
44  // Ports which need to perform #includes and #defines visible in
45  // virtually all the source of ScummVM should do so by providing a
46  // "portdefs.h" header file (and not by directly modifying this
47  // header file).
48  #include <portdefs.h>
49 #else // defined(NONSTANDARD_PORT)
50 
51  #if defined(WIN32)
52 
53  #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
54  #define NOGDICAPMASKS
55  #define OEMRESOURCE
56  #define NONLS
57  #define NOICONS
58  #define NOMCX
59  #define NOPROFILER
60  #define NOKANJI
61  #define NOSERVICE
62  #define NOMETAFILE
63  #define NOCOMM
64  #define NOCRYPT
65  #define NOIME
66  #define NOATOM
67  #define NOCTLMGR
68  #define NOCLIPBOARD
69  #define NOMEMMGR
70  #define NOSYSMETRICS
71  #define NOMENUS
72  #define NOOPENFILE
73  #define NOWH
74  #define NOSOUND
75  #define NODRAWTEXT
76  #define NOMINMAX 1
77 
78  #endif
79 
80  #if defined(__QNXNTO__)
81  #include <strings.h> /* For strcasecmp */
82  #endif
83 
84  #include <stdio.h>
85  #include <stdlib.h>
86  #include <string.h>
87  #include <stdarg.h>
88  #include <stddef.h>
89  #include <assert.h>
90  #include <ctype.h>
91 
92  // In C99, the following macros were necessary to get some <inttypes.h>
93  // features we want. The C++11 standard removed this requirement, but in
94  // practice, some systems (such as RISC OS or macOS < 10.7) are not fully
95  // compliant, and still require the old defines.
96  #define __STDC_CONSTANT_MACROS
97  #define __STDC_FORMAT_MACROS
98  #define __STDC_LIMIT_MACROS
99  #include <inttypes.h>
100 
101  // macOS 10.4 inttypes.h woes -- fixed in 10.5 SDK
102  #if defined(MACOSX) && defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1050
103  #undef __PRI_8_LENGTH_MODIFIER__
104  #undef __PRI_64_LENGTH_MODIFIER__
105  #undef __SCN_64_LENGTH_MODIFIER__
106  #define __PRI_8_LENGTH_MODIFIER__ "hh"
107  #define __PRI_64_LENGTH_MODIFIER__ "ll"
108  #define __SCN_64_LENGTH_MODIFIER__ "ll"
109  #endif
110 
111  #include <limits.h>
112 
113  // MSVC does not define M_PI, M_SQRT2 and other math defines by default.
114  // _USE_MATH_DEFINES must be defined in order to have these defined, thus
115  // we enable it here. For more information, check:
116  // https://docs.microsoft.com/en-us/cpp/c-runtime-library/math-constants
117  #define _USE_MATH_DEFINES
118  #include <math.h>
119 
120  // FIXME: We sadly can't assume standard C++ headers to be present on every
121  // system we support, so we should get rid of this. The solution should be to
122  // write a simple placement new on our own. It might be noteworthy we can't
123  // easily do that for systems which do have a <new>, since it might clash with
124  // the default definition otherwise!
125  #include <new>
126 
127  // After having discussion about use of std::numeric_limits in
128  // https://github.com/scummvm/scummvm/pull/3966 we concluded that it is safe to
129  // use it as minimal STL code with low probability to bring any incompatibilities
130  #include <limits>
131 #endif
132 
133 #ifndef STATIC_ASSERT
134 #if __cplusplus >= 201103L || defined(_MSC_VER)
135 
142  #define STATIC_ASSERT(expression, message) \
143  static_assert((expression), #message)
144 #else
145 
152  #define STATIC_ASSERT(expression, message) \
153  do { \
154  extern int STATIC_ASSERT_##message[(expression) ? 1 : -1]; \
155  (void)(STATIC_ASSERT_##message); \
156  } while (false)
157 #endif
158 #endif
159 
160 // The following math constants are usually defined by the system math.h header, but
161 // they are not part of the ANSI C++ standards and so can NOT be relied upon to be
162 // present i.e. when -std=c++11 is passed to GCC, enabling strict ANSI compliance.
163 // As we rely on these being present, we define them if they are not set.
164 
165 #ifndef M_E
166  #define M_E 2.7182818284590452354 /* e */
167 #endif
168 
169 #ifndef M_LOG2E
170  #define M_LOG2E 1.4426950408889634074 /* log_2 e */
171 #endif
172 
173 #ifndef M_LOG10E
174  #define M_LOG10E 0.43429448190325182765 /* log_10 e */
175 #endif
176 
177 #ifndef M_LN2
178  #define M_LN2 0.69314718055994530942 /* log_e 2 */
179 #endif
180 
181 #ifndef M_LN10
182  #define M_LN10 2.30258509299404568402 /* log_e 10 */
183 #endif
184 
185 #ifndef M_PI
186  #define M_PI 3.14159265358979323846 /* pi */
187 #endif
188 
189 #ifndef M_PI_2
190  #define M_PI_2 1.57079632679489661923 /* pi/2 */
191 #endif
192 
193 #ifndef M_PI_4
194  #define M_PI_4 0.78539816339744830962 /* pi/4 */
195 #endif
196 
197 #ifndef M_1_PI
198  #define M_1_PI 0.31830988618379067154 /* 1/pi */
199 #endif
200 
201 #ifndef M_2_PI
202  #define M_2_PI 0.63661977236758134308 /* 2/pi */
203 #endif
204 
205 #ifndef M_2_SQRTPI
206  #define M_2_SQRTPI 1.12837916709551257390 /* 2/sqrt(pi) */
207 #endif
208 
209 #ifndef M_SQRT2
210  #define M_SQRT2 1.41421356237309504880 /* sqrt(2) */
211 #endif
212 
213 #ifndef M_SQRT1_2
214  #define M_SQRT1_2 0.70710678118654752440 /* 1/sqrt(2) */
215 #endif
216 
217 // Use config.h, generated by configure
218 #if defined(HAVE_CONFIG_H)
219 #include "config.h"
220 #endif
221 
222 
223 // In the following we configure various targets, in particular those
224 // which can't use our "configure" tool and hence don't use config.h.
225 //
226 // Some #defines that occur here frequently:
227 // SCUMM_LITTLE_ENDIAN
228 // - Define this on a little endian target
229 // SCUMM_BIG_ENDIAN
230 // - Define this on a big endian target
231 // SCUMM_NEED_ALIGNMENT
232 // - Define this if your system has problems reading e.g. an int32 from an odd address
233 // SMALL_SCREEN_DEVICE
234 // - ...
235 // ...
236 
237 //
238 // If -fsanitize=alignment is in use (or UBSan enabled it), and the compiler
239 // happens to report it, make sure SCUMM_NEED_ALIGNMENT is defined, in order
240 // to avoid false positives. `alignment_sanitizer` may not be reported in
241 // earlier releases though, so look for the UBSan flag in that case.
242 //
243 #if __has_feature(alignment_sanitizer) || __has_feature(undefined_behavior_sanitizer)
244  #define SCUMM_NEED_ALIGNMENT
245 #endif
246 
247 //
248 // By default we try to use pragma push/pop to ensure various structs we use
249 // are "packed". If your compiler doesn't support this pragma, you are in for
250 // a problem. If you are lucky, there is a compiler switch, or another pragma,
251 // doing the same thing -- in that case, try to modify common/pack-begin.h and
252 // common/pack-end.h accordingly. Or maybe your port simply *always* packs
253 // everything, in which case you could #undefine SCUMMVM_USE_PRAGMA_PACK.
254 //
255 // If neither is possible, tough luck. Try to contact the team, maybe we can
256 // come up with a solution, though I wouldn't hold my breath on it :-/.
257 //
258 #define SCUMMVM_USE_PRAGMA_PACK
259 
260 //
261 // Determine the host endianess and whether memory alignment is required.
262 //
263 #if !defined(HAVE_CONFIG_H)
264 
265  #if defined(__DC__) || \
266  defined(__DS__) || \
267  defined(__3DS__) || \
268  defined(IPHONE) || \
269  defined(__PSP__)
270 
271  #define SCUMM_LITTLE_ENDIAN
272  #define SCUMM_NEED_ALIGNMENT
273 
274  #elif defined(_MSC_VER) || defined(__MINGW32__)
275 
276  #define SCUMM_LITTLE_ENDIAN
277 
278  #elif defined(__MORPHOS__) || defined(__amigaos4__) || defined(__N64__) || defined(__WII__)
279 
280  #define SCUMM_BIG_ENDIAN
281  #define SCUMM_NEED_ALIGNMENT
282 
283  #elif defined(SDL_BACKEND)
284  // On SDL based ports, we try to use SDL_BYTEORDER to determine the
285  // endianess. We explicitly do this as the *last* thing we try, so that
286  // platform specific settings have precedence.
287  #include <SDL_endian.h>
288 
289  #if SDL_BYTEORDER == SDL_LIL_ENDIAN
290  #define SCUMM_LITTLE_ENDIAN
291  #elif SDL_BYTEORDER == SDL_BIG_ENDIAN
292  #define SCUMM_BIG_ENDIAN
293  #else
294  #error Neither SDL_BIG_ENDIAN nor SDL_LIL_ENDIAN is set.
295  #endif
296 
297  #else
298 
299  #error No system type defined, host endianess unknown.
300 
301  #endif
302 #endif
303 
304 #if !defined(SCUMM_FLOAT_WORD_LITTLE_ENDIAN) && !defined(SCUMM_FLOAT_WORD_BIG_ENDIAN)
305 
306  #if defined(__ORDER_LITTLE_ENDIAN__) && defined(__ORDER_BIG_ENDIAN__) && defined(__FLOAT_WORD_ORDER__)
307 
308  #if (__FLOAT_WORD_ORDER__ == __ORDER_LITTLE_ENDIAN__)
309  #define SCUMM_FLOAT_WORD_LITTLE_ENDIAN
310  #elif (__FLOAT_WORD_ORDER__ == __ORDER_BIG_ENDIAN__)
311  #define SCUMM_FLOAT_WORD_BIG_ENDIAN
312  #else
313  #error Unsupported endianness
314  #endif
315 
316  #else
317  #ifdef SCUMM_LITTLE_ENDIAN
318  #define SCUMM_FLOAT_WORD_LITTLE_ENDIAN
319  #else
320  #define SCUMM_FLOAT_WORD_BIG_ENDIAN
321  #endif
322 
323  #endif
324 #endif
325 
326 #if defined(USE_TREMOR) && !defined(USE_VORBIS)
327 #define USE_VORBIS // make sure this one is defined together with USE_TREMOR!
328 #endif
329 
330 //
331 // Fallbacks / default values for various special macros
332 //
333 #ifndef GCC_PRINTF
334  #if defined(__GNUC__) || defined(__INTEL_COMPILER)
335  #if defined(__USE_MINGW_ANSI_STDIO) && __USE_MINGW_ANSI_STDIO && !defined(__clang__)
336  #define GCC_PRINTF(x,y) __attribute__((__format__(__gnu_printf__, x, y)))
337  #else
338  #define GCC_PRINTF(x,y) __attribute__((__format__(__printf__, x, y)))
339  #endif
340  #else
341  #define GCC_PRINTF(x,y)
342  #endif
343 #endif
344 
345 #ifndef MSVC_PRINTF
346  #if defined(_MSC_VER)
347  #define MSVC_PRINTF _Printf_format_string_
348  #else
349  #define MSVC_PRINTF
350  #endif
351 #endif
352 
353 #ifndef PACKED_STRUCT
354  #if defined(__GNUC__) || defined(__INTEL_COMPILER)
355  #define PACKED_STRUCT __attribute__((__packed__))
356  #else
357  #define PACKED_STRUCT
358  #endif
359 #endif
360 
361 #ifndef FORCEINLINE
362  #if defined(_MSC_VER)
363  #define FORCEINLINE __forceinline
364  #elif defined(__GNUC__)
365  #define FORCEINLINE inline __attribute__((__always_inline__))
366  #else
367  #define FORCEINLINE inline
368  #endif
369 #endif
370 
371 #ifndef PLUGIN_EXPORT
372  #if defined(_MSC_VER) || defined(__MINGW32__)
373  #define PLUGIN_EXPORT __declspec(dllexport)
374  #else
375  #define PLUGIN_EXPORT
376  #endif
377 #endif
378 
379 #ifndef NORETURN_PRE
380  #if defined(_MSC_VER)
381  #define NORETURN_PRE __declspec(noreturn)
382  #elif defined(__GNUC__)
383  #define NORETURN_PRE __attribute__((__noreturn__))
384  #else
385  #define NORETURN_PRE
386  #endif
387 #endif
388 
389 #ifndef NORETURN_POST
390  #if defined(__INTEL_COMPILER)
391  #define NORETURN_POST __attribute__((__noreturn__))
392  #else
393  #define NORETURN_POST
394  #endif
395 #endif
396 
397 #ifndef WARN_UNUSED_RESULT
398  #if __cplusplus >= 201703L
399  #define WARN_UNUSED_RESULT [[nodiscard]]
400  #elif defined(__GNUC__)
401  #define WARN_UNUSED_RESULT __attribute__((__warn_unused_result__))
402  #elif defined(_Check_return_)
403  #define WARN_UNUSED_RESULT _Check_return_
404  #else
405  #define WARN_UNUSED_RESULT
406  #endif
407 #endif
408 
409 #ifndef WARN_DEPRECATED
410  #if __cplusplus >= 201703L
411  #define WARN_DEPRECATED(msg) [[deprecated(msg)]]
412  #elif defined(__GNUC__)
413  #define WARN_DEPRECATED(msg) __attribute__((__deprecated__(msg)))
414  #elif defined(_MSC_VER)
415  #define WARN_DEPRECATED(msg) __declspec(deprecated(msg))
416  #else
417  #define WARN_DEPRECATED(msg)
418  #endif
419 #endif
420 
421 #ifndef STRINGBUFLEN
422  #if defined(__N64__) || defined(__DS__) || defined(__3DS__)
423  #define STRINGBUFLEN 256
424  #else
425  #define STRINGBUFLEN 1024
426  #endif
427 #endif
428 
429 #ifndef MAXPATHLEN
430 #define MAXPATHLEN 256
431 #endif
432 
433 #ifndef scumm_va_copy
434  #if defined(va_copy)
435  #define scumm_va_copy va_copy
436  #elif defined(__va_copy)
437  #define scumm_va_copy __va_copy
438  #elif defined(_MSC_VER)
439  #define scumm_va_copy(dst, src) ((dst) = (src))
440  #else
441  #error scumm_va_copy undefined for this port
442  #endif
443 #endif
444 
445 
446 
447 //
448 // Typedef our system types unless SCUMMVM_DONT_DEFINE_TYPES is set.
449 // This is usually due to conflicts with the system headers.
450 //
451 #ifndef SCUMMVM_DONT_DEFINE_TYPES
452  typedef unsigned char byte;
453  typedef unsigned int uint;
454 
455  typedef uint8_t uint8;
456  typedef int8_t int8;
457  typedef uint16_t uint16;
458  typedef int16_t int16;
459 #if defined(__3DS__) || defined(__DC__) || defined(__PSP__)
460 
464  typedef unsigned int uint32;
465  typedef int int32;
466 #elif defined(__amigaos4__) || defined(__MORPHOS__)
467 
472  typedef unsigned long uint32;
473  typedef signed long int32;
474 #else
475  typedef uint32_t uint32;
476  typedef int32_t int32;
477 #endif
478  typedef uint64_t uint64;
479  typedef int64_t int64;
480  typedef uintptr_t uintptr;
481  typedef intptr_t intptr;
482 #endif
483 
484 //
485 // std::nullptr_t when unavailable (e.g. the compiler supports C++11,
486 // but the standard library is older and has incomplete C++11 support)
487 //
488 #if defined(NO_CXX11_NULLPTR_T)
489 namespace std {
490  typedef decltype(nullptr) nullptr_t;
491 }
492 #endif
493 
494 //
495 // std::initializer_list when unavailable (e.g. the compiler supports C++11,
496 // but the standard library is older and has incomplete C++11 support)
497 //
498 #if defined(NO_CXX11_INITIALIZER_LIST)
499 namespace std {
500  template<class T> class initializer_list {
501  public:
502  typedef T value_type;
503  typedef const T &reference;
504  typedef const T &const_reference;
505  typedef size_t size_type;
506  typedef const T *iterator;
507  typedef const T *const_iterator;
508 
509  constexpr initializer_list() noexcept = default;
510  constexpr size_t size() const noexcept { return _size; };
511  constexpr const T *begin() const noexcept { return _begin; };
512  constexpr const T *end() const noexcept { return _begin + _size; }
513 
514  private:
515  // Note: begin has to be first or the compiler may get very upset
516  const T *_begin = { nullptr };
517  size_t _size = { 0 };
518 
519  // The compiler is allowed to call this constructor
520  constexpr initializer_list(const T* t, size_t s) noexcept : _begin(t) , _size(s) {}
521  };
522 
523  template<class T> constexpr const T* begin(initializer_list<T> il) noexcept {
524  return il.begin();
525  }
526 
527  template<class T> constexpr const T* end(initializer_list<T> il) noexcept {
528  return il.end();
529  }
530 }
531 
532 #else
533 
534 #include <initializer_list>
535 
536 #endif // NO_CXX11_INITIALIZER_LIST
537 
538 //
539 // Some more system specific settings.
540 // TODO/FIXME: All of these should be moved to backend specific files (such as portdefs.h)
541 //
542 #if defined(DINGUX)
543 
544  // Very BAD hack following, used to avoid triggering an assert in uClibc dingux library
545  // "toupper" when pressing keyboard function keys.
546  #undef toupper
547  #define toupper(c) __extension__ ({ auto _x = ((c) & 0xFF); (_x >= 97 && _x <= 122) ? (_x - 32) : _x; })
548 
549 #elif defined(__PSP__)
550 
551  #include <malloc.h>
552  #include "backends/platform/psp/memory.h"
553 
554  /* to make an efficient, inlined memcpy implementation */
555  #define memcpy(dst, src, size) psp_memcpy(dst, src, size)
556 
557 #endif
558 
559 #include "common/forbidden.h"
560 
561 #endif
Definition: algorithm.h:37