fix windowisms: BOOL
[rofl0r-openbor.git] / source / utils.c
blob2b1fafa13a4bd568aef969595137e32a86631104
1 /*
2 * OpenBOR - http://www.LavaLit.com
3 * -----------------------------------------------------------------------
4 * Licensed under the BSD license, see LICENSE in OpenBOR root for details.
6 * Copyright (c) 2004 - 2011 OpenBOR Team
7 */
9 #include <fcntl.h>
10 #include <stdio.h>
11 #include <string.h>
12 #include <stdarg.h>
13 #include <malloc.h>
14 #include <locale.h>
15 #include <math.h>
17 #include "stringptr.h"
18 #include "utils.h"
19 #include "stristr.h"
20 #include "openbor.h"
21 #include "packfile.h"
22 #include "savepng.h"
24 #include <dirent.h>
25 #include <sys/stat.h>
27 #ifdef SDL
28 # include <unistd.h>
29 # include "sdlport.h"
30 #endif
32 #define MKDIR(x) mkdir(x, 0777)
34 #ifdef XBOX
35 #define CHECK_LOGFILE(type) type ? fileExists("d:\\Logs\\OpenBorLog.txt") : fileExists("d:\\Logs\\ScriptLog.txt")
36 #define OPEN_LOGFILE(type) type ? fopen("d:\\Logs\\OpenBorLog.txt", "wt") : fopen("d:\\Logs\\ScriptLog.txt", "wt")
37 #define APPEND_LOGFILE(type) type ? fopen("d:\\Logs\\OpenBorLog.txt", "at") : fopen("d:\\Logs\\ScriptLog.txt", "at")
38 #define READ_LOGFILE(type) type ? fopen("d:\\Logs\\OpenBorLog.txt", "rt") : fopen("d:\\Logs\\ScriptLog.txt", "rt")
39 #define COPY_ROOT_PATH(buf, name) strncpy(buf, "d:\\", 3); strncat(buf, name, strlen(name)); strncat(buf, "\\", 1)
40 #define COPY_PAKS_PATH(buf, name) strncpy(buf, "d:\\Paks\\", 8); strncat(buf, name, strlen(name))
41 #elif WII && !SDL
42 #define CHECK_LOGFILE(type) type ? fileExists(getFullPath("Logs/OpenBorLog.txt")) : fileExists(getFullPath("Logs/ScriptLog.txt"))
43 #define OPEN_LOGFILE(type) type ? fopen(getFullPath("Logs/OpenBorLog.txt"), "wt") : fopen(getFullPath("Logs/ScriptLog.txt"), "wt")
44 #define APPEND_LOGFILE(type) type ? fopen(getFullPath("Logs/OpenBorLog.txt"), "at") : fopen(getFullPath("Logs/ScriptLog.txt"), "at")
45 #define READ_LOGFILE(type) type ? fopen(getFullPath("Logs/OpenBorLog.txt"), "rt") : fopen(getFullPath("Logs/ScriptLog.txt"), "rt")
46 #define COPY_ROOT_PATH(buf, name) strcpy(buf, rootDir); strncat(buf, name, strlen(name)); strncat(buf, "/", 1);
47 #define COPY_PAKS_PATH(buf, name) strncpy(buf, paksDir, strlen(paksDir)); strncat(buf, "/", 1); strncat(buf, name, strlen(name));
48 #elif WII && SDL
49 #define CHECK_LOGFILE(type) type ? fileExists("sd:/apps/OpenBOR/Logs/OpenBorLog.txt") : fileExists("sd:/apps/OpenBOR/Logs/ScriptLog.txt")
50 #define OPEN_LOGFILE(type) type ? fopen("sd:/apps/OpenBOR/Logs/OpenBorLog.txt", "wt") : fopen("sd:/apps/OpenBOR/Logs/ScriptLog.txt", "wt")
51 #define APPEND_LOGFILE(type) type ? fopen("sd:/apps/OpenBOR/Logs/OpenBorLog.txt", "at") : fopen("sd:/apps/OpenBOR/Logs/ScriptLog.txt", "at")
52 #define READ_LOGFILE(type) type ? fopen("sd:/apps/OpenBOR/Logs/OpenBorLog.txt", "rt") : fopen("sd:/apps/OpenBOR/Logs/ScriptLog.txt", "rt")
53 #define COPY_ROOT_PATH(buf, name) strncpy(buf, "sd:/apps/OpenBOR/", 17); strncat(buf, name, strlen(name)); strncat(buf, "/", 1);
54 #define COPY_PAKS_PATH(buf, name) strncpy(buf, "sd:/apps/OpenBOR/Paks/", 22); strncat(buf, name, strlen(name));
55 #else
56 #define CHECK_LOGFILE(type) type ? fileExists("./Logs/OpenBorLog.txt") : fileExists("./Logs/ScriptLog.txt")
57 #define OPEN_LOGFILE(type) type ? fopen("./Logs/OpenBorLog.txt", "wt") : fopen("./Logs/ScriptLog.txt", "wt")
58 #define APPEND_LOGFILE(type) type ? fopen("./Logs/OpenBorLog.txt", "at") : fopen("./Logs/ScriptLog.txt", "at")
59 #define READ_LOGFILE(type) type ? fopen("./Logs/OpenBorLog.txt", "rt") : fopen("./Logs/ScriptLog.txt", "rt")
60 #define COPY_ROOT_PATH(buf, name) strncpy(buf, "./", 2); strncat(buf, name, strlen(name)); strncat(buf, "/", 1);
61 #define COPY_PAKS_PATH(buf, name) strncpy(buf, "./Paks/", 7); strncat(buf, name, strlen(name));
62 #endif
64 void debugBuf(unsigned char *buf, size_t size, int columns) {
65 size_t pos = 0;
66 int i;
67 while(pos < size) {
68 for(i = 0; i < columns; i++) {
69 if(pos >= size)
70 break;
71 printf("%02x", buf[pos]);
72 pos++;
74 printf("\n");
78 //lowercases a buffer inplace
79 void lc(char *buf, size_t size) {
80 ptrdiff_t i;
81 for(i = 0; i < size; i++)
82 buf[i] = tolower((int) buf[i]);
85 // returns position after next newline in buf
86 size_t getNewLineStart(char *buf) {
87 size_t res = 0;
88 while(buf[res] && buf[res] != '\n' && buf[res] != '\r')
89 ++res;
90 while(buf[res] && (buf[res] == '\n' || buf[res] == '\r'))
91 ++res;
92 return res;
95 void freeAndNull(void** data) {
96 if(data && *data) {
97 free(*data);
98 *data = NULL;
102 int is_dir(char* fn) {
103 struct stat st;
104 if(stat(fn, &st) != -1 && S_ISDIR(st.st_mode))
105 return 1;
106 return 0;
109 FILE *openborLog = NULL;
110 FILE *scriptLog = NULL;
111 char debug_msg[2048];
112 unsigned long debug_time = 0xFFFFFFFF;
114 void getBasePath(char *newName, char *name, int type) {
115 char buf[128] = { "" };
116 if(type)
117 snprintf(buf, sizeof(buf) - 1, "%s/%s", paksDir, name);
118 else
119 snprintf(buf, sizeof(buf) - 1, "%s/", name);
121 if(is_dir(buf))
122 strcat(buf, "/");
123 strncpy(newName, buf, sizeof(buf));
128 #ifndef DC
129 int dirExists(char *dname, int create) {
130 char realName[128] = { "" };
131 #ifdef XBOX
132 getBasePath(realName, dname, 0);
133 return CreateDirectory(realName, NULL);
134 #else
135 DIR *fd1 = NULL;
136 int fd2 = -1;
137 strncpy(realName, dname, 128);
138 fd1 = opendir(realName);
139 if(fd1 != NULL) {
140 closedir(fd1);
141 return 1;
143 if(create) {
144 fd2 = MKDIR(realName);
145 if(fd2 < 0)
146 return 0;
147 #ifdef DARWIN
148 chmod(realName, 0777);
149 #endif
150 return 1;
152 #endif
153 return 0;
156 int fileExists(char *fnam) {
157 FILE *handle = NULL;
158 if((handle = fopen(fnam, "rb")) == NULL)
159 return 0;
160 fclose(handle);
161 return 1;
163 #endif
165 void debug_printf(char *format, ...) {
166 va_list arglist;
168 va_start(arglist, format);
169 vsprintf(debug_msg, format, arglist);
170 va_end(arglist);
172 debug_time = 0xFFFFFFFF;
175 const char* savefile_exts[] = {
176 [ST_SAVE] = ".sav",
177 [ST_HISCORE] = ".hi",
178 [ST_SCRIPT] = ".scr",
179 [ST_INP] = ".inp",
180 [ST_CFG] = ".cfg",
183 int packfile_is_dir(void) {
184 return packfile[strlen(packfile) - 1] == '/';
187 void getSaveFileName(char name[256], savefile_type type) {
189 char mod[256] = { "" };
190 const char* ext = "";
191 char* fn;
192 unsigned s, l;
194 if(type < ST_MAX)
195 ext = savefile_exts[type];
197 l = strlen(paksDir);
198 if(memcmp(packfile, paksDir, l))
199 s = 0;
200 else {
201 s = l;
202 if(paksDir[l - 1] != '/')
203 s++;
206 l = strlen(packfile) - s;
207 if(!packfile_is_dir())
208 l -= 4; // strip off ".pak"
209 else
210 l-=1; // strip off "/"
213 memcpy(mod, packfile + s, l);
214 memcpy(mod + l, ext, strlen(ext));
216 if((fn = strrchr(mod, '/')) || (fn = strrchr(mod, '\\')))
217 strcpy(name, fn + 1);
218 else
219 strcpy(name, mod);
222 void screenshot(s_screen * vscreen, unsigned char *pal, int ingame) {
223 int shotnum = 0;
224 char shotname[128] = { "" };
225 char modname[128] = { "" };
227 getSaveFileName(modname, 99);
228 do {
229 sprintf(shotname, "./ScreenShots/%s - %04u.png", modname, shotnum);
230 ++shotnum;
231 } while(fileExists(shotname) && shotnum < 100);
233 if(shotnum < 10000)
234 savepng(shotname, vscreen, pal);
235 if(ingame)
236 debug_printf("Saved %s", shotname);
239 unsigned readlsb32(const unsigned char *src) {
240 return
241 ((((unsigned) (src[0])) & 0xFF) << 0) |
242 ((((unsigned) (src[1])) & 0xFF) << 8) |
243 ((((unsigned) (src[2])) & 0xFF) << 16) | ((((unsigned) (src[3])) & 0xFF) << 24);
246 // Optimized search in an arranged string table, return the index
247 int searchList(const char *list[], const char *value, int length) {
248 int i;
249 int a = 0;
250 int b = length / 2;
251 int c = length - 1;
252 int v = value[0];
254 // We must convert uppercase values to lowercase,
255 // since this is how every command is written in
256 // our source. Refer to an ASCII Chart
257 if(v >= 0x41 && v <= 0x5A)
258 v += 0x20;
260 // Index value equals middle value,
261 // Lets search starting from center.
262 if(v == list[b][0]) {
263 if(stricmp(list[b], value) == 0)
264 return b;
266 // Search Down the List.
267 if(v == list[b - 1][0]) {
268 for(i = b - 1; i >= 0; i--) {
269 if(stricmp(list[i], value) == 0)
270 return i;
271 if(v != list[i - 1][0])
272 break;
275 // Search Up the List.
276 if(v == list[b + 1][0]) {
277 for(i = b + 1; i < length; i++) {
278 if(stricmp(list[i], value) == 0)
279 return i;
280 if(v != list[i + 1][0])
281 break;
284 // No match, return failure.
285 goto searchListFailed;
287 // Define the starting point.
288 if(v >= list[b + 1][0])
289 a = b + 1;
290 else if(v <= list[b - 1][0])
291 c = b - 1;
292 else
293 goto searchListFailed;
295 // Search Up from starting point.
296 for(i = a; i <= c; i++) {
297 if(v == list[i][0]) {
298 if(stricmp(list[i], value) == 0)
299 return i;
300 if(v != list[i + 1][0])
301 break;
305 searchListFailed:
307 // The search failed!
308 // On five reasons for failure!
309 // 1. Is the list in alphabetical order?
310 // 2. Is the first letter lowercase in list?
311 // 3. Does the value exist in the list?
312 // 4. Is it a typo?
313 // 5. Is it a text file error?
314 return -1;
317 char *commaprint(u64 n) {
318 static int comma = '\0';
319 static char retbuf[30];
320 char *p = &retbuf[sizeof(retbuf) - 1];
321 int i = 0;
323 if(comma == '\0') {
324 struct lconv *lcp = localeconv();
325 if(lcp != NULL) {
326 if(lcp->thousands_sep != NULL && *lcp->thousands_sep != '\0')
327 comma = *lcp->thousands_sep;
328 else
329 comma = ',';
333 *p = '\0';
335 do {
336 if(i % 3 == 0 && i != 0)
337 *--p = comma;
338 *--p = '0' + n % 10;
339 n /= 10;
340 i++;
341 } while(n != 0);
343 return p;
346 //! Increase or Decrease an array à la \e vector
348 \param f_caller : name of the calling function for logging purpose
349 \param array : the array to consider
350 \param new_size : new size needed for the array (in BYTE) :
351 -# if new_size <= 0 : Deallocation of the array
352 -# new_size < \a curr_size_allocated - \a grow_step => Decrease of the array
353 -# new_size >= \a curr_size_allocated => Increase of the array
354 \param curr_size_allocated : current allocated size to the array (in BYTE)
355 \param grow_step : bloc size of expansion of the array (in BYTE)
357 void Array_Check_Size(const char *f_caller, char **array, int new_size, int *curr_size_allocated, int grow_step) {
358 // Deallocation
359 if(new_size <= 0) {
360 if(*array != NULL) {
361 free(*array);
362 *array = NULL;
364 *curr_size_allocated = 0;
366 // First allocation
367 else if(*array == NULL) {
368 *curr_size_allocated = grow_step;
369 *array = malloc(*curr_size_allocated);
370 if(*array == NULL)
371 shutdown(1, "Out Of Memory! Failed in %s\n", f_caller);
372 memset(*array, 0, *curr_size_allocated);
373 return;
375 // No need to decrease or increase the array
376 else if(new_size > (*curr_size_allocated - grow_step) && new_size <= *curr_size_allocated)
377 return;
379 //-------------------------------------------
380 // Must increase or decrease the array size
382 int old_size = *curr_size_allocated;
384 // Recompute needed size
385 *curr_size_allocated = ((int) ceil((float) new_size / (float) grow_step)) * grow_step;
387 // Alloc a new array
388 void *copy = malloc(*curr_size_allocated);
389 if(copy == NULL)
390 shutdown(1, "Out Of Memory! Failed in %s\n", f_caller);
392 // Copy the previous content of the array
393 memcpy(copy, *array, ((old_size < new_size) ? old_size : new_size));
395 // Init the new allocations
396 if(old_size < *curr_size_allocated)
397 memset(copy + old_size, 0, *curr_size_allocated - old_size);
399 // Free previous array memory
400 free(*array);
402 // ReAssign the new allocated array
403 *array = copy;
406 void char_to_lower(char *dst, char *src, size_t maxlen) {
407 unsigned i;
408 for(i = 0; i < maxlen; i++) {
409 dst[i] = tolower(src[i]);
410 if(!src[i])
411 break;
413 if(i == maxlen)
414 dst[maxlen - 1] = 0;
417 void int_min_max(int* candidate, int min, int max) {
418 if(*candidate < min)
419 *candidate = min;
420 else if (*candidate > max)
421 *candidate = max;
424 void short_min_max(short* candidate, short min, short max) {
425 if(*candidate < min)
426 *candidate = min;
427 else if (*candidate > max)
428 *candidate = max;