all repos — mgba @ c3f69e7b693ae568e33d83cee264040c2db3d516

mGBA Game Boy Advance Emulator

src/gba/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/core.h"
  9#include "core/log.h"
 10#include "arm/debugger/debugger.h"
 11#include "gba/cheats.h"
 12#include "gba/gba.h"
 13#include "gba/extra/cli.h"
 14#include "gba/overrides.h"
 15#include "gba/renderers/video-software.h"
 16#include "gba/serialize.h"
 17#include "util/memory.h"
 18#include "util/patch.h"
 19#include "util/vfs.h"
 20
 21struct GBACore {
 22	struct mCore d;
 23	struct GBAVideoSoftwareRenderer renderer;
 24	int keys;
 25	struct mCPUComponent* components[CPU_COMPONENT_MAX];
 26	const struct Configuration* overrides;
 27	struct mDebuggerPlatform* debuggerPlatform;
 28	struct mCheatDevice* cheatDevice;
 29};
 30
 31static bool _GBACoreInit(struct mCore* core) {
 32	struct GBACore* gbacore = (struct GBACore*) core;
 33
 34	struct ARMCore* cpu = anonymousMemoryMap(sizeof(struct ARMCore));
 35	struct GBA* gba = anonymousMemoryMap(sizeof(struct GBA));
 36	if (!cpu || !gba) {
 37		free(cpu);
 38		free(gba);
 39		return false;
 40	}
 41	core->cpu = cpu;
 42	core->board = gba;
 43	core->debugger = NULL;
 44	gbacore->overrides = NULL;
 45	gbacore->debuggerPlatform = NULL;
 46	gbacore->cheatDevice = NULL;
 47
 48	GBACreate(gba);
 49	// TODO: Restore cheats
 50	memset(gbacore->components, 0, sizeof(gbacore->components));
 51	ARMSetComponents(cpu, &gba->d, CPU_COMPONENT_MAX, gbacore->components);
 52	ARMInit(cpu);
 53
 54	GBAVideoSoftwareRendererCreate(&gbacore->renderer);
 55	gbacore->renderer.outputBuffer = NULL;
 56
 57	gbacore->keys = 0;
 58	gba->keySource = &gbacore->keys;
 59
 60#if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2
 61	mDirectorySetInit(&core->dirs);
 62#endif
 63	
 64	return true;
 65}
 66
 67static void _GBACoreDeinit(struct mCore* core) {
 68	ARMDeinit(core->cpu);
 69	GBADestroy(core->board);
 70	mappedMemoryFree(core->cpu, sizeof(struct ARMCore));
 71	mappedMemoryFree(core->board, sizeof(struct GBA));
 72#if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2
 73	mDirectorySetDeinit(&core->dirs);
 74#endif
 75
 76	struct GBACore* gbacore = (struct GBACore*) core;
 77	free(gbacore->debuggerPlatform);
 78	if (gbacore->cheatDevice) {
 79		mCheatDeviceDestroy(gbacore->cheatDevice);
 80	}
 81	free(gbacore->cheatDevice);
 82	free(core);
 83}
 84
 85static enum mPlatform _GBACorePlatform(struct mCore* core) {
 86	UNUSED(core);
 87	return PLATFORM_GBA;
 88}
 89
 90static void _GBACoreSetSync(struct mCore* core, struct mCoreSync* sync) {
 91	struct GBA* gba = core->board;
 92	gba->sync = sync;
 93}
 94
 95static void _GBACoreLoadConfig(struct mCore* core, const struct mCoreConfig* config) {
 96	struct GBA* gba = core->board;
 97	if (core->opts.mute) {
 98		gba->audio.masterVolume = 0;
 99	} else {
100		gba->audio.masterVolume = core->opts.volume;
101	}
102	gba->video.frameskip = core->opts.frameskip;
103
104#if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2
105	struct GBACore* gbacore = (struct GBACore*) core;
106	gbacore->overrides = mCoreConfigGetOverridesConst(config);
107
108	struct VFile* bios = 0;
109	if (core->opts.useBios && core->opts.bios) {
110		bios = VFileOpen(core->opts.bios, O_RDONLY);
111	}
112	if (bios) {
113		GBALoadBIOS(gba, bios);
114	}
115#endif
116
117	const char* idleOptimization = mCoreConfigGetValue(config, "idleOptimization");
118	if (idleOptimization) {
119		if (strcasecmp(idleOptimization, "ignore") == 0) {
120			gba->idleOptimization = IDLE_LOOP_IGNORE;
121		} else if (strcasecmp(idleOptimization, "remove") == 0) {
122			gba->idleOptimization = IDLE_LOOP_REMOVE;
123		} else if (strcasecmp(idleOptimization, "detect") == 0) {
124			gba->idleOptimization = IDLE_LOOP_DETECT;
125		}
126	}
127}
128
129static void _GBACoreDesiredVideoDimensions(struct mCore* core, unsigned* width, unsigned* height) {
130	UNUSED(core);
131	*width = VIDEO_HORIZONTAL_PIXELS;
132	*height = VIDEO_VERTICAL_PIXELS;
133}
134
135static void _GBACoreSetVideoBuffer(struct mCore* core, color_t* buffer, size_t stride) {
136	struct GBACore* gbacore = (struct GBACore*) core;
137	gbacore->renderer.outputBuffer = buffer;
138	gbacore->renderer.outputBufferStride = stride;
139}
140
141static void _GBACoreGetVideoBuffer(struct mCore* core, color_t** buffer, size_t* stride) {
142	struct GBACore* gbacore = (struct GBACore*) core;
143	*buffer = gbacore->renderer.outputBuffer;
144	*stride = gbacore->renderer.outputBufferStride;
145}
146
147static struct blip_t* _GBACoreGetAudioChannel(struct mCore* core, int ch) {
148	struct GBA* gba = core->board;
149	switch (ch) {
150	case 0:
151		return gba->audio.psg.left;
152	case 1:
153		return gba->audio.psg.right;
154	default:
155		return NULL;
156	}
157}
158
159static void _GBACoreSetAudioBufferSize(struct mCore* core, size_t samples) {
160	struct GBA* gba = core->board;
161	GBAAudioResizeBuffer(&gba->audio, samples);
162}
163
164static size_t _GBACoreGetAudioBufferSize(struct mCore* core) {
165	struct GBA* gba = core->board;
166	return gba->audio.samples;
167}
168
169static void _GBACoreSetAVStream(struct mCore* core, struct mAVStream* stream) {
170	struct GBA* gba = core->board;
171	gba->stream = stream;
172	if (stream && stream->videoDimensionsChanged) {
173		stream->videoDimensionsChanged(stream, VIDEO_HORIZONTAL_PIXELS, VIDEO_VERTICAL_PIXELS);
174	}
175}
176
177static bool _GBACoreLoadROM(struct mCore* core, struct VFile* vf) {
178	return GBALoadROM(core->board, vf);
179}
180
181static bool _GBACoreLoadBIOS(struct mCore* core, struct VFile* vf, int type) {
182	UNUSED(type);
183	if (!GBAIsBIOS(vf)) {
184		return false;
185	}
186	GBALoadBIOS(core->board, vf);
187	return true;
188}
189
190static bool _GBACoreLoadSave(struct mCore* core, struct VFile* vf) {
191	return GBALoadSave(core->board, vf);
192}
193
194static bool _GBACoreLoadPatch(struct mCore* core, struct VFile* vf) {
195	if (!vf) {
196		return false;
197	}
198	struct Patch patch;
199	if (!loadPatch(vf, &patch)) {
200		return false;
201	}
202	GBAApplyPatch(core->board, &patch);
203	return true;
204}
205
206static void _GBACoreUnloadROM(struct mCore* core) {
207	return GBAUnloadROM(core->board);
208}
209
210static void _GBACoreReset(struct mCore* core) {
211	struct GBACore* gbacore = (struct GBACore*) core;
212	struct GBA* gba = (struct GBA*) core->board;
213	if (gbacore->renderer.outputBuffer) {
214		GBAVideoAssociateRenderer(&gba->video, &gbacore->renderer.d);
215	}
216	ARMReset(core->cpu);
217	if (core->opts.skipBios) {
218		GBASkipBIOS(core->board);
219	}
220
221	struct GBACartridgeOverride override;
222	const struct GBACartridge* cart = (const struct GBACartridge*) gba->memory.rom;
223	if (cart) {
224		memcpy(override.id, &cart->id, sizeof(override.id));
225		if (GBAOverrideFind(gbacore->overrides, &override)) {
226			GBAOverrideApply(gba, &override);
227		}
228	}
229}
230
231static void _GBACoreRunFrame(struct mCore* core) {
232	struct GBA* gba = core->board;
233	int32_t frameCounter = gba->video.frameCounter;
234	while (gba->video.frameCounter == frameCounter) {
235		ARMRunLoop(core->cpu);
236	}
237}
238
239static void _GBACoreRunLoop(struct mCore* core) {
240	ARMRunLoop(core->cpu);
241}
242
243static void _GBACoreStep(struct mCore* core) {
244	ARMRun(core->cpu);
245}
246
247static size_t _GBACoreStateSize(struct mCore* core) {
248	UNUSED(core);
249	return sizeof(struct GBASerializedState);
250}
251
252static bool _GBACoreLoadState(struct mCore* core, const void* state) {
253	return GBADeserialize(core->board, state);
254}
255
256static bool _GBACoreSaveState(struct mCore* core, void* state) {
257	GBASerialize(core->board, state);
258	return true;
259}
260
261static void _GBACoreSetKeys(struct mCore* core, uint32_t keys) {
262	struct GBACore* gbacore = (struct GBACore*) core;
263	gbacore->keys = keys;
264}
265
266static void _GBACoreAddKeys(struct mCore* core, uint32_t keys) {
267	struct GBACore* gbacore = (struct GBACore*) core;
268	gbacore->keys |= keys;
269}
270
271static void _GBACoreClearKeys(struct mCore* core, uint32_t keys) {
272	struct GBACore* gbacore = (struct GBACore*) core;
273	gbacore->keys &= ~keys;
274}
275
276static int32_t _GBACoreFrameCounter(struct mCore* core) {
277	struct GBA* gba = core->board;
278	return gba->video.frameCounter;
279}
280
281static int32_t _GBACoreFrameCycles(struct mCore* core) {
282	UNUSED(core);
283	return VIDEO_TOTAL_LENGTH;
284}
285
286static int32_t _GBACoreFrequency(struct mCore* core) {
287	UNUSED(core);
288	return GBA_ARM7TDMI_FREQUENCY;
289}
290
291static void _GBACoreGetGameTitle(struct mCore* core, char* title) {
292	GBAGetGameTitle(core->board, title);
293}
294
295static void _GBACoreGetGameCode(struct mCore* core, char* title) {
296	GBAGetGameCode(core->board, title);
297}
298
299static void _GBACoreSetRTC(struct mCore* core, struct mRTCSource* rtc) {
300	struct GBA* gba = core->board;
301	gba->rtcSource = rtc;
302}
303
304static void _GBACoreSetRotation(struct mCore* core, struct mRotationSource* rotation) {
305	struct GBA* gba = core->board;
306	gba->rotationSource = rotation;
307}
308
309static void _GBACoreSetRumble(struct mCore* core, struct mRumble* rumble) {
310	struct GBA* gba = core->board;
311	gba->rumble = rumble;
312}
313
314static uint32_t _GBACoreBusRead8(struct mCore* core, uint32_t address) {
315	struct ARMCore* cpu = core->cpu;
316	return cpu->memory.load8(cpu, address, 0);
317}
318
319static uint32_t _GBACoreBusRead16(struct mCore* core, uint32_t address) {
320	struct ARMCore* cpu = core->cpu;
321	return cpu->memory.load16(cpu, address, 0);
322
323}
324
325static uint32_t _GBACoreBusRead32(struct mCore* core, uint32_t address) {
326	struct ARMCore* cpu = core->cpu;
327	return cpu->memory.load32(cpu, address, 0);
328}
329
330static void _GBACoreBusWrite8(struct mCore* core, uint32_t address, uint8_t value) {
331	struct ARMCore* cpu = core->cpu;
332	cpu->memory.store8(cpu, address, value, 0);
333}
334
335static void _GBACoreBusWrite16(struct mCore* core, uint32_t address, uint16_t value) {
336	struct ARMCore* cpu = core->cpu;
337	cpu->memory.store16(cpu, address, value, 0);
338}
339
340static void _GBACoreBusWrite32(struct mCore* core, uint32_t address, uint32_t value) {
341	struct ARMCore* cpu = core->cpu;
342	cpu->memory.store32(cpu, address, value, 0);
343}
344
345static uint32_t _GBACoreRawRead8(struct mCore* core, uint32_t address) {
346	struct ARMCore* cpu = core->cpu;
347	return GBAView8(cpu, address);
348}
349
350static uint32_t _GBACoreRawRead16(struct mCore* core, uint32_t address) {
351	struct ARMCore* cpu = core->cpu;
352	return GBAView16(cpu, address);
353}
354
355static uint32_t _GBACoreRawRead32(struct mCore* core, uint32_t address) {
356	struct ARMCore* cpu = core->cpu;
357	return GBAView32(cpu, address);
358}
359
360static void _GBACoreRawWrite8(struct mCore* core, uint32_t address, uint8_t value) {
361	struct ARMCore* cpu = core->cpu;
362	GBAPatch8(cpu, address, value, NULL);
363}
364
365static void _GBACoreRawWrite16(struct mCore* core, uint32_t address, uint16_t value) {
366	struct ARMCore* cpu = core->cpu;
367	GBAPatch16(cpu, address, value, NULL);
368}
369
370static void _GBACoreRawWrite32(struct mCore* core, uint32_t address, uint32_t value) {
371	struct ARMCore* cpu = core->cpu;
372	GBAPatch32(cpu, address, value, NULL);
373}
374
375static bool _GBACoreSupportsDebuggerType(struct mCore* core, enum mDebuggerType type) {
376	UNUSED(core);
377	switch (type) {
378#ifdef USE_CLI_DEBUGGER
379	case DEBUGGER_CLI:
380		return true;
381#endif
382#ifdef USE_GDB_STUB
383	case DEBUGGER_GDB:
384		return true;
385#endif
386	default:
387		return false;
388	}
389}
390
391static struct mDebuggerPlatform* _GBACoreDebuggerPlatform(struct mCore* core) {
392	struct GBACore* gbacore = (struct GBACore*) core;
393	if (!gbacore->debuggerPlatform) {
394		gbacore->debuggerPlatform = ARMDebuggerPlatformCreate();
395	}
396	return gbacore->debuggerPlatform;
397}
398
399static struct CLIDebuggerSystem* _GBACoreCliDebuggerSystem(struct mCore* core) {
400#ifdef USE_CLI_DEBUGGER
401	return &GBACLIDebuggerCreate(core)->d;
402#else
403	UNUSED(core);
404	return NULL;
405#endif
406}
407
408static void _GBACoreAttachDebugger(struct mCore* core, struct mDebugger* debugger) {
409	if (core->debugger) {
410		GBADetachDebugger(core->board);
411	}
412	GBAAttachDebugger(core->board, debugger);
413	core->debugger = debugger;
414}
415
416static void _GBACoreDetachDebugger(struct mCore* core) {
417	GBADetachDebugger(core->board);
418	core->debugger = NULL;
419}
420
421static struct mCheatDevice* _GBACoreCheatDevice(struct mCore* core) {
422	struct GBACore* gbacore = (struct GBACore*) core;
423	if (!gbacore->cheatDevice) {
424		gbacore->cheatDevice = GBACheatDeviceCreate();
425		((struct ARMCore*) core->cpu)->components[CPU_COMPONENT_CHEAT_DEVICE] = &gbacore->cheatDevice->d;
426		ARMHotplugAttach(core->cpu, CPU_COMPONENT_CHEAT_DEVICE);
427		gbacore->cheatDevice->p = core;
428	}
429	return gbacore->cheatDevice;
430}
431
432struct mCore* GBACoreCreate(void) {
433	struct GBACore* gbacore = malloc(sizeof(*gbacore));
434	struct mCore* core = &gbacore->d;
435	memset(&core->opts, 0, sizeof(core->opts));
436	core->cpu = NULL;
437	core->board = NULL;
438	core->debugger = NULL;
439	core->init = _GBACoreInit;
440	core->deinit = _GBACoreDeinit;
441	core->platform = _GBACorePlatform;
442	core->setSync = _GBACoreSetSync;
443	core->loadConfig = _GBACoreLoadConfig;
444	core->desiredVideoDimensions = _GBACoreDesiredVideoDimensions;
445	core->setVideoBuffer = _GBACoreSetVideoBuffer;
446	core->getVideoBuffer = _GBACoreGetVideoBuffer;
447	core->getAudioChannel = _GBACoreGetAudioChannel;
448	core->setAudioBufferSize = _GBACoreSetAudioBufferSize;
449	core->getAudioBufferSize = _GBACoreGetAudioBufferSize;
450	core->setAVStream = _GBACoreSetAVStream;
451	core->isROM = GBAIsROM;
452	core->loadROM = _GBACoreLoadROM;
453	core->loadBIOS = _GBACoreLoadBIOS;
454	core->loadSave = _GBACoreLoadSave;
455	core->loadPatch = _GBACoreLoadPatch;
456	core->unloadROM = _GBACoreUnloadROM;
457	core->reset = _GBACoreReset;
458	core->runFrame = _GBACoreRunFrame;
459	core->runLoop = _GBACoreRunLoop;
460	core->step = _GBACoreStep;
461	core->stateSize = _GBACoreStateSize;
462	core->loadState = _GBACoreLoadState;
463	core->saveState = _GBACoreSaveState;
464	core->setKeys = _GBACoreSetKeys;
465	core->addKeys = _GBACoreAddKeys;
466	core->clearKeys = _GBACoreClearKeys;
467	core->frameCounter = _GBACoreFrameCounter;
468	core->frameCycles = _GBACoreFrameCycles;
469	core->frequency = _GBACoreFrequency;
470	core->getGameTitle = _GBACoreGetGameTitle;
471	core->getGameCode = _GBACoreGetGameCode;
472	core->setRTC = _GBACoreSetRTC;
473	core->setRotation = _GBACoreSetRotation;
474	core->setRumble = _GBACoreSetRumble;
475	core->busRead8 = _GBACoreBusRead8;
476	core->busRead16 = _GBACoreBusRead16;
477	core->busRead32 = _GBACoreBusRead32;
478	core->busWrite8 = _GBACoreBusWrite8;
479	core->busWrite16 = _GBACoreBusWrite16;
480	core->busWrite32 = _GBACoreBusWrite32;
481	core->rawRead8 = _GBACoreRawRead8;
482	core->rawRead16 = _GBACoreRawRead16;
483	core->rawRead32 = _GBACoreRawRead32;
484	core->rawWrite8 = _GBACoreRawWrite8;
485	core->rawWrite16 = _GBACoreRawWrite16;
486	core->rawWrite32 = _GBACoreRawWrite32;
487	core->supportsDebuggerType = _GBACoreSupportsDebuggerType;
488	core->debuggerPlatform = _GBACoreDebuggerPlatform;
489	core->cliDebuggerSystem = _GBACoreCliDebuggerSystem;
490	core->attachDebugger = _GBACoreAttachDebugger;
491	core->detachDebugger = _GBACoreDetachDebugger;
492	core->cheatDevice = _GBACoreCheatDevice;
493	return core;
494}