Decompiled source of R2API Animations v1.0.0
plugins/R2API.Animations/R2API.Animations.dll
Decompiled a month agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security; using System.Security.Cryptography; using System.Security.Permissions; using AssetsTools.NET; using AssetsTools.NET.Extra; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using Microsoft.CodeAnalysis; using R2API.AutoVersionGen; using R2API.Models; using R2API.NativeStructs; using RoR2; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("R2API.Animations")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+78685d44fb9687e5029dac97cb080a70cb7ae71f")] [assembly: AssemblyProduct("R2API.Animations")] [assembly: AssemblyTitle("R2API.Animations")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace System.Diagnostics.CodeAnalysis { [AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inherited = false, AllowMultiple = true)] [ExcludeFromCodeCoverage] [DebuggerNonUserCode] internal sealed class MemberNotNullAttribute : Attribute { public string[] Members { get; } public MemberNotNullAttribute(string member) { Members = new string[1] { member }; } public MemberNotNullAttribute(params string[] members) { Members = members; } } [AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inherited = false, AllowMultiple = true)] [ExcludeFromCodeCoverage] [DebuggerNonUserCode] internal sealed class MemberNotNullWhenAttribute : Attribute { public bool ReturnValue { get; } public string[] Members { get; } public MemberNotNullWhenAttribute(bool returnValue, string member) { ReturnValue = returnValue; Members = new string[1] { member }; } public MemberNotNullWhenAttribute(bool returnValue, params string[] members) { ReturnValue = returnValue; Members = members; } } } namespace R2API { [AutoVersion] public static class AnimationsAPI { public const string PluginGUID = "com.bepis.r2api.animations"; public const string PluginName = "R2API.Animations"; private const string bundleExtension = ".bundle"; private const string hashExtension = ".hash"; private const string dummyBundleName = "dummy_controller_bundle"; private const long dummyAnimatorControllerPathID = -27250459394986890L; private const string dummyAnimatorControllerPath = "assets/dummycontroller.controller"; private static readonly Dictionary<(string, RuntimeAnimatorController), List<AnimatorModifications>> controllerModifications = new Dictionary<(string, RuntimeAnimatorController), List<AnimatorModifications>>(); private static readonly Dictionary<RuntimeAnimatorController, List<Animator>> controllerToAnimators = new Dictionary<RuntimeAnimatorController, List<Animator>>(); private static readonly List<Object> cache = new List<Object>(); private static bool _hooksEnabled = false; private static bool _requestsDone = false; public const string PluginVersion = "1.0.0"; internal static void SetHooks() { if (!_hooksEnabled) { RoR2Application.onLoad = (Action)Delegate.Combine(RoR2Application.onLoad, new Action(OnLoad)); _hooksEnabled = true; } } internal static void UnsetHooks() { RoR2Application.onLoad = (Action)Delegate.Remove(RoR2Application.onLoad, new Action(OnLoad)); _hooksEnabled = false; } private static void OnLoad() { NativeHelpers.Init(); ApplyModifications(); } public static void AddModifications(string sourceBundlePath, RuntimeAnimatorController sourceAnimatorController, AnimatorModifications modifications) { SetHooks(); controllerModifications.GetOrAddDefault((sourceBundlePath, sourceAnimatorController), () => new List<AnimatorModifications>()).Add(modifications); } public static void AddAnimatorController(Animator animator, RuntimeAnimatorController controller) { SetHooks(); controllerToAnimators.GetOrAddDefault(controller, () => new List<Animator>()).Add(animator); } internal static void ApplyModifications() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown AssetsManager val = new AssetsManager(); string text = Path.Combine(Path.GetDirectoryName(((BaseUnityPlugin)AnimationsPlugin.Instance).Info.Location), "dummy_controller_bundle"); foreach (KeyValuePair<(string, RuntimeAnimatorController), List<AnimatorModifications>> controllerModification in controllerModifications) { controllerModification.Deconstruct(out var key, out var value); (string, RuntimeAnimatorController) tuple = key; string item = tuple.Item1; RuntimeAnimatorController item2 = tuple.Item2; List<AnimatorModifications> modifications = value; long assetPathID = NativeHelpers.GetAssetPathID((Object)(object)item2); string text2 = Path.Combine(Paths.CachePath, "R2API.Animations", string.Format("{0}_{1}{2}", Path.GetFileName(item), assetPathID, ".bundle")); string text3 = Path.Combine(Paths.CachePath, "R2API.Animations", string.Format("{0}_{1}{2}", Path.GetFileName(item), assetPathID, ".hash")); bool value2 = AnimationsPlugin.IgnoreCache.Value; string hash = null; if (value2 || !CachedBundleExists(text2, text3, assetPathID, modifications, out hash)) { BundleFileInstance val2 = val.LoadBundleFile(item, true); AssetsFileInstance assetFile = val.LoadAssetsFileFromBundle(val2, 0, false); BundleFileInstance val3 = val.LoadBundleFile(text, true); AssetsFileInstance val4 = val.LoadAssetsFileFromBundle(val3, 0, false); new ModificationsBundleCreator(val, assetFile, assetPathID, val4, val3, -27250459394986890L, modifications, text2).Run(); if (!value2) { File.WriteAllText(text3, hash); } val.UnloadAssetsFile(val4); val.UnloadBundleFile(val3); } RuntimeAnimatorController val5 = AssetBundle.LoadFromFile(text2).LoadAsset<RuntimeAnimatorController>("assets/dummycontroller.controller"); if (controllerToAnimators.TryGetValue(item2, out List<Animator> value3)) { foreach (Animator item3 in value3) { item3.runtimeAnimatorController = val5; } } cache.Add((Object)(object)item2); cache.Add((Object)(object)val5); } val.UnloadAll(true); controllerModifications.Clear(); controllerToAnimators.Clear(); } private static bool CachedBundleExists(string modifiedBundlePath, string hashPath, long sourceAnimatorControllerPathID, List<AnimatorModifications> modifications, out string hash) { using (MD5 mD = MD5.Create()) { using MemoryStream memoryStream = new MemoryStream(); using BinaryWriter binaryWriter = new BinaryWriter(memoryStream); binaryWriter.Write(RoR2Application.buildId); binaryWriter.Write(sourceAnimatorControllerPathID); foreach (AnimatorModifications modification in modifications) { modification.WriteBinary(binaryWriter); } byte[] array = mD.ComputeHash(memoryStream); hash = BitConverter.ToString(array); } if (!File.Exists(modifiedBundlePath)) { return false; } if (!File.Exists(hashPath)) { return false; } string text = File.ReadAllText(hashPath); return hash == text; } } [BepInPlugin("com.bepis.r2api.animations", "R2API.Animations", "1.0.0")] public sealed class AnimationsPlugin : BaseUnityPlugin { internal static AnimationsPlugin Instance { get; private set; } internal static ManualLogSource Logger { get; private set; } internal static ConfigEntry<bool> IgnoreCache { get; private set; } private void Awake() { Instance = this; Logger = ((BaseUnityPlugin)this).Logger; IgnoreCache = ((BaseUnityPlugin)this).Config.Bind<bool>("Dev", "IgnoreCache", false, "Always generate new bundles with modifications"); } private void OnDestroy() { AnimationsAPI.UnsetHooks(); } } public class AnimatorModifications { public string Key { get; } public Dictionary<string, State> NewStates { get; } = new Dictionary<string, State>(); public Dictionary<(string, string), Transition> NewTransitions { get; } = new Dictionary<(string, string), Transition>(); public List<Parameter> NewParameters { get; } = new List<Parameter>(); public AnimatorModifications(BepInPlugin plugin) { Key = $"{plugin.GUID};{plugin.Version}"; } public void WriteBinary(BinaryWriter writer) { writer.Write(Key); foreach (var (value, state2) in NewStates) { writer.Write(value); state2.WriteBinary(writer); } foreach (KeyValuePair<(string, string), Transition> newTransition in NewTransitions) { newTransition.Deconstruct(out var key, out var value2); (string, string) tuple = key; string item = tuple.Item1; string item2 = tuple.Item2; Transition transition = value2; writer.Write(item); writer.Write(item2); transition.WriteBinary(writer); } foreach (Parameter newParameter in NewParameters) { newParameter.WriteBinary(writer); } } } internal static class Extensions { public static TValue GetOrAddDefault<TKey, TValue>(this Dictionary<TKey, TValue> dict, TKey key, Func<TValue> defaultValueFunc) { if (dict.TryGetValue(key, out TValue value)) { return value; } return dict[key] = defaultValueFunc(); } } internal class ModificationsBundleCreator { private readonly AssetsManager manager; private readonly AssetsFileInstance assetFile; private readonly long sourceAnimatorControllerPathID; private readonly AssetsFileInstance dummyAssetFile; private readonly BundleFileInstance dummyBundleFile; private readonly long dummyAnimatorControllerPathID; private readonly List<AnimatorModifications> modifications; private readonly string modifiedBundlePath; private readonly List<string> dependencies = new List<string>(); private readonly HashSet<string> names = new HashSet<string>(); private AssetTypeValueField baseField; public ModificationsBundleCreator(AssetsManager manager, AssetsFileInstance assetFile, long sourceAnimatorControllerPathID, AssetsFileInstance dummyAssetFile, BundleFileInstance dummyBundleFile, long dummyAnimatorControllerPathID, List<AnimatorModifications> modifications, string modifiedBundlePath) { this.manager = manager; this.assetFile = assetFile; this.sourceAnimatorControllerPathID = sourceAnimatorControllerPathID; this.dummyAssetFile = dummyAssetFile; this.dummyBundleFile = dummyBundleFile; this.dummyAnimatorControllerPathID = dummyAnimatorControllerPathID; this.modifications = modifications; this.modifiedBundlePath = modifiedBundlePath; } public void Run() { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) AssetExternal extAsset = manager.GetExtAsset(assetFile, 0, sourceAnimatorControllerPathID, false, (AssetReadFlags)0); baseField = extAsset.baseField; RemapPPtrs(); AddParameters(); AddStates(); AddTransitions(); AddTOS(); SetExternals(); SaveBundle(); } private void AddParameters() { HashSet<uint> hashSet = new HashSet<uint>(); AssetTypeValueField obj = baseField["m_Controller"]; AssetTypeValueField val = obj["m_Values.data.m_ValueArray.Array"]; AssetTypeValueField obj2 = obj["m_DefaultValues.data"]; AssetTypeValueField val2 = obj2["m_BoolValues.Array"]; AssetTypeValueField val3 = obj2["m_FloatValues.Array"]; AssetTypeValueField val4 = obj2["m_IntValues.Array"]; foreach (AssetTypeValueField item in val) { hashSet.Add(item["m_ID"].AsUInt); } foreach (AnimatorModifications modification in modifications) { List<Parameter> newParameters = modification.NewParameters; if (newParameters == null) { continue; } foreach (Parameter item2 in newParameters) { uint num = (uint)Animator.StringToHash(item2.Name); if (!hashSet.Add(num)) { AnimationsPlugin.Logger.LogError((object)("Parameter " + item2.Name + " already exists for " + baseField["m_Name"].AsString)); continue; } int count; switch (item2.Type) { case ParameterType.Float: { count = val3.Children.Count; AssetTypeValueField val7 = ValueBuilder.DefaultValueFieldFromTemplate(val3.TemplateField.Children[1]); val7.AsFloat = item2.Value; val3.Children.Add(val7); break; } case ParameterType.Int: { count = val4.Children.Count; AssetTypeValueField val6 = ValueBuilder.DefaultValueFieldFromTemplate(val4.TemplateField.Children[1]); val6.AsInt = item2.Value; val4.Children.Add(val6); break; } case ParameterType.Bool: case ParameterType.Trigger: { count = val2.Children.Count; AssetTypeValueField val5 = ValueBuilder.DefaultValueFieldFromTemplate(val2.TemplateField.Children[1]); val5.AsBool = item2.Value; val2.Children.Add(val5); break; } default: AnimationsPlugin.Logger.LogError((object)$"Not supported parameter type {item2.Type}"); continue; } AssetTypeValueField val8 = ValueBuilder.DefaultValueFieldFromTemplate(val.TemplateField.Children[1]); val8["m_ID"].AsUInt = num; val8["m_Type"].AsUInt = (uint)item2.Type; val8["m_Index"].AsUInt = (uint)count; val.Children.Add(val8); names.Add(item2.Name); } } } private void AddStates() { AssetTypeValueField val = baseField["m_AnimationClips.Array"]; AssetTypeValueField val2 = baseField["m_Controller"]; string asString = baseField["m_Name"].AsString; foreach (AnimatorModifications modification in modifications) { foreach (KeyValuePair<string, State> newState in modification.NewStates) { newState.Deconstruct(out var key, out var value); string text = key; State state = value; uint layerHash = (uint)Animator.StringToHash(text); AssetTypeValueField val3 = ((IEnumerable<AssetTypeValueField>)val2["m_LayerArray.Array"]).FirstOrDefault((Func<AssetTypeValueField, bool>)((AssetTypeValueField f) => f["data.m_Binding"].AsUInt == layerHash)); if (val3 == null) { AnimationsPlugin.Logger.LogError((object)("Layer \"" + text + "\" not found for a controller \"" + asString + "\". Mod: " + modification.Key)); continue; } uint asUInt = val3["data.m_StateMachineIndex"].AsUInt; long assetPathID = NativeHelpers.GetAssetPathID((Object)(object)state.Clip); BundleFileInstance val4 = manager.LoadBundleFile(state.ClipBundlePath, true); AssetsFileInstance val5 = manager.LoadAssetsFileFromBundle(val4, 0, false); string item = "archive:/" + val5.name + "/" + val5.name; int num = dependencies.IndexOf(item); if (num == -1) { num = dependencies.Count; dependencies.Add(item); } num++; int count = val.Children.Count; AssetTypeValueField val6 = ValueBuilder.DefaultValueFieldFromTemplate(val.TemplateField.Children[1]); val6["m_FileID"].AsInt = num; val6["m_PathID"].AsLong = assetPathID; val.Children.Add(val6); AssetTypeValueField obj = val2["m_StateMachineArray.Array"][(int)asUInt]; uint asUInt2 = (uint)Animator.StringToHash(state.Name); string text2 = text + "." + state.Name; uint asUInt3 = (uint)Animator.StringToHash(text2); uint asUInt4 = (uint)Animator.StringToHash(state.Tag); uint asUInt5 = (uint)Animator.StringToHash(state.SpeedParam); uint asUInt6 = (uint)Animator.StringToHash(state.MirrorParam); uint asUInt7 = (uint)Animator.StringToHash(state.CycleOffsetParam); uint asUInt8 = (uint)Animator.StringToHash(state.TimeParam); AssetTypeValueField val7 = obj["data.m_StateConstantArray.Array"]; AssetTypeValueField val8 = ValueBuilder.DefaultValueFieldFromTemplate(val7.TemplateField.Children[1]); AssetTypeValueField obj2 = val8["data"]; obj2["m_NameID"].AsUInt = asUInt2; obj2["m_PathID"].AsUInt = asUInt3; obj2["m_FullPathID"].AsUInt = asUInt3; obj2["m_TagID"].AsUInt = asUInt4; obj2["m_SpeedParamID"].AsUInt = asUInt5; obj2["m_MirrorParamID"].AsUInt = asUInt6; obj2["m_CycleOffsetParamID"].AsUInt = asUInt7; obj2["m_TimeParamID"].AsUInt = asUInt8; obj2["m_Speed"].AsFloat = state.Speed; obj2["m_CycleOffset"].AsFloat = state.CycleOffset; obj2["m_IKOnFeet"].AsBool = state.IKOnFeet; obj2["m_WriteDefaultValues"].AsBool = state.WriteDefaultValues; obj2["m_Loop"].AsBool = state.Loop; obj2["m_Mirror"].AsBool = state.Mirror; val7.Children.Add(val8); AssetTypeValueField transitions = val8["data.m_TransitionConstantArray.Array"]; foreach (Transition transition in state.Transitions) { AddTransition(text, state.Name, transition, transitions, val7); } AssetTypeValueField obj3 = val8["data.m_BlendTreeConstantIndexArray.Array"]; AssetTypeValueField val9 = ValueBuilder.DefaultValueFieldFromTemplate(obj3.TemplateField.Children[1]); val9.AsInt = 0; obj3.Children.Add(val9); AssetTypeValueField obj4 = val8["data.m_BlendTreeConstantArray.Array"]; AssetTypeValueField val10 = ValueBuilder.DefaultValueFieldFromTemplate(obj4.TemplateField.Children[1]); obj4.Children.Add(val10); AssetTypeValueField obj5 = val10["data.m_NodeArray.Array"]; AssetTypeValueField val11 = ValueBuilder.DefaultValueFieldFromTemplate(obj5.TemplateField.Children[1]); AssetTypeValueField obj6 = val11["data"]; obj6["m_BlendEventID"].AsUInt = uint.MaxValue; obj6["m_BlendEventYID"].AsUInt = uint.MaxValue; obj6["m_ClipID"].AsInt = count; obj6["m_Duration"].AsFloat = 1f; obj6["m_CycleOffset"].AsFloat = 0f; obj5.Children.Add(val11); names.Add(text2); names.Add(state.Name); if (!string.IsNullOrWhiteSpace(state.Tag)) { names.Add(state.Tag); } } } } private void AddTransitions() { AssetTypeValueField val = baseField["m_Controller"]; string asString = baseField["m_Name"].AsString; foreach (AnimatorModifications modification in modifications) { foreach (KeyValuePair<(string, string), Transition> newTransition in modification.NewTransitions) { newTransition.Deconstruct(out var key, out var value); (string, string) tuple = key; string item = tuple.Item1; string item2 = tuple.Item2; Transition transition = value; uint layerHash = (uint)Animator.StringToHash(item); uint stateHash = (uint)Animator.StringToHash(item2); AssetTypeValueField val2 = ((IEnumerable<AssetTypeValueField>)val["m_LayerArray.Array"]).FirstOrDefault((Func<AssetTypeValueField, bool>)((AssetTypeValueField f) => f["data.m_Binding"].AsUInt == layerHash)); if (val2 == null) { AnimationsPlugin.Logger.LogError((object)("Layer \"" + item + "\" not found for controller " + asString + ". Mod: " + modification.Key)); continue; } uint asUInt = val2["data.m_StateMachineIndex"].AsUInt; AssetTypeValueField val3 = val["m_StateMachineArray.Array"][(int)asUInt]["data.m_StateConstantArray.Array"]; AssetTypeValueField val4 = ((IEnumerable<AssetTypeValueField>)val3).FirstOrDefault((Func<AssetTypeValueField, bool>)((AssetTypeValueField f) => f["data.m_NameID"].AsUInt == stateHash)); if (val4 == null) { AnimationsPlugin.Logger.LogError((object)("State \"" + item2 + "\" not found for a layer \"" + item + "\" for a controller \"" + asString + "\". Mod: " + modification.Key)); } AssetTypeValueField transitions = val4["data.m_TransitionConstantArray.Array"]; AddTransition(item, item2, transition, transitions, val3); } } } private void AddTransition(string layerName, string stateName, Transition transition, AssetTypeValueField transitions, AssetTypeValueField states) { string text = layerName + "." + stateName; uint num = (uint)Animator.StringToHash(transition.DestinationStateName); string text2 = stateName + " -> " + transition.DestinationStateName; uint asUInt = (uint)Animator.StringToHash(text2); string text3 = text + " -> " + layerName + "." + transition.DestinationStateName; uint asUInt2 = (uint)Animator.StringToHash(text3); uint asUInt3 = 0u; for (int i = 0; i < states.Children.Count; i++) { if (states[i]["data.m_NameID"].AsUInt == num) { asUInt3 = (uint)i; break; } } AssetTypeValueField val = ValueBuilder.DefaultValueFieldFromTemplate(transitions.TemplateField.Children[1]); AssetTypeValueField obj = val["data"]; obj["m_DestinationState"].AsUInt = asUInt3; obj["m_FullPathID"].AsUInt = asUInt2; obj["m_ID"].AsUInt = asUInt; obj["m_UserID"].AsUInt = 0u; obj["m_TransitionOffset"].AsFloat = transition.Offset; obj["m_TransitionDuration"].AsFloat = transition.TransitionDuration; obj["m_HasFixedDuration"].AsBool = transition.HasFixedDuration; obj["m_HasExitTime"].AsBool = transition.HasExitTime; obj["m_ExitTime"].AsFloat = transition.ExitTime; obj["m_InterruptionSource"].AsInt = 0; obj["m_CanTransitionToSelf"].AsBool = true; obj["m_OrderedInterruption"].AsBool = true; transitions.Children.Add(val); AssetTypeValueField val2 = obj["m_ConditionConstantArray.Array"]; foreach (Condition condition in transition.Conditions) { uint asUInt4 = (uint)Animator.StringToHash(condition.ParamName); AssetTypeValueField val3 = ValueBuilder.DefaultValueFieldFromTemplate(val2.TemplateField.Children[1]); AssetTypeValueField obj2 = val3["data"]; obj2["m_ConditionMode"].AsUInt = (uint)condition.ConditionMode; obj2["m_EventID"].AsUInt = asUInt4; obj2["m_EventThreshold"].AsFloat = condition.Value; obj2["m_ExitTime"].AsFloat = 0f; val2.Children.Add(val3); } names.Add(text2); names.Add(text3); } private void AddTOS() { AssetTypeValueField val = baseField["m_TOS.Array"]; HashSet<string> hashSet = new HashSet<string>(((IEnumerable<AssetTypeValueField>)val).Select((AssetTypeValueField f) => f["second"].AsString)); foreach (string name in names) { if (hashSet.Add(name)) { uint asUInt = (uint)Animator.StringToHash(name); AssetTypeValueField val2 = ValueBuilder.DefaultValueFieldFromTemplate(val.TemplateField.Children[1]); val2["first"].AsUInt = asUInt; val2["second"].AsString = name; val.Children.Add(val2); } } } private void SaveBundle() { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Expected O, but got Unknown AssetExternal extAsset = manager.GetExtAsset(dummyAssetFile, 0, dummyAnimatorControllerPathID, false, (AssetReadFlags)0); baseField["m_Name"].AsString = baseField["m_Name"].AsString + " (Modified)"; extAsset.info.SetNewData(baseField); AssetBundleDirectoryInfo val = dummyBundleFile.file.BlockAndDirInfo.DirectoryInfos[0]; val.SetNewData(dummyAssetFile.file); val.Name = Path.GetFileNameWithoutExtension(modifiedBundlePath); AssetExternal extAsset2 = manager.GetExtAsset(dummyAssetFile, 0, 1L, false, (AssetReadFlags)0); AssetTypeValueField val2 = extAsset2.baseField; val2["m_Name"].AsString = val.Name; extAsset2.info.SetNewData(val2); Directory.CreateDirectory(Path.GetDirectoryName(modifiedBundlePath)); using FileStream fileStream = File.Open(modifiedBundlePath, FileMode.Create, FileAccess.Write); AssetsFileWriter val3 = new AssetsFileWriter(fileStream); try { dummyBundleFile.file.Write(val3, 0L); } finally { ((IDisposable)val3)?.Dispose(); } } private void SetExternals() { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Expected O, but got Unknown List<AssetsFileExternal> externals = dummyAssetFile.file.Metadata.Externals; foreach (string dependency in dependencies) { externals.Add(new AssetsFileExternal { PathName = dependency, Type = (AssetsFileExternalType)0, VirtualAssetPathName = "" }); } } private void RemapPPtrs() { List<AssetTypeValueField> list = new List<AssetTypeValueField>(); GatherPPtrFileIDFields(baseField, list); HashSet<int> hashSet = new HashSet<int>(); foreach (AssetTypeValueField item2 in list) { hashSet.Add(item2.AsInt); } int num = 1; Dictionary<int, int> dictionary = new Dictionary<int, int>(); foreach (int item3 in hashSet.OrderBy((int d) => d)) { dictionary[item3] = num++; if (item3 == 0) { string item = "archive:/" + assetFile.name + "/" + assetFile.name; dependencies.Add(item); } else { dependencies.Add(assetFile.file.Metadata.Externals[item3 - 1].PathName); } } foreach (AssetTypeValueField item4 in list) { item4.AsInt = dictionary[item4.AsInt]; } } private void GatherPPtrFileIDFields(AssetTypeValueField field, List<AssetTypeValueField> fields) { if (field.TypeName.StartsWith("PPtr<")) { AssetTypeValueField item = field["m_FileID"]; fields.Add(item); return; } foreach (AssetTypeValueField child in field.Children) { GatherPPtrFileIDFields(child, fields); } } } internal static class NativeHelpers { [UnmanagedFunctionPointer(CallingConvention.ThisCall)] public unsafe delegate void InstanceIDToSerializedObjectIdentifierHandler(IntPtr remapper, int instanceID, SerializedObjectIdentifier* identifier); private const int InstanceIDToSerializedObjectIdentifierOffset = 6881312; private static IntPtr PersistentManagerPtr; private static InstanceIDToSerializedObjectIdentifierHandler InstanceIDToSerializedObjectIdentifier; private unsafe static PersistentManager* PersistentManager => *(PersistentManager**)PersistentManagerPtr.ToPointer(); public static void Init() { IntPtr baseAddress = (Process.GetCurrentProcess().Modules.Cast<ProcessModule>().FirstOrDefault(IsUnityPlayer) ?? Process.GetCurrentProcess().MainModule).BaseAddress; PersistentManagerPtr = baseAddress + 28557672; InstanceIDToSerializedObjectIdentifier = Marshal.GetDelegateForFunctionPointer<InstanceIDToSerializedObjectIdentifierHandler>(baseAddress + 6881312); static bool IsUnityPlayer(ProcessModule p) { return p.ModuleName.ToLowerInvariant().Contains("unityplayer"); } } public unsafe static long GetAssetPathID(Object obj) { SerializedObjectIdentifier serializedObjectIdentifier = default(SerializedObjectIdentifier); IntPtr remapper = PersistentManager->Remapper; InstanceIDToSerializedObjectIdentifier(remapper, obj.GetInstanceID(), &serializedObjectIdentifier); return serializedObjectIdentifier.pathID; } } } namespace R2API.AutoVersionGen { [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)] internal class AutoVersionAttribute : Attribute { } } namespace R2API.NativeStructs { [StructLayout(LayoutKind.Explicit)] public struct PersistentManager { [FieldOffset(88)] public IntPtr Remapper; } [StructLayout(LayoutKind.Sequential, Pack = 8)] public struct SerializedObjectIdentifier { public int fileID; public long pathID; } } namespace R2API.Models { public class Condition { public ConditionMode ConditionMode { get; set; } public string ParamName { get; set; } public float Value { get; set; } public void WriteBinary(BinaryWriter writer) { writer.Write((int)ConditionMode); writer.Write(ParamName ?? ""); writer.Write(Value.ToString(CultureInfo.InvariantCulture)); } } public enum ConditionMode { IsTrue = 1, IsFalse = 2, IsGreater = 3, IsLess = 4, IsEqual = 6, IsNotEqual = 7 } public class Parameter { public string Name { get; set; } public ParameterType Type { get; set; } public ParameterValue Value { get; set; } public void WriteBinary(BinaryWriter writer) { writer.Write(Name ?? ""); writer.Write((int)Type); Value.WriteBinary(writer); } } public enum ParameterType { Float = 1, Int = 3, Bool = 4, Trigger = 9 } [StructLayout(LayoutKind.Explicit)] public struct ParameterValue { [field: FieldOffset(0)] public bool BoolValue { get; set; } [field: FieldOffset(0)] public float FloatValue { get; set; } [field: FieldOffset(0)] public int IntValue { get; set; } public ParameterValue(bool value) { FloatValue = 0f; IntValue = 0; BoolValue = value; } public ParameterValue(float value) { BoolValue = false; IntValue = 0; FloatValue = value; } public ParameterValue(int value) { BoolValue = false; FloatValue = 0f; IntValue = value; } public static implicit operator ParameterValue(bool value) { return new ParameterValue(value); } public static implicit operator ParameterValue(float value) { return new ParameterValue(value); } public static implicit operator ParameterValue(int value) { return new ParameterValue(value); } public static implicit operator bool(ParameterValue value) { return value.BoolValue; } public static implicit operator float(ParameterValue value) { return value.FloatValue; } public static implicit operator int(ParameterValue value) { return value.IntValue; } public readonly void WriteBinary(BinaryWriter writer) { writer.Write(IntValue); } } public class State { public string Name { get; set; } public string ClipBundlePath { get; set; } public AnimationClip Clip { get; set; } public string Tag { get; set; } public string SpeedParam { get; set; } public string MirrorParam { get; set; } public string CycleOffsetParam { get; set; } public string TimeParam { get; set; } public float Speed { get; set; } public float CycleOffset { get; set; } public bool IKOnFeet { get; set; } public bool WriteDefaultValues { get; set; } public bool Loop { get; set; } public bool Mirror { get; set; } public List<Transition> Transitions { get; } = new List<Transition>(); public void WriteBinary(BinaryWriter writer) { writer.Write(Name ?? ""); writer.Write(ClipBundlePath ?? ""); writer.Write(NativeHelpers.GetAssetPathID((Object)(object)Clip)); writer.Write(Tag ?? ""); writer.Write(SpeedParam ?? ""); writer.Write(MirrorParam ?? ""); writer.Write(CycleOffsetParam ?? ""); writer.Write(TimeParam ?? ""); writer.Write(Speed); writer.Write(CycleOffset); writer.Write(IKOnFeet); writer.Write(WriteDefaultValues); writer.Write(Loop); writer.Write(Mirror); foreach (Transition transition in Transitions) { transition.WriteBinary(writer); } } } public class Transition { public string DestinationStateName { get; set; } public float TransitionDuration { get; set; } public float Offset { get; set; } public float ExitTime { get; set; } public bool HasExitTime { get; set; } public bool HasFixedDuration { get; set; } public List<Condition> Conditions { get; } = new List<Condition>(); public void WriteBinary(BinaryWriter writer) { writer.Write(DestinationStateName ?? ""); writer.Write(TransitionDuration); writer.Write(Offset); writer.Write(ExitTime); writer.Write(HasExitTime); writer.Write(HasFixedDuration); foreach (Condition condition in Conditions) { condition.WriteBinary(writer); } } } }
plugins/R2API.Animations/AssetsTools.NET.dll
Decompiled a month ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Text; using System.Text.RegularExpressions; using AssetsTools.NET.Extra; using AssetsTools.NET.Extra.Decompressors.LZ4; using LZ4ps; using SevenZip; using SevenZip.Compression.LZ; using SevenZip.Compression.LZMA; using SevenZip.Compression.RangeCoder; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("AssetsTools.NET")] [assembly: AssemblyDescription("A remake and port of SeriousCache's AssetTools")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("nesrak1")] [assembly: AssemblyProduct("AssetsTools.NET")] [assembly: AssemblyCopyright("Written by nes")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("e09d5ac2-1a2e-4ec1-94ad-3f5e22f17658")] [assembly: AssemblyFileVersion("3.0.0.0")] [assembly: TargetFramework(".NETStandard,Version=v2.0", FrameworkDisplayName = ".NET Standard 2.0")] [assembly: AssemblyVersion("3.0.0.0")] namespace SevenZip { internal class CRC { public static readonly uint[] Table; private uint _value = uint.MaxValue; static CRC() { Table = new uint[256]; for (uint num = 0u; num < 256; num++) { uint num2 = num; for (int i = 0; i < 8; i++) { num2 = (((num2 & 1) == 0) ? (num2 >> 1) : ((num2 >> 1) ^ 0xEDB88320u)); } Table[num] = num2; } } public void Init() { _value = uint.MaxValue; } public void UpdateByte(byte b) { _value = Table[(byte)_value ^ b] ^ (_value >> 8); } public void Update(byte[] data, uint offset, uint size) { for (uint num = 0u; num < size; num++) { _value = Table[(byte)_value ^ data[offset + num]] ^ (_value >> 8); } } public uint GetDigest() { return _value ^ 0xFFFFFFFFu; } private static uint CalculateDigest(byte[] data, uint offset, uint size) { CRC cRC = new CRC(); cRC.Update(data, offset, size); return cRC.GetDigest(); } private static bool VerifyDigest(uint digest, byte[] data, uint offset, uint size) { return CalculateDigest(data, offset, size) == digest; } } internal class DataErrorException : ApplicationException { public DataErrorException() : base("Data Error") { } } internal class InvalidParamException : ApplicationException { public InvalidParamException() : base("Invalid Parameter") { } } public interface ICodeProgress { void SetProgress(long inSize, long outSize); } public interface ICoder { void Code(Stream inStream, Stream outStream, long inSize, long outSize, ICodeProgress progress); } public enum CoderPropID { DefaultProp, DictionarySize, UsedMemorySize, Order, BlockSize, PosStateBits, LitContextBits, LitPosBits, NumFastBytes, MatchFinder, MatchFinderCycles, NumPasses, Algorithm, NumThreads, EndMarker } public interface ISetCoderProperties { void SetCoderProperties(CoderPropID[] propIDs, object[] properties); } public interface IWriteCoderProperties { void WriteCoderProperties(Stream outStream); } public interface ISetDecoderProperties { void SetDecoderProperties(byte[] properties); } } namespace SevenZip.Compression.RangeCoder { internal class Encoder { public const uint kTopValue = 16777216u; private Stream Stream; public ulong Low; public uint Range; private uint _cacheSize; private byte _cache; private long StartPosition; public void SetStream(Stream stream) { Stream = stream; } public void ReleaseStream() { Stream = null; } public void Init() { StartPosition = Stream.Position; Low = 0uL; Range = uint.MaxValue; _cacheSize = 1u; _cache = 0; } public void FlushData() { for (int i = 0; i < 5; i++) { ShiftLow(); } } public void FlushStream() { Stream.Flush(); } public void CloseStream() { Stream.Close(); } public void Encode(uint start, uint size, uint total) { Low += start * (Range /= total); Range *= size; while (Range < 16777216) { Range <<= 8; ShiftLow(); } } public void ShiftLow() { if ((uint)Low < 4278190080u || (int)(Low >> 32) == 1) { byte b = _cache; do { Stream.WriteByte((byte)(b + (Low >> 32))); b = byte.MaxValue; } while (--_cacheSize != 0); _cache = (byte)((uint)Low >> 24); } _cacheSize++; Low = (uint)((int)Low << 8); } public void EncodeDirectBits(uint v, int numTotalBits) { for (int num = numTotalBits - 1; num >= 0; num--) { Range >>= 1; if (((v >> num) & 1) == 1) { Low += Range; } if (Range < 16777216) { Range <<= 8; ShiftLow(); } } } public void EncodeBit(uint size0, int numTotalBits, uint symbol) { uint num = (Range >> numTotalBits) * size0; if (symbol == 0) { Range = num; } else { Low += num; Range -= num; } while (Range < 16777216) { Range <<= 8; ShiftLow(); } } public long GetProcessedSizeAdd() { return _cacheSize + Stream.Position - StartPosition + 4; } } internal class Decoder { public const uint kTopValue = 16777216u; public uint Range; public uint Code; public Stream Stream; public void Init(Stream stream) { Stream = stream; Code = 0u; Range = uint.MaxValue; for (int i = 0; i < 5; i++) { Code = (Code << 8) | (byte)Stream.ReadByte(); } } public void ReleaseStream() { Stream = null; } public void CloseStream() { Stream.Close(); } public void Normalize() { while (Range < 16777216) { Code = (Code << 8) | (byte)Stream.ReadByte(); Range <<= 8; } } public void Normalize2() { if (Range < 16777216) { Code = (Code << 8) | (byte)Stream.ReadByte(); Range <<= 8; } } public uint GetThreshold(uint total) { return Code / (Range /= total); } public void Decode(uint start, uint size, uint total) { Code -= start * Range; Range *= size; Normalize(); } public uint DecodeDirectBits(int numTotalBits) { uint num = Range; uint num2 = Code; uint num3 = 0u; for (int num4 = numTotalBits; num4 > 0; num4--) { num >>= 1; uint num5 = num2 - num >> 31; num2 -= num & (num5 - 1); num3 = (num3 << 1) | (1 - num5); if (num < 16777216) { num2 = (num2 << 8) | (byte)Stream.ReadByte(); num <<= 8; } } Range = num; Code = num2; return num3; } public uint DecodeBit(uint size0, int numTotalBits) { uint num = (Range >> numTotalBits) * size0; uint result; if (Code < num) { result = 0u; Range = num; } else { result = 1u; Code -= num; Range -= num; } Normalize(); return result; } } internal struct BitEncoder { public const int kNumBitModelTotalBits = 11; public const uint kBitModelTotal = 2048u; private const int kNumMoveBits = 5; private const int kNumMoveReducingBits = 2; public const int kNumBitPriceShiftBits = 6; private uint Prob; private static uint[] ProbPrices; public void Init() { Prob = 1024u; } public void UpdateModel(uint symbol) { if (symbol == 0) { Prob += 2048 - Prob >> 5; } else { Prob -= Prob >> 5; } } public void Encode(Encoder encoder, uint symbol) { uint num = (encoder.Range >> 11) * Prob; if (symbol == 0) { encoder.Range = num; Prob += 2048 - Prob >> 5; } else { encoder.Low += num; encoder.Range -= num; Prob -= Prob >> 5; } if (encoder.Range < 16777216) { encoder.Range <<= 8; encoder.ShiftLow(); } } static BitEncoder() { ProbPrices = new uint[512]; for (int num = 8; num >= 0; num--) { int num2 = 1 << 9 - num - 1; uint num3 = (uint)(1 << 9 - num); for (uint num4 = (uint)num2; num4 < num3; num4++) { ProbPrices[num4] = (uint)(num << 6) + (num3 - num4 << 6 >> 9 - num - 1); } } } public uint GetPrice(uint symbol) { return ProbPrices[(((Prob - symbol) ^ (int)(0 - symbol)) & 0x7FF) >> 2]; } public uint GetPrice0() { return ProbPrices[Prob >> 2]; } public uint GetPrice1() { return ProbPrices[2048 - Prob >> 2]; } } internal struct BitDecoder { public const int kNumBitModelTotalBits = 11; public const uint kBitModelTotal = 2048u; private const int kNumMoveBits = 5; private uint Prob; public void UpdateModel(int numMoveBits, uint symbol) { if (symbol == 0) { Prob += 2048 - Prob >> numMoveBits; } else { Prob -= Prob >> numMoveBits; } } public void Init() { Prob = 1024u; } public uint Decode(Decoder rangeDecoder) { uint num = (rangeDecoder.Range >> 11) * Prob; if (rangeDecoder.Code < num) { rangeDecoder.Range = num; Prob += 2048 - Prob >> 5; if (rangeDecoder.Range < 16777216) { rangeDecoder.Code = (rangeDecoder.Code << 8) | (byte)rangeDecoder.Stream.ReadByte(); rangeDecoder.Range <<= 8; } return 0u; } rangeDecoder.Range -= num; rangeDecoder.Code -= num; Prob -= Prob >> 5; if (rangeDecoder.Range < 16777216) { rangeDecoder.Code = (rangeDecoder.Code << 8) | (byte)rangeDecoder.Stream.ReadByte(); rangeDecoder.Range <<= 8; } return 1u; } } internal struct BitTreeEncoder { private BitEncoder[] Models; private int NumBitLevels; public BitTreeEncoder(int numBitLevels) { NumBitLevels = numBitLevels; Models = new BitEncoder[1 << numBitLevels]; } public void Init() { for (uint num = 1u; num < 1 << NumBitLevels; num++) { Models[num].Init(); } } public void Encode(Encoder rangeEncoder, uint symbol) { uint num = 1u; int num2 = NumBitLevels; while (num2 > 0) { num2--; uint num3 = (symbol >> num2) & 1u; Models[num].Encode(rangeEncoder, num3); num = (num << 1) | num3; } } public void ReverseEncode(Encoder rangeEncoder, uint symbol) { uint num = 1u; for (uint num2 = 0u; num2 < NumBitLevels; num2++) { uint num3 = symbol & 1u; Models[num].Encode(rangeEncoder, num3); num = (num << 1) | num3; symbol >>= 1; } } public uint GetPrice(uint symbol) { uint num = 0u; uint num2 = 1u; int num3 = NumBitLevels; while (num3 > 0) { num3--; uint num4 = (symbol >> num3) & 1u; num += Models[num2].GetPrice(num4); num2 = (num2 << 1) + num4; } return num; } public uint ReverseGetPrice(uint symbol) { uint num = 0u; uint num2 = 1u; for (int num3 = NumBitLevels; num3 > 0; num3--) { uint num4 = symbol & 1u; symbol >>= 1; num += Models[num2].GetPrice(num4); num2 = (num2 << 1) | num4; } return num; } public static uint ReverseGetPrice(BitEncoder[] Models, uint startIndex, int NumBitLevels, uint symbol) { uint num = 0u; uint num2 = 1u; for (int num3 = NumBitLevels; num3 > 0; num3--) { uint num4 = symbol & 1u; symbol >>= 1; num += Models[startIndex + num2].GetPrice(num4); num2 = (num2 << 1) | num4; } return num; } public static void ReverseEncode(BitEncoder[] Models, uint startIndex, Encoder rangeEncoder, int NumBitLevels, uint symbol) { uint num = 1u; for (int i = 0; i < NumBitLevels; i++) { uint num2 = symbol & 1u; Models[startIndex + num].Encode(rangeEncoder, num2); num = (num << 1) | num2; symbol >>= 1; } } } internal struct BitTreeDecoder { private BitDecoder[] Models; private int NumBitLevels; public BitTreeDecoder(int numBitLevels) { NumBitLevels = numBitLevels; Models = new BitDecoder[1 << numBitLevels]; } public void Init() { for (uint num = 1u; num < 1 << NumBitLevels; num++) { Models[num].Init(); } } public uint Decode(Decoder rangeDecoder) { uint num = 1u; for (int num2 = NumBitLevels; num2 > 0; num2--) { num = (num << 1) + Models[num].Decode(rangeDecoder); } return num - (uint)(1 << NumBitLevels); } public uint ReverseDecode(Decoder rangeDecoder) { uint num = 1u; uint num2 = 0u; for (int i = 0; i < NumBitLevels; i++) { uint num3 = Models[num].Decode(rangeDecoder); num <<= 1; num += num3; num2 |= num3 << i; } return num2; } public static uint ReverseDecode(BitDecoder[] Models, uint startIndex, Decoder rangeDecoder, int NumBitLevels) { uint num = 1u; uint num2 = 0u; for (int i = 0; i < NumBitLevels; i++) { uint num3 = Models[startIndex + num].Decode(rangeDecoder); num <<= 1; num += num3; num2 |= num3 << i; } return num2; } } } namespace SevenZip.Compression.LZ { internal interface IInWindowStream { void SetStream(Stream inStream); void Init(); void ReleaseStream(); byte GetIndexByte(int index); uint GetMatchLen(int index, uint distance, uint limit); uint GetNumAvailableBytes(); } internal interface IMatchFinder : IInWindowStream { void Create(uint historySize, uint keepAddBufferBefore, uint matchMaxLen, uint keepAddBufferAfter); uint GetMatches(uint[] distances); void Skip(uint num); } public class BinTree : InWindow, IMatchFinder, IInWindowStream { private uint _cyclicBufferPos; private uint _cyclicBufferSize; private uint _matchMaxLen; private uint[] _son; private uint[] _hash; private uint _cutValue = 255u; private uint _hashMask; private uint _hashSizeSum; private bool HASH_ARRAY = true; private const uint kHash2Size = 1024u; private const uint kHash3Size = 65536u; private const uint kBT2HashSize = 65536u; private const uint kStartMaxLen = 1u; private const uint kHash3Offset = 1024u; private const uint kEmptyHashValue = 0u; private const uint kMaxValForNormalize = 2147483647u; private uint kNumHashDirectBytes; private uint kMinMatchCheck = 4u; private uint kFixHashSize = 66560u; public void SetType(int numHashBytes) { HASH_ARRAY = numHashBytes > 2; if (HASH_ARRAY) { kNumHashDirectBytes = 0u; kMinMatchCheck = 4u; kFixHashSize = 66560u; } else { kNumHashDirectBytes = 2u; kMinMatchCheck = 3u; kFixHashSize = 0u; } } public new void SetStream(Stream stream) { base.SetStream(stream); } public new void ReleaseStream() { base.ReleaseStream(); } public new void Init() { base.Init(); for (uint num = 0u; num < _hashSizeSum; num++) { _hash[num] = 0u; } _cyclicBufferPos = 0u; ReduceOffsets(-1); } public new void MovePos() { if (++_cyclicBufferPos >= _cyclicBufferSize) { _cyclicBufferPos = 0u; } base.MovePos(); if (_pos == int.MaxValue) { Normalize(); } } public new byte GetIndexByte(int index) { return base.GetIndexByte(index); } public new uint GetMatchLen(int index, uint distance, uint limit) { return base.GetMatchLen(index, distance, limit); } public new uint GetNumAvailableBytes() { return base.GetNumAvailableBytes(); } public void Create(uint historySize, uint keepAddBufferBefore, uint matchMaxLen, uint keepAddBufferAfter) { if (historySize > 2147483391) { throw new Exception(); } _cutValue = 16 + (matchMaxLen >> 1); uint keepSizeReserv = (historySize + keepAddBufferBefore + matchMaxLen + keepAddBufferAfter) / 2 + 256; Create(historySize + keepAddBufferBefore, matchMaxLen + keepAddBufferAfter, keepSizeReserv); _matchMaxLen = matchMaxLen; uint num = historySize + 1; if (_cyclicBufferSize != num) { _son = new uint[(_cyclicBufferSize = num) * 2]; } uint num2 = 65536u; if (HASH_ARRAY) { num2 = historySize - 1; num2 |= num2 >> 1; num2 |= num2 >> 2; num2 |= num2 >> 4; num2 |= num2 >> 8; num2 >>= 1; num2 |= 0xFFFFu; if (num2 > 16777216) { num2 >>= 1; } _hashMask = num2; num2++; num2 += kFixHashSize; } if (num2 != _hashSizeSum) { _hash = new uint[_hashSizeSum = num2]; } } public uint GetMatches(uint[] distances) { uint num; if (_pos + _matchMaxLen <= _streamPos) { num = _matchMaxLen; } else { num = _streamPos - _pos; if (num < kMinMatchCheck) { MovePos(); return 0u; } } uint num2 = 0u; uint num3 = ((_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0u); uint num4 = _bufferOffset + _pos; uint num5 = 1u; uint num6 = 0u; uint num7 = 0u; uint num10; if (HASH_ARRAY) { uint num8 = CRC.Table[_bufferBase[num4]] ^ _bufferBase[num4 + 1]; num6 = num8 & 0x3FFu; int num9 = (int)num8 ^ (_bufferBase[num4 + 2] << 8); num7 = (uint)num9 & 0xFFFFu; num10 = ((uint)num9 ^ (CRC.Table[_bufferBase[num4 + 3]] << 5)) & _hashMask; } else { num10 = (uint)(_bufferBase[num4] ^ (_bufferBase[num4 + 1] << 8)); } uint num11 = _hash[kFixHashSize + num10]; if (HASH_ARRAY) { uint num12 = _hash[num6]; uint num13 = _hash[1024 + num7]; _hash[num6] = _pos; _hash[1024 + num7] = _pos; if (num12 > num3 && _bufferBase[_bufferOffset + num12] == _bufferBase[num4]) { num5 = (distances[num2++] = 2u); distances[num2++] = _pos - num12 - 1; } if (num13 > num3 && _bufferBase[_bufferOffset + num13] == _bufferBase[num4]) { if (num13 == num12) { num2 -= 2; } num5 = (distances[num2++] = 3u); distances[num2++] = _pos - num13 - 1; num12 = num13; } if (num2 != 0 && num12 == num11) { num2 -= 2; num5 = 1u; } } _hash[kFixHashSize + num10] = _pos; uint num14 = (_cyclicBufferPos << 1) + 1; uint num15 = _cyclicBufferPos << 1; uint val; uint val2 = (val = kNumHashDirectBytes); if (kNumHashDirectBytes != 0 && num11 > num3 && _bufferBase[_bufferOffset + num11 + kNumHashDirectBytes] != _bufferBase[num4 + kNumHashDirectBytes]) { num5 = (distances[num2++] = kNumHashDirectBytes); distances[num2++] = _pos - num11 - 1; } uint cutValue = _cutValue; while (true) { if (num11 <= num3 || cutValue-- == 0) { _son[num14] = (_son[num15] = 0u); break; } uint num16 = _pos - num11; uint num17 = ((num16 <= _cyclicBufferPos) ? (_cyclicBufferPos - num16) : (_cyclicBufferPos - num16 + _cyclicBufferSize)) << 1; uint num18 = _bufferOffset + num11; uint num19 = Math.Min(val2, val); if (_bufferBase[num18 + num19] == _bufferBase[num4 + num19]) { while (++num19 != num && _bufferBase[num18 + num19] == _bufferBase[num4 + num19]) { } if (num5 < num19) { num5 = (distances[num2++] = num19); distances[num2++] = num16 - 1; if (num19 == num) { _son[num15] = _son[num17]; _son[num14] = _son[num17 + 1]; break; } } } if (_bufferBase[num18 + num19] < _bufferBase[num4 + num19]) { _son[num15] = num11; num15 = num17 + 1; num11 = _son[num15]; val = num19; } else { _son[num14] = num11; num14 = num17; num11 = _son[num14]; val2 = num19; } } MovePos(); return num2; } public void Skip(uint num) { do { uint num2; if (_pos + _matchMaxLen <= _streamPos) { num2 = _matchMaxLen; } else { num2 = _streamPos - _pos; if (num2 < kMinMatchCheck) { MovePos(); continue; } } uint num3 = ((_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0u); uint num4 = _bufferOffset + _pos; uint num9; if (HASH_ARRAY) { uint num5 = CRC.Table[_bufferBase[num4]] ^ _bufferBase[num4 + 1]; uint num6 = num5 & 0x3FFu; _hash[num6] = _pos; int num7 = (int)num5 ^ (_bufferBase[num4 + 2] << 8); uint num8 = (uint)num7 & 0xFFFFu; _hash[1024 + num8] = _pos; num9 = ((uint)num7 ^ (CRC.Table[_bufferBase[num4 + 3]] << 5)) & _hashMask; } else { num9 = (uint)(_bufferBase[num4] ^ (_bufferBase[num4 + 1] << 8)); } uint num10 = _hash[kFixHashSize + num9]; _hash[kFixHashSize + num9] = _pos; uint num11 = (_cyclicBufferPos << 1) + 1; uint num12 = _cyclicBufferPos << 1; uint val; uint val2 = (val = kNumHashDirectBytes); uint cutValue = _cutValue; while (true) { if (num10 <= num3 || cutValue-- == 0) { _son[num11] = (_son[num12] = 0u); break; } uint num13 = _pos - num10; uint num14 = ((num13 <= _cyclicBufferPos) ? (_cyclicBufferPos - num13) : (_cyclicBufferPos - num13 + _cyclicBufferSize)) << 1; uint num15 = _bufferOffset + num10; uint num16 = Math.Min(val2, val); if (_bufferBase[num15 + num16] == _bufferBase[num4 + num16]) { while (++num16 != num2 && _bufferBase[num15 + num16] == _bufferBase[num4 + num16]) { } if (num16 == num2) { _son[num12] = _son[num14]; _son[num11] = _son[num14 + 1]; break; } } if (_bufferBase[num15 + num16] < _bufferBase[num4 + num16]) { _son[num12] = num10; num12 = num14 + 1; num10 = _son[num12]; val = num16; } else { _son[num11] = num10; num11 = num14; num10 = _son[num11]; val2 = num16; } } MovePos(); } while (--num != 0); } private void NormalizeLinks(uint[] items, uint numItems, uint subValue) { for (uint num = 0u; num < numItems; num++) { uint num2 = items[num]; num2 = ((num2 > subValue) ? (num2 - subValue) : 0u); items[num] = num2; } } private void Normalize() { uint subValue = _pos - _cyclicBufferSize; NormalizeLinks(_son, _cyclicBufferSize * 2, subValue); NormalizeLinks(_hash, _hashSizeSum, subValue); ReduceOffsets((int)subValue); } public void SetCutValue(uint cutValue) { _cutValue = cutValue; } } public class InWindow { public byte[] _bufferBase; private Stream _stream; private uint _posLimit; private bool _streamEndWasReached; private uint _pointerToLastSafePosition; public uint _bufferOffset; public uint _blockSize; public uint _pos; private uint _keepSizeBefore; private uint _keepSizeAfter; public uint _streamPos; public void MoveBlock() { uint num = _bufferOffset + _pos - _keepSizeBefore; if (num != 0) { num--; } uint num2 = _bufferOffset + _streamPos - num; for (uint num3 = 0u; num3 < num2; num3++) { _bufferBase[num3] = _bufferBase[num + num3]; } _bufferOffset -= num; } public virtual void ReadBlock() { if (_streamEndWasReached) { return; } while (true) { int num = (int)(0 - _bufferOffset + _blockSize - _streamPos); if (num == 0) { return; } int num2 = _stream.Read(_bufferBase, (int)(_bufferOffset + _streamPos), num); if (num2 == 0) { break; } _streamPos += (uint)num2; if (_streamPos >= _pos + _keepSizeAfter) { _posLimit = _streamPos - _keepSizeAfter; } } _posLimit = _streamPos; if (_bufferOffset + _posLimit > _pointerToLastSafePosition) { _posLimit = _pointerToLastSafePosition - _bufferOffset; } _streamEndWasReached = true; } private void Free() { _bufferBase = null; } public void Create(uint keepSizeBefore, uint keepSizeAfter, uint keepSizeReserv) { _keepSizeBefore = keepSizeBefore; _keepSizeAfter = keepSizeAfter; uint num = keepSizeBefore + keepSizeAfter + keepSizeReserv; if (_bufferBase == null || _blockSize != num) { Free(); _blockSize = num; _bufferBase = new byte[_blockSize]; } _pointerToLastSafePosition = _blockSize - keepSizeAfter; } public void SetStream(Stream stream) { _stream = stream; } public void ReleaseStream() { _stream = null; } public void Init() { _bufferOffset = 0u; _pos = 0u; _streamPos = 0u; _streamEndWasReached = false; ReadBlock(); } public void MovePos() { _pos++; if (_pos > _posLimit) { if (_bufferOffset + _pos > _pointerToLastSafePosition) { MoveBlock(); } ReadBlock(); } } public byte GetIndexByte(int index) { return _bufferBase[_bufferOffset + _pos + index]; } public uint GetMatchLen(int index, uint distance, uint limit) { if (_streamEndWasReached && _pos + index + limit > _streamPos) { limit = _streamPos - (uint)(int)(_pos + index); } distance++; uint num = _bufferOffset + _pos + (uint)index; uint num2; for (num2 = 0u; num2 < limit && _bufferBase[num + num2] == _bufferBase[num + num2 - distance]; num2++) { } return num2; } public uint GetNumAvailableBytes() { return _streamPos - _pos; } public void ReduceOffsets(int subValue) { _bufferOffset += (uint)subValue; _posLimit -= (uint)subValue; _pos -= (uint)subValue; _streamPos -= (uint)subValue; } } public class OutWindow { private byte[] _buffer; private uint _pos; private uint _windowSize; private uint _streamPos; private Stream _stream; public uint TrainSize; public void Create(uint windowSize) { if (_windowSize != windowSize) { _buffer = new byte[windowSize]; } _windowSize = windowSize; _pos = 0u; _streamPos = 0u; } public void Init(Stream stream, bool solid) { ReleaseStream(); _stream = stream; if (!solid) { _streamPos = 0u; _pos = 0u; TrainSize = 0u; } } public bool Train(Stream stream) { long length = stream.Length; uint num = (TrainSize = (uint)((length < _windowSize) ? length : _windowSize)); stream.Position = length - num; _streamPos = (_pos = 0u); while (num != 0) { uint num2 = _windowSize - _pos; if (num < num2) { num2 = num; } int num3 = stream.Read(_buffer, (int)_pos, (int)num2); if (num3 == 0) { return false; } num -= (uint)num3; _pos += (uint)num3; _streamPos += (uint)num3; if (_pos == _windowSize) { _streamPos = (_pos = 0u); } } return true; } public void ReleaseStream() { Flush(); _stream = null; } public void Flush() { uint num = _pos - _streamPos; if (num != 0) { _stream.Write(_buffer, (int)_streamPos, (int)num); if (_pos >= _windowSize) { _pos = 0u; } _streamPos = _pos; } } public void CopyBlock(uint distance, uint len) { uint num = _pos - distance - 1; if (num >= _windowSize) { num += _windowSize; } while (len != 0) { if (num >= _windowSize) { num = 0u; } _buffer[_pos++] = _buffer[num++]; if (_pos >= _windowSize) { Flush(); } len--; } } public void PutByte(byte b) { _buffer[_pos++] = b; if (_pos >= _windowSize) { Flush(); } } public byte GetByte(uint distance) { uint num = _pos - distance - 1; if (num >= _windowSize) { num += _windowSize; } return _buffer[num]; } } } namespace SevenZip.Compression.LZMA { internal abstract class Base { public struct State { public uint Index; public void Init() { Index = 0u; } public void UpdateChar() { if (Index < 4) { Index = 0u; } else if (Index < 10) { Index -= 3u; } else { Index -= 6u; } } public void UpdateMatch() { Index = ((Index < 7) ? 7u : 10u); } public void UpdateRep() { Index = ((Index < 7) ? 8u : 11u); } public void UpdateShortRep() { Index = ((Index < 7) ? 9u : 11u); } public bool IsCharState() { return Index < 7; } } public const uint kNumRepDistances = 4u; public const uint kNumStates = 12u; public const int kNumPosSlotBits = 6; public const int kDicLogSizeMin = 0; public const int kNumLenToPosStatesBits = 2; public const uint kNumLenToPosStates = 4u; public const uint kMatchMinLen = 2u; public const int kNumAlignBits = 4; public const uint kAlignTableSize = 16u; public const uint kAlignMask = 15u; public const uint kStartPosModelIndex = 4u; public const uint kEndPosModelIndex = 14u; public const uint kNumPosModels = 10u; public const uint kNumFullDistances = 128u; public const uint kNumLitPosStatesBitsEncodingMax = 4u; public const uint kNumLitContextBitsMax = 8u; public const int kNumPosStatesBitsMax = 4; public const uint kNumPosStatesMax = 16u; public const int kNumPosStatesBitsEncodingMax = 4; public const uint kNumPosStatesEncodingMax = 16u; public const int kNumLowLenBits = 3; public const int kNumMidLenBits = 3; public const int kNumHighLenBits = 8; public const uint kNumLowLenSymbols = 8u; public const uint kNumMidLenSymbols = 8u; public const uint kNumLenSymbols = 272u; public const uint kMatchMaxLen = 273u; public static uint GetLenToPosState(uint len) { len -= 2; if (len < 4) { return len; } return 3u; } } public class Decoder : ICoder, ISetDecoderProperties { private class LenDecoder { private BitDecoder m_Choice; private BitDecoder m_Choice2; private BitTreeDecoder[] m_LowCoder = new BitTreeDecoder[16]; private BitTreeDecoder[] m_MidCoder = new BitTreeDecoder[16]; private BitTreeDecoder m_HighCoder = new BitTreeDecoder(8); private uint m_NumPosStates; public void Create(uint numPosStates) { for (uint num = m_NumPosStates; num < numPosStates; num++) { m_LowCoder[num] = new BitTreeDecoder(3); m_MidCoder[num] = new BitTreeDecoder(3); } m_NumPosStates = numPosStates; } public void Init() { m_Choice.Init(); for (uint num = 0u; num < m_NumPosStates; num++) { m_LowCoder[num].Init(); m_MidCoder[num].Init(); } m_Choice2.Init(); m_HighCoder.Init(); } public uint Decode(SevenZip.Compression.RangeCoder.Decoder rangeDecoder, uint posState) { if (m_Choice.Decode(rangeDecoder) == 0) { return m_LowCoder[posState].Decode(rangeDecoder); } uint num = 8u; if (m_Choice2.Decode(rangeDecoder) == 0) { return num + m_MidCoder[posState].Decode(rangeDecoder); } num += 8; return num + m_HighCoder.Decode(rangeDecoder); } } private class LiteralDecoder { private struct Decoder2 { private BitDecoder[] m_Decoders; public void Create() { m_Decoders = new BitDecoder[768]; } public void Init() { for (int i = 0; i < 768; i++) { m_Decoders[i].Init(); } } public byte DecodeNormal(SevenZip.Compression.RangeCoder.Decoder rangeDecoder) { uint num = 1u; do { num = (num << 1) | m_Decoders[num].Decode(rangeDecoder); } while (num < 256); return (byte)num; } public byte DecodeWithMatchByte(SevenZip.Compression.RangeCoder.Decoder rangeDecoder, byte matchByte) { uint num = 1u; do { uint num2 = (uint)(matchByte >> 7) & 1u; matchByte <<= 1; uint num3 = m_Decoders[(1 + num2 << 8) + num].Decode(rangeDecoder); num = (num << 1) | num3; if (num2 != num3) { while (num < 256) { num = (num << 1) | m_Decoders[num].Decode(rangeDecoder); } break; } } while (num < 256); return (byte)num; } } private Decoder2[] m_Coders; private int m_NumPrevBits; private int m_NumPosBits; private uint m_PosMask; public void Create(int numPosBits, int numPrevBits) { if (m_Coders == null || m_NumPrevBits != numPrevBits || m_NumPosBits != numPosBits) { m_NumPosBits = numPosBits; m_PosMask = (uint)((1 << numPosBits) - 1); m_NumPrevBits = numPrevBits; uint num = (uint)(1 << m_NumPrevBits + m_NumPosBits); m_Coders = new Decoder2[num]; for (uint num2 = 0u; num2 < num; num2++) { m_Coders[num2].Create(); } } } public void Init() { uint num = (uint)(1 << m_NumPrevBits + m_NumPosBits); for (uint num2 = 0u; num2 < num; num2++) { m_Coders[num2].Init(); } } private uint GetState(uint pos, byte prevByte) { return ((pos & m_PosMask) << m_NumPrevBits) + (uint)(prevByte >> 8 - m_NumPrevBits); } public byte DecodeNormal(SevenZip.Compression.RangeCoder.Decoder rangeDecoder, uint pos, byte prevByte) { return m_Coders[GetState(pos, prevByte)].DecodeNormal(rangeDecoder); } public byte DecodeWithMatchByte(SevenZip.Compression.RangeCoder.Decoder rangeDecoder, uint pos, byte prevByte, byte matchByte) { return m_Coders[GetState(pos, prevByte)].DecodeWithMatchByte(rangeDecoder, matchByte); } } private OutWindow m_OutWindow = new OutWindow(); private SevenZip.Compression.RangeCoder.Decoder m_RangeDecoder = new SevenZip.Compression.RangeCoder.Decoder(); private BitDecoder[] m_IsMatchDecoders = new BitDecoder[192]; private BitDecoder[] m_IsRepDecoders = new BitDecoder[12]; private BitDecoder[] m_IsRepG0Decoders = new BitDecoder[12]; private BitDecoder[] m_IsRepG1Decoders = new BitDecoder[12]; private BitDecoder[] m_IsRepG2Decoders = new BitDecoder[12]; private BitDecoder[] m_IsRep0LongDecoders = new BitDecoder[192]; private BitTreeDecoder[] m_PosSlotDecoder = new BitTreeDecoder[4]; private BitDecoder[] m_PosDecoders = new BitDecoder[114]; private BitTreeDecoder m_PosAlignDecoder = new BitTreeDecoder(4); private LenDecoder m_LenDecoder = new LenDecoder(); private LenDecoder m_RepLenDecoder = new LenDecoder(); private LiteralDecoder m_LiteralDecoder = new LiteralDecoder(); private uint m_DictionarySize; private uint m_DictionarySizeCheck; private uint m_PosStateMask; private bool _solid; public Decoder() { m_DictionarySize = uint.MaxValue; for (int i = 0; (long)i < 4L; i++) { m_PosSlotDecoder[i] = new BitTreeDecoder(6); } } private void SetDictionarySize(uint dictionarySize) { if (m_DictionarySize != dictionarySize) { m_DictionarySize = dictionarySize; m_DictionarySizeCheck = Math.Max(m_DictionarySize, 1u); uint windowSize = Math.Max(m_DictionarySizeCheck, 4096u); m_OutWindow.Create(windowSize); } } private void SetLiteralProperties(int lp, int lc) { if (lp > 8) { throw new InvalidParamException(); } if (lc > 8) { throw new InvalidParamException(); } m_LiteralDecoder.Create(lp, lc); } private void SetPosBitsProperties(int pb) { if (pb > 4) { throw new InvalidParamException(); } uint num = (uint)(1 << pb); m_LenDecoder.Create(num); m_RepLenDecoder.Create(num); m_PosStateMask = num - 1; } private void Init(Stream inStream, Stream outStream) { m_RangeDecoder.Init(inStream); m_OutWindow.Init(outStream, _solid); for (uint num = 0u; num < 12; num++) { for (uint num2 = 0u; num2 <= m_PosStateMask; num2++) { uint num3 = (num << 4) + num2; m_IsMatchDecoders[num3].Init(); m_IsRep0LongDecoders[num3].Init(); } m_IsRepDecoders[num].Init(); m_IsRepG0Decoders[num].Init(); m_IsRepG1Decoders[num].Init(); m_IsRepG2Decoders[num].Init(); } m_LiteralDecoder.Init(); for (uint num = 0u; num < 4; num++) { m_PosSlotDecoder[num].Init(); } for (uint num = 0u; num < 114; num++) { m_PosDecoders[num].Init(); } m_LenDecoder.Init(); m_RepLenDecoder.Init(); m_PosAlignDecoder.Init(); } public void Code(Stream inStream, Stream outStream, long inSize, long outSize, ICodeProgress progress) { Init(inStream, outStream); Base.State state = default(Base.State); state.Init(); uint num = 0u; uint num2 = 0u; uint num3 = 0u; uint num4 = 0u; ulong num5 = 0uL; if (num5 < (ulong)outSize) { if (m_IsMatchDecoders[state.Index << 4].Decode(m_RangeDecoder) != 0) { throw new DataErrorException(); } state.UpdateChar(); byte b = m_LiteralDecoder.DecodeNormal(m_RangeDecoder, 0u, 0); m_OutWindow.PutByte(b); num5++; } while (num5 < (ulong)outSize) { uint num6 = (uint)(int)num5 & m_PosStateMask; if (m_IsMatchDecoders[(state.Index << 4) + num6].Decode(m_RangeDecoder) == 0) { byte @byte = m_OutWindow.GetByte(0u); byte b2 = (state.IsCharState() ? m_LiteralDecoder.DecodeNormal(m_RangeDecoder, (uint)num5, @byte) : m_LiteralDecoder.DecodeWithMatchByte(m_RangeDecoder, (uint)num5, @byte, m_OutWindow.GetByte(num))); m_OutWindow.PutByte(b2); state.UpdateChar(); num5++; continue; } uint num8; if (m_IsRepDecoders[state.Index].Decode(m_RangeDecoder) == 1) { if (m_IsRepG0Decoders[state.Index].Decode(m_RangeDecoder) == 0) { if (m_IsRep0LongDecoders[(state.Index << 4) + num6].Decode(m_RangeDecoder) == 0) { state.UpdateShortRep(); m_OutWindow.PutByte(m_OutWindow.GetByte(num)); num5++; continue; } } else { uint num7; if (m_IsRepG1Decoders[state.Index].Decode(m_RangeDecoder) == 0) { num7 = num2; } else { if (m_IsRepG2Decoders[state.Index].Decode(m_RangeDecoder) == 0) { num7 = num3; } else { num7 = num4; num4 = num3; } num3 = num2; } num2 = num; num = num7; } num8 = m_RepLenDecoder.Decode(m_RangeDecoder, num6) + 2; state.UpdateRep(); } else { num4 = num3; num3 = num2; num2 = num; num8 = 2 + m_LenDecoder.Decode(m_RangeDecoder, num6); state.UpdateMatch(); uint num9 = m_PosSlotDecoder[Base.GetLenToPosState(num8)].Decode(m_RangeDecoder); if (num9 >= 4) { int num10 = (int)((num9 >> 1) - 1); num = (2 | (num9 & 1)) << num10; if (num9 < 14) { num += BitTreeDecoder.ReverseDecode(m_PosDecoders, num - num9 - 1, m_RangeDecoder, num10); } else { num += m_RangeDecoder.DecodeDirectBits(num10 - 4) << 4; num += m_PosAlignDecoder.ReverseDecode(m_RangeDecoder); } } else { num = num9; } } if (num >= m_OutWindow.TrainSize + num5 || num >= m_DictionarySizeCheck) { if (num == uint.MaxValue) { break; } throw new DataErrorException(); } m_OutWindow.CopyBlock(num, num8); num5 += num8; } m_OutWindow.Flush(); m_OutWindow.ReleaseStream(); m_RangeDecoder.ReleaseStream(); } public void SetDecoderProperties(byte[] properties) { if (properties.Length < 5) { throw new InvalidParamException(); } int lc = properties[0] % 9; int num = properties[0] / 9; int lp = num % 5; int num2 = num / 5; if (num2 > 4) { throw new InvalidParamException(); } uint num3 = 0u; for (int i = 0; i < 4; i++) { num3 += (uint)(properties[1 + i] << i * 8); } SetDictionarySize(num3); SetLiteralProperties(lp, lc); SetPosBitsProperties(num2); } public bool Train(Stream stream) { _solid = true; return m_OutWindow.Train(stream); } } public class Encoder : ICoder, ISetCoderProperties, IWriteCoderProperties { private enum EMatchFinderType { BT2, BT4 } private class LiteralEncoder { public struct Encoder2 { private BitEncoder[] m_Encoders; public void Create() { m_Encoders = new BitEncoder[768]; } public void Init() { for (int i = 0; i < 768; i++) { m_Encoders[i].Init(); } } public void Encode(SevenZip.Compression.RangeCoder.Encoder rangeEncoder, byte symbol) { uint num = 1u; for (int num2 = 7; num2 >= 0; num2--) { uint num3 = (uint)(symbol >> num2) & 1u; m_Encoders[num].Encode(rangeEncoder, num3); num = (num << 1) | num3; } } public void EncodeMatched(SevenZip.Compression.RangeCoder.Encoder rangeEncoder, byte matchByte, byte symbol) { uint num = 1u; bool flag = true; for (int num2 = 7; num2 >= 0; num2--) { uint num3 = (uint)(symbol >> num2) & 1u; uint num4 = num; if (flag) { uint num5 = (uint)(matchByte >> num2) & 1u; num4 += 1 + num5 << 8; flag = num5 == num3; } m_Encoders[num4].Encode(rangeEncoder, num3); num = (num << 1) | num3; } } public uint GetPrice(bool matchMode, byte matchByte, byte symbol) { uint num = 0u; uint num2 = 1u; int num3 = 7; if (matchMode) { while (num3 >= 0) { uint num4 = (uint)(matchByte >> num3) & 1u; uint num5 = (uint)(symbol >> num3) & 1u; num += m_Encoders[(1 + num4 << 8) + num2].GetPrice(num5); num2 = (num2 << 1) | num5; if (num4 != num5) { num3--; break; } num3--; } } while (num3 >= 0) { uint num6 = (uint)(symbol >> num3) & 1u; num += m_Encoders[num2].GetPrice(num6); num2 = (num2 << 1) | num6; num3--; } return num; } } private Encoder2[] m_Coders; private int m_NumPrevBits; private int m_NumPosBits; private uint m_PosMask; public void Create(int numPosBits, int numPrevBits) { if (m_Coders == null || m_NumPrevBits != numPrevBits || m_NumPosBits != numPosBits) { m_NumPosBits = numPosBits; m_PosMask = (uint)((1 << numPosBits) - 1); m_NumPrevBits = numPrevBits; uint num = (uint)(1 << m_NumPrevBits + m_NumPosBits); m_Coders = new Encoder2[num]; for (uint num2 = 0u; num2 < num; num2++) { m_Coders[num2].Create(); } } } public void Init() { uint num = (uint)(1 << m_NumPrevBits + m_NumPosBits); for (uint num2 = 0u; num2 < num; num2++) { m_Coders[num2].Init(); } } public Encoder2 GetSubCoder(uint pos, byte prevByte) { return m_Coders[(int)((pos & m_PosMask) << m_NumPrevBits) + (prevByte >> 8 - m_NumPrevBits)]; } } private class LenEncoder { private BitEncoder _choice; private BitEncoder _choice2; private BitTreeEncoder[] _lowCoder = new BitTreeEncoder[16]; private BitTreeEncoder[] _midCoder = new BitTreeEncoder[16]; private BitTreeEncoder _highCoder = new BitTreeEncoder(8); public LenEncoder() { for (uint num = 0u; num < 16; num++) { _lowCoder[num] = new BitTreeEncoder(3); _midCoder[num] = new BitTreeEncoder(3); } } public void Init(uint numPosStates) { _choice.Init(); _choice2.Init(); for (uint num = 0u; num < numPosStates; num++) { _lowCoder[num].Init(); _midCoder[num].Init(); } _highCoder.Init(); } public void Encode(SevenZip.Compression.RangeCoder.Encoder rangeEncoder, uint symbol, uint posState) { if (symbol < 8) { _choice.Encode(rangeEncoder, 0u); _lowCoder[posState].Encode(rangeEncoder, symbol); return; } symbol -= 8; _choice.Encode(rangeEncoder, 1u); if (symbol < 8) { _choice2.Encode(rangeEncoder, 0u); _midCoder[posState].Encode(rangeEncoder, symbol); } else { _choice2.Encode(rangeEncoder, 1u); _highCoder.Encode(rangeEncoder, symbol - 8); } } public void SetPrices(uint posState, uint numSymbols, uint[] prices, uint st) { uint price = _choice.GetPrice0(); uint price2 = _choice.GetPrice1(); uint num = price2 + _choice2.GetPrice0(); uint num2 = price2 + _choice2.GetPrice1(); uint num3 = 0u; for (num3 = 0u; num3 < 8; num3++) { if (num3 >= numSymbols) { return; } prices[st + num3] = price + _lowCoder[posState].GetPrice(num3); } for (; num3 < 16; num3++) { if (num3 >= numSymbols) { return; } prices[st + num3] = num + _midCoder[posState].GetPrice(num3 - 8); } for (; num3 < numSymbols; num3++) { prices[st + num3] = num2 + _highCoder.GetPrice(num3 - 8 - 8); } } } private class LenPriceTableEncoder : LenEncoder { private uint[] _prices = new uint[4352]; private uint _tableSize; private uint[] _counters = new uint[16]; public void SetTableSize(uint tableSize) { _tableSize = tableSize; } public uint GetPrice(uint symbol, uint posState) { return _prices[posState * 272 + symbol]; } private void UpdateTable(uint posState) { SetPrices(posState, _tableSize, _prices, posState * 272); _counters[posState] = _tableSize; } public void UpdateTables(uint numPosStates) { for (uint num = 0u; num < numPosStates; num++) { UpdateTable(num); } } public new void Encode(SevenZip.Compression.RangeCoder.Encoder rangeEncoder, uint symbol, uint posState) { base.Encode(rangeEncoder, symbol, posState); if (--_counters[posState] == 0) { UpdateTable(posState); } } } private class Optimal { public Base.State State; public bool Prev1IsChar; public bool Prev2; public uint PosPrev2; public uint BackPrev2; public uint Price; public uint PosPrev; public uint BackPrev; public uint Backs0; public uint Backs1; public uint Backs2; public uint Backs3; public void MakeAsChar() { BackPrev = uint.MaxValue; Prev1IsChar = false; } public void MakeAsShortRep() { BackPrev = 0u; Prev1IsChar = false; } public bool IsShortRep() { return BackPrev == 0; } } private const uint kIfinityPrice = 268435455u; private static byte[] g_FastPos; private Base.State _state; private byte _previousByte; private uint[] _repDistances = new uint[4]; private const int kDefaultDictionaryLogSize = 22; private const uint kNumFastBytesDefault = 32u; private const uint kNumLenSpecSymbols = 16u; private const uint kNumOpts = 4096u; private Optimal[] _optimum = new Optimal[4096]; private IMatchFinder _matchFinder; private SevenZip.Compression.RangeCoder.Encoder _rangeEncoder = new SevenZip.Compression.RangeCoder.Encoder(); private BitEncoder[] _isMatch = new BitEncoder[192]; private BitEncoder[] _isRep = new BitEncoder[12]; private BitEncoder[] _isRepG0 = new BitEncoder[12]; private BitEncoder[] _isRepG1 = new BitEncoder[12]; private BitEncoder[] _isRepG2 = new BitEncoder[12]; private BitEncoder[] _isRep0Long = new BitEncoder[192]; private BitTreeEncoder[] _posSlotEncoder = new BitTreeEncoder[4]; private BitEncoder[] _posEncoders = new BitEncoder[114]; private BitTreeEncoder _posAlignEncoder = new BitTreeEncoder(4); private LenPriceTableEncoder _lenEncoder = new LenPriceTableEncoder(); private LenPriceTableEncoder _repMatchLenEncoder = new LenPriceTableEncoder(); private LiteralEncoder _literalEncoder = new LiteralEncoder(); private uint[] _matchDistances = new uint[548]; private uint _numFastBytes = 32u; private uint _longestMatchLength; private uint _numDistancePairs; private uint _additionalOffset; private uint _optimumEndIndex; private uint _optimumCurrentIndex; private bool _longestMatchWasFound; private uint[] _posSlotPrices = new uint[256]; private uint[] _distancesPrices = new uint[512]; private uint[] _alignPrices = new uint[16]; private uint _alignPriceCount; private uint _distTableSize = 44u; private int _posStateBits = 2; private uint _posStateMask = 3u; private int _numLiteralPosStateBits; private int _numLiteralContextBits = 3; private uint _dictionarySize = 4194304u; private uint _dictionarySizePrev = uint.MaxValue; private uint _numFastBytesPrev = uint.MaxValue; private long nowPos64; private bool _finished; private Stream _inStream; private EMatchFinderType _matchFinderType = EMatchFinderType.BT4; private bool _writeEndMark; private bool _needReleaseMFStream; private uint[] reps = new uint[4]; private uint[] repLens = new uint[4]; private const int kPropSize = 5; private byte[] properties = new byte[5]; private uint[] tempPrices = new uint[128]; private uint _matchPriceCount; private static string[] kMatchFinderIDs; private uint _trainSize; static Encoder() { g_FastPos = new byte[2048]; kMatchFinderIDs = new string[2] { "BT2", "BT4" }; int num = 2; g_FastPos[0] = 0; g_FastPos[1] = 1; for (byte b = 2; b < 22; b++) { uint num2 = (uint)(1 << (b >> 1) - 1); uint num3 = 0u; while (num3 < num2) { g_FastPos[num] = b; num3++; num++; } } } private static uint GetPosSlot(uint pos) { if (pos < 2048) { return g_FastPos[pos]; } if (pos < 2097152) { return (uint)(g_FastPos[pos >> 10] + 20); } return (uint)(g_FastPos[pos >> 20] + 40); } private static uint GetPosSlot2(uint pos) { if (pos < 131072) { return (uint)(g_FastPos[pos >> 6] + 12); } if (pos < 134217728) { return (uint)(g_FastPos[pos >> 16] + 32); } return (uint)(g_FastPos[pos >> 26] + 52); } private void BaseInit() { _state.Init(); _previousByte = 0; for (uint num = 0u; num < 4; num++) { _repDistances[num] = 0u; } } private void Create() { if (_matchFinder == null) { BinTree binTree = new BinTree(); int type = 4; if (_matchFinderType == EMatchFinderType.BT2) { type = 2; } binTree.SetType(type); _matchFinder = binTree; } _literalEncoder.Create(_numLiteralPosStateBits, _numLiteralContextBits); if (_dictionarySize != _dictionarySizePrev || _numFastBytesPrev != _numFastBytes) { _matchFinder.Create(_dictionarySize, 4096u, _numFastBytes, 274u); _dictionarySizePrev = _dictionarySize; _numFastBytesPrev = _numFastBytes; } } public Encoder() { for (int i = 0; (long)i < 4096L; i++) { _optimum[i] = new Optimal(); } for (int j = 0; (long)j < 4L; j++) { _posSlotEncoder[j] = new BitTreeEncoder(6); } } private void SetWriteEndMarkerMode(bool writeEndMarker) { _writeEndMark = writeEndMarker; } private void Init() { BaseInit(); _rangeEncoder.Init(); for (uint num = 0u; num < 12; num++) { for (uint num2 = 0u; num2 <= _posStateMask; num2++) { uint num3 = (num << 4) + num2; _isMatch[num3].Init(); _isRep0Long[num3].Init(); } _isRep[num].Init(); _isRepG0[num].Init(); _isRepG1[num].Init(); _isRepG2[num].Init(); } _literalEncoder.Init(); for (uint num = 0u; num < 4; num++) { _posSlotEncoder[num].Init(); } for (uint num = 0u; num < 114; num++) { _posEncoders[num].Init(); } _lenEncoder.Init((uint)(1 << _posStateBits)); _repMatchLenEncoder.Init((uint)(1 << _posStateBits)); _posAlignEncoder.Init(); _longestMatchWasFound = false; _optimumEndIndex = 0u; _optimumCurrentIndex = 0u; _additionalOffset = 0u; } private void ReadMatchDistances(out uint lenRes, out uint numDistancePairs) { lenRes = 0u; numDistancePairs = _matchFinder.GetMatches(_matchDistances); if (numDistancePairs != 0) { lenRes = _matchDistances[numDistancePairs - 2]; if (lenRes == _numFastBytes) { lenRes += _matchFinder.GetMatchLen((int)(lenRes - 1), _matchDistances[numDistancePairs - 1], 273 - lenRes); } } _additionalOffset++; } private void MovePos(uint num) { if (num != 0) { _matchFinder.Skip(num); _additionalOffset += num; } } private uint GetRepLen1Price(Base.State state, uint posState) { return _isRepG0[state.Index].GetPrice0() + _isRep0Long[(state.Index << 4) + posState].GetPrice0(); } private uint GetPureRepPrice(uint repIndex, Base.State state, uint posState) { uint price; if (repIndex == 0) { price = _isRepG0[state.Index].GetPrice0(); return price + _isRep0Long[(state.Index << 4) + posState].GetPrice1(); } price = _isRepG0[state.Index].GetPrice1(); if (repIndex == 1) { return price + _isRepG1[state.Index].GetPrice0(); } price += _isRepG1[state.Index].GetPrice1(); return price + _isRepG2[state.Index].GetPrice(repIndex - 2); } private uint GetRepPrice(uint repIndex, uint len, Base.State state, uint posState) { return _repMatchLenEncoder.GetPrice(len - 2, posState) + GetPureRepPrice(repIndex, state, posState); } private uint GetPosLenPrice(uint pos, uint len, uint posState) { uint lenToPosState = Base.GetLenToPosState(len); uint num = ((pos >= 128) ? (_posSlotPrices[(lenToPosState << 6) + GetPosSlot2(pos)] + _alignPrices[pos & 0xF]) : _distancesPrices[lenToPosState * 128 + pos]); return num + _lenEncoder.GetPrice(len - 2, posState); } private uint Backward(out uint backRes, uint cur) { _optimumEndIndex = cur; uint posPrev = _optimum[cur].PosPrev; uint backPrev = _optimum[cur].BackPrev; do { if (_optimum[cur].Prev1IsChar) { _optimum[posPrev].MakeAsChar(); _optimum[posPrev].PosPrev = posPrev - 1; if (_optimum[cur].Prev2) { _optimum[posPrev - 1].Prev1IsChar = false; _optimum[posPrev - 1].PosPrev = _optimum[cur].PosPrev2; _optimum[posPrev - 1].BackPrev = _optimum[cur].BackPrev2; } } uint num = posPrev; uint backPrev2 = backPrev; backPrev = _optimum[num].BackPrev; posPrev = _optimum[num].PosPrev; _optimum[num].BackPrev = backPrev2; _optimum[num].PosPrev = cur; cur = num; } while (cur != 0); backRes = _optimum[0].BackPrev; _optimumCurrentIndex = _optimum[0].PosPrev; return _optimumCurrentIndex; } private uint GetOptimum(uint position, out uint backRes) { if (_optimumEndIndex != _optimumCurrentIndex) { uint result = _optimum[_optimumCurrentIndex].PosPrev - _optimumCurrentIndex; backRes = _optimum[_optimumCurrentIndex].BackPrev; _optimumCurrentIndex = _optimum[_optimumCurrentIndex].PosPrev; return result; } _optimumCurrentIndex = (_optimumEndIndex = 0u); uint lenRes; uint numDistancePairs; if (!_longestMatchWasFound) { ReadMatchDistances(out lenRes, out numDistancePairs); } else { lenRes = _longestMatchLength; numDistancePairs = _numDistancePairs; _longestMatchWasFound = false; } uint num = _matchFinder.GetNumAvailableBytes() + 1; if (num < 2) { backRes = uint.MaxValue; return 1u; } if (num > 273) { num = 273u; } uint num2 = 0u; for (uint num3 = 0u; num3 < 4; num3++) { reps[num3] = _repDistances[num3]; repLens[num3] = _matchFinder.GetMatchLen(-1, reps[num3], 273u); if (repLens[num3] > repLens[num2]) { num2 = num3; } } if (repLens[num2] >= _numFastBytes) { backRes = num2; uint num4 = repLens[num2]; MovePos(num4 - 1); return num4; } if (lenRes >= _numFastBytes) { backRes = _matchDistances[numDistancePairs - 1] + 4; MovePos(lenRes - 1); return lenRes; } byte indexByte = _matchFinder.GetIndexByte(-1); byte indexByte2 = _matchFinder.GetIndexByte((int)(0 - _repDistances[0] - 1 - 1)); if (lenRes < 2 && indexByte != indexByte2 && repLens[num2] < 2) { backRes = uint.MaxValue; return 1u; } _optimum[0].State = _state; uint num5 = position & _posStateMask; _optimum[1].Price = _isMatch[(_state.Index << 4) + num5].GetPrice0() + _literalEncoder.GetSubCoder(position, _previousByte).GetPrice(!_state.IsCharState(), indexByte2, indexByte); _optimum[1].MakeAsChar(); uint price = _isMatch[(_state.Index << 4) + num5].GetPrice1(); uint num6 = price + _isRep[_state.Index].GetPrice1(); if (indexByte2 == indexByte) { uint num7 = num6 + GetRepLen1Price(_state, num5); if (num7 < _optimum[1].Price) { _optimum[1].Price = num7; _optimum[1].MakeAsShortRep(); } } uint num8 = ((lenRes >= repLens[num2]) ? lenRes : repLens[num2]); if (num8 < 2) { backRes = _optimum[1].BackPrev; return 1u; } _optimum[1].PosPrev = 0u; _optimum[0].Backs0 = reps[0]; _optimum[0].Backs1 = reps[1]; _optimum[0].Backs2 = reps[2]; _optimum[0].Backs3 = reps[3]; uint num9 = num8; do { _optimum[num9--].Price = 268435455u; } while (num9 >= 2); for (uint num3 = 0u; num3 < 4; num3++) { uint num10 = repLens[num3]; if (num10 < 2) { continue; } uint num11 = num6 + GetPureRepPrice(num3, _state, num5); do { uint num12 = num11 + _repMatchLenEncoder.GetPrice(num10 - 2, num5); Optimal optimal = _optimum[num10]; if (num12 < optimal.Price) { optimal.Price = num12; optimal.PosPrev = 0u; optimal.BackPrev = num3; optimal.Prev1IsChar = false; } } while (--num10 >= 2); } uint num13 = price + _isRep[_state.Index].GetPrice0(); num9 = ((repLens[0] >= 2) ? (repLens[0] + 1) : 2u); if (num9 <= lenRes) { uint num14; for (num14 = 0u; num9 > _matchDistances[num14]; num14 += 2) { } while (true) { uint num15 = _matchDistances[num14 + 1]; uint num16 = num13 + GetPosLenPrice(num15, num9, num5); Optimal optimal2 = _optimum[num9]; if (num16 < optimal2.Price) { optimal2.Price = num16; optimal2.PosPrev = 0u; optimal2.BackPrev = num15 + 4; optimal2.Prev1IsChar = false; } if (num9 == _matchDistances[num14]) { num14 += 2; if (num14 == numDistancePairs) { break; } } num9++; } } uint num17 = 0u; uint lenRes2; while (true) { num17++; if (num17 == num8) { return Backward(out backRes, num17); } ReadMatchDistances(out lenRes2, out numDistancePairs); if (lenRes2 >= _numFastBytes) { break; } position++; uint num18 = _optimum[num17].PosPrev; Base.State state; if (_optimum[num17].Prev1IsChar) { num18--; if (_optimum[num17].Prev2) { state = _optimum[_optimum[num17].PosPrev2].State; if (_optimum[num17].BackPrev2 < 4) { state.UpdateRep(); } else { state.UpdateMatch(); } } else { state = _optimum[num18].State; } state.UpdateChar(); } else { state = _optimum[num18].State; } if (num18 == num17 - 1) { if (_optimum[num17].IsShortRep()) { state.UpdateShortRep(); } else { state.UpdateChar(); } } else { uint num19; if (_optimum[num17].Prev1IsChar && _optimum[num17].Prev2) { num18 = _optimum[num17].PosPrev2; num19 = _optimum[num17].BackPrev2; state.UpdateRep(); } else { num19 = _optimum[num17].BackPrev; if (num19 < 4) { state.UpdateRep(); } else { state.UpdateMatch(); } } Optimal optimal3 = _optimum[num18]; switch (num19) { case 0u: reps[0] = optimal3.Backs0; reps[1] = optimal3.Backs1; reps[2] = optimal3.Backs2; reps[3] = optimal3.Backs3; break; case 1u: reps[0] = optimal3.Backs1; reps[1] = optimal3.Backs0; reps[2] = optimal3.Backs2; reps[3] = optimal3.Backs3; break; case 2u: reps[0] = optimal3.Backs2; reps[1] = optimal3.Backs0; reps[2] = optimal3.Backs1; reps[3] = optimal3.Backs3; break; case 3u: reps[0] = optimal3.Backs3; reps[1] = optimal3.Backs0; reps[2] = optimal3.Backs1; reps[3] = optimal3.Backs2; break; default: reps[0] = num19 - 4; reps[1] = optimal3.Backs0; reps[2] = optimal3.Backs1; reps[3] = optimal3.Backs2; break; } } _optimum[num17].State = state; _optimum[num17].Backs0 = reps[0]; _optimum[num17].Backs1 = reps[1]; _optimum[num17].Backs2 = reps[2]; _optimum[num17].Backs3 = reps[3]; uint price2 = _optimum[num17].Price; indexByte = _matchFinder.GetIndexByte(-1); indexByte2 = _matchFinder.GetIndexByte((int)(0 - reps[0] - 1 - 1)); num5 = position & _posStateMask; uint num20 = price2 + _isMatch[(state.Index << 4) + num5].GetPrice0() + _literalEncoder.GetSubCoder(position, _matchFinder.GetIndexByte(-2)).GetPrice(!state.IsCharState(), indexByte2, indexByte); Optimal optimal4 = _optimum[num17 + 1]; bool flag = false; if (num20 < optimal4.Price) { optimal4.Price = num20; optimal4.PosPrev = num17; optimal4.MakeAsChar(); flag = true; } price = price2 + _isMatch[(state.Index << 4) + num5].GetPrice1(); num6 = price + _isRep[state.Index].GetPrice1(); if (indexByte2 == indexByte && (optimal4.PosPrev >= num17 || optimal4.BackPrev != 0)) { uint num21 = num6 + GetRepLen1Price(state, num5); if (num21 <= optimal4.Price) { optimal4.Price = num21; optimal4.PosPrev = num17; optimal4.MakeAsShortRep(); flag = true; } } uint val = _matchFinder.GetNumAvailableBytes() + 1; val = Math.Min(4095 - num17, val); num = val; if (num < 2) { continue; } if (num > _numFastBytes) { num = _numFastBytes; } if (!flag && indexByte2 != indexByte) { uint limit = Math.Min(val - 1, _numFastBytes); uint matchLen = _matchFinder.GetMatchLen(0, reps[0], limit); if (matchLen >= 2) { Base.State state2 = state; state2.UpdateChar(); uint num22 = (position + 1) & _posStateMask; uint num23 = num20 + _isMatch[(state2.Index << 4) + num22].GetPrice1() + _isRep[state2.Index].GetPrice1(); uint num24 = num17 + 1 + matchLen; while (num8 < num24) { _optimum[++num8].Price = 268435455u; } uint num25 = num23 + GetRepPrice(0u, matchLen, state2, num22); Optimal optimal5 = _optimum[num24]; if (num25 < optimal5.Price) { optimal5.Price = num25; optimal5.PosPrev = num17 + 1; optimal5.BackPrev = 0u; optimal5.Prev1IsChar = true; optimal5.Prev2 = false; } } } uint num26 = 2u; for (uint num27 = 0u; num27 < 4; num27++) { uint num28 = _matchFinder.GetMatchLen(-1, reps[num27], num); if (num28 < 2) { continue; } uint num29 = num28; while (true) { if (num8 < num17 + num28) { _optimum[++num8].Price = 268435455u; continue; } uint num30 = num6 + GetRepPrice(num27, num28, state, num5); Optimal optimal6 = _optimum[num17 + num28]; if (num30 < optimal6.Price) { optimal6.Price = num30; optimal6.PosPrev = num17; optimal6.BackPrev = num27; optimal6.Prev1IsChar = false; } if (--num28 < 2) { break; } } num28 = num29; if (num27 == 0) { num26 = num28 + 1; } if (num28 >= val) { continue; } uint limit2 = Math.Min(val - 1 - num28, _numFastBytes); uint matchLen2 = _matchFinder.GetMatchLen((int)num28, reps[num27], limit2); if (matchLen2 >= 2) { Base.State state3 = state; state3.UpdateRep(); uint num31 = (position + num28) & _posStateMask; uint num32 = num6 + GetRepPrice(num27, num28, state, num5) + _isMatch[(state3.Index << 4) + num31].GetPrice0() + _literalEncoder.GetSubCoder(position + num28, _matchFinder.GetIndexByte((int)(num28 - 1 - 1))).GetPrice(matchMode: true, _matchFinder.GetIndexByte((int)(num28 - 1 - (reps[num27] + 1))), _matchFinder.GetIndexByte((int)(num28 - 1))); state3.UpdateChar(); num31 = (position + num28 + 1) & _posStateMask; uint num33 = num32 + _isMatch[(state3.Index << 4) + num31].GetPrice1() + _isRep[state3.Index].GetPrice1(); uint num34 = num28 + 1 + matchLen2; while (num8 < num17 + num34) { _optimum[++num8].Price = 268435455u; } uint num35 = num33 + GetRepPrice(0u, matchLen2, state3, num31); Optimal optimal7 = _optimum[num17 + num34]; if (num35 < optimal7.Price) { optimal7.Price = num35; optimal7.PosPrev = num17 + num28 + 1; optimal7.BackPrev = 0u; optimal7.Prev1IsChar = true; optimal7.Prev2 = true; optimal7.PosPrev2 = num17; optimal7.BackPrev2 = num27; } } } if (lenRes2 > num) { lenRes2 = num; for (numDistancePairs = 0u; lenRes2 > _matchDistances[numDistancePairs]; numDistancePairs += 2) { } _matchDistances[numDistancePairs] = lenRes2; numDistancePairs += 2; } if (lenRes2 < num26) { continue; } num13 = price + _isRep[state.Index].GetPrice0(); while (num8 < num17 + lenRes2) { _optimum[++num8].Price = 268435455u; } uint num36; for (num36 = 0u; num26 > _matchDistances[num36]; num36 += 2) { } uint num37 = num26; while (true) { uint num38 = _matchDistances[num36 + 1]; uint num39 = num13 + GetPosLenPrice(num38, num37, num5); Optimal optimal8 = _optimum[num17 + num37]; if (num39 < optimal8.Price) { optimal8.Price = num39; optimal8.PosPrev = num17; optimal8.BackPrev = num38 + 4; optimal8.Prev1IsChar = false; } if (num37 == _matchDistances[num36]) { if (num37 < val) { uint limit3 = Math.Min(val - 1 - num37, _numFastBytes); uint matchLen3 = _matchFinder.GetMatchLen((int)num37, num38, limit3); if (matchLen3 >= 2) { Base.State state4 = state; state4.UpdateMatch(); uint num40 = (position + num37) & _posStateMask; uint num41 = num39 + _isMatch[(state4.Index << 4) + num40].GetPrice0() + _literalEncoder.GetSubCoder(position + num37, _matchFinder.GetIndexByte((int)(num37 - 1 - 1))).GetPrice(matchMode: true, _matchFinder.GetIndexByte((int)(num37 - (num38 + 1) - 1)), _matchFinder.GetIndexByte((int)(num37 - 1))); state4.UpdateChar(); num40 = (position + num37 + 1) & _posStateMask; uint num42 = num41 + _isMatch[(state4.Index << 4) + num40].GetPrice1() + _isRep[state4.Index].GetPrice1(); uint num43 = num37 + 1 + matchLen3; while (num8 < num17 + num43) { _optimum[++num8].Price = 268435455u; } num39 = num42 + GetRepPrice(0u, matchLen3, state4, num40); optimal8 = _optimum[num17 + num43]; if (num39 < optimal8.Price) { optimal8.Price = num39; optimal8.PosPrev = num17 + num37 + 1; optimal8.BackPrev = 0u; optimal8.Prev1IsChar = true; optimal8.Prev2 = true; optimal8.PosPrev2 = num17; optimal8.BackPrev2 = num38 + 4; } } } num36 += 2; if (num36 == numDistancePairs) { break; } } num37++; } } _numDistancePairs = numDistancePairs; _longestMatchLength = lenRes2; _longestMatchWasFound = true; return Backward(out backRes, num17); } private bool ChangePair(uint smallDist, uint bigDist) { if (smallDist < 33554432) { return bigDist >= smallDist << 7; } return false; } private void WriteEndMarker(uint posState) { if (_writeEndMark) { _isMatch[(_state.Index << 4) + posState].Encode(_rangeEncoder, 1u); _isRep[_state.Index].Encode(_rangeEncoder, 0u); _state.UpdateMatch(); uint num = 2u; _lenEncoder.Encode(_rangeEncoder, num - 2, posState); uint symbol = 63u; uint lenToPosState = Base.GetLenToPosState(num); _posSlotEncoder[lenToPosState].Encode(_rangeEncoder, symbol); int num2 = 30; uint num3 = (uint)((1 << num2) - 1); _rangeEncoder.EncodeDirectBits(num3 >> 4, num2 - 4); _posAlignEncoder.ReverseEncode(_rangeEncoder, num3 & 0xFu); } } private void Flush(uint nowPos) { ReleaseMFStream(); WriteEndMarker(nowPos & _posStateMask); _rangeEncoder.FlushData(); _rangeEncoder.FlushStream(); } public void CodeOneBlock(out long inSize, out long outSize, out bool finished) { inSize = 0L; outSize = 0L; finished = true; if (_inStream != null) { _matchFinder.SetStream(_inStream); _matchFinder.Init(); _needReleaseMFStream = true; _inStream = null; if (_trainSize != 0) { _matchFinder.Skip(_trainSize); } } if (_finished) { return; } _finished = true; long num = nowPos64; if (nowPos64 == 0L) { if (_matchFinder.GetNumAvailableBytes() == 0) { Flush((uint)nowPos64); return; } ReadMatchDistances(out var _, out var _); uint num2 = (uint)(int)nowPos64 & _posStateMask; _isMatch[(_state.Index << 4) + num2].Encode(_rangeEncoder, 0u); _state.UpdateChar(); byte indexByte = _matchFinder.GetIndexByte((int)(0 - _additionalOffset)); _literalEncoder.GetSubCoder((uint)nowPos64, _previousByte).Encode(_rangeEncoder, indexByte); _previousByte = indexByte; _additionalOffset--; nowPos64++; } if (_matchFinder.GetNumAvailableBytes() == 0) { Flush((uint)nowPos64); return; } while (true) { uint backRes; uint optimum = GetOptimum((uint)nowPos64, out backRes); uint num3 = (uint)(int)nowPos64 & _posStateMask; uint num4 = (_state.Index << 4) + num3; if (optimum == 1 && backRes == uint.MaxValue) { _isMatch[num4].Encode(_rangeEncoder, 0u); byte indexByte2 = _matchFinder.GetIndexByte((int)(0 - _additionalOffset)); LiteralEncoder.Encoder2 subCoder = _literalEncoder.GetSubCoder((uint)nowPos64, _previousByte); if (!_state.IsCharState()) { byte indexByte3 = _matchFinder.GetIndexByte((int)(0 - _repDistances[0] - 1 - _additionalOffset)); subCoder.EncodeMatched(_rangeEncoder, indexByte3, indexByte2); } else { subCoder.Encode(_rangeEncoder, indexByte2); } _previousByte = indexByte2; _state.UpdateChar(); } else { _isMatch[num4].Encode(_rangeEncoder, 1u); if (backRes < 4) { _isRep[_state.Index].Encode(_rangeEncoder, 1u); if (backRes == 0) { _isRepG0[_state.Index].Encode(_rangeEncoder, 0u); if (optimum == 1) { _isRep0Long[num4].Encode(_rangeEncoder, 0u); } else { _isRep0Long[num4].Encode(_rangeEncoder, 1u); } } else { _isRepG0[_state.Index].Encode(_rangeEncoder, 1u); if (backRes == 1) { _isRepG1[_state.Index].Encode(_rangeEncoder, 0u); } else { _isRepG1[_state.Index].Encode(_rangeEncoder, 1u); _isRepG2[_state.Index].Encode(_rangeEncoder, backRes - 2); } } if (optimum == 1) { _state.UpdateShortRep(); } else { _repMatchLenEncoder.Encode(_rangeEncoder, optimum - 2, num3); _state.UpdateRep(); } uint num5 = _repDistances[backRes]; if (backRes != 0) { for (uint num6 = backRes; num6 >= 1; num6--) { _repDistances[num6] = _repDistances[num6 - 1]; } _repDistances[0] = num5; } } else { _isRep[_state.Index].Encode(_rangeEncoder, 0u); _state.UpdateMatch(); _lenEncoder.Encode(_rangeEncoder, optimum - 2, num3); backRes -= 4; uint posSlot = GetPosSlot(backRes); uint lenToPosState = Base.GetLenToPosState(optimum); _posSlotEncoder[lenToPosState].Encode(_rangeEncoder, posSlot); if (posSlot >= 4) { int num7 = (int)((posSlot >> 1) - 1); uint num8 = (2 | (posSlot & 1)) << num7; uint num9 = backRes - num8; if (posSlot < 14) { BitTreeEncoder.ReverseEncode(_posEncoders, num8 - posSlot - 1, _rangeEncoder, num7, num9); } else { _rangeEncoder.EncodeDirectBits(num9 >> 4, num7 - 4); _posAlignEncoder.ReverseEncode(_rangeEncoder, num9 & 0xFu); _alignPriceCount++; } } uint num10 = backRes; for (uint num11 = 3u; num11 >= 1; num11--) { _repDistances[num11] = _repDistances[num11 - 1]; } _repDistances[0] = num10; _matchPriceCount++; } _previousByte = _matchFinder.GetIndexByte((int)(optimum - 1 - _additionalOffset)); } _additionalOffset -= optimum; nowPos64 += optimum; if (_additionalOffset == 0) { if (_matchPriceCount >= 128) { FillDistancesPrices(); } if (_alignPriceCount >= 16) { FillAlignPrices(); } inSize = nowPos64; outSize = _rangeEncoder.GetProcessedSizeAdd(); if (_matchFinder.GetNumAvailableBytes() == 0) { Flush((uint)nowPos64); return; } if (nowPos64 - num >= 4096) { break; } } } _finished = false; finished = false; } private void ReleaseMFStream() { if (_matchFinder != null && _needReleaseMFStream) { _matchFinder.ReleaseStream(); _needReleaseMFStream = false; } } private void SetOutStream(Stream outStream) { _rangeEncoder.SetStream(outStream); } private void ReleaseOutStream() { _rangeEncoder.ReleaseStream(); } private void ReleaseStreams() { ReleaseMFStream(); ReleaseOutStream(); } private void SetStreams(Stream inStream, Stream outStream, long inSize, long outSize) { _inStream = inStream; _finished = false; Create(); SetOutStream(outStream); Init(); FillDistancesPrices(); FillAlignPrices(); _lenEncoder.SetTableSize(_numFastBytes + 1 - 2); _lenEncoder.UpdateTables((uint)(1 << _posStateBits)); _repMatchLenEncoder.SetTableSize(_numFastBytes + 1 - 2); _repMatchLenEncoder.UpdateTables((uint)(1 << _posStateBits)); nowPos64 = 0L; } public void Code(Stream inStream, Stream outStream, long inSize, long outSize, ICodeProgress progress) { _needReleaseMFStream = false; try { SetStreams(inStream, outStream, inSize, outSize); while (true) { CodeOneBlock(out var inSize2, out var outSize2, out var finished); if (finished) { break; } progress?.SetProgress(inSize2, outSize2); } } finally { ReleaseStreams(); } } public void WriteCoderProperties(Stream outStream) { properties[0] = (byte)((_posStateBits * 5 + _numLiteralPosStateBits) * 9 + _numLiteralContextBits); for (int i = 0; i < 4; i++) { properties[1 + i] = (byte)((_dictionarySize >> 8 * i) & 0xFFu); } outStream.Write(properties, 0, 5); } private void FillDistancesPrices() { for (uint num = 4u; num < 128; num++) { uint posSlot = GetPosSlot(num); int num2 = (int)((posSlot >> 1) - 1); uint num3 = (2 | (posSlot & 1)) << num2; tempPrices[num] = BitTreeEncoder.ReverseGetPrice(_posEncoders, num3 - posSlot - 1, num2, num - num3); } for (uint num4 = 0u; num4 < 4; num4++) { BitTreeEncoder bitTreeEncoder = _posSlotEncoder[num4]; uint num5 = num4 << 6; for (uint num6 = 0u; num6 < _distTableSize; num6++) { _posSlotPrices[num5 + num6] = bitTreeEncoder.GetPrice(num6); } for (uint num6 = 14u; num6 < _distTableSize; num6++) { _posSlotPrices[num5 + num6] += (num6 >> 1) - 1 - 4 << 6; } uint num7 = num4 * 128; uint num8; for (num8 = 0u; num8 < 4; num8++) { _distancesPrices[num7 + num8] = _posSlotPrices[num5 + num8]; } for (; num8 < 128; num8++) { _distancesPrices[num7 + num8] = _posSlotPrices[num5 + GetPosSlot(num8)] + tempPrices[num8]; } } _matchPriceCount = 0u; } private void FillAlignPrices() { for (uint num = 0u; num < 16; num++) { _alignPrices[num] = _posAlignEncoder.ReverseGetPrice(num); } _alignPriceCount = 0u; } private static int FindMatchFinder(string s) { for (int i = 0; i < kMatchFinderIDs.Length; i++) { if (s == kMatchFinderIDs[i]) { return i; } } return -1; } public void SetCoderProperties(CoderPropID[] propIDs, object[] properties) { for (uint num = 0u; num < properties.Length; num++) { object obj = properties[num]; switch (propIDs[num]) { case CoderPropID.NumFastBytes: if (!(obj is int num2)) { throw new InvalidParamException(); } if (num2 < 5 || (long)num2 > 273L) { throw new InvalidParamException(); } _numFastBytes = (uint)num2; break; case CoderPropID.MatchFinder: { if (!(obj is string)) { throw new InvalidParamException(); } EMatchFinderType matchFinderType = _matchFinderType; int num6 = FindMatchFinder(((string)obj).ToUpper()); if (num6 < 0) { throw new InvalidParamException(); } _matchFinderType = (EMatchFinderType)num6; if (_matchFinder != null && matchFinderType != _matchFinderType) { _dictionarySizePrev = uint.MaxValue; _matchFinder = null; } break; } case CoderPropID.DictionarySize: { if (!(obj is int num7)) { throw new InvalidParamException(); } if ((long)num7 < 1L || (long)num7 > 1073741824L) { throw new InvalidParamException(); } _dictionarySize = (uint)num7; int i; for (i = 0; (long)i < 30L && num7 > (uint)(1 << i); i++) { } _distTableSize = (uint)(i * 2); break; } case CoderPropID.PosStateBits: if (!(obj is int num3)) { throw new InvalidParamException(); } if (num3 < 0 || (long)num3 > 4L) { throw new InvalidParamException(); } _posStateBits = num3; _posStateMask = (uint)((1 << _posStateBits) - 1); break; case CoderPropID.LitPosBits: if (!(obj is int num5)) { throw new InvalidParamException(); } if (num5 < 0 || (long)num5 > 4L) { throw new InvalidParamException(); } _numLiteralPosStateBits = num5; break; case CoderPropID.LitContextBits: if (!(obj is int num4)) { throw new InvalidParamException(); } if (num4 < 0 || (long)num4 > 8L) { throw new InvalidParamException(); } _numLiteralContextBits = num4; break; case CoderPropID.EndMarker: if (!(obj is bool)) { throw new InvalidParamException(); } SetWriteEndMarkerMode((bool)obj); break; default: throw new InvalidParamException(); case CoderPropID.Algorithm: break; } } } public void SetTrainSize(uint trainSize) { _trainSize = trainSize; } } public static class SevenZipHelper { private static CoderPropID[] propIDs = new CoderPropID[8] { CoderPropID.DictionarySize, CoderPropID.PosStateBits, CoderPropID.LitContextBits, CoderPropID.LitPosBits, CoderPropID.Algorithm, CoderPropID.NumFastBytes, CoderPropID.MatchFinder, CoderPropID.EndMarker }; private static object[] properties = new object[8] { 2097152, 2, 3, 0, 2, 32, "bt4", false }; public static byte[] Compress(byte[] inputBytes, ICodeProgress progress = null) { MemoryStream inStream = new MemoryStream(inputBytes); MemoryStream memoryStream = new MemoryStream(); Compress(inStream, memoryStream, progress); return memoryStream.ToArray(); } public static void Compress(Stream inStream, Stream outStream, ICodeProgress progress = null) { Encoder encoder = new Encoder(); encoder.SetCoderProperties(propIDs, properties); encoder.WriteCoderProperties(outStream); encoder.Code(inStream, outStream, -1L, -1L, progress); } public static byte[] Decompress(byte[] inputBytes) { MemoryStream memoryStream = new MemoryStream(inputBytes); Decoder decoder = new Decoder(); memoryStream.Seek(0L, SeekOrigin.Begin); MemoryStream memoryStream2 = new MemoryStream(); byte[] array = new byte[5]; if (memoryStream.Read(array, 0, 5) != 5) { throw new Exception("input .lzma is too short"); } long num = 0L; for (int i = 0; i < 8; i++) { int num2 = memoryStream.ReadByte(); if (num2 < 0) { throw new Exception("Can't Read 1"); } num |= (long)((ulong)(byte)num2 << 8 * i); } decoder.SetDecoderProperties(array); long inSize = memoryStream.Length - memoryStream.Position; decoder.Code(memoryStream, memoryStream2, inSize, num, null); return memoryStream2.ToArray(); } public static MemoryStream StreamDecompress(MemoryStream newInStream) { Decoder decoder = new Decoder(); newInStream.Seek(0L, SeekOrigin.Begin); MemoryStream memoryStream = new MemoryStream(); byte[] array = new byte[5]; if (newInStream.Read(array, 0, 5) != 5) { throw new Exception("input .lzma is too short"); } long num = 0L; for (int i = 0; i < 8; i++) { int num2 = newInStream.ReadByte(); if (num2 < 0) { throw new Exception("Can't Read 1"); } num |= (long)((ulong)(byte)num2 << 8 * i); } decoder.SetDecoderProperties(array); long inSize = newInStream.Length - newInStream.Position; decoder.Code(newInStream, memoryStream, inSize, num, null); memoryStream.Position = 0L; return memoryStream; } public static MemoryStream StreamDecompress(MemoryStream newInStream, long outSize) { Decoder decoder = new Decoder(); newInStream.Seek(0L, SeekOrigin.Begin); MemoryStream memoryStream = new MemoryStream(); byte[] array = new byte[5]; if (newInStream.Read(array, 0, 5) != 5) { throw new Exception("input .lzma is too short"); } decoder.SetDecoderProperties(array); long inSize = newInStream.Length - newInStream.Position; decoder.Code(newInStream, memoryStream, inSize, outSize, null); memoryStream.Position = 0L; return memoryStream; } public static void StreamDecompress(Stream compressedStream, Stream decompressedStream, long compressedSize, long decompressedSize) { long position = compressedStream.Position; Decoder decoder = new Decoder(); byte[] array = new byte[5]; if (compressedStream.Read(array, 0, 5) != 5) { throw new Exception("input .lzma is too short"); } decoder.SetDecoderProperties(array); decoder.Code(compressedStream, decompressedStream, compressedSize - 5, decompressedSize, null); compressedStream.Position = position + compressedSize; } } } namespace SevenZip.Buffer { public class InBuffer { private byte[] m_Buffer; private uint m_Pos; private uint m_Limit; private uint m_BufferSize; private Stream m_Stream; private bool m_StreamWasExhausted; private ulong m_ProcessedSize; public InBuffer(uint bufferSize) { m_Buffer = new byte[bufferSize]; m_BufferSize = bufferSize; } public void Init(Stream stream) { m_Stream = stream; m_ProcessedSize = 0uL; m_Limit = 0u; m_Pos = 0u; m_StreamWasExhausted = false; } public bool ReadBlock() { if (m_StreamWasExhausted) { return false; } m_ProcessedSize += m_Pos; int num = m_Stream.Read(m_Buffer, 0, (int)m_BufferSize); m_Pos = 0u; m_Limit = (uint)num; m_StreamWasExhausted = num == 0; return !m_StreamWasExhausted; } public void ReleaseStream() { m_Stream = null; } public bool ReadByte(byte b) { if (m_Pos >= m_Limit && !ReadBlock()) { return false; } b = m_Buffer[m_Pos++]; return true; } public byte ReadByte() { if (m_Pos >= m_Limit && !ReadBlock()) { return byte.MaxValue; } return m_Buffer[m_Pos++]; } public ulong GetProcessedSize() { return m_ProcessedSize + m_Pos; } } public class OutBuffer { private byte[] m_Buffer; private uint m_Pos; private uint m_BufferSize; private Stream m_Stream; private ulong m_ProcessedSize; public OutBuffer(uint bufferSize) { m_Buffer = new byte[bufferSize]; m_BufferSize = bufferSize; } public void SetStream(Stream stream) { m_Stream = stream; } public void FlushStream() { m_Stream.Flush(); } public void CloseStream() { m_Stream.Close(); } public void ReleaseStream() { m_Stream = null; } public void Init() { m_ProcessedSize = 0uL; m_Pos = 0u; } public void WriteByte(byte b) { m_Buffer[m_Pos++] = b; if (m_Pos >= m_BufferSize) { FlushData(); } } public void FlushData() { if (m_Pos != 0) { m_Stream.Write(m_Buffer, 0, (int)m_Pos); m_Pos = 0u; } } public ulong GetProcessedSize() { return m_ProcessedSize + m_Pos; } } } namespace SevenZip.CommandLineParser { public enum SwitchType { Simple, PostMinus, LimitedPostString, UnLimitedPostString, PostChar } public class SwitchForm { public string IDString; public SwitchType Type; public bool Multi; public int MinLen; public int MaxLen; public string PostCharSet; public SwitchForm(string idString, SwitchType type, bool multi, int minLen, int maxLen, string postCharSet) { IDString = idString; Type = type; Multi = multi; MinLen = minLen; MaxLen = maxLen; PostCharSet = postCharSet; } public SwitchForm(string idString, SwitchType type, bool multi, int minLen) : this(idString, type, multi, minLen, 0, "") { } public SwitchForm(string idString, SwitchType type, bool multi) : this(idString, type, multi, 0) { } } public class SwitchResult { public bool ThereIs; public bool WithMinus; public ArrayList PostStrings = new ArrayList(); public int PostCharIndex; public SwitchResult() { ThereIs = false; } } public class Parser { public ArrayList NonSwitchStrings = new ArrayList(); private SwitchResult[] _switches; private const char kSwitchID1 = '-'; private const char kSwitchID2 = '/'; private const char kSwitchMinus = '-'; private const string kStopSwitchParsing = "--"; public SwitchResult this[int index] => _switches[index]; public Parser(int numSwitches) { _switches = new SwitchResult[numSwitches]; for (int i = 0; i < numSwitches; i++) { _switches[i] = new SwitchResult(); } } private bool ParseString(string srcString, SwitchForm[] switchForms) { int length = srcString.Length; if (length == 0) { return false; } int num = 0; if (!IsItSwitchChar(srcString[num])) { return false; } while (num < length) { if (IsItSwitchChar(srcString[num])) { num++; } int num2 = 0; int num3 = -1; for (int i = 0; i < _switches.Length; i++) { int length2 = switchForms[i].IDString.Length; if (length2 > num3 && num + length2 <= length && string.Compare(switchForms[i].IDString, 0, srcString, num, length2, ignoreCase: true) == 0) { num2 = i; num3 = length2; } } if (num3 == -1) { throw new Exception("maxLen == kNoLen"); } SwitchResult switchResult = _switches[num2]; SwitchForm switchForm = switchForms[num2]; if (!switchForm.Multi && switchResult.ThereIs) { throw new Exception("switch must be single"); } switchResult.ThereIs = true; num += num3; int num4 = length - num; SwitchType type = switchForm.Type; switch (type) { case SwitchType.PostMinus: if (num4 == 0) { switchResult.WithMinus = false; break; } switchResult.WithMinus = srcString[num] == '-'; if (switchResult.WithMinus) { num++; } break; case SwitchType.PostChar: { if (num4 < switchForm.MinLen) { throw new Exception("switch is not full"); } string postCharSet = switchForm.PostCharSet; if (num4 == 0) { switchResult.PostCharIndex = -1; break; } int num6 = postCharSet.IndexOf(srcString[num]); if (num6 < 0) { switchResult.PostCharIndex = -1; break; } switchResult.PostCharIndex = num6; num++; break; } case SwitchType.LimitedPostString: case SwitchType.UnLimitedPostString: { int minLen = switchForm.MinLen; if (num4 < minLen) { throw new Exception("switch is not full"); } if (type == SwitchType.UnLimitedPostString) { switchResult.PostStrings.Add(srcString.Substring(num)); return true; } string text = srcString.Substring(num, minLen); num += minLen; int num5 = minLen; while (num5 < switchForm.MaxLen && num < length) { char c = srcString[num]; if (IsItSwitchChar(c)) { break; } text += c; num5++; num++; } switchResult.PostStrings.Add(text); break; } } } return true; } public void ParseStrings(SwitchForm[] switchForms, string[] commandStrings) { int num = commandStrings.Length; bool flag = false; for (int i = 0; i < num; i++) { string text = commandStrings[i]; if (flag) { NonSwitchStrings.Add(text); } else if (text == "--") { flag = true; } else if (!ParseString(text, switchForms)) { NonSwitchStrings.Add(text); } } } public static int ParseCommand(CommandForm[] commandForms, string commandString, out string postString) { for (int i = 0; i < commandForms.Length; i++) { string iDString = commandForms[i].IDString; if (commandForms[i].PostStringMode) { if (commandString.IndexOf(iDString) == 0) { postString = commandString.Substring(iDString.Length); return i; } } else if (commandString == iDString) { postString = ""; return i; } } postString = ""; return -1; } private static bool ParseSubCharsCommand(int numForms, CommandSubCharsSet[] forms, string commandString, ArrayList indices) { indices.Clear(); int num = 0; for (int i = 0; i < numForms; i++) { CommandSubCharsSet commandSubCharsSet = forms[i]; int num2 = -1; int length = commandSubCharsSet.Chars.Length; for (int j = 0; j < length; j++) { char value = commandSubCharsSet.Chars[j]; int num3 = commandString.IndexOf(value); if (num3 >= 0) { if (num2 >= 0) { return false; } if (commandString.IndexOf(value, num3 + 1) >= 0) { return false; } num2 = j; num++; } } if (num2 == -1 && !commandSubCharsSet.EmptyAllowed) { return false; } indices.Add(num2); } return num == commandString.Length; } private static bool IsItSwitchChar(char c) { if (c != '-') { return c == '/'; } return true; } } public class CommandForm { public string IDString = ""; public bool PostStringMode; public CommandForm(string idString, bool postStringMode) { IDString = idString; PostStringMode = postStringMode; } } internal class CommandSubCharsSet { public string Chars = ""; public bool EmptyAllowed; } } namespace LZ4ps { public static class LZ4Codec { private class LZ4HC_Data_Structure { public byte[] src; public int src_base; public int src_end; public int src_LASTLITERALS; public byte[] dst; public int dst_base; public int dst_len; public int dst_end; public int[] hashTable; public ushort[] chainTable; public int nextToUpdate; } private const int MEMORY_USAGE = 14; private const int NOTCOMPRESSIBLE_DETECTIONLEVEL = 6; private const int BLOCK_COPY_LIMIT = 16; private const int MINMATCH = 4; private const int SKIPSTRENGTH = 6; private const int COPYLENGTH = 8; private const int LASTLITERALS = 5; private const int MFLIMIT = 12; private const int MINLENGTH = 13; private const int MAXD_LOG = 16; private const int MAXD = 65536; private const int MAXD_MASK = 65535; private const int MAX_DISTANCE = 65535; private const int ML_BITS = 4; private const int ML_MASK = 15; private const int RUN_BITS = 4; private const int RUN_MASK = 15; private const int STEPSIZE_64 = 8; private const int STEPSIZE_32 = 4; private const int LZ4_64KLIMIT = 65547; private const int HASH_LOG = 12; private const int HASH_TABLESIZE = 4096; private const int HASH_ADJUST = 20; private const int HASH64K_LOG = 13; private const int HASH64K_TABLESIZE = 8192; private const int HASH64K_ADJUST = 19; private const int HASHHC_LOG = 15; private const int HASHHC_TABLESIZE = 32768; private const int HASHHC_ADJUST = 17; private static readonly int[] DECODER_TABLE_32 = new int[8] { 0, 3, 2, 3, 0, 0, 0, 0 }; private static readonly int[] DECODER_TABLE_64 = new int[8] { 0, 0, 0, -1, 0, 1, 2, 3 }; private static readonly int[] DEBRUIJN_TABLE_32 = new int[32] { 0, 0, 3, 0, 3, 1, 3, 0, 3, 2, 2, 1, 3, 2, 0, 1, 3, 3, 1, 2, 2, 2, 2, 0, 3, 1, 2, 0, 1, 0, 1, 1 }; private static readonly int[] DEBRUIJN_TABLE_64 = new int[64] { 0, 0, 0, 0, 0, 1, 1, 2, 0, 3, 1, 3, 1, 4, 2, 7, 0, 2, 3, 6, 1, 5, 3, 5, 1, 3, 4, 4, 2, 5, 6, 7, 7, 0, 1, 2, 3, 3, 4, 6, 2, 6, 5, 5, 3, 4, 5, 6, 7, 1, 2, 4, 6, 4, 4, 5, 7, 2, 6, 5, 7, 6, 7, 7 }; private const int MAX_NB_ATTEMPTS = 256; private const int OPTIMAL_ML = 18; public static int MaximumOutputLength(int inputLength) { return inputLength + inputLength / 255 + 16; } internal static void CheckArguments(byte[] input, int inputOffset, ref int inputLength, byte[] output, int outputOffset, ref int outputLength) { if (inputLength < 0) { inputLength = input.Length - inputOffset; } if (inputLength == 0) { outputLength = 0; return; } if (input == null) { throw new ArgumentNullException("input"); } if (inputOffset < 0 || inputOffset + inputLength > input.Length) { throw new ArgumentException("inputOffset and inputLength are invalid for given input"); } if (outputLength < 0) { outputLength = output.Length - outputOffset; } if (output == null) { throw new ArgumentNullException("output"); } if (outputOffset >= 0 && outputOffset + outputLength <= output.Length) { return; } throw new ArgumentException("outputOffset and outputLength are invalid for given output"); } [Conditional("DEBUG")] private static void Assert(bool condition, string errorMessage) { if (!condition) { throw new ArgumentException(errorMessage); } } internal static void Poke2(byte[] buffer, int offset, ushort value) { buffer[offset] = (byte)value; buffer[offset + 1] = (byte)(value >> 8); } internal static ushort Peek2(byte[] buffer, int offset) { return (ushort)(buffer[offset] | (buffer[offset + 1] << 8)); } internal static uint Peek4(byte[] buffer, int offset) { return (uint)(buffer[offset] | (buffer[offset + 1] << 8) | (buffer[offset + 2] << 16) | (buffer[offset + 3] << 24)); } private static uint Xor4(byte[] buffer, int offset1, int offset2) { int num = buffer[offset1] | (buffer[offset1 + 1] << 8) | (buffer[offset1 + 2] << 16) | (buffer[offset1 + 3] << 24); uint num2 = (uint)(buffer[offset2] | (buffer[offset2 + 1] << 8) | (buffer[offset2 + 2] << 16) | (buffer[offset2 + 3] << 24)); return (uint)num ^ num2; } private static ulong Xor8(byte[] buffer, int offset1, int offset2) { ulong num = buffer[offset1] | ((ulong)buffer[offset1 + 1] << 8) | ((ulong)buffer[offset1 + 2] << 16) | ((ulong)buffer[offset1 + 3] << 24) | ((ulong)buffer[offset1 + 4] << 32) | ((ulong)buffer[offset1 + 5] << 40) | ((ulong)buffer[offset1 + 6] << 48) | ((ulong)buffer[offset1 + 7] << 56); ulong num2 = buffer[offset2] | ((ulong)buffer[offset2 + 1] << 8) | ((ulong)buffer[offset2 + 2] << 16) | ((ulong)buffer[offset2 + 3] << 24) | ((ulong)buffer[offset2 + 4] << 32) | ((ulong)buffer[offset2 + 5] << 40) | ((ulong)buffer[offset2 + 6] << 48) | ((ulong)buffer[offset2 + 7] << 56); return num ^ num2; } private static bool Equal2(byte[] buffer, int offset1, int offset2) { if (buffer[offset1] != buffer[offset2]) { return false; } return buffer[offset1 + 1] == buffer[offset2 + 1]; } private static bool Equal4(byte[] buffer, int offset1, int offset2) { if (buffer[offset1] != buffer[offset2]) { return false; } if (buffer[offset1 + 1] != buffer[offset2 + 1]) { return false; } if (buffer[offset1 + 2] != buffer[offset2 + 2]) { return false; } return buffer[offset1 + 3] == buffer[offset2 + 3]; } private static void Copy4(byte[] buf, int src, int dst) { buf[dst + 3] = buf[src + 3]; buf[dst + 2] = buf[src + 2]; buf[dst + 1] = buf[src + 1]; buf[dst] = buf[src]; } private static void Copy8(byte[] buf, int src, int dst) { buf[dst + 7] = buf[src + 7]; buf[dst + 6] = buf[src + 6]; buf[dst + 5] = buf[src + 5]; buf[dst + 4] = buf[src + 4]; buf[dst + 3] = buf[src + 3]; buf[dst + 2] = buf[src + 2]; buf[dst + 1] = buf[src + 1]; buf[dst] = buf[src]; } private static void BlockCopy(byte[] src, int src_0, byte[] dst, int dst_0, int len) { if (len >= 16) { Buffer.BlockCopy(src, src_0, dst, dst_0, len); return; } while (len >= 8) { dst[dst_0] = src[src_0]; dst[dst_0 + 1] = src[src_0 + 1]; dst[dst_0 + 2] = src[src_0 + 2]; dst[dst_0 + 3] = src[src_0 + 3]; dst[dst_0 + 4] = src[src_0 + 4]; dst[dst_0 + 5] = src[src_0 + 5]; dst[dst_0 + 6] = src[src_0 + 6]; dst[dst_0 + 7] = src[src_0 + 7]; len -= 8; src_0 += 8; dst_0 += 8; } while (len >= 4) { dst[dst_0] = src[src_0]; dst[dst_0 + 1] = src[src_0 + 1]; dst[dst_0 + 2] = src[src_0 + 2]; dst[dst_0 + 3] = src[src_0 + 3]; len -= 4; src_0 += 4; dst_0 += 4; } while (len-- > 0) { dst[dst_0++] = src[src_0++]; } } private static int WildCopy(byte[] src, int src_0, byte[] dst, int dst_0, int dst_end) { int num = dst_end - dst_0; if (num >= 16) { Buffer.BlockCopy(src, src_0, dst, dst_0, num); } else { while (num >= 4) { dst[dst_0] = src[src_0]; dst[dst_0 + 1] = src[src_0 + 1]; dst[dst_0 + 2] = src[src_0 + 2]; dst[dst_0 + 3] = src[src_0 + 3]; num -= 4; src_0 += 4; dst_0 += 4; } while (num-- > 0) { dst[dst_0++] = src[src_0++]; } } return num; } private static int SecureCopy(byte[] buffer, int src, int dst, int dst_end) { int num = dst - src; int num2 = dst_end - dst; int num3 = num2; if (num >= 16) { if (num >= num2) { Buffer.BlockCopy(buffer, src, buffer, dst, num2); return num2; } do { Buffer.BlockCopy(buffer, src, buffer, dst, num); src += num; dst += num; num3 -= num; } while (num3 >= num); } while (num3 >= 4) { buffer[dst] = buffer[src]; buffer[dst + 1] = buffer[src + 1]; buffer[dst + 2] = buffer[src + 2]; buffer[dst + 3] = buffer[src + 3]; dst += 4; src += 4; num3 -= 4; } while (num3-- > 0) { buffer[dst++] = buffer[src++]; } return num2; } public static int Encode32(byte[] input, int inputOffset, int inputLength, byte[] output, int outputOffset, int outputLength) { CheckArguments(input, inputOffset, ref inputLength, output, outputOffset, ref outputLength); if (outputLength == 0) { return 0; } if (inputLength < 65547) { return LZ4_compress64kCtx_safe32(new ushort[8192], input, output, inputOffset, outputOffset, inputLength, outputLength); } return LZ4_compressCtx_safe32(new int[4096], input, output, inputOffset, outputOffset, inputLength, outputLength); } public static byte[] Encode32(byte[] input, int inputOffset, int inputLength) { if (inputLength < 0) { inputLength = input.Length - inputOffset; } if (input == null) { throw new ArgumentNullException("input"); } if (inputOffset < 0 || inputOffset + inputLength > input.Length) { throw new ArgumentException("inputOffset and inputLength are invalid for given input"); } byte[] array = new byte[MaximumOutputLength(inputLength)]; int num = Encode32(input, inputOffset, inputLength, array, 0, array.Length); if (num != array.Length) { if (num < 0) { throw new InvalidOperationException("Compression has been corrupted"); } byte[] array2 = new byte[num]; Buffer.BlockCopy(array, 0, array2, 0, num); return array2; } return array; } public static int Encode64(byte[] input, int inputOffset, int inputLength, byte[] output, int outputOffset, int outputLength) { CheckArguments(input, inputOffset, ref inputLength, output, outputOffset, ref outputLength); if (outputLength == 0) { return 0; } if (inputLength < 65547) { return LZ4_compress64kCtx_safe64(new ushort[8192], input, output, inputOffset, outputOffset, inputLength, outputLength); } return LZ4_compressCtx_safe64(new int[4096], input, output, inputOffset, outputOffset, inputLength, outputLength); } public static byte[] Encode64(byte[] input, int inputOffset, int inputLength) { if (inputLength < 0) { inputLength = input.Length - inputOffset; } if (input == null) { throw new ArgumentNullException("input"); } if (inputOffset < 0 || inputOffset + inputLength > input.Length) { throw new ArgumentException("inputOffset and inputLength are invalid for given input"); } byte[] array = new byte[MaximumOutputLength(inputLength)]; int num = Encode64(input, inputOffset, inputLength, array, 0, array.Length); if (num != array.Length) { if (num < 0) { throw new InvalidOperationException("Compression has been corrupted"); } byte[] array2 = new byte[num]; Buffer.BlockCopy(array, 0, array2, 0, num); return array2; } return array; } public static int Decode32(byte[] input, int inputOffset, int inputLength, byte[] output, int outputOffset, int outputLength, bool knownOutputLength) { CheckArguments(input, inputOffset, ref inputLength, output, outputOffset, ref outputLength); if (outputLength == 0) { return 0;