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