home *** CD-ROM | disk | FTP | other *** search
/ Chip 2004 July / CMCD0704.ISO / Software / Freeware / Utilitare / VisualBoyAdvance-1.7.2 / src / Util.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2004-05-20  |  23.3 KB  |  1,070 lines

  1. // VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
  2. // Copyright (C) 1999-2003 Forgotten
  3. // Copyright (C) 2004 Forgotten and the VBA development team
  4.  
  5. // This program is free software; you can redistribute it and/or modify
  6. // it under the terms of the GNU General Public License as published by
  7. // the Free Software Foundation; either version 2, or(at your option)
  8. // any later version.
  9. //
  10. // This program is distributed in the hope that it will be useful,
  11. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. // GNU General Public License for more details.
  14. //
  15. // You should have received a copy of the GNU General Public License
  16. // along with this program; if not, write to the Free Software Foundation,
  17. // Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  18.  
  19. #include <stdio.h>
  20. #include <stdlib.h>
  21. #include <string.h>
  22. #include <zlib.h>
  23.  
  24. extern "C" {
  25. #include <png.h>
  26. }
  27.  
  28. #if 0
  29. #include "unrarlib.h"
  30. #endif
  31.  
  32. #include "System.h"
  33. #include "NLS.h"
  34. #include "Util.h"
  35. #include "Flash.h"
  36. #include "GBA.h"
  37. #include "Globals.h"
  38. #include "RTC.h"
  39. #include "Port.h"
  40.  
  41.  
  42. extern "C" {
  43. #include "memgzio.h"
  44. }
  45.  
  46. #ifndef _MSC_VER
  47. #define _stricmp strcasecmp
  48. #endif // ! _MSC_VER
  49.  
  50. static int (*utilGzWriteFunc)(gzFile, const voidp, unsigned int) = NULL;
  51. static int (*utilGzReadFunc)(gzFile, voidp, unsigned int) = NULL;
  52. static int (*utilGzCloseFunc)(gzFile) = NULL;
  53.  
  54. bool utilWritePNGFile(const char *fileName, int w, int h, u8 *pix)
  55. {
  56.   u8 writeBuffer[512 * 3];
  57.   
  58.   FILE *fp = fopen(fileName,"wb");
  59.  
  60.   if(!fp) {
  61.     systemMessage(MSG_ERROR_CREATING_FILE, N_("Error creating file %s"), fileName);
  62.     return false;
  63.   }
  64.   
  65.   png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
  66.                                                 NULL,
  67.                                                 NULL,
  68.                                                 NULL);
  69.   if(!png_ptr) {
  70.     fclose(fp);
  71.     return false;
  72.   }
  73.  
  74.   png_infop info_ptr = png_create_info_struct(png_ptr);
  75.  
  76.   if(!info_ptr) {
  77.     png_destroy_write_struct(&png_ptr,NULL);
  78.     fclose(fp);
  79.     return false;
  80.   }
  81.  
  82.   if(setjmp(png_ptr->jmpbuf)) {
  83.     png_destroy_write_struct(&png_ptr,NULL);
  84.     fclose(fp);
  85.     return false;
  86.   }
  87.  
  88.   png_init_io(png_ptr,fp);
  89.  
  90.   png_set_IHDR(png_ptr,
  91.                info_ptr,
  92.                w,
  93.                h,
  94.                8,
  95.                PNG_COLOR_TYPE_RGB,
  96.                PNG_INTERLACE_NONE,
  97.                PNG_COMPRESSION_TYPE_DEFAULT,
  98.                PNG_FILTER_TYPE_DEFAULT);
  99.  
  100.   png_write_info(png_ptr,info_ptr);
  101.  
  102.   u8 *b = writeBuffer;
  103.  
  104.   int sizeX = w;
  105.   int sizeY = h;
  106.  
  107.   switch(systemColorDepth) {
  108.   case 16:
  109.     {
  110.       u16 *p = (u16 *)(pix+(w+2)*2); // skip first black line
  111.       for(int y = 0; y < sizeY; y++) {
  112.          for(int x = 0; x < sizeX; x++) {
  113.           u16 v = *p++;
  114.           
  115.           *b++ = ((v >> systemRedShift) & 0x001f) << 3; // R
  116.           *b++ = ((v >> systemGreenShift) & 0x001f) << 3; // G 
  117.           *b++ = ((v >> systemBlueShift) & 0x01f) << 3; // B
  118.         }
  119.         p++; // skip black pixel for filters
  120.         p++; // skip black pixel for filters
  121.         png_write_row(png_ptr,writeBuffer);
  122.         
  123.         b = writeBuffer;
  124.       }
  125.     }
  126.     break;
  127.   case 24:
  128.     {
  129.       u8 *pixU8 = (u8 *)pix;
  130.       for(int y = 0; y < sizeY; y++) {
  131.         for(int x = 0; x < sizeX; x++) {
  132.           if(systemRedShift < systemBlueShift) {
  133.             *b++ = *pixU8++; // R
  134.             *b++ = *pixU8++; // G
  135.             *b++ = *pixU8++; // B
  136.           } else {
  137.             int blue = *pixU8++;
  138.             int green = *pixU8++;
  139.             int red = *pixU8++;
  140.             
  141.             *b++ = red;
  142.             *b++ = green;
  143.             *b++ = blue;
  144.           }
  145.         }
  146.         png_write_row(png_ptr,writeBuffer);
  147.         
  148.         b = writeBuffer;
  149.       }
  150.     }
  151.     break;
  152.   case 32:
  153.     {
  154.       u32 *pixU32 = (u32 *)(pix+4*(w+1));
  155.       for(int y = 0; y < sizeY; y++) {
  156.         for(int x = 0; x < sizeX; x++) {
  157.           u32 v = *pixU32++;
  158.           
  159.           *b++ = ((v >> systemRedShift) & 0x001f) << 3; // R
  160.           *b++ = ((v >> systemGreenShift) & 0x001f) << 3; // G
  161.           *b++ = ((v >> systemBlueShift) & 0x001f) << 3; // B
  162.         }
  163.         pixU32++;
  164.         
  165.         png_write_row(png_ptr,writeBuffer);
  166.         
  167.         b = writeBuffer;
  168.       }
  169.     }
  170.     break;
  171.   }
  172.   
  173.   png_write_end(png_ptr, info_ptr);
  174.  
  175.   png_destroy_write_struct(&png_ptr, &info_ptr);
  176.  
  177.   fclose(fp);
  178.  
  179.   return true;  
  180. }
  181.  
  182. void utilPutDword(u8 *p, u32 value)
  183. {
  184.   *p++ = value & 255;
  185.   *p++ = (value >> 8) & 255;
  186.   *p++ = (value >> 16) & 255;
  187.   *p = (value >> 24) & 255;
  188. }
  189.  
  190. void utilPutWord(u8 *p, u16 value)
  191. {
  192.   *p++ = value & 255;
  193.   *p = (value >> 8) & 255;
  194. }
  195.  
  196. void utilWriteBMP(char *buf, int w, int h, u8 *pix)
  197. {
  198.   u8 *b = (u8 *)buf;
  199.  
  200.   int sizeX = w;
  201.   int sizeY = h;
  202.  
  203.   switch(systemColorDepth) {
  204.   case 16:
  205.     {
  206.       u16 *p = (u16 *)(pix+(w+2)*(h)*2); // skip first black line
  207.       for(int y = 0; y < sizeY; y++) {
  208.         for(int x = 0; x < sizeX; x++) {
  209.           u16 v = *p++;
  210.  
  211.           *b++ = ((v >> systemBlueShift) & 0x01f) << 3; // B      
  212.           *b++ = ((v >> systemGreenShift) & 0x001f) << 3; // G 
  213.           *b++ = ((v >> systemRedShift) & 0x001f) << 3; // R
  214.         }
  215.         p++; // skip black pixel for filters
  216.         p++; // skip black pixel for filters
  217.         p -= 2*(w+2);
  218.       }
  219.     }
  220.     break;
  221.   case 24:
  222.     {
  223.       u8 *pixU8 = (u8 *)pix+3*w*(h-1);
  224.       for(int y = 0; y < sizeY; y++) {
  225.         for(int x = 0; x < sizeX; x++) {
  226.           if(systemRedShift > systemBlueShift) {
  227.             *b++ = *pixU8++; // B
  228.             *b++ = *pixU8++; // G
  229.             *b++ = *pixU8++; // R           
  230.           } else {
  231.             int red = *pixU8++;
  232.             int green = *pixU8++;
  233.             int blue = *pixU8++;
  234.             
  235.             *b++ = blue;
  236.             *b++ = green;
  237.             *b++ = red;
  238.           }
  239.         }
  240.         pixU8 -= 2*3*w;
  241.       }
  242.     }
  243.     break;
  244.   case 32:
  245.     {
  246.       u32 *pixU32 = (u32 *)(pix+4*(w+1)*(h));
  247.       for(int y = 0; y < sizeY; y++) {
  248.         for(int x = 0; x < sizeX; x++) {
  249.           u32 v = *pixU32++;
  250.  
  251.           *b++ = ((v >> systemBlueShift) & 0x001f) << 3; // B     
  252.           *b++ = ((v >> systemGreenShift) & 0x001f) << 3; // G
  253.           *b++ = ((v >> systemRedShift) & 0x001f) << 3; // R
  254.         }
  255.         pixU32++;
  256.         pixU32 -= 2*(w+1);
  257.       }
  258.     }
  259.     break;
  260.   }  
  261. }
  262.  
  263. bool utilWriteBMPFile(const char *fileName, int w, int h, u8 *pix)
  264. {
  265.   u8 writeBuffer[512 * 3];
  266.   
  267.   FILE *fp = fopen(fileName,"wb");
  268.  
  269.   if(!fp) {
  270.     systemMessage(MSG_ERROR_CREATING_FILE, N_("Error creating file %s"), fileName);
  271.     return false;
  272.   }
  273.  
  274.   struct {
  275.     u8 ident[2];
  276.     u8 filesize[4];
  277.     u8 reserved[4];
  278.     u8 dataoffset[4];
  279.     u8 headersize[4];
  280.     u8 width[4];
  281.     u8 height[4];
  282.     u8 planes[2];
  283.     u8 bitsperpixel[2];
  284.     u8 compression[4];
  285.     u8 datasize[4];
  286.     u8 hres[4];
  287.     u8 vres[4];
  288.     u8 colors[4];
  289.     u8 importantcolors[4];
  290.     //    u8 pad[2];
  291.   } bmpheader;
  292.   memset(&bmpheader, 0, sizeof(bmpheader));
  293.  
  294.   bmpheader.ident[0] = 'B';
  295.   bmpheader.ident[1] = 'M';
  296.  
  297.   u32 fsz = sizeof(bmpheader) + w*h*3;
  298.   utilPutDword(bmpheader.filesize, fsz);
  299.   utilPutDword(bmpheader.dataoffset, 0x36);
  300.   utilPutDword(bmpheader.headersize, 0x28);
  301.   utilPutDword(bmpheader.width, w);
  302.   utilPutDword(bmpheader.height, h);
  303.   utilPutDword(bmpheader.planes, 1);
  304.   utilPutDword(bmpheader.bitsperpixel, 24);
  305.   utilPutDword(bmpheader.datasize, 3*w*h);
  306.  
  307.   fwrite(&bmpheader, 1, sizeof(bmpheader), fp);
  308.  
  309.   u8 *b = writeBuffer;
  310.  
  311.   int sizeX = w;
  312.   int sizeY = h;
  313.  
  314.   switch(systemColorDepth) {
  315.   case 16:
  316.     {
  317.       u16 *p = (u16 *)(pix+(w+2)*(h)*2); // skip first black line
  318.       for(int y = 0; y < sizeY; y++) {
  319.         for(int x = 0; x < sizeX; x++) {
  320.           u16 v = *p++;
  321.  
  322.           *b++ = ((v >> systemBlueShift) & 0x01f) << 3; // B      
  323.           *b++ = ((v >> systemGreenShift) & 0x001f) << 3; // G 
  324.           *b++ = ((v >> systemRedShift) & 0x001f) << 3; // R
  325.         }
  326.         p++; // skip black pixel for filters
  327.         p++; // skip black pixel for filters
  328.         p -= 2*(w+2);
  329.         fwrite(writeBuffer, 1, 3*w, fp);
  330.         
  331.         b = writeBuffer;
  332.       }
  333.     }
  334.     break;
  335.   case 24:
  336.     {
  337.       u8 *pixU8 = (u8 *)pix+3*w*(h-1);
  338.       for(int y = 0; y < sizeY; y++) {
  339.         for(int x = 0; x < sizeX; x++) {
  340.           if(systemRedShift > systemBlueShift) {
  341.             *b++ = *pixU8++; // B
  342.             *b++ = *pixU8++; // G
  343.             *b++ = *pixU8++; // R           
  344.           } else {
  345.             int red = *pixU8++;
  346.             int green = *pixU8++;
  347.             int blue = *pixU8++;
  348.             
  349.             *b++ = blue;
  350.             *b++ = green;
  351.             *b++ = red;
  352.           }
  353.         }
  354.         pixU8 -= 2*3*w;
  355.         fwrite(writeBuffer, 1, 3*w, fp);
  356.         
  357.         b = writeBuffer;
  358.       }
  359.     }
  360.     break;
  361.   case 32:
  362.     {
  363.       u32 *pixU32 = (u32 *)(pix+4*(w+1)*(h));
  364.       for(int y = 0; y < sizeY; y++) {
  365.         for(int x = 0; x < sizeX; x++) {
  366.           u32 v = *pixU32++;
  367.  
  368.           *b++ = ((v >> systemBlueShift) & 0x001f) << 3; // B     
  369.           *b++ = ((v >> systemGreenShift) & 0x001f) << 3; // G
  370.           *b++ = ((v >> systemRedShift) & 0x001f) << 3; // R
  371.         }
  372.         pixU32++;
  373.         pixU32 -= 2*(w+1);
  374.         
  375.         fwrite(writeBuffer, 1, 3*w, fp);
  376.         
  377.         b = writeBuffer;
  378.       }
  379.     }
  380.     break;
  381.   }
  382.  
  383.   fclose(fp);
  384.  
  385.   return true;
  386. }
  387.  
  388. static int utilReadInt2(FILE *f)
  389. {
  390.   int res = 0;
  391.   int c = fgetc(f);
  392.   if(c == EOF)
  393.     return -1;
  394.   res = c;
  395.   c = fgetc(f);
  396.   if(c == EOF)
  397.     return -1;
  398.   return c + (res<<8);
  399. }
  400.  
  401. static int utilReadInt3(FILE *f)
  402. {
  403.   int res = 0;
  404.   int c = fgetc(f);
  405.   if(c == EOF)
  406.     return -1;
  407.   res = c;
  408.   c = fgetc(f);
  409.   if(c == EOF)
  410.     return -1;
  411.   res = c + (res<<8);
  412.   c = fgetc(f);
  413.   if(c == EOF)
  414.     return -1;
  415.   return c + (res<<8);
  416. }
  417.  
  418. void utilApplyIPS(const char *ips, u8 **r, int *s)
  419. {
  420.   // from the IPS spec at http://zerosoft.zophar.net/ips.htm
  421.   FILE *f = fopen(ips, "rb");
  422.   if(!f)
  423.     return;
  424.   u8 *rom = *r;
  425.   int size = *s;
  426.   if(fgetc(f) == 'P' &&
  427.      fgetc(f) == 'A' &&
  428.      fgetc(f) == 'T' &&
  429.      fgetc(f) == 'C' &&
  430.      fgetc(f) == 'H') {
  431.     int b;
  432.     int offset;
  433.     int len;
  434.     for(;;) {
  435.       // read offset
  436.       offset = utilReadInt3(f);
  437.       // if offset == EOF, end of patch
  438.       if(offset == 0x454f46)
  439.         break;
  440.       // read length
  441.       len = utilReadInt2(f);
  442.       if(!len) {
  443.         // len == 0, RLE block
  444.         len = utilReadInt2(f);
  445.         // byte to fill
  446.         int c = fgetc(f);
  447.         if(c == -1)
  448.           break;
  449.         b = (u8)c;
  450.       } else
  451.         b= -1;
  452.       // check if we need to reallocate our ROM
  453.       if((offset + len) >= size) {
  454.         size *= 2;
  455.         rom = (u8 *)realloc(rom, size);
  456.         *r = rom;
  457.         *s = size;
  458.       }      
  459.       if(b == -1) {
  460.         // normal block, just read the data
  461.         if(fread(&rom[offset], 1, len, f) != (size_t)len)
  462.           break;
  463.       } else {
  464.         // fill the region with the given byte
  465.         while(len--) {
  466.           rom[offset++] = b;
  467.         }
  468.       }
  469.     }
  470.   }
  471.   // close the file
  472.   fclose(f);
  473. }
  474.  
  475. extern bool cpuIsMultiBoot;
  476.  
  477. bool utilIsGBAImage(const char * file)
  478. {
  479.   cpuIsMultiBoot = false;
  480.   if(strlen(file) > 4) {
  481.     char * p = strrchr(file,'.');
  482.  
  483.     if(p != NULL) {
  484.       if(_stricmp(p, ".gba") == 0)
  485.         return true;
  486.       if(_stricmp(p, ".agb") == 0)
  487.         return true;
  488.       if(_stricmp(p, ".bin") == 0)
  489.         return true;
  490.       if(_stricmp(p, ".elf") == 0)
  491.         return true;
  492.       if(_stricmp(p, ".mb") == 0) {
  493.         cpuIsMultiBoot = true;
  494.         return true;
  495.       }
  496.     }
  497.   }
  498.  
  499.   return false;
  500. }
  501.  
  502. bool utilIsGBImage(const char * file)
  503. {
  504.   if(strlen(file) > 4) {
  505.     char * p = strrchr(file,'.');
  506.  
  507.     if(p != NULL) {
  508.       if(_stricmp(p, ".gb") == 0)
  509.         return true;
  510.       if(_stricmp(p, ".gbc") == 0)
  511.         return true;
  512.       if(_stricmp(p, ".cgb") == 0)
  513.         return true;
  514.       if(_stricmp(p, ".sgb") == 0)
  515.         return true;      
  516.     }
  517.   }
  518.  
  519.   return false;
  520. }
  521.  
  522. bool utilIsZipFile(const char *file)
  523. {
  524.   if(strlen(file) > 4) {
  525.     char * p = strrchr(file,'.');
  526.  
  527.     if(p != NULL) {
  528.       if(_stricmp(p, ".zip") == 0)
  529.         return true;
  530.     }
  531.   }
  532.  
  533.   return false;  
  534. }
  535.  
  536. #if 0
  537. bool utilIsRarFile(const char *file)
  538. {
  539.   if(strlen(file) > 4) {
  540.     char * p = strrchr(file,'.');
  541.  
  542.     if(p != NULL) {
  543.       if(_stricmp(p, ".rar") == 0)
  544.         return true;
  545.     }
  546.   }
  547.  
  548.   return false;  
  549. }
  550. #endif
  551.  
  552. bool utilIsGzipFile(const char *file)
  553. {
  554.   if(strlen(file) > 3) {
  555.     char * p = strrchr(file,'.');
  556.  
  557.     if(p != NULL) {
  558.       if(_stricmp(p, ".gz") == 0)
  559.         return true;
  560.       if(_stricmp(p, ".z") == 0)
  561.         return true;
  562.     }
  563.   }
  564.  
  565.   return false;  
  566. }
  567.  
  568. void utilGetBaseName(const char *file, char *buffer)
  569. {
  570.   strcpy(buffer, file);
  571.  
  572.   if(utilIsGzipFile(file)) {
  573.     char *p = strrchr(buffer, '.');
  574.  
  575.     if(p)
  576.       *p = 0;
  577.   }
  578. }
  579.  
  580. IMAGE_TYPE utilFindType(const char *file)
  581. {
  582.   char buffer[2048];
  583.   
  584.   if(utilIsZipFile(file)) {
  585.     unzFile unz = unzOpen(file);
  586.     
  587.     if(unz == NULL) {
  588.       systemMessage(MSG_CANNOT_OPEN_FILE, N_("Cannot open file %s"), file);
  589.       return IMAGE_UNKNOWN;
  590.     }
  591.     
  592.     int r = unzGoToFirstFile(unz);
  593.     
  594.     if(r != UNZ_OK) {
  595.       unzClose(unz);
  596.       systemMessage(MSG_BAD_ZIP_FILE, N_("Bad ZIP file %s"), file);
  597.       return IMAGE_UNKNOWN;
  598.     }
  599.     
  600.     IMAGE_TYPE found = IMAGE_UNKNOWN;
  601.     
  602.     unz_file_info info;
  603.     
  604.     while(true) {
  605.       r = unzGetCurrentFileInfo(unz,
  606.                                 &info,
  607.                                 buffer,
  608.                                 sizeof(buffer),
  609.                                 NULL,
  610.                                 0,
  611.                                 NULL,
  612.                                 0);
  613.       
  614.       if(r != UNZ_OK) {
  615.         unzClose(unz);
  616.         systemMessage(MSG_BAD_ZIP_FILE, N_("Bad ZIP file %s"), file);
  617.         return IMAGE_UNKNOWN;
  618.       }
  619.       
  620.       if(utilIsGBAImage(buffer)) {
  621.         found = IMAGE_GBA;
  622.         break;
  623.       }
  624.  
  625.       if(utilIsGBImage(buffer)) {
  626.         found = IMAGE_GB;
  627.         break;
  628.       }
  629.         
  630.       r = unzGoToNextFile(unz);
  631.       
  632.       if(r != UNZ_OK)
  633.         break;
  634.     }
  635.     unzClose(unz);
  636.     
  637.     if(found == IMAGE_UNKNOWN) {
  638.       systemMessage(MSG_NO_IMAGE_ON_ZIP,
  639.                     N_("No image found on ZIP file %s"), file);
  640.       return found;
  641.     }
  642.     return found;
  643. #if 0
  644.   } else if(utilIsRarFile(file)) {
  645.     IMAGE_TYPE found = IMAGE_UNKNOWN;
  646.     
  647.     ArchiveList_struct *rarList = NULL;
  648.     if(urarlib_list((void *)file, (ArchiveList_struct *)&rarList)) {
  649.       ArchiveList_struct *p = rarList;
  650.  
  651.       while(p) {
  652.         if(utilIsGBAImage(p->item.Name)) {
  653.           found = IMAGE_GBA;
  654.           break;
  655.         }
  656.  
  657.         if(utilIsGBImage(p->item.Name)) {
  658.           found = IMAGE_GB;
  659.           break;
  660.         }
  661.         p = p->next;
  662.       }
  663.       
  664.       urarlib_freelist(rarList);
  665.     }
  666.     return found;
  667. #endif
  668.   } else {
  669.     if(utilIsGzipFile(file))
  670.       utilGetBaseName(file, buffer);
  671.     else
  672.       strcpy(buffer, file);
  673.     
  674.     if(utilIsGBAImage(buffer))
  675.       return IMAGE_GBA;
  676.     if(utilIsGBImage(buffer))
  677.       return IMAGE_GB;
  678.   }
  679.   return IMAGE_UNKNOWN;  
  680. }
  681.  
  682. static int utilGetSize(int size)
  683. {
  684.   int res = 1;
  685.   while(res < size)
  686.     res <<= 1;
  687.   return res;
  688. }
  689.  
  690. static u8 *utilLoadFromZip(const char *file,
  691.                            bool (*accept)(const char *),
  692.                            u8 *data,
  693.                            int &size)
  694. {
  695.   char buffer[2048];
  696.   
  697.   unzFile unz = unzOpen(file);
  698.     
  699.   if(unz == NULL) {
  700.     systemMessage(MSG_CANNOT_OPEN_FILE, N_("Cannot open file %s"), file);
  701.     return NULL;
  702.   }
  703.   int r = unzGoToFirstFile(unz);
  704.     
  705.   if(r != UNZ_OK) {
  706.     unzClose(unz);
  707.     systemMessage(MSG_BAD_ZIP_FILE, N_("Bad ZIP file %s"), file);
  708.     return NULL;
  709.   }
  710.     
  711.   bool found = false;
  712.     
  713.   unz_file_info info;
  714.   
  715.   while(true) {
  716.     r = unzGetCurrentFileInfo(unz,
  717.                               &info,
  718.                               buffer,
  719.                               sizeof(buffer),
  720.                               NULL,
  721.                               0,
  722.                               NULL,
  723.                               0);
  724.       
  725.     if(r != UNZ_OK) {
  726.       unzClose(unz);
  727.       systemMessage(MSG_BAD_ZIP_FILE, N_("Bad ZIP file %s"), file);
  728.       return NULL;
  729.     }
  730.  
  731.     if(accept(buffer)) {
  732.       found = true;
  733.       break;
  734.     }
  735.     
  736.     r = unzGoToNextFile(unz);
  737.       
  738.     if(r != UNZ_OK)
  739.       break;
  740.   }
  741.  
  742.   if(!found) {
  743.     unzClose(unz);
  744.     systemMessage(MSG_NO_IMAGE_ON_ZIP,
  745.                   N_("No image found on ZIP file %s"), file);
  746.     return NULL;
  747.   }
  748.   
  749.   int fileSize = info.uncompressed_size;
  750.   if(size == 0)
  751.     size = fileSize;
  752.   r = unzOpenCurrentFile(unz);
  753.  
  754.   if(r != UNZ_OK) {
  755.     unzClose(unz);
  756.     systemMessage(MSG_ERROR_OPENING_IMAGE, N_("Error opening image %s"), buffer);
  757.     return NULL;
  758.   }
  759.  
  760.   u8 *image = data;
  761.   
  762.   if(image == NULL) {
  763.     image = (u8 *)malloc(utilGetSize(size));
  764.     if(image == NULL) {
  765.       unzCloseCurrentFile(unz);
  766.       unzClose(unz);
  767.       systemMessage(MSG_OUT_OF_MEMORY, N_("Failed to allocate memory for %s"),
  768.                     "data");
  769.       return NULL;
  770.     }
  771.     size = fileSize;
  772.   }
  773.   int read = fileSize <= size ? fileSize : size;
  774.   r = unzReadCurrentFile(unz,
  775.                          image,
  776.                          read);
  777.  
  778.   unzCloseCurrentFile(unz);
  779.   unzClose(unz);
  780.   
  781.   if(r != (int)read) {
  782.     systemMessage(MSG_ERROR_READING_IMAGE,
  783.                   N_("Error reading image %s"), buffer);
  784.     if(data == NULL)
  785.       free(image);
  786.     return NULL;
  787.   }
  788.  
  789.   size = fileSize;
  790.  
  791.   return image;
  792. }
  793.  
  794. static u8 *utilLoadGzipFile(const char *file,
  795.                             bool (*accept)(const char *),
  796.                             u8 *data,
  797.                             int &size)
  798. {
  799.   FILE *f = fopen(file, "rb");
  800.  
  801.   if(f == NULL) {
  802.     systemMessage(MSG_ERROR_OPENING_IMAGE, N_("Error opening image %s"), file);
  803.     return NULL;
  804.   }
  805.  
  806.   fseek(f, -4, SEEK_END);
  807.   int fileSize = fgetc(f) | (fgetc(f) << 8) | (fgetc(f) << 16) | (fgetc(f) << 24);
  808.   fclose(f);
  809.   if(size == 0)
  810.     size = fileSize;
  811.  
  812.   gzFile gz = gzopen(file, "rb");
  813.  
  814.   if(gz == NULL) {
  815.     // should not happen, but who knows?
  816.     systemMessage(MSG_ERROR_OPENING_IMAGE, N_("Error opening image %s"), file);
  817.     return NULL;
  818.   }
  819.  
  820.   u8 *image = data;
  821.  
  822.   if(image == NULL) {
  823.     image = (u8 *)malloc(utilGetSize(size));
  824.     if(image == NULL) {
  825.       systemMessage(MSG_OUT_OF_MEMORY, N_("Failed to allocate memory for %s"),
  826.                     "data");
  827.       fclose(f);
  828.       return NULL;
  829.     }
  830.     size = fileSize;
  831.   }
  832.   int read = fileSize <= size ? fileSize : size;
  833.   int r = gzread(gz, image, read);
  834.   gzclose(gz);
  835.  
  836.   if(r != (int)read) {
  837.     systemMessage(MSG_ERROR_READING_IMAGE,
  838.                   N_("Error reading image %s"), file);
  839.     if(data == NULL)
  840.       free(image);
  841.     return NULL;
  842.   }  
  843.   
  844.   size = fileSize;
  845.  
  846.   return image;  
  847. }
  848.  
  849. #if 0
  850. static u8 *utilLoadRarFile(const char *file,
  851.                            bool (*accept)(const char *),
  852.                            u8 *data,
  853.                            int &size)
  854. {
  855.   char buffer[2048];
  856.  
  857.   ArchiveList_struct *rarList = NULL;
  858.   if(urarlib_list((void *)file, (ArchiveList_struct *)&rarList)) {
  859.     ArchiveList_struct *p = rarList;
  860.     
  861.     bool found = false;
  862.     while(p) {
  863.       if(accept(p->item.Name)) {
  864.         strcpy(buffer, p->item.Name);
  865.         found = true;
  866.         break;
  867.       }
  868.       p = p->next;
  869.     }
  870.     if(found) {
  871.       void *memory = NULL;
  872.       unsigned long lsize = 0;
  873.       size = p->item.UnpSize;
  874.       int r = urarlib_get((void *)&memory, &lsize, buffer, (void *)file, "");
  875.       if(!r) {
  876.         systemMessage(MSG_ERROR_READING_IMAGE,
  877.                       N_("Error reading image %s"), buffer);
  878.         urarlib_freelist(rarList);
  879.         return NULL;
  880.       }
  881.       u8 *image = (u8 *)memory;
  882.       if(data != NULL) {
  883.         memcpy(image, data, size);
  884.       }
  885.       urarlib_freelist(rarList);
  886.       return image;
  887.     }
  888.     systemMessage(MSG_NO_IMAGE_ON_ZIP,
  889.                   N_("No image found on RAR file %s"), file);
  890.     urarlib_freelist(rarList);
  891.     return NULL;
  892.   }
  893.   // nothing found
  894.   return NULL;
  895. }
  896. #endif
  897.  
  898. u8 *utilLoad(const char *file,
  899.              bool (*accept)(const char *),
  900.              u8 *data,
  901.              int &size)
  902. {
  903.   if(utilIsZipFile(file)) {
  904.     return utilLoadFromZip(file, accept, data, size);
  905.   }
  906.   if(utilIsGzipFile(file)) {
  907.     return utilLoadGzipFile(file, accept, data, size);
  908.   }
  909. #if 0
  910.   if(utilIsRarFile(file)) {
  911.     return utilLoadRarFile(file, accept, data, size);
  912.   }
  913. #endif
  914.   
  915.   u8 *image = data;
  916.  
  917.   FILE *f = fopen(file, "rb");
  918.  
  919.   if(!f) {
  920.     systemMessage(MSG_ERROR_OPENING_IMAGE, N_("Error opening image %s"), file);
  921.     return NULL;
  922.   }
  923.  
  924.   fseek(f,0,SEEK_END);
  925.   int fileSize = ftell(f);
  926.   fseek(f,0,SEEK_SET);
  927.   if(size == 0)
  928.     size = fileSize;
  929.  
  930.   if(image == NULL) {
  931.     image = (u8 *)malloc(utilGetSize(size));
  932.     if(image == NULL) {
  933.       systemMessage(MSG_OUT_OF_MEMORY, N_("Failed to allocate memory for %s"),
  934.                     "data");
  935.       fclose(f);
  936.       return NULL;
  937.     }
  938.     size = fileSize;
  939.   }
  940.   int read = fileSize <= size ? fileSize : size;
  941.   int r = fread(image, 1, read, f);
  942.   fclose(f);
  943.  
  944.   if(r != (int)read) {
  945.     systemMessage(MSG_ERROR_READING_IMAGE,
  946.                   N_("Error reading image %s"), file);
  947.     if(data == NULL)
  948.       free(image);
  949.     return NULL;
  950.   }  
  951.  
  952.   size = fileSize;
  953.   
  954.   return image;
  955. }
  956.  
  957. void utilWriteInt(gzFile gzFile, int i)
  958. {
  959.   utilGzWrite(gzFile, &i, sizeof(int));
  960. }
  961.  
  962. int utilReadInt(gzFile gzFile)
  963. {
  964.   int i = 0;
  965.   utilGzRead(gzFile, &i, sizeof(int));
  966.   return i;
  967. }
  968.  
  969. void utilReadData(gzFile gzFile, variable_desc* data)
  970. {
  971.   while(data->address) {
  972.     utilGzRead(gzFile, data->address, data->size);
  973.     data++;
  974.   }
  975. }
  976.  
  977. void utilWriteData(gzFile gzFile, variable_desc *data)
  978. {
  979.   while(data->address) {
  980.     utilGzWrite(gzFile, data->address, data->size);
  981.     data++;
  982.   }
  983. }
  984.  
  985. gzFile utilGzOpen(const char *file, const char *mode)
  986. {
  987.   utilGzWriteFunc = (int (*)(void *,void * const, unsigned int))gzwrite;
  988.   utilGzReadFunc = gzread;
  989.   utilGzCloseFunc = gzclose;
  990.  
  991.   return gzopen(file, mode);
  992. }
  993.  
  994. gzFile utilMemGzOpen(char *memory, int available, char *mode)
  995. {
  996.   utilGzWriteFunc = memgzwrite;
  997.   utilGzReadFunc = memgzread;
  998.   utilGzCloseFunc = memgzclose;
  999.  
  1000.   return memgzopen(memory, available, mode);  
  1001. }
  1002.  
  1003. int utilGzWrite(gzFile file, const voidp buffer, unsigned int len)
  1004. {
  1005.   return utilGzWriteFunc(file, buffer, len);
  1006. }
  1007.  
  1008. int utilGzRead(gzFile file, voidp buffer, unsigned int len)
  1009. {
  1010.   return utilGzReadFunc(file, buffer, len);
  1011. }
  1012.  
  1013. int utilGzClose(gzFile file)
  1014. {
  1015.   return utilGzCloseFunc(file);
  1016. }
  1017.  
  1018. long utilGzMemTell(gzFile file)
  1019. {
  1020.   return memtell(file);
  1021. }
  1022.  
  1023. void utilGBAFindSave(const u8 *data, const int size)
  1024. {
  1025.   u32 *p = (u32 *)data;
  1026.   u32 *end = (u32 *)(data + size);
  1027.   int saveType = 0;
  1028.   int flashSize = 0x10000;
  1029.   bool rtcFound = false;
  1030.  
  1031.   while(p  < end) {
  1032.     u32 d = READ32LE(p);
  1033.     
  1034.     if(d == 0x52504545) {
  1035.       if(memcmp(p, "EEPROM_", 7) == 0) {
  1036.         if(saveType == 0)
  1037.           saveType = 1;
  1038.       }
  1039.     } else if (d == 0x4D415253) {
  1040.       if(memcmp(p, "SRAM_", 5) == 0) {
  1041.         if(saveType == 0)
  1042.           saveType = 2;
  1043.       }
  1044.     } else if (d == 0x53414C46) {
  1045.       if(memcmp(p, "FLASH1M_", 8) == 0) {
  1046.         if(saveType == 0) {
  1047.           saveType = 3;
  1048.           flashSize = 0x20000;
  1049.         }
  1050.       } else if(memcmp(p, "FLASH", 5) == 0) {
  1051.         if(saveType == 0) {
  1052.           saveType = 3;
  1053.           flashSize = 0x10000;
  1054.         }
  1055.       }
  1056.     } else if (d == 0x52494953) {
  1057.       if(memcmp(p, "SIIRTC_V", 8) == 0)
  1058.         rtcFound = true;
  1059.     }
  1060.     p++;
  1061.   } 
  1062.   // if no matches found, then set it to NONE
  1063.   if(saveType == 0) {
  1064.     saveType = 5;
  1065.   }
  1066.   rtcEnable(rtcFound);
  1067.   cpuSaveType = saveType;
  1068.   flashSetSize(flashSize);
  1069. }
  1070.