Mercurial > audlegacy-plugins
comparison 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 |
comparison
equal
deleted
inserted
replaced
11:cff1d04026ae | 12:3da1b8942b8b |
---|---|
1 /* Pcsx - Pc Psx Emulator | |
2 * Copyright (C) 1999-2002 Pcsx Team | |
3 * | |
4 * This program is free software; you can redistribute it and/or modify | |
5 * it under the terms of the GNU General Public License as published by | |
6 * the Free Software Foundation; either version 2 of the License, or | |
7 * (at your option) any later version. | |
8 * | |
9 * This program is distributed in the hope that it will be useful, | |
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 * GNU General Public License for more details. | |
13 * | |
14 * You should have received a copy of the GNU General Public License | |
15 * along with this program; if not, write to the Free Software | |
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
17 */ | |
18 | |
19 #include "audacious/vfs.h" | |
20 #include <stdio.h> | |
21 #include <string.h> | |
22 #include <stdlib.h> | |
23 #include <stdarg.h> | |
24 | |
25 #include "PsxCommon.h" | |
26 #include "driver.h" | |
27 | |
28 // LOAD STUFF | |
29 | |
30 typedef struct { | |
31 unsigned char id[8]; | |
32 u32 text; | |
33 u32 data; | |
34 u32 pc0; | |
35 u32 gp0; | |
36 u32 t_addr; | |
37 u32 t_size; | |
38 u32 d_addr; | |
39 u32 d_size; | |
40 u32 b_addr; | |
41 u32 b_size; | |
42 u32 S_addr;//normal must a s not a S but error (???) | |
43 u32 s_size; | |
44 u32 SavedSP; | |
45 u32 SavedFP; | |
46 u32 SavedGP; | |
47 u32 SavedRA; | |
48 u32 SavedS0; | |
49 } PACKSTRUCT EXE_HEADER; | |
50 | |
51 static long TimeToMS(const char *str) | |
52 { | |
53 int x,c=0; | |
54 int acc=0; | |
55 char s[100]; | |
56 | |
57 strncpy(s,str,100); | |
58 s[99]=0; | |
59 | |
60 for(x=strlen(s);x>=0;x--) | |
61 if(s[x]=='.' || s[x]==',') | |
62 { | |
63 acc=atoi(s+x+1); | |
64 s[x]=0; | |
65 } | |
66 else if(s[x]==':') | |
67 { | |
68 if(c==0) acc+=atoi(s+x+1)*10; | |
69 else if(c==1) acc+=atoi(s+x+(x?1:0))*10*60; | |
70 c++; | |
71 s[x]=0; | |
72 } | |
73 else if(x==0) | |
74 { | |
75 if(c==0) acc+=atoi(s+x)*10; | |
76 else if(c==1) acc+=atoi(s+x)*10*60; | |
77 else if(c==2) acc+=atoi(s+x)*10*60*60; | |
78 } | |
79 acc*=100; // To milliseconds. | |
80 return(acc); | |
81 } | |
82 | |
83 char *GetFileWithBase(char *f, char *newfile) | |
84 { | |
85 static char *ret; | |
86 char *tp1; | |
87 | |
88 #if PSS_STYLE==1 | |
89 tp1=((char *)strrchr(f,'/')); | |
90 #else | |
91 tp1=((char *)strrchr(f,'\\')); | |
92 #if PSS_STYLE!=3 | |
93 { | |
94 char *tp3; | |
95 | |
96 tp3=((char *)strrchr(f,'/')); | |
97 if(tp1<tp3) tp1=tp3; | |
98 } | |
99 #endif | |
100 #endif | |
101 if(!tp1) | |
102 { | |
103 ret=malloc(strlen(newfile)+1); | |
104 strcpy(ret,newfile); | |
105 } | |
106 else | |
107 { | |
108 ret=malloc(tp1-f+2+strlen(newfile)); // 1(NULL), 1(/). | |
109 memcpy(ret,f,tp1-f); | |
110 ret[tp1-f]='/'; | |
111 ret[tp1-f+1]=0; | |
112 strcat(ret,newfile); | |
113 } | |
114 return(ret); | |
115 } | |
116 | |
117 static int GetKeyVal(char *buf, char **key, char **val) | |
118 { | |
119 char *tmp; | |
120 | |
121 tmp=buf; | |
122 | |
123 /* First, convert any weirdo ASCII characters to spaces. */ | |
124 while(*tmp++) if(*tmp>0 && *tmp<0x20) *tmp=0x20; | |
125 | |
126 /* Strip off white space off end of string(which should be the "value"). */ | |
127 for(tmp=buf+strlen(buf)-1;tmp>=buf;tmp--) | |
128 { | |
129 if(*tmp != 0x20) break; | |
130 *tmp=0; | |
131 } | |
132 | |
133 /* Now, search for the first non-whitespace character. */ | |
134 while(*buf == 0x20) buf++; | |
135 | |
136 tmp=buf; | |
137 while((*buf != 0x20) && (*buf != '=')) | |
138 { | |
139 if(!*buf) return(0); /* Null character. */ | |
140 buf++; | |
141 } | |
142 | |
143 /* Allocate memory, copy string, and terminate string. */ | |
144 if(!(*key=malloc(buf-tmp+1))) return(0); | |
145 strncpy(*key,tmp,buf-tmp); | |
146 (*key)[(buf-tmp)]=0; | |
147 | |
148 /* Search for "=" character. */ | |
149 while(*buf != '=') | |
150 { | |
151 if(!*buf) return(0); /* Null character. */ | |
152 buf++; | |
153 } | |
154 | |
155 buf++; /* Skip over equals character. */ | |
156 | |
157 /* Remove leading whitespace on value. */ | |
158 while(*buf == 0x20) | |
159 { | |
160 if(!*buf) return(0); /* Null character. */ | |
161 buf++; | |
162 } | |
163 | |
164 /* Allocate memory, and copy string over. Trailing whitespace was eliminated | |
165 earlier. | |
166 */ | |
167 | |
168 if(!(*val=malloc(strlen(buf)+1))) return(0); | |
169 strcpy(*val,buf); | |
170 | |
171 //puts(*key); | |
172 //puts(*val); | |
173 | |
174 return(1); | |
175 } | |
176 | |
177 static void FreeTags(PSFTAG *tags) | |
178 { | |
179 while(tags) | |
180 { | |
181 PSFTAG *tmp=tags->next; | |
182 | |
183 free(tags->key); | |
184 free(tags->value); | |
185 free(tags); | |
186 | |
187 tags=tmp; | |
188 } | |
189 } | |
190 | |
191 static void AddKV(PSFTAG **tag, char *key, char *val) | |
192 { | |
193 PSFTAG *tmp; | |
194 | |
195 tmp=malloc(sizeof(PSFTAG)); | |
196 memset(tmp,0,sizeof(PSFTAG)); | |
197 | |
198 tmp->key=key; | |
199 tmp->value=val; | |
200 tmp->next=0; | |
201 | |
202 if(!*tag) *tag=tmp; | |
203 else | |
204 { | |
205 PSFTAG *rec; | |
206 rec=*tag; | |
207 while(rec->next) rec=rec->next; | |
208 rec->next=tmp; | |
209 } | |
210 | |
211 } | |
212 | |
213 typedef struct { | |
214 int num; | |
215 char *value; | |
216 } LIBNCACHE; | |
217 | |
218 static int ccomp(const void *v1, const void *v2) | |
219 { | |
220 const LIBNCACHE *a1,*a2; | |
221 a1=v1; a2=v2; | |
222 | |
223 return(a1->num - a2->num); | |
224 } | |
225 | |
226 static PSFINFO *LoadPSF(char *path, int level, int type) // Type==1 for just info load. | |
227 { | |
228 VFSFile *fp; | |
229 EXE_HEADER tmpHead; | |
230 unsigned char *in,*out=0; | |
231 u8 head[4]; | |
232 u32 reserved; | |
233 u32 complen; | |
234 u32 crc32; | |
235 uLongf outlen; | |
236 PSFINFO *psfi; | |
237 PSFINFO *tmpi; | |
238 | |
239 if(!(fp=vfs_fopen(path,"rb"))) | |
240 { | |
241 printf("path %s failed to load\n", path); | |
242 return(0); | |
243 } | |
244 | |
245 vfs_fread(head,1,4,fp); | |
246 if(memcmp(head,"PSF\x01",4)) return(0); | |
247 | |
248 psfi=malloc(sizeof(PSFINFO)); | |
249 memset(psfi,0,sizeof(PSFINFO)); | |
250 psfi->stop=~0; | |
251 psfi->fade=0; | |
252 | |
253 vfs_fread(&reserved,1,4,fp); | |
254 vfs_fread(&complen,1,4,fp); | |
255 complen=BFLIP32(complen); | |
256 | |
257 vfs_fread(&crc32,1,4,fp); | |
258 crc32=BFLIP32(crc32); | |
259 | |
260 vfs_fseek(fp,reserved,SEEK_CUR); | |
261 | |
262 if(type) | |
263 vfs_fseek(fp,complen,SEEK_CUR); | |
264 else | |
265 { | |
266 in=malloc(complen); | |
267 out=malloc(1024*1024*2+0x800); | |
268 vfs_fread(in,1,complen,fp); | |
269 outlen=1024*1024*2; | |
270 uncompress(out,&outlen,in,complen); | |
271 free(in); | |
272 memcpy(&tmpHead,out,sizeof(EXE_HEADER)); | |
273 psxRegs.pc = BFLIP32(tmpHead.pc0); | |
274 psxRegs.GPR.n.gp = BFLIP32(tmpHead.gp0); | |
275 psxRegs.GPR.n.sp = BFLIP32(tmpHead.S_addr); | |
276 if (psxRegs.GPR.n.sp == 0) psxRegs.GPR.n.sp = 0x801fff00; | |
277 | |
278 if(level) | |
279 { | |
280 LoadPSXMem(BFLIP32(tmpHead.t_addr),BFLIP32(tmpHead.t_size),out+0x800); | |
281 free(out); | |
282 } | |
283 } | |
284 | |
285 { | |
286 u8 tagdata[5]; | |
287 if(vfs_fread(tagdata,1,5,fp)==5) | |
288 { | |
289 if(!memcmp(tagdata,"[TAG]",5)) | |
290 { | |
291 char linebuf[1024]; | |
292 | |
293 while(vfs_fgets(linebuf,1024,fp)) | |
294 { | |
295 int x; | |
296 char *key=0,*value=0; | |
297 | |
298 if(!GetKeyVal(linebuf,&key,&value)) | |
299 { | |
300 if(key) free(key); | |
301 if(value) free(value); | |
302 continue; | |
303 } | |
304 | |
305 AddKV(&psfi->tags,key,value); | |
306 | |
307 if(!level) | |
308 { | |
309 static char *yoinks[8]={"title","artist","game","year","genre", | |
310 "copyright","psfby","comment"}; | |
311 char **yoinks2[8]={&psfi->title,&psfi->artist,&psfi->game,&psfi->year,&psfi->genre, | |
312 &psfi->copyright,&psfi->psfby,&psfi->comment}; | |
313 for(x=0;x<8;x++) | |
314 if(!strcasecmp(key,yoinks[x])) | |
315 *yoinks2[x]=value; | |
316 if(!strcasecmp(key,"length")) | |
317 psfi->stop=TimeToMS(value); | |
318 else if(!strcasecmp(key,"fade")) | |
319 psfi->fade=TimeToMS(value); | |
320 } | |
321 | |
322 if(!strcasecmp(key,"_lib") && !type) | |
323 { | |
324 char *tmpfn; | |
325 /* Load file name "value" from the directory specified in | |
326 the full path(directory + file name) "path" | |
327 */ | |
328 tmpfn=GetFileWithBase(path,value); | |
329 if(!(tmpi=LoadPSF(tmpfn,level+1,0))) | |
330 { | |
331 free(key); | |
332 free(value); | |
333 free(tmpfn); | |
334 if(!level) free(out); | |
335 vfs_fclose(fp); | |
336 FreeTags(psfi->tags); | |
337 free(psfi); | |
338 return(0); | |
339 } | |
340 FreeTags(tmpi->tags); | |
341 free(tmpi); | |
342 free(tmpfn); | |
343 } | |
344 } | |
345 } | |
346 } | |
347 } | |
348 | |
349 vfs_fclose(fp); | |
350 | |
351 /* Now, if we're at level 0(main PSF), load the main executable, and any libN stuff */ | |
352 if(!level && !type) | |
353 { | |
354 LoadPSXMem(BFLIP32(tmpHead.t_addr),BFLIP32(tmpHead.t_size),out+0x800); | |
355 free(out); | |
356 } | |
357 | |
358 if(!type) /* Load libN */ | |
359 { | |
360 LIBNCACHE *cache; | |
361 PSFTAG *tag; | |
362 unsigned int libncount=0; | |
363 unsigned int cur=0; | |
364 | |
365 tag=psfi->tags; | |
366 while(tag) | |
367 { | |
368 if(!strncasecmp(tag->key,"_lib",4) && tag->key[4]) | |
369 libncount++; | |
370 tag=tag->next; | |
371 } | |
372 | |
373 if(libncount) | |
374 { | |
375 cache=malloc(sizeof(LIBNCACHE)*libncount); | |
376 | |
377 tag=psfi->tags; | |
378 while(tag) | |
379 { | |
380 if(!strncasecmp(tag->key,"_lib",4) && tag->key[4]) | |
381 { | |
382 cache[cur].num=atoi(&tag->key[4]); | |
383 cache[cur].value=tag->value; | |
384 cur++; | |
385 } | |
386 tag=tag->next; | |
387 } | |
388 qsort(cache, libncount, sizeof(LIBNCACHE), ccomp); | |
389 for(cur=0;cur<libncount;cur++) | |
390 { | |
391 u32 ba[3]; | |
392 char *tmpfn; | |
393 | |
394 if(cache[cur].num < 2) continue; | |
395 | |
396 ba[0]=psxRegs.pc; | |
397 ba[1]=psxRegs.GPR.n.gp; | |
398 ba[2]=psxRegs.GPR.n.sp; | |
399 | |
400 /* Load file name "value" from the directory specified in | |
401 the full path(directory + file name) "path" | |
402 */ | |
403 tmpfn=GetFileWithBase(path,cache[cur].value); | |
404 if(!(tmpi=LoadPSF(tmpfn,level+1,0))) | |
405 { | |
406 //free(key); | |
407 //free(value); | |
408 //free(tmpfn); | |
409 //vfs_fclose(fp); | |
410 //return(0); | |
411 } | |
412 free(tmpfn); | |
413 FreeTags(tmpi->tags); | |
414 free(tmpi); | |
415 | |
416 psxRegs.pc=ba[0]; | |
417 psxRegs.GPR.n.gp=ba[1]; | |
418 psxRegs.GPR.n.sp=ba[2]; | |
419 } | |
420 free(cache); | |
421 | |
422 } // if(libncount) | |
423 | |
424 } // if(!type) | |
425 | |
426 return(psfi); | |
427 } | |
428 | |
429 void sexypsf_freepsfinfo(PSFINFO *info) | |
430 { | |
431 FreeTags(info->tags); | |
432 free(info); | |
433 } | |
434 | |
435 PSFINFO *sexypsf_getpsfinfo(char *path) | |
436 { | |
437 PSFINFO *ret; | |
438 if(!(ret=LoadPSF(path,0,1))) return(0); | |
439 if(ret->stop==(u32)~0) ret->fade=0; | |
440 ret->length=ret->stop+ret->fade; | |
441 return(ret); | |
442 } | |
443 | |
444 PSFINFO *sexypsf_load(char *path) | |
445 { | |
446 PSFINFO *ret; | |
447 | |
448 psxInit(); | |
449 psxReset(); | |
450 | |
451 SPUinit(); | |
452 SPUopen(); | |
453 | |
454 if(!(ret=LoadPSF(path,0,0))) | |
455 { | |
456 psxShutdown(); | |
457 return(0); | |
458 } | |
459 | |
460 if(ret->stop==(u32)~0) ret->fade=0; // Infinity+anything is still infinity...or is it? | |
461 SPUsetlength(ret->stop,ret->fade); | |
462 ret->length=ret->stop+ret->fade; | |
463 | |
464 return(ret); | |
465 } | |
466 | |
467 void sexypsf_execute(void) | |
468 { | |
469 psxCpu->Execute(); | |
470 } |