From 411967e4faf7f80a53b4b51d5c9b20a0d9de0ce4 Mon Sep 17 00:00:00 2001 From: Souryo Date: Sat, 2 Jan 2016 20:36:22 -0500 Subject: [PATCH] Open bus (PPU and CPU) - Fixes several open bus related tests (ppu_open_bus, test_cpu_exec_space_apu, test_cpu_exec_space_ppuio) --- Core/BaseMapper.h | 2 +- Core/MemoryManager.cpp | 2 +- Core/PPU.cpp | 77 ++++++++++++++++++++++++++++++++++++------ Core/PPU.h | 9 +++-- 4 files changed, 76 insertions(+), 14 deletions(-) diff --git a/Core/BaseMapper.h b/Core/BaseMapper.h index 077ca901..d71276d5 100644 --- a/Core/BaseMapper.h +++ b/Core/BaseMapper.h @@ -494,7 +494,7 @@ class BaseMapper : public IMemoryHandler, public Snapshotable, public INotificat } else { //assert(false); } - return 0; + return (addr & 0xFF00) >> 8; } virtual void WriteRAM(uint16_t addr, uint8_t value) diff --git a/Core/MemoryManager.cpp b/Core/MemoryManager.cpp index a6b5eb3a..f919fb9d 100644 --- a/Core/MemoryManager.cpp +++ b/Core/MemoryManager.cpp @@ -47,7 +47,7 @@ uint8_t MemoryManager::ReadRegister(uint16_t addr) if(_ramReadHandlers[addr]) { return _ramReadHandlers[addr]->ReadRAM(addr); } else { - return 0; + return (addr & 0xFF00) >> 8; } } diff --git a/Core/PPU.cpp b/Core/PPU.cpp index b8064b07..4b884dca 100644 --- a/Core/PPU.cpp +++ b/Core/PPU.cpp @@ -31,6 +31,9 @@ PPU::~PPU() void PPU::Reset() { + _openBus = 0; + memset(_openBusDecayStamp, 0, sizeof(_openBusDecayStamp)); + _skipTick = false; _state = {}; @@ -39,7 +42,7 @@ void PPU::Reset() _scanline = 0; _cycle = 0; - _frameCount = -1; + _frameCount = 1; _memoryReadBuffer = 0; } @@ -76,15 +79,56 @@ void PPU::UpdateVideoRamAddr() } } +void PPU::SetOpenBus(uint8_t mask, uint8_t value) +{ + //Decay expired bits, set new bits and update stamps on each individual bit + if(mask == 0xFF) { + //Shortcut when mask is 0xFF - all bits are set to the value and stamps updated + _openBus = value; + for(int i = 0; i < 8; i++) { + _openBusDecayStamp[i] = _frameCount; + } + } else { + uint16_t openBus = (_openBus << 8); + for(int i = 0; i < 8; i++) { + openBus >>= 1; + if(mask & 0x01) { + if(value & 0x01) { + openBus |= 0x80; + } else { + openBus &= 0xFF7F; + } + _openBusDecayStamp[i] = _frameCount; + } else if(_frameCount - _openBusDecayStamp[i] > 30) { + openBus &= 0xFF7F; + } + value >>= 1; + mask >>= 1; + } + + _openBus = openBus & 0xFF; + } +} + +uint8_t PPU::ApplyOpenBus(uint8_t mask, uint8_t value) +{ + SetOpenBus(~mask, value); + return value | (_openBus & mask); +} + uint8_t PPU::ReadRAM(uint16_t addr) { - uint8_t returnValue; + uint8_t openBusMask = 0xFF; + uint8_t returnValue = 0; switch(GetRegisterID(addr)) { case PPURegisters::Status: _state.WriteToggle = false; _flags.IntensifyBlue = false; UpdateStatusFlag(); - return _state.Status; + returnValue = _state.Status; + openBusMask = 0x1F; + break; + case PPURegisters::SpriteData: if(_scanline <= 240 && IsRenderingEnabled() && (_cycle >= 257 || _cycle <= 64)) { if(_cycle >= 257 && _cycle <= 320) { @@ -94,29 +138,39 @@ uint8_t PPU::ReadRAM(uint16_t addr) _secondaryOAMAddr = (_cycle - 257) / 8 * 4 + step; _oamCopybuffer = _secondarySpriteRAM[_secondaryOAMAddr]; } - return _oamCopybuffer; + returnValue = _oamCopybuffer; } else { - return _spriteRAM[_state.SpriteRamAddr]; + returnValue = _spriteRAM[_state.SpriteRamAddr]; } + openBusMask = 0x00; + break; + case PPURegisters::VideoMemoryData: returnValue = _memoryReadBuffer; _memoryReadBuffer = _memoryManager->ReadVRAM(_state.VideoRamAddr, MemoryOperationType::Read); if(_state.VideoRamAddr >= 0x3F00) { - returnValue = ReadPaletteRAM(_state.VideoRamAddr); + returnValue = ReadPaletteRAM(_state.VideoRamAddr) | (_openBus & 0xC0); + openBusMask = 0xC0; + } else { + openBusMask = 0x00; } UpdateVideoRamAddr(); - return returnValue; + break; + default: - //other registers are meant to be read-only break; } - return 0; + return ApplyOpenBus(openBusMask, returnValue); } void PPU::WriteRAM(uint16_t addr, uint8_t value) { + if(addr != 0x4014) { + SetOpenBus(0xFF, value); + } + switch(GetRegisterID(addr)) { case PPURegisters::Control: SetControlRegister(value); @@ -750,7 +804,7 @@ void PPU::StreamState(bool saving) Stream(_scanline); Stream(_cycle); - Stream(_frameCount); + Stream(_frameCount); Stream(_memoryReadBuffer); StreamArray(_paletteRAM, 0x20); @@ -794,6 +848,9 @@ void PPU::StreamState(bool saving) Stream(_skipTick); + Stream(_openBus); + StreamArray(_openBusDecayStamp, 8); + if(!saving) { SetNesModel(_nesModel); } diff --git a/Core/PPU.h b/Core/PPU.h index f81e8453..5fb11f2b 100644 --- a/Core/PPU.h +++ b/Core/PPU.h @@ -97,7 +97,7 @@ class PPU : public IMemoryHandler, public Snapshotable PPUState _state; int32_t _scanline; uint32_t _cycle; - int32_t _frameCount; + uint32_t _frameCount; uint8_t _memoryReadBuffer; uint8_t _paletteRAM[0x20]; @@ -131,6 +131,9 @@ class PPU : public IMemoryHandler, public Snapshotable uint32_t _spriteIndex = 0; + uint8_t _openBus = 0; + int32_t _openBusDecayStamp[8]; + uint16_t _spriteDmaCounter = 0; uint16_t _spriteDmaAddr = 0; @@ -146,6 +149,9 @@ class PPU : public IMemoryHandler, public Snapshotable bool IsRenderingEnabled(); + void SetOpenBus(uint8_t mask, uint8_t value); + uint8_t ApplyOpenBus(uint8_t mask, uint8_t value); + void UpdateVideoRamAddr(); void IncVerticalScrolling(); void IncHorizontalScrolling(); @@ -203,7 +209,6 @@ class PPU : public IMemoryHandler, public Snapshotable void GetMemoryRanges(MemoryRanges &ranges) { ranges.AddHandler(MemoryOperation::Read, 0x2000, 0x3FFF); - ranges.AddHandler(MemoryOperation::Read, 0x4014); ranges.AddHandler(MemoryOperation::Write, 0x2000, 0x3FFF); ranges.AddHandler(MemoryOperation::Write, 0x4014); }