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 SPRITE_MAPPER_H 20 #define SPRITE_MAPPER_H 21 22 #include "ly_counter.h" 23 #include "../savestate.h" 24 25 namespace gambatte { 26 27 class NextM0Time; 28 29 class SpriteMapper { 30 public: 31 SpriteMapper(NextM0Time &nextM0Time, 32 LyCounter const &lyCounter, 33 unsigned char const *oamram); 34 void reset(unsigned char const *oamram, bool cgb); 35 unsigned long doEvent(unsigned long time); largeSprites(unsigned spNo)36 bool largeSprites(unsigned spNo) const { return oamReader_.largeSprites(spNo); } numSprites(unsigned ly)37 unsigned numSprites(unsigned ly) const { return num_[ly] & ~need_sorting_mask; } oamChange(unsigned long cc)38 void oamChange(unsigned long cc) { oamReader_.change(cc); } oamChange(unsigned char const * oamram,unsigned long cc)39 void oamChange(unsigned char const *oamram, unsigned long cc) { oamReader_.change(oamram, cc); } oamram()40 unsigned char const * oamram() const { return oamReader_.oam(); } posbuf()41 unsigned char const * posbuf() const { return oamReader_.spritePosBuf(); } preSpeedChange(unsigned long cc)42 void preSpeedChange(unsigned long cc) { oamReader_.update(cc); } postSpeedChange(unsigned long cc)43 void postSpeedChange(unsigned long cc) { oamReader_.change(cc); } 44 resetCycleCounter(unsigned long oldCc,unsigned long newCc)45 void resetCycleCounter(unsigned long oldCc, unsigned long newCc) { 46 oamReader_.update(oldCc); 47 oamReader_.resetCycleCounter(oldCc, newCc); 48 } 49 setLargeSpritesSource(bool src)50 void setLargeSpritesSource(bool src) { oamReader_.setLargeSpritesSrc(src); } 51 sprites(unsigned ly)52 unsigned char const * sprites(unsigned ly) const { 53 if (num_[ly] & need_sorting_mask) 54 sortLine(ly); 55 56 return spritemap_ + ly * 10; 57 } 58 setStatePtrs(SaveState & state)59 void setStatePtrs(SaveState &state) { oamReader_.setStatePtrs(state); } enableDisplay(unsigned long cc)60 void enableDisplay(unsigned long cc) { oamReader_.enableDisplay(cc); } saveState(SaveState & state)61 void saveState(SaveState &state) const { oamReader_.saveState(state); } 62 loadState(SaveState const & state,unsigned char const * oamram)63 void loadState(SaveState const &state, unsigned char const *oamram) { 64 oamReader_.loadState(state, oamram); 65 mapSprites(); 66 } 67 inactivePeriodAfterDisplayEnable(unsigned long cc)68 bool inactivePeriodAfterDisplayEnable(unsigned long cc) const { 69 return oamReader_.inactivePeriodAfterDisplayEnable(cc); 70 } 71 schedule(LyCounter const & lyCounter,unsigned long cc)72 static unsigned long schedule(LyCounter const &lyCounter, unsigned long cc) { 73 return lyCounter.nextLineCycle(80, cc); 74 } 75 76 private: 77 class OamReader { 78 public: 79 OamReader(LyCounter const &lyCounter, unsigned char const *oamram); 80 void reset(unsigned char const *oamram, bool cgb); 81 void change(unsigned long cc); change(unsigned char const * oamram,unsigned long cc)82 void change(unsigned char const *oamram, unsigned long cc) { change(cc); oamram_ = oamram; } changed()83 bool changed() const { return lastChange_ != 0xFF; } largeSprites(unsigned spNo)84 bool largeSprites(unsigned spNo) const { return szbuf_[spNo]; } oam()85 unsigned char const * oam() const { return oamram_; } resetCycleCounter(unsigned long oldCc,unsigned long newCc)86 void resetCycleCounter(unsigned long oldCc, unsigned long newCc) { lu_ -= oldCc - newCc; } setLargeSpritesSrc(bool src)87 void setLargeSpritesSrc(bool src) { largeSpritesSrc_ = src; } 88 void update(unsigned long cc); spritePosBuf()89 unsigned char const * spritePosBuf() const { return buf_; } 90 void setStatePtrs(SaveState &state); 91 void enableDisplay(unsigned long cc); saveState(SaveState & state)92 void saveState(SaveState &state) const { state.ppu.enableDisplayM0Time = lu_; } 93 void loadState(SaveState const &ss, unsigned char const *oamram); inactivePeriodAfterDisplayEnable(unsigned long cc)94 bool inactivePeriodAfterDisplayEnable(unsigned long cc) const { return cc < lu_; } lineTime()95 unsigned lineTime() const { return lyCounter_.lineTime(); } 96 97 private: 98 unsigned char buf_[80]; 99 bool szbuf_[40]; 100 LyCounter const &lyCounter_; 101 unsigned char const *oamram_; 102 unsigned long lu_; 103 unsigned char lastChange_; 104 bool largeSpritesSrc_; 105 bool cgb_; 106 }; 107 108 enum { need_sorting_mask = 0x80 }; 109 110 mutable unsigned char spritemap_[144 * 10]; 111 mutable unsigned char num_[144]; 112 NextM0Time &nextM0Time_; 113 OamReader oamReader_; 114 115 void clearMap(); 116 void mapSprites(); 117 void sortLine(unsigned ly) const; 118 }; 119 120 } 121 122 #endif 123