mirror of
https://github.com/SourMesen/Mesen2.git
synced 2025-04-02 10:21:44 -04:00
Debugger: Tilemap viewer - Added view in memory viewer option
+ Fixed right-click working out-of-bounds due to scroll overlay + Give hex viewer focus when opening the window
This commit is contained in:
parent
d06f132b7b
commit
ea9c8fad96
12 changed files with 86 additions and 22 deletions
|
@ -118,7 +118,7 @@ namespace Mesen.Debugger.Controls
|
|||
private double RowWidth => LetterSize.Width * (3 * BytesPerRow - 1);
|
||||
private double StringViewMargin => 20;
|
||||
private double ColumnHeaderHeight => LetterSize.Height + 5;
|
||||
private int VisibleRows => (int)((Bounds.Height - ColumnHeaderHeight) / RowHeight) - 1;
|
||||
private int VisibleRows => Math.Max(0, (int)((Bounds.Height - ColumnHeaderHeight) / RowHeight) - 1);
|
||||
private string HexFormat => "X2";
|
||||
|
||||
private int _cursorPosition = 0;
|
||||
|
@ -136,11 +136,20 @@ namespace Mesen.Debugger.Controls
|
|||
SelectedRowColumnColorProperty, HeaderBackgroundProperty, HeaderForegroundProperty, HeaderHighlightProperty,
|
||||
IsFocusedProperty
|
||||
);
|
||||
|
||||
FontFamilyProperty.Changed.AddClassHandler<HexEditor>((x, e) => {
|
||||
x.InitFontAndLetterSize();
|
||||
});
|
||||
|
||||
FontSizeProperty.Changed.AddClassHandler<HexEditor>((x, e) => {
|
||||
x.InitFontAndLetterSize();
|
||||
});
|
||||
}
|
||||
|
||||
public HexEditor()
|
||||
{
|
||||
Focusable = true;
|
||||
InitFontAndLetterSize();
|
||||
}
|
||||
|
||||
protected override void OnPointerEnter(PointerEventArgs e)
|
||||
|
@ -178,7 +187,7 @@ namespace Mesen.Debugger.Controls
|
|||
}
|
||||
}
|
||||
|
||||
private void SetCursorPosition(int pos, bool keepNibble = false)
|
||||
public void SetCursorPosition(int pos, bool keepNibble = false, bool scrollToTop = false)
|
||||
{
|
||||
this.SelectionStart = Math.Min(Math.Max(0, pos), this.DataProvider.Length - 1);
|
||||
this.SelectionLength = 0;
|
||||
|
@ -188,7 +197,7 @@ namespace Mesen.Debugger.Controls
|
|||
_lastNibble = false;
|
||||
}
|
||||
|
||||
ScrollIntoView(_cursorPosition);
|
||||
ScrollIntoView(_cursorPosition, scrollToTop);
|
||||
}
|
||||
|
||||
private void ChangeSelectionLength(int offset)
|
||||
|
@ -426,14 +435,14 @@ namespace Mesen.Debugger.Controls
|
|||
return null;
|
||||
}
|
||||
|
||||
private void ScrollIntoView(int byteIndex)
|
||||
private void ScrollIntoView(int byteIndex, bool scrollToTop = false)
|
||||
{
|
||||
int topRow = TopRow;
|
||||
if(byteIndex < 0) {
|
||||
topRow = 0;
|
||||
} else if(byteIndex >= DataProvider.Length) {
|
||||
topRow = (DataProvider.Length / BytesPerRow) - VisibleRows;
|
||||
} else if(byteIndex < TopRow * BytesPerRow) {
|
||||
} else if(byteIndex < TopRow * BytesPerRow || scrollToTop) {
|
||||
//scroll up
|
||||
topRow = byteIndex / BytesPerRow;
|
||||
} else if(byteIndex > (TopRow + VisibleRows) * BytesPerRow) {
|
||||
|
@ -544,9 +553,6 @@ namespace Mesen.Debugger.Controls
|
|||
|
||||
context.DrawRectangle(ColorHelper.GetBrush(Colors.White), null, new Rect(Bounds.Size));
|
||||
|
||||
//Init font and letter size
|
||||
InitFontAndLetterSize();
|
||||
|
||||
//Draw column headers
|
||||
DrawColumnHeaders(context);
|
||||
using var columnHeaderTranslation = context.PushPostTransform(Matrix.CreateTranslation(0, this.ColumnHeaderHeight));
|
||||
|
|
|
@ -159,6 +159,9 @@ namespace Mesen.Debugger.Controls
|
|||
public PictureViewer()
|
||||
{
|
||||
Focusable = true;
|
||||
VerticalAlignment = VerticalAlignment.Top;
|
||||
HorizontalAlignment = HorizontalAlignment.Left;
|
||||
ClipToBounds = true;
|
||||
}
|
||||
|
||||
private void OnSourceInvalidated(object? sender, EventArgs e)
|
||||
|
|
|
@ -289,5 +289,8 @@ namespace Mesen.Debugger.Utilities
|
|||
|
||||
[IconFile("VerticalLayout")]
|
||||
ViewInTileViewer,
|
||||
|
||||
[IconFile("CheatCode")]
|
||||
ViewInMemoryViewer,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ namespace Mesen.Debugger.Utilities
|
|||
private static ConcurrentDictionary<Window, bool> _openedWindows = new();
|
||||
private static object _windowNotifLock = new();
|
||||
|
||||
public static void OpenDebugWindow<T>(Func<T> createWindow) where T : Window
|
||||
public static T OpenDebugWindow<T>(Func<T> createWindow) where T : Window
|
||||
{
|
||||
if(Interlocked.Increment(ref _debugWindowCounter) == 1) {
|
||||
//Opened a debug window and nothing else was opened, load the saved workspace
|
||||
|
@ -29,6 +29,17 @@ namespace Mesen.Debugger.Utilities
|
|||
};
|
||||
_openedWindows.TryAdd(wnd, true);
|
||||
wnd.Show();
|
||||
return wnd;
|
||||
}
|
||||
|
||||
public static T GetOrOpenDebugWindow<T>(Func<T> createWindow) where T : Window
|
||||
{
|
||||
foreach(Window wnd in _openedWindows.Keys) {
|
||||
if(wnd is T) {
|
||||
return (T)wnd;
|
||||
}
|
||||
}
|
||||
return OpenDebugWindow<T>(createWindow);
|
||||
}
|
||||
|
||||
private static void CloseDebugWindow(Window wnd)
|
||||
|
|
|
@ -7,6 +7,7 @@ using Avalonia.Threading;
|
|||
using Mesen.Config;
|
||||
using Mesen.Debugger.Controls;
|
||||
using Mesen.Debugger.Utilities;
|
||||
using Mesen.Debugger.Windows;
|
||||
using Mesen.Interop;
|
||||
using Mesen.Utilities;
|
||||
using Mesen.ViewModels;
|
||||
|
@ -110,6 +111,17 @@ namespace Mesen.Debugger.ViewModels
|
|||
});
|
||||
|
||||
DebugShortcutManager.CreateContextMenu(picViewer, new List<object>() {
|
||||
new ContextMenuAction() {
|
||||
ActionType = ActionType.ViewInMemoryViewer,
|
||||
OnClick = () => {
|
||||
DebugTilemapTileInfo? tile = GetSelectedTileInfo();
|
||||
if(tile != null && tile.Value.TileMapAddress >= 0) {
|
||||
MemoryToolsWindow wnd = DebugWindowManager.GetOrOpenDebugWindow(() => new MemoryToolsWindow(new MemoryToolsViewModel()));
|
||||
wnd.SetCursorPosition(CpuType.GetVramMemoryType(), tile.Value.TileMapAddress);
|
||||
wnd.Activate();
|
||||
}
|
||||
}
|
||||
},
|
||||
new ContextMenuAction() {
|
||||
ActionType = ActionType.ViewInTileViewer,
|
||||
IsEnabled = () => false,
|
||||
|
@ -168,6 +180,16 @@ namespace Mesen.Debugger.ViewModels
|
|||
}
|
||||
}
|
||||
|
||||
private DebugTilemapTileInfo? GetSelectedTileInfo()
|
||||
{
|
||||
if(SelectionRect.IsEmpty || _ppuState == null || _prevVram == null) {
|
||||
return null;
|
||||
} else {
|
||||
PixelPoint p =PixelPoint.FromPoint(SelectionRect.TopLeft, 1);
|
||||
return DebugApi.GetTilemapTileInfo((uint)p.X, (uint)p.Y, CpuType, GetOptions(SelectedTab), _prevVram, _ppuState);
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdatePreviewPanel()
|
||||
{
|
||||
if(SelectionRect.IsEmpty) {
|
||||
|
|
|
@ -64,8 +64,6 @@
|
|||
<Border BorderBrush="Gray" BorderThickness="1">
|
||||
<ScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto" AllowAutoHide="False">
|
||||
<dc:PictureViewer
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch"
|
||||
x:Name="picViewer"
|
||||
Source="{CompiledBinding ViewerBitmap}"
|
||||
Zoom="{CompiledBinding Config.ImageScale}"
|
||||
|
|
|
@ -44,6 +44,14 @@ namespace Mesen.Debugger.Windows
|
|||
_editor.ByteUpdated += editor_ByteUpdated;
|
||||
}
|
||||
|
||||
public void SetCursorPosition(MemoryType memType, int address)
|
||||
{
|
||||
if(_model.AvailableMemoryTypes.Contains(memType)) {
|
||||
_model.Config.MemoryType = memType;
|
||||
_editor.SetCursorPosition(address, scrollToTop: true);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnClosing(CancelEventArgs e)
|
||||
{
|
||||
base.OnClosing(e);
|
||||
|
@ -57,6 +65,7 @@ namespace Mesen.Debugger.Windows
|
|||
{
|
||||
base.OnOpened(e);
|
||||
InitializeActions();
|
||||
_editor.Focus();
|
||||
}
|
||||
|
||||
private void InitializeComponent()
|
||||
|
|
|
@ -113,8 +113,6 @@
|
|||
AllowAutoHide="False"
|
||||
>
|
||||
<dc:PictureViewer
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch"
|
||||
x:Name="picViewer"
|
||||
Source="{CompiledBinding ViewerBitmap}"
|
||||
Zoom="{CompiledBinding Config.ImageScale}"
|
||||
|
|
|
@ -111,8 +111,6 @@
|
|||
AllowAutoHide="False"
|
||||
>
|
||||
<dc:PictureViewer
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch"
|
||||
x:Name="picViewer"
|
||||
Source="{CompiledBinding ViewerBitmap}"
|
||||
Zoom="{CompiledBinding Config.ImageScale}"
|
||||
|
|
|
@ -95,8 +95,6 @@
|
|||
AllowAutoHide="False"
|
||||
>
|
||||
<dc:PictureViewer
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch"
|
||||
x:Name="picViewer"
|
||||
Source="{CompiledBinding ViewerBitmap}"
|
||||
Zoom="{CompiledBinding Config.ImageScale}"
|
||||
|
|
|
@ -302,18 +302,35 @@ namespace Mesen.Interop
|
|||
}
|
||||
|
||||
[DllImport(DllPath)] public static extern void ResetMemoryAccessCounts();
|
||||
public static void GetMemoryAccessCounts(MemoryType type, ref AddressCounters[] counters)
|
||||
public static void GetMemoryAccessCounts(MemoryType type, ref AddressCounters[] counts)
|
||||
{
|
||||
int size = DebugApi.GetMemorySize(type);
|
||||
Array.Resize(ref counters, size);
|
||||
DebugApi.GetMemoryAccessCountsWrapper(0, (uint)size, type, counters);
|
||||
Array.Resize(ref counts, size);
|
||||
|
||||
GCHandle handle = GCHandle.Alloc(counts, GCHandleType.Pinned);
|
||||
IntPtr ptr = handle.AddrOfPinnedObject();
|
||||
DebugApi.GetMemoryAccessCountsWrapper(0, (uint)size, type, ptr);
|
||||
handle.Free();
|
||||
}
|
||||
|
||||
[DllImport(DllPath, EntryPoint = "GetMemoryAccessCounts")] private static extern void GetMemoryAccessCountsWrapper(UInt32 offset, UInt32 length, MemoryType type, [In,Out]AddressCounters[] counts);
|
||||
public static AddressCounters[] GetMemoryAccessCounts(MemoryType type)
|
||||
{
|
||||
int size = DebugApi.GetMemorySize(type);
|
||||
AddressCounters[] counts = new AddressCounters[size];
|
||||
GetMemoryAccessCounts(type, ref counts);
|
||||
return counts;
|
||||
}
|
||||
|
||||
[DllImport(DllPath, EntryPoint = "GetMemoryAccessCounts")] private static extern void GetMemoryAccessCountsWrapper(UInt32 offset, UInt32 length, MemoryType type, IntPtr counts);
|
||||
public static AddressCounters[] GetMemoryAccessCounts(UInt32 offset, UInt32 length, MemoryType type)
|
||||
{
|
||||
AddressCounters[] counts = new AddressCounters[length];
|
||||
DebugApi.GetMemoryAccessCountsWrapper(offset, length, type, counts);
|
||||
|
||||
GCHandle handle = GCHandle.Alloc(counts, GCHandleType.Pinned);
|
||||
IntPtr ptr = handle.AddrOfPinnedObject();
|
||||
DebugApi.GetMemoryAccessCountsWrapper(offset, length, type, ptr);
|
||||
handle.Free();
|
||||
|
||||
return counts;
|
||||
}
|
||||
|
||||
|
|
|
@ -1800,6 +1800,7 @@ x == [$150] || y == [10]
|
|||
|
||||
<Value ID="ExportToPng">Export to PNG</Value>
|
||||
<Value ID="ViewInTileViewer">View in Tile Viewer</Value>
|
||||
<Value ID="ViewInMemoryViewer">View in Memory Viewer</Value>
|
||||
</Enum>
|
||||
</Enums>
|
||||
</Resources>
|
Loading…
Add table
Reference in a new issue