408 lines
		
	
	
		
			9.9 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			408 lines
		
	
	
		
			9.9 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| // Copyright (C) 2002-2012 Nikolaus Gebhardt
 | |
| // This file is part of the "Irrlicht Engine".
 | |
| // For conditions of distribution and use, see copyright notice in irrlicht.h
 | |
| 
 | |
| #include "os.h"
 | |
| #include "irrString.h"
 | |
| #include "irrMath.h"
 | |
| 
 | |
| #if defined(_IRR_COMPILE_WITH_SDL_DEVICE_)
 | |
| 	#include <SDL_endian.h>
 | |
| 	#define bswap_16(X) SDL_Swap16(X)
 | |
| 	#define bswap_32(X) SDL_Swap32(X)
 | |
| 	#define bswap_64(X) SDL_Swap64(X)
 | |
| #elif defined(_IRR_WINDOWS_API_) && defined(_MSC_VER)
 | |
| 	#include <stdlib.h>
 | |
| 	#define bswap_16(X) _byteswap_ushort(X)
 | |
| 	#define bswap_32(X) _byteswap_ulong(X)
 | |
| 	#define bswap_64(X) _byteswap_uint64(X)
 | |
| 	#define localtime _localtime_s
 | |
| #elif defined(_IRR_OSX_PLATFORM_)
 | |
| 	#include <libkern/OSByteOrder.h>
 | |
| 	#define bswap_16(X) OSReadSwapInt16(&X,0)
 | |
| 	#define bswap_32(X) OSReadSwapInt32(&X,0)
 | |
| 	#define bswap_64(X) OSReadSwapInt64(&X,0)
 | |
| #elif defined(__FreeBSD__)
 | |
| 	#include <sys/endian.h>
 | |
| 	#define bswap_16(X) bswap16(X)
 | |
| 	#define bswap_32(X) bswap32(X)
 | |
| 	#define bswap_64(X) bswap64(X)
 | |
| #elif defined(__OpenBSD__)
 | |
| 	#include <endian.h>
 | |
| 	#define bswap_16(X) letoh16(X)
 | |
| 	#define bswap_32(X) letoh32(X)
 | |
| 	#define bswap_64(X) letoh64(X)
 | |
| #elif !defined(_IRR_SOLARIS_PLATFORM_) && !defined(__PPC__) && !defined(_IRR_WINDOWS_API_)
 | |
| 	#include <byteswap.h>
 | |
| #else
 | |
| 	#define bswap_16(X) ((((X)&0xFF) << 8) | (((X)&0xFF00) >> 8))
 | |
| 	#define bswap_32(X) ((((X)&0x000000FF) << 24) | (((X)&0xFF000000) >> 24) | (((X)&0x0000FF00) << 8) | (((X) &0x00FF0000) >> 8))
 | |
| 	#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))
 | |
| #endif
 | |
| 
 | |
| namespace irr
 | |
| {
 | |
| namespace os
 | |
| {
 | |
| 	u16 Byteswap::byteswap(u16 num) {return bswap_16(num);}
 | |
| 	s16 Byteswap::byteswap(s16 num) {return bswap_16(num);}
 | |
| 	u32 Byteswap::byteswap(u32 num) {return bswap_32(num);}
 | |
| 	s32 Byteswap::byteswap(s32 num) {return bswap_32(num);}
 | |
| 	u64 Byteswap::byteswap(u64 num) {return bswap_64(num);}
 | |
| 	s64 Byteswap::byteswap(s64 num) {return bswap_64(num);}
 | |
| 	f32 Byteswap::byteswap(f32 num) {u32 tmp=IR(num); tmp=bswap_32(tmp); return (FR(tmp));}
 | |
| 	// prevent accidental byte swapping of chars
 | |
| 	u8  Byteswap::byteswap(u8 num)  {return num;}
 | |
| 	c8  Byteswap::byteswap(c8 num)  {return num;}
 | |
| }
 | |
| }
 | |
| 
 | |
| #if defined(_IRR_WINDOWS_API_)
 | |
| // ----------------------------------------------------------------
 | |
| // Windows specific functions
 | |
| // ----------------------------------------------------------------
 | |
| 
 | |
| #define WIN32_LEAN_AND_MEAN
 | |
| #include <windows.h>
 | |
| #include <time.h>
 | |
| 
 | |
| namespace irr
 | |
| {
 | |
| namespace os
 | |
| {
 | |
| 	//! prints a debuginfo string
 | |
| 	void Printer::print(const c8* message, ELOG_LEVEL ll)
 | |
| 	{
 | |
| 		core::stringc tmp(message);
 | |
| 		tmp += "\n";
 | |
| 		OutputDebugStringA(tmp.c_str());
 | |
| 		printf("%s", tmp.c_str());
 | |
| 	}
 | |
| 
 | |
| 	static LARGE_INTEGER HighPerformanceFreq;
 | |
| 	static BOOL HighPerformanceTimerSupport = FALSE;
 | |
| 
 | |
| 	void Timer::initTimer(bool usePerformanceTimer)
 | |
| 	{
 | |
| 		if (usePerformanceTimer)
 | |
| 			HighPerformanceTimerSupport = QueryPerformanceFrequency(&HighPerformanceFreq);
 | |
| 		else
 | |
| 			HighPerformanceTimerSupport = FALSE;
 | |
| 		initVirtualTimer();
 | |
| 	}
 | |
| 
 | |
| 	u32 Timer::getRealTime()
 | |
| 	{
 | |
| 		if (HighPerformanceTimerSupport)
 | |
| 		{
 | |
| 			LARGE_INTEGER nTime;
 | |
| 			BOOL queriedOK = QueryPerformanceCounter(&nTime);
 | |
| 
 | |
| 			if(queriedOK)
 | |
| 				return u32((nTime.QuadPart) * 1000 / HighPerformanceFreq.QuadPart);
 | |
| 		}
 | |
| 
 | |
| 		return GetTickCount();
 | |
| 	}
 | |
| 
 | |
| } // end namespace os
 | |
| 
 | |
| 
 | |
| #elif defined( _IRR_ANDROID_PLATFORM_ )
 | |
| 
 | |
| // ----------------------------------------------------------------
 | |
| // Android version
 | |
| // ----------------------------------------------------------------
 | |
| 
 | |
| #include <android/log.h>
 | |
| 
 | |
| namespace irr
 | |
| {
 | |
| namespace os
 | |
| {
 | |
| 
 | |
| 	//! prints a debuginfo string
 | |
| 	void Printer::print(const c8* message, ELOG_LEVEL ll)
 | |
| 	{
 | |
| 		android_LogPriority LogLevel = ANDROID_LOG_UNKNOWN;
 | |
| 
 | |
| 		switch (ll)
 | |
| 		{
 | |
| 		case ELL_DEBUG:
 | |
| 			LogLevel = ANDROID_LOG_DEBUG;
 | |
| 			break;
 | |
| 		case ELL_INFORMATION:
 | |
| 			LogLevel = ANDROID_LOG_INFO;
 | |
| 			break;
 | |
| 		case ELL_WARNING:
 | |
| 			LogLevel = ANDROID_LOG_WARN;
 | |
| 			break;
 | |
| 		case ELL_ERROR:
 | |
| 			LogLevel = ANDROID_LOG_ERROR;
 | |
| 			break;
 | |
| 		default: // ELL_NONE
 | |
| 			LogLevel = ANDROID_LOG_VERBOSE;
 | |
| 			break;
 | |
| 		}
 | |
| 
 | |
| 		// Android logcat restricts log-output and cuts the rest of the message away. But we want it all.
 | |
| 		// On my device max-len is 1023 (+ 0 byte). Some websites claim a limit of 4096 so maybe different numbers on different devices.
 | |
| 		const size_t maxLogLen = 1023;
 | |
| 		size_t msgLen = strlen(message);
 | |
| 		size_t start = 0;
 | |
| 		while ( msgLen-start > maxLogLen )
 | |
| 		{
 | |
| 			__android_log_print(LogLevel, "Irrlicht", "%.*s\n", maxLogLen, &message[start]);
 | |
| 			start += maxLogLen;
 | |
| 		}
 | |
| 		__android_log_print(LogLevel, "Irrlicht", "%s\n", &message[start]);
 | |
| 	}
 | |
| 
 | |
| 	void Timer::initTimer(bool usePerformanceTimer)
 | |
| 	{
 | |
| 		initVirtualTimer();
 | |
| 	}
 | |
| 
 | |
| 	u32 Timer::getRealTime()
 | |
| 	{
 | |
| 		timeval tv;
 | |
| 		gettimeofday(&tv, 0);
 | |
| 		return (u32)(tv.tv_sec * 1000) + (tv.tv_usec / 1000);
 | |
| 	}
 | |
| } // end namespace os
 | |
| 
 | |
| #elif defined(_IRR_EMSCRIPTEN_PLATFORM_)
 | |
| 
 | |
| // ----------------------------------------------------------------
 | |
| // emscripten version
 | |
| // ----------------------------------------------------------------
 | |
| 
 | |
| #include <emscripten.h>
 | |
| #include <time.h>
 | |
| #include <sys/time.h>
 | |
| 
 | |
| namespace irr
 | |
| {
 | |
| namespace os
 | |
| {
 | |
| 
 | |
| 	//! prints a debuginfo string
 | |
| 	void Printer::print(const c8* message, ELOG_LEVEL ll)
 | |
| 	{
 | |
|         int log_level;
 | |
| 		switch (ll)
 | |
| 		{
 | |
| 		case ELL_DEBUG:
 | |
|             log_level=0;
 | |
| 		break;
 | |
| 		case ELL_INFORMATION:
 | |
|            log_level=0;
 | |
| 		break;
 | |
| 		case ELL_WARNING:
 | |
|             log_level=EM_LOG_WARN;
 | |
| 			break;
 | |
| 		case ELL_ERROR:
 | |
|             log_level=EM_LOG_ERROR;
 | |
| 		break;
 | |
| 		default: // ELL_NONE
 | |
|             log_level=0;
 | |
| 			break;
 | |
| 		}
 | |
|         emscripten_log(log_level, "%s", message);	// Note: not adding \n as emscripten_log seems to do that already.
 | |
| 	}
 | |
| 
 | |
| 	void Timer::initTimer(bool usePerformanceTimer)
 | |
| 	{
 | |
| 		initVirtualTimer();
 | |
| 	}
 | |
| 
 | |
| 	u32 Timer::getRealTime()
 | |
| 	{
 | |
|         double time = emscripten_get_now();
 | |
|         return (u32)(time);
 | |
| 	}
 | |
| } // end namespace os
 | |
| 
 | |
| #else
 | |
| 
 | |
| // ----------------------------------------------------------------
 | |
| // linux/ansi version
 | |
| // ----------------------------------------------------------------
 | |
| 
 | |
| #include <stdio.h>
 | |
| #include <time.h>
 | |
| #include <sys/time.h>
 | |
| 
 | |
| namespace irr
 | |
| {
 | |
| namespace os
 | |
| {
 | |
| 
 | |
| 	//! prints a debuginfo string
 | |
| 	void Printer::print(const c8* message, ELOG_LEVEL ll)
 | |
| 	{
 | |
| 		printf("%s\n", message);
 | |
| 	}
 | |
| 
 | |
| 	void Timer::initTimer(bool usePerformanceTimer)
 | |
| 	{
 | |
| 		initVirtualTimer();
 | |
| 	}
 | |
| 
 | |
| 	u32 Timer::getRealTime()
 | |
| 	{
 | |
| 		timeval tv;
 | |
| 		gettimeofday(&tv, 0);
 | |
| 		return (u32)(tv.tv_sec * 1000) + (tv.tv_usec / 1000);
 | |
| 	}
 | |
| } // end namespace os
 | |
| 
 | |
| #endif // end linux / emscripten / android / windows
 | |
| 
 | |
| namespace os
 | |
| {
 | |
| 	// The platform independent implementation of the printer
 | |
| 	ILogger* Printer::Logger = 0;
 | |
| 
 | |
| 	void Printer::log(const c8* message, ELOG_LEVEL ll)
 | |
| 	{
 | |
| 		if (Logger)
 | |
| 			Logger->log(message, ll);
 | |
| 	}
 | |
| 
 | |
| 	void Printer::log(const wchar_t* message, ELOG_LEVEL ll)
 | |
| 	{
 | |
| 		if (Logger)
 | |
| 			Logger->log(message, ll);
 | |
| 	}
 | |
| 
 | |
| 	void Printer::log(const c8* message, const c8* hint, ELOG_LEVEL ll)
 | |
| 	{
 | |
| 		if (Logger)
 | |
| 			Logger->log(message, hint, ll);
 | |
| 	}
 | |
| 
 | |
| 	void Printer::log(const c8* message, const io::path& hint, ELOG_LEVEL ll)
 | |
| 	{
 | |
| 		if (Logger)
 | |
| 			Logger->log(message, hint.c_str(), ll);
 | |
| 	}
 | |
| 
 | |
| 	// ------------------------------------------------------
 | |
| 	// virtual timer implementation
 | |
| 
 | |
| 	f32 Timer::VirtualTimerSpeed = 1.0f;
 | |
| 	s32 Timer::VirtualTimerStopCounter = 0;
 | |
| 	u32 Timer::LastVirtualTime = 0;
 | |
| 	u32 Timer::StartRealTime = 0;
 | |
| 	u32 Timer::StaticTime = 0;
 | |
| 
 | |
| 	//! Get real time and date in calendar form
 | |
| 	ITimer::RealTimeDate Timer::getRealTimeAndDate()
 | |
| 	{
 | |
| 		time_t rawtime;
 | |
| 		time(&rawtime);
 | |
| 
 | |
| 		struct tm * timeinfo;
 | |
| 		timeinfo = localtime(&rawtime);
 | |
| 
 | |
| 		// init with all 0 to indicate error
 | |
| 		ITimer::RealTimeDate date;
 | |
| 		memset(&date, 0, sizeof(date));
 | |
| 		// at least Windows returns NULL on some illegal dates
 | |
| 		if (timeinfo)
 | |
| 		{
 | |
| 			// set useful values if succeeded
 | |
| 			date.Hour=(u32)timeinfo->tm_hour;
 | |
| 			date.Minute=(u32)timeinfo->tm_min;
 | |
| 			date.Second=(u32)timeinfo->tm_sec;
 | |
| 			date.Day=(u32)timeinfo->tm_mday;
 | |
| 			date.Month=(u32)timeinfo->tm_mon+1;
 | |
| 			date.Year=(u32)timeinfo->tm_year+1900;
 | |
| 			date.Weekday=(ITimer::EWeekday)timeinfo->tm_wday;
 | |
| 			date.Yearday=(u32)timeinfo->tm_yday+1;
 | |
| 			date.IsDST=timeinfo->tm_isdst != 0;
 | |
| 		}
 | |
| 		return date;
 | |
| 	}
 | |
| 
 | |
| 	//! returns current virtual time
 | |
| 	u32 Timer::getTime()
 | |
| 	{
 | |
| 		if (isStopped())
 | |
| 			return LastVirtualTime;
 | |
| 
 | |
| 		return LastVirtualTime + (u32)((StaticTime - StartRealTime) * VirtualTimerSpeed);
 | |
| 	}
 | |
| 
 | |
| 	//! ticks, advances the virtual timer
 | |
| 	void Timer::tick()
 | |
| 	{
 | |
| 		StaticTime = getRealTime();
 | |
| 	}
 | |
| 
 | |
| 	//! sets the current virtual time
 | |
| 	void Timer::setTime(u32 time)
 | |
| 	{
 | |
| 		StaticTime = getRealTime();
 | |
| 		LastVirtualTime = time;
 | |
| 		StartRealTime = StaticTime;
 | |
| 	}
 | |
| 
 | |
| 	//! stops the virtual timer
 | |
| 	void Timer::stopTimer()
 | |
| 	{
 | |
| 		if (!isStopped())
 | |
| 		{
 | |
| 			// stop the virtual timer
 | |
| 			LastVirtualTime = getTime();
 | |
| 		}
 | |
| 
 | |
| 		--VirtualTimerStopCounter;
 | |
| 	}
 | |
| 
 | |
| 	//! starts the virtual timer
 | |
| 	void Timer::startTimer()
 | |
| 	{
 | |
| 		++VirtualTimerStopCounter;
 | |
| 
 | |
| 		if (!isStopped())
 | |
| 		{
 | |
| 			// restart virtual timer
 | |
| 			setTime(LastVirtualTime);
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	//! sets the speed of the virtual timer
 | |
| 	void Timer::setSpeed(f32 speed)
 | |
| 	{
 | |
| 		setTime(getTime());
 | |
| 
 | |
| 		VirtualTimerSpeed = speed;
 | |
| 		if (VirtualTimerSpeed < 0.0f)
 | |
| 			VirtualTimerSpeed = 0.0f;
 | |
| 	}
 | |
| 
 | |
| 	//! gets the speed of the virtual timer
 | |
| 	f32 Timer::getSpeed()
 | |
| 	{
 | |
| 		return VirtualTimerSpeed;
 | |
| 	}
 | |
| 
 | |
| 	//! returns if the timer currently is stopped
 | |
| 	bool Timer::isStopped()
 | |
| 	{
 | |
| 		return VirtualTimerStopCounter < 0;
 | |
| 	}
 | |
| 
 | |
| 	void Timer::initVirtualTimer()
 | |
| 	{
 | |
| 		StaticTime = getRealTime();
 | |
| 		StartRealTime = StaticTime;
 | |
| 	}
 | |
| 
 | |
| } // end namespace os
 | |
| } // end namespace irr
 | |
| 
 | |
| 
 |