//----------------------------------------------------------------------------- // Copyright (c) 2012 GarageGames, LLC // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to // deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS // IN THE SOFTWARE. //----------------------------------------------------------------------------- #ifndef _PLATFORM_H_ #define _PLATFORM_H_ #include #ifndef _TORQUECONFIG_H_ #include "torqueConfig.h" #endif #ifndef _TORQUE_TYPES_H_ #include "platform/types.h" #endif #ifndef _PLATFORMASSERT_H_ #include "platform/platformAssert.h" #endif #ifndef _MSGBOX_H_ #include "platform/nativeDialogs/msgBox.h" #endif #ifndef _VERSION_H_ #include "app/version.h" #endif #ifndef _TORQUE_STRING_H_ #include "core/util/str.h" #endif #ifndef _TORQUE_SAFEDELETE_H_ #include "core/util/safeDelete.h" #endif #include #include /// Global processor identifiers. /// /// @note These enums must be globally scoped so that they work with the inline assembly enum ProcessorType { CPU_X86Compatible, CPU_ArmCompatible, CPU_Intel, CPU_AMD, CPU_Apple }; /// Properties for CPU. enum ProcessorProperties { CPU_PROP_C = (1<<0), ///< We should use C fallback math functions. CPU_PROP_FPU = (1<<1), ///< Has an FPU. (It better!) CPU_PROP_MMX = (1<<2), ///< Supports MMX instruction set extension. CPU_PROP_SSE = (1<<3), ///< Supports SSE instruction set extension. CPU_PROP_SSE2 = (1<<4), ///< Supports SSE2 instruction set extension. CPU_PROP_SSE3 = (1<<5), ///< Supports SSE3 instruction set extension. CPU_PROP_SSE3ex = (1<<6), ///< Supports Supplemental SSE3 instruction set CPU_PROP_SSE4_1 = (1<<7), ///< Supports SSE4_1 instruction set extension. CPU_PROP_SSE4_2 = (1<<8), ///< Supports SSE4_2 instruction set extension. CPU_PROP_AVX = (1<<9), ///< Supports AVX256 instruction set extension. CPU_PROP_MP = (1<<10), ///< This is a multi-processor system. CPU_PROP_LE = (1<<11), ///< This processor is LITTLE ENDIAN. CPU_PROP_64bit = (1<<12), ///< This processor is 64-bit capable CPU_PROP_NEON = (1<<13), ///< Supports the Arm Neon instruction set extension. }; /// Processor info manager. struct Processor { /// Gather processor state information. static void init(); }; #if defined(TORQUE_SUPPORTS_GCC_INLINE_X86_ASM) #define TORQUE_DEBUGBREAK() { asm ( "int 3"); } #elif defined (TORQUE_SUPPORTS_VC_INLINE_X86_ASM) // put this test second so that the __asm syntax doesn't break the Visual Studio Intellisense parser #define TORQUE_DEBUGBREAK() { __asm { int 3 }; } #else /// Macro to do in-line debug breaks, used for asserts. Does inline assembly when possible. #define TORQUE_DEBUGBREAK() Platform::debugBreak(); #endif /// Physical type of a drive. enum DriveType { DRIVETYPE_FIXED = 0, ///< Non-removable fixed drive. DRIVETYPE_REMOVABLE = 1, ///< Removable drive. DRIVETYPE_REMOTE = 2, ///< Networked/remote drive. DRIVETYPE_CDROM = 3, ///< CD-Rom. DRIVETYPE_RAMDISK = 4, ///< A ramdisk! DRIVETYPE_UNKNOWN = 5 ///< Don't know. }; // Some forward declares for later. class Point2I; template class Vector; template class Signal; struct InputEventInfo; namespace Platform { // Time struct LocalTime { U8 sec; ///< Seconds after minute (0-59) U8 min; ///< Minutes after hour (0-59) U8 hour; ///< Hours after midnight (0-23) U8 month; ///< Month (0-11; 0=january) U8 monthday; ///< Day of the month (1-31) U8 weekday; ///< Day of the week (0-6, 6=sunday) U16 year; ///< Current year minus 1900 U16 yearday; ///< Day of year (0-365) bool isdst; ///< True if daylight savings time is active }; enum ALERT_ASSERT_RESULT { ALERT_ASSERT_DEBUG, ALERT_ASSERT_IGNORE, ALERT_ASSERT_IGNORE_ALL, ALERT_ASSERT_EXIT }; void getLocalTime(LocalTime &); /// Converts the local time to a formatted string appropriate /// for the current platform. String localTimeToString( const LocalTime < ); U32 getTime(); U32 getVirtualMilliseconds(); /// Returns the milliseconds since the system was started. You should /// not depend on this for high precision timing. /// @see PlatformTimer U32 getRealMilliseconds(); void advanceTime(U32 delta); S32 getBackgroundSleepTime(); // Platform control void init(); void initConsole(); void shutdown(); void process(); // Math control state U32 getMathControlState(); void setMathControlState(U32 state); void setMathControlStateKnown(); // Process control void sleep(U32 ms); bool excludeOtherInstances(const char *string); bool checkOtherInstances(const char *string); void restartInstance(); void postQuitMessage(const S32 in_quitVal); void forceShutdown(S32 returnValue); // Debug void outputDebugString(const char *string, ...); void debugBreak(); // Random F32 getRandom(); // Window state void setWindowLocked(bool locked); void minimizeWindow(); //const Point2I &getWindowSize(); void setWindowSize( U32 newWidth, U32 newHeight, bool fullScreen ); void closeWindow(); // File stuff bool doCDCheck(); StringTableEntry createPlatformFriendlyFilename(const char *filename); struct FileInfo { const char* pFullPath; const char* pFileName; U32 fileSize; }; bool cdFileExists(const char *filePath, const char *volumeName, S32 serialNum); void fileToLocalTime(const FileTime &ft, LocalTime *lt); /// compare file times returns < 0 if a is earlier than b, >0 if b is earlier than a S32 compareFileTimes(const FileTime &a, const FileTime &b); bool stringToFileTime(const char * string, FileTime * time); bool fileTimeToString(FileTime * time, char * string, U32 strLen); /// Compares the last modified time between two file paths. Returns < 0 if /// the first file is earlier than the second, > 0 if the second file is earlier /// than the first, and 0 if the files are equal. /// /// If either of the files doesn't exist it returns -1. S32 compareModifiedTimes( const char *firstPath, const char *secondPath ); // Directory functions. Dump path returns false iff the directory cannot be // opened. StringTableEntry getCurrentDirectory(); bool setCurrentDirectory(StringTableEntry newDir); StringTableEntry getTemporaryDirectory(); StringTableEntry getTemporaryFileName(); /// Returns the filename of the torque executable. /// On Win32, this is the .exe file. /// On Mac, this is the .app/ directory bundle. StringTableEntry getExecutableName(); /// Returns full pathname of the torque executable without filename StringTableEntry getExecutablePath(); /// Returns the full path to the directory that contains main.tscript. /// Tools scripts are validated as such if they are in this directory or a /// subdirectory of this directory. StringTableEntry getMainDotCsDir(); /// Set main.tscript directory. Used in runEntryScript() void setMainDotCsDir(const char *dir); StringTableEntry getPrefsPath(const char *file = NULL); char *makeFullPathName(const char *path, char *buffer, U32 size, const char *cwd = NULL); StringTableEntry stripBasePath(const char *path); bool isFullPath(const char *path); StringTableEntry makeRelativePathName(const char *path, const char *to); String stripExtension( String fileName, Vector< String >& validExtensions ); bool dumpPath(const char *in_pBasePath, Vector& out_rFileVector, S32 recurseDepth = -1); bool dumpDirectories( const char *path, Vector &directoryVector, S32 depth = 0, bool noBasePath = false ); bool hasSubDirectory( const char *pPath ); bool getFileTimes(const char *filePath, FileTime *createTime, FileTime *modifyTime); bool isFile(const char *pFilePath); S32 getFileSize(const char *pFilePath); bool isDirectory(const char *pDirPath); bool isSubDirectory(const char *pParent, const char *pDir); void addExcludedDirectory(const char *pDir); void clearExcludedDirectories(); bool isExcludedDirectory(const char *pDir); bool deleteDirectory(const char* pPath); bool fileDelete(const char *name); /// Given a directory path, create all necessary directories for that path to exist. bool createPath(const char *path); // create a directory path // Alerts void AlertOK(const char *windowTitle, const char *message); bool AlertOKCancel(const char *windowTitle, const char *message); bool AlertRetry(const char *windowTitle, const char *message); ALERT_ASSERT_RESULT AlertAssert(const char *windowTitle, const char *message); // Volumes struct VolumeInformation { StringTableEntry RootPath; StringTableEntry Name; StringTableEntry FileSystem; U32 SerialNumber; U32 Type; bool ReadOnly; }; extern struct VolumeInformation *PVolumeInformation; // Volume functions. void getVolumeNamesList( Vector& out_rNameVector, bool bOnlyFixedDrives = false ); void getVolumeInformationList( Vector& out_rVolumeInfoVector, bool bOnlyFixedDrives = false ); struct SystemInfo_struct { struct Processor { ProcessorType type; const char* name; U32 mhz; bool isMultiCore; bool isHyperThreaded; U32 numLogicalProcessors; U32 numPhysicalProcessors; U32 properties; // CPU type specific enum } processor; }; extern Signal SystemInfoReady; extern SystemInfo_struct SystemInfo; // Web page launch function: bool openWebBrowser( const char* webAddress ); // display Splash Window bool displaySplashWindow( String path ); // close Splash Window bool closeSplashWindow(); void openFolder( const char* path ); // Open file at the OS level, according to registered file-types. void openFile( const char* path ); const char* getLoginPassword(); bool setLoginPassword( const char* password ); const char* getClipboard(); bool setClipboard(const char *text); // User Specific Functions StringTableEntry getUserHomeDirectory(); StringTableEntry getUserDataDirectory(); bool getUserIsAdministrator(); // Displays a fancy platform specific message box S32 messageBox(const UTF8 *title, const UTF8 *message, MBButtons buttons = MBOkCancel, MBIcons icon = MIInformation); /// Description of a keyboard input we want to ignore. struct KeyboardInputExclusion { KeyboardInputExclusion() { key = 0; orModifierMask = 0; andModifierMask = 0; } /// The key code to ignore, e.g. KEY_TAB. If this and the other /// conditions match, ignore the key. S32 key; /// if(modifiers | orModifierMask) and the other conditions match, /// ignore the key. U32 orModifierMask; /// if((modifiers & andModifierMask) == andModifierMask) and the /// other conditions match, ignore the key stroke. U32 andModifierMask; /// Based on the values above, determine if a given input event /// matchs this exclusion rule. const bool checkAgainstInput(const InputEventInfo *info) const; }; /// Reset the keyboard input exclusion list. void clearKeyboardInputExclusion(); /// Add a new keyboard exclusion. void addKeyboardInputExclusion(const KeyboardInputExclusion &kie); /// Check if a given input event should be excluded. const bool checkKeyboardInputExclusion(const InputEventInfo *info); /// Set/Get whether this is a web deployment bool getWebDeployment(); void setWebDeployment(bool v); }; //------------------------------------------------------------------------------ // Unicode string conversions // UNICODE is a windows platform API switching flag. Don't define it on other platforms. #ifdef UNICODE #define dT(s) L##s #else #define dT(s) s #endif //------------------------------------------------------------------------------ // Misc StdLib functions #define QSORT_CALLBACK FN_CDECL inline void dQsort(void *base, U32 nelem, U32 width, S32 (QSORT_CALLBACK *fcmp)(const void *, const void *)) { qsort(base, nelem, width, fcmp); } //-------------------------------------- Some all-around useful inlines and globals // ///@defgroup ObjTrickery Object Management Trickery /// /// These functions are to construct and destruct objects in memory /// without causing a free or malloc call to occur. This is so that /// we don't have to worry about allocating, say, space for a hundred /// NetAddresses with a single malloc call, calling delete on a single /// NetAdress, and having it try to free memory out from under us. /// /// @{ /// Constructs an object that already has memory allocated for it. template inline T* constructInPlace(T* p) { return new ( p ) T; } template< class T > inline T* constructArrayInPlace( T* p, U32 num ) { return new ( p ) T[ num ]; } /// Copy constructs an object that already has memory allocated for it. template inline T* constructInPlace(T* p, const T* copy) { return new ( p ) T( *copy ); } template inline T* constructInPlace(T* ptr, T2 t2) { return new ( ptr ) T( t2 ); } template inline T* constructInPlace(T* ptr, T2 t2, T3 t3) { return new ( ptr ) T( t2, t3 ); } template inline T* constructInPlace(T* ptr, T2 t2, T3 t3, T4 t4) { return new ( ptr ) T( t2, t3, t4 ); } template inline T* constructInPlace(T* ptr, T2 t2, T3 t3, T4 t4, T5 t5) { return new ( ptr ) T( t2, t3, t4, t5 ); } /// Destructs an object without freeing the memory associated with it. template inline void destructInPlace(T* p) { p->~T(); } //------------------------------------------------------------------------------ /// Memory functions #if !defined(TORQUE_DISABLE_MEMORY_MANAGER) # define TORQUE_TMM_ARGS_DECL , const char* fileName, const U32 lineNum # define TORQUE_TMM_ARGS , fileName, lineNum # define TORQUE_TMM_LOC , __FILE__, __LINE__ extern void* FN_CDECL operator new(dsize_t size, const char*, const U32); extern void* FN_CDECL operator new[](dsize_t size, const char*, const U32); extern void FN_CDECL operator delete(void* ptr); extern void FN_CDECL operator delete[](void* ptr); # define _new new(__FILE__, __LINE__) # define new _new #else # define TORQUE_TMM_ARGS_DECL # define TORQUE_TMM_ARGS # define TORQUE_TMM_LOC #endif #define dMalloc(x) dMalloc_r(x, __FILE__, __LINE__) #define dRealloc(x, y) dRealloc_r(x, y, __FILE__, __LINE__) extern void setBreakAlloc(dsize_t); extern void setMinimumAllocUnit(U32); extern void* dMalloc_r(dsize_t in_size, const char*, const dsize_t); extern void dFree(void* in_pFree); extern void* dRealloc_r(void* in_pResize, dsize_t in_size, const char*, const dsize_t); extern void* dRealMalloc(dsize_t); extern void dRealFree(void*); extern void *dMalloc_aligned(dsize_t in_size, S32 alignment); extern void dFree_aligned(void *); inline void dFree( const void* p ) { dFree( ( void* ) p ); } // Helper function to copy one array into another of different type template void dCopyArray(T *dst, const S *src, dsize_t size) { for (dsize_t i = 0; i < size; i++) dst[i] = (T)src[i]; } extern void* dMemcpy(void *dst, const void *src, dsize_t size); extern void* dMemmove(void *dst, const void *src, dsize_t size); extern void* dMemset(void *dst, S32 c, dsize_t size); extern S32 dMemcmp(const void *ptr1, const void *ptr2, dsize_t size); // Special case of the above function when the arrays are the same type (use memcpy) template void dCopyArray(T *dst, const T *src, dsize_t size) { dMemcpy(dst, src, size * sizeof(T)); } /// The dALIGN macro ensures the passed declaration is /// data aligned at 16 byte boundaries. #if defined( TORQUE_COMPILER_VISUALC ) #define dALIGN( decl ) __declspec( align( 16 ) ) decl #define dALIGN_BEGIN __declspec( align( 16 ) ) #define dALIGN_END #elif defined( TORQUE_COMPILER_GCC ) #define dALIGN( decl ) decl __attribute__( ( aligned( 16 ) ) ) #define dALIGN_BEGIN #define dALIGN_END __attribute__( ( aligned( 16 ) ) ) #else #define dALIGN( decl ) decl #define dALIGN_BEGIN() #define dALIGN_END() #endif //------------------------------------------------------------------------------ // FileIO functions extern bool dFileDelete(const char *name); extern bool dFileRename(const char *oldName, const char *newName); extern bool dFileTouch(const char *name); extern bool dPathCopy(const char *fromName, const char *toName, bool nooverwrite = true); typedef void* FILE_HANDLE; enum DFILE_STATUS { DFILE_OK = 1 }; extern FILE_HANDLE dOpenFileRead(const char *name, DFILE_STATUS &error); extern FILE_HANDLE dOpenFileReadWrite(const char *name, bool append, DFILE_STATUS &error); extern S32 dFileRead(FILE_HANDLE handle, U32 bytes, char *dst, DFILE_STATUS &error); extern S32 dFileWrite(FILE_HANDLE handle, U32 bytes, const char *dst, DFILE_STATUS &error); extern void dFileClose(FILE_HANDLE handle); extern StringTableEntry osGetTemporaryDirectory(); //------------------------------------------------------------------------------ struct Math { /// Initialize the math library with the appropriate libraries /// to support hardware acceleration features. /// /// @param properties Leave zero to detect available hardware. Otherwise, /// pass CPU instruction set flags that you want to load /// support for. static void init(U32 properties = 0); }; /// @} #endif