From 5279ebb688d9a13519c8a0977c45a6e16e910e10 Mon Sep 17 00:00:00 2001 From: Sour Date: Sat, 23 May 2020 11:19:22 -0400 Subject: [PATCH] GB: Fixed OAM write behavior during DMA --- Core/GbDmaController.cpp | 2 +- Core/GbMemoryManager.cpp | 8 +++++++- Core/GbMemoryManager.h | 1 + Core/GbPpu.cpp | 5 +++-- Core/GbPpu.h | 2 +- 5 files changed, 13 insertions(+), 5 deletions(-) diff --git a/Core/GbDmaController.cpp b/Core/GbDmaController.cpp index cf2433a..c40f8af 100644 --- a/Core/GbDmaController.cpp +++ b/Core/GbDmaController.cpp @@ -14,7 +14,7 @@ void GbDmaController::Exec() { if(_state.DmaCounter > 0) { if(_state.DmaCounter <= 160) { - _memoryManager->Write(0xFE00 + (160 - _state.DmaCounter), _state.DmaReadBuffer); + _memoryManager->WriteDma(0xFE00 + (160 - _state.DmaCounter), _state.DmaReadBuffer); } _state.DmaCounter--; diff --git a/Core/GbMemoryManager.cpp b/Core/GbMemoryManager.cpp index 59a1aa0..87b22a9 100644 --- a/Core/GbMemoryManager.cpp +++ b/Core/GbMemoryManager.cpp @@ -151,6 +151,12 @@ bool GbMemoryManager::IsOamDmaRunning() return _dmaController->IsOamDmaRunning(); } +void GbMemoryManager::WriteDma(uint16_t addr, uint8_t value) +{ + _console->ProcessMemoryRead(addr, value, MemoryOperationType::DmaWrite); + _ppu->WriteOam(addr, value, true); +} + uint8_t GbMemoryManager::ReadDma(uint16_t addr) { uint8_t value = 0; @@ -323,7 +329,7 @@ void GbMemoryManager::WriteRegister(uint16_t addr, uint8_t value) } } } else if(addr >= 0xFE00) { - _ppu->WriteOam((uint8_t)addr, value); + _ppu->WriteOam((uint8_t)addr, value, false); } else if(addr >= 0x8000 && addr <= 0x9FFF) { _ppu->WriteVram(addr, value); } else { diff --git a/Core/GbMemoryManager.h b/Core/GbMemoryManager.h index 11f32e7..ec0d9eb 100644 --- a/Core/GbMemoryManager.h +++ b/Core/GbMemoryManager.h @@ -57,6 +57,7 @@ public: uint8_t Read(uint16_t addr, MemoryOperationType opType); bool IsOamDmaRunning(); + void WriteDma(uint16_t addr, uint8_t value); uint8_t ReadDma(uint16_t addr); void Write(uint16_t addr, uint8_t value); diff --git a/Core/GbPpu.cpp b/Core/GbPpu.cpp index fa4bb2f..6ad1ad2 100644 --- a/Core/GbPpu.cpp +++ b/Core/GbPpu.cpp @@ -521,9 +521,10 @@ uint8_t GbPpu::ReadOam(uint8_t addr) return 0; } -void GbPpu::WriteOam(uint8_t addr, uint8_t value) +void GbPpu::WriteOam(uint8_t addr, uint8_t value, bool forDma) { - if(addr < 0xA0 && (int)_state.Mode <= (int)PpuMode::VBlank) { + //During DMA or rendering/oam evaluation, ignore writes to OAM + if(addr < 0xA0 && (int)_state.Mode <= (int)PpuMode::VBlank && (forDma || !_memoryManager->IsOamDmaRunning())) { _oam[addr] = value; } } diff --git a/Core/GbPpu.h b/Core/GbPpu.h index 1cc2f60..67adef8 100644 --- a/Core/GbPpu.h +++ b/Core/GbPpu.h @@ -84,7 +84,7 @@ public: void WriteVram(uint16_t addr, uint8_t value); uint8_t ReadOam(uint8_t addr); - void WriteOam(uint8_t addr, uint8_t value); + void WriteOam(uint8_t addr, uint8_t value, bool forDma); uint8_t ReadCgbRegister(uint16_t addr); void WriteCgbRegister(uint16_t addr, uint8_t value);