]> icculus.org git repositories - btb/d2x.git/blob - include/physfsx.h
use the orientation parameter of g3_draw_bitmap
[btb/d2x.git] / include / physfsx.h
1
2 /*
3  *
4  * Some simple physfs extensions
5  *
6  */
7
8 #ifndef PHYSFSX_H
9 #define PHYSFSX_H
10
11 #if !defined(macintosh) && !defined(_MSC_VER)
12 #include <sys/param.h>
13 #endif
14 #if defined(__linux__)
15 #include <sys/vfs.h>
16 #elif defined(__MACH__) && defined(__APPLE__)
17 #include <sys/mount.h>
18 #endif
19 #include <string.h>
20 #include <stdarg.h>
21
22 #include <physfs.h>
23
24 #include "pstypes.h"
25 #include "dxxerror.h"
26 #include "vecmat.h"
27 #include "args.h"
28
29 // Initialise PhysicsFS, set up basic search paths and add arguments from .ini file(s).
30 // The arguments are used to determine the search paths, so the first .ini file must be
31 // in the same directory as D2X. A second one can be in the user directory.
32 static inline void PHYSFSX_init(int argc, char *argv[])
33 {
34         int t;
35
36         PHYSFS_init(argv[0]);
37         PHYSFS_permitSymbolicLinks(1);
38
39         PHYSFS_addToSearchPath(PHYSFS_getBaseDir(), 1);
40         InitArgs( argc,argv );
41
42         if ((t = FindArg("-userdir"))
43 #ifdef __unix__
44                 || 1    // or if it's a unix platform
45 #endif
46                 )
47         {
48                 // This stuff below seems overly complicated - brad
49
50                 char *path = Args[t+1];
51                 char fullPath[PATH_MAX + 5];
52
53 #ifdef __unix__
54                 if (!t)
55                         path = "~/.d2x";
56 #endif
57                 PHYSFS_removeFromSearchPath(PHYSFS_getBaseDir());
58
59                 if (path[0] == '~') // yes, this tilde can be put before non-unix paths.
60                 {
61                         const char *home = PHYSFS_getUserDir();
62
63                         strcpy(fullPath, home); // prepend home to the path
64                         path++;
65                         if (*path == *PHYSFS_getDirSeparator())
66                                 path++;
67                         strncat(fullPath, path, PATH_MAX + 5 - strlen(home));
68                 }
69                 else
70                         strncpy(fullPath, path, PATH_MAX + 5);
71
72                 PHYSFS_setWriteDir(fullPath);
73                 if (!PHYSFS_getWriteDir())
74                 {                                               // need to make it
75                         char *p;
76                         char ancestor[PATH_MAX + 5];    // the directory which actually exists
77                         char child[PATH_MAX + 5];               // the directory relative to the above we're trying to make
78
79                         strcpy(ancestor, fullPath);
80                         while (!PHYSFS_getWriteDir() && ((p = strrchr(ancestor, *PHYSFS_getDirSeparator()))))
81                         {
82                                 if (p[1] == 0)
83                                 {                                       // separator at the end (intended here, for safety)
84                                         *p = 0;                 // kill this separator
85                                         if (!((p = strrchr(ancestor, *PHYSFS_getDirSeparator()))))
86                                                 break;          // give up, this is (usually) the root directory
87                                 }
88
89                                 p[1] = 0;                       // go to parent
90                                 PHYSFS_setWriteDir(ancestor);
91                         }
92
93                         strcpy(child, fullPath + strlen(ancestor));
94                         for (p = child; (p = strchr(p, *PHYSFS_getDirSeparator())); p++)
95                                 *p = '/';
96                         PHYSFS_mkdir(child);
97                         PHYSFS_setWriteDir(fullPath);
98                 }
99
100                 PHYSFS_addToSearchPath(PHYSFS_getWriteDir(), 1);
101                 AppendArgs();
102         }
103
104         if (!PHYSFS_getWriteDir())
105         {
106                 PHYSFS_setWriteDir(PHYSFS_getBaseDir());
107                 if (!PHYSFS_getWriteDir())
108                         Error("can't set write dir\n");
109                 else
110                         PHYSFS_addToSearchPath(PHYSFS_getWriteDir(), 0);
111         }
112
113         //tell cfile where hogdir is
114         if ((t=FindArg("-hogdir")))
115                 PHYSFS_addToSearchPath(Args[t + 1], 1);
116 #ifdef __unix__
117         else if (!FindArg("-nohogdir"))
118                 PHYSFS_addToSearchPath(SHAREPATH, 1);
119 #endif
120 #ifdef MACINTOSH
121         PHYSFS_addToSearchPath(":Data:", 1); // untested
122 #endif
123 }
124
125 static inline PHYSFS_sint64 PHYSFSX_readString(PHYSFS_file *file, char *s)
126 {
127         char *ptr = s;
128
129         if (PHYSFS_eof(file))
130                 *ptr = 0;
131         else
132                 do
133                         PHYSFS_read(file, ptr, 1, 1);
134                 while (!PHYSFS_eof(file) && *ptr++ != 0);
135
136         return strlen(s);
137 }
138
139 static inline PHYSFS_sint64 PHYSFSX_gets(PHYSFS_file *file, char *s)
140 {
141         char *ptr = s;
142
143         if (PHYSFS_eof(file))
144                 *ptr = 0;
145         else
146                 do
147                         PHYSFS_read(file, ptr, 1, 1);
148                 while (!PHYSFS_eof(file) && *ptr++ != '\n');
149         *ptr = 0;
150
151         return strlen(s);
152 }
153
154 static inline PHYSFS_sint64 PHYSFSX_writeU8(PHYSFS_file *file, PHYSFS_uint8 val)
155 {
156         return PHYSFS_write(file, &val, 1, 1);
157 }
158
159 static inline PHYSFS_sint64 PHYSFSX_writeString(PHYSFS_file *file, const char *s)
160 {
161         return PHYSFS_write(file, s, 1, (PHYSFS_uint32)strlen(s) + 1);
162 }
163
164 static inline PHYSFS_sint64 PHYSFSX_puts(PHYSFS_file *file, const char *s)
165 {
166         return PHYSFS_write(file, s, 1, (PHYSFS_uint32)strlen(s));
167 }
168
169 static inline int PHYSFSX_putc(PHYSFS_file *file, int c)
170 {
171         unsigned char ch = (unsigned char)c;
172
173         if (PHYSFS_write(file, &ch, 1, 1) < 1)
174                 return -1;
175         else
176                 return (int)c;
177 }
178
179 static inline PHYSFS_sint64 PHYSFSX_printf(PHYSFS_file *file, const char *format, ...)
180 {
181         char buffer[1024];
182         va_list args;
183
184         va_start(args, format);
185         vsprintf(buffer, format, args);
186
187         return PHYSFSX_puts(file, buffer);
188 }
189
190 #define PHYSFSX_writeFix        PHYSFS_writeSLE32
191 #define PHYSFSX_writeFixAng     PHYSFS_writeSLE16
192
193 static inline int PHYSFSX_writeVector(PHYSFS_file *file, vms_vector *v)
194 {
195         if (PHYSFSX_writeFix(file, v->x) < 1 ||
196          PHYSFSX_writeFix(file, v->y) < 1 ||
197          PHYSFSX_writeFix(file, v->z) < 1)
198                 return 0;
199
200         return 1;
201 }
202
203 static inline int PHYSFSX_writeAngleVec(PHYSFS_file *file, vms_angvec *v)
204 {
205         if (PHYSFSX_writeFixAng(file, v->p) < 1 ||
206          PHYSFSX_writeFixAng(file, v->b) < 1 ||
207          PHYSFSX_writeFixAng(file, v->h) < 1)
208                 return 0;
209
210         return 1;
211 }
212
213 static inline int PHYSFSX_writeMatrix(PHYSFS_file *file, vms_matrix *m)
214 {
215         if (PHYSFSX_writeVector(file, &m->rvec) < 1 ||
216          PHYSFSX_writeVector(file, &m->uvec) < 1 ||
217          PHYSFSX_writeVector(file, &m->fvec) < 1)
218                 return 0;
219
220         return 1;
221 }
222
223 static inline int PHYSFSX_getRealPath(const char *stdPath, char *realPath)
224 {
225         const char *realDir = PHYSFS_getRealDir(stdPath);
226         const char *sep = PHYSFS_getDirSeparator();
227         char *p;
228
229         if (!realDir)
230         {
231                 realDir = PHYSFS_getWriteDir();
232                 if (!realDir)
233                         return 0;
234         }
235
236         strncpy(realPath, realDir, PATH_MAX - 1);
237         if (strlen(realPath) >= strlen(sep))
238         {
239                 p = realPath + strlen(realPath) - strlen(sep);
240                 if (strcmp(p, sep)) // no sep at end of realPath
241                         strncat(realPath, sep, PATH_MAX - 1 - strlen(realPath));
242         }
243
244         if (strlen(stdPath) >= 1)
245                 if (*stdPath == '/')
246                         stdPath++;
247
248         while (*stdPath)
249         {
250                 if (*stdPath == '/')
251                         strncat(realPath, sep, PATH_MAX - 1 - strlen(realPath));
252                 else
253                 {
254                         if (strlen(realPath) < PATH_MAX - 2)
255                         {
256                                 p = realPath + strlen(realPath);
257                                 p[0] = *stdPath;
258                                 p[1] = '\0';
259                         }
260                 }
261                 stdPath++;
262         }
263
264         return 1;
265 }
266
267 static inline int PHYSFSX_rename(const char *oldpath, const char *newpath)
268 {
269         char old[PATH_MAX], new[PATH_MAX];
270
271         PHYSFSX_getRealPath(oldpath, old);
272         PHYSFSX_getRealPath(newpath, new);
273         return (rename(old, new) == 0);
274 }
275
276
277 // returns -1 if error
278 // Gets bytes free in current write dir
279 static inline PHYSFS_sint64 PHYSFSX_getFreeDiskSpace()
280 {
281 #if defined(__linux__) || (defined(__MACH__) && defined(__APPLE__))
282         struct statfs sfs;
283
284         if (!statfs(PHYSFS_getWriteDir(), &sfs))
285                 return (PHYSFS_sint64)(sfs.f_bavail * sfs.f_bsize);
286
287         return -1;
288 #else
289         return 0x7FFFFFFF;
290 #endif
291 }
292
293 //Open a file for reading, set up a buffer
294 static inline PHYSFS_file *PHYSFSX_openReadBuffered(const char *filename)
295 {
296         PHYSFS_file *fp;
297         PHYSFS_uint64 bufSize;
298
299         if (filename[0] == '\x01')
300         {
301                 //FIXME: don't look in dir, only in hogfile
302                 filename++;
303         }
304
305         fp = PHYSFS_openRead(filename);
306         if (!fp)
307                 return NULL;
308
309         bufSize = PHYSFS_fileLength(fp);
310         while (!PHYSFS_setBuffer(fp, bufSize) && bufSize)
311                 bufSize /= 2;   // even if the error isn't memory full, for a 20MB file it'll only do this 8 times
312
313         return fp;
314 }
315
316 //Open a file for writing, set up a buffer
317 static inline PHYSFS_file *PHYSFSX_openWriteBuffered(const char *filename)
318 {
319         PHYSFS_file *fp;
320         PHYSFS_uint64 bufSize = 1024*1024;      // hmm, seems like an OK size.
321
322         fp = PHYSFS_openWrite(filename);
323         if (!fp)
324                 return NULL;
325
326         while (!PHYSFS_setBuffer(fp, bufSize) && bufSize)
327                 bufSize /= 2;
328
329         return fp;
330 }
331
332 #endif /* PHYSFSX_H */