Mercurial > audlegacy-plugins
annotate src/xsf/vio2sf.c @ 3047:4434b4c4a715
ported EsounD plugin
author | Andrew O. Shadoura <bugzilla@tut.by> |
---|---|
date | Fri, 17 Apr 2009 16:17:10 +0300 |
parents | 6013ab159139 |
children |
rev | line source |
---|---|
2961 | 1 #include <stdio.h> |
2 #include <stdlib.h> | |
3 #include <string.h> | |
4 | |
5 #include "desmume/MMU.h" | |
6 #include "desmume/armcpu.h" | |
7 #include "desmume/NDSSystem.h" | |
8 #include "desmume/SPU.h" | |
9 #include "desmume/cp15.h" | |
10 | |
11 #include <zlib.h> | |
2965
6013ab159139
Make forward seeking work. Backwards seeking is still not working.
William Pitcock <nenolod@atheme.org>
parents:
2961
diff
changeset
|
12 #include <glib.h> |
2961 | 13 #include "tagget.h" |
14 #include "vio2sf.h" | |
15 | |
16 volatile BOOL execute = FALSE; | |
17 | |
18 static struct | |
19 { | |
20 unsigned char *rom; | |
21 unsigned char *state; | |
22 unsigned romsize; | |
23 unsigned statesize; | |
24 unsigned stateptr; | |
25 } loaderwork = {0, 0, 0, 0, 0}; | |
26 | |
27 static void load_term(void) | |
28 { | |
29 if (loaderwork.rom) | |
30 { | |
31 free(loaderwork.rom); | |
32 loaderwork.rom = 0; | |
33 } | |
34 loaderwork.romsize = 0; | |
35 if (loaderwork.state) | |
36 { | |
37 free(loaderwork.state); | |
38 loaderwork.state = 0; | |
39 } | |
40 loaderwork.statesize = 0; | |
41 } | |
42 | |
43 static int load_map(int issave, unsigned char *udata, unsigned usize) | |
44 { | |
45 unsigned char *iptr; | |
46 unsigned isize; | |
47 unsigned char *xptr; | |
48 unsigned xsize = getdwordle(udata + 4); | |
49 unsigned xofs = getdwordle(udata + 0); | |
50 if (issave) | |
51 { | |
52 iptr = loaderwork.state; | |
53 isize = loaderwork.statesize; | |
54 loaderwork.state = 0; | |
55 loaderwork.statesize = 0; | |
56 } | |
57 else | |
58 { | |
59 iptr = loaderwork.rom; | |
60 isize = loaderwork.romsize; | |
61 loaderwork.rom = 0; | |
62 loaderwork.romsize = 0; | |
63 } | |
64 if (!iptr) | |
65 { | |
66 iptr = malloc(xofs + xsize + 10); | |
67 if (!iptr) | |
68 return XSF_FALSE; | |
69 memset(iptr, 0, xofs + xsize + 10); | |
70 isize = xofs + xsize; | |
71 } | |
72 else if (isize < xofs + xsize) | |
73 { | |
74 unsigned rsize = xofs + xsize; | |
75 if (!issave) | |
76 { | |
77 rsize -= 1; | |
78 rsize |= rsize >> 1; | |
79 rsize |= rsize >> 2; | |
80 rsize |= rsize >> 4; | |
81 rsize |= rsize >> 8; | |
82 rsize |= rsize >> 16; | |
83 rsize += 1; | |
84 } | |
85 xptr = realloc(iptr, xofs + rsize + 10); | |
86 if (!xptr) | |
87 { | |
88 free(iptr); | |
89 return XSF_FALSE; | |
90 } | |
91 iptr = xptr; | |
92 isize = rsize; | |
93 } | |
94 memcpy(iptr + xofs, udata + 8, xsize); | |
95 if (issave) | |
96 { | |
97 loaderwork.state = iptr; | |
98 loaderwork.statesize = isize; | |
99 } | |
100 else | |
101 { | |
102 loaderwork.rom = iptr; | |
103 loaderwork.romsize = isize; | |
104 } | |
105 return XSF_TRUE; | |
106 } | |
107 | |
108 static int load_mapz(int issave, unsigned char *zdata, unsigned zsize, unsigned zcrc) | |
109 { | |
110 int ret; | |
111 int zerr; | |
112 uLongf usize = 8; | |
113 uLongf rsize = usize; | |
114 unsigned char *udata; | |
115 unsigned char *rdata; | |
116 | |
117 udata = malloc(usize); | |
118 if (!udata) | |
119 return XSF_FALSE; | |
120 | |
121 while (Z_OK != (zerr = uncompress(udata, &usize, zdata, zsize))) | |
122 { | |
123 if (Z_MEM_ERROR != zerr && Z_BUF_ERROR != zerr) | |
124 { | |
125 free(udata); | |
126 return XSF_FALSE; | |
127 } | |
128 if (usize >= 8) | |
129 { | |
130 usize = getdwordle(udata + 4) + 8; | |
131 if (usize < rsize) | |
132 { | |
133 rsize += rsize; | |
134 usize = rsize; | |
135 } | |
136 else | |
137 rsize = usize; | |
138 } | |
139 else | |
140 { | |
141 rsize += rsize; | |
142 usize = rsize; | |
143 } | |
144 free(udata); | |
145 udata = malloc(usize); | |
146 if (!udata) | |
147 return XSF_FALSE; | |
148 } | |
149 | |
150 rdata = realloc(udata, usize); | |
151 if (!rdata) | |
152 { | |
153 free(udata); | |
154 return XSF_FALSE; | |
155 } | |
156 | |
157 if (0) | |
158 { | |
159 unsigned ccrc = crc32(crc32(0L, Z_NULL, 0), rdata, usize); | |
160 if (ccrc != zcrc) | |
161 return XSF_FALSE; | |
162 } | |
163 | |
164 ret = load_map(issave, rdata, usize); | |
165 free(rdata); | |
166 return ret; | |
167 } | |
168 | |
169 static int load_psf_one(unsigned char *pfile, unsigned bytes) | |
170 { | |
171 unsigned char *ptr = pfile; | |
172 unsigned code_size; | |
173 unsigned resv_size; | |
174 unsigned code_crc; | |
175 if (bytes < 16 || getdwordle(ptr) != 0x24465350) | |
176 return XSF_FALSE; | |
177 | |
178 resv_size = getdwordle(ptr + 4); | |
179 code_size = getdwordle(ptr + 8); | |
180 code_crc = getdwordle(ptr + 12); | |
181 | |
182 if (resv_size) | |
183 { | |
184 unsigned resv_pos = 0; | |
185 ptr = pfile + 16; | |
186 if (16+ resv_size > bytes) | |
187 return XSF_FALSE; | |
188 while (resv_pos + 12 < resv_size) | |
189 { | |
190 unsigned save_size = getdwordle(ptr + resv_pos + 4); | |
191 unsigned save_crc = getdwordle(ptr + resv_pos + 8); | |
192 if (getdwordle(ptr + resv_pos + 0) == 0x45564153) | |
193 { | |
194 if (resv_pos + 12 + save_size > resv_size) | |
195 return XSF_FALSE; | |
196 if (!load_mapz(1, ptr + resv_pos + 12, save_size, save_crc)) | |
197 return XSF_FALSE; | |
198 } | |
199 resv_pos += 12 + save_size; | |
200 } | |
201 } | |
202 | |
203 if (code_size) | |
204 { | |
205 ptr = pfile + 16 + resv_size; | |
206 if (16 + resv_size + code_size > bytes) | |
207 return XSF_FALSE; | |
208 if (!load_mapz(0, ptr, code_size, code_crc)) | |
209 return XSF_FALSE; | |
210 } | |
211 | |
212 return XSF_TRUE; | |
213 } | |
214 | |
215 typedef struct | |
216 { | |
217 const char *tag; | |
218 int taglen; | |
219 int level; | |
220 int found; | |
221 } loadlibwork_t; | |
222 | |
223 static int load_libs(int level, void *pfile, unsigned bytes); | |
224 | |
225 static int load_psfcb(void *pWork, const char *pNameTop, const char *pNameEnd, const char *pValueTop, const char *pValueEnd) | |
226 { | |
227 loadlibwork_t *pwork = (loadlibwork_t *)pWork; | |
228 int ret = xsf_tagenum_callback_returnvaluecontinue; | |
229 if (pNameEnd - pNameTop == pwork->taglen && !strncasecmp(pNameTop, pwork->tag , pwork->taglen)) | |
230 { | |
231 unsigned l = pValueEnd - pValueTop; | |
232 char *lib = malloc(l + 1); | |
233 if (!lib) | |
234 { | |
235 ret = xsf_tagenum_callback_returnvaluebreak; | |
236 } | |
237 else | |
238 { | |
239 void *libbuf; | |
240 unsigned libsize; | |
241 memcpy(lib, pValueTop, l); | |
242 lib[l] = '\0'; | |
243 if (!xsf_get_lib(lib, &libbuf, &libsize)) | |
244 { | |
245 ret = xsf_tagenum_callback_returnvaluebreak; | |
246 } | |
247 else | |
248 { | |
249 if (!load_libs(pwork->level + 1, libbuf, libsize) || !load_psf_one(libbuf, libsize)) | |
250 ret = xsf_tagenum_callback_returnvaluebreak; | |
251 else | |
2965
6013ab159139
Make forward seeking work. Backwards seeking is still not working.
William Pitcock <nenolod@atheme.org>
parents:
2961
diff
changeset
|
252 { |
2961 | 253 pwork->found++; |
2965
6013ab159139
Make forward seeking work. Backwards seeking is still not working.
William Pitcock <nenolod@atheme.org>
parents:
2961
diff
changeset
|
254 free(libbuf); |
6013ab159139
Make forward seeking work. Backwards seeking is still not working.
William Pitcock <nenolod@atheme.org>
parents:
2961
diff
changeset
|
255 } |
2961 | 256 } |
257 free(lib); | |
258 } | |
259 } | |
260 return ret; | |
261 } | |
262 | |
263 static int load_libs(int level, void *pfile, unsigned bytes) | |
264 { | |
265 char tbuf[16]; | |
266 loadlibwork_t work; | |
267 int n = 1; | |
268 | |
269 if (level > 10) | |
270 return XSF_TRUE; | |
271 | |
272 work.level = level; | |
273 work.tag = "_lib"; | |
274 | |
275 do | |
276 { | |
277 work.taglen = strlen(work.tag); | |
278 work.found = 0; | |
279 | |
280 if (xsf_tagenum(load_psfcb, &work, pfile, bytes) < 0) | |
281 return XSF_FALSE; | |
282 | |
283 #ifdef HAVE_SPRINTF_S | |
284 sprintf_s(tbuf, sizeof(tbuf), "_lib%10d", ++n); | |
285 #else | |
286 sprintf(tbuf, "_lib%10d", ++n); | |
287 #endif | |
288 work.tag = tbuf; | |
289 } | |
290 while (work.found); | |
291 | |
292 return XSF_TRUE; | |
293 } | |
294 | |
295 static int load_psf(void *pfile, unsigned bytes) | |
296 { | |
297 load_term(); | |
298 | |
299 if (!load_libs(1, pfile, bytes) || !load_psf_one(pfile, bytes)) | |
300 return XSF_FALSE; | |
301 | |
302 return XSF_TRUE; | |
303 } | |
304 | |
305 static void load_getstateinit(unsigned ptr) | |
306 { | |
307 loaderwork.stateptr = ptr; | |
308 } | |
309 | |
310 static u16 getwordle(const unsigned char *pData) | |
311 { | |
312 return pData[0] | (((u16)pData[1]) << 8); | |
313 } | |
314 | |
315 static void load_getsta(Status_Reg *ptr, unsigned l) | |
316 { | |
317 unsigned s = l << 2; | |
318 unsigned i; | |
319 if ((loaderwork.stateptr > loaderwork.statesize) || ((loaderwork.stateptr + s) > loaderwork.statesize)) | |
320 return; | |
321 for (i = 0; i < l; i++) | |
322 { | |
323 u32 st = getdwordle(loaderwork.state + loaderwork.stateptr + (i << 2)); | |
324 ptr[i].bits.N = (st >> 31) & 1; | |
325 ptr[i].bits.Z = (st >> 30) & 1; | |
326 ptr[i].bits.C = (st >> 29) & 1; | |
327 ptr[i].bits.V = (st >> 28) & 1; | |
328 ptr[i].bits.Q = (st >> 27) & 1; | |
329 ptr[i].bits.RAZ = (st >> 8) & ((1 << 19) - 1); | |
330 ptr[i].bits.I = (st >> 7) & 1; | |
331 ptr[i].bits.F = (st >> 6) & 1; | |
332 ptr[i].bits.T = (st >> 5) & 1; | |
333 ptr[i].bits.mode = (st >> 0) & 0x1f; | |
334 } | |
335 loaderwork.stateptr += s; | |
336 } | |
337 | |
338 static void load_getbool(BOOL *ptr, unsigned l) | |
339 { | |
340 unsigned s = l << 2; | |
341 unsigned i; | |
342 if ((loaderwork.stateptr > loaderwork.statesize) || ((loaderwork.stateptr + s) > loaderwork.statesize)) | |
343 return; | |
344 for (i = 0; i < l; i++) | |
345 ptr[i] = (BOOL)getdwordle(loaderwork.state + loaderwork.stateptr + (i << 2)); | |
346 loaderwork.stateptr += s; | |
347 } | |
348 | |
349 #if defined(SIGNED_IS_NOT_2S_COMPLEMENT) | |
350 /* 2's complement */ | |
351 #define u32tos32(v) ((s32)((((s64)(v)) ^ 0x8000) - 0x8000)) | |
352 #else | |
353 /* 2's complement */ | |
354 #define u32tos32(v) ((s32)v) | |
355 #endif | |
356 | |
357 static void load_gets32(s32 *ptr, unsigned l) | |
358 { | |
359 unsigned s = l << 2; | |
360 unsigned i; | |
361 if ((loaderwork.stateptr > loaderwork.statesize) || ((loaderwork.stateptr + s) > loaderwork.statesize)) | |
362 return; | |
363 for (i = 0; i < l; i++) | |
364 ptr[i] = u32tos32(getdwordle(loaderwork.state + loaderwork.stateptr + (i << 2))); | |
365 loaderwork.stateptr += s; | |
366 } | |
367 | |
368 static void load_getu32(u32 *ptr, unsigned l) | |
369 { | |
370 unsigned s = l << 2; | |
371 unsigned i; | |
372 if ((loaderwork.stateptr > loaderwork.statesize) || ((loaderwork.stateptr + s) > loaderwork.statesize)) | |
373 return; | |
374 for (i = 0; i < l; i++) | |
375 ptr[i] = getdwordle(loaderwork.state + loaderwork.stateptr + (i << 2)); | |
376 loaderwork.stateptr += s; | |
377 } | |
378 | |
379 static void load_getu16(u16 *ptr, unsigned l) | |
380 { | |
381 unsigned s = l << 1; | |
382 unsigned i; | |
383 if ((loaderwork.stateptr > loaderwork.statesize) || ((loaderwork.stateptr + s) > loaderwork.statesize)) | |
384 return; | |
385 for (i = 0; i < l; i++) | |
386 ptr[i] = getwordle(loaderwork.state + loaderwork.stateptr + (i << 1)); | |
387 loaderwork.stateptr += s; | |
388 } | |
389 | |
390 static void load_getu8(u8 *ptr, unsigned l) | |
391 { | |
392 unsigned s = l; | |
393 unsigned i; | |
394 if ((loaderwork.stateptr > loaderwork.statesize) || ((loaderwork.stateptr + s) > loaderwork.statesize)) | |
395 return; | |
396 for (i = 0; i < l; i++) | |
397 ptr[i] = loaderwork.state[loaderwork.stateptr + i]; | |
398 loaderwork.stateptr += s; | |
399 } | |
400 | |
401 void gdb_stub_fix(armcpu_t *armcpu) | |
402 { | |
403 /* armcpu->R[15] = armcpu->instruct_adr; */ | |
404 armcpu->next_instruction = armcpu->instruct_adr; | |
405 if(armcpu->CPSR.bits.T == 0) | |
406 { | |
407 armcpu->instruction = MMU_read32_acl(armcpu->proc_ID, armcpu->next_instruction,CP15_ACCESS_EXECUTE); | |
408 armcpu->instruct_adr = armcpu->next_instruction; | |
409 armcpu->next_instruction += 4; | |
410 armcpu->R[15] = armcpu->next_instruction + 4; | |
411 } | |
412 else | |
413 { | |
414 armcpu->instruction = MMU_read16_acl(armcpu->proc_ID, armcpu->next_instruction,CP15_ACCESS_EXECUTE); | |
415 armcpu->instruct_adr = armcpu->next_instruction; | |
416 armcpu->next_instruction += 2; | |
417 armcpu->R[15] = armcpu->next_instruction + 2; | |
418 } | |
419 } | |
420 | |
421 static void load_setstate(void) | |
422 { | |
423 if (!loaderwork.statesize) | |
424 return; | |
425 | |
426 /* Skip over "Desmume Save File" crap */ | |
427 load_getstateinit(0x17); | |
428 | |
429 /* Read ARM7 cpu registers */ | |
430 load_getu32(&NDS_ARM7.proc_ID, 1); | |
431 load_getu32(&NDS_ARM7.instruction, 1); | |
432 load_getu32(&NDS_ARM7.instruct_adr, 1); | |
433 load_getu32(&NDS_ARM7.next_instruction, 1); | |
434 load_getu32(NDS_ARM7.R, 16); | |
435 load_getsta(&NDS_ARM7.CPSR, 1); | |
436 load_getsta(&NDS_ARM7.SPSR, 1); | |
437 load_getu32(&NDS_ARM7.R13_usr, 1); | |
438 load_getu32(&NDS_ARM7.R14_usr, 1); | |
439 load_getu32(&NDS_ARM7.R13_svc, 1); | |
440 load_getu32(&NDS_ARM7.R14_svc, 1); | |
441 load_getu32(&NDS_ARM7.R13_abt, 1); | |
442 load_getu32(&NDS_ARM7.R14_abt, 1); | |
443 load_getu32(&NDS_ARM7.R13_und, 1); | |
444 load_getu32(&NDS_ARM7.R14_und, 1); | |
445 load_getu32(&NDS_ARM7.R13_irq, 1); | |
446 load_getu32(&NDS_ARM7.R14_irq, 1); | |
447 load_getu32(&NDS_ARM7.R8_fiq, 1); | |
448 load_getu32(&NDS_ARM7.R9_fiq, 1); | |
449 load_getu32(&NDS_ARM7.R10_fiq, 1); | |
450 load_getu32(&NDS_ARM7.R11_fiq, 1); | |
451 load_getu32(&NDS_ARM7.R12_fiq, 1); | |
452 load_getu32(&NDS_ARM7.R13_fiq, 1); | |
453 load_getu32(&NDS_ARM7.R14_fiq, 1); | |
454 load_getsta(&NDS_ARM7.SPSR_svc, 1); | |
455 load_getsta(&NDS_ARM7.SPSR_abt, 1); | |
456 load_getsta(&NDS_ARM7.SPSR_und, 1); | |
457 load_getsta(&NDS_ARM7.SPSR_irq, 1); | |
458 load_getsta(&NDS_ARM7.SPSR_fiq, 1); | |
459 load_getu32(&NDS_ARM7.intVector, 1); | |
460 load_getu8(&NDS_ARM7.LDTBit, 1); | |
461 load_getbool(&NDS_ARM7.waitIRQ, 1); | |
462 load_getbool(&NDS_ARM7.wIRQ, 1); | |
463 load_getbool(&NDS_ARM7.wirq, 1); | |
464 | |
465 /* Read ARM9 cpu registers */ | |
466 load_getu32(&NDS_ARM9.proc_ID, 1); | |
467 load_getu32(&NDS_ARM9.instruction, 1); | |
468 load_getu32(&NDS_ARM9.instruct_adr, 1); | |
469 load_getu32(&NDS_ARM9.next_instruction, 1); | |
470 load_getu32(NDS_ARM9.R, 16); | |
471 load_getsta(&NDS_ARM9.CPSR, 1); | |
472 load_getsta(&NDS_ARM9.SPSR, 1); | |
473 load_getu32(&NDS_ARM9.R13_usr, 1); | |
474 load_getu32(&NDS_ARM9.R14_usr, 1); | |
475 load_getu32(&NDS_ARM9.R13_svc, 1); | |
476 load_getu32(&NDS_ARM9.R14_svc, 1); | |
477 load_getu32(&NDS_ARM9.R13_abt, 1); | |
478 load_getu32(&NDS_ARM9.R14_abt, 1); | |
479 load_getu32(&NDS_ARM9.R13_und, 1); | |
480 load_getu32(&NDS_ARM9.R14_und, 1); | |
481 load_getu32(&NDS_ARM9.R13_irq, 1); | |
482 load_getu32(&NDS_ARM9.R14_irq, 1); | |
483 load_getu32(&NDS_ARM9.R8_fiq, 1); | |
484 load_getu32(&NDS_ARM9.R9_fiq, 1); | |
485 load_getu32(&NDS_ARM9.R10_fiq, 1); | |
486 load_getu32(&NDS_ARM9.R11_fiq, 1); | |
487 load_getu32(&NDS_ARM9.R12_fiq, 1); | |
488 load_getu32(&NDS_ARM9.R13_fiq, 1); | |
489 load_getu32(&NDS_ARM9.R14_fiq, 1); | |
490 load_getsta(&NDS_ARM9.SPSR_svc, 1); | |
491 load_getsta(&NDS_ARM9.SPSR_abt, 1); | |
492 load_getsta(&NDS_ARM9.SPSR_und, 1); | |
493 load_getsta(&NDS_ARM9.SPSR_irq, 1); | |
494 load_getsta(&NDS_ARM9.SPSR_fiq, 1); | |
495 load_getu32(&NDS_ARM9.intVector, 1); | |
496 load_getu8(&NDS_ARM9.LDTBit, 1); | |
497 load_getbool(&NDS_ARM9.waitIRQ, 1); | |
498 load_getbool(&NDS_ARM9.wIRQ, 1); | |
499 load_getbool(&NDS_ARM9.wirq, 1); | |
500 | |
501 /* Read in other internal variables that are important */ | |
502 load_gets32(&nds.ARM9Cycle, 1); | |
503 load_gets32(&nds.ARM7Cycle, 1); | |
504 load_gets32(&nds.cycles, 1); | |
505 load_gets32(nds.timerCycle[0], 4); | |
506 load_gets32(nds.timerCycle[1], 4); | |
507 load_getbool(nds.timerOver[0], 4); | |
508 load_getbool(nds.timerOver[1], 4); | |
509 load_gets32(&nds.nextHBlank, 1); | |
510 load_getu32(&nds.VCount, 1); | |
511 load_getu32(&nds.old, 1); | |
512 load_gets32(&nds.diff, 1); | |
513 load_getbool(&nds.lignerendu, 1); | |
514 load_getu16(&nds.touchX, 1); | |
515 load_getu16(&nds.touchY, 1); | |
516 | |
517 /* Read in memory/registers specific to the ARM9 */ | |
518 load_getu8 (ARM9Mem.ARM9_ITCM, 0x8000); | |
519 load_getu8 (ARM9Mem.ARM9_DTCM, 0x4000); | |
520 load_getu8 (ARM9Mem.ARM9_WRAM, 0x1000000); | |
521 load_getu8 (ARM9Mem.MAIN_MEM, 0x400000); | |
522 load_getu8 (ARM9Mem.ARM9_REG, 0x10000); | |
523 load_getu8 (ARM9Mem.ARM9_VMEM, 0x800); | |
524 load_getu8 (ARM9Mem.ARM9_OAM, 0x800); | |
525 load_getu8 (ARM9Mem.ARM9_ABG, 0x80000); | |
526 load_getu8 (ARM9Mem.ARM9_BBG, 0x20000); | |
527 load_getu8 (ARM9Mem.ARM9_AOBJ, 0x40000); | |
528 load_getu8 (ARM9Mem.ARM9_BOBJ, 0x20000); | |
529 load_getu8 (ARM9Mem.ARM9_LCD, 0xA4000); | |
530 | |
531 /* Read in memory/registers specific to the ARM7 */ | |
532 load_getu8 (MMU.ARM7_ERAM, 0x10000); | |
533 load_getu8 (MMU.ARM7_REG, 0x10000); | |
534 load_getu8 (MMU.ARM7_WIRAM, 0x10000); | |
535 | |
536 /* Read in shared memory */ | |
537 load_getu8 (MMU.SWIRAM, 0x8000); | |
538 | |
539 #ifdef GDB_STUB | |
540 #else | |
541 gdb_stub_fix(&NDS_ARM9); | |
542 gdb_stub_fix(&NDS_ARM7); | |
543 #endif | |
544 } | |
545 | |
546 static struct | |
547 { | |
548 unsigned char *pcmbufalloc; | |
549 unsigned char *pcmbuftop; | |
550 unsigned filled; | |
551 unsigned used; | |
552 u32 bufferbytes; | |
553 u32 cycles; | |
554 int xfs_load; | |
555 int sync_type; | |
556 int arm7_clockdown_level; | |
557 int arm9_clockdown_level; | |
558 } sndifwork = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; | |
559 | |
560 static void SNDIFDeInit(void) | |
561 { | |
562 if (sndifwork.pcmbufalloc) | |
563 { | |
564 free(sndifwork.pcmbufalloc); | |
565 sndifwork.pcmbufalloc = 0; | |
566 sndifwork.pcmbuftop = 0; | |
567 sndifwork.bufferbytes = 0; | |
568 } | |
569 } | |
570 static int SNDIFInit(int buffersize) | |
571 { | |
572 u32 bufferbytes = buffersize * sizeof(s16); | |
573 SNDIFDeInit(); | |
574 sndifwork.pcmbufalloc = malloc(bufferbytes + 3); | |
575 if (!sndifwork.pcmbufalloc) | |
576 return -1; | |
577 sndifwork.pcmbuftop = sndifwork.pcmbufalloc + ((4 - (((int)sndifwork.pcmbufalloc) & 3)) & 3); | |
578 sndifwork.bufferbytes = bufferbytes; | |
579 sndifwork.filled = 0; | |
580 sndifwork.used = 0; | |
581 sndifwork.cycles = 0; | |
582 return 0; | |
583 } | |
584 static void SNDIFMuteAudio(void) | |
585 { | |
586 } | |
587 static void SNDIFUnMuteAudio(void) | |
588 { | |
589 } | |
590 static void SNDIFSetVolume(int volume) | |
591 { | |
592 } | |
593 static int SNDIFGetAudioSpace(void) | |
594 { | |
595 return sndifwork.bufferbytes >> 2; // bytes to samples | |
596 } | |
597 static void SNDIFUpdateAudio(s16 * buffer, u32 num_samples) | |
598 { | |
599 u32 num_bytes = num_samples << 2; | |
600 if (num_bytes > sndifwork.bufferbytes) num_bytes = sndifwork.bufferbytes; | |
601 memcpy(sndifwork.pcmbuftop, buffer, num_bytes); | |
602 sndifwork.filled = num_bytes; | |
603 sndifwork.used = 0; | |
604 } | |
605 #define VIO2SFSNDIFID 2 | |
606 static SoundInterface_struct VIO2SFSNDIF = | |
607 { | |
608 VIO2SFSNDIFID, | |
609 "vio2sf Sound Interface", | |
610 SNDIFInit, | |
611 SNDIFDeInit, | |
612 SNDIFUpdateAudio, | |
613 SNDIFGetAudioSpace, | |
614 SNDIFMuteAudio, | |
615 SNDIFUnMuteAudio, | |
616 SNDIFSetVolume | |
617 }; | |
618 | |
619 SoundInterface_struct *SNDCoreList[] = { | |
620 &VIO2SFSNDIF, | |
621 &SNDDummy, | |
622 NULL | |
623 }; | |
624 | |
625 static struct armcpu_ctrl_iface *arm9_ctrl_iface = 0; | |
626 static struct armcpu_ctrl_iface *arm7_ctrl_iface = 0; | |
627 | |
628 int xsf_start(void *pfile, unsigned bytes) | |
629 { | |
630 int frames = xsf_tagget_int("_frames", pfile, bytes, -1); | |
631 int clockdown = xsf_tagget_int("_clockdown", pfile, bytes, 0); | |
632 sndifwork.sync_type = xsf_tagget_int("_vio2sf_sync_type", pfile, bytes, 0); | |
633 sndifwork.arm9_clockdown_level = xsf_tagget_int("_vio2sf_arm9_clockdown_level", pfile, bytes, clockdown); | |
634 sndifwork.arm7_clockdown_level = xsf_tagget_int("_vio2sf_arm7_clockdown_level", pfile, bytes, clockdown); | |
635 | |
636 sndifwork.xfs_load = 0; | |
2965
6013ab159139
Make forward seeking work. Backwards seeking is still not working.
William Pitcock <nenolod@atheme.org>
parents:
2961
diff
changeset
|
637 printf("load_psf... "); |
2961 | 638 if (!load_psf(pfile, bytes)) |
639 return XSF_FALSE; | |
2965
6013ab159139
Make forward seeking work. Backwards seeking is still not working.
William Pitcock <nenolod@atheme.org>
parents:
2961
diff
changeset
|
640 printf("ok!\n"); |
2961 | 641 |
642 #ifdef GDB_STUB | |
643 if (NDS_Init(&arm9_base_memory_iface, &arm9_ctrl_iface, &arm7_base_memory_iface, &arm7_ctrl_iface)) | |
644 #else | |
645 if (NDS_Init()) | |
646 #endif | |
647 return XSF_FALSE; | |
648 | |
649 SPU_ChangeSoundCore(VIO2SFSNDIFID, 737); | |
650 | |
651 execute = FALSE; | |
652 | |
653 MMU_unsetRom(); | |
654 if (loaderwork.rom) | |
655 { | |
656 NDS_SetROM(loaderwork.rom, loaderwork.romsize - 1); | |
657 } | |
658 | |
659 NDS_Reset(); | |
660 | |
661 execute = TRUE; | |
662 | |
663 if (loaderwork.state) | |
664 { | |
665 armcp15_t *c9 = (armcp15_t *)NDS_ARM9.coproc[15]; | |
666 int proc; | |
667 if (frames == -1) | |
668 { | |
669 | |
670 /* set initial ARM9 coprocessor state */ | |
671 | |
672 armcp15_moveARM2CP(c9, 0x00000000, 0x01, 0x00, 0, 0); | |
673 armcp15_moveARM2CP(c9, 0x00000000, 0x07, 0x05, 0, 0); | |
674 armcp15_moveARM2CP(c9, 0x00000000, 0x07, 0x06, 0, 0); | |
675 armcp15_moveARM2CP(c9, 0x00000000, 0x07, 0x0a, 0, 4); | |
676 armcp15_moveARM2CP(c9, 0x04000033, 0x06, 0x00, 0, 4); | |
677 armcp15_moveARM2CP(c9, 0x0200002d, 0x06, 0x01, 0, 0); | |
678 armcp15_moveARM2CP(c9, 0x027e0021, 0x06, 0x02, 0, 0); | |
679 armcp15_moveARM2CP(c9, 0x08000035, 0x06, 0x03, 0, 0); | |
680 armcp15_moveARM2CP(c9, 0x027e001b, 0x06, 0x04, 0, 0); | |
681 armcp15_moveARM2CP(c9, 0x0100002f, 0x06, 0x05, 0, 0); | |
682 armcp15_moveARM2CP(c9, 0xffff001d, 0x06, 0x06, 0, 0); | |
683 armcp15_moveARM2CP(c9, 0x027ff017, 0x06, 0x07, 0, 0); | |
684 armcp15_moveARM2CP(c9, 0x00000020, 0x09, 0x01, 0, 1); | |
685 | |
686 armcp15_moveARM2CP(c9, 0x027e000a, 0x09, 0x01, 0, 0); | |
687 | |
688 armcp15_moveARM2CP(c9, 0x00000042, 0x02, 0x00, 0, 1); | |
689 armcp15_moveARM2CP(c9, 0x00000042, 0x02, 0x00, 0, 0); | |
690 armcp15_moveARM2CP(c9, 0x00000002, 0x03, 0x00, 0, 0); | |
691 armcp15_moveARM2CP(c9, 0x05100011, 0x05, 0x00, 0, 3); | |
692 armcp15_moveARM2CP(c9, 0x15111011, 0x05, 0x00, 0, 2); | |
693 armcp15_moveARM2CP(c9, 0x07dd1e10, 0x01, 0x00, 0, 0); | |
694 armcp15_moveARM2CP(c9, 0x0005707d, 0x01, 0x00, 0, 0); | |
695 | |
696 armcp15_moveARM2CP(c9, 0x00000000, 0x07, 0x0a, 0, 4); | |
697 armcp15_moveARM2CP(c9, 0x02004000, 0x07, 0x05, 0, 1); | |
698 armcp15_moveARM2CP(c9, 0x02004000, 0x07, 0x0e, 0, 1); | |
699 | |
700 /* set initial timer state */ | |
701 | |
702 MMU_write16(0, REG_TM0CNTL, 0x0000); | |
703 MMU_write16(0, REG_TM0CNTH, 0x00C1); | |
704 MMU_write16(1, REG_TM0CNTL, 0x0000); | |
705 MMU_write16(1, REG_TM0CNTH, 0x00C1); | |
706 MMU_write16(1, REG_TM1CNTL, 0xf7e7); | |
707 MMU_write16(1, REG_TM1CNTH, 0x00C1); | |
708 | |
709 /* set initial interrupt state */ | |
710 | |
711 MMU.reg_IME[0] = 0x00000001; | |
712 MMU.reg_IE[0] = 0x00042001; | |
713 MMU.reg_IME[1] = 0x00000001; | |
714 MMU.reg_IE[1] = 0x0104009d; | |
715 } | |
716 else if (frames > 0) | |
717 { | |
718 /* execute boot code */ | |
719 int i; | |
720 for (i=0; i<frames; i++) | |
721 NDS_exec_frame(0, 0); | |
722 i = 0; | |
723 } | |
724 | |
725 /* load state */ | |
726 | |
727 load_setstate(); | |
728 free(loaderwork.state); | |
729 loaderwork.state = 0; | |
730 | |
731 if (frames == -1) | |
732 { | |
733 armcp15_moveARM2CP(c9, (NDS_ARM9.R13_irq & 0x0fff0000) | 0x0a, 0x09, 0x01, 0, 0); | |
734 } | |
735 | |
736 /* restore timer state */ | |
737 | |
738 for (proc = 0; proc < 2; proc++) | |
739 { | |
740 MMU_write16(proc, REG_TM0CNTH, T1ReadWord(MMU.MMU_MEM[proc][0x40], REG_TM0CNTH & 0xFFF)); | |
741 MMU_write16(proc, REG_TM1CNTH, T1ReadWord(MMU.MMU_MEM[proc][0x40], REG_TM1CNTH & 0xFFF)); | |
742 MMU_write16(proc, REG_TM2CNTH, T1ReadWord(MMU.MMU_MEM[proc][0x40], REG_TM2CNTH & 0xFFF)); | |
743 MMU_write16(proc, REG_TM3CNTH, T1ReadWord(MMU.MMU_MEM[proc][0x40], REG_TM3CNTH & 0xFFF)); | |
744 } | |
745 } | |
746 else if (frames > 0) | |
747 { | |
748 /* skip 1 sec */ | |
749 int i; | |
750 for (i=0; i<frames; i++) | |
751 NDS_exec_frame(0, 0); | |
752 } | |
753 execute = TRUE; | |
754 sndifwork.xfs_load = 1; | |
755 return XSF_TRUE; | |
756 } | |
757 | |
758 int xsf_gen(void *pbuffer, unsigned samples) | |
759 { | |
760 unsigned char *ptr = pbuffer; | |
761 unsigned bytes = samples <<= 2; | |
762 if (!sndifwork.xfs_load) return 0; | |
763 while (bytes) | |
764 { | |
765 unsigned remainbytes = sndifwork.filled - sndifwork.used; | |
766 if (remainbytes > 0) | |
767 { | |
768 if (remainbytes > bytes) | |
769 { | |
770 memcpy(ptr, sndifwork.pcmbuftop + sndifwork.used, bytes); | |
771 sndifwork.used += bytes; | |
772 ptr += bytes; | |
773 remainbytes -= bytes; /**/ | |
774 bytes = 0; /**/ | |
775 break; | |
776 } | |
777 else | |
778 { | |
779 memcpy(ptr, sndifwork.pcmbuftop + sndifwork.used, remainbytes); | |
780 sndifwork.used += remainbytes; | |
781 ptr += remainbytes; | |
782 bytes -= remainbytes; | |
783 remainbytes = 0; | |
784 } | |
785 } | |
786 if (remainbytes == 0) | |
787 { | |
788 | |
789 #define HBASE_CYCLES 33509300.322234 | |
790 #define VBASE_CYCLES (((double)HBASE_CYCLES) / 100) | |
791 #define HSAMPLES ((u32)((44100.0 * 6 * (99 + 256)) / HBASE_CYCLES)) | |
792 #define VSAMPLES ((u32)((44100.0 * 6 * (99 + 256) * 263) / HBASE_CYCLES)) | |
793 | |
794 int numsamples; | |
795 if (sndifwork.sync_type == 1) | |
796 { | |
797 /* vsync */ | |
798 sndifwork.cycles += (441 * 6 * (99 + 256) * 263); | |
799 if (sndifwork.cycles >= (u32)(VBASE_CYCLES * (VSAMPLES + 1))) | |
800 { | |
801 numsamples = (VSAMPLES + 1); | |
802 sndifwork.cycles -= (u32)(VBASE_CYCLES * (VSAMPLES + 1)); | |
803 } | |
804 else | |
805 { | |
806 numsamples = (VSAMPLES + 0); | |
807 sndifwork.cycles -= (u32)(VBASE_CYCLES * (VSAMPLES + 0)); | |
808 } | |
809 NDS_exec_frame(sndifwork.arm9_clockdown_level, sndifwork.arm7_clockdown_level); | |
810 } | |
811 else | |
812 { | |
813 /* hsync */ | |
814 sndifwork.cycles += (44100 * 6 * (99 + 256)); | |
815 if (sndifwork.cycles >= (u32)(HBASE_CYCLES * (HSAMPLES + 1))) | |
816 { | |
817 numsamples = (HSAMPLES + 1); | |
818 sndifwork.cycles -= (u32)(HBASE_CYCLES * (HSAMPLES + 1)); | |
819 } | |
820 else | |
821 { | |
822 numsamples = (HSAMPLES + 0); | |
823 sndifwork.cycles -= (u32)(HBASE_CYCLES * (HSAMPLES + 0)); | |
824 } | |
825 NDS_exec_hframe(sndifwork.arm9_clockdown_level, sndifwork.arm7_clockdown_level); | |
826 } | |
827 SPU_EmulateSamples(numsamples); | |
828 } | |
829 } | |
830 return ptr - (unsigned char *)pbuffer; | |
831 } | |
832 | |
833 void xsf_term(void) | |
834 { | |
835 MMU_unsetRom(); | |
836 NDS_DeInit(); | |
837 load_term(); | |
838 } |