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