all repos — mgba @ 0088229e9f9fa9a64af4d60097e20c6c6a52cffa

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