Mercurial > audlegacy-plugins
diff src/sexypsf/Misc.c @ 12:3da1b8942b8b trunk
[svn] - remove src/Input src/Output src/Effect src/General src/Visualization src/Container
author | nenolod |
---|---|
date | Mon, 18 Sep 2006 03:14:20 -0700 |
parents | src/Input/sexypsf/Misc.c@088092a52fea |
children | 2ebeb7816c5e |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/sexypsf/Misc.c Mon Sep 18 03:14:20 2006 -0700 @@ -0,0 +1,470 @@ +/* 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(); +}