comparison src/psf2/eng_psf.c @ 2737:62cc6d667119

Import a bunch of stuff for new psf2 plugin.
author William Pitcock <nenolod@atheme.org>
date Mon, 30 Jun 2008 20:20:53 -0500
parents
children f0547285577e
comparison
equal deleted inserted replaced
2731:324f950774cb 2737:62cc6d667119
1 /*
2 Audio Overload SDK - PSF file format engine
3
4 Copyright (c) 2007 R. Belmont and Richard Bannister.
5
6 All rights reserved.
7
8 Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
9
10 * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
11 * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
12 * Neither the names of R. Belmont and Richard Bannister nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
13
14 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
15 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
16 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
17 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
18 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
22 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
23 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27 #include <stdio.h>
28 #include <string.h>
29 #include <stdlib.h>
30
31 #include "ao.h"
32 #include "eng_protos.h"
33 #include "cpuintrf.h"
34 #include "psx.h"
35
36 #include "peops/stdafx.h"
37 #include "peops/externals.h"
38 #include "peops/regs.h"
39 #include "peops/registers.h"
40 #include "peops/spu.h"
41
42
43 #include "corlett.h"
44
45 #define DEBUG_LOADER (0)
46
47 static corlett_t *c = NULL;
48 static char psfby[256];
49 char *spu_pOutput;
50 int psf_refresh = -1;
51
52
53 // main RAM
54 extern uint32 psx_ram[((2*1024*1024)/4)+4];
55 extern uint32 psx_scratch[0x400];
56 extern uint32 initial_ram[((2*1024*1024)/4)+4];
57 extern uint32 initial_scratch[0x400];
58 static uint32 initialPC, initialGP, initialSP;
59
60 extern void mips_init( void );
61 extern void mips_reset( void *param );
62 extern int mips_execute( int cycles );
63 extern void mips_set_info(UINT32 state, union cpuinfo *info);
64 extern void psx_hw_init(void);
65 extern void psx_hw_slice(void);
66 extern void psx_hw_frame(void);
67 extern void setlength(int32 stop, int32 fade);
68
69 int32 psf_start(uint8 *buffer, uint32 length)
70 {
71 uint8 *file, *lib_decoded, *lib_raw_file, *alib_decoded;
72 uint32 offset, plength, PC, SP, GP, lengthMS, fadeMS;
73 uint64 file_len, lib_len, lib_raw_length, alib_len;
74 corlett_t *lib;
75 int i;
76 union cpuinfo mipsinfo;
77
78 // clear PSX work RAM before we start scribbling in it
79 memset(psx_ram, 0, 2*1024*1024);
80
81 // printf("Length = %d\n", length);
82
83 // Decode the current GSF
84 if (corlett_decode(buffer, length, &file, &file_len, &c) != AO_SUCCESS)
85 {
86 return AO_FAIL;
87 }
88
89 // printf("file_len %d reserve %d\n", file_len, c->res_size);
90
91 // check for PSX EXE signature
92 if (strncmp((char *)file, "PS-X EXE", 8))
93 {
94 return AO_FAIL;
95 }
96
97 #if DEBUG_LOADER
98 offset = file[0x18] | file[0x19]<<8 | file[0x1a]<<16 | file[0x1b]<<24;
99 printf("Text section start: %x\n", offset);
100 offset = file[0x1c] | file[0x1d]<<8 | file[0x1e]<<16 | file[0x1f]<<24;
101 printf("Text section size: %x\n", offset);
102 printf("Region: [%s]\n", &file[0x4c]);
103 printf("refresh: [%s]\n", c->inf_refresh);
104 #endif
105
106 if (c->inf_refresh[0] == '5')
107 {
108 psf_refresh = 50;
109 }
110 if (c->inf_refresh[0] == '6')
111 {
112 psf_refresh = 60;
113 }
114
115 PC = file[0x10] | file[0x11]<<8 | file[0x12]<<16 | file[0x13]<<24;
116 GP = file[0x14] | file[0x15]<<8 | file[0x16]<<16 | file[0x17]<<24;
117 SP = file[0x30] | file[0x31]<<8 | file[0x32]<<16 | file[0x33]<<24;
118
119 #if DEBUG_LOADER
120 printf("Top level: PC %x GP %x SP %x\n", PC, GP, SP);
121 #endif
122
123 // Get the library file, if any
124 if (c->lib[0] != 0)
125 {
126 uint64 tmp_length;
127
128 #if DEBUG_LOADER
129 printf("Loading library: %s\n", c->lib);
130 #endif
131 if (ao_get_lib(c->lib, &lib_raw_file, &tmp_length) != AO_SUCCESS)
132 {
133 return AO_FAIL;
134 }
135 lib_raw_length = tmp_length;
136
137 if (corlett_decode(lib_raw_file, lib_raw_length, &lib_decoded, &lib_len, &lib) != AO_SUCCESS)
138 {
139 free(lib_raw_file);
140 return AO_FAIL;
141 }
142
143 // Free up raw file
144 free(lib_raw_file);
145
146 if (strncmp((char *)lib_decoded, "PS-X EXE", 8))
147 {
148 printf("Major error! PSF was OK, but referenced library is not!\n");
149 free(lib);
150 return AO_FAIL;
151 }
152
153 #if DEBUG_LOADER
154 offset = lib_decoded[0x18] | lib_decoded[0x19]<<8 | lib_decoded[0x1a]<<16 | lib_decoded[0x1b]<<24;
155 printf("Text section start: %x\n", offset);
156 offset = lib_decoded[0x1c] | lib_decoded[0x1d]<<8 | lib_decoded[0x1e]<<16 | lib_decoded[0x1f]<<24;
157 printf("Text section size: %x\n", offset);
158 printf("Region: [%s]\n", &lib_decoded[0x4c]);
159 printf("refresh: [%s]\n", lib->inf_refresh);
160 #endif
161
162 // if the original file had no refresh tag, give the lib a shot
163 if (psf_refresh == -1)
164 {
165 if (lib->inf_refresh[0] == '5')
166 {
167 psf_refresh = 50;
168 }
169 if (lib->inf_refresh[0] == '6')
170 {
171 psf_refresh = 60;
172 }
173 }
174
175 PC = lib_decoded[0x10] | lib_decoded[0x11]<<8 | lib_decoded[0x12]<<16 | lib_decoded[0x13]<<24;
176 GP = lib_decoded[0x14] | lib_decoded[0x15]<<8 | lib_decoded[0x16]<<16 | lib_decoded[0x17]<<24;
177 SP = lib_decoded[0x30] | lib_decoded[0x31]<<8 | lib_decoded[0x32]<<16 | lib_decoded[0x33]<<24;
178
179 #if DEBUG_LOADER
180 printf("Library: PC %x GP %x SP %x\n", PC, GP, SP);
181 #endif
182
183 // now patch the file into RAM
184 offset = lib_decoded[0x18] | lib_decoded[0x19]<<8 | lib_decoded[0x1a]<<16 | lib_decoded[0x1b]<<24;
185 offset &= 0x3fffffff; // kill any MIPS cache segment indicators
186 plength = lib_decoded[0x1c] | lib_decoded[0x1d]<<8 | lib_decoded[0x1e]<<16 | lib_decoded[0x1f]<<24;
187 #if DEBUG_LOADER
188 printf("library offset: %x plength: %d\n", offset, plength);
189 #endif
190 memcpy(&psx_ram[offset/4], lib_decoded+2048, plength);
191
192 // Dispose the corlett structure for the lib - we don't use it
193 free(lib);
194 }
195
196 // now patch the main file into RAM OVER the libraries (but not the aux lib)
197 offset = file[0x18] | file[0x19]<<8 | file[0x1a]<<16 | file[0x1b]<<24;
198 offset &= 0x3fffffff; // kill any MIPS cache segment indicators
199 plength = file[0x1c] | file[0x1d]<<8 | file[0x1e]<<16 | file[0x1f]<<24;
200
201 // Philosoma has an illegal "plength". *sigh*
202 if (plength > (file_len-2048))
203 {
204 plength = file_len-2048;
205 }
206 memcpy(&psx_ram[offset/4], file+2048, plength);
207
208 // load any auxiliary libraries now
209 for (i = 0; i < 8; i++)
210 {
211 if (c->libaux[i][0] != 0)
212 {
213 uint64 tmp_length;
214
215 #if DEBUG_LOADER
216 printf("Loading aux library: %s\n", c->libaux[i]);
217 #endif
218
219 if (ao_get_lib(c->libaux[i], &lib_raw_file, &tmp_length) != AO_SUCCESS)
220 {
221 return AO_FAIL;
222 }
223 lib_raw_length = tmp_length;
224
225 if (corlett_decode(lib_raw_file, lib_raw_length, &alib_decoded, &alib_len, &lib) != AO_SUCCESS)
226 {
227 free(lib_raw_file);
228 return AO_FAIL;
229 }
230
231 // Free up raw file
232 free(lib_raw_file);
233
234 if (strncmp((char *)alib_decoded, "PS-X EXE", 8))
235 {
236 printf("Major error! PSF was OK, but referenced library is not!\n");
237 free(lib);
238 return AO_FAIL;
239 }
240
241 #if DEBUG_LOADER
242 offset = alib_decoded[0x18] | alib_decoded[0x19]<<8 | alib_decoded[0x1a]<<16 | alib_decoded[0x1b]<<24;
243 printf("Text section start: %x\n", offset);
244 offset = alib_decoded[0x1c] | alib_decoded[0x1d]<<8 | alib_decoded[0x1e]<<16 | alib_decoded[0x1f]<<24;
245 printf("Text section size: %x\n", offset);
246 printf("Region: [%s]\n", &alib_decoded[0x4c]);
247 #endif
248
249 // now patch the file into RAM
250 offset = alib_decoded[0x18] | alib_decoded[0x19]<<8 | alib_decoded[0x1a]<<16 | alib_decoded[0x1b]<<24;
251 offset &= 0x3fffffff; // kill any MIPS cache segment indicators
252 plength = alib_decoded[0x1c] | alib_decoded[0x1d]<<8 | alib_decoded[0x1e]<<16 | alib_decoded[0x1f]<<24;
253 memcpy(&psx_ram[offset/4], alib_decoded+2048, plength);
254
255 // Dispose the corlett structure for the lib - we don't use it
256 free(lib);
257 }
258 }
259
260 free(file);
261 // free(lib_decoded);
262
263 // Finally, set psfby tag
264 strcpy(psfby, "n/a");
265 if (c)
266 {
267 int i;
268 for (i = 0; i < MAX_UNKNOWN_TAGS; i++)
269 {
270 if (!strcasecmp(c->tag_name[i], "psfby"))
271 strcpy(psfby, c->tag_data[i]);
272 }
273 }
274
275 mips_init();
276 mips_reset(NULL);
277
278 // set the initial PC, SP, GP
279 #if DEBUG_LOADER
280 printf("Initial PC %x, GP %x, SP %x\n", PC, GP, SP);
281 printf("Refresh = %d\n", psf_refresh);
282 #endif
283 mipsinfo.i = PC;
284 mips_set_info(CPUINFO_INT_PC, &mipsinfo);
285
286 // set some reasonable default for the stack
287 if (SP == 0)
288 {
289 SP = 0x801fff00;
290 }
291
292 mipsinfo.i = SP;
293 mips_set_info(CPUINFO_INT_REGISTER + MIPS_R29, &mipsinfo);
294 mips_set_info(CPUINFO_INT_REGISTER + MIPS_R30, &mipsinfo);
295
296 mipsinfo.i = GP;
297 mips_set_info(CPUINFO_INT_REGISTER + MIPS_R28, &mipsinfo);
298
299 #if DEBUG_LOADER && 1
300 {
301 FILE *f;
302
303 f = fopen("psxram.bin", "wb");
304 fwrite(psx_ram, 2*1024*1024, 1, f);
305 fclose(f);
306 }
307 #endif
308
309 psx_hw_init();
310 SPUinit();
311 SPUopen();
312
313 lengthMS = psfTimeToMS(c->inf_length);
314 fadeMS = psfTimeToMS(c->inf_fade);
315
316 #if DEBUG_LOADER
317 printf("length %d fade %d\n", lengthMS, fadeMS);
318 #endif
319
320 if (lengthMS == 0)
321 {
322 lengthMS = ~0;
323 }
324
325 setlength(lengthMS, fadeMS);
326
327 // psx_ram[0x118b8/4] = LE32(0); // crash 2 hack
328
329 // backup the initial state for restart
330 memcpy(initial_ram, psx_ram, 2*1024*1024);
331 memcpy(initial_scratch, psx_scratch, 0x400);
332 initialPC = PC;
333 initialGP = GP;
334 initialSP = SP;
335
336 mips_execute(5000);
337
338 return AO_SUCCESS;
339 }
340
341 void spu_update(unsigned char* pSound,long lBytes)
342 {
343 memcpy(spu_pOutput, pSound, lBytes);
344 }
345
346 int32 psf_gen(int16 *buffer, uint32 samples)
347 {
348 int i;
349
350 for (i = 0; i < samples; i++)
351 {
352 psx_hw_slice();
353 SPUasync(384);
354 }
355
356 spu_pOutput = (char *)buffer;
357 SPU_flushboot();
358
359 psx_hw_frame();
360
361 return AO_SUCCESS;
362 }
363
364 int32 psf_stop(void)
365 {
366 SPUclose();
367 free(c);
368
369 return AO_SUCCESS;
370 }
371
372 int32 psf_command(int32 command, int32 parameter)
373 {
374 union cpuinfo mipsinfo;
375 uint32 lengthMS, fadeMS;
376
377 switch (command)
378 {
379 case COMMAND_RESTART:
380 SPUclose();
381
382 memcpy(psx_ram, initial_ram, 2*1024*1024);
383 memcpy(psx_scratch, initial_scratch, 0x400);
384
385 mips_init();
386 mips_reset(NULL);
387 psx_hw_init();
388 SPUinit();
389 SPUopen();
390
391 lengthMS = psfTimeToMS(c->inf_length);
392 fadeMS = psfTimeToMS(c->inf_fade);
393
394 if (lengthMS == 0)
395 {
396 lengthMS = ~0;
397 }
398 setlength(lengthMS, fadeMS);
399
400 mipsinfo.i = initialPC;
401 mips_set_info(CPUINFO_INT_PC, &mipsinfo);
402 mipsinfo.i = initialSP;
403 mips_set_info(CPUINFO_INT_REGISTER + MIPS_R29, &mipsinfo);
404 mips_set_info(CPUINFO_INT_REGISTER + MIPS_R30, &mipsinfo);
405 mipsinfo.i = initialGP;
406 mips_set_info(CPUINFO_INT_REGISTER + MIPS_R28, &mipsinfo);
407
408 mips_execute(5000);
409
410 return AO_SUCCESS;
411
412 }
413 return AO_FAIL;
414 }
415
416 int32 psf_fill_info(ao_display_info *info)
417 {
418 if (c == NULL)
419 return AO_FAIL;
420
421 strcpy(info->title[1], "Name: ");
422 sprintf(info->info[1], "%s", c->inf_title);
423
424 strcpy(info->title[2], "Game: ");
425 sprintf(info->info[2], "%s", c->inf_game);
426
427 strcpy(info->title[3], "Artist: ");
428 sprintf(info->info[3], "%s", c->inf_artist);
429
430 strcpy(info->title[4], "Copyright: ");
431 sprintf(info->info[4], "%s", c->inf_copy);
432
433 strcpy(info->title[5], "Year: ");
434 sprintf(info->info[5], "%s", c->inf_year);
435
436 strcpy(info->title[6], "Length: ");
437 sprintf(info->info[6], "%s", c->inf_length);
438
439 strcpy(info->title[7], "Fade: ");
440 sprintf(info->info[7], "%s", c->inf_fade);
441
442 strcpy(info->title[8], "Ripper: ");
443 sprintf(info->info[8], "%s", psfby);
444
445 return AO_SUCCESS;
446 }