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