Skip to content

Commit

Permalink
Feat/debugger QoL (#948)
Browse files Browse the repository at this point in the history
* feat: Debugger keyboard shortcuts

Signed-off-by: Maximilien Noal <noal.maximilien@gmail.com>

* feat: StepOver goes to CS:IP only if needed

Signed-off-by: Maximilien Noal <noal.maximilien@gmail.com>

---------

Signed-off-by: Maximilien Noal <noal.maximilien@gmail.com>
  • Loading branch information
maximilien-noal authored Nov 27, 2024
1 parent bffc80f commit 763e681
Show file tree
Hide file tree
Showing 6 changed files with 84 additions and 40 deletions.
46 changes: 35 additions & 11 deletions src/Spice86/ViewModels/DisassemblyViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,10 @@ private void ConfirmCreateExecutionBreakpoint() {
if (!string.IsNullOrWhiteSpace(BreakpointAddress) &&
TryParseMemoryAddress(BreakpointAddress, out ulong? breakpointAddressValue)) {
AddressBreakPoint addressBreakPoint = new(BreakPointType.EXECUTION,
(long)breakpointAddressValue, OnBreakPointReached, false);
(long)breakpointAddressValue, (breakpoint) => {
RequestPause(breakpoint);
UpdateDisassemblyInternal();
}, false);
_breakpointsViewModel.AddAddressBreakpoint(addressBreakPoint);
}
}
Expand Down Expand Up @@ -172,7 +175,7 @@ private void StepOver() {
BreakPointType.EXECUTION,
nextInstructionAddressInListing,
(breakpoint) => {
OnBreakPointReached(breakpoint);
RequestPause(breakpoint);
_uiDispatcher.Post(GoToCsIp);
},
isRemovedOnTrigger: true);
Expand All @@ -184,7 +187,11 @@ private void StepOver() {
[RelayCommand(CanExecute = nameof(IsPaused))]
private void StepInto() {
_cpu.ExecuteNext();
_uiDispatcher.Post(GoToCsIp);
if (!Instructions.GetRange(0, 15).Any(x => x.Address == _state.IpPhysicalAddress)) {
GoToCsIp();
} else {
UpdateDisassemblyInternal();
}
}

[RelayCommand(CanExecute = nameof(IsPaused))]
Expand Down Expand Up @@ -230,12 +237,20 @@ private void UpdateDisassembly() {
if (startAddress is null) {
return;
}

Instructions = new(DecodeInstructions(_state, _memory, startAddress.Value, NumberOfInstructionsShown));
Instructions = new(DecodeCurrentWindowOfInstructions(startAddress.Value));
SelectedInstruction = Instructions.FirstOrDefault();
UpdateHeader(SelectedInstruction?.Address);
}

private List<CpuInstructionInfo> DecodeCurrentWindowOfInstructions(uint startAddress) {
return
DecodeInstructions(
_state,
_memory,
startAddress,
NumberOfInstructionsShown);
}

private CpuInstructionInfo? _selectedInstruction;

public CpuInstructionInfo? SelectedInstruction {
Expand Down Expand Up @@ -300,11 +315,16 @@ private List<CpuInstructionInfo> DecodeInstructions(State state, IMemory memory,
return instructions;
}

private void OnBreakPointReached(BreakPoint breakPoint) {
private void RequestPause(BreakPoint breakPoint) {
string message = $"{breakPoint.BreakPointType} breakpoint was reached.";
_pauseHandler.RequestPause(message);
_uiDispatcher.Post(() => {
_messenger.Send(new StatusMessage(DateTime.Now, this, message));
});
}

private void UpdateDisassemblyInternal() {
_uiDispatcher.Post(() => {
if (UpdateDisassemblyCommand.CanExecute(null)) {
UpdateDisassemblyCommand.Execute(null);
}
Expand All @@ -318,9 +338,7 @@ private void MoveCsIpHere() {
}
_state.CS = SelectedInstruction.SegmentedAddress.Segment;
_state.IP = SelectedInstruction.SegmentedAddress.Offset;
if (UpdateDisassemblyCommand.CanExecute(null)) {
UpdateDisassemblyCommand.Execute(null);
}
UpdateDisassemblyInternal();
}

private bool RemoveExecutionBreakpointHereCanExecute() =>
Expand All @@ -343,7 +361,13 @@ private void CreateExecutionBreakpointHere() {
if (SelectedInstruction is null) {
return;
}
AddressBreakPoint breakPoint = new(BreakPointType.EXECUTION, SelectedInstruction.Address, OnBreakPointReached,
AddressBreakPoint breakPoint = new(
BreakPointType.EXECUTION,
SelectedInstruction.Address,
(breakpoint) => {
RequestPause(breakpoint);
UpdateDisassemblyInternal();
},
isRemovedOnTrigger: false);
_breakpointsViewModel.AddAddressBreakpoint(breakPoint);
SelectedInstruction.HasBreakpoint = _breakpointsViewModel.HasUserExecutionBreakpoint(SelectedInstruction);
Expand All @@ -360,4 +384,4 @@ private static CodeReader CreateCodeReader(IMemory memory, out CodeMemoryStream
CodeReader codeReader = new StreamCodeReader(codeMemoryStream);
return codeReader;
}
}
}
2 changes: 1 addition & 1 deletion src/Spice86/Views/BreakpointsView.axaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
</Grid.RowDefinitions>
<StackPanel Grid.Row="0" Orientation="Horizontal" HorizontalAlignment="Center">
<Button Content="Remove" Command="{Binding RemoveBreakpointCommand}" Margin="5"/>
<Button Content="Toggle" Command="{Binding ToggleSelectedBreakpointCommand}" Margin="5"/>
<Button HotKey="Ctrl+F9" ToolTip.Tip="Ctrl-F9" Content="Toggle" Command="{Binding ToggleSelectedBreakpointCommand}" Margin="5"/>
</StackPanel>
<DataGrid Grid.Row="1"
ItemsSource="{Binding Breakpoints}"
Expand Down
36 changes: 20 additions & 16 deletions src/Spice86/Views/DebugWindow.axaml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@
<StackPanel Grid.Row="0" HorizontalAlignment="Center" VerticalAlignment="Top" Orientation="Horizontal">
<Button
Margin="5,0,0,0"
ToolTip.Tip="Pause (Ctrl+Shift+F5)"
HotKey="Ctrl+Shift+F5"
Command="{Binding PauseCommand}"
IsVisible="{Binding !IsPaused}">
<Button.Content>
Expand All @@ -39,6 +41,8 @@
</Button>
<Button
Margin="5,0,0,0"
ToolTip.Tip="Continue (F5)"
HotKey="F5"
Command="{Binding ContinueCommand}"
IsVisible="{Binding IsPaused}">
<Button.Content>
Expand All @@ -47,34 +51,34 @@
</Button>
</StackPanel>
<TabControl TabStripPlacement="Left" Grid.Row="1">
<controls:HotKeyTabItem HotKeyManager.HotKey="F1" Content="{Binding CpuViewModel}">
<controls:HotKeyTabItem HotKeyManager.HotKey="Alt+F1" Content="{Binding CpuViewModel}">
<controls:HotKeyTabItem.Header>
<LayoutTransformControl>
<LayoutTransformControl.LayoutTransform>
<RotateTransform Angle="-90" />
</LayoutTransformControl.LayoutTransform>
<TextBlock Margin="5,0,0,5" Text="CPU (F1)" />
<TextBlock Margin="5,0,0,5" Text="CPU" ToolTip.Tip="Alt-F1" />
</LayoutTransformControl>
</controls:HotKeyTabItem.Header>
</controls:HotKeyTabItem>
<controls:HotKeyTabItem HotKeyManager.HotKey="F2"
<controls:HotKeyTabItem HotKeyManager.HotKey="Alt+F2"
Content="{Binding CfgCpuViewModel}">
<controls:HotKeyTabItem.Header>
<LayoutTransformControl>
<LayoutTransformControl.LayoutTransform>
<RotateTransform Angle="-90" />
</LayoutTransformControl.LayoutTransform>
<TextBlock Margin="5,0,0,5" Text="Code Flow (F2)" />
<TextBlock Margin="5,0,0,5" Text="Code Flow" ToolTip.Tip="Alt-F2" />
</LayoutTransformControl>
</controls:HotKeyTabItem.Header>
</controls:HotKeyTabItem>
<controls:HotKeyTabItem HotKeyManager.HotKey="F3">
<controls:HotKeyTabItem HotKeyManager.HotKey="Alt+F3">
<controls:HotKeyTabItem.Header>
<LayoutTransformControl>
<LayoutTransformControl.LayoutTransform>
<RotateTransform Angle="-90" />
</LayoutTransformControl.LayoutTransform>
<TextBlock Margin="5,0,0,5" Text="Disassembly (F3)" />
<TextBlock Margin="5,0,0,5" Text="Disassembly" ToolTip.Tip="Alt-F3" />
</LayoutTransformControl>
</controls:HotKeyTabItem.Header>
<TabControl ItemsSource="{Binding DisassemblyViewModels}">
Expand All @@ -87,13 +91,13 @@
</TabControl.ItemTemplate>
</TabControl>
</controls:HotKeyTabItem>
<controls:HotKeyTabItem HotKeyManager.HotKey="F4">
<controls:HotKeyTabItem HotKeyManager.HotKey="Alt+F4">
<controls:HotKeyTabItem.Header>
<LayoutTransformControl>
<LayoutTransformControl.LayoutTransform>
<RotateTransform Angle="-90" />
</LayoutTransformControl.LayoutTransform>
<TextBlock Margin="5,0,0,5" Text="Memory (F4)" />
<TextBlock Margin="5,0,0,5" Text="Memory" ToolTip.Tip="Alt-F4" />
</LayoutTransformControl>
</controls:HotKeyTabItem.Header>
<TabControl ItemsSource="{Binding MemoryViewModels}">
Expand All @@ -106,29 +110,29 @@
</TabControl.ItemTemplate>
</TabControl>
</controls:HotKeyTabItem>
<controls:HotKeyTabItem HotKeyManager.HotKey="F5">
<controls:HotKeyTabItem HotKeyManager.HotKey="Alt+F5">
<controls:HotKeyTabItem.Header>
<LayoutTransformControl>
<LayoutTransformControl.LayoutTransform>
<RotateTransform Angle="-90" />
</LayoutTransformControl.LayoutTransform>
<TextBlock Margin="5,0,0,5" Text="Devices (F5)" />
<TextBlock Margin="5,0,0,5" Text="Devices" ToolTip.Tip="Alt-F5" />
</LayoutTransformControl>
</controls:HotKeyTabItem.Header>
<TabControl>
<controls:HotKeyTabItem HotKeyManager.HotKey="F6" Header="Video Card (F6)" Content="{Binding VideoCardViewModel}" />
<controls:HotKeyTabItem HotKeyManager.HotKey="F7" Header="Color Palette (F7)" Content="{Binding PaletteViewModel}" />
<controls:HotKeyTabItem HotKeyManager.HotKey="F8" Header="General MIDI / MT-32 (F8)" Content="{Binding MidiViewModel}" />
<controls:HotKeyTabItem HotKeyManager.HotKey="F9" Header="Software Mixer (F9)" Content="{Binding SoftwareMixerViewModel}" />
<controls:HotKeyTabItem HotKeyManager.HotKey="Alt+F7" Header="Video Card" ToolTip.Tip="Alt-F7" Content="{Binding VideoCardViewModel}" />
<controls:HotKeyTabItem HotKeyManager.HotKey="Alt+F8" Header="Color Palette" ToolTip.Tip="Alt-F8" Content="{Binding PaletteViewModel}" />
<controls:HotKeyTabItem HotKeyManager.HotKey="Alt+F9" Header="General MIDI / MT-32" ToolTip.Tip="Alt-F9" Content="{Binding MidiViewModel}" />
<controls:HotKeyTabItem HotKeyManager.HotKey="Alt+F10" Header="Software Mixer" ToolTip.Tip="Alt-F10" Content="{Binding SoftwareMixerViewModel}" />
</TabControl>
</controls:HotKeyTabItem>
<controls:HotKeyTabItem HotKeyManager.HotKey="F10" Content="{Binding BreakpointsViewModel}">
<controls:HotKeyTabItem HotKeyManager.HotKey="Alt+F6" Content="{Binding BreakpointsViewModel}">
<controls:HotKeyTabItem.Header>
<LayoutTransformControl>
<LayoutTransformControl.LayoutTransform>
<RotateTransform Angle="-90" />
</LayoutTransformControl.LayoutTransform>
<TextBlock Margin="5,0,0,5" Text="Breakpoints (F10)" />
<TextBlock Margin="5,0,0,5" Text="Breakpoints" ToolTip.Tip="Alt-F6" />
</LayoutTransformControl>
</controls:HotKeyTabItem.Header>
</controls:HotKeyTabItem>
Expand Down
21 changes: 16 additions & 5 deletions src/Spice86/Views/DisassemblyView.axaml
Original file line number Diff line number Diff line change
Expand Up @@ -25,16 +25,19 @@
<Button
Command="{Binding NewDisassemblyViewCommand}"
Content="New Disassembly View"
HotKey="Ctrl+T" ToolTip.Tip="Ctrl-T"
IsEnabled="{Binding IsPaused}" />
<Button
HotKey="Ctrl+F4"
ToolTip.Tip="Ctrl-F4"
Command="{Binding CloseTabCommand}"
Content="Close View"
IsEnabled="{Binding CanCloseTab}"/>
</StackPanel>
<StackPanel Orientation="Vertical" Grid.Column="1">
<Button Command="{Binding BeginCreateExecutionBreakpointCommand}" Content="Breakpoint..." />
<Button Content="Step into" Command="{Binding StepIntoCommand}" />
<Button Content="Step over" Command="{Binding StepOverCommand}" />
<Button Content="Step into" ToolTip.Tip="F11" HotKey="F11" Command="{Binding StepIntoCommand}" />
<Button Content="Step over" ToolTip.Tip="F10" HotKey="F10" Command="{Binding StepOverCommand}" />
</StackPanel>
<StackPanel Orientation="Vertical" Grid.Column="2">
<Label HorizontalAlignment="Center" Content="Number of instructions shown" Margin="5" />
Expand All @@ -55,7 +58,7 @@
</StackPanel>
</StackPanel>
<StackPanel Orientation="Vertical" Grid.Column="4">
<Button Content="Go to CS:IP" Command="{Binding GoToCsIpCommand}" />
<Button Content="Go to CS:IP" HotKey="Ctrl+F5" ToolTip.Tip="Ctrl-F5" Command="{Binding GoToCsIpCommand}" />
<Label
IsVisible="{Binding AreFunctionInformationProvided}">
Go to function:
Expand All @@ -65,7 +68,7 @@
ItemsSource="{Binding Functions}"
SelectedItem="{Binding SelectedFunction, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
</StackPanel>
<Button Grid.Column="5" Content="Refresh" Command="{Binding UpdateDisassemblyCommand}" />
<Button Grid.Column="5" Content="Refresh" HotKey="F5" ToolTip.Tip="F5" Command="{Binding UpdateDisassemblyCommand}" />
</Grid>
<DataGrid
Grid.Row="1"
Expand Down Expand Up @@ -99,7 +102,15 @@
<DataGridTextColumn MaxWidth="300"
Binding="{Binding Converter={StaticResource InstructionToStringConverter}}"
Header="MASM" />
<DataGridTextColumn Binding="{Binding Bytes}" Header="Bytes (Length)" />
<DataGridTextColumn Binding="{Binding Bytes}" Header="Bytes (Length)">
<DataGridTextColumn.CellTheme>
<ControlTheme TargetType="DataGridCell" BasedOn="{StaticResource {x:Type DataGridCell}}">
<Setter Property="FontWeight"
Value="{ReflectionBinding IsCsIp,
Converter={StaticResource BoolToFontWeightConverter}}" />
</ControlTheme>
</DataGridTextColumn.CellTheme>
</DataGridTextColumn>
<DataGridTextColumn Binding="{Binding SegmentPrefix}" Header="Segment Prefix" />
<DataGridTextColumn Binding="{Binding MemorySegment}" Header="Memory Segment" />
<DataGridTextColumn Binding="{Binding FlowControl}" Header="FlowControl" />
Expand Down
10 changes: 6 additions & 4 deletions src/Spice86/Views/MainWindow.axaml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
<Grid RowDefinitions="Auto,*,Auto">
<Menu Name="Menu" Focusable="False" Grid.Row="0" IsVisible="{Binding !IsDialogVisible}">
<MenuItem Header="Debug">
<MenuItem IsEnabled="{Binding IsEmulatorRunning}">
<MenuItem HotKey="Ctrl+Alt+F2" ToolTip.Tip="Ctrl+Alt+F2" IsEnabled="{Binding IsEmulatorRunning}">
<MenuItem.Header>
<StackPanel Orientation="Horizontal">
<fluent:SymbolIcon Symbol="Glance" />
Expand All @@ -59,7 +59,9 @@
<MenuItem Header="Error" Command="{Binding SetLogLevelToError}" />
<MenuItem Header="Fatal" Command="{Binding SetLogLevelToFatal}" />
</MenuItem>
<MenuItem IsEnabled="{Binding IsEmulatorRunning}" Command="{Binding DumpEmulatorStateToFileCommand}">
<MenuItem
HotKey="Ctrl+Alt+D" ToolTip.Tip="Ctrl+Alt+D"
IsEnabled="{Binding IsEmulatorRunning}" Command="{Binding DumpEmulatorStateToFileCommand}">
<MenuItem.Header>
<StackPanel Orientation="Horizontal">
<fluent:SymbolIcon Symbol="Document" />
Expand Down Expand Up @@ -93,10 +95,10 @@
</MenuItem>
</Menu>
<StackPanel Grid.Row="0" HorizontalAlignment="Center" VerticalAlignment="Top" Orientation="Horizontal">
<Button Focusable="False" Command="{Binding PauseCommand}" HotKey="Alt+Pause" IsVisible="{Binding !IsPaused}">
<Button Focusable="False" Command="{Binding PauseCommand}" ToolTip.Tip="Pause (Ctrl+Shift+F5)" HotKey="Ctrl+Shift+F5" IsVisible="{Binding !IsPaused}">
<fluent:SymbolIcon Symbol="Pause" />
</Button>
<Button Focusable="False" Command="{Binding PlayCommand}" HotKey="F5" IsVisible="{Binding IsPaused}">
<Button Focusable="False" Command="{Binding PlayCommand}" ToolTip.Tip="Continue (F5)" HotKey="F5" IsVisible="{Binding IsPaused}">
<fluent:SymbolIcon Symbol="Play" />
</Button>
<Label Focusable="False" VerticalAlignment="Center" Content="Time Modifier" />
Expand Down
9 changes: 6 additions & 3 deletions src/Spice86/Views/MemoryView.axaml
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,11 @@
HorizontalAlignment="Left"
VerticalAlignment="Top"
ScrollViewer.HorizontalScrollBarVisibility="Hidden">
<Button VerticalAlignment="Top" Command="{Binding StartMemorySearchCommand}" Content="Search..." />
<Button VerticalAlignment="Top" HotKey="F3" ToolTip.Tip="F3" Command="{Binding StartMemorySearchCommand}" Content="Search..." />
<Button VerticalAlignment="Top" Command="{Binding EditMemoryCommand}" Content="Edit..." />
<Button VerticalAlignment="Top" Command="{Binding DumpMemoryCommand}" Content="Dump..." />
<StackPanel Orientation="Vertical">
<Button Command="{Binding BeginCreateMemoryBreakpointCommand}" Content="Breakpoint..." />
<Button HotKey="F2" ToolTip.Tip="F2" Command="{Binding BeginCreateMemoryBreakpointCommand}" Content="Breakpoint..." />
<Button IsVisible="{Binding IsStructureInfoPresent}"
Command="{Binding ShowStructureView}"
Content="Structure view" />
Expand All @@ -37,9 +37,12 @@
<Button
Command="{Binding NewMemoryViewCommand}"
Content="New Memory View"
HotKey="Ctrl+T" ToolTip.Tip="Ctrl-T"
IsEnabled="{Binding IsPaused}" />
<Button
Command="{Binding CloseTabCommand}"
HotKey="Ctrl+F4"
ToolTip.Tip="Ctrl-F4"
Content="Close View"
IsEnabled="{Binding CanCloseTab}" />
</StackPanel>
Expand All @@ -49,7 +52,7 @@
<Label Content="End" />
<NumericUpDown Value="{Binding EndAddress}" />
</UniformGrid>
<Button IsVisible="{Binding IsPaused}" Command="{Binding UpdateBinaryDocumentCommand}" Content="Refresh" />
<Button IsVisible="{Binding IsPaused}" IsEnabled="{Binding IsPaused}" Command="{Binding UpdateBinaryDocumentCommand}" HotKey="F5" ToolTip.Tip="F5" Content="Refresh" />
</StackPanel>
<Grid Grid.Row="1">
<TextBlock IsVisible="{Binding !IsPaused}" Text="Memory is displayed only when the emulator is paused" />
Expand Down

0 comments on commit 763e681

Please sign in to comment.