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