X-Git-Url: https://git.jsancho.org/?a=blobdiff_plain;f=Source%2FMacCompatibility.cpp;h=ea8ba749c12d655499360cb2f7401d376d5d9d7a;hb=211943fca2a77110d07c4eab259ed0208462766e;hp=b05d2b91bc27541fbc6ebec0459dce6a648b6685;hpb=68db9594c12cd81dd246c2c0c511a499ac04b2fd;p=lugaru.git diff --git a/Source/MacCompatibility.cpp b/Source/MacCompatibility.cpp index b05d2b9..ea8ba74 100644 --- a/Source/MacCompatibility.cpp +++ b/Source/MacCompatibility.cpp @@ -1,4 +1,22 @@ -#if !PLATFORM_MACOSX +/* +Copyright (C) 2003, 2010 - Wolfire Games +Copyright (C) 2010-2016 - Lugaru contributors (see AUTHORS file) + +This file is part of Lugaru. + +Lugaru is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +Lugaru is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Lugaru. If not, see . +*/ /**> HEADER FILES <**/ #include "MacCompatibility.h" @@ -16,6 +34,7 @@ #if PLATFORM_UNIX #include #include +#include #include typedef long long __int64; typedef __int64 LARGE_INTEGER; @@ -40,110 +59,88 @@ static int QueryPerformanceCounter(LARGE_INTEGER *liptr) class AppTime { public: - AppTime() - { - counterRate = 1; - baseCounter = 0; - QueryPerformanceFrequency( (LARGE_INTEGER*)&counterRate); - QueryPerformanceCounter( (LARGE_INTEGER*)&baseCounter); - } - __int64 counterRate; // LARGE_INTEGER type has no math functions so use int64 - __int64 baseCounter; + AppTime() { + counterRate = 1; + baseCounter = 0; + QueryPerformanceFrequency( (LARGE_INTEGER*)&counterRate); + QueryPerformanceCounter( (LARGE_INTEGER*)&baseCounter); + } + __int64 counterRate; // LARGE_INTEGER type has no math functions so use int64 + __int64 baseCounter; }; static AppTime g_appTime; - -void CopyCStringToPascal( const char* src, unsigned char dst[256]) -{ - int len = strlen( src); - dst[ 0] = len; - memcpy( dst + 1, src, len); -} - - -void CopyPascalStringToC( const unsigned char* src, char* dst) -{ - int len = src[ 0]; - memcpy( dst, src + 1, len); - dst[ len] = 0; -} - - AbsoluteTime UpTime() { - __int64 counter; - QueryPerformanceCounter( (LARGE_INTEGER*)&counter); + __int64 counter; + QueryPerformanceCounter( (LARGE_INTEGER*)&counter); - counter -= g_appTime.baseCounter; + counter -= g_appTime.baseCounter; - AbsoluteTime time; - time.lo = (unsigned long)counter; - time.hi = (unsigned long)(counter >> 32); - return time; + AbsoluteTime time; + time.lo = (unsigned long)counter; + time.hi = (unsigned long)(counter >> 32); + return time; } Duration AbsoluteDeltaToDuration( AbsoluteTime& a, AbsoluteTime& b) { - __int64 value = a.hi; - value <<= 32; - value |= a.lo; - __int64 value2 = b.hi; - value2 <<= 32; - value2 |= b.lo; - value -= value2; - - if (value <= 0) - return durationImmediate; - - __int64 frac = value % g_appTime.counterRate; - value /= g_appTime.counterRate; - - Duration time; - - if (value == 0) - { - frac *= -1000000; - frac /= g_appTime.counterRate; - time = (Duration)frac; - } - else - { - frac *= 1000; - frac /= g_appTime.counterRate; - value *= 1000; - value += frac; - time = (Duration)value; - } - - return time; + __int64 value = a.hi; + value <<= 32; + value |= a.lo; + __int64 value2 = b.hi; + value2 <<= 32; + value2 |= b.lo; + value -= value2; + + if (value <= 0) + return durationImmediate; + + __int64 frac = value % g_appTime.counterRate; + value /= g_appTime.counterRate; + + Duration time; + + if (value == 0) { + frac *= -1000000; + frac /= g_appTime.counterRate; + time = (Duration)frac; + } else { + frac *= 1000; + frac /= g_appTime.counterRate; + value *= 1000; + value += frac; + time = (Duration)value; + } + + return time; } #if PLATFORM_UNIX #include +#include +#include +#include #include -// public domain code from PhysicsFS: http://icculus.org/physfs/ +// some but not all of this is code from PhysicsFS: http://icculus.org/physfs/ +// the zlib license on physfs allows this cut-and-pasting. static int locateOneElement(char *buf) { char *ptr; - char **rc; - char **i; DIR *dirp; - //if (PHYSFS_exists(buf)) if (access(buf, F_OK) == 0) return(1); /* quick rejection: exists in current case. */ ptr = strrchr(buf, '/'); /* find entry at end of path. */ - if (ptr == NULL) - { + if (ptr == NULL) { dirp = opendir("."); ptr = buf; } /* if */ - else - { + else { *ptr = '\0'; dirp = opendir(buf); *ptr = '/'; @@ -151,10 +148,8 @@ static int locateOneElement(char *buf) } /* else */ struct dirent *dent; - while ((dent = readdir(dirp)) != NULL) - { - if (stricmp(dent->d_name, ptr) == 0) - { + while ((dent = readdir(dirp)) != NULL) { + if (strcasecmp(dent->d_name, ptr) == 0) { strcpy(ptr, dent->d_name); /* found a match. Overwrite with this case. */ closedir(dirp); return(1); @@ -167,52 +162,107 @@ static int locateOneElement(char *buf) } /* locateOneElement */ -static inline int PHYSFSEXT_locateCorrectCase(char *buf) +static inline const char *getUserDirByUID(void) { - int rc; - char *ptr; - char *prevptr; + struct passwd *pw = getpwuid(getuid()); + if (pw != NULL) + return(pw->pw_dir); + return(NULL); +} /* getUserDirByUID */ + - ptr = prevptr = buf; - if (*ptr == '\0') - return(0); /* Uh...I guess that's success. */ +static inline const char *getPrefPath(void) +{ + static char *prefpath = NULL; + if (prefpath == NULL) { + const char *homedir = getenv("HOME"); + if (homedir == NULL) + homedir = getUserDirByUID(); + if (homedir == NULL) + homedir = "."; // oh well. + +#if (defined(__APPLE__) && defined(__MACH__)) + const char *PREFPATHNAME = "Library/Application Support/Lugaru"; +#else + const char *PREFPATHNAME = ".lugaru"; +#endif + size_t len = strlen(homedir) + strlen(PREFPATHNAME) + 2; + prefpath = new char[len]; + snprintf(prefpath, len, "%s/%s", homedir, PREFPATHNAME); + } + return(prefpath); +} - while (ptr = strchr(ptr + 1, '/')) - { +static int locateCorrectCase(char *buf, bool makedirs) +{ + int rc; + char *ptr = buf; + + while (ptr = strchr(ptr + 1, '/')) { *ptr = '\0'; /* block this path section off */ rc = locateOneElement(buf); + if (!rc) { + if (makedirs) /* normal if we're writing; build dirs! */ + mkdir(buf, S_IRWXU); + else { + *ptr = '/'; /* restore path separator */ + return(-2); /* missing element in path. */ + } /* else */ + } /* if */ *ptr = '/'; /* restore path separator */ - if (!rc) - return(-2); /* missing element in path. */ } /* while */ /* check final element... */ return(locateOneElement(buf) ? 0 : -1); -} /* PHYSFSEXT_locateCorrectCase */ -#endif +} -static char g_filename[ 256]; -char* ConvertFileName( const char* orgfilename) +static int locateCorrectFile(char *buf, const char *mode) { - // translate filename into proper path name - if (orgfilename[ 0] == ':') - orgfilename++; - strcpy( g_filename, orgfilename); - - for (int n = 0; g_filename[ n]; n++) - { - if (g_filename[ n] == ':') - g_filename[ n] = '/'; - } - - #if PLATFORM_UNIX - PHYSFSEXT_locateCorrectCase(g_filename); - #endif - - return g_filename; -} + if (*buf == '\0') + return(0); /* Uh...I guess that's failure. */ + + assert((mode[0] == 'w') || (mode[0] == 'r')); + + bool iswriting = (mode[0] == 'w'); + const char *prefpath = getPrefPath(); + size_t len = strlen(buf) + strlen(prefpath) + 2; + char *prefpathfile = (char *) alloca(len); + snprintf(prefpathfile, len, "%s/%s", prefpath, buf); + + int rc = locateCorrectCase(prefpathfile, iswriting); /* favor prefpath. */ + if ( (rc == 0) || ((rc == -1) && (iswriting)) ) // found or create? + strcpy(buf, prefpathfile); + else if ((rc < 0) && (!iswriting)) /* not writing? Try game dir... */ + rc = locateCorrectCase(buf, iswriting); + return(rc); +} /* locateCorrectFile */ #endif +static char g_filename[4096]; +char* ConvertFileName( const char* orgfilename, const char *mode) +{ + if (orgfilename == g_filename) // recursion? + return g_filename; + + // translate filename into proper path name + if (orgfilename[ 0] == ':') + orgfilename++; + strcpy( g_filename, orgfilename); + + for (int n = 0; g_filename[ n]; n++) { + if (g_filename[ n] == ':') + g_filename[ n] = '/'; + + else if (g_filename[ n] == '\\') + g_filename[ n] = '/'; + } + +#if PLATFORM_UNIX + locateCorrectFile(g_filename, mode); +#endif + + return g_filename; +}