all repos — mgba @ fdae17020df101fc68ccfda8f8b2937312197c8c

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