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 //$4015 read
Run(); 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::FrameCounter) ? 0x40 : 0x00;
status |= _console->GetCpu()->HasIrqSource(IRQSource::DMC) ? 0x80 : 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. //Reading $4015 clears the Frame Counter interrupt flag.
_console->GetCpu()->ClearIrqSource(IRQSource::FrameCounter); _console->GetCpu()->ClearIrqSource(IRQSource::FrameCounter);
return status; return status;
} }
uint8_t APU::PeekRAM(uint16_t addr)
{
return GetStatus();
}
void APU::WriteRAM(uint16_t addr, uint8_t value) void APU::WriteRAM(uint16_t addr, uint8_t value)
{ {
//$4015 write //$4015 write

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -227,6 +227,68 @@ uint8_t PPU::ApplyOpenBus(uint8_t mask, uint8_t value)
return value | (_openBus & mask); 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 PPU::ReadRAM(uint16_t addr)
{ {
uint8_t openBusMask = 0xFF; uint8_t openBusMask = 0xFF;
@ -239,14 +301,7 @@ uint8_t PPU::ReadRAM(uint16_t addr)
returnValue = _state.Status; returnValue = _state.Status;
openBusMask = 0x1F; openBusMask = 0x1F;
switch(_settings->GetPpuModel()) { ProcessStatusRegOpenBus(openBusMask, returnValue);
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;
}
break; break;
case PPURegisters::SpriteData: case PPURegisters::SpriteData:

View file

@ -114,6 +114,8 @@ class PPU : public IMemoryHandler, public Snapshotable
void SetOpenBus(uint8_t mask, uint8_t value); void SetOpenBus(uint8_t mask, uint8_t value);
uint8_t ApplyOpenBus(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 UpdateVideoRamAddr();
void IncVerticalScrolling(); void IncVerticalScrolling();
void IncHorizontalScrolling(); void IncHorizontalScrolling();
@ -189,6 +191,7 @@ class PPU : public IMemoryHandler, public Snapshotable
void WritePaletteRAM(uint16_t addr, uint8_t value); void WritePaletteRAM(uint16_t addr, uint8_t value);
uint8_t ReadRAM(uint16_t addr) override; uint8_t ReadRAM(uint16_t addr) override;
uint8_t PeekRAM(uint16_t addr) override;
void WriteRAM(uint16_t addr, uint8_t value) override; void WriteRAM(uint16_t addr, uint8_t value) override;
void SetNesModel(NesModel model); void SetNesModel(NesModel model);