comparison src/common/Util.cpp @ 1:f9f4f1b99eed

importing src directory
author Robert McIntyre <rlm@mit.edu>
date Sat, 03 Mar 2012 10:31:27 -0600
parents
children f94fa48624d0
comparison
equal deleted inserted replaced
0:8ced16adf2e1 1:f9f4f1b99eed
1 #include <cstdio>
2 #include <cstdlib>
3 #include <cstring>
4 #include <zlib.h>
5
6 extern "C" {
7 #include <png.h>
8 }
9
10 #if 0
11 #include "unrarlib.h"
12 #endif
13
14 #include "unzip.h"
15
16 #include "../NLS.h"
17 #include "System.h"
18 #include "Util.h"
19 #include "../gba/Flash.h"
20 #include "../gba/RTC.h"
21
22 extern "C" {
23 #include "memgzio.h"
24 }
25
26 #ifndef _MSC_VER
27 #define _stricmp strcasecmp
28 #endif // ! _MSC_VER
29
30 extern int32 cpuSaveType;
31
32 extern int systemColorDepth;
33 extern int systemRedShift;
34 extern int systemGreenShift;
35 extern int systemBlueShift;
36
37 extern u16 systemColorMap16[0x10000];
38 extern u32 systemColorMap32[0x10000];
39
40 static int (ZEXPORT *utilGzWriteFunc)(gzFile, voidp, unsigned int) = NULL;
41 static int (ZEXPORT *utilGzReadFunc)(gzFile, voidp, unsigned int) = NULL;
42 static int (ZEXPORT *utilGzCloseFunc)(gzFile) = NULL;
43 static z_off_t (ZEXPORT *utilGzSeekFunc)(gzFile, z_off_t, int) = NULL;
44 static z_off_t (ZEXPORT *utilGzTellFunc)(gzFile) = NULL;
45
46 //Kludge to get it to compile in Linux, GCC cannot convert
47 //gzwrite function pointer to the type of utilGzWriteFunc
48 //due to void* and const void* differences
49 //--Felipe
50 int gzWrite(gzFile file, void* buf, unsigned len){
51 return gzwrite(file,buf,len);
52 }
53
54 void utilPutDword(u8 *p, u32 value)
55 {
56 *p++ = value & 255;
57 *p++ = (value >> 8) & 255;
58 *p++ = (value >> 16) & 255;
59 *p = (value >> 24) & 255;
60 }
61
62 void utilPutWord(u8 *p, u16 value)
63 {
64 *p++ = value & 255;
65 *p = (value >> 8) & 255;
66 }
67
68 void utilWriteBMP(u8 *b, int w, int h, int dstDepth, u8 *pix)
69 {
70 int sizeX = w;
71 int sizeY = h;
72
73 switch (dstDepth > 0 ? dstDepth : systemColorDepth)
74 {
75 case 16:
76 {
77 u16 *p = (u16 *)(pix + (w + 2) * (h) * 2); // skip first black line
78 for (int y = 0; y < sizeY; y++)
79 {
80 for (int x = 0; x < sizeX; x++)
81 {
82 u16 v = *p++;
83
84 *b++ = ((v >> systemBlueShift) & 0x01f) << 3; // B
85 *b++ = ((v >> systemGreenShift) & 0x001f) << 3; // G
86 *b++ = ((v >> systemRedShift) & 0x001f) << 3; // R
87 }
88 p++; // skip black pixel for filters
89 p++; // skip black pixel for filters
90 p -= 2 * (w + 2);
91 }
92 break;
93 }
94 case 24:
95 {
96 u8 *pixU8 = (u8 *)pix + 3 * w * (h - 1);
97 for (int y = 0; y < sizeY; y++)
98 {
99 for (int x = 0; x < sizeX; x++)
100 {
101 if (systemRedShift > systemBlueShift)
102 {
103 *b++ = *pixU8++; // B
104 *b++ = *pixU8++; // G
105 *b++ = *pixU8++; // R
106 }
107 else
108 {
109 int red = *pixU8++;
110 int green = *pixU8++;
111 int blue = *pixU8++;
112
113 *b++ = blue;
114 *b++ = green;
115 *b++ = red;
116 }
117 }
118 pixU8 -= 2 * 3 * w;
119 }
120 break;
121 }
122 case 32:
123 {
124 u32 *pixU32 = (u32 *)(pix + 4 * (w + 1) * (h));
125 for (int y = 0; y < sizeY; y++)
126 {
127 for (int x = 0; x < sizeX; x++)
128 {
129 u32 v = *pixU32++;
130
131 *b++ = ((v >> systemBlueShift) & 0x001f) << 3; // B
132 *b++ = ((v >> systemGreenShift) & 0x001f) << 3; // G
133 *b++ = ((v >> systemRedShift) & 0x001f) << 3; // R
134 }
135 pixU32++;
136 pixU32 -= 2 * (w + 1);
137 }
138 break;
139 }
140 }
141 }
142
143 bool utilWriteBMPFile(const char *fileName, int w, int h, u8 *pix)
144 {
145 u8 writeBuffer[256 * 3];
146
147 FILE *fp = fopen(fileName, "wb");
148
149 if (!fp)
150 {
151 systemMessage(MSG_ERROR_CREATING_FILE, N_("Error creating file %s"), fileName);
152 return false;
153 }
154
155 struct
156 {
157 u8 ident[2];
158 u8 filesize[4];
159 u8 reserved[4];
160 u8 dataoffset[4];
161 u8 headersize[4];
162 u8 width[4];
163 u8 height[4];
164 u8 planes[2];
165 u8 bitsperpixel[2];
166 u8 compression[4];
167 u8 datasize[4];
168 u8 hres[4];
169 u8 vres[4];
170 u8 colors[4];
171 u8 importantcolors[4];
172 // u8 pad[2];
173 } bmpheader;
174 memset(&bmpheader, 0, sizeof(bmpheader));
175
176 bmpheader.ident[0] = 'B';
177 bmpheader.ident[1] = 'M';
178
179 u32 fsz = sizeof(bmpheader) + w * h * 3;
180 utilPutDword(bmpheader.filesize, fsz);
181 utilPutDword(bmpheader.dataoffset, 0x36);
182 utilPutDword(bmpheader.headersize, 0x28);
183 utilPutDword(bmpheader.width, w);
184 utilPutDword(bmpheader.height, h);
185 utilPutDword(bmpheader.planes, 1);
186 utilPutDword(bmpheader.bitsperpixel, 24);
187 utilPutDword(bmpheader.datasize, 3 * w * h);
188
189 fwrite(&bmpheader, 1, sizeof(bmpheader), fp);
190
191 #if 0
192 // FIXME: need sufficient buffer
193 utilWriteBMP(writeBuffer, w, h, systemColorDepth, pix);
194 #else
195 u8 *b = writeBuffer;
196
197 int sizeX = w;
198 int sizeY = h;
199
200 switch (systemColorDepth)
201 {
202 case 16:
203 {
204 u16 *p = (u16 *)(pix + (w + 2) * (h) * 2); // skip first black line
205 for (int y = 0; y < sizeY; y++)
206 {
207 for (int x = 0; x < sizeX; x++)
208 {
209 u16 v = *p++;
210
211 *b++ = ((v >> systemBlueShift) & 0x01f) << 3; // B
212 *b++ = ((v >> systemGreenShift) & 0x001f) << 3; // G
213 *b++ = ((v >> systemRedShift) & 0x001f) << 3; // R
214 }
215 p++; // skip black pixel for filters
216 p++; // skip black pixel for filters
217 p -= 2 * (w + 2);
218 fwrite(writeBuffer, 1, 3 * w, fp);
219
220 b = writeBuffer;
221 }
222 break;
223 }
224 case 24:
225 {
226 u8 *pixU8 = (u8 *)pix + 3 * w * (h - 1);
227 for (int y = 0; y < sizeY; y++)
228 {
229 for (int x = 0; x < sizeX; x++)
230 {
231 if (systemRedShift > systemBlueShift)
232 {
233 *b++ = *pixU8++; // B
234 *b++ = *pixU8++; // G
235 *b++ = *pixU8++; // R
236 }
237 else
238 {
239 int red = *pixU8++;
240 int green = *pixU8++;
241 int blue = *pixU8++;
242
243 *b++ = blue;
244 *b++ = green;
245 *b++ = red;
246 }
247 }
248 pixU8 -= 2 * 3 * w;
249 fwrite(writeBuffer, 1, 3 * w, fp);
250
251 b = writeBuffer;
252 }
253 break;
254 }
255 case 32:
256 {
257 u32 *pixU32 = (u32 *)(pix + 4 * (w + 1) * (h));
258 for (int y = 0; y < sizeY; y++)
259 {
260 for (int x = 0; x < sizeX; x++)
261 {
262 u32 v = *pixU32++;
263
264 *b++ = ((v >> systemBlueShift) & 0x001f) << 3; // B
265 *b++ = ((v >> systemGreenShift) & 0x001f) << 3; // G
266 *b++ = ((v >> systemRedShift) & 0x001f) << 3; // R
267 }
268 pixU32++;
269 pixU32 -= 2 * (w + 1);
270
271 fwrite(writeBuffer, 1, 3 * w, fp);
272
273 b = writeBuffer;
274 }
275 break;
276 }
277 }
278 #endif
279
280 fclose(fp);
281
282 return true;
283 }
284
285 bool utilWritePNGFile(const char *fileName, int w, int h, u8 *pix)
286 {
287 u8 writeBuffer[256 * 3];
288
289 FILE *fp = fopen(fileName, "wb");
290
291 if (!fp)
292 {
293 systemMessage(MSG_ERROR_CREATING_FILE, N_("Error creating file %s"), fileName);
294 return false;
295 }
296
297 png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
298 NULL,
299 NULL,
300 NULL);
301 if (!png_ptr)
302 {
303 fclose(fp);
304 return false;
305 }
306
307 png_infop info_ptr = png_create_info_struct(png_ptr);
308
309 if (!info_ptr)
310 {
311 png_destroy_write_struct(&png_ptr, NULL);
312 fclose(fp);
313 return false;
314 }
315
316 if (setjmp(png_ptr->jmpbuf))
317 {
318 png_destroy_write_struct(&png_ptr, NULL);
319 fclose(fp);
320 return false;
321 }
322
323 png_init_io(png_ptr, fp);
324
325 png_set_IHDR(png_ptr,
326 info_ptr,
327 w,
328 h,
329 8,
330 PNG_COLOR_TYPE_RGB,
331 PNG_INTERLACE_NONE,
332 PNG_COMPRESSION_TYPE_DEFAULT,
333 PNG_FILTER_TYPE_DEFAULT);
334
335 png_write_info(png_ptr, info_ptr);
336
337 u8 *b = writeBuffer;
338
339 int sizeX = w;
340 int sizeY = h;
341
342 switch (systemColorDepth)
343 {
344 case 16:
345 {
346 u16 *p = (u16 *)(pix + (w + 2) * 2); // skip first black line
347 for (int y = 0; y < sizeY; y++)
348 {
349 for (int x = 0; x < sizeX; x++)
350 {
351 u16 v = *p++;
352
353 *b++ = ((v >> systemRedShift) & 0x001f) << 3; // R
354 *b++ = ((v >> systemGreenShift) & 0x001f) << 3; // G
355 *b++ = ((v >> systemBlueShift) & 0x01f) << 3; // B
356 }
357 p++; // skip black pixel for filters
358 p++; // skip black pixel for filters
359 png_write_row(png_ptr, writeBuffer);
360
361 b = writeBuffer;
362 }
363 break;
364 }
365 case 24:
366 {
367 u8 *pixU8 = (u8 *)pix;
368 for (int y = 0; y < sizeY; y++)
369 {
370 for (int x = 0; x < sizeX; x++)
371 {
372 if (systemRedShift < systemBlueShift)
373 {
374 *b++ = *pixU8++; // R
375 *b++ = *pixU8++; // G
376 *b++ = *pixU8++; // B
377 }
378 else
379 {
380 int blue = *pixU8++;
381 int green = *pixU8++;
382 int red = *pixU8++;
383
384 *b++ = red;
385 *b++ = green;
386 *b++ = blue;
387 }
388 }
389 png_write_row(png_ptr, writeBuffer);
390
391 b = writeBuffer;
392 }
393 break;
394 }
395 case 32:
396 {
397 u32 *pixU32 = (u32 *)(pix + 4 * (w + 1));
398 for (int y = 0; y < sizeY; y++)
399 {
400 for (int x = 0; x < sizeX; x++)
401 {
402 u32 v = *pixU32++;
403
404 *b++ = ((v >> systemRedShift) & 0x001f) << 3; // R
405 *b++ = ((v >> systemGreenShift) & 0x001f) << 3; // G
406 *b++ = ((v >> systemBlueShift) & 0x001f) << 3; // B
407 }
408 pixU32++;
409
410 png_write_row(png_ptr, writeBuffer);
411
412 b = writeBuffer;
413 }
414 break;
415 }
416 }
417
418 png_write_end(png_ptr, info_ptr);
419
420 png_destroy_write_struct(&png_ptr, &info_ptr);
421
422 fclose(fp);
423
424 return true;
425 }
426
427 static int utilReadInt2(FILE *f)
428 {
429 int res = 0;
430 int c = fgetc(f);
431 if (c == EOF)
432 return -1;
433 res = c;
434 c = fgetc(f);
435 if (c == EOF)
436 return -1;
437 return c + (res << 8);
438 }
439
440 static int utilReadInt3(FILE *f)
441 {
442 int res = 0;
443 int c = fgetc(f);
444 if (c == EOF)
445 return -1;
446 res = c;
447 c = fgetc(f);
448 if (c == EOF)
449 return -1;
450 res = c + (res << 8);
451 c = fgetc(f);
452 if (c == EOF)
453 return -1;
454 return c + (res << 8);
455 }
456
457 void utilApplyIPS(const char *ips, u8 * *r, int *s)
458 {
459 // from the IPS spec at http://zerosoft.zophar.net/ips.htm
460 FILE *f = fopen(ips, "rb");
461 if (!f)
462 return;
463 u8 *rom = *r;
464 int size = *s;
465 if (fgetc(f) == 'P' &&
466 fgetc(f) == 'A' &&
467 fgetc(f) == 'T' &&
468 fgetc(f) == 'C' &&
469 fgetc(f) == 'H')
470 {
471 int b;
472 int offset;
473 int len;
474 for (;; )
475 {
476 // read offset
477 offset = utilReadInt3(f);
478 // if offset == EOF, end of patch
479 if (offset == 0x454f46)
480 break;
481 // read length
482 len = utilReadInt2(f);
483 if (!len)
484 {
485 // len == 0, RLE block
486 len = utilReadInt2(f);
487 // byte to fill
488 int c = fgetc(f);
489 if (c == -1)
490 break;
491 b = (u8)c;
492 }
493 else
494 b = -1;
495 // check if we need to reallocate our ROM
496 if ((offset + len) >= size)
497 {
498 size *= 2;
499 rom = (u8 *)realloc(rom, size);
500 *r = rom;
501 *s = size;
502 }
503 if (b == -1)
504 {
505 // normal block, just read the data
506 if (fread(&rom[offset], 1, len, f) != (size_t)len)
507 break;
508 }
509 else
510 {
511 // fill the region with the given byte
512 while (len--)
513 {
514 rom[offset++] = b;
515 }
516 }
517 }
518 }
519 // close the file
520 fclose(f);
521 }
522
523 extern bool8 cpuIsMultiBoot;
524
525 bool utilIsGBAImage(const char *file)
526 {
527 cpuIsMultiBoot = false;
528 if (strlen(file) > 4)
529 {
530 const char *p = strrchr(file, '.');
531
532 if (p != NULL)
533 {
534 if (_stricmp(p, ".gba") == 0)
535 return true;
536 if (_stricmp(p, ".agb") == 0)
537 return true;
538 if (_stricmp(p, ".bin") == 0)
539 return true;
540 if (_stricmp(p, ".elf") == 0)
541 return true;
542 if (_stricmp(p, ".mb") == 0)
543 {
544 cpuIsMultiBoot = true;
545 return true;
546 }
547 }
548 }
549
550 return false;
551 }
552
553 bool utilIsGBImage(const char *file)
554 {
555 if (strlen(file) > 4)
556 {
557 const char *p = strrchr(file, '.');
558
559 if (p != NULL)
560 {
561 if (_stricmp(p, ".gb") == 0)
562 return true;
563 if (_stricmp(p, ".gbc") == 0)
564 return true;
565 if (_stricmp(p, ".cgb") == 0)
566 return true;
567 if (_stricmp(p, ".sgb") == 0)
568 return true;
569 }
570 }
571
572 return false;
573 }
574
575 bool utilIsGBABios(const char *file)
576 {
577 if (strlen(file) > 4)
578 {
579 const char *p = strrchr(file, '.');
580
581 if (p != NULL)
582 {
583 if (_stricmp(p, ".gba") == 0)
584 return true;
585 if (_stricmp(p, ".agb") == 0)
586 return true;
587 if (_stricmp(p, ".bin") == 0)
588 return true;
589 if (_stricmp(p, ".bios") == 0)
590 return true;
591 if (_stricmp(p, ".rom") == 0)
592 return true;
593 }
594 }
595
596 return false;
597 }
598
599 bool utilIsGBBios(const char *file)
600 {
601 if (strlen(file) > 4)
602 {
603 const char *p = strrchr(file, '.');
604
605 if (p != NULL)
606 {
607 if (_stricmp(p, ".gb") == 0)
608 return true;
609 if (_stricmp(p, ".bin") == 0)
610 return true;
611 if (_stricmp(p, ".bios") == 0)
612 return true;
613 if (_stricmp(p, ".rom") == 0)
614 return true;
615 }
616 }
617
618 return false;
619 }
620
621 bool utilIsELF(const char *file)
622 {
623 if (strlen(file) > 4)
624 {
625 const char *p = strrchr(file, '.');
626
627 if (p != NULL)
628 {
629 if (_stricmp(p, ".elf") == 0)
630 return true;
631 }
632 }
633 return false;
634 }
635
636 bool utilIsZipFile(const char *file)
637 {
638 if (strlen(file) > 4)
639 {
640 const char *p = strrchr(file, '.');
641
642 if (p != NULL)
643 {
644 if (_stricmp(p, ".zip") == 0)
645 return true;
646 }
647 }
648
649 return false;
650 }
651
652 #if 0
653 bool utilIsRarFile(const char *file)
654 {
655 if (strlen(file) > 4)
656 {
657 char *p = strrchr(file, '.');
658
659 if (p != NULL)
660 {
661 if (_stricmp(p, ".rar") == 0)
662 return true;
663 }
664 }
665
666 return false;
667 }
668
669 #endif
670
671 bool utilIsGzipFile(const char *file)
672 {
673 if (strlen(file) > 3)
674 {
675 const char *p = strrchr(file, '.');
676
677 if (p != NULL)
678 {
679 if (_stricmp(p, ".gz") == 0)
680 return true;
681 if (_stricmp(p, ".z") == 0)
682 return true;
683 }
684 }
685
686 return false;
687 }
688
689 void utilGetBaseName(const char *file, char *buffer)
690 {
691 strcpy(buffer, file);
692
693 if (utilIsGzipFile(file))
694 {
695 char *p = strrchr(buffer, '.');
696
697 if (p)
698 *p = 0;
699 }
700 }
701
702 IMAGE_TYPE utilFindType(const char *file)
703 {
704 char buffer[2048];
705
706 if (utilIsZipFile(file))
707 {
708 unzFile unz = unzOpen(file);
709
710 if (unz == NULL)
711 {
712 systemMessage(MSG_CANNOT_OPEN_FILE, N_("Cannot open file %s"), file);
713 return IMAGE_UNKNOWN;
714 }
715
716 int r = unzGoToFirstFile(unz);
717
718 if (r != UNZ_OK)
719 {
720 unzClose(unz);
721 systemMessage(MSG_BAD_ZIP_FILE, N_("Bad ZIP file %s"), file);
722 return IMAGE_UNKNOWN;
723 }
724
725 IMAGE_TYPE found = IMAGE_UNKNOWN;
726
727 unz_file_info info;
728
729 while (true)
730 {
731 r = unzGetCurrentFileInfo(unz,
732 &info,
733 buffer,
734 sizeof(buffer),
735 NULL,
736 0,
737 NULL,
738 0);
739
740 if (r != UNZ_OK)
741 {
742 unzClose(unz);
743 systemMessage(MSG_BAD_ZIP_FILE, N_("Bad ZIP file %s"), file);
744 return IMAGE_UNKNOWN;
745 }
746
747 if (utilIsGBAImage(buffer))
748 {
749 found = IMAGE_GBA;
750 break;
751 }
752
753 if (utilIsGBImage(buffer))
754 {
755 found = IMAGE_GB;
756 break;
757 }
758
759 r = unzGoToNextFile(unz);
760
761 if (r != UNZ_OK)
762 break;
763 }
764 unzClose(unz);
765
766 if (found == IMAGE_UNKNOWN)
767 {
768 systemMessage(MSG_NO_IMAGE_ON_ZIP,
769 N_("No image found on ZIP file %s"), file);
770 return found;
771 }
772 return found;
773 #if 0
774 }
775 else if (utilIsRarFile(file))
776 {
777 IMAGE_TYPE found = IMAGE_UNKNOWN;
778
779 ArchiveList_struct *rarList = NULL;
780 if (urarlib_list((void *)file, (ArchiveList_struct *)&rarList))
781 {
782 ArchiveList_struct *p = rarList;
783
784 while (p)
785 {
786 if (utilIsGBAImage(p->item.Name))
787 {
788 found = IMAGE_GBA;
789 break;
790 }
791
792 if (utilIsGBImage(p->item.Name))
793 {
794 found = IMAGE_GB;
795 break;
796 }
797 p = p->next;
798 }
799
800 urarlib_freelist(rarList);
801 }
802 return found;
803 #endif
804 }
805 else
806 {
807 if (utilIsGzipFile(file))
808 utilGetBaseName(file, buffer);
809 else
810 strcpy(buffer, file);
811
812 if (utilIsGBAImage(buffer))
813 return IMAGE_GBA;
814 if (utilIsGBImage(buffer))
815 return IMAGE_GB;
816 }
817 return IMAGE_UNKNOWN;
818 }
819
820 static int utilGetSize(int size)
821 {
822 int res = 1;
823 while (res < size)
824 res <<= 1;
825 return res;
826 }
827
828 static u8 *utilLoadFromZip(const char *file,
829 bool (*accept)(const char *),
830 u8 *data,
831 int &size)
832 {
833 char buffer[2048];
834
835 unzFile unz = unzOpen(file);
836
837 if (unz == NULL)
838 {
839 systemMessage(MSG_CANNOT_OPEN_FILE, N_("Cannot open file %s"), file);
840 return NULL;
841 }
842 int r = unzGoToFirstFile(unz);
843
844 if (r != UNZ_OK)
845 {
846 unzClose(unz);
847 systemMessage(MSG_BAD_ZIP_FILE, N_("Bad ZIP file %s"), file);
848 return NULL;
849 }
850
851 bool found = false;
852
853 unz_file_info info;
854
855 while (true)
856 {
857 r = unzGetCurrentFileInfo(unz,
858 &info,
859 buffer,
860 sizeof(buffer),
861 NULL,
862 0,
863 NULL,
864 0);
865
866 if (r != UNZ_OK)
867 {
868 unzClose(unz);
869 systemMessage(MSG_BAD_ZIP_FILE, N_("Bad ZIP file %s"), file);
870 return NULL;
871 }
872
873 if (accept(buffer))
874 {
875 found = true;
876 break;
877 }
878
879 r = unzGoToNextFile(unz);
880
881 if (r != UNZ_OK)
882 break;
883 }
884
885 if (!found)
886 {
887 unzClose(unz);
888 systemMessage(MSG_NO_IMAGE_ON_ZIP,
889 N_("No image found on ZIP file %s"), file);
890 return NULL;
891 }
892
893 int fileSize = info.uncompressed_size;
894 if (size == 0)
895 size = fileSize;
896 r = unzOpenCurrentFile(unz);
897
898 if (r != UNZ_OK)
899 {
900 unzClose(unz);
901 systemMessage(MSG_ERROR_OPENING_IMAGE, N_("Error opening image %s"), buffer);
902 return NULL;
903 }
904
905 u8 *image = data;
906
907 if (image == NULL)
908 {
909 image = (u8 *)malloc(utilGetSize(size));
910 if (image == NULL)
911 {
912 unzCloseCurrentFile(unz);
913 unzClose(unz);
914 systemMessage(MSG_OUT_OF_MEMORY, N_("Failed to allocate memory for %s"),
915 "data");
916 return NULL;
917 }
918 size = fileSize;
919 }
920 int read = fileSize <= size ? fileSize : size;
921 r = unzReadCurrentFile(unz,
922 image,
923 read);
924
925 unzCloseCurrentFile(unz);
926 unzClose(unz);
927
928 if (r != (int)read)
929 {
930 systemMessage(MSG_ERROR_READING_IMAGE,
931 N_("Error reading image %s"), buffer);
932 if (data == NULL)
933 free(image);
934 return NULL;
935 }
936
937 size = fileSize;
938
939 return image;
940 }
941
942 static u8 *utilLoadGzipFile(const char *file,
943 bool (*accept)(const char *),
944 u8 *data,
945 int &size)
946 {
947 FILE *f = fopen(file, "rb");
948
949 if (f == NULL)
950 {
951 systemMessage(MSG_ERROR_OPENING_IMAGE, N_("Error opening image %s"), file);
952 return NULL;
953 }
954
955 fseek(f, -4, SEEK_END);
956 int fileSize = fgetc(f) | (fgetc(f) << 8) | (fgetc(f) << 16) | (fgetc(f) << 24);
957 fclose(f);
958 if (size == 0)
959 size = fileSize;
960
961 gzFile gz = gzopen(file, "rb");
962
963 if (gz == NULL)
964 {
965 // should not happen, but who knows?
966 systemMessage(MSG_ERROR_OPENING_IMAGE, N_("Error opening image %s"), file);
967 return NULL;
968 }
969
970 u8 *image = data;
971
972 if (image == NULL)
973 {
974 image = (u8 *)malloc(utilGetSize(size));
975 if (image == NULL)
976 {
977 systemMessage(MSG_OUT_OF_MEMORY, N_("Failed to allocate memory for %s"),
978 "data");
979 fclose(f);
980 return NULL;
981 }
982 size = fileSize;
983 }
984 int read = fileSize <= size ? fileSize : size;
985 int r = gzread(gz, image, read);
986 gzclose(gz);
987
988 if (r != (int)read)
989 {
990 systemMessage(MSG_ERROR_READING_IMAGE,
991 N_("Error reading image %s"), file);
992 if (data == NULL)
993 free(image);
994 return NULL;
995 }
996
997 size = fileSize;
998
999 return image;
1000 }
1001
1002 #if 0
1003 static u8 *utilLoadRarFile(const char *file,
1004 bool (*accept)(const char *),
1005 u8 *data,
1006 int &size)
1007 {
1008 char buffer[2048];
1009
1010 ArchiveList_struct *rarList = NULL;
1011 if (urarlib_list((void *)file, (ArchiveList_struct *)&rarList))
1012 {
1013 ArchiveList_struct *p = rarList;
1014
1015 bool found = false;
1016 while (p)
1017 {
1018 if (accept(p->item.Name))
1019 {
1020 strcpy(buffer, p->item.Name);
1021 found = true;
1022 break;
1023 }
1024 p = p->next;
1025 }
1026 if (found)
1027 {
1028 void *memory = NULL;
1029 unsigned long lsize = 0;
1030 size = p->item.UnpSize;
1031 int r = urarlib_get((void *)&memory, &lsize, buffer, (void *)file, "");
1032 if (!r)
1033 {
1034 systemMessage(MSG_ERROR_READING_IMAGE,
1035 N_("Error reading image %s"), buffer);
1036 urarlib_freelist(rarList);
1037 return NULL;
1038 }
1039 u8 *image = (u8 *)memory;
1040 if (data != NULL)
1041 {
1042 memcpy(image, data, size);
1043 }
1044 urarlib_freelist(rarList);
1045 return image;
1046 }
1047 systemMessage(MSG_NO_IMAGE_ON_ZIP,
1048 N_("No image found on RAR file %s"), file);
1049 urarlib_freelist(rarList);
1050 return NULL;
1051 }
1052 // nothing found
1053 return NULL;
1054 }
1055
1056 #endif
1057
1058 // the caller is responsible for caling free(return value) to release the memory
1059 u8 *utilLoad(const char *file,
1060 bool (*accept)(const char *),
1061 u8 *data,
1062 int &size)
1063 {
1064 if (utilIsZipFile(file))
1065 {
1066 return utilLoadFromZip(file, accept, data, size);
1067 }
1068 if (utilIsGzipFile(file))
1069 {
1070 return utilLoadGzipFile(file, accept, data, size);
1071 }
1072 #if 0
1073 if (utilIsRarFile(file))
1074 {
1075 return utilLoadRarFile(file, accept, data, size);
1076 }
1077 #endif
1078
1079 u8 *image = data;
1080
1081 FILE *f = fopen(file, "rb");
1082
1083 if (!f)
1084 {
1085 systemMessage(MSG_ERROR_OPENING_IMAGE, N_("Error opening image %s"), file);
1086 return NULL;
1087 }
1088
1089 fseek(f, 0, SEEK_END);
1090 int fileSize = ftell(f);
1091 fseek(f, 0, SEEK_SET);
1092 if (size == 0)
1093 size = fileSize;
1094
1095 if (image == NULL)
1096 {
1097 image = (u8 *)malloc(utilGetSize(size));
1098 if (image == NULL)
1099 {
1100 systemMessage(MSG_OUT_OF_MEMORY, N_("Failed to allocate memory for %s"),
1101 "data");
1102 fclose(f);
1103 return NULL;
1104 }
1105 size = fileSize;
1106 }
1107 int read = fileSize <= size ? fileSize : size;
1108 int r = fread(image, 1, read, f);
1109 fclose(f);
1110
1111 if (r != (int)read)
1112 {
1113 systemMessage(MSG_ERROR_READING_IMAGE,
1114 N_("Error reading image %s"), file);
1115 if (data == NULL)
1116 free(image);
1117 return NULL;
1118 }
1119
1120 size = fileSize;
1121
1122 return image;
1123 }
1124
1125 void utilWriteInt(gzFile gzFile, int32 i)
1126 {
1127 utilGzWrite(gzFile, &i, sizeof(int32));
1128 }
1129
1130 int32 utilReadInt(gzFile gzFile)
1131 {
1132 int32 i = 0;
1133 utilGzRead(gzFile, &i, sizeof(int32));
1134 return i;
1135 }
1136
1137 void utilReadData(gzFile gzFile, variable_desc *data)
1138 {
1139 while (data->address)
1140 {
1141 utilGzRead(gzFile, data->address, data->size);
1142 data++;
1143 }
1144 }
1145
1146 void utilWriteData(gzFile gzFile, variable_desc *data)
1147 {
1148 while (data->address)
1149 {
1150 utilGzWrite(gzFile, data->address, data->size);
1151 data++;
1152 }
1153 }
1154
1155 gzFile utilGzOpen(const char *file, const char *mode)
1156 {
1157 utilGzWriteFunc = gzWrite;
1158 utilGzReadFunc = gzread;
1159 utilGzCloseFunc = gzclose;
1160 utilGzSeekFunc = gzseek;
1161 utilGzTellFunc = gztell;
1162
1163 return gzopen(file, mode);
1164 }
1165
1166 gzFile utilGzReopen(int id, const char *mode)
1167 {
1168 utilGzWriteFunc = gzWrite;
1169 utilGzReadFunc = gzread;
1170 utilGzCloseFunc = gzclose;
1171 utilGzSeekFunc = gzseek;
1172 utilGzTellFunc = gztell;
1173
1174 return gzdopen(id, mode);
1175 }
1176
1177 gzFile utilMemGzOpen(char *memory, int available, char *mode)
1178 {
1179 utilGzWriteFunc = memgzwrite;
1180 utilGzReadFunc = memgzread;
1181 utilGzCloseFunc = memgzclose;
1182 utilGzSeekFunc = NULL; // FIXME: not implemented...
1183 utilGzTellFunc = memtell;
1184
1185 return memgzopen(memory, available, mode);
1186 }
1187
1188 int utilGzWrite(gzFile file, voidp buffer, unsigned int len)
1189 {
1190 return utilGzWriteFunc(file, buffer, len);
1191 }
1192
1193 int utilGzRead(gzFile file, voidp buffer, unsigned int len)
1194 {
1195 return utilGzReadFunc(file, buffer, len);
1196 }
1197
1198 int utilGzClose(gzFile file)
1199 {
1200 return utilGzCloseFunc(file);
1201 }
1202
1203 z_off_t utilGzSeek(gzFile file, z_off_t offset, int whence)
1204 {
1205 return utilGzSeekFunc(file, offset, whence);
1206 }
1207
1208 z_off_t utilGzTell(gzFile file)
1209 {
1210 return utilGzTellFunc(file);
1211 }
1212
1213 void utilGBAFindSave(const u8 *data, const int size)
1214 {
1215 u32 *p = (u32 *)data;
1216 u32 *end = (u32 *)(data + size);
1217 int saveType = 0;
1218 int flashSize = 0x10000;
1219 bool rtcFound = false;
1220
1221 while (p < end)
1222 {
1223 u32 d = READ32LE(p);
1224
1225 if (d == 0x52504545)
1226 {
1227 if (memcmp(p, "EEPROM_", 7) == 0)
1228 {
1229 if (saveType == 0)
1230 saveType = 1;
1231 }
1232 }
1233 else if (d == 0x4D415253)
1234 {
1235 if (memcmp(p, "SRAM_", 5) == 0)
1236 {
1237 if (saveType == 0)
1238 saveType = 2;
1239 }
1240 }
1241 else if (d == 0x53414C46)
1242 {
1243 if (memcmp(p, "FLASH1M_", 8) == 0)
1244 {
1245 if (saveType == 0)
1246 {
1247 saveType = 3;
1248 flashSize = 0x20000;
1249 }
1250 }
1251 else if (memcmp(p, "FLASH", 5) == 0)
1252 {
1253 if (saveType == 0)
1254 {
1255 saveType = 3;
1256 flashSize = 0x10000;
1257 }
1258 }
1259 }
1260 else if (d == 0x52494953)
1261 {
1262 if (memcmp(p, "SIIRTC_V", 8) == 0)
1263 rtcFound = true;
1264 }
1265 p++;
1266 }
1267 // if no matches found, then set it to NONE
1268 if (saveType == 0)
1269 {
1270 saveType = 5;
1271 }
1272 rtcEnable(rtcFound);
1273 cpuSaveType = saveType;
1274 flashSetSize(flashSize);
1275 }
1276
1277 void utilUpdateSystemColorMaps()
1278 {
1279 switch (systemColorDepth)
1280 {
1281 case 16:
1282 {
1283 for (int i = 0; i < 0x10000; i++)
1284 {
1285 systemColorMap16[i] = ((i & 0x1f) << systemRedShift) |
1286 (((i & 0x3e0) >> 5) << systemGreenShift) |
1287 (((i & 0x7c00) >> 10) << systemBlueShift);
1288 }
1289 break;
1290 }
1291 case 24:
1292 case 32:
1293 {
1294 for (int i = 0; i < 0x10000; i++)
1295 {
1296 systemColorMap32[i] = ((i & 0x1f) << systemRedShift) |
1297 (((i & 0x3e0) >> 5) << systemGreenShift) |
1298 (((i & 0x7c00) >> 10) << systemBlueShift);
1299 }
1300 break;
1301 }
1302 }
1303 }
1304
1305 //// BIOS stuff
1306 // systemType uses the same enum values as gbEmulatorType does
1307
1308 bool utilLoadBIOS(u8 *bios, const char *biosFileName, int systemType)
1309 {
1310 if (bios == NULL || strlen(biosFileName) == 0)
1311 return false;
1312
1313 if (systemType == 4)
1314 {
1315 int biosSize = 0x4000;
1316 if (utilLoad(biosFileName, utilIsGBABios, bios, biosSize))
1317 {
1318 if (biosSize == 0x4000)
1319 return true;
1320 }
1321 }
1322 else
1323 {
1324 int biosSize = 0x100;
1325 if (utilLoad(biosFileName, utilIsGBBios, bios, biosSize))
1326 {
1327 if (biosSize == 0x100)
1328 return true;
1329 }
1330 }
1331
1332 return false;
1333 }
1334
1335 bool utilCheckBIOS(const char *biosFileName, int systemType)
1336 {
1337 if (strlen(biosFileName) == 0)
1338 return false;
1339
1340 u8 * tempBIOS = (u8 *)malloc(systemType == 4 ? 0x4000 : 0x100);
1341 bool result = utilLoadBIOS(tempBIOS, biosFileName, systemType);
1342 free(tempBIOS);
1343
1344 return result;
1345 }
1346
1347 #if 0
1348 // returns the checksum of the BIOS that will be loaded after the next restart
1349 u16 utilCalcBIOSChecksum(const u8 *bios, int systemType)
1350 {
1351 u32 biosChecksum = 0;
1352 if (bios)
1353 {
1354 int biosSize = (systemType == 4 ? 0x4000 : 0x100);
1355 const u16 *data = reinterpret_cast<const u16 *>(bios);
1356 for (int i = biosSize; i > 0; i -= 2)
1357 biosChecksum += *data++;
1358 }
1359
1360 while ((biosChecksum >> 16) & 0xFFFF)
1361 biosChecksum = (biosChecksum &0xFFFF) + ((biosChecksum >> 16) & 0xFFFF);
1362
1363 return biosChecksum & 0xFFFF;
1364 }
1365 #else
1366 // returns the checksum of the BIOS that will be loaded after the next restart
1367 u16 utilCalcBIOSChecksum(const u8 *bios, int systemType)
1368 {
1369 u32 biosChecksum = 0;
1370 if (bios)
1371 {
1372 int biosSize = (systemType == 4 ? 0x4000 : 0x100);
1373 const u32 *data = reinterpret_cast<const u32 *>(bios);
1374 for (int i = biosSize; i > 0; i -= 4)
1375 biosChecksum += *data++;
1376 }
1377
1378 return biosChecksum & 0xFFFF;
1379 }
1380 #endif
1381
1382 // returns the checksum of the BIOS file
1383 u16 utilCalcBIOSFileChecksum(const char *biosFileName, int systemType)
1384 {
1385 if (strlen(biosFileName) == 0)
1386 return 0;
1387
1388 u16 biosChecksum = 0;
1389 const int biosSize = (systemType == 4 ? 0x4000 : 0x100);
1390 u8 * tempBIOS = (u8 *)malloc(biosSize);
1391 bool hasBIOS = utilLoadBIOS(tempBIOS, biosFileName, systemType);
1392 if (hasBIOS)
1393 {
1394 biosChecksum = utilCalcBIOSChecksum(tempBIOS, systemType);
1395 }
1396 free(tempBIOS);
1397
1398 return biosChecksum;
1399 }
1400