diff --git a/Reactor/Extensions/StreamExtensions.cs b/Reactor/Extensions/StreamExtensions.cs new file mode 100644 index 0000000..fd884be --- /dev/null +++ b/Reactor/Extensions/StreamExtensions.cs @@ -0,0 +1,81 @@ +using System; +using System.IO; +using System.Runtime.CompilerServices; +using UnhollowerBaseLib; +using UnhollowerBaseLib.Attributes; +using UnhollowerRuntimeLib; + +namespace Reactor.Extensions +{ + [RegisterInIl2Cpp] + public class StreamWrapper : Il2CppSystem.IO.Stream + { + private readonly Stream _stream; + + public StreamWrapper(IntPtr ptr) : base(ptr) { } + + public StreamWrapper(Stream stream) : base(ClassInjector.DerivedConstructorPointer()) + { + ClassInjector.DerivedConstructorBody(this); + _stream = stream; + } + + [HideFromIl2Cpp] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static unsafe Span GetSpan(Il2CppStructArray buffer, int offset, int count) + { + var rawBuffer = (byte*) buffer.Pointer + 4 * IntPtr.Size; + return new Span(rawBuffer + offset, count); + } + + public override int Read(Il2CppStructArray buffer, int offset, int count) + { + return _stream.Read(GetSpan(buffer, offset, count)); + } + + public override void Write(Il2CppStructArray buffer, int offset, int count) + { + _stream.Write(GetSpan(buffer, offset, count)); + } + + public override void Flush() + { + _stream.Flush(); + } + + public override long Seek(long offset, Il2CppSystem.IO.SeekOrigin origin) + { + return _stream.Seek(offset, origin switch + { + Il2CppSystem.IO.SeekOrigin.Begin => SeekOrigin.Begin, + Il2CppSystem.IO.SeekOrigin.Current => SeekOrigin.Current, + Il2CppSystem.IO.SeekOrigin.End => SeekOrigin.End, + _ => throw new ArgumentOutOfRangeException(nameof(origin), origin, null) + }); + } + + public override void SetLength(long value) + { + _stream.SetLength(value); + } + + public override bool CanRead => _stream.CanRead; + public override bool CanSeek => _stream.CanSeek; + public override bool CanWrite => _stream.CanWrite; + public override long Length => _stream.Length; + + public override long Position + { + get => _stream.Position; + set => _stream.Position = value; + } + } + + public static class StreamExtensions + { + /// + /// Wraps a System Stream into an Il2Cpp Stream + /// + public static StreamWrapper AsIl2Cpp(this Stream stream) => new(stream); + } +} diff --git a/Reactor/Reactor.csproj b/Reactor/Reactor.csproj index df09529..c235830 100644 --- a/Reactor/Reactor.csproj +++ b/Reactor/Reactor.csproj @@ -3,6 +3,7 @@ netstandard2.1 latest embedded + true 1.1.0 dev diff --git a/Reactor/Unstrip/DefaultBundle.cs b/Reactor/Unstrip/DefaultBundle.cs index 22ea6f4..29c5f16 100644 --- a/Reactor/Unstrip/DefaultBundle.cs +++ b/Reactor/Unstrip/DefaultBundle.cs @@ -8,7 +8,7 @@ namespace Reactor.Unstrip { public static void Load() { - var bundle = AssetBundle.LoadFromMemory(typeof(ReactorPlugin).Assembly.GetManifestResourceStream("Reactor.Assets.default.bundle").ReadFully()); + var bundle = AssetBundle.LoadFromStream(typeof(ReactorPlugin).Assembly.GetManifestResourceStream("Reactor.Assets.default.bundle").AsIl2Cpp()); var backupShader = bundle.LoadAsset("UI-Default");