all repos — mgba @ a5f664ca72882ef3865b94e8bd5c1dca7fdaef41

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