Mercurial > audlegacy-plugins
view src/sexypsf/Misc.c @ 943:584ab2a62af5 trunk
[svn] - if handle->cancel = TRUE, immediately abort the fread operation.
author | nenolod |
---|---|
date | Thu, 12 Apr 2007 12:02:56 -0700 |
parents | 3da1b8942b8b |
children | 2ebeb7816c5e |
line wrap: on
line source
/* Pcsx - Pc Psx Emulator * Copyright (C) 1999-2002 Pcsx Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "audacious/vfs.h" #include <stdio.h> #include <string.h> #include <stdlib.h> #include <stdarg.h> #include "PsxCommon.h" #include "driver.h" // LOAD STUFF typedef struct { unsigned char id[8]; u32 text; u32 data; u32 pc0; u32 gp0; u32 t_addr; u32 t_size; u32 d_addr; u32 d_size; u32 b_addr; u32 b_size; u32 S_addr;//normal must a s not a S but error (???) u32 s_size; u32 SavedSP; u32 SavedFP; u32 SavedGP; u32 SavedRA; u32 SavedS0; } PACKSTRUCT EXE_HEADER; static long TimeToMS(const char *str) { int x,c=0; int acc=0; char s[100]; strncpy(s,str,100); s[99]=0; for(x=strlen(s);x>=0;x--) if(s[x]=='.' || s[x]==',') { acc=atoi(s+x+1); s[x]=0; } else if(s[x]==':') { if(c==0) acc+=atoi(s+x+1)*10; else if(c==1) acc+=atoi(s+x+(x?1:0))*10*60; c++; s[x]=0; } else if(x==0) { if(c==0) acc+=atoi(s+x)*10; else if(c==1) acc+=atoi(s+x)*10*60; else if(c==2) acc+=atoi(s+x)*10*60*60; } acc*=100; // To milliseconds. return(acc); } char *GetFileWithBase(char *f, char *newfile) { static char *ret; char *tp1; #if PSS_STYLE==1 tp1=((char *)strrchr(f,'/')); #else tp1=((char *)strrchr(f,'\\')); #if PSS_STYLE!=3 { char *tp3; tp3=((char *)strrchr(f,'/')); if(tp1<tp3) tp1=tp3; } #endif #endif if(!tp1) { ret=malloc(strlen(newfile)+1); strcpy(ret,newfile); } else { ret=malloc(tp1-f+2+strlen(newfile)); // 1(NULL), 1(/). memcpy(ret,f,tp1-f); ret[tp1-f]='/'; ret[tp1-f+1]=0; strcat(ret,newfile); } return(ret); } static int GetKeyVal(char *buf, char **key, char **val) { char *tmp; tmp=buf; /* First, convert any weirdo ASCII characters to spaces. */ while(*tmp++) if(*tmp>0 && *tmp<0x20) *tmp=0x20; /* Strip off white space off end of string(which should be the "value"). */ for(tmp=buf+strlen(buf)-1;tmp>=buf;tmp--) { if(*tmp != 0x20) break; *tmp=0; } /* Now, search for the first non-whitespace character. */ while(*buf == 0x20) buf++; tmp=buf; while((*buf != 0x20) && (*buf != '=')) { if(!*buf) return(0); /* Null character. */ buf++; } /* Allocate memory, copy string, and terminate string. */ if(!(*key=malloc(buf-tmp+1))) return(0); strncpy(*key,tmp,buf-tmp); (*key)[(buf-tmp)]=0; /* Search for "=" character. */ while(*buf != '=') { if(!*buf) return(0); /* Null character. */ buf++; } buf++; /* Skip over equals character. */ /* Remove leading whitespace on value. */ while(*buf == 0x20) { if(!*buf) return(0); /* Null character. */ buf++; } /* Allocate memory, and copy string over. Trailing whitespace was eliminated earlier. */ if(!(*val=malloc(strlen(buf)+1))) return(0); strcpy(*val,buf); //puts(*key); //puts(*val); return(1); } static void FreeTags(PSFTAG *tags) { while(tags) { PSFTAG *tmp=tags->next; free(tags->key); free(tags->value); free(tags); tags=tmp; } } static void AddKV(PSFTAG **tag, char *key, char *val) { PSFTAG *tmp; tmp=malloc(sizeof(PSFTAG)); memset(tmp,0,sizeof(PSFTAG)); tmp->key=key; tmp->value=val; tmp->next=0; if(!*tag) *tag=tmp; else { PSFTAG *rec; rec=*tag; while(rec->next) rec=rec->next; rec->next=tmp; } } typedef struct { int num; char *value; } LIBNCACHE; static int ccomp(const void *v1, const void *v2) { const LIBNCACHE *a1,*a2; a1=v1; a2=v2; return(a1->num - a2->num); } static PSFINFO *LoadPSF(char *path, int level, int type) // Type==1 for just info load. { VFSFile *fp; EXE_HEADER tmpHead; unsigned char *in,*out=0; u8 head[4]; u32 reserved; u32 complen; u32 crc32; uLongf outlen; PSFINFO *psfi; PSFINFO *tmpi; if(!(fp=vfs_fopen(path,"rb"))) { printf("path %s failed to load\n", path); return(0); } vfs_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; vfs_fread(&reserved,1,4,fp); vfs_fread(&complen,1,4,fp); complen=BFLIP32(complen); vfs_fread(&crc32,1,4,fp); crc32=BFLIP32(crc32); vfs_fseek(fp,reserved,SEEK_CUR); if(type) vfs_fseek(fp,complen,SEEK_CUR); else { in=malloc(complen); out=malloc(1024*1024*2+0x800); vfs_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(vfs_fread(tagdata,1,5,fp)==5) { if(!memcmp(tagdata,"[TAG]",5)) { char linebuf[1024]; while(vfs_fgets(linebuf,1024,fp)) { 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); vfs_fclose(fp); FreeTags(psfi->tags); free(psfi); return(0); } FreeTags(tmpi->tags); free(tmpi); free(tmpfn); } } } } } vfs_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); //vfs_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); } void sexypsf_freepsfinfo(PSFINFO *info) { FreeTags(info->tags); free(info); } PSFINFO *sexypsf_getpsfinfo(char *path) { PSFINFO *ret; if(!(ret=LoadPSF(path,0,1))) return(0); if(ret->stop==(u32)~0) ret->fade=0; ret->length=ret->stop+ret->fade; return(ret); } PSFINFO *sexypsf_load(char *path) { PSFINFO *ret; psxInit(); psxReset(); SPUinit(); SPUopen(); if(!(ret=LoadPSF(path,0,0))) { psxShutdown(); return(0); } if(ret->stop==(u32)~0) ret->fade=0; // Infinity+anything is still infinity...or is it? SPUsetlength(ret->stop,ret->fade); ret->length=ret->stop+ret->fade; return(ret); } void sexypsf_execute(void) { psxCpu->Execute(); }