]> git.jsancho.org Git - lugaru.git/blob - Source/MacCompatibility.cpp
Removed obsolete PLATFORM_MACOSX code
[lugaru.git] / Source / MacCompatibility.cpp
1 /*
2 Copyright (C) 2003, 2010 - Wolfire Games
3
4 This file is part of Lugaru.
5
6 Lugaru is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 Lugaru is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with Lugaru.  If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 /**> HEADER FILES <**/
21 #include "MacCompatibility.h"
22
23 #ifdef WIN32
24 #include <windows.h>
25 #endif
26
27 #include <errno.h>
28 #include <time.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32
33 #if PLATFORM_UNIX
34 #include <unistd.h>
35 #include <sys/time.h>
36 #include <sys/stat.h>
37 #include <assert.h>
38 typedef long long __int64;
39 typedef __int64 LARGE_INTEGER;
40 static int QueryPerformanceFrequency(LARGE_INTEGER *liptr)
41 {
42     assert(sizeof (__int64) == 8);
43     assert(sizeof (LARGE_INTEGER) == 8);
44     *liptr = 1000;
45     return(1);
46 }
47
48 static int QueryPerformanceCounter(LARGE_INTEGER *liptr)
49 {
50     struct timeval tv;
51     gettimeofday(&tv, NULL);
52     *liptr = ( (((LARGE_INTEGER) tv.tv_sec) * 1000) +
53                (((LARGE_INTEGER) tv.tv_usec) / 1000) );
54     return(1);
55 }
56 #endif
57
58 class AppTime
59 {
60 public:
61     AppTime() {
62         counterRate = 1;
63         baseCounter = 0;
64         QueryPerformanceFrequency( (LARGE_INTEGER*)&counterRate);
65         QueryPerformanceCounter( (LARGE_INTEGER*)&baseCounter);
66     }
67     __int64 counterRate; // LARGE_INTEGER type has no math functions so use int64
68     __int64 baseCounter;
69 };
70 static AppTime g_appTime;
71
72
73 void CopyCStringToPascal( const char* src, unsigned char dst[256])
74 {
75     int len = strlen( src);
76     dst[ 0] = len;
77     memcpy( dst + 1, src, len);
78 }
79
80
81 void CopyPascalStringToC( const unsigned char* src, char* dst)
82 {
83     int len = src[ 0];
84     memcpy( dst, src + 1, len);
85     dst[ len] = 0;
86 }
87
88
89 AbsoluteTime UpTime()
90 {
91     __int64 counter;
92     QueryPerformanceCounter( (LARGE_INTEGER*)&counter);
93
94     counter -= g_appTime.baseCounter;
95
96     AbsoluteTime time;
97     time.lo = (unsigned long)counter;
98     time.hi = (unsigned long)(counter >> 32);
99     return time;
100 }
101
102
103 Duration AbsoluteDeltaToDuration( AbsoluteTime& a, AbsoluteTime& b)
104 {
105     __int64 value = a.hi;
106     value <<= 32;
107     value |= a.lo;
108     __int64 value2 = b.hi;
109     value2 <<= 32;
110     value2 |= b.lo;
111     value -= value2;
112
113     if (value <= 0)
114         return durationImmediate;
115
116     __int64 frac = value % g_appTime.counterRate;
117     value /= g_appTime.counterRate;
118
119     Duration time;
120
121     if (value == 0) {
122         frac *= -1000000;
123         frac /= g_appTime.counterRate;
124         time = (Duration)frac;
125     } else {
126         frac *= 1000;
127         frac /= g_appTime.counterRate;
128         value *= 1000;
129         value += frac;
130         time = (Duration)value;
131     }
132
133     return time;
134 }
135
136
137 #if PLATFORM_UNIX
138 #include <sys/types.h>
139 #include <pwd.h>
140 #include <fcntl.h>
141 #include <unistd.h>
142 #include <dirent.h>
143
144 // some but not all of this is code from PhysicsFS: http://icculus.org/physfs/
145 //  the zlib license on physfs allows this cut-and-pasting.
146 static int locateOneElement(char *buf)
147 {
148     char *ptr;
149     DIR *dirp;
150
151     //if (PHYSFS_exists(buf))
152     if (access(buf, F_OK) == 0)
153         return(1);  /* quick rejection: exists in current case. */
154
155     ptr = strrchr(buf, '/');  /* find entry at end of path. */
156     if (ptr == NULL) {
157         dirp = opendir(".");
158         ptr = buf;
159     } /* if */
160     else {
161         *ptr = '\0';
162         dirp = opendir(buf);
163         *ptr = '/';
164         ptr++;  /* point past dirsep to entry itself. */
165     } /* else */
166
167     struct dirent *dent;
168     while ((dent = readdir(dirp)) != NULL) {
169         if (strcasecmp(dent->d_name, ptr) == 0) {
170             strcpy(ptr, dent->d_name); /* found a match. Overwrite with this case. */
171             closedir(dirp);
172             return(1);
173         } /* if */
174     } /* for */
175
176     /* no match at all... */
177     closedir(dirp);
178     return(0);
179 } /* locateOneElement */
180
181
182 static inline const char *getUserDirByUID(void)
183 {
184     struct passwd *pw = getpwuid(getuid());
185     if (pw != NULL)
186         return(pw->pw_dir);
187     return(NULL);
188 } /* getUserDirByUID */
189
190
191 static inline const char *getPrefPath(void)
192 {
193     static char *prefpath = NULL;
194     if (prefpath == NULL) {
195         const char *homedir = getenv("HOME");
196         if (homedir == NULL)
197             homedir = getUserDirByUID();
198         if (homedir == NULL)
199             homedir = ".";  // oh well.
200
201 #if (defined(__APPLE__) && defined(__MACH__))
202         const char *PREFPATHNAME = "Library/Application Support/Lugaru";
203 #else
204         const char *PREFPATHNAME = ".lugaru";
205 #endif
206         size_t len = strlen(homedir) + strlen(PREFPATHNAME) + 2;
207         prefpath = new char[len];
208         snprintf(prefpath, len, "%s/%s", homedir, PREFPATHNAME);
209     }
210     return(prefpath);
211 }
212
213 static int locateCorrectCase(char *buf, bool makedirs)
214 {
215     int rc;
216     char *ptr = buf;
217
218     while (ptr = strchr(ptr + 1, '/')) {
219         *ptr = '\0';  /* block this path section off */
220         rc = locateOneElement(buf);
221         if (!rc) {
222             if (makedirs)  /* normal if we're writing; build dirs! */
223                 mkdir(buf, S_IRWXU);
224             else {
225                 *ptr = '/'; /* restore path separator */
226                 return(-2);  /* missing element in path. */
227             } /* else */
228         } /* if */
229         *ptr = '/'; /* restore path separator */
230     } /* while */
231
232     /* check final element... */
233     return(locateOneElement(buf) ? 0 : -1);
234 }
235
236
237 static int locateCorrectFile(char *buf, const char *mode)
238 {
239     if (*buf == '\0')
240         return(0);  /* Uh...I guess that's failure. */
241
242     assert((mode[0] == 'w') || (mode[0] == 'r'));
243
244     bool iswriting = (mode[0] == 'w');
245     const char *prefpath = getPrefPath();
246     size_t len = strlen(buf) + strlen(prefpath) + 2;
247     char *prefpathfile = (char *) alloca(len);
248     snprintf(prefpathfile, len, "%s/%s", prefpath, buf);
249
250     int rc = locateCorrectCase(prefpathfile, iswriting);  /* favor prefpath. */
251     if ( (rc == 0) || ((rc == -1) && (iswriting)) ) // found or create?
252         strcpy(buf, prefpathfile);
253     else if ((rc < 0) && (!iswriting))  /* not writing? Try game dir... */
254         rc = locateCorrectCase(buf, iswriting);
255
256     return(rc);
257 } /* locateCorrectFile */
258 #endif
259
260
261 static char g_filename[4096];
262 char* ConvertFileName( const char* orgfilename, const char *mode)
263 {
264     if (orgfilename == g_filename) // recursion?
265         return g_filename;
266
267     // translate filename into proper path name
268     if (orgfilename[ 0] == ':')
269         orgfilename++;
270     strcpy( g_filename, orgfilename);
271
272     for (int n = 0; g_filename[ n]; n++) {
273         if (g_filename[ n] == ':')
274             g_filename[ n] = '/';
275
276         else if (g_filename[ n] == '\\')
277             g_filename[ n] = '/';
278     }
279
280 #if PLATFORM_UNIX
281     locateCorrectFile(g_filename, mode);
282 #endif
283
284     return g_filename;
285 }