src/ds/core.c (view raw)
1/* Copyright (c) 2013-2016 Jeffrey Pfau
2 *
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6#include <mgba/ds/core.h>
7
8#include <mgba/core/cheats.h>
9#include <mgba/core/core.h>
10#include <mgba/core/log.h>
11#include <mgba/internal/arm/debugger/debugger.h>
12#include <mgba/internal/debugger/symbols.h>
13#include <mgba/internal/ds/ds.h>
14#include <mgba/internal/ds/extra/cli.h>
15#include <mgba/internal/ds/gx/software.h>
16#include <mgba/internal/ds/input.h>
17#include <mgba/internal/ds/renderers/software.h>
18#include <mgba-util/elf-read.h>
19#include <mgba-util/memory.h>
20#include <mgba-util/patch.h>
21#include <mgba-util/vfs.h>
22
23const static struct mCoreChannelInfo _DSVideoLayers[] = {
24 { 0, "abg0", "A BG0", "2D/3D" },
25 { 1, "abg1", "A BG1", NULL },
26 { 2, "abg2", "A BG2", NULL },
27 { 3, "abg3", "A BG3", NULL },
28 { 4, "aobj", "A OBJ", NULL },
29 { 10, "bbg0", "B BG0", "2D/3D" },
30 { 11, "bbg1", "B BG1", NULL },
31 { 12, "bbg2", "B BG2", NULL },
32 { 13, "bbg3", "B BG3", NULL },
33 { 14, "bobj", "B OBJ", NULL },
34};
35
36const static struct mCoreChannelInfo _DSAudioChannels[] = {
37 { 0, "ch00", "Channel 0", NULL },
38 { 1, "ch01", "Channel 1", NULL },
39 { 2, "ch02", "Channel 2", NULL },
40 { 3, "ch03", "Channel 3", NULL },
41 { 4, "ch04", "Channel 4", NULL },
42 { 5, "ch05", "Channel 5", NULL },
43 { 6, "ch06", "Channel 6", NULL },
44 { 7, "ch07", "Channel 7", NULL },
45 { 8, "ch08", "Channel 8", NULL },
46 { 9, "ch09", "Channel 9", NULL },
47 { 10, "ch10", "Channel 10", NULL },
48 { 11, "ch11", "Channel 11", NULL },
49 { 12, "ch12", "Channel 12", NULL },
50 { 13, "ch13", "Channel 13", NULL },
51 { 14, "ch14", "Channel 14", NULL },
52 { 15, "ch15", "Channel 15", NULL },
53};
54
55struct DSCore {
56 struct mCore d;
57 struct ARMCore* arm7;
58 struct ARMCore* arm9;
59 struct DSVideoSoftwareRenderer renderer;
60 struct DSGXSoftwareRenderer gxRenderer;
61 int keys;
62 int cursorX;
63 int cursorY;
64 bool touchDown;
65 struct mCPUComponent* components[CPU_COMPONENT_MAX];
66 struct mDebuggerPlatform* debuggerPlatform;
67 struct mCheatDevice* cheatDevice;
68};
69
70static bool _DSCoreInit(struct mCore* core) {
71 struct DSCore* dscore = (struct DSCore*) core;
72
73 struct ARMCore* arm7 = anonymousMemoryMap(sizeof(struct ARMCore));
74 struct ARMCore* arm9 = anonymousMemoryMap(sizeof(struct ARMCore));
75 struct DS* ds = anonymousMemoryMap(sizeof(struct DS));
76 if (!arm7 || !arm9 || !ds) {
77 free(arm7);
78 free(arm9);
79 free(ds);
80 return false;
81 }
82 core->cpu = arm9;
83 core->board = ds;
84 core->debugger = NULL;
85 dscore->arm7 = arm7;
86 dscore->arm9 = arm9;
87 dscore->debuggerPlatform = NULL;
88 dscore->cheatDevice = NULL;
89
90 DSCreate(ds);
91 memset(dscore->components, 0, sizeof(dscore->components));
92 ARMSetComponents(arm7, &ds->d, CPU_COMPONENT_MAX, dscore->components);
93 ARMSetComponents(arm9, &ds->d, CPU_COMPONENT_MAX, dscore->components);
94 ARMInit(arm7);
95 ARMInit(arm9);
96
97 DSVideoSoftwareRendererCreate(&dscore->renderer);
98 DSGXSoftwareRendererCreate(&dscore->gxRenderer);
99 dscore->renderer.outputBuffer = NULL;
100
101 dscore->keys = 0;
102 ds->keySource = &dscore->keys;
103 dscore->cursorX = 0;
104 ds->cursorSourceX = &dscore->cursorX;
105 dscore->cursorY = 0;
106 ds->cursorSourceY = &dscore->cursorY;
107 dscore->touchDown = false;
108 ds->touchSource = &dscore->touchDown;
109
110#if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2
111 mDirectorySetInit(&core->dirs);
112#endif
113
114#ifndef MINIMAL_CORE
115 core->inputInfo = &DSInputInfo; // TODO: GBInputInfo
116#endif
117
118 return true;
119}
120
121static void _DSCoreDeinit(struct mCore* core) {
122 struct DSCore* dscore = (struct DSCore*) core;
123 ARMDeinit(dscore->arm7);
124 ARMDeinit(dscore->arm9);
125 DSDestroy(core->board);
126 mappedMemoryFree(dscore->arm7, sizeof(struct ARMCore));
127 mappedMemoryFree(dscore->arm9, sizeof(struct ARMCore));
128 mappedMemoryFree(core->board, sizeof(struct DS));
129#if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2
130 mDirectorySetDeinit(&core->dirs);
131#endif
132
133 free(dscore->debuggerPlatform);
134 if (dscore->cheatDevice) {
135 mCheatDeviceDestroy(dscore->cheatDevice);
136 }
137 free(dscore->cheatDevice);
138 free(core);
139}
140
141static enum mPlatform _DSCorePlatform(const struct mCore* core) {
142 UNUSED(core);
143 return PLATFORM_DS;
144}
145
146static bool _DSCoreSupportsFeature(const struct mCore* core, enum mCoreFeature feature) {
147 UNUSED(core);
148 switch (feature) {
149 case mCORE_FEATURE_OPENGL:
150 return false;
151 default:
152 return false;
153 }
154}
155
156static void _DSCoreSetSync(struct mCore* core, struct mCoreSync* sync) {
157 struct DS* ds = core->board;
158 ds->sync = sync;
159}
160
161static void _DSCoreLoadConfig(struct mCore* core, const struct mCoreConfig* config) {
162 struct DS* ds = core->board;
163 struct VFile* bios = NULL;
164
165 mCoreConfigCopyValue(&core->config, config, "ds.bios7");
166 mCoreConfigCopyValue(&core->config, config, "ds.bios9");
167 mCoreConfigCopyValue(&core->config, config, "ds.firmware");
168}
169
170static void _DSCoreDesiredVideoDimensions(struct mCore* core, unsigned* width, unsigned* height) {
171 UNUSED(core);
172 *width = DS_VIDEO_HORIZONTAL_PIXELS;
173 *height = DS_VIDEO_VERTICAL_PIXELS * 2;
174}
175
176static void _DSCoreSetVideoBuffer(struct mCore* core, color_t* buffer, size_t stride) {
177 struct DSCore* dscore = (struct DSCore*) core;
178 dscore->renderer.outputBuffer = buffer;
179 dscore->renderer.outputBufferStride = stride;
180}
181
182static void _DSCoreGetPixels(struct mCore* core, const void** buffer, size_t* stride) {
183 struct DSCore* dscore = (struct DSCore*) core;
184 dscore->renderer.d.getPixels(&dscore->renderer.d, stride, buffer);
185}
186
187static void _DSCorePutPixels(struct mCore* core, const void* buffer, size_t stride) {
188 struct DSCore* dscore = (struct DSCore*) core;
189 dscore->renderer.d.putPixels(&dscore->renderer.d, stride, buffer);
190}
191
192static struct blip_t* _DSCoreGetAudioChannel(struct mCore* core, int ch) {
193 struct DS* ds = core->board;
194 switch (ch) {
195 case 0:
196 return ds->audio.left;
197 case 1:
198 return ds->audio.right;
199 default:
200 return NULL;
201 }
202}
203
204static void _DSCoreSetAudioBufferSize(struct mCore* core, size_t samples) {
205 struct DS* ds = core->board;
206 DSAudioResizeBuffer(&ds->audio, samples);
207}
208
209static size_t _DSCoreGetAudioBufferSize(struct mCore* core) {
210 struct DS* ds = core->board;
211 return ds->audio.samples;
212}
213
214static void _DSCoreAddCoreCallbacks(struct mCore* core, struct mCoreCallbacks* coreCallbacks) {
215 struct DS* ds = core->board;
216 *mCoreCallbacksListAppend(&ds->coreCallbacks) = *coreCallbacks;
217}
218
219static void _DSCoreClearCoreCallbacks(struct mCore* core) {
220 struct DS* ds = core->board;
221 mCoreCallbacksListClear(&ds->coreCallbacks);
222}
223
224static void _DSCoreSetAVStream(struct mCore* core, struct mAVStream* stream) {
225 struct DS* ds = core->board;
226 ds->stream = stream;
227 if (stream && stream->videoDimensionsChanged) {
228 stream->videoDimensionsChanged(stream, DS_VIDEO_HORIZONTAL_PIXELS, DS_VIDEO_VERTICAL_PIXELS * 2);
229 }
230 if (stream && stream->videoFrameRateChanged) {
231 stream->videoFrameRateChanged(stream, core->frameCycles(core), core->frequency(core));
232 }
233}
234
235static bool _DSCoreLoadROM(struct mCore* core, struct VFile* vf) {
236 return DSLoadROM(core->board, vf);
237}
238
239static bool _DSCoreLoadBIOS(struct mCore* core, struct VFile* vf, int type) {
240 UNUSED(type);
241 return DSLoadBIOS(core->board, vf);
242}
243
244static bool _DSCoreLoadSave(struct mCore* core, struct VFile* vf) {
245 return DSLoadSave(core->board, vf);
246}
247
248static bool _DSCoreLoadPatch(struct mCore* core, struct VFile* vf) {
249 return false;
250}
251
252static void _DSCoreUnloadROM(struct mCore* core) {
253 return DSUnloadROM(core->board);
254}
255
256static void _DSCoreChecksum(const struct mCore* core, void* data, enum mCoreChecksumType type) {
257}
258
259static void _DSCoreReset(struct mCore* core) {
260 struct DSCore* dscore = (struct DSCore*) core;
261 struct DS* ds = (struct DS*) core->board;
262
263 if (dscore->renderer.outputBuffer) {
264 struct DSVideoRenderer* renderer = &dscore->renderer.d;
265 DSVideoAssociateRenderer(&ds->video, renderer);
266
267 struct DSGXRenderer* gxRenderer = &dscore->gxRenderer.d;
268 DSGXAssociateRenderer(&ds->gx, gxRenderer);
269 }
270
271#if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2
272 struct VFile* bios7 = NULL;
273 struct VFile* bios9 = NULL;
274 struct VFile* firm = NULL;
275 if (core->opts.useBios) {
276 bool found7 = false;
277 bool found9 = false;
278 bool foundFirm = false;
279
280 if (!found7) {
281 const char* configPath = mCoreConfigGetValue(&core->config, "ds.bios7");
282 bios7 = VFileOpen(configPath, O_RDONLY);
283 if (bios7 && DSIsBIOS7(bios7)) {
284 found7 = true;
285 } else if (bios7) {
286 bios7->close(bios7);
287 bios7 = NULL;
288 }
289 }
290
291 if (!found9) {
292 const char* configPath = mCoreConfigGetValue(&core->config, "ds.bios9");
293 bios9 = VFileOpen(configPath, O_RDONLY);
294 if (bios9 && DSIsBIOS9(bios9)) {
295 found9 = true;
296 } else if (bios9) {
297 bios9->close(bios9);
298 bios9 = NULL;
299 }
300 }
301
302 if (!foundFirm) {
303 const char* configPath = mCoreConfigGetValue(&core->config, "ds.firmware");
304 firm = VFileOpen(configPath, O_RDONLY);
305 if (firm && DSIsFirmware(firm)) {
306 foundFirm = true;
307 } else if (firm) {
308 firm->close(firm);
309 firm = NULL;
310 }
311 }
312
313 if (!found7) {
314 char path[PATH_MAX];
315 mCoreConfigDirectory(path, PATH_MAX);
316 strncat(path, PATH_SEP "ds7_bios.bin", PATH_MAX - strlen(path));
317 bios7 = VFileOpen(path, O_RDONLY);
318 }
319
320 if (!found9) {
321 char path[PATH_MAX];
322 mCoreConfigDirectory(path, PATH_MAX);
323 strncat(path, PATH_SEP "ds9_bios.bin", PATH_MAX - strlen(path));
324 bios9 = VFileOpen(path, O_RDONLY);
325 }
326
327 if (!foundFirm) {
328 char path[PATH_MAX];
329 mCoreConfigDirectory(path, PATH_MAX);
330 strncat(path, PATH_SEP "ds_firmware.bin", PATH_MAX - strlen(path));
331 firm = VFileOpen(path, O_RDWR);
332 }
333 }
334 if (bios7) {
335 DSLoadBIOS(ds, bios7);
336 }
337 if (bios9) {
338 DSLoadBIOS(ds, bios9);
339 }
340 if (firm) {
341 DSLoadFirmware(ds, firm);
342 }
343#endif
344
345 ARMReset(ds->ds7.cpu);
346 ARMReset(ds->ds9.cpu);
347}
348
349static void _DSCoreRunFrame(struct mCore* core) {
350 struct DSCore* dscore = (struct DSCore*) core;
351 struct DS* ds = core->board;
352 int32_t frameCounter = ds->video.frameCounter;
353 while (ds->video.frameCounter == frameCounter) {
354 DSRunLoop(core->board);
355 }
356}
357
358static void _DSCoreRunLoop(struct mCore* core) {
359 DSRunLoop(core->board);
360}
361
362static void _DSCoreStep(struct mCore* core) {
363 struct DSCore* dscore = (struct DSCore*) core;
364 if (core->cpu == dscore->arm9) {
365 DS9Step(core->board);
366 } else {
367 DS7Step(core->board);
368 }
369}
370
371static size_t _DSCoreStateSize(struct mCore* core) {
372 UNUSED(core);
373 return 0;
374}
375
376static bool _DSCoreLoadState(struct mCore* core, const void* state) {
377 return false;
378}
379
380static bool _DSCoreSaveState(struct mCore* core, void* state) {
381 return false;
382}
383
384static void _DSCoreSetKeys(struct mCore* core, uint32_t keys) {
385 struct DSCore* dscore = (struct DSCore*) core;
386 dscore->keys = keys;
387}
388
389static void _DSCoreAddKeys(struct mCore* core, uint32_t keys) {
390 struct DSCore* dscore = (struct DSCore*) core;
391 dscore->keys |= keys;
392}
393
394static void _DSCoreClearKeys(struct mCore* core, uint32_t keys) {
395 struct DSCore* dscore = (struct DSCore*) core;
396 dscore->keys &= ~keys;
397}
398
399static void _DSCoreSetCursorLocation(struct mCore* core, int x, int y) {
400 struct DSCore* dscore = (struct DSCore*) core;
401 dscore->cursorX = x;
402 dscore->cursorY = y - DS_VIDEO_VERTICAL_PIXELS;
403 if (dscore->cursorY < 0) {
404 dscore->cursorY = 0;
405 } else if (dscore->cursorY >= DS_VIDEO_VERTICAL_PIXELS) {
406 dscore->cursorY = DS_VIDEO_VERTICAL_PIXELS - 1;
407 }
408 if (dscore->cursorX < 0) {
409 dscore->cursorX = 0;
410 } else if (dscore->cursorX >= DS_VIDEO_HORIZONTAL_PIXELS) {
411 dscore->cursorX = DS_VIDEO_HORIZONTAL_PIXELS - 1;
412 }
413}
414
415static void _DSCoreSetCursorDown(struct mCore* core, bool down) {
416 struct DSCore* dscore = (struct DSCore*) core;
417 dscore->touchDown = down;
418}
419
420static int32_t _DSCoreFrameCounter(const struct mCore* core) {
421 struct DS* ds = core->board;
422 return ds->video.frameCounter;
423}
424
425static int32_t _DSCoreFrameCycles(const struct mCore* core) {
426 UNUSED(core);
427 return DS_VIDEO_TOTAL_LENGTH * 2;
428}
429
430static int32_t _DSCoreFrequency(const struct mCore* core) {
431 UNUSED(core);
432 return DS_ARM946ES_FREQUENCY;
433}
434
435static void _DSCoreGetGameTitle(const struct mCore* core, char* title) {
436 DSGetGameTitle(core->board, title);
437}
438
439static void _DSCoreGetGameCode(const struct mCore* core, char* title) {
440 DSGetGameCode(core->board, title);
441}
442
443static void _DSCoreSetPeripheral(struct mCore* core, int type, void* periph) {
444 struct DS* ds = core->board;
445 switch (type) {
446 case mPERIPH_RUMBLE:
447 ds->rumble = periph;
448 break;
449 default:
450 break;
451 }
452}
453
454static uint32_t _DSCoreBusRead8(struct mCore* core, uint32_t address) {
455 struct ARMCore* cpu = core->cpu;
456 return cpu->memory.load8(cpu, address, 0);
457}
458
459static uint32_t _DSCoreBusRead16(struct mCore* core, uint32_t address) {
460 struct ARMCore* cpu = core->cpu;
461 return cpu->memory.load16(cpu, address, 0);
462
463}
464
465static uint32_t _DSCoreBusRead32(struct mCore* core, uint32_t address) {
466 struct ARMCore* cpu = core->cpu;
467 return cpu->memory.load32(cpu, address, 0);
468}
469
470static void _DSCoreBusWrite8(struct mCore* core, uint32_t address, uint8_t value) {
471 struct ARMCore* cpu = core->cpu;
472 cpu->memory.store8(cpu, address, value, 0);
473}
474
475static void _DSCoreBusWrite16(struct mCore* core, uint32_t address, uint16_t value) {
476 struct ARMCore* cpu = core->cpu;
477 cpu->memory.store16(cpu, address, value, 0);
478}
479
480static void _DSCoreBusWrite32(struct mCore* core, uint32_t address, uint32_t value) {
481 struct ARMCore* cpu = core->cpu;
482 cpu->memory.store32(cpu, address, value, 0);
483}
484
485static uint32_t _DSCoreRawRead8(struct mCore* core, uint32_t address, int segment) {
486 // TODO: Raw
487 struct ARMCore* cpu = core->cpu;
488 return cpu->memory.load8(cpu, address, 0);
489}
490
491static uint32_t _DSCoreRawRead16(struct mCore* core, uint32_t address, int segment) {
492 // TODO: Raw
493 struct ARMCore* cpu = core->cpu;
494 return cpu->memory.load16(cpu, address, 0);
495}
496
497static uint32_t _DSCoreRawRead32(struct mCore* core, uint32_t address, int segment) {
498 // TODO: Raw
499 struct ARMCore* cpu = core->cpu;
500 return cpu->memory.load32(cpu, address, 0);
501}
502
503static void _DSCoreRawWrite8(struct mCore* core, uint32_t address, int segment, uint8_t value) {
504}
505
506static void _DSCoreRawWrite16(struct mCore* core, uint32_t address, int segment, uint16_t value) {
507}
508
509static void _DSCoreRawWrite32(struct mCore* core, uint32_t address, int segment, uint32_t value) {
510}
511
512#ifdef USE_DEBUGGERS
513static bool _DSCoreSupportsDebuggerType(struct mCore* core, enum mDebuggerType type) {
514 UNUSED(core);
515 switch (type) {
516 case DEBUGGER_CLI:
517 return true;
518#ifdef USE_GDB_STUB
519 case DEBUGGER_GDB:
520 return true;
521#endif
522 default:
523 return false;
524 }
525}
526
527static struct mDebuggerPlatform* _DSCoreDebuggerPlatform(struct mCore* core) {
528 struct DSCore* dscore = (struct DSCore*) core;
529 if (!dscore->debuggerPlatform) {
530 dscore->debuggerPlatform = ARMDebuggerPlatformCreate();
531 }
532 return dscore->debuggerPlatform;
533}
534
535static struct CLIDebuggerSystem* _DSCoreCliDebuggerSystem(struct mCore* core) {
536 return &DSCLIDebuggerCreate(core)->d;
537}
538
539static void _DSCoreAttachDebugger(struct mCore* core, struct mDebugger* debugger) {
540 if (core->debugger) {
541 DSDetachDebugger(core->board);
542 }
543 DSAttachDebugger(core->board, debugger);
544 core->debugger = debugger;
545}
546
547static void _DSCoreDetachDebugger(struct mCore* core) {
548 DSDetachDebugger(core->board);
549 core->debugger = NULL;
550}
551
552static void _DSCoreLoadSymbols(struct mCore* core, struct VFile* vf) {
553#ifdef USE_ELF
554 bool closeAfter = false;
555 core->symbolTable = mDebuggerSymbolTableCreate();
556#if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2
557 if (!vf) {
558 closeAfter = true;
559 vf = mDirectorySetOpenSuffix(&core->dirs, core->dirs.base, ".elf", O_RDONLY);
560 }
561#endif
562 if (!vf) {
563 return;
564 }
565 struct ELF* elf = ELFOpen(vf);
566 if (elf) {
567 mCoreLoadELFSymbols(core->symbolTable, elf);
568 ELFClose(elf);
569 }
570 if (closeAfter) {
571 vf->close(vf);
572 }
573#endif
574}
575#endif
576
577static struct mCheatDevice* _DSCoreCheatDevice(struct mCore* core) {
578 return NULL;
579}
580
581static size_t _DSCoreSavedataClone(struct mCore* core, void** sram) {
582 return 0;
583}
584
585static bool _DSCoreSavedataRestore(struct mCore* core, const void* sram, size_t size, bool writeback) {
586 return false;
587}
588
589static size_t _DSCoreListVideoLayers(const struct mCore* core, const struct mCoreChannelInfo** info) {
590 UNUSED(core);
591 *info = _DSVideoLayers;
592 return sizeof(_DSVideoLayers) / sizeof(*_DSVideoLayers);
593}
594
595static size_t _DSCoreListAudioChannels(const struct mCore* core, const struct mCoreChannelInfo** info) {
596 UNUSED(core);
597 *info = _DSAudioChannels;
598 return sizeof(_DSAudioChannels) / sizeof(*_DSAudioChannels);
599}
600
601static void _DSCoreEnableVideoLayer(struct mCore* core, size_t id, bool enable) {
602 struct DS* ds = core->board;
603 switch (id) {
604 case 0:
605 case 1:
606 case 2:
607 case 3:
608 ds->video.renderer->disableABG[id] = !enable;
609 break;
610 case 4:
611 ds->video.renderer->disableAOBJ = !enable;
612 break;
613 case 10:
614 case 11:
615 case 12:
616 case 13:
617 ds->video.renderer->disableBBG[id - 10] = !enable;
618 break;
619 case 14:
620 ds->video.renderer->disableBOBJ = !enable;
621 break;
622 default:
623 break;
624 }
625}
626
627static void _DSCoreEnableAudioChannel(struct mCore* core, size_t id, bool enable) {
628 struct DS* ds = core->board;
629}
630
631struct mCore* DSCoreCreate(void) {
632 struct DSCore* dscore = malloc(sizeof(*dscore));
633 struct mCore* core = &dscore->d;
634 memset(&core->opts, 0, sizeof(core->opts));
635 core->cpu = NULL;
636 core->board = NULL;
637 core->debugger = NULL;
638 core->init = _DSCoreInit;
639 core->deinit = _DSCoreDeinit;
640 core->platform = _DSCorePlatform;
641 core->supportsFeature = _DSCoreSupportsFeature;
642 core->setSync = _DSCoreSetSync;
643 core->loadConfig = _DSCoreLoadConfig;
644 core->desiredVideoDimensions = _DSCoreDesiredVideoDimensions;
645 core->setVideoBuffer = _DSCoreSetVideoBuffer;
646 core->getPixels = _DSCoreGetPixels;
647 core->putPixels = _DSCorePutPixels;
648 core->getAudioChannel = _DSCoreGetAudioChannel;
649 core->setAudioBufferSize = _DSCoreSetAudioBufferSize;
650 core->getAudioBufferSize = _DSCoreGetAudioBufferSize;
651 core->addCoreCallbacks = _DSCoreAddCoreCallbacks;
652 core->clearCoreCallbacks = _DSCoreClearCoreCallbacks;
653 core->setAVStream = _DSCoreSetAVStream;
654 core->isROM = DSIsROM;
655 core->loadROM = _DSCoreLoadROM;
656 core->loadBIOS = _DSCoreLoadBIOS;
657 core->loadSave = _DSCoreLoadSave;
658 core->loadPatch = _DSCoreLoadPatch;
659 core->unloadROM = _DSCoreUnloadROM;
660 core->checksum = _DSCoreChecksum;
661 core->reset = _DSCoreReset;
662 core->runFrame = _DSCoreRunFrame;
663 core->runLoop = _DSCoreRunLoop;
664 core->step = _DSCoreStep;
665 core->stateSize = _DSCoreStateSize;
666 core->loadState = _DSCoreLoadState;
667 core->saveState = _DSCoreSaveState;
668 core->setKeys = _DSCoreSetKeys;
669 core->addKeys = _DSCoreAddKeys;
670 core->clearKeys = _DSCoreClearKeys;
671 core->setCursorLocation = _DSCoreSetCursorLocation;
672 core->setCursorDown = _DSCoreSetCursorDown;
673 core->frameCounter = _DSCoreFrameCounter;
674 core->frameCycles = _DSCoreFrameCycles;
675 core->frequency = _DSCoreFrequency;
676 core->getGameTitle = _DSCoreGetGameTitle;
677 core->getGameCode = _DSCoreGetGameCode;
678 core->setPeripheral = _DSCoreSetPeripheral;
679 core->busRead8 = _DSCoreBusRead8;
680 core->busRead16 = _DSCoreBusRead16;
681 core->busRead32 = _DSCoreBusRead32;
682 core->busWrite8 = _DSCoreBusWrite8;
683 core->busWrite16 = _DSCoreBusWrite16;
684 core->busWrite32 = _DSCoreBusWrite32;
685 core->rawRead8 = _DSCoreRawRead8;
686 core->rawRead16 = _DSCoreRawRead16;
687 core->rawRead32 = _DSCoreRawRead32;
688 core->rawWrite8 = _DSCoreRawWrite8;
689 core->rawWrite16 = _DSCoreRawWrite16;
690 core->rawWrite32 = _DSCoreRawWrite32;
691#ifdef USE_DEBUGGERS
692 core->supportsDebuggerType = _DSCoreSupportsDebuggerType;
693 core->debuggerPlatform = _DSCoreDebuggerPlatform;
694 core->cliDebuggerSystem = _DSCoreCliDebuggerSystem;
695 core->attachDebugger = _DSCoreAttachDebugger;
696 core->detachDebugger = _DSCoreDetachDebugger;
697 core->loadSymbols = _DSCoreLoadSymbols;
698#endif
699 core->cheatDevice = _DSCoreCheatDevice;
700 core->savedataClone = _DSCoreSavedataClone;
701 core->savedataRestore = _DSCoreSavedataRestore;
702 core->listVideoLayers = _DSCoreListVideoLayers;
703 core->listAudioChannels = _DSCoreListAudioChannels;
704 core->enableVideoLayer = _DSCoreEnableVideoLayer;
705 core->enableAudioChannel = _DSCoreEnableAudioChannel;
706 return core;
707}