1 /***************************************************************************
2 tgf.cpp -- The Gaming Framework
3 -------------------
4 created : Fri Aug 13 22:31:43 CEST 1999
5 copyright : (C) 1999-2014 by Eric Espie, Bernhard Wymann
6 email : torcs@free.fr
7 version : $Id: tgf.cpp,v 1.16.2.9 2014/05/23 09:32:05 berniw Exp $
8 ***************************************************************************/
9
10 /***************************************************************************
11 * *
12 * This program is free software; you can redistribute it and/or modify *
13 * it under the terms of the GNU General Public License as published by *
14 * the Free Software Foundation; either version 2 of the License, or *
15 * (at your option) any later version. *
16 * *
17 ***************************************************************************/
18
19 #ifdef WIN32
20 #include <windows.h>
21 #include <direct.h>
22 #else
23 #include <sys/stat.h>
24 #include <sys/types.h>
25 #endif
26 #include <errno.h>
27 #include <portability.h>
28
29 #include <tgf.h>
30 #include <time.h>
31
32 extern void gfDirInit(void);
33 extern void gfModInit(void);
34 extern void gfOsInit(void);
35 extern void GfParmInit(void);
36 extern void gfRlstInit(void);
37
38
39 #ifdef WIN32
40 #include <crtdbg.h>
41 #include <assert.h>
42
43
_tgf_win_malloc(size_t size)44 void * _tgf_win_malloc(size_t size)
45 {
46 #ifdef _DEBUG
47 char * p = (char*)GlobalAlloc(GMEM_FIXED, size + 3*sizeof(int));
48 *(int*)(p) = size + 3*sizeof(int);
49 *((int*)p + 1) = 123456789;
50 *((int*)(p + size + 3*sizeof(int)) - 1) = 987654321;
51
52 return p + 2*sizeof(int);
53 #else // _DEBUG
54 char * p = (char*)GlobalAlloc(GMEM_FIXED, size + sizeof(int));
55 if (p == NULL) {
56 return NULL;
57 }
58 *(int*)(p) = size;
59 return p + sizeof(int);
60 #endif // _DEBUG
61 }
62
63
_tgf_win_calloc(size_t num,size_t size)64 void * _tgf_win_calloc(size_t num, size_t size)
65 {
66 void * p = _tgf_win_malloc(num * size);
67 memset(p, 0, num * size);
68 return p;
69 }
70
71
_tgf_win_realloc(void * memblock,size_t size)72 void * _tgf_win_realloc(void * memblock, size_t size)
73 {
74 if (size == 0) {
75 _tgf_win_free(memblock);
76 return NULL;
77 }
78
79 void * p = _tgf_win_malloc(size);
80 if (p == NULL) {
81 return NULL;
82 }
83
84 if (memblock != NULL) {
85 #ifdef _DEBUG
86 memcpy(p, memblock, min(*(int*)((char*)memblock-2*sizeof(int)), (int)size));
87 #else // _DEBUG
88 memcpy(p, memblock, min(*(int*)((char*)memblock-sizeof(int)), (int)size));
89 #endif // _DEBUG
90 _tgf_win_free(memblock);
91 }
92 return p;
93 }
94
95
_tgf_win_free(void * memblock)96 void _tgf_win_free(void * memblock)
97 {
98 if (!memblock) {
99 return;
100 }
101
102 #ifdef _DEBUG
103 char * p = (char*)memblock - 2*sizeof(int);
104
105 if (!_CrtIsValidPointer(p, sizeof(int), TRUE)) {
106 assert(0);
107 }
108
109 if (!_CrtIsValidPointer(p, *(int*)p, TRUE)) {
110 assert( 0 );
111 }
112
113 if (*((int*)p + 1) != 123456789) {
114 assert( 0 );
115 }
116
117 if(*((int*)(p + *(int*)p ) - 1) != 987654321) {
118 assert( 0 );
119 }
120
121 GlobalFree((char*)memblock - 2*sizeof(int));
122 #else // _DEBUG
123 GlobalFree((char*)memblock - sizeof(int));
124 #endif // _DEBUG
125 }
126
127
_tgf_win_strdup(const char * str)128 char * _tgf_win_strdup(const char * str)
129 {
130 char * s = (char*)_tgf_win_malloc(strlen(str)+1);
131 strcpy(s,str);
132
133 return s;
134 }
135 #endif // WIN32
136
137
GfInit(void)138 void GfInit(void)
139 {
140 gfDirInit();
141 gfModInit();
142 gfOsInit();
143 GfParmInit();
144 }
145
146
gfMeanReset(tdble v,tMeanVal * pvt)147 void gfMeanReset(tdble v, tMeanVal *pvt)
148 {
149 int i;
150
151 for (i = 0; i < GF_MEAN_MAX_VAL; i++) {
152 pvt->val[i] = v;
153 }
154 }
155
156
gfMean(tdble v,tMeanVal * pvt,int n,int w)157 tdble gfMean(tdble v, tMeanVal *pvt, int n, int w)
158 {
159 int i;
160 tdble sum;
161
162 if (n > pvt->curNum) {
163 if (pvt->curNum < GF_MEAN_MAX_VAL) {
164 pvt->curNum++;
165 }
166 n = pvt->curNum;
167 } else {
168 pvt->curNum = n;
169 }
170
171 sum = 0;
172 for (i = 0; i < n; i++) {
173 pvt->val[i] = pvt->val[i + 1];
174 sum += pvt->val[i];
175 }
176
177 pvt->val[n] = v;
178 sum += (tdble)w * v;
179 sum /= (tdble)(n + w);
180
181 return sum;
182 }
183
184
185 /** Convert a time in seconds (float) to an ascii string.
186 @ingroup screen
187 @param result buffer for the formatted string
188 @param resultSize size of the buffer
189 @param sec Time to convert
190 @param sgn Flag to indicate if the sign (+) is to be displayed for positive values of time.
191 @return Time string.
192 */
GfTime2Str(char * result,int resultSize,tdble sec,int sgn)193 void GfTime2Str(char *result, int resultSize, tdble sec, int sgn)
194 {
195 const char* sign;
196
197 if (sec < 0.0) {
198 sec = -sec;
199 sign = "-";
200 } else {
201 if (sgn) {
202 sign = "+";
203 } else {
204 sign = " ";
205 }
206 }
207
208 int h = (int)(sec / 3600.0);
209 sec -= 3600 * h;
210 int m = (int)(sec / 60.0);
211 sec -= 60 * m;
212 int s = (int)(sec);
213 sec -= s;
214 int c = (int)floor((sec) * 100.0);
215
216 if (h) {
217 snprintf(result, resultSize, "%s%2.2d:%2.2d:%2.2d:%2.2d", sign, h, m, s, c);
218 } else if (m) {
219 snprintf(result, resultSize, " %s%2.2d:%2.2d:%2.2d", sign, m, s, c);
220 } else {
221 snprintf(result, resultSize, " %s%2.2d:%2.2d", sign, s, c);
222 }
223 }
224
225
226 static char *localDir = strdup("");
227 static char *libDir = strdup("");
228 static char *dataDir = strdup("");
229
230
GetLocalDir(void)231 char * GetLocalDir(void)
232 {
233 return localDir;
234 }
235
236
SetLocalDir(char * buf)237 void SetLocalDir(char *buf)
238 {
239 free(localDir);
240 localDir = strdup(buf);
241 }
242
243
GetLibDir(void)244 char * GetLibDir(void)
245 {
246 return libDir;
247 }
248
249
SetLibDir(char * buf)250 void SetLibDir(char *buf)
251 {
252 free(libDir);
253 libDir = strdup(buf);
254 }
255
256
GetDataDir(void)257 char * GetDataDir(void)
258 {
259 return dataDir;
260 }
261
262
SetDataDir(char * buf)263 void SetDataDir(char *buf)
264 {
265 free(dataDir);
266 dataDir = strdup(buf);
267 }
268
269
270 static int singleTextureMode = 0;
271
272
GetSingleTextureMode(void)273 int GetSingleTextureMode (void)
274 {
275 return singleTextureMode;
276 }
277
278
SetSingleTextureMode(void)279 void SetSingleTextureMode (void)
280 {
281 singleTextureMode = 1;
282 }
283
284
GfNearestPow2(int x)285 int GfNearestPow2 (int x)
286 {
287 int r;
288
289 if (!x) {
290 return 0;
291 }
292
293 x++;
294 r = 1;
295 while ((1 << r) < x) {
296 r++;
297 }
298 r--;
299
300 return (1 << r);
301 }
302
303
304 /** @brief Create directory for given path recursively, so all missing parent directories are created as well
305 * @param[in] path Path
306 * @return #GF_DIR_CREATED if directory was created or already exits
307 * <br>#GF_DIR_CREATION_FAILED if directory could not be created
308 */
GfCreateDir(char * path)309 int GfCreateDir(char *path)
310 {
311 if (path == NULL) {
312 return GF_DIR_CREATION_FAILED;
313 }
314
315 const int BUFSIZE = 1024;
316 char buf[BUFSIZE];
317 strncpy(buf, path, BUFSIZE);
318
319 #ifdef WIN32
320 #define mkdir(x) _mkdir(x)
321
322 // Translate path.
323 const char DELIM = '\\';
324 int i;
325 for (i = 0; i < BUFSIZE && buf[i] != '\0'; i++) {
326 if (buf[i] == '/') {
327 buf[i] = DELIM;
328 }
329 }
330
331 #else // WIN32
332 #define mkdir(x) mkdir((x), S_IRWXU);
333
334 const char DELIM = '/';
335
336 #endif // WIN32
337
338 int err = mkdir(buf);
339 if (err == -1) {
340 if (errno == ENOENT) {
341 char *end = strrchr(buf, DELIM);
342 *end = '\0';
343 GfCreateDir(buf);
344 *end = DELIM;
345 err = mkdir(buf);
346
347 }
348 }
349
350 if (err == -1 && errno != EEXIST) {
351 return GF_DIR_CREATION_FAILED;
352 } else {
353 return GF_DIR_CREATED;
354 }
355 }
356
357
358 /** @brief Create directory for given file path recursively, so all missing parent directories are created as well
359 * @param[in] filenameandpath Path including file name
360 * @return #GF_DIR_CREATED if directory was created or already exits
361 * <br>#GF_DIR_CREATION_FAILED if directory could not be created
362 * @see GfCreateDir
363 */
GfCreateDirForFile(const char * filenameandpath)364 int GfCreateDirForFile(const char *filenameandpath)
365 {
366 if (filenameandpath == 0) {
367 return GF_DIR_CREATION_FAILED;
368 }
369
370 const char* lastdelim = strrchr(filenameandpath, '/');
371 if (lastdelim != NULL && lastdelim != filenameandpath) {
372 const int BUFSIZE = 1024;
373 char buf[BUFSIZE];
374 const int size = MIN(lastdelim - filenameandpath, BUFSIZE - 1);
375 snprintf(buf, BUFSIZE, "%s", filenameandpath);
376 buf[size] = '\0';
377
378 return GfCreateDir(buf);
379 }
380
381 return GF_DIR_CREATED;
382 }
383