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