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