From 415441a069d8b0b55d217c9d4af614a6c98cdb51 Mon Sep 17 00:00:00 2001 From: vailkyte <133282358+vailkyte@users.noreply.github.com> Date: Thu, 18 May 2023 14:14:46 -0500 Subject: [PATCH] Backport Fixed PPU bus address on cycle 0 + improved MMC3 IRQ timing --- Core/MMC3.h | 20 +++++++++++++++----- Core/PPU.cpp | 24 ++++++++++++++++-------- 2 files changed, 31 insertions(+), 13 deletions(-) diff --git a/Core/MMC3.h b/Core/MMC3.h index 36f3fa8c..a0ca4b80 100644 --- a/Core/MMC3.h +++ b/Core/MMC3.h @@ -4,7 +4,6 @@ #include "BaseMapper.h" #include "CPU.h" #include "EmulationSettings.h" -#include "A12Watcher.h" class MMC3 : public BaseMapper @@ -28,7 +27,7 @@ class MMC3 : public BaseMapper bool _wramEnabled; bool _wramWriteProtected; - A12Watcher _a12Watcher; + uint64_t _a12LowClock = 0; bool _forceMmc3RevAIrqs; @@ -189,9 +188,8 @@ class MMC3 : public BaseMapper { BaseMapper::StreamState(saving); ArrayInfo registers = { _registers, 8 }; - SnapshotInfo a12Watcher{ &_a12Watcher }; Stream(_state.Reg8000, _state.RegA000, _state.RegA001, _currentRegister, _chrMode, _prgMode, - _irqReloadValue, _irqCounter, _irqReload, _irqEnabled, a12Watcher, + _irqReloadValue, _irqCounter, _irqReload, _irqEnabled, _a12LowClock, _wramEnabled, _wramWriteProtected, registers); } @@ -265,10 +263,22 @@ class MMC3 : public BaseMapper _console->GetCpu()->SetIrqSource(IRQSource::External); } + bool IsA12RisingEdge(uint16_t addr) + { + if(addr & 0x1000) { + bool isRisingEdge = _a12LowClock > 0 && (_console->GetCpu()->GetCycleCount() - _a12LowClock) >= 3; + _a12LowClock = 0; + return isRisingEdge; + } else if(_a12LowClock == 0) { + _a12LowClock = _console->GetCpu()->GetCycleCount(); + } + return false; + } + public: virtual void NotifyVRAMAddressChange(uint16_t addr) override { - if(_a12Watcher.UpdateVramAddress(addr, _console->GetPpu()->GetFrameCycle()) == A12StateChange::Rise) { + if(IsA12RisingEdge(addr)) { uint32_t count = _irqCounter; if(_irqCounter == 0 || _irqReload) { _irqCounter = _irqReloadValue; diff --git a/Core/PPU.cpp b/Core/PPU.cpp index 6ef367bd..32e15d6a 100644 --- a/Core/PPU.cpp +++ b/Core/PPU.cpp @@ -112,7 +112,7 @@ void PPU::Reset() _firstVisibleSpriteAddr = 0; _lastVisibleSpriteAddr = 0; - + memset(_oamDecayCycles, 0, sizeof(_oamDecayCycles)); _enableOamDecay = _settings->CheckFlag(EmulationFlags::EnableOamDecay); @@ -999,7 +999,7 @@ void PPU::ProcessScanline() } } else if(_cycle == 337 || _cycle == 339) { if(IsRenderingEnabled()) { - ReadVram(GetNameTableAddr()); + _nextTile.TileAddr = ReadVram(GetNameTableAddr()); if(_scanline == -1 && _cycle == 339 && (_frameCount & 0x01) && _nesModel == NesModel::NTSC && _settings->GetPpuModel() == PpuModel::Ppu2C02) { //This behavior is NTSC-specific - PAL frames are always the same number of cycles @@ -1270,12 +1270,20 @@ void PPU::Exec() } //Cycle = 0 - if(_scanline == -1) { - _statusFlags.SpriteOverflow = false; - _statusFlags.Sprite0Hit = false; - - //Switch to alternate output buffer (VideoDecoder may still be decoding the last frame buffer) - _currentOutputBuffer = (_currentOutputBuffer == _outputBuffers[0]) ? _outputBuffers[1] : _outputBuffers[0]; + if(_scanline < 240) { + if(_scanline == -1) { + _statusFlags.SpriteOverflow = false; + _statusFlags.Sprite0Hit = false; + + //Switch to alternate output buffer (VideoDecoder may still be decoding the last frame buffer) + _currentOutputBuffer = (_currentOutputBuffer == _outputBuffers[0]) ? _outputBuffers[1] : _outputBuffers[0]; + } else if(_prevRenderingEnabled) { + if(_scanline > 0 || (!(_frameCount & 0x01) || _nesModel != NesModel::NTSC || _settings->GetPpuModel() != PpuModel::Ppu2C02)) { + //Set bus address to the tile address calculated from the unused NT fetches at the end of the previous scanline + //This doesn't happen on scanline 0 if the last dot of the previous frame was skipped + SetBusAddress((_nextTile.TileAddr << 4) | (_state.VideoRamAddr >> 12) | _flags.BackgroundPatternAddr); + } + } } else if(_scanline == 240) { //At the start of vblank, the bus address is set back to VideoRamAddr. //According to Visual NES, this occurs on scanline 240, cycle 1, but is done here on cycle for performance reasons