diff --git a/Core/Console.cpp b/Core/Console.cpp index 3da132d..9280f85 100644 --- a/Core/Console.cpp +++ b/Core/Console.cpp @@ -57,6 +57,12 @@ void Console::Run() void Console::Stop() { _stopFlag = true; + + shared_ptr debugger = _debugger; + if(debugger) { + debugger->Run(); + } + _runLock.WaitForRelease(); _cpu.reset(); @@ -78,12 +84,12 @@ void Console::LoadRom(VirtualFile romFile, VirtualFile patchFile) _cpu.reset(new Cpu(_memoryManager)); - if(_debugger) { + //if(_debugger) { //Reset debugger if it was running before auto lock = _debuggerLock.AcquireSafe(); _debugger.reset(); GetDebugger(); - } + //} } } diff --git a/Core/Debugger.cpp b/Core/Debugger.cpp index 52875f7..bda262e 100644 --- a/Core/Debugger.cpp +++ b/Core/Debugger.cpp @@ -3,6 +3,7 @@ #include "Console.h" #include "Cpu.h" #include "Ppu.h" +#include "NotificationManager.h" #include "CpuTypes.h" #include "DisassemblyInfo.h" #include "TraceLogger.h" @@ -11,6 +12,7 @@ Debugger::Debugger(shared_ptr console) { + _console = console; _cpu = console->GetCpu(); _ppu = console->GetPpu(); _memoryManager = console->GetMemoryManager(); @@ -35,10 +37,18 @@ void Debugger::ProcessCpuRead(uint32_t addr, uint8_t value, MemoryOperationType _traceLogger->LogEffectiveAddress(_cpu->GetLastOperand()); _traceLogger->Log(debugState, disassemblyInfo); + if(value == 0x00) { + //break on BRK + _cpuStepCount = 1; + } + if(_cpuStepCount > 0) { _cpuStepCount--; - while(_cpuStepCount == 0) { - std::this_thread::sleep_for(std::chrono::duration(10)); + if(_cpuStepCount == 0) { + _console->GetNotificationManager()->SendNotification(ConsoleNotificationType::CodeBreak); + while(_cpuStepCount == 0) { + std::this_thread::sleep_for(std::chrono::duration(10)); + } } } } diff --git a/Core/Debugger.h b/Core/Debugger.h index f6e03bc..140b2b4 100644 --- a/Core/Debugger.h +++ b/Core/Debugger.h @@ -24,6 +24,7 @@ struct DebugState class Debugger { private: + shared_ptr _console; shared_ptr _cpu; shared_ptr _ppu; shared_ptr _memoryManager; diff --git a/UI/Debugger/DebugWindowManager.cs b/UI/Debugger/DebugWindowManager.cs new file mode 100644 index 0000000..6aed252 --- /dev/null +++ b/UI/Debugger/DebugWindowManager.cs @@ -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
_openedWindows = new HashSet(); + + public static List GetWindows() + { + return new List(_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 openedWindows = new List(_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 + } +} diff --git a/UI/Debugger/frmMemoryTools.cs b/UI/Debugger/frmMemoryTools.cs index 5a5d531..3c50cb8 100644 --- a/UI/Debugger/frmMemoryTools.cs +++ b/UI/Debugger/frmMemoryTools.cs @@ -78,7 +78,7 @@ namespace Mesen.GUI.Debugger InitMemoryTypeDropdown(true); _notifListener = new NotificationListener(); - _notifListener.OnNotification += _notifListener_OnNotification; + _notifListener.OnNotification += OnNotificationReceived; this.mnuShowCharacters.CheckedChanged += this.mnuShowCharacters_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) { case ConsoleNotificationType.CodeBreak: diff --git a/UI/Forms/frmMain.cs b/UI/Forms/frmMain.cs index dcb50ea..efdffa2 100644 --- a/UI/Forms/frmMain.cs +++ b/UI/Forms/frmMain.cs @@ -15,6 +15,8 @@ namespace Mesen.GUI.Forms { public partial class frmMain : BaseForm { + private NotificationListener _notifListener; + public frmMain(string[] args) { InitializeComponent(); @@ -27,26 +29,44 @@ namespace Mesen.GUI.Forms EmuApi.InitDll(); EmuApi.InitializeEmu(ConfigManager.HomeFolder, Handle, ctrlRenderer.Handle, false, false, false); + + _notifListener = new NotificationListener(); + _notifListener.OnNotification += OnNotificationReceived; } protected override void OnFormClosing(FormClosingEventArgs e) { base.OnFormClosing(e); + if(_notifListener != null) { + _notifListener.Dispose(); + _notifListener = null; + } + + DebugApi.ResumeExecution(); EmuApi.Stop(); 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) { - frmTraceLogger frm = new frmTraceLogger(); - frm.Show(); + DebugWindowManager.OpenDebugWindow(DebugWindow.TraceLogger); } private void mnuMemoryTools_Click(object sender, EventArgs e) { - frmMemoryTools frm = new frmMemoryTools(); - frm.Show(); + DebugWindowManager.OpenDebugWindow(DebugWindow.MemoryTools); } private void mnuStep_Click(object sender, EventArgs e) diff --git a/UI/UI.csproj b/UI/UI.csproj index afa8a39..0228770 100644 --- a/UI/UI.csproj +++ b/UI/UI.csproj @@ -371,6 +371,7 @@ + BaseConfigForm.cs