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