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 <= 160) {
_memoryManager->Write(0xFE00 + (160 - _state.DmaCounter), _state.DmaReadBuffer);
_memoryManager->WriteDma(0xFE00 + (160 - _state.DmaCounter), _state.DmaReadBuffer);
}
_state.DmaCounter--;

View file

@ -151,6 +151,12 @@ bool GbMemoryManager::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 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 {

View file

@ -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);

View file

@ -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;
}
}

View file

@ -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);