all repos — mgba @ bb83e78af97e3da21522a75c7349d6b52e86804a

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-util/memory.h>
 15#include <mgba-util/patch.h>
 16#include <mgba-util/vfs.h>
 17
 18struct DSCore {
 19	struct mCore d;
 20	struct ARMCore* arm7;
 21	struct ARMCore* arm9;
 22	int keys;
 23	struct mCPUComponent* components[CPU_COMPONENT_MAX];
 24	struct mDebuggerPlatform* debuggerPlatform;
 25	struct mCheatDevice* cheatDevice;
 26};
 27
 28static bool _DSCoreInit(struct mCore* core) {
 29	struct DSCore* dscore = (struct DSCore*) core;
 30
 31	struct ARMCore* arm7 = anonymousMemoryMap(sizeof(struct ARMCore));
 32	struct ARMCore* arm9 = anonymousMemoryMap(sizeof(struct ARMCore));
 33	struct DS* ds = anonymousMemoryMap(sizeof(struct DS));
 34	if (!arm7 || !arm9 || !ds) {
 35		free(arm7);
 36		free(arm9);
 37		free(ds);
 38		return false;
 39	}
 40	core->cpu = arm9;
 41	core->board = ds;
 42	core->debugger = NULL;
 43	dscore->arm7 = arm7;
 44	dscore->arm9 = arm9;
 45	dscore->debuggerPlatform = NULL;
 46	dscore->cheatDevice = NULL;
 47
 48	DSCreate(ds);
 49	memset(dscore->components, 0, sizeof(dscore->components));
 50	ARMSetComponents(arm7, &ds->d, CPU_COMPONENT_MAX, dscore->components);
 51	ARMSetComponents(arm9, &ds->d, CPU_COMPONENT_MAX, dscore->components);
 52	ARMInit(arm7);
 53	ARMInit(arm9);
 54
 55	dscore->keys = 0;
 56	ds->keySource = &dscore->keys;
 57
 58#if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2
 59	mDirectorySetInit(&core->dirs);
 60#endif
 61	
 62	return true;
 63}
 64
 65static void _DSCoreDeinit(struct mCore* core) {
 66	struct DSCore* dscore = (struct DSCore*) core;
 67	ARMDeinit(dscore->arm7);
 68	ARMDeinit(dscore->arm9);
 69	DSDestroy(core->board);
 70	mappedMemoryFree(dscore->arm7, sizeof(struct ARMCore));
 71	mappedMemoryFree(dscore->arm9, sizeof(struct ARMCore));
 72	mappedMemoryFree(core->board, sizeof(struct DS));
 73#if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2
 74	mDirectorySetDeinit(&core->dirs);
 75#endif
 76
 77	free(dscore->debuggerPlatform);
 78	if (dscore->cheatDevice) {
 79		mCheatDeviceDestroy(dscore->cheatDevice);
 80	}
 81	free(dscore->cheatDevice);
 82	free(core);
 83}
 84
 85static enum mPlatform _DSCorePlatform(const struct mCore* core) {
 86	UNUSED(core);
 87	return PLATFORM_DS;
 88}
 89
 90static void _DSCoreSetSync(struct mCore* core, struct mCoreSync* sync) {
 91	struct DS* ds = core->board;
 92	ds->sync = sync;
 93}
 94
 95static void _DSCoreLoadConfig(struct mCore* core, const struct mCoreConfig* config) {
 96	struct DS* ds = core->board;
 97	struct VFile* bios = NULL;
 98	if (core->opts.useBios && core->opts.bios) {
 99		bios = VFileOpen(core->opts.bios, O_RDONLY);
100	}
101	if (bios) {
102		DSLoadBIOS(ds, bios);
103	}
104}
105
106static void _DSCoreDesiredVideoDimensions(struct mCore* core, unsigned* width, unsigned* height) {
107	UNUSED(core);
108	*width = DS_VIDEO_HORIZONTAL_PIXELS;
109	*height = DS_VIDEO_VERTICAL_PIXELS * 2;
110}
111
112static void _DSCoreSetVideoBuffer(struct mCore* core, color_t* buffer, size_t stride) {
113}
114
115static void _DSCoreGetPixels(struct mCore* core, const void** buffer, size_t* stride) {
116}
117
118static void _DSCorePutPixels(struct mCore* core, const void* buffer, size_t stride) {
119}
120
121static struct blip_t* _DSCoreGetAudioChannel(struct mCore* core, int ch) {
122	return NULL;
123}
124
125static void _DSCoreSetAudioBufferSize(struct mCore* core, size_t samples) {
126}
127
128static size_t _DSCoreGetAudioBufferSize(struct mCore* core) {
129	return 2048;
130}
131
132static void _DSCoreSetCoreCallbacks(struct mCore* core, struct mCoreCallbacks* coreCallbacks) {
133}
134
135static void _DSCoreSetAVStream(struct mCore* core, struct mAVStream* stream) {
136}
137
138static bool _DSCoreLoadROM(struct mCore* core, struct VFile* vf) {
139	return DSLoadROM(core->board, vf);
140}
141
142static bool _DSCoreLoadBIOS(struct mCore* core, struct VFile* vf, int type) {
143	UNUSED(type);
144	return DSLoadBIOS(core->board, vf);
145}
146
147static bool _DSCoreLoadSave(struct mCore* core, struct VFile* vf) {
148	return false;
149}
150
151static bool _DSCoreLoadPatch(struct mCore* core, struct VFile* vf) {
152	return false;
153}
154
155static void _DSCoreUnloadROM(struct mCore* core) {
156	return DSUnloadROM(core->board);
157}
158
159static void _DSCoreReset(struct mCore* core) {
160	struct DSCore* dscore = (struct DSCore*) core;
161	struct DS* ds = (struct DS*) core->board;
162
163#if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2
164	struct VFile* bios7 = 0;
165	struct VFile* bios9 = 0;
166	if (core->opts.useBios) {
167		if (!core->opts.bios) {
168			char path[PATH_MAX];
169			mCoreConfigDirectory(path, PATH_MAX);
170			strncat(path, PATH_SEP "ds7_bios.bin", PATH_MAX - strlen(path));
171			bios7 = VFileOpen(path, O_RDONLY);
172			mCoreConfigDirectory(path, PATH_MAX);
173			strncat(path, PATH_SEP "ds9_bios.bin", PATH_MAX - strlen(path));
174			bios9 = VFileOpen(path, O_RDONLY);
175		} else {
176			bios7 = VFileOpen(core->opts.bios, O_RDONLY);
177		}
178	}
179	if (bios7) {
180		DSLoadBIOS(ds, bios7);
181	}
182	if (bios9) {
183		DSLoadBIOS(ds, bios9);
184	}
185#endif
186
187	ARMReset(ds->ds7.cpu);
188	ARMReset(ds->ds9.cpu);
189}
190
191static void _DSCoreRunFrame(struct mCore* core) {
192	struct DSCore* dscore = (struct DSCore*) core;
193	struct DS* ds = core->board;
194	int32_t frameCounter = ds->video.frameCounter;
195	while (ds->video.frameCounter == frameCounter) {
196		DSRunLoop(core->board);
197	}
198}
199
200static void _DSCoreRunLoop(struct mCore* core) {
201	DSRunLoop(core->board);
202}
203
204static void _DSCoreStep(struct mCore* core) {
205	struct DSCore* dscore = (struct DSCore*) core;
206	if (core->cpu == dscore->arm9) {
207		DS9Step(core->board);
208	} else {
209		DS7Step(core->board);
210	}
211}
212
213static size_t _DSCoreStateSize(struct mCore* core) {
214	UNUSED(core);
215	return 0;
216}
217
218static bool _DSCoreLoadState(struct mCore* core, const void* state) {
219	return false;
220}
221
222static bool _DSCoreSaveState(struct mCore* core, void* state) {
223	return false;
224}
225
226static void _DSCoreSetKeys(struct mCore* core, uint32_t keys) {
227	struct DSCore* dscore = (struct DSCore*) core;
228	dscore->keys = keys;
229}
230
231static void _DSCoreAddKeys(struct mCore* core, uint32_t keys) {
232	struct DSCore* dscore = (struct DSCore*) core;
233	dscore->keys |= keys;
234}
235
236static void _DSCoreClearKeys(struct mCore* core, uint32_t keys) {
237	struct DSCore* dscore = (struct DSCore*) core;
238	dscore->keys &= ~keys;
239}
240
241static int32_t _DSCoreFrameCounter(struct mCore* core) {
242	struct DS* ds = core->board;
243	return ds->video.frameCounter;
244}
245
246static int32_t _DSCoreFrameCycles(const struct mCore* core) {
247	UNUSED(core);
248	return DS_VIDEO_TOTAL_LENGTH;
249}
250
251static int32_t _DSCoreFrequency(const struct mCore* core) {
252	UNUSED(core);
253	return DS_ARM946ES_FREQUENCY;
254}
255
256static void _DSCoreGetGameTitle(const struct mCore* core, char* title) {
257	DSGetGameTitle(core->board, title);
258}
259
260static void _DSCoreGetGameCode(const struct mCore* core, char* title) {
261	DSGetGameCode(core->board, title);
262}
263
264static void _DSCoreSetRTC(struct mCore* core, struct mRTCSource* rtc) {
265	struct DS* ds = core->board;
266	ds->rtcSource = rtc;
267}
268
269static void _DSCoreSetRotation(struct mCore* core, struct mRotationSource* rotation) {
270}
271
272static void _DSCoreSetRumble(struct mCore* core, struct mRumble* rumble) {
273	struct DS* ds = core->board;
274	ds->rumble = rumble;
275}
276
277static uint32_t _DSCoreBusRead8(struct mCore* core, uint32_t address) {
278	struct ARMCore* cpu = core->cpu;
279	return cpu->memory.load8(cpu, address, 0);
280}
281
282static uint32_t _DSCoreBusRead16(struct mCore* core, uint32_t address) {
283	struct ARMCore* cpu = core->cpu;
284	return cpu->memory.load16(cpu, address, 0);
285
286}
287
288static uint32_t _DSCoreBusRead32(struct mCore* core, uint32_t address) {
289	struct ARMCore* cpu = core->cpu;
290	return cpu->memory.load32(cpu, address, 0);
291}
292
293static void _DSCoreBusWrite8(struct mCore* core, uint32_t address, uint8_t value) {
294	struct ARMCore* cpu = core->cpu;
295	cpu->memory.store8(cpu, address, value, 0);
296}
297
298static void _DSCoreBusWrite16(struct mCore* core, uint32_t address, uint16_t value) {
299	struct ARMCore* cpu = core->cpu;
300	cpu->memory.store16(cpu, address, value, 0);
301}
302
303static void _DSCoreBusWrite32(struct mCore* core, uint32_t address, uint32_t value) {
304	struct ARMCore* cpu = core->cpu;
305	cpu->memory.store32(cpu, address, value, 0);
306}
307
308static uint32_t _DSCoreRawRead8(struct mCore* core, uint32_t address, int segment) {
309	return 0;
310}
311
312static uint32_t _DSCoreRawRead16(struct mCore* core, uint32_t address, int segment) {
313	return 0;
314}
315
316static uint32_t _DSCoreRawRead32(struct mCore* core, uint32_t address, int segment) {
317	return 0;
318}
319
320static void _DSCoreRawWrite8(struct mCore* core, uint32_t address, int segment, uint8_t value) {
321}
322
323static void _DSCoreRawWrite16(struct mCore* core, uint32_t address, int segment, uint16_t value) {
324}
325
326static void _DSCoreRawWrite32(struct mCore* core, uint32_t address, int segment, uint32_t value) {
327}
328
329static bool _DSCoreSupportsDebuggerType(struct mCore* core, enum mDebuggerType type) {
330	UNUSED(core);
331	switch (type) {
332	case DEBUGGER_CLI:
333		return true;
334#ifdef USE_GDB_STUB
335	case DEBUGGER_GDB:
336		return true;
337#endif
338	default:
339		return false;
340	}
341}
342
343static struct mDebuggerPlatform* _DSCoreDebuggerPlatform(struct mCore* core) {
344	struct DSCore* dscore = (struct DSCore*) core;
345	if (!dscore->debuggerPlatform) {
346		dscore->debuggerPlatform = ARMDebuggerPlatformCreate();
347	}
348	return dscore->debuggerPlatform;
349}
350
351static struct CLIDebuggerSystem* _DSCoreCliDebuggerSystem(struct mCore* core) {
352	return &DSCLIDebuggerCreate(core)->d;
353}
354
355static void _DSCoreAttachDebugger(struct mCore* core, struct mDebugger* debugger) {
356	if (core->debugger) {
357		DSDetachDebugger(core->board);
358	}
359	DSAttachDebugger(core->board, debugger);
360	core->debugger = debugger;
361}
362
363static void _DSCoreDetachDebugger(struct mCore* core) {
364	DSDetachDebugger(core->board);
365	core->debugger = NULL;
366}
367
368static struct mCheatDevice* _DSCoreCheatDevice(struct mCore* core) {
369	return NULL;
370}
371
372static size_t _DSCoreSavedataClone(struct mCore* core, void** sram) {
373	return 0;
374}
375
376static bool _DSCoreSavedataRestore(struct mCore* core, const void* sram, size_t size, bool writeback) {
377	return false;
378}
379
380struct mCore* DSCoreCreate(void) {
381	struct DSCore* dscore = malloc(sizeof(*dscore));
382	struct mCore* core = &dscore->d;
383	memset(&core->opts, 0, sizeof(core->opts));
384	core->cpu = NULL;
385	core->board = NULL;
386	core->debugger = NULL;
387	core->init = _DSCoreInit;
388	core->deinit = _DSCoreDeinit;
389	core->platform = _DSCorePlatform;
390	core->setSync = _DSCoreSetSync;
391	core->loadConfig = _DSCoreLoadConfig;
392	core->desiredVideoDimensions = _DSCoreDesiredVideoDimensions;
393	core->setVideoBuffer = _DSCoreSetVideoBuffer;
394	core->getPixels = _DSCoreGetPixels;
395	core->putPixels = _DSCorePutPixels;
396	core->getAudioChannel = _DSCoreGetAudioChannel;
397	core->setAudioBufferSize = _DSCoreSetAudioBufferSize;
398	core->getAudioBufferSize = _DSCoreGetAudioBufferSize;
399	core->setCoreCallbacks = _DSCoreSetCoreCallbacks;
400	core->setAVStream = _DSCoreSetAVStream;
401	core->isROM = DSIsROM;
402	core->loadROM = _DSCoreLoadROM;
403	core->loadBIOS = _DSCoreLoadBIOS;
404	core->loadSave = _DSCoreLoadSave;
405	core->loadPatch = _DSCoreLoadPatch;
406	core->unloadROM = _DSCoreUnloadROM;
407	core->reset = _DSCoreReset;
408	core->runFrame = _DSCoreRunFrame;
409	core->runLoop = _DSCoreRunLoop;
410	core->step = _DSCoreStep;
411	core->stateSize = _DSCoreStateSize;
412	core->loadState = _DSCoreLoadState;
413	core->saveState = _DSCoreSaveState;
414	core->setKeys = _DSCoreSetKeys;
415	core->addKeys = _DSCoreAddKeys;
416	core->clearKeys = _DSCoreClearKeys;
417	core->frameCounter = _DSCoreFrameCounter;
418	core->frameCycles = _DSCoreFrameCycles;
419	core->frequency = _DSCoreFrequency;
420	core->getGameTitle = _DSCoreGetGameTitle;
421	core->getGameCode = _DSCoreGetGameCode;
422	core->setRTC = _DSCoreSetRTC;
423	core->setRotation = _DSCoreSetRotation;
424	core->setRumble = _DSCoreSetRumble;
425	core->busRead8 = _DSCoreBusRead8;
426	core->busRead16 = _DSCoreBusRead16;
427	core->busRead32 = _DSCoreBusRead32;
428	core->busWrite8 = _DSCoreBusWrite8;
429	core->busWrite16 = _DSCoreBusWrite16;
430	core->busWrite32 = _DSCoreBusWrite32;
431	core->rawRead8 = _DSCoreRawRead8;
432	core->rawRead16 = _DSCoreRawRead16;
433	core->rawRead32 = _DSCoreRawRead32;
434	core->rawWrite8 = _DSCoreRawWrite8;
435	core->rawWrite16 = _DSCoreRawWrite16;
436	core->rawWrite32 = _DSCoreRawWrite32;
437#ifdef USE_DEBUGGERS
438	core->supportsDebuggerType = _DSCoreSupportsDebuggerType;
439	core->debuggerPlatform = _DSCoreDebuggerPlatform;
440	core->cliDebuggerSystem = _DSCoreCliDebuggerSystem;
441	core->attachDebugger = _DSCoreAttachDebugger;
442	core->detachDebugger = _DSCoreDetachDebugger;
443#endif
444	core->cheatDevice = _DSCoreCheatDevice;
445	core->savedataClone = _DSCoreSavedataClone;
446	core->savedataRestore = _DSCoreSavedataRestore;
447	return core;
448}