/// <summary> /// Starts the machine in a background thread. /// </summary> /// <param name="options">Options to start the machine with.</param> /// <remarks> /// Reports completion when the machine starts executing its cycles. The machine can /// go into Paused or Stopped state, if the execution options allow, for example, /// when it runs to a predefined breakpoint. /// </remarks> public void Start(ExecuteCycleOptions options) { if (VmState == VmState.Running) { return; } // --- Prepare the machine to run IsFirstStart = VmState == VmState.None || VmState == VmState.Stopped; SpectrumVm.DebugInfoProvider?.PrepareBreakpoints(); if (IsFirstStart) { SpectrumVm.Reset(); SpectrumVm.Cpu.StackDebugSupport.ClearStepOutStack(); SpectrumVm.DebugInfoProvider?.ResetHitCounts(); } // --- Dispose the previous cancellation token, and create a new one CancellationTokenSource?.Dispose(); CancellationTokenSource = new CancellationTokenSource(); // --- Set up the task that runs the machine CompletionTask = new Task(async() => { Cancelled = false; ExecutionCycleResult = false; try { ExecutionCycleResult = SpectrumVm.ExecuteCycle(CancellationTokenSource.Token, options); } catch (TaskCanceledException) { Cancelled = true; } catch (Exception ex) { ExecutionCycleException = ex; } // --- Conclude the execution task await ExecuteOnMainThread(() => { MoveToState(VmState == VmState.Stopping || VmState == VmState.Stopped || ExecutionCycleException != null ? VmState.Stopped : VmState.Paused); if (ExecutionCycleException != null) { VmStoppedWithException?.Invoke(this, EventArgs.Empty); } }); }); MoveToState(VmState.Running); CompletionTask.Start(); }
/// <summary> /// Starts the machine in a background thread with the specified options. /// </summary> /// <remarks> /// Reports completion when the machine starts executing its cycles. The machine can /// go into Paused or Stopped state, if the execution options allow, for example, /// when it runs to a predefined breakpoint. /// </remarks> public void StartWithOptions(ExecuteCycleOptions options) { if (MachineState == VmState.Running) { return; } // --- Prepare the machine to run IsFirstStart = MachineState == VmState.None || MachineState == VmState.Stopped; SpectrumVm.DebugInfoProvider?.PrepareBreakpoints(); MachineState = VmState.Starting; if (IsFirstStart) { SpectrumVm.Reset(); SpectrumVm.Cpu.StackDebugSupport.Reset(); SpectrumVm.DebugInfoProvider?.ResetHitCounts(); CpuFrameCount = 0; RenderFrameCount = 0; } // --- Dispose the previous cancellation token, and create a new one _cancellationTokenSource?.Dispose(); _cancellationTokenSource = new CancellationTokenSource(); // --- Set up the task that runs the machine MachineState = VmState.Running; try { _completionTask = StartAndRun(_cancellationTokenSource.Token, options); _completionTask.GetAwaiter().OnCompleted(async() => { await WaitForPause(); }); } catch (TaskCanceledException) { ExecutionCompletionReason = ExecutionCompletionReason.Cancelled; } catch (Exception ex) { ExceptionRaised?.Invoke(this, new VmExceptionArgs(ex)); } }
/// <summary> /// Builds the machine that can be started /// </summary> protected virtual void BuildMachine() { if (SpectrumVm == null) { MoveToState(VmState.BuildingMachine); if (StartupConfiguration == null) { throw new InvalidOperationException("You must provide a startup configuration for " + "the virtual machine, it cannot be null"); } // --- Create the machine on first start SpectrumVm = new Spectrum48(StartupConfiguration.DeviceData, this); SpectrumVm.ScreenDevice.FrameCompleted += (s, e) => VmScreenRefreshed?.Invoke(s, new VmScreenRefreshedEventArgs(SpectrumVm.ScreenDevice.GetPixelBuffer())); } // --- We either provider out DebugInfoProvider, or use // --- the default one if (StartupConfiguration.DebugInfoProvider == null) { StartupConfiguration.DebugInfoProvider = SpectrumVm.DebugInfoProvider; } else { SpectrumVm.DebugInfoProvider = StartupConfiguration.DebugInfoProvider; } // --- Set up stack debug support if (StartupConfiguration.StackDebugSupport != null) { SpectrumVm.Cpu.StackDebugSupport = StartupConfiguration.StackDebugSupport; StartupConfiguration.StackDebugSupport.Reset(); } // --- At this point we have a Spectrum VM. // --- Let's reset it SpectrumVm.Reset(); }