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