/** Find the file in path ignoring case and return the full file path */ char* findFileIgnoreCase(const char* path, const char* file) { char* tmpfn = GetFileWithBase(path, file); if(access(tmpfn, F_OK) != -1 ) { return tmpfn; } // file does not exist, find it ignoring case sexypsf_dbg_printf("File %s does not exist!", tmpfn); DIR* d; struct dirent* dir; char* p = getPath(path); d = opendir(p); if (d) { sexypsf_dbg_printf("Opened dir %s", p); while ((dir = readdir(d)) != NULL) { sexypsf_dbg_printf("%s\n", dir->d_name); if (strcasecmp(dir->d_name, file) == 0) { // Find file! sexypsf_dbg_printf("Find similar file %s", dir->d_name); free(tmpfn); tmpfn = GetFileWithBase(path, dir->d_name); break; } } closedir(d); } else { sexypsf_dbg_printf("Failed to open dir %s", p); } free(p); return tmpfn; }
const wchar_t* SNSFLoader::load_psf_libs(PSFFile& psf, RawFile* file, unsigned char*& exebuffer, size_t& exebuffersize) { char libTagName[16]; int libIndex = 1; while (true) { if (libIndex == 1) strcpy(libTagName, "_lib"); else sprintf(libTagName, "_lib%d", libIndex); map<string, string>::iterator itLibTag = psf.tags.find(libTagName); if (itLibTag == psf.tags.end()) break; wchar_t tempfn[_MAX_PATH] = { 0 }; mbstowcs(tempfn, itLibTag->second.c_str(), itLibTag->second.size()); wchar_t *fullPath; fullPath=GetFileWithBase(file->GetFullPath(),tempfn); // TODO: Make sure to limit recursion to avoid crashing. RawFile* newRawFile = new RawFile(fullPath); const wchar_t* psflibError = NULL; if (newRawFile->open(fullPath)) psflibError = psf_read_exe(newRawFile, exebuffer, exebuffersize); else psflibError = L"Unable to open lib file."; delete fullPath; delete newRawFile; if (psflibError != NULL) return psflibError; libIndex++; } return NULL; }
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=GetFileWithBase(path,value); if(!(tmpi=LoadPSF(tmpfn,level+1,0))) { free(key); free(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) { 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=GetFileWithBase(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); }
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); }