public void Reset() { bool wasExecuting = IsExecuting; // Save context and stop executing if the system is currently running. SystemExecutionContext context = null; if (wasExecuting) { context = _currentExecutionContext; StopExecution(); } // Now do the actual reset. _cp.Reset(); _iop.Reset(); _displayController.Reset(); _ethernetController.Reset(); _hardDrive.Reset(); _shugartController.Reset(); // _scheduler.Reset(); _cpCycles = 0; _elapsedCycles = 0; // Restart execution if we were running before the reset. if (wasExecuting) { StartExecution(context); } }
private void ExecutionWorker(object obj) { SystemExecutionContext context = (SystemExecutionContext)obj; _abortExecution = false; while (!_abortExecution) { try { // // We clock the IOP first and let it run an instruction. // This returns the number of clock cycles consumed -- // on the 8085's 3Mhz timebase. // // We then execute the corresponding number of CP cycles // (based on a 137ns clock period, or about 7.3Mhz) that would // occur during that period. // int i8085Cycles = _iop.Execute(); // This is inexact and that's probably good enough on average. _cpCycles = (int)_cpCyclesPer8085Cycle * i8085Cycles; _cp.ExecuteInstruction(_cpCycles); if (Configuration.ThrottleSpeed) { _elapsedCycles += _cpCycles; if (_elapsedCycles > _cpCyclesPerField) { _elapsedCycles -= _cpCyclesPerField; if (_frameTimer != null) { _frameTimer.WaitForFrame(); } } } } catch (Exception e) { context.ErrorCallback(e); _abortExecution = true; } } ExecutionStateChanged(); }
public void StartExecution(SystemExecutionContext context) { StopExecution(); if (_executionThread == null || !_executionThread.IsAlive) { if (context.StepCallback8085 != null && context.StepCallbackCP != null && context.StepCallbackMesa != null) { _executionThread = new Thread(new ParameterizedThreadStart(DebugExecutionWorker)); } else { _executionThread = new Thread(new ParameterizedThreadStart(ExecutionWorker)); } _executionThread.Start(context); ExecutionStateChanged(); _currentExecutionContext = context; } }
private void DebugExecutionWorker(object obj) { SystemExecutionContext context = (SystemExecutionContext)obj; _abortExecution = false; bool iopAbort = false; while (!_abortExecution) { try { // // We clock the IOP first and let it run an instruction. // This returns the number of clock cycles consumed -- // on the 8085's 3Mhz timebase. // // We then execute the corresponding number of CP cycles // (based on a 137ns clock period, or about 7.3Mhz) that would // occur during that period. // if (_cpCycles == 0) { if (iopAbort) { // // Out of cycles after an IOP abort, now we actually abort. // _abortExecution = true; } else { int i8085Cycles = _iop.Execute(); // This is inexact and that's probably good enough on average. _cpCycles = (int)_cpCyclesPer8085Cycle * i8085Cycles; if (context.StepCallback8085()) { // // Set our local iopAbort flag, we still want to continue // to execute the CP and scheduler for as many microcycles as correspond to the // above 8085 instruction's execution time to keep things in sync. // iopAbort = true; } } } _cp.ExecuteInstruction(1); _cpCycles--; _elapsedCycles++; if (context.StepCallbackCP()) { // // Break on microinstruction step // _abortExecution = true; } if (_cp.IBDispatch && context.StepCallbackMesa()) { // // Break on macroinstruction step // _abortExecution = true; } } catch (Exception e) { context.ErrorCallback(e); _abortExecution = true; } } _cpCycles = 0; ExecutionStateChanged(); }