mirror of
https://github.com/libretro/Mesen.git
synced 2025-02-12 12:18:52 +00:00
Implemented ignored reads on PPU $2007 when read 2 cpu cycles in a row (i.e with a dummy read)
Changed DMC stall-time read behavior to read only every other cycle Fixes tests: "dma_2007_read", "dma_4016_read", "double_2007_read"
This commit is contained in:
parent
a6188aef7f
commit
c79a0326ed
@ -164,8 +164,9 @@ private:
|
|||||||
uint8_t MemoryRead(uint16_t addr, MemoryOperationType operationType = MemoryOperationType::Read) {
|
uint8_t MemoryRead(uint16_t addr, MemoryOperationType operationType = MemoryOperationType::Read) {
|
||||||
while(_dmcDmaRunning) {
|
while(_dmcDmaRunning) {
|
||||||
//Stall CPU until we can process a DMC read
|
//Stall CPU until we can process a DMC read
|
||||||
if((addr != 0x4016 && addr != 0x4017) || _dmcCounter == 1) {
|
if((addr != 0x4016 && addr != 0x4017 && (_cycleCount & 0x01)) || _dmcCounter == 1) {
|
||||||
//While the CPU is stalled, reads are performed on the current address
|
//While the CPU is stalled, reads are performed on the current address
|
||||||
|
//Reads are only performed every other cycle? This fixes "dma_2007_read" test
|
||||||
//This behavior causes the $4016/7 data corruption when a DMC is running.
|
//This behavior causes the $4016/7 data corruption when a DMC is running.
|
||||||
//When reading $4016/7, only the last read counts (because this only occurs to low-to-high transitions, i.e once in this case)
|
//When reading $4016/7, only the last read counts (because this only occurs to low-to-high transitions, i.e once in this case)
|
||||||
_memoryManager->Read(addr);
|
_memoryManager->Read(addr);
|
||||||
|
31
Core/PPU.cpp
31
Core/PPU.cpp
@ -31,6 +31,7 @@ PPU::~PPU()
|
|||||||
|
|
||||||
void PPU::Reset()
|
void PPU::Reset()
|
||||||
{
|
{
|
||||||
|
_ignoreVramRead = 0;
|
||||||
_openBus = 0;
|
_openBus = 0;
|
||||||
memset(_openBusDecayStamp, 0, sizeof(_openBusDecayStamp));
|
memset(_openBusDecayStamp, 0, sizeof(_openBusDecayStamp));
|
||||||
|
|
||||||
@ -146,17 +147,24 @@ uint8_t PPU::ReadRAM(uint16_t addr)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case PPURegisters::VideoMemoryData:
|
case PPURegisters::VideoMemoryData:
|
||||||
returnValue = _memoryReadBuffer;
|
if(_ignoreVramRead) {
|
||||||
_memoryReadBuffer = _memoryManager->ReadVRAM(_state.VideoRamAddr, MemoryOperationType::Read);
|
//2 reads to $2007 in quick succession (2 consecutive CPU cycles) causes the 2nd read to be ignored (normally depends on PPU/CPU timing, but this is the simplest solution)
|
||||||
|
//Return open bus in this case? (which will match the last value read)
|
||||||
if(_state.VideoRamAddr >= 0x3F00) {
|
openBusMask = 0xFF;
|
||||||
returnValue = ReadPaletteRAM(_state.VideoRamAddr) | (_openBus & 0xC0);
|
|
||||||
openBusMask = 0xC0;
|
|
||||||
} else {
|
} else {
|
||||||
openBusMask = 0x00;
|
returnValue = _memoryReadBuffer;
|
||||||
}
|
_memoryReadBuffer = _memoryManager->ReadVRAM(_state.VideoRamAddr, MemoryOperationType::Read);
|
||||||
|
|
||||||
UpdateVideoRamAddr();
|
if(_state.VideoRamAddr >= 0x3F00) {
|
||||||
|
returnValue = ReadPaletteRAM(_state.VideoRamAddr) | (_openBus & 0xC0);
|
||||||
|
openBusMask = 0xC0;
|
||||||
|
} else {
|
||||||
|
openBusMask = 0x00;
|
||||||
|
}
|
||||||
|
|
||||||
|
UpdateVideoRamAddr();
|
||||||
|
_ignoreVramRead = 2;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -782,6 +790,9 @@ void PPU::ExecStatic()
|
|||||||
PPU::Instance->Exec();
|
PPU::Instance->Exec();
|
||||||
PPU::Instance->Exec();
|
PPU::Instance->Exec();
|
||||||
PPU::Instance->Exec();
|
PPU::Instance->Exec();
|
||||||
|
if(PPU::Instance->_ignoreVramRead) {
|
||||||
|
PPU::Instance->_ignoreVramRead--;
|
||||||
|
}
|
||||||
if(PPU::Instance->_nesModel == NesModel::PAL && CPU::GetCycleCount() % 5 == 0) {
|
if(PPU::Instance->_nesModel == NesModel::PAL && CPU::GetCycleCount() % 5 == 0) {
|
||||||
//PAL PPU runs 3.2 clocks for every CPU clock, so we need to run an extra clock every 5 CPU clocks
|
//PAL PPU runs 3.2 clocks for every CPU clock, so we need to run an extra clock every 5 CPU clocks
|
||||||
PPU::Instance->Exec();
|
PPU::Instance->Exec();
|
||||||
@ -873,6 +884,8 @@ void PPU::StreamState(bool saving)
|
|||||||
Stream<uint8_t>(_openBus);
|
Stream<uint8_t>(_openBus);
|
||||||
StreamArray<int32_t>(_openBusDecayStamp, 8);
|
StreamArray<int32_t>(_openBusDecayStamp, 8);
|
||||||
|
|
||||||
|
Stream<uint32_t>(_ignoreVramRead);
|
||||||
|
|
||||||
if(!saving) {
|
if(!saving) {
|
||||||
SetNesModel(_nesModel);
|
SetNesModel(_nesModel);
|
||||||
}
|
}
|
||||||
|
@ -133,6 +133,7 @@ class PPU : public IMemoryHandler, public Snapshotable
|
|||||||
|
|
||||||
uint8_t _openBus = 0;
|
uint8_t _openBus = 0;
|
||||||
int32_t _openBusDecayStamp[8];
|
int32_t _openBusDecayStamp[8];
|
||||||
|
uint32_t _ignoreVramRead = 0;
|
||||||
|
|
||||||
uint16_t _spriteDmaCounter = 0;
|
uint16_t _spriteDmaCounter = 0;
|
||||||
uint16_t _spriteDmaAddr = 0;
|
uint16_t _spriteDmaAddr = 0;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user