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;
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 ARMReset(ds->arm7);
163 ARMReset(ds->arm9);
164}
165
166static void _DSCoreRunFrame(struct mCore* core) {
167 struct DSCore* dscore = (struct DSCore*) core;
168 struct DS* ds = core->board;
169 int32_t frameCounter = ds->video.frameCounter;
170 while (ds->video.frameCounter == frameCounter) {
171 DSRunLoop(core->board);
172 }
173}
174
175static void _DSCoreRunLoop(struct mCore* core) {
176 DSRunLoop(core->board);
177}
178
179static void _DSCoreStep(struct mCore* core) {
180 struct DSCore* dscore = (struct DSCore*) core;
181 if (core->cpu == dscore->arm9) {
182 DS9Step(core->board);
183 } else {
184 DS7Step(core->board);
185 }
186}
187
188static size_t _DSCoreStateSize(struct mCore* core) {
189 UNUSED(core);
190 return 0;
191}
192
193static bool _DSCoreLoadState(struct mCore* core, const void* state) {
194 return false;
195}
196
197static bool _DSCoreSaveState(struct mCore* core, void* state) {
198 return false;
199}
200
201static void _DSCoreSetKeys(struct mCore* core, uint32_t keys) {
202 struct DSCore* dscore = (struct DSCore*) core;
203 dscore->keys = keys;
204}
205
206static void _DSCoreAddKeys(struct mCore* core, uint32_t keys) {
207 struct DSCore* dscore = (struct DSCore*) core;
208 dscore->keys |= keys;
209}
210
211static void _DSCoreClearKeys(struct mCore* core, uint32_t keys) {
212 struct DSCore* dscore = (struct DSCore*) core;
213 dscore->keys &= ~keys;
214}
215
216static int32_t _DSCoreFrameCounter(struct mCore* core) {
217 struct DS* ds = core->board;
218 return ds->video.frameCounter;
219}
220
221static int32_t _DSCoreFrameCycles(const struct mCore* core) {
222 UNUSED(core);
223 return DS_VIDEO_TOTAL_LENGTH;
224}
225
226static int32_t _DSCoreFrequency(const struct mCore* core) {
227 UNUSED(core);
228 return DS_ARM946ES_FREQUENCY;
229}
230
231static void _DSCoreGetGameTitle(const struct mCore* core, char* title) {
232 DSGetGameTitle(core->board, title);
233}
234
235static void _DSCoreGetGameCode(const struct mCore* core, char* title) {
236 DSGetGameCode(core->board, title);
237}
238
239static void _DSCoreSetRTC(struct mCore* core, struct mRTCSource* rtc) {
240 struct DS* ds = core->board;
241 ds->rtcSource = rtc;
242}
243
244static void _DSCoreSetRotation(struct mCore* core, struct mRotationSource* rotation) {
245}
246
247static void _DSCoreSetRumble(struct mCore* core, struct mRumble* rumble) {
248 struct DS* ds = core->board;
249 ds->rumble = rumble;
250}
251
252static uint32_t _DSCoreBusRead8(struct mCore* core, uint32_t address) {
253 struct ARMCore* cpu = core->cpu;
254 return cpu->memory.load8(cpu, address, 0);
255}
256
257static uint32_t _DSCoreBusRead16(struct mCore* core, uint32_t address) {
258 struct ARMCore* cpu = core->cpu;
259 return cpu->memory.load16(cpu, address, 0);
260
261}
262
263static uint32_t _DSCoreBusRead32(struct mCore* core, uint32_t address) {
264 struct ARMCore* cpu = core->cpu;
265 return cpu->memory.load32(cpu, address, 0);
266}
267
268static void _DSCoreBusWrite8(struct mCore* core, uint32_t address, uint8_t value) {
269 struct ARMCore* cpu = core->cpu;
270 cpu->memory.store8(cpu, address, value, 0);
271}
272
273static void _DSCoreBusWrite16(struct mCore* core, uint32_t address, uint16_t value) {
274 struct ARMCore* cpu = core->cpu;
275 cpu->memory.store16(cpu, address, value, 0);
276}
277
278static void _DSCoreBusWrite32(struct mCore* core, uint32_t address, uint32_t value) {
279 struct ARMCore* cpu = core->cpu;
280 cpu->memory.store32(cpu, address, value, 0);
281}
282
283static uint32_t _DSCoreRawRead8(struct mCore* core, uint32_t address, int segment) {
284 return 0;
285}
286
287static uint32_t _DSCoreRawRead16(struct mCore* core, uint32_t address, int segment) {
288 return 0;
289}
290
291static uint32_t _DSCoreRawRead32(struct mCore* core, uint32_t address, int segment) {
292 return 0;
293}
294
295static void _DSCoreRawWrite8(struct mCore* core, uint32_t address, int segment, uint8_t value) {
296}
297
298static void _DSCoreRawWrite16(struct mCore* core, uint32_t address, int segment, uint16_t value) {
299}
300
301static void _DSCoreRawWrite32(struct mCore* core, uint32_t address, int segment, uint32_t value) {
302}
303
304static bool _DSCoreSupportsDebuggerType(struct mCore* core, enum mDebuggerType type) {
305 UNUSED(core);
306 switch (type) {
307 case DEBUGGER_CLI:
308 return true;
309#ifdef USE_GDB_STUB
310 case DEBUGGER_GDB:
311 return true;
312#endif
313 default:
314 return false;
315 }
316}
317
318static struct mDebuggerPlatform* _DSCoreDebuggerPlatform(struct mCore* core) {
319 struct DSCore* dscore = (struct DSCore*) core;
320 if (!dscore->debuggerPlatform) {
321 dscore->debuggerPlatform = ARMDebuggerPlatformCreate();
322 }
323 return dscore->debuggerPlatform;
324}
325
326static struct CLIDebuggerSystem* _DSCoreCliDebuggerSystem(struct mCore* core) {
327 return &DSCLIDebuggerCreate(core)->d;
328}
329
330static void _DSCoreAttachDebugger(struct mCore* core, struct mDebugger* debugger) {
331 if (core->debugger) {
332 DSDetachDebugger(core->board);
333 }
334 DSAttachDebugger(core->board, debugger);
335 core->debugger = debugger;
336}
337
338static void _DSCoreDetachDebugger(struct mCore* core) {
339 DSDetachDebugger(core->board);
340 core->debugger = NULL;
341}
342
343static struct mCheatDevice* _DSCoreCheatDevice(struct mCore* core) {
344 return NULL;
345}
346
347static size_t _DSCoreSavedataClone(struct mCore* core, void** sram) {
348 return 0;
349}
350
351static bool _DSCoreSavedataRestore(struct mCore* core, const void* sram, size_t size, bool writeback) {
352 return false;
353}
354
355struct mCore* DSCoreCreate(void) {
356 struct DSCore* dscore = malloc(sizeof(*dscore));
357 struct mCore* core = &dscore->d;
358 memset(&core->opts, 0, sizeof(core->opts));
359 core->cpu = NULL;
360 core->board = NULL;
361 core->debugger = NULL;
362 core->init = _DSCoreInit;
363 core->deinit = _DSCoreDeinit;
364 core->platform = _DSCorePlatform;
365 core->setSync = _DSCoreSetSync;
366 core->loadConfig = _DSCoreLoadConfig;
367 core->desiredVideoDimensions = _DSCoreDesiredVideoDimensions;
368 core->setVideoBuffer = _DSCoreSetVideoBuffer;
369 core->getPixels = _DSCoreGetPixels;
370 core->putPixels = _DSCorePutPixels;
371 core->getAudioChannel = _DSCoreGetAudioChannel;
372 core->setAudioBufferSize = _DSCoreSetAudioBufferSize;
373 core->getAudioBufferSize = _DSCoreGetAudioBufferSize;
374 core->setCoreCallbacks = _DSCoreSetCoreCallbacks;
375 core->setAVStream = _DSCoreSetAVStream;
376 core->isROM = DSIsROM;
377 core->loadROM = _DSCoreLoadROM;
378 core->loadBIOS = _DSCoreLoadBIOS;
379 core->loadSave = _DSCoreLoadSave;
380 core->loadPatch = _DSCoreLoadPatch;
381 core->unloadROM = _DSCoreUnloadROM;
382 core->reset = _DSCoreReset;
383 core->runFrame = _DSCoreRunFrame;
384 core->runLoop = _DSCoreRunLoop;
385 core->step = _DSCoreStep;
386 core->stateSize = _DSCoreStateSize;
387 core->loadState = _DSCoreLoadState;
388 core->saveState = _DSCoreSaveState;
389 core->setKeys = _DSCoreSetKeys;
390 core->addKeys = _DSCoreAddKeys;
391 core->clearKeys = _DSCoreClearKeys;
392 core->frameCounter = _DSCoreFrameCounter;
393 core->frameCycles = _DSCoreFrameCycles;
394 core->frequency = _DSCoreFrequency;
395 core->getGameTitle = _DSCoreGetGameTitle;
396 core->getGameCode = _DSCoreGetGameCode;
397 core->setRTC = _DSCoreSetRTC;
398 core->setRotation = _DSCoreSetRotation;
399 core->setRumble = _DSCoreSetRumble;
400 core->busRead8 = _DSCoreBusRead8;
401 core->busRead16 = _DSCoreBusRead16;
402 core->busRead32 = _DSCoreBusRead32;
403 core->busWrite8 = _DSCoreBusWrite8;
404 core->busWrite16 = _DSCoreBusWrite16;
405 core->busWrite32 = _DSCoreBusWrite32;
406 core->rawRead8 = _DSCoreRawRead8;
407 core->rawRead16 = _DSCoreRawRead16;
408 core->rawRead32 = _DSCoreRawRead32;
409 core->rawWrite8 = _DSCoreRawWrite8;
410 core->rawWrite16 = _DSCoreRawWrite16;
411 core->rawWrite32 = _DSCoreRawWrite32;
412#ifdef USE_DEBUGGERS
413 core->supportsDebuggerType = _DSCoreSupportsDebuggerType;
414 core->debuggerPlatform = _DSCoreDebuggerPlatform;
415 core->cliDebuggerSystem = _DSCoreCliDebuggerSystem;
416 core->attachDebugger = _DSCoreAttachDebugger;
417 core->detachDebugger = _DSCoreDetachDebugger;
418#endif
419 core->cheatDevice = _DSCoreCheatDevice;
420 core->savedataClone = _DSCoreSavedataClone;
421 core->savedataRestore = _DSCoreSavedataRestore;
422 return core;
423}