static upse_psf_t *_upse_load(char *path, int level, int type, upse_iofuncs_t *_upse_iofuncs) // Type==1 for just info load. { void *fp; upse_exe_header_t tmpHead; tmpHead.t_addr = 0; tmpHead.t_size = 0; unsigned char *in, *out = 0; u8 head[4]; u32 reserved; u32 complen; u32 crc32; uLongf outlen; upse_psf_t *psfi; upse_psf_t *tmpi; _ENTER; if (!(fp = _upse_iofuncs->open_impl(path, "rb"))) { _ERROR("path %s failed to load\n", path); return NULL; } _upse_iofuncs->read_impl(head, 1, 4, fp); if (memcmp(head, "PSF\x01", 4)) return NULL; psfi = calloc(sizeof(upse_psf_t), 1); psfi->stop = ~0; psfi->fade = 0; _upse_iofuncs->read_impl(&reserved, 1, 4, fp); _upse_iofuncs->read_impl(&complen, 1, 4, fp); complen = BFLIP32(complen); _upse_iofuncs->read_impl(&crc32, 1, 4, fp); crc32 = BFLIP32(crc32); _upse_iofuncs->seek_impl(fp, reserved, SEEK_CUR); if (type) _upse_iofuncs->seek_impl(fp, complen, SEEK_CUR); else { in = malloc(complen); out = malloc(1024 * 1024 * 2 + 0x800); _upse_iofuncs->read_impl(in, 1, complen, fp); outlen = 1024 * 1024 * 2; uncompress(out, &outlen, in, complen); free(in); memcpy(&tmpHead, out, sizeof(upse_exe_header_t)); upse_r3000_cpu_regs.pc = BFLIP32(tmpHead.pc0); upse_r3000_cpu_regs.GPR.n.gp = BFLIP32(tmpHead.gp0); upse_r3000_cpu_regs.GPR.n.sp = BFLIP32(tmpHead.s_addr); if (upse_r3000_cpu_regs.GPR.n.sp == 0) upse_r3000_cpu_regs.GPR.n.sp = 0x801fff00; if (level) { LoadPSXMem(BFLIP32(tmpHead.t_addr), BFLIP32(tmpHead.t_size), out + 0x800); free(out); } } { u8 tagdata[5]; if (_upse_iofuncs->read_impl(tagdata, 1, 5, fp) == 5) { if (!memcmp(tagdata, "[TAG]", 5)) { char linebuf[1024]; while (upse_io_fgets(linebuf, 1024, fp, _upse_iofuncs)) { int x; char *key = NULL, *value = NULL; if (!_upse_psf_get_tag(linebuf, &key, &value)) { if (key) free(key); if (value) free(value); continue; } _upse_psf_add_tag(&psfi->taglist, key, value); if (!level) { static char *yoinks[8] = { "title", "artist", "game", "year", "genre", "copyright", "psfby", "comment" }; char **yoinks2[8] = { &psfi->title, &psfi->artist, &psfi->game, &psfi->year, &psfi->genre, &psfi->copyright, &psfi->psfby, &psfi->comment }; for (x = 0; x < 8; x++) if (!strcasecmp(key, yoinks[x])) *yoinks2[x] = value; if (!strcasecmp(key, "length")) psfi->stop = _upse_time_to_ms(value); else if (!strcasecmp(key, "fade")) psfi->fade = _upse_time_to_ms(value); } if (!strcasecmp(key, "_lib") && !type) { char *tmpfn; /* Load file name "value" from the directory specified in the full path(directory + file name) "path" */ tmpfn = _upse_resolve_path(path, value); if (!(tmpi = _upse_load(tmpfn, level + 1, 0, _upse_iofuncs))) { free(key); free(value); free(tmpfn); if (!level) free(out); _upse_iofuncs->close_impl(fp); _upse_psf_free_tags(psfi->taglist); free(psfi); return NULL; } _upse_psf_free_tags(tmpi->taglist); free(tmpi); free(tmpfn); } if (key) free(key); } } } } _upse_iofuncs->close_impl(fp); /* Now, if we're at level 0(main PSF), load the main executable, and any libN stuff */ if (!level && !type) { LoadPSXMem(BFLIP32(tmpHead.t_addr), BFLIP32(tmpHead.t_size), out + 0x800); free(out); } if (!type) /* Load libN */ { upse_libcache_slot_t *cache; upse_psftag_t *tag; unsigned int libncount = 0; unsigned int cur = 0; tag = psfi->taglist; while (tag) { if (!strncasecmp(tag->key, "_lib", 4) && tag->key[4]) libncount++; tag = tag->next; } if (libncount) { cache = malloc(sizeof(upse_libcache_slot_t) * libncount); tag = psfi->taglist; while (tag) { if (!strncasecmp(tag->key, "_lib", 4) && tag->key[4]) { cache[cur].num = atoi(&tag->key[4]); cache[cur].value = tag->value; cur++; } tag = tag->next; } qsort(cache, libncount, sizeof(upse_libcache_slot_t), ccomp); for (cur = 0; cur < libncount; cur++) { u32 ba[3]; char *tmpfn; if (cache[cur].num < 2) continue; ba[0] = upse_r3000_cpu_regs.pc; ba[1] = upse_r3000_cpu_regs.GPR.n.gp; ba[2] = upse_r3000_cpu_regs.GPR.n.sp; /* Load file name "value" from the directory specified in the full path(directory + file name) "path" */ tmpfn = _upse_resolve_path(path, cache[cur].value); if (!(tmpi = _upse_load(tmpfn, level + 1, 0, _upse_iofuncs))) { //free(key); //free(value); //free(tmpfn); //_upse_iofuncs->close_impl(fp); //return(0); } free(tmpfn); _upse_psf_free_tags(tmpi->taglist); free(tmpi); upse_r3000_cpu_regs.pc = ba[0]; upse_r3000_cpu_regs.GPR.n.gp = ba[1]; upse_r3000_cpu_regs.GPR.n.sp = ba[2]; } free(cache); } // if(libncount) } // if(!type) _LEAVE; return psfi; }
static PSFINFO *LoadPSF(char *path, int level, int type,const char *pathDir) // Type==1 for just info load. { FILE *fp; u8 *in,*out=0; u8 head[4]; u32 reserved; u32 complen; u32 crc32; uLongf outlen; PSFINFO *psfi=NULL; PSFINFO *tmpi=NULL; u32 offset, plength; sexypsf_missing_psflib=0; #ifdef DEBUG fprintf(stderr, "Searching (%s)\n", path); #endif fp=fopen(path,"rb"); if(!fp) return 0; fread(head,1,4,fp); if(memcmp(head,"PSF\x01",4)) return(0); psfi=malloc(sizeof(PSFINFO)); if( psfi == NULL ) return(0); memset(psfi,0,sizeof(PSFINFO)); psfi->stop=~0; psfi->fade=0; fread(&reserved,1,4,fp); fread(&complen,1,4,fp); complen=BFLIP32(complen); fread(&crc32,1,4,fp); crc32=BFLIP32(crc32); #ifdef DEBUG fprintf(stderr, "CRC32 = 0x%x\n", crc32); #endif fseek(fp,reserved,SEEK_CUR); if(type) fseek(fp,complen,SEEK_CUR); else { in=malloc(complen); if( !in ) return(0); out=malloc(1024*1024*2+0x800); if( !out ) { free(in); return(0); } fread(in,1,complen,fp); outlen=1024*1024*2; uncompress(out,&outlen,in,complen); free(in); psxRegs->pc = out[0x10] | out[0x11]<<8 | out[0x12]<<16 | out[0x13]<<24; psxRegs->GPR.n.gp = out[0x14] | out[0x15]<<8 | out[0x16]<<16 | out[0x17]<<24; psxRegs->GPR.n.sp = out[0x30] | out[0x31]<<8 | out[0x32]<<16 | out[0x33]<<24; if (psxRegs->GPR.n.sp == 0) psxRegs->GPR.n.sp = 0x801fff00; #ifdef DEBUG fprintf(stderr, "%d Level: PC %x GP %x SP %x\n", level, psxRegs->pc, psxRegs->GPR.n.gp, psxRegs->GPR.n.sp); #endif if(level) { offset = out[0x18] | out[0x19]<<8 | out[0x1a]<<16 | out[0x1b]<<24; offset &= 0x3fffffff; // kill any MIPS cache segment indicators plength = out[0x1c] | out[0x1d]<<8 | out[0x1e]<<16 | out[0x1f]<<24; #ifdef DEBUG fprintf(stderr, "%d Level: offset %x plength: %d [%d]\n", level, offset, plength, plength); #endif LoadPSXMem(offset,plength,(char*)out+0x800); free(out); // I don't really know how does this // work, but apparently it breaks the // loop that makes ff6 and ct to take // several seconds to start ... if( crc32 == 0xEFDE8EEE || crc32 == 0x545D9F65 ) psxMemWrite32(0x5A66C, 0); // Same as above for Popolocrois if( crc32 == 0xF535726 ) psxMemWrite32(0x5A990, 0); } } { u8 tagdata[5]; if(fread(tagdata,1,5,fp)==5) { if(!memcmp(tagdata,"[TAG]",5)) { char linebuf[1024]; while(fgets(linebuf,1024,fp)>0) { int x; char *key=0,*value=0; if(!GetKeyVal(linebuf,&key,&value)) { if(key) free(key); if(value) free(value); continue; } AddKV(&psfi->tags,key,value); if(!level) { static char *yoinks[8]={"title","artist","game","year","genre", "copyright","psfby","comment"}; char **yoinks2[8]={&psfi->title,&psfi->artist,&psfi->game,&psfi->year,&psfi->genre, &psfi->copyright,&psfi->psfby,&psfi->comment}; for(x=0;x<8;x++) if(!strcasecmp(key,yoinks[x])) *yoinks2[x]=value; if(!strcasecmp(key,"length")) psfi->stop=TimeToMS(value); else if(!strcasecmp(key,"fade")) psfi->fade=TimeToMS(value); } if(!strcasecmp(key,"_lib") && !type) { char *tmpfn; /* Load file name "value" from the directory specified in the full path(directory + file name) "path" */ //printf("yo %s\nya %s\nyu%s\n",path,value,pathDir); tmpfn=GetFileWithBase(path,value,pathDir); //printf("ru: %s\n",tmpfn); if(!(tmpi=LoadPSF(tmpfn,level+1,0,pathDir))) { //free(key); //free(value); sexypsf_missing_psflib=1; strcpy(sexypsf_psflib_str,value); free(tmpfn); if(!level) free(out); fclose(fp); FreeTags(psfi->tags); free(psfi); return(0); } FreeTags(tmpi->tags); free(tmpi); free(tmpfn); } } } } } fclose(fp); /* Now, if we're at level 0(main PSF), load the main executable, and any libN stuff */ if(!level && !type) { offset = out[0x18] | out[0x19]<<8 | out[0x1a]<<16 | out[0x1b]<<24; offset &= 0x3fffffff; // kill any MIPS cache segment indicators plength = out[0x1c] | out[0x1d]<<8 | out[0x1e]<<16 | out[0x1f]<<24; // TODO - investigate: should i just make // plength = outlen-0x800? // Philosoma has an illegal "plength". *sigh* if (plength > (outlen-0x800)) { plength = outlen-0x800; } if( psfi->game ) { // Suikoden Tenmei has an illegal "plength". *sigh sigh* if( !strncmp(psfi->game, "Suikoden: Tenmei no Chikai", 26) ) { plength = outlen-0x800; } // Einhänder has an illegal "plength". *sigh sigh sigh* if( !strncmp(psfi->game, "Einhänder", 9) ) { plength = outlen-0x800; } } #ifdef DEBUG fprintf(stderr, "%d Level: offset %x plength: %d [%d]\n", level, offset, plength, outlen-2048); #endif LoadPSXMem(offset,plength,(char*)out+0x800); free(out); } if(!type) /* Load libN */{ LIBNCACHE *cache; PSFTAG *tag; unsigned int libncount=0; unsigned int cur=0; tag=psfi->tags; while(tag) { if(!strncasecmp(tag->key,"_lib",4) && tag->key[4]) libncount++; tag=tag->next; } if(libncount) { cache=malloc(sizeof(LIBNCACHE)*libncount); tag=psfi->tags; while(tag) { if(!strncasecmp(tag->key,"_lib",4) && tag->key[4]) { cache[cur].num=atoi(&tag->key[4]); cache[cur].value=tag->value; cur++; } tag=tag->next; } qsort(cache, libncount, sizeof(LIBNCACHE), ccomp); for(cur=0;cur<libncount;cur++) { u32 ba[3]; char *tmpfn; if(cache[cur].num < 2) continue; ba[0]=psxRegs->pc; ba[1]=psxRegs->GPR.n.gp; ba[2]=psxRegs->GPR.n.sp; /* Load file name "value" from the directory specified in the full path(directory + file name) "path" */ tmpfn=GetFileWithBase(path,cache[cur].value,pathDir); if(!(tmpi=LoadPSF(tmpfn,level+1,0,pathDir))) { //free(key); //free(value); //free(tmpfn); //fclose(fp); //return(0); } else { FreeTags(tmpi->tags); free(tmpi); } free(tmpfn); psxRegs->pc=ba[0]; psxRegs->GPR.n.gp=ba[1]; psxRegs->GPR.n.sp=ba[2]; } free(cache); } // if(libncount) } // if(!type) return(psfi); }
static PSFINFO *LoadPSF(char *path, int level, int type) // Type==1 for just info load. { FILE *fp; EXE_HEADER tmpHead; char *in,*out=0; u8 head[4]; u32 reserved; u32 complen; u32 crc32; uLongf outlen; PSFINFO *psfi; PSFINFO *tmpi; //printf("Loading: %s\n",path); if(!(fp=fopen(path,"rb"))) { return(0); } fread(head,1,4,fp); if(memcmp(head,"PSF\x01",4)) return(0); psfi=malloc(sizeof(PSFINFO)); memset(psfi,0,sizeof(PSFINFO)); psfi->stop=~0; psfi->fade=0; fread(&reserved,1,4,fp); fread(&complen,1,4,fp); complen=BFLIP32(complen); fread(&crc32,1,4,fp); crc32=BFLIP32(crc32); fseek(fp,reserved,SEEK_CUR); if(type) fseek(fp,complen,SEEK_CUR); else { in=malloc(complen); out=malloc(1024*1024*2+0x800); fread(in,1,complen,fp); outlen=1024*1024*2; uncompress(out,&outlen,in,complen); free(in); memcpy(&tmpHead,out,sizeof(EXE_HEADER)); psxRegs.pc = BFLIP32(tmpHead.pc0); psxRegs.GPR.n.gp = BFLIP32(tmpHead.gp0); psxRegs.GPR.n.sp = BFLIP32(tmpHead.S_addr); if (psxRegs.GPR.n.sp == 0) psxRegs.GPR.n.sp = 0x801fff00; if(level) { LoadPSXMem(BFLIP32(tmpHead.t_addr),BFLIP32(tmpHead.t_size),out+0x800); free(out); } } { u8 tagdata[5]; if(fread(tagdata,1,5,fp)==5) { if(!memcmp(tagdata,"[TAG]",5)) { char linebuf[1024]; while(fgets(linebuf,1024,fp)>0) { int x; char *key=0,*value=0; if(!GetKeyVal(linebuf,&key,&value)) { if(key) free(key); if(value) free(value); continue; } AddKV(&psfi->tags,key,value); if(!level) { static char *yoinks[8]={"title","artist","game","year","genre", "copyright","psfby","comment"}; char **yoinks2[8]={&psfi->title,&psfi->artist,&psfi->game,&psfi->year,&psfi->genre, &psfi->copyright,&psfi->psfby,&psfi->comment}; for(x=0;x<8;x++) if(!strcasecmp(key,yoinks[x])) *yoinks2[x]=value; if(!strcasecmp(key,"length")) psfi->stop=TimeToMS(value); else if(!strcasecmp(key,"fade")) psfi->fade=TimeToMS(value); } if(!strcasecmp(key,"_lib") && !type) { char *tmpfn; /* Load file name "value" from the directory specified in the full path(directory + file name) "path" */ tmpfn=findFileIgnoreCase(path,value); if(!(tmpi=LoadPSF(tmpfn,level+1,0))) { //free(key); //free(value); // key and value will be freed by FreeTags(psfi->tags) free(tmpfn); if(!level) free(out); fclose(fp); FreeTags(psfi->tags); free(psfi); return(0); } FreeTags(tmpi->tags); free(tmpi); free(tmpfn); } } } } } fclose(fp); /* Now, if we're at level 0(main PSF), load the main executable, and any libN stuff */ if(!level && !type) { LoadPSXMem(BFLIP32(tmpHead.t_addr),BFLIP32(tmpHead.t_size),out+0x800); free(out); } if(!type) /* Load libN */ { LIBNCACHE *cache; PSFTAG *tag; unsigned int libncount=0; unsigned int cur=0; tag=psfi->tags; while(tag) { if(!strncasecmp(tag->key,"_lib",4) && tag->key[4]) libncount++; tag=tag->next; } if(libncount) { cache=malloc(sizeof(LIBNCACHE)*libncount); tag=psfi->tags; while(tag) { if(!strncasecmp(tag->key,"_lib",4) && tag->key[4]) { cache[cur].num=atoi(&tag->key[4]); cache[cur].value=tag->value; cur++; } tag=tag->next; } qsort(cache, libncount, sizeof(LIBNCACHE), ccomp); for(cur=0;cur<libncount;cur++) { u32 ba[3]; char *tmpfn; if(cache[cur].num < 2) continue; ba[0]=psxRegs.pc; ba[1]=psxRegs.GPR.n.gp; ba[2]=psxRegs.GPR.n.sp; /* Load file name "value" from the directory specified in the full path(directory + file name) "path" */ tmpfn=findFileIgnoreCase(path,cache[cur].value); if(!(tmpi=LoadPSF(tmpfn,level+1,0))) { //free(key); //free(value); //free(tmpfn); //fclose(fp); //return(0); } free(tmpfn); FreeTags(tmpi->tags); free(tmpi); psxRegs.pc=ba[0]; psxRegs.GPR.n.gp=ba[1]; psxRegs.GPR.n.sp=ba[2]; } free(cache); } // if(libncount) } // if(!type) return(psfi); }
// LoadPSF for Memory static PSFINFO *memLoadPSF(char *addr, long size, int level, int type) // Type==1 for just info load. { u8 *in,*out=0; u8 head[4]; u32 reserved; u32 complen; u32 crc32; uLongf outlen; PSFINFO *psfi=NULL; PSFINFO *tmpi=NULL; u32 poffset, plength; u32 offset = 0; if( addr == NULL || size == 0 ) return(0); memread((void*)(head), 4, addr, size, &offset); if(memcmp(head,"PSF\x01",4)) return(0); psfi=malloc(sizeof(PSFINFO)); memset(psfi,0,sizeof(PSFINFO)); psfi->stop=~0; psfi->fade=0; memread((void*)(&reserved), 4, addr, size, &offset); memread((void*)(&complen), 4, addr, size, &offset); complen=BFLIP32(complen); memread((void*)(&crc32), 4, addr, size, &offset); crc32=BFLIP32(crc32); memseek(reserved, size, &offset); if(type) { memseek(complen, size, &offset); } else { in=malloc(complen); out=malloc(1024*1024*2+0x800); if( !in || !out ) { free(psfi); return (0); } memread((void*)(in), complen, addr, size, &offset); outlen=1024*1024*2; uncompress(out,&outlen,in,complen); free(in); psxRegs->pc = out[0x10] | out[0x11]<<8 | out[0x12]<<16 | out[0x13]<<24; psxRegs->GPR.n.gp = out[0x14] | out[0x15]<<8 | out[0x16]<<16 | out[0x17]<<24; psxRegs->GPR.n.sp = out[0x30] | out[0x31]<<8 | out[0x32]<<16 | out[0x33]<<24; if (psxRegs->GPR.n.sp == 0) psxRegs->GPR.n.sp = 0x801fff00; #ifdef DEBUG fprintf(stderr, "%d Level: PC %x GP %x SP %x\n", level, psxRegs->pc, psxRegs->GPR.n.gp, psxRegs->GPR.n.sp); #endif if(level) { poffset = out[0x18] | out[0x19]<<8 | out[0x1a]<<16 | out[0x1b]<<24; poffset &= 0x3fffffff; // kill any MIPS cache segment indicators plength = out[0x1c] | out[0x1d]<<8 | out[0x1e]<<16 | out[0x1f]<<24; #ifdef DEBUG fprintf(stderr, "%d Level: offset %x plength: %d\n", level, poffset, plength); #endif LoadPSXMem(poffset,plength,out+0x800); free(out); // I don't really know how does this // work, but apparently it breaks the // loop that makes ff6 and ct to take // several seconds to start ... if( crc32 == 0xEFDE8EEE || crc32 == 0x545D9F65 ) psxMemWrite32(0x5A66C, 0); // Same as above for Popolocrois and Einhänder if( crc32 == 0xF535726 ) psxMemWrite32(0x5A990, 0); } } { u8 tagdata[5]; if( memread((void*)(tagdata), 5, addr, size, &offset) == 5 ) { if(!memcmp(tagdata,"[TAG]",5)) { char linebuf[1024]; while( memfgets(linebuf, 1024, addr, size, &offset)>0 ) { int x; char *key=0,*value=0; if(!GetKeyVal(linebuf,&key,&value)) { if(key) free(key); if(value) free(value); continue; } AddKV(&psfi->tags,key,value); if(!level) { static char *yoinks[8]={"title","artist","game","year","genre", "copyright","psfby","comment"}; char **yoinks2[8]={&psfi->title,&psfi->artist,&psfi->game,&psfi->year,&psfi->genre, &psfi->copyright,&psfi->psfby,&psfi->comment}; for(x=0;x<8;x++) if(!strcasecmp(key,yoinks[x])) *yoinks2[x]=value; if(!strcasecmp(key,"length")) psfi->stop=TimeToMS(value); else if(!strcasecmp(key,"fade")) psfi->fade=TimeToMS(value); } if(!strcasecmp(key,"_lib") && !type && __psflibs) { /* Search file name "value" from the __psflibs array */ int n, found = 0; for(n=0;n<__psflibs->count;n++) if( !strcasecmp(value, __psflibs->libn[n].name) ) { found = 1; break; } if(!found || !(tmpi=memLoadPSF(__psflibs->libn[n].addr, __psflibs->libn[n].size, level+1,0))) { free(key); free(value); if(!level) free(out); FreeTags(psfi->tags); free(psfi); return(0); } FreeTags(tmpi->tags); free(tmpi); } } } } } /* Now, if we're at level 0(main PSF), load the main executable, and any libN stuff*/ if(!level && !type) { poffset = out[0x18] | out[0x19]<<8 | out[0x1a]<<16 | out[0x1b]<<24; poffset &= 0x3fffffff; // kill any MIPS cache segment indicators plength = out[0x1c] | out[0x1d]<<8 | out[0x1e]<<16 | out[0x1f]<<24; // TODO - investigate: should i just make // plength = outlen-0x800? // Philosoma has an illegal "plength". *sigh* if (plength > (outlen-0x800)) { plength = outlen-0x800; } if( psfi->game ) { // Suikoden Tenmei has an illegal "plength". *sigh sigh* if( !strncmp(psfi->game, "Suikoden: Tenmei no Chikai", 26) ) { plength = outlen-0x800; } // Einhänder has an illegal "plength". *sigh sigh sigh* if( !strncmp(psfi->game, "Einhänder", 9) ) { plength = outlen-0x800; } } #ifdef DEBUG fprintf(stderr, "%d Level: offset %x plength: %d\n", level, poffset, plength); #endif LoadPSXMem(poffset,plength,out+0x800); free(out); } if(!type && __psflibs) /* Load libN */ { LIBNCACHE *cache; PSFTAG *tag; unsigned int libncount=0; unsigned int cur=0; tag=psfi->tags; while(tag) { if(!strncasecmp(tag->key,"_lib",4) && tag->key[4]) libncount++; tag=tag->next; } if(libncount) { cache=malloc(sizeof(LIBNCACHE)*libncount); tag=psfi->tags; while(tag) { if(!strncasecmp(tag->key,"_lib",4) && tag->key[4]) { cache[cur].num=atoi(&tag->key[4]); cache[cur].value=tag->value; cur++; } tag=tag->next; } qsort(cache, libncount, sizeof(LIBNCACHE), ccomp); for(cur=0;cur<libncount;cur++) { u32 ba[3]; if(cache[cur].num < 2) continue; ba[0]=psxRegs->pc; ba[1]=psxRegs->GPR.n.gp; ba[2]=psxRegs->GPR.n.sp; /* Search file name "value" from the __psflibs array */ int n, found = 0; for(n=0;n<__psflibs->count;n++) if( !strcasecmp(cache[cur].value, __psflibs->libn[n].name) ) { found = 1; break; } if(!found || !(tmpi=memLoadPSF(__psflibs->libn[n].addr,__psflibs->libn[n].size,level+1,0))) { //free(key); //free(value); //free(tmpfn); //fclose(fp); //return(0); } FreeTags(tmpi->tags); free(tmpi); psxRegs->pc=ba[0]; psxRegs->GPR.n.gp=ba[1]; psxRegs->GPR.n.sp=ba[2]; } free(cache); } // if(libncount) } // if(!type) return(psfi); }