1 //
2 //   Copyright (C) 2007 by sinamas <sinamas at users.sourceforge.net>
3 //
4 //   This program is free software; you can redistribute it and/or modify
5 //   it under the terms of the GNU General Public License version 2 as
6 //   published by the Free Software Foundation.
7 //
8 //   This program is distributed in the hope that it will be useful,
9 //   but WITHOUT ANY WARRANTY; without even the implied warranty of
10 //   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 //   GNU General Public License version 2 for more details.
12 //
13 //   You should have received a copy of the GNU General Public License
14 //   version 2 along with this program; if not, write to the
15 //   Free Software Foundation, Inc.,
16 //   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
17 //
18 
19 #ifndef MEMORY_H
20 #define MEMORY_H
21 
22 #include "mem/cartridge.h"
23 #include "interrupter.h"
24 #include "bootloader.h"
25 #include "sound.h"
26 #include "tima.h"
27 #include "video.h"
28 
29 namespace gambatte {
30 
31 class InputGetter;
32 #ifdef HAVE_NETWORK
33 class SerialIO;
34 #endif
35 
36 class Memory {
37 public:
38    Bootloader bootloader;
39 
40 	explicit Memory(Interrupter const &interrupter);
loaded()41 	bool loaded() const { return cart_.loaded(); }
42 	void setStatePtrs(SaveState &state);
43 	unsigned long saveState(SaveState &state, unsigned long cc);
44 	void loadState(SaveState const &state);
45 #ifdef __LIBRETRO__
savedata_ptr()46    void *savedata_ptr() { return cart_.savedata_ptr(); }
savedata_size()47    unsigned savedata_size() { return cart_.savedata_size(); }
rtcdata_ptr()48    void *rtcdata_ptr() { return cart_.rtcdata_ptr(); }
rtcdata_size()49    unsigned rtcdata_size() { return cart_.rtcdata_size(); }
display_setColorCorrection(bool enable)50    void display_setColorCorrection(bool enable) { lcd_.setColorCorrection(enable); }
display_setColorCorrectionMode(unsigned colorCorrectionMode)51    void display_setColorCorrectionMode(unsigned colorCorrectionMode) { lcd_.setColorCorrectionMode(colorCorrectionMode); }
display_setColorCorrectionBrightness(float colorCorrectionBrightness)52    void display_setColorCorrectionBrightness(float colorCorrectionBrightness) { lcd_.setColorCorrectionBrightness(colorCorrectionBrightness); }
display_setDarkFilterLevel(unsigned darkFilterLevel)53    void display_setDarkFilterLevel(unsigned darkFilterLevel) { lcd_.setDarkFilterLevel(darkFilterLevel); }
display_gbcToRgb32(const unsigned bgr15)54    video_pixel_t display_gbcToRgb32(const unsigned bgr15) { return lcd_.gbcToRgb32(bgr15); }
clearCheats()55    void clearCheats() { cart_.clearCheats(); interrupter_.clearCheats(); }
vram_ptr()56    void *vram_ptr() const { return cart_.vramdata(); }
rambank0_ptr()57    void *rambank0_ptr() const { return cart_.wramdata(0); }
rambank1_ptr()58    void *rambank1_ptr() const { return cart_.wramdata(0) + 0x1000; }
rambank2_ptr()59    void *rambank2_ptr() const { return cart_.wramdata(0) + 0x2000; }
bankedram_ptr()60    void *bankedram_ptr() const { return cart_.wramdata(1); }
rombank0_ptr()61    void *rombank0_ptr() const { return cart_.romdata(0); }
rombank1_ptr()62    void *rombank1_ptr() const { return cart_.romdata(0) + 0x4000; }
zeropage_ptr()63    void *zeropage_ptr() const { return (void*)(ioamhram_ + 0x0180); }
oamram_ptr()64    void *oamram_ptr() const { return (void*)ioamhram_; }
65 #else
loadSavedata()66    void loadSavedata() { cart_.loadSavedata(); }
saveSavedata()67    void saveSavedata() { cart_.saveSavedata(); }
68 #endif
saveBasePath()69 	std::string const saveBasePath() const { return cart_.saveBasePath(); }
70 
71 	unsigned long stop(unsigned long cycleCounter);
isCgb()72 	bool isCgb() const { return lcd_.isCgb(); }
ime()73 	bool ime() const { return intreq_.ime(); }
halted()74 	bool halted() const { return intreq_.halted(); }
nextEventTime()75 	unsigned long nextEventTime() const { return intreq_.minEventTime(); }
isActive()76 	bool isActive() const { return intreq_.eventTime(intevent_end) != disabled_time; }
77 
cyclesSinceBlit(unsigned long cc)78 	long cyclesSinceBlit(unsigned long cc) const
79    {
80 		if (cc < intreq_.eventTime(intevent_blit))
81 			return -1;
82       unsigned is_doublespeed = (unsigned)isDoubleSpeed();
83 		return (cc - intreq_.eventTime(intevent_blit)) >> is_doublespeed;
84 	}
85 
halt()86 	void halt() { intreq_.halt(); }
ei(unsigned long cycleCounter)87 	void ei(unsigned long cycleCounter) { if (!ime()) { intreq_.ei(cycleCounter); } }
di()88 	void di() { intreq_.di(); }
89 
ff_read(unsigned p,unsigned long cc)90 	unsigned ff_read(unsigned p, unsigned long cc) {
91 		return p < 0x80 ? nontrivial_ff_read(p, cc) : ioamhram_[p + 0x100];
92 	}
93 
read(unsigned p,unsigned long cc)94 	unsigned read(unsigned p, unsigned long cc) {
95 		return cart_.rmem(p >> 12) ? cart_.rmem(p >> 12)[p] : nontrivial_read(p, cc);
96 	}
97 
write(unsigned p,unsigned data,unsigned long cc)98 	void write(unsigned p, unsigned data, unsigned long cc) {
99 		if (cart_.wmem(p >> 12)) {
100 			cart_.wmem(p >> 12)[p] = data;
101 		} else
102 			nontrivial_write(p, data, cc);
103 	}
104 
ff_write(unsigned p,unsigned data,unsigned long cc)105 	void ff_write(unsigned p, unsigned data, unsigned long cc) {
106 		if (p - 0x80u < 0x7Fu) {
107 			ioamhram_[p + 0x100] = data;
108 		} else
109 			nontrivial_ff_write(p, data, cc);
110 	}
111 #ifdef HAVE_NETWORK
112 	void startSerialTransfer(unsigned long cycleCounter, unsigned char data, bool fastCgb);
113 #endif
114 
115 	unsigned long event(unsigned long cycleCounter);
116 	unsigned long resetCounters(unsigned long cycleCounter);
setSaveDir(std::string const & dir)117 	void setSaveDir(std::string const &dir) { cart_.setSaveDir(dir); }
setInputGetter(InputGetter * getInput)118 	void setInputGetter(InputGetter *getInput) { getInput_ = getInput; }
119 #ifdef HAVE_NETWORK
setSerialIO(SerialIO * serial_io)120 	void setSerialIO(SerialIO* serial_io) { serial_io_ = serial_io; }
121 #endif
122 	void setEndtime(unsigned long cc, unsigned long inc);
setSoundBuffer(uint_least32_t * buf)123 	void setSoundBuffer(uint_least32_t *buf) { psg_.setBuffer(buf); }
124 	std::size_t fillSoundBuffer(unsigned long cc);
125 
setVideoBuffer(video_pixel_t * videoBuf,std::ptrdiff_t pitch)126 	void setVideoBuffer(video_pixel_t *videoBuf, std::ptrdiff_t pitch) {
127 		lcd_.setVideoBuffer(videoBuf, pitch);
128 	}
129 
setDmgPaletteColor(int palNum,int colorNum,unsigned long rgb32)130 	void setDmgPaletteColor(int palNum, int colorNum, unsigned long rgb32) {
131 		lcd_.setDmgPaletteColor(palNum, colorNum, rgb32);
132 	}
133 
setGameGenie(std::string const & codes)134 	void setGameGenie(std::string const &codes) { cart_.setGameGenie(codes); }
setGameShark(std::string const & codes)135 	void setGameShark(std::string const &codes) { interrupter_.setGameShark(codes); }
136 #ifdef HAVE_NETWORK
137 	void checkSerial(unsigned long cc);
138 #endif
139 	void updateInput();
140 
141    int loadROM(const void *romdata, unsigned int romsize, unsigned int forceModel, const bool multicartCompat);
142 
143 private:
144 	Cartridge cart_;
145 	unsigned char ioamhram_[0x200];
146 #ifdef HAVE_NETWORK
147 	unsigned char serialize_value_;
148 	bool serialize_is_fastcgb_;
149 	SerialIO *serial_io_;
150 #endif
151 	InputGetter *getInput_;
152 	unsigned long divLastUpdate_;
153 	unsigned long lastOamDmaUpdate_;
154 	InterruptRequester intreq_;
155 	Tima tima_;
156 	LCD lcd_;
157 	PSG psg_;
158 	Interrupter interrupter_;
159 	unsigned short dmaSource_;
160 	unsigned short dmaDestination_;
161 	unsigned char oamDmaPos_;
162 	unsigned char serialCnt_;
163 	bool blanklcd_;
164 
165 	void decEventCycles(IntEventId eventId, unsigned long dec);
166 	void oamDmaInitSetup();
167 	void updateOamDma(unsigned long cycleCounter);
168 	void startOamDma(unsigned long cycleCounter);
169 	void endOamDma(unsigned long cycleCounter);
170 	unsigned char const * oamDmaSrcPtr() const;
171 	unsigned nontrivial_ff_read(unsigned p, unsigned long cycleCounter);
172 	unsigned nontrivial_read(unsigned p, unsigned long cycleCounter);
173 	void nontrivial_ff_write(unsigned p, unsigned data, unsigned long cycleCounter);
174 	void nontrivial_write(unsigned p, unsigned data, unsigned long cycleCounter);
175 	void updateSerial(unsigned long cc);
176 	void updateTimaIrq(unsigned long cc);
177 	void updateIrqs(unsigned long cc);
isDoubleSpeed()178 	bool isDoubleSpeed() const { return lcd_.isDoubleSpeed(); }
179 };
180 
181 }
182 
183 #endif
184