Example #1
0
 private void SaveStateBodyBinary(BinaryWriter writer)
 {
     writer.Write(Count);
     for (var i = _firstStateIndex; i != _nextStateIndex; i = (i + 1) & STATEMASK)
     {
         writer.Write(_states[i].Frame);
         writer.Write(_states[i].Size);
     }
     if (Count != 0)
     {
         var startByte  = _states[_firstStateIndex].Start;
         var endByte    = (_states[HeadStateIndex].Start + _states[HeadStateIndex].Size) & _sizeMask;
         var destStream = SpanStream.GetOrBuild(writer.BaseStream);
         if (startByte > endByte)
         {
             _backingStore.Position = startByte;
             WaterboxUtils.CopySome(_backingStore, writer.BaseStream, Size - startByte);
             startByte = 0;
         }
         {
             _backingStore.Position = startByte;
             WaterboxUtils.CopySome(_backingStore, writer.BaseStream, endByte - startByte);
         }
     }
 }
Example #2
0
        private unsafe void RefillMaster(ZwinderBuffer.StateInformation state)
        {
            var lengthHolder     = 0;
            var lengthHolderSpan = new Span <byte>(&lengthHolder, 4);
            var zeldas           = SpanStream.GetOrBuild(state.GetReadStream());

            zeldas.Read(lengthHolderSpan);
            _masterLength = lengthHolder;
            fixed(byte *buffer_ = _master)
            {
                int *buffer = (int *)buffer_;

                while (zeldas.Read(lengthHolderSpan) == 4)
                {
                    if ((lengthHolder & IS_GAP) != 0)
                    {
                        buffer += lengthHolder & ~IS_GAP;
                    }
                    else
                    {
                        zeldas.Read(new Span <byte>(buffer, lengthHolder * 4));
                        buffer += lengthHolder;
                    }
                }
            }

            _masterFrame = state.Frame;
        }
Example #3
0
 public LoadStateStream(Stream backingStore, long offset, long size, long mask)
 {
     _backingStore   = backingStore;
     _backingStoreSS = SpanStream.GetOrBuild(backingStore);
     _offset         = offset;
     _size           = size;
     _mask           = mask;
 }
Example #4
0
 /// <summary>
 ///
 /// </summary>
 /// <param name="backingStore">The ringbuffer to write into</param>
 /// <param name="offset">Offset into the buffer to start writing (and treat as position 0 in the stream)</param>
 /// <param name="mask">Buffer size mask, used to wrap values in the ringbuffer correctly</param>
 /// <param name="notifySize">
 /// If the stream will exceed this size, notifySizeReached must be called before clobbering any data
 /// </param>
 /// <param name="notifySizeReached">
 /// The callback that will be called when notifySize is about to be exceeded.  Can either return a new larger notifySize,
 /// or abort processing with an IOException.  This must fail if size is going to exceed buffer.Length, as nothing else
 /// is preventing that case.
 /// </param>
 public SaveStateStream(Stream backingStore, long offset, long mask, long notifySize, Func <long> notifySizeReached)
 {
     _backingStore      = backingStore;
     _backingStoreSS    = SpanStream.GetOrBuild(backingStore);
     _offset            = offset;
     _mask              = mask;
     _notifySize        = notifySize;
     _notifySizeReached = notifySizeReached;
 }
Example #5
0
        public static ReadCallback MakeCallbackForReader(Stream s)
        {
            var ss = SpanStream.GetOrBuild(s);

            return((_unused, data, size) =>
            {
                try
                {
                    var count = (int)size;
                    var n = ss.Read(new Span <byte>((void *)data, count));
                    return Z.SS(n);
                }
                catch
                {
                    return Z.SS(-1);
                }
            });
        }
Example #6
0
        // public delegate UIntPtr /*MissingFileResult*/ FileCallback(IntPtr userdata, UIntPtr /*string*/ name);

        public static WriteCallback MakeCallbackForWriter(Stream s)
        {
            var ss = SpanStream.GetOrBuild(s);

            return((_unused, data, size) =>
            {
                try
                {
                    var count = (int)size;
                    ss.Write(new ReadOnlySpan <byte>((void *)data, (int)size));
                    return 0;
                }
                catch
                {
                    return -1;
                }
            });
        }
Example #7
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++;
                    });
                });
            }
        }