update build instructions
[rofl0r-VisualBoyAdvance.git] / src / Util.c
blob90d6fd807fdea203493f69fca6346591cc616916
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 #include <png.h>
26 #if 0
27 #include "unrarlib.h"
28 #endif
30 #include "System.h"
31 #include "NLS.h"
32 #include "Util.h"
33 #include "Flash.h"
34 #include "GBA.h"
35 #include "Globals.h"
36 #include "RTC.h"
37 #include "Port.h"
40 #include "memgzio.h"
42 #ifndef _MSC_VER
43 #define _stricmp strcasecmp
44 #endif // ! _MSC_VER
46 extern int systemColorDepth;
47 extern int systemRedShift;
48 extern int systemGreenShift;
49 extern int systemBlueShift;
51 extern u16 systemColorMap16[0x10000];
52 extern u32 systemColorMap32[0x10000];
54 static int (ZEXPORT *utilGzWriteFunc)(gzFile, const voidp, unsigned int) = NULL;
55 static int (ZEXPORT *utilGzReadFunc)(gzFile, voidp, unsigned int) = NULL;
56 static int (ZEXPORT *utilGzCloseFunc)(gzFile) = NULL;
58 bool utilWritePNGFile(const char *fileName, int w, int h, u8 *pix)
60 u8 writeBuffer[512 * 3];
62 FILE *fp = fopen(fileName,"wb");
64 if(!fp) {
65 systemMessage(MSG_ERROR_CREATING_FILE, N_("Error creating file %s"), fileName);
66 return false;
69 png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
70 NULL,
71 NULL,
72 NULL);
73 if(!png_ptr) {
74 fclose(fp);
75 return false;
78 png_infop info_ptr = png_create_info_struct(png_ptr);
80 if(!info_ptr) {
81 png_destroy_write_struct(&png_ptr,NULL);
82 fclose(fp);
83 return false;
86 if(setjmp(png_jmpbuf(png_ptr))) {
87 png_destroy_write_struct(&png_ptr,NULL);
88 fclose(fp);
89 return false;
92 png_init_io(png_ptr,fp);
94 png_set_IHDR(png_ptr,
95 info_ptr,
99 PNG_COLOR_TYPE_RGB,
100 PNG_INTERLACE_NONE,
101 PNG_COMPRESSION_TYPE_DEFAULT,
102 PNG_FILTER_TYPE_DEFAULT);
104 png_write_info(png_ptr,info_ptr);
106 u8 *b = writeBuffer;
108 int sizeX = w;
109 int sizeY = h;
111 switch(systemColorDepth) {
112 case 16:
114 u16 *p = (u16 *)(pix+(w+2)*2); // skip first black line
115 for(int y = 0; y < sizeY; y++) {
116 for(int x = 0; x < sizeX; x++) {
117 u16 v = *p++;
119 *b++ = ((v >> systemRedShift) & 0x001f) << 3; // R
120 *b++ = ((v >> systemGreenShift) & 0x001f) << 3; // G
121 *b++ = ((v >> systemBlueShift) & 0x01f) << 3; // B
123 p++; // skip black pixel for filters
124 p++; // skip black pixel for filters
125 png_write_row(png_ptr,writeBuffer);
127 b = writeBuffer;
130 break;
131 case 24:
133 u8 *pixU8 = (u8 *)pix;
134 for(int y = 0; y < sizeY; y++) {
135 for(int x = 0; x < sizeX; x++) {
136 if(systemRedShift < systemBlueShift) {
137 *b++ = *pixU8++; // R
138 *b++ = *pixU8++; // G
139 *b++ = *pixU8++; // B
140 } else {
141 int blue = *pixU8++;
142 int green = *pixU8++;
143 int red = *pixU8++;
145 *b++ = red;
146 *b++ = green;
147 *b++ = blue;
150 png_write_row(png_ptr,writeBuffer);
152 b = writeBuffer;
155 break;
156 case 32:
158 u32 *pixU32 = (u32 *)(pix+4*(w+1));
159 for(int y = 0; y < sizeY; y++) {
160 for(int x = 0; x < sizeX; x++) {
161 u32 v = *pixU32++;
163 *b++ = ((v >> systemRedShift) & 0x001f) << 3; // R
164 *b++ = ((v >> systemGreenShift) & 0x001f) << 3; // G
165 *b++ = ((v >> systemBlueShift) & 0x001f) << 3; // B
167 pixU32++;
169 png_write_row(png_ptr,writeBuffer);
171 b = writeBuffer;
174 break;
177 png_write_end(png_ptr, info_ptr);
179 png_destroy_write_struct(&png_ptr, &info_ptr);
181 fclose(fp);
183 return true;
186 void utilPutDword(u8 *p, u32 value)
188 *p++ = value & 255;
189 *p++ = (value >> 8) & 255;
190 *p++ = (value >> 16) & 255;
191 *p = (value >> 24) & 255;
194 void utilPutWord(u8 *p, u16 value)
196 *p++ = value & 255;
197 *p = (value >> 8) & 255;
200 void utilWriteBMP(char *buf, int w, int h, u8 *pix)
202 u8 *b = (u8 *)buf;
204 int sizeX = w;
205 int sizeY = h;
207 switch(systemColorDepth) {
208 case 16:
210 u16 *p = (u16 *)(pix+(w+2)*(h)*2); // skip first black line
211 for(int y = 0; y < sizeY; y++) {
212 for(int x = 0; x < sizeX; x++) {
213 u16 v = *p++;
215 *b++ = ((v >> systemBlueShift) & 0x01f) << 3; // B
216 *b++ = ((v >> systemGreenShift) & 0x001f) << 3; // G
217 *b++ = ((v >> systemRedShift) & 0x001f) << 3; // R
219 p++; // skip black pixel for filters
220 p++; // skip black pixel for filters
221 p -= 2*(w+2);
224 break;
225 case 24:
227 u8 *pixU8 = (u8 *)pix+3*w*(h-1);
228 for(int y = 0; y < sizeY; y++) {
229 for(int x = 0; x < sizeX; x++) {
230 if(systemRedShift > systemBlueShift) {
231 *b++ = *pixU8++; // B
232 *b++ = *pixU8++; // G
233 *b++ = *pixU8++; // R
234 } else {
235 int red = *pixU8++;
236 int green = *pixU8++;
237 int blue = *pixU8++;
239 *b++ = blue;
240 *b++ = green;
241 *b++ = red;
244 pixU8 -= 2*3*w;
247 break;
248 case 32:
250 u32 *pixU32 = (u32 *)(pix+4*(w+1)*(h));
251 for(int y = 0; y < sizeY; y++) {
252 for(int x = 0; x < sizeX; x++) {
253 u32 v = *pixU32++;
255 *b++ = ((v >> systemBlueShift) & 0x001f) << 3; // B
256 *b++ = ((v >> systemGreenShift) & 0x001f) << 3; // G
257 *b++ = ((v >> systemRedShift) & 0x001f) << 3; // R
259 pixU32++;
260 pixU32 -= 2*(w+1);
263 break;
267 bool utilWriteBMPFile(const char *fileName, int w, int h, u8 *pix)
269 u8 writeBuffer[512 * 3];
271 FILE *fp = fopen(fileName,"wb");
273 if(!fp) {
274 systemMessage(MSG_ERROR_CREATING_FILE, N_("Error creating file %s"), fileName);
275 return false;
278 struct {
279 u8 ident[2];
280 u8 filesize[4];
281 u8 reserved[4];
282 u8 dataoffset[4];
283 u8 headersize[4];
284 u8 width[4];
285 u8 height[4];
286 u8 planes[2];
287 u8 bitsperpixel[2];
288 u8 compression[4];
289 u8 datasize[4];
290 u8 hres[4];
291 u8 vres[4];
292 u8 colors[4];
293 u8 importantcolors[4];
294 // u8 pad[2];
295 } bmpheader;
296 memset(&bmpheader, 0, sizeof(bmpheader));
298 bmpheader.ident[0] = 'B';
299 bmpheader.ident[1] = 'M';
301 u32 fsz = sizeof(bmpheader) + w*h*3;
302 utilPutDword(bmpheader.filesize, fsz);
303 utilPutDword(bmpheader.dataoffset, 0x36);
304 utilPutDword(bmpheader.headersize, 0x28);
305 utilPutDword(bmpheader.width, w);
306 utilPutDword(bmpheader.height, h);
307 utilPutDword(bmpheader.planes, 1);
308 utilPutDword(bmpheader.bitsperpixel, 24);
309 utilPutDword(bmpheader.datasize, 3*w*h);
311 fwrite(&bmpheader, 1, sizeof(bmpheader), fp);
313 u8 *b = writeBuffer;
315 int sizeX = w;
316 int sizeY = h;
318 switch(systemColorDepth) {
319 case 16:
321 u16 *p = (u16 *)(pix+(w+2)*(h)*2); // skip first black line
322 for(int y = 0; y < sizeY; y++) {
323 for(int x = 0; x < sizeX; x++) {
324 u16 v = *p++;
326 *b++ = ((v >> systemBlueShift) & 0x01f) << 3; // B
327 *b++ = ((v >> systemGreenShift) & 0x001f) << 3; // G
328 *b++ = ((v >> systemRedShift) & 0x001f) << 3; // R
330 p++; // skip black pixel for filters
331 p++; // skip black pixel for filters
332 p -= 2*(w+2);
333 fwrite(writeBuffer, 1, 3*w, fp);
335 b = writeBuffer;
338 break;
339 case 24:
341 u8 *pixU8 = (u8 *)pix+3*w*(h-1);
342 for(int y = 0; y < sizeY; y++) {
343 for(int x = 0; x < sizeX; x++) {
344 if(systemRedShift > systemBlueShift) {
345 *b++ = *pixU8++; // B
346 *b++ = *pixU8++; // G
347 *b++ = *pixU8++; // R
348 } else {
349 int red = *pixU8++;
350 int green = *pixU8++;
351 int blue = *pixU8++;
353 *b++ = blue;
354 *b++ = green;
355 *b++ = red;
358 pixU8 -= 2*3*w;
359 fwrite(writeBuffer, 1, 3*w, fp);
361 b = writeBuffer;
364 break;
365 case 32:
367 u32 *pixU32 = (u32 *)(pix+4*(w+1)*(h));
368 for(int y = 0; y < sizeY; y++) {
369 for(int x = 0; x < sizeX; x++) {
370 u32 v = *pixU32++;
372 *b++ = ((v >> systemBlueShift) & 0x001f) << 3; // B
373 *b++ = ((v >> systemGreenShift) & 0x001f) << 3; // G
374 *b++ = ((v >> systemRedShift) & 0x001f) << 3; // R
376 pixU32++;
377 pixU32 -= 2*(w+1);
379 fwrite(writeBuffer, 1, 3*w, fp);
381 b = writeBuffer;
384 break;
387 fclose(fp);
389 return true;
392 static int utilReadInt2(FILE *f)
394 int res = 0;
395 int c = fgetc(f);
396 if(c == EOF)
397 return -1;
398 res = c;
399 c = fgetc(f);
400 if(c == EOF)
401 return -1;
402 return c + (res<<8);
405 static int utilReadInt3(FILE *f)
407 int res = 0;
408 int c = fgetc(f);
409 if(c == EOF)
410 return -1;
411 res = c;
412 c = fgetc(f);
413 if(c == EOF)
414 return -1;
415 res = c + (res<<8);
416 c = fgetc(f);
417 if(c == EOF)
418 return -1;
419 return c + (res<<8);
422 void utilApplyIPS(const char *ips, u8 **r, int *s)
424 // from the IPS spec at http://zerosoft.zophar.net/ips.htm
425 FILE *f = fopen(ips, "rb");
426 if(!f)
427 return;
428 u8 *rom = *r;
429 int size = *s;
430 if(fgetc(f) == 'P' &&
431 fgetc(f) == 'A' &&
432 fgetc(f) == 'T' &&
433 fgetc(f) == 'C' &&
434 fgetc(f) == 'H') {
435 int b;
436 int offset;
437 int len;
438 for(;;) {
439 // read offset
440 offset = utilReadInt3(f);
441 // if offset == EOF, end of patch
442 if(offset == 0x454f46)
443 break;
444 // read length
445 len = utilReadInt2(f);
446 if(!len) {
447 // len == 0, RLE block
448 len = utilReadInt2(f);
449 // byte to fill
450 int c = fgetc(f);
451 if(c == -1)
452 break;
453 b = (u8)c;
454 } else
455 b= -1;
456 // check if we need to reallocate our ROM
457 if((offset + len) >= size) {
458 size *= 2;
459 rom = (u8 *)realloc(rom, size);
460 *r = rom;
461 *s = size;
463 if(b == -1) {
464 // normal block, just read the data
465 if(fread(&rom[offset], 1, len, f) != (size_t)len)
466 break;
467 } else {
468 // fill the region with the given byte
469 while(len--) {
470 rom[offset++] = b;
475 // close the file
476 fclose(f);
479 extern bool cpuIsMultiBoot;
481 bool utilIsGBAImage(const char * file)
483 cpuIsMultiBoot = false;
484 if(strlen(file) > 4) {
485 const char * p = strrchr(file,'.');
487 if(p != NULL) {
488 if(_stricmp(p, ".gba") == 0)
489 return true;
490 if(_stricmp(p, ".agb") == 0)
491 return true;
492 if(_stricmp(p, ".bin") == 0)
493 return true;
494 if(_stricmp(p, ".elf") == 0)
495 return true;
496 if(_stricmp(p, ".mb") == 0) {
497 cpuIsMultiBoot = true;
498 return true;
503 return false;
506 bool utilIsGBImage(const char * file)
508 if(strlen(file) > 4) {
509 const char * p = strrchr(file,'.');
511 if(p != NULL) {
512 if(_stricmp(p, ".gb") == 0)
513 return true;
514 if(_stricmp(p, ".gbc") == 0)
515 return true;
516 if(_stricmp(p, ".cgb") == 0)
517 return true;
518 if(_stricmp(p, ".sgb") == 0)
519 return true;
523 return false;
526 bool utilIsZipFile(const char *file)
528 if(strlen(file) > 4) {
529 const char * p = strrchr(file,'.');
531 if(p != NULL) {
532 if(_stricmp(p, ".zip") == 0)
533 return true;
537 return false;
540 #if 0
541 bool utilIsRarFile(const char *file)
543 if(strlen(file) > 4) {
544 char * p = strrchr(file,'.');
546 if(p != NULL) {
547 if(_stricmp(p, ".rar") == 0)
548 return true;
552 return false;
554 #endif
556 bool utilIsGzipFile(const char *file)
558 if(strlen(file) > 3) {
559 const char * p = strrchr(file,'.');
561 if(p != NULL) {
562 if(_stricmp(p, ".gz") == 0)
563 return true;
564 if(_stricmp(p, ".z") == 0)
565 return true;
569 return false;
572 void utilGetBaseName(const char *file, char *buffer)
574 strcpy(buffer, file);
576 if(utilIsGzipFile(file)) {
577 char *p = strrchr(buffer, '.');
579 if(p)
580 *p = 0;
584 IMAGE_TYPE utilFindType(const char *file)
586 char buffer[2048];
588 if(utilIsZipFile(file)) {
589 unzFile unz = unzOpen(file);
591 if(unz == NULL) {
592 systemMessage(MSG_CANNOT_OPEN_FILE, N_("Cannot open file %s"), file);
593 return IMAGE_UNKNOWN;
596 int r = unzGoToFirstFile(unz);
598 if(r != UNZ_OK) {
599 unzClose(unz);
600 systemMessage(MSG_BAD_ZIP_FILE, N_("Bad ZIP file %s"), file);
601 return IMAGE_UNKNOWN;
604 IMAGE_TYPE found = IMAGE_UNKNOWN;
606 unz_file_info info;
608 while(true) {
609 r = unzGetCurrentFileInfo(unz,
610 &info,
611 buffer,
612 sizeof(buffer),
613 NULL,
615 NULL,
618 if(r != UNZ_OK) {
619 unzClose(unz);
620 systemMessage(MSG_BAD_ZIP_FILE, N_("Bad ZIP file %s"), file);
621 return IMAGE_UNKNOWN;
624 if(utilIsGBAImage(buffer)) {
625 found = IMAGE_GBA;
626 break;
629 if(utilIsGBImage(buffer)) {
630 found = IMAGE_GB;
631 break;
634 r = unzGoToNextFile(unz);
636 if(r != UNZ_OK)
637 break;
639 unzClose(unz);
641 if(found == IMAGE_UNKNOWN) {
642 systemMessage(MSG_NO_IMAGE_ON_ZIP,
643 N_("No image found on ZIP file %s"), file);
644 return found;
646 return found;
647 #if 0
648 } else if(utilIsRarFile(file)) {
649 IMAGE_TYPE found = IMAGE_UNKNOWN;
651 ArchiveList_struct *rarList = NULL;
652 if(urarlib_list((void *)file, (ArchiveList_struct *)&rarList)) {
653 ArchiveList_struct *p = rarList;
655 while(p) {
656 if(utilIsGBAImage(p->item.Name)) {
657 found = IMAGE_GBA;
658 break;
661 if(utilIsGBImage(p->item.Name)) {
662 found = IMAGE_GB;
663 break;
665 p = p->next;
668 urarlib_freelist(rarList);
670 return found;
671 #endif
672 } else {
673 if(utilIsGzipFile(file))
674 utilGetBaseName(file, buffer);
675 else
676 strcpy(buffer, file);
678 if(utilIsGBAImage(buffer))
679 return IMAGE_GBA;
680 if(utilIsGBImage(buffer))
681 return IMAGE_GB;
683 return IMAGE_UNKNOWN;
686 static int utilGetSize(int size)
688 int res = 1;
689 while(res < size)
690 res <<= 1;
691 return res;
694 static u8 *utilLoadFromZip(const char *file,
695 bool (*accept)(const char *),
696 u8 *data,
697 int *size)
699 char buffer[2048];
701 unzFile unz = unzOpen(file);
703 if(unz == NULL) {
704 systemMessage(MSG_CANNOT_OPEN_FILE, N_("Cannot open file %s"), file);
705 return NULL;
707 int r = unzGoToFirstFile(unz);
709 if(r != UNZ_OK) {
710 unzClose(unz);
711 systemMessage(MSG_BAD_ZIP_FILE, N_("Bad ZIP file %s"), file);
712 return NULL;
715 bool found = false;
717 unz_file_info info;
719 while(true) {
720 r = unzGetCurrentFileInfo(unz,
721 &info,
722 buffer,
723 sizeof(buffer),
724 NULL,
726 NULL,
729 if(r != UNZ_OK) {
730 unzClose(unz);
731 systemMessage(MSG_BAD_ZIP_FILE, N_("Bad ZIP file %s"), file);
732 return NULL;
735 if(accept(buffer)) {
736 found = true;
737 break;
740 r = unzGoToNextFile(unz);
742 if(r != UNZ_OK)
743 break;
746 if(!found) {
747 unzClose(unz);
748 systemMessage(MSG_NO_IMAGE_ON_ZIP,
749 N_("No image found on ZIP file %s"), file);
750 return NULL;
753 int fileSize = info.uncompressed_size;
754 if(*size == 0)
755 *size = fileSize;
756 r = unzOpenCurrentFile(unz);
758 if(r != UNZ_OK) {
759 unzClose(unz);
760 systemMessage(MSG_ERROR_OPENING_IMAGE, N_("Error opening image %s"), buffer);
761 return NULL;
764 u8 *image = data;
766 if(image == NULL) {
767 image = (u8 *)malloc(utilGetSize(*size));
768 if(image == NULL) {
769 unzCloseCurrentFile(unz);
770 unzClose(unz);
771 systemMessage(MSG_OUT_OF_MEMORY, N_("Failed to allocate memory for %s"),
772 "data");
773 return NULL;
775 *size = fileSize;
777 int read = fileSize <= *size ? fileSize : *size;
778 r = unzReadCurrentFile(unz,
779 image,
780 read);
782 unzCloseCurrentFile(unz);
783 unzClose(unz);
785 if(r != (int)read) {
786 systemMessage(MSG_ERROR_READING_IMAGE,
787 N_("Error reading image %s"), buffer);
788 if(data == NULL)
789 free(image);
790 return NULL;
793 *size = fileSize;
795 return image;
798 static u8 *utilLoadGzipFile(const char *file,
799 bool (*accept)(const char *),
800 u8 *data,
801 int *size)
803 FILE *f = fopen(file, "rb");
805 if(f == NULL) {
806 systemMessage(MSG_ERROR_OPENING_IMAGE, N_("Error opening image %s"), file);
807 return NULL;
810 fseek(f, -4, SEEK_END);
811 int fileSize = fgetc(f) | (fgetc(f) << 8) | (fgetc(f) << 16) | (fgetc(f) << 24);
812 fclose(f);
813 if(*size == 0)
814 *size = fileSize;
816 gzFile gz = gzopen(file, "rb");
818 if(gz == NULL) {
819 // should not happen, but who knows?
820 systemMessage(MSG_ERROR_OPENING_IMAGE, N_("Error opening image %s"), file);
821 return NULL;
824 u8 *image = data;
826 if(image == NULL) {
827 image = (u8 *)malloc(utilGetSize(*size));
828 if(image == NULL) {
829 systemMessage(MSG_OUT_OF_MEMORY, N_("Failed to allocate memory for %s"),
830 "data");
831 fclose(f);
832 return NULL;
834 *size = fileSize;
836 int read = fileSize <= *size ? fileSize : *size;
837 int r = gzread(gz, image, read);
838 gzclose(gz);
840 if(r != (int)read) {
841 systemMessage(MSG_ERROR_READING_IMAGE,
842 N_("Error reading image %s"), file);
843 if(data == NULL)
844 free(image);
845 return NULL;
848 *size = fileSize;
850 return image;
853 #if 0
854 static u8 *utilLoadRarFile(const char *file,
855 bool (*accept)(const char *),
856 u8 *data,
857 int *size)
859 char buffer[2048];
861 ArchiveList_struct *rarList = NULL;
862 if(urarlib_list((void *)file, (ArchiveList_struct *)&rarList)) {
863 ArchiveList_struct *p = rarList;
865 bool found = false;
866 while(p) {
867 if(accept(p->item.Name)) {
868 strcpy(buffer, p->item.Name);
869 found = true;
870 break;
872 p = p->next;
874 if(found) {
875 void *memory = NULL;
876 unsigned long lsize = 0;
877 *size = p->item.UnpSize;
878 int r = urarlib_get((void *)&memory, &lsize, buffer, (void *)file, "");
879 if(!r) {
880 systemMessage(MSG_ERROR_READING_IMAGE,
881 N_("Error reading image %s"), buffer);
882 urarlib_freelist(rarList);
883 return NULL;
885 u8 *image = (u8 *)memory;
886 if(data != NULL) {
887 memcpy(image, data, *size);
889 urarlib_freelist(rarList);
890 return image;
892 systemMessage(MSG_NO_IMAGE_ON_ZIP,
893 N_("No image found on RAR file %s"), file);
894 urarlib_freelist(rarList);
895 return NULL;
897 // nothing found
898 return NULL;
900 #endif
902 u8 *utilLoad(const char *file,
903 bool (*accept)(const char *),
904 u8 *data,
905 int *size)
907 if(utilIsZipFile(file)) {
908 return utilLoadFromZip(file, accept, data, size);
910 if(utilIsGzipFile(file)) {
911 return utilLoadGzipFile(file, accept, data, size);
913 #if 0
914 if(utilIsRarFile(file)) {
915 return utilLoadRarFile(file, accept, data, size);
917 #endif
919 u8 *image = data;
921 FILE *f = fopen(file, "rb");
923 if(!f) {
924 systemMessage(MSG_ERROR_OPENING_IMAGE, N_("Error opening image %s"), file);
925 return NULL;
928 fseek(f,0,SEEK_END);
929 int fileSize = ftell(f);
930 fseek(f,0,SEEK_SET);
931 if(*size == 0)
932 *size = fileSize;
934 if(image == NULL) {
935 image = (u8 *)malloc(utilGetSize(*size));
936 if(image == NULL) {
937 systemMessage(MSG_OUT_OF_MEMORY, N_("Failed to allocate memory for %s"),
938 "data");
939 fclose(f);
940 return NULL;
942 *size = fileSize;
944 size_t read = fileSize <= *size ? fileSize : *size;
945 size_t r = fread(image, 1, read, f);
946 fclose(f);
948 if(r != read) {
949 systemMessage(MSG_ERROR_READING_IMAGE,
950 N_("Error reading image %s"), file);
951 if(data == NULL)
952 free(image);
953 return NULL;
956 *size = fileSize;
958 return image;
961 void utilWriteInt(gzFile gzFile, int i)
963 utilGzWrite(gzFile, &i, sizeof(int));
966 int utilReadInt(gzFile gzFile)
968 int i = 0;
969 utilGzRead(gzFile, &i, sizeof(int));
970 return i;
973 void utilReadData(gzFile gzFile, variable_desc* data)
975 while(data->address) {
976 utilGzRead(gzFile, data->address, data->size);
977 data++;
981 void utilWriteData(gzFile gzFile, variable_desc *data)
983 while(data->address) {
984 utilGzWrite(gzFile, data->address, data->size);
985 data++;
989 gzFile utilGzOpen(const char *file, const char *mode)
991 utilGzWriteFunc = (int (ZEXPORT *)(gzFile,void * const, unsigned int))gzwrite;
992 utilGzReadFunc = gzread;
993 utilGzCloseFunc = gzclose;
995 return gzopen(file, mode);
998 gzFile utilMemGzOpen(char *memory, int available, char *mode)
1000 utilGzWriteFunc = memgzwrite;
1001 utilGzReadFunc = memgzread;
1002 utilGzCloseFunc = memgzclose;
1004 return memgzopen(memory, available, mode);
1007 int utilGzWrite(gzFile file, const voidp buffer, unsigned int len)
1009 return utilGzWriteFunc(file, buffer, len);
1012 int utilGzRead(gzFile file, voidp buffer, unsigned int len)
1014 return utilGzReadFunc(file, buffer, len);
1017 int utilGzClose(gzFile file)
1019 return utilGzCloseFunc(file);
1022 long utilGzMemTell(gzFile file)
1024 return memtell(file);
1027 void utilGBAFindSave(const u8 *data, const int size)
1029 u32 *p = (u32 *)data;
1030 u32 *end = (u32 *)(data + size);
1031 int saveType = 0;
1032 int flashSize = 0x10000;
1033 bool rtcFound = false;
1035 while(p < end) {
1036 u32 d = READ32LE(p);
1038 if(d == 0x52504545) {
1039 if(memcmp(p, "EEPROM_", 7) == 0) {
1040 if(saveType == 0)
1041 saveType = 3;
1043 } else if (d == 0x4D415253) {
1044 if(memcmp(p, "SRAM_", 5) == 0) {
1045 if(saveType == 0)
1046 saveType = 1;
1048 } else if (d == 0x53414C46) {
1049 if(memcmp(p, "FLASH1M_", 8) == 0) {
1050 if(saveType == 0) {
1051 saveType = 2;
1052 flashSize = 0x20000;
1054 } else if(memcmp(p, "FLASH", 5) == 0) {
1055 if(saveType == 0) {
1056 saveType = 2;
1057 flashSize = 0x10000;
1060 } else if (d == 0x52494953) {
1061 if(memcmp(p, "SIIRTC_V", 8) == 0)
1062 rtcFound = true;
1064 p++;
1066 // if no matches found, then set it to NONE
1067 if(saveType == 0) {
1068 saveType = 5;
1070 rtcEnable(rtcFound);
1071 cpuSaveType = saveType;
1072 flashSetSize(flashSize);
1075 void utilUpdateSystemColorMaps()
1077 switch(systemColorDepth) {
1078 case 16:
1080 for(int i = 0; i < 0x10000; i++) {
1081 systemColorMap16[i] = ((i & 0x1f) << systemRedShift) |
1082 (((i & 0x3e0) >> 5) << systemGreenShift) |
1083 (((i & 0x7c00) >> 10) << systemBlueShift);
1086 break;
1087 case 24:
1088 case 32:
1090 for(int i = 0; i < 0x10000; i++) {
1091 systemColorMap32[i] = ((i & 0x1f) << systemRedShift) |
1092 (((i & 0x3e0) >> 5) << systemGreenShift) |
1093 (((i & 0x7c00) >> 10) << systemBlueShift);
1096 break;