#include "Common.h" #include "BFPlatform.h" #include #include #include #include #include #include #include #include #include #include #include #include "SDL_timer.h" int gBFPlatformLastError = 0; #define NOT_IMPL throw "Unimplemented"; inline uint64 get_mach_frequency() { uint64 freq = 0; if (freq == 0) { static mach_timebase_info_data_t sTimebaseInfo; if ( sTimebaseInfo.denom == 0) (void) mach_timebase_info(&sTimebaseInfo); freq = (uint64_t)1000000 * (uint64)sTimebaseInfo.denom / (uint64)sTimebaseInfo.numer; } return freq; } uint32 Beefy::BFTickCount() { /*uint64 t; t = mach_absolute_time(); t /= get_mach_frequency(); return (uint32)t;*/ return SDL_GetTicks(); } int64 Beefy::EndianSwap(int64 val) { return CFSwapInt64(val); } bool IsDebuggerPresent() { /* int mib[4]; struct kinfo_proc info; size_t size; info.kp_proc.p_flag = 0; mib[0] = CTL_KERN; mib[1] = KERN_PROC; mib[2] = KERN_PROC_PID; mib[3] = getpid(); size = sizeof(info); sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, NULL, 0); return ((info.kp_proc.p_flag & P_TRACED) != 0);*/ return true; } void OutputDebugStringA(const char* str) { if (IsDebuggerPresent()) fputs(str, stdout); } void OutputDebugStringW(const wchar_t* str) { if (IsDebuggerPresent()) { fputws(str, stdout); } } void* BFTlsGetValue(BFTlsKey tlsKey) { return pthread_getspecific(tlsKey); } bool BFTlsSetValue(BFTlsKey tlsKey, void* tlsValue) { return pthread_setspecific(tlsKey, tlsValue) == 0; } BFTlsKey BFTlsAlloc() { pthread_key_t key = NULL; pthread_key_create(&key, NULL); return key; } bool BFTlsFree(BFTlsKey tlsKey) { return pthread_key_delete(tlsKey) == 0; } HANDLE GetModuleHandle(HANDLE h) { NOT_IMPL return 0; } uint32 GetModuleFileNameW(uint32 hModule, wchar_t* lpFilename, uint32 length) { return (uint32)mbstowcs(lpFilename, gBFArgV[0], length); } uint32 GetModuleFileNameA(uint32 hModule, char* lpFilename, uint32 length) { strncpy(lpFilename, gBFArgV[0], length); return (uint32)strlen(lpFilename); } HMODULE LoadLibraryA(const char* fileName) { HMODULE mod = NULL; /*(HMODULE)dlopen(fileName, RTLD_LAZY); if (mod == NULL) mod = (HMODULE)dlopen((std::string(fileName) + ".dylib").c_str(), RTLD_LAZY); if (mod == NULL) mod = (HMODULE)dlopen((std::string(fileName) + ".so").c_str(), RTLD_LAZY);*/ static const char* prefixes[] = {NULL, "lib"}; static const char* suffixes[] = {NULL, ".so", ".dylib"}; for (int prefixIdx = 0; prefixIdx < sizeof(prefixes)/sizeof(prefixes[0]); prefixIdx++) { for (int suffixIdx = 0; suffixIdx < sizeof(suffixes)/sizeof(suffixes[0]); suffixIdx++) { const char* prefix = prefixes[prefixIdx]; const char* suffix = suffixes[suffixIdx]; std::string checkName = fileName; if (prefix != NULL) checkName = std::string(prefix) + checkName; if (suffix != NULL) checkName += suffix; mod = (HMODULE)dlopen(checkName.c_str(), RTLD_LAZY); if (mod != NULL) return mod; } } return NULL; } BFLibProcAddr GetProcAddress(HMODULE mod, const char* name) { return (BFLibProcAddr)dlsym(mod, name); } bool CreateDirectoryW(const wchar_t* str, void* securityAttributes) {NOT_IMPL return false; } bool RemoveDirectoryW(const wchar_t* str) {NOT_IMPL return false; } int GetLastError() { return gBFPlatformLastError; } void BFSetLastError(int error) { gBFPlatformLastError = error; } int* GetStdHandle(int32 handleId) { if (handleId == STD_INPUT_HANDLE) return (int*)STDIN_FILENO; if (handleId == STD_OUTPUT_HANDLE) return (int*)STDOUT_FILENO; return (int*)STDERR_FILENO; } #ifdef USING_PTHREAD intptr GetCurrentThreadId() { return (intptr)pthread_self(); } HANDLE GetCurrentThread() { return pthread_self(); } bool SetThreadPriority(HANDLE hThread, int nPriority) { return false; } void* CreateThread(void* threadAttributes, int32 stackSize, BFThreadStartProc threadStartProc, void* param, uint32 flags, intptr* threadId) { BF_ASSERT(sizeof(pthread_t) <= sizeof(void*)); pthread_t thread; pthread_attr_t params; pthread_attr_init(¶ms); pthread_attr_setstacksize(¶ms, stackSize); //pthread_attr_setdetachstate(¶ms,PTHREAD_CREATE_DETACHED); pthread_create(threadId, ¶ms, (void*(*)(void *))threadStartProc, param); thread = (pthread_t)*threadId; pthread_attr_destroy(¶ms); //printf("CreateThread: %08X\n", (intptr)thread); return (void*)thread; } void ResumeThread(HANDLE thread) {NOT_IMPL thread_suspend(thread); } uint32 SuspendThread(HANDLE thread) {NOT_IMPL } #else BF_THREADID GetCurrentThreadId() { return pthread_self(); } HANDLE GetCurrentThread() { return (HANDLE)(intptr)mach_thread_self(); } static int gThreadPriorityDefaultValue = -1; int GetThreadPriority(HANDLE hThread) { mach_msg_type_number_t count = 1; boolean_t getDefault = false; thread_precedence_policy_data_t precedence; precedence.importance = -1; kern_return_t result = thread_policy_get((thread_act_t)(intptr)hThread, THREAD_PRECEDENCE_POLICY, (thread_policy_t)&precedence, &count, &getDefault); return precedence.importance - gThreadPriorityDefaultValue; } bool SetThreadPriority(HANDLE hThread, int nPriority) { /*thread_precedence_policy_data_t precedence; precedence.importance = 0; if (gThreadPriorityDefaultValue == -1) { mach_msg_type_number_t count = 1; boolean_t getDefault = false; kern_return_t result = thread_policy_get((thread_act_t)(intptr)hThread, THREAD_PRECEDENCE_POLICY, (thread_policy_t)&precedence, &count, &getDefault); gThreadPriorityDefaultValue = precedence.importance; } precedence.importance = gThreadPriorityDefaultValue + nPriority * 16; kern_return_t result = thread_policy_set((thread_act_t)(intptr)hThread, THREAD_PRECEDENCE_POLICY, (thread_policy_t)&precedence, THREAD_PRECEDENCE_POLICY_COUNT); return result == 0;*/ int policy = 0; struct sched_param sched; sched.sched_priority = 0; pthread_getschedparam(pthread_self(), &policy, &sched); sched.sched_priority = std::min(nPriority * 16 + 47, 62); //int retVal = pthread_setschedparam(pthread_self(), policy, &sched); return true; } HANDLE OpenThread(int desiredAccess, bool inheritHandle, BF_THREADID threadId) { return (HANDLE)(intptr)mach_thread_self(); } void* CreateThread(void* threadAttributes, int32 stackSize, BFThreadStartProc threadStartProc, void* param, uint32 flags, BF_THREADID* threadId) { BF_ASSERT(sizeof(pthread_t) <= sizeof(void*)); pthread_t thread; pthread_attr_t params; pthread_attr_init(¶ms); pthread_attr_setstacksize(¶ms, stackSize); //pthread_attr_setdetachstate(¶ms,PTHREAD_CREATE_DETACHED); pthread_create(&thread, ¶ms, (void*(*)(void *))threadStartProc, param); pthread_attr_destroy(¶ms); *threadId = thread; //printf("CreateThread: %08X\n", (int32)(intptr)thread); return (void*)thread; } uint32 SuspendThread(HANDLE thread) { kern_return_t kernResult = thread_suspend((thread_act_t)(intptr)thread); BF_ASSERT(kernResult == KERN_SUCCESS); return 0; } uint32 ResumeThread(HANDLE thread) { kern_return_t kernResult = thread_resume((thread_act_t)(intptr)thread); BF_ASSERT(kernResult == KERN_SUCCESS); return 0; } #endif void Sleep(int32 ms) { usleep(ms * 1000); } struct BFFindFileData { DIR* mDirStruct; std::string mWildcard; }; HANDLE FindFirstFileW(wchar_t* lpFileName, WIN32_FIND_DATAW* lpFindFileData) { std::string findStr = Beefy::UTF8Encode(lpFileName); std::string wildcard; int lastSlashPos = std::max((int)findStr.rfind('/'), (int)findStr.rfind('\\')); if (lastSlashPos != -1) { wildcard = findStr.substr(lastSlashPos + 1); findStr = findStr.substr(0, lastSlashPos); } DIR* dir = opendir(findStr.c_str()); if (dir == NULL) { BFSetLastError(ERROR_FILE_NOT_FOUND); return INVALID_HANDLE_VALUE; } BFFindFileData* bfFindFileData = new BFFindFileData(); bfFindFileData->mDirStruct = dir; bfFindFileData->mWildcard = wildcard; if (!FindNextFileW((HANDLE)bfFindFileData, lpFindFileData)) { FindClose((HANDLE)bfFindFileData); BFSetLastError(ERROR_NO_MORE_FILES); return INVALID_HANDLE_VALUE; } return (HANDLE)bfFindFileData; } void BFSystemTimeToFileTime(time_t timeT, long nsec, FILETIME* lpFileTime) { uint64 ft64 = (timeT * 10000000ULL) + (nsec / 100); lpFileTime->dwHighDateTime = (uint32)(ft64 >> 32); lpFileTime->dwLowDateTime = (uint32)ft64; } void BFSystemTimeToFileTime(timespec& timeSpec, FILETIME* lpFileTime) { uint64 ft64 = (timeSpec.tv_nsec * 10000000ULL) + (timeSpec.tv_nsec / 100); lpFileTime->dwHighDateTime = (uint32)(ft64 >> 32); lpFileTime->dwLowDateTime = (uint32)ft64; } bool FindNextFileW(HANDLE hFindFile, WIN32_FIND_DATAW* lpFindFileData) { memset(lpFindFileData, 0, sizeof(WIN32_FIND_DATAW)); BFFindFileData* bfFindFileData = (BFFindFileData*)hFindFile; dirent* ent = NULL; while (true) { ent = readdir(bfFindFileData->mDirStruct); if (ent == NULL) return false; if (bfFindFileData->mWildcard == "*") break; std::string fileName = ent->d_name; if (bfFindFileData->mWildcard[0] == '*') { if (fileName.length() < bfFindFileData->mWildcard.length() - 1) continue; std::string checkFileName = fileName.substr(fileName.length() - bfFindFileData->mWildcard.length() + 1); if (checkFileName == bfFindFileData->mWildcard.substr(1)) break; } } mbstowcs(lpFindFileData->cFileName, ent->d_name, 1024); struct stat statbuf = {0}; int result = stat(ent->d_name, &statbuf); if (result == -1) return -1; if (S_ISDIR(statbuf.st_mode)) lpFindFileData->dwFileAttributes |= FILE_ATTRIBUTE_DIRECTORY; if (S_ISREG(statbuf.st_mode)) lpFindFileData->dwFileAttributes |= FILE_ATTRIBUTE_NORMAL; else if (!S_ISLNK(statbuf.st_mode)) lpFindFileData->dwFileAttributes |= FILE_ATTRIBUTE_DEVICE; if ((statbuf.st_mode & S_IRUSR) == 0) lpFindFileData->dwFileAttributes |= FILE_ATTRIBUTE_READONLY; lpFindFileData->nFileSizeLow = (int32)statbuf.st_size; lpFindFileData->nFileSizeHigh = (int32)(statbuf.st_size >> 32); BFSystemTimeToFileTime(statbuf.st_ctimespec, &lpFindFileData->ftCreationTime); BFSystemTimeToFileTime(statbuf.st_atimespec, &lpFindFileData->ftLastAccessTime); BFSystemTimeToFileTime(statbuf.st_mtimespec, &lpFindFileData->ftLastWriteTime); return true; } bool FindClose(HANDLE hFindFile) { BFFindFileData* bfFindFileData = (BFFindFileData*)hFindFile; closedir(bfFindFileData->mDirStruct); delete bfFindFileData; return true; } uint32 GetCurrentDirectoryW(uint32 nBufferLength, wchar_t* lpBuffer) { char str[2048]; getcwd(str, 2048); return (uint32)mbstowcs(lpBuffer, str, nBufferLength); } bool SetCurrentDirectoryW(wchar_t* lpBuffer) { if (chdir(Beefy::UTF8Encode(lpBuffer).c_str()) == 0) return true; BFSetLastError(ERROR_FILE_NOT_FOUND); return false; } bool CopyFileW(wchar_t* lpExistingFileName, wchar_t* lpNewFileName, bool allowOverwrite) {NOT_IMPL return true; } bool MoveFileW(wchar_t* lpExistingFileName, wchar_t* lpNewFileName) {NOT_IMPL return true; } bool DeleteFileW(wchar_t* lpFileName) {NOT_IMPL return true; } bool ReplaceFileW(wchar_t* lpReplacedFileName, wchar_t* lpReplacementFileName, wchar_t* lpBackupFileName, uint32 dwReplaceFlags, void* lpExclude, void* lpReserved) {NOT_IMPL return true; } bool SetFileAttributesW(wchar_t* lpFileName, uint32 dwFileAttributes) {NOT_IMPL return true; } int32 GetFileType(HANDLE fileHandle) { if (isatty((int)(intptr)fileHandle)) return FILE_TYPE_CHAR; return FILE_TYPE_DISK; } bool GetFileAttributesExW(wchar_t* lpFileName, GET_FILEEX_INFO_LEVELS fInfoLevelId, void* lpFileInformation) {NOT_IMPL return 0; } HANDLE CreateFileW(wchar_t* lpFileName, uint32 dwDesiredAccess, uint32 dwShareMode, SECURITY_ATTRIBUTES* lpSecurityAttributes, uint32 dwCreationDisposition, uint32 dwFlagsAndAttributes, HANDLE hTemplateFile) { std::string fileName = Beefy::UTF8Encode(lpFileName); int flags = 0; int mode = 0; if ((dwDesiredAccess & (GENERIC_READ | GENERIC_WRITE)) == (GENERIC_READ | GENERIC_WRITE)) flags |= O_RDWR; else if (dwDesiredAccess & GENERIC_READ) flags |= O_RDONLY; else if (dwDesiredAccess & GENERIC_WRITE) flags |= O_WRONLY; if (dwCreationDisposition == OPEN_ALWAYS) flags |= O_CREAT; else if (dwCreationDisposition == CREATE_ALWAYS) flags |= O_CREAT | O_TRUNC; else if (dwCreationDisposition == CREATE_NEW) flags |= O_CREAT | O_EXCL; else if (dwCreationDisposition == TRUNCATE_EXISTING) flags |= O_TRUNC; mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; return (HANDLE)(intptr)open(fileName.c_str(), flags, mode); } bool CreatePipe(HANDLE* hReadPipe, HANDLE* hWritePipe, SECURITY_ATTRIBUTES* lpPipeAttributes, uint32 nSize) {NOT_IMPL return true; } bool WriteFile(HANDLE hFile, void* lpBuffer, uint32 nNumberOfBytesToWrite, uint32* lpNumberOfBytesWritten, OVERLAPPED* lpOverlapped) { #ifdef BF_PLATFORM_IOS int logType = -1; if (hFile == (int*)STDOUT_FILENO) logType = LOG_WARNING; else if (hFile == (int*)STDERR_FILENO) logType = LOG_ERR; if (logType != -1) { static std::string strOut; strOut.resize(nNumberOfBytesToWrite); memcpy(&strOut[0], lpBuffer, nNumberOfBytesToWrite); if ((strOut[0] != '\r') && (strOut[0] != '\n')) syslog(LOG_WARNING, "%s", strOut.c_str()); } #endif int writeCount = (int)::write((int)(intptr)hFile, lpBuffer, nNumberOfBytesToWrite); if (writeCount == -1) { //TODO: set gBFPlatformLastError lpNumberOfBytesWritten = 0; return false; } *lpNumberOfBytesWritten = (uint32)writeCount; return true; } static bool doSleep = false; bool ReadFile(HANDLE hFile, void* lpBuffer, uint32 nNumberOfBytesToRead, uint32* lpNumberOfBytesRead, OVERLAPPED* lpOverlapped) { int readCount = (int)::read((int)(intptr)hFile, lpBuffer, nNumberOfBytesToRead); if (doSleep) Sleep(1000); if (readCount == -1) { //TODO: set gBFPlatformLastError lpNumberOfBytesRead = 0; return false; } *lpNumberOfBytesRead = (uint32)readCount; return true; } bool CloseHandle_File(HANDLE handle) { return close((int)(intptr)handle) == 0; } bool FlushFileBuffers(HANDLE handle) { return fsync((int)(intptr)handle) == 0; } int32 SetFilePointer(HANDLE handle, int32 distanceToMove, int32* distanceToMoveHigh, uint32 moveMethod) { return (int32)lseek((int)(intptr)handle, distanceToMove, (moveMethod == FILE_BEGIN) ? SEEK_SET : (moveMethod == FILE_CURRENT) ? SEEK_CUR : SEEK_END); } int32 GetFileSize(HANDLE hFile, uint32* fileSizeHigh) { *fileSizeHigh = 0; int32 oldPos = (int32)lseek((int)(intptr)hFile, 0, SEEK_CUR); int32 size = (int32)lseek((int)(intptr)hFile, 0, SEEK_END); lseek((int)(intptr)hFile, oldPos, SEEK_SET); return size; } bool SetEndOfFile(HANDLE hFile) { int32 curPos = (int32)lseek((int)(intptr)hFile, 0, SEEK_CUR); ftruncate((int)(intptr)hFile, curPos); return true; } bool SetFileTime(HANDLE hFile, const FILETIME* lpCreationTime, const FILETIME* lpLastAccessTime, const FILETIME* lpLastWriteTime) {NOT_IMPL return true; } bool LockFile(HANDLE hFile, uint32 dwFileOffsetLow, uint32 dwFileOffsetHigh, uint32 nNumberOfBytesToLockLow, uint32 nNumberOfBytesToLockHigh) {NOT_IMPL return true; } bool UnlockFile(HANDLE hFile, uint32 dwFileOffsetLow, uint32 dwFileOffsetHigh, uint32 nNumberOfBytesToUnlockLow, uint32 nNumberOfBytesToUnlockHigh) {NOT_IMPL return true; } bool DuplicateHandle(HANDLE hSourceProcessHandle, HANDLE hSourceHandle, HANDLE hTargetProcessHandle, HANDLE* lpTargetHandle, uint32 dwDesiredAccess, bool bInheritHandle, uint32 dwOptions) {NOT_IMPL return true; } int32 GetTempPath(int32 bufferLen, wchar_t* str) {NOT_IMPL return 0; } HANDLE CreateEventW(SECURITY_ATTRIBUTES* lpEventAttributes, bool bManualReset, bool bInitialState, wchar_t* lpName) { BF_ASSERT(lpName == NULL); Beefy::SyncEvent* syncEvent = new Beefy::SyncEvent(bManualReset, bInitialState); return syncEvent; } HANDLE OpenEventW(uint32 dwDesiredAccess, bool bInheritHandle, wchar_t* lpName) {NOT_IMPL return 0; } bool SetEvent(HANDLE handle) { ((Beefy::SyncEvent*)handle)->Set(); return true; } bool ResetEvent(HANDLE handle) { ((Beefy::SyncEvent*)handle)->Reset(); return true; } bool CloseHandle_Event(HANDLE handle) { delete (Beefy::SyncEvent*)handle; return true; } int WaitForSingleObject(HANDLE obj, int waitMs) { Beefy::SyncEvent* syncEvent = (Beefy::SyncEvent*)obj; bool worked = syncEvent->WaitFor(waitMs); return worked ? WAIT_OBJECT_0 : -1; } int WaitForSingleObject_Thread(HANDLE obj, int waitMs) { BF_ASSERT(waitMs == -1); //printf("WaitForSingleObject_Thread: %08X\n", (int32)(intptr)obj); int result = pthread_join((pthread_t)obj, NULL); BF_ASSERT(result == 0); return WAIT_OBJECT_0; } HANDLE CreateMutexW(SECURITY_ATTRIBUTES* lpMutexAttributes, bool bInitialOwner, wchar_t* lpName) {NOT_IMPL return 0; } HANDLE OpenMutexW(uint32 dwDesiredAccess, bool bInheritHandle, wchar_t* lpName) {NOT_IMPL return 0; } bool ReleaseMutex(HANDLE mutex) {NOT_IMPL return true; } uint32 FormatMessageW(uint32 dwFlags, void* lpSource, uint32 dwMessageId, uint32 dwLanguageId, wchar_t* lpBuffer, uint32 nSize, va_list* Arguments) {NOT_IMPL return 0; } int32 WSAGetLastError() {NOT_IMPL return 0; } void GetExitCodeProcess(HANDLE handle, DWORD* code) {NOT_IMPL } bool CloseHandle_Thread(HANDLE handle) {NOT_IMPL return true; } bool CloseHandle_Process(HANDLE handle) {NOT_IMPL return true; } bool GetProcessTimes(HANDLE handle, FILETIME* createTime, FILETIME* exitTime, FILETIME* kernelTime, FILETIME* userTime) {NOT_IMPL return true; } bool GetProcessWorkingSetSize(HANDLE handle, size_t* curMin, size_t* curMax) {NOT_IMPL return true; } bool SetProcessWorkingSetSize(HANDLE handle, size_t curMin, size_t curMax) {NOT_IMPL return true; } bool EnumProcessModules(HANDLE handle, HMODULE* mods, DWORD cb, DWORD* needed) {NOT_IMPL return true; } HANDLE OpenProcess(DWORD desiredAccess, bool inheritHandle, DWORD pid) {NOT_IMPL return 0; } bool GetModuleBaseNameW(HANDLE handle, HMODULE mod, wchar_t* modname, int maxLen) {NOT_IMPL return true; } bool GetModuleFileNameExW(HANDLE handle, HMODULE mod, wchar_t* modname, int maxLen) {NOT_IMPL return true; } bool GetModuleInformation(HANDLE handle, HMODULE mod, MODULEINFO* modinfo, int modInfoSize) {NOT_IMPL return true; } int GetPriorityClass(HANDLE handle) {NOT_IMPL return 0; } bool SetPriorityClass(HANDLE handle, int priClass) {NOT_IMPL return true; } bool TerminateProcess(HANDLE handle, int termCode) {NOT_IMPL return true; } bool WaitForInputIdle(HANDLE handle, int ms) {NOT_IMPL return true; } int32 GetCurrentProcessId() {NOT_IMPL return 0; } HANDLE GetCurrentProcess() {NOT_IMPL return 0; } bool GetDiskFreeSpaceExW(wchar_t* pathNameStr, ULARGE_INTEGER* wapi_free_bytes_avail, ULARGE_INTEGER*wapi_total_number_of_bytes, ULARGE_INTEGER* wapi_total_number_of_free_bytes) {NOT_IMPL return true; } uint32 GetDriveTypeW(wchar_t* driveName) {NOT_IMPL return 0; } bool GetVolumeInformationW(wchar_t* lpRootPathName, wchar_t* lpVolumeNameBuffer, uint32 nVolumeNameSize, uint32* lpVolumeSerialNumber, uint32* lpMaximumComponentLength, uint32* lpFileSystemFlags, wchar_t* lpFileSystemNameBuffer, uint32 nFileSystemNameSize) {NOT_IMPL return true; } uint64 BFClockGetTime() { static bool initialized = false; static clock_serv_t cclock; if (!initialized) { host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &cclock); initialized = true; } time_t rawtime; struct tm timeinfo; time(&rawtime); timeinfo = *localtime(&rawtime); mach_timespec_t mts; clock_get_time(cclock, &mts); //mach_port_deallocate(mach_task_self(), cclock); //if (timeinfo.tm_isdst) //mts.tv_sec += 60 * 60; return ((mts.tv_sec /*+ timeinfo.tm_gmtoff*/) * 10000000ULL) + (mts.tv_nsec / 100); } DWORD GetTimeZoneInformation(TIME_ZONE_INFORMATION* lpTimeZoneInformation) { std::wstring tzName0 = Beefy::UTF8Decode(tzname[0]); std::wstring tzName1 = Beefy::UTF8Decode(tzname[1]); bool isDST = false; time_t timeNow; time(&timeNow); tm tmNow = *gmtime(&timeNow); isDST = tmNow.tm_isdst; struct tm checkTM; memset(&checkTM, 0, sizeof(tm)); checkTM.tm_mday = 1; checkTM.tm_year = tmNow.tm_year; time_t checkTime = mktime(&checkTM); time_t lastOffset = 0; time_t minOffset = 0; time_t maxOffset = 0; for (int pass = 0; pass < 2; pass++) { int searchDir = 60*60*24; int thresholdCount = 0; while (true) { checkTime += searchDir; tm checkTM = *gmtime(&checkTime); if (checkTM.tm_year != tmNow.tm_year) break; // No DST mktime(&checkTM); time_t offset = checkTM.tm_gmtoff; if (lastOffset != offset) { if (thresholdCount == 0) { minOffset = offset; maxOffset = offset; } else if (thresholdCount == 3) { SYSTEMTIME* sysTimeP = (offset == minOffset) ? &lpTimeZoneInformation->StandardDate : &lpTimeZoneInformation->DaylightDate; if (offset == minOffset) tzName0 = Beefy::UTF8Decode(checkTM.tm_zone); else tzName1 = Beefy::UTF8Decode(checkTM.tm_zone); sysTimeP->wDay = 0; sysTimeP->wDayOfWeek = 0; sysTimeP->wYear = checkTM.tm_year + 1900; sysTimeP->wMonth = checkTM.tm_mon; sysTimeP->wDay = checkTM.tm_mday + 1; sysTimeP->wHour = checkTM.tm_hour; sysTimeP->wMinute = checkTM.tm_min; sysTimeP->wSecond = checkTM.tm_sec; sysTimeP->wMilliseconds = 0; break; } else { if (thresholdCount == 1) searchDir /= -24; else searchDir /= -60; minOffset = std::min(minOffset, offset); maxOffset = std::max(maxOffset, offset); } thresholdCount++; lastOffset = offset; } } } wcsncpy(lpTimeZoneInformation->StandardName, tzName0.c_str(), 32); wcsncpy(lpTimeZoneInformation->DaylightName, tzName1.c_str(), 32); lpTimeZoneInformation->DaylightBias = (int32)maxOffset; lpTimeZoneInformation->StandardBias = (int32)minOffset; if (minOffset == maxOffset) return 0; return isDST ? 2 : 1; } bool SystemTimeToFileTime(const SYSTEMTIME* lpSystemTime, FILETIME* lpFileTime) { tm checkTM; checkTM.tm_year = lpSystemTime->wYear - 1900; checkTM.tm_mon = lpSystemTime->wMonth; checkTM.tm_mday = lpSystemTime->wDay - 1; checkTM.tm_hour = lpSystemTime->wHour; checkTM.tm_min = lpSystemTime->wMinute; checkTM.tm_sec = lpSystemTime->wSecond; time_t timeT = mktime(&checkTM); uint64 ft64 = timeT * 10000000ULL; lpFileTime->dwHighDateTime = (uint32)(ft64 >> 32); lpFileTime->dwLowDateTime = (uint32)ft64; return true; } uint64 Beefy::BFGetTickCountMicro() { static bool initialized = false; static clock_serv_t cclock; if (!initialized) { host_get_clock_service(mach_host_self(), REALTIME_CLOCK, &cclock); initialized = true; } mach_timespec_t mts; clock_get_time(cclock, &mts); return (mts.tv_sec * 1000000ULL) + (mts.tv_nsec / 1000); } uint64 Beefy::BFGetTickCountMicroFast() { return BFGetTickCountMicro(); } #if (defined __IPHONEOS__) && !TARGET_IPHONE_SIMULATOR void BFGetThreadRegisters(HANDLE threadHandle, intptr* stackPtr, intptr* dataPtr) { mach_msg_type_number_t thread_state_count = ARM_UNIFIED_THREAD_STATE_COUNT; arm_unified_thread_state_t unifiedState; kern_return_t kernResult = thread_get_state((thread_act_t)(intptr)threadHandle, ARM_UNIFIED_THREAD_STATE, (natural_t*)&unifiedState.ts_32, &thread_state_count); #ifdef BF32 arm_thread_state32_t state = unifiedState.ts_32; #else zzz SHOULDN'T GET HERE arm_thread_state64_t state = unifiedState.ts_64; #endif BF_ASSERT(kernResult == KERN_SUCCESS); *stackPtr = (intptr)state.__sp; if (dataPtr != NULL) { #ifdef BF32 intptr* curPtr = dataPtr; *(curPtr++) = (intptr)state.__r[0]; *(curPtr++) = (intptr)state.__r[1]; *(curPtr++) = (intptr)state.__r[2]; *(curPtr++) = (intptr)state.__r[3]; *(curPtr++) = (intptr)state.__r[4]; *(curPtr++) = (intptr)state.__r[5]; *(curPtr++) = (intptr)state.__r[6]; *(curPtr++) = (intptr)state.__r[7]; *(curPtr++) = (intptr)state.__r[8]; *(curPtr++) = (intptr)state.__r[9]; *(curPtr++) = (intptr)state.__r[10]; *(curPtr++) = (intptr)state.__r[11]; *(curPtr++) = (intptr)state.__r[12]; *(curPtr++) = (intptr)state.__lr; *(curPtr++) = (intptr)state.__cpsr; #else intptr* curPtr = dataPtr; #endif int count = (int)(curPtr - dataPtr); BF_ASSERT(count == BF_REGISTER_COUNT); } } #else void BFGetThreadRegisters(HANDLE threadHandle, intptr* stackPtr, intptr* dataPtr) { #ifdef BF32 mach_msg_type_number_t thread_state_count = x86_THREAD_STATE32_COUNT; x86_thread_state32_t state; kern_return_t kernResult = thread_get_state((thread_act_t)threadHandle, x86_THREAD_STATE32, (natural_t*)&state, &thread_state_count); #else mach_msg_type_number_t thread_state_count = x86_THREAD_STATE64_COUNT; x86_thread_state64_t state; kern_return_t kernResult = thread_get_state((thread_act_t)threadHandle, x86_THREAD_STATE64, (natural_t*)&state, &thread_state_count); #endif BF_ASSERT(kernResult == KERN_SUCCESS); *stackPtr = (intptr)state.__esp; if (dataPtr != NULL) { #ifdef BF32 intptr* curPtr = dataPtr; *(curPtr++) = (intptr)state.__eax; *(curPtr++) = (intptr)state.__ebx; *(curPtr++) = (intptr)state.__ecx; *(curPtr++) = (intptr)state.__edx; *(curPtr++) = (intptr)state.__esi; *(curPtr++) = (intptr)state.__edi; *(curPtr++) = (intptr)state.__ebp; #else intptr* curPtr = dataPtr; *(curPtr++) = (intptr)ctx.Rax; *(curPtr++) = (intptr)ctx.Rbx; *(curPtr++) = (intptr)ctx.Rcx; *(curPtr++) = (intptr)ctx.Rdx; *(curPtr++) = (intptr)ctx.Rsi; *(curPtr++) = (intptr)ctx.Rdi; *(curPtr++) = (intptr)ctx.Rbp; *(curPtr++) = (intptr)ctx.R8; *(curPtr++) = (intptr)ctx.R9; *(curPtr++) = (intptr)ctx.R10; *(curPtr++) = (intptr)ctx.R11; *(curPtr++) = (intptr)ctx.R12; *(curPtr++) = (intptr)ctx.R13; *(curPtr++) = (intptr)ctx.R14; *(curPtr++) = (intptr)ctx.R15; #endif int count = curPtr - dataPtr; BF_ASSERT(count == BF_REGISTER_COUNT); } } #endif int64 abs(int64 val) { return llabs(val); } void mkdir(const char* path) { mkdir(path, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); }