1 /*
2 * OpenBOR - http://www.LavaLit.com
3 * -----------------------------------------------------------------------
4 * All rights reserved, see LICENSE in OpenBOR root for details.
5 *
6 * Copyright (c) 2004 - 2011 OpenBOR Team
7 */
8
9 #include <fcntl.h>
10 #include <stdio.h>
11 #include <string.h>
12 #include <stdarg.h>
13 #include <stdlib.h>
14 #include <locale.h>
15 #include <math.h>
16
17 #include "stringptr.h"
18 #include "utils.h"
19 #include "stristr.h"
20 #include "openbor.h"
21 #include "packfile.h"
22
23 #if PSP || WIN || LINUX || GP2X || DINGOO || SYMBIAN
24 #include <dirent.h>
25 #endif
26
27 #if GP2X || LINUX || DINGOO
28 #include <sys/stat.h>
29 #endif
30
31 #ifdef DOS
32 #include <direct.h>
33 #include "dosport.h"
34 #include "savepng.h"
35 #endif
36
37 #ifdef SDL
38 #include <unistd.h>
39 #include "sdlport.h"
40 #include "savepng.h"
41 #endif
42
43 #ifdef DC
44 #include "dcport.h"
45 #endif
46
47 #ifdef XBOX
48 #include "xboxport.h"
49 #include "savepng.h"
50 #endif
51
52 #ifdef PSP
53 #include "image.h"
54 #endif
55
56
57 #if WII && !SDL
58 #include "wiiport.h"
59 #include "savepng.h"
60 #endif
61
62 #if PSP || GP2X || LINUX || DINGOO || WII || SYMBIAN
63 #define MKDIR(x) mkdir(x, 0777)
64 #else
65 #define MKDIR(x) mkdir(x)
66 #endif
67
68 #ifdef XBOX
69 #define CHECK_LOGFILE(type) type ? fileExists("d:\\Logs\\OpenBorLog.txt") : fileExists("d:\\Logs\\ScriptLog.txt")
70 #define OPEN_LOGFILE(type) type ? fopen("d:\\Logs\\OpenBorLog.txt", "wt") : fopen("d:\\Logs\\ScriptLog.txt", "wt")
71 #define APPEND_LOGFILE(type) type ? fopen("d:\\Logs\\OpenBorLog.txt", "at") : fopen("d:\\Logs\\ScriptLog.txt", "at")
72 #define READ_LOGFILE(type) type ? fopen("d:\\Logs\\OpenBorLog.txt", "rt") : fopen("d:\\Logs\\ScriptLog.txt", "rt")
73 #define COPY_ROOT_PATH(buf, name) strncpy(buf, "d:\\", 3); strncat(buf, name, strlen(name)); strncat(buf, "\\", 1)
74 #define COPY_PAKS_PATH(buf, name) strncpy(buf, "d:\\Paks\\", 8); strncat(buf, name, strlen(name))
75 #elif WII && !SDL
76 #define CHECK_LOGFILE(type) type ? fileExists(getFullPath("Logs/OpenBorLog.txt")) : fileExists(getFullPath("Logs/ScriptLog.txt"))
77 #define OPEN_LOGFILE(type) type ? fopen(getFullPath("Logs/OpenBorLog.txt"), "wt") : fopen(getFullPath("Logs/ScriptLog.txt"), "wt")
78 #define APPEND_LOGFILE(type) type ? fopen(getFullPath("Logs/OpenBorLog.txt"), "at") : fopen(getFullPath("Logs/ScriptLog.txt"), "at")
79 #define READ_LOGFILE(type) type ? fopen(getFullPath("Logs/OpenBorLog.txt"), "rt") : fopen(getFullPath("Logs/ScriptLog.txt"), "rt")
80 #define COPY_ROOT_PATH(buf, name) strcpy(buf, rootDir); strncat(buf, name, strlen(name)); strncat(buf, "/", 1);
81 #define COPY_PAKS_PATH(buf, name) strncpy(buf, paksDir, strlen(paksDir)); strncat(buf, "/", 1); strncat(buf, name, strlen(name));
82 #elif WII && SDL
83 #define CHECK_LOGFILE(type) type ? fileExists("sd:/apps/OpenBOR/Logs/OpenBorLog.txt") : fileExists("sd:/apps/OpenBOR/Logs/ScriptLog.txt")
84 #define OPEN_LOGFILE(type) type ? fopen("sd:/apps/OpenBOR/Logs/OpenBorLog.txt", "wt") : fopen("sd:/apps/OpenBOR/Logs/ScriptLog.txt", "wt")
85 #define APPEND_LOGFILE(type) type ? fopen("sd:/apps/OpenBOR/Logs/OpenBorLog.txt", "at") : fopen("sd:/apps/OpenBOR/Logs/ScriptLog.txt", "at")
86 #define READ_LOGFILE(type) type ? fopen("sd:/apps/OpenBOR/Logs/OpenBorLog.txt", "rt") : fopen("sd:/apps/OpenBOR/Logs/ScriptLog.txt", "rt")
87 #define COPY_ROOT_PATH(buf, name) strncpy(buf, "sd:/apps/OpenBOR/", 17); strncat(buf, name, strlen(name)); strncat(buf, "/", 1);
88 #define COPY_PAKS_PATH(buf, name) strncpy(buf, "sd:/apps/OpenBOR/Paks/", 22); strncat(buf, name, strlen(name));
89 #else
90 #define CHECK_LOGFILE(type) type ? fileExists("./Logs/OpenBorLog.txt") : fileExists("./Logs/ScriptLog.txt")
91 #define OPEN_LOGFILE(type) type ? fopen("./Logs/OpenBorLog.txt", "wt") : fopen("./Logs/ScriptLog.txt", "wt")
92 #define APPEND_LOGFILE(type) type ? fopen("./Logs/OpenBorLog.txt", "at") : fopen("./Logs/ScriptLog.txt", "at")
93 #define READ_LOGFILE(type) type ? fopen("./Logs/OpenBorLog.txt", "rt") : fopen("./Logs/ScriptLog.txt", "rt")
94 #define COPY_ROOT_PATH(buf, name) strncpy(buf, "./", 2); strncat(buf, name, strlen(name)); strncat(buf, "/", 1);
95 #define COPY_PAKS_PATH(buf, name) strncpy(buf, "./Paks/", 7); strncat(buf, name, strlen(name));
96 #endif
97
debugBuf(unsigned char * buf,size_t size,int columns)98 void debugBuf(unsigned char* buf, size_t size, int columns) {
99 size_t pos = 0;
100 int i;
101 while(pos<size) {
102 for(i=0;i<columns;i++) {
103 if(pos >= size) break;
104 printf("%02x", buf[pos]);
105 pos++;
106 }
107 printf("\n");
108 }
109 }
110
111 //lowercases a buffer inplace
lc(char * buf,size_t size)112 void lc(char* buf, size_t size) {
113 ptrdiff_t i;
114 for(i=0;i<size;i++)
115 buf[i] = tolower((int)buf[i]);
116 }
117
118 // returns position after next newline in buf
getNewLineStart(char * buf)119 size_t getNewLineStart(char* buf) {
120 size_t res = 0;
121 while(buf[res] && buf[res]!='\n' && buf[res]!='\r') ++res;
122 while(buf[res] && (buf[res]=='\n' || buf[res]=='\r')) ++res;
123 return res;
124 }
125
126 FILE* openborLog = NULL;
127 FILE* scriptLog = NULL;
128 char debug_msg[2048];
129 u32 debug_time = 0;
130
getBasePath(char * newName,char * name,int type)131 void getBasePath(char *newName, char *name, int type)
132 {
133 #ifndef DC
134 char buf[128] = {""};
135 switch(type)
136 {
137 case 0:
138 COPY_ROOT_PATH(buf, name);
139 break;
140 case 1:
141 COPY_PAKS_PATH(buf, name);
142 break;
143 }
144 memcpy(newName, buf, sizeof(buf));
145 #else
146 memcpy(newName, name, 128);
147 #endif
148 }
149
150
151
152 #ifndef DC
dirExists(char * dname,int create)153 int dirExists(char *dname, int create)
154 {
155 char realName[128] = {""};
156 #ifdef XBOX
157 getBasePath(realName, dname, 0);
158 return CreateDirectory(realName, NULL);
159 #else
160 DIR *fd1 = NULL;
161 int fd2 = -1;
162 strncpy(realName, dname, 128);
163 fd1 = opendir(realName);
164 if(fd1 != NULL)
165 {
166 closedir(fd1);
167 return 1;
168 }
169 if(create)
170 {
171 fd2 = MKDIR(realName);
172 if(fd2 < 0) return 0;
173 #ifdef DARWIN
174 chmod(realName, 0777);
175 #endif
176 return 1;
177 }
178 #endif
179 return 0;
180 }
181
fileExists(char * fnam)182 int fileExists(char *fnam)
183 {
184 FILE *handle = NULL;
185 if((handle=fopen(fnam,"rb")) == NULL) return 0;
186 fclose(handle);
187 return 1;
188 }
189
readFromLogFile(int which)190 stringptr* readFromLogFile(int which)
191 {
192 long size;
193 FILE* handle = NULL;
194 stringptr* buffer = NULL;
195 handle = READ_LOGFILE((which ? OPENBOR_LOG : SCRIPT_LOG));
196 if(handle == NULL) return NULL;
197 fseek(handle, 0, SEEK_END);
198 size = ftell(handle);
199 rewind(handle);
200 if (size == 0) goto CLOSE_AND_QUIT;
201 // allocate memory to contain the whole file:
202 //buffer = (char*)malloc(sizeof(char)*(size+1)); // alloc one additional byte for the
203 buffer = new_string(size);
204 if(buffer == NULL) goto CLOSE_AND_QUIT;
205 fread(buffer->ptr, 1, size, handle);
206 CLOSE_AND_QUIT:
207 fclose(handle);
208 return buffer;
209 }
210 #endif
211
writeToLogFile(const char * msg,...)212 void writeToLogFile(const char * msg, ...)
213 {
214 va_list arglist;
215
216 #ifdef DC
217 va_start(arglist, msg);
218 vfprintf(stdout, msg, arglist);
219 va_end(arglist);
220 fflush(stdout);
221 #else
222 if(openborLog == NULL)
223 {
224 openborLog = OPEN_LOGFILE(OPENBOR_LOG);
225 if(openborLog == NULL) return;
226 }
227 va_start(arglist, msg);
228 vfprintf(openborLog, msg, arglist);
229 va_end(arglist);
230 fflush(openborLog);
231 #endif
232 }
233
writeToScriptLog(const char * msg)234 void writeToScriptLog(const char *msg)
235 {
236 #ifndef DC
237 if(scriptLog == NULL)
238 {
239 scriptLog = OPEN_LOGFILE(SCRIPT_LOG);
240 if(scriptLog == NULL) return;
241 }
242 fwrite(msg, 1, strlen(msg), scriptLog);
243 fflush(scriptLog);
244 #endif
245 }
246
debug_printf(char * format,...)247 void debug_printf(char *format, ...){
248 va_list arglist;
249
250 va_start(arglist, format);
251 vsprintf(debug_msg, format, arglist);
252 va_end(arglist);
253
254 debug_time = 0xFFFFFFFF;
255 }
256
getPakName(char * name,int type)257 void getPakName(char* name, int type){
258
259 int i,x,y;
260 char mod[256] = {""};
261
262 strncpy(mod,packfile,strlen(packfile)-4);
263
264 switch(type){
265 case 0:
266 strncat(mod,".sav",4);
267 break;
268 case 1:
269 strncat(mod,".hi",3);
270 break;
271 case 2:
272 strncat(mod,".scr",4);
273 break;
274 case 3:
275 strncat(mod,".inp",4);
276 break;
277 case 4:
278 strncat(mod,".cfg",4);
279 break;
280 default:
281 // Loose extension!
282 break;
283 }
284
285 x=0;
286 for(i=0; i<(int)strlen(mod); i++){
287 if((mod[i] == '/') || (mod[i] == '\\')) x = i;
288 }
289 y=0;
290 for(i=0; i<(int)strlen(mod); i++){
291 // For packfiles without '/'
292 if(x == 0){
293 name[y] = mod[i];
294 y++;
295 }
296 // For packfiles with '/'
297 if(x != 0 && i > x){
298 name[y] = mod[i];
299 y++;
300 }
301 }
302 name[y] = 0;
303 }
304
screenshot(s_screen * vscreen,unsigned char * pal,int ingame)305 void screenshot(s_screen *vscreen, unsigned char *pal, int ingame){
306 #ifndef DC
307 int shotnum = 0;
308 char shotname[128] = {""};
309 char modname[128] = {""};
310
311 getPakName(modname,99);
312 #ifdef PSP
313 if(dirExists("ms0:/PICTURE/", 1) && dirExists("ms0:/PICTURE/Beats Of Rage/", 1)){
314 #endif
315 do{
316 #if PSP
317 sprintf(shotname, "ms0:/PICTURE/Beats Of Rage/%s - ScreenShot - %02u.png", modname,shotnum);
318 #elif DOS
319 sprintf(shotname, "./SShots/s%04u.png", shotnum);
320 #elif XBOX
321 sprintf(shotname, "d:\\ScreenShots\\%s - %04u.png", modname,shotnum);
322 #elif WII && SDL
323 sprintf(shotname, "sd:/apps/OpenBOR/ScreenShots/%s - %04u.png", modname,shotnum);
324 #elif WII
325 sprintf(shotname, "%s/%s - %04u.png", screenShotsDir,modname,shotnum);
326 #else
327 sprintf(shotname, "./ScreenShots/%s - %04u.png", modname,shotnum);
328 #endif
329 ++shotnum;
330 }while(fileExists(shotname) && shotnum<10000);
331
332 #ifdef PSP
333 if(shotnum<10000) saveImage(shotname);
334 #else
335 if(shotnum<10000) savepng(shotname, vscreen, pal);
336 #endif
337 if(ingame) debug_printf("Saved %s", shotname);
338 #ifdef PSP
339 }
340 #endif
341 #endif
342 }
343
344 #ifdef XBOX
findmods(void)345 int findmods(void)
346 {
347 int i = 0;
348 HANDLE hFind;
349 WIN32_FIND_DATAA oFindData;
350 hFind = FindFirstFile("d:\\Paks\\*", &oFindData);
351 if(hFind == INVALID_HANDLE_VALUE) return 1;
352 do
353 {
354 if(stristr(oFindData.cFileName, ".pak") && stricmp(oFindData.cFileName, "menu.pak") != 0)
355 {
356 strncpy(paklist[i].filename, oFindData.cFileName, 128-strlen(oFindData.cFileName));
357 i++;
358 }
359 }
360 while(FindNextFile(hFind, &oFindData));
361 FindClose(hFind);
362 return i;
363 }
364 #endif
365
readlsb32(const unsigned char * src)366 unsigned readlsb32(const unsigned char *src)
367 {
368 return
369 ((((unsigned)(src[0])) & 0xFF) << 0) |
370 ((((unsigned)(src[1])) & 0xFF) << 8) |
371 ((((unsigned)(src[2])) & 0xFF) << 16) |
372 ((((unsigned)(src[3])) & 0xFF) << 24);
373 }
374
375 // Optimized search in an arranged string table, return the index
searchList(const char * list[],const char * value,int length)376 int searchList(const char* list[], const char* value, int length)
377 {
378 int i;
379 int a = 0;
380 int b = length / 2;
381 int c = length - 1;
382 int v = value[0];
383
384 // We must convert uppercase values to lowercase,
385 // since this is how every command is written in
386 // our source. Refer to an ASCII Chart
387 if(v >= 0x41 && v <= 0x5A) v += 0x20;
388
389 // Index value equals middle value,
390 // Lets search starting from center.
391 if(v == list[b][0])
392 {
393 if(stricmp(list[b], value) == 0) return b;
394
395 // Search Down the List.
396 if(v == list[b-1][0])
397 {
398 for(i=b-1 ; i>=0; i--)
399 {
400 if(stricmp(list[i], value) == 0) return i;
401 if(v != list[i-1][0]) break;
402 }
403 }
404
405 // Search Up the List.
406 if(v == list[b+1][0])
407 {
408 for(i=b+1; i<length; i++)
409 {
410 if(stricmp(list[i], value) == 0) return i;
411 if(v != list[i+1][0]) break;
412 }
413 }
414
415 // No match, return failure.
416 goto searchListFailed;
417 }
418
419 // Define the starting point.
420 if(v >= list[b+1][0]) a = b+1;
421 else if(v <= list[b-1][0]) c = b-1;
422 else goto searchListFailed;
423
424 // Search Up from starting point.
425 for(i=a; i<=c; i++)
426 {
427 if(v == list[i][0])
428 {
429 if(stricmp(list[i], value) == 0) return i;
430 if(v != list[i+1][0]) break;
431 }
432 }
433
434 searchListFailed:
435
436 // The search failed!
437 // On five reasons for failure!
438 // 1. Is the list in alphabetical order?
439 // 2. Is the first letter lowercase in list?
440 // 3. Does the value exist in the list?
441 // 4. Is it a typo?
442 // 5. Is it a text file error?
443 return -1;
444 }
445
commaprint(u64 n)446 char *commaprint(u64 n)
447 {
448 static int comma = '\0';
449 static char retbuf[30];
450 char *p = &retbuf[sizeof(retbuf)-1];
451 int i = 0;
452
453 if(comma == '\0')
454 {
455 struct lconv *lcp = localeconv();
456 if(lcp != NULL)
457 {
458 if(lcp->thousands_sep != NULL &&
459 *lcp->thousands_sep != '\0')
460 comma = *lcp->thousands_sep;
461 else
462 comma = ',';
463 }
464 }
465
466 *p = '\0';
467
468 do {
469 if(i%3 == 0 && i != 0)
470 *--p = comma;
471 *--p = '0' + n % 10;
472 n /= 10;
473 i++;
474 } while(n != 0);
475
476 return p;
477 }
478
479 //! Increase or Decrease an array à la \e vector
480 /**
481 \param f_caller : name of the calling function for logging purpose
482 \param array : the array to consider
483 \param new_size : new size needed for the array (in BYTE) :
484 -# if new_size <= 0 : Deallocation of the array
485 -# new_size < \a curr_size_allocated - \a grow_step => Decrease of the array
486 -# new_size >= \a curr_size_allocated => Increase of the array
487 \param curr_size_allocated : current allocated size to the array (in BYTE)
488 \param grow_step : bloc size of expansion of the array (in BYTE)
489 */
490 void
Array_Check_Size(const char * f_caller,char ** array,int new_size,int * curr_size_allocated,int grow_step)491 Array_Check_Size( const char* f_caller, char** array, int new_size, int* curr_size_allocated, int grow_step )
492 {
493 // Deallocation
494 if( new_size <= 0 )
495 {
496 if( *array != NULL )
497 {
498 free(*array);
499 *array = NULL;
500 }
501 *curr_size_allocated = 0;
502 }
503
504 // First allocation
505 else if( *array == NULL )
506 {
507 *curr_size_allocated = grow_step;
508 *array = malloc(*curr_size_allocated );
509 if( *array == NULL)
510 shutdown(1, "Out Of Memory! Failed in %s\n", f_caller);
511 memset( *array, 0, *curr_size_allocated );
512 return;
513 }
514
515 // No need to decrease or increase the array
516 else if( new_size > (*curr_size_allocated - grow_step ) && new_size <= *curr_size_allocated )
517 return;
518
519 //-------------------------------------------
520 // Must increase or decrease the array size
521
522 int old_size = *curr_size_allocated;
523
524 // Recompute needed size
525 *curr_size_allocated = ((int)ceil((float)new_size / (float)grow_step)) * grow_step;
526
527 // Alloc a new array
528 void* copy = malloc(*curr_size_allocated );
529 if(copy == NULL)
530 shutdown(1, "Out Of Memory! Failed in %s\n", f_caller);
531
532 // Copy the previous content of the array
533 memcpy(copy, *array, ( (old_size<new_size) ?old_size :new_size) );
534
535 // Init the new allocations
536 if( old_size < *curr_size_allocated )
537 memset( copy + old_size, 0, *curr_size_allocated - old_size );
538
539 // Free previous array memory
540 free(*array);
541
542 // ReAssign the new allocated array
543 *array = copy;
544 }
545
546