Debugger: GB - Added GB-specific "break on" options

This commit is contained in:
Sour 2020-06-07 16:34:23 -04:00
parent 78dc5d3d1c
commit 4e77e6caef
17 changed files with 280 additions and 43 deletions

View file

@ -957,6 +957,13 @@ void Console::ProcessEvent(EventType type)
}
}
void Console::BreakImmediately(BreakSource source)
{
if(_debugger) {
_debugger->BreakImmediately(source);
}
}
template void Console::ProcessMemoryRead<CpuType::Cpu>(uint32_t addr, uint8_t value, MemoryOperationType opType);
template void Console::ProcessMemoryRead<CpuType::Sa1>(uint32_t addr, uint8_t value, MemoryOperationType opType);
template void Console::ProcessMemoryRead<CpuType::Spc>(uint32_t addr, uint8_t value, MemoryOperationType opType);

View file

@ -181,4 +181,5 @@ public:
void ProcessPpuCycle(uint16_t scanline, uint16_t cycle);
template<CpuType type> void ProcessInterrupt(uint32_t originalPc, uint32_t currentPc, bool forNmi);
void ProcessEvent(EventType type);
void BreakImmediately(BreakSource source);
};

View file

@ -230,7 +230,14 @@ enum class BreakSource
BreakOnCop = 4,
BreakOnWdm = 5,
BreakOnStp = 6,
BreakOnUninitMemoryRead = 7
BreakOnUninitMemoryRead = 7,
GbInvalidOamAccess = 8,
GbInvalidVramAccess = 9,
GbDisableLcdOutsideVblank = 10,
GbInvalidOpCode = 11,
GbNopLoad = 12,
GbOamCorruption = 13,
};
struct BreakEvent

View file

@ -434,6 +434,18 @@ void Debugger::SuspendDebugger(bool release)
}
}
void Debugger::BreakImmediately(BreakSource source)
{
if(source == BreakSource::GbDisableLcdOutsideVblank && !_settings->CheckDebuggerFlag(DebuggerFlags::GbBreakOnDisableLcdOutsideVblank)) {
return;
} else if(source == BreakSource::GbInvalidVramAccess && !_settings->CheckDebuggerFlag(DebuggerFlags::GbBreakOnInvalidVramAccess)) {
return;
} else if(source == BreakSource::GbInvalidOamAccess && !_settings->CheckDebuggerFlag(DebuggerFlags::GbBreakOnInvalidOamAccess)) {
return;
}
SleepUntilResume(source);
}
void Debugger::GetState(DebugState &state, bool partialPpuState)
{
state.MasterClock = _memoryManager->GetMasterClock();

View file

@ -116,6 +116,8 @@ public:
void BreakRequest(bool release);
void SuspendDebugger(bool release);
void BreakImmediately(BreakSource source);
void ProcessBreakConditions(bool needBreak, BreakpointManager *bpManager, MemoryOperationInfo &operation, AddressInfo &addressInfo, BreakSource source = BreakSource::Unspecified);
void GetState(DebugState &state, bool partialPpuState);

View file

@ -95,6 +95,25 @@ void GbDebugger::ProcessRead(uint16_t addr, uint8_t value, MemoryOperationType t
_step->StepCount = 0;
}
if(_settings->CheckDebuggerFlag(DebuggerFlags::GbDebuggerEnabled)) {
bool needBreak = false;
switch(value) {
case 0x40:
needBreak = _settings->CheckDebuggerFlag(DebuggerFlags::GbBreakOnNopLoad);
breakSource = BreakSource::GbNopLoad;
break;
case 0xD3: case 0xDB: case 0xDD: case 0xE3: case 0xE4: case 0xE8: case 0xEC: case 0xED: case 0xF4: case 0xFC: case 0xFD:
needBreak = _settings->CheckDebuggerFlag(DebuggerFlags::GbBreakOnInvalidOpCode);
breakSource = BreakSource::GbInvalidOpCode;
break;
}
if(needBreak) {
_step->StepCount = 0;
}
}
_prevOpCode = value;
_prevProgramCounter = gbState.PC;

View file

@ -218,6 +218,18 @@ uint8_t* GbMemoryManager::GetMappedBlock(uint16_t addr)
return nullptr;
}
uint8_t GbMemoryManager::PeekRegister(uint16_t addr)
{
//Peek on oam/vram to avoid triggering the invalid oam/vram access break options
if(addr >= 0xFE00 && addr <= 0xFE9F) {
return _ppu->PeekOam((uint8_t)addr);
} else if(addr >= 0x8000 && addr <= 0x9FFF) {
return _ppu->PeekVram(addr);
} else {
ReadRegister(addr);
}
}
uint8_t GbMemoryManager::ReadRegister(uint16_t addr)
{
if(addr >= 0xFF00) {

View file

@ -60,6 +60,7 @@ public:
template<MemoryOperationType type = MemoryOperationType::Write>
void Write(uint16_t addr, uint8_t value);
uint8_t PeekRegister(uint16_t addr);
uint8_t ReadRegister(uint16_t addr);
void WriteRegister(uint16_t addr, uint8_t value);

View file

@ -677,6 +677,10 @@ void GbPpu::Write(uint16_t addr, uint8_t value)
if(!_state.LcdEnabled) {
//Reset LCD to top of screen when it gets turned off
if(_state.Mode != PpuMode::VBlank) {
_console->BreakImmediately(BreakSource::GbDisableLcdOutsideVblank);
}
_state.Cycle = 0;
_state.Scanline = 0;
_state.Ly = 0;
@ -752,41 +756,82 @@ void GbPpu::Write(uint16_t addr, uint8_t value)
}
}
bool GbPpu::IsVramReadAllowed()
{
return _state.Mode <= PpuMode::VBlank || (_state.Mode == PpuMode::OamEvaluation && _state.Cycle < 80);
}
bool GbPpu::IsVramWriteAllowed()
{
return _state.Mode <= PpuMode::OamEvaluation;
}
uint8_t GbPpu::ReadVram(uint16_t addr)
{
if(_state.Mode <= PpuMode::VBlank || (_state.Mode == PpuMode::OamEvaluation && _state.Cycle < 80)) {
if(IsVramReadAllowed()) {
return _vram[(_state.CgbVramBank << 13) | (addr & 0x1FFF)];
} else {
_console->BreakImmediately(BreakSource::GbInvalidVramAccess);
return 0xFF;
}
}
uint8_t GbPpu::PeekVram(uint8_t addr)
{
return IsVramReadAllowed() ? _vram[(_state.CgbVramBank << 13) | (addr & 0x1FFF)] : 0xFF;
}
void GbPpu::WriteVram(uint16_t addr, uint8_t value)
{
if(_state.Mode <= PpuMode::OamEvaluation) {
if(IsVramWriteAllowed()) {
_vram[(_state.CgbVramBank << 13) | (addr & 0x1FFF)] = value;
} else {
_console->BreakImmediately(BreakSource::GbInvalidVramAccess);
}
}
bool GbPpu::IsOamWriteAllowed()
{
if(_memoryManager->IsOamDmaRunning()) {
return false;
}
if(_state.Scanline == 0 && _isFirstFrame) {
return _state.Mode == PpuMode::HBlank && _state.Cycle != 77 && _state.Cycle != 78;
} else {
return _state.Mode <= PpuMode::VBlank || (_state.Cycle >= 80 && _state.Cycle < 84);
}
}
bool GbPpu::IsOamReadAllowed()
{
if(_memoryManager->IsOamDmaRunning()) {
return false;
}
if(_state.Scanline == 0 && _isFirstFrame) {
return _state.Mode == PpuMode::HBlank;
} else {
return _state.Mode == PpuMode::VBlank || (_state.Mode == PpuMode::HBlank && _state.Cycle != 3);
}
}
uint8_t GbPpu::PeekOam(uint8_t addr)
{
if(addr < 0xA0) {
return IsOamReadAllowed() ? _oam[addr] : 0xFF;
}
return 0;
}
uint8_t GbPpu::ReadOam(uint8_t addr)
{
if(addr < 0xA0) {
if(_memoryManager->IsOamDmaRunning()) {
return 0xFF;
}
if(_state.Scanline == 0 && _isFirstFrame) {
if(_state.Mode == PpuMode::HBlank) {
return _oam[addr];
} else {
return 0xFF;
}
if(IsOamReadAllowed()) {
return _oam[addr];
} else {
if(_state.Mode == PpuMode::VBlank || (_state.Mode == PpuMode::HBlank && _state.Cycle != 3)) {
return _oam[addr];
} else {
return 0xFF;
}
_console->BreakImmediately(BreakSource::GbInvalidOamAccess);
return 0xFF;
}
}
return 0;
@ -800,18 +845,10 @@ void GbPpu::WriteOam(uint8_t addr, uint8_t value, bool forDma)
if(addr < 0xA0) {
if(forDma) {
_oam[addr] = value;
} else if(_memoryManager->IsOamDmaRunning()) {
return;
}
if(_state.Scanline == 0 && _isFirstFrame) {
if(_state.Mode == PpuMode::HBlank && _state.Cycle != 77 && _state.Cycle != 78) {
_oam[addr] = value;
}
} else if(IsOamWriteAllowed()) {
_oam[addr] = value;
} else {
if(_state.Mode <= PpuMode::VBlank || (_state.Cycle >= 80 && _state.Cycle < 84)) {
_oam[addr] = value;
}
_console->BreakImmediately(BreakSource::GbInvalidOamAccess);
}
}
}

View file

@ -90,10 +90,16 @@ public:
uint8_t Read(uint16_t addr);
void Write(uint16_t addr, uint8_t value);
bool IsVramReadAllowed();
bool IsVramWriteAllowed();
uint8_t ReadVram(uint16_t addr);
uint8_t PeekVram(uint8_t addr);
void WriteVram(uint16_t addr, uint8_t value);
bool IsOamReadAllowed();
bool IsOamWriteAllowed();
uint8_t ReadOam(uint8_t addr);
uint8_t PeekOam(uint8_t addr);
void WriteOam(uint8_t addr, uint8_t value, bool forDma);
uint8_t ReadCgbRegister(uint16_t addr);

View file

@ -504,6 +504,13 @@ enum class DebuggerFlags : uint32_t
AutoResetCdl = 0x4000,
GbBreakOnInvalidOamAccess = 0x10000,
GbBreakOnInvalidVramAccess = 0x20000,
GbBreakOnDisableLcdOutsideVblank = 0x40000,
GbBreakOnInvalidOpCode = 0x80000,
GbBreakOnNopLoad = 0x100000,
GbBreakOnOamCorruption = 0x200000,
GbDebuggerEnabled = 0x02000000,
Cx4DebuggerEnabled = 0x04000000,
NecDspDebuggerEnabled = 0x08000000,

View file

@ -25,6 +25,13 @@ namespace Mesen.GUI.Config
public bool BreakOnStp = false;
public bool BreakOnUninitRead = false;
public bool GbBreakOnInvalidOamAccess = false;
public bool GbBreakOnInvalidVramAccess = false;
public bool GbBreakOnDisableLcdOutsideVblank = false;
public bool GbBreakOnInvalidOpCode = false;
public bool GbBreakOnNopLoad = false;
public bool GbBreakOnOamCorruption = false;
public bool BreakOnOpen = true;
public bool BreakOnPowerCycleReset = true;
@ -78,6 +85,13 @@ namespace Mesen.GUI.Config
ConfigApi.SetDebuggerFlag(DebuggerFlags.BreakOnStp, BreakOnStp);
ConfigApi.SetDebuggerFlag(DebuggerFlags.BreakOnUninitRead, BreakOnUninitRead);
ConfigApi.SetDebuggerFlag(DebuggerFlags.GbBreakOnInvalidOamAccess, GbBreakOnInvalidOamAccess);
ConfigApi.SetDebuggerFlag(DebuggerFlags.GbBreakOnInvalidVramAccess, GbBreakOnInvalidVramAccess);
ConfigApi.SetDebuggerFlag(DebuggerFlags.GbBreakOnDisableLcdOutsideVblank, GbBreakOnDisableLcdOutsideVblank);
ConfigApi.SetDebuggerFlag(DebuggerFlags.GbBreakOnInvalidOpCode, GbBreakOnInvalidOpCode);
ConfigApi.SetDebuggerFlag(DebuggerFlags.GbBreakOnNopLoad, GbBreakOnNopLoad);
ConfigApi.SetDebuggerFlag(DebuggerFlags.GbBreakOnOamCorruption, GbBreakOnOamCorruption);
ConfigApi.SetDebuggerFlag(DebuggerFlags.ShowUnidentifiedData, UnidentifiedBlockDisplay == CodeDisplayMode.Show);
ConfigApi.SetDebuggerFlag(DebuggerFlags.DisassembleUnidentifiedData, UnidentifiedBlockDisplay == CodeDisplayMode.Disassemble);
ConfigApi.SetDebuggerFlag(DebuggerFlags.ShowVerifiedData, VerifiedDataDisplay == CodeDisplayMode.Show);

View file

@ -120,6 +120,13 @@
this.toolStripMenuItem10 = new System.Windows.Forms.ToolStripSeparator();
this.mnuBringToFrontOnBreak = new System.Windows.Forms.ToolStripMenuItem();
this.mnuBringToFrontOnPause = new System.Windows.Forms.ToolStripMenuItem();
this.sepGameboyBreak = new System.Windows.Forms.ToolStripSeparator();
this.mnuGbBreakOnOamCorruption = new System.Windows.Forms.ToolStripMenuItem();
this.mnuGbBreakOnInvalidOamAccess = new System.Windows.Forms.ToolStripMenuItem();
this.mnuGbBreakOnInvalidVramAccess = new System.Windows.Forms.ToolStripMenuItem();
this.mnuGbBreakOnDisableLcdOutsideVblank = new System.Windows.Forms.ToolStripMenuItem();
this.mnuGbBreakOnInvalidOpCode = new System.Windows.Forms.ToolStripMenuItem();
this.mnuGbBreakOnNopLoad = new System.Windows.Forms.ToolStripMenuItem();
this.toolStripMenuItem5 = new System.Windows.Forms.ToolStripSeparator();
this.mnuFontOptions = new System.Windows.Forms.ToolStripMenuItem();
this.mnuIncreaseFontSize = new System.Windows.Forms.ToolStripMenuItem();
@ -758,7 +765,14 @@
this.mnuBreakOnUnitRead,
this.toolStripMenuItem10,
this.mnuBringToFrontOnBreak,
this.mnuBringToFrontOnPause});
this.mnuBringToFrontOnPause,
this.sepGameboyBreak,
this.mnuGbBreakOnOamCorruption,
this.mnuGbBreakOnInvalidOamAccess,
this.mnuGbBreakOnInvalidVramAccess,
this.mnuGbBreakOnDisableLcdOutsideVblank,
this.mnuGbBreakOnInvalidOpCode,
this.mnuGbBreakOnNopLoad});
this.mnuBreakOptions.Name = "mnuBreakOptions";
this.mnuBreakOptions.Size = new System.Drawing.Size(209, 22);
this.mnuBreakOptions.Text = "Break Options";
@ -767,73 +781,121 @@
// mnuBreakOnPowerCycleReset
//
this.mnuBreakOnPowerCycleReset.Name = "mnuBreakOnPowerCycleReset";
this.mnuBreakOnPowerCycleReset.Size = new System.Drawing.Size(261, 22);
this.mnuBreakOnPowerCycleReset.Size = new System.Drawing.Size(265, 22);
this.mnuBreakOnPowerCycleReset.Text = "Break on power/reset";
//
// mnuBreakOnOpen
//
this.mnuBreakOnOpen.Name = "mnuBreakOnOpen";
this.mnuBreakOnOpen.Size = new System.Drawing.Size(261, 22);
this.mnuBreakOnOpen.Size = new System.Drawing.Size(265, 22);
this.mnuBreakOnOpen.Text = "Break when debugger is opened";
//
// sepBrkCopStpWdm
//
this.sepBrkCopStpWdm.Name = "sepBrkCopStpWdm";
this.sepBrkCopStpWdm.Size = new System.Drawing.Size(258, 6);
this.sepBrkCopStpWdm.Size = new System.Drawing.Size(262, 6);
//
// mnuBreakOnBrk
//
this.mnuBreakOnBrk.Name = "mnuBreakOnBrk";
this.mnuBreakOnBrk.Size = new System.Drawing.Size(261, 22);
this.mnuBreakOnBrk.Size = new System.Drawing.Size(265, 22);
this.mnuBreakOnBrk.Text = "Break on BRK";
//
// mnuBreakOnCop
//
this.mnuBreakOnCop.Name = "mnuBreakOnCop";
this.mnuBreakOnCop.Size = new System.Drawing.Size(261, 22);
this.mnuBreakOnCop.Size = new System.Drawing.Size(265, 22);
this.mnuBreakOnCop.Text = "Break on COP";
//
// mnuBreakOnStp
//
this.mnuBreakOnStp.Name = "mnuBreakOnStp";
this.mnuBreakOnStp.Size = new System.Drawing.Size(261, 22);
this.mnuBreakOnStp.Size = new System.Drawing.Size(265, 22);
this.mnuBreakOnStp.Text = "Break on STP";
//
// mnuBreakOnWdm
//
this.mnuBreakOnWdm.Name = "mnuBreakOnWdm";
this.mnuBreakOnWdm.Size = new System.Drawing.Size(261, 22);
this.mnuBreakOnWdm.Size = new System.Drawing.Size(265, 22);
this.mnuBreakOnWdm.Text = "Break on WDM";
//
// sepBreakOnUnitRead
//
this.sepBreakOnUnitRead.Name = "sepBreakOnUnitRead";
this.sepBreakOnUnitRead.Size = new System.Drawing.Size(258, 6);
this.sepBreakOnUnitRead.Size = new System.Drawing.Size(262, 6);
//
// mnuBreakOnUnitRead
//
this.mnuBreakOnUnitRead.Name = "mnuBreakOnUnitRead";
this.mnuBreakOnUnitRead.Size = new System.Drawing.Size(261, 22);
this.mnuBreakOnUnitRead.Size = new System.Drawing.Size(265, 22);
this.mnuBreakOnUnitRead.Text = "Break on uninitialized memory read";
//
// toolStripMenuItem10
//
this.toolStripMenuItem10.Name = "toolStripMenuItem10";
this.toolStripMenuItem10.Size = new System.Drawing.Size(258, 6);
this.toolStripMenuItem10.Size = new System.Drawing.Size(262, 6);
//
// mnuBringToFrontOnBreak
//
this.mnuBringToFrontOnBreak.Name = "mnuBringToFrontOnBreak";
this.mnuBringToFrontOnBreak.Size = new System.Drawing.Size(261, 22);
this.mnuBringToFrontOnBreak.Size = new System.Drawing.Size(265, 22);
this.mnuBringToFrontOnBreak.Text = "Bring debugger to front on break";
//
// mnuBringToFrontOnPause
//
this.mnuBringToFrontOnPause.Name = "mnuBringToFrontOnPause";
this.mnuBringToFrontOnPause.Size = new System.Drawing.Size(261, 22);
this.mnuBringToFrontOnPause.Size = new System.Drawing.Size(265, 22);
this.mnuBringToFrontOnPause.Text = "Bring debugger to front on pause";
this.mnuBringToFrontOnPause.Visible = false;
//
// sepGameboyBreak
//
this.sepGameboyBreak.Name = "sepGameboyBreak";
this.sepGameboyBreak.Size = new System.Drawing.Size(262, 6);
this.sepGameboyBreak.Visible = false;
//
// mnuGbBreakOnOamCorruption
//
this.mnuGbBreakOnOamCorruption.Name = "mnuGbBreakOnOamCorruption";
this.mnuGbBreakOnOamCorruption.Size = new System.Drawing.Size(265, 22);
this.mnuGbBreakOnOamCorruption.Text = "Break on OAM corruption";
this.mnuGbBreakOnOamCorruption.Visible = false;
//
// mnuGbBreakOnInvalidOamAccess
//
this.mnuGbBreakOnInvalidOamAccess.Name = "mnuGbBreakOnInvalidOamAccess";
this.mnuGbBreakOnInvalidOamAccess.Size = new System.Drawing.Size(265, 22);
this.mnuGbBreakOnInvalidOamAccess.Text = "Break on invalid OAM access";
this.mnuGbBreakOnInvalidOamAccess.Visible = false;
//
// mnuGbBreakOnInvalidVramAccess
//
this.mnuGbBreakOnInvalidVramAccess.Name = "mnuGbBreakOnInvalidVramAccess";
this.mnuGbBreakOnInvalidVramAccess.Size = new System.Drawing.Size(265, 22);
this.mnuGbBreakOnInvalidVramAccess.Text = "Break on invalid VRAM access";
this.mnuGbBreakOnInvalidVramAccess.Visible = false;
//
// mnuGbBreakOnDisableLcdOutsideVblank
//
this.mnuGbBreakOnDisableLcdOutsideVblank.Name = "mnuGbBreakOnDisableLcdOutsideVblank";
this.mnuGbBreakOnDisableLcdOutsideVblank.Size = new System.Drawing.Size(265, 22);
this.mnuGbBreakOnDisableLcdOutsideVblank.Text = "Break on LCD disable outside vblank";
this.mnuGbBreakOnDisableLcdOutsideVblank.Visible = false;
//
// mnuGbBreakOnInvalidOpCode
//
this.mnuGbBreakOnInvalidOpCode.Name = "mnuGbBreakOnInvalidOpCode";
this.mnuGbBreakOnInvalidOpCode.Size = new System.Drawing.Size(265, 22);
this.mnuGbBreakOnInvalidOpCode.Text = "Break on invalid instructions";
this.mnuGbBreakOnInvalidOpCode.Visible = false;
//
// mnuGbBreakOnNopLoad
//
this.mnuGbBreakOnNopLoad.Name = "mnuGbBreakOnNopLoad";
this.mnuGbBreakOnNopLoad.Size = new System.Drawing.Size(265, 22);
this.mnuGbBreakOnNopLoad.Text = "Break on LD B, B (nop)";
this.mnuGbBreakOnNopLoad.Visible = false;
//
// toolStripMenuItem5
//
this.toolStripMenuItem5.Name = "toolStripMenuItem5";
@ -1220,5 +1282,12 @@
private System.Windows.Forms.ToolStripMenuItem mnuAutoResetCdl;
private System.Windows.Forms.ToolStripSeparator toolStripMenuItem12;
private System.Windows.Forms.ToolStripMenuItem mnuShowMemoryMappings;
private System.Windows.Forms.ToolStripSeparator sepGameboyBreak;
private System.Windows.Forms.ToolStripMenuItem mnuGbBreakOnInvalidOamAccess;
private System.Windows.Forms.ToolStripMenuItem mnuGbBreakOnInvalidVramAccess;
private System.Windows.Forms.ToolStripMenuItem mnuGbBreakOnDisableLcdOutsideVblank;
private System.Windows.Forms.ToolStripMenuItem mnuGbBreakOnInvalidOpCode;
private System.Windows.Forms.ToolStripMenuItem mnuGbBreakOnNopLoad;
private System.Windows.Forms.ToolStripMenuItem mnuGbBreakOnOamCorruption;
}
}

View file

@ -154,6 +154,14 @@ namespace Mesen.GUI.Debugger
mnuBreakOnStp.Visible = false;
ctrlPpuStatus.Visible = false;
sepGameboyBreak.Visible = true;
mnuGbBreakOnDisableLcdOutsideVblank.Visible = true;
mnuGbBreakOnInvalidOamAccess.Visible = true;
mnuGbBreakOnInvalidOpCode.Visible = true;
mnuGbBreakOnInvalidVramAccess.Visible = true;
mnuGbBreakOnNopLoad.Visible = true;
mnuGbBreakOnOamCorruption.Visible = false;
this.ctrlGameboyStatus = new ctrlGameboyStatus();
this.ctrlGameboyStatus.Padding = new Padding(3, 0, 3, 0);
this.ctrlGameboyStatus.Dock = DockStyle.Top;
@ -345,8 +353,17 @@ namespace Mesen.GUI.Debugger
mnuBreakOnStp.Click += (s, e) => { InvertFlag(ref ConfigManager.Config.Debug.Debugger.BreakOnStp); };
mnuBreakOnWdm.Click += (s, e) => { InvertFlag(ref ConfigManager.Config.Debug.Debugger.BreakOnWdm); };
mnuBreakOnOpen.Click += (s, e) => { InvertFlag(ref ConfigManager.Config.Debug.Debugger.BreakOnOpen); };
mnuBreakOnPowerCycleReset.Click += (s, e) => { InvertFlag(ref ConfigManager.Config.Debug.Debugger.BreakOnPowerCycleReset); };
mnuBreakOnUnitRead.Click += (s, e) => { InvertFlag(ref ConfigManager.Config.Debug.Debugger.BreakOnUninitRead); };
mnuGbBreakOnDisableLcdOutsideVblank.Click += (s, e) => { InvertFlag(ref ConfigManager.Config.Debug.Debugger.GbBreakOnDisableLcdOutsideVblank); };
mnuGbBreakOnInvalidOamAccess.Click += (s, e) => { InvertFlag(ref ConfigManager.Config.Debug.Debugger.GbBreakOnInvalidOamAccess); };
mnuGbBreakOnInvalidOpCode.Click += (s, e) => { InvertFlag(ref ConfigManager.Config.Debug.Debugger.GbBreakOnInvalidOpCode); };
mnuGbBreakOnInvalidVramAccess.Click += (s, e) => { InvertFlag(ref ConfigManager.Config.Debug.Debugger.GbBreakOnInvalidVramAccess); };
mnuGbBreakOnNopLoad.Click += (s, e) => { InvertFlag(ref ConfigManager.Config.Debug.Debugger.GbBreakOnNopLoad); };
mnuGbBreakOnOamCorruption.Click += (s, e) => { InvertFlag(ref ConfigManager.Config.Debug.Debugger.GbBreakOnOamCorruption); };
mnuBringToFrontOnBreak.Click += (s, e) => { InvertFlag(ref ConfigManager.Config.Debug.Debugger.BringToFrontOnBreak); };
mnuBringToFrontOnPause.Click += (s, e) => { InvertFlag(ref ConfigManager.Config.Debug.Debugger.BringToFrontOnPause); };
mnuAutoResetCdl.Click += (s, e) => { InvertFlag(ref ConfigManager.Config.Debug.Debugger.AutoResetCdl); };
@ -389,6 +406,12 @@ namespace Mesen.GUI.Debugger
mnuBreakOnOpen.Checked = cfg.BreakOnOpen;
mnuBreakOnPowerCycleReset.Checked = cfg.BreakOnPowerCycleReset;
mnuBreakOnUnitRead.Checked = cfg.BreakOnUninitRead;
mnuGbBreakOnDisableLcdOutsideVblank.Checked = cfg.GbBreakOnDisableLcdOutsideVblank;
mnuGbBreakOnInvalidOamAccess.Checked = cfg.GbBreakOnInvalidOamAccess;
mnuGbBreakOnInvalidOpCode.Checked = cfg.GbBreakOnInvalidOpCode;
mnuGbBreakOnInvalidVramAccess.Checked = cfg.GbBreakOnInvalidVramAccess;
mnuGbBreakOnNopLoad.Checked = cfg.GbBreakOnNopLoad;
mnuGbBreakOnOamCorruption.Checked = cfg.GbBreakOnOamCorruption;
mnuBringToFrontOnBreak.Checked = cfg.BringToFrontOnBreak;
mnuBringToFrontOnPause.Checked = cfg.BringToFrontOnPause;
}

View file

@ -998,6 +998,12 @@
<Value ID="BreakOnWdm">WDM</Value>
<Value ID="BreakOnStp">STP</Value>
<Value ID="BreakOnUninitMemoryRead">Uninitialized memory read</Value>
<Value ID="GbInvalidOamAccess">Invalid OAM access</Value>
<Value ID="GbInvalidVramAccess">Invalid VRAM access</Value>
<Value ID="GbDisableLcdOutsideVblank">Disabled LCD outside vblank</Value>
<Value ID="GbInvalidOpCode">Invalid instruction</Value>
<Value ID="GbNopLoad">LD B,B (NOP)</Value>
<Value ID="GbOamCorruption">OAM corruption bug triggered</Value>
</Enum>
<Enum ID="MemoryOperationType">
<Value ID="Read">Read</Value>

View file

@ -64,6 +64,13 @@ namespace Mesen.GUI
AutoResetCdl = 0x4000,
GbBreakOnInvalidOamAccess = 0x10000,
GbBreakOnInvalidVramAccess = 0x20000,
GbBreakOnDisableLcdOutsideVblank = 0x40000,
GbBreakOnInvalidOpCode = 0x80000,
GbBreakOnNopLoad = 0x100000,
GbBreakOnOamCorruption = 0x200000,
GbDebuggerEnabled = 0x02000000,
Cx4DebuggerEnabled = 0x04000000,
NecDspDebuggerEnabled = 0x08000000,

View file

@ -597,7 +597,14 @@ namespace Mesen.GUI
BreakOnCop = 4,
BreakOnWdm = 5,
BreakOnStp = 6,
BreakOnUninitMemoryRead = 7
BreakOnUninitMemoryRead = 7,
GbInvalidOamAccess = 8,
GbInvalidVramAccess = 9,
GbDisableLcdOutsideVblank = 10,
GbInvalidOpCode = 11,
GbNopLoad = 12,
GbOamCorruption = 13,
}
public struct BreakEvent