rlm@1: #include rlm@1: #include rlm@1: #include rlm@1: #include rlm@1: rlm@1: extern "C" { rlm@1: #include rlm@1: } rlm@1: rlm@1: #if 0 rlm@1: #include "unrarlib.h" rlm@1: #endif rlm@1: rlm@1: #include "unzip.h" rlm@1: rlm@1: #include "../NLS.h" rlm@1: #include "System.h" rlm@1: #include "Util.h" rlm@1: #include "../gba/Flash.h" rlm@1: #include "../gba/RTC.h" rlm@1: rlm@1: extern "C" { rlm@1: #include "memgzio.h" rlm@1: } rlm@1: rlm@1: #ifndef _MSC_VER rlm@1: #define _stricmp strcasecmp rlm@1: #endif // ! _MSC_VER rlm@1: rlm@1: extern int32 cpuSaveType; rlm@1: rlm@1: extern int systemColorDepth; rlm@1: extern int systemRedShift; rlm@1: extern int systemGreenShift; rlm@1: extern int systemBlueShift; rlm@1: rlm@1: extern u16 systemColorMap16[0x10000]; rlm@1: extern u32 systemColorMap32[0x10000]; rlm@1: rlm@1: static int (ZEXPORT *utilGzWriteFunc)(gzFile, voidp, unsigned int) = NULL; rlm@1: static int (ZEXPORT *utilGzReadFunc)(gzFile, voidp, unsigned int) = NULL; rlm@1: static int (ZEXPORT *utilGzCloseFunc)(gzFile) = NULL; rlm@1: static z_off_t (ZEXPORT *utilGzSeekFunc)(gzFile, z_off_t, int) = NULL; rlm@1: static z_off_t (ZEXPORT *utilGzTellFunc)(gzFile) = NULL; rlm@1: rlm@1: //Kludge to get it to compile in Linux, GCC cannot convert rlm@1: //gzwrite function pointer to the type of utilGzWriteFunc rlm@1: //due to void* and const void* differences rlm@1: //--Felipe rlm@1: int gzWrite(gzFile file, void* buf, unsigned len){ rlm@1: return gzwrite(file,buf,len); rlm@1: } rlm@1: rlm@1: void utilPutDword(u8 *p, u32 value) rlm@1: { rlm@1: *p++ = value & 255; rlm@1: *p++ = (value >> 8) & 255; rlm@1: *p++ = (value >> 16) & 255; rlm@1: *p = (value >> 24) & 255; rlm@1: } rlm@1: rlm@1: void utilPutWord(u8 *p, u16 value) rlm@1: { rlm@1: *p++ = value & 255; rlm@1: *p = (value >> 8) & 255; rlm@1: } rlm@1: rlm@1: void utilWriteBMP(u8 *b, int w, int h, int dstDepth, u8 *pix) rlm@1: { rlm@1: int sizeX = w; rlm@1: int sizeY = h; rlm@1: rlm@1: switch (dstDepth > 0 ? dstDepth : systemColorDepth) rlm@1: { rlm@1: case 16: rlm@1: { rlm@1: u16 *p = (u16 *)(pix + (w + 2) * (h) * 2); // skip first black line rlm@1: for (int y = 0; y < sizeY; y++) rlm@1: { rlm@1: for (int x = 0; x < sizeX; x++) rlm@1: { rlm@1: u16 v = *p++; rlm@1: rlm@1: *b++ = ((v >> systemBlueShift) & 0x01f) << 3; // B rlm@1: *b++ = ((v >> systemGreenShift) & 0x001f) << 3; // G rlm@1: *b++ = ((v >> systemRedShift) & 0x001f) << 3; // R rlm@1: } rlm@1: p++; // skip black pixel for filters rlm@1: p++; // skip black pixel for filters rlm@1: p -= 2 * (w + 2); rlm@1: } rlm@1: break; rlm@1: } rlm@1: case 24: rlm@1: { rlm@1: u8 *pixU8 = (u8 *)pix + 3 * w * (h - 1); rlm@1: for (int y = 0; y < sizeY; y++) rlm@1: { rlm@1: for (int x = 0; x < sizeX; x++) rlm@1: { rlm@1: if (systemRedShift > systemBlueShift) rlm@1: { rlm@1: *b++ = *pixU8++; // B rlm@1: *b++ = *pixU8++; // G rlm@1: *b++ = *pixU8++; // R rlm@1: } rlm@1: else rlm@1: { rlm@1: int red = *pixU8++; rlm@1: int green = *pixU8++; rlm@1: int blue = *pixU8++; rlm@1: rlm@1: *b++ = blue; rlm@1: *b++ = green; rlm@1: *b++ = red; rlm@1: } rlm@1: } rlm@1: pixU8 -= 2 * 3 * w; rlm@1: } rlm@1: break; rlm@1: } rlm@1: case 32: rlm@1: { rlm@1: u32 *pixU32 = (u32 *)(pix + 4 * (w + 1) * (h)); rlm@1: for (int y = 0; y < sizeY; y++) rlm@1: { rlm@1: for (int x = 0; x < sizeX; x++) rlm@1: { rlm@1: u32 v = *pixU32++; rlm@1: rlm@1: *b++ = ((v >> systemBlueShift) & 0x001f) << 3; // B rlm@1: *b++ = ((v >> systemGreenShift) & 0x001f) << 3; // G rlm@1: *b++ = ((v >> systemRedShift) & 0x001f) << 3; // R rlm@1: } rlm@1: pixU32++; rlm@1: pixU32 -= 2 * (w + 1); rlm@1: } rlm@1: break; rlm@1: } rlm@1: } rlm@1: } rlm@1: rlm@1: bool utilWriteBMPFile(const char *fileName, int w, int h, u8 *pix) rlm@1: { rlm@1: u8 writeBuffer[256 * 3]; rlm@1: rlm@1: FILE *fp = fopen(fileName, "wb"); rlm@1: rlm@1: if (!fp) rlm@1: { rlm@1: systemMessage(MSG_ERROR_CREATING_FILE, N_("Error creating file %s"), fileName); rlm@1: return false; rlm@1: } rlm@1: rlm@1: struct rlm@1: { rlm@1: u8 ident[2]; rlm@1: u8 filesize[4]; rlm@1: u8 reserved[4]; rlm@1: u8 dataoffset[4]; rlm@1: u8 headersize[4]; rlm@1: u8 width[4]; rlm@1: u8 height[4]; rlm@1: u8 planes[2]; rlm@1: u8 bitsperpixel[2]; rlm@1: u8 compression[4]; rlm@1: u8 datasize[4]; rlm@1: u8 hres[4]; rlm@1: u8 vres[4]; rlm@1: u8 colors[4]; rlm@1: u8 importantcolors[4]; rlm@1: // u8 pad[2]; rlm@1: } bmpheader; rlm@1: memset(&bmpheader, 0, sizeof(bmpheader)); rlm@1: rlm@1: bmpheader.ident[0] = 'B'; rlm@1: bmpheader.ident[1] = 'M'; rlm@1: rlm@1: u32 fsz = sizeof(bmpheader) + w * h * 3; rlm@1: utilPutDword(bmpheader.filesize, fsz); rlm@1: utilPutDword(bmpheader.dataoffset, 0x36); rlm@1: utilPutDword(bmpheader.headersize, 0x28); rlm@1: utilPutDword(bmpheader.width, w); rlm@1: utilPutDword(bmpheader.height, h); rlm@1: utilPutDword(bmpheader.planes, 1); rlm@1: utilPutDword(bmpheader.bitsperpixel, 24); rlm@1: utilPutDword(bmpheader.datasize, 3 * w * h); rlm@1: rlm@1: fwrite(&bmpheader, 1, sizeof(bmpheader), fp); rlm@1: rlm@1: #if 0 rlm@1: // FIXME: need sufficient buffer rlm@1: utilWriteBMP(writeBuffer, w, h, systemColorDepth, pix); rlm@1: #else rlm@1: u8 *b = writeBuffer; rlm@1: rlm@1: int sizeX = w; rlm@1: int sizeY = h; rlm@1: rlm@1: switch (systemColorDepth) rlm@1: { rlm@1: case 16: rlm@1: { rlm@1: u16 *p = (u16 *)(pix + (w + 2) * (h) * 2); // skip first black line rlm@1: for (int y = 0; y < sizeY; y++) rlm@1: { rlm@1: for (int x = 0; x < sizeX; x++) rlm@1: { rlm@1: u16 v = *p++; rlm@1: rlm@1: *b++ = ((v >> systemBlueShift) & 0x01f) << 3; // B rlm@1: *b++ = ((v >> systemGreenShift) & 0x001f) << 3; // G rlm@1: *b++ = ((v >> systemRedShift) & 0x001f) << 3; // R rlm@1: } rlm@1: p++; // skip black pixel for filters rlm@1: p++; // skip black pixel for filters rlm@1: p -= 2 * (w + 2); rlm@1: fwrite(writeBuffer, 1, 3 * w, fp); rlm@1: rlm@1: b = writeBuffer; rlm@1: } rlm@1: break; rlm@1: } rlm@1: case 24: rlm@1: { rlm@1: u8 *pixU8 = (u8 *)pix + 3 * w * (h - 1); rlm@1: for (int y = 0; y < sizeY; y++) rlm@1: { rlm@1: for (int x = 0; x < sizeX; x++) rlm@1: { rlm@1: if (systemRedShift > systemBlueShift) rlm@1: { rlm@1: *b++ = *pixU8++; // B rlm@1: *b++ = *pixU8++; // G rlm@1: *b++ = *pixU8++; // R rlm@1: } rlm@1: else rlm@1: { rlm@1: int red = *pixU8++; rlm@1: int green = *pixU8++; rlm@1: int blue = *pixU8++; rlm@1: rlm@1: *b++ = blue; rlm@1: *b++ = green; rlm@1: *b++ = red; rlm@1: } rlm@1: } rlm@1: pixU8 -= 2 * 3 * w; rlm@1: fwrite(writeBuffer, 1, 3 * w, fp); rlm@1: rlm@1: b = writeBuffer; rlm@1: } rlm@1: break; rlm@1: } rlm@1: case 32: rlm@1: { rlm@1: u32 *pixU32 = (u32 *)(pix + 4 * (w + 1) * (h)); rlm@1: for (int y = 0; y < sizeY; y++) rlm@1: { rlm@1: for (int x = 0; x < sizeX; x++) rlm@1: { rlm@1: u32 v = *pixU32++; rlm@1: rlm@1: *b++ = ((v >> systemBlueShift) & 0x001f) << 3; // B rlm@1: *b++ = ((v >> systemGreenShift) & 0x001f) << 3; // G rlm@1: *b++ = ((v >> systemRedShift) & 0x001f) << 3; // R rlm@1: } rlm@1: pixU32++; rlm@1: pixU32 -= 2 * (w + 1); rlm@1: rlm@1: fwrite(writeBuffer, 1, 3 * w, fp); rlm@1: rlm@1: b = writeBuffer; rlm@1: } rlm@1: break; rlm@1: } rlm@1: } rlm@1: #endif rlm@1: rlm@1: fclose(fp); rlm@1: rlm@1: return true; rlm@1: } rlm@1: rlm@1: bool utilWritePNGFile(const char *fileName, int w, int h, u8 *pix) rlm@1: { rlm@41: u8 writeBuffer[256 * 3]; rlm@1: rlm@41: FILE *fp = fopen(fileName, "wb"); rlm@1: rlm@41: if (!fp) rlm@41: { rlm@41: systemMessage(MSG_ERROR_CREATING_FILE, N_("Error creating file %s"), fileName); rlm@41: return false; rlm@41: } rlm@1: rlm@41: png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, rlm@41: NULL, rlm@41: NULL, rlm@41: NULL); rlm@41: if (!png_ptr) rlm@41: { rlm@41: fclose(fp); rlm@41: return false; rlm@41: } rlm@1: rlm@41: png_infop info_ptr = png_create_info_struct(png_ptr); rlm@1: rlm@41: if (!info_ptr) rlm@41: { rlm@41: png_destroy_write_struct(&png_ptr, NULL); rlm@41: fclose(fp); rlm@41: return false; rlm@41: } rlm@1: rlm@41: if (setjmp(png_jmpbuf(png_ptr))) rlm@41: { rlm@41: png_destroy_write_struct(&png_ptr, NULL); rlm@41: fclose(fp); rlm@41: return false; rlm@41: } rlm@1: rlm@41: png_init_io(png_ptr, fp); rlm@1: rlm@41: png_set_IHDR(png_ptr, rlm@41: info_ptr, rlm@41: w, rlm@41: h, rlm@41: 8, rlm@41: PNG_COLOR_TYPE_RGB, rlm@41: PNG_INTERLACE_NONE, rlm@41: PNG_COMPRESSION_TYPE_DEFAULT, rlm@41: PNG_FILTER_TYPE_DEFAULT); rlm@1: rlm@41: png_write_info(png_ptr, info_ptr); rlm@1: rlm@41: u8 *b = writeBuffer; rlm@1: rlm@41: int sizeX = w; rlm@41: int sizeY = h; rlm@1: rlm@41: switch (systemColorDepth) rlm@41: { rlm@41: case 16: rlm@41: { rlm@41: u16 *p = (u16 *)(pix + (w + 2) * 2); // skip first black line rlm@41: for (int y = 0; y < sizeY; y++) rlm@41: { rlm@41: for (int x = 0; x < sizeX; x++) rlm@41: { rlm@41: u16 v = *p++; rlm@1: rlm@41: *b++ = ((v >> systemRedShift) & 0x001f) << 3; // R rlm@41: *b++ = ((v >> systemGreenShift) & 0x001f) << 3; // G rlm@41: *b++ = ((v >> systemBlueShift) & 0x01f) << 3; // B rlm@41: } rlm@41: p++; // skip black pixel for filters rlm@41: p++; // skip black pixel for filters rlm@41: png_write_row(png_ptr, writeBuffer); rlm@1: rlm@41: b = writeBuffer; rlm@41: } rlm@41: break; rlm@41: } rlm@41: case 24: rlm@41: { rlm@41: u8 *pixU8 = (u8 *)pix; rlm@41: for (int y = 0; y < sizeY; y++) rlm@41: { rlm@41: for (int x = 0; x < sizeX; x++) rlm@41: { rlm@41: if (systemRedShift < systemBlueShift) rlm@41: { rlm@41: *b++ = *pixU8++; // R rlm@41: *b++ = *pixU8++; // G rlm@41: *b++ = *pixU8++; // B rlm@41: } rlm@41: else rlm@41: { rlm@41: int blue = *pixU8++; rlm@41: int green = *pixU8++; rlm@41: int red = *pixU8++; rlm@1: rlm@41: *b++ = red; rlm@41: *b++ = green; rlm@41: *b++ = blue; rlm@41: } rlm@41: } rlm@41: png_write_row(png_ptr, writeBuffer); rlm@1: rlm@41: b = writeBuffer; rlm@41: } rlm@41: break; rlm@41: } rlm@41: case 32: rlm@41: { rlm@41: u32 *pixU32 = (u32 *)(pix + 4 * (w + 1)); rlm@41: for (int y = 0; y < sizeY; y++) rlm@41: { rlm@41: for (int x = 0; x < sizeX; x++) rlm@41: { rlm@41: u32 v = *pixU32++; rlm@1: rlm@41: *b++ = ((v >> systemRedShift) & 0x001f) << 3; // R rlm@41: *b++ = ((v >> systemGreenShift) & 0x001f) << 3; // G rlm@41: *b++ = ((v >> systemBlueShift) & 0x001f) << 3; // B rlm@41: } rlm@41: pixU32++; rlm@1: rlm@41: png_write_row(png_ptr, writeBuffer); rlm@1: rlm@41: b = writeBuffer; rlm@41: } rlm@41: break; rlm@41: } rlm@41: } rlm@1: rlm@41: png_write_end(png_ptr, info_ptr); rlm@1: rlm@41: png_destroy_write_struct(&png_ptr, &info_ptr); rlm@1: rlm@41: fclose(fp); rlm@1: rlm@41: return true; rlm@1: } rlm@1: rlm@1: static int utilReadInt2(FILE *f) rlm@1: { rlm@1: int res = 0; rlm@1: int c = fgetc(f); rlm@1: if (c == EOF) rlm@1: return -1; rlm@1: res = c; rlm@1: c = fgetc(f); rlm@1: if (c == EOF) rlm@1: return -1; rlm@1: return c + (res << 8); rlm@1: } rlm@1: rlm@1: static int utilReadInt3(FILE *f) rlm@1: { rlm@1: int res = 0; rlm@1: int c = fgetc(f); rlm@1: if (c == EOF) rlm@1: return -1; rlm@1: res = c; rlm@1: c = fgetc(f); rlm@1: if (c == EOF) rlm@1: return -1; rlm@1: res = c + (res << 8); rlm@1: c = fgetc(f); rlm@1: if (c == EOF) rlm@1: return -1; rlm@1: return c + (res << 8); rlm@1: } rlm@1: rlm@1: void utilApplyIPS(const char *ips, u8 * *r, int *s) rlm@1: { rlm@1: // from the IPS spec at http://zerosoft.zophar.net/ips.htm rlm@1: FILE *f = fopen(ips, "rb"); rlm@1: if (!f) rlm@1: return; rlm@1: u8 *rom = *r; rlm@1: int size = *s; rlm@1: if (fgetc(f) == 'P' && rlm@1: fgetc(f) == 'A' && rlm@1: fgetc(f) == 'T' && rlm@1: fgetc(f) == 'C' && rlm@1: fgetc(f) == 'H') rlm@1: { rlm@1: int b; rlm@1: int offset; rlm@1: int len; rlm@1: for (;; ) rlm@1: { rlm@1: // read offset rlm@1: offset = utilReadInt3(f); rlm@1: // if offset == EOF, end of patch rlm@1: if (offset == 0x454f46) rlm@1: break; rlm@1: // read length rlm@1: len = utilReadInt2(f); rlm@1: if (!len) rlm@1: { rlm@1: // len == 0, RLE block rlm@1: len = utilReadInt2(f); rlm@1: // byte to fill rlm@1: int c = fgetc(f); rlm@1: if (c == -1) rlm@1: break; rlm@1: b = (u8)c; rlm@1: } rlm@1: else rlm@1: b = -1; rlm@1: // check if we need to reallocate our ROM rlm@1: if ((offset + len) >= size) rlm@1: { rlm@1: size *= 2; rlm@1: rom = (u8 *)realloc(rom, size); rlm@1: *r = rom; rlm@1: *s = size; rlm@1: } rlm@1: if (b == -1) rlm@1: { rlm@1: // normal block, just read the data rlm@1: if (fread(&rom[offset], 1, len, f) != (size_t)len) rlm@1: break; rlm@1: } rlm@1: else rlm@1: { rlm@1: // fill the region with the given byte rlm@1: while (len--) rlm@1: { rlm@1: rom[offset++] = b; rlm@1: } rlm@1: } rlm@1: } rlm@1: } rlm@1: // close the file rlm@1: fclose(f); rlm@1: } rlm@1: rlm@1: extern bool8 cpuIsMultiBoot; rlm@1: rlm@1: bool utilIsGBAImage(const char *file) rlm@1: { rlm@1: cpuIsMultiBoot = false; rlm@1: if (strlen(file) > 4) rlm@1: { rlm@1: const char *p = strrchr(file, '.'); rlm@1: rlm@1: if (p != NULL) rlm@1: { rlm@1: if (_stricmp(p, ".gba") == 0) rlm@1: return true; rlm@1: if (_stricmp(p, ".agb") == 0) rlm@1: return true; rlm@1: if (_stricmp(p, ".bin") == 0) rlm@1: return true; rlm@1: if (_stricmp(p, ".elf") == 0) rlm@1: return true; rlm@1: if (_stricmp(p, ".mb") == 0) rlm@1: { rlm@1: cpuIsMultiBoot = true; rlm@1: return true; rlm@1: } rlm@1: } rlm@1: } rlm@1: rlm@1: return false; rlm@1: } rlm@1: rlm@1: bool utilIsGBImage(const char *file) rlm@1: { rlm@1: if (strlen(file) > 4) rlm@1: { rlm@1: const char *p = strrchr(file, '.'); rlm@1: rlm@1: if (p != NULL) rlm@1: { rlm@1: if (_stricmp(p, ".gb") == 0) rlm@1: return true; rlm@1: if (_stricmp(p, ".gbc") == 0) rlm@1: return true; rlm@1: if (_stricmp(p, ".cgb") == 0) rlm@1: return true; rlm@1: if (_stricmp(p, ".sgb") == 0) rlm@1: return true; rlm@1: } rlm@1: } rlm@1: rlm@1: return false; rlm@1: } rlm@1: rlm@1: bool utilIsGBABios(const char *file) rlm@1: { rlm@1: if (strlen(file) > 4) rlm@1: { rlm@1: const char *p = strrchr(file, '.'); rlm@1: rlm@1: if (p != NULL) rlm@1: { rlm@1: if (_stricmp(p, ".gba") == 0) rlm@1: return true; rlm@1: if (_stricmp(p, ".agb") == 0) rlm@1: return true; rlm@1: if (_stricmp(p, ".bin") == 0) rlm@1: return true; rlm@1: if (_stricmp(p, ".bios") == 0) rlm@1: return true; rlm@1: if (_stricmp(p, ".rom") == 0) rlm@1: return true; rlm@1: } rlm@1: } rlm@1: rlm@1: return false; rlm@1: } rlm@1: rlm@1: bool utilIsGBBios(const char *file) rlm@1: { rlm@1: if (strlen(file) > 4) rlm@1: { rlm@1: const char *p = strrchr(file, '.'); rlm@1: rlm@1: if (p != NULL) rlm@1: { rlm@1: if (_stricmp(p, ".gb") == 0) rlm@1: return true; rlm@1: if (_stricmp(p, ".bin") == 0) rlm@1: return true; rlm@1: if (_stricmp(p, ".bios") == 0) rlm@1: return true; rlm@1: if (_stricmp(p, ".rom") == 0) rlm@1: return true; rlm@1: } rlm@1: } rlm@1: rlm@1: return false; rlm@1: } rlm@1: rlm@1: bool utilIsELF(const char *file) rlm@1: { rlm@1: if (strlen(file) > 4) rlm@1: { rlm@1: const char *p = strrchr(file, '.'); rlm@1: rlm@1: if (p != NULL) rlm@1: { rlm@1: if (_stricmp(p, ".elf") == 0) rlm@1: return true; rlm@1: } rlm@1: } rlm@1: return false; rlm@1: } rlm@1: rlm@1: bool utilIsZipFile(const char *file) rlm@1: { rlm@1: if (strlen(file) > 4) rlm@1: { rlm@1: const char *p = strrchr(file, '.'); rlm@1: rlm@1: if (p != NULL) rlm@1: { rlm@1: if (_stricmp(p, ".zip") == 0) rlm@1: return true; rlm@1: } rlm@1: } rlm@1: rlm@1: return false; rlm@1: } rlm@1: rlm@1: #if 0 rlm@1: bool utilIsRarFile(const char *file) rlm@1: { rlm@1: if (strlen(file) > 4) rlm@1: { rlm@1: char *p = strrchr(file, '.'); rlm@1: rlm@1: if (p != NULL) rlm@1: { rlm@1: if (_stricmp(p, ".rar") == 0) rlm@1: return true; rlm@1: } rlm@1: } rlm@1: rlm@1: return false; rlm@1: } rlm@1: rlm@1: #endif rlm@1: rlm@1: bool utilIsGzipFile(const char *file) rlm@1: { rlm@1: if (strlen(file) > 3) rlm@1: { rlm@1: const char *p = strrchr(file, '.'); rlm@1: rlm@1: if (p != NULL) rlm@1: { rlm@1: if (_stricmp(p, ".gz") == 0) rlm@1: return true; rlm@1: if (_stricmp(p, ".z") == 0) rlm@1: return true; rlm@1: } rlm@1: } rlm@1: rlm@1: return false; rlm@1: } rlm@1: rlm@1: void utilGetBaseName(const char *file, char *buffer) rlm@1: { rlm@1: strcpy(buffer, file); rlm@1: rlm@1: if (utilIsGzipFile(file)) rlm@1: { rlm@1: char *p = strrchr(buffer, '.'); rlm@1: rlm@1: if (p) rlm@1: *p = 0; rlm@1: } rlm@1: } rlm@1: rlm@1: IMAGE_TYPE utilFindType(const char *file) rlm@1: { rlm@1: char buffer[2048]; rlm@1: rlm@1: if (utilIsZipFile(file)) rlm@1: { rlm@1: unzFile unz = unzOpen(file); rlm@1: rlm@1: if (unz == NULL) rlm@1: { rlm@1: systemMessage(MSG_CANNOT_OPEN_FILE, N_("Cannot open file %s"), file); rlm@1: return IMAGE_UNKNOWN; rlm@1: } rlm@1: rlm@1: int r = unzGoToFirstFile(unz); rlm@1: rlm@1: if (r != UNZ_OK) rlm@1: { rlm@1: unzClose(unz); rlm@1: systemMessage(MSG_BAD_ZIP_FILE, N_("Bad ZIP file %s"), file); rlm@1: return IMAGE_UNKNOWN; rlm@1: } rlm@1: rlm@1: IMAGE_TYPE found = IMAGE_UNKNOWN; rlm@1: rlm@1: unz_file_info info; rlm@1: rlm@1: while (true) rlm@1: { rlm@1: r = unzGetCurrentFileInfo(unz, rlm@1: &info, rlm@1: buffer, rlm@1: sizeof(buffer), rlm@1: NULL, rlm@1: 0, rlm@1: NULL, rlm@1: 0); rlm@1: rlm@1: if (r != UNZ_OK) rlm@1: { rlm@1: unzClose(unz); rlm@1: systemMessage(MSG_BAD_ZIP_FILE, N_("Bad ZIP file %s"), file); rlm@1: return IMAGE_UNKNOWN; rlm@1: } rlm@1: rlm@1: if (utilIsGBAImage(buffer)) rlm@1: { rlm@1: found = IMAGE_GBA; rlm@1: break; rlm@1: } rlm@1: rlm@1: if (utilIsGBImage(buffer)) rlm@1: { rlm@1: found = IMAGE_GB; rlm@1: break; rlm@1: } rlm@1: rlm@1: r = unzGoToNextFile(unz); rlm@1: rlm@1: if (r != UNZ_OK) rlm@1: break; rlm@1: } rlm@1: unzClose(unz); rlm@1: rlm@1: if (found == IMAGE_UNKNOWN) rlm@1: { rlm@1: systemMessage(MSG_NO_IMAGE_ON_ZIP, rlm@1: N_("No image found on ZIP file %s"), file); rlm@1: return found; rlm@1: } rlm@1: return found; rlm@1: #if 0 rlm@1: } rlm@1: else if (utilIsRarFile(file)) rlm@1: { rlm@1: IMAGE_TYPE found = IMAGE_UNKNOWN; rlm@1: rlm@1: ArchiveList_struct *rarList = NULL; rlm@1: if (urarlib_list((void *)file, (ArchiveList_struct *)&rarList)) rlm@1: { rlm@1: ArchiveList_struct *p = rarList; rlm@1: rlm@1: while (p) rlm@1: { rlm@1: if (utilIsGBAImage(p->item.Name)) rlm@1: { rlm@1: found = IMAGE_GBA; rlm@1: break; rlm@1: } rlm@1: rlm@1: if (utilIsGBImage(p->item.Name)) rlm@1: { rlm@1: found = IMAGE_GB; rlm@1: break; rlm@1: } rlm@1: p = p->next; rlm@1: } rlm@1: rlm@1: urarlib_freelist(rarList); rlm@1: } rlm@1: return found; rlm@1: #endif rlm@1: } rlm@1: else rlm@1: { rlm@1: if (utilIsGzipFile(file)) rlm@1: utilGetBaseName(file, buffer); rlm@1: else rlm@1: strcpy(buffer, file); rlm@1: rlm@1: if (utilIsGBAImage(buffer)) rlm@1: return IMAGE_GBA; rlm@1: if (utilIsGBImage(buffer)) rlm@1: return IMAGE_GB; rlm@1: } rlm@1: return IMAGE_UNKNOWN; rlm@1: } rlm@1: rlm@1: static int utilGetSize(int size) rlm@1: { rlm@1: int res = 1; rlm@1: while (res < size) rlm@1: res <<= 1; rlm@1: return res; rlm@1: } rlm@1: rlm@1: static u8 *utilLoadFromZip(const char *file, rlm@1: bool (*accept)(const char *), rlm@1: u8 *data, rlm@1: int &size) rlm@1: { rlm@1: char buffer[2048]; rlm@1: rlm@1: unzFile unz = unzOpen(file); rlm@1: rlm@1: if (unz == NULL) rlm@1: { rlm@1: systemMessage(MSG_CANNOT_OPEN_FILE, N_("Cannot open file %s"), file); rlm@1: return NULL; rlm@1: } rlm@1: int r = unzGoToFirstFile(unz); rlm@1: rlm@1: if (r != UNZ_OK) rlm@1: { rlm@1: unzClose(unz); rlm@1: systemMessage(MSG_BAD_ZIP_FILE, N_("Bad ZIP file %s"), file); rlm@1: return NULL; rlm@1: } rlm@1: rlm@1: bool found = false; rlm@1: rlm@1: unz_file_info info; rlm@1: rlm@1: while (true) rlm@1: { rlm@1: r = unzGetCurrentFileInfo(unz, rlm@1: &info, rlm@1: buffer, rlm@1: sizeof(buffer), rlm@1: NULL, rlm@1: 0, rlm@1: NULL, rlm@1: 0); rlm@1: rlm@1: if (r != UNZ_OK) rlm@1: { rlm@1: unzClose(unz); rlm@1: systemMessage(MSG_BAD_ZIP_FILE, N_("Bad ZIP file %s"), file); rlm@1: return NULL; rlm@1: } rlm@1: rlm@1: if (accept(buffer)) rlm@1: { rlm@1: found = true; rlm@1: break; rlm@1: } rlm@1: rlm@1: r = unzGoToNextFile(unz); rlm@1: rlm@1: if (r != UNZ_OK) rlm@1: break; rlm@1: } rlm@1: rlm@1: if (!found) rlm@1: { rlm@1: unzClose(unz); rlm@1: systemMessage(MSG_NO_IMAGE_ON_ZIP, rlm@1: N_("No image found on ZIP file %s"), file); rlm@1: return NULL; rlm@1: } rlm@1: rlm@1: int fileSize = info.uncompressed_size; rlm@1: if (size == 0) rlm@1: size = fileSize; rlm@1: r = unzOpenCurrentFile(unz); rlm@1: rlm@1: if (r != UNZ_OK) rlm@1: { rlm@1: unzClose(unz); rlm@1: systemMessage(MSG_ERROR_OPENING_IMAGE, N_("Error opening image %s"), buffer); rlm@1: return NULL; rlm@1: } rlm@1: rlm@1: u8 *image = data; rlm@1: rlm@1: if (image == NULL) rlm@1: { rlm@1: image = (u8 *)malloc(utilGetSize(size)); rlm@1: if (image == NULL) rlm@1: { rlm@1: unzCloseCurrentFile(unz); rlm@1: unzClose(unz); rlm@1: systemMessage(MSG_OUT_OF_MEMORY, N_("Failed to allocate memory for %s"), rlm@1: "data"); rlm@1: return NULL; rlm@1: } rlm@1: size = fileSize; rlm@1: } rlm@1: int read = fileSize <= size ? fileSize : size; rlm@1: r = unzReadCurrentFile(unz, rlm@1: image, rlm@1: read); rlm@1: rlm@1: unzCloseCurrentFile(unz); rlm@1: unzClose(unz); rlm@1: rlm@1: if (r != (int)read) rlm@1: { rlm@1: systemMessage(MSG_ERROR_READING_IMAGE, rlm@1: N_("Error reading image %s"), buffer); rlm@1: if (data == NULL) rlm@1: free(image); rlm@1: return NULL; rlm@1: } rlm@1: rlm@1: size = fileSize; rlm@1: rlm@1: return image; rlm@1: } rlm@1: rlm@1: static u8 *utilLoadGzipFile(const char *file, rlm@1: bool (*accept)(const char *), rlm@1: u8 *data, rlm@1: int &size) rlm@1: { rlm@1: FILE *f = fopen(file, "rb"); rlm@1: rlm@1: if (f == NULL) rlm@1: { rlm@1: systemMessage(MSG_ERROR_OPENING_IMAGE, N_("Error opening image %s"), file); rlm@1: return NULL; rlm@1: } rlm@1: rlm@1: fseek(f, -4, SEEK_END); rlm@1: int fileSize = fgetc(f) | (fgetc(f) << 8) | (fgetc(f) << 16) | (fgetc(f) << 24); rlm@1: fclose(f); rlm@1: if (size == 0) rlm@1: size = fileSize; rlm@1: rlm@1: gzFile gz = gzopen(file, "rb"); rlm@1: rlm@1: if (gz == NULL) rlm@1: { rlm@1: // should not happen, but who knows? rlm@1: systemMessage(MSG_ERROR_OPENING_IMAGE, N_("Error opening image %s"), file); rlm@1: return NULL; rlm@1: } rlm@1: rlm@1: u8 *image = data; rlm@1: rlm@1: if (image == NULL) rlm@1: { rlm@1: image = (u8 *)malloc(utilGetSize(size)); rlm@1: if (image == NULL) rlm@1: { rlm@1: systemMessage(MSG_OUT_OF_MEMORY, N_("Failed to allocate memory for %s"), rlm@1: "data"); rlm@1: fclose(f); rlm@1: return NULL; rlm@1: } rlm@1: size = fileSize; rlm@1: } rlm@1: int read = fileSize <= size ? fileSize : size; rlm@1: int r = gzread(gz, image, read); rlm@1: gzclose(gz); rlm@1: rlm@1: if (r != (int)read) rlm@1: { rlm@1: systemMessage(MSG_ERROR_READING_IMAGE, rlm@1: N_("Error reading image %s"), file); rlm@1: if (data == NULL) rlm@1: free(image); rlm@1: return NULL; rlm@1: } rlm@1: rlm@1: size = fileSize; rlm@1: rlm@1: return image; rlm@1: } rlm@1: rlm@1: #if 0 rlm@1: static u8 *utilLoadRarFile(const char *file, rlm@1: bool (*accept)(const char *), rlm@1: u8 *data, rlm@1: int &size) rlm@1: { rlm@1: char buffer[2048]; rlm@1: rlm@1: ArchiveList_struct *rarList = NULL; rlm@1: if (urarlib_list((void *)file, (ArchiveList_struct *)&rarList)) rlm@1: { rlm@1: ArchiveList_struct *p = rarList; rlm@1: rlm@1: bool found = false; rlm@1: while (p) rlm@1: { rlm@1: if (accept(p->item.Name)) rlm@1: { rlm@1: strcpy(buffer, p->item.Name); rlm@1: found = true; rlm@1: break; rlm@1: } rlm@1: p = p->next; rlm@1: } rlm@1: if (found) rlm@1: { rlm@1: void *memory = NULL; rlm@1: unsigned long lsize = 0; rlm@1: size = p->item.UnpSize; rlm@1: int r = urarlib_get((void *)&memory, &lsize, buffer, (void *)file, ""); rlm@1: if (!r) rlm@1: { rlm@1: systemMessage(MSG_ERROR_READING_IMAGE, rlm@1: N_("Error reading image %s"), buffer); rlm@1: urarlib_freelist(rarList); rlm@1: return NULL; rlm@1: } rlm@1: u8 *image = (u8 *)memory; rlm@1: if (data != NULL) rlm@1: { rlm@1: memcpy(image, data, size); rlm@1: } rlm@1: urarlib_freelist(rarList); rlm@1: return image; rlm@1: } rlm@1: systemMessage(MSG_NO_IMAGE_ON_ZIP, rlm@1: N_("No image found on RAR file %s"), file); rlm@1: urarlib_freelist(rarList); rlm@1: return NULL; rlm@1: } rlm@1: // nothing found rlm@1: return NULL; rlm@1: } rlm@1: rlm@1: #endif rlm@1: rlm@1: // the caller is responsible for caling free(return value) to release the memory rlm@1: u8 *utilLoad(const char *file, rlm@1: bool (*accept)(const char *), rlm@1: u8 *data, rlm@1: int &size) rlm@1: { rlm@1: if (utilIsZipFile(file)) rlm@1: { rlm@1: return utilLoadFromZip(file, accept, data, size); rlm@1: } rlm@1: if (utilIsGzipFile(file)) rlm@1: { rlm@1: return utilLoadGzipFile(file, accept, data, size); rlm@1: } rlm@1: #if 0 rlm@1: if (utilIsRarFile(file)) rlm@1: { rlm@1: return utilLoadRarFile(file, accept, data, size); rlm@1: } rlm@1: #endif rlm@1: rlm@1: u8 *image = data; rlm@1: rlm@1: FILE *f = fopen(file, "rb"); rlm@1: rlm@1: if (!f) rlm@1: { rlm@1: systemMessage(MSG_ERROR_OPENING_IMAGE, N_("Error opening image %s"), file); rlm@1: return NULL; rlm@1: } rlm@1: rlm@1: fseek(f, 0, SEEK_END); rlm@1: int fileSize = ftell(f); rlm@1: fseek(f, 0, SEEK_SET); rlm@1: if (size == 0) rlm@1: size = fileSize; rlm@1: rlm@1: if (image == NULL) rlm@1: { rlm@1: image = (u8 *)malloc(utilGetSize(size)); rlm@1: if (image == NULL) rlm@1: { rlm@1: systemMessage(MSG_OUT_OF_MEMORY, N_("Failed to allocate memory for %s"), rlm@1: "data"); rlm@1: fclose(f); rlm@1: return NULL; rlm@1: } rlm@1: size = fileSize; rlm@1: } rlm@1: int read = fileSize <= size ? fileSize : size; rlm@1: int r = fread(image, 1, read, f); rlm@1: fclose(f); rlm@1: rlm@1: if (r != (int)read) rlm@1: { rlm@1: systemMessage(MSG_ERROR_READING_IMAGE, rlm@1: N_("Error reading image %s"), file); rlm@1: if (data == NULL) rlm@1: free(image); rlm@1: return NULL; rlm@1: } rlm@1: rlm@1: size = fileSize; rlm@1: rlm@1: return image; rlm@1: } rlm@1: rlm@1: void utilWriteInt(gzFile gzFile, int32 i) rlm@1: { rlm@1: utilGzWrite(gzFile, &i, sizeof(int32)); rlm@1: } rlm@1: rlm@1: int32 utilReadInt(gzFile gzFile) rlm@1: { rlm@1: int32 i = 0; rlm@1: utilGzRead(gzFile, &i, sizeof(int32)); rlm@1: return i; rlm@1: } rlm@1: rlm@1: void utilReadData(gzFile gzFile, variable_desc *data) rlm@1: { rlm@1: while (data->address) rlm@1: { rlm@1: utilGzRead(gzFile, data->address, data->size); rlm@1: data++; rlm@1: } rlm@1: } rlm@1: rlm@1: void utilWriteData(gzFile gzFile, variable_desc *data) rlm@1: { rlm@1: while (data->address) rlm@1: { rlm@1: utilGzWrite(gzFile, data->address, data->size); rlm@1: data++; rlm@1: } rlm@1: } rlm@1: rlm@1: gzFile utilGzOpen(const char *file, const char *mode) rlm@1: { rlm@1: utilGzWriteFunc = gzWrite; rlm@1: utilGzReadFunc = gzread; rlm@1: utilGzCloseFunc = gzclose; rlm@1: utilGzSeekFunc = gzseek; rlm@1: utilGzTellFunc = gztell; rlm@1: rlm@1: return gzopen(file, mode); rlm@1: } rlm@1: rlm@1: gzFile utilGzReopen(int id, const char *mode) rlm@1: { rlm@1: utilGzWriteFunc = gzWrite; rlm@1: utilGzReadFunc = gzread; rlm@1: utilGzCloseFunc = gzclose; rlm@1: utilGzSeekFunc = gzseek; rlm@1: utilGzTellFunc = gztell; rlm@1: rlm@1: return gzdopen(id, mode); rlm@1: } rlm@1: rlm@1: gzFile utilMemGzOpen(char *memory, int available, char *mode) rlm@1: { rlm@1: utilGzWriteFunc = memgzwrite; rlm@1: utilGzReadFunc = memgzread; rlm@1: utilGzCloseFunc = memgzclose; rlm@1: utilGzSeekFunc = NULL; // FIXME: not implemented... rlm@1: utilGzTellFunc = memtell; rlm@1: rlm@1: return memgzopen(memory, available, mode); rlm@1: } rlm@1: rlm@1: int utilGzWrite(gzFile file, voidp buffer, unsigned int len) rlm@1: { rlm@1: return utilGzWriteFunc(file, buffer, len); rlm@1: } rlm@1: rlm@1: int utilGzRead(gzFile file, voidp buffer, unsigned int len) rlm@1: { rlm@1: return utilGzReadFunc(file, buffer, len); rlm@1: } rlm@1: rlm@1: int utilGzClose(gzFile file) rlm@1: { rlm@1: return utilGzCloseFunc(file); rlm@1: } rlm@1: rlm@1: z_off_t utilGzSeek(gzFile file, z_off_t offset, int whence) rlm@1: { rlm@1: return utilGzSeekFunc(file, offset, whence); rlm@1: } rlm@1: rlm@1: z_off_t utilGzTell(gzFile file) rlm@1: { rlm@1: return utilGzTellFunc(file); rlm@1: } rlm@1: rlm@1: void utilGBAFindSave(const u8 *data, const int size) rlm@1: { rlm@1: u32 *p = (u32 *)data; rlm@1: u32 *end = (u32 *)(data + size); rlm@1: int saveType = 0; rlm@1: int flashSize = 0x10000; rlm@1: bool rtcFound = false; rlm@1: rlm@1: while (p < end) rlm@1: { rlm@1: u32 d = READ32LE(p); rlm@1: rlm@1: if (d == 0x52504545) rlm@1: { rlm@1: if (memcmp(p, "EEPROM_", 7) == 0) rlm@1: { rlm@1: if (saveType == 0) rlm@1: saveType = 1; rlm@1: } rlm@1: } rlm@1: else if (d == 0x4D415253) rlm@1: { rlm@1: if (memcmp(p, "SRAM_", 5) == 0) rlm@1: { rlm@1: if (saveType == 0) rlm@1: saveType = 2; rlm@1: } rlm@1: } rlm@1: else if (d == 0x53414C46) rlm@1: { rlm@1: if (memcmp(p, "FLASH1M_", 8) == 0) rlm@1: { rlm@1: if (saveType == 0) rlm@1: { rlm@1: saveType = 3; rlm@1: flashSize = 0x20000; rlm@1: } rlm@1: } rlm@1: else if (memcmp(p, "FLASH", 5) == 0) rlm@1: { rlm@1: if (saveType == 0) rlm@1: { rlm@1: saveType = 3; rlm@1: flashSize = 0x10000; rlm@1: } rlm@1: } rlm@1: } rlm@1: else if (d == 0x52494953) rlm@1: { rlm@1: if (memcmp(p, "SIIRTC_V", 8) == 0) rlm@1: rtcFound = true; rlm@1: } rlm@1: p++; rlm@1: } rlm@1: // if no matches found, then set it to NONE rlm@1: if (saveType == 0) rlm@1: { rlm@1: saveType = 5; rlm@1: } rlm@1: rtcEnable(rtcFound); rlm@1: cpuSaveType = saveType; rlm@1: flashSetSize(flashSize); rlm@1: } rlm@1: rlm@1: void utilUpdateSystemColorMaps() rlm@1: { rlm@1: switch (systemColorDepth) rlm@1: { rlm@1: case 16: rlm@1: { rlm@1: for (int i = 0; i < 0x10000; i++) rlm@1: { rlm@1: systemColorMap16[i] = ((i & 0x1f) << systemRedShift) | rlm@1: (((i & 0x3e0) >> 5) << systemGreenShift) | rlm@1: (((i & 0x7c00) >> 10) << systemBlueShift); rlm@1: } rlm@1: break; rlm@1: } rlm@1: case 24: rlm@1: case 32: rlm@1: { rlm@1: for (int i = 0; i < 0x10000; i++) rlm@1: { rlm@1: systemColorMap32[i] = ((i & 0x1f) << systemRedShift) | rlm@1: (((i & 0x3e0) >> 5) << systemGreenShift) | rlm@1: (((i & 0x7c00) >> 10) << systemBlueShift); rlm@1: } rlm@1: break; rlm@1: } rlm@1: } rlm@1: } rlm@1: rlm@1: //// BIOS stuff rlm@1: // systemType uses the same enum values as gbEmulatorType does rlm@1: rlm@1: bool utilLoadBIOS(u8 *bios, const char *biosFileName, int systemType) rlm@1: { rlm@1: if (bios == NULL || strlen(biosFileName) == 0) rlm@1: return false; rlm@1: rlm@1: if (systemType == 4) rlm@1: { rlm@1: int biosSize = 0x4000; rlm@1: if (utilLoad(biosFileName, utilIsGBABios, bios, biosSize)) rlm@1: { rlm@1: if (biosSize == 0x4000) rlm@1: return true; rlm@1: } rlm@1: } rlm@1: else rlm@1: { rlm@1: int biosSize = 0x100; rlm@1: if (utilLoad(biosFileName, utilIsGBBios, bios, biosSize)) rlm@1: { rlm@1: if (biosSize == 0x100) rlm@1: return true; rlm@1: } rlm@1: } rlm@1: rlm@1: return false; rlm@1: } rlm@1: rlm@1: bool utilCheckBIOS(const char *biosFileName, int systemType) rlm@1: { rlm@1: if (strlen(biosFileName) == 0) rlm@1: return false; rlm@1: rlm@1: u8 * tempBIOS = (u8 *)malloc(systemType == 4 ? 0x4000 : 0x100); rlm@1: bool result = utilLoadBIOS(tempBIOS, biosFileName, systemType); rlm@1: free(tempBIOS); rlm@1: rlm@1: return result; rlm@1: } rlm@1: rlm@1: #if 0 rlm@1: // returns the checksum of the BIOS that will be loaded after the next restart rlm@1: u16 utilCalcBIOSChecksum(const u8 *bios, int systemType) rlm@1: { rlm@1: u32 biosChecksum = 0; rlm@1: if (bios) rlm@1: { rlm@1: int biosSize = (systemType == 4 ? 0x4000 : 0x100); rlm@1: const u16 *data = reinterpret_cast(bios); rlm@1: for (int i = biosSize; i > 0; i -= 2) rlm@1: biosChecksum += *data++; rlm@1: } rlm@1: rlm@1: while ((biosChecksum >> 16) & 0xFFFF) rlm@1: biosChecksum = (biosChecksum &0xFFFF) + ((biosChecksum >> 16) & 0xFFFF); rlm@1: rlm@1: return biosChecksum & 0xFFFF; rlm@1: } rlm@1: #else rlm@1: // returns the checksum of the BIOS that will be loaded after the next restart rlm@1: u16 utilCalcBIOSChecksum(const u8 *bios, int systemType) rlm@1: { rlm@1: u32 biosChecksum = 0; rlm@1: if (bios) rlm@1: { rlm@1: int biosSize = (systemType == 4 ? 0x4000 : 0x100); rlm@1: const u32 *data = reinterpret_cast(bios); rlm@1: for (int i = biosSize; i > 0; i -= 4) rlm@1: biosChecksum += *data++; rlm@1: } rlm@1: rlm@1: return biosChecksum & 0xFFFF; rlm@1: } rlm@1: #endif rlm@1: rlm@1: // returns the checksum of the BIOS file rlm@1: u16 utilCalcBIOSFileChecksum(const char *biosFileName, int systemType) rlm@1: { rlm@1: if (strlen(biosFileName) == 0) rlm@1: return 0; rlm@1: rlm@1: u16 biosChecksum = 0; rlm@1: const int biosSize = (systemType == 4 ? 0x4000 : 0x100); rlm@1: u8 * tempBIOS = (u8 *)malloc(biosSize); rlm@1: bool hasBIOS = utilLoadBIOS(tempBIOS, biosFileName, systemType); rlm@1: if (hasBIOS) rlm@1: { rlm@1: biosChecksum = utilCalcBIOSChecksum(tempBIOS, systemType); rlm@1: } rlm@1: free(tempBIOS); rlm@1: rlm@1: return biosChecksum; rlm@1: } rlm@1: