PPU: Prevent palette writes during HBlank when rendering is enabled

+ Try to emulate the behavior of $2007 writes during rendering better
This commit is contained in:
Sour 2019-01-27 20:53:25 -05:00
parent 1088eb6656
commit f6b474569d

View file

@ -346,9 +346,9 @@ uint8_t PPU::ReadRAM(uint16_t addr)
returnValue = _memoryReadBuffer; returnValue = _memoryReadBuffer;
_memoryReadBuffer = ReadVram(_ppuBusAddress & 0x3FFF, MemoryOperationType::Read); _memoryReadBuffer = ReadVram(_ppuBusAddress & 0x3FFF, MemoryOperationType::Read);
if((_state.VideoRamAddr & 0x3FFF) >= 0x3F00 && !_settings->CheckFlag(EmulationFlags::DisablePaletteRead)) { if((_ppuBusAddress & 0x3FFF) >= 0x3F00 && !_settings->CheckFlag(EmulationFlags::DisablePaletteRead)) {
returnValue = ReadPaletteRAM(_state.VideoRamAddr) | (_openBus & 0xC0); returnValue = ReadPaletteRAM(_ppuBusAddress) | (_openBus & 0xC0);
_console->DebugProcessVramReadOperation(MemoryOperationType::Read, _state.VideoRamAddr & 0x3FFF, returnValue); _console->DebugProcessVramReadOperation(MemoryOperationType::Read, _ppuBusAddress & 0x3FFF, returnValue);
openBusMask = 0xC0; openBusMask = 0xC0;
} else { } else {
openBusMask = 0x00; openBusMask = 0x00;
@ -429,11 +429,16 @@ void PPU::WriteRAM(uint16_t addr, uint8_t value)
_state.WriteToggle = !_state.WriteToggle; _state.WriteToggle = !_state.WriteToggle;
break; break;
case PPURegisters::VideoMemoryData: case PPURegisters::VideoMemoryData:
if((_state.VideoRamAddr & 0x3FFF) >= 0x3F00) { if((_ppuBusAddress & 0x3FFF) >= 0x3F00) {
WritePaletteRAM(_state.VideoRamAddr, value); WritePaletteRAM(_ppuBusAddress, value);
_console->DebugProcessVramWriteOperation(_state.VideoRamAddr & 0x3FFF, value); _console->DebugProcessVramWriteOperation(_ppuBusAddress & 0x3FFF, value);
} else { } else {
_console->GetMapper()->WriteVRAM(_ppuBusAddress & 0x3FFF, value); if(_scanline >= 240 || !IsRenderingEnabled()) {
_console->GetMapper()->WriteVRAM(_ppuBusAddress & 0x3FFF, value);
} else {
//During rendering, the value written is ignored, and instead the address' LSB is used (not confirmed, based on Visual NES)
_console->GetMapper()->WriteVRAM(_ppuBusAddress & 0x3FFF, _ppuBusAddress & 0xFF);
}
} }
UpdateVideoRamAddr(); UpdateVideoRamAddr();
break; break;
@ -1212,6 +1217,9 @@ void PPU::Exec()
//Switch to alternate output buffer (VideoDecoder may still be decoding the last frame buffer) //Switch to alternate output buffer (VideoDecoder may still be decoding the last frame buffer)
_currentOutputBuffer = (_currentOutputBuffer == _outputBuffers[0]) ? _outputBuffers[1] : _outputBuffers[0]; _currentOutputBuffer = (_currentOutputBuffer == _outputBuffers[0]) ? _outputBuffers[1] : _outputBuffers[0];
} else if(_scanline == 240) { } 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
SetBusAddress(_state.VideoRamAddr);
SendFrame(); SendFrame();
_frameCount++; _frameCount++;
} else if(_scanline == _nmiScanline) { } else if(_scanline == _nmiScanline) {