view src/common/Util.cpp @ 606:47572d444485

final video rendered.
author Robert McIntyre <rlm@mit.edu>
date Sun, 02 Sep 2012 23:44:22 -0500
parents a6d060a64246
children
line wrap: on
line source
1 #include <cstdio>
2 #include <cstdlib>
3 #include <cstring>
4 #include <zlib.h>
6 extern "C" {
7 #include <png.h>
8 }
10 #if 0
11 #include "unrarlib.h"
12 #endif
14 #include "unzip.h"
16 #include "../NLS.h"
17 #include "System.h"
18 #include "Util.h"
19 #include "../gba/Flash.h"
20 #include "../gba/RTC.h"
22 extern "C" {
23 #include "memgzio.h"
24 }
26 #ifndef _MSC_VER
27 #define _stricmp strcasecmp
28 #endif // ! _MSC_VER
30 extern int32 cpuSaveType;
32 extern int systemColorDepth;
33 extern int systemRedShift;
34 extern int systemGreenShift;
35 extern int systemBlueShift;
37 extern u16 systemColorMap16[0x10000];
38 extern u32 systemColorMap32[0x10000];
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;
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 }
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 }
62 void utilPutWord(u8 *p, u16 value)
63 {
64 *p++ = value & 255;
65 *p = (value >> 8) & 255;
66 }
68 void utilWriteBMP(u8 *b, int w, int h, int dstDepth, u8 *pix)
69 {
70 int sizeX = w;
71 int sizeY = h;
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++;
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++;
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 //RLM pack bits for java ARGB
133 *b++ = ((v >> systemRedShift) & 0x001f) << 3; // R
134 *b++ = ((v >> systemGreenShift) & 0x001f) << 3; // G
135 *b++ = ((v >> systemBlueShift) & 0x001f) << 3; // B
136 *b++ = 0; // Alpha
140 // end RLM
143 }
144 pixU32++;
145 pixU32 -= 2 * (w + 1);
146 }
147 break;
148 }
149 }
150 }
152 bool utilWriteBMPFile(const char *fileName, int w, int h, u8 *pix)
153 {
154 u8 writeBuffer[256 * 3];
156 FILE *fp = fopen(fileName, "wb");
158 if (!fp)
159 {
160 systemMessage(MSG_ERROR_CREATING_FILE, N_("Error creating file %s"), fileName);
161 return false;
162 }
164 struct
165 {
166 u8 ident[2];
167 u8 filesize[4];
168 u8 reserved[4];
169 u8 dataoffset[4];
170 u8 headersize[4];
171 u8 width[4];
172 u8 height[4];
173 u8 planes[2];
174 u8 bitsperpixel[2];
175 u8 compression[4];
176 u8 datasize[4];
177 u8 hres[4];
178 u8 vres[4];
179 u8 colors[4];
180 u8 importantcolors[4];
181 // u8 pad[2];
182 } bmpheader;
183 memset(&bmpheader, 0, sizeof(bmpheader));
185 bmpheader.ident[0] = 'B';
186 bmpheader.ident[1] = 'M';
188 u32 fsz = sizeof(bmpheader) + w * h * 3;
189 utilPutDword(bmpheader.filesize, fsz);
190 utilPutDword(bmpheader.dataoffset, 0x36);
191 utilPutDword(bmpheader.headersize, 0x28);
192 utilPutDword(bmpheader.width, w);
193 utilPutDword(bmpheader.height, h);
194 utilPutDword(bmpheader.planes, 1);
195 utilPutDword(bmpheader.bitsperpixel, 24);
196 utilPutDword(bmpheader.datasize, 3 * w * h);
198 fwrite(&bmpheader, 1, sizeof(bmpheader), fp);
200 #if 0
201 // FIXME: need sufficient buffer
202 utilWriteBMP(writeBuffer, w, h, systemColorDepth, pix);
203 #else
204 u8 *b = writeBuffer;
206 int sizeX = w;
207 int sizeY = h;
209 switch (systemColorDepth)
210 {
211 case 16:
212 {
213 u16 *p = (u16 *)(pix + (w + 2) * (h) * 2); // skip first black line
214 for (int y = 0; y < sizeY; y++)
215 {
216 for (int x = 0; x < sizeX; x++)
217 {
218 u16 v = *p++;
220 *b++ = ((v >> systemBlueShift) & 0x01f) << 3; // B
221 *b++ = ((v >> systemGreenShift) & 0x001f) << 3; // G
222 *b++ = ((v >> systemRedShift) & 0x001f) << 3; // R
223 }
224 p++; // skip black pixel for filters
225 p++; // skip black pixel for filters
226 p -= 2 * (w + 2);
227 fwrite(writeBuffer, 1, 3 * w, fp);
229 b = writeBuffer;
230 }
231 break;
232 }
233 case 24:
234 {
235 u8 *pixU8 = (u8 *)pix + 3 * w * (h - 1);
236 for (int y = 0; y < sizeY; y++)
237 {
238 for (int x = 0; x < sizeX; x++)
239 {
240 if (systemRedShift > systemBlueShift)
241 {
242 *b++ = *pixU8++; // B
243 *b++ = *pixU8++; // G
244 *b++ = *pixU8++; // R
245 }
246 else
247 {
248 int red = *pixU8++;
249 int green = *pixU8++;
250 int blue = *pixU8++;
252 *b++ = blue;
253 *b++ = green;
254 *b++ = red;
255 }
256 }
257 pixU8 -= 2 * 3 * w;
258 fwrite(writeBuffer, 1, 3 * w, fp);
260 b = writeBuffer;
261 }
262 break;
263 }
264 case 32:
265 {
266 u32 *pixU32 = (u32 *)(pix + 4 * (w + 1) * (h));
267 for (int y = 0; y < sizeY; y++)
268 {
269 for (int x = 0; x < sizeX; x++)
270 {
271 u32 v = *pixU32++;
273 *b++ = ((v >> systemBlueShift) & 0x001f) << 3; // B
274 *b++ = ((v >> systemGreenShift) & 0x001f) << 3; // G
275 *b++ = ((v >> systemRedShift) & 0x001f) << 3; // R
276 }
277 pixU32++;
278 pixU32 -= 2 * (w + 1);
280 fwrite(writeBuffer, 1, 3 * w, fp);
282 b = writeBuffer;
283 }
284 break;
285 }
286 }
287 #endif
289 fclose(fp);
291 return true;
292 }
294 bool utilWritePNGFile(const char *fileName, int w, int h, u8 *pix)
295 {
296 u8 writeBuffer[256 * 3];
298 FILE *fp = fopen(fileName, "wb");
300 if (!fp)
301 {
302 systemMessage(MSG_ERROR_CREATING_FILE, N_("Error creating file %s"), fileName);
303 return false;
304 }
306 png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
307 NULL,
308 NULL,
309 NULL);
310 if (!png_ptr)
311 {
312 fclose(fp);
313 return false;
314 }
316 png_infop info_ptr = png_create_info_struct(png_ptr);
318 if (!info_ptr)
319 {
320 png_destroy_write_struct(&png_ptr, NULL);
321 fclose(fp);
322 return false;
323 }
325 if (setjmp(png_jmpbuf(png_ptr)))
326 {
327 png_destroy_write_struct(&png_ptr, NULL);
328 fclose(fp);
329 return false;
330 }
332 png_init_io(png_ptr, fp);
334 png_set_IHDR(png_ptr,
335 info_ptr,
336 w,
337 h,
338 8,
339 PNG_COLOR_TYPE_RGB,
340 PNG_INTERLACE_NONE,
341 PNG_COMPRESSION_TYPE_DEFAULT,
342 PNG_FILTER_TYPE_DEFAULT);
344 png_write_info(png_ptr, info_ptr);
346 u8 *b = writeBuffer;
348 int sizeX = w;
349 int sizeY = h;
351 switch (systemColorDepth)
352 {
353 case 16:
354 {
355 u16 *p = (u16 *)(pix + (w + 2) * 2); // skip first black line
356 for (int y = 0; y < sizeY; y++)
357 {
358 for (int x = 0; x < sizeX; x++)
359 {
360 u16 v = *p++;
362 *b++ = ((v >> systemRedShift) & 0x001f) << 3; // R
363 *b++ = ((v >> systemGreenShift) & 0x001f) << 3; // G
364 *b++ = ((v >> systemBlueShift) & 0x01f) << 3; // B
365 }
366 p++; // skip black pixel for filters
367 p++; // skip black pixel for filters
368 png_write_row(png_ptr, writeBuffer);
370 b = writeBuffer;
371 }
372 break;
373 }
374 case 24:
375 {
376 u8 *pixU8 = (u8 *)pix;
377 for (int y = 0; y < sizeY; y++)
378 {
379 for (int x = 0; x < sizeX; x++)
380 {
381 if (systemRedShift < systemBlueShift)
382 {
383 *b++ = *pixU8++; // R
384 *b++ = *pixU8++; // G
385 *b++ = *pixU8++; // B
386 }
387 else
388 {
389 int blue = *pixU8++;
390 int green = *pixU8++;
391 int red = *pixU8++;
393 *b++ = red;
394 *b++ = green;
395 *b++ = blue;
396 }
397 }
398 png_write_row(png_ptr, writeBuffer);
400 b = writeBuffer;
401 }
402 break;
403 }
404 case 32:
405 {
406 u32 *pixU32 = (u32 *)(pix + 4 * (w + 1));
407 for (int y = 0; y < sizeY; y++)
408 {
409 for (int x = 0; x < sizeX; x++)
410 {
411 u32 v = *pixU32++;
413 *b++ = ((v >> systemRedShift) & 0x001f) << 3; // R
414 *b++ = ((v >> systemGreenShift) & 0x001f) << 3; // G
415 *b++ = ((v >> systemBlueShift) & 0x001f) << 3; // B
416 }
417 pixU32++;
419 png_write_row(png_ptr, writeBuffer);
421 b = writeBuffer;
422 }
423 break;
424 }
425 }
427 png_write_end(png_ptr, info_ptr);
429 png_destroy_write_struct(&png_ptr, &info_ptr);
431 fclose(fp);
433 return true;
434 }
436 static int utilReadInt2(FILE *f)
437 {
438 int res = 0;
439 int c = fgetc(f);
440 if (c == EOF)
441 return -1;
442 res = c;
443 c = fgetc(f);
444 if (c == EOF)
445 return -1;
446 return c + (res << 8);
447 }
449 static int utilReadInt3(FILE *f)
450 {
451 int res = 0;
452 int c = fgetc(f);
453 if (c == EOF)
454 return -1;
455 res = c;
456 c = fgetc(f);
457 if (c == EOF)
458 return -1;
459 res = c + (res << 8);
460 c = fgetc(f);
461 if (c == EOF)
462 return -1;
463 return c + (res << 8);
464 }
466 void utilApplyIPS(const char *ips, u8 * *r, int *s)
467 {
468 // from the IPS spec at http://zerosoft.zophar.net/ips.htm
469 FILE *f = fopen(ips, "rb");
470 if (!f)
471 return;
472 u8 *rom = *r;
473 int size = *s;
474 if (fgetc(f) == 'P' &&
475 fgetc(f) == 'A' &&
476 fgetc(f) == 'T' &&
477 fgetc(f) == 'C' &&
478 fgetc(f) == 'H')
479 {
480 int b;
481 int offset;
482 int len;
483 for (;; )
484 {
485 // read offset
486 offset = utilReadInt3(f);
487 // if offset == EOF, end of patch
488 if (offset == 0x454f46)
489 break;
490 // read length
491 len = utilReadInt2(f);
492 if (!len)
493 {
494 // len == 0, RLE block
495 len = utilReadInt2(f);
496 // byte to fill
497 int c = fgetc(f);
498 if (c == -1)
499 break;
500 b = (u8)c;
501 }
502 else
503 b = -1;
504 // check if we need to reallocate our ROM
505 if ((offset + len) >= size)
506 {
507 size *= 2;
508 rom = (u8 *)realloc(rom, size);
509 *r = rom;
510 *s = size;
511 }
512 if (b == -1)
513 {
514 // normal block, just read the data
515 if (fread(&rom[offset], 1, len, f) != (size_t)len)
516 break;
517 }
518 else
519 {
520 // fill the region with the given byte
521 while (len--)
522 {
523 rom[offset++] = b;
524 }
525 }
526 }
527 }
528 // close the file
529 fclose(f);
530 }
532 extern bool8 cpuIsMultiBoot;
534 bool utilIsGBAImage(const char *file)
535 {
536 cpuIsMultiBoot = false;
537 if (strlen(file) > 4)
538 {
539 const char *p = strrchr(file, '.');
541 if (p != NULL)
542 {
543 if (_stricmp(p, ".gba") == 0)
544 return true;
545 if (_stricmp(p, ".agb") == 0)
546 return true;
547 if (_stricmp(p, ".bin") == 0)
548 return true;
549 if (_stricmp(p, ".elf") == 0)
550 return true;
551 if (_stricmp(p, ".mb") == 0)
552 {
553 cpuIsMultiBoot = true;
554 return true;
555 }
556 }
557 }
559 return false;
560 }
562 bool utilIsGBImage(const char *file)
563 {
564 if (strlen(file) > 4)
565 {
566 const char *p = strrchr(file, '.');
568 if (p != NULL)
569 {
570 if (_stricmp(p, ".gb") == 0)
571 return true;
572 if (_stricmp(p, ".gbc") == 0)
573 return true;
574 if (_stricmp(p, ".cgb") == 0)
575 return true;
576 if (_stricmp(p, ".sgb") == 0)
577 return true;
578 }
579 }
581 return false;
582 }
584 bool utilIsGBABios(const char *file)
585 {
586 if (strlen(file) > 4)
587 {
588 const char *p = strrchr(file, '.');
590 if (p != NULL)
591 {
592 if (_stricmp(p, ".gba") == 0)
593 return true;
594 if (_stricmp(p, ".agb") == 0)
595 return true;
596 if (_stricmp(p, ".bin") == 0)
597 return true;
598 if (_stricmp(p, ".bios") == 0)
599 return true;
600 if (_stricmp(p, ".rom") == 0)
601 return true;
602 }
603 }
605 return false;
606 }
608 bool utilIsGBBios(const char *file)
609 {
610 if (strlen(file) > 4)
611 {
612 const char *p = strrchr(file, '.');
614 if (p != NULL)
615 {
616 if (_stricmp(p, ".gb") == 0)
617 return true;
618 if (_stricmp(p, ".bin") == 0)
619 return true;
620 if (_stricmp(p, ".bios") == 0)
621 return true;
622 if (_stricmp(p, ".rom") == 0)
623 return true;
624 }
625 }
627 return false;
628 }
630 bool utilIsELF(const char *file)
631 {
632 if (strlen(file) > 4)
633 {
634 const char *p = strrchr(file, '.');
636 if (p != NULL)
637 {
638 if (_stricmp(p, ".elf") == 0)
639 return true;
640 }
641 }
642 return false;
643 }
645 bool utilIsZipFile(const char *file)
646 {
647 if (strlen(file) > 4)
648 {
649 const char *p = strrchr(file, '.');
651 if (p != NULL)
652 {
653 if (_stricmp(p, ".zip") == 0)
654 return true;
655 }
656 }
658 return false;
659 }
661 #if 0
662 bool utilIsRarFile(const char *file)
663 {
664 if (strlen(file) > 4)
665 {
666 char *p = strrchr(file, '.');
668 if (p != NULL)
669 {
670 if (_stricmp(p, ".rar") == 0)
671 return true;
672 }
673 }
675 return false;
676 }
678 #endif
680 bool utilIsGzipFile(const char *file)
681 {
682 if (strlen(file) > 3)
683 {
684 const char *p = strrchr(file, '.');
686 if (p != NULL)
687 {
688 if (_stricmp(p, ".gz") == 0)
689 return true;
690 if (_stricmp(p, ".z") == 0)
691 return true;
692 }
693 }
695 return false;
696 }
698 void utilGetBaseName(const char *file, char *buffer)
699 {
700 strcpy(buffer, file);
702 if (utilIsGzipFile(file))
703 {
704 char *p = strrchr(buffer, '.');
706 if (p)
707 *p = 0;
708 }
709 }
711 IMAGE_TYPE utilFindType(const char *file)
712 {
713 char buffer[2048];
715 if (utilIsZipFile(file))
716 {
717 unzFile unz = unzOpen(file);
719 if (unz == NULL)
720 {
721 systemMessage(MSG_CANNOT_OPEN_FILE, N_("Cannot open file %s"), file);
722 return IMAGE_UNKNOWN;
723 }
725 int r = unzGoToFirstFile(unz);
727 if (r != UNZ_OK)
728 {
729 unzClose(unz);
730 systemMessage(MSG_BAD_ZIP_FILE, N_("Bad ZIP file %s"), file);
731 return IMAGE_UNKNOWN;
732 }
734 IMAGE_TYPE found = IMAGE_UNKNOWN;
736 unz_file_info info;
738 while (true)
739 {
740 r = unzGetCurrentFileInfo(unz,
741 &info,
742 buffer,
743 sizeof(buffer),
744 NULL,
745 0,
746 NULL,
747 0);
749 if (r != UNZ_OK)
750 {
751 unzClose(unz);
752 systemMessage(MSG_BAD_ZIP_FILE, N_("Bad ZIP file %s"), file);
753 return IMAGE_UNKNOWN;
754 }
756 if (utilIsGBAImage(buffer))
757 {
758 found = IMAGE_GBA;
759 break;
760 }
762 if (utilIsGBImage(buffer))
763 {
764 found = IMAGE_GB;
765 break;
766 }
768 r = unzGoToNextFile(unz);
770 if (r != UNZ_OK)
771 break;
772 }
773 unzClose(unz);
775 if (found == IMAGE_UNKNOWN)
776 {
777 systemMessage(MSG_NO_IMAGE_ON_ZIP,
778 N_("No image found on ZIP file %s"), file);
779 return found;
780 }
781 return found;
782 #if 0
783 }
784 else if (utilIsRarFile(file))
785 {
786 IMAGE_TYPE found = IMAGE_UNKNOWN;
788 ArchiveList_struct *rarList = NULL;
789 if (urarlib_list((void *)file, (ArchiveList_struct *)&rarList))
790 {
791 ArchiveList_struct *p = rarList;
793 while (p)
794 {
795 if (utilIsGBAImage(p->item.Name))
796 {
797 found = IMAGE_GBA;
798 break;
799 }
801 if (utilIsGBImage(p->item.Name))
802 {
803 found = IMAGE_GB;
804 break;
805 }
806 p = p->next;
807 }
809 urarlib_freelist(rarList);
810 }
811 return found;
812 #endif
813 }
814 else
815 {
816 if (utilIsGzipFile(file))
817 utilGetBaseName(file, buffer);
818 else
819 strcpy(buffer, file);
821 if (utilIsGBAImage(buffer))
822 return IMAGE_GBA;
823 if (utilIsGBImage(buffer))
824 return IMAGE_GB;
825 }
826 return IMAGE_UNKNOWN;
827 }
829 static int utilGetSize(int size)
830 {
831 int res = 1;
832 while (res < size)
833 res <<= 1;
834 return res;
835 }
837 static u8 *utilLoadFromZip(const char *file,
838 bool (*accept)(const char *),
839 u8 *data,
840 int &size)
841 {
842 char buffer[2048];
844 unzFile unz = unzOpen(file);
846 if (unz == NULL)
847 {
848 systemMessage(MSG_CANNOT_OPEN_FILE, N_("Cannot open file %s"), file);
849 return NULL;
850 }
851 int r = unzGoToFirstFile(unz);
853 if (r != UNZ_OK)
854 {
855 unzClose(unz);
856 systemMessage(MSG_BAD_ZIP_FILE, N_("Bad ZIP file %s"), file);
857 return NULL;
858 }
860 bool found = false;
862 unz_file_info info;
864 while (true)
865 {
866 r = unzGetCurrentFileInfo(unz,
867 &info,
868 buffer,
869 sizeof(buffer),
870 NULL,
871 0,
872 NULL,
873 0);
875 if (r != UNZ_OK)
876 {
877 unzClose(unz);
878 systemMessage(MSG_BAD_ZIP_FILE, N_("Bad ZIP file %s"), file);
879 return NULL;
880 }
882 if (accept(buffer))
883 {
884 found = true;
885 break;
886 }
888 r = unzGoToNextFile(unz);
890 if (r != UNZ_OK)
891 break;
892 }
894 if (!found)
895 {
896 unzClose(unz);
897 systemMessage(MSG_NO_IMAGE_ON_ZIP,
898 N_("No image found on ZIP file %s"), file);
899 return NULL;
900 }
902 int fileSize = info.uncompressed_size;
903 if (size == 0)
904 size = fileSize;
905 r = unzOpenCurrentFile(unz);
907 if (r != UNZ_OK)
908 {
909 unzClose(unz);
910 systemMessage(MSG_ERROR_OPENING_IMAGE, N_("Error opening image %s"), buffer);
911 return NULL;
912 }
914 u8 *image = data;
916 if (image == NULL)
917 {
918 image = (u8 *)malloc(utilGetSize(size));
919 if (image == NULL)
920 {
921 unzCloseCurrentFile(unz);
922 unzClose(unz);
923 systemMessage(MSG_OUT_OF_MEMORY, N_("Failed to allocate memory for %s"),
924 "data");
925 return NULL;
926 }
927 size = fileSize;
928 }
929 int read = fileSize <= size ? fileSize : size;
930 r = unzReadCurrentFile(unz,
931 image,
932 read);
934 unzCloseCurrentFile(unz);
935 unzClose(unz);
937 if (r != (int)read)
938 {
939 systemMessage(MSG_ERROR_READING_IMAGE,
940 N_("Error reading image %s"), buffer);
941 if (data == NULL)
942 free(image);
943 return NULL;
944 }
946 size = fileSize;
948 return image;
949 }
951 static u8 *utilLoadGzipFile(const char *file,
952 bool (*accept)(const char *),
953 u8 *data,
954 int &size)
955 {
956 FILE *f = fopen(file, "rb");
958 if (f == NULL)
959 {
960 systemMessage(MSG_ERROR_OPENING_IMAGE, N_("Error opening image %s"), file);
961 return NULL;
962 }
964 fseek(f, -4, SEEK_END);
965 int fileSize = fgetc(f) | (fgetc(f) << 8) | (fgetc(f) << 16) | (fgetc(f) << 24);
966 fclose(f);
967 if (size == 0)
968 size = fileSize;
970 gzFile gz = gzopen(file, "rb");
972 if (gz == NULL)
973 {
974 // should not happen, but who knows?
975 systemMessage(MSG_ERROR_OPENING_IMAGE, N_("Error opening image %s"), file);
976 return NULL;
977 }
979 u8 *image = data;
981 if (image == NULL)
982 {
983 image = (u8 *)malloc(utilGetSize(size));
984 if (image == NULL)
985 {
986 systemMessage(MSG_OUT_OF_MEMORY, N_("Failed to allocate memory for %s"),
987 "data");
988 fclose(f);
989 return NULL;
990 }
991 size = fileSize;
992 }
993 int read = fileSize <= size ? fileSize : size;
994 int r = gzread(gz, image, read);
995 gzclose(gz);
997 if (r != (int)read)
998 {
999 systemMessage(MSG_ERROR_READING_IMAGE,
1000 N_("Error reading image %s"), file);
1001 if (data == NULL)
1002 free(image);
1003 return NULL;
1006 size = fileSize;
1008 return image;
1011 #if 0
1012 static u8 *utilLoadRarFile(const char *file,
1013 bool (*accept)(const char *),
1014 u8 *data,
1015 int &size)
1017 char buffer[2048];
1019 ArchiveList_struct *rarList = NULL;
1020 if (urarlib_list((void *)file, (ArchiveList_struct *)&rarList))
1022 ArchiveList_struct *p = rarList;
1024 bool found = false;
1025 while (p)
1027 if (accept(p->item.Name))
1029 strcpy(buffer, p->item.Name);
1030 found = true;
1031 break;
1033 p = p->next;
1035 if (found)
1037 void *memory = NULL;
1038 unsigned long lsize = 0;
1039 size = p->item.UnpSize;
1040 int r = urarlib_get((void *)&memory, &lsize, buffer, (void *)file, "");
1041 if (!r)
1043 systemMessage(MSG_ERROR_READING_IMAGE,
1044 N_("Error reading image %s"), buffer);
1045 urarlib_freelist(rarList);
1046 return NULL;
1048 u8 *image = (u8 *)memory;
1049 if (data != NULL)
1051 memcpy(image, data, size);
1053 urarlib_freelist(rarList);
1054 return image;
1056 systemMessage(MSG_NO_IMAGE_ON_ZIP,
1057 N_("No image found on RAR file %s"), file);
1058 urarlib_freelist(rarList);
1059 return NULL;
1061 // nothing found
1062 return NULL;
1065 #endif
1067 // the caller is responsible for caling free(return value) to release the memory
1068 u8 *utilLoad(const char *file,
1069 bool (*accept)(const char *),
1070 u8 *data,
1071 int &size)
1073 if (utilIsZipFile(file))
1075 return utilLoadFromZip(file, accept, data, size);
1077 if (utilIsGzipFile(file))
1079 return utilLoadGzipFile(file, accept, data, size);
1081 #if 0
1082 if (utilIsRarFile(file))
1084 return utilLoadRarFile(file, accept, data, size);
1086 #endif
1088 u8 *image = data;
1090 FILE *f = fopen(file, "rb");
1092 if (!f)
1094 systemMessage(MSG_ERROR_OPENING_IMAGE, N_("Error opening image %s"), file);
1095 return NULL;
1098 fseek(f, 0, SEEK_END);
1099 int fileSize = ftell(f);
1100 fseek(f, 0, SEEK_SET);
1101 if (size == 0)
1102 size = fileSize;
1104 if (image == NULL)
1106 image = (u8 *)malloc(utilGetSize(size));
1107 if (image == NULL)
1109 systemMessage(MSG_OUT_OF_MEMORY, N_("Failed to allocate memory for %s"),
1110 "data");
1111 fclose(f);
1112 return NULL;
1114 size = fileSize;
1116 int read = fileSize <= size ? fileSize : size;
1117 int r = fread(image, 1, read, f);
1118 fclose(f);
1120 if (r != (int)read)
1122 systemMessage(MSG_ERROR_READING_IMAGE,
1123 N_("Error reading image %s"), file);
1124 if (data == NULL)
1125 free(image);
1126 return NULL;
1129 size = fileSize;
1131 return image;
1134 void utilWriteInt(gzFile gzFile, int32 i)
1136 utilGzWrite(gzFile, &i, sizeof(int32));
1139 int32 utilReadInt(gzFile gzFile)
1141 int32 i = 0;
1142 utilGzRead(gzFile, &i, sizeof(int32));
1143 return i;
1146 void utilReadData(gzFile gzFile, variable_desc *data)
1148 while (data->address)
1150 utilGzRead(gzFile, data->address, data->size);
1151 data++;
1155 void utilWriteData(gzFile gzFile, variable_desc *data)
1157 while (data->address)
1159 utilGzWrite(gzFile, data->address, data->size);
1160 data++;
1164 gzFile utilGzOpen(const char *file, const char *mode)
1166 utilGzWriteFunc = gzWrite;
1167 utilGzReadFunc = gzread;
1168 utilGzCloseFunc = gzclose;
1169 utilGzSeekFunc = gzseek;
1170 utilGzTellFunc = gztell;
1172 return gzopen(file, mode);
1175 gzFile utilGzReopen(int id, const char *mode)
1177 utilGzWriteFunc = gzWrite;
1178 utilGzReadFunc = gzread;
1179 utilGzCloseFunc = gzclose;
1180 utilGzSeekFunc = gzseek;
1181 utilGzTellFunc = gztell;
1183 return gzdopen(id, mode);
1186 gzFile utilMemGzOpen(char *memory, int available, char *mode)
1188 utilGzWriteFunc = memgzwrite;
1189 utilGzReadFunc = memgzread;
1190 utilGzCloseFunc = memgzclose;
1191 utilGzSeekFunc = NULL; // FIXME: not implemented...
1192 utilGzTellFunc = memtell;
1194 return memgzopen(memory, available, mode);
1197 int utilGzWrite(gzFile file, voidp buffer, unsigned int len)
1199 return utilGzWriteFunc(file, buffer, len);
1202 int utilGzRead(gzFile file, voidp buffer, unsigned int len)
1204 return utilGzReadFunc(file, buffer, len);
1207 int utilGzClose(gzFile file)
1209 return utilGzCloseFunc(file);
1212 z_off_t utilGzSeek(gzFile file, z_off_t offset, int whence)
1214 return utilGzSeekFunc(file, offset, whence);
1217 z_off_t utilGzTell(gzFile file)
1219 return utilGzTellFunc(file);
1222 void utilGBAFindSave(const u8 *data, const int size)
1224 u32 *p = (u32 *)data;
1225 u32 *end = (u32 *)(data + size);
1226 int saveType = 0;
1227 int flashSize = 0x10000;
1228 bool rtcFound = false;
1230 while (p < end)
1232 u32 d = READ32LE(p);
1234 if (d == 0x52504545)
1236 if (memcmp(p, "EEPROM_", 7) == 0)
1238 if (saveType == 0)
1239 saveType = 1;
1242 else if (d == 0x4D415253)
1244 if (memcmp(p, "SRAM_", 5) == 0)
1246 if (saveType == 0)
1247 saveType = 2;
1250 else if (d == 0x53414C46)
1252 if (memcmp(p, "FLASH1M_", 8) == 0)
1254 if (saveType == 0)
1256 saveType = 3;
1257 flashSize = 0x20000;
1260 else if (memcmp(p, "FLASH", 5) == 0)
1262 if (saveType == 0)
1264 saveType = 3;
1265 flashSize = 0x10000;
1269 else if (d == 0x52494953)
1271 if (memcmp(p, "SIIRTC_V", 8) == 0)
1272 rtcFound = true;
1274 p++;
1276 // if no matches found, then set it to NONE
1277 if (saveType == 0)
1279 saveType = 5;
1281 rtcEnable(rtcFound);
1282 cpuSaveType = saveType;
1283 flashSetSize(flashSize);
1286 void utilUpdateSystemColorMaps()
1288 switch (systemColorDepth)
1290 case 16:
1292 for (int i = 0; i < 0x10000; i++)
1294 systemColorMap16[i] = ((i & 0x1f) << systemRedShift) |
1295 (((i & 0x3e0) >> 5) << systemGreenShift) |
1296 (((i & 0x7c00) >> 10) << systemBlueShift);
1298 break;
1300 case 24:
1301 case 32:
1303 for (int i = 0; i < 0x10000; i++)
1305 systemColorMap32[i] = ((i & 0x1f) << systemRedShift) |
1306 (((i & 0x3e0) >> 5) << systemGreenShift) |
1307 (((i & 0x7c00) >> 10) << systemBlueShift);
1309 break;
1314 //// BIOS stuff
1315 // systemType uses the same enum values as gbEmulatorType does
1317 bool utilLoadBIOS(u8 *bios, const char *biosFileName, int systemType)
1319 if (bios == NULL || strlen(biosFileName) == 0)
1320 return false;
1322 if (systemType == 4)
1324 int biosSize = 0x4000;
1325 if (utilLoad(biosFileName, utilIsGBABios, bios, biosSize))
1327 if (biosSize == 0x4000)
1328 return true;
1331 else
1333 int biosSize = 0x100;
1334 if (utilLoad(biosFileName, utilIsGBBios, bios, biosSize))
1336 if (biosSize == 0x100)
1337 return true;
1341 return false;
1344 bool utilCheckBIOS(const char *biosFileName, int systemType)
1346 if (strlen(biosFileName) == 0)
1347 return false;
1349 u8 * tempBIOS = (u8 *)malloc(systemType == 4 ? 0x4000 : 0x100);
1350 bool result = utilLoadBIOS(tempBIOS, biosFileName, systemType);
1351 free(tempBIOS);
1353 return result;
1356 #if 0
1357 // returns the checksum of the BIOS that will be loaded after the next restart
1358 u16 utilCalcBIOSChecksum(const u8 *bios, int systemType)
1360 u32 biosChecksum = 0;
1361 if (bios)
1363 int biosSize = (systemType == 4 ? 0x4000 : 0x100);
1364 const u16 *data = reinterpret_cast<const u16 *>(bios);
1365 for (int i = biosSize; i > 0; i -= 2)
1366 biosChecksum += *data++;
1369 while ((biosChecksum >> 16) & 0xFFFF)
1370 biosChecksum = (biosChecksum &0xFFFF) + ((biosChecksum >> 16) & 0xFFFF);
1372 return biosChecksum & 0xFFFF;
1374 #else
1375 // returns the checksum of the BIOS that will be loaded after the next restart
1376 u16 utilCalcBIOSChecksum(const u8 *bios, int systemType)
1378 u32 biosChecksum = 0;
1379 if (bios)
1381 int biosSize = (systemType == 4 ? 0x4000 : 0x100);
1382 const u32 *data = reinterpret_cast<const u32 *>(bios);
1383 for (int i = biosSize; i > 0; i -= 4)
1384 biosChecksum += *data++;
1387 return biosChecksum & 0xFFFF;
1389 #endif
1391 // returns the checksum of the BIOS file
1392 u16 utilCalcBIOSFileChecksum(const char *biosFileName, int systemType)
1394 if (strlen(biosFileName) == 0)
1395 return 0;
1397 u16 biosChecksum = 0;
1398 const int biosSize = (systemType == 4 ? 0x4000 : 0x100);
1399 u8 * tempBIOS = (u8 *)malloc(biosSize);
1400 bool hasBIOS = utilLoadBIOS(tempBIOS, biosFileName, systemType);
1401 if (hasBIOS)
1403 biosChecksum = utilCalcBIOSChecksum(tempBIOS, systemType);
1405 free(tempBIOS);
1407 return biosChecksum;