all repos — mgba @ 1a0e44c014ad34bea30d237d27015d82d02cda4b

mGBA Game Boy Advance Emulator

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 void _DSCoreSetSync(struct mCore* core, struct mCoreSync* sync) {
147	struct DS* ds = core->board;
148	ds->sync = sync;
149}
150
151static void _DSCoreLoadConfig(struct mCore* core, const struct mCoreConfig* config) {
152	struct DS* ds = core->board;
153	struct VFile* bios = NULL;
154
155	mCoreConfigCopyValue(&core->config, config, "ds.bios7");
156	mCoreConfigCopyValue(&core->config, config, "ds.bios9");
157	mCoreConfigCopyValue(&core->config, config, "ds.firmware");
158}
159
160static void _DSCoreDesiredVideoDimensions(struct mCore* core, unsigned* width, unsigned* height) {
161	UNUSED(core);
162	*width = DS_VIDEO_HORIZONTAL_PIXELS;
163	*height = DS_VIDEO_VERTICAL_PIXELS * 2;
164}
165
166static void _DSCoreSetVideoBuffer(struct mCore* core, color_t* buffer, size_t stride) {
167	struct DSCore* dscore = (struct DSCore*) core;
168	dscore->renderer.outputBuffer = buffer;
169	dscore->renderer.outputBufferStride = stride;
170}
171
172static void _DSCoreGetPixels(struct mCore* core, const void** buffer, size_t* stride) {
173	struct DSCore* dscore = (struct DSCore*) core;
174	dscore->renderer.d.getPixels(&dscore->renderer.d, stride, buffer);
175}
176
177static void _DSCorePutPixels(struct mCore* core, const void* buffer, size_t stride) {
178	struct DSCore* dscore = (struct DSCore*) core;
179	dscore->renderer.d.putPixels(&dscore->renderer.d, stride, buffer);
180}
181
182static struct blip_t* _DSCoreGetAudioChannel(struct mCore* core, int ch) {
183	struct DS* ds = core->board;
184	switch (ch) {
185	case 0:
186		return ds->audio.left;
187	case 1:
188		return ds->audio.right;
189	default:
190		return NULL;
191	}
192}
193
194static void _DSCoreSetAudioBufferSize(struct mCore* core, size_t samples) {
195	struct DS* ds = core->board;
196	DSAudioResizeBuffer(&ds->audio, samples);
197}
198
199static size_t _DSCoreGetAudioBufferSize(struct mCore* core) {
200	struct DS* ds = core->board;
201	return ds->audio.samples;
202}
203
204static void _DSCoreAddCoreCallbacks(struct mCore* core, struct mCoreCallbacks* coreCallbacks) {
205	struct DS* ds = core->board;
206	*mCoreCallbacksListAppend(&ds->coreCallbacks) = *coreCallbacks;
207}
208
209static void _DSCoreClearCoreCallbacks(struct mCore* core) {
210	struct DS* ds = core->board;
211	mCoreCallbacksListClear(&ds->coreCallbacks);
212}
213
214static void _DSCoreSetAVStream(struct mCore* core, struct mAVStream* stream) {
215	struct DS* ds = core->board;
216	ds->stream = stream;
217	if (stream && stream->videoDimensionsChanged) {
218		stream->videoDimensionsChanged(stream, DS_VIDEO_HORIZONTAL_PIXELS, DS_VIDEO_VERTICAL_PIXELS * 2);
219	}
220	if (stream && stream->videoFrameRateChanged) {
221		stream->videoFrameRateChanged(stream, core->frameCycles(core), core->frequency(core));
222	}
223}
224
225static bool _DSCoreLoadROM(struct mCore* core, struct VFile* vf) {
226	return DSLoadROM(core->board, vf);
227}
228
229static bool _DSCoreLoadBIOS(struct mCore* core, struct VFile* vf, int type) {
230	UNUSED(type);
231	return DSLoadBIOS(core->board, vf);
232}
233
234static bool _DSCoreLoadSave(struct mCore* core, struct VFile* vf) {
235	return DSLoadSave(core->board, vf);
236}
237
238static bool _DSCoreLoadPatch(struct mCore* core, struct VFile* vf) {
239	return false;
240}
241
242static void _DSCoreUnloadROM(struct mCore* core) {
243	return DSUnloadROM(core->board);
244}
245
246static void _DSCoreChecksum(const struct mCore* core, void* data, enum mCoreChecksumType type) {
247}
248
249static void _DSCoreReset(struct mCore* core) {
250	struct DSCore* dscore = (struct DSCore*) core;
251	struct DS* ds = (struct DS*) core->board;
252
253	if (dscore->renderer.outputBuffer) {
254		struct DSVideoRenderer* renderer = &dscore->renderer.d;
255		DSVideoAssociateRenderer(&ds->video, renderer);
256
257		struct DSGXRenderer* gxRenderer = &dscore->gxRenderer.d;
258		DSGXAssociateRenderer(&ds->gx, gxRenderer);
259	}
260
261#if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2
262	struct VFile* bios7 = NULL;
263	struct VFile* bios9 = NULL;
264	struct VFile* firm = NULL;
265	if (core->opts.useBios) {
266		bool found7 = false;
267		bool found9 = false;
268		bool foundFirm = false;
269
270		if (!found7) {
271			const char* configPath = mCoreConfigGetValue(&core->config, "ds.bios7");
272			bios7 = VFileOpen(configPath, O_RDONLY);
273			if (bios7 && DSIsBIOS7(bios7)) {
274				found7 = true;
275			} else if (bios7) {
276				bios7->close(bios7);
277				bios7 = NULL;
278			}
279		}
280
281		if (!found9) {
282			const char* configPath = mCoreConfigGetValue(&core->config, "ds.bios9");
283			bios9 = VFileOpen(configPath, O_RDONLY);
284			if (bios9 && DSIsBIOS9(bios9)) {
285				found9 = true;
286			} else if (bios9) {
287				bios9->close(bios9);
288				bios9 = NULL;
289			}
290		}
291
292		if (!foundFirm) {
293			const char* configPath = mCoreConfigGetValue(&core->config, "ds.firmware");
294			firm = VFileOpen(configPath, O_RDONLY);
295			if (firm && DSIsFirmware(firm)) {
296				foundFirm = true;
297			} else if (firm) {
298				firm->close(firm);
299				firm = NULL;
300			}
301		}
302
303		if (!found7) {
304			char path[PATH_MAX];
305			mCoreConfigDirectory(path, PATH_MAX);
306			strncat(path, PATH_SEP "ds7_bios.bin", PATH_MAX - strlen(path));
307			bios7 = VFileOpen(path, O_RDONLY);
308		}
309
310		if (!found9) {
311			char path[PATH_MAX];
312			mCoreConfigDirectory(path, PATH_MAX);
313			strncat(path, PATH_SEP "ds9_bios.bin", PATH_MAX - strlen(path));
314			bios9 = VFileOpen(path, O_RDONLY);
315		}
316
317		if (!foundFirm) {
318			char path[PATH_MAX];
319			mCoreConfigDirectory(path, PATH_MAX);
320			strncat(path, PATH_SEP "ds_firmware.bin", PATH_MAX - strlen(path));
321			firm = VFileOpen(path, O_RDWR);
322		}
323	}
324	if (bios7) {
325		DSLoadBIOS(ds, bios7);
326	}
327	if (bios9) {
328		DSLoadBIOS(ds, bios9);
329	}
330	if (firm) {
331		DSLoadFirmware(ds, firm);
332	}
333#endif
334
335	ARMReset(ds->ds7.cpu);
336	ARMReset(ds->ds9.cpu);
337}
338
339static void _DSCoreRunFrame(struct mCore* core) {
340	struct DSCore* dscore = (struct DSCore*) core;
341	struct DS* ds = core->board;
342	int32_t frameCounter = ds->video.frameCounter;
343	while (ds->video.frameCounter == frameCounter) {
344		DSRunLoop(core->board);
345	}
346}
347
348static void _DSCoreRunLoop(struct mCore* core) {
349	DSRunLoop(core->board);
350}
351
352static void _DSCoreStep(struct mCore* core) {
353	struct DSCore* dscore = (struct DSCore*) core;
354	if (core->cpu == dscore->arm9) {
355		DS9Step(core->board);
356	} else {
357		DS7Step(core->board);
358	}
359}
360
361static size_t _DSCoreStateSize(struct mCore* core) {
362	UNUSED(core);
363	return 0;
364}
365
366static bool _DSCoreLoadState(struct mCore* core, const void* state) {
367	return false;
368}
369
370static bool _DSCoreSaveState(struct mCore* core, void* state) {
371	return false;
372}
373
374static void _DSCoreSetKeys(struct mCore* core, uint32_t keys) {
375	struct DSCore* dscore = (struct DSCore*) core;
376	dscore->keys = keys;
377}
378
379static void _DSCoreAddKeys(struct mCore* core, uint32_t keys) {
380	struct DSCore* dscore = (struct DSCore*) core;
381	dscore->keys |= keys;
382}
383
384static void _DSCoreClearKeys(struct mCore* core, uint32_t keys) {
385	struct DSCore* dscore = (struct DSCore*) core;
386	dscore->keys &= ~keys;
387}
388
389static void _DSCoreSetCursorLocation(struct mCore* core, int x, int y) {
390	struct DSCore* dscore = (struct DSCore*) core;
391	dscore->cursorX = x;
392	dscore->cursorY = y - DS_VIDEO_VERTICAL_PIXELS;
393	if (dscore->cursorY < 0) {
394		dscore->cursorY = 0;
395	} else if (dscore->cursorY >= DS_VIDEO_VERTICAL_PIXELS) {
396		dscore->cursorY = DS_VIDEO_VERTICAL_PIXELS - 1;
397	}
398	if (dscore->cursorX < 0) {
399		dscore->cursorX = 0;
400	} else if (dscore->cursorX >= DS_VIDEO_HORIZONTAL_PIXELS) {
401		dscore->cursorX = DS_VIDEO_HORIZONTAL_PIXELS - 1;
402	}
403}
404
405static void _DSCoreSetCursorDown(struct mCore* core, bool down) {
406	struct DSCore* dscore = (struct DSCore*) core;
407	dscore->touchDown = down;
408}
409
410static int32_t _DSCoreFrameCounter(const struct mCore* core) {
411	struct DS* ds = core->board;
412	return ds->video.frameCounter;
413}
414
415static int32_t _DSCoreFrameCycles(const struct mCore* core) {
416	UNUSED(core);
417	return DS_VIDEO_TOTAL_LENGTH * 2;
418}
419
420static int32_t _DSCoreFrequency(const struct mCore* core) {
421	UNUSED(core);
422	return DS_ARM946ES_FREQUENCY;
423}
424
425static void _DSCoreGetGameTitle(const struct mCore* core, char* title) {
426	DSGetGameTitle(core->board, title);
427}
428
429static void _DSCoreGetGameCode(const struct mCore* core, char* title) {
430	DSGetGameCode(core->board, title);
431}
432
433static void _DSCoreSetPeripheral(struct mCore* core, int type, void* periph) {
434	struct DS* ds = core->board;
435	switch (type) {
436	case mPERIPH_RUMBLE:
437		ds->rumble = periph;
438		break;
439	default:
440		break;
441	}
442}
443
444static uint32_t _DSCoreBusRead8(struct mCore* core, uint32_t address) {
445	struct ARMCore* cpu = core->cpu;
446	return cpu->memory.load8(cpu, address, 0);
447}
448
449static uint32_t _DSCoreBusRead16(struct mCore* core, uint32_t address) {
450	struct ARMCore* cpu = core->cpu;
451	return cpu->memory.load16(cpu, address, 0);
452
453}
454
455static uint32_t _DSCoreBusRead32(struct mCore* core, uint32_t address) {
456	struct ARMCore* cpu = core->cpu;
457	return cpu->memory.load32(cpu, address, 0);
458}
459
460static void _DSCoreBusWrite8(struct mCore* core, uint32_t address, uint8_t value) {
461	struct ARMCore* cpu = core->cpu;
462	cpu->memory.store8(cpu, address, value, 0);
463}
464
465static void _DSCoreBusWrite16(struct mCore* core, uint32_t address, uint16_t value) {
466	struct ARMCore* cpu = core->cpu;
467	cpu->memory.store16(cpu, address, value, 0);
468}
469
470static void _DSCoreBusWrite32(struct mCore* core, uint32_t address, uint32_t value) {
471	struct ARMCore* cpu = core->cpu;
472	cpu->memory.store32(cpu, address, value, 0);
473}
474
475static uint32_t _DSCoreRawRead8(struct mCore* core, uint32_t address, int segment) {
476	// TODO: Raw
477	struct ARMCore* cpu = core->cpu;
478	return cpu->memory.load8(cpu, address, 0);
479}
480
481static uint32_t _DSCoreRawRead16(struct mCore* core, uint32_t address, int segment) {
482	// TODO: Raw
483	struct ARMCore* cpu = core->cpu;
484	return cpu->memory.load16(cpu, address, 0);
485}
486
487static uint32_t _DSCoreRawRead32(struct mCore* core, uint32_t address, int segment) {
488	// TODO: Raw
489	struct ARMCore* cpu = core->cpu;
490	return cpu->memory.load32(cpu, address, 0);
491}
492
493static void _DSCoreRawWrite8(struct mCore* core, uint32_t address, int segment, uint8_t value) {
494}
495
496static void _DSCoreRawWrite16(struct mCore* core, uint32_t address, int segment, uint16_t value) {
497}
498
499static void _DSCoreRawWrite32(struct mCore* core, uint32_t address, int segment, uint32_t value) {
500}
501
502#ifdef USE_DEBUGGERS
503static bool _DSCoreSupportsDebuggerType(struct mCore* core, enum mDebuggerType type) {
504	UNUSED(core);
505	switch (type) {
506	case DEBUGGER_CLI:
507		return true;
508#ifdef USE_GDB_STUB
509	case DEBUGGER_GDB:
510		return true;
511#endif
512	default:
513		return false;
514	}
515}
516
517static struct mDebuggerPlatform* _DSCoreDebuggerPlatform(struct mCore* core) {
518	struct DSCore* dscore = (struct DSCore*) core;
519	if (!dscore->debuggerPlatform) {
520		dscore->debuggerPlatform = ARMDebuggerPlatformCreate();
521	}
522	return dscore->debuggerPlatform;
523}
524
525static struct CLIDebuggerSystem* _DSCoreCliDebuggerSystem(struct mCore* core) {
526	return &DSCLIDebuggerCreate(core)->d;
527}
528
529static void _DSCoreAttachDebugger(struct mCore* core, struct mDebugger* debugger) {
530	if (core->debugger) {
531		DSDetachDebugger(core->board);
532	}
533	DSAttachDebugger(core->board, debugger);
534	core->debugger = debugger;
535}
536
537static void _DSCoreDetachDebugger(struct mCore* core) {
538	DSDetachDebugger(core->board);
539	core->debugger = NULL;
540}
541
542static void _DSCoreLoadSymbols(struct mCore* core, struct VFile* vf) {
543#ifdef USE_ELF
544	bool closeAfter = false;
545	core->symbolTable = mDebuggerSymbolTableCreate();
546#if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2
547	if (!vf) {
548		closeAfter = true;
549		vf = mDirectorySetOpenSuffix(&core->dirs, core->dirs.base, ".elf", O_RDONLY);
550	}
551#endif
552	if (!vf) {
553		return;
554	}
555	struct ELF* elf = ELFOpen(vf);
556	if (elf) {
557		mCoreLoadELFSymbols(core->symbolTable, elf);
558		ELFClose(elf);
559	}
560	if (closeAfter) {
561		vf->close(vf);
562	}
563#endif
564}
565#endif
566
567static struct mCheatDevice* _DSCoreCheatDevice(struct mCore* core) {
568	return NULL;
569}
570
571static size_t _DSCoreSavedataClone(struct mCore* core, void** sram) {
572	return 0;
573}
574
575static bool _DSCoreSavedataRestore(struct mCore* core, const void* sram, size_t size, bool writeback) {
576	return false;
577}
578
579static size_t _DSCoreListVideoLayers(const struct mCore* core, const struct mCoreChannelInfo** info) {
580	UNUSED(core);
581	*info = _DSVideoLayers;
582	return sizeof(_DSVideoLayers) / sizeof(*_DSVideoLayers);
583}
584
585static size_t _DSCoreListAudioChannels(const struct mCore* core, const struct mCoreChannelInfo** info) {
586	UNUSED(core);
587	*info = _DSAudioChannels;
588	return sizeof(_DSAudioChannels) / sizeof(*_DSAudioChannels);
589}
590
591static void _DSCoreEnableVideoLayer(struct mCore* core, size_t id, bool enable) {
592	struct DS* ds = core->board;
593	switch (id) {
594	case 0:
595	case 1:
596	case 2:
597	case 3:
598		ds->video.renderer->disableABG[id] = !enable;
599		break;
600	case 4:
601		ds->video.renderer->disableAOBJ = !enable;
602		break;
603	case 10:
604	case 11:
605	case 12:
606	case 13:
607		ds->video.renderer->disableBBG[id - 10] = !enable;
608		break;
609	case 14:
610		ds->video.renderer->disableBOBJ = !enable;
611		break;
612	default:
613		break;
614	}
615}
616
617static void _DSCoreEnableAudioChannel(struct mCore* core, size_t id, bool enable) {
618	struct DS* ds = core->board;
619}
620
621struct mCore* DSCoreCreate(void) {
622	struct DSCore* dscore = malloc(sizeof(*dscore));
623	struct mCore* core = &dscore->d;
624	memset(&core->opts, 0, sizeof(core->opts));
625	core->cpu = NULL;
626	core->board = NULL;
627	core->debugger = NULL;
628	core->init = _DSCoreInit;
629	core->deinit = _DSCoreDeinit;
630	core->platform = _DSCorePlatform;
631	core->setSync = _DSCoreSetSync;
632	core->loadConfig = _DSCoreLoadConfig;
633	core->desiredVideoDimensions = _DSCoreDesiredVideoDimensions;
634	core->setVideoBuffer = _DSCoreSetVideoBuffer;
635	core->getPixels = _DSCoreGetPixels;
636	core->putPixels = _DSCorePutPixels;
637	core->getAudioChannel = _DSCoreGetAudioChannel;
638	core->setAudioBufferSize = _DSCoreSetAudioBufferSize;
639	core->getAudioBufferSize = _DSCoreGetAudioBufferSize;
640	core->addCoreCallbacks = _DSCoreAddCoreCallbacks;
641	core->clearCoreCallbacks = _DSCoreClearCoreCallbacks;
642	core->setAVStream = _DSCoreSetAVStream;
643	core->isROM = DSIsROM;
644	core->loadROM = _DSCoreLoadROM;
645	core->loadBIOS = _DSCoreLoadBIOS;
646	core->loadSave = _DSCoreLoadSave;
647	core->loadPatch = _DSCoreLoadPatch;
648	core->unloadROM = _DSCoreUnloadROM;
649	core->checksum = _DSCoreChecksum;
650	core->reset = _DSCoreReset;
651	core->runFrame = _DSCoreRunFrame;
652	core->runLoop = _DSCoreRunLoop;
653	core->step = _DSCoreStep;
654	core->stateSize = _DSCoreStateSize;
655	core->loadState = _DSCoreLoadState;
656	core->saveState = _DSCoreSaveState;
657	core->setKeys = _DSCoreSetKeys;
658	core->addKeys = _DSCoreAddKeys;
659	core->clearKeys = _DSCoreClearKeys;
660	core->setCursorLocation = _DSCoreSetCursorLocation;
661	core->setCursorDown = _DSCoreSetCursorDown;
662	core->frameCounter = _DSCoreFrameCounter;
663	core->frameCycles = _DSCoreFrameCycles;
664	core->frequency = _DSCoreFrequency;
665	core->getGameTitle = _DSCoreGetGameTitle;
666	core->getGameCode = _DSCoreGetGameCode;
667	core->setPeripheral = _DSCoreSetPeripheral;
668	core->busRead8 = _DSCoreBusRead8;
669	core->busRead16 = _DSCoreBusRead16;
670	core->busRead32 = _DSCoreBusRead32;
671	core->busWrite8 = _DSCoreBusWrite8;
672	core->busWrite16 = _DSCoreBusWrite16;
673	core->busWrite32 = _DSCoreBusWrite32;
674	core->rawRead8 = _DSCoreRawRead8;
675	core->rawRead16 = _DSCoreRawRead16;
676	core->rawRead32 = _DSCoreRawRead32;
677	core->rawWrite8 = _DSCoreRawWrite8;
678	core->rawWrite16 = _DSCoreRawWrite16;
679	core->rawWrite32 = _DSCoreRawWrite32;
680#ifdef USE_DEBUGGERS
681	core->supportsDebuggerType = _DSCoreSupportsDebuggerType;
682	core->debuggerPlatform = _DSCoreDebuggerPlatform;
683	core->cliDebuggerSystem = _DSCoreCliDebuggerSystem;
684	core->attachDebugger = _DSCoreAttachDebugger;
685	core->detachDebugger = _DSCoreDetachDebugger;
686	core->loadSymbols = _DSCoreLoadSymbols;
687#endif
688	core->cheatDevice = _DSCoreCheatDevice;
689	core->savedataClone = _DSCoreSavedataClone;
690	core->savedataRestore = _DSCoreSavedataRestore;
691	core->listVideoLayers = _DSCoreListVideoLayers;
692	core->listAudioChannels = _DSCoreListAudioChannels;
693	core->enableVideoLayer = _DSCoreEnableVideoLayer;
694	core->enableAudioChannel = _DSCoreEnableAudioChannel;
695	return core;
696}