Debugger: Break and open trace logger on BRK instruction
This commit is contained in:
parent
fa36f36314
commit
4bea25ecc7
7 changed files with 165 additions and 10 deletions
|
@ -57,6 +57,12 @@ void Console::Run()
|
||||||
void Console::Stop()
|
void Console::Stop()
|
||||||
{
|
{
|
||||||
_stopFlag = true;
|
_stopFlag = true;
|
||||||
|
|
||||||
|
shared_ptr<Debugger> debugger = _debugger;
|
||||||
|
if(debugger) {
|
||||||
|
debugger->Run();
|
||||||
|
}
|
||||||
|
|
||||||
_runLock.WaitForRelease();
|
_runLock.WaitForRelease();
|
||||||
|
|
||||||
_cpu.reset();
|
_cpu.reset();
|
||||||
|
@ -78,12 +84,12 @@ void Console::LoadRom(VirtualFile romFile, VirtualFile patchFile)
|
||||||
|
|
||||||
_cpu.reset(new Cpu(_memoryManager));
|
_cpu.reset(new Cpu(_memoryManager));
|
||||||
|
|
||||||
if(_debugger) {
|
//if(_debugger) {
|
||||||
//Reset debugger if it was running before
|
//Reset debugger if it was running before
|
||||||
auto lock = _debuggerLock.AcquireSafe();
|
auto lock = _debuggerLock.AcquireSafe();
|
||||||
_debugger.reset();
|
_debugger.reset();
|
||||||
GetDebugger();
|
GetDebugger();
|
||||||
}
|
//}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include "Console.h"
|
#include "Console.h"
|
||||||
#include "Cpu.h"
|
#include "Cpu.h"
|
||||||
#include "Ppu.h"
|
#include "Ppu.h"
|
||||||
|
#include "NotificationManager.h"
|
||||||
#include "CpuTypes.h"
|
#include "CpuTypes.h"
|
||||||
#include "DisassemblyInfo.h"
|
#include "DisassemblyInfo.h"
|
||||||
#include "TraceLogger.h"
|
#include "TraceLogger.h"
|
||||||
|
@ -11,6 +12,7 @@
|
||||||
|
|
||||||
Debugger::Debugger(shared_ptr<Console> console)
|
Debugger::Debugger(shared_ptr<Console> console)
|
||||||
{
|
{
|
||||||
|
_console = console;
|
||||||
_cpu = console->GetCpu();
|
_cpu = console->GetCpu();
|
||||||
_ppu = console->GetPpu();
|
_ppu = console->GetPpu();
|
||||||
_memoryManager = console->GetMemoryManager();
|
_memoryManager = console->GetMemoryManager();
|
||||||
|
@ -35,10 +37,18 @@ void Debugger::ProcessCpuRead(uint32_t addr, uint8_t value, MemoryOperationType
|
||||||
_traceLogger->LogEffectiveAddress(_cpu->GetLastOperand());
|
_traceLogger->LogEffectiveAddress(_cpu->GetLastOperand());
|
||||||
_traceLogger->Log(debugState, disassemblyInfo);
|
_traceLogger->Log(debugState, disassemblyInfo);
|
||||||
|
|
||||||
|
if(value == 0x00) {
|
||||||
|
//break on BRK
|
||||||
|
_cpuStepCount = 1;
|
||||||
|
}
|
||||||
|
|
||||||
if(_cpuStepCount > 0) {
|
if(_cpuStepCount > 0) {
|
||||||
_cpuStepCount--;
|
_cpuStepCount--;
|
||||||
while(_cpuStepCount == 0) {
|
if(_cpuStepCount == 0) {
|
||||||
std::this_thread::sleep_for(std::chrono::duration<int, std::milli>(10));
|
_console->GetNotificationManager()->SendNotification(ConsoleNotificationType::CodeBreak);
|
||||||
|
while(_cpuStepCount == 0) {
|
||||||
|
std::this_thread::sleep_for(std::chrono::duration<int, std::milli>(10));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,7 @@ struct DebugState
|
||||||
class Debugger
|
class Debugger
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
shared_ptr<Console> _console;
|
||||||
shared_ptr<Cpu> _cpu;
|
shared_ptr<Cpu> _cpu;
|
||||||
shared_ptr<Ppu> _ppu;
|
shared_ptr<Ppu> _ppu;
|
||||||
shared_ptr<MemoryManager> _memoryManager;
|
shared_ptr<MemoryManager> _memoryManager;
|
||||||
|
|
117
UI/Debugger/DebugWindowManager.cs
Normal file
117
UI/Debugger/DebugWindowManager.cs
Normal file
|
@ -0,0 +1,117 @@
|
||||||
|
using Mesen.GUI.Forms;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
|
||||||
|
namespace Mesen.GUI.Debugger
|
||||||
|
{
|
||||||
|
public class DebugWindowManager
|
||||||
|
{
|
||||||
|
private static HashSet<Form> _openedWindows = new HashSet<Form>();
|
||||||
|
|
||||||
|
public static List<Form> GetWindows()
|
||||||
|
{
|
||||||
|
return new List<Form>(_openedWindows);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Form OpenDebugWindow(DebugWindow window)
|
||||||
|
{
|
||||||
|
Form existingWindow = GetExistingSingleInstanceWindow(window);
|
||||||
|
if(existingWindow != null) {
|
||||||
|
existingWindow.BringToFront();
|
||||||
|
if(existingWindow.WindowState == FormWindowState.Minimized) {
|
||||||
|
//Unminimize window if it was minimized
|
||||||
|
existingWindow.WindowState = FormWindowState.Normal;
|
||||||
|
}
|
||||||
|
existingWindow.Focus();
|
||||||
|
return existingWindow;
|
||||||
|
} else {
|
||||||
|
BaseForm frm = null;
|
||||||
|
switch(window) {
|
||||||
|
case DebugWindow.TraceLogger: frm = new frmTraceLogger(); frm.Icon = Properties.Resources.LogWindow; break;
|
||||||
|
case DebugWindow.MemoryTools: frm = new frmMemoryTools(); frm.Icon = Properties.Resources.CheatCode; break;
|
||||||
|
}
|
||||||
|
_openedWindows.Add(frm);
|
||||||
|
frm.FormClosed += Debugger_FormClosed;
|
||||||
|
frm.Show();
|
||||||
|
return frm;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static frmMemoryTools OpenMemoryViewer()
|
||||||
|
{
|
||||||
|
frmMemoryTools frm = GetMemoryViewer();
|
||||||
|
if(frm == null) {
|
||||||
|
frm = new frmMemoryTools();
|
||||||
|
frm.Icon = Properties.Resources.CheatCode;
|
||||||
|
frm.FormClosed += Debugger_FormClosed;
|
||||||
|
_openedWindows.Add(frm);
|
||||||
|
} else {
|
||||||
|
if(frm.WindowState == FormWindowState.Minimized) {
|
||||||
|
//Unminimize window if it was minimized
|
||||||
|
frm.WindowState = FormWindowState.Normal;
|
||||||
|
}
|
||||||
|
frm.BringToFront();
|
||||||
|
}
|
||||||
|
frm.Show();
|
||||||
|
return frm;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static frmMemoryTools GetMemoryViewer()
|
||||||
|
{
|
||||||
|
return _openedWindows.ToList().Find((form) => form.GetType() == typeof(frmMemoryTools)) as frmMemoryTools;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool HasOpenedWindow
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return _openedWindows.Count > 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void CloseAll()
|
||||||
|
{
|
||||||
|
List<Form> openedWindows = new List<Form>(_openedWindows);
|
||||||
|
foreach(Form frm in openedWindows) {
|
||||||
|
frm.Close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Form GetExistingSingleInstanceWindow(DebugWindow window)
|
||||||
|
{
|
||||||
|
//Only one of each of these windows can be opened at once, check if one is already opened
|
||||||
|
switch(window) {
|
||||||
|
case DebugWindow.TraceLogger: return _openedWindows.ToList().Find((form) => form.GetType() == typeof(frmTraceLogger));
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void CleanupDebugger()
|
||||||
|
{
|
||||||
|
if(_openedWindows.Count == 0) {
|
||||||
|
//All windows have been closed, disable debugger
|
||||||
|
//TODO
|
||||||
|
//DebugWorkspaceManager.SaveWorkspace();
|
||||||
|
//DebugWorkspaceManager.Clear();
|
||||||
|
//DebugApi.ReleaseDebugger();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void Debugger_FormClosed(object sender, FormClosedEventArgs e)
|
||||||
|
{
|
||||||
|
_openedWindows.Remove((Form)sender);
|
||||||
|
CleanupDebugger();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum DebugWindow
|
||||||
|
{
|
||||||
|
MemoryTools,
|
||||||
|
TraceLogger
|
||||||
|
}
|
||||||
|
}
|
|
@ -78,7 +78,7 @@ namespace Mesen.GUI.Debugger
|
||||||
InitMemoryTypeDropdown(true);
|
InitMemoryTypeDropdown(true);
|
||||||
|
|
||||||
_notifListener = new NotificationListener();
|
_notifListener = new NotificationListener();
|
||||||
_notifListener.OnNotification += _notifListener_OnNotification;
|
_notifListener.OnNotification += OnNotificationReceived;
|
||||||
|
|
||||||
this.mnuShowCharacters.CheckedChanged += this.mnuShowCharacters_CheckedChanged;
|
this.mnuShowCharacters.CheckedChanged += this.mnuShowCharacters_CheckedChanged;
|
||||||
this.mnuIgnoreRedundantWrites.CheckedChanged += mnuIgnoreRedundantWrites_CheckedChanged;
|
this.mnuIgnoreRedundantWrites.CheckedChanged += mnuIgnoreRedundantWrites_CheckedChanged;
|
||||||
|
@ -230,7 +230,7 @@ namespace Mesen.GUI.Debugger
|
||||||
}
|
}
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
private void _notifListener_OnNotification(NotificationEventArgs e)
|
private void OnNotificationReceived(NotificationEventArgs e)
|
||||||
{
|
{
|
||||||
switch(e.NotificationType) {
|
switch(e.NotificationType) {
|
||||||
case ConsoleNotificationType.CodeBreak:
|
case ConsoleNotificationType.CodeBreak:
|
||||||
|
|
|
@ -15,6 +15,8 @@ namespace Mesen.GUI.Forms
|
||||||
{
|
{
|
||||||
public partial class frmMain : BaseForm
|
public partial class frmMain : BaseForm
|
||||||
{
|
{
|
||||||
|
private NotificationListener _notifListener;
|
||||||
|
|
||||||
public frmMain(string[] args)
|
public frmMain(string[] args)
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
@ -27,26 +29,44 @@ namespace Mesen.GUI.Forms
|
||||||
|
|
||||||
EmuApi.InitDll();
|
EmuApi.InitDll();
|
||||||
EmuApi.InitializeEmu(ConfigManager.HomeFolder, Handle, ctrlRenderer.Handle, false, false, false);
|
EmuApi.InitializeEmu(ConfigManager.HomeFolder, Handle, ctrlRenderer.Handle, false, false, false);
|
||||||
|
|
||||||
|
_notifListener = new NotificationListener();
|
||||||
|
_notifListener.OnNotification += OnNotificationReceived;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnFormClosing(FormClosingEventArgs e)
|
protected override void OnFormClosing(FormClosingEventArgs e)
|
||||||
{
|
{
|
||||||
base.OnFormClosing(e);
|
base.OnFormClosing(e);
|
||||||
|
|
||||||
|
if(_notifListener != null) {
|
||||||
|
_notifListener.Dispose();
|
||||||
|
_notifListener = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
DebugApi.ResumeExecution();
|
||||||
EmuApi.Stop();
|
EmuApi.Stop();
|
||||||
EmuApi.Release();
|
EmuApi.Release();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void OnNotificationReceived(NotificationEventArgs e)
|
||||||
|
{
|
||||||
|
switch(e.NotificationType) {
|
||||||
|
case ConsoleNotificationType.CodeBreak:
|
||||||
|
this.BeginInvoke((Action)(() => {
|
||||||
|
DebugWindowManager.OpenDebugWindow(DebugWindow.TraceLogger);
|
||||||
|
}));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void mnuTraceLogger_Click(object sender, EventArgs e)
|
private void mnuTraceLogger_Click(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
frmTraceLogger frm = new frmTraceLogger();
|
DebugWindowManager.OpenDebugWindow(DebugWindow.TraceLogger);
|
||||||
frm.Show();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void mnuMemoryTools_Click(object sender, EventArgs e)
|
private void mnuMemoryTools_Click(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
frmMemoryTools frm = new frmMemoryTools();
|
DebugWindowManager.OpenDebugWindow(DebugWindow.MemoryTools);
|
||||||
frm.Show();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void mnuStep_Click(object sender, EventArgs e)
|
private void mnuStep_Click(object sender, EventArgs e)
|
||||||
|
|
|
@ -371,6 +371,7 @@
|
||||||
<Compile Include="Debugger\HexBox\TblByteCharConverter.cs" />
|
<Compile Include="Debugger\HexBox\TblByteCharConverter.cs" />
|
||||||
<Compile Include="Debugger\HexBox\Util.cs" />
|
<Compile Include="Debugger\HexBox\Util.cs" />
|
||||||
<Compile Include="Debugger\TblLoader.cs" />
|
<Compile Include="Debugger\TblLoader.cs" />
|
||||||
|
<Compile Include="Debugger\DebugWindowManager.cs" />
|
||||||
<Compile Include="Forms\BaseConfigForm.Designer.cs">
|
<Compile Include="Forms\BaseConfigForm.Designer.cs">
|
||||||
<DependentUpon>BaseConfigForm.cs</DependentUpon>
|
<DependentUpon>BaseConfigForm.cs</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
|
Loading…
Add table
Reference in a new issue