Debugger: Event Viewer - Added refresh speed options

This commit is contained in:
Sour 2019-11-20 19:12:08 -05:00
parent 85f4c1cc2f
commit 4a258e6788
6 changed files with 216 additions and 30 deletions

View file

@ -154,6 +154,8 @@ namespace Mesen.GUI.Config
public Point EventViewerLocation;
public Size EventViewerSize;
public bool EventViewerAutoRefresh = true;
public RefreshSpeed EventViewerAutoRefreshSpeed = RefreshSpeed.Normal;
public bool EventViewerRefreshOnBreak = true;
public bool EventViewerShowPpuWrite2000 = true;
public bool EventViewerShowPpuWrite2001 = true;

View file

@ -19,6 +19,7 @@ namespace Mesen.GUI.Debugger.Controls
public int Scanline { get { return _scanline; } }
public int Cycle { get { return _cycle; } }
public int ViewerId { get { return _ppuViewerId; } }
public ctrlScanlineCycleSelect()
{

View file

@ -0,0 +1,92 @@
using Mesen.GUI.Config;
using Mesen.GUI.Debugger.Controls;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using static Mesen.GUI.InteropEmu;
namespace Mesen.GUI.Debugger
{
public class WindowRefreshManager : IDisposable
{
private IRefresh _window;
private NotificationListener _notifListener;
private Stopwatch _timer;
private long _lastUpdate = 0;
private long _minDelay = 0;
public bool AutoRefresh { get; set; }
public RefreshSpeed AutoRefreshSpeed { get; set; }
public WindowRefreshManager(IRefresh window)
{
_window = window;
_notifListener = new NotificationListener(ConfigManager.Config.DebugInfo.DebugConsoleId);
_notifListener.OnNotification += OnNotificationReceived;
_timer = Stopwatch.StartNew();
}
public void Dispose()
{
_notifListener.Dispose();
}
private void RefreshContent()
{
_lastUpdate = _timer.ElapsedTicks;
_window.RefreshData();
((Form)_window).BeginInvoke((Action)(() => {
_window.RefreshViewer();
//Limit FPS to 3x time it takes for a single update (rough estimate), and cap based on requested fps.
int divider;
switch(this.AutoRefreshSpeed) {
default:
case RefreshSpeed.Low: divider = 20; break;
case RefreshSpeed.Normal: divider = 40; break;
case RefreshSpeed.High: divider = 80; break;
}
_minDelay = Math.Max(Stopwatch.Frequency / divider, (long)((_timer.ElapsedTicks - _lastUpdate) * 2));
}));
}
private void OnNotificationReceived(NotificationEventArgs e)
{
switch(e.NotificationType) {
case ConsoleNotificationType.CodeBreak:
RefreshContent();
break;
case ConsoleNotificationType.EventViewerDisplayFrame:
if(_window.ScanlineCycleSelect == null && this.AutoRefresh && (_timer.ElapsedTicks - _lastUpdate) > _minDelay) {
RefreshContent();
}
break;
case ConsoleNotificationType.PpuViewerDisplayFrame:
if(_window.ScanlineCycleSelect != null && this.AutoRefresh && e.Parameter.ToInt32() == _window.ScanlineCycleSelect.ViewerId && (_timer.ElapsedTicks - _lastUpdate) > _minDelay) {
RefreshContent();
}
break;
case ConsoleNotificationType.GameLoaded:
//Configuration is lost when debugger is restarted (when switching game or power cycling)
_window.ScanlineCycleSelect?.RefreshSettings();
break;
}
}
}
public interface IRefresh
{
void RefreshData();
void RefreshViewer();
ctrlScanlineCycleSelect ScanlineCycleSelect { get; }
}
}

View file

@ -16,9 +16,6 @@
if(disposing && (components != null)) {
components.Dispose();
}
if(this._notifListener != null) {
this._notifListener.Dispose();
}
base.Dispose(disposing);
}
@ -81,6 +78,13 @@
this.fileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.mnuClose = new System.Windows.Forms.ToolStripMenuItem();
this.viewToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.mnuRefresh = new System.Windows.Forms.ToolStripMenuItem();
this.mnuAutoRefreshSpeed = new System.Windows.Forms.ToolStripMenuItem();
this.mnuAutoRefreshLow = new System.Windows.Forms.ToolStripMenuItem();
this.mnuAutoRefreshNormal = new System.Windows.Forms.ToolStripMenuItem();
this.mnuAutoRefreshHigh = new System.Windows.Forms.ToolStripMenuItem();
this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator();
this.mnuAutoRefresh = new System.Windows.Forms.ToolStripMenuItem();
this.mnuRefreshOnBreak = new System.Windows.Forms.ToolStripMenuItem();
this.toolStripMenuItem1 = new System.Windows.Forms.ToolStripSeparator();
this.mnuResetColors = new System.Windows.Forms.ToolStripMenuItem();
@ -730,6 +734,10 @@
// viewToolStripMenuItem
//
this.viewToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.mnuRefresh,
this.mnuAutoRefreshSpeed,
this.toolStripSeparator1,
this.mnuAutoRefresh,
this.mnuRefreshOnBreak,
this.toolStripMenuItem1,
this.mnuResetColors,
@ -740,6 +748,58 @@
this.viewToolStripMenuItem.Size = new System.Drawing.Size(44, 20);
this.viewToolStripMenuItem.Text = "View";
//
// mnuRefresh
//
this.mnuRefresh.Image = global::Mesen.GUI.Properties.Resources.Reset;
this.mnuRefresh.Name = "mnuRefresh";
this.mnuRefresh.Size = new System.Drawing.Size(198, 22);
this.mnuRefresh.Text = "Refresh";
this.mnuRefresh.Click += new System.EventHandler(this.mnuRefresh_Click);
//
// mnuAutoRefreshSpeed
//
this.mnuAutoRefreshSpeed.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.mnuAutoRefreshLow,
this.mnuAutoRefreshNormal,
this.mnuAutoRefreshHigh});
this.mnuAutoRefreshSpeed.Image = global::Mesen.GUI.Properties.Resources.Speed;
this.mnuAutoRefreshSpeed.Name = "mnuAutoRefreshSpeed";
this.mnuAutoRefreshSpeed.Size = new System.Drawing.Size(198, 22);
this.mnuAutoRefreshSpeed.Text = "Auto-refresh Speed";
//
// mnuAutoRefreshLow
//
this.mnuAutoRefreshLow.Name = "mnuAutoRefreshLow";
this.mnuAutoRefreshLow.Size = new System.Drawing.Size(159, 22);
this.mnuAutoRefreshLow.Text = "Low (15 FPS)";
//
// mnuAutoRefreshNormal
//
this.mnuAutoRefreshNormal.Name = "mnuAutoRefreshNormal";
this.mnuAutoRefreshNormal.Size = new System.Drawing.Size(159, 22);
this.mnuAutoRefreshNormal.Text = "Normal (30 FPS)";
//
// mnuAutoRefreshHigh
//
this.mnuAutoRefreshHigh.Name = "mnuAutoRefreshHigh";
this.mnuAutoRefreshHigh.Size = new System.Drawing.Size(159, 22);
this.mnuAutoRefreshHigh.Text = "High (60 FPS)";
//
// toolStripSeparator1
//
this.toolStripSeparator1.Name = "toolStripSeparator1";
this.toolStripSeparator1.Size = new System.Drawing.Size(195, 6);
//
// mnuAutoRefresh
//
this.mnuAutoRefresh.Checked = true;
this.mnuAutoRefresh.CheckOnClick = true;
this.mnuAutoRefresh.CheckState = System.Windows.Forms.CheckState.Checked;
this.mnuAutoRefresh.Name = "mnuAutoRefresh";
this.mnuAutoRefresh.Size = new System.Drawing.Size(198, 22);
this.mnuAutoRefresh.Text = "Auto-refresh";
this.mnuAutoRefresh.CheckedChanged += new System.EventHandler(this.mnuAutoRefresh_CheckedChanged);
//
// mnuRefreshOnBreak
//
this.mnuRefreshOnBreak.CheckOnClick = true;
@ -874,5 +934,12 @@
private System.Windows.Forms.ToolStripSeparator toolStripMenuItem2;
private System.Windows.Forms.ToolStripMenuItem mnuZoomIn;
private System.Windows.Forms.ToolStripMenuItem mnuZoomOut;
private System.Windows.Forms.ToolStripMenuItem mnuRefresh;
private System.Windows.Forms.ToolStripMenuItem mnuAutoRefreshSpeed;
private System.Windows.Forms.ToolStripMenuItem mnuAutoRefreshLow;
private System.Windows.Forms.ToolStripMenuItem mnuAutoRefreshNormal;
private System.Windows.Forms.ToolStripMenuItem mnuAutoRefreshHigh;
private System.Windows.Forms.ToolStripSeparator toolStripSeparator1;
private System.Windows.Forms.ToolStripMenuItem mnuAutoRefresh;
}
}

View file

@ -1,4 +1,5 @@
using Mesen.GUI.Config;
using Mesen.GUI.Debugger.Controls;
using Mesen.GUI.Forms;
using System;
using System.Collections.Generic;
@ -12,13 +13,14 @@ using System.Windows.Forms;
namespace Mesen.GUI.Debugger
{
public partial class frmEventViewer : BaseForm
public partial class frmEventViewer : BaseForm, IRefresh
{
private DateTime _lastUpdate = DateTime.MinValue;
private WindowRefreshManager _refreshManager;
private InteropEmu.NotificationListener _notifListener;
private EntityBinder _binder = new EntityBinder();
private bool _inListViewTab = false;
private bool _refreshing = false;
public ctrlScanlineCycleSelect ScanlineCycleSelect => null;
public frmEventViewer()
{
@ -77,12 +79,6 @@ namespace Mesen.GUI.Debugger
_binder.AddBinding(nameof(DebugInfo.EventViewerShowPreviousFrameEvents), chkShowPreviousFrameEvents);
_binder.AddBinding(nameof(DebugInfo.EventViewerShowNtscBorders), chkShowNtscBorders);
this.GetData();
_binder.UpdateUI();
this.RefreshViewer();
DebugWorkspaceManager.GetWorkspace();
RestoreLocation(ConfigManager.Config.DebugInfo.EventViewerLocation, ConfigManager.Config.DebugInfo.EventViewerSize);
@ -90,12 +86,27 @@ namespace Mesen.GUI.Debugger
this._notifListener = new InteropEmu.NotificationListener(ConfigManager.Config.DebugInfo.DebugConsoleId);
this._notifListener.OnNotification += this._notifListener_OnNotification;
DebugInfo cfg = ConfigManager.Config.DebugInfo;
_refreshManager = new WindowRefreshManager(this);
_refreshManager.AutoRefresh = cfg.EventViewerAutoRefresh;
_refreshManager.AutoRefreshSpeed = cfg.EventViewerAutoRefreshSpeed;
mnuAutoRefresh.Checked = cfg.EventViewerAutoRefresh;
mnuAutoRefreshLow.Click += (s, evt) => _refreshManager.AutoRefreshSpeed = RefreshSpeed.Low;
mnuAutoRefreshNormal.Click += (s, evt) => _refreshManager.AutoRefreshSpeed = RefreshSpeed.Normal;
mnuAutoRefreshHigh.Click += (s, evt) => _refreshManager.AutoRefreshSpeed = RefreshSpeed.High;
mnuAutoRefreshSpeed.DropDownOpening += (s, evt) => UpdateRefreshSpeedMenu();
this.RefreshData();
_binder.UpdateUI();
this.RefreshViewer();
InitShortcuts();
}
}
private void InitShortcuts()
{
mnuRefresh.InitShortcut(this, nameof(DebuggerShortcutsConfig.Refresh));
mnuZoomIn.InitShortcut(this, nameof(DebuggerShortcutsConfig.ZoomIn));
mnuZoomOut.InitShortcut(this, nameof(DebuggerShortcutsConfig.ZoomOut));
@ -108,10 +119,15 @@ namespace Mesen.GUI.Debugger
base.OnFormClosing(e);
this._notifListener.OnNotification -= this._notifListener_OnNotification;
_notifListener?.Dispose();
_refreshManager?.Dispose();
_binder.UpdateObject();
ConfigManager.Config.DebugInfo.EventViewerLocation = this.WindowState != FormWindowState.Normal ? this.RestoreBounds.Location : this.Location;
ConfigManager.Config.DebugInfo.EventViewerSize = this.WindowState != FormWindowState.Normal ? this.RestoreBounds.Size : this.Size;
DebugInfo cfg = ConfigManager.Config.DebugInfo;
cfg.EventViewerAutoRefresh = _refreshManager.AutoRefresh;
cfg.EventViewerAutoRefreshSpeed = _refreshManager.AutoRefreshSpeed;
cfg.EventViewerLocation = this.WindowState != FormWindowState.Normal ? this.RestoreBounds.Location : this.Location;
cfg.EventViewerSize = this.WindowState != FormWindowState.Normal ? this.RestoreBounds.Size : this.Size;
ConfigManager.ApplyChanges();
}
@ -121,23 +137,14 @@ namespace Mesen.GUI.Debugger
case InteropEmu.ConsoleNotificationType.CodeBreak:
case InteropEmu.ConsoleNotificationType.GamePaused:
if(ConfigManager.Config.DebugInfo.EventViewerRefreshOnBreak) {
this.GetData();
this.RefreshData();
this.BeginInvoke((MethodInvoker)(() => this.RefreshViewer()));
}
break;
case InteropEmu.ConsoleNotificationType.EventViewerDisplayFrame:
if(!_refreshing && (DateTime.Now - _lastUpdate).Milliseconds >= 32) {
//Update at ~30 fps at most
this.GetData();
this.BeginInvoke((MethodInvoker)(() => this.RefreshViewer()));
_lastUpdate = DateTime.Now;
}
break;
}
}
private void GetData()
public void RefreshData()
{
if(_inListViewTab) {
ctrlEventViewerListView.GetData();
@ -146,16 +153,14 @@ namespace Mesen.GUI.Debugger
}
}
private void RefreshViewer()
public void RefreshViewer()
{
if(_binder.Updating) {
return;
}
_refreshing = true;
_binder.UpdateObject();
ctrlEventViewerPpuView.RefreshViewer();
_refreshing = false;
}
private void mnuClose_Click(object sender, EventArgs e)
@ -166,7 +171,7 @@ namespace Mesen.GUI.Debugger
private void tabMain_SelectedIndexChanged(object sender, EventArgs e)
{
_inListViewTab = tabMain.SelectedTab == tpgListView;
GetData();
RefreshData();
}
private void mnuRefreshOnBreak_Click(object sender, EventArgs e)
@ -180,7 +185,7 @@ namespace Mesen.GUI.Debugger
ConfigManager.Config.DebugInfo.EventViewerShowPreviousFrameEvents = chkShowPreviousFrameEvents.Checked;
ConfigManager.ApplyChanges();
if(InteropEmu.DebugIsExecutionStopped()) {
this.GetData();
this.RefreshData();
this.RefreshViewer();
}
}
@ -218,5 +223,23 @@ namespace Mesen.GUI.Debugger
picBreakpoint.BackColor = ColorTranslator.FromHtml("#1898E4");
picDmcDmaRead.BackColor = ColorTranslator.FromHtml("#A9FEFC");
}
private void mnuRefresh_Click(object sender, EventArgs e)
{
RefreshData();
RefreshViewer();
}
private void mnuAutoRefresh_CheckedChanged(object sender, EventArgs e)
{
_refreshManager.AutoRefresh = mnuAutoRefresh.Checked;
}
private void UpdateRefreshSpeedMenu()
{
mnuAutoRefreshLow.Checked = _refreshManager.AutoRefreshSpeed == RefreshSpeed.Low;
mnuAutoRefreshNormal.Checked = _refreshManager.AutoRefreshSpeed == RefreshSpeed.Normal;
mnuAutoRefreshHigh.Checked = _refreshManager.AutoRefreshSpeed == RefreshSpeed.High;
}
}
}

View file

@ -893,6 +893,7 @@
<SubType>Form</SubType>
</Compile>
<Compile Include="Debugger\WatchManager.cs" />
<Compile Include="Debugger\WindowRefreshManager.cs" />
<Compile Include="Forms\BaseConfigForm.Designer.cs">
<DependentUpon>BaseConfigForm.cs</DependentUpon>
</Compile>