mirror of
https://github.com/libretro/Mesen.git
synced 2024-11-23 09:09:45 +00:00
Backport Fixed PPU bus address on cycle 0 + improved MMC3 IRQ timing
This commit is contained in:
parent
019a3f9da1
commit
415441a069
20
Core/MMC3.h
20
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<uint8_t> 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;
|
||||
|
24
Core/PPU.cpp
24
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
|
||||
|
Loading…
Reference in New Issue
Block a user