Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alexbevi
GitHub Repository: alexbevi/BizHawk
Path: blob/master/libgambatte/src/gambatte.cpp
2 views
1
/***************************************************************************
2
* Copyright (C) 2007 by Sindre AamÄs *
3
* [email protected] *
4
* *
5
* This program is free software; you can redistribute it and/or modify *
6
* it under the terms of the GNU General Public License version 2 as *
7
* published by the Free Software Foundation. *
8
* *
9
* This program is distributed in the hope that it will be useful, *
10
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
11
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
12
* GNU General Public License version 2 for more details. *
13
* *
14
* You should have received a copy of the GNU General Public License *
15
* version 2 along with this program; if not, write to the *
16
* Free Software Foundation, Inc., *
17
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
18
***************************************************************************/
19
#include "gambatte.h"
20
#include "cpu.h"
21
#include "savestate.h"
22
#include "initstate.h"
23
#include <sstream>
24
#include <cstring>
25
26
namespace gambatte {
27
struct GB::Priv {
28
CPU cpu;
29
bool gbaCgbMode;
30
unsigned layersMask;
31
32
uint_least32_t vbuff[160*144];
33
34
Priv() : gbaCgbMode(false), layersMask(LAYER_MASK_BG | LAYER_MASK_OBJ)
35
{
36
}
37
38
~Priv()
39
{
40
}
41
};
42
43
GB::GB() : p_(new Priv) {}
44
45
GB::~GB() {
46
//if (p_->cpu.loaded())
47
// p_->cpu.saveSavedata();
48
49
delete p_;
50
}
51
52
long GB::runFor(gambatte::uint_least32_t *const soundBuf, unsigned &samples) {
53
if (!p_->cpu.loaded()) {
54
samples = 0;
55
return -1;
56
}
57
58
p_->cpu.setVideoBuffer(p_->vbuff, 160);
59
p_->cpu.setSoundBuffer(soundBuf);
60
const long cyclesSinceBlit = p_->cpu.runFor(samples * 2);
61
samples = p_->cpu.fillSoundBuffer();
62
63
return cyclesSinceBlit < 0 ? cyclesSinceBlit : static_cast<long>(samples) - (cyclesSinceBlit >> 1);
64
}
65
66
void GB::setLayers(unsigned mask)
67
{
68
p_->cpu.setLayers(mask);
69
}
70
71
void GB::blitTo(gambatte::uint_least32_t *videoBuf, int pitch)
72
{
73
gambatte::uint_least32_t *src = p_->vbuff;
74
gambatte::uint_least32_t *dst = videoBuf;
75
76
for (int i = 0; i < 144; i++)
77
{
78
std::memcpy(dst, src, sizeof(gambatte::uint_least32_t) * 160);
79
src += 160;
80
dst += pitch;
81
}
82
}
83
84
void GB::reset(const std::uint32_t now) {
85
if (p_->cpu.loaded()) {
86
87
int length = p_->cpu.saveSavedataLength();
88
char *s;
89
if (length > 0)
90
{
91
s = (char *) std::malloc(length);
92
p_->cpu.saveSavedata(s);
93
}
94
95
SaveState state;
96
p_->cpu.setStatePtrs(state);
97
setInitState(state, p_->cpu.isCgb(), p_->gbaCgbMode, now);
98
p_->cpu.loadState(state);
99
if (length > 0)
100
{
101
p_->cpu.loadSavedata(s);
102
std::free(s);
103
}
104
}
105
}
106
107
void GB::setInputGetter(unsigned (*getInput)()) {
108
p_->cpu.setInputGetter(getInput);
109
}
110
111
void GB::setReadCallback(void (*callback)(unsigned)) {
112
p_->cpu.setReadCallback(callback);
113
}
114
115
void GB::setWriteCallback(void (*callback)(unsigned)) {
116
p_->cpu.setWriteCallback(callback);
117
}
118
119
void GB::setExecCallback(void (*callback)(unsigned)) {
120
p_->cpu.setExecCallback(callback);
121
}
122
123
void GB::setCDCallback(CDCallback cdc) {
124
p_->cpu.setCDCallback(cdc);
125
}
126
127
void GB::setTraceCallback(void (*callback)(void *)) {
128
p_->cpu.setTraceCallback(callback);
129
}
130
131
void GB::setScanlineCallback(void (*callback)(), int sl) {
132
p_->cpu.setScanlineCallback(callback, sl);
133
}
134
135
void GB::setRTCCallback(std::uint32_t (*callback)()) {
136
p_->cpu.setRTCCallback(callback);
137
}
138
139
int GB::load(const char *romfiledata, unsigned romfilelength, const std::uint32_t now, const unsigned flags) {
140
//if (p_->cpu.loaded())
141
// p_->cpu.saveSavedata();
142
143
const int failed = p_->cpu.load(romfiledata, romfilelength, flags & FORCE_DMG, flags & MULTICART_COMPAT);
144
145
if (!failed) {
146
SaveState state;
147
p_->cpu.setStatePtrs(state);
148
setInitState(state, p_->cpu.isCgb(), p_->gbaCgbMode = flags & GBA_CGB, now);
149
p_->cpu.loadState(state);
150
//p_->cpu.loadSavedata();
151
}
152
153
return failed;
154
}
155
156
bool GB::isCgb() const {
157
return p_->cpu.isCgb();
158
}
159
160
bool GB::isLoaded() const {
161
return p_->cpu.loaded();
162
}
163
164
void GB::saveSavedata(char *dest) {
165
if (p_->cpu.loaded())
166
p_->cpu.saveSavedata(dest);
167
}
168
void GB::loadSavedata(const char *data) {
169
if (p_->cpu.loaded())
170
p_->cpu.loadSavedata(data);
171
}
172
int GB::saveSavedataLength() {
173
if (p_->cpu.loaded())
174
return p_->cpu.saveSavedataLength();
175
else
176
return -1;
177
}
178
179
bool GB::getMemoryArea(int which, unsigned char **data, int *length) {
180
if (p_->cpu.loaded())
181
return p_->cpu.getMemoryArea(which, data, length);
182
else
183
return false;
184
}
185
186
unsigned char GB::ExternalRead(unsigned short addr) {
187
if (p_->cpu.loaded())
188
return p_->cpu.ExternalRead(addr);
189
else
190
return 0;
191
}
192
193
void GB::ExternalWrite(unsigned short addr, unsigned char val) {
194
if (p_->cpu.loaded())
195
p_->cpu.ExternalWrite(addr, val);
196
}
197
198
199
void GB::setDmgPaletteColor(unsigned palNum, unsigned colorNum, unsigned rgb32) {
200
p_->cpu.setDmgPaletteColor(palNum, colorNum, rgb32);
201
}
202
203
void GB::setCgbPalette(unsigned *lut) {
204
p_->cpu.setCgbPalette(lut);
205
}
206
207
const std::string GB::romTitle() const {
208
if (p_->cpu.loaded()) {
209
char title[0x11];
210
std::memcpy(title, p_->cpu.romTitle(), 0x10);
211
title[(title[0xF] & 0x80) ? 0xF : 0x10] = '\0';
212
return std::string(title);
213
}
214
215
return std::string();
216
}
217
218
int GB::LinkStatus(int which) {
219
return p_->cpu.LinkStatus(which);
220
}
221
222
void GB::GetRegs(int *dest) {
223
p_->cpu.GetRegs(dest);
224
}
225
226
SYNCFUNC(GB)
227
{
228
SSS(p_->cpu);
229
NSS(p_->gbaCgbMode);
230
NSS(p_->vbuff);
231
}
232
233
}
234
235