Debugger: Allow debugger to peek at APU/PPU registers without altering the state

This commit is contained in:
Sour 2018-12-24 23:31:32 -05:00
parent 60e0bd4e01
commit 40710c3665
11 changed files with 101 additions and 20 deletions

View file

@ -78,7 +78,7 @@ void APU::FrameCounterTick(FrameType type)
}
}
uint8_t APU::ReadRAM(uint16_t addr)
uint8_t APU::GetStatus()
{
//$4015 read
Run();
@ -92,12 +92,24 @@ uint8_t APU::ReadRAM(uint16_t addr)
status |= _console->GetCpu()->HasIrqSource(IRQSource::FrameCounter) ? 0x40 : 0x00;
status |= _console->GetCpu()->HasIrqSource(IRQSource::DMC) ? 0x80 : 0x00;
return status;
}
uint8_t APU::ReadRAM(uint16_t addr)
{
uint8_t status = GetStatus();
//Reading $4015 clears the Frame Counter interrupt flag.
_console->GetCpu()->ClearIrqSource(IRQSource::FrameCounter);
return status;
}
uint8_t APU::PeekRAM(uint16_t addr)
{
return GetStatus();
}
void APU::WriteRAM(uint16_t addr, uint8_t value)
{
//$4015 write

View file

@ -46,6 +46,7 @@ class APU : public Snapshotable, public IMemoryHandler
__forceinline bool NeedToRun(uint32_t currentCycle);
void FrameCounterTick(FrameType type);
uint8_t GetStatus();
protected:
void StreamState(bool saving) override;
@ -58,6 +59,7 @@ class APU : public Snapshotable, public IMemoryHandler
void SetNesModel(NesModel model, bool forceInit = false);
uint8_t ReadRAM(uint16_t addr) override;
uint8_t PeekRAM(uint16_t addr) override;
void WriteRAM(uint16_t addr, uint8_t value) override;
void GetMemoryRanges(MemoryRanges &ranges) override;

View file

@ -855,6 +855,11 @@ uint8_t BaseMapper::ReadRAM(uint16_t addr)
return _console->GetMemoryManager()->GetOpenBus();
}
uint8_t BaseMapper::PeekRAM(uint16_t addr)
{
return DebugReadRAM(addr);
}
uint8_t BaseMapper::DebugReadRAM(uint16_t addr)
{
if(_prgPageAccessType[addr >> 8] & MemoryAccessType::Read) {

View file

@ -176,6 +176,7 @@ public:
RomInfo GetRomInfo();
__forceinline uint8_t ReadRAM(uint16_t addr) override;
uint8_t PeekRAM(uint16_t addr) override;
uint8_t DebugReadRAM(uint16_t addr);
virtual void WriteRAM(uint16_t addr, uint8_t value) override;
void DebugWriteRAM(uint16_t addr, uint8_t value);

View file

@ -436,13 +436,8 @@ void Debugger::ProcessAllBreakpoints(OperationInfo &operationInfo, AddressTypeIn
if(_hasBreakpoint[BreakpointType::ReadVram]) {
OperationInfo ppuInfo;
ppuInfo.OperationType = MemoryOperationType::Read;
if((state.PPU.State.VideoRamAddr & 0x3FFF) >= 0x3F00) {
ppuInfo.Address = state.PPU.State.VideoRamAddr;
ppuInfo.Value = _ppu->ReadPaletteRAM(ppuInfo.Address);
} else {
ppuInfo.Address = state.PPU.BusAddress;
ppuInfo.Value = _mapper->DebugReadVRAM(ppuInfo.Address);
}
ppuInfo.Address = state.PPU.BusAddress;
ppuInfo.Value = _ppu->PeekRAM(addr);
if(ProcessBreakpoints(BreakpointType::ReadVram, ppuInfo, true, false)) {
return;
}

View file

@ -50,6 +50,7 @@ public:
virtual void GetMemoryRanges(MemoryRanges &ranges) = 0;
virtual uint8_t ReadRAM(uint16_t addr) = 0;
virtual void WriteRAM(uint16_t addr, uint8_t value) = 0;
virtual uint8_t PeekRAM(uint16_t addr) { return 0; }
virtual ~IMemoryHandler() {}
};

View file

@ -25,6 +25,11 @@ public:
return _internalRam[addr & Mask];
}
uint8_t PeekRAM(uint16_t addr) override
{
return ReadRAM(addr);
}
void WriteRAM(uint16_t addr, uint8_t value) override
{
_internalRam[addr & Mask] = value;

View file

@ -100,10 +100,7 @@ uint8_t MemoryManager::DebugRead(uint16_t addr, bool disableSideEffects)
IMemoryHandler* handler = _ramReadHandlers[addr];
if(handler) {
if(disableSideEffects) {
if(handler == _mapper.get()) {
//Only allow reads from prg/chr ram/rom (e.g not ppu, apu, mapper registers, etc.)
value = ((BaseMapper*)handler)->DebugReadRAM(addr);
}
value = handler->PeekRAM(addr);
} else {
value = handler->ReadRAM(addr);
}

View file

@ -18,6 +18,11 @@ public:
return _lastReadValue;
}
uint8_t PeekRAM(uint16_t addr) override
{
return addr >> 8; //Fake open bus for debugger
}
__forceinline uint8_t GetOpenBus()
{
return _lastReadValue;

View file

@ -227,6 +227,68 @@ uint8_t PPU::ApplyOpenBus(uint8_t mask, uint8_t value)
return value | (_openBus & mask);
}
void PPU::ProcessStatusRegOpenBus(uint8_t &openBusMask, uint8_t &returnValue)
{
switch(_settings->GetPpuModel()) {
case PpuModel::Ppu2C05A: openBusMask = 0x00; returnValue |= 0x1B; break;
case PpuModel::Ppu2C05B: openBusMask = 0x00; returnValue |= 0x3D; break;
case PpuModel::Ppu2C05C: openBusMask = 0x00; returnValue |= 0x1C; break;
case PpuModel::Ppu2C05D: openBusMask = 0x00; returnValue |= 0x1B; break;
case PpuModel::Ppu2C05E: openBusMask = 0x00; break;
default: break;
}
}
uint8_t PPU::PeekRAM(uint16_t addr)
{
//Used by debugger to get register values without side-effects (heavily edited copy of ReadRAM)
uint8_t openBusMask = 0xFF;
uint8_t returnValue = 0;
switch(GetRegisterID(addr)) {
case PPURegisters::Status:
returnValue = ((uint8_t)_statusFlags.SpriteOverflow << 5) | ((uint8_t)_statusFlags.Sprite0Hit << 6) | ((uint8_t)_statusFlags.VerticalBlank << 7);
if(_scanline == 241 && _cycle < 3) {
//Clear vertical blank flag
returnValue &= 0x7F;
}
openBusMask = 0x1F;
ProcessStatusRegOpenBus(openBusMask, returnValue);
break;
case PPURegisters::SpriteData:
if(!_settings->CheckFlag(EmulationFlags::DisablePpu2004Reads)) {
if(_scanline <= 239 && IsRenderingEnabled()) {
if(_cycle >= 257 && _cycle <= 320) {
uint8_t step = ((_cycle - 257) % 8) > 3 ? 3 : ((_cycle - 257) % 8);
uint8_t addr = (_cycle - 257) / 8 * 4 + step;
returnValue = _secondarySpriteRAM[addr];
} else {
returnValue = _oamCopybuffer;
}
} else {
returnValue = _spriteRAM[_state.SpriteRamAddr];
}
openBusMask = 0x00;
}
break;
case PPURegisters::VideoMemoryData:
returnValue = _memoryReadBuffer;
if((_state.VideoRamAddr & 0x3FFF) >= 0x3F00 && !_settings->CheckFlag(EmulationFlags::DisablePaletteRead)) {
returnValue = ReadPaletteRAM(_state.VideoRamAddr) | (_openBus & 0xC0);
openBusMask = 0xC0;
} else {
openBusMask = 0x00;
}
break;
default:
break;
}
return returnValue | (_openBus & openBusMask);
}
uint8_t PPU::ReadRAM(uint16_t addr)
{
uint8_t openBusMask = 0xFF;
@ -239,14 +301,7 @@ uint8_t PPU::ReadRAM(uint16_t addr)
returnValue = _state.Status;
openBusMask = 0x1F;
switch(_settings->GetPpuModel()) {
case PpuModel::Ppu2C05A: openBusMask = 0x00; returnValue |= 0x1B; break;
case PpuModel::Ppu2C05B: openBusMask = 0x00; returnValue |= 0x3D; break;
case PpuModel::Ppu2C05C: openBusMask = 0x00; returnValue |= 0x1C; break;
case PpuModel::Ppu2C05D: openBusMask = 0x00; returnValue |= 0x1B; break;
case PpuModel::Ppu2C05E: openBusMask = 0x00; break;
default: break;
}
ProcessStatusRegOpenBus(openBusMask, returnValue);
break;
case PPURegisters::SpriteData:

View file

@ -114,6 +114,8 @@ class PPU : public IMemoryHandler, public Snapshotable
void SetOpenBus(uint8_t mask, uint8_t value);
uint8_t ApplyOpenBus(uint8_t mask, uint8_t value);
void ProcessStatusRegOpenBus(uint8_t & openBusMask, uint8_t & returnValue);
void UpdateVideoRamAddr();
void IncVerticalScrolling();
void IncHorizontalScrolling();
@ -189,6 +191,7 @@ class PPU : public IMemoryHandler, public Snapshotable
void WritePaletteRAM(uint16_t addr, uint8_t value);
uint8_t ReadRAM(uint16_t addr) override;
uint8_t PeekRAM(uint16_t addr) override;
void WriteRAM(uint16_t addr, uint8_t value) override;
void SetNesModel(NesModel model);