using System; using System.Runtime.InteropServices; using System.Text; namespace UnityFileApi { public class UnityArchiveHandle : SafeHandle { public UnityArchiveHandle() : base(IntPtr.Zero, true) { } public override bool IsInvalid => handle == IntPtr.Zero; protected override bool ReleaseHandle() { return DllWrapper.UnmountArchive(handle) == ReturnCode.Success; } } public class UnityFileHandle : SafeHandle { public UnityFileHandle() : base(IntPtr.Zero, true) { } public override bool IsInvalid => handle == IntPtr.Zero; protected override bool ReleaseHandle() { return DllWrapper.CloseFile(handle) == ReturnCode.Success; } } public class SerializedFileHandle : SafeHandle { public SerializedFileHandle() : base(IntPtr.Zero, true) { } public override bool IsInvalid => handle == IntPtr.Zero; protected override bool ReleaseHandle() { return DllWrapper.CloseSerializedFile(handle) == ReturnCode.Success; } } public class TypeTreeHandle : SafeHandle { public TypeTreeHandle() : base(IntPtr.Zero, true) { } public override bool IsInvalid => handle == IntPtr.Zero; protected override bool ReleaseHandle() { return true; } internal IntPtr Handle => handle; } public enum ReturnCode { Success, AlreadyInitialized, NotInitialized, FileNotFound, FileFormatError, InvalidArgument, HigherSerializedFileVersion, DestinationBufferTooSmall, InvalidObjectId, UnknownError, FileError, ErrorCreatingArchiveFile, ErrorAddingFileToArchive, TypeNotFound, } [Flags] public enum ArchiveNodeFlags { None = 0, Directory = 1 << 0, Deleted = 1 << 1, SerializedFile = 1 << 2, } public enum CompressionType { None, Lzma, Lz4, Lz4HC, }; public enum SeekOrigin { Begin, Current, End, } public enum ExternalReferenceType { NonAssetType, DeprecatedCachedAssetType, SerializedAssetType, MetaAssetType, } [StructLayout(LayoutKind.Sequential)] public struct ObjectInfo { public readonly long Id; public readonly long Offset; public readonly long Size; public readonly int TypeId; } [Flags] public enum TypeTreeFlags { None = 0, IsArray = 1 << 0, IsManagedReference = 1 << 1, IsManagedReferenceRegistry = 1 << 2, IsArrayOfRefs = 1 << 3, } [Flags] public enum TypeTreeMetaFlags { None = 0, AlignBytes = 1 << 14, AnyChildUsesAlignBytes = 1 << 15, } public static class DllWrapper { [DllImport("UnityFileSystemApi", CallingConvention = CallingConvention.Cdecl, EntryPoint = "UFS_Init")] public static extern ReturnCode Init(); [DllImport("UnityFileSystemApi", CallingConvention = CallingConvention.Cdecl, EntryPoint = "UFS_Cleanup")] public static extern ReturnCode Cleanup(); [DllImport("UnityFileSystemApi", CallingConvention = CallingConvention.Cdecl, EntryPoint = "UFS_MountArchive")] public static extern ReturnCode MountArchive([MarshalAs(UnmanagedType.LPUTF8Str)] string path, [MarshalAs(UnmanagedType.LPUTF8Str)] string mountPoint, out UnityArchiveHandle handle); [DllImport("UnityFileSystemApi", CallingConvention = CallingConvention.Cdecl, EntryPoint = "UFS_UnmountArchive")] public static extern ReturnCode UnmountArchive(IntPtr handle); [DllImport("UnityFileSystemApi", CallingConvention = CallingConvention.Cdecl, EntryPoint = "UFS_GetArchiveNodeCount")] public static extern ReturnCode GetArchiveNodeCount(UnityArchiveHandle handle, out int count); [DllImport("UnityFileSystemApi", CallingConvention = CallingConvention.Cdecl, EntryPoint = "UFS_GetArchiveNode")] public static extern ReturnCode GetArchiveNode(UnityArchiveHandle handle, int nodeIndex, StringBuilder path, int pathLen, out long size, out ArchiveNodeFlags flags); [DllImport("UnityFileSystemApi", CallingConvention = CallingConvention.Cdecl, EntryPoint = "UFS_CreateArchive")] public static extern ReturnCode CreateArchive([MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPUTF8Str)] string[] sourceFiles, [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPUTF8Str)] string[] aliases, bool[] isSerializedFile, int count, [MarshalAs(UnmanagedType.LPUTF8Str)] string archiveFile, CompressionType compression, out int crc); [DllImport("UnityFileSystemApi", CallingConvention = CallingConvention.Cdecl, EntryPoint = "UFS_OpenFile")] public static extern ReturnCode OpenFile([MarshalAs(UnmanagedType.LPUTF8Str)] string path, out UnityFileHandle handle); [DllImport("UnityFileSystemApi", CallingConvention = CallingConvention.Cdecl, EntryPoint = "UFS_ReadFile")] public static extern ReturnCode ReadFile(UnityFileHandle handle, long size, [MarshalAs(UnmanagedType.LPArray)] byte[] buffer, out long actualSize); [DllImport("UnityFileSystemApi", CallingConvention = CallingConvention.Cdecl, EntryPoint = "UFS_SeekFile")] public static extern ReturnCode SeekFile(UnityFileHandle handle, long offset, SeekOrigin origin, out long newPosition); [DllImport("UnityFileSystemApi", CallingConvention = CallingConvention.Cdecl, EntryPoint = "UFS_GetFileSize")] public static extern ReturnCode GetFileSize(UnityFileHandle handle, out long size); [DllImport("UnityFileSystemApi", CallingConvention = CallingConvention.Cdecl, EntryPoint = "UFS_CloseFile")] public static extern ReturnCode CloseFile(IntPtr handle); [DllImport("UnityFileSystemApi", CallingConvention = CallingConvention.Cdecl, EntryPoint = "UFS_OpenSerializedFile")] public static extern ReturnCode OpenSerializedFile([MarshalAs(UnmanagedType.LPUTF8Str)] string path, out SerializedFileHandle handle); [DllImport("UnityFileSystemApi", CallingConvention = CallingConvention.Cdecl, EntryPoint = "UFS_CloseSerializedFile")] public static extern ReturnCode CloseSerializedFile(IntPtr handle); [DllImport("UnityFileSystemApi", CallingConvention = CallingConvention.Cdecl, EntryPoint = "UFS_GetExternalReferenceCount")] public static extern ReturnCode GetExternalReferenceCount(SerializedFileHandle handle, out int count); [DllImport("UnityFileSystemApi", CallingConvention = CallingConvention.Cdecl, EntryPoint = "UFS_GetExternalReference")] public static extern ReturnCode GetExternalReference(SerializedFileHandle handle, int index, StringBuilder path, int pathLen, StringBuilder guid, out ExternalReferenceType type); [DllImport("UnityFileSystemApi", CallingConvention = CallingConvention.Cdecl, EntryPoint = "UFS_GetObjectCount")] public static extern ReturnCode GetObjectCount(SerializedFileHandle handle, out int count); [DllImport("UnityFileSystemApi", CallingConvention = CallingConvention.Cdecl, EntryPoint = "UFS_GetObjectInfo")] public static extern ReturnCode GetObjectInfo(SerializedFileHandle handle, [In, Out] ObjectInfo[] objectData, int len); [DllImport("UnityFileSystemApi", CallingConvention = CallingConvention.Cdecl, EntryPoint = "UFS_GetTypeTree")] public static extern ReturnCode GetTypeTree(SerializedFileHandle handle, long objectId, out TypeTreeHandle typeTree); [DllImport("UnityFileSystemApi", CallingConvention = CallingConvention.Cdecl, EntryPoint = "UFS_GetRefTypeTypeTree")] public static extern ReturnCode GetRefTypeTypeTree(SerializedFileHandle handle, [MarshalAs(UnmanagedType.LPUTF8Str)] string className, [MarshalAs(UnmanagedType.LPUTF8Str)] string namespaceName, [MarshalAs(UnmanagedType.LPUTF8Str)] string assemblyName, out TypeTreeHandle typeTree); [DllImport("UnityFileSystemApi", CallingConvention = CallingConvention.Cdecl, EntryPoint = "UFS_GetTypeTreeNodeInfo")] public static extern ReturnCode GetTypeTreeNodeInfo(TypeTreeHandle handle, int node, StringBuilder type, int typeLen, StringBuilder name, int nameLen, out int offset, out int size, [MarshalAs(UnmanagedType.U4)] out TypeTreeFlags flags, [MarshalAs(UnmanagedType.U4)] out TypeTreeMetaFlags metaFlags, out int firstChildNode, out int nextNode); } }