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); } } }
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; }
public LoadStateStream(Stream backingStore, long offset, long size, long mask) { _backingStore = backingStore; _backingStoreSS = SpanStream.GetOrBuild(backingStore); _offset = offset; _size = size; _mask = mask; }
/// <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; }
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); } }); }
// 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; } }); }
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++; }); }); } }