示例#1
0
        public void Initialize(IStatable statableCore, RewindConfig rewindConfig)
        {
            Uninitialize();

            _statableCore = statableCore;

            int stateSize = _statableCore.CloneSavestate().Length;

            if (stateSize >= rewindConfig.LargeStateSize)
            {
                RewindEnabled   = rewindConfig.EnabledLarge;
                RewindFrequency = rewindConfig.FrequencyLarge;
            }
            else if (stateSize >= rewindConfig.MediumStateSize)
            {
                RewindEnabled   = rewindConfig.EnabledMedium;
                RewindFrequency = rewindConfig.FrequencyMedium;
            }
            else
            {
                RewindEnabled   = rewindConfig.EnabledSmall;
                RewindFrequency = rewindConfig.FrequencySmall;
            }

            _rewindDeltaEnable = rewindConfig.UseDelta;

            if (RewindActive)
            {
                var capacity = rewindConfig.BufferSize * 1024L * 1024L;
                _rewindBuffer = new StreamBlobDatabase(rewindConfig.OnDisk, capacity, BufferManage);
                _rewindThread = new RewindThreader(CaptureInternal, RewindInternal, rewindConfig.IsThreaded);
            }
        }
示例#2
0
        private int _stateSizeCategory = 1;         // 1 = small, 2 = med, 3 = large // TODO: enum

        public RewindConfig(Rewinder rewinder, Config config, IStatable statableCore)
        {
            _rewinder     = rewinder;
            _config       = config;
            _statableCore = statableCore;
            InitializeComponent();
        }
示例#3
0
        public void Attach(IEmulator emulator)
        {
            if (!_emulator.IsNull())
            {
                throw new InvalidOperationException("A core has already been attached!");
            }

            if (!emulator.HasSavestates())
            {
                throw new InvalidOperationException($"A core must be able to provide an {nameof(IStatable)} service");
            }

            _emulator = emulator;
            _core     = emulator.AsStatable();

            _decay = new StateManagerDecay(_movie, this);

            _expectedStateSizeInMb = _core.CloneSavestate().Length / (double)(1024 * 1024);
            if (_expectedStateSizeInMb.HawkFloatEquality(0))
            {
                throw new InvalidOperationException("Savestate size can not be zero!");
            }

            // don't erase states if they exist already (already loaded)
            if ((_states == null) || (_states.Capacity == 0))
            {
                _states = new SortedList <int, byte[]>(MaxStates);
            }

            UpdateStateFrequency();
        }
示例#4
0
        public void Capture(int frame, IStatable source, bool force = false)
        {
            if (frame <= Last)
            {
                CaptureHighPriority(frame, source);
            }

            _current.Capture(frame,
                             s => source.SaveStateBinary(new BinaryWriter(s)),
                             index =>
            {
                var state = _current.GetState(index);
                _recent.Capture(state.Frame,
                                s => state.GetReadStream().CopyTo(s),
                                index2 =>
                {
                    var state2 = _recent.GetState(index2);
                    var from   = _ancient.Count > 0 ? _ancient[_ancient.Count - 1].Key : 0;
                    if (state2.Frame - from >= _ancientInterval)
                    {
                        var ms = new MemoryStream();
                        state2.GetReadStream().CopyTo(ms);
                        _ancient.Add(new KeyValuePair <int, byte[]>(state2.Frame, ms.ToArray()));
                    }
                });
            },
                             force);
        }
示例#5
0
        public void Attach(IEmulator emulator)
        {
            // TODO: we aren't ready for this, attach is called when converting a bk2 to tasproj and again to officially load the emulator
            //if (!_emulator.IsNull())
            //{
            //	throw new InvalidOperationException("A core has already been attached!");
            //}

            if (!emulator.HasSavestates())
            {
                throw new InvalidOperationException($"A core must be able to provide an {nameof(IStatable)} service");
            }

            _emulator = emulator;
            _core     = emulator.AsStatable();

            _decay = new StateManagerDecay(_movie, this);

            _expectedStateSizeInMb = _core.CloneSavestate().Length / (double)(1024 * 1024);
            if (_expectedStateSizeInMb.HawkFloatEquality(0))
            {
                throw new InvalidOperationException("Savestate size can not be zero!");
            }

            _states = new SortedList <int, byte[]>(MaxStates);

            UpdateStateFrequency();
        }
示例#6
0
 public RewindConfig(Config config, Action recreateRewinder, Func <IRewinder> getRewinder, IStatable statableCore)
 {
     _config           = config;
     _recreateRewinder = recreateRewinder;
     _getRewinder      = getRewinder;
     _statableCore     = statableCore;
     InitializeComponent();
     btnResetCompression.Image = Properties.Resources.reboot;
 }
示例#7
0
        public static byte[] CloneSavestate(this IStatable core)
        {
            using var ms = new MemoryStream();
            using var bw = new BinaryWriter(ms);
            core.SaveStateBinary(bw);
            bw.Flush();
            var stateBuffer = ms.ToArray();

            bw.Close();
            return(stateBuffer);
        }
示例#8
0
        public static void SaveStateText(this IStatable core, TextWriter writer)
        {
            if (core is ITextStatable textCore)
            {
                textCore.SaveStateText(writer);
            }

            var temp = core.CloneSavestate();

            temp.SaveAsHexFast(writer);
        }
        internal void CaptureReserved(int frame, IStatable source)
        {
            if (_reserved.ContainsKey(frame))
            {
                return;
            }

            var ms = new MemoryStream();

            source.SaveStateBinary(new BinaryWriter(ms));
            _reserved.Add(frame, ms.ToArray());
            AddStateCache(frame);
        }
        public SavestateFile(IEmulator emulator, IMovieSession movieSession, IDictionary <string, object> userBag)
        {
            if (!emulator.HasSavestates())
            {
                throw new InvalidOperationException("The provided core must have savestates");
            }

            _emulator = emulator;
            _statable = emulator.AsStatable();
            if (emulator.HasVideoProvider())
            {
                _videoProvider = emulator.AsVideoProvider();
            }

            _movieSession = movieSession;
            _userBag      = userBag;
        }
        private void CaptureGap(int frame, IStatable source)
        {
            // We need to do this here for the following scenario
            // We are currently far enough in the game that there is a large "ancient interval" section
            // The user navigates to a frame after ancient interval 2, replay happens and we start filling gaps
            // Then the user, still without having made an edit, navigates to a frame before ancient interval 2, but after ancient interval 1
            // Without this logic, we end up with out of order states
            // We cannot use InvalidateGaps because that does not address the state cache or check for reserved states.
            for (int i = _gapFiller.Count - 1; i >= 0; i--)
            {
                var lastGap = _gapFiller.GetState(i);
                if (lastGap.Frame < frame)
                {
                    break;
                }

                if (_reserveCallback(lastGap.Frame))
                {
                    AddToReserved(lastGap);
                }
                else
                {
                    StateCache.Remove(lastGap.Frame);
                }

                _gapFiller.InvalidateEnd(i);
            }

            _gapFiller.Capture(
                frame, s =>
            {
                AddStateCache(frame);
                source.SaveStateBinary(new BinaryWriter(s));
            },
                index =>
            {
                var state = _gapFiller.GetState(index);
                StateCache.Remove(state.Frame);

                if (_reserveCallback(state.Frame))
                {
                    AddToReserved(state);
                    return;
                }
            });
        }
示例#12
0
        public static void LoadStateText(this IStatable core, TextReader reader)
        {
            if (core is ITextStatable textCore)
            {
                textCore.LoadStateText(reader);
            }

            string hex = reader.ReadLine();

            if (hex != null)
            {
                var state = new byte[hex.Length / 2];
                state.ReadFromHexFast(hex);
                using var ms = new MemoryStream(state);
                using var br = new BinaryReader(ms);
                core.LoadStateBinary(br);
            }
        }
        private ZwinderStateManager CreateSmallZwinder(IStatable ss)
        {
            var zw = new ZwinderStateManager(new ZwinderStateManagerSettings
            {
                CurrentBufferSize        = 1,
                CurrentTargetFrameLength = 10000,

                RecentBufferSize        = 1,
                RecentTargetFrameLength = 100000,

                AncientStateInterval = 50000
            }, f => false);

            var ms = new MemoryStream();

            ss.SaveStateBinary(new BinaryWriter(ms));
            zw.Engage(ms.ToArray());
            return(zw);
        }
示例#14
0
        private void CaptureGap(int frame, IStatable source)
        {
            // We need to do this here for the following scenario
            // We are currently far enough in the game that there is a large "ancient interval" section
            // The user navigates to a frame after ancient interval 2, replay happens and we start filling gaps
            // Then the user, still without having made an edit, navigates to a frame before ancient interval 2, but after ancient interval 1
            // Without this logic, we end up with out of order states
            if (_gapFiller.Count > 0 && frame < GapStates().First().Frame)
            {
                InvalidateGaps(frame);
            }

            _gapFiller.Capture(
                frame, s =>
            {
                StateCache.Add(frame);
                source.SaveStateBinary(new BinaryWriter(s));
            },
                index => StateCache.Remove(index));
        }
示例#15
0
文件: Zwinder.cs 项目: gocha/BizHawk
 public Zwinder(IStatable stateSource, IRewindSettings settings)
 {
     _buffer      = new ZwinderBuffer(settings);
     _stateSource = stateSource;
     Active       = true;
 }
示例#16
0
 public void CaptureHighPriority(int frame, IStatable source)
 {
     _highPriority.Capture(frame, s => source.SaveStateBinary(new BinaryWriter(s)));
 }
        public void Capture(int frame, IStatable source, bool force = false)
        {
            // We already have this state, no need to capture
            if (StateCache.Contains(frame))
            {
                return;
            }

            if (_reserveCallback(frame))
            {
                CaptureReserved(frame, source);
                return;
            }

            // We do not want to consider reserved states for a notion of Last
            // reserved states can include future states in the case of branch states
            if ((frame <= LastRing && NeedsGap(frame)) || force)
            {
                // We use the gap buffer for forced capture to avoid crowding the "current" buffer and thus reducing it's actual span of covered frames.
                CaptureGap(frame, source);
                return;
            }

            _current.Capture(frame,
                             s =>
            {
                source.SaveStateBinary(new BinaryWriter(s));
                AddStateCache(frame);
            },
                             index =>
            {
                var state = _current.GetState(index);
                StateCache.Remove(state.Frame);

                // If this is a reserved state, go ahead and reserve instead of potentially trying to force it into recent, for further eviction logic later
                if (_reserveCallback(state.Frame))
                {
                    AddToReserved(state);
                    return;
                }

                _recent.Capture(state.Frame,
                                s =>
                {
                    state.GetReadStream().CopyTo(s);
                    AddStateCache(state.Frame);
                },
                                index2 =>
                {
                    var state2 = _recent.GetState(index2);
                    StateCache.Remove(state2.Frame);

                    var isReserved = _reserveCallback(state2.Frame);

                    // Add to reserved if reserved, or if it matches an "ancient" state consideration
                    if (isReserved || !HasNearByReserved(state2.Frame))
                    {
                        AddToReserved(state2);
                    }
                });
            },
                             force);
        }
示例#18
0
 public static void LoadStateBinary(this IStatable core, byte[] state)
 {
     using var ms = new MemoryStream(state, false);
     using var br = new BinaryReader(ms);
     core.LoadStateBinary(br);
 }
示例#19
0
 public static void LoadStateText(this IStatable core, string textState)
 {
     core.LoadStateText(new StringReader(textState));
 }
示例#20
0
 /// <summary>
 ///
 /// </summary>
 /// <param name="stateble"></param>
 public StateController(IStatable statable)
 {
     this.Statable = statable;
 }
示例#21
0
 public float ChanceOfApply(IStatable target)
 {
     //more AGL RET STB you have, more chance to dodge this shit
     return
         ((float)(90 * Math.Pow(2.7, -(target.Aglity + target.Reticence + target.Stability))));
 }