]> git.lizzy.rs Git - irrlicht.git/blob - source/Irrlicht/os.cpp
2b894bcd0fb80da6a90222057f360f058defec77
[irrlicht.git] / source / Irrlicht / os.cpp
1 // Copyright (C) 2002-2012 Nikolaus Gebhardt\r
2 // This file is part of the "Irrlicht Engine".\r
3 // For conditions of distribution and use, see copyright notice in irrlicht.h\r
4 \r
5 #include "os.h"\r
6 #include "irrString.h"\r
7 #include "IrrCompileConfig.h"\r
8 #include "irrMath.h"\r
9 \r
10 #if defined(_IRR_COMPILE_WITH_SDL_DEVICE_)\r
11         #include <SDL_endian.h>\r
12         #define bswap_16(X) SDL_Swap16(X)\r
13         #define bswap_32(X) SDL_Swap32(X)\r
14         #define bswap_64(X) SDL_Swap64(X)\r
15 #elif defined(_IRR_WINDOWS_API_) && defined(_MSC_VER)\r
16         #include <stdlib.h>\r
17         #define bswap_16(X) _byteswap_ushort(X)\r
18         #define bswap_32(X) _byteswap_ulong(X)\r
19         #define bswap_64(X) _byteswap_uint64(X)\r
20         #define localtime _localtime_s\r
21 #elif defined(_IRR_OSX_PLATFORM_) || defined(_IRR_IOS_PLATFORM_)\r
22         #include <libkern/OSByteOrder.h>\r
23         #define bswap_16(X) OSReadSwapInt16(&X,0)\r
24         #define bswap_32(X) OSReadSwapInt32(&X,0)\r
25         #define bswap_64(X) OSReadSwapInt64(&X,0)\r
26 #elif defined(__FreeBSD__)\r
27         #include <sys/endian.h>\r
28         #define bswap_16(X) bswap16(X)\r
29         #define bswap_32(X) bswap32(X)\r
30         #define bswap_64(X) bswap64(X)\r
31 #elif defined(__OpenBSD__)\r
32         #include <endian.h>\r
33         #define bswap_16(X) letoh16(X)\r
34         #define bswap_32(X) letoh32(X)\r
35         #define bswap_64(X) letoh64(X)\r
36 #elif !defined(_IRR_SOLARIS_PLATFORM_) && !defined(__PPC__) && !defined(_IRR_WINDOWS_API_)\r
37         #include <byteswap.h>\r
38 #else\r
39         #define bswap_16(X) ((((X)&0xFF) << 8) | (((X)&0xFF00) >> 8))\r
40         #define bswap_32(X) ((((X)&0x000000FF) << 24) | (((X)&0xFF000000) >> 24) | (((X)&0x0000FF00) << 8) | (((X) &0x00FF0000) >> 8))\r
41         #define bswap_64(X) ((((X)&0x00000000000000FF) << 56) | (((X)&0xFF00000000000000) >> 56) | (((X)&0x000000000000FF00) << 40) | (((X)&0x00FF000000000000) >> 40) | (((X)&0x0000000000FF0000) << 24) | (((X)&0x0000FF0000000000) >> 24) | (((X)&0x00000000FF000000) << 8) | (((X) &0x000000FF00000000) >> 8))\r
42 #endif\r
43 \r
44 namespace irr\r
45 {\r
46 namespace os\r
47 {\r
48         u16 Byteswap::byteswap(u16 num) {return bswap_16(num);}\r
49         s16 Byteswap::byteswap(s16 num) {return bswap_16(num);}\r
50         u32 Byteswap::byteswap(u32 num) {return bswap_32(num);}\r
51         s32 Byteswap::byteswap(s32 num) {return bswap_32(num);}\r
52         u64 Byteswap::byteswap(u64 num) {return bswap_64(num);}\r
53         s64 Byteswap::byteswap(s64 num) {return bswap_64(num);}\r
54         f32 Byteswap::byteswap(f32 num) {u32 tmp=IR(num); tmp=bswap_32(tmp); return (FR(tmp));}\r
55         // prevent accidental byte swapping of chars\r
56         u8  Byteswap::byteswap(u8 num)  {return num;}\r
57         c8  Byteswap::byteswap(c8 num)  {return num;}\r
58 }\r
59 }\r
60 \r
61 #if defined(_IRR_WINDOWS_API_)\r
62 // ----------------------------------------------------------------\r
63 // Windows specific functions\r
64 // ----------------------------------------------------------------\r
65 \r
66 #define WIN32_LEAN_AND_MEAN\r
67 #include <windows.h>\r
68 #include <time.h>\r
69 \r
70 namespace irr\r
71 {\r
72 namespace os\r
73 {\r
74         //! prints a debuginfo string\r
75         void Printer::print(const c8* message, ELOG_LEVEL ll)\r
76         {\r
77                 core::stringc tmp(message);\r
78                 tmp += "\n";\r
79                 OutputDebugStringA(tmp.c_str());\r
80                 printf("%s", tmp.c_str());\r
81         }\r
82 \r
83         static LARGE_INTEGER HighPerformanceFreq;\r
84         static BOOL HighPerformanceTimerSupport = FALSE;\r
85 \r
86         void Timer::initTimer(bool usePerformanceTimer)\r
87         {\r
88                 if (usePerformanceTimer)\r
89                         HighPerformanceTimerSupport = QueryPerformanceFrequency(&HighPerformanceFreq);\r
90                 else\r
91                         HighPerformanceTimerSupport = FALSE;\r
92                 initVirtualTimer();\r
93         }\r
94 \r
95         u32 Timer::getRealTime()\r
96         {\r
97                 if (HighPerformanceTimerSupport)\r
98                 {\r
99                         LARGE_INTEGER nTime;\r
100                         BOOL queriedOK = QueryPerformanceCounter(&nTime);\r
101 \r
102                         if(queriedOK)\r
103                                 return u32((nTime.QuadPart) * 1000 / HighPerformanceFreq.QuadPart);\r
104                 }\r
105 \r
106                 return GetTickCount();\r
107         }\r
108 \r
109 } // end namespace os\r
110 \r
111 \r
112 #elif defined( _IRR_ANDROID_PLATFORM_ )\r
113 \r
114 // ----------------------------------------------------------------\r
115 // Android version\r
116 // ----------------------------------------------------------------\r
117 \r
118 #include <android/log.h>\r
119 \r
120 namespace irr\r
121 {\r
122 namespace os\r
123 {\r
124 \r
125         //! prints a debuginfo string\r
126         void Printer::print(const c8* message, ELOG_LEVEL ll)\r
127         {\r
128                 android_LogPriority LogLevel = ANDROID_LOG_UNKNOWN;\r
129 \r
130                 switch (ll)\r
131                 {\r
132                 case ELL_DEBUG:\r
133                         LogLevel = ANDROID_LOG_DEBUG;\r
134                         break;\r
135                 case ELL_INFORMATION:\r
136                         LogLevel = ANDROID_LOG_INFO;\r
137                         break;\r
138                 case ELL_WARNING:\r
139                         LogLevel = ANDROID_LOG_WARN;\r
140                         break;\r
141                 case ELL_ERROR:\r
142                         LogLevel = ANDROID_LOG_ERROR;\r
143                         break;\r
144                 default: // ELL_NONE\r
145                         LogLevel = ANDROID_LOG_VERBOSE;\r
146                         break;\r
147                 }\r
148 \r
149                 // Android logcat restricts log-output and cuts the rest of the message away. But we want it all.\r
150                 // On my device max-len is 1023 (+ 0 byte). Some websites claim a limit of 4096 so maybe different numbers on different devices.\r
151                 const size_t maxLogLen = 1023;\r
152                 size_t msgLen = strlen(message);\r
153                 size_t start = 0;\r
154                 while ( msgLen-start > maxLogLen )\r
155                 {\r
156                         __android_log_print(LogLevel, "Irrlicht", "%.*s\n", maxLogLen, &message[start]);\r
157                         start += maxLogLen;\r
158                 }\r
159                 __android_log_print(LogLevel, "Irrlicht", "%s\n", &message[start]);\r
160         }\r
161 \r
162         void Timer::initTimer(bool usePerformanceTimer)\r
163         {\r
164                 initVirtualTimer();\r
165         }\r
166 \r
167         u32 Timer::getRealTime()\r
168         {\r
169                 timeval tv;\r
170                 gettimeofday(&tv, 0);\r
171                 return (u32)(tv.tv_sec * 1000) + (tv.tv_usec / 1000);\r
172         }\r
173 } // end namespace os\r
174 \r
175 #elif defined(_IRR_EMSCRIPTEN_PLATFORM_)\r
176 \r
177 // ----------------------------------------------------------------\r
178 // emscripten version\r
179 // ----------------------------------------------------------------\r
180 \r
181 #include <emscripten.h>\r
182 #include <time.h>\r
183 #include <sys/time.h>\r
184 \r
185 namespace irr\r
186 {\r
187 namespace os\r
188 {\r
189 \r
190         //! prints a debuginfo string\r
191         void Printer::print(const c8* message, ELOG_LEVEL ll)\r
192         {\r
193         int log_level;\r
194                 switch (ll)\r
195                 {\r
196                 case ELL_DEBUG:\r
197             log_level=0;\r
198                 break;\r
199                 case ELL_INFORMATION:\r
200            log_level=0;\r
201                 break;\r
202                 case ELL_WARNING:\r
203             log_level=EM_LOG_WARN;\r
204                         break;\r
205                 case ELL_ERROR:\r
206             log_level=EM_LOG_ERROR;\r
207                 break;\r
208                 default: // ELL_NONE\r
209             log_level=0;\r
210                         break;\r
211                 }\r
212         emscripten_log(log_level, "%s", message);       // Note: not adding \n as emscripten_log seems to do that already.\r
213         }\r
214 \r
215         void Timer::initTimer(bool usePerformanceTimer)\r
216         {\r
217                 initVirtualTimer();\r
218         }\r
219 \r
220         u32 Timer::getRealTime()\r
221         {\r
222         double time = emscripten_get_now();\r
223         return (u32)(time);\r
224         }\r
225 } // end namespace os\r
226 \r
227 #else\r
228 \r
229 // ----------------------------------------------------------------\r
230 // linux/ansi version\r
231 // ----------------------------------------------------------------\r
232 \r
233 #include <stdio.h>\r
234 #include <time.h>\r
235 #include <sys/time.h>\r
236 \r
237 namespace irr\r
238 {\r
239 namespace os\r
240 {\r
241 \r
242         //! prints a debuginfo string\r
243         void Printer::print(const c8* message, ELOG_LEVEL ll)\r
244         {\r
245                 printf("%s\n", message);\r
246         }\r
247 \r
248         void Timer::initTimer(bool usePerformanceTimer)\r
249         {\r
250                 initVirtualTimer();\r
251         }\r
252 \r
253         u32 Timer::getRealTime()\r
254         {\r
255                 timeval tv;\r
256                 gettimeofday(&tv, 0);\r
257                 return (u32)(tv.tv_sec * 1000) + (tv.tv_usec / 1000);\r
258         }\r
259 } // end namespace os\r
260 \r
261 #endif // end linux / emscripten / android / windows\r
262 \r
263 namespace os\r
264 {\r
265         // The platform independent implementation of the printer\r
266         ILogger* Printer::Logger = 0;\r
267 \r
268         void Printer::log(const c8* message, ELOG_LEVEL ll)\r
269         {\r
270                 if (Logger)\r
271                         Logger->log(message, ll);\r
272         }\r
273 \r
274         void Printer::log(const wchar_t* message, ELOG_LEVEL ll)\r
275         {\r
276                 if (Logger)\r
277                         Logger->log(message, ll);\r
278         }\r
279 \r
280         void Printer::log(const c8* message, const c8* hint, ELOG_LEVEL ll)\r
281         {\r
282                 if (Logger)\r
283                         Logger->log(message, hint, ll);\r
284         }\r
285 \r
286         void Printer::log(const c8* message, const io::path& hint, ELOG_LEVEL ll)\r
287         {\r
288                 if (Logger)\r
289                         Logger->log(message, hint.c_str(), ll);\r
290         }\r
291 \r
292         // ------------------------------------------------------\r
293         // virtual timer implementation\r
294 \r
295         f32 Timer::VirtualTimerSpeed = 1.0f;\r
296         s32 Timer::VirtualTimerStopCounter = 0;\r
297         u32 Timer::LastVirtualTime = 0;\r
298         u32 Timer::StartRealTime = 0;\r
299         u32 Timer::StaticTime = 0;\r
300 \r
301         //! Get real time and date in calendar form\r
302         ITimer::RealTimeDate Timer::getRealTimeAndDate()\r
303         {\r
304                 time_t rawtime;\r
305                 time(&rawtime);\r
306 \r
307                 struct tm * timeinfo;\r
308                 timeinfo = localtime(&rawtime);\r
309 \r
310                 // init with all 0 to indicate error\r
311                 ITimer::RealTimeDate date;\r
312                 memset(&date, 0, sizeof(date));\r
313                 // at least Windows returns NULL on some illegal dates\r
314                 if (timeinfo)\r
315                 {\r
316                         // set useful values if succeeded\r
317                         date.Hour=(u32)timeinfo->tm_hour;\r
318                         date.Minute=(u32)timeinfo->tm_min;\r
319                         date.Second=(u32)timeinfo->tm_sec;\r
320                         date.Day=(u32)timeinfo->tm_mday;\r
321                         date.Month=(u32)timeinfo->tm_mon+1;\r
322                         date.Year=(u32)timeinfo->tm_year+1900;\r
323                         date.Weekday=(ITimer::EWeekday)timeinfo->tm_wday;\r
324                         date.Yearday=(u32)timeinfo->tm_yday+1;\r
325                         date.IsDST=timeinfo->tm_isdst != 0;\r
326                 }\r
327                 return date;\r
328         }\r
329 \r
330         //! returns current virtual time\r
331         u32 Timer::getTime()\r
332         {\r
333                 if (isStopped())\r
334                         return LastVirtualTime;\r
335 \r
336                 return LastVirtualTime + (u32)((StaticTime - StartRealTime) * VirtualTimerSpeed);\r
337         }\r
338 \r
339         //! ticks, advances the virtual timer\r
340         void Timer::tick()\r
341         {\r
342                 StaticTime = getRealTime();\r
343         }\r
344 \r
345         //! sets the current virtual time\r
346         void Timer::setTime(u32 time)\r
347         {\r
348                 StaticTime = getRealTime();\r
349                 LastVirtualTime = time;\r
350                 StartRealTime = StaticTime;\r
351         }\r
352 \r
353         //! stops the virtual timer\r
354         void Timer::stopTimer()\r
355         {\r
356                 if (!isStopped())\r
357                 {\r
358                         // stop the virtual timer\r
359                         LastVirtualTime = getTime();\r
360                 }\r
361 \r
362                 --VirtualTimerStopCounter;\r
363         }\r
364 \r
365         //! starts the virtual timer\r
366         void Timer::startTimer()\r
367         {\r
368                 ++VirtualTimerStopCounter;\r
369 \r
370                 if (!isStopped())\r
371                 {\r
372                         // restart virtual timer\r
373                         setTime(LastVirtualTime);\r
374                 }\r
375         }\r
376 \r
377         //! sets the speed of the virtual timer\r
378         void Timer::setSpeed(f32 speed)\r
379         {\r
380                 setTime(getTime());\r
381 \r
382                 VirtualTimerSpeed = speed;\r
383                 if (VirtualTimerSpeed < 0.0f)\r
384                         VirtualTimerSpeed = 0.0f;\r
385         }\r
386 \r
387         //! gets the speed of the virtual timer\r
388         f32 Timer::getSpeed()\r
389         {\r
390                 return VirtualTimerSpeed;\r
391         }\r
392 \r
393         //! returns if the timer currently is stopped\r
394         bool Timer::isStopped()\r
395         {\r
396                 return VirtualTimerStopCounter < 0;\r
397         }\r
398 \r
399         void Timer::initVirtualTimer()\r
400         {\r
401                 StaticTime = getRealTime();\r
402                 StartRealTime = StaticTime;\r
403         }\r
404 \r
405 } // end namespace os\r
406 } // end namespace irr\r
407 \r
408 \r