Mercurial > vba-clojure
view src/common/Util.cpp @ 500:0273c08cd2ff
discovered that the gb has far fewer unique colors than I initially thought.
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Tue, 12 Jun 2012 08:05:24 -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 011 #include "unrarlib.h"12 #endif14 #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_VER27 #define _stricmp strcasecmp28 #endif // ! _MSC_VER30 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 convert47 //gzwrite function pointer to the type of utilGzWriteFunc48 //due to void* and const void* differences49 //--Felipe50 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 line78 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; // B85 *b++ = ((v >> systemGreenShift) & 0x001f) << 3; // G86 *b++ = ((v >> systemRedShift) & 0x001f) << 3; // R87 }88 p++; // skip black pixel for filters89 p++; // skip black pixel for filters90 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++; // B104 *b++ = *pixU8++; // G105 *b++ = *pixU8++; // R106 }107 else108 {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 ARGB133 *b++ = ((v >> systemRedShift) & 0x001f) << 3; // R134 *b++ = ((v >> systemGreenShift) & 0x001f) << 3; // G135 *b++ = ((v >> systemBlueShift) & 0x001f) << 3; // B136 *b++ = 0; // Alpha140 // end RLM143 }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 struct165 {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 0201 // FIXME: need sufficient buffer202 utilWriteBMP(writeBuffer, w, h, systemColorDepth, pix);203 #else204 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 line214 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; // B221 *b++ = ((v >> systemGreenShift) & 0x001f) << 3; // G222 *b++ = ((v >> systemRedShift) & 0x001f) << 3; // R223 }224 p++; // skip black pixel for filters225 p++; // skip black pixel for filters226 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++; // B243 *b++ = *pixU8++; // G244 *b++ = *pixU8++; // R245 }246 else247 {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; // B274 *b++ = ((v >> systemGreenShift) & 0x001f) << 3; // G275 *b++ = ((v >> systemRedShift) & 0x001f) << 3; // R276 }277 pixU32++;278 pixU32 -= 2 * (w + 1);280 fwrite(writeBuffer, 1, 3 * w, fp);282 b = writeBuffer;283 }284 break;285 }286 }287 #endif289 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 line356 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; // R363 *b++ = ((v >> systemGreenShift) & 0x001f) << 3; // G364 *b++ = ((v >> systemBlueShift) & 0x01f) << 3; // B365 }366 p++; // skip black pixel for filters367 p++; // skip black pixel for filters368 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++; // R384 *b++ = *pixU8++; // G385 *b++ = *pixU8++; // B386 }387 else388 {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; // R414 *b++ = ((v >> systemGreenShift) & 0x001f) << 3; // G415 *b++ = ((v >> systemBlueShift) & 0x001f) << 3; // B416 }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.htm469 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 offset486 offset = utilReadInt3(f);487 // if offset == EOF, end of patch488 if (offset == 0x454f46)489 break;490 // read length491 len = utilReadInt2(f);492 if (!len)493 {494 // len == 0, RLE block495 len = utilReadInt2(f);496 // byte to fill497 int c = fgetc(f);498 if (c == -1)499 break;500 b = (u8)c;501 }502 else503 b = -1;504 // check if we need to reallocate our ROM505 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 data515 if (fread(&rom[offset], 1, len, f) != (size_t)len)516 break;517 }518 else519 {520 // fill the region with the given byte521 while (len--)522 {523 rom[offset++] = b;524 }525 }526 }527 }528 // close the file529 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 0662 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 #endif680 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 0783 }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 #endif813 }814 else815 {816 if (utilIsGzipFile(file))817 utilGetBaseName(file, buffer);818 else819 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;1004 }1006 size = fileSize;1008 return image;1009 }1011 #if 01012 static u8 *utilLoadRarFile(const char *file,1013 bool (*accept)(const char *),1014 u8 *data,1015 int &size)1016 {1017 char buffer[2048];1019 ArchiveList_struct *rarList = NULL;1020 if (urarlib_list((void *)file, (ArchiveList_struct *)&rarList))1021 {1022 ArchiveList_struct *p = rarList;1024 bool found = false;1025 while (p)1026 {1027 if (accept(p->item.Name))1028 {1029 strcpy(buffer, p->item.Name);1030 found = true;1031 break;1032 }1033 p = p->next;1034 }1035 if (found)1036 {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)1042 {1043 systemMessage(MSG_ERROR_READING_IMAGE,1044 N_("Error reading image %s"), buffer);1045 urarlib_freelist(rarList);1046 return NULL;1047 }1048 u8 *image = (u8 *)memory;1049 if (data != NULL)1050 {1051 memcpy(image, data, size);1052 }1053 urarlib_freelist(rarList);1054 return image;1055 }1056 systemMessage(MSG_NO_IMAGE_ON_ZIP,1057 N_("No image found on RAR file %s"), file);1058 urarlib_freelist(rarList);1059 return NULL;1060 }1061 // nothing found1062 return NULL;1063 }1065 #endif1067 // the caller is responsible for caling free(return value) to release the memory1068 u8 *utilLoad(const char *file,1069 bool (*accept)(const char *),1070 u8 *data,1071 int &size)1072 {1073 if (utilIsZipFile(file))1074 {1075 return utilLoadFromZip(file, accept, data, size);1076 }1077 if (utilIsGzipFile(file))1078 {1079 return utilLoadGzipFile(file, accept, data, size);1080 }1081 #if 01082 if (utilIsRarFile(file))1083 {1084 return utilLoadRarFile(file, accept, data, size);1085 }1086 #endif1088 u8 *image = data;1090 FILE *f = fopen(file, "rb");1092 if (!f)1093 {1094 systemMessage(MSG_ERROR_OPENING_IMAGE, N_("Error opening image %s"), file);1095 return NULL;1096 }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)1105 {1106 image = (u8 *)malloc(utilGetSize(size));1107 if (image == NULL)1108 {1109 systemMessage(MSG_OUT_OF_MEMORY, N_("Failed to allocate memory for %s"),1110 "data");1111 fclose(f);1112 return NULL;1113 }1114 size = fileSize;1115 }1116 int read = fileSize <= size ? fileSize : size;1117 int r = fread(image, 1, read, f);1118 fclose(f);1120 if (r != (int)read)1121 {1122 systemMessage(MSG_ERROR_READING_IMAGE,1123 N_("Error reading image %s"), file);1124 if (data == NULL)1125 free(image);1126 return NULL;1127 }1129 size = fileSize;1131 return image;1132 }1134 void utilWriteInt(gzFile gzFile, int32 i)1135 {1136 utilGzWrite(gzFile, &i, sizeof(int32));1137 }1139 int32 utilReadInt(gzFile gzFile)1140 {1141 int32 i = 0;1142 utilGzRead(gzFile, &i, sizeof(int32));1143 return i;1144 }1146 void utilReadData(gzFile gzFile, variable_desc *data)1147 {1148 while (data->address)1149 {1150 utilGzRead(gzFile, data->address, data->size);1151 data++;1152 }1153 }1155 void utilWriteData(gzFile gzFile, variable_desc *data)1156 {1157 while (data->address)1158 {1159 utilGzWrite(gzFile, data->address, data->size);1160 data++;1161 }1162 }1164 gzFile utilGzOpen(const char *file, const char *mode)1165 {1166 utilGzWriteFunc = gzWrite;1167 utilGzReadFunc = gzread;1168 utilGzCloseFunc = gzclose;1169 utilGzSeekFunc = gzseek;1170 utilGzTellFunc = gztell;1172 return gzopen(file, mode);1173 }1175 gzFile utilGzReopen(int id, const char *mode)1176 {1177 utilGzWriteFunc = gzWrite;1178 utilGzReadFunc = gzread;1179 utilGzCloseFunc = gzclose;1180 utilGzSeekFunc = gzseek;1181 utilGzTellFunc = gztell;1183 return gzdopen(id, mode);1184 }1186 gzFile utilMemGzOpen(char *memory, int available, char *mode)1187 {1188 utilGzWriteFunc = memgzwrite;1189 utilGzReadFunc = memgzread;1190 utilGzCloseFunc = memgzclose;1191 utilGzSeekFunc = NULL; // FIXME: not implemented...1192 utilGzTellFunc = memtell;1194 return memgzopen(memory, available, mode);1195 }1197 int utilGzWrite(gzFile file, voidp buffer, unsigned int len)1198 {1199 return utilGzWriteFunc(file, buffer, len);1200 }1202 int utilGzRead(gzFile file, voidp buffer, unsigned int len)1203 {1204 return utilGzReadFunc(file, buffer, len);1205 }1207 int utilGzClose(gzFile file)1208 {1209 return utilGzCloseFunc(file);1210 }1212 z_off_t utilGzSeek(gzFile file, z_off_t offset, int whence)1213 {1214 return utilGzSeekFunc(file, offset, whence);1215 }1217 z_off_t utilGzTell(gzFile file)1218 {1219 return utilGzTellFunc(file);1220 }1222 void utilGBAFindSave(const u8 *data, const int size)1223 {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)1231 {1232 u32 d = READ32LE(p);1234 if (d == 0x52504545)1235 {1236 if (memcmp(p, "EEPROM_", 7) == 0)1237 {1238 if (saveType == 0)1239 saveType = 1;1240 }1241 }1242 else if (d == 0x4D415253)1243 {1244 if (memcmp(p, "SRAM_", 5) == 0)1245 {1246 if (saveType == 0)1247 saveType = 2;1248 }1249 }1250 else if (d == 0x53414C46)1251 {1252 if (memcmp(p, "FLASH1M_", 8) == 0)1253 {1254 if (saveType == 0)1255 {1256 saveType = 3;1257 flashSize = 0x20000;1258 }1259 }1260 else if (memcmp(p, "FLASH", 5) == 0)1261 {1262 if (saveType == 0)1263 {1264 saveType = 3;1265 flashSize = 0x10000;1266 }1267 }1268 }1269 else if (d == 0x52494953)1270 {1271 if (memcmp(p, "SIIRTC_V", 8) == 0)1272 rtcFound = true;1273 }1274 p++;1275 }1276 // if no matches found, then set it to NONE1277 if (saveType == 0)1278 {1279 saveType = 5;1280 }1281 rtcEnable(rtcFound);1282 cpuSaveType = saveType;1283 flashSetSize(flashSize);1284 }1286 void utilUpdateSystemColorMaps()1287 {1288 switch (systemColorDepth)1289 {1290 case 16:1291 {1292 for (int i = 0; i < 0x10000; i++)1293 {1294 systemColorMap16[i] = ((i & 0x1f) << systemRedShift) |1295 (((i & 0x3e0) >> 5) << systemGreenShift) |1296 (((i & 0x7c00) >> 10) << systemBlueShift);1297 }1298 break;1299 }1300 case 24:1301 case 32:1302 {1303 for (int i = 0; i < 0x10000; i++)1304 {1305 systemColorMap32[i] = ((i & 0x1f) << systemRedShift) |1306 (((i & 0x3e0) >> 5) << systemGreenShift) |1307 (((i & 0x7c00) >> 10) << systemBlueShift);1308 }1309 break;1310 }1311 }1312 }1314 //// BIOS stuff1315 // systemType uses the same enum values as gbEmulatorType does1317 bool utilLoadBIOS(u8 *bios, const char *biosFileName, int systemType)1318 {1319 if (bios == NULL || strlen(biosFileName) == 0)1320 return false;1322 if (systemType == 4)1323 {1324 int biosSize = 0x4000;1325 if (utilLoad(biosFileName, utilIsGBABios, bios, biosSize))1326 {1327 if (biosSize == 0x4000)1328 return true;1329 }1330 }1331 else1332 {1333 int biosSize = 0x100;1334 if (utilLoad(biosFileName, utilIsGBBios, bios, biosSize))1335 {1336 if (biosSize == 0x100)1337 return true;1338 }1339 }1341 return false;1342 }1344 bool utilCheckBIOS(const char *biosFileName, int systemType)1345 {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;1354 }1356 #if 01357 // returns the checksum of the BIOS that will be loaded after the next restart1358 u16 utilCalcBIOSChecksum(const u8 *bios, int systemType)1359 {1360 u32 biosChecksum = 0;1361 if (bios)1362 {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++;1367 }1369 while ((biosChecksum >> 16) & 0xFFFF)1370 biosChecksum = (biosChecksum &0xFFFF) + ((biosChecksum >> 16) & 0xFFFF);1372 return biosChecksum & 0xFFFF;1373 }1374 #else1375 // returns the checksum of the BIOS that will be loaded after the next restart1376 u16 utilCalcBIOSChecksum(const u8 *bios, int systemType)1377 {1378 u32 biosChecksum = 0;1379 if (bios)1380 {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++;1385 }1387 return biosChecksum & 0xFFFF;1388 }1389 #endif1391 // returns the checksum of the BIOS file1392 u16 utilCalcBIOSFileChecksum(const char *biosFileName, int systemType)1393 {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)1402 {1403 biosChecksum = utilCalcBIOSChecksum(tempBIOS, systemType);1404 }1405 free(tempBIOS);1407 return biosChecksum;1408 }