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 return true;
42}
43
44static void _GBCoreDeinit(struct mCore* core) {
45 LR35902Deinit(core->cpu);
46 GBDestroy(core->board);
47 mappedMemoryFree(core->cpu, sizeof(struct LR35902Core));
48 mappedMemoryFree(core->board, sizeof(struct GB));
49}
50
51static void _GBCoreDesiredVideoDimensions(struct mCore* core, unsigned* width, unsigned* height) {
52 UNUSED(core);
53 *width = GB_VIDEO_HORIZONTAL_PIXELS;
54 *height = GB_VIDEO_VERTICAL_PIXELS;
55}
56
57static void _GBCoreSetVideoBuffer(struct mCore* core, color_t* buffer, size_t stride) {
58 struct GBCore* gbcore = (struct GBCore*) core;
59 gbcore->renderer.outputBuffer = buffer;
60 gbcore->renderer.outputBufferStride = stride;
61}
62
63static bool _GBCoreLoadROM(struct mCore* core, struct VFile* vf, struct VFile* save, const char* fname) {
64 return GBLoadROM(core->board, vf, save, fname);
65}
66
67static bool _GBCoreIsROM(struct mCore* core, struct VFile* vf) {
68 UNUSED(core);
69 return GBIsROM(vf);
70}
71
72static void _GBCoreUnloadROM(struct mCore* core) {
73 return GBUnloadROM(core->board);
74}
75
76static void _GBCoreReset(struct mCore* core) {
77 LR35902Reset(core->cpu);
78}
79
80static void _GBCoreRunFrame(struct mCore* core) {
81 struct GB* gb = core->board;
82 int32_t frameCounter = gb->video.frameCounter;
83 while (gb->video.frameCounter == frameCounter) {
84 LR35902Run(core->cpu);
85 }
86}
87
88static void _GBCoreRunLoop(struct mCore* core) {
89 LR35902Run(core->cpu);
90}
91
92static void _GBCoreStep(struct mCore* core) {
93 LR35902Tick(core->cpu);
94}
95
96static void _GBCoreSetKeys(struct mCore* core, uint32_t keys) {
97 struct GBCore* gbcore = (struct GBCore*) core;
98 gbcore->keys = keys;
99}
100
101static void _GBCoreAddKeys(struct mCore* core, uint32_t keys) {
102 struct GBCore* gbcore = (struct GBCore*) core;
103 gbcore->keys |= keys;
104}
105
106static void _GBCoreClearKeys(struct mCore* core, uint32_t keys) {
107 struct GBCore* gbcore = (struct GBCore*) core;
108 gbcore->keys &= ~keys;
109}
110
111static int32_t _GBCoreFrameCounter(struct mCore* core) {
112 struct GB* gb = core->board;
113 return gb->video.frameCounter;
114}
115
116static int32_t _GBCoreFrameCycles(struct mCore* core) {
117 UNUSED(core);
118 return GB_VIDEO_TOTAL_LENGTH;
119}
120
121static int32_t _GBCoreFrequency(struct mCore* core) {
122 UNUSED(core);
123 // TODO: GB differences
124 return DMG_LR35902_FREQUENCY;
125}
126
127static void _GBCoreSetRTC(struct mCore* core, struct mRTCSource* rtc) {
128 struct GB* gb = core->board;
129 gb->memory.rtc = rtc;
130}
131
132struct mCore* GBCoreCreate(void) {
133 struct GBCore* gbcore = malloc(sizeof(*gbcore));
134 struct mCore* core = &gbcore->d;
135 core->cpu = 0;
136 core->board = 0;
137 core->init = _GBCoreInit;
138 core->deinit = _GBCoreDeinit;
139 core->desiredVideoDimensions = _GBCoreDesiredVideoDimensions;
140 core->setVideoBuffer = _GBCoreSetVideoBuffer;
141 core->isROM = _GBCoreIsROM;
142 core->loadROM = _GBCoreLoadROM;
143 core->unloadROM = _GBCoreUnloadROM;
144 core->reset = _GBCoreReset;
145 core->runFrame = _GBCoreRunFrame;
146 core->runLoop = _GBCoreRunLoop;
147 core->step = _GBCoreStep;
148 core->setKeys = _GBCoreSetKeys;
149 core->addKeys = _GBCoreAddKeys;
150 core->clearKeys = _GBCoreClearKeys;
151 core->frameCounter = _GBCoreFrameCounter;
152 core->frameCycles = _GBCoreFrameCycles;
153 core->frequency = _GBCoreFrequency;
154 core->setRTC = _GBCoreSetRTC;
155 return core;
156}