diff --git a/Core/PPU.cpp b/Core/PPU.cpp index 8c0ab931..ae8f4966 100644 --- a/Core/PPU.cpp +++ b/Core/PPU.cpp @@ -38,6 +38,7 @@ void PPU::Reset() { _prevRenderingEnabled = false; _renderingEnabled = false; + _skipScrollingIncrement = true; _ignoreVramRead = 0; _openBus = 0; @@ -252,6 +253,10 @@ void PPU::WriteRAM(uint16_t addr, uint8_t value) //Trigger memory read when setting the vram address - needed by MMC3 IRQ counter //"4) Should be clocked when A12 changes to 1 via $2006 write" _memoryManager->ReadVRAM(_state.VideoRamAddr); + + if(_cycle == 255) { + _skipScrollingIncrement = true; + } } else { _state.TmpVideoRamAddr = (_state.TmpVideoRamAddr & ~0xFF00) | ((value & 0x3F) << 8); } @@ -622,13 +627,14 @@ void PPU::ProcessPreVBlankScanline() //Update video ram address according to scrolling logic if((_cycle > 0 && _cycle < 256 && (_cycle & 0x07) == 0) || _cycle == 328 || _cycle == 336) { IncHorizontalScrolling(); - } else if(_cycle == 256) { + } else if(_cycle == 256 && !_skipScrollingIncrement) { IncVerticalScrolling(); } else if(_cycle == 257) { //copy horizontal scrolling value from t _state.VideoRamAddr = (_state.VideoRamAddr & ~0x041F) | (_state.TmpVideoRamAddr & 0x041F); } } + _skipScrollingIncrement = false; if(_cycle >= 257 && _cycle <= 320) { if(IsRenderingEnabled()) { @@ -964,6 +970,8 @@ void PPU::StreamState(bool saving) Stream(_ignoreVramRead); + Stream(_skipScrollingIncrement); + if(!saving) { SetNesModel(_nesModel); } diff --git a/Core/PPU.h b/Core/PPU.h index 2be567a5..dd4c7cb4 100644 --- a/Core/PPU.h +++ b/Core/PPU.h @@ -148,6 +148,9 @@ class PPU : public IMemoryHandler, public Snapshotable bool _renderingEnabled; bool _prevRenderingEnabled; + + //Used to resolve a race condition when the 2nd write to $2006 occurs at cycle 255 (i.e approx. the same time as the PPU tries to increase Y scrolling) + bool _skipScrollingIncrement; void UpdateStatusFlag();