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 "core.h"
7
8#include "core/core.h"
9#include "gb/gb.h"
10#include "gb/renderers/software.h"
11#include "util/memory.h"
12
13struct GBCore {
14 struct mCore d;
15 struct GBVideoSoftwareRenderer renderer;
16 uint8_t keys;
17};
18
19static bool _GBCoreInit(struct mCore* core) {
20 struct GBCore* gbcore = (struct GBCore*) core;
21
22 struct LR35902Core* cpu = anonymousMemoryMap(sizeof(struct LR35902Core));
23 struct GB* gb = anonymousMemoryMap(sizeof(struct GB));
24 if (!cpu || !gb) {
25 free(cpu);
26 free(gb);
27 return false;
28 }
29 core->cpu = cpu;
30 core->board = gb;
31
32 GBCreate(gb);
33 LR35902SetComponents(cpu, &gb->d, 0, 0);
34 LR35902Init(cpu);
35
36 GBVideoSoftwareRendererCreate(&gbcore->renderer);
37 GBVideoAssociateRenderer(&gb->video, &gbcore->renderer.d);
38
39 gb->keySource = &gbcore->keys;
40
41#if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2
42 mDirectorySetInit(&core->dirs);
43#endif
44
45 return true;
46}
47
48static void _GBCoreDeinit(struct mCore* core) {
49 LR35902Deinit(core->cpu);
50 GBDestroy(core->board);
51 mappedMemoryFree(core->cpu, sizeof(struct LR35902Core));
52 mappedMemoryFree(core->board, sizeof(struct GB));
53#if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2
54 mDirectorySetDeinit(&core->dirs);
55#endif
56}
57
58static void _GBCoreSetSync(struct mCore* core, struct mCoreSync* sync) {
59 struct GB* gb = core->board;
60 gb->sync = sync;
61}
62
63static void _GBCoreDesiredVideoDimensions(struct mCore* core, unsigned* width, unsigned* height) {
64 UNUSED(core);
65 *width = GB_VIDEO_HORIZONTAL_PIXELS;
66 *height = GB_VIDEO_VERTICAL_PIXELS;
67}
68
69static void _GBCoreSetVideoBuffer(struct mCore* core, color_t* buffer, size_t stride) {
70 struct GBCore* gbcore = (struct GBCore*) core;
71 gbcore->renderer.outputBuffer = buffer;
72 gbcore->renderer.outputBufferStride = stride;
73}
74
75static bool _GBCoreLoadROM(struct mCore* core, struct VFile* vf) {
76 return GBLoadROM(core->board, vf);
77}
78
79static bool _GBCoreLoadSave(struct mCore* core, struct VFile* vf) {
80 return GBLoadSave(core->board, vf);
81}
82
83static void _GBCoreUnloadROM(struct mCore* core) {
84 return GBUnloadROM(core->board);
85}
86
87static void _GBCoreReset(struct mCore* core) {
88 LR35902Reset(core->cpu);
89}
90
91static void _GBCoreRunFrame(struct mCore* core) {
92 struct GB* gb = core->board;
93 int32_t frameCounter = gb->video.frameCounter;
94 while (gb->video.frameCounter == frameCounter) {
95 LR35902Run(core->cpu);
96 }
97}
98
99static void _GBCoreRunLoop(struct mCore* core) {
100 LR35902Run(core->cpu);
101}
102
103static void _GBCoreStep(struct mCore* core) {
104 LR35902Tick(core->cpu);
105}
106
107static void _GBCoreSetKeys(struct mCore* core, uint32_t keys) {
108 struct GBCore* gbcore = (struct GBCore*) core;
109 gbcore->keys = keys;
110}
111
112static void _GBCoreAddKeys(struct mCore* core, uint32_t keys) {
113 struct GBCore* gbcore = (struct GBCore*) core;
114 gbcore->keys |= keys;
115}
116
117static void _GBCoreClearKeys(struct mCore* core, uint32_t keys) {
118 struct GBCore* gbcore = (struct GBCore*) core;
119 gbcore->keys &= ~keys;
120}
121
122static int32_t _GBCoreFrameCounter(struct mCore* core) {
123 struct GB* gb = core->board;
124 return gb->video.frameCounter;
125}
126
127static int32_t _GBCoreFrameCycles(struct mCore* core) {
128 UNUSED(core);
129 return GB_VIDEO_TOTAL_LENGTH;
130}
131
132static int32_t _GBCoreFrequency(struct mCore* core) {
133 UNUSED(core);
134 // TODO: GB differences
135 return DMG_LR35902_FREQUENCY;
136}
137
138static void _GBCoreSetRTC(struct mCore* core, struct mRTCSource* rtc) {
139 struct GB* gb = core->board;
140 gb->memory.rtc = rtc;
141}
142
143struct mCore* GBCoreCreate(void) {
144 struct GBCore* gbcore = malloc(sizeof(*gbcore));
145 struct mCore* core = &gbcore->d;
146 core->cpu = 0;
147 core->board = 0;
148 core->init = _GBCoreInit;
149 core->deinit = _GBCoreDeinit;
150 core->setSync = _GBCoreSetSync;
151 core->desiredVideoDimensions = _GBCoreDesiredVideoDimensions;
152 core->setVideoBuffer = _GBCoreSetVideoBuffer;
153 core->isROM = GBIsROM;
154 core->loadROM = _GBCoreLoadROM;
155 core->loadSave = _GBCoreLoadSave;
156 core->unloadROM = _GBCoreUnloadROM;
157 core->reset = _GBCoreReset;
158 core->runFrame = _GBCoreRunFrame;
159 core->runLoop = _GBCoreRunLoop;
160 core->step = _GBCoreStep;
161 core->setKeys = _GBCoreSetKeys;
162 core->addKeys = _GBCoreAddKeys;
163 core->clearKeys = _GBCoreClearKeys;
164 core->frameCounter = _GBCoreFrameCounter;
165 core->frameCycles = _GBCoreFrameCycles;
166 core->frequency = _GBCoreFrequency;
167 core->setRTC = _GBCoreSetRTC;
168 return core;
169}