Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/debugger QoL #948

Merged
merged 2 commits into from
Nov 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading