1 /***************************************************************************
2 * Copyright (C) 2007 by Sindre Aamås *
3 * aamas@stud.ntnu.no *
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 "statesaver.h"
23 #include "initstate.h"
24 #include "bootloader.h"
25 #include <sstream>
26 #include <cstring>
27
28 namespace gambatte {
29 struct GB::Priv {
30 CPU cpu;
31 int stateNo;
32 bool gbaCgbMode;
33
Privgambatte::GB::Priv34 Priv() : stateNo(1), gbaCgbMode(false) {}
35
36 void full_init();
37 };
38
GB()39 GB::GB() : p_(new Priv) {}
40
~GB()41 GB::~GB() {
42 delete p_;
43 }
44
runFor(gambatte::video_pixel_t * const videoBuf,const int pitch,gambatte::uint_least32_t * const soundBuf,unsigned & samples)45 long GB::runFor(gambatte::video_pixel_t *const videoBuf, const int pitch,
46 gambatte::uint_least32_t *const soundBuf, unsigned &samples) {
47
48 p_->cpu.setVideoBuffer(videoBuf, pitch);
49 p_->cpu.setSoundBuffer(soundBuf);
50 const long cyclesSinceBlit = p_->cpu.runFor(samples * 2);
51 samples = p_->cpu.fillSoundBuffer();
52
53 return cyclesSinceBlit < 0 ? cyclesSinceBlit : static_cast<long>(samples) - (cyclesSinceBlit >> 1);
54 }
55
full_init()56 void GB::Priv::full_init() {
57 SaveState state;
58
59 cpu.setStatePtrs(state);
60 setInitState(state, cpu.isCgb(), gbaCgbMode);
61
62 cpu.mem_.bootloader.reset();
63 cpu.mem_.bootloader.set_address_space_start((void*)cpu.rombank0_ptr());
64 cpu.mem_.bootloader.load(cpu.isCgb(), gbaCgbMode);
65
66 if (cpu.mem_.bootloader.using_bootloader) {
67 uint8_t *ioamhram = (uint8_t*)state.mem.ioamhram.get();
68 uint8_t serialctrl = (cpu.isCgb() || gbaCgbMode) ? 0x7C : 0x7E;
69 state.cpu.pc = 0x0000;
70 // the hw registers must be zeroed out to prevent the logo from being garbled
71 std::memset((void*)(ioamhram + 0x100), 0x00, 0x100);
72 //init values taken from SameBoy
73 ioamhram[0x100] = 0xCF;//joypad initial value
74 ioamhram[0x102] = serialctrl;//serialctrl
75 ioamhram[0x148] = 0xFC;//object palette 0
76 ioamhram[0x149] = 0xFC;//object palette 1
77 }
78
79 cpu.loadState(state);
80 }
81
reset()82 void GB::reset() {
83 p_->full_init();
84 }
85
setInputGetter(InputGetter * getInput)86 void GB::setInputGetter(InputGetter *getInput) {
87 p_->cpu.setInputGetter(getInput);
88 }
89
setBootloaderGetter(bool (* getter)(void * userdata,bool isgbc,uint8_t * data,uint32_t max_size))90 void GB::setBootloaderGetter(bool (*getter)(void* userdata, bool isgbc, uint8_t* data, uint32_t max_size)) {
91 p_->cpu.mem_.bootloader.set_bootloader_getter(getter);
92 }
93
94 #ifdef HAVE_NETWORK
setSerialIO(SerialIO * serial_io)95 void GB::setSerialIO(SerialIO *serial_io) {
96 p_->cpu.setSerialIO(serial_io);
97 }
98 #endif
99
savedata_ptr()100 void *GB::savedata_ptr() { return p_->cpu.savedata_ptr(); }
savedata_size()101 unsigned GB::savedata_size() { return p_->cpu.savedata_size(); }
rtcdata_ptr()102 void *GB::rtcdata_ptr() { return p_->cpu.rtcdata_ptr(); }
rtcdata_size()103 unsigned GB::rtcdata_size() { return p_->cpu.rtcdata_size(); }
104
load(const void * romdata,unsigned romsize,const unsigned flags)105 int GB::load(const void *romdata, unsigned romsize, const unsigned flags) {
106 const int failed = p_->cpu.load(romdata, romsize, flags & (FORCE_DMG | FORCE_CGB), flags & MULTICART_COMPAT);
107
108 if (!failed) {
109 p_->gbaCgbMode = flags & GBA_CGB;
110 p_->full_init();
111 p_->stateNo = 1;
112 }
113
114 return failed;
115 }
116
isCgb() const117 bool GB::isCgb() const {
118 return p_->cpu.isCgb();
119 }
120
isLoaded() const121 bool GB::isLoaded() const {
122 return true;
123 }
124
setDmgPaletteColor(unsigned palNum,unsigned colorNum,unsigned rgb32)125 void GB::setDmgPaletteColor(unsigned palNum, unsigned colorNum, unsigned rgb32) {
126 p_->cpu.setDmgPaletteColor(palNum, colorNum, rgb32);
127 }
128
loadState(const void * data)129 void GB::loadState(const void *data) {
130 SaveState state;
131 p_->cpu.setStatePtrs(state);
132
133 if (StateSaver::loadState(state, data)) {
134 p_->cpu.loadState(state);
135 p_->cpu.mem_.bootloader.choosebank(state.mem.ioamhram.get()[0x150] != 0xFF);
136 }
137 }
138
saveState(void * data)139 void GB::saveState(void *data) {
140 SaveState state;
141 p_->cpu.setStatePtrs(state);
142 p_->cpu.saveState(state);
143 StateSaver::saveState(state, data);
144 }
145
stateSize() const146 size_t GB::stateSize() const {
147 SaveState state;
148 p_->cpu.setStatePtrs(state);
149 p_->cpu.saveState(state);
150 return StateSaver::stateSize(state);
151 }
152
setColorCorrection(bool enable)153 void GB::setColorCorrection(bool enable) {
154 p_->cpu.mem_.display_setColorCorrection(enable);
155 }
156
setColorCorrectionMode(unsigned colorCorrectionMode)157 void GB::setColorCorrectionMode(unsigned colorCorrectionMode) {
158 p_->cpu.mem_.display_setColorCorrectionMode(colorCorrectionMode);
159 }
160
setColorCorrectionBrightness(float colorCorrectionBrightness)161 void GB::setColorCorrectionBrightness(float colorCorrectionBrightness) {
162 p_->cpu.mem_.display_setColorCorrectionBrightness(colorCorrectionBrightness);
163 }
164
setDarkFilterLevel(unsigned darkFilterLevel)165 void GB::setDarkFilterLevel(unsigned darkFilterLevel) {
166 p_->cpu.mem_.display_setDarkFilterLevel(darkFilterLevel);
167 }
168
gbcToRgb32(const unsigned bgr15)169 video_pixel_t GB::gbcToRgb32(const unsigned bgr15) {
170 return p_->cpu.mem_.display_gbcToRgb32(bgr15);
171 }
172
173
setGameGenie(const std::string & codes)174 void GB::setGameGenie(const std::string &codes) {
175 p_->cpu.setGameGenie(codes);
176 }
177
setGameShark(const std::string & codes)178 void GB::setGameShark(const std::string &codes) {
179 p_->cpu.setGameShark(codes);
180 }
181
clearCheats()182 void GB::clearCheats() {
183 p_->cpu.clearCheats();
184 }
185
186 #ifdef __LIBRETRO__
vram_ptr() const187 void *GB::vram_ptr() const {
188 return p_->cpu.vram_ptr();
189 }
190
rambank0_ptr() const191 void *GB::rambank0_ptr() const {
192 return p_->cpu.rambank0_ptr();
193 }
194
rambank1_ptr() const195 void *GB::rambank1_ptr() const {
196 return p_->cpu.rambank1_ptr();
197 }
198
rambank2_ptr() const199 void *GB::rambank2_ptr() const {
200 return p_->cpu.rambank2_ptr();
201 }
202
bankedram_ptr() const203 void *GB::bankedram_ptr() const {
204 return p_->cpu.bankedram_ptr();
205 }
206
rombank0_ptr() const207 void *GB::rombank0_ptr() const {
208 return p_->cpu.rombank0_ptr();
209 }
210
rombank1_ptr() const211 void *GB::rombank1_ptr() const {
212 return p_->cpu.rombank1_ptr();
213 }
214
zeropage_ptr() const215 void *GB::zeropage_ptr() const {
216 return p_->cpu.zeropage_ptr();
217 }
218
oamram_ptr() const219 void *GB::oamram_ptr() const {
220 return p_->cpu.oamram_ptr();
221 }
222 #endif
223
224 }
225
226