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 struct blip_t* _GBCoreGetAudioChannel(struct mCore* core, int ch) {
76 struct GB* gb = core->board;
77 switch (ch) {
78 case 0:
79 return gb->audio.left;
80 case 1:
81 return gb->audio.right;
82 default:
83 return NULL;
84 }
85}
86
87static bool _GBCoreLoadROM(struct mCore* core, struct VFile* vf) {
88 return GBLoadROM(core->board, vf);
89}
90
91static bool _GBCoreLoadSave(struct mCore* core, struct VFile* vf) {
92 return GBLoadSave(core->board, vf);
93}
94
95static bool _GBCoreLoadPatch(struct mCore* core, struct VFile* vf) {
96 // TODO
97 UNUSED(core);
98 UNUSED(vf);
99 mLOG(GB, STUB, "Patches are not yet supported");
100 return false;
101}
102
103static void _GBCoreUnloadROM(struct mCore* core) {
104 return GBUnloadROM(core->board);
105}
106
107static void _GBCoreReset(struct mCore* core) {
108 LR35902Reset(core->cpu);
109}
110
111static void _GBCoreRunFrame(struct mCore* core) {
112 struct GB* gb = core->board;
113 int32_t frameCounter = gb->video.frameCounter;
114 while (gb->video.frameCounter == frameCounter) {
115 LR35902Run(core->cpu);
116 }
117}
118
119static void _GBCoreRunLoop(struct mCore* core) {
120 LR35902Run(core->cpu);
121}
122
123static void _GBCoreStep(struct mCore* core) {
124 LR35902Tick(core->cpu);
125}
126
127static bool _GBCoreLoadState(struct mCore* core, struct VFile* vf, int flags) {
128 UNUSED(core);
129 UNUSED(vf);
130 UNUSED(flags);
131 // TODO
132 return false;
133}
134
135static bool _GBCoreSaveState(struct mCore* core, struct VFile* vf, int flags) {
136 UNUSED(core);
137 UNUSED(vf);
138 UNUSED(flags);
139 // TODO
140 return false;
141}
142
143static void _GBCoreSetKeys(struct mCore* core, uint32_t keys) {
144 struct GBCore* gbcore = (struct GBCore*) core;
145 gbcore->keys = keys;
146}
147
148static void _GBCoreAddKeys(struct mCore* core, uint32_t keys) {
149 struct GBCore* gbcore = (struct GBCore*) core;
150 gbcore->keys |= keys;
151}
152
153static void _GBCoreClearKeys(struct mCore* core, uint32_t keys) {
154 struct GBCore* gbcore = (struct GBCore*) core;
155 gbcore->keys &= ~keys;
156}
157
158static int32_t _GBCoreFrameCounter(struct mCore* core) {
159 struct GB* gb = core->board;
160 return gb->video.frameCounter;
161}
162
163static int32_t _GBCoreFrameCycles(struct mCore* core) {
164 UNUSED(core);
165 return GB_VIDEO_TOTAL_LENGTH;
166}
167
168static int32_t _GBCoreFrequency(struct mCore* core) {
169 UNUSED(core);
170 // TODO: GB differences
171 return DMG_LR35902_FREQUENCY;
172}
173
174static void _GBCoreSetRTC(struct mCore* core, struct mRTCSource* rtc) {
175 struct GB* gb = core->board;
176 gb->memory.rtc = rtc;
177}
178
179struct mCore* GBCoreCreate(void) {
180 struct GBCore* gbcore = malloc(sizeof(*gbcore));
181 struct mCore* core = &gbcore->d;
182 core->cpu = 0;
183 core->board = 0;
184 core->init = _GBCoreInit;
185 core->deinit = _GBCoreDeinit;
186 core->setSync = _GBCoreSetSync;
187 core->desiredVideoDimensions = _GBCoreDesiredVideoDimensions;
188 core->setVideoBuffer = _GBCoreSetVideoBuffer;
189 core->getAudioChannel = _GBCoreGetAudioChannel;
190 core->isROM = GBIsROM;
191 core->loadROM = _GBCoreLoadROM;
192 core->loadSave = _GBCoreLoadSave;
193 core->loadPatch = _GBCoreLoadPatch;
194 core->unloadROM = _GBCoreUnloadROM;
195 core->reset = _GBCoreReset;
196 core->runFrame = _GBCoreRunFrame;
197 core->runLoop = _GBCoreRunLoop;
198 core->step = _GBCoreStep;
199 core->loadState = _GBCoreLoadState;
200 core->saveState = _GBCoreSaveState;
201 core->setKeys = _GBCoreSetKeys;
202 core->addKeys = _GBCoreAddKeys;
203 core->clearKeys = _GBCoreClearKeys;
204 core->frameCounter = _GBCoreFrameCounter;
205 core->frameCycles = _GBCoreFrameCycles;
206 core->frequency = _GBCoreFrequency;
207 core->setRTC = _GBCoreSetRTC;
208 return core;
209}