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 }