示例#1
0
        public unsafe void Capture(int frame)
        {
            Sync();
            if (!_active)
            {
                return;
            }
            if (_masterFrame == -1)
            {
                var sss = new SaveStateStream(this);
                _stateSource.SaveStateBinary(new BinaryWriter(sss));
                (_master, _scratch) = (_scratch, _master);
                _masterLength       = (int)sss.Position;
                _masterFrame        = frame;
                _count++;
                return;
            }
            if (!_buffer.WillCapture(_masterFrame))
            {
                return;
            }

            {
                var sss = new SaveStateStream(this);
                _stateSource.SaveStateBinary(new BinaryWriter(sss));

                Work(() =>
                {
                    _buffer.Capture(_masterFrame, underlyingStream_ =>
                    {
                        var zeldas = SpanStream.GetOrBuild(underlyingStream_);
                        if (_master.Length < _scratch.Length)
                        {
                            var replacement = new byte[_scratch.Length];
                            Array.Copy(_master, replacement, _master.Length);
                            _master = replacement;
                        }

                        var lengthHolder     = _masterLength;
                        var lengthHolderSpan = new ReadOnlySpan <byte>(&lengthHolder, 4);

                        zeldas.Write(lengthHolderSpan);

                        fixed(byte *older_ = _master)
                        fixed(byte *newer_ = _scratch)
                        {
                            int *older       = (int *)older_;
                            int *newer       = (int *)newer_;
                            int lastIndex    = (Math.Min(_masterLength, (int)sss.Position) + 3) / 4;
                            int lastOldIndex = (_masterLength + 3) / 4;
                            int *olderEnd    = older + lastIndex;

                            int *from = older;
                            int *to   = older;

                            while (older < olderEnd)
                            {
                                if (*older++ == *newer++)
                                {
                                    if (to < from)
                                    {
                                        // Save on [to, from]
                                        lengthHolder = (int)(from - to);
                                        zeldas.Write(lengthHolderSpan);
                                        zeldas.Write(new ReadOnlySpan <byte>(to, lengthHolder * 4));
                                    }
                                    to = older;
                                }
                                else
                                {
                                    if (from < to)
                                    {
                                        // encode gap [from, to]
                                        lengthHolder = (int)(to - from) | IS_GAP;
                                        zeldas.Write(lengthHolderSpan);
                                    }
                                    from = older;
                                }
                            }
                            if (from < to)
                            {
                                // encode gap [from, to]
                                lengthHolder = (int)(to - from) | IS_GAP;
                                zeldas.Write(lengthHolderSpan);
                            }
                            if (lastOldIndex > lastIndex)
                            {
                                from += lastOldIndex - lastIndex;
                            }
                            if (to < from)
                            {
                                // Save on [to, from]
                                lengthHolder = (int)(from - to);
                                zeldas.Write(lengthHolderSpan);
                                zeldas.Write(new ReadOnlySpan <byte>(to, lengthHolder * 4));
                            }
                        }

                        (_master, _scratch) = (_scratch, _master);
                        _masterLength       = (int)sss.Position;
                        _masterFrame        = frame;
                        _count++;
                    });
                });
            }
        }