diff --git a/Core/NES/NesConsole.cpp b/Core/NES/NesConsole.cpp index e56fcda2..c1bcbbef 100644 --- a/Core/NES/NesConsole.cpp +++ b/Core/NES/NesConsole.cpp @@ -64,6 +64,9 @@ void NesConsole::ProcessCpuClock() { _mapper->ProcessCpuClock(); _apu->ProcessCpuClock(); + if(_controlManager->HasPendingWrites()) { + _controlManager->ProcessWrites(); + } } NesConsole* NesConsole::GetVsMainConsole() diff --git a/Core/NES/NesControlManager.cpp b/Core/NES/NesControlManager.cpp index 64411d86..e75e54ea 100644 --- a/Core/NES/NesControlManager.cpp +++ b/Core/NES/NesControlManager.cpp @@ -250,9 +250,19 @@ uint8_t NesControlManager::ReadRam(uint16_t addr) void NesControlManager::WriteRam(uint16_t addr, uint8_t value) { - for(shared_ptr &device : _controlDevices) { - if(device->IsConnected()) { - device->WriteRam(addr, value); + //The OUT pins are only updated at the start of PUT cycles + _writeAddr = addr; + _writeValue = value; + _writePending = (_console->GetMasterClock() & 0x01) ? 1 : 2; +} + +void NesControlManager::ProcessWrites() +{ + if(_writePending && --_writePending == 0) { + for(shared_ptr& device : _controlDevices) { + if(device->IsConnected()) { + device->WriteRam(_writeAddr, _writeValue); + } } } } @@ -266,6 +276,9 @@ void NesControlManager::Serialize(Serializer& s) { BaseControlManager::Serialize(s); SV(_lagCounter); + SV(_writeAddr); + SV(_writeValue); + SV(_writePending); if(!s.IsSaving()) { UpdateControlDevices(); diff --git a/Core/NES/NesControlManager.h b/Core/NES/NesControlManager.h index 6cdc68a0..0e4ddcc2 100644 --- a/Core/NES/NesControlManager.h +++ b/Core/NES/NesControlManager.h @@ -19,6 +19,9 @@ class NesControlManager : public INesMemoryHandler, public BaseControlManager { private: NesConfig _prevConfig = {}; + uint16_t _writeAddr = 0; + uint8_t _writeValue = 0; + uint8_t _writePending = 0; protected: NesConsole* _console; @@ -51,4 +54,7 @@ public: uint8_t ReadRam(uint16_t addr) override; void WriteRam(uint16_t addr, uint8_t value) override; + + __noinline void ProcessWrites(); + __forceinline bool HasPendingWrites() { return _writePending > 0; } };