GB: Fixed OAM write behavior during DMA

This commit is contained in:
Sour 2020-05-23 11:19:22 -04:00
parent 10be89012c
commit 5279ebb688
5 changed files with 13 additions and 5 deletions

View file

@ -14,7 +14,7 @@ void GbDmaController::Exec()
{ {
if(_state.DmaCounter > 0) { if(_state.DmaCounter > 0) {
if(_state.DmaCounter <= 160) { if(_state.DmaCounter <= 160) {
_memoryManager->Write(0xFE00 + (160 - _state.DmaCounter), _state.DmaReadBuffer); _memoryManager->WriteDma(0xFE00 + (160 - _state.DmaCounter), _state.DmaReadBuffer);
} }
_state.DmaCounter--; _state.DmaCounter--;

View file

@ -151,6 +151,12 @@ bool GbMemoryManager::IsOamDmaRunning()
return _dmaController->IsOamDmaRunning(); return _dmaController->IsOamDmaRunning();
} }
void GbMemoryManager::WriteDma(uint16_t addr, uint8_t value)
{
_console->ProcessMemoryRead<CpuType::Gameboy>(addr, value, MemoryOperationType::DmaWrite);
_ppu->WriteOam(addr, value, true);
}
uint8_t GbMemoryManager::ReadDma(uint16_t addr) uint8_t GbMemoryManager::ReadDma(uint16_t addr)
{ {
uint8_t value = 0; uint8_t value = 0;
@ -323,7 +329,7 @@ void GbMemoryManager::WriteRegister(uint16_t addr, uint8_t value)
} }
} }
} else if(addr >= 0xFE00) { } else if(addr >= 0xFE00) {
_ppu->WriteOam((uint8_t)addr, value); _ppu->WriteOam((uint8_t)addr, value, false);
} else if(addr >= 0x8000 && addr <= 0x9FFF) { } else if(addr >= 0x8000 && addr <= 0x9FFF) {
_ppu->WriteVram(addr, value); _ppu->WriteVram(addr, value);
} else { } else {

View file

@ -57,6 +57,7 @@ public:
uint8_t Read(uint16_t addr, MemoryOperationType opType); uint8_t Read(uint16_t addr, MemoryOperationType opType);
bool IsOamDmaRunning(); bool IsOamDmaRunning();
void WriteDma(uint16_t addr, uint8_t value);
uint8_t ReadDma(uint16_t addr); uint8_t ReadDma(uint16_t addr);
void Write(uint16_t addr, uint8_t value); void Write(uint16_t addr, uint8_t value);

View file

@ -521,9 +521,10 @@ uint8_t GbPpu::ReadOam(uint8_t addr)
return 0; 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; _oam[addr] = value;
} }
} }

View file

@ -84,7 +84,7 @@ public:
void WriteVram(uint16_t addr, uint8_t value); void WriteVram(uint16_t addr, uint8_t value);
uint8_t ReadOam(uint8_t addr); 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); uint8_t ReadCgbRegister(uint16_t addr);
void WriteCgbRegister(uint16_t addr, uint8_t value); void WriteCgbRegister(uint16_t addr, uint8_t value);