示例#1
0
        public CoreActionHistoryEvent AddCoreAction(CoreAction coreAction, int id)
        {
            // Instead of continually adding "RunUntil" actions, just keep updating the
            // current one if it's a RunUntil, and only notify once we've finished. That
            // happens either when we add a non-RunUntil node after a RunUntil node, or
            // when we change the current node and the current node is a RunUntil. See
            // SetCurrentNode for that case.
            bool notify = coreAction.Type != CoreRequest.Types.RunUntil;

            if (!notify)
            {
                if (_currentNode is CoreActionHistoryNode currentCoreActionNode &&
                    currentCoreActionNode.Children.Count == 0 &&
                    currentCoreActionNode.CoreAction.Type == CoreRequest.Types.RunUntil)
                {
                    currentCoreActionNode.CoreAction.StopTicks = coreAction.StopTicks;

                    return(currentCoreActionNode.HistoryEvent as CoreActionHistoryEvent);
                }
            }

            CoreActionHistoryNode historyNode = new CoreActionHistoryNode(id, coreAction.Ticks, coreAction, _currentNode, DateTime.Now);

            _nextId = Math.Max(_nextId, id) + 1;

            AddChildNode(historyNode, notify);

            return(historyNode.HistoryEvent as CoreActionHistoryEvent);
        }
示例#2
0
        private void ReceiveSelectMachine(string machineName)
        {
            IMachine machine = _machines.Where(m => m.Name == machineName).FirstOrDefault();

            if (machine == _machine)
            {
                return;
            }

            if (_machine != null)
            {
                // Quit sending to the client.
                _machine.Auditors -= MachineAuditor;
                _machine           = null;
            }

            _machine = machine;
            if (_machine != null)
            {
                using ((machine as IPausableMachine)?.AutoPause())
                {
                    byte[] state = _machine.Core.GetState();

                    CoreAction loadCoreAction = CoreAction.LoadCore(0, new MemoryBlob(state));

                    _remote.SendName(_machine.Name);
                    _remote.SendCoreAction(loadCoreAction);

                    _machine.Auditors += MachineAuditor;
                }
            }
        }
示例#3
0
        private void SetCurrentEvent(HistoryEvent historyEvent)
        {
            if (historyEvent is BookmarkHistoryEvent bookmarkHistoryEvent)
            {
                Core core = Core.Create(Core.LatestVersion, bookmarkHistoryEvent.Bookmark.State.GetBytes());
                SetCore(core);

                Display.GetFromBookmark(bookmarkHistoryEvent.Bookmark);

                Auditors?.Invoke(CoreAction.LoadCore(historyEvent.Ticks, bookmarkHistoryEvent.Bookmark.State));
            }
            else if (historyEvent is RootHistoryEvent rootHistoryEvent)
            {
                Core core = Core.Create(Core.LatestVersion, Core.Type.CPC6128);
                SetCore(core);

                Display.GetFromBookmark(null);

                Auditors?.Invoke(CoreAction.Reset(rootHistoryEvent.Ticks));
            }
            else
            {
                throw new Exception("Can't set current event to an event that isn't the root or doesn't have a bookmark.");
            }

            _history.CurrentEvent = historyEvent;
        }
示例#4
0
        private CoreAction RunForAWhile(UInt64 stopTicks)
        {
            UInt64 ticks = Ticks;

            // Only proceed on an audio buffer underrun.
            if (!_audioBuffer.WaitForUnderrun(20))
            {
                return(null);
            }

            // Limit how long we can run for to reduce audio lag.
            stopTicks = Math.Min(stopTicks, Ticks + 1000);

            List <UInt16> audioSamples = new List <UInt16>();
            byte          stopReason   = RunUntil(stopTicks, StopReasons.VSync, audioSamples);

            foreach (UInt16 sample in audioSamples)
            {
                _audioBuffer.Write(sample);
            }

            if ((stopReason & StopReasons.VSync) != 0)
            {
                OnPropertyChanged("Ticks");
                BeginVSync?.Invoke(this);
            }

            return(CoreAction.RunUntil(ticks, Ticks, audioSamples));
        }
示例#5
0
 protected HistoryNode(int id, UInt64 ticks, CoreAction action, Bookmark bookmark, HistoryNode parent, DateTime createDate)
 {
     Id         = id;
     Ticks      = ticks;
     Parent     = parent;
     CreateDate = createDate;
     Children   = new List <HistoryNode>();
 }
示例#6
0
        private void OnNewMessage(byte[] msg)
        {
            MemoryByteStream bs = new MemoryByteStream(msg);

            byte id = bs.ReadByte();

            switch (id)
            {
            case _idSelectMachine:
            {
                string machineName = Serializer.SelectMachineFromBytes(bs);
                ReceiveSelectMachine?.Invoke(machineName);
            }
            break;

            case _idAvailableMachines:
            {
                List <string> machines = Serializer.AvailableMachinesFromBytes(bs);
                ReceiveAvailableMachines?.Invoke(machines);
            }
            break;

            case _idCoreAction:
            {
                CoreAction coreAction = Serializer.CoreActionFromBytes(bs);
                ReceiveCoreAction?.Invoke(coreAction);
            }
            break;

            case _idPing:
            {
                bool   response = bs.ReadBool();
                UInt64 pid      = bs.ReadUInt64();
                ReceivePing?.Invoke(response, pid);
            }
            break;

            case _idRequestAvailableMachines:
            {
                ReceiveRequestAvailableMachines?.Invoke();
            }
            break;

            case _idName:
            {
                string machineName = bs.ReadString();
                ReceiveName?.Invoke(machineName);
            }
            break;

            case _idCoreRequest:
            {
                CoreRequest coreRequest = Serializer.CoreRequestFromBytes(bs);
                ReceiveCoreRequest?.Invoke(coreRequest);
            }
            break;
            }
        }
示例#7
0
        static public CoreAction LoadTape(UInt64 ticks, IBlob tape)
        {
            CoreAction action = new CoreAction(Types.LoadTape, ticks)
            {
                MediaBuffer = tape
            };

            return(action);
        }
示例#8
0
        static public CoreAction CoreVersion(UInt64 ticks, int version)
        {
            CoreAction action = new CoreAction(Types.CoreVersion, ticks)
            {
                Version = version
            };

            return(action);
        }
示例#9
0
        public void SendCoreAction(CoreAction coreAction)
        {
            MemoryByteStream bs = new MemoryByteStream();

            bs.Write(_idCoreAction);
            Serializer.CoreActionToBytes(bs, coreAction);

            SendMessage(bs.AsBytes());
        }
示例#10
0
        static public CoreAction CreateSnapshot(UInt64 ticks, int id)
        {
            CoreAction action = new CoreAction(Types.CreateSnapshot, ticks)
            {
                SnapshotId = id
            };

            return(action);
        }
示例#11
0
        static public CoreAction LoadCore(UInt64 ticks, IBlob state)
        {
            CoreAction action = new CoreAction(Types.LoadCore, ticks)
            {
                CoreState = state
            };

            return(action);
        }
示例#12
0
        static public CoreAction LoadDisc(UInt64 ticks, byte drive, IBlob disc)
        {
            CoreAction action = new CoreAction(Types.LoadDisc, ticks)
            {
                Drive       = drive,
                MediaBuffer = disc
            };

            return(action);
        }
示例#13
0
        static public CoreAction RunUntil(UInt64 ticks, UInt64 stopTicks, List <UInt16> audioSamples)
        {
            CoreAction action = new CoreAction(Types.RunUntil, ticks)
            {
                StopTicks    = stopTicks,
                AudioSamples = audioSamples
            };

            return(action);
        }
示例#14
0
        static public CoreAction KeyPress(UInt64 ticks, byte keycode, bool down)
        {
            CoreAction action = new CoreAction(Types.KeyPress, ticks)
            {
                KeyCode = keycode,
                KeyDown = down
            };

            return(action);
        }
示例#15
0
            private void ReadReset(string line)
            {
                string[] tokens = line.Split(',');

                int        id     = Convert.ToInt32(tokens[0]);
                UInt64     ticks  = Convert.ToUInt64(tokens[1]);
                CoreAction action = CoreAction.Reset(ticks);

                AddCoreAction(id, action);
            }
示例#16
0
        private CoreAction DeleteSnapshot(int id)
        {
            bool result = _coreCLR.DeleteSnapshot(id);

            if (!result)
            {
                return(null);
            }

            return(CoreAction.DeleteSnapshot(Ticks, id));
        }
示例#17
0
 private void RequestProcessed(Core core, CoreRequest request, CoreAction action)
 {
     if (core == _core && action != null)
     {
         if (action.Type == CoreAction.Types.RevertToSnapshot)
         {
             // Ensure to update the display.
             Display.CopyScreenAsync();
         }
     }
 }
示例#18
0
            private void ReadRunUntil(string line)
            {
                string[] tokens = line.Split(',');

                int    id        = Convert.ToInt32(tokens[0]);
                UInt64 ticks     = Convert.ToUInt64(tokens[1]);
                UInt64 stopTicks = Convert.ToUInt64(tokens[2]);

                CoreAction action = CoreAction.RunUntil(ticks, stopTicks, null);

                AddCoreAction(id, action);
            }
示例#19
0
            private void ReadLoadTape(string line)
            {
                string[] tokens = line.Split(',');

                int    id        = Convert.ToInt32(tokens[0]);
                UInt64 ticks     = Convert.ToUInt64(tokens[1]);
                IBlob  mediaBlob = new MemoryBlob(Helpers.BytesFromStr(tokens[2]));

                CoreAction action = CoreAction.LoadTape(ticks, mediaBlob);

                AddCoreAction(id, action);
            }
示例#20
0
        public void ReceiveCoreAction(CoreAction coreAction)
        {
            if (_core == null)
            {
                Close();
                return;
            }

            Auditors?.Invoke(coreAction);

            _core.PushRequest(coreAction);
        }
示例#21
0
            private void ReadKey(string line)
            {
                string[] tokens = line.Split(',');

                int    id      = Convert.ToInt32(tokens[0]);
                UInt64 ticks   = Convert.ToUInt64(tokens[1]);
                byte   keyCode = Convert.ToByte(tokens[2]);
                bool   keyDown = Convert.ToBoolean(tokens[3]);

                CoreAction action = CoreAction.KeyPress(ticks, keyCode, keyDown);

                AddCoreAction(id, action);
            }
示例#22
0
        private CoreAction RevertToSnapshot(int id)
        {
            bool result = _coreCLR.RevertToSnapshot(id);

            if (!result)
            {
                return(null);
            }

            OnPropertyChanged("Ticks");

            return(CoreAction.RevertToSnapshot(Ticks, id));
        }
示例#23
0
            private HistoryEvent AddCoreAction(int id, CoreAction coreAction)
            {
                if (_idToHistoryEvent.ContainsKey(id))
                {
                    throw new InvalidOperationException(String.Format("Id {0} has already been processed!", id));
                }

                HistoryEvent historyEvent = _machineHistory.AddCoreAction(coreAction, id);

                _idToHistoryEvent[id] = historyEvent;

                _nextLineId = Math.Max(_nextLineId, id + 1);

                return(historyEvent);
            }
示例#24
0
        public CoreAction Clone()
        {
            switch (Type)
            {
            case Types.CoreVersion:
                return(CoreAction.CoreVersion(Ticks, Version));

            case Types.KeyPress:
                return(CoreAction.KeyPress(Ticks, KeyCode, KeyDown));

            case Types.LoadDisc:
                return(CoreAction.LoadDisc(Ticks, Drive, (MediaBuffer != null) ? (new MemoryBlob(MediaBuffer.GetBytes())) : null));

            case Types.LoadTape:
                return(CoreAction.LoadTape(Ticks, (MediaBuffer != null) ? (new MemoryBlob(MediaBuffer.GetBytes())) : null));

            case Types.Reset:
                return(CoreAction.Reset(Ticks));

            case Types.RunUntil:
            {
                List <UInt16> samples = null;
                if (AudioSamples != null)
                {
                    samples = new List <UInt16>(AudioSamples);
                }
                return(CoreAction.RunUntil(Ticks, StopTicks, samples));
            }

            case Types.LoadCore:
                return(CoreAction.LoadCore(Ticks, CoreState));

            case Types.CreateSnapshot:
                return(CoreAction.CreateSnapshot(Ticks, SnapshotId));

            case Types.RevertToSnapshot:
                return(CoreAction.RevertToSnapshot(Ticks, SnapshotId));

            default:
                return(null);
            }
        }
示例#25
0
        static public CoreAction CoreActionFromBytes(MemoryByteStream stream)
        {
            byte type = stream.ReadByte();

            switch (type)
            {
            case _coreActionKeyPress:
            {
                UInt64 ticks   = stream.ReadUInt64();
                byte   keyCode = stream.ReadByte();
                bool   keyDown = stream.ReadBool();

                return(CoreAction.KeyPress(ticks, keyCode, keyDown));
            }

            case _coreActionReset:
            {
                UInt64 ticks = stream.ReadUInt64();

                return(CoreAction.Reset(ticks));
            }

            case _coreActionLoadDisc:
            {
                UInt64 ticks = stream.ReadUInt64();
                byte   drive = stream.ReadByte();
                byte[] media = stream.ReadArray();

                return(CoreAction.LoadDisc(ticks, drive, new MemoryBlob(media)));
            }

            case _coreActionLoadTape:
            {
                UInt64 ticks = stream.ReadUInt64();
                byte[] media = stream.ReadArray();

                return(CoreAction.LoadTape(ticks, new MemoryBlob(media)));
            }

            case _coreActionRunUntil:
            {
                UInt64 ticks     = stream.ReadUInt64();
                UInt64 stopTicks = stream.ReadUInt64();

                return(CoreAction.RunUntil(ticks, stopTicks, null));
            }

            case _coreActionLoadCore:
            {
                UInt64 ticks = stream.ReadUInt64();
                byte[] state = stream.ReadArray();

                return(CoreAction.LoadCore(ticks, new MemoryBlob(state)));
            }

            case _coreActionCoreVersion:
            {
                UInt64 ticks   = stream.ReadUInt64();
                Int32  version = stream.ReadInt32();

                return(CoreAction.CoreVersion(ticks, version));
            }

            case _coreActionCreateSnapshot:
            {
                UInt64 ticks      = stream.ReadUInt64();
                Int32  snapshotId = stream.ReadInt32();

                return(CoreAction.CreateSnapshot(ticks, snapshotId));
            }

            case _coreActionDeleteSnapshot:
            {
                UInt64 ticks      = stream.ReadUInt64();
                Int32  snapshotId = stream.ReadInt32();

                return(CoreAction.DeleteSnapshot(ticks, snapshotId));
            }

            case _coreActionRevertToSnapshot:
            {
                UInt64 ticks      = stream.ReadUInt64();
                Int32  snapshotId = stream.ReadInt32();

                return(CoreAction.RevertToSnapshot(ticks, snapshotId));
            }
            }

            throw new Exception(String.Format("Unknown CoreAction type {0}!", type));
        }
示例#26
0
        static public void CoreActionToBytes(MemoryByteStream stream, CoreAction action)
        {
            switch (action.Type)
            {
            case CoreRequest.Types.KeyPress:
                stream.Write(_coreActionKeyPress);
                stream.Write(action.Ticks);
                stream.Write(action.KeyCode);
                stream.Write(action.KeyDown);
                break;

            case CoreRequest.Types.Reset:
                stream.Write(_coreActionReset);
                stream.Write(action.Ticks);
                break;

            case CoreRequest.Types.LoadDisc:
                stream.Write(_coreActionLoadDisc);
                stream.Write(action.Ticks);
                stream.Write(action.Drive);
                stream.WriteArray(action.MediaBuffer.GetBytes());
                break;

            case CoreRequest.Types.LoadTape:
                stream.Write(_coreActionLoadTape);
                stream.Write(action.Ticks);
                stream.WriteArray(action.MediaBuffer.GetBytes());
                break;

            case CoreRequest.Types.RunUntil:
                stream.Write(_coreActionRunUntil);
                stream.Write(action.Ticks);
                stream.Write(action.StopTicks);
                break;

            case CoreRequest.Types.LoadCore:
                stream.Write(_coreActionLoadCore);
                stream.Write(action.Ticks);
                stream.WriteArray(action.CoreState.GetBytes());
                break;

            case CoreRequest.Types.CoreVersion:
                stream.Write(_coreActionCoreVersion);
                stream.Write(action.Ticks);
                stream.Write(action.Version);
                break;

            case CoreRequest.Types.CreateSnapshot:
                stream.Write(_coreActionCreateSnapshot);
                stream.Write(action.Ticks);
                stream.Write(action.SnapshotId);
                break;

            case CoreRequest.Types.DeleteSnapshot:
                stream.Write(_coreActionDeleteSnapshot);
                stream.Write(action.Ticks);
                stream.Write(action.SnapshotId);
                break;

            case CoreRequest.Types.RevertToSnapshot:
                stream.Write(_coreActionRevertToSnapshot);
                stream.Write(action.Ticks);
                stream.Write(action.SnapshotId);
                break;

            default:
                throw new Exception(String.Format("Unknown CoreAction type {0}!", action.Type));
            }
        }
示例#27
0
 /// <summary>
 /// Delegate for logging core actions.
 /// </summary>
 /// <param name="core">The core the request was made for.</param>
 /// <param name="request">The original request.</param>
 /// <param name="action">The action taken.</param>
 private void RequestProcessed(Core core, CoreRequest request, CoreAction action)
 {
     Auditors?.Invoke(action);
 }
示例#28
0
        /// <summary>
        /// Delegate for logging core actions.
        /// </summary>
        /// <param name="core">The core the request was made for.</param>
        /// <param name="request">The original request.</param>
        /// <param name="action">The action taken.</param>
        private void RequestProcessed(Core core, CoreRequest request, CoreAction action)
        {
            if (core == _core)
            {
                if (action != null)
                {
                    Auditors?.Invoke(action);

                    if (action.Type != CoreAction.Types.CreateSnapshot &&
                        action.Type != CoreAction.Types.DeleteSnapshot &&
                        action.Type != CoreAction.Types.RevertToSnapshot)
                    {
                        HistoryEvent e = _history.AddCoreAction(action);

                        switch (action.Type)
                        {
                        case CoreRequest.Types.LoadDisc:
                            Status = (action.MediaBuffer.GetBytes() != null) ? "Loaded disc" : "Ejected disc";
                            break;

                        case CoreRequest.Types.LoadTape:
                            Status = (action.MediaBuffer.GetBytes() != null) ? "Loaded tape" : "Ejected tape";
                            break;

                        case CoreRequest.Types.Reset:
                            Status = "Reset";
                            break;
                        }
                    }

                    if (action.Type == CoreAction.Types.RunUntil)
                    {
                        lock (_snapshots)
                        {
                            SnapshotInfo newSnapshot = _snapshots.LastOrDefault();
                            if (newSnapshot != null && action.AudioSamples != null)
                            {
                                newSnapshot.AudioBuffer.Write(action.AudioSamples);
                            }
                        }
                    }
                    else if (action.Type == CoreAction.Types.RevertToSnapshot)
                    {
                        HistoryEvent historyEvent = ((SnapshotInfo)request.UserData).HistoryEvent;
                        if (_history.CurrentEvent != historyEvent)
                        {
                            _history.CurrentEvent = historyEvent;
                        }

                        Display.CopyScreenAsync();
                    }
                    else if (action.Type == CoreAction.Types.CreateSnapshot)
                    {
                        lock (_snapshots)
                        {
                            // Figure out what history event should be set as current if we revert to this snapshot.
                            // If the current event is a RunUntil, it may not be "finalized" yet (i.e. it may still
                            // be updated), so go with its parent.
                            HistoryEvent historyEvent = _history.MostRecentClosedEvent(_history.CurrentEvent);

                            SnapshotInfo newSnapshot = new SnapshotInfo(action.SnapshotId, historyEvent);
                            _snapshots.Add(newSnapshot);

                            while (_snapshots.Count > _snapshotLimit)
                            {
                                SnapshotInfo snapshot = _snapshots[0];
                                _snapshots.RemoveAt(0);
                                _core.PushRequest(CoreRequest.DeleteSnapshot(snapshot.Id));
                            }
                        }
                    }
                }
            }
        }
示例#29
0
 public CoreActionHistoryEvent AddCoreAction(CoreAction coreAction)
 {
     return(AddCoreAction(coreAction, _nextId));
 }
示例#30
0
        internal CoreActionHistoryNode(int id, UInt64 ticks, CoreAction action, HistoryNode parent, DateTime createDate) : base(id, ticks, action, null, parent, createDate)
        {
            CoreAction = action;

            HistoryEvent = new CoreActionHistoryEvent(this);
        }