1 /* FCE Ultra - NES/Famicom Emulator
3 * Copyright notice for this file:
4 * Copyright (C) 2002 Ben Parnell
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 #include "zlib/unzip.h"
37 static void *desctable[8]={0,0,0,0,0,0,0,0};
52 #define MEMWRAP ZIPWRAP
54 void ApplyIPS(FILE *ips, int destf)
60 FCEU_printf(" Applying IPS...\n");
63 FCEU_printf("failed (bad destf).\n");
67 dest=(MEMWRAP*)desctable[(destf&255)-1];
69 if(fread(header,1,5,ips)!=5)
71 FCEU_printf("failed (bad header).\n");
75 if(memcmp(header,"PATCH",5))
77 FCEU_printf("failed (bad header).\n");
82 while(fread(header,1,3,ips)==3)
84 uint32 offset=(header[0]<<16)|(header[1]<<8)|header[2];
87 if(!memcmp(header,"EOF",3))
89 FCEU_printf(" IPS EOF: Did %d patches\n\n",count);
103 //FCEU_printf(" Offset: %8d Size: %5d RLE\n",offset,size);
105 if((offset+size)>dest->size)
109 // Probably a little slow.
110 tmp=(uint8 *)realloc(dest->data,offset+size);
113 FCEU_printf(" Oops. IPS patch %d(type RLE) goes beyond end of file. Could not allocate memory.\n",count);
117 dest->size=offset+size;
119 memset(dest->data+dest->size,0,offset+size-dest->size);
122 start=dest->data+offset;
129 else /* Normal patch */
131 //FCEU_printf(" Offset: %8d Size: %5d\n",offset,size);
132 if((offset+size)>dest->size)
136 // Probably a little slow.
137 tmp=(uint8 *)realloc(dest->data,offset+size);
140 FCEU_printf(" Oops. IPS patch %d(type normal) goes beyond end of file. Could not allocate memory.\n",count);
145 memset(dest->data+dest->size,0,offset+size-dest->size);
147 fread(dest->data+offset,1,size,ips);
152 FCEU_printf(" Hard IPS end!\n");
159 void *MakeZipWrap(void *tz)
164 if(!(tmp=FCEU_malloc(sizeof(ZIPWRAP))))
167 unzGetCurrentFileInfo(tz,&ufo,0,0,0,0,0,0);
170 tmp->size=ufo.uncompressed_size;
171 if(!(tmp->data=FCEU_malloc(ufo.uncompressed_size)))
177 unzReadCurrentFile(tz,tmp->data,ufo.uncompressed_size);
181 unzCloseCurrentFile(tz);
189 #define strcasecmp strcmp
192 int FASTAPASS(2) FCEU_fopen(char *path, char *mode)
198 if((tz=unzOpen(path))) // If it's not a zip file, use regular file handlers.
199 // Assuming file type by extension usually works,
200 // but I don't like it. :)
202 if(unzGoToFirstFile(tz)==UNZ_OK)
206 char tempu[512]; // Longer filenames might be possible, but I don't
207 // think people would name files that long in zip files...
208 unzGetCurrentFileInfo(tz,0,tempu,512,0,0,0,0);
212 char *za=tempu+strlen(tempu)-4;
213 if(!strcasecmp(za,".nes") || !strcasecmp(za,".fds") ||
214 !strcasecmp(za,".nsf") || !strcasecmp(za,".unf") ||
215 !strcasecmp(za,".nez"))
220 if(!strcasecmp(tempu+strlen(tempu)-5,".unif"))
223 if(unzGoToNextFile(tz)!=UNZ_OK)
225 if(unzGoToFirstFile(tz)!=UNZ_OK) goto zpfail;
229 if(unzOpenCurrentFile(tz)!=UNZ_OK)
242 if(!(desctable[x]=MakeZipWrap(tz)))
244 return((x+1)|0x8000);
250 if((t=fopen(path,"rb")))
262 if((t=gzopen(path,mode)))
267 return((x+1)|0x4000);
273 if((t=fopen(path,mode)))
286 int FASTAPASS(1) FCEU_fopen_forcemem(char *path)
292 fp=FCEU_fopen(path, "rb");
295 if (fp&0x8000) return fp;
297 if (!(tmp=FCEU_malloc(sizeof(*tmp))))
300 size=FCEU_fgetsize(fp);
301 if (size <= 0) goto retr;
303 tmp->data=FCEU_malloc(size);
304 if (!tmp->data) goto retr;
305 FCEU_fread(tmp->data, 1, size, fp);
306 FCEU_fclose(fp); fp=0;
317 if (fp) FCEU_fclose(fp);
318 if (tmp && tmp->data) FCEU_free(tmp->data);
319 if (tmp) FCEU_free(tmp);
323 int FASTAPASS(1) FCEU_fclose(int stream)
328 gzclose(desctable[(stream&255)-1]);
329 desctable[(stream&255)-1]=0;
331 else if(stream&0x8000)
333 free(((ZIPWRAP*)desctable[(stream&255)-1])->data);
334 free(desctable[(stream&255)-1]);
335 desctable[(stream&255)-1]=0;
337 else // close zip file
340 fclose(desctable[stream-1]);
341 desctable[stream-1]=0;
348 size_t FASTAPASS(3) FCEU_fread(void *ptr, size_t size, size_t nmemb, int stream)
353 return gzread(desctable[(stream&255)-1],ptr,size*nmemb);
355 else if(stream&0x8000)
358 uint32 total=size*nmemb;
360 wz=(ZIPWRAP*)desctable[(stream&255)-1];
361 if(wz->location>=wz->size) return 0;
363 if((wz->location+total)>wz->size)
365 int ak=wz->size-wz->location;
366 memcpy((uint8*)ptr,wz->data+wz->location,ak);
367 wz->location=wz->size;
372 memcpy((uint8*)ptr,wz->data+wz->location,total);
380 return fread(ptr,size,nmemb,desctable[stream-1]);
386 size_t FASTAPASS(3) FCEU_fwrite(void *ptr, size_t size, size_t nmemb, int stream)
391 return gzwrite(desctable[(stream&255)-1],ptr,size*nmemb);
393 else if(stream&0x8000)
399 return fwrite(ptr,size,nmemb,desctable[stream-1]);
402 int FASTAPASS(3) FCEU_fseek(int stream, long offset, int whence)
407 return gzseek(desctable[(stream&255)-1],offset,whence);
409 else if(stream&0x8000)
412 wz=(ZIPWRAP*)desctable[(stream&255)-1];
416 case SEEK_SET:if(offset>=wz->size)
418 wz->location=offset;break;
419 case SEEK_CUR:if(offset+wz->location>wz->size)
421 wz->location+=offset;
428 return fseek(desctable[stream-1],offset,whence);
431 long FASTAPASS(1) FCEU_ftell(int stream)
436 return gztell(desctable[(stream&255)-1]);
438 else if(stream&0x8000)
440 return (((ZIPWRAP *)desctable[(stream&255)-1])->location);
444 return ftell(desctable[stream-1]);
447 void FASTAPASS(1)FCEU_rewind(int stream)
452 gzrewind(desctable[(stream&255)-1]);
454 else if(stream&0x8000)
456 ((ZIPWRAP *)desctable[(stream&255)-1])->location=0;
461 fseek(desctable[stream-1],0,SEEK_SET);
463 rewind(desctable[stream-1]);
467 int FASTAPASS(2) FCEU_read32(void *Bufo, int stream)
479 wz=(ZIPWRAP*)desctable[(stream&255)-1];
480 if(wz->location+4>wz->size)
482 memcpy(&t, wz->data+wz->location, 4);
485 else if(stream&0x4000)
486 gzread(desctable[(stream&255)-1],&t,4);
492 *(uint32*)Bufo=*(uint32*)x;
501 return read32(Bufo,desctable[stream-1]);
505 int FASTAPASS(1) FCEU_fgetc(int stream)
509 return gzgetc(desctable[(stream&255)-1]);
510 else if(stream&0x8000)
513 wz=(ZIPWRAP*)desctable[(stream&255)-1];
514 if(wz->location<wz->size)
515 return wz->data[wz->location++];
520 return fgetc(desctable[stream-1]);
523 long FASTAPASS(1) FCEU_fgetsize(int stream)
529 t=gztell(desctable[(stream&255)-1]);
530 gzrewind(desctable[(stream&255)-1]);
531 for(x=0;gzgetc(desctable[(stream&255)-1]) != EOF; x++);
532 gzseek(desctable[(stream&255)-1],t,SEEK_SET);
535 else if(stream&0x8000)
536 return ((ZIPWRAP*)desctable[(stream&255)-1])->size;
541 t=ftell(desctable[stream-1]);
542 fseek(desctable[stream-1],0,SEEK_END);
543 r=ftell(desctable[stream-1]);
544 fseek(desctable[stream-1],t,SEEK_SET);
549 int FASTAPASS(1) FCEU_fisarchive(int stream)