Skip to content

Commit

Permalink
feat: DISASM view Step Over button
Browse files Browse the repository at this point in the history
Signed-off-by: Maximilien Noal <noal.maximilien@gmail.com>
  • Loading branch information
maximilien-noal committed Nov 3, 2024
1 parent c45fced commit 57e9bd5
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 57 deletions.
5 changes: 4 additions & 1 deletion src/Spice86/ViewModels/DebugWindowViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,10 @@ public DebugWindowViewModel(IInstructionExecutor cpu, State cpuState, Stack stac
IsPaused = pauseHandler.IsPaused;
pauseHandler.Pausing += () => uiDispatcher.Post(() => IsPaused = true);
pauseHandler.Resumed += () => uiDispatcher.Post(() => IsPaused = false);
DisassemblyViewModel disassemblyVm = new(cpu, memory, cpuState, BreakpointsViewModel, pauseHandler, uiDispatcher, messenger, textClipboard);
DisassemblyViewModel disassemblyVm = new(
cpu, memory, cpuState,
BreakpointsViewModel, emulatorBreakpointsManager, pauseHandler,
uiDispatcher, messenger, textClipboard);
DisassemblyViewModels.Add(disassemblyVm);
PaletteViewModel = new(argbPalette, uiDispatcher);
SoftwareMixerViewModel = new(softwareMixer);
Expand Down
57 changes: 40 additions & 17 deletions src/Spice86/ViewModels/DisassemblyViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,24 @@ public partial class DisassemblyViewModel : ViewModelWithErrorDialog {
private readonly IPauseHandler _pauseHandler;
private readonly IInstructionExecutor _cpu;
private readonly BreakpointsViewModel _breakpointsViewModel;
private readonly EmulatorBreakpointsManager _emulatorBreakpointsManager;

public DisassemblyViewModel(IInstructionExecutor cpu, IMemory memory, State state,
BreakpointsViewModel breakpointsViewModel, EmulatorBreakpointsManager emulatorBreakpointsManager, IPauseHandler pauseHandler, IUIDispatcher uiDispatcher,
IMessenger messenger, ITextClipboard textClipboard, bool canCloseTab = false) : base(uiDispatcher, textClipboard) {
_cpu = cpu;
_emulatorBreakpointsManager = emulatorBreakpointsManager;
_breakpointsViewModel = breakpointsViewModel;
_messenger = messenger;
_memory = memory;
_state = state;
_pauseHandler = pauseHandler;
IsPaused = pauseHandler.IsPaused;
pauseHandler.Pausing += () => _uiDispatcher.Post(() => IsPaused = true);
pauseHandler.Resumed += () => _uiDispatcher.Post(() => IsPaused = false);
CanCloseTab = canCloseTab;
UpdateDisassembly();
}

[ObservableProperty]
private string _header = "Disassembly View";
Expand All @@ -41,6 +59,7 @@ public partial class DisassemblyViewModel : ViewModelWithErrorDialog {
[NotifyCanExecuteChangedFor(nameof(NewDisassemblyViewCommand))]
[NotifyCanExecuteChangedFor(nameof(CopyLineCommand))]
[NotifyCanExecuteChangedFor(nameof(StepIntoCommand))]
[NotifyCanExecuteChangedFor(nameof(StepOverCommand))]
private bool _isPaused;

[ObservableProperty]
Expand Down Expand Up @@ -96,29 +115,32 @@ public uint? StartAddress {
[NotifyCanExecuteChangedFor(nameof(CloseTabCommand))]
private bool _canCloseTab;

public DisassemblyViewModel(IInstructionExecutor cpu, IMemory memory, State state,
BreakpointsViewModel breakpointsViewModel, IPauseHandler pauseHandler, IUIDispatcher uiDispatcher,
IMessenger messenger, ITextClipboard textClipboard, bool canCloseTab = false) : base(uiDispatcher, textClipboard) {
_cpu = cpu;
_breakpointsViewModel = breakpointsViewModel;
_messenger = messenger;
_memory = memory;
_state = state;
_pauseHandler = pauseHandler;
IsPaused = pauseHandler.IsPaused;
pauseHandler.Pausing += () => _uiDispatcher.Post(() => IsPaused = true);
pauseHandler.Resumed += () => _uiDispatcher.Post(() => IsPaused = false);
CanCloseTab = canCloseTab;
UpdateDisassembly();
}

private void UpdateHeader(uint? address) {
Header = address is null ? "" : $"0x{address:X}";
}

[RelayCommand(CanExecute = nameof(CanCloseTab))]
private void CloseTab() => _messenger.Send(new RemoveViewModelMessage<DisassemblyViewModel>(this));

[RelayCommand(CanExecute = nameof(IsPaused))]
private void StepOver() {
if(SelectedInstruction is null) {
return;
}
var nextInstructionAddressInListing = SelectedInstruction.Address + SelectedInstruction.Length;
var addressBreakpoint = new AddressBreakPoint(
BreakPointType.EXECUTION,
nextInstructionAddressInListing,
(breakpoint) => {
OnBreakPointReached(breakpoint);
_uiDispatcher.Post(GoToCsIp);
},
isRemovedOnTrigger: true);
_emulatorBreakpointsManager.ToggleBreakPoint(addressBreakpoint, on: true);
_pauseHandler.Resume();
}


[RelayCommand(CanExecute = nameof(IsPaused))]
private void StepInto() {
_cpu.ExecuteNext();
Expand All @@ -127,7 +149,7 @@ private void StepInto() {

[RelayCommand(CanExecute = nameof(IsPaused))]
private void NewDisassemblyView() {
DisassemblyViewModel disassemblyViewModel = new(_cpu, _memory, _state, _breakpointsViewModel, _pauseHandler, _uiDispatcher, _messenger,
DisassemblyViewModel disassemblyViewModel = new(_cpu, _memory, _state, _breakpointsViewModel, _emulatorBreakpointsManager, _pauseHandler, _uiDispatcher, _messenger,
_textClipboard, canCloseTab: true) {
IsPaused = IsPaused
};
Expand Down Expand Up @@ -223,6 +245,7 @@ private void OnBreakPointReached(BreakPoint breakPoint) {
_pauseHandler.RequestPause(message);
_uiDispatcher.Post(() => {
_messenger.Send(new StatusMessage(DateTime.Now, this, message));
UpdateDisassembly();
});
}

Expand Down
1 change: 1 addition & 0 deletions src/Spice86/ViewModels/MemoryViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ private void OnBreakPointReached(BreakPoint breakPoint) {
_pauseHandler.RequestPause(message);
_uiDispatcher.Post(() => {
_messenger.Send(new StatusMessage(DateTime.Now, this, message));
TryUpdateHeaderAndMemoryDocument();
});
}

Expand Down
81 changes: 42 additions & 39 deletions src/Spice86/Views/DisassemblyView.axaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,47 +14,50 @@
<converters:SegmentedAddressConverter x:Key="SegmentedAddressConverter" />
</UserControl.Resources>
<Grid RowDefinitions="Auto,*">
<StackPanel Orientation="Horizontal"
Grid.Row="0" IsVisible="{Binding IsPaused}"
HorizontalAlignment="Center"
VerticalAlignment="Top">
<StackPanel Orientation="Vertical">
<Button
Command="{Binding NewDisassemblyViewCommand}"
Content="New Disassembly View"
IsEnabled="{Binding IsPaused}" />
<Button
Command="{Binding CloseTabCommand}"
Content="Close View"
IsEnabled="{Binding CanCloseTab}"/>
</StackPanel>
<StackPanel Orientation="Vertical">
<Button Command="{Binding BeginCreateExecutionBreakpointCommand}" IsEnabled="{Binding IsPaused}" Content="Breakpoint..." />
<Button Content="Step into" Command="{Binding StepIntoCommand}" />
</StackPanel>
<StackPanel Orientation="Vertical" IsEnabled="{Binding IsPaused}">
<Label HorizontalAlignment="Center" Content="Number of instructions shown" Margin="5" />
<NumericUpDown Margin="5" Value="{Binding NumberOfInstructionsShown}" />
</StackPanel>
<StackPanel Orientation="Vertical" IsEnabled="{Binding IsPaused}">
<RadioButton GroupName="AddressingMode" Content="Segmented addressing" IsChecked="{Binding !IsUsingLinearAddressing}" />
<RadioButton GroupName="AddressingMode" Content="Linear addressing" IsChecked="{Binding IsUsingLinearAddressing}" />
<Label HorizontalAlignment="Center" Content="Start Address" />
<StackPanel Orientation="Horizontal">
<TextBox IsEnabled="{Binding !IsUsingLinearAddressing}"
Text="{Binding SegmentedStartAddress, Mode=TwoWay, UpdateSourceTrigger=LostFocus,
<Viewbox Grid.Row="0">
<StackPanel Orientation="Horizontal"
IsVisible="{Binding IsPaused}"
HorizontalAlignment="Center"
VerticalAlignment="Top">
<StackPanel Orientation="Vertical">
<Button
Command="{Binding NewDisassemblyViewCommand}"
Content="New Disassembly View"
IsEnabled="{Binding IsPaused}" />
<Button
Command="{Binding CloseTabCommand}"
Content="Close View"
IsEnabled="{Binding CanCloseTab}"/>
</StackPanel>
<StackPanel Orientation="Vertical">
<Button Command="{Binding BeginCreateExecutionBreakpointCommand}" IsEnabled="{Binding IsPaused}" Content="Breakpoint..." />
<Button Content="Step into" Command="{Binding StepIntoCommand}" />
<Button Content="Step over" Command="{Binding StepOverCommand}" />
</StackPanel>
<StackPanel Orientation="Vertical" IsEnabled="{Binding IsPaused}">
<Label HorizontalAlignment="Center" Content="Number of instructions shown" Margin="5" />
<NumericUpDown Margin="5" Value="{Binding NumberOfInstructionsShown}" />
</StackPanel>
<StackPanel Orientation="Vertical" IsEnabled="{Binding IsPaused}">
<RadioButton GroupName="AddressingMode" Content="Segmented addressing" IsChecked="{Binding !IsUsingLinearAddressing}" />
<RadioButton GroupName="AddressingMode" Content="Linear addressing" IsChecked="{Binding IsUsingLinearAddressing}" />
<Label HorizontalAlignment="Center" Content="Start Address" />
<StackPanel Orientation="Horizontal">
<TextBox IsEnabled="{Binding !IsUsingLinearAddressing}"
Text="{Binding SegmentedStartAddress, Mode=TwoWay, UpdateSourceTrigger=LostFocus,
Converter={StaticResource SegmentedAddressConverter}}"
Watermark="segment:offset" />
<TextBox IsEnabled="{Binding IsUsingLinearAddressing, Mode=TwoWay}"
Text="{Binding StartAddress, UpdateSourceTrigger=PropertyChanged}"
Watermark="linear address"/>
Watermark="segment:offset" />
<TextBox IsEnabled="{Binding IsUsingLinearAddressing, Mode=TwoWay}"
Text="{Binding StartAddress, UpdateSourceTrigger=PropertyChanged}"
Watermark="linear address"/>
</StackPanel>
</StackPanel>
<StackPanel Orientation="Vertical">
<Button Content="Go to CS:IP" Command="{Binding GoToCsIpCommand}" />
<Button Content="Update" HotKey="Enter" IsDefault="True" Command="{Binding UpdateDisassemblyCommand}" />
</StackPanel>
</StackPanel>
<StackPanel Orientation="Vertical">
<Button Content="Go to CS:IP" Command="{Binding GoToCsIpCommand}" />
<Button Content="Update" HotKey="Enter" IsDefault="True" Command="{Binding UpdateDisassemblyCommand}" />
</StackPanel>
</StackPanel>
</StackPanel>
</Viewbox>
<DataGrid Grid.Row="1"
AutoGenerateColumns="False"
CanUserReorderColumns="True"
Expand Down

0 comments on commit 57e9bd5

Please sign in to comment.