Mercurial > vba-clojure
view src/common/Util.cpp @ 493:783a09c84a28
can now display a single color :)
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Thu, 07 Jun 2012 23:03:05 -0500 |
parents | f94fa48624d0 |
children | a6d060a64246 |
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++;131 *b++ = ((v >> systemBlueShift) & 0x001f) << 3; // B132 *b++ = ((v >> systemGreenShift) & 0x001f) << 3; // G133 *b++ = ((v >> systemRedShift) & 0x001f) << 3; // R134 }135 pixU32++;136 pixU32 -= 2 * (w + 1);137 }138 break;139 }140 }141 }143 bool utilWriteBMPFile(const char *fileName, int w, int h, u8 *pix)144 {145 u8 writeBuffer[256 * 3];147 FILE *fp = fopen(fileName, "wb");149 if (!fp)150 {151 systemMessage(MSG_ERROR_CREATING_FILE, N_("Error creating file %s"), fileName);152 return false;153 }155 struct156 {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));176 bmpheader.ident[0] = 'B';177 bmpheader.ident[1] = 'M';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);189 fwrite(&bmpheader, 1, sizeof(bmpheader), fp);191 #if 0192 // FIXME: need sufficient buffer193 utilWriteBMP(writeBuffer, w, h, systemColorDepth, pix);194 #else195 u8 *b = writeBuffer;197 int sizeX = w;198 int sizeY = h;200 switch (systemColorDepth)201 {202 case 16:203 {204 u16 *p = (u16 *)(pix + (w + 2) * (h) * 2); // skip first black line205 for (int y = 0; y < sizeY; y++)206 {207 for (int x = 0; x < sizeX; x++)208 {209 u16 v = *p++;211 *b++ = ((v >> systemBlueShift) & 0x01f) << 3; // B212 *b++ = ((v >> systemGreenShift) & 0x001f) << 3; // G213 *b++ = ((v >> systemRedShift) & 0x001f) << 3; // R214 }215 p++; // skip black pixel for filters216 p++; // skip black pixel for filters217 p -= 2 * (w + 2);218 fwrite(writeBuffer, 1, 3 * w, fp);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++; // B234 *b++ = *pixU8++; // G235 *b++ = *pixU8++; // R236 }237 else238 {239 int red = *pixU8++;240 int green = *pixU8++;241 int blue = *pixU8++;243 *b++ = blue;244 *b++ = green;245 *b++ = red;246 }247 }248 pixU8 -= 2 * 3 * w;249 fwrite(writeBuffer, 1, 3 * w, fp);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++;264 *b++ = ((v >> systemBlueShift) & 0x001f) << 3; // B265 *b++ = ((v >> systemGreenShift) & 0x001f) << 3; // G266 *b++ = ((v >> systemRedShift) & 0x001f) << 3; // R267 }268 pixU32++;269 pixU32 -= 2 * (w + 1);271 fwrite(writeBuffer, 1, 3 * w, fp);273 b = writeBuffer;274 }275 break;276 }277 }278 #endif280 fclose(fp);282 return true;283 }285 bool utilWritePNGFile(const char *fileName, int w, int h, u8 *pix)286 {287 u8 writeBuffer[256 * 3];289 FILE *fp = fopen(fileName, "wb");291 if (!fp)292 {293 systemMessage(MSG_ERROR_CREATING_FILE, N_("Error creating file %s"), fileName);294 return false;295 }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 }307 png_infop info_ptr = png_create_info_struct(png_ptr);309 if (!info_ptr)310 {311 png_destroy_write_struct(&png_ptr, NULL);312 fclose(fp);313 return false;314 }316 if (setjmp(png_jmpbuf(png_ptr)))317 {318 png_destroy_write_struct(&png_ptr, NULL);319 fclose(fp);320 return false;321 }323 png_init_io(png_ptr, fp);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);335 png_write_info(png_ptr, info_ptr);337 u8 *b = writeBuffer;339 int sizeX = w;340 int sizeY = h;342 switch (systemColorDepth)343 {344 case 16:345 {346 u16 *p = (u16 *)(pix + (w + 2) * 2); // skip first black line347 for (int y = 0; y < sizeY; y++)348 {349 for (int x = 0; x < sizeX; x++)350 {351 u16 v = *p++;353 *b++ = ((v >> systemRedShift) & 0x001f) << 3; // R354 *b++ = ((v >> systemGreenShift) & 0x001f) << 3; // G355 *b++ = ((v >> systemBlueShift) & 0x01f) << 3; // B356 }357 p++; // skip black pixel for filters358 p++; // skip black pixel for filters359 png_write_row(png_ptr, writeBuffer);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++; // R375 *b++ = *pixU8++; // G376 *b++ = *pixU8++; // B377 }378 else379 {380 int blue = *pixU8++;381 int green = *pixU8++;382 int red = *pixU8++;384 *b++ = red;385 *b++ = green;386 *b++ = blue;387 }388 }389 png_write_row(png_ptr, writeBuffer);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++;404 *b++ = ((v >> systemRedShift) & 0x001f) << 3; // R405 *b++ = ((v >> systemGreenShift) & 0x001f) << 3; // G406 *b++ = ((v >> systemBlueShift) & 0x001f) << 3; // B407 }408 pixU32++;410 png_write_row(png_ptr, writeBuffer);412 b = writeBuffer;413 }414 break;415 }416 }418 png_write_end(png_ptr, info_ptr);420 png_destroy_write_struct(&png_ptr, &info_ptr);422 fclose(fp);424 return true;425 }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 }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 }457 void utilApplyIPS(const char *ips, u8 * *r, int *s)458 {459 // from the IPS spec at http://zerosoft.zophar.net/ips.htm460 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 offset477 offset = utilReadInt3(f);478 // if offset == EOF, end of patch479 if (offset == 0x454f46)480 break;481 // read length482 len = utilReadInt2(f);483 if (!len)484 {485 // len == 0, RLE block486 len = utilReadInt2(f);487 // byte to fill488 int c = fgetc(f);489 if (c == -1)490 break;491 b = (u8)c;492 }493 else494 b = -1;495 // check if we need to reallocate our ROM496 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 data506 if (fread(&rom[offset], 1, len, f) != (size_t)len)507 break;508 }509 else510 {511 // fill the region with the given byte512 while (len--)513 {514 rom[offset++] = b;515 }516 }517 }518 }519 // close the file520 fclose(f);521 }523 extern bool8 cpuIsMultiBoot;525 bool utilIsGBAImage(const char *file)526 {527 cpuIsMultiBoot = false;528 if (strlen(file) > 4)529 {530 const char *p = strrchr(file, '.');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 }550 return false;551 }553 bool utilIsGBImage(const char *file)554 {555 if (strlen(file) > 4)556 {557 const char *p = strrchr(file, '.');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 }572 return false;573 }575 bool utilIsGBABios(const char *file)576 {577 if (strlen(file) > 4)578 {579 const char *p = strrchr(file, '.');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 }596 return false;597 }599 bool utilIsGBBios(const char *file)600 {601 if (strlen(file) > 4)602 {603 const char *p = strrchr(file, '.');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 }618 return false;619 }621 bool utilIsELF(const char *file)622 {623 if (strlen(file) > 4)624 {625 const char *p = strrchr(file, '.');627 if (p != NULL)628 {629 if (_stricmp(p, ".elf") == 0)630 return true;631 }632 }633 return false;634 }636 bool utilIsZipFile(const char *file)637 {638 if (strlen(file) > 4)639 {640 const char *p = strrchr(file, '.');642 if (p != NULL)643 {644 if (_stricmp(p, ".zip") == 0)645 return true;646 }647 }649 return false;650 }652 #if 0653 bool utilIsRarFile(const char *file)654 {655 if (strlen(file) > 4)656 {657 char *p = strrchr(file, '.');659 if (p != NULL)660 {661 if (_stricmp(p, ".rar") == 0)662 return true;663 }664 }666 return false;667 }669 #endif671 bool utilIsGzipFile(const char *file)672 {673 if (strlen(file) > 3)674 {675 const char *p = strrchr(file, '.');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 }686 return false;687 }689 void utilGetBaseName(const char *file, char *buffer)690 {691 strcpy(buffer, file);693 if (utilIsGzipFile(file))694 {695 char *p = strrchr(buffer, '.');697 if (p)698 *p = 0;699 }700 }702 IMAGE_TYPE utilFindType(const char *file)703 {704 char buffer[2048];706 if (utilIsZipFile(file))707 {708 unzFile unz = unzOpen(file);710 if (unz == NULL)711 {712 systemMessage(MSG_CANNOT_OPEN_FILE, N_("Cannot open file %s"), file);713 return IMAGE_UNKNOWN;714 }716 int r = unzGoToFirstFile(unz);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 }725 IMAGE_TYPE found = IMAGE_UNKNOWN;727 unz_file_info info;729 while (true)730 {731 r = unzGetCurrentFileInfo(unz,732 &info,733 buffer,734 sizeof(buffer),735 NULL,736 0,737 NULL,738 0);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 }747 if (utilIsGBAImage(buffer))748 {749 found = IMAGE_GBA;750 break;751 }753 if (utilIsGBImage(buffer))754 {755 found = IMAGE_GB;756 break;757 }759 r = unzGoToNextFile(unz);761 if (r != UNZ_OK)762 break;763 }764 unzClose(unz);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 0774 }775 else if (utilIsRarFile(file))776 {777 IMAGE_TYPE found = IMAGE_UNKNOWN;779 ArchiveList_struct *rarList = NULL;780 if (urarlib_list((void *)file, (ArchiveList_struct *)&rarList))781 {782 ArchiveList_struct *p = rarList;784 while (p)785 {786 if (utilIsGBAImage(p->item.Name))787 {788 found = IMAGE_GBA;789 break;790 }792 if (utilIsGBImage(p->item.Name))793 {794 found = IMAGE_GB;795 break;796 }797 p = p->next;798 }800 urarlib_freelist(rarList);801 }802 return found;803 #endif804 }805 else806 {807 if (utilIsGzipFile(file))808 utilGetBaseName(file, buffer);809 else810 strcpy(buffer, file);812 if (utilIsGBAImage(buffer))813 return IMAGE_GBA;814 if (utilIsGBImage(buffer))815 return IMAGE_GB;816 }817 return IMAGE_UNKNOWN;818 }820 static int utilGetSize(int size)821 {822 int res = 1;823 while (res < size)824 res <<= 1;825 return res;826 }828 static u8 *utilLoadFromZip(const char *file,829 bool (*accept)(const char *),830 u8 *data,831 int &size)832 {833 char buffer[2048];835 unzFile unz = unzOpen(file);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);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 }851 bool found = false;853 unz_file_info info;855 while (true)856 {857 r = unzGetCurrentFileInfo(unz,858 &info,859 buffer,860 sizeof(buffer),861 NULL,862 0,863 NULL,864 0);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 }873 if (accept(buffer))874 {875 found = true;876 break;877 }879 r = unzGoToNextFile(unz);881 if (r != UNZ_OK)882 break;883 }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 }893 int fileSize = info.uncompressed_size;894 if (size == 0)895 size = fileSize;896 r = unzOpenCurrentFile(unz);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 }905 u8 *image = data;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);925 unzCloseCurrentFile(unz);926 unzClose(unz);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 }937 size = fileSize;939 return image;940 }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");949 if (f == NULL)950 {951 systemMessage(MSG_ERROR_OPENING_IMAGE, N_("Error opening image %s"), file);952 return NULL;953 }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;961 gzFile gz = gzopen(file, "rb");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 }970 u8 *image = data;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);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 }997 size = fileSize;999 return image;1000 }1002 #if 01003 static u8 *utilLoadRarFile(const char *file,1004 bool (*accept)(const char *),1005 u8 *data,1006 int &size)1007 {1008 char buffer[2048];1010 ArchiveList_struct *rarList = NULL;1011 if (urarlib_list((void *)file, (ArchiveList_struct *)&rarList))1012 {1013 ArchiveList_struct *p = rarList;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 found1053 return NULL;1054 }1056 #endif1058 // the caller is responsible for caling free(return value) to release the memory1059 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 01073 if (utilIsRarFile(file))1074 {1075 return utilLoadRarFile(file, accept, data, size);1076 }1077 #endif1079 u8 *image = data;1081 FILE *f = fopen(file, "rb");1083 if (!f)1084 {1085 systemMessage(MSG_ERROR_OPENING_IMAGE, N_("Error opening image %s"), file);1086 return NULL;1087 }1089 fseek(f, 0, SEEK_END);1090 int fileSize = ftell(f);1091 fseek(f, 0, SEEK_SET);1092 if (size == 0)1093 size = fileSize;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);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 }1120 size = fileSize;1122 return image;1123 }1125 void utilWriteInt(gzFile gzFile, int32 i)1126 {1127 utilGzWrite(gzFile, &i, sizeof(int32));1128 }1130 int32 utilReadInt(gzFile gzFile)1131 {1132 int32 i = 0;1133 utilGzRead(gzFile, &i, sizeof(int32));1134 return i;1135 }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 }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 }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;1163 return gzopen(file, mode);1164 }1166 gzFile utilGzReopen(int id, const char *mode)1167 {1168 utilGzWriteFunc = gzWrite;1169 utilGzReadFunc = gzread;1170 utilGzCloseFunc = gzclose;1171 utilGzSeekFunc = gzseek;1172 utilGzTellFunc = gztell;1174 return gzdopen(id, mode);1175 }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;1185 return memgzopen(memory, available, mode);1186 }1188 int utilGzWrite(gzFile file, voidp buffer, unsigned int len)1189 {1190 return utilGzWriteFunc(file, buffer, len);1191 }1193 int utilGzRead(gzFile file, voidp buffer, unsigned int len)1194 {1195 return utilGzReadFunc(file, buffer, len);1196 }1198 int utilGzClose(gzFile file)1199 {1200 return utilGzCloseFunc(file);1201 }1203 z_off_t utilGzSeek(gzFile file, z_off_t offset, int whence)1204 {1205 return utilGzSeekFunc(file, offset, whence);1206 }1208 z_off_t utilGzTell(gzFile file)1209 {1210 return utilGzTellFunc(file);1211 }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;1221 while (p < end)1222 {1223 u32 d = READ32LE(p);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 NONE1268 if (saveType == 0)1269 {1270 saveType = 5;1271 }1272 rtcEnable(rtcFound);1273 cpuSaveType = saveType;1274 flashSetSize(flashSize);1275 }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 }1305 //// BIOS stuff1306 // systemType uses the same enum values as gbEmulatorType does1308 bool utilLoadBIOS(u8 *bios, const char *biosFileName, int systemType)1309 {1310 if (bios == NULL || strlen(biosFileName) == 0)1311 return false;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 else1323 {1324 int biosSize = 0x100;1325 if (utilLoad(biosFileName, utilIsGBBios, bios, biosSize))1326 {1327 if (biosSize == 0x100)1328 return true;1329 }1330 }1332 return false;1333 }1335 bool utilCheckBIOS(const char *biosFileName, int systemType)1336 {1337 if (strlen(biosFileName) == 0)1338 return false;1340 u8 * tempBIOS = (u8 *)malloc(systemType == 4 ? 0x4000 : 0x100);1341 bool result = utilLoadBIOS(tempBIOS, biosFileName, systemType);1342 free(tempBIOS);1344 return result;1345 }1347 #if 01348 // returns the checksum of the BIOS that will be loaded after the next restart1349 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 }1360 while ((biosChecksum >> 16) & 0xFFFF)1361 biosChecksum = (biosChecksum &0xFFFF) + ((biosChecksum >> 16) & 0xFFFF);1363 return biosChecksum & 0xFFFF;1364 }1365 #else1366 // returns the checksum of the BIOS that will be loaded after the next restart1367 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 }1378 return biosChecksum & 0xFFFF;1379 }1380 #endif1382 // returns the checksum of the BIOS file1383 u16 utilCalcBIOSFileChecksum(const char *biosFileName, int systemType)1384 {1385 if (strlen(biosFileName) == 0)1386 return 0;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);1398 return biosChecksum;1399 }