- Make sure to reset passed pointers when deleted. Fixes potential crash when loadin ROM during OAM busy.

git-svn-id: https://gambatte.svn.sourceforge.net/svnroot/gambatte@223 9dfb2916-2d38-0410-aef4-c5fe6c9ffc24
This commit is contained in:
sinamas 2009-01-10 19:22:59 +00:00
parent 323dd056df
commit bb91dcd035
5 changed files with 334 additions and 323 deletions

File diff suppressed because it is too large Load Diff

View File

@ -122,7 +122,7 @@ LCD::LCD(const unsigned char *const oamram, const unsigned char *const vram_in)
{
std::memset(bgpData, 0, sizeof(bgpData));
std::memset(objpData, 0, sizeof(objpData));
for (unsigned i = 0; i < sizeof(dmgColorsRgb32) / sizeof(unsigned long); ++i) {
setDmgPaletteColor(i, (3 - (i & 3)) * 85 * 0x010101);
}
@ -134,7 +134,7 @@ LCD::LCD(const unsigned char *const oamram, const unsigned char *const vram_in)
filters.push_back(new MaxSt_Hq2x);
filters.push_back(new MaxSt_Hq3x);
reset(false);
reset(oamram, false);
setDoubleSpeed(false);
setVideoFilter(0);
@ -146,9 +146,9 @@ LCD::~LCD() {
delete filters[i];
}
void LCD::reset(const bool cgb_in) {
void LCD::reset(const unsigned char *const oamram, const bool cgb_in) {
cgb = cgb_in;
spriteMapper.setCgb(cgb_in);
spriteMapper.reset(oamram, cgb_in);
setDBuffer();
}
@ -348,7 +348,7 @@ static void blitOsdElement(Gambatte::uint_least32_t *d, const Gambatte::uint_lea
++d;
++s;
}
d += dpitch - width;
}
}
@ -371,7 +371,7 @@ void LCD::updateScreen(const unsigned long cycleCounter) {
if (s) {
Gambatte::uint_least32_t *d = static_cast<Gambatte::uint_least32_t*>(dbuffer) + osdElement->y() * dpitch + osdElement->x();
switch (osdElement->opacity()) {
case OsdElement::SEVEN_EIGHTHS: blitOsdElement(d, s, osdElement->w(), osdElement->h(), dpitch, Blend<8>()); break;
case OsdElement::THREE_FOURTHS: blitOsdElement(d, s, osdElement->w(), osdElement->h(), dpitch, Blend<4>()); break;
@ -443,7 +443,7 @@ void LCD::lyWrite(const unsigned long cycleCounter) {
winYPos = 0xFF;
win.weMasterChecker.unset();
resetVideoState(cycleCounter);
// if ((statReg & 0x40) && lycIrq.lycReg() == 0)
// ifReg |= 2;
}
@ -1086,7 +1086,7 @@ void LCD::cgb_bg_drawPixels(T * const buffer_line, unsigned xpos, const unsigned
const unsigned char *const dataptr = tiledata + (attributes << 10 & 0x2000) +
maptmp[0] * 16 - (maptmp[0] & sign) * 32 + ((attributes & 0x40) ? 7 - tileline : tileline) * 2;
const unsigned short *const exp_lut = expand_lut + (attributes << 3 & 0x100);
const unsigned data = exp_lut[dataptr[0]] + exp_lut[dataptr[1]] * 2;
const unsigned long *const palette = bgPalette + (attributes & 7) * 4;

View File

@ -60,33 +60,33 @@ class LCD {
unsigned long bgPalette[8 * 4];
unsigned long spPalette[8 * 4];
unsigned char bgpData[8 * 8];
unsigned char objpData[8 * 8];
const unsigned char *const vram;
const unsigned char *bgTileData;
const unsigned char *bgTileMap;
const unsigned char *wdTileMap;
Gambatte::VideoBlitter *vBlitter;
Filter *filter;
void *dbuffer;
void (LCD::*draw)(unsigned xpos, unsigned ypos, unsigned endX);
unsigned long (*gbcToFormat)(unsigned bgr15);
const unsigned long *dmgColors;
unsigned long lastUpdate;
unsigned long videoCycles;
unsigned dpitch;
unsigned winYPos;
event_queue<VideoEvent*,VideoEventComparer> m3EventQueue;
event_queue<VideoEvent*,VideoEventComparer> irqEventQueue;
event_queue<VideoEvent*,VideoEventComparer> vEventQueue;
LyCounter lyCounter;
Window win;
ScxReader scxReader;
@ -95,46 +95,46 @@ class LCD {
ScReader scReader;
BreakEvent breakEvent;
Mode3Event mode3Event;
LycIrq lycIrq;
Mode0Irq mode0Irq;
Mode1Irq mode1Irq;
Mode2Irq mode2Irq;
IrqEvent irqEvent;
Gambatte::PixelBuffer pb;
Array<Gambatte::uint_least32_t> tmpbuf;
Rgb32ToUyvy rgb32ToUyvy;
std::auto_ptr<OsdElement> osdElement;
std::vector<Filter*> filters;
unsigned char drawStartCycle;
unsigned char scReadOffset;
unsigned char ifReg;
unsigned char tileIndexSign;
unsigned char statReg;
bool doubleSpeed;
bool enabled;
bool cgb;
bool bgEnable;
bool spriteEnable;
static void setDmgPalette(unsigned long *palette, const unsigned long *dmgColors, unsigned data);
void setDmgPaletteColor(unsigned index, unsigned long rgb32);
static unsigned long gbcToRgb32(unsigned bgr15);
static unsigned long gbcToRgb16(unsigned bgr15);
static unsigned long gbcToUyvy(unsigned bgr15);
void refreshPalettes();
void setDBuffer();
void resetVideoState(unsigned long cycleCounter);
void setDoubleSpeed(bool enabled);
void event();
bool cgbpAccessible(unsigned long cycleCounter);
bool isMode0IrqPeriod(unsigned long cycleCounter);
bool isMode2IrqPeriod(unsigned long cycleCounter);
@ -148,7 +148,7 @@ class LCD {
template<typename T> void cgb_bg_drawPixels(T *buffer_line, unsigned xpos, unsigned end, unsigned scx, unsigned tilemappos,
const unsigned char *tilemap, const unsigned char *tiledata, unsigned tileline);
template<typename T> void cgb_drawSprites(T *buffer_line, unsigned ypos);
void null_draw(unsigned xpos, unsigned ypos, unsigned endX);
template<typename T> void dmg_draw(unsigned xpos, unsigned ypos, unsigned endX);
template<typename T> void cgb_draw(unsigned xpos, unsigned ypos, unsigned endX);
@ -159,7 +159,7 @@ class LCD {
public:
LCD(const unsigned char *oamram, const unsigned char *vram_in);
~LCD();
void reset(bool cgb);
void reset(const unsigned char *oamram, bool cgb);
void setStatePtrs(SaveState &state);
void saveState(SaveState &state) const;
void loadState(const SaveState &state, const unsigned char *oamram);
@ -170,35 +170,35 @@ public:
unsigned videoWidth() const;
unsigned videoHeight() const;
void setDmgPaletteColor(unsigned palNum, unsigned colorNum, unsigned long rgb32);
void setOsdElement(std::auto_ptr<OsdElement> osdElement) {
this->osdElement = osdElement;
}
void wdTileMapSelectChange(bool newValue, unsigned long cycleCounter);
void bgTileMapSelectChange(bool newValue, unsigned long cycleCounter);
void bgTileDataSelectChange(bool newValue, unsigned long cycleCounter);
void bgEnableChange(bool newValue, unsigned long cycleCounter);
void spriteEnableChange(bool newValue, unsigned long cycleCounter);
void dmgBgPaletteChange(const unsigned data, const unsigned long cycleCounter) {
update(cycleCounter);
bgpData[0] = data;
setDmgPalette(bgPalette, dmgColors, data);
}
void dmgSpPalette1Change(const unsigned data, const unsigned long cycleCounter) {
update(cycleCounter);
objpData[0] = data;
setDmgPalette(spPalette, dmgColors + 4, data);
}
void dmgSpPalette2Change(const unsigned data, const unsigned long cycleCounter) {
update(cycleCounter);
objpData[1] = data;
setDmgPalette(spPalette + 4, dmgColors + 8, data);
}
void cgbBgColorChange(unsigned index, const unsigned data, const unsigned long cycleCounter) {
if (bgpData[index] != data && cgbpAccessible(cycleCounter)) {
update(cycleCounter);
@ -207,7 +207,7 @@ public:
bgPalette[index] = (*gbcToFormat)(bgpData[index << 1] | bgpData[(index << 1) + 1] << 8);
}
}
void cgbSpColorChange(unsigned index, const unsigned data, const unsigned long cycleCounter) {
if (objpData[index] != data && cgbpAccessible(cycleCounter)) {
update(cycleCounter);
@ -216,15 +216,15 @@ public:
spPalette[index] = (*gbcToFormat)(objpData[index << 1] | objpData[(index << 1) + 1] << 8);
}
}
unsigned cgbBgColorRead(const unsigned index, const unsigned long cycleCounter) {
return cgb & cgbpAccessible(cycleCounter) ? bgpData[index] : 0xFF;
}
unsigned cgbSpColorRead(const unsigned index, const unsigned long cycleCounter) {
return cgb & cgbpAccessible(cycleCounter) ? objpData[index] : 0xFF;
}
void updateScreen(unsigned long cc);
void enableChange(unsigned long cycleCounter);
void preResetCounter(unsigned long cycleCounter);
@ -242,22 +242,22 @@ public:
void scxChange(unsigned newScx, unsigned long cycleCounter);
void scyChange(unsigned newValue, unsigned long cycleCounter);
void spriteSizeChange(bool newLarge, unsigned long cycleCounter);
void vramChange(const unsigned long cycleCounter) {
update(cycleCounter);
}
unsigned get_stat(unsigned lycReg, unsigned long cycleCounter);
unsigned getLyReg(const unsigned long cycleCounter) {
unsigned lyReg = 0;
if (enabled) {
if (cycleCounter >= lyCounter.time())
update(cycleCounter);
lyReg = lyCounter.ly();
if (lyCounter.time() - cycleCounter <= 4) {
if (lyReg == 153)
lyReg = 0;
@ -269,11 +269,11 @@ public:
return lyReg;
}
unsigned long nextMode1IrqTime() const {
return mode1Irq.time();
}
void lyWrite(unsigned long cycleCounter);
void lcdstatChange(unsigned data, unsigned long cycleCounter);
void lycRegChange(unsigned data, unsigned long cycleCounter);
@ -283,7 +283,7 @@ public:
unsigned long nextHdmaTime(unsigned long cycleCounter);
bool isHdmaPeriod(unsigned long cycleCounter);
unsigned long nextHdmaTimeInvalid() const {
return mode3Event.time();
}

View File

@ -25,14 +25,19 @@
SpriteMapper::OamReader::OamReader(const LyCounter &lyCounter, const unsigned char *oamram)
: lyCounter(lyCounter), oamram(oamram) {
reset(oamram);
}
void SpriteMapper::OamReader::reset(const unsigned char *const oamram) {
this->oamram = oamram;
setLargeSpritesSrc(false);
lu = 0;
lastChange = 0xFF;
std::fill_n(szbuf, 40, largeSpritesSrc);
unsigned pos = 0;
unsigned distance = 80;
while (distance--) {
buf[pos] = oamram[((pos * 2) & ~3) | (pos & 1)];
++pos;
@ -41,10 +46,10 @@ SpriteMapper::OamReader::OamReader(const LyCounter &lyCounter, const unsigned ch
static unsigned toPosCycles(const unsigned long cc, const LyCounter &lyCounter) {
unsigned lc = lyCounter.lineCycles(cc) + 4 - lyCounter.isDoubleSpeed() * 3u;
if (lc >= 456)
lc -= 456;
return lc >> 1;
}
@ -52,37 +57,37 @@ void SpriteMapper::OamReader::update(const unsigned long cc) {
if (cc > lu) {
if (changed()) {
const unsigned lulc = toPosCycles(lu, lyCounter);
unsigned pos = std::min(lulc, 40u);
unsigned distance = 40;
if ((cc - lu) >> lyCounter.isDoubleSpeed() < 456) {
const unsigned cclc = toPosCycles(cc, lyCounter);
distance = std::min(cclc, 40u) - pos + (cclc < lulc ? 40 : 0);
}
{
const unsigned targetDistance = lastChange - pos + (lastChange <= pos ? 40 : 0);
if (targetDistance <= distance) {
distance = targetDistance;
lastChange = 0xFF;
}
}
while (distance--) {
if (pos >= 40)
pos = 0;
szbuf[pos] = largeSpritesSrc;
buf[pos * 2] = oamram[pos * 4];
buf[pos * 2 + 1] = oamram[pos * 4 + 1];
++pos;
}
}
lu = cc;
}
}
@ -107,12 +112,12 @@ void SpriteMapper::OamReader::enableDisplay(const unsigned long cc) {
bool SpriteMapper::OamReader::oamAccessible(const unsigned long cycleCounter, const M3ExtraCycles &m3ExtraCycles) const {
unsigned ly = lyCounter.ly();
unsigned lc = lyCounter.lineCycles(cycleCounter) + 4 - lyCounter.isDoubleSpeed() * 3u;
if (lc >= 456) {
lc -= 456;
++ly;
}
return cycleCounter < lu || ly >= 144 || lc >= 80 + 173 + m3ExtraCycles(ly);
}
@ -121,9 +126,15 @@ SpriteMapper::SpriteMapper(M3ExtraCycles &m3ExtraCycles,
const unsigned char *const oamram) :
VideoEvent(2),
m3ExtraCycles(m3ExtraCycles),
oamReader(lyCounter, oamram)
oamReader(lyCounter, oamram),
cgb(false)
{
setCgb(false);
clearMap();
}
void SpriteMapper::reset(const unsigned char *const oamram, const bool cgb_in) {
oamReader.reset(oamram);
cgb = cgb_in;
clearMap();
}
@ -133,34 +144,34 @@ void SpriteMapper::clearMap() {
void SpriteMapper::mapSprites() {
clearMap();
for (unsigned i = 0x00; i < 0x50; i += 2) {
const unsigned spriteHeight = 8u << largeSprites(i >> 1);
const unsigned bottom_pos = posbuf()[i] - (17u - spriteHeight);
if (bottom_pos >= 143 + spriteHeight)
continue;
unsigned char *map = spritemap;
unsigned char *n = num;
if (bottom_pos >= spriteHeight) {
const unsigned startly = bottom_pos + 1 - spriteHeight;
n += startly;
map += startly * 10;
}
unsigned char *const end = num + (bottom_pos >= 143 ? 143 : bottom_pos);
do {
if ((*n & ~NEED_SORTING_MASK) < 10)
map[(*n)++ & ~NEED_SORTING_MASK] = i;
map += 10;
++n;
} while (n <= end);
}
m3ExtraCycles.invalidateCache();
}

View File

@ -32,18 +32,19 @@ class SpriteMapper : public VideoEvent {
class OamReader {
unsigned char buf[80];
bool szbuf[40];
public:
const LyCounter &lyCounter;
private:
const unsigned char *oamram;
unsigned long lu;
unsigned char lastChange;
bool largeSpritesSrc;
public:
OamReader(const LyCounter &lyCounter, const unsigned char *oamram);
void reset(const unsigned char *oamram);
void change(unsigned long cc);
void change(const unsigned char *oamram, unsigned long cc) { change(cc); this->oamram = oamram; }
bool changed() const { return lastChange != 0xFF; }
@ -61,16 +62,16 @@ class SpriteMapper : public VideoEvent {
bool oamAccessible(unsigned long cycleCounter, const M3ExtraCycles &m3ExtraCycles) const;
bool inactivePeriodAfterDisplayEnable(const unsigned long cc) const { return cc < lu; }
};
enum { NEED_SORTING_MASK = 0x80 };
public:
class SpxLess {
const unsigned char *const posbuf_plus1;
public:
SpxLess(const unsigned char *const posbuf) : posbuf_plus1(posbuf + 1) {}
SpxLess(const unsigned char *const posbuf) : posbuf_plus1(posbuf + 1) {}
bool operator()(const unsigned char l, const unsigned char r) const {
return posbuf_plus1[l] < posbuf_plus1[r];
}
@ -79,21 +80,21 @@ public:
private:
mutable unsigned char spritemap[144*10];
mutable unsigned char num[144];
M3ExtraCycles &m3ExtraCycles;
OamReader oamReader;
bool cgb;
void clearMap();
void mapSprites();
void sortLine(unsigned ly) const;
public:
SpriteMapper(M3ExtraCycles &m3ExtraCycles,
const LyCounter &lyCounter,
const unsigned char *oamram_in);
void reset(const unsigned char *oamram, bool cgb_in);
void doEvent();
bool isCgb() const { return cgb; }
bool largeSprites(unsigned spNr) const { return oamReader.largeSprites(spNr); }
@ -103,35 +104,34 @@ public:
const unsigned char *oamram() const { return oamReader.oam(); }
const unsigned char *posbuf() const { return oamReader.spritePosBuf(); }
void preCounterChange(const unsigned long cc) { oamReader.update(cc); }
void resetCycleCounter(const unsigned long oldCc, const unsigned long newCc) {
oamReader.resetCycleCounter(oldCc, newCc);
}
static unsigned long schedule(const LyCounter &lyCounter, const unsigned long cycleCounter) {
return lyCounter.nextLineCycle(80, cycleCounter);
}
void setCgb(const bool cgb_in) { cgb = cgb_in; }
void setLargeSpritesSource(const bool src) { oamReader.setLargeSpritesSrc(src); }
const unsigned char* sprites(const unsigned ly) const {
if (num[ly] & NEED_SORTING_MASK)
sortLine(ly);
return spritemap + ly * 10;
}
void setStatePtrs(SaveState &state) { oamReader.setStatePtrs(state); }
void enableDisplay(unsigned long cc) { oamReader.enableDisplay(cc); }
void saveState(SaveState &state) const { oamReader.saveState(state); }
void loadState(const SaveState &state) { oamReader.loadState(state); }
void resetVideoState() { oamReader.resetVideoState(); }
bool oamAccessible(unsigned long cycleCounter) const {
return oamReader.oamAccessible(cycleCounter, m3ExtraCycles);
}
bool inactivePeriodAfterDisplayEnable(const unsigned long cc) const {
return oamReader.inactivePeriodAfterDisplayEnable(cc);
}