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