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