1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <string>
5
6 #ifndef _WIN32
7 #include <unistd.h>
8 #include <sys/stat.h>
9 #else // _WIN32
10 #include <io.h>
11 #include <direct.h>
12 #endif // _WIN32
13
14 #include <zlib.h>
15
16 #ifndef NO_PNG
17 extern "C" {
18 #include <png.h>
19 }
20 #endif
21
22 #include "System.h"
23 #include "NLS.h"
24 #include "Util.h"
25 #include "gba/Flash.h"
26 #include "gba/GBA.h"
27 #include "gba/Globals.h"
28 #include "gba/RTC.h"
29 #include "common/Port.h"
30
31 #include "fex/fex.h"
32
33 extern "C" {
34 #include "common/memgzio.h"
35 }
36
37 #include "gba/gbafilter.h"
38 #include "gb/gbGlobals.h"
39
40 #ifndef _MSC_VER
41 #define _stricmp strcasecmp
42 #endif // ! _MSC_VER
43
44 extern int systemColorDepth;
45 extern int systemRedShift;
46 extern int systemGreenShift;
47 extern int systemBlueShift;
48
49 extern u16 systemColorMap16[0x10000];
50 extern u32 systemColorMap32[0x10000];
51
52 static int (ZEXPORT *utilGzWriteFunc)(gzFile, const voidp, unsigned int) = NULL;
53 static int (ZEXPORT *utilGzReadFunc)(gzFile, voidp, unsigned int) = NULL;
54 static int (ZEXPORT *utilGzCloseFunc)(gzFile) = NULL;
55 static z_off_t (ZEXPORT *utilGzSeekFunc)(gzFile, z_off_t, int) = NULL;
56
FileExists(const char * filename)57 bool FileExists(const char *filename)
58 {
59 #ifdef _WIN32
60 return (_access(filename, 0) != -1);
61 #else
62 struct stat buffer;
63 return (stat(filename, &buffer) == 0);
64 #endif
65 }
66
utilReadScreenPixels(u8 * dest,int w,int h)67 void utilReadScreenPixels(u8* dest, int w, int h)
68 {
69 u8* b = dest;
70 int sizeX = w;
71 int sizeY = h;
72 switch (systemColorDepth) {
73 case 16:
74 {
75 u16 *p = (u16 *) (pix + (w + 2) * 2); // skip first black line
76 for (int y = 0; y < sizeY; y++) {
77 for (int x = 0; x < sizeX; x++) {
78 u16 v = *p++;
79
80 *b++ = ((v >> systemRedShift) & 0x001f) << 3; // R
81 *b++ = ((v >> systemGreenShift) & 0x001f) << 3; // G
82 *b++ = ((v >> systemBlueShift) & 0x01f) << 3; // B
83 }
84 p++; // skip black pixel for filters
85 p++; // skip black pixel for filters
86 }
87 }
88 break;
89 case 24:
90 {
91 u8 *pixU8 = (u8 *) pix;
92 for (int y = 0; y < sizeY; y++) {
93 for (int x = 0; x < sizeX; x++) {
94 if (systemRedShift < systemBlueShift) {
95 *b++ = *pixU8++; // R
96 *b++ = *pixU8++; // G
97 *b++ = *pixU8++; // B
98 }
99 else {
100 int blue = *pixU8++;
101 int green = *pixU8++;
102 int red = *pixU8++;
103
104 *b++ = red;
105 *b++ = green;
106 *b++ = blue;
107 }
108 }
109 }
110 }
111 break;
112 case 32:
113 {
114 u32 *pixU32 = (u32 *) (pix + 4 * (w + 1));
115 for (int y = 0; y < sizeY; y++) {
116 for (int x = 0; x < sizeX; x++) {
117 u32 v = *pixU32++;
118 *b++ = ((v >> systemBlueShift) & 0x001f) << 3; // B
119 *b++ = ((v >> systemGreenShift) & 0x001f) << 3; // G
120 *b++ = ((v >> systemRedShift) & 0x001f) << 3; // R
121 }
122 pixU32++;
123 }
124 }
125 break;
126 }
127 }
128
utilWritePNGFile(const char * fileName,int w,int h,u8 * pix)129 bool utilWritePNGFile(const char *fileName, int w, int h, u8 *pix)
130 {
131 #ifndef NO_PNG
132 u8 writeBuffer[512 * 3];
133
134 FILE *fp = fopen(fileName,"wb");
135
136 if(!fp) {
137 systemMessage(MSG_ERROR_CREATING_FILE, N_("Error creating file %s"), fileName);
138 return false;
139 }
140
141 png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
142 NULL,
143 NULL,
144 NULL);
145 if(!png_ptr) {
146 fclose(fp);
147 return false;
148 }
149
150 png_infop info_ptr = png_create_info_struct(png_ptr);
151
152 if(!info_ptr) {
153 png_destroy_write_struct(&png_ptr,NULL);
154 fclose(fp);
155 return false;
156 }
157
158 if(setjmp(png_jmpbuf(png_ptr))) {
159 png_destroy_write_struct(&png_ptr,NULL);
160 fclose(fp);
161 return false;
162 }
163
164 png_init_io(png_ptr,fp);
165
166 png_set_IHDR(png_ptr,
167 info_ptr,
168 w,
169 h,
170 8,
171 PNG_COLOR_TYPE_RGB,
172 PNG_INTERLACE_NONE,
173 PNG_COMPRESSION_TYPE_DEFAULT,
174 PNG_FILTER_TYPE_DEFAULT);
175
176 png_write_info(png_ptr,info_ptr);
177
178 u8 *b = writeBuffer;
179
180 int sizeX = w;
181 int sizeY = h;
182
183 switch(systemColorDepth) {
184 case 16:
185 {
186 u16 *p = (u16 *)(pix+(w+2)*2); // skip first black line
187 for(int y = 0; y < sizeY; y++) {
188 for(int x = 0; x < sizeX; x++) {
189 u16 v = *p++;
190
191 *b++ = ((v >> systemRedShift) & 0x001f) << 3; // R
192 *b++ = ((v >> systemGreenShift) & 0x001f) << 3; // G
193 *b++ = ((v >> systemBlueShift) & 0x01f) << 3; // B
194 }
195 p++; // skip black pixel for filters
196 p++; // skip black pixel for filters
197 png_write_row(png_ptr,writeBuffer);
198
199 b = writeBuffer;
200 }
201 }
202 break;
203 case 24:
204 {
205 u8 *pixU8 = (u8 *)pix;
206 for(int y = 0; y < sizeY; y++) {
207 for(int x = 0; x < sizeX; x++) {
208 if(systemRedShift < systemBlueShift) {
209 *b++ = *pixU8++; // R
210 *b++ = *pixU8++; // G
211 *b++ = *pixU8++; // B
212 } else {
213 int blue = *pixU8++;
214 int green = *pixU8++;
215 int red = *pixU8++;
216
217 *b++ = red;
218 *b++ = green;
219 *b++ = blue;
220 }
221 }
222 png_write_row(png_ptr,writeBuffer);
223
224 b = writeBuffer;
225 }
226 }
227 break;
228 case 32:
229 {
230 u32 *pixU32 = (u32 *)(pix+4*(w+1));
231 for(int y = 0; y < sizeY; y++) {
232 for(int x = 0; x < sizeX; x++) {
233 u32 v = *pixU32++;
234
235 *b++ = ((v >> systemRedShift) & 0x001f) << 3; // R
236 *b++ = ((v >> systemGreenShift) & 0x001f) << 3; // G
237 *b++ = ((v >> systemBlueShift) & 0x001f) << 3; // B
238 }
239 pixU32++;
240
241 png_write_row(png_ptr,writeBuffer);
242
243 b = writeBuffer;
244 }
245 }
246 break;
247 }
248
249 png_write_end(png_ptr, info_ptr);
250
251 png_destroy_write_struct(&png_ptr, &info_ptr);
252
253 fclose(fp);
254
255 return true;
256 #else
257 return false;
258 #endif
259 }
260
utilPutDword(u8 * p,u32 value)261 void utilPutDword(u8 *p, u32 value)
262 {
263 *p++ = value & 255;
264 *p++ = (value >> 8) & 255;
265 *p++ = (value >> 16) & 255;
266 *p = (value >> 24) & 255;
267 }
268
utilPutWord(u8 * p,u16 value)269 void utilPutWord(u8 *p, u16 value)
270 {
271 *p++ = value & 255;
272 *p = (value >> 8) & 255;
273 }
274
utilWriteBMPFile(const char * fileName,int w,int h,u8 * pix)275 bool utilWriteBMPFile(const char *fileName, int w, int h, u8 *pix)
276 {
277 u8 writeBuffer[512 * 3];
278
279 FILE *fp = fopen(fileName,"wb");
280
281 if(!fp) {
282 systemMessage(MSG_ERROR_CREATING_FILE, N_("Error creating file %s"), fileName);
283 return false;
284 }
285
286 struct {
287 u8 ident[2];
288 u8 filesize[4];
289 u8 reserved[4];
290 u8 dataoffset[4];
291 u8 headersize[4];
292 u8 width[4];
293 u8 height[4];
294 u8 planes[2];
295 u8 bitsperpixel[2];
296 u8 compression[4];
297 u8 datasize[4];
298 u8 hres[4];
299 u8 vres[4];
300 u8 colors[4];
301 u8 importantcolors[4];
302 // u8 pad[2];
303 } bmpheader;
304 memset(&bmpheader, 0, sizeof(bmpheader));
305
306 bmpheader.ident[0] = 'B';
307 bmpheader.ident[1] = 'M';
308
309 u32 fsz = sizeof(bmpheader) + w*h*3;
310 utilPutDword(bmpheader.filesize, fsz);
311 utilPutDword(bmpheader.dataoffset, 0x36);
312 utilPutDword(bmpheader.headersize, 0x28);
313 utilPutDword(bmpheader.width, w);
314 utilPutDword(bmpheader.height, h);
315 utilPutDword(bmpheader.planes, 1);
316 utilPutDword(bmpheader.bitsperpixel, 24);
317 utilPutDword(bmpheader.datasize, 3*w*h);
318
319 fwrite(&bmpheader, 1, sizeof(bmpheader), fp);
320
321 u8 *b = writeBuffer;
322
323 int sizeX = w;
324 int sizeY = h;
325
326 switch(systemColorDepth) {
327 case 16:
328 {
329 u16 *p = (u16 *)(pix+(w+2)*(h)*2); // skip first black line
330 for(int y = 0; y < sizeY; y++) {
331 for(int x = 0; x < sizeX; x++) {
332 u16 v = *p++;
333
334 *b++ = ((v >> systemBlueShift) & 0x01f) << 3; // B
335 *b++ = ((v >> systemGreenShift) & 0x001f) << 3; // G
336 *b++ = ((v >> systemRedShift) & 0x001f) << 3; // R
337 }
338 p++; // skip black pixel for filters
339 p++; // skip black pixel for filters
340 p -= 2*(w+2);
341 fwrite(writeBuffer, 1, 3*w, fp);
342
343 b = writeBuffer;
344 }
345 }
346 break;
347 case 24:
348 {
349 u8 *pixU8 = (u8 *)pix+3*w*(h-1);
350 for(int y = 0; y < sizeY; y++) {
351 for(int x = 0; x < sizeX; x++) {
352 if(systemRedShift > systemBlueShift) {
353 *b++ = *pixU8++; // B
354 *b++ = *pixU8++; // G
355 *b++ = *pixU8++; // R
356 } else {
357 int red = *pixU8++;
358 int green = *pixU8++;
359 int blue = *pixU8++;
360
361 *b++ = blue;
362 *b++ = green;
363 *b++ = red;
364 }
365 }
366 pixU8 -= 2*3*w;
367 fwrite(writeBuffer, 1, 3*w, fp);
368
369 b = writeBuffer;
370 }
371 }
372 break;
373 case 32:
374 {
375 u32 *pixU32 = (u32 *)(pix+4*(w+1)*(h));
376 for(int y = 0; y < sizeY; y++) {
377 for(int x = 0; x < sizeX; x++) {
378 u32 v = *pixU32++;
379
380 *b++ = ((v >> systemBlueShift) & 0x001f) << 3; // B
381 *b++ = ((v >> systemGreenShift) & 0x001f) << 3; // G
382 *b++ = ((v >> systemRedShift) & 0x001f) << 3; // R
383 }
384 pixU32++;
385 pixU32 -= 2*(w+1);
386
387 fwrite(writeBuffer, 1, 3*w, fp);
388
389 b = writeBuffer;
390 }
391 }
392 break;
393 }
394
395 fclose(fp);
396
397 return true;
398 }
399
400 extern bool cpuIsMultiBoot;
401
utilIsGBAImage(const char * file)402 bool utilIsGBAImage(const char * file)
403 {
404 cpuIsMultiBoot = false;
405 if(strlen(file) > 4) {
406 const char * p = strrchr(file,'.');
407
408 if(p != NULL) {
409 if((_stricmp(p, ".agb") == 0) ||
410 (_stricmp(p, ".gba") == 0) ||
411 (_stricmp(p, ".bin") == 0) ||
412 (_stricmp(p, ".elf") == 0))
413 return true;
414 if(_stricmp(p, ".mb") == 0) {
415 cpuIsMultiBoot = true;
416 return true;
417 }
418 }
419 }
420
421 return false;
422 }
423
utilIsGBImage(const char * file)424 bool utilIsGBImage(const char * file)
425 {
426 if(strlen(file) > 4) {
427 const char * p = strrchr(file,'.');
428
429 if(p != NULL) {
430 if((_stricmp(p, ".dmg") == 0) ||
431 (_stricmp(p, ".gb") == 0) ||
432 (_stricmp(p, ".gbc") == 0) ||
433 (_stricmp(p, ".cgb") == 0) ||
434 (_stricmp(p, ".sgb") == 0))
435 return true;
436 }
437 }
438
439 return false;
440 }
441
utilIsGzipFile(const char * file)442 bool utilIsGzipFile(const char *file)
443 {
444 if(strlen(file) > 3) {
445 const char * p = strrchr(file,'.');
446
447 if(p != NULL) {
448 if(_stricmp(p, ".gz") == 0)
449 return true;
450 if(_stricmp(p, ".z") == 0)
451 return true;
452 }
453 }
454
455 return false;
456 }
457
458 // strip .gz or .z off end
utilStripDoubleExtension(const char * file,char * buffer)459 void utilStripDoubleExtension(const char *file, char *buffer)
460 {
461 if(buffer != file) // allows conversion in place
462 strcpy(buffer, file);
463
464 if(utilIsGzipFile(file)) {
465 char *p = strrchr(buffer, '.');
466
467 if(p)
468 *p = 0;
469 }
470 }
471
472 // Opens and scans archive using accept(). Returns fex_t if found.
473 // If error or not found, displays message and returns NULL.
scan_arc(const char * file,bool (* accept)(const char *),char (& buffer)[2048])474 static fex_t* scan_arc(const char *file, bool (*accept)(const char *),
475 char (&buffer) [2048] )
476 {
477 fex_t* fe;
478 fex_err_t err = fex_open( &fe, file );
479 if(!fe)
480 {
481 systemMessage(MSG_CANNOT_OPEN_FILE, N_("Cannot open file %s: %s"), file, err);
482 return NULL;
483 }
484
485 // Scan filenames
486 bool found=false;
487 while(!fex_done(fe)) {
488 strncpy(buffer,fex_name(fe),sizeof buffer);
489 buffer [sizeof buffer-1] = '\0';
490
491 utilStripDoubleExtension(buffer, buffer);
492
493 if(accept(buffer)) {
494 found = true;
495 break;
496 }
497
498 fex_err_t err = fex_next(fe);
499 if(err) {
500 systemMessage(MSG_BAD_ZIP_FILE, N_("Cannot read archive %s: %s"), file, err);
501 fex_close(fe);
502 return NULL;
503 }
504 }
505
506 if(!found) {
507 systemMessage(MSG_NO_IMAGE_ON_ZIP,
508 N_("No image found in file %s"), file);
509 fex_close(fe);
510 return NULL;
511 }
512 return fe;
513 }
514
utilIsImage(const char * file)515 static bool utilIsImage(const char *file)
516 {
517 return utilIsGBAImage(file) || utilIsGBImage(file);
518 }
519
520 #ifdef WIN32
521 #include <windows.h>
522 #endif
523
524 IMAGE_TYPE utilFindType(const char *file, char (&buffer)[2048]);
525
utilFindType(const char * file)526 IMAGE_TYPE utilFindType(const char *file)
527 {
528 char buffer [2048];
529 return utilFindType(file, buffer);
530 }
531
utilFindType(const char * file,char (& buffer)[2048])532 IMAGE_TYPE utilFindType(const char *file, char (&buffer)[2048])
533 {
534 #ifdef WIN32
535 DWORD dwNum = MultiByteToWideChar (CP_ACP, 0, file, -1, NULL, 0);
536 wchar_t *pwText;
537 pwText = new wchar_t[dwNum];
538 if(!pwText)
539 {
540 return IMAGE_UNKNOWN;
541 }
542 MultiByteToWideChar (CP_ACP, 0, file, -1, pwText, dwNum );
543 char* file_conv = fex_wide_to_path( pwText);
544 // if ( !utilIsImage( file_conv ) ) // TODO: utilIsArchive() instead?
545 // {
546 fex_t* fe = scan_arc(file_conv,utilIsImage,buffer);
547 if(!fe)
548 return IMAGE_UNKNOWN;
549 fex_close(fe);
550 file = buffer;
551 // }
552 free(file_conv);
553 #else
554 // if ( !utilIsImage( file ) ) // TODO: utilIsArchive() instead?
555 // {
556 fex_t* fe = scan_arc(file,utilIsImage,buffer);
557 if(!fe)
558 return IMAGE_UNKNOWN;
559 fex_close(fe);
560 file = buffer;
561 // }
562 #endif
563 return utilIsGBAImage(file) ? IMAGE_GBA : IMAGE_GB;
564 }
565
utilGetSize(int size)566 static int utilGetSize(int size)
567 {
568 int res = 1;
569 while(res < size)
570 res <<= 1;
571 return res;
572 }
573
utilLoad(const char * file,bool (* accept)(const char *),u8 * data,int & size)574 u8 *utilLoad(const char *file,
575 bool (*accept)(const char *),
576 u8 *data,
577 int &size)
578 {
579 // find image file
580 char buffer [2048];
581 #ifdef WIN32
582 DWORD dwNum = MultiByteToWideChar (CP_ACP, 0, file, -1, NULL, 0);
583 wchar_t *pwText;
584 pwText = new wchar_t[dwNum];
585 if(!pwText)
586 {
587 return NULL;
588 }
589 MultiByteToWideChar (CP_ACP, 0, file, -1, pwText, dwNum );
590 char* file_conv = fex_wide_to_path( pwText);
591 delete []pwText;
592 fex_t *fe = scan_arc(file_conv,accept,buffer);
593 if(!fe)
594 return NULL;
595 free(file_conv);
596 #else
597 fex_t *fe = scan_arc(file,accept,buffer);
598 if(!fe)
599 return NULL;
600 #endif
601 // Allocate space for image
602 fex_err_t err = fex_stat(fe);
603 int fileSize = fex_size(fe);
604 if(size == 0)
605 size = fileSize;
606
607 u8 *image = data;
608
609 if(image == NULL) {
610 // allocate buffer memory if none was passed to the function
611 image = (u8 *)malloc(utilGetSize(size));
612 if(image == NULL) {
613 fex_close(fe);
614 systemMessage(MSG_OUT_OF_MEMORY, N_("Failed to allocate memory for %s"),
615 "data");
616 return NULL;
617 }
618 size = fileSize;
619 }
620
621 // Read image
622 int read = fileSize <= size ? fileSize : size; // do not read beyond file
623 err = fex_read(fe, image, read);
624 fex_close(fe);
625 if(err) {
626 systemMessage(MSG_ERROR_READING_IMAGE,
627 N_("Error reading image from %s: %s"), buffer, err);
628 if(data == NULL)
629 free(image);
630 return NULL;
631 }
632
633 size = fileSize;
634
635 return image;
636 }
637
replaceAll(std::string & str,const std::string & from,const std::string & to)638 void replaceAll(std::string& str, const std::string& from, const std::string& to) {
639 if (from.empty())
640 return;
641 size_t start_pos = 0;
642 while ((start_pos = str.find(from, start_pos)) != std::string::npos) {
643 str.replace(start_pos, from.length(), to);
644 start_pos += to.length(); // In case 'to' contains 'from', like replacing 'x' with 'yx'
645 }
646 }
647
utilExtract(const char * filepath,const char * filename)648 void utilExtract(const char* filepath, const char* filename)
649 {
650 fex_t* fex;
651 std::string archive_name(filepath);
652 archive_name.append(filename);
653
654 fex_open(&fex, archive_name.c_str());
655 while (!fex_done(fex))
656 {
657 std::string extracted_filename(filepath);
658 extracted_filename.append(fex_name(fex));
659 #ifdef WIN32
660 replaceAll(extracted_filename, "/", "\\");
661 #endif
662
663 std::string new_dir(filepath);
664 new_dir.append(fex_name(fex));
665 #ifdef WIN32
666 replaceAll(new_dir, "/", "\\");
667 #endif
668 new_dir = new_dir.substr(0, new_dir.find_last_of("\\"));
669 if (!FileExists(new_dir.c_str()))
670 mkdir(new_dir.c_str()
671 #ifndef WIN32
672 ,0777
673 #endif
674 );
675
676 if (FileExists(extracted_filename.c_str()))
677 {
678 std::string new_name(filepath);
679 new_name.append("old-");
680 new_name.append(fex_name(fex));
681 #ifdef WIN32
682 replaceAll(new_name, "/", "\\");
683 #endif
684 remove(new_name.c_str());
685 rename(extracted_filename.c_str(), new_name.c_str());
686 }
687
688 FILE *extracted_file = fopen(extracted_filename.c_str(), "wb");
689 const void* p;
690 fex_data(fex, &p);
691 fwrite(p, fex_size(fex), 1, extracted_file);
692 fclose(extracted_file);
693 fex_next(fex);
694 }
695 fex_close(fex);
696
697 }
698
utilWriteInt(gzFile gzFile,int i)699 void utilWriteInt(gzFile gzFile, int i)
700 {
701 utilGzWrite(gzFile, &i, sizeof(int));
702 }
703
utilReadInt(gzFile gzFile)704 int utilReadInt(gzFile gzFile)
705 {
706 int i = 0;
707 utilGzRead(gzFile, &i, sizeof(int));
708 return i;
709 }
710
utilReadData(gzFile gzFile,variable_desc * data)711 void utilReadData(gzFile gzFile, variable_desc* data)
712 {
713 while(data->address) {
714 utilGzRead(gzFile, data->address, data->size);
715 data++;
716 }
717 }
718
utilReadDataSkip(gzFile gzFile,variable_desc * data)719 void utilReadDataSkip(gzFile gzFile, variable_desc* data)
720 {
721 while(data->address) {
722 utilGzSeek(gzFile, data->size, SEEK_CUR);
723 data++;
724 }
725 }
726
utilWriteData(gzFile gzFile,variable_desc * data)727 void utilWriteData(gzFile gzFile, variable_desc *data)
728 {
729 while(data->address) {
730 utilGzWrite(gzFile, data->address, data->size);
731 data++;
732 }
733 }
734
utilGzOpen(const char * file,const char * mode)735 gzFile utilGzOpen(const char *file, const char *mode)
736 {
737 utilGzWriteFunc = (int (ZEXPORT *)(gzFile, void * const, unsigned int))gzwrite;
738 utilGzReadFunc = gzread;
739 utilGzCloseFunc = gzclose;
740 utilGzSeekFunc = gzseek;
741
742 return gzopen(file, mode);
743 }
744
utilMemGzOpen(char * memory,int available,const char * mode)745 gzFile utilMemGzOpen(char *memory, int available, const char *mode)
746 {
747 utilGzWriteFunc = memgzwrite;
748 utilGzReadFunc = memgzread;
749 utilGzCloseFunc = memgzclose;
750 utilGzSeekFunc = memgzseek;
751
752 return memgzopen(memory, available, mode);
753 }
754
utilGzWrite(gzFile file,const voidp buffer,unsigned int len)755 int utilGzWrite(gzFile file, const voidp buffer, unsigned int len)
756 {
757 return utilGzWriteFunc(file, buffer, len);
758 }
759
utilGzRead(gzFile file,voidp buffer,unsigned int len)760 int utilGzRead(gzFile file, voidp buffer, unsigned int len)
761 {
762 return utilGzReadFunc(file, buffer, len);
763 }
764
utilGzClose(gzFile file)765 int utilGzClose(gzFile file)
766 {
767 return utilGzCloseFunc(file);
768 }
769
utilGzSeek(gzFile file,z_off_t offset,int whence)770 z_off_t utilGzSeek(gzFile file, z_off_t offset, int whence)
771 {
772 return utilGzSeekFunc(file, offset, whence);
773 }
774
utilGzMemTell(gzFile file)775 long utilGzMemTell(gzFile file)
776 {
777 return memtell(file);
778 }
779
utilGBAFindSave(const int size)780 void utilGBAFindSave(const int size)
781 {
782 u32 *p = (u32 *)&rom[0];
783 u32 *end = (u32 *)(&rom[0] + size);
784 int detectedSaveType = 0;
785 int flashSize = 0x10000;
786 bool rtcFound = false;
787
788 while(p < end) {
789 u32 d = READ32LE(p);
790
791 if(d == 0x52504545) {
792 if(memcmp(p, "EEPROM_", 7) == 0) {
793 if(detectedSaveType == 0 || detectedSaveType == 4)
794 detectedSaveType = 1;
795 }
796 } else if (d == 0x4D415253) {
797 if(memcmp(p, "SRAM_", 5) == 0) {
798 if(detectedSaveType == 0 || detectedSaveType == 1 || detectedSaveType == 4)
799 detectedSaveType = 2;
800 }
801 } else if (d == 0x53414C46) {
802 if(memcmp(p, "FLASH1M_", 8) == 0) {
803 if(detectedSaveType == 0) {
804 detectedSaveType = 3;
805 flashSize = 0x20000;
806 }
807 } else if (memcmp(p, "FLASH512_", 9) == 0) {
808 if (detectedSaveType == 0) {
809 detectedSaveType = 3;
810 flashSize = 0x10000;
811 }
812 } else if(memcmp(p, "FLASH", 5) == 0) {
813 if(detectedSaveType == 0) {
814 detectedSaveType = 4;
815 flashSize = 0x10000;
816 }
817 }
818 } else if (d == 0x52494953) {
819 if(memcmp(p, "SIIRTC_V", 8) == 0)
820 rtcFound = true;
821 }
822 p++;
823 }
824 // if no matches found, then set it to NONE
825 if(detectedSaveType == 0) {
826 detectedSaveType = 5;
827 }
828 if(detectedSaveType == 4) {
829 detectedSaveType = 3;
830 }
831 rtcEnable(rtcFound);
832 rtcEnableRumble(!rtcFound);
833 saveType = detectedSaveType;
834 flashSetSize(flashSize);
835 }
836
utilUpdateSystemColorMaps(bool lcd)837 void utilUpdateSystemColorMaps(bool lcd)
838 {
839 switch(systemColorDepth) {
840 case 16:
841 {
842 for(int i = 0; i < 0x10000; i++) {
843 systemColorMap16[i] = ((i & 0x1f) << systemRedShift) |
844 (((i & 0x3e0) >> 5) << systemGreenShift) |
845 (((i & 0x7c00) >> 10) << systemBlueShift);
846 }
847 if (lcd) gbafilter_pal(systemColorMap16, 0x10000);
848 }
849 break;
850 case 24:
851 case 32:
852 {
853 for(int i = 0; i < 0x10000; i++) {
854 systemColorMap32[i] = ((i & 0x1f) << systemRedShift) |
855 (((i & 0x3e0) >> 5) << systemGreenShift) |
856 (((i & 0x7c00) >> 10) << systemBlueShift);
857 }
858 if (lcd) gbafilter_pal32(systemColorMap32, 0x10000);
859 }
860 break;
861 }
862 }
863
864 // Check for existence of file.
utilFileExists(const char * filename)865 bool utilFileExists( const char *filename )
866 {
867 FILE *f = fopen( filename, "r" );
868 if( f == NULL ) {
869 return false;
870 } else {
871 fclose( f );
872 return true;
873 }
874 }
875