configure.in: default profiling to off, as its broken
[rofl0r-VisualBoyAdvance.git] / src / Util.cpp
blob7f188c2f74dc88dce2ee3d0541379af292acd728
1 // VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
2 // Copyright (C) 1999-2003 Forgotten
3 // Copyright (C) 2004-2006 Forgotten and the VBA development team
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; either version 2, or(at your option)
8 // any later version.
9 //
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software Foundation,
17 // Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include <zlib.h>
24 extern "C" {
25 #include <png.h>
28 #if 0
29 #include "unrarlib.h"
30 #endif
32 #include "System.h"
33 #include "NLS.h"
34 #include "Util.h"
35 #include "Flash.h"
36 #include "GBA.h"
37 #include "Globals.h"
38 #include "RTC.h"
39 #include "Port.h"
42 extern "C" {
43 #include "memgzio.h"
46 #ifndef _MSC_VER
47 #define _stricmp strcasecmp
48 #endif // ! _MSC_VER
50 extern int systemColorDepth;
51 extern int systemRedShift;
52 extern int systemGreenShift;
53 extern int systemBlueShift;
55 extern u16 systemColorMap16[0x10000];
56 extern u32 systemColorMap32[0x10000];
58 static int (ZEXPORT *utilGzWriteFunc)(gzFile, const voidp, unsigned int) = NULL;
59 static int (ZEXPORT *utilGzReadFunc)(gzFile, voidp, unsigned int) = NULL;
60 static int (ZEXPORT *utilGzCloseFunc)(gzFile) = NULL;
62 bool utilWritePNGFile(const char *fileName, int w, int h, u8 *pix)
64 u8 writeBuffer[512 * 3];
66 FILE *fp = fopen(fileName,"wb");
68 if(!fp) {
69 systemMessage(MSG_ERROR_CREATING_FILE, N_("Error creating file %s"), fileName);
70 return false;
73 png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
74 NULL,
75 NULL,
76 NULL);
77 if(!png_ptr) {
78 fclose(fp);
79 return false;
82 png_infop info_ptr = png_create_info_struct(png_ptr);
84 if(!info_ptr) {
85 png_destroy_write_struct(&png_ptr,NULL);
86 fclose(fp);
87 return false;
90 if(setjmp(png_jmpbuf(png_ptr))) {
91 png_destroy_write_struct(&png_ptr,NULL);
92 fclose(fp);
93 return false;
96 png_init_io(png_ptr,fp);
98 png_set_IHDR(png_ptr,
99 info_ptr,
103 PNG_COLOR_TYPE_RGB,
104 PNG_INTERLACE_NONE,
105 PNG_COMPRESSION_TYPE_DEFAULT,
106 PNG_FILTER_TYPE_DEFAULT);
108 png_write_info(png_ptr,info_ptr);
110 u8 *b = writeBuffer;
112 int sizeX = w;
113 int sizeY = h;
115 switch(systemColorDepth) {
116 case 16:
118 u16 *p = (u16 *)(pix+(w+2)*2); // skip first black line
119 for(int y = 0; y < sizeY; y++) {
120 for(int x = 0; x < sizeX; x++) {
121 u16 v = *p++;
123 *b++ = ((v >> systemRedShift) & 0x001f) << 3; // R
124 *b++ = ((v >> systemGreenShift) & 0x001f) << 3; // G
125 *b++ = ((v >> systemBlueShift) & 0x01f) << 3; // B
127 p++; // skip black pixel for filters
128 p++; // skip black pixel for filters
129 png_write_row(png_ptr,writeBuffer);
131 b = writeBuffer;
134 break;
135 case 24:
137 u8 *pixU8 = (u8 *)pix;
138 for(int y = 0; y < sizeY; y++) {
139 for(int x = 0; x < sizeX; x++) {
140 if(systemRedShift < systemBlueShift) {
141 *b++ = *pixU8++; // R
142 *b++ = *pixU8++; // G
143 *b++ = *pixU8++; // B
144 } else {
145 int blue = *pixU8++;
146 int green = *pixU8++;
147 int red = *pixU8++;
149 *b++ = red;
150 *b++ = green;
151 *b++ = blue;
154 png_write_row(png_ptr,writeBuffer);
156 b = writeBuffer;
159 break;
160 case 32:
162 u32 *pixU32 = (u32 *)(pix+4*(w+1));
163 for(int y = 0; y < sizeY; y++) {
164 for(int x = 0; x < sizeX; x++) {
165 u32 v = *pixU32++;
167 *b++ = ((v >> systemRedShift) & 0x001f) << 3; // R
168 *b++ = ((v >> systemGreenShift) & 0x001f) << 3; // G
169 *b++ = ((v >> systemBlueShift) & 0x001f) << 3; // B
171 pixU32++;
173 png_write_row(png_ptr,writeBuffer);
175 b = writeBuffer;
178 break;
181 png_write_end(png_ptr, info_ptr);
183 png_destroy_write_struct(&png_ptr, &info_ptr);
185 fclose(fp);
187 return true;
190 void utilPutDword(u8 *p, u32 value)
192 *p++ = value & 255;
193 *p++ = (value >> 8) & 255;
194 *p++ = (value >> 16) & 255;
195 *p = (value >> 24) & 255;
198 void utilPutWord(u8 *p, u16 value)
200 *p++ = value & 255;
201 *p = (value >> 8) & 255;
204 void utilWriteBMP(char *buf, int w, int h, u8 *pix)
206 u8 *b = (u8 *)buf;
208 int sizeX = w;
209 int sizeY = h;
211 switch(systemColorDepth) {
212 case 16:
214 u16 *p = (u16 *)(pix+(w+2)*(h)*2); // skip first black line
215 for(int y = 0; y < sizeY; y++) {
216 for(int x = 0; x < sizeX; x++) {
217 u16 v = *p++;
219 *b++ = ((v >> systemBlueShift) & 0x01f) << 3; // B
220 *b++ = ((v >> systemGreenShift) & 0x001f) << 3; // G
221 *b++ = ((v >> systemRedShift) & 0x001f) << 3; // R
223 p++; // skip black pixel for filters
224 p++; // skip black pixel for filters
225 p -= 2*(w+2);
228 break;
229 case 24:
231 u8 *pixU8 = (u8 *)pix+3*w*(h-1);
232 for(int y = 0; y < sizeY; y++) {
233 for(int x = 0; x < sizeX; x++) {
234 if(systemRedShift > systemBlueShift) {
235 *b++ = *pixU8++; // B
236 *b++ = *pixU8++; // G
237 *b++ = *pixU8++; // R
238 } else {
239 int red = *pixU8++;
240 int green = *pixU8++;
241 int blue = *pixU8++;
243 *b++ = blue;
244 *b++ = green;
245 *b++ = red;
248 pixU8 -= 2*3*w;
251 break;
252 case 32:
254 u32 *pixU32 = (u32 *)(pix+4*(w+1)*(h));
255 for(int y = 0; y < sizeY; y++) {
256 for(int x = 0; x < sizeX; x++) {
257 u32 v = *pixU32++;
259 *b++ = ((v >> systemBlueShift) & 0x001f) << 3; // B
260 *b++ = ((v >> systemGreenShift) & 0x001f) << 3; // G
261 *b++ = ((v >> systemRedShift) & 0x001f) << 3; // R
263 pixU32++;
264 pixU32 -= 2*(w+1);
267 break;
271 bool utilWriteBMPFile(const char *fileName, int w, int h, u8 *pix)
273 u8 writeBuffer[512 * 3];
275 FILE *fp = fopen(fileName,"wb");
277 if(!fp) {
278 systemMessage(MSG_ERROR_CREATING_FILE, N_("Error creating file %s"), fileName);
279 return false;
282 struct {
283 u8 ident[2];
284 u8 filesize[4];
285 u8 reserved[4];
286 u8 dataoffset[4];
287 u8 headersize[4];
288 u8 width[4];
289 u8 height[4];
290 u8 planes[2];
291 u8 bitsperpixel[2];
292 u8 compression[4];
293 u8 datasize[4];
294 u8 hres[4];
295 u8 vres[4];
296 u8 colors[4];
297 u8 importantcolors[4];
298 // u8 pad[2];
299 } bmpheader;
300 memset(&bmpheader, 0, sizeof(bmpheader));
302 bmpheader.ident[0] = 'B';
303 bmpheader.ident[1] = 'M';
305 u32 fsz = sizeof(bmpheader) + w*h*3;
306 utilPutDword(bmpheader.filesize, fsz);
307 utilPutDword(bmpheader.dataoffset, 0x36);
308 utilPutDword(bmpheader.headersize, 0x28);
309 utilPutDword(bmpheader.width, w);
310 utilPutDword(bmpheader.height, h);
311 utilPutDword(bmpheader.planes, 1);
312 utilPutDword(bmpheader.bitsperpixel, 24);
313 utilPutDword(bmpheader.datasize, 3*w*h);
315 fwrite(&bmpheader, 1, sizeof(bmpheader), fp);
317 u8 *b = writeBuffer;
319 int sizeX = w;
320 int sizeY = h;
322 switch(systemColorDepth) {
323 case 16:
325 u16 *p = (u16 *)(pix+(w+2)*(h)*2); // skip first black line
326 for(int y = 0; y < sizeY; y++) {
327 for(int x = 0; x < sizeX; x++) {
328 u16 v = *p++;
330 *b++ = ((v >> systemBlueShift) & 0x01f) << 3; // B
331 *b++ = ((v >> systemGreenShift) & 0x001f) << 3; // G
332 *b++ = ((v >> systemRedShift) & 0x001f) << 3; // R
334 p++; // skip black pixel for filters
335 p++; // skip black pixel for filters
336 p -= 2*(w+2);
337 fwrite(writeBuffer, 1, 3*w, fp);
339 b = writeBuffer;
342 break;
343 case 24:
345 u8 *pixU8 = (u8 *)pix+3*w*(h-1);
346 for(int y = 0; y < sizeY; y++) {
347 for(int x = 0; x < sizeX; x++) {
348 if(systemRedShift > systemBlueShift) {
349 *b++ = *pixU8++; // B
350 *b++ = *pixU8++; // G
351 *b++ = *pixU8++; // R
352 } else {
353 int red = *pixU8++;
354 int green = *pixU8++;
355 int blue = *pixU8++;
357 *b++ = blue;
358 *b++ = green;
359 *b++ = red;
362 pixU8 -= 2*3*w;
363 fwrite(writeBuffer, 1, 3*w, fp);
365 b = writeBuffer;
368 break;
369 case 32:
371 u32 *pixU32 = (u32 *)(pix+4*(w+1)*(h));
372 for(int y = 0; y < sizeY; y++) {
373 for(int x = 0; x < sizeX; x++) {
374 u32 v = *pixU32++;
376 *b++ = ((v >> systemBlueShift) & 0x001f) << 3; // B
377 *b++ = ((v >> systemGreenShift) & 0x001f) << 3; // G
378 *b++ = ((v >> systemRedShift) & 0x001f) << 3; // R
380 pixU32++;
381 pixU32 -= 2*(w+1);
383 fwrite(writeBuffer, 1, 3*w, fp);
385 b = writeBuffer;
388 break;
391 fclose(fp);
393 return true;
396 static int utilReadInt2(FILE *f)
398 int res = 0;
399 int c = fgetc(f);
400 if(c == EOF)
401 return -1;
402 res = c;
403 c = fgetc(f);
404 if(c == EOF)
405 return -1;
406 return c + (res<<8);
409 static int utilReadInt3(FILE *f)
411 int res = 0;
412 int c = fgetc(f);
413 if(c == EOF)
414 return -1;
415 res = c;
416 c = fgetc(f);
417 if(c == EOF)
418 return -1;
419 res = c + (res<<8);
420 c = fgetc(f);
421 if(c == EOF)
422 return -1;
423 return c + (res<<8);
426 void utilApplyIPS(const char *ips, u8 **r, int *s)
428 // from the IPS spec at http://zerosoft.zophar.net/ips.htm
429 FILE *f = fopen(ips, "rb");
430 if(!f)
431 return;
432 u8 *rom = *r;
433 int size = *s;
434 if(fgetc(f) == 'P' &&
435 fgetc(f) == 'A' &&
436 fgetc(f) == 'T' &&
437 fgetc(f) == 'C' &&
438 fgetc(f) == 'H') {
439 int b;
440 int offset;
441 int len;
442 for(;;) {
443 // read offset
444 offset = utilReadInt3(f);
445 // if offset == EOF, end of patch
446 if(offset == 0x454f46)
447 break;
448 // read length
449 len = utilReadInt2(f);
450 if(!len) {
451 // len == 0, RLE block
452 len = utilReadInt2(f);
453 // byte to fill
454 int c = fgetc(f);
455 if(c == -1)
456 break;
457 b = (u8)c;
458 } else
459 b= -1;
460 // check if we need to reallocate our ROM
461 if((offset + len) >= size) {
462 size *= 2;
463 rom = (u8 *)realloc(rom, size);
464 *r = rom;
465 *s = size;
467 if(b == -1) {
468 // normal block, just read the data
469 if(fread(&rom[offset], 1, len, f) != (size_t)len)
470 break;
471 } else {
472 // fill the region with the given byte
473 while(len--) {
474 rom[offset++] = b;
479 // close the file
480 fclose(f);
483 extern bool cpuIsMultiBoot;
485 bool utilIsGBAImage(const char * file)
487 cpuIsMultiBoot = false;
488 if(strlen(file) > 4) {
489 const char * p = strrchr(file,'.');
491 if(p != NULL) {
492 if(_stricmp(p, ".gba") == 0)
493 return true;
494 if(_stricmp(p, ".agb") == 0)
495 return true;
496 if(_stricmp(p, ".bin") == 0)
497 return true;
498 if(_stricmp(p, ".elf") == 0)
499 return true;
500 if(_stricmp(p, ".mb") == 0) {
501 cpuIsMultiBoot = true;
502 return true;
507 return false;
510 bool utilIsGBImage(const char * file)
512 if(strlen(file) > 4) {
513 const char * p = strrchr(file,'.');
515 if(p != NULL) {
516 if(_stricmp(p, ".gb") == 0)
517 return true;
518 if(_stricmp(p, ".gbc") == 0)
519 return true;
520 if(_stricmp(p, ".cgb") == 0)
521 return true;
522 if(_stricmp(p, ".sgb") == 0)
523 return true;
527 return false;
530 bool utilIsZipFile(const char *file)
532 if(strlen(file) > 4) {
533 const char * p = strrchr(file,'.');
535 if(p != NULL) {
536 if(_stricmp(p, ".zip") == 0)
537 return true;
541 return false;
544 #if 0
545 bool utilIsRarFile(const char *file)
547 if(strlen(file) > 4) {
548 char * p = strrchr(file,'.');
550 if(p != NULL) {
551 if(_stricmp(p, ".rar") == 0)
552 return true;
556 return false;
558 #endif
560 bool utilIsGzipFile(const char *file)
562 if(strlen(file) > 3) {
563 const char * p = strrchr(file,'.');
565 if(p != NULL) {
566 if(_stricmp(p, ".gz") == 0)
567 return true;
568 if(_stricmp(p, ".z") == 0)
569 return true;
573 return false;
576 void utilGetBaseName(const char *file, char *buffer)
578 strcpy(buffer, file);
580 if(utilIsGzipFile(file)) {
581 char *p = strrchr(buffer, '.');
583 if(p)
584 *p = 0;
588 IMAGE_TYPE utilFindType(const char *file)
590 char buffer[2048];
592 if(utilIsZipFile(file)) {
593 unzFile unz = unzOpen(file);
595 if(unz == NULL) {
596 systemMessage(MSG_CANNOT_OPEN_FILE, N_("Cannot open file %s"), file);
597 return IMAGE_UNKNOWN;
600 int r = unzGoToFirstFile(unz);
602 if(r != UNZ_OK) {
603 unzClose(unz);
604 systemMessage(MSG_BAD_ZIP_FILE, N_("Bad ZIP file %s"), file);
605 return IMAGE_UNKNOWN;
608 IMAGE_TYPE found = IMAGE_UNKNOWN;
610 unz_file_info info;
612 while(true) {
613 r = unzGetCurrentFileInfo(unz,
614 &info,
615 buffer,
616 sizeof(buffer),
617 NULL,
619 NULL,
622 if(r != UNZ_OK) {
623 unzClose(unz);
624 systemMessage(MSG_BAD_ZIP_FILE, N_("Bad ZIP file %s"), file);
625 return IMAGE_UNKNOWN;
628 if(utilIsGBAImage(buffer)) {
629 found = IMAGE_GBA;
630 break;
633 if(utilIsGBImage(buffer)) {
634 found = IMAGE_GB;
635 break;
638 r = unzGoToNextFile(unz);
640 if(r != UNZ_OK)
641 break;
643 unzClose(unz);
645 if(found == IMAGE_UNKNOWN) {
646 systemMessage(MSG_NO_IMAGE_ON_ZIP,
647 N_("No image found on ZIP file %s"), file);
648 return found;
650 return found;
651 #if 0
652 } else if(utilIsRarFile(file)) {
653 IMAGE_TYPE found = IMAGE_UNKNOWN;
655 ArchiveList_struct *rarList = NULL;
656 if(urarlib_list((void *)file, (ArchiveList_struct *)&rarList)) {
657 ArchiveList_struct *p = rarList;
659 while(p) {
660 if(utilIsGBAImage(p->item.Name)) {
661 found = IMAGE_GBA;
662 break;
665 if(utilIsGBImage(p->item.Name)) {
666 found = IMAGE_GB;
667 break;
669 p = p->next;
672 urarlib_freelist(rarList);
674 return found;
675 #endif
676 } else {
677 if(utilIsGzipFile(file))
678 utilGetBaseName(file, buffer);
679 else
680 strcpy(buffer, file);
682 if(utilIsGBAImage(buffer))
683 return IMAGE_GBA;
684 if(utilIsGBImage(buffer))
685 return IMAGE_GB;
687 return IMAGE_UNKNOWN;
690 static int utilGetSize(int size)
692 int res = 1;
693 while(res < size)
694 res <<= 1;
695 return res;
698 static u8 *utilLoadFromZip(const char *file,
699 bool (*accept)(const char *),
700 u8 *data,
701 int &size)
703 char buffer[2048];
705 unzFile unz = unzOpen(file);
707 if(unz == NULL) {
708 systemMessage(MSG_CANNOT_OPEN_FILE, N_("Cannot open file %s"), file);
709 return NULL;
711 int r = unzGoToFirstFile(unz);
713 if(r != UNZ_OK) {
714 unzClose(unz);
715 systemMessage(MSG_BAD_ZIP_FILE, N_("Bad ZIP file %s"), file);
716 return NULL;
719 bool found = false;
721 unz_file_info info;
723 while(true) {
724 r = unzGetCurrentFileInfo(unz,
725 &info,
726 buffer,
727 sizeof(buffer),
728 NULL,
730 NULL,
733 if(r != UNZ_OK) {
734 unzClose(unz);
735 systemMessage(MSG_BAD_ZIP_FILE, N_("Bad ZIP file %s"), file);
736 return NULL;
739 if(accept(buffer)) {
740 found = true;
741 break;
744 r = unzGoToNextFile(unz);
746 if(r != UNZ_OK)
747 break;
750 if(!found) {
751 unzClose(unz);
752 systemMessage(MSG_NO_IMAGE_ON_ZIP,
753 N_("No image found on ZIP file %s"), file);
754 return NULL;
757 int fileSize = info.uncompressed_size;
758 if(size == 0)
759 size = fileSize;
760 r = unzOpenCurrentFile(unz);
762 if(r != UNZ_OK) {
763 unzClose(unz);
764 systemMessage(MSG_ERROR_OPENING_IMAGE, N_("Error opening image %s"), buffer);
765 return NULL;
768 u8 *image = data;
770 if(image == NULL) {
771 image = (u8 *)malloc(utilGetSize(size));
772 if(image == NULL) {
773 unzCloseCurrentFile(unz);
774 unzClose(unz);
775 systemMessage(MSG_OUT_OF_MEMORY, N_("Failed to allocate memory for %s"),
776 "data");
777 return NULL;
779 size = fileSize;
781 int read = fileSize <= size ? fileSize : size;
782 r = unzReadCurrentFile(unz,
783 image,
784 read);
786 unzCloseCurrentFile(unz);
787 unzClose(unz);
789 if(r != (int)read) {
790 systemMessage(MSG_ERROR_READING_IMAGE,
791 N_("Error reading image %s"), buffer);
792 if(data == NULL)
793 free(image);
794 return NULL;
797 size = fileSize;
799 return image;
802 static u8 *utilLoadGzipFile(const char *file,
803 bool (*accept)(const char *),
804 u8 *data,
805 int &size)
807 FILE *f = fopen(file, "rb");
809 if(f == NULL) {
810 systemMessage(MSG_ERROR_OPENING_IMAGE, N_("Error opening image %s"), file);
811 return NULL;
814 fseek(f, -4, SEEK_END);
815 int fileSize = fgetc(f) | (fgetc(f) << 8) | (fgetc(f) << 16) | (fgetc(f) << 24);
816 fclose(f);
817 if(size == 0)
818 size = fileSize;
820 gzFile gz = gzopen(file, "rb");
822 if(gz == NULL) {
823 // should not happen, but who knows?
824 systemMessage(MSG_ERROR_OPENING_IMAGE, N_("Error opening image %s"), file);
825 return NULL;
828 u8 *image = data;
830 if(image == NULL) {
831 image = (u8 *)malloc(utilGetSize(size));
832 if(image == NULL) {
833 systemMessage(MSG_OUT_OF_MEMORY, N_("Failed to allocate memory for %s"),
834 "data");
835 fclose(f);
836 return NULL;
838 size = fileSize;
840 int read = fileSize <= size ? fileSize : size;
841 int r = gzread(gz, image, read);
842 gzclose(gz);
844 if(r != (int)read) {
845 systemMessage(MSG_ERROR_READING_IMAGE,
846 N_("Error reading image %s"), file);
847 if(data == NULL)
848 free(image);
849 return NULL;
852 size = fileSize;
854 return image;
857 #if 0
858 static u8 *utilLoadRarFile(const char *file,
859 bool (*accept)(const char *),
860 u8 *data,
861 int &size)
863 char buffer[2048];
865 ArchiveList_struct *rarList = NULL;
866 if(urarlib_list((void *)file, (ArchiveList_struct *)&rarList)) {
867 ArchiveList_struct *p = rarList;
869 bool found = false;
870 while(p) {
871 if(accept(p->item.Name)) {
872 strcpy(buffer, p->item.Name);
873 found = true;
874 break;
876 p = p->next;
878 if(found) {
879 void *memory = NULL;
880 unsigned long lsize = 0;
881 size = p->item.UnpSize;
882 int r = urarlib_get((void *)&memory, &lsize, buffer, (void *)file, "");
883 if(!r) {
884 systemMessage(MSG_ERROR_READING_IMAGE,
885 N_("Error reading image %s"), buffer);
886 urarlib_freelist(rarList);
887 return NULL;
889 u8 *image = (u8 *)memory;
890 if(data != NULL) {
891 memcpy(image, data, size);
893 urarlib_freelist(rarList);
894 return image;
896 systemMessage(MSG_NO_IMAGE_ON_ZIP,
897 N_("No image found on RAR file %s"), file);
898 urarlib_freelist(rarList);
899 return NULL;
901 // nothing found
902 return NULL;
904 #endif
906 u8 *utilLoad(const char *file,
907 bool (*accept)(const char *),
908 u8 *data,
909 int &size)
911 if(utilIsZipFile(file)) {
912 return utilLoadFromZip(file, accept, data, size);
914 if(utilIsGzipFile(file)) {
915 return utilLoadGzipFile(file, accept, data, size);
917 #if 0
918 if(utilIsRarFile(file)) {
919 return utilLoadRarFile(file, accept, data, size);
921 #endif
923 u8 *image = data;
925 FILE *f = fopen(file, "rb");
927 if(!f) {
928 systemMessage(MSG_ERROR_OPENING_IMAGE, N_("Error opening image %s"), file);
929 return NULL;
932 fseek(f,0,SEEK_END);
933 int fileSize = ftell(f);
934 fseek(f,0,SEEK_SET);
935 if(size == 0)
936 size = fileSize;
938 if(image == NULL) {
939 image = (u8 *)malloc(utilGetSize(size));
940 if(image == NULL) {
941 systemMessage(MSG_OUT_OF_MEMORY, N_("Failed to allocate memory for %s"),
942 "data");
943 fclose(f);
944 return NULL;
946 size = fileSize;
948 size_t read = fileSize <= size ? fileSize : size;
949 size_t r = fread(image, 1, read, f);
950 fclose(f);
952 if(r != read) {
953 systemMessage(MSG_ERROR_READING_IMAGE,
954 N_("Error reading image %s"), file);
955 if(data == NULL)
956 free(image);
957 return NULL;
960 size = fileSize;
962 return image;
965 void utilWriteInt(gzFile gzFile, int i)
967 utilGzWrite(gzFile, &i, sizeof(int));
970 int utilReadInt(gzFile gzFile)
972 int i = 0;
973 utilGzRead(gzFile, &i, sizeof(int));
974 return i;
977 void utilReadData(gzFile gzFile, variable_desc* data)
979 while(data->address) {
980 utilGzRead(gzFile, data->address, data->size);
981 data++;
985 void utilWriteData(gzFile gzFile, variable_desc *data)
987 while(data->address) {
988 utilGzWrite(gzFile, data->address, data->size);
989 data++;
993 gzFile utilGzOpen(const char *file, const char *mode)
995 utilGzWriteFunc = (int (ZEXPORT *)(gzFile,void * const, unsigned int))gzwrite;
996 utilGzReadFunc = gzread;
997 utilGzCloseFunc = gzclose;
999 return gzopen(file, mode);
1002 gzFile utilMemGzOpen(char *memory, int available, char *mode)
1004 utilGzWriteFunc = memgzwrite;
1005 utilGzReadFunc = memgzread;
1006 utilGzCloseFunc = memgzclose;
1008 return memgzopen(memory, available, mode);
1011 int utilGzWrite(gzFile file, const voidp buffer, unsigned int len)
1013 return utilGzWriteFunc(file, buffer, len);
1016 int utilGzRead(gzFile file, voidp buffer, unsigned int len)
1018 return utilGzReadFunc(file, buffer, len);
1021 int utilGzClose(gzFile file)
1023 return utilGzCloseFunc(file);
1026 long utilGzMemTell(gzFile file)
1028 return memtell(file);
1031 void utilGBAFindSave(const u8 *data, const int size)
1033 u32 *p = (u32 *)data;
1034 u32 *end = (u32 *)(data + size);
1035 int saveType = 0;
1036 int flashSize = 0x10000;
1037 bool rtcFound = false;
1039 while(p < end) {
1040 u32 d = READ32LE(p);
1042 if(d == 0x52504545) {
1043 if(memcmp(p, "EEPROM_", 7) == 0) {
1044 if(saveType == 0)
1045 saveType = 3;
1047 } else if (d == 0x4D415253) {
1048 if(memcmp(p, "SRAM_", 5) == 0) {
1049 if(saveType == 0)
1050 saveType = 1;
1052 } else if (d == 0x53414C46) {
1053 if(memcmp(p, "FLASH1M_", 8) == 0) {
1054 if(saveType == 0) {
1055 saveType = 2;
1056 flashSize = 0x20000;
1058 } else if(memcmp(p, "FLASH", 5) == 0) {
1059 if(saveType == 0) {
1060 saveType = 2;
1061 flashSize = 0x10000;
1064 } else if (d == 0x52494953) {
1065 if(memcmp(p, "SIIRTC_V", 8) == 0)
1066 rtcFound = true;
1068 p++;
1070 // if no matches found, then set it to NONE
1071 if(saveType == 0) {
1072 saveType = 5;
1074 rtcEnable(rtcFound);
1075 cpuSaveType = saveType;
1076 flashSetSize(flashSize);
1079 void utilUpdateSystemColorMaps()
1081 switch(systemColorDepth) {
1082 case 16:
1084 for(int i = 0; i < 0x10000; i++) {
1085 systemColorMap16[i] = ((i & 0x1f) << systemRedShift) |
1086 (((i & 0x3e0) >> 5) << systemGreenShift) |
1087 (((i & 0x7c00) >> 10) << systemBlueShift);
1090 break;
1091 case 24:
1092 case 32:
1094 for(int i = 0; i < 0x10000; i++) {
1095 systemColorMap32[i] = ((i & 0x1f) << systemRedShift) |
1096 (((i & 0x3e0) >> 5) << systemGreenShift) |
1097 (((i & 0x7c00) >> 10) << systemBlueShift);
1100 break;