src/gb/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/gb/core.h>
7
8#include <mgba/core/core.h>
9#include <mgba/internal/gb/cheats.h>
10#include <mgba/internal/gb/extra/cli.h>
11#include <mgba/internal/gb/gb.h>
12#include <mgba/internal/gb/mbc.h>
13#include <mgba/internal/gb/overrides.h>
14#include <mgba/internal/gb/renderers/software.h>
15#include <mgba/internal/gb/serialize.h>
16#include <mgba/internal/lr35902/lr35902.h>
17#include <mgba/internal/lr35902/debugger/debugger.h>
18#include <mgba-util/crc32.h>
19#include <mgba-util/memory.h>
20#include <mgba-util/patch.h>
21#include <mgba-util/vfs.h>
22
23const static struct mCoreChannelInfo _GBVideoLayers[] = {
24 { 0, "bg", "Background", NULL },
25 { 1, "obj", "Objects", NULL },
26 { 2, "win", "Window", NULL },
27};
28
29const static struct mCoreChannelInfo _GBAudioChannels[] = {
30 { 0, "ch0", "Channel 0", "Square/Sweep" },
31 { 1, "ch1", "Channel 1", "Square" },
32 { 2, "ch2", "Channel 2", "PCM" },
33 { 3, "ch3", "Channel 3", "Noise" },
34};
35
36struct GBCore {
37 struct mCore d;
38 struct GBVideoSoftwareRenderer renderer;
39 uint8_t keys;
40 struct mCPUComponent* components[CPU_COMPONENT_MAX];
41 const struct Configuration* overrides;
42 struct mDebuggerPlatform* debuggerPlatform;
43 struct mCheatDevice* cheatDevice;
44};
45
46static bool _GBCoreInit(struct mCore* core) {
47 struct GBCore* gbcore = (struct GBCore*) core;
48
49 struct LR35902Core* cpu = anonymousMemoryMap(sizeof(struct LR35902Core));
50 struct GB* gb = anonymousMemoryMap(sizeof(struct GB));
51 if (!cpu || !gb) {
52 free(cpu);
53 free(gb);
54 return false;
55 }
56 core->cpu = cpu;
57 core->board = gb;
58 gbcore->overrides = NULL;
59 gbcore->debuggerPlatform = NULL;
60 gbcore->cheatDevice = NULL;
61
62 GBCreate(gb);
63 memset(gbcore->components, 0, sizeof(gbcore->components));
64 LR35902SetComponents(cpu, &gb->d, CPU_COMPONENT_MAX, gbcore->components);
65 LR35902Init(cpu);
66 mRTCGenericSourceInit(&core->rtc, core);
67 gb->memory.rtc = &core->rtc.d;
68
69 GBVideoSoftwareRendererCreate(&gbcore->renderer);
70 gbcore->renderer.outputBuffer = NULL;
71
72 gbcore->keys = 0;
73 gb->keySource = &gbcore->keys;
74
75#if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2
76 mDirectorySetInit(&core->dirs);
77#endif
78
79 return true;
80}
81
82static void _GBCoreDeinit(struct mCore* core) {
83 LR35902Deinit(core->cpu);
84 GBDestroy(core->board);
85 mappedMemoryFree(core->cpu, sizeof(struct LR35902Core));
86 mappedMemoryFree(core->board, sizeof(struct GB));
87#if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2
88 mDirectorySetDeinit(&core->dirs);
89#endif
90
91 struct GBCore* gbcore = (struct GBCore*) core;
92 free(gbcore->debuggerPlatform);
93 if (gbcore->cheatDevice) {
94 mCheatDeviceDestroy(gbcore->cheatDevice);
95 }
96 free(gbcore->cheatDevice);
97 mCoreConfigFreeOpts(&core->opts);
98 free(core);
99}
100
101static enum mPlatform _GBCorePlatform(const struct mCore* core) {
102 UNUSED(core);
103 return PLATFORM_GB;
104}
105
106static void _GBCoreSetSync(struct mCore* core, struct mCoreSync* sync) {
107 struct GB* gb = core->board;
108 gb->sync = sync;
109}
110
111static void _GBCoreLoadConfig(struct mCore* core, const struct mCoreConfig* config) {
112 UNUSED(config);
113
114 struct GB* gb = core->board;
115 if (core->opts.mute) {
116 gb->audio.masterVolume = 0;
117 } else {
118 gb->audio.masterVolume = core->opts.volume;
119 }
120 gb->video.frameskip = core->opts.frameskip;
121
122 int color;
123 if (mCoreConfigGetIntValue(&core->config, "gb.pal[0]", &color)) {
124 GBVideoSetPalette(&gb->video, 0, color);
125 }
126 if (mCoreConfigGetIntValue(&core->config, "gb.pal[1]", &color)) {
127 GBVideoSetPalette(&gb->video, 1, color);
128 }
129 if (mCoreConfigGetIntValue(&core->config, "gb.pal[2]", &color)) {
130 GBVideoSetPalette(&gb->video, 2, color);
131 }
132 if (mCoreConfigGetIntValue(&core->config, "gb.pal[3]", &color)) {
133 GBVideoSetPalette(&gb->video, 3, color);
134 }
135
136 mCoreConfigCopyValue(&core->config, config, "gb.bios");
137 mCoreConfigCopyValue(&core->config, config, "gbc.bios");
138
139#if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2
140 struct GBCore* gbcore = (struct GBCore*) core;
141 gbcore->overrides = mCoreConfigGetOverridesConst(config);
142#endif
143}
144
145static void _GBCoreDesiredVideoDimensions(struct mCore* core, unsigned* width, unsigned* height) {
146 UNUSED(core);
147 *width = GB_VIDEO_HORIZONTAL_PIXELS;
148 *height = GB_VIDEO_VERTICAL_PIXELS;
149}
150
151static void _GBCoreSetVideoBuffer(struct mCore* core, color_t* buffer, size_t stride) {
152 struct GBCore* gbcore = (struct GBCore*) core;
153 gbcore->renderer.outputBuffer = buffer;
154 gbcore->renderer.outputBufferStride = stride;
155}
156
157static void _GBCoreGetPixels(struct mCore* core, const void** buffer, size_t* stride) {
158 struct GBCore* gbcore = (struct GBCore*) core;
159 gbcore->renderer.d.getPixels(&gbcore->renderer.d, stride, buffer);
160}
161
162static void _GBCorePutPixels(struct mCore* core, const void* buffer, size_t stride) {
163 struct GBCore* gbcore = (struct GBCore*) core;
164 gbcore->renderer.d.putPixels(&gbcore->renderer.d, stride, buffer);
165}
166
167static struct blip_t* _GBCoreGetAudioChannel(struct mCore* core, int ch) {
168 struct GB* gb = core->board;
169 switch (ch) {
170 case 0:
171 return gb->audio.left;
172 case 1:
173 return gb->audio.right;
174 default:
175 return NULL;
176 }
177}
178
179static void _GBCoreSetAudioBufferSize(struct mCore* core, size_t samples) {
180 struct GB* gb = core->board;
181 GBAudioResizeBuffer(&gb->audio, samples);
182}
183
184static size_t _GBCoreGetAudioBufferSize(struct mCore* core) {
185 struct GB* gb = core->board;
186 return gb->audio.samples;
187}
188
189static void _GBCoreAddCoreCallbacks(struct mCore* core, struct mCoreCallbacks* coreCallbacks) {
190 struct GB* gb = core->board;
191 *mCoreCallbacksListAppend(&gb->coreCallbacks) = *coreCallbacks;
192}
193
194static void _GBCoreClearCoreCallbacks(struct mCore* core) {
195 struct GB* gb = core->board;
196 mCoreCallbacksListClear(&gb->coreCallbacks);
197}
198
199static void _GBCoreSetAVStream(struct mCore* core, struct mAVStream* stream) {
200 struct GB* gb = core->board;
201 gb->stream = stream;
202 if (stream && stream->videoDimensionsChanged) {
203 stream->videoDimensionsChanged(stream, GB_VIDEO_HORIZONTAL_PIXELS, GB_VIDEO_VERTICAL_PIXELS);
204 }
205}
206
207static bool _GBCoreLoadROM(struct mCore* core, struct VFile* vf) {
208 return GBLoadROM(core->board, vf);
209}
210
211static bool _GBCoreLoadBIOS(struct mCore* core, struct VFile* vf, int type) {
212 UNUSED(type);
213 GBLoadBIOS(core->board, vf);
214 return true;
215}
216
217static bool _GBCoreLoadSave(struct mCore* core, struct VFile* vf) {
218 return GBLoadSave(core->board, vf);
219}
220
221static bool _GBCoreLoadTemporarySave(struct mCore* core, struct VFile* vf) {
222 struct GB* gb = core->board;
223 GBSavedataMask(gb, vf, false);
224 return true; // TODO: Return a real value
225}
226
227static bool _GBCoreLoadPatch(struct mCore* core, struct VFile* vf) {
228 if (!vf) {
229 return false;
230 }
231 struct Patch patch;
232 if (!loadPatch(vf, &patch)) {
233 return false;
234 }
235 GBApplyPatch(core->board, &patch);
236 return true;
237}
238
239static void _GBCoreUnloadROM(struct mCore* core) {
240 struct GBCore* gbcore = (struct GBCore*) core;
241 struct LR35902Core* cpu = core->cpu;
242 if (gbcore->cheatDevice) {
243 LR35902HotplugDetach(cpu, CPU_COMPONENT_CHEAT_DEVICE);
244 cpu->components[CPU_COMPONENT_CHEAT_DEVICE] = NULL;
245 mCheatDeviceDestroy(gbcore->cheatDevice);
246 gbcore->cheatDevice = NULL;
247 }
248 return GBUnloadROM(core->board);
249}
250
251static void _GBCoreChecksum(const struct mCore* core, void* data, enum mCoreChecksumType type) {
252 struct GB* gb = (struct GB*) core->board;
253 switch (type) {
254 case CHECKSUM_CRC32:
255 memcpy(data, &gb->romCrc32, sizeof(gb->romCrc32));
256 break;
257 }
258 return;
259}
260
261static void _GBCoreReset(struct mCore* core) {
262 struct GBCore* gbcore = (struct GBCore*) core;
263 struct GB* gb = (struct GB*) core->board;
264 if (gbcore->renderer.outputBuffer) {
265 GBVideoAssociateRenderer(&gb->video, &gbcore->renderer.d);
266 }
267
268 if (gb->memory.rom) {
269 struct GBCartridgeOverride override;
270 const struct GBCartridge* cart = (const struct GBCartridge*) &gb->memory.rom[0x100];
271 override.headerCrc32 = doCrc32(cart, sizeof(*cart));
272 if (GBOverrideFind(gbcore->overrides, &override)) {
273 GBOverrideApply(gb, &override);
274 }
275 }
276
277#if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2
278 if (!gb->biosVf && core->opts.useBios) {
279 struct VFile* bios = NULL;
280 bool found = false;
281 if (core->opts.bios) {
282 bios = VFileOpen(core->opts.bios, O_RDONLY);
283 if (bios && GBIsBIOS(bios)) {
284 found = true;
285 } else if (bios) {
286 bios->close(bios);
287 bios = NULL;
288 }
289 }
290 if (!found) {
291 GBDetectModel(gb);
292 const char* configPath = NULL;
293
294 switch (gb->model) {
295 case GB_MODEL_DMG:
296 case GB_MODEL_SGB: // TODO
297 configPath = mCoreConfigGetValue(&core->config, "gb.bios");
298 break;
299 case GB_MODEL_CGB:
300 case GB_MODEL_AGB:
301 configPath = mCoreConfigGetValue(&core->config, "gbc.bios");
302 break;
303 default:
304 break;
305 };
306 if (configPath) {
307 bios = VFileOpen(configPath, O_RDONLY);
308 }
309 if (bios && GBIsBIOS(bios)) {
310 found = true;
311 } else if (bios) {
312 bios->close(bios);
313 bios = NULL;
314 }
315 }
316 if (!found) {
317 char path[PATH_MAX];
318 mCoreConfigDirectory(path, PATH_MAX);
319 switch (gb->model) {
320 case GB_MODEL_DMG:
321 case GB_MODEL_SGB: // TODO
322 strncat(path, PATH_SEP "gb_bios.bin", PATH_MAX - strlen(path));
323 break;
324 case GB_MODEL_CGB:
325 case GB_MODEL_AGB:
326 strncat(path, PATH_SEP "gbc_bios.bin", PATH_MAX - strlen(path));
327 break;
328 default:
329 break;
330 };
331 bios = VFileOpen(path, O_RDONLY);
332 if (bios && GBIsBIOS(bios)) {
333 found = true;
334 } else if (bios) {
335 bios->close(bios);
336 bios = NULL;
337 }
338 }
339 if (bios) {
340 GBLoadBIOS(gb, bios);
341 }
342 }
343#endif
344
345 LR35902Reset(core->cpu);
346}
347
348static void _GBCoreRunFrame(struct mCore* core) {
349 struct GB* gb = core->board;
350 int32_t frameCounter = gb->video.frameCounter;
351 while (gb->video.frameCounter == frameCounter) {
352 LR35902Run(core->cpu);
353 }
354}
355
356static void _GBCoreRunLoop(struct mCore* core) {
357 LR35902Run(core->cpu);
358}
359
360static void _GBCoreStep(struct mCore* core) {
361 struct LR35902Core* cpu = core->cpu;
362 do {
363 LR35902Tick(cpu);
364 } while (cpu->executionState != LR35902_CORE_FETCH);
365}
366
367static size_t _GBCoreStateSize(struct mCore* core) {
368 UNUSED(core);
369 return sizeof(struct GBSerializedState);
370}
371
372static bool _GBCoreLoadState(struct mCore* core, const void* state) {
373 return GBDeserialize(core->board, state);
374}
375
376static bool _GBCoreSaveState(struct mCore* core, void* state) {
377 struct LR35902Core* cpu = core->cpu;
378 while (cpu->executionState != LR35902_CORE_FETCH) {
379 LR35902Tick(cpu);
380 }
381 GBSerialize(core->board, state);
382 return true;
383}
384
385static void _GBCoreSetKeys(struct mCore* core, uint32_t keys) {
386 struct GBCore* gbcore = (struct GBCore*) core;
387 gbcore->keys = keys;
388}
389
390static void _GBCoreAddKeys(struct mCore* core, uint32_t keys) {
391 struct GBCore* gbcore = (struct GBCore*) core;
392 gbcore->keys |= keys;
393}
394
395static void _GBCoreClearKeys(struct mCore* core, uint32_t keys) {
396 struct GBCore* gbcore = (struct GBCore*) core;
397 gbcore->keys &= ~keys;
398}
399
400static int32_t _GBCoreFrameCounter(const struct mCore* core) {
401 const struct GB* gb = core->board;
402 return gb->video.frameCounter;
403}
404
405static int32_t _GBCoreFrameCycles(const struct mCore* core) {
406 UNUSED(core);
407 return GB_VIDEO_TOTAL_LENGTH;
408}
409
410static int32_t _GBCoreFrequency(const struct mCore* core) {
411 UNUSED(core);
412 // TODO: GB differences
413 return DMG_LR35902_FREQUENCY;
414}
415
416static void _GBCoreGetGameTitle(const struct mCore* core, char* title) {
417 GBGetGameTitle(core->board, title);
418}
419
420static void _GBCoreGetGameCode(const struct mCore* core, char* title) {
421 GBGetGameCode(core->board, title);
422}
423
424static void _GBCoreSetPeripheral(struct mCore* core, int type, void* periph) {
425 struct GB* gb = core->board;
426 switch (type) {
427 case mPERIPH_ROTATION:
428 gb->memory.rotation = periph;
429 break;
430 case mPERIPH_RUMBLE:
431 gb->memory.rumble = periph;
432 break;
433 default:
434 return;
435 }
436}
437
438static uint32_t _GBCoreBusRead8(struct mCore* core, uint32_t address) {
439 struct LR35902Core* cpu = core->cpu;
440 return cpu->memory.load8(cpu, address);
441}
442
443static uint32_t _GBCoreBusRead16(struct mCore* core, uint32_t address) {
444 struct LR35902Core* cpu = core->cpu;
445 return cpu->memory.load8(cpu, address) | (cpu->memory.load8(cpu, address + 1) << 8);
446}
447
448static uint32_t _GBCoreBusRead32(struct mCore* core, uint32_t address) {
449 struct LR35902Core* cpu = core->cpu;
450 return cpu->memory.load8(cpu, address) | (cpu->memory.load8(cpu, address + 1) << 8) |
451 (cpu->memory.load8(cpu, address + 2) << 16) | (cpu->memory.load8(cpu, address + 3) << 24);
452}
453
454static void _GBCoreBusWrite8(struct mCore* core, uint32_t address, uint8_t value) {
455 struct LR35902Core* cpu = core->cpu;
456 cpu->memory.store8(cpu, address, value);
457}
458
459static void _GBCoreBusWrite16(struct mCore* core, uint32_t address, uint16_t value) {
460 struct LR35902Core* cpu = core->cpu;
461 cpu->memory.store8(cpu, address, value);
462 cpu->memory.store8(cpu, address + 1, value >> 8);
463}
464
465static void _GBCoreBusWrite32(struct mCore* core, uint32_t address, uint32_t value) {
466 struct LR35902Core* cpu = core->cpu;
467 cpu->memory.store8(cpu, address, value);
468 cpu->memory.store8(cpu, address + 1, value >> 8);
469 cpu->memory.store8(cpu, address + 2, value >> 16);
470 cpu->memory.store8(cpu, address + 3, value >> 24);
471}
472
473static uint32_t _GBCoreRawRead8(struct mCore* core, uint32_t address, int segment) {
474 struct LR35902Core* cpu = core->cpu;
475 return GBView8(cpu, address, segment);
476}
477
478static uint32_t _GBCoreRawRead16(struct mCore* core, uint32_t address, int segment) {
479 struct LR35902Core* cpu = core->cpu;
480 return GBView8(cpu, address, segment) | (GBView8(cpu, address + 1, segment) << 8);
481}
482
483static uint32_t _GBCoreRawRead32(struct mCore* core, uint32_t address, int segment) {
484 struct LR35902Core* cpu = core->cpu;
485 return GBView8(cpu, address, segment) | (GBView8(cpu, address + 1, segment) << 8) |
486 (GBView8(cpu, address + 2, segment) << 16) | (GBView8(cpu, address + 3, segment) << 24);
487}
488
489static void _GBCoreRawWrite8(struct mCore* core, uint32_t address, int segment, uint8_t value) {
490 struct LR35902Core* cpu = core->cpu;
491 GBPatch8(cpu, address, value, NULL, segment);
492}
493
494static void _GBCoreRawWrite16(struct mCore* core, uint32_t address, int segment, uint16_t value) {
495 struct LR35902Core* cpu = core->cpu;
496 GBPatch8(cpu, address, value, NULL, segment);
497 GBPatch8(cpu, address + 1, value >> 8, NULL, segment);
498}
499
500static void _GBCoreRawWrite32(struct mCore* core, uint32_t address, int segment, uint32_t value) {
501 struct LR35902Core* cpu = core->cpu;
502 GBPatch8(cpu, address, value, NULL, segment);
503 GBPatch8(cpu, address + 1, value >> 8, NULL, segment);
504 GBPatch8(cpu, address + 2, value >> 16, NULL, segment);
505 GBPatch8(cpu, address + 3, value >> 24, NULL, segment);
506}
507
508#ifdef USE_DEBUGGERS
509static bool _GBCoreSupportsDebuggerType(struct mCore* core, enum mDebuggerType type) {
510 UNUSED(core);
511 switch (type) {
512 case DEBUGGER_CLI:
513 return true;
514 default:
515 return false;
516 }
517}
518
519static struct mDebuggerPlatform* _GBCoreDebuggerPlatform(struct mCore* core) {
520 struct GBCore* gbcore = (struct GBCore*) core;
521 if (!gbcore->debuggerPlatform) {
522 gbcore->debuggerPlatform = LR35902DebuggerPlatformCreate();
523 }
524 return gbcore->debuggerPlatform;
525}
526
527static struct CLIDebuggerSystem* _GBCoreCliDebuggerSystem(struct mCore* core) {
528 return GBCLIDebuggerCreate(core);
529}
530
531static void _GBCoreAttachDebugger(struct mCore* core, struct mDebugger* debugger) {
532 struct LR35902Core* cpu = core->cpu;
533 if (core->debugger) {
534 LR35902HotplugDetach(cpu, CPU_COMPONENT_DEBUGGER);
535 }
536 cpu->components[CPU_COMPONENT_DEBUGGER] = &debugger->d;
537 LR35902HotplugAttach(cpu, CPU_COMPONENT_DEBUGGER);
538 core->debugger = debugger;
539}
540
541static void _GBCoreDetachDebugger(struct mCore* core) {
542 struct LR35902Core* cpu = core->cpu;
543 if (core->debugger) {
544 LR35902HotplugDetach(cpu, CPU_COMPONENT_DEBUGGER);
545 }
546 cpu->components[CPU_COMPONENT_DEBUGGER] = NULL;
547 core->debugger = NULL;
548}
549#endif
550
551static struct mCheatDevice* _GBCoreCheatDevice(struct mCore* core) {
552 struct GBCore* gbcore = (struct GBCore*) core;
553 if (!gbcore->cheatDevice) {
554 gbcore->cheatDevice = GBCheatDeviceCreate();
555 ((struct LR35902Core*) core->cpu)->components[CPU_COMPONENT_CHEAT_DEVICE] = &gbcore->cheatDevice->d;
556 LR35902HotplugAttach(core->cpu, CPU_COMPONENT_CHEAT_DEVICE);
557 gbcore->cheatDevice->p = core;
558 }
559 return gbcore->cheatDevice;
560}
561
562static size_t _GBCoreSavedataClone(struct mCore* core, void** sram) {
563 struct GB* gb = core->board;
564 struct VFile* vf = gb->sramVf;
565 if (vf) {
566 *sram = malloc(vf->size(vf));
567 vf->seek(vf, 0, SEEK_SET);
568 return vf->read(vf, *sram, vf->size(vf));
569 }
570 *sram = malloc(gb->sramSize);
571 memcpy(*sram, gb->memory.sram, gb->sramSize);
572 return gb->sramSize;
573}
574
575static bool _GBCoreSavedataRestore(struct mCore* core, const void* sram, size_t size, bool writeback) {
576 struct GB* gb = core->board;
577 if (!writeback) {
578 struct VFile* vf = VFileMemChunk(sram, size);
579 GBSavedataMask(gb, vf, true);
580 return true;
581 }
582 struct VFile* vf = gb->sramVf;
583 if (vf) {
584 vf->seek(vf, 0, SEEK_SET);
585 return vf->write(vf, sram, size) > 0;
586 }
587 if (size > 0x20000) {
588 size = 0x20000;
589 }
590 GBResizeSram(gb, size);
591 memcpy(gb->memory.sram, sram, size);
592 return true;
593}
594
595static size_t _GBCoreListVideoLayers(const struct mCore* core, const struct mCoreChannelInfo** info) {
596 UNUSED(core);
597 *info = _GBVideoLayers;
598 return sizeof(_GBVideoLayers) / sizeof(*_GBVideoLayers);
599}
600
601static size_t _GBCoreListAudioChannels(const struct mCore* core, const struct mCoreChannelInfo** info) {
602 UNUSED(core);
603 *info = _GBAudioChannels;
604 return sizeof(_GBAudioChannels) / sizeof(*_GBAudioChannels);
605}
606
607static void _GBCoreEnableVideoLayer(struct mCore* core, size_t id, bool enable) {
608 struct GB* gb = core->board;
609 switch (id) {
610 case 0:
611 gb->video.renderer->disableBG = !enable;
612 break;
613 case 1:
614 gb->video.renderer->disableOBJ = !enable;
615 break;
616 case 2:
617 gb->video.renderer->disableWIN = !enable;
618 break;
619 default:
620 break;
621 }
622}
623
624static void _GBCoreEnableAudioChannel(struct mCore* core, size_t id, bool enable) {
625 struct GB* gb = core->board;
626 switch (id) {
627 case 0:
628 case 1:
629 case 2:
630 case 3:
631 gb->audio.forceDisableCh[id] = !enable;
632 break;
633 default:
634 break;
635 }
636}
637
638struct mCore* GBCoreCreate(void) {
639 struct GBCore* gbcore = malloc(sizeof(*gbcore));
640 struct mCore* core = &gbcore->d;
641 memset(&core->opts, 0, sizeof(core->opts));
642 core->cpu = NULL;
643 core->board = NULL;
644 core->debugger = NULL;
645 core->init = _GBCoreInit;
646 core->deinit = _GBCoreDeinit;
647 core->platform = _GBCorePlatform;
648 core->setSync = _GBCoreSetSync;
649 core->loadConfig = _GBCoreLoadConfig;
650 core->desiredVideoDimensions = _GBCoreDesiredVideoDimensions;
651 core->setVideoBuffer = _GBCoreSetVideoBuffer;
652 core->getPixels = _GBCoreGetPixels;
653 core->putPixels = _GBCorePutPixels;
654 core->getAudioChannel = _GBCoreGetAudioChannel;
655 core->setAudioBufferSize = _GBCoreSetAudioBufferSize;
656 core->getAudioBufferSize = _GBCoreGetAudioBufferSize;
657 core->setAVStream = _GBCoreSetAVStream;
658 core->addCoreCallbacks = _GBCoreAddCoreCallbacks;
659 core->clearCoreCallbacks = _GBCoreClearCoreCallbacks;
660 core->isROM = GBIsROM;
661 core->loadROM = _GBCoreLoadROM;
662 core->loadBIOS = _GBCoreLoadBIOS;
663 core->loadSave = _GBCoreLoadSave;
664 core->loadTemporarySave = _GBCoreLoadTemporarySave;
665 core->loadPatch = _GBCoreLoadPatch;
666 core->unloadROM = _GBCoreUnloadROM;
667 core->checksum = _GBCoreChecksum;
668 core->reset = _GBCoreReset;
669 core->runFrame = _GBCoreRunFrame;
670 core->runLoop = _GBCoreRunLoop;
671 core->step = _GBCoreStep;
672 core->stateSize = _GBCoreStateSize;
673 core->loadState = _GBCoreLoadState;
674 core->saveState = _GBCoreSaveState;
675 core->setKeys = _GBCoreSetKeys;
676 core->addKeys = _GBCoreAddKeys;
677 core->clearKeys = _GBCoreClearKeys;
678 core->frameCounter = _GBCoreFrameCounter;
679 core->frameCycles = _GBCoreFrameCycles;
680 core->frequency = _GBCoreFrequency;
681 core->getGameTitle = _GBCoreGetGameTitle;
682 core->getGameCode = _GBCoreGetGameCode;
683 core->setPeripheral = _GBCoreSetPeripheral;
684 core->busRead8 = _GBCoreBusRead8;
685 core->busRead16 = _GBCoreBusRead16;
686 core->busRead32 = _GBCoreBusRead32;
687 core->busWrite8 = _GBCoreBusWrite8;
688 core->busWrite16 = _GBCoreBusWrite16;
689 core->busWrite32 = _GBCoreBusWrite32;
690 core->rawRead8 = _GBCoreRawRead8;
691 core->rawRead16 = _GBCoreRawRead16;
692 core->rawRead32 = _GBCoreRawRead32;
693 core->rawWrite8 = _GBCoreRawWrite8;
694 core->rawWrite16 = _GBCoreRawWrite16;
695 core->rawWrite32 = _GBCoreRawWrite32;
696#ifdef USE_DEBUGGERS
697 core->supportsDebuggerType = _GBCoreSupportsDebuggerType;
698 core->debuggerPlatform = _GBCoreDebuggerPlatform;
699 core->cliDebuggerSystem = _GBCoreCliDebuggerSystem;
700 core->attachDebugger = _GBCoreAttachDebugger;
701 core->detachDebugger = _GBCoreDetachDebugger;
702#endif
703 core->cheatDevice = _GBCoreCheatDevice;
704 core->savedataClone = _GBCoreSavedataClone;
705 core->savedataRestore = _GBCoreSavedataRestore;
706 core->listVideoLayers = _GBCoreListVideoLayers;
707 core->listAudioChannels = _GBCoreListAudioChannels;
708 core->enableVideoLayer = _GBCoreEnableVideoLayer;
709 core->enableAudioChannel = _GBCoreEnableAudioChannel;
710 return core;
711}