]> git.jsancho.org Git - lugaru.git/blob - Source/MacCompatibility.cpp
Added GPL license and headers.
[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         {
67                 counterRate = 1;
68                 baseCounter = 0;
69                 QueryPerformanceFrequency( (LARGE_INTEGER*)&counterRate);
70                 QueryPerformanceCounter( (LARGE_INTEGER*)&baseCounter);
71         }
72         __int64 counterRate;            // LARGE_INTEGER type has no math functions so use int64
73         __int64 baseCounter;
74 };
75 static AppTime g_appTime;
76
77
78 void CopyCStringToPascal( const char* src, unsigned char dst[256])
79 {
80         int len = strlen( src);
81         dst[ 0] = len;
82         memcpy( dst + 1, src, len);
83 }
84
85
86 void CopyPascalStringToC( const unsigned char* src, char* dst)
87 {
88         int len = src[ 0];
89         memcpy( dst, src + 1, len);
90         dst[ len] = 0;
91 }
92
93
94 AbsoluteTime UpTime()
95 {
96         __int64 counter;
97         QueryPerformanceCounter( (LARGE_INTEGER*)&counter);
98
99         counter -= g_appTime.baseCounter;
100
101         AbsoluteTime time;
102         time.lo = (unsigned long)counter;
103         time.hi = (unsigned long)(counter >> 32);
104         return time;
105 }
106
107
108 Duration AbsoluteDeltaToDuration( AbsoluteTime& a, AbsoluteTime& b)
109 {
110         __int64 value = a.hi;
111         value <<= 32;
112         value |= a.lo;
113         __int64 value2 = b.hi;
114         value2 <<= 32;
115         value2 |= b.lo;
116         value -= value2;
117
118         if (value <= 0)
119                 return durationImmediate;
120
121         __int64 frac = value % g_appTime.counterRate;
122         value /= g_appTime.counterRate;
123
124         Duration time;
125
126         if (value == 0)
127         {
128                 frac *= -1000000;
129                 frac /= g_appTime.counterRate;
130                 time = (Duration)frac;
131         }
132         else
133         {
134                 frac *= 1000;
135                 frac /= g_appTime.counterRate;
136                 value *= 1000;
137                 value += frac;
138                 time = (Duration)value;
139         }
140
141         return time;
142 }
143
144
145 #if PLATFORM_UNIX
146 #include <sys/types.h>
147 #include <pwd.h>
148 #include <fcntl.h>
149 #include <unistd.h>
150 #include <dirent.h>
151
152 // some but not all of this is code from PhysicsFS: http://icculus.org/physfs/
153 //  the zlib license on physfs allows this cut-and-pasting.
154 static int locateOneElement(char *buf)
155 {
156     char *ptr;
157     char **rc;
158     char **i;
159     DIR *dirp;
160
161     //if (PHYSFS_exists(buf))
162     if (access(buf, F_OK) == 0)
163         return(1);  /* quick rejection: exists in current case. */
164
165     ptr = strrchr(buf, '/');  /* find entry at end of path. */
166     if (ptr == NULL)
167     {
168         dirp = opendir(".");
169         ptr = buf;
170     } /* if */
171     else
172     {
173         *ptr = '\0';
174         dirp = opendir(buf);
175         *ptr = '/';
176         ptr++;  /* point past dirsep to entry itself. */
177     } /* else */
178
179     struct dirent *dent;
180     while ((dent = readdir(dirp)) != NULL)
181     {
182         if (stricmp(dent->d_name, ptr) == 0)
183         {
184             strcpy(ptr, dent->d_name); /* found a match. Overwrite with this case. */
185             closedir(dirp);
186             return(1);
187         } /* if */
188     } /* for */
189
190     /* no match at all... */
191     closedir(dirp);
192     return(0);
193 } /* locateOneElement */
194
195
196 static inline const char *getUserDirByUID(void)
197 {
198     struct passwd *pw = getpwuid(getuid());
199     if (pw != NULL)
200         return(pw->pw_dir);
201     return(NULL);
202 } /* getUserDirByUID */
203
204
205 static inline const char *getPrefPath(void)
206 {
207     static char *prefpath = NULL;
208     if (prefpath == NULL)
209     {
210         const char *homedir = getenv("HOME");
211         if (homedir == NULL)
212             homedir = getUserDirByUID();
213         if (homedir == NULL)
214             homedir = ".";  // oh well.
215
216 #if (defined(__APPLE__) && defined(__MACH__))
217         const char *PREFPATHNAME = "Library/Application Support/Lugaru";
218 #else
219         const char *PREFPATHNAME = ".lugaru";
220 #endif
221         size_t len = strlen(homedir) + strlen(PREFPATHNAME) + 2;
222         prefpath = new char[len];
223         snprintf(prefpath, len, "%s/%s", homedir, PREFPATHNAME);
224     }
225     return(prefpath);
226 }
227
228 static int locateCorrectCase(char *buf, bool makedirs)
229 {
230     int rc;
231     char *ptr;
232     char *prevptr;
233
234     ptr = prevptr = buf;
235     while (ptr = strchr(ptr + 1, '/'))
236     {
237         *ptr = '\0';  /* block this path section off */
238         rc = locateOneElement(buf);
239         if (!rc)
240         {
241             if (makedirs)  /* normal if we're writing; build dirs! */
242                 mkdir(buf, S_IRWXU);
243             else
244             {
245                 *ptr = '/'; /* restore path separator */
246                 return(-2);  /* missing element in path. */
247             } /* else */
248         } /* if */
249         *ptr = '/'; /* restore path separator */
250     } /* while */
251
252     /* check final element... */
253     return(locateOneElement(buf) ? 0 : -1);
254 }
255
256
257 static int locateCorrectFile(char *buf, const char *mode)
258 {
259     if (*buf == '\0')
260         return(0);  /* Uh...I guess that's failure. */
261
262     assert((mode[0] == 'w') || (mode[0] == 'r'));
263
264     bool iswriting = (mode[0] == 'w');
265     const char *prefpath = getPrefPath();
266     size_t len = strlen(buf) + strlen(prefpath) + 2;
267     char *prefpathfile = (char *) alloca(len);
268     snprintf(prefpathfile, len, "%s/%s", prefpath, buf);
269
270     int rc = locateCorrectCase(prefpathfile, iswriting);  /* favor prefpath. */
271     if ( (rc == 0) || ((rc == -1) && (iswriting)) ) // found or create?
272         strcpy(buf, prefpathfile);
273     else if ((rc < 0) && (!iswriting))  /* not writing? Try game dir... */
274         rc = locateCorrectCase(buf, iswriting);
275
276     return(rc);
277 } /* locateCorrectFile */
278 #endif
279
280
281 static char g_filename[4096];
282 char* ConvertFileName( const char* orgfilename, const char *mode)
283 {
284     if (orgfilename == g_filename) // recursion?
285         return g_filename;
286
287         // translate filename into proper path name
288         if (orgfilename[ 0] == ':')
289                 orgfilename++;
290         strcpy( g_filename, orgfilename);
291
292         for (int n = 0; g_filename[ n]; n++)
293         {
294                 if (g_filename[ n] == ':')
295                         g_filename[ n] = '/';
296
297                 else if (g_filename[ n] == '\\')
298                         g_filename[ n] = '/';
299         }
300
301     #if PLATFORM_UNIX
302     locateCorrectFile(g_filename, mode);
303     #endif
304
305         return g_filename;
306 }
307
308 #endif
309
310